diff --git a/CREDITS b/CREDITS
index e371c5504a50..cef042453fa4 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1229,7 +1229,7 @@ E: philip@gladstonefamily.net
 D: Kernel / timekeeping stuff
 S: Carlisle, MA 01741
 S: USA
-  
+
 N: Jan-Benedict Glaw
 E: jbglaw@lug-owl.de
 D: SRM environment driver (for Alpha systems)
@@ -2560,10 +2560,14 @@ S: 22 Seaview St
 S: Fullarton 5063
 S: South Australia
 
-N. Wolfgang Muees
+N: Wolfgang Muees
 E: wolfgang@iksw-muees.de
 D: Auerswald USB driver
 
+N: Paul Mundt
+E: paul.mundt@gmail.com
+D: SuperH maintainer
+
 N: Ian A. Murdock
 E: imurdock@gnu.ai.mit.edu
 D: Creator of Debian distribution
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 07de7e19b4ce..27e67a98b7be 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -413,8 +413,6 @@ serial-console.txt
 	- how to set up Linux with a serial line console as the default.
 sgi-ioc4.txt
 	- description of the SGI IOC4 PCI (multi function) device.
-sgi-visws.txt
-	- short blurb on the SGI Visual Workstations.
 sh/
 	- directory with info on porting Linux to a new architecture.
 smsc_ece1099.txt
diff --git a/Documentation/ABI/testing/sysfs-block-zram b/Documentation/ABI/testing/sysfs-block-zram
index 3f0b9ae61d8c..70ec992514d0 100644
--- a/Documentation/ABI/testing/sysfs-block-zram
+++ b/Documentation/ABI/testing/sysfs-block-zram
@@ -43,6 +43,36 @@ Description:
 		The invalid_io file is read-only and specifies the number of
 		non-page-size-aligned I/O requests issued to this device.
 
+What:		/sys/block/zram<id>/failed_reads
+Date:		February 2014
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The failed_reads file is read-only and specifies the number of
+		failed reads happened on this device.
+
+What:		/sys/block/zram<id>/failed_writes
+Date:		February 2014
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The failed_writes file is read-only and specifies the number of
+		failed writes happened on this device.
+
+What:		/sys/block/zram<id>/max_comp_streams
+Date:		February 2014
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The max_comp_streams file is read-write and specifies the
+		number of backend's zcomp_strm compression streams (number of
+		concurrent compress operations).
+
+What:		/sys/block/zram<id>/comp_algorithm
+Date:		February 2014
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The comp_algorithm file is read-write and lets to show
+		available and selected compression algorithms, change
+		compression algorithm selection.
+
 What:		/sys/block/zram<id>/notify_free
 Date:		August 2010
 Contact:	Nitin Gupta <ngupta@vflare.org>
@@ -53,15 +83,6 @@ Description:
 		is freed. This statistic is applicable only when this disk is
 		being used as a swap disk.
 
-What:		/sys/block/zram<id>/discard
-Date:		August 2010
-Contact:	Nitin Gupta <ngupta@vflare.org>
-Description:
-		The discard file is read-only and specifies the number of
-		discard requests received by this device. These requests
-		provide information to block device regarding blocks which are
-		no longer used by filesystem.
-
 What:		/sys/block/zram<id>/zero_pages
 Date:		August 2010
 Contact:	Nitin Gupta <ngupta@vflare.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-mdio b/Documentation/ABI/testing/sysfs-bus-mdio
index 6349749ebc29..491baaf4285f 100644
--- a/Documentation/ABI/testing/sysfs-bus-mdio
+++ b/Documentation/ABI/testing/sysfs-bus-mdio
@@ -7,3 +7,23 @@ Description:
 		by the device during bus enumeration, encoded in hexadecimal.
 		This ID is used to match the device with the appropriate
 		driver.
+
+What:		/sys/bus/mdio_bus/devices/.../phy_interface
+Date:		February 2014
+KernelVersion:	3.15
+Contact:	netdev@vger.kernel.org
+Description:
+		This attribute contains the PHY interface as configured by the
+		Ethernet driver during bus enumeration, encoded in string.
+		This interface mode is used to configure the Ethernet MAC with the
+		appropriate mode for its data lines to the PHY hardware.
+
+What:		/sys/bus/mdio_bus/devices/.../phy_has_fixups
+Date:		February 2014
+KernelVersion:	3.15
+Contact:	netdev@vger.kernel.org
+Description:
+		This attribute contains the boolean value whether a given PHY
+		device has had any "fixup" workaround running on it, encoded as
+		a boolean. This information is provided to help troubleshooting
+		PHY configurations.
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-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index efe449bdf811..7dbf96b724ed 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -187,7 +187,7 @@ Description:
 		Not all drivers support this attribute.  If it isn't supported,
 		attempts to read or write it will yield I/O errors.
 
-What:		/sys/devices/.../power/pm_qos_latency_us
+What:		/sys/devices/.../power/pm_qos_resume_latency_us
 Date:		March 2012
 Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
@@ -205,6 +205,31 @@ Description:
 		This attribute has no effect on system-wide suspend/resume and
 		hibernation.
 
+What:		/sys/devices/.../power/pm_qos_latency_tolerance_us
+Date:		January 2014
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
+Description:
+		The /sys/devices/.../power/pm_qos_latency_tolerance_us attribute
+		contains the PM QoS active state latency tolerance limit for the
+		given device in microseconds.  That is the maximum memory access
+		latency the device can suffer without any visible adverse
+		effects on user space functionality.  If that value is the
+		string "any", the latency does not matter to user space at all,
+		but hardware should not be allowed to set the latency tolerance
+		for the device automatically.
+
+		Reading "auto" from this file means that the maximum memory
+		access latency for the device may be determined automatically
+		by the hardware as needed.  Writing "auto" to it allows the
+		hardware to be switched to this mode if there are no other
+		latency tolerance requirements from the kernel side.
+
+		This attribute is only present if the feature controlled by it
+		is supported by the hardware.
+
+		This attribute has no effect on runtime suspend and resume of
+		devices and on system-wide suspend/resume and hibernation.
+
 What:		/sys/devices/.../power/pm_qos_no_power_off
 Date:		September 2012
 Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 0f9c6ff41aac..8d96ebf524e9 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
 	    80211.xml debugobjects.xml sh.xml regulator.xml \
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
-	    tracepoint.xml drm.xml media_api.xml
+	    tracepoint.xml drm.xml media_api.xml w1.xml
 
 include $(srctree)/Documentation/DocBook/media/Makefile
 
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index d0758b241b23..b90959ba37e4 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -671,7 +671,7 @@ printk(KERN_INFO "my ip: %pI4\n", &amp;ipaddress);
 
   <sect1 id="routines-local-irqs">
    <title><function>local_irq_save()</function>/<function>local_irq_restore()</function>
-    <filename class="headerfile">include/asm/system.h</filename>
+    <filename class="headerfile">include/linux/irqflags.h</filename>
    </title>
 
    <para>
diff --git a/Documentation/DocBook/w1.tmpl b/Documentation/DocBook/w1.tmpl
new file mode 100644
index 000000000000..b0228d4c81bb
--- /dev/null
+++ b/Documentation/DocBook/w1.tmpl
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="w1id">
+  <bookinfo>
+    <title>W1: Dallas' 1-wire bus</title>
+
+    <authorgroup>
+      <author>
+        <firstname>David</firstname>
+        <surname>Fries</surname>
+        <affiliation>
+          <address>
+            <email>David@Fries.net</email>
+          </address>
+        </affiliation>
+      </author>
+
+    </authorgroup>
+
+    <copyright>
+      <year>2013</year>
+      <!--
+      <holder></holder>
+      -->
+    </copyright>
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute
+        it and/or modify it under the terms of the GNU General Public
+        License version 2.
+      </para>
+
+      <para>
+        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.
+        For more details see the file COPYING in the source
+        distribution of Linux.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+  <toc></toc>
+
+  <chapter id="w1_internal">
+    <title>W1 API internal to the kernel</title>
+
+    <sect1 id="w1_internal_api">
+      <title>W1 API internal to the kernel</title>
+      <sect2 id="w1.h">
+        <title>drivers/w1/w1.h</title>
+        <para>W1 core functions.</para>
+!Idrivers/w1/w1.h
+      </sect2>
+
+      <sect2 id="w1.c">
+        <title>drivers/w1/w1.c</title>
+        <para>W1 core functions.</para>
+!Idrivers/w1/w1.c
+      </sect2>
+
+      <sect2 id="w1_family.h">
+        <title>drivers/w1/w1_family.h</title>
+        <para>Allows registering device family operations.</para>
+!Idrivers/w1/w1_family.h
+      </sect2>
+
+      <sect2 id="w1_family.c">
+        <title>drivers/w1/w1_family.c</title>
+        <para>Allows registering device family operations.</para>
+!Edrivers/w1/w1_family.c
+      </sect2>
+
+      <sect2 id="w1_int.c">
+        <title>drivers/w1/w1_int.c</title>
+        <para>W1 internal initialization for master devices.</para>
+!Edrivers/w1/w1_int.c
+      </sect2>
+
+      <sect2 id="w1_netlink.h">
+        <title>drivers/w1/w1_netlink.h</title>
+        <para>W1 external netlink API structures and commands.</para>
+!Idrivers/w1/w1_netlink.h
+      </sect2>
+
+      <sect2 id="w1_io.c">
+        <title>drivers/w1/w1_io.c</title>
+        <para>W1 input/output.</para>
+!Edrivers/w1/w1_io.c
+!Idrivers/w1/w1_io.c
+      </sect2>
+
+    </sect1>
+
+
+  </chapter>
+
+</book>
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index 06741e925985..d0056a4e9c53 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -468,8 +468,6 @@
                   return err;
           }
 
-          snd_card_set_dev(card, &pci->dev);
-
           *rchip = chip;
           return 0;
   }
@@ -492,7 +490,8 @@
           }
 
           /* (2) */
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                             0, &card);
           if (err < 0)
                   return err;
 
@@ -591,7 +590,8 @@
   struct snd_card *card;
   int err;
   ....
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     0, &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -809,28 +809,34 @@
 
       <para>
         As mentioned above, to create a card instance, call
-      <function>snd_card_create()</function>.
+      <function>snd_card_new()</function>.
 
         <informalexample>
           <programlisting>
 <![CDATA[
   struct snd_card *card;
   int err;
-  err = snd_card_create(index, id, module, extra_size, &card);
+  err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
 ]]>
           </programlisting>
         </informalexample>
       </para>
 
       <para>
-        The function takes five arguments, the card-index number, the
-        id string, the module pointer (usually
+        The function takes six arguments: the parent device pointer,
+        the card-index number, the id string, the module pointer (usually
         <constant>THIS_MODULE</constant>),
         the size of extra-data space, and the pointer to return the
         card instance.  The extra_size argument is used to
         allocate card-&gt;private_data for the
         chip-specific data.  Note that these data
-        are allocated by <function>snd_card_create()</function>.
+        are allocated by <function>snd_card_new()</function>.
+      </para>
+
+      <para>
+	The first argument, the pointer of struct
+	<structname>device</structname>, specifies the parent device.
+	For PCI devices, typically &amp;pci-&gt; is passed there.
       </para>
     </section>
 
@@ -916,16 +922,16 @@
       </para>
 
       <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_create()</function>.</title>
+        <title>1. Allocating via <function>snd_card_new()</function>.</title>
         <para>
           As mentioned above, you can pass the extra-data-length
-	  to the 4th argument of <function>snd_card_create()</function>, i.e.
+	  to the 5th argument of <function>snd_card_new()</function>, i.e.
 
           <informalexample>
             <programlisting>
 <![CDATA[
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
-                        sizeof(struct mychip), &card);
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     sizeof(struct mychip), &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -954,7 +960,7 @@
 
         <para>
           After allocating a card instance via
-          <function>snd_card_create()</function> (with
+          <function>snd_card_new()</function> (with
           <constant>0</constant> on the 4th arg), call
           <function>kzalloc()</function>. 
 
@@ -963,7 +969,8 @@
 <![CDATA[
   struct snd_card *card;
   struct mychip *chip;
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     0, &card);
   .....
   chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 ]]>
@@ -1170,8 +1177,6 @@
                   return err;
           }
 
-          snd_card_set_dev(card, &pci->dev);
-
           *rchip = chip;
           return 0;
   }        
@@ -1526,30 +1531,6 @@
 
     </section>
 
-    <section id="pci-resource-device-struct">
-      <title>Registration of Device Struct</title>
-      <para>
-	At some point, typically after calling <function>snd_device_new()</function>,
-	you need to register the struct <structname>device</structname> of the chip
-	you're handling for udev and co.  ALSA provides a macro for compatibility with
-	older kernels.  Simply call like the following:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_card_set_dev(card, &pci->dev);
-]]>
-          </programlisting>
-        </informalexample>
-	so that it stores the PCI's device pointer to the card.  This will be
-	referred by ALSA core functions later when the devices are registered.
-      </para>
-      <para>
-	In the case of non-PCI, pass the proper device struct pointer of the BUS
-	instead.  (In the case of legacy ISA without PnP, you don't have to do
-	anything.)
-      </para>
-    </section>
-
     <section id="pci-resource-entries">
       <title>PCI Entries</title>
       <para>
@@ -5740,7 +5721,8 @@ struct _snd_pcm_runtime {
           struct mychip *chip;
           int err;
           ....
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                             0, &card);
           ....
           chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           ....
@@ -5752,7 +5734,7 @@ struct _snd_pcm_runtime {
       </informalexample>
 
 	When you created the chip data with
-	<function>snd_card_create()</function>, it's anyway accessible
+	<function>snd_card_new()</function>, it's anyway accessible
 	via <structfield>private_data</structfield> field.
 
       <informalexample>
@@ -5766,8 +5748,8 @@ struct _snd_pcm_runtime {
           struct mychip *chip;
           int err;
           ....
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
-                                sizeof(struct mychip), &card);
+          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                             sizeof(struct mychip), &card);
           ....
           chip = card->private_data;
           ....
diff --git a/Documentation/PCI/pci-iov-howto.txt b/Documentation/PCI/pci-iov-howto.txt
index 86551cc72e03..2d91ae251982 100644
--- a/Documentation/PCI/pci-iov-howto.txt
+++ b/Documentation/PCI/pci-iov-howto.txt
@@ -68,10 +68,6 @@ To disable SR-IOV capability:
 	echo  0 > \
         /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
-To notify SR-IOV core of Virtual Function Migration:
-(a) In the driver:
-	irqreturn_t pci_sriov_migration(struct pci_dev *dev);
-
 3.2 Usage example
 
 Following piece of code illustrates the usage of the SR-IOV API.
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 273e654d7d08..2f0fcb2112d2 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -31,6 +31,14 @@ has lapsed, so this approach may be used in non-GPL software, if desired.
 (In contrast, implementation of RCU is permitted only in software licensed
 under either GPL or LGPL.  Sorry!!!)
 
+In 1987, Rashid et al. described lazy TLB-flush [RichardRashid87a].
+At first glance, this has nothing to do with RCU, but nevertheless
+this paper helped inspire the update-side batching used in the later
+RCU implementation in DYNIX/ptx.  In 1988, Barbara Liskov published
+a description of Argus that noted that use of out-of-date values can
+be tolerated in some situations.  Thus, this paper provides some early
+theoretical justification for use of stale data.
+
 In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
 were reading a given data structure permitted deferred free to operate
 in the presence of non-terminating threads.  However, this explicit
@@ -41,11 +49,11 @@ providing a fine-grained locking design, however, it would be interesting
 to see how much of the performance advantage reported in 1990 remains
 today.
 
-At about this same time, Adams [Adams91] described ``chaotic relaxation'',
-where the normal barriers between successive iterations of convergent
-numerical algorithms are relaxed, so that iteration $n$ might use
-data from iteration $n-1$ or even $n-2$.  This introduces error,
-which typically slows convergence and thus increases the number of
+At about this same time, Andrews [Andrews91textbook] described ``chaotic
+relaxation'', where the normal barriers between successive iterations
+of convergent numerical algorithms are relaxed, so that iteration $n$
+might use data from iteration $n-1$ or even $n-2$.  This introduces
+error, which typically slows convergence and thus increases the number of
 iterations required.  However, this increase is sometimes more than made
 up for by a reduction in the number of expensive barrier operations,
 which are otherwise required to synchronize the threads at the end
@@ -55,7 +63,8 @@ is thus inapplicable to most data structures in operating-system kernels.
 
 In 1992, Henry (now Alexia) Massalin completed a dissertation advising
 parallel programmers to defer processing when feasible to simplify
-synchronization.  RCU makes extremely heavy use of this advice.
+synchronization [HMassalinPhD].  RCU makes extremely heavy use of
+this advice.
 
 In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
 simplest deferred-free technique: simply waiting a fixed amount of time
@@ -90,27 +99,29 @@ mechanism, which is quite similar to RCU [Gamsa99].  These operating
 systems made pervasive use of RCU in place of "existence locks", which
 greatly simplifies locking hierarchies and helps avoid deadlocks.
 
-2001 saw the first RCU presentation involving Linux [McKenney01a]
-at OLS.  The resulting abundance of RCU patches was presented the
-following year [McKenney02a], and use of RCU in dcache was first
-described that same year [Linder02a].
+The year 2000 saw an email exchange that would likely have
+led to yet another independent invention of something like RCU
+[RustyRussell2000a,RustyRussell2000b].  Instead, 2001 saw the first
+RCU presentation involving Linux [McKenney01a] at OLS.  The resulting
+abundance of RCU patches was presented the following year [McKenney02a],
+and use of RCU in dcache was first described that same year [Linder02a].
 
 Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
 techniques that defer the destruction of data structures to simplify
 non-blocking synchronization (wait-free synchronization, lock-free
 synchronization, and obstruction-free synchronization are all examples of
-non-blocking synchronization).  In particular, this technique eliminates
-locking, reduces contention, reduces memory latency for readers, and
-parallelizes pipeline stalls and memory latency for writers.  However,
-these techniques still impose significant read-side overhead in the
-form of memory barriers.  Researchers at Sun worked along similar lines
-in the same timeframe [HerlihyLM02].  These techniques can be thought
-of as inside-out reference counts, where the count is represented by the
-number of hazard pointers referencing a given data structure rather than
-the more conventional counter field within the data structure itself.
-The key advantage of inside-out reference counts is that they can be
-stored in immortal variables, thus allowing races between access and
-deletion to be avoided.
+non-blocking synchronization).  The corresponding journal article appeared
+in 2004 [MagedMichael04a].  This technique eliminates locking, reduces
+contention, reduces memory latency for readers, and parallelizes pipeline
+stalls and memory latency for writers.  However, these techniques still
+impose significant read-side overhead in the form of memory barriers.
+Researchers at Sun worked along similar lines in the same timeframe
+[HerlihyLM02].  These techniques can be thought of as inside-out reference
+counts, where the count is represented by the number of hazard pointers
+referencing a given data structure rather than the more conventional
+counter field within the data structure itself.  The key advantage
+of inside-out reference counts is that they can be stored in immortal
+variables, thus allowing races between access and deletion to be avoided.
 
 By the same token, RCU can be thought of as a "bulk reference count",
 where some form of reference counter covers all reference by a given CPU
@@ -123,8 +134,10 @@ can be thought of in other terms as well.
 
 In 2003, the K42 group described how RCU could be used to create
 hot-pluggable implementations of operating-system functions [Appavoo03a].
-Later that year saw a paper describing an RCU implementation of System
-V IPC [Arcangeli03], and an introduction to RCU in Linux Journal
+Later that year saw a paper describing an RCU implementation
+of System V IPC [Arcangeli03] (following up on a suggestion by
+Hugh Dickins [Dickins02a] and an implementation by Mingming Cao
+[MingmingCao2002IPCRCU]), and an introduction to RCU in Linux Journal
 [McKenney03a].
 
 2004 has seen a Linux-Journal article on use of RCU in dcache
@@ -383,6 +396,21 @@ for Programming Languages and Operating Systems}"
 }
 }
 
+@phdthesis{HMassalinPhD
+,author="H. Massalin"
+,title="Synthesis: An Efficient Implementation of Fundamental Operating
+System Services"
+,school="Columbia University"
+,address="New York, NY"
+,year="1992"
+,annotation={
+	Mondo optimizing compiler.
+	Wait-free stuff.
+	Good advice: defer work to avoid synchronization.  See page 90
+		(PDF page 106), Section 5.4, fourth bullet point.
+}
+}
+
 @unpublished{Jacobson93
 ,author="Van Jacobson"
 ,title="Avoid Read-Side Locking Via Delayed Free"
@@ -671,6 +699,20 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 [Viewed October 18, 2004]"
 }
 
+@conference{Michael02b
+,author="Maged M. Michael"
+,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
+,Year="2002"
+,Month="August"
+,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
+Symposium on Parallel
+Algorithms and Architecture}"
+,pages="73-82"
+,annotation={
+Like the title says...
+}
+}
+
 @Conference{Linder02a
 ,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
 ,Title="Scalability of the Directory Entry Cache"
@@ -727,6 +769,24 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 }
 }
 
+@conference{Michael02a
+,author="Maged M. Michael"
+,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
+Reads and Writes"
+,Year="2002"
+,Month="August"
+,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
+Symposium on Principles of Distributed Computing}"
+,pages="21-30"
+,annotation={
+	Each thread keeps an array of pointers to items that it is
+	currently referencing.	Sort of an inside-out garbage collection
+	mechanism, but one that requires the accessing code to explicitly
+	state its needs.  Also requires read-side memory barriers on
+	most architectures.
+}
+}
+
 @unpublished{Dickins02a
 ,author="Hugh Dickins"
 ,title="Use RCU for System-V IPC"
@@ -735,6 +795,17 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="private communication"
 }
 
+@InProceedings{HerlihyLM02
+,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
+,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
+Lock-Free Data Structures"
+,booktitle={Proceedings of 16\textsuperscript{th} International
+Symposium on Distributed Computing}
+,year=2002
+,month="October"
+,pages="339-353"
+}
+
 @unpublished{Sarma02b
 ,Author="Dipankar Sarma"
 ,Title="Some dcache\_rcu benchmark numbers"
@@ -749,6 +820,19 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 }
 }
 
+@unpublished{MingmingCao2002IPCRCU
+,Author="Mingming Cao"
+,Title="[PATCH]updated ipc lock patch"
+,month="October"
+,year="2002"
+,note="Available:
+\url{https://lkml.org/lkml/2002/10/24/262}
+[Viewed February 15, 2014]"
+,annotation={
+	Mingming Cao's patch to introduce RCU to SysV IPC.
+}
+}
+
 @unpublished{LinusTorvalds2003a
 ,Author="Linus Torvalds"
 ,Title="Re: {[PATCH]} small fixes in brlock.h"
@@ -982,6 +1066,23 @@ Realtime Applications"
 }
 }
 
+@article{MagedMichael04a
+,author="Maged M. Michael"
+,title="Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects"
+,Year="2004"
+,Month="June"
+,journal="IEEE Transactions on Parallel and Distributed Systems"
+,volume="15"
+,number="6"
+,pages="491-504"
+,url="Available:
+\url{http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf}
+[Viewed March 1, 2005]"
+,annotation={
+	New canonical hazard-pointer citation.
+}
+}
+
 @phdthesis{PaulEdwardMcKenneyPhD
 ,author="Paul E. McKenney"
 ,title="Exploiting Deferred Destruction:
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 91266193b8f4..9d10d1db16a5 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -256,10 +256,10 @@ over a rather long period of time, but improvements are always welcome!
 		variations on this theme.
 
 	b.	Limiting update rate.  For example, if updates occur only
-		once per hour, then no explicit rate limiting is required,
-		unless your system is already badly broken.  The dcache
-		subsystem takes this approach -- updates are guarded
-		by a global lock, limiting their rate.
+		once per hour, then no explicit rate limiting is
+		required, unless your system is already badly broken.
+		Older versions of the dcache subsystem take this approach,
+		guarding updates with a global lock, limiting their rate.
 
 	c.	Trusted update -- if updates can only be done manually by
 		superuser or some other trusted user, then it might not
@@ -268,7 +268,8 @@ over a rather long period of time, but improvements are always welcome!
 		the machine.
 
 	d.	Use call_rcu_bh() rather than call_rcu(), in order to take
-		advantage of call_rcu_bh()'s faster grace periods.
+		advantage of call_rcu_bh()'s faster grace periods.  (This
+		is only a partial solution, though.)
 
 	e.	Periodically invoke synchronize_rcu(), permitting a limited
 		number of updates per grace period.
@@ -276,6 +277,13 @@ over a rather long period of time, but improvements are always welcome!
 	The same cautions apply to call_rcu_bh(), call_rcu_sched(),
 	call_srcu(), and kfree_rcu().
 
+	Note that although these primitives do take action to avoid memory
+	exhaustion when any given CPU has too many callbacks, a determined
+	user could still exhaust memory.  This is especially the case
+	if a system with a large number of CPUs has been configured to
+	offload all of its RCU callbacks onto a single CPU, or if the
+	system has relatively little free memory.
+
 9.	All RCU list-traversal primitives, which include
 	rcu_dereference(), list_for_each_entry_rcu(), and
 	list_for_each_safe_rcu(), must be either within an RCU read-side
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 26b1e31d5a13..fdad7d197062 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -14,7 +14,10 @@ Read Documentation/SubmitChecklist for a list of items to check
 before submitting code.  If you are submitting a driver, also read
 Documentation/SubmittingDrivers.
 
-
+Many of these steps describe the default behavior of the git version
+control system; if you use git to prepare your patches, you'll find much
+of the mechanical work done for you, though you'll still need to prepare
+and document a sensible set of patches.
 
 --------------------------------------------
 SECTION 1 - CREATING AND SENDING YOUR CHANGE
@@ -25,7 +28,9 @@ SECTION 1 - CREATING AND SENDING YOUR CHANGE
 1) "diff -up"
 ------------
 
-Use "diff -up" or "diff -uprN" to create patches.
+Use "diff -up" or "diff -uprN" to create patches.  git generates patches
+in this form by default; if you're using git, you can skip this section
+entirely.
 
 All changes to the Linux kernel occur in the form of patches, as
 generated by diff(1).  When creating your patch, make sure to create it
@@ -66,19 +71,14 @@ Make sure your patch does not include any extra files which do not
 belong in a patch submission.  Make sure to review your patch -after-
 generated it with diff(1), to ensure accuracy.
 
-If your changes produce a lot of deltas, you may want to look into
-splitting them into individual patches which modify things in
-logical stages.  This will facilitate easier reviewing by other
-kernel developers, very important if you want your patch accepted.
-There are a number of scripts which can aid in this:
-
-Quilt:
-http://savannah.nongnu.org/projects/quilt
+If your changes produce a lot of deltas, you need to split them into
+individual patches which modify things in logical stages; see section
+#3.  This will facilitate easier reviewing by other kernel developers,
+very important if you want your patch accepted.
 
-Andrew Morton's patch scripts:
-http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz
-Instead of these scripts, quilt is the recommended patch management
-tool (see above).
+If you're using git, "git rebase -i" can help you with this process.  If
+you're not using git, quilt <http://savannah.nongnu.org/projects/quilt>
+is another popular alternative.
 
 
 
@@ -106,8 +106,21 @@ I.e., the patch (series) and its description should be self-contained.
 This benefits both the patch merger(s) and reviewers.  Some reviewers
 probably didn't even receive earlier versions of the patch.
 
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
+instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
+to do frotz", as if you are giving orders to the codebase to change
+its behaviour.
+
 If the patch fixes a logged bug entry, refer to that bug entry by
-number and URL.
+number and URL.  If the patch follows from a mailing list discussion,
+give a URL to the mailing list archive; use the https://lkml.kernel.org/
+redirector with a Message-Id, to ensure that the links cannot become
+stale.
+
+However, try to make your explanation understandable without external
+resources.  In addition to giving a URL to a mailing list archive or
+bug, summarize the relevant points of the discussion that led to the
+patch as submitted.
 
 If you want to refer to a specific commit, don't just refer to the
 SHA-1 ID of the commit. Please also include the oneline summary of
@@ -594,7 +607,8 @@ patch.
 If you are going to include a diffstat after the "---" marker, please
 use diffstat options "-p 1 -w 70" so that filenames are listed from
 the top of the kernel source tree and don't use too much horizontal
-space (easily fit in 80 columns, maybe with some indentation).
+space (easily fit in 80 columns, maybe with some indentation).  (git
+generates appropriate diffstats by default.)
 
 See more details on the proper patch format in the following
 references.
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README
index 5a930c1528ad..963ec445e15a 100644
--- a/Documentation/arm/Marvell/README
+++ b/Documentation/arm/Marvell/README
@@ -83,14 +83,24 @@ EBU Armada family
         88F6710
         88F6707
         88F6W11
+    Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
+
+  Armada 375 Flavors:
+	88F6720
+    Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA_375_SoC-01_product_brief.pdf
+
+  Armada 380/385 Flavors:
+	88F6810
+	88F6820
+	88F6828
 
   Armada XP Flavors:
         MV78230
         MV78260
         MV78460
     NOTE: not to be confused with the non-SMP 78xx0 SoCs
+    Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
 
-  Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
   No public datasheet available.
 
   Core: Sheeva ARMv7 compatible
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index 5e054bfe4dde..85e24c4f215c 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -35,11 +35,13 @@ ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
 
 ffffffbe00000000	ffffffbffbbfffff	  ~8GB		[guard, future vmmemap]
 
-ffffffbffbc00000	ffffffbffbdfffff	   2MB		earlyprintk device
+ffffffbffa000000	ffffffbffaffffff	  16MB		PCI I/O space
+
+ffffffbffb000000	ffffffbffbbfffff	  12MB		[guard]
 
-ffffffbffbe00000	ffffffbffbe0ffff	  64KB		PCI I/O space
+ffffffbffbc00000	ffffffbffbdfffff	   2MB		earlyprintk device
 
-ffffffbffbe10000	ffffffbcffffffff	  ~2MB		[guard]
+ffffffbffbe00000	ffffffbffbffffff	   2MB		[guard]
 
 ffffffbffc000000	ffffffbfffffffff	  64MB		modules
 
@@ -60,11 +62,13 @@ fffffdfc00000000	fffffdfdffffffff	   8GB		vmemmap
 
 fffffdfe00000000	fffffdfffbbfffff	  ~8GB		[guard, future vmmemap]
 
-fffffdfffbc00000	fffffdfffbdfffff	   2MB		earlyprintk device
+fffffdfffa000000	fffffdfffaffffff	  16MB		PCI I/O space
+
+fffffdfffb000000	fffffdfffbbfffff	  12MB		[guard]
 
-fffffdfffbe00000	fffffdfffbe0ffff	  64KB		PCI I/O space
+fffffdfffbc00000	fffffdfffbdfffff	   2MB		earlyprintk device
 
-fffffdfffbe10000	fffffdfffbffffff	  ~2MB		[guard]
+fffffdfffbe00000	fffffdfffbffffff	   2MB		[guard]
 
 fffffdfffc000000	fffffdffffffffff	  64MB		modules
 
diff --git a/Documentation/blockdev/drbd/data-structure-v9.txt b/Documentation/blockdev/drbd/data-structure-v9.txt
new file mode 100644
index 000000000000..1e52a0e32624
--- /dev/null
+++ b/Documentation/blockdev/drbd/data-structure-v9.txt
@@ -0,0 +1,38 @@
+This describes the in kernel data structure for DRBD-9. Starting with
+Linux v3.14 we are reorganizing DRBD to use this data structure.
+
+Basic Data Structure
+====================
+
+A node has a number of DRBD resources.  Each such resource has a number of
+devices (aka volumes) and connections to other nodes ("peer nodes"). Each DRBD
+device is represented by a block device locally.
+
+The DRBD objects are interconnected to form a matrix as depicted below; a
+drbd_peer_device object sits at each intersection between a drbd_device and a
+drbd_connection:
+
+  /--------------+---------------+.....+---------------\
+  |   resource   |    device     |     |    device     |
+  +--------------+---------------+.....+---------------+
+  |  connection  |  peer_device  |     |  peer_device  |
+  +--------------+---------------+.....+---------------+
+  :              :               :     :               :
+  :              :               :     :               :
+  +--------------+---------------+.....+---------------+
+  |  connection  |  peer_device  |     |  peer_device  |
+  \--------------+---------------+.....+---------------/
+
+In this table, horizontally, devices can be accessed from resources by their
+volume number.  Likewise, peer_devices can be accessed from connections by
+their volume number.  Objects in the vertical direction are connected by double
+linked lists.  There are back pointers from peer_devices to their connections a
+devices, and from connections and devices to their resource.
+
+All resources are in the drbd_resources double-linked list.  In addition, all
+devices can be accessed by their minor device number via the drbd_devices idr.
+
+The drbd_resource, drbd_connection, and drbd_device objects are reference
+counted.  The peer_device objects only serve to establish the links between
+devices and connections; their lifetime is determined by the lifetime of the
+device and connection which they reference.
diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt
index 2eccddffa6c8..2604ffed51db 100644
--- a/Documentation/blockdev/zram.txt
+++ b/Documentation/blockdev/zram.txt
@@ -21,7 +21,42 @@ Following shows a typical sequence of steps for using zram.
 	This creates 4 devices: /dev/zram{0,1,2,3}
 	(num_devices parameter is optional. Default: 1)
 
-2) Set Disksize
+2) Set max number of compression streams
+	Compression backend may use up to max_comp_streams compression streams,
+	thus allowing up to max_comp_streams concurrent compression operations.
+	By default, compression backend uses single compression stream.
+
+	Examples:
+	#show max compression streams number
+	cat /sys/block/zram0/max_comp_streams
+
+	#set max compression streams number to 3
+	echo 3 > /sys/block/zram0/max_comp_streams
+
+Note:
+In order to enable compression backend's multi stream support max_comp_streams
+must be initially set to desired concurrency level before ZRAM device
+initialisation. Once the device initialised as a single stream compression
+backend (max_comp_streams equals to 0) changing the value of max_comp_streams
+will not take any effect, because single stream compression backend implemented
+as a special case and does not support dynamic max_comp_streams. Only multi
+stream backend supports dynamic max_comp_streams adjustment.
+
+3) Select compression algorithm
+	Using comp_algorithm device attribute one can see available and
+	currently selected (shown in square brackets) compression algortithms,
+	change selected compression algorithm (once the device is initialised
+	there is no way to change compression algorithm).
+
+	Examples:
+	#show supported compression algorithms
+	cat /sys/block/zram0/comp_algorithm
+	lzo [lz4]
+
+	#select lzo compression algorithm
+	echo lzo > /sys/block/zram0/comp_algorithm
+
+4) Set Disksize
         Set disk size by writing the value to sysfs node 'disksize'.
         The value can be either in bytes or you can use mem suffixes.
         Examples:
@@ -33,32 +68,38 @@ Following shows a typical sequence of steps for using zram.
             echo 512M > /sys/block/zram0/disksize
             echo 1G > /sys/block/zram0/disksize
 
-3) Activate:
+Note:
+There is little point creating a zram of greater than twice the size of memory
+since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
+size of the disk when not in use so a huge zram is wasteful.
+
+5) Activate:
 	mkswap /dev/zram0
 	swapon /dev/zram0
 
 	mkfs.ext4 /dev/zram1
 	mount /dev/zram1 /tmp
 
-4) Stats:
+6) Stats:
 	Per-device statistics are exported as various nodes under
 	/sys/block/zram<id>/
 		disksize
 		num_reads
 		num_writes
+		failed_reads
+		failed_writes
 		invalid_io
 		notify_free
-		discard
 		zero_pages
 		orig_data_size
 		compr_data_size
 		mem_used_total
 
-5) Deactivate:
+7) Deactivate:
 	swapoff /dev/zram0
 	umount /dev/zram1
 
-6) Reset:
+8) Reset:
 	Write any positive value to 'reset' sysfs node
 	echo 1 > /sys/block/zram0/reset
 	echo 1 > /sys/block/zram1/reset
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
index adcca0368d60..d12cc944b696 100644
--- a/Documentation/connector/cn_test.c
+++ b/Documentation/connector/cn_test.c
@@ -145,7 +145,7 @@ static void cn_test_timer_func(unsigned long __data)
 
 		memcpy(m + 1, data, m->len);
 
-		cn_netlink_send(m, 0, GFP_ATOMIC);
+		cn_netlink_send(m, 0, 0, GFP_ATOMIC);
 		kfree(m);
 	}
 
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 10378cc48374..d154147d0015 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -353,6 +353,7 @@ Your cooperation is appreciated.
 		133 = /dev/exttrp	External device trap
 		134 = /dev/apm_bios	Advanced Power Management BIOS
 		135 = /dev/rtc		Real Time Clock
+		137 = /dev/vhci		Bluetooth virtual HCI driver
 		139 = /dev/openprom	SPARC OpenBoot PROM
 		140 = /dev/relay8	Berkshire Products Octal relay card
 		141 = /dev/relay16	Berkshire Products ISO-16 relay card
@@ -410,6 +411,7 @@ Your cooperation is appreciated.
 		194 = /dev/zkshim	Zero-Knowledge network shim control
 		195 = /dev/elographics/e2201	Elographics touchscreen E271-2201
 		196 = /dev/vfio/vfio	VFIO userspace driver interface
+		197 = /dev/pxa3xx-gcu	PXA3xx graphics controller unit driver
 		198 = /dev/sexec	Signed executable interface
 		199 = /dev/scanners/cuecat :CueCat barcode scanner
 		200 = /dev/net/tun	TAP/TUN network device
@@ -451,6 +453,7 @@ Your cooperation is appreciated.
 		236 = /dev/mapper/control	Device-Mapper control device
 		237 = /dev/loop-control Loopback control device
 		238 = /dev/vhost-net	Host kernel accelerator for virtio net
+		239 = /dev/uhid		User-space I/O driver support for HID subsystem
 
 		240-254			Reserved for local use
 		255			Reserved for MISC_DYNAMIC_MINOR
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index d74091a8a3bf..5fc03134a999 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -1,4 +1,4 @@
-Marvell Armada 370 and Armada XP Interrupt Controller
+Marvell Armada 370, 375, 38x, XP Interrupt Controller
 -----------------------------------------------------
 
 Required properties:
@@ -16,7 +16,13 @@ Required properties:
   automatically map to the interrupt controller registers of the
   current CPU)
 
+Optional properties:
 
+- interrupts: If defined, then it indicates that this MPIC is
+  connected as a slave to another interrupt controller. This is
+  typically the case on Armada 375 and Armada 38x, where the MPIC is
+  connected as a slave to the Cortex-A9 GIC. The provided interrupt
+  indicate to which GIC interrupt the MPIC output is connected.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/armada-375.txt b/Documentation/devicetree/bindings/arm/armada-375.txt
new file mode 100644
index 000000000000..867d0b80cb8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armada-375.txt
@@ -0,0 +1,9 @@
+Marvell Armada 375 Platforms Device Tree Bindings
+-------------------------------------------------
+
+Boards with a SoC of the Marvell Armada 375 family shall have the
+following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armada375"
diff --git a/Documentation/devicetree/bindings/arm/armada-38x.txt b/Documentation/devicetree/bindings/arm/armada-38x.txt
new file mode 100644
index 000000000000..11f2330a6554
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armada-38x.txt
@@ -0,0 +1,10 @@
+Marvell Armada 38x Platforms Device Tree Bindings
+-------------------------------------------------
+
+Boards with a SoC of the Marvell Armada 38x family shall have the
+following property:
+
+Required root node property:
+
+ - compatible: must contain either "marvell,armada380" or
+   "marvell,armada385" depending on the variant of the SoC being used.
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index d1061469f63d..9a1175b46f49 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -5,6 +5,9 @@ Required properties:
     <chip> can be "at91sam9260", "at91sam9g45" or "at91sam9x5"
   - reg: Should contain ADC registers location and length
   - interrupts: Should contain the IRQ line for the ADC
+  - clock-names: tuple listing input clock names.
+	Required elements: "adc_clk", "adc_op_clk".
+  - clocks: phandles to input clocks.
   - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
     device
   - atmel,adc-startup-time: Startup Time of the ADC in microseconds as
@@ -44,6 +47,8 @@ adc0: adc@fffb0000 {
 	compatible = "atmel,at91sam9260-adc";
 	reg = <0xfffb0000 0x100>;
 	interrupts = <20 4>;
+	clocks = <&adc_clk>, <&adc_op_clk>;
+	clock-names = "adc_clk", "adc_op_clk";
 	atmel,adc-channel-base = <0x30>;
 	atmel,adc-channels-used = <0xff>;
 	atmel,adc-drdy-mask = <0x10000>;
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 91304353eea4..333f4aea3029 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -180,7 +180,11 @@ nodes to be present and contain the properties described below.
 			  be one of:
 			     "spin-table"
 			     "psci"
-			# On ARM 32-bit systems this property is optional.
+			# On ARM 32-bit systems this property is optional and
+			  can be one of:
+			    "qcom,gcc-msm8660"
+			    "qcom,kpss-acc-v1"
+			    "qcom,kpss-acc-v2"
 
 	- cpu-release-addr
 		Usage: required for systems that have an "enable-method"
@@ -191,6 +195,21 @@ nodes to be present and contain the properties described below.
 			  property identifying a 64-bit zero-initialised
 			  memory location.
 
+	- qcom,saw
+		Usage: required for systems that have an "enable-method"
+		       property value of "qcom,kpss-acc-v1" or
+		       "qcom,kpss-acc-v2"
+		Value type: <phandle>
+		Definition: Specifies the SAW[1] node associated with this CPU.
+
+	- qcom,acc
+		Usage: required for systems that have an "enable-method"
+		       property value of "qcom,kpss-acc-v1" or
+		       "qcom,kpss-acc-v2"
+		Value type: <phandle>
+		Definition: Specifies the ACC[2] node associated with this CPU.
+
+
 Example 1 (dual-cluster big.LITTLE system 32-bit):
 
 	cpus {
@@ -382,3 +401,7 @@ cpus {
 		cpu-release-addr = <0 0x20000000>;
 	};
 };
+
+--
+[1] arm/msm/qcom,saw2.txt
+[2] arm/msm/qcom,kpss-acc.txt
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
 		resume-offset = <0x308>;
 		reboot-offset = <0x4>;
 	};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+	/* for Hi3620 */
+	pctrl: pctrl@fca09000 {
+		compatible = "hisilicon,pctrl";
+		reg = <0xfca09000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/keystone/keystone.txt b/Documentation/devicetree/bindings/arm/keystone/keystone.txt
index 63c0e6ae5cf7..ad16e7a58893 100644
--- a/Documentation/devicetree/bindings/arm/keystone/keystone.txt
+++ b/Documentation/devicetree/bindings/arm/keystone/keystone.txt
@@ -8,3 +8,13 @@ Required properties:
  - compatible: All TI specific devices present in Keystone SOC should be in
    the form "ti,keystone-*". Generic devices like gic, arch_timers, ns16550
    type UART should use the specified compatible for those devices.
+
+Boards:
+-  Keystone 2 Hawking/Kepler EVM
+   compatible = "ti,k2hk-evm"
+
+-  Keystone 2 Lamarr EVM
+   compatible = "ti,k2l-evm"
+
+-  Keystone 2 Edison EVM
+   compatible = "ti,k2e-evm"
diff --git a/Documentation/devicetree/bindings/arm/marvell,dove.txt b/Documentation/devicetree/bindings/arm/marvell,dove.txt
new file mode 100644
index 000000000000..aaaf64c56e44
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell,dove.txt
@@ -0,0 +1,22 @@
+Marvell Dove Platforms Device Tree Bindings
+-----------------------------------------------
+
+Boards with a Marvell Dove SoC shall have the following properties:
+
+Required root node property:
+- compatible: must contain "marvell,dove";
+
+* Global Configuration registers
+
+Global Configuration registers of Dove SoC are shared by a syscon node.
+
+Required properties:
+- compatible: must contain "marvell,dove-global-config" and "syscon".
+- reg: base address and size of the Global Configuration registers.
+
+Example:
+
+gconf: global-config@e802c {
+	compatible = "marvell,dove-global-config", "syscon";
+	reg = <0xe802c 0x14>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mrvl/feroceon.txt b/Documentation/devicetree/bindings/arm/mrvl/feroceon.txt
new file mode 100644
index 000000000000..0d244b999d10
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mrvl/feroceon.txt
@@ -0,0 +1,16 @@
+* Marvell Feroceon Cache
+
+Required properties:
+- compatible : Should be either "marvell,feroceon-cache" or
+  	       "marvell,kirkwood-cache".
+
+Optional properties:
+- reg        : Address of the L2 cache control register. Mandatory for
+  	       "marvell,kirkwood-cache", not used by "marvell,feroceon-cache"
+
+
+Example:
+		l2: l2-cache@20128 {
+			compatible = "marvell,kirkwood-cache";
+			reg = <0x20128 0x4>;
+		};
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
new file mode 100644
index 000000000000..1333db9acfee
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
@@ -0,0 +1,30 @@
+Krait Processor Sub-system (KPSS) Application Clock Controller (ACC)
+
+The KPSS ACC provides clock, power domain, and reset control to a Krait CPU.
+There is one ACC register region per CPU within the KPSS remapped region as
+well as an alias register region that remaps accesses to the ACC associated
+with the CPU accessing the region.
+
+PROPERTIES
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: should be one of:
+			"qcom,kpss-acc-v1"
+			"qcom,kpss-acc-v2"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the first element specifies the base address and size of
+		    the register region. An optional second element specifies
+		    the base address and size of the alias register region.
+
+Example:
+
+	clock-controller@2088000 {
+		compatible = "qcom,kpss-acc-v2";
+		reg = <0x02088000 0x1000>,
+		      <0x02008000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt
new file mode 100644
index 000000000000..1505fb8e131a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt
@@ -0,0 +1,35 @@
+SPM AVS Wrapper 2 (SAW2)
+
+The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the
+Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable
+micro-controller that transitions a piece of hardware (like a processor or
+subsystem) into and out of low power modes via a direct connection to
+the PMIC. It can also be wired up to interact with other processors in the
+system, notifying them when a low power state is entered or exited.
+
+PROPERTIES
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: shall contain "qcom,saw2". A more specific value should be
+		    one of:
+			 "qcom,saw2-v1"
+			 "qcom,saw2-v1.1"
+			 "qcom,saw2-v2"
+			 "qcom,saw2-v2.1"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the first element specifies the base address and size of
+		    the register region. An optional second element specifies
+		    the base address and size of the alias register region.
+
+
+Example:
+
+	regulator@2099000 {
+		compatible = "qcom,saw2";
+		reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt
index 081c6a786c8a..d24ab2ebf8a7 100644
--- a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt
+++ b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt
@@ -1,12 +1,13 @@
 MVEBU System Controller
 -----------------------
-MVEBU (Marvell SOCs: Armada 370/XP, Dove, mv78xx0, Kirkwood, Orion5x)
+MVEBU (Marvell SOCs: Armada 370/375/XP, Dove, mv78xx0, Kirkwood, Orion5x)
 
 Required properties:
 
 - compatible: one of:
 	- "marvell,orion-system-controller"
 	- "marvell,armada-370-xp-system-controller"
+	- "marvell,armada-375-system-controller"
 - reg: Should contain system controller registers location and length.
 
 Example:
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
index 3e1e498fea96..fe5cef8976cb 100644
--- a/Documentation/devicetree/bindings/arm/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -9,6 +9,7 @@ Required properties:
 - compatible : should be one of
 	"arm,armv8-pmuv3"
 	"arm,cortex-a15-pmu"
+	"arm,cortex-a12-pmu"
 	"arm,cortex-a9-pmu"
 	"arm,cortex-a8-pmu"
 	"arm,cortex-a7-pmu"
@@ -16,7 +17,14 @@ Required properties:
 	"arm,arm11mpcore-pmu"
 	"arm,arm1176-pmu"
 	"arm,arm1136-pmu"
-- interrupts : 1 combined interrupt or 1 per core.
+	"qcom,krait-pmu"
+- interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu
+               interrupt (PPI) then 1 interrupt should be specified.
+
+Optional properties:
+
+- qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd
+                     events.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
new file mode 100644
index 000000000000..f1f155255f28
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
@@ -0,0 +1,15 @@
+SAMSUNG Exynos SoC series PMU Registers
+
+Properties:
+ - compatible : should contain two values. First value must be one from following list:
+		   - "samsung,exynos5250-pmu" - for Exynos5250 SoC,
+		   - "samsung,exynos5420-pmu" - for Exynos5420 SoC.
+		second value must be always "syscon".
+
+ - reg : offset and length of the register set.
+
+Example :
+pmu_system_controller: system-controller@10040000 {
+	compatible = "samsung,exynos5250-pmu", "syscon";
+	reg = <0x10040000 0x5000>;
+};
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 89de1564950c..48b285ffa3a6 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -4,17 +4,33 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
 Each SATA controller should have its own node.
 
 Required properties:
-- compatible        : compatible list, contains "snps,spear-ahci"
+- compatible        : compatible list, one of "snps,spear-ahci",
+                      "snps,exynos5440-ahci", "ibm,476gtr-ahci",
+                      "allwinner,sun4i-a10-ahci", "fsl,imx53-ahci"
+                      "fsl,imx6q-ahci" or "snps,dwc-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
+- clocks            : a list of phandle + clock specifier pairs
+- target-supply     : regulator for SATA target power
 
-Example:
+"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
+- clocks            : must contain the sata, sata_ref and ahb clocks
+- clock-names       : must contain "ahb" for the ahb clock
+
+Examples:
         sata@ffe08000 {
 		compatible = "snps,spear-ahci";
 		reg = <0xffe08000 0x1000>;
 		interrupts = <115>;
-
         };
+
+	ahci: sata@01c18000 {
+		compatible = "allwinner,sun4i-a10-ahci";
+		reg = <0x01c18000 0x1000>;
+		interrupts = <56>;
+		clocks = <&pll6 0>, <&ahb_gates 25>;
+		target-supply = <&reg_ahci_5v>;
+	};
diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt
index 0fd76c405208..6630d842c7a3 100644
--- a/Documentation/devicetree/bindings/bus/imx-weim.txt
+++ b/Documentation/devicetree/bindings/bus/imx-weim.txt
@@ -8,7 +8,12 @@ The actual devices are instantiated from the child nodes of a WEIM node.
 
 Required properties:
 
- - compatible:		Should be set to "fsl,<soc>-weim"
+ - compatible:		Should contain one of the following:
+			  "fsl,imx1-weim"
+			  "fsl,imx27-weim"
+			  "fsl,imx51-weim"
+			  "fsl,imx50-weim"
+			  "fsl,imx6q-weim"
  - reg:			A resource specifier for the register space
 			(see the example below)
  - clocks:		the clock, see the example below.
@@ -19,6 +24,26 @@ Required properties:
 
 			   <cs-number> 0 <physical address of mapping> <size>
 
+Optional properties:
+
+ - fsl,weim-cs-gpr:	For "fsl,imx50-weim" and "fsl,imx6q-weim" type of
+			devices, it should be the phandle to the system General
+			Purpose Register controller that contains WEIM CS GPR
+			register, e.g. IOMUXC_GPR1 on i.MX6Q.  IOMUXC_GPR1[11:0]
+			should be set up as one of the following 4 possible
+			values depending on the CS space configuration.
+
+			IOMUXC_GPR1[11:0]    CS0    CS1    CS2    CS3
+			---------------------------------------------
+				05	    128M     0M     0M     0M
+				033          64M    64M     0M     0M
+				0113         64M    32M    32M     0M
+				01111        32M    32M    32M    32M
+
+			In case that the property is absent, the reset value or
+			what bootloader sets up in IOMUXC_GPR1[11:0] will be
+			used.
+
 Timing property for child nodes. It is mandatory, not optional.
 
  - fsl,weim-cs-timing:	The timing array, contains timing values for the
@@ -43,6 +68,7 @@ Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <0 0 0x08000000 0x08000000>;
+		fsl,weim-cs-gpr = <&gpr>;
 
 		nor@0,0 {
 			compatible = "cfi-flash";
diff --git a/Documentation/devicetree/bindings/clock/altr_socfpga.txt b/Documentation/devicetree/bindings/clock/altr_socfpga.txt
index 0045433eae1f..5dfd145d3ccf 100644
--- a/Documentation/devicetree/bindings/clock/altr_socfpga.txt
+++ b/Documentation/devicetree/bindings/clock/altr_socfpga.txt
@@ -23,3 +23,8 @@ Optional properties:
         and the bit index.
 - div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift,
         and width.
+- clk-phase : For the sdmmc_clk, contains the value of the clock phase that controls
+	the SDMMC CIU clock. The first value is the clk_sample(smpsel), and the second
+	value is the cclk_in_drv(drvsel). The clk-phase is used to enable the correct
+	hold/delay times that is needed for the SD/MMC CIU clock. The values of both
+	can be 0-315 degrees, in 45 degree increments.
diff --git a/Documentation/devicetree/bindings/clock/arm-integrator.txt b/Documentation/devicetree/bindings/clock/arm-integrator.txt
new file mode 100644
index 000000000000..652914b17b95
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/arm-integrator.txt
@@ -0,0 +1,34 @@
+Clock bindings for ARM Integrator Core Module clocks
+
+Auxilary Oscillator Clock
+
+This is a configurable clock fed from a 24 MHz chrystal,
+used for generating e.g. video clocks. It is located on the
+core module and there is only one of these.
+
+This clock node *must* be a subnode of the core module, since
+it obtains the base address for it's address range from its
+parent node.
+
+
+Required properties:
+- compatible: must be "arm,integrator-cm-auxosc"
+- #clock-cells: must be <0>
+
+Optional properties:
+- clocks: parent clock(s)
+
+Example:
+
+core-module@10000000 {
+	xtal24mhz: xtal24mhz@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+	auxosc: cm_aux_osc@25M {
+		#clock-cells = <0>;
+		compatible = "arm,integrator-cm-auxosc";
+		clocks = <&xtal24mhz>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt
index 028b493e97ff..20e1704e7df2 100644
--- a/Documentation/devicetree/bindings/clock/axi-clkgen.txt
+++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt
@@ -5,7 +5,7 @@ This binding uses the common clock binding[1].
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 
 Required properties:
-- compatible : shall be "adi,axi-clkgen".
+- compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a".
 - #clock-cells : from common clock binding; Should always be set to 0.
 - reg : Address and length of the axi-clkgen register set.
 - clocks : Phandle and clock specifier for the parent clock.
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 7c52c29d99fa..700e7aac3717 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -44,6 +44,23 @@ For example:
   clocks by index. The names should reflect the clock output signal
   names for the device.
 
+clock-indices:	   If the identifyng number for the clocks in the node
+		   is not linear from zero, then the this mapping allows
+		   the mapping of identifiers into the clock-output-names
+		   array.
+
+For example, if we have two clocks <&oscillator 1> and <&oscillator 3>:
+
+	oscillator {
+		compatible = "myclocktype";
+		#clock-cells = <1>;
+		clock-indices = <1>, <3>;
+		clock-output-names = "clka", "clkb";
+	}
+
+	This ensures we do not have any empty nodes in clock-output-names
+
+
 ==Clock consumers==
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: should be one of the following.
   - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+  - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
 
 - reg: physical base address of the controller and length of memory mapped
   region.
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
index 1e662948661e..307a503c5db8 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
@@ -11,6 +11,18 @@ The following is a list of provided IDs and clock names on Armada 370/XP:
  3 = hclk    (DRAM control clock)
  4 = dramclk (DDR clock)
 
+The following is a list of provided IDs and clock names on Armada 375:
+ 0 = tclk    (Internal Bus clock)
+ 1 = cpuclk  (CPU clock)
+ 2 = l2clk   (L2 Cache clock)
+ 3 = ddrclk  (DDR clock)
+
+The following is a list of provided IDs and clock names on Armada 380/385:
+ 0 = tclk    (Internal Bus clock)
+ 1 = cpuclk  (CPU clock)
+ 2 = l2clk   (L2 Cache clock)
+ 3 = ddrclk  (DDR clock)
+
 The following is a list of provided IDs and clock names on Kirkwood and Dove:
  0 = tclk   (Internal Bus clock)
  1 = cpuclk (CPU0 clock)
@@ -20,6 +32,8 @@ The following is a list of provided IDs and clock names on Kirkwood and Dove:
 Required properties:
 - compatible : shall be one of the following:
 	"marvell,armada-370-core-clock" - For Armada 370 SoC core clocks
+	"marvell,armada-375-core-clock" - For Armada 375 SoC core clocks
+	"marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks
 	"marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
 	"marvell,dove-core-clock" - for Dove SoC core clocks
 	"marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
index fc2910fa7e45..76477be742b2 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -1,9 +1,10 @@
 * Gated Clock bindings for Marvell EBU SoCs
 
-Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be
-gated to save some power. The clock consumer should specify the desired clock
-by having the clock ID in its "clocks" phandle cell. The clock ID is directly
-mapped to the corresponding clock gating control bit in HW to ease manual clock
+Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some
+peripheral clocks to be gated to save some power. The clock consumer
+should specify the desired clock by having the clock ID in its
+"clocks" phandle cell. The clock ID is directly mapped to the
+corresponding clock gating control bit in HW to ease manual clock
 lookup in datasheet.
 
 The following is a list of provided IDs for Armada 370:
@@ -22,6 +23,60 @@ ID	Clock	Peripheral
 28	ddr	DDR Cntrl
 30	sata1	SATA Host 0
 
+The following is a list of provided IDs for Armada 375:
+ID	Clock		Peripheral
+-----------------------------------
+2	mu		Management Unit
+3	pp		Packet Processor
+4	ptp		PTP
+5	pex0		PCIe 0 Clock out
+6	pex1		PCIe 1 Clock out
+8	audio		Audio Cntrl
+11	nd_clk		Nand Flash Cntrl
+14	sata0_link	SATA 0 Link
+15	sata0_core	SATA 0 Core
+16	usb3		USB3 Host
+17	sdio		SDHCI Host
+18	usb		USB Host
+19	gop		Gigabit Ethernet MAC
+20	sata1_link	SATA 1 Link
+21	sata1_core	SATA 1 Core
+22	xor0		XOR DMA 0
+23	xor1		XOR DMA 0
+24	copro		Coprocessor
+25	tdm		Time Division Mplx
+28	crypto0_enc	Cryptographic Unit Port 0 Encryption
+29	crypto0_core	Cryptographic Unit Port 0 Core
+30	crypto1_enc	Cryptographic Unit Port 1 Encryption
+31	crypto1_core	Cryptographic Unit Port 1 Core
+
+The following is a list of provided IDs for Armada 380/385:
+ID	Clock		Peripheral
+-----------------------------------
+0	audio		Audio
+2	ge2		Gigabit Ethernet 2
+3	ge1		Gigabit Ethernet 1
+4	ge0		Gigabit Ethernet 0
+5	pex1		PCIe 1
+6	pex2		PCIe 2
+7	pex3		PCIe 3
+8	pex0		PCIe 0
+9	usb3h0		USB3 Host 0
+10	usb3h1		USB3 Host 1
+11	usb3d		USB3 Device
+13	bm		Buffer Management
+14	crypto0z	Cryptographic 0 Z
+15	sata0		SATA 0
+16	crypto1z	Cryptographic 1 Z
+17	sdio		SDIO
+18	usb2		USB 2
+21	crypto1		Cryptographic 1
+22	xor0		XOR 0
+23	crypto0		Cryptographic 0
+25	tdm		Time Division Multiplexing
+28	xor1		XOR 1
+30	sata1		SATA 1
+
 The following is a list of provided IDs for Armada XP:
 ID	Clock	Peripheral
 -----------------------------------
@@ -95,6 +150,8 @@ ID	Clock	Peripheral
 Required properties:
 - compatible : shall be one of the following:
 	"marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating
+	"marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating
+	"marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating
 	"marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating
 	"marvell,dove-gating-clock" - for Dove SoC clock gating
 	"marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index a6a352c2771e..5992dceec7af 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -21,9 +21,9 @@ Required Properties:
     must appear in the same order as the output clocks.
   - #clock-cells: Must be 1
   - clock-output-names: The name of the clocks as free-form strings
-  - renesas,indices: Indices of the gate clocks into the group (0 to 31)
+  - renesas,clock-indices: Indices of the gate clocks into the group (0 to 31)
 
-The clocks, clock-output-names and renesas,indices properties contain one
+The clocks, clock-output-names and renesas,clock-indices properties contain one
 entry per gate clock. The MSTP groups are sparsely populated. Unimplemented
 gate clocks must not be declared.
 
diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt
new file mode 100644
index 000000000000..2b430960ba47
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt
@@ -0,0 +1,50 @@
+* Samsung S3C2412 Clock Controller
+
+The S3C2412 clock controller generates and supplies clock to various controllers
+within the SoC. The clock binding described here is applicable to the s3c2412
+and s3c2413 SoCs in the s3c24x family.
+
+Required Properties:
+
+- compatible: should be "samsung,s3c2412-clock"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. Some of the clocks are available only
+on a particular SoC.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s3c2412.h header and can be used in device
+tree sources.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xti" - crystal input - required,
+ - "ext" - external clock source - optional,
+
+Example: Clock controller node:
+
+	clocks: clock-controller@4c000000 {
+		compatible = "samsung,s3c2412-clock";
+		reg = <0x4c000000 0x20>;
+		#clock-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller (refer to the standard clock bindings for information about
+  "clocks" and "clock-names" properties):
+
+	serial@50004000 {
+		compatible = "samsung,s3c2412-uart";
+		reg = <0x50004000 0x4000>;
+		interrupts = <1 23 3 4>, <1 23 4 4>;
+		clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3";
+		clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+			 <&clocks SCLK_UART>;
+		status = "disabled";
+	};
diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt
new file mode 100644
index 000000000000..e67bb05478af
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt
@@ -0,0 +1,56 @@
+* Samsung S3C2443 Clock Controller
+
+The S3C2443 clock controller generates and supplies clock to various controllers
+within the SoC. The clock binding described here is applicable to all SoCs in
+the s3c24x family starting with the s3c2443.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "samsung,s3c2416-clock" - controller compatible with S3C2416 SoC.
+  - "samsung,s3c2443-clock" - controller compatible with S3C2443 SoC.
+  - "samsung,s3c2450-clock" - controller compatible with S3C2450 SoC.
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. Some of the clocks are available only
+on a particular SoC.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s3c2443.h header and can be used in device
+tree sources.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xti" - crystal input - required,
+ - "ext" - external clock source - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_uart" - external uart clock - optional,
+
+Example: Clock controller node:
+
+	clocks: clock-controller@4c000000 {
+		compatible = "samsung,s3c2416-clock";
+		reg = <0x4c000000 0x40>;
+		#clock-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller (refer to the standard clock bindings for information about
+  "clocks" and "clock-names" properties):
+
+	serial@50004000 {
+		compatible = "samsung,s3c2440-uart";
+		reg = <0x50004000 0x4000>;
+		interrupts = <1 23 3 4>, <1 23 4 4>;
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+				<&clocks SCLK_UART>;
+		status = "disabled";
+	};
diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt
new file mode 100644
index 000000000000..191d7bd8a6fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt
@@ -0,0 +1,76 @@
+* Freescale enhanced Direct Memory Access(eDMA) Controller
+
+  The eDMA channels have multiplex capability by programmble memory-mapped
+registers. channels are split into two groups, called DMAMUX0 and DMAMUX1,
+specific DMA request source can only be multiplexed by any channel of certain
+group, DMAMUX0 or DMAMUX1, but not both.
+
+* eDMA Controller
+Required properties:
+- compatible :
+	- "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC
+- reg : Specifies base physical address(s) and size of the eDMA registers.
+	The 1st region is eDMA control register's address and size.
+	The 2nd and the 3rd regions are programmable channel multiplexing
+	control register's address and size.
+- interrupts : A list of interrupt-specifiers, one for each entry in
+	interrupt-names.
+- interrupt-names : Should contain:
+	"edma-tx" - the transmission interrupt
+	"edma-err" - the error interrupt
+- #dma-cells : Must be <2>.
+	The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1).
+	Specific request source can only be multiplexed by specific channels
+	group called DMAMUX.
+	The 2nd cell specifies the request source(slot) ID.
+	See the SoC's reference manual for all the supported request sources.
+- dma-channels : Number of channels supported by the controller
+- clock-names : A list of channel group clock names. Should contain:
+	"dmamux0" - clock name of mux0 group
+	"dmamux1" - clock name of mux1 group
+- clocks : A list of phandle and clock-specifier pairs, one for each entry in
+	clock-names.
+
+Optional properties:
+- big-endian: If present registers and hardware scatter/gather descriptors
+	of the eDMA are implemented in big endian mode, otherwise in little
+	mode.
+
+
+Examples:
+
+edma0: dma-controller@40018000 {
+	#dma-cells = <2>;
+	compatible = "fsl,vf610-edma";
+	reg = <0x40018000 0x2000>,
+		<0x40024000 0x1000>,
+		<0x40025000 0x1000>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
+		<0 9 IRQ_TYPE_LEVEL_HIGH>;
+	interrupt-names = "edma-tx", "edma-err";
+	dma-channels = <32>;
+	clock-names = "dmamux0", "dmamux1";
+	clocks = <&clks VF610_CLK_DMAMUX0>,
+		<&clks VF610_CLK_DMAMUX1>;
+};
+
+
+* DMA clients
+DMA client drivers that uses the DMA function must use the format described
+in the dma.txt file, using a two-cell specifier for each channel: the 1st
+specifies the channel group(DMAMUX) in which this request can be multiplexed,
+and the 2nd specifies the request source.
+
+Examples:
+
+sai2: sai@40031000 {
+	compatible = "fsl,vf610-sai";
+	reg = <0x40031000 0x1000>;
+	interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+	clock-names = "sai";
+	clocks = <&clks VF610_CLK_SAI2>;
+	dma-names = "tx", "rx";
+	dmas = <&edma0 0 21>,
+		<&edma0 0 20>;
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
new file mode 100644
index 000000000000..d7df01c5bb3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
@@ -0,0 +1,27 @@
+Device-Tree bindings for the NXP TDA998x HDMI transmitter
+
+Required properties;
+  - compatible: must be "nxp,tda998x"
+
+Optional properties:
+  - interrupts: interrupt number and trigger type
+	default: polling
+
+  - pinctrl-0: pin control group to be used for
+	screen plug/unplug interrupt.
+
+  - pinctrl-names: must contain a "default" entry.
+
+  - video-ports: 24 bits value which defines how the video controller
+	output is wired to the TDA998x input - default: <0x230145>
+
+Example:
+
+	tda998x: hdmi-encoder {
+		compatible = "nxp,tda998x";
+		reg = <0x70>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <27 2>;		/* falling edge */
+		pinctrl-0 = <&pmx_camera>;
+		pinctrl-names = "default";
+	};
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
index efaeec8961b6..efa8b8451f93 100644
--- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -190,6 +190,48 @@ of the following host1x client modules:
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
 
+- sor: serial output resource
+
+  Required properties:
+  - compatible: "nvidia,tegra124-sor"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    - sor: clock input for the SOR hardware
+    - parent: input for the pixel clock
+    - dp: reference clock for the SOR clock
+    - safe: safe reference for the SOR clock during power up
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - sor
+
+  Optional properties:
+  - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+  - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+  - nvidia,edid: supplies a binary EDID blob
+  - nvidia,panel: phandle of a display panel
+
+  Optional properties when driving an eDP output:
+  - nvidia,dpaux: phandle to a DispayPort AUX interface
+
+- dpaux: DisplayPort AUX interface
+  - compatible: "nvidia,tegra124-dpaux"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    - dpaux: clock input for the DPAUX hardware
+    - parent: reference clock
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - dpaux
+  - vdd-supply: phandle of a supply that powers the DisplayPort link
+
 Example:
 
 / {
diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
index 897cfcd5ce92..dd8b2dd1edeb 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
@@ -6,6 +6,7 @@ Required properties:
 	"renesas,i2c-r8a7778"
 	"renesas,i2c-r8a7779"
 	"renesas,i2c-r8a7790"
+	"renesas,i2c-r8a7791"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: interrupt specifier.
@@ -13,11 +14,16 @@ Required properties:
 Optional properties:
 - clock-frequency: desired I2C bus clock frequency in Hz. The absence of this
   propoerty indicates the default frequency 100 kHz.
+- clocks: clock specifier.
 
 Examples :
 
-i2c0: i2c@e6500000 {
-	compatible = "renesas,i2c-rcar-h2";
-	reg = <0 0xe6500000 0 0x428>;
-	interrupts = <0 174 0x4>;
+i2c0: i2c@e6508000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "renesas,i2c-r8a7791";
+	reg = <0 0xe6508000 0 0x40>;
+	interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&mstp9_clks R8A7791_CLK_I2C0>;
+	clock-frequency = <400000>;
 };
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 1a1ac2e560e9..71724d026ffa 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -18,6 +18,7 @@ atmel,24c02		i2c serial eeprom  (24cxx)
 atmel,at97sc3204t	i2c trusted platform module (TPM)
 capella,cm32181		CM32181: Ambient Light Sensor
 catalyst,24c32		i2c serial eeprom
+cirrus,cs42l51		Cirrus Logic CS42L51 audio codec
 dallas,ds1307		64 x 8, Serial, I2C Real-Time Clock
 dallas,ds1338		I2C RTC with 56-Byte NV RAM
 dallas,ds1339		I2C Serial Real-Time Clock
@@ -58,6 +59,7 @@ plx,pex8648		48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
 ramtron,24c64		i2c serial eeprom  (24cxx)
 ricoh,rs5c372a		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 samsung,24ad0xd1	S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
+sii,s35390a		2-wire CMOS real-time clock
 st-micro,24c256		i2c serial eeprom  (24cxx)
 stm,m41t00		Serial Access TIMEKEEPER
 stm,m41t62		Serial real-time clock (RTC) with alarm
diff --git a/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
new file mode 100644
index 000000000000..dcebff1928e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
@@ -0,0 +1,22 @@
+Freescale vf610 Analog to Digital Converter bindings
+
+The devicetree bindings are for the new ADC driver written for
+vf610/i.MX6slx and upward SoCs from Freescale.
+
+Required properties:
+- compatible: Should contain "fsl,vf610-adc"
+- reg: Offset and length of the register set for the device
+- interrupts: Should contain the interrupt for the device
+- clocks: The clock is needed by the ADC controller, ADC clock source is ipg clock.
+- clock-names: Must contain "adc", matching entry in the clocks property.
+- vref-supply: The regulator supply ADC refrence voltage.
+
+Example:
+adc0: adc@4003b000 {
+	compatible = "fsl,vf610-adc";
+	reg = <0x4003b000 0x1000>;
+	interrupts = <0 53 0x04>;
+	clocks = <&clks VF610_CLK_ADC0>;
+	clock-names = "adc";
+	vref-supply = <&reg_vcc_3v3_mcu>;
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
new file mode 100644
index 000000000000..2faf1f1fa39e
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
@@ -0,0 +1,30 @@
+* Neonode infrared touchscreen controller
+
+Required properties:
+- compatible: must be "neonode,zforce"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- gpios: gpios the chip is connected to
+  first one is the interrupt gpio and second one the reset gpio
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		zforce_ts@50 {
+			compatible = "neonode,zforce";
+			reg = <0x50>;
+			interrupts = <2 0>;
+
+			gpios = <&gpio5 6 0>, /* INT */
+				<&gpio5 9 0>; /* RST */
+
+			x-size = <800>;
+			y-size = <600>;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt
new file mode 100644
index 000000000000..759339c34e4f
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt
@@ -0,0 +1,41 @@
+Cirrus Logic CLPS711X Interrupt Controller
+
+Required properties:
+
+- compatible: Should be "cirrus,clps711x-intc".
+- reg: Specifies base physical address of the registers set.
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+The interrupt sources are as follows:
+ID	Name	Description
+---------------------------
+1:	BLINT	Battery low (FIQ)
+3:	MCINT	Media changed (FIQ)
+4:	CSINT	CODEC sound
+5:	EINT1	External 1
+6:	EINT2	External 2
+7:	EINT3	External 3
+8:	TC1OI	TC1 under flow
+9:	TC2OI	TC2 under flow
+10:	RTCMI	RTC compare match
+11:	TINT	64Hz tick
+12:	UTXINT1	UART1 transmit FIFO half empty
+13:	URXINT1	UART1 receive FIFO half full
+14:	UMSINT	UART1 modem status changed
+15:	SSEOTI	SSI1 end of transfer
+16:	KBDINT	Keyboard
+17:	SS2RX	SSI2 receive FIFO half or greater full
+18:	SS2TX	SSI2 transmit FIFO less than half empty
+28:	UTXINT2	UART2 transmit FIFO half empty
+29:	URXINT2	UART2 receive FIFO half full
+32:	DAIINT	DAI interface (FIQ)
+
+Example:
+	intc: interrupt-controller {
+		compatible = "cirrus,clps711x-intc";
+		reg = <0x80000000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt
new file mode 100644
index 000000000000..1feb5825d372
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt
@@ -0,0 +1,17 @@
+Marvell Dove Power Management Unit interrupt controller
+
+Required properties:
+- compatible: shall be "marvell,dove-pmu-intc"
+- reg: base address of PMU interrupt registers starting with CAUSE register
+- interrupts: PMU interrupt of the main interrupt controller
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: number of cells to encode an interrupt source, shall be 1
+
+Example:
+	pmu_intc: pmu-interrupt-ctrl@d0050 {
+		compatible = "marvell,dove-pmu-intc";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xd0050 0x8>;
+		interrupts = <33>;
+	};
diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt
index df1b3080f6b8..f77148f372ea 100644
--- a/Documentation/devicetree/bindings/leds/leds-gpio.txt
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt
@@ -21,6 +21,8 @@ LED sub-node properties:
   on).  The "keep" setting will keep the LED at whatever its current
   state is, without producing a glitch.  The default is off if this
   property is not present.
+- retain-state-suspended: (optional) The suspend state can be retained.Such
+  as charge-led gpio.
 
 Examples:
 
@@ -50,3 +52,13 @@ run-control {
 		default-state = "on";
 	};
 };
+
+leds {
+	compatible = "gpio-leds";
+
+	charger-led {
+		gpios = <&gpio1 2 0>;
+		linux,default-trigger = "max8903-charger-charging";
+		retain-state-suspended;
+	};
+};
diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt b/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt
new file mode 100644
index 000000000000..d5e370450ac0
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt
@@ -0,0 +1,79 @@
+Integrated Flash Controller
+
+Properties:
+- name : Should be ifc
+- compatible : should contain "fsl,ifc". The version of the integrated
+               flash controller can be found in the IFC_REV register at
+               offset zero.
+
+- #address-cells : Should be either two or three.  The first cell is the
+                   chipselect number, and the remaining cells are the
+                   offset into the chipselect.
+- #size-cells : Either one or two, depending on how large each chipselect
+                can be.
+- reg : Offset and length of the register set for the device
+- interrupts: IFC may have one or two interrupts.  If two interrupt
+              specifiers are present, the first is the "common"
+              interrupt (CM_EVTER_STAT), and the second is the NAND
+              interrupt (NAND_EVTER_STAT).  If there is only one,
+              that interrupt reports both types of event.
+
+
+- ranges : Each range corresponds to a single chipselect, and covers
+           the entire access window as configured.
+
+Child device nodes describe the devices connected to IFC such as NOR (e.g.
+cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices
+like FPGAs, CPLDs, etc.
+
+Example:
+
+	ifc@ffe1e000 {
+		compatible = "fsl,ifc", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0x0 0xffe1e000 0 0x2000>;
+		interrupts = <16 2 19 2>;
+
+		/* NOR, NAND Flashes and CPLD on board */
+		ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+			  0x1 0x0 0x0 0xffa00000 0x00010000
+			  0x3 0x0 0x0 0xffb00000 0x00020000>;
+
+		flash@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x2000000>;
+			bank-width = <2>;
+			device-width = <1>;
+
+			partition@0 {
+				/* 32MB for user data */
+				reg = <0x0 0x02000000>;
+				label = "NOR Data";
+			};
+		};
+
+		flash@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x1 0x0 0x10000>;
+
+			partition@0 {
+				/* This location must not be altered  */
+				/* 1MB for u-boot Bootloader Image */
+				reg = <0x0 0x00100000>;
+				label = "NAND U-Boot Image";
+				read-only;
+			};
+		};
+
+		cpld@3,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p1010rdb-cpld";
+			reg = <0x3 0x0 0x000001f>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
new file mode 100644
index 000000000000..9592717f483f
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
@@ -0,0 +1,210 @@
+* Device tree bindings for Texas instruments AEMIF controller
+
+The Async External Memory Interface (EMIF16/AEMIF) controller is intended to
+provide a glue-less interface to a variety of asynchronous memory devices like
+ASRA M, NOR and NAND memory. A total of 256M bytes of any of these memories
+can be accessed at any given time via four chip selects with 64M byte access
+per chip select. Synchronous memories such as DDR1 SD RAM, SDR SDRAM
+and Mobile SDR are not supported.
+
+Documentation:
+Davinci DM646x - http://www.ti.com/lit/ug/sprueq7c/sprueq7c.pdf
+OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf
+Kestone - http://www.ti.com/lit/ug/sprugz3a/sprugz3a.pdf
+
+Required properties:
+
+- compatible:		"ti,davinci-aemif"
+			"ti,keystone-aemif"
+			"ti,da850-aemif"
+
+- reg:			contains offset/length value for AEMIF control registers
+			space.
+
+- #address-cells:	Must be 2. The partition number has to be encoded in the
+			first address cell and it may accept values 0..N-1
+			(N - total number of partitions). It's recommended to
+			assign N-1 number for the control partition. The second
+			cell is the offset into the partition.
+
+- #size-cells:		Must be set to 1.
+
+- ranges:		Contains memory regions. There are two types of
+			ranges/partitions:
+			- CS-specific partition/range. If continuous, must be
+			set up to reflect the memory layout for 4 chipselects,
+			if not then additional range/partition can be added and
+			child device can select the proper one.
+			- control partition which is common for all CS
+			interfaces.
+
+- clocks:		the clock feeding the controller clock. Required only
+			if clock tree data present in device tree.
+			See clock-bindings.txt
+
+- clock-names:		clock name. It has to be "aemif". Required only if clock
+			tree data present in device tree, in another case don't
+			use it.
+			See clock-bindings.txt
+
+- clock-ranges:		Empty property indicating that child nodes can inherit
+			named clocks. Required only if clock tree data present
+			in device tree.
+			See clock-bindings.txt
+
+
+Child chip-select (cs) nodes contain the memory devices nodes connected to
+such as NOR (e.g. cfi-flash) and NAND (ti,davinci-nand, see davinci-nand.txt).
+There might be board specific devices like FPGAs.
+
+Required child cs node properties:
+
+- #address-cells:	Must be 2.
+
+- #size-cells:		Must be 1.
+
+- ranges:		Empty property indicating that child nodes can inherit
+			memory layout.
+
+- clock-ranges:		Empty property indicating that child nodes can inherit
+			named clocks. Required only if clock tree data present
+			in device tree.
+
+- ti,cs-chipselect:	number of chipselect. Indicates on the aemif driver
+			which chipselect is used for accessing the memory. For
+			compatibles "ti,davinci-aemif" and "ti,keystone-aemif"
+			it can be in range [0-3]. For compatible
+			"ti,da850-aemif" range is [2-5].
+
+Optional child cs node properties:
+
+- ti,cs-bus-width:		width of the asynchronous device's data bus
+				8 or 16 if not preset 8
+
+- ti,cs-select-strobe-mode:	enable/disable select strobe mode
+				In select strobe mode chip select behaves as
+				the strobe and is active only during the strobe
+				period. If present then enable.
+
+- ti,cs-extended-wait-mode:	enable/disable extended wait mode
+				if set, the controller monitors the EMIFWAIT pin
+				mapped to that chip select to determine if the
+				device wants to extend the strobe period. If
+				present then enable.
+
+- ti,cs-min-turnaround-ns:	minimum turn around time, ns
+				Time between the end of one asynchronous memory
+				access and the start of another asynchronous
+				memory access. This delay is not incurred
+				between a read followed by read or a write
+				followed by a write to same chip select.
+
+- ti,cs-read-setup-ns:		read setup width, ns
+				Time between the beginning of a memory cycle
+				and the activation of read strobe.
+				Minimum value is 1 (0 treated as 1).
+
+- ti,cs-read-strobe-ns:		read strobe width, ns
+				Time between the activation and deactivation of
+				the read strobe.
+				Minimum value is 1 (0 treated as 1).
+
+- ti,cs-read-hold-ns:		read hold width, ns
+				Time between the deactivation of the read
+				strobe and the end of the cycle (which may be
+				either an address change or the deactivation of
+				the chip select signal.
+				Minimum value is 1 (0 treated as 1).
+
+- ti,cs-write-setup-ns:		write setup width, ns
+				Time between the beginning of a memory cycle
+				and the activation of write strobe.
+				Minimum value is 1 (0 treated as 1).
+
+- ti,cs-write-strobe-ns:	write strobe width, ns
+				Time between the activation and deactivation of
+				the write strobe.
+				Minimum value is 1 (0 treated as 1).
+
+- ti,cs-write-hold-ns:		write hold width, ns
+				Time between the deactivation of the write
+				strobe and the end of the cycle (which may be
+				either an address change or the deactivation of
+				the chip select signal.
+				Minimum value is 1 (0 treated as 1).
+
+If any of the above parameters are absent, current parameter value will be taken
+from the corresponding HW reg.
+
+Example for aemif, davinci nand and nor flash chip select shown below.
+
+memory-controller@21000A00 {
+	compatible = "ti,davinci-aemif";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	clocks = <&clkaemif 0>;
+	clock-names = "aemif";
+	clock-ranges;
+	reg = <0x21000A00 0x00000100>;
+	ranges = <0 0 0x70000000 0x10000000
+		  1 0 0x21000A00 0x00000100>;
+		  /*
+		   * Partition0: CS-specific memory range which is
+		   * implemented as continuous physical memory region
+		   * Partition1: control memory range
+		   */
+
+	nand:cs2 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <2>;
+		/* all timings in nanoseconds */
+		ti,cs-min-turnaround-ns = <0>;
+		ti,cs-read-hold-ns = <7>;
+		ti,cs-read-strobe-ns = <42>;
+		ti,cs-read-setup-ns = <14>;
+		ti,cs-write-hold-ns = <7>;
+		ti,cs-write-strobe-ns = <42>;
+		ti,cs-write-setup-ns = <14>;
+
+		nand@0,0x8000000 {
+			compatible = "ti,davinci-nand";
+			reg = <0 0x8000000 0x4000000
+			       1 0x0000000 0x0000100>;
+			/*
+			 * Partition0, offset 0x8000000, size 0x4000000
+			 * Partition1, offset 0x0000000, size 0x0000100
+			 */
+
+			.. see davinci-nand.txt
+		};
+	};
+
+	nor:cs0 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <0>;
+		/* all timings in nanoseconds */
+		ti,cs-min-turnaround-ns = <0>;
+		ti,cs-read-hold-ns = <8>;
+		ti,cs-read-strobe-ns = <40>;
+		ti,cs-read-setup-ns = <14>;
+		ti,cs-write-hold-ns = <7>;
+		ti,cs-write-strobe-ns = <40>;
+		ti,cs-write-setup-ns = <14>;
+		ti,cs-bus-width = <16>;
+
+		flash@0,0x0000000 {
+			compatible = "cfi-flash";
+			reg = <0 0x0000000 0x4000000>;
+
+			...
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
index abd9e3cb2db7..1413f39912d3 100644
--- a/Documentation/devicetree/bindings/mfd/mc13xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
@@ -10,9 +10,44 @@ Optional properties:
 - fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used
 
 Sub-nodes:
+- leds : Contain the led nodes and initial register values in property
+  "led-control". Number of register depends of used IC, for MC13783 is 6,
+  for MC13892 is 4, for MC34708 is 1. See datasheet for bits definitions of
+  these registers.
+  - #address-cells: Must be 1.
+  - #size-cells: Must be 0.
+  Each led node should contain "reg", which used as LED ID (described below).
+  Optional properties "label" and "linux,default-trigger" is described in
+  Documentation/devicetree/bindings/leds/common.txt.
 - regulators : Contain the regulator nodes. The regulators are bound using
   their names as listed below with their registers and bits for enabling.
 
+MC13783 LED IDs:
+    0  : Main display
+    1  : AUX display
+    2  : Keypad
+    3  : Red 1
+    4  : Green 1
+    5  : Blue 1
+    6  : Red 2
+    7  : Green 2
+    8  : Blue 2
+    9  : Red 3
+    10 : Green 3
+    11 : Blue 3
+
+MC13892 LED IDs:
+    0  : Main display
+    1  : AUX display
+    2  : Keypad
+    3  : Red
+    4  : Green
+    5  : Blue
+
+MC34708 LED IDs:
+    0  : Charger Red
+    1  : Charger Green
+
 MC13783 regulators:
     sw1a      : regulator SW1A      (register 24, bit 0)
     sw1b      : regulator SW1B      (register 25, bit 0)
@@ -89,6 +124,18 @@ ecspi@70010000 { /* ECSPI1 */
 		interrupt-parent = <&gpio0>;
 		interrupts = <8>;
 
+		leds {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			led-control = <0x000 0x000 0x0e0 0x000>;
+
+			sysled {
+				reg = <3>;
+				label = "system:red:live";
+				linux,default-trigger = "heartbeat";
+			};
+		};
+
 		regulators {
 			sw1_reg: mc13892__sw1 {
 				regulator-min-microvolt = <600000>;
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
index 68ba37295565..fabdf64a5737 100644
--- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
@@ -1,12 +1,12 @@
 Allwinner sunxi-sid
 
 Required properties:
-- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid".
+- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
 - reg: Should contain registers location and length
 
 Example for sun4i:
 	sid@01c23800 {
-		compatible = "allwinner,sun4i-sid";
+		compatible = "allwinner,sun4i-a10-sid";
 		reg = <0x01c23800 0x10>
 	};
 
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
index 60960b2755f4..efc98ea1f23d 100644
--- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -17,6 +17,14 @@ Required properties for devices compatible with "atmel,at91sam9g45-ssc":
   See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
 - dma-names: Must be "tx", "rx".
 
+Optional properties:
+  - atmel,clk-from-rk-pin: bool property.
+     - When SSC works in slave mode, according to the hardware design, the
+       clock can get from TK pin, and also can get from RK pin. So, add
+       this parameter to choose where the clock from.
+     - By default the clock is from TK pin, if the clock from RK pin, this
+       property is needed.
+
 Examples:
 - PDC transfer:
 ssc0: ssc@fffbc000 {
diff --git a/Documentation/devicetree/bindings/misc/sram.txt b/Documentation/devicetree/bindings/misc/sram.txt
index 4d0a00e453a8..36cbe5aea990 100644
--- a/Documentation/devicetree/bindings/misc/sram.txt
+++ b/Documentation/devicetree/bindings/misc/sram.txt
@@ -8,9 +8,44 @@ Required properties:
 
 - reg : SRAM iomem address range
 
+Reserving sram areas:
+---------------------
+
+Each child of the sram node specifies a region of reserved memory. Each
+child node should use a 'reg' property to specify a specific range of
+reserved memory.
+
+Following the generic-names recommended practice, node names should
+reflect the purpose of the node. Unit address (@<address>) should be
+appended to the name.
+
+Required properties in the sram node:
+
+- #address-cells, #size-cells : should use the same values as the root node
+- ranges : standard definition, should translate from local addresses
+           within the sram to bus addresses
+
+Required properties in the area nodes:
+
+- reg : iomem address range, relative to the SRAM range
+
+Optional properties in the area nodes:
+
+- compatible : standard definition, should contain a vendor specific string
+               in the form <vendor>,[<device>-]<usage>
+
 Example:
 
 sram: sram@5c000000 {
 	compatible = "mmio-sram";
 	reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
+
+	#adress-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0x5c000000 0x40000>;
+
+	smp-sram@100 {
+		compatible = "socvendor,smp-sram";
+		reg = <0x100 0x50>;
+	};
 };
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 458b57f199af..9dce540771fb 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -26,9 +26,18 @@ Optional properties:
   this system, even if the controller claims it is.
 - cap-sd-highspeed: SD high-speed timing is supported
 - cap-mmc-highspeed: MMC high-speed timing is supported
+- sd-uhs-sdr12: SD UHS SDR12 speed is supported
+- sd-uhs-sdr25: SD UHS SDR25 speed is supported
+- sd-uhs-sdr50: SD UHS SDR50 speed is supported
+- sd-uhs-sdr104: SD UHS SDR104 speed is supported
+- sd-uhs-ddr50: SD UHS DDR50 speed is supported
 - cap-power-off-card: powering off the card is safe
 - cap-sdio-irq: enable SDIO IRQ signalling on this interface
 - full-pwr-cycle: full power cycle of the card is supported
+- mmc-highspeed-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
+- mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
+- mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
+- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
 
 *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
 polarity properties, we have to fix the meaning of the "normal" and "inverted"
diff --git a/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt
new file mode 100644
index 000000000000..4897bea7e3f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt
@@ -0,0 +1,23 @@
+* Altera SOCFPGA specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Altera SOCFPGA specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+	- "altr,socfpga-dw-mshc": for Altera's SOCFPGA platform
+
+Example:
+
+	mmc: dwmmc0@ff704000 {
+		compatible = "altr,socfpga-dw-mshc";
+		reg = <0xff704000 0x1000>;
+		interrupts = <0 129 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
index 863d5b8155c7..10640b17c866 100644
--- a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
+++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
@@ -5,13 +5,9 @@ Required properties:
               "allwinner,sun4i-emac")
 - reg: address and length of the register set for the device.
 - interrupts: interrupt for the device
-- phy: A phandle to a phy node defining the PHY address (as the reg
-  property, a single integer).
+- phy: see ethernet.txt file in the same directory.
 - clocks: A phandle to the reference clock for this device
 
-Optional properties:
-- (local-)mac-address: mac address to be used by this driver
-
 Example:
 
 emac: ethernet@01c0b000 {
diff --git a/Documentation/devicetree/bindings/net/arc_emac.txt b/Documentation/devicetree/bindings/net/arc_emac.txt
index bcbc3f009158..7fbb027218a1 100644
--- a/Documentation/devicetree/bindings/net/arc_emac.txt
+++ b/Documentation/devicetree/bindings/net/arc_emac.txt
@@ -6,19 +6,12 @@ Required properties:
 - interrupts: Should contain the EMAC interrupts
 - clock-frequency: CPU frequency. It is needed to calculate and set polling
 period of EMAC.
-- max-speed: Maximum supported data-rate in Mbit/s. In some HW configurations
-bandwidth of external memory controller might be a limiting factor. That's why
-it's required to specify which data-rate is supported on current SoC or FPGA.
-For example if only 10 Mbit/s is supported (10BASE-T) set "10". If 100 Mbit/s is
-supported (100BASE-TX) set "100".
-- phy: PHY device attached to the EMAC via MDIO bus
+- max-speed: see ethernet.txt file in the same directory.
+- phy: see ethernet.txt file in the same directory.
 
 Child nodes of the driver are the individual PHY devices connected to the
 MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus.
 
-Optional properties:
-- mac-address: 6 bytes, mac address
-
 Examples:
 
 	ethernet@c0fc2000 {
diff --git a/Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt b/Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
new file mode 100644
index 000000000000..f2febb94550e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
@@ -0,0 +1,121 @@
+* Broadcom BCM7xxx Ethernet Controller (GENET)
+
+Required properties:
+- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
+  "brcm,genet-v3", "brcm,genet-v4".
+- reg: address and length of the register set for the device
+- interrupts: must be two cells, the first cell is the general purpose
+  interrupt line, while the second cell is the interrupt for the ring
+  RX and TX queues operating in ring mode
+- phy-mode: see ethernet.txt file in the same directory
+- #address-cells: should be 1
+- #size-cells: should be 1
+
+Optional properties:
+- clocks: When provided, must be two phandles to the functional clocks nodes
+  of the GENET block. The first phandle is the main GENET clock used during
+  normal operation, while the second phandle is the Wake-on-LAN clock.
+- clock-names: When provided, names of the functional clock phandles, first
+  name should be "enet" and second should be "enet-wol".
+
+- phy-handle: See ethernet.txt file in the same directory; used to describe
+  configurations where a PHY (internal or external) is used.
+
+- fixed-link: When the GENET interface is connected to a MoCA hardware block or
+  when operating in a RGMII to RGMII type of connection, or when the MDIO bus is
+  voluntarily disabled, this property should be used to describe the "fixed link".
+  See Documentation/devicetree/bindings/net/fsl-tsec-phy.txt for information on
+  the property specifics
+
+Required child nodes:
+
+- mdio bus node: this node should always be present regarless of the PHY
+  configuration of the GENET instance
+
+MDIO bus node required properties:
+
+- compatible: should contain one of "brcm,genet-mdio-v1", "brcm,genet-mdio-v2"
+  "brcm,genet-mdio-v3", "brcm,genet-mdio-v4", the version has to match the
+  parent node compatible property (e.g: brcm,genet-v4 pairs with
+  brcm,genet-mdio-v4)
+- reg: address and length relative to the parent node base register address
+- #address-cells: address cell for MDIO bus addressing, should be 1
+- #size-cells: size of the cells for MDIO bus addressing, should be 0
+
+Ethernet PHY node properties:
+
+See Documentation/devicetree/bindings/net/phy.txt for the list of required and
+optional properties.
+
+Internal Gigabit PHY example:
+
+ethernet@f0b60000 {
+	phy-mode = "internal";
+	phy-handle = <&phy1>;
+	mac-address = [ 00 10 18 36 23 1a ];
+	compatible = "brcm,genet-v4";
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	reg = <0xf0b60000 0xfc4c>;
+	interrupts = <0x0 0x14 0x0>, <0x0 0x15 0x0>;
+
+	mdio@e14 {
+		compatible = "brcm,genet-mdio-v4";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		reg = <0xe14 0x8>;
+
+		phy1: ethernet-phy@1 {
+			max-speed = <1000>;
+			reg = <0x1>;
+			compatible = "brcm,28nm-gphy", "ethernet-phy-ieee802.3-c22";
+		};
+	};
+};
+
+MoCA interface / MAC to MAC example:
+
+ethernet@f0b80000 {
+	phy-mode = "moca";
+	fixed-link = <1 0 1000 0 0>;
+	mac-address = [ 00 10 18 36 24 1a ];
+	compatible = "brcm,genet-v4";
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	reg = <0xf0b80000 0xfc4c>;
+	interrupts = <0x0 0x16 0x0>, <0x0 0x17 0x0>;
+
+	mdio@e14 {
+		compatible = "brcm,genet-mdio-v4";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		reg = <0xe14 0x8>;
+	};
+};
+
+
+External MDIO-connected Gigabit PHY/switch:
+
+ethernet@f0ba0000 {
+	phy-mode = "rgmii";
+	phy-handle = <&phy0>;
+	mac-address = [ 00 10 18 36 26 1a ];
+	compatible = "brcm,genet-v4";
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	reg = <0xf0ba0000 0xfc4c>;
+	interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>;
+
+	mdio@0e14 {
+		compatible = "brcm,genet-mdio-v4";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		reg = <0xe14 0x8>;
+
+		phy0: ethernet-phy@0 {
+			max-speed = <1000>;
+			reg = <0x0>;
+			compatible = "brcm,bcm53125", "ethernet-phy-ieee802.3-c22";
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/net/can/sja1000.txt b/Documentation/devicetree/bindings/net/can/sja1000.txt
index f2105a47ec87..b4a6d53fb01a 100644
--- a/Documentation/devicetree/bindings/net/can/sja1000.txt
+++ b/Documentation/devicetree/bindings/net/can/sja1000.txt
@@ -12,6 +12,10 @@ Required properties:
 
 Optional properties:
 
+- reg-io-width : Specify the size (in bytes) of the IO accesses that
+	should be performed on the device.  Valid value is 1, 2 or 4.
+	Default to 1 (8 bits).
+
 - nxp,external-clock-frequency : Frequency of the external oscillator
 	clock in Hz. Note that the internal clock frequency used by the
 	SJA1000 is half of that value. If not specified, a default value
diff --git a/Documentation/devicetree/bindings/net/cavium-mix.txt b/Documentation/devicetree/bindings/net/cavium-mix.txt
index 5da628db68bf..8d7c3096390f 100644
--- a/Documentation/devicetree/bindings/net/cavium-mix.txt
+++ b/Documentation/devicetree/bindings/net/cavium-mix.txt
@@ -18,12 +18,7 @@ Properties:
 - interrupts: Two interrupt specifiers.  The first is the MIX
   interrupt routing and the second the routing for the AGL interrupts.
 
-- mac-address: Optional, the MAC address to assign to the device.
-
-- local-mac-address: Optional, the MAC address to assign to the device
-  if mac-address is not specified.
-
-- phy-handle: Optional, a phandle for the PHY device connected to this device.
+- phy-handle: Optional, see ethernet.txt file in the same directory.
 
 Example:
 	ethernet@1070000100800 {
diff --git a/Documentation/devicetree/bindings/net/cavium-pip.txt b/Documentation/devicetree/bindings/net/cavium-pip.txt
index d4c53ba04b3b..7dbd158810d2 100644
--- a/Documentation/devicetree/bindings/net/cavium-pip.txt
+++ b/Documentation/devicetree/bindings/net/cavium-pip.txt
@@ -35,12 +35,7 @@ Properties for PIP port which is a child the PIP interface:
 
 - reg: The port number within the interface group.
 
-- mac-address: Optional, the MAC address to assign to the device.
-
-- local-mac-address: Optional, the MAC address to assign to the device
-  if mac-address is not specified.
-
-- phy-handle: Optional, a phandle for the PHY device connected to this device.
+- phy-handle: Optional, see ethernet.txt file in the same directory.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/net/cdns-emac.txt b/Documentation/devicetree/bindings/net/cdns-emac.txt
index 09055c2495f0..abd67c13d344 100644
--- a/Documentation/devicetree/bindings/net/cdns-emac.txt
+++ b/Documentation/devicetree/bindings/net/cdns-emac.txt
@@ -6,11 +6,7 @@ Required properties:
   or the generic form: "cdns,emac".
 - reg: Address and length of the register set for the device
 - interrupts: Should contain macb interrupt
-- phy-mode: String, operation mode of the PHY interface.
-  Supported values are: "mii", "rmii".
-
-Optional properties:
-- local-mac-address: 6 bytes, mac address
+- phy-mode: see ethernet.txt file in the same directory.
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 05d660e4ac64..ae2b8b7f9c38 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -28,9 +28,8 @@ Optional properties:
 Slave Properties:
 Required properties:
 - phy_id		: Specifies slave phy id
-- phy-mode		: The interface between the SoC and the PHY (a string
-			  that of_get_phy_mode() can understand)
-- mac-address		: Specifies slave MAC address
+- phy-mode		: See ethernet.txt file in the same directory
+- mac-address		: See ethernet.txt file in the same directory
 
 Optional properties:
 - dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
diff --git a/Documentation/devicetree/bindings/net/davicom-dm9000.txt b/Documentation/devicetree/bindings/net/davicom-dm9000.txt
index 2d39c990e641..28767ed7c1bd 100644
--- a/Documentation/devicetree/bindings/net/davicom-dm9000.txt
+++ b/Documentation/devicetree/bindings/net/davicom-dm9000.txt
@@ -9,8 +9,6 @@ Required properties:
 - interrupts : interrupt specifier specific to interrupt controller
 
 Optional properties:
-- local-mac-address : A bytestring of 6 bytes specifying Ethernet MAC address
-    to use (from firmware or bootloader)
 - davicom,no-eeprom : Configuration EEPROM is not available
 - davicom,ext-phy : Use external PHY
 
diff --git a/Documentation/devicetree/bindings/net/davinci_emac.txt b/Documentation/devicetree/bindings/net/davinci_emac.txt
index 6e356d15154a..032808843f90 100644
--- a/Documentation/devicetree/bindings/net/davinci_emac.txt
+++ b/Documentation/devicetree/bindings/net/davinci_emac.txt
@@ -17,9 +17,8 @@ Required properties:
 			  Miscellaneous Interrupt>
 
 Optional properties:
-- phy-handle: Contains a phandle to an Ethernet PHY.
+- phy-handle: See ethernet.txt file in the same directory.
               If absent, davinci_emac driver defaults to 100/FULL.
-- local-mac-address : 6 bytes, mac address
 - ti,davinci-rmii-en: 1 byte, 1 means use RMII
 - ti,davinci-no-bd-ram: boolean, does EMAC have BD RAM?
 
diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt
new file mode 100644
index 000000000000..9ecd43d8792c
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -0,0 +1,25 @@
+The following properties are common to the Ethernet controllers:
+
+- local-mac-address: array of 6 bytes, specifies the MAC address that was
+  assigned to the network device;
+- mac-address: array of 6 bytes, specifies the MAC address that was last used by
+  the boot program; should be used in cases where the MAC address assigned to
+  the device by the boot program is different from the "local-mac-address"
+  property;
+- max-speed: number, specifies maximum speed in Mbit/s supported by the device;
+- 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",
+  "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;
+- phy-handle: phandle, specifies a reference to a node representing a PHY
+  device; this property is described in ePAPR and so preferred;
+- phy: the same as "phy-handle" property, not recommended for new bindings.
+- phy-device: the same as "phy-handle" property, not recommended for new
+  bindings.
+
+Child nodes of the Ethernet controller are typically the individual PHY devices
+connected via the MDIO bus (sometimes the MDIO bus controller is separate).
+They are described in the phy.txt file in this same directory.
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 845ff848d895..6bc84adb10c0 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -4,12 +4,9 @@ Required properties:
 - compatible : Should be "fsl,<soc>-fec"
 - reg : Address and length of the register set for the device
 - interrupts : Should contain fec interrupt
-- phy-mode : String, operation mode of the PHY interface.
-  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
-  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+- phy-mode : See ethernet.txt file in the same directory
 
 Optional properties:
-- local-mac-address : 6 bytes, mac address
 - phy-reset-gpios : Should specify the gpio for phy reset
 - phy-reset-duration : Reset duration in milliseconds.  Should present
   only if property "phy-reset-gpios" is available.  Missing the property
diff --git a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
index d2ea4605d078..737cdef4f903 100644
--- a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
+++ b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
@@ -38,22 +38,17 @@ Properties:
   - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
   - compatible : Should be "gianfar"
   - reg : Offset and length of the register set for the device
-  - local-mac-address : List of bytes representing the ethernet address of
-    this controller
   - interrupts : For FEC devices, the first interrupt is the device's
     interrupt.  For TSEC and eTSEC devices, the first interrupt is
     transmit, the second is receive, and the third is error.
-  - phy-handle : The phandle for the PHY connected to this ethernet
-    controller.
+  - phy-handle : See ethernet.txt file in the same directory.
   - fixed-link : <a b c d e> where a is emulated phy id - choose any,
     but unique to the all specified fixed-links, b is duplex - 0 half,
     1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
     pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
-  - phy-connection-type : a string naming the controller/PHY interface type,
-    i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
-    "tbi", or "rtbi".  This property is only really needed if the connection
-    is of type "rgmii-id", as all other connection types are detected by
-    hardware.
+  - phy-connection-type : See ethernet.txt file in the same directory.
+    This property is only really needed if the connection is of type
+    "rgmii-id", as all other connection types are detected by hardware.
   - fsl,magic-packet : If present, indicates that the hardware supports
     waking up via magic packet.
   - bd-stash : If present, indicates that the hardware supports stashing
diff --git a/Documentation/devicetree/bindings/net/lpc-eth.txt b/Documentation/devicetree/bindings/net/lpc-eth.txt
index 585021acd178..b92e927808b6 100644
--- a/Documentation/devicetree/bindings/net/lpc-eth.txt
+++ b/Documentation/devicetree/bindings/net/lpc-eth.txt
@@ -6,10 +6,9 @@ Required properties:
 - interrupts: Should contain ethernet controller interrupt
 
 Optional properties:
-- phy-mode: String, operation mode of the PHY interface.
-  Supported values are: "mii", "rmii" (default)
+- phy-mode: See ethernet.txt file in the same directory. If the property is
+  absent, "rmii" is assumed.
 - use-iram: Use LPC32xx internal SRAM (IRAM) for DMA buffering
-- local-mac-address : 6 bytes, mac address
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt
index 70af2ec12b09..aaa696414f57 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -8,16 +8,12 @@ Required properties:
   the Cadence GEM, or the generic form: "cdns,gem".
 - reg: Address and length of the register set for the device
 - interrupts: Should contain macb interrupt
-- phy-mode: String, operation mode of the PHY interface.
-  Supported values are: "mii", "rmii", "gmii", "rgmii".
+- phy-mode: See ethernet.txt file in the same directory.
 - clock-names: Tuple listing input clock names.
 	Required elements: 'pclk', 'hclk'
 	Optional elements: 'tx_clk'
 - clocks: Phandles to input clocks.
 
-Optional properties:
-- local-mac-address: 6 bytes, mac address
-
 Examples:
 
 	macb0: ethernet@fffc4000 {
diff --git a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
index 859a6fa7569c..750d577e8083 100644
--- a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
+++ b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
@@ -4,10 +4,8 @@ Required properties:
 - compatible: should be "marvell,armada-370-neta".
 - reg: address and length of the register set for the device.
 - interrupts: interrupt for the device
-- phy: A phandle to a phy node defining the PHY address (as the reg
-  property, a single integer).
-- phy-mode: The interface between the SoC and the PHY (a string that
-  of_get_phy_mode() can understand)
+- phy: See ethernet.txt file in the same directory.
+- phy-mode: See ethernet.txt file in the same directory
 - clocks: a pointer to the reference clock for this device.
 
 Example:
diff --git a/Documentation/devicetree/bindings/net/marvell-orion-net.txt b/Documentation/devicetree/bindings/net/marvell-orion-net.txt
index c233b6114242..bce52b2ec55e 100644
--- a/Documentation/devicetree/bindings/net/marvell-orion-net.txt
+++ b/Documentation/devicetree/bindings/net/marvell-orion-net.txt
@@ -36,7 +36,7 @@ Required port properties:
       "marvell,kirkwood-eth-port".
  - reg: port number relative to ethernet controller, shall be 0, 1, or 2.
  - interrupts: port interrupt.
- - local-mac-address: 6 bytes MAC address.
+ - local-mac-address: See ethernet.txt file in the same directory.
 
 Optional port properties:
  - marvell,tx-queue-size: size of the transmit ring buffer.
@@ -48,7 +48,7 @@ Optional port properties:
 
 and
 
- - phy-handle: phandle reference to ethernet PHY.
+ - phy-handle: See ethernet.txt file in the same directory.
 
 or
 
diff --git a/Documentation/devicetree/bindings/net/micrel-ks8851.txt b/Documentation/devicetree/bindings/net/micrel-ks8851.txt
index 11ace3c3d805..8e20c04a1da1 100644
--- a/Documentation/devicetree/bindings/net/micrel-ks8851.txt
+++ b/Documentation/devicetree/bindings/net/micrel-ks8851.txt
@@ -4,6 +4,3 @@ Required properties:
 - compatible = "micrel,ks8851-ml" of parallel interface
 - reg : 2 physical address and size of registers for data and command
 - interrupts : interrupt connection
-
-Optional properties:
-- local-mac-address : Ethernet mac address to use
diff --git a/Documentation/devicetree/bindings/net/micrel.txt b/Documentation/devicetree/bindings/net/micrel.txt
new file mode 100644
index 000000000000..98a3e61f9ee8
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/micrel.txt
@@ -0,0 +1,18 @@
+Micrel PHY properties.
+
+These properties cover the base properties Micrel PHYs.
+
+Optional properties:
+
+ - micrel,led-mode : LED mode value to set for PHYs with configurable LEDs.
+
+              Configure the LED mode with single value. The list of PHYs and
+	      the bits that are currently supported:
+
+	      KSZ8001: register 0x1e, bits 15..14
+	      KSZ8041: register 0x1e, bits 15..14
+	      KSZ8021: register 0x1f, bits 5..4
+	      KSZ8031: register 0x1f, bits 5..4
+	      KSZ8051: register 0x1f, bits 5..4
+
+              See the respective PHY datasheet for the mode values.
diff --git a/Documentation/devicetree/bindings/net/opencores-ethoc.txt b/Documentation/devicetree/bindings/net/opencores-ethoc.txt
new file mode 100644
index 000000000000..2dc127c30d9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/opencores-ethoc.txt
@@ -0,0 +1,22 @@
+* OpenCores MAC 10/100 Mbps
+
+Required properties:
+- compatible: Should be "opencores,ethoc".
+- reg: two memory regions (address and length),
+  first region is for the device registers and descriptor rings,
+  second is for the device packet memory.
+- interrupts: interrupt for the device.
+
+Optional properties:
+- clocks: phandle to refer to the clk used as per
+  Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Examples:
+
+	enet0: ethoc@fd030000 {
+		compatible = "opencores,ethoc";
+		reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
+		interrupts = <1>;
+		local-mac-address = [00 50 c2 13 6f 00];
+		clocks = <&osc>;
+        };
diff --git a/Documentation/devicetree/bindings/net/sh_eth.txt b/Documentation/devicetree/bindings/net/sh_eth.txt
new file mode 100644
index 000000000000..e7106b50dbdc
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/sh_eth.txt
@@ -0,0 +1,55 @@
+* Renesas Electronics SH EtherMAC
+
+This file provides information on what the device node for the SH EtherMAC
+interface contains.
+
+Required properties:
+- compatible: "renesas,gether-r8a7740" if the device is a part of R8A7740 SoC.
+	      "renesas,ether-r8a7778"  if the device is a part of R8A7778 SoC.
+	      "renesas,ether-r8a7779"  if the device is a part of R8A7779 SoC.
+	      "renesas,ether-r8a7790"  if the device is a part of R8A7790 SoC.
+	      "renesas,ether-r8a7791"  if the device is a part of R8A7791 SoC.
+	      "renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
+- reg: offset and length of (1) the E-DMAC/feLic register block (required),
+       (2) the TSU register block (optional).
+- interrupts: interrupt specifier for the sole interrupt.
+- phy-mode: see ethernet.txt file in the same directory.
+- phy-handle: see ethernet.txt file in the same directory.
+- #address-cells: number of address cells for the MDIO bus, must be equal to 1.
+- #size-cells: number of size cells on the MDIO bus, must be equal to 0.
+- clocks: clock phandle and specifier pair.
+- pinctrl-0: phandle, referring to a default pin configuration node.
+
+Optional properties:
+- interrupt-parent: the phandle for the interrupt controller that services
+		    interrupts for this device.
+- pinctrl-names: pin configuration state name ("default").
+- renesas,no-ether-link: boolean, specify when a board does not provide a proper
+			 Ether LINK signal.
+- renesas,ether-link-active-low: boolean, specify when the Ether LINK signal is
+				 active-low instead of normal active-high.
+
+Example (Lager board):
+
+	ethernet@ee700000 {
+		compatible = "renesas,ether-r8a7790";
+		reg = <0 0xee700000 0 0x400>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
+		phy-mode = "rmii";
+		phy-handle = <&phy1>;
+		pinctrl-0 = <&ether_pins>;
+		pinctrl-names = "default";
+		renesas,ether-link-active-low;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		phy1: ethernet-phy@1 {
+			reg = <1>;
+			interrupt-parent = <&irqc0>;
+			interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+			pinctrl-0 = <&phy1_pins>;
+			pinctrl-names = "default";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
index 5a41a8658daa..0f8487b88822 100644
--- a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
+++ b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
@@ -6,8 +6,7 @@ Required properties:
 - interrupts : interrupt connection
 
 Optional properties:
-- phy-device : phandle to Ethernet phy
-- local-mac-address : Ethernet mac address to use
+- phy-device : see ethernet.txt file in the same directory
 - reg-io-width : Mask of sizes (in bytes) of the IO accesses that
   are supported on the device.  Valid value for SMSC LAN91c111 are
   1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
diff --git a/Documentation/devicetree/bindings/net/smsc911x.txt b/Documentation/devicetree/bindings/net/smsc911x.txt
index adb5b5744ecd..3fed3c124411 100644
--- a/Documentation/devicetree/bindings/net/smsc911x.txt
+++ b/Documentation/devicetree/bindings/net/smsc911x.txt
@@ -6,9 +6,7 @@ Required properties:
 - interrupts : Should contain SMSC LAN interrupt line
 - interrupt-parent : Should be the phandle for the interrupt controller
   that services interrupts for this device
-- phy-mode : String, operation mode of the PHY interface.
-  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
-  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+- phy-mode : See ethernet.txt file in the same directory
 
 Optional properties:
 - reg-shift : Specify the quantity to shift the register offsets by
@@ -23,7 +21,6 @@ Optional properties:
   external PHY
 - smsc,save-mac-address : Indicates that mac address needs to be saved
   before resetting the controller
-- local-mac-address : 6 bytes, mac address
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index 9d92d42140f2..5748351fb9df 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -10,8 +10,7 @@ Required properties:
 - interrupt-names: Should contain the interrupt names "macirq"
   "eth_wake_irq" if this interrupt is supported in the "interrupts"
   property
-- phy-mode: String, operation mode of the PHY interface.
-  Supported values are: "mii", "rmii", "gmii", "rgmii".
+- phy-mode: See ethernet.txt file in the same directory.
 - snps,reset-gpio 	gpio number for phy reset.
 - snps,reset-active-low boolean flag to indicate if phy reset is active low.
 - snps,reset-delays-us  is triplet of delays
@@ -28,12 +27,10 @@ Required properties:
 				ignored if force_thresh_dma_mode is set.
 
 Optional properties:
-- mac-address: 6 bytes, mac address
 - resets: Should contain a phandle to the STMMAC reset signal, if any
 - reset-names: Should contain the reset signal name "stmmaceth", if a
 	reset phandle is given
-- max-frame-size:	Maximum Transfer Unit (IEEE defined MTU), rather
-			than the maximum frame size.
+- max-frame-size: See ethernet.txt file in the same directory
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/panel/lg,lp129qe.txt b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt
new file mode 100644
index 000000000000..9f262e0c5a2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt
@@ -0,0 +1,7 @@
+LG 12.9" (2560x1700 pixels) TFT LCD panel
+
+Required properties:
+- compatible: should be "lg,lp129qe"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
index 01ef408e205f..adda2a8d1d52 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
@@ -5,6 +5,7 @@ part and usage.
 
 Required properties:
 - compatible: "marvell,88f6710-pinctrl"
+- reg: register specifier of MPP registers
 
 Available mpp pins/groups and functions:
 Note: brackets (x) are not part of the mpp name for marvell,function and given
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-375-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-375-pinctrl.txt
new file mode 100644
index 000000000000..7de0cda4a379
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-375-pinctrl.txt
@@ -0,0 +1,82 @@
+* Marvell Armada 375 SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6720-pinctrl"
+- reg: register specifier of MPP registers
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, dev(ad2), spi0(cs1), spi1(cs1)
+mpp1          1        gpio, dev(ad3), spi0(mosi), spi1(mosi)
+mpp2          2        gpio, dev(ad4), ptp(eventreq), led(c0), audio(sdi)
+mpp3          3        gpio, dev(ad5), ptp(triggen), led(p3), audio(mclk)
+mpp4          4        gpio, dev(ad6), spi0(miso), spi1(miso)
+mpp5          5        gpio, dev(ad7), spi0(cs2), spi1(cs2)
+mpp6          6        gpio, dev(ad0), led(p1), audio(rclk)
+mpp7          7        gpio, dev(ad1), ptp(clk), led(p2), audio(extclk)
+mpp8          8        gpio, dev (bootcs), spi0(cs0), spi1(cs0)
+mpp9          9        gpio, nf(wen), spi0(sck), spi1(sck)
+mpp10        10        gpio, nf(ren), dram(vttctrl), led(c1)
+mpp11        11        gpio, dev(a0), led(c2), audio(sdo)
+mpp12        12        gpio, dev(a1), audio(bclk)
+mpp13        13        gpio, dev(readyn), pcie0(rstoutn), pcie1(rstoutn)
+mpp14        14        gpio, i2c0(sda), uart1(txd)
+mpp15        15        gpio, i2c0(sck), uart1(rxd)
+mpp16        16        gpio, uart0(txd)
+mpp17        17        gpio, uart0(rxd)
+mpp18        18        gpio, tdm(intn)
+mpp19        19        gpio, tdm(rstn)
+mpp20        20        gpio, tdm(pclk)
+mpp21        21        gpio, tdm(fsync)
+mpp22        22        gpio, tdm(drx)
+mpp23        23        gpio, tdm(dtx)
+mpp24        24        gpio, led(p0), ge1(rxd0), sd(cmd), uart0(rts)
+mpp25        25        gpio, led(p2), ge1(rxd1), sd(d0), uart0(cts)
+mpp26        26        gpio, pcie0(clkreq), ge1(rxd2), sd(d2), uart1(rts)
+mpp27        27        gpio, pcie1(clkreq), ge1(rxd3), sd(d1), uart1(cts)
+mpp28        28        gpio, led(p3), ge1(txctl), sd(clk)
+mpp29        29        gpio, pcie1(clkreq), ge1(rxclk), sd(d3)
+mpp30        30        gpio, ge1(txd0), spi1(cs0)
+mpp31        31        gpio, ge1(txd1), spi1(mosi)
+mpp32        32        gpio, ge1(txd2), spi1(sck), ptp(triggen)
+mpp33        33        gpio, ge1(txd3), spi1(miso)
+mpp34        34        gpio, ge1(txclkout), spi1(sck)
+mpp35        35        gpio, ge1(rxctl), spi1(cs1), spi0(cs2)
+mpp36        36        gpio, pcie0(clkreq)
+mpp37        37        gpio, pcie0(clkreq), tdm(intn), ge(mdc)
+mpp38        38        gpio, pcie1(clkreq), ge(mdio)
+mpp39        39        gpio, ref(clkout)
+mpp40        40        gpio, uart1(txd)
+mpp41        41        gpio, uart1(rxd)
+mpp42        42        gpio, spi1(cs2), led(c0)
+mpp43        43        gpio, sata0(prsnt), dram(vttctrl)
+mpp44        44        gpio, sata0(prsnt)
+mpp45        45        gpio, spi0(cs2), pcie0(rstoutn)
+mpp46        46        gpio, led(p0), ge0(txd0), ge1(txd0)
+mpp47        47        gpio, led(p1), ge0(txd1), ge1(txd1)
+mpp48        48        gpio, led(p2), ge0(txd2), ge1(txd2)
+mpp49        49        gpio, led(p3), ge0(txd3), ge1(txd3)
+mpp50        50        gpio, led(c0), ge0(rxd0), ge1(rxd0)
+mpp51        51        gpio, led(c1), ge0(rxd1), ge1(rxd1)
+mpp52        52        gpio, led(c2), ge0(rxd2), ge1(rxd2)
+mpp53        53        gpio, pcie1(rstoutn), ge0(rxd3), ge1(rxd3)
+mpp54        54        gpio, pcie0(rstoutn), ge0(rxctl), ge1(rxctl)
+mpp55        55        gpio, ge0(rxclk), ge1(rxclk)
+mpp56        56        gpio, ge0(txclkout), ge1(txclkout)
+mpp57        57        gpio, ge0(txctl), ge1(txctl)
+mpp58        58        gpio, led(c0)
+mpp59        59        gpio, led(c1)
+mpp60        60        gpio, uart1(txd), led(c2)
+mpp61        61        gpio, i2c1(sda), uart1(rxd), spi1(cs2), led(p0)
+mpp62        62        gpio, i2c1(sck), led(p1)
+mpp63        63        gpio, ptp(triggen), led(p2)
+mpp64        64        gpio, dram(vttctrl), led(p3)
+mpp65        65        gpio, sata1(prsnt)
+mpp66        66        gpio, ptp(eventreq), spi1(cs3)
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-38x-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-38x-pinctrl.txt
new file mode 100644
index 000000000000..b17c96849fc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-38x-pinctrl.txt
@@ -0,0 +1,80 @@
+* Marvell Armada 380/385 SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6810-pinctrl", "marvell,88f6820-pinctrl" or
+  "marvell,88f6828-pinctrl" depending on the specific variant of the
+  SoC being used.
+- reg: register specifier of MPP registers
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, ua0(rxd)
+mpp1          1        gpio, ua0(txd)
+mpp2          2        gpio, i2c0(sck)
+mpp3          3        gpio, i2c0(sda)
+mpp4          4        gpio, ge(mdc), ua1(txd), ua0(rts)
+mpp5          5        gpio, ge(mdio), ua1(rxd), ua0(cts)
+mpp6          6        gpio, ge0(txclkout), ge0(crs), dev(cs3)
+mpp7          7        gpio, ge0(txd0), dev(ad9)
+mpp8          8        gpio, ge0(txd1), dev(ad10)
+mpp9          9        gpio, ge0(txd2), dev(ad11)
+mpp10         10       gpio, ge0(txd3), dev(ad12)
+mpp11         11       gpio, ge0(txctl), dev(ad13)
+mpp12         12       gpio, ge0(rxd0), pcie0(rstout), pcie1(rstout) [1], spi0(cs1), dev(ad14)
+mpp13         13       gpio, ge0(rxd1), pcie0(clkreq), pcie1(clkreq) [1], spi0(cs2), dev(ad15)
+mpp14         14       gpio, ge0(rxd2), ptp(clk), m(vtt_ctrl), spi0(cs3), dev(wen1)
+mpp15         15       gpio, ge0(rxd3), ge(mdc slave), pcie0(rstout), spi0(mosi), pcie1(rstout) [1]
+mpp16         16       gpio, ge0(rxctl), ge(mdio slave), m(decc_err), spi0(miso), pcie0(clkreq)
+mpp17         17       gpio, ge0(rxclk), ptp(clk), ua1(rxd), spi0(sck), sata1(prsnt)
+mpp18         18       gpio, ge0(rxerr), ptp(trig_gen), ua1(txd), spi0(cs0), pcie1(rstout) [1]
+mpp19         19       gpio, ge0(col), ptp(event_req), pcie0(clkreq), sata1(prsnt), ua0(cts)
+mpp20         20       gpio, ge0(txclk), ptp(clk), pcie1(rstout) [1], sata0(prsnt), ua0(rts)
+mpp21         21       gpio, spi0(cs1), ge1(rxd0), sata0(prsnt), sd0(cmd), dev(bootcs)
+mpp22         22       gpio, spi0(mosi), dev(ad0)
+mpp23         23       gpio, spi0(sck), dev(ad2)
+mpp24         24       gpio, spi0(miso), ua0(cts), ua1(rxd), sd0(d4), dev(ready)
+mpp25         25       gpio, spi0(cs0), ua0(rts), ua1(txd), sd0(d5), dev(cs0)
+mpp26         26       gpio, spi0(cs2), i2c1(sck), sd0(d6), dev(cs1)
+mpp27         27       gpio, spi0(cs3), ge1(txclkout), i2c1(sda), sd0(d7), dev(cs2)
+mpp28         28       gpio, ge1(txd0), sd0(clk), dev(ad5)
+mpp29         29       gpio, ge1(txd1), dev(ale0)
+mpp30         30       gpio, ge1(txd2), dev(oen)
+mpp31         31       gpio, ge1(txd3), dev(ale1)
+mpp32         32       gpio, ge1(txctl), dev(wen0)
+mpp33         33       gpio, m(decc_err), dev(ad3)
+mpp34         34       gpio, dev(ad1)
+mpp35         35       gpio, ref(clk_out1), dev(a1)
+mpp36         36       gpio, ptp(trig_gen), dev(a0)
+mpp37         37       gpio, ptp(clk), ge1(rxclk), sd0(d3), dev(ad8)
+mpp38         38       gpio, ptp(event_req), ge1(rxd1), ref(clk_out0), sd0(d0), dev(ad4)
+mpp39         39       gpio, i2c1(sck), ge1(rxd2), ua0(cts), sd0(d1), dev(a2)
+mpp40         40       gpio, i2c1(sda), ge1(rxd3), ua0(rts), sd0(d2), dev(ad6)
+mpp41         41       gpio, ua1(rxd), ge1(rxctl), ua0(cts), spi1(cs3), dev(burst/last)
+mpp42         42       gpio, ua1(txd), ua0(rts), dev(ad7)
+mpp43         43       gpio, pcie0(clkreq), m(vtt_ctrl), m(decc_err), pcie0(rstout), dev(clkout)
+mpp44         44       gpio, sata0(prsnt), sata1(prsnt), sata2(prsnt) [2], sata3(prsnt) [3], pcie0(rstout)
+mpp45         45       gpio, ref(clk_out0), pcie0(rstout), pcie1(rstout) [1], pcie2(rstout), pcie3(rstout)
+mpp46         46       gpio, ref(clk_out1), pcie0(rstout), pcie1(rstout) [1], pcie2(rstout), pcie3(rstout)
+mpp47         47       gpio, sata0(prsnt), sata1(prsnt), sata2(prsnt) [2], spi1(cs2), sata3(prsnt) [2]
+mpp48         48       gpio, sata0(prsnt), m(vtt_ctrl), tdm2c(pclk), audio(mclk), sd0(d4)
+mpp49         49       gpio, sata2(prsnt) [2], sata3(prsnt) [2], tdm2c(fsync), audio(lrclk), sd0(d5)
+mpp50         50       gpio, pcie0(rstout), pcie1(rstout) [1], tdm2c(drx), audio(extclk), sd0(cmd)
+mpp51         51       gpio, tdm2c(dtx), audio(sdo), m(decc_err)
+mpp52         52       gpio, pcie0(rstout), pcie1(rstout) [1], tdm2c(intn), audio(sdi), sd0(d6)
+mpp53         53       gpio, sata1(prsnt), sata0(prsnt), tdm2c(rstn), audio(bclk), sd0(d7)
+mpp54         54       gpio, sata0(prsnt), sata1(prsnt), pcie0(rstout), pcie1(rstout) [1], sd0(d3)
+mpp55         55       gpio, ua1(cts), ge(mdio), pcie1(clkreq) [1], spi1(cs1), sd0(d0)
+mpp56         56       gpio, ua1(rts), ge(mdc), m(decc_err), spi1(mosi)
+mpp57         57       gpio, spi1(sck), sd0(clk)
+mpp58         58       gpio, pcie1(clkreq) [1], i2c1(sck), pcie2(clkreq), spi1(miso), sd0(d1)
+mpp59         59       gpio, pcie0(rstout), i2c1(sda), pcie1(rstout) [1], spi1(cs0), sd0(d2)
+
+[1]: only available on 88F6820 and 88F6828
+[2]: only available on 88F6828
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
index bfa0a2e5e0cb..373dbccd7ab0 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
@@ -6,6 +6,7 @@ part and usage.
 Required properties:
 - compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl",
               "marvell,mv78460-pinctrl"
+- reg: register specifier of MPP registers
 
 This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460.
 
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
index 50ec3512a292..cf52477cc7ee 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
@@ -6,6 +6,7 @@ part and usage.
 Required properties:
 - compatible: "marvell,dove-pinctrl"
 - clocks: (optional) phandle of pdma clock
+- reg: register specifiers of MPP, MPP4, and PMU MPP registers
 
 Available mpp pins/groups and functions:
 Note: brackets (x) are not part of the mpp name for marvell,function and given
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
index 95daf6335c37..730444a9a4de 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
@@ -8,6 +8,7 @@ Required properties:
               "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
               "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
               "marvell,98dx4122-pinctrl"
+- reg: register specifier of MPP registers
 
 This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
 It also support the 88f6281-based variant in the 98dx412x Bobcat SoCs.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
index 0a26c3aa4e6d..0c09f4eb2af0 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
@@ -37,7 +37,7 @@ uart1: serial@12100 {
 
 pinctrl: pinctrl@d0200 {
 	compatible = "marvell,dove-pinctrl";
-	reg = <0xd0200 0x20>;
+	reg = <0xd0200 0x14>, <0xd0440 0x04>, <0xd802c 0x08>;
 
 	pmx_uart1_sw: pmx-uart1-sw {
 		marvell,pins = "mpp_uart1";
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index bc0dfdfdb148..66dcaa9efd74 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -63,6 +63,13 @@ Optional properties:
 		/* input, enable bits, disable bits, mask */
 		pinctrl-single,input-schmitt-enable = <0x30 0x40 0 0x70>;
 
+- pinctrl-single,low-power-mode : array of value that are used to configure
+  low power mode of this pin. For some silicons, the low power mode will
+  control the output of the pin when the pad including the pin enter low
+  power mode.
+		/* low power mode value, mask */
+		pinctrl-single,low-power-mode = <0x288 0x388>;
+
 - pinctrl-single,gpio-range : list of value that are used to configure a GPIO
   range. They're value of subnode phandle, pin base in pinctrl device, pin
   number in this range, GPIO function value of this GPIO range.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
index 05bf82a07dfd..4bd5be0e5e7d 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
@@ -11,18 +11,68 @@ Pull Up (PU) are driven by the related PIO block.
 ST pinctrl driver controls PIO multiplexing block and also interacts with
 gpio driver to configure a pin.
 
-Required properties: (PIO multiplexing block)
+GPIO bank can have one of the two possible types of interrupt-wirings.
+
+First type is via irqmux, single interrupt is used by multiple gpio banks. This
+reduces number of overall interrupts numbers required. All these banks belong to
+a single pincontroller.
+		  _________
+		 |	   |----> [gpio-bank (n)    ]
+		 |	   |----> [gpio-bank (n + 1)]
+	[irqN]-- | irq-mux |----> [gpio-bank (n + 2)]
+		 |	   |----> [gpio-bank (...  )]
+		 |_________|----> [gpio-bank (n + 7)]
+
+Second type has a dedicated interrupt per gpio bank.
+
+	[irqN]----> [gpio-bank (n)]
+
+
+Pin controller node:
+Required properties:
 - compatible	: should be "st,<SOC>-<pio-block>-pinctrl"
 	like st,stih415-sbc-pinctrl, st,stih415-front-pinctrl and so on.
-- gpio-controller : Indicates this device is a GPIO controller
-- #gpio-cells	  : Should be one. The first cell is the pin number.
+- st,syscfg		: Should be a phandle of the syscfg node.
 - st,retime-pin-mask	: Should be mask to specify which pins can be retimed.
 	If the property is not present, it is assumed that all the pins in the
 	bank are capable of retiming. Retiming is mainly used to improve the
 	IO timing margins of external synchronous interfaces.
-- st,bank-name		: Should be a name string for this bank as
-			specified in datasheet.
-- st,syscfg		: Should be a phandle of the syscfg node.
+- ranges : defines mapping between pin controller node (parent) to gpio-bank
+  node (children).
+
+Optional properties:
+- interrupts	: Interrupt number of the irqmux. If the interrupt is shared
+  with other gpio banks via irqmux.
+  a irqline and gpio banks.
+- reg		: irqmux memory resource. If irqmux is present.
+- reg-names	: irqmux resource should be named as "irqmux".
+
+GPIO controller/bank node.
+Required properties:
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells	  : Should be one. The first cell is the pin number.
+- st,bank-name	  : Should be a name string for this bank as specified in
+  datasheet.
+
+Optional properties:
+- interrupts	: Interrupt number for this gpio bank. If there is a dedicated
+  interrupt wired up for this gpio bank.
+
+- interrupt-controller : Indicates this device is a interrupt controller. GPIO
+  bank can be an interrupt controller iff one of the interrupt type either via
+irqmux or a dedicated interrupt per bank is specified.
+
+- #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
+for related macros look in:
+include/dt-bindings/interrupt-controller/irq.h
 
 Example:
 	pin-controller-sbc {
@@ -30,10 +80,17 @@ Example:
 		#size-cells	= <1>;
 		compatible	= "st,stih415-sbc-pinctrl";
 		st,syscfg	= <&syscfg_sbc>;
+		reg 		= <0xfe61f080 0x4>;
+		reg-names	= "irqmux";
+		interrupts 	= <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts-names = "irqmux";
 		ranges 		= <0 0xfe610000 0x5000>;
+
 		PIO0: gpio@fe610000 {
 			gpio-controller;
 			#gpio-cells	= <1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 			reg		= <0 0x100>;
 			st,bank-name	= "PIO0";
 		};
@@ -105,6 +162,10 @@ pin-controller {
 
 sdhci0:sdhci@fe810000{
 	...
+	interrupt-parent = <&PIO3>;
+	#interrupt-cells = <2>;
+	interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; /* Interrupt line via PIO3-3 */
+	interrupts-names = "card-detect";
 	pinctrl-names = "default";
 	pinctrl-0	= <&pinctrl_mmc>;
 };
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 257677de3e6b..2b32783ba821 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -16,6 +16,7 @@ Required Properties:
   - "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
   - "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
   - "samsung,exynos5250-pinctrl": for Exynos5250 compatible pin-controller.
+  - "samsung,exynos5260-pinctrl": for Exynos5260 compatible pin-controller.
   - "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller.
 
 - reg: Base address of the pin controller hardware module and length of
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt b/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
deleted file mode 100644
index d5e370450ac0..000000000000
--- a/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-Integrated Flash Controller
-
-Properties:
-- name : Should be ifc
-- compatible : should contain "fsl,ifc". The version of the integrated
-               flash controller can be found in the IFC_REV register at
-               offset zero.
-
-- #address-cells : Should be either two or three.  The first cell is the
-                   chipselect number, and the remaining cells are the
-                   offset into the chipselect.
-- #size-cells : Either one or two, depending on how large each chipselect
-                can be.
-- reg : Offset and length of the register set for the device
-- interrupts: IFC may have one or two interrupts.  If two interrupt
-              specifiers are present, the first is the "common"
-              interrupt (CM_EVTER_STAT), and the second is the NAND
-              interrupt (NAND_EVTER_STAT).  If there is only one,
-              that interrupt reports both types of event.
-
-
-- ranges : Each range corresponds to a single chipselect, and covers
-           the entire access window as configured.
-
-Child device nodes describe the devices connected to IFC such as NOR (e.g.
-cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices
-like FPGAs, CPLDs, etc.
-
-Example:
-
-	ifc@ffe1e000 {
-		compatible = "fsl,ifc", "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		reg = <0x0 0xffe1e000 0 0x2000>;
-		interrupts = <16 2 19 2>;
-
-		/* NOR, NAND Flashes and CPLD on board */
-		ranges = <0x0 0x0 0x0 0xee000000 0x02000000
-			  0x1 0x0 0x0 0xffa00000 0x00010000
-			  0x3 0x0 0x0 0xffb00000 0x00020000>;
-
-		flash@0,0 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "cfi-flash";
-			reg = <0x0 0x0 0x2000000>;
-			bank-width = <2>;
-			device-width = <1>;
-
-			partition@0 {
-				/* 32MB for user data */
-				reg = <0x0 0x02000000>;
-				label = "NOR Data";
-			};
-		};
-
-		flash@1,0 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,ifc-nand";
-			reg = <0x1 0x0 0x10000>;
-
-			partition@0 {
-				/* This location must not be altered  */
-				/* 1MB for u-boot Bootloader Image */
-				reg = <0x0 0x00100000>;
-				label = "NAND U-Boot Image";
-				read-only;
-			};
-		};
-
-		cpld@3,0 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p1010rdb-cpld";
-			reg = <0x3 0x0 0x000001f>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
index 63c659800c03..e5cac1e0ca8a 100644
--- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
@@ -8,8 +8,12 @@ Required properties:
 Optional properties:
 - enable-gpio		: GPIO to use to enable/disable the regulator.
 - gpios			: GPIO group used to control voltage.
+- gpios-states		: gpios pin's initial states array. 0: LOW, 1: HIGH.
+			  defualt is LOW if nothing is specified.
 - startup-delay-us	: Startup time in microseconds.
 - enable-active-high	: Polarity of GPIO is active high (default is low).
+- regulator-type	: Specifies what is being regulated, must be either
+			  "voltage" or "current", defaults to current.
 
 Any property defined as part of the core regulator binding defined in
 regulator.txt can also be used.
diff --git a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
index fc6b38f035bd..d290988ed975 100644
--- a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
@@ -69,13 +69,16 @@ sub-node should be of the format as listed below.
 		};
 	};
 The above regulator entries are defined in regulator bindings documentation
-except op_mode description.
+except these properties:
 	- op_mode: describes the different operating modes of the LDO's with
 		power mode change in SOC. The different possible values are,
 		0 - always off mode
 		1 - on in normal mode
 		2 - low power mode
 		3 - suspend mode
+	- s5m8767,pmic-ext-control-gpios: (optional) GPIO specifier for one
+		GPIO controlling this regulator (enable/disable); This is
+		valid only for buck9.
 
 The following are the names of the regulators that the s5m8767 pmic block
 supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
@@ -148,5 +151,13 @@ Example:
 				regulator-always-on;
 				regulator-boot-on;
 			};
+
+			vemmc_reg: BUCK9 {
+				regulator-name = "VMEM_VDD_2.8V";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <3>; /* Standby Mode */
+				s5m8767,pmic-ext-control-gpios = <&gpk0 2 0>;
+			};
 		};
 	};
diff --git a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
index 2e57a33e9029..c58db75f959e 100644
--- a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
@@ -4,10 +4,14 @@ Required Properties:
 - compatible: Should be one of:
   - "ti,abb-v1" for older SoCs like OMAP3
   - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
+  - "ti,abb-v3" for a generic definition where setup and control registers are
+     provided (example: DRA7)
 - reg: Address and length of the register set for the device. It contains
   the information of registers in the same order as described by reg-names
 - reg-names: Should contain the reg names
-  - "base-address"	- contains base address of ABB module
+  - "base-address"	- contains base address of ABB module (ti,abb-v1,ti,abb-v2)
+  - "control-address"	- contains control register address of ABB module (ti,abb-v3)
+  - "setup-address"	- contains setup register address of ABB module (ti,abb-v3)
   - "int-address"	- contains address of interrupt register for ABB module
   (also see Optional properties)
 - #address-cell: should be 0
diff --git a/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt b/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt
index 7cb9dbf34878..6983aad376c3 100644
--- a/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/sunxi-rtc.txt
@@ -3,7 +3,7 @@
 RTC controller for the Allwinner A10/A20
 
 Required properties:
-- compatible : Should be "allwinner,sun4i-rtc" or "allwinner,sun7i-a20-rtc"
+- compatible : Should be "allwinner,sun4i-a10-rtc" or "allwinner,sun7i-a20-rtc"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: IRQ line for the RTC.
@@ -11,7 +11,7 @@ Required properties:
 Example:
 
 rtc: rtc@01c20d00 {
-	compatible = "allwinner,sun4i-rtc";
+	compatible = "allwinner,sun4i-a10-rtc";
 	reg = <0x01c20d00 0x20>;
 	interrupts = <24>;
 };
diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 9c5d19ac935c..17c1042b2df8 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -13,6 +13,8 @@ Required properties:
 Optional properties:
 - atmel,use-dma-rx: use of PDC or DMA for receiving data
 - atmel,use-dma-tx: use of PDC or DMA for transmitting data
+- rts-gpios: specify a GPIO for RTS line. It will use specified PIO instead of the peripheral
+  function pin for the USART RTS feature. If unsure, don't specify this property.
 - add dma bindings for dma transfer:
 	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@ -33,6 +35,7 @@ Example:
 		clock-names = "usart";
 		atmel,use-dma-rx;
 		atmel,use-dma-tx;
+		rts-gpios = <&pioD 15 0>;
 	};
 
 - use DMA:
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index 6fd1dd1638dd..a1d1205d8185 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -4,11 +4,24 @@ Required properties:
 - compatible : Should be "fsl,<soc>-lpuart"
 - reg : Address and length of the register set for the device
 - interrupts : Should contain uart interrupt
+- clocks : phandle + clock specifier pairs, one for each entry in clock-names
+- clock-names : should contain: "ipg" - the uart clock
+
+Optional properties:
+- dmas: A list of two dma specifiers, one for each entry in dma-names.
+- dma-names: should contain "tx" and "rx".
+
+Note: Optional properties for DMA support. Write them both or both not.
 
 Example:
 
 uart0: serial@40027000 {
-	       compatible = "fsl,vf610-lpuart";
-	       reg = <0x40027000 0x1000>;
-	       interrupts = <0 61 0x00>;
-       };
+		compatible = "fsl,vf610-lpuart";
+		reg = <0x40027000 0x1000>;
+		interrupts = <0 61 0x00>;
+		clocks = <&clks VF610_CLK_UART0>;
+		clock-names = "ipg";
+		dmas = <&edma0 0 2>,
+			<&edma0 0 3>;
+		dma-names = "rx","tx";
+	};
diff --git a/Documentation/devicetree/bindings/serial/maxim,max310x.txt b/Documentation/devicetree/bindings/serial/maxim,max310x.txt
new file mode 100644
index 000000000000..83a919c241b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/maxim,max310x.txt
@@ -0,0 +1,36 @@
+* Maxim MAX310X advanced Universal Asynchronous Receiver-Transmitter (UART)
+
+Required properties:
+- compatible: Should be one of the following:
+  - "maxim,max3107" for Maxim MAX3107,
+  - "maxim,max3108" for Maxim MAX3108,
+  - "maxim,max3109" for Maxim MAX3109,
+  - "maxim,max14830" for Maxim MAX14830.
+- reg: SPI chip select number.
+- interrupt-parent: The phandle for the interrupt controller that
+  services interrupts for this IC.
+- interrupts: Specifies the interrupt source of the parent interrupt
+  controller. The format of the interrupt specifier depends on the
+  parent interrupt controller.
+- clocks: phandle to the IC source clock.
+- clock-names: Should be "xtal" if clock is an external crystal or
+  "osc" if an external clock source is used.
+
+Optional properties:
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Should be two. The first cell is the GPIO number and
+  the second cell is used to specify the GPIO polarity:
+    0 = active high,
+    1 = active low.
+
+Example:
+	max14830: max14830@0 {
+		compatible = "maxim,max14830";
+		reg = <0>;
+		clocks = <&clk20m>;
+		clock-names = "osc";
+		interrupt-parent = <&gpio3>;
+		interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
index f372cf29068d..53e6c175db6c 100644
--- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
+++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
@@ -37,7 +37,7 @@ Example:
 	};
 
 	scifa0: serial@e6c40000 {
-		compatible = "renesas,scifa-r8a7790", "renesas,scifa-generic";
+		compatible = "renesas,scifa-r8a7790", "renesas,scifa";
 		reg = <0 0xe6c40000 0 64>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt
new file mode 100644
index 000000000000..3893b4d15a20
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt
@@ -0,0 +1,24 @@
+Device Tree bindings for the Armada 370 DB audio
+================================================
+
+These Device Tree bindings are used to describe the audio complex
+found on the Armada 370 DB platform.
+
+Mandatory properties:
+
+ * compatible: must be "marvell,a370db-audio"
+
+ * marvell,audio-controller: a phandle that points to the audio
+   controller of the Armada 370 SoC.
+
+ * marvell,audio-codec: a phandle that points to the analog audio
+   codec connected to the Armada 370 SoC.
+
+Example:
+
+	sound {
+	      compatible = "marvell,a370db-audio";
+	      marvell,audio-controller = <&audio_controller>;
+	      marvell,audio-codec = <&audio_codec>;
+	      status = "okay";
+	};
diff --git a/Documentation/devicetree/bindings/sound/da9055.txt b/Documentation/devicetree/bindings/sound/da9055.txt
new file mode 100644
index 000000000000..ed1b7cc6f249
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/da9055.txt
@@ -0,0 +1,22 @@
+* Dialog DA9055 Audio CODEC
+
+DA9055 provides Audio CODEC support (I2C only).
+
+The Audio CODEC device in DA9055 has it's own I2C address which is configurable,
+so the device is instantiated separately from the PMIC (MFD) device.
+
+For details on accompanying PMIC I2C device, see the following:
+Documentation/devicetree/bindings/mfd/da9055.txt
+
+Required properties:
+
+  - compatible: "dlg,da9055-codec"
+  - reg: Specifies the I2C slave address
+
+
+Example:
+
+	codec: da9055-codec@1a {
+		compatible = "dlg,da9055-codec";
+		reg = <0x1a>;
+	};
diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
index 865178d5cdf3..963e100514c2 100644
--- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
@@ -5,12 +5,19 @@ Required properties:
 - ti,model : The user-visible name of this sound complex.
 - ti,audio-codec : The phandle of the TLV320AIC3x audio codec
 - ti,mcasp-controller : The phandle of the McASP controller
-- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
 - ti,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
   the second being the connection's source. Valid names for sources and
   sinks are the codec's pins, and the jacks on the board:
 
+Optional properties:
+- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec.
+- clocks : Reference to the master clock
+- clock-names : The clock should be named "mclk"
+- Either codec-clock-rate or the codec-clock reference has to be defined. If
+  the both are defined the driver attempts to set referenced clock to the
+  defined rate and takes the rate from the clock reference.
+
   Board connectors:
 
   * Headphone Jack
diff --git a/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt
new file mode 100644
index 000000000000..0d7985c864af
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt
@@ -0,0 +1,21 @@
+Audio complex for Eukrea boards with tlv320aic23 codec.
+
+Required properties:
+- compatible : "eukrea,asoc-tlv320"
+- eukrea,model : The user-visible name of this sound complex.
+- ssi-controller : The phandle of the SSI controller.
+- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX).
+- fsl,mux-ext-port : The external port of the i.MX audio muxer.
+
+Note: The AUDMUX port numbering should start at 1, which is consistent with
+hardware manual.
+
+Example:
+
+	sound {
+		compatible = "eukrea,asoc-tlv320";
+		eukrea,model = "imx51-eukrea-tlv320aic23";
+		ssi-controller = <&ssi2>;
+		fsl,mux-int-port = <2>;
+		fsl,mux-ext-port = <3>;
+	};
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index d7b99fa637b5..aeb8c4a0b88d 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -34,6 +34,10 @@ Required properties:
     that ESAI would work in the synchronous mode, which means all the settings
     for Receiving would be duplicated from Transmition related registers.
 
+  - big-endian : If this property is absent, the native endian mode will
+    be in use as default, or the big endian mode will be in use for all the
+    device registers.
+
 Example:
 
 esai: esai@02024000 {
@@ -46,5 +50,6 @@ esai: esai@02024000 {
 	dma-names = "rx", "tx";
 	fsl,fifo-depth = <128>;
 	fsl,esai-synchronous;
+	big-endian;
 	status = "disabled";
 };
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index f2ae335670f5..3e9e82c8eab3 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -29,6 +29,10 @@ Required properties:
 			can also be referred to TxClk_Source
 			bit of register SPDIF_STC.
 
+   - big-endian : If this property is absent, the native endian mode will
+   be in use as default, or the big endian mode will be in use for all the
+   device registers.
+
 Example:
 
 spdif: spdif@02004000 {
@@ -50,5 +54,6 @@ spdif: spdif@02004000 {
 		"rxtx5", "rxtx6",
 		"rxtx7";
 
+	big-endian;
 	status = "okay";
 };
diff --git a/Documentation/devicetree/bindings/sound/mvebu-audio.txt b/Documentation/devicetree/bindings/sound/mvebu-audio.txt
index f0062c5871b4..cb8c07c81ce4 100644
--- a/Documentation/devicetree/bindings/sound/mvebu-audio.txt
+++ b/Documentation/devicetree/bindings/sound/mvebu-audio.txt
@@ -5,6 +5,7 @@ Required properties:
 - compatible:
   "marvell,kirkwood-audio" for Kirkwood platforms
   "marvell,dove-audio" for Dove platforms
+  "marvell,armada370-audio" for Armada 370 platforms
 
 - reg: physical base address of the controller and length of memory mapped
   region.
diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt
new file mode 100644
index 000000000000..faff75e64573
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/pcm512x.txt
@@ -0,0 +1,30 @@
+PCM512x audio CODECs
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : One of "ti,pcm5121" or "ti,pcm5122"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+  - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
+    device, as covered in bindings/regulator/regulator.txt
+
+Optional properties:
+
+  - clocks : A clock specifier for the clock connected as SCLK.  If this
+    is absent the device will be configured to clock from BCLK.
+
+Example:
+
+	pcm5122: pcm5122@4c {
+		compatible = "ti,pcm5122";
+		reg = <0x4c>;
+
+		AVDD-supply = <&reg_3v3_analog>;
+		DVDD-supply = <&reg_1v8>;
+		CPVDD-supply = <&reg_3v3>;
+	};
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
index 19c84df5fffa..b30c222f9cd3 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.txt
+++ b/Documentation/devicetree/bindings/sound/simple-card.txt
@@ -8,13 +8,18 @@ Required properties:
 
 Optional properties:
 
+- simple-audio-card,name		: User specified audio sound card name, one string
+					  property.
 - simple-audio-card,format		: CPU/CODEC common audio format.
 					  "i2s", "right_j", "left_j" , "dsp_a"
 					  "dsp_b", "ac97", "pdm", "msb", "lsb"
+- simple-audio-card,widgets		: Please refer to widgets.txt.
 - simple-audio-card,routing		: A list of the connections between audio components.
 					  Each entry is a pair of strings, the first being the
 					  connection's sink, the second being the connection's
 					  source.
+- dai-tdm-slot-num			: Please refer to tdm-slot.txt.
+- dai-tdm-slot-width			: Please refer to tdm-slot.txt.
 
 Required subnodes:
 
@@ -42,11 +47,19 @@ Example:
 
 sound {
 	compatible = "simple-audio-card";
+	simple-audio-card,name = "VF610-Tower-Sound-Card";
 	simple-audio-card,format = "left_j";
+	simple-audio-card,widgets =
+		"Microphone", "Microphone Jack",
+		"Headphone", "Headphone Jack",
+		"Speaker", "External Speaker";
 	simple-audio-card,routing =
-		"MIC_IN", "Mic Jack",
+		"MIC_IN", "Microphone Jack",
 		"Headphone Jack", "HP_OUT",
-		"Ext Spk", "LINE_OUT";
+		"External Speaker", "LINE_OUT";
+
+	dai-tdm-slot-num = <2>;
+	dai-tdm-slot-width = <8>;
 
 	simple-audio-card,cpu {
 		sound-dai = <&sh_fsi2 0>;
diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt
new file mode 100644
index 000000000000..6a2c84247f91
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tdm-slot.txt
@@ -0,0 +1,20 @@
+TDM slot:
+
+This specifies audio DAI's TDM slot.
+
+TDM slot properties:
+dai-tdm-slot-num : Number of slots in use.
+dai-tdm-slot-width :  Width in bits for each slot.
+
+For instance:
+	dai-tdm-slot-num = <2>;
+	dai-tdm-slot-width = <8>;
+
+And for each spcified driver, there could be one .of_xlate_tdm_slot_mask()
+to specify a explicit mapping of the channels and the slots. If it's absent
+the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the
+tx and rx masks.
+
+For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit
+for an active slot as default, and the default active bits are at the LSB of
+the masks.
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
new file mode 100644
index 000000000000..5e2741af27be
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
@@ -0,0 +1,30 @@
+Texas Instruments - tlv320aic32x4 Codec module
+
+The tlv320aic32x4 serial control bus communicates through I2C protocols
+
+Required properties:
+ - compatible: Should be "ti,tlv320aic32x4"
+ - reg: I2C slave address
+ - supply-*: Required supply regulators are:
+    "iov" - digital IO power supply
+    "ldoin" - LDO power supply
+    "dv" - Digital core power supply
+    "av" - Analog core power supply
+    If you supply ldoin, dv and av are optional. Otherwise they are required
+   See regulator/regulator.txt for more information about the detailed binding
+   format.
+
+Optional properties:
+ - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
+ - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
+   See clock/clock-bindings.txt for information about the detailed format.
+
+
+Example:
+
+codec: tlv320aic32x4@18 {
+	compatible = "ti,tlv320aic32x4";
+	reg = <0x18>;
+	clocks = <&clks 201>;
+	clock-names = "mclk";
+};
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index 9d8ea14db490..5e6040c2c2e9 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -6,7 +6,6 @@ Required properties:
 
 - compatible - "string" - One of:
     "ti,tlv320aic3x" - Generic TLV320AIC3x device
-    "ti,tlv320aic32x4" - TLV320AIC32x4
     "ti,tlv320aic33" - TLV320AIC33
     "ti,tlv320aic3007" - TLV320AIC3007
     "ti,tlv320aic3106" - TLV320AIC3106
diff --git a/Documentation/devicetree/bindings/sound/widgets.txt b/Documentation/devicetree/bindings/sound/widgets.txt
new file mode 100644
index 000000000000..b6de5ba3b2de
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/widgets.txt
@@ -0,0 +1,20 @@
+Widgets:
+
+This mainly specifies audio off-codec DAPM widgets.
+
+Each entry is a pair of strings in DT:
+
+	"template-wname", "user-supplied-wname"
+
+The "template-wname" being the template widget name and currently includes:
+"Microphone", "Line", "Headphone" and "Speaker".
+
+The "user-supplied-wname" being the user specified widget name.
+
+For instance:
+	simple-audio-widgets =
+		"Microphone", "Microphone Jack",
+		"Line", "Line In Jack",
+		"Line", "Line Out Jack",
+		"Headphone", "Headphone Jack",
+		"Speaker", "Speaker External";
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
new file mode 100644
index 000000000000..b82a268f1bd4
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -0,0 +1,85 @@
+Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
+
+The QUP core is an AHB slave that provides a common data path (an output FIFO
+and an input FIFO) for serial peripheral interface (SPI) mini-core.
+
+SPI in master mode supports up to 50MHz, up to four chip selects, programmable
+data path from 4 bits to 32 bits and numerous protocol variants.
+
+Required properties:
+- compatible:     Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1"
+- reg:            Should contain base register location and length
+- interrupts:     Interrupt number used by this controller
+
+- clocks:         Should contain the core clock and the AHB clock.
+- clock-names:    Should be "core" for the core clock and "iface" for the
+                  AHB clock.
+
+- #address-cells: Number of cells required to define a chip select
+                  address on the SPI bus. Should be set to 1.
+- #size-cells:    Should be zero.
+
+Optional properties:
+- spi-max-frequency: Specifies maximum SPI clock frequency,
+                     Units - Hz. Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+SPI slave nodes must be children of the SPI master node and can contain
+properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+	spi_8: spi@f9964000 { /* BLSP2 QUP2 */
+
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xf9964000 0x1000>;
+		interrupts = <0 102 0>;
+		spi-max-frequency = <19200000>;
+
+		clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+		clock-names = "core", "iface";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi8_default>;
+
+		device@0 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0>; /* Chip select 0 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+		};
+
+		device@1 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <1>; /* Chip select 1 */
+			spi-max-frequency = <9600000>;
+			spi-cpha;
+		};
+
+		device@2 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <2>; /* Chip select 2 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+			spi-cpha;
+		};
+
+		device@3 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <3>; /* Chip select 3 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+			spi-cpha;
+			spi-cs-high;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt
index e6222106ca36..1f0cb33763a1 100644
--- a/Documentation/devicetree/bindings/spi/sh-msiof.txt
+++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt
@@ -1,12 +1,41 @@
 Renesas MSIOF spi controller
 
 Required properties:
-- compatible : 	"renesas,sh-msiof" for SuperH or
-		"renesas,sh-mobile-msiof" for SH Mobile series
-- reg : Offset and length of the register set for the device
-- interrupts : interrupt line used by MSIOF
+- compatible           : "renesas,msiof-<soctype>" for SoCs,
+			 "renesas,sh-msiof" for SuperH, or
+			 "renesas,sh-mobile-msiof" for SH Mobile series.
+			 Examples with soctypes are:
+			 "renesas,msiof-sh7724" (SH)
+			 "renesas,msiof-r8a7790" (R-Car H2)
+			 "renesas,msiof-r8a7791" (R-Car M2)
+- reg                  : Offset and length of the register set for the device
+- interrupt-parent     : The phandle for the interrupt controller that
+			 services interrupts for this device
+- interrupts           : Interrupt specifier
+- #address-cells       : Must be <1>
+- #size-cells          : Must be <0>
 
 Optional properties:
-- num-cs		: total number of chip-selects
-- renesas,tx-fifo-size	: Overrides the default tx fifo size given in words
-- renesas,rx-fifo-size	: Overrides the default rx fifo size given in words
+- clocks               : Must contain a reference to the functional clock.
+- num-cs               : Total number of chip-selects (default is 1)
+
+Optional properties, deprecated for soctype-specific bindings:
+- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
+			 (default is 64)
+- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
+			 (default is 64, or 256 on R-Car H2 and M2)
+
+Pinctrl properties might be needed, too.  See
+Documentation/devicetree/bindings/pinctrl/renesas,*.
+
+Example:
+
+	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";
+	};
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index a1fb3035a42b..5376de40f10b 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -10,6 +10,7 @@ Required properties:
 - pinctrl-names: must contain a "default" entry.
 - spi-num-chipselects : the number of the chipselect signals.
 - bus-num : the slave chip chipselect signal number.
+- big-endian : if DSPI modudle is big endian, the bool will be set in node.
 Example:
 
 dspi0@4002c000 {
@@ -24,6 +25,7 @@ dspi0@4002c000 {
 	bus-num = <0>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_dspi0_1>;
+	big-endian;
 	status = "okay";
 
 	sflash: at26df081a@0 {
diff --git a/Documentation/devicetree/bindings/spi/spi-rspi.txt b/Documentation/devicetree/bindings/spi/spi-rspi.txt
new file mode 100644
index 000000000000..d57d82a74054
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-rspi.txt
@@ -0,0 +1,61 @@
+Device tree configuration for Renesas RSPI/QSPI driver
+
+Required properties:
+- compatible       : For Renesas Serial Peripheral Interface on legacy SH:
+		     "renesas,rspi-<soctype>", "renesas,rspi" as fallback.
+		     For Renesas Serial Peripheral Interface on RZ/A1H:
+		     "renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback.
+		     For Quad Serial Peripheral Interface on R-Car Gen2:
+		     "renesas,qspi-<soctype>", "renesas,qspi" as fallback.
+		     Examples with soctypes are:
+		        - "renesas,rspi-sh7757" (SH)
+			- "renesas,rspi-r7s72100" (RZ/A1H)
+			- "renesas,qspi-r8a7790" (R-Car H2)
+			- "renesas,qspi-r8a7791" (R-Car M2)
+- reg              : Address start and address range size of the device
+- interrupts       : A list of interrupt-specifiers, one for each entry in
+		     interrupt-names.
+		     If interrupt-names is not present, an interrupt specifier
+		     for a single muxed interrupt.
+- interrupt-names  : A list of interrupt names. Should contain (if present):
+		       - "error" for SPEI,
+		       - "rx" for SPRI,
+		       - "tx" to SPTI,
+		       - "mux" for a single muxed interrupt.
+- interrupt-parent : The phandle for the interrupt controller that
+		     services interrupts for this device.
+- num-cs	   : Number of chip selects. Some RSPI cores have more than 1.
+- #address-cells   : Must be <1>
+- #size-cells      : Must be <0>
+
+Optional properties:
+- clocks           : Must contain a reference to the functional clock.
+
+Pinctrl properties might be needed, too.  See
+Documentation/devicetree/bindings/pinctrl/renesas,*.
+
+Examples:
+
+	spi0: spi@e800c800 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800c800 0x24>;
+		interrupts = <0 238 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 239 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 240 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		interrupt-parent = <&gic>;
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	spi: spi@e6b10000 {
+		compatible = "renesas,qspi-r8a7791", "renesas,qspi";
+		reg = <0 0xe6b10000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/spi/spi-sun4i.txt b/Documentation/devicetree/bindings/spi/spi-sun4i.txt
new file mode 100644
index 000000000000..de827f5a301e
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun4i.txt
@@ -0,0 +1,24 @@
+Allwinner A10 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun4-a10-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+          needed:
+  - "ahb": the gated AHB parent clock
+  - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+
+Example:
+
+spi1: spi@01c06000 {
+	compatible = "allwinner,sun4i-a10-spi";
+	reg = <0x01c06000 0x1000>;
+	interrupts = <11>;
+	clocks = <&ahb_gates 21>, <&spi1_clk>;
+	clock-names = "ahb", "mod";
+	status = "disabled";
+	#address-cells = <1>;
+	#size-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
new file mode 100644
index 000000000000..21de73db6a05
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -0,0 +1,24 @@
+Allwinner A31 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun6i-a31-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+          needed:
+  - "ahb": the gated AHB parent clock
+  - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset controller asserting this device in
+          reset
+
+Example:
+
+spi1: spi@01c69000 {
+	compatible = "allwinner,sun6i-a31-spi";
+	reg = <0x01c69000 0x1000>;
+	interrupts = <0 66 4>;
+	clocks = <&ahb1_gates 21>, <&spi1_clk>;
+	clock-names = "ahb", "mod";
+	resets = <&ahb1_rst 21>;
+};
diff --git a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
new file mode 100644
index 000000000000..715d0998af8e
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
@@ -0,0 +1,61 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+The SPMI PMIC Arbiter is found on the Snapdragon 800 Series.  It is an SPMI
+controller with wrapping arbitration logic to allow for multiple on-chip
+devices to control a single SPMI master.
+
+The PMIC Arbiter can also act as an interrupt controller, providing interrupts
+to slave devices.
+
+See spmi.txt for the generic SPMI controller binding requirements for child
+nodes.
+
+See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+generic interrupt controller binding documentation.
+
+Required properties:
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg-names  : must contain:
+     "core" - core registers
+     "intr" - interrupt controller registers
+     "cnfg" - configuration registers
+- reg : address + size pairs describing the PMIC arb register sets; order must
+        correspond with the order of entries in reg-names
+- #address-cells : must be set to 2
+- #size-cells : must be set to 0
+- qcom,ee : indicates the active Execution Environment identifier (0-5)
+- qcom,channel : which of the PMIC Arb provided channels to use for accesses (0-5)
+- interrupts : interrupt list for the PMIC Arb controller, must contain a
+               single interrupt entry for the peripheral interrupt
+- interrupt-names : corresponding interrupt names for the interrupts
+                    listed in the 'interrupts' property, must contain:
+     "periph_irq" - summary interrupt for PMIC peripherals
+- interrupt-controller : boolean indicator that the PMIC arbiter is an interrupt controller
+- #interrupt-cells :  must be set to 4. Interrupts are specified as a 4-tuple:
+    cell 1: slave ID for the requested interrupt (0-15)
+    cell 2: peripheral ID for requested interrupt (0-255)
+    cell 3: the requested peripheral interrupt (0-7)
+    cell 4: interrupt flags indicating level-sense information, as defined in
+            dt-bindings/interrupt-controller/irq.h
+
+Example:
+
+	spmi {
+		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
+		reg = <0xfc4cf000 0x1000>,
+		      <0xfc4cb000 0x1000>,
+		      <0xfc4ca000 0x1000>;
+
+		interrupt-names = "periph_irq";
+		interrupts = <0 190 0>;
+
+		qcom,ee = <0>;
+		qcom,channel = <0>;
+
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		interrupt-controller;
+		#interrupt-cells = <4>;
+	};
diff --git a/Documentation/devicetree/bindings/spmi/spmi.txt b/Documentation/devicetree/bindings/spmi/spmi.txt
new file mode 100644
index 000000000000..462a42fb3a1e
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/spmi.txt
@@ -0,0 +1,41 @@
+System Power Management Interface (SPMI) Controller
+
+This document defines a generic set of bindings for use by SPMI controllers.  A
+controller is modelled in device tree as a node with zero or more child nodes,
+each representing a unique slave on the bus.
+
+Required properties:
+- #address-cells : must be set to 2
+- #size-cells : must be set to 0
+
+Child nodes:
+
+An SPMI controller node can contain zero or more child nodes representing slave
+devices on the bus.  Child 'reg' properties are specified as an address, type
+pair.  The address must be in the range 0-15 (4 bits).  The type must be one of
+SPMI_USID (0) or SPMI_GSID (1) for Unique Slave ID or Group Slave ID respectively.
+These are the identifiers "statically assigned by the system integrator", as
+per the SPMI spec.
+
+Each child node must have one and only one 'reg' entry of type SPMI_USID.
+
+#include <dt-bindings/spmi/spmi.h>
+
+	spmi@.. {
+		compatible = "...";
+		reg = <...>;
+
+		#address-cells = <2>;
+		#size-cells <0>;
+
+		child@0 {
+			compatible = "...";
+			reg = <0 SPMI_USID>;
+		};
+
+		child@7 {
+			compatible = "...";
+			reg = <7 SPMI_USID
+			       3 SPMI_GSID>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
index b4b5b7906c88..a6a32cb7f777 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
@@ -18,6 +18,7 @@ Optional properties:
 - vbus-supply: regulator for vbus
 - disable-over-current: disable over current detect
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- maximum-speed: limit the maximum connection speed to "full-speed".
 
 Examples:
 usb@02184000 { /* USB OTG */
@@ -28,4 +29,5 @@ usb@02184000 { /* USB OTG */
 	fsl,usbmisc = <&usbmisc 0>;
 	disable-over-current;
 	external-vbus-divider;
+	maximum-speed = "full-speed";
 };
diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt
deleted file mode 100644
index a4fb0719d157..000000000000
--- a/Documentation/devicetree/bindings/usb/platform-uhci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Generic Platform UHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "platform-uhci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : UHCI controller interrupt
-
-Example:
-
-	uhci@d8007b00 {
-		compatible = "platform-uhci";
-		reg = <0xd8007b00 0x200>;
-		interrupts = <43>;
-	};
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index fa18612f757b..ff151ec084c4 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -1,19 +1,20 @@
 USB EHCI controllers
 
 Required properties:
-  - compatible : should be "usb-ehci".
+  - compatible : should be "generic-ehci".
   - reg : should contain at least address and length of the standard EHCI
     register set for the device. Optional platform-dependent registers
     (debug-port or other) can be also specified here, but only after
     definition of standard EHCI registers.
   - interrupts : one EHCI interrupt should be described here.
-If device registers are implemented in big endian mode, the device
-node should have "big-endian-regs" property.
-If controller implementation operates with big endian descriptors,
-"big-endian-desc" property should be specified.
-If both big endian registers and descriptors are used by the controller
-implementation, "big-endian" property can be specified instead of having
-both "big-endian-regs" and "big-endian-desc".
+
+Optional properties:
+ - big-endian-regs : boolean, set this for hcds with big-endian registers
+ - big-endian-desc : boolean, set this for hcds with big-endian descriptors
+ - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - clocks : a list of phandle + clock specifier pairs
+ - phys : phandle + phy specifier pair
+ - phy-names : "usb"
 
 Example (Sequoia 440EPx):
     ehci@e0000300 {
@@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
 	   reg = <0 e0000300 90 0 e0000390 70>;
 	   big-endian;
    };
+
+Example (Allwinner sun4i A10 SoC):
+   ehci0: usb@01c14000 {
+	   compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
+	   reg = <0x01c14000 0x100>;
+	   interrupts = <39>;
+	   clocks = <&ahb_gates 1>;
+	   phys = <&usbphy 1>;
+	   phy-names = "usb";
+   };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
new file mode 100644
index 000000000000..45f67d91e888
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -0,0 +1,25 @@
+USB OHCI controllers
+
+Required properties:
+- compatible : "generic-ohci"
+- reg : ohci controller register range (address and length)
+- interrupts : ohci controller interrupt
+
+Optional properties:
+- big-endian-regs : boolean, set this for hcds with big-endian registers
+- big-endian-desc : boolean, set this for hcds with big-endian descriptors
+- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+- clocks : a list of phandle + clock specifier pairs
+- phys : phandle + phy specifier pair
+- phy-names : "usb"
+
+Example:
+
+	ohci0: usb@01c14400 {
+		compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
+		reg = <0x01c14400 0x100>;
+		interrupts = <64>;
+		clocks = <&usb_clk 6>, <&ahb_gates 2>;
+		phys = <&usbphy 1>;
+		phy-names = "usb";
+	};
diff --git a/Documentation/devicetree/bindings/usb/usb-uhci.txt b/Documentation/devicetree/bindings/usb/usb-uhci.txt
new file mode 100644
index 000000000000..298133416c97
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt
@@ -0,0 +1,15 @@
+Generic Platform UHCI Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "generic-uhci" (deprecated: "platform-uhci")
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : UHCI controller interrupt
+
+Example:
+
+	uhci@d8007b00 {
+		compatible = "generic-uhci";
+		reg = <0xd8007b00 0x200>;
+		interrupts = <43>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 5752df0e17a2..90f8f607d125 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -1,14 +1,14 @@
 USB xHCI controllers
 
 Required properties:
-  - compatible: should be "xhci-platform".
+  - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
   - reg: should contain address and length of the standard XHCI
     register set for the device.
   - interrupts: one XHCI interrupt should be described here.
 
 Example:
 	usb@f0931000 {
-		compatible = "xhci-platform";
+		compatible = "generic-xhci";
 		reg = <0xf0931000 0x8c8>;
 		interrupts = <0x0 0x4e 0x0>;
 	};
diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
deleted file mode 100644
index 17b3ad1d97e7..000000000000
--- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-VIA/Wondermedia VT8500 EHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "via,vt8500-ehci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : ehci controller interrupt
-
-Example:
-
-	ehci@d8007900 {
-		compatible = "via,vt8500-ehci";
-		reg = <0xd8007900 0x200>;
-		interrupts = <43>;
-	};
diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
deleted file mode 100644
index 5fb8fd6e250c..000000000000
--- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
-
-Required properties:
- - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
- - reg: Address range of the ehci registers. size should be 0x200
- - interrupts: Should contain the ehci interrupt.
-
-usb: ehci@D8007100 {
-	compatible = "wm,prizm-ehci", "usb-ehci";
-	reg = <0xD8007100 0x200>;
-	interrupts = <1>;
-};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 40ce2df0e0e9..4685ec396c34 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -29,11 +29,13 @@ cortina	Cortina Systems, Inc.
 dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom	DAVICOM Semiconductor, Inc.
 denx	Denx Software Engineering
+dmo	Data Modul AG
 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
 fsl	Freescale Semiconductor
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
@@ -68,10 +70,12 @@ picochip	Picochip Ltd
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
+qnap	QNAP Systems, Inc.
 ralink	Mediatek/Ralink Technology Corp.
 ramtron	Ramtron International
 realtek Realtek Semiconductor Corp.
 renesas	Renesas Electronics Corporation
+ricoh	Ricoh Co. Ltd.
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
 sbs	Smart Battery System
@@ -79,18 +83,21 @@ schindler	Schindler
 sil	Silicon Image
 silabs	Silicon Laboratories
 simtek
+sii	Seiko Instruments, Inc.
 sirf	SiRF Technology, Inc.
 snps 	Synopsys, Inc.
 spansion	Spansion Inc.
 st	STMicroelectronics
 ste	ST-Ericsson
 stericsson	ST-Ericsson
+synology	Synology, Inc.
 ti	Texas Instruments
 tlm	Trusted Logic Mobility
 toshiba	Toshiba Corporation
 toumaz	Toumaz
 v3	V3 Semiconductor
 via	VIA Technologies, Inc.
+voipac	Voipac Technologies s.r.o.
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
 wm	Wondermedia Technologies, Inc.
diff --git a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
index 46da08db186a..e6b1ee9b8e2e 100644
--- a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
+++ b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
@@ -15,6 +15,7 @@ Required nodes:
 	- fsl,pcr: LCDC PCR value
 
 Optional properties:
+- lcd-supply: Regulator for LCD supply voltage.
 - fsl,dmacr: DMA Control Register value. This is optional. By default, the
 	register is not modified as recommended by the datasheet.
 - fsl,lscr1: LCDC Sharp Configuration Register value.
diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 5dc8d30061ce..de11eb4c121f 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -3,17 +3,24 @@
 Required Properties:
 
 - Compatibility : "marvell,orion-wdt"
-- reg		: Address of the timer registers
+		  "marvell,armada-370-wdt"
+		  "marvell,armada-xp-wdt"
+
+- reg		: Should contain two entries: first one with the
+		  timer control address, second one with the
+		  rstout enable address.
 
 Optional properties:
 
+- interrupts	: Contains the IRQ for watchdog expiration
 - timeout-sec	: Contains the watchdog timeout in seconds
 
 Example:
 
 	wdt@20300 {
 		compatible = "marvell,orion-wdt";
-		reg = <0x20300 0x28>;
+		reg = <0x20300 0x28>, <0x20108 0x4>;
+		interrupts = <3>;
 		timeout-sec = <10>;
 		status = "okay";
 	};
diff --git a/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt b/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
new file mode 100644
index 000000000000..6d63782a7378
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
@@ -0,0 +1,23 @@
+Xilinx AXI/PLB soft-core watchdog Device Tree Bindings
+---------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,xps-timebase-wdt-1.00.a" or
+			  "xlnx,xps-timebase-wdt-1.01.a".
+- reg			: Physical base address and size
+
+Optional properties:
+- clock-frequency	: Frequency of clock in Hz
+- xlnx,wdt-enable-once	: 0 - Watchdog can be restarted
+			  1 - Watchdog can be enabled just once
+- xlnx,wdt-interval	: Watchdog timeout interval in 2^<val> clock cycles,
+			  <val> is integer from 8 to 31.
+
+Example:
+axi-timebase-wdt@40100000 {
+	clock-frequency = <50000000>;
+	compatible = "xlnx,xps-timebase-wdt-1.00.a";
+	reg = <0x40100000 0x10000>;
+	xlnx,wdt-enable-once = <0x0>;
+	xlnx,wdt-interval = <0x1b>;
+} ;
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 5b0c083d7c0e..767930f04a12 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -525,6 +525,7 @@ locking rules:
 open:		yes
 close:		yes
 fault:		yes		can return with page locked
+map_pages:	yes
 page_mkwrite:	yes		can return with page locked
 access:		yes
 
@@ -536,6 +537,15 @@ the page, then ensure it is not already truncated (the page lock will block
 subsequent truncate), and then return with VM_FAULT_LOCKED, and the page
 locked. The VM will unlock the page.
 
+	->map_pages() is called when VM asks to map easy accessible pages.
+Filesystem should find and map pages associated with offsets from "pgoff"
+till "max_pgoff". ->map_pages() is called with page table locked and must
+not block.  If it's not possible to reach a page without blocking,
+filesystem should skip it. Filesystem should use do_set_pte() to setup
+page table entry. Pointer to entry associated with offset "pgoff" is
+passed in "pte" field in vm_fault structure. Pointers to entries for other
+offsets should be calculated relative to "pte".
+
 	->page_mkwrite() is called when a previously read-only pte is
 about to become writeable. The filesystem again must ensure that there are
 no truncate/invalidate races, and then return with the page locked. If
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index b8d284975f0f..803784e1e8ef 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -195,6 +195,13 @@ Files in /sys/fs/f2fs/<devname>
 			      cleaning operations. The default value is 4096
 			      which covers 8GB block address range.
 
+ dir_level                    This parameter controls the directory level to
+			      support large directory. If a directory has a
+			      number of files, it can reduce the file lookup
+			      latency by increasing this dir_level value.
+			      Otherwise, it needs to decrease this value to
+			      reduce the space overhead. The default value is 0.
+
 ================================================================================
 USAGE
 ================================================================================
@@ -444,9 +451,11 @@ The number of blocks and buckets are determined by,
   # of blocks in level #n = |
                             `- 4, Otherwise
 
-                             ,- 2^n, if n < MAX_DIR_HASH_DEPTH / 2,
+                             ,- 2^ (n + dir_level),
+			     |            if n < MAX_DIR_HASH_DEPTH / 2,
   # of buckets in level #n = |
-                             `- 2^((MAX_DIR_HASH_DEPTH / 2) - 1), Otherwise
+                             `- 2^((MAX_DIR_HASH_DEPTH / 2 + dir_level) - 1),
+			                  Otherwise
 
 When F2FS finds a file name in a directory, at first a hash value of the file
 name is calculated. Then, F2FS scans the hash table in level #0 to find the
diff --git a/Documentation/filesystems/hfsplus.txt b/Documentation/filesystems/hfsplus.txt
index af1628a1061c..59f7569fc9ed 100644
--- a/Documentation/filesystems/hfsplus.txt
+++ b/Documentation/filesystems/hfsplus.txt
@@ -56,4 +56,4 @@ References
 
 kernel source:		<file:fs/hfsplus>
 
-Apple Technote 1150	http://developer.apple.com/technotes/tn/tn1150.html
+Apple Technote 1150	https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt
index 06887d46ccf2..41c3d332acc9 100644
--- a/Documentation/filesystems/nilfs2.txt
+++ b/Documentation/filesystems/nilfs2.txt
@@ -25,9 +25,8 @@ available from the following download page.  At least "mkfs.nilfs2",
 cleaner or garbage collector) are required.  Details on the tools are
 described in the man pages included in the package.
 
-Project web page:    http://www.nilfs.org/en/
-Download page:       http://www.nilfs.org/en/download.html
-Git tree web page:   http://www.nilfs.org/git/
+Project web page:    http://nilfs.sourceforge.net/
+Download page:       http://nilfs.sourceforge.net/en/download.html
 List info:           http://vger.kernel.org/vger-lists.html#linux-nilfs
 
 Caveats
@@ -111,6 +110,13 @@ Table of NILFS2 specific ioctls
 			        nilfs_resize utilities and by nilfs_cleanerd
 			        daemon.
 
+ NILFS_IOCTL_SET_SUINFO         Modify segment usage info of requested
+				segments. This ioctl is used by
+				nilfs_cleanerd daemon to skip unnecessary
+				cleaning operation of segments and reduce
+				performance penalty or wear of flash device
+				due to redundant move of in-use blocks.
+
  NILFS_IOCTL_GET_SUSTAT         Return segment usage statistics. This ioctl
 			        is used in lssu, nilfs_resize utilities and
 			        by nilfs_cleanerd daemon.
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index 791af8dac065..61947facfc07 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -455,8 +455,6 @@ not have this problem with odd numbers of sectors.
 ChangeLog
 =========
 
-Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
-
 2.1.30:
 	- Fix writev() (it kept writing the first segment over and over again
 	  instead of moving onto subsequent segments).
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index fe2b7ae6f962..0f3a1390bf00 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -295,9 +295,9 @@ in the beginning of ->setattr unconditionally.
 	->clear_inode() and ->delete_inode() are gone; ->evict_inode() should
 be used instead.  It gets called whenever the inode is evicted, whether it has
 remaining links or not.  Caller does *not* evict the pagecache or inode-associated
-metadata buffers; getting rid of those is responsibility of method, as it had
-been for ->delete_inode(). Caller makes sure async writeback cannot be running
-for the inode while (or after) ->evict_inode() is called.
+metadata buffers; the method has to use truncate_inode_pages_final() to get rid
+of those. Caller makes sure async writeback cannot be running for the inode while
+(or after) ->evict_inode() is called.
 
 	->drop_inode() returns int now; it's called on final iput() with
 inode->i_lock held and it returns true if filesystems wants the inode to be
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/fmc/fmc-write-eeprom.txt b/Documentation/fmc/fmc-write-eeprom.txt
index 44a3bc678bf0..e0a9712156aa 100644
--- a/Documentation/fmc/fmc-write-eeprom.txt
+++ b/Documentation/fmc/fmc-write-eeprom.txt
@@ -9,7 +9,12 @@ Overwriting the EEPROM is not something you should do daily, and it is
 expected to only happen during manufacturing. For this reason, the
 module makes it unlikely for the random user to change a working EEPROM.
 
-The module takes the following measures:
+However, since the EEPROM may include application-specific information
+other than the identification, later versions of this packages added
+write-support through sysfs. See *note Accessing the EEPROM::.
+
+To avoid damaging the EEPROM content, the module takes the following
+measures:
 
    * It accepts a `file=' argument (within /lib/firmware) and if no
      such argument is received, it doesn't write anything to EEPROM
@@ -70,56 +75,24 @@ first time.
         [  132.899872]  fake-fmc: Product name: FmcDelay1ns4cha
 
 
-Writing to the EEPROM
+Accessing the EEPROM
 =====================
 
-Once you have created a binary file for your EEPROM, you can write it
-to the storage medium using the fmc-write-eeprom (See *note
-fmc-write-eeprom::, while relying on a carrier driver.  The procedure
-here shown here uses the SPEC driver
-(`http://www.ohwr.org/projects/spec-sw').
-
-The example assumes no driver is already loaded (actually, I unloaded
-them by hand as everything loads automatically at boot time after you
-installed the modules), and shows kernel messages together with
-commands. Here the prompt is spusa.root# and two SPEC cards are plugged
-in the system.
-
-     spusa.root# insmod fmc.ko
-     spusa.root# insmod spec.ko
-     [13972.382818] spec 0000:02:00.0:  probe for device 0002:0000
-     [13972.392773] spec 0000:02:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes
-     [13972.591388] spec 0000:02:00.0: FPGA programming successful
-     [13972.883011] spec 0000:02:00.0: EEPROM has no FRU information
-     [13972.888719] spec 0000:02:00.0: No device_id filled, using index
-     [13972.894676] spec 0000:02:00.0: No mezzanine_name found
-     [13972.899863] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
-     [13972.906578] spec 0000:04:00.0:  probe for device 0004:0000
-     [13972.916509] spec 0000:04:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes
-     [13973.115096] spec 0000:04:00.0: FPGA programming successful
-     [13973.401798] spec 0000:04:00.0: EEPROM has no FRU information
-     [13973.407474] spec 0000:04:00.0: No device_id filled, using index
-     [13973.413417] spec 0000:04:00.0: No mezzanine_name found
-     [13973.418600] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
-     spusa.root# ls /sys/bus/fmc/devices
-     fmc-0000  fmc-0001
-     spusa.root# insmod fmc-write-eeprom.ko busid=0x0200 file=fdelay-eeprom.bin
-     [14103.966259] spec 0000:02:00.0: Matching an generic driver (no ID)
-     [14103.975519] spec 0000:02:00.0: programming 6155 bytes
-     [14126.373762] spec 0000:02:00.0: write_eeprom: success
-     [14126.378770] spec 0000:04:00.0: Matching an generic driver (no ID)
-     [14126.384903] spec 0000:04:00.0: fmc_write_eeprom: no filename given: not programming
-     [14126.392600] fmc_write_eeprom: probe of fmc-0001 failed with error -2
-
-Reading back the EEPROM
-=======================
-
-In order to read back the binary content of the EEPROM of your
-mezzanine device, the bus creates a read-only sysfs file called eeprom
-for each mezzanine it knows about:
-
-   spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
-   -r--r--r-- 1 root root 8192 Apr  9 16:53 FmcDelay1ns4cha-f001/eeprom
-   -r--r--r-- 1 root root 8192 Apr  9 17:19 fake-design-for-testing-f002/eeprom
-   -r--r--r-- 1 root root 8192 Apr  9 17:19 fake-design-for-testing-f003/eeprom
-   -r--r--r-- 1 root root 8192 Apr  9 17:19 fmc-f004/eeprom
+The bus creates a sysfs binary file called eeprom for each mezzanine it
+knows about:
+
+        spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
+        -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcAdc100m14b4cha-0800/eeprom
+        -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDelay1ns4cha-0200/eeprom
+        -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDio5cha-0400/eeprom
+
+Everybody can read the files and the superuser can also modify it, but
+the operation may on the carrier driver, if the carrier is unable to
+access the I2C bus.  For example, the spec driver can access the bus
+only with its golden gateware: after a mezzanine driver reprogrammed
+the FPGA with a custom circuit, the carrier is unable to access the
+EEPROM and returns ENOTSUPP.
+
+An alternative way to write the EEPROM is the mezzanine driver
+fmc-write-eeprom (See *note fmc-write-eeprom::), but the procedure is
+more complex.
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
index e42f77d8d4ca..09854fe59307 100644
--- a/Documentation/gpio/consumer.txt
+++ b/Documentation/gpio/consumer.txt
@@ -154,6 +154,7 @@ raw line value:
 	void gpiod_set_raw_value(struct gpio_desc *desc, int value)
 	int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
 	void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
+	int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 
 The active-low state of a GPIO can also be queried using the following call:
 
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index 9da0bfa74781..f73cc7b5dc85 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -62,6 +62,37 @@ Any debugfs dump method should normally ignore signals which haven't been
 requested as GPIOs. They can use gpiochip_is_requested(), which returns either
 NULL or the label associated with that GPIO when it was requested.
 
+
+GPIO drivers providing IRQs
+---------------------------
+It is custom that GPIO drivers (GPIO chips) are also providing interrupts,
+most often cascaded off a parent interrupt controller, and in some special
+cases the GPIO logic is melded with a SoC's primary interrupt controller.
+
+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.
+
+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
+other.
+
+gpiod_to_irq() is just a convenience function to figure out the IRQ for a
+certain GPIO line and should not be relied upon to have been called before
+the IRQ is used.
+
+So always prepare the hardware and make it ready for action in respective
+callbacks from the GPIO and irqchip APIs. Do not rely on gpiod_to_irq() having
+been called first.
+
+This orthogonality leads to ambiguities that we need to solve: if there is
+competition inside the subsystem which side is using the resource (a certain
+GPIO line and register for example) it needs to deny certain operations and
+keep track of usage inside of the gpiolib subsystem. This is why the API
+below exists.
+
+
 Locking IRQ usage
 -----------------
 Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
@@ -73,3 +104,7 @@ This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
 is released:
 
 	void gpiod_unlock_as_irq(struct gpio_desc *desc)
+
+When implementing an irqchip inside a GPIO driver, these two functions should
+typically be called in the .startup() and .shutdown() callbacks from the
+irqchip.
diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
new file mode 100644
index 000000000000..3dcba9fd4a3a
--- /dev/null
+++ b/Documentation/hid/hid-transport.txt
@@ -0,0 +1,317 @@
+                          HID I/O Transport Drivers
+                         ===========================
+
+The HID subsystem is independent of the underlying transport driver. Initially,
+only USB was supported, but other specifications adopted the HID design and
+provided new transport drivers. The kernel includes at least support for USB,
+Bluetooth, I2C and user-space I/O drivers.
+
+1) HID Bus
+==========
+
+The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
+devices and register them with the HID bus. HID core then loads generic device
+drivers on top of it. The transport drivers are responsible of raw data
+transport and device setup/management. HID core is responsible of
+report-parsing, report interpretation and the user-space API. Device specifics
+and quirks are handled by all layers depending on the quirk.
+
+ +-----------+  +-----------+            +-----------+  +-----------+
+ | Device #1 |  | Device #i |            | Device #j |  | Device #k |
+ +-----------+  +-----------+            +-----------+  +-----------+
+          \\      //                              \\      //
+        +------------+                          +------------+
+        | I/O Driver |                          | I/O Driver |
+        +------------+                          +------------+
+              ||                                      ||
+     +------------------+                    +------------------+
+     | Transport Driver |                    | Transport Driver |
+     +------------------+                    +------------------+
+                       \___                ___/
+                           \              /
+                          +----------------+
+                          |    HID Core    |
+                          +----------------+
+                           /  |        |  \
+                          /   |        |   \
+             ____________/    |        |    \_________________
+            /                 |        |                      \
+           /                  |        |                       \
+ +----------------+  +-----------+  +------------------+  +------------------+
+ | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
+ +----------------+  +-----------+  +------------------+  +------------------+
+
+Example Drivers:
+  I/O: USB, I2C, Bluetooth-l2cap
+  Transport: USB-HID, I2C-HID, BT-HIDP
+
+Everything below "HID Core" is simplified in this graph as it is only of
+interest to HID device drivers. Transport drivers do not need to know the
+specifics.
+
+1.1) Device Setup
+-----------------
+
+I/O drivers normally provide hotplug detection or device enumeration APIs to the
+transport drivers. Transport drivers use this to find any suitable HID device.
+They allocate HID device objects and register them with HID core. Transport
+drivers are not required to register themselves with HID core. HID core is never
+aware of which transport drivers are available and is not interested in it. It
+is only interested in devices.
+
+Transport drivers attach a constant "struct hid_ll_driver" object with each
+device. Once a device is registered with HID core, the callbacks provided via
+this struct are used by HID core to communicate with the device.
+
+Transport drivers are responsible of detecting device failures and unplugging.
+HID core will operate a device as long as it is registered regardless of any
+device failures. Once transport drivers detect unplug or failure events, they
+must unregister the device from HID core and HID core will stop using the
+provided callbacks.
+
+1.2) Transport Driver Requirements
+----------------------------------
+
+The terms "asynchronous" and "synchronous" in this document describe the
+transmission behavior regarding acknowledgements. An asynchronous channel must
+not perform any synchronous operations like waiting for acknowledgements or
+verifications. Generally, HID calls operating on asynchronous channels must be
+running in atomic-context just fine.
+On the other hand, synchronous channels can be implemented by the transport
+driver in whatever way they like. They might just be the same as asynchronous
+channels, but they can also provide acknowledgement reports, automatic
+retransmission on failure, etc. in a blocking manner. If such functionality is
+required on asynchronous channels, a transport-driver must implement that via
+its own worker threads.
+
+HID core requires transport drivers to follow a given design. A Transport
+driver must provide two bi-directional I/O channels to each HID device. These
+channels must not necessarily be bi-directional in the hardware itself. A
+transport driver might just provide 4 uni-directional channels. Or it might
+multiplex all four on a single physical channel. However, in this document we
+will describe them as two bi-directional channels as they have several
+properties in common.
+
+ - Interrupt Channel (intr): The intr channel is used for asynchronous data
+   reports. No management commands or data acknowledgements are sent on this
+   channel. Any unrequested incoming or outgoing data report must be sent on
+   this channel and is never acknowledged by the remote side. Devices usually
+   send their input events on this channel. Outgoing events are normally
+   not send via intr, except if high throughput is required.
+ - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
+   device management. Unrequested data input events must not be sent on this
+   channel and are normally ignored. Instead, devices only send management
+   events or answers to host requests on this channel.
+   The control-channel is used for direct blocking queries to the device
+   independent of any events on the intr-channel.
+   Outgoing reports are usually sent on the ctrl channel via synchronous
+   SET_REPORT requests.
+
+Communication between devices and HID core is mostly done via HID reports. A
+report can be of one of three types:
+
+ - INPUT Report: Input reports provide data from device to host. This
+   data may include button events, axis events, battery status or more. This
+   data is generated by the device and sent to the host with or without
+   requiring explicit requests. Devices can choose to send data continuously or
+   only on change.
+ - OUTPUT Report: Output reports change device states. They are sent from host
+   to device and may include LED requests, rumble requests or more. Output
+   reports are never sent from device to host, but a host can retrieve their
+   current state.
+   Hosts may choose to send output reports either continuously or only on
+   change.
+ - FEATURE Report: Feature reports are used for specific static device features
+   and never reported spontaneously. A host can read and/or write them to access
+   data like battery-state or device-settings.
+   Feature reports are never sent without requests. A host must explicitly set
+   or retrieve a feature report. This also means, feature reports are never sent
+   on the intr channel as this channel is asynchronous.
+
+INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
+For INPUT reports this is the usual operational mode. But for OUTPUT reports,
+this is rarely done as OUTPUT reports are normally quite scarce. But devices are
+free to make excessive use of asynchronous OUTPUT reports (for instance, custom
+HID audio speakers make great use of it).
+
+Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
+channel provides synchronous GET/SET_REPORT requests. Plain reports are only
+allowed on the intr channel and are the only means of data there.
+
+ - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
+   from host to device. The device must answer with a data report for the
+   requested report ID on the ctrl channel as a synchronous acknowledgement.
+   Only one GET_REPORT request can be pending for each device. This restriction
+   is enforced by HID core as several transport drivers don't allow multiple
+   simultaneous GET_REPORT requests.
+   Note that data reports which are sent as answer to a GET_REPORT request are
+   not handled as generic device events. That is, if a device does not operate
+   in continuous data reporting mode, an answer to GET_REPORT does not replace
+   the raw data report on the intr channel on state change.
+   GET_REPORT is only used by custom HID device drivers to query device state.
+   Normally, HID core caches any device state so this request is not necessary
+   on devices that follow the HID specs except during device initialization to
+   retrieve the current state.
+   GET_REPORT requests can be sent for any of the 3 report types and shall
+   return the current report state of the device. However, OUTPUT reports as
+   payload may be blocked by the underlying transport driver if the
+   specification does not allow them.
+ - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
+   sent from host to device and a device must update it's current report state
+   according to the given data. Any of the 3 report types can be used. However,
+   INPUT reports as payload might be blocked by the underlying transport driver
+   if the specification does not allow them.
+   A device must answer with a synchronous acknowledgement. However, HID core
+   does not require transport drivers to forward this acknowledgement to HID
+   core.
+   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
+   restriction is enforced by HID core as some transport drivers do not support
+   multiple synchronous SET_REPORT requests.
+
+Other ctrl-channel requests are supported by USB-HID but are not available
+(or deprecated) in most other transport level specifications:
+
+ - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
+ - GET/SET_PROTOCOL: Not used by HID core.
+ - RESET: Used by I2C-HID, not hooked up in HID core.
+ - SET_POWER: Used by I2C-HID, not hooked up in HID core.
+
+2) HID API
+==========
+
+2.1) Initialization
+-------------------
+
+Transport drivers normally use the following procedure to register a new device
+with HID core:
+
+	struct hid_device *hid;
+	int ret;
+
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		ret = PTR_ERR(hid);
+		goto err_<...>;
+	}
+
+	strlcpy(hid->name, <device-name-src>, 127);
+	strlcpy(hid->phys, <device-phys-src>, 63);
+	strlcpy(hid->uniq, <device-uniq-src>, 63);
+
+	hid->ll_driver = &custom_ll_driver;
+	hid->bus = <device-bus>;
+	hid->vendor = <device-vendor>;
+	hid->product = <device-product>;
+	hid->version = <device-version>;
+	hid->country = <device-country>;
+	hid->dev.parent = <pointer-to-parent-device>;
+	hid->driver_data = <transport-driver-data-field>;
+
+	ret = hid_add_device(hid);
+	if (ret)
+		goto err_<...>;
+
+Once hid_add_device() is entered, HID core might use the callbacks provided in
+"custom_ll_driver". Note that fields like "country" can be ignored by underlying
+transport-drivers if not supported.
+
+To unregister a device, use:
+
+	hid_destroy_device(hid);
+
+Once hid_destroy_device() returns, HID core will no longer make use of any
+driver callbacks.
+
+2.2) hid_ll_driver operations
+-----------------------------
+
+The available HID callbacks are:
+ - int (*start) (struct hid_device *hdev)
+   Called from HID device drivers once they want to use the device. Transport
+   drivers can choose to setup their device in this callback. However, normally
+   devices are already set up before transport drivers register them to HID core
+   so this is mostly only used by USB-HID.
+
+ - void (*stop) (struct hid_device *hdev)
+   Called from HID device drivers once they are done with a device. Transport
+   drivers can free any buffers and deinitialize the device. But note that
+   ->start() might be called again if another HID device driver is loaded on the
+   device.
+   Transport drivers are free to ignore it and deinitialize devices after they
+   destroyed them via hid_destroy_device().
+
+ - int (*open) (struct hid_device *hdev)
+   Called from HID device drivers once they are interested in data reports.
+   Usually, while user-space didn't open any input API/etc., device drivers are
+   not interested in device data and transport drivers can put devices asleep.
+   However, once ->open() is called, transport drivers must be ready for I/O.
+   ->open() calls are nested for each client that opens the HID device.
+
+ - void (*close) (struct hid_device *hdev)
+   Called from HID device drivers after ->open() was called but they are no
+   longer interested in device reports. (Usually if user-space closed any input
+   devices of the driver).
+   Transport drivers can put devices asleep and terminate any I/O of all
+   ->open() calls have been followed by a ->close() call. However, ->start() may
+   be called again if the device driver is interested in input reports again.
+
+ - int (*parse) (struct hid_device *hdev)
+   Called once during device setup after ->start() has been called. Transport
+   drivers must read the HID report-descriptor from the device and tell HID core
+   about it via hid_parse_report().
+
+ - int (*power) (struct hid_device *hdev, int level)
+   Called by HID core to give PM hints to transport drivers. Usually this is
+   analogical to the ->open() and ->close() hints and redundant.
+
+ - void (*request) (struct hid_device *hdev, struct hid_report *report,
+                    int reqtype)
+   Send an HID request on the ctrl channel. "report" contains the report that
+   should be sent and "reqtype" the request type. Request-type can be
+   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
+   This callback is optional. If not provided, HID core will assemble a raw
+   report following the HID specs and send it via the ->raw_request() callback.
+   The transport driver is free to implement this asynchronously.
+
+ - int (*wait) (struct hid_device *hdev)
+   Used by HID core before calling ->request() again. A transport driver can use
+   it to wait for any pending requests to complete if only one request is
+   allowed at a time.
+
+ - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
+                       __u8 *buf, size_t count, unsigned char rtype,
+                       int reqtype)
+   Same as ->request() but provides the report as raw buffer. This request shall
+   be synchronous. A transport driver must not use ->wait() to complete such
+   requests. This request is mandatory and hid core will reject the device if
+   it is missing.
+
+ - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
+   Send raw output report via intr channel. Used by some HID device drivers
+   which require high throughput for outgoing requests on the intr channel. This
+   must not cause SET_REPORT calls! This must be implemented as asynchronous
+   output report on the intr channel!
+
+ - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
+   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
+
+2.3) Data Path
+--------------
+
+Transport drivers are responsible of reading data from I/O devices. They must
+handle any I/O-related state-tracking themselves. HID core does not implement
+protocol handshakes or other management commands which can be required by the
+given HID transport specification.
+
+Every raw data packet read from a device must be fed into HID core via
+hid_input_report(). You must specify the channel-type (intr or ctrl) and report
+type (input/output/feature). Under normal conditions, only input reports are
+provided via this API.
+
+Responses to GET_REPORT requests via ->request() must also be provided via this
+API. Responses to ->raw_request() are synchronous and must be intercepted by the
+transport driver and not passed to hid_input_report().
+Acknowledgements to SET_REPORT requests are not of interest to HID core.
+
+----------------------------------------------------
+Written 2013, David Herrmann <dh.herrmann@gmail.com>
diff --git a/Documentation/hwmon/adc128d818 b/Documentation/hwmon/adc128d818
new file mode 100644
index 000000000000..39c95004dabc
--- /dev/null
+++ b/Documentation/hwmon/adc128d818
@@ -0,0 +1,47 @@
+Kernel driver adc128d818
+========================
+
+Supported chips:
+  * Texas Instruments ADC818D818
+    Prefix: 'adc818d818'
+    Addresses scanned: I2C 0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f
+    Datasheet: Publicly available at the TI website
+               http://www.ti.com/
+
+Author: Guenter Roeck
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments ADC128D818.
+It is described as 'ADC System Monitor with Temperature Sensor'.
+
+The ADC128D818 implements one temperature sensor and seven voltage sensors.
+
+Temperatures are measured in degrees Celsius. There is one set of limits.
+When the HOT Temperature Limit is crossed, this will cause an alarm that will
+be reasserted until the temperature drops below the HOT Hysteresis.
+Measurements are guaranteed between -55 and +125 degrees. The temperature
+measurement has a resolution of 0.5 degrees; the limits have a resolution
+of 1 degree.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 2.55 volts, with a resolution
+of 0.625 mV.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared by the time the alarm is read. The driver
+caches the alarm status for each sensor until it is at least reported
+once, to ensure that alarms are reported to user space.
+
+The ADC128D818 only updates its values approximately once per second;
+reading it more often will do no harm, but will return 'old' values.
+
+In addition to the scanned address list, the chip can also be configured for
+addresses 0x35 to 0x37. Those addresses are not scanned. You have to instantiate
+the driver explicitly if the chip is configured for any of those addresses in
+your system.
diff --git a/Documentation/hwmon/lm95245 b/Documentation/hwmon/lm95245
index cbd8aeab7124..77eaf2812d25 100644
--- a/Documentation/hwmon/lm95245
+++ b/Documentation/hwmon/lm95245
@@ -24,8 +24,12 @@ is given within a range of -127 to +127.875 degrees. Remote temperatures are
 given within a range of -127 to +255 degrees. Resolution depends on
 temperature input and range.
 
-Each sensor has its own critical limit, but the hysteresis is common to all
-two channels.
+Each sensor has its own critical limit. Additionally, there is a relative
+hysteresis value common to both critical limits. To make life easier to
+user-space applications, two absolute values are exported, one for each
+channel, but these values are of course linked. Only the local hysteresis
+can be set from user-space, and the same delta applies to the remote
+hysteresis.
 
 The lm95245 driver can change its update interval to a fixed set of values.
 It will round up to the next selectable interval. See the datasheet for exact
diff --git a/Documentation/hwmon/ltc2945 b/Documentation/hwmon/ltc2945
new file mode 100644
index 000000000000..f8d0f7f19adb
--- /dev/null
+++ b/Documentation/hwmon/ltc2945
@@ -0,0 +1,84 @@
+Kernel driver ltc2945
+=====================
+
+Supported chips:
+  * Linear Technology LTC2945
+    Prefix: 'ltc2945'
+    Addresses scanned: -
+    Datasheet:
+        http://cds.linear.com/docs/en/datasheet/2945fa.pdf
+
+Author: Guenter Roeck <linux@roeck-us.net>
+
+
+Description
+-----------
+
+The LTC2945  is a rail-to-rail system monitor that measures current, voltage,
+and power consumption.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC2945 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC2945 at address 0x10
+on I2C bus #1:
+$ modprobe ltc2945
+$ echo ltc2945 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADC
+registers. If a set of voltage divider resistors is installed, calculate the
+real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
+value of the divider resistor against the measured voltage and R2 is the value
+of the divider resistor against Ground.
+
+Current reading provided by this driver is reported as obtained from the ADC
+Current Sense register. The reported value assumes that a 1 mOhm sense resistor
+is installed. If a different sense resistor is installed, calculate the real
+current by dividing the reported value by the sense resistor value in mOhm.
+
+in1_input		VIN voltage (mV). Voltage is measured either at
+			SENSE+ or VDD pin depending on chip configuration.
+in1_min			Undervoltage threshold
+in1_max			Overvoltage threshold
+in1_lowest		Lowest measured voltage
+in1_highest		Highest measured voltage
+in1_reset_history	Write 1 to reset in1 history
+in1_min_alarm		Undervoltage alarm
+in1_max_alarm		Overvoltage alarm
+
+in2_input		ADIN voltage (mV)
+in2_min			Undervoltage threshold
+in2_max			Overvoltage threshold
+in2_lowest		Lowest measured voltage
+in2_highest		Highest measured voltage
+in2_reset_history	Write 1 to reset in2 history
+in2_min_alarm		Undervoltage alarm
+in2_max_alarm		Overvoltage alarm
+
+curr1_input		SENSE current (mA)
+curr1_min		Undercurrent threshold
+curr1_max		Overcurrent threshold
+curr1_lowest		Lowest measured current
+curr1_highest		Highest measured current
+curr1_reset_history	Write 1 to reset curr1 history
+curr1_min_alarm		Undercurrent alarm
+curr1_max_alarm		Overcurrent alarm
+
+power1_input		Power (in uW). Power is calculated based on SENSE+/VDD
+			voltage or ADIN voltage depending on chip configuration.
+power1_min		Low lower threshold
+power1_max		High power threshold
+power1_input_lowest	Historical minimum power use
+power1_input_highest	Historical maximum power use
+power1_reset_history	Write 1 to reset power1 history
+power1_min_alarm	Low power alarm
+power1_max_alarm	High power alarm
diff --git a/Documentation/hwmon/ltc4260 b/Documentation/hwmon/ltc4260
new file mode 100644
index 000000000000..c4ff4ad998b2
--- /dev/null
+++ b/Documentation/hwmon/ltc4260
@@ -0,0 +1,56 @@
+Kernel driver ltc4260
+=====================
+
+Supported chips:
+  * Linear Technology LTC4260
+    Prefix: 'ltc4260'
+    Addresses scanned: -
+    Datasheet:
+        http://cds.linear.com/docs/en/datasheet/4260fc.pdf
+
+Author: Guenter Roeck <linux@roeck-us.net>
+
+
+Description
+-----------
+
+The LTC4260 Hot Swap controller allows a board to be safely inserted
+and removed from a live backplane.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4260 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4260 at address 0x10
+on I2C bus #1:
+$ modprobe ltc4260
+$ echo ltc4260 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADC
+registers. If a set of voltage divider resistors is installed, calculate the
+real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
+value of the divider resistor against the measured voltage and R2 is the value
+of the divider resistor against Ground.
+
+Current reading provided by this driver is reported as obtained from the ADC
+Current Sense register. The reported value assumes that a 1 mOhm sense resistor
+is installed. If a different sense resistor is installed, calculate the real
+current by dividing the reported value by the sense resistor value in mOhm.
+
+in1_input		SOURCE voltage (mV)
+in1_min_alarm		Undervoltage alarm
+in1_max_alarm		Overvoltage alarm
+
+in2_input		ADIN voltage (mV)
+in2_alarm		Power bad alarm
+
+curr1_input		SENSE current (mA)
+curr1_alarm		SENSE overcurrent alarm
diff --git a/Documentation/irqflags-tracing.txt b/Documentation/irqflags-tracing.txt
index 67aa71e73035..f6da05670e16 100644
--- a/Documentation/irqflags-tracing.txt
+++ b/Documentation/irqflags-tracing.txt
@@ -22,13 +22,6 @@ rather straightforward and risk-free manner.
 Architectures that want to support this need to do a couple of
 code-organizational changes first:
 
-- move their irq-flags manipulation code from their asm/system.h header
-  to asm/irqflags.h
-
-- rename local_irq_disable()/etc to raw_local_irq_disable()/etc. so that
-  the linux/irqflags.h code can inject callbacks and can construct the
-  real local_irq_disable()/etc APIs.
-
 - add and enable TRACE_IRQFLAGS_SUPPORT in their arch level Kconfig file
 
 and then a couple of functional changes are needed as well to implement
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index c420676c6fe3..350f733bf2c7 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -157,6 +157,10 @@ applicable everywhere (see syntax).
     to the build environment (if this is desired, it can be done via
     another symbol).
 
+  - "allnoconfig_y"
+    This declares the symbol as one that should have the value y when
+    using "allnoconfig". Used for symbols that hide other symbols.
+
 Menu dependencies
 -----------------
 
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 7116fda7077f..88e5905bfc82 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -231,6 +231,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	acpi_no_auto_ssdt	[HW,ACPI] Disable automatic loading of SSDT
 
+	acpica_no_return_repair [HW, ACPI]
+			Disable AML predefined validation mechanism
+			This mechanism can repair the evaluation result to make
+			the return objects more ACPI specification compliant.
+			This option is useful for developers to identify the
+			root cause of an AML interpreter issue when the issue
+			has something to do with the repair mechanism.
+
 	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
 			Format: To spoof as Windows 98: ="Microsoft Windows"
 
@@ -2053,8 +2061,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			IOAPICs that may be present in the system.
 
 	nokaslr		[X86]
-			Disable kernel base offset ASLR (Address Space
-			Layout Randomization) if built into the kernel.
+			Disable kernel and module base offset ASLR (Address
+			Space Layout Randomization) if built into the kernel.
 
 	noautogroup	Disable scheduler automatic task group creation.
 
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index 827104fb9364..f3cd299fcc41 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -162,7 +162,18 @@ Purpose: Execute workqueue requests
 To reduce its OS jitter, do any of the following:
 1.	Run your workload at a real-time priority, which will allow
 	preempting the kworker daemons.
-2.	Do any of the following needed to avoid jitter that your
+2.	A given workqueue can be made visible in the sysfs filesystem
+	by passing the WQ_SYSFS to that workqueue's alloc_workqueue().
+	Such a workqueue can be confined to a given subset of the
+	CPUs using the /sys/devices/virtual/workqueue/*/cpumask sysfs
+	files.	The set of WQ_SYSFS workqueues can be displayed using
+	"ls sys/devices/virtual/workqueue".  That said, the workqueues
+	maintainer would like to caution people against indiscriminately
+	sprinkling WQ_SYSFS across all the workqueues.	The reason for
+	caution is that it is easy to add WQ_SYSFS, but because sysfs is
+	part of the formal user/kernel API, it can be nearly impossible
+	to remove it, even if its addition was a mistake.
+3.	Do any of the following needed to avoid jitter that your
 	application cannot tolerate:
 	a.	Build your kernel with CONFIG_SLUB=y rather than
 		CONFIG_SLAB=y, thus avoiding the slab allocator's periodic
diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt
index b6e39739a36d..6dc801365543 100644
--- a/Documentation/kmemleak.txt
+++ b/Documentation/kmemleak.txt
@@ -11,9 +11,7 @@ with the difference that the orphan objects are not freed but only
 reported via /sys/kernel/debug/kmemleak. A similar method is used by the
 Valgrind tool (memcheck --leak-check) to detect the memory leaks in
 user-space applications.
-
-Please check DEBUG_KMEMLEAK dependencies in lib/Kconfig.debug for supported
-architectures.
+Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze, ppc, mips, s390, metag and tile.
 
 Usage
 -----
@@ -68,7 +66,7 @@ Basic Algorithm
 
 The memory allocations via kmalloc, vmalloc, kmem_cache_alloc and
 friends are traced and the pointers, together with additional
-information like size and stack trace, are stored in a prio search tree.
+information like size and stack trace, are stored in a rbtree.
 The corresponding freeing function calls are tracked and the pointers
 removed from the kmemleak data structures.
 
@@ -84,7 +82,7 @@ The scanning algorithm steps:
   1. mark all objects as white (remaining white objects will later be
      considered orphan)
   2. scan the memory starting with the data section and stacks, checking
-     the values against the addresses stored in the prio search tree. If
+     the values against the addresses stored in the rbtree. If
      a pointer to a white object is found, the object is added to the
      gray list
   3. scan the gray objects for matching addresses (some white objects
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/memory-barriers.txt b/Documentation/memory-barriers.txt
index 102dc19c4119..11c1d2049662 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -608,26 +608,30 @@ as follows:
 	b = p;  /* BUG: Compiler can reorder!!! */
 	do_something();
 
-The solution is again ACCESS_ONCE(), which preserves the ordering between
-the load from variable 'a' and the store to variable 'b':
+The solution is again ACCESS_ONCE() and barrier(), which preserves the
+ordering between the load from variable 'a' and the store to variable 'b':
 
 	q = ACCESS_ONCE(a);
 	if (q) {
+		barrier();
 		ACCESS_ONCE(b) = p;
 		do_something();
 	} else {
+		barrier();
 		ACCESS_ONCE(b) = p;
 		do_something_else();
 	}
 
-You could also use barrier() to prevent the compiler from moving
-the stores to variable 'b', but barrier() would not prevent the
-compiler from proving to itself that a==1 always, so ACCESS_ONCE()
-is also needed.
+The initial ACCESS_ONCE() is required to prevent the compiler from
+proving the value of 'a', and the pair of barrier() invocations are
+required to prevent the compiler from pulling the two identical stores
+to 'b' out from the legs of the "if" statement.
 
 It is important to note that control dependencies absolutely require a
 a conditional.  For example, the following "optimized" version of
-the above example breaks ordering:
+the above example breaks ordering, which is why the barrier() invocations
+are absolutely required if you have identical stores in both legs of
+the "if" statement:
 
 	q = ACCESS_ONCE(a);
 	ACCESS_ONCE(b) = p;  /* BUG: No ordering vs. load from a!!! */
@@ -643,9 +647,11 @@ It is of course legal for the prior load to be part of the conditional,
 for example, as follows:
 
 	if (ACCESS_ONCE(a) > 0) {
+		barrier();
 		ACCESS_ONCE(b) = q / 2;
 		do_something();
 	} else {
+		barrier();
 		ACCESS_ONCE(b) = q / 3;
 		do_something_else();
 	}
@@ -659,9 +665,11 @@ the needed conditional.  For example:
 
 	q = ACCESS_ONCE(a);
 	if (q % MAX) {
+		barrier();
 		ACCESS_ONCE(b) = p;
 		do_something();
 	} else {
+		barrier();
 		ACCESS_ONCE(b) = p;
 		do_something_else();
 	}
@@ -723,8 +731,13 @@ In summary:
       use smb_rmb(), smp_wmb(), or, in the case of prior stores and
       later loads, smp_mb().
 
+  (*) If both legs of the "if" statement begin with identical stores
+      to the same variable, a barrier() statement is required at the
+      beginning of each leg of the "if" statement.
+
   (*) Control dependencies require at least one run-time conditional
-      between the prior load and the subsequent store.  If the compiler
+      between the prior load and the subsequent store, and this
+      conditional must involve the prior load.  If the compiler
       is able to optimize the conditional away, it will have also
       optimized away the ordering.  Careful use of ACCESS_ONCE() can
       help to preserve the needed conditional.
@@ -1249,6 +1262,23 @@ The ACCESS_ONCE() function can prevent any number of optimizations that,
 while perfectly safe in single-threaded code, can be fatal in concurrent
 code.  Here are some examples of these sorts of optimizations:
 
+ (*) The compiler is within its rights to reorder loads and stores
+     to the same variable, and in some cases, the CPU is within its
+     rights to reorder loads to the same variable.  This means that
+     the following code:
+
+	a[0] = x;
+	a[1] = x;
+
+     Might result in an older value of x stored in a[1] than in a[0].
+     Prevent both the compiler and the CPU from doing this as follows:
+
+	a[0] = ACCESS_ONCE(x);
+	a[1] = ACCESS_ONCE(x);
+
+     In short, ACCESS_ONCE() provides cache coherence for accesses from
+     multiple CPUs to a single variable.
+
  (*) The compiler is within its rights to merge successive loads from
      the same variable.  Such merging can cause the compiler to "optimize"
      the following code:
@@ -1644,12 +1674,12 @@ for each construct.  These operations all imply certain barriers:
      Memory operations issued after the ACQUIRE will be completed after the
      ACQUIRE operation has completed.
 
-     Memory operations issued before the ACQUIRE may be completed after the
-     ACQUIRE operation has completed.  An smp_mb__before_spinlock(), combined
-     with a following ACQUIRE, orders prior loads against subsequent stores and
-     stores and prior stores against subsequent stores.  Note that this is
-     weaker than smp_mb()!  The smp_mb__before_spinlock() primitive is free on
-     many architectures.
+     Memory operations issued before the ACQUIRE may be completed after
+     the ACQUIRE operation has completed.  An smp_mb__before_spinlock(),
+     combined with a following ACQUIRE, orders prior loads against
+     subsequent loads and stores and also orders prior stores against
+     subsequent stores.  Note that this is weaker than smp_mb()!  The
+     smp_mb__before_spinlock() primitive is free on many architectures.
 
  (2) RELEASE operation implication:
 
@@ -1694,24 +1724,21 @@ may occur as:
 
 	ACQUIRE M, STORE *B, STORE *A, RELEASE M
 
-This same reordering can of course occur if the lock's ACQUIRE and RELEASE are
-to the same lock variable, but only from the perspective of another CPU not
-holding that lock.
-
-In short, a RELEASE followed by an ACQUIRE may -not- be assumed to be a full
-memory barrier because it is possible for a preceding RELEASE to pass a
-later ACQUIRE from the viewpoint of the CPU, but not from the viewpoint
-of the compiler.  Note that deadlocks cannot be introduced by this
-interchange because if such a deadlock threatened, the RELEASE would
-simply complete.
-
-If it is necessary for a RELEASE-ACQUIRE pair to produce a full barrier, the
-ACQUIRE can be followed by an smp_mb__after_unlock_lock() invocation.  This
-will produce a full barrier if either (a) the RELEASE and the ACQUIRE are
-executed by the same CPU or task, or (b) the RELEASE and ACQUIRE act on the
-same variable.  The smp_mb__after_unlock_lock() primitive is free on many
-architectures.  Without smp_mb__after_unlock_lock(), the critical sections
-corresponding to the RELEASE and the ACQUIRE can cross:
+When the ACQUIRE and RELEASE are a lock acquisition and release,
+respectively, this same reordering can occur if the lock's ACQUIRE and
+RELEASE are to the same lock variable, but only from the perspective of
+another CPU not holding that lock.  In short, a ACQUIRE followed by an
+RELEASE may -not- be assumed to be a full memory barrier.
+
+Similarly, the reverse case of a RELEASE followed by an ACQUIRE does not
+imply a full memory barrier.  If it is necessary for a RELEASE-ACQUIRE
+pair to produce a full barrier, the ACQUIRE can be followed by an
+smp_mb__after_unlock_lock() invocation.  This will produce a full barrier
+if either (a) the RELEASE and the ACQUIRE are executed by the same
+CPU or task, or (b) the RELEASE and ACQUIRE act on the same variable.
+The smp_mb__after_unlock_lock() primitive is free on many architectures.
+Without smp_mb__after_unlock_lock(), the CPU's execution of the critical
+sections corresponding to the RELEASE and the ACQUIRE can cross, so that:
 
 	*A = a;
 	RELEASE M
@@ -1722,7 +1749,36 @@ could occur as:
 
 	ACQUIRE N, STORE *B, STORE *A, RELEASE M
 
-With smp_mb__after_unlock_lock(), they cannot, so that:
+It might appear that this reordering could introduce a deadlock.
+However, this cannot happen because if such a deadlock threatened,
+the RELEASE would simply complete, thereby avoiding the deadlock.
+
+	Why does this work?
+
+	One key point is that we are only talking about the CPU doing
+	the reordering, not the compiler.  If the compiler (or, for
+	that matter, the developer) switched the operations, deadlock
+	-could- occur.
+
+	But suppose the CPU reordered the operations.  In this case,
+	the unlock precedes the lock in the assembly code.  The CPU
+	simply elected to try executing the later lock operation first.
+	If there is a deadlock, this lock operation will simply spin (or
+	try to sleep, but more on that later).	The CPU will eventually
+	execute the unlock operation (which preceded the lock operation
+	in the assembly code), which will unravel the potential deadlock,
+	allowing the lock operation to succeed.
+
+	But what if the lock is a sleeplock?  In that case, the code will
+	try to enter the scheduler, where it will eventually encounter
+	a memory barrier, which will force the earlier unlock operation
+	to complete, again unraveling the deadlock.  There might be
+	a sleep-unlock race, but the locking primitive needs to resolve
+	such races properly in any case.
+
+With smp_mb__after_unlock_lock(), the two critical sections cannot overlap.
+For example, with the following code, the store to *A will always be
+seen by other CPUs before the store to *B:
 
 	*A = a;
 	RELEASE M
@@ -1730,13 +1786,18 @@ With smp_mb__after_unlock_lock(), they cannot, so that:
 	smp_mb__after_unlock_lock();
 	*B = b;
 
-will always occur as either of the following:
+The operations will always occur in one of the following orders:
 
-	STORE *A, RELEASE, ACQUIRE, STORE *B
-	STORE *A, ACQUIRE, RELEASE, STORE *B
+	STORE *A, RELEASE, ACQUIRE, smp_mb__after_unlock_lock(), STORE *B
+	STORE *A, ACQUIRE, RELEASE, smp_mb__after_unlock_lock(), STORE *B
+	ACQUIRE, STORE *A, RELEASE, smp_mb__after_unlock_lock(), STORE *B
 
 If the RELEASE and ACQUIRE were instead both operating on the same lock
-variable, only the first of these two alternatives can occur.
+variable, only the first of these alternatives can occur.  In addition,
+the more strongly ordered systems may rule out some of the above orders.
+But in any case, as noted earlier, the smp_mb__after_unlock_lock()
+ensures that the store to *A will always be seen as happening before
+the store to *B.
 
 Locks and semaphores may not provide any guarantee of ordering on UP compiled
 systems, and so cannot be counted on in such a situation to actually achieve
@@ -2757,7 +2818,7 @@ in that order, but, without intervention, the sequence may have almost any
 combination of elements combined or discarded, provided the program's view of
 the world remains consistent.  Note that ACCESS_ONCE() is -not- optional
 in the above example, as there are architectures where a given CPU might
-interchange successive loads to the same location.  On such architectures,
+reorder successive loads to the same location.  On such architectures,
 ACCESS_ONCE() does whatever is necessary to prevent this, for example, on
 Itanium the volatile casts used by ACCESS_ONCE() cause GCC to emit the
 special ld.acq and st.rel instructions that prevent such reordering.
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
index 2b40e04d3c49..09b583e38907 100644
--- a/Documentation/module-signing.txt
+++ b/Documentation/module-signing.txt
@@ -77,11 +77,11 @@ This has a number of options available:
      This presents a choice of which hash algorithm the installation phase will
      sign the modules with:
 
-	CONFIG_SIG_SHA1		"Sign modules with SHA-1"
-	CONFIG_SIG_SHA224	"Sign modules with SHA-224"
-	CONFIG_SIG_SHA256	"Sign modules with SHA-256"
-	CONFIG_SIG_SHA384	"Sign modules with SHA-384"
-	CONFIG_SIG_SHA512	"Sign modules with SHA-512"
+	CONFIG_MODULE_SIG_SHA1		"Sign modules with SHA-1"
+	CONFIG_MODULE_SIG_SHA224	"Sign modules with SHA-224"
+	CONFIG_MODULE_SIG_SHA256	"Sign modules with SHA-256"
+	CONFIG_MODULE_SIG_SHA384	"Sign modules with SHA-384"
+	CONFIG_MODULE_SIG_SHA512	"Sign modules with SHA-512"
 
      The algorithm selected here will also be built into the kernel (rather
      than being a module) so that modules signed with that algorithm can have
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 5cdb22971d19..a383c00392d0 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -270,16 +270,15 @@ arp_ip_target
 arp_validate
 
 	Specifies whether or not ARP probes and replies should be
-	validated in the active-backup mode.  This causes the ARP
-	monitor to examine the incoming ARP requests and replies, and
-	only consider a slave to be up if it is receiving the
-	appropriate ARP traffic.
+	validated in any mode that supports arp monitoring, or whether
+	non-ARP traffic should be filtered (disregarded) for link
+	monitoring purposes.
 
 	Possible values are:
 
 	none or 0
 
-		No validation is performed.  This is the default.
+		No validation or filtering is performed.
 
 	active or 1
 
@@ -293,31 +292,68 @@ arp_validate
 
 		Validation is performed for all slaves.
 
-	For the active slave, the validation checks ARP replies to
-	confirm that they were generated by an arp_ip_target.  Since
-	backup slaves do not typically receive these replies, the
-	validation performed for backup slaves is on the ARP request
-	sent out via the active slave.  It is possible that some
-	switch or network configurations may result in situations
-	wherein the backup slaves do not receive the ARP requests; in
-	such a situation, validation of backup slaves must be
-	disabled.
-
-	The validation of ARP requests on backup slaves is mainly
-	helping bonding to decide which slaves are more likely to
-	work in case of the active slave failure, it doesn't really
-	guarantee that the backup slave will work if it's selected
-	as the next active slave.
-
-	This option is useful in network configurations in which
-	multiple bonding hosts are concurrently issuing ARPs to one or
-	more targets beyond a common switch.  Should the link between
-	the switch and target fail (but not the switch itself), the
-	probe traffic generated by the multiple bonding instances will
-	fool the standard ARP monitor into considering the links as
-	still up.  Use of the arp_validate option can resolve this, as
-	the ARP monitor will only consider ARP requests and replies
-	associated with its own instance of bonding.
+	filter or 4
+
+		Filtering is applied to all slaves. No validation is
+		performed.
+
+	filter_active or 5
+
+		Filtering is applied to all slaves, validation is performed
+		only for the active slave.
+
+	filter_backup or 6
+
+		Filtering is applied to all slaves, validation is performed
+		only for backup slaves.
+
+	Validation:
+
+	Enabling validation causes the ARP monitor to examine the incoming
+	ARP requests and replies, and only consider a slave to be up if it
+	is receiving the appropriate ARP traffic.
+
+	For an active slave, the validation checks ARP replies to confirm
+	that they were generated by an arp_ip_target.  Since backup slaves
+	do not typically receive these replies, the validation performed
+	for backup slaves is on the broadcast ARP request sent out via the
+	active slave.  It is possible that some switch or network
+	configurations may result in situations wherein the backup slaves
+	do not receive the ARP requests; in such a situation, validation
+	of backup slaves must be disabled.
+
+	The validation of ARP requests on backup slaves is mainly helping
+	bonding to decide which slaves are more likely to work in case of
+	the active slave failure, it doesn't really guarantee that the
+	backup slave will work if it's selected as the next active slave.
+
+	Validation is useful in network configurations in which multiple
+	bonding hosts are concurrently issuing ARPs to one or more targets
+	beyond a common switch.  Should the link between the switch and
+	target fail (but not the switch itself), the probe traffic
+	generated by the multiple bonding instances will fool the standard
+	ARP monitor into considering the links as still up.  Use of
+	validation can resolve this, as the ARP monitor will only consider
+	ARP requests and replies associated with its own instance of
+	bonding.
+
+	Filtering:
+
+	Enabling filtering causes the ARP monitor to only use incoming ARP
+	packets for link availability purposes.  Arriving packets that are
+	not ARPs are delivered normally, but do not count when determining
+	if a slave is available.
+
+	Filtering operates by only considering the reception of ARP
+	packets (any ARP packet, regardless of source or destination) when
+	determining if a slave has received traffic for link availability
+	purposes.
+
+	Filtering is useful in network configurations in which significant
+	levels of third party broadcast traffic would fool the standard
+	ARP monitor into considering the links as still up.  Use of
+	filtering can resolve this, as only ARP traffic is considered for
+	link availability purposes.
 
 	This option was added in bonding version 3.1.0.
 
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index f3089d423515..0cbe6ec22d6f 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -554,12 +554,6 @@ solution for a couple of reasons:
   not specified in the struct can_frame and therefore it is only valid in
   CANFD_MTU sized CAN FD frames.
 
-  As long as the payload length is <=8 the received CAN frames from CAN FD
-  capable CAN devices can be received and read by legacy sockets too. When
-  user-generated CAN FD frames have a payload length <=8 these can be send
-  by legacy CAN network interfaces too. Sending CAN FD frames with payload
-  length > 8 to a legacy CAN network interface returns an -EMSGSIZE error.
-
   Implementation hint for new CAN applications:
 
   To build a CAN FD aware application use struct canfd_frame as basic CAN
diff --git a/Documentation/networking/gianfar.txt b/Documentation/networking/gianfar.txt
index ad474ea07d07..ba1daea7f2e4 100644
--- a/Documentation/networking/gianfar.txt
+++ b/Documentation/networking/gianfar.txt
@@ -1,38 +1,8 @@
 The Gianfar Ethernet Driver
-Sysfs File description
 
 Author: Andy Fleming <afleming@freescale.com>
 Updated: 2005-07-28
 
-SYSFS
-
-Several of the features of the gianfar driver are controlled
-through sysfs files.  These are:
-
-bd_stash:
-To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
-bd_stash, echo 'off' or '0' to disable
-
-rx_stash_len:
-To stash the first n bytes of the packet in L2, echo the number
-of bytes to buf_stash_len.  echo 0 to disable.
-
-WARNING: You could really screw these up if you set them too low or high!
-fifo_threshold:
-To change the number of bytes the controller needs in the
-fifo before it starts transmission, echo the number of bytes to 
-fifo_thresh.  Range should be 0-511.
-
-fifo_starve:
-When the FIFO has less than this many bytes during a transmit, it
-enters starve mode, and increases the priority of TX memory
-transactions.  To change, echo the number of bytes to
-fifo_starve.  Range should be 0-511.
-
-fifo_starve_off:
-Once in starve mode, the FIFO remains there until it has this
-many bytes.  To change, echo the number of bytes to
-fifo_starve_off.  Range should be 0-511.
 
 CHECKSUM OFFLOADING
 
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index ebf270719402..e602c6f347df 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -253,16 +253,25 @@ Writing a PHY driver
 
  Each driver consists of a number of function pointers:
 
+   soft_reset: perform a PHY software reset
    config_init: configures PHY into a sane state after a reset.
      For instance, a Davicom PHY requires descrambling disabled.
    probe: Allocate phy->priv, optionally refuse to bind.
    PHY may not have been reset or had fixups run yet.
    suspend/resume: power management
    config_aneg: Changes the speed/duplex/negotiation settings
+   aneg_done: Determines the auto-negotiation result
    read_status: Reads the current speed/duplex/negotiation settings
    ack_interrupt: Clear a pending interrupt
+   did_interrupt: Checks if the PHY generated an interrupt
    config_intr: Enable or disable interrupts
    remove: Does any driver take-down
+   ts_info: Queries about the HW timestamping status
+   hwtstamp: Set the PHY HW timestamping configuration
+   rxtstamp: Requests a receive timestamp at the PHY level for a 'skb'
+   txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
+   set_wol: Enable Wake-on-LAN at the PHY level
+   get_wol: Get the Wake-on-LAN status at the PHY level
 
  Of these, only config_aneg and read_status are required to be
  assigned by the driver code.  The rest are optional.  Also, it is
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index 5a61a240a652..0e30c7845b2b 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -102,13 +102,18 @@ Examples:
                          The 'minimum' MAC is what you set with dstmac.
 
  pgset "flag [name]"     Set a flag to determine behaviour.  Current flags
-                         are: IPSRC_RND #IP Source is random (between min/max),
-                              IPDST_RND, UDPSRC_RND,
-                              UDPDST_RND, MACSRC_RND, MACDST_RND 
+                         are: IPSRC_RND # IP source is random (between min/max)
+                              IPDST_RND # IP destination is random
+                              UDPSRC_RND, UDPDST_RND,
+                              MACSRC_RND, MACDST_RND
+                              TXSIZE_RND, IPV6,
                               MPLS_RND, VID_RND, SVID_RND
+                              FLOW_SEQ,
                               QUEUE_MAP_RND # queue map random
                               QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
-                              IPSEC # Make IPsec encapsulation for packet
+                              UDPCSUM,
+                              IPSEC # IPsec encapsulation (needs CONFIG_XFRM)
+                              NODE_ALLOC # node specific memory allocation
 
  pgset spi SPI_VALUE     Set specific SA used to transform packet.
 
@@ -233,13 +238,22 @@ udp_dst_max
 
 flag
   IPSRC_RND
-  TXSIZE_RND
   IPDST_RND
   UDPSRC_RND
   UDPDST_RND
   MACSRC_RND
   MACDST_RND
+  TXSIZE_RND
+  IPV6
+  MPLS_RND
+  VID_RND
+  SVID_RND
+  FLOW_SEQ
+  QUEUE_MAP_RND
+  QUEUE_MAP_CPU
+  UDPCSUM
   IPSEC
+  NODE_ALLOC
 
 dst_min
 dst_max
diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt
index 7d11bb5dc30a..bdc4c0db51e1 100644
--- a/Documentation/networking/tcp.txt
+++ b/Documentation/networking/tcp.txt
@@ -30,7 +30,7 @@ A congestion control mechanism can be registered through functions in
 tcp_cong.c. The functions used by the congestion control mechanism are
 registered via passing a tcp_congestion_ops struct to
 tcp_register_congestion_control. As a minimum name, ssthresh,
-cong_avoid, min_cwnd must be valid.
+cong_avoid must be valid.
 
 Private data for a congestion control mechanism is stored in tp->ca_priv.
 tcp_ca(tp) returns a pointer to this space.  This is preallocated space - it
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index 483632087788..a5da5c7e7128 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -88,17 +88,19 @@ node.
 
 2. PM QoS per-device latency and flags framework
 
-For each device, there are two lists of PM QoS requests. One is maintained
-along with the aggregated target of latency value and the other is for PM QoS
-flags. Values are updated in response to changes of the request list.
+For each device, there are three lists of PM QoS requests. Two of them are
+maintained along with the aggregated targets of resume latency and active
+state latency tolerance (in microseconds) and the third one is for PM QoS flags.
+Values are updated in response to changes of the request list.
 
-Target latency value is simply the minimum of the request values held in the
-parameter list elements.  The PM QoS flags aggregate value is a gather (bitwise
-OR) of all list elements' values. Two device PM QoS flags are defined currently:
-PM_QOS_FLAG_NO_POWER_OFF and PM_QOS_FLAG_REMOTE_WAKEUP.
+The target values of resume latency and active state latency tolerance are
+simply the minimum of the request values held in the parameter list elements.
+The PM QoS flags aggregate value is a gather (bitwise OR) of all list elements'
+values.  Two device PM QoS flags are defined currently: PM_QOS_FLAG_NO_POWER_OFF
+and PM_QOS_FLAG_REMOTE_WAKEUP.
 
-Note: the aggregated target value is implemented as an atomic variable so that
-reading the aggregated value does not require any locking mechanism.
+Note: The aggregated target values are implemented in such a way that reading
+the aggregated value does not require any locking mechanism.
 
 
 From kernel mode the use of this interface is the following:
@@ -132,19 +134,21 @@ The meaning of the return values is as follows:
 	PM_QOS_FLAGS_UNDEFINED: The device's PM QoS structure has not been
 			initialized or the list of requests is empty.
 
-int dev_pm_qos_add_ancestor_request(dev, handle, value)
+int dev_pm_qos_add_ancestor_request(dev, handle, type, value)
 Add a PM QoS request for the first direct ancestor of the given device whose
-power.ignore_children flag is unset.
+power.ignore_children flag is unset (for DEV_PM_QOS_RESUME_LATENCY requests)
+or whose power.set_latency_tolerance callback pointer is not NULL (for
+DEV_PM_QOS_LATENCY_TOLERANCE requests).
 
 int dev_pm_qos_expose_latency_limit(device, value)
-Add a request to the device's PM QoS list of latency constraints and create
-a sysfs attribute pm_qos_resume_latency_us under the device's power directory
-allowing user space to manipulate that request.
+Add a request to the device's PM QoS list of resume latency constraints and
+create a sysfs attribute pm_qos_resume_latency_us under the device's power
+directory allowing user space to manipulate that request.
 
 void dev_pm_qos_hide_latency_limit(device)
 Drop the request added by dev_pm_qos_expose_latency_limit() from the device's
-PM QoS list of latency constraints and remove sysfs attribute pm_qos_resume_latency_us
-from the device's power directory.
+PM QoS list of resume latency constraints and remove sysfs attribute
+pm_qos_resume_latency_us from the device's power directory.
 
 int dev_pm_qos_expose_flags(device, value)
 Add a request to the device's PM QoS list of flags and create sysfs attributes
@@ -163,7 +167,7 @@ a per-device notification tree and a global notification tree.
 int dev_pm_qos_add_notifier(device, notifier):
 Adds a notification callback function for the device.
 The callback is called when the aggregated value of the device constraints list
-is changed.
+is changed (for resume latency device PM QoS only).
 
 int dev_pm_qos_remove_notifier(device, notifier):
 Removes the notification callback function for the device.
@@ -171,14 +175,48 @@ Removes the notification callback function for the device.
 int dev_pm_qos_add_global_notifier(notifier):
 Adds a notification callback function in the global notification tree of the
 framework.
-The callback is called when the aggregated value for any device is changed.
+The callback is called when the aggregated value for any device is changed
+(for resume latency device PM QoS only).
 
 int dev_pm_qos_remove_global_notifier(notifier):
 Removes the notification callback function from the global notification tree
 of the framework.
 
 
-From user mode:
-No API for user space access to the per-device latency constraints is provided
-yet - still under discussion.
-
+Active state latency tolerance
+
+This device PM QoS type is used to support systems in which hardware may switch
+to energy-saving operation modes on the fly.  In those systems, if the operation
+mode chosen by the hardware attempts to save energy in an overly aggressive way,
+it may cause excess latencies to be visible to software, causing it to miss
+certain protocol requirements or target frame or sample rates etc.
+
+If there is a latency tolerance control mechanism for a given device available
+to software, the .set_latency_tolerance callback in that device's dev_pm_info
+structure should be populated.  The routine pointed to by it is should implement
+whatever is necessary to transfer the effective requirement value to the
+hardware.
+
+Whenever the effective latency tolerance changes for the device, its
+.set_latency_tolerance() callback will be executed and the effective value will
+be passed to it.  If that value is negative, which means that the list of
+latency tolerance requirements for the device is empty, the callback is expected
+to switch the underlying hardware latency tolerance control mechanism to an
+autonomous mode if available.  If that value is PM_QOS_LATENCY_ANY, in turn, and
+the hardware supports a special "no requirement" setting, the callback is
+expected to use it.  That allows software to prevent the hardware from
+automatically updating the device's latency tolerance in response to its power
+state changes (e.g. during transitions from D3cold to D0), which generally may
+be done in the autonomous latency tolerance control mode.
+
+If .set_latency_tolerance() is present for the device, sysfs attribute
+pm_qos_latency_tolerance_us will be present in the devivce's power directory.
+Then, user space can use that attribute to specify its latency tolerance
+requirement for the device, if any.  Writing "any" to it means "no requirement,
+but do not let the hardware control latency tolerance" and writing "auto" to it
+allows the hardware to be switched to the autonomous mode if there are no other
+requirements from the kernel side in the device's list.
+
+Kernel code can use the functions described above along with the
+DEV_PM_QOS_LATENCY_TOLERANCE device PM QoS type to add, remove and update
+latency tolerance requirements for devices.
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/rapidio/sysfs.txt b/Documentation/rapidio/sysfs.txt
index 271438c0617f..47ce9a5336e1 100644
--- a/Documentation/rapidio/sysfs.txt
+++ b/Documentation/rapidio/sysfs.txt
@@ -2,8 +2,8 @@
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-1. Device Subdirectories
-------------------------
+1. RapidIO Device Subdirectories
+--------------------------------
 
 For each RapidIO device, the RapidIO subsystem creates files in an individual
 subdirectory with the following name, /sys/bus/rapidio/devices/<device_name>.
@@ -25,8 +25,8 @@ seen by the enumerating host (destID = 1):
 NOTE: An enumerating or discovering endpoint does not create a sysfs entry for
 itself, this is why an endpoint with destID=1 is not shown in the list.
 
-2. Attributes Common for All Devices
-------------------------------------
+2. Attributes Common for All RapidIO Devices
+--------------------------------------------
 
 Each device subdirectory contains the following informational read-only files:
 
@@ -52,16 +52,16 @@ This attribute is similar in behavior to the "config" attribute of PCI devices
 and provides an access to the RapidIO device registers using standard file read
 and write operations.
 
-3. Endpoint Device Attributes
------------------------------
+3. RapidIO Endpoint Device Attributes
+-------------------------------------
 
 Currently Linux RapidIO subsystem does not create any endpoint specific sysfs
 attributes. It is possible that RapidIO master port drivers and endpoint device
 drivers will add their device-specific sysfs attributes but such attributes are
 outside the scope of this document.
 
-4. Switch Device Attributes
----------------------------
+4. RapidIO Switch Device Attributes
+-----------------------------------
 
 RapidIO switches have additional attributes in sysfs. RapidIO subsystem supports
 common and device-specific sysfs attributes for switches. Because switches are
@@ -106,3 +106,53 @@ attribute:
 	 for that controller always will be 0.
 	 To initiate RapidIO enumeration/discovery on all available mports
 	 a user must write '-1' (or RIO_MPORT_ANY) into this attribute file.
+
+
+6. RapidIO Bus Controllers/Ports
+--------------------------------
+
+On-chip RapidIO controllers and PCIe-to-RapidIO bridges (referenced as
+"Master Port" or "mport") are presented in sysfs as the special class of
+devices: "rapidio_port".
+
+The /sys/class/rapidio_port subdirectory contains individual subdirectories
+named as "rapidioN" where N = mport ID registered with RapidIO subsystem.
+
+NOTE: An mport ID is not a RapidIO destination ID assigned to a given local
+mport device.
+
+Each mport device subdirectory in addition to standard entries contains the
+following device-specific attributes:
+
+   port_destid - reports RapidIO destination ID assigned to the given RapidIO
+                 mport device. If value 0xFFFFFFFF is returned this means that
+                 no valid destination ID have been assigned to the mport (yet).
+                 Normally, before enumeration/discovery have been executed only
+                 fabric enumerating mports have a valid destination ID assigned
+                 to them using "hdid=..." rapidio module parameter.
+      sys_size - reports RapidIO common transport system size:
+                   0 = small (8-bit destination ID, max. 256 devices),
+                   1 = large (16-bit destination ID, max. 65536 devices).
+
+After enumeration or discovery was performed for a given mport device,
+the corresponding subdirectory will also contain subdirectories for each
+child RapidIO device connected to the mport. Naming conventions for RapidIO
+devices are described in Section 1 above.
+
+The example below shows mport device subdirectory with several child RapidIO
+devices attached to it.
+
+[rio@rapidio ~]$ ls /sys/class/rapidio_port/rapidio0/ -l
+total 0
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0001
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0004
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:e:0007
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0002
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0003
+drwxr-xr-x 3 root root    0 Feb 11 15:10 00:s:0005
+lrwxrwxrwx 1 root root    0 Feb 11 15:11 device -> ../../../0000:01:00.0
+-r--r--r-- 1 root root 4096 Feb 11 15:11 port_destid
+drwxr-xr-x 2 root root    0 Feb 11 15:11 power
+lrwxrwxrwx 1 root root    0 Feb 11 15:04 subsystem -> ../../../../../../class/rapidio_port
+-r--r--r-- 1 root root 4096 Feb 11 15:11 sys_size
+-rw-r--r-- 1 root root 4096 Feb 11 15:04 uevent
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index 9290de703450..a2f27bbf2cba 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -8,7 +8,7 @@ Context switch
 By default, the switch_to arch function is called with the runqueue
 locked. This is usually not a problem unless switch_to may need to
 take the runqueue lock. This is usually due to a wake up operation in
-the context switch. See arch/ia64/include/asm/system.h for an example.
+the context switch. See arch/ia64/include/asm/switch_to.h for an example.
 
 To request the scheduler call switch_to with the runqueue unlocked,
 you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file
diff --git a/Documentation/sgi-visws.txt b/Documentation/sgi-visws.txt
deleted file mode 100644
index 7ff0811ca2ba..000000000000
--- a/Documentation/sgi-visws.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-The SGI Visual Workstations (models 320 and 540) are based around
-the Cobalt, Lithium, and Arsenic ASICs.  The Cobalt ASIC is the
-main system ASIC which interfaces the 1-4 IA32 cpus, the memory
-system, and the I/O system in the Lithium ASIC.  The Cobalt ASIC
-also contains the 3D gfx rendering engine which renders to main
-system memory -- part of which is used as the frame buffer which
-is DMA'ed to a video connector using the Arsenic ASIC.  A PIIX4
-chip and NS87307 are used to provide legacy device support (IDE,
-serial, floppy, and parallel).
-
-The Visual Workstation chipset largely conforms to the PC architecture
-with some notable exceptions such as interrupt handling.
diff --git a/Documentation/sound/oss/vwsnd b/Documentation/sound/oss/vwsnd
deleted file mode 100644
index 4c6cbdb3c548..000000000000
--- a/Documentation/sound/oss/vwsnd
+++ /dev/null
@@ -1,293 +0,0 @@
-vwsnd - Sound driver for the Silicon Graphics 320 and 540 Visual
-Workstations' onboard audio.
-
-Copyright 1999 Silicon Graphics, Inc.  All rights reserved.
-
-
-At the time of this writing, March 1999, there are two models of
-Visual Workstation, the 320 and the 540.  This document only describes
-those models.  Future Visual Workstation models may have different
-sound capabilities, and this driver will probably not work on those
-boxes.
-
-The Visual Workstation has an Analog Devices AD1843 "SoundComm" audio
-codec chip.  The AD1843 is accessed through the Cobalt I/O ASIC, also
-known as Lithium.  This driver programs both chips.
-
-==============================================================================
-QUICK CONFIGURATION
-
-	# insmod soundcore
-	# insmod vwsnd
-
-==============================================================================
-I/O CONNECTIONS
-
-On the Visual Workstation, only three of the AD1843 inputs are hooked
-up.  The analog line in jacks are connected to the AD1843's AUX1
-input.  The CD audio lines are connected to the AD1843's AUX2 input.
-The microphone jack is connected to the AD1843's MIC input.  The mic
-jack is mono, but the signal is delivered to both the left and right
-MIC inputs.  You can record in stereo from the mic input, but you will
-get the same signal on both channels (within the limits of A/D
-accuracy).  Full scale on the Line input is +/- 2.0 V.  Full scale on
-the MIC input is 20 dB less, or +/- 0.2 V.
-
-The AD1843's LOUT1 outputs are connected to the Line Out jacks.  The
-AD1843's HPOUT outputs are connected to the speaker/headphone jack.
-LOUT2 is not connected.  Line out's maximum level is +/- 2.0 V peak to
-peak.  The speaker/headphone out's maximum is +/- 4.0 V peak to peak.
-
-The AD1843's PCM input channel and one of its output channels (DAC1)
-are connected to Lithium.  The other output channel (DAC2) is not
-connected.
-
-==============================================================================
-CAPABILITIES
-
-The AD1843 has PCM input and output (Pulse Code Modulation, also known
-as wavetable).  PCM input and output can be mono or stereo in any of
-four formats.  The formats are 16 bit signed and 8 bit unsigned,
-u-Law, and A-Law format.  Any sample rate from 4 KHz to 49 KHz is
-available, in 1 Hz increments.
-
-The AD1843 includes an analog mixer that can mix all three input
-signals (line, mic and CD) into the analog outputs.  The mixer has a
-separate gain control and mute switch for each input.
-
-There are two outputs, line out and speaker/headphone out.  They
-always produce the same signal, and the speaker always has 3 dB more
-gain than the line out.  The speaker/headphone output can be muted,
-but this driver does not export that function.
-
-The hardware can sync audio to the video clock, but this driver does
-not have a way to specify syncing to video.
-
-==============================================================================
-PROGRAMMING
-
-This section explains the API supported by the driver.  Also see the
-Open Sound Programming Guide at http://www.opensound.com/pguide/ .
-This section assumes familiarity with that document.
-
-The driver has two interfaces, an I/O interface and a mixer interface.
-There is no MIDI or sequencer capability.
-
-==============================================================================
-PROGRAMMING PCM I/O
-
-The I/O interface is usually accessed as /dev/audio or /dev/dsp.
-Using the standard Open Sound System (OSS) ioctl calls, the sample
-rate, number of channels, and sample format may be set within the
-limitations described above.  The driver supports triggering.  It also
-supports getting the input and output pointers with one-sample
-accuracy.
-
-The SNDCTL_DSP_GETCAP ioctl returns these capabilities.
-
-	DSP_CAP_DUPLEX - driver supports full duplex.
-
-	DSP_CAP_TRIGGER - driver supports triggering.
-
-	DSP_CAP_REALTIME - values returned by SNDCTL_DSP_GETIPTR
-	and SNDCTL_DSP_GETOPTR are accurate to a few samples.
-
-Memory mapping (mmap) is not implemented.
-
-The driver permits subdivided fragment sizes from 64 to 4096 bytes.
-The number of fragments can be anything from 3 fragments to however
-many fragments fit into 124 kilobytes.  It is up to the user to
-determine how few/small fragments can be used without introducing
-glitches with a given workload.  Linux is not realtime, so we can't
-promise anything.  (sigh...)
-
-When this driver is switched into or out of mu-Law or A-Law mode on
-output, it may produce an audible click.  This is unavoidable.  To
-prevent clicking, use signed 16-bit mode instead, and convert from
-mu-Law or A-Law format in software.
-
-==============================================================================
-PROGRAMMING THE MIXER INTERFACE
-
-The mixer interface is usually accessed as /dev/mixer.  It is accessed
-through ioctls.  The mixer allows the application to control gain or
-mute several audio signal paths, and also allows selection of the
-recording source.
-
-Each of the constants described here can be read using the
-MIXER_READ(SOUND_MIXER_xxx) ioctl.  Those that are not read-only can
-also be written using the MIXER_WRITE(SOUND_MIXER_xxx) ioctl.  In most
-cases, <sys/soundcard.h> defines constants SOUND_MIXER_READ_xxx and
-SOUND_MIXER_WRITE_xxx which work just as well.
-
-SOUND_MIXER_CAPS	Read-only
-
-This is a mask of optional driver capabilities that are implemented.
-This driver's only capability is SOUND_CAP_EXCL_INPUT, which means
-that only one recording source can be active at a time.
-
-SOUND_MIXER_DEVMASK	Read-only
-
-This is a mask of the sound channels.  This driver's channels are PCM,
-LINE, MIC, CD, and RECLEV.
-
-SOUND_MIXER_STEREODEVS	Read-only
-
-This is a mask of which sound channels are capable of stereo.  All
-channels are capable of stereo.  (But see caveat on MIC input in I/O
-CONNECTIONS section above).
-
-SOUND_MIXER_OUTMASK	Read-only
-
-This is a mask of channels that route inputs through to outputs.
-Those are LINE, MIC, and CD.
-
-SOUND_MIXER_RECMASK	Read-only
-
-This is a mask of channels that can be recording sources.  Those are
-PCM, LINE, MIC, CD.
-
-SOUND_MIXER_PCM		Default: 0x5757 (0 dB)
-
-This is the gain control for PCM output.  The left and right channel
-gain are controlled independently.  This gain control has 64 levels,
-which range from -82.5 dB to +12.0 dB in 1.5 dB steps.  Those 64
-levels are mapped onto 100 levels at the ioctl, see below.
-
-SOUND_MIXER_LINE	Default: 0x4a4a (0 dB)
-
-This is the gain control for mixing the Line In source into the
-outputs.  The left and right channel gain are controlled
-independently.  This gain control has 32 levels, which range from
--34.5 dB to +12.0 dB in 1.5 dB steps.  Those 32 levels are mapped onto
-100 levels at the ioctl, see below.
-
-SOUND_MIXER_MIC		Default: 0x4a4a (0 dB)
-
-This is the gain control for mixing the MIC source into the outputs.
-The left and right channel gain are controlled independently.  This
-gain control has 32 levels, which range from -34.5 dB to +12.0 dB in
-1.5 dB steps.  Those 32 levels are mapped onto 100 levels at the
-ioctl, see below.
-
-SOUND_MIXER_CD		Default: 0x4a4a (0 dB)
-
-This is the gain control for mixing the CD audio source into the
-outputs.  The left and right channel gain are controlled
-independently.  This gain control has 32 levels, which range from
--34.5 dB to +12.0 dB in 1.5 dB steps.  Those 32 levels are mapped onto
-100 levels at the ioctl, see below.
-
-SOUND_MIXER_RECLEV	 Default: 0 (0 dB)
-
-This is the gain control for PCM input (RECording LEVel).  The left
-and right channel gain are controlled independently.  This gain
-control has 16 levels, which range from 0 dB to +22.5 dB in 1.5 dB
-steps.  Those 16 levels are mapped onto 100 levels at the ioctl, see
-below.
-
-SOUND_MIXER_RECSRC	 Default: SOUND_MASK_LINE
-
-This is a mask of currently selected PCM input sources (RECording
-SouRCes).  Because the AD1843 can only have a single recording source
-at a time, only one bit at a time can be set in this mask.  The
-allowable values are SOUND_MASK_PCM, SOUND_MASK_LINE, SOUND_MASK_MIC,
-or SOUND_MASK_CD.  Selecting SOUND_MASK_PCM sets up internal
-resampling which is useful for loopback testing and for hardware
-sample rate conversion.  But software sample rate conversion is
-probably faster, so I don't know how useful that is.
-
-SOUND_MIXER_OUTSRC	DEFAULT: SOUND_MASK_LINE|SOUND_MASK_MIC|SOUND_MASK_CD
-
-This is a mask of sources that are currently passed through to the
-outputs.  Those sources whose bits are not set are muted.
-
-==============================================================================
-GAIN CONTROL
-
-There are five gain controls listed above.  Each has 16, 32, or 64
-steps.  Each control has 1.5 dB of gain per step.  Each control is
-stereo.
-
-The OSS defines the argument to a channel gain ioctl as having two
-components, left and right, each of which ranges from 0 to 100.  The
-two components are packed into the same word, with the left side gain
-in the least significant byte, and the right side gain in the second
-least significant byte.  In C, we would say this.
-
-	#include <assert.h>
-
-	...
-
-	 	assert(leftgain >= 0 && leftgain <= 100);
-		assert(rightgain >= 0 && rightgain <= 100);
-		arg = leftgain | rightgain << 8;
-
-So each OSS gain control has 101 steps.  But the hardware has 16, 32,
-or 64 steps.  The hardware steps are spread across the 101 OSS steps
-nearly evenly.  The conversion formulas are like this, given N equals
-16, 32, or 64.
-
-	int round = N/2 - 1;
-	OSS_gain_steps = (hw_gain_steps * 100 + round) / (N - 1);
-	hw_gain_steps = (OSS_gain_steps * (N - 1) + round) / 100;
-
-Here is a snippet of C code that will return the left and right gain
-of any channel in dB.  Pass it one of the predefined gain_desc_t
-structures to access any of the five channels' gains.
-
-	typedef struct gain_desc {
-		float min_gain;
-		float gain_step;
-		int nbits;
-		int chan;
-	} gain_desc_t;
-
-	const gain_desc_t gain_pcm    = { -82.5, 1.5, 6, SOUND_MIXER_PCM    };
-	const gain_desc_t gain_line   = { -34.5, 1.5, 5, SOUND_MIXER_LINE   };
-	const gain_desc_t gain_mic    = { -34.5, 1.5, 5, SOUND_MIXER_MIC    };
-	const gain_desc_t gain_cd     = { -34.5, 1.5, 5, SOUND_MIXER_CD     };
-	const gain_desc_t gain_reclev = {   0.0, 1.5, 4, SOUND_MIXER_RECLEV };
-
-	int get_gain_dB(int fd, const gain_desc_t *gp,
-			float *left, float *right)
-	{
-		int word;
-		int lg, rg;
-		int mask = (1 << gp->nbits) - 1;
-
-		if (ioctl(fd, MIXER_READ(gp->chan), &word) != 0)
-			return -1;	/* fail */
-		lg = word & 0xFF;
-		rg = word >> 8 & 0xFF;
-		lg = (lg * mask + mask / 2) / 100;
-		rg = (rg * mask + mask / 2) / 100;
-		*left = gp->min_gain + gp->gain_step * lg;
-		*right = gp->min_gain + gp->gain_step * rg;
-		return 0;
-	}	
-
-And here is the corresponding routine to set a channel's gain in dB.
-
-	int set_gain_dB(int fd, const gain_desc_t *gp, float left, float right)
-	{
-		float max_gain =
-			gp->min_gain + (1 << gp->nbits) * gp->gain_step;
-		float round = gp->gain_step / 2;
-		int mask = (1 << gp->nbits) - 1;
-		int word;
-		int lg, rg;
-
-		if (left < gp->min_gain || right < gp->min_gain)
-			return EINVAL;
-		lg = (left - gp->min_gain + round) / gp->gain_step;
-		rg = (right - gp->min_gain + round) / gp->gain_step;
-		if (lg >= (1 << gp->nbits) || rg >= (1 << gp->nbits))
-			return EINVAL;
-		lg = (100 * lg + mask / 2) / mask;
-		rg = (100 * rg + mask / 2) / mask;
-		word = lg | rg << 8;
-
-		return ioctl(fd, MIXER_WRITE(gp->chan), &word);
-	}
-
diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev
index ed2da5e5b28a..3d14035b1766 100644
--- a/Documentation/spi/spidev
+++ b/Documentation/spi/spidev
@@ -85,6 +85,12 @@ settings for data transfer parameters:
 	SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
 	(clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
 	sample on trailing edge iff this is set) flags.
+	Note that this request is limited to SPI mode flags that fit in a
+	single byte.
+
+    SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t
+	which will return (RD) or assign (WR) the full SPI transfer mode,
+	not limited to the bits that fit in one byte.
 
     SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
 	which will return (RD) or assign (WR) the bit justification used to
diff --git a/Documentation/spi/spidev_fdx.c b/Documentation/spi/spidev_fdx.c
index 36ec0774ca0b..0ea3e51292fc 100644
--- a/Documentation/spi/spidev_fdx.c
+++ b/Documentation/spi/spidev_fdx.c
@@ -78,10 +78,10 @@ static void do_msg(int fd, int len)
 
 static void dumpstat(const char *name, int fd)
 {
-	__u8	mode, lsb, bits;
-	__u32	speed;
+	__u8	lsb, bits;
+	__u32	mode, speed;
 
-	if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
+	if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
 		perror("SPI rd_mode");
 		return;
 	}
@@ -98,7 +98,7 @@ static void dumpstat(const char *name, int fd)
 		return;
 	}
 
-	printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+	printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
 		name, mode, bits, lsb ? "(lsb first) " : "", speed);
 }
 
diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
index 16feda901469..3a2f9d59edab 100644
--- a/Documentation/spi/spidev_test.c
+++ b/Documentation/spi/spidev_test.c
@@ -30,7 +30,7 @@ static void pabort(const char *s)
 }
 
 static const char *device = "/dev/spidev1.1";
-static uint8_t mode;
+static uint32_t mode;
 static uint8_t bits = 8;
 static uint32_t speed = 500000;
 static uint16_t delay;
@@ -57,6 +57,21 @@ static void transfer(int fd)
 		.bits_per_word = bits,
 	};
 
+	if (mode & SPI_TX_QUAD)
+		tr.tx_nbits = 4;
+	else if (mode & SPI_TX_DUAL)
+		tr.tx_nbits = 2;
+	if (mode & SPI_RX_QUAD)
+		tr.rx_nbits = 4;
+	else if (mode & SPI_RX_DUAL)
+		tr.rx_nbits = 2;
+	if (!(mode & SPI_LOOP)) {
+		if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
+			tr.rx_buf = 0;
+		else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
+			tr.tx_buf = 0;
+	}
+
 	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
 	if (ret < 1)
 		pabort("can't send spi message");
@@ -81,7 +96,11 @@ static void print_usage(const char *prog)
 	     "  -O --cpol     clock polarity\n"
 	     "  -L --lsb      least significant bit first\n"
 	     "  -C --cs-high  chip select active high\n"
-	     "  -3 --3wire    SI/SO signals shared\n");
+	     "  -3 --3wire    SI/SO signals shared\n"
+	     "  -N --no-cs    no chip select\n"
+	     "  -R --ready    slave pulls low to pause\n"
+	     "  -2 --dual     dual transfer\n"
+	     "  -4 --quad     quad transfer\n");
 	exit(1);
 }
 
@@ -101,11 +120,13 @@ static void parse_opts(int argc, char *argv[])
 			{ "3wire",   0, 0, '3' },
 			{ "no-cs",   0, 0, 'N' },
 			{ "ready",   0, 0, 'R' },
+			{ "dual",    0, 0, '2' },
+			{ "quad",    0, 0, '4' },
 			{ NULL, 0, 0, 0 },
 		};
 		int c;
 
-		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
+		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL);
 
 		if (c == -1)
 			break;
@@ -147,11 +168,23 @@ static void parse_opts(int argc, char *argv[])
 		case 'R':
 			mode |= SPI_READY;
 			break;
+		case '2':
+			mode |= SPI_TX_DUAL;
+			break;
+		case '4':
+			mode |= SPI_TX_QUAD;
+			break;
 		default:
 			print_usage(argv[0]);
 			break;
 		}
 	}
+	if (mode & SPI_LOOP) {
+		if (mode & SPI_TX_DUAL)
+			mode |= SPI_RX_DUAL;
+		if (mode & SPI_TX_QUAD)
+			mode |= SPI_RX_QUAD;
+	}
 }
 
 int main(int argc, char *argv[])
@@ -168,11 +201,11 @@ int main(int argc, char *argv[])
 	/*
 	 * spi mode
 	 */
-	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
+	ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
 	if (ret == -1)
 		pabort("can't set spi mode");
 
-	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
+	ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
 	if (ret == -1)
 		pabort("can't get spi mode");
 
@@ -198,7 +231,7 @@ int main(int argc, char *argv[])
 	if (ret == -1)
 		pabort("can't get max speed hz");
 
-	printf("spi mode: %d\n", mode);
+	printf("spi mode: 0x%x\n", mode);
 	printf("bits per word: %d\n", bits);
 	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
 
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index e55124e7c40c..ec8be46bf48d 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -320,10 +320,11 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 ==============================================================
 
-hung_task_warning:
+hung_task_warnings:
 
 The maximum number of warnings to report. During a check interval
-When this value is reached, no more the warnings will be reported.
+if a hung task is detected, this value is decreased by 1.
+When this value reaches 0, no more warnings will be reported.
 This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 -1: report an infinite number of warnings.
@@ -441,8 +442,7 @@ feature should be disabled. Otherwise, if the system overhead from the
 feature is too high then the rate the kernel samples for NUMA hinting
 faults may be controlled by the numa_balancing_scan_period_min_ms,
 numa_balancing_scan_delay_ms, numa_balancing_scan_period_max_ms,
-numa_balancing_scan_size_mb, numa_balancing_settle_count sysctls and
-numa_balancing_migrate_deferred.
+numa_balancing_scan_size_mb, and numa_balancing_settle_count sysctls.
 
 ==============================================================
 
@@ -483,13 +483,6 @@ rate for each task.
 numa_balancing_scan_size_mb is how many megabytes worth of pages are
 scanned for a given scan.
 
-numa_balancing_migrate_deferred is how many page migrations get skipped
-unconditionally, after a page migration is skipped because a page is shared
-with other tasks. This reduces page migration overhead, and determines
-how much stronger the "move task near its memory" policy scheduler becomes,
-versus the "move memory near its task" memory management policy, for workloads
-with shared memory.
-
 ==============================================================
 
 osrelease, ostype & version:
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index d614a9b6a280..dd9d0e33b443 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -175,18 +175,39 @@ Setting this to zero disables periodic writeback altogether.
 
 drop_caches
 
-Writing to this will cause the kernel to drop clean caches, dentries and
-inodes from memory, causing that memory to become free.
+Writing to this will cause the kernel to drop clean caches, as well as
+reclaimable slab objects like dentries and inodes.  Once dropped, their
+memory becomes free.
 
 To free pagecache:
 	echo 1 > /proc/sys/vm/drop_caches
-To free dentries and inodes:
+To free reclaimable slab objects (includes dentries and inodes):
 	echo 2 > /proc/sys/vm/drop_caches
-To free pagecache, dentries and inodes:
+To free slab objects and pagecache:
 	echo 3 > /proc/sys/vm/drop_caches
 
-As this is a non-destructive operation and dirty objects are not freeable, the
-user should run `sync' first.
+This is a non-destructive operation and will not free any dirty objects.
+To increase the number of objects freed by this operation, the user may run
+`sync' prior to writing to /proc/sys/vm/drop_caches.  This will minimize the
+number of dirty objects on the system and create more candidates to be
+dropped.
+
+This file is not a means to control the growth of the various kernel caches
+(inodes, dentries, pagecache, etc...)  These objects are automatically
+reclaimed by the kernel when memory is needed elsewhere on the system.
+
+Use of this file can cause performance problems.  Since it discards cached
+objects, it may cost a significant amount of I/O and CPU to recreate the
+dropped objects, especially if they were under heavy use.  Because of this,
+use outside of a testing or debugging environment is not recommended.
+
+You may see informational messages in your kernel log when this file is
+used:
+
+	cat (1234): drop_caches: 3
+
+These are informational only.  They do not mean that anything is wrong
+with your system.  To disable them, echo 4 (bit 3) into drop_caches.
 
 ==============================================================
 
diff --git a/Documentation/trace/events-power.txt b/Documentation/trace/events-power.txt
index 3bd33b8dc7c4..21d514ced212 100644
--- a/Documentation/trace/events-power.txt
+++ b/Documentation/trace/events-power.txt
@@ -92,5 +92,5 @@ dev_pm_qos_remove_request          "device=%s type=%s new_value=%d"
 
 The first parameter gives the device name which tries to add/update/remove
 QoS requests.
-The second parameter gives the request type (e.g. "DEV_PM_QOS_LATENCY").
+The second parameter gives the request type (e.g. "DEV_PM_QOS_RESUME_LATENCY").
 The third parameter is value to be added/updated/removed.
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
new file mode 100644
index 000000000000..410fa673e5b6
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/s390_flic.txt
@@ -0,0 +1,46 @@
+FLIC (floating interrupt controller)
+====================================
+
+FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
+machine check interruptions. All interrupts are stored in a per-vm list of
+pending interrupts. FLIC performs operations on this list.
+
+Only one FLIC instance may be instantiated.
+
+FLIC provides support to
+- add interrupts (KVM_DEV_FLIC_ENQUEUE)
+- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
+- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
+- enable/disable for the guest transparent async page faults
+
+Groups:
+  KVM_DEV_FLIC_ENQUEUE
+    Passes a buffer and length into the kernel which are then injected into
+    the list of pending interrupts.
+    attr->addr contains the pointer to the buffer and attr->attr contains
+    the length of the buffer.
+    The format of the data structure kvm_s390_irq as it is copied from userspace
+    is defined in usr/include/linux/kvm.h.
+
+  KVM_DEV_FLIC_GET_ALL_IRQS
+    Copies all floating interrupts into a buffer provided by userspace.
+    When the buffer is too small it returns -ENOMEM, which is the indication
+    for userspace to try again with a bigger buffer.
+    All interrupts remain pending, i.e. are not deleted from the list of
+    currently pending interrupts.
+    attr->addr contains the userspace address of the buffer into which all
+    interrupt data will be copied.
+    attr->attr contains the size of the buffer in bytes.
+
+  KVM_DEV_FLIC_CLEAR_IRQS
+    Simply deletes all elements from the list of currently pending floating
+    interrupts.  No interrupts are injected into the guest.
+
+  KVM_DEV_FLIC_APF_ENABLE
+    Enables async page faults for the guest. So in case of a major page fault
+    the host is allowed to handle this async and continues the guest.
+
+  KVM_DEV_FLIC_APF_DISABLE_WAIT
+    Disables async page faults for the guest and waits until already pending
+    async page faults are done. This is necessary to trigger a completion interrupt
+    for every init interrupt before migrating the interrupt list.
diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490
index 28176def3d6f..3e091151dd80 100644
--- a/Documentation/w1/masters/ds2490
+++ b/Documentation/w1/masters/ds2490
@@ -21,8 +21,6 @@ Notes and limitations.
 - The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA.
 - The 5V strong pullup is supported with a minimum of 5.9mA and a
   maximum of 30.4 mA.  (From DS2490.pdf)
-- While the ds2490 supports a hardware search the code doesn't take
-  advantage of it (in tested case it only returned first device).
 - The hardware will detect when devices are attached to the bus on the
   next bus (reset?) operation, however only a message is printed as
   the core w1 code doesn't make use of the information.  Connecting
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
index f59a31965d50..927a52cc0519 100644
--- a/Documentation/w1/w1.netlink
+++ b/Documentation/w1/w1.netlink
@@ -5,8 +5,8 @@ Message types.
 =============
 
 There are three types of messages between w1 core and userspace:
-1. Events. They are generated each time new master or slave device
-	found either due to automatic or requested search.
+1. Events. They are generated each time a new master or slave device
+	is found either due to automatic or requested search.
 2. Userspace commands.
 3. Replies to userspace commands.
 
@@ -131,7 +131,7 @@ of the w1_netlink_cmd structure and cn_msg.len will be equal to the sum
 of the sizeof(struct w1_netlink_msg) and sizeof(struct w1_netlink_cmd).
 If reply is generated for master or root command (which do not have
 w1_netlink_cmd attached), reply will contain only cn_msg and w1_netlink_msg
-structires.
+structures.
 
 w1_netlink_msg.status field will carry positive error value
 (EINVAL for example) or zero in case of success.
@@ -160,7 +160,7 @@ procedure is started to select given device.
 Then all requested in w1_netlink_msg operations are performed one by one.
 If command requires reply (like read command) it is sent on command completion.
 
-When all commands (w1_netlink_cmd) are processed muster device is unlocked
+When all commands (w1_netlink_cmd) are processed master device is unlocked
 and next w1_netlink_msg header processing started.
 
 
diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt
index f9492fed4104..b39f35596ba2 100644
--- a/Documentation/watchdog/watchdog-parameters.txt
+++ b/Documentation/watchdog/watchdog-parameters.txt
@@ -325,6 +325,11 @@ soft_noboot: Softdog action, set to 1 to ignore reboots, 0 to reboot
 stmp3xxx_wdt:
 heartbeat: Watchdog heartbeat period in seconds from 1 to 4194304, default 19
 -------------------------------------------------
+tegra_wdt:
+heartbeat: Watchdog heartbeats in seconds. (default = 120)
+nowayout: Watchdog cannot be stopped once started
+	(default=kernel config parameter)
+-------------------------------------------------
 ts72xx_wdt:
 timeout: Watchdog timeout in seconds. (1 <= timeout <= 8, default=8)
 nowayout: Disable watchdog shutdown on close
diff --git a/MAINTAINERS b/MAINTAINERS
index c6d0e93eff62..e0db41f7fe6c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -73,7 +73,8 @@ Descriptions of section entries:
 	L: Mailing list that is relevant to this area
 	W: Web-page with status/info
 	Q: Patchwork web based patch tracking system site
-	T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit, topgit.
+	T: SCM tree type and location.
+	   Type is one of: git, hg, quilt, stgit, topgit
 	S: Status, one of the following:
 	   Supported:	Someone is actually paid to look after this.
 	   Maintained:	Someone actually looks after it.
@@ -816,7 +817,7 @@ ARM/CIRRUS LOGIC CLPS711X ARM ARCHITECTURE
 M:	Alexander Shiyan <shc_work@mail.ru>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Odd Fixes
-F:	arch/arm/mach-clps711x/
+N:	clps711x
 
 ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
 M:	Hartley Sweeten <hsweeten@visionengravers.com>
@@ -1167,6 +1168,14 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.arm.linux.org.uk/
 S:	Maintained
 
+ARM/QUALCOMM SUPPORT
+M:	Kumar Gala <galak@codeaurora.org>
+M:	David Brown <davidb@codeaurora.org>
+L:	linux-arm-msm@vger.kernel.org
+S:	Maintained
+F:	arch/arm/mach-qcom/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
+
 ARM/RADISYS ENP2611 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1612,11 +1621,11 @@ S:	Maintained
 F:	drivers/net/wireless/atmel*
 
 ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
-M:      Bradley Grove <linuxdrivers@attotech.com>
-L:      linux-scsi@vger.kernel.org
-W:      http://www.attotech.com
-S:      Supported
-F:      drivers/scsi/esas2r
+M:	Bradley Grove <linuxdrivers@attotech.com>
+L:	linux-scsi@vger.kernel.org
+W:	http://www.attotech.com
+S:	Supported
+F:	drivers/scsi/esas2r
 
 AUDIT SUBSYSTEM
 M:	Eric Paris <eparis@redhat.com>
@@ -1695,6 +1704,8 @@ F:	drivers/net/wireless/b43legacy/
 
 BACKLIGHT CLASS/SUBSYSTEM
 M:	Jingoo Han <jg1.han@samsung.com>
+M:	Bryan Wu <cooloney@gmail.com>
+M:	Lee Jones <lee.jones@linaro.org>
 S:	Maintained
 F:	drivers/video/backlight/
 F:	include/linux/backlight.h
@@ -1845,6 +1856,12 @@ L:	netdev@vger.kernel.org
 S:	Supported
 F:	drivers/net/ethernet/broadcom/b44.*
 
+BROADCOM GENET ETHERNET DRIVER
+M:	Florian Fainelli <f.fainelli@gmail.com>
+L:	netdev@vger.kernel.org
+S:	Supported
+F:	drivers/net/ethernet/broadcom/genet/
+
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
 M:	Michael Chan <mchan@broadcom.com>
 L:	netdev@vger.kernel.org
@@ -1876,7 +1893,7 @@ M:	Stephen Warren <swarren@wwwdotorg.org>
 L:	linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git
 S:	Maintained
-F:	arch/arm/mach-bcm2835/
+F:	arch/arm/mach-bcm/board_bcm2835.c
 F:	arch/arm/boot/dts/bcm2835*
 F:	arch/arm/configs/bcm2835_defconfig
 F:	drivers/*/*bcm2835*
@@ -1910,6 +1927,13 @@ L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	drivers/scsi/bnx2i/
 
+BROADCOM KONA GPIO DRIVER
+M:	Markus Mayer <markus.mayer@linaro.org>
+L:	bcm-kernel-feedback-list@broadcom.com
+S:	Supported
+F:	drivers/gpio/gpio-bcm-kona.c
+F:	Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
+
 BROADCOM SPECIFIC AMBA DRIVER (BCMA)
 M:	Rafał Miłecki <zajec5@gmail.com>
 L:	linux-wireless@vger.kernel.org
@@ -2159,7 +2183,7 @@ F:	Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
 M:	Peter Chen <Peter.Chen@freescale.com>
-T:	git://github.com/hzpeterchen/linux-usb.git
+T:	git git://github.com/hzpeterchen/linux-usb.git
 L:	linux-usb@vger.kernel.org
 S:	Maintained
 F:	drivers/usb/chipidea/
@@ -2179,9 +2203,9 @@ S:	Supported
 F:	drivers/net/ethernet/cisco/enic/
 
 CISCO VIC LOW LATENCY NIC DRIVER
-M:      Upinder Malhi <umalhi@cisco.com>
-S:      Supported
-F:      drivers/infiniband/hw/usnic
+M:	Upinder Malhi <umalhi@cisco.com>
+S:	Supported
+F:	drivers/infiniband/hw/usnic
 
 CIRRUS LOGIC EP93XX ETHERNET DRIVER
 M:	Hartley Sweeten <hsweeten@visionengravers.com>
@@ -2201,6 +2225,13 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Odd Fixes
 F:	sound/soc/codecs/cs4270*
 
+CIRRUS LOGIC AUDIO CODEC DRIVERS
+M:	Brian Austin <brian.austin@cirrus.com>
+M:	Paul Handrigan <Paul.Handrigan@cirrus.com>
+L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:	Maintained
+F:	sound/soc/codecs/cs*
+
 CLEANCACHE API
 M:	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 L:	linux-kernel@vger.kernel.org
@@ -2378,20 +2409,20 @@ F:	drivers/cpufreq/arm_big_little.c
 F:	drivers/cpufreq/arm_big_little_dt.c
 
 CPUIDLE DRIVER - ARM BIG LITTLE
-M:      Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-M:      Daniel Lezcano <daniel.lezcano@linaro.org>
-L:      linux-pm@vger.kernel.org
-L:      linux-arm-kernel@lists.infradead.org
-T:      git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
-S:      Maintained
-F:      drivers/cpuidle/cpuidle-big_little.c
+M:	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+M:	Daniel Lezcano <daniel.lezcano@linaro.org>
+L:	linux-pm@vger.kernel.org
+L:	linux-arm-kernel@lists.infradead.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
+S:	Maintained
+F:	drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVERS
 M:	Rafael J. Wysocki <rjw@rjwysocki.net>
 M:	Daniel Lezcano <daniel.lezcano@linaro.org>
 L:	linux-pm@vger.kernel.org
 S:	Maintained
-T:	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 F:	drivers/cpuidle/*
 F:	include/linux/cpuidle.h
 
@@ -2458,9 +2489,9 @@ S:	Maintained
 F:	sound/pci/cs5535audio/
 
 CW1200 WLAN driver
-M:     Solomon Peachy <pizza@shaftnet.org>
-S:     Maintained
-F:     drivers/net/wireless/cw1200/
+M:	Solomon Peachy <pizza@shaftnet.org>
+S:	Maintained
+F:	drivers/net/wireless/cw1200/
 
 CX18 VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
@@ -3095,6 +3126,8 @@ F:	fs/ecryptfs/
 
 EDAC-CORE
 M:	Doug Thompson <dougthompson@xmission.com>
+M:	Borislav Petkov <bp@alien8.de>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Supported
@@ -3461,6 +3494,8 @@ F:	include/uapi/scsi/fc/
 
 FILE LOCKING (flock() and fcntl()/lockf())
 M:	Matthew Wilcox <matthew@wil.cx>
+M:	Jeff Layton <jlayton@redhat.com>
+M:	J. Bruce Fields <bfields@fieldses.org>
 L:	linux-fsdevel@vger.kernel.org
 S:	Maintained
 F:	include/linux/fcntl.h
@@ -4558,6 +4593,7 @@ F:	Documentation/networking/ixgbevf.txt
 F:	Documentation/networking/i40e.txt
 F:	Documentation/networking/i40evf.txt
 F:	drivers/net/ethernet/intel/
+F:	drivers/net/ethernet/intel/*/
 
 INTEL-MID GPIO DRIVER
 M:	David Cohen <david.a.cohen@linux.intel.com>
@@ -4914,7 +4950,7 @@ F:	drivers/staging/ktap/
 KCONFIG
 M:	"Yann E. MORIN" <yann.morin.1998@free.fr>
 L:	linux-kbuild@vger.kernel.org
-T:	git://gitorious.org/linux-kconfig/linux-kconfig
+T:	git git://gitorious.org/linux-kconfig/linux-kconfig
 S:	Maintained
 F:	Documentation/kbuild/kconfig-language.txt
 F:	scripts/kconfig/
@@ -5471,11 +5507,11 @@ S:	Maintained
 F:	drivers/media/tuners/m88ts2022*
 
 MA901 MASTERKIT USB FM RADIO DRIVER
-M:      Alexey Klimov <klimov.linux@gmail.com>
-L:      linux-media@vger.kernel.org
-T:      git git://linuxtv.org/media_tree.git
-S:      Maintained
-F:      drivers/media/radio/radio-ma901.c
+M:	Alexey Klimov <klimov.linux@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/radio/radio-ma901.c
 
 MAC80211
 M:	Johannes Berg <johannes@sipsolutions.net>
@@ -5636,7 +5672,7 @@ F:	drivers/scsi/megaraid/
 
 MELLANOX ETHERNET DRIVER (mlx4_en)
 M:	Amir Vadai <amirv@mellanox.com>
-L: 	netdev@vger.kernel.org
+L:	netdev@vger.kernel.org
 S:	Supported
 W:	http://www.mellanox.com
 Q:	http://patchwork.ozlabs.org/project/netdev/list/
@@ -5677,11 +5713,17 @@ F:	include/linux/mtd/
 F:	include/uapi/mtd/
 
 MEN A21 WATCHDOG DRIVER
-M:  	Johannes Thumshirn <johannes.thumshirn@men.de>
+M:	Johannes Thumshirn <johannes.thumshirn@men.de>
 L:	linux-watchdog@vger.kernel.org
 S:	Supported
 F:	drivers/watchdog/mena21_wdt.c
 
+MEN CHAMELEON BUS (mcb)
+M:  	Johannes Thumshirn <johannes.thumshirn@men.de>
+S:	Supported
+F:	drivers/mcb/
+F:	include/linux/mcb.h
+
 METAG ARCHITECTURE
 M:	James Hogan <james.hogan@imgtec.com>
 L:	linux-metag@vger.kernel.org
@@ -5733,20 +5775,20 @@ L:	linux-rdma@vger.kernel.org
 W:	http://www.mellanox.com
 Q:	http://patchwork.ozlabs.org/project/netdev/list/
 Q:	http://patchwork.kernel.org/project/linux-rdma/list/
-T:	git://openfabrics.org/~eli/connect-ib.git
+T:	git git://openfabrics.org/~eli/connect-ib.git
 S:	Supported
 F:	drivers/net/ethernet/mellanox/mlx5/core/
 F:	include/linux/mlx5/
 
 Mellanox MLX5 IB driver
-M:      Eli Cohen <eli@mellanox.com>
-L:      linux-rdma@vger.kernel.org
-W:      http://www.mellanox.com
-Q:      http://patchwork.kernel.org/project/linux-rdma/list/
-T:      git://openfabrics.org/~eli/connect-ib.git
-S:      Supported
-F:      include/linux/mlx5/
-F:      drivers/infiniband/hw/mlx5/
+M:	Eli Cohen <eli@mellanox.com>
+L:	linux-rdma@vger.kernel.org
+W:	http://www.mellanox.com
+Q:	http://patchwork.kernel.org/project/linux-rdma/list/
+T:	git git://openfabrics.org/~eli/connect-ib.git
+S:	Supported
+F:	include/linux/mlx5/
+F:	drivers/infiniband/hw/mlx5/
 
 MODULE SUPPORT
 M:	Rusty Russell <rusty@rustcorp.com.au>
@@ -5829,6 +5871,7 @@ F:	include/linux/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
 M:	Chris Ball <chris@printf.net>
+M:	Ulf Hansson <ulf.hansson@linaro.org>
 L:	linux-mmc@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
 S:	Maintained
@@ -6021,6 +6064,7 @@ L:	netdev@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
 S:	Maintained
+F:	net/core/flow.c
 F:	net/xfrm/
 F:	net/key/
 F:	net/ipv4/xfrm*
@@ -6114,10 +6158,10 @@ F:	include/uapi/linux/nfs*
 F:	include/uapi/linux/sunrpc/
 
 NILFS2 FILESYSTEM
-M:	KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
+M:	Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
 L:	linux-nilfs@vger.kernel.org
-W:	http://www.nilfs.org/en/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2.git
+W:	http://nilfs.sourceforge.net/
+T:	git git://github.com/konis/nilfs2.git
 S:	Supported
 F:	Documentation/filesystems/nilfs2.txt
 F:	fs/nilfs2/
@@ -7049,13 +7093,8 @@ F:	Documentation/networking/LICENSE.qla3xxx
 F:	drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:	Himanshu Madhani <himanshu.madhani@qlogic.com>
-M:	Rajesh Borundia <rajesh.borundia@qlogic.com>
 M:	Shahed Shaikh <shahed.shaikh@qlogic.com>
-M:	Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
-M:	Sony Chacko <sony.chacko@qlogic.com>
-M:	Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
-M:	linux-driver@qlogic.com
+M:	Dept-HSGLinuxNICDev@qlogic.com
 L:	netdev@vger.kernel.org
 S:	Supported
 F:	drivers/net/ethernet/qlogic/qlcnic/
@@ -7390,10 +7429,26 @@ W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 F:	arch/s390/
 F:	drivers/s390/
-F:	block/partitions/ibm.c
 F:	Documentation/s390/
 F:	Documentation/DocBook/s390*
 
+S390 COMMON I/O LAYER
+M:	Sebastian Ott <sebott@linux.vnet.ibm.com>
+M:	Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+L:	linux-s390@vger.kernel.org
+W:	http://www.ibm.com/developerworks/linux/linux390/
+S:	Supported
+F:	drivers/s390/cio/
+
+S390 DASD DRIVER
+M:	Stefan Weinhuber <wein@de.ibm.com>
+M:	Stefan Haberland <stefan.haberland@de.ibm.com>
+L:	linux-s390@vger.kernel.org
+W:	http://www.ibm.com/developerworks/linux/linux390/
+S:	Supported
+F:	drivers/s390/block/dasd*
+F:	block/partitions/ibm.c
+
 S390 NETWORK DRIVERS
 M:	Ursula Braun <ursula.braun@de.ibm.com>
 M:	Frank Blaschka <blaschka@linux.vnet.ibm.com>
@@ -7403,6 +7458,15 @@ W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 F:	drivers/s390/net/
 
+S390 PCI SUBSYSTEM
+M:	Sebastian Ott <sebott@linux.vnet.ibm.com>
+M:	Gerald Schaefer <gerald.schaefer@de.ibm.com>
+L:	linux-s390@vger.kernel.org
+W:	http://www.ibm.com/developerworks/linux/linux390/
+S:	Supported
+F:	arch/s390/pci/
+F:	drivers/pci/hotplug/s390_pci_hpc.c
+
 S390 ZCRYPT DRIVER
 M:	Ingo Tuchscherer <ingo.tuchscherer@de.ibm.com>
 M:	linux390@de.ibm.com
@@ -7715,11 +7779,10 @@ M:	Security Officers <security@kernel.org>
 S:	Supported
 
 SELINUX SECURITY MODULE
+M:	Paul Moore <paul@paul-moore.com>
 M:	Stephen Smalley <sds@tycho.nsa.gov>
-M:	James Morris <james.l.morris@oracle.com>
 M:	Eric Paris <eparis@parisplace.org>
-M:	Paul Moore <paul@paul-moore.com>
-L:	selinux@tycho.nsa.gov (subscribers-only, general discussion)
+L:	selinux@tycho.nsa.gov (moderated for non-subscribers)
 W:	http://selinuxproject.org
 T:	git git://git.infradead.org/users/pcmoore/selinux
 S:	Supported
@@ -7786,13 +7849,6 @@ F:	Documentation/ia64/serial.txt
 F:	drivers/tty/serial/ioc?_serial.c
 F:	include/linux/ioc?.h
 
-SGI VISUAL WORKSTATION 320 AND 540
-M:	Andrey Panin <pazke@donpac.ru>
-L:	linux-visws-devel@lists.sf.net
-W:	http://linux-visws.sf.net
-S:	Maintained for 2.6.
-F:	Documentation/sgi-visws.txt
-
 SGI XP/XPC/XPNET DRIVER
 M:	Cliff Whickman <cpw@sgi.com>
 M:	Robin Holt <robinmholt@gmail.com>
@@ -8340,6 +8396,12 @@ M:	Teddy Wang <teddy.wang@siliconmotion.com.cn>
 S:	Odd Fixes
 F:	drivers/staging/sm7xxfb/
 
+STAGING - SLICOSS
+M:	Lior Dotan <liodot@gmail.com>
+M:	Christopher Harrer <charrer@alacritech.com>
+S:	Odd Fixes
+F:	drivers/staging/slicoss/
+
 STAGING - SOFTLOGIC 6x10 MPEG CODEC
 M:	Ismael Luceno <ismael.luceno@corp.bluecherry.net>
 S:	Supported
@@ -8401,12 +8463,10 @@ S:	Maintained
 F:	drivers/net/ethernet/dlink/sundance.c
 
 SUPERH
-M:	Paul Mundt <lethal@linux-sh.org>
 L:	linux-sh@vger.kernel.org
 W:	http://www.linux-sh.org
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
-T:	git git://github.com/pmundt/linux-sh.git sh-latest
-S:	Supported
+S:	Orphan
 F:	Documentation/sh/
 F:	arch/sh/
 F:	drivers/sh/
@@ -8700,17 +8760,17 @@ S:	Maintained
 F:	drivers/media/radio/radio-raremono.c
 
 THERMAL
-M:      Zhang Rui <rui.zhang@intel.com>
-M:      Eduardo Valentin <eduardo.valentin@ti.com>
-L:      linux-pm@vger.kernel.org
-T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
-T:      git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
-Q:      https://patchwork.kernel.org/project/linux-pm/list/
-S:      Supported
-F:      drivers/thermal/
-F:      include/linux/thermal.h
-F:      include/linux/cpu_cooling.h
-F:      Documentation/devicetree/bindings/thermal/
+M:	Zhang Rui <rui.zhang@intel.com>
+M:	Eduardo Valentin <eduardo.valentin@ti.com>
+L:	linux-pm@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
+Q:	https://patchwork.kernel.org/project/linux-pm/list/
+S:	Supported
+F:	drivers/thermal/
+F:	include/linux/thermal.h
+F:	include/linux/cpu_cooling.h
+F:	Documentation/devicetree/bindings/thermal/
 
 THINGM BLINK(1) USB RGB LED DRIVER
 M:	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
@@ -9812,7 +9872,7 @@ ZR36067 VIDEO FOR LINUX DRIVER
 L:	mjpeg-users@lists.sourceforge.net
 L:	linux-media@vger.kernel.org
 W:	http://mjpeg.sourceforge.net/driver-zoran/
-T:	Mercurial http://linuxtv.org/hg/v4l-dvb
+T:	hg http://linuxtv.org/hg/v4l-dvb
 S:	Odd Fixes
 F:	drivers/media/pci/zoran/
 
diff --git a/Makefile b/Makefile
index 78209ee1f981..176e310cd76d 100644
--- a/Makefile
+++ b/Makefile
@@ -414,8 +414,9 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_ve
 
 # Files to ignore in find ... statements
 
-RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
-		   -o -name .pc -o -name .hg -o -name .git \) -prune -o
+export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o    \
+			  -name CVS -o -name .pc -o -name .hg -o -name .git \) \
+			  -prune -o
 export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
 			 --exclude CVS --exclude .pc --exclude .hg --exclude .git
 
@@ -729,6 +730,13 @@ export KBUILD_IMAGE ?= vmlinux
 export	INSTALL_PATH ?= /boot
 
 #
+# INSTALL_DTBS_PATH specifies a prefix for relocations required by build roots.
+# Like INSTALL_MOD_PATH, it isn't defined in the Makefile, but can be passed as
+# an argument if needed. Otherwise it defaults to the kernel install path
+#
+export INSTALL_DTBS_PATH ?= $(INSTALL_PATH)/dtbs/$(KERNELRELEASE)
+
+#
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
 # makefile but the argument can be passed to make if needed.
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 000000000000..b00d7e10db82
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,212 @@
+Name		SHA1
+----		----
+origin		0c0bd34a142963ca3454f530e47ce1c230d8cc9d
+fixes		b0031f227e47919797dc0e1c1990f3ef151ff0cc
+kbuild-current	38dbfb59d1175ef458d006556061adeaa8751b72
+arc-current	7e22e91102c6b9df7c4ae2168910e19d2bb14cd6
+arm-current	b3634575930857724d5c3987a2739b0637999b4e
+m68k-current	7247f55381d54645a1eb47588de51bb26fa7cb7a
+metag-fixes	f229006ec6beabf7b844653d92fa61f025fe3dcf
+powerpc-merge	e0cf957614976896111e676e5134ac98ee227d3d
+sparc		10527106abec1e72a3b1f06fe58f0162603ed9df
+net		8b4703e9bd1172a5f8244276ebb94302e6153e26
+ipsec		3a9016f97fdc8bfbb26ff36ba8f3dc9162eb691b
+sound-current	a6b92b6650d010d58b6e6fe42c6271266e0b1134
+pci-current	fc40363b2140f5777c88e67814fac9327bf1ee68
+wireless	adb07df1e039e9fe43e66aeea8b4771f83659dbb
+driver-core.current	0414855fdc4a40da05221fc6062cccbc0c30f169
+tty.current	0414855fdc4a40da05221fc6062cccbc0c30f169
+usb.current	0414855fdc4a40da05221fc6062cccbc0c30f169
+staging.current	0414855fdc4a40da05221fc6062cccbc0c30f169
+char-misc.current	0414855fdc4a40da05221fc6062cccbc0c30f169
+input-current	70b0052425ffd549bb27fb08649a4d30daaf40e4
+md-current	d47648fcf0611812286f68131b40251c6fa54f5e
+crypto-current	ee97dc7db4cbda33e4241c2d85b42d1835bc8a35
+ide		738b52bb9845da183b6ff46a8f685b56a63379d1
+dwmw2		5950f0803ca9d396ab79b7fe6789351f96e1d8d5
+devicetree-current	1f42e5dd5065963979bb53daadf5d4f1e71f0c5f
+rr-fixes	7122c3e9154b5d9a7422f68f02d8acf050fad2b0
+mfd-fixes	73beb63d290f961c299526852884846b0d868840
+vfio-fixes	239a87020b263fe7e70adc5803cb157955023d3c
+drm-intel-fixes	6375b768a9850b6154478993e5fb566fa4614a9c
+asm-generic	fb9de7ebc3a2eb7ddb83c92e288447a0c313bced
+arc		67a2635aa64a75fa8d83d1339c5309fe853593ed
+arm		93c95d4353c69580f84591fe58cedd080c3d7329
+arm-perf	8e781f65423c2e8e65a56972ba996b6c01a5ef3e
+arm-soc		403172d8553f78ec5c3bdafe3475b78716c43c64
+bcm2835		8ac06bb693ca978e5e50c2b4e0973d90e04254ca
+cortex-m	f0d7515372ff0ea53fd66099533d3c8e0464cbbf
+ep93xx		bfb0709fd17b13498d99592bbe12c91130e35a55
+imx-mxs		df5ec17e8ab90f9c4dc126a396b3cd31275b5c04
+ixp4xx		19f949f52599ba7c3f67a5897ac6be14bfcb1200
+keystone	5c0426dcd3868deef97c2039275ee5af0a32b28d
+msm		81cf1e061d001fab44dbaa85fc4fbfb6da6713a1
+mvebu		79e8e9df3918171369a2b5b49c6bbaf54d54116d
+renesas		3952e65ec9edd4ad9bc2e851cf36f0b953abd5e5
+samsung		941e7012a3b984d4db76f41ffba64d881a160991
+tegra		19bb3595b7e207eae76d2d97877597ef3bbeeb39
+arm64		addea9ef055bf5a10f9ec967b1e0443ceb44bd83
+blackfin	58095fdaaf1cee12d8e01aa20f94b976e3137d27
+c6x		546153d75a488f234709c009faf9fafbe34e1ba0
+cris		cd065a010a97e3c330d1ded9af551664c9689b19
+hexagon		44eb66c228fe5617a15535dc3ad2b8965661c426
+ia64		d21114236d0e1232023cb8c84bd29e06810f6a2f
+m68k		7247f55381d54645a1eb47588de51bb26fa7cb7a
+m68knommu	72a8ab3cb2a5e94f50fd7a2173b65e63be882010
+metag		e9a1d0165bbda4398d4a5d71736cf6390fb42c6f
+microblaze	1cbe158dec8c5635cf364bdc0a3dfd7f2576ee47
+mips		22fdf79f9c812eea90f2b7636c666be1db275f8a
+openrisc	548dafe880ad84d0accc0a5596c26e3348b103e1
+parisc		6c700d71f7faecb540b3fa4303edb5323a2768c1
+parisc-hd	38dbfb59d1175ef458d006556061adeaa8751b72
+powerpc		66f9af83e56bfa12964d251df9d60fb571579913
+mpc5xxx		bc75059422338197ce487d338ac9c898761e1e61
+galak		9e2ecdbba3b0745f9ed454ab86961e3ccf9dc224
+s390		d72d2bb5a6bc85af77a9f969687c74ea00cdcc99
+sparc-next	049ffa8ab33a63b3bff672d1a0ee6a35ad253fe8
+tile		5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52
+uml		989e59fa41c5464ab77bf0bf82f32f721430544e
+unicore32	c284464658acab50c67ff65ff3dc9215a0231ad2
+xtensa		b3fdfc1b4b641d372e35ced98814289bc60bc5d1
+btrfs		cf93da7bcf450cb4595055d491a0519cb39e68ed
+ceph		bee26897097fea59a969654b36d25b5844ba0b63
+cifs		dca1c8d17a2feae056f9e334ea75a462ae4cb52a
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	9e78d14a9f641c0476f733f6fc559ba5cac6f52b
+ext3		ff57cd5863cf3014c1c5ed62ce2715294f065b17
+ext4		442ed22745a0b8d357a4b54348ac36b2cd08c4df
+f2fs		9cf3c3898a274ca637b88ad01b0830550ee2d318
+fscache		fe02fb3ec10932ce07406b1581e28326181fc9d8
+fuse		b2ec2778df9d2f3c8a4925f0d1903719427a5e88
+gfs2		fcf10d38afd2d39d08bf76c48ff9c12345770678
+jfs		844fa1b5f8493cff4b976fa7a5b9ebeeafdd75cc
+logfs		339466142b3f58fe0ee4dea7e8c5f3d33099e89c
+nfs		755a48a7a4eb05b9c8424e3017d947b2961a60e0
+nfsd		1406b916f4a29d5f9660264a28ce609c8c77e7ae
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	6d565409503f4e1f74ac30de14e8c91a2b826cd8
+v9fs		38dbfb59d1175ef458d006556061adeaa8751b72
+ubifs		9d54c8a33eec78289b1b3f6e10874719c27ce0a7
+xfs		14e637ca53fa257cbff7f73981dd87c457a6be1e
+file-private-locks	1ed1950c412f1b1a1c445b37df1c2710244cdc81
+vfs		527d1511310a89650000081869260394e20c7013
+pci		2c0503f202f597325baae76e9f5686518e5ed0dd
+hid		afbe1c7e1a5342100126fdf9cd610495290ccd9b
+i2c		e89364556824cc7a947f99173af842217074c099
+jdelvare-hwmon	c1d70b646daeddc4ef9a7e396b3848a68c3dce44
+hwmon-staging	d44cdded6ab33951b767506d84c2d35729d0db76
+v4l-dvb		b215621049bd57221455990880fb6b906f7dac21
+kbuild		ff6b9bdb62633f4509a9049f713a2ef0fce6a8fe
+kconfig		95edca5c523c4b404dd60baa0a1bea0e4c38fd72
+libata		70320a1803e5c4c6f17e45aa5201936ea2427bf6
+pm		c208b7bbf7df0b8daa117894acf856cdeb5ab2c1
+idle		62eec04c7fa3a4eec0d0f5b3b79549ce0cb27c44
+apm		158204397034f088bfd505eeee281f7072da1c24
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		e79ca84d62d289b90cb39c80df83acf9f315a25c
+ieee1394	8987583366ae9e03c306c2b7d73bdb952df1d08d
+dlm		075f01775f53640af4a2ca3ed8cbc71de6e37582
+swiotlb		0cb637bff80d5ba2b916bb19f19ffd59cd4079fd
+slave-dma	3c79200df630ebecf7143db8435e74441f393fac
+dmaengine	77873803363c9e831fc1d1e6895c084279090c22
+net-next	f19c29e3e391a66a273e9afebaf01917245148cd
+ipsec-next	bc861959103cb5ca43157db6ddb83d1e17e9c38a
+wireless-next	35582ad9d342025653aaf28ed321bf5352488d7f
+bluetooth	81ad6fd9698f659dbabdc6cd3e1667a98eb2be3b
+infiniband	7f3c1e1ba82ed2082d607ab68a91e084b9060c0d
+mtd		bb38eefb6858ce16b34716145b9597a5680aa54c
+l2-mtd		b9d3ea0eccce8fa880ba1538e217060be652cf01
+crypto		c65a52f8360dc29116395708bde18399e4699f87
+drm		4d538b79197901fecc42e746d515d07fd1089b62
+drm-intel	b5ea642a76ee0884a4d378b4d5fe290ddb461524
+drm-tegra	c1a68b4c29b86504208bf27cd3249ac92fc9901e
+sound		31278997add61ee13b709e274934c7b0085accce
+sound-asoc	d01fcf8e8e14c227a1f4947120cd6ce45cadeb1e
+modules		917307b09ad53bcb473e67266b89786aa05be237
+virtio		6f0317058f436d1daff3c6477f74449ae7acebcd
+input		7fb45edba8b5206e645572a682c946f67375447e
+input-mt	5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52
+block		a9f4f164c0362f98c53c003a96b610366eaceeb5
+device-mapper	14f398ca2f26a2ed6236aec54395e0fa06ec8a82
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		370aede6a18a41e01f2668108d847b598443fbc0
+kgdb		6bedf31c25dd93c4f70a28e9ab94a239a5fb592c
+slab		26e4f2057516f1c457e0e95346a00303f983ad53
+uclinux		6dbe51c251a327e012439c4772097a13df43c5b8
+md		789b5e0315284463617e106baad360cb9e8db3ac
+mfd		90b128ed1557c2f523995a379a53e5105891ecf8
+mfd-lj		4d0621451ff2b8ce8a4aed66b98d66121a048fc3
+battery		ac323d8d807060f7c95a685a9fe861e7b6300993
+fbdev		718b90ac4c21c81f42b6db062ca0867f3cac7648
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	2b04f21e69a186f645dc543aa3c90a72ffb946a0
+regulator	9e90ea8166d1b85e2faa46f4debee2e8a5e79435
+security	864f32a52b53341c54a25953afb5b66ed79a7f76
+selinux		0909c0ae999c325b9d34c6f4710f40730ae3bc24
+lblnet		d8ec26d7f8287f5788a494f56e8814210f0e64be
+watchdog	db5dd336cb238c50b177b760064eff1f8d348d17
+dwmw2-iommu	e5d0c874391a500be7643d3eef9fb07171eee129
+iommu		972157cac528f6cfd1f7e640139287951066106e
+vfio		9d830d47c7a756da6f0b55fa25d51eec0739eb02
+osd		19350e7627a6f3b0f662cbd2eb1128c9961a41fe
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		80dd6eac00908a2c3e7a7c3f538ceee75c03f94f
+audit		f3411cb2b2e396a41ed3a439863f028db7140a34
+fsnotify	1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06
+devicetree	f4d4ffc03efc864645b990e1d579bbe1b8e358a4
+dt-rh		06b29e76a74b2373e6f8b5a7938b3630b9ae98b2
+spi		d4127e50a72f5d0c82b237dc490b1dc5a96faa37
+tip		05c0f92abb17f84d0e03297f7a0d77cb12d77892
+clockevents	00e2bcd6d35f59fce7fa0e76e24d08f74c6a8506
+edac		3e45588825c1c9c7b561102dd878d23af1b46bb9
+edac-amd	c045ebdf6079b79ac4b4dd16ff37f93ae0bd5190
+ftrace		1fcc155351f183e5044180eeb372a8ff47710855
+rcu		f5604f67fe8cbd6f2088b20b9463f721aa613d4b
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kvm		d3714010c307d26df251c45be9cd12ab6d41f0c4
+kvm-arm		b73117c49364551ff789db7c424a115ac5b77850
+kvm-ppc		b73117c49364551ff789db7c424a115ac5b77850
+oprofile	6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae
+fw-nohz		74876a98a87a115254b3a66a14b27320b7f0acaa
+xen-tip		08ac54ab46ab1f941ed0a36fb90007e68645a5cd
+percpu		d5f2deed588b8d53f9667d2b0508ca146f70e176
+workqueues	379e899a2c667cb911afb20489b6cbaa60916058
+drivers-x86	b4b0b4a9e0392dbd00e5f033e1329ce61ed06fef
+chrome-platform	2b8454a75b90d7cd1ac325a0baba77244733354f
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		f7368630e4186a6488060d0fd6611324d4058661
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		aad0f292756cb267953f6cd04bbf4b51f2497034
+driver-core	13df7977431e3b906a23bb75f29e0f40a8d73f87
+tty		013daec9c19b73ef1e8e427dd7c8acca5766c17e
+usb		3c1b2c3ecd3122fe6dded7b012f74021144d95b2
+usb-gadget	fa92f305f31180df5cb7604adfb8dd9a79d65e78
+staging		17b02809cfa77abcab155ce3afbb1467e7f0744f
+char-misc	aa074c1c805a38c01c0dfe56f78d409e33be28a2
+cgroup		392a65859327f20645ecde0675dba2ace8ea61e9
+scsi		960dfc4eb23a28495276b02604d7458e0e1a1ed8
+target-updates	9af6de4a22c5a1417bcfd3abc95d8e468a5878b2
+target-merge	b28a960c42fcd9cfc987441fa6d1c1a471f0f9ed
+writeback	f9b0e058cbd04ada76b13afffa7e1df830543c24
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		1e999c2ba8dddc4b5565e6bd965393e495fcbb5d
+vhost		d3d665a654a35c47463d2aa6353bac3ce293f4f5
+remoteproc	bd88acba5f9809af48f66267bb16024b9e33cf2b
+rpmsg		397944df3290ddc46dcc6a08cd71fb560700431b
+gpio		41c761a0c89265e6011b2c892e72556b27c81d47
+dma-mapping	68efd7d2fb32c2606f1da318b6a851d933813f27
+pwm		8468949cddcdbb1b1b1bc552aefceb252078ceb1
+dma-buf		c0b00a525c127d0055c1df6283300e17f601a1a1
+userns		f58437f1f9161847c636e4fed5569ed5b908af36
+ktest		62183dcac539a14ed0a820b8392db353d72a7d7e
+signal		20b4fb485227404329e41ad15588afad3df23050
+clk		5ba8dac012c33b336b29d472fdf5296b5682d8bf
+random		a9f069e38cc36d6c4ab3c831bc4bef2ae1a16e96
+lzo-update	42b775abafafdf811ef300e869a4e1480ef1cf95
+arm64-hugepages	af07484863e0c20796081e57093886c22dc16705
+aio		168a3eb76a7f75fa19afe9098118d3aa64b0ce83
+llvmlinux	f557840d89920d232db0ac73ff45d4301b0e0b81
+akpm-current	6dea20c464493740dff9fce99c464e8fc7a1e01e
+akpm		ab47cc00257d4a9eb72c9e5fc5cf6f3ad40725f4
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 000000000000..bc358406db77
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,214 @@
+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-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
+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.linaro.org/people/shawnguo/linux-2.6.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.linaro.org/people/ljones/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
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+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
+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..0d950f0fcd57
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,8980 @@
+$ date
+Tuesday 4 March  10:29:52 EST 2014
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at c59224d1326e Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
+Merging origin/master (0c0bd34a1429 Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip)
+$ git merge origin/master
+Updating c59224d1326e..0c0bd34a1429
+Fast-forward
+ .../bindings/clock/renesas,cpg-mstp-clocks.txt     |  4 +-
+ Makefile                                           |  2 +-
+ arch/arm/boot/dts/keystone-clocks.dtsi             |  2 +-
+ drivers/clk/at91/clk-master.c                      |  2 +-
+ drivers/clk/clk-nomadik.c                          |  3 ++
+ drivers/clk/clk.c                                  | 13 +++---
+ drivers/clk/keystone/gate.c                        |  1 +
+ drivers/clk/mvebu/armada-370.c                     | 21 +++++-----
+ drivers/clk/mvebu/armada-xp.c                      | 20 ++++-----
+ drivers/clk/mvebu/dove.c                           | 19 ++++-----
+ drivers/clk/mvebu/kirkwood.c                       | 34 ++++++++-------
+ drivers/clk/shmobile/clk-rcar-gen2.c               | 12 +++++-
+ drivers/clk/tegra/clk-divider.c                    |  2 +-
+ drivers/clk/tegra/clk-id.h                         |  4 ++
+ drivers/clk/tegra/clk-tegra-periph.c               | 10 +++--
+ drivers/clk/tegra/clk-tegra-super-gen4.c           |  2 +-
+ drivers/clk/tegra/clk-tegra114.c                   |  8 ++--
+ drivers/clk/tegra/clk-tegra124.c                   | 48 ++++++++++++----------
+ drivers/clk/tegra/clk-tegra20.c                    |  2 +
+ include/dt-bindings/clock/tegra124-car.h           |  4 +-
+ kernel/sched/cpudeadline.c                         |  4 +-
+ kernel/sched/deadline.c                            | 10 +++--
+ kernel/sched/fair.c                                |  8 ++--
+ kernel/sched/rt.c                                  |  8 ++++
+ tools/lib/lockdep/Makefile                         |  6 +--
+ tools/lib/lockdep/preload.c                        |  2 +-
+ tools/lib/lockdep/run_tests.sh                     |  0
+ tools/lib/lockdep/uinclude/asm/hash.h              |  6 +++
+ tools/lib/lockdep/uinclude/linux/rcu.h             |  5 +++
+ 29 files changed, 152 insertions(+), 110 deletions(-)
+ mode change 100644 => 100755 tools/lib/lockdep/run_tests.sh
+ create mode 100644 tools/lib/lockdep/uinclude/asm/hash.h
+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 (7e22e91102c6 Linux 3.13-rc8)
+$ git merge arc-current/for-curr
+Already up-to-date.
+Merging arm-current/fixes (b36345759308 ARM: 7980/1: kernel: improve error message when LPAE config doesn't match CPU)
+$ git merge arm-current/fixes
+Merge made by the 'recursive' strategy.
+ arch/arm/kernel/head-common.S | 12 ++++++++++++
+ arch/arm/kernel/head.S        |  2 +-
+ arch/arm/mm/dump.c            |  3 +++
+ scripts/mod/modpost.c         | 13 +++++++++++++
+ 4 files changed, 29 insertions(+), 1 deletion(-)
+Merging m68k-current/for-linus (7247f55381d5 m68k: Wire up sched_setattr and sched_getattr)
+$ git merge m68k-current/for-linus
+Already up-to-date.
+Merging metag-fixes/fixes (f229006ec6be irq-metag*: stop set_affinity vectoring to offline cpus)
+$ git merge metag-fixes/fixes
+Already up-to-date.
+Merging powerpc-merge/merge (e0cf95761497 powerpc/powernv: Fix indirect XSCOM unmangling)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (10527106abec Merge tag 'dt-for-linus' of git://git.secretlab.ca/git/linux)
+$ git merge sparc/master
+Already up-to-date.
+Merging net/master (8b4703e9bd11 macvlan: Add support for 'always_on' offload features)
+$ git merge net/master
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/net/opencores-ethoc.txt    |  22 +++
+ Documentation/networking/can.txt                   |   6 -
+ MAINTAINERS                                        |   1 +
+ drivers/infiniband/hw/mlx4/main.c                  |   4 +-
+ drivers/infiniband/hw/mlx5/main.c                  |   4 +-
+ drivers/net/bonding/bond_3ad.c                     |  16 +-
+ drivers/net/bonding/bond_main.c                    | 124 ++++++++-------
+ drivers/net/bonding/bonding.h                      |  47 +++++-
+ drivers/net/can/flexcan.c                          | 172 ++++++++++++++++-----
+ drivers/net/ethernet/broadcom/b44.c                |  14 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |   9 +-
+ drivers/net/ethernet/broadcom/tg3.c                |   3 +-
+ drivers/net/ethernet/broadcom/tg3.h                |   6 +-
+ drivers/net/ethernet/brocade/bna/bnad.c            |  40 +++--
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   1 +
+ drivers/net/ethernet/emulex/benet/be.h             |   4 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |  84 +++++-----
+ drivers/net/ethernet/freescale/fec_main.c          |  13 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4.h          |   4 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h       |   4 +-
+ drivers/net/ethernet/mellanox/mlx5/core/main.c     |   4 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |   1 +
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c    |   4 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   5 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c   |   9 --
+ drivers/net/ethernet/realtek/r8169.c               |   2 +
+ drivers/net/ethernet/sfc/ptp.c                     |   7 +
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |   2 +-
+ drivers/net/ethernet/ti/cpsw.c                     |   6 +
+ drivers/net/macvlan.c                              |   7 +-
+ drivers/net/phy/phy_device.c                       |  16 +-
+ drivers/net/tun.c                                  |   4 +-
+ drivers/net/usb/ax88179_178a.c                     |  34 ++++
+ drivers/net/veth.c                                 |   3 +-
+ drivers/net/virtio_net.c                           |   3 +-
+ .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h   |   4 +-
+ drivers/net/wireless/ath/ath9k/hw.c                |   8 +-
+ drivers/net/wireless/ath/ath9k/recv.c              |  70 ++++-----
+ drivers/net/wireless/ath/ath9k/xmit.c              |  13 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  14 +-
+ drivers/net/wireless/hostap/hostap_ap.c            |   2 +-
+ drivers/net/wireless/iwlwifi/dvm/sta.c             |   1 +
+ drivers/net/wireless/iwlwifi/dvm/tx.c              |  14 +-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h             |   2 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c              |  18 +--
+ drivers/net/wireless/libertas/cfg.c                |   2 +-
+ drivers/net/wireless/mwifiex/pcie.c                |  34 ++--
+ drivers/net/wireless/mwifiex/usb.c                 |  12 +-
+ drivers/net/wireless/mwifiex/wmm.c                 |   3 +-
+ drivers/net/xen-netfront.c                         |   1 +
+ drivers/s390/net/qeth_core_main.c                  |   5 +-
+ drivers/s390/net/qeth_l2_main.c                    |   3 +
+ drivers/s390/net/qeth_l3_main.c                    |   3 +
+ include/linux/skbuff.h                             |   5 +-
+ include/net/ip_tunnels.h                           |   1 +
+ include/net/tcp.h                                  |   3 +-
+ include/net/xfrm.h                                 |  11 ++
+ net/can/raw.c                                      |  26 +---
+ net/core/neighbour.c                               |   8 +-
+ net/core/skbuff.c                                  |   3 -
+ net/hsr/hsr_framereg.c                             |   2 +-
+ net/ipv4/af_inet.c                                 |   7 +-
+ net/ipv4/ip_output.c                               |   3 -
+ net/ipv4/ip_tunnel.c                               |  53 +------
+ net/ipv4/ip_tunnel_core.c                          |  47 +++++-
+ net/ipv4/netfilter/nf_nat_snmp_basic.c             |   4 +-
+ net/ipv4/tcp.c                                     |   8 +-
+ net/ipv4/tcp_cong.c                                |   3 +-
+ net/ipv4/tcp_input.c                               |   3 +-
+ net/ipv4/tcp_output.c                              |  22 ++-
+ net/ipv6/Kconfig                                   |   1 +
+ net/ipv6/exthdrs_core.c                            |   2 +-
+ net/ipv6/ip6_offload.c                             |  20 ++-
+ net/ipv6/ip6_output.c                              |   3 -
+ net/ipv6/ping.c                                    |   1 +
+ net/ipv6/sit.c                                     |  19 +++
+ net/ipv6/udp_offload.c                             |   2 +-
+ net/mac80211/ieee80211_i.h                         |  10 +-
+ net/mac80211/mlme.c                                |  24 +++
+ net/mac80211/rx.c                                  |   7 +
+ net/mac80211/sta_info.c                            |  66 +++++---
+ net/mac80211/sta_info.h                            |   7 +-
+ net/mac80211/tx.c                                  |  15 ++
+ net/mac80211/util.c                                |  48 +++---
+ net/mac80211/wme.c                                 |   5 +
+ net/netfilter/nf_conntrack_netlink.c               |  35 ++---
+ net/netfilter/nf_nat_core.c                        |  56 ++++---
+ net/netfilter/nft_meta.c                           |   4 +-
+ net/netfilter/nft_payload.c                        |   3 +-
+ net/netfilter/nft_reject_inet.c                    |   4 +-
+ net/netlink/af_netlink.c                           |   4 +-
+ net/nfc/nci/core.c                                 |   2 +-
+ net/sched/sch_tbf.c                                |  24 +--
+ net/sctp/associola.c                               | 129 ++++++++++------
+ net/sctp/sm_sideeffect.c                           |   7 +-
+ net/sctp/sm_statefuns.c                            |   7 +
+ net/tipc/bearer.c                                  |   7 +-
+ net/tipc/config.c                                  |   2 +-
+ net/tipc/core.c                                    | 109 +++++++------
+ net/tipc/core.h                                    |   1 -
+ net/tipc/name_table.c                              |   3 -
+ net/tipc/netlink.c                                 |   8 -
+ net/tipc/ref.c                                     |   3 -
+ net/tipc/server.c                                  |   5 -
+ net/tipc/server.h                                  |   2 -
+ net/tipc/socket.c                                  |   8 -
+ net/wireless/reg.c                                 |  12 +-
+ net/xfrm/xfrm_policy.c                             |   2 +-
+ net/xfrm/xfrm_state.c                              |  23 ++-
+ net/xfrm/xfrm_user.c                               |   5 -
+ 110 files changed, 1108 insertions(+), 690 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/net/opencores-ethoc.txt
+Merging ipsec/master (3a9016f97fdc xfrm: Fix unlink race when policies are deleted.)
+$ git merge ipsec/master
+Already up-to-date.
+Merging sound-current/for-linus (a6b92b6650d0 ALSA: hda - Added inverted digital-mic handling for Acer TravelMate 8371)
+$ git merge sound-current/for-linus
+Merge made by the 'recursive' strategy.
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+Merging pci-current/for-linus (fc40363b2140 ahci: Fix broken fallback to single MSI mode)
+$ git merge pci-current/for-linus
+Already up-to-date.
+Merging wireless/master (adb07df1e039 mwifiex: do not advertise usb autosuspend support)
+$ git merge wireless/master
+Already up-to-date.
+Merging driver-core.current/driver-core-linus (0414855fdc4a Linux 3.14-rc5)
+$ git merge driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (0414855fdc4a Linux 3.14-rc5)
+$ git merge tty.current/tty-linus
+Already up-to-date.
+Merging usb.current/usb-linus (0414855fdc4a Linux 3.14-rc5)
+$ git merge usb.current/usb-linus
+Already up-to-date.
+Merging staging.current/staging-linus (0414855fdc4a Linux 3.14-rc5)
+$ git merge staging.current/staging-linus
+Already up-to-date.
+Merging char-misc.current/char-misc-linus (0414855fdc4a Linux 3.14-rc5)
+$ git merge char-misc.current/char-misc-linus
+Already up-to-date.
+Merging input-current/for-linus (70b0052425ff Input: da9052_onkey - use correct register bit for key status)
+$ git merge input-current/for-linus
+Merge made by the 'recursive' strategy.
+ drivers/input/keyboard/adp5588-keys.c | 12 +++++++++++-
+ drivers/input/misc/da9052_onkey.c     | 29 ++++++++++++++++-------------
+ 2 files changed, 27 insertions(+), 14 deletions(-)
+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 (ee97dc7db4cb crypto: s390 - fix des and des3_ede ctr concurrency issue)
+$ git merge crypto-current/master
+Already up-to-date.
+Merging ide/master (738b52bb9845 Merge tag 'microblaze-3.14-rc3' of git://git.monstr.eu/linux-2.6-microblaze)
+$ git merge ide/master
+Already up-to-date.
+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 (6375b768a985 drm/i915: Reject >165MHz modes w/ DVI monitors)
+$ git merge drm-intel-fixes/for-linux-next-fixes
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/i915/i915_drv.c        | 23 +++++++++--------------
+ drivers/gpu/drm/i915/i915_gem_stolen.c | 19 ++++++++++++++++---
+ drivers/gpu/drm/i915/intel_display.c   |  8 ++++----
+ drivers/gpu/drm/i915/intel_hdmi.c      |  6 +++---
+ drivers/gpu/drm/i915/intel_panel.c     |  4 ++--
+ drivers/gpu/drm/i915/intel_pm.c        |  6 ++++--
+ 6 files changed, 38 insertions(+), 28 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 (67a2635aa64a ARC: [clockevent] simplify timer ISR)
+$ git merge arc/for-next
+Merge made by the 'recursive' strategy.
+ arch/arc/boot/.gitignore         |  1 +
+ arch/arc/include/asm/linkage.h   | 14 -----------
+ arch/arc/kernel/ctx_sw_asm.S     |  2 +-
+ arch/arc/kernel/entry.S          | 52 ++++++++++++++++++++--------------------
+ arch/arc/kernel/time.c           | 37 +++++++++++++---------------
+ arch/arc/lib/memcmp.S            |  6 ++---
+ arch/arc/lib/memcpy-700.S        |  6 ++---
+ arch/arc/lib/memset.S            | 10 ++++----
+ arch/arc/lib/strchr-700.S        |  6 ++---
+ arch/arc/lib/strcmp.S            |  6 ++---
+ arch/arc/lib/strcpy-700.S        |  6 ++---
+ arch/arc/lib/strlen.S            |  6 ++---
+ arch/arc/mm/init.c               | 27 +++++++++++++++++++++
+ arch/arc/mm/tlbex.S              | 10 ++++----
+ arch/arc/plat-arcfpga/Kconfig    |  1 -
+ arch/arc/plat-arcfpga/platform.c |  6 ++---
+ 16 files changed, 101 insertions(+), 95 deletions(-)
+Merging arm/for-next (93c95d4353c6 Merge branch 'devel-stable' into for-next)
+$ git merge arm/for-next
+Auto-merging arch/arm/mm/dma-mapping.c
+Removing arch/arm/include/asm/system.h
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                           |   2 +-
+ arch/arm/common/Makefile                   |   1 +
+ arch/arm/include/asm/assembler.h           |   8 +-
+ arch/arm/include/asm/atomic.h              |  44 +-
+ arch/arm/include/asm/cmpxchg.h             |   6 +
+ arch/arm/include/asm/cputype.h             |   1 +
+ arch/arm/include/asm/futex.h               |   9 +-
+ arch/arm/include/asm/hw_breakpoint.h       |   1 +
+ arch/arm/include/asm/hwcap.h               |   3 +-
+ arch/arm/include/asm/jump_label.h          |   1 -
+ arch/arm/include/asm/pgtable-2level.h      |   1 +
+ arch/arm/include/asm/pgtable.h             |   7 +-
+ arch/arm/include/asm/ptrace.h              |   8 +-
+ arch/arm/include/asm/sync_bitops.h         |   1 -
+ arch/arm/include/asm/system.h              |   7 -
+ arch/arm/include/asm/uaccess.h             |   2 +-
+ arch/arm/include/uapi/asm/hwcap.h          |   9 +
+ arch/arm/kernel/bios32.c                   |  37 +-
+ arch/arm/kernel/hw_breakpoint.c            |   3 +-
+ arch/arm/kernel/process.c                  |   9 +-
+ arch/arm/kernel/setup.c                    |  16 +
+ arch/arm/kernel/unwind.c                   | 137 ++++--
+ arch/arm/lib/bitops.h                      |   5 +
+ arch/arm/lib/copy_template.S               |  36 +-
+ arch/arm/lib/csumpartialcopygeneric.S      |  96 ++---
+ arch/arm/lib/io-readsl.S                   |  12 +-
+ arch/arm/lib/io-writesl.S                  |  12 +-
+ arch/arm/lib/memmove.S                     |  36 +-
+ arch/arm/lib/uaccess.S                     | 192 ++++-----
+ arch/arm/mach-footbridge/dc21285-timer.c   |   4 +-
+ arch/arm/mach-gemini/idle.c                |   2 +-
+ arch/arm/mach-omap1/dma.c                  | 191 ++++-----
+ arch/arm/mach-omap2/am35xx-emac.c          |   1 -
+ arch/arm/mach-omap2/dma.c                  | 183 ++++----
+ arch/arm/mach-sa1100/collie.c              |  33 ++
+ arch/arm/mach-sa1100/h3100.c               |   7 -
+ arch/arm/mach-sa1100/h3600.c               |   7 -
+ arch/arm/mach-sa1100/h3xxx.c               |  58 ++-
+ arch/arm/mach-sa1100/include/mach/collie.h |   2 +-
+ arch/arm/mach-sa1100/include/mach/h3xxx.h  |  11 -
+ arch/arm/mach-vexpress/Makefile            |   3 +
+ arch/arm/mm/Kconfig                        |   3 +-
+ arch/arm/mm/cache-feroceon-l2.c            |   4 +-
+ arch/arm/mm/dma-mapping.c                  |   3 -
+ arch/arm/mm/mmu.c                          |  10 +
+ arch/arm/mm/proc-macros.S                  |  19 +-
+ arch/arm/mm/proc-v7-2level.S               |   7 -
+ arch/arm/mm/proc-v7.S                      |  11 +
+ arch/arm/plat-omap/dma.c                   |  17 +-
+ drivers/amba/bus.c                         |   4 +-
+ drivers/dma/omap-dma.c                     | 659 ++++++++++++++++++++++++++---
+ drivers/mmc/host/mmci.h                    |   9 +-
+ drivers/usb/gadget/lpc32xx_udc.c           |   1 -
+ include/linux/omap-dma.h                   |  25 +-
+ 54 files changed, 1295 insertions(+), 681 deletions(-)
+ delete mode 100644 arch/arm/include/asm/system.h
+Merging arm-perf/for-next/perf (8e781f65423c ARM: perf: add support for the Cortex-A12 PMU)
+$ git merge arm-perf/for-next/perf
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/arm/pmu.txt |  10 +-
+ arch/arm/include/asm/pmu.h                    |   2 +
+ arch/arm/kernel/perf_event.c                  |  27 +-
+ arch/arm/kernel/perf_event_cpu.c              | 113 ++--
+ arch/arm/kernel/perf_event_v7.c               | 717 ++++++++++++++++++++++++++
+ 5 files changed, 824 insertions(+), 45 deletions(-)
+Merging arm-soc/for-next (403172d8553f arm-soc: select CLKSRC_OF as an intermediate fixup)
+$ git merge arm-soc/for-next
+Auto-merging drivers/clocksource/qcom-timer.c
+Removing arch/arm/plat-omap/include/plat/timex.h
+Removing arch/arm/mach-w90x900/include/mach/timex.h
+Removing arch/arm/mach-virt/virt.c
+Removing arch/arm/mach-virt/Makefile
+Removing arch/arm/mach-virt/Kconfig
+Removing arch/arm/mach-versatile/include/mach/timex.h
+Removing arch/arm/mach-ux500/board-mop500-pins.c
+Removing arch/arm/mach-spear/include/mach/timex.h
+Removing arch/arm/mach-shmobile/include/mach/timex.h
+Removing arch/arm/mach-sa1100/include/mach/timex.h
+Removing arch/arm/mach-s5pv210/include/mach/timex.h
+Removing arch/arm/mach-s5pc100/include/mach/timex.h
+Removing arch/arm/mach-s5p64x0/include/mach/timex.h
+Removing arch/arm/mach-s3c64xx/include/mach/timex.h
+Removing arch/arm/mach-s3c24xx/include/mach/timex.h
+Removing arch/arm/mach-rpc/include/mach/timex.h
+Removing arch/arm/mach-realview/include/mach/timex.h
+Auto-merging arch/arm/mach-qcom/scm-boot.h
+Auto-merging arch/arm/mach-qcom/board.c
+Removing arch/arm/mach-pxa/include/mach/timex.h
+Removing arch/arm/mach-orion5x/include/mach/timex.h
+Removing arch/arm/mach-omap2/include/mach/timex.h
+Removing arch/arm/mach-omap1/include/mach/timex.h
+Removing arch/arm/mach-netx/include/mach/timex.h
+Auto-merging arch/arm/mach-mvebu/board-v7.c
+Removing arch/arm/mach-mv78xx0/include/mach/timex.h
+Removing arch/arm/mach-msm/platsmp.c
+Removing arch/arm/mach-msm/include/mach/timex.h
+Removing arch/arm/mach-msm/hotplug.c
+Removing arch/arm/mach-msm/headsmp.S
+Removing arch/arm/mach-mmp/include/mach/timex.h
+Removing arch/arm/mach-lpc32xx/include/mach/timex.h
+Removing arch/arm/mach-ks8695/include/mach/timex.h
+Removing arch/arm/mach-kirkwood/include/mach/timex.h
+Removing arch/arm/mach-ixp4xx/include/mach/timex.h
+Removing arch/arm/mach-iop33x/include/mach/timex.h
+Removing arch/arm/mach-iop32x/include/mach/timex.h
+Removing arch/arm/mach-iop13xx/include/mach/timex.h
+Removing arch/arm/mach-integrator/include/mach/timex.h
+Removing arch/arm/mach-gemini/include/mach/timex.h
+Removing arch/arm/mach-footbridge/include/mach/timex.h
+Removing arch/arm/mach-exynos/include/mach/timex.h
+Removing arch/arm/mach-ep93xx/include/mach/timex.h
+Removing arch/arm/mach-efm32/include/mach/timex.h
+Removing arch/arm/mach-efm32/include/mach/entry-macro.S
+Removing arch/arm/mach-ebsa110/include/mach/timex.h
+Removing arch/arm/mach-dove/include/mach/timex.h
+Removing arch/arm/mach-davinci/include/mach/timex.h
+Removing arch/arm/mach-clps711x/include/mach/timex.h
+Removing arch/arm/mach-at91/include/mach/timex.h
+Auto-merging arch/arm/configs/mvebu_v7_defconfig
+Removing arch/arm/boot/dts/r8a7791-koelsch-reference.dts
+Removing arch/arm/boot/dts/imx53-evk.dts
+Auto-merging arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
+Auto-merging arch/arm/Kconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/arm/Marvell/README                   |  12 +-
+ .../devicetree/bindings/arm/armada-375.txt         |   9 +
+ .../devicetree/bindings/arm/armada-38x.txt         |  10 +
+ Documentation/devicetree/bindings/arm/cpus.txt     |  25 +-
+ .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  30 +
+ .../devicetree/bindings/arm/msm/qcom,saw2.txt      |  35 +
+ .../bindings/arm/mvebu-system-controller.txt       |   3 +-
+ .../devicetree/bindings/clock/arm-integrator.txt   |  34 +
+ .../interrupt-controller/cirrus,clps711x-intc.txt  |  41 +
+ .../devicetree/bindings/serial/atmel-usart.txt     |   3 +
+ .../devicetree/bindings/vendor-prefixes.txt        |   3 +
+ .../devicetree/bindings/watchdog/marvel.txt        |  11 +-
+ MAINTAINERS                                        |  10 +-
+ arch/arm/Kconfig                                   |  28 +-
+ arch/arm/Kconfig.debug                             |   2 +-
+ arch/arm/Makefile                                  |   2 +-
+ arch/arm/arm-soc-for-next-contents.txt             | 104 +++
+ arch/arm/boot/dts/Makefile                         |  46 +-
+ arch/arm/boot/dts/armada-370-db.dts                |  56 ++
+ arch/arm/boot/dts/armada-370-mirabox.dts           |   7 +-
+ arch/arm/boot/dts/armada-370-rd.dts                |   6 +-
+ arch/arm/boot/dts/armada-370-xp.dtsi               |   4 +
+ arch/arm/boot/dts/armada-370.dtsi                  |  33 +
+ arch/arm/boot/dts/armada-xp-axpwifiap.dts          |   6 +-
+ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts   |  12 +-
+ arch/arm/boot/dts/armada-xp.dtsi                   |   6 +
+ arch/arm/boot/dts/dove.dtsi                        |   8 +
+ arch/arm/boot/dts/imx23-evk.dts                    |   8 +-
+ arch/arm/boot/dts/imx23-olinuxino.dts              |   5 +-
+ arch/arm/boot/dts/imx23-stmp378x_devb.dts          |   5 +-
+ arch/arm/boot/dts/imx23.dtsi                       |   8 +-
+ arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi       |  73 ++
+ .../boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts  | 174 ++++
+ arch/arm/boot/dts/imx25-pinfunc.h                  | 494 +++++++++++
+ arch/arm/boot/dts/imx25.dtsi                       |  18 +-
+ arch/arm/boot/dts/imx27-apf27.dts                  |  38 +
+ arch/arm/boot/dts/imx27-apf27dev.dts               | 149 +++-
+ arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts   |  61 +-
+ arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts   |  42 +-
+ arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts     |  97 ++-
+ ...ycore-som.dts => imx27-phytec-phycore-som.dtsi} |  95 ++-
+ arch/arm/boot/dts/imx27-pinfunc.h                  | 526 ++++++++++++
+ arch/arm/boot/dts/imx27.dtsi                       | 151 ++--
+ arch/arm/boot/dts/imx28-apf28dev.dts               |  29 +-
+ arch/arm/boot/dts/imx28-apx4devkit.dts             |   5 +-
+ arch/arm/boot/dts/imx28-cfa10036.dts               |   2 +
+ arch/arm/boot/dts/imx28-cfa10037.dts               |   7 +-
+ arch/arm/boot/dts/imx28-cfa10049.dts               |  31 +-
+ arch/arm/boot/dts/imx28-cfa10057.dts               |   7 +-
+ arch/arm/boot/dts/imx28-cfa10058.dts               |   7 +-
+ arch/arm/boot/dts/imx28-duckbill.dts               | 121 +++
+ arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts       |  71 ++
+ arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts       |  50 ++
+ arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi       | 326 +++++++
+ arch/arm/boot/dts/imx28-evk.dts                    |  24 +-
+ arch/arm/boot/dts/imx28-m28cu3.dts                 |  17 +-
+ arch/arm/boot/dts/imx28-m28evk.dts                 |  18 +-
+ arch/arm/boot/dts/imx28-sps1.dts                   |   7 +-
+ arch/arm/boot/dts/imx28-tx28.dts                   |  23 +-
+ arch/arm/boot/dts/imx28.dtsi                       |  65 +-
+ arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi       |  81 ++
+ .../boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts  | 143 ++++
+ arch/arm/boot/dts/imx35.dtsi                       | 359 ++++++++
+ arch/arm/boot/dts/imx50-evk.dts                    | 119 +++
+ arch/arm/boot/dts/imx50-pinfunc.h                  | 923 ++++++++++++++++++++
+ arch/arm/boot/dts/imx50.dtsi                       | 478 +++++++++++
+ arch/arm/boot/dts/imx51-apf51.dts                  |  40 +-
+ arch/arm/boot/dts/imx51-apf51dev.dts               | 102 ++-
+ arch/arm/boot/dts/imx51-babbage.dts                | 238 +++++-
+ arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi       |  93 ++
+ .../boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts  | 175 ++++
+ arch/arm/boot/dts/imx51.dtsi                       | 459 ++--------
+ arch/arm/boot/dts/imx53-ard.dts                    |  33 +-
+ arch/arm/boot/dts/imx53-evk.dts                    | 126 ---
+ arch/arm/boot/dts/imx53-m53evk.dts                 | 233 ++++-
+ arch/arm/boot/dts/imx53-mba53.dts                  |  40 +-
+ arch/arm/boot/dts/imx53-qsb-common.dtsi            | 336 ++++++++
+ arch/arm/boot/dts/imx53-qsb.dts                    | 210 +----
+ arch/arm/boot/dts/imx53-qsrb.dts                   | 158 ++++
+ arch/arm/boot/dts/imx53-smd.dts                    | 119 ++-
+ arch/arm/boot/dts/imx53-tqma53.dtsi                | 175 +++-
+ arch/arm/boot/dts/imx53-tx53-x03x.dts              | 315 +++++++
+ arch/arm/boot/dts/imx53-tx53-x13x.dts              | 243 ++++++
+ arch/arm/boot/dts/imx53-tx53.dtsi                  | 511 ++++++++++-
+ arch/arm/boot/dts/imx53-voipac-bsb.dts             | 159 ++++
+ arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi        | 277 ++++++
+ arch/arm/boot/dts/imx53.dtsi                       | 663 +++------------
+ arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts         |  23 +
+ arch/arm/boot/dts/imx6dl-gw51xx.dts                |  19 +
+ arch/arm/boot/dts/imx6dl-gw52xx.dts                |  19 +
+ arch/arm/boot/dts/imx6dl-gw53xx.dts                |  19 +
+ arch/arm/boot/dts/imx6dl-gw54xx.dts                |  19 +
+ arch/arm/boot/dts/imx6dl-nitrogen6x.dts            |  21 +
+ arch/arm/boot/dts/imx6dl-pinfunc.h                 |   2 +
+ arch/arm/boot/dts/imx6dl-sabrelite.dts             |  20 +
+ arch/arm/boot/dts/imx6dl.dtsi                      |  29 +-
+ arch/arm/boot/dts/imx6q-arm2.dts                   | 140 ++-
+ arch/arm/boot/dts/imx6q-cm-fx6.dts                 | 107 +++
+ arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts          |  23 +
+ arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts            | 372 ++++++++
+ arch/arm/boot/dts/imx6q-gk802.dts                  | 171 ++++
+ arch/arm/boot/dts/imx6q-gw51xx.dts                 |  19 +
+ arch/arm/boot/dts/imx6q-gw52xx.dts                 |  23 +
+ arch/arm/boot/dts/imx6q-gw53xx.dts                 |  23 +
+ arch/arm/boot/dts/imx6q-gw5400-a.dts               | 546 ++++++++++++
+ arch/arm/boot/dts/imx6q-gw54xx.dts                 |  23 +
+ arch/arm/boot/dts/imx6q-nitrogen6x.dts             |  25 +
+ arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi         |  85 +-
+ arch/arm/boot/dts/imx6q-pinfunc.h                  |   2 +
+ arch/arm/boot/dts/imx6q-sabrelite.dts              | 178 +---
+ arch/arm/boot/dts/imx6q-sbc6x.dts                  |  58 +-
+ arch/arm/boot/dts/imx6q-udoo.dts                   |  54 +-
+ arch/arm/boot/dts/imx6q.dtsi                       |  21 +-
+ arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi       | 199 +++++
+ arch/arm/boot/dts/imx6qdl-gw51xx.dtsi              | 374 ++++++++
+ arch/arm/boot/dts/imx6qdl-gw52xx.dtsi              | 490 +++++++++++
+ arch/arm/boot/dts/imx6qdl-gw53xx.dtsi              | 553 ++++++++++++
+ arch/arm/boot/dts/imx6qdl-gw54xx.dtsi              | 580 +++++++++++++
+ arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi          | 422 +++++++++
+ arch/arm/boot/dts/imx6qdl-sabreauto.dtsi           | 246 +++++-
+ arch/arm/boot/dts/imx6qdl-sabrelite.dtsi           | 423 ++++++++++
+ arch/arm/boot/dts/imx6qdl-sabresd.dtsi             | 272 +++++-
+ arch/arm/boot/dts/imx6qdl-wandboard.dtsi           | 128 ++-
+ arch/arm/boot/dts/imx6qdl.dtsi                     | 938 +++------------------
+ arch/arm/boot/dts/imx6sl-evk.dts                   | 210 ++++-
+ arch/arm/boot/dts/imx6sl.dtsi                      | 385 +++------
+ arch/arm/boot/dts/integratorap.dts                 |  35 +
+ arch/arm/boot/dts/integratorcp.dts                 | 102 ++-
+ arch/arm/boot/dts/kirkwood-b3.dts                  | 204 +++++
+ arch/arm/boot/dts/kirkwood-rd88f6192.dts           | 112 +++
+ arch/arm/boot/dts/kirkwood-rd88f6281-a0.dts        |  26 +
+ arch/arm/boot/dts/kirkwood-rd88f6281-a1.dts        |  31 +
+ arch/arm/boot/dts/kirkwood-rd88f6281.dtsi          | 152 ++++
+ arch/arm/boot/dts/kirkwood-ts419-6281.dts          |  20 +
+ arch/arm/boot/dts/kirkwood-ts419-6282.dts          |  32 +
+ arch/arm/boot/dts/kirkwood-ts419.dtsi              |  75 ++
+ arch/arm/boot/dts/kirkwood.dtsi                    |   2 +-
+ arch/arm/boot/dts/qcom-msm8660-surf.dts            |  59 +-
+ arch/arm/boot/dts/qcom-msm8660.dtsi                |  87 ++
+ arch/arm/boot/dts/qcom-msm8960-cdp.dts             |  66 +-
+ arch/arm/boot/dts/qcom-msm8960.dtsi                | 135 +++
+ arch/arm/boot/dts/qcom-msm8974.dtsi                |  81 ++
+ arch/arm/boot/dts/r7s72100-genmai-reference.dts    |   2 +-
+ arch/arm/boot/dts/r7s72100.dtsi                    |  75 ++
+ arch/arm/boot/dts/r8a7778-bockw-reference.dts      |   4 +-
+ arch/arm/boot/dts/r8a7790-lager.dts                |   4 +
+ arch/arm/boot/dts/r8a7790.dtsi                     | 131 ++-
+ arch/arm/boot/dts/r8a7791-koelsch-reference.dts    | 115 ---
+ arch/arm/boot/dts/r8a7791-koelsch.dts              | 101 ++-
+ arch/arm/boot/dts/r8a7791.dtsi                     | 222 ++++-
+ arch/arm/boot/dts/ste-href-ab8500.dtsi             | 428 ++++++++++
+ arch/arm/boot/dts/ste-href-ab8505.dtsi             | 240 ++++++
+ arch/arm/boot/dts/ste-hrefprev60.dtsi              |   1 +
+ arch/arm/boot/dts/ste-hrefv60plus.dtsi             |   1 +
+ arch/arm/boot/dts/ste-snowball.dts                 |   1 +
+ arch/arm/boot/dts/vf610-cosmic.dts                 |  29 +-
+ arch/arm/boot/dts/vf610-twr.dts                    |  66 +-
+ arch/arm/boot/dts/vf610.dtsi                       | 207 +----
+ arch/arm/common/timer-sp.c                         |   8 +-
+ arch/arm/configs/ape6evm_defconfig                 |   2 +
+ arch/arm/configs/armadillo800eva_defconfig         |   2 +
+ arch/arm/configs/bockw_defconfig                   |   2 +
+ arch/arm/configs/clps711x_defconfig                |   3 +-
+ arch/arm/configs/dove_defconfig                    |   3 +-
+ arch/arm/configs/genmai_defconfig                  |   4 +
+ arch/arm/configs/koelsch_defconfig                 |  12 +-
+ arch/arm/configs/kzm9d_defconfig                   |   2 +
+ arch/arm/configs/kzm9g_defconfig                   |   2 +
+ arch/arm/configs/lager_defconfig                   |  17 +
+ arch/arm/configs/mackerel_defconfig                |   2 +
+ arch/arm/configs/marzen_defconfig                  |   2 +
+ arch/arm/configs/multi_v7_defconfig                |  14 +
+ .../{mvebu_defconfig => mvebu_v7_defconfig}        |   9 +
+ arch/arm/include/asm/smp.h                         |   9 +
+ arch/arm/include/asm/timex.h                       |   6 -
+ arch/arm/kernel/devtree.c                          |  40 +
+ arch/arm/mach-at91/at91rm9200.c                    |   1 +
+ arch/arm/mach-at91/at91rm9200_devices.c            |  11 +-
+ arch/arm/mach-at91/at91rm9200_time.c               |   1 +
+ arch/arm/mach-at91/at91sam9260.c                   |   1 +
+ arch/arm/mach-at91/at91sam9260_devices.c           |   8 +
+ arch/arm/mach-at91/at91sam9261.c                   |   1 +
+ arch/arm/mach-at91/at91sam9261_devices.c           |   5 +
+ arch/arm/mach-at91/at91sam9263.c                   |   1 +
+ arch/arm/mach-at91/at91sam9263_devices.c           |   5 +
+ arch/arm/mach-at91/at91sam926x_time.c              |   1 +
+ arch/arm/mach-at91/at91sam9g45.c                   |   1 +
+ arch/arm/mach-at91/at91sam9g45_devices.c           |   6 +
+ arch/arm/mach-at91/at91sam9rl.c                    |   1 +
+ arch/arm/mach-at91/at91sam9rl_devices.c            |   6 +
+ arch/arm/mach-at91/at91x40.c                       |   2 +-
+ arch/arm/mach-at91/at91x40_time.c                  |   1 +
+ arch/arm/mach-at91/board-gsia18s.c                 |   1 +
+ arch/arm/mach-at91/board-pcontrol-g20.c            |   1 +
+ arch/arm/mach-at91/board-stamp9g20.c               |   1 +
+ arch/arm/mach-at91/include/mach/at91x40.h          |   2 +
+ arch/arm/mach-at91/include/mach/timex.h            |  37 -
+ arch/arm/mach-at91/pm.c                            |   1 +
+ arch/arm/mach-bcm/Kconfig                          |   5 -
+ arch/arm/mach-bcm2835/Kconfig                      |   4 -
+ arch/arm/mach-berlin/Kconfig                       |   4 -
+ arch/arm/mach-clps711x/Kconfig                     |  14 -
+ arch/arm/mach-clps711x/board-autcpu12.c            |   4 +-
+ arch/arm/mach-clps711x/board-cdb89712.c            |   2 -
+ arch/arm/mach-clps711x/board-clep7312.c            |   2 -
+ arch/arm/mach-clps711x/board-edb7211.c             |   2 -
+ arch/arm/mach-clps711x/board-p720t.c               |   2 -
+ arch/arm/mach-clps711x/common.c                    | 201 +----
+ arch/arm/mach-clps711x/common.h                    |   5 +-
+ arch/arm/mach-clps711x/include/mach/clps711x.h     |  16 -
+ arch/arm/mach-clps711x/include/mach/hardware.h     |  17 -
+ arch/arm/mach-clps711x/include/mach/timex.h        |   2 -
+ arch/arm/mach-cns3xxx/Kconfig                      |   3 -
+ arch/arm/mach-davinci/aemif.c                      | 107 ++-
+ arch/arm/mach-davinci/board-da830-evm.c            |   3 +
+ arch/arm/mach-davinci/board-da850-evm.c            |   3 +
+ arch/arm/mach-davinci/board-dm644x-evm.c           |   5 +
+ arch/arm/mach-davinci/board-dm646x-evm.c           |   3 +
+ arch/arm/mach-davinci/board-mityomapl138.c         |   4 +
+ arch/arm/mach-davinci/include/mach/timex.h         |  22 -
+ arch/arm/mach-dove/include/mach/bridge-regs.h      |   1 +
+ arch/arm/mach-dove/include/mach/timex.h            |   9 -
+ arch/arm/mach-ebsa110/include/mach/timex.h         |  19 -
+ arch/arm/mach-efm32/include/mach/entry-macro.S     |   4 -
+ arch/arm/mach-efm32/include/mach/timex.h           |   3 -
+ arch/arm/mach-ep93xx/core.c                        |   2 +-
+ arch/arm/mach-ep93xx/include/mach/timex.h          |   5 -
+ arch/arm/mach-exynos/include/mach/timex.h          |  29 -
+ arch/arm/mach-footbridge/include/mach/timex.h      |  18 -
+ arch/arm/mach-gemini/include/mach/timex.h          |  13 -
+ arch/arm/mach-highbank/Kconfig                     |   7 -
+ arch/arm/mach-hisi/Kconfig                         |   4 -
+ arch/arm/mach-imx/Kconfig                          |  14 -
+ arch/arm/mach-integrator/Kconfig                   |   3 +
+ arch/arm/mach-integrator/impd1.c                   |  81 +-
+ arch/arm/mach-integrator/include/mach/timex.h      |  26 -
+ arch/arm/mach-integrator/integrator_ap.c           |  19 +-
+ arch/arm/mach-integrator/integrator_cp.c           |   6 -
+ arch/arm/mach-iop13xx/include/mach/timex.h         |   1 -
+ arch/arm/mach-iop32x/include/mach/timex.h          |   6 -
+ arch/arm/mach-iop33x/include/mach/timex.h          |   6 -
+ arch/arm/mach-ixp4xx/common.c                      |  14 +-
+ arch/arm/mach-ixp4xx/include/mach/timex.h          |  16 -
+ arch/arm/mach-keystone/Kconfig                     |   4 -
+ arch/arm/mach-kirkwood/include/mach/bridge-regs.h  |   1 +
+ arch/arm/mach-kirkwood/include/mach/timex.h        |  10 -
+ arch/arm/mach-ks8695/include/mach/timex.h          |  21 -
+ arch/arm/mach-lpc32xx/include/mach/timex.h         |  28 -
+ arch/arm/mach-mmp/include/mach/timex.h             |  13 -
+ arch/arm/mach-mmp/time.c                           |  12 +-
+ arch/arm/mach-moxart/Kconfig                       |   5 -
+ arch/arm/mach-msm/Kconfig                          |  54 +-
+ arch/arm/mach-msm/Makefile                         |   8 -
+ arch/arm/mach-msm/common.h                         |   3 -
+ arch/arm/mach-msm/headsmp.S                        |  39 -
+ arch/arm/mach-msm/hotplug.c                        |  74 --
+ arch/arm/mach-msm/include/mach/timex.h             |  21 -
+ arch/arm/mach-msm/platsmp.c                        | 161 ----
+ arch/arm/mach-mv78xx0/include/mach/bridge-regs.h   |   1 +
+ arch/arm/mach-mv78xx0/include/mach/timex.h         |   9 -
+ arch/arm/mach-mvebu/Kconfig                        |  43 +-
+ arch/arm/mach-mvebu/Makefile                       |   2 +-
+ .../arm/mach-mvebu/{armada-370-xp.c => board-v7.c} |  58 +-
+ arch/arm/mach-mvebu/system-controller.c            |  23 +-
+ arch/arm/mach-mxs/Kconfig                          |   4 -
+ arch/arm/mach-mxs/mach-mxs.c                       |  33 +
+ arch/arm/mach-netx/include/mach/timex.h            |  20 -
+ arch/arm/mach-netx/time.c                          |  11 +-
+ arch/arm/mach-nomadik/Kconfig                      |   5 -
+ arch/arm/mach-nspire/Kconfig                       |   5 -
+ arch/arm/mach-omap1/include/mach/timex.h           |   5 -
+ arch/arm/mach-omap2/Kconfig                        |  17 -
+ arch/arm/mach-omap2/cclock3xxx_data.c              |   2 +
+ arch/arm/mach-omap2/cpuidle44xx.c                  |   8 +-
+ arch/arm/mach-omap2/dpll3xxx.c                     |  92 +-
+ arch/arm/mach-omap2/include/mach/timex.h           |   5 -
+ arch/arm/mach-omap2/omap_hwmod.c                   |  20 +-
+ arch/arm/mach-omap2/omap_hwmod_7xx_data.c          |   9 +-
+ arch/arm/mach-omap2/pdata-quirks.c                 |  21 +-
+ arch/arm/mach-omap2/prminst44xx.c                  |   4 +-
+ arch/arm/mach-orion5x/include/mach/bridge-regs.h   |   1 +
+ arch/arm/mach-orion5x/include/mach/timex.h         |  11 -
+ arch/arm/mach-picoxcell/Kconfig                    |   5 -
+ arch/arm/mach-prima2/Kconfig                       |   6 -
+ arch/arm/mach-pxa/include/mach/timex.h             |  34 -
+ arch/arm/mach-qcom/Kconfig                         |  33 +
+ arch/arm/mach-qcom/Makefile                        |   5 +
+ .../arm/{mach-msm/board-dt.c => mach-qcom/board.c} |  23 +-
+ arch/arm/mach-qcom/platsmp.c                       | 378 +++++++++
+ arch/arm/{mach-msm => mach-qcom}/scm-boot.c        |   0
+ arch/arm/{mach-msm => mach-qcom}/scm-boot.h        |   8 +-
+ arch/arm/{mach-msm => mach-qcom}/scm.c             |   0
+ arch/arm/{mach-msm => mach-qcom}/scm.h             |   0
+ arch/arm/mach-realview/include/mach/timex.h        |  23 -
+ arch/arm/mach-rockchip/Kconfig                     |   3 -
+ arch/arm/mach-rpc/include/mach/timex.h             |  17 -
+ arch/arm/mach-rpc/time.c                           |  15 +-
+ arch/arm/mach-s3c24xx/include/mach/timex.h         |  24 -
+ arch/arm/mach-s3c64xx/include/mach/timex.h         |  24 -
+ arch/arm/mach-s5p64x0/include/mach/timex.h         |  27 -
+ arch/arm/mach-s5pc100/include/mach/timex.h         |  24 -
+ arch/arm/mach-s5pv210/include/mach/timex.h         |  29 -
+ arch/arm/mach-sa1100/include/mach/timex.h          |  12 -
+ arch/arm/mach-sa1100/time.c                        |   8 +-
+ arch/arm/mach-shmobile/Kconfig                     |  19 +-
+ arch/arm/mach-shmobile/board-bockw.c               |  24 +-
+ arch/arm/mach-shmobile/board-genmai.c              |  64 ++
+ arch/arm/mach-shmobile/board-koelsch-reference.c   |   4 +-
+ arch/arm/mach-shmobile/board-koelsch.c             | 131 +++
+ arch/arm/mach-shmobile/board-kzm9d-reference.c     |   5 +-
+ arch/arm/mach-shmobile/board-lager-reference.c     |   4 +-
+ arch/arm/mach-shmobile/board-lager.c               | 354 +++++++-
+ arch/arm/mach-shmobile/clock-r7s72100.c            |   4 +
+ arch/arm/mach-shmobile/clock-r8a7779.c             |  27 +-
+ arch/arm/mach-shmobile/clock-r8a7790.c             | 140 +--
+ arch/arm/mach-shmobile/clock-r8a7791.c             |  81 +-
+ arch/arm/mach-shmobile/include/mach/common.h       |   1 -
+ arch/arm/mach-shmobile/include/mach/head-kzm9g.txt | 410 +++++++++
+ arch/arm/mach-shmobile/include/mach/r8a7790.h      |  25 +
+ arch/arm/mach-shmobile/include/mach/timex.h        |   6 -
+ arch/arm/mach-shmobile/include/mach/zboot.h        |   3 +
+ arch/arm/mach-shmobile/include/mach/zboot_macros.h |  43 +
+ arch/arm/mach-shmobile/setup-emev2.c               |   2 +-
+ arch/arm/mach-shmobile/setup-r8a7790.c             |  90 ++
+ arch/arm/mach-socfpga/Kconfig                      |   7 -
+ arch/arm/mach-spear/Kconfig                        |  10 -
+ arch/arm/mach-spear/include/mach/timex.h           |  19 -
+ arch/arm/mach-sti/Kconfig                          |   4 -
+ arch/arm/mach-sunxi/Kconfig                        |   5 -
+ arch/arm/mach-tegra/Kconfig                        |   8 -
+ arch/arm/mach-u300/Kconfig                         |   6 -
+ arch/arm/mach-ux500/Kconfig                        |   6 -
+ arch/arm/mach-ux500/Makefile                       |   1 -
+ arch/arm/mach-ux500/board-mop500-pins.c            | 291 -------
+ arch/arm/mach-ux500/board-mop500.h                 |   4 -
+ arch/arm/mach-ux500/cpu-db8500.c                   |  10 -
+ arch/arm/mach-versatile/core.c                     |   2 +-
+ arch/arm/mach-versatile/include/mach/timex.h       |  23 -
+ arch/arm/mach-vexpress/Kconfig                     |   5 -
+ arch/arm/mach-virt/Kconfig                         |  10 -
+ arch/arm/mach-virt/Makefile                        |   5 -
+ arch/arm/mach-virt/virt.c                          |  41 -
+ arch/arm/mach-vt8500/Kconfig                       |   4 -
+ arch/arm/mach-w90x900/include/mach/timex.h         |  25 -
+ arch/arm/mach-zynq/Kconfig                         |   7 -
+ arch/arm/plat-omap/include/plat/timex.h            |  33 -
+ arch/arm/plat-orion/common.c                       |  10 +-
+ drivers/bus/arm-cci.c                              |  24 +-
+ drivers/char/hw_random/Kconfig                     |   6 +-
+ drivers/clk/versatile/clk-icst.c                   |  21 +-
+ drivers/clk/versatile/clk-icst.h                   |   1 +
+ drivers/clk/versatile/clk-impd1.c                  |   6 +-
+ drivers/clk/versatile/clk-integrator.c             |  83 +-
+ drivers/clk/versatile/clk-realview.c               |   4 +-
+ drivers/clocksource/Kconfig                        |   3 +
+ drivers/clocksource/Makefile                       |   1 +
+ .../timer.c => drivers/clocksource/qcom-timer.c    |  29 +-
+ drivers/clocksource/timer-marco.c                  |  13 +-
+ drivers/clocksource/timer-prima2.c                 |  16 +-
+ drivers/gpio/Kconfig                               |   2 +-
+ drivers/gpu/drm/msm/Kconfig                        |   2 +-
+ drivers/input/misc/ixp4xx-beeper.c                 |   2 +-
+ drivers/irqchip/Kconfig                            |   8 +
+ drivers/irqchip/Makefile                           |   1 +
+ drivers/irqchip/irq-clps711x.c                     | 243 ++++++
+ drivers/irqchip/irq-gic.c                          |   4 +-
+ drivers/irqchip/irq-vic.c                          |  60 +-
+ drivers/mtd/nand/davinci_nand.c                    |  22 -
+ drivers/power/reset/Kconfig                        |   2 +-
+ drivers/rtc/rtc-at91sam9.c                         |   2 +-
+ drivers/rtc/rtc-pxa.c                              |   1 -
+ drivers/sh/clk/cpg.c                               |  38 +
+ drivers/tty/serial/Kconfig                         |   2 +-
+ drivers/tty/serial/atmel_serial.c                  |  49 +-
+ drivers/watchdog/Kconfig                           |   2 +-
+ drivers/watchdog/orion_wdt.c                       | 381 +++++++--
+ include/asm-generic/vmlinux.lds.h                  |  10 +
+ include/linux/clk/ti.h                             |   4 +
+ include/linux/irqchip/arm-vic.h                    |   6 +-
+ include/linux/platform_data/atmel.h                |   1 +
+ include/linux/platform_data/clk-integrator.h       |   1 -
+ include/linux/platform_data/mtd-davinci-aemif.h    |   5 +-
+ include/linux/sh_clk.h                             |  19 +-
+ 383 files changed, 20048 insertions(+), 5745 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/armada-375.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/armada-38x.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/arm-integrator.txt
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ create mode 100644 arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
+ create mode 100644 arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
+ create mode 100644 arch/arm/boot/dts/imx25-pinfunc.h
+ rename arch/arm/boot/dts/{imx27-phytec-phycore-som.dts => imx27-phytec-phycore-som.dtsi} (61%)
+ create mode 100644 arch/arm/boot/dts/imx27-pinfunc.h
+ create mode 100644 arch/arm/boot/dts/imx28-duckbill.dts
+ create mode 100644 arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts
+ create mode 100644 arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts
+ create mode 100644 arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi
+ create mode 100644 arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
+ create mode 100644 arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
+ create mode 100644 arch/arm/boot/dts/imx35.dtsi
+ create mode 100644 arch/arm/boot/dts/imx50-evk.dts
+ create mode 100644 arch/arm/boot/dts/imx50-pinfunc.h
+ create mode 100644 arch/arm/boot/dts/imx50.dtsi
+ create mode 100644 arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
+ create mode 100644 arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
+ delete mode 100644 arch/arm/boot/dts/imx53-evk.dts
+ create mode 100644 arch/arm/boot/dts/imx53-qsb-common.dtsi
+ create mode 100644 arch/arm/boot/dts/imx53-qsrb.dts
+ create mode 100644 arch/arm/boot/dts/imx53-tx53-x03x.dts
+ create mode 100644 arch/arm/boot/dts/imx53-tx53-x13x.dts
+ create mode 100644 arch/arm/boot/dts/imx53-voipac-bsb.dts
+ create mode 100644 arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-gw51xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-gw52xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-gw53xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-gw54xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-nitrogen6x.dts
+ create mode 100644 arch/arm/boot/dts/imx6dl-sabrelite.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-cm-fx6.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gk802.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gw51xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gw52xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gw53xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gw5400-a.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-gw54xx.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-nitrogen6x.dts
+ create mode 100644 arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-b3.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rd88f6192.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rd88f6281-a0.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rd88f6281-a1.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-ts419-6281.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ts419-6282.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ts419.dtsi
+ create mode 100644 arch/arm/boot/dts/qcom-msm8660.dtsi
+ create mode 100644 arch/arm/boot/dts/qcom-msm8960.dtsi
+ delete mode 100644 arch/arm/boot/dts/r8a7791-koelsch-reference.dts
+ create mode 100644 arch/arm/boot/dts/ste-href-ab8500.dtsi
+ create mode 100644 arch/arm/boot/dts/ste-href-ab8505.dtsi
+ rename arch/arm/configs/{mvebu_defconfig => mvebu_v7_defconfig} (91%)
+ delete mode 100644 arch/arm/mach-at91/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-clps711x/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-davinci/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-dove/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-ebsa110/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-efm32/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-efm32/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-ep93xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-exynos/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-footbridge/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-gemini/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-integrator/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-iop13xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-iop32x/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-iop33x/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-ixp4xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-kirkwood/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-ks8695/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-lpc32xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-mmp/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-msm/headsmp.S
+ delete mode 100644 arch/arm/mach-msm/hotplug.c
+ delete mode 100644 arch/arm/mach-msm/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-msm/platsmp.c
+ delete mode 100644 arch/arm/mach-mv78xx0/include/mach/timex.h
+ rename arch/arm/mach-mvebu/{armada-370-xp.c => board-v7.c} (58%)
+ delete mode 100644 arch/arm/mach-netx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-omap1/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-omap2/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-orion5x/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-pxa/include/mach/timex.h
+ create mode 100644 arch/arm/mach-qcom/Kconfig
+ create mode 100644 arch/arm/mach-qcom/Makefile
+ rename arch/arm/{mach-msm/board-dt.c => mach-qcom/board.c} (52%)
+ create mode 100644 arch/arm/mach-qcom/platsmp.c
+ rename arch/arm/{mach-msm => mach-qcom}/scm-boot.c (100%)
+ rename arch/arm/{mach-msm => mach-qcom}/scm-boot.h (78%)
+ rename arch/arm/{mach-msm => mach-qcom}/scm.c (100%)
+ rename arch/arm/{mach-msm => mach-qcom}/scm.h (100%)
+ delete mode 100644 arch/arm/mach-realview/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-rpc/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-s3c24xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-s3c64xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-s5p64x0/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-s5pc100/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-s5pv210/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-sa1100/include/mach/timex.h
+ create mode 100644 arch/arm/mach-shmobile/include/mach/head-kzm9g.txt
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-spear/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-ux500/board-mop500-pins.c
+ delete mode 100644 arch/arm/mach-versatile/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-virt/Kconfig
+ delete mode 100644 arch/arm/mach-virt/Makefile
+ delete mode 100644 arch/arm/mach-virt/virt.c
+ delete mode 100644 arch/arm/mach-w90x900/include/mach/timex.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/timex.h
+ rename arch/arm/mach-msm/timer.c => drivers/clocksource/qcom-timer.c (98%)
+ create mode 100644 drivers/irqchip/irq-clps711x.c
+Merging bcm2835/for-next (8ac06bb693ca Merge branch 'for-3.15/dt' into for-next)
+$ git merge bcm2835/for-next
+Removing arch/arm/mach-bcm2835/Makefile
+CONFLICT (modify/delete): arch/arm/mach-bcm2835/Kconfig deleted in bcm2835/for-next and modified in HEAD. Version HEAD of arch/arm/mach-bcm2835/Kconfig left in tree.
+Auto-merging arch/arm/mach-bcm/Kconfig
+Auto-merging arch/arm/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f arch/arm/mach-bcm2835/Kconfig
+arch/arm/mach-bcm2835/Kconfig: needs merge
+rm 'arch/arm/mach-bcm2835/Kconfig'
+$ git commit -v -a
+[master 1cb3cefc8b3f] Merge remote-tracking branch 'bcm2835/for-next'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS                                        |  2 +-
+ arch/arm/Kconfig                                   |  2 -
+ arch/arm/Makefile                                  |  1 -
+ arch/arm/boot/dts/bcm2835.dtsi                     | 92 +++++++++++++++-------
+ arch/arm/configs/bcm2835_defconfig                 |  1 +
+ arch/arm/mach-bcm/Kconfig                          | 16 ++++
+ arch/arm/mach-bcm/Makefile                         |  2 +
+ .../bcm2835.c => mach-bcm/board_bcm2835.c}         |  0
+ arch/arm/mach-bcm2835/Kconfig                      | 11 ---
+ arch/arm/mach-bcm2835/Makefile                     |  1 -
+ 10 files changed, 85 insertions(+), 43 deletions(-)
+ rename arch/arm/{mach-bcm2835/bcm2835.c => mach-bcm/board_bcm2835.c} (100%)
+ delete mode 100644 arch/arm/mach-bcm2835/Kconfig
+ delete mode 100644 arch/arm/mach-bcm2835/Makefile
+$ git am -3 ../patches/0001-ARM-bcm2835-merge-fix-for-movement-to-mach-bcm-direc.patch
+Applying: ARM: bcm2835: merge fix for movement to mach-bcm directory
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/arm/mach-bcm/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master dc17b6bdbc7c] Merge remote-tracking branch 'bcm2835/for-next'
+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 (df5ec17e8ab9 Merge branch 'imx/soc' into for-next)
+$ git merge imx-mxs/for-next
+Resolved 'arch/arm/mach-imx/Kconfig' using previous resolution.
+Removing arch/arm/mach-imx/pm-imx6q.c
+Removing arch/arm/mach-imx/devices/platform-mxc_pwm.c
+Auto-merging arch/arm/mach-imx/Kconfig
+CONFLICT (content): Merge conflict in arch/arm/mach-imx/Kconfig
+Auto-merging arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi
+Auto-merging arch/arm/boot/dts/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 36a9cdfe9950] Merge remote-tracking branch 'imx-mxs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/bus/imx-weim.txt |  28 +-
+ arch/arm/boot/dts/Makefile                         |   1 -
+ arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts   |  16 +-
+ ...d-s-som.dts => imx27-phytec-phycard-s-som.dtsi} |  49 +-
+ arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts     |  81 +++
+ arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi    |  44 ++
+ arch/arm/boot/dts/imx27.dtsi                       |  56 +++
+ arch/arm/boot/dts/imx28-m28evk.dts                 |   2 +-
+ arch/arm/boot/dts/imx28-tx28.dts                   |   1 -
+ arch/arm/boot/dts/imx51-babbage.dts                |  17 +
+ arch/arm/boot/dts/imx53-m53evk.dts                 |   1 -
+ arch/arm/boot/dts/imx53-mba53.dts                  |   1 -
+ arch/arm/boot/dts/imx53-tx53.dtsi                  |   1 -
+ arch/arm/boot/dts/imx6q-phytec-pbab01.dts          |  16 +
+ arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi         |  82 +++
+ arch/arm/boot/dts/imx6q.dtsi                       |   2 +
+ arch/arm/boot/dts/imx6qdl-sabreauto.dtsi           | 132 +++++
+ arch/arm/boot/dts/imx6qdl-sabresd.dtsi             |   7 +-
+ arch/arm/boot/dts/imx6qdl-wandboard.dtsi           |   3 +
+ arch/arm/boot/dts/imx6sl-evk.dts                   | 217 ++++++++
+ arch/arm/boot/dts/vf610-twr.dts                    |  92 ++++
+ arch/arm/boot/dts/vf610.dtsi                       |  63 +++
+ arch/arm/configs/imx_v4_v5_defconfig               |   1 +
+ arch/arm/configs/imx_v6_v7_defconfig               |   7 +
+ arch/arm/mach-imx/Kconfig                          |  43 +-
+ arch/arm/mach-imx/Makefile                         |   9 +-
+ arch/arm/mach-imx/clk-imx21.c                      |   1 -
+ arch/arm/mach-imx/clk-imx25.c                      |   8 -
+ arch/arm/mach-imx/clk-imx27.c                      |   1 -
+ arch/arm/mach-imx/clk-imx51-imx53.c                |   2 -
+ arch/arm/mach-imx/clk-imx6q.c                      |   7 +-
+ arch/arm/mach-imx/clk-imx6sl.c                     | 159 +++++-
+ arch/arm/mach-imx/clk-vf610.c                      |  36 +-
+ arch/arm/mach-imx/common.h                         |  17 +-
+ arch/arm/mach-imx/cpuidle-imx6q.c                  |   4 +-
+ arch/arm/mach-imx/cpuidle-imx6sl.c                 |  57 +++
+ arch/arm/mach-imx/cpuidle.h                        |   5 +
+ arch/arm/mach-imx/devices-imx25.h                  |   4 -
+ arch/arm/mach-imx/devices-imx51.h                  |   4 -
+ arch/arm/mach-imx/devices/Kconfig                  |   3 -
+ arch/arm/mach-imx/devices/Makefile                 |   1 -
+ arch/arm/mach-imx/devices/devices-common.h         |   9 -
+ arch/arm/mach-imx/devices/platform-mxc_pwm.c       |  69 ---
+ arch/arm/mach-imx/hardware.h                       |   4 +-
+ arch/arm/mach-imx/headsmp.S                        |  40 --
+ arch/arm/mach-imx/mach-imx6q.c                     |  98 +++-
+ arch/arm/mach-imx/mach-imx6sl.c                    |   6 +-
+ arch/arm/mach-imx/pm-imx6.c                        | 552 +++++++++++++++++++++
+ arch/arm/mach-imx/pm-imx6q.c                       | 241 ---------
+ arch/arm/mach-imx/suspend-imx6.S                   | 361 ++++++++++++++
+ arch/arm/mach-imx/time.c                           |  12 +
+ drivers/bus/imx-weim.c                             |  58 +++
+ include/linux/mfd/syscon/imx6q-iomuxc-gpr.h        |  18 +
+ 53 files changed, 2254 insertions(+), 495 deletions(-)
+ rename arch/arm/boot/dts/{imx27-phytec-phycard-s-som.dts => imx27-phytec-phycard-s-som.dtsi} (81%)
+ create mode 100644 arch/arm/mach-imx/cpuidle-imx6sl.c
+ delete mode 100644 arch/arm/mach-imx/devices/platform-mxc_pwm.c
+ create mode 100644 arch/arm/mach-imx/pm-imx6.c
+ delete mode 100644 arch/arm/mach-imx/pm-imx6q.c
+ create mode 100644 arch/arm/mach-imx/suspend-imx6.S
+Merging ixp4xx/next (19f949f52599 Linux 3.8)
+$ git merge ixp4xx/next
+Already up-to-date.
+Merging keystone/next (5c0426dcd386 Merge branch 'for_3.15/dts_2' into next)
+$ git merge keystone/next
+Resolved 'arch/arm/boot/dts/keystone-clocks.dtsi' using previous resolution.
+Auto-merging arch/arm/boot/dts/keystone-clocks.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/keystone-clocks.dtsi
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e780fad77300] Merge remote-tracking branch 'keystone/next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/keystone/keystone.txt  |  10 +
+ arch/arm/boot/dts/k2e-clocks.dtsi                  |  78 ++++
+ arch/arm/boot/dts/k2e-evm.dts                      |  60 +++
+ arch/arm/boot/dts/k2e.dtsi                         |  80 ++++
+ arch/arm/boot/dts/k2hk-clocks.dtsi                 | 426 ++++++++++++++++++++
+ arch/arm/boot/dts/k2hk-evm.dts                     |  31 +-
+ arch/arm/boot/dts/k2hk.dtsi                        |  46 +++
+ arch/arm/boot/dts/k2l-clocks.dtsi                  | 267 +++++++++++++
+ arch/arm/boot/dts/k2l-evm.dts                      |  37 ++
+ arch/arm/boot/dts/k2l.dtsi                         |  55 +++
+ arch/arm/boot/dts/keystone-clocks.dtsi             | 427 +--------------------
+ arch/arm/boot/dts/keystone.dtsi                    |  89 +++--
+ arch/arm/configs/keystone_defconfig                |  13 +
+ arch/arm/mach-keystone/keystone.c                  |   3 +
+ 14 files changed, 1172 insertions(+), 450 deletions(-)
+ create mode 100644 arch/arm/boot/dts/k2e-clocks.dtsi
+ create mode 100644 arch/arm/boot/dts/k2e-evm.dts
+ create mode 100644 arch/arm/boot/dts/k2e.dtsi
+ create mode 100644 arch/arm/boot/dts/k2hk-clocks.dtsi
+ create mode 100644 arch/arm/boot/dts/k2hk.dtsi
+ create mode 100644 arch/arm/boot/dts/k2l-clocks.dtsi
+ create mode 100644 arch/arm/boot/dts/k2l-evm.dts
+ create mode 100644 arch/arm/boot/dts/k2l.dtsi
+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 (79e8e9df3918 Merge branch 'mvebu/dt' into for-next)
+$ git merge mvebu/for-next
+Resolved 'Documentation/devicetree/bindings/vendor-prefixes.txt' using previous resolution.
+Resolved 'arch/arm/boot/dts/Makefile' using previous resolution.
+Auto-merging drivers/phy/Kconfig
+Auto-merging arch/arm/mm/cache-feroceon-l2.c
+Auto-merging arch/arm/mm/Kconfig
+Auto-merging arch/arm/mach-mvebu/Kconfig
+Removing arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
+Auto-merging arch/arm/include/asm/hardware/cache-feroceon-l2.h
+Auto-merging arch/arm/boot/dts/Makefile
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging Documentation/devicetree/bindings/vendor-prefixes.txt
+CONFLICT (content): Merge conflict in Documentation/devicetree/bindings/vendor-prefixes.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 9525d9189867] Merge remote-tracking branch 'mvebu/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/armada-370-xp-mpic.txt |   8 +-
+ .../devicetree/bindings/arm/marvell,dove.txt       |  22 +
+ .../devicetree/bindings/arm/mrvl/feroceon.txt      |  16 +
+ .../devicetree/bindings/clock/mvebu-core-clock.txt |  14 +
+ .../bindings/clock/mvebu-gated-clock.txt           |  65 +-
+ .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
+ .../pinctrl/marvell,armada-370-pinctrl.txt         |   1 +
+ .../pinctrl/marvell,armada-375-pinctrl.txt         |  82 ++
+ .../pinctrl/marvell,armada-38x-pinctrl.txt         |  80 ++
+ .../bindings/pinctrl/marvell,armada-xp-pinctrl.txt |   1 +
+ .../bindings/pinctrl/marvell,dove-pinctrl.txt      |   1 +
+ .../bindings/pinctrl/marvell,kirkwood-pinctrl.txt  |   1 +
+ .../bindings/pinctrl/marvell,mvebu-pinctrl.txt     |   2 +-
+ .../devicetree/bindings/vendor-prefixes.txt        |   4 +
+ arch/arm/Kconfig                                   |   2 +-
+ arch/arm/boot/dts/Makefile                         |  33 +-
+ arch/arm/boot/dts/armada-375-db.dts                | 130 +++
+ arch/arm/boot/dts/armada-375.dtsi                  | 464 +++++++++++
+ arch/arm/boot/dts/armada-380.dtsi                  | 117 +++
+ arch/arm/boot/dts/armada-385-db.dts                | 101 +++
+ arch/arm/boot/dts/armada-385.dtsi                  | 149 ++++
+ arch/arm/boot/dts/armada-38x.dtsi                  | 351 +++++++++
+ arch/arm/boot/dts/dove.dtsi                        |  21 +-
+ arch/arm/boot/dts/kirkwood-ds109.dts               |  41 +
+ arch/arm/boot/dts/kirkwood-ds110jv10.dts           |  41 +
+ arch/arm/boot/dts/kirkwood-ds111.dts               |  44 ++
+ arch/arm/boot/dts/kirkwood-ds112.dts               |  48 ++
+ arch/arm/boot/dts/kirkwood-ds209.dts               |  44 ++
+ arch/arm/boot/dts/kirkwood-ds210.dts               |  46 ++
+ arch/arm/boot/dts/kirkwood-ds212.dts               |  47 ++
+ arch/arm/boot/dts/kirkwood-ds212j.dts              |  41 +
+ arch/arm/boot/dts/kirkwood-ds409.dts               |  48 ++
+ arch/arm/boot/dts/kirkwood-ds409slim.dts           |  40 +
+ arch/arm/boot/dts/kirkwood-ds411.dts               |  52 ++
+ arch/arm/boot/dts/kirkwood-ds411j.dts              |  48 ++
+ arch/arm/boot/dts/kirkwood-ds411slim.dts           |  48 ++
+ arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts     |  62 ++
+ arch/arm/boot/dts/kirkwood-rs212.dts               |  48 ++
+ arch/arm/boot/dts/kirkwood-rs409.dts               |  44 ++
+ arch/arm/boot/dts/kirkwood-rs411.dts               |  44 ++
+ arch/arm/boot/dts/kirkwood-synology.dtsi           | 871 +++++++++++++++++++++
+ arch/arm/boot/dts/kirkwood-t5325.dts               | 208 +++++
+ arch/arm/boot/dts/kirkwood.dtsi                    |  22 +-
+ arch/arm/configs/multi_v5_defconfig                | 194 +++++
+ arch/arm/configs/mvebu_v5_defconfig                | 181 +++++
+ .../asm/hardware}/cache-feroceon-l2.h              |   4 +-
+ arch/arm/mach-kirkwood/Kconfig                     |   7 -
+ arch/arm/mach-kirkwood/Makefile                    |   4 +-
+ arch/arm/mach-kirkwood/board-dt.c                  | 113 ++-
+ arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c     |  50 --
+ arch/arm/mach-kirkwood/common.c                    |   3 +-
+ arch/arm/mach-kirkwood/common.h                    |  13 -
+ arch/arm/mach-kirkwood/include/mach/bridge-regs.h  |   2 +
+ arch/arm/mach-kirkwood/pm.c                        |   9 +-
+ arch/arm/mach-kirkwood/pm.h                        |  26 +
+ arch/arm/mach-mv78xx0/common.c                     |   2 +-
+ arch/arm/mach-mvebu/Kconfig                        |  36 +-
+ arch/arm/mach-mvebu/Makefile                       |   2 +
+ arch/arm/mach-mvebu/board-t5325.c                  |  41 +
+ arch/arm/mach-mvebu/board.h                        |  22 +
+ arch/arm/mach-mvebu/kirkwood-pm.c                  |  76 ++
+ arch/arm/mach-mvebu/kirkwood-pm.h                  |  26 +
+ arch/arm/mach-mvebu/kirkwood.c                     | 199 +++++
+ arch/arm/mach-mvebu/kirkwood.h                     |  22 +
+ arch/arm/mach-mvebu/mvebu-soc-id.c                 |   1 +
+ arch/arm/mm/Kconfig                                |   2 +-
+ arch/arm/mm/cache-feroceon-l2.c                    |  45 +-
+ drivers/bus/mvebu-mbus.c                           |   3 +-
+ drivers/clk/mvebu/Kconfig                          |   8 +
+ drivers/clk/mvebu/Makefile                         |   2 +
+ drivers/clk/mvebu/armada-375.c                     | 184 +++++
+ drivers/clk/mvebu/armada-38x.c                     | 167 ++++
+ drivers/clk/mvebu/clk-corediv.c                    | 131 +++-
+ drivers/cpufreq/Kconfig.arm                        |   2 +-
+ drivers/cpuidle/Kconfig.arm                        |   2 +-
+ drivers/irqchip/irq-armada-370-xp.c                |  96 ++-
+ drivers/leds/Kconfig                               |   4 +-
+ drivers/phy/Kconfig                                |   2 +-
+ drivers/pinctrl/mvebu/Kconfig                      |   9 +
+ drivers/pinctrl/mvebu/Makefile                     |   2 +
+ drivers/pinctrl/mvebu/pinctrl-armada-370.c         |  20 +-
+ drivers/pinctrl/mvebu/pinctrl-armada-375.c         | 459 +++++++++++
+ drivers/pinctrl/mvebu/pinctrl-armada-38x.c         | 462 +++++++++++
+ drivers/pinctrl/mvebu/pinctrl-armada-xp.c          |  24 +-
+ drivers/pinctrl/mvebu/pinctrl-dove.c               | 403 +++++-----
+ drivers/pinctrl/mvebu/pinctrl-kirkwood.c           |  25 +-
+ drivers/pinctrl/mvebu/pinctrl-mvebu.c              | 122 +--
+ drivers/pinctrl/mvebu/pinctrl-mvebu.h              |  55 +-
+ drivers/rtc/rtc-isl12057.c                         |   5 +-
+ drivers/rtc/rtc-mv.c                               |  12 +
+ drivers/thermal/Kconfig                            |   2 +-
+ drivers/watchdog/orion_wdt.c                       |   2 +-
+ sound/soc/kirkwood/Kconfig                         |   2 +-
+ 93 files changed, 6356 insertions(+), 482 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/marvell,dove.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mrvl/feroceon.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-375-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-38x-pinctrl.txt
+ create mode 100644 arch/arm/boot/dts/armada-375-db.dts
+ create mode 100644 arch/arm/boot/dts/armada-375.dtsi
+ create mode 100644 arch/arm/boot/dts/armada-380.dtsi
+ create mode 100644 arch/arm/boot/dts/armada-385-db.dts
+ create mode 100644 arch/arm/boot/dts/armada-385.dtsi
+ create mode 100644 arch/arm/boot/dts/armada-38x.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds109.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds110jv10.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds111.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds112.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds209.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds210.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds212.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds212j.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds409.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds409slim.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds411.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds411j.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ds411slim.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rs212.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rs409.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-rs411.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-synology.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-t5325.dts
+ create mode 100644 arch/arm/configs/multi_v5_defconfig
+ create mode 100644 arch/arm/configs/mvebu_v5_defconfig
+ rename arch/arm/{plat-orion/include/plat => include/asm/hardware}/cache-feroceon-l2.h (75%)
+ delete mode 100644 arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
+ create mode 100644 arch/arm/mach-kirkwood/pm.h
+ create mode 100644 arch/arm/mach-mvebu/board-t5325.c
+ create mode 100644 arch/arm/mach-mvebu/board.h
+ create mode 100644 arch/arm/mach-mvebu/kirkwood-pm.c
+ create mode 100644 arch/arm/mach-mvebu/kirkwood-pm.h
+ create mode 100644 arch/arm/mach-mvebu/kirkwood.c
+ create mode 100644 arch/arm/mach-mvebu/kirkwood.h
+ create mode 100644 drivers/clk/mvebu/armada-375.c
+ create mode 100644 drivers/clk/mvebu/armada-38x.c
+ create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-375.c
+ create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-38x.c
+Merging renesas/next (3952e65ec9ed Merge branches 'heads/cleanup-for-v3.15', 'heads/defconfig-for-v3.15', 'heads/intc-for-v3.15', 'heads/soc-for-v3.15', 'heads/clock-for-v3.15', 'heads/boards-for-v3.15' and 'heads/dt-for-v3.15' into next)
+$ git merge renesas/next
+Removing arch/arm/mach-shmobile/board-kzm9d-reference.c
+Auto-merging arch/arm/mach-shmobile/Kconfig
+Removing arch/arm/configs/kzm9d_defconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/r7s72100-genmai-reference.dts  |  11 ++
+ arch/arm/boot/dts/r7s72100.dtsi                  |  72 ++++++++++
+ arch/arm/boot/dts/r8a7778.dtsi                   |  40 ------
+ arch/arm/boot/dts/r8a7790-lager.dts              | 149 ++++++++++++++++++-
+ arch/arm/boot/dts/r8a7790.dtsi                   |  85 +++++++----
+ arch/arm/boot/dts/r8a7791-koelsch.dts            | 173 +++++++++++++++++++++-
+ arch/arm/boot/dts/r8a7791.dtsi                   | 143 ++++++++++++++-----
+ arch/arm/configs/genmai_defconfig                |   4 +-
+ arch/arm/configs/koelsch_defconfig               |   9 ++
+ arch/arm/configs/kzm9d_defconfig                 |  91 ------------
+ arch/arm/configs/lager_defconfig                 |   4 +
+ arch/arm/configs/shmobile_defconfig              | 129 +++++++++++++++++
+ arch/arm/mach-shmobile/Kconfig                   |   9 +-
+ arch/arm/mach-shmobile/Makefile                  |   4 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c   |   2 +
+ arch/arm/mach-shmobile/board-bockw.c             |  21 ++-
+ arch/arm/mach-shmobile/board-genmai.c            |  19 ++-
+ arch/arm/mach-shmobile/board-koelsch-reference.c | 104 +++++++++++---
+ arch/arm/mach-shmobile/board-koelsch.c           | 174 ++++++++++++++++++++++-
+ arch/arm/mach-shmobile/board-kzm9d-reference.c   |  47 ------
+ arch/arm/mach-shmobile/board-lager-reference.c   | 107 +++++++++++---
+ arch/arm/mach-shmobile/board-lager.c             | 138 +++++++++++++++++-
+ arch/arm/mach-shmobile/clock-r7s72100.c          |  30 +++-
+ arch/arm/mach-shmobile/clock-r8a7778.c           |   4 +
+ arch/arm/mach-shmobile/clock-r8a7790.c           |  56 ++++++--
+ arch/arm/mach-shmobile/clock-r8a7791.c           |  63 +++++++-
+ arch/arm/mach-shmobile/include/mach/pm-rcar.h    |  15 ++
+ arch/arm/mach-shmobile/include/mach/r8a7779.h    |  13 +-
+ arch/arm/mach-shmobile/include/mach/r8a7790.h    |   1 +
+ arch/arm/mach-shmobile/pm-r8a7779.c              | 131 +----------------
+ arch/arm/mach-shmobile/pm-r8a7790.c              |  45 ++++++
+ arch/arm/mach-shmobile/pm-rcar.c                 | 141 ++++++++++++++++++
+ arch/arm/mach-shmobile/setup-rcar-gen2.c         |   2 +-
+ arch/arm/mach-shmobile/smp-r8a7779.c             |  17 +--
+ arch/arm/mach-shmobile/smp-r8a7790.c             |  17 +++
+ drivers/sh/intc/Kconfig                          |   2 +-
+ include/dt-bindings/clock/r8a7790-clock.h        |   4 +-
+ 37 files changed, 1599 insertions(+), 477 deletions(-)
+ delete mode 100644 arch/arm/configs/kzm9d_defconfig
+ create mode 100644 arch/arm/configs/shmobile_defconfig
+ delete mode 100644 arch/arm/mach-shmobile/board-kzm9d-reference.c
+ create mode 100644 arch/arm/mach-shmobile/include/mach/pm-rcar.h
+ create mode 100644 arch/arm/mach-shmobile/pm-r8a7790.c
+ create mode 100644 arch/arm/mach-shmobile/pm-rcar.c
+Merging samsung/for-next (941e7012a3b9 Merge branch 'v3.15-next/clk-s3c24xx' into for-next)
+$ git merge samsung/for-next
+Removing arch/arm/plat-samsung/include/plat/regs-serial.h
+Removing arch/arm/mach-s5pc100/include/mach/tick.h
+Removing arch/arm/mach-s3c64xx/include/mach/tick.h
+Removing arch/arm/mach-s3c24xx/include/mach/tick.h
+Auto-merging arch/arm/mach-s3c24xx/include/mach/rtc-core.h
+Removing arch/arm/mach-s3c24xx/common-s3c2443.c
+Removing arch/arm/mach-s3c24xx/clock-s3c2443.c
+Removing arch/arm/mach-s3c24xx/clock-s3c2416.c
+Removing arch/arm/mach-s3c24xx/clock-s3c2412.c
+Removing arch/arm/mach-exynos/include/mach/uncompress.h
+Auto-merging arch/arm/Kconfig.debug
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/samsung/pmu.txt        |  15 +
+ .../bindings/clock/samsung,s3c2412-clock.txt       |  50 ++
+ .../bindings/clock/samsung,s3c2443-clock.txt       |  56 ++
+ arch/arm/Kconfig.debug                             |   5 +-
+ arch/arm/boot/dts/exynos4412-odroidx.dts           |   2 +-
+ arch/arm/boot/dts/exynos4412-origen.dts            |   4 +-
+ arch/arm/boot/dts/exynos5.dtsi                     |   7 -
+ arch/arm/boot/dts/exynos5250-arndale.dts           |   5 +
+ arch/arm/boot/dts/exynos5250-smdk5250.dts          | 146 ++++
+ arch/arm/boot/dts/exynos5250-snow.dts              |   4 +
+ arch/arm/boot/dts/exynos5250.dtsi                  |  13 +-
+ arch/arm/boot/dts/exynos5420-arndale-octa.dts      | 298 ++++++++
+ arch/arm/boot/dts/exynos5420-smdk5420.dts          | 253 +++++++
+ arch/arm/boot/dts/exynos5420.dtsi                  |  70 +-
+ arch/arm/boot/dts/s3c2416-smdk2416.dts             |  13 +
+ arch/arm/boot/dts/s3c2416.dtsi                     |  42 ++
+ arch/arm/configs/exynos_defconfig                  |   2 +-
+ arch/arm/include/debug/samsung.S                   |   2 +-
+ arch/arm/mach-exynos/common.c                      |   2 +-
+ arch/arm/mach-exynos/include/mach/uncompress.h     |  48 --
+ arch/arm/mach-exynos/pm.c                          | 148 +---
+ arch/arm/mach-exynos/pm_domains.c                  |   2 -
+ arch/arm/mach-s3c24xx/Kconfig                      |  26 +-
+ arch/arm/mach-s3c24xx/Makefile                     |   7 +-
+ arch/arm/mach-s3c24xx/clock-s3c2410.c              |   3 +-
+ arch/arm/mach-s3c24xx/clock-s3c2412.c              | 761 ---------------------
+ arch/arm/mach-s3c24xx/clock-s3c2416.c              | 171 -----
+ arch/arm/mach-s3c24xx/clock-s3c2440.c              |   2 +-
+ arch/arm/mach-s3c24xx/clock-s3c2443.c              | 212 ------
+ arch/arm/mach-s3c24xx/common-s3c2443.c             | 675 ------------------
+ arch/arm/mach-s3c24xx/common.c                     |  32 +-
+ arch/arm/mach-s3c24xx/common.h                     |  10 +
+ arch/arm/mach-s3c24xx/dma-s3c2410.c                |   2 +-
+ arch/arm/mach-s3c24xx/dma-s3c2412.c                |   2 +-
+ arch/arm/mach-s3c24xx/dma-s3c2440.c                |   2 +-
+ arch/arm/mach-s3c24xx/dma-s3c2443.c                |   2 +-
+ arch/arm/mach-s3c24xx/include/mach/debug-macro.S   |   2 +-
+ .../plat => mach-s3c24xx/include/mach}/rtc-core.h  |  13 +-
+ arch/arm/mach-s3c24xx/include/mach/tick.h          |  15 -
+ arch/arm/mach-s3c24xx/mach-amlm5900.c              |   2 +-
+ arch/arm/mach-s3c24xx/mach-anubis.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-at2440evb.c             |   2 +-
+ arch/arm/mach-s3c24xx/mach-bast.c                  |   2 +-
+ arch/arm/mach-s3c24xx/mach-gta02.c                 |   2 +-
+ arch/arm/mach-s3c24xx/mach-h1940.c                 |   2 +-
+ arch/arm/mach-s3c24xx/mach-jive.c                  |  11 +-
+ arch/arm/mach-s3c24xx/mach-mini2440.c              |   2 +-
+ arch/arm/mach-s3c24xx/mach-n30.c                   |   2 +-
+ arch/arm/mach-s3c24xx/mach-nexcoder.c              |   2 +-
+ arch/arm/mach-s3c24xx/mach-osiris.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-otom.c                  |   2 +-
+ arch/arm/mach-s3c24xx/mach-qt2410.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-rx1950.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-rx3715.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-s3c2416-dt.c            |  39 +-
+ arch/arm/mach-s3c24xx/mach-smdk2410.c              |   2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2413.c              |  11 +-
+ arch/arm/mach-s3c24xx/mach-smdk2416.c              |  11 +-
+ arch/arm/mach-s3c24xx/mach-smdk2440.c              |   2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2443.c              |  11 +-
+ arch/arm/mach-s3c24xx/mach-tct_hammer.c            |   2 +-
+ arch/arm/mach-s3c24xx/mach-vr1000.c                |   2 +-
+ arch/arm/mach-s3c24xx/mach-vstms.c                 |  11 +-
+ arch/arm/mach-s3c24xx/pm.c                         |  15 +-
+ arch/arm/mach-s3c24xx/s3c2410.c                    |   2 +-
+ arch/arm/mach-s3c24xx/s3c2412.c                    |  45 +-
+ arch/arm/mach-s3c24xx/s3c2416.c                    |   2 +-
+ arch/arm/mach-s3c24xx/s3c2443.c                    |   2 +-
+ arch/arm/mach-s3c24xx/s3c244x.c                    |   2 +-
+ arch/arm/mach-s3c24xx/sleep-s3c2410.S              |   2 +-
+ arch/arm/mach-s3c24xx/sleep.S                      |   2 +-
+ arch/arm/mach-s3c64xx/common.c                     |   2 +-
+ arch/arm/mach-s3c64xx/include/mach/debug-macro.S   |   2 +-
+ arch/arm/mach-s3c64xx/include/mach/tick.h          |  31 -
+ arch/arm/mach-s3c64xx/irq-pm.c                     |   2 +-
+ arch/arm/mach-s3c64xx/mach-anw6410.c               |   2 +-
+ arch/arm/mach-s3c64xx/mach-crag6410-module.c       |   2 +-
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |   2 +-
+ arch/arm/mach-s3c64xx/mach-hmt.c                   |   2 +-
+ arch/arm/mach-s3c64xx/mach-mini6410.c              |   2 +-
+ arch/arm/mach-s3c64xx/mach-ncp.c                   |   2 +-
+ arch/arm/mach-s3c64xx/mach-real6410.c              |   2 +-
+ arch/arm/mach-s3c64xx/mach-smartq.c                |   2 +-
+ arch/arm/mach-s3c64xx/mach-smdk6400.c              |   3 +-
+ arch/arm/mach-s3c64xx/mach-smdk6410.c              |   2 +-
+ arch/arm/mach-s3c64xx/s3c6400.c                    |   2 +-
+ arch/arm/mach-s3c64xx/s3c6410.c                    |   2 +-
+ arch/arm/mach-s5p64x0/common.c                     |   2 +-
+ arch/arm/mach-s5p64x0/include/mach/debug-macro.S   |   3 +-
+ arch/arm/mach-s5p64x0/irq-pm.c                     |   2 +-
+ arch/arm/mach-s5p64x0/mach-smdk6440.c              |   2 +-
+ arch/arm/mach-s5p64x0/mach-smdk6450.c              |   2 +-
+ arch/arm/mach-s5pc100/common.c                     |   2 +-
+ arch/arm/mach-s5pc100/include/mach/debug-macro.S   |   2 +-
+ arch/arm/mach-s5pc100/include/mach/tick.h          |  31 -
+ arch/arm/mach-s5pc100/mach-smdkc100.c              |   2 +-
+ arch/arm/mach-s5pv210/common.c                     |   2 +-
+ arch/arm/mach-s5pv210/include/mach/debug-macro.S   |   2 +-
+ arch/arm/mach-s5pv210/mach-aquila.c                |   2 +-
+ arch/arm/mach-s5pv210/mach-goni.c                  |   2 +-
+ arch/arm/mach-s5pv210/mach-smdkc110.c              |   2 +-
+ arch/arm/mach-s5pv210/mach-smdkv210.c              |   2 +-
+ arch/arm/mach-s5pv210/mach-torbreck.c              |   2 +-
+ arch/arm/plat-samsung/clock.c                      |   2 +-
+ arch/arm/plat-samsung/cpu.c                        |   7 -
+ arch/arm/plat-samsung/devs.c                       |  12 +-
+ arch/arm/plat-samsung/include/plat/cpu.h           |   1 -
+ arch/arm/plat-samsung/include/plat/regs-serial.h   |   1 -
+ arch/arm/plat-samsung/include/plat/uncompress.h    |   2 +-
+ arch/arm/plat-samsung/init.c                       |   3 +-
+ arch/arm/plat-samsung/pm-gpio.c                    |   5 +-
+ arch/arm/plat-samsung/pm.c                         |   3 +-
+ arch/arm/plat-samsung/s5p-irq-pm.c                 |  13 -
+ drivers/clk/samsung/Makefile                       |   2 +
+ drivers/clk/samsung/clk-exynos4.c                  | 172 ++++-
+ drivers/clk/samsung/clk-exynos5250.c               |  49 +-
+ drivers/clk/samsung/clk-exynos5420.c               |  49 +-
+ drivers/clk/samsung/clk-exynos5440.c               |   2 +-
+ drivers/clk/samsung/clk-pll.c                      | 266 ++++++-
+ drivers/clk/samsung/clk-pll.h                      |   6 +
+ drivers/clk/samsung/clk-s3c2412.c                  | 269 ++++++++
+ drivers/clk/samsung/clk-s3c2443.c                  | 462 +++++++++++++
+ drivers/clk/samsung/clk-s3c64xx.c                  |  79 ++-
+ drivers/clk/samsung/clk.c                          |  71 +-
+ drivers/clk/samsung/clk.h                          |  14 +-
+ drivers/clocksource/exynos_mct.c                   |   2 -
+ drivers/irqchip/exynos-combiner.c                  |   3 +-
+ include/dt-bindings/clock/s3c2412.h                |  73 ++
+ include/dt-bindings/clock/s3c2443.h                |  92 +++
+ 129 files changed, 2673 insertions(+), 2437 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/samsung/pmu.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt
+ delete mode 100644 arch/arm/mach-exynos/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2412.c
+ delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2416.c
+ delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2443.c
+ delete mode 100644 arch/arm/mach-s3c24xx/common-s3c2443.c
+ rename arch/arm/{plat-samsung/include/plat => mach-s3c24xx/include/mach}/rtc-core.h (69%)
+ delete mode 100644 arch/arm/mach-s3c24xx/include/mach/tick.h
+ delete mode 100644 arch/arm/mach-s3c64xx/include/mach/tick.h
+ delete mode 100644 arch/arm/mach-s5pc100/include/mach/tick.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/regs-serial.h
+ create mode 100644 drivers/clk/samsung/clk-s3c2412.c
+ create mode 100644 drivers/clk/samsung/clk-s3c2443.c
+ create mode 100644 include/dt-bindings/clock/s3c2412.h
+ create mode 100644 include/dt-bindings/clock/s3c2443.h
+Merging tegra/for-next (19bb3595b7e2 Merge branch for-3.15/defconfig into for-next)
+$ git merge tegra/for-next
+Removing arch/arm/mach-tegra/tegra2_emc.h
+Removing arch/arm/mach-tegra/tegra2_emc.c
+Auto-merging arch/arm/boot/dts/tegra30.dtsi
+Auto-merging arch/arm/boot/dts/tegra30-cardhu.dtsi
+Auto-merging arch/arm/boot/dts/tegra114.dtsi
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/tegra114-dalmore.dts     |   5 +
+ arch/arm/boot/dts/tegra114.dtsi            |   8 +-
+ arch/arm/boot/dts/tegra124-venice2.dts     | 269 ++++++++++++++--------
+ arch/arm/boot/dts/tegra124.dtsi            | 174 ++++++++++++++-
+ arch/arm/boot/dts/tegra20-paz00.dts        |  46 +++-
+ arch/arm/boot/dts/tegra20-seaboard.dts     |  55 ++++-
+ arch/arm/boot/dts/tegra20-ventana.dts      |  39 +++-
+ arch/arm/boot/dts/tegra30-cardhu.dtsi      |   7 +
+ arch/arm/boot/dts/tegra30.dtsi             |   2 +-
+ arch/arm/configs/tegra_defconfig           |   6 +-
+ arch/arm/firmware/Kconfig                  |   3 +-
+ arch/arm/firmware/trusted_foundations.c    |  20 +-
+ arch/arm/include/asm/firmware.h            |   4 +
+ arch/arm/include/asm/trusted_foundations.h |  13 +-
+ arch/arm/mach-tegra/Makefile               |   1 -
+ arch/arm/mach-tegra/cpuidle-tegra114.c     |   7 +-
+ arch/arm/mach-tegra/platsmp.c              |   2 +-
+ arch/arm/mach-tegra/powergate.c            |   2 +
+ arch/arm/mach-tegra/tegra2_emc.c           | 347 -----------------------------
+ arch/arm/mach-tegra/tegra2_emc.h           |  24 --
+ drivers/amba/tegra-ahb.c                   |   2 -
+ 21 files changed, 548 insertions(+), 488 deletions(-)
+ delete mode 100644 arch/arm/mach-tegra/tegra2_emc.c
+ delete mode 100644 arch/arm/mach-tegra/tegra2_emc.h
+Merging arm64/for-next/core (addea9ef055b cpufreq: enable ARM drivers on arm64)
+$ git merge arm64/for-next/core
+Merge made by the 'recursive' strategy.
+ Documentation/arm64/memory.txt          |  16 +-
+ arch/arm64/Kconfig                      |  11 +-
+ arch/arm64/include/asm/cacheflush.h     |   7 +
+ arch/arm64/include/asm/debug-monitors.h |  64 ++++--
+ arch/arm64/include/asm/dma-mapping.h    |   7 +
+ arch/arm64/include/asm/io.h             |   2 +-
+ arch/arm64/include/asm/irqflags.h       |  23 +++
+ arch/arm64/include/asm/kgdb.h           |  84 ++++++++
+ arch/arm64/include/asm/psci.h           |   2 +-
+ arch/arm64/include/asm/ptrace.h         |   2 +-
+ arch/arm64/include/asm/tlb.h            | 136 ++-----------
+ arch/arm64/kernel/Makefile              |   1 +
+ arch/arm64/kernel/debug-monitors.c      |   6 +-
+ arch/arm64/kernel/head.S                |  20 +-
+ arch/arm64/kernel/kgdb.c                | 336 ++++++++++++++++++++++++++++++++
+ arch/arm64/kernel/process.c             |  11 +-
+ arch/arm64/kernel/psci.c                |  13 +-
+ arch/arm64/kernel/smp.c                 |   1 +
+ arch/arm64/kernel/vdso.c                |  42 ++--
+ arch/arm64/mm/cache.S                   |  78 ++++++++
+ arch/arm64/mm/dma-mapping.c             | 194 ++++++++++++++++--
+ arch/arm64/mm/init.c                    |  33 ++--
+ drivers/cpufreq/Kconfig                 |   2 +-
+ kernel/debug/debug_core.c               |   2 +-
+ 24 files changed, 863 insertions(+), 230 deletions(-)
+ create mode 100644 arch/arm64/include/asm/kgdb.h
+ create mode 100644 arch/arm64/kernel/kgdb.c
+Merging blackfin/for-linus (58095fdaaf1c From: Eunbong Song <eunb.song@samsung.com>)
+$ git merge blackfin/for-linus
+Already up-to-date.
+Merging c6x/for-linux-next (546153d75a48 c6x: fix build failure caused by cache.h)
+$ git merge c6x/for-linux-next
+Merge made by the 'recursive' strategy.
+ arch/c6x/include/asm/cache.h | 1 +
+ 1 file changed, 1 insertion(+)
+Merging cris/for-next (cd065a010a97 CRISv10: Readd missing header)
+$ git merge cris/for-next
+Already up-to-date.
+Merging hexagon/linux-next (44eb66c228fe Hexagon: update CR year for elf.h)
+$ git merge hexagon/linux-next
+Merge made by the 'recursive' strategy.
+ arch/hexagon/Kconfig                      |  1 +
+ arch/hexagon/include/asm/Kbuild           |  4 +-
+ arch/hexagon/include/asm/atomic.h         | 15 ++++++-
+ arch/hexagon/include/asm/delay.h          |  1 +
+ arch/hexagon/include/asm/dma-mapping.h    |  1 -
+ arch/hexagon/include/asm/elf.h            |  4 +-
+ arch/hexagon/include/asm/hexagon_vm.h     | 72 +++++++++++++++----------------
+ arch/hexagon/include/asm/io.h             |  2 +
+ arch/hexagon/include/asm/kgdb.h           |  5 ++-
+ arch/hexagon/include/asm/pgalloc.h        |  2 +-
+ arch/hexagon/include/asm/smp.h            |  1 -
+ arch/hexagon/include/uapi/asm/registers.h |  4 +-
+ arch/hexagon/include/uapi/asm/setup.h     |  5 +++
+ arch/hexagon/kernel/Makefile              |  2 +
+ arch/hexagon/kernel/hexagon_ksyms.c       | 24 +++++++++--
+ arch/hexagon/kernel/kgdb.c                |  2 +
+ arch/hexagon/kernel/ptrace.c              |  1 +
+ arch/hexagon/kernel/reset.c               |  5 +--
+ arch/hexagon/kernel/screen_info.c         |  3 ++
+ arch/hexagon/kernel/smp.c                 |  6 +--
+ arch/hexagon/kernel/time.c                | 12 ++++--
+ 21 files changed, 109 insertions(+), 63 deletions(-)
+ create mode 100644 arch/hexagon/kernel/screen_info.c
+Merging ia64/next (d21114236d0e Fix warning in make defconfig)
+$ git merge ia64/next
+Merge made by the 'recursive' strategy.
+ arch/ia64/configs/generic_defconfig | 4 ++--
+ arch/ia64/hp/common/sba_iommu.c     | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+Merging m68k/for-next (7247f55381d5 m68k: Wire up sched_setattr and sched_getattr)
+$ git merge m68k/for-next
+Already up-to-date.
+Merging m68knommu/for-next (72a8ab3cb2a5 m68knommu: fix arg types for outs* functions)
+$ git merge m68knommu/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/configs/m5208evb_defconfig | 1 -
+ arch/m68k/configs/m5249evb_defconfig | 1 -
+ arch/m68k/configs/m5272c3_defconfig  | 1 -
+ arch/m68k/configs/m5275evb_defconfig | 1 -
+ arch/m68k/configs/m5307c3_defconfig  | 1 -
+ arch/m68k/configs/m5407c3_defconfig  | 1 -
+ arch/m68k/include/asm/io_no.h        | 6 +++---
+ 7 files changed, 3 insertions(+), 9 deletions(-)
+Merging metag/for-next (e9a1d0165bbd metag/smp: Make boot_secondary() static)
+$ git merge metag/for-next
+Already up-to-date.
+Merging microblaze/next (1cbe158dec8c microblaze: Drop architecture-specific declaration of early_printk)
+$ git merge microblaze/next
+Merge made by the 'recursive' strategy.
+ arch/microblaze/include/asm/setup.h | 6 ++----
+ arch/microblaze/kernel/heartbeat.c  | 4 ++--
+ arch/microblaze/kernel/timer.c      | 4 ++--
+ 3 files changed, 6 insertions(+), 8 deletions(-)
+Merging mips/mips-for-linux-next (22fdf79f9c81 Merge branch '3.14-fixes' into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Removing arch/mips/include/asm/gcmpregs.h
+Removing arch/mips/configs/db1235_defconfig
+Removing arch/mips/configs/db1000_defconfig
+Auto-merging arch/mips/alchemy/devboards/db1xxx.c
+Merge made by the 'recursive' strategy.
+ arch/mips/Kconfig                                  |  99 +++-
+ arch/mips/Makefile                                 |   5 +
+ arch/mips/alchemy/Kconfig                          |  22 +-
+ arch/mips/alchemy/Platform                         |  16 +-
+ arch/mips/alchemy/board-gpr.c                      |   4 +-
+ arch/mips/alchemy/board-mtx1.c                     |   4 +-
+ arch/mips/alchemy/common/setup.c                   |  10 +
+ arch/mips/alchemy/devboards/Makefile               |   4 +-
+ arch/mips/alchemy/devboards/db1000.c               |  47 +-
+ arch/mips/alchemy/devboards/db1200.c               |   9 +
+ arch/mips/alchemy/devboards/db1300.c               |   6 +-
+ arch/mips/alchemy/devboards/db1550.c               |  10 +-
+ arch/mips/alchemy/devboards/{db1235.c => db1xxx.c} |  41 +-
+ arch/mips/bcm47xx/board.c                          |   1 +
+ arch/mips/bcm47xx/setup.c                          |   2 +-
+ arch/mips/configs/db1000_defconfig                 | 359 -------------
+ arch/mips/configs/db1235_defconfig                 | 434 ----------------
+ arch/mips/configs/db1xxx_defconfig                 | 248 +++++++++
+ arch/mips/configs/malta_defconfig                  |   9 +-
+ arch/mips/configs/malta_kvm_defconfig              |  10 +-
+ arch/mips/configs/malta_kvm_guest_defconfig        |   7 +-
+ arch/mips/configs/maltaaprp_defconfig              |   3 +-
+ arch/mips/configs/maltasmtc_defconfig              |   4 +-
+ arch/mips/configs/maltasmvp_defconfig              |   5 +-
+ arch/mips/configs/maltasmvp_eva_defconfig          | 200 ++++++++
+ arch/mips/configs/maltaup_defconfig                |   3 +-
+ arch/mips/include/asm/asm-eva.h                    | 135 +++++
+ arch/mips/include/asm/asm.h                        |   9 +
+ arch/mips/include/asm/asmmacro-32.h                | 128 ++---
+ arch/mips/include/asm/asmmacro.h                   | 330 +++++++++---
+ arch/mips/include/asm/bootinfo.h                   |   2 +
+ arch/mips/include/asm/checksum.h                   |  44 +-
+ arch/mips/include/asm/cpu-features.h               |  10 +-
+ arch/mips/include/asm/cpu-info.h                   |   1 +
+ arch/mips/include/asm/cpu-type.h                   |   1 +
+ arch/mips/include/asm/cpu.h                        |   5 +-
+ arch/mips/include/asm/fpu.h                        |   2 +-
+ arch/mips/include/asm/futex.h                      |   9 +-
+ arch/mips/include/asm/fw/fw.h                      |   2 +-
+ arch/mips/include/asm/gcmpregs.h                   | 125 -----
+ arch/mips/include/asm/gic.h                        |   3 +
+ arch/mips/include/asm/idle.h                       |  14 +
+ arch/mips/include/asm/io.h                         |   4 +-
+ .../include/asm/mach-malta/kernel-entry-init.h     | 115 ++++-
+ arch/mips/include/asm/mach-malta/spaces.h          |  46 ++
+ arch/mips/include/asm/mips-boards/malta.h          |   5 +
+ arch/mips/include/asm/mips-cm.h                    | 322 ++++++++++++
+ arch/mips/include/asm/mips-cpc.h                   | 150 ++++++
+ arch/mips/include/asm/mipsregs.h                   |  22 +
+ arch/mips/include/asm/msa.h                        | 199 ++++++++
+ arch/mips/include/asm/page.h                       |   2 +
+ arch/mips/include/asm/processor.h                  |  45 +-
+ arch/mips/include/asm/ptrace.h                     |   2 +-
+ arch/mips/include/asm/r4kcache.h                   | 171 ++++++-
+ arch/mips/include/asm/sigcontext.h                 |   2 +
+ arch/mips/include/asm/smp-cps.h                    |  33 ++
+ arch/mips/include/asm/smp-ops.h                    |  17 +
+ arch/mips/include/asm/switch_to.h                  |  22 +-
+ arch/mips/include/asm/syscall.h                    |  38 +-
+ arch/mips/include/asm/thread_info.h                |   7 +-
+ arch/mips/include/asm/uaccess.h                    | 559 ++++++++++++++++-----
+ arch/mips/include/asm/uasm.h                       |   7 +
+ arch/mips/include/uapi/asm/inst.h                  |  40 +-
+ arch/mips/include/uapi/asm/sigcontext.h            |   8 +
+ arch/mips/kernel/Makefile                          |   5 +
+ arch/mips/kernel/asm-offsets.c                     |  82 +++
+ arch/mips/kernel/cps-vec.S                         | 191 +++++++
+ arch/mips/kernel/cpu-probe.c                       |  48 +-
+ arch/mips/kernel/ftrace.c                          |   4 +
+ arch/mips/kernel/genex.S                           |   2 +
+ arch/mips/kernel/head.S                            |   2 +-
+ arch/mips/kernel/idle.c                            |  22 +-
+ arch/mips/kernel/irq-gic.c                         |   1 -
+ arch/mips/kernel/kgdb.c                            |  18 +-
+ arch/mips/kernel/mips-cm.c                         | 121 +++++
+ arch/mips/kernel/mips-cpc.c                        |  52 ++
+ arch/mips/kernel/mips_ksyms.c                      |  24 +-
+ arch/mips/kernel/perf_event_mipsxx.c               |   6 +
+ arch/mips/kernel/proc.c                            |   2 +
+ arch/mips/kernel/process.c                         |  23 +-
+ arch/mips/kernel/ptrace.c                          |  96 ++--
+ arch/mips/kernel/ptrace32.c                        |  25 +-
+ arch/mips/kernel/r4k_fpu.S                         | 213 ++++++++
+ arch/mips/kernel/r4k_switch.S                      |  58 ++-
+ arch/mips/kernel/scall32-o32.S                     |  24 +-
+ arch/mips/kernel/scall64-64.S                      |   5 +-
+ arch/mips/kernel/scall64-n32.S                     |   5 +-
+ arch/mips/kernel/scall64-o32.S                     |  17 +-
+ arch/mips/kernel/signal.c                          | 170 ++++++-
+ arch/mips/kernel/signal32.c                        | 137 ++++-
+ arch/mips/kernel/smp-cmp.c                         |  52 +-
+ arch/mips/kernel/smp-cps.c                         | 329 ++++++++++++
+ arch/mips/kernel/smp-gic.c                         |  53 ++
+ arch/mips/kernel/spram.c                           |   2 +
+ arch/mips/kernel/traps.c                           | 144 +++++-
+ arch/mips/kernel/unaligned.c                       | 135 ++++-
+ arch/mips/lib/csum_partial.S                       | 282 +++++++----
+ arch/mips/lib/memcpy.S                             | 416 ++++++++++-----
+ arch/mips/lib/memset.S                             | 146 ++++--
+ arch/mips/lib/strlen_user.S                        |  36 +-
+ arch/mips/lib/strncpy_user.S                       |  40 +-
+ arch/mips/lib/strnlen_user.S                       |  36 +-
+ arch/mips/math-emu/cp1emu.c                        |  58 ++-
+ arch/mips/math-emu/kernel_linkage.c                |  76 +--
+ arch/mips/mm/c-r4k.c                               |  87 +++-
+ arch/mips/mm/cache.c                               |   4 +-
+ arch/mips/mm/init.c                                |  12 +-
+ arch/mips/mm/sc-mips.c                             |   2 +
+ arch/mips/mm/tlbex.c                               |   2 +
+ arch/mips/mm/uasm-micromips.c                      |   3 +
+ arch/mips/mm/uasm-mips.c                           |   5 +
+ arch/mips/mm/uasm.c                                |  25 +-
+ arch/mips/mti-malta/malta-init.c                   |  30 +-
+ arch/mips/mti-malta/malta-int.c                    |  70 +--
+ arch/mips/mti-malta/malta-memory.c                 |  58 ++-
+ arch/mips/mti-malta/malta-setup.c                  |   8 +-
+ arch/mips/oprofile/common.c                        |   2 +
+ arch/mips/oprofile/op_model_mipsxx.c               |   5 +
+ arch/mips/pci/pci-alchemy.c                        |   5 +-
+ arch/mips/pci/pci-malta.c                          |  22 +-
+ drivers/cpuidle/Kconfig                            |   5 +
+ drivers/cpuidle/Kconfig.mips                       |  14 +
+ drivers/cpuidle/Makefile                           |   4 +
+ drivers/cpuidle/cpuidle-mips-cps.c                 | 545 ++++++++++++++++++++
+ drivers/spi/spi-au1550.c                           |   9 +
+ include/linux/cpuidle.h                            |   1 +
+ 126 files changed, 6204 insertions(+), 2070 deletions(-)
+ rename arch/mips/alchemy/devboards/{db1235.c => db1xxx.c} (65%)
+ delete mode 100644 arch/mips/configs/db1000_defconfig
+ delete mode 100644 arch/mips/configs/db1235_defconfig
+ create mode 100644 arch/mips/configs/db1xxx_defconfig
+ create mode 100644 arch/mips/configs/maltasmvp_eva_defconfig
+ create mode 100644 arch/mips/include/asm/asm-eva.h
+ delete mode 100644 arch/mips/include/asm/gcmpregs.h
+ create mode 100644 arch/mips/include/asm/mach-malta/spaces.h
+ create mode 100644 arch/mips/include/asm/mips-cm.h
+ create mode 100644 arch/mips/include/asm/mips-cpc.h
+ create mode 100644 arch/mips/include/asm/msa.h
+ create mode 100644 arch/mips/include/asm/smp-cps.h
+ create mode 100644 arch/mips/kernel/cps-vec.S
+ create mode 100644 arch/mips/kernel/mips-cm.c
+ create mode 100644 arch/mips/kernel/mips-cpc.c
+ create mode 100644 arch/mips/kernel/smp-cps.c
+ create mode 100644 arch/mips/kernel/smp-gic.c
+ create mode 100644 drivers/cpuidle/Kconfig.mips
+ create mode 100644 drivers/cpuidle/cpuidle-mips-cps.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 (38dbfb59d117 Linus 3.14-rc1)
+$ git merge parisc-hd/for-next
+Already up-to-date.
+Merging powerpc/next (66f9af83e56b powerpc/eeh: Disable EEH on reboot)
+$ 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 (d72d2bb5a6bc s390/checksum: remove memset() within csum_partial_copy_from_user())
+$ git merge s390/features
+Auto-merging kernel/sched/core.c
+Auto-merging drivers/s390/net/qeth_core_main.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                         |  27 +++++-
+ arch/s390/Kconfig                   |   4 +
+ arch/s390/include/asm/airq.h        |  14 ++-
+ arch/s390/include/asm/bitops.h      |   8 +-
+ arch/s390/include/asm/ccwdev.h      |   4 +-
+ arch/s390/include/asm/checksum.h    |  11 +--
+ arch/s390/include/asm/futex.h       |  13 ++-
+ arch/s390/include/asm/kvm_host.h    |   5 +-
+ arch/s390/include/asm/mmu_context.h |  39 ++++++--
+ arch/s390/include/asm/pgalloc.h     |  18 +++-
+ arch/s390/include/asm/pgtable.h     |  86 +++++++++++++-----
+ arch/s390/include/asm/setup.h       |   3 -
+ arch/s390/include/asm/thread_info.h |   2 +
+ arch/s390/include/asm/uaccess.h     | 171 +++++++++++++++---------------------
+ arch/s390/kernel/early.c            |   2 -
+ arch/s390/kernel/entry.S            |   9 +-
+ arch/s390/kernel/entry64.S          |   9 +-
+ arch/s390/kernel/setup.c            |  17 ----
+ arch/s390/kvm/diag.c                |   3 +
+ arch/s390/kvm/kvm-s390.c            |  25 ++++++
+ arch/s390/kvm/kvm-s390.h            |   2 +
+ arch/s390/kvm/priv.c                |  41 +++++++++
+ arch/s390/lib/Makefile              |   3 +-
+ arch/s390/lib/find.c                |   2 +-
+ arch/s390/lib/uaccess.h             |   8 +-
+ arch/s390/lib/uaccess_mvcos.c       | 116 ++++++++++++++++++------
+ arch/s390/lib/uaccess_pt.c          |  69 ++++++---------
+ arch/s390/mm/maccess.c              |  28 +-----
+ arch/s390/mm/pgtable.c              | 153 +++++++++++++++++++++++++++++++-
+ arch/s390/pci/pci_debug.c           |   2 +-
+ drivers/s390/char/con3215.c         |   8 +-
+ drivers/s390/char/con3270.c         |   6 +-
+ drivers/s390/char/raw3270.c         |  17 +++-
+ drivers/s390/char/raw3270.h         |   2 +-
+ drivers/s390/char/sclp_early.c      |   8 +-
+ drivers/s390/cio/airq.c             |  66 ++++++++------
+ drivers/s390/cio/chsc_sch.c         |   3 +-
+ drivers/s390/cio/cio.c              |   4 +-
+ drivers/s390/cio/device.c           |  52 ++++++-----
+ drivers/s390/net/qeth_core_main.c   |   4 +-
+ include/asm-generic/pgtable.h       |  13 +++
+ include/linux/mm.h                  |  10 ++-
+ kernel/sched/core.c                 |   4 +-
+ mm/mmu_context.c                    |   3 +
+ mm/rmap.c                           |  10 +++
+ 45 files changed, 754 insertions(+), 350 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 (5e01dc7b26d9 Linux 3.12)
+$ 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 99b778a9953f] 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 (b3fdfc1b4b64 Merge tag 'xtensa-for-next-20140221-1' into for_next)
+$ git merge xtensa/for_next
+Already up-to-date.
+Merging btrfs/next (cf93da7bcf45 Btrfs: fix spin_unlock in check_ref_cleanup)
+$ git merge btrfs/next
+Already up-to-date.
+Merging ceph/master (bee26897097f libceph: a per-osdc crush scratch buffer)
+$ git merge ceph/master
+Merge made by the 'recursive' strategy.
+ include/linux/ceph/osdmap.h |  3 +++
+ net/ceph/osdmap.c           | 25 ++++++++++++++++---------
+ 2 files changed, 19 insertions(+), 9 deletions(-)
+Merging cifs/for-next (dca1c8d17a2f cifs: mask off top byte in get_rfc1002_length())
+$ git merge cifs/for-next
+Merge made by the 'recursive' strategy.
+ fs/cifs/cifsglob.h  |  2 +-
+ fs/cifs/file.c      | 24 ++++++------------------
+ fs/cifs/transport.c | 29 +++++++++++++++++++++++++++++
+ 3 files changed, 36 insertions(+), 19 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 (ff57cd5863cf fsnotify: Allocate overflow events with proper type)
+$ git merge ext3/for_next
+Already up-to-date.
+Merging ext4/dev (442ed22745a0 ext4: merge uninitialized extents)
+$ git merge ext4/dev
+Merge made by the 'recursive' strategy.
+ fs/ext4/extents.c        | 29 ++++++++++++++++++++++------
+ fs/ext4/extents_status.c | 28 +++++++++++++--------------
+ fs/ext4/extents_status.h |  9 +++++++++
+ fs/ext4/inode.c          | 12 ++++++++++++
+ fs/ext4/ioctl.c          | 24 ++++++-----------------
+ fs/ext4/mballoc.c        |  7 ++++---
+ fs/ext4/mballoc.h        |  4 +---
+ fs/ext4/move_extent.c    |  3 +--
+ fs/ext4/super.c          | 50 +++++++++++++++++++++++++-----------------------
+ fs/ext4/xattr.c          |  8 ++++----
+ fs/jbd2/journal.c        |  6 +++---
+ 11 files changed, 102 insertions(+), 78 deletions(-)
+Merging f2fs/dev (9cf3c3898a27 f2fs: fix dirty page accounting when redirty)
+$ git merge f2fs/dev
+Merge made by the 'recursive' strategy.
+ Documentation/filesystems/f2fs.txt |  13 +++-
+ fs/f2fs/checkpoint.c               | 112 ++++++++++++++++++++++++++++---
+ fs/f2fs/data.c                     |  64 ++++++++----------
+ fs/f2fs/debug.c                    |   4 +-
+ fs/f2fs/dir.c                      |  69 ++++++++++---------
+ fs/f2fs/f2fs.h                     |  61 ++++++++++-------
+ fs/f2fs/file.c                     |   5 ++
+ fs/f2fs/gc.c                       |  14 ++--
+ fs/f2fs/inode.c                    |  25 ++++---
+ fs/f2fs/node.c                     | 132 ++++++++++++++++++-------------------
+ fs/f2fs/node.h                     |  10 ++-
+ fs/f2fs/recovery.c                 |  27 ++++----
+ fs/f2fs/segment.c                  |  78 +++++-----------------
+ fs/f2fs/segment.h                  |  30 ++-------
+ fs/f2fs/super.c                    |  55 +++++++++-------
+ include/linux/f2fs_fs.h            |   2 +-
+ 16 files changed, 388 insertions(+), 313 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 (b2ec2778df9d fuse: Turn writeback cache on)
+$ git merge fuse/for-next
+Auto-merging fs/fuse/file.c
+Merge made by the 'recursive' strategy.
+ fs/fuse/cuse.c            |   5 +-
+ fs/fuse/dir.c             | 119 +++++++++++++++++----
+ fs/fuse/file.c            | 257 ++++++++++++++++++++++++++++++++++++----------
+ fs/fuse/fuse_i.h          |  22 +++-
+ fs/fuse/inode.c           |  29 ++++--
+ include/uapi/linux/fuse.h |   5 +
+ 6 files changed, 355 insertions(+), 82 deletions(-)
+Merging gfs2/master (fcf10d38afd2 GFS2: replace kmalloc - __vmalloc / memset 0)
+$ git merge gfs2/master
+Auto-merging include/trace/events/writeback.h
+Auto-merging fs/posix_acl.c
+Auto-merging fs/fs-writeback.c
+Merge made by the 'recursive' strategy.
+ fs/fs-writeback.c                |   2 +
+ fs/gfs2/aops.c                   | 132 ++++++++++++++++++++++++++++-----------
+ fs/gfs2/dir.c                    |   9 +++
+ fs/gfs2/file.c                   |  13 ++--
+ fs/gfs2/glops.c                  |   2 +
+ fs/gfs2/incore.h                 |  15 ++---
+ fs/gfs2/inode.c                  |  50 ++++++++++++---
+ fs/gfs2/lock_dlm.c               |   2 +-
+ fs/gfs2/log.c                    | 101 ++++++++++++++++--------------
+ fs/gfs2/lops.c                   |  43 ++++++-------
+ fs/gfs2/lops.h                   |   5 +-
+ fs/gfs2/meta_io.c                |   9 +--
+ fs/gfs2/ops_fstype.c             |   2 -
+ fs/gfs2/quota.c                  |   7 +--
+ fs/gfs2/rgrp.c                   |   6 +-
+ fs/gfs2/trans.c                  |  11 ++--
+ fs/posix_acl.c                   |   5 +-
+ include/trace/events/writeback.h |   1 +
+ include/uapi/linux/gfs2_ondisk.h |  12 +++-
+ 19 files changed, 270 insertions(+), 157 deletions(-)
+Merging jfs/jfs-next (844fa1b5f849 jfs: set i_ctime when setting ACL)
+$ git merge jfs/jfs-next
+Already up-to-date.
+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 (755a48a7a4eb NFS: Fix a delegation callback race)
+$ git merge nfs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/nfs/delegation.c     | 11 +++++++----
+ fs/nfs/nfs4proc.c       | 10 +++++-----
+ include/linux/nfs_xdr.h |  5 +++++
+ 3 files changed, 17 insertions(+), 9 deletions(-)
+Merging nfsd/nfsd-next (1406b916f4a2 nfsd: fix lost nfserrno() call in nfsd_setattr())
+$ git merge nfsd/nfsd-next
+Merge made by the 'recursive' strategy.
+ fs/nfsd/vfs.c | 1 +
+ 1 file changed, 1 insertion(+)
+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 (38dbfb59d117 Linus 3.14-rc1)
+$ git merge v9fs/for-next
+Already up-to-date.
+Merging ubifs/linux-next (9d54c8a33eec UBI: R/O block driver on top of UBI volumes)
+$ git merge ubifs/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/mtd/ubi/Kconfig     |  15 +
+ drivers/mtd/ubi/Makefile    |   1 +
+ drivers/mtd/ubi/block.c     | 646 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/mtd/ubi/build.c     |  11 +
+ drivers/mtd/ubi/cdev.c      |  20 ++
+ drivers/mtd/ubi/ubi.h       |  14 +
+ include/uapi/mtd/ubi-user.h |  11 +
+ 7 files changed, 718 insertions(+)
+ create mode 100644 drivers/mtd/ubi/block.c
+Merging xfs/for-next (14e637ca53fa Merge branch 'xfs-verifier-cleanup' into for-next)
+$ git merge xfs/for-next
+Auto-merging include/linux/fs.h
+Auto-merging fs/xfs/xfs_file.c
+Merge made by the 'recursive' strategy.
+ fs/direct-io.c              |  18 ++-
+ fs/open.c                   |  24 +++-
+ fs/xfs/xfs_acl.c            |   2 +-
+ fs/xfs/xfs_ag.h             |   6 +
+ fs/xfs/xfs_alloc.c          |  45 +++---
+ fs/xfs/xfs_alloc_btree.c    |  16 ++-
+ fs/xfs/xfs_aops.c           |   3 +-
+ fs/xfs/xfs_attr_leaf.c      |  17 +--
+ fs/xfs/xfs_attr_remote.c    |  15 +-
+ fs/xfs/xfs_bmap.c           | 193 +++++++++++++++++++++++++
+ fs/xfs/xfs_bmap.h           |  15 ++
+ fs/xfs/xfs_bmap_btree.c     |  16 +--
+ fs/xfs/xfs_bmap_util.c      |  97 ++++++++++++-
+ fs/xfs/xfs_bmap_util.h      |   2 +
+ fs/xfs/xfs_btree.c          |  14 +-
+ fs/xfs/xfs_buf.h            |  14 ++
+ fs/xfs/xfs_buf_item.c       |  19 ---
+ fs/xfs/xfs_da_btree.c       |  17 +--
+ fs/xfs/xfs_dinode.h         |   2 +
+ fs/xfs/xfs_dir2.c           | 342 +++++++++++++++++++++++++++-----------------
+ fs/xfs/xfs_dir2_block.c     |  17 +--
+ fs/xfs/xfs_dir2_data.c      |  20 +--
+ fs/xfs/xfs_dir2_leaf.c      |  17 +--
+ fs/xfs/xfs_dir2_node.c      |  17 +--
+ fs/xfs/xfs_dquot.c          |   2 +-
+ fs/xfs/xfs_dquot_buf.c      |  11 +-
+ fs/xfs/xfs_error.c          |  27 +++-
+ fs/xfs/xfs_error.h          |   1 +
+ fs/xfs/xfs_file.c           |  19 ++-
+ fs/xfs/xfs_format.h         |   2 +
+ fs/xfs/xfs_ialloc.c         |  24 ++--
+ fs/xfs/xfs_ialloc_btree.c   |  16 ++-
+ fs/xfs/xfs_inode_buf.c      |   7 +-
+ fs/xfs/xfs_iomap.c          |  10 +-
+ fs/xfs/xfs_iops.c           |  14 ++
+ fs/xfs/xfs_linux.h          |   2 +
+ fs/xfs/xfs_log.h            |   2 +-
+ fs/xfs/xfs_log_cil.c        |  55 +++++--
+ fs/xfs/xfs_rtalloc.c        |   2 +-
+ fs/xfs/xfs_sb.c             |  17 +--
+ fs/xfs/xfs_sb.h             |   2 +
+ fs/xfs/xfs_symlink_remote.c |  16 +--
+ fs/xfs/xfs_trace.h          |   1 +
+ fs/xfs/xfs_trans.c          |  12 +-
+ fs/xfs/xfs_trans_resv.c     |   6 +-
+ fs/xfs/xfs_trans_resv.h     |   1 -
+ include/linux/fs.h          |   3 +
+ include/uapi/linux/falloc.h |  21 +++
+ 48 files changed, 863 insertions(+), 358 deletions(-)
+Merging file-private-locks/linux-next (1ed1950c412f locks: add new fcntl cmd values for handling file private locks)
+$ git merge file-private-locks/linux-next
+Auto-merging include/linux/fs.h
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                       |   2 +
+ arch/arm/kernel/sys_oabi-compat.c |   3 +
+ fs/compat.c                       |  35 +++-
+ fs/fcntl.c                        |  37 ++--
+ fs/file_table.c                   |   2 +-
+ fs/locks.c                        | 349 +++++++++++++++++++++++---------------
+ include/linux/fs.h                |  21 ++-
+ include/uapi/asm-generic/fcntl.h  |  19 ++-
+ security/selinux/hooks.c          |   3 +
+ 9 files changed, 303 insertions(+), 168 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 (2c0503f202f5 Merge branches 'pci/host-designware', 'pci/host-imx6' and 'pci/host-rcar' into next)
+$ git merge pci/next
+Resolved 'drivers/ata/ahci.c' using previous resolution.
+Auto-merging include/linux/pci.h
+Auto-merging drivers/pci/pci.c
+Auto-merging drivers/pci/hotplug/acpiphp_glue.c
+Auto-merging drivers/pci/host/pci-mvebu.c
+Auto-merging drivers/bus/mvebu-mbus.c
+Auto-merging drivers/ata/ahci.c
+CONFLICT (content): Merge conflict in drivers/ata/ahci.c
+Auto-merging arch/ia64/hp/common/sba_iommu.c
+Auto-merging arch/arm/kernel/bios32.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 392d313b658a] Merge remote-tracking branch 'pci/next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/PCI/pci-iov-howto.txt        |   4 -
+ arch/arm/kernel/bios32.c                   |   9 +-
+ arch/frv/mb93090-mb00/pci-frv.c            |   2 +-
+ arch/ia64/hp/common/sba_iommu.c            |  32 ++---
+ arch/ia64/include/asm/pci.h                |   2 +-
+ arch/ia64/kernel/acpi.c                    |  28 ++---
+ arch/ia64/pci/fixup.c                      |  25 ++--
+ arch/ia64/pci/pci.c                        |  10 +-
+ arch/powerpc/kernel/pci_64.c               |   4 +-
+ arch/powerpc/platforms/pseries/pci_dlpar.c |   6 +-
+ arch/x86/include/asm/pci.h                 |   7 +-
+ arch/x86/include/asm/topology.h            |  14 +--
+ arch/x86/pci/acpi.c                        |  59 +++------
+ arch/x86/pci/amd_bus.c                     |  10 --
+ arch/x86/pci/bus_numa.c                    |  13 +-
+ arch/x86/pci/common.c                      | 128 +++-----------------
+ arch/x86/pci/fixup.c                       |  24 ++--
+ arch/x86/pci/irq.c                         |   6 +-
+ arch/x86/pci/legacy.c                      |   4 +-
+ arch/x86/pci/numaq_32.c                    |   6 +-
+ arch/x86/pci/visws.c                       |   4 +-
+ drivers/acpi/numa.c                        |  16 +--
+ drivers/ata/ahci.c                         |  20 ++--
+ drivers/bus/mvebu-mbus.c                   |   4 +-
+ drivers/gpu/drm/drm_fops.c                 |   3 +-
+ drivers/iommu/amd_iommu_types.h            |   1 +
+ drivers/misc/mei/hw-me.h                   |   1 +
+ drivers/misc/mic/card/mic_device.h         |   1 +
+ drivers/misc/mic/host/mic_device.h         |   1 +
+ drivers/pci/Makefile                       |  22 ++--
+ drivers/pci/host/Kconfig                   |   2 +-
+ drivers/pci/host/pci-imx6.c                |  47 ++++++--
+ drivers/pci/host/pci-mvebu.c               |  26 +++-
+ drivers/pci/host/pci-rcar-gen2.c           | 180 ++++++++++++++++++----------
+ drivers/pci/host/pcie-designware.c         |   2 +-
+ drivers/pci/hotplug/acpiphp_glue.c         |   6 +-
+ drivers/pci/hotplug/cpqphp_core.c          |   4 +-
+ drivers/pci/hotplug/pciehp.h               |   5 +
+ drivers/pci/hotplug/pciehp_acpi.c          |   1 +
+ drivers/pci/hotplug/pciehp_core.c          |   8 +-
+ drivers/pci/hotplug/pciehp_ctrl.c          | 173 +++++++++++++++++++++------
+ drivers/pci/hotplug/pciehp_hpc.c           |  75 ++++++------
+ drivers/pci/hotplug/pciehp_pci.c           |   2 +-
+ drivers/pci/iov.c                          | 119 -------------------
+ drivers/pci/pci.c                          |  72 ++++++-----
+ drivers/pci/pci.h                          |   4 -
+ drivers/pci/probe.c                        |  76 +++++-------
+ drivers/pci/quirks.c                       | 185 +++++++++++++++++++++++++++++
+ drivers/pci/search.c                       |  10 +-
+ drivers/pcmcia/yenta_socket.c              |  18 +--
+ drivers/vfio/pci/vfio_pci_intrs.c          |  12 +-
+ include/acpi/acpi_numa.h                   |   1 -
+ include/linux/acpi.h                       |   9 +-
+ include/linux/pci.h                        |   9 +-
+ 54 files changed, 797 insertions(+), 715 deletions(-)
+Merging hid/for-next (afbe1c7e1a53 Merge branch 'for-3.15/sony' into for-next)
+$ git merge hid/for-next
+Resolved 'drivers/hid/hid-core.c' using previous resolution.
+Resolved 'drivers/hid/hid-ids.h' using previous resolution.
+Resolved 'drivers/hid/i2c-hid/i2c-hid.c' using previous resolution.
+Auto-merging net/bluetooth/hidp/core.c
+Auto-merging drivers/hid/i2c-hid/i2c-hid.c
+CONFLICT (content): Merge conflict in drivers/hid/i2c-hid/i2c-hid.c
+Auto-merging drivers/hid/hid-sensor-hub.c
+Auto-merging drivers/hid/hid-microsoft.c
+Auto-merging drivers/hid/hid-input.c
+Auto-merging drivers/hid/hid-ids.h
+CONFLICT (content): Merge conflict in drivers/hid/hid-ids.h
+Auto-merging drivers/hid/hid-core.c
+CONFLICT (content): Merge conflict in drivers/hid/hid-core.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 6a0bb60e5b3b] Merge remote-tracking branch 'hid/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/hid/hid-transport.txt                |  317 ++++++
+ drivers/hid/Kconfig                                |   19 +-
+ drivers/hid/Makefile                               |    1 +
+ drivers/hid/hid-core.c                             |   52 +-
+ drivers/hid/hid-cp2112.c                           | 1068 ++++++++++++++++++++
+ drivers/hid/hid-ids.h                              |    2 +
+ drivers/hid/hid-input.c                            |   21 +-
+ drivers/hid/hid-lg.c                               |    6 +-
+ drivers/hid/hid-logitech-dj.c                      |  111 +-
+ drivers/hid/hid-magicmouse.c                       |    4 +-
+ drivers/hid/hid-microsoft.c                        |   74 +-
+ drivers/hid/hid-sensor-hub.c                       |  210 ++--
+ drivers/hid/hid-sony.c                             |  761 ++++++++++++--
+ drivers/hid/hid-thingm.c                           |    4 +-
+ drivers/hid/hid-wacom.c                            |   28 +-
+ drivers/hid/hid-wiimote-core.c                     |    4 +-
+ drivers/hid/hidraw.c                               |   26 +-
+ drivers/hid/i2c-hid/i2c-hid.c                      |  149 ++-
+ drivers/hid/uhid.c                                 |   24 +-
+ drivers/hid/usbhid/hid-core.c                      |  107 +-
+ .../iio/common/hid-sensors/hid-sensor-trigger.c    |   39 +-
+ include/linux/hid-sensor-hub.h                     |    9 +-
+ include/linux/hid-sensor-ids.h                     |   16 +-
+ include/linux/hid.h                                |   84 +-
+ net/bluetooth/hidp/core.c                          |  110 +-
+ 25 files changed, 2810 insertions(+), 436 deletions(-)
+ create mode 100644 Documentation/hid/hid-transport.txt
+ create mode 100644 drivers/hid/hid-cp2112.c
+Merging i2c/i2c/for-next (e89364556824 i2c: rcar: add compatible entry for r8a7791)
+$ git merge i2c/i2c/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/i2c/i2c-rcar.txt | 14 ++++++++++----
+ drivers/i2c/busses/i2c-rcar.c                      |  1 +
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+Merging jdelvare-hwmon/master (c1d70b646dae hwmon: (lm90) Convert to use hwmon_device_register_with_groups)
+$ git merge jdelvare-hwmon/master
+Merge made by the 'recursive' strategy.
+ drivers/hwmon/adm1021.c   |  70 +++++++--------------
+ drivers/hwmon/asc7621.c   |   1 -
+ drivers/hwmon/atxp1.c     |   2 -
+ drivers/hwmon/f71805f.c   |   2 +-
+ drivers/hwmon/lm63.c      | 157 +++++++++++++++++++---------------------------
+ drivers/hwmon/lm77.c      |   1 -
+ drivers/hwmon/lm80.c      |  70 +++++++--------------
+ drivers/hwmon/lm83.c      |   1 -
+ drivers/hwmon/lm87.c      |   1 -
+ drivers/hwmon/lm90.c      | 111 ++++++++++++++------------------
+ drivers/hwmon/lm92.c      |   1 -
+ drivers/hwmon/lm93.c      |   1 -
+ drivers/hwmon/max1619.c   |   1 -
+ drivers/hwmon/pc87360.c   |  12 ++--
+ drivers/hwmon/w83792d.c   |   1 -
+ drivers/hwmon/w83l785ts.c |   4 --
+ 16 files changed, 162 insertions(+), 274 deletions(-)
+Merging hwmon-staging/hwmon-next (d44cdded6ab3 hwmon: (max6639) Use SIMPLE_DEV_PM_OPS macro)
+$ git merge hwmon-staging/hwmon-next
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/adc128d818 |  47 +++
+ Documentation/hwmon/lm95245    |   8 +-
+ Documentation/hwmon/ltc2945    |  84 +++++
+ Documentation/hwmon/ltc4260    |  56 ++++
+ drivers/hwmon/Kconfig          | 698 ++++++++++++++++++++++-------------------
+ drivers/hwmon/Makefile         |   4 +
+ drivers/hwmon/adc128d818.c     | 491 +++++++++++++++++++++++++++++
+ drivers/hwmon/coretemp.c       |  71 +----
+ drivers/hwmon/emc2103.c        |   2 +-
+ drivers/hwmon/iio_hwmon.c      |  37 +--
+ drivers/hwmon/jz4740-hwmon.c   |  25 +-
+ drivers/hwmon/lm95241.c        |  93 ++----
+ drivers/hwmon/lm95245.c        | 112 +++----
+ drivers/hwmon/ltc2945.c        | 519 ++++++++++++++++++++++++++++++
+ drivers/hwmon/ltc4215.c        |  51 +--
+ drivers/hwmon/ltc4222.c        | 237 ++++++++++++++
+ drivers/hwmon/ltc4245.c        |  30 +-
+ drivers/hwmon/ltc4260.c        | 200 ++++++++++++
+ drivers/hwmon/max1668.c        |  81 ++---
+ drivers/hwmon/max6639.c        |  91 ++----
+ drivers/hwmon/max6650.c        | 257 +++++++--------
+ drivers/hwmon/smm665.c         |   2 +-
+ 22 files changed, 2311 insertions(+), 885 deletions(-)
+ create mode 100644 Documentation/hwmon/adc128d818
+ create mode 100644 Documentation/hwmon/ltc2945
+ create mode 100644 Documentation/hwmon/ltc4260
+ create mode 100644 drivers/hwmon/adc128d818.c
+ create mode 100644 drivers/hwmon/ltc2945.c
+ create mode 100644 drivers/hwmon/ltc4222.c
+ create mode 100644 drivers/hwmon/ltc4260.c
+Merging v4l-dvb/master (b215621049bd Merge branch 'v4l_for_linus' into to_next)
+$ git merge v4l-dvb/master
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging kbuild/for-next (ff6b9bdb6263 Merge branch 'kbuild/misc' into kbuild/for-next)
+$ git merge kbuild/for-next
+Auto-merging Makefile
+Merge made by the 'recursive' strategy.
+ Makefile        | 5 +++--
+ scripts/tags.sh | 9 ++++-----
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+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 (70320a1803e5 Merge branch 'for-3.14-fixes' into for-next)
+$ git merge libata/for-next
+Auto-merging drivers/ata/ahci.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/ata/ahci-platform.txt      |  22 +-
+ drivers/ata/Kconfig                                |  13 +-
+ drivers/ata/Makefile                               |   1 +
+ drivers/ata/acard-ahci.c                           |   1 -
+ drivers/ata/ahci.c                                 |   7 +-
+ drivers/ata/ahci.h                                 |  14 +-
+ drivers/ata/ahci_imx.c                             | 331 +++++--------
+ drivers/ata/ahci_platform.c                        | 545 +++++++++++++++------
+ drivers/ata/ahci_sunxi.c                           | 249 ++++++++++
+ drivers/ata/ata_generic.c                          |   1 -
+ drivers/ata/libahci.c                              |  36 +-
+ drivers/ata/libata-core.c                          |   1 +
+ drivers/ata/pata_acpi.c                            |   1 -
+ drivers/ata/pata_amd.c                             |   1 -
+ drivers/ata/pata_artop.c                           |   1 -
+ drivers/ata/pata_at91.c                            |   1 -
+ drivers/ata/pata_atiixp.c                          |   1 -
+ drivers/ata/pata_atp867x.c                         |   1 -
+ drivers/ata/pata_cmd640.c                          |   1 -
+ drivers/ata/pata_cmd64x.c                          |   1 -
+ drivers/ata/pata_cs5520.c                          |   1 -
+ drivers/ata/pata_cs5530.c                          |   1 -
+ drivers/ata/pata_cs5535.c                          |   1 -
+ drivers/ata/pata_cs5536.c                          |   1 -
+ drivers/ata/pata_cypress.c                         |   1 -
+ drivers/ata/pata_efar.c                            |   1 -
+ drivers/ata/pata_ep93xx.c                          |   1 -
+ drivers/ata/pata_hpt366.c                          |   1 -
+ drivers/ata/pata_hpt37x.c                          |   1 -
+ drivers/ata/pata_hpt3x2n.c                         |   1 -
+ drivers/ata/pata_hpt3x3.c                          |   1 -
+ drivers/ata/pata_imx.c                             |  14 +-
+ drivers/ata/pata_it8213.c                          |   1 -
+ drivers/ata/pata_it821x.c                          |   1 -
+ drivers/ata/pata_jmicron.c                         |   1 -
+ drivers/ata/pata_marvell.c                         |   1 -
+ drivers/ata/pata_mpiix.c                           |   1 -
+ drivers/ata/pata_netcell.c                         |   1 -
+ drivers/ata/pata_ninja32.c                         |   1 -
+ drivers/ata/pata_ns87410.c                         |   1 -
+ drivers/ata/pata_ns87415.c                         |   1 -
+ drivers/ata/pata_oldpiix.c                         |   1 -
+ drivers/ata/pata_opti.c                            |   1 -
+ drivers/ata/pata_optidma.c                         |   1 -
+ drivers/ata/pata_pcmcia.c                          |   1 -
+ drivers/ata/pata_pdc2027x.c                        |   1 -
+ drivers/ata/pata_pdc202xx_old.c                    |   1 -
+ drivers/ata/pata_piccolo.c                         |   1 -
+ drivers/ata/pata_platform.c                        |   1 -
+ drivers/ata/pata_pxa.c                             |   1 -
+ drivers/ata/pata_radisys.c                         |   1 -
+ drivers/ata/pata_rdc.c                             |   1 -
+ drivers/ata/pata_rz1000.c                          |   1 -
+ drivers/ata/pata_sc1200.c                          |   1 -
+ drivers/ata/pata_scc.c                             |   1 -
+ drivers/ata/pata_sch.c                             |   1 -
+ drivers/ata/pata_serverworks.c                     |   1 -
+ drivers/ata/pata_sil680.c                          |   1 -
+ drivers/ata/pata_sis.c                             |   1 -
+ drivers/ata/pata_sl82c105.c                        |   1 -
+ drivers/ata/pata_triflex.c                         |   1 -
+ drivers/ata/pata_via.c                             |   1 -
+ drivers/ata/pdc_adma.c                             |   1 -
+ drivers/ata/sata_dwc_460ex.c                       |   1 -
+ drivers/ata/sata_highbank.c                        |   4 +-
+ drivers/ata/sata_nv.c                              |   1 -
+ drivers/ata/sata_promise.c                         |   1 -
+ drivers/ata/sata_qstor.c                           |   1 -
+ drivers/ata/sata_sil.c                             |   1 -
+ drivers/ata/sata_sis.c                             |   1 -
+ drivers/ata/sata_svw.c                             |   1 -
+ drivers/ata/sata_sx4.c                             |   1 -
+ drivers/ata/sata_uli.c                             |   1 -
+ drivers/ata/sata_via.c                             |   1 -
+ drivers/ata/sata_vsc.c                             |   1 -
+ include/linux/ahci_platform.h                      |  28 +-
+ 76 files changed, 879 insertions(+), 449 deletions(-)
+ create mode 100644 drivers/ata/ahci_sunxi.c
+Merging pm/linux-next (c208b7bbf7df Merge branch 'acpi-processor' into linux-next)
+$ git merge pm/linux-next
+Auto-merging include/linux/acpi.h
+Auto-merging drivers/pci/hotplug/acpiphp_glue.c
+Auto-merging arch/ia64/kernel/acpi.c
+Auto-merging arch/ia64/configs/generic_defconfig
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-devices-power |  27 +-
+ Documentation/kernel-parameters.txt           |   8 +
+ Documentation/power/pm_qos_interface.txt      |  82 ++--
+ Documentation/trace/events-power.txt          |   2 +-
+ arch/ia64/configs/generic_defconfig           |   1 -
+ arch/ia64/configs/tiger_defconfig             |   1 -
+ arch/ia64/configs/zx1_defconfig               |   1 -
+ arch/ia64/kernel/acpi.c                       |   4 -
+ arch/x86/configs/i386_defconfig               |   1 -
+ arch/x86/configs/x86_64_defconfig             |   1 -
+ arch/x86/kernel/acpi/boot.c                   |   4 -
+ drivers/acpi/Kconfig                          |  26 +-
+ drivers/acpi/acpi_lpss.c                      |  82 +++-
+ drivers/acpi/acpi_pad.c                       |  24 +-
+ drivers/acpi/acpica/Makefile                  |   4 +-
+ drivers/acpi/acpica/accommon.h                |   2 +-
+ drivers/acpi/acpica/acdebug.h                 |   4 +-
+ drivers/acpi/acpica/acdispat.h                |   2 +-
+ drivers/acpi/acpica/acevents.h                |   2 +-
+ drivers/acpi/acpica/acglobal.h                |   2 +-
+ drivers/acpi/acpica/achware.h                 |   2 +-
+ drivers/acpi/acpica/acinterp.h                |   2 +-
+ drivers/acpi/acpica/aclocal.h                 |   2 +-
+ drivers/acpi/acpica/acmacros.h                |  16 +-
+ drivers/acpi/acpica/acnamesp.h                |   2 +-
+ drivers/acpi/acpica/acobject.h                |   2 +-
+ drivers/acpi/acpica/acopcode.h                |   2 +-
+ drivers/acpi/acpica/acparser.h                |   2 +-
+ drivers/acpi/acpica/acpredef.h                |   2 +-
+ drivers/acpi/acpica/acresrc.h                 |   2 +-
+ drivers/acpi/acpica/acstruct.h                |   2 +-
+ drivers/acpi/acpica/actables.h                |   2 +-
+ drivers/acpi/acpica/acutils.h                 |   4 +-
+ drivers/acpi/acpica/amlcode.h                 |   2 +-
+ drivers/acpi/acpica/amlresrc.h                |   2 +-
+ drivers/acpi/acpica/dsargs.c                  |   2 +-
+ drivers/acpi/acpica/dscontrol.c               |   2 +-
+ drivers/acpi/acpica/dsfield.c                 |   2 +-
+ drivers/acpi/acpica/dsinit.c                  |   2 +-
+ drivers/acpi/acpica/dsmethod.c                |   2 +-
+ drivers/acpi/acpica/dsmthdat.c                |   2 +-
+ drivers/acpi/acpica/dsobject.c                |   2 +-
+ drivers/acpi/acpica/dsopcode.c                |   2 +-
+ drivers/acpi/acpica/dsutils.c                 |   2 +-
+ drivers/acpi/acpica/dswexec.c                 |   2 +-
+ drivers/acpi/acpica/dswload.c                 |   2 +-
+ drivers/acpi/acpica/dswload2.c                |   2 +-
+ drivers/acpi/acpica/dswscope.c                |   2 +-
+ drivers/acpi/acpica/dswstate.c                |   2 +-
+ drivers/acpi/acpica/evevent.c                 |   2 +-
+ drivers/acpi/acpica/evglock.c                 |   2 +-
+ drivers/acpi/acpica/evgpe.c                   |   2 +-
+ drivers/acpi/acpica/evgpeblk.c                |   2 +-
+ drivers/acpi/acpica/evgpeinit.c               |   2 +-
+ drivers/acpi/acpica/evgpeutil.c               |   2 +-
+ drivers/acpi/acpica/evhandler.c               |   2 +-
+ drivers/acpi/acpica/evmisc.c                  |   2 +-
+ drivers/acpi/acpica/evregion.c                |   2 +-
+ drivers/acpi/acpica/evrgnini.c                |   2 +-
+ drivers/acpi/acpica/evsci.c                   |   2 +-
+ drivers/acpi/acpica/evxface.c                 |   2 +-
+ drivers/acpi/acpica/evxfevnt.c                |   2 +-
+ drivers/acpi/acpica/evxfgpe.c                 |  21 +-
+ drivers/acpi/acpica/evxfregn.c                |   2 +-
+ drivers/acpi/acpica/exconfig.c                |   2 +-
+ drivers/acpi/acpica/exconvrt.c                |   2 +-
+ drivers/acpi/acpica/excreate.c                |   2 +-
+ drivers/acpi/acpica/exdebug.c                 |   2 +-
+ drivers/acpi/acpica/exdump.c                  |   2 +-
+ drivers/acpi/acpica/exfield.c                 |   2 +-
+ drivers/acpi/acpica/exfldio.c                 |   2 +-
+ drivers/acpi/acpica/exmisc.c                  |   2 +-
+ drivers/acpi/acpica/exmutex.c                 |   2 +-
+ drivers/acpi/acpica/exnames.c                 |   2 +-
+ drivers/acpi/acpica/exoparg1.c                |   2 +-
+ drivers/acpi/acpica/exoparg2.c                |   2 +-
+ drivers/acpi/acpica/exoparg3.c                |   2 +-
+ drivers/acpi/acpica/exoparg6.c                |   2 +-
+ drivers/acpi/acpica/exprep.c                  |   2 +-
+ drivers/acpi/acpica/exregion.c                |   2 +-
+ drivers/acpi/acpica/exresnte.c                |   2 +-
+ drivers/acpi/acpica/exresolv.c                |   2 +-
+ drivers/acpi/acpica/exresop.c                 |   2 +-
+ drivers/acpi/acpica/exstore.c                 |   2 +-
+ drivers/acpi/acpica/exstoren.c                |   2 +-
+ drivers/acpi/acpica/exstorob.c                |   2 +-
+ drivers/acpi/acpica/exsystem.c                |   2 +-
+ drivers/acpi/acpica/exutils.c                 |   2 +-
+ drivers/acpi/acpica/hwacpi.c                  |   2 +-
+ drivers/acpi/acpica/hwesleep.c                |   2 +-
+ drivers/acpi/acpica/hwgpe.c                   |   2 +-
+ drivers/acpi/acpica/hwpci.c                   |   2 +-
+ drivers/acpi/acpica/hwregs.c                  |   2 +-
+ drivers/acpi/acpica/hwsleep.c                 |   2 +-
+ drivers/acpi/acpica/hwtimer.c                 |   2 +-
+ drivers/acpi/acpica/hwvalid.c                 |   2 +-
+ drivers/acpi/acpica/hwxface.c                 |   2 +-
+ drivers/acpi/acpica/hwxfsleep.c               |   2 +-
+ drivers/acpi/acpica/nsaccess.c                |   2 +-
+ drivers/acpi/acpica/nsalloc.c                 |   2 +-
+ drivers/acpi/acpica/nsarguments.c             |   2 +-
+ drivers/acpi/acpica/nsconvert.c               |   2 +-
+ drivers/acpi/acpica/nsdump.c                  |   2 +-
+ drivers/acpi/acpica/nsdumpdv.c                |   2 +-
+ drivers/acpi/acpica/nseval.c                  |   2 +-
+ drivers/acpi/acpica/nsinit.c                  |   2 +-
+ drivers/acpi/acpica/nsload.c                  |   2 +-
+ drivers/acpi/acpica/nsnames.c                 |   2 +-
+ drivers/acpi/acpica/nsobject.c                |   2 +-
+ drivers/acpi/acpica/nsparse.c                 |   2 +-
+ drivers/acpi/acpica/nspredef.c                |   2 +-
+ drivers/acpi/acpica/nsprepkg.c                |   2 +-
+ drivers/acpi/acpica/nsrepair.c                |   2 +-
+ drivers/acpi/acpica/nsrepair2.c               |   2 +-
+ drivers/acpi/acpica/nssearch.c                |   2 +-
+ drivers/acpi/acpica/nsutils.c                 |   2 +-
+ drivers/acpi/acpica/nswalk.c                  |   2 +-
+ drivers/acpi/acpica/nsxfeval.c                |  35 +-
+ drivers/acpi/acpica/nsxfname.c                |   2 +-
+ drivers/acpi/acpica/nsxfobj.c                 |   2 +-
+ drivers/acpi/acpica/psargs.c                  |   2 +-
+ drivers/acpi/acpica/psloop.c                  |   2 +-
+ drivers/acpi/acpica/psobject.c                |   2 +-
+ drivers/acpi/acpica/psopcode.c                |   2 +-
+ drivers/acpi/acpica/psopinfo.c                |   2 +-
+ drivers/acpi/acpica/psparse.c                 |   2 +-
+ drivers/acpi/acpica/psscope.c                 |   2 +-
+ drivers/acpi/acpica/pstree.c                  |   2 +-
+ drivers/acpi/acpica/psutils.c                 |   2 +-
+ drivers/acpi/acpica/pswalk.c                  |   2 +-
+ drivers/acpi/acpica/psxface.c                 |   2 +-
+ drivers/acpi/acpica/rsaddr.c                  |   2 +-
+ drivers/acpi/acpica/rscalc.c                  |   2 +-
+ drivers/acpi/acpica/rscreate.c                |   2 +-
+ drivers/acpi/acpica/rsdump.c                  |   5 +-
+ drivers/acpi/acpica/rsdumpinfo.c              |   4 +-
+ drivers/acpi/acpica/rsinfo.c                  |   6 +-
+ drivers/acpi/acpica/rsio.c                    |   2 +-
+ drivers/acpi/acpica/rsirq.c                   |   2 +-
+ drivers/acpi/acpica/rslist.c                  |   2 +-
+ drivers/acpi/acpica/rsmemory.c                |   2 +-
+ drivers/acpi/acpica/rsmisc.c                  |   2 +-
+ drivers/acpi/acpica/rsserial.c                |   2 +-
+ drivers/acpi/acpica/rsutils.c                 |   2 +-
+ drivers/acpi/acpica/rsxface.c                 |   2 +-
+ drivers/acpi/acpica/tbfadt.c                  |   2 +-
+ drivers/acpi/acpica/tbfind.c                  |   2 +-
+ drivers/acpi/acpica/tbinstal.c                |  17 +-
+ drivers/acpi/acpica/tbprint.c                 |  22 +-
+ drivers/acpi/acpica/tbutils.c                 |   2 +-
+ drivers/acpi/acpica/tbxface.c                 |   2 +-
+ drivers/acpi/acpica/tbxfload.c                |   2 +-
+ drivers/acpi/acpica/tbxfroot.c                |   2 +-
+ drivers/acpi/acpica/utaddress.c               |   2 +-
+ drivers/acpi/acpica/utalloc.c                 |   2 +-
+ drivers/acpi/acpica/utbuffer.c                |   2 +-
+ drivers/acpi/acpica/utcache.c                 |   2 +-
+ drivers/acpi/acpica/utcopy.c                  |   8 +-
+ drivers/acpi/acpica/utdebug.c                 |   2 +-
+ drivers/acpi/acpica/utdecode.c                |   2 +-
+ drivers/acpi/acpica/utdelete.c                |   2 +-
+ drivers/acpi/acpica/uterror.c                 |   2 +-
+ drivers/acpi/acpica/uteval.c                  |   2 +-
+ drivers/acpi/acpica/utexcep.c                 |   2 +-
+ drivers/acpi/acpica/utglobal.c                |   2 +-
+ drivers/acpi/acpica/utids.c                   |   2 +-
+ drivers/acpi/acpica/utinit.c                  |   2 +-
+ drivers/acpi/acpica/utlock.c                  |   2 +-
+ drivers/acpi/acpica/utmath.c                  |   2 +-
+ drivers/acpi/acpica/utmisc.c                  |   2 +-
+ drivers/acpi/acpica/utmutex.c                 |   2 +-
+ drivers/acpi/acpica/utobject.c                |   2 +-
+ drivers/acpi/acpica/utosi.c                   |   3 +-
+ drivers/acpi/acpica/utownerid.c               |   2 +-
+ drivers/acpi/acpica/utpredef.c                |   2 +-
+ drivers/acpi/acpica/utresrc.c                 |   5 +-
+ drivers/acpi/acpica/utstate.c                 |   2 +-
+ drivers/acpi/acpica/utstring.c                |   2 +-
+ drivers/acpi/acpica/uttrack.c                 |   5 +-
+ drivers/acpi/acpica/utxface.c                 |   2 +-
+ drivers/acpi/acpica/utxferror.c               |   2 +-
+ drivers/acpi/acpica/utxfinit.c                |   2 +-
+ drivers/acpi/acpica/utxfmutex.c               |   2 +-
+ drivers/acpi/apei/Kconfig                     |   2 +-
+ drivers/acpi/bus.c                            |  63 ++--
+ drivers/acpi/container.c                      |   3 +
+ drivers/acpi/dock.c                           | 452 ++++++----------------
+ drivers/acpi/fan.c                            |  13 +-
+ drivers/acpi/glue.c                           |  12 +
+ drivers/acpi/internal.h                       |  12 +-
+ drivers/acpi/osl.c                            |  11 +
+ drivers/acpi/pci_irq.c                        |  36 +-
+ drivers/acpi/pci_root.c                       |   2 +-
+ drivers/acpi/processor_core.c                 |  78 ++--
+ drivers/acpi/processor_perflib.c              |  14 +-
+ drivers/acpi/scan.c                           | 257 ++++++++-----
+ drivers/acpi/utils.c                          |  16 +-
+ drivers/ata/libata-acpi.c                     |  72 ++--
+ drivers/base/power/main.c                     | 275 +++++++++++---
+ drivers/base/power/power.h                    |   4 +-
+ drivers/base/power/qos.c                      | 220 ++++++++---
+ drivers/base/power/sysfs.c                    |  97 +++--
+ drivers/cpufreq/cpufreq.c                     | 100 +++--
+ drivers/input/touchscreen/st1232.c            |   3 +-
+ drivers/mtd/nand/sh_flctl.c                   |   2 +-
+ drivers/pci/hotplug/acpiphp.h                 |  16 +-
+ drivers/pci/hotplug/acpiphp_glue.c            | 516 +++++++++-----------------
+ drivers/powercap/intel_rapl.c                 |  17 +-
+ drivers/xen/xen-acpi-cpuhotplug.c             |   2 +-
+ drivers/xen/xen-acpi-memhotplug.c             |   2 +-
+ drivers/xen/xen-acpi-pad.c                    |  26 +-
+ include/acpi/acbuffer.h                       |   2 +-
+ include/acpi/acconfig.h                       |   2 +-
+ include/acpi/acexcep.h                        |   2 +-
+ include/acpi/acnames.h                        |   2 +-
+ include/acpi/acoutput.h                       |   2 +-
+ include/acpi/acpi.h                           |   5 +-
+ include/acpi/acpi_bus.h                       |  45 ++-
+ include/acpi/acpi_drivers.h                   |  26 +-
+ include/acpi/acpiosxf.h                       |   2 +-
+ include/acpi/acpixf.h                         |   8 +-
+ include/acpi/acrestyp.h                       |   2 +-
+ include/acpi/actbl.h                          |   2 +-
+ include/acpi/actbl1.h                         |   2 +-
+ include/acpi/actbl2.h                         |   2 +-
+ include/acpi/actbl3.h                         |   2 +-
+ include/acpi/actypes.h                        |  66 ++--
+ include/acpi/platform/acenv.h                 |   2 +-
+ include/acpi/platform/acgcc.h                 |   2 +-
+ include/acpi/platform/aclinux.h               |  20 +-
+ include/linux/acpi.h                          |   4 +
+ include/linux/pci-acpi.h                      |   4 +-
+ include/linux/pm.h                            |   3 +
+ include/linux/pm_qos.h                        |  34 +-
+ include/trace/events/power.h                  |   4 +-
+ kernel/power/qos.c                            |  18 +-
+ 236 files changed, 1831 insertions(+), 1486 deletions(-)
+Merging idle/next (62eec04c7fa3 Merge branch 'turbostat' into release)
+$ git merge idle/next
+Merge made by the 'recursive' strategy.
+ arch/x86/kernel/acpi/cstate.c         |   4 +-
+ drivers/idle/intel_idle.c             |  62 ++++++++-
+ tools/power/x86/turbostat/turbostat.8 | 127 +++++++------------
+ tools/power/x86/turbostat/turbostat.c | 228 ++++++++++++++++------------------
+ 4 files changed, 212 insertions(+), 209 deletions(-)
+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 (e79ca84d62d2 Merge branches 'soc-fix' and 'thermal-core-fix' of .git into next)
+$ git merge thermal/next
+Auto-merging drivers/thermal/Kconfig
+Merge made by the 'recursive' strategy.
+ drivers/thermal/Kconfig                     | 13 ++++++++--
+ drivers/thermal/imx_thermal.c               | 39 +++++++++++++++++++----------
+ drivers/thermal/rcar_thermal.c              |  9 +++++--
+ drivers/thermal/thermal_core.c              | 27 ++++++++++++++------
+ drivers/thermal/ti-soc-thermal/ti-bandgap.c |  6 ++---
+ drivers/thermal/x86_pkg_temp_thermal.c      | 11 ++++----
+ 6 files changed, 71 insertions(+), 34 deletions(-)
+Merging ieee1394/for-next (8987583366ae firewire: net: fix use after free)
+$ git merge ieee1394/for-next
+Merge made by the 'recursive' strategy.
+ drivers/firewire/net.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+Merging dlm/next (075f01775f53 dlm: use INFO for recovery messages)
+$ git merge dlm/next
+Merge made by the 'recursive' strategy.
+ fs/dlm/ast.c          |  3 ++-
+ fs/dlm/dir.c          |  4 ++--
+ fs/dlm/dlm_internal.h |  2 ++
+ fs/dlm/lock.c         |  7 ++++---
+ fs/dlm/lockspace.c    |  8 ++++----
+ fs/dlm/member.c       | 27 ++++++++++++---------------
+ fs/dlm/recover.c      | 10 +++++-----
+ fs/dlm/recoverd.c     | 34 +++++++++++++++++-----------------
+ 8 files changed, 48 insertions(+), 47 deletions(-)
+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 (3c79200df630 Merge branch 'fixes' into next)
+$ git merge slave-dma/next
+Auto-merging drivers/dma/Kconfig
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/dma/fsl-edma.txt |  76 ++
+ drivers/dma/Kconfig                                |  12 +-
+ drivers/dma/Makefile                               |   1 +
+ drivers/dma/acpi-dma.c                             |  17 +-
+ drivers/dma/dmaengine.c                            |   9 +-
+ drivers/dma/dw/core.c                              |   4 +-
+ drivers/dma/dw/pci.c                               |   3 +
+ drivers/dma/fsl-edma.c                             | 975 +++++++++++++++++++++
+ include/linux/acpi_dma.h                           |   5 +-
+ include/linux/dw_dmac.h                            |   5 +-
+ 10 files changed, 1083 insertions(+), 24 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/dma/fsl-edma.txt
+ create mode 100644 drivers/dma/fsl-edma.c
+Merging dmaengine/next (77873803363c net_dma: mark broken)
+$ git merge dmaengine/next
+Already up-to-date.
+Merging net-next/master (f19c29e3e391 tcp: snmp stats for Fast Open, SYN rtx, and data pkts)
+$ git merge net-next/master
+Resolved 'drivers/net/wireless/ath/ath9k/recv.c' using previous resolution.
+Resolved 'drivers/net/wireless/mwifiex/pcie.c' using previous resolution.
+Resolved 'net/ipv6/sit.c' using previous resolution.
+Auto-merging net/xfrm/xfrm_user.c
+Auto-merging net/xfrm/xfrm_state.c
+Auto-merging net/xfrm/xfrm_policy.c
+Auto-merging net/wireless/reg.c
+Auto-merging net/tipc/socket.c
+Auto-merging net/tipc/core.c
+Auto-merging net/tipc/bearer.c
+Auto-merging net/sched/sch_tbf.c
+Auto-merging net/netlink/af_netlink.c
+Auto-merging net/mac80211/util.c
+Auto-merging net/mac80211/tx.c
+Auto-merging net/mac80211/sta_info.h
+Auto-merging net/mac80211/rx.c
+Auto-merging net/mac80211/mlme.c
+Auto-merging net/mac80211/ieee80211_i.h
+Auto-merging net/ipv6/sit.c
+CONFLICT (content): Merge conflict in net/ipv6/sit.c
+Auto-merging net/ipv6/ip6_output.c
+Auto-merging net/ipv4/tcp_output.c
+Auto-merging net/ipv4/tcp_input.c
+Auto-merging net/ipv4/tcp_cong.c
+Auto-merging net/ipv4/tcp.c
+Auto-merging net/ipv4/ip_tunnel.c
+Auto-merging net/ipv4/ip_output.c
+Auto-merging net/ieee802154/6lowpan_rtnl.c
+Auto-merging net/hsr/hsr_framereg.c
+Auto-merging net/core/skbuff.c
+Auto-merging net/core/neighbour.c
+Auto-merging include/net/xfrm.h
+Auto-merging include/net/tcp.h
+Auto-merging include/linux/skbuff.h
+Auto-merging drivers/net/xen-netfront.c
+Auto-merging drivers/net/wireless/mwifiex/wmm.c
+Auto-merging drivers/net/wireless/mwifiex/pcie.c
+CONFLICT (content): Merge conflict in drivers/net/wireless/mwifiex/pcie.c
+Auto-merging drivers/net/wireless/libertas/cfg.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/tx.c
+Removing drivers/net/wireless/iwlwifi/mvm/power_legacy.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/mvm.h
+Removing drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+Removing drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+Auto-merging drivers/net/wireless/ath/ath9k/xmit.c
+Auto-merging drivers/net/wireless/ath/ath9k/recv.c
+CONFLICT (content): Merge conflict in drivers/net/wireless/ath/ath9k/recv.c
+Removing drivers/net/wireless/ath/ath9k/rc.h
+Removing drivers/net/wireless/ath/ath9k/rc.c
+Auto-merging drivers/net/wireless/ath/ath9k/hw.c
+Auto-merging drivers/net/veth.c
+Auto-merging drivers/net/phy/phy_device.c
+Auto-merging drivers/net/macvlan.c
+Auto-merging drivers/net/ethernet/ti/cpsw.c
+Auto-merging drivers/net/ethernet/sfc/ptp.c
+Auto-merging drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+Auto-merging drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+Auto-merging drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+Auto-merging drivers/net/ethernet/mellanox/mlx5/core/main.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+Removing drivers/net/ethernet/freescale/gianfar_sysfs.c
+Auto-merging drivers/net/ethernet/emulex/benet/be_main.c
+Auto-merging drivers/net/ethernet/emulex/benet/be.h
+Auto-merging drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+Auto-merging drivers/net/ethernet/brocade/bna/bnad.c
+Auto-merging drivers/net/ethernet/broadcom/tg3.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+Removing drivers/net/can/sja1000/sja1000_of_platform.c
+Auto-merging drivers/net/bonding/bonding.h
+Auto-merging drivers/net/bonding/bond_main.c
+Auto-merging drivers/net/bonding/bond_3ad.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 951751adc4dc] Merge remote-tracking branch 'net-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-bus-mdio           |   20 +
+ .../bindings/net/allwinner,sun4i-emac.txt          |    6 +-
+ Documentation/devicetree/bindings/net/arc_emac.txt |   11 +-
+ .../devicetree/bindings/net/broadcom-bcmgenet.txt  |  121 +
+ .../devicetree/bindings/net/can/sja1000.txt        |    4 +
+ .../devicetree/bindings/net/cavium-mix.txt         |    7 +-
+ .../devicetree/bindings/net/cavium-pip.txt         |    7 +-
+ .../devicetree/bindings/net/cdns-emac.txt          |    6 +-
+ Documentation/devicetree/bindings/net/cpsw.txt     |    5 +-
+ .../devicetree/bindings/net/davicom-dm9000.txt     |    2 -
+ .../devicetree/bindings/net/davinci_emac.txt       |    3 +-
+ Documentation/devicetree/bindings/net/ethernet.txt |   25 +
+ Documentation/devicetree/bindings/net/fsl-fec.txt  |    5 +-
+ .../devicetree/bindings/net/fsl-tsec-phy.txt       |   13 +-
+ Documentation/devicetree/bindings/net/lpc-eth.txt  |    5 +-
+ Documentation/devicetree/bindings/net/macb.txt     |    6 +-
+ .../bindings/net/marvell-armada-370-neta.txt       |    6 +-
+ .../devicetree/bindings/net/marvell-orion-net.txt  |    4 +-
+ .../devicetree/bindings/net/micrel-ks8851.txt      |    3 -
+ Documentation/devicetree/bindings/net/micrel.txt   |   18 +
+ Documentation/devicetree/bindings/net/sh_eth.txt   |   55 +
+ .../devicetree/bindings/net/smsc-lan91c111.txt     |    3 +-
+ Documentation/devicetree/bindings/net/smsc911x.txt |    5 +-
+ Documentation/devicetree/bindings/net/stmmac.txt   |    7 +-
+ Documentation/networking/bonding.txt               |   96 +-
+ Documentation/networking/gianfar.txt               |   30 -
+ Documentation/networking/phy.txt                   |    9 +
+ Documentation/networking/pktgen.txt                |   24 +-
+ Documentation/networking/tcp.txt                   |    2 +-
+ MAINTAINERS                                        |   14 +-
+ drivers/atm/ambassador.c                           |    2 +-
+ drivers/atm/firestream.c                           |    4 +-
+ drivers/atm/nicstar.c                              |   24 +-
+ drivers/atm/solos-pci.c                            |    2 +-
+ drivers/connector/connector.c                      |    1 -
+ drivers/isdn/divert/divert_procfs.c                |    7 +-
+ drivers/isdn/hisax/elsa.c                          |    9 +-
+ drivers/isdn/hisax/elsa_ser.c                      |    3 +-
+ drivers/isdn/hysdn/hysdn_proclog.c                 |    7 +-
+ drivers/isdn/i4l/isdn_common.c                     |   13 +-
+ drivers/isdn/pcbit/drv.c                           |    6 +-
+ drivers/net/bonding/bond_3ad.c                     |   38 +-
+ drivers/net/bonding/bond_3ad.h                     |  175 +-
+ drivers/net/bonding/bond_alb.c                     |  134 +-
+ drivers/net/bonding/bond_debugfs.c                 |   10 +-
+ drivers/net/bonding/bond_main.c                    |  330 ++-
+ drivers/net/bonding/bond_netlink.c                 |    6 +-
+ drivers/net/bonding/bond_options.c                 |  124 +-
+ drivers/net/bonding/bond_procfs.c                  |   12 +-
+ drivers/net/bonding/bond_sysfs.c                   |    8 +-
+ drivers/net/bonding/bonding.h                      |   26 +-
+ drivers/net/caif/caif_serial.c                     |    1 -
+ drivers/net/caif/caif_spi.c                        |    1 -
+ drivers/net/can/at91_can.c                         |    9 +-
+ drivers/net/can/dev.c                              |   24 +
+ drivers/net/can/sja1000/Kconfig                    |   13 +-
+ drivers/net/can/sja1000/Makefile                   |    1 -
+ drivers/net/can/sja1000/sja1000.c                  |    3 +-
+ drivers/net/can/sja1000/sja1000_of_platform.c      |  220 --
+ drivers/net/can/sja1000/sja1000_platform.c         |  194 +-
+ drivers/net/dummy.c                                |    8 +-
+ drivers/net/ethernet/3com/3c589_cs.c               | 1127 ++++-----
+ drivers/net/ethernet/amd/pcnet32.c                 |  124 +-
+ drivers/net/ethernet/broadcom/Kconfig              |   11 +
+ drivers/net/ethernet/broadcom/Makefile             |    1 +
+ drivers/net/ethernet/broadcom/bnx2.c               |   15 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |   24 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |  153 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h    |   48 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c    |    8 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h    |    1 -
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h    |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |  235 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |  155 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h     |   21 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c  |  289 ++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h  |   13 +
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c   |  127 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h   |   22 +
+ drivers/net/ethernet/broadcom/genet/Makefile       |    2 +
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c     | 2578 ++++++++++++++++++++
+ drivers/net/ethernet/broadcom/genet/bcmgenet.h     |  629 +++++
+ drivers/net/ethernet/broadcom/genet/bcmmii.c       |  464 ++++
+ drivers/net/ethernet/broadcom/tg3.c                |    6 +-
+ drivers/net/ethernet/brocade/bna/bnad.c            |   23 +-
+ drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c    |   26 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |    5 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  123 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |    1 +
+ drivers/net/ethernet/chelsio/cxgb4/sge.c           |   38 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |   46 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h      |    4 +
+ .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c    |   35 +-
+ drivers/net/ethernet/cisco/enic/enic_main.c        |    6 +-
+ drivers/net/ethernet/emulex/benet/be.h             |   14 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.c        |   22 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.h        |   38 +-
+ drivers/net/ethernet/emulex/benet/be_ethtool.c     |    2 +-
+ drivers/net/ethernet/emulex/benet/be_hw.h          |    6 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |  202 +-
+ drivers/net/ethernet/emulex/benet/be_roce.c        |    2 +-
+ drivers/net/ethernet/emulex/benet/be_roce.h        |    2 +-
+ drivers/net/ethernet/freescale/Makefile            |    3 +-
+ drivers/net/ethernet/freescale/gianfar.c           | 1071 ++++----
+ drivers/net/ethernet/freescale/gianfar.h           |   62 +-
+ drivers/net/ethernet/freescale/gianfar_ethtool.c   |  165 +-
+ drivers/net/ethernet/freescale/gianfar_sysfs.c     |  340 ---
+ drivers/net/ethernet/intel/e1000e/netdev.c         |   11 +-
+ drivers/net/ethernet/intel/i40e/i40e_adminq.c      |    5 +-
+ drivers/net/ethernet/intel/i40e/i40e_main.c        |  102 +-
+ drivers/net/ethernet/intel/i40e/i40e_txrx.c        |    2 +-
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |   33 +-
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h |    1 +
+ .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h    |    2 +-
+ drivers/net/ethernet/intel/i40evf/i40e_txrx.c      |    8 +-
+ drivers/net/ethernet/intel/i40evf/i40e_type.h      |    4 +-
+ drivers/net/ethernet/intel/i40evf/i40evf.h         |   47 +-
+ drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c |   13 +-
+ drivers/net/ethernet/intel/i40evf/i40evf_main.c    |  242 +-
+ .../net/ethernet/intel/i40evf/i40evf_virtchnl.c    |   27 +-
+ drivers/net/ethernet/intel/igb/Makefile            |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.c       |    9 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.h       |    7 +-
+ drivers/net/ethernet/intel/igb/e1000_defines.h     |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_hw.h          |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_i210.c        |   25 +-
+ drivers/net/ethernet/intel/igb/e1000_i210.h        |   14 +-
+ drivers/net/ethernet/intel/igb/e1000_mac.c         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_mac.h         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_mbx.c         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_mbx.h         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_nvm.c         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_nvm.h         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.c         |   76 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.h         |    6 +-
+ drivers/net/ethernet/intel/igb/e1000_regs.h        |    5 +-
+ drivers/net/ethernet/intel/igb/igb.h               |    7 +-
+ drivers/net/ethernet/intel/igb/igb_ethtool.c       |    5 +-
+ drivers/net/ethernet/intel/igb/igb_hwmon.c         |    5 +-
+ drivers/net/ethernet/intel/igb/igb_main.c          |   16 +-
+ drivers/net/ethernet/intel/igb/igb_ptp.c           |   11 +-
+ drivers/net/ethernet/intel/igbvf/netdev.c          |    6 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe.h           |    6 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c     |   12 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c     |  189 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.c    |  188 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h    |   11 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c   |    9 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c       |   16 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |   87 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c       |   44 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h       |    3 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c       |   31 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h      |   22 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c      |    2 +
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |   37 +-
+ drivers/net/ethernet/marvell/mvneta.c              |    9 +-
+ drivers/net/ethernet/mellanox/mlx4/Kconfig         |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c     |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_main.c       |   45 +-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |   34 +-
+ drivers/net/ethernet/mellanox/mlx4/en_port.c       |    6 +
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c         |   25 +
+ drivers/net/ethernet/mellanox/mlx4/en_selftest.c   |    6 +-
+ drivers/net/ethernet/mellanox/mlx4/en_tx.c         |   38 +-
+ drivers/net/ethernet/mellanox/mlx4/fw.c            |    3 +-
+ drivers/net/ethernet/mellanox/mlx4/main.c          |   24 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h       |   14 +-
+ drivers/net/ethernet/mellanox/mlx5/core/main.c     |   16 +-
+ drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |   40 +-
+ drivers/net/ethernet/neterion/s2io.c               |    5 +-
+ drivers/net/ethernet/neterion/vxge/vxge-main.c     |   15 +-
+ drivers/net/ethernet/nvidia/forcedeth.c            |   41 +-
+ .../net/ethernet/qlogic/netxen/netxen_nic_main.c   |    5 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |   77 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |    7 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |    8 +
+ .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |   17 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |   22 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h     |    8 +
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   29 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c   |  233 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c   |    6 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c  |  102 +-
+ drivers/net/ethernet/qlogic/qlge/qlge_main.c       |   16 +-
+ drivers/net/ethernet/renesas/sh_eth.c              |   73 +-
+ drivers/net/ethernet/renesas/sh_eth.h              |    3 +-
+ drivers/net/ethernet/sfc/ef10.c                    |    4 +-
+ drivers/net/ethernet/sfc/ef10_regs.h               |   61 -
+ drivers/net/ethernet/sfc/efx.c                     |   26 +-
+ drivers/net/ethernet/sfc/efx.h                     |    2 +-
+ drivers/net/ethernet/sfc/ethtool.c                 |   21 +-
+ drivers/net/ethernet/sfc/falcon.c                  |    4 +-
+ drivers/net/ethernet/sfc/farch.c                   |    2 -
+ drivers/net/ethernet/sfc/net_driver.h              |    1 -
+ drivers/net/ethernet/sfc/nic.c                     |    1 -
+ drivers/net/ethernet/sfc/ptp.c                     |   92 +-
+ drivers/net/ethernet/sfc/tx.c                      |   21 +-
+ drivers/net/ethernet/sun/niu.c                     |   11 +-
+ drivers/net/ethernet/ti/cpsw.c                     |   10 +-
+ drivers/net/ethernet/wiznet/w5100.c                |    9 +-
+ drivers/net/ethernet/wiznet/w5300.c                |    9 +-
+ drivers/net/hyperv/hyperv_net.h                    |   61 +-
+ drivers/net/hyperv/netvsc.c                        |   87 +-
+ drivers/net/hyperv/netvsc_drv.c                    |    4 +-
+ drivers/net/hyperv/rndis_filter.c                  |   41 +-
+ drivers/net/ieee802154/at86rf230.c                 |  428 +++-
+ drivers/net/loopback.c                             |   12 +-
+ drivers/net/macvlan.c                              |    9 +-
+ drivers/net/nlmon.c                                |   11 +-
+ drivers/net/phy/Kconfig                            |    6 +
+ drivers/net/phy/Makefile                           |    1 +
+ drivers/net/phy/bcm7xxx.c                          |  343 +++
+ drivers/net/phy/broadcom.c                         |   52 -
+ drivers/net/phy/mdio_bus.c                         |   20 +
+ drivers/net/phy/micrel.c                           |   49 +-
+ drivers/net/phy/phy.c                              |   51 +-
+ drivers/net/phy/phy_device.c                       |   57 +-
+ drivers/net/team/team.c                            |    8 +-
+ drivers/net/usb/r8152.c                            |  711 ++++--
+ drivers/net/veth.c                                 |   19 +-
+ drivers/net/vmxnet3/vmxnet3_drv.c                  |  110 +-
+ drivers/net/vxlan.c                                |   13 +-
+ drivers/net/wireless/ath/ath.h                     |    2 +
+ drivers/net/wireless/ath/ath10k/txrx.c             |    4 +-
+ drivers/net/wireless/ath/ath6kl/cfg80211.c         |   27 +-
+ drivers/net/wireless/ath/ath9k/Kconfig             |   12 -
+ drivers/net/wireless/ath/ath9k/Makefile            |    1 -
+ drivers/net/wireless/ath/ath9k/ar9003_calib.c      |  235 +-
+ drivers/net/wireless/ath/ath9k/ath9k.h             |   11 +-
+ drivers/net/wireless/ath/ath9k/beacon.c            |   29 +-
+ drivers/net/wireless/ath/ath9k/common.c            |  244 ++
+ drivers/net/wireless/ath/ath9k/common.h            |   19 +
+ drivers/net/wireless/ath/ath9k/debug.h             |    1 -
+ drivers/net/wireless/ath/ath9k/dfs_debug.h         |    2 +
+ drivers/net/wireless/ath/ath9k/hif_usb.c           |    2 +
+ drivers/net/wireless/ath/ath9k/htc.h               |    1 -
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c      |    1 +
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c      |    1 +
+ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      |  176 +-
+ drivers/net/wireless/ath/ath9k/htc_hst.c           |   36 +
+ drivers/net/wireless/ath/ath9k/htc_hst.h           |   12 +
+ drivers/net/wireless/ath/ath9k/hw.c                |    1 -
+ drivers/net/wireless/ath/ath9k/init.c              |   16 +-
+ drivers/net/wireless/ath/ath9k/mac.h               |    9 +-
+ drivers/net/wireless/ath/ath9k/main.c              |   16 +-
+ drivers/net/wireless/ath/ath9k/rc.c                | 1495 ------------
+ drivers/net/wireless/ath/ath9k/rc.h                |  248 --
+ drivers/net/wireless/ath/ath9k/recv.c              |  267 +-
+ drivers/net/wireless/ath/ath9k/xmit.c              |    2 +-
+ drivers/net/wireless/ath/wcn36xx/dxe.c             |   10 +-
+ drivers/net/wireless/ath/wcn36xx/dxe.h             |    4 +-
+ drivers/net/wireless/ath/wcn36xx/hal.h             |    4 +-
+ drivers/net/wireless/ath/wcn36xx/main.c            |   72 +-
+ drivers/net/wireless/ath/wcn36xx/smd.c             |   64 +-
+ drivers/net/wireless/ath/wcn36xx/smd.h             |    5 +-
+ drivers/net/wireless/ath/wcn36xx/txrx.c            |    7 +-
+ drivers/net/wireless/ath/wcn36xx/wcn36xx.h         |   10 +-
+ drivers/net/wireless/ath/wil6210/pcie_bus.c        |   32 +-
+ drivers/net/wireless/b43/main.h                    |   35 -
+ drivers/net/wireless/b43/xmit.c                    |   12 +-
+ drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    4 +-
+ drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |    8 +-
+ drivers/net/wireless/brcm80211/brcmfmac/chip.c     | 1029 ++++++++
+ drivers/net/wireless/brcm80211/brcmfmac/chip.h     |   91 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  536 ++--
+ drivers/net/wireless/brcm80211/brcmfmac/fwil.c     |    5 +-
+ drivers/net/wireless/brcm80211/brcmfmac/fwil.h     |    2 +-
+ .../net/wireless/brcm80211/brcmfmac/sdio_chip.c    |  972 --------
+ .../net/wireless/brcm80211/brcmfmac/sdio_chip.h    |  231 --
+ .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |   89 +
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   83 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |    3 +-
+ drivers/net/wireless/iwlegacy/3945-rs.c            |    3 +-
+ drivers/net/wireless/iwlegacy/4965-rs.c            |    3 +-
+ drivers/net/wireless/iwlwifi/Kconfig               |   14 +
+ drivers/net/wireless/iwlwifi/Makefile              |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/rs.c              |   23 +-
+ drivers/net/wireless/iwlwifi/dvm/rs.h              |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-7000.c            |   23 +-
+ drivers/net/wireless/iwlwifi/iwl-8000.c            |  132 +
+ drivers/net/wireless/iwlwifi/iwl-config.h          |   18 +
+ drivers/net/wireless/iwlwifi/iwl-csr.h             |   32 -
+ drivers/net/wireless/iwlwifi/iwl-debug.h           |    2 +
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |    5 +-
+ drivers/net/wireless/iwlwifi/iwl-fw.h              |    7 +-
+ drivers/net/wireless/iwlwifi/iwl-io.c              |   15 +
+ drivers/net/wireless/iwlwifi/iwl-io.h              |    2 +
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.c       |    6 +-
+ drivers/net/wireless/iwlwifi/iwl-op-mode.h         |   24 +-
+ drivers/net/wireless/iwlwifi/iwl-phy-db.c          |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-prph.h            |   46 +
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |   38 +
+ drivers/net/wireless/iwlwifi/mvm/Makefile          |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/bt-coex.c         |  138 +-
+ drivers/net/wireless/iwlwifi/mvm/constants.h       |    4 +
+ drivers/net/wireless/iwlwifi/mvm/d3.c              |   31 +-
+ drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c     |  112 +-
+ drivers/net/wireless/iwlwifi/mvm/debugfs.c         |  285 ++-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h  |   17 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h       |    6 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-power.h    |   33 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h      |   31 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api.h          |  128 +-
+ drivers/net/wireless/iwlwifi/mvm/fw.c              |   67 +-
+ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c        |   76 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c        |  476 +++-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h             |  168 +-
+ drivers/net/wireless/iwlwifi/mvm/nvm.c             |   34 +-
+ drivers/net/wireless/iwlwifi/mvm/ops.c             |  257 +-
+ drivers/net/wireless/iwlwifi/mvm/power.c           |  385 ++-
+ drivers/net/wireless/iwlwifi/mvm/power_legacy.c    |  319 ---
+ drivers/net/wireless/iwlwifi/mvm/quota.c           |  119 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.c              |   29 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.h              |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/rx.c              |   12 +-
+ drivers/net/wireless/iwlwifi/mvm/scan.c            |   15 +-
+ drivers/net/wireless/iwlwifi/mvm/sta.c             |  203 +-
+ drivers/net/wireless/iwlwifi/mvm/sta.h             |   62 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.c      |    2 +
+ drivers/net/wireless/iwlwifi/mvm/tt.c              |    7 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c              |   23 +
+ drivers/net/wireless/iwlwifi/mvm/utils.c           |   99 +-
+ drivers/net/wireless/iwlwifi/pcie/drv.c            |   82 +
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |    3 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |  267 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |    5 +-
+ drivers/net/wireless/libertas/cfg.c                |    3 +-
+ drivers/net/wireless/mac80211_hwsim.c              |   90 +-
+ drivers/net/wireless/mac80211_hwsim.h              |    2 +
+ drivers/net/wireless/mwifiex/11ac.c                |  192 +-
+ drivers/net/wireless/mwifiex/11ac.h                |    2 +
+ drivers/net/wireless/mwifiex/11n.c                 |   51 +-
+ drivers/net/wireless/mwifiex/11n.h                 |   44 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.c       |   27 +-
+ drivers/net/wireless/mwifiex/Makefile              |    1 +
+ drivers/net/wireless/mwifiex/cfg80211.c            |  184 +-
+ drivers/net/wireless/mwifiex/cfp.c                 |  203 +-
+ drivers/net/wireless/mwifiex/cmdevt.c              |   54 +-
+ drivers/net/wireless/mwifiex/decl.h                |   23 +
+ drivers/net/wireless/mwifiex/fw.h                  |  181 +-
+ drivers/net/wireless/mwifiex/init.c                |    5 +
+ drivers/net/wireless/mwifiex/ioctl.h               |   22 +-
+ drivers/net/wireless/mwifiex/join.c                |   14 +-
+ drivers/net/wireless/mwifiex/main.h                |   90 +-
+ drivers/net/wireless/mwifiex/pcie.c                |  138 +-
+ drivers/net/wireless/mwifiex/scan.c                |  598 +++--
+ drivers/net/wireless/mwifiex/sta_cmd.c             |  373 ++-
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |  112 +-
+ drivers/net/wireless/mwifiex/sta_event.c           |   12 +
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |   40 +-
+ drivers/net/wireless/mwifiex/sta_rx.c              |   13 +-
+ drivers/net/wireless/mwifiex/sta_tx.c              |    3 +
+ drivers/net/wireless/mwifiex/tdls.c                | 1044 ++++++++
+ drivers/net/wireless/mwifiex/uap_event.c           |  118 -
+ drivers/net/wireless/mwifiex/util.c                |  114 +
+ drivers/net/wireless/mwifiex/util.h                |   20 +-
+ drivers/net/wireless/mwifiex/wmm.c                 |   96 +-
+ drivers/net/wireless/mwifiex/wmm.h                 |   18 +
+ drivers/net/wireless/rndis_wlan.c                  |    4 +-
+ drivers/net/wireless/rt2x00/rt2800usb.c            |   10 +-
+ drivers/net/wireless/rtl818x/rtl8180/dev.c         |    8 +-
+ drivers/net/wireless/rtl818x/rtl8187/dev.c         |   14 +-
+ drivers/net/wireless/rtl818x/rtl818x.h             |   10 +-
+ drivers/net/wireless/rtlwifi/rc.c                  |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8188ee/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/trx.c       |    2 +-
+ drivers/net/wireless/ti/wl12xx/main.c              |   67 +-
+ drivers/net/wireless/ti/wl12xx/wl12xx.h            |   53 +
+ drivers/net/wireless/ti/wl18xx/main.c              |   85 +-
+ drivers/net/wireless/ti/wl18xx/tx.c                |    4 +-
+ drivers/net/wireless/ti/wl18xx/wl18xx.h            |   62 +-
+ drivers/net/wireless/ti/wlcore/acx.c               |    7 +-
+ drivers/net/wireless/ti/wlcore/acx.h               |    6 +-
+ drivers/net/wireless/ti/wlcore/cmd.c               |   24 +-
+ drivers/net/wireless/ti/wlcore/cmd.h               |    9 +-
+ drivers/net/wireless/ti/wlcore/event.c             |    4 +-
+ drivers/net/wireless/ti/wlcore/hw_ops.h            |    9 +
+ drivers/net/wireless/ti/wlcore/init.c              |    6 +-
+ drivers/net/wireless/ti/wlcore/io.h                |    8 +-
+ drivers/net/wireless/ti/wlcore/main.c              |  192 +-
+ drivers/net/wireless/ti/wlcore/ps.c                |    6 +-
+ drivers/net/wireless/ti/wlcore/rx.c                |   19 +-
+ drivers/net/wireless/ti/wlcore/rx.h                |    2 +-
+ drivers/net/wireless/ti/wlcore/tx.c                |   45 +-
+ drivers/net/wireless/ti/wlcore/tx.h                |    1 +
+ drivers/net/wireless/ti/wlcore/wlcore.h            |   27 +-
+ drivers/net/wireless/ti/wlcore/wlcore_i.h          |   86 +-
+ drivers/net/xen-netfront.c                         |    8 +-
+ drivers/of/of_net.c                                |   26 +-
+ drivers/staging/rtl8821ae/rc.c                     |    1 -
+ include/linux/brcmphy.h                            |   60 +
+ include/linux/can/dev.h                            |    2 +
+ include/linux/ethtool.h                            |    3 +
+ include/linux/ieee80211.h                          |  199 +-
+ include/linux/mlx4/driver.h                        |   12 +
+ include/linux/mlx4/qp.h                            |   11 +-
+ include/linux/netdevice.h                          |  109 +-
+ include/linux/nl802154.h                           |   12 +
+ include/linux/phy.h                                |   56 +
+ include/linux/skbuff.h                             |   61 +-
+ include/linux/tcp.h                                |    8 +-
+ include/net/act_api.h                              |   22 +-
+ include/net/addrconf.h                             |    6 +-
+ include/net/cfg80211.h                             |   43 +-
+ include/net/flow.h                                 |    5 +-
+ include/net/flowcache.h                            |   25 +
+ include/net/ieee80211_radiotap.h                   |    4 +
+ include/net/ieee802154_netdev.h                    |    7 +
+ include/net/ip.h                                   |   12 +-
+ include/net/ip6_route.h                            |    9 +-
+ include/net/mac80211.h                             |   52 +-
+ include/net/mac802154.h                            |   35 +
+ include/net/net_namespace.h                        |    4 +
+ include/net/netns/ieee802154_6lowpan.h             |   22 +
+ include/net/netns/xfrm.h                           |   12 +-
+ include/net/rtnetlink.h                            |    2 +-
+ include/net/tc_act/tc_csum.h                       |    4 +-
+ include/net/tc_act/tc_defact.h                     |    4 +-
+ include/net/tc_act/tc_gact.h                       |    4 +-
+ include/net/tc_act/tc_ipt.h                        |    4 +-
+ include/net/tc_act/tc_mirred.h                     |    4 +-
+ include/net/tc_act/tc_nat.h                        |    4 +-
+ include/net/tc_act/tc_pedit.h                      |    4 +-
+ include/net/tc_act/tc_skbedit.h                    |    4 +-
+ include/net/tcp.h                                  |   13 +-
+ include/net/wpan-phy.h                             |   19 +-
+ include/net/xfrm.h                                 |  108 +-
+ include/uapi/linux/can.h                           |   32 +
+ include/uapi/linux/ethtool.h                       |  439 +++-
+ include/uapi/linux/if.h                            |  134 +-
+ include/uapi/linux/if_ether.h                      |    4 +-
+ include/uapi/linux/in.h                            |    4 +
+ include/uapi/linux/in6.h                           |    4 +
+ include/uapi/linux/nl80211.h                       |   52 +-
+ include/uapi/linux/pfkeyv2.h                       |   15 +-
+ include/uapi/linux/snmp.h                          |    6 +
+ include/uapi/linux/tcp.h                           |    3 +
+ include/uapi/linux/tcp_metrics.h                   |    7 +-
+ include/uapi/linux/xfrm.h                          |   10 +
+ net/8021q/vlan_dev.c                               |   11 +-
+ net/appletalk/aarp.c                               |    4 +-
+ net/appletalk/ddp.c                                |  100 +-
+ net/batman-adv/gateway_client.c                    |    2 -
+ net/bridge/br_device.c                             |   11 +-
+ net/bridge/br_multicast.c                          |    4 +-
+ net/bridge/br_netfilter.c                          |    2 +-
+ net/bridge/br_private.h                            |    4 +-
+ net/bridge/netfilter/ebt_among.c                   |    2 +-
+ net/bridge/netfilter/ebt_dnat.c                    |    2 +-
+ net/bridge/netfilter/ebt_redirect.c                |    6 +-
+ net/bridge/netfilter/ebt_snat.c                    |    2 +-
+ net/ceph/osd_client.c                              |    2 -
+ net/core/flow.c                                    |  127 +-
+ net/core/neighbour.c                               |    9 +-
+ net/core/net-sysfs.c                               |   11 +-
+ net/core/pktgen.c                                  |   32 +-
+ net/core/request_sock.c                            |    1 -
+ net/core/rtnetlink.c                               |  107 +-
+ net/core/skbuff.c                                  |   26 +
+ net/hsr/hsr_device.c                               |   10 +-
+ net/hsr/hsr_framereg.c                             |   20 +-
+ net/hsr/hsr_main.c                                 |    4 +-
+ net/ieee802154/6lowpan.h                           |  113 +
+ net/ieee802154/{6lowpan.c => 6lowpan_rtnl.c}       |  327 +--
+ net/ieee802154/Makefile                            |    1 +
+ net/ieee802154/ieee802154.h                        |    1 +
+ net/ieee802154/netlink.c                           |    1 +
+ net/ieee802154/nl-phy.c                            |  200 +-
+ net/ieee802154/nl_policy.c                         |   10 +
+ net/ieee802154/reassembly.c                        |  564 +++++
+ net/ieee802154/reassembly.h                        |   66 +
+ net/ieee802154/wpan-class.c                        |   10 +-
+ net/ipv4/Makefile                                  |    2 +-
+ net/ipv4/ah4.c                                     |   78 +-
+ net/ipv4/esp4.c                                    |   26 +-
+ net/ipv4/ip_forward.c                              |    7 +-
+ net/ipv4/ip_output.c                               |   12 +-
+ net/ipv4/ip_sockglue.c                             |   21 +-
+ net/ipv4/ip_tunnel.c                               |   31 +-
+ net/ipv4/ip_vti.c                                  |  310 ++-
+ net/ipv4/ipcomp.c                                  |   26 +-
+ net/ipv4/ping.c                                    |    2 +-
+ net/ipv4/proc.c                                    |    6 +
+ net/ipv4/raw.c                                     |    2 +-
+ net/ipv4/route.c                                   |    1 -
+ net/ipv4/tcp.c                                     |   13 +-
+ net/ipv4/tcp_cong.c                                |   10 -
+ net/ipv4/tcp_cubic.c                               |    4 -
+ net/ipv4/tcp_highspeed.c                           |    1 -
+ net/ipv4/tcp_hybla.c                               |   13 +-
+ net/ipv4/tcp_illinois.c                            |    2 -
+ net/ipv4/tcp_input.c                               |  186 +-
+ net/ipv4/tcp_ipv4.c                                |    6 +-
+ net/ipv4/tcp_lp.c                                  |    2 -
+ net/ipv4/tcp_metrics.c                             |   83 +-
+ net/ipv4/tcp_minisocks.c                           |    4 +-
+ net/ipv4/tcp_output.c                              |   53 +-
+ net/ipv4/tcp_probe.c                               |    2 +-
+ net/ipv4/tcp_scalable.c                            |    1 -
+ net/ipv4/tcp_timer.c                               |    3 +
+ net/ipv4/tcp_vegas.c                               |    2 -
+ net/ipv4/tcp_veno.c                                |    1 -
+ net/ipv4/tcp_westwood.c                            |    1 -
+ net/ipv4/tcp_yeah.c                                |    2 -
+ net/ipv4/udp.c                                     |    3 +-
+ net/ipv4/xfrm4_input.c                             |    9 -
+ net/ipv4/xfrm4_mode_tunnel.c                       |   68 -
+ net/ipv4/xfrm4_protocol.c                          |  275 +++
+ net/ipv6/addrlabel.c                               |   59 +-
+ net/ipv6/ah6.c                                     |   56 +-
+ net/ipv6/ip6_checksum.c                            |    4 +-
+ net/ipv6/ip6_flowlabel.c                           |    6 -
+ net/ipv6/ip6_gre.c                                 |    9 +-
+ net/ipv6/ip6_output.c                              |    9 +-
+ net/ipv6/ip6_tunnel.c                              |    9 +-
+ net/ipv6/ip6_vti.c                                 |    8 +-
+ net/ipv6/ipv6_sockglue.c                           |    2 +-
+ net/ipv6/sit.c                                     |   18 +-
+ net/ipv6/tcp_ipv6.c                                |    4 +-
+ net/ipx/af_ipx.c                                   |   28 +-
+ net/key/af_key.c                                   |   39 +-
+ net/l2tp/l2tp_core.c                               |    2 -
+ net/l2tp/l2tp_ppp.c                                |    3 -
+ net/mac80211/agg-tx.c                              |    2 +-
+ net/mac80211/cfg.c                                 |  198 +-
+ net/mac80211/cfg.h                                 |    2 +-
+ net/mac80211/chan.c                                |    2 +
+ net/mac80211/debugfs_sta.c                         |    2 +-
+ net/mac80211/ht.c                                  |    2 +-
+ net/mac80211/ibss.c                                |   28 +-
+ net/mac80211/ieee80211_i.h                         |   14 +-
+ net/mac80211/iface.c                               |    2 +
+ net/mac80211/main.c                                |    9 +-
+ net/mac80211/mesh.c                                |   96 +-
+ net/mac80211/mlme.c                                |   41 +-
+ net/mac80211/rate.c                                |   46 +-
+ net/mac80211/rate.h                                |    2 +-
+ net/mac80211/rc80211_minstrel.c                    |    2 +-
+ net/mac80211/rc80211_minstrel.h                    |    2 +-
+ net/mac80211/rc80211_minstrel_ht.c                 |    7 +-
+ net/mac80211/rc80211_pid_algo.c                    |    2 +-
+ net/mac80211/rx.c                                  |  101 +-
+ net/mac80211/sta_info.h                            |    2 +
+ net/mac80211/status.c                              |    3 +-
+ net/mac80211/tx.c                                  |   33 +-
+ net/mac80211/util.c                                |   42 +-
+ net/mac80211/vht.c                                 |   26 +-
+ net/mac80211/wpa.c                                 |    9 +-
+ net/mac802154/ieee802154_dev.c                     |   67 +
+ net/mac802154/mib.c                                |    4 -
+ net/mac802154/rx.c                                 |    1 -
+ net/netlink/af_netlink.c                           |    4 +-
+ net/openvswitch/datapath.c                         |   20 +-
+ net/openvswitch/datapath.h                         |    2 +-
+ net/openvswitch/vport.c                            |   10 +-
+ net/packet/af_packet.c                             |   16 +-
+ net/rfkill/core.c                                  |    9 +-
+ net/sched/act_api.c                                |  142 +-
+ net/sched/act_csum.c                               |   31 +-
+ net/sched/act_gact.c                               |   34 +-
+ net/sched/act_ipt.c                                |   68 +-
+ net/sched/act_mirred.c                             |   56 +-
+ net/sched/act_nat.c                                |   33 +-
+ net/sched/act_pedit.c                              |   45 +-
+ net/sched/act_police.c                             |   22 +-
+ net/sched/act_simple.c                             |   64 +-
+ net/sched/act_skbedit.c                            |   36 +-
+ net/sched/sch_netem.c                              |   79 +-
+ net/sched/sch_tbf.c                                |   23 +-
+ net/sctp/transport.c                               |    1 -
+ net/socket.c                                       |   13 +-
+ net/tipc/addr.h                                    |    2 +
+ net/tipc/bcast.c                                   |   28 +-
+ net/tipc/bcast.h                                   |    4 +-
+ net/tipc/bearer.c                                  |   42 +-
+ net/tipc/bearer.h                                  |    7 +-
+ net/tipc/core.c                                    |    2 +-
+ net/tipc/discover.c                                |    4 +-
+ net/tipc/discover.h                                |    2 +-
+ net/tipc/link.c                                    |  608 ++---
+ net/tipc/link.h                                    |   57 +-
+ net/tipc/name_distr.c                              |    8 +-
+ net/tipc/name_distr.h                              |    2 +-
+ net/tipc/net.c                                     |   10 +-
+ net/tipc/node.c                                    |   14 +-
+ net/tipc/port.c                                    |   97 +-
+ net/tipc/port.h                                    |   26 +-
+ net/tipc/socket.c                                  |  188 +-
+ net/wireless/ap.c                                  |    3 +-
+ net/wireless/chan.c                                |   25 +-
+ net/wireless/core.c                                |    2 +-
+ net/wireless/core.h                                |    7 +-
+ net/wireless/ibss.c                                |   19 +-
+ net/wireless/mesh.c                                |    6 +-
+ net/wireless/mlme.c                                |    2 +-
+ net/wireless/nl80211.c                             |  229 +-
+ net/wireless/nl80211.h                             |    2 +
+ net/wireless/reg.c                                 |  188 +-
+ net/wireless/reg.h                                 |    2 +
+ net/wireless/trace.h                               |   23 +-
+ net/wireless/util.c                                |    5 +-
+ net/xfrm/xfrm_input.c                              |   22 +-
+ net/xfrm/xfrm_policy.c                             |   35 +-
+ net/xfrm/xfrm_state.c                              |   72 +-
+ net/xfrm/xfrm_user.c                               |   37 +-
+ security/selinux/include/xfrm.h                    |    5 +-
+ tools/net/bpf_dbg.c                                |  119 +-
+ 610 files changed, 24459 insertions(+), 13587 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
+ create mode 100644 Documentation/devicetree/bindings/net/ethernet.txt
+ create mode 100644 Documentation/devicetree/bindings/net/micrel.txt
+ create mode 100644 Documentation/devicetree/bindings/net/sh_eth.txt
+ delete mode 100644 drivers/net/can/sja1000/sja1000_of_platform.c
+ create mode 100644 drivers/net/ethernet/broadcom/genet/Makefile
+ create mode 100644 drivers/net/ethernet/broadcom/genet/bcmgenet.c
+ create mode 100644 drivers/net/ethernet/broadcom/genet/bcmgenet.h
+ create mode 100644 drivers/net/ethernet/broadcom/genet/bcmmii.c
+ delete mode 100644 drivers/net/ethernet/freescale/gianfar_sysfs.c
+ create mode 100644 drivers/net/phy/bcm7xxx.c
+ delete mode 100644 drivers/net/wireless/ath/ath9k/rc.c
+ delete mode 100644 drivers/net/wireless/ath/ath9k/rc.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/chip.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/chip.h
+ delete mode 100644 drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+ delete mode 100644 drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+ create mode 100644 drivers/net/wireless/iwlwifi/iwl-8000.c
+ delete mode 100644 drivers/net/wireless/iwlwifi/mvm/power_legacy.c
+ create mode 100644 drivers/net/wireless/mwifiex/tdls.c
+ create mode 100644 include/net/flowcache.h
+ create mode 100644 include/net/netns/ieee802154_6lowpan.h
+ rename net/ieee802154/{6lowpan.c => 6lowpan_rtnl.c} (70%)
+ create mode 100644 net/ieee802154/reassembly.c
+ create mode 100644 net/ieee802154/reassembly.h
+ create mode 100644 net/ipv4/xfrm4_protocol.c
+Merging ipsec-next/master (bc861959103c ipv6: addrconf: silence sparse endianness warnings)
+$ git merge ipsec-next/master
+Already up-to-date.
+Merging wireless-next/master (c14c5d99a453 wil6210: fix smatch warning in wil_cfg80211_get_station())
+$ git merge wireless-next/master
+Auto-merging net/wireless/reg.c
+Auto-merging net/wireless/chan.c
+Auto-merging net/mac80211/rx.c
+Auto-merging net/mac80211/mlme.c
+Auto-merging net/mac80211/iface.c
+Auto-merging net/mac80211/ieee80211_i.h
+Auto-merging drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+Auto-merging drivers/net/wireless/mwifiex/usb.c
+Auto-merging drivers/net/wireless/mwifiex/pcie.c
+Auto-merging drivers/net/wireless/mwifiex/main.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/tx.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/mvm.h
+Auto-merging drivers/net/wireless/iwlwifi/mvm/mac80211.c
+Auto-merging drivers/net/wireless/iwlwifi/iwl-modparams.h
+Auto-merging drivers/net/wireless/iwlwifi/iwl-drv.c
+Auto-merging drivers/net/wireless/iwlwifi/dvm/mac80211.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+Auto-merging drivers/net/wireless/ath/ath9k/xmit.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/80211.tmpl                   |    2 +
+ Documentation/devices.txt                          |    1 +
+ .../devicetree/bindings/net/wireless/ti,wl1251.txt |   39 +
+ arch/arm/mach-omap2/board-omap3pandora.c           |    6 +-
+ arch/arm/mach-omap2/board-rx51-peripherals.c       |   13 +-
+ drivers/bluetooth/ath3k.c                          |   84 +-
+ drivers/bluetooth/btusb.c                          |   58 +-
+ drivers/bluetooth/hci_vhci.c                       |    3 +-
+ drivers/net/wireless/Kconfig                       |    8 +-
+ drivers/net/wireless/airo.c                        |   17 +-
+ drivers/net/wireless/ath/ath.h                     |    3 +-
+ drivers/net/wireless/ath/ath10k/core.c             |   36 +-
+ drivers/net/wireless/ath/ath10k/core.h             |   47 +-
+ drivers/net/wireless/ath/ath10k/debug.h            |    2 +-
+ drivers/net/wireless/ath/ath10k/htt_rx.c           |   35 +-
+ drivers/net/wireless/ath/ath10k/htt_tx.c           |    4 +-
+ drivers/net/wireless/ath/ath10k/hw.h               |    6 +
+ drivers/net/wireless/ath/ath10k/mac.c              |  634 +++++++--
+ drivers/net/wireless/ath/ath10k/pci.c              |  147 +-
+ drivers/net/wireless/ath/ath10k/txrx.c             |    4 +-
+ drivers/net/wireless/ath/ath10k/wmi.c              |  118 +-
+ drivers/net/wireless/ath/ath10k/wmi.h              |   34 +-
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c      |    1 +
+ drivers/net/wireless/ath/ath6kl/usb.c              |    6 +-
+ drivers/net/wireless/ath/ath6kl/wmi.c              |    4 +-
+ drivers/net/wireless/ath/ath9k/Makefile            |    3 +-
+ drivers/net/wireless/ath/ath9k/ani.c               |   41 +-
+ drivers/net/wireless/ath/ath9k/ani.h               |    4 +
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c        |    4 -
+ drivers/net/wireless/ath/ath9k/ath9k.h             |    2 -
+ drivers/net/wireless/ath/ath9k/beacon.c            |   23 +-
+ drivers/net/wireless/ath/ath9k/common-init.c       |  244 ++++
+ drivers/net/wireless/ath/ath9k/common-init.h       |   20 +
+ drivers/net/wireless/ath/ath9k/common.h            |    2 +
+ drivers/net/wireless/ath/ath9k/debug.c             |   26 +-
+ drivers/net/wireless/ath/ath9k/htc.h               |    1 -
+ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c    |   22 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c      |  229 +--
+ drivers/net/wireless/ath/ath9k/init.c              |  231 +--
+ drivers/net/wireless/ath/ath9k/main.c              |    8 +-
+ drivers/net/wireless/ath/ath9k/xmit.c              |    5 +-
+ drivers/net/wireless/ath/regd.c                    |   10 +-
+ drivers/net/wireless/ath/wil6210/Makefile          |    1 +
+ drivers/net/wireless/ath/wil6210/cfg80211.c        |  202 ++-
+ drivers/net/wireless/ath/wil6210/debugfs.c         |  119 +-
+ drivers/net/wireless/ath/wil6210/main.c            |  119 +-
+ drivers/net/wireless/ath/wil6210/rx_reorder.c      |  177 +++
+ drivers/net/wireless/ath/wil6210/txrx.c            |  125 +-
+ drivers/net/wireless/ath/wil6210/txrx.h            |    7 +
+ drivers/net/wireless/ath/wil6210/wil6210.h         |   82 +-
+ drivers/net/wireless/ath/wil6210/wmi.c             |  116 +-
+ drivers/net/wireless/atmel.c                       |    8 +-
+ drivers/net/wireless/b43/Kconfig                   |    2 +-
+ drivers/net/wireless/b43/debugfs.h                 |    2 +-
+ drivers/net/wireless/b43/main.c                    |    2 +-
+ drivers/net/wireless/b43/phy_common.c              |    4 +-
+ drivers/net/wireless/b43/pio.c                     |   10 +-
+ drivers/net/wireless/b43/sysfs.c                   |    2 +-
+ drivers/net/wireless/b43/xmit.c                    |    2 +-
+ drivers/net/wireless/b43legacy/main.c              |    4 +-
+ drivers/net/wireless/b43legacy/sysfs.c             |    2 +-
+ drivers/net/wireless/b43legacy/xmit.c              |    2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |   55 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |    4 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  200 +--
+ .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    2 +
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   55 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |    1 -
+ drivers/net/wireless/cw1200/fwio.c                 |    4 +-
+ drivers/net/wireless/hostap/hostap_cs.c            |    2 +
+ drivers/net/wireless/ipw2x00/ipw2100.c             |    2 +-
+ drivers/net/wireless/ipw2x00/ipw2200.c             |    2 +-
+ drivers/net/wireless/iwlegacy/3945-mac.c           |   13 +-
+ drivers/net/wireless/iwlegacy/4965-mac.c           |   12 +-
+ drivers/net/wireless/iwlegacy/commands.h           |    3 +-
+ drivers/net/wireless/iwlegacy/common.c             |   83 +-
+ drivers/net/wireless/iwlegacy/common.h             |   15 +
+ drivers/net/wireless/iwlwifi/dvm/agn.h             |    4 +-
+ drivers/net/wireless/iwlwifi/dvm/devices.c         |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c        |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/rx.c              |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |   53 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.h             |   14 +
+ drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h    |    5 +-
+ drivers/net/wireless/iwlwifi/iwl-fw-file.h         |   17 +
+ drivers/net/wireless/iwlwifi/iwl-fw.h              |   24 +-
+ drivers/net/wireless/iwlwifi/iwl-modparams.h       |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.c       |  245 +++-
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.h       |    3 +-
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c     |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/debugfs.c         |  118 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h       |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api.h          |    5 +-
+ drivers/net/wireless/iwlwifi/mvm/fw.c              |   14 +-
+ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c        |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c        |   18 +-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h             |   35 +-
+ drivers/net/wireless/iwlwifi/mvm/nvm.c             |   67 +-
+ drivers/net/wireless/iwlwifi/mvm/ops.c             |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c        |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/power.c           |   48 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.c              |   93 +-
+ drivers/net/wireless/iwlwifi/mvm/rx.c              |   21 +
+ drivers/net/wireless/iwlwifi/mvm/scan.c            |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.c      |    6 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c              |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/utils.c           |    6 +-
+ drivers/net/wireless/iwlwifi/pcie/internal.h       |    2 +-
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |   47 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |   68 +-
+ drivers/net/wireless/libertas/if_sdio.c            |    4 +-
+ drivers/net/wireless/mac80211_hwsim.c              |   31 +-
+ drivers/net/wireless/mac80211_hwsim.h              |    4 +
+ drivers/net/wireless/mwifiex/11h.c                 |    4 +-
+ drivers/net/wireless/mwifiex/11n.c                 |    8 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.c       |   32 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.h       |    3 +-
+ drivers/net/wireless/mwifiex/README                |    2 +-
+ drivers/net/wireless/mwifiex/cfg80211.c            |  205 +--
+ drivers/net/wireless/mwifiex/cfp.c                 |    2 +-
+ drivers/net/wireless/mwifiex/cmdevt.c              |   95 +-
+ drivers/net/wireless/mwifiex/debugfs.c             |    8 +-
+ drivers/net/wireless/mwifiex/fw.h                  |   13 +
+ drivers/net/wireless/mwifiex/ie.c                  |    6 +-
+ drivers/net/wireless/mwifiex/init.c                |    3 +-
+ drivers/net/wireless/mwifiex/ioctl.h               |    2 +-
+ drivers/net/wireless/mwifiex/join.c                |   52 +-
+ drivers/net/wireless/mwifiex/main.c                |    7 +-
+ drivers/net/wireless/mwifiex/main.h                |   14 +-
+ drivers/net/wireless/mwifiex/pcie.c                |    9 +-
+ drivers/net/wireless/mwifiex/pcie.h                |    3 +
+ drivers/net/wireless/mwifiex/scan.c                |    4 +-
+ drivers/net/wireless/mwifiex/sdio.c                |    9 +-
+ drivers/net/wireless/mwifiex/sdio.h                |    6 +
+ drivers/net/wireless/mwifiex/sta_cmd.c             |   84 +-
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |    9 +-
+ drivers/net/wireless/mwifiex/sta_event.c           |   40 +-
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |  117 +-
+ drivers/net/wireless/mwifiex/tdls.c                |   18 +-
+ drivers/net/wireless/mwifiex/uap_cmd.c             |    4 +-
+ drivers/net/wireless/mwifiex/uap_event.c           |    6 +-
+ drivers/net/wireless/mwifiex/usb.c                 |   10 +-
+ drivers/net/wireless/mwifiex/util.c                |    4 +-
+ drivers/net/wireless/mwl8k.c                       |  197 ++-
+ drivers/net/wireless/orinoco/cfg.c                 |    5 +-
+ drivers/net/wireless/orinoco/hw.c                  |    2 +-
+ drivers/net/wireless/orinoco/scan.c                |    5 +-
+ drivers/net/wireless/orinoco/wext.c                |    2 +-
+ drivers/net/wireless/p54/p54usb.c                  |    2 +-
+ drivers/net/wireless/prism54/isl_ioctl.c           |    2 +-
+ drivers/net/wireless/rndis_wlan.c                  |    3 +-
+ drivers/net/wireless/rt2x00/rt2800usb.c            |    2 +-
+ drivers/net/wireless/rt2x00/rt2x00debug.c          |    2 +-
+ drivers/net/wireless/rtl818x/rtl8180/dev.c         |   30 +-
+ drivers/net/wireless/rtlwifi/core.c                |   52 +-
+ drivers/net/wireless/rtlwifi/rtl8188ee/hw.c        |    5 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/hw.c        |    4 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/hw.c        |    4 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/hw.c        |    6 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/hw.c        |    5 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/rf.c        |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/hw.c        |    5 +-
+ drivers/net/wireless/ti/wilink_platform_data.c     |   37 +-
+ drivers/net/wireless/ti/wl1251/rx.c                |    2 +-
+ drivers/net/wireless/ti/wl1251/sdio.c              |   31 +-
+ drivers/net/wireless/ti/wl1251/spi.c               |   71 +-
+ drivers/net/wireless/ti/wl1251/wl1251.h            |    4 +-
+ drivers/net/wireless/ti/wlcore/main.c              |    8 +-
+ drivers/net/wireless/ti/wlcore/spi.c               |    4 +-
+ drivers/net/wireless/ti/wlcore/sysfs.c             |    2 +-
+ drivers/net/wireless/wl3501_cs.c                   |    6 +-
+ drivers/net/wireless/zd1201.c                      |    9 +-
+ drivers/staging/rtl8821ae/rc.c                     |    1 +
+ include/linux/ieee80211.h                          |   36 -
+ include/linux/miscdevice.h                         |    1 +
+ include/linux/tty.h                                |    6 +-
+ include/linux/wl12xx.h                             |   24 +-
+ include/net/bluetooth/bluetooth.h                  |    1 +
+ include/net/bluetooth/hci.h                        |   76 +-
+ include/net/bluetooth/hci_core.h                   |  197 ++-
+ include/net/bluetooth/l2cap.h                      |    8 +-
+ include/net/bluetooth/mgmt.h                       |   51 +-
+ include/net/bluetooth/rfcomm.h                     |   10 +-
+ include/net/cfg80211.h                             |   24 +-
+ include/net/mac80211.h                             |   43 +-
+ include/uapi/linux/nl80211.h                       |   42 +-
+ net/bluetooth/a2mp.c                               |    8 +-
+ net/bluetooth/af_bluetooth.c                       |    2 +-
+ net/bluetooth/hci_conn.c                           |  206 ++-
+ net/bluetooth/hci_core.c                           | 1469 ++++++++++++++++----
+ net/bluetooth/hci_event.c                          |  478 ++++++-
+ net/bluetooth/hci_sock.c                           |    1 +
+ net/bluetooth/hci_sysfs.c                          |   18 +-
+ net/bluetooth/l2cap_core.c                         |  616 ++++----
+ net/bluetooth/l2cap_sock.c                         |   62 +-
+ net/bluetooth/mgmt.c                               |  913 ++++++++++--
+ net/bluetooth/rfcomm/core.c                        |   92 +-
+ net/bluetooth/rfcomm/sock.c                        |   33 +-
+ net/bluetooth/rfcomm/tty.c                         |  262 ++--
+ net/bluetooth/smp.c                                |  418 +++++-
+ net/bluetooth/smp.h                                |   22 +-
+ net/mac80211/cfg.c                                 |    7 +-
+ net/mac80211/debugfs_netdev.c                      |   13 +
+ net/mac80211/driver-ops.h                          |   12 +-
+ net/mac80211/ht.c                                  |    2 -
+ net/mac80211/ibss.c                                |    5 +
+ net/mac80211/ieee80211_i.h                         |    2 +
+ net/mac80211/iface.c                               |   11 +-
+ net/mac80211/main.c                                |   12 +
+ net/mac80211/mlme.c                                |   72 +-
+ net/mac80211/rx.c                                  |    5 +-
+ net/mac80211/scan.c                                |    9 +-
+ net/wireless/chan.c                                |    6 +-
+ net/wireless/genregdb.awk                          |    2 +
+ net/wireless/ibss.c                                |    7 +-
+ net/wireless/mesh.c                                |    6 +
+ net/wireless/nl80211.c                             |   33 +-
+ net/wireless/rdev-ops.h                            |    9 +-
+ net/wireless/reg.c                                 |   83 +-
+ net/wireless/trace.h                               |   12 +-
+ net/wireless/util.c                                |   31 +-
+ 222 files changed, 8279 insertions(+), 3079 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt
+ create mode 100644 drivers/net/wireless/ath/ath9k/common-init.c
+ create mode 100644 drivers/net/wireless/ath/ath9k/common-init.h
+ create mode 100644 drivers/net/wireless/ath/wil6210/rx_reorder.c
+$ git reset --hard HEAD^
+HEAD is now at 951751adc4dc Merge remote-tracking branch 'net-next/master'
+Merging next-20140224 version of wireless-next
+$ git merge -m next-20140224/wireless-next 35582ad9d342025653aaf28ed321bf5352488d7f
+Already up-to-date.
+Merging bluetooth/master (81ad6fd9698f Bluetooth: Remove unnecessary stop_scan_complete function)
+$ git merge bluetooth/master
+Merge made by the 'recursive' strategy.
+ Documentation/devices.txt         |    1 +
+ drivers/bluetooth/ath3k.c         |   84 ++-
+ drivers/bluetooth/btusb.c         |   58 +-
+ drivers/bluetooth/hci_vhci.c      |    3 +-
+ include/linux/miscdevice.h        |    1 +
+ include/linux/tty.h               |    6 +-
+ include/net/bluetooth/bluetooth.h |    1 +
+ include/net/bluetooth/hci.h       |   76 +-
+ include/net/bluetooth/hci_core.h  |  197 ++++-
+ include/net/bluetooth/l2cap.h     |    8 +-
+ include/net/bluetooth/mgmt.h      |   51 +-
+ include/net/bluetooth/rfcomm.h    |   10 +-
+ net/bluetooth/a2mp.c              |    8 +-
+ net/bluetooth/af_bluetooth.c      |    2 +-
+ net/bluetooth/hci_conn.c          |  206 ++++--
+ net/bluetooth/hci_core.c          | 1469 +++++++++++++++++++++++++++++++------
+ net/bluetooth/hci_event.c         |  478 ++++++++++--
+ net/bluetooth/hci_sock.c          |    1 +
+ net/bluetooth/hci_sysfs.c         |   18 +-
+ net/bluetooth/l2cap_core.c        |  616 +++++++++-------
+ net/bluetooth/l2cap_sock.c        |   62 +-
+ net/bluetooth/mgmt.c              |  913 +++++++++++++++++++----
+ net/bluetooth/rfcomm/core.c       |   92 ++-
+ net/bluetooth/rfcomm/sock.c       |   33 +-
+ net/bluetooth/rfcomm/tty.c        |  262 ++++---
+ net/bluetooth/smp.c               |  418 +++++++++--
+ net/bluetooth/smp.h               |   22 +-
+ 27 files changed, 3944 insertions(+), 1152 deletions(-)
+Merging infiniband/for-next (7f3c1e1ba82e Merge branches 'cma', 'cxgb4', 'iser', 'misc', 'mlx4', 'mlx5', 'nes', 'ocrdma', 'qib' and 'usnic' into for-next)
+$ git merge infiniband/for-next
+Merge made by the 'recursive' strategy.
+Merging mtd/master (bb38eefb6858 mtd: nand: omap: fix ecclayout->oobfree->length)
+$ git merge mtd/master
+Already up-to-date.
+Merging l2-mtd/master (b9d3ea0eccce jffs2: Fix crash due to truncation of csize)
+$ git merge l2-mtd/master
+Auto-merging drivers/mtd/ubi/ubi.h
+Auto-merging drivers/mtd/nand/nand_base.c
+Auto-merging drivers/mtd/nand/mpc5121_nfc.c
+Auto-merging drivers/mtd/nand/davinci_nand.c
+Merge made by the 'recursive' strategy.
+ drivers/mtd/chips/cfi_cmdset_0001.c            |   9 +-
+ drivers/mtd/chips/cfi_cmdset_0002.c            |   9 +-
+ drivers/mtd/chips/cfi_cmdset_0020.c            |   3 -
+ drivers/mtd/chips/cfi_probe.c                  |   4 +-
+ drivers/mtd/chips/cfi_util.c                   |   4 +-
+ drivers/mtd/chips/gen_probe.c                  |   2 -
+ drivers/mtd/devices/block2mtd.c                |  13 ++-
+ drivers/mtd/devices/elm.c                      |   6 +-
+ drivers/mtd/devices/m25p80.c                   |  34 ++++--
+ drivers/mtd/devices/mtd_dataflash.c            |   1 -
+ drivers/mtd/devices/phram.c                    |  41 ++++++--
+ drivers/mtd/devices/pmc551.c                   |   7 +-
+ drivers/mtd/devices/spear_smi.c                |   2 -
+ drivers/mtd/devices/sst25l.c                   |   1 -
+ drivers/mtd/inftlmount.c                       |   1 -
+ drivers/mtd/lpddr/lpddr_cmds.c                 |   4 +-
+ drivers/mtd/lpddr/qinfo_probe.c                |   5 +-
+ drivers/mtd/maps/Kconfig                       |   2 +-
+ drivers/mtd/maps/bfin-async-flash.c            |   1 -
+ drivers/mtd/maps/gpio-addr-flash.c             |   1 -
+ drivers/mtd/maps/intel_vr_nor.c                |   1 -
+ drivers/mtd/maps/ixp4xx.c                      |   1 -
+ drivers/mtd/maps/lantiq-flash.c                |   1 -
+ drivers/mtd/maps/latch-addr-flash.c            |   1 -
+ drivers/mtd/maps/pci.c                         |   1 -
+ drivers/mtd/maps/physmap_of.c                  |   1 -
+ drivers/mtd/maps/plat-ram.c                    |   2 -
+ drivers/mtd/maps/pxa2xx-flash.c                |   1 -
+ drivers/mtd/maps/rbtx4939-flash.c              |   1 -
+ drivers/mtd/maps/scb2_flash.c                  |   1 -
+ drivers/mtd/maps/sun_uflash.c                  |   1 -
+ drivers/mtd/mtd_blkdevs.c                      |   1 -
+ drivers/mtd/nand/Kconfig                       |   2 +
+ drivers/mtd/nand/ams-delta.c                   |   1 -
+ drivers/mtd/nand/atmel_nand.c                  |  13 +--
+ drivers/mtd/nand/au1550nd.c                    |   4 +-
+ drivers/mtd/nand/bf5xx_nand.c                  |   1 -
+ drivers/mtd/nand/cafe_nand.c                   |  68 ++++++++----
+ drivers/mtd/nand/davinci_nand.c                |   1 -
+ drivers/mtd/nand/diskonchip.c                  |   3 +-
+ drivers/mtd/nand/fsl_elbc_nand.c               |   1 -
+ drivers/mtd/nand/fsl_ifc_nand.c                |   1 -
+ drivers/mtd/nand/gpio.c                        |   1 -
+ drivers/mtd/nand/mpc5121_nfc.c                 |   1 -
+ drivers/mtd/nand/mxc_nand.c                    |   2 +
+ drivers/mtd/nand/nand_base.c                   | 139 +++++++++++++++++++++----
+ drivers/mtd/nand/nand_ids.c                    |   3 +
+ drivers/mtd/nand/nuc900_nand.c                 |   6 +-
+ drivers/mtd/nand/pasemi_nand.c                 |   1 -
+ drivers/mtd/nand/s3c2410.c                     |   1 -
+ drivers/mtd/onenand/generic.c                  |   1 -
+ drivers/mtd/onenand/omap2.c                    |   1 -
+ drivers/mtd/onenand/onenand_base.c             |   8 +-
+ drivers/mtd/onenand/samsung.c                  |   4 +-
+ drivers/mtd/rfd_ftl.c                          |   9 +-
+ drivers/mtd/sm_ftl.c                           |  11 +-
+ drivers/mtd/tests/mtd_test.c                   |   1 -
+ drivers/mtd/ubi/ubi.h                          |   1 -
+ fs/jffs2/compr_rtime.c                         |   4 +-
+ fs/jffs2/fs.c                                  |   9 +-
+ fs/jffs2/nodelist.h                            |   2 +-
+ fs/jffs2/nodemgmt.c                            |  14 ++-
+ include/linux/mtd/nand.h                       | 124 +++++++++++++++++++---
+ include/linux/platform_data/mtd-nand-s3c2410.h |   8 +-
+ 64 files changed, 407 insertions(+), 202 deletions(-)
+Merging crypto/master (c65a52f8360d crypto: ccp - Account for CCP backlog processing)
+$ git merge crypto/master
+Removing drivers/crypto/tegra-aes.h
+Removing drivers/crypto/tegra-aes.c
+Auto-merging crypto/crc32c_generic.c
+Merge made by the 'recursive' strategy.
+ arch/x86/crypto/blowfish_glue.c        |    3 -
+ arch/x86/crypto/cast5_avx_glue.c       |    3 -
+ crypto/Makefile                        |    2 +-
+ crypto/{crc32c.c => crc32c_generic.c}  |    2 +
+ drivers/char/hw_random/atmel-rng.c     |   15 +-
+ drivers/char/hw_random/core.c          |   10 +-
+ drivers/char/hw_random/picoxcell-rng.c |   19 +-
+ drivers/crypto/Kconfig                 |   22 +-
+ drivers/crypto/Makefile                |    2 +-
+ drivers/crypto/caam/ctrl.c             |   61 +-
+ drivers/crypto/caam/ctrl.h             |    2 +-
+ drivers/crypto/caam/regs.h             |    4 +-
+ drivers/crypto/ccp/ccp-crypto-main.c   |  224 +++---
+ drivers/crypto/ccp/ccp-crypto-sha.c    |  130 +---
+ drivers/crypto/ccp/ccp-crypto.h        |    8 +-
+ drivers/crypto/ccp/ccp-dev.c           |   21 +-
+ drivers/crypto/ccp/ccp-ops.c           |  108 ++-
+ drivers/crypto/mxs-dcp.c               |   49 +-
+ drivers/crypto/omap-des.c              | 1218 ++++++++++++++++++++++++++++++++
+ drivers/crypto/picoxcell_crypto.c      |   16 +-
+ drivers/crypto/s5p-sss.c               |   13 +-
+ drivers/crypto/sahara.c                |   19 +-
+ drivers/crypto/talitos.c               |    4 +-
+ drivers/crypto/tegra-aes.c             | 1087 ----------------------------
+ drivers/crypto/tegra-aes.h             |  103 ---
+ include/linux/ccp.h                    |    7 +
+ 26 files changed, 1553 insertions(+), 1599 deletions(-)
+ rename crypto/{crc32c.c => crc32c_generic.c} (98%)
+ create mode 100644 drivers/crypto/omap-des.c
+ delete mode 100644 drivers/crypto/tegra-aes.c
+ delete mode 100644 drivers/crypto/tegra-aes.h
+Merging drm/drm-next (4d538b791979 Merge branch 'drm-next-3.15' of git://people.freedesktop.org/~deathsimple/linux into drm-next)
+$ git merge drm/drm-next
+Auto-merging drivers/gpu/drm/radeon/radeon_kms.c
+Auto-merging drivers/gpu/drm/radeon/radeon.h
+Auto-merging drivers/gpu/drm/radeon/evergreen.c
+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_display.c
+Auto-merging drivers/gpu/drm/i915/i915_drv.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/drm/i2c/tda998x.txt        |  27 +
+ drivers/gpu/drm/drm_dp_helper.c                    | 395 ++++++++++++
+ drivers/gpu/drm/i2c/tda998x_drv.c                  | 602 +++++++++++-------
+ drivers/gpu/drm/i915/Makefile                      |   1 +
+ drivers/gpu/drm/i915/i915_debugfs.c                | 301 ++++++++-
+ drivers/gpu/drm/i915/i915_dma.c                    |   6 +-
+ drivers/gpu/drm/i915/i915_drv.c                    | 182 ++----
+ drivers/gpu/drm/i915/i915_drv.h                    | 415 ++++++++----
+ drivers/gpu/drm/i915/i915_gem.c                    | 412 +++++-------
+ drivers/gpu/drm/i915/i915_gem_context.c            | 435 +++++++++----
+ drivers/gpu/drm/i915/i915_gem_evict.c              |  49 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c         | 164 ++---
+ drivers/gpu/drm/i915/i915_gem_gtt.c                | 675 +++++++++++++++-----
+ drivers/gpu/drm/i915/i915_gem_tiling.c             |   2 +-
+ drivers/gpu/drm/i915/i915_gpu_error.c              | 442 +++++++++----
+ drivers/gpu/drm/i915/i915_irq.c                    | 259 ++++----
+ drivers/gpu/drm/i915/i915_params.c                 | 155 +++++
+ drivers/gpu/drm/i915/i915_reg.h                    | 336 +++++-----
+ drivers/gpu/drm/i915/i915_suspend.c                |  40 +-
+ drivers/gpu/drm/i915/i915_sysfs.c                  |  10 +
+ drivers/gpu/drm/i915/i915_ums.c                    |   8 +
+ drivers/gpu/drm/i915/intel_bios.c                  |   4 +-
+ drivers/gpu/drm/i915/intel_crt.c                   |   2 +
+ drivers/gpu/drm/i915/intel_ddi.c                   | 101 ++-
+ drivers/gpu/drm/i915/intel_display.c               | 216 +++++--
+ drivers/gpu/drm/i915/intel_dp.c                    | 365 +++++++----
+ drivers/gpu/drm/i915/intel_drv.h                   |  28 +-
+ drivers/gpu/drm/i915/intel_fbdev.c                 |   4 +-
+ drivers/gpu/drm/i915/intel_hdmi.c                  |   6 +-
+ drivers/gpu/drm/i915/intel_lvds.c                  |   6 +-
+ drivers/gpu/drm/i915/intel_overlay.c               |   8 +-
+ drivers/gpu/drm/i915/intel_panel.c                 |  17 +-
+ drivers/gpu/drm/i915/intel_pm.c                    | 294 +++++----
+ drivers/gpu/drm/i915/intel_ringbuffer.c            |  37 +-
+ drivers/gpu/drm/i915/intel_ringbuffer.h            |   2 +
+ drivers/gpu/drm/i915/intel_sprite.c                |  18 +-
+ drivers/gpu/drm/i915/intel_uncore.c                |   8 +-
+ drivers/gpu/drm/radeon/Makefile                    |   6 +
+ drivers/gpu/drm/radeon/btc_dpm.c                   |   4 +
+ drivers/gpu/drm/radeon/ci_dpm.c                    |  67 +-
+ drivers/gpu/drm/radeon/cik.c                       | 109 +++-
+ drivers/gpu/drm/radeon/cik_sdma.c                  |   6 +-
+ drivers/gpu/drm/radeon/cikd.h                      |  49 ++
+ drivers/gpu/drm/radeon/cypress_dpm.c               |   4 +
+ drivers/gpu/drm/radeon/evergreen.c                 |   6 +-
+ drivers/gpu/drm/radeon/evergreen_dma.c             |   4 +-
+ drivers/gpu/drm/radeon/kv_dpm.c                    |  64 +-
+ drivers/gpu/drm/radeon/ni.c                        |   8 +-
+ drivers/gpu/drm/radeon/ni_dma.c                    |   6 +-
+ drivers/gpu/drm/radeon/ni_dpm.c                    |   7 +-
+ drivers/gpu/drm/radeon/r100.c                      |   5 +-
+ drivers/gpu/drm/radeon/r600.c                      |   6 +-
+ drivers/gpu/drm/radeon/r600_dma.c                  |   6 +-
+ drivers/gpu/drm/radeon/r600_dpm.c                  |  48 +-
+ drivers/gpu/drm/radeon/r600_dpm.h                  |   2 +
+ drivers/gpu/drm/radeon/radeon.h                    |  99 ++-
+ drivers/gpu/drm/radeon/radeon_asic.c               |  19 +
+ drivers/gpu/drm/radeon/radeon_asic.h               |  14 +
+ drivers/gpu/drm/radeon/radeon_cs.c                 |   7 +
+ drivers/gpu/drm/radeon/radeon_kms.c                |  10 +
+ drivers/gpu/drm/radeon/radeon_pm.c                 |  25 +
+ drivers/gpu/drm/radeon/radeon_ring.c               |  74 +--
+ drivers/gpu/drm/radeon/radeon_test.c               |  39 +-
+ drivers/gpu/drm/radeon/radeon_vce.c                | 694 +++++++++++++++++++++
+ drivers/gpu/drm/radeon/rs780_dpm.c                 |   7 +-
+ drivers/gpu/drm/radeon/rv6xx_dpm.c                 |   7 +-
+ drivers/gpu/drm/radeon/rv770_dpm.c                 |   7 +-
+ drivers/gpu/drm/radeon/si.c                        |  10 +-
+ drivers/gpu/drm/radeon/si_dma.c                    |   4 +-
+ drivers/gpu/drm/radeon/si_dpm.c                    |   7 +-
+ drivers/gpu/drm/radeon/sid.h                       |  47 ++
+ drivers/gpu/drm/radeon/sumo_dpm.c                  |   7 +-
+ drivers/gpu/drm/radeon/trinity_dpm.c               |   7 +-
+ drivers/gpu/drm/radeon/uvd_v1_0.c                  |   2 +-
+ drivers/gpu/drm/radeon/vce_v1_0.c                  | 187 ++++++
+ drivers/gpu/drm/radeon/vce_v2_0.c                  | 181 ++++++
+ include/drm/drm_dp_helper.h                        | 121 ++++
+ include/uapi/drm/radeon_drm.h                      |   5 +
+ 78 files changed, 5949 insertions(+), 2070 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/drm/i2c/tda998x.txt
+ create mode 100644 drivers/gpu/drm/i915/i915_params.c
+ create mode 100644 drivers/gpu/drm/radeon/radeon_vce.c
+ create mode 100644 drivers/gpu/drm/radeon/vce_v1_0.c
+ create mode 100644 drivers/gpu/drm/radeon/vce_v2_0.c
+Merging drm-intel/for-linux-next (b5ea642a76ee drm/i915: sprinkle static)
+$ git merge drm-intel/for-linux-next
+Auto-merging include/drm/drm_crtc.h
+Auto-merging drivers/gpu/drm/i915/intel_ringbuffer.c
+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_dp.c
+Auto-merging drivers/gpu/drm/i915/intel_display.c
+Auto-merging drivers/gpu/drm/i915/i915_irq.c
+Auto-merging drivers/gpu/drm/i915/i915_gem_gtt.c
+Auto-merging drivers/gpu/drm/i915/i915_drv.h
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/drm_crtc.c                 |  23 +++
+ drivers/gpu/drm/drm_fb_helper.c            |   6 +-
+ drivers/gpu/drm/i915/i915_debugfs.c        | 162 +++++++++++++++++
+ drivers/gpu/drm/i915/i915_dma.c            |  81 +++++++--
+ drivers/gpu/drm/i915/i915_drv.h            |  58 +++---
+ drivers/gpu/drm/i915/i915_gem.c            | 155 ++++++++--------
+ drivers/gpu/drm/i915/i915_gem_context.c    |   9 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c      |  10 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +-
+ drivers/gpu/drm/i915/i915_gem_gtt.c        |  61 ++++---
+ drivers/gpu/drm/i915/i915_irq.c            | 172 ++++++++++++++----
+ drivers/gpu/drm/i915/i915_params.c         |   4 +
+ drivers/gpu/drm/i915/i915_reg.h            | 181 ++++++++++---------
+ drivers/gpu/drm/i915/i915_trace.h          |  20 +--
+ drivers/gpu/drm/i915/intel_crt.c           |   1 +
+ drivers/gpu/drm/i915/intel_ddi.c           |   2 +-
+ drivers/gpu/drm/i915/intel_display.c       | 275 +++++++++++++++--------------
+ drivers/gpu/drm/i915/intel_dp.c            |  25 ++-
+ drivers/gpu/drm/i915/intel_drv.h           |  20 ++-
+ drivers/gpu/drm/i915/intel_dsi.c           |   3 +-
+ drivers/gpu/drm/i915/intel_dvo.c           |   1 +
+ drivers/gpu/drm/i915/intel_fbdev.c         | 171 ++++++++++++++++--
+ drivers/gpu/drm/i915/intel_hdmi.c          |  32 +---
+ drivers/gpu/drm/i915/intel_lvds.c          |  13 +-
+ drivers/gpu/drm/i915/intel_overlay.c       |   4 +-
+ drivers/gpu/drm/i915/intel_panel.c         |   4 +-
+ drivers/gpu/drm/i915/intel_pm.c            |  51 +++---
+ drivers/gpu/drm/i915/intel_ringbuffer.c    |  22 ++-
+ drivers/gpu/drm/i915/intel_sdvo.c          |  70 +++++++-
+ drivers/gpu/drm/i915/intel_tv.c            |   9 +-
+ include/drm/drm_crtc.h                     |   1 +
+ include/drm/drm_fb_helper.h                |   6 +
+ 32 files changed, 1136 insertions(+), 534 deletions(-)
+Merging drm-tegra/drm/for-next (c1a68b4c29b8 drm/tegra: Add eDP support)
+$ git merge drm-tegra/drm/for-next
+Auto-merging drivers/gpu/drm/tegra/drm.c
+Merge made by the 'recursive' strategy.
+ .../bindings/gpu/nvidia,tegra20-host1x.txt         |   42 +
+ .../devicetree/bindings/panel/lg,lp129qe.txt       |    7 +
+ drivers/gpu/drm/panel/panel-simple.c               |   25 +
+ drivers/gpu/drm/tegra/Makefile                     |    2 +
+ drivers/gpu/drm/tegra/dc.h                         |    1 +
+ drivers/gpu/drm/tegra/dpaux.c                      |  544 ++++++++++
+ drivers/gpu/drm/tegra/dpaux.h                      |   73 ++
+ drivers/gpu/drm/tegra/drm.c                        |   19 +-
+ drivers/gpu/drm/tegra/drm.h                        |   20 +
+ drivers/gpu/drm/tegra/gem.c                        |   14 +
+ drivers/gpu/drm/tegra/output.c                     |    8 +
+ drivers/gpu/drm/tegra/sor.c                        | 1092 ++++++++++++++++++++
+ drivers/gpu/drm/tegra/sor.h                        |  278 +++++
+ drivers/gpu/host1x/syncpt.c                        |    1 +
+ include/linux/host1x.h                             |    1 +
+ 15 files changed, 2125 insertions(+), 2 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/panel/lg,lp129qe.txt
+ create mode 100644 drivers/gpu/drm/tegra/dpaux.c
+ create mode 100644 drivers/gpu/drm/tegra/dpaux.h
+ create mode 100644 drivers/gpu/drm/tegra/sor.c
+ create mode 100644 drivers/gpu/drm/tegra/sor.h
+Merging sound/for-next (31278997add6 ALSA: hda/realtek - Add headset quirk for Dell DT)
+$ git merge sound/for-next
+Auto-merging sound/pci/hda/patch_realtek.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/writing-an-alsa-driver.tmpl |   72 +-
+ drivers/hid/hid-prodikeys.c                       |    5 +-
+ drivers/media/pci/cx18/cx18-alsa-main.c           |    9 +-
+ drivers/media/pci/cx23885/cx23885-alsa.c          |    5 +-
+ drivers/media/pci/cx25821/cx25821-alsa.c          |    7 +-
+ drivers/media/pci/cx88/cx88-alsa.c                |    6 +-
+ drivers/media/pci/ivtv/ivtv-alsa-main.c           |    9 +-
+ drivers/media/pci/saa7134/saa7134-alsa.c          |    6 +-
+ drivers/media/usb/cx231xx/cx231xx-audio.c         |    5 +-
+ drivers/media/usb/em28xx/em28xx-audio.c           |    5 +-
+ drivers/media/usb/stk1160/stk1160-ac97.c          |    6 +-
+ drivers/media/usb/tlg2300/pd-alsa.c               |    3 +-
+ drivers/media/usb/tm6000/tm6000-alsa.c            |    4 +-
+ drivers/platform/x86/thinkpad_acpi.c              |    6 +-
+ drivers/staging/line6/audio.c                     |    5 +-
+ drivers/staging/line6/midi.c                      |    2 -
+ drivers/staging/line6/pcm.c                       |    2 -
+ drivers/staging/media/go7007/snd-go7007.c         |    5 +-
+ drivers/staging/media/solo6x10/solo6x10-g723.c    |    6 +-
+ drivers/usb/gadget/f_midi.c                       |    7 +-
+ drivers/usb/gadget/f_uac2.c                       |    4 +-
+ include/sound/core.h                              |  113 +-
+ include/sound/hwdep.h                             |    3 +-
+ include/sound/pcm.h                               |    8 +
+ include/sound/rawmidi.h                           |    2 -
+ sound/aoa/aoa.h                                   |    2 +-
+ sound/aoa/codecs/onyx.c                           |    2 +-
+ sound/aoa/codecs/tas.c                            |    2 +-
+ sound/aoa/codecs/toonie.c                         |    2 +-
+ sound/aoa/core/alsa.c                             |    7 +-
+ sound/arm/aaci.c                                  |    6 +-
+ sound/arm/pxa2xx-ac97.c                           |    6 +-
+ sound/atmel/abdac.c                               |   13 +-
+ sound/atmel/ac97c.c                               |   10 +-
+ sound/core/control.c                              |   17 +-
+ sound/core/control_compat.c                       |    2 +-
+ sound/core/device.c                               |  175 +-
+ sound/core/hrtimer.c                              |    3 +-
+ sound/core/hwdep.c                                |   53 +-
+ sound/core/info.c                                 |   15 +-
+ sound/core/init.c                                 |  186 +-
+ sound/core/isadma.c                               |    2 +-
+ sound/core/memalloc.c                             |    4 +-
+ sound/core/oss/mixer_oss.c                        |   20 +-
+ sound/core/oss/pcm_oss.c                          |  103 +-
+ sound/core/pcm.c                                  |   52 +-
+ sound/core/pcm_lib.c                              |   27 +-
+ sound/core/pcm_native.c                           |   51 +-
+ sound/core/pcm_timer.c                            |    4 +-
+ sound/core/rawmidi.c                              |   90 +-
+ sound/core/rtctimer.c                             |    7 +-
+ sound/core/seq/oss/seq_oss.c                      |   22 +-
+ sound/core/seq/oss/seq_oss_device.h               |   13 -
+ sound/core/seq/oss/seq_oss_init.c                 |   29 +-
+ sound/core/seq/oss/seq_oss_ioctl.c                |   18 -
+ sound/core/seq/oss/seq_oss_midi.c                 |    7 +-
+ sound/core/seq/oss/seq_oss_readq.c                |    4 +-
+ sound/core/seq/oss/seq_oss_synth.c                |   11 +-
+ sound/core/seq/oss/seq_oss_timer.c                |    7 -
+ sound/core/seq/seq_clientmgr.c                    |   16 +-
+ sound/core/seq/seq_device.c                       |   18 +-
+ sound/core/seq/seq_dummy.c                        |    2 +-
+ sound/core/seq/seq_fifo.c                         |    2 +-
+ sound/core/seq/seq_lock.c                         |    4 +-
+ sound/core/seq/seq_memory.c                       |    8 +-
+ sound/core/seq/seq_midi.c                         |    8 +-
+ sound/core/seq/seq_midi_emul.c                    |    6 +-
+ sound/core/seq/seq_ports.c                        |    4 +-
+ sound/core/seq/seq_prioq.c                        |   14 +-
+ sound/core/seq/seq_queue.c                        |    2 +-
+ sound/core/seq/seq_timer.c                        |   10 +-
+ sound/core/seq/seq_virmidi.c                      |    2 +-
+ sound/core/sound.c                                |   29 +-
+ sound/core/sound_oss.c                            |    7 +-
+ sound/core/timer.c                                |   17 +-
+ sound/core/vmaster.c                              |    2 +-
+ sound/drivers/aloop.c                             |    4 +-
+ sound/drivers/dummy.c                             |    6 +-
+ sound/drivers/ml403-ac97cr.c                      |    5 +-
+ sound/drivers/mpu401/mpu401.c                     |   12 +-
+ sound/drivers/mtpav.c                             |    4 +-
+ sound/drivers/mts64.c                             |    5 +-
+ sound/drivers/opl3/opl3_lib.c                     |    4 +-
+ sound/drivers/opl3/opl3_synth.c                   |    2 +-
+ sound/drivers/pcsp/pcsp.c                         |    4 +-
+ sound/drivers/pcsp/pcsp_input.c                   |    1 +
+ sound/drivers/portman2x4.c                        |    5 +-
+ sound/drivers/serial-u16550.c                     |    5 +-
+ sound/drivers/virmidi.c                           |    6 +-
+ sound/firewire/dice.c                             |    4 +-
+ sound/firewire/isight.c                           |    4 +-
+ sound/firewire/scs1x.c                            |    4 +-
+ sound/firewire/speakers.c                         |    4 +-
+ sound/i2c/other/ak4113.c                          |    2 +-
+ sound/i2c/other/ak4114.c                          |    2 +-
+ sound/i2c/other/ak4117.c                          |    2 +-
+ sound/isa/ad1816a/ad1816a.c                       |    6 +-
+ sound/isa/ad1848/ad1848.c                         |    4 +-
+ sound/isa/adlib.c                                 |    4 +-
+ sound/isa/als100.c                                |    6 +-
+ sound/isa/azt2320.c                               |    6 +-
+ sound/isa/cmi8328.c                               |    5 +-
+ sound/isa/cmi8330.c                               |   13 +-
+ sound/isa/cs423x/cs4231.c                         |    4 +-
+ sound/isa/cs423x/cs4236.c                         |   16 +-
+ sound/isa/es1688/es1688.c                         |   12 +-
+ sound/isa/es18xx.c                                |   16 +-
+ sound/isa/galaxy/galaxy.c                         |    6 +-
+ sound/isa/gus/gusclassic.c                        |    4 +-
+ sound/isa/gus/gusextreme.c                        |    6 +-
+ sound/isa/gus/gusmax.c                            |    6 +-
+ sound/isa/gus/interwave.c                         |   13 +-
+ sound/isa/msnd/msnd_pinnacle.c                    |   11 +-
+ sound/isa/opl3sa2.c                               |   16 +-
+ sound/isa/opti9xx/miro.c                          |   11 +-
+ sound/isa/opti9xx/opti92x-ad1848.c                |   12 +-
+ sound/isa/sb/jazz16.c                             |    6 +-
+ sound/isa/sb/sb16.c                               |   13 +-
+ sound/isa/sb/sb8.c                                |    6 +-
+ sound/isa/sc6000.c                                |    6 +-
+ sound/isa/sscape.c                                |   11 +-
+ sound/isa/wavefront/wavefront.c                   |   13 +-
+ sound/mips/au1x00.c                               |  241 +-
+ sound/mips/hal2.c                                 |    3 +-
+ sound/mips/sgio2audio.c                           |    3 +-
+ sound/oss/pas2.h                                  |    3 +
+ sound/oss/pas2_card.c                             |    2 -
+ sound/parisc/harmony.c                            |    4 +-
+ sound/pci/Kconfig                                 |    4 +-
+ sound/pci/ac97/ac97_codec.c                       |   45 +-
+ sound/pci/ac97/ac97_patch.c                       |    3 +-
+ sound/pci/ac97/ac97_pcm.c                         |   15 +-
+ sound/pci/ad1889.c                                |   37 +-
+ sound/pci/ali5451/ali5451.c                       |  152 +-
+ sound/pci/als300.c                                |   57 +-
+ sound/pci/als4000.c                               |   22 +-
+ sound/pci/asihpi/asihpi.c                         |   16 +-
+ sound/pci/atiixp.c                                |   33 +-
+ sound/pci/atiixp_modem.c                          |   28 +-
+ sound/pci/au88x0/au88x0.c                         |    5 +-
+ sound/pci/aw2/aw2-alsa.c                          |   46 +-
+ sound/pci/aw2/aw2-saa7146.c                       |    6 +-
+ sound/pci/azt3328.c                               |  351 +--
+ sound/pci/bt87x.c                                 |   41 +-
+ sound/pci/ca0106/ca0106_main.c                    |   89 +-
+ sound/pci/ca0106/ca_midi.c                        |    4 +-
+ sound/pci/cmipci.c                                |   41 +-
+ sound/pci/cs4281.c                                |   49 +-
+ sound/pci/cs46xx/cs46xx.c                         |    3 +-
+ sound/pci/cs46xx/cs46xx_lib.c                     |  145 +-
+ sound/pci/cs46xx/dsp_spos.c                       |  126 +-
+ sound/pci/cs46xx/dsp_spos_scb_lib.c               |   57 +-
+ sound/pci/cs5530.c                                |   27 +-
+ sound/pci/cs5535audio/cs5535audio.c               |   31 +-
+ sound/pci/cs5535audio/cs5535audio_olpc.c          |    7 +-
+ sound/pci/cs5535audio/cs5535audio_pcm.c           |    6 +-
+ sound/pci/cs5535audio/cs5535audio_pm.c            |    7 +-
+ sound/pci/ctxfi/ctatc.c                           |    2 -
+ sound/pci/ctxfi/xfi.c                             |    3 +-
+ sound/pci/echoaudio/echoaudio.c                   |   26 +-
+ sound/pci/echoaudio/echoaudio_dsp.c               |    9 +-
+ sound/pci/echoaudio/midi.c                        |    3 +-
+ sound/pci/emu10k1/emu10k1.c                       |    9 +-
+ sound/pci/emu10k1/emu10k1_callback.c              |    4 +-
+ sound/pci/emu10k1/emu10k1_main.c                  |   74 +-
+ sound/pci/emu10k1/emu10k1_patch.c                 |    6 +-
+ sound/pci/emu10k1/emu10k1x.c                      |   32 +-
+ sound/pci/emu10k1/emufx.c                         |   12 +-
+ sound/pci/emu10k1/emumixer.c                      |    6 +-
+ sound/pci/emu10k1/emumpu401.c                     |    7 +-
+ sound/pci/emu10k1/emupcm.c                        |   22 +-
+ sound/pci/emu10k1/io.c                            |   10 +-
+ sound/pci/emu10k1/irq.c                           |   21 +-
+ sound/pci/emu10k1/memory.c                        |   12 +-
+ sound/pci/emu10k1/p16v.c                          |   45 +-
+ sound/pci/emu10k1/voice.c                         |    6 +-
+ sound/pci/ens1370.c                               |   44 +-
+ sound/pci/es1938.c                                |   79 +-
+ sound/pci/es1968.c                                |   54 +-
+ sound/pci/fm801.c                                 |   31 +-
+ sound/pci/hda/Kconfig                             |   45 +-
+ sound/pci/hda/Makefile                            |    8 +-
+ sound/pci/hda/hda_auto_parser.c                   |   35 +-
+ sound/pci/hda/hda_beep.c                          |   36 +-
+ sound/pci/hda/hda_beep.h                          |    6 +
+ sound/pci/hda/hda_codec.c                         |  238 +-
+ sound/pci/hda/hda_codec.h                         |    8 +-
+ sound/pci/hda/hda_controller.c                    | 2031 +++++++++++++++
+ sound/pci/hda/hda_controller.h                    |   53 +
+ sound/pci/hda/hda_eld.c                           |   17 +-
+ sound/pci/hda/hda_generic.c                       |   49 +-
+ sound/pci/hda/hda_generic.h                       |    1 -
+ sound/pci/hda/hda_hwdep.c                         |  769 +-----
+ sound/pci/hda/hda_i915.c                          |    6 +-
+ sound/pci/hda/hda_intel.c                         | 2824 +++------------------
+ sound/pci/hda/hda_local.h                         |   26 +-
+ sound/pci/hda/hda_priv.h                          |  463 ++++
+ sound/pci/hda/hda_sysfs.c                         |  780 ++++++
+ sound/pci/hda/patch_analog.c                      |    1 -
+ sound/pci/hda/patch_ca0110.c                      |    1 -
+ sound/pci/hda/patch_ca0132.c                      |  209 +-
+ sound/pci/hda/patch_cirrus.c                      |    1 -
+ sound/pci/hda/patch_cmedia.c                      |   34 +-
+ sound/pci/hda/patch_conexant.c                    |  847 +++---
+ sound/pci/hda/patch_hdmi.c                        |   76 +-
+ sound/pci/hda/patch_realtek.c                     |  203 +-
+ sound/pci/hda/patch_si3054.c                      |    5 +-
+ sound/pci/hda/patch_sigmatel.c                    |   15 +-
+ sound/pci/hda/patch_via.c                         |    8 +-
+ sound/pci/hda/thinkpad_helper.c                   |    6 +-
+ sound/pci/ice1712/aureon.c                        |    7 +-
+ sound/pci/ice1712/delta.c                         |    5 +-
+ sound/pci/ice1712/ews.c                           |   12 +-
+ sound/pci/ice1712/ice1712.c                       |   38 +-
+ sound/pci/ice1712/ice1724.c                       |   50 +-
+ sound/pci/ice1712/juli.c                          |   14 +-
+ sound/pci/ice1712/prodigy192.c                    |   13 +-
+ sound/pci/ice1712/quartet.c                       |    6 +-
+ sound/pci/intel8x0.c                              |   90 +-
+ sound/pci/intel8x0m.c                             |   50 +-
+ sound/pci/korg1212/korg1212.c                     |    5 +-
+ sound/pci/lola/lola.c                             |   47 +-
+ sound/pci/lola/lola_clock.c                       |   14 +-
+ sound/pci/lola/lola_mixer.c                       |   22 +-
+ sound/pci/lola/lola_pcm.c                         |   26 +-
+ sound/pci/lx6464es/lx6464es.c                     |  162 +-
+ sound/pci/lx6464es/lx_core.c                      |  173 +-
+ sound/pci/maestro3.c                              |   42 +-
+ sound/pci/mixart/mixart.c                         |  123 +-
+ sound/pci/mixart/mixart_core.c                    |   49 +-
+ sound/pci/mixart/mixart_hwdep.c                   |   65 +-
+ sound/pci/mixart/mixart_mixer.c                   |   16 +-
+ sound/pci/nm256/nm256.c                           |   79 +-
+ sound/pci/oxygen/oxygen_io.c                      |    8 +-
+ sound/pci/oxygen/oxygen_lib.c                     |   14 +-
+ sound/pci/oxygen/xonar_hdmi.c                     |    2 +-
+ sound/pci/oxygen/xonar_lib.c                      |    4 +-
+ sound/pci/pcxhr/pcxhr.c                           |   58 +-
+ sound/pci/pcxhr/pcxhr_core.c                      |  108 +-
+ sound/pci/pcxhr/pcxhr_hwdep.c                     |   31 +-
+ sound/pci/pcxhr/pcxhr_mix22.c                     |   23 +-
+ sound/pci/pcxhr/pcxhr_mixer.c                     |   13 +-
+ sound/pci/riptide/riptide.c                       |    5 +-
+ sound/pci/rme32.c                                 |   10 +-
+ sound/pci/rme96.c                                 |   51 +-
+ sound/pci/rme9652/hdsp.c                          |  133 +-
+ sound/pci/rme9652/hdspm.c                         |  131 +-
+ sound/pci/rme9652/rme9652.c                       |   24 +-
+ sound/pci/sis7019.c                               |    5 +-
+ sound/pci/sonicvibes.c                            |  240 +-
+ sound/pci/trident/trident.c                       |    3 +-
+ sound/pci/trident/trident_main.c                  |   90 +-
+ sound/pci/via82xx.c                               |   73 +-
+ sound/pci/via82xx_modem.c                         |   49 +-
+ sound/pci/vx222/vx222.c                           |   12 +-
+ sound/pci/vx222/vx222_ops.c                       |   19 +-
+ sound/pci/ymfpci/ymfpci.c                         |   25 +-
+ sound/pci/ymfpci/ymfpci_main.c                    |   28 +-
+ sound/pcmcia/pdaudiocf/pdaudiocf.c                |    5 +-
+ sound/pcmcia/vx/vxpocket.c                        |    4 +-
+ sound/ppc/powermac.c                              |    4 +-
+ sound/ppc/snd_ps3.c                               |    4 +-
+ sound/sh/aica.c                                   |    5 +-
+ sound/sh/sh_dac_audio.c                           |    2 +-
+ sound/soc/soc-core.c                              |    3 +-
+ sound/sparc/amd7930.c                             |    4 +-
+ sound/sparc/cs4231.c                              |   11 +-
+ sound/sparc/dbri.c                                |    4 +-
+ sound/spi/at73c213.c                              |    6 +-
+ sound/usb/6fire/chip.c                            |   13 +-
+ sound/usb/6fire/comm.c                            |    4 +-
+ sound/usb/6fire/control.c                         |   18 +-
+ sound/usb/6fire/firmware.c                        |   70 +-
+ sound/usb/6fire/midi.c                            |   12 +-
+ sound/usb/6fire/pcm.c                             |   46 +-
+ sound/usb/caiaq/device.c                          |    6 +-
+ sound/usb/card.c                                  |   69 +-
+ sound/usb/clock.c                                 |   65 +-
+ sound/usb/endpoint.c                              |   32 +-
+ sound/usb/format.c                                |   68 +-
+ sound/usb/hiface/chip.c                           |   10 +-
+ sound/usb/midi.c                                  |   45 +-
+ sound/usb/misc/ua101.c                            |    7 +-
+ sound/usb/mixer.c                                 |  225 +-
+ sound/usb/mixer.h                                 |    7 +-
+ sound/usb/mixer_quirks.c                          |   10 +-
+ sound/usb/pcm.c                                   |   83 +-
+ sound/usb/quirks.c                                |   52 +-
+ sound/usb/stream.c                                |   50 +-
+ sound/usb/usbaudio.h                              |    9 +
+ sound/usb/usx2y/us122l.c                          |   11 +-
+ sound/usb/usx2y/usbusx2y.c                        |   13 +-
+ sound/usb/usx2y/usbusx2y.h                        |    2 +-
+ sound/usb/usx2y/usbusx2yaudio.c                   |   60 +-
+ sound/usb/usx2y/usx2yhwdeppcm.c                   |   76 +-
+ 295 files changed, 8414 insertions(+), 7740 deletions(-)
+ create mode 100644 sound/pci/hda/hda_controller.c
+ create mode 100644 sound/pci/hda/hda_controller.h
+ create mode 100644 sound/pci/hda/hda_priv.h
+ create mode 100644 sound/pci/hda/hda_sysfs.c
+Merging sound-asoc/for-next (d01fcf8e8e14 Merge remote-tracking branches 'asoc/topic/wm8988', 'asoc/topic/wm8990', 'asoc/topic/wm8991', 'asoc/topic/wm8993', 'asoc/topic/wm8994', 'asoc/topic/wm8996', 'asoc/topic/wm9081' and 'asoc/topic/wm9705' into asoc-next)
+$ git merge sound-asoc/for-next
+Resolved 'sound/soc/kirkwood/Kconfig' using previous resolution.
+Auto-merging sound/soc/soc-core.c
+Auto-merging sound/soc/kirkwood/Kconfig
+CONFLICT (content): Merge conflict in sound/soc/kirkwood/Kconfig
+Auto-merging sound/soc/intel/sst-mfld-platform.h
+Auto-merging sound/soc/intel/sst-mfld-platform.c
+Auto-merging sound/soc/intel/sst-mfld-dsp.h
+Auto-merging sound/core/pcm_lib.c
+Auto-merging MAINTAINERS
+Auto-merging Documentation/devicetree/bindings/i2c/trivial-devices.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 8bde0f3b54e2] Merge remote-tracking branch 'sound-asoc/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/i2c/trivial-devices.txt    |    1 +
+ .../devicetree/bindings/misc/atmel-ssc.txt         |    8 +
+ .../bindings/sound/armada-370db-audio.txt          |   24 +
+ Documentation/devicetree/bindings/sound/da9055.txt |   22 +
+ .../bindings/sound/davinci-evm-audio.txt           |    9 +-
+ .../devicetree/bindings/sound/eukrea-tlv320.txt    |   21 +
+ .../devicetree/bindings/sound/fsl,esai.txt         |    5 +
+ .../devicetree/bindings/sound/fsl,spdif.txt        |    5 +
+ .../devicetree/bindings/sound/mvebu-audio.txt      |    1 +
+ .../devicetree/bindings/sound/pcm512x.txt          |   30 +
+ .../devicetree/bindings/sound/simple-card.txt      |   17 +-
+ .../devicetree/bindings/sound/tdm-slot.txt         |   20 +
+ .../devicetree/bindings/sound/tlv320aic32x4.txt    |   30 +
+ .../devicetree/bindings/sound/tlv320aic3x.txt      |    1 -
+ .../devicetree/bindings/sound/widgets.txt          |   20 +
+ MAINTAINERS                                        |    7 +
+ drivers/misc/atmel-ssc.c                           |    6 +
+ include/linux/atmel-ssc.h                          |    1 +
+ include/linux/platform_data/adau1977.h             |   45 +
+ include/linux/platform_data/asoc-s3c.h             |    3 +-
+ include/linux/platform_data/asoc-s3c24xx_simtec.h  |    3 +-
+ include/linux/platform_data/davinci_asp.h          |    4 +-
+ include/sound/rcar_snd.h                           |    8 +-
+ include/sound/simple_card.h                        |    6 +-
+ include/sound/soc-dai.h                            |    2 +
+ include/sound/soc-dapm.h                           |   39 +-
+ include/sound/soc.h                                |  107 +-
+ include/trace/events/hswadsp.h                     |  384 +++++
+ include/trace/events/intel-sst.h                   |  148 ++
+ sound/core/pcm_lib.c                               |    1 +
+ sound/soc/atmel/atmel_ssc_dai.c                    |   13 +-
+ sound/soc/blackfin/Kconfig                         |    9 +-
+ sound/soc/cirrus/Kconfig                           |    2 +-
+ sound/soc/codecs/88pm860x-codec.c                  |  116 +-
+ sound/soc/codecs/Kconfig                           |  155 +-
+ sound/soc/codecs/Makefile                          |   20 +
+ sound/soc/codecs/ad1836.c                          |    4 +-
+ sound/soc/codecs/ad193x-i2c.c                      |   54 +
+ sound/soc/codecs/ad193x-spi.c                      |   48 +
+ sound/soc/codecs/ad193x.c                          |  144 +-
+ sound/soc/codecs/ad193x.h                          |    7 +
+ sound/soc/codecs/adau1373.c                        |   32 +-
+ sound/soc/codecs/adau1977-i2c.c                    |   59 +
+ sound/soc/codecs/adau1977-spi.c                    |   76 +
+ sound/soc/codecs/adau1977.c                        | 1018 +++++++++++
+ sound/soc/codecs/adau1977.h                        |   37 +
+ sound/soc/codecs/adav801.c                         |   53 +
+ sound/soc/codecs/adav803.c                         |   50 +
+ sound/soc/codecs/adav80x.c                         |  148 +-
+ sound/soc/codecs/adav80x.h                         |    7 +
+ sound/soc/codecs/ak4641.c                          |   16 +-
+ sound/soc/codecs/ak4671.c                          |  240 ++-
+ sound/soc/codecs/ak4671.h                          |    2 -
+ sound/soc/codecs/alc5623.c                         |  117 +-
+ sound/soc/codecs/alc5632.c                         |   40 +-
+ sound/soc/codecs/arizona.c                         |   71 +-
+ sound/soc/codecs/cs4271.c                          |   61 +-
+ sound/soc/codecs/cs42l51.c                         |   86 +-
+ sound/soc/codecs/cs42l52.c                         |   92 +-
+ sound/soc/codecs/cs42l73.c                         |   55 +-
+ sound/soc/codecs/da7210.c                          |   20 +-
+ sound/soc/codecs/da7213.c                          |  151 +-
+ sound/soc/codecs/da732x.c                          |  167 +-
+ sound/soc/codecs/da732x.h                          |    3 -
+ sound/soc/codecs/da9055.c                          |   92 +-
+ sound/soc/codecs/lm4857.c                          |    3 +-
+ sound/soc/codecs/lm49453.c                         |   30 +-
+ sound/soc/codecs/max98088.c                        |   41 +-
+ sound/soc/codecs/max98090.c                        |  172 +-
+ sound/soc/codecs/max98095.c                        |   54 +-
+ sound/soc/codecs/mc13783.c                         |   20 +-
+ sound/soc/codecs/ml26124.c                         |   12 +-
+ sound/soc/codecs/pcm1681.c                         |   15 +-
+ sound/soc/codecs/pcm1792a.c                        |   33 +-
+ sound/soc/codecs/pcm512x.c                         |  707 ++++++++
+ sound/soc/codecs/pcm512x.h                         |  162 ++
+ sound/soc/codecs/rt5631.c                          |   75 +-
+ sound/soc/codecs/rt5640.c                          |   75 +-
+ sound/soc/codecs/sgtl5000.c                        |   18 +-
+ sound/soc/codecs/sn95031.c                         |   44 +-
+ sound/soc/codecs/ssm2518.c                         |   14 +-
+ sound/soc/codecs/ssm2602-i2c.c                     |   57 +
+ sound/soc/codecs/ssm2602-spi.c                     |   41 +
+ sound/soc/codecs/ssm2602.c                         |  173 +-
+ sound/soc/codecs/ssm2602.h                         |   14 +
+ sound/soc/codecs/sta529.c                          |    2 +-
+ sound/soc/codecs/stac9766.c                        |   38 +-
+ sound/soc/codecs/tlv320aic23.c                     |   12 +-
+ sound/soc/codecs/tlv320aic26.c                     |    5 +-
+ sound/soc/codecs/tlv320aic32x4.c                   |  232 ++-
+ sound/soc/codecs/tlv320dac33.c                     |   32 +-
+ sound/soc/codecs/twl4030.c                         |  101 +-
+ sound/soc/codecs/twl6040.c                         |   17 +-
+ sound/soc/codecs/uda1380.c                         |   38 +-
+ sound/soc/codecs/wl1273.c                          |    7 +-
+ sound/soc/codecs/wm2200.c                          |   18 +-
+ sound/soc/codecs/wm5100.c                          |   36 +-
+ sound/soc/codecs/wm5102.c                          |   26 +-
+ sound/soc/codecs/wm5110.c                          |   17 +-
+ sound/soc/codecs/wm8523.c                          |    4 +-
+ sound/soc/codecs/wm8731.c                          |    4 +-
+ sound/soc/codecs/wm8737.c                          |   50 +-
+ sound/soc/codecs/wm8741.c                          |   34 +-
+ sound/soc/codecs/wm8804.c                          |    2 +-
+ sound/soc/codecs/wm8903.c                          |  108 +-
+ sound/soc/codecs/wm8904.c                          |   77 +-
+ sound/soc/codecs/wm8940.c                          |   20 +-
+ sound/soc/codecs/wm8955.c                          |   11 +-
+ sound/soc/codecs/wm8958-dsp2.c                     |    8 +-
+ sound/soc/codecs/wm8961.c                          |   16 +-
+ sound/soc/codecs/wm8962.c                          |   80 +-
+ sound/soc/codecs/wm8974.c                          |    4 +-
+ sound/soc/codecs/wm8978.c                          |   30 +-
+ sound/soc/codecs/wm8983.c                          |   45 +-
+ sound/soc/codecs/wm8985.c                          |   39 +-
+ sound/soc/codecs/wm8988.c                          |   62 +-
+ sound/soc/codecs/wm8990.c                          |   41 +-
+ sound/soc/codecs/wm8991.c                          |   44 +-
+ sound/soc/codecs/wm8993.c                          |   66 +-
+ sound/soc/codecs/wm8994.c                          |   52 +-
+ sound/soc/codecs/wm8995.c                          |   43 +-
+ sound/soc/codecs/wm8996.c                          |   75 +-
+ sound/soc/codecs/wm8997.c                          |   23 +-
+ sound/soc/codecs/wm9081.c                          |   23 +-
+ sound/soc/codecs/wm9705.c                          |   12 +-
+ sound/soc/codecs/wm_adsp.c                         |    2 +
+ sound/soc/codecs/wm_hubs.c                         |   16 +-
+ sound/soc/davinci/davinci-evm.c                    |   58 +-
+ sound/soc/davinci/davinci-mcasp.c                  |  152 +-
+ sound/soc/fsl/Kconfig                              |    9 +-
+ sound/soc/fsl/eukrea-tlv320.c                      |  108 +-
+ sound/soc/fsl/fsl_esai.c                           |   32 +-
+ sound/soc/fsl/fsl_sai.c                            |  332 ++--
+ sound/soc/fsl/fsl_sai.h                            |   48 +-
+ sound/soc/fsl/fsl_spdif.c                          |    9 +-
+ sound/soc/fsl/imx-pcm-fiq.c                        |    7 +-
+ sound/soc/generic/simple-card.c                    |  243 +--
+ sound/soc/intel/Kconfig                            |   42 +-
+ sound/soc/intel/Makefile                           |   27 +-
+ sound/soc/intel/byt-rt5640.c                       |  187 ++
+ sound/soc/intel/haswell.c                          |  241 +++
+ sound/soc/intel/mfld_machine.c                     |   65 +-
+ sound/soc/intel/sst-acpi.c                         |  284 ++++
+ sound/soc/intel/sst-baytrail-dsp.c                 |  372 ++++
+ sound/soc/intel/sst-baytrail-ipc.c                 |  867 ++++++++++
+ sound/soc/intel/sst-baytrail-ipc.h                 |   69 +
+ sound/soc/intel/sst-baytrail-pcm.c                 |  422 +++++
+ sound/soc/intel/sst-dsp-priv.h                     |  309 ++++
+ sound/soc/intel/sst-dsp.c                          |  385 +++++
+ sound/soc/intel/sst-dsp.h                          |  233 +++
+ sound/soc/intel/sst-firmware.c                     |  587 +++++++
+ sound/soc/intel/sst-haswell-dsp.c                  |  517 ++++++
+ sound/soc/intel/sst-haswell-ipc.c                  | 1785 ++++++++++++++++++++
+ sound/soc/intel/sst-haswell-ipc.h                  |  488 ++++++
+ sound/soc/intel/sst-haswell-pcm.c                  |  872 ++++++++++
+ sound/soc/intel/{sst_dsp.h => sst-mfld-dsp.h}      |    8 +-
+ .../intel/{sst_platform.c => sst-mfld-platform.c}  |    8 +-
+ .../intel/{sst_platform.h => sst-mfld-platform.h}  |    4 +-
+ sound/soc/kirkwood/Kconfig                         |   10 +-
+ sound/soc/kirkwood/Makefile                        |    2 +
+ sound/soc/kirkwood/armada-370-db.c                 |  120 ++
+ sound/soc/kirkwood/kirkwood-i2s.c                  |    1 +
+ sound/soc/omap/ams-delta.c                         |   55 +-
+ sound/soc/omap/n810.c                              |   22 +-
+ sound/soc/omap/rx51.c                              |   22 +-
+ sound/soc/pxa/corgi.c                              |   49 +-
+ sound/soc/pxa/e740_wm9705.c                        |   10 +-
+ sound/soc/pxa/e750_wm9705.c                        |   10 +-
+ sound/soc/pxa/e800_wm9712.c                        |   19 +-
+ sound/soc/pxa/magician.c                           |   26 +-
+ sound/soc/pxa/mioa701_wm9713.c                     |   19 +-
+ sound/soc/pxa/poodle.c                             |    7 +-
+ sound/soc/pxa/spitz.c                              |   58 +-
+ sound/soc/pxa/tosa.c                               |   32 +-
+ sound/soc/pxa/zylonite.c                           |   17 +-
+ sound/soc/samsung/h1940_uda1380.c                  |    7 +-
+ sound/soc/samsung/neo1973_wm8753.c                 |  168 +-
+ sound/soc/samsung/rx1950_uda1380.c                 |    5 -
+ sound/soc/samsung/smdk_wm8994.c                    |    2 +-
+ sound/soc/samsung/tobermory.c                      |    2 +
+ sound/soc/sh/rcar/adg.c                            |  216 ++-
+ sound/soc/sh/rcar/core.c                           |  123 +-
+ sound/soc/sh/rcar/gen.c                            |   46 +-
+ sound/soc/sh/rcar/rsnd.h                           |   76 +-
+ sound/soc/sh/rcar/scu.c                            |  612 +++++--
+ sound/soc/sh/rcar/ssi.c                            |  226 +--
+ sound/soc/soc-core.c                               |  307 +++-
+ sound/soc/soc-dapm.c                               |  444 ++---
+ sound/soc/soc-io.c                                 |   19 -
+ sound/soc/soc-jack.c                               |    5 +-
+ 190 files changed, 15354 insertions(+), 3728 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/armada-370db-audio.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/da9055.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/eukrea-tlv320.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/pcm512x.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/tdm-slot.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/widgets.txt
+ create mode 100644 include/linux/platform_data/adau1977.h
+ create mode 100644 include/trace/events/hswadsp.h
+ create mode 100644 include/trace/events/intel-sst.h
+ create mode 100644 sound/soc/codecs/ad193x-i2c.c
+ create mode 100644 sound/soc/codecs/ad193x-spi.c
+ create mode 100644 sound/soc/codecs/adau1977-i2c.c
+ create mode 100644 sound/soc/codecs/adau1977-spi.c
+ create mode 100644 sound/soc/codecs/adau1977.c
+ create mode 100644 sound/soc/codecs/adau1977.h
+ create mode 100644 sound/soc/codecs/adav801.c
+ create mode 100644 sound/soc/codecs/adav803.c
+ create mode 100644 sound/soc/codecs/pcm512x.c
+ create mode 100644 sound/soc/codecs/pcm512x.h
+ create mode 100644 sound/soc/codecs/ssm2602-i2c.c
+ create mode 100644 sound/soc/codecs/ssm2602-spi.c
+ create mode 100644 sound/soc/intel/byt-rt5640.c
+ create mode 100644 sound/soc/intel/haswell.c
+ create mode 100644 sound/soc/intel/sst-acpi.c
+ create mode 100644 sound/soc/intel/sst-baytrail-dsp.c
+ create mode 100644 sound/soc/intel/sst-baytrail-ipc.c
+ create mode 100644 sound/soc/intel/sst-baytrail-ipc.h
+ create mode 100644 sound/soc/intel/sst-baytrail-pcm.c
+ create mode 100644 sound/soc/intel/sst-dsp-priv.h
+ create mode 100644 sound/soc/intel/sst-dsp.c
+ create mode 100644 sound/soc/intel/sst-dsp.h
+ create mode 100644 sound/soc/intel/sst-firmware.c
+ create mode 100644 sound/soc/intel/sst-haswell-dsp.c
+ create mode 100644 sound/soc/intel/sst-haswell-ipc.c
+ create mode 100644 sound/soc/intel/sst-haswell-ipc.h
+ create mode 100644 sound/soc/intel/sst-haswell-pcm.c
+ rename sound/soc/intel/{sst_dsp.h => sst-mfld-dsp.h} (96%)
+ rename sound/soc/intel/{sst_platform.c => sst-mfld-platform.c} (99%)
+ rename sound/soc/intel/{sst_platform.h => sst-mfld-platform.h} (97%)
+ create mode 100644 sound/soc/kirkwood/armada-370-db.c
+Merging modules/modules-next (917307b09ad5 module: remove MODULE_GENERIC_TABLE)
+$ git merge modules/modules-next
+Auto-merging scripts/mod/file2alias.c
+Merge made by the 'recursive' strategy.
+ include/linux/isapnp.h   |  4 ----
+ include/linux/module.h   | 19 ++++++++-----------
+ kernel/module.c          |  6 +++---
+ scripts/mod/file2alias.c | 14 +++++++++-----
+ 4 files changed, 20 insertions(+), 23 deletions(-)
+Merging virtio/virtio-next (6f0317058f43 tools/virtio: add a missing ))
+$ git merge virtio/virtio-next
+Merge made by the 'recursive' strategy.
+ drivers/virtio/virtio_ring.c  | 1 +
+ tools/virtio/linux/kmemleak.h | 3 +++
+ tools/virtio/linux/virtio.h   | 4 ++--
+ tools/virtio/virtio_test.c    | 2 +-
+ 4 files changed, 7 insertions(+), 3 deletions(-)
+ create mode 100644 tools/virtio/linux/kmemleak.h
+Merging input/next (7fb45edba8b5 Input: imx_keypad - Propagate the real error code on platform_get_irq() failure)
+$ git merge input/next
+Auto-merging drivers/input/touchscreen/zforce_ts.c
+Merge made by the 'recursive' strategy.
+ .../bindings/input/touchscreen/zforce_ts.txt       |  30 +++
+ drivers/input/keyboard/imx_keypad.c                |   4 +-
+ drivers/input/misc/ims-pcu.c                       | 258 ++++++++++++++++++++-
+ drivers/input/misc/sirfsoc-onkey.c                 | 110 ++++++---
+ drivers/input/misc/uinput.c                        |  97 +++++---
+ drivers/input/misc/wistron_btns.c                  |  19 ++
+ drivers/input/tablet/gtco.c                        |   2 +-
+ drivers/input/touchscreen/zforce_ts.c              |  95 ++++++--
+ include/linux/platform_data/touchscreen-s3c2410.h  |  17 +-
+ include/linux/uinput.h                             |   2 +
+ include/uapi/linux/uinput.h                        |  13 +-
+ 11 files changed, 552 insertions(+), 95 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
+Merging input-mt/for-next (5e01dc7b26d9 Linux 3.12)
+$ git merge input-mt/for-next
+Already up-to-date.
+Merging block/for-next (a9f4f164c036 Merge branch 'for-3.15/drivers' into for-next)
+$ git merge block/for-next
+Auto-merging net/core/dev.c
+Auto-merging kernel/sched/core.c
+Merge made by the 'recursive' strategy.
+ Documentation/blockdev/drbd/data-structure-v9.txt |   38 +
+ block/blk-cgroup.c                                |    2 +-
+ block/blk-ioc.c                                   |    2 +-
+ block/blk-mq.c                                    |    2 +-
+ block/blk-softirq.c                               |   19 +-
+ block/cfq-iosched.c                               |    8 +-
+ block/deadline-iosched.c                          |    8 +-
+ block/partitions/atari.h                          |    4 +-
+ block/partitions/efi.h                            |    9 +-
+ block/partitions/karma.c                          |    3 +-
+ drivers/block/DAC960.c                            |   34 +-
+ drivers/block/ataflop.c                           |   16 +-
+ drivers/block/drbd/drbd_actlog.c                  |  629 ++---
+ drivers/block/drbd/drbd_bitmap.c                  |  368 ++-
+ drivers/block/drbd/drbd_int.h                     | 1130 ++++-----
+ drivers/block/drbd/drbd_main.c                    | 2009 ++++++++--------
+ drivers/block/drbd/drbd_nl.c                      | 1653 +++++++-------
+ drivers/block/drbd/drbd_proc.c                    |  140 +-
+ drivers/block/drbd/drbd_protocol.h                |  295 +++
+ drivers/block/drbd/drbd_receiver.c                | 2532 +++++++++++----------
+ drivers/block/drbd/drbd_req.c                     |  464 ++--
+ drivers/block/drbd/drbd_req.h                     |   20 +-
+ drivers/block/drbd/drbd_state.c                   |  859 +++----
+ drivers/block/drbd/drbd_state.h                   |   40 +-
+ drivers/block/drbd/drbd_strings.c                 |    1 +
+ drivers/block/drbd/drbd_strings.h                 |    9 +
+ drivers/block/drbd/drbd_worker.c                  |  944 ++++----
+ drivers/block/drbd/drbd_wrappers.h                |   14 +-
+ drivers/block/mtip32xx/mtip32xx.c                 |    4 +-
+ drivers/block/skd_main.c                          |   66 +-
+ drivers/block/swim3.c                             |   18 +-
+ drivers/cpuidle/coupled.c                         |    2 +-
+ fs/bio-integrity.c                                |   86 +-
+ fs/bio.c                                          |    1 -
+ include/linux/blkdev.h                            |    1 +
+ include/linux/drbd.h                              |    8 +-
+ include/linux/drbd_genl.h                         |    6 +-
+ include/linux/elevator.h                          |   11 +-
+ include/linux/idr.h                               |    1 +
+ include/linux/smp.h                               |    8 +-
+ kernel/sched/core.c                               |    2 +-
+ kernel/smp.c                                      |  139 +-
+ kernel/up.c                                       |    6 +-
+ kernel/watchdog.c                                 |    3 +-
+ lib/idr.c                                         |   10 +
+ net/core/dev.c                                    |    4 +-
+ 46 files changed, 6025 insertions(+), 5603 deletions(-)
+ create mode 100644 Documentation/blockdev/drbd/data-structure-v9.txt
+ create mode 100644 drivers/block/drbd/drbd_protocol.h
+ create mode 100644 drivers/block/drbd/drbd_strings.h
+Merging device-mapper/for-next (14f398ca2f26 dm cache mq: fix memory allocation failure for large cache devices)
+$ git merge device-mapper/for-next
+Merge made by the 'recursive' strategy.
+ drivers/md/dm-cache-policy-mq.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 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 (370aede6a18a mmc: dw_mmc: fix possible build error)
+$ git merge mmc/mmc-next
+Auto-merging drivers/mmc/host/mmci.h
+Removing drivers/mmc/host/dw_mmc-socfpga.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/mmc/mmc.txt      |   9 +
+ .../devicetree/bindings/mmc/socfpga-dw-mshc.txt    |  23 +
+ MAINTAINERS                                        |   1 +
+ arch/arm/boot/dts/socfpga.dtsi                     |  17 +-
+ arch/arm/boot/dts/socfpga_arria5.dtsi              |  11 +
+ arch/arm/boot/dts/socfpga_cyclone5.dtsi            |  11 +
+ arch/arm/boot/dts/socfpga_vt.dts                   |  11 +
+ drivers/mfd/rtsx_pcr.c                             | 132 +++--
+ drivers/mmc/card/block.c                           | 181 ++++---
+ drivers/mmc/core/Kconfig                           |  15 -
+ drivers/mmc/core/bus.c                             |  12 +-
+ drivers/mmc/core/core.c                            |  83 +---
+ drivers/mmc/core/host.c                            |  18 +
+ drivers/mmc/core/mmc.c                             |  65 ++-
+ drivers/mmc/core/mmc_ops.c                         |  64 ++-
+ drivers/mmc/core/sd.c                              |  23 +-
+ drivers/mmc/host/Kconfig                           |   8 -
+ drivers/mmc/host/Makefile                          |   1 -
+ drivers/mmc/host/davinci_mmc.c                     |   4 +-
+ drivers/mmc/host/dw_mmc-k3.c                       |   2 +
+ drivers/mmc/host/dw_mmc-pltfm.c                    |  12 +-
+ drivers/mmc/host/dw_mmc-socfpga.c                  | 138 ------
+ drivers/mmc/host/dw_mmc.c                          |   2 +-
+ drivers/mmc/host/dw_mmc.h                          |   3 +-
+ drivers/mmc/host/mmci.c                            |  54 ++-
+ drivers/mmc/host/mmci.h                            |   2 +
+ drivers/mmc/host/omap.c                            |  93 ++--
+ drivers/mmc/host/rtsx_pci_sdmmc.c                  | 529 +++++++++++++++------
+ drivers/mmc/host/sdhci-bcm-kona.c                  |  37 +-
+ drivers/mmc/host/sdhci-dove.c                      |   2 +-
+ drivers/mmc/host/sdhci-pci.c                       |  20 +
+ drivers/mmc/host/sdhci-s3c.c                       | 170 +++----
+ drivers/mmc/host/sdhci-spear.c                     |   8 +-
+ drivers/mmc/host/sdhci.c                           |  13 +-
+ drivers/mmc/host/sh_mobile_sdhi.c                  |  50 +-
+ drivers/mmc/host/tmio_mmc.c                        |  30 +-
+ drivers/mmc/host/tmio_mmc.h                        |   7 +-
+ drivers/mmc/host/tmio_mmc_pio.c                    |   7 +-
+ drivers/mmc/host/ushc.c                            |   2 +-
+ drivers/mmc/host/wmt-sdmmc.c                       |   4 +-
+ include/linux/mfd/rtsx_common.h                    |   1 +
+ include/linux/mfd/rtsx_pci.h                       |   8 +-
+ include/linux/mmc/core.h                           |   4 +-
+ include/linux/mmc/host.h                           |  13 +-
+ include/linux/mmc/sdhci.h                          |   2 +
+ include/linux/platform_data/mmc-msm_sdcc.h         |   7 +-
+ include/linux/platform_data/mmc-mvsdio.h           |   6 +-
+ 47 files changed, 1089 insertions(+), 826 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt
+ delete mode 100644 drivers/mmc/host/dw_mmc-socfpga.c
+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 (26e4f2057516 slub: Fix possible format string bug.)
+$ 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 (789b5e031528 md/raid5: Fix CPU hotplug callback registration)
+$ 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 (2c752f79c7c0 mfd: mc13xxx: Add missing spi_setup())
+$ git merge mfd-lj/for-mfd-next
+Removing include/linux/mfd/pm8xxx/pm8921.h
+Removing include/linux/mfd/pm8xxx/irq.h
+Removing drivers/mfd/pm8xxx-irq.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/mfd/qcom,pm8xxx.txt        |  63 ++
+ drivers/gpio/gpio-ich.c                            |  96 ++-
+ drivers/mfd/88pm800.c                              |   3 +-
+ drivers/mfd/88pm860x-core.c                        |   6 +
+ drivers/mfd/Kconfig                                |  67 +-
+ drivers/mfd/Makefile                               |   3 +-
+ drivers/mfd/adp5520.c                              |   1 -
+ drivers/mfd/cs5535-mfd.c                           |   1 -
+ drivers/mfd/da9052-core.c                          |   3 +
+ drivers/mfd/da9052-i2c.c                           |   5 +-
+ drivers/mfd/da9052-spi.c                           |   1 +
+ drivers/mfd/da9063-core.c                          |  25 +-
+ drivers/mfd/janz-cmodio.c                          |   1 -
+ drivers/mfd/kempld-core.c                          |  24 +
+ drivers/mfd/lpc_ich.c                              |   2 +-
+ drivers/mfd/lpc_sch.c                              |   1 -
+ drivers/mfd/max14577.c                             |   6 +-
+ drivers/mfd/max77686.c                             |   4 +
+ drivers/mfd/max77693.c                             |  12 +-
+ drivers/mfd/max8925-i2c.c                          |   9 +
+ drivers/mfd/max8997.c                              |  18 +
+ drivers/mfd/max8998.c                              |   4 +
+ drivers/mfd/mc13xxx-spi.c                          |   5 +
+ drivers/mfd/mcp-sa11x0.c                           |   1 -
+ drivers/mfd/omap-usb-host.c                        |  81 +--
+ drivers/mfd/omap-usb-tll.c                         |   2 +-
+ drivers/mfd/pcf50633-adc.c                         |   1 -
+ drivers/mfd/pm8921-core.c                          | 427 ++++++++++--
+ drivers/mfd/pm8xxx-irq.c                           | 371 ----------
+ drivers/mfd/rc5t583-irq.c                          |   1 -
+ drivers/mfd/rdc321x-southbridge.c                  |   1 -
+ drivers/mfd/retu-mfd.c                             |   1 -
+ drivers/mfd/rtsx_usb.c                             | 760 +++++++++++++++++++++
+ drivers/mfd/sec-core.c                             |  61 +-
+ drivers/mfd/sec-irq.c                              |  97 ++-
+ drivers/mfd/smsc-ece1099.c                         |   1 -
+ drivers/mfd/stmpe.c                                |   2 +-
+ drivers/mfd/stw481x.c                              |   8 +-
+ drivers/mfd/syscon.c                               |   2 +-
+ drivers/mfd/tc3589x.c                              |  84 ++-
+ drivers/mfd/ti-ssp.c                               |   1 -
+ drivers/mfd/ti_am335x_tscadc.c                     |  24 +-
+ drivers/mfd/timberdale.c                           |   2 +-
+ drivers/mfd/tps65218.c                             | 281 ++++++++
+ drivers/mfd/tps65912-core.c                        |   1 -
+ drivers/mfd/tps65912-irq.c                         |   1 -
+ drivers/mfd/twl4030-irq.c                          |   1 -
+ drivers/mfd/twl4030-madc.c                         |   1 -
+ drivers/mfd/twl6030-irq.c                          |   1 -
+ drivers/mfd/twl6040.c                              |   6 +-
+ drivers/mfd/ucb1x00-core.c                         |   4 +-
+ drivers/mfd/vexpress-config.c                      |   1 -
+ drivers/mfd/vexpress-sysreg.c                      |   2 +-
+ drivers/mfd/wm5102-tables.c                        |  35 +
+ drivers/mfd/wm5110-tables.c                        | 168 +++++
+ drivers/mfd/wm8350-core.c                          |   1 -
+ drivers/mfd/wm8350-irq.c                           |   1 -
+ drivers/mfd/wm8400-core.c                          |  22 +-
+ include/linux/mfd/arizona/registers.h              |  84 +++
+ include/linux/mfd/da9052/da9052.h                  |   1 +
+ include/linux/mfd/da9063/core.h                    |   6 +-
+ include/linux/mfd/lpc_ich.h                        |  17 +-
+ include/linux/mfd/max14577-private.h               |   8 -
+ include/linux/mfd/max14577.h                       |   5 -
+ include/linux/mfd/pm8xxx/irq.h                     |  59 --
+ include/linux/mfd/pm8xxx/pm8921.h                  |  30 -
+ include/linux/mfd/rtsx_usb.h                       | 628 +++++++++++++++++
+ include/linux/mfd/samsung/core.h                   |   1 +
+ include/linux/mfd/samsung/irq.h                    |  31 +-
+ include/linux/mfd/samsung/rtc.h                    |  57 +-
+ include/linux/mfd/samsung/s2mps14.h                | 152 +++++
+ include/linux/mfd/tps65218.h                       | 284 ++++++++
+ include/linux/ssbi.h                               |  20 +
+ 73 files changed, 3435 insertions(+), 762 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
+ delete mode 100644 drivers/mfd/pm8xxx-irq.c
+ create mode 100644 drivers/mfd/rtsx_usb.c
+ create mode 100644 drivers/mfd/tps65218.c
+ delete mode 100644 include/linux/mfd/pm8xxx/irq.h
+ delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h
+ create mode 100644 include/linux/mfd/rtsx_usb.h
+ create mode 100644 include/linux/mfd/samsung/s2mps14.h
+ create mode 100644 include/linux/mfd/tps65218.h
+$ git reset --hard HEAD^
+HEAD is now at 0bfc50cc3da2 Merge remote-tracking branch 'kgdb/kgdb-next'
+Merging next-20140210 version of mfd-lj
+$ git merge -m next-20140210/mfd-lj 4d0621451ff2b8ce8a4aed66b98d66121a048fc3
+Auto-merging drivers/mfd/max14577.c
+Merge made by the 'recursive' strategy.
+ drivers/mfd/Kconfig                   |   6 +-
+ drivers/mfd/max14577.c                |   5 +-
+ drivers/mfd/wm5102-tables.c           |  35 +++++++
+ drivers/mfd/wm5110-tables.c           | 168 ++++++++++++++++++++++++++++++++++
+ include/linux/mfd/arizona/registers.h |  84 +++++++++++++++++
+ include/linux/mfd/max14577-private.h  |   8 --
+ include/linux/mfd/max14577.h          |   5 -
+ 7 files changed, 294 insertions(+), 17 deletions(-)
+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 (2b04f21e69a1 Merge branch '3.15/fb-reorder' into for-next)
+$ git merge omap_dss2/for-next
+Removing include/linux/xilinxfb.h
+Removing drivers/video/omap2/Kconfig
+Auto-merging drivers/video/fbdev/xilinxfb.c
+Auto-merging drivers/video/fbdev/wmt_ge_rops.c
+Auto-merging drivers/video/fbdev/tgafb.c
+Auto-merging drivers/video/fbdev/omap2/dss/dss.h
+Auto-merging drivers/video/fbdev/omap2/dss/dss.c
+Auto-merging drivers/video/fbdev/omap2/dss/dispc.c
+Auto-merging drivers/video/fbdev/mmp/Kconfig
+Auto-merging drivers/video/fbdev/matrox/matroxfb_base.h
+Auto-merging drivers/video/fbdev/matrox/matroxfb_base.c
+Auto-merging drivers/video/fbdev/matrox/matroxfb_accel.c
+Auto-merging drivers/video/fbdev/imxfb.c
+Auto-merging drivers/video/fbdev/exynos/s6e8ax0.c
+Auto-merging drivers/video/fbdev/exynos/Kconfig
+Auto-merging drivers/video/fbdev/da8xx-fb.c
+Auto-merging drivers/video/fbdev/core/fbmon.c
+Auto-merging drivers/video/fbdev/core/fb_ddc.c
+Auto-merging drivers/video/fbdev/core/cfbcopyarea.c
+Auto-merging drivers/video/fbdev/aty/mach64_cursor.c
+Auto-merging drivers/video/fbdev/aty/mach64_accel.c
+Auto-merging drivers/video/fbdev/aty/atyfb_base.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/video/fsl,imx-fb.txt       |    1 +
+ arch/arm/mach-imx/mach-mx27ads.c                   |   55 +-
+ arch/arm/mach-omap2/display.c                      |    1 -
+ drivers/Makefile                                   |    4 +-
+ drivers/video/Kconfig                              | 2487 +-------------------
+ drivers/video/Makefile                             |  168 +-
+ drivers/video/console/fbcon.c                      |   27 +-
+ 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         |    7 +-
+ drivers/video/{ => fbdev}/aty/mach64_accel.c       |    3 +-
+ drivers/video/{ => fbdev}/aty/mach64_ct.c          |    0
+ drivers/video/{ => fbdev}/aty/mach64_cursor.c      |   22 +-
+ 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       |  153 +-
+ 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               |   22 +-
+ 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           |    2 +-
+ drivers/video/{ => fbdev}/exynos/Makefile          |    0
+ drivers/video/{ => fbdev}/exynos/exynos_dp_core.c  |    0
+ drivers/video/{ => fbdev}/exynos/exynos_dp_core.h  |    0
+ drivers/video/{ => fbdev}/exynos/exynos_dp_reg.c   |    0
+ drivers/video/{ => fbdev}/exynos/exynos_dp_reg.h   |    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         |   13 +-
+ 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                  |  377 ++-
+ 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  |   38 +-
+ drivers/video/{ => fbdev}/matrox/matroxfb_accel.h  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_base.c   |    3 +-
+ drivers/video/{ => fbdev}/matrox/matroxfb_base.h   |    2 +
+ 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        |   24 +-
+ 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.c          |   16 -
+ drivers/video/{ => fbdev}/omap2/dss/dss.h          |    2 -
+ 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}/sgivwfb.c                |    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                  |  288 +--
+ 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               |   15 +-
+ drivers/video/omap2/Kconfig                        |   10 -
+ include/linux/platform_data/video-imxfb.h          |   12 -
+ include/linux/xilinxfb.h                           |   30 -
+ include/video/omapdss.h                            |    1 -
+ 487 files changed, 3149 insertions(+), 3306 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 (99%)
+ rename drivers/video/{ => fbdev}/aty/mach64_accel.c (99%)
+ rename drivers/video/{ => fbdev}/aty/mach64_ct.c (100%)
+ rename drivers/video/{ => fbdev}/aty/mach64_cursor.c (90%)
+ 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 (78%)
+ 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 (99%)
+ 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 (96%)
+ rename drivers/video/{ => fbdev}/exynos/Makefile (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_dp_core.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_dp_core.h (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_dp_reg.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_dp_reg.h (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 (98%)
+ 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 (81%)
+ 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 (95%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_accel.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_base.c (99%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_base.h (99%)
+ 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 (99%)
+ 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.c (98%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss.h (99%)
+ 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}/sgivwfb.c (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 (87%)
+ 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 (96%)
+ delete mode 100644 drivers/video/omap2/Kconfig
+ delete mode 100644 include/linux/xilinxfb.h
+$ git am -3 ../patches/0001-video-staging-fixup-for-drivers-movement.patch
+Applying: video: staging fixup for drivers movement
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/staging/xgifb/vb_def.h
+M	drivers/staging/xgifb/vb_struct.h
+M	drivers/staging/xgifb/vgatypes.h
+$ git add -A .
+$ git commit -v -a --amend
+[master e0ff255e4761] Merge remote-tracking branch 'omap_dss2/for-next'
+Merging regulator/for-next (9e90ea8166d1 Merge remote-tracking branches 'regulator/topic/tps65217', 'regulator/topic/tps65218', 'regulator/topic/tps6524x', 'regulator/topic/tps6586x', 'regulator/topic/tps65910', 'regulator/topic/tps80031', 'regulator/topic/wm831x', 'regulator/topic/wm8350' and 'regulator/topic/wm8994' into regulator-next)
+$ git merge regulator/for-next
+Merge made by the 'recursive' strategy.
+ .../bindings/regulator/gpio-regulator.txt          |   4 +
+ .../bindings/regulator/s5m8767-regulator.txt       |  13 +-
+ .../bindings/regulator/ti-abb-regulator.txt        |   6 +-
+ drivers/base/devres.c                              |  26 ++
+ drivers/of/base.c                                  |  32 +++
+ drivers/regulator/88pm800.c                        |   4 +-
+ drivers/regulator/88pm8607.c                       |   8 +-
+ drivers/regulator/Kconfig                          |   9 +
+ drivers/regulator/Makefile                         |   1 +
+ drivers/regulator/act8865-regulator.c              |   8 +-
+ drivers/regulator/anatop-regulator.c               | 115 ++++++++-
+ drivers/regulator/arizona-ldo1.c                   |   4 +-
+ drivers/regulator/arizona-micsupp.c                |   4 +-
+ drivers/regulator/as3711-regulator.c               |  15 +-
+ drivers/regulator/as3722-regulator.c               |   1 +
+ drivers/regulator/core.c                           |  62 +++--
+ drivers/regulator/da9052-regulator.c               |  29 ++-
+ drivers/regulator/da9055-regulator.c               |  69 ++++-
+ drivers/regulator/da9063-regulator.c               |  11 +-
+ drivers/regulator/da9210-regulator.c               |   5 +-
+ drivers/regulator/dbx500-prcmu.c                   |  10 +-
+ drivers/regulator/dummy.c                          |   6 +-
+ drivers/regulator/fan53555.c                       |  13 +-
+ drivers/regulator/fixed.c                          |  46 +---
+ drivers/regulator/gpio-regulator.c                 |  34 ++-
+ drivers/regulator/lp3971.c                         |   2 +-
+ drivers/regulator/lp872x.c                         |   4 +-
+ drivers/regulator/max14577.c                       |   8 +-
+ drivers/regulator/max77686.c                       |   6 +-
+ drivers/regulator/max77693.c                       |   7 +-
+ drivers/regulator/max8660.c                        |   3 +-
+ drivers/regulator/max8907-regulator.c              |   7 +-
+ drivers/regulator/max8925-regulator.c              |   4 +-
+ drivers/regulator/max8952.c                        |   4 +-
+ drivers/regulator/max8973-regulator.c              |   4 +-
+ drivers/regulator/max8997.c                        |   3 +-
+ drivers/regulator/max8998.c                        |   7 +-
+ drivers/regulator/mc13xxx-regulator-core.c         |  12 +-
+ drivers/regulator/pfuze100-regulator.c             |   8 +-
+ drivers/regulator/rc5t583-regulator.c              |  13 +-
+ drivers/regulator/s2mps11.c                        |  89 +++++--
+ drivers/regulator/s5m8767.c                        |  97 ++++++-
+ drivers/regulator/ti-abb-regulator.c               | 140 +++++-----
+ drivers/regulator/tps51632-regulator.c             |   8 +-
+ drivers/regulator/tps62360-regulator.c             |   9 +-
+ drivers/regulator/tps6507x-regulator.c             |  29 +--
+ drivers/regulator/tps65090-regulator.c             |  13 +-
+ drivers/regulator/tps65217-regulator.c             |  17 +-
+ drivers/regulator/tps65218-regulator.c             | 285 +++++++++++++++++++++
+ drivers/regulator/tps6524x-regulator.c             |   5 +-
+ drivers/regulator/tps6586x-regulator.c             |   8 +-
+ drivers/regulator/tps65910-regulator.c             |  21 +-
+ drivers/regulator/tps80031-regulator.c             |   4 +-
+ drivers/regulator/wm831x-dcdc.c                    |  16 +-
+ drivers/regulator/wm831x-isink.c                   |   4 +-
+ drivers/regulator/wm831x-ldo.c                     |  12 +-
+ drivers/regulator/wm8350-regulator.c               |   4 +-
+ drivers/regulator/wm8994-regulator.c               |   4 +-
+ include/linux/device.h                             |   1 +
+ include/linux/mfd/samsung/core.h                   |   3 +-
+ include/linux/mfd/samsung/s5m8767.h                |   7 +
+ include/linux/of.h                                 |  76 ++++++
+ 62 files changed, 1086 insertions(+), 393 deletions(-)
+ create mode 100644 drivers/regulator/tps65218-regulator.c
+Merging security/next (864f32a52b53 kernel: Mark function as static in kernel/seccomp.c)
+$ git merge security/next
+Auto-merging security/selinux/hooks.c
+Auto-merging kernel/capability.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                              |  5 ++---
+ kernel/capability.c                      | 29 ++++++++++-------------------
+ kernel/seccomp.c                         |  2 +-
+ security/Makefile                        | 12 ++++++------
+ security/apparmor/lsm.c                  |  2 +-
+ security/integrity/Makefile              |  4 ++--
+ security/integrity/ima/ima_policy.c      |  6 +++---
+ security/integrity/integrity_audit.c     |  2 +-
+ security/keys/encrypted-keys/encrypted.c |  2 +-
+ security/keys/trusted.c                  |  6 +++---
+ security/selinux/hooks.c                 |  4 ++--
+ security/selinux/selinuxfs.c             |  2 +-
+ 12 files changed, 33 insertions(+), 43 deletions(-)
+Merging selinux/next (0909c0ae999c selinux: put the mmap() DAC controls before the MAC controls)
+$ git merge selinux/next
+Auto-merging security/selinux/hooks.c
+Merge made by the 'recursive' strategy.
+ security/selinux/hooks.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+Merging lblnet/next (d8ec26d7f828 Linux 3.13)
+$ git merge lblnet/next
+Already up-to-date.
+Merging watchdog/master (db5dd336cb23 watchdog: orion: prepare new Dove DT Kconfig variable)
+$ git merge watchdog/master
+Resolved 'drivers/watchdog/Kconfig' using previous resolution.
+Resolved 'drivers/watchdog/orion_wdt.c' using previous resolution.
+Auto-merging drivers/watchdog/orion_wdt.c
+CONFLICT (content): Merge conflict in drivers/watchdog/orion_wdt.c
+Auto-merging drivers/watchdog/Kconfig
+CONFLICT (content): Merge conflict in drivers/watchdog/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 7e415e531661] Merge remote-tracking branch 'watchdog/master'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/watchdog/of-xilinx-wdt.txt |  23 ++
+ Documentation/watchdog/watchdog-parameters.txt     |   5 +
+ drivers/watchdog/Kconfig                           |  34 +-
+ drivers/watchdog/Makefile                          |   1 +
+ drivers/watchdog/ar7_wdt.c                         |   1 -
+ drivers/watchdog/at32ap700x_wdt.c                  |   4 +-
+ drivers/watchdog/ath79_wdt.c                       |   1 -
+ drivers/watchdog/bcm2835_wdt.c                     |   4 +-
+ drivers/watchdog/bcm47xx_wdt.c                     |   1 -
+ drivers/watchdog/bcm63xx_wdt.c                     |   2 -
+ drivers/watchdog/cpu5wdt.c                         |   1 -
+ drivers/watchdog/cpwd.c                            |   1 -
+ drivers/watchdog/da9052_wdt.c                      |   1 -
+ drivers/watchdog/da9055_wdt.c                      |   4 +-
+ drivers/watchdog/davinci_wdt.c                     |   1 -
+ drivers/watchdog/ep93xx_wdt.c                      |  19 +-
+ drivers/watchdog/hpwdt.c                           |   1 -
+ drivers/watchdog/i6300esb.c                        |   1 -
+ drivers/watchdog/iTCO_wdt.c                        |   6 +-
+ drivers/watchdog/ibmasr.c                          |   2 +-
+ drivers/watchdog/indydog.c                         |  13 +-
+ drivers/watchdog/intel_scu_watchdog.c              |   4 +-
+ drivers/watchdog/jz4740_wdt.c                      |   1 -
+ drivers/watchdog/max63xx_wdt.c                     |   1 -
+ drivers/watchdog/mpc8xxx_wdt.c                     |   1 +
+ drivers/watchdog/mtx-1_wdt.c                       |   1 -
+ drivers/watchdog/nuc900_wdt.c                      |   1 -
+ drivers/watchdog/of_xilinx_wdt.c                   | 390 ++++++---------------
+ drivers/watchdog/omap_wdt.c                        |  23 +-
+ drivers/watchdog/orion_wdt.c                       |   1 -
+ drivers/watchdog/pc87413_wdt.c                     |   7 +-
+ drivers/watchdog/pcwd_usb.c                        |   4 +-
+ drivers/watchdog/pnx4008_wdt.c                     |   1 -
+ drivers/watchdog/rdc321x_wdt.c                     |   1 -
+ drivers/watchdog/retu_wdt.c                        |   1 -
+ drivers/watchdog/riowd.c                           |   1 -
+ drivers/watchdog/s3c2410_wdt.c                     |   1 -
+ drivers/watchdog/sc520_wdt.c                       |   3 +-
+ drivers/watchdog/shwdt.c                           |   2 -
+ drivers/watchdog/softdog.c                         |   2 +-
+ drivers/watchdog/sp805_wdt.c                       |  19 +-
+ drivers/watchdog/stmp3xxx_rtc_wdt.c                |   1 -
+ drivers/watchdog/tegra_wdt.c                       | 302 ++++++++++++++++
+ drivers/watchdog/ts72xx_wdt.c                      |   6 +-
+ drivers/watchdog/w83697hf_wdt.c                    |   4 +-
+ drivers/watchdog/wdt285.c                          |   3 +-
+ drivers/watchdog/wdt_pci.c                         |   1 -
+ drivers/watchdog/wm831x_wdt.c                      |   1 -
+ 48 files changed, 505 insertions(+), 404 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
+ create mode 100644 drivers/watchdog/tegra_wdt.c
+Merging dwmw2-iommu/master (e5d0c874391a Merge tag 'iommu-updates-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu)
+$ git merge dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (972157cac528 arm/smmu: Use irqsafe spinlock for domain lock)
+$ git merge iommu/next
+Already up-to-date.
+Merging vfio/next (9d830d47c7a7 kvm/vfio: Support for DMA coherent IOMMUs)
+$ git merge vfio/next
+Merge made by the 'recursive' strategy.
+ drivers/vfio/vfio.c             |   6 +
+ drivers/vfio/vfio_iommu_type1.c | 656 ++++++++++++++++++++++------------------
+ include/linux/vfio.h            |   2 +
+ include/uapi/linux/vfio.h       |   6 +
+ virt/kvm/vfio.c                 |  27 +-
+ 5 files changed, 389 insertions(+), 308 deletions(-)
+Merging osd/linux-next (19350e7627a6 exofs: Print less in r4w)
+$ 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 (80dd6eac0090 net-sysfs: fix comment typo 'CONFIG_SYFS')
+$ git merge trivial/for-next
+Auto-merging net/core/net-sysfs.c
+Auto-merging net/core/dev.c
+Auto-merging include/net/mac80211.h
+Auto-merging include/linux/skbuff.h
+Auto-merging include/linux/idr.h
+Auto-merging include/drm/drm_fb_helper.h
+Auto-merging drivers/regulator/core.c
+Auto-merging drivers/ata/libata-core.c
+Merge made by the 'recursive' strategy.
+ CREDITS                                       |  4 ++--
+ Documentation/filesystems/hfsplus.txt         |  2 +-
+ Documentation/module-signing.txt              | 10 +++++-----
+ arch/arc/Kconfig                              |  1 -
+ arch/cris/arch-v32/drivers/Kconfig            |  2 --
+ arch/s390/include/asm/cio.h                   |  2 +-
+ block/blk-core.c                              |  2 +-
+ block/blk-map.c                               |  2 +-
+ drivers/ata/libata-core.c                     |  4 ++--
+ drivers/base/bus.c                            |  2 +-
+ drivers/gpu/drm/drm_crtc_helper.c             |  2 +-
+ drivers/input/sparse-keymap.c                 |  2 +-
+ drivers/misc/mic/Kconfig                      |  2 --
+ drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c |  2 +-
+ drivers/regulator/core.c                      |  2 +-
+ drivers/scsi/scsi_transport_iscsi.c           |  6 +++---
+ drivers/staging/android/Kconfig               |  2 --
+ drivers/staging/bcm/Kconfig                   |  1 -
+ drivers/staging/frontier/Kconfig              |  1 -
+ drivers/staging/media/go7007/Kconfig          |  3 ---
+ drivers/staging/rtl8187se/Kconfig             |  1 -
+ drivers/staging/rtl8188eu/Kconfig             |  1 -
+ drivers/staging/rtl8192e/rtl8192e/Kconfig     |  1 -
+ drivers/staging/rtl8192u/Kconfig              |  1 -
+ drivers/staging/rtl8712/Kconfig               |  2 --
+ drivers/staging/usbip/Kconfig                 |  4 ----
+ drivers/usb/core/Kconfig                      |  1 -
+ drivers/usb/core/message.c                    |  2 +-
+ drivers/usb/core/urb.c                        |  2 +-
+ drivers/usb/host/Kconfig                      |  3 ---
+ fs/buffer.c                                   |  2 +-
+ fs/debugfs/inode.c                            |  6 +++---
+ include/drm/drm_fb_helper.h                   |  2 +-
+ include/linux/gpio.h                          |  2 +-
+ include/linux/hsi/hsi.h                       |  2 +-
+ include/linux/idr.h                           |  1 -
+ include/linux/kfifo.h                         |  2 +-
+ include/linux/pipe_fs_i.h                     |  2 +-
+ include/linux/platform_data/ata-samsung_cf.h  |  9 ++++-----
+ include/linux/skbuff.h                        |  2 +-
+ include/linux/spi/spi.h                       |  8 ++++----
+ include/linux/usb/composite.h                 |  2 +-
+ include/net/mac80211.h                        |  6 +++---
+ kernel/relay.c                                |  2 +-
+ kernel/signal.c                               |  2 +-
+ net/core/dev.c                                |  2 +-
+ net/core/net-sysfs.c                          |  2 +-
+ 47 files changed, 49 insertions(+), 77 deletions(-)
+Merging audit/master (f3411cb2b2e3 audit: whitespace fix in kernel-parameters.txt)
+$ git merge audit/master
+Already up-to-date.
+Merging fsnotify/for-next (1ca39ab9d21a inotify: automatically restart syscalls)
+$ git merge fsnotify/for-next
+Already up-to-date.
+Merging devicetree/devicetree/next (f4d4ffc03efc kbuild: dtbs_install: new make target)
+$ git merge devicetree/devicetree/next
+Resolved 'drivers/of/of_net.c' using previous resolution.
+Auto-merging scripts/Makefile.lib
+Auto-merging include/linux/of.h
+Auto-merging drivers/of/of_net.c
+CONFLICT (content): Merge conflict in drivers/of/of_net.c
+Auto-merging drivers/of/base.c
+Auto-merging drivers/of/address.c
+Auto-merging arch/arm/mach-mvebu/Kconfig
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Makefile
+Auto-merging Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 081f5ea193a5] Merge remote-tracking branch 'devicetree/devicetree/next'
+$ git diff -M --stat --summary HEAD^..
+ Makefile                             |   7 +
+ arch/arm/Makefile                    |   7 +-
+ arch/arm/boot/dts/Makefile           |   4 +-
+ arch/arm/mach-mvebu/Kconfig          |   1 +
+ drivers/of/Kconfig                   |   4 +
+ drivers/of/address.c                 |   8 +-
+ drivers/of/base.c                    |  75 +++---
+ drivers/of/of_net.c                  |   7 +-
+ include/linux/of.h                   |  22 +-
+ scripts/Makefile.lib                 |  12 +
+ scripts/dtc/dtc-parser.tab.c_shipped | 469 +++++++++++++++--------------------
+ scripts/dtc/dtc-parser.tab.h_shipped |  36 ++-
+ scripts/dtc/dtc.c                    | 119 +++++----
+ scripts/dtc/dtc.h                    |   1 -
+ scripts/dtc/srcpos.c                 |   6 +-
+ scripts/dtc/update-dtc-source.sh     |  54 ++++
+ scripts/dtc/util.c                   | 141 ++++++++++-
+ scripts/dtc/util.h                   | 107 +++++++-
+ scripts/dtc/version_gen.h            |   2 +-
+ 19 files changed, 671 insertions(+), 411 deletions(-)
+ create mode 100755 scripts/dtc/update-dtc-source.sh
+Merging dt-rh/for-next (06b29e76a74b of: search the best compatible match first in __of_match_node())
+$ git merge dt-rh/for-next
+Already up-to-date.
+Merging spi/for-next (d4127e50a72f Merge remote-tracking branches 'spi/topic/tegra114', 'spi/topic/topcliff-pch', 'spi/topic/txx9', 'spi/topic/xfer' and 'spi/topic/xilinx' into spi-next)
+$ git merge spi/for-next
+Auto-merging include/linux/spi/spi.h
+Auto-merging drivers/spi/spi-au1550.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/spi/qcom,spi-qup.txt       |  85 +++
+ Documentation/devicetree/bindings/spi/sh-msiof.txt |  43 +-
+ .../devicetree/bindings/spi/spi-fsl-dspi.txt       |   2 +
+ Documentation/devicetree/bindings/spi/spi-rspi.txt |  61 ++
+ .../devicetree/bindings/spi/spi-sun4i.txt          |  24 +
+ .../devicetree/bindings/spi/spi-sun6i.txt          |  24 +
+ Documentation/spi/spidev                           |   6 +
+ Documentation/spi/spidev_fdx.c                     |   8 +-
+ Documentation/spi/spidev_test.c                    |  45 +-
+ drivers/spi/Kconfig                                |  33 +-
+ drivers/spi/Makefile                               |   3 +
+ drivers/spi/spi-altera.c                           |   1 -
+ drivers/spi/spi-ath79.c                            |   1 -
+ drivers/spi/spi-atmel.c                            |  19 -
+ drivers/spi/spi-au1550.c                           |  30 +-
+ drivers/spi/spi-bcm2835.c                          |   1 -
+ drivers/spi/spi-bcm63xx-hsspi.c                    |   3 +-
+ drivers/spi/spi-bcm63xx.c                          |   4 +-
+ drivers/spi/spi-bfin-sport.c                       |   1 -
+ drivers/spi/spi-bfin-v3.c                          |   3 +-
+ drivers/spi/spi-bfin5xx.c                          |   8 -
+ drivers/spi/spi-bitbang.c                          |   1 -
+ drivers/spi/spi-clps711x.c                         | 142 ++--
+ drivers/spi/spi-coldfire-qspi.c                    | 101 +--
+ drivers/spi/spi-davinci.c                          |  14 +-
+ drivers/spi/spi-dw-mmio.c                          |   2 +-
+ drivers/spi/spi-dw.c                               |   3 +-
+ drivers/spi/spi-efm32.c                            |   7 +-
+ drivers/spi/spi-ep93xx.c                           |  21 +-
+ drivers/spi/spi-falcon.c                           |   5 -
+ drivers/spi/spi-fsl-dspi.c                         |  88 ++-
+ drivers/spi/spi-fsl-spi.c                          |  30 +-
+ drivers/spi/spi-gpio.c                             |   3 +-
+ drivers/spi/spi-imx.c                              |  11 +-
+ drivers/spi/spi-mpc512x-psc.c                      |  17 +-
+ drivers/spi/spi-mpc52xx-psc.c                      |   1 -
+ drivers/spi/spi-mpc52xx.c                          |   4 -
+ drivers/spi/spi-mxs.c                              |   7 +-
+ drivers/spi/spi-nuc900.c                           |  10 +-
+ drivers/spi/spi-oc-tiny.c                          |   1 -
+ drivers/spi/spi-octeon.c                           |  80 +-
+ drivers/spi/spi-omap-100k.c                        |  16 -
+ drivers/spi/spi-omap-uwire.c                       |  24 +-
+ drivers/spi/spi-omap2-mcspi.c                      |  65 +-
+ drivers/spi/spi-orion.c                            |  80 +-
+ drivers/spi/spi-pl022.c                            |  26 +-
+ drivers/spi/spi-ppc4xx.c                           |   1 -
+ drivers/spi/spi-pxa2xx-dma.c                       |   1 -
+ drivers/spi/spi-pxa2xx-pxadma.c                    |   1 -
+ drivers/spi/spi-pxa2xx.c                           |   3 +-
+ drivers/spi/spi-qup.c                              | 779 +++++++++++++++++++
+ drivers/spi/spi-rspi.c                             | 844 ++++++++++++++-------
+ drivers/spi/spi-s3c24xx.c                          |  12 +-
+ drivers/spi/spi-s3c64xx.c                          | 424 +++--------
+ drivers/spi/spi-sc18is602.c                        |  16 +-
+ drivers/spi/spi-sh-hspi.c                          |  39 +-
+ drivers/spi/spi-sh-msiof.c                         | 382 ++++++----
+ drivers/spi/spi-sh-sci.c                           |   1 -
+ drivers/spi/spi-sirf.c                             | 109 +--
+ drivers/spi/spi-sun4i.c                            | 477 ++++++++++++
+ drivers/spi/spi-sun6i.c                            | 483 ++++++++++++
+ drivers/spi/spi-tegra114.c                         |  27 +-
+ drivers/spi/spi-tegra20-sflash.c                   |  26 +-
+ drivers/spi/spi-tegra20-slink.c                    |  20 +-
+ drivers/spi/spi-ti-qspi.c                          |   4 +-
+ drivers/spi/spi-topcliff-pch.c                     |  55 +-
+ drivers/spi/spi-txx9.c                             |  25 +-
+ drivers/spi/spi-xcomm.c                            |   1 -
+ drivers/spi/spi-xilinx.c                           |  27 +-
+ drivers/spi/spi.c                                  | 225 +++++-
+ drivers/spi/spidev.c                               |  23 +-
+ include/linux/platform_data/spi-s3c64xx.h          |   9 +-
+ include/linux/spi/spi.h                            |  31 +
+ include/uapi/linux/spi/spidev.h                    |  14 +-
+ 74 files changed, 3600 insertions(+), 1623 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-rspi.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-sun4i.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
+ create mode 100644 drivers/spi/spi-qup.c
+ create mode 100644 drivers/spi/spi-sun4i.c
+ create mode 100644 drivers/spi/spi-sun6i.c
+Merging tip/auto-latest (05c0f92abb17 Merge branch 'x86/x32')
+$ git merge tip/auto-latest
+Recorded preimage for 'drivers/video/Kconfig'
+Recorded preimage for 'drivers/video/Makefile'
+Resolved 'drivers/pci/Makefile' using previous resolution.
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE09
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE08
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE07
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE06
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE05
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE04
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE03
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE02
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TREE01
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TINY02
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/TINY01
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
+Auto-merging tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
+Auto-merging tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+Auto-merging tools/perf/util/unwind-libunwind.c
+Removing tools/perf/util/include/linux/prefetch.h
+Removing tools/perf/util/include/linux/hash.h
+Removing tools/perf/util/fs.h
+Auto-merging tools/perf/arch/x86/util/unwind-libunwind.c
+Auto-merging tools/perf/arch/arm/util/unwind-libunwind.c
+Auto-merging tools/lib/api/fs/fs.h
+Auto-merging tools/lib/api/fs/fs.c
+Removing sound/oss/vwsnd.c
+Auto-merging scripts/mod/modpost.c
+Auto-merging kernel/sched/idle.c
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/rcu/rcutorture.c
+Auto-merging kernel/module.c
+Removing kernel/cpu/Makefile
+Removing include/video/sgivw.h
+Auto-merging fs/compat.c
+CONFLICT (rename/delete): drivers/video/fbdev/sgivwfb.c deleted in tip/auto-latest and renamed in HEAD. Version HEAD of drivers/video/fbdev/sgivwfb.c left in tree.
+Auto-merging drivers/video/fbdev/gbefb.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
+Auto-merging drivers/pci/Makefile
+CONFLICT (content): Merge conflict in drivers/pci/Makefile
+Auto-merging drivers/irqchip/Makefile
+Removing drivers/clocksource/cyclone.c
+Auto-merging drivers/clocksource/Makefile
+Removing arch/x86/platform/visws/visws_quirks.c
+Removing arch/x86/platform/visws/Makefile
+CONFLICT (modify/delete): arch/x86/pci/visws.c deleted in tip/auto-latest and modified in HEAD. Version HEAD of arch/x86/pci/visws.c left in tree.
+CONFLICT (modify/delete): arch/x86/pci/numaq_32.c deleted in tip/auto-latest and modified in HEAD. Version HEAD of arch/x86/pci/numaq_32.c left in tree.
+Auto-merging arch/x86/pci/common.c
+Removing arch/x86/kernel/apic/summit_32.c
+Removing arch/x86/kernel/apic/numaq_32.c
+Removing arch/x86/kernel/apic/es7000_32.c
+Auto-merging arch/x86/kernel/acpi/boot.c
+Removing arch/x86/include/asm/visws/sgivw.h
+Removing arch/x86/include/asm/visws/piix4.h
+Removing arch/x86/include/asm/visws/lithium.h
+Removing arch/x86/include/asm/visws/cobalt.h
+Removing arch/x86/include/asm/numaq.h
+Auto-merging arch/s390/Kconfig
+Auto-merging arch/hexagon/include/asm/Kbuild
+Auto-merging arch/arm64/kernel/process.c
+Auto-merging arch/arm/kernel/process.c
+Auto-merging MAINTAINERS
+Removing Documentation/sound/oss/vwsnd
+Removing Documentation/sgi-visws.txt
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f arch/x86/pci/numaq_32.c arch/x86/pci/visws.c drivers/video/fbdev/sgivwfb.c
+arch/x86/pci/numaq_32.c: needs merge
+arch/x86/pci/visws.c: needs merge
+drivers/video/fbdev/sgivwfb.c: needs merge
+rm 'arch/x86/pci/numaq_32.c'
+rm 'arch/x86/pci/visws.c'
+rm 'drivers/video/fbdev/sgivwfb.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/video/Kconfig'.
+Recorded resolution for 'drivers/video/Makefile'.
+[master 2db7d3f21d74] Merge remote-tracking branch 'tip/auto-latest'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/00-INDEX                             |    2 -
+ Documentation/RCU/RTFP.txt                         |  149 +-
+ Documentation/RCU/checklist.txt                    |   18 +-
+ .../interrupt-controller/marvell,dove-pmu-intc.txt |   17 +
+ Documentation/kernel-parameters.txt                |    4 +-
+ Documentation/kernel-per-CPU-kthreads.txt          |   13 +-
+ Documentation/memory-barriers.txt                  |  137 +-
+ Documentation/sgi-visws.txt                        |   13 -
+ Documentation/sound/oss/vwsnd                      |  293 --
+ Documentation/sysctl/kernel.txt                    |   15 +-
+ MAINTAINERS                                        |    7 -
+ arch/alpha/include/asm/Kbuild                      |    7 +-
+ arch/arc/include/asm/Kbuild                        |    7 +-
+ arch/arm/include/asm/Kbuild                        |    5 +-
+ arch/arm/kernel/process.c                          |   16 +-
+ arch/arm64/include/asm/Kbuild                      |    7 +-
+ arch/arm64/kernel/process.c                        |    7 +-
+ arch/avr32/include/asm/Kbuild                      |   41 +-
+ arch/blackfin/include/asm/Kbuild                   |    7 +-
+ arch/c6x/include/asm/Kbuild                        |    5 +-
+ arch/cris/include/asm/Kbuild                       |    3 +-
+ arch/frv/include/asm/Kbuild                        |    5 +-
+ arch/hexagon/include/asm/Kbuild                    |    5 +-
+ arch/ia64/include/asm/Kbuild                       |    5 +-
+ arch/m32r/include/asm/Kbuild                       |    5 +-
+ arch/m68k/include/asm/Kbuild                       |    3 +-
+ arch/metag/include/asm/Kbuild                      |    5 +-
+ arch/microblaze/include/asm/Kbuild                 |    5 +-
+ arch/mips/include/asm/Kbuild                       |    5 +-
+ arch/mn10300/include/asm/Kbuild                    |    3 +-
+ arch/openrisc/include/asm/Kbuild                   |   11 +-
+ arch/parisc/include/asm/Kbuild                     |   32 +-
+ arch/powerpc/include/asm/Kbuild                    |    5 +-
+ arch/powerpc/platforms/cell/spufs/sched.c          |    1 -
+ arch/powerpc/platforms/powernv/setup.c             |   13 +-
+ arch/powerpc/platforms/pseries/setup.c             |   34 +-
+ arch/s390/Kconfig                                  |    1 +
+ arch/s390/include/asm/Kbuild                       |    5 +-
+ arch/score/include/asm/Kbuild                      |    5 +-
+ arch/sh/include/asm/Kbuild                         |    9 +-
+ arch/sh/kernel/idle.c                              |    4 +-
+ arch/sparc/include/asm/Kbuild                      |   11 +-
+ arch/tile/include/asm/Kbuild                       |    5 +-
+ arch/um/include/asm/Kbuild                         |   34 +-
+ arch/unicore32/include/asm/Kbuild                  |    5 +-
+ arch/x86/Kconfig                                   |   87 +-
+ arch/x86/Kconfig.cpu                               |    2 +-
+ arch/x86/Makefile                                  |    4 +-
+ arch/x86/include/asm/Kbuild                        |    1 +
+ arch/x86/include/asm/apic.h                        |   14 +-
+ arch/x86/include/asm/cpufeature.h                  |    9 +-
+ arch/x86/include/asm/fixmap.h                      |    6 -
+ arch/x86/include/asm/hw_irq.h                      |    1 -
+ arch/x86/include/asm/iosf_mbi.h                    |   33 +
+ arch/x86/include/asm/mmzone_32.h                   |    3 -
+ arch/x86/include/asm/mpspec.h                      |    6 -
+ arch/x86/include/asm/nmi.h                         |    3 +
+ arch/x86/include/asm/numaq.h                       |  171 -
+ arch/x86/include/asm/setup.h                       |    6 -
+ arch/x86/include/asm/special_insns.h               |    8 +
+ arch/x86/include/asm/visws/cobalt.h                |  127 -
+ arch/x86/include/asm/visws/lithium.h               |   53 -
+ arch/x86/include/asm/visws/piix4.h                 |  107 -
+ arch/x86/include/asm/visws/sgivw.h                 |    5 -
+ arch/x86/include/asm/xsave.h                       |   16 +-
+ arch/x86/kernel/acpi/boot.c                        |   20 +-
+ arch/x86/kernel/apic/Makefile                      |    3 -
+ arch/x86/kernel/apic/apic.c                        |   10 +-
+ arch/x86/kernel/apic/apic_flat_64.c                |    4 +-
+ arch/x86/kernel/apic/apic_noop.c                   |    3 +-
+ arch/x86/kernel/apic/apic_numachip.c               |    2 +-
+ arch/x86/kernel/apic/bigsmp_32.c                   |    3 +-
+ arch/x86/kernel/apic/es7000_32.c                   |  746 -----
+ arch/x86/kernel/apic/numaq_32.c                    |  525 ---
+ arch/x86/kernel/apic/probe_32.c                    |    3 +-
+ arch/x86/kernel/apic/summit_32.c                   |  551 ---
+ arch/x86/kernel/apic/x2apic_cluster.c              |    2 +-
+ arch/x86/kernel/apic/x2apic_phys.c                 |    2 +-
+ arch/x86/kernel/apic/x2apic_uv_x.c                 |    2 +-
+ arch/x86/kernel/cpu/common.c                       |    3 +-
+ arch/x86/kernel/cpu/intel.c                        |    4 -
+ arch/x86/kernel/cpu/perf_event.c                   |   47 +-
+ arch/x86/kernel/cpu/perf_event.h                   |    8 +-
+ arch/x86/kernel/cpu/perf_event_intel_uncore.c      |  540 ++-
+ arch/x86/kernel/cpu/perf_event_intel_uncore.h      |    5 +
+ arch/x86/kernel/cpu/perf_event_p4.c                |   34 +-
+ arch/x86/kernel/early-quirks.c                     |  211 +-
+ arch/x86/kernel/iosf_mbi.c                         |    6 +
+ arch/x86/kernel/module.c                           |   43 +-
+ arch/x86/kernel/nmi.c                              |   37 +-
+ arch/x86/kernel/process.c                          |    5 +-
+ arch/x86/kernel/setup.c                            |    1 -
+ arch/x86/kernel/smpboot.c                          |    7 +-
+ arch/x86/kernel/time.c                             |    2 +-
+ arch/x86/kvm/cpuid.c                               |    2 +-
+ arch/x86/lib/memcpy_32.c                           |    6 +-
+ arch/x86/mm/numa.c                                 |    4 -
+ arch/x86/mm/pageattr.c                             |    8 +-
+ arch/x86/mm/srat.c                                 |   12 +-
+ arch/x86/pci/Makefile                              |    3 -
+ arch/x86/pci/common.c                              |    5 +-
+ arch/x86/pci/numaq_32.c                            |  165 -
+ arch/x86/pci/visws.c                               |   87 -
+ arch/x86/platform/Makefile                         |    1 -
+ arch/x86/platform/ts5500/ts5500.c                  |    2 +-
+ arch/x86/platform/visws/Makefile                   |    1 -
+ arch/x86/platform/visws/visws_quirks.c             |  608 ----
+ arch/x86/vdso/Makefile                             |   10 +-
+ arch/x86/xen/Kconfig                               |    2 +-
+ arch/xtensa/include/asm/Kbuild                     |    5 +-
+ drivers/clocksource/Makefile                       |    1 -
+ drivers/clocksource/cyclone.c                      |  113 -
+ drivers/cpuidle/cpuidle-powernv.c                  |    5 +
+ drivers/cpuidle/cpuidle-pseries.c                  |    6 +
+ drivers/cpuidle/cpuidle.c                          |   14 +-
+ drivers/firmware/dcdbas.c                          |    2 +-
+ drivers/gpu/drm/drm_cache.c                        |   10 +-
+ drivers/gpu/drm/gma500/mmu.c                       |    2 +-
+ drivers/irqchip/Makefile                           |    1 +
+ drivers/irqchip/irq-dove.c                         |  126 +
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c      |    2 +-
+ drivers/pci/Makefile                               |    1 -
+ drivers/pnp/pnpbios/bioscalls.c                    |    9 +-
+ drivers/scsi/qla1280.c                             |    7 -
+ drivers/tty/tty_ldsem.c                            |   15 +-
+ drivers/video/fbdev/gbefb.c                        |    4 -
+ drivers/video/fbdev/sgivwfb.c                      |  889 -----
+ drivers/video/logo/Kconfig                         |    2 +-
+ drivers/video/logo/logo.c                          |    2 +-
+ fs/compat.c                                        |    6 +-
+ fs/file.c                                          |    2 +-
+ include/asm-generic/bitops/const_hweight.h         |   17 +-
+ include/asm-generic/mcs_spinlock.h                 |   13 +
+ include/drm/i915_drm.h                             |   20 +
+ include/linux/clockchips.h                         |   16 +-
+ include/linux/compat.h                             |   23 +-
+ include/linux/futex.h                              |    4 +
+ include/linux/hardirq.h                            |    1 +
+ include/linux/init.h                               |   20 +-
+ include/linux/interrupt.h                          |    1 +
+ include/linux/io.h                                 |    2 +-
+ include/linux/irq_work.h                           |    4 +-
+ include/linux/linkage.h                            |    4 +-
+ include/linux/lockdep.h                            |   29 +-
+ include/linux/mcs_spinlock.h                       |  114 +
+ include/linux/mutex.h                              |    5 +-
+ include/linux/pci_ids.h                            |    3 +
+ include/linux/rculist.h                            |   17 +-
+ include/linux/rcupdate.h                           |   96 +-
+ include/linux/rcutiny.h                            |   10 +-
+ include/linux/rcutree.h                            |    6 +-
+ include/linux/sched.h                              |   44 +-
+ include/linux/sched/prio.h                         |   44 +
+ include/linux/sched/rt.h                           |   26 +-
+ include/linux/srcu.h                               |    4 +-
+ include/linux/torture.h                            |  100 +
+ include/video/sgivw.h                              |  681 ----
+ init/Kconfig                                       |    7 +
+ ipc/compat.c                                       |   12 +-
+ ipc/compat_mq.c                                    |   19 +-
+ kernel/Makefile                                    |    5 +-
+ kernel/compat.c                                    |  112 +-
+ kernel/cpu/Makefile                                |    1 -
+ kernel/events/core.c                               |   39 +-
+ kernel/extable.c                                   |    2 +-
+ kernel/futex.c                                     |   37 +-
+ kernel/futex_compat.c                              |    2 +-
+ kernel/irq/handle.c                                |    4 +-
+ kernel/irq/internals.h                             |    1 +
+ kernel/irq/irqdomain.c                             |    1 +
+ kernel/irq/manage.c                                |  102 +-
+ kernel/irq_work.c                                  |    6 +-
+ kernel/ksysfs.c                                    |    2 +
+ kernel/locking/Makefile                            |    1 +
+ kernel/locking/lockdep.c                           |   23 +-
+ kernel/locking/locktorture.c                       |  452 +++
+ kernel/locking/mutex.c                             |   70 +-
+ kernel/locking/rtmutex.c                           |   12 +
+ kernel/locking/rwsem-xadd.c                        |    4 +
+ kernel/module.c                                    |    4 +
+ kernel/notifier.c                                  |    2 +-
+ kernel/panic.c                                     |    2 +-
+ kernel/rcu/Makefile                                |    2 +-
+ kernel/rcu/rcu.h                                   |    7 +-
+ kernel/rcu/{torture.c => rcutorture.c}             | 1004 ++----
+ kernel/rcu/srcu.c                                  |   11 +-
+ kernel/rcu/tiny.c                                  |    8 +-
+ kernel/rcu/tiny_plugin.h                           |    4 +-
+ kernel/rcu/tree.c                                  |   18 +-
+ kernel/rcu/tree.h                                  |    4 +-
+ kernel/rcu/tree_plugin.h                           |   19 +-
+ kernel/rcu/tree_trace.c                            |    6 +-
+ kernel/rcu/update.c                                |    5 +-
+ kernel/sched/Makefile                              |    2 +-
+ kernel/sched/auto_group.c                          |    2 +-
+ kernel/sched/core.c                                |  197 +-
+ kernel/sched/cputime.c                             |    4 +-
+ kernel/sched/deadline.c                            |   46 +-
+ kernel/sched/debug.c                               |    7 +-
+ kernel/sched/fair.c                                |  583 +++-
+ kernel/{cpu => sched}/idle.c                       |    7 +-
+ kernel/sched/idle_task.c                           |   26 +-
+ kernel/sched/rt.c                                  |   85 +-
+ kernel/sched/sched.h                               |   53 +-
+ kernel/sched/stop_task.c                           |   15 +-
+ kernel/sys.c                                       |    8 +-
+ kernel/sysctl.c                                    |    7 -
+ kernel/time/Kconfig                                |    2 +-
+ kernel/time/Makefile                               |    5 +-
+ kernel/time/clockevents.c                          |   40 +-
+ kernel/time/ntp.c                                  |    5 +-
+ kernel/time/tick-broadcast-hrtimer.c               |  106 +
+ kernel/time/tick-broadcast.c                       |   85 +-
+ kernel/time/tick-internal.h                        |   11 +-
+ kernel/timer.c                                     |   41 +-
+ kernel/torture.c                                   |  719 ++++
+ kernel/trace/ring_buffer_benchmark.c               |    6 +-
+ kernel/trace/trace_irqsoff.c                       |    4 +-
+ kernel/workqueue.c                                 |    2 +-
+ lib/Kconfig.debug                                  |   20 +
+ lib/string.c                                       |    2 +-
+ mm/mempolicy.c                                     |   74 +-
+ scripts/Kbuild.include                             |    9 +
+ scripts/Makefile.build                             |    2 +-
+ scripts/gcc-ld                                     |   29 +
+ scripts/ld-version.sh                              |    8 +
+ scripts/mod/modpost.c                              |   25 +-
+ scripts/mod/modpost.h                              |    2 +-
+ sound/oss/Kconfig                                  |    9 -
+ sound/oss/Makefile                                 |    1 -
+ sound/oss/vwsnd.c                                  | 3506 --------------------
+ tools/include/linux/hash.h                         |    5 +
+ tools/lib/api/Makefile                             |    2 +
+ tools/{perf/util => lib/api/fs}/fs.c               |   11 +-
+ .../util/include/linux/magic.h => lib/api/fs/fs.h} |   12 +-
+ tools/perf/MANIFEST                                |    1 +
+ tools/perf/Makefile.perf                           |   39 +-
+ tools/perf/arch/arm/Makefile                       |    2 +-
+ .../arch/arm/util/{unwind.c => unwind-libunwind.c} |    2 +-
+ tools/perf/arch/x86/Makefile                       |    9 +-
+ tools/perf/arch/x86/include/perf_regs.h            |    6 +
+ tools/perf/arch/x86/tests/dwarf-unwind.c           |   59 +
+ tools/perf/arch/x86/tests/regs_load.S              |   92 +
+ tools/perf/arch/x86/util/unwind-libdw.c            |   51 +
+ .../arch/x86/util/{unwind.c => unwind-libunwind.c} |    4 +-
+ tools/perf/builtin-inject.c                        |    1 -
+ tools/perf/builtin-probe.c                         |   12 +-
+ tools/perf/builtin-record.c                        |   30 +-
+ tools/perf/builtin-report.c                        |   24 +-
+ tools/perf/builtin-top.c                           |   12 +
+ tools/perf/config/Makefile                         |  232 +-
+ tools/perf/config/feature-checks/Makefile          |    6 +-
+ tools/perf/config/feature-checks/test-all.c        |    5 +
+ .../feature-checks/test-libdw-dwarf-unwind.c       |   13 +
+ tools/perf/perf.h                                  |    4 +-
+ tools/perf/tests/builtin-test.c                    |    8 +
+ tools/perf/tests/dwarf-unwind.c                    |  144 +
+ tools/perf/tests/make                              |   25 +-
+ tools/perf/tests/parse-events.c                    |    2 +-
+ tools/perf/tests/sample-parsing.c                  |   17 +-
+ tools/perf/tests/tests.h                           |    9 +
+ tools/perf/util/cpumap.c                           |    2 +-
+ tools/perf/util/dso.c                              |    4 +-
+ tools/perf/util/dso.h                              |   10 +
+ tools/perf/util/event.h                            |    5 +-
+ tools/perf/util/evsel.c                            |   17 +-
+ tools/perf/util/fs.h                               |    7 -
+ tools/perf/util/hist.c                             |    4 +-
+ tools/perf/util/include/linux/hash.h               |    5 -
+ tools/perf/util/include/linux/list.h               |    1 -
+ tools/perf/util/include/linux/prefetch.h           |    6 -
+ tools/perf/util/machine.c                          |   27 +-
+ tools/perf/util/machine.h                          |   10 +-
+ tools/perf/util/map.h                              |   10 +
+ tools/perf/util/perf_regs.c                        |   19 +
+ tools/perf/util/perf_regs.h                        |   13 +
+ tools/perf/util/pmu.c                              |    2 +-
+ tools/perf/util/probe-event.c                      |  863 ++---
+ tools/perf/util/probe-event.h                      |   12 +-
+ tools/perf/util/probe-finder.c                     |  198 +-
+ tools/perf/util/probe-finder.h                     |    5 +-
+ tools/perf/util/python-ext-sources                 |    2 +-
+ tools/perf/util/record.c                           |    2 +-
+ tools/perf/util/session.c                          |    5 +-
+ tools/perf/util/symbol-elf.c                       |    2 +
+ tools/perf/util/symbol.c                           |   63 +-
+ tools/perf/util/symbol.h                           |   12 +-
+ tools/perf/util/trace-event-parse.c                |    1 +
+ tools/perf/util/unwind-libdw.c                     |  210 ++
+ tools/perf/util/unwind-libdw.h                     |   21 +
+ tools/perf/util/{unwind.c => unwind-libunwind.c}   |   50 +-
+ tools/perf/util/unwind.h                           |   11 +-
+ tools/perf/util/util.c                             |    2 +-
+ .../testing/selftests/rcutorture/bin/functions.sh  |    1 +
+ .../selftests/rcutorture/bin/kvm-recheck-lock.sh   |   51 +
+ .../selftests/rcutorture/bin/kvm-recheck-rcu.sh    |   51 +
+ .../selftests/rcutorture/bin/kvm-recheck.sh        |   13 +-
+ .../bin/{kvm-test-1-rcu.sh => kvm-test-1-run.sh}   |   53 +-
+ tools/testing/selftests/rcutorture/bin/kvm.sh      |  276 +-
+ .../selftests/rcutorture/configs/lock/BUSTED       |    6 +
+ .../selftests/rcutorture/configs/lock/BUSTED.boot  |    1 +
+ .../selftests/rcutorture/configs/lock/CFLIST       |    1 +
+ .../selftests/rcutorture/configs/lock/CFcommon     |    2 +
+ .../selftests/rcutorture/configs/lock/LOCK01       |    6 +
+ .../rcutorture/configs/lock/ver_functions.sh       |   43 +
+ .../selftests/rcutorture/configs/rcu/BUSTED        |    7 +
+ .../selftests/rcutorture/configs/rcu/BUSTED.boot   |    1 +
+ .../selftests/rcutorture/configs/{ => rcu}/CFLIST  |    0
+ .../selftests/rcutorture/configs/rcu/CFcommon      |    2 +
+ .../selftests/rcutorture/configs/{ => rcu}/SRCU-N  |    3 +-
+ .../rcutorture/configs/{ => rcu}/SRCU-N.boot       |    0
+ .../selftests/rcutorture/configs/{ => rcu}/SRCU-P  |    1 -
+ .../rcutorture/configs/{ => rcu}/SRCU-P.boot       |    0
+ .../selftests/rcutorture/configs/{ => rcu}/TINY01  |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TINY02  |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TREE01  |    1 -
+ .../rcutorture/configs/{ => rcu}/TREE01.boot       |    0
+ .../selftests/rcutorture/configs/{ => rcu}/TREE02  |    3 +-
+ .../selftests/rcutorture/configs/{ => rcu}/TREE03  |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TREE04  |    1 -
+ .../rcutorture/configs/{ => rcu}/TREE04.boot       |    0
+ .../selftests/rcutorture/configs/{ => rcu}/TREE05  |    1 -
+ .../rcutorture/configs/{ => rcu}/TREE05.boot       |    0
+ .../selftests/rcutorture/configs/{ => rcu}/TREE06  |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TREE07  |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TREE08  |    1 -
+ .../rcutorture/configs/{ => rcu}/TREE08-T          |    1 -
+ .../selftests/rcutorture/configs/{ => rcu}/TREE09  |    1 -
+ .../rcutorture/configs/{ => rcu}/v0.0/CFLIST       |    0
+ .../configs/{ => rcu}/v0.0/N1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v0.0/N2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v0.0/N3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v0.0/N4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v0.0/N5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v0.0/NT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v0.0/NT3-NH       |    0
+ .../configs/{ => rcu}/v0.0/P1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v0.0/P2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v0.0/P3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v0.0/P4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v0.0/P5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v0.0/PT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v0.0/PT2-NH       |    0
+ .../configs/{ => rcu}/v0.0/ver_functions.sh        |   22 +-
+ .../rcutorture/configs/{ => rcu}/v3.12/CFLIST      |    0
+ .../configs/{ => rcu}/v3.12/N1-S-T-NH-SD-SMP-HP    |    0
+ .../configs/{ => rcu}/v3.12/N2-2-t-nh-sd-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/N3-3-T-nh-SD-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/N4-A-t-NH-sd-SMP-HP    |    0
+ .../configs/{ => rcu}/v3.12/N5-U-T-NH-sd-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/N6---t-nh-SD-smp-hp    |    0
+ .../configs/{ => rcu}/v3.12/N7-4-T-NH-SD-SMP-HP    |    0
+ .../configs/{ => rcu}/v3.12/N8-2-T-NH-SD-SMP-HP    |    0
+ .../rcutorture/configs/{ => rcu}/v3.12/NT1-nh      |    0
+ .../rcutorture/configs/{ => rcu}/v3.12/NT3-NH      |    0
+ .../configs/{ => rcu}/v3.12/P1-S-T-NH-SD-SMP-HP    |    0
+ .../configs/{ => rcu}/v3.12/P2-2-t-nh-sd-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/P3-3-T-nh-SD-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/P4-A-t-NH-sd-SMP-HP    |    0
+ .../configs/{ => rcu}/v3.12/P5-U-T-NH-sd-SMP-hp    |    0
+ .../configs/{ => rcu}/v3.12/P6---t-nh-SD-smp-hp    |    0
+ .../configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP    |    0
+ .../{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP-all        |    0
+ .../{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP-none       |    0
+ .../configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-hp    |    0
+ .../rcutorture/configs/{ => rcu}/v3.12/PT1-nh      |    0
+ .../rcutorture/configs/{ => rcu}/v3.12/PT2-NH      |    0
+ .../rcutorture/configs/{ => rcu}/v3.3/CFLIST       |    0
+ .../configs/{ => rcu}/v3.3/N1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.3/N2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.3/N3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.3/N4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.3/N5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v3.3/NT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v3.3/NT3-NH       |    0
+ .../configs/{ => rcu}/v3.3/P1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.3/P2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.3/P3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.3/P4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.3/P5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v3.3/PT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v3.3/PT2-NH       |    0
+ .../configs/{ => rcu/v3.3}/ver_functions.sh        |   28 +-
+ .../rcutorture/configs/{ => rcu}/v3.5/CFLIST       |    0
+ .../configs/{ => rcu}/v3.5/N1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.5/N2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.5/N3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.5/N4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.5/N5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v3.5/NT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v3.5/NT3-NH       |    0
+ .../configs/{ => rcu}/v3.5/P1-S-T-NH-SD-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.5/P2-2-t-nh-sd-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.5/P3-3-T-nh-SD-SMP-hp     |    0
+ .../configs/{ => rcu}/v3.5/P4-A-t-NH-sd-SMP-HP     |    0
+ .../configs/{ => rcu}/v3.5/P5-U-T-NH-sd-SMP-hp     |    0
+ .../rcutorture/configs/{ => rcu}/v3.5/PT1-nh       |    0
+ .../rcutorture/configs/{ => rcu}/v3.5/PT2-NH       |    0
+ .../configs/{ => rcu}/v3.5/ver_functions.sh        |   23 +-
+ .../configs/{v3.3 => rcu}/ver_functions.sh         |   26 +-
+ .../{TREE_RCU-Kconfig.txt => TREE_RCU-kconfig.txt} |    0
+ virt/kvm/kvm_main.c                                |    2 +-
+ 402 files changed, 6972 insertions(+), 11790 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt
+ delete mode 100644 Documentation/sgi-visws.txt
+ delete mode 100644 Documentation/sound/oss/vwsnd
+ delete mode 100644 arch/x86/include/asm/numaq.h
+ delete mode 100644 arch/x86/include/asm/visws/cobalt.h
+ delete mode 100644 arch/x86/include/asm/visws/lithium.h
+ delete mode 100644 arch/x86/include/asm/visws/piix4.h
+ delete mode 100644 arch/x86/include/asm/visws/sgivw.h
+ delete mode 100644 arch/x86/kernel/apic/es7000_32.c
+ delete mode 100644 arch/x86/kernel/apic/numaq_32.c
+ delete mode 100644 arch/x86/kernel/apic/summit_32.c
+ delete mode 100644 arch/x86/pci/numaq_32.c
+ delete mode 100644 arch/x86/pci/visws.c
+ delete mode 100644 arch/x86/platform/visws/Makefile
+ delete mode 100644 arch/x86/platform/visws/visws_quirks.c
+ delete mode 100644 drivers/clocksource/cyclone.c
+ create mode 100644 drivers/irqchip/irq-dove.c
+ delete mode 100644 drivers/video/fbdev/sgivwfb.c
+ create mode 100644 include/asm-generic/mcs_spinlock.h
+ create mode 100644 include/linux/mcs_spinlock.h
+ create mode 100644 include/linux/sched/prio.h
+ create mode 100644 include/linux/torture.h
+ delete mode 100644 include/video/sgivw.h
+ delete mode 100644 kernel/cpu/Makefile
+ create mode 100644 kernel/locking/locktorture.c
+ rename kernel/rcu/{torture.c => rcutorture.c} (58%)
+ rename kernel/{cpu => sched}/idle.c (95%)
+ create mode 100644 kernel/time/tick-broadcast-hrtimer.c
+ create mode 100644 kernel/torture.c
+ create mode 100644 scripts/gcc-ld
+ create mode 100755 scripts/ld-version.sh
+ delete mode 100644 sound/oss/vwsnd.c
+ create mode 100644 tools/include/linux/hash.h
+ rename tools/{perf/util => lib/api/fs}/fs.c (91%)
+ rename tools/{perf/util/include/linux/magic.h => lib/api/fs/fs.h} (50%)
+ rename tools/perf/arch/arm/util/{unwind.c => unwind-libunwind.c} (95%)
+ create mode 100644 tools/perf/arch/x86/tests/dwarf-unwind.c
+ create mode 100644 tools/perf/arch/x86/tests/regs_load.S
+ create mode 100644 tools/perf/arch/x86/util/unwind-libdw.c
+ rename tools/perf/arch/x86/util/{unwind.c => unwind-libunwind.c} (95%)
+ create mode 100644 tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
+ create mode 100644 tools/perf/tests/dwarf-unwind.c
+ delete mode 100644 tools/perf/util/fs.h
+ delete mode 100644 tools/perf/util/include/linux/hash.h
+ delete mode 100644 tools/perf/util/include/linux/prefetch.h
+ create mode 100644 tools/perf/util/perf_regs.c
+ create mode 100644 tools/perf/util/unwind-libdw.c
+ create mode 100644 tools/perf/util/unwind-libdw.h
+ rename tools/perf/util/{unwind.c => unwind-libunwind.c} (92%)
+ create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
+ create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
+ rename tools/testing/selftests/rcutorture/bin/{kvm-test-1-rcu.sh => kvm-test-1-run.sh} (79%)
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/BUSTED
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/CFLIST
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/CFcommon
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/LOCK01
+ create mode 100644 tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
+ create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/BUSTED
+ create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/CFLIST (100%)
+ create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/CFcommon
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/SRCU-N (75%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/SRCU-N.boot (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/SRCU-P (86%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/SRCU-P.boot (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TINY01 (92%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TINY02 (92%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE01 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE01.boot (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE02 (92%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE03 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE04 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE04.boot (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE05 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE05.boot (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE06 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE07 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE08 (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE08-T (96%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/TREE09 (95%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/CFLIST (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/N1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/N2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/N3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/N4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/N5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/NT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/NT3-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/P1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/P2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/P3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/P4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/P5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/PT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/PT2-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v0.0/ver_functions.sh (70%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/CFLIST (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N6---t-nh-SD-smp-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N7-4-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/N8-2-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/NT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/NT3-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P6---t-nh-SD-smp-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP-all (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-HP-none (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/P7-4-T-NH-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/PT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.12/PT2-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/CFLIST (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/N1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/N2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/N3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/N4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/N5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/NT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/NT3-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/P1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/P2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/P3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/P4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/P5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/PT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.3/PT2-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu/v3.3}/ver_functions.sh (72%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/CFLIST (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/N1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/N2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/N3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/N4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/N5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/NT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/NT3-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/P1-S-T-NH-SD-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/P2-2-t-nh-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/P3-3-T-nh-SD-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/P4-A-t-NH-sd-SMP-HP (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/P5-U-T-NH-sd-SMP-hp (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/PT1-nh (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/PT2-NH (100%)
+ rename tools/testing/selftests/rcutorture/configs/{ => rcu}/v3.5/ver_functions.sh (69%)
+ rename tools/testing/selftests/rcutorture/configs/{v3.3 => rcu}/ver_functions.sh (66%)
+ rename tools/testing/selftests/rcutorture/doc/{TREE_RCU-Kconfig.txt => TREE_RCU-kconfig.txt} (100%)
+$ 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 320a01fde5e1] Merge remote-tracking branch 'tip/auto-latest'
+Merging clockevents/clockevents/next (00e2bcd6d35f clocksource: Timer-sun5i: Switch to sched_clock_register())
+$ git merge clockevents/clockevents/next
+Already up-to-date.
+Merging edac/linux_next (3e45588825c1 cell_edac: fix missing of_node_put)
+$ 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
+Auto-merging include/linux/pci_ids.h
+Merge made by the 'recursive' strategy.
+ arch/x86/kernel/amd_nb.c    |  2 ++
+ drivers/edac/amd64_edac.c   | 38 +++++++++++++++++++++++---
+ drivers/edac/amd64_edac.h   |  3 +++
+ drivers/edac/amd8111_edac.c | 44 ++++++++++++++++++++----------
+ drivers/edac/e752x_edac.c   | 30 ++++++++-------------
+ drivers/edac/i3200_edac.c   |  2 ++
+ drivers/edac/i5100_edac.c   | 17 +++++-------
+ drivers/edac/i5400_edac.c   |  2 ++
+ drivers/edac/i7core_edac.c  | 10 +++----
+ drivers/edac/i82875p_edac.c |  2 --
+ drivers/edac/mce_amd.c      | 65 +++++++++++++++++++++++----------------------
+ drivers/edac/mpc85xx_edac.c |  6 ++---
+ drivers/edac/sb_edac.c      |  2 +-
+ include/linux/pci_ids.h     |  2 ++
+ 14 files changed, 134 insertions(+), 91 deletions(-)
+Merging ftrace/for-next (1fcc155351f1 ftrace: Have static function trace clear ENABLED flag on unregister)
+$ git merge ftrace/for-next
+Auto-merging kernel/trace/trace_irqsoff.c
+Merge made by the 'recursive' strategy.
+ include/linux/ftrace.h               |  14 +++
+ kernel/trace/blktrace.c              |   3 +-
+ kernel/trace/ftrace.c                |  72 +++++++++----
+ kernel/trace/trace.c                 | 187 +++++++++++++++++++++++++---------
+ kernel/trace/trace.h                 |  38 ++++++-
+ kernel/trace/trace_functions.c       | 143 ++++++++++++++++++--------
+ kernel/trace/trace_functions_graph.c |   3 +-
+ kernel/trace/trace_irqsoff.c         |  10 +-
+ kernel/trace/trace_kprobe.c          |  17 ----
+ kernel/trace/trace_nop.c             |   5 +-
+ kernel/trace/trace_probe.h           |  17 ++++
+ kernel/trace/trace_sched_wakeup.c    |  10 +-
+ kernel/trace/trace_uprobe.c          | 191 ++++++++++++++++++++++++-----------
+ 13 files changed, 519 insertions(+), 191 deletions(-)
+Merging rcu/rcu/next (f5604f67fe8c Merge branch 'torture.2014.02.23a' into HEAD)
+$ 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 (d3714010c307 KVM: x86: emulator_cmpxchg_emulated should mark_page_dirty)
+$ git merge kvm/linux-next
+Auto-merging virt/kvm/kvm_main.c
+Auto-merging arch/x86/kvm/x86.c
+Auto-merging arch/x86/kvm/vmx.c
+Auto-merging arch/x86/kvm/mmu.c
+Auto-merging arch/x86/kvm/cpuid.c
+Auto-merging arch/x86/include/asm/xsave.h
+Auto-merging arch/s390/kvm/kvm-s390.h
+Auto-merging arch/s390/kvm/kvm-s390.c
+Auto-merging arch/s390/kvm/diag.c
+Auto-merging arch/s390/include/asm/pgtable.h
+Auto-merging arch/s390/include/asm/kvm_host.h
+Merge made by the 'recursive' strategy.
+ Documentation/virtual/kvm/devices/s390_flic.txt |  46 +++
+ arch/s390/include/asm/kvm_host.h                |  58 ++--
+ arch/s390/include/asm/pgtable.h                 |   2 +
+ arch/s390/include/asm/processor.h               |   1 +
+ arch/s390/include/uapi/asm/kvm.h                |  19 ++
+ arch/s390/kvm/Kconfig                           |   2 +
+ arch/s390/kvm/Makefile                          |   2 +-
+ arch/s390/kvm/diag.c                            |  84 +++++
+ arch/s390/kvm/interrupt.c                       | 389 ++++++++++++++++++++----
+ arch/s390/kvm/kvm-s390.c                        | 135 +++++++-
+ arch/s390/kvm/kvm-s390.h                        |   4 +
+ arch/s390/kvm/sigp.c                            |   7 +
+ arch/s390/kvm/trace.h                           |  46 +++
+ arch/s390/mm/fault.c                            |  26 +-
+ arch/x86/include/asm/kvm_host.h                 |   2 +-
+ arch/x86/include/asm/vmx.h                      |   4 +
+ arch/x86/include/asm/xsave.h                    |   2 +
+ arch/x86/include/uapi/asm/msr-index.h           |   1 +
+ arch/x86/kernel/kvm.c                           |   1 -
+ arch/x86/kernel/kvmclock.c                      |   2 +-
+ arch/x86/kvm/cpuid.c                            |  11 +-
+ arch/x86/kvm/mmu.c                              |   2 +-
+ arch/x86/kvm/paging_tmpl.h                      |   7 +-
+ arch/x86/kvm/svm.c                              |   1 +
+ arch/x86/kvm/vmx.c                              |  24 +-
+ arch/x86/kvm/x86.c                              |  14 +-
+ arch/x86/kvm/x86.h                              |   3 +-
+ include/linux/kvm_host.h                        |   7 +-
+ include/uapi/linux/kvm.h                        |  66 ++++
+ virt/kvm/Kconfig                                |   4 +
+ virt/kvm/async_pf.c                             |  27 +-
+ virt/kvm/kvm_main.c                             |  10 +-
+ 32 files changed, 882 insertions(+), 127 deletions(-)
+ create mode 100644 Documentation/virtual/kvm/devices/s390_flic.txt
+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 (b73117c49364 Merge branch 'kvm-ppc-next' of git://github.com/agraf/linux-2.6 into kvm-queue)
+$ 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 (08ac54ab46ab Merge branch 'stable/for-linus-3.14' into linux-next)
+$ git merge xen-tip/linux-next
+Auto-merging arch/x86/xen/Kconfig
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                      |   1 +
+ arch/x86/include/asm/pgtable_types.h  |  12 +--
+ arch/x86/kernel/entry_32.S            |  23 +++++
+ arch/x86/kernel/entry_64.S            |  19 ++++
+ arch/x86/mm/init_32.c                 |   2 +-
+ arch/x86/mm/init_64.c                 |   2 +-
+ arch/x86/pci/i386.c                   |   2 -
+ arch/x86/pci/xen.c                    |  29 ++++--
+ arch/x86/xen/Kconfig                  |   5 -
+ arch/x86/xen/enlighten.c              |   2 -
+ arch/x86/xen/mmu.c                    |  52 +---------
+ arch/x86/xen/p2m.c                    | 174 ++++++++++++++++++++++------------
+ arch/x86/xen/setup.c                  |  15 ++-
+ drivers/xen/Makefile                  |   2 +-
+ drivers/xen/events/events_base.c      |  83 ++++++++--------
+ drivers/xen/events/events_internal.h  |   1 +
+ drivers/xen/pcpu.c                    |   1 +
+ drivers/xen/platform-pci.c            |   2 +-
+ drivers/xen/preempt.c                 |  17 ++++
+ drivers/xen/privcmd.c                 |   2 +
+ drivers/xen/xen-pciback/pciback_ops.c |   3 +-
+ drivers/xen/xen-selfballoon.c         |   1 +
+ drivers/xen/xenbus/xenbus_client.c    |  27 ------
+ include/xen/events.h                  |   3 +-
+ include/xen/interface/physdev.h       |  10 +-
+ include/xen/xen-ops.h                 |  27 ++++++
+ include/xen/xenbus.h                  |   1 -
+ 27 files changed, 309 insertions(+), 209 deletions(-)
+ create mode 100644 drivers/xen/preempt.c
+Merging percpu/for-next (d5f2deed588b Merge branch 'for-3.14' into for-next)
+$ git merge percpu/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging workqueues/for-next (379e899a2c66 Merge branch 'for-3.15' into for-next)
+$ git merge workqueues/for-next
+Merge made by the 'recursive' strategy.
+ include/linux/workqueue.h | 15 ---------------
+ 1 file changed, 15 deletions(-)
+Merging drivers-x86/linux-next (b4b0b4a9e039 ipc: add intel-mid's pci id macros)
+$ git merge drivers-x86/linux-next
+Already up-to-date.
+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 (f7368630e418 Merge remote-tracking branches 'regmap/topic/irq', 'regmap/topic/nodev' and 'regmap/topic/patch' into regmap-next)
+$ git merge regmap/for-next
+Auto-merging drivers/mfd/wm5102-tables.c
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/regcache.c       |   8 +-
+ drivers/base/regmap/regmap-debugfs.c |   2 +-
+ drivers/base/regmap/regmap-irq.c     |   2 +-
+ drivers/base/regmap/regmap.c         | 151 ++++++++++++++++++++++++-----------
+ drivers/mfd/arizona-core.c           |   4 -
+ drivers/mfd/wm5102-tables.c          |  21 +----
+ include/linux/regmap.h               |   7 +-
+ 7 files changed, 120 insertions(+), 75 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 (aad0f292756c leds: clevo-mail: remove __initdata marker)
+$ git merge leds/for-next
+Auto-merging drivers/leds/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/leds/leds-gpio.txt         |  12 ++
+ Documentation/devicetree/bindings/mfd/mc13xxx.txt  |  47 +++++
+ drivers/leds/Kconfig                               |   2 +-
+ drivers/leds/led-core.c                            |   6 +-
+ drivers/leds/led-triggers.c                        |   1 -
+ drivers/leds/leds-88pm860x.c                       |   1 -
+ drivers/leds/leds-adp5520.c                        |   1 -
+ drivers/leds/leds-asic3.c                          |   1 -
+ drivers/leds/leds-blinkm.c                         |   3 +-
+ drivers/leds/leds-clevo-mail.c                     |   2 +-
+ drivers/leds/leds-cobalt-qube.c                    |   1 -
+ drivers/leds/leds-da903x.c                         |   1 -
+ drivers/leds/leds-da9052.c                         |   1 -
+ drivers/leds/leds-fsg.c                            |   1 -
+ drivers/leds/leds-gpio.c                           |   4 +-
+ drivers/leds/leds-hp6xx.c                          |   1 -
+ drivers/leds/leds-lm3533.c                         |   1 -
+ drivers/leds/leds-lp5521.c                         |   1 -
+ drivers/leds/leds-lp5523.c                         |   1 -
+ drivers/leds/leds-lp5562.c                         |   7 +-
+ drivers/leds/leds-lt3593.c                         |   1 -
+ drivers/leds/leds-mc13783.c                        | 223 ++++++++++++++-------
+ drivers/leds/leds-netxbig.c                        |   1 -
+ drivers/leds/leds-ns2.c                            |   1 -
+ drivers/leds/leds-ot200.c                          |   1 -
+ drivers/leds/leds-pwm.c                            |   1 -
+ drivers/leds/leds-s3c24xx.c                        |   1 -
+ drivers/leds/leds-ss4200.c                         |   4 +-
+ drivers/leds/leds-wm831x-status.c                  |   1 -
+ drivers/leds/leds-wm8350.c                         |   1 -
+ drivers/leds/trigger/ledtrig-cpu.c                 |  24 +++
+ include/linux/mfd/mc13xxx.h                        |   6 +
+ include/linux/platform_data/leds-s3c24xx.h         |   9 +-
+ 33 files changed, 254 insertions(+), 115 deletions(-)
+Merging driver-core/driver-core-next (13df7977431e Merge 3.14-rc5 into driver-core-next)
+$ git merge driver-core/driver-core-next
+Auto-merging scripts/mod/file2alias.c
+Auto-merging include/linux/device.h
+Auto-merging arch/x86/include/asm/cpufeature.h
+Auto-merging arch/x86/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/s390/include/asm/ccwgroup.h               |   1 +
+ arch/s390/pci/pci_sysfs.c                      |  18 +-
+ arch/x86/Kconfig                               |   4 +-
+ arch/x86/include/asm/cpufeature.h              |   7 +
+ arch/x86/kernel/cpu/match.c                    |  42 --
+ drivers/base/Kconfig                           |   3 +
+ drivers/base/attribute_container.c             |   1 -
+ drivers/base/core.c                            |  51 +-
+ drivers/base/cpu.c                             |  46 +-
+ drivers/base/dma-buf.c                         |  18 +-
+ drivers/base/firmware_class.c                  |  13 +-
+ drivers/base/platform.c                        |  11 +-
+ drivers/base/power/clock_ops.c                 |   1 -
+ drivers/base/power/common.c                    |   1 -
+ drivers/base/power/domain.c                    |   1 -
+ drivers/base/power/domain_governor.c           |   1 -
+ drivers/base/power/opp.c                       |   1 -
+ drivers/base/regmap/regmap-i2c.c               |   1 -
+ drivers/base/regmap/regmap-mmio.c              |   1 -
+ drivers/base/regmap/regmap-spi.c               |   1 -
+ drivers/base/topology.c                        |   1 -
+ drivers/firmware/google/gsmi.c                 |   7 -
+ drivers/firmware/google/memconsole.c           |  47 +-
+ drivers/gpu/drm/drm_prime.c                    |   2 +-
+ drivers/gpu/drm/exynos/exynos_drm_dmabuf.c     |   2 +-
+ drivers/media/v4l2-core/videobuf2-dma-contig.c |   2 +-
+ drivers/pci/pci-sysfs.c                        |  17 +-
+ drivers/s390/block/dcssblk.c                   |  14 +-
+ drivers/s390/cio/ccwgroup.c                    |  26 +-
+ drivers/scsi/scsi_sysfs.c                      |  15 +-
+ fs/Kconfig                                     |   1 +
+ fs/Makefile                                    |   3 +-
+ fs/kernfs/Kconfig                              |   7 +
+ fs/kernfs/dir.c                                | 750 ++++++++++++++++++-------
+ fs/kernfs/file.c                               |  55 +-
+ fs/kernfs/kernfs-internal.h                    |  15 +-
+ fs/kernfs/mount.c                              |  39 +-
+ fs/kernfs/symlink.c                            |   6 +-
+ fs/sysfs/Kconfig                               |   1 +
+ fs/sysfs/dir.c                                 |  44 +-
+ fs/sysfs/file.c                                | 115 +---
+ fs/sysfs/group.c                               |   7 +-
+ fs/sysfs/mount.c                               |   2 +-
+ include/linux/cpu.h                            |   7 -
+ include/linux/cpufeature.h                     |  60 ++
+ include/linux/device.h                         |  13 +-
+ include/linux/kernfs.h                         | 108 +++-
+ include/linux/mod_devicetable.h                |   9 +
+ include/linux/sysfs.h                          |  23 +-
+ lib/kobject.c                                  |   2 +-
+ scripts/mod/devicetable-offsets.c              |   3 +
+ scripts/mod/file2alias.c                       |  20 +-
+ 52 files changed, 1028 insertions(+), 618 deletions(-)
+ create mode 100644 fs/kernfs/Kconfig
+ create mode 100644 include/linux/cpufeature.h
+Merging tty/tty-next (013daec9c19b Merge 3.14-rc5 into tty-next)
+$ git merge tty/tty-next
+Auto-merging include/linux/tty.h
+Removing include/linux/platform_data/max310x.h
+Auto-merging drivers/tty/serial/atmel_serial.c
+Auto-merging drivers/tty/serial/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/serial/fsl-lpuart.txt      |  21 +-
+ .../devicetree/bindings/serial/maxim,max310x.txt   |  36 ++
+ .../bindings/serial/renesas,sci-serial.txt         |   2 +-
+ arch/arm/boot/dts/atlas6.dtsi                      |  17 +-
+ arch/arm/boot/dts/prima2.dtsi                      |  20 +-
+ arch/arm/mach-imx/mach-mx31moboard.c               |  21 +-
+ drivers/tty/hvc/hvc_console.c                      |   6 +-
+ drivers/tty/ipwireless/tty.c                       |   3 -
+ drivers/tty/n_tty.c                                |  11 +-
+ drivers/tty/serial/8250/8250_core.c                |   4 +
+ drivers/tty/serial/Kconfig                         |   4 +-
+ drivers/tty/serial/amba-pl011.c                    |  21 +-
+ drivers/tty/serial/atmel_serial.c                  |  28 +-
+ drivers/tty/serial/bcm63xx_uart.c                  |  16 +-
+ drivers/tty/serial/crisv10.c                       | 112 ------
+ drivers/tty/serial/fsl_lpuart.c                    | 430 ++++++++++++++++++++-
+ drivers/tty/serial/imx.c                           |  82 +---
+ drivers/tty/serial/max310x.c                       | 416 +++++++++++---------
+ drivers/tty/serial/msm_serial.c                    | 140 ++++++-
+ drivers/tty/serial/msm_serial.h                    |   9 +
+ drivers/tty/serial/pch_uart.c                      |   2 +
+ drivers/tty/serial/samsung.c                       |  40 +-
+ drivers/tty/serial/serial_core.c                   |   6 +
+ drivers/tty/serial/sh-sci.c                        |   3 +-
+ drivers/tty/serial/sirfsoc_uart.c                  | 195 +++-------
+ drivers/tty/serial/sirfsoc_uart.h                  |   5 -
+ drivers/tty/tty_buffer.c                           |  20 +-
+ drivers/tty/tty_io.c                               |  23 +-
+ drivers/tty/vt/vt.c                                |  20 +-
+ drivers/usb/gadget/u_serial.c                      |   4 +-
+ include/linux/platform_data/max310x.h              |  64 ---
+ include/linux/platform_data/serial-imx.h           |   2 -
+ include/linux/serial_bcm63xx.h                     |   2 +
+ include/linux/tty.h                                |   2 +-
+ include/linux/tty_ldisc.h                          |   1 -
+ 35 files changed, 1053 insertions(+), 735 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/serial/maxim,max310x.txt
+ delete mode 100644 include/linux/platform_data/max310x.h
+Merging usb/usb-next (3c1b2c3ecd31 USB: sisusb: Use static const, fix typo)
+$ git merge usb/usb-next
+Resolved 'arch/arm/mach-tegra/Kconfig' using previous resolution.
+Auto-merging drivers/usb/host/Kconfig
+Auto-merging drivers/hid/hid-ids.h
+Auto-merging drivers/hid/hid-core.c
+Auto-merging arch/mips/Kconfig
+Auto-merging arch/arm/mach-tegra/Kconfig
+CONFLICT (content): Merge conflict in arch/arm/mach-tegra/Kconfig
+Auto-merging arch/arm/mach-shmobile/Kconfig
+Auto-merging arch/arm/mach-omap2/Kconfig
+Auto-merging arch/arm/Kconfig
+Removing Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+Removing Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+Auto-merging Documentation/devicetree/bindings/usb/usb-uhci.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e6b5299b18a0] Merge remote-tracking branch 'usb/usb-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/usb/ci-hdrc-imx.txt        |   2 +
+ Documentation/devicetree/bindings/usb/usb-ehci.txt |  27 ++-
+ Documentation/devicetree/bindings/usb/usb-ohci.txt |  25 +++
+ .../usb/{platform-uhci.txt => usb-uhci.txt}        |   4 +-
+ Documentation/devicetree/bindings/usb/usb-xhci.txt |   4 +-
+ .../devicetree/bindings/usb/via,vt8500-ehci.txt    |  15 --
+ .../devicetree/bindings/usb/vt8500-ehci.txt        |  12 --
+ arch/arm/Kconfig                                   |   3 -
+ arch/arm/mach-exynos/Kconfig                       |   1 -
+ arch/arm/mach-omap2/Kconfig                        |   2 -
+ arch/arm/mach-shmobile/Kconfig                     |   4 -
+ arch/arm/mach-tegra/Kconfig                        |   1 -
+ arch/mips/Kconfig                                  |   7 -
+ arch/mips/ath79/Kconfig                            |   8 -
+ arch/mips/ralink/Kconfig                           |   6 -
+ arch/powerpc/platforms/44x/Kconfig                 |   1 -
+ arch/powerpc/platforms/ps3/Kconfig                 |   2 -
+ arch/sh/Kconfig                                    |   9 -
+ drivers/hid/hid-core.c                             |   1 +
+ drivers/hid/hid-ids.h                              |   3 +
+ drivers/usb/Kconfig                                |  10 -
+ drivers/usb/chipidea/bits.h                        |   2 +
+ drivers/usb/chipidea/ci.h                          |   2 -
+ drivers/usb/chipidea/core.c                        |  87 ++++----
+ drivers/usb/chipidea/udc.c                         |  34 +---
+ drivers/usb/core/devio.c                           |  16 ++
+ drivers/usb/core/driver.c                          |   4 +-
+ drivers/usb/core/hub.c                             |  27 ++-
+ drivers/usb/dwc2/core_intr.c                       |  25 ++-
+ drivers/usb/dwc2/hcd_intr.c                        |  14 +-
+ drivers/usb/gadget/Kconfig                         |   2 +-
+ drivers/usb/host/Kconfig                           |   1 -
+ drivers/usb/host/ehci-platform.c                   | 182 ++++++++++++++---
+ drivers/usb/host/ehci-tegra.c                      |   4 -
+ drivers/usb/host/ohci-platform.c                   | 199 +++++++++++++++---
+ drivers/usb/host/uhci-platform.c                   |   1 +
+ drivers/usb/host/xhci-plat.c                       |   1 +
+ drivers/usb/misc/Kconfig                           |   1 -
+ drivers/usb/misc/sisusbvga/sisusb.c                |  10 +-
+ drivers/usb/misc/usbled.c                          |  34 ++++
+ drivers/usb/phy/phy-msm-usb.c                      |   3 +-
+ drivers/usb/wusbcore/devconnect.c                  |   4 +-
+ drivers/usb/wusbcore/wa-rpipe.c                    |   2 +-
+ drivers/usb/wusbcore/wa-xfer.c                     | 222 ++++++++++++++++-----
+ include/linux/usb/chipidea.h                       |   1 +
+ 45 files changed, 717 insertions(+), 308 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-ohci.txt
+ rename Documentation/devicetree/bindings/usb/{platform-uhci.txt => usb-uhci.txt} (76%)
+ delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+ delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+Merging usb-gadget/next (fa92f305f311 usb: dwc3: gadget: pre-start Stream transfers when they're queued)
+$ git merge usb-gadget/next
+Auto-merging drivers/usb/musb/musb_host.c
+Auto-merging drivers/usb/musb/musb_core.c
+Auto-merging drivers/usb/gadget/printer.c
+Auto-merging drivers/usb/gadget/f_fs.c
+Merge made by the 'recursive' strategy.
+ drivers/usb/dwc3/core.c             | 131 ++++++++++++-
+ drivers/usb/dwc3/core.h             |  62 +++---
+ drivers/usb/dwc3/dwc3-omap.c        |   5 -
+ drivers/usb/dwc3/gadget.c           | 196 ++++++++++++++++---
+ drivers/usb/dwc3/gadget.h           |   1 +
+ drivers/usb/gadget/Kconfig          |   1 -
+ drivers/usb/gadget/at91_udc.c       |  14 +-
+ drivers/usb/gadget/atmel_usba_udc.c |   4 +-
+ drivers/usb/gadget/atmel_usba_udc.h |   2 +-
+ drivers/usb/gadget/epautoconf.c     |  30 ++-
+ drivers/usb/gadget/f_fs.c           | 378 ++++++++++++++++++++++++++++++------
+ drivers/usb/gadget/gr_udc.c         |  10 +-
+ drivers/usb/gadget/printer.c        |   8 +-
+ drivers/usb/gadget/s3c-hsotg.c      |  90 +++++----
+ drivers/usb/gadget/s3c-hsudc.c      |   1 -
+ drivers/usb/gadget/u_fs.h           |  20 +-
+ drivers/usb/musb/Kconfig            |   2 +
+ drivers/usb/musb/musb_core.c        |   5 +-
+ drivers/usb/musb/musb_cppi41.c      |  66 +++++++
+ drivers/usb/musb/musb_dsps.c        |  58 +++++-
+ drivers/usb/musb/musb_host.c        |  30 ++-
+ drivers/usb/phy/phy-rcar-gen2-usb.c |   6 +-
+ include/linux/usb/gadget.h          |  13 ++
+ 23 files changed, 928 insertions(+), 205 deletions(-)
+Merging staging/staging-next (17b02809cfa7 Merge 3.14-rc5 into staging-next)
+$ git merge staging/staging-next
+Resolved 'arch/arm/boot/dts/imx51-babbage.dts' using previous resolution.
+Resolved 'arch/arm/boot/dts/imx53-mba53.dts' using previous resolution.
+Resolved 'arch/arm/boot/dts/imx53-qsb.dts' using previous resolution.
+Auto-merging include/linux/hid-sensor-ids.h
+Auto-merging drivers/usb/core/message.c
+Removing drivers/staging/sm7xxfb/sm7xxfb.c
+Removing drivers/staging/sm7xxfb/sm7xx.h
+Removing drivers/staging/sm7xxfb/TODO
+Removing drivers/staging/sm7xxfb/Makefile
+Removing drivers/staging/sm7xxfb/Kconfig
+Removing drivers/staging/sb105x/sb_ser_core.h
+Removing drivers/staging/sb105x/sb_pci_mp.h
+Removing drivers/staging/sb105x/sb_pci_mp.c
+Removing drivers/staging/sb105x/sb_mp_register.h
+Removing drivers/staging/sb105x/Makefile
+Removing drivers/staging/sb105x/Kconfig
+Removing drivers/staging/rtl8192u/r819xU_HTType.h
+Removing drivers/staging/rtl8192u/r819xU_HTGen.h
+Removing drivers/staging/rtl8192u/ieee80211/scatterwalk.h
+Removing drivers/staging/rtl8192u/ieee80211/scatterwalk.c
+Removing drivers/staging/rtl8192u/ieee80211/rtl_crypto.h
+Removing drivers/staging/rtl8192u/ieee80211/proc.c
+Removing drivers/staging/rtl8192u/ieee80211/michael_mic.c
+Removing drivers/staging/rtl8192u/ieee80211/internal.h
+Removing drivers/staging/rtl8192u/ieee80211/digest.c
+Removing drivers/staging/rtl8192u/ieee80211/crypto_compat.h
+Removing drivers/staging/rtl8192u/ieee80211/compress.c
+Removing drivers/staging/rtl8192u/ieee80211/cipher.c
+Removing drivers/staging/rtl8192u/ieee80211/autoload.c
+Removing drivers/staging/rtl8192u/ieee80211/arc4.c
+Removing drivers/staging/rtl8192u/ieee80211/aes.c
+Removing drivers/staging/rtl8192u/ieee80211/EndianFree.h
+Removing drivers/staging/rtl8188eu/include/nic_spec.h
+Removing drivers/staging/rtl8188eu/include/ip.h
+Removing drivers/staging/rtl8188eu/include/ioctl_cfg80211.h
+Removing drivers/staging/rtl8188eu/include/if_ether.h
+Removing drivers/staging/rtl8188eu/include/h2clbk.h
+Removing drivers/staging/rtl8188eu/include/ethernet.h
+Removing drivers/staging/rtl8188eu/hal/odm_interface.c
+Auto-merging drivers/staging/rtl8188eu/Kconfig
+Removing drivers/staging/imx-drm/imx-fbdev.c
+Removing drivers/staging/imx-drm/imx-fb.c
+Removing drivers/staging/echo/TODO
+Removing drivers/staging/dgap/downld.c
+Removing drivers/staging/dgap/digi.h
+Removing drivers/staging/dgap/dgap_types.h
+Removing drivers/staging/dgap/dgap_tty.h
+Removing drivers/staging/dgap/dgap_tty.c
+Removing drivers/staging/dgap/dgap_trace.h
+Removing drivers/staging/dgap/dgap_trace.c
+Removing drivers/staging/dgap/dgap_sysfs.h
+Removing drivers/staging/dgap/dgap_sysfs.c
+Removing drivers/staging/dgap/dgap_pci.h
+Removing drivers/staging/dgap/dgap_parse.h
+Removing drivers/staging/dgap/dgap_parse.c
+Removing drivers/staging/dgap/dgap_kcompat.h
+Removing drivers/staging/dgap/dgap_fep5.h
+Removing drivers/staging/dgap/dgap_fep5.c
+Removing drivers/staging/dgap/dgap_driver.h
+Removing drivers/staging/dgap/dgap_driver.c
+Removing drivers/staging/dgap/dgap_downld.h
+Removing drivers/staging/dgap/dgap_conf.h
+Auto-merging drivers/staging/android/Kconfig
+Auto-merging arch/arm/boot/dts/imx6qdl.dtsi
+Auto-merging arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+Auto-merging arch/arm/boot/dts/imx6q.dtsi
+Auto-merging arch/arm/boot/dts/imx6dl.dtsi
+Auto-merging arch/arm/boot/dts/imx53-qsb.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/imx53-qsb.dts
+Auto-merging arch/arm/boot/dts/imx53-mba53.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/imx53-mba53.dts
+Auto-merging arch/arm/boot/dts/imx53-m53evk.dts
+Auto-merging arch/arm/boot/dts/imx51-babbage.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/imx51-babbage.dts
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master f1610a2a2f12] Merge remote-tracking branch 'staging/staging-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/atmel-adc.txt          |    5 +
+ .../devicetree/bindings/iio/adc/vf610-adc.txt      |   22 +
+ MAINTAINERS                                        |    6 +
+ arch/arm/boot/dts/imx51-babbage.dts                |   10 +-
+ arch/arm/boot/dts/imx53-m53evk.dts                 |    8 +-
+ arch/arm/boot/dts/imx53-mba53.dts                  |    6 +
+ arch/arm/boot/dts/imx53-qsb.dts                    |    5 +
+ arch/arm/boot/dts/imx6dl.dtsi                      |    5 +
+ arch/arm/boot/dts/imx6q-sabresd.dts                |    4 +
+ arch/arm/boot/dts/imx6q.dtsi                       |    5 +
+ arch/arm/boot/dts/imx6qdl-sabresd.dtsi             |    6 +
+ arch/arm/boot/dts/imx6qdl.dtsi                     |    9 +
+ drivers/iio/accel/bma180.c                         |    4 +-
+ drivers/iio/adc/Kconfig                            |   10 +
+ drivers/iio/adc/Makefile                           |    1 +
+ drivers/iio/adc/max1363.c                          |   16 +-
+ drivers/iio/adc/ti_am335x_adc.c                    |    1 -
+ drivers/iio/adc/twl6030-gpadc.c                    |    1 -
+ drivers/iio/adc/vf610_adc.c                        |  711 ++
+ drivers/iio/adc/viperboard_adc.c                   |    2 -
+ drivers/iio/buffer_cb.c                            |    7 +-
+ drivers/iio/dac/ad7303.c                           |    2 +-
+ drivers/iio/dac/max517.c                           |    1 -
+ drivers/iio/dac/mcp4725.c                          |    1 -
+ drivers/iio/humidity/Kconfig                       |   10 +
+ drivers/iio/humidity/Makefile                      |    1 +
+ drivers/iio/humidity/si7005.c                      |  189 +
+ drivers/iio/imu/Kconfig                            |    4 +-
+ drivers/iio/imu/adis16400_core.c                   |    2 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c         |    3 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h          |   38 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c         |    1 -
+ drivers/iio/industrialio-buffer.c                  |   16 +-
+ drivers/iio/industrialio-core.c                    |   51 +-
+ drivers/iio/industrialio-event.c                   |  100 +-
+ drivers/iio/industrialio-trigger.c                 |   11 +-
+ drivers/iio/light/Kconfig                          |   26 +
+ drivers/iio/light/Makefile                         |    2 +
+ drivers/iio/light/adjd_s311.c                      |    3 -
+ drivers/iio/light/hid-sensor-prox.c                |  375 +
+ drivers/iio/light/ltr501.c                         |  445 ++
+ drivers/iio/light/tcs3472.c                        |    2 -
+ drivers/iio/magnetometer/ak8975.c                  |    1 +
+ drivers/iio/magnetometer/mag3110.c                 |   16 +-
+ drivers/iio/pressure/Kconfig                       |   16 +-
+ drivers/iio/pressure/Makefile                      |    1 +
+ drivers/iio/pressure/hid-sensor-press.c            |  376 +
+ drivers/iio/pressure/mpl3115.c                     |    2 +-
+ drivers/iio/pressure/st_pressure.h                 |    1 +
+ drivers/iio/pressure/st_pressure_core.c            |   87 +-
+ drivers/iio/pressure/st_pressure_i2c.c             |    1 +
+ drivers/iio/pressure/st_pressure_spi.c             |    1 +
+ drivers/misc/Kconfig                               |    1 +
+ drivers/misc/Makefile                              |    1 +
+ drivers/{staging => misc}/echo/Kconfig             |    0
+ drivers/{staging => misc}/echo/Makefile            |    0
+ drivers/{staging => misc}/echo/echo.c              |    0
+ drivers/{staging => misc}/echo/echo.h              |    0
+ drivers/{staging => misc}/echo/fir.h               |    0
+ drivers/{staging => misc}/echo/oslec.h             |    0
+ drivers/staging/Kconfig                            |   10 +-
+ drivers/staging/Makefile                           |    5 +-
+ drivers/staging/android/Kconfig                    |   13 +
+ drivers/staging/android/android_alarm.h            |   44 +-
+ drivers/staging/android/ashmem.h                   |   30 +-
+ drivers/staging/android/binder.c                   |  268 +-
+ drivers/staging/android/binder.h                   |  308 +-
+ drivers/staging/android/binder_trace.h             |   14 +-
+ drivers/staging/android/ion/ion.c                  |  135 +-
+ drivers/staging/android/ion/ion_cma_heap.c         |    2 +-
+ drivers/staging/android/ion/ion_dummy_driver.c     |   12 +-
+ drivers/staging/android/ion/ion_heap.c             |   67 +-
+ drivers/staging/android/ion/ion_page_pool.c        |    8 +-
+ drivers/staging/android/ion/ion_priv.h             |   89 +-
+ drivers/staging/android/ion/ion_system_heap.c      |   84 +-
+ drivers/staging/android/lowmemorykiller.c          |    5 +-
+ drivers/staging/android/sw_sync.h                  |   20 +-
+ drivers/staging/android/sync.h                     |   88 +-
+ drivers/staging/android/timed_output.h             |    4 +-
+ drivers/staging/android/uapi/android_alarm.h       |   62 +
+ drivers/staging/android/uapi/ashmem.h              |   47 +
+ drivers/staging/android/uapi/binder.h              |  351 +
+ drivers/staging/android/uapi/sw_sync.h             |   32 +
+ drivers/staging/android/uapi/sync.h                |   97 +
+ drivers/staging/bcm/Bcmchar.c                      | 3216 ++++----
+ drivers/staging/bcm/DDRInit.c                      |   32 +-
+ drivers/staging/bcm/InterfaceInit.c                |   93 +-
+ drivers/staging/bcm/Qos.c                          |   35 +-
+ drivers/staging/ced1401/ced_ioc.c                  |  151 +-
+ drivers/staging/ced1401/usb1401.c                  |  189 +-
+ drivers/staging/comedi/comedi_fops.c               |   24 +-
+ drivers/staging/comedi/comedidev.h                 |   56 +-
+ drivers/staging/comedi/drivers.c                   |   30 +
+ drivers/staging/comedi/drivers/8255_pci.c          |    3 -
+ .../comedi/drivers/addi-data/hwdrv_apci035.c       |  261 +-
+ .../comedi/drivers/addi-data/hwdrv_apci1564.c      |  125 +-
+ drivers/staging/comedi/drivers/addi_apci_3xxx.c    |   57 +-
+ drivers/staging/comedi/drivers/adl_pci6208.c       |   22 +-
+ drivers/staging/comedi/drivers/adl_pci7x3x.c       |    3 -
+ drivers/staging/comedi/drivers/adl_pci9111.c       |   64 +-
+ drivers/staging/comedi/drivers/adl_pci9118.c       |   55 +-
+ drivers/staging/comedi/drivers/adq12b.c            |   31 +-
+ drivers/staging/comedi/drivers/adv_pci1710.c       |   39 +-
+ drivers/staging/comedi/drivers/adv_pci1723.c       |    2 -
+ drivers/staging/comedi/drivers/adv_pci_dio.c       |   10 +-
+ drivers/staging/comedi/drivers/aio_aio12_8.c       |   31 +-
+ drivers/staging/comedi/drivers/aio_iiro_16.c       |    2 +-
+ .../staging/comedi/drivers/amplc_dio200_common.c   |    2 +-
+ drivers/staging/comedi/drivers/amplc_pc236.c       |   35 +-
+ drivers/staging/comedi/drivers/amplc_pc263.c       |    2 -
+ drivers/staging/comedi/drivers/amplc_pci224.c      |   17 +-
+ drivers/staging/comedi/drivers/amplc_pci230.c      |   42 +-
+ drivers/staging/comedi/drivers/amplc_pci263.c      |    2 -
+ drivers/staging/comedi/drivers/cb_das16_cs.c       |  150 +-
+ drivers/staging/comedi/drivers/cb_pcidas.c         |   37 +-
+ drivers/staging/comedi/drivers/cb_pcidas64.c       |   59 +-
+ drivers/staging/comedi/drivers/cb_pcidda.c         |    2 -
+ drivers/staging/comedi/drivers/cb_pcimdas.c        |   41 +-
+ drivers/staging/comedi/drivers/cb_pcimdda.c        |    4 +-
+ drivers/staging/comedi/drivers/comedi_bond.c       |    5 +-
+ drivers/staging/comedi/drivers/comedi_test.c       |    6 +-
+ drivers/staging/comedi/drivers/contec_pci_dio.c    |    2 -
+ drivers/staging/comedi/drivers/daqboard2000.c      |   85 +-
+ drivers/staging/comedi/drivers/das08.c             |   35 +-
+ drivers/staging/comedi/drivers/das16.c             |   19 +-
+ drivers/staging/comedi/drivers/das16m1.c           |   29 +-
+ drivers/staging/comedi/drivers/das800.c            |   35 +-
+ drivers/staging/comedi/drivers/dmm32at.c           |   83 +-
+ drivers/staging/comedi/drivers/dt2811.c            |   23 +-
+ drivers/staging/comedi/drivers/dt2814.c            |   29 +-
+ drivers/staging/comedi/drivers/dt2815.c            |   39 +-
+ drivers/staging/comedi/drivers/dt282x.c            |   62 +-
+ drivers/staging/comedi/drivers/dt3000.c            |    2 -
+ drivers/staging/comedi/drivers/dyna_pci10xx.c      |   40 +-
+ drivers/staging/comedi/drivers/fl512.c             |    2 +-
+ drivers/staging/comedi/drivers/icp_multi.c         |  109 +-
+ drivers/staging/comedi/drivers/ii_pci20kc.c        |   20 +-
+ drivers/staging/comedi/drivers/jr3_pci.c           |    2 +-
+ drivers/staging/comedi/drivers/ke_counter.c        |    3 -
+ drivers/staging/comedi/drivers/me_daq.c            |   36 +-
+ drivers/staging/comedi/drivers/mf6x4.c             |   23 +-
+ drivers/staging/comedi/drivers/mpc624.c            |   30 +-
+ drivers/staging/comedi/drivers/multiq3.c           |   38 +-
+ drivers/staging/comedi/drivers/ni_660x.c           |    2 +-
+ drivers/staging/comedi/drivers/ni_670x.c           |    3 -
+ drivers/staging/comedi/drivers/ni_at_a2150.c       |   46 +-
+ drivers/staging/comedi/drivers/ni_atmio16d.c       |   61 +-
+ drivers/staging/comedi/drivers/ni_daq_700.c        |   56 +-
+ drivers/staging/comedi/drivers/ni_labpc.c          |   21 +-
+ drivers/staging/comedi/drivers/ni_mio_common.c     |   26 +-
+ drivers/staging/comedi/drivers/ni_pcimio.c         |    2 +-
+ drivers/staging/comedi/drivers/pcl711.c            |   26 +-
+ drivers/staging/comedi/drivers/pcl812.c            |  935 ++-
+ drivers/staging/comedi/drivers/pcl816.c            |  581 +-
+ drivers/staging/comedi/drivers/pcl818.c            |  744 +-
+ drivers/staging/comedi/drivers/pcm3724.c           |    6 +-
+ drivers/staging/comedi/drivers/pcmad.c             |   21 +-
+ drivers/staging/comedi/drivers/pcmmio.c            |   42 +-
+ drivers/staging/comedi/drivers/rtd520.c            |   86 +-
+ drivers/staging/comedi/drivers/rti800.c            |   29 +-
+ drivers/staging/comedi/drivers/s526.c              |   34 +-
+ drivers/staging/comedi/drivers/s626.c              |   22 +-
+ drivers/staging/comedi/drivers/skel.c              |   43 +-
+ drivers/staging/comedi/drivers/ssv_dnp.c           |    3 +-
+ drivers/staging/comedi/drivers/usbduxfast.c        |   51 +-
+ .../staging/comedi/kcomedilib/kcomedilib_main.c    |    3 +-
+ drivers/staging/crystalhd/crystalhd_hw.c           |    8 +-
+ drivers/staging/cxt1e1/functions.c                 |  372 +-
+ drivers/staging/cxt1e1/hwprobe.c                   |  604 +-
+ drivers/staging/cxt1e1/pmc93x6_eeprom.c            |    6 +-
+ drivers/staging/cxt1e1/pmcc4.h                     |    1 -
+ drivers/staging/dgap/Makefile                      |    6 -
+ drivers/staging/dgap/dgap.c                        | 7857 ++++++++++++++++++++
+ drivers/staging/dgap/dgap.h                        | 1408 ++++
+ drivers/staging/dgap/dgap_conf.h                   |  290 -
+ drivers/staging/dgap/dgap_downld.h                 |   69 -
+ drivers/staging/dgap/dgap_driver.c                 | 1030 ---
+ drivers/staging/dgap/dgap_driver.h                 |  620 --
+ drivers/staging/dgap/dgap_fep5.c                   | 1938 -----
+ drivers/staging/dgap/dgap_fep5.h                   |  253 -
+ drivers/staging/dgap/dgap_kcompat.h                |   64 -
+ drivers/staging/dgap/dgap_parse.c                  | 1374 ----
+ drivers/staging/dgap/dgap_parse.h                  |   35 -
+ drivers/staging/dgap/dgap_pci.h                    |   92 -
+ drivers/staging/dgap/dgap_sysfs.c                  |  793 --
+ drivers/staging/dgap/dgap_sysfs.h                  |   48 -
+ drivers/staging/dgap/dgap_trace.c                  |  186 -
+ drivers/staging/dgap/dgap_trace.h                  |   36 -
+ drivers/staging/dgap/dgap_tty.c                    | 3580 ---------
+ drivers/staging/dgap/dgap_tty.h                    |   39 -
+ drivers/staging/dgap/dgap_types.h                  |   36 -
+ drivers/staging/dgap/digi.h                        |  376 -
+ drivers/staging/dgap/downld.c                      |  798 --
+ drivers/staging/echo/TODO                          |    5 -
+ drivers/staging/et131x/et131x.c                    |   19 +-
+ drivers/staging/gdm724x/gdm_usb.c                  |   21 +-
+ drivers/staging/gs_fpgaboot/Kconfig                |    8 +
+ drivers/staging/gs_fpgaboot/Makefile               |    4 +
+ drivers/staging/gs_fpgaboot/README                 |   71 +
+ drivers/staging/gs_fpgaboot/TODO                   |    7 +
+ drivers/staging/gs_fpgaboot/gs_fpgaboot.c          |  422 ++
+ drivers/staging/gs_fpgaboot/gs_fpgaboot.h          |   56 +
+ drivers/staging/gs_fpgaboot/io.c                   |  294 +
+ drivers/staging/gs_fpgaboot/io.h                   |   90 +
+ drivers/staging/iio/Documentation/iio_utils.h      |   22 +
+ drivers/staging/iio/Documentation/lsiio.c          |  157 +
+ drivers/staging/iio/accel/sca3000.h                |   26 +-
+ drivers/staging/iio/accel/sca3000_core.c           |  172 +-
+ drivers/staging/iio/adc/ad799x.h                   |   10 +-
+ drivers/staging/iio/adc/ad799x_core.c              |   56 +-
+ drivers/staging/iio/adc/mxs-lradc.c                |    6 +-
+ drivers/staging/imx-drm/Kconfig                    |    1 +
+ drivers/staging/imx-drm/Makefile                   |    3 +-
+ drivers/staging/imx-drm/imx-drm-core.c             |  796 +-
+ drivers/staging/imx-drm/imx-drm.h                  |   43 +-
+ drivers/staging/imx-drm/imx-fb.c                   |   47 -
+ drivers/staging/imx-drm/imx-fbdev.c                |   74 -
+ drivers/staging/imx-drm/imx-hdmi.c                 |  684 +-
+ drivers/staging/imx-drm/imx-ldb.c                  |  131 +-
+ drivers/staging/imx-drm/imx-tve.c                  |  135 +-
+ drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h        |    2 +
+ drivers/staging/imx-drm/ipu-v3/ipu-dc.c            |    2 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-di.c            |  317 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c          |    3 -
+ drivers/staging/imx-drm/ipuv3-crtc.c               |   56 +-
+ drivers/staging/imx-drm/ipuv3-plane.c              |    4 +-
+ drivers/staging/imx-drm/parallel-display.c         |  127 +-
+ drivers/staging/line6/driver.c                     |    2 +-
+ drivers/staging/line6/driver.h                     |    2 +-
+ drivers/staging/line6/usbdefs.h                    |    6 +-
+ .../staging/lustre/include/linux/libcfs/curproc.h  |    9 -
+ .../lustre/include/linux/libcfs/libcfs_hash.h      |    2 -
+ .../staging/lustre/include/linux/lnet/lib-lnet.h   |    2 +-
+ .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c    |   70 +-
+ drivers/staging/lustre/lnet/lnet/api-ni.c          |    2 +-
+ drivers/staging/lustre/lnet/lnet/lib-ptl.c         |    2 +-
+ drivers/staging/lustre/lustre/include/cl_object.h  |    6 +-
+ drivers/staging/lustre/lustre/include/lclient.h    |    2 +-
+ .../lustre/lustre/include/lustre/lustre_idl.h      |   79 +-
+ .../lustre/lustre/include/lustre/lustre_user.h     |   18 +-
+ drivers/staging/lustre/lustre/include/lustre_cfg.h |    2 +
+ .../staging/lustre/lustre/include/lustre_disk.h    |    2 +
+ .../lustre/lustre/include/lustre_dlm_flags.h       |   14 +-
+ .../staging/lustre/lustre/include/lustre_export.h  |   17 +
+ drivers/staging/lustre/lustre/include/lustre_fid.h |    2 +-
+ .../staging/lustre/lustre/include/lustre_import.h  |   11 +
+ drivers/staging/lustre/lustre/include/lustre_mdc.h |   11 +
+ drivers/staging/lustre/lustre/include/lustre_net.h |    2 +
+ drivers/staging/lustre/lustre/include/obd.h        |    5 +-
+ drivers/staging/lustre/lustre/include/obd_class.h  |   13 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_flock.c    |   41 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_lock.c     |    2 -
+ drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c    |    1 +
+ drivers/staging/lustre/lustre/ldlm/ldlm_resource.c |    4 +-
+ .../lustre/lustre/libcfs/kernel_user_comm.c        |  102 -
+ .../staging/lustre/lustre/libcfs/linux/linux-cpu.c |   19 +-
+ .../lustre/lustre/libcfs/linux/linux-curproc.c     |   57 +-
+ .../lustre/lustre/libcfs/linux/linux-module.c      |    4 +-
+ drivers/staging/lustre/lustre/libcfs/workitem.c    |    4 +-
+ drivers/staging/lustre/lustre/llite/dcache.c       |  326 +-
+ drivers/staging/lustre/lustre/llite/dir.c          |   35 +-
+ drivers/staging/lustre/lustre/llite/file.c         |   95 +-
+ .../staging/lustre/lustre/llite/llite_internal.h   |   30 +-
+ drivers/staging/lustre/lustre/llite/llite_lib.c    |   23 +-
+ drivers/staging/lustre/lustre/llite/llite_nfs.c    |    6 +-
+ drivers/staging/lustre/lustre/llite/namei.c        |  122 +-
+ drivers/staging/lustre/lustre/llite/rw.c           |    2 +-
+ drivers/staging/lustre/lustre/llite/statahead.c    |   12 +-
+ drivers/staging/lustre/lustre/llite/vvp_io.c       |   31 +-
+ drivers/staging/lustre/lustre/llite/xattr.c        |   31 +-
+ drivers/staging/lustre/lustre/llite/xattr_cache.c  |  117 +-
+ drivers/staging/lustre/lustre/lmv/lmv_intent.c     |    1 -
+ drivers/staging/lustre/lustre/lmv/lmv_obd.c        |    5 +-
+ drivers/staging/lustre/lustre/lov/lov_io.c         |    1 +
+ drivers/staging/lustre/lustre/lov/lov_object.c     |   10 +-
+ drivers/staging/lustre/lustre/lov/lovsub_dev.c     |    4 +
+ drivers/staging/lustre/lustre/mdc/mdc_internal.h   |    4 +-
+ drivers/staging/lustre/lustre/mdc/mdc_lib.c        |    2 +-
+ drivers/staging/lustre/lustre/mdc/mdc_locks.c      |  111 +-
+ drivers/staging/lustre/lustre/mdc/mdc_reint.c      |    3 +-
+ drivers/staging/lustre/lustre/mdc/mdc_request.c    |   57 +-
+ drivers/staging/lustre/lustre/mgc/mgc_request.c    |   90 +-
+ drivers/staging/lustre/lustre/obdclass/cl_io.c     |    2 +-
+ drivers/staging/lustre/lustre/obdclass/cl_object.c |    2 +-
+ drivers/staging/lustre/lustre/obdclass/genops.c    |    8 +-
+ .../lustre/lustre/obdclass/linux/linux-module.c    |    2 +-
+ drivers/staging/lustre/lustre/obdclass/llog_cat.c  |    6 +-
+ drivers/staging/lustre/lustre/obdclass/llog_lvfs.c |    2 +-
+ drivers/staging/lustre/lustre/obdclass/llog_osd.c  |    6 +-
+ .../staging/lustre/lustre/obdclass/local_storage.c |    2 +-
+ .../lustre/lustre/obdclass/lprocfs_status.c        |    2 +
+ drivers/staging/lustre/lustre/obdclass/lu_object.c |    6 +-
+ drivers/staging/lustre/lustre/obdclass/md_attrs.c  |    6 +-
+ .../staging/lustre/lustre/obdclass/obd_config.c    |   51 +-
+ drivers/staging/lustre/lustre/obdclass/obd_mount.c |    4 +-
+ drivers/staging/lustre/lustre/obdclass/obdo.c      |    6 +-
+ .../staging/lustre/lustre/obdecho/echo_client.c    |   16 +-
+ drivers/staging/lustre/lustre/osc/osc_cache.c      |   10 +-
+ drivers/staging/lustre/lustre/osc/osc_io.c         |   16 +-
+ drivers/staging/lustre/lustre/osc/osc_page.c       |    2 +-
+ drivers/staging/lustre/lustre/osc/osc_quota.c      |    7 +-
+ drivers/staging/lustre/lustre/ptlrpc/client.c      |  187 +-
+ drivers/staging/lustre/lustre/ptlrpc/events.c      |    2 +-
+ .../lustre/lustre/ptlrpc/gss/gss_cli_upcall.c      |    2 +-
+ .../staging/lustre/lustre/ptlrpc/gss/gss_keyring.c |    2 +-
+ .../lustre/lustre/ptlrpc/gss/gss_krb5_mech.c       |    1 -
+ .../staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c  |    4 +-
+ .../lustre/lustre/ptlrpc/gss/gss_svc_upcall.c      |    6 +-
+ drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c |   14 +-
+ drivers/staging/lustre/lustre/ptlrpc/import.c      |   37 +-
+ drivers/staging/lustre/lustre/ptlrpc/layout.c      |    5 +-
+ .../staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c    |    4 +-
+ drivers/staging/lustre/lustre/ptlrpc/niobuf.c      |    8 +-
+ drivers/staging/lustre/lustre/ptlrpc/nrs.c         |    4 +-
+ .../staging/lustre/lustre/ptlrpc/pack_generic.c    |   14 +-
+ drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c     |    4 +-
+ drivers/staging/lustre/lustre/ptlrpc/recover.c     |   57 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec.c         |   14 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c    |    2 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_config.c  |    2 +-
+ drivers/staging/lustre/lustre/ptlrpc/service.c     |   12 +-
+ drivers/staging/lustre/lustre/ptlrpc/wiretest.c    |    2 +
+ drivers/staging/nokia_h4p/Kconfig                  |    9 +
+ drivers/staging/nokia_h4p/Makefile                 |    6 +
+ drivers/staging/nokia_h4p/TODO                     |  140 +
+ drivers/staging/nokia_h4p/hci_h4p.h                |  228 +
+ drivers/staging/nokia_h4p/nokia_core.c             | 1205 +++
+ drivers/staging/nokia_h4p/nokia_fw-bcm.c           |  147 +
+ drivers/staging/nokia_h4p/nokia_fw-csr.c           |  150 +
+ drivers/staging/nokia_h4p/nokia_fw-ti1273.c        |  110 +
+ drivers/staging/nokia_h4p/nokia_fw.c               |  195 +
+ drivers/staging/nokia_h4p/nokia_uart.c             |  199 +
+ drivers/staging/olpc_dcon/olpc_dcon.h              |    2 +-
+ drivers/staging/ozwpan/ozproto.c                   |   42 +-
+ drivers/staging/panel/panel.c                      |   41 +-
+ drivers/staging/rtl8187se/ieee80211/ieee80211.h    |    8 +-
+ drivers/staging/rtl8187se/r8180.h                  |  790 +-
+ drivers/staging/rtl8187se/r8180_core.c             |  254 +-
+ drivers/staging/rtl8187se/r8180_wx.c               |   10 +-
+ drivers/staging/rtl8187se/r8185b_init.c            |   20 +-
+ drivers/staging/rtl8188eu/Kconfig                  |    4 +-
+ drivers/staging/rtl8188eu/Makefile                 |    1 -
+ drivers/staging/rtl8188eu/TODO                     |    5 +
+ drivers/staging/rtl8188eu/core/rtw_ap.c            |   78 +-
+ drivers/staging/rtl8188eu/core/rtw_br_ext.c        |    6 +-
+ drivers/staging/rtl8188eu/core/rtw_cmd.c           |  116 +-
+ drivers/staging/rtl8188eu/core/rtw_debug.c         |    8 +-
+ drivers/staging/rtl8188eu/core/rtw_ieee80211.c     |   55 +-
+ drivers/staging/rtl8188eu/core/rtw_io.c            |   28 -
+ drivers/staging/rtl8188eu/core/rtw_ioctl_set.c     |   35 +-
+ drivers/staging/rtl8188eu/core/rtw_led.c           |    4 +-
+ drivers/staging/rtl8188eu/core/rtw_mlme.c          |  230 +-
+ drivers/staging/rtl8188eu/core/rtw_mlme_ext.c      |  271 +-
+ drivers/staging/rtl8188eu/core/rtw_mp.c            |    9 +-
+ drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c      |   78 -
+ drivers/staging/rtl8188eu/core/rtw_p2p.c           |   50 +-
+ drivers/staging/rtl8188eu/core/rtw_pwrctrl.c       |   27 +-
+ drivers/staging/rtl8188eu/core/rtw_recv.c          |  502 +-
+ drivers/staging/rtl8188eu/core/rtw_security.c      |   93 +-
+ drivers/staging/rtl8188eu/core/rtw_sta_mgt.c       |   87 +-
+ drivers/staging/rtl8188eu/core/rtw_wlan_util.c     |   46 +-
+ drivers/staging/rtl8188eu/core/rtw_xmit.c          |  129 +-
+ .../staging/rtl8188eu/hal/Hal8188ERateAdaptive.c   |   13 +-
+ drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c     |   37 +-
+ drivers/staging/rtl8188eu/hal/hal_intf.c           |    4 -
+ drivers/staging/rtl8188eu/hal/odm.c                |   15 +-
+ drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c |    4 +-
+ drivers/staging/rtl8188eu/hal/odm_interface.c      |  101 -
+ drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c       |   12 -
+ drivers/staging/rtl8188eu/hal/rtl8188e_dm.c        |    2 -
+ drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c  |   87 +-
+ drivers/staging/rtl8188eu/hal/rtl8188e_mp.c        |    6 +-
+ drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c    |   37 +-
+ drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c     |    3 -
+ drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c     |    6 +-
+ drivers/staging/rtl8188eu/hal/usb_halinit.c        |   10 -
+ drivers/staging/rtl8188eu/hal/usb_ops_linux.c      |   63 +-
+ drivers/staging/rtl8188eu/include/drv_types.h      |    6 +
+ drivers/staging/rtl8188eu/include/ethernet.h       |   42 -
+ drivers/staging/rtl8188eu/include/h2clbk.h         |   35 -
+ drivers/staging/rtl8188eu/include/if_ether.h       |  111 -
+ drivers/staging/rtl8188eu/include/ioctl_cfg80211.h |  107 -
+ drivers/staging/rtl8188eu/include/ip.h             |  126 -
+ drivers/staging/rtl8188eu/include/nic_spec.h       |   44 -
+ drivers/staging/rtl8188eu/include/odm_interface.h  |   23 -
+ drivers/staging/rtl8188eu/include/osdep_service.h  |   34 -
+ drivers/staging/rtl8188eu/include/recv_osdep.h     |   10 +-
+ drivers/staging/rtl8188eu/include/rtl8188e_hal.h   |   11 -
+ drivers/staging/rtl8188eu/include/rtl8188e_recv.h  |    7 +-
+ drivers/staging/rtl8188eu/include/rtw_debug.h      |   24 -
+ drivers/staging/rtl8188eu/include/rtw_io.h         |   44 -
+ drivers/staging/rtl8188eu/include/rtw_ioctl.h      |    2 -
+ drivers/staging/rtl8188eu/include/rtw_mlme.h       |   32 -
+ drivers/staging/rtl8188eu/include/rtw_mlme_ext.h   |   49 +-
+ drivers/staging/rtl8188eu/include/rtw_pwrctrl.h    |    4 -
+ drivers/staging/rtl8188eu/include/rtw_recv.h       |  139 +-
+ drivers/staging/rtl8188eu/include/rtw_xmit.h       |    5 -
+ drivers/staging/rtl8188eu/os_dep/ioctl_linux.c     |  161 +-
+ drivers/staging/rtl8188eu/os_dep/mlme_linux.c      |    9 +-
+ drivers/staging/rtl8188eu/os_dep/os_intfs.c        |   10 +-
+ drivers/staging/rtl8188eu/os_dep/osdep_service.c   |   35 +-
+ drivers/staging/rtl8188eu/os_dep/recv_linux.c      |   44 +-
+ drivers/staging/rtl8188eu/os_dep/rtw_android.c     |    1 -
+ drivers/staging/rtl8188eu/os_dep/usb_intf.c        |   19 +-
+ drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c   |    5 -
+ drivers/staging/rtl8188eu/os_dep/xmit_linux.c      |   17 +-
+ drivers/staging/rtl8192e/rtl8192e/rtl_pci.h        |   52 -
+ drivers/staging/rtl8192e/rtl8192e/rtl_wx.c         |    2 +-
+ drivers/staging/rtl8192u/ieee80211/EndianFree.h    |  194 -
+ drivers/staging/rtl8192u/ieee80211/aes.c           |  468 --
+ drivers/staging/rtl8192u/ieee80211/arc4.c          |  103 -
+ drivers/staging/rtl8192u/ieee80211/autoload.c      |   40 -
+ drivers/staging/rtl8192u/ieee80211/cipher.c        |  298 -
+ drivers/staging/rtl8192u/ieee80211/compress.c      |   64 -
+ drivers/staging/rtl8192u/ieee80211/crypto_compat.h |   58 -
+ drivers/staging/rtl8192u/ieee80211/digest.c        |  108 -
+ drivers/staging/rtl8192u/ieee80211/internal.h      |   81 -
+ drivers/staging/rtl8192u/ieee80211/michael_mic.c   |  194 -
+ drivers/staging/rtl8192u/ieee80211/proc.c          |  112 -
+ drivers/staging/rtl8192u/ieee80211/rtl_crypto.h    |  398 -
+ drivers/staging/rtl8192u/ieee80211/scatterwalk.c   |  117 -
+ drivers/staging/rtl8192u/ieee80211/scatterwalk.h   |   51 -
+ drivers/staging/rtl8192u/r819xU_HTGen.h            |   12 -
+ drivers/staging/rtl8192u/r819xU_HTType.h           |  379 -
+ drivers/staging/rtl8712/rtl8712_recv.c             |    2 -
+ drivers/staging/rtl8821ae/base.c                   |  154 +-
+ .../staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c  |    2 +-
+ .../staging/rtl8821ae/btcoexist/habtc8723a1ant.c   |    2 +-
+ .../staging/rtl8821ae/btcoexist/halbtc8192e1ant.c  |    2 +-
+ .../staging/rtl8821ae/btcoexist/halbtc8192e2ant.c  |    2 +-
+ .../staging/rtl8821ae/btcoexist/halbtc8723a2ant.c  |    2 +-
+ .../staging/rtl8821ae/btcoexist/halbtc8723b1ant.c  |    2 +-
+ .../staging/rtl8821ae/btcoexist/halbtc8723b2ant.c  |    2 +-
+ drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.c |   10 -
+ drivers/staging/rtl8821ae/core.c                   |   12 +-
+ drivers/staging/rtl8821ae/core.h                   |    8 +-
+ drivers/staging/rtl8821ae/debug.c                  |   10 +-
+ drivers/staging/rtl8821ae/debug.h                  |   12 +-
+ drivers/staging/rtl8821ae/efuse.c                  |   26 +-
+ drivers/staging/rtl8821ae/pci.c                    |  274 +-
+ drivers/staging/rtl8821ae/pci.h                    |    8 +-
+ drivers/staging/rtl8821ae/ps.c                     |    2 +-
+ drivers/staging/rtl8821ae/regd.c                   |    4 +-
+ drivers/staging/rtl8821ae/regd.h                   |    4 +-
+ drivers/staging/rtl8821ae/rtl8821ae/dm.c           |   24 +-
+ drivers/staging/rtl8821ae/rtl8821ae/fw.c           |    8 +-
+ .../staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h   |    2 +-
+ drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c      |    4 +-
+ drivers/staging/rtl8821ae/rtl8821ae/hw.c           |   13 +-
+ drivers/staging/rtl8821ae/rtl8821ae/phy.c          |    4 +-
+ drivers/staging/rtl8821ae/rtl8821ae/phy.h          |    2 +-
+ drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h       |   10 +-
+ drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c    |    2 +-
+ drivers/staging/rtl8821ae/rtl8821ae/reg.h          |   28 +-
+ drivers/staging/rtl8821ae/rtl8821ae/sw.c           |    4 +-
+ drivers/staging/rtl8821ae/rtl8821ae/trx.c          |    8 +-
+ drivers/staging/rtl8821ae/wifi.h                   |  486 +-
+ drivers/staging/rts5208/ms.c                       |    2 +-
+ drivers/staging/sb105x/Kconfig                     |    9 -
+ drivers/staging/sb105x/Makefile                    |    3 -
+ drivers/staging/sb105x/sb_mp_register.h            |  295 -
+ drivers/staging/sb105x/sb_pci_mp.c                 | 3189 --------
+ drivers/staging/sb105x/sb_pci_mp.h                 |  291 -
+ drivers/staging/sb105x/sb_ser_core.h               |  368 -
+ drivers/staging/sbe-2t3e3/module.c                 |    2 +-
+ drivers/staging/sep/sep_crypto.c                   |    2 +-
+ drivers/staging/sep/sep_main.c                     |   93 +-
+ drivers/staging/silicom/bp_mod.h                   |    2 -
+ drivers/staging/silicom/bpctl_mod.c                |  604 +-
+ drivers/staging/silicom/bypasslib/bp_ioctl.h       |    4 +-
+ drivers/staging/slicoss/README                     |   40 -
+ drivers/staging/slicoss/TODO                       |   38 +
+ drivers/staging/slicoss/slic.h                     |    9 +-
+ drivers/staging/slicoss/slicoss.c                  |   34 +-
+ drivers/staging/sm7xxfb/Kconfig                    |   13 -
+ drivers/staging/sm7xxfb/Makefile                   |    1 -
+ drivers/staging/sm7xxfb/TODO                       |    9 -
+ drivers/staging/sm7xxfb/sm7xx.h                    |  779 --
+ drivers/staging/sm7xxfb/sm7xxfb.c                  | 1028 ---
+ drivers/staging/tidspbridge/Kconfig                |    2 +-
+ drivers/staging/tidspbridge/dynload/tramp.c        |    2 +-
+ drivers/staging/tidspbridge/rmgr/dbdcd.c           |    4 +-
+ drivers/staging/tidspbridge/rmgr/drv.c             |    2 +-
+ drivers/staging/tidspbridge/rmgr/nldr.c            |    2 +-
+ drivers/staging/tidspbridge/rmgr/node.c            |    6 +-
+ drivers/staging/usbip/stub.h                       |    2 +-
+ drivers/staging/usbip/stub_dev.c                   |  155 +-
+ drivers/staging/usbip/stub_main.c                  |    6 +-
+ drivers/staging/usbip/stub_rx.c                    |    2 +-
+ drivers/staging/usbip/usbip_common.c               |   22 +-
+ .../staging/usbip/userspace/libsrc/usbip_common.c  |    2 +
+ .../staging/usbip/userspace/libsrc/usbip_common.h  |    8 +-
+ .../usbip/userspace/libsrc/usbip_host_driver.c     |   48 +-
+ .../staging/usbip/userspace/libsrc/vhci_driver.c   |   53 +-
+ drivers/staging/usbip/userspace/src/usbip_bind.c   |  142 +-
+ drivers/staging/usbip/userspace/src/usbip_list.c   |   19 +-
+ drivers/staging/usbip/userspace/src/usbip_unbind.c |   51 +-
+ drivers/staging/usbip/userspace/src/usbipd.c       |   15 -
+ drivers/staging/usbip/vhci_hcd.c                   |    2 -
+ drivers/staging/usbip/vhci_sysfs.c                 |    5 +-
+ drivers/staging/vt6656/card.h                      |    7 -
+ drivers/staging/vt6656/device.h                    |   85 +-
+ drivers/staging/vt6656/dpc.c                       |   92 +-
+ drivers/staging/vt6656/int.c                       |  150 +-
+ drivers/staging/vt6656/int.h                       |   45 +-
+ drivers/staging/vt6656/iwctl.c                     |    3 +-
+ drivers/staging/vt6656/mac.c                       |   16 +-
+ drivers/staging/vt6656/mac.h                       |    2 +-
+ drivers/staging/vt6656/main_usb.c                  |  348 +-
+ drivers/staging/vt6656/power.c                     |    6 +-
+ drivers/staging/vt6656/rxtx.c                      |   37 +-
+ drivers/staging/vt6656/usbpipe.c                   |  447 +-
+ drivers/staging/vt6656/wcmd.c                      |   77 +-
+ drivers/staging/vt6656/wcmd.h                      |    4 +-
+ drivers/staging/vt6656/wmgr.c                      |    8 +-
+ drivers/staging/wlan-ng/cfg80211.c                 |    7 +-
+ drivers/staging/xgifb/XGI_main_26.c                |   15 +-
+ drivers/usb/core/generic.c                         |    1 +
+ drivers/usb/core/message.c                         |    1 +
+ include/linux/hid-sensor-ids.h                     |   10 +
+ include/linux/iio/iio.h                            |   16 +-
+ include/linux/platform_data/bt-nokia-h4p.h         |   38 +
+ include/linux/usb.h                                |    4 +
+ 523 files changed, 26194 insertions(+), 34342 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
+ create mode 100644 drivers/iio/adc/vf610_adc.c
+ create mode 100644 drivers/iio/humidity/si7005.c
+ create mode 100644 drivers/iio/light/hid-sensor-prox.c
+ create mode 100644 drivers/iio/light/ltr501.c
+ create mode 100644 drivers/iio/pressure/hid-sensor-press.c
+ rename drivers/{staging => misc}/echo/Kconfig (100%)
+ rename drivers/{staging => misc}/echo/Makefile (100%)
+ rename drivers/{staging => misc}/echo/echo.c (100%)
+ rename drivers/{staging => misc}/echo/echo.h (100%)
+ rename drivers/{staging => misc}/echo/fir.h (100%)
+ rename drivers/{staging => misc}/echo/oslec.h (100%)
+ create mode 100644 drivers/staging/android/uapi/android_alarm.h
+ create mode 100644 drivers/staging/android/uapi/ashmem.h
+ create mode 100644 drivers/staging/android/uapi/binder.h
+ create mode 100644 drivers/staging/android/uapi/sw_sync.h
+ create mode 100644 drivers/staging/android/uapi/sync.h
+ create mode 100644 drivers/staging/dgap/dgap.c
+ create mode 100644 drivers/staging/dgap/dgap.h
+ delete mode 100644 drivers/staging/dgap/dgap_conf.h
+ delete mode 100644 drivers/staging/dgap/dgap_downld.h
+ delete mode 100644 drivers/staging/dgap/dgap_driver.c
+ delete mode 100644 drivers/staging/dgap/dgap_driver.h
+ delete mode 100644 drivers/staging/dgap/dgap_fep5.c
+ delete mode 100644 drivers/staging/dgap/dgap_fep5.h
+ delete mode 100644 drivers/staging/dgap/dgap_kcompat.h
+ delete mode 100644 drivers/staging/dgap/dgap_parse.c
+ delete mode 100644 drivers/staging/dgap/dgap_parse.h
+ delete mode 100644 drivers/staging/dgap/dgap_pci.h
+ delete mode 100644 drivers/staging/dgap/dgap_sysfs.c
+ delete mode 100644 drivers/staging/dgap/dgap_sysfs.h
+ delete mode 100644 drivers/staging/dgap/dgap_trace.c
+ delete mode 100644 drivers/staging/dgap/dgap_trace.h
+ delete mode 100644 drivers/staging/dgap/dgap_tty.c
+ delete mode 100644 drivers/staging/dgap/dgap_tty.h
+ delete mode 100644 drivers/staging/dgap/dgap_types.h
+ delete mode 100644 drivers/staging/dgap/digi.h
+ delete mode 100644 drivers/staging/dgap/downld.c
+ delete mode 100644 drivers/staging/echo/TODO
+ create mode 100644 drivers/staging/gs_fpgaboot/Kconfig
+ create mode 100644 drivers/staging/gs_fpgaboot/Makefile
+ create mode 100644 drivers/staging/gs_fpgaboot/README
+ create mode 100644 drivers/staging/gs_fpgaboot/TODO
+ create mode 100644 drivers/staging/gs_fpgaboot/gs_fpgaboot.c
+ create mode 100644 drivers/staging/gs_fpgaboot/gs_fpgaboot.h
+ create mode 100644 drivers/staging/gs_fpgaboot/io.c
+ create mode 100644 drivers/staging/gs_fpgaboot/io.h
+ create mode 100644 drivers/staging/iio/Documentation/lsiio.c
+ delete mode 100644 drivers/staging/imx-drm/imx-fb.c
+ delete mode 100644 drivers/staging/imx-drm/imx-fbdev.c
+ create mode 100644 drivers/staging/nokia_h4p/Kconfig
+ create mode 100644 drivers/staging/nokia_h4p/Makefile
+ create mode 100644 drivers/staging/nokia_h4p/TODO
+ create mode 100644 drivers/staging/nokia_h4p/hci_h4p.h
+ create mode 100644 drivers/staging/nokia_h4p/nokia_core.c
+ create mode 100644 drivers/staging/nokia_h4p/nokia_fw-bcm.c
+ create mode 100644 drivers/staging/nokia_h4p/nokia_fw-csr.c
+ create mode 100644 drivers/staging/nokia_h4p/nokia_fw-ti1273.c
+ create mode 100644 drivers/staging/nokia_h4p/nokia_fw.c
+ create mode 100644 drivers/staging/nokia_h4p/nokia_uart.c
+ delete mode 100644 drivers/staging/rtl8188eu/hal/odm_interface.c
+ delete mode 100644 drivers/staging/rtl8188eu/include/ethernet.h
+ delete mode 100644 drivers/staging/rtl8188eu/include/h2clbk.h
+ delete mode 100644 drivers/staging/rtl8188eu/include/if_ether.h
+ delete mode 100644 drivers/staging/rtl8188eu/include/ioctl_cfg80211.h
+ delete mode 100644 drivers/staging/rtl8188eu/include/ip.h
+ delete mode 100644 drivers/staging/rtl8188eu/include/nic_spec.h
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/EndianFree.h
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/aes.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/arc4.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/autoload.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/cipher.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/compress.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/crypto_compat.h
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/digest.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/internal.h
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/michael_mic.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/proc.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/rtl_crypto.h
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/scatterwalk.c
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/scatterwalk.h
+ delete mode 100644 drivers/staging/rtl8192u/r819xU_HTGen.h
+ delete mode 100644 drivers/staging/rtl8192u/r819xU_HTType.h
+ delete mode 100644 drivers/staging/sb105x/Kconfig
+ delete mode 100644 drivers/staging/sb105x/Makefile
+ delete mode 100644 drivers/staging/sb105x/sb_mp_register.h
+ delete mode 100644 drivers/staging/sb105x/sb_pci_mp.c
+ delete mode 100644 drivers/staging/sb105x/sb_pci_mp.h
+ delete mode 100644 drivers/staging/sb105x/sb_ser_core.h
+ create mode 100644 drivers/staging/slicoss/TODO
+ delete mode 100644 drivers/staging/sm7xxfb/Kconfig
+ delete mode 100644 drivers/staging/sm7xxfb/Makefile
+ delete mode 100644 drivers/staging/sm7xxfb/TODO
+ delete mode 100644 drivers/staging/sm7xxfb/sm7xx.h
+ delete mode 100644 drivers/staging/sm7xxfb/sm7xxfb.c
+ create mode 100644 include/linux/platform_data/bt-nokia-h4p.h
+$ git am -3 ../patches/0001-ARM-dts-i.MX53-merge-fix-patch.patch
+Applying: ARM: dts: i.MX53: merge fix patch
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/arm/boot/dts/imx53-qsb-common.dtsi
+$ git add -A .
+$ git commit -v -a --amend
+[master 3ed45a7217dd] Merge remote-tracking branch 'staging/staging-next'
+Merging char-misc/char-misc-next (aa074c1c805a Merge 3.14-rc5 into char-misc-next)
+$ git merge char-misc/char-misc-next
+Auto-merging include/linux/regmap.h
+Auto-merging include/linux/mod_devicetable.h
+Auto-merging include/linux/miscdevice.h
+Auto-merging drivers/video/fbdev/uvesafb.c
+Auto-merging drivers/video/fbdev/hyperv_fb.c
+Auto-merging drivers/mtd/nand/fsl_ifc_nand.c
+Auto-merging drivers/mtd/nand/Kconfig
+Auto-merging drivers/memory/fsl_ifc.c
+Auto-merging drivers/iio/adc/Makefile
+Auto-merging drivers/iio/adc/Kconfig
+Auto-merging drivers/connector/connector.c
+Auto-merging drivers/char/hw_random/core.c
+Auto-merging drivers/Makefile
+Removing arch/avr32/boards/mimc200/fram.c
+Auto-merging MAINTAINERS
+Auto-merging Documentation/devices.txt
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/Makefile                     |    2 +-
+ Documentation/DocBook/w1.tmpl                      |  101 ++
+ Documentation/connector/cn_test.c                  |    2 +-
+ Documentation/devices.txt                          |    2 +
+ .../{powerpc => memory-controllers}/fsl/ifc.txt    |    0
+ .../bindings/memory-controllers/ti-aemif.txt       |  210 ++++
+ .../bindings/misc/allwinner,sunxi-sid.txt          |    4 +-
+ Documentation/devicetree/bindings/misc/sram.txt    |   35 +
+ .../bindings/spmi/qcom,spmi-pmic-arb.txt           |   61 ++
+ Documentation/devicetree/bindings/spmi/spmi.txt    |   41 +
+ Documentation/fmc/fmc-write-eeprom.txt             |   77 +-
+ Documentation/w1/masters/ds2490                    |    2 -
+ Documentation/w1/w1.netlink                        |    8 +-
+ MAINTAINERS                                        |    6 +
+ arch/arm/boot/dts/sun4i-a10.dtsi                   |    2 +-
+ arch/arm/boot/dts/sun5i-a10s.dtsi                  |    2 +-
+ arch/arm/boot/dts/sun5i-a13.dtsi                   |    2 +-
+ arch/avr32/boards/mimc200/Makefile                 |    2 +-
+ arch/avr32/boards/mimc200/fram.c                   |   82 --
+ arch/powerpc/Kconfig                               |    4 -
+ arch/powerpc/sysdev/Makefile                       |    1 -
+ drivers/Kconfig                                    |    4 +
+ drivers/Makefile                                   |    2 +
+ drivers/base/regmap/regmap-spmi.c                  |  228 +++-
+ drivers/char/agp/frontend.c                        |    1 -
+ drivers/char/agp/generic.c                         |    1 -
+ drivers/char/agp/intel-gtt.c                       |    1 -
+ drivers/char/agp/sgi-agp.c                         |    1 -
+ drivers/char/hw_random/bcm2835-rng.c               |    1 -
+ drivers/char/hw_random/core.c                      |    1 -
+ drivers/char/hw_random/exynos-rng.c                |    1 -
+ drivers/char/hw_random/n2-drv.c                    |    1 -
+ drivers/char/hw_random/nomadik-rng.c               |    1 -
+ drivers/char/hw_random/octeon-rng.c                |    1 -
+ drivers/char/ipmi/ipmi_si_intf.c                   |    1 -
+ drivers/char/mem.c                                 |    6 +
+ drivers/char/mwave/3780i.c                         |    1 -
+ drivers/char/tile-srom.c                           |    1 -
+ drivers/char/tpm/tpm_i2c_infineon.c                |    1 -
+ drivers/char/tpm/tpm_i2c_stm_st33.c                |    1 -
+ drivers/connector/cn_proc.c                        |   18 +-
+ drivers/connector/connector.c                      |   20 +-
+ drivers/fmc/fmc-core.c                             |   22 +-
+ drivers/fmc/fmc-sdb.c                              |   41 +-
+ drivers/hv/Makefile                                |    2 +-
+ drivers/hv/channel.c                               |   42 +-
+ drivers/hv/hv_balloon.c                            |    3 +-
+ drivers/hv/hv_fcopy.c                              |  414 ++++++++
+ drivers/hv/hv_kvp.c                                |    4 +-
+ drivers/hv/hv_snapshot.c                           |    2 +-
+ drivers/hv/hv_util.c                               |   11 +
+ drivers/hv/hyperv_vmbus.h                          |    8 +-
+ drivers/hv/ring_buffer.c                           |   17 +-
+ drivers/hv/vmbus_drv.c                             |   51 +-
+ drivers/iio/adc/Kconfig                            |   10 +
+ drivers/iio/adc/Makefile                           |    1 +
+ drivers/iio/adc/men_z188_adc.c                     |  171 +++
+ drivers/mcb/Kconfig                                |   29 +
+ drivers/mcb/Makefile                               |    7 +
+ drivers/mcb/mcb-core.c                             |  414 ++++++++
+ drivers/mcb/mcb-internal.h                         |  118 +++
+ drivers/mcb/mcb-parse.c                            |  159 +++
+ drivers/mcb/mcb-pci.c                              |  114 ++
+ drivers/md/dm-log-userspace-transfer.c             |    2 +-
+ drivers/memory/Kconfig                             |   15 +
+ drivers/memory/Makefile                            |    2 +
+ {arch/powerpc/sysdev => drivers/memory}/fsl_ifc.c  |    8 +-
+ drivers/memory/ti-aemif.c                          |  427 ++++++++
+ drivers/misc/ad525x_dpot.c                         |    1 -
+ drivers/misc/apds9802als.c                         |    1 -
+ drivers/misc/bmp085.c                              |    1 -
+ drivers/misc/carma/carma-fpga.c                    |    1 -
+ drivers/misc/ds1682.c                              |    1 -
+ drivers/misc/eeprom/at25.c                         |    1 -
+ drivers/misc/eeprom/eeprom.c                       |    1 -
+ drivers/misc/eeprom/eeprom_93xx46.c                |    1 -
+ drivers/misc/eeprom/max6875.c                      |    1 -
+ drivers/misc/eeprom/sunxi_sid.c                    |    3 +-
+ drivers/misc/genwqe/card_debugfs.c                 |    1 -
+ drivers/misc/hmc6352.c                             |    1 -
+ drivers/misc/isl29003.c                            |    1 -
+ drivers/misc/isl29020.c                            |    1 -
+ drivers/misc/lattice-ecp3-config.c                 |    1 -
+ drivers/misc/lis3lv02d/lis3lv02d.c                 |    1 -
+ drivers/misc/lis3lv02d/lis3lv02d_i2c.c             |    1 -
+ drivers/misc/lis3lv02d/lis3lv02d_spi.c             |    1 -
+ drivers/misc/lkdtm.c                               |   74 +-
+ drivers/misc/mei/Kconfig                           |    9 +
+ drivers/misc/mei/Makefile                          |    6 +-
+ drivers/misc/mei/amthif.c                          |   66 +-
+ drivers/misc/mei/bus.c                             |   20 +-
+ drivers/misc/mei/client.c                          |  224 ++--
+ drivers/misc/mei/client.h                          |    4 +-
+ drivers/misc/mei/debugfs.c                         |   54 +
+ drivers/misc/mei/hbm.c                             |  277 ++---
+ drivers/misc/mei/hbm.h                             |    1 +
+ drivers/misc/mei/hw-me.c                           |   17 +-
+ drivers/misc/mei/hw-txe-regs.h                     |  294 ++++++
+ drivers/misc/mei/hw-txe.c                          | 1107 ++++++++++++++++++++
+ drivers/misc/mei/hw-txe.h                          |   74 ++
+ drivers/misc/mei/hw.h                              |   20 +-
+ drivers/misc/mei/init.c                            |   43 +-
+ drivers/misc/mei/interrupt.c                       |  156 +--
+ drivers/misc/mei/main.c                            |    4 +-
+ drivers/misc/mei/mei_dev.h                         |   29 +-
+ drivers/misc/mei/nfc.c                             |   14 +-
+ drivers/misc/mei/pci-me.c                          |    6 +-
+ drivers/misc/mei/pci-txe.c                         |  293 ++++++
+ drivers/misc/mei/wd.c                              |  135 +--
+ drivers/misc/mic/host/mic_intr.c                   |    2 +-
+ drivers/misc/sram.c                                |  127 ++-
+ drivers/misc/ti-st/st_core.c                       |    1 -
+ drivers/misc/ti_dac7512.c                          |    1 -
+ drivers/misc/tsl2550.c                             |    1 -
+ drivers/misc/vmw_vmci/vmci_guest.c                 |    7 +-
+ drivers/mtd/nand/Kconfig                           |    1 +
+ drivers/mtd/nand/fsl_ifc_nand.c                    |    2 +-
+ drivers/parport/share.c                            |    3 +-
+ drivers/spmi/Kconfig                               |   27 +
+ drivers/spmi/Makefile                              |    6 +
+ drivers/spmi/spmi-pmic-arb.c                       |  778 ++++++++++++++
+ drivers/spmi/spmi.c                                |  609 +++++++++++
+ drivers/video/fbdev/hyperv_fb.c                    |   88 +-
+ drivers/video/fbdev/uvesafb.c                      |    4 +-
+ drivers/vme/bridges/vme_ca91cx42.c                 |   29 +-
+ drivers/vme/bridges/vme_tsi148.c                   |   18 +-
+ drivers/w1/masters/Kconfig                         |    3 +-
+ drivers/w1/masters/ds2490.c                        |  155 ++-
+ drivers/w1/masters/mxc_w1.c                        |   43 +-
+ drivers/w1/masters/w1-gpio.c                       |   19 +-
+ drivers/w1/slaves/Kconfig                          |    5 -
+ drivers/w1/slaves/w1_therm.c                       |   21 +-
+ drivers/w1/w1.c                                    |  269 +++--
+ drivers/w1/w1.h                                    |  186 +++-
+ drivers/w1/w1_family.c                             |    8 +
+ drivers/w1/w1_family.h                             |   13 +
+ drivers/w1/w1_int.c                                |   25 +-
+ drivers/w1/w1_io.c                                 |  102 +-
+ drivers/w1/w1_netlink.c                            |  359 +++++--
+ drivers/w1/w1_netlink.h                            |   33 +-
+ include/dt-bindings/spmi/spmi.h                    |   18 +
+ include/linux/connector.h                          |    2 +-
+ include/linux/fmc-sdb.h                            |    2 +
+ .../include/asm => include/linux}/fsl_ifc.h        |    0
+ include/linux/hyperv.h                             |  351 +------
+ include/linux/mcb.h                                |  119 +++
+ include/linux/miscdevice.h                         |   16 +-
+ include/linux/mod_devicetable.h                    |   13 +
+ include/linux/regmap.h                             |   12 +-
+ include/linux/spmi.h                               |  191 ++++
+ include/uapi/linux/Kbuild                          |    1 +
+ include/uapi/linux/hyperv.h                        |  390 +++++++
+ tools/Makefile                                     |   11 +-
+ tools/hv/Makefile                                  |   13 +
+ tools/hv/hv_fcopy_daemon.c                         |  195 ++++
+ tools/hv/hv_vss_daemon.c                           |    2 +
+ 156 files changed, 8738 insertions(+), 1523 deletions(-)
+ create mode 100644 Documentation/DocBook/w1.tmpl
+ rename Documentation/devicetree/bindings/{powerpc => memory-controllers}/fsl/ifc.txt (100%)
+ create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
+ create mode 100644 Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
+ create mode 100644 Documentation/devicetree/bindings/spmi/spmi.txt
+ delete mode 100644 arch/avr32/boards/mimc200/fram.c
+ create mode 100644 drivers/hv/hv_fcopy.c
+ create mode 100644 drivers/iio/adc/men_z188_adc.c
+ create mode 100644 drivers/mcb/Kconfig
+ create mode 100644 drivers/mcb/Makefile
+ create mode 100644 drivers/mcb/mcb-core.c
+ create mode 100644 drivers/mcb/mcb-internal.h
+ create mode 100644 drivers/mcb/mcb-parse.c
+ create mode 100644 drivers/mcb/mcb-pci.c
+ rename {arch/powerpc/sysdev => drivers/memory}/fsl_ifc.c (98%)
+ create mode 100644 drivers/memory/ti-aemif.c
+ create mode 100644 drivers/misc/mei/hw-txe-regs.h
+ create mode 100644 drivers/misc/mei/hw-txe.c
+ create mode 100644 drivers/misc/mei/hw-txe.h
+ create mode 100644 drivers/misc/mei/pci-txe.c
+ create mode 100644 drivers/spmi/Kconfig
+ create mode 100644 drivers/spmi/Makefile
+ create mode 100644 drivers/spmi/spmi-pmic-arb.c
+ create mode 100644 drivers/spmi/spmi.c
+ create mode 100644 include/dt-bindings/spmi/spmi.h
+ rename {arch/powerpc/include/asm => include/linux}/fsl_ifc.h (100%)
+ create mode 100644 include/linux/mcb.h
+ create mode 100644 include/linux/spmi.h
+ create mode 100644 include/uapi/linux/hyperv.h
+ create mode 100644 tools/hv/Makefile
+ create mode 100644 tools/hv/hv_fcopy_daemon.c
+$ git am -3 ../patches/0001-Revert-mcb-Add-PCI-carrier-for-MEN-Chameleon-Bus.patch
+Applying: Revert "mcb: Add PCI carrier for MEN Chameleon Bus"
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/mcb/Kconfig
+M	drivers/mcb/Makefile
+M	drivers/mcb/mcb-internal.h
+D	drivers/mcb/mcb-pci.c
+$ git add -A .
+$ git commit -v -a --amend
+[master b308410a8e26] Merge remote-tracking branch 'char-misc/char-misc-next'
+$ git am -3 ../patches/0001-Revert-iio-adc-Add-MEN-16z188-ADC-driver.patch
+Applying: Revert "iio: adc: Add MEN 16z188 ADC driver"
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/iio/adc/Kconfig
+M	drivers/iio/adc/Makefile
+D	drivers/iio/adc/men_z188_adc.c
+$ git add -A .
+$ git commit -v -a --amend
+[master aaca890a4679] Merge remote-tracking branch 'char-misc/char-misc-next'
+Merging cgroup/for-next (392a65859327 Merge branch 'for-3.15' into for-next)
+$ git merge cgroup/for-next
+Resolved 'mm/memcontrol.c' using previous resolution.
+Auto-merging mm/memory-failure.c
+Auto-merging mm/memcontrol.c
+CONFLICT (content): Merge conflict in mm/memcontrol.c
+Auto-merging kernel/sched/debug.c
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/events/core.c
+Auto-merging init/Kconfig
+Auto-merging fs/kernfs/dir.c
+Auto-merging fs/bio.c
+Auto-merging block/cfq-iosched.c
+Auto-merging block/blk-cgroup.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 508b16e2a62d] Merge remote-tracking branch 'cgroup/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/sparc/kernel/leon_pci_grpci2.c |    1 +
+ arch/sparc/kernel/sun4m_irq.c       |    2 +
+ block/blk-cgroup.c                  |   11 +-
+ block/blk-cgroup.h                  |   14 +-
+ block/blk-throttle.c                |    4 -
+ block/cfq-iosched.c                 |    3 -
+ fs/bio.c                            |    2 +-
+ fs/kernfs/dir.c                     |    1 +
+ include/linux/cgroup.h              |  260 ++-
+ include/linux/cgroup_subsys.h       |   30 +-
+ include/linux/hugetlb_cgroup.h      |    2 +-
+ include/linux/memcontrol.h          |    2 +-
+ include/net/cls_cgroup.h            |    2 +-
+ include/net/netprio_cgroup.h        |   17 +-
+ init/Kconfig                        |    1 +
+ kernel/cgroup.c                     | 3448 ++++++++++++++---------------------
+ kernel/cgroup_freezer.c             |   38 +-
+ kernel/cpuset.c                     |  270 +--
+ kernel/events/core.c                |   25 +-
+ kernel/sched/core.c                 |   10 +-
+ kernel/sched/cpuacct.c              |    6 +-
+ kernel/sched/debug.c                |    3 +-
+ mm/hugetlb_cgroup.c                 |    9 +-
+ mm/memcontrol.c                     |  106 +-
+ mm/memory-failure.c                 |    8 +-
+ net/Kconfig                         |    2 +-
+ net/core/netclassid_cgroup.c        |   15 +-
+ net/core/netprio_cgroup.c           |   39 +-
+ net/ipv4/tcp_memcontrol.c           |    2 +-
+ security/device_cgroup.c            |    8 +-
+ 30 files changed, 1716 insertions(+), 2625 deletions(-)
+$ git am -3 ../patches/0001-cgroup-fix-up-for-kernfs_mount-API-change.patch
+Applying: cgroup: fix up for kernfs_mount API change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	kernel/cgroup.c
+$ git add -A .
+$ git commit -v -a --amend
+[master a7ba6055ee13] Merge remote-tracking branch 'cgroup/for-next'
+Merging scsi/for-next (960dfc4eb23a Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux)
+$ git merge scsi/for-next
+Already up-to-date.
+Merging target-updates/for-next (9af6de4a22c5 target: silence GCC warning in target_alua_state_check)
+$ git merge target-updates/for-next
+Auto-merging drivers/target/target_core_alua.c
+Merge made by the 'recursive' strategy.
+ drivers/target/target_core_alua.c | 95 ++++++++++++++++++---------------------
+ 1 file changed, 44 insertions(+), 51 deletions(-)
+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 (1e999c2ba8dd Merge branch 'devel' into for-next)
+$ git merge pinctrl/for-next
+Auto-merging arch/arm/boot/dts/r8a7791.dtsi
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/pinctrl/pinctrl-single.txt |   7 +
+ .../devicetree/bindings/pinctrl/pinctrl-st.txt     |  73 ++++-
+ .../bindings/pinctrl/samsung-pinctrl.txt           |   1 +
+ arch/arm/boot/dts/r8a7791.dtsi                     |   2 +-
+ arch/blackfin/include/asm/irq.h                    |   9 -
+ drivers/pinctrl/Kconfig                            |   2 +-
+ drivers/pinctrl/devicetree.c                       |   4 +-
+ drivers/pinctrl/pinctrl-adi2-bf54x.c               | 138 ++++-----
+ drivers/pinctrl/pinctrl-adi2-bf60x.c               | 128 ++++----
+ drivers/pinctrl/pinctrl-adi2.c                     |  31 +-
+ drivers/pinctrl/pinctrl-adi2.h                     |   8 +-
+ drivers/pinctrl/pinctrl-at91.c                     |  39 +++
+ drivers/pinctrl/pinctrl-exynos.c                   |  82 +++++
+ drivers/pinctrl/pinctrl-imx.c                      |   2 +-
+ drivers/pinctrl/pinctrl-msm.c                      |  27 ++
+ drivers/pinctrl/pinctrl-msm8x74.c                  |  13 +-
+ drivers/pinctrl/pinctrl-nomadik.c                  |  19 +-
+ drivers/pinctrl/pinctrl-samsung.c                  |   2 +
+ drivers/pinctrl/pinctrl-samsung.h                  |   1 +
+ drivers/pinctrl/pinctrl-single.c                   |   3 +
+ drivers/pinctrl/pinctrl-st.c                       | 337 ++++++++++++++++++++-
+ drivers/pinctrl/pinctrl-sunxi-pins.h               |  12 +-
+ drivers/pinctrl/pinctrl-sunxi.c                    |   6 +-
+ drivers/pinctrl/pinctrl-sunxi.h                    |   6 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a7790.c               |  42 +++
+ drivers/pinctrl/sh-pfc/pfc-r8a7791.c               | 127 ++++++++
+ drivers/pinctrl/sirf/pinctrl-atlas6.c              |  46 ++-
+ drivers/pinctrl/sirf/pinctrl-prima2.c              |   3 +-
+ drivers/pinctrl/sirf/pinctrl-sirf.c                |   3 +-
+ 29 files changed, 977 insertions(+), 196 deletions(-)
+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
+Merge made by the 'recursive' strategy.
+ drivers/remoteproc/da8xx_remoteproc.c | 16 +---------------
+ drivers/remoteproc/ste_modem_rproc.c  |  4 ++--
+ 2 files changed, 3 insertions(+), 17 deletions(-)
+Merging rpmsg/for-next (397944df3290 rpmsg: fix kconfig dependencies for VIRTIO)
+$ git merge rpmsg/for-next
+Already up-to-date.
+Merging gpio/for-next (41c761a0c892 Merge branch 'devel' into for-next)
+$ git merge gpio/for-next
+Auto-merging drivers/gpio/Kconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/gpio/consumer.txt |  1 +
+ Documentation/gpio/driver.txt   | 35 +++++++++++++++
+ MAINTAINERS                     |  7 +++
+ drivers/gpio/Kconfig            | 10 +++--
+ drivers/gpio/gpio-adp5588.c     | 16 ++++++-
+ drivers/gpio/gpio-bcm-kona.c    | 95 ++++++++++++++++++++++++-----------------
+ drivers/gpio/gpio-clps711x.c    |  1 +
+ drivers/gpio/gpio-davinci.c     |  3 +-
+ drivers/gpio/gpio-generic.c     |  4 +-
+ drivers/gpio/gpio-ich.c         | 70 ++++++++++++++++++++++++------
+ drivers/gpio/gpio-intel-mid.c   |  8 +---
+ drivers/gpio/gpio-mvebu.c       |  7 +++
+ drivers/gpio/gpio-omap.c        | 20 ++-------
+ drivers/gpio/gpio-pca953x.c     | 10 ++++-
+ drivers/gpio/gpio-pl061.c       | 78 ++++++++++++++++++++++-----------
+ drivers/gpio/gpio-rc5t583.c     |  2 +-
+ drivers/gpio/gpiolib-acpi.c     |  2 +-
+ drivers/gpio/gpiolib-of.c       |  3 +-
+ drivers/gpio/gpiolib.c          | 84 ++++++++++++++++++++++++------------
+ include/asm-generic/gpio.h      |  2 +-
+ include/linux/basic_mmio_gpio.h |  1 +
+ include/linux/gpio/consumer.h   | 15 +++----
+ include/linux/gpio/driver.h     | 18 ++++++++
+ include/linux/i2c/adp5588.h     |  4 +-
+ 24 files changed, 346 insertions(+), 150 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
+Auto-merging arch/arm/mm/dma-mapping.c
+Merge made by the 'recursive' strategy.
+ arch/arm/include/asm/dma-iommu.h          |  12 +--
+ arch/arm/mm/dma-mapping.c                 | 144 +++++++++++++++++++++++-------
+ drivers/gpu/drm/exynos/exynos_drm_drv.h   |   2 -
+ drivers/gpu/drm/exynos/exynos_drm_iommu.c |   6 +-
+ drivers/gpu/drm/exynos/exynos_drm_iommu.h |   1 -
+ drivers/iommu/shmobile-iommu.c            |   2 +-
+ 6 files changed, 124 insertions(+), 43 deletions(-)
+Merging pwm/for-next (8468949cddcd pwm: pxa: Use of_match_ptr())
+$ git merge pwm/for-next
+Resolved 'arch/arm/Kconfig' using previous resolution.
+Auto-merging arch/mips/Kconfig
+Auto-merging arch/arm/Kconfig
+CONFLICT (content): Merge conflict in arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 0f5d6761549f] Merge remote-tracking branch 'pwm/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Kconfig           |  4 ----
+ arch/arm/mach-pxa/Kconfig  | 15 ---------------
+ arch/mips/Kconfig          |  1 -
+ drivers/input/misc/Kconfig |  4 ++--
+ drivers/pwm/Kconfig        |  1 +
+ drivers/pwm/pwm-pxa.c      |  4 +---
+ drivers/pwm/pwm-samsung.c  |  5 ++---
+ include/linux/pwm.h        |  2 +-
+ 8 files changed, 7 insertions(+), 29 deletions(-)
+Merging dma-buf/for-next (c0b00a525c12 dma-buf: update debugfs output)
+$ git merge dma-buf/for-next
+Already up-to-date.
+Merging userns/for-next (f58437f1f916 MIPS: VPE: Remove vpe_getuid and vpe_getgid)
+$ git merge userns/for-next
+Already up-to-date.
+Merging ktest/for-next (62183dcac539 ktest: Set CLOSE_CONSOLE_SIGNAL in the kvm.conf)
+$ git merge ktest/for-next
+Merge made by the 'recursive' strategy.
+ tools/testing/ktest/examples/kvm.conf | 4 ++++
+ 1 file changed, 4 insertions(+)
+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 (5ba8dac012c3 Merge branch 'clk-fixes' into clk-next)
+$ git merge clk/clk-next
+Auto-merging arch/arm/boot/dts/socfpga.dtsi
+Merge made by the 'recursive' strategy.
+ .../bindings/arm/hisilicon/hisilicon.txt           |  14 +
+ .../devicetree/bindings/clock/altr_socfpga.txt     |   5 +
+ .../devicetree/bindings/clock/axi-clkgen.txt       |   2 +-
+ .../devicetree/bindings/clock/clock-bindings.txt   |  17 ++
+ .../devicetree/bindings/clock/hi3620-clock.txt     |   1 +
+ arch/arm/boot/dts/socfpga.dtsi                     |   1 +
+ arch/arm/mach-socfpga/socfpga.c                    |   5 -
+ drivers/clk/clk-axi-clkgen.c                       | 312 +++++++++++++++++---
+ drivers/clk/clk-divider.c                          |  10 +-
+ drivers/clk/clk.c                                  |  42 ++-
+ drivers/clk/clkdev.c                               |   2 +
+ drivers/clk/hisilicon/clk-hi3620.c                 | 274 +++++++++++++++++
+ drivers/clk/shmobile/clk-div6.c                    |   2 +-
+ drivers/clk/socfpga/Makefile                       |   3 +
+ drivers/clk/socfpga/clk-gate.c                     | 263 +++++++++++++++++
+ drivers/clk/socfpga/clk-periph.c                   |  94 ++++++
+ drivers/clk/socfpga/clk-pll.c                      | 131 +++++++++
+ drivers/clk/socfpga/clk.c                          | 326 +--------------------
+ drivers/clk/socfpga/clk.h                          |  57 ++++
+ drivers/clk/tegra/clk-periph.c                     |   2 +-
+ drivers/clk/ti/clk-33xx.c                          |   1 -
+ drivers/clk/ti/divider.c                           |   8 +-
+ drivers/clk/ux500/u8500_of_clk.c                   |   3 +-
+ drivers/clk/zynq/clkc.c                            |   4 +-
+ drivers/clk/zynq/pll.c                             |  18 +-
+ include/dt-bindings/clock/hi3620-clock.h           |   5 +
+ include/linux/clk.h                                |  14 +
+ 27 files changed, 1214 insertions(+), 402 deletions(-)
+ create mode 100644 drivers/clk/socfpga/clk-gate.c
+ create mode 100644 drivers/clk/socfpga/clk-periph.c
+ create mode 100644 drivers/clk/socfpga/clk-pll.c
+ create mode 100644 drivers/clk/socfpga/clk.h
+Merging random/dev (a9f069e38cc3 random: use the architectural HWRNG for the SHA's IV in extract_buf())
+$ git merge random/dev
+Merge made by the 'recursive' strategy.
+ drivers/char/random.c | 192 ++++++++++++++++++++++----------------------------
+ 1 file changed, 84 insertions(+), 108 deletions(-)
+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 (168a3eb76a7f aio, memory-hotplug: Fix confliction when migrating and accessing ring pages.)
+$ git merge aio/master
+Merge made by the 'recursive' strategy.
+ fs/aio.c | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+Merging llvmlinux/for-next (f557840d8992 x86, acpi: LLVMLinux: Remove nested functions from Thinkpad ACPI)
+$ git merge llvmlinux/for-next
+Auto-merging drivers/platform/x86/thinkpad_acpi.c
+Merge made by the 'recursive' strategy.
+ drivers/platform/x86/thinkpad_acpi.c | 86 +++++++++++++++++++-----------------
+ 1 file changed, 45 insertions(+), 41 deletions(-)
+Merging akpm-current/current (6dea20c46449 ipc: use device_initcall)
+$ git merge --no-ff akpm-current/current
+Recorded preimage for 'mm/memcontrol.c'
+Auto-merging net/core/rtnetlink.c
+Auto-merging mm/rmap.c
+Auto-merging mm/mempolicy.c
+Auto-merging mm/memory-failure.c
+Auto-merging mm/memcontrol.c
+CONFLICT (content): Merge conflict in mm/memcontrol.c
+Auto-merging kernel/watchdog.c
+Auto-merging kernel/sysctl.c
+Auto-merging kernel/sys.c
+Auto-merging kernel/panic.c
+Auto-merging kernel/locking/Makefile
+Auto-merging kernel/cpuset.c
+Auto-merging ipc/compat.c
+Auto-merging init/Kconfig
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/mm.h
+Auto-merging include/linux/memcontrol.h
+Auto-merging include/linux/fs.h
+Auto-merging fs/xfs/xfs_file.c
+Auto-merging fs/jffs2/fs.c
+Auto-merging fs/gfs2/file.c
+Auto-merging fs/fuse/inode.c
+Auto-merging fs/fuse/file.c
+Auto-merging fs/fs-writeback.c
+Auto-merging fs/f2fs/inode.c
+Auto-merging fs/f2fs/file.c
+Auto-merging fs/ext4/inode.c
+Auto-merging fs/direct-io.c
+Auto-merging fs/cifs/file.c
+Auto-merging drivers/vfio/vfio_iommu_type1.c
+Auto-merging drivers/staging/lustre/lustre/llite/llite_lib.c
+Auto-merging drivers/rtc/rtc-isl12057.c
+Auto-merging drivers/misc/ti-st/st_core.c
+Auto-merging drivers/leds/Kconfig
+Auto-merging arch/s390/mm/pgtable.c
+Auto-merging arch/arm/boot/dts/sun4i-a10.dtsi
+Auto-merging MAINTAINERS
+Auto-merging CREDITS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'mm/memcontrol.c'.
+[master c008d2e174c6] Merge branch 'akpm-current/current'
+$ git diff -M --stat --summary HEAD^..
+ CREDITS                                            |   4 +
+ Documentation/ABI/testing/sysfs-block-zram         |  39 +-
+ Documentation/SubmittingPatches                    |  46 +-
+ Documentation/blockdev/zram.txt                    |  53 +-
+ .../devicetree/bindings/rtc/sunxi-rtc.txt          |   4 +-
+ Documentation/filesystems/Locking                  |  10 +
+ Documentation/filesystems/nilfs2.txt               |  12 +-
+ Documentation/filesystems/ntfs.txt                 |   2 -
+ Documentation/filesystems/porting                  |   6 +-
+ Documentation/filesystems/vfat.txt                 |  10 +
+ Documentation/kbuild/kconfig-language.txt          |   4 +
+ Documentation/kmemleak.txt                         |   8 +-
+ Documentation/leds/leds-class.txt                  |   3 -
+ Documentation/printk-formats.txt                   |   6 +
+ Documentation/rapidio/sysfs.txt                    |  66 ++-
+ Documentation/sysctl/vm.txt                        |  33 +-
+ MAINTAINERS                                        | 115 +++--
+ arch/arm/boot/dts/sun4i-a10.dtsi                   |   2 +-
+ arch/arm/include/asm/fixmap.h                      |  29 +-
+ arch/arm/mm/init.c                                 |   2 +-
+ arch/ia64/kernel/uncached.c                        |   2 +-
+ arch/powerpc/include/asm/fadump.h                  |   1 -
+ arch/powerpc/mm/subpage-prot.c                     |   6 +-
+ arch/powerpc/platforms/cell/ras.c                  |   3 +-
+ arch/powerpc/sysdev/fsl_rio.c                      |   1 +
+ arch/s390/mm/pgtable.c                             |   3 +
+ arch/sh/boards/board-sh7757lcr.c                   |   2 +-
+ arch/sh/include/asm/syscalls_32.h                  |  12 +-
+ arch/sh/include/asm/traps_32.h                     |  16 +-
+ arch/sh/include/cpu-sh2/cpu/cache.h                |   2 +-
+ arch/sh/include/cpu-sh2a/cpu/cache.h               |   4 +-
+ arch/sh/include/cpu-sh3/cpu/cache.h                |   2 +-
+ arch/sh/include/cpu-sh4/cpu/cache.h                |   2 +-
+ arch/sh/kernel/cpu/init.c                          |   4 +-
+ arch/sh/kernel/entry-common.S                      |  15 +-
+ arch/sh/kernel/signal_32.c                         |  12 +-
+ arch/sh/kernel/sys_sh32.c                          |   7 +-
+ arch/sh/kernel/traps_32.c                          |  23 +-
+ arch/sh/math-emu/math.c                            |  18 -
+ arch/sh/mm/cache-debugfs.c                         |   2 +-
+ arch/sh/mm/cache-sh2.c                             |   4 +-
+ arch/sh/mm/cache-sh2a.c                            |   6 +-
+ arch/sh/mm/cache-sh4.c                             |   4 +-
+ arch/sh/mm/cache-shx3.c                            |   4 +-
+ arch/sh/mm/cache.c                                 |   4 +-
+ arch/x86/mm/kmemcheck/kmemcheck.c                  |   8 +-
+ block/genhd.c                                      |   2 +-
+ drivers/block/aoe/aoecmd.c                         |   4 +-
+ drivers/block/zram/Kconfig                         |  10 +
+ drivers/block/zram/Makefile                        |   4 +-
+ drivers/block/zram/zcomp.c                         | 349 +++++++++++++
+ drivers/block/zram/zcomp.h                         |  68 +++
+ drivers/block/zram/zcomp_lz4.c                     |  47 ++
+ drivers/block/zram/zcomp_lz4.h                     |  17 +
+ drivers/block/zram/zcomp_lzo.c                     |  47 ++
+ drivers/block/zram/zcomp_lzo.h                     |  17 +
+ drivers/block/zram/zram_drv.c                      | 306 ++++++-----
+ drivers/block/zram/zram_drv.h                      |  21 +-
+ drivers/input/Kconfig                              |   9 +
+ drivers/input/Makefile                             |   3 +
+ drivers/input/input.c                              |   6 +
+ drivers/input/leds.c                               | 249 +++++++++
+ drivers/leds/Kconfig                               |   3 -
+ drivers/lguest/page_tables.c                       |   6 +-
+ drivers/misc/sgi-gru/grukdump.c                    |   6 +-
+ drivers/misc/sgi-xp/xpc_uv.c                       |   2 +-
+ drivers/misc/ti-st/st_core.c                       |   2 +-
+ drivers/net/irda/donauboe.c                        |  15 +-
+ drivers/net/rionet.c                               |   1 +
+ drivers/pps/pps.c                                  |  57 ++-
+ drivers/rapidio/devices/tsi721.c                   |   1 +
+ drivers/rapidio/devices/tsi721.h                   |   5 +
+ drivers/rapidio/devices/tsi721_dma.c               | 138 +++--
+ drivers/rapidio/rio-driver.c                       |  22 +-
+ drivers/rapidio/rio-scan.c                         |   1 +
+ drivers/rapidio/rio-sysfs.c                        |  40 ++
+ drivers/rapidio/rio.c                              |  11 +
+ drivers/rapidio/rio.h                              |   1 +
+ drivers/rtc/interface.c                            |   3 +
+ drivers/rtc/rtc-as3722.c                           |   5 +-
+ drivers/rtc/rtc-at32ap700x.c                       |   4 +-
+ drivers/rtc/rtc-cmos.c                             |   8 +-
+ drivers/rtc/rtc-coh901331.c                        |  18 +-
+ drivers/rtc/rtc-da9052.c                           |   4 +-
+ drivers/rtc/rtc-davinci.c                          |  33 +-
+ drivers/rtc/rtc-ds1307.c                           | 185 ++++++-
+ drivers/rtc/rtc-ds1390.c                           |   5 +-
+ drivers/rtc/rtc-ds3232.c                           |  99 +++-
+ drivers/rtc/rtc-imxdi.c                            |   4 +-
+ drivers/rtc/rtc-isl12057.c                         |   1 -
+ drivers/rtc/rtc-jz4740.c                           |  25 +-
+ drivers/rtc/rtc-lpc32xx.c                          |   5 +-
+ drivers/rtc/rtc-mc13xxx.c                          | 139 ++---
+ drivers/rtc/rtc-moxart.c                           |   4 +-
+ drivers/rtc/rtc-nuc900.c                           |   5 +-
+ drivers/rtc/rtc-palmas.c                           |   5 +-
+ drivers/rtc/rtc-pm8xxx.c                           |   4 +-
+ drivers/rtc/rtc-rx8025.c                           |   1 -
+ drivers/rtc/rtc-s3c.c                              |  17 +-
+ drivers/rtc/rtc-sirfsoc.c                          |  68 +--
+ drivers/rtc/rtc-spear.c                            |   4 +-
+ drivers/rtc/rtc-sunxi.c                            |   2 +-
+ drivers/rtc/rtc-vt8500.c                           |  28 +-
+ drivers/scsi/megaraid/megaraid_mm.c                |   2 +
+ drivers/staging/lustre/lustre/llite/llite_lib.c    |   2 +-
+ drivers/tty/Kconfig                                |   4 +
+ drivers/tty/vt/keyboard.c                          | 110 +++-
+ drivers/vfio/vfio_iommu_type1.c                    |   4 +-
+ drivers/video/backlight/aat2870_bl.c               |   2 -
+ drivers/video/backlight/adp8860_bl.c               |   4 +-
+ drivers/video/backlight/adp8870_bl.c               |   4 +-
+ drivers/video/backlight/backlight.c                |  30 +-
+ drivers/video/backlight/corgi_lcd.c                |   4 +-
+ drivers/video/backlight/hx8357.c                   |   4 +-
+ drivers/video/backlight/ili922x.c                  |   4 +-
+ drivers/video/backlight/ili9320.c                  |   4 +-
+ drivers/video/backlight/l4f00242t03.c              |   5 +-
+ drivers/video/backlight/lm3533_bl.c                |   5 +-
+ drivers/video/backlight/lms283gf05.c               |   4 +-
+ drivers/video/backlight/platform_lcd.c             |   4 +-
+ drivers/video/backlight/tps65217_bl.c              |   5 +-
+ fs/9p/vfs_file.c                                   |   2 +
+ fs/9p/vfs_inode.c                                  |   2 +-
+ fs/adfs/super.c                                    |   2 +-
+ fs/affs/dir.c                                      |  28 +-
+ fs/affs/inode.c                                    |   2 +-
+ fs/affs/super.c                                    |   2 +-
+ fs/afs/inode.c                                     |   2 +-
+ fs/befs/linuxvfs.c                                 |   6 +-
+ fs/bfs/inode.c                                     |   2 +-
+ fs/binfmt_elf.c                                    |  34 +-
+ fs/block_dev.c                                     |   6 +-
+ fs/btrfs/compression.c                             |   2 +-
+ fs/btrfs/file.c                                    |   3 +-
+ fs/btrfs/inode.c                                   |   2 +-
+ fs/cachefiles/rdwr.c                               |  33 +-
+ fs/cifs/cifsfs.c                                   |   4 +-
+ fs/cifs/file.c                                     |   1 +
+ fs/coda/inode.c                                    |   2 +-
+ fs/cramfs/inode.c                                  |   3 +-
+ fs/direct-io.c                                     |   1 -
+ fs/drop_caches.c                                   |  16 +-
+ fs/ecryptfs/super.c                                |   2 +-
+ fs/efs/super.c                                     |   2 +-
+ fs/exec.c                                          |   2 +
+ fs/exofs/inode.c                                   |   2 +-
+ fs/ext2/inode.c                                    |   2 +-
+ fs/ext3/inode.c                                    |   2 +-
+ fs/ext4/file.c                                     |   3 +-
+ fs/ext4/inode.c                                    |   4 +-
+ fs/f2fs/file.c                                     |   1 +
+ fs/f2fs/inode.c                                    |   2 +-
+ fs/fat/cache.c                                     |  19 +-
+ fs/fat/fat.h                                       |   6 +-
+ fs/fat/file.c                                      |  78 ++-
+ fs/fat/inode.c                                     |  59 ++-
+ fs/filesystems.c                                   |   2 +
+ fs/freevxfs/vxfs_inode.c                           |   2 +-
+ fs/fs-writeback.c                                  |   5 +-
+ fs/fuse/file.c                                     |   1 +
+ fs/fuse/inode.c                                    |   2 +-
+ fs/gfs2/file.c                                     |   1 +
+ fs/gfs2/super.c                                    |   2 +-
+ fs/hfs/inode.c                                     |   2 +-
+ fs/hfsplus/catalog.c                               | 130 ++++-
+ fs/hfsplus/dir.c                                   |  11 +-
+ fs/hfsplus/extents.c                               |  16 +-
+ fs/hfsplus/hfsplus_fs.h                            |   5 +-
+ fs/hfsplus/hfsplus_raw.h                           |   6 +-
+ fs/hfsplus/inode.c                                 |   9 +
+ fs/hfsplus/options.c                               |   2 +-
+ fs/hfsplus/super.c                                 |   6 +-
+ fs/hostfs/hostfs_kern.c                            |   2 +-
+ fs/hpfs/inode.c                                    |   2 +-
+ fs/hugetlbfs/inode.c                               |  17 +-
+ fs/inode.c                                         |   4 +-
+ fs/jffs2/fs.c                                      |   4 +-
+ fs/jfs/inode.c                                     |   4 +-
+ fs/kernfs/inode.c                                  |   2 +-
+ fs/logfs/readwrite.c                               |   2 +-
+ fs/minix/inode.c                                   |   4 +-
+ fs/ncpfs/dir.c                                     |  69 ++-
+ fs/ncpfs/file.c                                    |  24 +-
+ fs/ncpfs/getopt.c                                  |  12 +-
+ fs/ncpfs/inode.c                                   |  34 +-
+ fs/ncpfs/ioctl.c                                   |  17 +-
+ fs/ncpfs/mmap.c                                    |   2 +-
+ fs/ncpfs/ncp_fs.h                                  |  30 +-
+ fs/ncpfs/ncplib_kernel.c                           |  28 +-
+ fs/ncpfs/sock.c                                    |  49 +-
+ fs/ncpfs/symlink.c                                 |   2 +-
+ fs/nfs/blocklayout/blocklayout.c                   |   2 +-
+ fs/nfs/file.c                                      |   1 +
+ fs/nfs/inode.c                                     |   2 +-
+ fs/nfs/nfs4super.c                                 |   2 +-
+ fs/nfsd/auth.c                                     |   5 +-
+ fs/nilfs2/cpfile.c                                 |  12 +
+ fs/nilfs2/dat.c                                    |  12 +
+ fs/nilfs2/file.c                                   |   1 +
+ fs/nilfs2/inode.c                                  |   6 +-
+ fs/nilfs2/ioctl.c                                  | 137 +++++
+ fs/nilfs2/sufile.c                                 | 295 +++++++++++
+ fs/nilfs2/sufile.h                                 |   2 +
+ fs/nilfs2/the_nilfs.c                              |  10 +
+ fs/ntfs/inode.c                                    |   2 +-
+ fs/ocfs2/alloc.c                                   |   1 +
+ fs/ocfs2/aops.c                                    |   7 +-
+ fs/ocfs2/aops.h                                    |   5 -
+ fs/ocfs2/cluster/tcp.c                             |  35 +-
+ fs/ocfs2/dcache.c                                  |  61 +--
+ fs/ocfs2/dcache.h                                  |  12 +-
+ fs/ocfs2/dir.c                                     |   4 +
+ fs/ocfs2/dlm/dlmdomain.c                           |   6 +-
+ fs/ocfs2/dlm/dlmrecovery.c                         |  29 +-
+ fs/ocfs2/dlmglue.c                                 |  44 +-
+ fs/ocfs2/dlmglue.h                                 |   3 +-
+ fs/ocfs2/file.c                                    |  62 +--
+ fs/ocfs2/inode.c                                   |  61 ++-
+ fs/ocfs2/inode.h                                   |  17 +-
+ fs/ocfs2/journal.c                                 |   6 -
+ fs/ocfs2/journal.h                                 |  11 +
+ fs/ocfs2/locks.c                                   |   2 +
+ fs/ocfs2/namei.c                                   | 113 +++-
+ fs/ocfs2/ocfs2.h                                   |  31 +-
+ fs/ocfs2/quota.h                                   |   2 +
+ fs/ocfs2/quota_global.c                            |  62 ++-
+ fs/ocfs2/quota_local.c                             |   4 -
+ fs/ocfs2/stackglue.c                               |  14 +
+ fs/ocfs2/super.c                                   |  51 +-
+ fs/omfs/inode.c                                    |   2 +-
+ fs/proc/array.c                                    |   4 +-
+ fs/proc/base.c                                     |   3 +
+ fs/proc/inode.c                                    |   2 +-
+ fs/proc/meminfo.c                                  |   2 +-
+ fs/proc/page.c                                     |   5 +-
+ fs/proc/task_mmu.c                                 | 271 ++++------
+ fs/proc/vmcore.c                                   |   1 -
+ fs/quota/dquot.c                                   |   4 +-
+ fs/reiserfs/inode.c                                |   2 +-
+ fs/reiserfs/reiserfs.h                             |   1 +
+ fs/reiserfs/super.c                                |   1 -
+ fs/sysv/inode.c                                    |   2 +-
+ fs/ubifs/file.c                                    |   1 +
+ fs/ubifs/super.c                                   |   2 +-
+ fs/udf/inode.c                                     |   4 +-
+ fs/udf/super.c                                     |   2 +-
+ fs/ufs/balloc.c                                    |  42 +-
+ fs/ufs/ialloc.c                                    |  21 +-
+ fs/ufs/inode.c                                     |   2 +-
+ fs/ufs/super.c                                     |  21 +-
+ fs/ufs/ufs.h                                       |   1 -
+ fs/xfs/xfs_file.c                                  |   1 +
+ fs/xfs/xfs_super.c                                 |   2 +-
+ include/asm-generic/bug.h                          |  62 +--
+ include/linux/backlight.h                          |   6 +
+ include/linux/cpuset.h                             |  27 +-
+ include/linux/crash_dump.h                         |   1 +
+ include/linux/crc64_ecma.h                         |  56 ++
+ include/linux/cred.h                               |   2 +-
+ include/linux/decompress/inflate.h                 |   4 +-
+ include/linux/err.h                                |   7 +-
+ include/linux/fs.h                                 |   1 +
+ include/linux/gfp.h                                |   4 +
+ include/linux/huge_mm.h                            |  41 --
+ include/linux/hugetlb.h                            |  17 +-
+ include/linux/hugetlb_inline.h                     |   7 +
+ include/linux/input.h                              |  21 +
+ include/linux/kobject.h                            |   1 +
+ include/linux/kthread.h                            |   1 +
+ include/linux/lglock.h                             |  16 +
+ include/linux/list_lru.h                           |   8 +-
+ include/linux/memcontrol.h                         |   9 +-
+ include/linux/mm.h                                 |  67 ++-
+ include/linux/mm_types.h                           |   3 +-
+ include/linux/mmzone.h                             |  10 +-
+ include/linux/nilfs2_fs.h                          |  52 ++
+ include/linux/pagemap.h                            |  71 ++-
+ include/linux/pagevec.h                            |   3 +
+ include/linux/printk.h                             |  10 +-
+ include/linux/quotaops.h                           |   8 +
+ include/linux/radix-tree.h                         |  55 +-
+ include/linux/rio.h                                |   5 +-
+ include/linux/sched.h                              |   5 +-
+ include/linux/shmem_fs.h                           |   1 +
+ include/linux/slab.h                               |   8 +-
+ include/linux/slub_def.h                           |   3 +
+ include/linux/string.h                             |   1 +
+ include/linux/swap.h                               |  36 ++
+ include/linux/syscalls.h                           |   2 +
+ include/linux/vm_event_item.h                      |   1 +
+ include/linux/vmstat.h                             |  17 +-
+ include/uapi/linux/prctl.h                         |   3 +
+ init/Kconfig                                       |  21 +
+ init/do_mounts.c                                   |   4 +-
+ init/initramfs.c                                   |   1 +
+ ipc/compat.c                                       |   3 -
+ ipc/ipc_sysctl.c                                   |   2 +-
+ ipc/mqueue.c                                       |   2 +-
+ ipc/util.c                                         |   2 +-
+ kernel/audit.c                                     |  10 +-
+ kernel/audit.h                                     |   2 +-
+ kernel/auditfilter.c                               |   3 +-
+ kernel/cpuset.c                                    |   2 +-
+ kernel/exit.c                                      | 102 ++--
+ kernel/fork.c                                      |  11 +-
+ kernel/groups.c                                    |  14 +-
+ kernel/hung_task.c                                 |   3 +-
+ kernel/kexec.c                                     |   4 +-
+ kernel/kmod.c                                      |  11 +-
+ kernel/kthread.c                                   |  13 +-
+ kernel/locking/Makefile                            |   3 +-
+ kernel/panic.c                                     |  13 +-
+ kernel/printk/printk.c                             |  13 +-
+ kernel/profile.c                                   |   6 +-
+ kernel/resource.c                                  |   2 +-
+ kernel/sched/stats.c                               |   2 +-
+ kernel/sys.c                                       |  15 +
+ kernel/sys_ni.c                                    |   2 +
+ kernel/sysctl.c                                    |   4 +-
+ kernel/time/sched_clock.c                          |   4 +
+ kernel/user.c                                      |   3 +-
+ kernel/user_namespace.c                            |   2 +-
+ kernel/watchdog.c                                  |  26 +-
+ lib/Kconfig                                        |   7 +
+ lib/Makefile                                       |   1 +
+ lib/clz_ctz.c                                      |   7 +
+ lib/crc64_ecma.c                                   | 341 ++++++++++++
+ lib/decompress.c                                   |   3 +
+ lib/decompress_inflate.c                           |   1 +
+ lib/devres.c                                       |  12 +-
+ lib/dma-debug.c                                    | 131 +++--
+ lib/kobject_uevent.c                               |  42 +-
+ lib/radix-tree.c                                   | 389 +++++++-------
+ lib/random32.c                                     |  76 +--
+ lib/vsprintf.c                                     |  65 +--
+ mm/Kconfig                                         |   1 +
+ mm/Makefile                                        |   2 +-
+ mm/backing-dev.c                                   |   2 +-
+ mm/compaction.c                                    |  87 ++--
+ mm/filemap.c                                       | 569 +++++++++++++++++----
+ mm/huge_memory.c                                   |  96 +---
+ mm/hugetlb.c                                       | 297 +++++++----
+ mm/ksm.c                                           |   2 +-
+ mm/list_lru.c                                      |  16 +-
+ mm/madvise.c                                       |  43 +-
+ mm/memcontrol.c                                    | 194 +++----
+ mm/memory-failure.c                                |   8 +-
+ mm/memory.c                                        | 521 +++++++++++--------
+ mm/mempolicy.c                                     | 267 ++++------
+ mm/migrate.c                                       |  11 +-
+ mm/mincore.c                                       |  20 +-
+ mm/mmap.c                                          |   5 +-
+ mm/mprotect.c                                      |  22 +-
+ mm/nobootmem.c                                     |   2 +-
+ mm/nommu.c                                         |   6 +
+ mm/page_alloc.c                                    |  43 +-
+ mm/page_cgroup.c                                   |  12 +-
+ mm/pagewalk.c                                      | 371 +++++++++-----
+ mm/process_vm_access.c                             |   2 +-
+ mm/readahead.c                                     |  10 +-
+ mm/rmap.c                                          |  10 +-
+ mm/shmem.c                                         | 122 ++---
+ mm/slab.c                                          |   8 +-
+ mm/slab.h                                          |  21 +-
+ mm/slab_common.c                                   | 250 +++++----
+ mm/slob.c                                          |  10 +-
+ mm/slub.c                                          |  82 ++-
+ mm/swap.c                                          |  54 +-
+ mm/truncate.c                                      | 147 +++++-
+ mm/util.c                                          |  30 ++
+ mm/vmscan.c                                        | 134 ++---
+ mm/vmstat.c                                        |   6 +
+ mm/workingset.c                                    | 414 +++++++++++++++
+ mm/zswap.c                                         |  72 +--
+ net/core/rtnetlink.c                               |   2 +-
+ scripts/checkpatch.pl                              | 158 ++++--
+ scripts/gen_initramfs_list.sh                      |   2 +-
+ scripts/kallsyms.c                                 |   3 +-
+ scripts/kconfig/confdata.c                         |   5 +-
+ scripts/kconfig/expr.h                             |   3 +
+ scripts/kconfig/lkc.h                              |   1 +
+ scripts/kconfig/menu.c                             |   3 +
+ scripts/kconfig/zconf.gperf                        |   1 +
+ scripts/kconfig/zconf.hash.c_shipped               |  13 +-
+ tools/vm/page-types.c                              | 170 +++++-
+ 385 files changed, 7996 insertions(+), 3714 deletions(-)
+ create mode 100644 drivers/block/zram/zcomp.c
+ create mode 100644 drivers/block/zram/zcomp.h
+ create mode 100644 drivers/block/zram/zcomp_lz4.c
+ create mode 100644 drivers/block/zram/zcomp_lz4.h
+ create mode 100644 drivers/block/zram/zcomp_lzo.c
+ create mode 100644 drivers/block/zram/zcomp_lzo.h
+ create mode 100644 drivers/input/leds.c
+ create mode 100644 include/linux/crc64_ecma.h
+ create mode 100644 lib/crc64_ecma.c
+ create mode 100644 mm/workingset.c
+$ git am -3 ../patches/ppc_Make_PPC_BOOK3S_64_select_IRQ_WORK.patch
+Applying: ppc: Make PPC_BOOK3S_64 select IRQ_WORK
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/powerpc/platforms/Kconfig.cputype
+$ git add -A .
+$ git commit -v -a --amend
+[master 0f56d56b67e4] Merge branch 'akpm-current/current'
+$ git am -3 ../patches/ia64__select_CONFIG_TTY_for_use_of_tty_write_message_in_unaligned.patch
+Applying: ia64: select CONFIG_TTY for use of tty_write_message in unaligned
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/ia64/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master 85af1a351c53] Merge branch 'akpm-current/current'
+$ git am -3 ../patches/s390__select_CONFIG_TTY_for_use_of_tty_in_unconditional_keyboard_driver.patch
+Applying: s390: select CONFIG_TTY for use of tty in unconditional keyboard driver
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/s390/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master ece6dcb66d4e] Merge branch 'akpm-current/current'
+$ git am -3 ../patches/cris__Make_ETRAX_ARCH_V10_select_TTY_for_use_in_debugport.patch
+Applying: cris: Make ETRAX_ARCH_V10 select TTY for use in debugport
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/cris/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master 2e82f81700c2] Merge branch 'akpm-current/current'
+$ git am -3 ../patches/cris__cpuinfo_op_should_depend_on_CONFIG_PROC_FS.patch
+Applying: cris: cpuinfo_op should depend on CONFIG_PROC_FS
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/cris/kernel/setup.c
+$ git add -A .
+$ git commit -v -a --amend
+[master 91166db3bba3] 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: Kconfig: rename HAS_IOPORT to HAS_IOPORT_MAP
+Applying: kernel: use macros from compiler.h instead of __attribute__((...))
+Applying: asm/system.h: clean asm/system.h from docs
+Applying: asm/system.h: um: arch_align_stack() moved to asm/exec.h
+Applying: drivers/w1/w1_int.c: call put_device if device_register fails
+Applying: arm: move arm_dma_limit to setup_dma_zone
+Applying: mm: add strictlimit knob
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + 73f248f5541f...ab47cc00257d akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (ab47cc00257d mm: add strictlimit knob)
+$ git merge --no-ff akpm/master
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-class-bdi |  8 +++++++
+ Documentation/DocBook/kernel-hacking.tmpl |  2 +-
+ Documentation/irqflags-tracing.txt        |  7 -------
+ Documentation/scheduler/sched-arch.txt    |  2 +-
+ arch/arc/Kconfig                          |  2 +-
+ arch/arm/Kconfig                          | 12 +++++------
+ arch/arm/mach-picoxcell/Kconfig           |  2 +-
+ arch/arm/mach-prima2/Kconfig              |  2 +-
+ arch/arm/mach-s3c24xx/Kconfig             |  2 +-
+ arch/arm/mach-shmobile/Kconfig            |  2 +-
+ arch/arm/mach-vexpress/Kconfig            |  2 +-
+ arch/arm/mm/init.c                        |  6 ++++--
+ arch/arm/mm/mm.h                          |  2 --
+ arch/arm/plat-samsung/Kconfig             |  4 ++--
+ arch/arm64/Kconfig                        |  2 +-
+ arch/cris/Kconfig                         |  2 +-
+ arch/hexagon/Kconfig                      |  2 +-
+ arch/m32r/Kconfig                         |  2 +-
+ arch/m68k/Kconfig                         |  2 +-
+ arch/metag/Kconfig                        |  2 +-
+ arch/mips/Kconfig                         |  4 ++--
+ arch/openrisc/Kconfig                     |  2 +-
+ arch/s390/Kconfig                         |  2 +-
+ arch/sh/Kconfig                           |  4 ++--
+ arch/sh/boards/Kconfig                    |  8 +++----
+ arch/sh/include/asm/io.h                  |  4 ++--
+ arch/sh/include/asm/io_trapped.h          |  2 +-
+ arch/sh/include/asm/machvec.h             |  2 +-
+ arch/sh/kernel/Makefile                   |  2 +-
+ arch/sh/kernel/io_trapped.c               |  4 ++--
+ arch/tile/Kconfig                         |  2 +-
+ arch/um/kernel/process.c                  |  2 +-
+ arch/unicore32/Kconfig                    |  2 +-
+ arch/xtensa/Kconfig                       |  4 ++--
+ arch/xtensa/configs/iss_defconfig         |  2 +-
+ arch/xtensa/configs/s6105_defconfig       |  2 +-
+ drivers/char/tpm/Kconfig                  |  2 +-
+ drivers/i2c/busses/Kconfig                |  2 +-
+ drivers/net/can/sja1000/Kconfig           |  2 +-
+ drivers/net/ethernet/3com/Kconfig         |  2 +-
+ drivers/w1/w1_int.c                       |  5 ++---
+ include/asm-generic/io.h                  |  4 ++--
+ include/asm-generic/iomap.h               |  2 +-
+ include/linux/io.h                        |  2 +-
+ kernel/fork.c                             |  3 ++-
+ kernel/kallsyms.c                         | 11 +++++-----
+ kernel/kexec.c                            |  5 +++--
+ kernel/ksysfs.c                           |  5 +++--
+ kernel/power/power.h                      |  3 ++-
+ kernel/power/snapshot.c                   |  3 ++-
+ kernel/power/suspend.c                    |  5 +++--
+ kernel/power/swap.c                       |  2 +-
+ kernel/sched/clock.c                      |  3 ++-
+ kernel/sched/core.c                       |  3 ++-
+ kernel/signal.c                           |  4 +++-
+ kernel/time/timekeeping.c                 |  5 +++--
+ kernel/trace/trace.h                      |  3 ++-
+ lib/Kconfig                               |  4 ++--
+ lib/devres.c                              |  4 ++--
+ lib/iomap.c                               |  4 ++--
+ mm/backing-dev.c                          | 35 +++++++++++++++++++++++++++++++
+ sound/isa/Kconfig                         |  2 +-
+ sound/pci/Kconfig                         |  2 +-
+ 63 files changed, 145 insertions(+), 97 deletions(-)
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 000000000000..bf20d2cab775
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,2 @@
+Importing jdelvare-hwmon based on 3.14-rc3
+Unchanged quilt series jdelvare-hwmon
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index a73a8e208a4a..7736f426ff3b 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -1,7 +1,8 @@
 
-generic-y += clkdev.h
 
+generic-y += clkdev.h
 generic-y += exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 9be30c8cb0c2..9596b0ab108d 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -57,7 +57,7 @@ config ARCH_FLATMEM_ENABLE
 config MMU
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config GENERIC_CALIBRATE_DELAY
@@ -356,7 +356,6 @@ config ARC_CURR_IN_REG
 
 config ARC_MISALIGN_ACCESS
 	bool "Emulate unaligned memory access (userspace only)"
-	default N
 	select SYSCTL_ARCH_UNALIGN_NO_WARN
 	select SYSCTL_ARCH_UNALIGN_ALLOW
 	help
diff --git a/arch/arc/boot/.gitignore b/arch/arc/boot/.gitignore
index 5d65b54bf17a..5246969a20c5 100644
--- a/arch/arc/boot/.gitignore
+++ b/arch/arc/boot/.gitignore
@@ -1 +1,2 @@
 *.dtb*
+uImage
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0d3362991c31..e76fd79f32b0 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -1,15 +1,15 @@
 generic-y += auxvec.h
 generic-y += barrier.h
-generic-y += bugs.h
 generic-y += bitsperlong.h
+generic-y += bugs.h
 generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += device.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
-generic-y += fcntl.h
 generic-y += fb.h
+generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += hardirq.h
 generic-y += hash.h
@@ -22,6 +22,7 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += param.h
@@ -30,6 +31,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -48,4 +50,3 @@ generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h
index 66ee5527aefc..5faad17118b4 100644
--- a/arch/arc/include/asm/linkage.h
+++ b/arch/arc/include/asm/linkage.h
@@ -13,20 +13,6 @@
 
 #define ASM_NL		 `	/* use '`' to mark new line in macro */
 
-/* Can't use the ENTRY macro in linux/linkage.h
- * gas considers ';' as comment vs. newline
- */
-.macro ARC_ENTRY name
-	.global \name
-	.align 4
-	\name:
-.endm
-
-.macro ARC_EXIT name
-#define ASM_PREV_SYM_ADDR(name)  .-##name
-	.size \ name, ASM_PREV_SYM_ADDR(\name)
-.endm
-
 /* annotation for data we want in DCCM - if enabled in .config */
 .macro ARCFP_DATA nm
 #ifdef CONFIG_ARC_HAS_DCCM
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S
index 65690e7fcc8c..2ff0347a2fd7 100644
--- a/arch/arc/kernel/ctx_sw_asm.S
+++ b/arch/arc/kernel/ctx_sw_asm.S
@@ -62,4 +62,4 @@ __switch_to:
 	ld.ab   blink, [sp, 4]
 	j       [blink]
 
-ARC_EXIT __switch_to
+END(__switch_to)
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 47d09d07f093..819dd5f7eb05 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -141,7 +141,7 @@ VECTOR   EV_Extension            ; 0x130, Extn Intruction Excp  (0x26)
 VECTOR   reserved                ; Reserved Exceptions
 .endr
 
-#include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
+#include <linux/linkage.h>   /* {EXTRY,EXIT} */
 #include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,SYS...} */
 #include <asm/errno.h>
 #include <asm/arcregs.h>
@@ -184,7 +184,7 @@ reserved:		; processor restart
 ; ---------------------------------------------
 ;  Level 2 ISR: Can interrupt a Level 1 ISR
 ; ---------------------------------------------
-ARC_ENTRY handle_interrupt_level2
+ENTRY(handle_interrupt_level2)
 
 	; TODO-vineetg for SMP this wont work
 	; free up r9 as scratchpad
@@ -225,14 +225,14 @@ ARC_ENTRY handle_interrupt_level2
 
 	b   ret_from_exception
 
-ARC_EXIT handle_interrupt_level2
+END(handle_interrupt_level2)
 
 #endif
 
 ; ---------------------------------------------
 ;  Level 1 ISR
 ; ---------------------------------------------
-ARC_ENTRY handle_interrupt_level1
+ENTRY(handle_interrupt_level1)
 
 	/* free up r9 as scratchpad */
 #ifdef CONFIG_SMP
@@ -265,7 +265,7 @@ ARC_ENTRY handle_interrupt_level1
 	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
 
 	b   ret_from_exception
-ARC_EXIT handle_interrupt_level1
+END(handle_interrupt_level1)
 
 ;################### Non TLB Exception Handling #############################
 
@@ -273,7 +273,7 @@ ARC_EXIT handle_interrupt_level1
 ; Instruction Error Exception Handler
 ; ---------------------------------------------
 
-ARC_ENTRY instr_service
+ENTRY(instr_service)
 
 	EXCEPTION_PROLOGUE
 
@@ -284,13 +284,13 @@ ARC_ENTRY instr_service
 
 	bl  do_insterror_or_kprobe
 	b   ret_from_exception
-ARC_EXIT instr_service
+END(instr_service)
 
 ; ---------------------------------------------
 ; Memory Error Exception Handler
 ; ---------------------------------------------
 
-ARC_ENTRY mem_service
+ENTRY(mem_service)
 
 	EXCEPTION_PROLOGUE
 
@@ -301,13 +301,13 @@ ARC_ENTRY mem_service
 
 	bl  do_memory_error
 	b   ret_from_exception
-ARC_EXIT mem_service
+END(mem_service)
 
 ; ---------------------------------------------
 ; Machine Check Exception Handler
 ; ---------------------------------------------
 
-ARC_ENTRY EV_MachineCheck
+ENTRY(EV_MachineCheck)
 
 	EXCEPTION_PROLOGUE
 
@@ -331,13 +331,13 @@ ARC_ENTRY EV_MachineCheck
 
 	j  do_machine_check_fault
 
-ARC_EXIT EV_MachineCheck
+END(EV_MachineCheck)
 
 ; ---------------------------------------------
 ; Protection Violation Exception Handler
 ; ---------------------------------------------
 
-ARC_ENTRY EV_TLBProtV
+ENTRY(EV_TLBProtV)
 
 	EXCEPTION_PROLOGUE
 
@@ -385,12 +385,12 @@ ARC_ENTRY EV_TLBProtV
 
 	b   ret_from_exception
 
-ARC_EXIT EV_TLBProtV
+END(EV_TLBProtV)
 
 ; ---------------------------------------------
 ; Privilege Violation Exception Handler
 ; ---------------------------------------------
-ARC_ENTRY EV_PrivilegeV
+ENTRY(EV_PrivilegeV)
 
 	EXCEPTION_PROLOGUE
 
@@ -401,12 +401,12 @@ ARC_ENTRY EV_PrivilegeV
 
 	bl  do_privilege_fault
 	b   ret_from_exception
-ARC_EXIT EV_PrivilegeV
+END(EV_PrivilegeV)
 
 ; ---------------------------------------------
 ; Extension Instruction Exception Handler
 ; ---------------------------------------------
-ARC_ENTRY EV_Extension
+ENTRY(EV_Extension)
 
 	EXCEPTION_PROLOGUE
 
@@ -417,7 +417,7 @@ ARC_ENTRY EV_Extension
 
 	bl  do_extension_fault
 	b   ret_from_exception
-ARC_EXIT EV_Extension
+END(EV_Extension)
 
 ;######################### System Call Tracing #########################
 
@@ -504,7 +504,7 @@ trap_with_param:
 ;   (2) Break Points
 ;------------------------------------------------------------------
 
-ARC_ENTRY EV_Trap
+ENTRY(EV_Trap)
 
 	EXCEPTION_PROLOGUE
 
@@ -534,9 +534,9 @@ ARC_ENTRY EV_Trap
 	jl      [r9]        ; Entry into Sys Call Handler
 
 	; fall through to ret_from_system_call
-ARC_EXIT EV_Trap
+END(EV_Trap)
 
-ARC_ENTRY ret_from_system_call
+ENTRY(ret_from_system_call)
 
 	st  r0, [sp, PT_r0]     ; sys call return value in pt_regs
 
@@ -546,7 +546,7 @@ ARC_ENTRY ret_from_system_call
 ;
 ; If ret to user mode do we need to handle signals, schedule() et al.
 
-ARC_ENTRY ret_from_exception
+ENTRY(ret_from_exception)
 
 	; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32
 	ld  r8, [sp, PT_status32]   ; returning to User/Kernel Mode
@@ -726,9 +726,9 @@ not_level1_interrupt:
 debug_marker_syscall:
 	rtie
 
-ARC_EXIT ret_from_exception
+END(ret_from_exception)
 
-ARC_ENTRY ret_from_fork
+ENTRY(ret_from_fork)
 	; when the forked child comes here from the __switch_to function
 	; r0 has the last task pointer.
 	; put last task in scheduler queue
@@ -745,11 +745,11 @@ ARC_ENTRY ret_from_fork
 	; special case of kernel_thread entry point returning back due to
 	; kernel_execve() - pretend return from syscall to ret to userland
 	b    ret_from_exception
-ARC_EXIT ret_from_fork
+END(ret_from_fork)
 
 ;################### Special Sys Call Wrappers ##########################
 
-ARC_ENTRY sys_clone_wrapper
+ENTRY(sys_clone_wrapper)
 	SAVE_CALLEE_SAVED_USER
 	bl  @sys_clone
 	DISCARD_CALLEE_SAVED_USER
@@ -759,7 +759,7 @@ ARC_ENTRY sys_clone_wrapper
 	bnz  tracesys_exit
 
 	b ret_from_system_call
-ARC_EXIT sys_clone_wrapper
+END(sys_clone_wrapper)
 
 #ifdef CONFIG_ARC_DW2_UNWIND
 ; Workaround for bug 94179 (STAR ):
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index e5f3a837fb35..71c42521c77f 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -155,22 +155,6 @@ static void arc_timer_event_setup(unsigned int limit)
 	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
 }
 
-/*
- * Acknowledge the interrupt (oneshot) and optionally re-arm it (periodic)
- * -Any write to CTRL Reg will ack the intr (NH bit: Count when not halted)
- * -Rearming is done by setting the IE bit
- *
- * Small optimisation: Normal code would have been
- *   if (irq_reenable)
- *     CTRL_REG = (IE | NH);
- *   else
- *     CTRL_REG = NH;
- * However since IE is BIT0 we can fold the branch
- */
-static void arc_timer_event_ack(unsigned int irq_reenable)
-{
-	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
-}
 
 static int arc_clkevent_set_next_event(unsigned long delta,
 				       struct clock_event_device *dev)
@@ -207,10 +191,22 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
 
 static irqreturn_t timer_irq_handler(int irq, void *dev_id)
 {
-	struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device);
+	/*
+	 * Note that generic IRQ core could have passed @evt for @dev_id if
+	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
+	 */
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+	int irq_reenable = evt->mode == CLOCK_EVT_MODE_PERIODIC;
+
+	/*
+	 * Any write to CTRL reg ACks the interrupt, we rewrite the
+	 * Count when [N]ot [H]alted bit.
+	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
+	 */
+	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
+
+	evt->event_handler(evt);
 
-	arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC);
-	clk->event_handler(clk);
 	return IRQ_HANDLED;
 }
 
@@ -222,9 +218,8 @@ static struct irqaction arc_timer_irq = {
 
 /*
  * Setup the local event timer for @cpu
- * N.B. weak so that some exotic ARC SoCs can completely override it
  */
-void __weak arc_local_timer_setup(unsigned int cpu)
+void arc_local_timer_setup(unsigned int cpu)
 {
 	struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu);
 
diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S
index bc813d55b6c3..978bf8314dfb 100644
--- a/arch/arc/lib/memcmp.S
+++ b/arch/arc/lib/memcmp.S
@@ -6,7 +6,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
 #ifdef __LITTLE_ENDIAN__
 #define WORD2 r2
@@ -16,7 +16,7 @@
 #define SHIFT r2
 #endif
 
-ARC_ENTRY memcmp
+ENTRY(memcmp)
 	or	r12,r0,r1
 	asl_s	r12,r12,30
 	sub	r3,r2,1
@@ -121,4 +121,4 @@ ARC_ENTRY memcmp
 .Lnil:
 	j_s.d	[blink]
 	mov	r0,0
-ARC_EXIT memcmp
+END(memcmp)
diff --git a/arch/arc/lib/memcpy-700.S b/arch/arc/lib/memcpy-700.S
index b64cc10ac918..3222573e50de 100644
--- a/arch/arc/lib/memcpy-700.S
+++ b/arch/arc/lib/memcpy-700.S
@@ -6,9 +6,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
-ARC_ENTRY memcpy
+ENTRY(memcpy)
 	or	r3,r0,r1
 	asl_s	r3,r3,30
 	mov_s	r5,r0
@@ -63,4 +63,4 @@ ARC_ENTRY memcpy
 .Lendbloop:
 	j_s.d	[blink]
 	stb	r12,[r5,0]
-ARC_EXIT memcpy
+END(memcpy)
diff --git a/arch/arc/lib/memset.S b/arch/arc/lib/memset.S
index 9b2d88d2e141..d36bd43fc98d 100644
--- a/arch/arc/lib/memset.S
+++ b/arch/arc/lib/memset.S
@@ -6,11 +6,11 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
 #define SMALL	7 /* Must be at least 6 to deal with alignment/loop issues.  */
 
-ARC_ENTRY memset
+ENTRY(memset)
 	mov_s	r4,r0
 	or	r12,r0,r2
 	bmsk.f	r12,r12,1
@@ -46,14 +46,14 @@ ARC_ENTRY memset
 	stb.ab	r1,[r4,1]
 .Ltiny_end:
 	j_s	[blink]
-ARC_EXIT memset
+END(memset)
 
 ; memzero: @r0 = mem, @r1 = size_t
 ; memset:  @r0 = mem, @r1 = char, @r2 = size_t
 
-ARC_ENTRY memzero
+ENTRY(memzero)
     ; adjust bzero args to memset args
     mov r2, r1
     mov r1, 0
     b  memset    ;tail call so need to tinker with blink
-ARC_EXIT memzero
+END(memzero)
diff --git a/arch/arc/lib/strchr-700.S b/arch/arc/lib/strchr-700.S
index 9c548c7cf001..b725d5862107 100644
--- a/arch/arc/lib/strchr-700.S
+++ b/arch/arc/lib/strchr-700.S
@@ -11,9 +11,9 @@
    presence of the norm instruction makes it easier to operate on whole
    words branch-free.  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
-ARC_ENTRY strchr
+ENTRY(strchr)
 	extb_s	r1,r1
 	asl	r5,r1,8
 	bmsk	r2,r0,1
@@ -130,4 +130,4 @@ ARC_ENTRY strchr
 	j_s.d	[blink]
 	mov.mi	r0,0
 #endif /* ENDIAN */
-ARC_EXIT strchr
+END(strchr)
diff --git a/arch/arc/lib/strcmp.S b/arch/arc/lib/strcmp.S
index 5dc802b45cf3..3544600fefe6 100644
--- a/arch/arc/lib/strcmp.S
+++ b/arch/arc/lib/strcmp.S
@@ -13,9 +13,9 @@
    source 1; however, that would increase the overhead for loop setup / finish,
    and strcmp might often terminate early.  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
-ARC_ENTRY strcmp
+ENTRY(strcmp)
 	or	r2,r0,r1
 	bmsk_s	r2,r2,1
 	brne	r2,0,.Lcharloop
@@ -93,4 +93,4 @@ ARC_ENTRY strcmp
 .Lcmpend:
 	j_s.d	[blink]
 	sub	r0,r2,r3
-ARC_EXIT strcmp
+END(strcmp)
diff --git a/arch/arc/lib/strcpy-700.S b/arch/arc/lib/strcpy-700.S
index b7ca4ae81d88..8422f38e1218 100644
--- a/arch/arc/lib/strcpy-700.S
+++ b/arch/arc/lib/strcpy-700.S
@@ -16,9 +16,9 @@
    there, but the it is not likely to be taken often, and it
    would also be likey to cost an unaligned mispredict at the next call.  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
-ARC_ENTRY strcpy
+ENTRY(strcpy)
 	or	r2,r0,r1
 	bmsk_s	r2,r2,1
 	brne.d	r2,0,charloop
@@ -67,4 +67,4 @@ charloop:
 	brne.d	r3,0,charloop
 	stb.ab	r3,[r10,1]
 	j	[blink]
-ARC_EXIT strcpy
+END(strcpy)
diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S
index 39759e099696..53cfd5685a5f 100644
--- a/arch/arc/lib/strlen.S
+++ b/arch/arc/lib/strlen.S
@@ -6,9 +6,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/linkage.h>
+#include <linux/linkage.h>
 
-ARC_ENTRY strlen
+ENTRY(strlen)
 	or	r3,r0,7
 	ld	r2,[r3,-7]
 	ld.a	r6,[r3,-3]
@@ -80,4 +80,4 @@ ARC_ENTRY strlen
 .Learly_end:
 	b.d	.Lend
 	sub_s.ne r1,r1,r1
-ARC_EXIT strlen
+END(strlen)
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 55e0a85bea78..523412369f70 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -10,6 +10,9 @@
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/initrd.h>
+#endif
 #include <linux/swap.h>
 #include <linux/module.h>
 #include <asm/page.h>
@@ -42,6 +45,24 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 	pr_info("Memory size set via devicetree %ldM\n", TO_MB(arc_mem_sz));
 }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static int __init early_initrd(char *p)
+{
+	unsigned long start, size;
+	char *endp;
+
+	start = memparse(p, &endp);
+	if (*endp == ',') {
+		size = memparse(endp + 1, NULL);
+
+		initrd_start = (unsigned long)__va(start);
+		initrd_end = (unsigned long)__va(start + size);
+	}
+	return 0;
+}
+early_param("initrd", early_initrd);
+#endif
+
 /*
  * First memory setup routine called from setup_arch()
  * 1. setup swapper's mm @init_mm
@@ -80,6 +101,12 @@ void __init setup_arch_memory(void)
 	memblock_reserve(CONFIG_LINUX_LINK_BASE,
 			 __pa(_end) - CONFIG_LINUX_LINK_BASE);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+	/*------------- reserve initrd image -----------------------*/
+	if (initrd_start)
+		memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+#endif
+
 	memblock_dump_all();
 
 	/*-------------- node setup --------------------------------*/
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index 3fcfdb38d242..79bfc81358c9 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -260,7 +260,7 @@ ARCFP_CODE	;Fast Path Code, candidate for ICCM
 ; I-TLB Miss Exception Handler
 ;-----------------------------------------------------------------------------
 
-ARC_ENTRY EV_TLBMissI
+ENTRY(EV_TLBMissI)
 
 	TLBMISS_FREEUP_REGS
 
@@ -293,13 +293,13 @@ ARC_ENTRY EV_TLBMissI
 	TLBMISS_RESTORE_REGS
 	rtie
 
-ARC_EXIT EV_TLBMissI
+END(EV_TLBMissI)
 
 ;-----------------------------------------------------------------------------
 ; D-TLB Miss Exception Handler
 ;-----------------------------------------------------------------------------
 
-ARC_ENTRY EV_TLBMissD
+ENTRY(EV_TLBMissD)
 
 	TLBMISS_FREEUP_REGS
 
@@ -381,6 +381,4 @@ do_slow_path_pf:
 	bl  do_page_fault
 	b   ret_from_exception
 
-ARC_EXIT EV_TLBMissD
-
-ARC_ENTRY EV_TLBMissB   ; Bogus entry to measure sz of DTLBMiss hdlr
+END(EV_TLBMissD)
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index 295cefeb25d3..33058aa40e77 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -33,7 +33,6 @@ config ISS_SMP_EXTN
 	bool "ARC SMP Extensions (ISS Models only)"
 	default n
 	depends on SMP
-	select ARC_HAS_COH_RTSC
 	help
 	  SMP Extensions to ARC700, in a "simulation only" Model, supported in
 	  ARC ISS (Instruction Set Simulator).
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index d71f3c3bcf24..19b76b61f44b 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -201,7 +201,7 @@ static void __init plat_fpga_populate_dev(void)
  * callback set, by matching the DT compatible name.
  */
 
-static const char *aa4_compat[] __initdata = {
+static const char *aa4_compat[] __initconst = {
 	"snps,arc-angel4",
 	NULL,
 };
@@ -216,7 +216,7 @@ MACHINE_START(ANGEL4, "angel4")
 #endif
 MACHINE_END
 
-static const char *ml509_compat[] __initdata = {
+static const char *ml509_compat[] __initconst = {
 	"snps,arc-ml509",
 	NULL,
 };
@@ -231,7 +231,7 @@ MACHINE_START(ML509, "ml509")
 #endif
 MACHINE_END
 
-static const char *nsimosci_compat[] __initdata = {
+static const char *nsimosci_compat[] __initconst = {
 	"snps,nsimosci",
 	NULL,
 };
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e25419817791..78259d375b85 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -113,9 +113,6 @@ config ARM_DMA_IOMMU_ALIGNMENT
 
 endif
 
-config HAVE_PWM
-	bool
-
 config MIGHT_HAVE_PCI
 	bool
 
@@ -129,7 +126,7 @@ config HAVE_TCM
 config HAVE_PROC_CPU
 	bool
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	bool
 
 config EISA
@@ -306,9 +303,12 @@ choice
 config ARCH_MULTIPLATFORM
 	bool "Allow multiple platforms to be selected"
 	depends on MMU
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_PATCH_PHYS_VIRT
 	select AUTO_ZRELADDR
+	select CLKSRC_OF
 	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
 	select MULTI_IRQ_HANDLER
 	select SPARSE_IRQ
 	select USE_OF
@@ -388,8 +388,6 @@ config ARCH_CLPS711X
 	select CPU_ARM720T
 	select GENERIC_CLOCKEVENTS
 	select MFD_SYSCON
-	select MULTI_IRQ_HANDLER
-	select SPARSE_IRQ
 	help
 	  Support for Cirrus Logic 711x/721x/731x based boards.
 
@@ -409,7 +407,7 @@ config ARCH_EBSA110
 	select ISA
 	select NEED_MACH_IO_H
 	select NEED_MACH_MEMORY_H
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	help
 	  This is an evaluation board for the StrongARM processor available
 	  from Digital. It has limited hardware on-board, including an
@@ -421,15 +419,12 @@ config ARCH_EFM32
 	depends on !MMU
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_NVIC
-	# CLKSRC_MMIO is wrong here, but needed until a proper fix is merged,
-	# i.e. CLKSRC_EFM32 selecting CLKSRC_MMIO
-	select CLKSRC_MMIO
 	select CLKSRC_OF
 	select COMMON_CLK
 	select CPU_V7M
 	select GENERIC_CLOCKEVENTS
 	select NO_DMA
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select SPARSE_IRQ
 	select USE_OF
 	help
@@ -534,7 +529,6 @@ config ARCH_DOVE
 	select PINCTRL
 	select PINCTRL_DOVE
 	select PLAT_ORION_LEGACY
-	select USB_ARCH_HAS_EHCI
 	help
 	  Support for the Marvell Dove SoC 88AP510
 
@@ -632,8 +626,6 @@ config ARCH_LPC32XX
 	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
 	select HAVE_IDE
-	select HAVE_PWM
-	select USB_ARCH_HAS_OHCI
 	select USE_OF
 	help
 	  Support for the NXP LPC32XX family of processors
@@ -657,9 +649,8 @@ config ARCH_PXA
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
-config ARCH_MSM_NODT
-	bool "Qualcomm MSM"
-	select ARCH_MSM
+config ARCH_MSM
+	bool "Qualcomm MSM (non-multiplatform)"
 	select ARCH_REQUIRE_GPIOLIB
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
@@ -682,7 +673,7 @@ config ARCH_SHMOBILE_LEGACY
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select MULTI_IRQ_HANDLER
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select PINCTRL
 	select PM_GENERIC_DOMAINS if PM
 	select SPARSE_IRQ
@@ -703,7 +694,7 @@ config ARCH_RPC
 	select ISA_DMA_API
 	select NEED_MACH_IO_H
 	select NEED_MACH_MEMORY_H
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select VIRT_TO_BUS
 	help
 	  On the Acorn Risc-PC, Linux can support the internal IDE disk and
@@ -762,7 +753,7 @@ config ARCH_S3C64XX
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_TCM
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select PLAT_SAMSUNG
 	select PM_GENERIC_DOMAINS
 	select S3C_DEV_NAND
@@ -770,7 +761,6 @@ config ARCH_S3C64XX
 	select SAMSUNG_ATAGS
 	select SAMSUNG_WAKEMASK
 	select SAMSUNG_WDT_RESET
-	select USB_ARCH_HAS_OHCI
 	help
 	  Samsung S3C64XX series based systems
 
@@ -898,7 +888,7 @@ config ARCH_MULTI_V5
 	bool "ARMv5 based platforms (ARM926T, XSCALE, PJ1, ...)"
 	depends on !ARCH_MULTI_V6_V7
 	select ARCH_MULTI_V4_V5
-	select CPU_ARM926T if (!CPU_ARM946E || CPU_ARM1020 || \
+	select CPU_ARM926T if !(CPU_ARM946E || CPU_ARM1020 || \
 		CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \
 		CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_FEROCEON)
 
@@ -908,16 +898,18 @@ config ARCH_MULTI_V4_V5
 config ARCH_MULTI_V6
 	bool "ARMv6 based platforms (ARM11)"
 	select ARCH_MULTI_V6_V7
-	select CPU_V6
+	select CPU_V6K
 
 config ARCH_MULTI_V7
 	bool "ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)"
 	default y
 	select ARCH_MULTI_V6_V7
 	select CPU_V7
+	select HAVE_SMP
 
 config ARCH_MULTI_V6_V7
 	bool
+	select MIGHT_HAVE_CACHE_L2X0
 
 config ARCH_MULTI_CPU_AUTO
 	def_bool !(ARCH_MULTI_V4 || ARCH_MULTI_V4T || ARCH_MULTI_V6_V7)
@@ -925,6 +917,13 @@ config ARCH_MULTI_CPU_AUTO
 
 endmenu
 
+config ARCH_VIRT
+	bool "Dummy Virtual Machine" if ARCH_MULTI_V7
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_PSCI
+	select HAVE_ARM_ARCH_TIMER
+
 #
 # This is sorted alphabetically by mach-* pathname.  However, plat-*
 # Kconfigs may be included either alphabetically (according to the
@@ -936,8 +935,6 @@ source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcm/Kconfig"
 
-source "arch/arm/mach-bcm2835/Kconfig"
-
 source "arch/arm/mach-berlin/Kconfig"
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -1005,6 +1002,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-qcom/Kconfig"
+
 source "arch/arm/mach-realview/Kconfig"
 
 source "arch/arm/mach-rockchip/Kconfig"
@@ -1048,8 +1047,6 @@ source "arch/arm/mach-versatile/Kconfig"
 source "arch/arm/mach-vexpress/Kconfig"
 source "arch/arm/plat-versatile/Kconfig"
 
-source "arch/arm/mach-virt/Kconfig"
-
 source "arch/arm/mach-vt8500/Kconfig"
 
 source "arch/arm/mach-w90x900/Kconfig"
@@ -1903,6 +1900,7 @@ config XEN
 	depends on ARM && AEABI && OF
 	depends on CPU_V7 && !CPU_V6
 	depends on !GENERIC_ATOMIC64
+	depends on MMU
 	select ARM_PSCI
 	select SWIOTLB_XEN
 	select ARCH_DMA_ADDR_T_64BIT
@@ -2270,7 +2268,7 @@ source "kernel/power/Kconfig"
 config ARCH_SUSPEND_POSSIBLE
 	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_FEROCEON || CPU_SA1100 || \
-		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
+		CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
 	def_bool y
 
 config ARM_CPU_SUSPEND
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 0531da8e5216..84ca340e0105 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -956,7 +956,7 @@ config DEBUG_STI_UART
 
 config DEBUG_MSM_UART
 	bool
-	depends on ARCH_MSM
+	depends on ARCH_MSM || ARCH_QCOM
 
 config DEBUG_LL_INCLUDE
 	string
@@ -1145,7 +1145,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 
 config DEBUG_UNCOMPRESS
 	bool
-	depends on ARCH_MULTIPLATFORM || ARCH_MSM
+	depends on ARCH_MULTIPLATFORM || ARCH_MSM || ARCH_EXYNOS
 	default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
 		     (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
 	help
@@ -1161,7 +1161,8 @@ config DEBUG_UNCOMPRESS
 
 config UNCOMPRESS_INCLUDE
 	string
-	default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM
+	default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
+					ARCH_EXYNOS
 	default "mach/uncompress.h"
 
 config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 08a9ef58d9c3..41c1931f0155 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -143,7 +143,6 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 # by CONFIG_* macro name.
 machine-$(CONFIG_ARCH_AT91)		+= at91
 machine-$(CONFIG_ARCH_BCM)		+= bcm
-machine-$(CONFIG_ARCH_BCM2835)		+= bcm2835
 machine-$(CONFIG_ARCH_BERLIN)		+= berlin
 machine-$(CONFIG_ARCH_CLPS711X)		+= clps711x
 machine-$(CONFIG_ARCH_CNS3XXX)		+= cns3xxx
@@ -180,6 +179,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
 machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PXA)		+= pxa
+machine-$(CONFIG_ARCH_QCOM)		+= qcom
 machine-$(CONFIG_ARCH_REALVIEW)		+= realview
 machine-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip
 machine-$(CONFIG_ARCH_RPC)		+= rpc
@@ -199,7 +199,6 @@ machine-$(CONFIG_ARCH_U300)		+= u300
 machine-$(CONFIG_ARCH_U8500)		+= ux500
 machine-$(CONFIG_ARCH_VERSATILE)	+= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		+= vexpress
-machine-$(CONFIG_ARCH_VIRT)		+= virt
 machine-$(CONFIG_ARCH_VT8500)		+= vt8500
 machine-$(CONFIG_ARCH_W90X900)		+= w90x900
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
@@ -310,9 +309,9 @@ $(INSTALL_TARGETS):
 %.dtb: | scripts
 	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
 
-PHONY += dtbs
-dtbs: scripts
-	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
+PHONY += dtbs dtbs_install
+dtbs dtbs_install: prepare scripts
+	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
@@ -331,6 +330,7 @@ define archhelp
   echo  '  bootpImage    - Combined zImage and initial RAM disk'
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
   echo  '* dtbs          - Build device tree blobs for enabled boards'
+  echo  '  dtbs_install  - Install dtbs to $(INSTALL_DTBS_PATH)'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 000000000000..a9e06c2e0e04
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,104 @@
+dependencies
+	depends/irqchip-mvebu-fixes
+		git://git.infradead.org/linux-mvebu.git tags/mvebu-watchdog-3.15
+
+next/fixes-non-critical
+	patch
+		irqchip: gic: use dmb ishst instead of dsb when raising a softirq
+		MAINTAINERS: ARM: clps711x: Use regex patterns to involve all CLPS711X drivers
+		ARM: clps711x: autcpu12: Fix incorrect NAND CLE GPIO
+
+next/cleanup
+	cleanup/timex-removal
+		git://git.pengutronix.de/git/ukl/linux tags/dropmachtimexh-v2
+	renesas/cleanup
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-cleanup-for-v3.15
+	qcom/cleanup
+		git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom tags/qcom-cleanup-for-3.15
+	mvebu/soc
+		git://git.infradead.org/linux-mvebu tags/mvebu-soc-3.15
+	efm32/cleanup
+		git://git.pengutronix.de/git/ukl/linux.git tags/efm32-next
+	patch
+		ARM: clps711x: Update defconfig
+		ARM: clps711x: Remove EP72XX_ROM_BOOT option
+
+next/soc
+	qcom/soc
+		git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom tags/qcom-soc-for-3.15
+		contains qcom/cleanup
+	patch
+		ARM: dts: msm: Add krait-pmu to platforms with Krait CPUs
+	mvebu/soc-3xx
+		git://git.infradead.org/linux-mvebu.git tags/mvebu-soc-3xx-3.15
+		contains mvebu/soc
+	patch
+		ARM: clps711x: Migrate CLPS711X subarch to the new irqchip driver
+		ARM: dts: clps711x: Add bindings documentation for CLPS711X irqchip driver
+		ARM: clps711x: Add CLPS711X irqchip driver
+	
+next/boards
+	renesas/boards
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-boards-for-v3.15
+	renesas/defconfig
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-defconfig-for-v3.15
+	renesas/boards2
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-boards2-for-v3.15
+	renesas/defconfig2
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-defconfig2-for-v3.15
+	mvebu/defconfig
+		git://git.infradead.org/linux-mvebu tags/mvebu-defconfig-3.15
+	patch
+		ARM: qcom: Enable basic support for Qualcomm platforms in multi_v7_defconfig
+
+next/dt
+	renesas/dt
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-dt-for-v3.15
+	imx/dt-imx6
+		git://git.linaro.org/people/shawnguo/linux-2.6 tags/imx6-dt-3.15
+	imx/dt
+		git://git.linaro.org/people/shawnguo/linux-2.6 tags/imx-dt-3.15
+	ux500/dt
+		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson tags/ab8500-dt-for-arm-soc
+	renesas/dt2
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-dt2-for-v3.15
+	mvebu/dt
+		git://git.infradead.org/linux-mvebu tags/mvebu-dt-3.15
+	mvebu/dt2
+		git://git.infradead.org/linux-mvebu.git tags/mvebu-dt-3.15-2
+	qcom/dt
+		git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git tags/qcom-dt-for-3.15
+		contains qcom/cleanup
+
+next/drivers
+	renesas/soc
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas tags/renesas-soc-for-v3.15
+	integrator/multiplatform-base
+		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator tags/integrator-for-v3.15-1
+	davinci/nand
+		git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-for-v3.15/nand
+	mvebu/watchdog
+		git://git.infradead.org/linux-mvebu.git tags/mvebu-watchdog-3.15
+	patch
+		irqchip: VIC: export vic_init_cascaded
+	qcom/drivers
+		git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git tags/qcom-drivers-for-3.15
+		contains qcom/cleanup
+	patch
+		drivers: cci: Export CCI PMU revision
+		drivers: cci: Extend support to CCI revisions > r1p2
+
+fixes
+	<no branch>
+		https://git.kernel.org/pub/scm/linux/kernel/git/hzhuang1/linux tags/pwm_pxa_for_v3.14
+	patch
+		ARM: tegra: fix RTC0 alias for Cardhu
+	<no branch>
+		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/fixes-against-rc1
+	patch
+		ARM: imx6: build pm-imx6q.c independently of CONFIG_PM
+	<no branch>
+		git://git.infradead.org/linux-mvebu tags/mvebu-dt-fixes-3.14
+	patch
+		ARM: tegra: Add head numbers to display controllers
+		ARM: tegra: only run PL310 init on systems with one
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 032030361bef..f7d678808122 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -82,14 +82,27 @@ dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
 	integratorcp.dtb
-dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
-dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
+kirkwood := \
+	kirkwood-b3.dtb \
+	kirkwood-cloudbox.dtb \
 	kirkwood-db-88f6281.dtb \
 	kirkwood-db-88f6282.dtb \
 	kirkwood-dns320.dtb \
 	kirkwood-dns325.dtb \
 	kirkwood-dockstar.dtb \
 	kirkwood-dreamplug.dtb \
+	kirkwood-ds109.dtb \
+	kirkwood-ds110jv10.dtb \
+	kirkwood-ds111.dtb \
+	kirkwood-ds209.dtb \
+	kirkwood-ds210.dtb \
+	kirkwood-ds212.dtb \
+	kirkwood-ds212j.dtb \
+	kirkwood-ds409.dtb \
+	kirkwood-ds409slim.dtb \
+	kirkwood-ds411.dtb \
+	kirkwood-ds411j.dtb \
+	kirkwood-ds411slim.dtb \
 	kirkwood-goflexnet.dtb \
 	kirkwood-guruplug-server-plus.dtb \
 	kirkwood-ib62x0.dtb \
@@ -112,21 +125,36 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
 	kirkwood-nsa310a.dtb \
 	kirkwood-openblocks_a6.dtb \
 	kirkwood-openblocks_a7.dtb \
+	kirkwood-rd88f6192.dtb \
+	kirkwood-rd88f6281-a0.dtb \
+	kirkwood-rd88f6281-a1.dtb \
+	kirkwood-rs212.dtb \
+	kirkwood-rs409.dtb \
+	kirkwood-rs411.dtb \
 	kirkwood-sheevaplug.dtb \
 	kirkwood-sheevaplug-esata.dtb \
+	kirkwood-t5325.dtb \
 	kirkwood-topkick.dtb \
 	kirkwood-ts219-6281.dtb \
-	kirkwood-ts219-6282.dtb
+	kirkwood-ts219-6282.dtb \
+	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_MVEBU) += armada-370-db.dtb \
+dtb-$(CONFIG_MACH_ARMADA_370) += \
+	armada-370-db.dtb \
 	armada-370-mirabox.dtb \
 	armada-370-netgear-rn102.dtb \
 	armada-370-netgear-rn104.dtb \
-	armada-370-rd.dtb \
+	armada-370-rd.dtb
+dtb-$(CONFIG_MACH_ARMADA_375) += \
+	armada-375-db.dtb
+dtb-$(CONFIG_MACH_ARMADA_38X) += \
+	armada-385-db.dtb
+dtb-$(CONFIG_MACH_ARMADA_XP) += \
 	armada-xp-axpwifiap.dtb \
 	armada-xp-db.dtb \
 	armada-xp-gp.dtb \
@@ -134,32 +162,54 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
 	armada-xp-matrix.dtb \
 	armada-xp-openblocks-ax3-4.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
+	imx25-eukrea-mbimxsd25-baseboard.dtb \
 	imx25-karo-tx25.dtb \
 	imx25-pdk.dtb \
 	imx27-apf27.dtb \
 	imx27-apf27dev.dtb \
 	imx27-pdk.dtb \
-	imx27-phytec-phycore-som.dtb \
 	imx27-phytec-phycore-rdk.dtb \
-	imx27-phytec-phycard-s-som.dtb \
 	imx27-phytec-phycard-s-rdk.dtb \
 	imx31-bug.dtb \
+	imx35-eukrea-mbimxsd35-baseboard.dtb \
+	imx50-evk.dtb \
 	imx51-apf51.dtb \
 	imx51-apf51dev.dtb \
 	imx51-babbage.dtb \
+	imx51-eukrea-mbimxsd51-baseboard.dtb \
 	imx53-ard.dtb \
-	imx53-evk.dtb \
 	imx53-m53evk.dtb \
 	imx53-mba53.dtb \
 	imx53-qsb.dtb \
+	imx53-qsrb.dtb \
 	imx53-smd.dtb \
+	imx53-tx53-x03x.dtb \
+	imx53-tx53-x13x.dtb \
+	imx53-voipac-bsb.dtb \
 	imx6dl-cubox-i.dtb \
+	imx6dl-dfi-fs700-m60.dtb \
+	imx6dl-gw51xx.dtb \
+	imx6dl-gw52xx.dtb \
+	imx6dl-gw53xx.dtb \
+	imx6dl-gw54xx.dtb \
 	imx6dl-hummingboard.dtb \
+	imx6dl-nitrogen6x.dtb \
 	imx6dl-sabreauto.dtb \
+	imx6dl-sabrelite.dtb \
 	imx6dl-sabresd.dtb \
 	imx6dl-wandboard.dtb \
 	imx6q-arm2.dtb \
+	imx6q-cm-fx6.dtb \
 	imx6q-cubox-i.dtb \
+	imx6q-dfi-fs700-m60.dtb \
+	imx6q-dmo-edmqmx6.dtb \
+	imx6q-gk802.dtb \
+	imx6q-gw51xx.dtb \
+	imx6q-gw52xx.dtb \
+	imx6q-gw53xx.dtb \
+	imx6q-gw5400-a.dtb \
+	imx6q-gw54xx.dtb \
+	imx6q-nitrogen6x.dtb \
 	imx6q-phytec-pbab01.dtb \
 	imx6q-sabreauto.dtb \
 	imx6q-sabrelite.dtb \
@@ -183,6 +233,9 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
 	imx28-cfa10056.dtb \
 	imx28-cfa10057.dtb \
 	imx28-cfa10058.dtb \
+	imx28-duckbill.dtb \
+	imx28-eukrea-mbmx283lc.dtb \
+	imx28-eukrea-mbmx287lc.dtb \
 	imx28-evk.dtb \
 	imx28-m28cu3.dtb \
 	imx28-m28evk.dtb \
@@ -234,6 +287,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \
+	qcom-msm8960-cdp.dtb \
+	qcom-apq8074-dragonboard.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
 	ste-hrefprev60-tvk.dtb \
@@ -323,7 +379,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \
 	zynq-zc706.dtb \
 	zynq-zed.dtb
 
-targets += dtbs
+targets += dtbs dtbs_install
 targets += $(dtb-y)
 endif
 
@@ -333,3 +389,5 @@ dtbs: $(addprefix $(obj)/, $(dtb-y))
 	$(Q)rm -f $(obj)/../*.dtb
 
 clean-files := *.dtb
+
+dtbs_install: $(addsuffix _dtbinst_, $(dtb-y))
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index 08a56bcfc724..82f238a9063f 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -64,6 +64,22 @@
 				phy-mode = "rgmii-id";
 			};
 
+			i2c@11000 {
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				audio_codec: audio-codec@4a {
+					compatible = "cirrus,cs42l51";
+					reg = <0x4a>;
+				};
+			};
+
+			audio-controller@30000 {
+				pinctrl-0 = <&i2s_pins2>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
 			mvsdio@d4000 {
 				pinctrl-0 = <&sdio_pins1>;
 				pinctrl-names = "default";
@@ -80,6 +96,30 @@
 				broken-cd;
 			};
 
+			pinctrl {
+				/*
+				 * These pins might be muxed as I2S by
+				 * the bootloader, but it conflicts
+				 * with the real I2S pins that are
+				 * muxed using i2s_pins. We must mux
+				 * those pins to a function other than
+				 * I2S.
+				 */
+				pinctrl-0 = <&hog_pins1 &hog_pins2>;
+				pinctrl-names = "default";
+
+				hog_pins1: hog-pins1 {
+					marvell,pins = "mpp6",  "mpp8", "mpp10",
+						       "mpp12", "mpp13";
+					marvell,function = "gpio";
+				};
+
+				hog_pins2: hog-pins2 {
+					marvell,pins = "mpp5", "mpp7", "mpp9";
+					marvell,function = "gpo";
+				};
+			};
+
 			usb@50000 {
 				status = "okay";
 			};
@@ -112,10 +152,26 @@
 				/* Port 0, Lane 0 */
 				status = "okay";
 			};
+
 			pcie@2,0 {
 				/* Port 1, Lane 0 */
 				status = "okay";
 			};
 		};
 	};
+
+	sound {
+	      compatible = "marvell,a370db-audio";
+	      marvell,audio-controller = <&audio_controller>;
+	      marvell,audio-codec = <&audio_codec &spdif_out &spdif_in>;
+	      status = "okay";
+	};
+
+	spdif_out: spdif-out {
+	      compatible = "linux,spdif-dit";
+	};
+
+	spdif_in: spdif-in {
+	      compatible = "linux,spdif-dir";
+	};
 };
diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
index 944e8785b308..2354fe023ee0 100644
--- a/arch/arm/boot/dts/armada-370-mirabox.dts
+++ b/arch/arm/boot/dts/armada-370-mirabox.dts
@@ -9,6 +9,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-370.dtsi"
 
 / {
@@ -73,19 +74,19 @@
 
 				green_pwr_led {
 					label = "mirabox:green:pwr";
-					gpios = <&gpio1 31 1>;
+					gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
 					default-state = "keep";
 				};
 
 				blue_stat_led {
 					label = "mirabox:blue:stat";
-					gpios = <&gpio2 0 1>;
+					gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
 					default-state = "off";
 				};
 
 				green_stat_led {
 					label = "mirabox:green:stat";
-					gpios = <&gpio2 1 1>;
+					gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
 					default-state = "off";
 				};
 			};
diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index abbb807459d2..3e2c857d6000 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -12,6 +12,8 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-370.dtsi"
 
 / {
@@ -100,8 +102,8 @@
 				#size-cells = <0>;
 				button@1 {
 					label = "Software Button";
-					linux,code = <116>;
-					gpios = <&gpio0 6 1>;
+					linux,code = <KEY_POWER>;
+					gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 74b5964430ac..7bbc4ac997fb 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -199,6 +199,10 @@
 				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
 			};
 
+			watchdog@20300 {
+				reg = <0x20300 0x34>, <0x20704 0x4>;
+			};
+
 			usb@50000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x50000 0x500>;
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 0d8530c98cf5..af1f11e9e5a0 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -132,6 +132,25 @@
 							"mpp51", "mpp52", "mpp53";
 					marvell,function = "sd0";
 				};
+
+				i2c0_pins: i2c0-pins {
+					marvell,pins = "mpp2", "mpp3";
+					marvell,function = "i2c0";
+				};
+
+				i2s_pins1: i2s-pins1 {
+					marvell,pins = "mpp5", "mpp6", "mpp7",
+						       "mpp8", "mpp9", "mpp10",
+						       "mpp12", "mpp13";
+					marvell,function = "audio";
+				};
+
+				i2s_pins2: i2s-pins2 {
+					marvell,pins = "mpp49", "mpp47", "mpp50",
+						       "mpp59", "mpp57", "mpp61",
+						       "mpp62", "mpp60", "mpp58";
+					marvell,function = "audio";
+				};
 			};
 
 			gpio0: gpio@18100 {
@@ -196,6 +215,20 @@
 				clocks = <&coreclk 2>;
 			};
 
+			watchdog@20300 {
+				compatible = "marvell,armada-370-wdt";
+				clocks = <&coreclk 2>;
+			};
+
+			audio_controller: audio-controller@30000 {
+				compatible = "marvell,armada370-audio";
+				reg = <0x30000 0x4000>;
+				interrupts = <93>;
+				clocks = <&gateclk 0>;
+				clock-names = "internal";
+				status = "disabled";
+			};
+
 			usb@50000 {
 				clocks = <&coreclk 0>;
 			};
diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts
new file mode 100644
index 000000000000..9378d3136b41
--- /dev/null
+++ b/arch/arm/boot/dts/armada-375-db.dts
@@ -0,0 +1,130 @@
+/*
+ * Device Tree file for Marvell Armada 375 evaluation board
+ * (DB-88F6720)
+ *
+ *  Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 <dt-bindings/gpio/gpio.h>
+#include "armada-375.dtsi"
+
+/ {
+	model = "Marvell Armada 375 Development Board";
+	compatible = "marvell,a375-db", "marvell,armada375";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1 GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi@10600 {
+				pinctrl-0 = <&spi0_pins>;
+				pinctrl-names = "default";
+				/*
+				 * SPI conflicts with NAND, so we disable it
+				 * here, and select NAND as the enabled device
+				 * by default.
+				 */
+				status = "disabled";
+
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a13";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+			};
+
+			i2c@11000 {
+				status = "okay";
+				clock-frequency = <100000>;
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+			};
+
+			i2c@11100 {
+				status = "okay";
+				clock-frequency = <100000>;
+				pinctrl-0 = <&i2c1_pins>;
+				pinctrl-names = "default";
+			};
+
+			serial@12000 {
+				clock-frequency = <200000000>;
+				status = "okay";
+			};
+
+			pinctrl {
+				sdio_st_pins: sdio-st-pins {
+					marvell,pins = "mpp44", "mpp45";
+					marvell,function = "gpio";
+				};
+			};
+
+			nand: nand@d0000 {
+				pinctrl-0 = <&nand_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				num-cs = <1>;
+				marvell,nand-keep-config;
+				marvell,nand-enable-arbiter;
+				nand-on-flash-bbt;
+
+				partition@0 {
+					label = "U-Boot";
+					reg = <0 0x800000>;
+				};
+				partition@800000 {
+					label = "Linux";
+					reg = <0x800000 0x800000>;
+				};
+				partition@1000000 {
+					label = "Filesystem";
+					reg = <0x1000000 0x3f000000>;
+				};
+			};
+
+			mvsdio@d4000 {
+				pinctrl-0 = <&sdio_pins &sdio_st_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+				wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
new file mode 100644
index 000000000000..3877693fb2d8
--- /dev/null
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -0,0 +1,464 @@
+/*
+ * Device Tree Include file for Marvell Armada 375 family SoC
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+	model = "Marvell Armada 375 family SoC";
+	compatible = "marvell,armada375";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
+	clocks {
+		/* 2 GHz fixed main PLL */
+		mainpll: mainpll {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <2000000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	soc {
+		compatible = "marvell,armada375-mbus", "marvell,armada370-mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		interrupt-parent = <&gic>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+		};
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			L2: cache-controller@8000 {
+				compatible = "arm,pl310-cache";
+				reg = <0x8000 0x1000>;
+				cache-unified;
+				cache-level = <2>;
+			};
+
+			timer@c600 {
+				compatible = "arm,cortex-a9-twd-timer";
+				reg = <0xc600 0x20>;
+				interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
+				clocks = <&coreclk 2>;
+			};
+
+			gic: interrupt-controller@d000 {
+				compatible = "arm,cortex-a9-gic";
+				#interrupt-cells = <3>;
+				#size-cells = <0>;
+				interrupt-controller;
+				reg = <0xd000 0x1000>,
+				      <0xc100 0x100>;
+			};
+
+			spi0: spi@10600 {
+				compatible = "marvell,orion-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			spi1: spi@10680 {
+				compatible = "marvell,orion-spi";
+				reg = <0x10680 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			serial@12000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				status = "disabled";
+			};
+
+			serial@12100 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				status = "disabled";
+			};
+
+			pinctrl {
+				compatible = "marvell,mv88f6720-pinctrl";
+				reg = <0x18000 0x24>;
+
+				i2c0_pins: i2c0-pins {
+					marvell,pins = "mpp14",  "mpp15";
+					marvell,function = "i2c0";
+				};
+
+				i2c1_pins: i2c1-pins {
+					marvell,pins = "mpp61",  "mpp62";
+					marvell,function = "i2c1";
+				};
+
+				nand_pins: nand-pins {
+					marvell,pins = "mpp0", "mpp1", "mpp2",
+						"mpp3", "mpp4", "mpp5",
+						"mpp6", "mpp7", "mpp8",
+						"mpp9", "mpp10", "mpp11",
+						"mpp12", "mpp13";
+					marvell,function = "nand";
+				};
+
+				sdio_pins: sdio-pins {
+					marvell,pins = "mpp24",  "mpp25", "mpp26",
+						     "mpp27", "mpp28", "mpp29";
+					marvell,function = "sd";
+				};
+
+				spi0_pins: spi0-pins {
+					marvell,pins = "mpp0",  "mpp1", "mpp4",
+						     "mpp5", "mpp8", "mpp9";
+					marvell,function = "spi0";
+				};
+			};
+
+			gpio0: gpio@18100 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18100 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio1: gpio@18140 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18140 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio2: gpio@18180 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18180 0x40>;
+				ngpios = <3>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			system-controller@18200 {
+				compatible = "marvell,armada-375-system-controller";
+				reg = <0x18200 0x100>;
+			};
+
+			gateclk: clock-gating-control@18220 {
+				compatible = "marvell,armada-375-gating-clock";
+				reg = <0x18220 0x4>;
+				clocks = <&coreclk 0>;
+				#clock-cells = <1>;
+			};
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			mpic: interrupt-controller@20000 {
+				compatible = "marvell,mpic";
+				reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+				#interrupt-cells = <1>;
+				#size-cells = <1>;
+				interrupt-controller;
+				msi-controller;
+				interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			timer@20300 {
+				compatible = "marvell,armada-375-timer", "marvell,armada-370-timer";
+				reg = <0x20300 0x30>, <0x21040 0x30>;
+				interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+						      <&mpic 5>,
+						      <&mpic 6>;
+				clocks = <&coreclk 0>;
+			};
+
+			xor@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60A00 0x100>;
+				clocks = <&gateclk 22>;
+				status = "okay";
+
+				xor00 {
+					interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor01 {
+					interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			xor@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gateclk 23>;
+				status = "okay";
+
+				xor10 {
+					interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			sata@a0000 {
+				compatible = "marvell,orion-sata";
+				reg = <0xa0000 0x5000>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 14>, <&gateclk 20>;
+				clock-names = "0", "1";
+				status = "disabled";
+			};
+
+			nand@d0000 {
+				compatible = "marvell,armada370-nand";
+				reg = <0xd0000 0x54>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 11>;
+				status = "disabled";
+			};
+
+			mvsdio@d4000 {
+				compatible = "marvell,orion-sdio";
+				reg = <0xd4000 0x200>;
+				interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 17>;
+				bus-width = <4>;
+				cap-sdio-irq;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				status = "disabled";
+			};
+
+			coreclk: mvebu-sar@e8204 {
+				compatible = "marvell,armada-375-core-clock";
+				reg = <0xe8204 0x04>;
+				#clock-cells = <1>;
+			};
+
+			coredivclk: corediv-clock@e8250 {
+				compatible = "marvell,armada-375-corediv-clock";
+				reg = <0xe8250 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0       MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 1 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi
new file mode 100644
index 000000000000..068031f0f263
--- /dev/null
+++ b/arch/arm/boot/dts/armada-380.dtsi
@@ -0,0 +1,117 @@
+/*
+ * Device Tree Include file for Marvell Armada 380 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 "armada-38x.dtsi"
+
+/ {
+	model = "Marvell Armada 380 family SoC";
+	compatible = "marvell,armada380", "marvell,armada38x";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			pinctrl {
+				compatible = "marvell,mv88f6810-pinctrl";
+				reg = <0x18000 0x20>;
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO  */>;
+
+			/* x1 port */
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-385-db.dts b/arch/arm/boot/dts/armada-385-db.dts
new file mode 100644
index 000000000000..01b6cc76ddc8
--- /dev/null
+++ b/arch/arm/boot/dts/armada-385-db.dts
@@ -0,0 +1,101 @@
+/*
+ * Device Tree file for Marvell Armada 385 evaluation board
+ * (DB-88F6820)
+ *
+ *  Copyright (C) 2014 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@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 "armada-385.dtsi"
+
+/ {
+	model = "Marvell Armada 385 Development Board";
+	compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada38x";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi@10600 {
+				status = "okay";
+
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "w25q32";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+			};
+
+			i2c@11000 {
+				status = "okay";
+				clock-frequency = <100000>;
+			};
+
+			i2c@11100 {
+				status = "okay";
+				clock-frequency = <100000>;
+			};
+
+			serial@12000 {
+				clock-frequency = <200000000>;
+				status = "okay";
+			};
+
+			ethernet@30000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "rgmii";
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii";
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 {
+					reg = <1>;
+				};
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
new file mode 100644
index 000000000000..e2919f02e1d4
--- /dev/null
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -0,0 +1,149 @@
+/*
+ * Device Tree Include file for Marvell Armada 385 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 "armada-38x.dtsi"
+
+/ {
+	model = "Marvell Armada 385 family SoC";
+	compatible = "marvell,armada385", "marvell,armada38x";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			pinctrl {
+				compatible = "marvell,mv88f6820-pinctrl";
+				reg = <0x18000 0x20>;
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO  */
+				0x82000000 0x4 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 3 MEM */
+				0x81000000 0x4 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 3 IO  */>;
+
+			/*
+			 * This port can be either x4 or x1. When
+			 * configured in x4 by the bootloader, then
+			 * pcie@4,0 is not available.
+			 */
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+			/*
+			 * x1 port only available when pcie@1,0 is
+			 * configured as a x1 port
+			 */
+			pcie@4,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <3>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 7>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
new file mode 100644
index 000000000000..812ce280b349
--- /dev/null
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -0,0 +1,351 @@
+/*
+ * Device Tree Include file for Marvell Armada 38x family of SoCs.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+	model = "Marvell Armada 38x family SoC";
+	compatible = "marvell,armada38x";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		eth0 = &eth0;
+		eth1 = &eth1;
+		eth2 = &eth2;
+	};
+
+	soc {
+		compatible = "marvell,armada380-mbus", "marvell,armada370-mbus",
+			     "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		interrupt-parent = <&gic>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x200000>;
+		};
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			L2: cache-controller@8000 {
+				compatible = "arm,pl310-cache";
+				reg = <0x8000 0x1000>;
+				cache-unified;
+				cache-level = <2>;
+			};
+
+			timer@c600 {
+				compatible = "arm,cortex-a9-twd-timer";
+				reg = <0xc600 0x20>;
+				interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
+				clocks = <&coreclk 2>;
+			};
+
+			gic: interrupt-controller@d000 {
+				compatible = "arm,cortex-a9-gic";
+				#interrupt-cells = <3>;
+				#size-cells = <0>;
+				interrupt-controller;
+				reg = <0xd000 0x1000>,
+				      <0xc100 0x100>;
+			};
+
+			spi0: spi@10600 {
+				compatible = "marvell,orion-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			spi1: spi@10680 {
+				compatible = "marvell,orion-spi";
+				reg = <0x10680 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			serial@12000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				status = "disabled";
+			};
+
+			serial@12100 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				status = "disabled";
+			};
+
+			pinctrl {
+				compatible = "marvell,mv88f6820-pinctrl";
+				reg = <0x18000 0x20>;
+			};
+
+			gpio0: gpio@18100 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18100 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio1: gpio@18140 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18140 0x40>;
+				ngpios = <28>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			system-controller@18200 {
+				compatible = "marvell,armada-380-system-controller",
+					     "marvell,armada-370-xp-system-controller";
+				reg = <0x18200 0x100>;
+			};
+
+			gateclk: clock-gating-control@18220 {
+				compatible = "marvell,armada-380-gating-clock";
+				reg = <0x18220 0x4>;
+				clocks = <&coreclk 0>;
+				#clock-cells = <1>;
+			};
+
+			coreclk: mvebu-sar@18600 {
+				compatible = "marvell,armada-380-core-clock";
+				reg = <0x18600 0x04>;
+				#clock-cells = <1>;
+			};
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			mpic: interrupt-controller@20000 {
+				compatible = "marvell,mpic";
+				reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+				#interrupt-cells = <1>;
+				#size-cells = <1>;
+				interrupt-controller;
+				msi-controller;
+				interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			timer@20300 {
+				compatible = "marvell,armada-380-timer",
+					     "marvell,armada-xp-timer";
+				reg = <0x20300 0x30>, <0x21040 0x30>;
+				interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+						      <&mpic 5>,
+						      <&mpic 6>;
+				clocks = <&coreclk 2>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
+			eth1: ethernet@30000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x30000 0x4000>;
+				interrupts-extended = <&mpic 10>;
+				clocks = <&gateclk 3>;
+				status = "disabled";
+			};
+
+			eth2: ethernet@34000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x34000 0x4000>;
+				interrupts-extended = <&mpic 12>;
+				clocks = <&gateclk 2>;
+				status = "disabled";
+			};
+
+			xor@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60a00 0x100>;
+				clocks = <&gateclk 22>;
+				status = "okay";
+
+				xor00 {
+					interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor01 {
+					interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			xor@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gateclk 28>;
+				status = "okay";
+
+				xor10 {
+					interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			eth0: ethernet@70000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x70000 0x4000>;
+				interrupts-extended = <&mpic 8>;
+				clocks = <&gateclk 4>;
+				status = "disabled";
+			};
+
+			mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0x72004 0x4>;
+			};
+		};
+	};
+
+	clocks {
+		/* 25 MHz reference crystal */
+		refclk: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-xp-axpwifiap.dts b/arch/arm/boot/dts/armada-xp-axpwifiap.dts
index c5fe57269f5a..d83d7d69ac01 100644
--- a/arch/arm/boot/dts/armada-xp-axpwifiap.dts
+++ b/arch/arm/boot/dts/armada-xp-axpwifiap.dts
@@ -16,6 +16,8 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include "armada-xp-mv78230.dtsi"
 
 / {
@@ -157,8 +159,8 @@
 
 		button@1 {
 			label = "Factory Reset Button";
-			linux,code = <141>; /* KEY_SETUP */
-			gpios = <&gpio1 1 1>;
+			linux,code = <KEY_SETUP>;
+			gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
index 99bcf76e6953..985948ce67b3 100644
--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
@@ -11,6 +11,8 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include "armada-xp-mv78260.dtsi"
 
 / {
@@ -90,19 +92,19 @@
 
 				red_led {
 					label = "red_led";
-					gpios = <&gpio1 17 1>;
+					gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
 					default-state = "off";
 				};
 
 				yellow_led {
 					label = "yellow_led";
-					gpios = <&gpio1 19 1>;
+					gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
 					default-state = "off";
 				};
 
 				green_led {
 					label = "green_led";
-					gpios = <&gpio1 21 1>;
+					gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
 					default-state = "keep";
 				};
 			};
@@ -114,8 +116,8 @@
 
 				button@1 {
 					label = "Init Button";
-					linux,code = <116>;
-					gpios = <&gpio1 28 0>;
+					linux,code = <KEY_POWER>;
+					gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index b8b84a22f0f3..abb9f9dcc525 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -111,6 +111,12 @@
 				clock-names = "nbclk", "fixed";
 			};
 
+			watchdog@20300 {
+				compatible = "marvell,armada-xp-wdt";
+				clocks = <&coreclk 2>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
 			armada-370-xp-pmsu@22000 {
 				compatible = "marvell,armada-370-xp-pmsu";
 				reg = <0x22100 0x400>, <0x20800 0x20>;
diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi
index f8674bcc4489..0c81dc945aed 100644
--- a/arch/arm/boot/dts/atlas6.dtsi
+++ b/arch/arm/boot/dts/atlas6.dtsi
@@ -217,8 +217,8 @@
 				interrupts = <17>;
 				fifosize = <128>;
 				clocks = <&clks 13>;
-				sirf,uart-dma-rx-channel = <21>;
-				sirf,uart-dma-tx-channel = <2>;
+				dmas = <&dmac1 5>, <&dmac0 2>;
+				dma-names = "rx", "tx";
 			};
 
 			uart1: uart@b0060000 {
@@ -228,6 +228,7 @@
 				interrupts = <18>;
 				fifosize = <32>;
 				clocks = <&clks 14>;
+				dma-names = "no-rx", "no-tx";
 			};
 
 			uart2: uart@b0070000 {
@@ -237,8 +238,8 @@
 				interrupts = <19>;
 				fifosize = <128>;
 				clocks = <&clks 15>;
-				sirf,uart-dma-rx-channel = <6>;
-				sirf,uart-dma-tx-channel = <7>;
+				dmas = <&dmac0 6>, <&dmac0 7>;
+				dma-names = "rx", "tx";
 			};
 
 			usp0: usp@b0080000 {
@@ -248,8 +249,8 @@
 				interrupts = <20>;
 				fifosize = <128>;
 				clocks = <&clks 28>;
-				sirf,usp-dma-rx-channel = <17>;
-				sirf,usp-dma-tx-channel = <18>;
+				dmas = <&dmac1 1>, <&dmac1 2>;
+				dma-names = "rx", "tx";
 			};
 
 			usp1: usp@b0090000 {
@@ -259,8 +260,8 @@
 				interrupts = <21>;
 				fifosize = <128>;
 				clocks = <&clks 29>;
-				sirf,usp-dma-rx-channel = <14>;
-				sirf,usp-dma-tx-channel = <15>;
+				dmas = <&dmac0 14>, <&dmac0 15>;
+				dma-names = "rx", "tx";
 			};
 
 			dmac0: dma-controller@b00b0000 {
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index b021c96d3ba1..b8473c43e888 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -15,39 +15,52 @@
 		#size-cells = <1>;
 		ranges = <0x7e000000 0x20000000 0x02000000>;
 
-		timer {
+		timer@7e003000 {
 			compatible = "brcm,bcm2835-system-timer";
 			reg = <0x7e003000 0x1000>;
 			interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
 			clock-frequency = <1000000>;
 		};
 
-		intc: interrupt-controller {
+		dma: dma@7e007000 {
+			compatible = "brcm,bcm2835-dma";
+			reg = <0x7e007000 0xf00>;
+			interrupts = <1 16>,
+				     <1 17>,
+				     <1 18>,
+				     <1 19>,
+				     <1 20>,
+				     <1 21>,
+				     <1 22>,
+				     <1 23>,
+				     <1 24>,
+				     <1 25>,
+				     <1 26>,
+				     <1 27>,
+				     <1 28>;
+
+			#dma-cells = <1>;
+			brcm,dma-channel-mask = <0x7f35>;
+		};
+
+		intc: interrupt-controller@7e00b200 {
 			compatible = "brcm,bcm2835-armctrl-ic";
 			reg = <0x7e00b200 0x200>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
 
-		watchdog {
+		watchdog@7e100000 {
 			compatible = "brcm,bcm2835-pm-wdt";
 			reg = <0x7e100000 0x28>;
 		};
 
-		rng {
+		rng@7e104000 {
 			compatible = "brcm,bcm2835-rng";
 			reg = <0x7e104000 0x10>;
 		};
 
-		uart@20201000 {
-			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-			reg = <0x7e201000 0x1000>;
-			interrupts = <2 25>;
-			clock-frequency = <3000000>;
-			arm,primecell-periphid = <0x00241011>;
-		};
-
-		gpio: gpio {
+		gpio: gpio@7e200000 {
 			compatible = "brcm,bcm2835-gpio";
 			reg = <0x7e200000 0xb4>;
 			/*
@@ -70,7 +83,25 @@
 			#interrupt-cells = <2>;
 		};
 
-		spi: spi@20204000 {
+		uart@7e201000 {
+			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
+			reg = <0x7e201000 0x1000>;
+			interrupts = <2 25>;
+			clock-frequency = <3000000>;
+			arm,primecell-periphid = <0x00241011>;
+		};
+
+		i2s: i2s@7e203000 {
+			compatible = "brcm,bcm2835-i2s";
+			reg = <0x7e203000 0x20>,
+			      <0x7e101098 0x02>;
+
+			dmas = <&dma 2>,
+			       <&dma 3>;
+			dma-names = "tx", "rx";
+		};
+
+		spi: spi@7e204000 {
 			compatible = "brcm,bcm2835-spi";
 			reg = <0x7e204000 0x1000>;
 			interrupts = <2 22>;
@@ -90,7 +121,15 @@
 			status = "disabled";
 		};
 
-		i2c1: i2c@20804000 {
+		sdhci: sdhci@7e300000 {
+			compatible = "brcm,bcm2835-sdhci";
+			reg = <0x7e300000 0x100>;
+			interrupts = <2 30>;
+			clocks = <&clk_mmc>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@7e804000 {
 			compatible = "brcm,bcm2835-i2c";
 			reg = <0x7e804000 0x1000>;
 			interrupts = <2 21>;
@@ -100,19 +139,15 @@
 			status = "disabled";
 		};
 
-		sdhci: sdhci {
-			compatible = "brcm,bcm2835-sdhci";
-			reg = <0x7e300000 0x100>;
-			interrupts = <2 30>;
-			clocks = <&clk_mmc>;
-			status = "disabled";
-		};
-
-		usb {
+		usb@7e980000 {
 			compatible = "brcm,bcm2835-usb";
 			reg = <0x7e980000 0x10000>;
 			interrupts = <1 9>;
 		};
+
+		arm-pmu {
+			compatible = "arm,arm1176-pmu";
+		};
 	};
 
 	clocks {
@@ -120,24 +155,27 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		clk_mmc: mmc {
+		clk_mmc: clock@0 {
 			compatible = "fixed-clock";
 			reg = <0>;
 			#clock-cells = <0>;
+			clock-output-names = "mmc";
 			clock-frequency = <100000000>;
 		};
 
-		clk_i2c: i2c {
+		clk_i2c: clock@1 {
 			compatible = "fixed-clock";
 			reg = <1>;
 			#clock-cells = <0>;
+			clock-output-names = "i2c";
 			clock-frequency = <250000000>;
 		};
 
-		clk_spi: spi {
+		clk_spi: clock@2 {
 			compatible = "fixed-clock";
 			reg = <2>;
 			#clock-cells = <0>;
+			clock-output-names = "spi";
 			clock-frequency = <250000000>;
 		};
 	};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 187fd46b7b5e..7b826ecd264c 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -210,6 +210,14 @@
 				clocks = <&core_clk 0>;
 			};
 
+			watchdog@20300 {
+				compatible = "marvell,orion-wdt";
+				reg = <0x20300 0x28>, <0x20108 0x4>;
+				interrupt-parent = <&bridge_intc>;
+				interrupts = <3>;
+				clocks = <&core_clk 0>;
+			};
+
 			crypto: crypto-engine@30000 {
 				compatible = "marvell,orion-crypto";
 				reg = <0x30000 0x10000>,
@@ -379,9 +387,20 @@
 				#clock-cells = <1>;
 			};
 
+			pmu_intc: pmu-interrupt-ctrl@d0050 {
+				compatible = "marvell,dove-pmu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0xd0050 0x8>;
+				interrupts = <33>;
+				marvell,#interrupts = <7>;
+			};
+
 			pinctrl: pin-ctrl@d0200 {
 				compatible = "marvell,dove-pinctrl";
-				reg = <0xd0200 0x10>;
+				reg = <0xd0200 0x14>,
+				      <0xd0440 0x04>,
+				      <0xd802c 0x08>;
 				clocks = <&gate_clk 22>;
 
 				pmx_gpio_0: pmx-gpio-0 {
@@ -601,6 +620,14 @@
 			rtc: real-time-clock@d8500 {
 				compatible = "marvell,orion-rtc";
 				reg = <0xd8500 0x20>;
+				interrupt-parent = <&pmu_intc>;
+				interrupts = <5>;
+			};
+
+			gconf: global-config@e802c {
+				compatible = "marvell,dove-global-config",
+				             "syscon";
+				reg = <0xe802c 0x14>;
 			};
 
 			gpio2: gpio-ctrl@e8400 {
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 9804fcb71f8c..12459b01cca3 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -251,7 +251,7 @@
 				buck2_reg: BUCK2 {
 					regulator-name = "vdd_arm";
 					regulator-min-microvolt = <900000>;
-					regulator-max-microvolt = <1300000>;
+					regulator-max-microvolt = <1350000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 6bc053924e9e..388f03579661 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -459,8 +459,8 @@
 
 				buck2_reg: BUCK2 {
 					regulator-name = "vdd_arm";
-					regulator-min-microvolt = <925000>;
-					regulator-max-microvolt	= <1300000>;
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt	= <1350000>;
 					regulator-always-on;
 					regulator-boot-on;
 					op_mode = <1>; /* Normal Mode */
diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index 258dca441f36..79d0608d6dcc 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -81,13 +81,6 @@
 		status = "disabled";
 	};
 
-	watchdog {
-		compatible = "samsung,s3c2410-wdt";
-		reg = <0x101D0000 0x100>;
-		interrupts = <0 42 0>;
-		status = "disabled";
-	};
-
 	fimd@14400000 {
 		compatible = "samsung,exynos5250-fimd";
 		interrupt-parent = <&combiner>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index b42e658876e5..38b96a4cba6d 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -25,6 +25,10 @@
 		bootargs = "console=ttySAC2,115200";
 	};
 
+	rtc@101E0000 {
+		status = "okay";
+	};
+
 	codec@11000000 {
 		samsung,mfc-r = <0x43000000 0x800000>;
 		samsung,mfc-l = <0x51000000 0x800000>;
@@ -287,6 +291,7 @@
 					regulator-name = "vdd_g3d";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
 					regulator-boot-on;
 					op_mode = <1>;
 				};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 3e69837c435c..f76946e97e6a 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -27,6 +27,10 @@
 		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
 	};
 
+	rtc@101E0000 {
+		status = "okay";
+	};
+
 	i2c@12C60000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <20000>;
@@ -36,6 +40,148 @@
 			compatible = "samsung,s524ad0xd1";
 			reg = <0x50>;
 		};
+
+		max77686@09 {
+			compatible = "maxim,max77686";
+			reg = <0x09>;
+
+			voltage-regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "P1.0V_LDO_OUT1";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "P1.2V_LDO_OUT2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "P1.8V_LDO_OUT3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "P2.8V_LDO_OUT4";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "P1.8V_LDO_OUT5";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "P1.1V_LDO_OUT6";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "P1.1V_LDO_OUT7";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "P1.0V_LDO_OUT8";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "P1.8V_LDO_OUT10";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "P1.8V_LDO_OUT11";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "P3.0V_LDO_OUT12";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "P1.8V_LDO_OUT13";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "P1.8V_LDO_OUT14";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "P1.0V_LDO_OUT15";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "P1.8V_LDO_OUT16";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "P1.8V_BUCK_OUT5";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+			};
+		};
 	};
 
 	vdd: fixed-regulator@0 {
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
index 7e45eea2d78f..b13bf499f5e2 100644
--- a/arch/arm/boot/dts/exynos5250-snow.dts
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -20,6 +20,10 @@
 		i2c104 = &i2c_104;
 	};
 
+	rtc@101E0000 {
+		status = "okay";
+	};
+
 	pinctrl@11400000 {
 		sd3_clk: sd3-clk {
 			samsung,pin-drv = <0>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index b7dec41e32af..8f6300fb2315 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -167,9 +167,18 @@
 		interrupts = <0 47 0>;
 	};
 
-	watchdog {
+	pmu_system_controller: system-controller@10040000 {
+		compatible = "samsung,exynos5250-pmu", "syscon";
+		reg = <0x10040000 0x5000>;
+	};
+
+	watchdog@101D0000 {
+		compatible = "samsung,exynos5250-wdt";
+		reg = <0x101D0000 0x100>;
+		interrupts = <0 42 0>;
 		clocks = <&clock 336>;
 		clock-names = "watchdog";
+		samsung,syscon-phandle = <&pmu_system_controller>;
 	};
 
 	g2d@10850000 {
@@ -192,7 +201,7 @@
 	rtc@101E0000 {
 		clocks = <&clock 337>;
 		clock-names = "rtc";
-		status = "okay";
+		status = "disabled";
 	};
 
 	tmu@10060000 {
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 7340745ff979..f509e8fc290f 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 #include "exynos5420.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
@@ -31,6 +33,10 @@
 		};
 	};
 
+	rtc@101E0000 {
+		status = "okay";
+	};
+
 	mmc@12200000 {
 		status = "okay";
 		broken-cd;
@@ -41,6 +47,7 @@
 		samsung,dw-mshc-ddr-timing = <0 2>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+		vmmc-supply = <&ldo10_reg>;
 
 		slot@0 {
 			reg = <0>;
@@ -57,10 +64,301 @@
 		samsung,dw-mshc-ddr-timing = <1 2>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+		vmmc-supply = <&ldo10_reg>;
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <4>;
 		};
 	};
+
+	hsi2c_4: i2c@12CA0000 {
+		status = "okay";
+
+		s2mps11_pmic@66 {
+			compatible = "samsung,s2mps11-pmic";
+			reg = <0x66>;
+			s2mps11,buck2-ramp-delay = <12>;
+			s2mps11,buck34-ramp-delay = <12>;
+			s2mps11,buck16-ramp-delay = <12>;
+			s2mps11,buck6-ramp-enable = <1>;
+			s2mps11,buck2-ramp-enable = <1>;
+			s2mps11,buck3-ramp-enable = <1>;
+			s2mps11,buck4-ramp-enable = <1>;
+
+			interrupt-parent = <&gpx3>;
+			interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+
+			s2mps11_osc: clocks {
+				#clock-cells = <1>;
+				clock-output-names = "s2mps11_ap",
+						"s2mps11_cp", "s2mps11_bt";
+			};
+
+			regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "PVDD_ALIVE_1V0";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "PVDD_APIO_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "PVDD_APIO_MMCON_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "PVDD_ADC_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "PVDD_PLL_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "PVDD_ANAIP_1V0";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "PVDD_ANAIP_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "PVDD_ABB_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "PVDD_USB_3V3";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "PVDD_PRE_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "PVDD_USB_1V0";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "PVDD_HSIC_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "PVDD_APIO_MMCOFF_2V8";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "PVDD_PERI_2V8";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "PVDD_PERI_3V3";
+					regulator-min-microvolt = <2200000>;
+					regulator-max-microvolt = <2200000>;
+				};
+
+				ldo18_reg: LDO18 {
+					regulator-name = "PVDD_EMMC_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo19_reg: LDO19 {
+					regulator-name = "PVDD_TFLASH_2V8";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo20_reg: LDO20 {
+					regulator-name = "PVDD_BTWIFI_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo21_reg: LDO21 {
+					regulator-name = "PVDD_CAM1IO_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo23_reg: LDO23 {
+					regulator-name = "PVDD_MIFS_1V1";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo24_reg: LDO24 {
+					regulator-name = "PVDD_CAM1_AVDD_2V8";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo26_reg: LDO26 {
+					regulator-name = "PVDD_CAM0_AF_2V8";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+				};
+
+				ldo27_reg: LDO27 {
+					regulator-name = "PVDD_G3DS_1V0";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo28_reg: LDO28 {
+					regulator-name = "PVDD_TSP_3V3";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo29_reg: LDO29 {
+					regulator-name = "PVDD_AUDIO_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo31_reg: LDO31 {
+					regulator-name = "PVDD_PERI_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo32_reg: LDO32 {
+					regulator-name = "PVDD_LCD_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo33_reg: LDO33 {
+					regulator-name = "PVDD_CAM0IO_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo35_reg: LDO35 {
+					regulator-name = "PVDD_CAM0_DVDD_1V2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo38_reg: LDO38 {
+					regulator-name = "PVDD_CAM0_AVDD_2V8";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "PVDD_MIF_1V1";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "PVDD_INT_1V0";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "PVDD_G3D_1V0";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "PVDD_LPDDR3_1V2";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				buck6_reg: BUCK6 {
+					regulator-name = "PVDD_KFC_1V0";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				buck7_reg: BUCK7 {
+					regulator-name = "VIN_LLDO_1V4";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-always-on;
+				};
+
+				buck8_reg: BUCK8 {
+					regulator-name = "VIN_MLDO_2V0";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <2000000>;
+					regulator-always-on;
+				};
+
+				buck9_reg: BUCK9 {
+					regulator-name = "VIN_HLDO_3V5";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3500000>;
+					regulator-always-on;
+				};
+
+				buck10_reg: BUCK10 {
+					regulator-name = "PVDD_EMMCF_2V8";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		wakeup {
+			label = "SW-TACT1";
+			gpios = <&gpx2 7 1>;
+			linux,code = <KEY_WAKEUP>;
+			gpio-key,wakeup;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index fb5a1e25c632..ae1ee0470fca 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -31,6 +31,43 @@
 		};
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd: fixed-regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd-supply";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		dbvdd: fixed-regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "dbvdd-supply";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		spkvdd: fixed-regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "spkvdd-supply";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+	};
+
+	rtc@101E0000 {
+		status = "okay";
+	};
+
 	mmc@12200000 {
 		status = "okay";
 		broken-cd;
@@ -120,4 +157,220 @@
 			reg = <0x50>;
 		};
 	};
+
+	hsi2c_4: i2c@12CA0000 {
+		status = "okay";
+
+		s2mps11_pmic@66 {
+			compatible = "samsung,s2mps11-pmic";
+			reg = <0x66>;
+			s2mps11,buck2-ramp-delay = <12>;
+			s2mps11,buck34-ramp-delay = <12>;
+			s2mps11,buck16-ramp-delay = <12>;
+			s2mps11,buck6-ramp-enable = <1>;
+			s2mps11,buck2-ramp-enable = <1>;
+			s2mps11,buck3-ramp-enable = <1>;
+			s2mps11,buck4-ramp-enable = <1>;
+
+			s2mps11_osc: clocks {
+				#clock-cells = <1>;
+				clock-output-names = "s2mps11_ap",
+						"s2mps11_cp", "s2mps11_bt";
+			};
+
+			regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "vdd_ldo1";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "vdd_ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "vdd_ldo5";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "vdd_ldo6";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "vdd_ldo7";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "vdd_ldo8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "vdd_ldo9";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "vdd_ldo10";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "vdd_ldo11";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "vdd_ldo12";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "vdd_ldo13";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "vdd_ldo15";
+					regulator-min-microvolt = <3100000>;
+					regulator-max-microvolt = <3100000>;
+					regulator-always-on;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "vdd_ldo16";
+					regulator-min-microvolt = <2200000>;
+					regulator-max-microvolt = <2200000>;
+					regulator-always-on;
+				};
+
+				ldo17_reg: LDO17 {
+					regulator-name = "tsp_avdd";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo19_reg: LDO19 {
+					regulator-name = "vdd_sd";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo24_reg: LDO24 {
+					regulator-name = "tsp_io";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "vdd_mem";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck6_reg: BUCK6 {
+					regulator-name = "vdd_kfc";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck7_reg: BUCK7 {
+					regulator-name = "vdd_1.0v_ldo";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck8_reg: BUCK8 {
+					regulator-name = "vdd_1.8v_ldo";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck9_reg: BUCK9 {
+					regulator-name = "vdd_2.8v_ldo";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3750000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck10_reg: BUCK10 {
+					regulator-name = "vdd_vmem";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+			};
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8db792b26f79..45e2e658b03b 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -271,7 +271,7 @@
 	rtc@101E0000 {
 		clocks = <&clock 317>;
 		clock-names = "rtc";
-		status = "okay";
+		status = "disabled";
 	};
 
 	amba {
@@ -281,6 +281,17 @@
 		interrupt-parent = <&gic>;
 		ranges;
 
+		adma: adma@03880000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x03880000 0x1000>;
+			interrupts = <0 110 0>;
+			clocks = <&clock_audss EXYNOS_ADMA>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+			#dma-channels = <6>;
+			#dma-requests = <16>;
+		};
+
 		pdma0: pdma@121A0000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x121A0000 0x1000>;
@@ -326,6 +337,49 @@
 		};
 	};
 
+	i2s0: i2s@03830000 {
+		compatible = "samsung,exynos5420-i2s";
+		reg = <0x03830000 0x100>;
+		dmas = <&adma 0
+			&adma 2
+			&adma 1>;
+		dma-names = "tx", "rx", "tx-sec";
+		clocks = <&clock_audss EXYNOS_I2S_BUS>,
+			<&clock_audss EXYNOS_I2S_BUS>,
+			<&clock_audss EXYNOS_SCLK_I2S>;
+		clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
+		samsung,idma-addr = <0x03000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_bus>;
+		status = "disabled";
+	};
+
+	i2s1: i2s@12D60000 {
+		compatible = "samsung,exynos5420-i2s";
+		reg = <0x12D60000 0x100>;
+		dmas = <&pdma1 12
+			&pdma1 11>;
+		dma-names = "tx", "rx";
+		clocks = <&clock 275>, <&clock 138>;
+		clock-names = "iis", "i2s_opclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s1_bus>;
+		status = "disabled";
+	};
+
+	i2s2: i2s@12D70000 {
+		compatible = "samsung,exynos5420-i2s";
+		reg = <0x12D70000 0x100>;
+		dmas = <&pdma0 12
+			&pdma0 11>;
+		dma-names = "tx", "rx";
+		clocks = <&clock 276>, <&clock 139>;
+		clock-names = "iis", "i2s_opclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s2_bus>;
+		status = "disabled";
+	};
+
 	spi_0: spi@12d20000 {
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x12d20000 0x100>;
@@ -613,6 +667,11 @@
 		samsung,power-domain = <&gsc_pd>;
 	};
 
+	pmu_system_controller: system-controller@10040000 {
+		compatible = "samsung,exynos5420-pmu", "syscon";
+		reg = <0x10040000 0x5000>;
+	};
+
 	tmu_cpu0: tmu@10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -652,4 +711,13 @@
 		clocks = <&clock 319>, <&clock 318>;
 		clock-names = "tmu_apbif", "tmu_triminfo_apbif";
 	};
+
+        watchdog@101D0000 {
+		compatible = "samsung,exynos5420-wdt";
+		reg = <0x101D0000 0x100>;
+		interrupts = <0 42 0>;
+		clocks = <&clock 316>;
+		clock-names = "watchdog";
+		samsung,syscon-phandle = <&pmu_system_controller>;
+        };
 };
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index 1f026adefd45..a33f66c11b73 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -127,17 +127,21 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_vddio_sd0: vddio-sd0 {
+		reg_vddio_sd0: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "vddio-sd0";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio1 29 0>;
 		};
 
-		reg_lcd_3v3: lcd-3v3 {
+		reg_lcd_3v3: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "lcd-3v3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index 526bfdbd87f9..7e6eef2488e8 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -100,9 +100,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
index cb64e2b191ea..455169e99d49 100644
--- a/arch/arm/boot/dts/imx23-stmp378x_devb.dts
+++ b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
@@ -66,9 +66,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_vddio_sd0: vddio-sd0 {
+		reg_vddio_sd0: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "vddio-sd0";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 581b75433be6..bbcfb5a19c77 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -23,6 +23,7 @@
 		serial1 = &auart1;
 		spi0 = &ssp0;
 		spi1 = &ssp1;
+		usbphy0 = &usbphy0;
 	};
 
 	cpus {
@@ -428,7 +429,7 @@
 				status = "disabled";
 			};
 
-			lradc@80050000 {
+			lradc: lradc@80050000 {
 				compatible = "fsl,imx23-lradc";
 				reg = <0x80050000 0x2000>;
 				interrupts = <36 37 38 39 40 41 42 43 44>;
@@ -526,4 +527,9 @@
 			status = "disabled";
 		};
 	};
+
+	iio_hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&lradc 8>;
+	};
 };
diff --git a/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi b/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
new file mode 100644
index 000000000000..d6f27641c0ef
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+#include "imx25.dtsi"
+
+/ {
+	model = "Eukrea CPUIMX25";
+	compatible = "eukrea,cpuimx25", "fsl,imx25";
+
+	memory {
+		reg = <0x80000000 0x4000000>; /* 64M */
+	};
+};
+
+&fec {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&iomuxc {
+	imx25-eukrea-cpuimx25 {
+		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
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX25_PAD_I2C1_CLK__I2C1_CLK		0x80000000
+				MX25_PAD_I2C1_DAT__I2C1_DAT		0x80000000
+			>;
+		};
+	};
+};
+
+&nfc {
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
new file mode 100644
index 000000000000..62fb3da50bdb
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx25-eukrea-cpuimx25.dtsi"
+
+/ {
+	model = "Eukrea MBIMXSD25";
+	compatible = "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpiokeys>;
+
+		bp1 {
+			label = "BP1";
+			gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_MISC>;
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioled>;
+
+		led1 {
+			label = "led1";
+			gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	sound {
+		compatible = "eukrea,asoc-tlv320";
+		eukrea,model = "imx25-eukrea-tlv320aic23";
+		ssi-controller = <&ssi1>;
+		fsl,mux-int-port = <1>;
+		fsl,mux-ext-port = <5>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	cd-gpios = <&gpio1 20>;
+	status = "okay";
+};
+
+&i2c1 {
+	tlv320aic23: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+	};
+};
+
+&iomuxc {
+	imx25-eukrea-mbimxsd25-baseboard {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX25_PAD_KPP_COL3__AUD5_TXFS		0xe0
+				MX25_PAD_KPP_COL2__AUD5_TXC		0xe0
+				MX25_PAD_KPP_COL1__AUD5_RXD		0xe0
+				MX25_PAD_KPP_COL0__AUD5_TXD		0xe0
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX25_PAD_SD1_CMD__SD1_CMD		0x400000c0
+				MX25_PAD_SD1_CLK__SD1_CLK		0x400000c0
+				MX25_PAD_SD1_DATA0__SD1_DATA0		0x400000c0
+				MX25_PAD_SD1_DATA1__SD1_DATA1		0x400000c0
+				MX25_PAD_SD1_DATA2__SD1_DATA2		0x400000c0
+				MX25_PAD_SD1_DATA3__SD1_DATA3		0x400000c0
+			>;
+		};
+
+		pinctrl_gpiokeys: gpiokeysgrp {
+			fsl,pins = <MX25_PAD_VSTBY_ACK__GPIO_3_18 0x80000000>;
+		};
+
+		pinctrl_gpioled: gpioledgrp {
+			fsl,pins = <MX25_PAD_POWER_FAIL__GPIO_3_19 0x80000000>;
+		};
+
+		pinctrl_lcdc: lcdcgrp {
+			fsl,pins = <
+				MX25_PAD_LD0__LD0			0x1
+				MX25_PAD_LD1__LD1			0x1
+				MX25_PAD_LD2__LD2			0x1
+				MX25_PAD_LD3__LD3			0x1
+				MX25_PAD_LD4__LD4			0x1
+				MX25_PAD_LD5__LD5			0x1
+				MX25_PAD_LD6__LD6			0x1
+				MX25_PAD_LD7__LD7			0x1
+				MX25_PAD_LD8__LD8			0x1
+				MX25_PAD_LD9__LD9			0x1
+				MX25_PAD_LD10__LD10			0x1
+				MX25_PAD_LD11__LD11			0x1
+				MX25_PAD_LD12__LD12			0x1
+				MX25_PAD_LD13__LD13			0x1
+				MX25_PAD_LD14__LD14			0x1
+				MX25_PAD_LD15__LD15			0x1
+				MX25_PAD_GPIO_E__LD16			0x1
+				MX25_PAD_GPIO_F__LD17			0x1
+				MX25_PAD_HSYNC__HSYNC			0x80000000
+				MX25_PAD_VSYNC__VSYNC			0x80000000
+				MX25_PAD_LSCLK__LSCLK			0x80000000
+				MX25_PAD_OE_ACD__OE_ACD			0x80000000
+				MX25_PAD_CONTRAST__CONTRAST		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
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX25_PAD_UART2_RXD__UART2_RXD		0x80000000
+				MX25_PAD_UART2_TXD__UART2_TXD		0x80000000
+				MX25_PAD_UART2_RTS__UART2_RTS		0x80000000
+				MX25_PAD_UART2_CTS__UART2_CTS		0x80000000
+			>;
+		};
+	};
+};
+
+&ssi1 {
+	codec-handle = <&tlv320aic23>;
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h
new file mode 100644
index 000000000000..9238a95d8e62
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-pinfunc.h
@@ -0,0 +1,494 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ * Based on imx35-pinfunc.h in the same directory Which is:
+ * Copyright 2013 Freescale Semiconductor, 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.
+ *
+ */
+
+#ifndef __DTS_IMX25_PINFUNC_H
+#define __DTS_IMX25_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+
+#define MX25_PAD_A10__A10			0x008 0x000 0x000 0x00 0x000
+#define MX25_PAD_A10__GPIO_4_0			0x008 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_A13__A13			0x00c 0x22C 0x000 0x00 0x000
+#define MX25_PAD_A13__GPIO_4_1			0x00c 0x22C 0x000 0x05 0x000
+
+#define MX25_PAD_A14__A14			0x010 0x230 0x000 0x10 0x000
+#define MX25_PAD_A14__GPIO_2_0			0x010 0x230 0x000 0x15 0x000
+
+#define MX25_PAD_A15__A15			0x014 0x234 0x000 0x10 0x000
+#define MX25_PAD_A15__GPIO_2_1			0x014 0x234 0x000 0x15 0x000
+
+#define MX25_PAD_A16__A16			0x018 0x000 0x000 0x10 0x000
+#define MX25_PAD_A16__GPIO_2_2			0x018 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_A17__A17			0x01c 0x238 0x000 0x10 0x000
+#define MX25_PAD_A17__GPIO_2_3			0x01c 0x238 0x000 0x15 0x000
+
+#define MX25_PAD_A18__A18			0x020 0x23c 0x000 0x10 0x000
+#define MX25_PAD_A18__GPIO_2_4			0x020 0x23c 0x000 0x15 0x000
+#define MX25_PAD_A18__FEC_COL			0x020 0x23c 0x504 0x17 0x000
+
+#define MX25_PAD_A19__A19			0x024 0x240 0x000 0x10 0x000
+#define MX25_PAD_A19__FEC_RX_ER			0x024 0x240 0x518 0x17 0x000
+#define MX25_PAD_A19__GPIO_2_5			0x024 0x240 0x000 0x15 0x000
+
+#define MX25_PAD_A20__A20			0x028 0x244 0x000 0x10 0x000
+#define MX25_PAD_A20__GPIO_2_6			0x028 0x244 0x000 0x15 0x000
+#define MX25_PAD_A20__FEC_RDATA2		0x028 0x244 0x50c 0x17 0x000
+
+#define MX25_PAD_A21__A21			0x02c 0x248 0x000 0x10 0x000
+#define MX25_PAD_A21__GPIO_2_7			0x02c 0x248 0x000 0x15 0x000
+#define MX25_PAD_A21__FEC_RDATA3		0x02c 0x248 0x510 0x17 0x000
+
+#define MX25_PAD_A22__A22			0x030 0x000 0x000 0x10 0x000
+#define MX25_PAD_A22__GPIO_2_8			0x030 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_A23__A23			0x034 0x24c 0x000 0x10 0x000
+#define MX25_PAD_A23__GPIO_2_9			0x034 0x24c 0x000 0x15 0x000
+
+#define MX25_PAD_A24__A24			0x038 0x250 0x000 0x10 0x000
+#define MX25_PAD_A24__GPIO_2_10			0x038 0x250 0x000 0x15 0x000
+#define MX25_PAD_A24__FEC_RX_CLK		0x038 0x250 0x514 0x17 0x000
+
+#define MX25_PAD_A25__A25			0x03c 0x254 0x000 0x10 0x000
+#define MX25_PAD_A25__GPIO_2_11			0x03c 0x254 0x000 0x15 0x000
+#define MX25_PAD_A25__FEC_CRS			0x03c 0x254 0x508 0x17 0x000
+
+#define MX25_PAD_EB0__EB0			0x040 0x258 0x000 0x10 0x000
+#define MX25_PAD_EB0__AUD4_TXD			0x040 0x258 0x464 0x14 0x000
+#define MX25_PAD_EB0__GPIO_2_12			0x040 0x258 0x000 0x15 0x000
+
+#define MX25_PAD_EB1__EB1			0x044 0x25c 0x000 0x10 0x000
+#define MX25_PAD_EB1__AUD4_RXD			0x044 0x25c 0x460 0x14 0x000
+#define MX25_PAD_EB1__GPIO_2_13			0x044 0x25c 0x000 0x15 0x000
+
+#define MX25_PAD_OE__OE				0x048 0x260 0x000 0x10 0x000
+#define MX25_PAD_OE__AUD4_TXC			0x048 0x260 0x000 0x14 0x000
+#define MX25_PAD_OE__GPIO_2_14			0x048 0x260 0x000 0x15 0x000
+
+#define MX25_PAD_CS0__CS0			0x04c 0x000 0x000 0x00 0x000
+#define MX25_PAD_CS0__GPIO_4_2			0x04c 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_CS1__CS1			0x050 0x000 0x000 0x00 0x000
+#define MX25_PAD_CS1__NF_CE3			0x050 0x000 0x000 0x01 0x000
+#define MX25_PAD_CS1__GPIO_4_3			0x050 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_CS4__CS4			0x054 0x264 0x000 0x10 0x000
+#define MX25_PAD_CS4__NF_CE1			0x054 0x264 0x000 0x01 0x000
+#define MX25_PAD_CS4__UART5_CTS			0x054 0x264 0x000 0x13 0x000
+#define MX25_PAD_CS4__GPIO_3_20			0x054 0x264 0x000 0x15 0x000
+
+#define MX25_PAD_CS5__CS5			0x058 0x268 0x000 0x10 0x000
+#define MX25_PAD_CS5__NF_CE2			0x058 0x268 0x000 0x01 0x000
+#define MX25_PAD_CS5__UART5_RTS			0x058 0x268 0x574 0x13 0x000
+#define MX25_PAD_CS5__GPIO_3_21			0x058 0x268 0x000 0x15 0x000
+
+#define MX25_PAD_NF_CE0__NF_CE0			0x05c 0x26c 0x000 0x10 0x000
+#define MX25_PAD_NF_CE0__GPIO_3_22		0x05c 0x26c 0x000 0x15 0x000
+
+#define MX25_PAD_ECB__ECB			0x060 0x270 0x000 0x10 0x000
+#define MX25_PAD_ECB__UART5_TXD_MUX		0x060 0x270 0x000 0x13 0x000
+#define MX25_PAD_ECB__GPIO_3_23			0x060 0x270 0x000 0x15 0x000
+
+#define MX25_PAD_LBA__LBA			0x064 0x274 0x000 0x10 0x000
+#define MX25_PAD_LBA__UART5_RXD_MUX		0x064 0x274 0x578 0x13 0x000
+#define MX25_PAD_LBA__GPIO_3_24			0x064 0x274 0x000 0x15 0x000
+
+#define MX25_PAD_BCLK__BCLK			0x068 0x000 0x000 0x00 0x000
+#define MX25_PAD_BCLK__GPIO_4_4			0x068 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_RW__RW				0x06c 0x278 0x000 0x10 0x000
+#define MX25_PAD_RW__AUD4_TXFS			0x06c 0x278 0x474 0x14 0x000
+#define MX25_PAD_RW__GPIO_3_25			0x06c 0x278 0x000 0x15 0x000
+
+#define MX25_PAD_NFWE_B__NFWE_B			0x070 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFWE_B__GPIO_3_26		0x070 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFRE_B__NFRE_B			0x074 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFRE_B__GPIO_3_27		0x074 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFALE__NFALE			0x078 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFALE__GPIO_3_28		0x078 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFCLE__NFCLE			0x07c 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFCLE__GPIO_3_29		0x07c 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFWP_B__NFWP_B			0x080 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFWP_B__GPIO_3_30		0x080 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFRB__NFRB			0x084 0x27c 0x000 0x10 0x000
+#define MX25_PAD_NFRB__GPIO_3_31		0x084 0x27c 0x000 0x15 0x000
+
+#define MX25_PAD_D15__D15			0x088 0x280 0x000 0x00 0x000
+#define MX25_PAD_D15__LD16			0x088 0x280 0x000 0x01 0x000
+#define MX25_PAD_D15__GPIO_4_5			0x088 0x280 0x000 0x05 0x000
+
+#define MX25_PAD_D14__D14			0x08c 0x284 0x000 0x00 0x000
+#define MX25_PAD_D14__LD17			0x08c 0x284 0x000 0x01 0x000
+#define MX25_PAD_D14__GPIO_4_6			0x08c 0x284 0x000 0x05 0x000
+
+#define MX25_PAD_D13__D13			0x090 0x288 0x000 0x00 0x000
+#define MX25_PAD_D13__LD18			0x090 0x288 0x000 0x01 0x000
+#define MX25_PAD_D13__GPIO_4_7			0x090 0x288 0x000 0x05 0x000
+
+#define MX25_PAD_D12__D12			0x094 0x28c 0x000 0x00 0x000
+#define MX25_PAD_D12__GPIO_4_8			0x094 0x28c 0x000 0x05 0x000
+
+#define MX25_PAD_D11__D11			0x098 0x290 0x000 0x00 0x000
+#define MX25_PAD_D11__GPIO_4_9			0x098 0x290 0x000 0x05 0x000
+
+#define MX25_PAD_D10__D10			0x09c 0x294 0x000 0x00 0x000
+#define MX25_PAD_D10__GPIO_4_10			0x09c 0x294 0x000 0x05 0x000
+#define MX25_PAD_D10__USBOTG_OC			0x09c 0x294 0x57c 0x06 0x000
+
+#define MX25_PAD_D9__D9				0x0a0 0x298 0x000 0x00 0x000
+#define MX25_PAD_D9__GPIO_4_11			0x0a0 0x298 0x000 0x05 0x000
+#define MX25_PAD_D9__USBH2_PWR			0x0a0 0x298 0x000 0x06 0x000
+
+#define MX25_PAD_D8__D8				0x0a4 0x29c 0x000 0x00 0x000
+#define MX25_PAD_D8__GPIO_4_12			0x0a4 0x29c 0x000 0x05 0x000
+#define MX25_PAD_D8__USBH2_OC			0x0a4 0x29c 0x580 0x06 0x000
+
+#define MX25_PAD_D7__D7				0x0a8 0x2a0 0x000 0x00 0x000
+#define MX25_PAD_D7__GPIO_4_13			0x0a8 0x2a0 0x000 0x05 0x000
+
+#define MX25_PAD_D6__D6				0x0ac 0x2a4 0x000 0x00 0x000
+#define MX25_PAD_D6__GPIO_4_14			0x0ac 0x2a4 0x000 0x05 0x000
+
+#define MX25_PAD_D5__D5				0x0b0 0x2a8 0x000 0x00 0x000
+#define MX25_PAD_D5__GPIO_4_15			0x0b0 0x2a8 0x000 0x05 0x000
+
+#define MX25_PAD_D4__D4				0x0b4 0x2ac 0x000 0x00 0x000
+#define MX25_PAD_D4__GPIO_4_16			0x0b4 0x2ac 0x000 0x05 0x000
+
+#define MX25_PAD_D3__D3				0x0b8 0x2b0 0x000 0x00 0x000
+#define MX25_PAD_D3__GPIO_4_17			0x0b8 0x2b0 0x000 0x05 0x000
+
+#define MX25_PAD_D2__D2				0x0bc 0x2b4 0x000 0x00 0x000
+#define MX25_PAD_D2__GPIO_4_18			0x0bc 0x2b4 0x000 0x05 0x000
+
+#define MX25_PAD_D1__D1				0x0c0 0x2b8 0x000 0x00 0x000
+#define MX25_PAD_D1__GPIO_4_19			0x0c0 0x2b8 0x000 0x05 0x000
+
+#define MX25_PAD_D0__D0				0x0c4 0x2bc 0x000 0x00 0x000
+#define MX25_PAD_D0__GPIO_4_20			0x0c4 0x2bc 0x000 0x05 0x000
+
+#define MX25_PAD_LD0__LD0			0x0c8 0x2c0 0x000 0x10 0x000
+#define MX25_PAD_LD0__CSI_D0			0x0c8 0x2c0 0x488 0x12 0x000
+#define MX25_PAD_LD0__GPIO_2_15			0x0c8 0x2c0 0x000 0x15 0x000
+
+#define MX25_PAD_LD1__LD1			0x0cc 0x2c4 0x000 0x10 0x000
+#define MX25_PAD_LD1__CSI_D1			0x0cc 0x2c4 0x48c 0x12 0x000
+#define MX25_PAD_LD1__GPIO_2_16			0x0cc 0x2c4 0x000 0x15 0x000
+
+#define MX25_PAD_LD2__LD2			0x0d0 0x2c8 0x000 0x10 0x000
+#define MX25_PAD_LD2__GPIO_2_17			0x0d0 0x2c8 0x000 0x15 0x000
+
+#define MX25_PAD_LD3__LD3			0x0d4 0x2cc 0x000 0x10 0x000
+#define MX25_PAD_LD3__GPIO_2_18			0x0d4 0x2cc 0x000 0x15 0x000
+
+#define MX25_PAD_LD4__LD4			0x0d8 0x2d0 0x000 0x10 0x000
+#define MX25_PAD_LD4__GPIO_2_19			0x0d8 0x2d0 0x000 0x15 0x000
+
+#define MX25_PAD_LD5__LD5			0x0dc 0x2d4 0x000 0x10 0x000
+#define MX25_PAD_LD5__GPIO_1_19			0x0dc 0x2d4 0x000 0x15 0x000
+
+#define MX25_PAD_LD6__LD6			0x0e0 0x2d8 0x000 0x10 0x000
+#define MX25_PAD_LD6__GPIO_1_20			0x0e0 0x2d8 0x000 0x15 0x000
+
+#define MX25_PAD_LD7__LD7			0x0e4 0x2dc 0x000 0x10 0x000
+#define MX25_PAD_LD7__GPIO_1_21			0x0e4 0x2dc 0x000 0x15 0x000
+
+#define MX25_PAD_LD8__LD8			0x0e8 0x2e0 0x000 0x10 0x000
+#define MX25_PAD_LD8__FEC_TX_ERR		0x0e8 0x2e0 0x000 0x15 0x000
+
+#define MX25_PAD_LD9__LD9			0x0ec 0x2e4 0x000 0x10 0x000
+#define MX25_PAD_LD9__FEC_COL			0x0ec 0x2e4 0x504 0x15 0x001
+
+#define MX25_PAD_LD10__LD10			0x0f0 0x2e8 0x000 0x10 0x000
+#define MX25_PAD_LD10__FEC_RX_ER		0x0f0 0x2e8 0x518 0x15 0x001
+
+#define MX25_PAD_LD11__LD11			0x0f4 0x2ec 0x000 0x10 0x000
+#define MX25_PAD_LD11__FEC_RDATA2		0x0f4 0x2ec 0x50c 0x15 0x001
+
+#define MX25_PAD_LD12__LD12			0x0f8 0x2f0 0x000 0x10 0x000
+#define MX25_PAD_LD12__FEC_RDATA3		0x0f8 0x2f0 0x510 0x15 0x001
+
+#define MX25_PAD_LD13__LD13			0x0fc 0x2f4 0x000 0x10 0x000
+#define MX25_PAD_LD13__FEC_TDATA2		0x0fc 0x2f4 0x000 0x15 0x000
+
+#define MX25_PAD_LD14__LD14			0x100 0x2f8 0x000 0x10 0x000
+#define MX25_PAD_LD14__FEC_TDATA3		0x100 0x2f8 0x000 0x15 0x000
+
+#define MX25_PAD_LD15__LD15			0x104 0x2fc 0x000 0x10 0x000
+#define MX25_PAD_LD15__FEC_RX_CLK		0x104 0x2fc 0x514 0x15 0x001
+
+#define MX25_PAD_HSYNC__HSYNC			0x108 0x300 0x000 0x10 0x000
+#define MX25_PAD_HSYNC__GPIO_1_22		0x108 0x300 0x000 0x15 0x000
+
+#define MX25_PAD_VSYNC__VSYNC			0x10c 0x304 0x000 0x10 0x000
+#define MX25_PAD_VSYNC__GPIO_1_23		0x10c 0x304 0x000 0x15 0x000
+
+#define MX25_PAD_LSCLK__LSCLK			0x110 0x308 0x000 0x10 0x000
+#define MX25_PAD_LSCLK__GPIO_1_24		0x110 0x308 0x000 0x15 0x000
+
+#define MX25_PAD_OE_ACD__OE_ACD			0x114 0x30c 0x000 0x10 0x000
+#define MX25_PAD_OE_ACD__GPIO_1_25		0x114 0x30c 0x000 0x15 0x000
+
+#define MX25_PAD_CONTRAST__CONTRAST		0x118 0x310 0x000 0x10 0x000
+#define MX25_PAD_CONTRAST__PWM4_PWMO		0x118 0x310 0x000 0x14 0x000
+#define MX25_PAD_CONTRAST__FEC_CRS		0x118 0x310 0x508 0x15 0x001
+
+#define MX25_PAD_PWM__PWM			0x11c 0x314 0x000 0x10 0x000
+#define MX25_PAD_PWM__GPIO_1_26			0x11c 0x314 0x000 0x15 0x000
+#define MX25_PAD_PWM__USBH2_OC			0x11c 0x314 0x580 0x16 0x001
+
+#define MX25_PAD_CSI_D2__CSI_D2			0x120 0x318 0x000 0x10 0x000
+#define MX25_PAD_CSI_D2__UART5_RXD_MUX		0x120 0x318 0x578 0x11 0x001
+#define MX25_PAD_CSI_D2__GPIO_1_27		0x120 0x318 0x000 0x15 0x000
+#define MX25_PAD_CSI_D2__CSPI3_MOSI		0x120 0x318 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D3__CSI_D3			0x124 0x31c 0x000 0x10 0x000
+#define MX25_PAD_CSI_D3__GPIO_1_28		0x124 0x31c 0x000 0x15 0x000
+#define MX25_PAD_CSI_D3__CSPI3_MISO		0x124 0x31c 0x4b4 0x17 0x001
+
+#define MX25_PAD_CSI_D4__CSI_D4			0x128 0x320 0x000 0x10 0x000
+#define MX25_PAD_CSI_D4__UART5_RTS		0x128 0x320 0x574 0x11 0x001
+#define MX25_PAD_CSI_D4__GPIO_1_29		0x128 0x320 0x000 0x15 0x000
+#define MX25_PAD_CSI_D4__CSPI3_SCLK		0x128 0x320 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D5__CSI_D5			0x12c 0x324 0x000 0x10 0x000
+#define MX25_PAD_CSI_D5__GPIO_1_30		0x12c 0x324 0x000 0x15 0x000
+#define MX25_PAD_CSI_D5__CSPI3_RDY		0x12c 0x324 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D6__CSI_D6			0x130 0x328 0x000 0x10 0x000
+#define MX25_PAD_CSI_D6__GPIO_1_31		0x130 0x328 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D7__CSI_D7			0x134 0x32c 0x000 0x10 0x000
+#define MX25_PAD_CSI_D7__GPIO_1_6		0x134 0x32c 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D8__CSI_D8			0x138 0x330 0x000 0x10 0x000
+#define MX25_PAD_CSI_D8__GPIO_1_7		0x138 0x330 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D9__CSI_D9			0x13c 0x334 0x000 0x10 0x000
+#define MX25_PAD_CSI_D9__GPIO_4_21		0x13c 0x334 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_MCLK__CSI_MCLK		0x140 0x338 0x000 0x10 0x000
+#define MX25_PAD_CSI_MCLK__GPIO_1_8		0x140 0x338 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_VSYNC__CSI_VSYNC		0x144 0x33c 0x000 0x10 0x000
+#define MX25_PAD_CSI_VSYNC__GPIO_1_9		0x144 0x33c 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_HSYNC__CSI_HSYNC		0x148 0x340 0x000 0x10 0x000
+#define MX25_PAD_CSI_HSYNC__GPIO_1_10		0x148 0x340 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK		0x14c 0x344 0x000 0x10 0x000
+#define MX25_PAD_CSI_PIXCLK__GPIO_1_11		0x14c 0x344 0x000 0x15 0x000
+
+#define MX25_PAD_I2C1_CLK__I2C1_CLK		0x150 0x348 0x000 0x10 0x000
+#define MX25_PAD_I2C1_CLK__GPIO_1_12		0x150 0x348 0x000 0x15 0x000
+
+#define MX25_PAD_I2C1_DAT__I2C1_DAT		0x154 0x34c 0x000 0x10 0x000
+#define MX25_PAD_I2C1_DAT__GPIO_1_13		0x154 0x34c 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI		0x158 0x350 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_MOSI__GPIO_1_14		0x158 0x350 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_MISO__CSPI1_MISO		0x15c 0x354 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_MISO__GPIO_1_15		0x15c 0x354 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SS0__CSPI1_SS0		0x160 0x358 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SS0__GPIO_1_16		0x160 0x358 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SS1__CSPI1_SS1		0x164 0x35c 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SS1__GPIO_1_17		0x164 0x35c 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK		0x168 0x360 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SCLK__GPIO_1_18		0x168 0x360 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_RDY__CSPI1_RDY		0x16c 0x364 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_RDY__GPIO_2_22		0x16c 0x364 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_RXD__UART1_RXD		0x170 0x368 0x000 0x10 0x000
+#define MX25_PAD_UART1_RXD__GPIO_4_22		0x170 0x368 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_TXD__UART1_TXD		0x174 0x36c 0x000 0x10 0x000
+#define MX25_PAD_UART1_TXD__GPIO_4_23		0x174 0x36c 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_RTS__UART1_RTS		0x178 0x370 0x000 0x10 0x000
+#define MX25_PAD_UART1_RTS__CSI_D0		0x178 0x370 0x488 0x11 0x001
+#define MX25_PAD_UART1_RTS__GPIO_4_24		0x178 0x370 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_CTS__UART1_CTS		0x17c 0x374 0x000 0x10 0x000
+#define MX25_PAD_UART1_CTS__CSI_D1		0x17c 0x374 0x48c 0x11 0x001
+#define MX25_PAD_UART1_CTS__GPIO_4_25		0x17c 0x374 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_RXD__UART2_RXD		0x180 0x378 0x000 0x10 0x000
+#define MX25_PAD_UART2_RXD__GPIO_4_26		0x180 0x378 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_TXD__UART2_TXD		0x184 0x37c 0x000 0x10 0x000
+#define MX25_PAD_UART2_TXD__GPIO_4_27		0x184 0x37c 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_RTS__UART2_RTS		0x188 0x380 0x000 0x10 0x000
+#define MX25_PAD_UART2_RTS__FEC_COL		0x188 0x380 0x504 0x12 0x002
+#define MX25_PAD_UART2_RTS__GPIO_4_28		0x188 0x380 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_CTS__FEC_RX_ER		0x18c 0x384 0x518 0x12 0x002
+#define MX25_PAD_UART2_CTS__UART2_CTS		0x18c 0x384 0x000 0x10 0x000
+#define MX25_PAD_UART2_CTS__GPIO_4_29		0x18c 0x384 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_CMD__SD1_CMD		0x190 0x388 0x000 0x10 0x000
+#define MX25_PAD_SD1_CMD__FEC_RDATA2		0x190 0x388 0x50c 0x12 0x002
+#define MX25_PAD_SD1_CMD__GPIO_2_23		0x190 0x388 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_CLK__SD1_CLK		0x194 0x38c 0x000 0x10 0x000
+#define MX25_PAD_SD1_CLK__FEC_RDATA3		0x194 0x38c 0x510 0x12 0x002
+#define MX25_PAD_SD1_CLK__GPIO_2_24		0x194 0x38c 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA0__SD1_DATA0		0x198 0x390 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA0__GPIO_2_25		0x198 0x390 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA1__SD1_DATA1		0x19c 0x394 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA1__AUD7_RXD		0x19c 0x394 0x478 0x13 0x000
+#define MX25_PAD_SD1_DATA1__GPIO_2_26		0x19c 0x394 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA2__SD1_DATA2		0x1a0 0x398 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK		0x1a0 0x398 0x514 0x15 0x002
+#define MX25_PAD_SD1_DATA2__GPIO_2_27		0x1a0 0x398 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA3__SD1_DATA3		0x1a4 0x39c 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA3__FEC_CRS		0x1a4 0x39c 0x508 0x10 0x002
+#define MX25_PAD_SD1_DATA3__GPIO_2_28		0x1a4 0x39c 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW0__KPP_ROW0		0x1a8 0x3a0 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW0__GPIO_2_29		0x1a8 0x3a0 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW1__KPP_ROW1		0x1ac 0x3a4 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW1__GPIO_2_30		0x1ac 0x3a4 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW2__KPP_ROW2		0x1b0 0x3a8 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW2__CSI_D0		0x1b0 0x3a8 0x488 0x13 0x002
+#define MX25_PAD_KPP_ROW2__GPIO_2_31		0x1b0 0x3a8 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW3__KPP_ROW3		0x1b4 0x3ac 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW3__CSI_LD1		0x1b4 0x3ac 0x48c 0x13 0x002
+#define MX25_PAD_KPP_ROW3__GPIO_3_0		0x1b4 0x3ac 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL0__KPP_COL0		0x1b8 0x3b0 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL0__UART4_RXD_MUX	0x1b8 0x3b0 0x570 0x11 0x001
+#define MX25_PAD_KPP_COL0__AUD5_TXD		0x1b8 0x3b0 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL0__GPIO_3_1		0x1b8 0x3b0 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL1__KPP_COL1		0x1bc 0x3b4 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL1__UART4_TXD_MUX	0x1bc 0x3b4 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL1__AUD5_RXD		0x1bc 0x3b4 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL1__GPIO_3_2		0x1bc 0x3b4 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL2__KPP_COL2		0x1c0 0x3b8 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL2__UART4_RTS		0x1c0 0x3b8 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL2__AUD5_TXC		0x1c0 0x3b8 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL2__GPIO_3_3		0x1c0 0x3b8 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL3__KPP_COL3		0x1c4 0x3bc 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL3__UART4_CTS		0x1c4 0x3bc 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL3__AUD5_TXFS		0x1c4 0x3bc 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL3__GPIO_3_4		0x1c4 0x3bc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_MDC__FEC_MDC		0x1c8 0x3c0 0x000 0x10 0x000
+#define MX25_PAD_FEC_MDC__AUD4_TXD		0x1c8 0x3c0 0x464 0x12 0x001
+#define MX25_PAD_FEC_MDC__GPIO_3_5		0x1c8 0x3c0 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_MDIO__FEC_MDIO		0x1cc 0x3c4 0x000 0x10 0x000
+#define MX25_PAD_FEC_MDIO__AUD4_RXD		0x1cc 0x3c4 0x460 0x12 0x001
+#define MX25_PAD_FEC_MDIO__GPIO_3_6		0x1cc 0x3c4 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TDATA0__FEC_TDATA0		0x1d0 0x3c8 0x000 0x10 0x000
+#define MX25_PAD_FEC_TDATA0__GPIO_3_7		0x1d0 0x3c8 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TDATA1__FEC_TDATA1		0x1d4 0x3cc 0x000 0x10 0x000
+#define MX25_PAD_FEC_TDATA1__AUD4_TXFS		0x1d4 0x3cc 0x474 0x12 0x001
+#define MX25_PAD_FEC_TDATA1__GPIO_3_8		0x1d4 0x3cc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TX_EN__FEC_TX_EN		0x1d8 0x3d0 0x000 0x10 0x000
+#define MX25_PAD_FEC_TX_EN__GPIO_3_9		0x1d8 0x3d0 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RDATA0__FEC_RDATA0		0x1dc 0x3d4 0x000 0x10 0x000
+#define MX25_PAD_FEC_RDATA0__GPIO_3_10		0x1dc 0x3d4 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RDATA1__FEC_RDATA1		0x1e0 0x3d8 0x000 0x10 0x000
+#define MX25_PAD_FEC_RDATA1__GPIO_3_11		0x1e0 0x3d8 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RX_DV__FEC_RX_DV		0x1e4 0x3dc 0x000 0x10 0x000
+#define MX25_PAD_FEC_RX_DV__CAN2_RX		0x1e4 0x3dc 0x484 0x14 0x000
+#define MX25_PAD_FEC_RX_DV__GPIO_3_12		0x1e4 0x3dc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK		0x1e8 0x3e0 0x000 0x10 0x000
+#define MX25_PAD_FEC_TX_CLK__GPIO_3_13		0x1e8 0x3e0 0x000 0x15 0x000
+
+#define MX25_PAD_RTCK__RTCK			0x1ec 0x3e4 0x000 0x10 0x000
+#define MX25_PAD_RTCK__OWIRE			0x1ec 0x3e4 0x000 0x11 0x000
+#define MX25_PAD_RTCK__GPIO_3_14		0x1ec 0x3e4 0x000 0x15 0x000
+
+#define MX25_PAD_DE_B__DE_B			0x1f0 0x3ec 0x000 0x10 0x000
+#define MX25_PAD_DE_B__GPIO_2_20		0x1f0 0x3ec 0x000 0x15 0x000
+
+#define MX25_PAD_TDO__TDO			0x000 0x3e8 0x000 0x00 0x000
+
+#define MX25_PAD_GPIO_A__GPIO_A			0x1f4 0x3f0 0x000 0x10 0x000
+#define MX25_PAD_GPIO_A__CAN1_TX		0x1f4 0x3f0 0x000 0x16 0x000
+#define MX25_PAD_GPIO_A__USBOTG_PWR		0x1f4 0x3f0 0x000 0x12 0x000
+
+#define MX25_PAD_GPIO_B__GPIO_B			0x1f8 0x3f4 0x000 0x10 0x000
+#define MX25_PAD_GPIO_B__CAN1_RX		0x1f8 0x3f4 0x480 0x16 0x001
+#define MX25_PAD_GPIO_B__USBOTG_OC		0x1f8 0x3f4 0x57c 0x12 0x001
+
+#define MX25_PAD_GPIO_C__GPIO_C			0x1fc 0x3f8 0x000 0x10 0x000
+#define MX25_PAD_GPIO_C__CAN2_TX		0x1fc 0x3f8 0x000 0x16 0x000
+
+#define MX25_PAD_GPIO_D__GPIO_D			0x200 0x3fc 0x000 0x10 0x000
+#define MX25_PAD_GPIO_E__LD16			0x204 0x400 0x000 0x02 0x000
+#define MX25_PAD_GPIO_D__CAN2_RX		0x200 0x3fc 0x484 0x16 0x001
+
+#define MX25_PAD_GPIO_E__GPIO_E			0x204 0x400 0x000 0x10 0x000
+#define MX25_PAD_GPIO_F__LD17			0x208 0x404 0x000 0x02 0x000
+#define MX25_PAD_GPIO_E__AUD7_TXD		0x204 0x400 0x000 0x14 0x000
+
+#define MX25_PAD_GPIO_F__GPIO_F			0x208 0x404 0x000 0x10 0x000
+#define MX25_PAD_GPIO_F__AUD7_TXC		0x208 0x404 0x000 0x14 0x000
+
+#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK		0x20c 0x000 0x000 0x10 0x000
+#define MX25_PAD_EXT_ARMCLK__GPIO_3_15		0x20c 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK	0x210 0x000 0x000 0x10 0x000
+#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16		0x210 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_VSTBY_REQ__VSTBY_REQ		0x214 0x408 0x000 0x10 0x000
+#define MX25_PAD_VSTBY_REQ__AUD7_TXFS		0x214 0x408 0x000 0x14 0x000
+#define MX25_PAD_VSTBY_REQ__GPIO_3_17		0x214 0x408 0x000 0x15 0x000
+#define MX25_PAD_VSTBY_ACK__VSTBY_ACK		0x218 0x40c 0x000 0x10 0x000
+#define MX25_PAD_VSTBY_ACK__GPIO_3_18		0x218 0x40c 0x000 0x15 0x000
+
+#define MX25_PAD_POWER_FAIL__POWER_FAIL		0x21c 0x410 0x000 0x10 0x000
+#define MX25_PAD_POWER_FAIL__AUD7_RXD		0x21c 0x410 0x478 0x14 0x001
+#define MX25_PAD_POWER_FAIL__GPIO_3_19		0x21c 0x410 0x000 0x15 0x000
+
+#define MX25_PAD_CLKO__CLKO			0x220 0x414 0x000 0x10 0x000
+#define MX25_PAD_CLKO__GPIO_2_21		0x220 0x414 0x000 0x15 0x000
+
+#define MX25_PAD_BOOT_MODE0__BOOT_MODE0		0x224 0x000 0x000 0x00 0x000
+#define MX25_PAD_BOOT_MODE0__GPIO_4_30		0x224 0x000 0x000 0x05 0x000
+#define MX25_PAD_BOOT_MODE1__BOOT_MODE1		0x228 0x000 0x000 0x00 0x000
+#define MX25_PAD_BOOT_MODE1__GPIO_4_31		0x228 0x000 0x000 0x05 0x000
+
+#endif /* __DTS_IMX25_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index 737ed5da8f71..32f760e24898 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -10,6 +10,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "imx25-pinfunc.h"
 
 / {
 	aliases {
@@ -173,12 +174,12 @@
 				status = "disabled";
 			};
 
-			iomuxc@43fac000{
+			iomuxc: iomuxc@43fac000 {
 				compatible = "fsl,imx25-iomuxc";
 				reg = <0x43fac000 0x4000>;
 			};
 
-			audmux@43fb0000 {
+			audmux: audmux@43fb0000 {
 				compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
 				reg = <0x43fb0000 0x4000>;
 				status = "disabled";
@@ -236,6 +237,11 @@
 				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
 				reg = <0x50014000 0x4000>;
 				interrupts = <11>;
+				clocks = <&clks 118>;
+				clock-names = "ipg";
+				dmas = <&sdma 24 1 0>,
+				       <&sdma 25 1 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -266,6 +272,11 @@
 				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
 				reg = <0x50034000 0x4000>;
 				interrupts = <12>;
+				clocks = <&clks 117>;
+				clock-names = "ipg";
+				dmas = <&sdma 28 1 0>,
+				       <&sdma 29 1 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -436,13 +447,14 @@
 				#interrupt-cells = <2>;
 			};
 
-			sdma@53fd4000 {
+			sdma: sdma@53fd4000 {
 				compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
 				reg = <0x53fd4000 0x4000>;
 				clocks = <&clks 112>, <&clks 68>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				interrupts = <34>;
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx25.bin";
 			};
 
 			wdog@53fdc000 {
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
index ba4c6df08ece..09f57b39e3ef 100644
--- a/arch/arm/boot/dts/imx27-apf27.dts
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -34,11 +34,49 @@
 	};
 };
 
+&iomuxc {
+	imx27-apf27 {
+		pinctrl_fec1: fec1grp {
+			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
+			>;
+		};
+	};
+};
+
 &uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts
index 47c8c26012e4..2b6d489dae69 100644
--- a/arch/arm/boot/dts/imx27-apf27dev.dts
+++ b/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -22,10 +22,10 @@
 		bits-per-pixel = <16>;  /* non-standard but required */
 		fsl,pcr = <0xfae80083>;	/* non-standard but required */
 		display-timings {
-			timing0: 640x480 {
+			timing0: 800x480 {
 				clock-frequency = <33000033>;
 				hactive = <800>;
-				vactive = <640>;
+				vactive = <480>;
 				hback-porch = <96>;
 				hfront-porch = <96>;
 				vback-porch = <20>;
@@ -38,20 +38,24 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
 
 		user-key {
 			label = "user";
-			gpios = <&gpio6 13 0>;
+			gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>;
 			linux,code = <276>; /* BTN_EXTRA */
 		};
 	};
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
 
 		user {
 			label = "Heartbeat";
-			gpios = <&gpio6 14 0>;
+			gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
@@ -59,25 +63,34 @@
 
 &cspi1 {
 	fsl,spi-num-chipselects = <1>;
-	cs-gpios = <&gpio4 28 1>;
+	cs-gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cspi1 &pinctrl_cspi1_cs>;
 	status = "okay";
 };
 
 &cspi2 {
 	fsl,spi-num-chipselects = <3>;
-	cs-gpios = <&gpio4 21 1>, <&gpio4 27 1>,
-			<&gpio2 17 1>;
+	cs-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>,
+		   <&gpio4 27 GPIO_ACTIVE_LOW>,
+		   <&gpio2 17 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cspi2 &pinctrl_cspi2_cs>;
 	status = "okay";
 };
 
 &fb {
 	display = <&display>;
 	fsl,dmacr = <0x00020010>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_imxfb1>;
 	status = "okay";
 };
 
 &i2c1 {
 	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	rtc@68 {
@@ -87,5 +100,127 @@
 };
 
 &i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 };
+
+&iomuxc {
+	imx27-apf27dev {
+		pinctrl_cspi1: cspi1grp {
+			fsl,pins = <
+				MX27_PAD_CSPI1_MISO__CSPI1_MISO 0x0
+				MX27_PAD_CSPI1_MOSI__CSPI1_MOSI 0x0
+				MX27_PAD_CSPI1_SCLK__CSPI1_SCLK 0x0
+			>;
+		};
+
+		pinctrl_cspi1_cs: cspi1csgrp {
+			fsl,pins = <MX27_PAD_CSPI1_SS0__GPIO4_28 0x0>;
+		};
+
+		pinctrl_cspi2: cspi2grp {
+			fsl,pins = <
+				MX27_PAD_CSPI2_MISO__CSPI2_MISO 0x0
+				MX27_PAD_CSPI2_MOSI__CSPI2_MOSI 0x0
+				MX27_PAD_CSPI2_SCLK__CSPI2_SCLK 0x0
+			>;
+		};
+
+		pinctrl_cspi2_cs: cspi2csgrp {
+			fsl,pins = <
+				MX27_PAD_CSI_D5__GPIO2_17 0x0
+				MX27_PAD_CSPI2_SS0__GPIO4_21 0x0
+				MX27_PAD_CSPI1_SS1__GPIO4_27 0x0
+			>;
+		};
+
+		pinctrl_gpio_leds: gpioledsgrp {
+			fsl,pins = <MX27_PAD_PC_VS1__GPIO6_14 0x0>;
+		};
+
+		pinctrl_gpio_keys: gpiokeysgrp {
+			fsl,pins = <MX27_PAD_PC_VS2__GPIO6_13 0x0>;
+		};
+
+		pinctrl_imxfb1: imxfbgrp {
+			fsl,pins = <
+				MX27_PAD_CLS__CLS 0x0
+				MX27_PAD_CONTRAST__CONTRAST 0x0
+				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_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 {
+			fsl,pins = <
+				MX27_PAD_I2C_DATA__I2C_DATA 0x0
+				MX27_PAD_I2C_CLK__I2C_CLK 0x0
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+			>;
+		};
+
+		pinctrl_pwm: pwmgrp {
+			fsl,pins = <
+				MX27_PAD_PWMO__PWMO 0x0
+			>;
+		};
+
+		pinctrl_sdhc2: sdhc2grp {
+			fsl,pins = <
+				MX27_PAD_SD2_CLK__SD2_CLK 0x0
+				MX27_PAD_SD2_CMD__SD2_CMD 0x0
+				MX27_PAD_SD2_D0__SD2_D0 0x0
+				MX27_PAD_SD2_D1__SD2_D1 0x0
+				MX27_PAD_SD2_D2__SD2_D2 0x0
+				MX27_PAD_SD2_D3__SD2_D3 0x0
+			>;
+		};
+
+		pinctrl_sdhc2_cd: sdhc2cdgrp {
+			fsl,pins = <MX27_PAD_TOUT__GPIO3_14 0x0>;
+		};
+	};
+};
+
+&sdhci2 {
+	bus-width = <4>;
+	cd-gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc2 &pinctrl_sdhc2_cd>;
+	status = "okay";
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm>;
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
index 5a31c776513f..3c3964a99637 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
@@ -9,7 +9,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "imx27-phytec-phycard-s-som.dts"
+#include "imx27-phytec-phycard-s-som.dtsi"
 
 / {
 	model = "Phytec pca100 rapid development kit";
@@ -37,9 +37,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3v3: 3v3 {
+		reg_3v3: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3V3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -54,6 +57,8 @@
 };
 
 &i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	rtc@51 {
@@ -68,26 +73,92 @@
 	};
 };
 
+&iomuxc {
+	imx27-phycard-s-rdk {
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+			>;
+		};
+
+		pinctrl_owire1: owire1grp {
+			fsl,pins = <
+				MX27_PAD_RTCK__OWIRE 0x0
+			>;
+		};
+
+		pinctrl_sdhc2: sdhc2grp {
+			fsl,pins = <
+				MX27_PAD_SD2_CLK__SD2_CLK 0x0
+				MX27_PAD_SD2_CMD__SD2_CMD 0x0
+				MX27_PAD_SD2_D0__SD2_D0 0x0
+				MX27_PAD_SD2_D1__SD2_D1 0x0
+				MX27_PAD_SD2_D2__SD2_D2 0x0
+				MX27_PAD_SD2_D3__SD2_D3 0x0
+				MX27_PAD_SSI3_RXDAT__GPIO3_29 0x0 /* CD */
+			>;
+		};
+
+		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
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX27_PAD_UART2_TXD__UART2_TXD 0x0
+				MX27_PAD_UART2_RXD__UART2_RXD 0x0
+				MX27_PAD_UART2_CTS__UART2_CTS 0x0
+				MX27_PAD_UART2_RTS__UART2_RTS 0x0
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX27_PAD_UART3_TXD__UART3_TXD 0x0
+				MX27_PAD_UART3_RXD__UART3_RXD 0x0
+				MX27_PAD_UART3_CTS__UART3_CTS 0x0
+				MX27_PAD_UART3_RTS__UART3_RTS 0x0
+			>;
+		};
+	};
+};
+
 &owire {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_owire1>;
 	status = "okay";
 };
 
 &sdhci2 {
-	cd-gpios = <&gpio3 29 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc2>;
+	cd-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 };
 
 &uart1 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &uart2 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "okay";
 };
 
 &uart3 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
deleted file mode 100644
index c8d57d1d0743..000000000000
--- a/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Uwe Kleine-König, Steffen Trumtrar
- * and Markus Pargmann, Pengutronix
- *
- * 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 "imx27.dtsi"
-
-/ {
-	model = "Phytec pca100";
-	compatible = "phytec,imx27-pca100", "fsl,imx27";
-
-	memory {
-		reg = <0xa0000000 0x08000000>; /* 128MB */
-	};
-};
-
-&cspi1 {
-	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio4 28 0>,
-		<&gpio4 27 0>;
-	status = "okay";
-};
-
-&fec {
-	status = "okay";
-};
-
-&i2c2 {
-	status = "okay";
-
-	at24@52 {
-		compatible = "at,24c32";
-		pagesize = <32>;
-		reg = <0x52>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi b/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi
new file mode 100644
index 000000000000..1b6248079682
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 Sascha Hauer, Uwe Kleine-König, Steffen Trumtrar
+ * and Markus Pargmann, Pengutronix
+ *
+ * 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 "imx27.dtsi"
+
+/ {
+	model = "Phytec pca100";
+	compatible = "phytec,imx27-pca100", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x08000000>; /* 128MB */
+	};
+};
+
+&cspi1 {
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>,
+		   <&gpio4 27 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	at24@52 {
+		compatible = "at,24c32";
+		pagesize = <32>;
+		reg = <0x52>;
+	};
+};
+
+&iomuxc {
+	imx27-phycard-s-som {
+		pinctrl_fec1: fec1grp {
+			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_i2c2: i2c2grp {
+			fsl,pins = <
+				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+			>;
+		};
+
+		pinctrl_nfc: nfcgrp {
+			fsl,pins = <
+				MX27_PAD_NFRB__NFRB 0x0
+				MX27_PAD_NFCLE__NFCLE 0x0
+				MX27_PAD_NFWP_B__NFWP_B 0x0
+				MX27_PAD_NFCE_B__NFCE_B 0x0
+				MX27_PAD_NFALE__NFALE 0x0
+				MX27_PAD_NFRE_B__NFRE_B 0x0
+				MX27_PAD_NFWE_B__NFWE_B 0x0
+			>;
+		};
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nfc>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
index 0fc6551786c6..df3b2e731835 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -7,7 +7,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "imx27-phytec-phycore-som.dts"
+#include "imx27-phytec-phycore-som.dtsi"
 
 / {
 	model = "Phytec pcm970";
@@ -16,32 +16,200 @@
 
 &cspi1 {
 	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio4 28 0>, <&gpio4 27 0>;
+	cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>,
+		   <&gpio4 27 GPIO_ACTIVE_LOW>;
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	camgpio: pca9536@41 {
+		compatible = "nxp,pca9536";
+		reg = <0x41>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&iomuxc {
+	imx27_phycore_rdk {
+		pinctrl_i2c1: i2c1grp {
+			/* Add pullup to DATA line */
+			fsl,pins = <
+				MX27_PAD_I2C_DATA__I2C_DATA	0x1
+				MX27_PAD_I2C_CLK__I2C_CLK	0x0
+			>;
+		};
+
+		pinctrl_owire1: owire1grp {
+			fsl,pins = <
+				MX27_PAD_RTCK__OWIRE 0x0
+			>;
+		};
+
+		pinctrl_sdhc2: sdhc2grp {
+			fsl,pins = <
+				MX27_PAD_SD2_CLK__SD2_CLK 0x0
+				MX27_PAD_SD2_CMD__SD2_CMD 0x0
+				MX27_PAD_SD2_D0__SD2_D0 0x0
+				MX27_PAD_SD2_D1__SD2_D1 0x0
+				MX27_PAD_SD2_D2__SD2_D2 0x0
+				MX27_PAD_SD2_D3__SD2_D3 0x0
+				MX27_PAD_SSI3_FS__GPIO3_28	0x0 /* WP */
+				MX27_PAD_SSI3_RXDAT__GPIO3_29	0x0 /* CD */
+			>;
+		};
+
+		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
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX27_PAD_UART2_TXD__UART2_TXD 0x0
+				MX27_PAD_UART2_RXD__UART2_RXD 0x0
+				MX27_PAD_UART2_CTS__UART2_CTS 0x0
+				MX27_PAD_UART2_RTS__UART2_RTS 0x0
+			>;
+		};
+
+		pinctrl_usbh2: usbh2grp {
+			fsl,pins = <
+				MX27_PAD_USBH2_CLK__USBH2_CLK 0x0
+				MX27_PAD_USBH2_DIR__USBH2_DIR 0x0
+				MX27_PAD_USBH2_NXT__USBH2_NXT 0x0
+				MX27_PAD_USBH2_STP__USBH2_STP 0x0
+				MX27_PAD_CSPI2_SCLK__USBH2_DATA0 0x0
+				MX27_PAD_CSPI2_MOSI__USBH2_DATA1 0x0
+				MX27_PAD_CSPI2_MISO__USBH2_DATA2 0x0
+				MX27_PAD_CSPI2_SS1__USBH2_DATA3 0x0
+				MX27_PAD_CSPI2_SS2__USBH2_DATA4 0x0
+				MX27_PAD_CSPI1_SS2__USBH2_DATA5 0x0
+				MX27_PAD_CSPI2_SS0__USBH2_DATA6 0x0
+				MX27_PAD_USBH2_DATA7__USBH2_DATA7 0x0
+			>;
+		};
+
+		pinctrl_weim: weimgrp {
+			fsl,pins = <
+				MX27_PAD_CS4_B__CS4_B		0x0 /* CS4 */
+				MX27_PAD_SD1_D1__GPIO5_19	0x0 /* CAN IRQ */
+			>;
+		};
+	};
+};
+
+&owire {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_owire1>;
+	status = "okay";
+};
+
+&pmicleds {
+	ledr1: led@3 {
+		reg = <3>;
+		label = "system:red1:user";
+	};
+
+	ledg1: led@4 {
+		reg = <4>;
+		label = "system:green1:user";
+	};
+
+	ledb1: led@5 {
+		reg = <5>;
+		label = "system:blue1:user";
+	};
+
+	ledr2: led@6 {
+		reg = <6>;
+		label = "system:red2:user";
+	};
+
+	ledg2: led@7 {
+		reg = <7>;
+		label = "system:green2:user";
+	};
+
+	ledb2: led@8 {
+		reg = <8>;
+		label = "system:blue2:user";
+	};
+
+	ledr3: led@9 {
+		reg = <9>;
+		label = "system:red3:nand";
+		linux,default-trigger = "nand-disk";
+	};
+
+	ledg3: led@10 {
+		reg = <10>;
+		label = "system:green3:live";
+		linux,default-trigger = "heartbeat";
+	};
+
+	ledb3: led@11 {
+		reg = <11>;
+		label = "system:blue3:cpu";
+		linux,default-trigger = "cpu0";
+	};
 };
 
 &sdhci2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc2>;
 	bus-width = <4>;
-	cd-gpios = <&gpio3 29 0>;
-	wp-gpios = <&gpio3 28 0>;
+	cd-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+	wp-gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
 	vmmc-supply = <&vmmc1_reg>;
 	status = "okay";
 };
 
 &uart1 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
 };
 
 &uart2 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbh2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh2>;
+	dr_mode = "host";
+	phy_type = "ulpi";
+	vbus-supply = <&reg_5v0>;
+	disable-over-current;
 	status = "okay";
 };
 
+&usbphy2 {
+	vcc-supply = <&reg_5v0>;
+};
+
 &weim {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_weim>;
+
 	can@d4000000 {
 		compatible = "nxp,sja1000";
 		reg = <4 0x00000000 0x00000100>;
 		interrupt-parent = <&gpio5>;
-		interrupts = <19 0x2>;
+		interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
 		nxp,external-clock-frequency = <16000000>;
 		nxp,tx-output-config = <0x16>;
 		nxp,no-comparator-bypass;
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dts b/arch/arm/boot/dts/imx27-phytec-phycore-som.dts
deleted file mode 100644
index 4ec402c38945..000000000000
--- a/arch/arm/boot/dts/imx27-phytec-phycore-som.dts
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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 "imx27.dtsi"
-
-/ {
-	model = "Phytec pcm038";
-	compatible = "phytec,imx27-pcm038", "fsl,imx27";
-
-	memory {
-		reg = <0xa0000000 0x08000000>;
-	};
-};
-
-&audmux {
-	status = "okay";
-
-	/* SSI0 <=> PINS_4 (MC13783 Audio) */
-	ssi0 {
-		fsl,audmux-port = <0>;
-		fsl,port-config = <0xcb205000>;
-	};
-
-	pins4 {
-		fsl,audmux-port = <2>;
-		fsl,port-config = <0x00001000>;
-	};
-};
-
-&cspi1 {
-	fsl,spi-num-chipselects = <1>;
-	cs-gpios = <&gpio4 28 0>;
-	status = "okay";
-
-	pmic: mc13783@0 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mc13783";
-		spi-max-frequency = <20000000>;
-		reg = <0>;
-		interrupt-parent = <&gpio2>;
-		interrupts = <23 0x4>;
-		fsl,mc13xxx-uses-adc;
-		fsl,mc13xxx-uses-rtc;
-
-		regulators {
-			/* SW1A and SW1B joined operation */
-			sw1_reg: sw1a {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <1520000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			/* SW2A and SW2B joined operation */
-			sw2_reg: sw2a {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			sw3_reg: sw3 {
-				regulator-min-microvolt = <5000000>;
-				regulator-max-microvolt = <5000000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			vaudio_reg: vaudio {
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			violo_reg: violo {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			viohi_reg: viohi {
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			vgen_reg: vgen {
-				regulator-min-microvolt = <1500000>;
-				regulator-max-microvolt = <1500000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			vcam_reg: vcam {
-				regulator-min-microvolt = <2800000>;
-				regulator-max-microvolt = <2800000>;
-			};
-
-			vrf1_reg: vrf1 {
-				regulator-min-microvolt = <2775000>;
-				regulator-max-microvolt = <2775000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			vrf2_reg: vrf2 {
-				regulator-min-microvolt = <2775000>;
-				regulator-max-microvolt = <2775000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			vmmc1_reg: vmmc1 {
-				regulator-min-microvolt = <1600000>;
-				regulator-max-microvolt = <3000000>;
-			};
-
-			gpo1_reg: gpo1 { };
-
-			pwgt1spi_reg: pwgt1spi {
-				regulator-always-on;
-			};
-		};
-	};
-};
-
-&fec {
-	phy-reset-gpios = <&gpio3 30 0>;
-	status = "okay";
-};
-
-&i2c2 {
-	clock-frequency = <400000>;
-	status = "okay";
-
-	at24@52 {
-		compatible = "at,24c32";
-		pagesize = <32>;
-		reg = <0x52>;
-	};
-
-	pcf8563@51 {
-		compatible = "nxp,pcf8563";
-		reg = <0x51>;
-	};
-
-	lm75@4a {
-		compatible = "national,lm75";
-		reg = <0x4a>;
-	};
-};
-
-&nfc {
-	nand-bus-width = <8>;
-	nand-ecc-mode = "hw";
-	status = "okay";
-};
-
-&uart1 {
-	status = "okay";
-};
-
-&weim {
-	status = "okay";
-
-	nor: nor@c0000000 {
-		compatible = "cfi-flash";
-		reg = <0 0x00000000 0x02000000>;
-		bank-width = <2>;
-		linux,mtd-name = "physmap-flash.0";
-		fsl,weim-cs-timing = <0x22c2cf00 0x75000d01 0x00000900>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-	};
-
-	sram: sram@c8000000 {
-		compatible = "mtd-ram";
-		reg = <1 0x00000000 0x00800000>;
-		bank-width = <2>;
-		linux,mtd-name = "mtd-ram.0";
-		fsl,weim-cs-timing = <0x0000d843 0x22252521 0x22220a00>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
new file mode 100644
index 000000000000..cefaa6994623
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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 "imx27.dtsi"
+
+/ {
+	model = "Phytec pcm038";
+	compatible = "phytec,imx27-pcm038", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3v3: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+
+		reg_5v0: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "5V0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+	};
+};
+
+&audmux {
+	status = "okay";
+
+	/* SSI0 <=> PINS_4 (MC13783 Audio) */
+	ssi0 {
+		fsl,audmux-port = <0>;
+		fsl,port-config = <0xcb205000>;
+	};
+
+	pins4 {
+		fsl,audmux-port = <2>;
+		fsl,port-config = <0x00001000>;
+	};
+};
+
+&cspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cspi1>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+
+	pmic: mc13783@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mc13783";
+		reg = <0>;
+		spi-cs-high;
+		spi-max-frequency = <20000000>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+		fsl,mc13xxx-uses-adc;
+		fsl,mc13xxx-uses-rtc;
+
+		pmicleds: leds {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			led-control = <0x001 0x000 0x000 0x000 0x000 0x000>;
+		};
+
+		regulators {
+			/* SW1A and SW1B joined operation */
+			sw1_reg: sw1a {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1520000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			/* SW2A and SW2B joined operation */
+			sw2_reg: sw2a {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			sw3_reg: sw3 {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5000000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vaudio_reg: vaudio {
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			violo_reg: violo {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			viohi_reg: viohi {
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vgen_reg: vgen {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcam_reg: vcam {
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			vrf1_reg: vrf1 {
+				regulator-min-microvolt = <2775000>;
+				regulator-max-microvolt = <2775000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vrf2_reg: vrf2 {
+				regulator-min-microvolt = <2775000>;
+				regulator-max-microvolt = <2775000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vmmc1_reg: vmmc1 {
+				regulator-min-microvolt = <1600000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			gpo1_reg: gpo1 { };
+
+			pwgt1spi_reg: pwgt1spi {
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&fec {
+	phy-mode = "mii";
+	phy-reset-gpios = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+	phy-supply = <&reg_3v3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	at24@52 {
+		compatible = "at,24c32";
+		pagesize = <32>;
+		reg = <0x52>;
+	};
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+
+	lm75@4a {
+		compatible = "national,lm75";
+		reg = <0x4a>;
+	};
+};
+
+&iomuxc {
+	imx27_phycore_som {
+		pinctrl_cspi1: cspi1grp {
+			fsl,pins = <
+				MX27_PAD_CSPI1_MISO__CSPI1_MISO 0x0
+				MX27_PAD_CSPI1_MOSI__CSPI1_MOSI 0x0
+				MX27_PAD_CSPI1_SCLK__CSPI1_SCLK 0x0
+				MX27_PAD_CSPI1_SS0__GPIO4_28	0x0 /* SPI1 CS0 */
+				MX27_PAD_USB_PWR__GPIO2_23	0x0 /* PMIC IRQ */
+			>;
+		};
+
+		pinctrl_fec1: fec1grp {
+			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
+				MX27_PAD_SSI3_TXDAT__GPIO3_30	0x0 /* FEC RST */
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+			>;
+		};
+
+		pinctrl_nfc: nfcgrp {
+			fsl,pins = <
+				MX27_PAD_NFRB__NFRB 0x0
+				MX27_PAD_NFCLE__NFCLE 0x0
+				MX27_PAD_NFWP_B__NFWP_B 0x0
+				MX27_PAD_NFCE_B__NFCE_B 0x0
+				MX27_PAD_NFALE__NFALE 0x0
+				MX27_PAD_NFRE_B__NFRE_B 0x0
+				MX27_PAD_NFWE_B__NFWE_B 0x0
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX27_PAD_USBOTG_CLK__USBOTG_CLK 0x0
+				MX27_PAD_USBOTG_DIR__USBOTG_DIR 0x0
+				MX27_PAD_USBOTG_NXT__USBOTG_NXT 0x0
+				MX27_PAD_USBOTG_STP__USBOTG_STP 0x0
+				MX27_PAD_USBOTG_DATA0__USBOTG_DATA0 0x0
+				MX27_PAD_USBOTG_DATA1__USBOTG_DATA1 0x0
+				MX27_PAD_USBOTG_DATA2__USBOTG_DATA2 0x0
+				MX27_PAD_USBOTG_DATA3__USBOTG_DATA3 0x0
+				MX27_PAD_USBOTG_DATA4__USBOTG_DATA4 0x0
+				MX27_PAD_USBOTG_DATA5__USBOTG_DATA5 0x0
+				MX27_PAD_USBOTG_DATA6__USBOTG_DATA6 0x0
+				MX27_PAD_USBOTG_DATA7__USBOTG_DATA7 0x0
+			>;
+		};
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nfc>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	phy_type = "ulpi";
+	vbus-supply = <&sw3_reg>;
+	status = "okay";
+};
+
+&usbphy0 {
+	vcc-supply = <&sw3_reg>;
+};
+
+&weim {
+	status = "okay";
+
+	nor: nor@c0000000 {
+		compatible = "cfi-flash";
+		reg = <0 0x00000000 0x02000000>;
+		bank-width = <2>;
+		linux,mtd-name = "physmap-flash.0";
+		fsl,weim-cs-timing = <0x22c2cf00 0x75000d01 0x00000900>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	sram: sram@c8000000 {
+		compatible = "mtd-ram";
+		reg = <1 0x00000000 0x00800000>;
+		bank-width = <2>;
+		linux,mtd-name = "mtd-ram.0";
+		fsl,weim-cs-timing = <0x0000d843 0x22252521 0x22220a00>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-pinfunc.h b/arch/arm/boot/dts/imx27-pinfunc.h
new file mode 100644
index 000000000000..f5387b4de577
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-pinfunc.h
@@ -0,0 +1,526 @@
+/*
+ * Copyright 2013 Markus Pargmann <mpa@pengutronix.de>, Pengutronix
+ *
+ * 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
+ */
+
+#ifndef __DTS_IMX27_PINFUNC_H
+#define __DTS_IMX27_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <pin mux_id>
+ * mux_id consists of
+ * function + (direction << 2) + (gpio_oconf << 4) + (gpio_iconfa << 8) + (gpio_iconfb << 10)
+ *
+ * function:      0 - Primary function
+ *                1 - Alternate function
+ *                2 - GPIO
+ * direction:     0 - Input
+ *                1 - Output
+ * gpio_oconf:    0 - A_IN
+ *                1 - B_IN
+ *                2 - C_IN
+ *                3 - Data Register
+ * gpio_iconfa/b: 0 - GPIO_IN
+ *                1 - Interrupt Status Register
+ *                2 - 0
+ *                3 - 1
+ *
+ * 'pin' is an integer between 0 and 0xbf. imx27 has 6 ports with 32 configurable
+ * configurable pins each. 'pin' is PORT * 32 + PORT_PIN, PORT_PIN is the pin
+ * number on the specific port (between 0 and 31).
+ */
+
+#define MX27_PAD_USBH2_CLK__USBH2_CLK                      0x00 0x000
+#define MX27_PAD_USBH2_CLK__GPIO1_0                        0x00 0x032
+#define MX27_PAD_USBH2_DIR__USBH2_DIR                      0x01 0x000
+#define MX27_PAD_USBH2_DIR__GPIO1_1                        0x01 0x032
+#define MX27_PAD_USBH2_DATA7__USBH2_DATA7                  0x02 0x004
+#define MX27_PAD_USBH2_DATA7__GPIO1_2                      0x02 0x032
+#define MX27_PAD_USBH2_NXT__USBH2_NXT                      0x03 0x000
+#define MX27_PAD_USBH2_NXT__GPIO1_3                        0x03 0x032
+#define MX27_PAD_USBH2_STP__USBH2_STP                      0x04 0x004
+#define MX27_PAD_USBH2_STP__GPIO1_4                        0x04 0x032
+#define MX27_PAD_LSCLK__LSCLK                              0x05 0x004
+#define MX27_PAD_LSCLK__GPIO1_5                            0x05 0x032
+#define MX27_PAD_LD0__LD0                                  0x06 0x004
+#define MX27_PAD_LD0__GPIO1_6                              0x06 0x032
+#define MX27_PAD_LD1__LD1                                  0x07 0x004
+#define MX27_PAD_LD1__GPIO1_7                              0x07 0x032
+#define MX27_PAD_LD2__LD2                                  0x08 0x004
+#define MX27_PAD_LD2__GPIO1_8                              0x08 0x032
+#define MX27_PAD_LD3__LD3                                  0x09 0x004
+#define MX27_PAD_LD3__GPIO1_9                              0x09 0x032
+#define MX27_PAD_LD4__LD4                                  0x0a 0x004
+#define MX27_PAD_LD4__GPIO1_10                             0x0a 0x032
+#define MX27_PAD_LD5__LD5                                  0x0b 0x004
+#define MX27_PAD_LD5__GPIO1_11                             0x0b 0x032
+#define MX27_PAD_LD6__LD6                                  0x0c 0x004
+#define MX27_PAD_LD6__GPIO1_12                             0x0c 0x032
+#define MX27_PAD_LD7__LD7                                  0x0d 0x004
+#define MX27_PAD_LD7__GPIO1_13                             0x0d 0x032
+#define MX27_PAD_LD8__LD8                                  0x0e 0x004
+#define MX27_PAD_LD8__GPIO1_14                             0x0e 0x032
+#define MX27_PAD_LD9__LD9                                  0x0f 0x004
+#define MX27_PAD_LD9__GPIO1_15                             0x0f 0x032
+#define MX27_PAD_LD10__LD10                                0x10 0x004
+#define MX27_PAD_LD10__GPIO1_16                            0x10 0x032
+#define MX27_PAD_LD11__LD11                                0x11 0x004
+#define MX27_PAD_LD11__GPIO1_17                            0x11 0x032
+#define MX27_PAD_LD12__LD12                                0x12 0x004
+#define MX27_PAD_LD12__GPIO1_18                            0x12 0x032
+#define MX27_PAD_LD13__LD13                                0x13 0x004
+#define MX27_PAD_LD13__GPIO1_19                            0x13 0x032
+#define MX27_PAD_LD14__LD14                                0x14 0x004
+#define MX27_PAD_LD14__GPIO1_20                            0x14 0x032
+#define MX27_PAD_LD15__LD15                                0x15 0x004
+#define MX27_PAD_LD15__GPIO1_21                            0x15 0x032
+#define MX27_PAD_LD16__LD16                                0x16 0x004
+#define MX27_PAD_LD16__GPIO1_22                            0x16 0x032
+#define MX27_PAD_LD17__LD17                                0x17 0x004
+#define MX27_PAD_LD17__GPIO1_23                            0x17 0x032
+#define MX27_PAD_REV__REV                                  0x18 0x004
+#define MX27_PAD_REV__GPIO1_24                             0x18 0x032
+#define MX27_PAD_CLS__CLS                                  0x19 0x004
+#define MX27_PAD_CLS__GPIO1_25                             0x19 0x032
+#define MX27_PAD_PS__PS                                    0x1a 0x004
+#define MX27_PAD_PS__GPIO1_26                              0x1a 0x032
+#define MX27_PAD_SPL_SPR__SPL_SPR                          0x1b 0x004
+#define MX27_PAD_SPL_SPR__GPIO1_27                         0x1b 0x032
+#define MX27_PAD_HSYNC__HSYNC                              0x1c 0x004
+#define MX27_PAD_HSYNC__GPIO1_28                           0x1c 0x032
+#define MX27_PAD_VSYNC__VSYNC                              0x1d 0x004
+#define MX27_PAD_VSYNC__GPIO1_29                           0x1d 0x032
+#define MX27_PAD_CONTRAST__CONTRAST                        0x1e 0x004
+#define MX27_PAD_CONTRAST__GPIO1_30                        0x1e 0x032
+#define MX27_PAD_OE_ACD__OE_ACD                            0x1f 0x004
+#define MX27_PAD_OE_ACD__GPIO1_31                          0x1f 0x032
+#define MX27_PAD_UNUSED0__UNUSED0                          0x20 0x004
+#define MX27_PAD_UNUSED0__GPIO2_0                          0x20 0x032
+#define MX27_PAD_UNUSED1__UNUSED1                          0x21 0x004
+#define MX27_PAD_UNUSED1__GPIO2_1                          0x21 0x032
+#define MX27_PAD_UNUSED2__UNUSED2                          0x22 0x004
+#define MX27_PAD_UNUSED2__GPIO2_2                          0x22 0x032
+#define MX27_PAD_UNUSED3__UNUSED3                          0x23 0x004
+#define MX27_PAD_UNUSED3__GPIO2_3                          0x23 0x032
+#define MX27_PAD_SD2_D0__SD2_D0                            0x24 0x004
+#define MX27_PAD_SD2_D0__MSHC_DATA0                        0x24 0x005
+#define MX27_PAD_SD2_D0__GPIO2_4                           0x24 0x032
+#define MX27_PAD_SD2_D1__SD2_D1                            0x25 0x004
+#define MX27_PAD_SD2_D1__MSHC_DATA1                        0x25 0x005
+#define MX27_PAD_SD2_D1__GPIO2_5                           0x25 0x032
+#define MX27_PAD_SD2_D2__SD2_D2                            0x26 0x004
+#define MX27_PAD_SD2_D2__MSHC_DATA2                        0x26 0x005
+#define MX27_PAD_SD2_D2__GPIO2_6                           0x26 0x032
+#define MX27_PAD_SD2_D3__SD2_D3                            0x27 0x004
+#define MX27_PAD_SD2_D3__MSHC_DATA3                        0x27 0x005
+#define MX27_PAD_SD2_D3__GPIO2_7                           0x27 0x032
+#define MX27_PAD_SD2_CMD__SD2_CMD                          0x28 0x004
+#define MX27_PAD_SD2_CMD__MSHC_BS                          0x28 0x005
+#define MX27_PAD_SD2_CMD__GPIO2_8                          0x28 0x032
+#define MX27_PAD_SD2_CLK__SD2_CLK                          0x29 0x004
+#define MX27_PAD_SD2_CLK__MSHC_SCLK                        0x29 0x005
+#define MX27_PAD_SD2_CLK__GPIO2_9                          0x29 0x032
+#define MX27_PAD_CSI_D0__CSI_D0                            0x2a 0x000
+#define MX27_PAD_CSI_D0__UART6_TXD                         0x2a 0x005
+#define MX27_PAD_CSI_D0__GPIO2_10                          0x2a 0x032
+#define MX27_PAD_CSI_D1__CSI_D1                            0x2b 0x000
+#define MX27_PAD_CSI_D1__UART6_RXD                         0x2b 0x001
+#define MX27_PAD_CSI_D1__GPIO2_11                          0x2b 0x032
+#define MX27_PAD_CSI_D2__CSI_D2                            0x2c 0x000
+#define MX27_PAD_CSI_D2__UART6_CTS                         0x2c 0x005
+#define MX27_PAD_CSI_D2__GPIO2_12                          0x2c 0x032
+#define MX27_PAD_CSI_D3__CSI_D3                            0x2d 0x000
+#define MX27_PAD_CSI_D3__UART6_RTS                         0x2d 0x001
+#define MX27_PAD_CSI_D3__GPIO2_13                          0x2d 0x032
+#define MX27_PAD_CSI_D4__CSI_D4                            0x2e 0x000
+#define MX27_PAD_CSI_D4__GPIO2_14                          0x2e 0x032
+#define MX27_PAD_CSI_MCLK__CSI_MCLK                        0x2f 0x004
+#define MX27_PAD_CSI_MCLK__GPIO2_15                        0x2f 0x032
+#define MX27_PAD_CSI_PIXCLK__CSI_PIXCLK                    0x30 0x000
+#define MX27_PAD_CSI_PIXCLK__GPIO2_16                      0x30 0x032
+#define MX27_PAD_CSI_D5__CSI_D5                            0x31 0x000
+#define MX27_PAD_CSI_D5__GPIO2_17                          0x31 0x032
+#define MX27_PAD_CSI_D6__CSI_D6                            0x32 0x000
+#define MX27_PAD_CSI_D6__UART5_TXD                         0x32 0x005
+#define MX27_PAD_CSI_D6__GPIO2_18                          0x32 0x032
+#define MX27_PAD_CSI_D7__CSI_D7                            0x33 0x000
+#define MX27_PAD_CSI_D7__UART5_RXD                         0x33 0x001
+#define MX27_PAD_CSI_D7__GPIO2_19                          0x33 0x032
+#define MX27_PAD_CSI_VSYNC__CSI_VSYNC                      0x34 0x000
+#define MX27_PAD_CSI_VSYNC__UART5_CTS                      0x34 0x005
+#define MX27_PAD_CSI_VSYNC__GPIO2_20                       0x34 0x032
+#define MX27_PAD_CSI_HSYNC__CSI_HSYNC                      0x35 0x000
+#define MX27_PAD_CSI_HSYNC__UART5_RTS                      0x35 0x001
+#define MX27_PAD_CSI_HSYNC__GPIO2_21                       0x35 0x032
+#define MX27_PAD_USBH1_SUSP__USBH1_SUSP                    0x36 0x004
+#define MX27_PAD_USBH1_SUSP__GPIO2_22                      0x36 0x032
+#define MX27_PAD_USB_PWR__USB_PWR                          0x37 0x004
+#define MX27_PAD_USB_PWR__GPIO2_23                         0x37 0x032
+#define MX27_PAD_USB_OC_B__USB_OC_B                        0x38 0x000
+#define MX27_PAD_USB_OC_B__GPIO2_24                        0x38 0x032
+#define MX27_PAD_USBH1_RCV__USBH1_RCV                      0x39 0x004
+#define MX27_PAD_USBH1_RCV__GPIO2_25                       0x39 0x032
+#define MX27_PAD_USBH1_FS__USBH1_FS                        0x3a 0x004
+#define MX27_PAD_USBH1_FS__UART4_RTS                       0x3a 0x001
+#define MX27_PAD_USBH1_FS__GPIO2_26                        0x3a 0x032
+#define MX27_PAD_USBH1_OE_B__USBH1_OE_B                    0x3b 0x004
+#define MX27_PAD_USBH1_OE_B__GPIO2_27                      0x3b 0x032
+#define MX27_PAD_USBH1_TXDM__USBH1_TXDM                    0x3c 0x004
+#define MX27_PAD_USBH1_TXDM__UART4_TXD                     0x3c 0x005
+#define MX27_PAD_USBH1_TXDM__GPIO2_28                      0x3c 0x032
+#define MX27_PAD_USBH1_TXDP__USBH1_TXDP                    0x3d 0x004
+#define MX27_PAD_USBH1_TXDP__UART4_CTS                     0x3d 0x005
+#define MX27_PAD_USBH1_TXDP__GPIO2_29                      0x3d 0x032
+#define MX27_PAD_USBH1_RXDM__USBH1_RXDM                    0x3e 0x004
+#define MX27_PAD_USBH1_RXDM__GPIO2_30                      0x3e 0x032
+#define MX27_PAD_USBH1_RXDP__USBH1_RXDP                    0x3f 0x004
+#define MX27_PAD_USBH1_RXDP__UART4_RXD                     0x3f 0x001
+#define MX27_PAD_USBH1_RXDP__GPIO2_31                      0x3f 0x032
+#define MX27_PAD_UNUSED4__UNUSED4                          0x40 0x004
+#define MX27_PAD_UNUSED4__GPIO3_0                          0x40 0x032
+#define MX27_PAD_UNUSED5__UNUSED5                          0x41 0x004
+#define MX27_PAD_UNUSED5__GPIO3_1                          0x41 0x032
+#define MX27_PAD_UNUSED6__UNUSED6                          0x42 0x004
+#define MX27_PAD_UNUSED6__GPIO3_2                          0x42 0x032
+#define MX27_PAD_UNUSED7__UNUSED7                          0x43 0x004
+#define MX27_PAD_UNUSED7__GPIO3_3                          0x43 0x032
+#define MX27_PAD_UNUSED8__UNUSED8                          0x44 0x004
+#define MX27_PAD_UNUSED8__GPIO3_4                          0x44 0x032
+#define MX27_PAD_I2C2_SDA__I2C2_SDA                        0x45 0x004
+#define MX27_PAD_I2C2_SDA__GPIO3_5                         0x45 0x032
+#define MX27_PAD_I2C2_SCL__I2C2_SCL                        0x46 0x004
+#define MX27_PAD_I2C2_SCL__GPIO3_6                         0x46 0x032
+#define MX27_PAD_USBOTG_DATA5__USBOTG_DATA5                0x47 0x004
+#define MX27_PAD_USBOTG_DATA5__GPIO3_7                     0x47 0x032
+#define MX27_PAD_USBOTG_DATA6__USBOTG_DATA6                0x48 0x004
+#define MX27_PAD_USBOTG_DATA6__GPIO3_8                     0x48 0x032
+#define MX27_PAD_USBOTG_DATA0__USBOTG_DATA0                0x49 0x004
+#define MX27_PAD_USBOTG_DATA0__GPIO3_9                     0x49 0x032
+#define MX27_PAD_USBOTG_DATA2__USBOTG_DATA2                0x4a 0x004
+#define MX27_PAD_USBOTG_DATA2__GPIO3_10                    0x4a 0x032
+#define MX27_PAD_USBOTG_DATA1__USBOTG_DATA1                0x4b 0x004
+#define MX27_PAD_USBOTG_DATA1__GPIO3_11                    0x4b 0x032
+#define MX27_PAD_USBOTG_DATA4__USBOTG_DATA4                0x4c 0x004
+#define MX27_PAD_USBOTG_DATA4__GPIO3_12                    0x4c 0x032
+#define MX27_PAD_USBOTG_DATA3__USBOTG_DATA3                0x4d 0x004
+#define MX27_PAD_USBOTG_DATA3__GPIO3_13                    0x4d 0x032
+#define MX27_PAD_TOUT__TOUT                                0x4e 0x004
+#define MX27_PAD_TOUT__GPIO3_14                            0x4e 0x032
+#define MX27_PAD_TIN__TIN                                  0x4f 0x000
+#define MX27_PAD_TIN__GPIO3_15                             0x4f 0x032
+#define MX27_PAD_SSI4_FS__SSI4_FS                          0x50 0x004
+#define MX27_PAD_SSI4_FS__GPIO3_16                         0x50 0x032
+#define MX27_PAD_SSI4_RXDAT__SSI4_RXDAT                    0x51 0x004
+#define MX27_PAD_SSI4_RXDAT__GPIO3_17                      0x51 0x032
+#define MX27_PAD_SSI4_TXDAT__SSI4_TXDAT                    0x52 0x004
+#define MX27_PAD_SSI4_TXDAT__GPIO3_18                      0x52 0x032
+#define MX27_PAD_SSI4_CLK__SSI4_CLK                        0x53 0x004
+#define MX27_PAD_SSI4_CLK__GPIO3_19                        0x53 0x032
+#define MX27_PAD_SSI1_FS__SSI1_FS                          0x54 0x004
+#define MX27_PAD_SSI1_FS__GPIO3_20                         0x54 0x032
+#define MX27_PAD_SSI1_RXDAT__SSI1_RXDAT                    0x55 0x004
+#define MX27_PAD_SSI1_RXDAT__GPIO3_21                      0x55 0x032
+#define MX27_PAD_SSI1_TXDAT__SSI1_TXDAT                    0x56 0x004
+#define MX27_PAD_SSI1_TXDAT__GPIO3_22                      0x56 0x032
+#define MX27_PAD_SSI1_CLK__SSI1_CLK                        0x57 0x004
+#define MX27_PAD_SSI1_CLK__GPIO3_23                        0x57 0x032
+#define MX27_PAD_SSI2_FS__SSI2_FS                          0x58 0x004
+#define MX27_PAD_SSI2_FS__GPT5_TOUT                        0x58 0x005
+#define MX27_PAD_SSI2_FS__GPIO3_24                         0x58 0x032
+#define MX27_PAD_SSI2_RXDAT__SSI2_RXDAT                    0x59 0x004
+#define MX27_PAD_SSI2_RXDAT__GPTS_TIN                      0x59 0x001
+#define MX27_PAD_SSI2_RXDAT__GPIO3_25                      0x59 0x032
+#define MX27_PAD_SSI2_TXDAT__SSI2_TXDAT                    0x5a 0x004
+#define MX27_PAD_SSI2_TXDAT__GPT4_TOUT                     0x5a 0x005
+#define MX27_PAD_SSI2_TXDAT__GPIO3_26                      0x5a 0x032
+#define MX27_PAD_SSI2_CLK__SSI2_CLK                        0x5b 0x004
+#define MX27_PAD_SSI2_CLK__GPT4_TIN                        0x5b 0x001
+#define MX27_PAD_SSI2_CLK__GPIO3_27                        0x5b 0x032
+#define MX27_PAD_SSI3_FS__SSI3_FS                          0x5c 0x004
+#define MX27_PAD_SSI3_FS__SLCDC2_D0                        0x5c 0x001
+#define MX27_PAD_SSI3_FS__GPIO3_28                         0x5c 0x032
+#define MX27_PAD_SSI3_RXDAT__SSI3_RXDAT                    0x5d 0x004
+#define MX27_PAD_SSI3_RXDAT__SLCDC2_RS                     0x5d 0x001
+#define MX27_PAD_SSI3_RXDAT__GPIO3_29                      0x5d 0x032
+#define MX27_PAD_SSI3_TXDAT__SSI3_TXDAT                    0x5e 0x004
+#define MX27_PAD_SSI3_TXDAT__SLCDC2_CS                     0x5e 0x001
+#define MX27_PAD_SSI3_TXDAT__GPIO3_30                      0x5e 0x032
+#define MX27_PAD_SSI3_CLK__SSI3_CLK                        0x5f 0x004
+#define MX27_PAD_SSI3_CLK__SLCDC2_CLK                      0x5f 0x001
+#define MX27_PAD_SSI3_CLK__GPIO3_31                        0x5f 0x032
+#define MX27_PAD_SD3_CMD__SD3_CMD                          0x60 0x004
+#define MX27_PAD_SD3_CMD__FEC_TXD0                         0x60 0x006
+#define MX27_PAD_SD3_CMD__GPIO4_0                          0x60 0x032
+#define MX27_PAD_SD3_CLK__SD3_CLK                          0x61 0x004
+#define MX27_PAD_SD3_CLK__ETMTRACEPKT15                    0x61 0x005
+#define MX27_PAD_SD3_CLK__FEC_TXD1                         0x61 0x006
+#define MX27_PAD_SD3_CLK__GPIO4_1                          0x61 0x032
+#define MX27_PAD_ATA_DATA0__ATA_DATA0                      0x62 0x004
+#define MX27_PAD_ATA_DATA0__SD3_D0                         0x62 0x005
+#define MX27_PAD_ATA_DATA0__FEC_TXD2                       0x62 0x006
+#define MX27_PAD_ATA_DATA0__GPIO4_2                        0x62 0x032
+#define MX27_PAD_ATA_DATA1__ATA_DATA1                      0x63 0x004
+#define MX27_PAD_ATA_DATA1__SD3_D1                         0x63 0x005
+#define MX27_PAD_ATA_DATA1__FEC_TXD3                       0x63 0x006
+#define MX27_PAD_ATA_DATA1__GPIO4_3                        0x63 0x032
+#define MX27_PAD_ATA_DATA2__ATA_DATA2                      0x64 0x004
+#define MX27_PAD_ATA_DATA2__SD3_D2                         0x64 0x005
+#define MX27_PAD_ATA_DATA2__FEC_RX_ER                      0x64 0x002
+#define MX27_PAD_ATA_DATA2__GPIO4_4                        0x64 0x032
+#define MX27_PAD_ATA_DATA3__ATA_DATA3                      0x65 0x004
+#define MX27_PAD_ATA_DATA3__SD3_D3                         0x65 0x005
+#define MX27_PAD_ATA_DATA3__FEC_RXD1                       0x65 0x002
+#define MX27_PAD_ATA_DATA3__GPIO4_5                        0x65 0x032
+#define MX27_PAD_ATA_DATA4__ATA_DATA4                      0x66 0x004
+#define MX27_PAD_ATA_DATA4__ETMTRACEPKT14                  0x66 0x005
+#define MX27_PAD_ATA_DATA4__FEC_RXD2                       0x66 0x002
+#define MX27_PAD_ATA_DATA4__GPIO4_6                        0x66 0x032
+#define MX27_PAD_ATA_DATA5__ATA_DATA5                      0x67 0x004
+#define MX27_PAD_ATA_DATA5__ETMTRACEPKT13                  0x67 0x005
+#define MX27_PAD_ATA_DATA5__FEC_RXD3                       0x67 0x002
+#define MX27_PAD_ATA_DATA5__GPIO4_7                        0x67 0x032
+#define MX27_PAD_ATA_DATA6__ATA_DATA6                      0x68 0x004
+#define MX27_PAD_ATA_DATA6__FEC_MDIO                       0x68 0x005
+#define MX27_PAD_ATA_DATA6__GPIO4_8                        0x68 0x032
+#define MX27_PAD_ATA_DATA7__ATA_DATA7                      0x69 0x004
+#define MX27_PAD_ATA_DATA7__ETMTRACEPKT12                  0x69 0x005
+#define MX27_PAD_ATA_DATA7__FEC_MDC                        0x69 0x006
+#define MX27_PAD_ATA_DATA7__GPIO4_9                        0x69 0x032
+#define MX27_PAD_ATA_DATA8__ATA_DATA8                      0x6a 0x004
+#define MX27_PAD_ATA_DATA8__ETMTRACEPKT11                  0x6a 0x005
+#define MX27_PAD_ATA_DATA8__FEC_CRS                        0x6a 0x002
+#define MX27_PAD_ATA_DATA8__GPIO4_10                       0x6a 0x032
+#define MX27_PAD_ATA_DATA9__ATA_DATA9                      0x6b 0x004
+#define MX27_PAD_ATA_DATA9__ETMTRACEPKT10                  0x6b 0x005
+#define MX27_PAD_ATA_DATA9__FEC_TX_CLK                     0x6b 0x002
+#define MX27_PAD_ATA_DATA9__GPIO4_11                       0x6b 0x032
+#define MX27_PAD_ATA_DATA10__ATA_DATA10                    0x6c 0x004
+#define MX27_PAD_ATA_DATA10__ETMTRACEPKT9                  0x6c 0x005
+#define MX27_PAD_ATA_DATA10__FEC_RXD0                      0x6c 0x002
+#define MX27_PAD_ATA_DATA10__GPIO4_12                      0x6c 0x032
+#define MX27_PAD_ATA_DATA11__ATA_DATA11                    0x6d 0x004
+#define MX27_PAD_ATA_DATA11__ETMTRACEPKT8                  0x6d 0x005
+#define MX27_PAD_ATA_DATA11__FEC_RX_DV                     0x6d 0x002
+#define MX27_PAD_ATA_DATA11__GPIO4_13                      0x6d 0x032
+#define MX27_PAD_ATA_DATA12__ATA_DATA12                    0x6e 0x004
+#define MX27_PAD_ATA_DATA12__ETMTRACEPKT7                  0x6e 0x005
+#define MX27_PAD_ATA_DATA12__FEC_RX_CLK                    0x6e 0x002
+#define MX27_PAD_ATA_DATA12__GPIO4_14                      0x6e 0x032
+#define MX27_PAD_ATA_DATA13__ATA_DATA13                    0x6f 0x004
+#define MX27_PAD_ATA_DATA13__ETMTRACEPKT6                  0x6f 0x005
+#define MX27_PAD_ATA_DATA13__FEC_COL                       0x6f 0x002
+#define MX27_PAD_ATA_DATA13__GPIO4_15                      0x6f 0x032
+#define MX27_PAD_ATA_DATA14__ATA_DATA14                    0x70 0x004
+#define MX27_PAD_ATA_DATA14__ETMTRACEPKT5                  0x70 0x005
+#define MX27_PAD_ATA_DATA14__FEC_TX_ER                     0x70 0x006
+#define MX27_PAD_ATA_DATA14__GPIO4_16                      0x70 0x032
+#define MX27_PAD_I2C_DATA__I2C_DATA                        0x71 0x004
+#define MX27_PAD_I2C_DATA__GPIO4_17                        0x71 0x032
+#define MX27_PAD_I2C_CLK__I2C_CLK                          0x72 0x004
+#define MX27_PAD_I2C_CLK__GPIO4_18                         0x72 0x032
+#define MX27_PAD_CSPI2_SS2__CSPI2_SS2                      0x73 0x004
+#define MX27_PAD_CSPI2_SS2__USBH2_DATA4                    0x73 0x005
+#define MX27_PAD_CSPI2_SS2__GPIO4_19                       0x73 0x032
+#define MX27_PAD_CSPI2_SS1__CSPI2_SS1                      0x74 0x004
+#define MX27_PAD_CSPI2_SS1__USBH2_DATA3                    0x74 0x005
+#define MX27_PAD_CSPI2_SS1__GPIO4_20                       0x74 0x032
+#define MX27_PAD_CSPI2_SS0__CSPI2_SS0                      0x75 0x004
+#define MX27_PAD_CSPI2_SS0__USBH2_DATA6                    0x75 0x005
+#define MX27_PAD_CSPI2_SS0__GPIO4_21                       0x75 0x032
+#define MX27_PAD_CSPI2_SCLK__CSPI2_SCLK                    0x76 0x004
+#define MX27_PAD_CSPI2_SCLK__USBH2_DATA0                   0x76 0x005
+#define MX27_PAD_CSPI2_SCLK__GPIO4_22                      0x76 0x032
+#define MX27_PAD_CSPI2_MISO__CSPI2_MISO                    0x77 0x004
+#define MX27_PAD_CSPI2_MISO__USBH2_DATA2                   0x77 0x005
+#define MX27_PAD_CSPI2_MISO__GPIO4_23                      0x77 0x032
+#define MX27_PAD_CSPI2_MOSI__CSPI2_MOSI                    0x78 0x004
+#define MX27_PAD_CSPI2_MOSI__USBH2_DATA1                   0x78 0x005
+#define MX27_PAD_CSPI2_MOSI__GPIO4_24                      0x78 0x032
+#define MX27_PAD_CSPI1_RDY__CSPI1_RDY                      0x79 0x000
+#define MX27_PAD_CSPI1_RDY__GPIO4_25                       0x79 0x032
+#define MX27_PAD_CSPI1_SS2__CSPI1_SS2                      0x7a 0x004
+#define MX27_PAD_CSPI1_SS2__USBH2_DATA5                    0x7a 0x005
+#define MX27_PAD_CSPI1_SS2__GPIO4_26                       0x7a 0x032
+#define MX27_PAD_CSPI1_SS1__CSPI1_SS1                      0x7b 0x004
+#define MX27_PAD_CSPI1_SS1__GPIO4_27                       0x7b 0x032
+#define MX27_PAD_CSPI1_SS0__CSPI1_SS0                      0x7c 0x004
+#define MX27_PAD_CSPI1_SS0__GPIO4_28                       0x7c 0x032
+#define MX27_PAD_CSPI1_SCLK__CSPI1_SCLK                    0x7d 0x004
+#define MX27_PAD_CSPI1_SCLK__GPIO4_29                      0x7d 0x032
+#define MX27_PAD_CSPI1_MISO__CSPI1_MISO                    0x7e 0x004
+#define MX27_PAD_CSPI1_MISO__GPIO4_30                      0x7e 0x032
+#define MX27_PAD_CSPI1_MOSI__CSPI1_MOSI                    0x7f 0x004
+#define MX27_PAD_CSPI1_MOSI__GPIO4_31                      0x7f 0x032
+#define MX27_PAD_USBOTG_NXT__USBOTG_NXT                    0x80 0x000
+#define MX27_PAD_USBOTG_NXT__KP_COL6A                      0x80 0x005
+#define MX27_PAD_USBOTG_NXT__GPIO5_0                       0x80 0x032
+#define MX27_PAD_USBOTG_STP__USBOTG_STP                    0x81 0x004
+#define MX27_PAD_USBOTG_STP__KP_ROW6A                      0x81 0x005
+#define MX27_PAD_USBOTG_STP__GPIO5_1                       0x81 0x032
+#define MX27_PAD_USBOTG_DIR__USBOTG_DIR                    0x82 0x000
+#define MX27_PAD_USBOTG_DIR__KP_ROW7A                      0x82 0x005
+#define MX27_PAD_USBOTG_DIR__GPIO5_2                       0x82 0x032
+#define MX27_PAD_UART2_CTS__UART2_CTS                      0x83 0x004
+#define MX27_PAD_UART2_CTS__KP_COL7                        0x83 0x005
+#define MX27_PAD_UART2_CTS__GPIO5_3                        0x83 0x032
+#define MX27_PAD_UART2_RTS__UART2_RTS                      0x84 0x000
+#define MX27_PAD_UART2_RTS__KP_ROW7                        0x84 0x005
+#define MX27_PAD_UART2_RTS__GPIO5_4                        0x84 0x032
+#define MX27_PAD_PWMO__PWMO                                0x85 0x004
+#define MX27_PAD_PWMO__GPIO5_5                             0x85 0x032
+#define MX27_PAD_UART2_TXD__UART2_TXD                      0x86 0x004
+#define MX27_PAD_UART2_TXD__KP_COL6                        0x86 0x005
+#define MX27_PAD_UART2_TXD__GPIO5_6                        0x86 0x032
+#define MX27_PAD_UART2_RXD__UART2_RXD                      0x87 0x000
+#define MX27_PAD_UART2_RXD__KP_ROW6                        0x87 0x005
+#define MX27_PAD_UART2_RXD__GPIO5_7                        0x87 0x032
+#define MX27_PAD_UART3_TXD__UART3_TXD                      0x88 0x004
+#define MX27_PAD_UART3_TXD__GPIO5_8                        0x88 0x032
+#define MX27_PAD_UART3_RXD__UART3_RXD                      0x89 0x000
+#define MX27_PAD_UART3_RXD__GPIO5_9                        0x89 0x032
+#define MX27_PAD_UART3_CTS__UART3_CTS                      0x8a 0x004
+#define MX27_PAD_UART3_CTS__GPIO5_10                       0x8a 0x032
+#define MX27_PAD_UART3_RTS__UART3_RTS                      0x8b 0x000
+#define MX27_PAD_UART3_RTS__GPIO5_11                       0x8b 0x032
+#define MX27_PAD_UART1_TXD__UART1_TXD                      0x8c 0x004
+#define MX27_PAD_UART1_TXD__GPIO5_12                       0x8c 0x032
+#define MX27_PAD_UART1_RXD__UART1_RXD                      0x8d 0x000
+#define MX27_PAD_UART1_RXD__GPIO5_13                       0x8d 0x032
+#define MX27_PAD_UART1_CTS__UART1_CTS                      0x8e 0x004
+#define MX27_PAD_UART1_CTS__GPIO5_14                       0x8e 0x032
+#define MX27_PAD_UART1_RTS__UART1_RTS                      0x8f 0x000
+#define MX27_PAD_UART1_RTS__GPIO5_15                       0x8f 0x032
+#define MX27_PAD_RTCK__RTCK                                0x90 0x004
+#define MX27_PAD_RTCK__OWIRE                               0x90 0x005
+#define MX27_PAD_RTCK__GPIO5_16                            0x90 0x032
+#define MX27_PAD_RESET_OUT_B__RESET_OUT_B                  0x91 0x004
+#define MX27_PAD_RESET_OUT_B__GPIO5_17                     0x91 0x032
+#define MX27_PAD_SD1_D0__SD1_D0                            0x92 0x004
+#define MX27_PAD_SD1_D0__CSPI3_MISO                        0x92 0x001
+#define MX27_PAD_SD1_D0__GPIO5_18                          0x92 0x032
+#define MX27_PAD_SD1_D1__SD1_D1                            0x93 0x004
+#define MX27_PAD_SD1_D1__GPIO5_19                          0x93 0x032
+#define MX27_PAD_SD1_D2__SD1_D2                            0x94 0x004
+#define MX27_PAD_SD1_D2__GPIO5_20                          0x94 0x032
+#define MX27_PAD_SD1_D3__SD1_D3                            0x95 0x004
+#define MX27_PAD_SD1_D3__CSPI3_SS                          0x95 0x005
+#define MX27_PAD_SD1_D3__GPIO5_21                          0x95 0x032
+#define MX27_PAD_SD1_CMD__SD1_CMD                          0x96 0x004
+#define MX27_PAD_SD1_CMD__CSPI3_MOSI                       0x96 0x005
+#define MX27_PAD_SD1_CMD__GPIO5_22                         0x96 0x032
+#define MX27_PAD_SD1_CLK__SD1_CLK                          0x97 0x004
+#define MX27_PAD_SD1_CLK__CSPI3_SCLK                       0x97 0x005
+#define MX27_PAD_SD1_CLK__GPIO5_23                         0x97 0x032
+#define MX27_PAD_USBOTG_CLK__USBOTG_CLK                    0x98 0x000
+#define MX27_PAD_USBOTG_CLK__GPIO5_24                      0x98 0x032
+#define MX27_PAD_USBOTG_DATA7__USBOTG_DATA7                0x99 0x004
+#define MX27_PAD_USBOTG_DATA7__GPIO5_25                    0x99 0x032
+#define MX27_PAD_UNUSED9__UNUSED9                          0x9a 0x004
+#define MX27_PAD_UNUSED9__GPIO5_26                         0x9a 0x032
+#define MX27_PAD_UNUSED10__UNUSED10                        0x9b 0x004
+#define MX27_PAD_UNUSED10__GPIO5_27                        0x9b 0x032
+#define MX27_PAD_UNUSED11__UNUSED11                        0x9c 0x004
+#define MX27_PAD_UNUSED11__GPIO5_28                        0x9c 0x032
+#define MX27_PAD_UNUSED12__UNUSED12                        0x9d 0x004
+#define MX27_PAD_UNUSED12__GPIO5_29                        0x9d 0x032
+#define MX27_PAD_UNUSED13__UNUSED13                        0x9e 0x004
+#define MX27_PAD_UNUSED13__GPIO5_30                        0x9e 0x032
+#define MX27_PAD_UNUSED14__UNUSED14                        0x9f 0x004
+#define MX27_PAD_UNUSED14__GPIO5_31                        0x9f 0x032
+#define MX27_PAD_NFRB__NFRB                                0xa0 0x000
+#define MX27_PAD_NFRB__ETMTRACEPKT3                        0xa0 0x005
+#define MX27_PAD_NFRB__GPIO6_0                             0xa0 0x032
+#define MX27_PAD_NFCLE__NFCLE                              0xa1 0x004
+#define MX27_PAD_NFCLE__ETMTRACEPKT0                       0xa1 0x005
+#define MX27_PAD_NFCLE__GPIO6_1                            0xa1 0x032
+#define MX27_PAD_NFWP_B__NFWP_B                            0xa2 0x004
+#define MX27_PAD_NFWP_B__ETMTRACEPKT1                      0xa2 0x005
+#define MX27_PAD_NFWP_B__GPIO6_2                           0xa2 0x032
+#define MX27_PAD_NFCE_B__NFCE_B                            0xa3 0x004
+#define MX27_PAD_NFCE_B__ETMTRACEPKT2                      0xa3 0x005
+#define MX27_PAD_NFCE_B__GPIO6_3                           0xa3 0x032
+#define MX27_PAD_NFALE__NFALE                              0xa4 0x004
+#define MX27_PAD_NFALE__ETMPIPESTAT0                       0xa4 0x005
+#define MX27_PAD_NFALE__GPIO6_4                            0xa4 0x032
+#define MX27_PAD_NFRE_B__NFRE_B                            0xa5 0x004
+#define MX27_PAD_NFRE_B__ETMPIPESTAT1                      0xa5 0x005
+#define MX27_PAD_NFRE_B__GPIO6_5                           0xa5 0x032
+#define MX27_PAD_NFWE_B__NFWE_B                            0xa6 0x004
+#define MX27_PAD_NFWE_B__ETMPIPESTAT2                      0xa6 0x005
+#define MX27_PAD_NFWE_B__GPIO6_6                           0xa6 0x032
+#define MX27_PAD_PC_POE__PC_POE                            0xa7 0x004
+#define MX27_PAD_PC_POE__ATA_BUFFER_EN                     0xa7 0x005
+#define MX27_PAD_PC_POE__GPIO6_7                           0xa7 0x032
+#define MX27_PAD_PC_RW_B__PC_RW_B                          0xa8 0x004
+#define MX27_PAD_PC_RW_B__ATA_IORDY                        0xa8 0x001
+#define MX27_PAD_PC_RW_B__GPIO6_8                          0xa8 0x032
+#define MX27_PAD_IOIS16__IOIS16                            0xa9 0x000
+#define MX27_PAD_IOIS16__ATA_INTRQ                         0xa9 0x001
+#define MX27_PAD_IOIS16__GPIO6_9                           0xa9 0x032
+#define MX27_PAD_PC_RST__PC_RST                            0xaa 0x004
+#define MX27_PAD_PC_RST__ATA_RESET_B                       0xaa 0x005
+#define MX27_PAD_PC_RST__GPIO6_10                          0xaa 0x032
+#define MX27_PAD_PC_BVD2__PC_BVD2                          0xab 0x000
+#define MX27_PAD_PC_BVD2__ATA_DMACK                        0xab 0x005
+#define MX27_PAD_PC_BVD2__GPIO6_11                         0xab 0x032
+#define MX27_PAD_PC_BVD1__PC_BVD1                          0xac 0x000
+#define MX27_PAD_PC_BVD1__ATA_DMARQ                        0xac 0x001
+#define MX27_PAD_PC_BVD1__GPIO6_12                         0xac 0x032
+#define MX27_PAD_PC_VS2__PC_VS2                            0xad 0x000
+#define MX27_PAD_PC_VS2__ATA_DA0                           0xad 0x005
+#define MX27_PAD_PC_VS2__GPIO6_13                          0xad 0x032
+#define MX27_PAD_PC_VS1__PC_VS1                            0xae 0x000
+#define MX27_PAD_PC_VS1__ATA_DA1                           0xae 0x005
+#define MX27_PAD_PC_VS1__GPIO6_14                          0xae 0x032
+#define MX27_PAD_CLKO__CLKO                                0xaf 0x004
+#define MX27_PAD_CLKO__GPIO6_15                            0xaf 0x032
+#define MX27_PAD_PC_PWRON__PC_PWRON                        0xb0 0x000
+#define MX27_PAD_PC_PWRON__ATA_DA2                         0xb0 0x005
+#define MX27_PAD_PC_PWRON__GPIO6_16                        0xb0 0x032
+#define MX27_PAD_PC_READY__PC_READY                        0xb1 0x000
+#define MX27_PAD_PC_READY__ATA_CS0                         0xb1 0x005
+#define MX27_PAD_PC_READY__GPIO6_17                        0xb1 0x032
+#define MX27_PAD_PC_WAIT_B__PC_WAIT_B                      0xb2 0x000
+#define MX27_PAD_PC_WAIT_B__ATA_CS1                        0xb2 0x005
+#define MX27_PAD_PC_WAIT_B__GPIO6_18                       0xb2 0x032
+#define MX27_PAD_PC_CD2_B__PC_CD2_B                        0xb3 0x000
+#define MX27_PAD_PC_CD2_B__ATA_DIOW                        0xb3 0x005
+#define MX27_PAD_PC_CD2_B__GPIO6_19                        0xb3 0x032
+#define MX27_PAD_PC_CD1_B__PC_CD1_B                        0xb4 0x000
+#define MX27_PAD_PC_CD1_B__ATA_DIOR                        0xb4 0x005
+#define MX27_PAD_PC_CD1_B__GPIO6_20                        0xb4 0x032
+#define MX27_PAD_CS4_B__CS4_B                              0xb5 0x004
+#define MX27_PAD_CS4_B__ETMTRACESYNC                       0xb5 0x005
+#define MX27_PAD_CS4_B__GPIO6_21                           0xb5 0x032
+#define MX27_PAD_CS5_B__CS5_B                              0xb6 0x004
+#define MX27_PAD_CS5_B__ETMTRACECLK                        0xb6 0x005
+#define MX27_PAD_CS5_B__GPIO6_22                           0xb6 0x032
+#define MX27_PAD_ATA_DATA15__ATA_DATA15                    0xb7 0x004
+#define MX27_PAD_ATA_DATA15__ETMTRACEPKT4                  0xb7 0x005
+#define MX27_PAD_ATA_DATA15__FEC_TX_EN                     0xb7 0x006
+#define MX27_PAD_ATA_DATA15__GPIO6_23                      0xb7 0x032
+#define MX27_PAD_UNUSED15__UNUSED15                        0xb8 0x004
+#define MX27_PAD_UNUSED15__GPIO6_24                        0xb8 0x032
+#define MX27_PAD_UNUSED16__UNUSED16                        0xb9 0x004
+#define MX27_PAD_UNUSED16__GPIO6_25                        0xb9 0x032
+#define MX27_PAD_UNUSED17__UNUSED17                        0xba 0x004
+#define MX27_PAD_UNUSED17__GPIO6_26                        0xba 0x032
+#define MX27_PAD_UNUSED18__UNUSED18                        0xbb 0x004
+#define MX27_PAD_UNUSED18__GPIO6_27                        0xbb 0x032
+#define MX27_PAD_UNUSED19__UNUSED19                        0xbc 0x004
+#define MX27_PAD_UNUSED19__GPIO6_28                        0xbc 0x032
+#define MX27_PAD_UNUSED20__UNUSED20                        0xbd 0x004
+#define MX27_PAD_UNUSED20__GPIO6_29                        0xbd 0x032
+#define MX27_PAD_UNUSED21__UNUSED21                        0xbe 0x004
+#define MX27_PAD_UNUSED21__GPIO6_30                        0xbe 0x032
+#define MX27_PAD_UNUSED22__UNUSED22                        0xbf 0x004
+#define MX27_PAD_UNUSED22__GPIO6_31                        0xbf 0x032
+
+#endif /* __DTS_IMX27_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 826231eb4446..6279e0b4f768 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -10,6 +10,9 @@
  */
 
 #include "skeleton.dtsi"
+#include "imx27-pinfunc.h"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	aliases {
@@ -67,6 +70,26 @@
 		};
 	};
 
+	usbphy {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usbphy0: usbphy@0 {
+			compatible = "usb-nop-xceiv";
+			reg = <0>;
+			clocks = <&clks 75>;
+			clock-names = "main_clk";
+		};
+
+		usbphy2: usbphy@2 {
+			compatible = "usb-nop-xceiv";
+			reg = <2>;
+			clocks = <&clks 75>;
+			clock-names = "main_clk";
+		};
+	};
+
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -204,6 +227,30 @@
 				status = "disabled";
 			};
 
+			ssi1: ssi@10010000 {
+				#sound-dai-cells = <0>;
+				compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
+				reg = <0x10010000 0x1000>;
+				interrupts = <14>;
+				clocks = <&clks 26>;
+				dmas = <&dma 12>, <&dma 13>, <&dma 14>, <&dma 15>;
+				dma-names = "rx0", "tx0", "rx1", "tx1";
+				fsl,fifo-depth = <8>;
+				status = "disabled";
+			};
+
+			ssi2: ssi@10011000 {
+				#sound-dai-cells = <0>;
+				compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
+				reg = <0x10011000 0x1000>;
+				interrupts = <13>;
+				clocks = <&clks 25>;
+				dmas = <&dma 8>, <&dma 9>, <&dma 10>, <&dma 11>;
+				dma-names = "rx0", "tx0", "rx1", "tx1";
+				fsl,fifo-depth = <8>;
+				status = "disabled";
+			};
+
 			i2c1: i2c@10012000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -236,64 +283,72 @@
 				status = "disabled";
 			};
 
-			gpio1: gpio@10015000 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015000 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@10015100 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015100 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio3: gpio@10015200 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015200 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio4: gpio@10015300 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015300 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio5: gpio@10015400 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015400 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio6: gpio@10015500 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015500 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+			iomuxc: iomuxc@10015000 {
+				compatible = "fsl,imx27-iomuxc";
+				reg = <0x10015000 0x600>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				gpio1: gpio@10015000 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015000 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				gpio2: gpio@10015100 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015100 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				gpio3: gpio@10015200 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015200 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				gpio4: gpio@10015300 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015300 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				gpio5: gpio@10015400 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015400 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				gpio6: gpio@10015500 {
+					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+					reg = <0x10015500 0x100>;
+					interrupts = <8>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
 			audmux: audmux@10016000 {
@@ -404,6 +459,42 @@
 				iram = <&iram>;
 			};
 
+			usbotg: usb@10024000 {
+				compatible = "fsl,imx27-usb";
+				reg = <0x10024000 0x200>;
+				interrupts = <56>;
+				clocks = <&clks 15>;
+				fsl,usbmisc = <&usbmisc 0>;
+				fsl,usbphy = <&usbphy0>;
+				status = "disabled";
+			};
+
+			usbh1: usb@10024200 {
+				compatible = "fsl,imx27-usb";
+				reg = <0x10024200 0x200>;
+				interrupts = <54>;
+				clocks = <&clks 15>;
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbh2: usb@10024400 {
+				compatible = "fsl,imx27-usb";
+				reg = <0x10024400 0x200>;
+				interrupts = <55>;
+				clocks = <&clks 15>;
+				fsl,usbmisc = <&usbmisc 2>;
+				fsl,usbphy = <&usbphy2>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc@10024600 {
+				#index-cells = <1>;
+				compatible = "fsl,imx27-usbmisc";
+				reg = <0x10024600 0x200>;
+				clocks = <&clks 62>;
+			};
+
 			sahara2: sahara@10025000 {
 				compatible = "fsl,imx27-sahara";
 				reg = <0x10025000 0x1000>;
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
index e2efd8d89c4f..221cac4fb2cd 100644
--- a/arch/arm/boot/dts/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -48,6 +48,7 @@
 						MX28_PAD_LCD_D20__GPIO_1_20
 						MX28_PAD_LCD_D21__GPIO_1_21
 						MX28_PAD_LCD_D22__GPIO_1_22
+						MX28_PAD_GPMI_CE1N__GPIO_0_17
 					>;
 					fsl,drive-strength = <MXS_DRIVE_4mA>;
 					fsl,voltage = <MXS_VOLTAGE_HIGH>;
@@ -66,6 +67,16 @@
 					fsl,voltage = <MXS_VOLTAGE_HIGH>;
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
+
+				usb0_otg_apf28dev: otg-apf28dev@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_LCD_D23__GPIO_1_23
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
 			};
 
 			lcdif@80030000 {
@@ -131,6 +142,8 @@
 
 	ahb@80080000 {
 		usb0: usb@80080000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb0_otg_apf28dev>;
 			vbus-supply = <&reg_usb0_vbus>;
 			status = "okay";
 		};
@@ -150,13 +163,17 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			gpio = <&gpio1 23 1>;
+			enable-active-high;
 		};
 	};
 
@@ -177,4 +194,14 @@
 		brightness-levels = <0 4 8 16 32 64 128 255>;
 		default-brightness-level = <6>;
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-button {
+			label = "User button";
+			gpios = <&gpio0 17 0>;
+			linux,code = <0x100>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
index 6f254ca816cb..e1ce9179db63 100644
--- a/arch/arm/boot/dts/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/imx28-apx4devkit.dts
@@ -193,9 +193,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index cabb6171a19d..ae7c3390e65a 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -100,6 +100,8 @@
 		usb0: usb@80080000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&usb0_otg_cfa10036>;
+			dr_mode = "peripheral";
+			phy_type = "utmi";
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/imx28-cfa10037.dts b/arch/arm/boot/dts/imx28-cfa10037.dts
index f93e9a700e52..e5beaa58bb40 100644
--- a/arch/arm/boot/dts/imx28-cfa10037.dts
+++ b/arch/arm/boot/dts/imx28-cfa10037.dts
@@ -54,7 +54,7 @@
 	ahb@80080000 {
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			pinctrl-names = "default";
 			status = "okay";
 		};
@@ -72,9 +72,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&usb_pins_cfa10037>;
 			regulator-name = "usb1_vbus";
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 7087b4bf6a8f..7d51459de5e8 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -229,15 +229,39 @@
 				i2c-parent = <&i2c1>;
 
 				i2c@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
 					reg = <0>;
+
+					adc0: nau7802@2a {
+						compatible = "nuvoton,nau7802";
+						reg = <0x2a>;
+						nuvoton,vldo = <3000>;
+					};
 				};
 
 				i2c@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
 					reg = <1>;
+
+					adc1: nau7802@2a {
+						compatible = "nuvoton,nau7802";
+						reg = <0x2a>;
+						nuvoton,vldo = <3000>;
+					};
 				};
 
 				i2c@2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
 					reg = <2>;
+
+					adc2: nau7802@2a {
+						compatible = "nuvoton,nau7802";
+						reg = <0x2a>;
+						nuvoton,vldo = <3000>;
+					};
 				};
 
 				i2c@3 {
@@ -274,7 +298,7 @@
 	ahb@80080000 {
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			pinctrl-names = "default";
 			status = "okay";
 		};
@@ -282,9 +306,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&usb_pins_cfa10049>;
 			regulator-name = "usb1_vbus";
diff --git a/arch/arm/boot/dts/imx28-cfa10057.dts b/arch/arm/boot/dts/imx28-cfa10057.dts
index 3c1312885ae0..c4e00ce4b6da 100644
--- a/arch/arm/boot/dts/imx28-cfa10057.dts
+++ b/arch/arm/boot/dts/imx28-cfa10057.dts
@@ -134,7 +134,7 @@
 	ahb@80080000 {
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			pinctrl-names = "default";
 			status = "okay";
 		};
@@ -142,9 +142,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&usb_pins_cfa10057>;
 			regulator-name = "usb1_vbus";
diff --git a/arch/arm/boot/dts/imx28-cfa10058.dts b/arch/arm/boot/dts/imx28-cfa10058.dts
index 2469d34df0ae..7c9cc783f0d1 100644
--- a/arch/arm/boot/dts/imx28-cfa10058.dts
+++ b/arch/arm/boot/dts/imx28-cfa10058.dts
@@ -101,7 +101,7 @@
 	ahb@80080000 {
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			pinctrl-names = "default";
 			status = "okay";
 		};
@@ -109,11 +109,14 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@0 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&usb_pins_cfa10058>;
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-duckbill.dts b/arch/arm/boot/dts/imx28-duckbill.dts
new file mode 100644
index 000000000000..5f326c1c1850
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-duckbill.dts
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 Michael Heimpold <mhei@heimpold.de>
+ *
+ * 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 "imx28.dtsi"
+
+/ {
+	model = "I2SE Duckbill";
+	compatible = "i2se,duckbill", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			ssp0: ssp@80010000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_8bit_pins_a
+					&mmc0_cd_cfg &mmc0_sck_cfg>;
+				bus-width = <8>;
+				vmmc-supply = <&reg_3p3v>;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_ENET0_RX_CLK__GPIO_4_13 /* PHY Reset */
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				led_pins_a: led_gpio@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_AUART1_RX__GPIO_3_4
+						MX28_PAD_AUART1_TX__GPIO_3_5
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+			};
+		};
+
+		apbx@80040000 {
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			status = "okay";
+		};
+
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			phy-supply = <&reg_3p3v>;
+			phy-reset-gpios = <&gpio4 13 0>;
+			phy-reset-duration = <100>;
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_a>;
+
+		status {
+			label = "duckbill:green:status";
+			gpios = <&gpio3 5 0>;
+		};
+
+		failure {
+			label = "duckbill:red:status";
+			gpios = <&gpio3 4 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts b/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts
new file mode 100644
index 000000000000..7c1572c5a4fb
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/*
+ * Module contains : i.MX282 + 64MB DDR2 + NAND + Ethernet PHY + RTC
+ */
+
+/dts-v1/;
+#include "imx28-eukrea-mbmx28lc.dtsi"
+
+/ {
+	model = "Eukrea Electromatique MBMX283LC";
+	compatible = "eukrea,mbmx283lc", "eukrea,mbmx28lc", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x04000000>;
+	};
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpmi_pins_a>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	pcf8563: rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+
+&mac0 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mac0_pins_a>;
+	phy-reset-gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pinctrl{
+	pinctrl-names = "default";
+	pinctrl-0 = <&hog_pins_cpuimx283>;
+
+	hog_pins_cpuimx283: hog-cpuimx283@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+			MX28_PAD_ENET0_TX_CLK__GPIO_4_5
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_ENABLE>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts b/arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts
new file mode 100644
index 000000000000..e773144e1e03
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/*
+ * Module contains : i.MX287 + 128MB DDR2 + NAND + 2 x Ethernet PHY + RTC
+ */
+
+#include "imx28-eukrea-mbmx283lc.dts"
+
+/ {
+	model = "Eukrea Electromatique MBMX287LC";
+	compatible = "eukrea,mbmx287lc", "eukrea,mbmx283lc", "eukrea,mbmx28lc", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+};
+
+&mac1 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mac1_pins_a>;
+	phy-reset-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hog_pins_cpuimx283 &hog_pins_cpuimx287>;
+	hog_pins_cpuimx287: hog-cpuimx287@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_SPDIF__GPIO_3_27
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_ENABLE>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi b/arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi
new file mode 100644
index 000000000000..927b391d2058
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+	model = "Eukrea Electromatique MBMX28LC";
+	compatible = "eukrea,mbmx28lc", "fsl,imx28";
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 4 1000000>;
+		brightness-levels = <0 25 50 75 100 125 150 175 200 225 255>;
+		default-brightness-level = <10>;
+	};
+
+	button-sw3 {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_button_sw3_pins_mbmx28lc>;
+
+		sw3 {
+			label = "SW3";
+			gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_MISC>;
+			gpio-key,wakeup;
+		};
+	};
+
+	button-sw4 {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_button_sw4_pins_mbmx28lc>;
+
+		sw4 {
+			label = "SW4";
+			gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_MISC>;
+			gpio-key,wakeup;
+		};
+	};
+
+	led-d6 {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_d6_pins_mbmx28lc>;
+
+		led1 {
+			label = "d6";
+			gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	led-d7 {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_d7_pins_mbmx28lc>;
+
+		led1 {
+			label = "d7";
+			gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_lcd_3v3: regulator@1 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&reg_lcd_3v3_pins_mbmx28lc>;
+			regulator-name = "lcd-3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usb0_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&reg_usb0_vbus_pins_mbmx28lc>;
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usb1_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&reg_usb1_vbus_pins_mbmx28lc>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 19 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx28-mbmx28lc-sgtl5000",
+			     "fsl,mxs-audio-sgtl5000";
+		model = "imx28-mbmx28lc-sgtl5000";
+		saif-controllers = <&saif0 &saif1>;
+		audio-codec = <&sgtl5000>;
+	};
+};
+
+&duart {
+	pinctrl-names = "default";
+	pinctrl-0 = <&duart_4pins_a>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+		clocks = <&saif0>;
+	};
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcdif_18bit_pins_a &lcdif_pins_mbmx28lc>;
+	lcd-supply = <&reg_lcd_3v3>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display0 {
+		model = "43WVF1G-0";
+		bits-per-pixel = <16>;
+		bus-width = <18>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: timing0 {
+				clock-frequency = <9072000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <10>;
+				hfront-porch = <5>;
+				vback-porch = <8>;
+				vfront-porch = <8>;
+				hsync-len = <40>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&lradc {
+	fsl,lradc-touchscreen-wires = <4>;
+	status = "okay";
+};
+
+&pinctrl {
+	gpio_button_sw3_pins_mbmx28lc: gpio-button-sw3-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D21__GPIO_1_21
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	gpio_button_sw4_pins_mbmx28lc: gpio-button-sw4-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D20__GPIO_1_20
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	lcdif_pins_mbmx28lc: lcdif-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_VSYNC__LCD_VSYNC
+			MX28_PAD_LCD_HSYNC__LCD_HSYNC
+			MX28_PAD_LCD_DOTCLK__LCD_DOTCLK
+			MX28_PAD_LCD_ENABLE__LCD_ENABLE
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	led_d6_pins_mbmx28lc: led-d6-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D23__GPIO_1_23
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	led_d7_pins_mbmx28lc: led-d7-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D22__GPIO_1_22
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	reg_lcd_3v3_pins_mbmx28lc: lcd-3v3-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_RESET__GPIO_3_30
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	reg_usb0_vbus_pins_mbmx28lc: reg-usb0-vbus-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D18__GPIO_1_18
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	reg_usb1_vbus_pins_mbmx28lc: reg-usb1-vbus-mbmx28lc@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D19__GPIO_1_19
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm4_pins_a>;
+	status = "okay";
+};
+
+&saif0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&saif0_pins_a>;
+	status = "okay";
+};
+
+&saif1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&saif1_pins_a>;
+	fsl,saif-master = <&saif0>;
+	status = "okay";
+};
+
+&ssp0 {
+	compatible = "fsl,imx28-mmc";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_cd_cfg &mmc0_sck_cfg>;
+	bus-width = <4>;
+	cd-inverted;
+	status = "okay";
+};
+
+&usb0 {
+	disable-over-current;
+	vbus-supply = <&reg_usb0_vbus>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_pins_b>;
+};
+
+&usb1 {
+	vbus-supply = <&reg_usb1_vbus>;
+	status = "okay";
+};
+
+&usbphy0 {
+	status = "okay";
+};
+
+&usbphy1 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 4267c2b05d60..e4cc44c98585 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -193,6 +193,7 @@
 			i2c0: i2c@80058000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&i2c0_pins_a>;
+				clock-frequency = <400000>;
 				status = "okay";
 
 				sgtl5000: codec@0a {
@@ -278,33 +279,39 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 
-		reg_vddio_sd0: vddio-sd0 {
+		reg_vddio_sd0: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "vddio-sd0";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio3 28 0>;
 		};
 
-		reg_fec_3v3: fec-3v3 {
+		reg_fec_3v3: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "fec-3v3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio2 15 0>;
 		};
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@3 {
 			compatible = "regulator-fixed";
+			reg = <3>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -312,8 +319,9 @@
 			enable-active-high;
 		};
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@4 {
 			compatible = "regulator-fixed";
+			reg = <4>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -321,8 +329,9 @@
 			enable-active-high;
 		};
 
-		reg_lcd_3v3: lcd-3v3 {
+		reg_lcd_3v3: regulator@5 {
 			compatible = "regulator-fixed";
+			reg = <5>;
 			regulator-name = "lcd-3v3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -330,8 +339,9 @@
 			enable-active-high;
 		};
 
-		reg_can_3v3: can-3v3 {
+		reg_can_3v3: regulator@6 {
 			compatible = "regulator-fixed";
+			reg = <6>;
 			regulator-name = "can-3v3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx28-m28cu3.dts b/arch/arm/boot/dts/imx28-m28cu3.dts
index d3958da60bd7..9348ce59dda4 100644
--- a/arch/arm/boot/dts/imx28-m28cu3.dts
+++ b/arch/arm/boot/dts/imx28-m28cu3.dts
@@ -116,7 +116,6 @@
 				pinctrl-0 = <&lcdif_24bit_pins_a
 					     &lcdif_pins_m28>;
 				display = <&display>;
-				reset-active-high;
 				status = "okay";
 
 				display: display0 {
@@ -180,7 +179,7 @@
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
 			pinctrl-names = "default";
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			disable-over-current;
 			status = "okay";
 		};
@@ -229,33 +228,39 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 
-		reg_vddio_sd0: vddio-sd0 {
+		reg_vddio_sd0: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "vddio-sd0";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio3 29 0>;
 		};
 
-		reg_vddio_sd1: vddio-sd1 {
+		reg_vddio_sd1: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "vddio-sd1";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio2 19 0>;
 		};
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@3 {
 			compatible = "regulator-fixed";
+			reg = <3>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 8e2477fbe1d7..f0ad7b9b9d9a 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -194,7 +194,7 @@
 				};
 
 				rtc: rtc@68 {
-					compatible = "stm,mt41t62";
+					compatible = "stm,m41t62";
 					reg = <0x68>;
 				};
 			};
@@ -248,14 +248,14 @@
 		usb0: usb@80080000 {
 			vbus-supply = <&reg_usb0_vbus>;
 			pinctrl-names = "default";
-			pinctrl-0 = <&usbphy0_pins_a>;
+			pinctrl-0 = <&usb0_pins_a>;
 			status = "okay";
 		};
 
 		usb1: usb@80090000 {
 			vbus-supply = <&reg_usb1_vbus>;
 			pinctrl-names = "default";
-			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-0 = <&usb1_pins_a>;
 			status = "okay";
 		};
 
@@ -285,33 +285,39 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 
-		reg_vddio_sd0: vddio-sd0 {
+		reg_vddio_sd0: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "vddio-sd0";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio3 28 0>;
 		};
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			gpio = <&gpio3 12 0>;
 		};
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@3 {
 			compatible = "regulator-fixed";
+			reg = <3>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
index 4870f07bf56a..0ce3cb8e7914 100644
--- a/arch/arm/boot/dts/imx28-sps1.dts
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -106,7 +106,7 @@
 		usb0: usb@80080000 {
 			vbus-supply = <&reg_usb0_vbus>;
 			pinctrl-names = "default";
-			pinctrl-0 = <&usbphy0_pins_b>;
+			pinctrl-0 = <&usb0_pins_b>;
 			status = "okay";
 		};
 
@@ -127,9 +127,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
index be5a0550d58c..e14bd86f3e99 100644
--- a/arch/arm/boot/dts/imx28-tx28.dts
+++ b/arch/arm/boot/dts/imx28-tx28.dts
@@ -43,9 +43,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb0_vbus: usb0_vbus {
+		reg_usb0_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -53,8 +56,9 @@
 			enable-active-high;
 		};
 
-		reg_usb1_vbus: usb1_vbus {
+		reg_usb1_vbus: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -62,35 +66,38 @@
 			enable-active-high;
 		};
 
-		reg_2p5v: 2p5v {
+		reg_2p5v: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "2P5V";
 			regulator-min-microvolt = <2500000>;
 			regulator-max-microvolt = <2500000>;
 			regulator-always-on;
 		};
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@3 {
 			compatible = "regulator-fixed";
+			reg = <3>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 
-		reg_can_xcvr: can-xcvr {
+		reg_can_xcvr: regulator@4 {
 			compatible = "regulator-fixed";
+			reg = <4>;
 			regulator-name = "CAN XCVR";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			gpio = <&gpio1 0 0>;
-			enable-active-low;
 			pinctrl-names = "default";
 			pinctrl-0 = <&tx28_flexcan_xcvr_pins>;
 		};
 
-		reg_lcd: lcd-power {
+		reg_lcd: regulator@5 {
 			compatible = "regulator-fixed";
+			reg = <5>;
 			regulator-name = "LCD POWER";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -98,8 +105,9 @@
 			enable-active-high;
 		};
 
-		reg_lcd_reset: lcd-reset {
+		reg_lcd_reset: regulator@6 {
 			compatible = "regulator-fixed";
+			reg = <6>;
 			regulator-name = "LCD RESET";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index f8e9b20f6982..90a579532b8b 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -32,6 +32,8 @@
 		serial4 = &auart4;
 		spi0 = &ssp1;
 		spi1 = &ssp2;
+		usbphy0 = &usbphy0;
+		usbphy1 = &usbphy1;
 	};
 
 	cpus {
@@ -343,6 +345,19 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				auart2_pins_a: auart2-pins@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_AUART2_RX__AUART2_RX
+						MX28_PAD_AUART2_TX__AUART2_TX
+						MX28_PAD_AUART2_CTS__AUART2_CTS
+						MX28_PAD_AUART2_RTS__AUART2_RTS
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
 				auart3_pins_a: auart3@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -655,6 +670,33 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				lcdif_18bit_pins_a: lcdif-18bit@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
+						MX28_PAD_LCD_D16__LCD_D16
+						MX28_PAD_LCD_D17__LCD_D17
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
 				lcdif_16bit_pins_a: lcdif-16bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -743,7 +785,7 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
-				usbphy0_pins_a: usbphy0@0 {
+				usb0_pins_a: usb0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						MX28_PAD_SSP2_SS2__USB0_OVERCURRENT
@@ -753,7 +795,7 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
-				usbphy0_pins_b: usbphy0@1 {
+				usb0_pins_b: usb0@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
 						MX28_PAD_AUART1_CTS__USB0_OVERCURRENT
@@ -763,7 +805,7 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
-				usbphy1_pins_a: usbphy1@0 {
+				usb1_pins_a: usb1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						MX28_PAD_SSP2_SS1__USB1_OVERCURRENT
@@ -782,6 +824,17 @@
 					fsl,voltage = <MXS_VOLTAGE_HIGH>;
 					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
+
+				usb0_id_pins_b: usb0id1@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_PWM2__USB0_ID
+					>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
 			};
 
 			digctl: digctl@8001c000 {
@@ -946,6 +999,7 @@
 						20 21 22 23 24 25>;
 				status = "disabled";
 				clocks = <&clks 41>;
+				#io-channel-cells = <1>;
 			};
 
 			spdif: spdif@80054000 {
@@ -1130,4 +1184,9 @@
 			status = "disabled";
 		};
 	};
+
+	iio_hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&lradc 8>;
+	};
 };
diff --git a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
new file mode 100644
index 000000000000..906ae937b013
--- /dev/null
+++ b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+#include "imx35.dtsi"
+
+/ {
+	model = "Eukrea CPUIMX35";
+	compatible = "eukrea,cpuimx35", "fsl,imx35";
+
+	memory {
+		reg = <0x80000000 0x8000000>; /* 128M */
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&iomuxc {
+	imx35-eukrea {
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX35_PAD_FEC_TX_CLK__FEC_TX_CLK		0x80000000
+				MX35_PAD_FEC_RX_CLK__FEC_RX_CLK		0x80000000
+				MX35_PAD_FEC_RX_DV__FEC_RX_DV		0x80000000
+				MX35_PAD_FEC_COL__FEC_COL		0x80000000
+				MX35_PAD_FEC_RDATA0__FEC_RDATA_0	0x80000000
+				MX35_PAD_FEC_TDATA0__FEC_TDATA_0	0x80000000
+				MX35_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX35_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX35_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX35_PAD_FEC_TX_ERR__FEC_TX_ERR		0x80000000
+				MX35_PAD_FEC_RX_ERR__FEC_RX_ERR		0x80000000
+				MX35_PAD_FEC_CRS__FEC_CRS		0x80000000
+				MX35_PAD_FEC_RDATA1__FEC_RDATA_1	0x80000000
+				MX35_PAD_FEC_TDATA1__FEC_TDATA_1	0x80000000
+				MX35_PAD_FEC_RDATA2__FEC_RDATA_2	0x80000000
+				MX35_PAD_FEC_TDATA2__FEC_TDATA_2	0x80000000
+				MX35_PAD_FEC_RDATA3__FEC_RDATA_3	0x80000000
+				MX35_PAD_FEC_TDATA3__FEC_TDATA_3	0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX35_PAD_I2C1_CLK__I2C1_SCL		0x80000000
+				MX35_PAD_I2C1_DAT__I2C1_SDA		0x80000000
+			>;
+		};
+	};
+};
+
+&nfc {
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
new file mode 100644
index 000000000000..1bdec21f4533
--- /dev/null
+++ b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx35-eukrea-cpuimx35.dtsi"
+
+/ {
+	model = "Eukrea CPUIMX35";
+	compatible = "eukrea,mbimxsd35-baseboard", "eukrea,cpuimx35", "fsl,imx35";
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_bp1>;
+
+		bp1 {
+			label = "BP1";
+			gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_MISC>;
+			gpio-key,wakeup;
+			linux,input-type = <1>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led1>;
+
+		led1 {
+			label = "led1";
+			gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	cd-gpios = <&gpio3 24>;
+	status = "okay";
+};
+
+&i2c1 {
+	tlv320aic23: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+	};
+};
+
+&iomuxc {
+	imx35-eukrea {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS	0x80000000
+				MX35_PAD_STXD4__AUDMUX_AUD4_TXD		0x80000000
+				MX35_PAD_SRXD4__AUDMUX_AUD4_RXD		0x80000000
+				MX35_PAD_SCK4__AUDMUX_AUD4_TXC		0x80000000
+			>;
+		};
+
+		pinctrl_bp1: bp1grp {
+			fsl,pins = <MX35_PAD_LD19__GPIO3_25  0x80000000>;
+		};
+
+		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
+				MX35_PAD_LD18__GPIO3_24			0x80000000 /* CD */
+			>;
+		};
+
+		pinctrl_led1: led1grp {
+			fsl,pins = <MX35_PAD_LD23__GPIO3_29  0x80000000>;
+		};
+
+		pinctrl_reg_lcd_3v3: reg-lcd-3v3 {
+			fsl,pins = <MX35_PAD_D3_CLS__GPIO1_4 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
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX35_PAD_RXD2__UART2_RXD_MUX		0x1c5
+				MX35_PAD_TXD2__UART2_TXD_MUX		0x1c5
+				MX35_PAD_RTS2__UART2_RTS		0x1c5
+				MX35_PAD_CTS2__UART2_CTS		0x1c5
+			>;
+		};
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
new file mode 100644
index 000000000000..88b218f8f810
--- /dev/null
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2012 Steffen Trumtrar, Pengutronix
+ *
+ * based on imx27.dtsi
+ *
+ * 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 "skeleton.dtsi"
+#include "imx35-pinfunc.h"
+
+/ {
+	aliases {
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		spi0 = &spi1;
+		spi1 = &spi2;
+	};
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			compatible = "arm,arm1136";
+			device_type = "cpu";
+		};
+	};
+
+	avic: avic-interrupt-controller@68000000 {
+		compatible = "fsl,imx35-avic", "fsl,avic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x68000000 0x10000000>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&avic>;
+		ranges;
+
+		L2: l2-cache@30000000 {
+			compatible = "arm,l210-cache";
+			reg = <0x30000000 0x1000>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		aips1: aips@43f00000 {
+			compatible = "fsl,aips", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x43f00000 0x100000>;
+			ranges;
+
+			i2c1: i2c@43f80000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx35-i2c", "fsl,imx1-i2c";
+				reg = <0x43f80000 0x4000>;
+				clocks = <&clks 51>;
+				clock-names = "ipg_per";
+				interrupts = <10>;
+				status = "disabled";
+			};
+
+			i2c3: i2c@43f84000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx35-i2c", "fsl,imx1-i2c";
+				reg = <0x43f84000 0x4000>;
+				clocks = <&clks 53>;
+				clock-names = "ipg_per";
+				interrupts = <3>;
+				status = "disabled";
+			};
+
+			uart1: serial@43f90000 {
+				compatible = "fsl,imx35-uart", "fsl,imx21-uart";
+				reg = <0x43f90000 0x4000>;
+				clocks = <&clks 9>, <&clks 70>;
+				clock-names = "ipg", "per";
+				interrupts = <45>;
+				status = "disabled";
+			};
+
+			uart2: serial@43f94000 {
+				compatible = "fsl,imx35-uart", "fsl,imx21-uart";
+				reg = <0x43f94000 0x4000>;
+				clocks = <&clks 9>, <&clks 71>;
+				clock-names = "ipg", "per";
+				interrupts = <32>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@43f98000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx35-i2c", "fsl,imx1-i2c";
+				reg = <0x43f98000 0x4000>;
+				clocks = <&clks 52>;
+				clock-names = "ipg_per";
+				interrupts = <4>;
+				status = "disabled";
+			};
+
+			ssi1: ssi@43fa0000 {
+				compatible = "fsl,imx35-ssi", "fsl,imx21-ssi";
+				reg = <0x43fa0000 0x4000>;
+				interrupts = <11>;
+				clocks = <&clks 68>;
+				dmas = <&sdma 28 0 0>,
+				       <&sdma 29 0 0>;
+				dma-names = "rx", "tx";
+				fsl,fifo-depth = <15>;
+				status = "disabled";
+			};
+
+			spi1: cspi@43fa4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx35-cspi";
+				reg = <0x43fa4000 0x4000>;
+				clocks = <&clks 35 &clks 35>;
+				clock-names = "ipg", "per";
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			iomuxc: iomuxc@43fac000 {
+				compatible = "fsl,imx35-iomuxc";
+				reg = <0x43fac000 0x4000>;
+			};
+		};
+
+		spba: spba-bus@50000000 {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x100000>;
+			ranges;
+
+			uart3: serial@5000c000 {
+				compatible = "fsl,imx35-uart", "fsl,imx21-uart";
+				reg = <0x5000c000 0x4000>;
+				clocks = <&clks 9>, <&clks 72>;
+				clock-names = "ipg", "per";
+				interrupts = <18>;
+				status = "disabled";
+			};
+
+			spi2: cspi@50010000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx35-cspi";
+				reg = <0x50010000 0x4000>;
+				interrupts = <13>;
+				clocks = <&clks 36 &clks 36>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			fec: fec@50038000 {
+				compatible = "fsl,imx35-fec", "fsl,imx27-fec";
+				reg = <0x50038000 0x4000>;
+				clocks = <&clks 46>, <&clks 8>;
+				clock-names = "ipg", "ahb";
+				interrupts = <57>;
+				status = "disabled";
+			};
+		};
+
+		aips2: aips@53f00000 {
+			compatible = "fsl,aips", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x53f00000 0x100000>;
+			ranges;
+
+			clks: ccm@53f80000 {
+				compatible = "fsl,imx35-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <31>;
+				#clock-cells = <1>;
+			};
+
+			gpio3: gpio@53fa4000 {
+				compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
+				reg = <0x53fa4000 0x4000>;
+				interrupts = <56>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			esdhc1: esdhc@53fb4000 {
+				compatible = "fsl,imx35-esdhc";
+				reg = <0x53fb4000 0x4000>;
+				interrupts = <7>;
+				clocks = <&clks 9>, <&clks 8>, <&clks 43>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			esdhc2: esdhc@53fb8000 {
+				compatible = "fsl,imx35-esdhc";
+				reg = <0x53fb8000 0x4000>;
+				interrupts = <8>;
+				clocks = <&clks 9>, <&clks 8>, <&clks 44>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			esdhc3: esdhc@53fbc000 {
+				compatible = "fsl,imx35-esdhc";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <9>;
+				clocks = <&clks 9>, <&clks 8>, <&clks 45>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			audmux: audmux@53fc4000 {
+				compatible = "fsl,imx35-audmux", "fsl,imx31-audmux";
+				reg = <0x53fc4000 0x4000>;
+				status = "disabled";
+			};
+
+			gpio1: gpio@53fcc000 {
+				compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
+				reg = <0x53fcc000 0x4000>;
+				interrupts = <52>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@53fd0000 {
+				compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
+				reg = <0x53fd0000 0x4000>;
+				interrupts = <51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			sdma: sdma@53fd4000 {
+				compatible = "fsl,imx35-sdma";
+				reg = <0x53fd4000 0x4000>;
+				clocks = <&clks 9>, <&clks 65>;
+				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
+				interrupts = <34>;
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx35.bin";
+			};
+
+			wdog: wdog@53fdc000 {
+				compatible = "fsl,imx35-wdt", "fsl,imx21-wdt";
+				reg = <0x53fdc000 0x4000>;
+				clocks = <&clks 74>;
+				clock-names = "";
+				interrupts = <55>;
+			};
+
+			can1: can@53fe4000 {
+				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fe4000 0x1000>;
+				clocks = <&clks 33>;
+				clock-names = "ipg";
+				interrupts = <43>;
+				status = "disabled";
+			};
+
+			can2: can@53fe8000 {
+				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fe8000 0x1000>;
+				clocks = <&clks 34>;
+				clock-names = "ipg";
+				interrupts = <44>;
+				status = "disabled";
+			};
+
+			usbotg: usb@53ff4000 {
+				compatible = "fsl,imx35-usb", "fsl,imx27-usb";
+				reg = <0x53ff4000 0x0200>;
+				interrupts = <37>;
+				clocks = <&clks 9>, <&clks 73>, <&clks 28>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 0>;
+				status = "disabled";
+			};
+
+			usbhost1: usb@53ff4400 {
+				compatible = "fsl,imx35-usb", "fsl,imx27-usb";
+				reg = <0x53ff4400 0x0200>;
+				interrupts = <35>;
+				clocks = <&clks 9>, <&clks 73>, <&clks 28>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc@53ff4600 {
+				#index-cells = <1>;
+				compatible = "fsl,imx35-usbmisc";
+				clocks = <&clks 9>, <&clks 73>, <&clks 28>;
+				clock-names = "ipg", "ahb", "per";
+				reg = <0x53ff4600 0x00f>;
+			};
+		};
+
+		emi@80000000 { /* External Memory Interface */
+			compatible = "fsl,emi", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x40000000>;
+			ranges;
+
+			nfc: nand@bb000000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,imx35-nand", "fsl,imx25-nand";
+				reg = <0xbb000000 0x2000>;
+				clocks = <&clks 29>;
+				clock-names = "";
+				interrupts = <33>;
+				status = "disabled";
+			};
+
+			weim: weim@b8002000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clocks = <&clks 0>;
+				compatible = "fsl,imx35-weim", "fsl,imx27-weim";
+				reg = <0xb8002000 0x1000>;
+				ranges = <
+					0 0 0xa0000000 0x8000000
+					1 0 0xa8000000 0x8000000
+					2 0 0xb0000000 0x2000000
+					3 0 0xb2000000 0x2000000
+					4 0 0xb4000000 0x2000000
+					5 0 0xb6000000 0x2000000
+				>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx50-evk.dts b/arch/arm/boot/dts/imx50-evk.dts
new file mode 100644
index 000000000000..1b22512c91bd
--- /dev/null
+++ b/arch/arm/boot/dts/imx50-evk.dts
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx50.dtsi"
+
+/ {
+	model = "Freescale i.MX50 Evaluation Kit";
+	compatible = "fsl,imx50-evk", "fsl,imx50";
+
+	memory {
+		reg = <0x70000000 0x80000000>;
+	};
+};
+
+&cspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cspi>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio4 11 0>, <&gpio4 13 0>;
+	status = "okay";
+
+	flash: m25p32@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "m25p32", "m25p80";
+		spi-max-frequency = <25000000>;
+		reg = <1>;
+
+		partition@0 {
+			label = "bootloader";
+			reg = <0x0 0x100000>;
+			read-only;
+		};
+
+		partition@100000 {
+			label = "kernel";
+			reg = <0x100000 0x300000>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio4 12 0>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx50-evk {
+		pinctrl_cspi: cspigrp {
+			fsl,pins = <
+				MX50_PAD_CSPI_SCLK__CSPI_SCLK		0x00
+				MX50_PAD_CSPI_MISO__CSPI_MISO		0x00
+				MX50_PAD_CSPI_MOSI__CSPI_MOSI		0x00
+				MX50_PAD_CSPI_SS0__GPIO4_11		0xc4
+				MX50_PAD_ECSPI1_MOSI__CSPI_SS1		0xf4
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX50_PAD_SSI_RXFS__FEC_MDC		0x80
+				MX50_PAD_SSI_RXC__FEC_MDIO		0x80
+				MX50_PAD_DISP_D0__FEC_TX_CLK		0x80
+				MX50_PAD_DISP_D1__FEC_RX_ERR		0x80
+				MX50_PAD_DISP_D2__FEC_RX_DV		0x80
+				MX50_PAD_DISP_D3__FEC_RDATA_1		0x80
+				MX50_PAD_DISP_D4__FEC_RDATA_0		0x80
+				MX50_PAD_DISP_D5__FEC_TX_EN		0x80
+				MX50_PAD_DISP_D6__FEC_TDATA_1		0x80
+				MX50_PAD_DISP_D7__FEC_TDATA_0		0x80
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX50_PAD_UART1_TXD__UART1_TXD_MUX	0x1e4
+				MX50_PAD_UART1_RXD__UART1_RXD_MUX	0x1e4
+				MX50_PAD_UART1_RTS__UART1_RTS		0x1e4
+				MX50_PAD_UART1_CTS__UART1_CTS		0x1e4
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbh2 {
+	status = "okay";
+};
+
+&usbh3 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx50-pinfunc.h b/arch/arm/boot/dts/imx50-pinfunc.h
new file mode 100644
index 000000000000..97e6e7f4ebdd
--- /dev/null
+++ b/arch/arm/boot/dts/imx50-pinfunc.h
@@ -0,0 +1,923 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.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.
+ *
+ */
+
+#ifndef __DTS_IMX50_PINFUNC_H
+#define __DTS_IMX50_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX50_PAD_KEY_COL0__KPP_COL_0				0x020 0x2cc 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL0__GPIO4_0				0x020 0x2cc 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL0__EIM_NANDF_CLE			0x020 0x2cc 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL0__CTI_TRIGIN7				0x020 0x2cc 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL0__USBPHY1_TXREADY			0x020 0x2cc 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW0__KPP_ROW_0				0x024 0x2d0 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW0__GPIO4_1				0x024 0x2d0 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW0__EIM_NANDF_ALE			0x024 0x2d0 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW0__CTI_TRIGIN_ACK7			0x024 0x2d0 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW0__USBPHY1_RXVALID			0x024 0x2d0 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL1__KPP_COL_1				0x028 0x2d4 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL1__GPIO4_2				0x028 0x2d4 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL1__EIM_NANDF_CEN_0			0x028 0x2d4 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL1__CTI_TRIGOUT_ACK6			0x028 0x2d4 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL1__USBPHY1_RXACTIVE			0x028 0x2d4 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW1__KPP_ROW_1				0x02c 0x2d8 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW1__GPIO4_3				0x02c 0x2d8 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW1__EIM_NANDF_CEN_1			0x02c 0x2d8 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW1__CTI_TRIGOUT_ACK7			0x02c 0x2d8 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW1__USBPHY1_RXERROR			0x02c 0x2d8 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL2__KPP_COL_1				0x030 0x2dc 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL2__GPIO4_4				0x030 0x2dc 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL2__EIM_NANDF_CEN_2			0x030 0x2dc 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL2__CTI_TRIGOUT6				0x030 0x2dc 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL2__USBPHY1_SIECLOCK			0x030 0x2dc 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW2__KPP_ROW_2				0x034 0x2e0 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW2__GPIO4_5				0x034 0x2e0 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW2__EIM_NANDF_CEN_3			0x034 0x2e0 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW2__CTI_TRIGOUT7				0x034 0x2e0 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW2__USBPHY1_LINESTATE_0			0x034 0x2e0 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL3__KPP_COL_2				0x038 0x2e4 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL3__GPIO4_6				0x038 0x2e4 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL3__EIM_NANDF_READY0			0x038 0x2e4 0x7b4 0x2 0x0
+#define MX50_PAD_KEY_COL3__SDMA_EXT_EVENT_0			0x038 0x2e4 0x7b8 0x6 0x0
+#define MX50_PAD_KEY_COL3__USBPHY1_LINESTATE_1			0x038 0x2e4 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW3__KPP_ROW_3				0x03c 0x2e8 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW3__GPIO4_7				0x03c 0x2e8 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW3__EIM_NANDF_DQS			0x03c 0x2e8 0x7b0 0x2 0x0
+#define MX50_PAD_KEY_ROW3__SDMA_EXT_EVENT_1			0x03c 0x2e8 0x7bc 0x6 0x0
+#define MX50_PAD_KEY_ROW3__USBPHY1_VBUSVALID			0x03c 0x2e8 0x000 0x7 0x0
+#define MX50_PAD_I2C1_SCL__I2C1_SCL				0x040 0x2ec 0x000 0x0 0x0
+#define MX50_PAD_I2C1_SCL__GPIO6_18				0x040 0x2ec 0x000 0x1 0x0
+#define MX50_PAD_I2C1_SCL__UART2_TXD_MUX			0x040 0x2ec 0x7cc 0x2 0x0
+#define MX50_PAD_I2C1_SDA__I2C1_SDA				0x044 0x2f0 0x000 0x0 0x0
+#define MX50_PAD_I2C1_SDA__GPIO6_19				0x044 0x2f0 0x000 0x1 0x0
+#define MX50_PAD_I2C1_SDA__UART2_RXD_MUX			0x044 0x2f0 0x7cc 0x2 0x1
+#define MX50_PAD_I2C2_SCL__I2C2_SCL				0x048 0x2f4 0x000 0x0 0x0
+#define MX50_PAD_I2C2_SCL__GPIO6_20				0x048 0x2f4 0x000 0x1 0x0
+#define MX50_PAD_I2C2_SCL__UART2_CTS				0x048 0x2f4 0x000 0x2 0x0
+#define MX50_PAD_I2C2_SDA__I2C2_SDA				0x04c 0x2f8 0x000 0x0 0x0
+#define MX50_PAD_I2C2_SDA__GPIO6_21				0x04c 0x2f8 0x000 0x1 0x0
+#define MX50_PAD_I2C2_SDA__UART2_RTS				0x04c 0x2f8 0x7c8 0x2 0x1
+#define MX50_PAD_I2C3_SCL__I2C3_SCL				0x050 0x2fc 0x000 0x0 0x0
+#define MX50_PAD_I2C3_SCL__GPIO6_22				0x050 0x2fc 0x000 0x1 0x0
+#define MX50_PAD_I2C3_SCL__FEC_MDC				0x050 0x2fc 0x000 0x2 0x0
+#define MX50_PAD_I2C3_SCL__GPC_PMIC_RDY				0x050 0x2fc 0x000 0x3 0x0
+#define MX50_PAD_I2C3_SCL__GPT_CAPIN1				0x050 0x2fc 0x000 0x5 0x0
+#define MX50_PAD_I2C3_SCL__OBSERVE_MUX_OBSRV_INT_OUT0		0x050 0x2fc 0x000 0x6 0x0
+#define MX50_PAD_I2C3_SCL__USBOH1_USBOTG_OC			0x050 0x2fc 0x7e8 0x7 0x0
+#define MX50_PAD_I2C3_SDA__I2C3_SDA				0x054 0x300 0x000 0x0 0x0
+#define MX50_PAD_I2C3_SDA__GPIO6_23				0x054 0x300 0x000 0x1 0x0
+#define MX50_PAD_I2C3_SDA__FEC_MDIO				0x054 0x300 0x774 0x2 0x0
+#define MX50_PAD_I2C3_SDA__TZIC_PWRFAIL_INT			0x054 0x300 0x000 0x3 0x0
+#define MX50_PAD_I2C3_SDA__SRTC_ALARM_DEB			0x054 0x300 0x000 0x4 0x0
+#define MX50_PAD_I2C3_SDA__GPT_CAPIN2				0x054 0x300 0x000 0x5 0x0
+#define MX50_PAD_I2C3_SDA__OBSERVE_MUX_OBSRV_INT_OUT1		0x054 0x300 0x000 0x6 0x0
+#define MX50_PAD_I2C3_SDA__USBOH1_USBOTG_PWR			0x054 0x300 0x000 0x7 0x0
+#define MX50_PAD_PWM1__PWM1_PWMO				0x058 0x304 0x000 0x0 0x0
+#define MX50_PAD_PWM1__GPIO6_24					0x058 0x304 0x000 0x1 0x0
+#define MX50_PAD_PWM1__USBOH1_USBOTG_OC				0x058 0x304 0x7e8 0x2 0x1
+#define MX50_PAD_PWM1__GPT_CMPOUT1				0x058 0x304 0x000 0x5 0x0
+#define MX50_PAD_PWM1__OBSERVE_MUX_OBSRV_INT_OUT2		0x058 0x304 0x000 0x6 0x0
+#define MX50_PAD_PWM1__SJC_FAIL					0x058 0x304 0x000 0x7 0x0
+#define MX50_PAD_PWM2__PWM2_PWMO				0x05c 0x308 0x000 0x0 0x0
+#define MX50_PAD_PWM2__GPIO6_25					0x05c 0x308 0x000 0x1 0x0
+#define MX50_PAD_PWM2__USBOH1_USBOTG_PWR			0x05c 0x308 0x000 0x2 0x0
+#define MX50_PAD_PWM2__GPT_CMPOUT2				0x05c 0x308 0x000 0x5 0x0
+#define MX50_PAD_PWM2__OBSERVE_MUX_OBSRV_INT_OUT3		0x05c 0x308 0x000 0x6 0x0
+#define MX50_PAD_PWM2__SRC_ANY_PU_RST				0x05c 0x308 0x000 0x7 0x0
+#define MX50_PAD_OWIRE__OWIRE_LINE				0x060 0x30c 0x000 0x0 0x0
+#define MX50_PAD_OWIRE__GPIO6_26				0x060 0x30c 0x000 0x1 0x0
+#define MX50_PAD_OWIRE__USBOH1_USBH1_OC				0x060 0x30c 0x000 0x2 0x0
+#define MX50_PAD_OWIRE__CCM_SSI_EXT1_CLK			0x060 0x30c 0x000 0x3 0x0
+#define MX50_PAD_OWIRE__EPDC_PWRIRQ				0x060 0x30c 0x000 0x4 0x0
+#define MX50_PAD_OWIRE__GPT_CMPOUT3				0x060 0x30c 0x000 0x5 0x0
+#define MX50_PAD_OWIRE__OBSERVE_MUX_OBSRV_INT_OUT4		0x060 0x30c 0x000 0x6 0x0
+#define MX50_PAD_OWIRE__SJC_JTAG_ACT				0x060 0x30c 0x000 0x7 0x0
+#define MX50_PAD_EPITO__EPIT1_EPITO				0x064 0x310 0x000 0x0 0x0
+#define MX50_PAD_EPITO__GPIO6_27				0x064 0x310 0x000 0x1 0x0
+#define MX50_PAD_EPITO__USBOH1_USBH1_PWR			0x064 0x310 0x000 0x2 0x0
+#define MX50_PAD_EPITO__CCM_SSI_EXT2_CLK			0x064 0x310 0x000 0x3 0x0
+#define MX50_PAD_EPITO__DPLLIP1_TOG_EN				0x064 0x310 0x000 0x4 0x0
+#define MX50_PAD_EPITO__GPT_CLK_IN				0x064 0x310 0x000 0x5 0x0
+#define MX50_PAD_EPITO__PMU_IRQ_B				0x064 0x310 0x000 0x6 0x0
+#define MX50_PAD_EPITO__SJC_DE_B				0x064 0x310 0x000 0x7 0x0
+#define MX50_PAD_WDOG__WDOG1_WDOG_B				0x068 0x314 0x000 0x0 0x0
+#define MX50_PAD_WDOG__GPIO6_28					0x068 0x314 0x000 0x1 0x0
+#define MX50_PAD_WDOG__WDOG1_WDOG_RST_B_DEB			0x068 0x314 0x000 0x2 0x0
+#define MX50_PAD_WDOG__CCM_XTAL32K				0x068 0x314 0x000 0x6 0x0
+#define MX50_PAD_WDOG__SJC_DONE					0x068 0x314 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXFS__AUDMUX_AUD3_TXFS			0x06c 0x318 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXFS__GPIO6_0				0x06c 0x318 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXFS__SRC_BT_FUSE_RSV_1			0x06c 0x318 0x000 0x6 0x0
+#define MX50_PAD_SSI_TXFS__USBPHY1_DATAOUT_8			0x06c 0x318 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXC__AUDMUX_AUD3_TXC			0x070 0x31c 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXC__GPIO6_1				0x070 0x31c 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXC__SRC_BT_FUSE_RSV_0			0x070 0x31c 0x000 0x6 0x0
+#define MX50_PAD_SSI_TXC__USBPHY1_DATAOUT_9			0x070 0x31c 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXD__AUDMUX_AUD3_TXD			0x074 0x320 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXD__GPIO6_2				0x074 0x320 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXD__CSPI_RDY				0x074 0x320 0x6e8 0x4 0x0
+#define MX50_PAD_SSI_TXD__USBPHY1_DATAOUT_10			0x074 0x320 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXD__AUDMUX_AUD3_RXD			0x078 0x324 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXD__GPIO6_3				0x078 0x324 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXD__CSPI_SS3				0x078 0x324 0x6f4 0x4 0x0
+#define MX50_PAD_SSI_RXD__USBPHY1_DATAOUT_11			0x078 0x324 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXFS__AUDMUX_AUD3_RXFS			0x07c 0x328 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXFS__GPIO6_4				0x07c 0x328 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXFS__UART5_TXD_MUX			0x07c 0x328 0x7e4 0x2 0x0
+#define MX50_PAD_SSI_RXFS__EIM_WEIM_D_6				0x07c 0x328 0x804 0x3 0x0
+#define MX50_PAD_SSI_RXFS__CSPI_SS2				0x07c 0x328 0x6f0 0x4 0x0
+#define MX50_PAD_SSI_RXFS__FEC_COL				0x07c 0x328 0x770 0x5 0x0
+#define MX50_PAD_SSI_RXFS__FEC_MDC				0x07c 0x328 0x000 0x6 0x0
+#define MX50_PAD_SSI_RXFS__USBPHY1_DATAOUT_12			0x07c 0x328 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXC__AUDMUX_AUD3_RXC			0x080 0x32c 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXC__GPIO6_5				0x080 0x32c 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXC__UART5_RXD_MUX				0x080 0x32c 0x7e4 0x2 0x1
+#define MX50_PAD_SSI_RXC__EIM_WEIM_D_7				0x080 0x32c 0x808 0x3 0x0
+#define MX50_PAD_SSI_RXC__CSPI_SS1				0x080 0x32c 0x6ec 0x4 0x0
+#define MX50_PAD_SSI_RXC__FEC_RX_CLK				0x080 0x32c 0x780 0x5 0x0
+#define MX50_PAD_SSI_RXC__FEC_MDIO				0x080 0x32c 0x774 0x6 0x1
+#define MX50_PAD_SSI_RXC__USBPHY1_DATAOUT_13			0x080 0x32c 0x000 0x7 0x0
+#define MX50_PAD_UART1_TXD__UART1_TXD_MUX			0x084 0x330 0x7c4 0x0 0x0
+#define MX50_PAD_UART1_TXD__GPIO6_6				0x084 0x330 0x000 0x1 0x0
+#define MX50_PAD_UART1_TXD__USBPHY1_DATAOUT_14			0x084 0x330 0x000 0x7 0x0
+#define MX50_PAD_UART1_RXD__UART1_RXD_MUX			0x088 0x334 0x7c4 0x0 0x1
+#define MX50_PAD_UART1_RXD__GPIO6_7				0x088 0x334 0x000 0x1 0x0
+#define MX50_PAD_UART1_RXD__USBPHY1_DATAOUT_15			0x088 0x334 0x000 0x7 0x0
+#define MX50_PAD_UART1_CTS__UART1_CTS				0x08c 0x338 0x000 0x0 0x0
+#define MX50_PAD_UART1_CTS__GPIO6_8				0x08c 0x338 0x000 0x1 0x0
+#define MX50_PAD_UART1_CTS__UART5_TXD_MUX			0x08c 0x338 0x7e4 0x2 0x2
+#define MX50_PAD_UART1_CTS__ESDHC4_DAT4				0x08c 0x338 0x760 0x4 0x0
+#define MX50_PAD_UART1_CTS__ESDHC4_CMD				0x08c 0x338 0x74c 0x5 0x0
+#define MX50_PAD_UART1_CTS__USBPHY2_DATAOUT_8			0x08c 0x338 0x000 0x7 0x0
+#define MX50_PAD_UART1_RTS__UART1_RTS				0x090 0x33c 0x7c0 0x0 0x3
+#define MX50_PAD_UART1_RTS__GPIO6_9				0x090 0x33c 0x000 0x1 0x0
+#define MX50_PAD_UART1_RTS__UART5_RXD_MUX			0x090 0x33c 0x7e4 0x2 0x3
+#define MX50_PAD_UART1_RTS__ESDHC4_DAT5				0x090 0x33c 0x764 0x4 0x0
+#define MX50_PAD_UART1_RTS__ESDHC4_CLK				0x090 0x33c 0x748 0x5 0x0
+#define MX50_PAD_UART1_RTS__USBPHY2_DATAOUT_9			0x090 0x33c 0x000 0x7 0x0
+#define MX50_PAD_UART2_TXD__UART2_TXD_MUX			0x094 0x340 0x7cc 0x0 0x2
+#define MX50_PAD_UART2_TXD__GPIO6_10				0x094 0x340 0x000 0x1 0x0
+#define MX50_PAD_UART2_TXD__ESDHC4_DAT6				0x094 0x340 0x768 0x4 0x0
+#define MX50_PAD_UART2_TXD__ESDHC4_DAT4				0x094 0x340 0x760 0x5 0x1
+#define MX50_PAD_UART2_TXD__USBPHY2_DATAOUT_10			0x094 0x340 0x000 0x7 0x0
+#define MX50_PAD_UART2_RXD__UART2_RXD_MUX			0x098 0x344 0x7cc 0x0 0x3
+#define MX50_PAD_UART2_RXD__GPIO6_11				0x098 0x344 0x000 0x1 0x0
+#define MX50_PAD_UART2_RXD__ESDHC4_DAT7				0x098 0x344 0x76c 0x4 0x0
+#define MX50_PAD_UART2_RXD__ESDHC4_DAT5				0x098 0x344 0x764 0x5 0x1
+#define MX50_PAD_UART2_RXD__USBPHY2_DATAOUT_11			0x098 0x344 0x000 0x7 0x0
+#define MX50_PAD_UART2_CTS__UART2_CTS				0x09c 0x348 0x000 0x0 0x0
+#define MX50_PAD_UART2_CTS__GPIO6_12				0x09c 0x348 0x000 0x1 0x0
+#define MX50_PAD_UART2_CTS__ESDHC4_CMD				0x09c 0x348 0x74c 0x4 0x1
+#define MX50_PAD_UART2_CTS__ESDHC4_DAT6				0x09c 0x348 0x768 0x5 0x1
+#define MX50_PAD_UART2_CTS__USBPHY2_DATAOUT_12			0x09c 0x348 0x000 0x7 0x0
+#define MX50_PAD_UART2_RTS__UART2_RTS				0x0a0 0x34c 0x7c8 0x0 0x2
+#define MX50_PAD_UART2_RTS__GPIO6_13				0x0a0 0x34c 0x000 0x1 0x0
+#define MX50_PAD_UART2_RTS__ESDHC4_CLK				0x0a0 0x34c 0x748 0x4 0x1
+#define MX50_PAD_UART2_RTS__ESDHC4_DAT7				0x0a0 0x34c 0x76c 0x5 0x1
+#define MX50_PAD_UART2_RTS__USBPHY2_DATAOUT_13			0x0a0 0x34c 0x000 0x7 0x0
+#define MX50_PAD_UART3_TXD__UART3_TXD_MUX			0x0a4 0x350 0x7d4 0x0 0x0
+#define MX50_PAD_UART3_TXD__GPIO6_14				0x0a4 0x350 0x000 0x1 0x0
+#define MX50_PAD_UART3_TXD__ESDHC1_DAT4				0x0a4 0x350 0x000 0x3 0x0
+#define MX50_PAD_UART3_TXD__ESDHC4_DAT0				0x0a4 0x350 0x000 0x4 0x0
+#define MX50_PAD_UART3_TXD__ESDHC2_WP				0x0a4 0x350 0x744 0x5 0x0
+#define MX50_PAD_UART3_TXD__EIM_WEIM_D_12			0x0a4 0x350 0x81c 0x6 0x0
+#define MX50_PAD_UART3_TXD__USBPHY2_DATAOUT_14			0x0a4 0x350 0x000 0x7 0x0
+#define MX50_PAD_UART3_RXD__UART3_RXD_MUX			0x0a8 0x354 0x7d4 0x0 0x1
+#define MX50_PAD_UART3_RXD__GPIO6_15				0x0a8 0x354 0x000 0x1 0x0
+#define MX50_PAD_UART3_RXD__ESDHC1_DAT5				0x0a8 0x354 0x000 0x3 0x0
+#define MX50_PAD_UART3_RXD__ESDHC4_DAT1				0x0a8 0x354 0x754 0x4 0x0
+#define MX50_PAD_UART3_RXD__ESDHC2_CD				0x0a8 0x354 0x740 0x5 0x0
+#define MX50_PAD_UART3_RXD__EIM_WEIM_D_13			0x0a8 0x354 0x820 0x6 0x0
+#define MX50_PAD_UART3_RXD__USBPHY2_DATAOUT_15			0x0a8 0x354 0x000 0x7 0x0
+#define MX50_PAD_UART4_TXD__UART4_TXD_MUX			0x0ac 0x358 0x7dc 0x0 0x0
+#define MX50_PAD_UART4_TXD__GPIO6_16				0x0ac 0x358 0x000 0x1 0x0
+#define MX50_PAD_UART4_TXD__UART3_CTS				0x0ac 0x358 0x7d0 0x2 0x0
+#define MX50_PAD_UART4_TXD__ESDHC1_DAT6				0x0ac 0x358 0x000 0x3 0x0
+#define MX50_PAD_UART4_TXD__ESDHC4_DAT2				0x0ac 0x358 0x758 0x4 0x0
+#define MX50_PAD_UART4_TXD__ESDHC2_LCTL				0x0ac 0x358 0x000 0x5 0x0
+#define MX50_PAD_UART4_TXD__EIM_WEIM_D_14			0x0ac 0x358 0x824 0x6 0x0
+#define MX50_PAD_UART4_RXD__UART4_RXD_MUX			0x0b0 0x35c 0x7dc 0x0 0x1
+#define MX50_PAD_UART4_RXD__GPIO6_17				0x0b0 0x35c 0x000 0x1 0x0
+#define MX50_PAD_UART4_RXD__UART3_RTS				0x0b0 0x35c 0x7d0 0x2 0x1
+#define MX50_PAD_UART4_RXD__ESDHC1_DAT7				0x0b0 0x35c 0x000 0x3 0x0
+#define MX50_PAD_UART4_RXD__ESDHC4_DAT3				0x0b0 0x35c 0x75c 0x4 0x0
+#define MX50_PAD_UART4_RXD__ESDHC1_LCTL				0x0b0 0x35c 0x000 0x5 0x0
+#define MX50_PAD_UART4_RXD__EIM_WEIM_D_15			0x0b0 0x35c 0x828 0x6 0x0
+#define MX50_PAD_CSPI_SCLK__CSPI_SCLK				0x0b4 0x360 0x000 0x0 0x0
+#define MX50_PAD_CSPI_SCLK__GPIO4_8				0x0b4 0x360 0x000 0x1 0x0
+#define MX50_PAD_CSPI_MOSI__CSPI_MOSI				0x0b8 0x364 0x000 0x0 0x0
+#define MX50_PAD_CSPI_MOSI__GPIO4_9				0x0b8 0x364 0x000 0x1 0x0
+#define MX50_PAD_CSPI_MISO__CSPI_MISO				0x0bc 0x368 0x000 0x0 0x0
+#define MX50_PAD_CSPI_MISO__GPIO4_10				0x0bc 0x368 0x000 0x1 0x0
+#define MX50_PAD_CSPI_SS0__CSPI_SS0				0x0c0 0x36c 0x000 0x0 0x0
+#define MX50_PAD_CSPI_SS0__GPIO4_11				0x0c0 0x36c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK			0x0c4 0x370 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_SCLK__GPIO4_12				0x0c4 0x370 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY				0x0c4 0x370 0x6e8 0x2 0x1
+#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY			0x0c4 0x370 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_SCLK__UART3_RTS				0x0c4 0x370 0x7d0 0x4 0x2
+#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE_6			0x0c4 0x370 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_SCLK__EIM_WEIM_D_8			0x0c4 0x370 0x80c 0x7 0x0
+#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI			0x0c8 0x374 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_MOSI__GPIO4_13				0x0c8 0x374 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1				0x0c8 0x374 0x6ec 0x2 0x1
+#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1			0x0c8 0x374 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS				0x0c8 0x374 0x000 0x4 0x0
+#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE_7			0x0c8 0x374 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_MOSI__EIM_WEIM_D_9			0x0c8 0x374 0x810 0x7 0x0
+#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO			0x0cc 0x378 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_MISO__GPIO4_14				0x0cc 0x378 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_MISO__CSPI_SS2				0x0cc 0x378 0x6f0 0x2 0x1
+#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2			0x0cc 0x378 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_MISO__UART4_RTS				0x0cc 0x378 0x7d8 0x4 0x0
+#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE_8			0x0cc 0x378 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_MISO__EIM_WEIM_D_10			0x0cc 0x378 0x814 0x7 0x0
+#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0				0x0d0 0x37c 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_SS0__GPIO4_15				0x0d0 0x37c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SS0__CSPI_SS3				0x0d0 0x37c 0x6f4 0x2 0x1
+#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3				0x0d0 0x37c 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS				0x0d0 0x37c 0x000 0x4 0x0
+#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE_9			0x0d0 0x37c 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_SS0__EIM_WEIM_D_11			0x0d0 0x37c 0x818 0x7 0x0
+#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK			0x0d4 0x380 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_SCLK__GPIO4_16				0x0d4 0x380 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR_RWN			0x0d4 0x380 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY			0x0d4 0x380 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_SCLK__UART5_RTS				0x0d4 0x380 0x7e0 0x4 0x0
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK			0x0d4 0x380 0x000 0x5 0x0
+#define MX50_PAD_ECSPI2_SCLK__EIM_NANDF_CEN_4			0x0d4 0x380 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_SCLK__EIM_WEIM_D_8			0x0d4 0x380 0x80c 0x7 0x1
+#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI			0x0d8 0x384 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_MOSI__GPIO4_17				0x0d8 0x384 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RE_E			0x0d8 0x384 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1			0x0d8 0x384 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS				0x0d8 0x384 0x7e0 0x4 0x1
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_ENABLE			0x0d8 0x384 0x000 0x5 0x0
+#define MX50_PAD_ECSPI2_MOSI__EIM_NANDF_CEN_5			0x0d8 0x384 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_MOSI__EIM_WEIM_D_9			0x0d8 0x384 0x810 0x7 0x1
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO			0x0dc 0x388 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_MISO__GPIO4_18				0x0dc 0x388 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS				0x0dc 0x388 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2			0x0dc 0x388 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD_MUX			0x0dc 0x388 0x7e4 0x4 0x4
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC			0x0dc 0x388 0x73c 0x5 0x0
+#define MX50_PAD_ECSPI2_MISO__EIM_NANDF_CEN_6			0x0dc 0x388 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_MISO__EIM_WEIM_D_10			0x0dc 0x388 0x814 0x7 0x1
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0				0x0e0 0x38c 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_SS0__GPIO4_19				0x0e0 0x38c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS				0x0e0 0x38c 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS3				0x0e0 0x38c 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_SS0__UART5_RXD_MUX			0x0e0 0x38c 0x7e4 0x4 0x5
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC			0x0e0 0x38c 0x6f8 0x5 0x0
+#define MX50_PAD_ECSPI2_SS0__EIM_NANDF_CEN_7			0x0e0 0x38c 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_SS0__EIM_WEIM_D_11			0x0e0 0x38c 0x818 0x7 0x1
+#define MX50_PAD_SD1_CLK__ESDHC1_CLK				0x0e4 0x390 0x000 0x0 0x0
+#define MX50_PAD_SD1_CLK__GPIO5_0				0x0e4 0x390 0x000 0x1 0x0
+#define MX50_PAD_SD1_CLK__CCM_CLKO				0x0e4 0x390 0x000 0x7 0x0
+#define MX50_PAD_SD1_CMD__ESDHC1_CMD				0x0e8 0x394 0x000 0x0 0x0
+#define MX50_PAD_SD1_CMD__GPIO5_1				0x0e8 0x394 0x000 0x1 0x0
+#define MX50_PAD_SD1_CMD__CCM_CLKO2				0x0e8 0x394 0x000 0x7 0x0
+#define MX50_PAD_SD1_D0__ESDHC1_DAT0				0x0ec 0x398 0x000 0x0 0x0
+#define MX50_PAD_SD1_D0__GPIO5_2				0x0ec 0x398 0x000 0x1 0x0
+#define MX50_PAD_SD1_D0__CCM_PLL1_BYP				0x0ec 0x398 0x6dc 0x7 0x0
+#define MX50_PAD_SD1_D1__ESDHC1_DAT1				0x0f0 0x39c 0x000 0x0 0x0
+#define MX50_PAD_SD1_D1__GPIO5_3				0x0f0 0x39c 0x000 0x1 0x0
+#define MX50_PAD_SD1_D1__CCM_PLL2_BYP				0x0f0 0x39c 0x000 0x7 0x0
+#define MX50_PAD_SD1_D2__ESDHC1_DAT2				0x0f4 0x3a0 0x000 0x0 0x0
+#define MX50_PAD_SD1_D2__GPIO5_4				0x0f4 0x3a0 0x000 0x1 0x0
+#define MX50_PAD_SD1_D2__CCM_PLL3_BYP				0x0f4 0x3a0 0x6e4 0x7 0x0
+#define MX50_PAD_SD1_D3__ESDHC1_DAT3				0x0f8 0x3a4 0x000 0x0 0x0
+#define MX50_PAD_SD1_D3__GPIO5_5				0x0f8 0x3a4 0x000 0x1 0x0
+#define MX50_PAD_SD2_CLK__ESDHC2_CLK				0x0fc 0x3a8 0x000 0x0 0x0
+#define MX50_PAD_SD2_CLK__GPIO5_6				0x0fc 0x3a8 0x000 0x1 0x0
+#define MX50_PAD_SD2_CLK__MSHC_SCLK				0x0fc 0x3a8 0x000 0x2 0x0
+#define MX50_PAD_SD2_CMD__ESDHC2_CMD				0x100 0x3ac 0x000 0x0 0x0
+#define MX50_PAD_SD2_CMD__GPIO5_7				0x100 0x3ac 0x000 0x1 0x0
+#define MX50_PAD_SD2_CMD__MSHC_BS				0x100 0x3ac 0x000 0x2 0x0
+#define MX50_PAD_SD2_D0__ESDHC2_DAT0				0x104 0x3b0 0x000 0x0 0x0
+#define MX50_PAD_SD2_D0__GPIO5_8				0x104 0x3b0 0x000 0x1 0x0
+#define MX50_PAD_SD2_D0__MSHC_DATA_0				0x104 0x3b0 0x000 0x2 0x0
+#define MX50_PAD_SD2_D0__KPP_COL_4				0x104 0x3b0 0x790 0x3 0x0
+#define MX50_PAD_SD2_D1__ESDHC2_DAT1				0x108 0x3b4 0x000 0x0 0x0
+#define MX50_PAD_SD2_D1__GPIO5_9				0x108 0x3b4 0x000 0x1 0x0
+#define MX50_PAD_SD2_D1__MSHC_DATA_1				0x108 0x3b4 0x000 0x2 0x0
+#define MX50_PAD_SD2_D1__KPP_ROW_4				0x108 0x3b4 0x7a0 0x3 0x0
+#define MX50_PAD_SD2_D2__ESDHC2_DAT2				0x10c 0x3b8 0x000 0x0 0x0
+#define MX50_PAD_SD2_D2__GPIO5_10				0x10c 0x3b8 0x000 0x1 0x0
+#define MX50_PAD_SD2_D2__MSHC_DATA_2				0x10c 0x3b8 0x000 0x2 0x0
+#define MX50_PAD_SD2_D2__KPP_COL_5				0x10c 0x3b8 0x794 0x3 0x0
+#define MX50_PAD_SD2_D3__ESDHC2_DAT3				0x110 0x3bc 0x000 0x0 0x0
+#define MX50_PAD_SD2_D3__GPIO5_11				0x110 0x3bc 0x000 0x1 0x0
+#define MX50_PAD_SD2_D3__MSHC_DATA_3				0x110 0x3bc 0x000 0x2 0x0
+#define MX50_PAD_SD2_D3__KPP_ROW_5				0x110 0x3bc 0x7a4 0x3 0x0
+#define MX50_PAD_SD2_D4__ESDHC2_DAT4				0x114 0x3c0 0x000 0x0 0x0
+#define MX50_PAD_SD2_D4__GPIO5_12				0x114 0x3c0 0x000 0x1 0x0
+#define MX50_PAD_SD2_D4__AUDMUX_AUD4_RXFS			0x114 0x3c0 0x6d0 0x2 0x0
+#define MX50_PAD_SD2_D4__KPP_COL_6				0x114 0x3c0 0x798 0x3 0x0
+#define MX50_PAD_SD2_D4__EIM_WEIM_D_0				0x114 0x3c0 0x7ec 0x4 0x0
+#define MX50_PAD_SD2_D4__CCM_CCM_OUT_0				0x114 0x3c0 0x000 0x7 0x0
+#define MX50_PAD_SD2_D5__ESDHC2_DAT5				0x118 0x3c4 0x000 0x0 0x0
+#define MX50_PAD_SD2_D5__GPIO5_13				0x118 0x3c4 0x000 0x1 0x0
+#define MX50_PAD_SD2_D5__AUDMUX_AUD4_RXC			0x118 0x3c4 0x6cc 0x2 0x0
+#define MX50_PAD_SD2_D5__KPP_ROW_6				0x118 0x3c4 0x7a8 0x3 0x0
+#define MX50_PAD_SD2_D5__EIM_WEIM_D_1				0x118 0x3c4 0x7f0 0x4 0x0
+#define MX50_PAD_SD2_D5__CCM_CCM_OUT_1				0x118 0x3c4 0x000 0x7 0x0
+#define MX50_PAD_SD2_D6__ESDHC2_DAT6				0x11c 0x3c8 0x000 0x0 0x0
+#define MX50_PAD_SD2_D6__GPIO5_14				0x11c 0x3c8 0x000 0x1 0x0
+#define MX50_PAD_SD2_D6__AUDMUX_AUD4_RXD			0x11c 0x3c8 0x6c4 0x2 0x0
+#define MX50_PAD_SD2_D6__KPP_COL_7				0x11c 0x3c8 0x79c 0x3 0x0
+#define MX50_PAD_SD2_D6__EIM_WEIM_D_2				0x11c 0x3c8 0x7f4 0x4 0x0
+#define MX50_PAD_SD2_D6__CCM_CCM_OUT_2				0x11c 0x3c8 0x000 0x7 0x0
+#define MX50_PAD_SD2_D7__ESDHC2_DAT7				0x120 0x3cc 0x000 0x0 0x0
+#define MX50_PAD_SD2_D7__GPIO5_15				0x120 0x3cc 0x000 0x1 0x0
+#define MX50_PAD_SD2_D7__AUDMUX_AUD4_TXFS			0x120 0x3cc 0x6d8 0x2 0x0
+#define MX50_PAD_SD2_D7__KPP_ROW_7				0x120 0x3cc 0x7ac 0x3 0x0
+#define MX50_PAD_SD2_D7__EIM_WEIM_D_3				0x120 0x3cc 0x7f8 0x4 0x0
+#define MX50_PAD_SD2_D7__CCM_STOP				0x120 0x3cc 0x000 0x7 0x0
+#define MX50_PAD_SD2_WP__ESDHC2_WP				0x124 0x3d0 0x744 0x0 0x1
+#define MX50_PAD_SD2_WP__GPIO5_16				0x124 0x3d0 0x000 0x1 0x0
+#define MX50_PAD_SD2_WP__AUDMUX_AUD4_TXD			0x124 0x3d0 0x6c8 0x2 0x0
+#define MX50_PAD_SD2_WP__EIM_WEIM_D_4				0x124 0x3d0 0x7fc 0x4 0x0
+#define MX50_PAD_SD2_WP__CCM_WAIT				0x124 0x3d0 0x000 0x7 0x0
+#define MX50_PAD_SD2_CD__ESDHC2_CD				0x128 0x3d4 0x740 0x0 0x1
+#define MX50_PAD_SD2_CD__GPIO5_17				0x128 0x3d4 0x000 0x1 0x0
+#define MX50_PAD_SD2_CD__AUDMUX_AUD4_TXC			0x128 0x3d4 0x6d4 0x2 0x0
+#define MX50_PAD_SD2_CD__EIM_WEIM_D_5				0x128 0x3d4 0x800 0x4 0x0
+#define MX50_PAD_SD2_CD__CCM_REF_EN_B				0x128 0x3d4 0x000 0x7 0x0
+#define MX50_PAD_DISP_D0__ELCDIF_DAT_0				0x12c 0x40c 0x6fc 0x0 0x0
+#define MX50_PAD_DISP_D0__GPIO2_0				0x12c 0x40c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D0__FEC_TX_CLK				0x12c 0x40c 0x78c 0x2 0x0
+#define MX50_PAD_DISP_D0__EIM_WEIM_A_16				0x12c 0x40c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D0__SDMA_DEBUG_PC_0			0x12c 0x40c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D0__USBPHY1_VSTATUS_0			0x12c 0x40c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D1__ELCDIF_DAT_1				0x130 0x410 0x700 0x0 0x0
+#define MX50_PAD_DISP_D1__GPIO2_1				0x130 0x410 0x000 0x1 0x0
+#define MX50_PAD_DISP_D1__FEC_RX_ERR				0x130 0x410 0x788 0x2 0x0
+#define MX50_PAD_DISP_D1__EIM_WEIM_A_17				0x130 0x410 0x000 0x3 0x0
+#define MX50_PAD_DISP_D1__SDMA_DEBUG_PC_1			0x130 0x410 0x000 0x6 0x0
+#define MX50_PAD_DISP_D1__USBPHY1_VSTATUS_1			0x130 0x410 0x000 0x7 0x0
+#define MX50_PAD_DISP_D2__ELCDIF_DAT_2				0x134 0x414 0x704 0x0 0x0
+#define MX50_PAD_DISP_D2__GPIO2_2				0x134 0x414 0x000 0x1 0x0
+#define MX50_PAD_DISP_D2__FEC_RX_DV				0x134 0x414 0x784 0x2 0x0
+#define MX50_PAD_DISP_D2__EIM_WEIM_A_18				0x134 0x414 0x000 0x3 0x0
+#define MX50_PAD_DISP_D2__SDMA_DEBUG_PC_2			0x134 0x414 0x000 0x6 0x0
+#define MX50_PAD_DISP_D2__USBPHY1_VSTATUS_2			0x134 0x414 0x000 0x7 0x0
+#define MX50_PAD_DISP_D3__ELCDIF_DAT_3				0x138 0x418 0x708 0x0 0x0
+#define MX50_PAD_DISP_D3__GPIO2_3				0x138 0x418 0x000 0x1 0x0
+#define MX50_PAD_DISP_D3__FEC_RDATA_1				0x138 0x418 0x77c 0x2 0x0
+#define MX50_PAD_DISP_D3__EIM_WEIM_A_19				0x138 0x418 0x000 0x3 0x0
+#define MX50_PAD_DISP_D3__FEC_COL				0x138 0x418 0x770 0x4 0x1
+#define MX50_PAD_DISP_D3__SDMA_DEBUG_PC_3			0x138 0x418 0x000 0x6 0x0
+#define MX50_PAD_DISP_D3__USBPHY1_VSTATUS_3			0x138 0x418 0x000 0x7 0x0
+#define MX50_PAD_DISP_D4__ELCDIF_DAT_4				0x13c 0x41c 0x70c 0x0 0x0
+#define MX50_PAD_DISP_D4__GPIO2_4				0x13c 0x41c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D4__FEC_RDATA_0				0x13c 0x41c 0x778 0x2 0x0
+#define MX50_PAD_DISP_D4__EIM_WEIM_A_20				0x13c 0x41c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D4__SDMA_DEBUG_PC_4			0x13c 0x41c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D4__USBPHY1_VSTATUS_4			0x13c 0x41c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D5__ELCDIF_DAT_5				0x140 0x420 0x710 0x0 0x0
+#define MX50_PAD_DISP_D5__GPIO2_5				0x140 0x420 0x000 0x1 0x0
+#define MX50_PAD_DISP_D5__FEC_TX_EN				0x140 0x420 0x000 0x2 0x0
+#define MX50_PAD_DISP_D5__EIM_WEIM_A_21				0x140 0x420 0x000 0x3 0x0
+#define MX50_PAD_DISP_D5__SDMA_DEBUG_PC_5			0x140 0x420 0x000 0x6 0x0
+#define MX50_PAD_DISP_D5__USBPHY1_VSTATUS_5			0x140 0x420 0x000 0x7 0x0
+#define MX50_PAD_DISP_D6__ELCDIF_DAT_6				0x144 0x424 0x714 0x0 0x0
+#define MX50_PAD_DISP_D6__GPIO2_6				0x144 0x424 0x000 0x1 0x0
+#define MX50_PAD_DISP_D6__FEC_TDATA_1				0x144 0x424 0x000 0x2 0x0
+#define MX50_PAD_DISP_D6__EIM_WEIM_A_22				0x144 0x424 0x000 0x3 0x0
+#define MX50_PAD_DISP_D6__FEC_RX_CLK				0x144 0x424 0x780 0x4 0x1
+#define MX50_PAD_DISP_D6__SDMA_DEBUG_PC_6			0x144 0x424 0x000 0x6 0x0
+#define MX50_PAD_DISP_D6__USBPHY1_VSTATUS_6			0x144 0x424 0x000 0x7 0x0
+#define MX50_PAD_DISP_D7__ELCDIF_DAT_7				0x148 0x428 0x718 0x0 0x0
+#define MX50_PAD_DISP_D7__GPIO2_7				0x148 0x428 0x000 0x1 0x0
+#define MX50_PAD_DISP_D7__FEC_TDATA_0				0x148 0x428 0x000 0x2 0x0
+#define MX50_PAD_DISP_D7__EIM_WEIM_A_23				0x148 0x428 0x000 0x3 0x0
+#define MX50_PAD_DISP_D7__SDMA_DEBUG_PC_7			0x148 0x428 0x000 0x6 0x0
+#define MX50_PAD_DISP_D7__USBPHY1_VSTATUS_7			0x148 0x428 0x000 0x7 0x0
+#define MX50_PAD_DISP_WR__ELCDIF_WR_RWN				0x14c 0x42c 0x000 0x0 0x0
+#define MX50_PAD_DISP_WR__GPIO2_16				0x14c 0x42c 0x000 0x1 0x0
+#define MX50_PAD_DISP_WR__ELCDIF_DOTCLK				0x14c 0x42c 0x000 0x2 0x0
+#define MX50_PAD_DISP_WR__EIM_WEIM_A_24				0x14c 0x42c 0x000 0x3 0x0
+#define MX50_PAD_DISP_WR__SDMA_DEBUG_PC_8			0x14c 0x42c 0x000 0x6 0x0
+#define MX50_PAD_DISP_WR__USBPHY1_AVALID			0x14c 0x42c 0x000 0x7 0x0
+#define MX50_PAD_DISP_RD__ELCDIF_RD_E				0x150 0x430 0x000 0x0 0x0
+#define MX50_PAD_DISP_RD__GPIO2_19				0x150 0x430 0x000 0x1 0x0
+#define MX50_PAD_DISP_RD__ELCDIF_ENABLE				0x150 0x430 0x000 0x2 0x0
+#define MX50_PAD_DISP_RD__EIM_WEIM_A_25				0x150 0x430 0x000 0x3 0x0
+#define MX50_PAD_DISP_RD__SDMA_DEBUG_PC_9			0x150 0x430 0x000 0x6 0x0
+#define MX50_PAD_DISP_RD__USBPHY1_BVALID			0x150 0x430 0x000 0x7 0x0
+#define MX50_PAD_DISP_RS__ELCDIF_RS				0x154 0x434 0x000 0x0 0x0
+#define MX50_PAD_DISP_RS__GPIO2_17				0x154 0x434 0x000 0x1 0x0
+#define MX50_PAD_DISP_RS__ELCDIF_VSYNC				0x154 0x434 0x73c 0x2 0x1
+#define MX50_PAD_DISP_RS__EIM_WEIM_A_26				0x154 0x434 0x000 0x3 0x0
+#define MX50_PAD_DISP_RS__SDMA_DEBUG_PC_10			0x154 0x434 0x000 0x6 0x0
+#define MX50_PAD_DISP_RS__USBPHY1_ENDSESSION			0x154 0x434 0x000 0x7 0x0
+#define MX50_PAD_DISP_CS__ELCDIF_CS				0x158 0x438 0x000 0x0 0x0
+#define MX50_PAD_DISP_CS__GPIO2_21				0x158 0x438 0x000 0x1 0x0
+#define MX50_PAD_DISP_CS__ELCDIF_HSYNC				0x158 0x438 0x6f8 0x2 0x1
+#define MX50_PAD_DISP_CS__EIM_WEIM_A_27				0x158 0x438 0x000 0x3 0x0
+#define MX50_PAD_DISP_CS__EIM_WEIM_CS_3				0x158 0x438 0x000 0x4 0x0
+#define MX50_PAD_DISP_CS__SDMA_DEBUG_PC_11			0x158 0x438 0x000 0x6 0x0
+#define MX50_PAD_DISP_CS__USBPHY1_IDDIG				0x158 0x438 0x000 0x7 0x0
+#define MX50_PAD_DISP_BUSY__ELCDIF_BUSY				0x15c 0x43c 0x6f8 0x0 0x2
+#define MX50_PAD_DISP_BUSY__GPIO2_18				0x15c 0x43c 0x000 0x1 0x0
+#define MX50_PAD_DISP_BUSY__EIM_WEIM_CS_3			0x15c 0x43c 0x000 0x4 0x0
+#define MX50_PAD_DISP_BUSY__SDMA_DEBUG_PC_12			0x15c 0x43c 0x000 0x6 0x0
+#define MX50_PAD_DISP_BUSY__USBPHY2_HOSTDISCONNECT		0x15c 0x43c 0x000 0x7 0x0
+#define MX50_PAD_DISP_RESET__ELCDIF_RESET			0x160 0x440 0x000 0x0 0x0
+#define MX50_PAD_DISP_RESET__GPIO2_20				0x160 0x440 0x000 0x1 0x0
+#define MX50_PAD_DISP_RESET__EIM_WEIM_CS_3			0x160 0x440 0x000 0x4 0x0
+#define MX50_PAD_DISP_RESET__SDMA_DEBUG_PC_13			0x160 0x440 0x000 0x6 0x0
+#define MX50_PAD_DISP_RESET__USBPHY2_BISTOK			0x160 0x440 0x000 0x7 0x0
+#define MX50_PAD_SD3_CMD__ESDHC3_CMD				0x164 0x444 0x000 0x0 0x0
+#define MX50_PAD_SD3_CMD__GPIO5_18				0x164 0x444 0x000 0x1 0x0
+#define MX50_PAD_SD3_CMD__EIM_NANDF_WRN				0x164 0x444 0x000 0x2 0x0
+#define MX50_PAD_SD3_CMD__SSP_CMD				0x164 0x444 0x000 0x3 0x0
+#define MX50_PAD_SD3_CLK__ESDHC3_CLK				0x168 0x448 0x000 0x0 0x0
+#define MX50_PAD_SD3_CLK__GPIO5_19				0x168 0x448 0x000 0x1 0x0
+#define MX50_PAD_SD3_CLK__EIM_NANDF_RDN				0x168 0x448 0x000 0x2 0x0
+#define MX50_PAD_SD3_CLK__SSP_CLK				0x168 0x448 0x000 0x3 0x0
+#define MX50_PAD_SD3_D0__ESDHC3_DAT0				0x16c 0x44c 0x000 0x0 0x0
+#define MX50_PAD_SD3_D0__GPIO5_20				0x16c 0x44c 0x000 0x1 0x0
+#define MX50_PAD_SD3_D0__EIM_NANDF_D_4				0x16c 0x44c 0x000 0x2 0x0
+#define MX50_PAD_SD3_D0__SSP_D0					0x16c 0x44c 0x000 0x3 0x0
+#define MX50_PAD_SD3_D0__CCM_PLL1_BYP				0x16c 0x44c 0x6dc 0x7 0x1
+#define MX50_PAD_SD3_D1__ESDHC3_DAT1				0x170 0x450 0x000 0x0 0x0
+#define MX50_PAD_SD3_D1__GPIO5_21				0x170 0x450 0x000 0x1 0x0
+#define MX50_PAD_SD3_D1__EIM_NANDF_D_5				0x170 0x450 0x000 0x2 0x0
+#define MX50_PAD_SD3_D1__SSP_D1					0x170 0x450 0x000 0x3 0x0
+#define MX50_PAD_SD3_D1__CCM_PLL2_BYP				0x170 0x450 0x000 0x7 0x0
+#define MX50_PAD_SD3_D2__ESDHC3_DAT2				0x174 0x454 0x000 0x0 0x0
+#define MX50_PAD_SD3_D2__GPIO5_22				0x174 0x454 0x000 0x1 0x0
+#define MX50_PAD_SD3_D2__EIM_NANDF_D_6				0x174 0x454 0x000 0x2 0x0
+#define MX50_PAD_SD3_D2__SSP_D2					0x174 0x454 0x000 0x3 0x0
+#define MX50_PAD_SD3_D2__CCM_PLL3_BYP				0x174 0x454 0x6e4 0x7 0x1
+#define MX50_PAD_SD3_D3__ESDHC3_DAT3				0x178 0x458 0x000 0x0 0x0
+#define MX50_PAD_SD3_D3__GPIO5_23				0x178 0x458 0x000 0x1 0x0
+#define MX50_PAD_SD3_D3__EIM_NANDF_D_7				0x178 0x458 0x000 0x2 0x0
+#define MX50_PAD_SD3_D3__SSP_D3					0x178 0x458 0x000 0x3 0x0
+#define MX50_PAD_SD3_D4__ESDHC3_DAT4				0x17c 0x45c 0x000 0x0 0x0
+#define MX50_PAD_SD3_D4__GPIO5_24				0x17c 0x45c 0x000 0x1 0x0
+#define MX50_PAD_SD3_D4__EIM_NANDF_D_0				0x17c 0x45c 0x000 0x2 0x0
+#define MX50_PAD_SD3_D4__SSP_D4					0x17c 0x45c 0x000 0x3 0x0
+#define MX50_PAD_SD3_D5__ESDHC3_DAT5				0x180 0x460 0x000 0x0 0x0
+#define MX50_PAD_SD3_D5__GPIO5_25				0x180 0x460 0x000 0x1 0x0
+#define MX50_PAD_SD3_D5__EIM_NANDF_D_1				0x180 0x460 0x000 0x2 0x0
+#define MX50_PAD_SD3_D5__SSP_D5					0x180 0x460 0x000 0x3 0x0
+#define MX50_PAD_SD3_D6__ESDHC3_DAT6				0x184 0x464 0x000 0x0 0x0
+#define MX50_PAD_SD3_D6__GPIO5_26				0x184 0x464 0x000 0x1 0x0
+#define MX50_PAD_SD3_D6__EIM_NANDF_D_2				0x184 0x464 0x000 0x2 0x0
+#define MX50_PAD_SD3_D6__SSP_D6					0x184 0x464 0x000 0x3 0x0
+#define MX50_PAD_SD3_D7__ESDHC3_DAT7				0x188 0x468 0x000 0x0 0x0
+#define MX50_PAD_SD3_D7__GPIO5_27				0x188 0x468 0x000 0x1 0x0
+#define MX50_PAD_SD3_D7__EIM_NANDF_D_3				0x188 0x468 0x000 0x2 0x0
+#define MX50_PAD_SD3_D7__SSP_D7					0x188 0x468 0x000 0x3 0x0
+#define MX50_PAD_SD3_WP__ESDHC3_WP				0x18c 0x46C 0x000 0x0 0x0
+#define MX50_PAD_SD3_WP__GPIO5_28				0x18c 0x46C 0x000 0x1 0x0
+#define MX50_PAD_SD3_WP__EIM_NANDF_RESETN			0x18c 0x46C 0x000 0x2 0x0
+#define MX50_PAD_SD3_WP__SSP_CD					0x18c 0x46C 0x000 0x3 0x0
+#define MX50_PAD_SD3_WP__ESDHC4_LCTL				0x18c 0x46C 0x000 0x4 0x0
+#define MX50_PAD_SD3_WP__EIM_WEIM_CS_3				0x18c 0x46C 0x000 0x5 0x0
+#define MX50_PAD_DISP_D8__ELCDIF_DAT_8				0x190 0x470 0x71c 0x0 0x0
+#define MX50_PAD_DISP_D8__GPIO2_8				0x190 0x470 0x000 0x1 0x0
+#define MX50_PAD_DISP_D8__EIM_NANDF_CLE				0x190 0x470 0x000 0x2 0x0
+#define MX50_PAD_DISP_D8__ESDHC1_LCTL				0x190 0x470 0x000 0x3 0x0
+#define MX50_PAD_DISP_D8__ESDHC4_CMD				0x190 0x470 0x74c 0x4 0x2
+#define MX50_PAD_DISP_D8__KPP_COL_4				0x190 0x470 0x790 0x5 0x1
+#define MX50_PAD_DISP_D8__FEC_TX_CLK				0x190 0x470 0x78c 0x6 0x1
+#define MX50_PAD_DISP_D8__USBPHY1_DATAOUT_0			0x190 0x470 0x000 0x7 0x0
+#define MX50_PAD_DISP_D9__ELCDIF_DAT_9				0x194 0x474 0x720 0x0 0x0
+#define MX50_PAD_DISP_D9__GPIO2_9				0x194 0x474 0x000 0x1 0x0
+#define MX50_PAD_DISP_D9__EIM_NANDF_ALE				0x194 0x474 0x000 0x2 0x0
+#define MX50_PAD_DISP_D9__ESDHC2_LCTL				0x194 0x474 0x000 0x3 0x0
+#define MX50_PAD_DISP_D9__ESDHC4_CLK				0x194 0x474 0x748 0x4 0x2
+#define MX50_PAD_DISP_D9__KPP_ROW_4				0x194 0x474 0x7a0 0x5 0x1
+#define MX50_PAD_DISP_D9__FEC_RX_ER				0x194 0x474 0x788 0x6 0x1
+#define MX50_PAD_DISP_D9__USBPHY1_DATAOUT_1			0x194 0x474 0x000 0x7 0x0
+#define MX50_PAD_DISP_D10__ELCDIF_DAT_10			0x198 0x478 0x724 0x0 0x0
+#define MX50_PAD_DISP_D10__GPIO2_10				0x198 0x478 0x000 0x1 0x0
+#define MX50_PAD_DISP_D10__EIM_NANDF_CEN_0			0x198 0x478 0x000 0x2 0x0
+#define MX50_PAD_DISP_D10__ESDHC3_LCTL				0x198 0x478 0x000 0x3 0x0
+#define MX50_PAD_DISP_D10__ESDHC4_DAT0				0x198 0x478 0x000 0x4 0x0
+#define MX50_PAD_DISP_D10__KPP_COL_5				0x198 0x478 0x794 0x5 0x1
+#define MX50_PAD_DISP_D10__FEC_RX_DV				0x198 0x478 0x784 0x6 0x1
+#define MX50_PAD_DISP_D10__USBPHY1_DATAOUT_2			0x198 0x478 0x000 0x7 0x0
+#define MX50_PAD_DISP_D11__ELCDIF_DAT_11			0x19c 0x47c 0x728 0x0 0x0
+#define MX50_PAD_DISP_D11__GPIO2_11				0x19c 0x47c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D11__EIM_NANDF_CEN_1			0x19c 0x47c 0x000 0x2 0x0
+#define MX50_PAD_DISP_D11__ESDHC4_DAT1				0x19c 0x47c 0x754 0x4 0x1
+#define MX50_PAD_DISP_D11__KPP_ROW_5				0x19c 0x47c 0x7a4 0x5 0x1
+#define MX50_PAD_DISP_D11__FEC_RDATA_1				0x19c 0x47c 0x77c 0x6 0x1
+#define MX50_PAD_DISP_D11__USBPHY1_DATAOUT_3			0x19c 0x47c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D12__ELCDIF_DAT_12			0x1a0 0x480 0x72c 0x0 0x0
+#define MX50_PAD_DISP_D12__GPIO2_12				0x1a0 0x480 0x000 0x1 0x0
+#define MX50_PAD_DISP_D12__EIM_NANDF_CEN_2			0x1a0 0x480 0x000 0x2 0x0
+#define MX50_PAD_DISP_D12__ESDHC1_CD				0x1a0 0x480 0x000 0x3 0x0
+#define MX50_PAD_DISP_D12__ESDHC4_DAT2				0x1a0 0x480 0x758 0x4 0x1
+#define MX50_PAD_DISP_D12__KPP_COL_6				0x1a0 0x480 0x798 0x5 0x1
+#define MX50_PAD_DISP_D12__FEC_RDATA_0				0x1a0 0x480 0x778 0x6 0x1
+#define MX50_PAD_DISP_D12__USBPHY1_DATAOUT_4			0x1a0 0x480 0x000 0x7 0x0
+#define MX50_PAD_DISP_D13__ELCDIF_DAT_13			0x1a4 0x484 0x730 0x0 0x0
+#define MX50_PAD_DISP_D13__GPIO2_13				0x1a4 0x484 0x000 0x1 0x0
+#define MX50_PAD_DISP_D13__EIM_NANDF_CEN_3			0x1a4 0x484 0x000 0x2 0x0
+#define MX50_PAD_DISP_D13__ESDHC3_CD				0x1a4 0x484 0x000 0x3 0x0
+#define MX50_PAD_DISP_D13__ESDHC4_DAT3				0x1a4 0x484 0x75c 0x4 0x1
+#define MX50_PAD_DISP_D13__KPP_ROW_6				0x1a4 0x484 0x7a8 0x5 0x1
+#define MX50_PAD_DISP_D13__FEC_TX_EN				0x1a4 0x484 0x000 0x6 0x0
+#define MX50_PAD_DISP_D13__USBPHY1_DATAOUT_5			0x1a4 0x484 0x000 0x7 0x0
+#define MX50_PAD_DISP_D14__ELCDIF_DAT_14			0x1a8 0x488 0x734 0x0 0x0
+#define MX50_PAD_DISP_D14__GPIO2_14				0x1a8 0x488 0x000 0x1 0x0
+#define MX50_PAD_DISP_D14__EIM_NANDF_READY0			0x1a8 0x488 0x7b4 0x2 0x1
+#define MX50_PAD_DISP_D14__ESDHC1_WP				0x1a8 0x488 0x000 0x3 0x0
+#define MX50_PAD_DISP_D14__ESDHC4_WP				0x1a8 0x488 0x000 0x4 0x0
+#define MX50_PAD_DISP_D14__KPP_COL_7				0x1a8 0x488 0x79c 0x5 0x1
+#define MX50_PAD_DISP_D14__FEC_TDATA_1				0x1a8 0x488 0x000 0x6 0x0
+#define MX50_PAD_DISP_D14__USBPHY1_DATAOUT_6			0x1a8 0x488 0x000 0x7 0x0
+#define MX50_PAD_DISP_D15__ELCDIF_DAT_15			0x1ac 0x48c 0x738 0x0 0x0
+#define MX50_PAD_DISP_D15__GPIO2_15				0x1ac 0x48c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D15__EIM_NANDF_DQS			0x1ac 0x48c 0x7b0 0x2 0x1
+#define MX50_PAD_DISP_D15__ESDHC3_RST				0x1ac 0x48c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D15__ESDHC4_CD				0x1ac 0x48c 0x000 0x4 0x0
+#define MX50_PAD_DISP_D15__KPP_ROW_7				0x1ac 0x48c 0x7ac 0x5 0x1
+#define MX50_PAD_DISP_D15__FEC_TDATA_0				0x1ac 0x48c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D15__USBPHY1_DATAOUT_7			0x1ac 0x48c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D0__EPDC_SDDO_0				0x1b0 0x54c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D0__GPIO3_0				0x1b0 0x54c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D0__EIM_WEIM_D_0				0x1b0 0x54c 0x7ec 0x2 0x1
+#define MX50_PAD_EPDC_D0__ELCDIF_RS				0x1b0 0x54c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D0__ELCDIF_DOTCLK				0x1b0 0x54c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D0__SDMA_DEBUG_EVT_CHN_LINES_0		0x1b0 0x54c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D0__USBPHY2_DATAOUT_0			0x1b0 0x54c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D1__EPDC_SDDO_1				0x1b4 0x550 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D1__GPIO3_1				0x1b4 0x550 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D1__EIM_WEIM_D_1				0x1b4 0x550 0x7f0 0x2 0x1
+#define MX50_PAD_EPDC_D1__ELCDIF_CS				0x1b4 0x550 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D1__ELCDIF_ENABLE				0x1b4 0x550 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D1__SDMA_DEBUG_EVT_CHN_LINES_1		0x1b4 0x550 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D1__USBPHY2_DATAOUT_1			0x1b4 0x550 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D2__EPDC_SDDO_2				0x1b8 0x554 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D2__GPIO3_2				0x1b8 0x554 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D2__EIM_WEIM_D_2				0x1b8 0x554 0x7f4 0x2 0x1
+#define MX50_PAD_EPDC_D2__ELCDIF_WR_RWN				0x1b8 0x554 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC				0x1b8 0x554 0x73c 0x4 0x2
+#define MX50_PAD_EPDC_D2__SDMA_DEBUG_EVT_CHN_LINES_2		0x1b8 0x554 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D2__USBPHY2_DATAOUT_2			0x1b8 0x554 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D3__EPDC_SDDO_3				0x1bc 0x558 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D3__GPIO3_3				0x1bc 0x558 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D3__EIM_WEIM_D_3				0x1bc 0x558 0x7f8 0x2 0x1
+#define MX50_PAD_EPDC_D3__ELCDIF_RD_E				0x1bc 0x558 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC				0x1bc 0x558 0x6f8 0x4 0x3
+#define MX50_PAD_EPDC_D3__SDMA_DEBUG_EVT_CHN_LINES_3		0x1bc 0x558 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D3__USBPHY2_DATAOUT_3			0x1bc 0x558 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D4__EPDC_SDDO_4				0x1c0 0x55c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D4__GPIO3_4				0x1c0 0x55c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D4__EIM_WEIM_D_4				0x1c0 0x55c 0x7fc 0x2 0x1
+#define MX50_PAD_EPDC_D4__SDMA_DEBUG_EVT_CHN_LINES_4		0x1c0 0x55c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D4__USBPHY2_DATAOUT_4			0x1c0 0x55c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D5__EPDC_SDDO_5				0x1c4 0x560 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D5__GPIO3_5				0x1c4 0x560 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D5__EIM_WEIM_D_5				0x1c4 0x560 0x800 0x2 0x1
+#define MX50_PAD_EPDC_D5__SDMA_DEBUG_EVT_CHN_LINES_5		0x1c4 0x560 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D5__USBPHY2_DATAOUT_5			0x1c4 0x560 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D6__EPDC_SDDO_6				0x1c8 0x564 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D6__GPIO3_6				0x1c8 0x564 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D6__EIM_WEIM_D_6				0x1c8 0x564 0x804 0x2 0x1
+#define MX50_PAD_EPDC_D6__SDMA_DEBUG_EVT_CHN_LINES_6		0x1c8 0x564 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D6__USBPHY2_DATAOUT_6			0x1c8 0x564 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D7__EPDC_SDDO_7				0x1cc 0x568 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D7__GPIO3_7				0x1cc 0x568 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D7__EIM_WEIM_D_7				0x1cc 0x568 0x808 0x2 0x1
+#define MX50_PAD_EPDC_D7__SDMA_DEBUG_EVT_CHN_LINES_7		0x1cc 0x568 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D7__USBPHY2_DATAOUT_7			0x1cc 0x568 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D8__EPDC_SDDO_8				0x1d0 0x56c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D8__GPIO3_8				0x1d0 0x56c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D8__EIM_WEIM_D_8				0x1d0 0x56c 0x80c 0x2 0x2
+#define MX50_PAD_EPDC_D8__ELCDIF_DAT_24				0x1d0 0x56c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D8__SDMA_DEBUG_MATCHED_DMBUS		0x1d0 0x56c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D8__USBPHY2_VSTATUS_0			0x1d0 0x56c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D9__EPDC_SDDO_9				0x1d4 0x570 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D9__GPIO3_9				0x1d4 0x570 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D9__EIM_WEIM_D_9				0x1d4 0x570 0x810 0x2 0x2
+#define MX50_PAD_EPDC_D9__ELCDIF_DAT_25				0x1d4 0x570 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D9__SDMA_DEBUG_EVENT_CHANNEL_SEL		0x1d4 0x570 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D9__USBPHY2_VSTATUS_1			0x1d4 0x570 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D10__EPDC_SDDO_10				0x1d8 0x574 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D10__GPIO3_10				0x1d8 0x574 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D10__EIM_WEIM_D_10			0x1d8 0x574 0x814 0x2 0x2
+#define MX50_PAD_EPDC_D10__ELCDIF_DAT_26			0x1d8 0x574 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D10__SDMA_DEBUG_EVENT_CHANNEL_0		0x1d8 0x574 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D10__USBPHY2_VSTATUS_2			0x1d8 0x574 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D11__EPDC_SDDO_11				0x1dc 0x578 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D11__GPIO3_11				0x1dc 0x578 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D11__EIM_WEIM_D_11			0x1dc 0x578 0x818 0x2 0x2
+#define MX50_PAD_EPDC_D11__ELCDIF_DAT_27			0x1dc 0x578 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D11__SDMA_DEBUG_EVENT_CHANNEL_1		0x1dc 0x578 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D11__USBPHY2_VSTATUS_3			0x1dc 0x578 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D12__EPDC_SDDO_12				0x1e0 0x57c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D12__GPIO3_12				0x1e0 0x57c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D12__EIM_WEIM_D_12			0x1e0 0x57c 0x81c 0x2 0x1
+#define MX50_PAD_EPDC_D12__ELCDIF_DAT_28			0x1e0 0x57c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D12__SDMA_DEBUG_EVENT_CHANNEL_2		0x1e0 0x57c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D12__USBPHY2_VSTATUS_4			0x1e0 0x57c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D13__EPDC_SDDO_13				0x1e4 0x580 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D13__GPIO3_13				0x1e4 0x580 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D13__EIM_WEIM_D_13			0x1e4 0x580 0x820 0x2 0x1
+#define MX50_PAD_EPDC_D13__ELCDIF_DAT_29			0x1e4 0x580 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D13__SDMA_DEBUG_EVENT_CHANNEL_3		0x1e4 0x580 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D13__USBPHY2_VSTATUS_5			0x1e4 0x580 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D14__EPDC_SDDO_14				0x1e8 0x584 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D14__GPIO3_14				0x1e8 0x584 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D14__EIM_WEIM_D_14			0x1e8 0x584 0x824 0x2 0x1
+#define MX50_PAD_EPDC_D14__ELCDIF_DAT_30			0x1e8 0x584 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D14__AUDMUX_AUD6_TXD			0x1e8 0x584 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D14__SDMA_DEBUG_EVENT_CHANNEL_4		0x1e8 0x584 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D14__USBPHY2_VSTATUS_6			0x1e8 0x584 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D15__EPDC_SDDO_15				0x1ec 0x588 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D15__GPIO3_15				0x1ec 0x588 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D15__EIM_WEIM_D_15			0x1ec 0x588 0x828 0x2 0x1
+#define MX50_PAD_EPDC_D15__ELCDIF_DAT_31			0x1ec 0x588 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D15__AUDMUX_AUD6_TXC			0x1ec 0x588 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D15__SDMA_DEBUG_EVENT_CHANNEL_5		0x1ec 0x588 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D15__USBPHY2_VSTATUS_7			0x1ec 0x588 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK				0x1f0 0x58c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDCLK__GPIO3_16				0x1f0 0x58c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDCLK__EIM_WEIM_D_16			0x1f0 0x58c 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDCLK__ELCDIF_DAT_16			0x1f0 0x58c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDCLK__AUDMUX_AUD6_TXFS			0x1f0 0x58c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDCLK__SDMA_DEBUG_CORE_STATE_0		0x1f0 0x58c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDCLK__USBPHY2_BISTOK			0x1f0 0x58c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDSP__EPCD_GDSP				0x1f4 0x590 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDSP__GPIO3_17				0x1f4 0x590 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDSP__EIM_WEIM_D_17			0x1f4 0x590 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDSP__ELCDIF_DAT_17			0x1f4 0x590 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDSP__AUDMUX_AUD6_RXD			0x1f4 0x590 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDSP__SDMA_DEBUG_CORE_STATE_1		0x1f4 0x590 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDSP__USBPHY2_BVALID			0x1f4 0x590 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDOE__EPCD_GDOE				0x1f8 0x594 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDOE__GPIO3_18				0x1f8 0x594 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDOE__EIM_WEIM_D_18			0x1f8 0x594 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDOE__ELCDIF_DAT_18			0x1f8 0x594 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDOE__AUDMUX_AUD6_RXC			0x1f8 0x594 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDOE__SDMA_DEBUG_CORE_STATE_2		0x1f8 0x594 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDOE__USBPHY2_ENDSESSION			0x1f8 0x594 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDRL__EPCD_GDRL				0x1fc 0x598 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDRL__GPIO3_19				0x1fc 0x598 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDRL__EIM_WEIM_D_19			0x1f8 0x598 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDRL__ELCDIF_DAT_19			0x1fc 0x598 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDRL__AUDMUX_AUD6_RXFS			0x1fc 0x598 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDRL__SDMA_DEBUG_CORE_STATE_3		0x1fc 0x598 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDRL__USBPHY2_IDDIG			0x1fc 0x598 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDCLK__EPCD_SDCLK				0x200 0x59c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCLK__GPIO3_20				0x200 0x59c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCLK__EIM_WEIM_D_20			0x200 0x59c 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDCLK__ELCDIF_DAT_20			0x200 0x59c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDCLK__AUDMUX_AUD5_TXD			0x200 0x59c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDCLK__SDMA_DEBUG_BUS_DEVICE_0		0x200 0x59c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDCLK__USBPHY2_HOSTDISCONNECT		0x200 0x59c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOEZ__EPCD_SDOEZ				0x204 0x5a0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOEZ__GPIO3_21				0x204 0x5a0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOEZ__EIM_WEIM_D_21			0x204 0x5a0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOEZ__ELCDIF_DAT_21			0x204 0x5a0 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOEZ__AUDMUX_AUD5_TXC			0x204 0x5a0 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOEZ__SDMA_DEBUG_BUS_DEVICE_1		0x204 0x5a0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOEZ__USBPHY2_TXREADY			0x204 0x5a0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOED__EPCD_SDOED				0x208 0x5a4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOED__GPIO3_22				0x208 0x5a4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOED__EIM_WEIM_D_22			0x208 0x5a4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOED__ELCDIF_DAT_22			0x208 0x5a4 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOED__AUDMUX_AUD5_TXFS			0x208 0x5a4 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOED__SDMA_DEBUG_BUS_DEVICE_2		0x208 0x5a4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOED__USBPHY2_RXVALID			0x208 0x5a4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOE__EPCD_SDOE				0x20c 0x5a8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOE__GPIO3_23				0x20c 0x5a8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOE__EIM_WEIM_D_23			0x20c 0x5a8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOE__ELCDIF_DAT_23			0x20c 0x5a8 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOE__AUDMUX_AUD5_RXD			0x20c 0x5a8 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOE__SDMA_DEBUG_BUS_DEVICE_3		0x20c 0x5a8 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOE__USBPHY2_RXACTIVE			0x20c 0x5a8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDLE__EPCD_SDLE				0x210 0x5ac 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDLE__GPIO3_24				0x210 0x5ac 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDLE__EIM_WEIM_D_24			0x210 0x5ac 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDLE__ELCDIF_DAT_8			0x210 0x5ac 0x71c 0x3 0x1
+#define MX50_PAD_EPDC_SDLE__AUDMUX_AUD5_RXC			0x210 0x5ac 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDLE__SDMA_DEBUG_BUS_DEVICE_4		0x210 0x5ac 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDLE__USBPHY2_RXERROR			0x210 0x5ac 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDCLKN__EPCD_SDCLKN			0x214 0x5b0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCLKN__GPIO3_25				0x214 0x5b0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCLKN__EIM_WEIM_D_25			0x214 0x5b0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDCLKN__ELCDIF_DAT_9			0x214 0x5b0 0x720 0x3 0x1
+#define MX50_PAD_EPDC_SDCLKN__AUDMUX_AUD5_RXFS			0x214 0x5b0 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDCLKN__SDMA_DEBUG_BUS_ERROR		0x214 0x5b0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDCLKN__USBPHY2_SIECLOCK			0x214 0x5b0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDSHR__EPCD_SDSHR				0x218 0x5b4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDSHR__GPIO3_26				0x218 0x5b4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDSHR__EIM_WEIM_D_26			0x218 0x5b4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDSHR__ELCDIF_DAT_10			0x218 0x5b4 0x724 0x3 0x1
+#define MX50_PAD_EPDC_SDSHR__AUDMUX_AUD4_TXD			0x218 0x5b4 0x6c8 0x4 0x1
+#define MX50_PAD_EPDC_SDSHR__SDMA_DEBUG_BUS_RWB			0x218 0x5b4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDSHR__USBPHY2_LINESTATE_0		0x218 0x5b4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCOM__EPCD_PWRCOM			0x21c 0x5b8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCOM__GPIO3_27				0x21c 0x5b8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCOM__EIM_WEIM_D_27			0x21c 0x5b8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCOM__ELCDIF_DAT_11			0x21c 0x5b8 0x728 0x3 0x1
+#define MX50_PAD_EPDC_PWRCOM__AUDMUX_AUD4_TXC			0x21c 0x5b8 0x6d4 0x4 0x1
+#define MX50_PAD_EPDC_PWRCOM__SDMA_DEBUG_CORE_RUN		0x21c 0x5b8 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCOM__USBPHY2_LINESTATE_1		0x21c 0x5b8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRSTAT__EPCD_PWRSTAT			0x220 0x5bc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRSTAT__GPIO3_28				0x220 0x5bc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRSTAT__EIM_WEIM_D_28			0x220 0x5bc 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_DAT_12			0x220 0x5bc 0x72c 0x3 0x1
+#define MX50_PAD_EPDC_PWRSTAT__AUDMUX_AUD4_TXFS			0x220 0x5bc 0x6d8 0x4 0x1
+#define MX50_PAD_EPDC_PWRSTAT__SDMA_DEBUG_MODE			0x220 0x5bc 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRSTAT__USBPHY2_VBUSVALID		0x220 0x5bc 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__EPCD_PWRCTRL0			0x224 0x5c0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__GPIO3_29			0x224 0x5c0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__EIM_WEIM_D_29			0x224 0x5c0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_DAT_13			0x224 0x5c0 0x730 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL0__AUDMUX_AUD4_RXD			0x224 0x5c0 0x6c4 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL0__SDMA_DEBUG_RTBUFFER_WRITE	0x224 0x5c0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__USBPHY2_AVALID			0x224 0x5c0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__EPCD_PWRCTRL1			0x228 0x5c4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__GPIO3_30			0x228 0x5c4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__EIM_WEIM_D_30			0x228 0x5c4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_DAT_14			0x228 0x5c4 0x734 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL1__AUDMUX_AUD4_RXC			0x228 0x5c4 0x6cc 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL1__SDMA_DEBUG_YIELD		0x228 0x5c4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__USBPHY1_ONBIST			0x228 0x5c4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__EPCD_PWRCTRL2			0x22c 0x5c8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__GPIO3_31			0x22c 0x5c8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__EIM_WEIM_D_31			0x22c 0x5c8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_DAT_15			0x22c 0x5c8 0x738 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__AUDMUX_AUD4_RXFS		0x22c 0x5c8 0x6d0 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT_EVENT_0		0x22c 0x5c8 0x7b8 0x6 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__USBPHY2_ONBIST			0x22c 0x5c8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__EPCD_PWRCTRL3			0x230 0x5cc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__GPIO4_20			0x230 0x5cc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__EIM_WEIM_EB_2			0x230 0x5cc 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT_EVENT_1		0x230 0x5cc 0x7bc 0x6 0x1
+#define MX50_PAD_EPDC_PWRCTRL3__USBPHY1_BISTOK			0x230 0x5cc 0x000 0x7 0x0
+#define MX50_PAD_EPDC_VCOM0__EPCD_VCOM_0			0x234 0x5d0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_VCOM0__GPIO4_21				0x234 0x5d0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_VCOM0__EIM_WEIM_EB_3			0x234 0x5d0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_VCOM0__USBPHY2_BISTOK			0x234 0x5d0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_VCOM1__EPCD_VCOM_1			0x238 0x5d4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_VCOM1__GPIO4_22				0x238 0x5d4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_VCOM1__EIM_WEIM_CS_3			0x238 0x5d4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_BDR0__EPCD_BDR_0				0x23c 0x5d8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_BDR0__GPIO4_23				0x23c 0x5d8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_BDR0__ELCDIF_DAT_7			0x23c 0x5d8 0x718 0x3 0x1
+#define MX50_PAD_EPDC_BDR1__EPCD_BDR_1				0x240 0x5dc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_BDR1__GPIO4_24				0x240 0x5dc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_BDR1__ELCDIF_DAT_6			0x240 0x5dc 0x714 0x3 0x1
+#define MX50_PAD_EPDC_SDCE0__EPCD_SDCE_0			0x244 0x5e0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE0__GPIO4_25				0x244 0x5e0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE0__ELCDIF_DAT_5			0x244 0x5e0 0x710 0x3 0x1
+#define MX50_PAD_EPDC_SDCE1__EPCD_SDCE_1			0x248 0x5e4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE1__GPIO4_26				0x248 0x5e4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE1__ELCDIF_DAT_4			0x248 0x5e4 0x70c 0x3 0x0
+#define MX50_PAD_EPDC_SDCE2__EPCD_SDCE_2			0x24c 0x5e8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE2__GPIO4_27				0x24c 0x5e8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT_3			0x24c 0x5e8 0x708 0x3 0x1
+#define MX50_PAD_EPDC_SDCE3__EPCD_SDCE_3			0x250 0x5ec 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE3__GPIO4_28				0x250 0x5ec 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE3__ELCDIF_DAT_2			0x250 0x5ec 0x704 0x3 0x1
+#define MX50_PAD_EPDC_SDCE4__EPCD_SDCE_4			0x254 0x5f0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE4__GPIO4_29				0x254 0x5f0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE4__ELCDIF_DAT_1			0x254 0x5f0 0x700 0x3 0x1
+#define MX50_PAD_EPDC_SDCE5__EPCD_SDCE_5			0x258 0x5f4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE5__GPIO4_30				0x258 0x5f4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE5__ELCDIF_DAT_0			0x258 0x5f4 0x6fc 0x3 0x1
+#define MX50_PAD_EIM_DA0__EIM_WEIM_A_0				0x25c 0x5f8 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA0__GPIO1_0				0x25c 0x5f8 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA0__KPP_COL_4				0x25c 0x5f8 0x790 0x3 0x2
+#define MX50_PAD_EIM_DA0__TPIU_TRACE_0				0x25c 0x5f8 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA0__SRC_BT_CFG1_0				0x25c 0x5f8 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA1__EIM_WEIM_A_1				0x260 0x5fc 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA1__GPIO1_1				0x260 0x5fc 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA1__KPP_ROW_4				0x260 0x5fc 0x7a0 0x3 0x2
+#define MX50_PAD_EIM_DA1__TPIU_TRACE_1				0x260 0x5fc 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA1__SRC_BT_CFG1_1				0x260 0x5fc 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA2__EIM_WEIM_A_2				0x264 0x600 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA2__GPIO1_2				0x264 0x600 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA2__KPP_COL_5				0x264 0x600 0x794 0x3 0x2
+#define MX50_PAD_EIM_DA2__TPIU_TRACE_2				0x264 0x600 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA2__SRC_BT_CFG1_2				0x264 0x600 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA3__EIM_WEIM_A_3				0x268 0x604 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA3__GPIO1_3				0x268 0x604 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA3__KPP_ROW_5				0x268 0x604 0x7a4 0x3 0x2
+#define MX50_PAD_EIM_DA3__TPIU_TRACE_3				0x268 0x604 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA3__SRC_BT_CFG1_3				0x268 0x604 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA4__EIM_WEIM_A_4				0x26c 0x608 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA4__GPIO1_4				0x26c 0x608 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA4__KPP_COL_6				0x26c 0x608 0x798 0x3 0x2
+#define MX50_PAD_EIM_DA4__TPIU_TRACE_4				0x26c 0x608 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA4__SRC_BT_CFG1_4				0x26c 0x608 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA5__EIM_WEIM_A_5				0x270 0x60c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA5__GPIO1_5				0x270 0x60c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA5__KPP_ROW_6				0x270 0x60c 0x7a8 0x3 0x2
+#define MX50_PAD_EIM_DA5__TPIU_TRACE_5				0x270 0x60c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA5__SRC_BT_CFG1_5				0x270 0x60c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA6__EIM_WEIM_A_6				0x274 0x610 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA6__GPIO1_6				0x274 0x610 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA6__KPP_COL_7				0x274 0x610 0x79c 0x3 0x2
+#define MX50_PAD_EIM_DA6__TPIU_TRACE_6				0x274 0x610 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA6__SRC_BT_CFG1_6				0x274 0x610 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA7__EIM_WEIM_A_7				0x278 0x614 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA7__GPIO1_7				0x278 0x614 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA7__KPP_ROW_7				0x278 0x614 0x7ac 0x3 0x2
+#define MX50_PAD_EIM_DA7__TPIU_TRACE_7				0x278 0x614 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA7__SRC_BT_CFG1_7				0x278 0x614 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA8__EIM_WEIM_A_8				0x27c 0x618 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA8__GPIO1_8				0x27c 0x618 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA8__EIM_NANDF_CLE				0x27c 0x618 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA8__TPIU_TRACE_8				0x27c 0x618 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA8__SRC_BT_CFG2_0				0x27c 0x618 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA9__EIM_WEIM_A_9				0x280 0x61c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA9__GPIO1_9				0x280 0x61c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA9__EIM_NANDF_ALE				0x280 0x61c 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA9__TPIU_TRACE_9				0x280 0x61c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA9__SRC_BT_CFG2_1				0x280 0x61c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA10__EIM_WEIM_A_10			0x284 0x620 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA10__GPIO1_10				0x284 0x620 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA10__EIM_NANDF_CEN_0			0x284 0x620 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA10__TPIU_TRACE_10			0x284 0x620 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA10__SRC_BT_CFG2_2			0x284 0x620 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA11__EIM_WEIM_A_11			0x288 0x624 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA11__GPIO1_11				0x288 0x624 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA11__EIM_NANDF_CEN_1			0x288 0x624 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA11__TPIU_TRACE_11			0x288 0x624 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA11__SRC_BT_CFG2_3			0x288 0x624 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA12__EIM_WEIM_A_12			0x28c 0x628 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA12__GPIO1_12				0x28c 0x628 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA12__EIM_NANDF_CEN_2			0x28c 0x628 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA12__EPDC_SDCE_6				0x28c 0x628 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA12__TPIU_TRACE_12			0x28c 0x628 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA12__SRC_BT_CFG2_4			0x28c 0x628 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA13__EIM_WEIM_A_13			0x290 0x62c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA13__GPIO1_13				0x290 0x62c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA13__EIM_NANDF_CEN_3			0x290 0x62c 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA13__EPDC_SDCE_7				0x290 0x62c 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA13__TPIU_TRACE_13			0x290 0x62c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA13__SRC_BT_CFG2_5			0x290 0x62c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA14__EIM_WEIM_A_14			0x294 0x630 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA14__GPIO1_14				0x294 0x630 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA14__EIM_NANDF_READY0			0x294 0x630 0x7b4 0x2 0x2
+#define MX50_PAD_EIM_DA14__EPDC_SDCE_8				0x294 0x630 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA14__TPIU_TRACE_14			0x294 0x630 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA14__SRC_BT_CFG2_6			0x294 0x630 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA15__EIM_WEIM_A_15			0x298 0x634 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA15__GPIO1_15				0x298 0x634 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA15__EIM_NANDF_DQS			0x298 0x634 0x7b0 0x2 0x2
+#define MX50_PAD_EIM_DA15__EPDC_SDCE_9				0x298 0x634 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA15__TPIU_TRACE_15			0x298 0x634 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA15__SRC_BT_CFG2_7			0x298 0x634 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS2__EIM_WEIM_CS_2				0x29c 0x638 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS2__GPIO1_16				0x29c 0x638 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS2__EIM_WEIM_A_27				0x29c 0x638 0x000 0x2 0x0
+#define MX50_PAD_EIM_CS2__TPIU_TRCLK				0x29c 0x638 0x000 0x6 0x0
+#define MX50_PAD_EIM_CS2__SRC_BT_CFG3_0				0x29c 0x638 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS1__EIM_WEIM_CS_1				0x2a0 0x63c 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS1__GPIO1_17				0x2a0 0x63c 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS1__TPIU_TRCTL				0x2a0 0x63c 0x000 0x6 0x0
+#define MX50_PAD_EIM_CS1__SRC_BT_CFG3_1				0x2a0 0x63c 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS0__EIM_WEIM_CS_0				0x2a4 0x640 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS0__GPIO1_18				0x2a4 0x640 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS0__SRC_BT_CFG3_2				0x2a4 0x640 0x000 0x7 0x0
+#define MX50_PAD_EIM_EB0__EIM_WEIM_EB_0				0x2a8 0x644 0x000 0x0 0x0
+#define MX50_PAD_EIM_EB0__GPIO1_19				0x2a8 0x644 0x000 0x1 0x0
+#define MX50_PAD_EIM_EB0__SRC_BT_CFG3_3				0x2a8 0x644 0x000 0x7 0x0
+#define MX50_PAD_EIM_EB1__EIM_WEIM_EB_1				0x2ac 0x648 0x000 0x0 0x0
+#define MX50_PAD_EIM_EB1__GPIO1_20				0x2ac 0x648 0x000 0x1 0x0
+#define MX50_PAD_EIM_EB1__SRC_BT_CFG3_4				0x2ac 0x648 0x000 0x7 0x0
+#define MX50_PAD_EIM_WAIT__EIM_WEIM_WAIT			0x2b0 0x64c 0x000 0x0 0x0
+#define MX50_PAD_EIM_WAIT__GPIO1_21				0x2b0 0x64c 0x000 0x1 0x0
+#define MX50_PAD_EIM_WAIT__EIM_WEIM_DTACK_B			0x2b0 0x64c 0x000 0x2 0x0
+#define MX50_PAD_EIM_WAIT__SRC_BT_CFG3_5			0x2b0 0x64c 0x000 0x7 0x0
+#define MX50_PAD_EIM_BCLK__EIM_WEIM_BCLK			0x2b4 0x650 0x000 0x0 0x0
+#define MX50_PAD_EIM_BCLK__GPIO1_22				0x2b4 0x650 0x000 0x1 0x0
+#define MX50_PAD_EIM_BCLK__SRC_BT_CFG3_6			0x2b4 0x650 0x000 0x7 0x0
+#define MX50_PAD_EIM_RDY__EIM_WEIM_RDY				0x2b8 0x654 0x000 0x0 0x0
+#define MX50_PAD_EIM_RDY__GPIO1_23				0x2b8 0x654 0x000 0x1 0x0
+#define MX50_PAD_EIM_RDY__SRC_BT_CFG3_7				0x2b8 0x654 0x000 0x7 0x0
+#define MX50_PAD_EIM_OE__EIM_WEIM_OE				0x2bc 0x658 0x000 0x0 0x0
+#define MX50_PAD_EIM_OE__GPIO1_24				0x2bc 0x658 0x000 0x1 0x0
+#define MX50_PAD_EIM_OE__INT_BOOT				0x2bc 0x658 0x000 0x7 0x0
+#define MX50_PAD_EIM_RW__EIM_WEIM_RW				0x2c0 0x65c 0x000 0x0 0x0
+#define MX50_PAD_EIM_RW__GPIO1_25				0x2c0 0x65c 0x000 0x1 0x0
+#define MX50_PAD_EIM_RW__SYSTEM_RST				0x2c0 0x65c 0x000 0x7 0x0
+#define MX50_PAD_EIM_LBA__EIM_WEIM_LBA				0x2c4 0x660 0x000 0x0 0x0
+#define MX50_PAD_EIM_LBA__GPIO1_26				0x2c4 0x660 0x000 0x1 0x0
+#define MX50_PAD_EIM_LBA__TESTER_ACK				0x2c4 0x660 0x000 0x7 0x0
+#define MX50_PAD_EIM_CRE__EIM_WEIM_CRE				0x2c8 0x664 0x000 0x0 0x0
+#define MX50_PAD_EIM_CRE__GPIO1_27				0x2c8 0x664 0x000 0x1 0x0
+
+#endif /* __DTS_IMX50_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
new file mode 100644
index 000000000000..0c75fe3deb35
--- /dev/null
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "skeleton.dtsi"
+#include "imx50-pinfunc.h"
+#include <dt-bindings/clock/imx5-clock.h>
+
+/ {
+	aliases {
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		gpio5 = &gpio6;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a8";
+			reg = <0x0>;
+		};
+	};
+
+	tzic: tz-interrupt-controller@0fffc000 {
+		compatible = "fsl,imx50-tzic", "fsl,imx53-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x0fffc000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@50000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x10000000>;
+			ranges;
+
+			spba@50000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x50000000 0x40000>;
+				ranges;
+
+				esdhc1: esdhc@50004000 {
+					compatible = "fsl,imx50-esdhc";
+					reg = <0x50004000 0x4000>;
+					interrupts = <1>;
+					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				esdhc2: esdhc@50008000 {
+					compatible = "fsl,imx50-esdhc";
+					reg = <0x50008000 0x4000>;
+					interrupts = <2>;
+					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				uart3: serial@5000c000 {
+					compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+					reg = <0x5000c000 0x4000>;
+					interrupts = <33>;
+					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+					         <&clks IMX5_CLK_UART3_PER_GATE>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi1: ecspi@50010000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi";
+					reg = <0x50010000 0x4000>;
+					interrupts = <36>;
+					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ssi2: ssi@50014000 {
+					compatible = "fsl,imx50-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
+					reg = <0x50014000 0x4000>;
+					interrupts = <30>;
+					clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
+					status = "disabled";
+				};
+
+				esdhc3: esdhc@50020000 {
+					compatible = "fsl,imx50-esdhc";
+					reg = <0x50020000 0x4000>;
+					interrupts = <3>;
+					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				esdhc4: esdhc@50024000 {
+					compatible = "fsl,imx50-esdhc";
+					reg = <0x50024000 0x4000>;
+					interrupts = <4>;
+					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+			};
+
+			usbotg: usb@53f80000 {
+				compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+				reg = <0x53f80000 0x0200>;
+				interrupts = <18>;
+				clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
+				status = "disabled";
+			};
+
+			usbh1: usb@53f80200 {
+				compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+				reg = <0x53f80200 0x0200>;
+				interrupts = <14>;
+				clocks = <&clks IMX5_CLK_USB_PHY2_GATE>;
+				status = "disabled";
+			};
+
+			usbh2: usb@53f80400 {
+				compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+				reg = <0x53f80400 0x0200>;
+				interrupts = <16>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+				status = "disabled";
+			};
+
+			usbh3: usb@53f80600 {
+				compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+				reg = <0x53f80600 0x0200>;
+				interrupts = <17>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+				status = "disabled";
+			};
+
+			gpio1: gpio@53f84000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@53f88000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@53f8c000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@53f90000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			wdog1: wdog@53f98000 {
+				compatible = "fsl,imx50-wdt", "fsl,imx21-wdt";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <58>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
+			};
+
+			gpt: timer@53fa0000 {
+				compatible = "fsl,imx50-gpt", "fsl,imx31-gpt";
+				reg = <0x53fa0000 0x4000>;
+				interrupts = <39>;
+				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+				         <&clks IMX5_CLK_GPT_HF_GATE>;
+				clock-names = "ipg", "per";
+			};
+
+			iomuxc: iomuxc@53fa8000 {
+				compatible = "fsl,imx50-iomuxc", "fsl,imx53-iomuxc";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			gpr: iomuxc-gpr@53fa8000 {
+				compatible = "fsl,imx50-iomuxc-gpr", "syscon";
+				reg = <0x53fa8000 0xc>;
+			};
+
+			pwm1: pwm@53fb4000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb4000 0x4000>;
+				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM1_HF_GATE>;
+				clock-names = "ipg", "per";
+				interrupts = <61>;
+			};
+
+			pwm2: pwm@53fb8000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb8000 0x4000>;
+				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM2_HF_GATE>;
+				clock-names = "ipg", "per";
+				interrupts = <94>;
+			};
+
+			uart1: serial@53fbc000 {
+				compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <31>;
+				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+				         <&clks IMX5_CLK_UART1_PER_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@53fc0000 {
+				compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+				         <&clks IMX5_CLK_UART2_PER_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			src: src@53fd0000 {
+				compatible = "fsl,imx50-src", "fsl,imx51-src";
+				reg = <0x53fd0000 0x4000>;
+				#reset-cells = <1>;
+			};
+
+			clks: ccm@53fd4000{
+				compatible = "fsl,imx50-ccm";
+				reg = <0x53fd4000 0x4000>;
+				interrupts = <0 71 0x04 0 72 0x04>;
+				#clock-cells = <1>;
+			};
+
+			gpio5: gpio@53fdc000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53fdc000 0x4000>;
+				interrupts = <103 104>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio6: gpio@53fe0000 {
+				compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+				reg = <0x53fe0000 0x4000>;
+				interrupts = <105 106>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			i2c3: i2c@53fec000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+				reg = <0x53fec000 0x4000>;
+				interrupts = <64>;
+				clocks = <&clks IMX5_CLK_I2C3_GATE>;
+				status = "disabled";
+			};
+
+			uart4: serial@53ff0000 {
+				compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <13>;
+				clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
+				         <&clks IMX5_CLK_UART4_PER_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x60000000 0x10000000>;
+			ranges;
+
+			uart5: serial@63f90000 {
+				compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+				reg = <0x63f90000 0x4000>;
+				interrupts = <86>;
+				clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
+				         <&clks IMX5_CLK_UART5_PER_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			owire: owire@63fa4000 {
+				compatible = "fsl,imx50-owire", "fsl,imx21-owire";
+				reg = <0x63fa4000 0x4000>;
+				clocks = <&clks IMX5_CLK_OWIRE_GATE>;
+				status = "disabled";
+			};
+
+			ecspi2: ecspi@63fac000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi";
+				reg = <0x63fac000 0x4000>;
+				interrupts = <37>;
+				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			sdma: sdma@63fb0000 {
+				compatible = "fsl,imx50-sdma", "fsl,imx35-sdma";
+				reg = <0x63fb0000 0x4000>;
+				interrupts = <6>;
+				clocks = <&clks IMX5_CLK_SDMA_GATE>,
+				         <&clks IMX5_CLK_SDMA_GATE>;
+				clock-names = "ipg", "ahb";
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx50.bin";
+			};
+
+			cspi: cspi@63fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx50-cspi", "fsl,imx35-cspi";
+				reg = <0x63fc0000 0x4000>;
+				interrupts = <38>;
+				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@63fc4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+				reg = <0x63fc4000 0x4000>;
+				interrupts = <63>;
+				clocks = <&clks IMX5_CLK_I2C2_GATE>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@63fc8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+				reg = <0x63fc8000 0x4000>;
+				interrupts = <62>;
+				clocks = <&clks IMX5_CLK_I2C1_GATE>;
+				status = "disabled";
+			};
+
+			ssi1: ssi@63fcc000 {
+				compatible = "fsl,imx50-ssi", "fsl,imx51-ssi",
+							"fsl,imx21-ssi";
+				reg = <0x63fcc000 0x4000>;
+				interrupts = <29>;
+				clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+				fsl,fifo-depth = <15>;
+				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
+				status = "disabled";
+			};
+
+			audmux: audmux@63fd0000 {
+				compatible = "fsl,imx50-audmux", "fsl,imx31-audmux";
+				reg = <0x63fd0000 0x4000>;
+				status = "disabled";
+			};
+
+			fec: ethernet@63fec000 {
+				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+				reg = <0x63fec000 0x4000>;
+				interrupts = <87>;
+				clocks = <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>;
+				clock-names = "ipg", "ahb", "ptp";
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51-apf51.dts b/arch/arm/boot/dts/imx51-apf51.dts
index b3606993f2e8..e88b2a6be079 100644
--- a/arch/arm/boot/dts/imx51-apf51.dts
+++ b/arch/arm/boot/dts/imx51-apf51.dts
@@ -34,13 +34,47 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_2>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "mii";
-	phy-reset-gpios = <&gpio3 0 0>;
+	phy-reset-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>;
 	phy-reset-duration = <1>;
 	status = "okay";
 };
 
+&iomuxc {
+	imx51-apf51 {
+		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_uart3: uart3grp {
+			fsl,pins = <
+				MX51_PAD_UART3_RXD__UART3_RXD		0x1c5
+				MX51_PAD_UART3_TXD__UART3_TXD		0x1c5
+			>;
+		};
+	};
+};
+
 &nfc {
 	nand-bus-width = <8>;
 	nand-ecc-mode = "hw";
@@ -50,6 +84,6 @@
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_2>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts
index 5a7f552786a1..c29cfa927c98 100644
--- a/arch/arm/boot/dts/imx51-apf51dev.dts
+++ b/arch/arm/boot/dts/imx51-apf51dev.dts
@@ -21,7 +21,7 @@
 		crtcs = <&ipu 0>;
 		interface-pix-fmt = "bgr666";
 		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+		pinctrl-0 = <&pinctrl_ipu_disp1>;
 
 		display-timings {
 			lw700 {
@@ -48,7 +48,7 @@
 
 		user-key {
 			label = "user";
-			gpios = <&gpio1 3 0>;
+			gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
 			linux,code = <256>; /* BTN_0 */
 		};
 	};
@@ -58,7 +58,7 @@
 
 		user {
 			label = "Heartbeat";
-			gpios = <&gpio1 2 0>;
+			gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
@@ -66,31 +66,33 @@
 
 &ecspi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+		   <&gpio4 25 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 };
 
 &ecspi2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi2_1>;
+	pinctrl-0 = <&pinctrl_ecspi2>;
 	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio3 28 1>, <&gpio3 27 1>;
+	cs-gpios = <&gpio3 28 GPIO_ACTIVE_LOW>,
+		   <&gpio3 27 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
 &esdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio2 29 0>;
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	cd-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
 	bus-width = <4>;
 	status = "okay";
 };
 
 &esdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	pinctrl-0 = <&pinctrl_esdhc2>;
 	bus-width = <4>;
 	non-removable;
 	status = "okay";
@@ -98,7 +100,7 @@
 
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_2>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 };
 
@@ -106,7 +108,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx51-apf51dev {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX51_PAD_EIM_EB2__GPIO2_22   0x0C5
@@ -120,5 +122,81 @@
 				MX51_PAD_GPIO1_3__GPIO1_3    0x0C5
 			>;
 		};
+
+		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
+			>;
+		};
+
+		pinctrl_ecspi2: ecspi2grp {
+			fsl,pins = <
+				MX51_PAD_NANDF_RB3__ECSPI2_MISO		0x185
+				MX51_PAD_NANDF_D15__ECSPI2_MOSI		0x185
+				MX51_PAD_NANDF_RB2__ECSPI2_SCLK		0x185
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX51_PAD_SD1_CMD__SD1_CMD		0x400020d5
+				MX51_PAD_SD1_CLK__SD1_CLK		0x20d5
+				MX51_PAD_SD1_DATA0__SD1_DATA0		0x20d5
+				MX51_PAD_SD1_DATA1__SD1_DATA1		0x20d5
+				MX51_PAD_SD1_DATA2__SD1_DATA2		0x20d5
+				MX51_PAD_SD1_DATA3__SD1_DATA3		0x20d5
+			>;
+		};
+
+		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_i2c2: i2c2grp {
+			fsl,pins = <
+				MX51_PAD_EIM_D27__I2C2_SCL		0x400001ed
+				MX51_PAD_EIM_D24__I2C2_SDA		0x400001ed
+			>;
+		};
+
+		pinctrl_ipu_disp1: ipudisp1grp {
+			fsl,pins = <
+				MX51_PAD_DISP1_DAT0__DISP1_DAT0		0x5
+				MX51_PAD_DISP1_DAT1__DISP1_DAT1		0x5
+				MX51_PAD_DISP1_DAT2__DISP1_DAT2		0x5
+				MX51_PAD_DISP1_DAT3__DISP1_DAT3		0x5
+				MX51_PAD_DISP1_DAT4__DISP1_DAT4		0x5
+				MX51_PAD_DISP1_DAT5__DISP1_DAT5		0x5
+				MX51_PAD_DISP1_DAT6__DISP1_DAT6		0x5
+				MX51_PAD_DISP1_DAT7__DISP1_DAT7		0x5
+				MX51_PAD_DISP1_DAT8__DISP1_DAT8		0x5
+				MX51_PAD_DISP1_DAT9__DISP1_DAT9		0x5
+				MX51_PAD_DISP1_DAT10__DISP1_DAT10	0x5
+				MX51_PAD_DISP1_DAT11__DISP1_DAT11	0x5
+				MX51_PAD_DISP1_DAT12__DISP1_DAT12	0x5
+				MX51_PAD_DISP1_DAT13__DISP1_DAT13	0x5
+				MX51_PAD_DISP1_DAT14__DISP1_DAT14	0x5
+				MX51_PAD_DISP1_DAT15__DISP1_DAT15	0x5
+				MX51_PAD_DISP1_DAT16__DISP1_DAT16	0x5
+				MX51_PAD_DISP1_DAT17__DISP1_DAT17	0x5
+				MX51_PAD_DISP1_DAT18__DISP1_DAT18	0x5
+				MX51_PAD_DISP1_DAT19__DISP1_DAT19	0x5
+				MX51_PAD_DISP1_DAT20__DISP1_DAT20	0x5
+				MX51_PAD_DISP1_DAT21__DISP1_DAT21	0x5
+				MX51_PAD_DISP1_DAT22__DISP1_DAT22	0x5
+				MX51_PAD_DISP1_DAT23__DISP1_DAT23	0x5
+				MX51_PAD_DI1_PIN2__DI1_PIN2		0x5
+				MX51_PAD_DI1_PIN3__DI1_PIN3		0x5
+			>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index be1407cf5abd..ebe6c1d08597 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -21,12 +21,12 @@
 		reg = <0x90000000 0x20000000>;
 	};
 
-	display@di0 {
+	display0: display@di0 {
 		compatible = "fsl,imx-parallel-display";
 		crtcs = <&ipu 0>;
 		interface-pix-fmt = "rgb24";
 		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+		pinctrl-0 = <&pinctrl_ipu_disp1>;
 		display-timings {
 			native-mode = <&timing0>;
 			timing0: dvi {
@@ -43,12 +43,12 @@
 		};
 	};
 
-	display@di1 {
+	display1: display@di1 {
 		compatible = "fsl,imx-parallel-display";
 		crtcs = <&ipu 1>;
 		interface-pix-fmt = "rgb565";
 		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+		pinctrl-0 = <&pinctrl_ipu_disp2>;
 		status = "disabled";
 		display-timings {
 			native-mode = <&timing1>;
@@ -75,12 +75,29 @@
 
 		power {
 			label = "Power Button";
-			gpios = <&gpio2 21 0>;
+			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
 			linux,code = <116>; /* KEY_POWER */
 			gpio-key,wakeup;
 		};
 	};
 
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led-diagnostic {
+			label = "diagnostic";
+			gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 0>, <&ipu 1>;
+		connectors = <&display0>, <&display1>;
+	};
+
 	sound {
 		compatible = "fsl,imx51-babbage-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
@@ -105,14 +122,14 @@
 			reg=<0>;
 			#clock-cells = <0>;
 			clock-frequency = <26000000>;
-			gpios = <&gpio4 26 1>;
+			gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
 		};
 	};
 };
 
 &esdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	pinctrl-0 = <&pinctrl_esdhc1>;
 	fsl,cd-controller;
 	fsl,wp-controller;
 	status = "okay";
@@ -120,24 +137,25 @@
 
 &esdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
-	cd-gpios = <&gpio1 6 0>;
-	wp-gpios = <&gpio1 5 0>;
+	pinctrl-0 = <&pinctrl_esdhc2>;
+	cd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+	wp-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1 &pinctrl_uart3_rtscts_1>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
 &ecspi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+		   <&gpio4 25 GPIO_ACTIVE_LOW>;
 	status = "okay";
 
 	pmic: mc13892@0 {
@@ -148,7 +166,7 @@
 		spi-cs-high;
 		reg = <0>;
 		interrupt-parent = <&gpio1>;
-		interrupts = <8 0x4>;
+		interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
 
 		regulators {
 			sw1_reg: sw1 {
@@ -267,7 +285,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx51-babbage {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX51_PAD_GPIO1_0__SD1_CD     0x20d5
@@ -280,25 +298,194 @@
 				MX51_PAD_CSPI1_RDY__GPIO4_26 0x80000000
 			>;
 		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX51_PAD_AUD3_BB_TXD__AUD3_TXD		0x80000000
+				MX51_PAD_AUD3_BB_RXD__AUD3_RXD		0x80000000
+				MX51_PAD_AUD3_BB_CK__AUD3_TXC		0x80000000
+				MX51_PAD_AUD3_BB_FS__AUD3_TXFS		0x80000000
+			>;
+		};
+
+		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
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX51_PAD_SD1_CMD__SD1_CMD		0x400020d5
+				MX51_PAD_SD1_CLK__SD1_CLK		0x20d5
+				MX51_PAD_SD1_DATA0__SD1_DATA0		0x20d5
+				MX51_PAD_SD1_DATA1__SD1_DATA1		0x20d5
+				MX51_PAD_SD1_DATA2__SD1_DATA2		0x20d5
+				MX51_PAD_SD1_DATA3__SD1_DATA3		0x20d5
+			>;
+		};
+
+		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_EIM_EB2__FEC_MDIO		0x80000000
+				MX51_PAD_EIM_EB3__FEC_RDATA1		0x80000000
+				MX51_PAD_EIM_CS2__FEC_RDATA2		0x80000000
+				MX51_PAD_EIM_CS3__FEC_RDATA3		0x80000000
+				MX51_PAD_EIM_CS4__FEC_RX_ER		0x80000000
+				MX51_PAD_EIM_CS5__FEC_CRS		0x80000000
+				MX51_PAD_NANDF_RB2__FEC_COL		0x80000000
+				MX51_PAD_NANDF_RB3__FEC_RX_CLK		0x80000000
+				MX51_PAD_NANDF_D9__FEC_RDATA0		0x80000000
+				MX51_PAD_NANDF_D8__FEC_TDATA0		0x80000000
+				MX51_PAD_NANDF_CS2__FEC_TX_ER		0x80000000
+				MX51_PAD_NANDF_CS3__FEC_MDC		0x80000000
+				MX51_PAD_NANDF_CS4__FEC_TDATA1		0x80000000
+				MX51_PAD_NANDF_CS5__FEC_TDATA2		0x80000000
+				MX51_PAD_NANDF_CS6__FEC_TDATA3		0x80000000
+				MX51_PAD_NANDF_CS7__FEC_TX_EN		0x80000000
+				MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	0x80000000
+				MX51_PAD_EIM_A20__GPIO2_14 0x85 /* Reset */
+			>;
+		};
+
+		pinctrl_gpio_leds: gpioledsgrp {
+			fsl,pins = <
+				MX51_PAD_EIM_D22__GPIO2_6		0x80000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX51_PAD_KEY_COL4__I2C2_SCL		0x400001ed
+				MX51_PAD_KEY_COL5__I2C2_SDA		0x400001ed
+			>;
+		};
+
+		pinctrl_ipu_disp1: ipudisp1grp {
+			fsl,pins = <
+				MX51_PAD_DISP1_DAT0__DISP1_DAT0		0x5
+				MX51_PAD_DISP1_DAT1__DISP1_DAT1		0x5
+				MX51_PAD_DISP1_DAT2__DISP1_DAT2		0x5
+				MX51_PAD_DISP1_DAT3__DISP1_DAT3		0x5
+				MX51_PAD_DISP1_DAT4__DISP1_DAT4		0x5
+				MX51_PAD_DISP1_DAT5__DISP1_DAT5		0x5
+				MX51_PAD_DISP1_DAT6__DISP1_DAT6		0x5
+				MX51_PAD_DISP1_DAT7__DISP1_DAT7		0x5
+				MX51_PAD_DISP1_DAT8__DISP1_DAT8		0x5
+				MX51_PAD_DISP1_DAT9__DISP1_DAT9		0x5
+				MX51_PAD_DISP1_DAT10__DISP1_DAT10	0x5
+				MX51_PAD_DISP1_DAT11__DISP1_DAT11	0x5
+				MX51_PAD_DISP1_DAT12__DISP1_DAT12	0x5
+				MX51_PAD_DISP1_DAT13__DISP1_DAT13	0x5
+				MX51_PAD_DISP1_DAT14__DISP1_DAT14	0x5
+				MX51_PAD_DISP1_DAT15__DISP1_DAT15	0x5
+				MX51_PAD_DISP1_DAT16__DISP1_DAT16	0x5
+				MX51_PAD_DISP1_DAT17__DISP1_DAT17	0x5
+				MX51_PAD_DISP1_DAT18__DISP1_DAT18	0x5
+				MX51_PAD_DISP1_DAT19__DISP1_DAT19	0x5
+				MX51_PAD_DISP1_DAT20__DISP1_DAT20	0x5
+				MX51_PAD_DISP1_DAT21__DISP1_DAT21	0x5
+				MX51_PAD_DISP1_DAT22__DISP1_DAT22	0x5
+				MX51_PAD_DISP1_DAT23__DISP1_DAT23	0x5
+				MX51_PAD_DI1_PIN2__DI1_PIN2		0x5
+				MX51_PAD_DI1_PIN3__DI1_PIN3		0x5
+			>;
+		};
+
+		pinctrl_ipu_disp2: ipudisp2grp {
+			fsl,pins = <
+				MX51_PAD_DISP2_DAT0__DISP2_DAT0		0x5
+				MX51_PAD_DISP2_DAT1__DISP2_DAT1		0x5
+				MX51_PAD_DISP2_DAT2__DISP2_DAT2		0x5
+				MX51_PAD_DISP2_DAT3__DISP2_DAT3		0x5
+				MX51_PAD_DISP2_DAT4__DISP2_DAT4		0x5
+				MX51_PAD_DISP2_DAT5__DISP2_DAT5		0x5
+				MX51_PAD_DISP2_DAT6__DISP2_DAT6		0x5
+				MX51_PAD_DISP2_DAT7__DISP2_DAT7		0x5
+				MX51_PAD_DISP2_DAT8__DISP2_DAT8		0x5
+				MX51_PAD_DISP2_DAT9__DISP2_DAT9		0x5
+				MX51_PAD_DISP2_DAT10__DISP2_DAT10	0x5
+				MX51_PAD_DISP2_DAT11__DISP2_DAT11	0x5
+				MX51_PAD_DISP2_DAT12__DISP2_DAT12	0x5
+				MX51_PAD_DISP2_DAT13__DISP2_DAT13	0x5
+				MX51_PAD_DISP2_DAT14__DISP2_DAT14	0x5
+				MX51_PAD_DISP2_DAT15__DISP2_DAT15	0x5
+				MX51_PAD_DI2_PIN2__DI2_PIN2		0x5
+				MX51_PAD_DI2_PIN3__DI2_PIN3		0x5
+				MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	0x5
+				MX51_PAD_DI_GP4__DI2_PIN15		0x5
+			>;
+		};
+
+		pinctrl_kpp: kppgrp {
+			fsl,pins = <
+				MX51_PAD_KEY_ROW0__KEY_ROW0		0xe0
+				MX51_PAD_KEY_ROW1__KEY_ROW1		0xe0
+				MX51_PAD_KEY_ROW2__KEY_ROW2		0xe0
+				MX51_PAD_KEY_ROW3__KEY_ROW3		0xe0
+				MX51_PAD_KEY_COL0__KEY_COL0		0xe8
+				MX51_PAD_KEY_COL1__KEY_COL1		0xe8
+				MX51_PAD_KEY_COL2__KEY_COL2		0xe8
+				MX51_PAD_KEY_COL3__KEY_COL3		0xe8
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX51_PAD_UART1_RXD__UART1_RXD		0x1c5
+				MX51_PAD_UART1_TXD__UART1_TXD		0x1c5
+				MX51_PAD_UART1_RTS__UART1_RTS		0x1c5
+				MX51_PAD_UART1_CTS__UART1_CTS		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_EIM_D25__UART3_RXD		0x1c5
+				MX51_PAD_EIM_D26__UART3_TXD		0x1c5
+				MX51_PAD_EIM_D27__UART3_RTS		0x1c5
+				MX51_PAD_EIM_D24__UART3_CTS		0x1c5
+			>;
+		};
 	};
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1 &pinctrl_uart1_rtscts_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "okay";
 };
 
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 
 	sgtl5000: codec@0a {
@@ -312,35 +499,39 @@
 
 &audmux {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
+	pinctrl-0 = <&pinctrl_audmux>;
 	status = "okay";
 };
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "mii";
+	phy-reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <1>;
 	status = "okay";
 };
 
 &kpp {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_kpp_1>;
-	linux,keymap = <0x00000067	/* KEY_UP */
-			0x0001006c	/* KEY_DOWN */
-			0x00020072	/* KEY_VOLUMEDOWN */
-			0x00030066	/* KEY_HOME */
-			0x0100006a	/* KEY_RIGHT */
-			0x01010069	/* KEY_LEFT */
-			0x0102001c	/* KEY_ENTER */
-			0x01030073	/* KEY_VOLUMEUP */
-			0x02000040	/* KEY_F6 */
-			0x02010042	/* KEY_F8 */
-			0x02020043	/* KEY_F9 */
-			0x02030044	/* KEY_F10 */
-			0x0300003b	/* KEY_F1 */
-			0x0301003c	/* KEY_F2 */
-			0x0302003d	/* KEY_F3 */
-			0x03030074>;	/* KEY_POWER */
+	pinctrl-0 = <&pinctrl_kpp>;
+	linux,keymap = <
+		MATRIX_KEY(0, 0, KEY_UP)
+		MATRIX_KEY(0, 1, KEY_DOWN)
+		MATRIX_KEY(0, 2, KEY_VOLUMEDOWN)
+		MATRIX_KEY(0, 3, KEY_HOME)
+		MATRIX_KEY(1, 0, KEY_RIGHT)
+		MATRIX_KEY(1, 1, KEY_LEFT)
+		MATRIX_KEY(1, 2, KEY_ENTER)
+		MATRIX_KEY(1, 3, KEY_VOLUMEUP)
+		MATRIX_KEY(2, 0, KEY_F6)
+		MATRIX_KEY(2, 1, KEY_F8)
+		MATRIX_KEY(2, 2, KEY_F9)
+		MATRIX_KEY(2, 3, KEY_F10)
+		MATRIX_KEY(3, 0, KEY_F1)
+		MATRIX_KEY(3, 1, KEY_F2)
+		MATRIX_KEY(3, 2, KEY_F3)
+		MATRIX_KEY(3, 3, KEY_POWER)
+		>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
new file mode 100644
index 000000000000..9b3acf6e4282
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "imx51.dtsi"
+
+/ {
+	model = "Eukrea CPUIMX51";
+	compatible = "eukrea,cpuimx51", "fsl,imx51";
+
+	memory {
+		reg = <0x90000000 0x10000000>; /* 256M */
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&iomuxc {
+	imx51-eukrea {
+		pinctrl_tsc2007_1: tsc2007grp-1 {
+			fsl,pins = <
+				MX51_PAD_GPIO_NAND__GPIO_NAND 0x1f5
+				MX51_PAD_NANDF_D8__GPIO4_0 0x1f5
+			>;
+		};
+
+		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_i2c1: i2c1grp {
+			fsl,pins = <
+				MX51_PAD_SD2_CMD__I2C1_SCL		0x400001ed
+				MX51_PAD_SD2_CLK__I2C1_SDA		0x400001ed
+			>;
+		};
+	};
+};
+
+&nfc {
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
new file mode 100644
index 000000000000..5cec4f322096
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/dts-v1/;
+#include "imx51-eukrea-cpuimx51.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Eukrea CPUIMX51";
+	compatible = "eukrea,mbimxsd51","eukrea,cpuimx51", "fsl,imx51";
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpiokeys_1>;
+
+		button-1 {
+			label = "BP1";
+			gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+			linux,code = <256>;
+			gpio-key,wakeup;
+			linux,input-type = <1>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioled>;
+
+		led1 {
+			label = "led1";
+			gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	sound {
+		compatible = "eukrea,asoc-tlv320";
+		eukrea,model = "imx51-eukrea-tlv320aic23";
+		ssi-controller = <&ssi2>;
+		fsl,mux-int-port = <2>;
+		fsl,mux-ext-port = <3>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1 &pinctrl_esdhc1_cd>;
+	fsl,cd-controller;
+	status = "okay";
+};
+
+&i2c1 {
+	tlv320aic23: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+	};
+};
+
+&iomuxc {
+	imx51-eukrea {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX51_PAD_AUD3_BB_TXD__AUD3_TXD		0x80000000
+				MX51_PAD_AUD3_BB_RXD__AUD3_RXD		0x80000000
+				MX51_PAD_AUD3_BB_CK__AUD3_TXC		0x80000000
+				MX51_PAD_AUD3_BB_FS__AUD3_TXFS		0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX51_PAD_SD1_CMD__SD1_CMD		0x400020d5
+				MX51_PAD_SD1_CLK__SD1_CLK		0x20d5
+				MX51_PAD_SD1_DATA0__SD1_DATA0		0x20d5
+				MX51_PAD_SD1_DATA1__SD1_DATA1		0x20d5
+				MX51_PAD_SD1_DATA2__SD1_DATA2		0x20d5
+				MX51_PAD_SD1_DATA3__SD1_DATA3		0x20d5
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX51_PAD_UART1_RXD__UART1_RXD		0x1c5
+				MX51_PAD_UART1_TXD__UART1_TXD		0x1c5
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX51_PAD_UART3_RXD__UART3_RXD		0x1c5
+				MX51_PAD_UART3_TXD__UART3_TXD		0x1c5
+			>;
+		};
+
+		pinctrl_uart3_rtscts: uart3rtsctsgrp {
+			fsl,pins = <
+				MX51_PAD_KEY_COL4__UART3_RTS		0x1c5
+				MX51_PAD_KEY_COL5__UART3_CTS		0x1c5
+			>;
+		};
+
+		pinctrl_backlight_1: backlightgrp-1 {
+			fsl,pins = <
+				MX51_PAD_DI1_D1_CS__GPIO3_4 0x1f5
+			>;
+		};
+
+		pinctrl_esdhc1_cd: esdhc1_cd {
+			fsl,pins = <
+				MX51_PAD_GPIO1_0__SD1_CD 0x20d5
+			>;
+		};
+
+		pinctrl_gpiokeys_1: gpiokeysgrp-1 {
+			fsl,pins = <
+				MX51_PAD_NANDF_D9__GPIO3_31 0x1f5
+			>;
+		};
+
+		pinctrl_gpioled: gpioledgrp-1 {
+			fsl,pins = <
+				MX51_PAD_NANDF_D10__GPIO3_30 0x80000000
+			>;
+		};
+
+		pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
+			fsl,pins = <
+				MX51_PAD_CSI1_D9__GPIO3_13 0x1f5
+			>;
+		};
+	};
+};
+
+&ssi2 {
+	codec-handle = <&tlv320aic23>;
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 4bcdd3ad15e5..e4b07d1a9a56 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -12,6 +12,10 @@
 
 #include "skeleton.dtsi"
 #include "imx51-pinfunc.h"
+#include <dt-bindings/clock/imx5-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	aliases {
@@ -21,6 +25,10 @@
 		gpio3 = &gpio4;
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
+		mmc0 = &esdhc1;
+		mmc1 = &esdhc2;
+		mmc2 = &esdhc3;
+		mmc3 = &esdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -64,18 +72,32 @@
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		cpu@0 {
+		cpu: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a8";
 			reg = <0>;
-			clock-latency = <61036>; /* two CLK32 periods */
-			clocks = <&clks 24>;
+			clock-latency = <62500>;
+			clocks = <&clks IMX5_CLK_CPU_PODF>;
 			clock-names = "cpu";
 			operating-points = <
-				/* kHz  uV (No regulator support) */
-				160000  0
-				800000  0
+				166000	1000000
+				600000	1050000
+				800000	1100000
 			>;
+			voltage-tolerance = <5>;
+		};
+	};
+
+	usbphy {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "simple-bus";
+
+		usbphy0: usbphy@0 {
+			compatible = "usb-nop-xceiv";
+			reg = <0>;
+			clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
+			clock-names = "main_clk";
 		};
 	};
 
@@ -96,7 +118,9 @@
 			compatible = "fsl,imx51-ipu";
 			reg = <0x40000000 0x20000000>;
 			interrupts = <11 10>;
-			clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+			clocks = <&clks IMX5_CLK_IPU_GATE>,
+			         <&clks IMX5_CLK_IPU_DI0_GATE>,
+			         <&clks IMX5_CLK_IPU_DI1_GATE>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
 		};
@@ -119,7 +143,9 @@
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70004000 0x4000>;
 					interrupts = <1>;
-					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
@@ -128,7 +154,9 @@
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70008000 0x4000>;
 					interrupts = <2>;
-					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -138,7 +166,8 @@
 					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 					reg = <0x7000c000 0x4000>;
 					interrupts = <33>;
-					clocks = <&clks 32>, <&clks 33>;
+					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+					         <&clks IMX5_CLK_UART3_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -149,7 +178,8 @@
 					compatible = "fsl,imx51-ecspi";
 					reg = <0x70010000 0x4000>;
 					interrupts = <36>;
-					clocks = <&clks 51>, <&clks 52>;
+					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -158,7 +188,7 @@
 					compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 					reg = <0x70014000 0x4000>;
 					interrupts = <30>;
-					clocks = <&clks 49>;
+					clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
 					dmas = <&sdma 24 1 0>,
 					       <&sdma 25 1 0>;
 					dma-names = "rx", "tx";
@@ -171,7 +201,9 @@
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70020000 0x4000>;
 					interrupts = <3>;
-					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -181,25 +213,20 @@
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70024000 0x4000>;
 					interrupts = <4>;
-					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
 				};
 			};
 
-			usbphy0: usbphy@0 {
-				compatible = "usb-nop-xceiv";
-				clocks = <&clks 75>;
-				clock-names = "main_clk";
-				status = "okay";
-			};
-
 			usbotg: usb@73f80000 {
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80000 0x0200>;
 				interrupts = <18>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 0>;
 				fsl,usbphy = <&usbphy0>;
 				status = "disabled";
@@ -209,7 +236,7 @@
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80200 0x0200>;
 				interrupts = <14>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 1>;
 				status = "disabled";
 			};
@@ -218,7 +245,7 @@
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80400 0x0200>;
 				interrupts = <16>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
 			};
@@ -227,7 +254,7 @@
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80600 0x0200>;
 				interrupts = <17>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 3>;
 				status = "disabled";
 			};
@@ -236,7 +263,7 @@
 				#index-cells = <1>;
 				compatible = "fsl,imx51-usbmisc";
 				reg = <0x73f80800 0x200>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 			};
 
 			gpio1: gpio@73f84000 {
@@ -283,7 +310,7 @@
 				compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
 				reg = <0x73f94000 0x4000>;
 				interrupts = <60>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
 				status = "disabled";
 			};
 
@@ -291,14 +318,14 @@
 				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 				reg = <0x73f98000 0x4000>;
 				interrupts = <58>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
 			};
 
 			wdog2: wdog@73f9c000 {
 				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 				reg = <0x73f9c000 0x4000>;
 				interrupts = <59>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
 				status = "disabled";
 			};
 
@@ -306,7 +333,8 @@
 				compatible = "fsl,imx51-gpt", "fsl,imx31-gpt";
 				reg = <0x73fa0000 0x4000>;
 				interrupts = <39>;
-				clocks = <&clks 36>, <&clks 41>;
+				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+				         <&clks IMX5_CLK_GPT_HF_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -319,7 +347,8 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
 				reg = <0x73fb4000 0x4000>;
-				clocks = <&clks 37>, <&clks 38>;
+				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM1_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <61>;
 			};
@@ -328,7 +357,8 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
 				reg = <0x73fb8000 0x4000>;
-				clocks = <&clks 39>, <&clks 40>;
+				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM2_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <94>;
 			};
@@ -337,7 +367,8 @@
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fbc000 0x4000>;
 				interrupts = <31>;
-				clocks = <&clks 28>, <&clks 29>;
+				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+				         <&clks IMX5_CLK_UART1_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -346,7 +377,8 @@
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fc0000 0x4000>;
 				interrupts = <32>;
-				clocks = <&clks 30>, <&clks 31>;
+				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+				         <&clks IMX5_CLK_UART2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -376,14 +408,14 @@
 				compatible = "fsl,imx51-iim", "fsl,imx27-iim";
 				reg = <0x83f98000 0x4000>;
 				interrupts = <69>;
-				clocks = <&clks 107>;
+				clocks = <&clks IMX5_CLK_IIM_GATE>;
 			};
 
 			owire: owire@83fa4000 {
 				compatible = "fsl,imx51-owire", "fsl,imx21-owire";
 				reg = <0x83fa4000 0x4000>;
 				interrupts = <88>;
-				clocks = <&clks 159>;
+				clocks = <&clks IMX5_CLK_OWIRE_GATE>;
 				status = "disabled";
 			};
 
@@ -393,7 +425,8 @@
 				compatible = "fsl,imx51-ecspi";
 				reg = <0x83fac000 0x4000>;
 				interrupts = <37>;
-				clocks = <&clks 53>, <&clks 54>;
+				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -402,7 +435,8 @@
 				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
 				reg = <0x83fb0000 0x4000>;
 				interrupts = <6>;
-				clocks = <&clks 56>, <&clks 56>;
+				clocks = <&clks IMX5_CLK_SDMA_GATE>,
+				         <&clks IMX5_CLK_SDMA_GATE>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
@@ -414,7 +448,8 @@
 				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
 				reg = <0x83fc0000 0x4000>;
 				interrupts = <38>;
-				clocks = <&clks 55>, <&clks 55>;
+				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -425,7 +460,7 @@
 				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
 				reg = <0x83fc4000 0x4000>;
 				interrupts = <63>;
-				clocks = <&clks 35>;
+				clocks = <&clks IMX5_CLK_I2C2_GATE>;
 				status = "disabled";
 			};
 
@@ -435,7 +470,7 @@
 				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
 				reg = <0x83fc8000 0x4000>;
 				interrupts = <62>;
-				clocks = <&clks 34>;
+				clocks = <&clks IMX5_CLK_I2C1_GATE>;
 				status = "disabled";
 			};
 
@@ -443,7 +478,7 @@
 				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 				reg = <0x83fcc000 0x4000>;
 				interrupts = <29>;
-				clocks = <&clks 48>;
+				clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
 				dmas = <&sdma 28 0 0>,
 				       <&sdma 29 0 0>;
 				dma-names = "rx", "tx";
@@ -455,6 +490,8 @@
 			audmux: audmux@83fd0000 {
 				compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
 				reg = <0x83fd0000 0x4000>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
+				clock-names = "audmux";
 				status = "disabled";
 			};
 
@@ -463,7 +500,7 @@
 				#size-cells = <1>;
 				compatible = "fsl,imx51-weim";
 				reg = <0x83fda000 0x1000>;
-				clocks = <&clks 57>;
+				clocks = <&clks IMX5_CLK_EMI_SLOW_GATE>;
 				ranges = <
 					0 0 0xb0000000 0x08000000
 					1 0 0xb8000000 0x08000000
@@ -479,7 +516,7 @@
 				compatible = "fsl,imx51-nand";
 				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
 				interrupts = <8>;
-				clocks = <&clks 60>;
+				clocks = <&clks IMX5_CLK_NFC_GATE>;
 				status = "disabled";
 			};
 
@@ -487,7 +524,7 @@
 				compatible = "fsl,imx51-pata", "fsl,imx27-pata";
 				reg = <0x83fe0000 0x4000>;
 				interrupts = <70>;
-				clocks = <&clks 172>;
+				clocks = <&clks IMX5_CLK_PATA_GATE>;
 				status = "disabled";
 			};
 
@@ -495,7 +532,7 @@
 				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 				reg = <0x83fe8000 0x4000>;
 				interrupts = <96>;
-				clocks = <&clks 50>;
+				clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
 				dmas = <&sdma 46 0 0>,
 				       <&sdma 47 0 0>;
 				dma-names = "rx", "tx";
@@ -508,336 +545,12 @@
 				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
 				reg = <0x83fec000 0x4000>;
 				interrupts = <87>;
-				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clocks = <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
 		};
 	};
 };
-
-&iomuxc {
-	audmux {
-		pinctrl_audmux_1: audmuxgrp-1 {
-			fsl,pins = <
-				MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
-				MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
-				MX51_PAD_AUD3_BB_CK__AUD3_TXC  0x80000000
-				MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
-			>;
-		};
-	};
-
-	fec {
-		pinctrl_fec_1: fecgrp-1 {
-			fsl,pins = <
-				MX51_PAD_EIM_EB2__FEC_MDIO	   0x80000000
-				MX51_PAD_EIM_EB3__FEC_RDATA1	   0x80000000
-				MX51_PAD_EIM_CS2__FEC_RDATA2	   0x80000000
-				MX51_PAD_EIM_CS3__FEC_RDATA3	   0x80000000
-				MX51_PAD_EIM_CS4__FEC_RX_ER	   0x80000000
-				MX51_PAD_EIM_CS5__FEC_CRS	   0x80000000
-				MX51_PAD_NANDF_RB2__FEC_COL	   0x80000000
-				MX51_PAD_NANDF_RB3__FEC_RX_CLK	   0x80000000
-				MX51_PAD_NANDF_D9__FEC_RDATA0	   0x80000000
-				MX51_PAD_NANDF_D8__FEC_TDATA0	   0x80000000
-				MX51_PAD_NANDF_CS2__FEC_TX_ER	   0x80000000
-				MX51_PAD_NANDF_CS3__FEC_MDC	   0x80000000
-				MX51_PAD_NANDF_CS4__FEC_TDATA1	   0x80000000
-				MX51_PAD_NANDF_CS5__FEC_TDATA2	   0x80000000
-				MX51_PAD_NANDF_CS6__FEC_TDATA3	   0x80000000
-				MX51_PAD_NANDF_CS7__FEC_TX_EN	   0x80000000
-				MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x80000000
-			>;
-		};
-
-		pinctrl_fec_2: fecgrp-2 {
-			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
-			>;
-		};
-	};
-
-	ecspi1 {
-		pinctrl_ecspi1_1: ecspi1grp-1 {
-			fsl,pins = <
-				MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
-				MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
-				MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
-			>;
-		};
-	};
-
-	ecspi2 {
-		pinctrl_ecspi2_1: ecspi2grp-1 {
-			fsl,pins = <
-				MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185
-				MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185
-				MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185
-			>;
-		};
-	};
-
-	esdhc1 {
-		pinctrl_esdhc1_1: esdhc1grp-1 {
-			fsl,pins = <
-				MX51_PAD_SD1_CMD__SD1_CMD     0x400020d5
-				MX51_PAD_SD1_CLK__SD1_CLK     0x20d5
-				MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
-				MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
-				MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
-				MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
-			>;
-		};
-	};
-
-	esdhc2 {
-		pinctrl_esdhc2_1: esdhc2grp-1 {
-			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
-			>;
-		};
-	};
-
-	i2c2 {
-		pinctrl_i2c2_1: i2c2grp-1 {
-			fsl,pins = <
-				MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed
-				MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed
-			>;
-		};
-
-		pinctrl_i2c2_2: i2c2grp-2 {
-			fsl,pins = <
-				MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed
-				MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed
-			>;
-		};
-
-		pinctrl_i2c2_3: i2c2grp-3 {
-			fsl,pins = <
-				MX51_PAD_GPIO1_2__I2C2_SCL 0x400001ed
-				MX51_PAD_GPIO1_3__I2C2_SDA 0x400001ed
-			>;
-		};
-	};
-
-	ipu_disp1 {
-		pinctrl_ipu_disp1_1: ipudisp1grp-1 {
-			fsl,pins = <
-				MX51_PAD_DISP1_DAT0__DISP1_DAT0	  0x5
-				MX51_PAD_DISP1_DAT1__DISP1_DAT1	  0x5
-				MX51_PAD_DISP1_DAT2__DISP1_DAT2	  0x5
-				MX51_PAD_DISP1_DAT3__DISP1_DAT3	  0x5
-				MX51_PAD_DISP1_DAT4__DISP1_DAT4	  0x5
-				MX51_PAD_DISP1_DAT5__DISP1_DAT5	  0x5
-				MX51_PAD_DISP1_DAT6__DISP1_DAT6	  0x5
-				MX51_PAD_DISP1_DAT7__DISP1_DAT7	  0x5
-				MX51_PAD_DISP1_DAT8__DISP1_DAT8	  0x5
-				MX51_PAD_DISP1_DAT9__DISP1_DAT9	  0x5
-				MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
-				MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
-				MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
-				MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
-				MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
-				MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
-				MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
-				MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
-				MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
-				MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
-				MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
-				MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
-				MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
-				MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
-				MX51_PAD_DI1_PIN2__DI1_PIN2	  0x5 /* hsync */
-				MX51_PAD_DI1_PIN3__DI1_PIN3	  0x5 /* vsync */
-			>;
-		};
-	};
-
-	ipu_disp2 {
-		pinctrl_ipu_disp2_1: ipudisp2grp-1 {
-			fsl,pins = <
-				MX51_PAD_DISP2_DAT0__DISP2_DAT0	    0x5
-				MX51_PAD_DISP2_DAT1__DISP2_DAT1	    0x5
-				MX51_PAD_DISP2_DAT2__DISP2_DAT2	    0x5
-				MX51_PAD_DISP2_DAT3__DISP2_DAT3	    0x5
-				MX51_PAD_DISP2_DAT4__DISP2_DAT4	    0x5
-				MX51_PAD_DISP2_DAT5__DISP2_DAT5	    0x5
-				MX51_PAD_DISP2_DAT6__DISP2_DAT6	    0x5
-				MX51_PAD_DISP2_DAT7__DISP2_DAT7	    0x5
-				MX51_PAD_DISP2_DAT8__DISP2_DAT8	    0x5
-				MX51_PAD_DISP2_DAT9__DISP2_DAT9	    0x5
-				MX51_PAD_DISP2_DAT10__DISP2_DAT10   0x5
-				MX51_PAD_DISP2_DAT11__DISP2_DAT11   0x5
-				MX51_PAD_DISP2_DAT12__DISP2_DAT12   0x5
-				MX51_PAD_DISP2_DAT13__DISP2_DAT13   0x5
-				MX51_PAD_DISP2_DAT14__DISP2_DAT14   0x5
-				MX51_PAD_DISP2_DAT15__DISP2_DAT15   0x5
-				MX51_PAD_DI2_PIN2__DI2_PIN2	    0x5 /* hsync */
-				MX51_PAD_DI2_PIN3__DI2_PIN3	    0x5 /* vsync */
-				MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5 /* CLK */
-				MX51_PAD_DI_GP4__DI2_PIN15	    0x5 /* DE */
-			>;
-		};
-	};
-
-	kpp {
-		pinctrl_kpp_1: kppgrp-1 {
-			fsl,pins = <
-				MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
-				MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
-				MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
-				MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
-				MX51_PAD_KEY_COL0__KEY_COL0 0xe8
-				MX51_PAD_KEY_COL1__KEY_COL1 0xe8
-				MX51_PAD_KEY_COL2__KEY_COL2 0xe8
-				MX51_PAD_KEY_COL3__KEY_COL3 0xe8
-			>;
-		};
-	};
-
-	pata {
-		pinctrl_pata_1: patagrp-1 {
-			fsl,pins = <
-				MX51_PAD_NANDF_WE_B__PATA_DIOW	   0x2004
-				MX51_PAD_NANDF_RE_B__PATA_DIOR	   0x2004
-				MX51_PAD_NANDF_ALE__PATA_BUFFER_EN 0x2004
-				MX51_PAD_NANDF_CLE__PATA_RESET_B   0x2004
-				MX51_PAD_NANDF_WP_B__PATA_DMACK	   0x2004
-				MX51_PAD_NANDF_RB0__PATA_DMARQ	   0x2004
-				MX51_PAD_NANDF_RB1__PATA_IORDY	   0x2004
-				MX51_PAD_GPIO_NAND__PATA_INTRQ	   0x2004
-				MX51_PAD_NANDF_CS2__PATA_CS_0	   0x2004
-				MX51_PAD_NANDF_CS3__PATA_CS_1	   0x2004
-				MX51_PAD_NANDF_CS4__PATA_DA_0	   0x2004
-				MX51_PAD_NANDF_CS5__PATA_DA_1	   0x2004
-				MX51_PAD_NANDF_CS6__PATA_DA_2	   0x2004
-				MX51_PAD_NANDF_D15__PATA_DATA15	   0x2004
-				MX51_PAD_NANDF_D14__PATA_DATA14	   0x2004
-				MX51_PAD_NANDF_D13__PATA_DATA13	   0x2004
-				MX51_PAD_NANDF_D12__PATA_DATA12	   0x2004
-				MX51_PAD_NANDF_D11__PATA_DATA11	   0x2004
-				MX51_PAD_NANDF_D10__PATA_DATA10	   0x2004
-				MX51_PAD_NANDF_D9__PATA_DATA9	   0x2004
-				MX51_PAD_NANDF_D8__PATA_DATA8	   0x2004
-				MX51_PAD_NANDF_D7__PATA_DATA7	   0x2004
-				MX51_PAD_NANDF_D6__PATA_DATA6	  0x2004
-				MX51_PAD_NANDF_D5__PATA_DATA5	  0x2004
-				MX51_PAD_NANDF_D4__PATA_DATA4	  0x2004
-				MX51_PAD_NANDF_D3__PATA_DATA3	  0x2004
-				MX51_PAD_NANDF_D2__PATA_DATA2	  0x2004
-				MX51_PAD_NANDF_D1__PATA_DATA1	  0x2004
-				MX51_PAD_NANDF_D0__PATA_DATA0	  0x2004
-			>;
-		};
-	};
-
-	uart1 {
-		pinctrl_uart1_1: uart1grp-1 {
-			fsl,pins = <
-				MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
-				MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
-			>;
-		};
-
-		pinctrl_uart1_rtscts_1: uart1rtscts-1 {
-			fsl,pins = <
-				MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
-				MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
-			>;
-		};
-	};
-
-	uart2 {
-		pinctrl_uart2_1: uart2grp-1 {
-			fsl,pins = <
-				MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
-				MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
-			>;
-		};
-	};
-
-	uart3 {
-		pinctrl_uart3_1: uart3grp-1 {
-			fsl,pins = <
-				MX51_PAD_EIM_D25__UART3_RXD 0x1c5
-				MX51_PAD_EIM_D26__UART3_TXD 0x1c5
-			>;
-		};
-
-		pinctrl_uart3_rtscts_1: uart3rtscts-1 {
-			fsl,pins = <
-				MX51_PAD_EIM_D27__UART3_RTS 0x1c5
-				MX51_PAD_EIM_D24__UART3_CTS 0x1c5
-			>;
-		};
-
-		pinctrl_uart3_2: uart3grp-2 {
-			fsl,pins = <
-				MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
-				MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
-			>;
-		};
-	};
-
-	usbh1 {
-		pinctrl_usbh1_1: usbh1grp-1 {
-			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
-			>;
-		};
-	};
-
-	usbh2 {
-		pinctrl_usbh2_1: usbh2grp-1 {
-			fsl,pins = <
-				MX51_PAD_EIM_D16__USBH2_DATA0 0x1e5
-				MX51_PAD_EIM_D17__USBH2_DATA1 0x1e5
-				MX51_PAD_EIM_D18__USBH2_DATA2 0x1e5
-				MX51_PAD_EIM_D19__USBH2_DATA3 0x1e5
-				MX51_PAD_EIM_D20__USBH2_DATA4 0x1e5
-				MX51_PAD_EIM_D21__USBH2_DATA5 0x1e5
-				MX51_PAD_EIM_D22__USBH2_DATA6 0x1e5
-				MX51_PAD_EIM_D23__USBH2_DATA7 0x1e5
-				MX51_PAD_EIM_A24__USBH2_CLK   0x1e5
-				MX51_PAD_EIM_A25__USBH2_DIR   0x1e5
-				MX51_PAD_EIM_A27__USBH2_NXT   0x1e5
-				MX51_PAD_EIM_A26__USBH2_STP   0x1e5
-			>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
index 174f86938c89..e9337ad52f59 100644
--- a/arch/arm/boot/dts/imx53-ard.dts
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -49,9 +49,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -99,7 +102,7 @@
 
 &esdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_2>;
+	pinctrl-0 = <&pinctrl_esdhc1>;
 	cd-gpios = <&gpio1 1 0>;
 	wp-gpios = <&gpio1 9 0>;
 	status = "okay";
@@ -109,7 +112,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx53-ard {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX53_PAD_GPIO_1__GPIO1_1             0x80000000
@@ -148,11 +151,33 @@
 				MX53_PAD_EIM_CS1__EMI_WEIM_CS_1	     0x80000000
 			>;
 		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+				MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+				MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+				MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+				MX53_PAD_PATA_DATA8__ESDHC1_DAT4	0x1d5
+				MX53_PAD_PATA_DATA9__ESDHC1_DAT5	0x1d5
+				MX53_PAD_PATA_DATA10__ESDHC1_DAT6	0x1d5
+				MX53_PAD_PATA_DATA11__ESDHC1_DAT7	0x1d5
+				MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+				MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DIOW__UART1_TXD_MUX	0x1e4
+				MX53_PAD_PATA_DMACK__UART1_RXD_MUX	0x1e4
+			>;
+		};
 	};
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
deleted file mode 100644
index 801fda728ed6..000000000000
--- a/arch/arm/boot/dts/imx53-evk.dts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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 "imx53.dtsi"
-
-/ {
-	model = "Freescale i.MX53 Evaluation Kit";
-	compatible = "fsl,imx53-evk", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x80000000>;
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		green {
-			label = "Heartbeat";
-			gpios = <&gpio7 7 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio3 13 0>;
-	wp-gpios = <&gpio3 14 0>;
-	status = "okay";
-};
-
-&ecspi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
-	status = "okay";
-
-	flash: at45db321d@1 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
-		spi-max-frequency = <25000000>;
-		reg = <1>;
-
-		partition@0 {
-			label = "U-Boot";
-			reg = <0x0 0x40000>;
-			read-only;
-		};
-
-		partition@40000 {
-			label = "Kernel";
-			reg = <0x40000 0x3c0000>;
-		};
-	};
-};
-
-&esdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	cd-gpios = <&gpio3 11 0>;
-	wp-gpios = <&gpio3 12 0>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX53_PAD_EIM_EB2__GPIO2_30  0x80000000
-				MX53_PAD_EIM_D19__GPIO3_19  0x80000000
-				MX53_PAD_EIM_DA11__GPIO3_11 0x80000000
-				MX53_PAD_EIM_DA12__GPIO3_12 0x80000000
-				MX53_PAD_EIM_DA13__GPIO3_13 0x80000000
-				MX53_PAD_EIM_DA14__GPIO3_14 0x80000000
-				MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
-				MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	pmic: mc13892@08 {
-		compatible = "fsl,mc13892", "fsl,mc13xxx";
-		reg = <0x08>;
-	};
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	phy-reset-gpios = <&gpio7 6 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index 7d304d02ed38..d939ba8f7e27 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -21,12 +21,12 @@
 	};
 
 	soc {
-		display@di1 {
+		display1: display@di1 {
 			compatible = "fsl,imx-parallel-display";
 			crtcs = <&ipu 1>;
 			interface-pix-fmt = "bgr666";
 			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+			pinctrl-0 = <&pinctrl_ipu_disp1>;
 
 			display-timings {
 				800x480p60 {
@@ -51,6 +51,13 @@
 		pwms = <&pwm1 0 3000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
 		default-brightness-level = <6>;
+		power-supply = <&reg_backlight>;
+	};
+
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 1>;
+		connectors = <&display1>;
 	};
 
 	leds {
@@ -73,14 +80,36 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p2v: 3p2v {
+		reg_3p2v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P2V";
 			regulator-min-microvolt = <3200000>;
 			regulator-max-microvolt = <3200000>;
 			regulator-always-on;
 		};
+
+
+		reg_backlight: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "lcd-supply";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
+
+		reg_usbh1_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 2 0>;
+		};
 	};
 
 	sound {
@@ -102,25 +131,25 @@
 
 &audmux {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_2>;
+	pinctrl-0 = <&pinctrl_audmux>;
 	status = "okay";
 };
 
 &can1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can1_3>;
+	pinctrl-0 = <&pinctrl_can1>;
 	status = "okay";
 };
 
 &can2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can2_1>;
+	pinctrl-0 = <&pinctrl_can2>;
 	status = "okay";
 };
 
 &esdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	pinctrl-0 = <&pinctrl_esdhc1>;
 	cd-gpios = <&gpio1 1 0>;
 	wp-gpios = <&gpio1 9 0>;
 	status = "okay";
@@ -128,14 +157,14 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "rmii";
 	status = "okay";
 };
 
 &i2c1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_2>;
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	sgtl5000: codec@0a {
@@ -143,13 +172,13 @@
 		reg = <0x0a>;
 		VDDA-supply = <&reg_3p2v>;
 		VDDIO-supply = <&reg_3p2v>;
-		clocks = <&clks 150>;
+		clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
 	};
 };
 
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_2>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	clock-frequency = <400000>;
 	status = "okay";
 
@@ -193,7 +222,7 @@
 
 &i2c3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3_1>;
+	pinctrl-0 = <&pinctrl_i2c3>;
 	status = "okay";
 };
 
@@ -201,14 +230,14 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx53-m53evk {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	0x80000000
 				MX53_PAD_EIM_EB3__GPIO2_31		0x80000000
 				MX53_PAD_PATA_DA_0__GPIO7_6		0x80000000
-				MX53_PAD_DISP0_DAT8__PWM1_PWMO		0x5
-
+				MX53_PAD_GPIO_2__GPIO1_2		0x80000000
+				MX53_PAD_GPIO_3__USBOH3_USBH1_OC	0x80000000
 			>;
 		};
 
@@ -218,12 +247,168 @@
 				MX53_PAD_PATA_DATA9__GPIO2_9		0x80000000
 			>;
 		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	0x80000000
+				MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	0x80000000
+				MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	0x80000000
+				MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	0x80000000
+			>;
+		};
+
+		pinctrl_can1: can1grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_7__CAN1_TXCAN		0x80000000
+				MX53_PAD_GPIO_8__CAN1_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_can2: can2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL4__CAN2_TXCAN		0x80000000
+				MX53_PAD_KEY_ROW4__CAN2_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+				MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+				MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+				MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+				MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+				MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D21__I2C1_SCL		0xc0000000
+				MX53_PAD_EIM_D28__I2C1_SDA		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D16__I2C2_SDA		0xc0000000
+				MX53_PAD_EIM_EB2__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_6__I2C3_SDA		0xc0000000
+				MX53_PAD_GPIO_5__I2C3_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_ipu_disp1: ipudisp1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0	0x5
+				MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1	0x5
+				MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2	0x5
+				MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3	0x5
+				MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4	0x5
+				MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5	0x5
+				MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6	0x5
+				MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7	0x5
+				MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8	0x5
+				MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9	0x5
+				MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10	0x5
+				MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11	0x5
+				MX53_PAD_EIM_A17__IPU_DISP1_DAT_12	0x5
+				MX53_PAD_EIM_A18__IPU_DISP1_DAT_13	0x5
+				MX53_PAD_EIM_A19__IPU_DISP1_DAT_14	0x5
+				MX53_PAD_EIM_A20__IPU_DISP1_DAT_15	0x5
+				MX53_PAD_EIM_A21__IPU_DISP1_DAT_16	0x5
+				MX53_PAD_EIM_A22__IPU_DISP1_DAT_17	0x5
+				MX53_PAD_EIM_A23__IPU_DISP1_DAT_18	0x5
+				MX53_PAD_EIM_A24__IPU_DISP1_DAT_19	0x5
+				MX53_PAD_EIM_D31__IPU_DISP1_DAT_20	0x5
+				MX53_PAD_EIM_D30__IPU_DISP1_DAT_21	0x5
+				MX53_PAD_EIM_D26__IPU_DISP1_DAT_22	0x5
+				MX53_PAD_EIM_D27__IPU_DISP1_DAT_23	0x5
+				MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK	0x5
+				MX53_PAD_EIM_DA13__IPU_DI1_D0_CS	0x5
+				MX53_PAD_EIM_DA14__IPU_DI1_D1_CS	0x5
+				MX53_PAD_EIM_DA15__IPU_DI1_PIN1		0x5
+				MX53_PAD_EIM_DA11__IPU_DI1_PIN2		0x5
+				MX53_PAD_EIM_DA12__IPU_DI1_PIN3		0x5
+				MX53_PAD_EIM_A25__IPU_DI1_PIN12		0x5
+				MX53_PAD_EIM_DA10__IPU_DI1_PIN15	0x5
+			>;
+		};
+
+		pinctrl_nand: nandgrp {
+			fsl,pins = <
+				MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
+				MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
+				MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
+				MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
+				MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
+				MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
+				MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
+				MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	0xa4
+				MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	0xa4
+				MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	0xa4
+				MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	0xa4
+				MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	0xa4
+				MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	0xa4
+				MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	0xa4
+				MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	0xa4
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX53_PAD_DISP0_DAT8__PWM1_PWMO		0x5
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DIOW__UART1_TXD_MUX	0x1e4
+				MX53_PAD_PATA_DMACK__UART1_RXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_CS_0__UART3_TXD_MUX	0x1e4
+				MX53_PAD_PATA_CS_1__UART3_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DA_1__UART3_CTS		0x1e4
+				MX53_PAD_PATA_DA_2__UART3_RTS		0x1e4
+			>;
+		};
 	};
 };
 
 &nfc {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_nand_1>;
+	pinctrl-0 = <&pinctrl_nand>;
 	nand-bus-width = <8>;
 	nand-ecc-mode = "hw";
 	status = "okay";
@@ -231,7 +416,11 @@
 
 &pwm1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm1_1>;
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&sata {
 	status = "okay";
 };
 
@@ -242,18 +431,29 @@
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	phy_type = "utmi";
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "peripheral";
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
index a63090267941..a398745bc9a3 100644
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ b/arch/arm/boot/dts/imx53-mba53.dts
@@ -17,14 +17,6 @@
 	model = "TQ MBa53 starter kit";
 	compatible = "tq,mba53", "tq,tqma53", "fsl,imx53";
 
-	reg_backlight: fixed@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "lcd-supply";
-		gpio = <&gpio2 5 0>;
-		startup-delay-us = <5000>;
-		enable-active-low;
-	};
-
 	backlight {
 		compatible = "pwm-backlight";
 		pwms = <&pwm2 0 50000>;
@@ -43,12 +35,33 @@
 		status = "disabled";
 	};
 
-	reg_3p2v: 3p2v {
-		compatible = "regulator-fixed";
-		regulator-name = "3P2V";
-		regulator-min-microvolt = <3200000>;
-		regulator-max-microvolt = <3200000>;
-		regulator-always-on;
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 1>;
+		connectors = <&disp1>, <&tve>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_backlight: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "lcd-supply";
+			gpio = <&gpio2 5 0>;
+			startup-delay-us = <5000>;
+		};
+
+		reg_3p2v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P2V";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
 	};
 
 	sound {
@@ -148,14 +161,14 @@
 &audmux {
 	status = "okay";
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
+	pinctrl-0 = <&pinctrl_audmux>;
 };
 
 &i2c2 {
 	codec: sgtl5000@a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 150>;
+		clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
 		VDDA-supply = <&reg_3p2v>;
 		VDDIO-supply = <&reg_3p2v>;
 	};
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
new file mode 100644
index 000000000000..5dd37c7c38b8
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx53.dtsi"
+
+/ {
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	display0: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		crtcs = <&ipu 0>;
+		interface-pix-fmt = "rgb565";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu_disp0>;
+		status = "disabled";
+		display-timings {
+			claawvga {
+				native-mode;
+				clock-frequency = <27000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <40>;
+				hfront-porch = <60>;
+				vback-porch = <10>;
+				vfront-porch = <10>;
+				hsync-len = <20>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 8 0>;
+			linux,code = <116>; /* KEY_POWER */
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio2 14 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+			gpio-key,wakeup;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio2 15 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio7_7>;
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio7 7 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p2v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P2V";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
+
+		reg_usb_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio7 8 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx53-qsb-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx53-qsb-sgtl5000";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <2>;
+		mux-ext-port = <5>;
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&esdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc3>;
+	cd-gpios = <&gpio3 11 0>;
+	wp-gpios = <&gpio3 12 0>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx53-qsb {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
+				MX53_PAD_GPIO_8__GPIO1_8          0x80000000
+				MX53_PAD_PATA_DATA14__GPIO2_14    0x80000000
+				MX53_PAD_PATA_DATA15__GPIO2_15    0x80000000
+				MX53_PAD_EIM_DA11__GPIO3_11       0x80000000
+				MX53_PAD_EIM_DA12__GPIO3_12       0x80000000
+				MX53_PAD_PATA_DA_0__GPIO7_6       0x80000000
+				MX53_PAD_PATA_DA_2__GPIO7_8	  0x80000000
+				MX53_PAD_GPIO_16__GPIO7_11        0x80000000
+			>;
+		};
+
+		led_pin_gpio7_7: led_gpio7_7@0 {
+			fsl,pins = <
+				MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
+			>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	0x80000000
+				MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	0x80000000
+				MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	0x80000000
+				MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+				MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+				MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+				MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+				MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+				MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_esdhc3: esdhc3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DATA8__ESDHC3_DAT0	0x1d5
+				MX53_PAD_PATA_DATA9__ESDHC3_DAT1	0x1d5
+				MX53_PAD_PATA_DATA10__ESDHC3_DAT2	0x1d5
+				MX53_PAD_PATA_DATA11__ESDHC3_DAT3	0x1d5
+				MX53_PAD_PATA_DATA0__ESDHC3_DAT4	0x1d5
+				MX53_PAD_PATA_DATA1__ESDHC3_DAT5	0x1d5
+				MX53_PAD_PATA_DATA2__ESDHC3_DAT6	0x1d5
+				MX53_PAD_PATA_DATA3__ESDHC3_DAT7	0x1d5
+				MX53_PAD_PATA_RESET_B__ESDHC3_CMD	0x1d5
+				MX53_PAD_PATA_IORDY__ESDHC3_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT8__I2C1_SDA		0xc0000000
+				MX53_PAD_CSI0_DAT9__I2C1_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_ROW3__I2C2_SDA		0xc0000000
+				MX53_PAD_KEY_COL3__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_ipu_disp0: ipudisp0grp {
+			fsl,pins = <
+				MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	0x5
+				MX53_PAD_DI0_PIN15__IPU_DI0_PIN15	0x5
+				MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		0x5
+				MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		0x5
+				MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0	0x5
+				MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1	0x5
+				MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2	0x5
+				MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3	0x5
+				MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4	0x5
+				MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5	0x5
+				MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6	0x5
+				MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7	0x5
+				MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8	0x5
+				MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9	0x5
+				MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10	0x5
+				MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11	0x5
+				MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12	0x5
+				MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13	0x5
+				MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14	0x5
+				MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15	0x5
+				MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16	0x5
+				MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17	0x5
+				MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18	0x5
+				MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19	0x5
+				MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20	0x5
+				MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21	0x5
+				MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22	0x5
+				MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23	0x5
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	0x1e4
+				MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	0x1e4
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_3p2v>;
+		VDDIO-supply = <&reg_3p2v>;
+		clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	accelerometer: mma8450@1c {
+		compatible = "fsl,mma8450";
+		reg = <0x1c>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio7 6 0>;
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
+
+&vpu {
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_vbus>;
+	phy_type = "utmi";
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 91a5935a4aac..b2de00c6163b 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -11,193 +11,19 @@
  */
 
 /dts-v1/;
-#include "imx53.dtsi"
+#include "imx53-qsb-common.dtsi"
 
 / {
 	model = "Freescale i.MX53 Quick Start Board";
 	compatible = "fsl,imx53-qsb", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x40000000>;
-	};
-
-	display@di0 {
-		compatible = "fsl,imx-parallel-display";
+	imx-drm {
+		compatible = "fsl,imx-drm";
 		crtcs = <&ipu 0>;
-		interface-pix-fmt = "rgb565";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp0_1>;
-		status = "disabled";
-		display-timings {
-			claawvga {
-				native-mode;
-				clock-frequency = <27000000>;
-				hactive = <800>;
-				vactive = <480>;
-				hback-porch = <40>;
-				hfront-porch = <60>;
-				vback-porch = <10>;
-				vfront-porch = <10>;
-				hsync-len = <20>;
-				vsync-len = <10>;
-				hsync-active = <0>;
-				vsync-active = <0>;
-				de-active = <1>;
-				pixelclk-active = <0>;
-			};
-		};
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		power {
-			label = "Power Button";
-			gpios = <&gpio1 8 0>;
-			linux,code = <116>; /* KEY_POWER */
-		};
-
-		volume-up {
-			label = "Volume Up";
-			gpios = <&gpio2 14 0>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
-			gpio-key,wakeup;
-		};
-
-		volume-down {
-			label = "Volume Down";
-			gpios = <&gpio2 15 0>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
-			gpio-key,wakeup;
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&led_pin_gpio7_7>;
-
-		user {
-			label = "Heartbeat";
-			gpios = <&gpio7 7 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_3p2v: 3p2v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P2V";
-			regulator-min-microvolt = <3200000>;
-			regulator-max-microvolt = <3200000>;
-			regulator-always-on;
-		};
-
-		reg_usb_vbus: usb_vbus {
-			compatible = "regulator-fixed";
-			regulator-name = "usb_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			gpio = <&gpio7 8 0>;
-			enable-active-high;
-		};
-	};
-
-	sound {
-		compatible = "fsl,imx53-qsb-sgtl5000",
-			     "fsl,imx-audio-sgtl5000";
-		model = "imx53-qsb-sgtl5000";
-		ssi-controller = <&ssi2>;
-		audio-codec = <&sgtl5000>;
-		audio-routing =
-			"MIC_IN", "Mic Jack",
-			"Mic Jack", "Mic Bias",
-			"Headphone Jack", "HP_OUT";
-		mux-int-port = <2>;
-		mux-ext-port = <5>;
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	status = "okay";
-};
-
-&ssi2 {
-	fsl,mode = "i2s-slave";
-	status = "okay";
-};
-
-&esdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	cd-gpios = <&gpio3 11 0>;
-	wp-gpios = <&gpio3 12 0>;
-	bus-width = <8>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
-				MX53_PAD_GPIO_8__GPIO1_8          0x80000000
-				MX53_PAD_PATA_DATA14__GPIO2_14    0x80000000
-				MX53_PAD_PATA_DATA15__GPIO2_15    0x80000000
-				MX53_PAD_EIM_DA11__GPIO3_11       0x80000000
-				MX53_PAD_EIM_DA12__GPIO3_12       0x80000000
-				MX53_PAD_PATA_DA_0__GPIO7_6       0x80000000
-				MX53_PAD_PATA_DA_2__GPIO7_8	  0x80000000
-				MX53_PAD_GPIO_16__GPIO7_11        0x80000000
-			>;
-		};
-
-		led_pin_gpio7_7: led_gpio7_7@0 {
-			fsl,pins = <
-				MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
-			>;
-		};
-	};
-
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	sgtl5000: codec@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		VDDA-supply = <&reg_3p2v>;
-		VDDIO-supply = <&reg_3p2v>;
-		clocks = <&clks 150>;
+		connectors = <&display0>;
 	};
 };
 
 &i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-	status = "okay";
-
-	accelerometer: mma8450@1c {
-		compatible = "fsl,mma8450";
-		reg = <0x1c>;
-	};
-
 	pmic: dialog@48 {
 		compatible = "dlg,da9053-aa", "dlg,da9052";
 		reg = <0x48>;
@@ -292,32 +118,3 @@
 		};
 	};
 };
-
-&audmux {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	phy-reset-gpios = <&gpio7 6 0>;
-	status = "okay";
-};
-
-&vpu {
-	status = "okay";
-};
-
-&usbh1 {
-	vbus-supply = <&reg_usb_vbus>;
-	phy_type = "utmi";
-	status = "okay";
-};
-
-&usbotg {
-	dr_mode = "peripheral";
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-qsrb.dts b/arch/arm/boot/dts/imx53-qsrb.dts
new file mode 100644
index 000000000000..f1bbf9a32991
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsrb.dts
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx53-qsb-common.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Quick Start-R Board";
+	compatible = "fsl,imx53-qsrb", "fsl,imx53";
+};
+
+&iomuxc {
+	i2c1 {
+		/* open drain */
+		pinctrl_i2c1_qsrb: i2c1grp-1 {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT8__I2C1_SDA      0x400001ec
+				MX53_PAD_CSI0_DAT9__I2C1_SCL      0x400001ec
+			>;
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_qsrb>;
+	status = "okay";
+
+	pmic: mc34708@8 {
+		compatible = "fsl,mc34708";
+		reg = <0x08>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <23 0x8>;
+		regulators {
+			sw1_reg: sw1a {
+				regulator-name = "SW1";
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <1437500>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw1b_reg: sw1b {
+				regulator-name = "SW1B";
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <1437500>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-name = "SW2";
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <1437500>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: sw3 {
+				regulator-name = "SW3";
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <1425000>;
+				regulator-boot-on;
+			};
+
+			sw4a_reg: sw4a {
+				regulator-name = "SW4A";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4b_reg: sw4b {
+				regulator-name = "SW4B";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw5_reg: sw5 {
+				regulator-name = "SW5";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst {
+				regulator-name = "SWBST";
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vpll_reg: vpll {
+				regulator-name = "VPLL";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			vrefddr_reg: vrefddr {
+				regulator-name = "VREFDDR";
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vusb_reg: vusb {
+				regulator-name = "VUSB";
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vusb2_reg: vusb2 {
+				regulator-name = "VUSB2";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vdac_reg: vdac {
+				regulator-name = "VDAC";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2775000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-name = "VGEN1";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-name = "VGEN2";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
index a9b6e10de0a5..5ec1590ff7bc 100644
--- a/arch/arm/boot/dts/imx53-smd.dts
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -40,7 +40,7 @@
 
 &esdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	pinctrl-0 = <&pinctrl_esdhc1>;
 	cd-gpios = <&gpio3 13 0>;
 	wp-gpios = <&gpio4 11 0>;
 	status = "okay";
@@ -48,21 +48,21 @@
 
 &esdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	pinctrl-0 = <&pinctrl_esdhc2>;
 	non-removable;
 	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
 &ecspi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	fsl,spi-num-chipselects = <2>;
 	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
 	status = "okay";
@@ -95,7 +95,7 @@
 
 &esdhc3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	pinctrl-0 = <&pinctrl_esdhc3>;
 	non-removable;
 	status = "okay";
 };
@@ -104,7 +104,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx53-smd {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
@@ -116,24 +116,121 @@
 				MX53_PAD_PATA_DA_0__GPIO7_6    0x80000000
 			>;
 		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D16__ECSPI1_SCLK		0x80000000
+				MX53_PAD_EIM_D17__ECSPI1_MISO		0x80000000
+				MX53_PAD_EIM_D18__ECSPI1_MOSI		0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+				MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+				MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+				MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+				MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+				MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_esdhc2: esdhc2grp {
+			fsl,pins = <
+				MX53_PAD_SD2_CMD__ESDHC2_CMD		0x1d5
+				MX53_PAD_SD2_CLK__ESDHC2_CLK		0x1d5
+				MX53_PAD_SD2_DATA0__ESDHC2_DAT0		0x1d5
+				MX53_PAD_SD2_DATA1__ESDHC2_DAT1		0x1d5
+				MX53_PAD_SD2_DATA2__ESDHC2_DAT2		0x1d5
+				MX53_PAD_SD2_DATA3__ESDHC2_DAT3		0x1d5
+			>;
+		};
+
+		pinctrl_esdhc3: esdhc3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DATA8__ESDHC3_DAT0	0x1d5
+				MX53_PAD_PATA_DATA9__ESDHC3_DAT1	0x1d5
+				MX53_PAD_PATA_DATA10__ESDHC3_DAT2	0x1d5
+				MX53_PAD_PATA_DATA11__ESDHC3_DAT3	0x1d5
+				MX53_PAD_PATA_DATA0__ESDHC3_DAT4	0x1d5
+				MX53_PAD_PATA_DATA1__ESDHC3_DAT5	0x1d5
+				MX53_PAD_PATA_DATA2__ESDHC3_DAT6	0x1d5
+				MX53_PAD_PATA_DATA3__ESDHC3_DAT7	0x1d5
+				MX53_PAD_PATA_RESET_B__ESDHC3_CMD	0x1d5
+				MX53_PAD_PATA_IORDY__ESDHC3_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT8__I2C1_SDA		0xc0000000
+				MX53_PAD_CSI0_DAT9__I2C1_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_ROW3__I2C2_SDA		0xc0000000
+				MX53_PAD_KEY_COL3__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	0x1e4
+				MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_CS_0__UART3_TXD_MUX	0x1e4
+				MX53_PAD_PATA_CS_1__UART3_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DA_1__UART3_CTS		0x1e4
+				MX53_PAD_PATA_DA_2__UART3_RTS		0x1e4
+			>;
+		};
 	};
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "okay";
 };
 
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 
 	codec: sgtl5000@0a {
@@ -154,7 +251,7 @@
 
 &i2c1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	accelerometer: mma8450@1c {
@@ -175,7 +272,7 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "rmii";
 	phy-reset-gpios = <&gpio7 6 0>;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsi b/arch/arm/boot/dts/imx53-tqma53.dtsi
index abd72af545bf..4f1f0e2868bf 100644
--- a/arch/arm/boot/dts/imx53-tqma53.dtsi
+++ b/arch/arm/boot/dts/imx53-tqma53.dtsi
@@ -22,9 +22,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -35,8 +38,8 @@
 
 &esdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>,
-		    <&pinctrl_tqma53_esdhc2_2>;
+	pinctrl-0 = <&pinctrl_esdhc2>,
+		    <&pinctrl_esdhc2_cdwp>;
 	vmmc-supply = <&reg_3p3v>;
 	wp-gpios = <&gpio1 2 0>;
 	cd-gpios = <&gpio1 4 0>;
@@ -45,13 +48,13 @@
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_2>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	status = "disabled";
 };
 
 &ecspi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	fsl,spi-num-chipselects = <4>;
 	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>,
 		   <&gpio3 24 0>, <&gpio3 25 0>;
@@ -60,7 +63,7 @@
 
 &esdhc3 { /* EMMC */
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	pinctrl-0 = <&pinctrl_esdhc3>;
 	vmmc-supply = <&reg_3p3v>;
 	non-removable;
 	bus-width = <8>;
@@ -71,27 +74,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	esdhc2_2 {
-		pinctrl_tqma53_esdhc2_2: esdhc2-tqma53-grp2 {
-			fsl,pins = <
-				MX53_PAD_GPIO_4__GPIO1_4	0x80000000 /* SD2_CD */
-				MX53_PAD_GPIO_2__GPIO1_2	0x80000000 /* SD2_WP */
-			>;
-		};
-	};
-
-	i2s {
-		pinctrl_i2s_1: i2s-grp1 {
-			fsl,pins = <
-				 MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x80000000 /* I2S_SCLK */
-				 MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x80000000 /* I2S_DOUT */
-				 MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000 /* I2S_LRCLK */
-				 MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x80000000 /* I2S_DIN */
-			>;
-		};
-	};
-
-	hog {
+	imx53-tqma53 {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				 MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000 /* SSI_MCLK */
@@ -107,43 +90,165 @@
 				 MX53_PAD_GPIO_1__PWM2_PWMO	 0x80000000 /* LCD_CONTRAST */
 			>;
 		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	0x80000000
+				MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	0x80000000
+				MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	0x80000000
+				MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	0x80000000
+			>;
+		};
+
+		pinctrl_can1: can1grp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL2__CAN1_TXCAN		0x80000000
+				MX53_PAD_KEY_ROW2__CAN1_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_can2: can2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL4__CAN2_TXCAN		0x80000000
+				MX53_PAD_KEY_ROW4__CAN2_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_cspi: cspigrp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__CSPI_MISO		0x1d5
+				MX53_PAD_SD1_CMD__CSPI_MOSI		0x1d5
+				MX53_PAD_SD1_CLK__CSPI_SCLK		0x1d5
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D16__ECSPI1_SCLK		0x80000000
+				MX53_PAD_EIM_D17__ECSPI1_MISO		0x80000000
+				MX53_PAD_EIM_D18__ECSPI1_MOSI		0x80000000
+			>;
+		};
+
+		pinctrl_esdhc2: esdhc2grp {
+			fsl,pins = <
+				MX53_PAD_SD2_CMD__ESDHC2_CMD		0x1d5
+				MX53_PAD_SD2_CLK__ESDHC2_CLK		0x1d5
+				MX53_PAD_SD2_DATA0__ESDHC2_DAT0		0x1d5
+				MX53_PAD_SD2_DATA1__ESDHC2_DAT1		0x1d5
+				MX53_PAD_SD2_DATA2__ESDHC2_DAT2		0x1d5
+				MX53_PAD_SD2_DATA3__ESDHC2_DAT3		0x1d5
+			>;
+		};
+
+		pinctrl_esdhc2_cdwp: esdhc2cdwp {
+			fsl,pins = <
+				MX53_PAD_GPIO_4__GPIO1_4	0x80000000 /* SD2_CD */
+				MX53_PAD_GPIO_2__GPIO1_2	0x80000000 /* SD2_WP */
+			>;
+		};
+
+		pinctrl_esdhc3: esdhc3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DATA8__ESDHC3_DAT0	0x1d5
+				MX53_PAD_PATA_DATA9__ESDHC3_DAT1	0x1d5
+				MX53_PAD_PATA_DATA10__ESDHC3_DAT2	0x1d5
+				MX53_PAD_PATA_DATA11__ESDHC3_DAT3	0x1d5
+				MX53_PAD_PATA_DATA0__ESDHC3_DAT4	0x1d5
+				MX53_PAD_PATA_DATA1__ESDHC3_DAT5	0x1d5
+				MX53_PAD_PATA_DATA2__ESDHC3_DAT6	0x1d5
+				MX53_PAD_PATA_DATA3__ESDHC3_DAT7	0x1d5
+				MX53_PAD_PATA_RESET_B__ESDHC3_CMD	0x1d5
+				MX53_PAD_PATA_IORDY__ESDHC3_CLK		0x1d5
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_ROW3__I2C2_SDA		0xc0000000
+				MX53_PAD_KEY_COL3__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_6__I2C3_SDA		0xc0000000
+				MX53_PAD_GPIO_5__I2C3_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DIOW__UART1_TXD_MUX	0x1e4
+				MX53_PAD_PATA_DMACK__UART1_RXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_CS_0__UART3_TXD_MUX	0x1e4
+				MX53_PAD_PATA_CS_1__UART3_RXD_MUX	0x1e4
+			>;
+		};
 	};
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	fsl,uart-has-rtscts;
 	status = "disabled";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "disabled";
 };
 
 &can1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can1_2>;
+	pinctrl-0 = <&pinctrl_can1>;
 	status = "disabled";
 };
 
 &can2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can2_1>;
+	pinctrl-0 = <&pinctrl_can2>;
 	status = "disabled";
 };
 
 &i2c3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3_1>;
+	pinctrl-0 = <&pinctrl_i2c3>;
 	status = "disabled";
 };
 
 &cspi {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_cspi_1>;
+	pinctrl-0 = <&pinctrl_cspi>;
 	fsl,spi-num-chipselects = <3>;
 	cs-gpios = <&gpio1 18 0>, <&gpio1 19 0>,
 		   <&gpio1 21 0>;
@@ -152,7 +257,7 @@
 
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 
 	pmic: mc34708@8 {
@@ -177,7 +282,7 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "rmii";
 	status = "disabled";
 };
diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/imx53-tx53-x03x.dts
new file mode 100644
index 000000000000..0217dde3b36b
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-tx53-x03x.dts
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx53-tx53.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "Ka-Ro electronics TX53 module (LCD)";
+	compatible = "karo,tx53", "fsl,imx53";
+
+	aliases {
+		display = &display;
+	};
+
+	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";
+
+			display-timings {
+				VGA {
+					clock-frequency = <25200000>;
+					hactive = <640>;
+					vactive = <480>;
+					hback-porch = <48>;
+					hsync-len = <96>;
+					hfront-porch = <16>;
+					vback-porch = <31>;
+					vsync-len = <2>;
+					vfront-porch = <12>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+
+				ETV570 {
+					clock-frequency = <25200000>;
+					hactive = <640>;
+					vactive = <480>;
+					hback-porch = <114>;
+					hsync-len = <30>;
+					hfront-porch = <16>;
+					vback-porch = <32>;
+					vsync-len = <3>;
+					vfront-porch = <10>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+
+				ET0350 {
+					clock-frequency = <6413760>;
+					hactive = <320>;
+					vactive = <240>;
+					hback-porch = <34>;
+					hsync-len = <34>;
+					hfront-porch = <20>;
+					vback-porch = <15>;
+					vsync-len = <3>;
+					vfront-porch = <4>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+
+				ET0430 {
+					clock-frequency = <9009000>;
+					hactive = <480>;
+					vactive = <272>;
+					hback-porch = <2>;
+					hsync-len = <41>;
+					hfront-porch = <2>;
+					vback-porch = <2>;
+					vsync-len = <10>;
+					vfront-porch = <2>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <1>;
+				};
+
+				ET0500 {
+					clock-frequency = <33264000>;
+					hactive = <800>;
+					vactive = <480>;
+					hback-porch = <88>;
+					hsync-len = <128>;
+					hfront-porch = <40>;
+					vback-porch = <33>;
+					vsync-len = <2>;
+					vfront-porch = <10>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+
+				ET0700 { /* same as ET0500 */
+					clock-frequency = <33264000>;
+					hactive = <800>;
+					vactive = <480>;
+					hback-porch = <88>;
+					hsync-len = <128>;
+					hfront-porch = <40>;
+					vback-porch = <33>;
+					vsync-len = <2>;
+					vfront-porch = <10>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+
+				ETQ570 {
+					clock-frequency = <6596040>;
+					hactive = <320>;
+					vactive = <240>;
+					hback-porch = <38>;
+					hsync-len = <30>;
+					hfront-porch = <30>;
+					vback-porch = <16>;
+					vsync-len = <3>;
+					vfront-porch = <4>;
+					hsync-active = <0>;
+					vsync-active = <0>;
+					de-active = <1>;
+					pixelclk-active = <0>;
+				};
+			};
+		};
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_3v3>;
+		brightness-levels = <
+			  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 32 33 34 35 36 37 38 39
+			 40 41 42 43 44 45 46 47 48 49
+			 50 51 52 53 54 55 56 57 58 59
+			 60 61 62 63 64 65 66 67 68 69
+			 70 71 72 73 74 75 76 77 78 79
+			 80 81 82 83 84 85 86 87 88 89
+			 90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <50>;
+	};
+
+	regulators {
+		reg_lcd_pwr: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "LCD POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+
+		reg_lcd_reset: regulator@6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "LCD RESET";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_2v5>;
+		VDDIO-supply = <&reg_3v3>;
+		clocks = <&mclk>;
+	};
+
+	polytouch: edt-ft5x06@38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_edt_ft5x06_1>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <15 0>;
+		reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+		wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+	};
+
+	touchscreen: tsc2007@48 {
+		compatible = "ti,tsc2007";
+		reg = <0x48>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2007>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <26 0>;
+		gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;
+		ti,x-plate-ohms = <660>;
+		linux,wakeup;
+	};
+};
+
+&iomuxc {
+	imx53-tx53-x03x {
+		pinctrl_edt_ft5x06_1: edt-ft5x06grp-1 {
+			fsl,pins = <
+				MX53_PAD_NANDF_CS2__GPIO6_15 0x1f0 /* Interrupt */
+				MX53_PAD_EIM_A16__GPIO2_22   0x04 /* Reset */
+				MX53_PAD_EIM_A17__GPIO2_21   0x04 /* Wake */
+			>;
+		};
+
+		pinctrl_kpp: kppgrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_9__KPP_COL_6 0x1f4
+				MX53_PAD_GPIO_4__KPP_COL_7 0x1f4
+				MX53_PAD_KEY_COL2__KPP_COL_2 0x1f4
+				MX53_PAD_KEY_COL3__KPP_COL_3 0x1f4
+				MX53_PAD_GPIO_2__KPP_ROW_6 0x1f4
+				MX53_PAD_GPIO_5__KPP_ROW_7 0x1f4
+				MX53_PAD_KEY_ROW2__KPP_ROW_2 0x1f4
+				MX53_PAD_KEY_ROW3__KPP_ROW_3 0x1f4
+			>;
+		};
+
+		pinctrl_rgb24_vga1: rgb24-vgagrp1 {
+			fsl,pins = <
+				MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		0x5
+				MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		0x5
+				MX53_PAD_DI0_PIN2__IPU_DI0_PIN2			0x5
+				MX53_PAD_DI0_PIN3__IPU_DI0_PIN3			0x5
+				MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		0x5
+				MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		0x5
+				MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		0x5
+				MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		0x5
+				MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		0x5
+				MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		0x5
+				MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		0x5
+				MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		0x5
+				MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		0x5
+				MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		0x5
+				MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		0x5
+				MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		0x5
+				MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		0x5
+				MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		0x5
+				MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		0x5
+				MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		0x5
+				MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		0x5
+				MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		0x5
+				MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		0x5
+				MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		0x5
+				MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		0x5
+				MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		0x5
+				MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		0x5
+				MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		0x5
+			>;
+		};
+
+		pinctrl_tsc2007: tsc2007grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D26__GPIO3_26 0x1f0 /* Interrupt */
+			>;
+		};
+	};
+};
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp>;
+	/* sample keymap */
+	/* row/col 0,1 are mapped to KPP row/col 6,7 */
+	linux,keymap = <
+		MATRIX_KEY(6, 6, KEY_POWER)
+		MATRIX_KEY(6, 7, KEY_KP0)
+		MATRIX_KEY(6, 2, KEY_KP1)
+		MATRIX_KEY(6, 3, KEY_KP2)
+		MATRIX_KEY(7, 6, KEY_KP3)
+		MATRIX_KEY(7, 7, KEY_KP4)
+		MATRIX_KEY(7, 2, KEY_KP5)
+		MATRIX_KEY(7, 3, KEY_KP6)
+		MATRIX_KEY(2, 6, KEY_KP7)
+		MATRIX_KEY(2, 7, KEY_KP8)
+		MATRIX_KEY(2, 2, KEY_KP9)
+	>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-tx53-x13x.dts b/arch/arm/boot/dts/imx53-tx53-x13x.dts
new file mode 100644
index 000000000000..64804719f0f4
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-tx53-x13x.dts
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx53-tx53.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Ka-Ro electronics TX53 module (LVDS)";
+	compatible = "karo,tx53", "fsl,imx53";
+
+	aliases {
+		display = &lvds0;
+		lvds0 = &lvds0;
+		lvds1 = &lvds1;
+	};
+
+	backlight0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_3v3>;
+		brightness-levels = <
+			  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 32 33 34 35 36 37 38 39
+			 40 41 42 43 44 45 46 47 48 49
+			 50 51 52 53 54 55 56 57 58 59
+			 60 61 62 63 64 65 66 67 68 69
+			 70 71 72 73 74 75 76 77 78 79
+			 80 81 82 83 84 85 86 87 88 89
+			 90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <50>;
+	};
+
+	backlight1: backlight1 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 500000 0>;
+		power-supply = <&reg_3v3>;
+		brightness-levels = <
+			  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 32 33 34 35 36 37 38 39
+			 40 41 42 43 44 45 46 47 48 49
+			 50 51 52 53 54 55 56 57 58 59
+			 60 61 62 63 64 65 66 67 68 69
+			 70 71 72 73 74 75 76 77 78 79
+			 80 81 82 83 84 85 86 87 88 89
+			 90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <50>;
+	};
+
+	regulators {
+		reg_lcd_pwr0: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "LVDS0 POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+
+		reg_lcd_pwr1: regulator@6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "LVDS1 POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	touchscreen2: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti2>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <23 0>;
+		wakeup-gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+		linux,wakeup;
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_2v5>;
+		VDDIO-supply = <&reg_3v3>;
+		clocks = <&mclk>;
+	};
+
+	touchscreen1: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti1>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <22 0>;
+		wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		linux,wakeup;
+	};
+};
+
+&iomuxc {
+	imx53-tx53-x13x {
+		pinctrl_i2c2: i2c2-grp1 {
+			fsl,pins = <
+				MX53_PAD_KEY_ROW3__I2C2_SDA		0xc0000000
+				MX53_PAD_KEY_COL3__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_lvds0: lvds0grp {
+			fsl,pins = <
+				MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
+				MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
+				MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
+				MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
+				MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
+			>;
+		};
+
+		pinctrl_lvds1: lvds1grp {
+			fsl,pins = <
+				MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x80000000
+				MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x80000000
+				MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x80000000
+				MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x80000000
+				MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x80000000
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <MX53_PAD_GPIO_9__PWM1_PWMO 0x04>;
+		};
+
+		pinctrl_eeti1: eeti1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D22__GPIO3_22 0x1f0 /* Interrupt */
+			>;
+		};
+
+		pinctrl_eeti2: eeti2grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D23__GPIO3_23 0x1f0 /* Interrupt */
+			>;
+		};
+	};
+};
+
+&ldb {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lvds0 &pinctrl_lvds1>;
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		fsl,data-mapping = "jeida";
+		fsl,data-width = <24>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds_timing0>;
+			lvds_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hsync-len = <60>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vsync-len = <10>;
+				vfront-porch = <7>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		fsl,data-mapping = "jeida";
+		fsl,data-width = <24>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds_timing1>;
+			lvds_timing1: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hsync-len = <60>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vsync-len = <10>;
+				vfront-porch = <7>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/imx53-tx53.dtsi
index f494766700a3..e348796ba689 100644
--- a/arch/arm/boot/dts/imx53-tx53.dtsi
+++ b/arch/arm/boot/dts/imx53-tx53.dtsi
@@ -1,122 +1,550 @@
 /*
- * Copyright 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ * Copyright 2012 <LW@KARO-electronics.de>
+ * based on imx53-qsb.dts
+ *   Copyright 2011 Freescale Semiconductor, Inc.
+ *   Copyright 2011 Linaro Ltd.
  *
  * 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:
+ * Version 2 at the following locations:
  *
  * http://www.opensource.org/licenses/gpl-license.html
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-/include/ "imx53.dtsi"
+#include "imx53.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
-	model = "Ka-Ro TX53";
+	model = "Ka-Ro electronics TX53 module";
 	compatible = "karo,tx53", "fsl,imx53";
 
-	memory {
-		reg = <0x70000000 0x40000000>; /* Up to 1GiB */
+	aliases {
+		can0 = &can2; /* Make the can interface indices consistent with TX28/TX48 modules */
+		can1 = &can1;
+		ipu = &ipu;
+		reg_can_xcvr = &reg_can_xcvr;
+		usbh1 = &usbh1;
+		usbotg = &usbotg;
+	};
+
+	clocks {
+		ckih1 {
+			clock-frequency = <0>;
+		};
+
+		mclk: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <27000000>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_key>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_stk5led>;
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
 	};
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_2v5: regulator@0 {
 			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
+			reg = <0>;
+			regulator-name = "2V5";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+		};
+
+		reg_3v3: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3V3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
 		};
+
+		reg_can_xcvr: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "CAN XCVR";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_can_xcvr>;
+			gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+		};
+
+		reg_usbh1_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usbh1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbh1_vbus>;
+			gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usbotg_vbus: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usbotg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbotg_vbus>;
+			gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "karo,tx53-audio-sgtl5000", "fsl,imx-audio-sgtl5000";
+		model = "tx53-audio-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		/* '1' based port numbers according to datasheet names */
+		mux-int-port = <1>;
+		mux-ext-port = <5>;
 	};
 };
 
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ssi1>;
+	status = "okay";
+};
+
 &can1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can1_2>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_can1>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
 };
 
 &can2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can2_1>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_can2>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
 };
 
 &ecspi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_2>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <2>;
+	status = "okay";
+
+	cs-gpios = <
+		&gpio2 30 GPIO_ACTIVE_HIGH
+		&gpio3 19 GPIO_ACTIVE_HIGH
+	>;
+
+	spidev0: spi@0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <54000000>;
+	};
+
+	spidev1: spi@1 {
+		compatible = "spidev";
+		reg = <1>;
+		spi-max-frequency = <54000000>;
+	};
 };
 
 &esdhc1 {
+	cd-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+	fsl,wp-controller;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_2>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	status = "okay";
 };
 
 &esdhc2 {
+	cd-gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+	fsl,wp-controller;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_esdhc2>;
+	status = "okay";
 };
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "rmii";
-	status = "disabled";
+	phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>;
+	phy-handle = <&phy0>;
+	mac-address = [000000000000]; /* placeholder; will be overwritten by bootloader */
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		interrupt-parent = <&gpio2>;
+		interrupts = <4>;
+		device_type = "ethernet-phy";
+	};
 };
 
-&i2c3 {
+&i2c1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3_2>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	rtc1: ds1339@68 {
+		compatible = "dallas,ds1339";
+		reg = <0x68>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ds1339>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <20 0>;
+	};
 };
 
-&owire {
+&iomuxc {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_owire_1>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx53-tx53 {
+		pinctrl_hog: hoggrp {
+			/* pins not in use by any device on the Starterkit board series */
+			fsl,pins = <
+				/* CMOS Sensor Interface */
+				MX53_PAD_CSI0_DAT12__GPIO5_30 0x1f4
+				MX53_PAD_CSI0_DAT13__GPIO5_31 0x1f4
+				MX53_PAD_CSI0_DAT14__GPIO6_0 0x1f4
+				MX53_PAD_CSI0_DAT15__GPIO6_1 0x1f4
+				MX53_PAD_CSI0_DAT16__GPIO6_2 0x1f4
+				MX53_PAD_CSI0_DAT17__GPIO6_3 0x1f4
+				MX53_PAD_CSI0_DAT18__GPIO6_4 0x1f4
+				MX53_PAD_CSI0_DAT19__GPIO6_5 0x1f4
+				MX53_PAD_CSI0_MCLK__GPIO5_19 0x1f4
+				MX53_PAD_CSI0_VSYNC__GPIO5_21 0x1f4
+				MX53_PAD_CSI0_PIXCLK__GPIO5_18 0x1f4
+				MX53_PAD_GPIO_0__GPIO1_0 0x1f4
+				/* Module Specific Signal */
+				/* MX53_PAD_NANDF_CS2__GPIO6_15 0x1f4 maybe used by EDT-FT5x06 */
+				/* MX53_PAD_EIM_A16__GPIO2_22 0x1f4 maybe used by EDT-FT5x06 */
+				MX53_PAD_EIM_D29__GPIO3_29 0x1f4
+				MX53_PAD_EIM_EB3__GPIO2_31 0x1f4
+				/* MX53_PAD_EIM_A17__GPIO2_21 0x1f4 maybe used by EDT-FT5x06 */
+				/* MX53_PAD_EIM_A18__GPIO2_20 0x1f4 used by LED */
+				MX53_PAD_EIM_A19__GPIO2_19 0x1f4
+				MX53_PAD_EIM_A20__GPIO2_18 0x1f4
+				MX53_PAD_EIM_A21__GPIO2_17 0x1f4
+				MX53_PAD_EIM_A22__GPIO2_16 0x1f4
+				MX53_PAD_EIM_A23__GPIO6_6 0x1f4
+				MX53_PAD_EIM_A24__GPIO5_4 0x1f4
+				MX53_PAD_CSI0_DAT8__GPIO5_26 0x1f4
+				MX53_PAD_CSI0_DAT9__GPIO5_27 0x1f4
+				MX53_PAD_CSI0_DAT10__GPIO5_28 0x1f4
+				MX53_PAD_CSI0_DAT11__GPIO5_29 0x1f4
+				/* MX53_PAD_EIM_D22__GPIO3_22 0x1f4 maybe used by EETI touchpanel driver */
+				/* MX53_PAD_EIM_D23__GPIO3_23 0x1f4 maybe used by EETI touchpanel driver */
+				MX53_PAD_GPIO_13__GPIO4_3 0x1f4
+				MX53_PAD_EIM_CS0__GPIO2_23 0x1f4
+				MX53_PAD_EIM_CS1__GPIO2_24 0x1f4
+				MX53_PAD_CSI0_DATA_EN__GPIO5_20 0x1f4
+				MX53_PAD_EIM_WAIT__GPIO5_0 0x1f4
+				MX53_PAD_EIM_EB0__GPIO2_28 0x1f4
+				MX53_PAD_EIM_EB1__GPIO2_29 0x1f4
+				MX53_PAD_EIM_OE__GPIO2_25 0x1f4
+				MX53_PAD_EIM_LBA__GPIO2_27 0x1f4
+				MX53_PAD_EIM_RW__GPIO2_26 0x1f4
+				MX53_PAD_EIM_DA8__GPIO3_8 0x1f4
+				MX53_PAD_EIM_DA9__GPIO3_9 0x1f4
+				MX53_PAD_EIM_DA10__GPIO3_10 0x1f4
+				MX53_PAD_EIM_DA11__GPIO3_11 0x1f4
+				MX53_PAD_EIM_DA12__GPIO3_12 0x1f4
+				MX53_PAD_EIM_DA13__GPIO3_13 0x1f4
+				MX53_PAD_EIM_DA14__GPIO3_14 0x1f4
+				MX53_PAD_EIM_DA15__GPIO3_15 0x1f4
+				>;
+		};
+
+		pinctrl_can1: can1grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_7__CAN1_TXCAN		0x80000000
+				MX53_PAD_GPIO_8__CAN1_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_can2: can2grp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL4__CAN2_TXCAN		0x80000000
+				MX53_PAD_KEY_ROW4__CAN2_RXCAN		0x80000000
+			>;
+		};
+
+		pinctrl_can_xcvr: can-xcvrgrp {
+			fsl,pins = <MX53_PAD_DISP0_DAT0__GPIO4_21 0xe0>; /* Flexcan XCVR enable */
+		};
+
+		pinctrl_ds1339: ds1339grp {
+			fsl,pins = <MX53_PAD_DI0_PIN4__GPIO4_20 0xe0>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_19__ECSPI1_RDY		0x80000000
+				MX53_PAD_EIM_EB2__ECSPI1_SS0		0x80000000
+				MX53_PAD_EIM_D16__ECSPI1_SCLK		0x80000000
+				MX53_PAD_EIM_D17__ECSPI1_MISO		0x80000000
+				MX53_PAD_EIM_D18__ECSPI1_MOSI		0x80000000
+				MX53_PAD_EIM_D19__ECSPI1_SS1		0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+				MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+				MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+				MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+				MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+				MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+				MX53_PAD_EIM_D24__GPIO3_24 0x1f0
+			>;
+		};
+
+		pinctrl_esdhc2: esdhc2grp {
+			fsl,pins = <
+				MX53_PAD_SD2_CMD__ESDHC2_CMD		0x1d5
+				MX53_PAD_SD2_CLK__ESDHC2_CLK		0x1d5
+				MX53_PAD_SD2_DATA0__ESDHC2_DAT0		0x1d5
+				MX53_PAD_SD2_DATA1__ESDHC2_DAT1		0x1d5
+				MX53_PAD_SD2_DATA2__ESDHC2_DAT2		0x1d5
+				MX53_PAD_SD2_DATA3__ESDHC2_DAT3		0x1d5
+				MX53_PAD_EIM_D25__GPIO3_25 0x1f0
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_gpio_key: gpio-keygrp {
+			fsl,pins = <MX53_PAD_EIM_A25__GPIO5_2 0x1f4>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D21__I2C1_SCL		0xc0000000
+				MX53_PAD_EIM_D28__I2C1_SDA		0xc0000000
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_3__I2C3_SCL		0xc0000000
+				MX53_PAD_GPIO_6__I2C3_SDA		0xc0000000
+			>;
+		};
+
+		pinctrl_nand: nandgrp {
+			fsl,pins = <
+				MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
+				MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
+				MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
+				MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
+				MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
+				MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
+				MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
+				MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0	0xa4
+				MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1	0xa4
+				MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2	0xa4
+				MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3	0xa4
+				MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4	0xa4
+				MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5	0xa4
+				MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	0xa4
+				MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7	0xa4
+			>;
+		};
+
+		pinctrl_pwm2: pwm2grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_1__PWM2_PWMO		0x80000000
+			>;
+		};
+
+		pinctrl_ssi1: ssi1grp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	0x80000000
+				MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	0x80000000
+				MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	0x80000000
+				MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	0x80000000
+			>;
+		};
+
+		pinctrl_ssi2: ssi2grp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	0x80000000
+				MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	0x80000000
+				MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	0x80000000
+				MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	0x80000000
+				MX53_PAD_EIM_D27__GPIO3_27 0x1f0
+			>;
+		};
+
+		pinctrl_stk5led: stk5ledgrp {
+			fsl,pins = <MX53_PAD_EIM_A18__GPIO2_20 0xc0>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DIOW__UART1_TXD_MUX	0x1e4
+				MX53_PAD_PATA_DMACK__UART1_RXD_MUX	0x1e4
+				MX53_PAD_PATA_RESET_B__UART1_CTS	0x1c5
+				MX53_PAD_PATA_IORDY__UART1_RTS		0x1c5
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	0x1c5
+				MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	0x1c5
+				MX53_PAD_PATA_DIOR__UART2_RTS		0x1c5
+				MX53_PAD_PATA_INTRQ__UART2_CTS		0x1c5
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX53_PAD_PATA_CS_0__UART3_TXD_MUX	0x1e4
+				MX53_PAD_PATA_CS_1__UART3_RXD_MUX	0x1e4
+				MX53_PAD_PATA_DA_1__UART3_CTS		0x1e4
+				MX53_PAD_PATA_DA_2__UART3_RTS		0x1e4
+			>;
+		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D30__GPIO3_30 0x100 /* OC */
+			>;
+		};
+
+		pinctrl_usbh1_vbus: usbh1-vbusgrp {
+			fsl,pins = <
+				MX53_PAD_EIM_D31__GPIO3_31 0xe0 /* VBUS ENABLE */
+			>;
+		};
+
+		pinctrl_usbotg_vbus: usbotg-vbusgrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_7__GPIO1_7 0xe0 /* VBUS ENABLE */
+				MX53_PAD_GPIO_8__GPIO1_8 0x100 /* OC */
+			>;
+		};
+	};
+};
+
+&ipu {
+	status = "okay";
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nand>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
 };
 
 &pwm2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm2_1>;
-	status = "disabled";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	#pwm-cells = <3>;
+};
+
+&sdma {
+	fsl,sdma-ram-script-name = "sdma-imx53.bin";
 };
 
 &ssi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-	status = "disabled";
+	fsl,mode = "i2s-slave";
+	codec-handle = <&sgtl5000>;
+	status = "okay";
 };
 
 &ssi2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_2>;
 	status = "disabled";
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>,
-		    <&pinctrl_uart1_3>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	fsl,uart-has-rtscts;
-	status = "disabled";
+	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_2>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	fsl,uart-has-rtscts;
-	status = "disabled";
+	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	fsl,uart-has-rtscts;
-	status = "disabled";
+	status = "okay";
+};
+
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	phy_type = "utmi";
+	disable-over-current;
+	vbus-supply = <&reg_usbh1_vbus>;
+	status = "okay";
+};
+
+&usbotg {
+	phy_type = "utmi";
+	dr_mode = "peripheral";
+	disable-over-current;
+	vbus-supply = <&reg_usbotg_vbus>;
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/imx53-voipac-bsb.dts
new file mode 100644
index 000000000000..7f6711a48615
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-voipac-bsb.dts
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2013 Rostislav Lisovy <lisovy@gmail.com>, PiKRON s.r.o.
+ *
+ * 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 "imx53-voipac-dmm-668.dtsi"
+
+/ {
+	sound {
+		compatible = "fsl,imx53-voipac-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx53-voipac-sgtl5000";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <2>;
+		mux-ext-port = <5>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio>;
+
+		led1 {
+			label = "led-red";
+			gpios = <&gpio3 29 0>;
+			default-state = "off";
+		};
+
+		led2 {
+			label = "led-orange";
+			gpios = <&gpio2 31 0>;
+			default-state = "off";
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx53-voipac {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* SD2_CD */
+				MX53_PAD_EIM_D25__GPIO3_25	0x80000000
+				/* SD2_WP */
+				MX53_PAD_EIM_A19__GPIO2_19 	0x80000000
+			>;
+		};
+
+		led_pin_gpio: led_gpio {
+			fsl,pins = <
+				MX53_PAD_EIM_D29__GPIO3_29	0x80000000
+				MX53_PAD_EIM_EB3__GPIO2_31	0x80000000
+			>;
+		};
+
+		/* Keyboard controller */
+		pinctrl_kpp_1: kppgrp-1 {
+			fsl,pins = <
+				MX53_PAD_GPIO_9__KPP_COL_6	0xe8
+				MX53_PAD_GPIO_4__KPP_COL_7	0xe8
+				MX53_PAD_KEY_COL2__KPP_COL_2	0xe8
+				MX53_PAD_KEY_COL3__KPP_COL_3	0xe8
+				MX53_PAD_KEY_COL4__KPP_COL_4	0xe8
+				MX53_PAD_GPIO_2__KPP_ROW_6	0xe0
+				MX53_PAD_GPIO_5__KPP_ROW_7	0xe0
+				MX53_PAD_KEY_ROW2__KPP_ROW_2	0xe0
+				MX53_PAD_KEY_ROW3__KPP_ROW_3	0xe0
+				MX53_PAD_KEY_ROW4__KPP_ROW_4	0xe0
+			>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	0x80000000
+				MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	0x80000000
+				MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	0x80000000
+				MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	0x80000000
+			>;
+		};
+
+		pinctrl_esdhc2: esdhc2grp {
+			fsl,pins = <
+				MX53_PAD_SD2_CMD__ESDHC2_CMD		0x1d5
+				MX53_PAD_SD2_CLK__ESDHC2_CLK		0x1d5
+				MX53_PAD_SD2_DATA0__ESDHC2_DAT0		0x1d5
+				MX53_PAD_SD2_DATA1__ESDHC2_DAT1		0x1d5
+				MX53_PAD_SD2_DATA2__ESDHC2_DAT2		0x1d5
+				MX53_PAD_SD2_DATA3__ESDHC2_DAT3		0x1d5
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX53_PAD_GPIO_3__I2C3_SCL		0xc0000000
+				MX53_PAD_GPIO_6__I2C3_SDA		0xc0000000
+			>;
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>; /* SSI1 */
+	status = "okay";
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2>;
+	cd-gpios = <&gpio3 25 0>;
+	wp-gpios = <&gpio2 19 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+		clocks = <&clks 150>;
+	};
+};
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp_1>;
+	linux,keymap = <
+			0x0203003b	/* KEY_F1 */
+			0x0603003c	/* KEY_F2 */
+			0x0207003d	/* KEY_F3 */
+			0x0607003e	/* KEY_F4 */
+			>;
+	keypad,num-rows = <8>;
+	keypad,num-columns = <1>;
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
new file mode 100644
index 000000000000..ba689fbd0e41
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2013 Rostislav Lisovy <lisovy@gmail.com>, PiKRON s.r.o.
+ *
+ * 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 "imx53.dtsi"
+
+/ {
+	model = "Voipac i.MX53 X53-DMM-668";
+	compatible = "voipac,imx53-dmm-668", "fsl,imx53";
+
+	memory@70000000 {
+		device_type = "memory";
+		reg = <0x70000000 0x20000000>;
+	};
+
+	memory@b0000000 {
+		device_type = "memory";
+		reg = <0xb0000000 0x20000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 31 0>; /* PEN */
+			enable-active-high;
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx53-voipac {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* Make DA9053 regulator functional */
+				MX53_PAD_GPIO_16__GPIO7_11	0x80000000
+				/* FEC Power enable */
+				MX53_PAD_GPIO_11__GPIO4_1	0x80000000
+				/* FEC RST */
+				MX53_PAD_GPIO_12__GPIO4_2	0x80000000
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D16__ECSPI1_SCLK		0x80000000
+				MX53_PAD_EIM_D17__ECSPI1_MISO		0x80000000
+				MX53_PAD_EIM_D18__ECSPI1_MOSI		0x80000000
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX53_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX53_PAD_FEC_MDIO__FEC_MDIO		0x80000000
+				MX53_PAD_FEC_REF_CLK__FEC_TX_CLK	0x80000000
+				MX53_PAD_FEC_RX_ER__FEC_RX_ER		0x80000000
+				MX53_PAD_FEC_CRS_DV__FEC_RX_DV		0x80000000
+				MX53_PAD_FEC_RXD1__FEC_RDATA_1		0x80000000
+				MX53_PAD_FEC_RXD0__FEC_RDATA_0		0x80000000
+				MX53_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX53_PAD_FEC_TXD1__FEC_TDATA_1		0x80000000
+				MX53_PAD_FEC_TXD0__FEC_TDATA_0		0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D21__I2C1_SCL		0xc0000000
+				MX53_PAD_EIM_D28__I2C1_SDA		0xc0000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX53_PAD_PATA_DIOW__UART1_TXD_MUX	0x1e4
+				MX53_PAD_PATA_DMACK__UART1_RXD_MUX	0x1e4
+			>;
+		};
+
+		pinctrl_nand: nandgrp {
+			fsl,pins = <
+				MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
+				MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
+				MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
+				MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
+				MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
+				MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
+				MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
+				MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	0xa4
+				MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	0xa4
+				MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	0xa4
+				MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	0xa4
+				MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	0xa4
+				MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	0xa4
+				MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	0xa4
+				MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	0xa4
+			>;
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <4>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>, <&gpio2 16 0>, <&gpio2 17 0>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio4 2 0>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: dialog@48 {
+		compatible = "dlg,da9053-aa", "dlg,da9052";
+		reg = <0x48>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
+
+		regulators {
+			buck1_reg: buck1 {
+				regulator-name = "BUCKCORE";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-always-on;
+			};
+
+			buck2_reg: buck2 {
+				regulator-name = "BUCKPRO";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			buck3_reg: buck3 {
+				regulator-name = "BUCKMEM";
+				regulator-min-microvolt = <1420000>;
+				regulator-max-microvolt = <1580000>;
+				regulator-always-on;
+			};
+
+			buck4_reg: buck4 {
+				regulator-name = "BUCKPERI";
+				regulator-min-microvolt = <2370000>;
+				regulator-max-microvolt = <2630000>;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				regulator-name = "ldo1_1v3";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-name = "ldo2_1v3";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ldo3 {
+				regulator-name = "ldo3_3v3";
+				regulator-min-microvolt = <3250000>;
+				regulator-max-microvolt = <3350000>;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ldo4 {
+				regulator-name = "ldo4_2v775";
+				regulator-min-microvolt = <2770000>;
+				regulator-max-microvolt = <2780000>;
+				regulator-always-on;
+			};
+
+			ldo5_reg: ldo5 {
+				regulator-name = "ldo5_3v3";
+				regulator-min-microvolt = <3250000>;
+				regulator-max-microvolt = <3350000>;
+				regulator-always-on;
+			};
+
+			ldo6_reg: ldo6 {
+				regulator-name = "ldo6_1v3";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			ldo7_reg: ldo7 {
+				regulator-name = "ldo7_2v75";
+				regulator-min-microvolt = <2700000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+			};
+
+			ldo8_reg: ldo8 {
+				regulator-name = "ldo8_1v8";
+				regulator-min-microvolt = <1750000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-always-on;
+			};
+
+			ldo9_reg: ldo9 {
+				regulator-name = "ldo9_1v5";
+				regulator-min-microvolt = <1450000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-always-on;
+			};
+
+			ldo10_reg: ldo10 {
+				regulator-name = "ldo10_1v3";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nand>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_vbus>;
+	phy_type = "utmi";
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 4307e80b2d2e..80615dfa2177 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -12,6 +12,9 @@
 
 #include "skeleton.dtsi"
 #include "imx53-pinfunc.h"
+#include <dt-bindings/clock/imx5-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 
 / {
 	aliases {
@@ -25,6 +28,10 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		mmc0 = &esdhc1;
+		mmc1 = &esdhc2;
+		mmc2 = &esdhc3;
+		mmc3 = &esdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -84,12 +91,25 @@
 		interrupt-parent = <&tzic>;
 		ranges;
 
+		sata: sata@10000000 {
+			compatible = "fsl,imx53-ahci";
+			reg = <0x10000000 0x1000>;
+			interrupts = <28>;
+			clocks = <&clks IMX5_CLK_SATA_GATE>,
+				 <&clks IMX5_CLK_SATA_REF>,
+				 <&clks IMX5_CLK_AHB>;
+			clock-names = "sata_gate", "sata_ref", "ahb";
+			status = "disabled";
+		};
+
 		ipu: ipu@18000000 {
 			#crtc-cells = <1>;
 			compatible = "fsl,imx53-ipu";
 			reg = <0x18000000 0x080000000>;
 			interrupts = <11 10>;
-			clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+			clocks = <&clks IMX5_CLK_IPU_GATE>,
+			         <&clks IMX5_CLK_IPU_DI0_GATE>,
+			         <&clks IMX5_CLK_IPU_DI1_GATE>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
 		};
@@ -112,7 +132,9 @@
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50004000 0x4000>;
 					interrupts = <1>;
-					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -122,7 +144,9 @@
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50008000 0x4000>;
 					interrupts = <2>;
-					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -132,7 +156,8 @@
 					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 					reg = <0x5000c000 0x4000>;
 					interrupts = <33>;
-					clocks = <&clks 32>, <&clks 33>;
+					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+					         <&clks IMX5_CLK_UART3_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -143,16 +168,19 @@
 					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
 					reg = <0x50010000 0x4000>;
 					interrupts = <36>;
-					clocks = <&clks 51>, <&clks 52>;
+					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
 				ssi2: ssi@50014000 {
-					compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+					compatible = "fsl,imx53-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x50014000 0x4000>;
 					interrupts = <30>;
-					clocks = <&clks 49>;
+					clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
 					dmas = <&sdma 24 1 0>,
 					       <&sdma 25 1 0>;
 					dma-names = "rx", "tx";
@@ -165,7 +193,9 @@
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50020000 0x4000>;
 					interrupts = <3>;
-					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -175,7 +205,9 @@
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50024000 0x4000>;
 					interrupts = <4>;
-					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+					         <&clks IMX5_CLK_DUMMY>,
+					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -184,14 +216,14 @@
 
 			usbphy0: usbphy@0 {
 				compatible = "usb-nop-xceiv";
-				clocks = <&clks 124>;
+				clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
 				clock-names = "main_clk";
 				status = "okay";
 			};
 
 			usbphy1: usbphy@1 {
 				compatible = "usb-nop-xceiv";
-				clocks = <&clks 125>;
+				clocks = <&clks IMX5_CLK_USB_PHY2_GATE>;
 				clock-names = "main_clk";
 				status = "okay";
 			};
@@ -200,7 +232,7 @@
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80000 0x0200>;
 				interrupts = <18>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 0>;
 				fsl,usbphy = <&usbphy0>;
 				status = "disabled";
@@ -210,7 +242,7 @@
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80200 0x0200>;
 				interrupts = <14>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 1>;
 				fsl,usbphy = <&usbphy1>;
 				status = "disabled";
@@ -220,7 +252,7 @@
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80400 0x0200>;
 				interrupts = <16>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
 			};
@@ -229,7 +261,7 @@
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80600 0x0200>;
 				interrupts = <17>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 				fsl,usbmisc = <&usbmisc 3>;
 				status = "disabled";
 			};
@@ -238,7 +270,7 @@
 				#index-cells = <1>;
 				compatible = "fsl,imx53-usbmisc";
 				reg = <0x53f80800 0x200>;
-				clocks = <&clks 108>;
+				clocks = <&clks IMX5_CLK_USBOH3_GATE>;
 			};
 
 			gpio1: gpio@53f84000 {
@@ -281,18 +313,26 @@
 				#interrupt-cells = <2>;
 			};
 
+			kpp: kpp@53f94000 {
+				compatible = "fsl,imx53-kpp", "fsl,imx21-kpp";
+				reg = <0x53f94000 0x4000>;
+				interrupts = <60>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
+				status = "disabled";
+			};
+
 			wdog1: wdog@53f98000 {
 				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
 				reg = <0x53f98000 0x4000>;
 				interrupts = <58>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
 			};
 
 			wdog2: wdog@53f9c000 {
 				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
 				reg = <0x53f9c000 0x4000>;
 				interrupts = <59>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX5_CLK_DUMMY>;
 				status = "disabled";
 			};
 
@@ -300,521 +340,14 @@
 				compatible = "fsl,imx53-gpt", "fsl,imx31-gpt";
 				reg = <0x53fa0000 0x4000>;
 				interrupts = <39>;
-				clocks = <&clks 36>, <&clks 41>;
+				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+				         <&clks IMX5_CLK_GPT_HF_GATE>;
 				clock-names = "ipg", "per";
 			};
 
 			iomuxc: iomuxc@53fa8000 {
 				compatible = "fsl,imx53-iomuxc";
 				reg = <0x53fa8000 0x4000>;
-
-				audmux {
-					pinctrl_audmux_1: audmuxgrp-1 {
-						fsl,pins = <
-							MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x80000000
-							MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x80000000
-							MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
-							MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x80000000
-						>;
-					};
-
-					pinctrl_audmux_2: audmuxgrp-2 {
-						fsl,pins = <
-							MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	0x80000000
-							MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	0x80000000
-							MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	0x80000000
-							MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	0x80000000
-						>;
-					};
-
-					pinctrl_audmux_3: audmuxgrp-3 {
-						fsl,pins = <
-							MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	0x80000000
-							MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	0x80000000
-							MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	0x80000000
-							MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	0x80000000
-						>;
-					};
-				};
-
-				fec {
-					pinctrl_fec_1: fecgrp-1 {
-						fsl,pins = <
-							MX53_PAD_FEC_MDC__FEC_MDC	 0x80000000
-							MX53_PAD_FEC_MDIO__FEC_MDIO	 0x80000000
-							MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
-							MX53_PAD_FEC_RX_ER__FEC_RX_ER    0x80000000
-							MX53_PAD_FEC_CRS_DV__FEC_RX_DV   0x80000000
-							MX53_PAD_FEC_RXD1__FEC_RDATA_1   0x80000000
-							MX53_PAD_FEC_RXD0__FEC_RDATA_0   0x80000000
-							MX53_PAD_FEC_TX_EN__FEC_TX_EN    0x80000000
-							MX53_PAD_FEC_TXD1__FEC_TDATA_1   0x80000000
-							MX53_PAD_FEC_TXD0__FEC_TDATA_0   0x80000000
-						>;
-					};
-
-					pinctrl_fec_2: fecgrp-2 {
-						fsl,pins = <
-							MX53_PAD_FEC_MDC__FEC_MDC	 0x80000000
-							MX53_PAD_FEC_MDIO__FEC_MDIO	 0x80000000
-							MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
-							MX53_PAD_FEC_RX_ER__FEC_RX_ER    0x80000000
-							MX53_PAD_FEC_CRS_DV__FEC_RX_DV   0x80000000
-							MX53_PAD_FEC_RXD1__FEC_RDATA_1   0x80000000
-							MX53_PAD_FEC_RXD0__FEC_RDATA_0   0x80000000
-							MX53_PAD_FEC_TX_EN__FEC_TX_EN    0x80000000
-							MX53_PAD_FEC_TXD1__FEC_TDATA_1   0x80000000
-							MX53_PAD_FEC_TXD0__FEC_TDATA_0   0x80000000
-							MX53_PAD_KEY_ROW1__FEC_COL	 0x80000000
-							MX53_PAD_KEY_COL3__FEC_CRS	 0x80000000
-							MX53_PAD_KEY_COL2__FEC_RDATA_2	 0x80000000
-							MX53_PAD_KEY_COL0__FEC_RDATA_3	 0x80000000
-							MX53_PAD_KEY_COL1__FEC_RX_CLK	 0x80000000
-							MX53_PAD_KEY_ROW2__FEC_TDATA_2	 0x80000000
-							MX53_PAD_GPIO_19__FEC_TDATA_3	 0x80000000
-							MX53_PAD_KEY_ROW0__FEC_TX_ER	 0x80000000
-						>;
-					};
-				};
-
-				csi {
-					pinctrl_csi_1: csigrp-1 {
-						fsl,pins = <
-							MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 0x1d5
-							MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC     0x1d5
-							MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC      0x1d5
-							MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
-							MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19      0x1d5
-							MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18      0x1d5
-							MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17      0x1d5
-							MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16      0x1d5
-							MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15      0x1d5
-							MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14      0x1d5
-							MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13      0x1d5
-							MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12      0x1d5
-							MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11      0x1d5
-							MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10      0x1d5
-							MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9	0x1d5
-							MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8	0x1d5
-							MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7	0x1d5
-							MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6	0x1d5
-							MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5	0x1d5
-							MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4	0x1d5
-							MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
-						>;
-					};
-
-					pinctrl_csi_2: csigrp-2 {
-						fsl,pins = <
-							MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC	0x1d5
-							MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC	0x1d5
-							MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK	0x1d5
-							MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19	0x1d5
-							MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18	0x1d5
-							MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17	0x1d5
-							MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16	0x1d5
-							MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15	0x1d5
-							MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14	0x1d5
-							MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13	0x1d5
-							MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12	0x1d5
-						>;
-					};
-				};
-
-				cspi {
-					pinctrl_cspi_1: cspigrp-1 {
-						fsl,pins = <
-							MX53_PAD_SD1_DATA0__CSPI_MISO 0x1d5
-							MX53_PAD_SD1_CMD__CSPI_MOSI   0x1d5
-							MX53_PAD_SD1_CLK__CSPI_SCLK   0x1d5
-						>;
-					};
-
-					pinctrl_cspi_2: cspigrp-2 {
-						fsl,pins = <
-							MX53_PAD_EIM_D22__CSPI_MISO 0x1d5
-							MX53_PAD_EIM_D28__CSPI_MOSI 0x1d5
-							MX53_PAD_EIM_D21__CSPI_SCLK 0x1d5
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
-							MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
-							MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
-						>;
-					};
-
-					pinctrl_ecspi1_2: ecspi1grp-2 {
-						fsl,pins = <
-							MX53_PAD_GPIO_19__ECSPI1_RDY	0x80000000
-							MX53_PAD_EIM_EB2__ECSPI1_SS0	0x80000000
-							MX53_PAD_EIM_D16__ECSPI1_SCLK	0x80000000
-							MX53_PAD_EIM_D17__ECSPI1_MISO	0x80000000
-							MX53_PAD_EIM_D18__ECSPI1_MOSI	0x80000000
-							MX53_PAD_EIM_D19__ECSPI1_SS1	0x80000000
-						>;
-					};
-				};
-
-				ecspi2 {
-					pinctrl_ecspi2_1: ecspi2grp-1 {
-						fsl,pins = <
-							MX53_PAD_EIM_OE__ECSPI2_MISO  0x80000000
-							MX53_PAD_EIM_CS1__ECSPI2_MOSI 0x80000000
-							MX53_PAD_EIM_CS0__ECSPI2_SCLK 0x80000000
-						>;
-					};
-				};
-
-				esdhc1 {
-					pinctrl_esdhc1_1: esdhc1grp-1 {
-						fsl,pins = <
-							MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
-							MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
-							MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
-							MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
-							MX53_PAD_SD1_CMD__ESDHC1_CMD	0x1d5
-							MX53_PAD_SD1_CLK__ESDHC1_CLK	0x1d5
-						>;
-					};
-
-					pinctrl_esdhc1_2: esdhc1grp-2 {
-						fsl,pins = <
-							MX53_PAD_SD1_DATA0__ESDHC1_DAT0   0x1d5
-							MX53_PAD_SD1_DATA1__ESDHC1_DAT1   0x1d5
-							MX53_PAD_SD1_DATA2__ESDHC1_DAT2   0x1d5
-							MX53_PAD_SD1_DATA3__ESDHC1_DAT3   0x1d5
-							MX53_PAD_PATA_DATA8__ESDHC1_DAT4  0x1d5
-							MX53_PAD_PATA_DATA9__ESDHC1_DAT5  0x1d5
-							MX53_PAD_PATA_DATA10__ESDHC1_DAT6 0x1d5
-							MX53_PAD_PATA_DATA11__ESDHC1_DAT7 0x1d5
-							MX53_PAD_SD1_CMD__ESDHC1_CMD	  0x1d5
-							MX53_PAD_SD1_CLK__ESDHC1_CLK	  0x1d5
-						>;
-					};
-				};
-
-				esdhc2 {
-					pinctrl_esdhc2_1: esdhc2grp-1 {
-						fsl,pins = <
-							MX53_PAD_SD2_CMD__ESDHC2_CMD	0x1d5
-							MX53_PAD_SD2_CLK__ESDHC2_CLK	0x1d5
-							MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
-							MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
-							MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
-							MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
-						>;
-					};
-				};
-
-				esdhc3 {
-					pinctrl_esdhc3_1: esdhc3grp-1 {
-						fsl,pins = <
-							MX53_PAD_PATA_DATA8__ESDHC3_DAT0  0x1d5
-							MX53_PAD_PATA_DATA9__ESDHC3_DAT1  0x1d5
-							MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
-							MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
-							MX53_PAD_PATA_DATA0__ESDHC3_DAT4  0x1d5
-							MX53_PAD_PATA_DATA1__ESDHC3_DAT5  0x1d5
-							MX53_PAD_PATA_DATA2__ESDHC3_DAT6  0x1d5
-							MX53_PAD_PATA_DATA3__ESDHC3_DAT7  0x1d5
-							MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
-							MX53_PAD_PATA_IORDY__ESDHC3_CLK   0x1d5
-						>;
-					};
-				};
-
-				can1 {
-					pinctrl_can1_1: can1grp-1 {
-						fsl,pins = <
-							MX53_PAD_PATA_INTRQ__CAN1_TXCAN 0x80000000
-							MX53_PAD_PATA_DIOR__CAN1_RXCAN  0x80000000
-						>;
-					};
-
-					pinctrl_can1_2: can1grp-2 {
-						fsl,pins = <
-							MX53_PAD_KEY_COL2__CAN1_TXCAN 0x80000000
-							MX53_PAD_KEY_ROW2__CAN1_RXCAN 0x80000000
-						>;
-					};
-
-					pinctrl_can1_3: can1grp-3 {
-						fsl,pins = <
-							MX53_PAD_GPIO_7__CAN1_TXCAN	0x80000000
-							MX53_PAD_GPIO_8__CAN1_RXCAN	0x80000000
-						>;
-					};
-				};
-
-				can2 {
-					pinctrl_can2_1: can2grp-1 {
-						fsl,pins = <
-							MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
-							MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <
-							MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
-							MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
-						>;
-					};
-
-					pinctrl_i2c1_2: i2c1grp-2 {
-						fsl,pins = <
-							MX53_PAD_EIM_D21__I2C1_SCL	0xc0000000
-							MX53_PAD_EIM_D28__I2C1_SDA	0xc0000000
-						>;
-					};
-				};
-
-				i2c2 {
-					pinctrl_i2c2_1: i2c2grp-1 {
-						fsl,pins = <
-							MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
-							MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
-						>;
-					};
-
-					pinctrl_i2c2_2: i2c2grp-2 {
-						fsl,pins = <
-							MX53_PAD_EIM_D16__I2C2_SDA	0xc0000000
-							MX53_PAD_EIM_EB2__I2C2_SCL	0xc0000000
-						>;
-					};
-				};
-
-				i2c3 {
-					pinctrl_i2c3_1: i2c3grp-1 {
-						fsl,pins = <
-							MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
-							MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
-						>;
-					};
-				};
-
-				ipu_disp0 {
-					pinctrl_ipu_disp0_1: ipudisp0grp-1 {
-						fsl,pins = <
-						MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	0x5
-						MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		0x5
-						MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		0x5
-						MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 		0x5
-						MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		0x5
-						MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		0x5
-						MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		0x5
-						MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		0x5
-						MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		0x5
-						MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		0x5
-						MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		0x5
-						MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		0x5
-						MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		0x5
-						MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		0x5
-						MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		0x5
-						MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		0x5
-						MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		0x5
-						MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		0x5
-						MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		0x5
-						MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		0x5
-						MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		0x5
-						MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		0x5
-						MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		0x5
-						MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		0x5
-						MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		0x5
-						MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		0x5
-						MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		0x5
-						MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		0x5
-						>;
-					};
-				};
-
-				ipu_disp1 {
-					pinctrl_ipu_disp1_1: ipudisp1grp-1 {
-						fsl,pins = <
-							MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0	0x5
-							MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1	0x5
-							MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2	0x5
-							MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3	0x5
-							MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4	0x5
-							MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5	0x5
-							MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6	0x5
-							MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7	0x5
-							MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8	0x5
-							MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9	0x5
-							MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10	0x5
-							MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11	0x5
-							MX53_PAD_EIM_A17__IPU_DISP1_DAT_12	0x5
-							MX53_PAD_EIM_A18__IPU_DISP1_DAT_13	0x5
-							MX53_PAD_EIM_A19__IPU_DISP1_DAT_14	0x5
-							MX53_PAD_EIM_A20__IPU_DISP1_DAT_15	0x5
-							MX53_PAD_EIM_A21__IPU_DISP1_DAT_16	0x5
-							MX53_PAD_EIM_A22__IPU_DISP1_DAT_17	0x5
-							MX53_PAD_EIM_A23__IPU_DISP1_DAT_18	0x5
-							MX53_PAD_EIM_A24__IPU_DISP1_DAT_19	0x5
-							MX53_PAD_EIM_D31__IPU_DISP1_DAT_20	0x5
-							MX53_PAD_EIM_D30__IPU_DISP1_DAT_21	0x5
-							MX53_PAD_EIM_D26__IPU_DISP1_DAT_22	0x5
-							MX53_PAD_EIM_D27__IPU_DISP1_DAT_23	0x5
-							MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK	0x5
-							MX53_PAD_EIM_DA13__IPU_DI1_D0_CS	0x5
-							MX53_PAD_EIM_DA14__IPU_DI1_D1_CS	0x5
-							MX53_PAD_EIM_DA15__IPU_DI1_PIN1		0x5
-							MX53_PAD_EIM_DA11__IPU_DI1_PIN2		0x5
-							MX53_PAD_EIM_DA12__IPU_DI1_PIN3		0x5
-							MX53_PAD_EIM_A25__IPU_DI1_PIN12		0x5
-							MX53_PAD_EIM_DA10__IPU_DI1_PIN15	0x5
-						>;
-					};
-				};
-
-				ipu_disp2 {
-					pinctrl_ipu_disp2_1: ipudisp2grp-1 {
-						fsl,pins = <
-							MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0	0x80000000
-							MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1	0x80000000
-							MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2	0x80000000
-							MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3	0x80000000
-							MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK	0x80000000
-							MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0	0x80000000
-							MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1	0x80000000
-							MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2	0x80000000
-							MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3	0x80000000
-							MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK	0x80000000
-						>;
-					};
-				};
-
-				nand {
-					pinctrl_nand_1: nandgrp-1 {
-						fsl,pins = <
-							MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
-							MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
-							MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
-							MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
-							MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
-							MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
-							MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
-							MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	0xa4
-							MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	0xa4
-							MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	0xa4
-							MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	0xa4
-							MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	0xa4
-							MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	0xa4
-							MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	0xa4
-							MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	0xa4
-						>;
-					};
-				};
-
-				owire {
-					pinctrl_owire_1: owiregrp-1 {
-						fsl,pins = <
-							MX53_PAD_GPIO_18__OWIRE_LINE 0x80000000
-						>;
-					};
-				};
-
-				pwm1 {
-					pinctrl_pwm1_1: pwm1grp-1 {
-						fsl,pins = <
-							MX53_PAD_DISP0_DAT8__PWM1_PWMO	0x5
-						>;
-					};
-				};
-
-				pwm2 {
-					pinctrl_pwm2_1: pwm2grp-1 {
-						fsl,pins = <
-							MX53_PAD_GPIO_1__PWM2_PWMO	0x80000000
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
-							MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
-						>;
-					};
-
-					pinctrl_uart1_2: uart1grp-2 {
-						fsl,pins = <
-							MX53_PAD_PATA_DIOW__UART1_TXD_MUX  0x1e4
-							MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
-						>;
-					};
-
-					pinctrl_uart1_3: uart1grp-3 {
-						fsl,pins = <
-							MX53_PAD_PATA_RESET_B__UART1_CTS 0x1c5
-							MX53_PAD_PATA_IORDY__UART1_RTS	 0x1c5
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
-							MX53_PAD_PATA_DMARQ__UART2_TXD_MUX     0x1e4
-						>;
-					};
-
-					pinctrl_uart2_2: uart2grp-2 {
-						fsl,pins = <
-							MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	0x1c5
-							MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	0x1c5
-							MX53_PAD_PATA_DIOR__UART2_RTS		0x1c5
-							MX53_PAD_PATA_INTRQ__UART2_CTS		0x1c5
-						>;
-					};
-				};
-
-				uart3 {
-					pinctrl_uart3_1: uart3grp-1 {
-						fsl,pins = <
-							MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
-							MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
-							MX53_PAD_PATA_DA_1__UART3_CTS	  0x1e4
-							MX53_PAD_PATA_DA_2__UART3_RTS	  0x1e4
-						>;
-					};
-
-					pinctrl_uart3_2: uart3grp-2 {
-						fsl,pins = <
-							MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
-							MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
-						>;
-					};
-
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							MX53_PAD_KEY_COL0__UART4_TXD_MUX 0x1e4
-							MX53_PAD_KEY_ROW0__UART4_RXD_MUX 0x1e4
-						>;
-					};
-				};
-
-				uart5 {
-					pinctrl_uart5_1: uart5grp-1 {
-						fsl,pins = <
-							MX53_PAD_KEY_COL1__UART5_TXD_MUX 0x1e4
-							MX53_PAD_KEY_ROW1__UART5_RXD_MUX 0x1e4
-						>;
-					};
-				};
 			};
 
 			gpr: iomuxc-gpr@53fa8000 {
@@ -828,9 +361,12 @@
 				compatible = "fsl,imx53-ldb";
 				reg = <0x53fa8008 0x4>;
 				gpr = <&gpr>;
-				clocks = <&clks 122>, <&clks 120>,
-					 <&clks 115>, <&clks 116>,
-					 <&clks 123>, <&clks 85>;
+				clocks = <&clks IMX5_CLK_LDB_DI0_SEL>,
+				         <&clks IMX5_CLK_LDB_DI1_SEL>,
+				         <&clks IMX5_CLK_IPU_DI0_SEL>,
+				         <&clks IMX5_CLK_IPU_DI1_SEL>,
+				         <&clks IMX5_CLK_LDB_DI0_GATE>,
+				         <&clks IMX5_CLK_LDB_DI1_GATE>;
 				clock-names = "di0_pll", "di1_pll",
 					      "di0_sel", "di1_sel",
 					      "di0", "di1";
@@ -853,7 +389,8 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb4000 0x4000>;
-				clocks = <&clks 37>, <&clks 38>;
+				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM1_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <61>;
 			};
@@ -862,7 +399,8 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb8000 0x4000>;
-				clocks = <&clks 39>, <&clks 40>;
+				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+				         <&clks IMX5_CLK_PWM2_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <94>;
 			};
@@ -871,7 +409,8 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fbc000 0x4000>;
 				interrupts = <31>;
-				clocks = <&clks 28>, <&clks 29>;
+				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+				         <&clks IMX5_CLK_UART1_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -880,7 +419,8 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fc0000 0x4000>;
 				interrupts = <32>;
-				clocks = <&clks 30>, <&clks 31>;
+				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+				         <&clks IMX5_CLK_UART2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -889,7 +429,8 @@
 				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fc8000 0x4000>;
 				interrupts = <82>;
-				clocks = <&clks 158>, <&clks 157>;
+				clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>,
+				         <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -898,7 +439,8 @@
 				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fcc000 0x4000>;
 				interrupts = <83>;
-				clocks = <&clks 87>, <&clks 86>;
+				clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>,
+				         <&clks IMX5_CLK_CAN2_SERIAL_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -952,7 +494,7 @@
 				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x53fec000 0x4000>;
 				interrupts = <64>;
-				clocks = <&clks 88>;
+				clocks = <&clks IMX5_CLK_I2C3_GATE>;
 				status = "disabled";
 			};
 
@@ -960,7 +502,8 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53ff0000 0x4000>;
 				interrupts = <13>;
-				clocks = <&clks 65>, <&clks 66>;
+				clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
+				         <&clks IMX5_CLK_UART4_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -977,14 +520,15 @@
 				compatible = "fsl,imx53-iim", "fsl,imx27-iim";
 				reg = <0x63f98000 0x4000>;
 				interrupts = <69>;
-				clocks = <&clks 107>;
+				clocks = <&clks IMX5_CLK_IIM_GATE>;
 			};
 
 			uart5: serial@63f90000 {
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x63f90000 0x4000>;
 				interrupts = <86>;
-				clocks = <&clks 67>, <&clks 68>;
+				clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
+				         <&clks IMX5_CLK_UART5_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -992,7 +536,7 @@
 			owire: owire@63fa4000 {
 				compatible = "fsl,imx53-owire", "fsl,imx21-owire";
 				reg = <0x63fa4000 0x4000>;
-				clocks = <&clks 159>;
+				clocks = <&clks IMX5_CLK_OWIRE_GATE>;
 				status = "disabled";
 			};
 
@@ -1002,7 +546,8 @@
 				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
 				reg = <0x63fac000 0x4000>;
 				interrupts = <37>;
-				clocks = <&clks 53>, <&clks 54>;
+				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -1011,7 +556,8 @@
 				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
 				reg = <0x63fb0000 0x4000>;
 				interrupts = <6>;
-				clocks = <&clks 56>, <&clks 56>;
+				clocks = <&clks IMX5_CLK_SDMA_GATE>,
+				         <&clks IMX5_CLK_SDMA_GATE>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
@@ -1023,7 +569,8 @@
 				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
 				reg = <0x63fc0000 0x4000>;
 				interrupts = <38>;
-				clocks = <&clks 55>, <&clks 55>;
+				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -1034,7 +581,7 @@
 				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x63fc4000 0x4000>;
 				interrupts = <63>;
-				clocks = <&clks 35>;
+				clocks = <&clks IMX5_CLK_I2C2_GATE>;
 				status = "disabled";
 			};
 
@@ -1044,15 +591,16 @@
 				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x63fc8000 0x4000>;
 				interrupts = <62>;
-				clocks = <&clks 34>;
+				clocks = <&clks IMX5_CLK_I2C1_GATE>;
 				status = "disabled";
 			};
 
 			ssi1: ssi@63fcc000 {
-				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+				compatible = "fsl,imx53-ssi", "fsl,imx51-ssi",
+						"fsl,imx21-ssi";
 				reg = <0x63fcc000 0x4000>;
 				interrupts = <29>;
-				clocks = <&clks 48>;
+				clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
 				dmas = <&sdma 28 0 0>,
 				       <&sdma 29 0 0>;
 				dma-names = "rx", "tx";
@@ -1071,15 +619,16 @@
 				compatible = "fsl,imx53-nand";
 				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
 				interrupts = <8>;
-				clocks = <&clks 60>;
+				clocks = <&clks IMX5_CLK_NFC_GATE>;
 				status = "disabled";
 			};
 
 			ssi3: ssi@63fe8000 {
-				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+				compatible = "fsl,imx53-ssi", "fsl,imx51-ssi",
+						"fsl,imx21-ssi";
 				reg = <0x63fe8000 0x4000>;
 				interrupts = <96>;
-				clocks = <&clks 50>;
+				clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
 				dmas = <&sdma 46 0 0>,
 				       <&sdma 47 0 0>;
 				dma-names = "rx", "tx";
@@ -1092,7 +641,9 @@
 				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
 				reg = <0x63fec000 0x4000>;
 				interrupts = <87>;
-				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clocks = <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>,
+				         <&clks IMX5_CLK_FEC_GATE>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
@@ -1101,7 +652,8 @@
 				compatible = "fsl,imx53-tve";
 				reg = <0x63ff0000 0x1000>;
 				interrupts = <92>;
-				clocks = <&clks 69>, <&clks 116>;
+				clocks = <&clks IMX5_CLK_TVE_GATE>,
+				         <&clks IMX5_CLK_IPU_DI1_SEL>;
 				clock-names = "tve", "di_sel";
 				crtcs = <&ipu 1>;
 				status = "disabled";
@@ -1111,7 +663,8 @@
 				compatible = "fsl,imx53-vpu";
 				reg = <0x63ff4000 0x1000>;
 				interrupts = <9>;
-				clocks = <&clks 63>, <&clks 63>;
+				clocks = <&clks IMX5_CLK_VPU_GATE>,
+				         <&clks IMX5_CLK_VPU_GATE>;
 				clock-names = "per", "ahb";
 				iram = <&ocram>;
 				status = "disabled";
@@ -1121,7 +674,7 @@
 		ocram: sram@f8000000 {
 			compatible = "mmio-sram";
 			reg = <0xf8000000 0x20000>;
-			clocks = <&clks 186>;
+			clocks = <&clks IMX5_CLK_OCRAM>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts b/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts
new file mode 100644
index 000000000000..994f96a3fb54
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * 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
+ */
+
+#ifndef __DTS_V1__
+#define __DTS_V1__
+/dts-v1/;
+#endif
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-dfi-fs700-m60.dtsi"
+
+/ {
+	model = "DFI FS700-M60-6DL i.MX6dl Q7 Board";
+	compatible = "dfi,fs700-m60-6dl", "dfi,fs700e-m60", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw51xx.dts b/arch/arm/boot/dts/imx6dl-gw51xx.dts
new file mode 100644
index 000000000000..4bd055f4c930
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-gw51xx.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-gw51xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite GW51XX";
+	compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw52xx.dts b/arch/arm/boot/dts/imx6dl-gw52xx.dts
new file mode 100644
index 000000000000..c9136058f15e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-gw52xx.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite GW52XX";
+	compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw53xx.dts b/arch/arm/boot/dts/imx6dl-gw53xx.dts
new file mode 100644
index 000000000000..61818a14fde6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-gw53xx.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite GW53XX";
+	compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw54xx.dts b/arch/arm/boot/dts/imx6dl-gw54xx.dts
new file mode 100644
index 000000000000..ab38b6770a06
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-gw54xx.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite GW54XX";
+	compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-nitrogen6x.dts b/arch/arm/boot/dts/imx6dl-nitrogen6x.dts
new file mode 100644
index 000000000000..5f4d33ccc4b3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-nitrogen6x.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 Boundary Devices, Inc.
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-nitrogen6x.dtsi"
+
+/ {
+	model = "Freescale i.MX6 DualLite Nitrogen6x Board";
+	compatible = "fsl,imx6dl-nitrogen6x", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-pinfunc.h b/arch/arm/boot/dts/imx6dl-pinfunc.h
index b81a7a4ebab6..0ead323fdbd2 100644
--- a/arch/arm/boot/dts/imx6dl-pinfunc.h
+++ b/arch/arm/boot/dts/imx6dl-pinfunc.h
@@ -755,6 +755,7 @@
 #define MX6QDL_PAD_GPIO_5__I2C3_SCL                 0x230 0x600 0x878 0x6 0x2
 #define MX6QDL_PAD_GPIO_5__ARM_EVENTI               0x230 0x600 0x000 0x7 0x0
 #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK              0x234 0x604 0x840 0x0 0x1
+#define MX6QDL_PAD_GPIO_6__ENET_IRQ		    0x234 0x604 0x03c 0x11 0xff000609
 #define MX6QDL_PAD_GPIO_6__I2C3_SDA                 0x234 0x604 0x87c 0x2 0x2
 #define MX6QDL_PAD_GPIO_6__GPIO1_IO06               0x234 0x604 0x000 0x5 0x0
 #define MX6QDL_PAD_GPIO_6__SD2_LCTL                 0x234 0x604 0x000 0x6 0x0
@@ -950,6 +951,7 @@
 #define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19            0x2d8 0x6c0 0x000 0x5 0x0
 #define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x2d8 0x6c0 0x000 0x7 0x0
 #define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x2dc 0x6c4 0x928 0x0 0x1
+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT          0x2dc 0x6c4 0x000 0x2 0x0
 #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x2dc 0x6c4 0x000 0x3 0x0
 #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x2dc 0x6c4 0x000 0x5 0x0
 #define MX6QDL_PAD_SD1_CMD__SD1_CMD                 0x2e0 0x6c8 0x000 0x0 0x0
diff --git a/arch/arm/boot/dts/imx6dl-sabrelite.dts b/arch/arm/boot/dts/imx6dl-sabrelite.dts
new file mode 100644
index 000000000000..2de04479dc35
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabrelite.dts
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx6dl.dtsi"
+#include "imx6qdl-sabrelite.dtsi"
+
+/ {
+	model = "Freescale i.MX6 DualLite SABRE Lite Board";
+	compatible = "fsl,imx6dl-sabrelite", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 9e8ae118fdd4..3ab8711a15a4 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -8,6 +8,7 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "imx6dl-pinfunc.h"
 #include "imx6qdl.dtsi"
 
@@ -21,6 +22,26 @@
 			device_type = "cpu";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				996000  1275000
+				792000  1175000
+				396000  1075000
+			>;
+			fsl,soc-operating-points = <
+				/* ARM kHz  SOC-PU uV */
+				996000	1175000
+				792000	1175000
+				396000	1175000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
+				 <&clks 17>, <&clks 170>;
+			clock-names = "arm", "pll2_pfd2_396m", "step",
+				      "pll1_sw", "pll1_sys";
+			arm-supply = <&reg_arm>;
+			pu-supply = <&reg_pu>;
+			soc-supply = <&reg_soc>;
 		};
 
 		cpu@1 {
@@ -45,17 +66,17 @@
 
 			pxp: pxp@020f0000 {
 				reg = <0x020f0000 0x4000>;
-				interrupts = <0 98 0x04>;
+				interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			epdc: epdc@020f4000 {
 				reg = <0x020f4000 0x4000>;
-				interrupts = <0 97 0x04>;
+				interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			lcdif: lcdif@020f8000 {
 				reg = <0x020f8000 0x4000>;
-				interrupts = <0 39 0x04>;
+				interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -65,7 +86,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx1-i2c";
 				reg = <0x021f8000 0x4000>;
-				interrupts = <0 35 0x04>;
+				interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 			};
 		};
@@ -88,3 +109,8 @@
 		crtcs = <&ipu1 0>, <&ipu1 1>;
 	};
 };
+
+&hdmi {
+	compatible = "fsl,imx6dl-hdmi";
+	crtcs = <&ipu1 0>, <&ipu1 1>;
+};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
index edf1bd967164..78df05e9d1ce 100644
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/imx6q-arm2.dts
@@ -23,14 +23,27 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
+
+		reg_usb_otg_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
 	};
 
 	leds {
@@ -46,7 +59,7 @@
 
 &gpmi {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
 	status = "disabled"; /* gpmi nand conflicts with SD */
 };
 
@@ -54,28 +67,131 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6q-arm2 {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
 			>;
 		};
-	};
 
-	arm2 {
-		pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_KEY_COL2__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_RX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B	0x1b0b1
+				MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3_cdwp: usdhc3cdwp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
 				MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
 			>;
 		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+				MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+				MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+				MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+			>;
+		};
 	};
 };
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_2>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
 	status = "okay";
 };
 
@@ -84,8 +200,8 @@
 	wp-gpios = <&gpio6 14 0>;
 	vmmc-supply = <&reg_3p3v>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_1
-		     &pinctrl_usdhc3_arm2>;
+	pinctrl-0 = <&pinctrl_usdhc3
+		     &pinctrl_usdhc3_cdwp>;
 	status = "okay";
 };
 
@@ -93,13 +209,13 @@
 	non-removable;
 	vmmc-supply = <&reg_3p3v>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc4_1>;
+	pinctrl-0 = <&pinctrl_usdhc4>;
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_2>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	fsl,dte-mode;
 	fsl,uart-has-rtscts;
 	status = "okay";
@@ -107,6 +223,6 @@
 
 &uart4 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_1>;
+	pinctrl-0 = <&pinctrl_uart4>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
new file mode 100644
index 000000000000..99b46f8030ad
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2013 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * 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 "imx6q.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6";
+	compatible = "compulab,cm-fx6", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		heartbeat-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 31 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx6q-cm-fx6 {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+	};
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts b/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts
new file mode 100644
index 000000000000..fd0ad9a8866c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * 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
+ */
+
+#ifndef __DTS_V1__
+#define __DTS_V1__
+/dts-v1/;
+#endif
+
+#include "imx6q.dtsi"
+#include "imx6qdl-dfi-fs700-m60.dtsi"
+
+/ {
+	model = "DFI FS700-M60-6QD i.MX6qd Q7 Board";
+	compatible = "dfi,fs700-m60-6qd", "dfi,fs700e-m60", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
new file mode 100644
index 000000000000..a63bbb3d46bb
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2013 Data Modul AG
+ *
+ * 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 <dt-bindings/gpio/gpio.h>
+#include "imx6q.dtsi"
+
+/ {
+	model = "Data Modul eDM-QMX6 Board";
+	compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q";
+
+	aliases {
+		gpio7 = &stmpe_gpio;
+	};
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio7 12 0>;
+		};
+
+		reg_usb_host1: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_host1_en";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 31 0>;
+			enable-active-high;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led-blue {
+			label = "blue";
+			gpios = <&stmpe_gpio 8 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-green {
+			label = "green";
+			gpios = <&stmpe_gpio 9 GPIO_ACTIVE_HIGH>;
+		};
+
+		led-pink {
+			label = "pink";
+			gpios = <&stmpe_gpio 10 GPIO_ACTIVE_HIGH>;
+		};
+
+		led-red {
+			label = "red";
+			gpios = <&stmpe_gpio 11 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 23 0>;
+	phy-supply = <&vgen2_1v2_eth>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2
+		     &pinctrl_stmpe>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <20 8>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+				regulator-always-on;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_1v2_eth: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vdd_high_in: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	stmpe: stmpe1601@40 {
+		compatible = "st,stmpe1601";
+		reg = <0x40>;
+		interrupts = <30 0>;
+		interrupt-parent = <&gpio3>;
+
+		stmpe_gpio: stmpe_gpio {
+			#gpio-cells = <2>;
+			compatible = "st,stmpe-gpio";
+		};
+	};
+
+	temp1: ad7414@4c {
+		compatible = "ad,ad7414";
+		reg = <0x4c>;
+	};
+
+	temp2: ad7414@4d {
+		compatible = "ad,ad7414";
+		reg = <0x4d>;
+	};
+
+	rtc: m41t62@68 {
+		compatible = "stm,m41t62";
+		reg = <0x68>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-dmo-edmqmx6 {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
+				MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_EB2__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_stmpe: stmpegrp {
+			fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+				MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+				MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+				MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+			>;
+		};
+	};
+};
+
+&sata {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_host1>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	bus-width = <8>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts
new file mode 100644
index 000000000000..4a9b4dc9afc0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gk802.dts
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 Philipp Zabel
+ *
+ * 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 "imx6q.dtsi"
+
+/ {
+	model = "Zealz GK802";
+	compatible = "zealz,imx6q-gk802", "fsl,imx6q";
+
+	chosen {
+		linux,stdout-path = &uart4;
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		recovery-button {
+			label = "recovery";
+			gpios = <&gpio3 16 1>;
+			linux,code = <0x198>; /* KEY_RESTART */
+			gpio-key,wakeup;
+		};
+	};
+};
+
+/* Internal I2C */
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	/* SDMC DM2016 1024 bit EEPROM + 128 bit OTP */
+	eeprom: dm2016@51 {
+		compatible = "sdmc,dm2016";
+		reg = <0x51>;
+	};
+};
+
+/* External I2C via HDMI */
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	clock-frequency = <100000>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-gk802 {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* Recovery button, active-low */
+				MX6QDL_PAD_EIM_D16__GPIO3_IO16  0x100b1
+				/* RTL8192CU enable GPIO, active-low */
+				MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_16__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+			>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+/* External USB-A port (USBOTG) */
+&usbotg {
+	disable-over-current;
+	status = "okay";
+};
+
+/* Internal USB port (USBH1), connected to RTL8192CU */
+&usbh1 {
+	disable-over-current;
+	status = "okay";
+};
+
+/* External microSD */
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 11 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+/* Internal microSD */
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw51xx.dts b/arch/arm/boot/dts/imx6q-gw51xx.dts
new file mode 100644
index 000000000000..af4929aee075
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gw51xx.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Quad GW51XX";
+	compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw52xx.dts b/arch/arm/boot/dts/imx6q-gw52xx.dts
new file mode 100644
index 000000000000..5f71ddbc7f05
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gw52xx.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6q.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Quad GW52XX";
+	compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw53xx.dts b/arch/arm/boot/dts/imx6q-gw53xx.dts
new file mode 100644
index 000000000000..360c316b4740
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gw53xx.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6q.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Quad GW53XX";
+	compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
new file mode 100644
index 000000000000..902f98310481
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6q.dtsi"
+
+/ {
+	model = "Gateworks Ventana GW5400-A";
+	compatible = "gw,imx6q-gw5400-a", "gw,ventana", "fsl,imx6q";
+
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		ethernet0 = &fec;
+		ethernet1 = &eth1;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		sky2 = &eth1;
+		ssi0 = &ssi1;
+		spi0 = &ecspi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+		usdhc2 = &usdhc3;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 10 0>; /* 106 -> MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio1 5 0>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_1p0v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "1P0V";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_h1_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-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>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "sst,w25q256";
+		spi-max-frequency = <30000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 30 0>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	gpio: pca9555@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hwmon: gsc@29 {
+		compatible = "gw,gsp";
+		reg = <0x29>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3950000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	pciswitch: pex8609@3f {
+		compatible = "plx,pex8609";
+		reg = <0x3f>;
+	};
+
+	pciclkgen: si52147@6b {
+		compatible = "sil,si52147";
+		reg = <0x6b>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accelerometer: mma8450@1c {
+		compatible = "fsl,mma8450";
+		reg = <0x1c>;
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&sw4_reg>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	hdmiin: adv7611@4c {
+		compatible = "adi,adv7611";
+		reg = <0x4c>;
+	};
+
+	touchscreen: egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 2>; /* gpio7_12 active low */
+		wakeup-gpios = <&gpio7 12 0>;
+	};
+
+	videoout: adv7393@2a {
+		compatible = "adi,adv7393";
+		reg = <0x2a>;
+	};
+
+	videoin: adv7180@20 {
+		compatible = "adi,adv7180";
+		reg = <0x20>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-gw5400-a {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19    0x80000000 /* SPINOR_CS0# */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+				MX6QDL_PAD_GPIO_5__GPIO1_IO05     0x80000000 /* GPS_PPS */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* TOUCH_IRQ# */
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+				MX6QDL_PAD_KEY_COL2__GPIO4_IO10   0x80000000 /* user2 led */
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+				MX6QDL_PAD_SD1_DAT0__GPIO1_IO16   0x80000000 /* USBHUB_RST# */
+				MX6QDL_PAD_SD1_DAT3__GPIO1_IO21   0x80000000 /* MIPI_DIO */
+			 >;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+	lvds-channel@0 {
+		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+	};
+};
+
+&pcie {
+	reset-gpio = <&gpio1 29 0>;
+	status = "okay";
+
+	eth1: sky2@8 { /* MAC/PHY on bus 8 */
+		compatible = "marvell,sky2";
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw54xx.dts b/arch/arm/boot/dts/imx6q-gw54xx.dts
new file mode 100644
index 000000000000..ab518d66a75e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-gw54xx.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Quad GW54XX";
+	compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-nitrogen6x.dts b/arch/arm/boot/dts/imx6q-nitrogen6x.dts
new file mode 100644
index 000000000000..a57866b2e97e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-nitrogen6x.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 Boundary Devices, Inc.
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "imx6q.dtsi"
+#include "imx6qdl-nitrogen6x.dtsi"
+
+/ {
+	model = "Freescale i.MX6 Quad Nitrogen6x Board";
+	compatible = "fsl,imx6q-nitrogen6x", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
index 7d37ec60d58d..5607c331fca8 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
@@ -21,10 +21,26 @@
 	status = "okay";
 };
 
+&gpmi {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
+
 &uart4 {
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
index 1a3b50d4d8fa..324f1550976b 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
@@ -18,11 +18,35 @@
 	memory {
 		reg = <0x10000000 0x80000000>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_otg_vbus: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio4 15 0>;
+		};
+
+		reg_usb_h1_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 0 0>;
+		};
+	};
 };
 
 &ecspi3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi3_1>;
+	pinctrl-0 = <&pinctrl_ecspi3>;
 	status = "okay";
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 24 0>;
@@ -36,7 +60,7 @@
 
 &i2c1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	eeprom@50 {
@@ -128,7 +152,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6q-phytec-pfla02 {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
@@ -136,10 +160,109 @@
 				MX6QDL_PAD_DI0_PIN15__GPIO4_IO17  0x80000000 /* PMIC interrupt */
 			>;
 		};
-	};
 
-	pfla02 {
-		pinctrl_usdhc3_pfla02: usdhc3grp-pfla02 {
+		pinctrl_ecspi3: ecspi3grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_0__USB_H1_PWR		0x80000000
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+				MX6QDL_PAD_KEY_COL4__USB_OTG_OC		0x1b0b0
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x80000000
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3_cdwp: usdhc3cdwp {
 			fsl,pins = <
 				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
 				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
@@ -150,21 +273,43 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_3>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
 	phy-reset-gpios = <&gpio3 23 0>;
 	status = "disabled";
 };
 
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	status = "disabled";
+};
+
 &uart4 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_1>;
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "disabled";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "disabled";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
 	status = "disabled";
 };
 
 &usdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2_2>;
+	pinctrl-0 = <&pinctrl_usdhc2>;
 	cd-gpios = <&gpio1 4 0>;
 	wp-gpios = <&gpio1 2 0>;
 	status = "disabled";
@@ -172,8 +317,8 @@
 
 &usdhc3 {
         pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_usdhc3_2
-		     &pinctrl_usdhc3_pfla02>;
+        pinctrl-0 = <&pinctrl_usdhc3
+		     &pinctrl_usdhc3_cdwp>;
         cd-gpios = <&gpio1 27 0>;
         wp-gpios = <&gpio1 29 0>;
         status = "disabled";
diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/imx6q-pinfunc.h
index 97ed0816a6e0..9fc6120a1853 100644
--- a/arch/arm/boot/dts/imx6q-pinfunc.h
+++ b/arch/arm/boot/dts/imx6q-pinfunc.h
@@ -673,6 +673,7 @@
 #define MX6QDL_PAD_GPIO_3__USB_H1_OC                0x22c 0x5fc 0x948 0x6 0x1
 #define MX6QDL_PAD_GPIO_3__MLB_CLK                  0x22c 0x5fc 0x900 0x7 0x1
 #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK              0x230 0x600 0x870 0x0 0x1
+#define MX6QDL_PAD_GPIO_6__ENET_IRQ		    0x230 0x600 0x03c 0x11 0xff000609
 #define MX6QDL_PAD_GPIO_6__I2C3_SDA                 0x230 0x600 0x8ac 0x2 0x1
 #define MX6QDL_PAD_GPIO_6__GPIO1_IO06               0x230 0x600 0x000 0x5 0x0
 #define MX6QDL_PAD_GPIO_6__SD2_LCTL                 0x230 0x600 0x000 0x6 0x0
@@ -1024,6 +1025,7 @@
 #define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x34c 0x734 0x000 0x6 0x0
 #define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x350 0x738 0x000 0x0 0x0
 #define MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK             0x350 0x738 0x828 0x1 0x0
+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT          0x350 0x738 0x000 0x2 0x0
 #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x350 0x738 0x000 0x3 0x0
 #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x350 0x738 0x000 0x5 0x0
 #define MX6QDL_PAD_SD2_CLK__SD2_CLK                 0x354 0x73c 0x000 0x0 0x0
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index f004913f7d80..96e4688be77c 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -12,189 +12,13 @@
 
 /dts-v1/;
 #include "imx6q.dtsi"
+#include "imx6qdl-sabrelite.dtsi"
 
 / {
 	model = "Freescale i.MX6 Quad SABRE Lite Board";
 	compatible = "fsl,imx6q-sabrelite", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x40000000>;
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_2p5v: 2p5v {
-			compatible = "regulator-fixed";
-			regulator-name = "2P5V";
-			regulator-min-microvolt = <2500000>;
-			regulator-max-microvolt = <2500000>;
-			regulator-always-on;
-		};
-
-		reg_3p3v: 3p3v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		reg_usb_otg_vbus: usb_otg_vbus {
-			compatible = "regulator-fixed";
-			regulator-name = "usb_otg_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			gpio = <&gpio3 22 0>;
-			enable-active-high;
-		};
-	};
-
-	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
-			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-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>;
-	};
-};
-
-&audmux {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-};
-
-&ecspi1 {
-	fsl,spi-num-chipselects = <1>;
-	cs-gpios = <&gpio3 19 0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	status = "okay";
-
-	flash: m25p80@0 {
-		compatible = "sst,sst25vf016b";
-		spi-max-frequency = <20000000>;
-		reg = <0>;
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
-	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio3 23 0>;
-	status = "okay";
-};
-
-&i2c1 {
-	status = "okay";
-	clock-frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		clocks = <&clks 201>;
-		VDDA-supply = <&reg_2p5v>;
-		VDDIO-supply = <&reg_3p3v>;
-	};
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000
-				MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000
-				MX6QDL_PAD_EIM_D19__GPIO3_IO19  0x80000000
-				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x80000000
-				MX6QDL_PAD_EIM_D23__GPIO3_IO23  0x80000000
-				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
-				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
-				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x80000000
-				MX6QDL_PAD_EIM_D23__GPIO3_IO23	0x80000000
-			>;
-		};
-	};
-};
-
-&ldb {
-	status = "okay";
-
-	lvds-channel@0 {
-		fsl,data-mapping = "spwg";
-		fsl,data-width = <18>;
-		status = "okay";
-
-		display-timings {
-			native-mode = <&timing0>;
-			timing0: hsd100pxn1 {
-				clock-frequency = <65000000>;
-				hactive = <1024>;
-				vactive = <768>;
-				hback-porch = <220>;
-				hfront-porch = <40>;
-				vback-porch = <21>;
-				vfront-porch = <7>;
-				hsync-len = <60>;
-				vsync-len = <10>;
-			};
-		};
-	};
 };
 
 &sata {
 	status = "okay";
 };
-
-&ssi1 {
-	fsl,mode = "i2s-slave";
-	status = "okay";
-};
-
-&uart2 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-};
-
-&usbh1 {
-	status = "okay";
-};
-
-&usbotg {
-	vbus-supply = <&reg_usb_otg_vbus>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg_1>;
-	disable-over-current;
-	status = "okay";
-};
-
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
-	cd-gpios = <&gpio7 0 0>;
-	wp-gpios = <&gpio7 1 0>;
-	vmmc-supply = <&reg_3p3v>;
-	status = "okay";
-};
-
-&usdhc4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc4_2>;
-	cd-gpios = <&gpio2 6 0>;
-	wp-gpios = <&gpio2 7 0>;
-	vmmc-supply = <&reg_3p3v>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 9cbdfe7a0931..66f220a82e45 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -20,6 +20,10 @@
 	compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
 };
 
+&imx_drm {
+	crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
+
 &sata {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-sbc6x.dts b/arch/arm/boot/dts/imx6q-sbc6x.dts
index ee6addf149af..86cf09364664 100644
--- a/arch/arm/boot/dts/imx6q-sbc6x.dts
+++ b/arch/arm/boot/dts/imx6q-sbc6x.dts
@@ -17,28 +17,78 @@
 	};
 };
 
+
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
 	status = "okay";
 };
 
+&iomuxc {
+	imx6q-sbc6x {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &usbotg {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg_1>;
+	pinctrl-0 = <&pinctrl_usbotg>;
 	disable-over-current;
 	status = "okay";
 };
 
 &usdhc3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts
index 6e1ccdc019a7..ed397d149ab6 100644
--- a/arch/arm/boot/dts/imx6q-udoo.dts
+++ b/arch/arm/boot/dts/imx6q-udoo.dts
@@ -21,19 +21,69 @@
 	};
 };
 
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&iomuxc {
+	imx6q-udoo {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
 &sata {
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
+	pinctrl-0 = <&pinctrl_uart2>;
 	status = "okay";
 };
 
 &usdhc3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
 	non-removable;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index f024ef28b34b..6bb1ce915164 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -8,10 +8,15 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "imx6q-pinfunc.h"
 #include "imx6qdl.dtsi"
 
 / {
+	aliases {
+		spi4 = &ecspi5;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -25,8 +30,17 @@
 				/* kHz    uV */
 				1200000 1275000
 				996000  1250000
+				852000  1250000
 				792000  1150000
-				396000  950000
+				396000  975000
+			>;
+			fsl,soc-operating-points = <
+				/* ARM kHz  SOC-PU uV */
+				1200000 1275000
+				996000	1250000
+				852000	1250000
+				792000	1175000
+				396000	1175000
 			>;
 			clock-latency = <61036>; /* two CLK32 periods */
 			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
@@ -74,7 +88,7 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02018000 0x4000>;
-					interrupts = <0 35 0x04>;
+					interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 116>, <&clks 116>;
 					clock-names = "ipg", "per";
 					status = "disabled";
@@ -125,7 +139,7 @@
 		sata: sata@02200000 {
 			compatible = "fsl,imx6q-ahci";
 			reg = <0x02200000 0x4000>;
-			interrupts = <0 39 0x04>;
+			interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
 			clocks =  <&clks 154>, <&clks 187>, <&clks 105>;
 			clock-names = "sata", "sata_ref", "ahb";
 			status = "disabled";
@@ -135,7 +149,8 @@
 			#crtc-cells = <1>;
 			compatible = "fsl,imx6q-ipu";
 			reg = <0x02800000 0x400000>;
-			interrupts = <0 8 0x4 0 7 0x4>;
+			interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 7 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clks 133>, <&clks 134>, <&clks 137>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 4>;
@@ -159,3 +174,8 @@
 		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
 	};
 };
+
+&hdmi {
+	compatible = "fsl,imx6q-hdmi";
+	crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
new file mode 100644
index 000000000000..25cf035dd36e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
@@ -0,0 +1,199 @@
+/ {
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dummy_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "dummy-supply";
+		};
+
+		reg_usb_otg_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	chosen {
+		linux,stdout-path = &uart1;
+	};
+};
+
+&ecspi3 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 24 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "sst,sst25vf040b", "m25p80";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	status = "okay";
+	phy-mode = "rgmii";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-dfi-fs700-m60 {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+				MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000 /* PMIC irq */
+				MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000 /* MAX11801 irq */
+				MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000030b0 /* Backlight enable */
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_EB2__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D16__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 /* card detect */
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+				MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+				MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+				MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+			>;
+		};
+
+		pinctrl_ecspi3: ecspi3grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+				MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
+			>;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usdhc2 { /* module slot */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	cd-gpios = <&gpio2 2 0>;
+	status = "okay";
+};
+
+&usdhc3 { /* baseboard slot */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+};
+
+&usdhc4 { /* eMMC */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
new file mode 100644
index 000000000000..98a422153ce7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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
+ */
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		can0 = &can1;
+		ethernet0 = &fec;
+		led0 = &led0;
+		led1 = &led1;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+			default-state = "off";
+		};
+	};
+
+	memory {
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio1 26 0>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_5p0v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "5P0V";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 30 0>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	gpio: pca9555@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hwmon: gsc@29 {
+		compatible = "gw,gsp";
+		reg = <0x29>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: ltc3676@3c {
+		compatible = "ltc,ltc3676";
+		reg = <0x3c>;
+
+		regulators {
+			sw1_reg: ltc3676__sw1 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: ltc3676__sw2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: ltc3676__sw3 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: ltc3676__sw4 {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ltc3676__ldo2 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ltc3676__ldo4 {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	videoin: adv7180@20 {
+		compatible = "adi,adv7180";
+		reg = <0x20>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-gw51xx {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A19__GPIO2_IO19   0x80000000 /* MEZZ_DIO0 */
+				MX6QDL_PAD_EIM_A20__GPIO2_IO18   0x80000000 /* MEZZ_DIO1 */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22   0x80000000 /* OTG_PWR_EN */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
+				MX6QDL_PAD_GPIO_0__GPIO1_IO00    0x80000000 /* PCIE_RST# */
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x80000000 /* user1 led */
+				MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x80000000 /* user2 led */
+			 >;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+	};
+};
+
+&pcie {
+	reset-gpio = <&gpio1 0 0>;
+	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";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
new file mode 100644
index 000000000000..8e99c9a9bc76
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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
+ */
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		ethernet0 = &fec;
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		nand = &gpmi;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+		usdhc2 = &usdhc3;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 1>; /* 111 - MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory {
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio1 26 0>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_1p0v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "1P0V";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-always-on;
+		};
+
+		/* remove this fixed regulator once ltc3676__sw2 driver available */
+		reg_1p8v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "1P8V";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_5p0v: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "5P0V";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-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>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 30 0>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	gpio: pca9555@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hwmon: gsc@29 {
+		compatible = "gw,gsp";
+		reg = <0x29>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pciswitch: pex8609@3f {
+		compatible = "plx,pex8609";
+		reg = <0x3f>;
+	};
+
+	pmic: ltc3676@3c {
+		compatible = "ltc,ltc3676";
+		reg = <0x3c>;
+
+		regulators {
+			sw1_reg: ltc3676__sw1 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: ltc3676__sw2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: ltc3676__sw3 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: ltc3676__sw4 {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ltc3676__ldo2 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ltc3676__ldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ltc3676__ldo4 {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accelerometer: fxos8700@1e {
+		compatible = "fsl,fxos8700";
+		reg = <0x13>;
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 169>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	touchscreen: egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 2>; /* gpio7_12 active low */
+		wakeup-gpios = <&gpio7 12 0>;
+	};
+
+	videoin: adv7180@20 {
+		compatible = "adi,adv7180";
+		reg = <0x20>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-gw52xx {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A19__GPIO2_IO19   0x80000000 /* MEZZ_DIO0 */
+				MX6QDL_PAD_EIM_A20__GPIO2_IO18   0x80000000 /* MEZZ_DIO1 */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22   0x80000000 /* OTG_PWR_EN */
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31   0x80000000 /* VIDDEC_PDN# */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE_RST# */
+				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_PWDN */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1     0x000130b0 /* AUD4_MCK */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02    0x80000000 /* USB_SEL_PCI */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12   0x80000000 /* TOUCH_IRQ# */
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x80000000 /* user1 led */
+				MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x80000000 /* user2 led */
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15  0x80000000 /* user3 led */
+				MX6QDL_PAD_SD2_CMD__GPIO1_IO11   0x80000000 /* LVDS_TCH# */
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00  0x80000000 /* SD3_CD# */
+				MX6QDL_PAD_SD4_DAT3__GPIO2_IO11  0x80000000 /* UART2_EN# */
+			 >;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+	lvds-channel@0 {
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+	};
+};
+
+&pcie {
+	reset-gpio = <&gpio1 29 0>;
+	status = "okay";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
new file mode 100644
index 000000000000..c8e5ae06deaf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -0,0 +1,553 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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
+ */
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		can0 = &can1;
+		ethernet0 = &fec;
+		ethernet1 = &eth1;
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		nand = &gpmi;
+		sky2 = &eth1;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+		usdhc2 = &usdhc3;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio1 26 0>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_1p0v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "1P0V";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-always-on;
+		};
+
+		/* remove when pmic 1p8 regulator available */
+		reg_1p8v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "1P8V";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_h1_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-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>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 30 0>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	gpio: pca9555@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hwmon: gsc@29 {
+		compatible = "gw,gsp";
+		reg = <0x29>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pciclkgen: si53156@6b {
+		compatible = "sil,si53156";
+		reg = <0x6b>;
+	};
+
+	pciswitch: pex8606@3f {
+		compatible = "plx,pex8606";
+		reg = <0x3f>;
+	};
+
+	pmic: ltc3676@3c {
+		compatible = "ltc,ltc3676";
+		reg = <0x3c>;
+
+		regulators {
+			/* VDD_SOC */
+			sw1_reg: ltc3676__sw1 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 */
+			sw2_reg: ltc3676__sw2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM */
+			sw3_reg: ltc3676__sw3 {
+				regulator-min-microvolt = <1175000>;
+				regulator-max-microvolt = <1175000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR */
+			sw4_reg: ltc3676__sw4 {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 */
+			ldo2_reg: ltc3676__ldo2 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 */
+			ldo3_reg: ltc3676__ldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_HIGH */
+			ldo4_reg: ltc3676__ldo4 {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accelerometer: fxos8700@1e {
+		compatible = "fsl,fxos8700";
+		reg = <0x1e>;
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	hdmiin: adv7611@4c {
+		compatible = "adi,adv7611";
+		reg = <0x4c>;
+	};
+
+	touchscreen: egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <11 2>; /* gpio1_11 active low */
+		wakeup-gpios = <&gpio1 11 0>;
+	};
+
+	videoout: adv7393@2a {
+		compatible = "adi,adv7393";
+		reg = <0x2a>;
+	};
+
+	videoin: adv7180@20 {
+		compatible = "adi,adv7180";
+		reg = <0x20>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-gw53xx {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A19__GPIO2_IO19    0x80000000 /* PCIE6EXP_DIO0 */
+				MX6QDL_PAD_EIM_A20__GPIO2_IO18    0x80000000 /* PCIE6EXP_DIO1 */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27  0x80000000 /* GPS_SHDN */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26  0x80000000 /* GPS_PPS */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02     0x80000000 /* CAN_STBY */
+				MX6QDL_PAD_GPIO_8__GPIO1_IO08     0x80000000 /* PMIC_IRQ# */
+				MX6QDL_PAD_GPIO_9__GPIO1_IO09     0x80000000 /* HUB_RST# */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* PCIE_WDIS# */
+				MX6QDL_PAD_GPIO_19__GPIO4_IO05    0x80000000 /* ACCEL_IRQ# */
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+				MX6QDL_PAD_KEY_COL4__GPIO4_IO14   0x80000000 /* USBOTG_OC# */
+				MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x80000000 /* user2 led */
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+				MX6QDL_PAD_SD2_CMD__GPIO1_IO11    0x80000000 /* TOUCH_IRQ# */
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00   0x80000000 /* SD3_DET# */
+			 >;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_flexcan1: flexcan1grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x80000000
+				MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x80000000
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	reset-gpio = <&gpio1 29 0>;
+	status = "okay";
+
+	eth1: sky2@8 { /* MAC/PHY on bus 8 */
+		compatible = "marvell,sky2";
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
new file mode 100644
index 000000000000..2795dfc8c926
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -0,0 +1,580 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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
+ */
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		can0 = &can1;
+		ethernet0 = &fec;
+		ethernet1 = &eth1;
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		nand = &gpmi;
+		sky2 = &eth1;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+		usdhc2 = &usdhc3;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio1 26 0>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_1p0v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "1P0V";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_h1_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-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>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 30 0>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	gpio: pca9555@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hwmon: gsc@29 {
+		compatible = "gw,gsp";
+		reg = <0x29>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3950000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	pciswitch: pex8609@3f {
+		compatible = "plx,pex8609";
+		reg = <0x3f>;
+	};
+
+	pciclkgen: si52147@6b {
+		compatible = "sil,si52147";
+		reg = <0x6b>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accelerometer: fxos8700@1e {
+		compatible = "fsl,fxos8700";
+		reg = <0x1e>;
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&sw4_reg>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	hdmiin: adv7611@4c {
+		compatible = "adi,adv7611";
+		reg = <0x4c>;
+	};
+
+	touchscreen: egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 2>; /* gpio7_12 active low */
+		wakeup-gpios = <&gpio7 12 0>;
+	};
+
+	videoout: adv7393@2a {
+		compatible = "adi,adv7393";
+		reg = <0x2a>;
+	};
+
+	videoin: adv7180@20 {
+		compatible = "adi,adv7180";
+		reg = <0x20>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-gw54xx {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19    0x80000000 /* SPINOR_CS0# */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26  0x80000000 /* GPS_PPS */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02     0x80000000 /* CAN_STBY */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* TOUCH_IRQ# */
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+				MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x80000000 /* user2 led */
+				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+				MX6QDL_PAD_SD1_DAT0__GPIO1_IO16   0x80000000 /* USBHUB_RST# */
+				MX6QDL_PAD_SD1_DAT3__GPIO1_IO21   0x80000000 /* MIPI_DIO */
+			 >;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_flexcan1: flexcan1grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x80000000
+				MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x80000000
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	reset-gpio = <&gpio1 29 0>;
+	status = "okay";
+
+	eth1: sky2@8 { /* MAC/PHY on bus 8 */
+		compatible = "marvell,sky2";
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
new file mode 100644
index 000000000000..99be301b5232
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2013 Boundary Devices, Inc.
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_2p5v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			gpio-key,wakeup;
+		};
+
+		menu {
+			label = "Menu";
+			gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_MENU>;
+		};
+
+		home {
+			label = "Home";
+			gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_HOME>;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-nitrogen6x-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-nitrogen6x-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 = <3>;
+	};
+
+	backlight_lcd {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "sst,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 27 0>;
+	txen-skew-ps = <0>;
+	txc-skew-ps = <3000>;
+	rxdv-skew-ps = <0>;
+	rxc-skew-ps = <3000>;
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txd0-skew-ps = <0>;
+	txd1-skew-ps = <0>;
+	txd2-skew-ps = <0>;
+	txd3-skew-ps = <0>;
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	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 201>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-nitrogen6x {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* SGTL5000 sys_mclk */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x030b0
+			>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19  0x000b1	/* CS */
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x100b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x100b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x100b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x100b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x100b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x100b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x100b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x100b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x100b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				/* Phy reset */
+				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x000b0
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_gpio_keys: gpio_keysgrp {
+			fsl,pins = <
+				/* Power Button */
+				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+				/* Menu Button */
+				MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+				/* Home Button */
+				MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x1b0b0
+				/* Back Button */
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+				/* Volume Up Button */
+				MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
+				/* Volume Down Button */
+				MX6QDL_PAD_GPIO_19__GPIO4_IO05		0x1b0b0
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm3: pwm3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm4: pwm4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID	0x17059
+				MX6QDL_PAD_KEY_COL4__USB_OTG_OC	0x1b0b0
+				/* power enable, high active */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x000b0
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0	/* CD */
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0	/* CD */
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	cd-gpios = <&gpio2 6 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index ff6f1e8f2dd9..009abd69385d 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -10,17 +10,46 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/gpio/gpio.h>
+
 / {
 	memory {
 		reg = <0x10000000 0x80000000>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		user {
+			label = "debug";
+			gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	sound-spdif {
+		compatible = "fsl,imx-audio-spdif",
+			   "fsl,imx-sabreauto-spdif";
+		model = "imx-spdif";
+		spdif-controller = <&spdif>;
+		spdif-in;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm3 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		status = "okay";
+	};
 };
 
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio3 19 0>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_sabreauto>;
+	pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>;
 	status = "disabled"; /* pin conflict with WEIM NOR */
 
 	flash: m25p80@0 {
@@ -34,22 +63,130 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_2>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
 };
 
 &gpmi {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
 };
 
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6qdl-sabreauto {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
@@ -57,28 +194,245 @@
 				MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
 			>;
 		};
-	};
 
-	ecspi1 {
-		pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			>;
+		};
+
+		pinctrl_ecspi1_cs: ecspi1cs {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
 			>;
 		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_KEY_COL2__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_gpio_leds: gpioledsgrp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15	0x80000000
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_EB2__I2C2_SCL	0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA	0x4001b8b1
+			>;
+		};
+
+		pinctrl_pwm3: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT1__PWM3_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_spdif: spdifgrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170b9
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170b9
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170b9
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170b9
+			>;
+		};
+
+		pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170f9
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170f9
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170f9
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170f9
+			>;
+		};
+
+		pinctrl_weim_cs0: weimcs0grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_CS0__EIM_CS0_B		0xb0b1
+			>;
+		};
+
+		pinctrl_weim_nor: weimnorgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_OE__EIM_OE_B		0xb0b1
+				MX6QDL_PAD_EIM_RW__EIM_RW		0xb0b1
+				MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B		0xb060
+				MX6QDL_PAD_EIM_D16__EIM_DATA16		0x1b0b0
+				MX6QDL_PAD_EIM_D17__EIM_DATA17		0x1b0b0
+				MX6QDL_PAD_EIM_D18__EIM_DATA18		0x1b0b0
+				MX6QDL_PAD_EIM_D19__EIM_DATA19		0x1b0b0
+				MX6QDL_PAD_EIM_D20__EIM_DATA20		0x1b0b0
+				MX6QDL_PAD_EIM_D21__EIM_DATA21		0x1b0b0
+				MX6QDL_PAD_EIM_D22__EIM_DATA22		0x1b0b0
+				MX6QDL_PAD_EIM_D23__EIM_DATA23		0x1b0b0
+				MX6QDL_PAD_EIM_D24__EIM_DATA24		0x1b0b0
+				MX6QDL_PAD_EIM_D25__EIM_DATA25		0x1b0b0
+				MX6QDL_PAD_EIM_D26__EIM_DATA26		0x1b0b0
+				MX6QDL_PAD_EIM_D27__EIM_DATA27		0x1b0b0
+				MX6QDL_PAD_EIM_D28__EIM_DATA28		0x1b0b0
+				MX6QDL_PAD_EIM_D29__EIM_DATA29		0x1b0b0
+				MX6QDL_PAD_EIM_D30__EIM_DATA30		0x1b0b0
+				MX6QDL_PAD_EIM_D31__EIM_DATA31		0x1b0b0
+				MX6QDL_PAD_EIM_A23__EIM_ADDR23		0xb0b1
+				MX6QDL_PAD_EIM_A22__EIM_ADDR22		0xb0b1
+				MX6QDL_PAD_EIM_A21__EIM_ADDR21		0xb0b1
+				MX6QDL_PAD_EIM_A20__EIM_ADDR20		0xb0b1
+				MX6QDL_PAD_EIM_A19__EIM_ADDR19		0xb0b1
+				MX6QDL_PAD_EIM_A18__EIM_ADDR18		0xb0b1
+				MX6QDL_PAD_EIM_A17__EIM_ADDR17		0xb0b1
+				MX6QDL_PAD_EIM_A16__EIM_ADDR16		0xb0b1
+				MX6QDL_PAD_EIM_DA15__EIM_AD15		0xb0b1
+				MX6QDL_PAD_EIM_DA14__EIM_AD14		0xb0b1
+				MX6QDL_PAD_EIM_DA13__EIM_AD13		0xb0b1
+				MX6QDL_PAD_EIM_DA12__EIM_AD12		0xb0b1
+				MX6QDL_PAD_EIM_DA11__EIM_AD11		0xb0b1
+				MX6QDL_PAD_EIM_DA10__EIM_AD10		0xb0b1
+				MX6QDL_PAD_EIM_DA9__EIM_AD09		0xb0b1
+				MX6QDL_PAD_EIM_DA8__EIM_AD08		0xb0b1
+				MX6QDL_PAD_EIM_DA7__EIM_AD07		0xb0b1
+				MX6QDL_PAD_EIM_DA6__EIM_AD06		0xb0b1
+				MX6QDL_PAD_EIM_DA5__EIM_AD05		0xb0b1
+				MX6QDL_PAD_EIM_DA4__EIM_AD04		0xb0b1
+				MX6QDL_PAD_EIM_DA3__EIM_AD03		0xb0b1
+				MX6QDL_PAD_EIM_DA2__EIM_AD02		0xb0b1
+				MX6QDL_PAD_EIM_DA1__EIM_AD01		0xb0b1
+				MX6QDL_PAD_EIM_DA0__EIM_AD00		0xb0b1
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
 	};
 };
 
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdif>;
+	status = "okay";
+};
+
 &uart4 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_1>;
+	pinctrl-0 = <&pinctrl_uart4>;
 	status = "okay";
 };
 
 &usdhc3 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
-	pinctrl-0 = <&pinctrl_usdhc3_1>;
-	pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
-	pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
 	cd-gpios = <&gpio6 15 0>;
 	wp-gpios = <&gpio1 13 0>;
 	status = "okay";
@@ -86,7 +440,7 @@
 
 &weim {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>;
+	pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>;
 	#address-cells = <2>;
 	#size-cells = <1>;
 	ranges = <0 0 0x08000000 0x08000000>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
new file mode 100644
index 000000000000..3bec128c7971
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -0,0 +1,423 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_2p5v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			gpio-key,wakeup;
+		};
+
+		menu {
+			label = "Menu";
+			gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_MENU>;
+		};
+
+		home {
+			label = "Home";
+			gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_HOME>;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-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>;
+	};
+
+	backlight_lcd {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "sst,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+	txen-skew-ps = <0>;
+	txc-skew-ps = <3000>;
+	rxdv-skew-ps = <0>;
+	rxc-skew-ps = <3000>;
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txd0-skew-ps = <0>;
+	txd1-skew-ps = <0>;
+	txd2-skew-ps = <0>;
+	txd3-skew-ps = <0>;
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	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 201>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6q-sabrelite {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* SGTL5000 sys_mclk */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x030b0
+			>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19  0x000b1	/* CS */
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x100b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x100b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x100b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x100b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x100b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x100b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x100b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x100b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x100b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				/* Phy reset */
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23		0x000b0
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_gpio_keys: gpio_keysgrp {
+			fsl,pins = <
+				/* Power Button */
+				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+				/* Menu Button */
+				MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+				/* Home Button */
+				MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x1b0b0
+				/* Back Button */
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+				/* Volume Up Button */
+				MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
+				/* Volume Down Button */
+				MX6QDL_PAD_GPIO_19__GPIO4_IO05		0x1b0b0
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm3: pwm3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm4: pwm4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+				MX6QDL_PAD_KEY_COL4__USB_OTG_OC	0x1b0b0
+				/* power enable, high active */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x000b0
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0	/* CD */
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0	/* WP */
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0	/* CD */
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 0>;
+	wp-gpios = <&gpio7 1 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	cd-gpios = <&gpio2 6 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index e75e11b36dff..04487cbd4b8d 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -10,6 +10,9 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
 / {
 	memory {
 		reg = <0x10000000 0x40000000>;
@@ -17,9 +20,12 @@
 
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb_otg_vbus: usb_otg_vbus {
+		reg_usb_otg_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb_otg_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -27,8 +33,9 @@
 			enable-active-high;
 		};
 
-		reg_usb_h1_vbus: usb_h1_vbus {
+		reg_usb_h1_vbus: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "usb_h1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -36,8 +43,9 @@
 			enable-active-high;
 		};
 
-		reg_audio: wm8962_supply {
+		reg_audio: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "wm8962-supply";
 			gpio = <&gpio4 10 0>;
 			enable-active-high;
@@ -46,22 +54,37 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
+			gpio-key,wakeup;
+			linux,code = <KEY_POWER>;
+		};
 
 		volume-up {
 			label = "Volume Up";
-			gpios = <&gpio1 4 0>;
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 			gpio-key,wakeup;
-			linux,code = <115>; /* KEY_VOLUMEUP */
+			linux,code = <KEY_VOLUMEUP>;
 		};
 
 		volume-down {
 			label = "Volume Down";
-			gpios = <&gpio1 5 0>;
+			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
 			gpio-key,wakeup;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
+			linux,code = <KEY_VOLUMEDOWN>;
 		};
 	};
 
+	imx_drm: imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+		connectors = <&ldb>;
+	};
+
 	sound {
 		compatible = "fsl,imx6q-sabresd-wm8962",
 			   "fsl,imx-audio-wm8962";
@@ -92,7 +115,7 @@
 
 &audmux {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_2>;
+	pinctrl-0 = <&pinctrl_audmux>;
 	status = "okay";
 };
 
@@ -100,7 +123,7 @@
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 9 0>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_2>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	status = "okay";
 
 	flash: m25p80@0 {
@@ -114,7 +137,7 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
 	phy-reset-gpios = <&gpio1 25 0>;
 	status = "okay";
@@ -123,7 +146,7 @@
 &i2c1 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_2>;
+	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
 	codec: wm8962@1a {
@@ -149,10 +172,116 @@
        };
 };
 
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
 &i2c3 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3_2>;
+	pinctrl-0 = <&pinctrl_i2c3>;
 	status = "okay";
 
 	egalax_ts@04 {
@@ -168,11 +297,9 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6qdl-sabresd {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
-				MX6QDL_PAD_GPIO_4__GPIO1_IO04   0x80000000
-				MX6QDL_PAD_GPIO_5__GPIO1_IO05   0x80000000
 				MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
 				MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
 				MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
@@ -184,6 +311,122 @@
 				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
 			>;
 		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__ECSPI1_MISO	0x100b1
+				MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI	0x100b1
+				MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK	0x100b1
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_gpio_keys: gpio_keysgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04  0x80000000
+				MX6QDL_PAD_GPIO_5__GPIO1_IO05  0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT8__I2C1_SDA		0x4001b8b1
+				MX6QDL_PAD_CSI0_DAT9__I2C1_SCL		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT3__PWM1_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+				MX6QDL_PAD_NANDF_D4__SD2_DATA4		0x17059
+				MX6QDL_PAD_NANDF_D5__SD2_DATA5		0x17059
+				MX6QDL_PAD_NANDF_D6__SD2_DATA6		0x17059
+				MX6QDL_PAD_NANDF_D7__SD2_DATA7		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
+			>;
+		};
 	};
 };
 
@@ -214,7 +457,7 @@
 
 &pwm1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm0_1>;
+	pinctrl-0 = <&pinctrl_pwm1>;
 	status = "okay";
 };
 
@@ -225,7 +468,7 @@
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
@@ -237,14 +480,14 @@
 &usbotg {
 	vbus-supply = <&reg_usb_otg_vbus>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg_2>;
+	pinctrl-0 = <&pinctrl_usbotg>;
 	disable-over-current;
 	status = "okay";
 };
 
 &usdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2_1>;
+	pinctrl-0 = <&pinctrl_usdhc2>;
 	bus-width = <8>;
 	cd-gpios = <&gpio2 2 0>;
 	wp-gpios = <&gpio2 3 0>;
@@ -253,7 +496,7 @@
 
 &usdhc3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
 	bus-width = <8>;
 	cd-gpios = <&gpio2 0 0>;
 	wp-gpios = <&gpio2 1 0>;
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index 35f547929167..bdfdf89d405f 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -12,17 +12,21 @@
 / {
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_2p5v: 2p5v {
+		reg_2p5v: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "2P5V";
 			regulator-min-microvolt = <2500000>;
 			regulator-max-microvolt = <2500000>;
 			regulator-always-on;
 		};
 
-		reg_3p3v: 3p3v {
+		reg_3p3v: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "3P3V";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -54,14 +58,14 @@
 
 &audmux {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_2>;
+	pinctrl-0 = <&pinctrl_audmux>;
 	status = "okay";
 };
 
 &i2c2 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_2>;
+	pinctrl-0 = <&pinctrl_i2c2>;
 	status = "okay";
 
 	codec: sgtl5000@0a {
@@ -77,7 +81,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6qdl-wandboard {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX6QDL_PAD_GPIO_0__CCM_CLKO1 	 0x130b0
@@ -91,20 +95,121 @@
 				MX6QDL_PAD_EIM_D29__GPIO3_IO29   0x80000000
 			>;
 		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				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_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_spdif: spdifgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RXD0__SPDIF_OUT		0x1b0b0
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D23__UART3_CTS_B		0x1b0b1
+				MX6QDL_PAD_EIM_EB3__UART3_RTS_B		0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			>;
+		};
+
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x17059
+				MX6QDL_PAD_SD1_CLK__SD1_CLK		0x10059
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x17059
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x17059
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x17059
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
 	};
 };
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
+	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
 	phy-reset-gpios = <&gpio3 29 0>;
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
 };
 
 &spdif {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_spdif_3>;
+	pinctrl-0 = <&pinctrl_spdif>;
 	status = "okay";
 };
 
@@ -115,13 +220,13 @@
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_2>;
+	pinctrl-0 = <&pinctrl_uart3>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
@@ -132,7 +237,7 @@
 
 &usbotg {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg_1>;
+	pinctrl-0 = <&pinctrl_usbotg>;
 	disable-over-current;
 	dr_mode = "peripheral";
 	status = "okay";
@@ -140,21 +245,21 @@
 
 &usdhc1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc1_2>;
+	pinctrl-0 = <&pinctrl_usdhc1>;
 	cd-gpios = <&gpio1 2 0>;
 	status = "okay";
 };
 
 &usdhc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2_2>;
+	pinctrl-0 = <&pinctrl_usdhc2>;
 	non-removable;
 	status = "okay";
 };
 
 &usdhc3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
 	cd-gpios = <&gpio3 9 0>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index fb28b2ecb1db..a2d5c49827e2 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -14,6 +14,8 @@
 
 / {
 	aliases {
+		can0 = &can1;
+		can1 = &can2;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -24,6 +26,10 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		mmc2 = &usdhc3;
+		mmc3 = &usdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -33,6 +39,8 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usbphy0 = &usbphy1;
+		usbphy1 = &usbphy2;
 	};
 
 	intc: interrupt-controller@00a01000 {
@@ -75,7 +83,10 @@
 		dma_apbh: dma-apbh@00110000 {
 			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x00110000 0x2000>;
-			interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>;
+			interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 13 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
 			#dma-cells = <1>;
 			dma-channels = <4>;
@@ -88,7 +99,7 @@
 			#size-cells = <1>;
 			reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
 			reg-names = "gpmi-nand", "bch";
-			interrupts = <0 15 0x04>;
+			interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "bch";
 			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
 				 <&clks 150>, <&clks 149>;
@@ -109,7 +120,7 @@
 		L2: l2-cache@00a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
-			interrupts = <0 92 0x04>;
+			interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
 			cache-unified;
 			cache-level = <2>;
 			arm,tag-latency = <4 2 3>;
@@ -126,7 +137,7 @@
 				  0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
 				  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
 			num-lanes = <1>;
-			interrupts = <0 123 0x04>;
+			interrupts = <0 123 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";
@@ -134,7 +145,7 @@
 
 		pmu {
 			compatible = "arm,cortex-a9-pmu";
-			interrupts = <0 94 0x04>;
+			interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		aips-bus@02000000 { /* AIPS1 */
@@ -154,7 +165,7 @@
 				spdif: spdif@02004000 {
 					compatible = "fsl,imx35-spdif";
 					reg = <0x02004000 0x4000>;
-					interrupts = <0 52 0x04>;
+					interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
 					dmas = <&sdma 14 18 0>,
 					       <&sdma 15 18 0>;
 					dma-names = "rx", "tx";
@@ -176,9 +187,11 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02008000 0x4000>;
-					interrupts = <0 31 0x04>;
+					interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 112>, <&clks 112>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
@@ -187,9 +200,11 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x0200c000 0x4000>;
-					interrupts = <0 32 0x04>;
+					interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 113>, <&clks 113>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
@@ -198,9 +213,11 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02010000 0x4000>;
-					interrupts = <0 33 0x04>;
+					interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 114>, <&clks 114>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
@@ -209,16 +226,18 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02014000 0x4000>;
-					interrupts = <0 34 0x04>;
+					interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 115>, <&clks 115>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
 				uart1: serial@02020000 {
 					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02020000 0x4000>;
-					interrupts = <0 26 0x04>;
+					interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 160>, <&clks 161>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
@@ -228,13 +247,15 @@
 
 				esai: esai@02024000 {
 					reg = <0x02024000 0x4000>;
-					interrupts = <0 51 0x04>;
+					interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
 				};
 
 				ssi1: ssi@02028000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6q-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x02028000 0x4000>;
-					interrupts = <0 46 0x04>;
+					interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 178>;
 					dmas = <&sdma 37 1 0>,
 					       <&sdma 38 1 0>;
@@ -245,9 +266,11 @@
 				};
 
 				ssi2: ssi@0202c000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6q-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x0202c000 0x4000>;
-					interrupts = <0 47 0x04>;
+					interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 179>;
 					dmas = <&sdma 41 1 0>,
 					       <&sdma 42 1 0>;
@@ -258,9 +281,11 @@
 				};
 
 				ssi3: ssi@02030000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6q-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x02030000 0x4000>;
-					interrupts = <0 48 0x04>;
+					interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks 180>;
 					dmas = <&sdma 45 1 0>,
 					       <&sdma 46 1 0>;
@@ -272,7 +297,7 @@
 
 				asrc: asrc@02034000 {
 					reg = <0x02034000 0x4000>;
-					interrupts = <0 50 0x04>;
+					interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
 				};
 
 				spba@0203c000 {
@@ -282,7 +307,8 @@
 
 			vpu: vpu@02040000 {
 				reg = <0x02040000 0x3c000>;
-				interrupts = <0 3 0x04 0 12 0x04>;
+				interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
+				             <0 12 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			aipstz@0207c000 { /* AIPSTZ1 */
@@ -293,7 +319,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02080000 0x4000>;
-				interrupts = <0 83 0x04>;
+				interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 62>, <&clks 145>;
 				clock-names = "ipg", "per";
 			};
@@ -302,7 +328,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02084000 0x4000>;
-				interrupts = <0 84 0x04>;
+				interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 62>, <&clks 146>;
 				clock-names = "ipg", "per";
 			};
@@ -311,7 +337,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02088000 0x4000>;
-				interrupts = <0 85 0x04>;
+				interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 62>, <&clks 147>;
 				clock-names = "ipg", "per";
 			};
@@ -320,7 +346,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x0208c000 0x4000>;
-				interrupts = <0 86 0x04>;
+				interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 62>, <&clks 148>;
 				clock-names = "ipg", "per";
 			};
@@ -328,23 +354,25 @@
 			can1: flexcan@02090000 {
 				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02090000 0x4000>;
-				interrupts = <0 110 0x04>;
+				interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 108>, <&clks 109>;
 				clock-names = "ipg", "per";
+				status = "disabled";
 			};
 
 			can2: flexcan@02094000 {
 				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02094000 0x4000>;
-				interrupts = <0 111 0x04>;
+				interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 110>, <&clks 111>;
 				clock-names = "ipg", "per";
+				status = "disabled";
 			};
 
 			gpt: gpt@02098000 {
 				compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
 				reg = <0x02098000 0x4000>;
-				interrupts = <0 55 0x04>;
+				interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 119>, <&clks 120>;
 				clock-names = "ipg", "per";
 			};
@@ -352,7 +380,8 @@
 			gpio1: gpio@0209c000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x0209c000 0x4000>;
-				interrupts = <0 66 0x04 0 67 0x04>;
+				interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 67 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -362,7 +391,8 @@
 			gpio2: gpio@020a0000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020a0000 0x4000>;
-				interrupts = <0 68 0x04 0 69 0x04>;
+				interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 69 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -372,7 +402,8 @@
 			gpio3: gpio@020a4000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020a4000 0x4000>;
-				interrupts = <0 70 0x04 0 71 0x04>;
+				interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 71 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -382,7 +413,8 @@
 			gpio4: gpio@020a8000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020a8000 0x4000>;
-				interrupts = <0 72 0x04 0 73 0x04>;
+				interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 73 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -392,7 +424,8 @@
 			gpio5: gpio@020ac000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020ac000 0x4000>;
-				interrupts = <0 74 0x04 0 75 0x04>;
+				interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 75 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -402,7 +435,8 @@
 			gpio6: gpio@020b0000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020b0000 0x4000>;
-				interrupts = <0 76 0x04 0 77 0x04>;
+				interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 77 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -412,7 +446,8 @@
 			gpio7: gpio@020b4000 {
 				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
 				reg = <0x020b4000 0x4000>;
-				interrupts = <0 78 0x04 0 79 0x04>;
+				interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 79 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -421,20 +456,20 @@
 
 			kpp: kpp@020b8000 {
 				reg = <0x020b8000 0x4000>;
-				interrupts = <0 82 0x04>;
+				interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			wdog1: wdog@020bc000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020bc000 0x4000>;
-				interrupts = <0 80 0x04>;
+				interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 0>;
 			};
 
 			wdog2: wdog@020c0000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020c0000 0x4000>;
-				interrupts = <0 81 0x04>;
+				interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 0>;
 				status = "disabled";
 			};
@@ -442,14 +477,17 @@
 			clks: ccm@020c4000 {
 				compatible = "fsl,imx6q-ccm";
 				reg = <0x020c4000 0x4000>;
-				interrupts = <0 87 0x04 0 88 0x04>;
+				interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 88 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
 			};
 
 			anatop: anatop@020c8000 {
 				compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
-				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+				interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
 				regulator-1p1@110 {
 					compatible = "fsl,anatop-regulator";
@@ -495,7 +533,7 @@
 
 				reg_arm: regulator-vddcore@140 {
 					compatible = "fsl,anatop-regulator";
-					regulator-name = "cpu";
+					regulator-name = "vddarm";
 					regulator-min-microvolt = <725000>;
 					regulator-max-microvolt = <1450000>;
 					regulator-always-on;
@@ -547,23 +585,26 @@
 
 			tempmon: tempmon {
 				compatible = "fsl,imx6q-tempmon";
-				interrupts = <0 49 0x04>;
+				interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
 				fsl,tempmon = <&anatop>;
 				fsl,tempmon-data = <&ocotp>;
+				clocks = <&clks 172>;
 			};
 
 			usbphy1: usbphy@020c9000 {
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020c9000 0x1000>;
-				interrupts = <0 44 0x04>;
+				interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 182>;
+				fsl,anatop = <&anatop>;
 			};
 
 			usbphy2: usbphy@020ca000 {
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020ca000 0x1000>;
-				interrupts = <0 45 0x04>;
+				interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 183>;
+				fsl,anatop = <&anatop>;
 			};
 
 			snvs@020cc000 {
@@ -575,31 +616,34 @@
 				snvs-rtc-lp@34 {
 					compatible = "fsl,sec-v4.0-mon-rtc-lp";
 					reg = <0x34 0x58>;
-					interrupts = <0 19 0x04 0 20 0x04>;
+					interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
+						     <0 20 IRQ_TYPE_LEVEL_HIGH>;
 				};
 			};
 
 			epit1: epit@020d0000 { /* EPIT1 */
 				reg = <0x020d0000 0x4000>;
-				interrupts = <0 56 0x04>;
+				interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			epit2: epit@020d4000 { /* EPIT2 */
 				reg = <0x020d4000 0x4000>;
-				interrupts = <0 57 0x04>;
+				interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			src: src@020d8000 {
 				compatible = "fsl,imx6q-src", "fsl,imx51-src";
 				reg = <0x020d8000 0x4000>;
-				interrupts = <0 91 0x04 0 96 0x04>;
+				interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 96 IRQ_TYPE_LEVEL_HIGH>;
 				#reset-cells = <1>;
 			};
 
 			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
-				interrupts = <0 89 0x04 0 90 0x04>;
+				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			gpr: iomuxc-gpr@020e0000 {
@@ -610,744 +654,6 @@
 			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc";
 				reg = <0x020e0000 0x4000>;
-
-				audmux {
-					pinctrl_audmux_1: audmux-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x80000000
-							MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x80000000
-							MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x80000000
-							MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x80000000
-						>;
-					};
-
-					pinctrl_audmux_2: audmux-2 {
-						fsl,pins = <
-							MX6QDL_PAD_CSI0_DAT7__AUD3_RXD  0x80000000
-							MX6QDL_PAD_CSI0_DAT4__AUD3_TXC  0x80000000
-							MX6QDL_PAD_CSI0_DAT5__AUD3_TXD  0x80000000
-							MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
-						>;
-					};
-
-					pinctrl_audmux_3: audmux-3 {
-						fsl,pins = <
-							MX6QDL_PAD_DISP0_DAT16__AUD5_TXC  0x80000000
-							MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x80000000
-							MX6QDL_PAD_DISP0_DAT19__AUD5_RXD  0x80000000
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-							MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-							MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-						>;
-					};
-
-					pinctrl_ecspi1_2: ecspi1grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
-							MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
-							MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
-						>;
-					};
-				};
-
-				ecspi3 {
-					pinctrl_ecspi3_1: ecspi3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
-							MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
-							MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
-						>;
-					};
-				};
-
-				enet {
-					pinctrl_enet_1: enetgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-							MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							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_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-							MX6QDL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
-						>;
-					};
-
-					pinctrl_enet_2: enetgrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
-							MX6QDL_PAD_KEY_COL2__ENET_MDC         0x1b0b0
-							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							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_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-						>;
-					};
-
-					pinctrl_enet_3: enetgrp-3 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-							MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							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_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-							MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN     0x1b0b0
-						>;
-					};
-				};
-
-				esai {
-					pinctrl_esai_1: esaigrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1b030
-							MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK  0x1b030
-							MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS     0x1b030
-							MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2  0x1b030
-							MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3   0x1b030
-							MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1   0x1b030
-							MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0    0x1b030
-							MX6QDL_PAD_NANDF_CS2__ESAI_TX0       0x1b030
-							MX6QDL_PAD_NANDF_CS3__ESAI_TX1       0x1b030
-						>;
-					};
-
-					pinctrl_esai_2: esaigrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
-							MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS    0x1b030
-							MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
-							MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3     0x1b030
-							MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1  0x1b030
-							MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0   0x1b030
-							MX6QDL_PAD_GPIO_17__ESAI_TX0        0x1b030
-							MX6QDL_PAD_NANDF_CS3__ESAI_TX1      0x1b030
-							MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK   0x1b030
-							MX6QDL_PAD_GPIO_9__ESAI_RX_FS       0x1b030
-						>;
-					};
-				};
-
-				flexcan1 {
-					pinctrl_flexcan1_1: flexcan1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
-							MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
-						>;
-					};
-
-					pinctrl_flexcan1_2: flexcan1grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_7__FLEXCAN1_TX   0x80000000
-							MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
-						>;
-					};
-				};
-
-				flexcan2 {
-					pinctrl_flexcan2_1: flexcan2grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000
-							MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000
-						>;
-					};
-				};
-
-				gpmi-nand {
-					pinctrl_gpmi_nand_1: gpmi-nand-1 {
-						fsl,pins = <
-							MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
-							MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
-							MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
-							MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
-							MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
-							MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
-							MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
-							MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
-							MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
-							MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
-							MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
-							MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
-							MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
-							MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
-							MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
-							MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
-							MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
-						>;
-					};
-				};
-
-				hdmi_hdcp {
-					pinctrl_hdmi_hdcp_1: hdmihdcpgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
-							MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_hdmi_hdcp_2: hdmihdcpgrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
-							MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_hdmi_hdcp_3: hdmihdcpgrp-3 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL  0x4001b8b1
-							MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
-						>;
-					};
-				};
-
-				hdmi_cec {
-					pinctrl_hdmi_cec_1: hdmicecgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
-						>;
-					};
-
-					pinctrl_hdmi_cec_2: hdmicecgrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-							MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c1_2: i2c1grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
-							MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
-						>;
-					};
-				};
-
-				i2c2 {
-					pinctrl_i2c2_1: i2c2grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
-							MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c2_2: i2c2grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
-							MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c2_3: i2c2grp-3 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_EB2__I2C2_SCL  0x4001b8b1
-							MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-						>;
-					};
-				};
-
-				i2c3 {
-					pinctrl_i2c3_1: i2c3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
-							MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c3_2: i2c3grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
-							MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c3_3: i2c3grp-3 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_5__I2C3_SCL  0x4001b8b1
-							MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
-						>;
-					};
-
-					pinctrl_i2c3_4: i2c3grp-4 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_3__I2C3_SCL  0x4001b8b1
-							MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-						>;
-					};
-				};
-
-				ipu1 {
-					pinctrl_ipu1_1: ipu1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
-							MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
-							MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
-							MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
-							MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04        0x80000000
-							MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
-							MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
-							MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
-							MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
-							MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
-							MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
-							MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
-							MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
-							MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
-							MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
-							MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
-							MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
-							MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
-							MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
-							MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
-							MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
-							MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
-							MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
-							MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
-							MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
-							MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
-							MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
-							MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
-							MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
-						>;
-					};
-
-					pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */
-						fsl,pins = <
-							MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x80000000
-							MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x80000000
-							MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x80000000
-							MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x80000000
-							MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x80000000
-							MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x80000000
-							MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x80000000
-							MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x80000000
-							MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000
-							MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x80000000
-							MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x80000000
-							MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x80000000
-						>;
-					};
-
-					pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */
-						fsl,pins = <
-							MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04   0x80000000
-							MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05   0x80000000
-							MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06   0x80000000
-							MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07   0x80000000
-							MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08   0x80000000
-							MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09   0x80000000
-							MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10  0x80000000
-							MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11  0x80000000
-							MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12  0x80000000
-							MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13  0x80000000
-							MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14  0x80000000
-							MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15  0x80000000
-							MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16  0x80000000
-							MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17  0x80000000
-							MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18  0x80000000
-							MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19  0x80000000
-							MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
-							MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC    0x80000000
-							MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC   0x80000000
-						>;
-					};
-				};
-
-				mlb {
-					pinctrl_mlb_1: mlbgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_3__MLB_CLK  0x71
-							MX6QDL_PAD_GPIO_6__MLB_SIG  0x71
-							MX6QDL_PAD_GPIO_2__MLB_DATA 0x71
-						>;
-					};
-
-					pinctrl_mlb_2: mlbgrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x71
-							MX6QDL_PAD_GPIO_6__MLB_SIG    0x71
-							MX6QDL_PAD_GPIO_2__MLB_DATA   0x71
-						>;
-					};
-				};
-
-				pwm0 {
-					pinctrl_pwm0_1: pwm0grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
-						>;
-					};
-				};
-
-				pwm3 {
-					pinctrl_pwm3_1: pwm3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
-						>;
-					};
-				};
-
-				spdif {
-					pinctrl_spdif_1: spdifgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
-						>;
-					};
-
-					pinctrl_spdif_2: spdifgrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
-							MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
-						>;
-					};
-
-					pinctrl_spdif_3: spdifgrp-3 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
-							MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
-							MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
-						>;
-					};
-
-					pinctrl_uart2_2: uart2grp-2 { /* DTE mode */
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D26__UART2_RX_DATA   0x1b0b1
-							MX6QDL_PAD_EIM_D27__UART2_TX_DATA   0x1b0b1
-							MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
-							MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
-						>;
-					};
-				};
-
-				uart3 {
-					pinctrl_uart3_1: uart3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
-							MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
-							MX6QDL_PAD_EIM_D30__UART3_CTS_B   0x1b0b1
-							MX6QDL_PAD_EIM_EB3__UART3_RTS_B   0x1b0b1
-						>;
-					};
-
-					pinctrl_uart3_2: uart3grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
-							MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
-							MX6QDL_PAD_EIM_D23__UART3_CTS_B	  0x1b0b1
-							MX6QDL_PAD_EIM_EB3__UART3_RTS_B	  0x1b0b1
-						>;
-					};
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
-							MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				usbotg {
-					pinctrl_usbotg_1: usbotggrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg_2: usbotggrp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
-						>;
-					};
-				};
-
-				usbh2 {
-					pinctrl_usbh2_1: usbh2grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_RGMII_TXC__USB_H2_DATA      0x40013030
-							MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030
-						>;
-					};
-
-					pinctrl_usbh2_2: usbh2grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030
-						>;
-					};
-				};
-
-				usbh3 {
-					pinctrl_usbh3_1: usbh3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030
-							MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE  0x40013030
-						>;
-					};
-
-					pinctrl_usbh3_2: usbh3grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030
-						>;
-					};
-				};
-
-				usdhc1 {
-					pinctrl_usdhc1_1: usdhc1grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-							MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-							MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-							MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-							MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-							MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-							MX6QDL_PAD_NANDF_D0__SD1_DATA4 0x17059
-							MX6QDL_PAD_NANDF_D1__SD1_DATA5 0x17059
-							MX6QDL_PAD_NANDF_D2__SD1_DATA6 0x17059
-							MX6QDL_PAD_NANDF_D3__SD1_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc1_2: usdhc1grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-							MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-							MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-							MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-							MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-							MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-						>;
-					};
-				};
-
-				usdhc2 {
-					pinctrl_usdhc2_1: usdhc2grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-							MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
-							MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
-							MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
-							MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc2_2: usdhc2grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-						>;
-					};
-				};
-
-				usdhc3 {
-					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
-							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
-							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
-							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { /* 100Mhz */
-						fsl,pins = <
-							MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
-							MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
-							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
-							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
-							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
-							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
-							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
-							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
-							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
-							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
-						>;
-					};
-
-					pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { /* 200Mhz */
-						fsl,pins = <
-							MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
-							MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
-							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
-							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
-							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
-							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
-							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
-							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
-							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
-							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
-						>;
-					};
-
-					pinctrl_usdhc3_2: usdhc3grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-						>;
-					};
-				};
-
-				usdhc4 {
-					pinctrl_usdhc4_1: usdhc4grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
-							MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
-							MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
-							MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
-							MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
-							MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
-							MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
-							MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
-							MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
-							MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc4_2: usdhc4grp-2 {
-						fsl,pins = <
-							MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
-							MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
-							MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
-							MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
-							MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
-							MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
-						>;
-					};
-				};
-
-				weim {
-					pinctrl_weim_cs0_1: weim_cs0grp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_CS0__EIM_CS0_B   0xb0b1
-						>;
-					};
-
-					pinctrl_weim_nor_1: weim_norgrp-1 {
-						fsl,pins = <
-							MX6QDL_PAD_EIM_OE__EIM_OE_B     0xb0b1
-							MX6QDL_PAD_EIM_RW__EIM_RW       0xb0b1
-							MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
-							/* data */
-							MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
-							MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
-							MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
-							MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
-							MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
-							MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
-							MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
-							MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
-							MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
-							MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
-							MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
-							MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
-							MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
-							MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
-							MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
-							MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
-							/* address */
-							MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
-							MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
-							MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
-							MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
-							MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
-							MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
-							MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
-							MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
-							MX6QDL_PAD_EIM_DA15__EIM_AD15  0xb0b1
-							MX6QDL_PAD_EIM_DA14__EIM_AD14  0xb0b1
-							MX6QDL_PAD_EIM_DA13__EIM_AD13  0xb0b1
-							MX6QDL_PAD_EIM_DA12__EIM_AD12  0xb0b1
-							MX6QDL_PAD_EIM_DA11__EIM_AD11  0xb0b1
-							MX6QDL_PAD_EIM_DA10__EIM_AD10  0xb0b1
-							MX6QDL_PAD_EIM_DA9__EIM_AD09   0xb0b1
-							MX6QDL_PAD_EIM_DA8__EIM_AD08   0xb0b1
-							MX6QDL_PAD_EIM_DA7__EIM_AD07   0xb0b1
-							MX6QDL_PAD_EIM_DA6__EIM_AD06   0xb0b1
-							MX6QDL_PAD_EIM_DA5__EIM_AD05   0xb0b1
-							MX6QDL_PAD_EIM_DA4__EIM_AD04   0xb0b1
-							MX6QDL_PAD_EIM_DA3__EIM_AD03   0xb0b1
-							MX6QDL_PAD_EIM_DA2__EIM_AD02   0xb0b1
-							MX6QDL_PAD_EIM_DA1__EIM_AD01   0xb0b1
-							MX6QDL_PAD_EIM_DA0__EIM_AD00   0xb0b1
-						>;
-					};
-				};
 			};
 
 			ldb: ldb@020e0008 {
@@ -1368,20 +674,29 @@
 				};
 			};
 
+			hdmi: hdmi@0120000 {
+				reg = <0x00120000 0x9000>;
+				interrupts = <0 115 0x04>;
+				gpr = <&gpr>;
+				clocks = <&clks 123>, <&clks 124>;
+				clock-names = "iahb", "isfr";
+				status = "disabled";
+			};
+
 			dcic1: dcic@020e4000 {
 				reg = <0x020e4000 0x4000>;
-				interrupts = <0 124 0x04>;
+				interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			dcic2: dcic@020e8000 {
 				reg = <0x020e8000 0x4000>;
-				interrupts = <0 125 0x04>;
+				interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			sdma: sdma@020ec000 {
 				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
 				reg = <0x020ec000 0x4000>;
-				interrupts = <0 2 0x04>;
+				interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 155>, <&clks 155>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
@@ -1398,7 +713,8 @@
 
 			caam@02100000 {
 				reg = <0x02100000 0x40000>;
-				interrupts = <0 105 0x04 0 106 0x04>;
+				interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 106 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			aipstz@0217c000 { /* AIPSTZ2 */
@@ -1408,7 +724,7 @@
 			usbotg: usb@02184000 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184000 0x200>;
-				interrupts = <0 43 0x04>;
+				interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 162>;
 				fsl,usbphy = <&usbphy1>;
 				fsl,usbmisc = <&usbmisc 0>;
@@ -1418,7 +734,7 @@
 			usbh1: usb@02184200 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
-				interrupts = <0 40 0x04>;
+				interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 162>;
 				fsl,usbphy = <&usbphy2>;
 				fsl,usbmisc = <&usbmisc 1>;
@@ -1428,7 +744,7 @@
 			usbh2: usb@02184400 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
-				interrupts = <0 41 0x04>;
+				interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 162>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
@@ -1437,7 +753,7 @@
 			usbh3: usb@02184600 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184600 0x200>;
-				interrupts = <0 42 0x04>;
+				interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 162>;
 				fsl,usbmisc = <&usbmisc 3>;
 				status = "disabled";
@@ -1453,7 +769,9 @@
 			fec: ethernet@02188000 {
 				compatible = "fsl,imx6q-fec";
 				reg = <0x02188000 0x4000>;
-				interrupts = <0 118 0x04 0 119 0x04>;
+				interrupts-extended =
+					<&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
+					<&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 117>, <&clks 117>, <&clks 190>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
@@ -1461,13 +779,15 @@
 
 			mlb@0218c000 {
 				reg = <0x0218c000 0x4000>;
-				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+				interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 117 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 126 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			usdhc1: usdhc@02190000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02190000 0x4000>;
-				interrupts = <0 22 0x04>;
+				interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
@@ -1477,7 +797,7 @@
 			usdhc2: usdhc@02194000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02194000 0x4000>;
-				interrupts = <0 23 0x04>;
+				interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
@@ -1487,7 +807,7 @@
 			usdhc3: usdhc@02198000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02198000 0x4000>;
-				interrupts = <0 24 0x04>;
+				interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
@@ -1497,7 +817,7 @@
 			usdhc4: usdhc@0219c000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x0219c000 0x4000>;
-				interrupts = <0 25 0x04>;
+				interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
@@ -1509,7 +829,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a0000 0x4000>;
-				interrupts = <0 36 0x04>;
+				interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 125>;
 				status = "disabled";
 			};
@@ -1519,7 +839,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a4000 0x4000>;
-				interrupts = <0 37 0x04>;
+				interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 126>;
 				status = "disabled";
 			};
@@ -1529,7 +849,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a8000 0x4000>;
-				interrupts = <0 38 0x04>;
+				interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 127>;
 				status = "disabled";
 			};
@@ -1550,7 +870,7 @@
 			weim: weim@021b8000 {
 				compatible = "fsl,imx6q-weim";
 				reg = <0x021b8000 0x4000>;
-				interrupts = <0 14 0x04>;
+				interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 196>;
 			};
 
@@ -1561,12 +881,12 @@
 
 			tzasc@021d0000 { /* TZASC1 */
 				reg = <0x021d0000 0x4000>;
-				interrupts = <0 108 0x04>;
+				interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			tzasc@021d4000 { /* TZASC2 */
 				reg = <0x021d4000 0x4000>;
-				interrupts = <0 109 0x04>;
+				interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			audmux: audmux@021d8000 {
@@ -1575,7 +895,7 @@
 				status = "disabled";
 			};
 
-			mipi@021dc000 { /* MIPI-CSI */
+			mipi_csi: mipi@021dc000 {
 				reg = <0x021dc000 0x4000>;
 			};
 
@@ -1585,13 +905,13 @@
 
 			vdoa@021e4000 {
 				reg = <0x021e4000 0x4000>;
-				interrupts = <0 18 0x04>;
+				interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			uart2: serial@021e8000 {
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021e8000 0x4000>;
-				interrupts = <0 27 0x04>;
+				interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
@@ -1602,7 +922,7 @@
 			uart3: serial@021ec000 {
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021ec000 0x4000>;
-				interrupts = <0 28 0x04>;
+				interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
@@ -1613,7 +933,7 @@
 			uart4: serial@021f0000 {
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f0000 0x4000>;
-				interrupts = <0 29 0x04>;
+				interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
@@ -1624,7 +944,7 @@
 			uart5: serial@021f4000 {
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f4000 0x4000>;
-				interrupts = <0 30 0x04>;
+				interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
@@ -1637,7 +957,8 @@
 			#crtc-cells = <1>;
 			compatible = "fsl,imx6q-ipu";
 			reg = <0x02400000 0x400000>;
-			interrupts = <0 6 0x4 0 5 0x4>;
+			interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 5 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clks 130>, <&clks 131>, <&clks 132>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index cc68e19c5163..864d8dfb51ca 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -8,6 +8,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include "imx6sl.dtsi"
 
 / {
@@ -18,11 +20,26 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		user {
+			label = "debug";
+			gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
 	regulators {
 		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		reg_usb_otg1_vbus: usb_otg1_vbus {
+		reg_usb_otg1_vbus: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "usb_otg1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -30,22 +47,63 @@
 			enable-active-high;
 		};
 
-		reg_usb_otg2_vbus: usb_otg2_vbus {
+		reg_usb_otg2_vbus: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "usb_otg2_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			gpio = <&gpio4 2 0>;
 			enable-active-high;
 		};
+
+		reg_aud3v: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "wm8962-supply-3v15";
+			regulator-min-microvolt = <3150000>;
+			regulator-max-microvolt = <3150000>;
+			regulator-boot-on;
+		};
+
+		reg_aud4v: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "wm8962-supply-4v2";
+			regulator-min-microvolt = <4325000>;
+			regulator-max-microvolt = <4325000>;
+			regulator-boot-on;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+		model = "wm8962-audio";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"Ext Spk", "SPKOUTL",
+			"Ext Spk", "SPKOUTR",
+			"AMIC", "MICBIAS",
+			"IN3R", "AMIC";
+		mux-int-port = <2>;
+		mux-ext-port = <3>;
 	};
 };
 
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux3>;
+	status = "okay";
+};
+
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 11 0>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	pinctrl-0 = <&pinctrl_ecspi1>;
 	status = "okay";
 
 	flash: m25p80@0 {
@@ -59,16 +117,144 @@
 
 &fec {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
+	pinctrl-0 = <&pinctrl_fec>;
 	phy-mode = "rmii";
 	status = "okay";
 };
 
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8962@1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		clocks = <&clks IMX6SL_CLK_EXTERN_AUDIO>;
+		DCVDD-supply = <&vgen3_reg>;
+		DBVDD-supply = <&reg_aud3v>;
+		AVDD-supply = <&vgen3_reg>;
+		CPVDD-supply = <&vgen3_reg>;
+		MICVDD-supply = <&reg_aud3v>;
+		PLLVDD-supply = <&vgen3_reg>;
+		SPKVDD1-supply = <&reg_aud4v>;
+		SPKVDD2-supply = <&reg_aud4v>;
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	hog {
+	imx6sl-evk {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
 				MX6SL_PAD_KEY_ROW7__GPIO4_IO07    0x17059
@@ -78,21 +264,230 @@
 				MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
 				MX6SL_PAD_KEY_COL4__GPIO4_IO00	0x80000000
 				MX6SL_PAD_KEY_COL5__GPIO4_IO02	0x80000000
+				MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+			>;
+		};
+
+		pinctrl_audmux3: audmux3grp {
+			fsl,pins = <
+				MX6SL_PAD_AUD_RXD__AUD3_RXD	  0x4130b0
+				MX6SL_PAD_AUD_TXC__AUD3_TXC	  0x4130b0
+				MX6SL_PAD_AUD_TXD__AUD3_TXD	  0x4110b0
+				MX6SL_PAD_AUD_TXFS__AUD3_TXFS	  0x4130b0
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO	0x100b1
+				MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI	0x100b1
+				MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK	0x100b1
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX6SL_PAD_FEC_MDC__FEC_MDC		0x1b0b0
+				MX6SL_PAD_FEC_MDIO__FEC_MDIO		0x1b0b0
+				MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV		0x1b0b0
+				MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0	0x1b0b0
+				MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1	0x1b0b0
+				MX6SL_PAD_FEC_TX_EN__FEC_TX_EN		0x1b0b0
+				MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0	0x1b0b0
+				MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1	0x1b0b0
+				MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT	0x4001b0a8
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C1_SCL__I2C1_SCL	0x4001b8b1
+				MX6SL_PAD_I2C1_SDA__I2C1_SDA	0x4001b8b1
+			>;
+		};
+
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C2_SCL__I2C2_SCL	0x4001b8b1
+				MX6SL_PAD_I2C2_SDA__I2C2_SDA	0x4001b8b1
+			>;
+		};
+
+		pinctrl_led: ledgrp {
+			fsl,pins = <
+				MX6SL_PAD_HSIC_STROBE__GPIO3_IO20 0x17059
+			>;
+		};
+
+		pinctrl_kpp: kppgrp {
+			fsl,pins = <
+				MX6SL_PAD_KEY_ROW0__KEY_ROW0    0x1b010
+				MX6SL_PAD_KEY_ROW1__KEY_ROW1    0x1b010
+				MX6SL_PAD_KEY_ROW2__KEY_ROW2    0x1b0b0
+				MX6SL_PAD_KEY_COL0__KEY_COL0    0x110b0
+				MX6SL_PAD_KEY_COL1__KEY_COL1    0x110b0
+				MX6SL_PAD_KEY_COL2__KEY_COL2    0x110b0
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6SL_PAD_UART1_RXD__UART1_RX_DATA	0x1b0b1
+				MX6SL_PAD_UART1_TXD__UART1_TX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg1: usbotg1grp {
+			fsl,pins = <
+				MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID	0x17059
+			>;
+		};
+
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX6SL_PAD_SD1_CMD__SD1_CMD		0x17059
+				MX6SL_PAD_SD1_CLK__SD1_CLK		0x10059
+				MX6SL_PAD_SD1_DAT0__SD1_DATA0		0x17059
+				MX6SL_PAD_SD1_DAT1__SD1_DATA1		0x17059
+				MX6SL_PAD_SD1_DAT2__SD1_DATA2		0x17059
+				MX6SL_PAD_SD1_DAT3__SD1_DATA3		0x17059
+				MX6SL_PAD_SD1_DAT4__SD1_DATA4		0x17059
+				MX6SL_PAD_SD1_DAT5__SD1_DATA5		0x17059
+				MX6SL_PAD_SD1_DAT6__SD1_DATA6		0x17059
+				MX6SL_PAD_SD1_DAT7__SD1_DATA7		0x17059
+			>;
+		};
+
+		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD1_CMD__SD1_CMD		0x170b9
+				MX6SL_PAD_SD1_CLK__SD1_CLK		0x100b9
+				MX6SL_PAD_SD1_DAT0__SD1_DATA0		0x170b9
+				MX6SL_PAD_SD1_DAT1__SD1_DATA1		0x170b9
+				MX6SL_PAD_SD1_DAT2__SD1_DATA2		0x170b9
+				MX6SL_PAD_SD1_DAT3__SD1_DATA3		0x170b9
+				MX6SL_PAD_SD1_DAT4__SD1_DATA4		0x170b9
+				MX6SL_PAD_SD1_DAT5__SD1_DATA5		0x170b9
+				MX6SL_PAD_SD1_DAT6__SD1_DATA6		0x170b9
+				MX6SL_PAD_SD1_DAT7__SD1_DATA7		0x170b9
+			>;
+		};
+
+		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD1_CMD__SD1_CMD		0x170f9
+				MX6SL_PAD_SD1_CLK__SD1_CLK		0x100f9
+				MX6SL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
+				MX6SL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
+				MX6SL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
+				MX6SL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
+				MX6SL_PAD_SD1_DAT4__SD1_DATA4		0x170f9
+				MX6SL_PAD_SD1_DAT5__SD1_DATA5		0x170f9
+				MX6SL_PAD_SD1_DAT6__SD1_DATA6		0x170f9
+				MX6SL_PAD_SD1_DAT7__SD1_DATA7		0x170f9
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6SL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6SL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6SL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6SL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6SL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6SL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD2_CMD__SD2_CMD		0x170b9
+				MX6SL_PAD_SD2_CLK__SD2_CLK		0x100b9
+				MX6SL_PAD_SD2_DAT0__SD2_DATA0		0x170b9
+				MX6SL_PAD_SD2_DAT1__SD2_DATA1		0x170b9
+				MX6SL_PAD_SD2_DAT2__SD2_DATA2		0x170b9
+				MX6SL_PAD_SD2_DAT3__SD2_DATA3		0x170b9
+			>;
+		};
+
+		pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD2_CMD__SD2_CMD		0x170f9
+				MX6SL_PAD_SD2_CLK__SD2_CLK		0x100f9
+				MX6SL_PAD_SD2_DAT0__SD2_DATA0		0x170f9
+				MX6SL_PAD_SD2_DAT1__SD2_DATA1		0x170f9
+				MX6SL_PAD_SD2_DAT2__SD2_DATA2		0x170f9
+				MX6SL_PAD_SD2_DAT3__SD2_DATA3		0x170f9
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6SL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6SL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6SL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6SL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6SL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6SL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD3_CMD__SD3_CMD		0x170b9
+				MX6SL_PAD_SD3_CLK__SD3_CLK		0x100b9
+				MX6SL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+				MX6SL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+				MX6SL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+				MX6SL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			>;
+		};
+
+		pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+			fsl,pins = <
+				MX6SL_PAD_SD3_CMD__SD3_CMD		0x170f9
+				MX6SL_PAD_SD3_CLK__SD3_CLK		0x100f9
+				MX6SL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+				MX6SL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+				MX6SL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+				MX6SL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
 			>;
 		};
 	};
 };
 
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp>;
+	linux,keymap = <
+			MATRIX_KEY(0x0, 0x0, KEY_UP)         /* ROW0, COL0 */
+			MATRIX_KEY(0x0, 0x1, KEY_DOWN)       /* ROW0, COL1 */
+			MATRIX_KEY(0x0, 0x2, KEY_ENTER)      /* ROW0, COL2 */
+			MATRIX_KEY(0x1, 0x0, KEY_HOME)       /* ROW1, COL0 */
+			MATRIX_KEY(0x1, 0x1, KEY_RIGHT)      /* ROW1, COL1 */
+			MATRIX_KEY(0x1, 0x2, KEY_LEFT)       /* ROW1, COL2 */
+			MATRIX_KEY(0x2, 0x0, KEY_VOLUMEDOWN) /* ROW2, COL0 */
+			MATRIX_KEY(0x2, 0x1, KEY_VOLUMEUP)   /* ROW2, COL1 */
+	>;
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
 &usbotg1 {
 	vbus-supply = <&reg_usb_otg1_vbus>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg1_1>;
+	pinctrl-0 = <&pinctrl_usbotg1>;
 	disable-over-current;
 	status = "okay";
 };
@@ -106,9 +501,9 @@
 
 &usdhc1 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
-	pinctrl-0 = <&pinctrl_usdhc1_1>;
-	pinctrl-1 = <&pinctrl_usdhc1_1_100mhz>;
-	pinctrl-2 = <&pinctrl_usdhc1_1_200mhz>;
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
 	bus-width = <8>;
 	cd-gpios = <&gpio4 7 0>;
 	wp-gpios = <&gpio4 6 0>;
@@ -117,9 +512,9 @@
 
 &usdhc2 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
-	pinctrl-0 = <&pinctrl_usdhc2_1>;
-	pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
-	pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
 	cd-gpios = <&gpio5 0 0>;
 	wp-gpios = <&gpio4 29 0>;
 	status = "okay";
@@ -127,9 +522,9 @@
 
 &usdhc3 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
-	pinctrl-0 = <&pinctrl_usdhc3_1>;
-	pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
-	pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
 	cd-gpios = <&gpio3 22 0>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 28558f1aaf2d..3cb4941afeef 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -7,6 +7,7 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "skeleton.dtsi"
 #include "imx6sl-pinfunc.h"
 #include <dt-bindings/clock/imx6sl-clock.h>
@@ -27,6 +28,8 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usbphy0 = &usbphy1;
+		usbphy1 = &usbphy2;
 	};
 
 	cpus {
@@ -38,6 +41,27 @@
 			device_type = "cpu";
 			reg = <0x0>;
 			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				996000  1275000
+				792000  1175000
+				396000  975000
+			>;
+			fsl,soc-operating-points = <
+				/* ARM kHz      SOC-PU uV */
+				996000          1225000
+				792000          1175000
+				396000          1175000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>,
+					<&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_CLK_PLL1_SW>,
+					<&clks IMX6SL_CLK_PLL1_SYS>;
+			clock-names = "arm", "pll2_pfd2_396m", "step",
+				      "pll1_sw", "pll1_sys";
+			arm-supply = <&reg_arm>;
+			pu-supply = <&reg_pu>;
+			soc-supply = <&reg_soc>;
 		};
 	};
 
@@ -73,10 +97,16 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
+		ocram: sram@00900000 {
+			compatible = "mmio-sram";
+			reg = <0x00900000 0x20000>;
+			clocks = <&clks IMX6SL_CLK_OCRAM>;
+		};
+
 		L2: l2-cache@00a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
-			interrupts = <0 92 0x04>;
+			interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
 			cache-unified;
 			cache-level = <2>;
 			arm,tag-latency = <4 2 3>;
@@ -85,7 +115,7 @@
 
 		pmu {
 			compatible = "arm,cortex-a9-pmu";
-			interrupts = <0 94 0x04>;
+			interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		aips1: aips-bus@02000000 {
@@ -104,7 +134,7 @@
 
 				spdif: spdif@02004000 {
 					reg = <0x02004000 0x4000>;
-					interrupts = <0 52 0x04>;
+					interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
 				};
 
 				ecspi1: ecspi@02008000 {
@@ -112,7 +142,7 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02008000 0x4000>;
-					interrupts = <0 31 0x04>;
+					interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_ECSPI1>,
 						 <&clks IMX6SL_CLK_ECSPI1>;
 					clock-names = "ipg", "per";
@@ -124,7 +154,7 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
 					reg = <0x0200c000 0x4000>;
-					interrupts = <0 32 0x04>;
+					interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_ECSPI2>,
 						 <&clks IMX6SL_CLK_ECSPI2>;
 					clock-names = "ipg", "per";
@@ -136,7 +166,7 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02010000 0x4000>;
-					interrupts = <0 33 0x04>;
+					interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_ECSPI3>,
 						 <&clks IMX6SL_CLK_ECSPI3>;
 					clock-names = "ipg", "per";
@@ -148,7 +178,7 @@
 					#size-cells = <0>;
 					compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02014000 0x4000>;
-					interrupts = <0 34 0x04>;
+					interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_ECSPI4>,
 						 <&clks IMX6SL_CLK_ECSPI4>;
 					clock-names = "ipg", "per";
@@ -159,7 +189,7 @@
 					compatible = "fsl,imx6sl-uart",
 						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02018000 0x4000>;
-					interrupts = <0 30 0x04>;
+					interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
@@ -172,7 +202,7 @@
 					compatible = "fsl,imx6sl-uart",
 						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02020000 0x4000>;
-					interrupts = <0 26 0x04>;
+					interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
@@ -185,7 +215,7 @@
 					compatible = "fsl,imx6sl-uart",
 						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02024000 0x4000>;
-					interrupts = <0 27 0x04>;
+					interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
@@ -195,9 +225,11 @@
 				};
 
 				ssi1: ssi@02028000 {
-					compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6sl-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x02028000 0x4000>;
-					interrupts = <0 46 0x04>;
+					interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI1>;
 					dmas = <&sdma 37 1 0>,
 					       <&sdma 38 1 0>;
@@ -207,9 +239,11 @@
 				};
 
 				ssi2: ssi@0202c000 {
-					compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6sl-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x0202c000 0x4000>;
-					interrupts = <0 47 0x04>;
+					interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI2>;
 					dmas = <&sdma 41 1 0>,
 					       <&sdma 42 1 0>;
@@ -219,9 +253,11 @@
 				};
 
 				ssi3: ssi@02030000 {
-					compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
+					compatible = "fsl,imx6sl-ssi",
+							"fsl,imx51-ssi",
+							"fsl,imx21-ssi";
 					reg = <0x02030000 0x4000>;
-					interrupts = <0 48 0x04>;
+					interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI3>;
 					dmas = <&sdma 45 1 0>,
 					       <&sdma 46 1 0>;
@@ -234,7 +270,7 @@
 					compatible = "fsl,imx6sl-uart",
 						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02034000 0x4000>;
-					interrupts = <0 28 0x04>;
+					interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
@@ -247,7 +283,7 @@
 					compatible = "fsl,imx6sl-uart",
 						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02038000 0x4000>;
-					interrupts = <0 29 0x04>;
+					interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
@@ -261,7 +297,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
 				reg = <0x02080000 0x4000>;
-				interrupts = <0 83 0x04>;
+				interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_PWM1>,
 					 <&clks IMX6SL_CLK_PWM1>;
 				clock-names = "ipg", "per";
@@ -271,7 +307,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
 				reg = <0x02084000 0x4000>;
-				interrupts = <0 84 0x04>;
+				interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_PWM2>,
 					 <&clks IMX6SL_CLK_PWM2>;
 				clock-names = "ipg", "per";
@@ -281,7 +317,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
 				reg = <0x02088000 0x4000>;
-				interrupts = <0 85 0x04>;
+				interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_PWM3>,
 					 <&clks IMX6SL_CLK_PWM3>;
 				clock-names = "ipg", "per";
@@ -291,7 +327,7 @@
 				#pwm-cells = <2>;
 				compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
 				reg = <0x0208c000 0x4000>;
-				interrupts = <0 86 0x04>;
+				interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_PWM4>,
 					 <&clks IMX6SL_CLK_PWM4>;
 				clock-names = "ipg", "per";
@@ -300,7 +336,7 @@
 			gpt: gpt@02098000 {
 				compatible = "fsl,imx6sl-gpt";
 				reg = <0x02098000 0x4000>;
-				interrupts = <0 55 0x04>;
+				interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_GPT>,
 					 <&clks IMX6SL_CLK_GPT_SERIAL>;
 				clock-names = "ipg", "per";
@@ -309,7 +345,8 @@
 			gpio1: gpio@0209c000 {
 				compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
 				reg = <0x0209c000 0x4000>;
-				interrupts = <0 66 0x04 0 67 0x04>;
+				interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 67 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -319,7 +356,8 @@
 			gpio2: gpio@020a0000 {
 				compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
 				reg = <0x020a0000 0x4000>;
-				interrupts = <0 68 0x04 0 69 0x04>;
+				interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 69 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -329,7 +367,8 @@
 			gpio3: gpio@020a4000 {
 				compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
 				reg = <0x020a4000 0x4000>;
-				interrupts = <0 70 0x04 0 71 0x04>;
+				interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 71 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -339,7 +378,8 @@
 			gpio4: gpio@020a8000 {
 				compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
 				reg = <0x020a8000 0x4000>;
-				interrupts = <0 72 0x04 0 73 0x04>;
+				interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 73 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -349,7 +389,8 @@
 			gpio5: gpio@020ac000 {
 				compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
 				reg = <0x020ac000 0x4000>;
-				interrupts = <0 74 0x04 0 75 0x04>;
+				interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 75 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -357,21 +398,23 @@
 			};
 
 			kpp: kpp@020b8000 {
+				compatible = "fsl,imx6sl-kpp", "fsl,imx21-kpp";
 				reg = <0x020b8000 0x4000>;
-				interrupts = <0 82 0x04>;
+				interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SL_CLK_DUMMY>;
 			};
 
 			wdog1: wdog@020bc000 {
 				compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
 				reg = <0x020bc000 0x4000>;
-				interrupts = <0 80 0x04>;
+				interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_DUMMY>;
 			};
 
 			wdog2: wdog@020c0000 {
 				compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
 				reg = <0x020c0000 0x4000>;
-				interrupts = <0 81 0x04>;
+				interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_DUMMY>;
 				status = "disabled";
 			};
@@ -379,7 +422,8 @@
 			clks: ccm@020c4000 {
 				compatible = "fsl,imx6sl-ccm";
 				reg = <0x020c4000 0x4000>;
-				interrupts = <0 87 0x04 0 88 0x04>;
+				interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 88 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
 			};
 
@@ -388,7 +432,9 @@
 					     "fsl,imx6q-anatop",
 					     "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
-				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+				interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
 				regulator-1p1@110 {
 					compatible = "fsl,anatop-regulator";
@@ -434,7 +480,7 @@
 
 				reg_arm: regulator-vddcore@140 {
 					compatible = "fsl,anatop-regulator";
-					regulator-name = "cpu";
+					regulator-name = "vddarm";
 					regulator-min-microvolt = <725000>;
 					regulator-max-microvolt = <1450000>;
 					regulator-always-on;
@@ -487,15 +533,17 @@
 			usbphy1: usbphy@020c9000 {
 				compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020c9000 0x1000>;
-				interrupts = <0 44 0x04>;
+				interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USBPHY1>;
+				fsl,anatop = <&anatop>;
 			};
 
 			usbphy2: usbphy@020ca000 {
 				compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020ca000 0x1000>;
-				interrupts = <0 45 0x04>;
+				interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USBPHY2>;
+				fsl,anatop = <&anatop>;
 			};
 
 			snvs@020cc000 {
@@ -507,31 +555,33 @@
 				snvs-rtc-lp@34 {
 					compatible = "fsl,sec-v4.0-mon-rtc-lp";
 					reg = <0x34 0x58>;
-					interrupts = <0 19 0x04 0 20 0x04>;
+					interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
+						     <0 20 IRQ_TYPE_LEVEL_HIGH>;
 				};
 			};
 
 			epit1: epit@020d0000 {
 				reg = <0x020d0000 0x4000>;
-				interrupts = <0 56 0x04>;
+				interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			epit2: epit@020d4000 {
 				reg = <0x020d4000 0x4000>;
-				interrupts = <0 57 0x04>;
+				interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			src: src@020d8000 {
 				compatible = "fsl,imx6sl-src", "fsl,imx51-src";
 				reg = <0x020d8000 0x4000>;
-				interrupts = <0 91 0x04 0 96 0x04>;
+				interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 96 IRQ_TYPE_LEVEL_HIGH>;
 				#reset-cells = <1>;
 			};
 
 			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
-				interrupts = <0 89 0x04>;
+				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			gpr: iomuxc-gpr@020e0000 {
@@ -543,235 +593,22 @@
 			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6sl-iomuxc";
 				reg = <0x020e0000 0x4000>;
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
-							MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
-							MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
-						>;
-					};
-				};
-
-				fec {
-					pinctrl_fec_1: fecgrp-1 {
-						fsl,pins = <
-							MX6SL_PAD_FEC_MDC__FEC_MDC         0x1b0b0
-							MX6SL_PAD_FEC_MDIO__FEC_MDIO       0x1b0b0
-							MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV    0x1b0b0
-							MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0   0x1b0b0
-							MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1   0x1b0b0
-							MX6SL_PAD_FEC_TX_EN__FEC_TX_EN     0x1b0b0
-							MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0   0x1b0b0
-							MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1   0x1b0b0
-							MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
-							MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				usbotg1 {
-					pinctrl_usbotg1_1: usbotg1grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg1_2: usbotg1grp-2 {
-						fsl,pins = <
-							MX6SL_PAD_FEC_RXD0__USB_OTG1_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg1_3: usbotg1grp-3 {
-						fsl,pins = <
-							MX6SL_PAD_LCD_DAT1__USB_OTG1_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg1_4: usbotg1grp-4 {
-						fsl,pins = <
-							MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg1_5: usbotg1grp-5 {
-						fsl,pins = <
-							MX6SL_PAD_SD3_DAT0__USB_OTG1_ID 0x17059
-						>;
-					};
-				};
-
-				usbotg2 {
-					pinctrl_usbotg2_1: usbotg2grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x17059
-						>;
-					};
-
-					pinctrl_usbotg2_2: usbotg2grp-2 {
-						fsl,pins = <
-							MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x17059
-						>;
-					};
-
-					pinctrl_usbotg2_3: usbotg2grp-3 {
-						fsl,pins = <
-							MX6SL_PAD_KEY_ROW5__USB_OTG2_OC 0x17059
-						>;
-					};
-
-					pinctrl_usbotg2_4: usbotg2grp-4 {
-						fsl,pins = <
-							MX6SL_PAD_SD3_DAT2__USB_OTG2_OC 0x17059
-						>;
-					};
-				};
-
-				usdhc1 {
-					pinctrl_usdhc1_1: usdhc1grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_SD1_CMD__SD1_CMD    0x17059
-							MX6SL_PAD_SD1_CLK__SD1_CLK    0x10059
-							MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-							MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-							MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-							MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-							MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
-							MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
-							MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
-							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc1_1_100mhz: usdhc1grp-1-100mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
-							MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
-							MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
-							MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
-							MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
-							MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
-							MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
-							MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
-							MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
-							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
-						>;
-					};
-
-					pinctrl_usdhc1_1_200mhz: usdhc1grp-1-200mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
-							MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
-							MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
-							MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
-							MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
-							MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
-							MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
-							MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
-							MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
-							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
-						>;
-					};
-
-
-				};
-
-				usdhc2 {
-					pinctrl_usdhc2_1: usdhc2grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6SL_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-						>;
-					};
-
-					pinctrl_usdhc2_1_100mhz: usdhc2grp-1-100mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD2_CMD__SD2_CMD    0x170b9
-							MX6SL_PAD_SD2_CLK__SD2_CLK    0x100b9
-							MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
-							MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
-							MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
-							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
-						>;
-					};
-
-					pinctrl_usdhc2_1_200mhz: usdhc2grp-1-200mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD2_CMD__SD2_CMD    0x170f9
-							MX6SL_PAD_SD2_CLK__SD2_CLK    0x100f9
-							MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
-							MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
-							MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
-							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
-						>;
-					};
-
-				};
-
-				usdhc3 {
-					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <
-							MX6SL_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6SL_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-						>;
-					};
-
-					pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD3_CMD__SD3_CMD    0x170b9
-							MX6SL_PAD_SD3_CLK__SD3_CLK    0x100b9
-							MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
-							MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
-							MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
-							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
-						>;
-					};
-
-					pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
-						fsl,pins = <
-							MX6SL_PAD_SD3_CMD__SD3_CMD    0x170f9
-							MX6SL_PAD_SD3_CLK__SD3_CLK    0x100f9
-							MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
-							MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
-							MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
-							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
-						>;
-					};
-				};
 			};
 
 			csi: csi@020e4000 {
 				reg = <0x020e4000 0x4000>;
-				interrupts = <0 7 0x04>;
+				interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			spdc: spdc@020e8000 {
 				reg = <0x020e8000 0x4000>;
-				interrupts = <0 6 0x04>;
+				interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			sdma: sdma@020ec000 {
 				compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma";
 				reg = <0x020ec000 0x4000>;
-				interrupts = <0 2 0x04>;
+				interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_SDMA>,
 					 <&clks IMX6SL_CLK_SDMA>;
 				clock-names = "ipg", "ahb";
@@ -782,22 +619,22 @@
 
 			pxp: pxp@020f0000 {
 				reg = <0x020f0000 0x4000>;
-				interrupts = <0 98 0x04>;
+				interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			epdc: epdc@020f4000 {
 				reg = <0x020f4000 0x4000>;
-				interrupts = <0 97 0x04>;
+				interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			lcdif: lcdif@020f8000 {
 				reg = <0x020f8000 0x4000>;
-				interrupts = <0 39 0x04>;
+				interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			dcp: dcp@020fc000 {
 				reg = <0x020fc000 0x4000>;
-				interrupts = <0 99 0x04>;
+				interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -811,7 +648,7 @@
 			usbotg1: usb@02184000 {
 				compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
 				reg = <0x02184000 0x200>;
-				interrupts = <0 43 0x04>;
+				interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USBOH3>;
 				fsl,usbphy = <&usbphy1>;
 				fsl,usbmisc = <&usbmisc 0>;
@@ -821,7 +658,7 @@
 			usbotg2: usb@02184200 {
 				compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
-				interrupts = <0 42 0x04>;
+				interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USBOH3>;
 				fsl,usbphy = <&usbphy2>;
 				fsl,usbmisc = <&usbmisc 1>;
@@ -831,7 +668,7 @@
 			usbh: usb@02184400 {
 				compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
-				interrupts = <0 40 0x04>;
+				interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USBOH3>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
@@ -847,7 +684,7 @@
 			fec: ethernet@02188000 {
 				compatible = "fsl,imx6sl-fec", "fsl,imx25-fec";
 				reg = <0x02188000 0x4000>;
-				interrupts = <0 114 0x04>;
+				interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_ENET_REF>,
 					 <&clks IMX6SL_CLK_ENET_REF>;
 				clock-names = "ipg", "ahb";
@@ -857,7 +694,7 @@
 			usdhc1: usdhc@02190000 {
 				compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
 				reg = <0x02190000 0x4000>;
-				interrupts = <0 22 0x04>;
+				interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USDHC1>,
 					 <&clks IMX6SL_CLK_USDHC1>,
 					 <&clks IMX6SL_CLK_USDHC1>;
@@ -869,7 +706,7 @@
 			usdhc2: usdhc@02194000 {
 				compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
 				reg = <0x02194000 0x4000>;
-				interrupts = <0 23 0x04>;
+				interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USDHC2>,
 					 <&clks IMX6SL_CLK_USDHC2>,
 					 <&clks IMX6SL_CLK_USDHC2>;
@@ -881,7 +718,7 @@
 			usdhc3: usdhc@02198000 {
 				compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
 				reg = <0x02198000 0x4000>;
-				interrupts = <0 24 0x04>;
+				interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USDHC3>,
 					 <&clks IMX6SL_CLK_USDHC3>,
 					 <&clks IMX6SL_CLK_USDHC3>;
@@ -893,7 +730,7 @@
 			usdhc4: usdhc@0219c000 {
 				compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
 				reg = <0x0219c000 0x4000>;
-				interrupts = <0 25 0x04>;
+				interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_USDHC4>,
 					 <&clks IMX6SL_CLK_USDHC4>,
 					 <&clks IMX6SL_CLK_USDHC4>;
@@ -907,7 +744,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
 				reg = <0x021a0000 0x4000>;
-				interrupts = <0 36 0x04>;
+				interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_I2C1>;
 				status = "disabled";
 			};
@@ -917,7 +754,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
 				reg = <0x021a4000 0x4000>;
-				interrupts = <0 37 0x04>;
+				interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_I2C2>;
 				status = "disabled";
 			};
@@ -927,7 +764,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
 				reg = <0x021a8000 0x4000>;
-				interrupts = <0 38 0x04>;
+				interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_I2C3>;
 				status = "disabled";
 			};
@@ -939,12 +776,12 @@
 
 			rngb: rngb@021b4000 {
 				reg = <0x021b4000 0x4000>;
-				interrupts = <0 5 0x04>;
+				interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			weim: weim@021b8000 {
 				reg = <0x021b8000 0x4000>;
-				interrupts = <0 14 0x04>;
+				interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			ocotp: ocotp@021bc000 {
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index e6be9315ff0a..b10e6351da53 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -18,6 +18,28 @@
 		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
 	};
 
+	/* 24 MHz chrystal on the core module */
+	xtal24mhz: xtal24mhz@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	pclk: pclk@0 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	/* The UART clock is 14.74 MHz divided by an ICS525 */
+	uartclk: uartclk@14.74M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <14745600>;
+	};
+
 	syscon {
 		compatible = "arm,integrator-ap-syscon";
 		reg = <0x11000000 0x100>;
@@ -28,14 +50,17 @@
 
 	timer0: timer@13000000 {
 		compatible = "arm,integrator-timer";
+		clocks = <&xtal24mhz>;
 	};
 
 	timer1: timer@13000100 {
 		compatible = "arm,integrator-timer";
+		clocks = <&xtal24mhz>;
 	};
 
 	timer2: timer@13000200 {
 		compatible = "arm,integrator-timer";
+		clocks = <&xtal24mhz>;
 	};
 
 	pic: pic@14000000 {
@@ -92,26 +117,36 @@
 		rtc: rtc@15000000 {
 			compatible = "arm,pl030", "arm,primecell";
 			arm,primecell-periphid = <0x00041030>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		uart0: uart@16000000 {
 			compatible = "arm,pl010", "arm,primecell";
 			arm,primecell-periphid = <0x00041010>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		uart1: uart@17000000 {
 			compatible = "arm,pl010", "arm,primecell";
 			arm,primecell-periphid = <0x00041010>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		kmi0: kmi@18000000 {
 			compatible = "arm,pl050", "arm,primecell";
 			arm,primecell-periphid = <0x00041050>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
 		};
 
 		kmi1: kmi@19000000 {
 			compatible = "arm,pl050", "arm,primecell";
 			arm,primecell-periphid = <0x00041050>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index a21c17de9a5e..d43f15b4f79a 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -13,25 +13,107 @@
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
 
+	/*
+	 * The Integrator/CP overall clocking architecture can be found in
+	 * ARM DUI 0184B page 7-28 "Integrator/CP922T system clocks" which
+	 * appear to illustrate the layout used in most configurations.
+	 */
+
+	/* The codec chrystal operates at 24.576 MHz */
+	xtal_codec: xtal24.576@24.576M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24576000>;
+	};
+
+	/* The chrystal is divided by 2 by the codec for the AACI bit clock */
+	aaci_bitclk: aaci_bitclk@12.288M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <2>;
+		clock-mult = <1>;
+		clocks = <&xtal_codec>;
+	};
+
+	/* This is a 25MHz chrystal on the base board */
+	xtal25mhz: xtal25mhz@25M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	/* The UART clock is 14.74 MHz divided from 25MHz by an ICS525 */
+	uartclk: uartclk@14.74M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <14745600>;
+	};
+
+	/* Actually sysclk I think */
+	pclk: pclk@0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	core-module@10000000 {
+		/* 24 MHz chrystal on the core module */
+		xtal24mhz: xtal24mhz@24M {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+
+		/*
+		 * External oscillator on the core module, usually used
+		 * to drive video circuitry. Driven from the 24MHz clock.
+		 */
+		auxosc: cm_aux_osc@25M {
+			#clock-cells = <0>;
+			compatible = "arm,integrator-cm-auxosc";
+			clocks = <&xtal24mhz>;
+		};
+
+		/* The KMI clock is the 24 MHz oscillator divided to 8MHz */
+		kmiclk: kmiclk@1M {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <3>;
+			clock-mult = <1>;
+			clocks = <&xtal24mhz>;
+		};
+
+		/* The timer clock is the 24 MHz oscillator divided to 1MHz */
+		timclk: timclk@1M {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <24>;
+			clock-mult = <1>;
+			clocks = <&xtal24mhz>;
+		};
+	};
+
 	syscon {
 		compatible = "arm,integrator-cp-syscon";
 		reg = <0xcb000000 0x100>;
 	};
 
 	timer0: timer@13000000 {
-		/* TIMER0 runs @ 25MHz */
+		/* TIMER0 runs directly on the 25MHz chrystal */
 		compatible = "arm,integrator-cp-timer";
-		status = "disabled";
+		clocks = <&xtal25mhz>;
 	};
 
 	timer1: timer@13000100 {
 		/* TIMER1 runs @ 1MHz */
 		compatible = "arm,integrator-cp-timer";
+		clocks = <&timclk>;
 	};
 
 	timer2: timer@13000200 {
 		/* TIMER2 runs @ 1MHz */
 		compatible = "arm,integrator-cp-timer";
+		clocks = <&timclk>;
 	};
 
 	pic: pic@14000000 {
@@ -74,22 +156,32 @@
 		 */
 		rtc@15000000 {
 			compatible = "arm,pl031", "arm,primecell";
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		uart@16000000 {
 			compatible = "arm,pl011", "arm,primecell";
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		uart@17000000 {
 			compatible = "arm,pl011", "arm,primecell";
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		kmi@18000000 {
 			compatible = "arm,pl050", "arm,primecell";
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
 		};
 
 		kmi@19000000 {
 			compatible = "arm,pl050", "arm,primecell";
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
 		};
 
 		/*
@@ -100,18 +192,24 @@
 			reg = <0x1c000000 0x1000>;
 			interrupts = <23 24>;
 			max-frequency = <515633>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "mclk", "apb_pclk";
 		};
 
 		aaci@1d000000 {
 			compatible = "arm,pl041", "arm,primecell";
 			reg = <0x1d000000 0x1000>;
 			interrupts = <25>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		clcd@c0000000 {
 			compatible = "arm,pl110", "arm,primecell";
 			reg = <0xC0000000 0x1000>;
 			interrupts = <22>;
+			clocks = <&auxosc>, <&pclk>;
+			clock-names = "clcd", "apb_pclk";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/k2e-clocks.dtsi b/arch/arm/boot/dts/k2e-clocks.dtsi
new file mode 100644
index 000000000000..90774d604bc1
--- /dev/null
+++ b/arch/arm/boot/dts/k2e-clocks.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison SoC specific device tree
+ *
+ * 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.
+ */
+
+clocks {
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>;
+		reg-names = "control", "multiplier";
+		fixed-postdiv = <2>;
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkpass>;
+		clock-output-names = "pa-pll-clk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3a>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	clkusb1: clkusb1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "usb";
+		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkhyperlink0: clkhyperlink0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-0";
+		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <5>;
+	};
+
+	clkpcie1: clkpcie1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "pcie";
+		reg = <0x0235006c 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkxge: clkxge {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "xge";
+		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+};
diff --git a/arch/arm/boot/dts/k2e-evm.dts b/arch/arm/boot/dts/k2e-evm.dts
new file mode 100644
index 000000000000..bb8faeb1a2f8
--- /dev/null
+++ b/arch/arm/boot/dts/k2e-evm.dts
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison EVM device tree
+ *
+ * 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.
+ */
+/dts-v1/;
+
+#include "keystone.dtsi"
+#include "k2e.dtsi"
+
+/ {
+	compatible =  "ti,k2e-evm";
+	model = "Texas Instruments Keystone 2 Edison EVM";
+
+	soc {
+
+		clocks {
+			refclksys: refclksys {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-sys";
+			};
+
+			refclkpass: refclkpass {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-pass";
+			};
+
+			refclkddr3a: refclkddr3a {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-ddr3a";
+			};
+		};
+	};
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/k2e.dtsi b/arch/arm/boot/dts/k2e.dtsi
new file mode 100644
index 000000000000..03d01909525b
--- /dev/null
+++ b/arch/arm/boot/dts/k2e.dtsi
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison soc device tree
+ *
+ * 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.
+ */
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <3>;
+		};
+	};
+
+	soc {
+		/include/ "k2e-clocks.dtsi"
+
+		usb: usb@2680000 {
+			interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
+			dwc3@2690000 {
+				interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
+
+		usb1_phy: usb_phy@2620750 {
+			compatible = "ti,keystone-usbphy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x2620750 24>;
+			status = "disabled";
+		};
+
+		usb1: usb@25000000 {
+			compatible = "ti,keystone-dwc3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x25000000 0x10000>;
+			clocks = <&clkusb1>;
+			clock-names = "usb";
+			interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
+			ranges;
+			status = "disabled";
+
+			dwc3@25010000 {
+				compatible = "synopsys,dwc3";
+				reg = <0x25010000 0x70000>;
+				interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
+				usb-phy = <&usb1_phy>, <&usb1_phy>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/k2hk-clocks.dtsi b/arch/arm/boot/dts/k2hk-clocks.dtsi
new file mode 100644
index 000000000000..a71aa2996321
--- /dev/null
+++ b/arch/arm/boot/dts/k2hk-clocks.dtsi
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Kepler/Hawking SoC clock nodes
+ *
+ * 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.
+ */
+
+clocks {
+	armpllclk: armpllclk@2620370 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkarm>;
+		clock-output-names = "arm-pll-clk";
+		reg = <0x02620370 4>;
+		reg-names = "control";
+	};
+
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>;
+		reg-names = "control", "multiplier";
+		fixed-postdiv = <2>;
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkpass>;
+		clock-output-names = "pa-pll-clk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3a>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	ddr3bpllclk: ddr3bpllclk@2620368 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3b>;
+		clock-output-names = "ddr-3b-pll-clk";
+		reg = <0x02620368 4>;
+		reg-names = "control";
+	};
+
+	clktsip: clktsip {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "tsip";
+		reg = <0x0235000c 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clksrio: clksrio {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1rstiso13>;
+		clock-output-names = "srio";
+		reg = <0x0235002c 0xb00>, <0x02350010 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <4>;
+	};
+
+	clkhyperlink0: clkhyperlink0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-0";
+		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <5>;
+	};
+
+	clkgem1: clkgem1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem1";
+		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <9>;
+	};
+
+	clkgem2: clkgem2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem2";
+		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <10>;
+	};
+
+	clkgem3: clkgem3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem3";
+		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <11>;
+	};
+
+	clkgem4: clkgem4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem4";
+		reg = <0x0235004c 0xb00>, <0x02350030 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <12>;
+	};
+
+	clkgem5: clkgem5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem5";
+		reg = <0x02350050 0xb00>, <0x02350034 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <13>;
+	};
+
+	clkgem6: clkgem6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem6";
+		reg = <0x02350054 0xb00>, <0x02350038 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <14>;
+	};
+
+	clkgem7: clkgem7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem7";
+		reg = <0x02350058 0xb00>, <0x0235003c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <15>;
+	};
+
+	clkddr31: clkddr31 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "ddr3-1";
+		reg = <0x02350060 0xb00>, <0x02350040 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <16>;
+	};
+
+	clktac: clktac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tac";
+		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac01: clkrac01 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-01";
+		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac23: clkrac23 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-23";
+		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkfftc0: clkfftc0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-0";
+		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc1: clkfftc1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-1";
+		reg = <0x02350074 0xb00>, <0x023504c0 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc2: clkfftc2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-2";
+		reg = <0x02350078 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc3: clkfftc3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-3";
+		reg = <0x0235007c 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc4: clkfftc4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-4";
+		reg = <0x02350080 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc5: clkfftc5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-5";
+		reg = <0x02350084 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkaif: clkaif {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "aif";
+		reg = <0x02350088 0xb00>, <0x02350054 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <21>;
+	};
+
+	clktcp3d0: clktcp3d0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-0";
+		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d1: clktcp3d1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-1";
+		reg = <0x02350090 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d2: clktcp3d2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-2";
+		reg = <0x02350094 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clktcp3d3: clktcp3d3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-3";
+		reg = <0x02350098 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clkvcp0: clkvcp0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-0";
+		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp1: clkvcp1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-1";
+		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp2: clkvcp2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-2";
+		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp3: clkvcp3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-3";
+		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp4: clkvcp4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-4";
+		reg = <0x023500ac 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp5: clkvcp5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-5";
+		reg = <0x023500b0 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp6: clkvcp6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-6";
+		reg = <0x023500b4 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp7: clkvcp7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-7";
+		reg = <0x023500b8 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkbcp: clkbcp {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "bcp";
+		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <26>;
+	};
+
+	clkdxb: clkdxb {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dxb";
+		reg = <0x023500c0 0xb00>, <0x0235006c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <27>;
+	};
+
+	clkhyperlink1: clkhyperlink1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-1";
+		reg = <0x023500c4 0xb00>, <0x02350070 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <28>;
+	};
+
+	clkxge: clkxge {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "xge";
+		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+};
diff --git a/arch/arm/boot/dts/k2hk-evm.dts b/arch/arm/boot/dts/k2hk-evm.dts
index eaefdfef65c3..d8cc99af51e8 100644
--- a/arch/arm/boot/dts/k2hk-evm.dts
+++ b/arch/arm/boot/dts/k2hk-evm.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Texas Instruments, Inc.
+ * Copyright 2013-2014 Texas Instruments, Inc.
  *
  * Keystone 2 Kepler/Hawking EVM device tree
  *
@@ -10,12 +10,14 @@
 /dts-v1/;
 
 #include "keystone.dtsi"
+#include "k2hk.dtsi"
 
 / {
-	compatible =  "ti,keystone-evm";
+	compatible =  "ti,k2hk-evm";
+	model = "Texas Instruments Keystone 2 Kepler/Hawking EVM";
 
 	soc {
-		clock {
+		clocks {
 			refclksys: refclksys {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
@@ -52,6 +54,29 @@
 			};
 		};
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		debug1_1 {
+			label = "keystone:green:debug1";
+			gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; /* 12 */
+		};
+
+		debug1_2 {
+			label = "keystone:red:debug1";
+			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* 13 */
+		};
+
+		debug2 {
+			label = "keystone:blue:debug2";
+			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* 14 */
+		};
+
+		debug3 {
+			label = "keystone:blue:debug3";
+			gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; /* 15 */
+		};
+	};
 };
 
 &usb_phy {
diff --git a/arch/arm/boot/dts/k2hk.dtsi b/arch/arm/boot/dts/k2hk.dtsi
new file mode 100644
index 000000000000..c73899c73118
--- /dev/null
+++ b/arch/arm/boot/dts/k2hk.dtsi
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Kepler/Hawking soc specific device tree
+ *
+ * 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.
+ */
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <3>;
+		};
+	};
+
+	soc {
+		/include/ "k2hk-clocks.dtsi"
+	};
+};
diff --git a/arch/arm/boot/dts/k2l-clocks.dtsi b/arch/arm/boot/dts/k2l-clocks.dtsi
new file mode 100644
index 000000000000..f584b80200f8
--- /dev/null
+++ b/arch/arm/boot/dts/k2l-clocks.dtsi
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 lamarr SoC clock nodes
+ *
+ * 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.
+ */
+
+clocks {
+	armpllclk: armpllclk@2620370 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "arm-pll-clk";
+		reg = <0x02620370 4>;
+		reg-names = "control";
+	};
+
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>;
+		reg-names = "control", "multiplier";
+		fixed-postdiv = <2>;
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "pa-pll-clk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	clkdfeiqnsys: clkdfeiqnsys {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "dfe";
+		reg-names = "control", "domain";
+		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
+		domain-id = <0>;
+	};
+
+	clkpcie1: clkpcie1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "pcie";
+		reg = <0x0235002c 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <4>;
+	};
+
+	clkgem1: clkgem1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem1";
+		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <9>;
+	};
+
+	clkgem2: clkgem2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem2";
+		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <10>;
+	};
+
+	clkgem3: clkgem3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem3";
+		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <11>;
+	};
+
+	clktac: clktac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tac";
+		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac: clkrac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac";
+		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkdfepd0: clkdfepd0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dfe-pd0";
+		reg = <0x0235006c 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkfftc0: clkfftc0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-0";
+		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkosr: clkosr {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "osr";
+		reg = <0x02350088 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <21>;
+	};
+
+	clktcp3d0: clktcp3d0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-0";
+		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d1: clktcp3d1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-1";
+		reg = <0x02350094 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clkvcp0: clkvcp0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-0";
+		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp1: clkvcp1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-1";
+		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp2: clkvcp2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-2";
+		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp3: clkvcp3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-3";
+		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkbcp: clkbcp {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "bcp";
+		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <26>;
+	};
+
+	clkdfepd1: clkdfepd1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dfe-pd1";
+		reg = <0x023500c0 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <27>;
+	};
+
+	clkfftc1: clkfftc1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-1";
+		reg = <0x023500c4 0xb00>, <0x023504c0 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <28>;
+	};
+
+	clkiqnail: clkiqnail {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "iqn-ail";
+		reg = <0x023500c8 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+
+	clkuart2: clkuart2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart2";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkuart3: clkuart3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart3";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/k2l-evm.dts b/arch/arm/boot/dts/k2l-evm.dts
new file mode 100644
index 000000000000..ebf316a1bf6b
--- /dev/null
+++ b/arch/arm/boot/dts/k2l-evm.dts
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Lamarr EVM device tree
+ *
+ * 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.
+ */
+/dts-v1/;
+
+#include "keystone.dtsi"
+#include "k2l.dtsi"
+
+/ {
+	compatible =  "ti,k2l-evm";
+	model = "Texas Instruments Keystone 2 Lamarr EVM";
+
+	soc {
+		clocks {
+			refclksys: refclksys {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <122880000>;
+				clock-output-names = "refclk-sys";
+			};
+		};
+	};
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/k2l.dtsi b/arch/arm/boot/dts/k2l.dtsi
new file mode 100644
index 000000000000..1f7f479589e1
--- /dev/null
+++ b/arch/arm/boot/dts/k2l.dtsi
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Lamarr SoC specific device tree
+ *
+ * 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.
+ */
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+	};
+
+	soc {
+
+		/include/ "k2l-clocks.dtsi"
+
+		uart2: serial@02348400 {
+			compatible = "ns16550a";
+			current-speed = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			reg = <0x02348400 0x100>;
+			clocks	= <&clkuart2>;
+			interrupts = <GIC_SPI 432 IRQ_TYPE_EDGE_RISING>;
+		};
+
+		uart3:	serial@02348800 {
+			compatible = "ns16550a";
+			current-speed = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			reg = <0x02348800 0x100>;
+			clocks	= <&clkuart3>;
+			interrupts = <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/keystone-clocks.dtsi
index 2363593e1050..93f82c7010ab 100644
--- a/arch/arm/boot/dts/keystone-clocks.dtsi
+++ b/arch/arm/boot/dts/keystone-clocks.dtsi
@@ -13,51 +13,6 @@ clocks {
 	#size-cells = <1>;
 	ranges;
 
-	mainpllclk: mainpllclk@2310110 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,main-pll-clock";
-		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>;
-		reg-names = "control", "multiplier";
-		fixed-postdiv = <2>;
-	};
-
-	papllclk: papllclk@2620358 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkpass>;
-		clock-output-names = "pa-pll-clk";
-		reg = <0x02620358 4>;
-		reg-names = "control";
-	};
-
-	ddr3apllclk: ddr3apllclk@2620360 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkddr3a>;
-		clock-output-names = "ddr-3a-pll-clk";
-		reg = <0x02620360 4>;
-		reg-names = "control";
-	};
-
-	ddr3bpllclk: ddr3bpllclk@2620368 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkddr3b>;
-		clock-output-names = "ddr-3b-pll-clk";
-		reg = <0x02620368 4>;
-		reg-names = "control";
-	};
-
-	armpllclk: armpllclk@2620370 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkarm>;
-		clock-output-names = "arm-pll-clk";
-		reg = <0x02620370 4>;
-		reg-names = "control";
-	};
-
 	mainmuxclk: mainmuxclk@2310108 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,pll-mux-clock";
@@ -244,7 +199,7 @@ clocks {
 		clock-output-names = "debugss-trc";
 		reg = <0x02350014 0xb00>, <0x02350000 0x400>;
 		reg-names = "control", "domain";
-		domain-id = <0>;
+		domain-id = <1>;
 	};
 
 	clktetbtrc: clktetbtrc {
@@ -297,26 +252,6 @@ clocks {
 		domain-id = <3>;
 	};
 
-	clksrio: clksrio {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1rstiso13>;
-		clock-output-names = "srio";
-		reg = <0x0235002c 0xb00>, <0x02350010 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <4>;
-	};
-
-	clkhyperlink0: clkhyperlink0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "hyperlink-0";
-		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <5>;
-	};
-
 	clksr: clksr {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
@@ -327,16 +262,6 @@ clocks {
 		domain-id = <6>;
 	};
 
-	clkmsmcsram: clkmsmcsram {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "msmcsram";
-		reg = <0x02350038 0xb00>, <0x0235001c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <7>;
-	};
-
 	clkgem0: clkgem0 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
@@ -347,76 +272,6 @@ clocks {
 		domain-id = <8>;
 	};
 
-	clkgem1: clkgem1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem1";
-		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <9>;
-	};
-
-	clkgem2: clkgem2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem2";
-		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <10>;
-	};
-
-	clkgem3: clkgem3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem3";
-		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <11>;
-	};
-
-	clkgem4: clkgem4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem4";
-		reg = <0x0235004c 0xb00>, <0x02350030 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <12>;
-	};
-
-	clkgem5: clkgem5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem5";
-		reg = <0x02350050 0xb00>, <0x02350034 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <13>;
-	};
-
-	clkgem6: clkgem6 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem6";
-		reg = <0x02350054 0xb00>, <0x02350038 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <14>;
-	};
-
-	clkgem7: clkgem7 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem7";
-		reg = <0x02350058 0xb00>, <0x0235003c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <15>;
-	};
-
 	clkddr30: clkddr30 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
@@ -427,276 +282,6 @@ clocks {
 		domain-id = <16>;
 	};
 
-	clkddr31: clkddr31 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "ddr3-1";
-		reg = <0x02350060 0xb00>, <0x02350040 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <16>;
-	};
-
-	clktac: clktac {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tac";
-		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkrac01: clktac01 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "rac-01";
-		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkrac23: clktac23 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "rac-23";
-		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <18>;
-	};
-
-	clkfftc0: clkfftc0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-0";
-		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <19>;
-	};
-
-	clkfftc1: clkfftc1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-1";
-		reg = <0x02350074 0xb00>, <0x023504c0 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <19>;
-	};
-
-	clkfftc2: clkfftc2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-2";
-		reg = <0x02350078 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc3: clkfftc3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-3";
-		reg = <0x0235007c 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc4: clkfftc4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-4";
-		reg = <0x02350080 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc5: clkfftc5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-5";
-		reg = <0x02350084 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkaif: clkaif {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "aif";
-		reg = <0x02350088 0xb00>, <0x02350054 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <21>;
-	};
-
-	clktcp3d0: clktcp3d0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-0";
-		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <22>;
-	};
-
-	clktcp3d1: clktcp3d1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-1";
-		reg = <0x02350090 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <22>;
-	};
-
-	clktcp3d2: clktcp3d2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-2";
-		reg = <0x02350094 0xb00>, <0x0235005c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <23>;
-	};
-
-	clktcp3d3: clktcp3d3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-3";
-		reg = <0x02350098 0xb00>, <0x0235005c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <23>;
-	};
-
-	clkvcp0: clkvcp0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-0";
-		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp1: clkvcp1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-1";
-		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp2: clkvcp2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-2";
-		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp3: clkvcp3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-3";
-		reg = <0x0235000a8 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp4: clkvcp4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-4";
-		reg = <0x023500ac 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp5: clkvcp5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-5";
-		reg = <0x023500b0 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp6: clkvcp6 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-6";
-		reg = <0x023500b4 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp7: clkvcp7 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-7";
-		reg = <0x023500b8 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkbcp: clkbcp {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "bcp";
-		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <26>;
-	};
-
-	clkdxb: clkdxb {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "dxb";
-		reg = <0x023500c0 0xb00>, <0x0235006c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <27>;
-	};
-
-	clkhyperlink1: clkhyperlink1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "hyperlink-1";
-		reg = <0x023500c4 0xb00>, <0x02350070 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <28>;
-	};
-
-	clkxge: clkxge {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "xge";
-		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <29>;
-	};
-
 	clkwdtimer0: clkwdtimer0 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
@@ -737,6 +322,16 @@ clocks {
 		domain-id = <0>;
 	};
 
+	clktimer15: clktimer15 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer15";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
 	clkuart0: clkuart0 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index b4202907a27b..1992351e09fa 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -7,6 +7,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
 
 #include "skeleton.dtsi"
 
@@ -24,37 +25,6 @@
 		reg = <0x00000000 0x80000000 0x00000000 0x40000000>;
 	};
 
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		interrupt-parent = <&gic>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <0>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <1>;
-		};
-
-		cpu@2 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <2>;
-		};
-
-		cpu@3 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <3>;
-		};
-	};
-
 	gic: interrupt-controller {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
@@ -208,5 +178,62 @@
 				usb-phy = <&usb_phy>, <&usb_phy>;
 			};
 		};
+
+		wdt: wdt@022f0080 {
+			compatible = "ti,keystone-wdt","ti,davinci-wdt";
+			reg = <0x022f0080 0x80>;
+			clocks = <&clkwdtimer0>;
+		};
+
+		clock_event: timer@22f0000 {
+			compatible = "ti,keystone-timer";
+			reg = <0x022f0000 0x80>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clktimer15>;
+		};
+
+		gpio0: gpio@260bf00 {
+			compatible = "ti,keystone-gpio";
+			reg = <0x0260bf00 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			/* HW Interrupts mapped to GPIO pins */
+			interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 121 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 122 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 123 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 124 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 125 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 126 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 127 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 128 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 129 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 130 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 131 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 132 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 133 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 134 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 135 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 136 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 137 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 138 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 139 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 140 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 141 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 142 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 143 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 144 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 145 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 146 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 147 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 148 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 149 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 150 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkgpio>;
+			clock-names = "gpio";
+			ti,ngpio = <32>;
+			ti,davinci-gpio-unbanked = <32>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/kirkwood-b3.dts
new file mode 100644
index 000000000000..40791053106b
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-b3.dts
@@ -0,0 +1,204 @@
+/*
+ * Device Tree file for Excito Bubba B3
+ *
+ * Copyright (C) 2013, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute 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: This requires a new'ish version of u-boot, which disables the
+ * L2 cache. If your B3 silently fails to boot, u-boot is probably too
+ * old. Either upgrade, or consider the following email:
+ *
+ * http://lists.debian.org/debian-arm/2012/08/msg00128.html
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	model = "Excito B3";
+	compatible = "excito,b3", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+	memory { /* 512 MB */
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			/* Wifi model has Atheros chipset on pcie port */
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pmx_button_power: pmx-button-power {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+			pmx_led_green: pmx-led-green {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+			pmx_led_red: pmx-led-red {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_led_blue: pmx-led-blue {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_beeper: pmx-beeper {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+		};
+
+		spi@10600 {
+			status = "okay";
+			pinctrl-0 = <&pmx_spi>;
+			pinctrl-names = "default";
+
+			m25p16@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "m25p16";
+				reg = <0>;
+				spi-max-frequency = <40000000>;
+				mode = <0>;
+
+				partition@0 {
+					reg = <0x0 0xc0000>;
+					label = "u-boot";
+				};
+
+				partition@c0000 {
+					reg = <0xc0000 0x20000>;
+					label = "u-boot env";
+				};
+
+				partition@e0000 {
+					reg = <0xe0000 0x120000>;
+					label = "data";
+				};
+			};
+		};
+
+		i2c@11000 {
+			status = "okay";
+			/*
+			 * There is something on the bus at address 0x64.
+			 * Not yet identified what it is, maybe the eeprom
+			 * for the Atheros WiFi chip?
+			 */
+		};
+
+
+		serial@12000 {
+			/* Internal on test pins, 3.3v TTL
+		 	 * UART0_RX = Testpoint 65
+			 * UART0_TX = Testpoint 66
+			 * See the Excito Wiki for more details.
+		 	 */
+			pinctrl-0 = <&pmx_uart0>;
+			pinctrl-names = "default";
+			status = "okay";
+		};
+
+		sata@80000 {
+			/* One internal, the second as eSATA */
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio-leds {
+		/*
+		 * There is one LED "port" on the front and the colours
+		 * mix together giving some interesting combinations.
+		 */
+		compatible = "gpio-leds";
+		pinctrl-0 = < &pmx_led_green &pmx_led_red
+			      &pmx_led_blue >;
+		pinctrl-names = "default";
+
+		programming_led {
+			label = "bubba3:green:programming";
+			gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		error_led {
+			label = "bubba3:red:error";
+			gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+		};
+
+		active_led {
+			label = "bubba3:blue:active";
+			gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&pmx_button_power>;
+		pinctrl-names = "default";
+
+		power-button {
+			/* On the back */
+			label = "Power Button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	beeper: beeper {
+		/* 4KHz Piezoelectric buzzer */
+		compatible = "gpio-beeper";
+		pinctrl-0 = <&pmx_beeper>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@8 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+
+	ethphy1: ethernet-phy@24 {
+		device_type = "ethernet-phy";
+		reg = <24>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
+
diff --git a/arch/arm/boot/dts/kirkwood-ds109.dts b/arch/arm/boot/dts/kirkwood-ds109.dts
new file mode 100644
index 000000000000..772092c94ca3
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds109.dts
@@ -0,0 +1,41 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS109, DS110, DS110jv20";
+	compatible = "synology,ds109", "synology,ds110jv20",
+		     "synology,ds110", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-1 {
+		status = "okay";
+	};
+};
+
+&rs5c372 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds110jv10.dts b/arch/arm/boot/dts/kirkwood-ds110jv10.dts
new file mode 100644
index 000000000000..aabafbe0da4c
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds110jv10.dts
@@ -0,0 +1,41 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS110j v10 and v30";
+	compatible = "synology,ds110jv10", "synology,ds110jv30",
+		     "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-1 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds111.dts b/arch/arm/boot/dts/kirkwood-ds111.dts
new file mode 100644
index 000000000000..16ec7fbab573
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds111.dts
@@ -0,0 +1,44 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS111";
+	compatible = "synology,ds111", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-1 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds112.dts b/arch/arm/boot/dts/kirkwood-ds112.dts
new file mode 100644
index 000000000000..cff1b2388765
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds112.dts
@@ -0,0 +1,48 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS111";
+	compatible = "synology,ds111", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "okay";
+	};
+
+	gpio-leds-21-2 {
+		status = "okay";
+	};
+
+	regulators-hdd-30 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds209.dts b/arch/arm/boot/dts/kirkwood-ds209.dts
new file mode 100644
index 000000000000..330411993d38
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds209.dts
@@ -0,0 +1,44 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS209";
+	compatible = "synology,ds209", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-2 {
+		status = "okay";
+	};
+
+	regulators-hdd-31 {
+		status = "okay";
+	};
+};
+
+&rs5c372 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds210.dts b/arch/arm/boot/dts/kirkwood-ds210.dts
new file mode 100644
index 000000000000..6052eaa37d4f
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds210.dts
@@ -0,0 +1,46 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS210 v10, v20, v30, DS211j";
+	compatible = "synology,ds210jv10", "synology,ds210jv20",
+		     "synology,ds210jv30", "synology,ds211j",
+		     "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-2 {
+		status = "okay";
+	};
+
+	regulators-hdd-31 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds212.dts b/arch/arm/boot/dts/kirkwood-ds212.dts
new file mode 100644
index 000000000000..7f76cd30e84e
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds212.dts
@@ -0,0 +1,47 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS212, DS212p v10, v20, DS213air v10, DS213 v10";
+	compatible = "synology,ds212", "synology,ds212pv10",
+		     "synology,ds212pv10", "synology,ds212pv20",
+		     "synology,ds213airv10", "synology,ds213v10",
+		     "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-2 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds212j.dts b/arch/arm/boot/dts/kirkwood-ds212j.dts
new file mode 100644
index 000000000000..1f83a00f1f74
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds212j.dts
@@ -0,0 +1,41 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS212j v10, v20";
+	compatible = "synology,ds212jv10", "synology,ds212jv20",
+		     "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-21-2 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds409.dts b/arch/arm/boot/dts/kirkwood-ds409.dts
new file mode 100644
index 000000000000..0a573add44a2
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds409.dts
@@ -0,0 +1,48 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS409, DS410j";
+	compatible = "synology,ds409", "synology,ds410j", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-15-18 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+
+	gpio-leds-alarm-12 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&rs5c372 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds409slim.dts b/arch/arm/boot/dts/kirkwood-ds409slim.dts
new file mode 100644
index 000000000000..1848a6245fd3
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds409slim.dts
@@ -0,0 +1,40 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology 409slim";
+	compatible = "synology,ds409slim", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-32-35 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-20 {
+		status = "okay";
+	};
+};
+
+&rs5c372 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds411.dts b/arch/arm/boot/dts/kirkwood-ds411.dts
new file mode 100644
index 000000000000..a1737b4311c6
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds411.dts
@@ -0,0 +1,52 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS411, DS413jv10";
+	compatible = "synology,ds411", "synology,ds413jv10", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+
+	regulators-hdd-34 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds411j.dts b/arch/arm/boot/dts/kirkwood-ds411j.dts
new file mode 100644
index 000000000000..0cde914eceae
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds411j.dts
@@ -0,0 +1,48 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS411j";
+	compatible = "synology,ds411j", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-15-18 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+
+	gpio-leds-alarm-12 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&s35390a {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-ds411slim.dts b/arch/arm/boot/dts/kirkwood-ds411slim.dts
new file mode 100644
index 000000000000..aef0cadc2c78
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ds411slim.dts
@@ -0,0 +1,48 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology DS411slim";
+	compatible = "synology,ds411slim", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
index dc86429756d7..2cb0dc529165 100644
--- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
+++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
@@ -122,4 +122,66 @@
 			gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
 		};
 	};
+
+	dsa@0 {
+		compatible = "marvell,dsa";
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		dsa,ethernet = <&eth0>;
+		dsa,mii-bus = <&ethphy0>;
+
+		switch@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0 0>;	/* MDIO address 0, switch 0 in tree */
+
+			port@0 {
+				reg = <0>;
+				label = "lan1";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan2";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan3";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "lan4";
+			};
+
+			port@4 {
+				reg = <4>;
+				label = "wan";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+			};
+		};
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@ff {
+		reg = <0xff>; 	/* No phy attached */
+		speed = <1000>;
+		duplex = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6192.dts b/arch/arm/boot/dts/kirkwood-rd88f6192.dts
new file mode 100644
index 000000000000..e9dd85049297
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rd88f6192.dts
@@ -0,0 +1,112 @@
+/*
+ * Marvell RD88F6192 Board descrition
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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 file contains the definitions that are common between the three
+ * variants of the Marvell Kirkwood Development Board.
+ */
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6192.dtsi"
+
+/ {
+	model = "Marvell RD88F6192 reference design";
+	compatible = "marvell,rd88f6192", "marvell,kirkwood-88f6192", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-0 = <&pmx_usb_power>;
+			pinctrl-names = "default";
+
+                        pmx_usb_power: pmx-usb-power {
+                                marvell,pins = "mpp10";
+                                marvell,function = "gpo";
+                        };
+		};
+
+		serial@12000 {
+			status = "okay";
+
+		};
+
+		spi@10600 {
+			status = "okay";
+			pinctrl-0 = <&pmx_spi>;
+			pinctrl-names = "default";
+
+			m25p128@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "st,m25p128";
+				reg = <0>;
+				spi-max-frequency = <20000000>;
+				mode = <0>;
+			};
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	regulators {
+                compatible = "simple-bus";
+                #address-cells = <1>;
+                #size-cells = <0>;
+                pinctrl-0 = <&pmx_usb_power>;
+                pinctrl-names = "default";
+
+                usb_power: regulator@0 {
+                        compatible = "regulator-fixed";
+                        reg = <0>;
+                        regulator-name = "USB VBUS";
+                        regulator-min-microvolt = <5000000>;
+                        regulator-max-microvolt = <5000000>;
+                        enable-active-high;
+                        regulator-always-on;
+                        regulator-boot-on;
+                        gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+                };
+	};
+};
+
+&mdio {
+        status = "okay";
+
+        ethphy0: ethernet-phy@8 {
+                reg = <8>;
+        };
+};
+
+&eth0 {
+        status = "okay";
+        ethernet0-port@0 {
+                phy-handle = <&ethphy0>;
+        };
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-a0.dts b/arch/arm/boot/dts/kirkwood-rd88f6281-a0.dts
new file mode 100644
index 000000000000..a803bbb70bc8
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rd88f6281-a0.dts
@@ -0,0 +1,26 @@
+/*
+ * Marvell RD88F6181 A0 Board descrition
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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 file contains the definitions for the board with the A0 variant of
+ * the SoC. The ethernet switch does not have a "wan" port.
+ */
+
+/dts-v1/;
+#include "kirkwood-rd88f6281.dtsi"
+
+/ {
+	model = "Marvell RD88f6281 Reference design, with A0 SoC";
+	compatible = "marvell,rd88f6281-a0", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	dsa@0 {
+		switch@0 {
+			reg = <10 0>;    /* MDIO address 10, switch 0 in tree */
+		};
+	};
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-a1.dts b/arch/arm/boot/dts/kirkwood-rd88f6281-a1.dts
new file mode 100644
index 000000000000..baeebbf1d8c7
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rd88f6281-a1.dts
@@ -0,0 +1,31 @@
+/*
+ * Marvell RD88F6181 A1 Board descrition
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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 file contains the definitions for the board with the A1 variant of
+ * the SoC. The ethernet switch has a "wan" port.
+ */
+
+/dts-v1/;
+
+#include "kirkwood-rd88f6281.dtsi"
+
+/ {
+	model = "Marvell RD88f6281 Reference design, with A1 SoC";
+	compatible = "marvell,rd88f6281-a1", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	dsa@0 {
+		switch@0 {
+			reg = <0 0>;    /* MDIO address 0, switch 0 in tree */
+			port@4 {
+				reg = <4>;
+				label = "wan";
+			};
+		};
+	};
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
new file mode 100644
index 000000000000..d6368c39102e
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
@@ -0,0 +1,152 @@
+/*
+ * Marvell RD88F6181 Common Board descrition
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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 file contains the definitions that are common between the two
+ * variants of the Marvell Kirkwood Development Board.
+ */
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-0 = <&pmx_sdio_cd>;
+			pinctrl-names = "default";
+
+			pmx_sdio_cd: pmx-sdio-cd {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+		};
+
+		serial@12000 {
+			status = "okay";
+
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+		mvsdio@90000 {
+			pinctrl-0 = <&pmx_sdio &pmx_sdio_cd>;
+			pinctrl-names = "default";
+			status = "okay";
+			cd-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+			/* No WP GPIO */
+		};
+	};
+
+	dsa@0 {
+		compatible = "marvell,dsa";
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		dsa,ethernet = <&eth0>;
+		dsa,mii-bus = <&ethphy1>;
+
+		switch@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				label = "lan1";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan2";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan3";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "lan4";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+			};
+		};
+       };
+};
+
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x200000>;
+	};
+
+	partition@300000 {
+		label = "data";
+		reg = <0x0300000 0x500000>;
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@ff {
+		reg = <0xff>; /* No PHY attached */
+		speed = <1000>;
+		duple = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-rs212.dts b/arch/arm/boot/dts/kirkwood-rs212.dts
new file mode 100644
index 000000000000..93ec3d00c6ab
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rs212.dts
@@ -0,0 +1,48 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology RS212";
+	compatible = "synology,rs212", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-3 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-38 {
+		status = "okay";
+	};
+
+	regulators-hdd-30-2 {
+		status = "okay";
+	};
+};
+
+&s35390a {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-rs409.dts b/arch/arm/boot/dts/kirkwood-rs409.dts
new file mode 100644
index 000000000000..311df4e5aa28
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rs409.dts
@@ -0,0 +1,44 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology RS409";
+	compatible = "synology,rs409", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-150-15-18 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&rs5c372 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-rs411.dts b/arch/arm/boot/dts/kirkwood-rs411.dts
new file mode 100644
index 000000000000..f90da850bb31
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-rs411.dts
@@ -0,0 +1,44 @@
+/*
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-synology.dtsi"
+
+/ {
+	model = "Synology RS411 RS812";
+	compatible = "synology,rs411", "synology,rs812", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gpio-fan-100-15-35-3 {
+		status = "okay";
+	};
+
+	gpio-leds-hdd-36 {
+		status = "okay";
+	};
+};
+
+&eth1 {
+	status = "okay";
+};
+
+&s35390a {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-synology.dtsi b/arch/arm/boot/dts/kirkwood-synology.dtsi
new file mode 100644
index 000000000000..4227c974729d
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-synology.dtsi
@@ -0,0 +1,871 @@
+/*
+ * Nodes for Marvell 628x Synology devices
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ * Ben Peddell <klightspeed@killerwolves.net>
+ *
+ * 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.
+ */
+
+/ {
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+
+			pcie2: pcie@2,0 {
+				status = "disabled";
+			};
+		};
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pmx_alarmled_12: pmx-alarmled-12 {
+				marvell,pins = "mpp12";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanctrl_15: pmx-fanctrl-15 {
+				marvell,pins = "mpp15";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanctrl_16: pmx-fanctrl-16 {
+				marvell,pins = "mpp16";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanctrl_17: pmx-fanctrl-17 {
+				marvell,pins = "mpp17";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanalarm_18: pmx-fanalarm-18 {
+				marvell,pins = "mpp18";
+				marvell,function = "gpo";
+			};
+
+			pmx_hddled_20: pmx-hddled-20 {
+				marvell,pins = "mpp20";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_21: pmx-hddled-21 {
+				marvell,pins = "mpp21";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_22: pmx-hddled-22 {
+				marvell,pins = "mpp22";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_23: pmx-hddled-23 {
+				marvell,pins = "mpp23";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_24: pmx-hddled-24 {
+				marvell,pins = "mpp24";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_25: pmx-hddled-25 {
+				marvell,pins = "mpp25";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_26: pmx-hddled-26 {
+				marvell,pins = "mpp26";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_27: pmx-hddled-27 {
+				marvell,pins = "mpp27";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_28: pmx-hddled-28 {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd1_pwr_29: pmx-hdd1-pwr-29 {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd1_pwr_30: pmx-hdd-pwr-30 {
+				marvell,pins = "mpp30";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd2_pwr_31: pmx-hdd2-pwr-31 {
+				marvell,pins = "mpp31";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanctrl_32: pmx-fanctrl-32 {
+				marvell,pins = "mpp32";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanctrl_33: pmx-fanctrl-33 {
+				marvell,pins = "mpp33";
+				marvell,function = "gpo";
+			};
+
+			pmx_fanctrl_34: pmx-fanctrl-34 {
+				marvell,pins = "mpp34";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd2_pwr_34: pmx-hdd2-pwr-34 {
+				marvell,pins = "mpp34";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanalarm_35: pmx-fanalarm-35 {
+				marvell,pins = "mpp35";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_36: pmx-hddled-36 {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_37: pmx-hddled-37 {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_38: pmx-hddled-38 {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_39: pmx-hddled-39 {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_40: pmx-hddled-40 {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_41: pmx-hddled-41 {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_42: pmx-hddled-42 {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_43: pmx-hddled-43 {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_44: pmx-hddled-44 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			pmx_hddled_45: pmx-hddled-45 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd3_pwr_44: pmx-hdd3-pwr-44 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			pmx_hdd4_pwr_45: pmx-hdd4-pwr-45 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanalarm_44: pmx-fanalarm-44 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			pmx_fanalarm_45: pmx-fanalarm-45 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+		};
+
+		rtc@10300 {
+			status = "disabled";
+		};
+
+		spi@10600 {
+			status = "okay";
+			pinctrl-0 = <&pmx_spi>;
+			pinctrl-names = "default";
+
+			m25p80@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "st,m25p80";
+				reg = <0>;
+				spi-max-frequency = <20000000>;
+				mode = <0>;
+
+				partition@00000000 {
+					reg = <0x00000000 0x00080000>;
+					label = "RedBoot";
+				};
+
+				partition@00080000 {
+					reg = <0x00080000 0x00200000>;
+					label = "zImage";
+				};
+
+				partition@00280000 {
+					reg = <0x00280000 0x00140000>;
+					label = "rd.gz";
+				};
+
+				partition@003c0000 {
+					reg = <0x003c0000 0x00010000>;
+					label = "vendor";
+				};
+
+				partition@003d0000 {
+					reg = <0x003d0000 0x00020000>;
+					label = "RedBoot config";
+				};
+
+				partition@003f0000 {
+					reg = <0x003f0000 0x00010000>;
+					label = "FIS directory";
+				};
+			};
+		};
+
+		i2c@11000 {
+			status = "okay";
+			clock-frequency = <400000>;
+			pinctrl-0 = <&pmx_twsi0>;
+			pinctrl-names = "default";
+
+			rs5c372: rs5c372@32 {
+				status = "disabled";
+				compatible = "ricoh,rs5c372";
+				reg = <0x32>;
+			};
+
+			s35390a: s35390a@30 {
+				status = "disabled";
+				compatible = "ssi,s35390a";
+				reg = <0x30>;
+			};
+		};
+
+		serial@12000 {
+			status = "okay";
+			pinctrl-0 = <&pmx_uart0>;
+			pinctrl-names = "default";
+		};
+
+		serial@12100 {
+			status = "okay";
+			pinctrl-0 = <&pmx_uart1>;
+			pinctrl-names = "default";
+		};
+
+		poweroff@12100 {
+			compatible = "synology,power-off";
+			reg = <0x12100 0x100>;
+			clocks = <&gate_clk 7>;
+		};
+
+		sata@80000 {
+			pinctrl-0 = <&pmx_sata0 &pmx_sata1>;
+			pinctrl-names = "default";
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio-fan-150-32-35 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_32 &pmx_fanctrl_33 &pmx_fanctrl_34
+		             &pmx_fanalarm_35>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 0 GPIO_ACTIVE_HIGH
+			 &gpio1 1 GPIO_ACTIVE_HIGH
+			 &gpio1 2 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2200 1
+				       2500 2
+				       3000 4
+				       3300 3
+				       3700 5
+				       3800 6
+				       4200 7 >;
+	};
+
+	gpio-fan-150-15-18 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_15 &pmx_fanctrl_16 &pmx_fanctrl_17
+		             &pmx_fanalarm_18>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 15 GPIO_ACTIVE_HIGH
+			 &gpio0 16 GPIO_ACTIVE_HIGH
+			 &gpio0 17 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2200 1
+				       2500 2
+				       3000 4
+				       3300 3
+				       3700 5
+				       3800 6
+				       4200 7 >;
+	};
+
+	gpio-fan-100-32-35 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_32 &pmx_fanctrl_33 &pmx_fanctrl_34
+		             &pmx_fanalarm_35>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 0 GPIO_ACTIVE_HIGH
+			 &gpio1 1 GPIO_ACTIVE_HIGH
+			 &gpio1 2 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2500 1
+				       3100 2
+				       3800 3
+				       4600 4
+				       4800 5
+				       4900 6
+				       5000 7 >;
+	};
+
+	gpio-fan-100-15-18 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_15 &pmx_fanctrl_16 &pmx_fanctrl_17
+		             &pmx_fanalarm_18>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 15 GPIO_ACTIVE_HIGH
+			 &gpio0 16 GPIO_ACTIVE_HIGH
+			 &gpio0 17 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2500 1
+				       3100 2
+				       3800 3
+				       4600 4
+				       4800 5
+				       4900 6
+				       5000 7 >;
+	};
+
+	gpio-fan-100-15-35-1 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_15 &pmx_fanctrl_16 &pmx_fanctrl_17
+		             &pmx_fanalarm_35>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 15 GPIO_ACTIVE_HIGH
+			 &gpio0 16 GPIO_ACTIVE_HIGH
+			 &gpio0 17 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2500 1
+				       3100 2
+				       3800 3
+				       4600 4
+				       4800 5
+				       4900 6
+				       5000 7 >;
+	};
+
+	gpio-fan-100-15-35-3 {
+		status = "disabled";
+		compatible = "gpio-fan";
+		pinctrl-0 = <&pmx_fanctrl_15 &pmx_fanctrl_16 &pmx_fanctrl_17
+		             &pmx_fanalarm_35 &pmx_fanalarm_44 &pmx_fanalarm_45>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 15 GPIO_ACTIVE_HIGH
+			 &gpio0 16 GPIO_ACTIVE_HIGH
+			 &gpio0 17 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH
+			       &gpio1 12 GPIO_ACTIVE_HIGH
+			       &gpio1 13 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <    0 0
+				       2500 1
+				       3100 2
+				       3800 3
+				       4600 4
+				       4800 5
+				       4900 6
+				       5000 7 >;
+	};
+
+	gpio-leds-alarm-12 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_alarmled_12>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:alarm";
+			gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds-hdd-20 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_hddled_20 &pmx_hddled_21 &pmx_hddled_22
+			     &pmx_hddled_23 &pmx_hddled_24 &pmx_hddled_25
+			     &pmx_hddled_26 &pmx_hddled_27>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:green:hdd1";
+			gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd1-amber {
+			label = "synology:amber:hdd1";
+			gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-green {
+			label = "synology:green:hdd2";
+			gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-amber {
+			label = "synology:amber:hdd2";
+			gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd3-green {
+			label = "synology:green:hdd3";
+			gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd3-amber {
+			label = "synology:amber:hdd3";
+			gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd4-green {
+			label = "synology:green:hdd4";
+			gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd4-amber {
+			label = "synology:amber:hdd4";
+			gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds-hdd-21-1 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_hddled_21 &pmx_hddled_23>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:green:hdd1";
+			gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd1-amber {
+			label = "synology:amber:hdd1";
+			gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds-hdd-21-2 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_hddled_21 &pmx_hddled_23 &pmx_hddled_20 &pmx_hddled_22>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:green:hdd1";
+			gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd1-amber {
+			label = "synology:amber:hdd1";
+			gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-green {
+			label = "synology:green:hdd2";
+			gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-amber {
+			label = "synology:amber:hdd2";
+			gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds-hdd-36 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_hddled_36 &pmx_hddled_37 &pmx_hddled_38
+			     &pmx_hddled_39 &pmx_hddled_40 &pmx_hddled_41
+			     &pmx_hddled_42 &pmx_hddled_43 &pmx_hddled_44
+			     &pmx_hddled_45>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:green:hdd1";
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd1-amber {
+			label = "synology:amber:hdd1";
+			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-green {
+			label = "synology:green:hdd2";
+			gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-amber {
+			label = "synology:amber:hdd2";
+			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd3-green {
+			label = "synology:green:hdd3";
+			gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd3-amber {
+			label = "synology:amber:hdd3";
+			gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd4-green {
+			label = "synology:green:hdd4";
+			gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd4-amber {
+			label = "synology:amber:hdd4";
+			gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd5-green {
+			label = "synology:green:hdd5";
+			gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd5-amber {
+			label = "synology:amber:hdd5";
+			gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds-hdd-38 {
+		status = "disabled";
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_hddled_38 &pmx_hddled_39 &pmx_hddled_36 &pmx_hddled_37>;
+		pinctrl-names = "default";
+
+		hdd1-green {
+			label = "synology:green:hdd1";
+			gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd1-amber {
+			label = "synology:amber:hdd1";
+			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-green {
+			label = "synology:green:hdd2";
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+		};
+
+		hdd2-amber {
+			label = "synology:amber:hdd2";
+			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	regulators-hdd-29 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd1_pwr_29 &pmx_hdd2_pwr_31>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd1power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "hdd2power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 31 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	regulators-hdd-30-1 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd1_pwr_30>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd1power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	regulators-hdd-30-2 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd1_pwr_30 &pmx_hdd2_pwr_34>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd1power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "hdd2power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	regulators-hdd-30-4 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd1_pwr_30 &pmx_hdd2_pwr_34
+			     &pmx_hdd3_pwr_44 &pmx_hdd4_pwr_45>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd1power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "hdd2power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "hdd3power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "hdd4power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	regulators-hdd-31 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd2_pwr_31>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd2power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio0 31 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	regulators-hdd-34 {
+		status = "disabled";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_hdd2_pwr_34 &pmx_hdd3_pwr_44
+			     &pmx_hdd4_pwr_45>;
+		pinctrl-names = "default";
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "hdd2power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "hdd3power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		};
+
+		regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "hdd4power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			startup-delay-us = <5000000>;
+			gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+		reg = <9>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "disabled";
+
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts
new file mode 100644
index 000000000000..7d1c7677a18f
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-t5325.dts
@@ -0,0 +1,208 @@
+/*
+ * Device Tree file for HP t5325 Thin Client"
+ *
+ * Copyright (C) 2014
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	model = "HP t5325 Thin Client";
+	compatible = "hp,t5325", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-0 = <&pmx_i2s &pmx_sysrst>;
+			pinctrl-names = "default";
+
+			pmx_button_power: pmx-button_power {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+			pmx_power_off: pmx-power-off {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+
+			pmx_led: pmx-led {
+				marvell,pins = "mpp21";
+				marvell,function = "gpio";
+			};
+
+			pmx_usb_sata_power_enable: pmx-usb-sata-power-enable {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			/*
+			 * Redefined from kirkwood-6281.dtsi, because
+			 * we don't use SPI CS on MPP0, but on MPP7.
+			 */
+			pmx_spi: pmx-spi {
+				marvell,pins = "mpp1", "mpp2", "mpp3", "mpp7";
+				marvell,function = "spi";
+			};
+
+			pmx_sysrst: pmx-sysrst {
+				marvell,pins = "mpp6";
+				marvell,function = "sysrst";
+			};
+
+			pmx_i2s: pmx-i2s {
+				marvell,pins = "mpp39", "mpp40", "mpp41", "mpp42",
+					       "mpp43";
+				marvell,function = "audio";
+			};
+		};
+
+		spi@10600 {
+			pinctrl-0 = <&pmx_spi>;
+			pinctrl-names = "default";
+			status = "okay";
+
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "st,m25p80";
+				spi-max-frequency = <86000000>;
+				reg = <0>;
+				mode = <0>;
+
+				partition@0 {
+					reg = <0x0 0x80000>;
+					label = "u-boot";
+				};
+
+				partition@1 {
+					reg = <0x80000 0x40000>;
+					label = "SSD firmware";
+				};
+
+				partition@2 {
+					reg = <0xc0000 0x10000>;
+					label = "u-boot env";
+				};
+
+				partition@3 {
+					reg = <0xd0000 0x10000>;
+					label = "permanent u-boot env";
+				};
+
+				partition@4 {
+					reg = <0xd0000 0x10000>;
+					label = "permanent u-boot env";
+				};
+			};
+		};
+
+		i2c@11000 {
+			status = "okay";
+
+			alc5621: alc5621@1a {
+				compatible = "realtek,alc5621";
+				reg = <0x1a>;
+			};
+		};
+
+		serial@12000 {
+			status = "okay";
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+
+		audio: audio-controller@a0000 {
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_usb_sata_power_enable>;
+		pinctrl-names = "default";
+
+		usb_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "USB-SATA Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_button_power>;
+		pinctrl-names = "default";
+
+		button@1 {
+			label = "Power Button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		pinctrl-0 = <&pmx_power_off>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+	};
+
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ts419-6281.dts b/arch/arm/boot/dts/kirkwood-ts419-6281.dts
new file mode 100644
index 000000000000..aa22aa862857
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ts419-6281.dts
@@ -0,0 +1,20 @@
+/*
+ * Device Tree file for QNAP TS41X with 6281 SoC
+ *
+ * Copyright (C) 2013, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute 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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-ts219.dtsi"
+#include "kirkwood-ts419.dtsi"
+
+&ethphy0 { reg = <8>; };
+&ethphy1 { reg = <0>; };
diff --git a/arch/arm/boot/dts/kirkwood-ts419-6282.dts b/arch/arm/boot/dts/kirkwood-ts419-6282.dts
new file mode 100644
index 000000000000..d7512d4cdced
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ts419-6282.dts
@@ -0,0 +1,32 @@
+/*
+ * Device Tree file for QNAP TS41X with 6282 SoC
+ *
+ * Copyright (C) 2013, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute 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 "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-ts219.dtsi"
+#include "kirkwood-ts419.dtsi"
+
+/ {
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@2,0 {
+				status = "okay";
+			};
+		};
+	};
+};
+
+&ethphy0 { reg = <0>; };
+&ethphy1 { reg = <1>; };
diff --git a/arch/arm/boot/dts/kirkwood-ts419.dtsi b/arch/arm/boot/dts/kirkwood-ts419.dtsi
new file mode 100644
index 000000000000..1a9c624c7a92
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ts419.dtsi
@@ -0,0 +1,75 @@
+/*
+ * Device Tree include file for QNAP TS41X
+ *
+ * Copyright (C) 2013, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute 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.
+ */
+
+/ {
+	model = "QNAP TS419 family";
+	compatible = "qnap,ts419", "marvell,kirkwood";
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-names = "default";
+
+			pmx_USB_copy_button: pmx-USB-copy-button {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_reset_button: pmx-reset-button {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+			/*
+			 * JP1 indicates if an LCD module is installed
+			 * on the serial port (0), or if the port is used
+			 * as a console (1).
+			 */
+			pmx_jumper_jp1: pmx-jumper_jp1 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
+		pinctrl-names = "default";
+
+		button@1 {
+			label = "USB Copy";
+			linux,code = <KEY_COPY>;
+			gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+		};
+		button@2 {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy1: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+                /* overwrite reg property in board file */
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 6abf44d257df..90384587c278 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -24,6 +24,7 @@
 	aliases {
 	       gpio0 = &gpio0;
 	       gpio1 = &gpio1;
+	       i2c0 = &i2c0;
 	};
 
 	mbus {
@@ -111,7 +112,7 @@
 			clocks = <&gate_clk 7>;
 		};
 
-		i2c@11000 {
+		i2c0: i2c@11000 {
 			compatible = "marvell,mv64xxx-i2c";
 			reg = <0x11000 0x20>;
 			#address-cells = <1>;
@@ -145,6 +146,11 @@
 			reg = <0x20000 0x80>, <0x1500 0x20>;
 		};
 
+		system-controller@20000 {
+			compatible = "marvell,orion-system-controller";
+			reg = <0x20000 0x120>;
+		};
+
 		bridge_intc: bridge-interrupt-ctrl@20110 {
 			compatible = "marvell,orion-bridge-intc";
 			interrupt-controller;
@@ -161,6 +167,11 @@
 			#clock-cells = <1>;
 		};
 
+		l2: l2-cache@20128 {
+			compatible = "marvell,kirkwood-cache";
+			reg = <0x20128 0x4>;
+		};
+
 		intc: main-interrupt-ctrl@20200 {
 			compatible = "marvell,orion-intc";
 			interrupt-controller;
@@ -178,7 +189,7 @@
 
 		wdt: watchdog-timer@20300 {
 			compatible = "marvell,orion-wdt";
-			reg = <0x20300 0x28>;
+			reg = <0x20300 0x28>, <0x20108 0x4>;
 			interrupt-parent = <&bridge_intc>;
 			interrupts = <3>;
 			clocks = <&gate_clk 7>;
@@ -300,5 +311,14 @@
 			#phy-cells = <0>;
 			status = "ok";
 		};
+
+		audio0: audio-controller@a0000 {
+			compatible = "marvell,kirkwood-audio";
+			reg = <0xa0000 0x2210>;
+			interrupts = <24>;
+			clocks = <&gate_clk 9>;
+			clock-names = "internal";
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi
index 0e219932d7cc..8582ae41a583 100644
--- a/arch/arm/boot/dts/prima2.dtsi
+++ b/arch/arm/boot/dts/prima2.dtsi
@@ -223,8 +223,8 @@
 				interrupts = <17>;
 				fifosize = <128>;
 				clocks = <&clks 13>;
-				sirf,uart-dma-rx-channel = <21>;
-				sirf,uart-dma-tx-channel = <2>;
+				dmas = <&dmac1 5>, <&dmac0 2>;
+				dma-names = "rx", "tx";
 			};
 
 			uart1: uart@b0060000 {
@@ -243,8 +243,8 @@
 				interrupts = <19>;
 				fifosize = <128>;
 				clocks = <&clks 15>;
-				sirf,uart-dma-rx-channel = <6>;
-				sirf,uart-dma-tx-channel = <7>;
+				dmas = <&dmac0 6>, <&dmac0 7>;
+				dma-names = "rx", "tx";
 			};
 
 			usp0: usp@b0080000 {
@@ -254,8 +254,8 @@
 				interrupts = <20>;
 				fifosize = <128>;
 				clocks = <&clks 28>;
-				sirf,usp-dma-rx-channel = <17>;
-				sirf,usp-dma-tx-channel = <18>;
+				dmas = <&dmac1 1>, <&dmac1 2>;
+				dma-names = "rx", "tx";
 			};
 
 			usp1: usp@b0090000 {
@@ -265,8 +265,8 @@
 				interrupts = <21>;
 				fifosize = <128>;
 				clocks = <&clks 29>;
-				sirf,usp-dma-rx-channel = <14>;
-				sirf,usp-dma-tx-channel = <15>;
+				dmas = <&dmac0 14>, <&dmac0 15>;
+				dma-names = "rx", "tx";
 			};
 
 			usp2: usp@b00a0000 {
@@ -276,8 +276,8 @@
 				interrupts = <22>;
 				fifosize = <128>;
 				clocks = <&clks 30>;
-				sirf,usp-dma-rx-channel = <10>;
-				sirf,usp-dma-tx-channel = <11>;
+				dmas = <&dmac0 10>, <&dmac0 11>;
+				dma-names = "rx", "tx";
 			};
 
 			dmac0: dma-controller@b00b0000 {
diff --git a/arch/arm/boot/dts/qcom-msm8660-surf.dts b/arch/arm/boot/dts/qcom-msm8660-surf.dts
index 68a72f5507b9..169bad90dac9 100644
--- a/arch/arm/boot/dts/qcom-msm8660-surf.dts
+++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts
@@ -1,63 +1,6 @@
-/dts-v1/;
-
-/include/ "skeleton.dtsi"
-
-#include <dt-bindings/clock/qcom,gcc-msm8660.h>
+#include "qcom-msm8660.dtsi"
 
 / {
 	model = "Qualcomm MSM8660 SURF";
 	compatible = "qcom,msm8660-surf", "qcom,msm8660";
-	interrupt-parent = <&intc>;
-
-	intc: interrupt-controller@2080000 {
-		compatible = "qcom,msm-8660-qgic";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		reg = < 0x02080000 0x1000 >,
-		      < 0x02081000 0x1000 >;
-	};
-
-	timer@2000000 {
-		compatible = "qcom,scss-timer", "qcom,msm-timer";
-		interrupts = <1 0 0x301>,
-			     <1 1 0x301>,
-			     <1 2 0x301>;
-		reg = <0x02000000 0x100>;
-		clock-frequency = <27000000>,
-				  <32768>;
-		cpu-offset = <0x40000>;
-	};
-
-	msmgpio: gpio@800000 {
-		compatible = "qcom,msm-gpio";
-		reg = <0x00800000 0x4000>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpio = <173>;
-		interrupts = <0 16 0x4>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gcc: clock-controller@900000 {
-		compatible = "qcom,gcc-msm8660";
-		#clock-cells = <1>;
-		#reset-cells = <1>;
-		reg = <0x900000 0x4000>;
-	};
-
-	serial@19c40000 {
-		compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
-		reg = <0x19c40000 0x1000>,
-		      <0x19c00000 0x1000>;
-		interrupts = <0 195 0x0>;
-		clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>;
-		clock-names = "core", "iface";
-	};
-
-	qcom,ssbi@500000 {
-		compatible = "qcom,ssbi";
-		reg = <0x500000 0x1000>;
-		qcom,controller-type = "pmic-arbiter";
-	};
 };
diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi
new file mode 100644
index 000000000000..c52a9e964a44
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi
@@ -0,0 +1,87 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+#include <dt-bindings/clock/qcom,gcc-msm8660.h>
+
+/ {
+	model = "Qualcomm MSM8660";
+	compatible = "qcom,msm8660";
+	interrupt-parent = <&intc>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "qcom,scorpion";
+		enable-method = "qcom,gcc-msm8660";
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		L2: l2-cache {
+			compatible = "cache";
+			cache-level = <2>;
+		};
+	};
+
+	intc: interrupt-controller@2080000 {
+		compatible = "qcom,msm-8660-qgic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = < 0x02080000 0x1000 >,
+		      < 0x02081000 0x1000 >;
+	};
+
+	timer@2000000 {
+		compatible = "qcom,scss-timer", "qcom,msm-timer";
+		interrupts = <1 0 0x301>,
+			     <1 1 0x301>,
+			     <1 2 0x301>;
+		reg = <0x02000000 0x100>;
+		clock-frequency = <27000000>,
+				  <32768>;
+		cpu-offset = <0x40000>;
+	};
+
+	msmgpio: gpio@800000 {
+		compatible = "qcom,msm-gpio";
+		reg = <0x00800000 0x4000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpio = <173>;
+		interrupts = <0 16 0x4>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gcc: clock-controller@900000 {
+		compatible = "qcom,gcc-msm8660";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		reg = <0x900000 0x4000>;
+	};
+
+	serial@19c40000 {
+		compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <0 195 0x0>;
+		clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>;
+		clock-names = "core", "iface";
+	};
+
+	qcom,ssbi@500000 {
+		compatible = "qcom,ssbi";
+		reg = <0x500000 0x1000>;
+		qcom,controller-type = "pmic-arbiter";
+	};
+};
diff --git a/arch/arm/boot/dts/qcom-msm8960-cdp.dts b/arch/arm/boot/dts/qcom-msm8960-cdp.dts
index 7c30de4fa302..a58fb88315f6 100644
--- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts
+++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts
@@ -1,70 +1,6 @@
-/dts-v1/;
-
-/include/ "skeleton.dtsi"
-
-#include <dt-bindings/clock/qcom,gcc-msm8960.h>
+#include "qcom-msm8960.dtsi"
 
 / {
 	model = "Qualcomm MSM8960 CDP";
 	compatible = "qcom,msm8960-cdp", "qcom,msm8960";
-	interrupt-parent = <&intc>;
-
-	intc: interrupt-controller@2000000 {
-		compatible = "qcom,msm-qgic2";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		reg = < 0x02000000 0x1000 >,
-		      < 0x02002000 0x1000 >;
-	};
-
-	timer@200a000 {
-		compatible = "qcom,kpss-timer", "qcom,msm-timer";
-		interrupts = <1 1 0x301>,
-			     <1 2 0x301>,
-			     <1 3 0x301>;
-		reg = <0x0200a000 0x100>;
-		clock-frequency = <27000000>,
-				  <32768>;
-		cpu-offset = <0x80000>;
-	};
-
-	msmgpio: gpio@800000 {
-		compatible = "qcom,msm-gpio";
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpio = <150>;
-		interrupts = <0 16 0x4>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		reg = <0x800000 0x4000>;
-	};
-
-	gcc: clock-controller@900000 {
-		compatible = "qcom,gcc-msm8960";
-		#clock-cells = <1>;
-		#reset-cells = <1>;
-		reg = <0x900000 0x4000>;
-	};
-
-	clock-controller@4000000 {
-		compatible = "qcom,mmcc-msm8960";
-		reg = <0x4000000 0x1000>;
-		#clock-cells = <1>;
-		#reset-cells = <1>;
-	};
-
-	serial@16440000 {
-		compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
-		reg = <0x16440000 0x1000>,
-		      <0x16400000 0x1000>;
-		interrupts = <0 154 0x0>;
-		clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
-		clock-names = "core", "iface";
-	};
-
-	qcom,ssbi@500000 {
-		compatible = "qcom,ssbi";
-		reg = <0x500000 0x1000>;
-		qcom,controller-type = "pmic-arbiter";
-	};
 };
diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom-msm8960.dtsi
new file mode 100644
index 000000000000..997b7b94e117
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi
@@ -0,0 +1,135 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+#include <dt-bindings/clock/qcom,gcc-msm8960.h>
+
+/ {
+	model = "Qualcomm MSM8960";
+	compatible = "qcom,msm8960";
+	interrupt-parent = <&intc>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <1 14 0x304>;
+		compatible = "qcom,krait";
+		enable-method = "qcom,kpss-acc-v1";
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc0>;
+			qcom,saw = <&saw0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc1>;
+			qcom,saw = <&saw1>;
+		};
+
+		L2: l2-cache {
+			compatible = "cache";
+			cache-level = <2>;
+			interrupts = <0 2 0x4>;
+		};
+	};
+
+	cpu-pmu {
+		compatible = "qcom,krait-pmu";
+		interrupts = <1 10 0x304>;
+		qcom,no-pc-write;
+	};
+
+	intc: interrupt-controller@2000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = < 0x02000000 0x1000 >,
+		      < 0x02002000 0x1000 >;
+	};
+
+	timer@200a000 {
+		compatible = "qcom,kpss-timer", "qcom,msm-timer";
+		interrupts = <1 1 0x301>,
+			     <1 2 0x301>,
+			     <1 3 0x301>;
+		reg = <0x0200a000 0x100>;
+		clock-frequency = <27000000>,
+				  <32768>;
+		cpu-offset = <0x80000>;
+	};
+
+	msmgpio: gpio@800000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpio = <150>;
+		interrupts = <0 16 0x4>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0x800000 0x4000>;
+	};
+
+	gcc: clock-controller@900000 {
+		compatible = "qcom,gcc-msm8960";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		reg = <0x900000 0x4000>;
+	};
+
+	clock-controller@4000000 {
+		compatible = "qcom,mmcc-msm8960";
+		reg = <0x4000000 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	acc0: clock-controller@2088000 {
+		compatible = "qcom,kpss-acc-v1";
+		reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
+	};
+
+	acc1: clock-controller@2098000 {
+		compatible = "qcom,kpss-acc-v1";
+		reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
+	};
+
+	saw0: regulator@2089000 {
+		compatible = "qcom,saw2";
+		reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
+		regulator;
+	};
+
+	saw1: regulator@2099000 {
+		compatible = "qcom,saw2";
+		reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
+		regulator;
+	};
+
+	serial@16440000 {
+		compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+		reg = <0x16440000 0x1000>,
+		      <0x16400000 0x1000>;
+		interrupts = <0 154 0x0>;
+		clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
+		clock-names = "core", "iface";
+	};
+
+	qcom,ssbi@500000 {
+		compatible = "qcom,ssbi";
+		reg = <0x500000 0x1000>;
+		qcom,controller-type = "pmic-arbiter";
+	};
+
+	rng@1a500000 {
+		compatible = "qcom,prng";
+		reg = <0x1a500000 0x200>;
+		clocks = <&gcc PRNG_CLK>;
+		clock-names = "core";
+	};
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 9e5dadb101eb..f68723918b3f 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -9,6 +9,54 @@
 	compatible = "qcom,msm8974";
 	interrupt-parent = <&intc>;
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <1 9 0xf04>;
+		compatible = "qcom,krait";
+		enable-method = "qcom,kpss-acc-v2";
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc1>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc2>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2>;
+			qcom,acc = <&acc3>;
+		};
+
+		L2: l2-cache {
+			compatible = "cache";
+			cache-level = <2>;
+			interrupts = <0 2 0x4>;
+			qcom,saw = <&saw_l2>;
+		};
+	};
+
+	cpu-pmu {
+		compatible = "qcom,krait-pmu";
+		interrupts = <1 7 0xf04>;
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -91,6 +139,32 @@
 			};
 		};
 
+		saw_l2: regulator@f9012000 {
+			compatible = "qcom,saw2";
+			reg = <0xf9012000 0x1000>;
+			regulator;
+		};
+
+		acc0: clock-controller@f9088000 {
+			compatible = "qcom,kpss-acc-v2";
+			reg = <0xf9088000 0x1000>, <0xf9008000 0x1000>;
+		};
+
+		acc1: clock-controller@f9098000 {
+			compatible = "qcom,kpss-acc-v2";
+			reg = <0xf9098000 0x1000>, <0xf9008000 0x1000>;
+		};
+
+		acc2: clock-controller@f90a8000 {
+			compatible = "qcom,kpss-acc-v2";
+			reg = <0xf90a8000 0x1000>, <0xf9008000 0x1000>;
+		};
+
+		acc3: clock-controller@f90b8000 {
+			compatible = "qcom,kpss-acc-v2";
+			reg = <0xf90b8000 0x1000>, <0xf9008000 0x1000>;
+		};
+
 		restart@fc4ab000 {
 			compatible = "qcom,pshold";
 			reg = <0xfc4ab000 0x4>;
@@ -117,5 +191,12 @@
 			clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
 			clock-names = "core", "iface";
 		};
+
+		rng@f9bff000 {
+			compatible = "qcom,prng";
+			reg = <0xf9bff000 0x200>;
+			clocks = <&gcc GCC_PRNG_AHB_CLK>;
+			clock-names = "core";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/r7s72100-genmai-reference.dts b/arch/arm/boot/dts/r7s72100-genmai-reference.dts
index da19c70ed82b..e664611a47c8 100644
--- a/arch/arm/boot/dts/r7s72100-genmai-reference.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai-reference.dts
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r7s72100.dtsi"
+#include "r7s72100.dtsi"
 
 / {
 	model = "Genmai";
@@ -29,3 +29,14 @@
 		#size-cells = <1>;
 	};
 };
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	eeprom@50 {
+		compatible = "renesas,24c128";
+		reg = <0x50>;
+		pagesize = <64>;
+	};
+};
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 46b82aa7dc4e..ee700717a34b 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -8,12 +8,26 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
 	compatible = "renesas,r7s72100";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		spi4 = &spi4;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -33,4 +47,137 @@
 		reg = <0xe8201000 0x1000>,
 			<0xe8202000 0x1000>;
 	};
+
+	i2c0: i2c@fcfee000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+		reg = <0xfcfee000 0x44>;
+		interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 158 IRQ_TYPE_EDGE_RISING>,
+			     <0 159 IRQ_TYPE_EDGE_RISING>,
+			     <0 160 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 161 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 162 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 163 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 164 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <100000>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@fcfee400 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+		reg = <0xfcfee400 0x44>;
+		interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 166 IRQ_TYPE_EDGE_RISING>,
+			     <0 167 IRQ_TYPE_EDGE_RISING>,
+			     <0 168 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 169 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 170 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 171 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 172 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <100000>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@fcfee800 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+		reg = <0xfcfee800 0x44>;
+		interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 174 IRQ_TYPE_EDGE_RISING>,
+			     <0 175 IRQ_TYPE_EDGE_RISING>,
+			     <0 176 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 177 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 178 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 179 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 180 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <100000>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@fcfeec00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+		reg = <0xfcfeec00 0x44>;
+		interrupts = <0 181 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 182 IRQ_TYPE_EDGE_RISING>,
+			     <0 183 IRQ_TYPE_EDGE_RISING>,
+			     <0 184 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 185 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 186 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 187 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 188 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <100000>;
+		status = "disabled";
+	};
+
+	spi0: spi@e800c800 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800c800 0x24>;
+		interrupts = <0 238 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 239 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 240 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi@e800d000 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800d000 0x24>;
+		interrupts = <0 241 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 242 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 243 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi2: spi@e800d800 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800d800 0x24>;
+		interrupts = <0 244 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 245 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 246 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi3: spi@e800e000 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800e000 0x24>;
+		interrupts = <0 247 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 248 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 249 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi4: spi@e800e800 {
+		compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+		reg = <0xe800e800 0x24>;
+		interrupts = <0 250 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 251 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 252 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error", "rx", "tx";
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
index bb62c7a906f4..06cda19dac6a 100644
--- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -17,6 +17,7 @@
 /dts-v1/;
 #include "r8a7778.dtsi"
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "bockw";
@@ -84,7 +85,7 @@
 
 	sdhi0_pins: sd0 {
 		renesas,groups = "sdhi0_data4", "sdhi0_ctrl",
-				  "sdhi0_cd", "sdhi0_wp";
+				  "sdhi0_cd";
 		renesas,function = "sdhi0";
 	};
 
@@ -101,6 +102,7 @@
 	vmmc-supply = <&fixedregulator3v3>;
 	bus-width = <4>;
 	status = "okay";
+	wp-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>;
 };
 
 &hspi0 {
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index ddb3bd7a8838..85c5b3b99f5e 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -203,46 +203,6 @@
 		status = "disabled";
 	};
 
-	i2c0: i2c@ffc70000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "renesas,i2c-r8a7778";
-		reg = <0xffc70000 0x1000>;
-		interrupt-parent = <&gic>;
-		interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
-	i2c1: i2c@ffc71000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "renesas,i2c-r8a7778";
-		reg = <0xffc71000 0x1000>;
-		interrupt-parent = <&gic>;
-		interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
-	i2c2: i2c@ffc72000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "renesas,i2c-r8a7778";
-		reg = <0xffc72000 0x1000>;
-		interrupt-parent = <&gic>;
-		interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
-	i2c3: i2c@ffc73000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "renesas,i2c-r8a7778";
-		reg = <0xffc73000 0x1000>;
-		interrupt-parent = <&gic>;
-		interrupts = <0 77 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
 	hspi0: spi@fffc7000 {
 		compatible = "renesas,hspi";
 		reg = <0xfffc7000 0x18>;
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 57569cba1528..6e99eb2df076 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -1,7 +1,8 @@
 /*
  * Device Tree Source for the Lager board
  *
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded, 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
@@ -56,6 +57,54 @@
 		regulator-boot-on;
 		regulator-always-on;
 	};
+
+	vcc_sdhi0: regulator@1 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio5 24 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator@2 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi2: regulator@3 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI2 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio5 25 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi2: regulator@4 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI2 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio5 30 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
 };
 
 &extal_clk {
@@ -63,23 +112,68 @@
 };
 
 &pfc {
-	pinctrl-0 = <&scif0_pins &scif1_pins>;
+	pinctrl-0 = <&du_pins &scif0_pins &scif1_pins>;
 	pinctrl-names = "default";
 
+	du_pins: du {
+		renesas,groups = "du_rgb666", "du_sync_1", "du_clk_out_0";
+		renesas,function = "du";
+	};
+
 	scif0_pins: serial0 {
 		renesas,groups = "scif0_data";
 		renesas,function = "scif0";
 	};
 
+	ether_pins: ether {
+		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
+		renesas,function = "eth";
+	};
+
+	phy1_pins: phy1 {
+		renesas,groups = "intc_irq0";
+		renesas,function = "intc";
+	};
+
 	scif1_pins: serial1 {
 		renesas,groups = "scif1_data";
 		renesas,function = "scif1";
 	};
 
+	sdhi0_pins: sd0 {
+		renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+		renesas,function = "sdhi0";
+	};
+
+	sdhi2_pins: sd2 {
+		renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,function = "sdhi2";
+	};
+
 	mmc1_pins: mmc1 {
 		renesas,groups = "mmc1_data8", "mmc1_ctrl";
 		renesas,function = "mmc1";
 	};
+
+	qspi_pins: spi {
+		renesas,groups = "qspi_ctrl", "qspi_data4";
+		renesas,function = "qspi";
+	};
+};
+
+&ether {
+	pinctrl-0 = <&ether_pins &phy1_pins>;
+	pinctrl-names = "default";
+
+	phy-handle = <&phy1>;
+	renesas,ether-link-active-low;
+	status = "ok";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+		interrupt-parent = <&irqc0>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+	};
 };
 
 &mmcif1 {
@@ -91,3 +185,58 @@
 	non-removable;
 	status = "okay";
 };
+
+&sata1 {
+	status = "okay";
+};
+
+&spi {
+	pinctrl-0 = <&qspi_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,s25fl512s";
+		reg = <0>;
+		spi-max-frequency = <30000000>;
+		m25p,fast-read;
+
+		partition@0 {
+			label = "loader";
+			reg = <0x00000000 0x00040000>;
+			read-only;
+		};
+		partition@40000 {
+			label = "user";
+			reg = <0x00040000 0x00400000>;
+			read-only;
+		};
+		partition@440000 {
+			label = "flash";
+			reg = <0x00440000 0x03bc0000>;
+		};
+	};
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&sdhi2 {
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi2>;
+	vqmmc-supply = <&vccq_sdhi2>;
+	cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 71b1251f79c7..618e5b537eaf 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -1,7 +1,8 @@
 /*
  * Device Tree Source for the r8a7790 SoC
  *
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded 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
@@ -18,6 +19,13 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -94,7 +102,6 @@
 	gpio0: gpio@e6050000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6050000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -106,7 +113,6 @@
 	gpio1: gpio@e6051000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6051000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -118,7 +124,6 @@
 	gpio2: gpio@e6052000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6052000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -130,7 +135,6 @@
 	gpio3: gpio@e6053000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6053000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -142,7 +146,6 @@
 	gpio4: gpio@e6054000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6054000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -154,7 +157,6 @@
 	gpio5: gpio@e6055000 {
 		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
 		reg = <0 0xe6055000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -166,8 +168,8 @@
 	thermal@e61f0000 {
 		compatible = "renesas,thermal-r8a7790", "renesas,rcar-thermal";
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp5_clks R8A7790_CLK_THERMAL>;
 	};
 
 	timer {
@@ -183,7 +185,6 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		reg = <0 0xe61c0000 0 0x200>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 1 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 2 IRQ_TYPE_LEVEL_HIGH>,
@@ -195,7 +196,6 @@
 		#size-cells = <0>;
 		compatible = "renesas,i2c-r8a7790";
 		reg = <0 0xe6508000 0 0x40>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C0>;
 		status = "disabled";
@@ -206,7 +206,6 @@
 		#size-cells = <0>;
 		compatible = "renesas,i2c-r8a7790";
 		reg = <0 0xe6518000 0 0x40>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 288 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C1>;
 		status = "disabled";
@@ -217,7 +216,6 @@
 		#size-cells = <0>;
 		compatible = "renesas,i2c-r8a7790";
 		reg = <0 0xe6530000 0 0x40>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 286 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C2>;
 		status = "disabled";
@@ -228,7 +226,6 @@
 		#size-cells = <0>;
 		compatible = "renesas,i2c-r8a7790";
 		reg = <0 0xe6540000 0 0x40>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 290 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C3>;
 		status = "disabled";
@@ -237,7 +234,6 @@
 	mmcif0: mmcif@ee200000 {
 		compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
 		reg = <0 0xee200000 0 0x80>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
 		reg-io-width = <4>;
@@ -247,7 +243,6 @@
 	mmcif1: mmc@ee220000 {
 		compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
 		reg = <0 0xee220000 0 0x80>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>;
 		reg-io-width = <4>;
@@ -262,7 +257,6 @@
 	sdhi0: sd@ee100000 {
 		compatible = "renesas,sdhi-r8a7790";
 		reg = <0 0xee100000 0 0x200>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
 		cap-sd-highspeed;
@@ -272,7 +266,6 @@
 	sdhi1: sd@ee120000 {
 		compatible = "renesas,sdhi-r8a7790";
 		reg = <0 0xee120000 0 0x200>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
 		cap-sd-highspeed;
@@ -282,7 +275,6 @@
 	sdhi2: sd@ee140000 {
 		compatible = "renesas,sdhi-r8a7790";
 		reg = <0 0xee140000 0 0x100>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
 		cap-sd-highspeed;
@@ -292,13 +284,129 @@
 	sdhi3: sd@ee160000 {
 		compatible = "renesas,sdhi-r8a7790";
 		reg = <0 0xee160000 0 0x100>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
 		cap-sd-highspeed;
 		status = "disabled";
 	};
 
+	scifa0: serial@e6c40000 {
+		compatible = "renesas,scifa-r8a7790", "renesas,scifa";
+		reg = <0 0xe6c40000 0 64>;
+		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa1: serial@e6c50000 {
+		compatible = "renesas,scifa-r8a7790", "renesas,scifa";
+		reg = <0 0xe6c50000 0 64>;
+		interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFA1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa2: serial@e6c60000 {
+		compatible = "renesas,scifa-r8a7790", "renesas,scifa";
+		reg = <0 0xe6c60000 0 64>;
+		interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFA2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb0: serial@e6c20000 {
+		compatible = "renesas,scifb-r8a7790", "renesas,scifb";
+		reg = <0 0xe6c20000 0 64>;
+		interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFB0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb1: serial@e6c30000 {
+		compatible = "renesas,scifb-r8a7790", "renesas,scifb";
+		reg = <0 0xe6c30000 0 64>;
+		interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFB1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb2: serial@e6ce0000 {
+		compatible = "renesas,scifb-r8a7790", "renesas,scifb";
+		reg = <0 0xe6ce0000 0 64>;
+		interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_SCIFB2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif0: serial@e6e60000 {
+		compatible = "renesas,scif-r8a7790", "renesas,scif";
+		reg = <0 0xe6e60000 0 64>;
+		interrupts = <0 152 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7790_CLK_SCIF0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif1: serial@e6e68000 {
+		compatible = "renesas,scif-r8a7790", "renesas,scif";
+		reg = <0 0xe6e68000 0 64>;
+		interrupts = <0 153 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7790_CLK_SCIF1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	hscif0: serial@e62c0000 {
+		compatible = "renesas,hscif-r8a7790", "renesas,hscif";
+		reg = <0 0xe62c0000 0 96>;
+		interrupts = <0 154 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7790_CLK_HSCIF0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	hscif1: serial@e62c8000 {
+		compatible = "renesas,hscif-r8a7790", "renesas,hscif";
+		reg = <0 0xe62c8000 0 96>;
+		interrupts = <0 155 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7790_CLK_HSCIF1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	ether: ethernet@ee700000 {
+		compatible = "renesas,ether-r8a7790";
+		reg = <0 0xee700000 0 0x400>;
+		interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
+		phy-mode = "rmii";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	sata0: sata@ee300000 {
+		compatible = "renesas,sata-r8a7790";
+		reg = <0 0xee300000 0 0x2000>;
+		interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7790_CLK_SATA0>;
+		status = "disabled";
+	};
+
+	sata1: sata@ee500000 {
+		compatible = "renesas,sata-r8a7790";
+		reg = <0 0xee500000 0 0x2000>;
+		interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7790_CLK_SATA1>;
+		status = "disabled";
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -313,6 +421,29 @@
 			clock-output-names = "extal";
 		};
 
+		/*
+		 * The external audio clocks are configured as 0 Hz fixed frequency clocks by
+		 * default. Boards that provide audio clocks should override them.
+		 */
+		audio_clk_a: audio_clk_a {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_a";
+		};
+		audio_clk_b: audio_clk_b {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_b";
+		};
+		audio_clk_c: audio_clk_c {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_c";
+		};
+
 		/* Special CPG clocks */
 		cpg_clocks: cpg_clocks@e6150000 {
 			compatible = "renesas,r8a7790-cpg-clocks",
@@ -607,10 +738,16 @@
 		mstp8_clks: mstp8_clks@e6150990 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>;
-			clocks = <&p_clk>;
+			clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>,
+				 <&zs_clk>, <&zs_clk>;
 			#clock-cells = <1>;
-			renesas,clock-indices = <R8A7790_CLK_ETHER>;
-			clock-output-names = "ether";
+			renesas,clock-indices = <
+				R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 R8A7790_CLK_VIN1
+				R8A7790_CLK_VIN0 R8A7790_CLK_ETHER R8A7790_CLK_SATA1
+				R8A7790_CLK_SATA0
+			>;
+			clock-output-names =
+				"vin3", "vin2", "vin1", "vin0", "ether", "sata1", "sata0";
 		};
 		mstp9_clks: mstp9_clks@e6150994 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -627,4 +764,15 @@
 				"rcan1", "rcan0", "qspi_mod", "i2c3", "i2c2", "i2c1", "i2c0";
 		};
 	};
+
+	spi: spi@e6b10000 {
+		compatible = "renesas,qspi-r8a7790", "renesas,qspi";
+		reg = <0 0xe6b10000 0 0x2c>;
+		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7790_CLK_QSPI_MOD>;
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7791-koelsch-reference.dts b/arch/arm/boot/dts/r8a7791-koelsch-reference.dts
deleted file mode 100644
index 588ca17ea1f0..000000000000
--- a/arch/arm/boot/dts/r8a7791-koelsch-reference.dts
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Device Tree Source for the Koelsch board
- *
- * Copyright (C) 2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * 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 "r8a7791.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
-	model = "Koelsch";
-	compatible = "renesas,koelsch-reference", "renesas,r8a7791";
-
-	chosen {
-		bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
-	};
-
-	memory@40000000 {
-		device_type = "memory";
-		reg = <0 0x40000000 0 0x80000000>;
-	};
-
-	lbsc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		key-a {
-			gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
-			linux,code = <30>;
-			label = "SW30";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-b {
-			gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
-			linux,code = <48>;
-			label = "SW31";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-c {
-			gpios = <&gpio7 2 GPIO_ACTIVE_LOW>;
-			linux,code = <46>;
-			label = "SW32";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-d {
-			gpios = <&gpio7 3 GPIO_ACTIVE_LOW>;
-			linux,code = <32>;
-			label = "SW33";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-e {
-			gpios = <&gpio7 4 GPIO_ACTIVE_LOW>;
-			linux,code = <18>;
-			label = "SW34";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-f {
-			gpios = <&gpio7 5 GPIO_ACTIVE_LOW>;
-			linux,code = <33>;
-			label = "SW35";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-		key-g {
-			gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
-			linux,code = <34>;
-			label = "SW36";
-			gpio-key,wakeup;
-			debounce-interval = <20>;
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		led6 {
-			gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
-		};
-		led7 {
-			gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
-		};
-		led8 {
-			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
-		};
-	};
-};
-
-&pfc {
-	pinctrl-0 = <&scif0_pins &scif1_pins>;
-	pinctrl-names = "default";
-
-	scif0_pins: serial0 {
-		renesas,groups = "scif0_data_d";
-		renesas,function = "scif0";
-	};
-
-	scif1_pins: serial1 {
-		renesas,groups = "scif1_data_d";
-		renesas,function = "scif1";
-	};
-};
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index fd556c3483e3..bdd73e6657b2 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -2,7 +2,8 @@
  * Device Tree Source for the Koelsch board
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded, 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
@@ -23,7 +24,12 @@
 
 	memory@40000000 {
 		device_type = "memory";
-		reg = <0 0x40000000 0 0x80000000>;
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+
+	memory@200000000 {
+		device_type = "memory";
+		reg = <2 0x00000000 0 0x40000000>;
 	};
 
 	lbsc {
@@ -31,6 +37,60 @@
 		#size-cells = <1>;
 	};
 
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		key-a {
+			gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+			linux,code = <30>;
+			label = "SW30";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-b {
+			gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
+			linux,code = <48>;
+			label = "SW31";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-c {
+			gpios = <&gpio7 2 GPIO_ACTIVE_LOW>;
+			linux,code = <46>;
+			label = "SW32";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-d {
+			gpios = <&gpio7 3 GPIO_ACTIVE_LOW>;
+			linux,code = <32>;
+			label = "SW33";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-e {
+			gpios = <&gpio7 4 GPIO_ACTIVE_LOW>;
+			linux,code = <18>;
+			label = "SW34";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-f {
+			gpios = <&gpio7 5 GPIO_ACTIVE_LOW>;
+			linux,code = <33>;
+			label = "SW35";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-g {
+			gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
+			linux,code = <34>;
+			label = "SW36";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		led6 {
@@ -43,16 +103,112 @@
 			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
 		};
 	};
+
+	vcc_sdhi0: regulator@0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 17 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator@1 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi1: regulator@2 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI1 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi1: regulator@3 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI1 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi2: regulator@4 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI2 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 19 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi2: regulator@5 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI2 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
 };
 
 &extal_clk {
 	clock-frequency = <20000000>;
 };
 
+&i2c2 {
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	eeprom@50 {
+		compatible = "renesas,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+};
+
 &pfc {
-	pinctrl-0 = <&scif0_pins &scif1_pins>;
+	pinctrl-0 = <&du_pins &scif0_pins &scif1_pins>;
 	pinctrl-names = "default";
 
+	i2c2_pins: i2c {
+		renesas,groups = "i2c2";
+		renesas,function = "i2c2";
+	};
+
+	du_pins: du {
+		renesas,groups = "du_rgb666", "du_sync", "du_clk_out_0";
+		renesas,function = "du";
+	};
+
 	scif0_pins: serial0 {
 		renesas,groups = "scif0_data_d";
 		renesas,function = "scif0";
@@ -62,4 +218,116 @@
 		renesas,groups = "scif1_data_d";
 		renesas,function = "scif1";
 	};
+
+	ether_pins: ether {
+		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
+		renesas,function = "eth";
+	};
+
+	phy1_pins: phy1 {
+		renesas,groups = "intc_irq0";
+		renesas,function = "intc";
+	};
+
+	sdhi0_pins: sd0 {
+		renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+		renesas,function = "sdhi0";
+	};
+
+	sdhi1_pins: sd1 {
+		renesas,gpios = "sdhi1_data4", "sdhi1_ctrl";
+		renesas,function = "sdhi1";
+	};
+
+	sdhi2_pins: sd2 {
+		renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,function = "sdhi2";
+	};
+
+	qspi_pins: spi {
+		renesas,groups = "qspi_ctrl", "qspi_data4";
+		renesas,function = "qspi";
+	};
+};
+
+&ether {
+	pinctrl-0 = <&ether_pins &phy1_pins>;
+	pinctrl-names = "default";
+
+	phy-handle = <&phy1>;
+	renesas,ether-link-active-low;
+	status = "ok";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+		interrupt-parent = <&irqc0>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&sata0 {
+	status = "okay";
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&sdhi1 {
+	pinctrl-0 = <&sdhi1_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi1>;
+	vqmmc-supply = <&vccq_sdhi1>;
+	cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&sdhi2 {
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi2>;
+	vqmmc-supply = <&vccq_sdhi2>;
+	cd-gpios = <&gpio6 22 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&spi {
+	pinctrl-0 = <&qspi_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,s25fl512s";
+		reg = <0>;
+		spi-max-frequency = <30000000>;
+		m25p,fast-read;
+
+		partition@0 {
+			label = "loader";
+			reg = <0x00000000 0x00080000>;
+			read-only;
+		};
+		partition@80000 {
+			label = "bootenv";
+			reg = <0x00080000 0x00080000>;
+			read-only;
+		};
+		partition@100000 {
+			label = "data";
+			reg = <0x00100000 0x03f00000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 19c65509a22d..46181708e59c 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -2,7 +2,8 @@
  * Device Tree Source for the r8a7791 SoC
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded 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
@@ -19,6 +20,15 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -53,7 +63,6 @@
 	gpio0: gpio@e6050000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6050000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -65,7 +74,6 @@
 	gpio1: gpio@e6051000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6051000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -77,7 +85,6 @@
 	gpio2: gpio@e6052000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6052000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -89,7 +96,6 @@
 	gpio3: gpio@e6053000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6053000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -101,7 +107,6 @@
 	gpio4: gpio@e6054000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6054000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -113,7 +118,6 @@
 	gpio5: gpio@e6055000 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6055000 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -125,7 +129,6 @@
 	gpio6: gpio@e6055400 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6055400 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -137,7 +140,6 @@
 	gpio7: gpio@e6055800 {
 		compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
 		reg = <0 0xe6055800 0 0x50>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
 		#gpio-cells = <2>;
 		gpio-controller;
@@ -149,8 +151,8 @@
 	thermal@e61f0000 {
 		compatible = "renesas,thermal-r8a7791", "renesas,rcar-thermal";
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp5_clks R8A7791_CLK_THERMAL>;
 	};
 
 	timer {
@@ -166,7 +168,6 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		reg = <0 0xe61c0000 0 0x200>;
-		interrupt-parent = <&gic>;
 		interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 1 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 2 IRQ_TYPE_LEVEL_HIGH>,
@@ -179,12 +180,288 @@
 			     <0 17 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	i2c0: i2c@e6508000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6508000 0 0x40>;
+		interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@e6518000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6518000 0 0x40>;
+		interrupts = <0 288 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C1>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@e6530000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6530000 0 0x40>;
+		interrupts = <0 286 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C2>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@e6540000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6540000 0 0x40>;
+		interrupts = <0 290 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C3>;
+		status = "disabled";
+	};
+
+	i2c4: i2c@e6520000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6520000 0 0x40>;
+		interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C4>;
+		status = "disabled";
+	};
+
+	i2c5: i2c@e6528000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7791";
+		reg = <0 0xe6528000 0 0x40>;
+		interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_I2C5>;
+		status = "disabled";
+	};
+
 	pfc: pfc@e6060000 {
 		compatible = "renesas,pfc-r8a7791";
 		reg = <0 0xe6060000 0 0x250>;
 		#gpio-range-cells = <3>;
 	};
 
+	sdhi0: sd@ee100000 {
+		compatible = "renesas,sdhi-r8a7791";
+		reg = <0 0xee100000 0 0x200>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_SDHI0>;
+		status = "disabled";
+	};
+
+	sdhi1: sd@ee140000 {
+		compatible = "renesas,sdhi-r8a7791";
+		reg = <0 0xee140000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_SDHI1>;
+		status = "disabled";
+	};
+
+	sdhi2: sd@ee160000 {
+		compatible = "renesas,sdhi-r8a7791";
+		reg = <0 0xee160000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_SDHI2>;
+		status = "disabled";
+	};
+
+	scifa0: serial@e6c40000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c40000 0 64>;
+		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFA0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa1: serial@e6c50000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c50000 0 64>;
+		interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFA1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa2: serial@e6c60000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c60000 0 64>;
+		interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFA2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa3: serial@e6c70000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c70000 0 64>;
+		interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp11_clks R8A7791_CLK_SCIFA3>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa4: serial@e6c78000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c78000 0 64>;
+		interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp11_clks R8A7791_CLK_SCIFA4>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifa5: serial@e6c80000 {
+		compatible = "renesas,scifa-r8a7791", "renesas,scifa";
+		reg = <0 0xe6c80000 0 64>;
+		interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp11_clks R8A7791_CLK_SCIFA5>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb0: serial@e6c20000 {
+		compatible = "renesas,scifb-r8a7791", "renesas,scifb";
+		reg = <0 0xe6c20000 0 64>;
+		interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFB0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb1: serial@e6c30000 {
+		compatible = "renesas,scifb-r8a7791", "renesas,scifb";
+		reg = <0 0xe6c30000 0 64>;
+		interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFB1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scifb2: serial@e6ce0000 {
+		compatible = "renesas,scifb-r8a7791", "renesas,scifb";
+		reg = <0 0xe6ce0000 0 64>;
+		interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_SCIFB2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif0: serial@e6e60000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6e60000 0 64>;
+		interrupts = <0 152 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif1: serial@e6e68000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6e68000 0 64>;
+		interrupts = <0 153 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif2: serial@e6e58000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6e58000 0 64>;
+		interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif3: serial@e6ea8000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6ea8000 0 64>;
+		interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF3>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif4: serial@e6ee0000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6ee0000 0 64>;
+		interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF4>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif5: serial@e6ee8000 {
+		compatible = "renesas,scif-r8a7791", "renesas,scif";
+		reg = <0 0xe6ee8000 0 64>;
+		interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_SCIF5>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	hscif0: serial@e62c0000 {
+		compatible = "renesas,hscif-r8a7791", "renesas,hscif";
+		reg = <0 0xe62c0000 0 96>;
+		interrupts = <0 154 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_HSCIF0>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	hscif1: serial@e62c8000 {
+		compatible = "renesas,hscif-r8a7791", "renesas,hscif";
+		reg = <0 0xe62c8000 0 96>;
+		interrupts = <0 155 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_HSCIF1>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	hscif2: serial@e62d0000 {
+		compatible = "renesas,hscif-r8a7791", "renesas,hscif";
+		reg = <0 0xe62d0000 0 96>;
+		interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7791_CLK_HSCIF2>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	ether: ethernet@ee700000 {
+		compatible = "renesas,ether-r8a7791";
+		reg = <0 0xee700000 0 0x400>;
+		interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7791_CLK_ETHER>;
+		phy-mode = "rmii";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	sata0: sata@ee300000 {
+		compatible = "renesas,sata-r8a7791";
+		reg = <0 0xee300000 0 0x2000>;
+		interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7791_CLK_SATA0>;
+		status = "disabled";
+	};
+
+	sata1: sata@ee500000 {
+		compatible = "renesas,sata-r8a7791";
+		reg = <0 0xee500000 0 0x2000>;
+		interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7791_CLK_SATA1>;
+		status = "disabled";
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -429,7 +706,7 @@
 				R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2
 			>;
 			clock-output-names =
-				"scifa2", "scifa1", "scifa0", "misof2", "scifb0",
+				"scifa2", "scifa1", "scifa0", "msiof2", "scifb0",
 				"scifb1", "msiof1", "scifb2";
 		};
 		mstp3_clks: mstp3_clks@e615013c {
@@ -474,10 +751,15 @@
 		mstp8_clks: mstp8_clks@e6150990 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>;
-			clocks = <&p_clk>;
+			clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>,
+				 <&zs_clk>;
 			#clock-cells = <1>;
-			renesas,clock-indices = <R8A7791_CLK_ETHER>;
-			clock-output-names = "ether";
+			renesas,clock-indices = <
+				R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0
+				R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0
+			>;
+			clock-output-names =
+				"vin2", "vin1", "vin0", "ether", "sata1", "sata0";
 		};
 		mstp9_clks: mstp9_clks@e6150994 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -488,7 +770,7 @@
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD
-				R8A7791_CLK_I2C4 R8A7791_CLK_I2C4 R8A7791_CLK_I2C3
+				R8A7791_CLK_I2C5 R8A7791_CLK_I2C4 R8A7791_CLK_I2C3
 				R8A7791_CLK_I2C2 R8A7791_CLK_I2C1 R8A7791_CLK_I2C0
 			>;
 			clock-output-names =
@@ -506,4 +788,15 @@
 			clock-output-names = "scifa3", "scifa4", "scifa5";
 		};
 	};
+
+	spi: spi@e6b10000 {
+		compatible = "renesas,qspi-r8a7791", "renesas,qspi";
+		reg = <0 0xe6b10000 0 0x2c>;
+		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
+		num-cs = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/s3c2416-smdk2416.dts b/arch/arm/boot/dts/s3c2416-smdk2416.dts
index 59594cf15998..ea92fd69529a 100644
--- a/arch/arm/boot/dts/s3c2416-smdk2416.dts
+++ b/arch/arm/boot/dts/s3c2416-smdk2416.dts
@@ -19,6 +19,19 @@
 		reg =  <0x30000000 0x4000000>;
 	};
 
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		xti: xti {
+			compatible = "fixed-clock";
+			clock-frequency = <12000000>;
+			clock-output-names = "xti";
+			#clock-cells = <0>;
+		};
+	};
+
 	serial@50000000 {
 		status = "okay";
 		pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi
index e6555bdd81b8..955e4a4f8c31 100644
--- a/arch/arm/boot/dts/s3c2416.dtsi
+++ b/arch/arm/boot/dts/s3c2416.dtsi
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <dt-bindings/clock/s3c2443.h>
 #include "s3c24xx.dtsi"
 #include "s3c2416-pinctrl.dtsi"
 
@@ -28,26 +29,53 @@
 		compatible = "samsung,s3c2416-irq";
 	};
 
+	clocks: clock-controller@0x4c000000 {
+		compatible = "samsung,s3c2416-clock";
+		reg = <0x4c000000 0x40>;
+		#clock-cells = <1>;
+	};
+
 	pinctrl@56000000 {
 		compatible = "samsung,s3c2416-pinctrl";
 	};
 
+	timer@51000000 {
+		clocks = <&clocks PCLK_PWM>;
+		clock-names = "timers";
+	};
+
 	serial@50000000 {
 		compatible = "samsung,s3c2440-uart";
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+				<&clocks SCLK_UART>;
 	};
 
 	serial@50004000 {
 		compatible = "samsung,s3c2440-uart";
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+				<&clocks SCLK_UART>;
 	};
 
 	serial@50008000 {
 		compatible = "samsung,s3c2440-uart";
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>,
+				<&clocks SCLK_UART>;
 	};
 
 	serial@5000C000 {
 		compatible = "samsung,s3c2440-uart";
 		reg = <0x5000C000 0x4000>;
 		interrupts = <1 18 24 4>, <1 18 25 4>;
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>,
+				<&clocks SCLK_UART>;
 		status = "disabled";
 	};
 
@@ -55,6 +83,10 @@
 		compatible = "samsung,s3c6410-sdhci";
 		reg = <0x4AC00000 0x100>;
 		interrupts = <0 0 21 3>;
+		clock-names = "hsmmc", "mmc_busclk.0",
+				"mmc_busclk.2";
+		clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>,
+				<&clocks MUX_HSMMC0>;
 		status = "disabled";
 	};
 
@@ -62,18 +94,28 @@
 		compatible = "samsung,s3c6410-sdhci";
 		reg = <0x4A800000 0x100>;
 		interrupts = <0 0 20 3>;
+		clock-names = "hsmmc", "mmc_busclk.0",
+				"mmc_busclk.2";
+		clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>,
+				<&clocks MUX_HSMMC1>;
 		status = "disabled";
 	};
 
 	watchdog@53000000 {
 		interrupts = <1 9 27 3>;
+		clocks = <&clocks PCLK_WDT>;
+		clock-names = "watchdog";
 	};
 
 	rtc@57000000 {
 		compatible = "samsung,s3c2416-rtc";
+		clocks = <&clocks PCLK_RTC>;
+		clock-names = "rtc";
 	};
 
 	i2c@54000000 {
 		compatible = "samsung,s3c2440-i2c";
+		clocks = <&clocks PCLK_I2C0>;
+		clock-names = "i2c";
 	};
 };
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 537f1a5c07f5..0166f4795217 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -415,6 +415,7 @@
 						compatible = "altr,socfpga-gate-clk";
 						clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
 						clk-gate = <0xa0 8>;
+						clk-phase = <0 135>;
 					};
 
 					nand_x_clk: nand_x_clk {
@@ -473,6 +474,17 @@
 			arm,data-latency = <2 1 1>;
 		};
 
+		mmc: dwmmc0@ff704000 {
+			compatible = "altr,socfpga-dw-mshc";
+			reg = <0xff704000 0x1000>;
+			interrupts = <0 139 4>;
+			fifo-depth = <0x400>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&l4_mp_clk>, <&sdmmc_clk>;
+			clock-names = "biu", "ciu";
+		};
+
 		/* Local timer */
 		timer@fffec600 {
 			compatible = "arm,cortex-a9-twd-timer";
@@ -527,8 +539,8 @@
 		};
 
 		sysmgr@ffd08000 {
-				compatible = "altr,sys-mgr";
-				reg = <0xffd08000 0x4000>;
-			};
+			compatible = "altr,sys-mgr", "syscon";
+			reg = <0xffd08000 0x4000>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/socfpga_arria5.dtsi
index a85b4043f888..6c87b7070ca7 100644
--- a/arch/arm/boot/dts/socfpga_arria5.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria5.dtsi
@@ -27,6 +27,17 @@
 			};
 		};
 
+		dwmmc0@ff704000 {
+			num-slots = <1>;
+			supports-highspeed;
+			broken-cd;
+
+			slot@0 {
+				reg = <0>;
+				bus-width = <4>;
+			};
+		};
+
 		serial0@ffc02000 {
 			clock-frequency = <100000000>;
 		};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
index a8716f6dbe2e..ca41b0ebf461 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi
+++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
@@ -28,6 +28,17 @@
 			};
 		};
 
+		dwmmc0@ff704000 {
+			num-slots = <1>;
+			supports-highspeed;
+			broken-cd;
+
+			slot@0 {
+				reg = <0>;
+				bus-width = <4>;
+			};
+		};
+
 		ethernet@ff702000 {
 			phy-mode = "rgmii";
 			phy-addr = <0xffffffff>; /* probe for phy addr */
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts
index d1ec0cab2dee..222313f5420b 100644
--- a/arch/arm/boot/dts/socfpga_vt.dts
+++ b/arch/arm/boot/dts/socfpga_vt.dts
@@ -41,6 +41,17 @@
 			};
 		};
 
+		dwmmc0@ff704000 {
+			num-slots = <1>;
+			supports-highspeed;
+			broken-cd;
+
+			slot@0 {
+				reg = <0>;
+				bus-width = <4>;
+			};
+		};
+
 		ethernet@ff700000 {
 			phy-mode = "gmii";
 			status = "okay";
diff --git a/arch/arm/boot/dts/ste-href-ab8500.dtsi b/arch/arm/boot/dts/ste-href-ab8500.dtsi
new file mode 100644
index 000000000000..30f8601da323
--- /dev/null
+++ b/arch/arm/boot/dts/ste-href-ab8500.dtsi
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ *
+ * 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
+ */
+
+/ {
+	soc {
+		prcmu@80157000 {
+			ab8500 {
+				ab8500-gpio {
+					/* Hog a few default settings */
+					pinctrl-names = "default";
+					pinctrl-0 = <&gpio2_default_mode>,
+						    <&gpio4_default_mode>,
+						    <&gpio10_default_mode>,
+						    <&gpio11_default_mode>,
+						    <&gpio12_default_mode>,
+						    <&gpio13_default_mode>,
+						    <&gpio16_default_mode>,
+						    <&gpio24_default_mode>,
+						    <&gpio25_default_mode>,
+						    <&gpio36_default_mode>,
+						    <&gpio37_default_mode>,
+						    <&gpio38_default_mode>,
+						    <&gpio39_default_mode>,
+						    <&gpio42_default_mode>,
+						    <&gpio26_default_mode>,
+						    <&gpio35_default_mode>,
+						    <&ycbcr_default_mode>,
+						    <&pwm_default_mode>,
+						    <&adi1_default_mode>,
+						    <&usbuicc_default_mode>,
+						    <&dmic_default_mode>,
+						    <&extcpena_default_mode>,
+						    <&modsclsda_default_mode>;
+
+					/*
+					 * Pins 2, 4, 10, 11, 12, 13, 16, 24, 25, 36, 37, 38, 39 and 42
+					 * are muxed in as GPIO, and configured as INPUT PULL DOWN
+					 */
+					gpio2 {
+						gpio2_default_mode: gpio2_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio2_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO2_T9";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio4 {
+						gpio4_default_mode: gpio4_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio4_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO4_W2";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio10 {
+						gpio10_default_mode: gpio10_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio10_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO10_U17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio11 {
+						gpio11_default_mode: gpio11_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio11_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO11_AA18";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio12 {
+						gpio12_default_mode: gpio12_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio12_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO12_U16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio13 {
+						gpio13_default_mode: gpio13_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio13_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO13_W17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio16 {
+						gpio16_default_mode: gpio16_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio16_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO16_F15";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio24 {
+						gpio24_default_mode: gpio24_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio24_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO24_T14";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio25 {
+						gpio25_default_mode: gpio25_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio25_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO25_R16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio36 {
+						gpio36_default_mode: gpio36_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio36_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO36_A17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio37 {
+						gpio37_default_mode: gpio37_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio37_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO37_E15";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio38 {
+						gpio38_default_mode: gpio38_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio38_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO38_C17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio39 {
+						gpio39_default_mode: gpio39_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio39_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO39_E16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio42 {
+						gpio42_default_mode: gpio42_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio42_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO42_U2";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/*
+					 * Pins 26 and 35 muxed in as GPIO, and configured as OUTPUT LOW
+					 */
+					gpio26 {
+						gpio26_default_mode: gpio26_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio26_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO26_M16";
+								output-low;
+							};
+						};
+					};
+					gpio35 {
+						gpio35_default_mode: gpio35_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio35_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO35_W15";
+								output-low;
+							};
+						};
+					};
+					/*
+					 * This sets up the YCBCR connector pins, i.e. analog video out.
+					 * Set as input with no bias.
+					 */
+					ycbcr {
+						ycbcr_default_mode: ycbcr_default {
+							default_mux {
+								ste,function = "ycbcr";
+								ste,pins = "ycbcr0123_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO6_Y18",
+									 "GPIO7_AA20",
+									 "GPIO8_W18",
+									 "GPIO9_AA19";
+								input-enable;
+								bias-disable;
+							};
+						};
+					};
+					/* This sets up the PWM pins 14 and 15 */
+					pwm {
+						pwm_default_mode: pwm_default {
+							default_mux {
+								ste,function = "pwmout";
+								ste,pins = "pwmout1_d_1", "pwmout2_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO14_F14",
+									 "GPIO15_B17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* This sets up audio interface 1 */
+					adi1 {
+						adi1_default_mode: adi1_default {
+							default_mux {
+								ste,function = "adi1";
+								ste,pins = "adi1_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO17_P5",
+									 "GPIO18_R5",
+									 "GPIO19_U5",
+									 "GPIO20_T5";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* This sets up the USB UICC pins */
+					usbuicc {
+						usbuicc_default_mode: usbuicc_default {
+							default_mux {
+								ste,function = "usbuicc";
+								ste,pins = "usbuicc_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO21_H19",
+									 "GPIO22_G20",
+									 "GPIO23_G19";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* This sets up the microphone pins */
+					dmic {
+						dmic_default_mode: dmic_default {
+							default_mux {
+								ste,function = "dmic";
+								ste,pins = "dmic12_d_1",
+									 "dmic34_d_1",
+									 "dmic56_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO27_J6",
+									 "GPIO28_K6",
+									 "GPIO29_G6",
+									 "GPIO30_H6",
+									 "GPIO31_F5",
+									 "GPIO32_G5";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					extcpena {
+						extcpena_default_mode: extcpena_default {
+							default_mux {
+								ste,function = "extcpena";
+								ste,pins = "extcpena_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO34_R17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* Modem I2C setup (SCL and SDA pins) */
+					modsclsda {
+						modsclsda_default_mode: modsclsda_default {
+							default_mux {
+								ste,function = "modsclsda";
+								ste,pins = "modsclsda_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO40_T19",
+									"GPIO41_U19";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/*
+					 * Clock output pins associated with regulators.
+					 */
+					sysclkreq2 {
+						sysclkreq2_default_mode: sysclkreq2_default {
+							default_mux {
+								ste,function = "sysclkreq";
+								ste,pins = "sysclkreq2_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO1_T10";
+								input-enable;
+								bias-disable;
+							};
+						};
+						sysclkreq2_sleep_mode: sysclkreq2_sleep {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio1_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO1_T10";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					sysclkreq4 {
+						sysclkreq4_default_mode: sysclkreq4_default {
+							default_mux {
+								ste,function = "sysclkreq";
+								ste,pins = "sysclkreq4_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO3_U9";
+								input-enable;
+								bias-disable;
+							};
+						};
+						sysclkreq4_sleep_mode: sysclkreq4_sleep {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio3_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO3_U9";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-href-ab8505.dtsi b/arch/arm/boot/dts/ste-href-ab8505.dtsi
new file mode 100644
index 000000000000..6006d62086a2
--- /dev/null
+++ b/arch/arm/boot/dts/ste-href-ab8505.dtsi
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2014 Linaro Ltd.
+ *
+ * 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
+ */
+
+/ {
+	soc {
+		prcmu@80157000 {
+			ab8505 {
+				ab8505-gpio {
+					/* Hog a few default settings */
+					pinctrl-names = "default";
+					pinctrl-0 = <&gpio2_default_mode>,
+						    <&gpio10_default_mode>,
+						    <&gpio11_default_mode>,
+						    <&gpio13_default_mode>,
+						    <&gpio34_default_mode>,
+						    <&gpio50_default_mode>,
+						    <&pwm_default_mode>,
+						    <&adi2_default_mode>,
+						    <&modsclsda_default_mode>,
+						    <&resethw_default_mode>,
+						    <&service_default_mode>;
+
+					/*
+					 * Pins 2, 10, 11, 13, 34 and 50
+					 * are muxed in as GPIO, and configured as INPUT PULL DOWN
+					 */
+					gpio2 {
+						gpio2_default_mode: gpio2_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio2_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO2_R5";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio10 {
+						gpio10_default_mode: gpio10_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio10_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO10_B16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio11 {
+						gpio11_default_mode: gpio11_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio11_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO11_B17";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio13 {
+						gpio13_default_mode: gpio13_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio13_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO13_D17";
+								input-enable;
+								bias-disable;
+							};
+						};
+					};
+					gpio34 {
+						gpio34_default_mode: gpio34_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio34_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO34_H14";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					gpio50 {
+						gpio50_default_mode: gpio50_default {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio50_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO50_L4";
+								input-enable;
+								bias-disable;
+							};
+						};
+					};
+					/* This sets up the PWM pin 14 */
+					pwm {
+						pwm_default_mode: pwm_default {
+							default_mux {
+								ste,function = "pwmout";
+								ste,pins = "pwmout1_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO14_C16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* This sets up audio interface 2 */
+					adi2 {
+						adi2_default_mode: adi2_default {
+							default_mux {
+								ste,function = "adi2";
+								ste,pins = "adi2_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO17_P2",
+									 "GPIO18_N3",
+									 "GPIO19_T1",
+									 "GPIO20_P3";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/* Modem I2C setup (SCL and SDA pins) */
+					modsclsda {
+						modsclsda_default_mode: modsclsda_default {
+							default_mux {
+								ste,function = "modsclsda";
+								ste,pins = "modsclsda_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO40_J15",
+									"GPIO41_J14";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					resethw {
+						resethw_default_mode: resethw_default {
+							default_mux {
+								ste,function = "resethw";
+								ste,pins = "resethw_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO52_D16";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					service {
+						service_default_mode: service_default {
+							default_mux {
+								ste,function = "service";
+								ste,pins = "service_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO53_D15";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					/*
+					 * Clock output pins associated with regulators.
+					 */
+					sysclkreq2 {
+						sysclkreq2_default_mode: sysclkreq2_default {
+							default_mux {
+								ste,function = "sysclkreq";
+								ste,pins = "sysclkreq2_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO1_N4";
+								input-enable;
+								bias-disable;
+							};
+						};
+						sysclkreq2_sleep_mode: sysclkreq2_sleep {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio1_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO1_N4";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+					sysclkreq4 {
+						sysclkreq4_default_mode: sysclkreq4_default {
+							default_mux {
+								ste,function = "sysclkreq";
+								ste,pins = "sysclkreq4_d_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO3_P5";
+								input-enable;
+								bias-disable;
+							};
+						};
+						sysclkreq4_sleep_mode: sysclkreq4_sleep {
+							default_mux {
+								ste,function = "gpio";
+								ste,pins = "gpio3_a_1";
+							};
+							default_cfg {
+								ste,pins = "GPIO3_P5";
+								input-enable;
+								bias-pull-down;
+							};
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/ste-hrefprev60.dtsi
index 40f0ecdf9303..abc762e24fcb 100644
--- a/arch/arm/boot/dts/ste-hrefprev60.dtsi
+++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi
@@ -12,6 +12,7 @@
  */
 
 #include "ste-dbx5x0.dtsi"
+#include "ste-href-ab8500.dtsi"
 #include "ste-href.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
index 3b6d1181939b..c2341061b943 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -10,6 +10,7 @@
  */
 
 #include "ste-dbx5x0.dtsi"
+#include "ste-href-ab8500.dtsi"
 #include "ste-href.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 97d5d21b7db7..a2f632d0be2a 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -11,6 +11,7 @@
 
 /dts-v1/;
 #include "ste-dbx5x0.dtsi"
+#include "ste-href-ab8500.dtsi"
 #include "ste-href-family-pinctrl.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 10666ca8aee1..53478f017087 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -415,13 +415,13 @@
 		};
 
 		rtc: rtc@01c20d00 {
-			compatible = "allwinner,sun4i-rtc";
+			compatible = "allwinner,sun4i-a10-rtc";
 			reg = <0x01c20d00 0x20>;
 			interrupts = <24>;
 		};
 
 		sid: eeprom@01c23800 {
-			compatible = "allwinner,sun4i-sid";
+			compatible = "allwinner,sun4i-a10-sid";
 			reg = <0x01c23800 0x10>;
 		};
 
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 64961595e8d6..327e87bbca0d 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -378,7 +378,7 @@
 		};
 
 		sid: eeprom@01c23800 {
-			compatible = "allwinner,sun4i-sid";
+			compatible = "allwinner,sun4i-a10-sid";
 			reg = <0x01c23800 0x10>;
 		};
 
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 320335abfccd..f49eb13c33c3 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -341,7 +341,7 @@
 		};
 
 		sid: eeprom@01c23800 {
-			compatible = "allwinner,sun4i-sid";
+			compatible = "allwinner,sun4i-a10-sid";
 			reg = <0x01c23800 0x10>;
 		};
 
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index 73aecfb57ccb..8de543777882 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -1,3 +1,8 @@
+/*
+ * This dts file supports Dalmore A04.
+ * Other board revisions are not supported
+ */
+
 /dts-v1/;
 
 #include <dt-bindings/input/input.h>
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 44ec401ec366..fdc559ab2db3 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -604,7 +604,7 @@
 		clocks = <&tegra_car TEGRA114_CLK_SDMMC1>;
 		resets = <&tegra_car 14>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@78000200 {
@@ -614,7 +614,7 @@
 		clocks = <&tegra_car TEGRA114_CLK_SDMMC2>;
 		resets = <&tegra_car 9>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@78000400 {
@@ -624,7 +624,7 @@
 		clocks = <&tegra_car TEGRA114_CLK_SDMMC3>;
 		resets = <&tegra_car 69>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@78000600 {
@@ -634,7 +634,7 @@
 		clocks = <&tegra_car TEGRA114_CLK_SDMMC4>;
 		resets = <&tegra_car 15>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	usb@7d000000 {
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index c6dcef513e5d..1ad686154286 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -8,7 +8,7 @@
 	compatible = "nvidia,venice2", "nvidia,tegra124";
 
 	aliases {
-		rtc0 = "/i2c@7000d000/as3722@40";
+		rtc0 = "/i2c@7000d000/pmic@40";
 		rtc1 = "/rtc@7000e000";
 	};
 
@@ -16,6 +16,20 @@
 		reg = <0x80000000 0x80000000>;
 	};
 
+	host1x@50000000 {
+		sor@54540000 {
+			status = "okay";
+
+			nvidia,dpaux = <&dpaux>;
+			nvidia,panel = <&panel>;
+		};
+
+		dpaux: dpaux@545c0000 {
+			vdd-supply = <&vdd_3v3_panel>;
+			status = "okay";
+		};
+	};
+
 	pinmux: pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinmux_default>;
@@ -402,19 +416,11 @@
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 			};
 			usb_vbus_en0_pn4 {
-				nvidia,pins = "usb_vbus_en0_pn4";
-				nvidia,function = "usb";
-				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-				nvidia,pull = <TEGRA_PIN_PULL_UP>;
-				nvidia,tristate = <TEGRA_PIN_DISABLE>;
-				nvidia,lock = <TEGRA_PIN_DISABLE>;
-				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
-			};
-			usb_vbus_en1_pn5 {
-				nvidia,pins = "usb_vbus_en1_pn5";
+				nvidia,pins = "usb_vbus_en0_pn4",
+					      "usb_vbus_en1_pn5";
 				nvidia,function = "usb";
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,lock = <TEGRA_PIN_DISABLE>;
 				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
@@ -611,11 +617,13 @@
 		status = "okay";
 		clock-frequency = <400000>;
 
-		as3722: as3722@40 {
+		pmic: pmic@40 {
 			compatible = "ams,as3722";
 			reg = <0x40>;
 			interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
 
+			ams,system-power-controller;
+
 			#interrupt-cells = <2>;
 			interrupt-controller;
 
@@ -650,19 +658,19 @@
 			};
 
 			regulators {
-				vsup-sd2-supply = <&vdd_ac_bat_reg>;
-				vsup-sd3-supply = <&vdd_ac_bat_reg>;
-				vsup-sd4-supply = <&vdd_ac_bat_reg>;
-				vsup-sd5-supply = <&vdd_ac_bat_reg>;
-				vin-ldo0-supply = <&as3722_sd2>;
-				vin-ldo1-6-supply = <&vdd_ac_bat_reg>;
-				vin-ldo2-5-7-supply = <&as3722_sd5>;
-				vin-ldo3-4-supply = <&vdd_ac_bat_reg>;
-				vin-ldo9-10-supply = <&vdd_ac_bat_reg>;
-				vin-ldo11-supply = <&vdd_ac_bat_reg>;
+				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";
+					regulator-name = "+VDD_CPU_AP";
 					regulator-min-microvolt = <700000>;
 					regulator-max-microvolt = <1400000>;
 					regulator-min-microamp = <3500000>;
@@ -673,7 +681,7 @@
 				};
 
 				sd1 {
-					regulator-name = "vdd-core";
+					regulator-name = "+VDD_CORE";
 					regulator-min-microvolt = <700000>;
 					regulator-max-microvolt = <1350000>;
 					regulator-min-microamp = <2500000>;
@@ -683,8 +691,8 @@
 					ams,external-control = <1>;
 				};
 
-				as3722_sd2: sd2 {
-					regulator-name = "vddio-ddr";
+				vdd_1v35_lp0: sd2 {
+					regulator-name = "+1.35V_LP0(sd2)";
 					regulator-min-microvolt = <1350000>;
 					regulator-max-microvolt = <1350000>;
 					regulator-always-on;
@@ -692,7 +700,7 @@
 				};
 
 				sd3 {
-					regulator-name = "vddio-ddr-2phase";
+					regulator-name = "+1.35V_LP0(sd3)";
 					regulator-min-microvolt = <1350000>;
 					regulator-max-microvolt = <1350000>;
 					regulator-always-on;
@@ -700,15 +708,13 @@
 				};
 
 				sd4 {
-					regulator-name = "avdd-pex-sata";
+					regulator-name = "+1.05V_RUN";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
-					regulator-boot-on;
-					regulator-always-on;
 				};
 
-				as3722_sd5: sd5 {
-					regulator-name = "vddio-sys";
+				vddio_1v8: sd5 {
+					regulator-name = "+1.8V_VDDIO";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-boot-on;
@@ -716,7 +722,7 @@
 				};
 
 				sd6 {
-					regulator-name = "vdd-gpu";
+					regulator-name = "+VDD_GPU_AP";
 					regulator-min-microvolt = <650000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-min-microamp = <3500000>;
@@ -726,7 +732,7 @@
 				};
 
 				ldo0 {
-					regulator-name = "avdd_pll";
+					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
 					regulator-boot-on;
@@ -735,13 +741,13 @@
 				};
 
 				ldo1 {
-					regulator-name = "run-cam-1.8";
+					regulator-name = "+1.8V_RUN_CAM";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
 				ldo2 {
-					regulator-name = "gen-avdd,vddio-hsic";
+					regulator-name = "+1.2V_GEN_AVDD";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-boot-on;
@@ -749,7 +755,7 @@
 				};
 
 				ldo3 {
-					regulator-name = "vdd-rtc";
+					regulator-name = "+1.00V_LP0_VDD_RTC";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-boot-on;
@@ -757,48 +763,44 @@
 					ams,enable-tracking;
 				};
 
-				ldo4 {
-					regulator-name = "vdd-cam";
+				vdd_run_cam: ldo4 {
+					regulator-name = "+3.3V_RUN_CAM";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
-					regulator-boot-on;
-					regulator-always-on;
 				};
 
 				ldo5 {
-					regulator-name = "vdd-cam-front";
+					regulator-name = "+1.2V_RUN_CAM_FRONT";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				ldo6 {
-					regulator-name = "vddio-sdmmc3";
+				vddio_sdmmc3: ldo6 {
+					regulator-name = "+VDDIO_SDMMC3";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <3300000>;
-					regulator-boot-on;
-					regulator-always-on;
 				};
 
 				ldo7 {
-					regulator-name = "vdd-cam-rear";
+					regulator-name = "+1.05V_RUN_CAM_REAR";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
 				};
 
 				ldo9 {
-					regulator-name = "vdd-touch";
+					regulator-name = "+2.8V_RUN_TOUCH";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
 				ldo10 {
-					regulator-name = "vdd-cam-af";
+					regulator-name = "+2.8V_RUN_CAM_AF";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
 				ldo11 {
-					regulator-name = "vpp-fuse";
+					regulator-name = "+1.8V_RUN_VPP_FUSE";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
@@ -912,6 +914,16 @@
 		};
 	};
 
+	spi@7000da00 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+		spi-flash@0 {
+			compatible = "winbond,w25q32dw";
+			reg = <0>;
+			spi-max-frequency = <20000000>;
+		};
+	};
+
 	pmc@7000e400 {
 		nvidia,invert-interrupt;
 		nvidia,suspend-mode = <1>;
@@ -928,6 +940,7 @@
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
 		status = "okay";
 		bus-width = <4>;
+		vmmc-supply = <&vddio_sdmmc3>;
 	};
 
 	sdhci@700b0600 {
@@ -941,6 +954,44 @@
 		};
 	};
 
+	usb@7d000000 {
+		status = "okay";
+	};
+
+	usb-phy@7d000000 {
+		status = "okay";
+		vbus-supply = <&vdd_usb1_vbus>;
+	};
+
+	usb@7d004000 {
+		status = "okay";
+	};
+
+	usb-phy@7d004000 {
+		status = "okay";
+		vbus-supply = <&vdd_run_cam>;
+	};
+
+	usb@7d008000 {
+		status = "okay";
+	};
+
+	usb-phy@7d008000 {
+		status = "okay";
+		vbus-supply = <&vdd_usb3_vbus>;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+
+		enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
+		power-supply = <&vdd_led>;
+		pwms = <&pwm 1 1000000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -948,7 +999,7 @@
 
 		clk32k_in: clock@0 {
 			compatible = "fixed-clock";
-			reg=<0>;
+			reg = <0>;
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
@@ -966,104 +1017,140 @@
 		};
 	};
 
+	panel: panel {
+		compatible = "lg,lp129qe", "simple-panel";
+
+		backlight = <&backlight>;
+		ddc-i2c-bus = <&dpaux>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		vdd_ac_bat_reg: regulator@0 {
+		vdd_mux: regulator@0 {
 			compatible = "regulator-fixed";
 			reg = <0>;
-			regulator-name = "vdd_ac_bat";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
+			regulator-name = "+VDD_MUX";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
 			regulator-always-on;
+			regulator-boot-on;
 		};
 
-		vdd_3v3_reg: regulator@1 {
+		vdd_5v0_sys: regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
-			regulator-name = "vdd_3v3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
+			regulator-name = "+5V_SYS";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
 			regulator-always-on;
 			regulator-boot-on;
-			enable-active-high;
-			gpio = <&as3722 1 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_mux>;
 		};
 
-		vdd_3v3_modem_reg: regulator@2 {
+		vdd_3v3_sys: regulator@2 {
 			compatible = "regulator-fixed";
 			reg = <2>;
-			regulator-name = "vdd-modem-3v3";
+			regulator-name = "+3.3V_SYS";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
-			enable-active-high;
-			gpio = <&as3722 2 GPIO_ACTIVE_HIGH>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&vdd_mux>;
 		};
 
-		vdd_hdmi_5v0_reg: regulator@3 {
+		vdd_3v3_run: regulator@3 {
 			compatible = "regulator-fixed";
 			reg = <3>;
-			regulator-name = "vdd-hdmi-5v0";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
+			regulator-name = "+3.3V_RUN";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
 			enable-active-high;
-			gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_3v3_sys>;
 		};
 
-		vdd_bl_reg: regulator@4 {
+		vdd_3v3_hdmi: regulator@4 {
 			compatible = "regulator-fixed";
 			reg = <4>;
-			regulator-name = "vdd-bl";
+			regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
-			gpio = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_LOW>;
+			vin-supply = <&vdd_3v3_run>;
 		};
 
-		vdd_ts_sw_5v0: regulator@5 {
+		vdd_led: regulator@5 {
 			compatible = "regulator-fixed";
 			reg = <5>;
-			regulator-name = "vdd_ts_sw";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
+			regulator-name = "+VDD_LED";
+			gpio = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
 			enable-active-high;
-			regulator-boot-on;
-			gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_LOW>;
+			vin-supply = <&vdd_mux>;
 		};
 
-		usb1_vbus_reg: regulator@6 {
+		vdd_5v0_ts: regulator@6 {
 			compatible = "regulator-fixed";
 			reg = <6>;
-			regulator-name = "usb1_vbus";
+			regulator-name = "+5V_VDD_TS_SW";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			regulator-boot-on;
+			gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_HIGH>;
 			enable-active-high;
-			gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
-			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
 		};
 
-		usb3_vbus_reg: regulator@7 {
+		vdd_usb1_vbus: regulator@7 {
 			compatible = "regulator-fixed";
 			reg = <7>;
-			regulator-name = "usb3_vbus";
+			regulator-name = "+5V_USB_HS";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
-			regulator-boot-on;
+			gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
 			enable-active-high;
-			gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
 			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
 		};
 
-		panel_3v3_reg: regulator@8 {
+		vdd_usb3_vbus: regulator@8 {
 			compatible = "regulator-fixed";
 			reg = <8>;
-			regulator-name = "panel_3v3";
+			regulator-name = "+5V_USB_SS";
+			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_panel: regulator@9 {
+			compatible = "regulator-fixed";
+			reg = <9>;
+			regulator-name = "+3.3V_PANEL";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
+			gpio = <&pmic 4 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_3v3_run>;
+		};
+
+		vdd_3v3_lp0: regulator@10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "+3.3V_LP0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			/*
+			 * TODO: find a way to wire this up with the USB EHCI
+			 * controllers so that it can be enabled on demand.
+			 */
+			regulator-always-on;
+			gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
 			enable-active-high;
-			gpio = <&as3722 4 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_3v3_sys>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index ec0698a8354a..b1459844ef09 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -9,6 +9,73 @@
 	compatible = "nvidia,tegra124";
 	interrupt-parent = <&gic>;
 
+	host1x@50000000 {
+		compatible = "nvidia,tegra124-host1x", "simple-bus";
+		reg = <0x50000000 0x00034000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
+			     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
+		clocks = <&tegra_car TEGRA124_CLK_HOST1X>;
+		resets = <&tegra_car 28>;
+		reset-names = "host1x";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x54000000 0x54000000 0x01000000>;
+
+		dc@54200000 {
+			compatible = "nvidia,tegra124-dc";
+			reg = <0x54200000 0x00040000>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&tegra_car TEGRA124_CLK_DISP1>,
+				 <&tegra_car TEGRA124_CLK_PLL_P>;
+			clock-names = "dc", "parent";
+			resets = <&tegra_car 27>;
+			reset-names = "dc";
+
+			nvidia,head = <0>;
+		};
+
+		dc@54240000 {
+			compatible = "nvidia,tegra124-dc";
+			reg = <0x54240000 0x00040000>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&tegra_car TEGRA124_CLK_DISP2>,
+				 <&tegra_car TEGRA124_CLK_PLL_P>;
+			clock-names = "dc", "parent";
+			resets = <&tegra_car 26>;
+			reset-names = "dc";
+
+			nvidia,head = <1>;
+		};
+
+		sor@54540000 {
+			compatible = "nvidia,tegra124-sor";
+			reg = <0x54540000 0x00040000>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&tegra_car TEGRA124_CLK_SOR0>,
+				 <&tegra_car TEGRA124_CLK_PLL_D_OUT0>,
+				 <&tegra_car TEGRA124_CLK_PLL_DP>,
+				 <&tegra_car TEGRA124_CLK_CLK_M>;
+			clock-names = "sor", "parent", "dp", "safe";
+			resets = <&tegra_car 182>;
+			reset-names = "sor";
+			status = "disabled";
+		};
+
+		dpaux@545c0000 {
+			compatible = "nvidia,tegra124-dpaux";
+			reg = <0x545c0000 0x00040000>;
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&tegra_car TEGRA124_CLK_DPAUX>,
+				 <&tegra_car TEGRA124_CLK_PLL_DP>;
+			clock-names = "dpaux", "parent";
+			resets = <&tegra_car 181>;
+			reset-names = "dpaux";
+			status = "disabled";
+		};
+	};
+
 	gic: interrupt-controller@50041000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
@@ -388,7 +455,7 @@
 		clocks = <&tegra_car TEGRA124_CLK_SDMMC1>;
 		resets = <&tegra_car 14>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@700b0200 {
@@ -398,7 +465,7 @@
 		clocks = <&tegra_car TEGRA124_CLK_SDMMC2>;
 		resets = <&tegra_car 9>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@700b0400 {
@@ -408,7 +475,7 @@
 		clocks = <&tegra_car TEGRA124_CLK_SDMMC3>;
 		resets = <&tegra_car 69>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	sdhci@700b0600 {
@@ -418,7 +485,7 @@
 		clocks = <&tegra_car TEGRA124_CLK_SDMMC4>;
 		resets = <&tegra_car 15>;
 		reset-names = "sdhci";
-		status = "disable";
+		status = "disabled";
 	};
 
 	ahub@70300000 {
@@ -524,6 +591,105 @@
 		};
 	};
 
+	usb@7d000000 {
+		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
+		reg = <0x7d000000 0x4000>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USBD>;
+		resets = <&tegra_car 22>;
+		reset-names = "usb";
+		nvidia,phy = <&phy1>;
+		status = "disabled";
+	};
+
+	phy1: usb-phy@7d000000 {
+		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
+		reg = <0x7d000000 0x4000 0x7d000000 0x4000>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USBD>,
+			 <&tegra_car TEGRA124_CLK_PLL_U>,
+			 <&tegra_car TEGRA124_CLK_USBD>;
+		clock-names = "reg", "pll_u", "utmi-pads";
+		nvidia,hssync-start-delay = <0>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <0>;
+		nvidia,xcvr-lsrslew = <3>;
+		nvidia,hssquelch-level = <2>;
+		nvidia,hsdiscon-level = <5>;
+		nvidia,xcvr-hsslew = <12>;
+		status = "disabled";
+	};
+
+	usb@7d004000 {
+		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
+		reg = <0x7d004000 0x4000>;
+		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USB2>;
+		resets = <&tegra_car 58>;
+		reset-names = "usb";
+		nvidia,phy = <&phy2>;
+		status = "disabled";
+	};
+
+	phy2: usb-phy@7d004000 {
+		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
+		reg = <0x7d004000 0x4000 0x7d000000 0x4000>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USB2>,
+			 <&tegra_car TEGRA124_CLK_PLL_U>,
+			 <&tegra_car TEGRA124_CLK_USBD>;
+		clock-names = "reg", "pll_u", "utmi-pads";
+		nvidia,hssync-start-delay = <0>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <0>;
+		nvidia,xcvr-lsrslew = <3>;
+		nvidia,hssquelch-level = <2>;
+		nvidia,hsdiscon-level = <5>;
+		nvidia,xcvr-hsslew = <12>;
+		status = "disabled";
+	};
+
+	usb@7d008000 {
+		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
+		reg = <0x7d008000 0x4000>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USB3>;
+		resets = <&tegra_car 59>;
+		reset-names = "usb";
+		nvidia,phy = <&phy3>;
+		status = "disabled";
+	};
+
+	phy3: usb-phy@7d008000 {
+		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
+		reg = <0x7d008000 0x4000 0x7d000000 0x4000>;
+		phy_type = "utmi";
+		clocks = <&tegra_car TEGRA124_CLK_USB3>,
+			 <&tegra_car TEGRA124_CLK_PLL_U>,
+			 <&tegra_car TEGRA124_CLK_USBD>;
+		clock-names = "reg", "pll_u", "utmi-pads";
+		nvidia,hssync-start-delay = <0>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <0>;
+		nvidia,xcvr-lsrslew = <3>;
+		nvidia,hssquelch-level = <2>;
+		nvidia,hsdiscon-level = <5>;
+		nvidia,xcvr-hsslew = <12>;
+		status = "disabled";
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index c7cd8e6802d7..9a39a8001f78 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -17,6 +17,14 @@
 	};
 
 	host1x@50000000 {
+		dc@54200000 {
+			rgb {
+				status = "okay";
+
+				nvidia,panel = <&panel>;
+			};
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
@@ -257,7 +265,11 @@
 		status = "okay";
 	};
 
-	i2c@7000c000 {
+	pwm: pwm@7000a000 {
+		status = "okay";
+	};
+
+	lvds_ddc: i2c@7000c000 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -475,6 +487,18 @@
 		non-removable;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+
+		enable-gpios = <&gpio TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm 0 5000000>;
+
+		brightness-levels = <0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 255>;
+		default-brightness-level = <10>;
+
+		backlight-boot-off;
+	};
+
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -509,6 +533,16 @@
 		};
 	};
 
+	panel: panel {
+		compatible = "samsung,ltn101nt05", "simple-panel";
+
+		ddc-i2c-bus = <&lvds_ddc>;
+		power-supply = <&vdd_pnl_reg>;
+		enable-gpios = <&gpio TEGRA_GPIO(M, 6) GPIO_ACTIVE_HIGH>;
+
+		backlight = <&backlight>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -522,6 +556,16 @@
 			regulator-max-microvolt = <5000000>;
 			regulator-always-on;
 		};
+
+		vdd_pnl_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "+3VS,vdd_pnl";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio TEGRA_GPIO(A, 4) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
 	};
 
 	sound {
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index a11b6e7b4759..a1d4bf9895d7 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -17,6 +17,14 @@
 	};
 
 	host1x@50000000 {
+		dc@54200000 {
+			rgb {
+				status = "okay";
+
+				nvidia,panel = <&panel>;
+			};
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
@@ -312,6 +320,10 @@
 		status = "okay";
 	};
 
+	pwm: pwm@7000a000 {
+		status = "okay";
+	};
+
 	i2c@7000c000 {
 		status = "okay";
 		clock-frequency = <400000>;
@@ -369,7 +381,7 @@
 			#size-cells = <0>;
 		};
 
-		i2c@1 {
+		lvds_ddc: i2c@1 {
 			reg = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -762,6 +774,17 @@
 		non-removable;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+
+		enable-gpios = <&gpio TEGRA_GPIO(D, 4) GPIO_ACTIVE_HIGH>;
+		power-supply = <&vdd_bl_reg>;
+		pwms = <&pwm 2 5000000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -795,6 +818,16 @@
 		};
 	};
 
+	panel: panel {
+		compatible = "chunghwa,claa101wa01a", "simple-panel";
+
+		power-supply = <&vdd_pnl_reg>;
+		enable-gpios = <&gpio TEGRA_GPIO(B, 2) GPIO_ACTIVE_HIGH>;
+
+		backlight = <&backlight>;
+		ddc-i2c-bus = <&lvds_ddc>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -839,6 +872,26 @@
 			regulator-always-on;
 			regulator-boot-on;
 		};
+
+		vdd_pnl_reg: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "vdd_pnl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio TEGRA_GPIO(C, 6) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		vdd_bl_reg: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
 	};
 
 	sound {
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index 571d12e6ac2d..ca8484cccddc 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -17,6 +17,14 @@
 	};
 
 	host1x@50000000 {
+		dc@54200000 {
+			rgb {
+				status = "okay";
+
+				nvidia,panel = <&panel>;
+			};
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
@@ -309,6 +317,10 @@
 		status = "okay";
 	};
 
+	pwm: pwm@7000a000 {
+		status = "okay";
+	};
+
 	i2c@7000c000 {
 		status = "okay";
 		clock-frequency = <400000>;
@@ -359,7 +371,7 @@
 			#size-cells = <0>;
 		};
 
-		i2c@1 {
+		lvds_ddc: i2c@1 {
 			reg = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -557,6 +569,17 @@
 		non-removable;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+
+		enable-gpios = <&gpio TEGRA_GPIO(D, 4) GPIO_ACTIVE_HIGH>;
+		power-supply = <&vdd_bl_reg>;
+		pwms = <&pwm 2 5000000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -581,6 +604,16 @@
 		};
 	};
 
+	panel: panel {
+		compatible = "chunghwa,claa101wa01a", "simple-panel";
+
+		power-supply = <&vdd_pnl_reg>;
+		enable-gpios = <&gpio TEGRA_GPIO(B, 2) GPIO_ACTIVE_HIGH>;
+
+		backlight = <&backlight>;
+		ddc-i2c-bus = <&lvds_ddc>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -614,7 +647,7 @@
 			enable-active-high;
 		};
 
-		regulator@3 {
+		vdd_pnl_reg: regulator@3 {
 			compatible = "regulator-fixed";
 			reg = <3>;
 			regulator-name = "vdd_pnl";
@@ -624,7 +657,7 @@
 			enable-active-high;
 		};
 
-		regulator@4 {
+		vdd_bl_reg: regulator@4 {
 			compatible = "regulator-fixed";
 			reg = <4>;
 			regulator-name = "vdd_bl";
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 1e156d9d0506..0cf0848a82d8 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -187,6 +187,13 @@
 			interrupt-parent = <&gpio>;
 			interrupts = <TEGRA_GPIO(L, 0) IRQ_TYPE_LEVEL_HIGH>;
 		};
+
+		i2cmux@70 {
+			compatible = "nxp,pca9546";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x70>;
+		};
 	};
 
 	i2c@7000c700 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 19a84e933f4e..7f995739c1a7 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -144,9 +144,9 @@
 			compatible = "nvidia,tegra30-gr2d";
 			reg = <0x54140000 0x00040000>;
 			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&tegra_car TEGRA30_CLK_GR2D>;
 			resets = <&tegra_car 21>;
 			reset-names = "2d";
-			clocks = <&tegra_car TEGRA30_CLK_GR2D>;
 		};
 
 		gr3d@54180000 {
diff --git a/arch/arm/boot/dts/vf610-cosmic.dts b/arch/arm/boot/dts/vf610-cosmic.dts
index c42e4f938dcd..3fd1b74e1216 100644
--- a/arch/arm/boot/dts/vf610-cosmic.dts
+++ b/arch/arm/boot/dts/vf610-cosmic.dts
@@ -36,12 +36,37 @@
 &fec1 {
 	phy-mode = "rmii";
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec1_1>;
+	pinctrl-0 = <&pinctrl_fec1>;
 	status = "okay";
 };
 
+&iomuxc {
+	vf610-cosmic {
+		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_uart1: uart1grp {
+			fsl,pins = <
+				VF610_PAD_PTB4__UART1_TX		0x21a2
+				VF610_PAD_PTB5__UART1_RX		0x21a1
+			>;
+		};
+	};
+};
+
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index c8047ca16501..7dd1d6ede525 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -34,12 +34,70 @@
 		};
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_vcc_3v3_mcu: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "vcc_3v3_mcu";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,widgets =
+			"Microphone", "Microphone Jack",
+			"Headphone", "Headphone Jack",
+			"Speaker", "Speaker Ext",
+			"Line", "Line In Jack";
+		simple-audio-card,routing =
+			"MIC_IN", "Microphone Jack",
+			"Microphone Jack", "Mic Bias",
+			"LINE_IN", "Line In Jack",
+			"Headphone Jack", "HP_OUT",
+			"Speaker Ext", "LINE_OUT";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+			master-clkdir-out;
+			frame-master;
+			bitclock-master;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&codec>;
+			frame-master;
+			bitclock-master;
+		};
+	};
+};
+
+&adc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc0_ad5>;
+	vref-supply = <&reg_vcc_3v3_mcu>;
+	status = "okay";
 };
 
 &dspi0 {
 	bus-num = <0>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_dspi0_1>;
+	pinctrl-0 = <&pinctrl_dspi0>;
 	status = "okay";
 
 	sflash: at26df081a@0 {
@@ -56,26 +114,116 @@
 &fec0 {
 	phy-mode = "rmii";
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec0_1>;
+	pinctrl-0 = <&pinctrl_fec0>;
 	status = "okay";
 };
 
 &fec1 {
 	phy-mode = "rmii";
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec1_1>;
+	pinctrl-0 = <&pinctrl_fec1>;
 	status = "okay";
 };
 
 &i2c0 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c0_1>;
+	pinctrl-0 = <&pinctrl_i2c0>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+	       #sound-dai-cells = <0>;
+	       compatible = "fsl,sgtl5000";
+	       reg = <0x0a>;
+	       VDDA-supply = <&reg_3p3v>;
+	       VDDIO-supply = <&reg_3p3v>;
+	       clocks = <&clks VF610_CLK_SAI2>;
+       };
+};
+
+&iomuxc {
+	vf610-twr {
+		pinctrl_adc0_ad5: adc0ad5grp {
+			fsl,pins = <
+				VF610_PAD_PTC30__ADC0_SE5		0xa1
+			>;
+		};
+
+		pinctrl_dspi0: dspi0grp {
+			fsl,pins = <
+				VF610_PAD_PTB19__DSPI0_CS0		0x1182
+				VF610_PAD_PTB20__DSPI0_SIN		0x1181
+				VF610_PAD_PTB21__DSPI0_SOUT		0x1182
+				VF610_PAD_PTB22__DSPI0_SCK		0x1182
+			>;
+		};
+
+		pinctrl_fec0: fec0grp {
+			fsl,pins = <
+				VF610_PAD_PTA6__RMII_CLKIN		0x30d1
+				VF610_PAD_PTC0__ENET_RMII0_MDC		0x30d3
+				VF610_PAD_PTC1__ENET_RMII0_MDIO		0x30d1
+				VF610_PAD_PTC2__ENET_RMII0_CRS		0x30d1
+				VF610_PAD_PTC3__ENET_RMII0_RXD1		0x30d1
+				VF610_PAD_PTC4__ENET_RMII0_RXD0		0x30d1
+				VF610_PAD_PTC5__ENET_RMII0_RXER		0x30d1
+				VF610_PAD_PTC6__ENET_RMII0_TXD1		0x30d2
+				VF610_PAD_PTC7__ENET_RMII0_TXD0		0x30d2
+				VF610_PAD_PTC8__ENET_RMII0_TXEN		0x30d2
+			>;
+		};
+
+		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_i2c0: i2c0grp {
+			fsl,pins = <
+				VF610_PAD_PTB14__I2C0_SCL		0x30d3
+				VF610_PAD_PTB15__I2C0_SDA		0x30d3
+			>;
+		};
+
+		pinctrl_sai2: sai2grp {
+			fsl,pins = <
+				VF610_PAD_PTA16__SAI2_TX_BCLK		0x02ed
+				VF610_PAD_PTA18__SAI2_TX_DATA		0x02ee
+				VF610_PAD_PTA19__SAI2_TX_SYNC		0x02ed
+				VF610_PAD_PTA21__SAI2_RX_BCLK		0x02ed
+				VF610_PAD_PTA22__SAI2_RX_DATA		0x02ed
+				VF610_PAD_PTA23__SAI2_RX_SYNC		0x02ed
+				VF610_PAD_PTB18__EXT_AUDIO_MCLK		0x02ed
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				VF610_PAD_PTB4__UART1_TX		0x21a2
+				VF610_PAD_PTB5__UART1_RX		0x21a1
+			>;
+		};
+	};
+};
+
+&sai2 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
 	status = "okay";
 };
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index d31ce1b4a7b0..c63d26d3aa83 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -10,6 +10,7 @@
 #include "skeleton.dtsi"
 #include "vf610-pinfunc.h"
 #include <dt-bindings/clock/vf610-clock.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	aliases {
@@ -87,39 +88,66 @@
 				arm,tag-latency = <2 2 2>;
 			};
 
+			edma0: dma-controller@40018000 {
+				#dma-cells = <2>;
+				compatible = "fsl,vf610-edma";
+				reg = <0x40018000 0x2000>,
+					<0x40024000 0x1000>,
+					<0x40025000 0x1000>;
+				interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
+						<0 9 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "edma-tx", "edma-err";
+				dma-channels = <32>;
+				clock-names = "dmamux0", "dmamux1";
+				clocks = <&clks VF610_CLK_DMAMUX0>,
+					<&clks VF610_CLK_DMAMUX1>;
+			};
+
 			uart0: serial@40027000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x40027000 0x1000>;
-				interrupts = <0 61 0x00>;
+				interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART0>;
 				clock-names = "ipg";
+				dmas = <&edma0 0 2>,
+					<&edma0 0 3>;
+				dma-names = "rx","tx";
 				status = "disabled";
 			};
 
 			uart1: serial@40028000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x40028000 0x1000>;
-				interrupts = <0 62 0x04>;
+				interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART1>;
 				clock-names = "ipg";
+				dmas = <&edma0 0 4>,
+					<&edma0 0 5>;
+				dma-names = "rx","tx";
 				status = "disabled";
 			};
 
 			uart2: serial@40029000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x40029000 0x1000>;
-				interrupts = <0 63 0x04>;
+				interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART2>;
 				clock-names = "ipg";
+				dmas = <&edma0 0 6>,
+					<&edma0 0 7>;
+				dma-names = "rx","tx";
 				status = "disabled";
 			};
 
 			uart3: serial@4002a000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x4002a000 0x1000>;
-				interrupts = <0 64 0x04>;
+				interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART3>;
 				clock-names = "ipg";
+				dmas = <&edma0 0 8>,
+					<&edma0 0 9>;
+				dma-names = "rx","tx";
 				status = "disabled";
 			};
 
@@ -128,7 +156,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,vf610-dspi";
 				reg = <0x4002c000 0x1000>;
-				interrupts = <0 67 0x04>;
+				interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_DSPI0>;
 				clock-names = "dspi";
 				spi-num-chipselects = <5>;
@@ -138,20 +166,32 @@
 			sai2: sai@40031000 {
 				compatible = "fsl,vf610-sai";
 				reg = <0x40031000 0x1000>;
-				interrupts = <0 86 0x04>;
+				interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_SAI2>;
 				clock-names = "sai";
+				dma-names = "tx", "rx";
+				dmas = <&edma0 0 21>,
+					<&edma0 0 20>;
 				status = "disabled";
 			};
 
 			pit: pit@40037000 {
 				compatible = "fsl,vf610-pit";
 				reg = <0x40037000 0x1000>;
-				interrupts = <0 39 0x04>;
+				interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_PIT>;
 				clock-names = "pit";
 			};
 
+			adc0: adc@4003b000 {
+				compatible = "fsl,vf610-adc";
+				reg = <0x4003b000 0x1000>;
+				interrupts = <0 53 0x04>;
+				clocks = <&clks VF610_CLK_ADC0>;
+				clock-names = "adc";
+				status = "disabled";
+			};
+
 			wdog@4003e000 {
 				compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
 				reg = <0x4003e000 0x1000>;
@@ -164,7 +204,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,vf610-qspi";
 				reg = <0x40044000 0x1000>;
-				interrupts = <0 24 0x04>;
+				interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_QSPI0_EN>,
 					<&clks VF610_CLK_QSPI0>;
 				clock-names = "qspi_en", "qspi";
@@ -175,182 +215,12 @@
 				compatible = "fsl,vf610-iomuxc";
 				reg = <0x40048000 0x1000>;
 				#gpio-range-cells = <3>;
-
-				/* functions and groups pins */
-
-				dcu0 {
-					pinctrl_dcu0_1: dcu0grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTB8__GPIO_30		0x42
-						VF610_PAD_PTE0__DCU0_HSYNC	0x42
-						VF610_PAD_PTE1__DCU0_VSYNC	0x42
-						VF610_PAD_PTE2__DCU0_PCLK	0x42
-						VF610_PAD_PTE4__DCU0_DE		0x42
-						VF610_PAD_PTE5__DCU0_R0		0x42
-						VF610_PAD_PTE6__DCU0_R1		0x42
-						VF610_PAD_PTE7__DCU0_R2		0x42
-						VF610_PAD_PTE8__DCU0_R3		0x42
-						VF610_PAD_PTE9__DCU0_R4		0x42
-						VF610_PAD_PTE10__DCU0_R5	0x42
-						VF610_PAD_PTE11__DCU0_R6	0x42
-						VF610_PAD_PTE12__DCU0_R7	0x42
-						VF610_PAD_PTE13__DCU0_G0	0x42
-						VF610_PAD_PTE14__DCU0_G1	0x42
-						VF610_PAD_PTE15__DCU0_G2	0x42
-						VF610_PAD_PTE16__DCU0_G3	0x42
-						VF610_PAD_PTE17__DCU0_G4	0x42
-						VF610_PAD_PTE18__DCU0_G5	0x42
-						VF610_PAD_PTE19__DCU0_G6	0x42
-						VF610_PAD_PTE20__DCU0_G7	0x42
-						VF610_PAD_PTE21__DCU0_B0	0x42
-						VF610_PAD_PTE22__DCU0_B1	0x42
-						VF610_PAD_PTE23__DCU0_B2	0x42
-						VF610_PAD_PTE24__DCU0_B3	0x42
-						VF610_PAD_PTE25__DCU0_B4	0x42
-						VF610_PAD_PTE26__DCU0_B5	0x42
-						VF610_PAD_PTE27__DCU0_B6	0x42
-						VF610_PAD_PTE28__DCU0_B7	0x42
-						>;
-					};
-				};
-
-				dspi0 {
-					pinctrl_dspi0_1: dspi0grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTB19__DSPI0_CS0	0x1182
-						VF610_PAD_PTB20__DSPI0_SIN	0x1181
-						VF610_PAD_PTB21__DSPI0_SOUT	0x1182
-						VF610_PAD_PTB22__DSPI0_SCK	0x1182
-						>;
-					};
-				};
-
-				esdhc1 {
-					pinctrl_esdhc1_1: esdhc1grp_1 {
-						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
-						>;
-					};
-				};
-
-				fec0 {
-					pinctrl_fec0_1: fec0grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTA6__RMII_CLKIN	0x30d1
-						VF610_PAD_PTC0__ENET_RMII0_MDC	0x30d3
-						VF610_PAD_PTC1__ENET_RMII0_MDIO	0x30d1
-						VF610_PAD_PTC2__ENET_RMII0_CRS	0x30d1
-						VF610_PAD_PTC3__ENET_RMII0_RXD1	0x30d1
-						VF610_PAD_PTC4__ENET_RMII0_RXD0	0x30d1
-						VF610_PAD_PTC5__ENET_RMII0_RXER	0x30d1
-						VF610_PAD_PTC6__ENET_RMII0_TXD1	0x30d2
-						VF610_PAD_PTC7__ENET_RMII0_TXD0	0x30d2
-						VF610_PAD_PTC8__ENET_RMII0_TXEN	0x30d2
-						>;
-					};
-				};
-
-				fec1 {
-					pinctrl_fec1_1: fec1grp_1 {
-						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
-						>;
-					};
-				};
-
-				i2c0 {
-					pinctrl_i2c0_1: i2c0grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTB14__I2C0_SCL	0x30d3
-						VF610_PAD_PTB15__I2C0_SDA	0x30d3
-						>;
-					};
-				};
-
-				pwm0 {
-					pinctrl_pwm0_1: pwm0grp_1 {
-						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
-						>;
-					};
-				};
-
-				qspi0 {
-					pinctrl_qspi0_1: qspi0grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTD0__QSPI0_A_QSCK	0x307b
-						VF610_PAD_PTD1__QSPI0_A_CS0	0x307f
-						VF610_PAD_PTD2__QSPI0_A_DATA3	0x3073
-						VF610_PAD_PTD3__QSPI0_A_DATA2	0x3073
-						VF610_PAD_PTD4__QSPI0_A_DATA1	0x3073
-						VF610_PAD_PTD5__QSPI0_A_DATA0	0x307b
-						VF610_PAD_PTD7__QSPI0_B_QSCK	0x307b
-						VF610_PAD_PTD8__QSPI0_B_CS0	0x307f
-						VF610_PAD_PTD9__QSPI0_B_DATA3	0x3073
-						VF610_PAD_PTD10__QSPI0_B_DATA2	0x3073
-						VF610_PAD_PTD11__QSPI0_B_DATA1	0x3073
-						VF610_PAD_PTD12__QSPI0_B_DATA0	0x307b
-						>;
-					};
-				};
-
-				sai2 {
-					pinctrl_sai2_1: sai2grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTA16__SAI2_TX_BCLK	0x02ed
-						VF610_PAD_PTA18__SAI2_TX_DATA	0x02ee
-						VF610_PAD_PTA19__SAI2_TX_SYNC	0x02ed
-						VF610_PAD_PTA21__SAI2_RX_BCLK	0x02ed
-						VF610_PAD_PTA22__SAI2_RX_DATA	0x02ed
-						VF610_PAD_PTA23__SAI2_RX_SYNC	0x02ed
-						VF610_PAD_PTB18__EXT_AUDIO_MCLK	0x02ed
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp_1 {
-						fsl,pins = <
-						VF610_PAD_PTB4__UART1_TX	0x21a2
-						VF610_PAD_PTB5__UART1_RX	0x21a1
-						>;
-					};
-				};
-
-				usbvbus {
-					pinctrl_usbvbus_1: usbvbusgrp_1 {
-						fsl,pins = <
-						VF610_PAD_PTA24__USB1_VBUS_EN	0x219c
-						VF610_PAD_PTA16__USB0_VBUS_EN	0x219c
-						>;
-					};
-				};
-
 			};
 
 			gpio1: gpio@40049000 {
 				compatible = "fsl,vf610-gpio";
 				reg = <0x40049000 0x1000 0x400ff000 0x40>;
-				interrupts = <0 107 0x04>;
+				interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -361,7 +231,7 @@
 			gpio2: gpio@4004a000 {
 				compatible = "fsl,vf610-gpio";
 				reg = <0x4004a000 0x1000 0x400ff040 0x40>;
-				interrupts = <0 108 0x04>;
+				interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -372,7 +242,7 @@
 			gpio3: gpio@4004b000 {
 				compatible = "fsl,vf610-gpio";
 				reg = <0x4004b000 0x1000 0x400ff080 0x40>;
-				interrupts = <0 109 0x04>;
+				interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -383,7 +253,7 @@
 			gpio4: gpio@4004c000 {
 				compatible = "fsl,vf610-gpio";
 				reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
-				interrupts = <0 110 0x04>;
+				interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -394,7 +264,7 @@
 			gpio5: gpio@4004d000 {
 				compatible = "fsl,vf610-gpio";
 				reg = <0x4004d000 0x1000 0x400ff100 0x40>;
-				interrupts = <0 111 0x04>;
+				interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
@@ -412,7 +282,7 @@
 				#size-cells = <0>;
 				compatible = "fsl,vf610-i2c";
 				reg = <0x40066000 0x1000>;
-				interrupts =<0 71 0x04>;
+				interrupts =<0 71 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_I2C0>;
 				clock-names = "ipg";
 				status = "disabled";
@@ -432,10 +302,25 @@
 			reg = <0x40080000 0x80000>;
 			ranges;
 
+			edma1: dma-controller@40098000 {
+				#dma-cells = <2>;
+				compatible = "fsl,vf610-edma";
+				reg = <0x40098000 0x2000>,
+					<0x400a1000 0x1000>,
+					<0x400a2000 0x1000>;
+				interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>,
+						<0 11 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "edma-tx", "edma-err";
+				dma-channels = <32>;
+				clock-names = "dmamux0", "dmamux1";
+				clocks = <&clks VF610_CLK_DMAMUX2>,
+					<&clks VF610_CLK_DMAMUX3>;
+			};
+
 			uart4: serial@400a9000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x400a9000 0x1000>;
-				interrupts = <0 65 0x04>;
+				interrupts = <0 65 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART4>;
 				clock-names = "ipg";
 				status = "disabled";
@@ -444,16 +329,25 @@
 			uart5: serial@400aa000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x400aa000 0x1000>;
-				interrupts = <0 66 0x04>;
+				interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_UART5>;
 				clock-names = "ipg";
 				status = "disabled";
 			};
 
+			adc1: adc@400bb000 {
+				compatible = "fsl,vf610-adc";
+				reg = <0x400bb000 0x1000>;
+				interrupts = <0 54 0x04>;
+				clocks = <&clks VF610_CLK_ADC1>;
+				clock-names = "adc";
+				status = "disabled";
+			};
+
 			fec0: ethernet@400d0000 {
 				compatible = "fsl,mvf600-fec";
 				reg = <0x400d0000 0x1000>;
-				interrupts = <0 78 0x04>;
+				interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_ENET0>,
 					<&clks VF610_CLK_ENET0>,
 					<&clks VF610_CLK_ENET>;
@@ -464,7 +358,7 @@
 			fec1: ethernet@400d1000 {
 				compatible = "fsl,mvf600-fec";
 				reg = <0x400d1000 0x1000>;
-				interrupts = <0 79 0x04>;
+				interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks VF610_CLK_ENET1>,
 					<&clks VF610_CLK_ENET1>,
 					<&clks VF610_CLK_ENET>;
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 4bdc41622c36..70b1eff477b3 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
 obj-$(CONFIG_MCPM)		+= mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
+CFLAGS_REMOVE_mcpm_entry.o	= -pg
 AFLAGS_mcpm_head.o		:= -march=armv7-a
 AFLAGS_vlock.o			:= -march=armv7-a
 obj-$(CONFIG_TI_PRIV_EDMA)	+= edma.o
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 53c6a26b633d..fd6bff0c5b96 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -271,10 +271,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
 	void __iomem *base;
 	int irq;
 	const char *name = of_get_property(np, "compatible", NULL);
+	struct clk *clk;
 
 	base = of_iomap(np, 0);
 	if (WARN_ON(!base))
 		return;
+	clk = of_clk_get(np, 0);
+	if (WARN_ON(IS_ERR(clk)))
+		return;
 
 	/* Ensure timer is disabled */
 	writel(0, base + TIMER_CTRL);
@@ -283,13 +287,13 @@ static void __init integrator_cp_of_init(struct device_node *np)
 		goto err;
 
 	if (!init_count)
-		sp804_clocksource_init(base, name);
+		__sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
 	else {
 		irq = irq_of_parse_and_map(np, 0);
 		if (irq <= 0)
 			goto err;
 
-		sp804_clockevents_init(base, irq, name);
+		__sp804_clockevents_init(base, irq, clk, name);
 	}
 
 	init_count++;
diff --git a/arch/arm/configs/ape6evm_defconfig b/arch/arm/configs/ape6evm_defconfig
index cb26c62dc722..bb396c0e5fda 100644
--- a/arch/arm/configs/ape6evm_defconfig
+++ b/arch/arm/configs/ape6evm_defconfig
@@ -48,6 +48,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6_SIT is not set
 CONFIG_NETFILTER=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_NETDEVICES=y
 # CONFIG_NET_CADENCE is not set
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index 9287a62de830..065adddeee3e 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -58,6 +58,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_MD=y
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index f43392dc2dcf..0302d293fba0 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -31,6 +31,7 @@ CONFIG_OPROFILE=y
 CONFIG_JUMP_LABEL=y
 CONFIG_ARCH_MULTI_V6=y
 # CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM2835=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig
index 80cff50beb34..e816140d81c5 100644
--- a/arch/arm/configs/bockw_defconfig
+++ b/arch/arm/configs/bockw_defconfig
@@ -44,6 +44,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
diff --git a/arch/arm/configs/clps711x_defconfig b/arch/arm/configs/clps711x_defconfig
index 9e8c8316d6b0..0facf9da047c 100644
--- a/arch/arm/configs/clps711x_defconfig
+++ b/arch/arm/configs/clps711x_defconfig
@@ -15,7 +15,6 @@ CONFIG_ARCH_CDB89712=y
 CONFIG_ARCH_CLEP7312=y
 CONFIG_ARCH_EDB7211=y
 CONFIG_ARCH_P720T=y
-CONFIG_ARCH_FORTUNET=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
@@ -27,7 +26,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 CONFIG_IRDA=y
 CONFIG_IRTTY_SIR=y
-CONFIG_EP7211_DONGLE=y
 # CONFIG_WIRELESS is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -58,6 +56,7 @@ CONFIG_CS89x0_PLATFORM=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+CONFIG_SERIAL_CLPS711X=y
 CONFIG_SERIAL_CLPS711X_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig
index 110105476848..f15955144175 100644
--- a/arch/arm/configs/dove_defconfig
+++ b/arch/arm/configs/dove_defconfig
@@ -48,7 +48,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_M25P80=y
-CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
@@ -80,6 +79,8 @@ CONFIG_SPI_ORION=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_DOVE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index dbe1f1c47bb0..4ce7b70ea901 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -94,7 +94,7 @@ CONFIG_FONT_7x14=y
 CONFIG_LOGO=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_EHCI_EXYNOS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_PHY=y
diff --git a/arch/arm/configs/genmai_defconfig b/arch/arm/configs/genmai_defconfig
index aa0b704f48af..d238fafb6762 100644
--- a/arch/arm/configs/genmai_defconfig
+++ b/arch/arm/configs/genmai_defconfig
@@ -50,6 +50,9 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_CORE is not set
 # CONFIG_NET_VENDOR_ARC is not set
@@ -78,7 +81,10 @@ CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=10
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_I2C_SH_MOBILE=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_RIIC=y
+CONFIG_SPI=y
+CONFIG_SPI_RSPI=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 6309ee52ccfc..f1aeb7d72712 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -154,6 +154,7 @@ CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 53e82c2523eb..09e974392fa1 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -39,6 +39,8 @@ CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_SOC_IMX6SL=y
 CONFIG_SOC_VF610=y
+CONFIG_PCI=y
+CONFIG_PCI_IMX6=y
 CONFIG_SMP=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -165,6 +167,7 @@ CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_ANATOP=y
 CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_REGULATOR_PFUZE100=y
@@ -186,6 +189,7 @@ CONFIG_LCD_L4F00242T03=y
 CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
@@ -211,6 +215,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
@@ -225,6 +230,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_RTC_DRV_SNVS=y
@@ -277,6 +283,7 @@ CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_PROVE_LOCKING=y
diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index 4582e160feab..7056ef499657 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -131,6 +131,8 @@ CONFIG_SPI_DAVINCI=y
 CONFIG_SPI_SPIDEV=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_DAVINCI_WATCHDOG=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -177,3 +179,14 @@ CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_ANSI_CPRNG=y
 CONFIG_CRYPTO_USER_API_HASH=y
 CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_DAVINCI=y
+CONFIG_LEDS_CLASS=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
index e248f49d5549..86faab565a96 100644
--- a/arch/arm/configs/koelsch_defconfig
+++ b/arch/arm/configs/koelsch_defconfig
@@ -8,7 +8,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
-# CONFIG_BLOCK is not set
 CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7791=y
 CONFIG_MACH_KOELSCH=y
@@ -35,7 +34,14 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_RCAR=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
@@ -53,18 +59,31 @@ CONFIG_SH_ETH=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=20
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_I2C=y
+CONFIG_I2C_RCAR=y
+CONFIG_SPI=y
+CONFIG_SPI_RSPI=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_RCAR=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig
deleted file mode 100644
index e42ce3756af3..000000000000
--- a/arch/arm/configs/kzm9d_defconfig
+++ /dev/null
@@ -1,89 +0,0 @@
-# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_EMEV2=y
-CONFIG_MACH_KZM9D=y
-CONFIG_MEMORY_START=0x40000000
-CONFIG_MEMORY_SIZE=0x10000000
-# CONFIG_SH_TIMER_TMU is not set
-# CONFIG_SWP_EMULATE is not set
-# CONFIG_CACHE_L2X0 is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_HOTPLUG_CPU=y
-# CONFIG_LOCAL_TIMERS is not set
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
-CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_VFP=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-CONFIG_SMSC911X=y
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EM=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_EM=y
-# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-# CONFIG_FTRACE is not set
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
index 9934dbc23d64..12bd1f63c399 100644
--- a/arch/arm/configs/kzm9g_defconfig
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -60,6 +60,8 @@ CONFIG_IRDA=y
 CONFIG_SH_IRDA=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig
index 883443f8f4f3..58702440472a 100644
--- a/arch/arm/configs/lager_defconfig
+++ b/arch/arm/configs/lager_defconfig
@@ -49,6 +49,13 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_RCAR=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_CORE is not set
 # CONFIG_NET_VENDOR_ARC is not set
@@ -81,6 +88,8 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
 CONFIG_I2C_RCAR=y
+CONFIG_SPI=y
+CONFIG_SPI_RSPI=y
 CONFIG_GPIO_SH_PFC=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_RCAR=y
@@ -90,8 +99,20 @@ CONFIG_RCAR_THERMAL=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_VIDEO_RCAR_VIN=y
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+CONFIG_VIDEO_ADV7180=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_RCAR=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
diff --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig
index a61e1653fc5e..57ececba2ae6 100644
--- a/arch/arm/configs/mackerel_defconfig
+++ b/arch/arm/configs/mackerel_defconfig
@@ -42,6 +42,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index f21bd405cc2a..92994f7f6fd8 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -43,6 +43,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
new file mode 100644
index 000000000000..84ba24a0ead7
--- /dev/null
+++ b/arch/arm/configs/multi_v5_defconfig
@@ -0,0 +1,194 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_T5325=y
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_IMX25_DT=y
+CONFIG_MACH_IMX27_DT=y
+CONFIG_ARCH_U300=y
+CONFIG_PCI_MVEBU=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_KIRKWOOD_CPUIDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IPV6 is not set
+CONFIG_NET_PKTGEN=m
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ORION=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_EEPROM_AT24=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
+CONFIG_MV643XX_ETH=y
+CONFIG_R8169=y
+CONFIG_MARVELL_PHY=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_I2C_NOMADIK=y
+CONFIG_SPI=y
+CONFIG_SPI_ORION=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_QNAP=y
+CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_LM63=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_LM85=y
+CONFIG_THERMAL=y
+CONFIG_KIRKWOOD_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_KIRKWOOD_SOC=y
+CONFIG_SND_KIRKWOOD_SOC_T5325=y
+# CONFIG_ABX500_CORE is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_KIRKWOOD_SOC=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_MMC=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_DMADEVICES=y
+CONFIG_MV_XOR=y
+CONFIG_STAGING=y
+CONFIG_FB_XGI=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_MV_CESA=y
+CONFIG_CRC_CCITT=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index ee6982976d66..64e850d4896c 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -9,6 +9,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_375=y
+CONFIG_MACH_ARMADA_38X=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM_MOBILE=y
@@ -31,6 +33,10 @@ CONFIG_SOC_OMAP5=y
 CONFIG_SOC_AM33XX=y
 CONFIG_SOC_DRA7XX=y
 CONFIG_SOC_AM43XX=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_ARCH_MSM8960=y
+CONFIG_ARCH_MSM8974=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_PLAT_SPEAR=y
@@ -146,6 +152,8 @@ CONFIG_SERIAL_SIRFSOC_CONSOLE=y
 CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_VT8500=y
 CONFIG_SERIAL_VT8500_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
@@ -188,6 +196,8 @@ CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
 CONFIG_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
@@ -294,6 +304,10 @@ CONFIG_MFD_NVEC=y
 CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
 CONFIG_NVEC_POWER=y
+CONFIG_COMMON_CLK_QCOM=y
+CONFIG_MSM_GCC_8660=y
+CONFIG_MSM_MMCC_8960=y
+CONFIG_MSM_MMCC_8974=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_MEMORY=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
deleted file mode 100644
index 0f4511d2849f..000000000000
--- a/arch/arm/configs/mvebu_defconfig
+++ /dev/null
@@ -1,107 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_ARMADA_370=y
-CONFIG_MACH_ARMADA_XP=y
-# CONFIG_CACHE_L2X0 is not set
-# CONFIG_SWP_EMULATE is not set
-CONFIG_PCI=y
-CONFIG_PCI_MVEBU=y
-CONFIG_SMP=y
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-# CONFIG_COMPACTION is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_VFP=y
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_BT=y
-CONFIG_BT_MRVL=y
-CONFIG_BT_MRVL_SDIO=y
-CONFIG_CFG80211=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_SD=y
-CONFIG_ATA=y
-CONFIG_SATA_MV=y
-CONFIG_NETDEVICES=y
-CONFIG_MVNETA=y
-CONFIG_MARVELL_PHY=y
-CONFIG_MWIFIEX=y
-CONFIG_MWIFIEX_SDIO=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_SPI=y
-CONFIG_SPI_ORION=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PXA3xx=y
-CONFIG_SERIAL_8250_DW=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_THERMAL=y
-CONFIG_ARMADA_THERMAL=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_MMC=y
-CONFIG_MMC_MVSDIO=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_CLASS=m
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_S35390A=y
-CONFIG_RTC_DRV_MV=y
-CONFIG_DMADEVICES=y
-CONFIG_MV_XOR=y
-CONFIG_MEMORY=y
-CONFIG_MVEBU_DEVBUS=y
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/mvebu_v5_defconfig b/arch/arm/configs/mvebu_v5_defconfig
new file mode 100644
index 000000000000..36484a37a1ca
--- /dev/null
+++ b/arch/arm/configs/mvebu_v5_defconfig
@@ -0,0 +1,181 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_T5325=y
+# CONFIG_CPU_FEROCEON_OLD_ID is not set
+CONFIG_PCI_MVEBU=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IPV6 is not set
+CONFIG_NET_PKTGEN=m
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ORION=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_EEPROM_AT24=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
+CONFIG_MV643XX_ETH=y
+CONFIG_R8169=y
+CONFIG_MARVELL_PHY=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_SPI=y
+CONFIG_SPI_ORION=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_QNAP=y
+CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_LM63=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_LM85=y
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_KIRKWOOD_SOC=y
+CONFIG_SND_KIRKWOOD_SOC_T5325=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_MMC=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_DMADEVICES=y
+CONFIG_MV_XOR=y
+CONFIG_STAGING=y
+CONFIG_FB_XGI=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_MV_CESA=y
+CONFIG_CRC_CCITT=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig
new file mode 100644
index 000000000000..62b6a37626c5
--- /dev/null
+++ b/arch/arm/configs/mvebu_v7_defconfig
@@ -0,0 +1,116 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_375=y
+CONFIG_MACH_ARMADA_38X=y
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_CACHE_L2X0 is not set
+# CONFIG_SWP_EMULATE is not set
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SMP=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_VFP=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_BT=y
+CONFIG_BT_MRVL=y
+CONFIG_BT_MRVL_SDIO=y
+CONFIG_CFG80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_MVNETA=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MWIFIEX=y
+CONFIG_MWIFIEX_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_I2C=y
+CONFIG_SPI=y
+CONFIG_SPI_ORION=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_PXA3xx=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_THERMAL=y
+CONFIG_ARMADA_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_KIRKWOOD_SOC=y
+CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_MMC=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_DMADEVICES=y
+CONFIG_MV_XOR=y
+CONFIG_MEMORY=y
+CONFIG_MVEBU_DEVBUS=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
new file mode 100644
index 000000000000..83b07258a385
--- /dev/null
+++ b/arch/arm/configs/shmobile_defconfig
@@ -0,0 +1,129 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_ARCH_SHMOBILE_MULTI=y
+CONFIG_ARCH_EMEV2=y
+CONFIG_ARCH_R8A7790=y
+CONFIG_ARCH_R8A7791=y
+CONFIG_MACH_KOELSCH=y
+CONFIG_MACH_LAGER=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_CPU_BPREDICT_DISABLE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_PCI=y
+CONFIG_PCI_RCAR_GEN2=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_NR_CPUS=8
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_KEXEC=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_RCAR=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_SH_ETH=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_EM=y
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=20
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_RCAR=y
+CONFIG_SPI=y
+CONFIG_SPI_RSPI=y
+CONFIG_GPIO_EM=y
+CONFIG_GPIO_RCAR=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_VIDEO_RCAR_VIN=y
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+CONFIG_VIDEO_ADV7180=y
+CONFIG_DRM=y
+CONFIG_DRM_RCAR_DU=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_RCAR=y
+CONFIG_USB_RCAR_GEN2_PHY=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
+CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 00fe9e9710fd..bd7f6dd95cd3 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -86,6 +86,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
@@ -125,6 +126,7 @@ CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
@@ -141,6 +143,7 @@ CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_CHARGER_TPS65090=y
 CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_AS3722=y
@@ -166,7 +169,8 @@ CONFIG_REGULATOR_TPS65910=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_USB_SUPPORT=y
-CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_GSPCA=y
 CONFIG_DRM=y
 CONFIG_DRM_TEGRA=y
 CONFIG_DRM_PANEL_SIMPLE=y
diff --git a/arch/arm/firmware/Kconfig b/arch/arm/firmware/Kconfig
index bb00ccf00d66..ad396af68e47 100644
--- a/arch/arm/firmware/Kconfig
+++ b/arch/arm/firmware/Kconfig
@@ -11,6 +11,7 @@ menu "Firmware options"
 config TRUSTED_FOUNDATIONS
 	bool "Trusted Foundations secure monitor support"
 	depends on ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
+	default y
 	help
 	  Some devices (including most Tegra-based consumer devices on the
 	  market) are booted with the Trusted Foundations secure monitor
@@ -20,7 +21,7 @@ config TRUSTED_FOUNDATIONS
 	  This option allows the kernel to invoke the secure monitor whenever
 	  required on devices using Trusted Foundations. See
 	  arch/arm/include/asm/trusted_foundations.h or the
-	  tl,trusted-foundations device tree binding documentation for details
+	  tlm,trusted-foundations device tree binding documentation for details
 	  on how to use it.
 
 	  Say n if you don't know what this is about.
diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c
index ef1e3d8f4af0..3fb1b5a1dce9 100644
--- a/arch/arm/firmware/trusted_foundations.c
+++ b/arch/arm/firmware/trusted_foundations.c
@@ -22,6 +22,15 @@
 
 #define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
 
+#define TF_CPU_PM		0xfffffffc
+#define TF_CPU_PM_S3		0xffffffe3
+#define TF_CPU_PM_S2		0xffffffe6
+#define TF_CPU_PM_S2_NO_MC_CLK	0xffffffe5
+#define TF_CPU_PM_S1		0xffffffe4
+#define TF_CPU_PM_S1_NOFLUSH_L2	0xffffffe7
+
+static unsigned long cpu_boot_addr;
+
 static void __naked tf_generic_smc(u32 type, u32 arg1, u32 arg2)
 {
 	asm volatile(
@@ -41,13 +50,22 @@ static void __naked tf_generic_smc(u32 type, u32 arg1, u32 arg2)
 
 static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 {
-	tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, boot_addr, 0);
+	cpu_boot_addr = boot_addr;
+	tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0);
+
+	return 0;
+}
+
+static int tf_prepare_idle(void)
+{
+	tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2, cpu_boot_addr);
 
 	return 0;
 }
 
 static const struct firmware_ops trusted_foundations_ops = {
 	.set_cpu_boot_addr = tf_set_cpu_boot_addr,
+	.prepare_idle = tf_prepare_idle,
 };
 
 void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 3278afe2c3ab..23e728ecf8ab 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -7,16 +7,19 @@ generic-y += current.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += poll.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += sections.h
 generic-y += segment.h
@@ -33,5 +36,3 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 5c2285160575..380ac4f20000 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -30,8 +30,8 @@
  * Endian independent macros for shifting bytes within registers.
  */
 #ifndef __ARMEB__
-#define pull            lsr
-#define push            lsl
+#define lspull          lsr
+#define lspush          lsl
 #define get_byte_0      lsl #0
 #define get_byte_1	lsr #8
 #define get_byte_2	lsr #16
@@ -41,8 +41,8 @@
 #define put_byte_2	lsl #16
 #define put_byte_3	lsl #24
 #else
-#define pull            lsl
-#define push            lsr
+#define lspull          lsl
+#define lspush          lsr
 #define get_byte_0	lsr #24
 #define get_byte_1	lsr #16
 #define get_byte_2	lsr #8
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 62d2cb53b069..9a92fd7864a8 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -60,6 +60,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
 	int result;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic_add_return\n"
 "1:	ldrex	%0, [%3]\n"
@@ -99,6 +100,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 	int result;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic_sub_return\n"
 "1:	ldrex	%0, [%3]\n"
@@ -121,6 +123,7 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
 	unsigned long res;
 
 	smp_mb();
+	prefetchw(&ptr->counter);
 
 	do {
 		__asm__ __volatile__("@ atomic_cmpxchg\n"
@@ -138,6 +141,33 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
 	return oldval;
 }
 
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int oldval, newval;
+	unsigned long tmp;
+
+	smp_mb();
+	prefetchw(&v->counter);
+
+	__asm__ __volatile__ ("@ atomic_add_unless\n"
+"1:	ldrex	%0, [%4]\n"
+"	teq	%0, %5\n"
+"	beq	2f\n"
+"	add	%1, %0, %6\n"
+"	strex	%2, %1, [%4]\n"
+"	teq	%2, #0\n"
+"	bne	1b\n"
+"2:"
+	: "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter)
+	: "r" (&v->counter), "r" (u), "r" (a)
+	: "cc");
+
+	if (oldval != u)
+		smp_mb();
+
+	return oldval;
+}
+
 #else /* ARM_ARCH_6 */
 
 #ifdef CONFIG_SMP
@@ -186,10 +216,6 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 	return ret;
 }
 
-#endif /* __LINUX_ARM_ARCH__ */
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
@@ -200,6 +226,10 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 	return c;
 }
 
+#endif /* __LINUX_ARM_ARCH__ */
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
 #define atomic_inc(v)		atomic_add(1, v)
 #define atomic_dec(v)		atomic_sub(1, v)
 
@@ -299,6 +329,7 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v)
 	unsigned long tmp;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic64_add_return\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
@@ -340,6 +371,7 @@ static inline long long atomic64_sub_return(long long i, atomic64_t *v)
 	unsigned long tmp;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic64_sub_return\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
@@ -364,6 +396,7 @@ static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old,
 	unsigned long res;
 
 	smp_mb();
+	prefetchw(&ptr->counter);
 
 	do {
 		__asm__ __volatile__("@ atomic64_cmpxchg\n"
@@ -388,6 +421,7 @@ static inline long long atomic64_xchg(atomic64_t *ptr, long long new)
 	unsigned long tmp;
 
 	smp_mb();
+	prefetchw(&ptr->counter);
 
 	__asm__ __volatile__("@ atomic64_xchg\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
@@ -409,6 +443,7 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
 	unsigned long tmp;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic64_dec_if_positive\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
@@ -436,6 +471,7 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
 	int ret = 1;
 
 	smp_mb();
+	prefetchw(&v->counter);
 
 	__asm__ __volatile__("@ atomic64_add_unless\n"
 "1:	ldrexd	%0, %H0, [%4]\n"
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
index df2fbba7efc8..abb2c3769b01 100644
--- a/arch/arm/include/asm/cmpxchg.h
+++ b/arch/arm/include/asm/cmpxchg.h
@@ -2,6 +2,7 @@
 #define __ASM_ARM_CMPXCHG_H
 
 #include <linux/irqflags.h>
+#include <linux/prefetch.h>
 #include <asm/barrier.h>
 
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
@@ -35,6 +36,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
 #endif
 
 	smp_mb();
+	prefetchw((const void *)ptr);
 
 	switch (size) {
 #if __LINUX_ARM_ARCH__ >= 6
@@ -138,6 +140,8 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 {
 	unsigned long oldval, res;
 
+	prefetchw((const void *)ptr);
+
 	switch (size) {
 #ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
 	case 1:
@@ -230,6 +234,8 @@ static inline unsigned long long __cmpxchg64(unsigned long long *ptr,
 	unsigned long long oldval;
 	unsigned long res;
 
+	prefetchw(ptr);
+
 	__asm__ __volatile__(
 "1:	ldrexd		%1, %H1, [%3]\n"
 "	teq		%1, %4\n"
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index acdde76b39bb..42f0889f0584 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -71,6 +71,7 @@
 #define ARM_CPU_PART_CORTEX_A5		0xC050
 #define ARM_CPU_PART_CORTEX_A15		0xC0F0
 #define ARM_CPU_PART_CORTEX_A7		0xC070
+#define ARM_CPU_PART_CORTEX_A12		0xC0D0
 
 #define ARM_CPU_XSCALE_ARCH_MASK	0xe000
 #define ARM_CPU_XSCALE_ARCH_V1		0x2000
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index a8c56acc8c98..eec0a12c5c1d 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -13,9 +13,12 @@ struct dma_iommu_mapping {
 	/* iommu specific data */
 	struct iommu_domain	*domain;
 
-	void			*bitmap;
-	size_t			bits;
-	unsigned int		order;
+	unsigned long		**bitmaps;	/* array of bitmaps */
+	unsigned int		nr_bitmaps;	/* nr of elements in array */
+	unsigned int		extensions;
+	size_t			bitmap_size;	/* size of a single bitmap */
+	size_t			bits;		/* per bitmap */
+	unsigned int		size;		/* per bitmap */
 	dma_addr_t		base;
 
 	spinlock_t		lock;
@@ -23,8 +26,7 @@ struct dma_iommu_mapping {
 };
 
 struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-			 int order);
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size);
 
 void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
 
diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h
index 15631300c238..2c9f10df7568 100644
--- a/arch/arm/include/asm/firmware.h
+++ b/arch/arm/include/asm/firmware.h
@@ -22,6 +22,10 @@
  */
 struct firmware_ops {
 	/*
+	 * Inform the firmware we intend to enter CPU idle mode
+	 */
+	int (*prepare_idle)(void);
+	/*
 	 * Enters CPU idle mode
 	 */
 	int (*do_idle)(void);
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/futex.h b/arch/arm/include/asm/futex.h
index e42cf597f6e6..53e69dae796f 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -3,11 +3,6 @@
 
 #ifdef __KERNEL__
 
-#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP)
-/* ARM doesn't provide unprivileged exclusive memory accessors */
-#include <asm-generic/futex.h>
-#else
-
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
@@ -28,6 +23,7 @@
 
 #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
 	smp_mb();						\
+	prefetchw(uaddr);					\
 	__asm__ __volatile__(					\
 	"1:	ldrex	%1, [%3]\n"				\
 	"	" insn "\n"					\
@@ -51,6 +47,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		return -EFAULT;
 
 	smp_mb();
+	/* Prefetching cannot fault */
+	prefetchw(uaddr);
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
 	"1:	ldrex	%1, [%4]\n"
 	"	teq	%1, %2\n"
@@ -164,6 +162,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 	return ret;
 }
 
-#endif /* !(CPU_USE_DOMAINS && SMP) */
 #endif /* __KERNEL__ */
 #endif /* _ASM_ARM_FUTEX_H */
diff --git a/arch/arm/include/asm/hardware/cache-feroceon-l2.h b/arch/arm/include/asm/hardware/cache-feroceon-l2.h
new file mode 100644
index 000000000000..12e1588dc4f1
--- /dev/null
+++ b/arch/arm/include/asm/hardware/cache-feroceon-l2.h
@@ -0,0 +1,13 @@
+/*
+ * arch/arm/include/asm/hardware/cache-feroceon-l2.h
+ *
+ * Copyright (C) 2008 Marvell Semiconductor
+ *
+ * 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.
+ */
+
+extern void __init feroceon_l2_init(int l2_wt_override);
+extern int __init feroceon_of_init(void);
+
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
index eef55ea9ef00..8e427c7b4425 100644
--- a/arch/arm/include/asm/hw_breakpoint.h
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -51,6 +51,7 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_DEBUG_ARCH_V7_ECP14	3
 #define ARM_DEBUG_ARCH_V7_MM	4
 #define ARM_DEBUG_ARCH_V7_1	5
+#define ARM_DEBUG_ARCH_V8	6
 
 /* Breakpoint */
 #define ARM_BREAKPOINT_EXECUTE	0
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h
index 6ff56eca3f1f..6e183fd269fb 100644
--- a/arch/arm/include/asm/hwcap.h
+++ b/arch/arm/include/asm/hwcap.h
@@ -9,6 +9,7 @@
  * instruction set this cpu supports.
  */
 #define ELF_HWCAP	(elf_hwcap)
-extern unsigned int elf_hwcap;
+#define ELF_HWCAP2	(elf_hwcap2)
+extern unsigned int elf_hwcap, elf_hwcap2;
 #endif
 #endif
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 863c892b4aaa..70f9b9bfb1f9 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -4,7 +4,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <asm/system.h>
 
 #define JUMP_LABEL_NOP_SIZE 4
 
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index dfff709fda3c..219ac88a9542 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -140,6 +140,7 @@
 #define L_PTE_MT_DEV_NONSHARED	(_AT(pteval_t, 0x0c) << 2)	/* 1100 */
 #define L_PTE_MT_DEV_WC		(_AT(pteval_t, 0x09) << 2)	/* 1001 */
 #define L_PTE_MT_DEV_CACHED	(_AT(pteval_t, 0x0b) << 2)	/* 1011 */
+#define L_PTE_MT_VECTORS	(_AT(pteval_t, 0x0f) << 2)	/* 1111 */
 #define L_PTE_MT_MASK		(_AT(pteval_t, 0x0f) << 2)
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 7d59b524f2af..5478e5d6ad89 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -216,13 +216,16 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 
 #define pte_none(pte)		(!pte_val(pte))
 #define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
+#define pte_valid(pte)		(pte_val(pte) & L_PTE_VALID)
+#define pte_accessible(mm, pte)	(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
 #define pte_write(pte)		(!(pte_val(pte) & L_PTE_RDONLY))
 #define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
 #define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN))
 #define pte_special(pte)	(0)
 
-#define pte_present_user(pte)  (pte_present(pte) && (pte_val(pte) & L_PTE_USER))
+#define pte_valid_user(pte)	\
+	(pte_valid(pte) && (pte_val(pte) & L_PTE_USER) && pte_young(pte))
 
 #if __LINUX_ARM_ARCH__ < 6
 static inline void __sync_icache_dcache(pte_t pteval)
@@ -237,7 +240,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 {
 	unsigned long ext = 0;
 
-	if (addr < TASK_SIZE && pte_present_user(pteval)) {
+	if (addr < TASK_SIZE && pte_valid_user(pteval)) {
 		__sync_icache_dcache(pteval);
 		ext |= PTE_EXT_NG;
 	}
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index f24edad26c70..ae1919be8f98 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -71,6 +71,8 @@ struct arm_pmu {
 	void		(*disable)(struct perf_event *event);
 	int		(*get_event_idx)(struct pmu_hw_events *hw_events,
 					 struct perf_event *event);
+	void		(*clear_event_idx)(struct pmu_hw_events *hw_events,
+					 struct perf_event *event);
 	int		(*set_event_filter)(struct hw_perf_event *evt,
 					    struct perf_event_attr *attr);
 	u32		(*read_counter)(struct perf_event *event);
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 04c99f36ff7f..627a03ebb987 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -27,9 +27,13 @@ struct pt_regs {
 #define thumb_mode(regs) (0)
 #endif
 
+#ifndef CONFIG_CPU_V7M
 #define isa_mode(regs) \
-	((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
-	 (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+	((((regs)->ARM_cpsr & PSR_J_BIT) >> (__ffs(PSR_J_BIT) - 1)) | \
+	 (((regs)->ARM_cpsr & PSR_T_BIT) >> (__ffs(PSR_T_BIT))))
+#else
+#define isa_mode(regs) 1 /* Thumb */
+#endif
 
 #define processor_mode(regs) \
 	((regs)->ARM_cpsr & MODE_MASK)
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 22a3b9b5d4a1..772435b08207 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -114,6 +114,15 @@ struct smp_operations {
 #endif
 };
 
+struct of_cpu_method {
+	const char *method;
+	struct smp_operations *ops;
+};
+
+#define CPU_METHOD_OF_DECLARE(name, _method, _ops)			\
+	static const struct of_cpu_method __cpu_method_of_table_##name	\
+		__used __section(__cpu_method_of_table)			\
+		= { .method = _method, .ops = _ops }
 /*
  * set platform specific SMP operations
  */
diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h
index 63479eecbf76..9732b8e11e63 100644
--- a/arch/arm/include/asm/sync_bitops.h
+++ b/arch/arm/include/asm/sync_bitops.h
@@ -2,7 +2,6 @@
 #define __ASM_SYNC_BITOPS_H__
 
 #include <asm/bitops.h>
-#include <asm/system.h>
 
 /* sync_bitops functions are equivalent to the SMP implementation of the
  * original functions, independently from CONFIG_SMP being defined.
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
deleted file mode 100644
index 368165e33c1c..000000000000
--- a/arch/arm/include/asm/system.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
-#include <asm/barrier.h>
-#include <asm/compiler.h>
-#include <asm/cmpxchg.h>
-#include <asm/switch_to.h>
-#include <asm/system_info.h>
-#include <asm/system_misc.h>
diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h
index 83f2aa83899c..f6fcc67ef06e 100644
--- a/arch/arm/include/asm/timex.h
+++ b/arch/arm/include/asm/timex.h
@@ -12,12 +12,6 @@
 #ifndef _ASMARM_TIMEX_H
 #define _ASMARM_TIMEX_H
 
-#ifdef CONFIG_ARCH_MULTIPLATFORM
-#define CLOCK_TICK_RATE 1000000
-#else
-#include <mach/timex.h>
-#endif
-
 typedef unsigned long cycles_t;
 #define get_cycles()	({ cycles_t c; read_current_timer(&c) ? 0 : c; })
 
diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h
index 3bd36e2c5f2e..b5f7705abcb0 100644
--- a/arch/arm/include/asm/trusted_foundations.h
+++ b/arch/arm/include/asm/trusted_foundations.h
@@ -30,6 +30,8 @@
 #include <linux/printk.h>
 #include <linux/bug.h>
 #include <linux/of.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
 
 struct trusted_foundations_platform_data {
 	unsigned int version_major;
@@ -47,10 +49,13 @@ static inline void register_trusted_foundations(
 				   struct trusted_foundations_platform_data *pd)
 {
 	/*
-	 * If we try to register TF, this means the system needs it to continue.
-	 * Its absence if thus a fatal error.
+	 * If the system requires TF and we cannot provide it, continue booting
+	 * but disable features that cannot be provided.
 	 */
-	panic("No support for Trusted Foundations, stopping...\n");
+	pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
+	pr_err("Secondary processors as well as CPU PM will be disabled.\n");
+	setup_max_cpus = 0;
+	cpu_idle_poll_ctrl(true);
 }
 
 static inline void of_register_trusted_foundations(void)
@@ -59,7 +64,7 @@ static inline void of_register_trusted_foundations(void)
 	 * If we find the target should enable TF but does not support it,
 	 * fail as the system won't be able to do much anyway
 	 */
-	if (of_find_compatible_node(NULL, NULL, "tl,trusted-foundations"))
+	if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
 		register_trusted_foundations(NULL);
 }
 #endif /* CONFIG_TRUSTED_FOUNDATIONS */
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 72abdc541f38..12c3a5decc60 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -19,7 +19,7 @@
 #include <asm/unified.h>
 #include <asm/compiler.h>
 
-#if __LINUX_ARM_ARCH__ < 6
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 #include <asm-generic/uaccess-unaligned.h>
 #else
 #define __get_user_unaligned __get_user
diff --git a/arch/arm/include/debug/samsung.S b/arch/arm/include/debug/samsung.S
index f3a9cff6d5d4..8d8d922e5e44 100644
--- a/arch/arm/include/debug/samsung.S
+++ b/arch/arm/include/debug/samsung.S
@@ -9,7 +9,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <plat/regs-serial.h>
+#include <linux/serial_s3c.h>
 
 /* The S5PV210/S5PC110 implementations are as belows. */
 
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index 7dcc10d67253..20d12f230a2f 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -28,4 +28,13 @@
 #define HWCAP_LPAE	(1 << 20)
 #define HWCAP_EVTSTRM	(1 << 21)
 
+/*
+ * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2
+ */
+#define HWCAP2_AES	(1 << 0)
+#define HWCAP2_PMULL	(1 << 1)
+#define HWCAP2_SHA1	(1 << 2)
+#define HWCAP2_SHA2	(1 << 3)
+#define HWCAP2_CRC32	(1 << 4)
+
 #endif /* _UAPI__ASMARM_HWCAP_H */
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 317da88ae65b..16d43cd45619 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -19,7 +19,7 @@
 static int debug_pci;
 
 /*
- * We can't use pci_find_device() here since we are
+ * We can't use pci_get_device() here since we are
  * called from interrupt context.
  */
 static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
@@ -57,13 +57,10 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
 
 void pcibios_report_status(u_int status_mask, int warn)
 {
-	struct list_head *l;
-
-	list_for_each(l, &pci_root_buses) {
-		struct pci_bus *bus = pci_bus_b(l);
+	struct pci_bus *bus;
 
+	list_for_each_entry(bus, &pci_root_buses, node)
 		pcibios_bus_report_status(bus, status_mask, warn);
-	}
 }
 
 /*
@@ -608,41 +605,10 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-
-		r = dev->resource + idx;
-		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because"
-			       " of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	/*
-	 * Bridges (eg, cardbus bridges) need to be fully enabled
-	 */
-	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
-		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+	if (pci_has_flag(PCI_PROBE_ONLY))
+		return 0;
 
-	if (cmd != old_cmd) {
-		printk("PCI: enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
+	return pci_enable_resources(dev, mask);
 }
 
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index f751714d52c1..c7419a585ddc 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -18,6 +18,7 @@
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/smp.h>
 
 #include <asm/cputype.h>
 #include <asm/setup.h>
@@ -63,6 +64,34 @@ void __init arm_dt_memblock_reserve(void)
 	}
 }
 
+#ifdef CONFIG_SMP
+extern struct of_cpu_method __cpu_method_of_table_begin[];
+extern struct of_cpu_method __cpu_method_of_table_end[];
+
+static int __init set_smp_ops_by_method(struct device_node *node)
+{
+	const char *method;
+	struct of_cpu_method *m = __cpu_method_of_table_begin;
+
+	if (of_property_read_string(node, "enable-method", &method))
+		return 0;
+
+	for (; m < __cpu_method_of_table_end; m++)
+		if (!strcmp(m->method, method)) {
+			smp_set_ops(m->ops);
+			return 1;
+		}
+
+	return 0;
+}
+#else
+static inline int set_smp_ops_by_method(struct device_node *node)
+{
+	return 1;
+}
+#endif
+
+
 /*
  * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
  * and builds the cpu logical map array containing MPIDR values related to
@@ -79,6 +108,7 @@ void __init arm_dt_init_cpu_maps(void)
 	 * read as 0.
 	 */
 	struct device_node *cpu, *cpus;
+	int found_method = 0;
 	u32 i, j, cpuidx = 1;
 	u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
 
@@ -150,8 +180,18 @@ void __init arm_dt_init_cpu_maps(void)
 		}
 
 		tmp_map[i] = hwid;
+
+		if (!found_method)
+			found_method = set_smp_ops_by_method(cpu);
 	}
 
+	/*
+	 * Fallback to an enable-method in the cpus node if nothing found in
+	 * a cpu node.
+	 */
+	if (!found_method)
+		set_smp_ops_by_method(cpus);
+
 	if (!bootcpu_valid) {
 		pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n");
 		return;
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 47cd974e57ea..c96ecacb2021 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -177,6 +177,18 @@ __lookup_processor_type_data:
 	.long	__proc_info_end
 	.size	__lookup_processor_type_data, . - __lookup_processor_type_data
 
+__error_lpae:
+#ifdef CONFIG_DEBUG_LL
+	adr	r0, str_lpae
+	bl 	printascii
+	b	__error
+str_lpae: .asciz "\nError: Kernel with LPAE support, but CPU does not support LPAE.\n"
+#else
+	b	__error
+#endif
+	.align
+ENDPROC(__error_lpae)
+
 __error_p:
 #ifdef CONFIG_DEBUG_LL
 	adr	r0, str_p1
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 914616e0bdcd..f5f381d91556 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -102,7 +102,7 @@ ENTRY(stext)
 	and	r3, r3, #0xf			@ extract VMSA support
 	cmp	r3, #5				@ long-descriptor translation table format?
  THUMB( it	lo )				@ force fixup-able long branch encoding
-	blo	__error_p			@ only classic page table format
+	blo	__error_lpae			@ only classic page table format
 #endif
 
 #ifndef CONFIG_XIP_KERNEL
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 3d446605cbf8..9da35c6d3411 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -167,7 +167,7 @@ static int debug_arch_supported(void)
 /* Can we determine the watchpoint access type from the fsr? */
 static int debug_exception_updates_fsr(void)
 {
-	return 0;
+	return get_debug_arch() >= ARM_DEBUG_ARCH_V8;
 }
 
 /* Determine number of WRP registers available. */
@@ -257,6 +257,7 @@ static int enable_monitor_mode(void)
 		break;
 	case ARM_DEBUG_ARCH_V7_ECP14:
 	case ARM_DEBUG_ARCH_V7_1:
+	case ARM_DEBUG_ARCH_V8:
 		ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN));
 		isb();
 		break;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 789d846a9184..a6bc431cde70 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -16,6 +16,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/uaccess.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
 
 #include <asm/irq_regs.h>
 #include <asm/pmu.h>
@@ -205,6 +207,8 @@ armpmu_del(struct perf_event *event, int flags)
 	armpmu_stop(event, PERF_EF_UPDATE);
 	hw_events->events[idx] = NULL;
 	clear_bit(idx, hw_events->used_mask);
+	if (armpmu->clear_event_idx)
+		armpmu->clear_event_idx(hw_events, event);
 
 	perf_event_update_userpage(event);
 }
@@ -295,14 +299,27 @@ validate_group(struct perf_event *event)
 
 static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
 {
-	struct arm_pmu *armpmu = (struct arm_pmu *) dev;
-	struct platform_device *plat_device = armpmu->plat_device;
-	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
+	struct arm_pmu *armpmu;
+	struct platform_device *plat_device;
+	struct arm_pmu_platdata *plat;
+	int ret;
+	u64 start_clock, finish_clock;
 
+	if (irq_is_percpu(irq))
+		dev = *(void **)dev;
+	armpmu = dev;
+	plat_device = armpmu->plat_device;
+	plat = dev_get_platdata(&plat_device->dev);
+
+	start_clock = sched_clock();
 	if (plat && plat->handle_irq)
-		return plat->handle_irq(irq, dev, armpmu->handle_irq);
+		ret = plat->handle_irq(irq, dev, armpmu->handle_irq);
 	else
-		return armpmu->handle_irq(irq, dev);
+		ret = armpmu->handle_irq(irq, dev);
+	finish_clock = sched_clock();
+
+	perf_sample_event_took(finish_clock - start_clock);
+	return ret;
 }
 
 static void
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 20d553c9f5e2..51798d7854ac 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -25,6 +25,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
 
 #include <asm/cputype.h>
 #include <asm/irq_regs.h>
@@ -33,6 +35,7 @@
 /* Set at runtime when we know what CPU type we are. */
 static struct arm_pmu *cpu_pmu;
 
+static DEFINE_PER_CPU(struct arm_pmu *, percpu_pmu);
 static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
 static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
 static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
@@ -71,6 +74,26 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return this_cpu_ptr(&cpu_hw_events);
 }
 
+static void cpu_pmu_enable_percpu_irq(void *data)
+{
+	struct arm_pmu *cpu_pmu = data;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+	int irq = platform_get_irq(pmu_device, 0);
+
+	enable_percpu_irq(irq, IRQ_TYPE_NONE);
+	cpumask_set_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
+}
+
+static void cpu_pmu_disable_percpu_irq(void *data)
+{
+	struct arm_pmu *cpu_pmu = data;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+	int irq = platform_get_irq(pmu_device, 0);
+
+	cpumask_clear_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
+	disable_percpu_irq(irq);
+}
+
 static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
 	int i, irq, irqs;
@@ -78,12 +101,18 @@ static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 
 	irqs = min(pmu_device->num_resources, num_possible_cpus());
 
-	for (i = 0; i < irqs; ++i) {
-		if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
-			continue;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, cpu_pmu);
+	irq = platform_get_irq(pmu_device, 0);
+	if (irq >= 0 && irq_is_percpu(irq)) {
+		on_each_cpu(cpu_pmu_disable_percpu_irq, cpu_pmu, 1);
+		free_percpu_irq(irq, &percpu_pmu);
+	} else {
+		for (i = 0; i < irqs; ++i) {
+			if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
+				continue;
+			irq = platform_get_irq(pmu_device, i);
+			if (irq >= 0)
+				free_irq(irq, cpu_pmu);
+		}
 	}
 }
 
@@ -101,33 +130,44 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 		return -ENODEV;
 	}
 
-	for (i = 0; i < irqs; ++i) {
-		err = 0;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq < 0)
-			continue;
-
-		/*
-		 * If we have a single PMU interrupt that we can't shift,
-		 * assume that we're running on a uniprocessor machine and
-		 * continue. Otherwise, continue without this interrupt.
-		 */
-		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
-			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-				    irq, i);
-			continue;
-		}
-
-		err = request_irq(irq, handler,
-				  IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu",
-				  cpu_pmu);
+	irq = platform_get_irq(pmu_device, 0);
+	if (irq >= 0 && irq_is_percpu(irq)) {
+		err = request_percpu_irq(irq, handler, "arm-pmu", &percpu_pmu);
 		if (err) {
 			pr_err("unable to request IRQ%d for ARM PMU counters\n",
 				irq);
 			return err;
 		}
-
-		cpumask_set_cpu(i, &cpu_pmu->active_irqs);
+		on_each_cpu(cpu_pmu_enable_percpu_irq, cpu_pmu, 1);
+	} else {
+		for (i = 0; i < irqs; ++i) {
+			err = 0;
+			irq = platform_get_irq(pmu_device, i);
+			if (irq < 0)
+				continue;
+
+			/*
+			 * If we have a single PMU interrupt that we can't shift,
+			 * assume that we're running on a uniprocessor machine and
+			 * continue. Otherwise, continue without this interrupt.
+			 */
+			if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+				pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+					    irq, i);
+				continue;
+			}
+
+			err = request_irq(irq, handler,
+					  IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu",
+					  cpu_pmu);
+			if (err) {
+				pr_err("unable to request IRQ%d for ARM PMU counters\n",
+					irq);
+				return err;
+			}
+
+			cpumask_set_cpu(i, &cpu_pmu->active_irqs);
+		}
 	}
 
 	return 0;
@@ -141,6 +181,7 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
 		events->events = per_cpu(hw_events, cpu);
 		events->used_mask = per_cpu(used_mask, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
+		per_cpu(percpu_pmu, cpu) = cpu_pmu;
 	}
 
 	cpu_pmu->get_hw_events	= cpu_pmu_get_cpu_events;
@@ -181,6 +222,7 @@ static struct notifier_block cpu_pmu_hotplug_notifier = {
  */
 static struct of_device_id cpu_pmu_of_device_ids[] = {
 	{.compatible = "arm,cortex-a15-pmu",	.data = armv7_a15_pmu_init},
+	{.compatible = "arm,cortex-a12-pmu",	.data = armv7_a12_pmu_init},
 	{.compatible = "arm,cortex-a9-pmu",	.data = armv7_a9_pmu_init},
 	{.compatible = "arm,cortex-a8-pmu",	.data = armv7_a8_pmu_init},
 	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
@@ -188,6 +230,7 @@ static struct of_device_id cpu_pmu_of_device_ids[] = {
 	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
 	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
 	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
+	{.compatible = "qcom,krait-pmu",	.data = krait_pmu_init},
 	{},
 };
 
@@ -225,15 +268,6 @@ static int probe_current_pmu(struct arm_pmu *pmu)
 		case ARM_CPU_PART_CORTEX_A9:
 			ret = armv7_a9_pmu_init(pmu);
 			break;
-		case ARM_CPU_PART_CORTEX_A5:
-			ret = armv7_a5_pmu_init(pmu);
-			break;
-		case ARM_CPU_PART_CORTEX_A15:
-			ret = armv7_a15_pmu_init(pmu);
-			break;
-		case ARM_CPU_PART_CORTEX_A7:
-			ret = armv7_a7_pmu_init(pmu);
-			break;
 		}
 	/* Intel CPUs [xscale]. */
 	} else if (implementor == ARM_CPU_IMP_INTEL) {
@@ -270,6 +304,9 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	cpu_pmu = pmu;
+	cpu_pmu->plat_device = pdev;
+
 	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
 		init_fn = of_id->data;
 		ret = init_fn(pmu);
@@ -282,8 +319,6 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
 		goto out_free;
 	}
 
-	cpu_pmu = pmu;
-	cpu_pmu->plat_device = pdev;
 	cpu_pmu_init(cpu_pmu);
 	ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW);
 
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 039cffb053a7..f4ef3981ed02 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -18,6 +18,10 @@
 
 #ifdef CONFIG_CPU_V7
 
+#include <asm/cp15.h>
+#include <asm/vfp.h>
+#include "../vfp/vfpinstr.h"
+
 /*
  * Common ARMv7 event types
  *
@@ -109,6 +113,33 @@ enum armv7_a15_perf_types {
 	ARMV7_A15_PERFCTR_PC_WRITE_SPEC			= 0x76,
 };
 
+/* ARMv7 Cortex-A12 specific event types */
+enum armv7_a12_perf_types {
+	ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ		= 0x40,
+	ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE	= 0x41,
+
+	ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ		= 0x50,
+	ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE		= 0x51,
+
+	ARMV7_A12_PERFCTR_PC_WRITE_SPEC			= 0x76,
+
+	ARMV7_A12_PERFCTR_PF_TLB_REFILL			= 0xe7,
+};
+
+/* ARMv7 Krait specific event types */
+enum krait_perf_types {
+	KRAIT_PMRESR0_GROUP0				= 0xcc,
+	KRAIT_PMRESR1_GROUP0				= 0xd0,
+	KRAIT_PMRESR2_GROUP0				= 0xd4,
+	KRAIT_VPMRESR0_GROUP0				= 0xd8,
+
+	KRAIT_PERFCTR_L1_ICACHE_ACCESS			= 0x10011,
+	KRAIT_PERFCTR_L1_ICACHE_MISS			= 0x10010,
+
+	KRAIT_PERFCTR_L1_ITLB_ACCESS			= 0x12222,
+	KRAIT_PERFCTR_L1_DTLB_ACCESS			= 0x12210,
+};
+
 /*
  * Cortex-A8 HW events mapping
  *
@@ -732,6 +763,262 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 };
 
 /*
+ * Cortex-A12 HW events mapping
+ */
+static const unsigned armv7_a12_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_A12_PERFCTR_PC_WRITE_SPEC,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV7_PERFCTR_BUS_CYCLES,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a12_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		/*
+		 * Not all performance counters differentiate between read
+		 * and write accesses/misses so we're not always strictly
+		 * correct, but it's the best we can do. Writes and reads get
+		 * combined in these cases.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_A12_PERFCTR_PF_TLB_REFILL,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Krait HW events mapping
+ */
+static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					  [PERF_COUNT_HW_CACHE_OP_MAX]
+					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		/*
+		 * The performance counters don't differentiate between read
+		 * and write accesses/misses so this isn't strictly correct,
+		 * but it's the best we can do. Writes and reads get
+		 * combined.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= KRAIT_PERFCTR_L1_ICACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
  * Perf Events' indices
  */
 #define	ARMV7_IDX_CYCLE_COUNTER	0
@@ -1212,6 +1499,24 @@ static int armv7_a7_map_event(struct perf_event *event)
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
+static int armv7_a12_map_event(struct perf_event *event)
+{
+	return armpmu_map_event(event, &armv7_a12_perf_map,
+				&armv7_a12_perf_cache_map, 0xFF);
+}
+
+static int krait_map_event(struct perf_event *event)
+{
+	return armpmu_map_event(event, &krait_perf_map,
+				&krait_perf_cache_map, 0xFFFFF);
+}
+
+static int krait_map_event_no_branch(struct perf_event *event)
+{
+	return armpmu_map_event(event, &krait_perf_map_no_branch,
+				&krait_perf_cache_map, 0xFFFFF);
+}
+
 static void armv7pmu_init(struct arm_pmu *cpu_pmu)
 {
 	cpu_pmu->handle_irq	= armv7pmu_handle_irq;
@@ -1283,6 +1588,408 @@ static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
 	return 0;
 }
+
+static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A12";
+	cpu_pmu->map_event	= armv7_a12_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+	return 0;
+}
+
+/*
+ * Krait Performance Monitor Region Event Selection Register (PMRESRn)
+ *
+ *            31   30     24     16     8      0
+ *            +--------------------------------+
+ *  PMRESR0   | EN |  CC  |  CC  |  CC  |  CC  |   N = 1, R = 0
+ *            +--------------------------------+
+ *  PMRESR1   | EN |  CC  |  CC  |  CC  |  CC  |   N = 1, R = 1
+ *            +--------------------------------+
+ *  PMRESR2   | EN |  CC  |  CC  |  CC  |  CC  |   N = 1, R = 2
+ *            +--------------------------------+
+ *  VPMRESR0  | EN |  CC  |  CC  |  CC  |  CC  |   N = 2, R = ?
+ *            +--------------------------------+
+ *              EN | G=3  | G=2  | G=1  | G=0
+ *
+ *  Event Encoding:
+ *
+ *      hwc->config_base = 0xNRCCG
+ *
+ *      N  = prefix, 1 for Krait CPU (PMRESRn), 2 for Venum VFP (VPMRESR)
+ *      R  = region register
+ *      CC = class of events the group G is choosing from
+ *      G  = group or particular event
+ *
+ *  Example: 0x12021 is a Krait CPU event in PMRESR2's group 1 with code 2
+ *
+ *  A region (R) corresponds to a piece of the CPU (execution unit, instruction
+ *  unit, etc.) while the event code (CC) corresponds to a particular class of
+ *  events (interrupts for example). An event code is broken down into
+ *  groups (G) that can be mapped into the PMU (irq, fiqs, and irq+fiqs for
+ *  example).
+ */
+
+#define KRAIT_EVENT		(1 << 16)
+#define VENUM_EVENT		(2 << 16)
+#define KRAIT_EVENT_MASK	(KRAIT_EVENT | VENUM_EVENT)
+#define PMRESRn_EN		BIT(31)
+
+static u32 krait_read_pmresrn(int n)
+{
+	u32 val;
+
+	switch (n) {
+	case 0:
+		asm volatile("mrc p15, 1, %0, c9, c15, 0" : "=r" (val));
+		break;
+	case 1:
+		asm volatile("mrc p15, 1, %0, c9, c15, 1" : "=r" (val));
+		break;
+	case 2:
+		asm volatile("mrc p15, 1, %0, c9, c15, 2" : "=r" (val));
+		break;
+	default:
+		BUG(); /* Should be validated in krait_pmu_get_event_idx() */
+	}
+
+	return val;
+}
+
+static void krait_write_pmresrn(int n, u32 val)
+{
+	switch (n) {
+	case 0:
+		asm volatile("mcr p15, 1, %0, c9, c15, 0" : : "r" (val));
+		break;
+	case 1:
+		asm volatile("mcr p15, 1, %0, c9, c15, 1" : : "r" (val));
+		break;
+	case 2:
+		asm volatile("mcr p15, 1, %0, c9, c15, 2" : : "r" (val));
+		break;
+	default:
+		BUG(); /* Should be validated in krait_pmu_get_event_idx() */
+	}
+}
+
+static u32 krait_read_vpmresr0(void)
+{
+	u32 val;
+	asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
+	return val;
+}
+
+static void krait_write_vpmresr0(u32 val)
+{
+	asm volatile("mcr p10, 7, %0, c11, c0, 0" : : "r" (val));
+}
+
+static void krait_pre_vpmresr0(u32 *venum_orig_val, u32 *fp_orig_val)
+{
+	u32 venum_new_val;
+	u32 fp_new_val;
+
+	BUG_ON(preemptible());
+	/* CPACR Enable CP10 and CP11 access */
+	*venum_orig_val = get_copro_access();
+	venum_new_val = *venum_orig_val | CPACC_SVC(10) | CPACC_SVC(11);
+	set_copro_access(venum_new_val);
+
+	/* Enable FPEXC */
+	*fp_orig_val = fmrx(FPEXC);
+	fp_new_val = *fp_orig_val | FPEXC_EN;
+	fmxr(FPEXC, fp_new_val);
+}
+
+static void krait_post_vpmresr0(u32 venum_orig_val, u32 fp_orig_val)
+{
+	BUG_ON(preemptible());
+	/* Restore FPEXC */
+	fmxr(FPEXC, fp_orig_val);
+	isb();
+	/* Restore CPACR */
+	set_copro_access(venum_orig_val);
+}
+
+static u32 krait_get_pmresrn_event(unsigned int region)
+{
+	static const u32 pmresrn_table[] = { KRAIT_PMRESR0_GROUP0,
+					     KRAIT_PMRESR1_GROUP0,
+					     KRAIT_PMRESR2_GROUP0 };
+	return pmresrn_table[region];
+}
+
+static void krait_evt_setup(int idx, u32 config_base)
+{
+	u32 val;
+	u32 mask;
+	u32 vval, fval;
+	unsigned int region;
+	unsigned int group;
+	unsigned int code;
+	unsigned int group_shift;
+	bool venum_event;
+
+	venum_event = !!(config_base & VENUM_EVENT);
+	region = (config_base >> 12) & 0xf;
+	code   = (config_base >> 4) & 0xff;
+	group  = (config_base >> 0)  & 0xf;
+
+	group_shift = group * 8;
+	mask = 0xff << group_shift;
+
+	/* Configure evtsel for the region and group */
+	if (venum_event)
+		val = KRAIT_VPMRESR0_GROUP0;
+	else
+		val = krait_get_pmresrn_event(region);
+	val += group;
+	/* Mix in mode-exclusion bits */
+	val |= config_base & (ARMV7_EXCLUDE_USER | ARMV7_EXCLUDE_PL1);
+	armv7_pmnc_write_evtsel(idx, val);
+
+	asm volatile("mcr p15, 0, %0, c9, c15, 0" : : "r" (0));
+
+	if (venum_event) {
+		krait_pre_vpmresr0(&vval, &fval);
+		val = krait_read_vpmresr0();
+		val &= ~mask;
+		val |= code << group_shift;
+		val |= PMRESRn_EN;
+		krait_write_vpmresr0(val);
+		krait_post_vpmresr0(vval, fval);
+	} else {
+		val = krait_read_pmresrn(region);
+		val &= ~mask;
+		val |= code << group_shift;
+		val |= PMRESRn_EN;
+		krait_write_pmresrn(region, val);
+	}
+}
+
+static u32 krait_clear_pmresrn_group(u32 val, int group)
+{
+	u32 mask;
+	int group_shift;
+
+	group_shift = group * 8;
+	mask = 0xff << group_shift;
+	val &= ~mask;
+
+	/* Don't clear enable bit if entire region isn't disabled */
+	if (val & ~PMRESRn_EN)
+		return val |= PMRESRn_EN;
+
+	return 0;
+}
+
+static void krait_clearpmu(u32 config_base)
+{
+	u32 val;
+	u32 vval, fval;
+	unsigned int region;
+	unsigned int group;
+	bool venum_event;
+
+	venum_event = !!(config_base & VENUM_EVENT);
+	region = (config_base >> 12) & 0xf;
+	group  = (config_base >> 0)  & 0xf;
+
+	if (venum_event) {
+		krait_pre_vpmresr0(&vval, &fval);
+		val = krait_read_vpmresr0();
+		val = krait_clear_pmresrn_group(val, group);
+		krait_write_vpmresr0(val);
+		krait_post_vpmresr0(vval, fval);
+	} else {
+		val = krait_read_pmresrn(region);
+		val = krait_clear_pmresrn_group(val, group);
+		krait_write_pmresrn(region, val);
+	}
+}
+
+static void krait_pmu_disable_event(struct perf_event *event)
+{
+	unsigned long flags;
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	/* Disable counter and interrupt */
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/* Disable counter */
+	armv7_pmnc_disable_counter(idx);
+
+	/*
+	 * Clear pmresr code (if destined for PMNx counters)
+	 */
+	if (hwc->config_base & KRAIT_EVENT_MASK)
+		krait_clearpmu(hwc->config_base);
+
+	/* Disable interrupt for this counter */
+	armv7_pmnc_disable_intens(idx);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void krait_pmu_enable_event(struct perf_event *event)
+{
+	unsigned long flags;
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	/*
+	 * Enable counter and interrupt, and set the counter to count
+	 * the event that we're interested in.
+	 */
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/* Disable counter */
+	armv7_pmnc_disable_counter(idx);
+
+	/*
+	 * Set event (if destined for PMNx counters)
+	 * We set the event for the cycle counter because we
+	 * have the ability to perform event filtering.
+	 */
+	if (hwc->config_base & KRAIT_EVENT_MASK)
+		krait_evt_setup(idx, hwc->config_base);
+	else
+		armv7_pmnc_write_evtsel(idx, hwc->config_base);
+
+	/* Enable interrupt for this counter */
+	armv7_pmnc_enable_intens(idx);
+
+	/* Enable counter */
+	armv7_pmnc_enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void krait_pmu_reset(void *info)
+{
+	u32 vval, fval;
+
+	armv7pmu_reset(info);
+
+	/* Clear all pmresrs */
+	krait_write_pmresrn(0, 0);
+	krait_write_pmresrn(1, 0);
+	krait_write_pmresrn(2, 0);
+
+	krait_pre_vpmresr0(&vval, &fval);
+	krait_write_vpmresr0(0);
+	krait_post_vpmresr0(vval, fval);
+}
+
+static int krait_event_to_bit(struct perf_event *event, unsigned int region,
+			      unsigned int group)
+{
+	int bit;
+	struct hw_perf_event *hwc = &event->hw;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+
+	if (hwc->config_base & VENUM_EVENT)
+		bit = KRAIT_VPMRESR0_GROUP0;
+	else
+		bit = krait_get_pmresrn_event(region);
+	bit -= krait_get_pmresrn_event(0);
+	bit += group;
+	/*
+	 * Lower bits are reserved for use by the counters (see
+	 * armv7pmu_get_event_idx() for more info)
+	 */
+	bit += ARMV7_IDX_COUNTER_LAST(cpu_pmu) + 1;
+
+	return bit;
+}
+
+/*
+ * We check for column exclusion constraints here.
+ * Two events cant use the same group within a pmresr register.
+ */
+static int krait_pmu_get_event_idx(struct pmu_hw_events *cpuc,
+				   struct perf_event *event)
+{
+	int idx;
+	int bit;
+	unsigned int prefix;
+	unsigned int region;
+	unsigned int code;
+	unsigned int group;
+	bool krait_event;
+	struct hw_perf_event *hwc = &event->hw;
+
+	region = (hwc->config_base >> 12) & 0xf;
+	code   = (hwc->config_base >> 4) & 0xff;
+	group  = (hwc->config_base >> 0) & 0xf;
+	krait_event = !!(hwc->config_base & KRAIT_EVENT_MASK);
+
+	if (krait_event) {
+		/* Ignore invalid events */
+		if (group > 3 || region > 2)
+			return -EINVAL;
+		prefix = hwc->config_base & KRAIT_EVENT_MASK;
+		if (prefix != KRAIT_EVENT && prefix != VENUM_EVENT)
+			return -EINVAL;
+		if (prefix == VENUM_EVENT && (code & 0xe0))
+			return -EINVAL;
+
+		bit = krait_event_to_bit(event, region, group);
+		if (test_and_set_bit(bit, cpuc->used_mask))
+			return -EAGAIN;
+	}
+
+	idx = armv7pmu_get_event_idx(cpuc, event);
+	if (idx < 0 && krait_event)
+		clear_bit(bit, cpuc->used_mask);
+
+	return idx;
+}
+
+static void krait_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
+				      struct perf_event *event)
+{
+	int bit;
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned int region;
+	unsigned int group;
+	bool krait_event;
+
+	region = (hwc->config_base >> 12) & 0xf;
+	group  = (hwc->config_base >> 0) & 0xf;
+	krait_event = !!(hwc->config_base & KRAIT_EVENT_MASK);
+
+	if (krait_event) {
+		bit = krait_event_to_bit(event, region, group);
+		clear_bit(bit, cpuc->used_mask);
+	}
+}
+
+static int krait_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Krait";
+	/* Some early versions of Krait don't support PC write events */
+	if (of_property_read_bool(cpu_pmu->plat_device->dev.of_node,
+				  "qcom,no-pc-write"))
+		cpu_pmu->map_event = krait_map_event_no_branch;
+	else
+		cpu_pmu->map_event = krait_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+	cpu_pmu->reset		= krait_pmu_reset;
+	cpu_pmu->enable		= krait_pmu_enable_event;
+	cpu_pmu->disable	= krait_pmu_disable_event;
+	cpu_pmu->get_event_idx	= krait_pmu_get_event_idx;
+	cpu_pmu->clear_event_idx = krait_pmu_clear_event_idx;
+	return 0;
+}
 #else
 static inline int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
@@ -1308,4 +2015,14 @@ static inline int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	return -ENODEV;
 }
+
+static inline int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	return -ENODEV;
+}
+
+static inline int krait_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	return -ENODEV;
+}
 #endif	/* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 92f7b15dd221..806d287e3e53 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -30,7 +30,6 @@
 #include <linux/uaccess.h>
 #include <linux/random.h>
 #include <linux/hw_breakpoint.h>
-#include <linux/cpuidle.h>
 #include <linux/leds.h>
 #include <linux/reboot.h>
 
@@ -48,14 +47,14 @@ unsigned long __stack_chk_guard __read_mostly;
 EXPORT_SYMBOL(__stack_chk_guard);
 #endif
 
-static const char *processor_modes[] = {
+static const char *processor_modes[] __maybe_unused = {
   "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
   "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
   "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
-static const char *isa_modes[] = {
+static const char *isa_modes[] __maybe_unused = {
   "ARM" , "Thumb" , "Jazelle", "ThumbEE"
 };
 
@@ -133,7 +132,11 @@ EXPORT_SYMBOL_GPL(arm_pm_restart);
 
 void (*arm_pm_idle)(void);
 
-static void default_idle(void)
+/*
+ * Called from the core idle loop.
+ */
+
+void arch_cpu_idle(void)
 {
 	if (arm_pm_idle)
 		arm_pm_idle();
@@ -168,15 +171,6 @@ void arch_cpu_idle_dead(void)
 #endif
 
 /*
- * Called from the core idle loop.
- */
-void arch_cpu_idle(void)
-{
-	if (cpuidle_idle_call())
-		default_idle();
-}
-
-/*
  * Called by kexec, immediately prior to machine_kexec().
  *
  * This must completely disable all secondary CPUs; simply causing those CPUs
@@ -276,12 +270,17 @@ void __show_regs(struct pt_regs *regs)
 	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
 	buf[4] = '\0';
 
+#ifndef CONFIG_CPU_V7M
 	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
 		buf, interrupts_enabled(regs) ? "n" : "ff",
 		fast_interrupts_enabled(regs) ? "n" : "ff",
 		processor_modes[processor_mode(regs)],
 		isa_modes[isa_mode(regs)],
 		get_fs() == get_ds() ? "kernel" : "user");
+#else
+	printk("xPSR: %08lx\n", regs->ARM_cpsr);
+#endif
+
 #ifdef CONFIG_CPU_CP15
 	{
 		unsigned int ctrl;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1e8b030dbefd..50e198c1e9c8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -100,6 +100,9 @@ EXPORT_SYMBOL(system_serial_high);
 unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL(elf_hwcap);
 
+unsigned int elf_hwcap2 __read_mostly;
+EXPORT_SYMBOL(elf_hwcap2);
+
 
 #ifdef MULTI_CPU
 struct processor processor __read_mostly;
@@ -1005,6 +1008,15 @@ static const char *hwcap_str[] = {
 	NULL
 };
 
+static const char *hwcap2_str[] = {
+	"aes",
+	"pmull",
+	"sha1",
+	"sha2",
+	"crc32",
+	NULL
+};
+
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
@@ -1028,6 +1040,10 @@ static int c_show(struct seq_file *m, void *v)
 			if (elf_hwcap & (1 << j))
 				seq_printf(m, "%s ", hwcap_str[j]);
 
+		for (j = 0; hwcap2_str[j]; j++)
+			if (elf_hwcap2 & (1 << j))
+				seq_printf(m, "%s ", hwcap2_str[j]);
+
 		seq_printf(m, "\nCPU implementer\t: 0x%02x\n", cpuid >> 24);
 		seq_printf(m, "CPU architecture: %s\n",
 			   proc_arch[cpu_architecture()]);
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 3e94811690ce..702bd329d9d0 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -203,6 +203,9 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
 	int ret;
 
 	switch (cmd) {
+	case F_GETLKP:
+	case F_SETLKP:
+	case F_SETLKPW:
 	case F_GETLK64:
 	case F_SETLK64:
 	case F_SETLKW64:
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index 00df012c4678..3c217694ebec 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -68,6 +68,12 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
 struct unwind_ctrl_block {
 	unsigned long vrs[16];		/* virtual register set */
 	const unsigned long *insn;	/* pointer to the current instructions word */
+	unsigned long sp_high;		/* highest value of sp allowed */
+	/*
+	 * 1 : check for stack overflow for each register pop.
+	 * 0 : save overhead if there is plenty of stack remaining.
+	 */
+	int check_each_pop;
 	int entries;			/* number of entries left to interpret */
 	int byte;			/* current byte number in the instructions word */
 };
@@ -235,12 +241,85 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
 	return ret;
 }
 
+/* Before poping a register check whether it is feasible or not */
+static int unwind_pop_register(struct unwind_ctrl_block *ctrl,
+				unsigned long **vsp, unsigned int reg)
+{
+	if (unlikely(ctrl->check_each_pop))
+		if (*vsp >= (unsigned long *)ctrl->sp_high)
+			return -URC_FAILURE;
+
+	ctrl->vrs[reg] = *(*vsp)++;
+	return URC_OK;
+}
+
+/* Helper functions to execute the instructions */
+static int unwind_exec_pop_subset_r4_to_r13(struct unwind_ctrl_block *ctrl,
+						unsigned long mask)
+{
+	unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+	int load_sp, reg = 4;
+
+	load_sp = mask & (1 << (13 - 4));
+	while (mask) {
+		if (mask & 1)
+			if (unwind_pop_register(ctrl, &vsp, reg))
+				return -URC_FAILURE;
+		mask >>= 1;
+		reg++;
+	}
+	if (!load_sp)
+		ctrl->vrs[SP] = (unsigned long)vsp;
+
+	return URC_OK;
+}
+
+static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl,
+					unsigned long insn)
+{
+	unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+	int reg;
+
+	/* pop R4-R[4+bbb] */
+	for (reg = 4; reg <= 4 + (insn & 7); reg++)
+		if (unwind_pop_register(ctrl, &vsp, reg))
+				return -URC_FAILURE;
+
+	if (insn & 0x80)
+		if (unwind_pop_register(ctrl, &vsp, 14))
+				return -URC_FAILURE;
+
+	ctrl->vrs[SP] = (unsigned long)vsp;
+
+	return URC_OK;
+}
+
+static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl,
+						unsigned long mask)
+{
+	unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+	int reg = 0;
+
+	/* pop R0-R3 according to mask */
+	while (mask) {
+		if (mask & 1)
+			if (unwind_pop_register(ctrl, &vsp, reg))
+				return -URC_FAILURE;
+		mask >>= 1;
+		reg++;
+	}
+	ctrl->vrs[SP] = (unsigned long)vsp;
+
+	return URC_OK;
+}
+
 /*
  * Execute the current unwind instruction.
  */
 static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 {
 	unsigned long insn = unwind_get_byte(ctrl);
+	int ret = URC_OK;
 
 	pr_debug("%s: insn = %08lx\n", __func__, insn);
 
@@ -250,8 +329,6 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 		ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4;
 	else if ((insn & 0xf0) == 0x80) {
 		unsigned long mask;
-		unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
-		int load_sp, reg = 4;
 
 		insn = (insn << 8) | unwind_get_byte(ctrl);
 		mask = insn & 0x0fff;
@@ -261,29 +338,16 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 			return -URC_FAILURE;
 		}
 
-		/* pop R4-R15 according to mask */
-		load_sp = mask & (1 << (13 - 4));
-		while (mask) {
-			if (mask & 1)
-				ctrl->vrs[reg] = *vsp++;
-			mask >>= 1;
-			reg++;
-		}
-		if (!load_sp)
-			ctrl->vrs[SP] = (unsigned long)vsp;
+		ret = unwind_exec_pop_subset_r4_to_r13(ctrl, mask);
+		if (ret)
+			goto error;
 	} else if ((insn & 0xf0) == 0x90 &&
 		   (insn & 0x0d) != 0x0d)
 		ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f];
 	else if ((insn & 0xf0) == 0xa0) {
-		unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
-		int reg;
-
-		/* pop R4-R[4+bbb] */
-		for (reg = 4; reg <= 4 + (insn & 7); reg++)
-			ctrl->vrs[reg] = *vsp++;
-		if (insn & 0x80)
-			ctrl->vrs[14] = *vsp++;
-		ctrl->vrs[SP] = (unsigned long)vsp;
+		ret = unwind_exec_pop_r4_to_rN(ctrl, insn);
+		if (ret)
+			goto error;
 	} else if (insn == 0xb0) {
 		if (ctrl->vrs[PC] == 0)
 			ctrl->vrs[PC] = ctrl->vrs[LR];
@@ -291,8 +355,6 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 		ctrl->entries = 0;
 	} else if (insn == 0xb1) {
 		unsigned long mask = unwind_get_byte(ctrl);
-		unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
-		int reg = 0;
 
 		if (mask == 0 || mask & 0xf0) {
 			pr_warning("unwind: Spare encoding %04lx\n",
@@ -300,14 +362,9 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 			return -URC_FAILURE;
 		}
 
-		/* pop R0-R3 according to mask */
-		while (mask) {
-			if (mask & 1)
-				ctrl->vrs[reg] = *vsp++;
-			mask >>= 1;
-			reg++;
-		}
-		ctrl->vrs[SP] = (unsigned long)vsp;
+		ret = unwind_exec_pop_subset_r0_to_r3(ctrl, mask);
+		if (ret)
+			goto error;
 	} else if (insn == 0xb2) {
 		unsigned long uleb128 = unwind_get_byte(ctrl);
 
@@ -320,7 +377,8 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 	pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__,
 		 ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]);
 
-	return URC_OK;
+error:
+	return ret;
 }
 
 /*
@@ -329,13 +387,13 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
  */
 int unwind_frame(struct stackframe *frame)
 {
-	unsigned long high, low;
+	unsigned long low;
 	const struct unwind_idx *idx;
 	struct unwind_ctrl_block ctrl;
 
-	/* only go to a higher address on the stack */
+	/* store the highest address on the stack to avoid crossing it*/
 	low = frame->sp;
-	high = ALIGN(low, THREAD_SIZE);
+	ctrl.sp_high = ALIGN(low, THREAD_SIZE);
 
 	pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__,
 		 frame->pc, frame->lr, frame->sp);
@@ -382,11 +440,16 @@ int unwind_frame(struct stackframe *frame)
 		return -URC_FAILURE;
 	}
 
+	ctrl.check_each_pop = 0;
+
 	while (ctrl.entries > 0) {
-		int urc = unwind_exec_insn(&ctrl);
+		int urc;
+		if ((ctrl.sp_high - ctrl.vrs[SP]) < sizeof(ctrl.vrs))
+			ctrl.check_each_pop = 1;
+		urc = unwind_exec_insn(&ctrl);
 		if (urc < 0)
 			return urc;
-		if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
+		if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= ctrl.sp_high)
 			return -URC_FAILURE;
 	}
 
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index 52886b89706c..9f12ed1eea86 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -37,6 +37,11 @@ UNWIND(	.fnstart	)
 	add	r1, r1, r0, lsl #2	@ Get word offset
 	mov	r3, r2, lsl r3		@ create mask
 	smp_dmb
+#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+	.arch_extension	mp
+	ALT_SMP(W(pldw)	[r1])
+	ALT_UP(W(nop))
+#endif
 1:	ldrex	r2, [r1]
 	ands	r0, r2, r3		@ save old value of bit
 	\instr	r2, r2, r3		@ toggle bit
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
index 805e3f8fb007..3bc8eb811a73 100644
--- a/arch/arm/lib/copy_template.S
+++ b/arch/arm/lib/copy_template.S
@@ -197,24 +197,24 @@
 
 12:	PLD(	pld	[r1, #124]		)
 13:		ldr4w	r1, r4, r5, r6, r7, abort=19f
-		mov	r3, lr, pull #\pull
+		mov	r3, lr, lspull #\pull
 		subs	r2, r2, #32
 		ldr4w	r1, r8, r9, ip, lr, abort=19f
-		orr	r3, r3, r4, push #\push
-		mov	r4, r4, pull #\pull
-		orr	r4, r4, r5, push #\push
-		mov	r5, r5, pull #\pull
-		orr	r5, r5, r6, push #\push
-		mov	r6, r6, pull #\pull
-		orr	r6, r6, r7, push #\push
-		mov	r7, r7, pull #\pull
-		orr	r7, r7, r8, push #\push
-		mov	r8, r8, pull #\pull
-		orr	r8, r8, r9, push #\push
-		mov	r9, r9, pull #\pull
-		orr	r9, r9, ip, push #\push
-		mov	ip, ip, pull #\pull
-		orr	ip, ip, lr, push #\push
+		orr	r3, r3, r4, lspush #\push
+		mov	r4, r4, lspull #\pull
+		orr	r4, r4, r5, lspush #\push
+		mov	r5, r5, lspull #\pull
+		orr	r5, r5, r6, lspush #\push
+		mov	r6, r6, lspull #\pull
+		orr	r6, r6, r7, lspush #\push
+		mov	r7, r7, lspull #\pull
+		orr	r7, r7, r8, lspush #\push
+		mov	r8, r8, lspull #\pull
+		orr	r8, r8, r9, lspush #\push
+		mov	r9, r9, lspull #\pull
+		orr	r9, r9, ip, lspush #\push
+		mov	ip, ip, lspull #\pull
+		orr	ip, ip, lr, lspush #\push
 		str8w	r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
 		bge	12b
 	PLD(	cmn	r2, #96			)
@@ -225,10 +225,10 @@
 14:		ands	ip, r2, #28
 		beq	16f
 
-15:		mov	r3, lr, pull #\pull
+15:		mov	r3, lr, lspull #\pull
 		ldr1w	r1, lr, abort=21f
 		subs	ip, ip, #4
-		orr	r3, r3, lr, push #\push
+		orr	r3, r3, lr, lspush #\push
 		str1w	r0, r3, abort=21f
 		bgt	15b
 	CALGN(	cmp	r2, #0			)
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
index d620a5f22a09..d6e742d24007 100644
--- a/arch/arm/lib/csumpartialcopygeneric.S
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -141,7 +141,7 @@ FN_ENTRY
 		tst	len, #2
 		mov	r5, r4, get_byte_0
 		beq	.Lexit
-		adcs	sum, sum, r4, push #16
+		adcs	sum, sum, r4, lspush #16
 		strb	r5, [dst], #1
 		mov	r5, r4, get_byte_1
 		strb	r5, [dst], #1
@@ -171,23 +171,23 @@ FN_ENTRY
 		cmp	ip, #2
 		beq	.Lsrc2_aligned
 		bhi	.Lsrc3_aligned
-		mov	r4, r5, pull #8		@ C = 0
+		mov	r4, r5, lspull #8		@ C = 0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, push #24
-		mov	r5, r5, pull #8
-		orr	r5, r5, r6, push #24
-		mov	r6, r6, pull #8
-		orr	r6, r6, r7, push #24
-		mov	r7, r7, pull #8
-		orr	r7, r7, r8, push #24
+		orr	r4, r4, r5, lspush #24
+		mov	r5, r5, lspull #8
+		orr	r5, r5, r6, lspush #24
+		mov	r6, r6, lspull #8
+		orr	r6, r6, r7, lspush #24
+		mov	r7, r7, lspull #8
+		orr	r7, r7, r8, lspush #24
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, pull #8
+		mov	r4, r8, lspull #8
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -196,50 +196,50 @@ FN_ENTRY
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, push #24
-		mov	r5, r5, pull #8
-		orr	r5, r5, r6, push #24
+		orr	r4, r4, r5, lspush #24
+		mov	r5, r5, lspull #8
+		orr	r5, r5, r6, lspush #24
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, pull #8
+		mov	r4, r6, lspull #8
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, push #24
+		orr	r4, r4, r5, lspush #24
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, pull #8
+		mov	r4, r5, lspull #8
 4:		ands	len, len, #3
 		beq	.Ldone
 		mov	r5, r4, get_byte_0
 		tst	len, #2
 		beq	.Lexit
-		adcs	sum, sum, r4, push #16
+		adcs	sum, sum, r4, lspush #16
 		strb	r5, [dst], #1
 		mov	r5, r4, get_byte_1
 		strb	r5, [dst], #1
 		mov	r5, r4, get_byte_2
 		b	.Lexit
 
-.Lsrc2_aligned:	mov	r4, r5, pull #16
+.Lsrc2_aligned:	mov	r4, r5, lspull #16
 		adds	sum, sum, #0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, push #16
-		mov	r5, r5, pull #16
-		orr	r5, r5, r6, push #16
-		mov	r6, r6, pull #16
-		orr	r6, r6, r7, push #16
-		mov	r7, r7, pull #16
-		orr	r7, r7, r8, push #16
+		orr	r4, r4, r5, lspush #16
+		mov	r5, r5, lspull #16
+		orr	r5, r5, r6, lspush #16
+		mov	r6, r6, lspull #16
+		orr	r6, r6, r7, lspush #16
+		mov	r7, r7, lspull #16
+		orr	r7, r7, r8, lspush #16
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, pull #16
+		mov	r4, r8, lspull #16
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -248,20 +248,20 @@ FN_ENTRY
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, push #16
-		mov	r5, r5, pull #16
-		orr	r5, r5, r6, push #16
+		orr	r4, r4, r5, lspush #16
+		mov	r5, r5, lspull #16
+		orr	r5, r5, r6, lspush #16
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, pull #16
+		mov	r4, r6, lspull #16
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, push #16
+		orr	r4, r4, r5, lspush #16
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, pull #16
+		mov	r4, r5, lspull #16
 4:		ands	len, len, #3
 		beq	.Ldone
 		mov	r5, r4, get_byte_0
@@ -276,24 +276,24 @@ FN_ENTRY
 		load1b	r5
 		b	.Lexit
 
-.Lsrc3_aligned:	mov	r4, r5, pull #24
+.Lsrc3_aligned:	mov	r4, r5, lspull #24
 		adds	sum, sum, #0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, push #8
-		mov	r5, r5, pull #24
-		orr	r5, r5, r6, push #8
-		mov	r6, r6, pull #24
-		orr	r6, r6, r7, push #8
-		mov	r7, r7, pull #24
-		orr	r7, r7, r8, push #8
+		orr	r4, r4, r5, lspush #8
+		mov	r5, r5, lspull #24
+		orr	r5, r5, r6, lspush #8
+		mov	r6, r6, lspull #24
+		orr	r6, r6, r7, lspush #8
+		mov	r7, r7, lspull #24
+		orr	r7, r7, r8, lspush #8
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, pull #24
+		mov	r4, r8, lspull #24
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -302,20 +302,20 @@ FN_ENTRY
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, push #8
-		mov	r5, r5, pull #24
-		orr	r5, r5, r6, push #8
+		orr	r4, r4, r5, lspush #8
+		mov	r5, r5, lspull #24
+		orr	r5, r5, r6, lspush #8
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, pull #24
+		mov	r4, r6, lspull #24
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, push #8
+		orr	r4, r4, r5, lspush #8
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, pull #24
+		mov	r4, r5, lspull #24
 4:		ands	len, len, #3
 		beq	.Ldone
 		mov	r5, r4, get_byte_0
@@ -326,7 +326,7 @@ FN_ENTRY
 		load1l	r4
 		mov	r5, r4, get_byte_0
 		strb	r5, [dst], #1
-		adcs	sum, sum, r4, push #24
+		adcs	sum, sum, r4, lspush #24
 		mov	r5, r4, get_byte_1
 		b	.Lexit
 FN_EXIT
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
index 5fb97e7f9f4b..7a7430950c79 100644
--- a/arch/arm/lib/io-readsl.S
+++ b/arch/arm/lib/io-readsl.S
@@ -47,25 +47,25 @@ ENTRY(__raw_readsl)
 		strb	ip, [r1], #1
 
 4:		subs	r2, r2, #1
-		mov	ip, r3, pull #24
+		mov	ip, r3, lspull #24
 		ldrne	r3, [r0]
-		orrne	ip, ip, r3, push #8
+		orrne	ip, ip, r3, lspush #8
 		strne	ip, [r1], #4
 		bne	4b
 		b	8f
 
 5:		subs	r2, r2, #1
-		mov	ip, r3, pull #16
+		mov	ip, r3, lspull #16
 		ldrne	r3, [r0]
-		orrne	ip, ip, r3, push #16
+		orrne	ip, ip, r3, lspush #16
 		strne	ip, [r1], #4
 		bne	5b
 		b	7f
 
 6:		subs	r2, r2, #1
-		mov	ip, r3, pull #8
+		mov	ip, r3, lspull #8
 		ldrne	r3, [r0]
-		orrne	ip, ip, r3, push #24
+		orrne	ip, ip, r3, lspush #24
 		strne	ip, [r1], #4
 		bne	6b
 
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
index 8d3b7813725c..d0d104a0dd11 100644
--- a/arch/arm/lib/io-writesl.S
+++ b/arch/arm/lib/io-writesl.S
@@ -41,26 +41,26 @@ ENTRY(__raw_writesl)
 		blt	5f
 		bgt	6f
 
-4:		mov	ip, r3, pull #16
+4:		mov	ip, r3, lspull #16
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, push #16
+		orr	ip, ip, r3, lspush #16
 		str	ip, [r0]
 		bne	4b
 		mov	pc, lr
 
-5:		mov	ip, r3, pull #8
+5:		mov	ip, r3, lspull #8
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, push #24
+		orr	ip, ip, r3, lspush #24
 		str	ip, [r0]
 		bne	5b
 		mov	pc, lr
 
-6:		mov	ip, r3, pull #24
+6:		mov	ip, r3, lspull #24
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, push #8
+		orr	ip, ip, r3, lspush #8
 		str	ip, [r0]
 		bne	6b
 		mov	pc, lr
diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S
index 938fc14f962d..d1fc0c0c342c 100644
--- a/arch/arm/lib/memmove.S
+++ b/arch/arm/lib/memmove.S
@@ -147,24 +147,24 @@ ENTRY(memmove)
 
 12:	PLD(	pld	[r1, #-128]		)
 13:		ldmdb   r1!, {r7, r8, r9, ip}
-		mov     lr, r3, push #\push
+		mov     lr, r3, lspush #\push
 		subs    r2, r2, #32
 		ldmdb   r1!, {r3, r4, r5, r6}
-		orr     lr, lr, ip, pull #\pull
-		mov     ip, ip, push #\push
-		orr     ip, ip, r9, pull #\pull
-		mov     r9, r9, push #\push
-		orr     r9, r9, r8, pull #\pull
-		mov     r8, r8, push #\push
-		orr     r8, r8, r7, pull #\pull
-		mov     r7, r7, push #\push
-		orr     r7, r7, r6, pull #\pull
-		mov     r6, r6, push #\push
-		orr     r6, r6, r5, pull #\pull
-		mov     r5, r5, push #\push
-		orr     r5, r5, r4, pull #\pull
-		mov     r4, r4, push #\push
-		orr     r4, r4, r3, pull #\pull
+		orr     lr, lr, ip, lspull #\pull
+		mov     ip, ip, lspush #\push
+		orr     ip, ip, r9, lspull #\pull
+		mov     r9, r9, lspush #\push
+		orr     r9, r9, r8, lspull #\pull
+		mov     r8, r8, lspush #\push
+		orr     r8, r8, r7, lspull #\pull
+		mov     r7, r7, lspush #\push
+		orr     r7, r7, r6, lspull #\pull
+		mov     r6, r6, lspush #\push
+		orr     r6, r6, r5, lspull #\pull
+		mov     r5, r5, lspush #\push
+		orr     r5, r5, r4, lspull #\pull
+		mov     r4, r4, lspush #\push
+		orr     r4, r4, r3, lspull #\pull
 		stmdb   r0!, {r4 - r9, ip, lr}
 		bge	12b
 	PLD(	cmn	r2, #96			)
@@ -175,10 +175,10 @@ ENTRY(memmove)
 14:		ands	ip, r2, #28
 		beq	16f
 
-15:		mov     lr, r3, push #\push
+15:		mov     lr, r3, lspush #\push
 		ldr	r3, [r1, #-4]!
 		subs	ip, ip, #4
-		orr	lr, lr, r3, pull #\pull
+		orr	lr, lr, r3, lspull #\pull
 		str	lr, [r0, #-4]!
 		bgt	15b
 	CALGN(	cmp	r2, #0			)
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index 5c908b1cb8ed..e50520904b76 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -117,9 +117,9 @@ USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault
 .Lc2u_1fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lc2u_1nowords
-		mov	r3, r7, pull #8
+		mov	r3, r7, lspull #8
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, push #24
+		orr	r3, r3, r7, lspush #24
 USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -131,30 +131,30 @@ USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		subs	ip, ip, #16
 		blt	.Lc2u_1rem8lp
 
-.Lc2u_1cpy8lp:	mov	r3, r7, pull #8
+.Lc2u_1cpy8lp:	mov	r3, r7, lspull #8
 		ldmia	r1!, {r4 - r7}
 		subs	ip, ip, #16
-		orr	r3, r3, r4, push #24
-		mov	r4, r4, pull #8
-		orr	r4, r4, r5, push #24
-		mov	r5, r5, pull #8
-		orr	r5, r5, r6, push #24
-		mov	r6, r6, pull #8
-		orr	r6, r6, r7, push #24
+		orr	r3, r3, r4, lspush #24
+		mov	r4, r4, lspull #8
+		orr	r4, r4, r5, lspush #24
+		mov	r5, r5, lspull #8
+		orr	r5, r5, r6, lspush #24
+		mov	r6, r6, lspull #8
+		orr	r6, r6, r7, lspush #24
 		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.Lc2u_1cpy8lp
 
 .Lc2u_1rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #8
+		movne	r3, r7, lspull #8
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, push #24
-		movne	r4, r4, pull #8
-		orrne	r4, r4, r7, push #24
+		orrne	r3, r3, r4, lspush #24
+		movne	r4, r4, lspull #8
+		orrne	r4, r4, r7, lspush #24
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, pull #8
+		movne	r3, r7, lspull #8
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, push #24
+		orrne	r3, r3, r7, lspush #24
 	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_1fupi
@@ -172,9 +172,9 @@ USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault
 .Lc2u_2fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lc2u_2nowords
-		mov	r3, r7, pull #16
+		mov	r3, r7, lspull #16
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, push #16
+		orr	r3, r3, r7, lspush #16
 USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -186,30 +186,30 @@ USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		subs	ip, ip, #16
 		blt	.Lc2u_2rem8lp
 
-.Lc2u_2cpy8lp:	mov	r3, r7, pull #16
+.Lc2u_2cpy8lp:	mov	r3, r7, lspull #16
 		ldmia	r1!, {r4 - r7}
 		subs	ip, ip, #16
-		orr	r3, r3, r4, push #16
-		mov	r4, r4, pull #16
-		orr	r4, r4, r5, push #16
-		mov	r5, r5, pull #16
-		orr	r5, r5, r6, push #16
-		mov	r6, r6, pull #16
-		orr	r6, r6, r7, push #16
+		orr	r3, r3, r4, lspush #16
+		mov	r4, r4, lspull #16
+		orr	r4, r4, r5, lspush #16
+		mov	r5, r5, lspull #16
+		orr	r5, r5, r6, lspush #16
+		mov	r6, r6, lspull #16
+		orr	r6, r6, r7, lspush #16
 		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.Lc2u_2cpy8lp
 
 .Lc2u_2rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #16
+		movne	r3, r7, lspull #16
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, push #16
-		movne	r4, r4, pull #16
-		orrne	r4, r4, r7, push #16
+		orrne	r3, r3, r4, lspush #16
+		movne	r4, r4, lspull #16
+		orrne	r4, r4, r7, lspush #16
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, pull #16
+		movne	r3, r7, lspull #16
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, push #16
+		orrne	r3, r3, r7, lspush #16
 	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_2fupi
@@ -227,9 +227,9 @@ USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault
 .Lc2u_3fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lc2u_3nowords
-		mov	r3, r7, pull #24
+		mov	r3, r7, lspull #24
 		ldr	r7, [r1], #4
-		orr	r3, r3, r7, push #8
+		orr	r3, r3, r7, lspush #8
 USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -241,30 +241,30 @@ USER(	TUSER(	str)	r3, [r0], #4)			@ May fault
 		subs	ip, ip, #16
 		blt	.Lc2u_3rem8lp
 
-.Lc2u_3cpy8lp:	mov	r3, r7, pull #24
+.Lc2u_3cpy8lp:	mov	r3, r7, lspull #24
 		ldmia	r1!, {r4 - r7}
 		subs	ip, ip, #16
-		orr	r3, r3, r4, push #8
-		mov	r4, r4, pull #24
-		orr	r4, r4, r5, push #8
-		mov	r5, r5, pull #24
-		orr	r5, r5, r6, push #8
-		mov	r6, r6, pull #24
-		orr	r6, r6, r7, push #8
+		orr	r3, r3, r4, lspush #8
+		mov	r4, r4, lspull #24
+		orr	r4, r4, r5, lspush #8
+		mov	r5, r5, lspull #24
+		orr	r5, r5, r6, lspush #8
+		mov	r6, r6, lspull #24
+		orr	r6, r6, r7, lspush #8
 		stmia	r0!, {r3 - r6}			@ Shouldnt fault
 		bpl	.Lc2u_3cpy8lp
 
 .Lc2u_3rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #24
+		movne	r3, r7, lspull #24
 		ldmneia	r1!, {r4, r7}
-		orrne	r3, r3, r4, push #8
-		movne	r4, r4, pull #24
-		orrne	r4, r4, r7, push #8
+		orrne	r3, r3, r4, lspush #8
+		movne	r4, r4, lspull #24
+		orrne	r4, r4, r7, lspush #8
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
-		movne	r3, r7, pull #24
+		movne	r3, r7, lspull #24
 		ldrne	r7, [r1], #4
-		orrne	r3, r3, r7, push #8
+		orrne	r3, r3, r7, lspush #8
 	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_3fupi
@@ -382,9 +382,9 @@ USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
 .Lcfu_1fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lcfu_1nowords
-		mov	r3, r7, pull #8
+		mov	r3, r7, lspull #8
 USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, push #24
+		orr	r3, r3, r7, lspush #24
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -396,30 +396,30 @@ USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
 		subs	ip, ip, #16
 		blt	.Lcfu_1rem8lp
 
-.Lcfu_1cpy8lp:	mov	r3, r7, pull #8
+.Lcfu_1cpy8lp:	mov	r3, r7, lspull #8
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
 		subs	ip, ip, #16
-		orr	r3, r3, r4, push #24
-		mov	r4, r4, pull #8
-		orr	r4, r4, r5, push #24
-		mov	r5, r5, pull #8
-		orr	r5, r5, r6, push #24
-		mov	r6, r6, pull #8
-		orr	r6, r6, r7, push #24
+		orr	r3, r3, r4, lspush #24
+		mov	r4, r4, lspull #8
+		orr	r4, r4, r5, lspush #24
+		mov	r5, r5, lspull #8
+		orr	r5, r5, r6, lspush #24
+		mov	r6, r6, lspull #8
+		orr	r6, r6, r7, lspush #24
 		stmia	r0!, {r3 - r6}
 		bpl	.Lcfu_1cpy8lp
 
 .Lcfu_1rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #8
+		movne	r3, r7, lspull #8
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, push #24
-		movne	r4, r4, pull #8
-		orrne	r4, r4, r7, push #24
+		orrne	r3, r3, r4, lspush #24
+		movne	r4, r4, lspull #8
+		orrne	r4, r4, r7, lspush #24
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, pull #8
+		movne	r3, r7, lspull #8
 USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, push #24
+		orrne	r3, r3, r7, lspush #24
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.Lcfu_1fupi
@@ -437,9 +437,9 @@ USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault
 .Lcfu_2fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lcfu_2nowords
-		mov	r3, r7, pull #16
+		mov	r3, r7, lspull #16
 USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, push #16
+		orr	r3, r3, r7, lspush #16
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -452,30 +452,30 @@ USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
 		blt	.Lcfu_2rem8lp
 
 
-.Lcfu_2cpy8lp:	mov	r3, r7, pull #16
+.Lcfu_2cpy8lp:	mov	r3, r7, lspull #16
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
 		subs	ip, ip, #16
-		orr	r3, r3, r4, push #16
-		mov	r4, r4, pull #16
-		orr	r4, r4, r5, push #16
-		mov	r5, r5, pull #16
-		orr	r5, r5, r6, push #16
-		mov	r6, r6, pull #16
-		orr	r6, r6, r7, push #16
+		orr	r3, r3, r4, lspush #16
+		mov	r4, r4, lspull #16
+		orr	r4, r4, r5, lspush #16
+		mov	r5, r5, lspull #16
+		orr	r5, r5, r6, lspush #16
+		mov	r6, r6, lspull #16
+		orr	r6, r6, r7, lspush #16
 		stmia	r0!, {r3 - r6}
 		bpl	.Lcfu_2cpy8lp
 
 .Lcfu_2rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #16
+		movne	r3, r7, lspull #16
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, push #16
-		movne	r4, r4, pull #16
-		orrne	r4, r4, r7, push #16
+		orrne	r3, r3, r4, lspush #16
+		movne	r4, r4, lspull #16
+		orrne	r4, r4, r7, lspush #16
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, pull #16
+		movne	r3, r7, lspull #16
 USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, push #16
+		orrne	r3, r3, r7, lspush #16
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.Lcfu_2fupi
@@ -493,9 +493,9 @@ USER(	TUSER(	ldrgtb) r3, [r1], #0)			@ May fault
 .Lcfu_3fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lcfu_3nowords
-		mov	r3, r7, pull #24
+		mov	r3, r7, lspull #24
 USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
-		orr	r3, r3, r7, push #8
+		orr	r3, r3, r7, lspush #8
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
@@ -507,30 +507,30 @@ USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault
 		subs	ip, ip, #16
 		blt	.Lcfu_3rem8lp
 
-.Lcfu_3cpy8lp:	mov	r3, r7, pull #24
+.Lcfu_3cpy8lp:	mov	r3, r7, lspull #24
 		ldmia	r1!, {r4 - r7}			@ Shouldnt fault
-		orr	r3, r3, r4, push #8
-		mov	r4, r4, pull #24
-		orr	r4, r4, r5, push #8
-		mov	r5, r5, pull #24
-		orr	r5, r5, r6, push #8
-		mov	r6, r6, pull #24
-		orr	r6, r6, r7, push #8
+		orr	r3, r3, r4, lspush #8
+		mov	r4, r4, lspull #24
+		orr	r4, r4, r5, lspush #8
+		mov	r5, r5, lspull #24
+		orr	r5, r5, r6, lspush #8
+		mov	r6, r6, lspull #24
+		orr	r6, r6, r7, lspush #8
 		stmia	r0!, {r3 - r6}
 		subs	ip, ip, #16
 		bpl	.Lcfu_3cpy8lp
 
 .Lcfu_3rem8lp:	tst	ip, #8
-		movne	r3, r7, pull #24
+		movne	r3, r7, lspull #24
 		ldmneia	r1!, {r4, r7}			@ Shouldnt fault
-		orrne	r3, r3, r4, push #8
-		movne	r4, r4, pull #24
-		orrne	r4, r4, r7, push #8
+		orrne	r3, r3, r4, lspush #8
+		movne	r4, r4, lspull #24
+		orrne	r4, r4, r7, lspush #8
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		movne	r3, r7, pull #24
+		movne	r3, r7, lspull #24
 USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault
-		orrne	r3, r3, r7, push #8
+		orrne	r3, r3, r7, lspush #8
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.Lcfu_3fupi
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index e47f5fd232f5..787bb50a4dff 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -21,6 +21,7 @@
 #include <mach/at91rm9200.h>
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "soc.h"
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 3ebc9792560c..f3f19f21352a 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -21,6 +21,7 @@
 #include <mach/at91rm9200.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
+#include <mach/hardware.h>
 
 #include "board.h"
 #include "generic.h"
@@ -922,6 +923,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -960,6 +962,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -987,9 +990,10 @@ static inline void configure_usart0_pins(unsigned pins)
 	if (pins & ATMEL_UART_RTS) {
 		/*
 		 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
-		 *  We need to drive the pin manually.  Default is off (RTS is active low).
+		 * We need to drive the pin manually. The serial driver will driver
+		 * this to high when initializing.
 		 */
-		at91_set_gpio_output(AT91_PIN_PA21, 1);
+		uart0_data.rts_gpio = AT91_PIN_PA21;
 	}
 }
 
@@ -1009,6 +1013,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1060,6 +1065,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1103,6 +1109,7 @@ static struct resource uart3_resources[] = {
 static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index bc7b363a3083..7fd13aef9827 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -31,6 +31,7 @@
 #include <asm/mach/time.h>
 
 #include <mach/at91_st.h>
+#include <mach/hardware.h>
 
 static unsigned long last_crtr;
 static u32 irqmask;
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 6c821e562159..c3d22be73b7c 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -21,6 +21,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index eda8d1679d40..2ae7715f1309 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -25,6 +25,7 @@
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_adc.h>
+#include <mach/hardware.h>
 
 #include "board.h"
 #include "generic.h"
@@ -819,6 +820,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -857,6 +859,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -908,6 +911,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -951,6 +955,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -994,6 +999,7 @@ static struct resource uart3_resources[] = {
 static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
@@ -1037,6 +1043,7 @@ static struct resource uart4_resources[] = {
 static struct atmel_uart_data uart4_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart4_dmamask = DMA_BIT_MASK(32);
@@ -1075,6 +1082,7 @@ static struct resource uart5_resources[] = {
 static struct atmel_uart_data uart5_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart5_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 6276b4c1acfe..48b51f796d6a 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -20,6 +20,7 @@
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index b2a34740146a..80e35895d28f 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -25,6 +25,7 @@
 #include <mach/at91sam9261_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 
 #include "board.h"
 #include "generic.h"
@@ -880,6 +881,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -918,6 +920,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -961,6 +964,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1004,6 +1008,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 37b90f4b990c..486530c3973b 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -19,6 +19,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 4aeadddbc181..43d53d6156dd 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -24,6 +24,7 @@
 #include <mach/at91sam9263_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 
 #include "board.h"
 #include "generic.h"
@@ -1324,6 +1325,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1362,6 +1364,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1405,6 +1408,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1448,6 +1452,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 0f04ffe9c5a8..0a9e2fc8f796 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -19,6 +19,7 @@
 #include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
+#include <mach/hardware.h>
 
 #define AT91_PIT_MR		0x00			/* Mode Register */
 #define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 2f455ce35268..8c11696f606e 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -20,6 +20,7 @@
 #include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
 #include <mach/cpu.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "soc.h"
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index cb36fa872d30..77b04c2edd78 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -32,6 +32,7 @@
 #include <mach/at91sam9_smc.h>
 #include <linux/platform_data/dma-atmel.h>
 #include <mach/atmel-mci.h>
+#include <mach/hardware.h>
 
 #include <media/atmel-isi.h>
 
@@ -1587,6 +1588,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1625,6 +1627,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1668,6 +1671,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1711,6 +1715,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1754,6 +1759,7 @@ static struct resource uart3_resources[] = {
 static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 3651517abedf..c0d5474706f8 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -20,6 +20,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index a698bdab2cce..428fc412aaf1 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -21,6 +21,7 @@
 #include <mach/at91sam9rl_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 #include <linux/platform_data/dma-atmel.h>
 
 #include "board.h"
@@ -956,6 +957,7 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -994,6 +996,7 @@ static struct resource uart0_resources[] = {
 static struct atmel_uart_data uart0_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart0_dmamask = DMA_BIT_MASK(32);
@@ -1045,6 +1048,7 @@ static struct resource uart1_resources[] = {
 static struct atmel_uart_data uart1_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart1_dmamask = DMA_BIT_MASK(32);
@@ -1088,6 +1092,7 @@ static struct resource uart2_resources[] = {
 static struct atmel_uart_data uart2_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart2_dmamask = DMA_BIT_MASK(32);
@@ -1131,6 +1136,7 @@ static struct resource uart3_resources[] = {
 static struct atmel_uart_data uart3_data = {
 	.use_dma_tx	= 1,
 	.use_dma_rx	= 1,
+	.rts_gpio	= -EINVAL,
 };
 
 static u64 uart3_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
index bad94b84a46f..7523f1cdfe1d 100644
--- a/arch/arm/mach-at91/at91x40.c
+++ b/arch/arm/mach-at91/at91x40.c
@@ -19,7 +19,7 @@
 #include <asm/mach/arch.h>
 #include <mach/at91x40.h>
 #include <mach/at91_st.h>
-#include <mach/timex.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "generic.h"
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index c0e637adf65d..07d0bf2ac2da 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -25,6 +25,7 @@
 #include <linux/time.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
+#include <mach/at91x40.h>
 #include <asm/mach/time.h>
 
 #include "at91_tc.h"
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index c1d61d247790..416bae8435ee 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -31,6 +31,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "board.h"
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index 65c0d6b5ecba..5f25fa54eb93 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -30,6 +30,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "board.h"
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 869cbecf00b7..e4a5ac17cdbc 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/at91sam9_smc.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "board.h"
diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h
index 90680217064e..38dca2bb027f 100644
--- a/arch/arm/mach-at91/include/mach/at91x40.h
+++ b/arch/arm/mach-at91/include/mach/at91x40.h
@@ -55,4 +55,6 @@
 #define	AT91_PS_CR	(AT91_PS + 0)	/* PS Control register */
 #define	AT91_PS_CR_CPU	(1 << 0)	/* CPU clock disable bit */
 
+#define AT91X40_MASTER_CLOCK	40000000
+
 #endif /* AT91X40_H */
diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h
deleted file mode 100644
index 5e917a66edd7..000000000000
--- a/arch/arm/mach-at91/include/mach/timex.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/timex.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * This program is free software; you can redistribute 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#include <mach/hardware.h>
-
-#ifdef CONFIG_ARCH_AT91X40
-
-#define AT91X40_MASTER_CLOCK	40000000
-#define CLOCK_TICK_RATE		(AT91X40_MASTER_CLOCK)
-
-#else
-
-#define CLOCK_TICK_RATE		12345678
-
-#endif
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 590b52dea9f7..8bda1cefdf96 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -27,6 +27,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/cpu.h>
+#include <mach/hardware.h>
 
 #include "at91_aic.h"
 #include "generic.h"
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index b1aa6a9b3bd1..7de3282a8613 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -16,12 +16,7 @@ config ARCH_BCM_MOBILE
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
-	select CPU_V7
-	select CLKSRC_OF
-	select GENERIC_CLOCKEVENTS
-	select GENERIC_TIME
 	select GPIO_BCM_KONA
-	select SPARSE_IRQ
 	select TICK_ONESHOT
 	select CACHE_L2X0
 	select HAVE_ARM_ARCH_TIMER
@@ -32,6 +27,18 @@ config ARCH_BCM_MOBILE
 	  BCM11130, BCM11140, BCM11351, BCM28145 and
 	  BCM28155 variants.
 
+config ARCH_BCM2835
+	bool "Broadcom BCM2835 family" if ARCH_MULTI_V6
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select ARM_ERRATA_411920
+	select ARM_TIMER_SP804
+	select PINCTRL
+	select PINCTRL_BCM2835
+	help
+	  This enables support for the Broadcom BCM2835 SoC. This SoC is
+	  used in the Raspberry Pi and Roku 2 devices.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index c2ccd5a0f772..0ad293882079 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -11,5 +11,7 @@
 # GNU General Public License for more details.
 
 obj-$(CONFIG_ARCH_BCM_MOBILE)	:= board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o
+obj-$(CONFIG_ARCH_BCM2835)	+= board_bcm2835.o
+
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_bcm_kona_smc_asm.o	:=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c
new file mode 100644
index 000000000000..70f2f3925f0e
--- /dev/null
+++ b/arch/arm/mach-bcm/board_bcm2835.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute 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/delay.h>
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/clk/bcm2835.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#define PM_RSTC				0x1c
+#define PM_RSTS				0x20
+#define PM_WDOG				0x24
+
+#define PM_PASSWORD			0x5a000000
+#define PM_RSTC_WRCFG_MASK		0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+#define PM_RSTS_HADWRH_SET		0x00000040
+
+#define BCM2835_PERIPH_PHYS	0x20000000
+#define BCM2835_PERIPH_VIRT	0xf0000000
+#define BCM2835_PERIPH_SIZE	SZ_16M
+
+static void __iomem *wdt_regs;
+
+/*
+ * The machine restart method can be called from an atomic context so we won't
+ * be able to ioremap the regs then.
+ */
+static void bcm2835_setup_restart(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"brcm,bcm2835-pm-wdt");
+	if (WARN(!np, "unable to setup watchdog restart"))
+		return;
+
+	wdt_regs = of_iomap(np, 0);
+	WARN(!wdt_regs, "failed to remap watchdog regs");
+}
+
+static void bcm2835_restart(enum reboot_mode mode, const char *cmd)
+{
+	u32 val;
+
+	if (!wdt_regs)
+		return;
+
+	/* use a timeout of 10 ticks (~150us) */
+	writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
+	val = readl_relaxed(wdt_regs + PM_RSTC);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+	writel_relaxed(val, wdt_regs + PM_RSTC);
+
+	/* No sleeping, possibly atomic. */
+	mdelay(1);
+}
+
+/*
+ * We can't really power off, but if we do the normal reset scheme, and
+ * indicate to bootcode.bin not to reboot, then most of the chip will be
+ * powered off.
+ */
+static void bcm2835_power_off(void)
+{
+	u32 val;
+
+	/*
+	 * We set the watchdog hard reset bit here to distinguish this reset
+	 * from the normal (full) reset. bootcode.bin will not reboot after a
+	 * hard reset.
+	 */
+	val = readl_relaxed(wdt_regs + PM_RSTS);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
+	writel_relaxed(val, wdt_regs + PM_RSTS);
+
+	/* Continue with normal reset mechanism */
+	bcm2835_restart(REBOOT_HARD, "");
+}
+
+static struct map_desc io_map __initdata = {
+	.virtual = BCM2835_PERIPH_VIRT,
+	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
+	.length = BCM2835_PERIPH_SIZE,
+	.type = MT_DEVICE
+};
+
+static void __init bcm2835_map_io(void)
+{
+	iotable_init(&io_map, 1);
+}
+
+static void __init bcm2835_init(void)
+{
+	int ret;
+
+	bcm2835_setup_restart();
+	if (wdt_regs)
+		pm_power_off = bcm2835_power_off;
+
+	bcm2835_init_clocks();
+
+	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
+				   NULL);
+	if (ret) {
+		pr_err("of_platform_populate failed: %d\n", ret);
+		BUG();
+	}
+}
+
+static const char * const bcm2835_compat[] = {
+	"brcm,bcm2835",
+	NULL
+};
+
+DT_MACHINE_START(BCM2835, "BCM2835")
+	.map_io = bcm2835_map_io,
+	.init_irq = irqchip_init,
+	.init_machine = bcm2835_init,
+	.restart = bcm2835_restart,
+	.dt_compat = bcm2835_compat
+MACHINE_END
diff --git a/arch/arm/mach-bcm2835/Kconfig b/arch/arm/mach-bcm2835/Kconfig
deleted file mode 100644
index d1f9612f8c15..000000000000
--- a/arch/arm/mach-bcm2835/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config ARCH_BCM2835
-	bool "Broadcom BCM2835 family" if ARCH_MULTI_V6
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_AMBA
-	select ARM_ERRATA_411920
-	select ARM_TIMER_SP804
-	select CLKDEV_LOOKUP
-	select CLKSRC_OF
-	select CPU_V6
-	select GENERIC_CLOCKEVENTS
-	select PINCTRL
-	select PINCTRL_BCM2835
-	help
-	  This enables support for the Broadcom BCM2835 SoC. This SoC is
-	  used in the Raspberry Pi and Roku 2 devices.
diff --git a/arch/arm/mach-bcm2835/Makefile b/arch/arm/mach-bcm2835/Makefile
deleted file mode 100644
index 4c3892fe02c3..000000000000
--- a/arch/arm/mach-bcm2835/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-y += bcm2835.o
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
deleted file mode 100644
index 70f2f3925f0e..000000000000
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2010 Broadcom
- *
- * This program is free software; you can redistribute 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/delay.h>
-#include <linux/init.h>
-#include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/clk/bcm2835.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#define PM_RSTC				0x1c
-#define PM_RSTS				0x20
-#define PM_WDOG				0x24
-
-#define PM_PASSWORD			0x5a000000
-#define PM_RSTC_WRCFG_MASK		0x00000030
-#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
-#define PM_RSTS_HADWRH_SET		0x00000040
-
-#define BCM2835_PERIPH_PHYS	0x20000000
-#define BCM2835_PERIPH_VIRT	0xf0000000
-#define BCM2835_PERIPH_SIZE	SZ_16M
-
-static void __iomem *wdt_regs;
-
-/*
- * The machine restart method can be called from an atomic context so we won't
- * be able to ioremap the regs then.
- */
-static void bcm2835_setup_restart(void)
-{
-	struct device_node *np = of_find_compatible_node(NULL, NULL,
-						"brcm,bcm2835-pm-wdt");
-	if (WARN(!np, "unable to setup watchdog restart"))
-		return;
-
-	wdt_regs = of_iomap(np, 0);
-	WARN(!wdt_regs, "failed to remap watchdog regs");
-}
-
-static void bcm2835_restart(enum reboot_mode mode, const char *cmd)
-{
-	u32 val;
-
-	if (!wdt_regs)
-		return;
-
-	/* use a timeout of 10 ticks (~150us) */
-	writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
-	val = readl_relaxed(wdt_regs + PM_RSTC);
-	val &= ~PM_RSTC_WRCFG_MASK;
-	val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
-	writel_relaxed(val, wdt_regs + PM_RSTC);
-
-	/* No sleeping, possibly atomic. */
-	mdelay(1);
-}
-
-/*
- * We can't really power off, but if we do the normal reset scheme, and
- * indicate to bootcode.bin not to reboot, then most of the chip will be
- * powered off.
- */
-static void bcm2835_power_off(void)
-{
-	u32 val;
-
-	/*
-	 * We set the watchdog hard reset bit here to distinguish this reset
-	 * from the normal (full) reset. bootcode.bin will not reboot after a
-	 * hard reset.
-	 */
-	val = readl_relaxed(wdt_regs + PM_RSTS);
-	val &= ~PM_RSTC_WRCFG_MASK;
-	val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
-	writel_relaxed(val, wdt_regs + PM_RSTS);
-
-	/* Continue with normal reset mechanism */
-	bcm2835_restart(REBOOT_HARD, "");
-}
-
-static struct map_desc io_map __initdata = {
-	.virtual = BCM2835_PERIPH_VIRT,
-	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
-	.length = BCM2835_PERIPH_SIZE,
-	.type = MT_DEVICE
-};
-
-static void __init bcm2835_map_io(void)
-{
-	iotable_init(&io_map, 1);
-}
-
-static void __init bcm2835_init(void)
-{
-	int ret;
-
-	bcm2835_setup_restart();
-	if (wdt_regs)
-		pm_power_off = bcm2835_power_off;
-
-	bcm2835_init_clocks();
-
-	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
-				   NULL);
-	if (ret) {
-		pr_err("of_platform_populate failed: %d\n", ret);
-		BUG();
-	}
-}
-
-static const char * const bcm2835_compat[] = {
-	"brcm,bcm2835",
-	NULL
-};
-
-DT_MACHINE_START(BCM2835, "BCM2835")
-	.map_io = bcm2835_map_io,
-	.init_irq = irqchip_init,
-	.init_machine = bcm2835_init,
-	.restart = bcm2835_restart,
-	.dt_compat = bcm2835_compat
-MACHINE_END
diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig
index 7a02d222c378..b0cb0722acd2 100644
--- a/arch/arm/mach-berlin/Kconfig
+++ b/arch/arm/mach-berlin/Kconfig
@@ -1,9 +1,7 @@
 config ARCH_BERLIN
 	bool "Marvell Berlin SoCs" if ARCH_MULTI_V7
 	select ARM_GIC
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select COMMON_CLK
 	select DW_APB_ICTL
 	select DW_APB_TIMER_OF
 
@@ -16,12 +14,10 @@ config MACH_BERLIN_BG2
 	select CACHE_L2X0
 	select CPU_PJ4B
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 
 config MACH_BERLIN_BG2CD
 	bool "Marvell Armada 1500-mini (BG2CD)"
 	select CACHE_L2X0
-	select CPU_V7
 	select HAVE_ARM_TWD if SMP
 
 endmenu
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index bea6295c8c59..f711498c180c 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -33,20 +33,6 @@ config ARCH_P720T
 	  Say Y here if you intend to run this kernel on the ARM Prospector
 	  720T.
 
-config EP72XX_ROM_BOOT
-	bool "EP721x/EP731x ROM boot"
-	help
-	  If you say Y here, your CLPS711x-based kernel will use the bootstrap
-	  mode memory map instead of the normal memory map.
-
-	  Processors derived from the Cirrus CLPS711X core support two boot
-	  modes.  Normal mode boots from the external memory device at CS0.
-	  Bootstrap mode rearranges parts of the memory map, placing an
-	  internal 128 byte bootstrap ROM at CS0.  This option performs the
-	  address map changes required to support booting in this mode.
-
-	  You almost surely want to say N here.
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c
index f8d71a89644a..d62ca16d5394 100644
--- a/arch/arm/mach-clps711x/board-autcpu12.c
+++ b/arch/arm/mach-clps711x/board-autcpu12.c
@@ -73,7 +73,7 @@
 #define AUTCPU12_SMC_NCE	(AUTCPU12_MMGPIO_BASE + 0) /* Bit 0 */
 #define AUTCPU12_SMC_RDY	CLPS711X_GPIO(1, 2)
 #define AUTCPU12_SMC_ALE	CLPS711X_GPIO(1, 3)
-#define AUTCPU12_SMC_CLE	CLPS711X_GPIO(1, 3)
+#define AUTCPU12_SMC_CLE	CLPS711X_GPIO(1, 4)
 
 /* LCD contrast digital potentiometer */
 #define AUTCPU12_DPOT_CS	CLPS711X_GPIO(4, 0)
@@ -265,14 +265,12 @@ static void __init autcpu12_init_late(void)
 MACHINE_START(AUTCPU12, "autronix autcpu12")
 	/* Maintainer: Thomas Gleixner */
 	.atag_offset	= 0x20000,
-	.nr_irqs	= CLPS711X_NR_IRQS,
 	.map_io		= clps711x_map_io,
 	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
 	.init_machine	= autcpu12_init,
 	.init_late	= autcpu12_init_late,
-	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c
index a9e38c6bcfb4..e261a47f2aff 100644
--- a/arch/arm/mach-clps711x/board-cdb89712.c
+++ b/arch/arm/mach-clps711x/board-cdb89712.c
@@ -139,12 +139,10 @@ static void __init cdb89712_init(void)
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
 	/* Maintainer: Ray Lehtiniemi */
 	.atag_offset	= 0x100,
-	.nr_irqs	= CLPS711X_NR_IRQS,
 	.map_io		= clps711x_map_io,
 	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
 	.init_machine	= cdb89712_init,
-	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c
index b4764246d0f8..221b9de32dd6 100644
--- a/arch/arm/mach-clps711x/board-clep7312.c
+++ b/arch/arm/mach-clps711x/board-clep7312.c
@@ -36,12 +36,10 @@ fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
 	/* Maintainer: Nobody */
 	.atag_offset	= 0x0100,
-	.nr_irqs	= CLPS711X_NR_IRQS,
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
 	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
-	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c
index fe6184ead896..077609841f14 100644
--- a/arch/arm/mach-clps711x/board-edb7211.c
+++ b/arch/arm/mach-clps711x/board-edb7211.c
@@ -177,7 +177,6 @@ static void __init edb7211_init_late(void)
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
 	/* Maintainer: Jon McClintock */
 	.atag_offset	= VIDEORAM_SIZE + 0x100,
-	.nr_irqs	= CLPS711X_NR_IRQS,
 	.fixup		= fixup_edb7211,
 	.reserve	= edb7211_reserve,
 	.map_io		= clps711x_map_io,
@@ -186,6 +185,5 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
 	.init_time	= clps711x_timer_init,
 	.init_machine	= edb7211_init,
 	.init_late	= edb7211_init_late,
-	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c
index dd81b06f68fe..67b733744ed7 100644
--- a/arch/arm/mach-clps711x/board-p720t.c
+++ b/arch/arm/mach-clps711x/board-p720t.c
@@ -363,7 +363,6 @@ static void __init p720t_init_late(void)
 MACHINE_START(P720T, "ARM-Prospector720T")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
-	.nr_irqs	= CLPS711X_NR_IRQS,
 	.fixup		= fixup_p720t,
 	.map_io		= clps711x_map_io,
 	.init_early	= clps711x_init_early,
@@ -371,6 +370,5 @@ MACHINE_START(P720T, "ARM-Prospector720T")
 	.init_time	= clps711x_timer_init,
 	.init_machine	= p720t_init,
 	.init_late	= p720t_init_late,
-	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index a1935911e4f1..aee81fa46ccf 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -31,14 +31,14 @@
 #include <linux/clk-provider.h>
 #include <linux/sched_clock.h>
 
-#include <asm/exception.h>
-#include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 
+#include "common.h"
+
 static struct clk *clk_pll, *clk_bus, *clk_uart, *clk_timerl, *clk_timerh,
 		  *clk_tint, *clk_spi;
 
@@ -59,204 +59,9 @@ void __init clps711x_map_io(void)
 	iotable_init(clps711x_io_desc, ARRAY_SIZE(clps711x_io_desc));
 }
 
-static void int1_mask(struct irq_data *d)
-{
-	u32 intmr1;
-
-	intmr1 = clps_readl(INTMR1);
-	intmr1 &= ~(1 << d->irq);
-	clps_writel(intmr1, INTMR1);
-}
-
-static void int1_eoi(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_CSINT:  clps_writel(0, COEOI);  break;
-	case IRQ_TC1OI:  clps_writel(0, TC1EOI); break;
-	case IRQ_TC2OI:  clps_writel(0, TC2EOI); break;
-	case IRQ_RTCMI:  clps_writel(0, RTCEOI); break;
-	case IRQ_TINT:   clps_writel(0, TEOI);   break;
-	case IRQ_UMSINT: clps_writel(0, UMSEOI); break;
-	}
-}
-
-static void int1_unmask(struct irq_data *d)
-{
-	u32 intmr1;
-
-	intmr1 = clps_readl(INTMR1);
-	intmr1 |= 1 << d->irq;
-	clps_writel(intmr1, INTMR1);
-}
-
-static struct irq_chip int1_chip = {
-	.name		= "Interrupt Vector 1",
-	.irq_eoi	= int1_eoi,
-	.irq_mask	= int1_mask,
-	.irq_unmask	= int1_unmask,
-};
-
-static void int2_mask(struct irq_data *d)
-{
-	u32 intmr2;
-
-	intmr2 = clps_readl(INTMR2);
-	intmr2 &= ~(1 << (d->irq - 16));
-	clps_writel(intmr2, INTMR2);
-}
-
-static void int2_eoi(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
-	}
-}
-
-static void int2_unmask(struct irq_data *d)
-{
-	u32 intmr2;
-
-	intmr2 = clps_readl(INTMR2);
-	intmr2 |= 1 << (d->irq - 16);
-	clps_writel(intmr2, INTMR2);
-}
-
-static struct irq_chip int2_chip = {
-	.name		= "Interrupt Vector 2",
-	.irq_eoi	= int2_eoi,
-	.irq_mask	= int2_mask,
-	.irq_unmask	= int2_unmask,
-};
-
-static void int3_mask(struct irq_data *d)
-{
-	u32 intmr3;
-
-	intmr3 = clps_readl(INTMR3);
-	intmr3 &= ~(1 << (d->irq - 32));
-	clps_writel(intmr3, INTMR3);
-}
-
-static void int3_unmask(struct irq_data *d)
-{
-	u32 intmr3;
-
-	intmr3 = clps_readl(INTMR3);
-	intmr3 |= 1 << (d->irq - 32);
-	clps_writel(intmr3, INTMR3);
-}
-
-static struct irq_chip int3_chip = {
-	.name		= "Interrupt Vector 3",
-	.irq_mask	= int3_mask,
-	.irq_unmask	= int3_unmask,
-};
-
-static struct {
-	int			nr;
-	struct irq_chip		*chip;
-	irq_flow_handler_t	handle;
-} clps711x_irqdescs[] __initdata = {
-	{ IRQ_CSINT,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_EINT1,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_EINT2,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_EINT3,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_TC1OI,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_TC2OI,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_RTCMI,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_TINT,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_UTXINT1,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_URXINT1,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_UMSINT,	&int1_chip,	handle_fasteoi_irq,	},
-	{ IRQ_SSEOTI,	&int1_chip,	handle_level_irq,	},
-	{ IRQ_KBDINT,	&int2_chip,	handle_fasteoi_irq,	},
-	{ IRQ_SS2RX,	&int2_chip,	handle_level_irq,	},
-	{ IRQ_SS2TX,	&int2_chip,	handle_level_irq,	},
-	{ IRQ_UTXINT2,	&int2_chip,	handle_level_irq,	},
-	{ IRQ_URXINT2,	&int2_chip,	handle_level_irq,	},
-};
-
 void __init clps711x_init_irq(void)
 {
-	unsigned int i;
-
-	/* Disable interrupts */
-	clps_writel(0, INTMR1);
-	clps_writel(0, INTMR2);
-	clps_writel(0, INTMR3);
-
-	/* Clear down any pending interrupts */
-	clps_writel(0, BLEOI);
-	clps_writel(0, MCEOI);
-	clps_writel(0, COEOI);
-	clps_writel(0, TC1EOI);
-	clps_writel(0, TC2EOI);
-	clps_writel(0, RTCEOI);
-	clps_writel(0, TEOI);
-	clps_writel(0, UMSEOI);
-	clps_writel(0, KBDEOI);
-	clps_writel(0, SRXEOF);
-	clps_writel(0xffffffff, DAISR);
-
-	for (i = 0; i < ARRAY_SIZE(clps711x_irqdescs); i++) {
-		irq_set_chip_and_handler(clps711x_irqdescs[i].nr,
-					 clps711x_irqdescs[i].chip,
-					 clps711x_irqdescs[i].handle);
-		set_irq_flags(clps711x_irqdescs[i].nr,
-			      IRQF_VALID | IRQF_PROBE);
-	}
-
-	if (IS_ENABLED(CONFIG_FIQ)) {
-		init_FIQ(0);
-		irq_set_chip_and_handler(IRQ_DAIINT, &int3_chip,
-					 handle_bad_irq);
-		set_irq_flags(IRQ_DAIINT,
-			      IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
-	}
-}
-
-static inline u32 fls16(u32 x)
-{
-	u32 r = 15;
-
-	if (!(x & 0xff00)) {
-		x <<= 8;
-		r -= 8;
-	}
-	if (!(x & 0xf000)) {
-		x <<= 4;
-		r -= 4;
-	}
-	if (!(x & 0xc000)) {
-		x <<= 2;
-		r -= 2;
-	}
-	if (!(x & 0x8000))
-		r--;
-
-	return r;
-}
-
-asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs)
-{
-	do {
-		u32 irqstat;
-		void __iomem *base = CLPS711X_VIRT_BASE;
-
-		irqstat = readw_relaxed(base + INTSR1) &
-			  readw_relaxed(base + INTMR1);
-		if (irqstat)
-			handle_IRQ(fls16(irqstat), regs);
-
-		irqstat = readw_relaxed(base + INTSR2) &
-			  readw_relaxed(base + INTMR2);
-		if (irqstat) {
-			handle_IRQ(fls16(irqstat) + 16, regs);
-			continue;
-		}
-
-		break;
-	} while (1);
+	clps711x_intc_init(CLPS711X_PHYS_BASE, SZ_16K);
 }
 
 static u64 notrace clps711x_sched_clock_read(void)
diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h
index 9a6767bfdc47..7489139d5d63 100644
--- a/arch/arm/mach-clps711x/common.h
+++ b/arch/arm/mach-clps711x/common.h
@@ -6,13 +6,14 @@
 
 #include <linux/reboot.h>
 
-#define CLPS711X_NR_IRQS	(33)
 #define CLPS711X_NR_GPIO	(4 * 8 + 3)
 #define CLPS711X_GPIO(prt, bit)	((prt) * 8 + (bit))
 
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
 extern void clps711x_timer_init(void);
-extern void clps711x_handle_irq(struct pt_regs *regs);
 extern void clps711x_restart(enum reboot_mode mode, const char *cmd);
 extern void clps711x_init_early(void);
+
+/* drivers/irqchip/irq-clps711x.c */
+void clps711x_intc_init(phys_addr_t, resource_size_t);
diff --git a/arch/arm/mach-clps711x/include/mach/clps711x.h b/arch/arm/mach-clps711x/include/mach/clps711x.h
index 0286f4bf9945..eb052a11aa9d 100644
--- a/arch/arm/mach-clps711x/include/mach/clps711x.h
+++ b/arch/arm/mach-clps711x/include/mach/clps711x.h
@@ -40,8 +40,6 @@
 #define MEMCFG1		(0x0180)
 #define MEMCFG2		(0x01c0)
 #define DRFPR		(0x0200)
-#define INTSR1		(0x0240)
-#define INTMR1		(0x0280)
 #define LCDCON		(0x02c0)
 #define TC1D		(0x0300)
 #define TC2D		(0x0340)
@@ -55,28 +53,16 @@
 #define PALLSW		(0x0540)
 #define PALMSW		(0x0580)
 #define STFCLR		(0x05c0)
-#define BLEOI		(0x0600)
-#define MCEOI		(0x0640)
-#define TEOI		(0x0680)
-#define TC1EOI		(0x06c0)
-#define TC2EOI		(0x0700)
-#define RTCEOI		(0x0740)
-#define UMSEOI		(0x0780)
-#define COEOI		(0x07c0)
 #define HALT		(0x0800)
 #define STDBY		(0x0840)
 
 #define FBADDR		(0x1000)
 #define SYSCON2		(0x1100)
 #define SYSFLG2		(0x1140)
-#define INTSR2		(0x1240)
-#define INTMR2		(0x1280)
 #define UARTDR2		(0x1480)
 #define UBRLCR2		(0x14c0)
 #define SS2DR		(0x1500)
-#define SRXEOF		(0x1600)
 #define SS2POP		(0x16c0)
-#define KBDEOI		(0x1700)
 
 #define DAIR		(0x2000)
 #define DAIDR0		(0x2040)
@@ -84,8 +70,6 @@
 #define DAIDR2		(0x20c0)
 #define DAISR		(0x2100)
 #define SYSCON3		(0x2200)
-#define INTSR3		(0x2240)
-#define INTMR3		(0x2280)
 #define LEDFLSH		(0x22c0)
 #define SDCONF		(0x2300)
 #define SDRFPR		(0x2340)
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index c5a8ea6839ef..5d6afda1c0e8 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -38,13 +38,6 @@
 #define clps_writel(val,off)	writel(val, CLPS711X_VIRT_BASE + (off))
 #endif
 
-/*
- * The physical addresses that the external chip select signals map to is
- * dependent on the setting of the nMEDCHG signal on EP7211 and EP7212
- * processors.  CONFIG_EP72XX_BOOT_ROM is only available if these
- * processors are in use.
- */
-#ifndef CONFIG_EP72XX_ROM_BOOT
 #define CS0_PHYS_BASE		(0x00000000)
 #define CS1_PHYS_BASE		(0x10000000)
 #define CS2_PHYS_BASE		(0x20000000)
@@ -53,16 +46,6 @@
 #define CS5_PHYS_BASE		(0x50000000)
 #define CS6_PHYS_BASE		(0x60000000)
 #define CS7_PHYS_BASE		(0x70000000)
-#else
-#define CS0_PHYS_BASE		(0x70000000)
-#define CS1_PHYS_BASE		(0x60000000)
-#define CS2_PHYS_BASE		(0x50000000)
-#define CS3_PHYS_BASE		(0x40000000)
-#define CS4_PHYS_BASE		(0x30000000)
-#define CS5_PHYS_BASE		(0x20000000)
-#define CS6_PHYS_BASE		(0x10000000)
-#define CS7_PHYS_BASE		(0x00000000)
-#endif
 
 #define CLPS711X_SRAM_BASE	CS6_PHYS_BASE
 #define CLPS711X_SRAM_SIZE	(48 * 1024)
diff --git a/arch/arm/mach-clps711x/include/mach/timex.h b/arch/arm/mach-clps711x/include/mach/timex.h
deleted file mode 100644
index de6fd192d1c3..000000000000
--- a/arch/arm/mach-clps711x/include/mach/timex.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Bogus value */
-#define CLOCK_TICK_RATE 512000
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index dbf0df8bb0ac..dce8decd5d46 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -1,9 +1,6 @@
 config ARCH_CNS3XXX
 	bool "Cavium Networks CNS3XXX family" if ARCH_MULTI_V6
 	select ARM_GIC
-	select CPU_V6K
-	select GENERIC_CLOCKEVENTS
-	select MIGHT_HAVE_CACHE_L2X0
 	select MIGHT_HAVE_PCI
 	select PCI_DOMAINS if PCI
 	help
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index f091a9010c2f..ff8b7e76b6e9 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -16,6 +16,7 @@
 #include <linux/time.h>
 
 #include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/mtd-davinci.h>
 
 /* Timing value configuration */
 
@@ -43,6 +44,17 @@
 				WSTROBE(WSTROBE_MAX) | \
 				WSETUP(WSETUP_MAX))
 
+static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
+{
+	return readl_relaxed(base + offset);
+}
+
+static inline void davinci_aemif_writel(void __iomem *base,
+					int offset, unsigned long value)
+{
+	writel_relaxed(value, base + offset);
+}
+
 /*
  * aemif_calc_rate - calculate timing data.
  * @wanted: The cycle time needed in nanoseconds.
@@ -76,6 +88,7 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
  * @t: timing values to be progammed
  * @base: The virtual base address of the AEMIF interface
  * @cs: chip-select to program the timing values for
+ * @clkrate: the AEMIF clkrate
  *
  * This function programs the given timing values (in real clock) into the
  * AEMIF registers taking the AEMIF clock into account.
@@ -86,24 +99,17 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max)
  *
  * Returns 0 on success, else negative errno.
  */
-int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-					void __iomem *base, unsigned cs)
+static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+					void __iomem *base, unsigned cs,
+					unsigned long clkrate)
 {
 	unsigned set, val;
 	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
 	unsigned offset = A1CR_OFFSET + cs * 4;
-	struct clk *aemif_clk;
-	unsigned long clkrate;
 
 	if (!t)
 		return 0;	/* Nothing to do */
 
-	aemif_clk = clk_get(NULL, "aemif");
-	if (IS_ERR(aemif_clk))
-		return PTR_ERR(aemif_clk);
-
-	clkrate = clk_get_rate(aemif_clk);
-
 	clkrate /= 1000;	/* turn clock into kHz for ease of use */
 
 	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
@@ -130,4 +136,83 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
 
 	return 0;
 }
-EXPORT_SYMBOL(davinci_aemif_setup_timing);
+
+/**
+ * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
+ * @pdev - link to platform device to setup settings for
+ *
+ * This function does not use any locking while programming the AEMIF
+ * because it is expected that there is only one user of a given
+ * chip-select.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int davinci_aemif_setup(struct platform_device *pdev)
+{
+	struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
+	uint32_t val;
+	unsigned long clkrate;
+	struct resource	*res;
+	void __iomem *base;
+	struct clk *clk;
+	int ret = 0;
+
+	clk = clk_get(&pdev->dev, "aemif");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
+			ret);
+		goto err_put;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	base = ioremap(res->start, resource_size(res));
+	if (!base) {
+		dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * Setup Async configuration register in case we did not boot
+	 * from NAND and so bootloader did not bother to set it up.
+	 */
+	val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4);
+	/*
+	 * Extended Wait is not valid and Select Strobe mode is not
+	 * used
+	 */
+	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
+	if (pdata->options & NAND_BUSWIDTH_16)
+		val |= 0x1;
+
+	davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val);
+
+	clkrate = clk_get_rate(clk);
+
+	if (pdata->timing)
+		ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
+						 clkrate);
+
+	if (ret < 0)
+		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
+
+	iounmap(base);
+err:
+	clk_disable_unprepare(clk);
+err_put:
+	clk_put(clk);
+	return ret;
+}
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index d1f45af7a530..5623131c4f0b 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -419,6 +419,9 @@ static inline void da830_evm_init_nand(int mux_mode)
 	if (ret)
 		pr_warning("da830_evm_init: NAND device not registered.\n");
 
+	if (davinci_aemif_setup(&da830_evm_nand_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+
 	gpio_direction_output(mux_mode, 1);
 }
 #else
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index e0af0eccde8f..234c5bb091f5 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -358,6 +358,9 @@ static inline void da850_evm_setup_nor_nand(void)
 
 		platform_add_devices(da850_evm_devices,
 					ARRAY_SIZE(da850_evm_devices));
+
+		if (davinci_aemif_setup(&da850_evm_nandflash_device))
+			pr_warn("%s: Cannot configure AEMIF.\n", __func__);
 	}
 }
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 987605b78556..5602957b67d7 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -778,6 +778,11 @@ static __init void davinci_evm_init(void)
 		/* only one device will be jumpered and detected */
 		if (HAS_NAND) {
 			platform_device_register(&davinci_evm_nandflash_device);
+
+			if (davinci_aemif_setup(&davinci_evm_nandflash_device))
+				pr_warn("%s: Cannot configure AEMIF.\n",
+					__func__);
+
 			evm_leds[7].default_trigger = "nand-disk";
 			if (HAS_NOR)
 				pr_warning("WARNING: both NAND and NOR flash "
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 13d0801fd6b1..ae129bc49273 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -805,6 +805,9 @@ static __init void evm_init(void)
 
 	platform_device_register(&davinci_nand_device);
 
+	if (davinci_aemif_setup(&davinci_nand_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+
 	dm646x_init_edma(dm646x_edma_rsv);
 
 	if (HAS_ATA)
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 7aa105b1fd0f..96fc00a167f5 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -27,6 +27,7 @@
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
 #include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
 #include <mach/mux.h>
 #include <linux/platform_data/spi-davinci.h>
 
@@ -432,6 +433,9 @@ static void __init mityomapl138_setup_nand(void)
 {
 	platform_add_devices(mityomapl138_devices,
 				 ARRAY_SIZE(mityomapl138_devices));
+
+	if (davinci_aemif_setup(&mityomapl138_nandflash_device))
+		pr_warn("%s: Cannot configure AEMIF.\n", __func__);
 }
 
 static const short mityomap_mii_pins[] = {
diff --git a/arch/arm/mach-davinci/include/mach/timex.h b/arch/arm/mach-davinci/include/mach/timex.h
deleted file mode 100644
index 9b885298f106..000000000000
--- a/arch/arm/mach-davinci/include/mach/timex.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * DaVinci timer defines
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, 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.
- */
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/*
- * Alert: Not all timers of the DaVinci family run at a frequency of 27MHz,
- * but we should be fine as long as CLOCK_TICK_RATE or LATCH (see include/
- * linux/jiffies.h) are not used directly in code. Currently none of the
- * code relevant to DaVinci platform depends on these values directly.
- */
-#define CLOCK_TICK_RATE 27000000
-
-#endif /* __ASM_ARCH_TIMEX_H__ */
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index 5362df3df89f..f4a5b34489b7 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -21,6 +21,7 @@
 #define  CPU_CTRL_PCIE1_LINK	0x00000008
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define  SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-dove/include/mach/timex.h b/arch/arm/mach-dove/include/mach/timex.h
deleted file mode 100644
index 251d538541db..000000000000
--- a/arch/arm/mach-dove/include/mach/timex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/timex.h
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-ebsa110/include/mach/timex.h b/arch/arm/mach-ebsa110/include/mach/timex.h
deleted file mode 100644
index 4fb43b22a102..000000000000
--- a/arch/arm/mach-ebsa110/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  arch/arm/mach-ebsa110/include/mach/timex.h
- *
- *  Copyright (C) 1997, 1998 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.
- *
- *  EBSA110 architecture timex specifications
- */
-
-/*
- * On the EBSA, the clock ticks at weird rates.
- * This is therefore not used to calculate the
- * divisor.
- */
-#define CLOCK_TICK_RATE		47894000
-
diff --git a/arch/arm/mach-efm32/include/mach/entry-macro.S b/arch/arm/mach-efm32/include/mach/entry-macro.S
deleted file mode 100644
index 322159d5ed91..000000000000
--- a/arch/arm/mach-efm32/include/mach/entry-macro.S
+++ /dev/null
@@ -1,4 +0,0 @@
-/*
- * Empty file waiting for deletion once <mach/entry-macro.S> isn't needed any
- * more. Patch "ARM: v7-M: drop using mach/entry-macro.S" sitting in next.
- */
diff --git a/arch/arm/mach-efm32/include/mach/timex.h b/arch/arm/mach-efm32/include/mach/timex.h
deleted file mode 100644
index 7a8b26da6599..000000000000
--- a/arch/arm/mach-efm32/include/mach/timex.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * Empty file waiting for deletion once <mach/timex.h> isn't needed any more.
- */
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 157ba88433c9..6c705472da6c 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -117,7 +117,7 @@ void __init ep93xx_map_io(void)
 #define EP93XX_TIMER4_CLOCK		983040
 
 #define TIMER1_RELOAD			((EP93XX_TIMER123_CLOCK / HZ) - 1)
-#define TIMER4_TICKS_PER_JIFFY		DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ)
+#define TIMER4_TICKS_PER_JIFFY		DIV_ROUND_CLOSEST(EP93XX_TIMER4_CLOCK, HZ)
 
 static unsigned int last_jiffy_time;
 
diff --git a/arch/arm/mach-ep93xx/include/mach/timex.h b/arch/arm/mach-ep93xx/include/mach/timex.h
deleted file mode 100644
index 6b3503b01fa6..000000000000
--- a/arch/arm/mach-ep93xx/include/mach/timex.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/timex.h
- */
-
-#define CLOCK_TICK_RATE		983040
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 4c414af75ef0..8d197dcdd2c0 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -36,7 +36,6 @@ config ARCH_EXYNOS5
 	select HAVE_ARM_SCU if SMP
 	select HAVE_SMP
 	select PINCTRL
-	select USB_ARCH_HAS_XHCI
 	help
 	  Samsung EXYNOS5 (Cortex-A15) SoC based systems
 
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index f18be40e5b21..025fd8215ca3 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -20,6 +20,7 @@
 #include <clocksource/samsung_pwm.h>
 #include <linux/sched.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
@@ -40,7 +41,6 @@
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 
 #include "common.h"
 #include "regs-pmu.h"
diff --git a/arch/arm/mach-exynos/include/mach/timex.h b/arch/arm/mach-exynos/include/mach/timex.h
deleted file mode 100644
index 6d138750a708..000000000000
--- a/arch/arm/mach-exynos/include/mach/timex.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/timex.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2003-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/timex.h
- *
- * EXYNOS4 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H __FILE__
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-exynos/include/mach/uncompress.h b/arch/arm/mach-exynos/include/mach/uncompress.h
deleted file mode 100644
index 5d7ce36be46f..000000000000
--- a/arch/arm/mach-exynos/include/mach/uncompress.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS - uncompress code
- *
- * 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 __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H __FILE__
-
-#include <asm/mach-types.h>
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static unsigned int __raw_readl(unsigned int ptr)
-{
-	return *((volatile unsigned int *)ptr);
-}
-
-static void arch_detect_cpu(void)
-{
-	u32 chip_id = __raw_readl(EXYNOS_PA_CHIPID);
-
-	/*
-	 * product_id is bits 31:12
-	 * bits 23:20 describe the exynosX family
-	 * bits 27:24 describe the exynosX family in exynos5420
-	 */
-	chip_id >>= 20;
-
-	if ((chip_id & 0x0f) == 0x5 || (chip_id & 0xf0) == 0x50)
-		uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
-	else
-		uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
-
-	/*
-	 * For preventing FIFO overrun or infinite loop of UART console,
-	 * fifo_max should be the minimum fifo size of all of the UART channels
-	 */
-	fifo_mask = S5PV210_UFSTAT_TXMASK;
-	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
-}
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index e00025bbbe89..ba18214c9aca 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -35,56 +35,6 @@
 #include "common.h"
 #include "regs-pmu.h"
 
-#define EXYNOS4_EPLL_LOCK			(S5P_VA_CMU + 0x0C010)
-#define EXYNOS4_VPLL_LOCK			(S5P_VA_CMU + 0x0C020)
-
-#define EXYNOS4_EPLL_CON0			(S5P_VA_CMU + 0x0C110)
-#define EXYNOS4_EPLL_CON1			(S5P_VA_CMU + 0x0C114)
-#define EXYNOS4_VPLL_CON0			(S5P_VA_CMU + 0x0C120)
-#define EXYNOS4_VPLL_CON1			(S5P_VA_CMU + 0x0C124)
-
-#define EXYNOS4_CLKSRC_MASK_TOP			(S5P_VA_CMU + 0x0C310)
-#define EXYNOS4_CLKSRC_MASK_CAM			(S5P_VA_CMU + 0x0C320)
-#define EXYNOS4_CLKSRC_MASK_TV			(S5P_VA_CMU + 0x0C324)
-#define EXYNOS4_CLKSRC_MASK_LCD0		(S5P_VA_CMU + 0x0C334)
-#define EXYNOS4_CLKSRC_MASK_MAUDIO		(S5P_VA_CMU + 0x0C33C)
-#define EXYNOS4_CLKSRC_MASK_FSYS		(S5P_VA_CMU + 0x0C340)
-#define EXYNOS4_CLKSRC_MASK_PERIL0		(S5P_VA_CMU + 0x0C350)
-#define EXYNOS4_CLKSRC_MASK_PERIL1		(S5P_VA_CMU + 0x0C354)
-
-#define EXYNOS4_CLKSRC_MASK_DMC			(S5P_VA_CMU + 0x10300)
-
-#define EXYNOS4_EPLLCON0_LOCKED_SHIFT		(29)
-#define EXYNOS4_VPLLCON0_LOCKED_SHIFT		(29)
-
-#define EXYNOS4210_CLKSRC_MASK_LCD1		(S5P_VA_CMU + 0x0C338)
-
-static const struct sleep_save exynos4_set_clksrc[] = {
-	{ .reg = EXYNOS4_CLKSRC_MASK_TOP		, .val = 0x00000001, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_CAM		, .val = 0x11111111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_TV			, .val = 0x00000111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_LCD0		, .val = 0x00001111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_MAUDIO		, .val = 0x00000001, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_FSYS		, .val = 0x01011111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_PERIL0		, .val = 0x01111111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_PERIL1		, .val = 0x01110111, },
-	{ .reg = EXYNOS4_CLKSRC_MASK_DMC		, .val = 0x00010000, },
-};
-
-static const struct sleep_save exynos4210_set_clksrc[] = {
-	{ .reg = EXYNOS4210_CLKSRC_MASK_LCD1		, .val = 0x00001111, },
-};
-
-static struct sleep_save exynos4_epll_save[] = {
-	SAVE_ITEM(EXYNOS4_EPLL_CON0),
-	SAVE_ITEM(EXYNOS4_EPLL_CON1),
-};
-
-static struct sleep_save exynos4_vpll_save[] = {
-	SAVE_ITEM(EXYNOS4_VPLL_CON0),
-	SAVE_ITEM(EXYNOS4_VPLL_CON1),
-};
-
 static struct sleep_save exynos5_sys_save[] = {
 	SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
 };
@@ -124,10 +74,7 @@ static void exynos_pm_prepare(void)
 
 	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
-	if (!soc_is_exynos5250()) {
-		s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
-		s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
-	} else {
+	if (soc_is_exynos5250()) {
 		s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
 		/* Disable USE_RETENTION of JPEG_MEM_OPTION */
 		tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
@@ -143,15 +90,6 @@ static void exynos_pm_prepare(void)
 	/* ensure at least INFORM0 has the resume address */
 
 	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
-
-	/* Before enter central sequence mode, clock src register have to set */
-
-	if (!soc_is_exynos5250())
-		s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
-
-	if (soc_is_exynos4210())
-		s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
-
 }
 
 static int exynos_pm_add(struct device *dev, struct subsys_interface *sif)
@@ -162,73 +100,6 @@ static int exynos_pm_add(struct device *dev, struct subsys_interface *sif)
 	return 0;
 }
 
-static unsigned long pll_base_rate;
-
-static void exynos4_restore_pll(void)
-{
-	unsigned long pll_con, locktime, lockcnt;
-	unsigned long pll_in_rate;
-	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
-
-	if (pll_base_rate == 0)
-		return;
-
-	pll_in_rate = pll_base_rate;
-
-	/* EPLL */
-	pll_con = exynos4_epll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
-		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
-
-		pll_in_rate /= 1000000;
-
-		locktime = (3000 / pll_in_rate) * p_div;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, EXYNOS4_EPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_epll_save,
-					ARRAY_SIZE(exynos4_epll_save));
-		epll_wait = 1;
-	}
-
-	pll_in_rate = pll_base_rate;
-
-	/* VPLL */
-	pll_con = exynos4_vpll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_in_rate /= 1000000;
-		/* 750us */
-		locktime = 750;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, EXYNOS4_VPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_vpll_save,
-					ARRAY_SIZE(exynos4_vpll_save));
-		vpll_wait = 1;
-	}
-
-	/* Wait PLL locking */
-
-	do {
-		if (epll_wait) {
-			pll_con = __raw_readl(EXYNOS4_EPLL_CON0);
-			if (pll_con & (1 << EXYNOS4_EPLLCON0_LOCKED_SHIFT))
-				epll_wait = 0;
-		}
-
-		if (vpll_wait) {
-			pll_con = __raw_readl(EXYNOS4_VPLL_CON0);
-			if (pll_con & (1 << EXYNOS4_VPLLCON0_LOCKED_SHIFT))
-				vpll_wait = 0;
-		}
-	} while (epll_wait || vpll_wait);
-}
-
 static struct subsys_interface exynos_pm_interface = {
 	.name		= "exynos_pm",
 	.subsys		= &exynos_subsys,
@@ -237,7 +108,6 @@ static struct subsys_interface exynos_pm_interface = {
 
 static __init int exynos_pm_drvinit(void)
 {
-	struct clk *pll_base;
 	unsigned int tmp;
 
 	if (soc_is_exynos5440())
@@ -251,15 +121,6 @@ static __init int exynos_pm_drvinit(void)
 	tmp |= ((0xFF << 8) | (0x1F << 1));
 	__raw_writel(tmp, S5P_WAKEUP_MASK);
 
-	if (!soc_is_exynos5250()) {
-		pll_base = clk_get(NULL, "xtal");
-
-		if (!IS_ERR(pll_base)) {
-			pll_base_rate = clk_get_rate(pll_base);
-			clk_put(pll_base);
-		}
-	}
-
 	return subsys_interface_register(&exynos_pm_interface);
 }
 arch_initcall(exynos_pm_drvinit);
@@ -343,13 +204,8 @@ static void exynos_pm_resume(void)
 
 	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
-	if (!soc_is_exynos5250()) {
-		exynos4_restore_pll();
-
-#ifdef CONFIG_SMP
+	if (IS_ENABLED(CONFIG_SMP) && !soc_is_exynos5250())
 		scu_enable(S5P_VA_SCU);
-#endif
-	}
 
 early_wakeup:
 
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 8fd24882f0b1..fe6570ebbdde 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -22,8 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/sched.h>
 
-#include <plat/devs.h>
-
 #include "regs-pmu.h"
 
 /*
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index 3971104d32d4..5d2725fd878c 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -125,7 +125,7 @@ void __init footbridge_timer_init(void)
 	clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
 }
 
-static u32 notrace footbridge_read_sched_clock(void)
+static u64 notrace footbridge_read_sched_clock(void)
 {
 	return ~*CSR_TIMER3_VALUE;
 }
@@ -138,5 +138,5 @@ void __init footbridge_sched_clock(void)
 	*CSR_TIMER3_CLR = 0;
 	*CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
 
-	setup_sched_clock(footbridge_read_sched_clock, 24, rate);
+	sched_clock_register(footbridge_read_sched_clock, 24, rate);
 }
diff --git a/arch/arm/mach-footbridge/include/mach/timex.h b/arch/arm/mach-footbridge/include/mach/timex.h
deleted file mode 100644
index d0fea9d6d4ab..000000000000
--- a/arch/arm/mach-footbridge/include/mach/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/mach-footbridge/include/mach/timex.h
- *
- *  Copyright (C) 1998 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.
- *
- *  EBSA285 architecture timex specifications
- */
-
-/*
- * We assume a constant here; this satisfies the maths in linux/timex.h
- * and linux/time.h.  CLOCK_TICK_RATE is actually system dependent, but
- * this must be a constant.
- */
-#define CLOCK_TICK_RATE		(50000000/16)
diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c
index 87dff4f5059e..ddf8ec9d203b 100644
--- a/arch/arm/mach-gemini/idle.c
+++ b/arch/arm/mach-gemini/idle.c
@@ -3,7 +3,7 @@
  */
 
 #include <linux/init.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 #include <asm/proc-fns.h>
 
 static void gemini_idle(void)
diff --git a/arch/arm/mach-gemini/include/mach/timex.h b/arch/arm/mach-gemini/include/mach/timex.h
deleted file mode 100644
index dc5690ba975c..000000000000
--- a/arch/arm/mach-gemini/include/mach/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Gemini timex specifications
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute 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.
- */
-
-/* When AHB bus frequency is 150MHz */
-#define CLOCK_TICK_RATE	38000000
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index 0aded64a9ebc..830b76e70250 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -5,7 +5,6 @@ config ARCH_HIGHBANK
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_HAS_OPP
 	select ARCH_SUPPORTS_BIG_ENDIAN
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_AMBA
 	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
@@ -14,14 +13,8 @@ config ARCH_HIGHBANK
 	select ARM_PSCI
 	select ARM_TIMER_SP804
 	select CACHE_L2X0
-	select COMMON_CLK
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select MAILBOX
 	select PL320_MBOX
-	select SPARSE_IRQ
-	select USE_OF
 	select ZONE_DMA if ARM_LPAE
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 1abae5f6a418..9d0a87b025e3 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -3,13 +3,9 @@ config ARCH_HI3xxx
 	select ARM_AMBA
 	select ARM_GIC
 	select ARM_TIMER_SP804
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select CACHE_L2X0
-	select CLKSRC_OF
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select PINCTRL
 	select PINCTRL_SINGLE
 	help
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 33567aa5880f..5740296dc429 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,19 +1,15 @@
 config ARCH_MXC
 	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_CPU_SUSPEND if PM
-	select ARM_PATCH_PHYS_VIRT
 	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_ALLOCATOR
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
-	select MULTI_IRQ_HANDLER
 	select PINCTRL
+	select PM_OPP if PM
 	select SOC_BUS
-	select SPARSE_IRQ
-	select USE_OF
+	select SRAM
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -121,18 +117,16 @@ config SOC_IMX31
 config SOC_IMX35
 	bool
 	select ARCH_MXC_IOMUX_V3
-	select CPU_V6K
 	select HAVE_EPIT
 	select MXC_AVIC
+	select PINCTRL_IMX35
 	select SMP_ON_UP if SMP
-	select PINCTRL
 
 config SOC_IMX5
 	bool
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_OPP
 	select ARCH_MXC_IOMUX_V3
-	select CPU_V7
 	select MXC_TZIC
 
 config	SOC_IMX51
@@ -777,65 +771,50 @@ config	SOC_IMX50
 config	SOC_IMX53
 	bool "i.MX53 support"
 	select HAVE_IMX_SRC
-	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select PINCTRL_IMX53
 	select SOC_IMX5
 
 	help
 	  This enables support for Freescale i.MX53 processor.
 
-config SOC_IMX6Q
-	bool "i.MX6 Quad/DualLite support"
-	select ARCH_HAS_CPUFREQ
-	select ARCH_HAS_OPP
+config SOC_IMX6
+	bool
 	select ARM_ERRATA_754322
-	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
 	select ARM_GIC
-	select CPU_V7
-	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if SMP
 	select HAVE_IMX_ANATOP
 	select HAVE_IMX_GPC
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_SRC
-	select HAVE_SMP
 	select MFD_SYSCON
-	select MIGHT_HAVE_PCI
-	select PCI_DOMAINS if PCI
-	select PINCTRL_IMX6Q
 	select PL310_ERRATA_588369 if CACHE_PL310
 	select PL310_ERRATA_727915 if CACHE_PL310
 	select PL310_ERRATA_769419 if CACHE_PL310
-	select PM_OPP if PM
+
+config SOC_IMX6Q
+	bool "i.MX6 Quad/DualLite support"
+	select ARM_ERRATA_764369 if SMP
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	select MIGHT_HAVE_PCI
+	select PCI_DOMAINS if PCI
+	select PINCTRL_IMX6Q
+	select SOC_IMX6
 
 	help
 	  This enables support for Freescale i.MX6 Quad processor.
 
 config SOC_IMX6SL
 	bool "i.MX6 SoloLite support"
-	select ARM_ERRATA_754322
-	select ARM_ERRATA_775420
-	select ARM_GIC
-	select CPU_V7
-	select HAVE_IMX_ANATOP
-	select HAVE_IMX_GPC
-	select HAVE_IMX_MMDC
-	select HAVE_IMX_SRC
-	select MFD_SYSCON
 	select PINCTRL_IMX6SL
-	select PL310_ERRATA_588369 if CACHE_PL310
-	select PL310_ERRATA_727915 if CACHE_PL310
-	select PL310_ERRATA_769419 if CACHE_PL310
+	select SOC_IMX6
 
 	help
 	  This enables support for Freescale i.MX6 SoloLite processor.
 
 config SOC_VF610
 	bool "Vybrid Family VF610 support"
-	select CPU_V7
 	select ARM_GIC
-	select CLKSRC_OF
 	select PINCTRL_VF610
 	select VF_PIT_TIMER
 	select PL310_ERRATA_588369 if CACHE_PL310
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index ec419649320f..f4ed83032dd0 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
 obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
+obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
 endif
 
 ifdef CONFIG_SND_IMX_SOC
@@ -101,9 +102,11 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
-obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
-# i.MX6SL reuses i.MX6Q code
-obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
+ifeq ($(CONFIG_SUSPEND),y)
+AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
+endif
+obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c
index d7ed66091a2a..bdc2e4630a08 100644
--- a/arch/arm/mach-imx/clk-imx21.c
+++ b/arch/arm/mach-imx/clk-imx21.c
@@ -149,7 +149,6 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
 	clk_register_clkdev(clk[per1], "per", "imx-gpt.1");
 	clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2");
 	clk_register_clkdev(clk[per1], "per", "imx-gpt.2");
-	clk_register_clkdev(clk[pwm_ipg_gate], "pwm", "mxc_pwm.0");
 	clk_register_clkdev(clk[per2], "per", "imx21-cspi.0");
 	clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx21-cspi.0");
 	clk_register_clkdev(clk[per2], "per", "imx21-cspi.1");
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index 69858c78f40d..dc36e6c2f1da 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -265,14 +265,6 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
 	clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1");
 	clk_register_clkdev(clk[cspi3_ipg], NULL, "imx35-cspi.2");
-	clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.0");
-	clk_register_clkdev(clk[per10], "per", "mxc_pwm.0");
-	clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.1");
-	clk_register_clkdev(clk[per10], "per", "mxc_pwm.1");
-	clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.2");
-	clk_register_clkdev(clk[per10], "per", "mxc_pwm.2");
-	clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.3");
-	clk_register_clkdev(clk[per10], "per", "mxc_pwm.3");
 	clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad");
 	clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc");
 	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.0");
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index c6b40f386786..d2da8908b268 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -231,7 +231,6 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.4");
 	clk_register_clkdev(clk[gpt6_ipg_gate], "ipg", "imx-gpt.5");
 	clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.5");
-	clk_register_clkdev(clk[pwm_ipg_gate], NULL, "mxc_pwm.0");
 	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0");
 	clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0");
 	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1");
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 19fca1fdc6fe..568ef0a4de84 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -266,8 +266,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk_register_clkdev(clk[IMX5_CLK_ECSPI2_PER_GATE], "per", "imx51-ecspi.1");
 	clk_register_clkdev(clk[IMX5_CLK_ECSPI2_IPG_GATE], "ipg", "imx51-ecspi.1");
 	clk_register_clkdev(clk[IMX5_CLK_CSPI_IPG_GATE], NULL, "imx35-cspi.2");
-	clk_register_clkdev(clk[IMX5_CLK_PWM1_IPG_GATE], "pwm", "mxc_pwm.0");
-	clk_register_clkdev(clk[IMX5_CLK_PWM2_IPG_GATE], "pwm", "mxc_pwm.1");
 	clk_register_clkdev(clk[IMX5_CLK_I2C1_GATE], NULL, "imx21-i2c.0");
 	clk_register_clkdev(clk[IMX5_CLK_I2C2_GATE], NULL, "imx21-i2c.1");
 	clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.0");
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 4d677f442539..b0e7f9d2c245 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -437,12 +437,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 
 	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
-	clk_register_clkdev(clk[ahb], "ahb", NULL);
-	clk_register_clkdev(clk[cko1], "cko1", NULL);
-	clk_register_clkdev(clk[arm], NULL, "cpu0");
-	clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
-	clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
+	clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
 
 	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
 	    cpu_is_imx6dl()) {
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index 4c86f3035205..f7073c0782fb 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2014 Freescale Semiconductor, 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
@@ -18,27 +18,43 @@
 #include "clk.h"
 #include "common.h"
 
-static const char const *step_sels[]		= { "osc", "pll2_pfd2", };
-static const char const *pll1_sw_sels[]		= { "pll1_sys", "step", };
-static const char const *ocram_alt_sels[]	= { "pll2_pfd2", "pll3_pfd1", };
-static const char const *ocram_sels[]		= { "periph", "ocram_alt_sels", };
-static const char const *pre_periph_sels[]	= { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", };
-static const char const *periph_clk2_sels[]	= { "pll3_usb_otg", "osc", "osc", "dummy", };
-static const char const *periph2_clk2_sels[]	= { "pll3_usb_otg", "pll2_bus", };
-static const char const *periph_sels[]		= { "pre_periph_sel", "periph_clk2_podf", };
-static const char const *periph2_sels[]		= { "pre_periph2_sel", "periph2_clk2_podf", };
-static const char const *csi_lcdif_sels[]	= { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", };
-static const char const *usdhc_sels[]		= { "pll2_pfd2", "pll2_pfd0", };
-static const char const *ssi_sels[]		= { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", };
-static const char const *perclk_sels[]		= { "ipg", "osc", };
-static const char const *epdc_pxp_sels[]	= { "mmdc", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd1", };
-static const char const *gpu2d_ovg_sels[]	= { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", };
-static const char const *gpu2d_sels[]		= { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", };
-static const char const *lcdif_pix_sels[]	= { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", };
-static const char const *epdc_pix_sels[]	= { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", };
-static const char const *audio_sels[]		= { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", };
-static const char const *ecspi_sels[]		= { "pll3_60m", "osc", };
-static const char const *uart_sels[]		= { "pll3_80m", "osc", };
+#define CCSR			0xc
+#define BM_CCSR_PLL1_SW_CLK_SEL	(1 << 2)
+#define CACRR			0x10
+#define CDHIPR			0x48
+#define BM_CDHIPR_ARM_PODF_BUSY	(1 << 16)
+#define ARM_WAIT_DIV_396M	2
+#define ARM_WAIT_DIV_792M	4
+#define ARM_WAIT_DIV_996M	6
+
+#define PLL_ARM			0x0
+#define BM_PLL_ARM_DIV_SELECT	(0x7f << 0)
+#define BM_PLL_ARM_POWERDOWN	(1 << 12)
+#define BM_PLL_ARM_ENABLE	(1 << 13)
+#define BM_PLL_ARM_LOCK		(1 << 31)
+#define PLL_ARM_DIV_792M	66
+
+static const char *step_sels[]		= { "osc", "pll2_pfd2", };
+static const char *pll1_sw_sels[]	= { "pll1_sys", "step", };
+static const char *ocram_alt_sels[]	= { "pll2_pfd2", "pll3_pfd1", };
+static const char *ocram_sels[]		= { "periph", "ocram_alt_sels", };
+static const char *pre_periph_sels[]	= { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", };
+static const char *periph_clk2_sels[]	= { "pll3_usb_otg", "osc", "osc", "dummy", };
+static const char *periph2_clk2_sels[]	= { "pll3_usb_otg", "pll2_bus", };
+static const char *periph_sels[]	= { "pre_periph_sel", "periph_clk2_podf", };
+static const char *periph2_sels[]	= { "pre_periph2_sel", "periph2_clk2_podf", };
+static const char *csi_lcdif_sels[]	= { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", };
+static const char *usdhc_sels[]		= { "pll2_pfd2", "pll2_pfd0", };
+static const char *ssi_sels[]		= { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", };
+static const char *perclk_sels[]	= { "ipg", "osc", };
+static const char *epdc_pxp_sels[]	= { "mmdc", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd1", };
+static const char *gpu2d_ovg_sels[]	= { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", };
+static const char *gpu2d_sels[]		= { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", };
+static const char *lcdif_pix_sels[]	= { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", };
+static const char *epdc_pix_sels[]	= { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", };
+static const char *audio_sels[]		= { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", };
+static const char *ecspi_sels[]		= { "pll3_60m", "osc", };
+static const char *uart_sels[]		= { "pll3_80m", "osc", };
 
 static struct clk_div_table clk_enet_ref_table[] = {
 	{ .val = 0, .div = 20, },
@@ -65,6 +81,89 @@ static struct clk_div_table video_div_table[] = {
 
 static struct clk *clks[IMX6SL_CLK_END];
 static struct clk_onecell_data clk_data;
+static void __iomem *ccm_base;
+static void __iomem *anatop_base;
+
+static const u32 clks_init_on[] __initconst = {
+	IMX6SL_CLK_IPG, IMX6SL_CLK_ARM, IMX6SL_CLK_MMDC_ROOT,
+};
+
+/*
+ * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken
+ *           during WAIT mode entry process could cause cache memory
+ *           corruption.
+ *
+ * Software workaround:
+ *     To prevent this issue from occurring, software should ensure that the
+ * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before
+ * entering WAIT mode.
+ *
+ * This function will set the ARM clk to max value within the 12:5 limit.
+ * As IPG clock is fixed at 66MHz(so ARM freq must not exceed 158.4MHz),
+ * ARM freq are one of below setpoints: 396MHz, 792MHz and 996MHz, since
+ * the clk APIs can NOT be called in idle thread(may cause kernel schedule
+ * as there is sleep function in PLL wait function), so here we just slow
+ * down ARM to below freq according to previous freq:
+ *
+ * run mode      wait mode
+ * 396MHz   ->   132MHz;
+ * 792MHz   ->   158.4MHz;
+ * 996MHz   ->   142.3MHz;
+ */
+static int imx6sl_get_arm_divider_for_wait(void)
+{
+	if (readl_relaxed(ccm_base + CCSR) & BM_CCSR_PLL1_SW_CLK_SEL) {
+		return ARM_WAIT_DIV_396M;
+	} else {
+		if ((readl_relaxed(anatop_base + PLL_ARM) &
+			BM_PLL_ARM_DIV_SELECT) == PLL_ARM_DIV_792M)
+			return ARM_WAIT_DIV_792M;
+		else
+			return ARM_WAIT_DIV_996M;
+	}
+}
+
+static void imx6sl_enable_pll_arm(bool enable)
+{
+	static u32 saved_pll_arm;
+	u32 val;
+
+	if (enable) {
+		saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM);
+		val |= BM_PLL_ARM_ENABLE;
+		val &= ~BM_PLL_ARM_POWERDOWN;
+		writel_relaxed(val, anatop_base + PLL_ARM);
+		while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK))
+			;
+	} else {
+		 writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM);
+	}
+}
+
+void imx6sl_set_wait_clk(bool enter)
+{
+	static unsigned long saved_arm_div;
+	int arm_div_for_wait = imx6sl_get_arm_divider_for_wait();
+
+	/*
+	 * According to hardware design, arm podf change need
+	 * PLL1 clock enabled.
+	 */
+	if (arm_div_for_wait == ARM_WAIT_DIV_396M)
+		imx6sl_enable_pll_arm(true);
+
+	if (enter) {
+		saved_arm_div = readl_relaxed(ccm_base + CACRR);
+		writel_relaxed(arm_div_for_wait, ccm_base + CACRR);
+	} else {
+		writel_relaxed(saved_arm_div, ccm_base + CACRR);
+	}
+	while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY)
+		;
+
+	if (arm_div_for_wait == ARM_WAIT_DIV_396M)
+		imx6sl_enable_pll_arm(false);
+}
 
 static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 {
@@ -72,6 +171,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	void __iomem *base;
 	int irq;
 	int i;
+	int ret;
 
 	clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
 	clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
@@ -80,6 +180,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop");
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
+	anatop_base = base;
 
 	/*                                             type               name            parent  base         div_mask */
 	clks[IMX6SL_CLK_PLL1_SYS]      = imx_clk_pllv3(IMX_PLLV3_SYS,	  "pll1_sys",	   "osc", base,        0x7f);
@@ -127,6 +228,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	np = ccm_node;
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
+	ccm_base = base;
 
 	/* Reuse imx6q pm code */
 	imx6q_pm_set_ccm_base(base);
@@ -258,6 +360,19 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
 
+	/* Ensure the AHB clk is at 132MHz. */
+	ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
+	if (ret)
+		pr_warn("%s: failed to set AHB clock rate %d!\n",
+			__func__, ret);
+
+	/*
+	 * Make sure those always on clocks are enabled to maintain the correct
+	 * usecount and enabling/disabling of parent PLLs.
+	 */
+	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+		clk_prepare_enable(clks[clks_init_on[i]]);
+
 	if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
 		clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]);
 		clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]);
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index ecd66d8e20b6..22dc3ee21fd4 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -63,25 +63,25 @@ static void __iomem *anatop_base;
 static void __iomem *ccm_base;
 
 /* sources for multiplexer clocks, this is used multiple times */
-static const char const *fast_sels[]	= { "firc", "fxosc", };
-static const char const *slow_sels[]	= { "sirc_32k", "sxosc", };
-static const char const *pll1_sels[]	= { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", };
-static const char const *pll2_sels[]	= { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", };
-static const char const *sys_sels[]	= { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", };
-static const char const *ddr_sels[]	= { "pll2_pfd2", "sys_sel", };
-static const char const *rmii_sels[]	= { "enet_ext", "audio_ext", "enet_50m", "enet_25m", };
-static const char const *enet_ts_sels[]	= { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", };
-static const char const *esai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
-static const char const *sai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
-static const char const *nfc_sels[]	= { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", };
-static const char const *qspi_sels[]	= { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", };
-static const char const *esdhc_sels[]	= { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", };
-static const char const *dcu_sels[]	= { "pll1_pfd2", "pll3_main", };
-static const char const *gpu_sels[]	= { "pll2_pfd2", "pll3_pfd2", };
-static const char const *vadc_sels[]	= { "pll6_main_div", "pll3_main_div", "pll3_main", };
+static const char *fast_sels[]	= { "firc", "fxosc", };
+static const char *slow_sels[]	= { "sirc_32k", "sxosc", };
+static const char *pll1_sels[]	= { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", };
+static const char *pll2_sels[]	= { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", };
+static const char *sys_sels[]	= { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", };
+static const char *ddr_sels[]	= { "pll2_pfd2", "sys_sel", };
+static const char *rmii_sels[]	= { "enet_ext", "audio_ext", "enet_50m", "enet_25m", };
+static const char *enet_ts_sels[]	= { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", };
+static const char *esai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
+static const char *sai_sels[]	= { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
+static const char *nfc_sels[]	= { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", };
+static const char *qspi_sels[]	= { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", };
+static const char *esdhc_sels[]	= { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", };
+static const char *dcu_sels[]	= { "pll1_pfd2", "pll3_main", };
+static const char *gpu_sels[]	= { "pll2_pfd2", "pll3_pfd2", };
+static const char *vadc_sels[]	= { "pll6_main_div", "pll3_main_div", "pll3_main", };
 /* FTM counter clock source, not module clock */
-static const char const *ftm_ext_sels[]	= {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", };
-static const char const *ftm_fix_sels[]	= { "sxosc", "ipg_bus", };
+static const char *ftm_ext_sels[]	= {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", };
+static const char *ftm_fix_sels[]	= { "sxosc", "ipg_bus", };
 
 static struct clk_div_table pll4_main_div_table[] = {
 	{ .val = 0, .div = 1 },
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index baf439dc22d8..b5241ea76706 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -116,7 +116,6 @@ void imx_enable_cpu(int cpu, bool enable);
 void imx_set_cpu_jump(int cpu, void *jump_addr);
 u32 imx_get_cpu_arg(int cpu);
 void imx_set_cpu_arg(int cpu, u32 arg);
-void v7_cpu_resume(void);
 #ifdef CONFIG_SMP
 void v7_secondary_startup(void);
 void imx_scu_map_io(void);
@@ -139,13 +138,25 @@ void imx_anatop_init(void);
 void imx_anatop_pre_suspend(void);
 void imx_anatop_post_resume(void);
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-void imx6q_set_chicken_bit(void);
+void imx6q_set_int_mem_clk_lpm(void);
+void imx6sl_set_wait_clk(bool enter);
 
 void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
 
+#ifdef CONFIG_SUSPEND
+void v7_cpu_resume(void);
+void imx6_suspend(void __iomem *ocram_vbase);
+#else
+static inline void v7_cpu_resume(void) {}
+static inline void imx6_suspend(void __iomem *ocram_vbase) {}
+#endif
+
 void imx6q_pm_init(void);
+void imx6dl_pm_init(void);
+void imx6sl_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
+
 #ifdef CONFIG_PM
 void imx5_pm_init(void);
 #else
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index 23ddfb693b2d..6bcae0479049 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -68,8 +68,8 @@ int __init imx6q_cpuidle_init(void)
 	/* Need to enable SCU standby for entering WAIT modes */
 	imx_scu_standby_enable();
 
-	/* Set chicken bit to get a reliable WAIT mode support */
-	imx6q_set_chicken_bit();
+	/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
+	imx6q_set_int_mem_clk_lpm();
 
 	return cpuidle_register(&imx6q_cpuidle_driver, NULL);
 }
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
new file mode 100644
index 000000000000..d4b6b8171fa9
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, 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.
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static int imx6sl_enter_wait(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
+{
+	imx6q_set_lpm(WAIT_UNCLOCKED);
+	/*
+	 * Software workaround for ERR005311, see function
+	 * description for details.
+	 */
+	imx6sl_set_wait_clk(true);
+	cpu_do_idle();
+	imx6sl_set_wait_clk(false);
+	imx6q_set_lpm(WAIT_CLOCKED);
+
+	return index;
+}
+
+static struct cpuidle_driver imx6sl_cpuidle_driver = {
+	.name = "imx6sl_cpuidle",
+	.owner = THIS_MODULE,
+	.states = {
+		/* WFI */
+		ARM_CPUIDLE_WFI_STATE,
+		/* WAIT */
+		{
+			.exit_latency = 50,
+			.target_residency = 75,
+			.flags = CPUIDLE_FLAG_TIME_VALID |
+				CPUIDLE_FLAG_TIMER_STOP,
+			.enter = imx6sl_enter_wait,
+			.name = "WAIT",
+			.desc = "Clock off",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
+int __init imx6sl_cpuidle_init(void)
+{
+	return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index 786f98ecc145..24e33670417c 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -13,6 +13,7 @@
 #ifdef CONFIG_CPU_IDLE
 extern int imx5_cpuidle_init(void);
 extern int imx6q_cpuidle_init(void);
+extern int imx6sl_cpuidle_init(void);
 #else
 static inline int imx5_cpuidle_init(void)
 {
@@ -22,4 +23,8 @@ static inline int imx6q_cpuidle_init(void)
 {
 	return 0;
 }
+static inline int imx6sl_cpuidle_init(void)
+{
+	return 0;
+}
 #endif
diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h
index 769563fdeaa0..61a114cddc39 100644
--- a/arch/arm/mach-imx/devices-imx25.h
+++ b/arch/arm/mach-imx/devices-imx25.h
@@ -83,7 +83,3 @@ extern const struct imx_spi_imx_data imx25_cspi_data[];
 #define imx25_add_spi_imx0(pdata)	imx25_add_spi_imx(0, pdata)
 #define imx25_add_spi_imx1(pdata)	imx25_add_spi_imx(1, pdata)
 #define imx25_add_spi_imx2(pdata)	imx25_add_spi_imx(2, pdata)
-
-extern struct imx_mxc_pwm_data imx25_mxc_pwm_data[];
-#define imx25_add_mxc_pwm(id)	\
-	imx_add_mxc_pwm(&imx25_mxc_pwm_data[id])
diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h
index deee5baee88c..26389f35a2b2 100644
--- a/arch/arm/mach-imx/devices-imx51.h
+++ b/arch/arm/mach-imx/devices-imx51.h
@@ -57,10 +57,6 @@ extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
 #define imx51_add_imx2_wdt(id)	\
 	imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
 
-extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
-#define imx51_add_mxc_pwm(id)	\
-	imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
-
 extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
 #define imx51_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig
index 68c74fb0373c..2d260a5a307c 100644
--- a/arch/arm/mach-imx/devices/Kconfig
+++ b/arch/arm/mach-imx/devices/Kconfig
@@ -67,9 +67,6 @@ config IMX_HAVE_PLATFORM_MXC_MMC
 config IMX_HAVE_PLATFORM_MXC_NAND
 	bool
 
-config IMX_HAVE_PLATFORM_MXC_PWM
-	bool
-
 config IMX_HAVE_PLATFORM_MXC_RNGA
 	bool
 	select ARCH_HAS_RNGA
diff --git a/arch/arm/mach-imx/devices/Makefile b/arch/arm/mach-imx/devices/Makefile
index 67416fb1dc69..1cbc14cd80d1 100644
--- a/arch/arm/mach-imx/devices/Makefile
+++ b/arch/arm/mach-imx/devices/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_PWM) += platform-mxc_pwm.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA) += platform-mxc_rnga.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h
index c13b76b9f6b3..61352a80bb59 100644
--- a/arch/arm/mach-imx/devices/devices-common.h
+++ b/arch/arm/mach-imx/devices/devices-common.h
@@ -290,15 +290,6 @@ struct imx_pata_imx_data {
 struct platform_device *__init imx_add_pata_imx(
 		const struct imx_pata_imx_data *data);
 
-struct imx_mxc_pwm_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mxc_pwm(
-		const struct imx_mxc_pwm_data *data);
-
 /* mxc_rtc */
 struct imx_mxc_rtc_data {
 	const char *devid;
diff --git a/arch/arm/mach-imx/devices/platform-mxc_pwm.c b/arch/arm/mach-imx/devices/platform-mxc_pwm.c
deleted file mode 100644
index dcd289777687..000000000000
--- a/arch/arm/mach-imx/devices/platform-mxc_pwm.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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 "../hardware.h"
-#include "devices-common.h"
-
-#define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _PWM ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_PWM ## _hwid,			\
-	}
-#define imx_mxc_pwm_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_mxc_pwm_data imx21_mxc_pwm_data __initconst =
-	imx_mxc_pwm_data_entry_single(MX21, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst = {
-#define imx25_mxc_pwm_data_entry(_id, _hwid)				\
-	imx_mxc_pwm_data_entry(MX25, _id, _hwid, SZ_16K)
-	imx25_mxc_pwm_data_entry(0, 1),
-	imx25_mxc_pwm_data_entry(1, 2),
-	imx25_mxc_pwm_data_entry(2, 3),
-	imx25_mxc_pwm_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_pwm_data imx27_mxc_pwm_data __initconst =
-	imx_mxc_pwm_data_entry_single(MX27, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = {
-#define imx51_mxc_pwm_data_entry(_id, _hwid)				\
-	imx_mxc_pwm_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_mxc_pwm_data_entry(0, 1),
-	imx51_mxc_pwm_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-struct platform_device *__init imx_add_mxc_pwm(
-		const struct imx_mxc_pwm_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("mxc_pwm", data->id,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index a3b0b04b45c9..abf43bb47eca 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2007, 2014 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
  *
  * This program is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
 #ifndef __ASM_ARCH_MXC_HARDWARE_H__
 #define __ASM_ARCH_MXC_HARDWARE_H__
 
+#ifndef __ASSEMBLY__
 #include <asm/io.h>
+#endif
 #include <asm/sizes.h>
 
 #define addr_in_module(addr, mod) \
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index 627f16f0e9d1..de5047c8a6c8 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -12,12 +12,7 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/asm-offsets.h>
-#include <asm/hardware/cache-l2x0.h>
 
-	.section ".text.head", "ax"
-
-#ifdef CONFIG_SMP
 diag_reg_offset:
 	.word	g_diag_reg - .
 
@@ -34,38 +29,3 @@ ENTRY(v7_secondary_startup)
 	set_diag_reg
 	b	secondary_startup
 ENDPROC(v7_secondary_startup)
-#endif
-
-#ifdef CONFIG_ARM_CPU_SUSPEND
-/*
- * The following code must assume it is running from physical address
- * where absolute virtual addresses to the data section have to be
- * turned into relative ones.
- */
-
-#ifdef CONFIG_CACHE_L2X0
-	.macro	pl310_resume
-	adr	r0, l2x0_saved_regs_offset
-	ldr	r2, [r0]
-	add	r2, r2, r0
-	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
-	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
-	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
-	mov	r1, #0x1
-	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
-	.endm
-
-l2x0_saved_regs_offset:
-	.word	l2x0_saved_regs - .
-
-#else
-	.macro	pl310_resume
-	.endm
-#endif
-
-ENTRY(v7_cpu_resume)
-	bl	v7_invalidate_l1
-	pl310_resume
-	b	cpu_resume
-ENDPROC(v7_cpu_resume)
-#endif
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 76e5db4fce35..e60456d85c9d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -182,16 +182,83 @@ static void __init imx6q_enet_phy_init(void)
 
 static void __init imx6q_1588_init(void)
 {
+	struct device_node *np;
+	struct clk *ptp_clk;
+	struct clk *enet_ref;
 	struct regmap *gpr;
+	u32 clksel;
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
+	if (!np) {
+		pr_warn("%s: failed to find fec node\n", __func__);
+		return;
+	}
+
+	ptp_clk = of_clk_get(np, 2);
+	if (IS_ERR(ptp_clk)) {
+		pr_warn("%s: failed to get ptp clock\n", __func__);
+		goto put_node;
+	}
+
+	enet_ref = clk_get_sys(NULL, "enet_ref");
+	if (IS_ERR(enet_ref)) {
+		pr_warn("%s: failed to get enet clock\n", __func__);
+		goto put_ptp_clk;
+	}
+
+	/*
+	 * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
+	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
+	 * (external OSC), and we need to clear the bit.
+	 */
+	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
+				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
 		regmap_update_bits(gpr, IOMUXC_GPR1,
 				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
-				IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
+				clksel);
 	else
 		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
 
+	clk_put(enet_ref);
+put_ptp_clk:
+	clk_put(ptp_clk);
+put_node:
+	of_node_put(np);
+}
+
+static void __init imx6q_axi_init(void)
+{
+	struct regmap *gpr;
+	unsigned int mask;
+
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr)) {
+		/*
+		 * Enable the cacheable attribute of VPU and IPU
+		 * AXI transactions.
+		 */
+		mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
+			IMX6Q_GPR4_VPU_RD_CACHE_SEL |
+			IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
+			IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
+			IMX6Q_GPR4_IPU_WR_CACHE_CTL |
+			IMX6Q_GPR4_IPU_RD_CACHE_CTL;
+		regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask);
+
+		/* Increase IPU read QoS priority */
+		regmap_update_bits(gpr, IOMUXC_GPR6,
+				IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
+				IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK,
+				(0xf << 16) | (0x7 << 20));
+		regmap_update_bits(gpr, IOMUXC_GPR7,
+				IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
+				IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK,
+				(0xf << 16) | (0x7 << 20));
+	} else {
+		pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
+	}
 }
 
 static void __init imx6q_init_machine(void)
@@ -212,15 +279,18 @@ static void __init imx6q_init_machine(void)
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
 	imx_anatop_init();
-	imx6q_pm_init();
+	cpu_is_imx6q() ?  imx6q_pm_init() : imx6dl_pm_init();
 	imx6q_1588_init();
+	imx6q_axi_init();
 }
 
 #define OCOTP_CFG3			0x440
 #define OCOTP_CFG3_SPEED_SHIFT		16
 #define OCOTP_CFG3_SPEED_1P2GHZ		0x3
+#define OCOTP_CFG3_SPEED_996MHZ		0x2
+#define OCOTP_CFG3_SPEED_852MHZ		0x1
 
-static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
+static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
 {
 	struct device_node *np;
 	void __iomem *base;
@@ -238,11 +308,29 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
 		goto put_node;
 	}
 
+	/*
+	 * SPEED_GRADING[1:0] defines the max speed of ARM:
+	 * 2b'11: 1200000000Hz;
+	 * 2b'10: 996000000Hz;
+	 * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+	 * 2b'00: 792000000Hz;
+	 * We need to set the max speed of ARM according to fuse map.
+	 */
 	val = readl_relaxed(base + OCOTP_CFG3);
 	val >>= OCOTP_CFG3_SPEED_SHIFT;
-	if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
+	val &= 0x3;
+
+	if (val != OCOTP_CFG3_SPEED_1P2GHZ)
 		if (dev_pm_opp_disable(cpu_dev, 1200000000))
 			pr_warn("failed to disable 1.2 GHz OPP\n");
+	if (val < OCOTP_CFG3_SPEED_996MHZ)
+		if (dev_pm_opp_disable(cpu_dev, 996000000))
+			pr_warn("failed to disable 996 MHz OPP\n");
+	if (cpu_is_imx6q()) {
+		if (val != OCOTP_CFG3_SPEED_852MHZ)
+			if (dev_pm_opp_disable(cpu_dev, 852000000))
+				pr_warn("failed to disable 852 MHz OPP\n");
+	}
 
 put_node:
 	of_node_put(np);
@@ -268,7 +356,7 @@ static void __init imx6q_opp_init(void)
 		goto put_node;
 	}
 
-	imx6q_opp_check_1p2ghz(cpu_dev);
+	imx6q_opp_check_speed_grading(cpu_dev);
 
 put_node:
 	of_node_put(np);
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 0f4fd4c0ab8e..ad323385115c 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -17,6 +17,7 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
+#include "cpuidle.h"
 
 static void __init imx6sl_fec_init(void)
 {
@@ -39,6 +40,8 @@ static void __init imx6sl_init_late(void)
 	/* imx6sl reuses imx6q cpufreq driver */
 	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
 		platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
+
+	imx6sl_cpuidle_init();
 }
 
 static void __init imx6sl_init_machine(void)
@@ -55,8 +58,7 @@ static void __init imx6sl_init_machine(void)
 
 	imx6sl_fec_init();
 	imx_anatop_init();
-	/* Reuse imx6q pm code */
-	imx6q_pm_init();
+	imx6sl_pm_init();
 }
 
 static void __init imx6sl_init_irq(void)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 9821b824dcaf..a7a4a9c67615 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -21,6 +21,10 @@
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.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>
@@ -195,14 +199,58 @@ static const struct imxi2c_platform_data mx27ads_i2c1_data __initconst = {
 static struct i2c_board_info mx27ads_i2c_devices[] = {
 };
 
-void lcd_power(int on)
+static void vgpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	if (on)
+	if (value)
 		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG);
 	else
 		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
 }
 
+static int vgpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+	return 0;
+}
+
+#define MX27ADS_LCD_GPIO	(6 * 32)
+
+static struct regulator_consumer_supply mx27ads_lcd_regulator_consumer =
+	REGULATOR_SUPPLY("lcd", "imx-fb.0");
+
+static struct regulator_init_data mx27ads_lcd_regulator_init_data = {
+	.constraints	= {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+},
+	.consumer_supplies	= &mx27ads_lcd_regulator_consumer,
+	.num_consumer_supplies	= 1,
+};
+
+static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = {
+	.supply_name	= "LCD",
+	.microvolts	= 3300000,
+	.gpio		= MX27ADS_LCD_GPIO,
+	.init_data	= &mx27ads_lcd_regulator_init_data,
+};
+
+static void __init mx27ads_regulator_init(void)
+{
+	struct gpio_chip *vchip;
+
+	vchip = kzalloc(sizeof(*vchip), GFP_KERNEL);
+	vchip->owner		= THIS_MODULE;
+	vchip->label		= "LCD";
+	vchip->base		= MX27ADS_LCD_GPIO;
+	vchip->ngpio		= 1;
+	vchip->direction_output	= vgpio_dir_out;
+	vchip->set		= vgpio_set;
+	gpiochip_add(vchip);
+
+	platform_device_register_data(&platform_bus, "reg-fixed-voltage",
+				      PLATFORM_DEVID_AUTO,
+				      &mx27ads_lcd_regulator_pdata,
+				      sizeof(mx27ads_lcd_regulator_pdata));
+}
+
 static struct imx_fb_videomode mx27ads_modes[] = {
 	{
 		.mode = {
@@ -239,8 +287,6 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = {
 	.pwmr		= 0x00A903FF,
 	.lscr1		= 0x00120300,
 	.dmacr		= 0x00020010,
-
-	.lcd_power	= lcd_power,
 };
 
 static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
@@ -304,6 +350,7 @@ static void __init mx27ads_board_init(void)
 	i2c_register_board_info(1, mx27ads_i2c_devices,
 				ARRAY_SIZE(mx27ads_i2c_devices));
 	imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
+	mx27ads_regulator_init();
 	imx27_add_imx_fb(&mx27ads_fb_data);
 	imx27_add_mxc_mmc(0, &sdhc1_pdata);
 	imx27_add_mxc_mmc(1, &sdhc2_pdata);
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index b3738e616f19..8f45afe785f8 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -128,27 +128,15 @@ static struct platform_device mx31moboard_flash = {
 	.num_resources = 1,
 };
 
-static int moboard_uart0_init(struct platform_device *pdev)
+static void __init moboard_uart0_init(void)
 {
-	int ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack");
-	if (ret)
-		return ret;
-
-	ret = gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
-	if (ret)
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack")) {
+		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
 		gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
-
-	return ret;
-}
-
-static void moboard_uart0_exit(struct platform_device *pdev)
-{
-	gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
+	}
 }
 
 static const struct imxuart_platform_data uart0_pdata __initconst = {
-	.init = moboard_uart0_init,
-	.exit = moboard_uart0_exit,
 };
 
 static const struct imxuart_platform_data uart4_pdata __initconst = {
@@ -543,6 +531,7 @@ static void __init mx31moboard_init(void)
 
 	imx31_add_imx2_wdt();
 
+	moboard_uart0_init();
 	imx31_add_imx_uart0(&uart0_pdata);
 	imx31_add_imx_uart4(&uart4_pdata);
 
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
new file mode 100644
index 000000000000..16f0d249f6a7
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright 2011-2014 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/genalloc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include "common.h"
+#include "hardware.h"
+
+#define CCR				0x0
+#define BM_CCR_WB_COUNT			(0x7 << 16)
+#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
+#define BM_CCR_RBC_EN			(0x1 << 27)
+
+#define CLPCR				0x54
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define CGPR				0x64
+#define BM_CGPR_INT_MEM_CLK_LPM		(0x1 << 17)
+
+#define MX6Q_SUSPEND_OCRAM_SIZE		0x1000
+#define MX6_MAX_MMDC_IO_NUM		33
+
+static void __iomem *ccm_base;
+static void __iomem *suspend_ocram_base;
+static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
+
+/*
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ *                              .
+ *                              .
+ *                              .
+ *                              ^
+ *                              ^
+ *                              ^
+ *                      imx6_suspend code
+ *              PM_INFO structure(imx6_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+struct imx6_pm_base {
+	phys_addr_t pbase;
+	void __iomem *vbase;
+};
+
+struct imx6_pm_socdata {
+	u32 cpu_type;
+	const char *mmdc_compat;
+	const char *src_compat;
+	const char *iomuxc_compat;
+	const char *gpc_compat;
+	const u32 mmdc_io_num;
+	const u32 *mmdc_io_offset;
+};
+
+static const u32 imx6q_mmdc_io_offset[] __initconst = {
+	0x5ac, 0x5b4, 0x528, 0x520, /* DQM0 ~ DQM3 */
+	0x514, 0x510, 0x5bc, 0x5c4, /* DQM4 ~ DQM7 */
+	0x56c, 0x578, 0x588, 0x594, /* CAS, RAS, SDCLK_0, SDCLK_1 */
+	0x5a8, 0x5b0, 0x524, 0x51c, /* SDQS0 ~ SDQS3 */
+	0x518, 0x50c, 0x5b8, 0x5c0, /* SDQS4 ~ SDQS7 */
+	0x784, 0x788, 0x794, 0x79c, /* GPR_B0DS ~ GPR_B3DS */
+	0x7a0, 0x7a4, 0x7a8, 0x748, /* GPR_B4DS ~ GPR_B7DS */
+	0x59c, 0x5a0, 0x750, 0x774, /* SODT0, SODT1, MODE_CTL, MODE */
+	0x74c,			    /* GPR_ADDS */
+};
+
+static const u32 imx6dl_mmdc_io_offset[] __initconst = {
+	0x470, 0x474, 0x478, 0x47c, /* DQM0 ~ DQM3 */
+	0x480, 0x484, 0x488, 0x48c, /* DQM4 ~ DQM7 */
+	0x464, 0x490, 0x4ac, 0x4b0, /* CAS, RAS, SDCLK_0, SDCLK_1 */
+	0x4bc, 0x4c0, 0x4c4, 0x4c8, /* DRAM_SDQS0 ~ DRAM_SDQS3 */
+	0x4cc, 0x4d0, 0x4d4, 0x4d8, /* DRAM_SDQS4 ~ DRAM_SDQS7 */
+	0x764, 0x770, 0x778, 0x77c, /* GPR_B0DS ~ GPR_B3DS */
+	0x780, 0x784, 0x78c, 0x748, /* GPR_B4DS ~ GPR_B7DS */
+	0x4b4, 0x4b8, 0x750, 0x760, /* SODT0, SODT1, MODE_CTL, MODE */
+	0x74c,			    /* GPR_ADDS */
+};
+
+static const u32 imx6sl_mmdc_io_offset[] __initconst = {
+	0x30c, 0x310, 0x314, 0x318, /* DQM0 ~ DQM3 */
+	0x5c4, 0x5cc, 0x5d4, 0x5d8, /* GPR_B0DS ~ GPR_B3DS */
+	0x300, 0x31c, 0x338, 0x5ac, /* CAS, RAS, SDCLK_0, GPR_ADDS */
+	0x33c, 0x340, 0x5b0, 0x5c0, /* SODT0, SODT1, MODE_CTL, MODE */
+	0x330, 0x334, 0x320,        /* SDCKE0, SDCKE1, RESET */
+};
+
+static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
+	.cpu_type = MXC_CPU_IMX6Q,
+	.mmdc_compat = "fsl,imx6q-mmdc",
+	.src_compat = "fsl,imx6q-src",
+	.iomuxc_compat = "fsl,imx6q-iomuxc",
+	.gpc_compat = "fsl,imx6q-gpc",
+	.mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
+	.mmdc_io_offset = imx6q_mmdc_io_offset,
+};
+
+static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
+	.cpu_type = MXC_CPU_IMX6DL,
+	.mmdc_compat = "fsl,imx6q-mmdc",
+	.src_compat = "fsl,imx6q-src",
+	.iomuxc_compat = "fsl,imx6dl-iomuxc",
+	.gpc_compat = "fsl,imx6q-gpc",
+	.mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
+	.mmdc_io_offset = imx6dl_mmdc_io_offset,
+};
+
+static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
+	.cpu_type = MXC_CPU_IMX6SL,
+	.mmdc_compat = "fsl,imx6sl-mmdc",
+	.src_compat = "fsl,imx6sl-src",
+	.iomuxc_compat = "fsl,imx6sl-iomuxc",
+	.gpc_compat = "fsl,imx6sl-gpc",
+	.mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
+	.mmdc_io_offset = imx6sl_mmdc_io_offset,
+};
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/suspend-imx6.S must be also changed accordingly,
+ * otherwise, the suspend to ocram function will be broken!
+ */
+struct imx6_cpu_pm_info {
+	phys_addr_t pbase; /* The physical address of pm_info. */
+	phys_addr_t resume_addr; /* The physical resume address for asm code */
+	u32 cpu_type;
+	u32 pm_info_size; /* Size of pm_info. */
+	struct imx6_pm_base mmdc_base;
+	struct imx6_pm_base src_base;
+	struct imx6_pm_base iomuxc_base;
+	struct imx6_pm_base ccm_base;
+	struct imx6_pm_base gpc_base;
+	struct imx6_pm_base l2_base;
+	u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
+	u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+void imx6q_set_int_mem_clk_lpm(void)
+{
+	u32 val = readl_relaxed(ccm_base + CGPR);
+
+	val |= BM_CGPR_INT_MEM_CLK_LPM;
+	writel_relaxed(val, ccm_base + CGPR);
+}
+
+static void imx6q_enable_rbc(bool enable)
+{
+	u32 val;
+
+	/*
+	 * need to mask all interrupts in GPC before
+	 * operating RBC configurations
+	 */
+	imx_gpc_mask_all();
+
+	/* configure RBC enable bit */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_EN;
+	val |= enable ? BM_CCR_RBC_EN : 0;
+	writel_relaxed(val, ccm_base + CCR);
+
+	/* configure RBC count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_BYPASS_COUNT;
+	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
+	writel(val, ccm_base + CCR);
+
+	/*
+	 * need to delay at least 2 cycles of CKIL(32K)
+	 * due to hardware design requirement, which is
+	 * ~61us, here we use 65us for safe
+	 */
+	udelay(65);
+
+	/* restore GPC interrupt mask settings */
+	imx_gpc_restore_all();
+}
+
+static void imx6q_enable_wb(bool enable)
+{
+	u32 val;
+
+	/* configure well bias enable bit */
+	val = readl_relaxed(ccm_base + CLPCR);
+	val &= ~BM_CLPCR_WB_PER_AT_LPM;
+	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
+	writel_relaxed(val, ccm_base + CLPCR);
+
+	/* configure well bias count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_WB_COUNT;
+	val |= enable ? BM_CCR_WB_COUNT : 0;
+	writel_relaxed(val, ccm_base + CCR);
+}
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	struct irq_desc *iomuxc_irq_desc;
+	u32 val = readl_relaxed(ccm_base + CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		if (cpu_is_imx6sl()) {
+			val |= BM_CLPCR_BYPASS_PMIC_READY;
+			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+		} else {
+			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * ERR007265: CCM: When improper low-power sequence is used,
+	 * the SoC enters low power mode before the ARM core executes WFI.
+	 *
+	 * Software workaround:
+	 * 1) Software should trigger IRQ #32 (IOMUX) to be always pending
+	 *    by setting IOMUX_GPR1_GINT.
+	 * 2) Software should then unmask IRQ #32 in GPC before setting CCM
+	 *    Low-Power mode.
+	 * 3) Software should mask IRQ #32 right after CCM Low-Power mode
+	 *    is set (set bits 0-1 of CCM_CLPCR).
+	 */
+	iomuxc_irq_desc = irq_to_desc(32);
+	imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
+	writel_relaxed(val, ccm_base + CLPCR);
+	imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
+
+	return 0;
+}
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+	if (!imx6_suspend_in_ocram_fn) {
+		cpu_do_idle();
+	} else {
+		/*
+		 * call low level suspend function in ocram,
+		 * as we need to float DDR IO.
+		 */
+		local_flush_tlb_all();
+		imx6_suspend_in_ocram_fn(suspend_ocram_base);
+	}
+
+	return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		imx6q_set_lpm(STOP_POWER_OFF);
+		imx6q_enable_wb(true);
+		/*
+		 * For suspend into ocram, asm code already take care of
+		 * RBC setting, so we do NOT need to do that here.
+		 */
+		if (!imx6_suspend_in_ocram_fn)
+			imx6q_enable_rbc(true);
+		imx_gpc_pre_suspend();
+		imx_anatop_pre_suspend();
+		imx_set_cpu_jump(0, v7_cpu_resume);
+		/* Zzz ... */
+		cpu_suspend(0, imx6q_suspend_finish);
+		if (cpu_is_imx6q() || cpu_is_imx6dl())
+			imx_smp_prepare();
+		imx_anatop_post_resume();
+		imx_gpc_post_resume();
+		imx6q_enable_rbc(false);
+		imx6q_enable_wb(false);
+		imx6q_set_lpm(WAIT_CLOCKED);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+	.enter = imx6q_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_set_ccm_base(void __iomem *base)
+{
+	ccm_base = base;
+}
+
+static int __init imx6_pm_get_base(struct imx6_pm_base *base,
+				const char *compat)
+{
+	struct device_node *node;
+	struct resource res;
+	int ret = 0;
+
+	node = of_find_compatible_node(NULL, NULL, compat);
+	if (!node) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret)
+		goto put_node;
+
+	base->pbase = res.start;
+	base->vbase = ioremap(res.start, resource_size(&res));
+	if (!base->vbase)
+		ret = -ENOMEM;
+
+put_node:
+	of_node_put(node);
+out:
+	return ret;
+}
+
+static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
+{
+	phys_addr_t ocram_pbase;
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct imx6_cpu_pm_info *pm_info;
+	struct gen_pool *ocram_pool;
+	unsigned long ocram_base;
+	int i, ret = 0;
+	const u32 *mmdc_offset_array;
+
+	suspend_set_ops(&imx6q_pm_ops);
+
+	if (!socdata) {
+		pr_warn("%s: invalid argument!\n", __func__);
+		return -EINVAL;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "mmio-sram");
+	if (!node) {
+		pr_warn("%s: failed to find ocram node!\n", __func__);
+		return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(node);
+	if (!pdev) {
+		pr_warn("%s: failed to find ocram device!\n", __func__);
+		ret = -ENODEV;
+		goto put_node;
+	}
+
+	ocram_pool = dev_get_gen_pool(&pdev->dev);
+	if (!ocram_pool) {
+		pr_warn("%s: ocram pool unavailable!\n", __func__);
+		ret = -ENODEV;
+		goto put_node;
+	}
+
+	ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
+	if (!ocram_base) {
+		pr_warn("%s: unable to alloc ocram!\n", __func__);
+		ret = -ENOMEM;
+		goto put_node;
+	}
+
+	ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
+
+	suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
+		MX6Q_SUSPEND_OCRAM_SIZE, false);
+
+	pm_info = suspend_ocram_base;
+	pm_info->pbase = ocram_pbase;
+	pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
+	pm_info->pm_info_size = sizeof(*pm_info);
+
+	/*
+	 * ccm physical address is not used by asm code currently,
+	 * so get ccm virtual address directly, as we already have
+	 * it from ccm driver.
+	 */
+	pm_info->ccm_base.vbase = ccm_base;
+
+	ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
+	if (ret) {
+		pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
+		goto put_node;
+	}
+
+	ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
+	if (ret) {
+		pr_warn("%s: failed to get src base %d!\n", __func__, ret);
+		goto src_map_failed;
+	}
+
+	ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat);
+	if (ret) {
+		pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret);
+		goto iomuxc_map_failed;
+	}
+
+	ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
+	if (ret) {
+		pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
+		goto gpc_map_failed;
+	}
+
+	ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
+	if (ret) {
+		pr_warn("%s: failed to get pl310-cache base %d!\n",
+			__func__, ret);
+		goto pl310_cache_map_failed;
+	}
+
+	pm_info->cpu_type = socdata->cpu_type;
+	pm_info->mmdc_io_num = socdata->mmdc_io_num;
+	mmdc_offset_array = socdata->mmdc_io_offset;
+
+	for (i = 0; i < pm_info->mmdc_io_num; i++) {
+		pm_info->mmdc_io_val[i][0] =
+			mmdc_offset_array[i];
+		pm_info->mmdc_io_val[i][1] =
+			readl_relaxed(pm_info->iomuxc_base.vbase +
+			mmdc_offset_array[i]);
+	}
+
+	imx6_suspend_in_ocram_fn = fncpy(
+		suspend_ocram_base + sizeof(*pm_info),
+		&imx6_suspend,
+		MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
+
+	goto put_node;
+
+pl310_cache_map_failed:
+	iounmap(&pm_info->gpc_base.vbase);
+gpc_map_failed:
+	iounmap(&pm_info->iomuxc_base.vbase);
+iomuxc_map_failed:
+	iounmap(&pm_info->src_base.vbase);
+src_map_failed:
+	iounmap(&pm_info->mmdc_base.vbase);
+put_node:
+	of_node_put(node);
+
+	return ret;
+}
+
+static void __init imx6_pm_common_init(const struct imx6_pm_socdata
+					*socdata)
+{
+	struct regmap *gpr;
+	int ret;
+
+	WARN_ON(!ccm_base);
+
+	if (IS_ENABLED(CONFIG_SUSPEND)) {
+		ret = imx6q_suspend_init(socdata);
+		if (ret)
+			pr_warn("%s: No DDR LPM support with suspend %d!\n",
+				__func__, ret);
+	}
+
+	/*
+	 * This is for SW workaround step #1 of ERR007265, see comments
+	 * in imx6q_set_lpm for details of this errata.
+	 * Force IOMUXC irq pending, so that the interrupt to GPC can be
+	 * used to deassert dsm_request signal when the signal gets
+	 * asserted unexpectedly.
+	 */
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr))
+		regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
+				   IMX6Q_GPR1_GINT);
+}
+
+void __init imx6q_pm_init(void)
+{
+	imx6_pm_common_init(&imx6q_pm_data);
+}
+
+void __init imx6dl_pm_init(void)
+{
+	imx6_pm_common_init(&imx6dl_pm_data);
+}
+
+void __init imx6sl_pm_init(void)
+{
+	imx6_pm_common_init(&imx6sl_pm_data);
+}
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
deleted file mode 100644
index 7a9b98589db7..000000000000
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/regmap.h>
-#include <linux/suspend.h>
-#include <asm/cacheflush.h>
-#include <asm/proc-fns.h>
-#include <asm/suspend.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include "common.h"
-#include "hardware.h"
-
-#define CCR				0x0
-#define BM_CCR_WB_COUNT			(0x7 << 16)
-#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
-#define BM_CCR_RBC_EN			(0x1 << 27)
-
-#define CLPCR				0x54
-#define BP_CLPCR_LPM			0
-#define BM_CLPCR_LPM			(0x3 << 0)
-#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
-#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
-#define BM_CLPCR_SBYOS			(0x1 << 6)
-#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
-#define BM_CLPCR_VSTBY			(0x1 << 8)
-#define BP_CLPCR_STBY_COUNT		9
-#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
-#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
-#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
-#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
-#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
-#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
-#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
-#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
-#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
-#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
-#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
-#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
-
-#define CGPR				0x64
-#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
-
-static void __iomem *ccm_base;
-
-void imx6q_set_chicken_bit(void)
-{
-	u32 val = readl_relaxed(ccm_base + CGPR);
-
-	val |= BM_CGPR_CHICKEN_BIT;
-	writel_relaxed(val, ccm_base + CGPR);
-}
-
-static void imx6q_enable_rbc(bool enable)
-{
-	u32 val;
-
-	/*
-	 * need to mask all interrupts in GPC before
-	 * operating RBC configurations
-	 */
-	imx_gpc_mask_all();
-
-	/* configure RBC enable bit */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_EN;
-	val |= enable ? BM_CCR_RBC_EN : 0;
-	writel_relaxed(val, ccm_base + CCR);
-
-	/* configure RBC count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_BYPASS_COUNT;
-	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
-	writel(val, ccm_base + CCR);
-
-	/*
-	 * need to delay at least 2 cycles of CKIL(32K)
-	 * due to hardware design requirement, which is
-	 * ~61us, here we use 65us for safe
-	 */
-	udelay(65);
-
-	/* restore GPC interrupt mask settings */
-	imx_gpc_restore_all();
-}
-
-static void imx6q_enable_wb(bool enable)
-{
-	u32 val;
-
-	/* configure well bias enable bit */
-	val = readl_relaxed(ccm_base + CLPCR);
-	val &= ~BM_CLPCR_WB_PER_AT_LPM;
-	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
-	writel_relaxed(val, ccm_base + CLPCR);
-
-	/* configure well bias count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_WB_COUNT;
-	val |= enable ? BM_CCR_WB_COUNT : 0;
-	writel_relaxed(val, ccm_base + CCR);
-}
-
-int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
-{
-	struct irq_desc *iomuxc_irq_desc;
-	u32 val = readl_relaxed(ccm_base + CLPCR);
-
-	val &= ~BM_CLPCR_LPM;
-	switch (mode) {
-	case WAIT_CLOCKED:
-		break;
-	case WAIT_UNCLOCKED:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
-		break;
-	case STOP_POWER_ON:
-		val |= 0x2 << BP_CLPCR_LPM;
-		break;
-	case WAIT_UNCLOCKED_POWER_OFF:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val &= ~BM_CLPCR_VSTBY;
-		val &= ~BM_CLPCR_SBYOS;
-		break;
-	case STOP_POWER_OFF:
-		val |= 0x2 << BP_CLPCR_LPM;
-		val |= 0x3 << BP_CLPCR_STBY_COUNT;
-		val |= BM_CLPCR_VSTBY;
-		val |= BM_CLPCR_SBYOS;
-		if (cpu_is_imx6sl()) {
-			val |= BM_CLPCR_BYPASS_PMIC_READY;
-			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
-		} else {
-			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * ERR007265: CCM: When improper low-power sequence is used,
-	 * the SoC enters low power mode before the ARM core executes WFI.
-	 *
-	 * Software workaround:
-	 * 1) Software should trigger IRQ #32 (IOMUX) to be always pending
-	 *    by setting IOMUX_GPR1_GINT.
-	 * 2) Software should then unmask IRQ #32 in GPC before setting CCM
-	 *    Low-Power mode.
-	 * 3) Software should mask IRQ #32 right after CCM Low-Power mode
-	 *    is set (set bits 0-1 of CCM_CLPCR).
-	 */
-	iomuxc_irq_desc = irq_to_desc(32);
-	imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
-	writel_relaxed(val, ccm_base + CLPCR);
-	imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
-
-	return 0;
-}
-
-static int imx6q_suspend_finish(unsigned long val)
-{
-	cpu_do_idle();
-	return 0;
-}
-
-static int imx6q_pm_enter(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-		imx6q_set_lpm(STOP_POWER_OFF);
-		imx6q_enable_wb(true);
-		imx6q_enable_rbc(true);
-		imx_gpc_pre_suspend();
-		imx_anatop_pre_suspend();
-		imx_set_cpu_jump(0, v7_cpu_resume);
-		/* Zzz ... */
-		cpu_suspend(0, imx6q_suspend_finish);
-		if (cpu_is_imx6q() || cpu_is_imx6dl())
-			imx_smp_prepare();
-		imx_anatop_post_resume();
-		imx_gpc_post_resume();
-		imx6q_enable_rbc(false);
-		imx6q_enable_wb(false);
-		imx6q_set_lpm(WAIT_CLOCKED);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct platform_suspend_ops imx6q_pm_ops = {
-	.enter = imx6q_pm_enter,
-	.valid = suspend_valid_only_mem,
-};
-
-void __init imx6q_pm_set_ccm_base(void __iomem *base)
-{
-	ccm_base = base;
-}
-
-void __init imx6q_pm_init(void)
-{
-	struct regmap *gpr;
-
-	WARN_ON(!ccm_base);
-
-	/*
-	 * This is for SW workaround step #1 of ERR007265, see comments
-	 * in imx6q_set_lpm for details of this errata.
-	 * Force IOMUXC irq pending, so that the interrupt to GPC can be
-	 * used to deassert dsm_request signal when the signal gets
-	 * asserted unexpectedly.
-	 */
-	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
-	if (!IS_ERR(gpr))
-		regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
-				   IMX6Q_GPR1_GINT);
-
-
-	suspend_set_ops(&imx6q_pm_ops);
-}
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
new file mode 100644
index 000000000000..20048ff05739
--- /dev/null
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -0,0 +1,361 @@
+/*
+ * 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
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "hardware.h"
+
+/*
+ * ==================== low level suspend ====================
+ *
+ * Better to follow below rules to use ARM registers:
+ * r0: pm_info structure address;
+ * r1 ~ r4: for saving pm_info members;
+ * r5 ~ r10: free registers;
+ * r11: io base address.
+ *
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ *                              .
+ *                              .
+ *                              .
+ *                              ^
+ *                              ^
+ *                              ^
+ *                      imx6_suspend code
+ *              PM_INFO structure(imx6_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+/*
+ * Below offsets are based on struct imx6_cpu_pm_info
+ * which defined in arch/arm/mach-imx/pm-imx6q.c, this
+ * structure contains necessary pm info for low level
+ * suspend related code.
+ */
+#define PM_INFO_PBASE_OFFSET			0x0
+#define PM_INFO_RESUME_ADDR_OFFSET		0x4
+#define PM_INFO_CPU_TYPE_OFFSET			0x8
+#define PM_INFO_PM_INFO_SIZE_OFFSET		0xC
+#define PM_INFO_MX6Q_MMDC_P_OFFSET		0x10
+#define PM_INFO_MX6Q_MMDC_V_OFFSET		0x14
+#define PM_INFO_MX6Q_SRC_P_OFFSET		0x18
+#define PM_INFO_MX6Q_SRC_V_OFFSET		0x1C
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET		0x20
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET		0x24
+#define PM_INFO_MX6Q_CCM_P_OFFSET		0x28
+#define PM_INFO_MX6Q_CCM_V_OFFSET		0x2C
+#define PM_INFO_MX6Q_GPC_P_OFFSET		0x30
+#define PM_INFO_MX6Q_GPC_V_OFFSET		0x34
+#define PM_INFO_MX6Q_L2_P_OFFSET		0x38
+#define PM_INFO_MX6Q_L2_V_OFFSET		0x3C
+#define PM_INFO_MMDC_IO_NUM_OFFSET		0x40
+#define PM_INFO_MMDC_IO_VAL_OFFSET		0x44
+
+#define MX6Q_SRC_GPR1	0x20
+#define MX6Q_SRC_GPR2	0x24
+#define MX6Q_MMDC_MAPSR	0x404
+#define MX6Q_MMDC_MPDGCTRL0	0x83c
+#define MX6Q_GPC_IMR1	0x08
+#define MX6Q_GPC_IMR2	0x0c
+#define MX6Q_GPC_IMR3	0x10
+#define MX6Q_GPC_IMR4	0x14
+#define MX6Q_CCM_CCR	0x0
+
+	.align 3
+
+	.macro  sync_l2_cache
+
+	/* sync L2 cache to drain L2's buffers to DRAM. */
+#ifdef CONFIG_CACHE_L2X0
+	ldr	r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+	mov	r6, #0x0
+	str	r6, [r11, #L2X0_CACHE_SYNC]
+1:
+	ldr	r6, [r11, #L2X0_CACHE_SYNC]
+	ands	r6, r6, #0x1
+	bne	1b
+#endif
+
+	.endm
+
+	.macro	resume_mmdc
+
+	/* restore MMDC IO */
+	cmp	r5, #0x0
+	ldreq	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+	ldrne	r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+	ldr	r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+	ldr	r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+	add	r7, r7, r0
+1:
+	ldr	r8, [r7], #0x4
+	ldr	r9, [r7], #0x4
+	str	r9, [r11, r8]
+	subs	r6, r6, #0x1
+	bne	1b
+
+	cmp	r5, #0x0
+	ldreq	r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+	ldrne	r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
+
+	cmp 	r3, #MXC_CPU_IMX6SL
+	bne	4f
+
+	/* reset read FIFO, RST_RD_FIFO */
+	ldr	r7, =MX6Q_MMDC_MPDGCTRL0
+	ldr	r6, [r11, r7]
+	orr     r6, r6, #(1 << 31)
+	str	r6, [r11, r7]
+2:
+	ldr	r6, [r11, r7]
+	ands	r6, r6, #(1 << 31)
+	bne	2b
+
+	/* reset FIFO a second time */
+	ldr	r6, [r11, r7]
+	orr     r6, r6, #(1 << 31)
+	str	r6, [r11, r7]
+3:
+	ldr	r6, [r11, r7]
+	ands	r6, r6, #(1 << 31)
+	bne	3b
+4:
+	/* let DDR out of self-refresh */
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	bic	r7, r7, #(1 << 21)
+	str	r7, [r11, #MX6Q_MMDC_MAPSR]
+5:
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	ands	r7, r7, #(1 << 25)
+	bne	5b
+
+	/* enable DDR auto power saving */
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	bic	r7, r7, #0x1
+	str	r7, [r11, #MX6Q_MMDC_MAPSR]
+
+	.endm
+
+ENTRY(imx6_suspend)
+	ldr	r1, [r0, #PM_INFO_PBASE_OFFSET]
+	ldr	r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+	ldr	r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+	ldr	r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+	/*
+	 * counting the resume address in iram
+	 * to set it in SRC register.
+	 */
+	ldr	r6, =imx6_suspend
+	ldr	r7, =resume
+	sub	r7, r7, r6
+	add	r8, r1, r4
+	add	r9, r8, r7
+
+	/*
+	 * make sure TLB contain the addr we want,
+	 * as we will access them after MMDC IO floated.
+	 */
+
+	ldr	r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+	ldr	r6, [r11, #0x0]
+	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+	ldr	r6, [r11, #0x0]
+
+	/* use r11 to store the IO address */
+	ldr	r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
+	/* store physical resume addr and pm_info address. */
+	str	r9, [r11, #MX6Q_SRC_GPR1]
+	str	r1, [r11, #MX6Q_SRC_GPR2]
+
+	/* need to sync L2 cache before DSM. */
+	sync_l2_cache
+
+	ldr	r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+	/*
+	 * put DDR explicitly into self-refresh and
+	 * disable automatic power savings.
+	 */
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	orr	r7, r7, #0x1
+	str	r7, [r11, #MX6Q_MMDC_MAPSR]
+
+	/* make the DDR explicitly enter self-refresh. */
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	orr	r7, r7, #(1 << 21)
+	str	r7, [r11, #MX6Q_MMDC_MAPSR]
+
+poll_dvfs_set:
+	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
+	ands	r7, r7, #(1 << 25)
+	beq	poll_dvfs_set
+
+	ldr	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+	ldr	r6, =0x0
+	ldr	r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+	ldr	r8, =PM_INFO_MMDC_IO_VAL_OFFSET
+	add	r8, r8, r0
+	/* i.MX6SL's last 3 IOs need special setting */
+	cmp	r3, #MXC_CPU_IMX6SL
+	subeq	r7, r7, #0x3
+set_mmdc_io_lpm:
+	ldr	r9, [r8], #0x8
+	str	r6, [r11, r9]
+	subs	r7, r7, #0x1
+	bne	set_mmdc_io_lpm
+
+	cmp 	r3, #MXC_CPU_IMX6SL
+	bne	set_mmdc_io_lpm_done
+	ldr	r6, =0x1000
+	ldr	r9, [r8], #0x8
+	str	r6, [r11, r9]
+	ldr	r9, [r8], #0x8
+	str	r6, [r11, r9]
+	ldr	r6, =0x80000
+	ldr	r9, [r8]
+	str	r6, [r11, r9]
+set_mmdc_io_lpm_done:
+
+	/*
+	 * mask all GPC interrupts before
+	 * enabling the RBC counters to
+	 * avoid the counter starting too
+	 * early if an interupt is already
+	 * pending.
+	 */
+	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+	ldr	r6, [r11, #MX6Q_GPC_IMR1]
+	ldr	r7, [r11, #MX6Q_GPC_IMR2]
+	ldr	r8, [r11, #MX6Q_GPC_IMR3]
+	ldr	r9, [r11, #MX6Q_GPC_IMR4]
+
+	ldr	r10, =0xffffffff
+	str	r10, [r11, #MX6Q_GPC_IMR1]
+	str	r10, [r11, #MX6Q_GPC_IMR2]
+	str	r10, [r11, #MX6Q_GPC_IMR3]
+	str	r10, [r11, #MX6Q_GPC_IMR4]
+
+	/*
+	 * enable the RBC bypass counter here
+	 * to hold off the interrupts. RBC counter
+	 * = 32 (1ms), Minimum RBC delay should be
+	 * 400us for the analog LDOs to power down.
+	 */
+	ldr	r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+	ldr	r10, [r11, #MX6Q_CCM_CCR]
+	bic	r10, r10, #(0x3f << 21)
+	orr	r10, r10, #(0x20 << 21)
+	str	r10, [r11, #MX6Q_CCM_CCR]
+
+	/* enable the counter. */
+	ldr	r10, [r11, #MX6Q_CCM_CCR]
+	orr	r10, r10, #(0x1 << 27)
+	str	r10, [r11, #MX6Q_CCM_CCR]
+
+	/* unmask all the GPC interrupts. */
+	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+	str	r6, [r11, #MX6Q_GPC_IMR1]
+	str	r7, [r11, #MX6Q_GPC_IMR2]
+	str	r8, [r11, #MX6Q_GPC_IMR3]
+	str	r9, [r11, #MX6Q_GPC_IMR4]
+
+	/*
+	 * now delay for a short while (3usec)
+	 * ARM is at 1GHz at this point
+	 * so a short loop should be enough.
+	 * this delay is required to ensure that
+	 * the RBC counter can start counting in
+	 * case an interrupt is already pending
+	 * or in case an interrupt arrives just
+	 * as ARM is about to assert DSM_request.
+	 */
+	ldr	r6, =2000
+rbc_loop:
+	subs	r6, r6, #0x1
+	bne	rbc_loop
+
+	/* Zzz, enter stop mode */
+	wfi
+	nop
+	nop
+	nop
+	nop
+
+	/*
+	 * run to here means there is pending
+	 * wakeup source, system should auto
+	 * resume, we need to restore MMDC IO first
+	 */
+	mov	r5, #0x0
+	resume_mmdc
+
+	/* return to suspend finish */
+	mov	pc, lr
+
+resume:
+	/* invalidate L1 I-cache first */
+	mov     r6, #0x0
+	mcr     p15, 0, r6, c7, c5, 0
+	mcr     p15, 0, r6, c7, c5, 6
+	/* enable the Icache and branch prediction */
+	mov     r6, #0x1800
+	mcr     p15, 0, r6, c1, c0, 0
+	isb
+
+	/* get physical resume address from pm_info. */
+	ldr	lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+	/* clear core0's entry and parameter */
+	ldr	r11, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
+	mov	r7, #0x0
+	str	r7, [r11, #MX6Q_SRC_GPR1]
+	str	r7, [r11, #MX6Q_SRC_GPR2]
+
+	ldr	r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+	mov	r5, #0x1
+	resume_mmdc
+
+	mov	pc, lr
+ENDPROC(imx6_suspend)
+
+/*
+ * The following code must assume it is running from physical address
+ * where absolute virtual addresses to the data section have to be
+ * turned into relative ones.
+ */
+
+#ifdef CONFIG_CACHE_L2X0
+	.macro	pl310_resume
+	adr	r0, l2x0_saved_regs_offset
+	ldr	r2, [r0]
+	add	r2, r2, r0
+	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
+	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
+	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
+	mov	r1, #0x1
+	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
+	.endm
+
+l2x0_saved_regs_offset:
+	.word	l2x0_saved_regs - .
+
+#else
+	.macro	pl310_resume
+	.endm
+#endif
+
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+	pl310_resume
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 1a3a5f615770..65222ea0df6d 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/clockchips.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/sched_clock.h>
 
@@ -116,11 +117,22 @@ static u64 notrace mxc_read_sched_clock(void)
 	return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
 }
 
+static struct delay_timer imx_delay_timer;
+
+static unsigned long imx_read_current_timer(void)
+{
+	return __raw_readl(sched_clock_reg);
+}
+
 static int __init mxc_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 	void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
 
+	imx_delay_timer.read_current_timer = &imx_read_current_timer;
+	imx_delay_timer.freq = c;
+	register_current_timer_delay(&imx_delay_timer);
+
 	sched_clock_reg = reg;
 
 	sched_clock_register(mxc_read_sched_clock, 32, c);
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index abeff25532ab..6e8b0e10b420 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -30,6 +30,9 @@ config ARCH_CINTEGRATOR
 config INTEGRATOR_IMPD1
 	tristate "Include support for Integrator/IM-PD1"
 	depends on ARCH_INTEGRATOR_AP
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_VIC
+	select GPIO_PL061 if GPIOLIB
 	help
 	  The IM-PD1 is an add-on logic module for the Integrator which
 	  allows ARM(R) Ltd PrimeCells to be developed and evaluated.
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 9f82f9dcbb98..d9b784824808 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/slab.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <mach/lm.h>
 #include <mach/impd1.h>
@@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
 
 struct impd1_module {
 	void __iomem	*base;
+	void __iomem	*vic_base;
 };
 
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -262,9 +264,6 @@ struct impd1_device {
 
 static struct impd1_device impd1_devs[] = {
 	{
-		.offset	= 0x03000000,
-		.id	= 0x00041190,
-	}, {
 		.offset	= 0x00100000,
 		.irq	= { 1 },
 		.id	= 0x00141011,
@@ -304,46 +303,72 @@ static struct impd1_device impd1_devs[] = {
 	}
 };
 
-static int impd1_probe(struct lm_device *dev)
+/*
+ * Valid IRQs: 0 thru 9 and 11, 10 unused.
+ */
+#define IMPD1_VALID_IRQS 0x00000bffU
+
+static int __init impd1_probe(struct lm_device *dev)
 {
 	struct impd1_module *impd1;
-	int i, ret;
+	int irq_base;
+	int i;
 
 	if (dev->id != module_id)
 		return -EINVAL;
 
-	if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers"))
+	if (!devm_request_mem_region(&dev->dev, dev->resource.start,
+				     SZ_4K, "LM registers"))
 		return -EBUSY;
 
-	impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL);
-	if (!impd1) {
-		ret = -ENOMEM;
-		goto release_lm;
-	}
+	impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module),
+			     GFP_KERNEL);
+	if (!impd1)
+		return -ENOMEM;
 
-	impd1->base = ioremap(dev->resource.start, SZ_4K);
-	if (!impd1->base) {
-		ret = -ENOMEM;
-		goto free_impd1;
-	}
+	impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K);
+	if (!impd1->base)
+		return -ENOMEM;
 
-	lm_set_drvdata(dev, impd1);
+	integrator_impd1_clk_init(impd1->base, dev->id);
 
-	printk("IM-PD1 found at 0x%08lx\n",
-		(unsigned long)dev->resource.start);
+	if (!devm_request_mem_region(&dev->dev,
+				     dev->resource.start + 0x03000000,
+				     SZ_4K, "VIC"))
+		return -EBUSY;
 
-	integrator_impd1_clk_init(impd1->base, dev->id);
+	impd1->vic_base = devm_ioremap(&dev->dev,
+				       dev->resource.start + 0x03000000,
+				       SZ_4K);
+	if (!impd1->vic_base)
+		return -ENOMEM;
+
+	irq_base = vic_init_cascaded(impd1->vic_base, dev->irq,
+				     IMPD1_VALID_IRQS, 0);
+
+	lm_set_drvdata(dev, impd1);
+
+	dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n",
+		 (unsigned long)dev->resource.start);
 
 	for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
 		struct impd1_device *idev = impd1_devs + i;
 		struct amba_device *d;
 		unsigned long pc_base;
 		char devname[32];
+		int irq1 = idev->irq[0];
+		int irq2 = idev->irq[1];
+
+		/* Translate IRQs to IM-PD1 local numberspace */
+		if (irq1)
+			irq1 += irq_base;
+		if (irq2)
+			irq2 += irq_base;
 
 		pc_base = dev->resource.start + idev->offset;
 		snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
 		d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K,
-					    dev->irq, dev->irq,
+					    irq1, irq2,
 					    idev->platform_data, idev->id,
 					    &dev->resource);
 		if (IS_ERR(d)) {
@@ -353,14 +378,6 @@ static int impd1_probe(struct lm_device *dev)
 	}
 
 	return 0;
-
- free_impd1:
-	if (impd1 && impd1->base)
-		iounmap(impd1->base);
-	kfree(impd1);
- release_lm:
-	release_mem_region(dev->resource.start, SZ_4K);
-	return ret;
 }
 
 static int impd1_remove_one(struct device *dev, void *data)
@@ -371,16 +388,10 @@ static int impd1_remove_one(struct device *dev, void *data)
 
 static void impd1_remove(struct lm_device *dev)
 {
-	struct impd1_module *impd1 = lm_get_drvdata(dev);
-
 	device_for_each_child(&dev->dev, NULL, impd1_remove_one);
 	integrator_impd1_clk_exit(dev->id);
 
 	lm_set_drvdata(dev, NULL);
-
-	iounmap(impd1->base);
-	kfree(impd1);
-	release_mem_region(dev->resource.start, SZ_4K);
 }
 
 static struct lm_driver impd1_driver = {
diff --git a/arch/arm/mach-integrator/include/mach/timex.h b/arch/arm/mach-integrator/include/mach/timex.h
deleted file mode 100644
index 1dcb42028c82..000000000000
--- a/arch/arm/mach-integrator/include/mach/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-integrator/include/mach/timex.h
- *
- *  Integrator architecture timex specifications
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute 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
- */
-
-/*
- * ??
- */
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 17c0fe627435..fedcd2fab094 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -42,6 +42,7 @@
 #include <linux/sys_soc.h>
 #include <linux/termios.h>
 #include <linux/sched_clock.h>
+#include <linux/clk-provider.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -402,10 +403,7 @@ static void __init ap_of_timer_init(void)
 	struct clk *clk;
 	unsigned long rate;
 
-	clk = clk_get_sys("ap_timer", NULL);
-	BUG_ON(IS_ERR(clk));
-	clk_prepare_enable(clk);
-	rate = clk_get_rate(clk);
+	of_clk_init(NULL);
 
 	err = of_property_read_string(of_aliases,
 				"arm,timer-primary", &path);
@@ -415,6 +413,12 @@ static void __init ap_of_timer_init(void)
 	base = of_iomap(node, 0);
 	if (WARN_ON(!base))
 		return;
+
+	clk = of_clk_get(node, 0);
+	BUG_ON(IS_ERR(clk));
+	clk_prepare_enable(clk);
+	rate = clk_get_rate(clk);
+
 	writel(0, base + TIMER_CTRL);
 	integrator_clocksource_init(rate, base);
 
@@ -427,6 +431,12 @@ static void __init ap_of_timer_init(void)
 	if (WARN_ON(!base))
 		return;
 	irq = irq_of_parse_and_map(node, 0);
+
+	clk = of_clk_get(node, 0);
+	BUG_ON(IS_ERR(clk));
+	clk_prepare_enable(clk);
+	rate = clk_get_rate(clk);
+
 	writel(0, base + TIMER_CTRL);
 	integrator_clockevent_init(rate, base, irq);
 }
@@ -440,7 +450,6 @@ static void __init ap_init_irq_of(void)
 {
 	cm_init();
 	of_irq_init(fpga_irq_of_match);
-	integrator_clk_init(false);
 }
 
 /* For the Device Tree, add in the UART callbacks as AUXDATA */
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index a3ef961e4a93..0ad5f60598c8 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -23,7 +23,6 @@
 #include <linux/irqchip/versatile-fpga.h>
 #include <linux/gfp.h>
 #include <linux/mtd/physmap.h>
-#include <linux/platform_data/clk-integrator.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
@@ -33,8 +32,6 @@
 #include <mach/platform.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
-#include <asm/hardware/arm_timer.h>
-#include <asm/hardware/icst.h>
 
 #include <mach/lm.h>
 
@@ -43,8 +40,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <asm/hardware/timer-sp.h>
-
 #include <plat/clcd.h>
 #include <plat/sched_clock.h>
 
@@ -250,7 +245,6 @@ static void __init intcp_init_irq_of(void)
 {
 	cm_init();
 	of_irq_init(fpga_irq_of_match);
-	integrator_clk_init(true);
 }
 
 /*
diff --git a/arch/arm/mach-iop13xx/include/mach/timex.h b/arch/arm/mach-iop13xx/include/mach/timex.h
deleted file mode 100644
index 45fb2745bb54..000000000000
--- a/arch/arm/mach-iop13xx/include/mach/timex.h
+++ /dev/null
@@ -1 +0,0 @@
-#define CLOCK_TICK_RATE (100 * HZ)
diff --git a/arch/arm/mach-iop32x/include/mach/timex.h b/arch/arm/mach-iop32x/include/mach/timex.h
deleted file mode 100644
index 7262ab81419d..000000000000
--- a/arch/arm/mach-iop32x/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/timex.h
- *
- * IOP32x architecture timex specifications
- */
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-iop33x/include/mach/timex.h b/arch/arm/mach-iop33x/include/mach/timex.h
deleted file mode 100644
index 54c589091d6e..000000000000
--- a/arch/arm/mach-iop33x/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/timex.h
- *
- * IOP3xx architecture timex specifications
- */
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 6d68aed6548a..dc5d7a0e5d9c 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -23,7 +23,6 @@
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/time.h>
-#include <linux/timex.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
@@ -45,6 +44,17 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#define IXP4XX_TIMER_FREQ 66666000
+
+/*
+ * The timer register doesn't allow to specify the two least significant bits of
+ * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
+ * the best value with the two least significant bits unset.
+ */
+#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
+				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
+			(IXP4XX_OST_RELOAD_MASK + 1)
+
 static void __init ixp4xx_clocksource_init(void);
 static void __init ixp4xx_clockevent_init(void);
 static struct clock_event_device clockevent_ixp4xx;
@@ -520,7 +530,7 @@ static void ixp4xx_set_mode(enum clock_event_mode mode,
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
+		osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
  		opts = IXP4XX_OST_ENABLE;
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
diff --git a/arch/arm/mach-ixp4xx/include/mach/timex.h b/arch/arm/mach-ixp4xx/include/mach/timex.h
deleted file mode 100644
index 0396d89f947c..000000000000
--- a/arch/arm/mach-ixp4xx/include/mach/timex.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/timex.h
- * 
- */
-
-#include <mach/ixp4xx-regs.h>
-
-/*
- * We use IXP425 General purpose timer for our timer needs, it runs at 
- * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the
- * timer register ignores the bottom 2 bits of the LATCH value.
- */
-#define IXP4XX_TIMER_FREQ 66666000
-#define CLOCK_TICK_RATE \
-	(((IXP4XX_TIMER_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
-
diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 90a708fef541..f50bc936cb84 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -1,13 +1,9 @@
 config ARCH_KEYSTONE
 	bool "Texas Instruments Keystone Devices"
 	depends on ARCH_MULTI_V7
-	select CPU_V7
 	select ARM_GIC
 	select HAVE_ARM_ARCH_TIMER
-	select HAVE_SMP
 	select CLKSRC_MMIO
-	select GENERIC_CLOCKEVENTS
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_ERRATA_798181 if SMP
 	select COMMON_CLK_KEYSTONE
 	select ARCH_SUPPORTS_BIG_ENDIAN
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index 6e6bb7d5ea30..aa0d2121449f 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -47,6 +47,9 @@ static void __init keystone_init(void)
 
 static const char *keystone_match[] __initconst = {
 	"ti,keystone-evm",
+	"ti,k2hk-evm",
+	"ti,k2l-evm",
+	"ti,k2e-evm",
 	NULL,
 };
 
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index fe8319ad3158..df4b26340ae4 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -106,13 +106,6 @@ config ARCH_KIRKWOOD_DT
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell Kirkwood using flattened device tree.
 
-config MACH_MV88F6281GTW_GE_DT
-	bool "Marvell 88F6281 GTW GE Board (Flattened Device Tree)"
-	depends on ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell 88F6281 GTW GE Board (Flattened Device Tree).
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 144b51102939..3a72c5c6e747 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -1,5 +1,4 @@
-obj-y				+= common.o pcie.o
-obj-$(CONFIG_KIRKWOOD_LEGACY)	+= irq.o mpp.o
+obj-$(CONFIG_KIRKWOOD_LEGACY)	+= irq.o mpp.o common.o pcie.o
 obj-$(CONFIG_PM)		+= pm.o
 
 obj-$(CONFIG_MACH_D2NET_V2)		+= d2net_v2-setup.o lacie_v2-common.o
@@ -13,4 +12,3 @@ obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
 
 obj-$(CONFIG_ARCH_KIRKWOOD_DT)		+= board-dt.o
-obj-$(CONFIG_MACH_MV88F6281GTW_GE_DT)	+= board-mv88f6281gtw_ge.o
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 78188159484d..2801da49e2a3 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -19,11 +19,84 @@
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
 #include <linux/irqchip.h>
-#include <linux/kexec.h>
+#include <asm/hardware/cache-feroceon-l2.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 #include <mach/bridge-regs.h>
 #include <plat/common.h>
-#include "common.h"
+#include <plat/pcie.h>
+#include "pm.h"
+
+static struct map_desc kirkwood_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
+		.pfn		= __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
+		.length		= KIRKWOOD_REGS_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init kirkwood_map_io(void)
+{
+	iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
+}
+
+static struct resource kirkwood_cpufreq_resources[] = {
+	[0] = {
+		.start  = CPU_CONTROL_PHYS,
+		.end    = CPU_CONTROL_PHYS + 3,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device kirkwood_cpufreq_device = {
+	.name		= "kirkwood-cpufreq",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(kirkwood_cpufreq_resources),
+	.resource	= kirkwood_cpufreq_resources,
+};
+
+static void __init kirkwood_cpufreq_init(void)
+{
+	platform_device_register(&kirkwood_cpufreq_device);
+}
+
+static struct resource kirkwood_cpuidle_resource[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+		.start	= DDR_OPERATION_BASE,
+		.end	= DDR_OPERATION_BASE + 3,
+	},
+};
+
+static struct platform_device kirkwood_cpuidle = {
+	.name		= "kirkwood_cpuidle",
+	.id		= -1,
+	.resource	= kirkwood_cpuidle_resource,
+	.num_resources	= 1,
+};
+
+static void __init kirkwood_cpuidle_init(void)
+{
+	platform_device_register(&kirkwood_cpuidle);
+}
+
+/* Temporary here since mach-mvebu has a function we can use */
+static void kirkwood_restart(enum reboot_mode mode, const char *cmd)
+{
+	/*
+	 * Enable soft reset to assert RSTOUTn.
+	 */
+	writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
+
+	/*
+	 * Assert soft reset.
+	 */
+	writel(SOFT_RESET, SYSTEM_SOFT_RESET);
+
+	while (1)
+		;
+}
 
 #define MV643XX_ETH_MAC_ADDR_LOW	0x0414
 #define MV643XX_ETH_MAC_ADDR_HIGH	0x0418
@@ -104,35 +177,35 @@ eth_fixup_skip:
 	}
 }
 
-static void __init kirkwood_dt_init(void)
+/*
+ * Disable propagation of mbus errors to the CPU local bus, as this
+ * causes mbus errors (which can occur for example for PCI aborts) to
+ * throw CPU aborts, which we're not set up to deal with.
+ */
+static void __init kirkwood_disable_mbus_error_propagation(void)
 {
-	pr_info("Kirkwood: %s.\n", kirkwood_id());
+	void __iomem *cpu_config;
 
-	/*
-	 * Disable propagation of mbus errors to the CPU local bus,
-	 * as this causes mbus errors (which can occur for example
-	 * for PCI aborts) to throw CPU aborts, which we're not set
-	 * up to deal with.
-	 */
-	writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
+	cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
+	writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
+	iounmap(cpu_config);
+}
 
-	BUG_ON(mvebu_mbus_dt_init());
+static void __init kirkwood_dt_init(void)
+{
+	kirkwood_disable_mbus_error_propagation();
 
-	kirkwood_l2_init();
+	BUG_ON(mvebu_mbus_dt_init());
 
+#ifdef CONFIG_CACHE_FEROCEON_L2
+	feroceon_of_init();
+#endif
 	kirkwood_cpufreq_init();
 	kirkwood_cpuidle_init();
 
 	kirkwood_pm_init();
 	kirkwood_dt_eth_fixup();
 
-#ifdef CONFIG_KEXEC
-	kexec_reinit = kirkwood_enable_pcie;
-#endif
-
-	if (of_machine_is_compatible("marvell,mv88f6281gtw-ge"))
-		mv88f6281gtw_ge_init();
-
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff --git a/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c b/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
deleted file mode 100644
index ee5eea678c11..000000000000
--- a/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
- *
- * Marvell 88F6281 GTW GE Board Setup
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/timer.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ethtool.h>
-#include <linux/gpio.h>
-#include <net/dsa.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data mv88f6281gtw_ge_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_NONE,
-	.speed		= SPEED_1000,
-	.duplex		= DUPLEX_FULL,
-};
-
-static struct dsa_chip_data mv88f6281gtw_ge_switch_chip_data = {
-	.port_names[0]	= "lan1",
-	.port_names[1]	= "lan2",
-	.port_names[2]	= "lan3",
-	.port_names[3]	= "lan4",
-	.port_names[4]	= "wan",
-	.port_names[5]	= "cpu",
-};
-
-static struct dsa_platform_data mv88f6281gtw_ge_switch_plat_data = {
-	.nr_chips	= 1,
-	.chip		= &mv88f6281gtw_ge_switch_chip_data,
-};
-
-void __init mv88f6281gtw_ge_init(void)
-{
-	kirkwood_ge00_init(&mv88f6281gtw_ge_ge00_data);
-	kirkwood_ge00_switch_init(&mv88f6281gtw_ge_switch_plat_data, NO_IRQ);
-}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index f3407a5db216..255f33a3903c 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -25,10 +25,10 @@
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <asm/hardware/cache-feroceon-l2.h>
 #include <mach/kirkwood.h>
 #include <mach/bridge-regs.h>
 #include <linux/platform_data/asoc-kirkwood.h>
-#include <plat/cache-feroceon-l2.h>
 #include <linux/platform_data/mmc-mvsdio.h>
 #include <linux/platform_data/mtd-orion_nand.h>
 #include <linux/platform_data/usb-ehci-orion.h>
@@ -36,6 +36,7 @@
 #include <plat/time.h>
 #include <linux/platform_data/dma-mv_xor.h>
 #include "common.h"
+#include "pm.h"
 
 /* These can go away once Kirkwood uses the mvebu-mbus DT binding */
 #define KIRKWOOD_MBUS_NAND_TARGET 0x01
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index 05fd648df543..832a4e2ab8d7 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -58,19 +58,6 @@ void kirkwood_cpufreq_init(void);
 void kirkwood_restart(enum reboot_mode, const char *);
 void kirkwood_clk_init(void);
 
-#ifdef CONFIG_PM
-void kirkwood_pm_init(void);
-#else
-static inline void kirkwood_pm_init(void) {};
-#endif
-
-/* board init functions for boards not fully converted to fdt */
-#ifdef CONFIG_MACH_MV88F6281GTW_GE_DT
-void mv88f6281gtw_ge_init(void);
-#else
-static inline void mv88f6281gtw_ge_init(void) {};
-#endif
-
 /* early init functions not converted to fdt yet */
 char *kirkwood_id(void);
 void kirkwood_l2_init(void);
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index 8b9d1c9ff199..1c37082c8b39 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -14,6 +14,7 @@
 #include <mach/kirkwood.h>
 
 #define CPU_CONFIG		(BRIDGE_VIRT_BASE + 0x0100)
+#define CPU_CONFIG_PHYS		(BRIDGE_PHYS_BASE + 0x0100)
 #define CPU_CONFIG_ERROR_PROP	0x00000004
 
 #define CPU_CONTROL		(BRIDGE_VIRT_BASE + 0x0104)
@@ -21,6 +22,7 @@
 #define CPU_RESET		0x00000002
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
@@ -79,5 +81,6 @@
 #define CGC_RESERVED		(0x6 << 21)
 
 #define MEMORY_PM_CTRL		(BRIDGE_VIRT_BASE + 0x118)
+#define MEMORY_PM_CTRL_PHYS	(BRIDGE_PHYS_BASE + 0x118)
 
 #endif
diff --git a/arch/arm/mach-kirkwood/include/mach/timex.h b/arch/arm/mach-kirkwood/include/mach/timex.h
deleted file mode 100644
index c923cd169b9c..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/timex.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/timex.h
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
-
diff --git a/arch/arm/mach-kirkwood/pm.c b/arch/arm/mach-kirkwood/pm.c
index c6ab8d9303a5..8e5e0329d04c 100644
--- a/arch/arm/mach-kirkwood/pm.c
+++ b/arch/arm/mach-kirkwood/pm.c
@@ -21,15 +21,16 @@
 #include "common.h"
 
 static void __iomem *ddr_operation_base;
+static void __iomem *memory_pm_ctrl;
 
 static void kirkwood_low_power(void)
 {
 	u32 mem_pm_ctrl;
 
-	mem_pm_ctrl = readl(MEMORY_PM_CTRL);
+	mem_pm_ctrl = readl(memory_pm_ctrl);
 
 	/* Set peripherals to low-power mode */
-	writel_relaxed(~0, MEMORY_PM_CTRL);
+	writel_relaxed(~0, memory_pm_ctrl);
 
 	/* Set DDR in self-refresh */
 	writel_relaxed(0x7, ddr_operation_base);
@@ -41,7 +42,7 @@ static void kirkwood_low_power(void)
 	 */
 	cpu_do_idle();
 
-	writel_relaxed(mem_pm_ctrl, MEMORY_PM_CTRL);
+	writel_relaxed(mem_pm_ctrl, memory_pm_ctrl);
 }
 
 static int kirkwood_suspend_enter(suspend_state_t state)
@@ -69,5 +70,7 @@ static const struct platform_suspend_ops kirkwood_suspend_ops = {
 void __init kirkwood_pm_init(void)
 {
 	ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
+	memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4);
+
 	suspend_set_ops(&kirkwood_suspend_ops);
 }
diff --git a/arch/arm/mach-kirkwood/pm.h b/arch/arm/mach-kirkwood/pm.h
new file mode 100644
index 000000000000..21e7530f368b
--- /dev/null
+++ b/arch/arm/mach-kirkwood/pm.h
@@ -0,0 +1,26 @@
+/*
+ * Power Management driver for Marvell Kirkwood SoCs
+ *
+ * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 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.
+ */
+
+#ifndef __ARCH_KIRKWOOD_PM_H
+#define __ARCH_KIRKWOOD_PM_H
+
+#ifdef CONFIG_PM
+void kirkwood_pm_init(void);
+#else
+static inline void kirkwood_pm_init(void) {};
+#endif
+
+#endif
diff --git a/arch/arm/mach-ks8695/include/mach/timex.h b/arch/arm/mach-ks8695/include/mach/timex.h
deleted file mode 100644
index 10f716371bd3..000000000000
--- a/arch/arm/mach-ks8695/include/mach/timex.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/timex.h
- *
- * Copyright (C) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * KS8695 - Time Parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#include <mach/hardware.h>
-
-#define CLOCK_TICK_RATE 	KS8695_CLOCK_RATE
-
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/timex.h b/arch/arm/mach-lpc32xx/include/mach/timex.h
deleted file mode 100644
index 8d4066b16b3f..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/timex.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/timex.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute 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.
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/*
- * Rate in Hz of the main system oscillator. This value should match
- * the value 'MAIN_OSC_FREQ' in platform.h
- */
-#define CLOCK_TICK_RATE	13000000
-
-#endif
diff --git a/arch/arm/mach-mmp/include/mach/timex.h b/arch/arm/mach-mmp/include/mach/timex.h
deleted file mode 100644
index 70c9f1d88c02..000000000000
--- a/arch/arm/mach-mmp/include/mach/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/timex.h
- *
- * 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.
- */
-
-#ifdef CONFIG_CPU_MMP2
-#define CLOCK_TICK_RATE		6500000
-#else
-#define CLOCK_TICK_RATE		3250000
-#endif
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index 024022d91fe3..048997e75dd0 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -39,6 +39,12 @@
 
 #include "clock.h"
 
+#ifdef CONFIG_CPU_MMP2
+#define MMP_CLOCK_FREQ		6500000
+#else
+#define MMP_CLOCK_FREQ		3250000
+#endif
+
 #define TIMERS_VIRT_BASE	TIMERS1_VIRT_BASE
 
 #define MAX_DELTA		(0xfffffffe)
@@ -195,14 +201,14 @@ void __init timer_init(int irq)
 {
 	timer_config();
 
-	sched_clock_register(mmp_read_sched_clock, 32, CLOCK_TICK_RATE);
+	sched_clock_register(mmp_read_sched_clock, 32, MMP_CLOCK_FREQ);
 
 	ckevt.cpumask = cpumask_of(0);
 
 	setup_irq(irq, &timer_irq);
 
-	clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
-	clockevents_config_and_register(&ckevt, CLOCK_TICK_RATE,
+	clocksource_register_hz(&cksrc, MMP_CLOCK_FREQ);
+	clockevents_config_and_register(&ckevt, MMP_CLOCK_FREQ,
 					MIN_DELTA, MAX_DELTA);
 }
 
diff --git a/arch/arm/mach-moxart/Kconfig b/arch/arm/mach-moxart/Kconfig
index 3795ae28a613..95a6a4b43c37 100644
--- a/arch/arm/mach-moxart/Kconfig
+++ b/arch/arm/mach-moxart/Kconfig
@@ -2,14 +2,9 @@ config ARCH_MOXART
 	bool "MOXA ART SoC" if ARCH_MULTI_V4T
 	select CPU_FA526
 	select ARM_DMA_MEM_BUFFERABLE
-	select USE_OF
-	select CLKSRC_OF
 	select CLKSRC_MMIO
-	select HAVE_CLK
-	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_CLOCKEVENTS
 	select PHYLIB if NETDEVICES
 	help
 	  Say Y here if you want to run your kernel on hardware with a
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 9625cf378931..a7f959e58c3d 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1,50 +1,9 @@
-config ARCH_MSM
-	bool
-
-config ARCH_MSM_DT
-	bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7
-	select ARCH_MSM
-	select ARCH_REQUIRE_GPIOLIB
-	select CLKSRC_OF
-	select GENERIC_CLOCKEVENTS
-	help
-	  Support for Qualcomm's devicetree based MSM systems.
-
 if ARCH_MSM
 
-menu "Qualcomm MSM SoC Selection"
-	depends on ARCH_MSM_DT
-
-config ARCH_MSM8X60
-	bool "Enable support for MSM8X60"
-	select ARM_GIC
-	select CPU_V7
-	select HAVE_SMP
-	select MSM_SCM if SMP
-	select MSM_TIMER
-
-config ARCH_MSM8960
-	bool "Enable support for MSM8960"
-	select ARM_GIC
-	select CPU_V7
-	select HAVE_SMP
-	select MSM_SCM if SMP
-	select MSM_TIMER
-
-config ARCH_MSM8974
-	bool "Enable support for MSM8974"
-	select ARM_GIC
-	select CPU_V7
-	select HAVE_ARM_ARCH_TIMER
-	select HAVE_SMP
-	select MSM_SCM if SMP
-
-endmenu
-
 choice
 	prompt "Qualcomm MSM SoC Type"
 	default ARCH_MSM7X00A
-	depends on ARCH_MSM_NODT
+	depends on ARCH_MSM
 
 config ARCH_MSM7X00A
 	bool "MSM7x00A / MSM7x01A"
@@ -54,7 +13,7 @@ config ARCH_MSM7X00A
 	select MACH_TROUT if !MACH_HALIBUT
 	select MSM_PROC_COMM
 	select MSM_SMD
-	select MSM_TIMER
+	select CLKSRC_QCOM
 	select MSM_SMD_PKG3
 
 config ARCH_MSM7X30
@@ -66,7 +25,7 @@ config ARCH_MSM7X30
 	select MSM_GPIOMUX
 	select MSM_PROC_COMM
 	select MSM_SMD
-	select MSM_TIMER
+	select CLKSRC_QCOM
 	select MSM_VIC
 
 config ARCH_QSD8X50
@@ -78,7 +37,7 @@ config ARCH_QSD8X50
 	select MSM_GPIOMUX
 	select MSM_PROC_COMM
 	select MSM_SMD
-	select MSM_TIMER
+	select CLKSRC_QCOM
 	select MSM_VIC
 
 endchoice
@@ -99,7 +58,7 @@ config  MSM_VIC
 	bool
 
 menu "Qualcomm MSM Board Type"
-	depends on ARCH_MSM_NODT
+	depends on ARCH_MSM
 
 config MACH_HALIBUT
 	depends on ARCH_MSM
@@ -153,7 +112,4 @@ config MSM_GPIOMUX
 config MSM_SCM
 	bool
 
-config MSM_TIMER
-	bool
-
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8e307a10d3c3..27c078a568df 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_MSM_TIMER) += timer.o
 obj-$(CONFIG_MSM_PROC_COMM) += clock.o
 
 obj-$(CONFIG_MSM_VIC) += irq-vic.o
@@ -14,18 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
 
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
-obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
-
-CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
-
-obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
 obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
 obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
-obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o
 obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
deleted file mode 100644
index 1f11d93e700e..000000000000
--- a/arch/arm/mach-msm/board-dt.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (c) 2010-2012,2013 The Linux Foundation. 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 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/init.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-static const char * const msm_dt_match[] __initconst = {
-	"qcom,msm8660-fluid",
-	"qcom,msm8660-surf",
-	"qcom,msm8960-cdp",
-	NULL
-};
-
-static const char * const apq8074_dt_match[] __initconst = {
-	"qcom,apq8074-dragonboard",
-	NULL
-};
-
-DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
-	.smp = smp_ops(msm_smp_ops),
-	.dt_compat = msm_dt_match,
-MACHINE_END
-
-DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)")
-	.dt_compat = apq8074_dt_match,
-MACHINE_END
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
index 33c7725adae2..572479a3c7be 100644
--- a/arch/arm/mach-msm/common.h
+++ b/arch/arm/mach-msm/common.h
@@ -23,9 +23,6 @@ extern void msm_map_qsd8x50_io(void);
 extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
 					  unsigned int mtype, void *caller);
 
-extern struct smp_operations msm_smp_ops;
-extern void msm_cpu_die(unsigned int cpu);
-
 struct msm_mmc_platform_data;
 
 extern void msm_add_devices(void);
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
deleted file mode 100644
index 6c62c3f82fe6..000000000000
--- a/arch/arm/mach-msm/headsmp.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  linux/arch/arm/mach-realview/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  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/linkage.h>
-#include <linux/init.h>
-
-/*
- * MSM specific entry point for secondary CPUs.  This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(msm_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-ENDPROC(msm_secondary_startup)
-
-	.align
-1:	.long	.
-	.long	pen_release
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
deleted file mode 100644
index 326a87261f9a..000000000000
--- a/arch/arm/mach-msm/hotplug.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *  Copyright (C) 2002 ARM Ltd.
- *  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/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-
-#include <asm/smp_plat.h>
-
-#include "common.h"
-
-static inline void cpu_enter_lowpower(void)
-{
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-}
-
-static inline void platform_do_lowpower(unsigned int cpu)
-{
-	/* Just enter wfi for now. TODO: Properly shut off the cpu. */
-	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm("wfi"
-		    :
-		    :
-		    : "memory", "cc");
-
-		if (pen_release == cpu_logical_map(cpu)) {
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		}
-
-		/*
-		 * getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * The trouble is, letting people know about this is not really
-		 * possible, since we are currently running incoherently, and
-		 * therefore cannot safely call printk() or anything else
-		 */
-		pr_debug("CPU%u: spurious wakeup call\n", cpu);
-	}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void __ref msm_cpu_die(unsigned int cpu)
-{
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu);
-
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
-}
diff --git a/arch/arm/mach-msm/include/mach/timex.h b/arch/arm/mach-msm/include/mach/timex.h
deleted file mode 100644
index a62e6b215aec..000000000000
--- a/arch/arm/mach-msm/include/mach/timex.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-msm/include/mach/timex.h
- *
- * Copyright (C) 2007 Google, 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.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_TIMEX_H
-#define __ASM_ARCH_MSM_TIMEX_H
-
-#define CLOCK_TICK_RATE		1000000
-
-#endif
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
deleted file mode 100644
index f10a1f58fde9..000000000000
--- a/arch/arm/mach-msm/platsmp.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *  Copyright (c) 2010, Code Aurora Forum. 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/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/mach-types.h>
-#include <asm/smp_plat.h>
-
-#include "scm-boot.h"
-#include "common.h"
-
-#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
-#define SCSS_CPU1CORE_RESET 0xD80
-#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
-
-extern void msm_secondary_startup(void);
-
-static DEFINE_SPINLOCK(boot_lock);
-
-static inline int get_core_count(void)
-{
-	/* 1 + the PART[1:0] field of MIDR */
-	return ((read_cpuid_id() >> 4) & 3) + 1;
-}
-
-static void msm_secondary_init(unsigned int cpu)
-{
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	pen_release = -1;
-	smp_wmb();
-
-	/*
-	 * Synchronise with the boot thread.
-	 */
-	spin_lock(&boot_lock);
-	spin_unlock(&boot_lock);
-}
-
-static void prepare_cold_cpu(unsigned int cpu)
-{
-	int ret;
-	ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
-				SCM_FLAG_COLDBOOT_CPU1);
-	if (ret == 0) {
-		void __iomem *sc1_base_ptr;
-		sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
-		if (sc1_base_ptr) {
-			writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
-			writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
-			writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
-			iounmap(sc1_base_ptr);
-		}
-	} else
-		printk(KERN_DEBUG "Failed to set secondary core boot "
-				  "address\n");
-}
-
-static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	unsigned long timeout;
-	static int cold_boot_done;
-
-	/* Only need to bring cpu out of reset this way once */
-	if (cold_boot_done == false) {
-		prepare_cold_cpu(cpu);
-		cold_boot_done = true;
-	}
-
-	/*
-	 * set synchronisation state between this boot processor
-	 * and the secondary one
-	 */
-	spin_lock(&boot_lock);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	pen_release = cpu_logical_map(cpu);
-	sync_cache_w(&pen_release);
-
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system. The msm8x60
- * does not support the ARM SCU, so just set the possible cpu mask to
- * NR_CPUS.
- */
-static void __init msm_smp_init_cpus(void)
-{
-	unsigned int i, ncores = get_core_count();
-
-	if (ncores > nr_cpu_ids) {
-		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-			ncores, nr_cpu_ids);
-		ncores = nr_cpu_ids;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
-{
-}
-
-struct smp_operations msm_smp_ops __initdata = {
-	.smp_init_cpus		= msm_smp_init_cpus,
-	.smp_prepare_cpus	= msm_smp_prepare_cpus,
-	.smp_secondary_init	= msm_secondary_init,
-	.smp_boot_secondary	= msm_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-	.cpu_die		= msm_cpu_die,
-#endif
-};
diff --git a/arch/arm/mach-msm/scm-boot.c b/arch/arm/mach-msm/scm-boot.c
deleted file mode 100644
index 45cee3e469a5..000000000000
--- a/arch/arm/mach-msm/scm-boot.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 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.
- *
- * 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/module.h>
-#include <linux/slab.h>
-
-#include "scm.h"
-#include "scm-boot.h"
-
-/*
- * Set the cold/warm boot address for one of the CPU cores.
- */
-int scm_set_boot_addr(phys_addr_t addr, int flags)
-{
-	struct {
-		unsigned int flags;
-		phys_addr_t  addr;
-	} cmd;
-
-	cmd.addr = addr;
-	cmd.flags = flags;
-	return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
-			&cmd, sizeof(cmd), NULL, 0);
-}
-EXPORT_SYMBOL(scm_set_boot_addr);
diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h
deleted file mode 100644
index 7be32ff5d687..000000000000
--- a/arch/arm/mach-msm/scm-boot.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 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.
- */
-#ifndef __MACH_SCM_BOOT_H
-#define __MACH_SCM_BOOT_H
-
-#define SCM_BOOT_ADDR			0x1
-#define SCM_FLAG_COLDBOOT_CPU1		0x1
-#define SCM_FLAG_WARMBOOT_CPU1		0x2
-#define SCM_FLAG_WARMBOOT_CPU0		0x4
-
-int scm_set_boot_addr(phys_addr_t addr, int flags);
-
-#endif
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
deleted file mode 100644
index c536fd6bf827..000000000000
--- a/arch/arm/mach-msm/scm.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 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.
- *
- * 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/slab.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-
-#include <asm/cacheflush.h>
-
-#include "scm.h"
-
-/* Cache line size for msm8x60 */
-#define CACHELINESIZE 32
-
-#define SCM_ENOMEM		-5
-#define SCM_EOPNOTSUPP		-4
-#define SCM_EINVAL_ADDR		-3
-#define SCM_EINVAL_ARG		-2
-#define SCM_ERROR		-1
-#define SCM_INTERRUPTED		1
-
-static DEFINE_MUTEX(scm_lock);
-
-/**
- * struct scm_command - one SCM command buffer
- * @len: total available memory for command and response
- * @buf_offset: start of command buffer
- * @resp_hdr_offset: start of response buffer
- * @id: command to be executed
- * @buf: buffer returned from scm_get_command_buffer()
- *
- * An SCM command is laid out in memory as follows:
- *
- *	------------------- <--- struct scm_command
- *	| command header  |
- *	------------------- <--- scm_get_command_buffer()
- *	| command buffer  |
- *	------------------- <--- struct scm_response and
- *	| response header |      scm_command_to_response()
- *	------------------- <--- scm_get_response_buffer()
- *	| response buffer |
- *	-------------------
- *
- * There can be arbitrary padding between the headers and buffers so
- * you should always use the appropriate scm_get_*_buffer() routines
- * to access the buffers in a safe manner.
- */
-struct scm_command {
-	u32	len;
-	u32	buf_offset;
-	u32	resp_hdr_offset;
-	u32	id;
-	u32	buf[0];
-};
-
-/**
- * struct scm_response - one SCM response buffer
- * @len: total available memory for response
- * @buf_offset: start of response data relative to start of scm_response
- * @is_complete: indicates if the command has finished processing
- */
-struct scm_response {
-	u32	len;
-	u32	buf_offset;
-	u32	is_complete;
-};
-
-/**
- * alloc_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &scm_command on success or %NULL if the allocation fails.
- */
-static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
-{
-	struct scm_command *cmd;
-	size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
-		resp_size;
-
-	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
-	if (cmd) {
-		cmd->len = len;
-		cmd->buf_offset = offsetof(struct scm_command, buf);
-		cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
-	}
-	return cmd;
-}
-
-/**
- * free_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_scm_command(struct scm_command *cmd)
-{
-	kfree(cmd);
-}
-
-/**
- * scm_command_to_response() - Get a pointer to a scm_response
- * @cmd: command
- *
- * Returns a pointer to a response for a command.
- */
-static inline struct scm_response *scm_command_to_response(
-		const struct scm_command *cmd)
-{
-	return (void *)cmd + cmd->resp_hdr_offset;
-}
-
-/**
- * scm_get_command_buffer() - Get a pointer to a command buffer
- * @cmd: command
- *
- * Returns a pointer to the command buffer of a command.
- */
-static inline void *scm_get_command_buffer(const struct scm_command *cmd)
-{
-	return (void *)cmd->buf;
-}
-
-/**
- * scm_get_response_buffer() - Get a pointer to a response buffer
- * @rsp: response
- *
- * Returns a pointer to a response buffer of a response.
- */
-static inline void *scm_get_response_buffer(const struct scm_response *rsp)
-{
-	return (void *)rsp + rsp->buf_offset;
-}
-
-static int scm_remap_error(int err)
-{
-	switch (err) {
-	case SCM_ERROR:
-		return -EIO;
-	case SCM_EINVAL_ADDR:
-	case SCM_EINVAL_ARG:
-		return -EINVAL;
-	case SCM_EOPNOTSUPP:
-		return -EOPNOTSUPP;
-	case SCM_ENOMEM:
-		return -ENOMEM;
-	}
-	return -EINVAL;
-}
-
-static u32 smc(u32 cmd_addr)
-{
-	int context_id;
-	register u32 r0 asm("r0") = 1;
-	register u32 r1 asm("r1") = (u32)&context_id;
-	register u32 r2 asm("r2") = cmd_addr;
-	do {
-		asm volatile(
-			__asmeq("%0", "r0")
-			__asmeq("%1", "r0")
-			__asmeq("%2", "r1")
-			__asmeq("%3", "r2")
-#ifdef REQUIRES_SEC
-			".arch_extension sec\n"
-#endif
-			"smc	#0	@ switch to secure world\n"
-			: "=r" (r0)
-			: "r" (r0), "r" (r1), "r" (r2)
-			: "r3");
-	} while (r0 == SCM_INTERRUPTED);
-
-	return r0;
-}
-
-static int __scm_call(const struct scm_command *cmd)
-{
-	int ret;
-	u32 cmd_addr = virt_to_phys(cmd);
-
-	/*
-	 * Flush the entire cache here so callers don't have to remember
-	 * to flush the cache when passing physical addresses to the secure
-	 * side in the buffer.
-	 */
-	flush_cache_all();
-	ret = smc(cmd_addr);
-	if (ret < 0)
-		ret = scm_remap_error(ret);
-
-	return ret;
-}
-
-/**
- * scm_call() - Send an SCM command
- * @svc_id: service identifier
- * @cmd_id: command identifier
- * @cmd_buf: command buffer
- * @cmd_len: length of the command buffer
- * @resp_buf: response buffer
- * @resp_len: length of the response buffer
- *
- * Sends a command to the SCM and waits for the command to finish processing.
- */
-int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
-		void *resp_buf, size_t resp_len)
-{
-	int ret;
-	struct scm_command *cmd;
-	struct scm_response *rsp;
-
-	cmd = alloc_scm_command(cmd_len, resp_len);
-	if (!cmd)
-		return -ENOMEM;
-
-	cmd->id = (svc_id << 10) | cmd_id;
-	if (cmd_buf)
-		memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
-
-	mutex_lock(&scm_lock);
-	ret = __scm_call(cmd);
-	mutex_unlock(&scm_lock);
-	if (ret)
-		goto out;
-
-	rsp = scm_command_to_response(cmd);
-	do {
-		u32 start = (u32)rsp;
-		u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
-		start &= ~(CACHELINESIZE - 1);
-		while (start < end) {
-			asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-			     : "memory");
-			start += CACHELINESIZE;
-		}
-	} while (!rsp->is_complete);
-
-	if (resp_buf)
-		memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
-out:
-	free_scm_command(cmd);
-	return ret;
-}
-EXPORT_SYMBOL(scm_call);
-
-u32 scm_get_version(void)
-{
-	int context_id;
-	static u32 version = -1;
-	register u32 r0 asm("r0");
-	register u32 r1 asm("r1");
-
-	if (version != -1)
-		return version;
-
-	mutex_lock(&scm_lock);
-
-	r0 = 0x1 << 8;
-	r1 = (u32)&context_id;
-	do {
-		asm volatile(
-			__asmeq("%0", "r0")
-			__asmeq("%1", "r1")
-			__asmeq("%2", "r0")
-			__asmeq("%3", "r1")
-#ifdef REQUIRES_SEC
-			".arch_extension sec\n"
-#endif
-			"smc	#0	@ switch to secure world\n"
-			: "=r" (r0), "=r" (r1)
-			: "r" (r0), "r" (r1)
-			: "r2", "r3");
-	} while (r0 == SCM_INTERRUPTED);
-
-	version = r1;
-	mutex_unlock(&scm_lock);
-
-	return version;
-}
-EXPORT_SYMBOL(scm_get_version);
diff --git a/arch/arm/mach-msm/scm.h b/arch/arm/mach-msm/scm.h
deleted file mode 100644
index 00b31ea58f29..000000000000
--- a/arch/arm/mach-msm/scm.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 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.
- */
-#ifndef __MACH_SCM_H
-#define __MACH_SCM_H
-
-#define SCM_SVC_BOOT			0x1
-#define SCM_SVC_PIL			0x2
-
-extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
-		void *resp_buf, size_t resp_len);
-
-#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
-
-extern u32 scm_get_version(void);
-
-#endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
deleted file mode 100644
index fd1644987534..000000000000
--- a/arch/arm/mach-msm/timer.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
- *
- * 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/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/cpu.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/sched_clock.h>
-
-#include <asm/mach/time.h>
-
-#include "common.h"
-
-#define TIMER_MATCH_VAL			0x0000
-#define TIMER_COUNT_VAL			0x0004
-#define TIMER_ENABLE			0x0008
-#define TIMER_ENABLE_CLR_ON_MATCH_EN	BIT(1)
-#define TIMER_ENABLE_EN			BIT(0)
-#define TIMER_CLEAR			0x000C
-#define DGT_CLK_CTL			0x10
-#define DGT_CLK_CTL_DIV_4		0x3
-#define TIMER_STS_GPT0_CLR_PEND		BIT(10)
-
-#define GPT_HZ 32768
-
-#define MSM_DGT_SHIFT 5
-
-static void __iomem *event_base;
-static void __iomem *sts_base;
-
-static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-	/* Stop the timer tick */
-	if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
-		u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
-		ctrl &= ~TIMER_ENABLE_EN;
-		writel_relaxed(ctrl, event_base + TIMER_ENABLE);
-	}
-	evt->event_handler(evt);
-	return IRQ_HANDLED;
-}
-
-static int msm_timer_set_next_event(unsigned long cycles,
-				    struct clock_event_device *evt)
-{
-	u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
-
-	ctrl &= ~TIMER_ENABLE_EN;
-	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
-
-	writel_relaxed(ctrl, event_base + TIMER_CLEAR);
-	writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
-
-	if (sts_base)
-		while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
-			cpu_relax();
-
-	writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
-	return 0;
-}
-
-static void msm_timer_set_mode(enum clock_event_mode mode,
-			      struct clock_event_device *evt)
-{
-	u32 ctrl;
-
-	ctrl = readl_relaxed(event_base + TIMER_ENABLE);
-	ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_RESUME:
-	case CLOCK_EVT_MODE_PERIODIC:
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* Timer is enabled in set_next_event */
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		break;
-	}
-	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
-}
-
-static struct clock_event_device __percpu *msm_evt;
-
-static void __iomem *source_base;
-
-static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
-{
-	return readl_relaxed(source_base + TIMER_COUNT_VAL);
-}
-
-static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
-{
-	/*
-	 * Shift timer count down by a constant due to unreliable lower bits
-	 * on some targets.
-	 */
-	return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
-}
-
-static struct clocksource msm_clocksource = {
-	.name	= "dg_timer",
-	.rating	= 300,
-	.read	= msm_read_timer_count,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int msm_timer_irq;
-static int msm_timer_has_ppi;
-
-static int msm_local_timer_setup(struct clock_event_device *evt)
-{
-	int cpu = smp_processor_id();
-	int err;
-
-	evt->irq = msm_timer_irq;
-	evt->name = "msm_timer";
-	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	evt->rating = 200;
-	evt->set_mode = msm_timer_set_mode;
-	evt->set_next_event = msm_timer_set_next_event;
-	evt->cpumask = cpumask_of(cpu);
-
-	clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
-
-	if (msm_timer_has_ppi) {
-		enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
-	} else {
-		err = request_irq(evt->irq, msm_timer_interrupt,
-				IRQF_TIMER | IRQF_NOBALANCING |
-				IRQF_TRIGGER_RISING, "gp_timer", evt);
-		if (err)
-			pr_err("request_irq failed\n");
-	}
-
-	return 0;
-}
-
-static void msm_local_timer_stop(struct clock_event_device *evt)
-{
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
-	disable_percpu_irq(evt->irq);
-}
-
-static int msm_timer_cpu_notify(struct notifier_block *self,
-					   unsigned long action, void *hcpu)
-{
-	/*
-	 * Grab cpu pointer in each case to avoid spurious
-	 * preemptible warnings
-	 */
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_STARTING:
-		msm_local_timer_setup(this_cpu_ptr(msm_evt));
-		break;
-	case CPU_DYING:
-		msm_local_timer_stop(this_cpu_ptr(msm_evt));
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block msm_timer_cpu_nb = {
-	.notifier_call = msm_timer_cpu_notify,
-};
-
-static u64 notrace msm_sched_clock_read(void)
-{
-	return msm_clocksource.read(&msm_clocksource);
-}
-
-static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
-				  bool percpu)
-{
-	struct clocksource *cs = &msm_clocksource;
-	int res = 0;
-
-	msm_timer_irq = irq;
-	msm_timer_has_ppi = percpu;
-
-	msm_evt = alloc_percpu(struct clock_event_device);
-	if (!msm_evt) {
-		pr_err("memory allocation failed for clockevents\n");
-		goto err;
-	}
-
-	if (percpu)
-		res = request_percpu_irq(irq, msm_timer_interrupt,
-					 "gp_timer", msm_evt);
-
-	if (res) {
-		pr_err("request_percpu_irq failed\n");
-	} else {
-		res = register_cpu_notifier(&msm_timer_cpu_nb);
-		if (res) {
-			free_percpu_irq(irq, msm_evt);
-			goto err;
-		}
-
-		/* Immediately configure the timer on the boot CPU */
-		msm_local_timer_setup(__this_cpu_ptr(msm_evt));
-	}
-
-err:
-	writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
-	res = clocksource_register_hz(cs, dgt_hz);
-	if (res)
-		pr_err("clocksource_register failed\n");
-	sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
-}
-
-#ifdef CONFIG_OF
-static void __init msm_dt_timer_init(struct device_node *np)
-{
-	u32 freq;
-	int irq;
-	struct resource res;
-	u32 percpu_offset;
-	void __iomem *base;
-	void __iomem *cpu0_base;
-
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("Failed to map event base\n");
-		return;
-	}
-
-	/* We use GPT0 for the clockevent */
-	irq = irq_of_parse_and_map(np, 1);
-	if (irq <= 0) {
-		pr_err("Can't get irq\n");
-		return;
-	}
-
-	/* We use CPU0's DGT for the clocksource */
-	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
-		percpu_offset = 0;
-
-	if (of_address_to_resource(np, 0, &res)) {
-		pr_err("Failed to parse DGT resource\n");
-		return;
-	}
-
-	cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
-	if (!cpu0_base) {
-		pr_err("Failed to map source base\n");
-		return;
-	}
-
-	if (of_property_read_u32(np, "clock-frequency", &freq)) {
-		pr_err("Unknown frequency\n");
-		return;
-	}
-
-	event_base = base + 0x4;
-	sts_base = base + 0x88;
-	source_base = cpu0_base + 0x24;
-	freq /= 4;
-	writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
-
-	msm_timer_init(freq, 32, irq, !!percpu_offset);
-}
-CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
-CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
-#endif
-
-static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
-				u32 sts)
-{
-	void __iomem *base;
-
-	base = ioremap(addr, SZ_256);
-	if (!base) {
-		pr_err("Failed to map timer base\n");
-		return -ENOMEM;
-	}
-	event_base = base + event;
-	source_base = base + source;
-	if (sts)
-		sts_base = base + sts;
-
-	return 0;
-}
-
-void __init msm7x01_timer_init(void)
-{
-	struct clocksource *cs = &msm_clocksource;
-
-	if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
-		return;
-	cs->read = msm_read_timer_count_shift;
-	cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
-	/* 600 KHz */
-	msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
-			false);
-}
-
-void __init msm7x30_timer_init(void)
-{
-	if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
-		return;
-	msm_timer_init(24576000 / 4, 32, 1, false);
-}
-
-void __init qsd8x50_timer_init(void)
-{
-	if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
-		return;
-	msm_timer_init(19200000 / 4, 32, 7, false);
-}
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 75062eff2494..e6ac679bece9 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -15,11 +15,11 @@
 #include <linux/ata_platform.h>
 #include <linux/clk-provider.h>
 #include <linux/ethtool.h>
+#include <asm/hardware/cache-feroceon-l2.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <mach/mv78xx0.h>
 #include <mach/bridge-regs.h>
-#include <plat/cache-feroceon-l2.h>
 #include <linux/platform_data/usb-ehci-orion.h>
 #include <linux/platform_data/mtd-orion_nand.h>
 #include <plat/time.h>
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index 5f03484584d4..e20d6da234a6 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -15,6 +15,7 @@
 #define L2_WRITETHROUGH		0x00020000
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-mv78xx0/include/mach/timex.h b/arch/arm/mach-mv78xx0/include/mach/timex.h
deleted file mode 100644
index 0e8c443c723a..000000000000
--- a/arch/arm/mach-mv78xx0/include/mach/timex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/timex.h
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 5e269d7263ce..44d5771f5778 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,51 +1,99 @@
 config ARCH_MVEBU
-	bool "Marvell SOCs with Device Tree support" if ARCH_MULTI_V7
+	bool "Marvell Engineering Business Unit (MVEBU) SoCs" if (ARCH_MULTI_V7 || ARCH_MULTI_V5)
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
-	select MULTI_IRQ_HANDLER
 	select PINCTRL
 	select PLAT_ORION
-	select SPARSE_IRQ
-	select CLKDEV_LOOKUP
 	select MVEBU_MBUS
 	select ZONE_DMA if ARM_LPAE
 	select ARCH_REQUIRE_GPIOLIB
 	select MIGHT_HAVE_PCI
 	select PCI_QUIRKS if PCI
+	select OF_ADDRESS_PCI
 
 if ARCH_MVEBU
 
-menu "Marvell SOC with device tree"
+menu "Marvell EBU SoC variants"
 
-config MACH_ARMADA_370_XP
+config MACH_MVEBU_V7
 	bool
 	select ARMADA_370_XP_TIMER
-	select HAVE_SMP
 	select CACHE_L2X0
-	select CPU_PJ4B
 
 config MACH_ARMADA_370
-	bool "Marvell Armada 370 boards"
+	bool "Marvell Armada 370 boards" if ARCH_MULTI_V7
 	select ARMADA_370_CLK
-	select MACH_ARMADA_370_XP
+	select CPU_PJ4B
+	select MACH_MVEBU_V7
 	select PINCTRL_ARMADA_370
 	help
 	  Say 'Y' here if you want your kernel to support boards based
 	  on the Marvell Armada 370 SoC with device tree.
 
+config MACH_ARMADA_375
+	bool "Marvell Armada 375 boards" if ARCH_MULTI_V7
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_753970
+	select ARM_GIC
+	select ARMADA_375_CLK
+	select CPU_V7
+	select MACH_MVEBU_V7
+	select NEON
+	select PINCTRL_ARMADA_375
+	help
+	  Say 'Y' here if you want your kernel to support boards based
+	  on the Marvell Armada 375 SoC with device tree.
+
+config MACH_ARMADA_38X
+	bool "Marvell Armada 380/385 boards" if ARCH_MULTI_V7
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_753970
+	select ARM_GIC
+	select ARMADA_38X_CLK
+	select CPU_V7
+	select MACH_MVEBU_V7
+	select NEON
+	select PINCTRL_ARMADA_38X
+	help
+	  Say 'Y' here if you want your kernel to support boards based
+	  on the Marvell Armada 380/385 SoC with device tree.
+
 config MACH_ARMADA_XP
-	bool "Marvell Armada XP boards"
+	bool "Marvell Armada XP boards" if ARCH_MULTI_V7
 	select ARMADA_XP_CLK
-	select MACH_ARMADA_370_XP
+	select CPU_PJ4B
+	select MACH_MVEBU_V7
 	select PINCTRL_ARMADA_XP
 	help
 	  Say 'Y' here if you want your kernel to support boards based
 	  on the Marvell Armada XP SoC with device tree.
 
+config MACH_KIRKWOOD
+	bool "Marvell Kirkwood boards" if ARCH_MULTI_V5
+	select ARCH_HAS_CPUFREQ
+	select ARCH_REQUIRE_GPIOLIB
+	select CPU_FEROCEON
+	select KIRKWOOD_CLK
+	select OF_IRQ
+	select ORION_IRQCHIP
+	select ORION_TIMER
+	select PCI
+	select PCI_QUIRKS
+	select PINCTRL_KIRKWOOD
+	select USE_OF
+	help
+	  Say 'Y' here if you want your kernel to support boards based
+	  on the Marvell Kirkwood device tree.
+
+config MACH_T5325
+	bool "HP T5325 thin client"
+	depends on MACH_KIRKWOOD
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  HP T5325 Thin client
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 878aebe98dcc..bbeb41ee3e75 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -4,7 +4,9 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
 AFLAGS_coherency_ll.o		:= -Wa,-march=armv7-a
 
 obj-y				 += system-controller.o mvebu-soc-id.o
-obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o
+obj-$(CONFIG_MACH_MVEBU_V7)      += board-v7.o
 obj-$(CONFIG_ARCH_MVEBU)	 += coherency.o coherency_ll.o pmsu.o
 obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)        += hotplug.o
+obj-$(CONFIG_MACH_KIRKWOOD)	 += kirkwood.o kirkwood-pm.o
+obj-$(CONFIG_MACH_T5325)	 += board-t5325.o
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
deleted file mode 100644
index f6c9d1d85c14..000000000000
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Device Tree support for Armada 370 and XP platforms.
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- * Thomas Petazzoni <thomas.petazzoni@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 <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk-provider.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/io.h>
-#include <linux/clocksource.h>
-#include <linux/dma-mapping.h>
-#include <linux/mbus.h>
-#include <linux/slab.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include "armada-370-xp.h"
-#include "common.h"
-#include "coherency.h"
-#include "mvebu-soc-id.h"
-
-static void __init armada_370_xp_map_io(void)
-{
-	debug_ll_io_init();
-}
-
-static void __init armada_370_xp_timer_and_clk_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-	coherency_init();
-	BUG_ON(mvebu_mbus_dt_init());
-#ifdef CONFIG_CACHE_L2X0
-	l2x0_of_init(0, ~0UL);
-#endif
-}
-
-static void __init i2c_quirk(void)
-{
-	struct device_node *np;
-	u32 dev, rev;
-
-	/*
-	 * Only revisons more recent than A0 support the offload
-	 * mechanism. We can exit only if we are sure that we can
-	 * get the SoC revision and it is more recent than A0.
-	 */
-	if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV)
-		return;
-
-	for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
-		struct property *new_compat;
-
-		new_compat = kzalloc(sizeof(*new_compat), GFP_KERNEL);
-
-		new_compat->name = kstrdup("compatible", GFP_KERNEL);
-		new_compat->length = sizeof("marvell,mv78230-a0-i2c");
-		new_compat->value = kstrdup("marvell,mv78230-a0-i2c",
-						GFP_KERNEL);
-
-		of_update_property(np, new_compat);
-	}
-	return;
-}
-
-static void __init armada_370_xp_dt_init(void)
-{
-	if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
-		i2c_quirk();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const armada_370_xp_dt_compat[] = {
-	"marvell,armada-370-xp",
-	NULL,
-};
-
-DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)")
-	.smp		= smp_ops(armada_xp_smp_ops),
-	.init_machine	= armada_370_xp_dt_init,
-	.map_io		= armada_370_xp_map_io,
-	.init_time	= armada_370_xp_timer_and_clk_init,
-	.restart	= mvebu_restart,
-	.dt_compat	= armada_370_xp_dt_compat,
-MACHINE_END
diff --git a/arch/arm/mach-mvebu/board-t5325.c b/arch/arm/mach-mvebu/board-t5325.c
new file mode 100644
index 000000000000..65ace6db9f28
--- /dev/null
+++ b/arch/arm/mach-mvebu/board-t5325.c
@@ -0,0 +1,41 @@
+/*
+ * HP T5325 Board Setup
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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/kernel.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <sound/alc5623.h>
+#include "board.h"
+
+static struct platform_device hp_t5325_audio_device = {
+	.name		= "t5325-audio",
+	.id		= -1,
+};
+
+static struct alc5623_platform_data alc5621_data = {
+	.add_ctrl = 0x3700,
+	.jack_det_ctrl = 0x4810,
+};
+
+static struct i2c_board_info i2c_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("alc5621", 0x1a),
+		.platform_data = &alc5621_data,
+	},
+};
+
+void __init t5325_init(void)
+{
+	i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
+	platform_device_register(&hp_t5325_audio_device);
+}
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
new file mode 100644
index 000000000000..746134ecdfc2
--- /dev/null
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -0,0 +1,139 @@
+/*
+ * Device Tree support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/clocksource.h>
+#include <linux/dma-mapping.h>
+#include <linux/mbus.h>
+#include <linux/slab.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include "armada-370-xp.h"
+#include "common.h"
+#include "coherency.h"
+#include "mvebu-soc-id.h"
+
+/*
+ * Early versions of Armada 375 SoC have a bug where the BootROM
+ * leaves an external data abort pending. The kernel is hit by this
+ * data abort as soon as it enters userspace, because it unmasks the
+ * data aborts at this moment. We register a custom abort handler
+ * below to ignore the first data abort to work around this
+ * problem.
+ */
+static int armada_375_external_abort_wa(unsigned long addr, unsigned int fsr,
+					struct pt_regs *regs)
+{
+	static int ignore_first;
+
+	if (!ignore_first && fsr == 0x1406) {
+		ignore_first = 1;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void __init mvebu_timer_and_clk_init(void)
+{
+	of_clk_init(NULL);
+	clocksource_of_init();
+	coherency_init();
+	BUG_ON(mvebu_mbus_dt_init());
+#ifdef CONFIG_CACHE_L2X0
+	l2x0_of_init(0, ~0UL);
+#endif
+
+	if (of_machine_is_compatible("marvell,armada375"))
+		hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0,
+				"imprecise external abort");
+}
+
+static void __init i2c_quirk(void)
+{
+	struct device_node *np;
+	u32 dev, rev;
+
+	/*
+	 * Only revisons more recent than A0 support the offload
+	 * mechanism. We can exit only if we are sure that we can
+	 * get the SoC revision and it is more recent than A0.
+	 */
+	if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV)
+		return;
+
+	for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
+		struct property *new_compat;
+
+		new_compat = kzalloc(sizeof(*new_compat), GFP_KERNEL);
+
+		new_compat->name = kstrdup("compatible", GFP_KERNEL);
+		new_compat->length = sizeof("marvell,mv78230-a0-i2c");
+		new_compat->value = kstrdup("marvell,mv78230-a0-i2c",
+						GFP_KERNEL);
+
+		of_update_property(np, new_compat);
+	}
+	return;
+}
+
+static void __init mvebu_dt_init(void)
+{
+	if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
+		i2c_quirk();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const armada_370_xp_dt_compat[] = {
+	"marvell,armada-370-xp",
+	NULL,
+};
+
+DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
+	.smp		= smp_ops(armada_xp_smp_ops),
+	.init_machine	= mvebu_dt_init,
+	.init_time	= mvebu_timer_and_clk_init,
+	.restart	= mvebu_restart,
+	.dt_compat	= armada_370_xp_dt_compat,
+MACHINE_END
+
+static const char * const armada_375_dt_compat[] = {
+	"marvell,armada375",
+	NULL,
+};
+
+DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)")
+	.init_time	= mvebu_timer_and_clk_init,
+	.restart	= mvebu_restart,
+	.dt_compat	= armada_375_dt_compat,
+MACHINE_END
+
+static const char * const armada_38x_dt_compat[] = {
+	"marvell,armada380",
+	"marvell,armada385",
+	NULL,
+};
+
+DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)")
+	.init_time	= mvebu_timer_and_clk_init,
+	.restart	= mvebu_restart,
+	.dt_compat	= armada_38x_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mvebu/board.h b/arch/arm/mach-mvebu/board.h
new file mode 100644
index 000000000000..de7f0a191394
--- /dev/null
+++ b/arch/arm/mach-mvebu/board.h
@@ -0,0 +1,22 @@
+/*
+ * Board functions for Marvell System On Chip
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_MVEBU_BOARD_H
+#define __ARCH_MVEBU_BOARD_H
+
+#ifdef CONFIG_MACH_T5325
+void t5325_init(void);
+#else
+static inline void t5325_init(void) {};
+#endif
+
+#endif
diff --git a/arch/arm/mach-mvebu/kirkwood-pm.c b/arch/arm/mach-mvebu/kirkwood-pm.c
new file mode 100644
index 000000000000..cbb816f2120c
--- /dev/null
+++ b/arch/arm/mach-mvebu/kirkwood-pm.c
@@ -0,0 +1,76 @@
+/*
+ * Power Management driver for Marvell Kirkwood SoCs
+ *
+ * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include "kirkwood.h"
+
+static void __iomem *ddr_operation_base;
+static void __iomem *memory_pm_ctrl;
+
+static void kirkwood_low_power(void)
+{
+	u32 mem_pm_ctrl;
+
+	mem_pm_ctrl = readl(memory_pm_ctrl);
+
+	/* Set peripherals to low-power mode */
+	writel_relaxed(~0, memory_pm_ctrl);
+
+	/* Set DDR in self-refresh */
+	writel_relaxed(0x7, ddr_operation_base);
+
+	/*
+	 * Set CPU in wait-for-interrupt state.
+	 * This disables the CPU core clocks,
+	 * the array clocks, and also the L2 controller.
+	 */
+	cpu_do_idle();
+
+	writel_relaxed(mem_pm_ctrl, memory_pm_ctrl);
+}
+
+static int kirkwood_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		kirkwood_low_power();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int kirkwood_pm_valid_standby(suspend_state_t state)
+{
+	return state == PM_SUSPEND_STANDBY;
+}
+
+static const struct platform_suspend_ops kirkwood_suspend_ops = {
+	.enter = kirkwood_suspend_enter,
+	.valid = kirkwood_pm_valid_standby,
+};
+
+int __init kirkwood_pm_init(void)
+{
+	ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
+	memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4);
+
+	suspend_set_ops(&kirkwood_suspend_ops);
+	return 0;
+}
diff --git a/arch/arm/mach-mvebu/kirkwood-pm.h b/arch/arm/mach-mvebu/kirkwood-pm.h
new file mode 100644
index 000000000000..21e7530f368b
--- /dev/null
+++ b/arch/arm/mach-mvebu/kirkwood-pm.h
@@ -0,0 +1,26 @@
+/*
+ * Power Management driver for Marvell Kirkwood SoCs
+ *
+ * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 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.
+ */
+
+#ifndef __ARCH_KIRKWOOD_PM_H
+#define __ARCH_KIRKWOOD_PM_H
+
+#ifdef CONFIG_PM
+void kirkwood_pm_init(void);
+#else
+static inline void kirkwood_pm_init(void) {};
+#endif
+
+#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
new file mode 100644
index 000000000000..120207fc36f1
--- /dev/null
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
+ *
+ * arch/arm/mach-mvebu/kirkwood.c
+ *
+ * Flattened Device Tree board initialization
+ *
+ * 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/clk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mbus.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <asm/hardware/cache-feroceon-l2.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "kirkwood.h"
+#include "kirkwood-pm.h"
+#include "common.h"
+#include "board.h"
+
+static struct resource kirkwood_cpufreq_resources[] = {
+	[0] = {
+		.start  = CPU_CONTROL_PHYS,
+		.end    = CPU_CONTROL_PHYS + 3,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device kirkwood_cpufreq_device = {
+	.name		= "kirkwood-cpufreq",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(kirkwood_cpufreq_resources),
+	.resource	= kirkwood_cpufreq_resources,
+};
+
+static void __init kirkwood_cpufreq_init(void)
+{
+	platform_device_register(&kirkwood_cpufreq_device);
+}
+
+static struct resource kirkwood_cpuidle_resource[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+		.start	= DDR_OPERATION_BASE,
+		.end	= DDR_OPERATION_BASE + 3,
+	},
+};
+
+static struct platform_device kirkwood_cpuidle = {
+	.name		= "kirkwood_cpuidle",
+	.id		= -1,
+	.resource	= kirkwood_cpuidle_resource,
+	.num_resources	= 1,
+};
+
+static void __init kirkwood_cpuidle_init(void)
+{
+	platform_device_register(&kirkwood_cpuidle);
+}
+
+#define MV643XX_ETH_MAC_ADDR_LOW	0x0414
+#define MV643XX_ETH_MAC_ADDR_HIGH	0x0418
+
+static void __init kirkwood_dt_eth_fixup(void)
+{
+	struct device_node *np;
+
+	/*
+	 * The ethernet interfaces forget the MAC address assigned by u-boot
+	 * if the clocks are turned off. Usually, u-boot on kirkwood boards
+	 * has no DT support to properly set local-mac-address property.
+	 * As a workaround, we get the MAC address from mv643xx_eth registers
+	 * and update the port device node if no valid MAC address is set.
+	 */
+	for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
+		struct device_node *pnp = of_get_parent(np);
+		struct clk *clk;
+		struct property *pmac;
+		void __iomem *io;
+		u8 *macaddr;
+		u32 reg;
+
+		if (!pnp)
+			continue;
+
+		/* skip disabled nodes or nodes with valid MAC address*/
+		if (!of_device_is_available(pnp) || of_get_mac_address(np))
+			goto eth_fixup_skip;
+
+		clk = of_clk_get(pnp, 0);
+		if (IS_ERR(clk))
+			goto eth_fixup_skip;
+
+		io = of_iomap(pnp, 0);
+		if (!io)
+			goto eth_fixup_no_map;
+
+		/* ensure port clock is not gated to not hang CPU */
+		clk_prepare_enable(clk);
+
+		/* store MAC address register contents in local-mac-address */
+		pr_err(FW_INFO "%s: local-mac-address is not set\n",
+		       np->full_name);
+
+		pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
+		if (!pmac)
+			goto eth_fixup_no_mem;
+
+		pmac->value = pmac + 1;
+		pmac->length = 6;
+		pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
+		if (!pmac->name) {
+			kfree(pmac);
+			goto eth_fixup_no_mem;
+		}
+
+		macaddr = pmac->value;
+		reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
+		macaddr[0] = (reg >> 24) & 0xff;
+		macaddr[1] = (reg >> 16) & 0xff;
+		macaddr[2] = (reg >> 8) & 0xff;
+		macaddr[3] = reg & 0xff;
+
+		reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
+		macaddr[4] = (reg >> 8) & 0xff;
+		macaddr[5] = reg & 0xff;
+
+		of_update_property(np, pmac);
+
+eth_fixup_no_mem:
+		iounmap(io);
+		clk_disable_unprepare(clk);
+eth_fixup_no_map:
+		clk_put(clk);
+eth_fixup_skip:
+		of_node_put(pnp);
+	}
+}
+
+/*
+ * Disable propagation of mbus errors to the CPU local bus, as this
+ * causes mbus errors (which can occur for example for PCI aborts) to
+ * throw CPU aborts, which we're not set up to deal with.
+ */
+void kirkwood_disable_mbus_error_propagation(void)
+{
+	void __iomem *cpu_config;
+
+	cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
+	writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
+}
+
+static struct of_dev_auxdata auxdata[] __initdata = {
+	OF_DEV_AUXDATA("marvell,kirkwood-audio", 0xf10a0000,
+		       "mvebu-audio", NULL),
+	{ /* sentinel */ }
+};
+
+static void __init kirkwood_dt_init(void)
+{
+	kirkwood_disable_mbus_error_propagation();
+
+	BUG_ON(mvebu_mbus_dt_init());
+
+#ifdef CONFIG_CACHE_FEROCEON_L2
+	feroceon_of_init();
+#endif
+	kirkwood_cpufreq_init();
+	kirkwood_cpuidle_init();
+
+	kirkwood_pm_init();
+	kirkwood_dt_eth_fixup();
+
+	if (of_machine_is_compatible("hp,t5325"))
+		t5325_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
+}
+
+static const char * const kirkwood_dt_board_compat[] = {
+	"marvell,kirkwood",
+	NULL
+};
+
+DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
+	/* Maintainer: Jason Cooper <jason@lakedaemon.net> */
+	.init_machine	= kirkwood_dt_init,
+	.restart	= mvebu_restart,
+	.dt_compat	= kirkwood_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mvebu/kirkwood.h b/arch/arm/mach-mvebu/kirkwood.h
new file mode 100644
index 000000000000..89f3d1f51643
--- /dev/null
+++ b/arch/arm/mach-mvebu/kirkwood.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-mvebu/kirkwood.h
+ *
+ * Generic definitions for Marvell Kirkwood SoC flavors:
+ * 88F6180, 88F6192 and 88F6281.
+ *
+ * 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.
+ */
+
+#define KIRKWOOD_REGS_PHYS_BASE	0xf1000000
+#define DDR_PHYS_BASE           (KIRKWOOD_REGS_PHYS_BASE + 0x00000)
+#define BRIDGE_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x20000)
+
+#define DDR_OPERATION_BASE	(DDR_PHYS_BASE + 0x1418)
+
+#define CPU_CONFIG_PHYS		(BRIDGE_PHYS_BASE + 0x0100)
+#define CPU_CONFIG_ERROR_PROP	0x00000004
+
+#define CPU_CONTROL_PHYS	(BRIDGE_PHYS_BASE + 0x0104)
+#define MEMORY_PM_CTRL_PHYS	(BRIDGE_PHYS_BASE + 0x0118)
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c
index f3b325f6cbd4..f3d4cf53f746 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.c
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.c
@@ -38,6 +38,7 @@ static bool is_id_valid;
 static const struct of_device_id mvebu_pcie_of_match_table[] = {
 	{ .compatible = "marvell,armada-xp-pcie", },
 	{ .compatible = "marvell,armada-370-pcie", },
+	{ .compatible = "marvell,kirkwood-pcie" },
 	{},
 };
 
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
index a7fb89a5b5d9..614ba6832ff3 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -1,5 +1,5 @@
 /*
- * System controller support for Armada 370 and XP platforms.
+ * System controller support for Armada 370, 375 and XP platforms.
  *
  * Copyright (C) 2012 Marvell
  *
@@ -11,7 +11,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  *
- * The Armada 370 and Armada XP SoCs both have a range of
+ * The Armada 370, 375 and Armada XP SoCs have a range of
  * miscellaneous registers, that do not belong to a particular device,
  * but rather provide system-level features. This basic
  * system-controller driver provides a device tree binding for those
@@ -47,6 +47,13 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = {
 	.system_soft_reset = 0x1,
 };
 
+static const struct mvebu_system_controller armada_375_system_controller = {
+	.rstoutn_mask_offset = 0x54,
+	.system_soft_reset_offset = 0x58,
+	.rstoutn_mask_reset_out_en = 0x1,
+	.system_soft_reset = 0x1,
+};
+
 static const struct mvebu_system_controller orion_system_controller = {
 	.rstoutn_mask_offset = 0x108,
 	.system_soft_reset_offset = 0x10c,
@@ -54,13 +61,16 @@ static const struct mvebu_system_controller orion_system_controller = {
 	.system_soft_reset = 0x1,
 };
 
-static struct of_device_id of_system_controller_table[] = {
+static const struct of_device_id of_system_controller_table[] = {
 	{
 		.compatible = "marvell,orion-system-controller",
 		.data = (void *) &orion_system_controller,
 	}, {
 		.compatible = "marvell,armada-370-xp-system-controller",
 		.data = (void *) &armada_370_xp_system_controller,
+	}, {
+		.compatible = "marvell,armada-375-system-controller",
+		.data = (void *) &armada_375_system_controller,
 	},
 	{ /* end of list */ },
 };
@@ -90,13 +100,12 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd)
 
 static int __init mvebu_system_controller_init(void)
 {
+	const struct of_device_id *match;
 	struct device_node *np;
 
-	np = of_find_matching_node(NULL, of_system_controller_table);
+	np = of_find_matching_node_and_match(NULL, of_system_controller_table,
+					     &match);
 	if (np) {
-		const struct of_device_id *match =
-		    of_match_node(of_system_controller_table, np);
-		BUG_ON(!match);
 		system_controller_base = of_iomap(np, 0);
 		mvebu_sc = (struct mvebu_system_controller *)match->data;
 		of_node_put(np);
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 8cde9e05b5d6..84794137b175 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -16,11 +16,7 @@ config ARCH_MXS
 	bool "Freescale MXS (i.MX23, i.MX28) support"
 	depends on ARCH_MULTI_V5
 	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
-	select CLKSRC_OF
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK_PREPARE
 	select PINCTRL
 	select SOC_BUS
 	select SOC_IMX23
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 1dc5acd4fc99..2e7cec86e50e 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -157,6 +157,8 @@ enum mac_oui {
 	OUI_FSL,
 	OUI_DENX,
 	OUI_CRYSTALFONTZ,
+	OUI_I2SE,
+	OUI_ARMADEUS,
 };
 
 static void __init update_fec_mac_prop(enum mac_oui oui)
@@ -211,6 +213,16 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
 			macaddr[1] = 0xb9;
 			macaddr[2] = 0xe1;
 			break;
+		case OUI_I2SE:
+			macaddr[0] = 0x00;
+			macaddr[1] = 0x01;
+			macaddr[2] = 0x87;
+			break;
+		case OUI_ARMADEUS:
+			macaddr[0] = 0x00;
+			macaddr[1] = 0x1e;
+			macaddr[2] = 0xac;
+			break;
 		}
 		val = ocotp[i];
 		macaddr[3] = (val >> 16) & 0xff;
@@ -236,6 +248,11 @@ static void __init imx28_evk_init(void)
 	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 }
 
+static void __init imx28_apf28_init(void)
+{
+	update_fec_mac_prop(OUI_ARMADEUS);
+}
+
 static int apx4devkit_phy_fixup(struct phy_device *phy)
 {
 	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -330,6 +347,11 @@ static void __init crystalfontz_init(void)
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
 }
 
+static void __init duckbill_init(void)
+{
+	update_fec_mac_prop(OUI_I2SE);
+}
+
 static void __init m28cu3_init(void)
 {
 	update_fec_mac_prop(OUI_DENX);
@@ -426,6 +448,11 @@ static int __init mxs_restart_init(void)
 	return 0;
 }
 
+static void __init eukrea_mbmx283lc_init(void)
+{
+	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
+}
+
 static void __init mxs_machine_init(void)
 {
 	struct device_node *root;
@@ -458,10 +485,16 @@ static void __init mxs_machine_init(void)
 
 	if (of_machine_is_compatible("fsl,imx28-evk"))
 		imx28_evk_init();
+	if (of_machine_is_compatible("armadeus,imx28-apf28"))
+		imx28_apf28_init();
 	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 		apx4devkit_init();
 	else if (of_machine_is_compatible("crystalfontz,cfa10036"))
 		crystalfontz_init();
+	else if (of_machine_is_compatible("eukrea,mbmx283lc"))
+		eukrea_mbmx283lc_init();
+	else if (of_machine_is_compatible("i2se,duckbill"))
+		duckbill_init();
 	else if (of_machine_is_compatible("msr,m28cu3"))
 		m28cu3_init();
 
diff --git a/arch/arm/mach-netx/include/mach/timex.h b/arch/arm/mach-netx/include/mach/timex.h
deleted file mode 100644
index 1120dd0ba393..000000000000
--- a/arch/arm/mach-netx/include/mach/timex.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-netx/include/mach/timex.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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 CLOCK_TICK_RATE 100000000
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 6df42e643031..e2346013e227 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -28,6 +28,9 @@
 #include <asm/mach/time.h>
 #include <mach/netx-regs.h>
 
+#define NETX_CLOCK_FREQ 100000000
+#define NETX_LATCH DIV_ROUND_CLOSEST(NETX_CLOCK_FREQ, HZ)
+
 #define TIMER_CLOCKEVENT 0
 #define TIMER_CLOCKSOURCE 1
 
@@ -41,7 +44,7 @@ static void netx_set_mode(enum clock_event_mode mode,
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		writel(LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
+		writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
 		tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
 			NETX_GPIO_COUNTER_CTRL_IRQ_EN |
 			NETX_GPIO_COUNTER_CTRL_RUN;
@@ -114,7 +117,7 @@ void __init netx_timer_init(void)
 	/* Reset the timer value to zero */
 	writel(0, NETX_GPIO_COUNTER_CURRENT(0));
 
-	writel(LATCH, NETX_GPIO_COUNTER_MAX(0));
+	writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(0));
 
 	/* acknowledge interrupt */
 	writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
@@ -137,11 +140,11 @@ void __init netx_timer_init(void)
 			NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
 
 	clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
-		"netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up);
+		"netx_timer", NETX_CLOCK_FREQ, 200, 32, clocksource_mmio_readl_up);
 
 	/* with max_delta_ns >= delta2ns(0x800) the system currently runs fine.
 	 * Adding some safety ... */
 	netx_clockevent.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&netx_clockevent, CLOCK_TICK_RATE,
+	clockevents_config_and_register(&netx_clockevent, NETX_CLOCK_FREQ,
 					0xa00, 0xfffffffe);
 }
diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
index 4d42da49753c..486d301f43fd 100644
--- a/arch/arm/mach-nomadik/Kconfig
+++ b/arch/arm/mach-nomadik/Kconfig
@@ -6,16 +6,11 @@ config ARCH_NOMADIK
 	select ARM_VIC
 	select CLKSRC_NOMADIK_MTU
 	select CLKSRC_NOMADIK_MTU_SCHED_CLOCK
-	select CLKSRC_OF
-	select COMMON_CLK
 	select CPU_ARM926T
-	select GENERIC_CLOCKEVENTS
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
 	select PINCTRL_NOMADIK
 	select PINCTRL_STN8815
-	select SPARSE_IRQ
-	select USE_OF
 	help
 	  Support for the Nomadik platform by ST-Ericsson
 
diff --git a/arch/arm/mach-nspire/Kconfig b/arch/arm/mach-nspire/Kconfig
index 59d8f0a70919..bc41f26c1a12 100644
--- a/arch/arm/mach-nspire/Kconfig
+++ b/arch/arm/mach-nspire/Kconfig
@@ -3,14 +3,9 @@ config ARCH_NSPIRE
 	depends on ARCH_MULTI_V4_V5
 	depends on MMU
 	select CPU_ARM926T
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select SPARSE_IRQ
 	select ARM_AMBA
 	select ARM_VIC
 	select ARM_TIMER_SP804
-	select USE_OF
-	select CLKSRC_OF
 	help
 	  This enables support for systems using the TI-NSPIRE CPU
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 5bb8ce86d54b..4be601b638d7 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -32,55 +32,51 @@
 
 #define OMAP1_DMA_BASE			(0xfffed800)
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
-#define OMAP1_DMA_STRIDE		0x40
 
-static u32 errata;
 static u32 enable_1510_mode;
-static u8 dma_stride;
-static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
-
-static u16 reg_map[] = {
-	[GCR]		= 0x400,
-	[GSCR]		= 0x404,
-	[GRST1]		= 0x408,
-	[HW_ID]		= 0x442,
-	[PCH2_ID]	= 0x444,
-	[PCH0_ID]	= 0x446,
-	[PCH1_ID]	= 0x448,
-	[PCHG_ID]	= 0x44a,
-	[PCHD_ID]	= 0x44c,
-	[CAPS_0]	= 0x44e,
-	[CAPS_1]	= 0x452,
-	[CAPS_2]	= 0x456,
-	[CAPS_3]	= 0x458,
-	[CAPS_4]	= 0x45a,
-	[PCH2_SR]	= 0x460,
-	[PCH0_SR]	= 0x480,
-	[PCH1_SR]	= 0x482,
-	[PCHD_SR]	= 0x4c0,
+
+static const struct omap_dma_reg reg_map[] = {
+	[GCR]		= { 0x0400, 0x00, OMAP_DMA_REG_16BIT },
+	[GSCR]		= { 0x0404, 0x00, OMAP_DMA_REG_16BIT },
+	[GRST1]		= { 0x0408, 0x00, OMAP_DMA_REG_16BIT },
+	[HW_ID]		= { 0x0442, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH2_ID]	= { 0x0444, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH0_ID]	= { 0x0446, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH1_ID]	= { 0x0448, 0x00, OMAP_DMA_REG_16BIT },
+	[PCHG_ID]	= { 0x044a, 0x00, OMAP_DMA_REG_16BIT },
+	[PCHD_ID]	= { 0x044c, 0x00, OMAP_DMA_REG_16BIT },
+	[CAPS_0]	= { 0x044e, 0x00, OMAP_DMA_REG_2X16BIT },
+	[CAPS_1]	= { 0x0452, 0x00, OMAP_DMA_REG_2X16BIT },
+	[CAPS_2]	= { 0x0456, 0x00, OMAP_DMA_REG_16BIT },
+	[CAPS_3]	= { 0x0458, 0x00, OMAP_DMA_REG_16BIT },
+	[CAPS_4]	= { 0x045a, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH2_SR]	= { 0x0460, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH0_SR]	= { 0x0480, 0x00, OMAP_DMA_REG_16BIT },
+	[PCH1_SR]	= { 0x0482, 0x00, OMAP_DMA_REG_16BIT },
+	[PCHD_SR]	= { 0x04c0, 0x00, OMAP_DMA_REG_16BIT },
 
 	/* Common Registers */
-	[CSDP]		= 0x00,
-	[CCR]		= 0x02,
-	[CICR]		= 0x04,
-	[CSR]		= 0x06,
-	[CEN]		= 0x10,
-	[CFN]		= 0x12,
-	[CSFI]		= 0x14,
-	[CSEI]		= 0x16,
-	[CPC]		= 0x18,	/* 15xx only */
-	[CSAC]		= 0x18,
-	[CDAC]		= 0x1a,
-	[CDEI]		= 0x1c,
-	[CDFI]		= 0x1e,
-	[CLNK_CTRL]	= 0x28,
+	[CSDP]		= { 0x0000, 0x40, OMAP_DMA_REG_16BIT },
+	[CCR]		= { 0x0002, 0x40, OMAP_DMA_REG_16BIT },
+	[CICR]		= { 0x0004, 0x40, OMAP_DMA_REG_16BIT },
+	[CSR]		= { 0x0006, 0x40, OMAP_DMA_REG_16BIT },
+	[CEN]		= { 0x0010, 0x40, OMAP_DMA_REG_16BIT },
+	[CFN]		= { 0x0012, 0x40, OMAP_DMA_REG_16BIT },
+	[CSFI]		= { 0x0014, 0x40, OMAP_DMA_REG_16BIT },
+	[CSEI]		= { 0x0016, 0x40, OMAP_DMA_REG_16BIT },
+	[CPC]		= { 0x0018, 0x40, OMAP_DMA_REG_16BIT },	/* 15xx only */
+	[CSAC]		= { 0x0018, 0x40, OMAP_DMA_REG_16BIT },
+	[CDAC]		= { 0x001a, 0x40, OMAP_DMA_REG_16BIT },
+	[CDEI]		= { 0x001c, 0x40, OMAP_DMA_REG_16BIT },
+	[CDFI]		= { 0x001e, 0x40, OMAP_DMA_REG_16BIT },
+	[CLNK_CTRL]	= { 0x0028, 0x40, OMAP_DMA_REG_16BIT },
 
 	/* Channel specific register offsets */
-	[CSSA]		= 0x08,
-	[CDSA]		= 0x0c,
-	[COLOR]		= 0x20,
-	[CCR2]		= 0x24,
-	[LCH_CTRL]	= 0x2a,
+	[CSSA]		= { 0x0008, 0x40, OMAP_DMA_REG_2X16BIT },
+	[CDSA]		= { 0x000c, 0x40, OMAP_DMA_REG_2X16BIT },
+	[COLOR]		= { 0x0020, 0x40, OMAP_DMA_REG_2X16BIT },
+	[CCR2]		= { 0x0024, 0x40, OMAP_DMA_REG_16BIT },
+	[LCH_CTRL]	= { 0x002a, 0x40, OMAP_DMA_REG_16BIT },
 };
 
 static struct resource res[] __initdata = {
@@ -181,44 +177,36 @@ static struct resource res[] __initdata = {
 static void __iomem *dma_base;
 static inline void dma_write(u32 val, int reg, int lch)
 {
-	u8  stride;
-	u32 offset;
+	void __iomem *addr = dma_base;
 
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
+	addr += reg_map[reg].offset;
+	addr += reg_map[reg].stride * lch;
 
-	__raw_writew(val, dma_base + offset);
-	if ((reg > CLNK_CTRL && reg < CCEN) ||
-			(reg > PCHD_ID && reg < CAPS_2)) {
-		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
-		__raw_writew(val >> 16, dma_base + offset2);
-	}
+	__raw_writew(val, addr);
+	if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
+		__raw_writew(val >> 16, addr + 2);
 }
 
 static inline u32 dma_read(int reg, int lch)
 {
-	u8 stride;
-	u32 offset, val;
-
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
-
-	val = __raw_readw(dma_base + offset);
-	if ((reg > CLNK_CTRL && reg < CCEN) ||
-			(reg > PCHD_ID && reg < CAPS_2)) {
-		u16 upper;
-		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
-		upper = __raw_readw(dma_base + offset2);
-		val |= (upper << 16);
-	}
+	void __iomem *addr = dma_base;
+	uint32_t val;
+
+	addr += reg_map[reg].offset;
+	addr += reg_map[reg].stride * lch;
+
+	val = __raw_readw(addr);
+	if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
+		val |= __raw_readw(addr + 2) << 16;
+
 	return val;
 }
 
 static void omap1_clear_lch_regs(int lch)
 {
-	int i = dma_common_ch_start;
+	int i;
 
-	for (; i <= dma_common_ch_end; i += 1)
+	for (i = CPC; i <= COLOR; i += 1)
 		dma_write(0, i, lch);
 }
 
@@ -255,8 +243,9 @@ static void omap1_show_dma_caps(void)
 	return;
 }
 
-static u32 configure_dma_errata(void)
+static unsigned configure_dma_errata(void)
 {
+	unsigned errata = 0;
 
 	/*
 	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
@@ -272,11 +261,23 @@ static const struct platform_device_info omap_dma_dev_info = {
 	.name = "omap-dma-engine",
 	.id = -1,
 	.dma_mask = DMA_BIT_MASK(32),
+	.res = res,
+	.num_res = 1,
+};
+
+static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.reg_map	= reg_map,
+	.channel_stride	= 0x40,
+	.show_dma_caps	= omap1_show_dma_caps,
+	.clear_lch_regs	= omap1_clear_lch_regs,
+	.clear_dma	= omap1_clear_dma,
+	.dma_write	= dma_write,
+	.dma_read	= dma_read,
 };
 
 static int __init omap1_system_dma_init(void)
 {
-	struct omap_system_dma_plat_info	*p;
+	struct omap_system_dma_plat_info	p;
 	struct omap_dma_dev_attr		*d;
 	struct platform_device			*pdev, *dma_pdev;
 	int ret;
@@ -302,20 +303,12 @@ static int __init omap1_system_dma_init(void)
 		goto exit_iounmap;
 	}
 
-	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
-	if (!p) {
-		dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
-			__func__, pdev->name);
-		ret = -ENOMEM;
-		goto exit_iounmap;
-	}
-
 	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
 	if (!d) {
 		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
 			__func__, pdev->name);
 		ret = -ENOMEM;
-		goto exit_release_p;
+		goto exit_iounmap;
 	}
 
 	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
@@ -336,17 +329,6 @@ static int __init omap1_system_dma_init(void)
 	d->dev_caps		|= CLEAR_CSR_ON_READ;
 	d->dev_caps		|= IS_WORD_16;
 
-
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-	if (!d->chan) {
-		dev_err(&pdev->dev,
-			"%s: Memory allocation failed for d->chan!\n",
-			__func__);
-		ret = -ENOMEM;
-		goto exit_release_d;
-	}
-
 	if (cpu_is_omap15xx())
 		d->chan_count = 9;
 	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -356,35 +338,24 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
-	p->dma_attr = d;
-
-	p->show_dma_caps	= omap1_show_dma_caps;
-	p->clear_lch_regs	= omap1_clear_lch_regs;
-	p->clear_dma		= omap1_clear_dma;
-	p->dma_write		= dma_write;
-	p->dma_read		= dma_read;
-	p->disable_irq_lch	= NULL;
-
-	p->errata = configure_dma_errata();
+	p = dma_plat_info;
+	p.dma_attr = d;
+	p.errata = configure_dma_errata();
 
-	ret = platform_device_add_data(pdev, p, sizeof(*p));
+	ret = platform_device_add_data(pdev, &p, sizeof(p));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_release_chan;
+		goto exit_release_d;
 	}
 
 	ret = platform_device_add(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_release_chan;
+		goto exit_release_d;
 	}
 
-	dma_stride		= OMAP1_DMA_STRIDE;
-	dma_common_ch_start	= CPC;
-	dma_common_ch_end	= COLOR;
-
 	dma_pdev = platform_device_register_full(&omap_dma_dev_info);
 	if (IS_ERR(dma_pdev)) {
 		ret = PTR_ERR(dma_pdev);
@@ -395,12 +366,8 @@ static int __init omap1_system_dma_init(void)
 
 exit_release_pdev:
 	platform_device_del(pdev);
-exit_release_chan:
-	kfree(d->chan);
 exit_release_d:
 	kfree(d);
-exit_release_p:
-	kfree(p);
 exit_iounmap:
 	iounmap(dma_base);
 exit_device_put:
diff --git a/arch/arm/mach-omap1/include/mach/timex.h b/arch/arm/mach-omap1/include/mach/timex.h
deleted file mode 100644
index 4793790d53cc..000000000000
--- a/arch/arm/mach-omap1/include/mach/timex.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/timex.h
- */
-
-#include <plat/timex.h>
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0af7ca02314d..0dc337d02f69 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -6,7 +6,6 @@ config ARCH_OMAP2
 	depends on ARCH_MULTI_V6
 	select ARCH_OMAP2PLUS
 	select CPU_V6
-	select MULTI_IRQ_HANDLER
 	select SOC_HAS_OMAP2_SDRC
 
 config ARCH_OMAP3
@@ -15,13 +14,10 @@ config ARCH_OMAP3
 	select ARCH_OMAP2PLUS
 	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
-	select CPU_V7
-	select MULTI_IRQ_HANDLER
 	select OMAP_INTERCONNECT
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
 	select SOC_HAS_OMAP2_SDRC
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -33,16 +29,13 @@ config ARCH_OMAP4
 	select ARM_ERRATA_720789
 	select ARM_GIC
 	select CACHE_L2X0
-	select CPU_V7
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select OMAP_INTERCONNECT
 	select PL310_ERRATA_588369
 	select PL310_ERRATA_727915
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_775420
 
@@ -53,10 +46,8 @@ config SOC_OMAP5
 	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
-	select CPU_V7
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select HAVE_ARM_ARCH_TIMER
 	select ARM_ERRATA_798181 if SMP
 
@@ -66,16 +57,12 @@ config SOC_AM33XX
 	select ARCH_OMAP2PLUS
 	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
-	select CPU_V7
-	select MULTI_IRQ_HANDLER
 
 config SOC_AM43XX
 	bool "TI AM43x"
 	depends on ARCH_MULTI_V7
-	select CPU_V7
 	select ARCH_OMAP2PLUS
 	select ARCH_HAS_OPP
-	select MULTI_IRQ_HANDLER
 	select ARM_GIC
 	select MACH_OMAP_GENERIC
 
@@ -86,8 +73,6 @@ config SOC_DRA7XX
 	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
-	select CPU_V7
-	select HAVE_SMP
 	select HAVE_ARM_ARCH_TIMER
 
 config ARCH_OMAP2PLUS
@@ -98,17 +83,13 @@ config ARCH_OMAP2PLUS
 	select ARCH_OMAP
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
 	select MACH_OMAP_GENERIC
 	select OMAP_DM_TIMER
 	select PINCTRL
 	select PROC_DEVICETREE if PROC_FS
 	select SOC_BUS
-	select SPARSE_IRQ
 	select TI_PRIV_EDMA
-	select USE_OF
 	help
 	  Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 
diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c
index 25b79a297365..6a6935caac1e 100644
--- a/arch/arm/mach-omap2/am35xx-emac.c
+++ b/arch/arm/mach-omap2/am35xx-emac.c
@@ -17,7 +17,6 @@
 
 #include <linux/err.h>
 #include <linux/davinci_emac.h>
-#include <asm/system.h>
 #include "omap_device.h"
 #include "am35xx.h"
 #include "control.h"
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 3b05aea56d1f..11ed9152e665 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -433,7 +433,9 @@ static const struct clk_ops dpll4_m5x2_ck_ops = {
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.set_rate	= &omap3_clkoutx2_set_rate,
 	.recalc_rate	= &omap3_clkoutx2_recalc,
+	.round_rate	= &omap3_clkoutx2_round_rate,
 };
 
 static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 4c158c838d40..01fc710c8181 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -23,6 +23,8 @@
 #include "prm.h"
 #include "clockdomain.h"
 
+#define MAX_CPUS	2
+
 /* Machine specific information */
 struct idle_statedata {
 	u32 cpu_state;
@@ -48,11 +50,11 @@ static struct idle_statedata omap4_idle_data[] = {
 	},
 };
 
-static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS];
-static struct clockdomain *cpu_clkdm[NR_CPUS];
+static struct powerdomain *mpu_pd, *cpu_pd[MAX_CPUS];
+static struct clockdomain *cpu_clkdm[MAX_CPUS];
 
 static atomic_t abort_barrier;
-static bool cpu_done[NR_CPUS];
+static bool cpu_done[MAX_CPUS];
 static struct idle_statedata *state_ptr = &omap4_idle_data[0];
 
 /* Private functions */
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 4cf165502b35..93ebb4007ea9 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -301,7 +301,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	board_data->version = ver;
 	board_data->dsi_enable_pads = omap_dsi_enable_pads;
 	board_data->dsi_disable_pads = omap_dsi_disable_pads;
-	board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 	board_data->set_min_bus_tput = omap_dss_set_min_bus_tput;
 
 	omap_display_device.dev.platform_data = board_data;
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 49fd0d501c9b..5689c88d986d 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -35,97 +35,80 @@
 #include "omap_hwmod.h"
 #include "omap_device.h"
 
-#define OMAP2_DMA_STRIDE	0x60
-
-static u32 errata;
-static u8 dma_stride;
-
-static struct omap_dma_dev_attr *d;
-
-static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
-
-static u16 reg_map[] = {
-	[REVISION]		= 0x00,
-	[GCR]			= 0x78,
-	[IRQSTATUS_L0]		= 0x08,
-	[IRQSTATUS_L1]		= 0x0c,
-	[IRQSTATUS_L2]		= 0x10,
-	[IRQSTATUS_L3]		= 0x14,
-	[IRQENABLE_L0]		= 0x18,
-	[IRQENABLE_L1]		= 0x1c,
-	[IRQENABLE_L2]		= 0x20,
-	[IRQENABLE_L3]		= 0x24,
-	[SYSSTATUS]		= 0x28,
-	[OCP_SYSCONFIG]		= 0x2c,
-	[CAPS_0]		= 0x64,
-	[CAPS_2]		= 0x6c,
-	[CAPS_3]		= 0x70,
-	[CAPS_4]		= 0x74,
+static enum omap_reg_offsets dma_common_ch_end;
+
+static const struct omap_dma_reg reg_map[] = {
+	[REVISION]	= { 0x0000, 0x00, OMAP_DMA_REG_32BIT },
+	[GCR]		= { 0x0078, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQSTATUS_L0]	= { 0x0008, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQSTATUS_L1]	= { 0x000c, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQSTATUS_L2]	= { 0x0010, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQSTATUS_L3]	= { 0x0014, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQENABLE_L0]	= { 0x0018, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQENABLE_L1]	= { 0x001c, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQENABLE_L2]	= { 0x0020, 0x00, OMAP_DMA_REG_32BIT },
+	[IRQENABLE_L3]	= { 0x0024, 0x00, OMAP_DMA_REG_32BIT },
+	[SYSSTATUS]	= { 0x0028, 0x00, OMAP_DMA_REG_32BIT },
+	[OCP_SYSCONFIG]	= { 0x002c, 0x00, OMAP_DMA_REG_32BIT },
+	[CAPS_0]	= { 0x0064, 0x00, OMAP_DMA_REG_32BIT },
+	[CAPS_2]	= { 0x006c, 0x00, OMAP_DMA_REG_32BIT },
+	[CAPS_3]	= { 0x0070, 0x00, OMAP_DMA_REG_32BIT },
+	[CAPS_4]	= { 0x0074, 0x00, OMAP_DMA_REG_32BIT },
 
 	/* Common register offsets */
-	[CCR]			= 0x80,
-	[CLNK_CTRL]		= 0x84,
-	[CICR]			= 0x88,
-	[CSR]			= 0x8c,
-	[CSDP]			= 0x90,
-	[CEN]			= 0x94,
-	[CFN]			= 0x98,
-	[CSEI]			= 0xa4,
-	[CSFI]			= 0xa8,
-	[CDEI]			= 0xac,
-	[CDFI]			= 0xb0,
-	[CSAC]			= 0xb4,
-	[CDAC]			= 0xb8,
+	[CCR]		= { 0x0080, 0x60, OMAP_DMA_REG_32BIT },
+	[CLNK_CTRL]	= { 0x0084, 0x60, OMAP_DMA_REG_32BIT },
+	[CICR]		= { 0x0088, 0x60, OMAP_DMA_REG_32BIT },
+	[CSR]		= { 0x008c, 0x60, OMAP_DMA_REG_32BIT },
+	[CSDP]		= { 0x0090, 0x60, OMAP_DMA_REG_32BIT },
+	[CEN]		= { 0x0094, 0x60, OMAP_DMA_REG_32BIT },
+	[CFN]		= { 0x0098, 0x60, OMAP_DMA_REG_32BIT },
+	[CSEI]		= { 0x00a4, 0x60, OMAP_DMA_REG_32BIT },
+	[CSFI]		= { 0x00a8, 0x60, OMAP_DMA_REG_32BIT },
+	[CDEI]		= { 0x00ac, 0x60, OMAP_DMA_REG_32BIT },
+	[CDFI]		= { 0x00b0, 0x60, OMAP_DMA_REG_32BIT },
+	[CSAC]		= { 0x00b4, 0x60, OMAP_DMA_REG_32BIT },
+	[CDAC]		= { 0x00b8, 0x60, OMAP_DMA_REG_32BIT },
 
 	/* Channel specific register offsets */
-	[CSSA]			= 0x9c,
-	[CDSA]			= 0xa0,
-	[CCEN]			= 0xbc,
-	[CCFN]			= 0xc0,
-	[COLOR]			= 0xc4,
+	[CSSA]		= { 0x009c, 0x60, OMAP_DMA_REG_32BIT },
+	[CDSA]		= { 0x00a0, 0x60, OMAP_DMA_REG_32BIT },
+	[CCEN]		= { 0x00bc, 0x60, OMAP_DMA_REG_32BIT },
+	[CCFN]		= { 0x00c0, 0x60, OMAP_DMA_REG_32BIT },
+	[COLOR]		= { 0x00c4, 0x60, OMAP_DMA_REG_32BIT },
 
 	/* OMAP4 specific registers */
-	[CDP]			= 0xd0,
-	[CNDP]			= 0xd4,
-	[CCDN]			= 0xd8,
+	[CDP]		= { 0x00d0, 0x60, OMAP_DMA_REG_32BIT },
+	[CNDP]		= { 0x00d4, 0x60, OMAP_DMA_REG_32BIT },
+	[CCDN]		= { 0x00d8, 0x60, OMAP_DMA_REG_32BIT },
 };
 
 static void __iomem *dma_base;
 static inline void dma_write(u32 val, int reg, int lch)
 {
-	u8  stride;
-	u32 offset;
+	void __iomem *addr = dma_base;
 
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
-	__raw_writel(val, dma_base + offset);
+	addr += reg_map[reg].offset;
+	addr += reg_map[reg].stride * lch;
+
+	__raw_writel(val, addr);
 }
 
 static inline u32 dma_read(int reg, int lch)
 {
-	u8 stride;
-	u32 offset, val;
-
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
-	val = __raw_readl(dma_base + offset);
-	return val;
-}
+	void __iomem *addr = dma_base;
 
-static inline void omap2_disable_irq_lch(int lch)
-{
-	u32 val;
+	addr += reg_map[reg].offset;
+	addr += reg_map[reg].stride * lch;
 
-	val = dma_read(IRQENABLE_L0, lch);
-	val &= ~(1 << lch);
-	dma_write(val, IRQENABLE_L0, lch);
+	return __raw_readl(addr);
 }
 
 static void omap2_clear_dma(int lch)
 {
-	int i = dma_common_ch_start;
+	int i;
 
-	for (; i <= dma_common_ch_end; i += 1)
+	for (i = CSDP; i <= dma_common_ch_end; i += 1)
 		dma_write(0, i, lch);
 }
 
@@ -137,8 +120,9 @@ static void omap2_show_dma_caps(void)
 	return;
 }
 
-static u32 configure_dma_errata(void)
+static unsigned configure_dma_errata(void)
 {
+	unsigned errata = 0;
 
 	/*
 	 * Errata applicable for OMAP2430ES1.0 and all omap2420
@@ -220,48 +204,50 @@ static u32 configure_dma_errata(void)
 	return errata;
 }
 
+static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.reg_map	= reg_map,
+	.channel_stride	= 0x60,
+	.show_dma_caps	= omap2_show_dma_caps,
+	.clear_dma	= omap2_clear_dma,
+	.dma_write	= dma_write,
+	.dma_read	= dma_read,
+};
+
+static struct platform_device_info omap_dma_dev_info = {
+	.name = "omap-dma-engine",
+	.id = -1,
+	.dma_mask = DMA_BIT_MASK(32),
+};
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
 	struct platform_device			*pdev;
-	struct omap_system_dma_plat_info	*p;
+	struct omap_system_dma_plat_info	p;
+	struct omap_dma_dev_attr		*d;
 	struct resource				*mem;
 	char					*name = "omap_dma_system";
 
-	dma_stride		= OMAP2_DMA_STRIDE;
-	dma_common_ch_start	= CSDP;
-
-	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
-	if (!p) {
-		pr_err("%s: Unable to allocate pdata for %s:%s\n",
-			__func__, name, oh->name);
-		return -ENOMEM;
-	}
-
-	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
-	p->disable_irq_lch	= omap2_disable_irq_lch;
-	p->show_dma_caps	= omap2_show_dma_caps;
-	p->clear_dma		= omap2_clear_dma;
-	p->dma_write		= dma_write;
-	p->dma_read		= dma_read;
-
-	p->clear_lch_regs	= NULL;
-
-	p->errata		= configure_dma_errata();
+	p = dma_plat_info;
+	p.dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr;
+	p.errata = configure_dma_errata();
 
-	pdev = omap_device_build(name, 0, oh, p, sizeof(*p));
-	kfree(p);
+	pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
 	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
 		return PTR_ERR(pdev);
 	}
 
+	omap_dma_dev_info.res = pdev->resource;
+	omap_dma_dev_info.num_res = pdev->num_resources;
+
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
 		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
 		return -EINVAL;
 	}
+
 	dma_base = ioremap(mem->start, resource_size(mem));
 	if (!dma_base) {
 		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -269,13 +255,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	}
 
 	d = oh->dev_attr;
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-
-	if (!d->chan) {
-		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
-		return -ENOMEM;
-	}
 
 	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
 		d->dev_caps |= HS_CHANNELS_RESERVED;
@@ -289,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	return 0;
 }
 
-static const struct platform_device_info omap_dma_dev_info = {
-	.name = "omap-dma-engine",
-	.id = -1,
-	.dma_mask = DMA_BIT_MASK(32),
-};
-
 static int __init omap2_system_dma_init(void)
 {
 	struct platform_device *pdev;
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 3185ced807c9..3c418ea54bbe 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -623,6 +623,32 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 
 /* Clock control for DPLL outputs */
 
+/* Find the parent DPLL for the given clkoutx2 clock */
+static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
+{
+	struct clk_hw_omap *pclk = NULL;
+	struct clk *parent;
+
+	/* Walk up the parents of clk, looking for a DPLL */
+	do {
+		do {
+			parent = __clk_get_parent(hw->clk);
+			hw = __clk_get_hw(parent);
+		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+		if (!hw)
+			break;
+		pclk = to_clk_hw_omap(hw);
+	} while (pclk && !pclk->dpll_data);
+
+	/* clk does not have a DPLL as a parent?  error in the clock data */
+	if (!pclk) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	return pclk;
+}
+
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
@@ -637,27 +663,14 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	unsigned long rate;
 	u32 v;
 	struct clk_hw_omap *pclk = NULL;
-	struct clk *parent;
 
 	if (!parent_rate)
 		return 0;
 
-	/* Walk up the parents of clk, looking for a DPLL */
-	do {
-		do {
-			parent = __clk_get_parent(hw->clk);
-			hw = __clk_get_hw(parent);
-		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
-		if (!hw)
-			break;
-		pclk = to_clk_hw_omap(hw);
-	} while (pclk && !pclk->dpll_data);
+	pclk = omap3_find_clkoutx2_dpll(hw);
 
-	/* clk does not have a DPLL as a parent?  error in the clock data */
-	if (!pclk) {
-		WARN_ON(1);
+	if (!pclk)
 		return 0;
-	}
 
 	dd = pclk->dpll_data;
 
@@ -672,6 +685,55 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	return rate;
 }
 
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	return 0;
+}
+
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	const struct dpll_data *dd;
+	u32 v;
+	struct clk_hw_omap *pclk = NULL;
+
+	if (!*prate)
+		return 0;
+
+	pclk = omap3_find_clkoutx2_dpll(hw);
+
+	if (!pclk)
+		return 0;
+
+	dd = pclk->dpll_data;
+
+	/* TYPE J does not have a clkoutx2 */
+	if (dd->flags & DPLL_J_TYPE) {
+		*prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
+		return *prate;
+	}
+
+	WARN_ON(!dd->enable_mask);
+
+	v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+	v >>= __ffs(dd->enable_mask);
+
+	/* If in bypass, the rate is fixed to the bypass rate*/
+	if (v != OMAP3XXX_EN_DPLL_LOCKED)
+		return *prate;
+
+	if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent;
+
+		best_parent = (rate / 2);
+		*prate = __clk_round_rate(__clk_get_parent(hw->clk),
+				best_parent);
+	}
+
+	return *prate * 2;
+}
+
 /* OMAP3/4 non-CORE DPLL clkops */
 const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
 	.allow_idle	= omap3_dpll_allow_idle,
diff --git a/arch/arm/mach-omap2/include/mach/timex.h b/arch/arm/mach-omap2/include/mach/timex.h
deleted file mode 100644
index de9f8fc40e7c..000000000000
--- a/arch/arm/mach-omap2/include/mach/timex.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/timex.h
- */
-
-#include <plat/timex.h>
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 42d81885c700..1f33f5db10d5 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1947,29 +1947,31 @@ static int _ocp_softreset(struct omap_hwmod *oh)
 		goto dis_opt_clks;
 
 	_write_sysconfig(v, oh);
-	ret = _clear_softreset(oh, &v);
-	if (ret)
-		goto dis_opt_clks;
-
-	_write_sysconfig(v, oh);
 
 	if (oh->class->sysc->srst_udelay)
 		udelay(oh->class->sysc->srst_udelay);
 
 	c = _wait_softreset_complete(oh);
-	if (c == MAX_MODULE_SOFTRESET_WAIT)
+	if (c == MAX_MODULE_SOFTRESET_WAIT) {
 		pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
 			   oh->name, MAX_MODULE_SOFTRESET_WAIT);
-	else
+		ret = -ETIMEDOUT;
+		goto dis_opt_clks;
+	} else {
 		pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
+	}
+
+	ret = _clear_softreset(oh, &v);
+	if (ret)
+		goto dis_opt_clks;
+
+	_write_sysconfig(v, oh);
 
 	/*
 	 * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
 	 * _wait_target_ready() or _reset()
 	 */
 
-	ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
-
 dis_opt_clks:
 	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
 		_disable_optional_clocks(oh);
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 18f333c440db..810c205d668b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -1365,11 +1365,10 @@ static struct omap_hwmod_class_sysconfig dra7xx_spinlock_sysc = {
 	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   SIDLE_SMART_WKUP),
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 3d5b24dcd9a4..c33e07e2f0d4 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -22,6 +22,8 @@
 #include "common-board-devices.h"
 #include "dss-common.h"
 #include "control.h"
+#include "omap-secure.h"
+#include "soc.h"
 
 struct pdata_init {
 	const char *compatible;
@@ -169,6 +171,22 @@ static void __init am3517_evm_legacy_init(void)
 	omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
 	omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
 }
+
+static void __init nokia_n900_legacy_init(void)
+{
+	hsmmc2_internal_input_clk();
+
+	if (omap_type() == OMAP2_DEVICE_TYPE_SEC) {
+		if (IS_ENABLED(CONFIG_ARM_ERRATA_430973)) {
+			pr_info("RX-51: Enabling ARM errata 430973 workaround\n");
+			/* set IBE to 1 */
+			rx51_secure_update_aux_cr(BIT(6), 0);
+		} else {
+			pr_warning("RX-51: Not enabling ARM errata 430973 workaround\n");
+			pr_warning("Thumb binaries may crash randomly without this workaround\n");
+		}
+	}
+}
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #ifdef CONFIG_ARCH_OMAP4
@@ -239,6 +257,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 #endif
 #ifdef CONFIG_ARCH_OMAP3
 	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata),
+	OF_DEV_AUXDATA("ti,omap3-padconf", 0x480025a0, "480025a0.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata),
 	/* Only on am3517 */
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
@@ -259,7 +278,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
 	{ "compulab,omap3-sbc-t3730", omap3_sbc_t3730_legacy_init, },
-	{ "nokia,omap3-n900", hsmmc2_internal_input_clk, },
+	{ "nokia,omap3-n900", nokia_n900_legacy_init, },
 	{ "nokia,omap3-n9", hsmmc2_internal_input_clk, },
 	{ "nokia,omap3-n950", hsmmc2_internal_input_clk, },
 	{ "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index 6334b96b4097..280f3c58abe5 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -183,11 +183,11 @@ void omap4_prminst_global_warm_sw_reset(void)
 					OMAP4_PRM_RSTCTRL_OFFSET);
 	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
 	omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
-				 OMAP4430_PRM_DEVICE_INST,
+				 dev_inst,
 				 OMAP4_PRM_RSTCTRL_OFFSET);
 
 	/* OCP barrier */
 	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-				    OMAP4430_PRM_DEVICE_INST,
+				    dev_inst,
 				    OMAP4_PRM_RSTCTRL_OFFSET);
 }
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index f727d03f1688..5766e3fbff69 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -18,6 +18,7 @@
 #define CPU_CTRL		(ORION5X_BRIDGE_VIRT_BASE + 0x104)
 
 #define RSTOUTn_MASK		(ORION5X_BRIDGE_VIRT_BASE + 0x108)
+#define RSTOUTn_MASK_PHYS	(ORION5X_BRIDGE_PHYS_BASE + 0x108)
 
 #define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE + 0x10c)
 
diff --git a/arch/arm/mach-orion5x/include/mach/timex.h b/arch/arm/mach-orion5x/include/mach/timex.h
deleted file mode 100644
index 4c69820e0810..000000000000
--- a/arch/arm/mach-orion5x/include/mach/timex.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/timex.h
- *
- * Tzachi Perelstein <tzachi@marvell.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.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-picoxcell/Kconfig b/arch/arm/mach-picoxcell/Kconfig
index b1022f4315f7..62240f69b4ee 100644
--- a/arch/arm/mach-picoxcell/Kconfig
+++ b/arch/arm/mach-picoxcell/Kconfig
@@ -1,12 +1,7 @@
 config ARCH_PICOXCELL
 	bool "Picochip PicoXcell" if ARCH_MULTI_V6
 	select ARCH_REQUIRE_GPIOLIB
-	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
-	select CPU_V6K
 	select DW_APB_TIMER_OF
-	select GENERIC_CLOCKEVENTS
 	select HAVE_TCM
-	select NO_IOPORT
-	select SPARSE_IRQ
-	select USE_OF
+	select NO_IOPORT_MAP
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index 6988b117fc17..82482cd1fc03 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -1,10 +1,8 @@
 config ARCH_SIRF
 	bool "CSR SiRF" if ARCH_MULTI_V7
 	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select MIGHT_HAVE_CACHE_L2X0
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select PINCTRL
 	select PINCTRL_SIRF
 	help
@@ -17,7 +15,6 @@ menu "CSR SiRF atlas6/primaII/Marco/Polo Specific Features"
 config ARCH_ATLAS6
 	bool "CSR SiRFSoC ATLAS6 ARM Cortex A9 Platform"
 	default y
-	select CPU_V7
 	select SIRF_IRQ
 	help
           Support for CSR SiRFSoC ARM Cortex A9 Platform
@@ -25,7 +22,6 @@ config ARCH_ATLAS6
 config ARCH_PRIMA2
 	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
 	default y
-	select CPU_V7
 	select SIRF_IRQ
 	select ZONE_DMA
 	help
@@ -35,9 +31,7 @@ config ARCH_MARCO
 	bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
 	default y
 	select ARM_GIC
-	select CPU_V7
 	select HAVE_ARM_SCU if SMP
-	select HAVE_SMP
 	select SMP_ON_UP if SMP
 	help
           Support for CSR SiRFSoC ARM Cortex A9 Platform
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 96100dbf5a2e..b96244c73ea4 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -7,7 +7,6 @@ comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
-	select HAVE_PWM
 	select POWER_SUPPLY
 	select PXA3xx
 	select USE_OF
@@ -23,12 +22,10 @@ config ARCH_LUBBOCK
 
 config MACH_MAINSTONE
 	bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
-	select HAVE_PWM
 	select PXA27x
 
 config MACH_ZYLONITE
 	bool
-	select HAVE_PWM
 	select PXA3xx
 
 config MACH_ZYLONITE300
@@ -69,7 +66,6 @@ config ARCH_PXA_IDP
 config ARCH_VIPER
 	bool "Arcom/Eurotech VIPER SBC"
 	select ARCOM_PCMCIA
-	select HAVE_PWM
 	select I2C_GPIO
 	select ISA
 	select PXA25x
@@ -120,7 +116,6 @@ config MACH_CM_X300
 	bool "CompuLab CM-X300 modules"
 	select CPU_PXA300
 	select CPU_PXA310
-	select HAVE_PWM
 	select PXA3xx
 
 config MACH_CAPC7117
@@ -211,7 +206,6 @@ config TRIZEPS_PCMCIA
 
 config MACH_LOGICPD_PXA270
 	bool "LogicPD PXA270 Card Engine Development Platform"
-	select HAVE_PWM
 	select PXA27x
 
 config MACH_PCM027
@@ -222,7 +216,6 @@ config MACH_PCM027
 config MACH_PCM990_BASEBOARD
 	bool "PHYTEC PCM-990 development board"
 	depends on MACH_PCM027
-	select HAVE_PWM
 
 choice
 	prompt "display on pcm990"
@@ -246,7 +239,6 @@ config MACH_COLIBRI
 config MACH_COLIBRI_PXA270_INCOME
 	bool "Income s.r.o. PXA270 SBC"
 	depends on MACH_COLIBRI
-	select HAVE_PWM
 	select PXA27x
 
 config MACH_COLIBRI300
@@ -275,7 +267,6 @@ comment "End-user Products (sorted by vendor name)"
 
 config MACH_H4700
 	bool "HP iPAQ hx4700"
-	select HAVE_PWM
 	select IWMMXT
 	select PXA27x
 
@@ -289,14 +280,12 @@ config MACH_HIMALAYA
 
 config MACH_MAGICIAN
 	bool "Enable HTC Magician Support"
-	select HAVE_PWM
 	select IWMMXT
 	select PXA27x
 
 config MACH_MIOA701
 	bool "Mitac Mio A701 Support"
 	select GPIO_SYSFS
-	select HAVE_PWM
 	select IWMMXT
 	select PXA27x
 	help
@@ -306,7 +295,6 @@ config MACH_MIOA701
 
 config PXA_EZX
 	bool "Motorola EZX Platform"
-	select HAVE_PWM
 	select IWMMXT
 	select PXA27x
 
@@ -346,7 +334,6 @@ config MACH_MP900C
 
 config ARCH_PXA_PALM
 	bool "PXA based Palm PDAs"
-	select HAVE_PWM
 
 config MACH_PALM27X
 	bool
@@ -444,7 +431,6 @@ config MACH_TREO680
 config MACH_RAUMFELD_RC
 	bool "Raumfeld Controller"
 	select CPU_PXA300
-	select HAVE_PWM
 	select POWER_SUPPLY
 	select PXA3xx
 
@@ -608,7 +594,6 @@ config MACH_E800
 
 config MACH_ZIPIT2
 	bool "Zipit Z2 Handheld"
-	select HAVE_PWM
 	select PXA27x
 endmenu
 
diff --git a/arch/arm/mach-pxa/include/mach/timex.h b/arch/arm/mach-pxa/include/mach/timex.h
deleted file mode 100644
index af6760a50e1a..000000000000
--- a/arch/arm/mach-pxa/include/mach/timex.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-pxa/include/mach/timex.h
- *
- * Author:	Nicolas Pitre
- * Created:	Jun 15, 2001
- * Copyright:	MontaVista Software 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.
- */
-
-/* Various drivers are still using the constant of CLOCK_TICK_RATE, for
- * those drivers to at least work, the definition is provided here.
- *
- * NOTE: this is no longer accurate when multiple processors and boards
- * are selected, newer drivers should not depend on this any more.  Use
- * either the clocksource/clockevent or get this at run-time by calling
- * get_clock_tick_rate() (as defined in generic.c).
- */
-
-#if defined(CONFIG_PXA25x)
-/* PXA250/210 timer base */
-#define CLOCK_TICK_RATE 3686400
-#elif defined(CONFIG_PXA27x)
-/* PXA27x timer base */
-#ifdef CONFIG_MACH_MAINSTONE
-#define CLOCK_TICK_RATE 3249600
-#else
-#define CLOCK_TICK_RATE 3250000
-#endif
-#else
-#define CLOCK_TICK_RATE 3250000
-#endif
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
new file mode 100644
index 000000000000..a028be234334
--- /dev/null
+++ b/arch/arm/mach-qcom/Kconfig
@@ -0,0 +1,33 @@
+config ARCH_QCOM
+	bool "Qualcomm Support" if ARCH_MULTI_V7
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_GIC
+	select CLKSRC_OF
+	select GENERIC_CLOCKEVENTS
+	select HAVE_SMP
+	select QCOM_SCM if SMP
+	help
+	  Support for Qualcomm's devicetree based systems.
+
+if ARCH_QCOM
+
+menu "Qualcomm SoC Selection"
+
+config ARCH_MSM8X60
+	bool "Enable support for MSM8X60"
+	select CLKSRC_QCOM
+
+config ARCH_MSM8960
+	bool "Enable support for MSM8960"
+	select CLKSRC_QCOM
+
+config ARCH_MSM8974
+	bool "Enable support for MSM8974"
+	select HAVE_ARM_ARCH_TIMER
+
+endmenu
+
+config QCOM_SCM
+	bool
+
+endif
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
new file mode 100644
index 000000000000..8f756ae1ae31
--- /dev/null
+++ b/arch/arm/mach-qcom/Makefile
@@ -0,0 +1,5 @@
+obj-y			:= board.o
+obj-$(CONFIG_SMP)	+= platsmp.o
+obj-$(CONFIG_QCOM_SCM)	+= scm.o scm-boot.o
+
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
diff --git a/arch/arm/mach-qcom/board.c b/arch/arm/mach-qcom/board.c
new file mode 100644
index 000000000000..bae617ef0b31
--- /dev/null
+++ b/arch/arm/mach-qcom/board.c
@@ -0,0 +1,26 @@
+/* Copyright (c) 2010-2014 The Linux Foundation. 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 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/init.h>
+
+#include <asm/mach/arch.h>
+
+static const char * const qcom_dt_match[] __initconst = {
+	"qcom,msm8660-surf",
+	"qcom,msm8960-cdp",
+	"qcom,apq8074-dragonboard",
+	NULL
+};
+
+DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
+	.dt_compat = qcom_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
new file mode 100644
index 000000000000..d6908569ecaf
--- /dev/null
+++ b/arch/arm/mach-qcom/platsmp.c
@@ -0,0 +1,378 @@
+/*
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *  Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2014 The Linux Foundation. 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/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_plat.h>
+
+#include "scm-boot.h"
+
+#define VDD_SC1_ARRAY_CLAMP_GFS_CTL	0x35a0
+#define SCSS_CPU1CORE_RESET		0x2d80
+#define SCSS_DBG_STATUS_CORE_PWRDUP	0x2e64
+
+#define APCS_CPU_PWR_CTL	0x04
+#define PLL_CLAMP		BIT(8)
+#define CORE_PWRD_UP		BIT(7)
+#define COREPOR_RST		BIT(5)
+#define CORE_RST		BIT(4)
+#define L2DT_SLP		BIT(3)
+#define CLAMP			BIT(0)
+
+#define APC_PWR_GATE_CTL	0x14
+#define BHS_CNT_SHIFT		24
+#define LDO_PWR_DWN_SHIFT	16
+#define LDO_BYP_SHIFT		8
+#define BHS_SEG_SHIFT		1
+#define BHS_EN			BIT(0)
+
+#define APCS_SAW2_VCTL		0x14
+#define APCS_SAW2_2_VCTL	0x1c
+
+extern void secondary_startup(void);
+
+static DEFINE_SPINLOCK(boot_lock);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void __ref qcom_cpu_die(unsigned int cpu)
+{
+	wfi();
+}
+#endif
+
+static void qcom_secondary_init(unsigned int cpu)
+{
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+static int scss_release_secondary(unsigned int cpu)
+{
+	struct device_node *node;
+	void __iomem *base;
+
+	node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660");
+	if (!node) {
+		pr_err("%s: can't find node\n", __func__);
+		return -ENXIO;
+	}
+
+	base = of_iomap(node, 0);
+	of_node_put(node);
+	if (!base)
+		return -ENOMEM;
+
+	writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
+	writel_relaxed(0, base + SCSS_CPU1CORE_RESET);
+	writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP);
+	mb();
+	iounmap(base);
+
+	return 0;
+}
+
+static int kpssv1_release_secondary(unsigned int cpu)
+{
+	int ret = 0;
+	void __iomem *reg, *saw_reg;
+	struct device_node *cpu_node, *acc_node, *saw_node;
+	u32 val;
+
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		return -ENODEV;
+
+	acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
+	if (!acc_node) {
+		ret = -ENODEV;
+		goto out_acc;
+	}
+
+	saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
+	if (!saw_node) {
+		ret = -ENODEV;
+		goto out_saw;
+	}
+
+	reg = of_iomap(acc_node, 0);
+	if (!reg) {
+		ret = -ENOMEM;
+		goto out_acc_map;
+	}
+
+	saw_reg = of_iomap(saw_node, 0);
+	if (!saw_reg) {
+		ret = -ENOMEM;
+		goto out_saw_map;
+	}
+
+	/* Turn on CPU rail */
+	writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL);
+	mb();
+	udelay(512);
+
+	/* Krait bring-up sequence */
+	val = PLL_CLAMP | L2DT_SLP | CLAMP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	val &= ~L2DT_SLP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	ndelay(300);
+
+	val |= COREPOR_RST;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	val &= ~CLAMP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	val &= ~COREPOR_RST;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(100);
+
+	val |= CORE_PWRD_UP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+
+	iounmap(saw_reg);
+out_saw_map:
+	iounmap(reg);
+out_acc_map:
+	of_node_put(saw_node);
+out_saw:
+	of_node_put(acc_node);
+out_acc:
+	of_node_put(cpu_node);
+	return ret;
+}
+
+static int kpssv2_release_secondary(unsigned int cpu)
+{
+	void __iomem *reg;
+	struct device_node *cpu_node, *l2_node, *acc_node, *saw_node;
+	void __iomem *l2_saw_base;
+	unsigned reg_val;
+	int ret;
+
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		return -ENODEV;
+
+	acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
+	if (!acc_node) {
+		ret = -ENODEV;
+		goto out_acc;
+	}
+
+	l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
+	if (!l2_node) {
+		ret = -ENODEV;
+		goto out_l2;
+	}
+
+	saw_node = of_parse_phandle(l2_node, "qcom,saw", 0);
+	if (!saw_node) {
+		ret = -ENODEV;
+		goto out_saw;
+	}
+
+	reg = of_iomap(acc_node, 0);
+	if (!reg) {
+		ret = -ENOMEM;
+		goto out_map;
+	}
+
+	l2_saw_base = of_iomap(saw_node, 0);
+	if (!l2_saw_base) {
+		ret = -ENOMEM;
+		goto out_saw_map;
+	}
+
+	/* Turn on the BHS, turn off LDO Bypass and power down LDO */
+	reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN;
+	writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
+	mb();
+	/* wait for the BHS to settle */
+	udelay(1);
+
+	/* Turn on BHS segments */
+	reg_val |= 0x3f << BHS_SEG_SHIFT;
+	writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
+	mb();
+	 /* wait for the BHS to settle */
+	udelay(1);
+
+	/* Finally turn on the bypass so that BHS supplies power */
+	reg_val |= 0x3f << LDO_BYP_SHIFT;
+	writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
+
+	/* enable max phases */
+	writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL);
+	mb();
+	udelay(50);
+
+	reg_val = COREPOR_RST | CLAMP;
+	writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	reg_val &= ~CLAMP;
+	writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	reg_val &= ~COREPOR_RST;
+	writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
+	mb();
+
+	reg_val |= CORE_PWRD_UP;
+	writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
+	mb();
+
+	ret = 0;
+
+	iounmap(l2_saw_base);
+out_saw_map:
+	iounmap(reg);
+out_map:
+	of_node_put(saw_node);
+out_saw:
+	of_node_put(l2_node);
+out_l2:
+	of_node_put(acc_node);
+out_acc:
+	of_node_put(cpu_node);
+
+	return ret;
+}
+
+static DEFINE_PER_CPU(int, cold_boot_done);
+
+static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
+{
+	int ret = 0;
+
+	if (!per_cpu(cold_boot_done, cpu)) {
+		ret = func(cpu);
+		if (!ret)
+			per_cpu(cold_boot_done, cpu) = true;
+	}
+
+	/*
+	 * set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return ret;
+}
+
+static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	return qcom_boot_secondary(cpu, scss_release_secondary);
+}
+
+static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	return qcom_boot_secondary(cpu, kpssv1_release_secondary);
+}
+
+static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	return qcom_boot_secondary(cpu, kpssv2_release_secondary);
+}
+
+static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int cpu, map;
+	unsigned int flags = 0;
+	static const int cold_boot_flags[] = {
+		0,
+		SCM_FLAG_COLDBOOT_CPU1,
+		SCM_FLAG_COLDBOOT_CPU2,
+		SCM_FLAG_COLDBOOT_CPU3,
+	};
+
+	for_each_present_cpu(cpu) {
+		map = cpu_logical_map(cpu);
+		if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
+			set_cpu_present(cpu, false);
+			continue;
+		}
+		flags |= cold_boot_flags[map];
+	}
+
+	if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) {
+		for_each_present_cpu(cpu) {
+			if (cpu == smp_processor_id())
+				continue;
+			set_cpu_present(cpu, false);
+		}
+		pr_warn("Failed to set CPU boot address, disabling SMP\n");
+	}
+}
+
+static struct smp_operations smp_msm8660_ops __initdata = {
+	.smp_prepare_cpus	= qcom_smp_prepare_cpus,
+	.smp_secondary_init	= qcom_secondary_init,
+	.smp_boot_secondary	= msm8660_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= qcom_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops);
+
+static struct smp_operations qcom_smp_kpssv1_ops __initdata = {
+	.smp_prepare_cpus	= qcom_smp_prepare_cpus,
+	.smp_secondary_init	= qcom_secondary_init,
+	.smp_boot_secondary	= kpssv1_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= qcom_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops);
+
+static struct smp_operations qcom_smp_kpssv2_ops __initdata = {
+	.smp_prepare_cpus	= qcom_smp_prepare_cpus,
+	.smp_secondary_init	= qcom_secondary_init,
+	.smp_boot_secondary	= kpssv2_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= qcom_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops);
diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c
new file mode 100644
index 000000000000..45cee3e469a5
--- /dev/null
+++ b/arch/arm/mach-qcom/scm-boot.c
@@ -0,0 +1,39 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 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.
+ *
+ * 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/module.h>
+#include <linux/slab.h>
+
+#include "scm.h"
+#include "scm-boot.h"
+
+/*
+ * Set the cold/warm boot address for one of the CPU cores.
+ */
+int scm_set_boot_addr(phys_addr_t addr, int flags)
+{
+	struct {
+		unsigned int flags;
+		phys_addr_t  addr;
+	} cmd;
+
+	cmd.addr = addr;
+	cmd.flags = flags;
+	return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
+			&cmd, sizeof(cmd), NULL, 0);
+}
+EXPORT_SYMBOL(scm_set_boot_addr);
diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h
new file mode 100644
index 000000000000..6aabb2428176
--- /dev/null
+++ b/arch/arm/mach-qcom/scm-boot.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 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.
+ */
+#ifndef __MACH_SCM_BOOT_H
+#define __MACH_SCM_BOOT_H
+
+#define SCM_BOOT_ADDR			0x1
+#define SCM_FLAG_COLDBOOT_CPU1		0x01
+#define SCM_FLAG_COLDBOOT_CPU2		0x08
+#define SCM_FLAG_COLDBOOT_CPU3		0x20
+#define SCM_FLAG_WARMBOOT_CPU0		0x04
+#define SCM_FLAG_WARMBOOT_CPU1		0x02
+
+int scm_set_boot_addr(phys_addr_t addr, int flags);
+
+#endif
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
new file mode 100644
index 000000000000..c536fd6bf827
--- /dev/null
+++ b/arch/arm/mach-qcom/scm.c
@@ -0,0 +1,299 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 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.
+ *
+ * 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/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/cacheflush.h>
+
+#include "scm.h"
+
+/* Cache line size for msm8x60 */
+#define CACHELINESIZE 32
+
+#define SCM_ENOMEM		-5
+#define SCM_EOPNOTSUPP		-4
+#define SCM_EINVAL_ADDR		-3
+#define SCM_EINVAL_ARG		-2
+#define SCM_ERROR		-1
+#define SCM_INTERRUPTED		1
+
+static DEFINE_MUTEX(scm_lock);
+
+/**
+ * struct scm_command - one SCM command buffer
+ * @len: total available memory for command and response
+ * @buf_offset: start of command buffer
+ * @resp_hdr_offset: start of response buffer
+ * @id: command to be executed
+ * @buf: buffer returned from scm_get_command_buffer()
+ *
+ * An SCM command is laid out in memory as follows:
+ *
+ *	------------------- <--- struct scm_command
+ *	| command header  |
+ *	------------------- <--- scm_get_command_buffer()
+ *	| command buffer  |
+ *	------------------- <--- struct scm_response and
+ *	| response header |      scm_command_to_response()
+ *	------------------- <--- scm_get_response_buffer()
+ *	| response buffer |
+ *	-------------------
+ *
+ * There can be arbitrary padding between the headers and buffers so
+ * you should always use the appropriate scm_get_*_buffer() routines
+ * to access the buffers in a safe manner.
+ */
+struct scm_command {
+	u32	len;
+	u32	buf_offset;
+	u32	resp_hdr_offset;
+	u32	id;
+	u32	buf[0];
+};
+
+/**
+ * struct scm_response - one SCM response buffer
+ * @len: total available memory for response
+ * @buf_offset: start of response data relative to start of scm_response
+ * @is_complete: indicates if the command has finished processing
+ */
+struct scm_response {
+	u32	len;
+	u32	buf_offset;
+	u32	is_complete;
+};
+
+/**
+ * alloc_scm_command() - Allocate an SCM command
+ * @cmd_size: size of the command buffer
+ * @resp_size: size of the response buffer
+ *
+ * Allocate an SCM command, including enough room for the command
+ * and response headers as well as the command and response buffers.
+ *
+ * Returns a valid &scm_command on success or %NULL if the allocation fails.
+ */
+static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
+{
+	struct scm_command *cmd;
+	size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
+		resp_size;
+
+	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
+	if (cmd) {
+		cmd->len = len;
+		cmd->buf_offset = offsetof(struct scm_command, buf);
+		cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
+	}
+	return cmd;
+}
+
+/**
+ * free_scm_command() - Free an SCM command
+ * @cmd: command to free
+ *
+ * Free an SCM command.
+ */
+static inline void free_scm_command(struct scm_command *cmd)
+{
+	kfree(cmd);
+}
+
+/**
+ * scm_command_to_response() - Get a pointer to a scm_response
+ * @cmd: command
+ *
+ * Returns a pointer to a response for a command.
+ */
+static inline struct scm_response *scm_command_to_response(
+		const struct scm_command *cmd)
+{
+	return (void *)cmd + cmd->resp_hdr_offset;
+}
+
+/**
+ * scm_get_command_buffer() - Get a pointer to a command buffer
+ * @cmd: command
+ *
+ * Returns a pointer to the command buffer of a command.
+ */
+static inline void *scm_get_command_buffer(const struct scm_command *cmd)
+{
+	return (void *)cmd->buf;
+}
+
+/**
+ * scm_get_response_buffer() - Get a pointer to a response buffer
+ * @rsp: response
+ *
+ * Returns a pointer to a response buffer of a response.
+ */
+static inline void *scm_get_response_buffer(const struct scm_response *rsp)
+{
+	return (void *)rsp + rsp->buf_offset;
+}
+
+static int scm_remap_error(int err)
+{
+	switch (err) {
+	case SCM_ERROR:
+		return -EIO;
+	case SCM_EINVAL_ADDR:
+	case SCM_EINVAL_ARG:
+		return -EINVAL;
+	case SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case SCM_ENOMEM:
+		return -ENOMEM;
+	}
+	return -EINVAL;
+}
+
+static u32 smc(u32 cmd_addr)
+{
+	int context_id;
+	register u32 r0 asm("r0") = 1;
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = cmd_addr;
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2)
+			: "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
+	return r0;
+}
+
+static int __scm_call(const struct scm_command *cmd)
+{
+	int ret;
+	u32 cmd_addr = virt_to_phys(cmd);
+
+	/*
+	 * Flush the entire cache here so callers don't have to remember
+	 * to flush the cache when passing physical addresses to the secure
+	 * side in the buffer.
+	 */
+	flush_cache_all();
+	ret = smc(cmd_addr);
+	if (ret < 0)
+		ret = scm_remap_error(ret);
+
+	return ret;
+}
+
+/**
+ * scm_call() - Send an SCM command
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @cmd_buf: command buffer
+ * @cmd_len: length of the command buffer
+ * @resp_buf: response buffer
+ * @resp_len: length of the response buffer
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ */
+int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len)
+{
+	int ret;
+	struct scm_command *cmd;
+	struct scm_response *rsp;
+
+	cmd = alloc_scm_command(cmd_len, resp_len);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->id = (svc_id << 10) | cmd_id;
+	if (cmd_buf)
+		memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
+
+	mutex_lock(&scm_lock);
+	ret = __scm_call(cmd);
+	mutex_unlock(&scm_lock);
+	if (ret)
+		goto out;
+
+	rsp = scm_command_to_response(cmd);
+	do {
+		u32 start = (u32)rsp;
+		u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
+		start &= ~(CACHELINESIZE - 1);
+		while (start < end) {
+			asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+			     : "memory");
+			start += CACHELINESIZE;
+		}
+	} while (!rsp->is_complete);
+
+	if (resp_buf)
+		memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
+out:
+	free_scm_command(cmd);
+	return ret;
+}
+EXPORT_SYMBOL(scm_call);
+
+u32 scm_get_version(void)
+{
+	int context_id;
+	static u32 version = -1;
+	register u32 r0 asm("r0");
+	register u32 r1 asm("r1");
+
+	if (version != -1)
+		return version;
+
+	mutex_lock(&scm_lock);
+
+	r0 = 0x1 << 8;
+	r1 = (u32)&context_id;
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r1")
+			__asmeq("%2", "r0")
+			__asmeq("%3", "r1")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0), "=r" (r1)
+			: "r" (r0), "r" (r1)
+			: "r2", "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
+	version = r1;
+	mutex_unlock(&scm_lock);
+
+	return version;
+}
+EXPORT_SYMBOL(scm_get_version);
diff --git a/arch/arm/mach-qcom/scm.h b/arch/arm/mach-qcom/scm.h
new file mode 100644
index 000000000000..00b31ea58f29
--- /dev/null
+++ b/arch/arm/mach-qcom/scm.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 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.
+ */
+#ifndef __MACH_SCM_H
+#define __MACH_SCM_H
+
+#define SCM_SVC_BOOT			0x1
+#define SCM_SVC_PIL			0x2
+
+extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len);
+
+#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
+
+extern u32 scm_get_version(void);
+
+#endif
diff --git a/arch/arm/mach-realview/include/mach/timex.h b/arch/arm/mach-realview/include/mach/timex.h
deleted file mode 100644
index 4eeb069373c2..000000000000
--- a/arch/arm/mach-realview/include/mach/timex.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  arch/arm/mach-realview/include/mach/timex.h
- *
- *  RealView architecture timex specifications
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute 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
- */
-
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index cf073dea5784..6b2f58645a73 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -6,9 +6,6 @@ config ARCH_ROCKCHIP
 	select ARM_GIC
 	select CACHE_L2X0
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 	select DW_APB_TIMER_OF
 	select ARM_GLOBAL_TIMER
 	select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
diff --git a/arch/arm/mach-rpc/include/mach/timex.h b/arch/arm/mach-rpc/include/mach/timex.h
deleted file mode 100644
index dd75e7387bbe..000000000000
--- a/arch/arm/mach-rpc/include/mach/timex.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- *  arch/arm/mach-rpc/include/mach/timex.h
- *
- *  Copyright (C) 1997, 1998 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.
- *
- *  RiscPC architecture timex specifications
- */
-
-/*
- * On the RiscPC, the clock ticks at 2MHz.
- */
-#define CLOCK_TICK_RATE		2000000
-
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 9a6def14df01..99363ae5cac7 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -24,6 +24,9 @@
 
 #include <asm/mach/time.h>
 
+#define RPC_CLOCK_FREQ 2000000
+#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
+
 static u32 ioc_timer_gettimeoffset(void)
 {
 	unsigned int count1, count2, status;
@@ -46,23 +49,23 @@ static u32 ioc_timer_gettimeoffset(void)
 		 * and count2.
 		 */
 		if (status & (1 << 5))
-			offset -= LATCH;
+			offset -= RPC_LATCH;
 	} else if (count2 > count1) {
 		/*
 		 * We have just had another interrupt between reading
 		 * count1 and count2.
 		 */
-		offset -= LATCH;
+		offset -= RPC_LATCH;
 	}
 
-	offset = (LATCH - offset) * (tick_nsec / 1000);
-	return ((offset + LATCH/2) / LATCH) * 1000;
+	offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
+	return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
 }
 
 void __init ioctime_init(void)
 {
-	ioc_writeb(LATCH & 255, IOC_T0LTCHL);
-	ioc_writeb(LATCH >> 8, IOC_T0LTCHH);
+	ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
+	ioc_writeb(RPC_LATCH >> 8, IOC_T0LTCHH);
 	ioc_writeb(0, IOC_T0GO);
 }
 
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index d876431d64c0..008b299ef9de 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -12,7 +12,7 @@ if ARCH_S3C24XX
 config PLAT_S3C24XX
 	def_bool y
 	select ARCH_REQUIRE_GPIOLIB
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select S3C_DEV_NAND
 	select IRQ_DOMAIN
 	help
@@ -25,6 +25,7 @@ comment "S3C24XX SoCs"
 config CPU_S3C2410
 	bool "SAMSUNG S3C2410"
 	default y
+	depends on SAMSUNG_CLOCK
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2410
 	select S3C2410_CLOCK
@@ -38,8 +39,10 @@ config CPU_S3C2410
 
 config CPU_S3C2412
 	bool "SAMSUNG S3C2412"
+	select COMMON_CLK
 	select CPU_ARM926T
 	select CPU_LLSERIAL_S3C2440
+	select S3C2412_COMMON_CLK
 	select S3C2412_DMA if S3C24XX_DMA
 	select S3C2412_PM if PM
 	help
@@ -47,17 +50,18 @@ config CPU_S3C2412
 
 config CPU_S3C2416
 	bool "SAMSUNG S3C2416/S3C2450"
+	select COMMON_CLK
 	select CPU_ARM926T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2416_PM if PM
-	select S3C2443_COMMON
+	select S3C2443_COMMON_CLK
 	select S3C2443_DMA if S3C24XX_DMA
-	select SAMSUNG_CLKSRC
 	help
 	  Support for the S3C2416 SoC from the S3C24XX line
 
 config CPU_S3C2440
 	bool "SAMSUNG S3C2440"
+	depends on SAMSUNG_CLOCK
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2410_CLOCK
@@ -68,6 +72,7 @@ config CPU_S3C2440
 
 config CPU_S3C2442
 	bool "SAMSUNG S3C2442"
+	depends on SAMSUNG_CLOCK
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2410_CLOCK
@@ -83,11 +88,11 @@ config CPU_S3C244X
 
 config CPU_S3C2443
 	bool "SAMSUNG S3C2443"
+	select COMMON_CLK
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2440
-	select S3C2443_COMMON
+	select S3C2443_COMMON_CLK
 	select S3C2443_DMA if S3C24XX_DMA
-	select SAMSUNG_CLKSRC
 	help
 	  Support for the S3C2443 SoC from the S3C24XX line
 
@@ -359,6 +364,11 @@ config S3C2412_PM_SLEEP
 
 if CPU_S3C2412
 
+config S3C2412_COMMON_CLK
+	bool
+	help
+	  Build the s3c2412 clock driver based on the common clock framework.
+
 config CPU_S3C2412_ONLY
 	bool
 	depends on !CPU_S3C2410 && !CPU_S3C2416 && !CPU_S3C2440 && \
@@ -521,7 +531,6 @@ config MACH_ANUBIS
 	select HAVE_PATA_PLATFORM
 	select S3C2440_XTAL_12000000
 	select S3C24XX_DCLK
-	select S3C24XX_GPIO_EXTRA64
 	select S3C24XX_SIMTEC_PM if PM
 	select S3C_DEV_USB_HOST
 	help
@@ -562,7 +571,6 @@ config MACH_OSIRIS
 	select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ
 	select S3C2440_XTAL_12000000
 	select S3C24XX_DCLK
-	select S3C24XX_GPIO_EXTRA128
 	select S3C24XX_SIMTEC_PM if PM
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
@@ -643,11 +651,11 @@ endif	# CPU_S3C2442
 
 if CPU_S3C2443 || CPU_S3C2416
 
-config S3C2443_COMMON
+config S3C2443_COMMON_CLK
 	bool
 	help
-	  Common code for the S3C2443 and similar processors, which includes
-	  the S3C2416 and S3C2450.
+	  Temporary symbol to build the clock driver based on the common clock
+	  framework.
 
 config S3C2443_DMA
 	bool
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 7f54e5b954ca..f25479721dc9 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -21,12 +21,12 @@ obj-$(CONFIG_S3C2410_DMA)	+= dma-s3c2410.o
 obj-$(CONFIG_S3C2410_PLL)	+= pll-s3c2410.o
 obj-$(CONFIG_S3C2410_PM)	+= pm-s3c2410.o sleep-s3c2410.o
 
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o clock-s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma-s3c2412.o
 obj-$(CONFIG_S3C2412_PM)	+= pm-s3c2412.o
 obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep-s3c2412.o
 
-obj-$(CONFIG_CPU_S3C2416)	+= s3c2416.o clock-s3c2416.o
+obj-$(CONFIG_CPU_S3C2416)	+= s3c2416.o
 obj-$(CONFIG_S3C2416_PM)	+= pm-s3c2416.o
 
 obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o clock-s3c2440.o
@@ -36,7 +36,7 @@ obj-$(CONFIG_S3C2440_DMA)	+= dma-s3c2440.o
 obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
 obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o
 
-obj-$(CONFIG_CPU_S3C2443)	+= s3c2443.o clock-s3c2443.o
+obj-$(CONFIG_CPU_S3C2443)	+= s3c2443.o
 
 # PM
 
@@ -53,7 +53,6 @@ obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o
 obj-$(CONFIG_S3C2410_IOTIMING)	+= iotiming-s3c2410.o
 obj-$(CONFIG_S3C2412_IOTIMING)	+= iotiming-s3c2412.o
 
-obj-$(CONFIG_S3C2443_COMMON)	+= common-s3c2443.o
 obj-$(CONFIG_S3C2443_DMA)	+= dma-s3c2443.o
 
 #
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2410.c b/arch/arm/mach-s3c24xx/clock-s3c2410.c
index d39d3c787580..d1afcf9252d1 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2410.c
@@ -30,13 +30,12 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2412.c b/arch/arm/mach-s3c24xx/clock-s3c2412.c
deleted file mode 100644
index 11b3b28457bb..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c2412.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2412,S3C2413 Clock control 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/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-/* We currently have to assume that the system is running
- * from the XTPll input, and that all ***REFCLKs are being
- * fed from it, as we cannot read the state of OM[4] from
- * software.
- *
- * It would be possible for each board initialisation to
- * set the correct muxing at initialisation
-*/
-
-static int s3c2412_clkcon_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-
-	return 0;
-}
-
-static int s3c2412_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
-	unsigned long orig = upllcon;
-
-	if (!enable)
-		upllcon |= S3C2412_PLLCON_OFF;
-	else
-		upllcon &= ~S3C2412_PLLCON_OFF;
-
-	__raw_writel(upllcon, S3C2410_UPLLCON);
-
-	/* allow ~150uS for the PLL to settle and lock */
-
-	if (enable && (orig & S3C2412_PLLCON_OFF))
-		udelay(150);
-
-	return 0;
-}
-
-/* clock selections */
-
-static struct clk clk_erefclk = {
-	.name		= "erefclk",
-};
-
-static struct clk clk_urefclk = {
-	.name		= "urefclk",
-};
-
-static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_urefclk)
-		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
-	else if (parent == &clk_upll)
-		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static struct clk clk_usysclk = {
-	.name		= "usysclk",
-	.parent		= &clk_xtal,
-	.ops		= &(struct clk_ops) {
-		.set_parent	= s3c2412_setparent_usysclk,
-	},
-};
-
-static struct clk clk_mrefclk = {
-	.name		= "mrefclk",
-	.parent		= &clk_xtal,
-};
-
-static struct clk clk_mdivclk = {
-	.name		= "mdivclk",
-	.parent		= &clk_xtal,
-};
-
-static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_usysclk)
-		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
-	else if (parent == &clk_h)
-		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	div = parent_rate / rate;
-	if (div > 2)
-		div = 2;
-
-	return parent_rate / div;
-}
-
-static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
-}
-
-static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_usbsrc(clk, rate);
-
-	if ((parent_rate / rate) == 2)
-		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
-	else
-		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_usbsrc = {
-	.name		= "usbsrc",
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2412_getrate_usbsrc,
-		.set_rate	= s3c2412_setrate_usbsrc,
-		.round_rate	= s3c2412_roundrate_usbsrc,
-		.set_parent	= s3c2412_setparent_usbsrc,
-	},
-};
-
-static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_mdivclk)
-		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
-	else if (parent == &clk_mpll)
-		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static struct clk clk_msysclk = {
-	.name		= "msysclk",
-	.ops		= &(struct clk_ops) {
-		.set_parent	= s3c2412_setparent_msysclk,
-	},
-};
-
-static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long flags;
-	unsigned long clkdiv;
-	unsigned long dvs;
-
-	/* Note, we current equate fclk andf msysclk for S3C2412 */
-
-	if (parent == &clk_msysclk || parent == &clk_f)
-		dvs = 0;
-	else if (parent == &clk_h)
-		dvs = S3C2412_CLKDIVN_DVSEN;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	/* update this under irq lockdown, clkdivn is not protected
-	 * by the clock system. */
-
-	local_irq_save(flags);
-
-	clkdiv  = __raw_readl(S3C2410_CLKDIVN);
-	clkdiv &= ~S3C2412_CLKDIVN_DVSEN;
-	clkdiv |= dvs;
-	__raw_writel(clkdiv, S3C2410_CLKDIVN);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static struct clk clk_armclk = {
-	.name		= "armclk",
-	.parent		= &clk_msysclk,
-	.ops		= &(struct clk_ops) {
-		.set_parent	= s3c2412_setparent_armclk,
-	},
-};
-
-/* these next clocks have an divider immediately after them,
- * so we can register them with their divider and leave out the
- * intermediate clock stage
-*/
-static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	/* note, we remove the +/- 1 calculations as they cancel out */
-
-	div = (rate / parent_rate);
-
-	if (div < 1)
-		div = 1;
-	else if (div > 16)
-		div = 16;
-
-	return parent_rate / div;
-}
-
-static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_erefclk)
-		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
-	else if (parent == &clk_mpll)
-		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_getrate_uart(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
-	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_uart = {
-	.name		= "uartclk",
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2412_getrate_uart,
-		.set_rate	= s3c2412_setrate_uart,
-		.set_parent	= s3c2412_setparent_uart,
-		.round_rate	= s3c2412_roundrate_clksrc,
-	},
-};
-
-static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_erefclk)
-		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
-	else if (parent == &clk_mpll)
-		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_getrate_i2s(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
-	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_i2s = {
-	.name		= "i2sclk",
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2412_getrate_i2s,
-		.set_rate	= s3c2412_setrate_i2s,
-		.set_parent	= s3c2412_setparent_i2s,
-		.round_rate	= s3c2412_roundrate_clksrc,
-	},
-};
-
-static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_usysclk)
-		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
-	else if (parent == &clk_h)
-		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-static unsigned long s3c2412_getrate_cam(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
-	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_cam = {
-	.name		= "camif-upll",	/* same as 2440 name */
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2412_getrate_cam,
-		.set_rate	= s3c2412_setrate_cam,
-		.set_parent	= s3c2412_setparent_cam,
-		.round_rate	= s3c2412_roundrate_clksrc,
-	},
-};
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_NAND,
-	}, {
-		.name		= "sdi",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_SDI,
-	}, {
-		.name		= "adc",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_SPI,
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "dma.0",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA0,
-	}, {
-		.name		= "dma.1",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA1,
-	}, {
-		.name		= "dma.2",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA2,
-	}, {
-		.name		= "dma.3",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA3,
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_LCDC,
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_GPIO,
-	}, {
-		.name		= "usb-host",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_PWMT,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2412-uart.0",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2412-uart.1",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2412-uart.2",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART2,
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_RTC,
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}, {
-		.name		= "usb-bus-gadget",
-		.parent		= &clk_usb_bus,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
-	}, {
-		.name		= "usb-bus-host",
-		.parent		= &clk_usb_bus,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
-	}
-};
-
-/* clocks to add where we need to check their parentage */
-
-struct clk_init {
-	struct clk	*clk;
-	unsigned int	 bit;
-	struct clk	*src_0;
-	struct clk	*src_1;
-};
-
-static struct clk_init clks_src[] __initdata = {
-	{
-		.clk	= &clk_usysclk,
-		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
-		.src_0	= &clk_urefclk,
-		.src_1	= &clk_upll,
-	}, {
-		.clk	= &clk_i2s,
-		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
-		.src_0	= &clk_erefclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_cam,
-		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
-		.src_0	= &clk_usysclk,
-		.src_1	= &clk_h,
-	}, {
-		.clk	= &clk_msysclk,
-		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
-		.src_0	= &clk_mdivclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_uart,
-		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
-		.src_0	= &clk_erefclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_usbsrc,
-		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
-		.src_0	= &clk_usysclk,
-		.src_1	= &clk_h,
-	/* here we assume  OM[4] select xtal */
-	}, {
-		.clk	= &clk_erefclk,
-		.bit	= S3C2412_CLKSRC_EREFCLK_EXTCLK,
-		.src_0	= &clk_xtal,
-		.src_1	= &clk_ext,
-	}, {
-		.clk	= &clk_urefclk,
-		.bit	= S3C2412_CLKSRC_UREFCLK_EXTCLK,
-		.src_0	= &clk_xtal,
-		.src_1	= &clk_ext,
-	},
-};
-
-/* s3c2412_clk_initparents
- *
- * Initialise the parents for the clocks that we get at start-time
-*/
-
-static void __init s3c2412_clk_initparents(void)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-	struct clk_init *cip = clks_src;
-	struct clk *src;
-	int ptr;
-	int ret;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
-		ret = s3c24xx_register_clock(cip->clk);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       cip->clk->name, ret);
-		}
-
-		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
-
-		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
-		clk_set_parent(cip->clk, src);
-	}
-}
-
-/* clocks to add straight away */
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_usb_bus,
-	&clk_mrefclk,
-	&clk_armclk,
-};
-
-static struct clk_lookup s3c2412_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk),
-};
-
-int __init s3c2412_baseclk_add(void)
-{
-	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-	unsigned int dvs;
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
-	clk_upll.enable = s3c2412_upll_enable;
-	clk_usb_bus.parent = &clk_usbsrc;
-	clk_usb_bus.rate = 0x0;
-
-	clk_f.parent = &clk_msysclk;
-
-	s3c2412_clk_initparents();
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
-		clkp = clks[ptr];
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* set the dvs state according to what we got at boot time */
-
-	dvs = __raw_readl(S3C2410_CLKDIVN) & S3C2412_CLKDIVN_DVSEN;
-
-	if (dvs)
-		clk_armclk.parent = &clk_h;
-
-	printk(KERN_INFO "S3C2412: DVS is %s\n", dvs ? "on" : "off");
-
-	/* ensure usb bus clock is within correct rate of 48MHz */
-
-	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
-		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
-
-		/* for the moment, let's use the UPLL, and see if we can
-		 * get 48MHz */
-
-		clk_set_parent(&clk_usysclk, &clk_upll);
-		clk_set_parent(&clk_usbsrc, &clk_usysclk);
-		clk_set_rate(&clk_usbsrc, 48*1000*1000);
-	}
-
-	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
-	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
-	       print_mhz(clk_get_rate(&clk_upll)),
-	       print_mhz(clk_get_rate(&clk_usb_bus)));
-
-	/* register clocks from clock array */
-
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		/* ensure that we note the clock state */
-
-		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsystems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	/* install (and disable) the clocks we do not need immediately */
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		s3c2412_clkcon_enable(clkp, 0);
-	}
-
-	clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup));
-	return 0;
-}
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2416.c b/arch/arm/mach-s3c24xx/clock-s3c2416.c
deleted file mode 100644
index d421a72920a5..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c2416.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* linux/arch/arm/mach-s3c2416/clock.c
- *
- * Copyright (c) 2010 Simtec Electronics
- * Copyright (c) 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * S3C2416 Clock control 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.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/cpu.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/pll.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/regs-clock.h>
-#include <mach/regs-s3c2443-clock.h>
-
-/* armdiv
- *
- * this clock is sourced from msysclk and can have a number of
- * divider values applied to it to then be fed into armclk.
- * The real clock definition is done in s3c2443-clock.c,
- * only the armdiv divisor table must be defined here.
-*/
-
-static unsigned int armdiv[8] = {
-	[0] = 1,
-	[1] = 2,
-	[2] = 3,
-	[3] = 4,
-	[5] = 6,
-	[7] = 8,
-};
-
-static struct clksrc_clk hsspi_eplldiv = {
-	.clk = {
-		.name	= "hsspi-eplldiv",
-		.parent	= &clk_esysclk.clk,
-		.ctrlbit = (1 << 14),
-		.enable = s3c2443_clkcon_enable_s,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
-};
-
-static struct clk *hsspi_sources[] = {
-	[0] = &hsspi_eplldiv.clk,
-	[1] = NULL, /* to fix */
-};
-
-static struct clksrc_clk hsspi_mux = {
-	.clk	= {
-		.name	= "hsspi-if",
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = hsspi_sources,
-		.nr_sources = ARRAY_SIZE(hsspi_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
-};
-
-static struct clksrc_clk hsmmc_div[] = {
-	[0] = {
-		.clk = {
-			.name	= "hsmmc-div",
-			.devname	= "s3c-sdhci.0",
-			.parent	= &clk_esysclk.clk,
-		},
-		.reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 },
-	},
-	[1] = {
-		.clk = {
-			.name	= "hsmmc-div",
-			.devname	= "s3c-sdhci.1",
-			.parent	= &clk_esysclk.clk,
-		},
-		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
-	},
-};
-
-static struct clksrc_clk hsmmc_mux0 = {
-	.clk	= {
-		.name		= "hsmmc-if",
-		.devname	= "s3c-sdhci.0",
-		.ctrlbit	= (1 << 6),
-		.enable		= s3c2443_clkcon_enable_s,
-	},
-	.sources	= &(struct clksrc_sources) {
-		.nr_sources	= 2,
-		.sources	= (struct clk * []) {
-			[0]	= &hsmmc_div[0].clk,
-			[1]	= NULL, /* to fix */
-		},
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 },
-};
-
-static struct clksrc_clk hsmmc_mux1 = {
-	.clk	= {
-		.name		= "hsmmc-if",
-		.devname	= "s3c-sdhci.1",
-		.ctrlbit	= (1 << 12),
-		.enable		= s3c2443_clkcon_enable_s,
-	},
-	.sources	= &(struct clksrc_sources) {
-		.nr_sources	= 2,
-		.sources	= (struct clk * []) {
-			[0]	= &hsmmc_div[1].clk,
-			[1]	= NULL, /* to fix */
-		},
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 },
-};
-
-static struct clk hsmmc0_clk = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.0",
-	.parent		= &clk_h,
-	.enable		= s3c2443_clkcon_enable_h,
-	.ctrlbit	= S3C2416_HCLKCON_HSMMC0,
-};
-
-static struct clksrc_clk *clksrcs[] __initdata = {
-	&hsspi_eplldiv,
-	&hsspi_mux,
-	&hsmmc_div[0],
-	&hsmmc_div[1],
-	&hsmmc_mux0,
-	&hsmmc_mux1,
-};
-
-static struct clk_lookup s3c2416_clk_lookup[] = {
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk),
-	/* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */
-	CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk),
-};
-
-void __init s3c2416_init_clocks(int xtal)
-{
-	u32 epllcon = __raw_readl(S3C2443_EPLLCON);
-	u32 epllcon1 = __raw_readl(S3C2443_EPLLCON+4);
-	int ptr;
-
-	/* s3c2416 EPLL compatible with s3c64xx */
-	clk_epll.rate = s3c_get_pll6553x(xtal, epllcon, epllcon1);
-
-	clk_epll.parent = &clk_epllref.clk;
-
-	s3c2443_common_init_clocks(xtal, s3c2416_get_pll,
-				   armdiv, ARRAY_SIZE(armdiv),
-				   S3C2416_CLKDIV0_ARMDIV_MASK);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_register_clksrc(clksrcs[ptr], 1);
-
-	s3c24xx_register_clock(&hsmmc0_clk);
-	clkdev_add_table(s3c2416_clk_lookup, ARRAY_SIZE(s3c2416_clk_lookup));
-
-}
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c
index aaf006d1d6dc..5527226fd61f 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2440.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c
@@ -34,6 +34,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <mach/hardware.h>
 #include <linux/atomic.h>
@@ -43,7 +44,6 @@
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
-#include <plat/regs-serial.h>
 
 /* S3C2440 extended clock support */
 
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c
deleted file mode 100644
index 76cd31f7804e..000000000000
--- a/arch/arm/mach-s3c24xx/clock-s3c2443.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* linux/arch/arm/mach-s3c2443/clock.c
- *
- * Copyright (c) 2007, 2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2443 Clock control 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/init.h>
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-
-#include <mach/regs-s3c2443-clock.h>
-
-#include <plat/cpu-freq.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/cpu.h>
-
-/* We currently have to assume that the system is running
- * from the XTPll input, and that all ***REFCLKs are being
- * fed from it, as we cannot read the state of OM[4] from
- * software.
- *
- * It would be possible for each board initialisation to
- * set the correct muxing at initialisation
-*/
-
-/* clock selections */
-
-/* armdiv
- *
- * this clock is sourced from msysclk and can have a number of
- * divider values applied to it to then be fed into armclk.
- * The real clock definition is done in s3c2443-clock.c,
- * only the armdiv divisor table must be defined here.
-*/
-
-static unsigned int armdiv[16] = {
-	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
-	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
-	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,
-	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,
-	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,
-	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,
-	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,
-	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
-};
-
-/* hsspi
- *
- * high-speed spi clock, sourced from esysclk
-*/
-
-static struct clksrc_clk clk_hsspi = {
-	.clk	= {
-		.name		= "hsspi-if",
-		.parent		= &clk_esysclk.clk,
-		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
-		.enable		= s3c2443_clkcon_enable_s,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
-};
-
-
-/* clk_hsmcc_div
- *
- * this clock is sourced from epll, and is fed through a divider,
- * to a mux controlled by sclkcon where either it or a extclk can
- * be fed to the hsmmc block
-*/
-
-static struct clksrc_clk clk_hsmmc_div = {
-	.clk	= {
-		.name		= "hsmmc-div",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_esysclk.clk,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
-};
-
-static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
-
-	clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
-		    S3C2443_SCLKCON_HSMMCCLK_EPLL);
-
-	if (parent == &clk_epll)
-		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
-	else if (parent == &clk_ext)
-		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
-	else
-		return -EINVAL;
-
-	if (clk->usage > 0) {
-		__raw_writel(clksrc, S3C2443_SCLKCON);
-	}
-
-	clk->parent = parent;
-	return 0;
-}
-
-static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
-{
-	return s3c2443_setparent_hsmmc(clk, clk->parent);
-}
-
-static struct clk clk_hsmmc = {
-	.name		= "hsmmc-if",
-	.devname	= "s3c-sdhci.1",
-	.parent		= &clk_hsmmc_div.clk,
-	.enable		= s3c2443_enable_hsmmc,
-	.ops		= &(struct clk_ops) {
-		.set_parent	= s3c2443_setparent_hsmmc,
-	},
-};
-
-/* standard clock definitions */
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sdi",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_SDI,
-	}, {
-		.name		= "spi",
-		.devname	= "s3c2410-spi.0",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_SPI1,
-	}
-};
-
-/* clocks to add straight away */
-
-static struct clksrc_clk *clksrcs[] __initdata = {
-	&clk_hsspi,
-	&clk_hsmmc_div,
-};
-
-static struct clk *clks[] __initdata = {
-	&clk_hsmmc,
-};
-
-static struct clk_lookup s3c2443_clk_lookup[] = {
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc),
-	CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk),
-};
-
-void __init s3c2443_init_clocks(int xtal)
-{
-	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
-	int ptr;
-
-	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
-	clk_epll.parent = &clk_epllref.clk;
-
-	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll,
-				   armdiv, ARRAY_SIZE(armdiv),
-				   S3C2443_CLKDIV0_ARMDIV_MASK);
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_register_clksrc(clksrcs[ptr], 1);
-
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsystems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	/* install (and disable) the clocks we do not need immediately */
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup));
-}
diff --git a/arch/arm/mach-s3c24xx/common-s3c2443.c b/arch/arm/mach-s3c24xx/common-s3c2443.c
deleted file mode 100644
index 65d3eef73090..000000000000
--- a/arch/arm/mach-s3c24xx/common-s3c2443.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Common code for SoCs starting with the S3C2443
- *
- * Copyright (c) 2007, 2010 Simtec Electronics
- *	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 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/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/regs-s3c2443-clock.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/cpu.h>
-
-#include <plat/cpu-freq.h>
-
-
-static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable)
-{
-	u32 ctrlbit = clk->ctrlbit;
-	u32 con = __raw_readl(reg);
-
-	if (enable)
-		con |= ctrlbit;
-	else
-		con &= ~ctrlbit;
-
-	__raw_writel(con, reg);
-	return 0;
-}
-
-int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
-{
-	return s3c2443_gate(S3C2443_HCLKCON, clk, enable);
-}
-
-int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
-{
-	return s3c2443_gate(S3C2443_PCLKCON, clk, enable);
-}
-
-int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
-{
-	return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
-}
-
-/* mpllref is a direct descendant of clk_xtal by default, but it is not
- * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as
- * such directly equating the two source clocks is impossible.
- */
-static struct clk clk_mpllref = {
-	.name		= "mpllref",
-	.parent		= &clk_xtal,
-};
-
-static struct clk *clk_epllref_sources[] = {
-	[0] = &clk_mpllref,
-	[1] = &clk_mpllref,
-	[2] = &clk_xtal,
-	[3] = &clk_ext,
-};
-
-struct clksrc_clk clk_epllref = {
-	.clk	= {
-		.name		= "epllref",
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_epllref_sources,
-		.nr_sources = ARRAY_SIZE(clk_epllref_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
-};
-
-/* esysclk
- *
- * this is sourced from either the EPLL or the EPLLref clock
-*/
-
-static struct clk *clk_sysclk_sources[] = {
-	[0] = &clk_epllref.clk,
-	[1] = &clk_epll,
-};
-
-struct clksrc_clk clk_esysclk = {
-	.clk	= {
-		.name		= "esysclk",
-		.parent		= &clk_epll,
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_sysclk_sources,
-		.nr_sources = ARRAY_SIZE(clk_sysclk_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 },
-};
-
-static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV0);
-
-	div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
-	div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);	/* x2 */
-
-	return parent_rate / (div + 1);
-}
-
-static struct clk clk_mdivclk = {
-	.name		= "mdivclk",
-	.parent		= &clk_mpllref,
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2443_getrate_mdivclk,
-	},
-};
-
-static struct clk *clk_msysclk_sources[] = {
-	[0] = &clk_mpllref,
-	[1] = &clk_mpll,
-	[2] = &clk_mdivclk,
-	[3] = &clk_mpllref,
-};
-
-static struct clksrc_clk clk_msysclk = {
-	.clk	= {
-		.name		= "msysclk",
-		.parent		= &clk_xtal,
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_msysclk_sources,
-		.nr_sources = ARRAY_SIZE(clk_msysclk_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 },
-};
-
-/* prediv
- *
- * this divides the msysclk down to pass to h/p/etc.
- */
-
-static unsigned long s3c2443_prediv_getrate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
-
-	clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK;
-	clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
-
-	return rate / (clkdiv0 + 1);
-}
-
-static struct clk clk_prediv = {
-	.name		= "prediv",
-	.parent		= &clk_msysclk.clk,
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c2443_prediv_getrate,
-	},
-};
-
-/* hclk divider
- *
- * divides the prediv and provides the hclk.
- */
-
-static unsigned long s3c2443_hclkdiv_getrate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
-
-	clkdiv0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
-
-	return rate / (clkdiv0 + 1);
-}
-
-static struct clk_ops clk_h_ops = {
-	.get_rate	= s3c2443_hclkdiv_getrate,
-};
-
-/* pclk divider
- *
- * divides the hclk and provides the pclk.
- */
-
-static unsigned long s3c2443_pclkdiv_getrate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
-
-	clkdiv0 = ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 1 : 0);
-
-	return rate / (clkdiv0 + 1);
-}
-
-static struct clk_ops clk_p_ops = {
-	.get_rate	= s3c2443_pclkdiv_getrate,
-};
-
-/* armdiv
- *
- * this clock is sourced from msysclk and can have a number of
- * divider values applied to it to then be fed into armclk.
-*/
-
-static unsigned int *armdiv;
-static int nr_armdiv;
-static int armdivmask;
-
-static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned best = 256; /* bigger than any value */
-	unsigned div;
-	int ptr;
-
-	if (!nr_armdiv)
-		return -EINVAL;
-
-	for (ptr = 0; ptr < nr_armdiv; ptr++) {
-		div = armdiv[ptr];
-		if (div) {
-			/* cpufreq provides 266mhz as 266666000 not 266666666 */
-			calc = (parent / div / 1000) * 1000;
-			if (calc <= rate && div < best)
-				best = div;
-		}
-	}
-
-	return parent / best;
-}
-
-static unsigned long s3c2443_armclk_getrate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	unsigned long clkcon0;
-	int val;
-
-	if (!nr_armdiv || !armdivmask)
-		return -EINVAL;
-
-	clkcon0 = __raw_readl(S3C2443_CLKDIV0);
-	clkcon0 &= armdivmask;
-	val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
-
-	return rate / armdiv[val];
-}
-
-static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned div;
-	unsigned best = 256; /* bigger than any value */
-	int ptr;
-	int val = -1;
-
-	if (!nr_armdiv || !armdivmask)
-		return -EINVAL;
-
-	for (ptr = 0; ptr < nr_armdiv; ptr++) {
-		div = armdiv[ptr];
-		if (div) {
-			/* cpufreq provides 266mhz as 266666000 not 266666666 */
-			calc = (parent / div / 1000) * 1000;
-			if (calc <= rate && div < best) {
-				best = div;
-				val = ptr;
-			}
-		}
-	}
-
-	if (val >= 0) {
-		unsigned long clkcon0;
-
-		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
-		clkcon0 &= ~armdivmask;
-		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-		__raw_writel(clkcon0, S3C2443_CLKDIV0);
-	}
-
-	return (val == -1) ? -EINVAL : 0;
-}
-
-static struct clk clk_armdiv = {
-	.name		= "armdiv",
-	.parent		= &clk_msysclk.clk,
-	.ops		= &(struct clk_ops) {
-		.round_rate = s3c2443_armclk_roundrate,
-		.get_rate = s3c2443_armclk_getrate,
-		.set_rate = s3c2443_armclk_setrate,
-	},
-};
-
-/* armclk
- *
- * this is the clock fed into the ARM core itself, from armdiv or from hclk.
- */
-
-static struct clk *clk_arm_sources[] = {
-	[0] = &clk_armdiv,
-	[1] = &clk_h,
-};
-
-static struct clksrc_clk clk_arm = {
-	.clk	= {
-		.name		= "armclk",
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_arm_sources,
-		.nr_sources = ARRAY_SIZE(clk_arm_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
-};
-
-/* usbhost
- *
- * usb host bus-clock, usually 48MHz to provide USB bus clock timing
-*/
-
-static struct clksrc_clk clk_usb_bus_host = {
-	.clk	= {
-		.name		= "usb-bus-host-parent",
-		.parent		= &clk_esysclk.clk,
-		.ctrlbit	= S3C2443_SCLKCON_USBHOST,
-		.enable		= s3c2443_clkcon_enable_s,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
-};
-
-/* common clksrc clocks */
-
-static struct clksrc_clk clksrc_clks[] = {
-	{
-		/* camera interface bus-clock, divided down from esysclk */
-		.clk	= {
-			.name		= "camif-upll",	/* same as 2440 name */
-			.parent		= &clk_esysclk.clk,
-			.ctrlbit	= S3C2443_SCLKCON_CAMCLK,
-			.enable		= s3c2443_clkcon_enable_s,
-		},
-		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
-	}, {
-		.clk	= {
-			.name		= "display-if",
-			.parent		= &clk_esysclk.clk,
-			.ctrlbit	= S3C2443_SCLKCON_DISPCLK,
-			.enable		= s3c2443_clkcon_enable_s,
-		},
-		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
-	},
-};
-
-static struct clksrc_clk clk_esys_uart = {
-	/* ART baud-rate clock sourced from esysclk via a divisor */
-	.clk	= {
-		.name		= "uartclk",
-		.parent		= &clk_esysclk.clk,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
-};
-
-static struct clk clk_i2s_ext = {
-	.name		= "i2s-ext",
-};
-
-/* i2s_eplldiv
- *
- * This clock is the output from the I2S divisor of ESYSCLK, and is separate
- * from the mux that comes after it (cannot merge into one single clock)
-*/
-
-static struct clksrc_clk clk_i2s_eplldiv = {
-	.clk	= {
-		.name		= "i2s-eplldiv",
-		.parent		= &clk_esysclk.clk,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
-};
-
-/* i2s-ref
- *
- * i2s bus reference clock, selectable from external, esysclk or epllref
- *
- * Note, this used to be two clocks, but was compressed into one.
-*/
-
-static struct clk *clk_i2s_srclist[] = {
-	[0] = &clk_i2s_eplldiv.clk,
-	[1] = &clk_i2s_ext,
-	[2] = &clk_epllref.clk,
-	[3] = &clk_epllref.clk,
-};
-
-static struct clksrc_clk clk_i2s = {
-	.clk	= {
-		.name		= "i2s-if",
-		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
-		.enable		= s3c2443_clkcon_enable_s,
-
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_i2s_srclist,
-		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "iis",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_IIS,
-	}, {
-		.name		= "adc",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_IIC,
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "dma.0",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA0,
-	}, {
-		.name		= "dma.1",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA1,
-	}, {
-		.name		= "dma.2",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA2,
-	}, {
-		.name		= "dma.3",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA3,
-	}, {
-		.name		= "dma.4",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA4,
-	}, {
-		.name		= "dma.5",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_DMA5,
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_GPIO,
-	}, {
-		.name		= "usb-host",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_USBD,
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_LCDC,
-
-	}, {
-		.name		= "timers",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_PWMT,
-	}, {
-		.name		= "cfc",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_CFC,
-	}, {
-		.name		= "ssmc",
-		.parent		= &clk_h,
-		.enable		= s3c2443_clkcon_enable_h,
-		.ctrlbit	= S3C2443_HCLKCON_SSMC,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2440-uart.0",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2440-uart.1",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2440-uart.2",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_UART2,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c2440-uart.3",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_UART3,
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_RTC,
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_p,
-		.ctrlbit	= S3C2443_PCLKCON_WDT,
-	}, {
-		.name		= "ac97",
-		.parent		= &clk_p,
-		.ctrlbit	= S3C2443_PCLKCON_AC97,
-	}, {
-		.name		= "nand",
-		.parent		= &clk_h,
-	}, {
-		.name		= "usb-bus-host",
-		.parent		= &clk_usb_bus_host.clk,
-	}
-};
-
-static struct clk hsmmc1_clk = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.1",
-	.parent		= &clk_h,
-	.enable		= s3c2443_clkcon_enable_h,
-	.ctrlbit	= S3C2443_HCLKCON_HSMMC,
-};
-
-static struct clk hsspi_clk = {
-	.name		= "spi",
-	.devname	= "s3c2443-spi.0",
-	.parent		= &clk_p,
-	.enable		= s3c2443_clkcon_enable_p,
-	.ctrlbit	= S3C2443_PCLKCON_HSSPI,
-};
-
-/* EPLLCON compatible enough to get on/off information */
-
-void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
-{
-	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
-	unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
-	struct clk *xtal_clk;
-	unsigned long xtal;
-	unsigned long pll;
-	int ptr;
-
-	xtal_clk = clk_get(NULL, "xtal");
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	pll = get_mpll(mpllcon, xtal);
-	clk_msysclk.clk.rate = pll;
-	clk_mpll.rate = pll;
-
-	printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
-	       (mpllcon & S3C2443_PLLCON_OFF) ? "off" : "on",
-	       print_mhz(pll), print_mhz(clk_get_rate(&clk_armdiv)),
-	       print_mhz(clk_get_rate(&clk_h)),
-	       print_mhz(clk_get_rate(&clk_p)));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++)
-		s3c_set_clksrc(&clksrc_clks[ptr], true);
-
-	/* ensure usb bus clock is within correct rate of 48MHz */
-
-	if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
-		printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
-		clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
-	}
-
-	printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
-	       (epllcon & S3C2443_PLLCON_OFF) ? "off" : "on",
-	       print_mhz(clk_get_rate(&clk_epll)),
-	       print_mhz(clk_get_rate(&clk_usb_bus)));
-}
-
-static struct clk *clks[] __initdata = {
-	&clk_prediv,
-	&clk_mpllref,
-	&clk_mdivclk,
-	&clk_ext,
-	&clk_epll,
-	&clk_usb_bus,
-	&clk_armdiv,
-	&hsmmc1_clk,
-	&hsspi_clk,
-};
-
-static struct clksrc_clk *clksrcs[] __initdata = {
-	&clk_i2s_eplldiv,
-	&clk_i2s,
-	&clk_usb_bus_host,
-	&clk_epllref,
-	&clk_esysclk,
-	&clk_msysclk,
-	&clk_arm,
-};
-
-static struct clk_lookup s3c2443_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk),
-	CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk),
-};
-
-void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
-				       unsigned int *divs, int nr_divs,
-				       int divmask)
-{
-	int ptr;
-
-	armdiv = divs;
-	nr_armdiv = nr_divs;
-	armdivmask = divmask;
-
-	/* s3c2443 parents h clock from prediv */
-	clk_h.parent = &clk_prediv;
-	clk_h.ops = &clk_h_ops;
-
-	/* and p clock from h clock */
-	clk_p.parent = &clk_h;
-	clk_p.ops = &clk_p_ops;
-
-	clk_usb_bus.parent = &clk_usb_bus_host.clk;
-	clk_epll.parent = &clk_epllref.clk;
-
-	s3c24xx_register_baseclocks(xtal);
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_register_clksrc(clksrcs[ptr], 1);
-
-	s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-	/* See s3c2443/etc notes on disabling clocks at init time */
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup));
-
-	s3c2443_common_setup_clocks(get_mpll);
-}
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index 4adaa4b43ffe..ad5b76bf4d51 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <clocksource/samsung_pwm.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -44,7 +45,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/regs-gpio.h>
-#include <plat/regs-serial.h>
 #include <mach/dma.h>
 
 #include <plat/cpu.h>
@@ -127,7 +127,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= 0x32412001,
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2412_map_io,
-		.init_clocks	= s3c2412_init_clocks,
 		.init_uarts	= s3c2412_init_uarts,
 		.init		= s3c2412_init,
 		.name		= name_s3c2412,
@@ -136,7 +135,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= 0x32412003,
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2412_map_io,
-		.init_clocks	= s3c2412_init_clocks,
 		.init_uarts	= s3c2412_init_uarts,
 		.init		= s3c2412_init,
 		.name		= name_s3c2412,
@@ -145,7 +143,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= 0x32450003,
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2416_map_io,
-		.init_clocks	= s3c2416_init_clocks,
 		.init_uarts	= s3c2416_init_uarts,
 		.init		= s3c2416_init,
 		.name		= name_s3c2416,
@@ -154,7 +151,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= 0x32443001,
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2443_map_io,
-		.init_clocks	= s3c2443_init_clocks,
 		.init_uarts	= s3c2443_init_uarts,
 		.init		= s3c2443_init,
 		.name		= name_s3c2443,
@@ -240,7 +236,6 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 	} else {
 		samsung_cpu_id = s3c24xx_read_idcode_v4();
 	}
-	s3c24xx_init_cpu();
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 
@@ -319,6 +314,7 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
 
 /* initialise all the clocks */
 
+#ifdef CONFIG_SAMSUNG_CLOCK
 void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk,
 					   unsigned long hclk,
 					   unsigned long pclk)
@@ -331,6 +327,7 @@ void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk,
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
 }
+#endif
 
 #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
 	defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
@@ -484,7 +481,7 @@ struct platform_device s3c2440_device_dma = {
 };
 #endif
 
-#if defined(CONFIG_CPUS_3C2443) || defined(CONFIG_CPU_S3C2416)
+#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416)
 static struct resource s3c2443_dma_resource[] = {
 	[0] = DEFINE_RES_MEM(S3C24XX_PA_DMA, S3C24XX_SZ_DMA),
 	[1] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA0),
@@ -535,3 +532,24 @@ struct platform_device s3c2443_device_dma = {
 	},
 };
 #endif
+
+#ifdef CONFIG_CPU_S3C2412
+void __init s3c2412_init_clocks(int xtal)
+{
+	s3c2412_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2416
+void __init s3c2416_init_clocks(int xtal)
+{
+	s3c2443_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2443
+void __init s3c2443_init_clocks(int xtal)
+{
+	s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR);
+}
+#endif
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index e46c10417216..3fade6d796f9 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -114,4 +114,14 @@ extern struct platform_device s3c2412_device_dma;
 extern struct platform_device s3c2440_device_dma;
 extern struct platform_device s3c2443_device_dma;
 
+#ifdef CONFIG_S3C2412_COMMON_CLK
+void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
+				unsigned long ext_f, void __iomem *reg_base);
+#endif
+#ifdef CONFIG_S3C2443_COMMON_CLK
+void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
+				    int current_soc,
+				    void __iomem *reg_base);
+#endif
+
 #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2410.c b/arch/arm/mach-s3c24xx/dma-s3c2410.c
index 30aa53ff07a6..09aa12da1789 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2410.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
@@ -23,7 +24,6 @@
 #include <plat/cpu.h>
 #include <plat/dma-s3c24xx.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2412.c b/arch/arm/mach-s3c24xx/dma-s3c2412.c
index b7e094671522..0c0106d1a4d1 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2412.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <mach/dma.h>
@@ -23,7 +24,6 @@
 #include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2440.c b/arch/arm/mach-s3c24xx/dma-s3c2440.c
index cd25de28804c..2f8e8a3017df 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2440.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2440.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
@@ -23,7 +24,6 @@
 #include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2443.c b/arch/arm/mach-s3c24xx/dma-s3c2443.c
index 95b9f759fe97..f4096ec0700a 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2443.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2443.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <mach/dma.h>
@@ -23,7 +24,6 @@
 #include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S
index 2558952e3147..2f39737544c0 100644
--- a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S
@@ -14,7 +14,7 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <plat/regs-serial.h>
+#include <linux/serial_s3c.h>
 
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
diff --git a/arch/arm/mach-s3c24xx/include/mach/rtc-core.h b/arch/arm/mach-s3c24xx/include/mach/rtc-core.h
new file mode 100644
index 000000000000..4d5f5768f700
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/include/mach/rtc-core.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ * Samsung RTC Controller core functions
+ *
+ * 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 __RTC_CORE_H
+#define __RTC_CORE_H __FILE__
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+extern struct platform_device s3c_device_rtc;
+
+/* re-define device name depending on support. */
+static inline void s3c_rtc_setname(char *name)
+{
+	s3c_device_rtc.name = name;
+}
+
+#endif /* __RTC_CORE_H */
diff --git a/arch/arm/mach-s3c24xx/include/mach/tick.h b/arch/arm/mach-s3c24xx/include/mach/tick.h
deleted file mode 100644
index 544da41979db..000000000000
--- a/arch/arm/mach-s3c24xx/include/mach/tick.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/include/mach/tick.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C2410 - timer tick support
- */
-
-#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
-
-static inline int s3c24xx_ostimer_pending(void)
-{
-	return __raw_readl(S3C2410_SRCPND) & SRCPND_TIMER4;
-}
diff --git a/arch/arm/mach-s3c24xx/include/mach/timex.h b/arch/arm/mach-s3c24xx/include/mach/timex.h
deleted file mode 100644
index fe9ca1ffd51b..000000000000
--- a/arch/arm/mach-s3c24xx/include/mach/timex.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c
index 284ea1f44205..8ac9554aa996 100644
--- a/arch/arm/mach-s3c24xx/mach-amlm5900.c
+++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c
@@ -37,6 +37,7 @@
 #include <linux/platform_device.h>
 #include <linux/proc_fs.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -49,7 +50,6 @@
 #include <asm/mach-types.h>
 #include <mach/fb.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-gpio.h>
 #include <mach/gpio-samsung.h>
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 2a16f8fb3584..81a270af2336 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 #include <linux/i2c.h>
@@ -32,7 +33,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 #include <mach/gpio-samsung.h>
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 6beab674c147..d8f6bb1096cb 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/dm9000.h>
 #include <linux/platform_device.h>
 
@@ -33,7 +34,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 #include <mach/gpio-samsung.h>
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 981ba1eb9fdc..e371ff53a408 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/dm9000.h>
 #include <linux/ata_platform.h>
@@ -55,7 +56,6 @@
 #include <plat/cpu-freq.h>
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "bast.h"
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index d9170e9f8ccd..8e0581317f17 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -35,6 +35,7 @@
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -81,7 +82,6 @@
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index de0832181d8c..e453acd92cbf 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -62,7 +63,6 @@
 #include <plat/gpio-cfg.h>
 #include <plat/pll.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 67cb8e948b7e..e81ea82c55f9 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 
@@ -31,7 +32,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
@@ -507,11 +507,16 @@ static struct syscore_ops jive_pm_syscore_ops = {
 static void __init jive_map_io(void)
 {
 	s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
-	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
+static void __init jive_init_time(void)
+{
+	s3c2412_init_clocks(12000000);
+	samsung_timer_init();
+}
+
 static void jive_power_off(void)
 {
 	printk(KERN_INFO "powering system down...\n");
@@ -665,6 +670,6 @@ MACHINE_START(JIVE, "JIVE")
 	.init_irq	= s3c2412_init_irq,
 	.map_io		= jive_map_io,
 	.init_machine	= jive_machine_init,
-	.init_time	= samsung_timer_init,
+	.init_time	= jive_init_time,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 1f1559713d8b..9e57fd9f4f3b 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -23,6 +23,7 @@
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/dm9000.h>
 #include <linux/platform_data/at24.h>
 #include <linux/platform_device.h>
@@ -37,7 +38,6 @@
 #include <mach/fb.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <linux/platform_data/leds-s3c24xx.h>
 #include <mach/regs-lcd.h>
diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c
index 997684f17930..4cccaad34847 100644
--- a/arch/arm/mach-s3c24xx/mach-n30.c
+++ b/arch/arm/mach-s3c24xx/mach-n30.c
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/mmc/host.h>
@@ -43,7 +44,6 @@
 #include <asm/mach/map.h>
 
 #include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/regs-serial.h>
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
index 575d28c9e6c6..3066851f584d 100644
--- a/arch/arm/mach-s3c24xx/mach-nexcoder.c
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/string.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -38,7 +39,6 @@
 //#include <asm/debug-ll.h>
 #include <mach/regs-gpio.h>
 #include <mach/gpio-samsung.h>
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index f84f2a4c0c6d..a4ae4bb3666d 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/clk.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
@@ -44,7 +45,6 @@
 #include <plat/cpu-freq.h>
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c
index 7e16b0740ec1..bdb3faac2d9b 100644
--- a/arch/arm/mach-s3c24xx/mach-otom.c
+++ b/arch/arm/mach-s3c24xx/mach-otom.c
@@ -15,6 +15,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -32,7 +33,6 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index b534b76812e3..8c12787a8fd3 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -31,6 +31,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
 #include <linux/io.h>
@@ -49,7 +50,6 @@
 
 #include <linux/platform_data/leds-s3c24xx.h>
 #include <mach/regs-lcd.h>
-#include <plat/regs-serial.h>
 #include <mach/fb.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 0a5456cda1bc..afb784e934c8 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/device.h>
@@ -57,7 +58,6 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 #include <plat/gpio-cfg.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index b36edce8b2b8..e6535ce1bc5c 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -23,6 +23,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/serial.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
@@ -49,7 +50,6 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
index f50454a34f72..b3f10b6c70e2 100644
--- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
+++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
@@ -19,58 +19,24 @@
 #include <linux/irqchip.h>
 #include <linux/of_platform.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <asm/mach/arch.h>
 #include <mach/map.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 
 #include "common.h"
 
-/*
- * The following lookup table is used to override device names when devices
- * are registered from device tree. This is temporarily added to enable
- * device tree support addition for the S3C2416 architecture.
- *
- * For drivers that require platform data to be provided from the machine
- * file, a platform data pointer can also be supplied along with the
- * devices names. Usually, the platform data elements that cannot be parsed
- * from the device tree by the drivers (example: function pointers) are
- * supplied. But it should be noted that this is a temporary mechanism and
- * at some point, the drivers should be capable of parsing all the platform
- * data from the device tree.
- */
-static const struct of_dev_auxdata s3c2416_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART,
-				"s3c2440-uart.0", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x4000,
-				"s3c2440-uart.1", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x8000,
-				"s3c2440-uart.2", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0xC000,
-				"s3c2440-uart.3", NULL),
-	OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC0,
-				"s3c-sdhci.0", NULL),
-	OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC1,
-				"s3c-sdhci.1", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", S3C_PA_IIC,
-				"s3c2440-i2c.0", NULL),
-	{},
-};
-
 static void __init s3c2416_dt_map_io(void)
 {
 	s3c24xx_init_io(NULL, 0);
-	s3c24xx_init_clocks(12000000);
 }
 
 static void __init s3c2416_dt_machine_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-				s3c2416_auxdata_lookup, NULL);
-
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	s3c_pm_init();
 }
 
@@ -86,6 +52,5 @@ DT_MACHINE_START(S3C2416_DT, "Samsung S3C2416 (Flattened Device Tree)")
 	.map_io		= s3c2416_dt_map_io,
 	.init_irq	= irqchip_init,
 	.init_machine	= s3c2416_dt_machine_init,
-	 .init_time	= clocksource_of_init,
 	.restart	= s3c2416_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c
index a773789e4f38..f32924ee0e9f 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2410.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c
@@ -35,6 +35,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -46,7 +47,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index f5bc721217e3..a38f8a049e22 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -33,7 +34,6 @@
 #include <asm/mach-types.h>
 
 //#include <asm/debug-ll.h>
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
@@ -106,11 +106,16 @@ static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
 static void __init smdk2413_map_io(void)
 {
 	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
-	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
+static void __init smdk2413_init_time(void)
+{
+	s3c2412_init_clocks(12000000);
+	samsung_timer_init();
+}
+
 static void __init smdk2413_machine_init(void)
 {	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
@@ -159,6 +164,6 @@ MACHINE_START(SMDK2413, "SMDK2413")
 	.init_irq	= s3c2412_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.init_time	= samsung_timer_init,
+	.init_time	= smdk2413_init_time,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index 12023cae4378..fa6f30d23601 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -18,6 +18,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/partitions.h>
@@ -34,7 +35,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-s3c2443-clock.h>
@@ -219,10 +219,15 @@ static struct platform_device *smdk2416_devices[] __initdata = {
 	&s3c2443_device_dma,
 };
 
+static void __init smdk2416_init_time(void)
+{
+	s3c2416_init_clocks(12000000);
+	samsung_timer_init();
+}
+
 static void __init smdk2416_map_io(void)
 {
 	s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
-	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
@@ -257,6 +262,6 @@ MACHINE_START(SMDK2416, "SMDK2416")
 	.init_irq	= s3c2416_init_irq,
 	.map_io		= smdk2416_map_io,
 	.init_machine	= smdk2416_machine_init,
-	.init_time	= samsung_timer_init,
+	.init_time	= smdk2416_init_time,
 	.restart	= s3c2416_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c
index de2e5d39a847..d071dcfea548 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2440.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -31,7 +32,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index d9933fcc6cc8..ef5d5ea33182 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -31,7 +32,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
@@ -121,11 +121,16 @@ static struct platform_device *smdk2443_devices[] __initdata = {
 static void __init smdk2443_map_io(void)
 {
 	s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
-	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
+static void __init smdk2443_init_time(void)
+{
+	s3c2443_init_clocks(12000000);
+	samsung_timer_init();
+}
+
 static void __init smdk2443_machine_init(void)
 {
 	s3c_i2c0_set_platdata(NULL);
@@ -145,6 +150,6 @@ MACHINE_START(SMDK2443, "SMDK2443")
 	.init_irq	= s3c2443_init_irq,
 	.map_io		= smdk2443_map_io,
 	.init_machine	= smdk2443_machine_init,
-	.init_time	= samsung_timer_init,
+	.init_time	= smdk2443_init_time,
 	.restart	= s3c2443_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
index 7fad8f055cab..4108b2f0cede 100644
--- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -44,7 +45,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index 755df489a45f..1cc5b1bd51cd 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -25,6 +25,7 @@
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -45,7 +46,6 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/regs-serial.h>
 #include <plat/samsung-time.h>
 
 #include "bast.h"
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index f7ec9c550787..6b706c915387 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
@@ -32,7 +33,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
@@ -142,11 +142,16 @@ static void __init vstms_fixup(struct tag *tags, char **cmdline,
 static void __init vstms_map_io(void)
 {
 	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
-	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
+static void __init vstms_init_time(void)
+{
+	s3c2412_init_clocks(12000000);
+	samsung_timer_init();
+}
+
 static void __init vstms_init(void)
 {
 	s3c_i2c0_set_platdata(NULL);
@@ -162,6 +167,6 @@ MACHINE_START(VSTMS, "VSTMS")
 	.init_irq	= s3c2412_init_irq,
 	.init_machine	= vstms_init,
 	.map_io		= vstms_map_io,
-	.init_time	= samsung_timer_init,
+	.init_time	= vstms_init_time,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c
index 052ca23393a7..16281bdc750a 100644
--- a/arch/arm/mach-s3c24xx/pm.c
+++ b/arch/arm/mach-s3c24xx/pm.c
@@ -33,9 +33,9 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-irq.h>
@@ -51,9 +51,6 @@
 #define PFX "s3c24xx-pm: "
 
 static struct sleep_save core_save[] = {
-	SAVE_ITEM(S3C2410_LOCKTIME),
-	SAVE_ITEM(S3C2410_CLKCON),
-
 	/* we restore the timings here, with the proviso that the board
 	 * brings the system up in an slower, or equal frequency setting
 	 * to the original system.
@@ -70,6 +67,9 @@ static struct sleep_save core_save[] = {
 	SAVE_ITEM(S3C2410_BANKCON4),
 	SAVE_ITEM(S3C2410_BANKCON5),
 
+#ifdef CONFIG_SAMSUNG_CLOCK
+	SAVE_ITEM(S3C2410_LOCKTIME),
+	SAVE_ITEM(S3C2410_CLKCON),
 #ifndef CONFIG_CPU_FREQ
 	SAVE_ITEM(S3C2410_CLKDIVN),
 	SAVE_ITEM(S3C2410_MPLLCON),
@@ -77,11 +77,14 @@ static struct sleep_save core_save[] = {
 #endif
 	SAVE_ITEM(S3C2410_UPLLCON),
 	SAVE_ITEM(S3C2410_CLKSLOW),
+#endif /* CONFIG_SAMSUNG_CLOCK */
 };
 
+#ifdef CONFIG_SAMSUNG_CLOCK
 static struct sleep_save misc_save[] = {
 	SAVE_ITEM(S3C2410_DCLKCON),
 };
+#endif
 
 /* s3c_pm_check_resume_pin
  *
@@ -140,12 +143,16 @@ void s3c_pm_configure_extint(void)
 void s3c_pm_restore_core(void)
 {
 	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+#ifdef CONFIG_SAMSUNG_CLOCK
 	s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
+#endif
 }
 
 void s3c_pm_save_core(void)
 {
+#ifdef CONFIG_SAMSUNG_CLOCK
 	s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+#endif
 	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
 }
 
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index ffb92cbca08c..04b58cb49888 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/io.h>
@@ -37,7 +38,6 @@
 #include <plat/cpu-freq.h>
 
 #include <mach/regs-clock.h>
-#include <plat/regs-serial.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c
index 0251650cbf80..d49f52fbc842 100644
--- a/arch/arm/mach-s3c24xx/s3c2412.c
+++ b/arch/arm/mach-s3c24xx/s3c2412.c
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/reboot.h>
@@ -43,7 +44,6 @@
 #include <plat/nand-core.h>
 #include <plat/pll.h>
 #include <plat/pm.h>
-#include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
 
 #include "common.h"
@@ -173,49 +173,6 @@ void __init s3c2412_map_io(void)
 
 void __init_or_cpufreq s3c2412_setup_clocks(void)
 {
-	struct clk *xtal_clk;
-	unsigned long tmp;
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long pclk;
-
-	xtal_clk = clk_get(NULL, "xtal");
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	/* now we've got our machine bits initialised, work out what
-	 * clocks we've got */
-
-	fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal * 2);
-
-	clk_mpll.rate = fclk;
-
-	tmp = __raw_readl(S3C2410_CLKDIVN);
-
-	/* work out clock scalings */
-
-	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
-	hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1);
-	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
-
-	/* print brieft summary of clocks, etc */
-
-	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	s3c24xx_setup_clocks(fclk, hclk, pclk);
-}
-
-void __init s3c2412_init_clocks(int xtal)
-{
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them
-	 */
-
-	s3c24xx_register_baseclocks(xtal);
-	s3c2412_setup_clocks();
-	s3c2412_baseclk_add();
 }
 
 /* need to register the subsystem before we actually register the device, and
diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c
index 8e01b4f2df35..9fe260ae11e1 100644
--- a/arch/arm/mach-s3c24xx/s3c2416.c
+++ b/arch/arm/mach-s3c24xx/s3c2416.c
@@ -48,6 +48,7 @@
 #include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
+#include <mach/rtc-core.h>
 
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
@@ -61,7 +62,6 @@
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
-#include <plat/rtc-core.h>
 #include <plat/spi-core.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c
index 886c2147062b..c7a804d0348e 100644
--- a/arch/arm/mach-s3c24xx/s3c2443.c
+++ b/arch/arm/mach-s3c24xx/s3c2443.c
@@ -34,6 +34,7 @@
 #include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
+#include <mach/rtc-core.h>
 
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
@@ -43,7 +44,6 @@
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
-#include <plat/rtc-core.h>
 #include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c
index 911b555029fc..fe30ebb234d2 100644
--- a/arch/arm/mach-s3c24xx/s3c244x.c
+++ b/arch/arm/mach-s3c24xx/s3c244x.c
@@ -17,6 +17,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/device.h>
@@ -35,7 +36,6 @@
 #include <plat/cpu-freq.h>
 
 #include <mach/regs-clock.h>
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2410.S b/arch/arm/mach-s3c24xx/sleep-s3c2410.S
index dd47c8fa07fa..c9b91223697c 100644
--- a/arch/arm/mach-s3c24xx/sleep-s3c2410.S
+++ b/arch/arm/mach-s3c24xx/sleep-s3c2410.S
@@ -25,13 +25,13 @@
 */
 
 #include <linux/linkage.h>
+#include <linux/serial_s3c.h>
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
-#include <plat/regs-serial.h>
 
 #include "regs-mem.h"
 
diff --git a/arch/arm/mach-s3c24xx/sleep.S b/arch/arm/mach-s3c24xx/sleep.S
index 7f378b662da6..d833d616bd2e 100644
--- a/arch/arm/mach-s3c24xx/sleep.S
+++ b/arch/arm/mach-s3c24xx/sleep.S
@@ -25,13 +25,13 @@
 */
 
 #include <linux/linkage.h>
+#include <linux/serial_s3c.h>
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
-#include <plat/regs-serial.h>
 
 /* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
  * reset the UART configuration, only enable if you really need this!
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 76ab595d849b..5c45aae675b6 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/io.h>
@@ -50,7 +51,6 @@
 #include <plat/irq-uart.h>
 #include <plat/pwm-core.h>
 #include <plat/regs-irqtype.h>
-#include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
index dd9ccca5de1f..c9b95325b672 100644
--- a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
@@ -12,8 +12,8 @@
 
 /* pull in the relevant register and map files. */
 
+#include <linux/serial_s3c.h>
 #include <mach/map.h>
-#include <plat/regs-serial.h>
 
 	/* note, for the boot process to work we have to keep the UART
 	 * virtual address aligned to an 1MiB boundary for the L1
diff --git a/arch/arm/mach-s3c64xx/include/mach/tick.h b/arch/arm/mach-s3c64xx/include/mach/tick.h
deleted file mode 100644
index db9c1b1d56a4..000000000000
--- a/arch/arm/mach-s3c64xx/include/mach/tick.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/tick.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - Timer tick support definitions
- *
- * 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 __ASM_ARCH_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-#include <linux/irqchip/arm-vic.h>
-
-/* note, the timer interrutps turn up in 2 places, the vic and then
- * the timer block. We take the VIC as the base at the moment.
- */
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
-	return pend & 1 << (IRQ_TIMER4_VIC - S3C64XX_IRQ_VIC0(0));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_6400_TICK_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/timex.h b/arch/arm/mach-s3c64xx/include/mach/timex.h
deleted file mode 100644
index fb2e8cd40829..000000000000
--- a/arch/arm/mach-s3c64xx/include/mach/timex.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/mach/timex.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C6400 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c
index 1649c0d1c1b8..a61247bb6e7a 100644
--- a/arch/arm/mach-s3c64xx/irq-pm.c
+++ b/arch/arm/mach-s3c64xx/irq-pm.c
@@ -20,13 +20,13 @@
 #include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/of.h>
 
 #include <mach/map.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index ddeb0e51a962..55eb6a69655b 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -41,7 +42,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index 7ccfef227c77..9c00d83f7151 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -401,4 +401,4 @@ static int __init wlf_gf_module_register(void)
 {
 	return i2c_add_driver(&wlf_gf_module_driver);
 }
-module_init(wlf_gf_module_register);
+device_initcall(wlf_gf_module_register);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 3df3c372ee1f..4b0199fff9f5 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
 #include <linux/io.h>
@@ -51,7 +52,6 @@
 #include <mach/regs-gpio.h>
 #include <mach/gpio-samsung.h>
 
-#include <plat/regs-serial.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 0431016925b9..72cee08c8bf5 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -33,7 +34,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/gpio-samsung.h>
 #include <plat/fb.h>
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 8d553a418e1c..9cbc07602ef3 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -22,6 +22,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/types.h>
 
 #include <asm/mach-types.h>
@@ -38,7 +39,6 @@
 #include <plat/fb.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <linux/platform_data/mmc-sdhci-s3c.h>
-#include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 2067b0bf55b4..67f06a9ae656 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -36,7 +37,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 5152026f0e19..fbad2af1ef16 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -23,6 +23,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/types.h>
 
 #include <asm/mach-types.h>
@@ -38,7 +39,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
-#include <plat/regs-serial.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 6e72bd5c1d0c..78dd6f73c072 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/spi/spi_gpio.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/platform_data/s3c-hsotg.h>
@@ -33,7 +34,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <linux/platform_data/hwmon-s3c.h>
-#include <plat/regs-serial.h>
 #include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/sdhci.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index 150f55fb9e33..c85d1cbe769f 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
@@ -29,8 +30,6 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 
-#include <plat/regs-serial.h>
-
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 43261d24a0a5..c6a8b2ab0240 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
@@ -55,7 +56,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/gpio-samsung.h>
 #include <linux/platform_data/ata-samsung_cf.h>
diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c
index 3db0c98222f7..8c42807bf579 100644
--- a/arch/arm/mach-s3c64xx/s3c6400.c
+++ b/arch/arm/mach-s3c64xx/s3c6400.c
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 
@@ -34,7 +35,6 @@
 #include <asm/irq.h>
 
 #include <plat/cpu-freq.h>
-#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
index 72b2278953a8..5be3f09bac92 100644
--- a/arch/arm/mach-s3c64xx/s3c6410.c
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 
@@ -35,7 +36,6 @@
 #include <asm/irq.h>
 
 #include <plat/cpu-freq.h>
-#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c
index 42e14f2e7ca7..eb2ad14947f4 100644
--- a/arch/arm/mach-s5p64x0/common.c
+++ b/arch/arm/mach-s5p64x0/common.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <clocksource/samsung_pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
@@ -50,7 +51,6 @@
 #include <plat/gpio-cfg.h>
 #include <plat/pwm-core.h>
 #include <plat/regs-irqtype.h>
-#include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
index 5e2916fb19a9..8759e7882bcb 100644
--- a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
@@ -10,11 +10,10 @@
 
 /* pull in the relevant register and map files. */
 
+#include <linux/serial_s3c.h>
 #include <plat/map-base.h>
 #include <plat/map-s5p.h>
 
-#include <plat/regs-serial.h>
-
 	.macro addruart, rp, rv, tmp
 		mov	\rp, #0xE0000000
 		orr	\rp, \rp, #0x00100000
diff --git a/arch/arm/mach-s5p64x0/include/mach/timex.h b/arch/arm/mach-s5p64x0/include/mach/timex.h
deleted file mode 100644
index 4b91faa195a8..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/timex.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S5P64X0 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5p64x0/irq-pm.c b/arch/arm/mach-s5p64x0/irq-pm.c
index 3e6f2456ee9d..1c83d2899625 100644
--- a/arch/arm/mach-s5p64x0/irq-pm.c
+++ b/arch/arm/mach-s5p64x0/irq-pm.c
@@ -14,9 +14,9 @@
 
 #include <linux/syscore_ops.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
-#include <plat/regs-serial.h>
 #include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 9efdcc03df3b..6840e197cb2d 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index c3cacc067efe..fa1341c074ca 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c
index c5a8eeacf81c..6a41bf7dacf6 100644
--- a/arch/arm/mach-s5pc100/common.c
+++ b/arch/arm/mach-s5pc100/common.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <clocksource/samsung_pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
@@ -49,7 +50,6 @@
 #include <plat/onenand-core.h>
 #include <plat/pwm-core.h>
 #include <plat/spi-core.h>
-#include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
index 66cb7f16bf2a..22c23859e45e 100644
--- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
@@ -13,8 +13,8 @@
 
 /* pull in the relevant register and map files. */
 
+#include <linux/serial_s3c.h>
 #include <mach/map.h>
-#include <plat/regs-serial.h>
 
 	/* note, for the boot process to work we have to keep the UART
 	 * virtual address aligned to an 1MiB boundary for the L1
diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h
deleted file mode 100644
index 0af8e41230ed..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/tick.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/tick.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * S3C64XX - Timer tick support definitions
- *
- * Based on mach-s3c6400/include/mach/tick.h
- *
- * 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 __ASM_ARCH_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-#include <linux/irqchip/arm-vic.h>
-
-/* note, the timer interrutps turn up in 2 places, the vic and then
- * the timer block. We take the VIC as the base at the moment.
- */
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
-	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/timex.h b/arch/arm/mach-s5pc100/include/mach/timex.h
deleted file mode 100644
index 47ffb17aff96..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/timex.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/timex.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C6400 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 9e256b9fc930..668af3ac31f3 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -37,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
 
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c
index 26027a29b8a1..7024dcd0e40a 100644
--- a/arch/arm/mach-s5pv210/common.c
+++ b/arch/arm/mach-s5pv210/common.c
@@ -24,6 +24,7 @@
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <asm/proc-fns.h>
 #include <asm/mach/arch.h>
@@ -46,7 +47,6 @@
 #include <plat/pwm-core.h>
 #include <plat/tv-core.h>
 #include <plat/spi-core.h>
-#include <plat/regs-serial.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
index 80c21996c943..30b511a580aa 100644
--- a/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
@@ -12,8 +12,8 @@
 
 /* pull in the relevant register and map files. */
 
+#include <linux/serial_s3c.h>
 #include <mach/map.h>
-#include <plat/regs-serial.h>
 
 	/* note, for the boot process to work we have to keep the UART
 	 * virtual address aligned to an 1MiB boundary for the L1
diff --git a/arch/arm/mach-s5pv210/include/mach/timex.h b/arch/arm/mach-s5pv210/include/mach/timex.h
deleted file mode 100644
index 73dc85496a83..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/timex.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/timex.h
- *
- * Copyright (c) 2003-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/mach-s5p6442/include/mach/timex.h
- *
- * S5PV210 - time parameters
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H __FILE__
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index ad40ab0f5dbd..cc37edacda26 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/fb.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
@@ -32,7 +33,6 @@
 #include <mach/regs-clock.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb.h>
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index e5cd9fbf19e9..b41a38a75844 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/fb.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
@@ -39,7 +40,6 @@
 #include <mach/regs-clock.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb.h>
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 7c0ed07a78a3..448e1d2eeed6 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/i2c.h>
 #include <linux/device.h>
 
@@ -23,7 +24,6 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
-#include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/ata-samsung_cf.h>
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index f52cc15c2d85..2a6655fb63e7 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/device.h>
 #include <linux/dm9000.h>
 #include <linux/fb.h>
@@ -32,7 +33,6 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
-#include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
 #include <plat/gpio-cfg.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 579afe89842a..157805529f26 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -22,7 +23,6 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
-#include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 831a15824ec8..f9874ba60cc8 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -43,6 +43,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
+#include <asm/mach/irda.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/mach/sharpsl_param.h>
@@ -96,6 +97,37 @@ static struct mcp_plat_data collie_mcp_data = {
 	.codec_pdata	= &collie_ucb1x00_data,
 };
 
+static int collie_ir_startup(struct device *dev)
+{
+	int rc = gpio_request(COLLIE_GPIO_IR_ON, "IrDA");
+	if (rc)
+		return rc;
+	rc = gpio_direction_output(COLLIE_GPIO_IR_ON, 1);
+
+	if (!rc)
+		return 0;
+
+	gpio_free(COLLIE_GPIO_IR_ON);
+	return rc;
+}
+
+static void collie_ir_shutdown(struct device *dev)
+{
+	gpio_free(COLLIE_GPIO_IR_ON);
+}
+
+static int collie_ir_set_power(struct device *dev, unsigned int state)
+{
+	gpio_set_value(COLLIE_GPIO_IR_ON, !state);
+	return 0;
+}
+
+static struct irda_platform_data collie_ir_data = {
+	.startup = collie_ir_startup,
+	.shutdown = collie_ir_shutdown,
+	.set_power = collie_ir_set_power,
+};
+
 /*
  * Collie AC IN
  */
@@ -400,6 +432,7 @@ static void __init collie_init(void)
 	sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
 			    ARRAY_SIZE(collie_flash_resources));
 	sa11x0_register_mcp(&collie_mcp_data);
+	sa11x0_register_irda(&collie_ir_data);
 
 	sharpsl_save_param();
 }
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index daa27c474c13..3c43219bc881 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -122,15 +122,8 @@ static struct irda_platform_data h3100_irda_data = {
 	.shutdown	= h3100_irda_shutdown,
 };
 
-static struct gpio_default_state h3100_default_gpio[] = {
-	{ H3XXX_GPIO_COM_DCD,	GPIO_MODE_IN,	"COM DCD" },
-	{ H3XXX_GPIO_COM_CTS,	GPIO_MODE_IN,	"COM CTS" },
-	{ H3XXX_GPIO_COM_RTS,	GPIO_MODE_OUT0,	"COM RTS" },
-};
-
 static void __init h3100_mach_init(void)
 {
-	h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
 	h3xxx_mach_init();
 
 	sa11x0_register_lcd(&h3100_lcd_info);
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index a663e7230141..5be54c214c7c 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -130,15 +130,8 @@ static struct irda_platform_data h3600_irda_data = {
 	.shutdown	= h3600_irda_shutdown,
 };
 
-static struct gpio_default_state h3600_default_gpio[] = {
-	{ H3XXX_GPIO_COM_DCD,	GPIO_MODE_IN,	"COM DCD" },
-	{ H3XXX_GPIO_COM_CTS,	GPIO_MODE_IN,	"COM CTS" },
-	{ H3XXX_GPIO_COM_RTS,	GPIO_MODE_OUT0,	"COM RTS" },
-};
-
 static void __init h3600_mach_init(void)
 {
-	h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio));
 	h3xxx_mach_init();
 
 	sa11x0_register_lcd(&h3600_lcd_info);
diff --git a/arch/arm/mach-sa1100/h3xxx.c b/arch/arm/mach-sa1100/h3xxx.c
index f17e7382242a..c79bf467fb7f 100644
--- a/arch/arm/mach-sa1100/h3xxx.c
+++ b/arch/arm/mach-sa1100/h3xxx.c
@@ -28,37 +28,6 @@
 
 #include "generic.h"
 
-void h3xxx_init_gpio(struct gpio_default_state *s, size_t n)
-{
-	while (n--) {
-		const char *name = s->name;
-		int err;
-
-		if (!name)
-			name = "[init]";
-		err = gpio_request(s->gpio, name);
-		if (err) {
-			printk(KERN_ERR "gpio%u: unable to request: %d\n",
-				s->gpio, err);
-			continue;
-		}
-		if (s->mode >= 0) {
-			err = gpio_direction_output(s->gpio, s->mode);
-		} else {
-			err = gpio_direction_input(s->gpio);
-		}
-		if (err) {
-			printk(KERN_ERR "gpio%u: unable to set direction: %d\n",
-				s->gpio, err);
-			continue;
-		}
-		if (!s->name)
-			gpio_free(s->gpio);
-		s++;
-	}
-}
-
-
 /*
  * H3xxx flash support
  */
@@ -116,9 +85,34 @@ static struct resource h3xxx_flash_resource =
 /*
  * H3xxx uart support
  */
+static struct gpio h3xxx_uart_gpio[] = {
+	{ H3XXX_GPIO_COM_DCD,	GPIOF_IN,		"COM DCD" },
+	{ H3XXX_GPIO_COM_CTS,	GPIOF_IN,		"COM CTS" },
+	{ H3XXX_GPIO_COM_RTS,	GPIOF_OUT_INIT_LOW,	"COM RTS" },
+};
+
+static bool h3xxx_uart_request_gpios(void)
+{
+	static bool h3xxx_uart_gpio_ok;
+	int rc;
+
+	if (h3xxx_uart_gpio_ok)
+		return true;
+
+	rc = gpio_request_array(h3xxx_uart_gpio, ARRAY_SIZE(h3xxx_uart_gpio));
+	if (rc)
+		pr_err("h3xxx_uart_request_gpios: error %d\n", rc);
+	else
+		h3xxx_uart_gpio_ok = true;
+
+	return h3xxx_uart_gpio_ok;
+}
+
 static void h3xxx_uart_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 	if (port->mapbase == _Ser3UTCR0) {
+		if (!h3xxx_uart_request_gpios())
+			return;
 		gpio_set_value(H3XXX_GPIO_COM_RTS, !(mctrl & TIOCM_RTS));
 	}
 }
@@ -128,6 +122,8 @@ static u_int h3xxx_uart_get_mctrl(struct uart_port *port)
 	u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
 
 	if (port->mapbase == _Ser3UTCR0) {
+		if (!h3xxx_uart_request_gpios())
+			return ret;
 		/*
 		 * DCD and CTS bits are inverted in GPLR by RS232 transceiver
 		 */
diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h
index f33679d2d3ee..0ef22f9cda95 100644
--- a/arch/arm/mach-sa1100/include/mach/collie.h
+++ b/arch/arm/mach-sa1100/include/mach/collie.h
@@ -78,7 +78,7 @@ extern void locomolcd_power(int on);
 #define COLLIE_TC35143_GPIO_VERSION0    UCB_IO_0
 #define COLLIE_TC35143_GPIO_TBL_CHK     UCB_IO_1
 #define COLLIE_TC35143_GPIO_VPEN_ON     UCB_IO_2
-#define COLLIE_TC35143_GPIO_IR_ON       UCB_IO_3
+#define COLLIE_GPIO_IR_ON		(COLLIE_TC35143_GPIO_BASE + 3)
 #define COLLIE_TC35143_GPIO_AMP_ON      UCB_IO_4
 #define COLLIE_TC35143_GPIO_VERSION1    UCB_IO_5
 #define COLLIE_TC35143_GPIO_FS8KLPF     UCB_IO_5
diff --git a/arch/arm/mach-sa1100/include/mach/h3xxx.h b/arch/arm/mach-sa1100/include/mach/h3xxx.h
index c810620db53d..603d4343f7f6 100644
--- a/arch/arm/mach-sa1100/include/mach/h3xxx.h
+++ b/arch/arm/mach-sa1100/include/mach/h3xxx.h
@@ -79,17 +79,6 @@
 #define H3600_EGPIO_LCD_5V_ON		(H3XXX_EGPIO_BASE + 14) /* enable 5V to LCD. active high. */
 #define H3600_EGPIO_LVDD_ON		(H3XXX_EGPIO_BASE + 15) /* enable 9V and -6.5V to LCD. */
 
-struct gpio_default_state {
-	int gpio;
-	int mode;
-	const char *name;
-};
-
-#define GPIO_MODE_IN	-1
-#define GPIO_MODE_OUT0	0
-#define GPIO_MODE_OUT1	1
-
-void h3xxx_init_gpio(struct gpio_default_state *s, size_t n);
 void __init h3xxx_map_io(void);
 void __init h3xxx_mach_init(void);
 
diff --git a/arch/arm/mach-sa1100/include/mach/timex.h b/arch/arm/mach-sa1100/include/mach/timex.h
deleted file mode 100644
index 7a5d017b58b3..000000000000
--- a/arch/arm/mach-sa1100/include/mach/timex.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * arch/arm/mach-sa1100/include/mach/timex.h
- *
- * SA1100 architecture timex specifications
- *
- * Copyright (C) 1998 
- */
-
-/*
- * SA1100 timer
- */
-#define CLOCK_TICK_RATE		3686400
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 6fd4acb8f187..7aaac005e036 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -9,6 +9,7 @@
  *
  */
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -20,6 +21,9 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
+#define SA1100_CLOCK_FREQ 3686400
+#define SA1100_LATCH DIV_ROUND_CLOSEST(SA1100_CLOCK_FREQ, HZ)
+
 static u64 notrace sa1100_read_sched_clock(void)
 {
 	return readl_relaxed(OSCR);
@@ -93,7 +97,7 @@ static void sa1100_timer_resume(struct clock_event_device *cedev)
 	/*
 	 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
 	 */
-	writel_relaxed(OSMR0 - LATCH, OSCR);
+	writel_relaxed(OSMR0 - SA1100_LATCH, OSCR);
 }
 #else
 #define sa1100_timer_suspend NULL
@@ -128,7 +132,7 @@ void __init sa1100_timer_init(void)
 
 	setup_irq(IRQ_OST0, &sa1100_timer_irq);
 
-	clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
+	clocksource_mmio_init(OSCR, "oscr", SA1100_CLOCK_FREQ, 200, 32,
 		clocksource_mmio_readl_up);
 	clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400,
 					MIN_OSCR_DELTA * 2, 0x7fffffff);
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 05fa505df585..288cb85aebeb 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -5,18 +5,14 @@ config ARCH_SHMOBILE_MULTI
 	bool "Renesas ARM SoCs" if ARCH_MULTI_V7
 	depends on MMU
 	select ARCH_SHMOBILE
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select ARM_GIC
-	select MIGHT_HAVE_CACHE_L2X0
 	select MIGHT_HAVE_PCI
-	select NO_IOPORT
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+	select NO_IOPORT_MAP
 	select PINCTRL
 	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
 
 if ARCH_SHMOBILE_MULTI
 
@@ -45,15 +41,12 @@ config MACH_GENMAI
 config MACH_KOELSCH
 	bool "Koelsch board"
 	depends on ARCH_R8A7791
-
-config MACH_KZM9D
-	bool "KZM9D board"
-	depends on ARCH_EMEV2
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select MICREL_PHY if SH_ETH
 
 config MACH_LAGER
 	bool "Lager board"
 	depends on ARCH_R8A7790
+	select MICREL_PHY if SH_ETH
 
 comment "Renesas ARM SoCs System Configuration"
 endif
@@ -102,8 +95,6 @@ config ARCH_R8A7778
 	select CPU_V7
 	select SH_CLK_CPG
 	select ARM_GIC
-	select USB_ARCH_HAS_EHCI
-	select USB_ARCH_HAS_OHCI
 
 config ARCH_R8A7779
 	bool "R-Car H1 (R8A77790)"
@@ -111,8 +102,6 @@ config ARCH_R8A7779
 	select ARM_GIC
 	select CPU_V7
 	select SH_CLK_CPG
-	select USB_ARCH_HAS_EHCI
-	select USB_ARCH_HAS_OHCI
 	select RENESAS_INTC_IRQPIN
 
 config ARCH_R8A7790
@@ -123,6 +112,7 @@ config ARCH_R8A7790
 	select MIGHT_HAVE_PCI
 	select SH_CLK_CPG
 	select RENESAS_IRQC
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 
 config ARCH_R8A7791
 	bool "R-Car M2 (R8A77910)"
@@ -132,6 +122,7 @@ config ARCH_R8A7791
 	select MIGHT_HAVE_PCI
 	select SH_CLK_CPG
 	select RENESAS_IRQC
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 
 config ARCH_EMEV2
 	bool "Emma Mobile EV2"
@@ -154,11 +145,13 @@ comment "Renesas ARM SoCs Board Type"
 config MACH_APE6EVM
 	bool "APE6EVM board"
 	depends on ARCH_R8A73A4
+	select SMSC_PHY if SMSC911X
 	select USE_OF
 
 config MACH_APE6EVM_REFERENCE
 	bool "APE6EVM board - Reference Device Tree Implementation"
 	depends on ARCH_R8A73A4
+	select SMSC_PHY if SMSC911X
 	select USE_OF
 	---help---
 	   Use reference implementation of APE6EVM board support
@@ -172,6 +165,7 @@ config MACH_MACKEREL
 	depends on ARCH_SH7372
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select SMSC_PHY if SMSC911X
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 	select USE_OF
 
@@ -180,6 +174,7 @@ config MACH_ARMADILLO800EVA
 	depends on ARCH_R8A7740
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select SMSC_PHY if SH_ETH
 	select SND_SOC_WM8978 if SND_SIMPLE_CARD
 	select USE_OF
 
@@ -188,6 +183,7 @@ config MACH_ARMADILLO800EVA_REFERENCE
 	depends on ARCH_R8A7740
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select SMSC_PHY if SH_ETH
 	select SND_SOC_WM8978 if SND_SIMPLE_CARD
 	select USE_OF
 	---help---
@@ -201,11 +197,11 @@ config MACH_BOCKW
 	bool "BOCK-W platform"
 	depends on ARCH_R8A7778
 	select ARCH_REQUIRE_GPIOLIB
-	select RENESAS_INTC_IRQPIN
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	select USE_OF
+	select RENESAS_INTC_IRQPIN
 	select SND_SOC_AK4554 if SND_SIMPLE_CARD
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
+	select USE_OF
 
 config MACH_BOCKW_REFERENCE
 	bool "BOCK-W  - Reference Device Tree Implementation"
@@ -261,6 +257,8 @@ config MACH_LAGER
 	bool "Lager board"
 	depends on ARCH_R8A7790
 	select USE_OF
+	select MICREL_PHY if SH_ETH
+	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 
 config MACH_KOELSCH
 	bool "Koelsch board"
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index fe7d4ff706e4..4caffc912a81 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -52,13 +52,13 @@ obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o pm-rmobile.o
 obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
 obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o pm-rmobile.o
-obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o pm-rcar.o
+obj-$(CONFIG_ARCH_R8A7790)	+= pm-r8a7790.o pm-rcar.o
 
 # Board objects
 ifdef CONFIG_ARCH_SHMOBILE_MULTI
 obj-$(CONFIG_MACH_GENMAI)	+= board-genmai-reference.o
 obj-$(CONFIG_MACH_KOELSCH)	+= board-koelsch-reference.o
-obj-$(CONFIG_MACH_KZM9D)	+= board-kzm9d-reference.o
 obj-$(CONFIG_MACH_LAGER)	+= board-lager-reference.o
 else
 obj-$(CONFIG_MACH_APE6EVM)	+= board-ape6evm.o
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 93533e2710a8..4da3da7be3fa 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -383,6 +383,8 @@ static struct platform_device sh_eth_device = {
 	.id = -1,
 	.dev = {
 		.platform_data = &sh_eth_platdata,
+		.dma_mask = &sh_eth_device.dev.coherent_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
 	.resource = sh_eth_resources,
 	.num_resources = ARRAY_SIZE(sh_eth_resources),
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index c475220545f2..aaed215e96b9 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -1,9 +1,9 @@
 /*
  * Bock-W board support
  *
- * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013-2014  Renesas Solutions Corp.
  * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- * Copyright (C) 2013  Cogent Embedded, Inc.
+ * Copyright (C) 2013-2014  Cogent Embedded, 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
@@ -168,6 +168,8 @@ static struct renesas_usbhs_platform_info usbhs_info __initdata = {
 	},
 	.driver_param = {
 		.buswait_bwait	= 4,
+		.d0_tx_id	= HPBDMA_SLAVE_USBFUNC_TX,
+		.d1_rx_id	= HPBDMA_SLAVE_USBFUNC_RX,
 	},
 };
 
@@ -233,6 +235,17 @@ static struct sh_eth_plat_data ether_platform_data __initdata = {
 	.no_ether_link	= 1,
 };
 
+static struct platform_device_info ether_info __initdata = {
+	.parent		= &platform_bus,
+	.name		= "r8a777x-ether",
+	.id		= -1,
+	.res		= ether_resources,
+	.num_res	= ARRAY_SIZE(ether_resources),
+	.data		= &ether_platform_data,
+	.size_data	= sizeof(ether_platform_data),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
 /* I2C */
 static struct i2c_board_info i2c0_devices[] = {
 	{
@@ -332,16 +345,24 @@ 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, 0, gic_iid(0x85), RSND_SSI_PLAY),
-	RSND_SSI_SET(2, 0, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
-	RSND_SSI_SET(0, 0, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(0, 0, gic_iid(0x86), 0),
-	RSND_SSI_SET(3, 0, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(4, 0, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
+	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),
 };
 
 static struct rsnd_scu_platform_info rsnd_scu[9] = {
-	/* no member at this point */
+	{ .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, },
 };
 
 enum {
@@ -582,11 +603,7 @@ static void __init bockw_init(void)
 	r8a7778_init_irq_extpin(1);
 	r8a7778_add_standard_devices();
 
-	platform_device_register_resndata(&platform_bus, "r8a777x-ether", -1,
-					  ether_resources,
-					  ARRAY_SIZE(ether_resources),
-					  &ether_platform_data,
-					  sizeof(ether_platform_data));
+	platform_device_register_full(&ether_info);
 
 	platform_device_register_full(&vin0_info);
 	/* VIN1 has a pin conflict with Ether */
diff --git a/arch/arm/mach-shmobile/board-genmai.c b/arch/arm/mach-shmobile/board-genmai.c
index 3e92e3c62d4c..6c328d63b819 100644
--- a/arch/arm/mach-shmobile/board-genmai.c
+++ b/arch/arm/mach-shmobile/board-genmai.c
@@ -1,8 +1,9 @@
 /*
  * Genmai board support
  *
- * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013-2014  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
+ * Copyright (C) 2014  Cogent Embedded, 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
@@ -20,15 +21,87 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/sh_eth.h>
+#include <linux/spi/rspi.h>
+#include <linux/spi/spi.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/r7s72100.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+/* Ether */
+static const struct sh_eth_plat_data ether_pdata __initconst = {
+	.phy			= 0x00, /* PD60610 */
+	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
+	.phy_interface		= PHY_INTERFACE_MODE_MII,
+	.no_ether_link		= 1
+};
+
+static const struct resource ether_resources[] __initconst = {
+	DEFINE_RES_MEM(0xe8203000, 0x800),
+	DEFINE_RES_MEM(0xe8204800, 0x200),
+	DEFINE_RES_IRQ(gic_iid(359)),
+};
+
+static const struct platform_device_info ether_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "r7s72100-ether",
+	.id		= -1,
+	.res		= ether_resources,
+	.num_res	= ARRAY_SIZE(ether_resources),
+	.data		= &ether_pdata,
+	.size_data	= sizeof(ether_pdata),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
+/* RSPI */
+#define RSPI_RESOURCE(idx, baseaddr, irq)				\
+static const struct resource rspi##idx##_resources[] __initconst = {	\
+	DEFINE_RES_MEM(baseaddr, 0x24),					\
+	DEFINE_RES_IRQ_NAMED(irq, "error"),				\
+	DEFINE_RES_IRQ_NAMED(irq + 1, "rx"),				\
+	DEFINE_RES_IRQ_NAMED(irq + 2, "tx"),				\
+}
+
+RSPI_RESOURCE(0, 0xe800c800, gic_iid(270));
+RSPI_RESOURCE(1, 0xe800d000, gic_iid(273));
+RSPI_RESOURCE(2, 0xe800d800, gic_iid(276));
+RSPI_RESOURCE(3, 0xe800e000, gic_iid(279));
+RSPI_RESOURCE(4, 0xe800e800, gic_iid(282));
+
+static const struct rspi_plat_data rspi_pdata __initconst = {
+	.num_chipselect	= 1,
+};
+
+#define r7s72100_register_rspi(idx)					   \
+	platform_device_register_resndata(&platform_bus, "rspi-rz", idx,   \
+					rspi##idx##_resources,		   \
+					ARRAY_SIZE(rspi##idx##_resources), \
+					&rspi_pdata, sizeof(rspi_pdata))
+
+static const struct spi_board_info spi_info[] __initconst = {
+	{
+		.modalias               = "wm8978",
+		.max_speed_hz           = 5000000,
+		.bus_num                = 4,
+		.chip_select            = 0,
+	},
+};
+
 static void __init genmai_add_standard_devices(void)
 {
 	r7s72100_clock_init();
 	r7s72100_add_dt_devices();
+
+	platform_device_register_full(&ether_info);
+
+	r7s72100_register_rspi(0);
+	r7s72100_register_rspi(1);
+	r7s72100_register_rspi(2);
+	r7s72100_register_rspi(3);
+	r7s72100_register_rspi(4);
+	spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
 }
 
 static const char * const genmai_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index 652b59268416..a3fd30242bd8 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -21,46 +21,114 @@
 
 #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/common.h>
+#include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
 #include <mach/r8a7791.h>
 #include <asm/mach/arch.h>
 
+/* DU */
+static struct rcar_du_encoder_data koelsch_du_encoders[] = {
+	{
+		.type = RCAR_DU_ENCODER_NONE,
+		.output = RCAR_DU_OUTPUT_LVDS0,
+		.connector.lvds.panel = {
+			.width_mm = 210,
+			.height_mm = 158,
+			.mode = {
+				.clock = 65000,
+				.hdisplay = 1024,
+				.hsync_start = 1048,
+				.hsync_end = 1184,
+				.htotal = 1344,
+				.vdisplay = 768,
+				.vsync_start = 771,
+				.vsync_end = 777,
+				.vtotal = 806,
+				.flags = 0,
+			},
+		},
+	},
+};
+
+static struct rcar_du_platform_data koelsch_du_pdata = {
+	.encoders = koelsch_du_encoders,
+	.num_encoders = ARRAY_SIZE(koelsch_du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+	DEFINE_RES_MEM(0xfeb00000, 0x40000),
+	DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
+	DEFINE_RES_IRQ(gic_spi(256)),
+	DEFINE_RES_IRQ(gic_spi(268)),
+};
+
+static void __init koelsch_add_du_device(void)
+{
+	struct platform_device_info info = {
+		.name = "rcar-du-r8a7791",
+		.id = -1,
+		.res = du_resources,
+		.num_res = ARRAY_SIZE(du_resources),
+		.data = &koelsch_du_pdata,
+		.size_data = sizeof(koelsch_du_pdata),
+		.dma_mask = DMA_BIT_MASK(32),
+	};
+
+	platform_device_register_full(&info);
+}
+
 static void __init koelsch_add_standard_devices(void)
 {
-#ifdef CONFIG_COMMON_CLK
 	/*
-	 * This is a really crude hack to provide clkdev support to the SCIF
-	 * and CMT devices until they get moved to DT.
+	 * This is a really crude hack to provide clkdev support to the CMT and
+	 * DU devices until they get moved to DT.
 	 */
-	static const char * const scif_names[] = {
-		"scifa0", "scifa1", "scifb0", "scifb1", "scifb2", "scifa2",
-		"scif0", "scif1", "scif2", "scif3", "scif4", "scif5", "scifa3",
-		"scifa4", "scifa5",
+	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;
 
-	for (i = 0; i < ARRAY_SIZE(scif_names); ++i) {
-		clk = clk_get(NULL, scif_names[i]);
-		if (clk) {
-			clk_register_clkdev(clk, NULL, "sh-sci.%u", i);
+	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);
 		}
 	}
 
-	clk = clk_get(NULL, "cmt0");
-	if (clk) {
-		clk_register_clkdev(clk, NULL, "sh_cmt.0");
-		clk_put(clk);
-	}
-#else
-	r8a7791_clock_init();
-#endif
 	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	koelsch_add_du_device();
 }
 
 static const char * const koelsch_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
index de7cc64b1f37..5a034ff405d0 100644
--- a/arch/arm/mach-shmobile/board-koelsch.c
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -2,8 +2,9 @@
  * Koelsch board support
  *
  * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013-2014  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
+ * Copyright (C) 2014  Cogent Embedded, 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
@@ -23,14 +24,27 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/leds.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 #include <linux/phy.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/rcar-du.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/rspi.h>
+#include <linux/spi/spi.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7791.h>
@@ -92,6 +106,7 @@ static void __init koelsch_add_du_device(void)
 /* Ether */
 static const struct sh_eth_plat_data ether_pdata __initconst = {
 	.phy			= 0x1,
+	.phy_irq		= irq_pin(0),
 	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
 	.phy_interface		= PHY_INTERFACE_MODE_RMII,
 	.ether_link_active_low	= 1,
@@ -102,6 +117,17 @@ static const struct resource ether_resources[] __initconst = {
 	DEFINE_RES_IRQ(gic_spi(162)),
 };
 
+static const struct platform_device_info ether_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "r8a7791-ether",
+	.id		= -1,
+	.res		= ether_resources,
+	.num_res	= ARRAY_SIZE(ether_resources),
+	.data		= &ether_pdata,
+	.size_data	= sizeof(ether_pdata),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
 /* LEDS */
 static struct gpio_led koelsch_leds[] = {
 	{
@@ -148,6 +174,199 @@ static const struct gpio_keys_platform_data koelsch_keys_pdata __initconst = {
 	.nbuttons	= ARRAY_SIZE(gpio_buttons),
 };
 
+/* QSPI */
+static const struct resource qspi_resources[] __initconst = {
+	DEFINE_RES_MEM(0xe6b10000, 0x1000),
+	DEFINE_RES_IRQ_NAMED(gic_spi(184), "mux"),
+};
+
+static const struct rspi_plat_data qspi_pdata __initconst = {
+	.num_chipselect = 1,
+};
+
+/* SPI Flash memory (Spansion S25FL512SAGMFIG11 64 MiB) */
+static struct mtd_partition spi_flash_part[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "data",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static const struct flash_platform_data spi_flash_data = {
+	.name		= "m25p80",
+	.parts		= spi_flash_part,
+	.nr_parts	= ARRAY_SIZE(spi_flash_part),
+	.type		= "s25fl512s",
+};
+
+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,
+	},
+};
+
+/* SATA0 */
+static const struct resource sata0_resources[] __initconst = {
+	DEFINE_RES_MEM(0xee300000, 0x2000),
+	DEFINE_RES_IRQ(gic_spi(105)),
+};
+
+static const struct platform_device_info sata0_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "sata-r8a7791",
+	.id		= 0,
+	.res		= sata0_resources,
+	.num_res	= ARRAY_SIZE(sata0_resources),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
+/* I2C */
+static const struct resource i2c_resources[] __initconst = {
+	/* I2C0 */
+	DEFINE_RES_MEM(0xE6508000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(287)),
+	/* I2C1 */
+	DEFINE_RES_MEM(0xE6518000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(288)),
+	/* I2C2 */
+	DEFINE_RES_MEM(0xE6530000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(286)),
+	/* I2C3 */
+	DEFINE_RES_MEM(0xE6540000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(290)),
+	/* I2C4 */
+	DEFINE_RES_MEM(0xE6520000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(19)),
+	/* I2C5 */
+	DEFINE_RES_MEM(0xE6528000, 0x40),
+	DEFINE_RES_IRQ(gic_spi(20)),
+};
+
+static void __init koelsch_add_i2c(unsigned idx)
+{
+	unsigned res_idx = idx * 2;
+
+	BUG_ON(res_idx >= ARRAY_SIZE(i2c_resources));
+
+	platform_device_register_simple("i2c-rcar_gen2", idx,
+					i2c_resources + res_idx, 2);
+}
+
+#define SDHI_REGULATOR(idx, vdd_pin, vccq_pin)				\
+static struct regulator_consumer_supply vcc_sdhi##idx##_consumer =	\
+	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi." #idx);		\
+									\
+static struct regulator_init_data vcc_sdhi##idx##_init_data = {		\
+	.constraints = {						\
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,		\
+	},								\
+	.consumer_supplies	= &vcc_sdhi##idx##_consumer,		\
+	.num_consumer_supplies	= 1,					\
+};									\
+									\
+static const struct fixed_voltage_config vcc_sdhi##idx##_info __initconst = {\
+	.supply_name	= "SDHI" #idx "Vcc",				\
+	.microvolts	= 3300000,					\
+	.gpio		= vdd_pin,					\
+	.enable_high	= 1,						\
+	.init_data	= &vcc_sdhi##idx##_init_data,			\
+};									\
+									\
+static struct regulator_consumer_supply vccq_sdhi##idx##_consumer =	\
+	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi." #idx);		\
+									\
+static struct regulator_init_data vccq_sdhi##idx##_init_data = {	\
+	.constraints = {						\
+		.input_uV	= 3300000,				\
+		.min_uV		= 1800000,				\
+		.max_uV		= 3300000,				\
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |		\
+				  REGULATOR_CHANGE_STATUS,		\
+	},								\
+	.consumer_supplies	= &vccq_sdhi##idx##_consumer,		\
+	.num_consumer_supplies	= 1,					\
+};									\
+									\
+static struct gpio vccq_sdhi##idx##_gpio =				\
+	{ vccq_pin, GPIOF_OUT_INIT_HIGH, "vccq-sdhi" #idx };		\
+									\
+static struct gpio_regulator_state vccq_sdhi##idx##_states[] = {	\
+	{ .value = 1800000, .gpios = 0 },				\
+	{ .value = 3300000, .gpios = 1 },				\
+};									\
+									\
+static const struct gpio_regulator_config vccq_sdhi##idx##_info __initconst = {\
+	.supply_name	= "vqmmc",					\
+	.gpios		= &vccq_sdhi##idx##_gpio,			\
+	.nr_gpios	= 1,						\
+	.states		= vccq_sdhi##idx##_states,			\
+	.nr_states	= ARRAY_SIZE(vccq_sdhi##idx##_states),		\
+	.type		= REGULATOR_VOLTAGE,				\
+	.init_data	= &vccq_sdhi##idx##_init_data,			\
+};
+
+SDHI_REGULATOR(0, RCAR_GP_PIN(7, 17), RCAR_GP_PIN(2, 12));
+SDHI_REGULATOR(1, RCAR_GP_PIN(7, 18), RCAR_GP_PIN(2, 13));
+SDHI_REGULATOR(2, RCAR_GP_PIN(7, 19), RCAR_GP_PIN(2, 26));
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_caps2	= MMC_CAP2_NO_MULTI_READ,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee100000, 0x200),
+	DEFINE_RES_IRQ(gic_spi(165)),
+};
+
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info __initdata = {
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_caps2	= MMC_CAP2_NO_MULTI_READ,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi1_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee140000, 0x100),
+	DEFINE_RES_IRQ(gic_spi(167)),
+};
+
+/* SDHI2 */
+static struct sh_mobile_sdhi_info sdhi2_info __initdata = {
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_caps2	= MMC_CAP2_NO_MULTI_READ,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
+			  TMIO_MMC_WRPROTECT_DISABLE,
+};
+
+static struct resource sdhi2_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee160000, 0x100),
+	DEFINE_RES_IRQ(gic_spi(168)),
+};
+
 static const struct pinctrl_map koelsch_pinctrl_map[] = {
 	/* DU */
 	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7791", "pfc-r8a7791",
@@ -165,12 +384,51 @@ static const struct pinctrl_map koelsch_pinctrl_map[] = {
 				  "eth_rmii", "eth"),
 	PIN_MAP_MUX_GROUP_DEFAULT("r8a7791-ether", "pfc-r8a7791",
 				  "intc_irq0", "intc"),
+	/* QSPI */
+	PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7791",
+				  "qspi_ctrl", "qspi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7791",
+				  "qspi_data4", "qspi"),
 	/* SCIF0 (CN19: DEBUG SERIAL0) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7791",
 				  "scif0_data_d", "scif0"),
 	/* SCIF1 (CN20: DEBUG SERIAL1) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7791",
 				  "scif1_data_d", "scif1"),
+	/* I2C1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.1", "pfc-r8a7791",
+				  "i2c1_e", "i2c1"),
+	/* I2C2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.2", "pfc-r8a7791",
+				  "i2c2", "i2c2"),
+	/* I2C4 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.4", "pfc-r8a7791",
+				  "i2c4_c", "i2c4"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
+				  "sdhi1_ctrl", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
+				  "sdhi1_cd", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
+				  "sdhi1_wp", "sdhi1"),
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
+				  "sdhi2_data4", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
+				  "sdhi2_ctrl", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
+				  "sdhi2_cd", "sdhi2"),
 };
 
 static void __init koelsch_add_standard_devices(void)
@@ -180,18 +438,53 @@ static void __init koelsch_add_standard_devices(void)
 				  ARRAY_SIZE(koelsch_pinctrl_map));
 	r8a7791_pinmux_init();
 	r8a7791_add_standard_devices();
-	platform_device_register_resndata(&platform_bus, "r8a7791-ether", -1,
-					  ether_resources,
-					  ARRAY_SIZE(ether_resources),
-					  &ether_pdata, sizeof(ether_pdata));
+	platform_device_register_full(&ether_info);
 	platform_device_register_data(&platform_bus, "leds-gpio", -1,
 				      &koelsch_leds_pdata,
 				      sizeof(koelsch_leds_pdata));
 	platform_device_register_data(&platform_bus, "gpio-keys", -1,
 				      &koelsch_keys_pdata,
 				      sizeof(koelsch_keys_pdata));
+	platform_device_register_resndata(&platform_bus, "qspi", 0,
+					  qspi_resources,
+					  ARRAY_SIZE(qspi_resources),
+					  &qspi_pdata, sizeof(qspi_pdata));
+	spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
 
 	koelsch_add_du_device();
+
+	platform_device_register_full(&sata0_info);
+
+	koelsch_add_i2c(1);
+	koelsch_add_i2c(2);
+	koelsch_add_i2c(4);
+	koelsch_add_i2c(5);
+
+	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 0,
+				      &vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
+	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 1,
+				      &vcc_sdhi1_info, sizeof(struct fixed_voltage_config));
+	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+				      &vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
+	platform_device_register_data(&platform_bus, "gpio-regulator", 0,
+				      &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
+	platform_device_register_data(&platform_bus, "gpio-regulator", 1,
+				      &vccq_sdhi1_info, sizeof(struct gpio_regulator_config));
+	platform_device_register_data(&platform_bus, "gpio-regulator", 2,
+				      &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
+
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
+					  &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
+
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
+					  &sdhi1_info, sizeof(struct sh_mobile_sdhi_info));
+
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+					  sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
+					  &sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
+
 }
 
 /*
@@ -215,6 +508,8 @@ static void __init koelsch_init(void)
 {
 	koelsch_add_standard_devices();
 
+	irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW);
+
 	if (IS_ENABLED(CONFIG_PHYLIB))
 		phy_register_fixup_for_id("r8a7791-ether-ff:01",
 					  koelsch_ksz8041_fixup);
diff --git a/arch/arm/mach-shmobile/board-kzm9d-reference.c b/arch/arm/mach-shmobile/board-kzm9d-reference.c
deleted file mode 100644
index 054d8d5c8fc1..000000000000
--- a/arch/arm/mach-shmobile/board-kzm9d-reference.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * kzm9d board support - Reference DT implementation
- *
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  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/of_platform.h>
-#include <mach/emev2.h>
-#include <mach/common.h>
-#include <asm/mach/arch.h>
-
-static void __init kzm9d_add_standard_devices(void)
-{
-	if (!IS_ENABLED(CONFIG_COMMON_CLK))
-		emev2_clock_init();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *kzm9d_boards_compat_dt[] __initdata = {
-	"renesas,kzm9d",
-	"renesas,kzm9d-reference",
-	NULL,
-};
-
-DT_MACHINE_START(KZM9D_DT, "kzm9d")
-	.smp		= smp_ops(emev2_smp_ops),
-	.map_io		= emev2_map_io,
-	.init_early	= emev2_init_delay,
-	.init_machine	= kzm9d_add_standard_devices,
-	.init_late	= shmobile_init_late,
-	.dt_compat	= kzm9d_boards_compat_dt,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index a6e271d92af0..440aac36d693 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -20,47 +20,116 @@
 
 #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/common.h>
+#include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
 #include <mach/r8a7790.h>
 #include <asm/mach/arch.h>
 
+/* DU */
+static struct rcar_du_encoder_data lager_du_encoders[] = {
+	{
+		.type = RCAR_DU_ENCODER_VGA,
+		.output = RCAR_DU_OUTPUT_DPAD0,
+	}, {
+		.type = RCAR_DU_ENCODER_NONE,
+		.output = RCAR_DU_OUTPUT_LVDS1,
+		.connector.lvds.panel = {
+			.width_mm = 210,
+			.height_mm = 158,
+			.mode = {
+				.clock = 65000,
+				.hdisplay = 1024,
+				.hsync_start = 1048,
+				.hsync_end = 1184,
+				.htotal = 1344,
+				.vdisplay = 768,
+				.vsync_start = 771,
+				.vsync_end = 777,
+				.vtotal = 806,
+				.flags = 0,
+			},
+		},
+	},
+};
+
+static struct rcar_du_platform_data lager_du_pdata = {
+	.encoders = lager_du_encoders,
+	.num_encoders = ARRAY_SIZE(lager_du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+	DEFINE_RES_MEM(0xfeb00000, 0x70000),
+	DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
+	DEFINE_RES_MEM_NAMED(0xfeb94000, 0x1c, "lvds.1"),
+	DEFINE_RES_IRQ(gic_spi(256)),
+	DEFINE_RES_IRQ(gic_spi(268)),
+	DEFINE_RES_IRQ(gic_spi(269)),
+};
+
+static void __init lager_add_du_device(void)
+{
+	struct platform_device_info info = {
+		.name = "rcar-du-r8a7790",
+		.id = -1,
+		.res = du_resources,
+		.num_res = ARRAY_SIZE(du_resources),
+		.data = &lager_du_pdata,
+		.size_data = sizeof(lager_du_pdata),
+		.dma_mask = DMA_BIT_MASK(32),
+	};
+
+	platform_device_register_full(&info);
+}
+
 static void __init lager_add_standard_devices(void)
 {
-#ifdef CONFIG_COMMON_CLK
 	/*
-	 * This is a really crude hack to provide clkdev support to the SCIF
-	 * and CMT devices until they get moved to DT.
+	 * This is a really crude hack to provide clkdev support to platform
+	 * devices until they get moved to DT.
 	 */
-	static const char * const scif_names[] = {
-		"scifa0", "scifa1", "scifb0", "scifb1",
-		"scifb2", "scifa2", "scif0", "scif1",
-		"hscif0", "hscif1",
+	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;
 
-	for (i = 0; i < ARRAY_SIZE(scif_names); ++i) {
-		clk = clk_get(NULL, scif_names[i]);
-		if (clk) {
-			clk_register_clkdev(clk, NULL, "sh-sci.%u", i);
+	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);
 		}
 	}
 
-	clk = clk_get(NULL, "cmt0");
-	if (clk) {
-		clk_register_clkdev(clk, NULL, "sh_cmt.0");
-		clk_put(clk);
-	}
-#else
-	r8a7790_clock_init();
-#endif
-
 	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	lager_add_du_device();
 }
 
 static const char *lager_boards_compat_dt[] __initdata = {
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f20c10a18543..f0104bfe544e 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -1,8 +1,9 @@
 /*
  * Lager board support
  *
- * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013-2014  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
+ * Copyright (C) 2014  Cogent Embedded, 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
@@ -20,15 +21,21 @@
 
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
+#include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/leds.h>
+#include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/camera-rcar.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/rcar-du.h>
+#include <linux/platform_data/usb-rcar-gen2-phy.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/regulator/driver.h>
@@ -36,9 +43,12 @@
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/renesas_usbhs.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7790.h>
+#include <media/soc_camera.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <linux/mtd/partitions.h>
@@ -46,6 +56,33 @@
 #include <linux/spi/flash.h>
 #include <linux/spi/rspi.h>
 #include <linux/spi/spi.h>
+#include <sound/rcar_snd.h>
+#include <sound/simple_card.h>
+
+/*
+ * SSI-AK4643
+ *
+ * SW1: 1: AK4643
+ *      2: CN22
+ *      3: ADV7511
+ *
+ * this command is required when playback.
+ *
+ * # amixer set "LINEOUT Mixer DACL" on
+ */
+
+/*
+ * SDHI0 (CN8)
+ *
+ * JP3:  pin1
+ * SW20: pin1
+
+ * GP5_24:	1:  VDD  3.3V (defult)
+ *		0:  VDD  0.0V
+ * GP5_29:	1:  VccQ 3.3V (defult)
+ *		0:  VccQ 1.8V
+ *
+ */
 
 /* DU */
 static struct rcar_du_encoder_data lager_du_encoders[] = {
@@ -228,6 +265,7 @@ static const struct resource mmcif1_resources[] __initconst = {
 /* Ether */
 static const struct sh_eth_plat_data ether_pdata __initconst = {
 	.phy			= 0x1,
+	.phy_irq		= irq_pin(0),
 	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
 	.phy_interface		= PHY_INTERFACE_MODE_RMII,
 	.ether_link_active_low	= 1,
@@ -238,6 +276,17 @@ static const struct resource ether_resources[] __initconst = {
 	DEFINE_RES_IRQ(gic_spi(162)),
 };
 
+static const struct platform_device_info ether_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "r8a7790-ether",
+	.id		= -1,
+	.res		= ether_resources,
+	.num_res	= ARRAY_SIZE(ether_resources),
+	.data		= &ether_pdata,
+	.size_data	= sizeof(ether_pdata),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
 /* SPI Flash memory (Spansion S25FL512SAGMFIG11 64Mb) */
 static struct mtd_partition spi_flash_part[] = {
 	/* Reserved for user loader program, read-only */
@@ -263,7 +312,7 @@ static struct mtd_partition spi_flash_part[] = {
 	},
 };
 
-static struct flash_platform_data spi_flash_data = {
+static const struct flash_platform_data spi_flash_data = {
 	.name           = "m25p80",
 	.parts          = spi_flash_part,
 	.nr_parts       = ARRAY_SIZE(spi_flash_part),
@@ -288,9 +337,361 @@ static const struct spi_board_info spi_info[] __initconst = {
 /* QSPI resource */
 static const struct resource qspi_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe6b10000, 0x1000),
-	DEFINE_RES_IRQ(gic_spi(184)),
+	DEFINE_RES_IRQ_NAMED(gic_spi(184), "mux"),
+};
+
+/* VIN */
+static const struct resource vin_resources[] __initconst = {
+	/* VIN0 */
+	DEFINE_RES_MEM(0xe6ef0000, 0x1000),
+	DEFINE_RES_IRQ(gic_spi(188)),
+	/* VIN1 */
+	DEFINE_RES_MEM(0xe6ef1000, 0x1000),
+	DEFINE_RES_IRQ(gic_spi(189)),
+};
+
+static void __init lager_add_vin_device(unsigned idx,
+					struct rcar_vin_platform_data *pdata)
+{
+	struct platform_device_info vin_info = {
+		.parent		= &platform_bus,
+		.name		= "r8a7790-vin",
+		.id		= idx,
+		.res		= &vin_resources[idx * 2],
+		.num_res	= 2,
+		.dma_mask	= DMA_BIT_MASK(32),
+		.data		= pdata,
+		.size_data	= sizeof(*pdata),
+	};
+
+	BUG_ON(idx > 1);
+
+	platform_device_register_full(&vin_info);
+}
+
+#define LAGER_CAMERA(idx, name, addr, pdata, flag)			\
+static struct i2c_board_info i2c_cam##idx##_device = {			\
+	I2C_BOARD_INFO(name, addr),					\
+};									\
+									\
+static struct rcar_vin_platform_data vin##idx##_pdata = {		\
+	.flags = flag,							\
+};									\
+									\
+static struct soc_camera_link cam##idx##_link = {			\
+	.bus_id = idx,							\
+	.board_info = &i2c_cam##idx##_device,				\
+	.i2c_adapter_id = 2,						\
+	.module_name = name,						\
+	.priv = pdata,							\
+}
+
+/* Camera 0 is not currently supported due to adv7612 support missing */
+LAGER_CAMERA(1, "adv7180", 0x20, NULL, RCAR_VIN_BT656);
+
+static void __init lager_add_camera1_device(void)
+{
+	platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+				      &cam1_link, sizeof(cam1_link));
+	lager_add_vin_device(1, &vin1_pdata);
+}
+
+/* SATA1 */
+static const struct resource sata1_resources[] __initconst = {
+	DEFINE_RES_MEM(0xee500000, 0x2000),
+	DEFINE_RES_IRQ(gic_spi(106)),
+};
+
+static const struct platform_device_info sata1_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "sata-r8a7790",
+	.id		= 1,
+	.res		= sata1_resources,
+	.num_res	= ARRAY_SIZE(sata1_resources),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
+/* USBHS */
+static const struct resource usbhs_resources[] __initconst = {
+	DEFINE_RES_MEM(0xe6590000, 0x100),
+	DEFINE_RES_IRQ(gic_spi(107)),
+};
+
+struct usbhs_private {
+	struct renesas_usbhs_platform_info info;
+	struct usb_phy *phy;
+};
+
+#define usbhs_get_priv(pdev) \
+	container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info)
+
+static int usbhs_power_ctrl(struct platform_device *pdev,
+				void __iomem *base, int enable)
+{
+	struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+	if (!priv->phy)
+		return -ENODEV;
+
+	if (enable) {
+		int retval = usb_phy_init(priv->phy);
+
+		if (!retval)
+			retval = usb_phy_set_suspend(priv->phy, 0);
+		return retval;
+	}
+
+	usb_phy_set_suspend(priv->phy, 1);
+	usb_phy_shutdown(priv->phy);
+	return 0;
+}
+
+static int usbhs_hardware_init(struct platform_device *pdev)
+{
+	struct usbhs_private *priv = usbhs_get_priv(pdev);
+	struct usb_phy *phy;
+	int ret;
+
+	/* USB0 Function - use PWEN as GPIO input to detect DIP Switch SW5
+	 * setting to avoid VBUS short circuit due to wrong cable.
+	 * PWEN should be pulled up high if USB Function is selected by SW5
+	 */
+	gpio_request_one(RCAR_GP_PIN(5, 18), GPIOF_IN, NULL); /* USB0_PWEN */
+	if (!gpio_get_value(RCAR_GP_PIN(5, 18))) {
+		pr_warn("Error: USB Function not selected - check SW5 + SW6\n");
+		ret = -ENOTSUPP;
+		goto error;
+	}
+
+	phy = usb_get_phy_dev(&pdev->dev, 0);
+	if (IS_ERR(phy)) {
+		ret = PTR_ERR(phy);
+		goto error;
+	}
+
+	priv->phy = phy;
+	return 0;
+ error:
+	gpio_free(RCAR_GP_PIN(5, 18));
+	return ret;
+}
+
+static int usbhs_hardware_exit(struct platform_device *pdev)
+{
+	struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+	if (!priv->phy)
+		return 0;
+
+	usb_put_phy(priv->phy);
+	priv->phy = NULL;
+
+	gpio_free(RCAR_GP_PIN(5, 18));
+	return 0;
+}
+
+static int usbhs_get_id(struct platform_device *pdev)
+{
+	return USBHS_GADGET;
+}
+
+static u32 lager_usbhs_pipe_type[] = {
+	USB_ENDPOINT_XFER_CONTROL,
+	USB_ENDPOINT_XFER_ISOC,
+	USB_ENDPOINT_XFER_ISOC,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_INT,
+	USB_ENDPOINT_XFER_INT,
+	USB_ENDPOINT_XFER_INT,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
+	USB_ENDPOINT_XFER_BULK,
 };
 
+static struct usbhs_private usbhs_priv __initdata = {
+	.info = {
+		.platform_callback = {
+			.power_ctrl	= usbhs_power_ctrl,
+			.hardware_init	= usbhs_hardware_init,
+			.hardware_exit	= usbhs_hardware_exit,
+			.get_id		= usbhs_get_id,
+		},
+		.driver_param = {
+			.buswait_bwait	= 4,
+			.pipe_type = lager_usbhs_pipe_type,
+			.pipe_size = ARRAY_SIZE(lager_usbhs_pipe_type),
+		},
+	}
+};
+
+static void __init lager_register_usbhs(void)
+{
+	usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
+	platform_device_register_resndata(&platform_bus,
+					  "renesas_usbhs", -1,
+					  usbhs_resources,
+					  ARRAY_SIZE(usbhs_resources),
+					  &usbhs_priv.info,
+					  sizeof(usbhs_priv.info));
+}
+
+/* USBHS PHY */
+static const struct rcar_gen2_phy_platform_data usbhs_phy_pdata __initconst = {
+	.chan0_pci = 0,	/* Channel 0 is USBHS */
+	.chan2_pci = 1,	/* Channel 2 is PCI USB */
+};
+
+static const struct resource usbhs_phy_resources[] __initconst = {
+	DEFINE_RES_MEM(0xe6590100, 0x100),
+};
+
+/* I2C */
+static struct i2c_board_info i2c2_devices[] = {
+	{
+		I2C_BOARD_INFO("ak4643", 0x12),
+	}
+};
+
+/* Sound */
+static struct resource rsnd_resources[] __initdata = {
+	[RSND_GEN2_SCU]  = DEFINE_RES_MEM(0xec500000, 0x1000),
+	[RSND_GEN2_ADG]  = DEFINE_RES_MEM(0xec5a0000, 0x100),
+	[RSND_GEN2_SSIU] = DEFINE_RES_MEM(0xec540000, 0x1000),
+	[RSND_GEN2_SSI]  = DEFINE_RES_MEM(0xec541000, 0x1280),
+};
+
+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),
+};
+
+static struct rsnd_scu_platform_info rsnd_scu[2] = {
+	/* no member at this point */
+};
+
+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),
+};
+
+static struct asoc_simple_card_info rsnd_card_info = {
+	.name		= "AK4643",
+	.card		= "SSI01-AK4643",
+	.codec		= "ak4642-codec.2-0012",
+	.platform	= "rcar_sound",
+	.daifmt		= SND_SOC_DAIFMT_LEFT_J,
+	.cpu_dai = {
+		.name	= "rcar_sound",
+		.fmt	= SND_SOC_DAIFMT_CBS_CFS,
+	},
+	.codec_dai = {
+		.name	= "ak4642-hifi",
+		.fmt	= SND_SOC_DAIFMT_CBM_CFM,
+		.sysclk	= 11289600,
+	},
+};
+
+static void __init lager_add_rsnd_device(void)
+{
+	struct platform_device_info cardinfo = {
+		.parent         = &platform_bus,
+		.name           = "asoc-simple-card",
+		.id             = -1,
+		.data           = &rsnd_card_info,
+		.size_data      = sizeof(struct asoc_simple_card_info),
+		.dma_mask       = DMA_BIT_MASK(32),
+	};
+
+	i2c_register_board_info(2, i2c2_devices,
+				ARRAY_SIZE(i2c2_devices));
+
+	platform_device_register_resndata(
+		&platform_bus, "rcar_sound", -1,
+		rsnd_resources, ARRAY_SIZE(rsnd_resources),
+		&rsnd_info, sizeof(rsnd_info));
+
+	platform_device_register_full(&cardinfo);
+}
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_caps2	= MMC_CAP2_NO_MULTI_READ,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
+			  TMIO_MMC_WRPROTECT_DISABLE,
+};
+
+static struct resource sdhi0_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee100000, 0x200),
+	DEFINE_RES_IRQ(gic_spi(165)),
+};
+
+/* SDHI2 */
+static struct sh_mobile_sdhi_info sdhi2_info __initdata = {
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_caps2	= MMC_CAP2_NO_MULTI_READ,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
+			  TMIO_MMC_WRPROTECT_DISABLE,
+};
+
+static struct resource sdhi2_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee140000, 0x100),
+	DEFINE_RES_IRQ(gic_spi(167)),
+};
+
+/* Internal PCI1 */
+static const struct resource pci1_resources[] __initconst = {
+	DEFINE_RES_MEM(0xee0b0000, 0x10000),	/* CFG */
+	DEFINE_RES_MEM(0xee0a0000, 0x10000),	/* MEM */
+	DEFINE_RES_IRQ(gic_spi(112)),
+};
+
+static const struct platform_device_info pci1_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "pci-rcar-gen2",
+	.id		= 1,
+	.res		= pci1_resources,
+	.num_res	= ARRAY_SIZE(pci1_resources),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
+static void __init lager_add_usb1_device(void)
+{
+	platform_device_register_full(&pci1_info);
+}
+
+/* Internal PCI2 */
+static const struct resource pci2_resources[] __initconst = {
+	DEFINE_RES_MEM(0xee0d0000, 0x10000),	/* CFG */
+	DEFINE_RES_MEM(0xee0c0000, 0x10000),	/* MEM */
+	DEFINE_RES_IRQ(gic_spi(113)),
+};
+
+static const struct platform_device_info pci2_info __initconst = {
+	.parent		= &platform_bus,
+	.name		= "pci-rcar-gen2",
+	.id		= 2,
+	.res		= pci2_resources,
+	.num_res	= ARRAY_SIZE(pci2_resources),
+	.dma_mask	= DMA_BIT_MASK(32),
+};
+
+static void __init lager_add_usb2_device(void)
+{
+	platform_device_register_full(&pci2_info);
+}
+
 static const struct pinctrl_map lager_pinctrl_map[] = {
 	/* DU (CN10: ARGB0, CN13: LVDS) */
 	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
@@ -299,12 +700,43 @@ static const struct pinctrl_map lager_pinctrl_map[] = {
 				  "du_sync_1", "du"),
 	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
 				  "du_clk_out_0", "du"),
+	/* I2C2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar.2", "pfc-r8a7790",
+				  "i2c2", "i2c2"),
+	/* QSPI */
+	PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790",
+				  "qspi_ctrl", "qspi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790",
+				  "qspi_data4", "qspi"),
 	/* SCIF0 (CN19: DEBUG SERIAL0) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790",
 				  "scif0_data", "scif0"),
 	/* SCIF1 (CN20: DEBUG SERIAL1) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790",
 				  "scif1_data", "scif1"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790",
+				  "sdhi0_cd", "sdhi0"),
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790",
+				  "sdhi2_data4", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790",
+				  "sdhi2_ctrl", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790",
+				  "sdhi2_cd", "sdhi2"),
+	/* SSI (CN17: sound) */
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790",
+				  "ssi0129_ctrl", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790",
+				  "ssi0_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790",
+				  "ssi1_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790",
+				  "audio_clk_a", "audio_clk"),
 	/* MMCIF1 */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790",
 				  "mmc1_data8", "mmc1"),
@@ -319,6 +751,31 @@ static const struct pinctrl_map lager_pinctrl_map[] = {
 				  "eth_rmii", "eth"),
 	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790",
 				  "intc_irq0", "intc"),
+	/* VIN0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790",
+				  "vin0_data24", "vin0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790",
+				  "vin0_sync", "vin0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790",
+				  "vin0_field", "vin0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790",
+				  "vin0_clkenb", "vin0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790",
+				  "vin0_clk", "vin0"),
+	/* VIN1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790",
+				  "vin1_data8", "vin1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790",
+				  "vin1_clk", "vin1"),
+	/* USB0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7790",
+				  "usb0_ovc_vbus", "usb0"),
+	/* USB1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.1", "pfc-r8a7790",
+				  "usb1", "usb1"),
+	/* USB2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.2", "pfc-r8a7790",
+				  "usb2", "usb2"),
 };
 
 static void __init lager_add_standard_devices(void)
@@ -346,10 +803,7 @@ static void __init lager_add_standard_devices(void)
 					  mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
 					  &mmcif1_pdata, sizeof(mmcif1_pdata));
 
-	platform_device_register_resndata(&platform_bus, "r8a7790-ether", -1,
-					  ether_resources,
-					  ARRAY_SIZE(ether_resources),
-					  &ether_pdata, sizeof(ether_pdata));
+	platform_device_register_full(&ether_info);
 
 	lager_add_du_device();
 
@@ -368,6 +822,28 @@ static void __init lager_add_standard_devices(void)
 				      &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
 	platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
 				      &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
+
+	lager_add_camera1_device();
+
+	platform_device_register_full(&sata1_info);
+
+	platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
+					  -1, usbhs_phy_resources,
+					  ARRAY_SIZE(usbhs_phy_resources),
+					  &usbhs_phy_pdata,
+					  sizeof(usbhs_phy_pdata));
+	lager_register_usbhs();
+	lager_add_usb1_device();
+	lager_add_usb2_device();
+
+	lager_add_rsnd_device();
+
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
+					  &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+					  sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
+					  &sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
 }
 
 /*
@@ -391,6 +867,8 @@ static void __init lager_init(void)
 {
 	lager_add_standard_devices();
 
+	irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW);
+
 	if (IS_ENABLED(CONFIG_PHYLIB))
 		phy_register_fixup_for_id("r8a7790-ether-ff:01",
 					  lager_ksz8041_fixup);
diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c
index e6ab0cd5b286..f17a5db00221 100644
--- a/arch/arm/mach-shmobile/clock-r7s72100.c
+++ b/arch/arm/mach-shmobile/clock-r7s72100.c
@@ -22,12 +22,15 @@
 #include <mach/common.h>
 #include <mach/r7s72100.h>
 
-/* registers */
+/* Frequency Control Registers */
 #define FRQCR		0xfcfe0010
 #define FRQCR2		0xfcfe0014
+/* Standby Control Registers */
 #define STBCR3		0xfcfe0420
 #define STBCR4		0xfcfe0424
+#define STBCR7		0xfcfe0430
 #define STBCR9		0xfcfe0438
+#define STBCR10		0xfcfe043c
 
 #define PLL_RATE 30
 
@@ -145,15 +148,25 @@ struct clk div4_clks[DIV4_NR] = {
 					| CLK_ENABLE_ON_INIT),
 };
 
-enum {	MSTP97, MSTP96, MSTP95, MSTP94,
+enum {
+	MSTP107, MSTP106, MSTP105, MSTP104, MSTP103,
+	MSTP97, MSTP96, MSTP95, MSTP94,
+	MSTP74,
 	MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
-	MSTP33,	MSTP_NR };
+	MSTP33,	MSTP_NR
+};
 
 static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP107] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 7, 0), /* RSPI0 */
+	[MSTP106] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 6, 0), /* RSPI1 */
+	[MSTP105] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 5, 0), /* RSPI2 */
+	[MSTP104] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 4, 0), /* RSPI3 */
+	[MSTP103] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 3, 0), /* RSPI4 */
 	[MSTP97] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 7, 0), /* RIIC0 */
 	[MSTP96] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 6, 0), /* RIIC1 */
 	[MSTP95] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 5, 0), /* RIIC2 */
 	[MSTP94] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 4, 0), /* RIIC3 */
+	[MSTP74] = SH_CLK_MSTP8(&peripheral1_clk, STBCR7, 4, 0), /* Ether */
 	[MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
 	[MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
 	[MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
@@ -176,6 +189,21 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
 	/* MSTP clocks */
+	CLKDEV_DEV_ID("rspi-rz.0", &mstp_clks[MSTP107]),
+	CLKDEV_DEV_ID("rspi-rz.1", &mstp_clks[MSTP106]),
+	CLKDEV_DEV_ID("rspi-rz.2", &mstp_clks[MSTP105]),
+	CLKDEV_DEV_ID("rspi-rz.3", &mstp_clks[MSTP104]),
+	CLKDEV_DEV_ID("rspi-rz.4", &mstp_clks[MSTP103]),
+	CLKDEV_DEV_ID("e800c800.spi", &mstp_clks[MSTP107]),
+	CLKDEV_DEV_ID("e800d000.spi", &mstp_clks[MSTP106]),
+	CLKDEV_DEV_ID("e800d800.spi", &mstp_clks[MSTP105]),
+	CLKDEV_DEV_ID("e800e000.spi", &mstp_clks[MSTP104]),
+	CLKDEV_DEV_ID("e800e800.spi", &mstp_clks[MSTP103]),
+	CLKDEV_DEV_ID("fcfee000.i2c", &mstp_clks[MSTP97]),
+	CLKDEV_DEV_ID("fcfee400.i2c", &mstp_clks[MSTP96]),
+	CLKDEV_DEV_ID("fcfee800.i2c", &mstp_clks[MSTP95]),
+	CLKDEV_DEV_ID("fcfeec00.i2c", &mstp_clks[MSTP94]),
+	CLKDEV_DEV_ID("r7s72100-ether", &mstp_clks[MSTP74]),
 	CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]),
 
 	/* ICK */
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index 9783945f8bc7..2009a9bc6356 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -221,6 +221,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
 	CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
 
+	CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a),
+	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", &s1_clk),
 	CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
 	CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
 	CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index f1fb89b76786..8e403ae0c7b2 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -47,17 +47,10 @@
 
 #define MD(nr)	BIT(nr)
 
-#define FRQMR		IOMEM(0xffc80014)
 #define MSTPCR0		IOMEM(0xffc80030)
 #define MSTPCR1		IOMEM(0xffc80034)
 #define MSTPCR3		IOMEM(0xffc8003c)
 #define MSTPSR1		IOMEM(0xffc80044)
-#define MSTPSR4		IOMEM(0xffc80048)
-#define MSTPSR6		IOMEM(0xffc8004c)
-#define MSTPCR4		IOMEM(0xffc80050)
-#define MSTPCR5		IOMEM(0xffc80054)
-#define MSTPCR6		IOMEM(0xffc80058)
-#define MSTPCR7		IOMEM(0xffc80040)
 
 #define MODEMR		0xffcc0020
 
@@ -127,16 +120,16 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */
 	[MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */
 	[MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */
-	[MSTP120] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 20, 0), /* VIN3 */
-	[MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */
-	[MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */
-	[MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */
-	[MSTP110] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 10, 0), /* VIN0 */
-	[MSTP109] = SH_CLK_MSTP32(&clks_clk, MSTPCR1,  9, 0), /* VIN1 */
-	[MSTP108] = SH_CLK_MSTP32(&clks_clk, MSTPCR1,  8, 0), /* VIN2 */
-	[MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1,  3, 0), /* DU */
-	[MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1,  1, 0), /* USB2 */
-	[MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1,  0, 0), /* USB0/1 */
+	[MSTP120] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 20, MSTPSR1, 0), /* VIN3 */
+	[MSTP116] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 16, MSTPSR1, 0), /* PCIe */
+	[MSTP115] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 15, MSTPSR1, 0), /* SATA */
+	[MSTP114] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 14, MSTPSR1, 0), /* Ether */
+	[MSTP110] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 10, MSTPSR1, 0), /* VIN0 */
+	[MSTP109] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  9, MSTPSR1, 0), /* VIN1 */
+	[MSTP108] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  8, MSTPSR1, 0), /* VIN2 */
+	[MSTP103] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  3, MSTPSR1, 0), /* DU */
+	[MSTP101] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1,  1, MSTPSR1, 0), /* USB2 */
+	[MSTP100] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1,  0, MSTPSR1, 0), /* USB0/1 */
 	[MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */
 	[MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */
 	[MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index f44987a92ad4..3f93503f5b96 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -43,17 +43,26 @@
  *	see "p1 / 2" on R8A7790_CLOCK_ROOT() below
  */
 
-#define CPG_BASE 0xe6150000
-#define CPG_LEN 0x1000
-
-#define SMSTPCR1 0xe6150134
-#define SMSTPCR2 0xe6150138
-#define SMSTPCR3 0xe615013c
-#define SMSTPCR5 0xe6150144
-#define SMSTPCR7 0xe615014c
-#define SMSTPCR8 0xe6150990
-#define SMSTPCR9 0xe6150994
-#define SMSTPCR10 0xe6150998
+#define CPG_BASE	0xe6150000
+#define CPG_LEN		0x1000
+
+#define SMSTPCR1	0xe6150134
+#define SMSTPCR2	0xe6150138
+#define SMSTPCR3	0xe615013c
+#define SMSTPCR5	0xe6150144
+#define SMSTPCR7	0xe615014c
+#define SMSTPCR8	0xe6150990
+#define SMSTPCR9	0xe6150994
+#define SMSTPCR10	0xe6150998
+
+#define MSTPSR1		IOMEM(0xe6150038)
+#define MSTPSR2		IOMEM(0xe6150040)
+#define MSTPSR3		IOMEM(0xe6150048)
+#define MSTPSR5		IOMEM(0xe615003c)
+#define MSTPSR7		IOMEM(0xe61501c4)
+#define MSTPSR8		IOMEM(0xe61509a0)
+#define MSTPSR9		IOMEM(0xe61509a4)
+#define MSTPSR10	IOMEM(0xe61509a8)
 
 #define SDCKCR		0xE6150074
 #define SD2CKCR		0xE6150078
@@ -82,6 +91,15 @@ static struct clk main_clk = {
 	.ops	= &followparent_clk_ops,
 };
 
+static struct clk audio_clk_a = {
+};
+
+static struct clk audio_clk_b = {
+};
+
+static struct clk audio_clk_c = {
+};
+
 /*
  * clock ratio of these clock will be updated
  * on r8a7790_clock_init()
@@ -115,6 +133,9 @@ SH_FIXED_RATIO_CLK_SET(ddr_clk,			pll3_clk,	1, 8);
 SH_FIXED_RATIO_CLK_SET(mp_clk,			pll1_div2_clk,	1, 15);
 
 static struct clk *main_clks[] = {
+	&audio_clk_a,
+	&audio_clk_b,
+	&audio_clk_c,
 	&extal_clk,
 	&extal_div2_clk,
 	&main_clk,
@@ -183,15 +204,22 @@ static struct clk div6_clks[DIV6_NR] = {
 
 /* MSTP */
 enum {
+	MSTP1017, /* parent of SCU */
+
+	MSTP1031, MSTP1030,
+	MSTP1029, MSTP1028, MSTP1027, MSTP1026, MSTP1025, MSTP1024, MSTP1023, MSTP1022,
 	MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010,
 	MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005,
 	MSTP931, MSTP930, MSTP929, MSTP928,
 	MSTP917,
+	MSTP815, MSTP814,
 	MSTP813,
+	MSTP811, MSTP810, MSTP809, MSTP808,
 	MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720,
 	MSTP717, MSTP716,
-	MSTP704,
+	MSTP704, MSTP703,
 	MSTP522,
+	MSTP502, MSTP501,
 	MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
 	MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
 	MSTP124,
@@ -199,53 +227,77 @@ enum {
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP1015] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 15, 0), /* SSI0 */
-	[MSTP1014] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 14, 0), /* SSI1 */
-	[MSTP1013] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 13, 0), /* SSI2 */
-	[MSTP1012] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 12, 0), /* SSI3 */
-	[MSTP1011] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 11, 0), /* SSI4 */
-	[MSTP1010] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 10, 0), /* SSI5 */
-	[MSTP1009] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  9, 0), /* SSI6 */
-	[MSTP1008] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  8, 0), /* SSI7 */
-	[MSTP1007] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  7, 0), /* SSI8 */
-	[MSTP1006] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  6, 0), /* SSI9 */
-	[MSTP1005] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  5, 0), /* SSI ALL */
-	[MSTP931] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 31, 0), /* I2C0 */
-	[MSTP930] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 30, 0), /* I2C1 */
-	[MSTP929] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 29, 0), /* I2C2 */
-	[MSTP928] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 28, 0), /* I2C3 */
-	[MSTP917] = SH_CLK_MSTP32(&qspi_clk, SMSTPCR9, 17, 0), /* QSPI */
-	[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
-	[MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
-	[MSTP725] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 25, 0), /* LVDS1 */
-	[MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */
-	[MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */
-	[MSTP722] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 22, 0), /* DU2 */
-	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
-	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
-	[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
-	[MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
-	[MSTP704] = SH_CLK_MSTP32(&mp_clk, SMSTPCR7, 4, 0), /* HSUSB */
-	[MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
-	[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */
-	[MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */
-	[MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_SD1], SMSTPCR3, 13, 0), /* SDHI1 */
-	[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SD2], SMSTPCR3, 12, 0), /* SDHI2 */
-	[MSTP311] = SH_CLK_MSTP32(&div6_clks[DIV6_SD3], SMSTPCR3, 11, 0), /* SDHI3 */
-	[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, 0), /* MMC1 */
-	[MSTP304] = SH_CLK_MSTP32(&cp_clk, SMSTPCR3, 4, 0), /* TPU0 */
-	[MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
-	[MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
-	[MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
-	[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
-	[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
-	[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
-	[MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
+	[MSTP1031] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 31, MSTPSR10, 0), /* SCU0 */
+	[MSTP1030] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 30, MSTPSR10, 0), /* SCU1 */
+	[MSTP1029] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 29, MSTPSR10, 0), /* SCU2 */
+	[MSTP1028] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 28, MSTPSR10, 0), /* SCU3 */
+	[MSTP1027] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 27, MSTPSR10, 0), /* SCU4 */
+	[MSTP1026] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 26, MSTPSR10, 0), /* SCU5 */
+	[MSTP1025] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 25, MSTPSR10, 0), /* SCU6 */
+	[MSTP1024] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 24, MSTPSR10, 0), /* SCU7 */
+	[MSTP1023] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 23, MSTPSR10, 0), /* SCU8 */
+	[MSTP1022] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 22, MSTPSR10, 0), /* SCU9 */
+	[MSTP1017] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 17, MSTPSR10, 0), /* SCU */
+	[MSTP1015] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 15, MSTPSR10, 0), /* SSI0 */
+	[MSTP1014] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 14, MSTPSR10, 0), /* SSI1 */
+	[MSTP1013] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 13, MSTPSR10, 0), /* SSI2 */
+	[MSTP1012] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 12, MSTPSR10, 0), /* SSI3 */
+	[MSTP1011] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 11, MSTPSR10, 0), /* SSI4 */
+	[MSTP1010] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 10, MSTPSR10, 0), /* SSI5 */
+	[MSTP1009] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 9, MSTPSR10, 0), /* SSI6 */
+	[MSTP1008] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 8, MSTPSR10, 0), /* SSI7 */
+	[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 */
+	[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 */
+	[MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */
+	[MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */
+	[MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */
+	[MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8,  9, MSTPSR8, 0), /* VIN2 */
+	[MSTP808] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8,  8, MSTPSR8, 0), /* VIN3 */
+	[MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */
+	[MSTP725] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 25, MSTPSR7, 0), /* LVDS1 */
+	[MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */
+	[MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */
+	[MSTP722] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 22, MSTPSR7, 0), /* DU2 */
+	[MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */
+	[MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */
+	[MSTP717] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 17, MSTPSR7, 0), /* HSCIF0 */
+	[MSTP716] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 16, MSTPSR7, 0), /* HSCIF1 */
+	[MSTP704] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 4, MSTPSR7, 0), /* HSUSB */
+	[MSTP703] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 3, MSTPSR7, 0), /* EHCI */
+	[MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */
+	[MSTP502] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 2, MSTPSR5, 0), /* Audio-DMAC low */
+	[MSTP501] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 1, MSTPSR5, 0), /* Audio-DMAC hi */
+	[MSTP315] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, MSTPSR3, 0), /* MMC0 */
+	[MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */
+	[MSTP313] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD1], SMSTPCR3, 13, MSTPSR3, 0), /* SDHI1 */
+	[MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI2 */
+	[MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD3], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI3 */
+	[MSTP305] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, MSTPSR3, 0), /* MMC1 */
+	[MSTP304] = SH_CLK_MSTP32_STS(&cp_clk, SMSTPCR3, 4, MSTPSR3, 0), /* TPU0 */
+	[MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */
+	[MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */
+	[MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */
+	[MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */
+	[MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */
+	[MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */
 };
 
 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),
@@ -291,32 +343,32 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
 	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
 	CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
-	CLKDEV_DEV_ID("e6508000.i2c", &mstp_clks[MSTP931]),
 	CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]),
-	CLKDEV_DEV_ID("e6518000.i2c", &mstp_clks[MSTP930]),
 	CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]),
-	CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]),
 	CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]),
-	CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]),
 	CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]),
 	CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]),
-	CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
+	CLKDEV_DEV_ID("r8a7790-vin.0", &mstp_clks[MSTP811]),
+	CLKDEV_DEV_ID("r8a7790-vin.1", &mstp_clks[MSTP810]),
+	CLKDEV_DEV_ID("r8a7790-vin.2", &mstp_clks[MSTP809]),
+	CLKDEV_DEV_ID("r8a7790-vin.3", &mstp_clks[MSTP808]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
-	CLKDEV_DEV_ID("ee200000.mmc", &mstp_clks[MSTP315]),
+	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP502]),
+	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP501]),
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
-	CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-	CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-	CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP312]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
-	CLKDEV_DEV_ID("ee160000.sd", &mstp_clks[MSTP311]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
-	CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
 	CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
 	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]),
+	CLKDEV_DEV_ID("pci-rcar-gen2.0", &mstp_clks[MSTP703]),
+	CLKDEV_DEV_ID("pci-rcar-gen2.1", &mstp_clks[MSTP703]),
+	CLKDEV_DEV_ID("pci-rcar-gen2.2", &mstp_clks[MSTP703]),
+	CLKDEV_DEV_ID("sata-r8a7790.0", &mstp_clks[MSTP815]),
+	CLKDEV_DEV_ID("sata-r8a7790.1", &mstp_clks[MSTP814]),
 
 	/* ICK */
 	CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]),
@@ -325,6 +377,20 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]),
 	CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]),
 	CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]),
+	CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a),
+	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("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 f5461262ee25..605fc778e3e2 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -59,10 +59,19 @@
 #define SMSTPCR10	0xE6150998
 #define SMSTPCR11	0xE615099C
 
+#define MSTPSR1		IOMEM(0xe6150038)
+#define MSTPSR2		IOMEM(0xe6150040)
+#define MSTPSR3		IOMEM(0xe6150048)
+#define MSTPSR5		IOMEM(0xe615003c)
+#define MSTPSR7		IOMEM(0xe61501c4)
+#define MSTPSR8		IOMEM(0xe61509a0)
+#define MSTPSR9		IOMEM(0xe61509a4)
+#define MSTPSR11	IOMEM(0xe61509ac)
+
 #define MODEMR		0xE6160060
 #define SDCKCR		0xE6150074
-#define SD2CKCR		0xE6150078
-#define SD3CKCR		0xE615007C
+#define SD1CKCR		0xE6150078
+#define SD2CKCR		0xE615026c
 #define MMC0CKCR	0xE6150240
 #define MMC1CKCR	0xE6150244
 #define SSPCKCR		0xE6150248
@@ -93,6 +102,7 @@ static struct clk main_clk = {
  */
 SH_FIXED_RATIO_CLK_SET(pll1_clk,		main_clk,	1, 1);
 SH_FIXED_RATIO_CLK_SET(pll3_clk,		main_clk,	1, 1);
+SH_FIXED_RATIO_CLK_SET(qspi_clk,		pll1_clk,	1, 1);
 
 /* fixed ratio clock */
 SH_FIXED_RATIO_CLK_SET(extal_div2_clk,		extal_clk,	1, 2);
@@ -103,7 +113,9 @@ SH_FIXED_RATIO_CLK_SET(hp_clk,			pll1_clk,	1, 12);
 SH_FIXED_RATIO_CLK_SET(p_clk,			pll1_clk,	1, 24);
 SH_FIXED_RATIO_CLK_SET(rclk_clk,		pll1_clk,	1, (48 * 1024));
 SH_FIXED_RATIO_CLK_SET(mp_clk,			pll1_div2_clk,	1, 15);
+SH_FIXED_RATIO_CLK_SET(zg_clk,			pll1_clk,	1, 3);
 SH_FIXED_RATIO_CLK_SET(zx_clk,			pll1_clk,	1, 3);
+SH_FIXED_RATIO_CLK_SET(zs_clk,			pll1_clk,	1, 6);
 
 static struct clk *main_clks[] = {
 	&extal_clk,
@@ -114,18 +126,59 @@ static struct clk *main_clks[] = {
 	&pll3_clk,
 	&hp_clk,
 	&p_clk,
+	&qspi_clk,
 	&rclk_clk,
 	&mp_clk,
 	&cp_clk,
+	&zg_clk,
 	&zx_clk,
+	&zs_clk,
+};
+
+/* SDHI (DIV4) clock */
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
+enum {
+	DIV4_SDH, DIV4_SD0,
+	DIV4_NR
+};
+
+static struct clk div4_clks[DIV4_NR] = {
+	[DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
+	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
+};
+
+/* DIV6 clocks */
+enum {
+	DIV6_SD1, DIV6_SD2,
+	DIV6_NR
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+	[DIV6_SD1]	= SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
+	[DIV6_SD2]	= SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
 };
 
 /* MSTP */
 enum {
+	MSTP931, MSTP930, MSTP929, MSTP928, MSTP927, MSTP925,
+	MSTP917,
+	MSTP815, MSTP814,
 	MSTP813,
+	MSTP811, MSTP810, MSTP809,
 	MSTP726, MSTP724, MSTP723, MSTP721, MSTP720,
 	MSTP719, MSTP718, MSTP715, MSTP714,
 	MSTP522,
+	MSTP314, MSTP312, MSTP311,
 	MSTP216, MSTP207, MSTP206,
 	MSTP204, MSTP203, MSTP202, MSTP1105, MSTP1106, MSTP1107,
 	MSTP124,
@@ -133,27 +186,42 @@ enum {
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
-	[MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
-	[MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */
-	[MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */
-	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
-	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
-	[MSTP719] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 19, 0), /* SCIF2 */
-	[MSTP718] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 18, 0), /* SCIF3 */
-	[MSTP715] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 15, 0), /* SCIF4 */
-	[MSTP714] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 14, 0), /* SCIF5 */
-	[MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
-	[MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
-	[MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
-	[MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
-	[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
-	[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
-	[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
-	[MSTP1105] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 5, 0), /* SCIFA3 */
-	[MSTP1106] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 6, 0), /* SCIFA4 */
-	[MSTP1107] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 7, 0), /* SCIFA5 */
-	[MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
+	[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 */
+	[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 */
+	[MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */
+	[MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */
+	[MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */
+	[MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */
+	[MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */
+	[MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */
+	[MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */
+	[MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */
+	[MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */
+	[MSTP719] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 19, MSTPSR7, 0), /* SCIF2 */
+	[MSTP718] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 18, MSTPSR7, 0), /* SCIF3 */
+	[MSTP715] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 15, MSTPSR7, 0), /* SCIF4 */
+	[MSTP714] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 14, MSTPSR7, 0), /* SCIF5 */
+	[MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */
+	[MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */
+	[MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD1], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI1 */
+	[MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI2 */
+	[MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */
+	[MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */
+	[MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */
+	[MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */
+	[MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */
+	[MSTP1105] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 5, MSTPSR11, 0), /* SCIFA3 */
+	[MSTP1106] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 6, MSTPSR11, 0), /* SCIFA4 */
+	[MSTP1107] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 7, MSTPSR11, 0), /* SCIFA5 */
+	[MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */
 };
 
 static struct clk_lookup lookups[] = {
@@ -165,8 +233,11 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("pll1",		&pll1_clk),
 	CLKDEV_CON_ID("pll1_div2",	&pll1_div2_clk),
 	CLKDEV_CON_ID("pll3",		&pll3_clk),
+	CLKDEV_CON_ID("zg",		&zg_clk),
+	CLKDEV_CON_ID("zs",		&zs_clk),
 	CLKDEV_CON_ID("hp",		&hp_clk),
 	CLKDEV_CON_ID("p",		&p_clk),
+	CLKDEV_CON_ID("qspi",		&qspi_clk),
 	CLKDEV_CON_ID("rclk",		&rclk_clk),
 	CLKDEV_CON_ID("mp",		&mp_clk),
 	CLKDEV_CON_ID("cp",		&cp_clk),
@@ -191,10 +262,24 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1105]), /* SCIFA3 */
 	CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1106]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1107]), /* SCIFA5 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
+	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP312]),
+	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]),
 	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
-	CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
+	CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.4", &mstp_clks[MSTP927]),
+	CLKDEV_DEV_ID("i2c-rcar_gen2.5", &mstp_clks[MSTP925]),
 	CLKDEV_DEV_ID("r8a7791-ether", &mstp_clks[MSTP813]), /* Ether */
+	CLKDEV_DEV_ID("r8a7791-vin.0", &mstp_clks[MSTP811]),
+	CLKDEV_DEV_ID("r8a7791-vin.1", &mstp_clks[MSTP810]),
+	CLKDEV_DEV_ID("r8a7791-vin.2", &mstp_clks[MSTP809]),
+	CLKDEV_DEV_ID("sata-r8a7791.0", &mstp_clks[MSTP815]),
+	CLKDEV_DEV_ID("sata-r8a7791.1", &mstp_clks[MSTP814]),
 };
 
 #define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31)		\
@@ -232,10 +317,21 @@ void __init r8a7791_clock_init(void)
 		break;
 	}
 
+	if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2))
+		SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16);
+	else
+		SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20);
+
 	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 		ret = clk_register(main_clks[k]);
 
 	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+	if (!ret)
 		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index e31980590eb4..cb8e32deb2a3 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -25,7 +25,6 @@ extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
 					    struct task_struct *idle);
 extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
 extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
-extern void shmobile_invalidate_start(void);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
diff --git a/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt b/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt
new file mode 100644
index 000000000000..9531f46a822a
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt
@@ -0,0 +1,410 @@
+LIST "KZM9G low-level initialization routine."
+LIST "Adapted from u-boot KZM9G support code."
+
+LIST "Copyright (C) 2013 Ulrich Hecht"
+
+LIST "This program is free software; you can redistribute it and/or modify"
+LIST "it under the terms of the GNU General Public License version 2 as"
+LIST "published by the Free Software Foundation."
+
+LIST "This program is distributed in the hope that it will be useful,"
+LIST "but WITHOUT ANY WARRANTY; without even the implied warranty of"
+LIST "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
+LIST "GNU General Public License for more details."
+
+
+LIST "Register definitions:"
+
+LIST "Secure control register"
+#define LIFEC_SEC_SRC (0xE6110008)
+
+LIST "RWDT"
+#define RWDT_BASE   (0xE6020000)
+#define RWTCSRA0 (RWDT_BASE + 0x04)
+
+LIST "HPB Semaphore Control Registers"
+#define HPBSCR_BASE (0xE6000000)
+#define HPBCTRL6 (HPBSCR_BASE + 0x1030)
+
+#define SBSC1_BASE  (0xFE400000)
+#define SDCR0A		(SBSC1_BASE + 0x0008)
+#define SDCR1A		(SBSC1_BASE + 0x000C)
+#define SDPCRA		(SBSC1_BASE + 0x0010)
+#define SDCR0SA		(SBSC1_BASE + 0x0018)
+#define SDCR1SA		(SBSC1_BASE + 0x001C)
+#define RTCSRA		(SBSC1_BASE + 0x0020)
+#define RTCORA		(SBSC1_BASE + 0x0028)
+#define RTCORHA		(SBSC1_BASE + 0x002C)
+#define SDWCRC0A	(SBSC1_BASE + 0x0040)
+#define SDWCRC1A	(SBSC1_BASE + 0x0044)
+#define SDWCR00A	(SBSC1_BASE + 0x0048)
+#define SDWCR01A	(SBSC1_BASE + 0x004C)
+#define SDWCR10A	(SBSC1_BASE + 0x0050)
+#define SDWCR11A	(SBSC1_BASE + 0x0054)
+#define SDWCR2A		(SBSC1_BASE + 0x0060)
+#define SDWCRC2A	(SBSC1_BASE + 0x0064)
+#define ZQCCRA		(SBSC1_BASE + 0x0068)
+#define SDMRACR0A	(SBSC1_BASE + 0x0084)
+#define SDMRTMPCRA	(SBSC1_BASE + 0x008C)
+#define SDMRTMPMSKA	(SBSC1_BASE + 0x0094)
+#define SDGENCNTA	(SBSC1_BASE + 0x009C)
+#define SDDRVCR0A	(SBSC1_BASE + 0x00B4)
+#define DLLCNT0A	(SBSC1_BASE + 0x0354)
+
+#define SDMRA1  (0xFE500000)
+#define SDMRA2  (0xFE5C0000)
+#define SDMRA3  (0xFE504000)
+
+#define SBSC2_BASE  (0xFB400000)
+#define SDCR0B		(SBSC2_BASE + 0x0008)
+#define SDCR1B		(SBSC2_BASE + 0x000C)
+#define SDPCRB		(SBSC2_BASE + 0x0010)
+#define SDCR0SB		(SBSC2_BASE + 0x0018)
+#define SDCR1SB		(SBSC2_BASE + 0x001C)
+#define RTCSRB		(SBSC2_BASE + 0x0020)
+#define RTCORB		(SBSC2_BASE + 0x0028)
+#define RTCORHB		(SBSC2_BASE + 0x002C)
+#define SDWCRC0B	(SBSC2_BASE + 0x0040)
+#define SDWCRC1B	(SBSC2_BASE + 0x0044)
+#define SDWCR00B	(SBSC2_BASE + 0x0048)
+#define SDWCR01B	(SBSC2_BASE + 0x004C)
+#define SDWCR10B	(SBSC2_BASE + 0x0050)
+#define SDWCR11B	(SBSC2_BASE + 0x0054)
+#define SDPDCR0B	(SBSC2_BASE + 0x0058)
+#define SDWCR2B		(SBSC2_BASE + 0x0060)
+#define SDWCRC2B	(SBSC2_BASE + 0x0064)
+#define ZQCCRB		(SBSC2_BASE + 0x0068)
+#define SDMRACR0B	(SBSC2_BASE + 0x0084)
+#define SDMRTMPCRB	(SBSC2_BASE + 0x008C)
+#define SDMRTMPMSKB	(SBSC2_BASE + 0x0094)
+#define SDGENCNTB	(SBSC2_BASE + 0x009C)
+#define DPHYCNT0B	(SBSC2_BASE + 0x00A0)
+#define DPHYCNT1B	(SBSC2_BASE + 0x00A4)
+#define DPHYCNT2B	(SBSC2_BASE + 0x00A8)
+#define SDDRVCR0B	(SBSC2_BASE + 0x00B4)
+#define DLLCNT0B	(SBSC2_BASE + 0x0354)
+
+#define SDMRB1  (0xFB500000)
+#define SDMRB2  (0xFB5C0000)
+#define SDMRB3  (0xFB504000)
+
+#define CPG_BASE   (0xE6150000)
+#define FRQCRA		(CPG_BASE + 0x0000)
+#define FRQCRB		(CPG_BASE + 0x0004)
+#define FRQCRD		(CPG_BASE + 0x00E4)
+#define VCLKCR1		(CPG_BASE + 0x0008)
+#define VCLKCR2		(CPG_BASE + 0x000C)
+#define VCLKCR3		(CPG_BASE + 0x001C)
+#define ZBCKCR		(CPG_BASE + 0x0010)
+#define FLCKCR		(CPG_BASE + 0x0014)
+#define SD0CKCR		(CPG_BASE + 0x0074)
+#define SD1CKCR		(CPG_BASE + 0x0078)
+#define SD2CKCR		(CPG_BASE + 0x007C)
+#define FSIACKCR	(CPG_BASE + 0x0018)
+#define SUBCKCR		(CPG_BASE + 0x0080)
+#define SPUACKCR	(CPG_BASE + 0x0084)
+#define SPUVCKCR	(CPG_BASE + 0x0094)
+#define MSUCKCR		(CPG_BASE + 0x0088)
+#define HSICKCR		(CPG_BASE + 0x008C)
+#define FSIBCKCR	(CPG_BASE + 0x0090)
+#define MFCK1CR		(CPG_BASE + 0x0098)
+#define MFCK2CR		(CPG_BASE + 0x009C)
+#define DSITCKCR	(CPG_BASE + 0x0060)
+#define DSI0PCKCR	(CPG_BASE + 0x0064)
+#define DSI1PCKCR	(CPG_BASE + 0x0068)
+#define DSI0PHYCR	(CPG_BASE + 0x006C)
+#define DVFSCR3		(CPG_BASE + 0x0174)
+#define DVFSCR4		(CPG_BASE + 0x0178)
+#define DVFSCR5		(CPG_BASE + 0x017C)
+#define MPMODE		(CPG_BASE + 0x00CC)
+
+#define PLLECR		(CPG_BASE + 0x00D0)
+#define PLL0CR		(CPG_BASE + 0x00D8)
+#define PLL1CR		(CPG_BASE + 0x0028)
+#define PLL2CR		(CPG_BASE + 0x002C)
+#define PLL3CR		(CPG_BASE + 0x00DC)
+#define PLL0STPCR	(CPG_BASE + 0x00F0)
+#define PLL1STPCR	(CPG_BASE + 0x00C8)
+#define PLL2STPCR	(CPG_BASE + 0x00F8)
+#define PLL3STPCR	(CPG_BASE + 0x00FC)
+#define RMSTPCR0	(CPG_BASE + 0x0110)
+#define RMSTPCR1	(CPG_BASE + 0x0114)
+#define RMSTPCR2	(CPG_BASE + 0x0118)
+#define RMSTPCR3	(CPG_BASE + 0x011C)
+#define RMSTPCR4	(CPG_BASE + 0x0120)
+#define RMSTPCR5	(CPG_BASE + 0x0124)
+#define SMSTPCR0	(CPG_BASE + 0x0130)
+#define SMSTPCR2	(CPG_BASE + 0x0138)
+#define SMSTPCR3	(CPG_BASE + 0x013C)
+#define CPGXXCR4	(CPG_BASE + 0x0150)
+#define SRCR0		(CPG_BASE + 0x80A0)
+#define SRCR2		(CPG_BASE + 0x80B0)
+#define SRCR3		(CPG_BASE + 0x80A8)
+#define VREFCR		(CPG_BASE + 0x00EC)
+#define PCLKCR		(CPG_BASE + 0x1020)
+
+#define PORT32CR (0xE6051020)
+#define PORT33CR (0xE6051021)
+#define PORT34CR (0xE6051022)
+#define PORT35CR (0xE6051023)
+
+LIST "DRAM initialization code:"
+
+EW RWTCSRA0, 0xA507
+
+ED_AND LIFEC_SEC_SRC, 0xFFFF7FFF
+
+ED_AND SMSTPCR3,0xFFFF7FFF
+ED_AND SRCR3, 0xFFFF7FFF
+ED_AND SMSTPCR2,0xFFFBFFFF
+ED_AND SRCR2, 0xFFFBFFFF
+ED PLLECR, 0x00000000
+
+WAIT_MASK PLLECR, 0x00000F00, 0x00000000
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+
+ED PLL0CR, 0x2D000000
+ED PLL1CR, 0x17100000
+ED FRQCRB, 0x96235880
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+
+ED FLCKCR, 0x0000000B
+ED_AND SMSTPCR0, 0xFFFFFFFD
+
+ED_AND SRCR0, 0xFFFFFFFD
+ED 0xE6001628, 0x514
+ED 0xE6001648, 0x514
+ED 0xE6001658, 0x514
+ED 0xE6001678, 0x514
+
+ED DVFSCR4, 0x00092000
+ED DVFSCR5, 0x000000DC
+ED PLLECR, 0x00000000
+WAIT_MASK PLLECR, 0x00000F00, 0x00000000
+
+ED FRQCRA, 0x0012453C
+ED FRQCRB, 0x80431350
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+ED FRQCRD, 0x00000B0B
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+
+ED PCLKCR, 0x00000003
+ED VCLKCR1, 0x0000012F
+ED VCLKCR2, 0x00000119
+ED VCLKCR3, 0x00000119
+ED ZBCKCR, 0x00000002
+ED FLCKCR, 0x00000005
+ED SD0CKCR, 0x00000080
+ED SD1CKCR, 0x00000080
+ED SD2CKCR, 0x00000080
+ED FSIACKCR, 0x0000003F
+ED FSIBCKCR, 0x0000003F
+ED SUBCKCR, 0x00000080
+ED SPUACKCR, 0x0000000B
+ED SPUVCKCR, 0x0000000B
+ED MSUCKCR, 0x0000013F
+ED HSICKCR, 0x00000080
+ED MFCK1CR, 0x0000003F
+ED MFCK2CR, 0x0000003F
+ED DSITCKCR, 0x00000107
+ED DSI0PCKCR, 0x00000313
+ED DSI1PCKCR, 0x0000130D
+ED DSI0PHYCR, 0x2A800E0E
+ED PLL0CR, 0x1E000000
+ED PLL0CR, 0x2D000000
+ED PLL1CR, 0x17100000
+ED PLL2CR, 0x27000080
+ED PLL3CR, 0x1D000000
+ED PLL0STPCR, 0x00080000
+ED PLL1STPCR, 0x000120C0
+ED PLL2STPCR, 0x00012000
+ED PLL3STPCR, 0x00000030
+ED PLLECR, 0x0000000B
+WAIT_MASK PLLECR, 0x00000B00, 0x00000B00
+
+ED DVFSCR3, 0x000120F0
+ED MPMODE, 0x00000020
+ED VREFCR, 0x0000028A
+ED RMSTPCR0, 0xE4628087
+ED RMSTPCR1, 0xFFFFFFFF
+ED RMSTPCR2, 0x53FFFFFF
+ED RMSTPCR3, 0xFFFFFFFF
+ED RMSTPCR4, 0x00800D3D
+ED RMSTPCR5, 0xFFFFF3FF
+ED SMSTPCR2, 0x00000000
+ED SRCR2,  0x00040000
+ED_AND PLLECR, 0xFFFFFFF7
+WAIT_MASK PLLECR, 0x00000800, 0x00000000
+
+LIST "set SBSC operational"
+ED HPBCTRL6, 0x00000001
+WAIT_MASK HPBCTRL6, 0x00000001, 0x00000001
+
+LIST "set SBSC operating frequency"
+ED FRQCRD, 0x00001414
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+ED PLL3CR, 0x1D000000
+ED_OR PLLECR, 0x00000008
+WAIT_MASK PLLECR, 0x00000800, 0x00000800
+
+LIST "enable DLL oscillation in DDRPHY"
+ED_OR DLLCNT0A, 0x00000002
+
+LIST "wait >= 100 ns"
+ED SDGENCNTA, 0x00000005
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "target LPDDR2 device settings"
+ED SDCR0A, 0xACC90159
+ED SDCR1A, 0x00010059
+ED SDWCRC0A, 0x50874114
+ED SDWCRC1A, 0x33199B37
+ED SDWCRC2A, 0x008F2313
+ED SDWCR00A, 0x31020707
+ED SDWCR01A, 0x0017040A
+ED SDWCR10A, 0x31020707
+ED SDWCR11A, 0x0017040A
+
+ED SDDRVCR0A, 0x055557ff
+
+ED SDWCR2A, 0x30000000
+
+LIST "drive CKE high"
+ED_OR SDPCRA, 0x00000080
+WAIT_MASK SDPCRA, 0x00000080, 0x00000080
+
+LIST "wait >= 200 us"
+ED SDGENCNTA, 0x00002710
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "issue reset command to LPDDR2 device"
+ED SDMRACR0A, 0x0000003F
+ED SDMRA1, 0x00000000
+
+LIST "wait >= 10 (or 1) us (docs inconsistent)"
+ED SDGENCNTA, 0x000001F4
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "MRW ZS initialization calibration command"
+ED SDMRACR0A, 0x0000FF0A
+ED SDMRA3, 0x00000000
+
+LIST "wait >= 1 us"
+ED SDGENCNTA, 0x00000032
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "specify operating mode in LPDDR2"
+ED SDMRACR0A, 0x00002201
+ED SDMRA1, 0x00000000
+ED SDMRACR0A, 0x00000402
+ED SDMRA1, 0x00000000
+ED SDMRACR0A, 0x00000203
+ED SDMRA1, 0x00000000
+
+LIST "initialize DDR interface"
+ED SDMRA2, 0x00000000
+
+LIST "temperature sensor control"
+ED SDMRTMPCRA, 0x88800004
+ED SDMRTMPMSKA,0x00000004
+
+LIST "auto-refreshing control"
+ED RTCORA, 0xA55A0032
+ED RTCORHA, 0xA55A000C
+ED RTCSRA, 0xA55A2048
+
+ED_OR SDCR0A, 0x00000800
+ED_OR SDCR1A, 0x00000400
+
+LIST "auto ZQ calibration control"
+ED ZQCCRA, 0xFFF20000
+
+ED_OR DLLCNT0B, 0x00000002
+ED SDGENCNTB, 0x00000005
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDCR0B, 0xACC90159
+ED SDCR1B, 0x00010059
+ED SDWCRC0B, 0x50874114
+ED SDWCRC1B, 0x33199B37
+ED SDWCRC2B, 0x008F2313
+ED SDWCR00B, 0x31020707
+ED SDWCR01B, 0x0017040A
+ED SDWCR10B, 0x31020707
+ED SDWCR11B, 0x0017040A
+ED SDDRVCR0B, 0x055557ff
+ED SDWCR2B, 0x30000000
+ED_OR SDPCRB, 0x00000080
+WAIT_MASK SDPCRB, 0x00000080, 0x00000080
+
+ED SDGENCNTB, 0x00002710
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+ED SDMRACR0B, 0x0000003F
+
+LIST "upstream u-boot writes to SDMRA1A for both SBSC 1 and 2, which does"
+LIST "not seem to make a lot of sense..."
+ED SDMRB1, 0x00000000
+
+ED SDGENCNTB, 0x000001F4
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDMRACR0B, 0x0000FF0A
+ED SDMRB3, 0x00000000
+ED SDGENCNTB, 0x00000032
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDMRACR0B, 0x00002201
+ED SDMRB1, 0x00000000
+ED SDMRACR0B, 0x00000402
+ED SDMRB1, 0x00000000
+ED SDMRACR0B, 0x00000203
+ED SDMRB1, 0x00000000
+ED SDMRB2, 0x00000000
+ED SDMRTMPCRB, 0x88800004
+ED SDMRTMPMSKB, 0x00000004
+ED RTCORB,  0xA55A0032
+ED RTCORHB, 0xA55A000C
+ED RTCSRB,  0xA55A2048
+ED_OR SDCR0B, 0x00000800
+ED_OR SDCR1B, 0x00000400
+ED ZQCCRB, 0xFFF20000
+ED_OR SDPDCR0B, 0x00030000
+ED DPHYCNT1B, 0xA5390000
+ED DPHYCNT0B, 0x00001200
+ED DPHYCNT1B, 0x07CE0000
+ED DPHYCNT0B, 0x00001247
+WAIT_MASK DPHYCNT2B, 0xFFFFFFFF, 0x07CE0000
+
+ED_AND SDPDCR0B, 0xFFFCFFFF
+
+ED FRQCRD, 0x00000B0B
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+
+ED CPGXXCR4, 0xfffffffc
+
+LIST "Setup SCIF4 / workaround"
+EB PORT32CR, 0x12
+EB PORT33CR, 0x22
+EB PORT34CR, 0x12
+EB PORT35CR, 0x22
+
+EW 0xE6C80000, 0
+EB 0xE6C80004, 0x19
+EW 0xE6C80008, 0x0030
+EW 0xE6C80018, 0
+EW 0xE6C80030, 0x0014
+
+LIST "Magic to avoid hangs and corruption on DRAM writes."
+
+LIST "It has been observed that the system would most often hang while"
+LIST "decompressing the kernel, and if it didn't it would always write"
+LIST "a corrupt image to DRAM."
+LIST "This problem does not occur in u-boot, and the reason is that"
+LIST "u-boot performs an additional cache invalidation after setting up"
+LIST "the DRAM controller. Such an invalidation should not be necessary at"
+LIST "this point, and attempts at removing parts of the routine to arrive"
+LIST "at the minimal snippet of code necessary to avoid the DRAM stability"
+LIST "problem yielded the following:"
+
+MRC p15, 0, r0, c1, c0, 0
+MCR p15, 0, r0, c1, c0, 0
diff --git a/arch/arm/mach-shmobile/include/mach/pm-rcar.h b/arch/arm/mach-shmobile/include/mach/pm-rcar.h
new file mode 100644
index 000000000000..ef3a1ef628f1
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/pm-rcar.h
@@ -0,0 +1,15 @@
+#ifndef PM_RCAR_H
+#define PM_RCAR_H
+
+struct rcar_sysc_ch {
+	unsigned long chan_offs;
+	unsigned int chan_bit;
+	unsigned int isr_bit;
+};
+
+int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch);
+int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch);
+bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch);
+void __iomem *rcar_sysc_init(phys_addr_t base);
+
+#endif /* PM_RCAR_H */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index b40e13631f6a..88eeceaf1088 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -3,6 +3,7 @@
 
 #include <linux/sh_clk.h>
 #include <linux/pm_domain.h>
+#include <mach/pm-rcar.h>
 
 /* HPB-DMA slave IDs */
 enum {
@@ -11,18 +12,12 @@ enum {
 	HPBDMA_SLAVE_SDHI0_RX,
 };
 
-struct r8a7779_pm_ch {
-	unsigned long chan_offs;
-	unsigned int chan_bit;
-	unsigned int isr_bit;
-};
-
 struct r8a7779_pm_domain {
 	struct generic_pm_domain genpd;
-	struct r8a7779_pm_ch ch;
+	struct rcar_sysc_ch ch;
 };
 
-static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
 {
 	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
 }
@@ -41,8 +36,6 @@ extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
 extern void r8a7779_pm_init(void);
 extern void r8a7779_register_twd(void);
-extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch);
-extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch);
 
 #ifdef CONFIG_PM
 extern void __init r8a7779_init_pm_domains(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 5fbfa28b40b6..0b95babe84ba 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -3,10 +3,36 @@
 
 #include <mach/rcar-gen2.h>
 
+/* DMA slave IDs */
+enum {
+	RCAR_DMA_SLAVE_INVALID,
+	AUDIO_DMAC_SLAVE_SSI0_TX,
+	AUDIO_DMAC_SLAVE_SSI0_RX,
+	AUDIO_DMAC_SLAVE_SSI1_TX,
+	AUDIO_DMAC_SLAVE_SSI1_RX,
+	AUDIO_DMAC_SLAVE_SSI2_TX,
+	AUDIO_DMAC_SLAVE_SSI2_RX,
+	AUDIO_DMAC_SLAVE_SSI3_TX,
+	AUDIO_DMAC_SLAVE_SSI3_RX,
+	AUDIO_DMAC_SLAVE_SSI4_TX,
+	AUDIO_DMAC_SLAVE_SSI4_RX,
+	AUDIO_DMAC_SLAVE_SSI5_TX,
+	AUDIO_DMAC_SLAVE_SSI5_RX,
+	AUDIO_DMAC_SLAVE_SSI6_TX,
+	AUDIO_DMAC_SLAVE_SSI6_RX,
+	AUDIO_DMAC_SLAVE_SSI7_TX,
+	AUDIO_DMAC_SLAVE_SSI7_RX,
+	AUDIO_DMAC_SLAVE_SSI8_TX,
+	AUDIO_DMAC_SLAVE_SSI8_RX,
+	AUDIO_DMAC_SLAVE_SSI9_TX,
+	AUDIO_DMAC_SLAVE_SSI9_RX,
+};
+
 void r8a7790_add_standard_devices(void);
 void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
+void r8a7790_pm_init(void);
 void r8a7790_init_early(void);
 extern struct smp_operations r8a7790_smp_ops;
 
diff --git a/arch/arm/mach-shmobile/include/mach/timex.h b/arch/arm/mach-shmobile/include/mach/timex.h
deleted file mode 100644
index ae0d8d825c23..000000000000
--- a/arch/arm/mach-shmobile/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_MACH_TIMEX_H
-#define __ASM_MACH_TIMEX_H
-
-#define CLOCK_TICK_RATE		1193180 /* unused i8253 PIT value */
-
-#endif /* __ASM_MACH_TIMEX_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
index c3c4669a2d72..727cc78ac8ec 100644
--- a/arch/arm/mach-shmobile/include/mach/zboot.h
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -12,6 +12,9 @@
 #ifdef CONFIG_MACH_MACKEREL
 #define MEMORY_START	0x40000000
 #include "mach/head-mackerel.txt"
+#elif defined(CONFIG_MACH_KZM9G) || defined(CONFIG_MACH_KZM9G_REFERENCE)
+#define MEMORY_START	0x43000000
+#include "mach/head-kzm9g.txt"
 #else
 #error "unsupported board."
 #endif
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
index aa6111fbc989..14fd3d538e9a 100644
--- a/arch/arm/mach-shmobile/include/mach/zboot_macros.h
+++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
@@ -62,4 +62,47 @@
 2 :
 .endm
 
+/* loop until a given value has been read (with mask) */
+.macro WAIT_MASK, addr, data, cmp
+	LDR	r0, 2f
+	LDR	r1, 3f
+	LDR	r2, 4f
+1:
+	LDR	r3, [r0, #0]
+	AND	r3, r1, r3
+	CMP	r2, r3
+	BNE	1b
+	B	5f
+2:	.long	\addr
+3:	.long	\data
+4:	.long	\cmp
+5:
+.endm
+
+/* read 32-bit value from addr, "or" an immediate and write back */
+.macro ED_OR, addr, data
+	LDR r4, 1f
+	LDR r5, 2f
+	LDR r6, [r4]
+	ORR r5, r6, r5
+	STR r5, [r4]
+	B	3f
+1:	.long	\addr
+2:	.long	\data
+3:
+.endm
+
+/* read 32-bit value from addr, "and" an immediate and write back */
+.macro ED_AND, addr, data
+	LDR r4, 1f
+	LDR r5, 2f
+	LDR r6, [r4]
+	AND r5, r6, r5
+	STR r5, [r4]
+	B	3f
+1:	.long \addr
+2:	.long \data
+3:
+.endm
+
 #endif /* __ZBOOT_MACRO_H */
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
index d50a8e9b94a4..d6fe189b2df6 100644
--- a/arch/arm/mach-shmobile/pm-r8a7779.c
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -20,132 +20,22 @@
 #include <linux/console.h>
 #include <asm/io.h>
 #include <mach/common.h>
+#include <mach/pm-rcar.h>
 #include <mach/r8a7779.h>
 
-static void __iomem *r8a7779_sysc_base;
-
 /* SYSC */
-#define SYSCSR 0x00
-#define SYSCISR 0x04
-#define SYSCISCR 0x08
 #define SYSCIER 0x0c
 #define SYSCIMR 0x10
-#define PWRSR0 0x40
-#define PWRSR1 0x80
-#define PWRSR2 0xc0
-#define PWRSR3 0x100
-#define PWRSR4 0x140
-
-#define PWRSR_OFFS 0x00
-#define PWROFFCR_OFFS 0x04
-#define PWRONCR_OFFS 0x0c
-#define PWRER_OFFS 0x14
-
-#define SYSCSR_RETRIES 100
-#define SYSCSR_DELAY_US 1
-
-#define SYSCISR_RETRIES 1000
-#define SYSCISR_DELAY_US 1
 
 #if defined(CONFIG_PM) || defined(CONFIG_SMP)
 
-static DEFINE_SPINLOCK(r8a7779_sysc_lock); /* SMP CPUs + I/O devices */
-
-static int r8a7779_sysc_pwr_on_off(struct r8a7779_pm_ch *r8a7779_ch,
-				   int sr_bit, int reg_offs)
-{
-	int k;
-
-	for (k = 0; k < SYSCSR_RETRIES; k++) {
-		if (ioread32(r8a7779_sysc_base + SYSCSR) & (1 << sr_bit))
-			break;
-		udelay(SYSCSR_DELAY_US);
-	}
-
-	if (k == SYSCSR_RETRIES)
-		return -EAGAIN;
-
-	iowrite32(1 << r8a7779_ch->chan_bit,
-		  r8a7779_sysc_base + r8a7779_ch->chan_offs + reg_offs);
-
-	return 0;
-}
-
-static int r8a7779_sysc_pwr_off(struct r8a7779_pm_ch *r8a7779_ch)
-{
-	return r8a7779_sysc_pwr_on_off(r8a7779_ch, 0, PWROFFCR_OFFS);
-}
-
-static int r8a7779_sysc_pwr_on(struct r8a7779_pm_ch *r8a7779_ch)
-{
-	return r8a7779_sysc_pwr_on_off(r8a7779_ch, 1, PWRONCR_OFFS);
-}
-
-static int r8a7779_sysc_update(struct r8a7779_pm_ch *r8a7779_ch,
-			       int (*on_off_fn)(struct r8a7779_pm_ch *))
-{
-	unsigned int isr_mask = 1 << r8a7779_ch->isr_bit;
-	unsigned int chan_mask = 1 << r8a7779_ch->chan_bit;
-	unsigned int status;
-	unsigned long flags;
-	int ret = 0;
-	int k;
-
-	spin_lock_irqsave(&r8a7779_sysc_lock, flags);
-
-	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
-
-	do {
-		ret = on_off_fn(r8a7779_ch);
-		if (ret)
-			goto out;
-
-		status = ioread32(r8a7779_sysc_base +
-				  r8a7779_ch->chan_offs + PWRER_OFFS);
-	} while (status & chan_mask);
-
-	for (k = 0; k < SYSCISR_RETRIES; k++) {
-		if (ioread32(r8a7779_sysc_base + SYSCISR) & isr_mask)
-			break;
-		udelay(SYSCISR_DELAY_US);
-	}
-
-	if (k == SYSCISR_RETRIES)
-		ret = -EIO;
-
-	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
-
- out:
-	spin_unlock_irqrestore(&r8a7779_sysc_lock, flags);
-
-	pr_debug("r8a7779 power domain %d: %02x %02x %02x %02x %02x -> %d\n",
-		 r8a7779_ch->isr_bit, ioread32(r8a7779_sysc_base + PWRSR0),
-		 ioread32(r8a7779_sysc_base + PWRSR1),
-		 ioread32(r8a7779_sysc_base + PWRSR2),
-		 ioread32(r8a7779_sysc_base + PWRSR3),
-		 ioread32(r8a7779_sysc_base + PWRSR4), ret);
-	return ret;
-}
-
-int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
-{
-	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_off);
-}
-
-int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
-{
-	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_on);
-}
-
 static void __init r8a7779_sysc_init(void)
 {
-	r8a7779_sysc_base = ioremap_nocache(0xffd85000, PAGE_SIZE);
-	if (!r8a7779_sysc_base)
-		panic("unable to ioremap r8a7779 SYSC hardware block\n");
+	void __iomem *base = rcar_sysc_init(0xffd85000);
 
 	/* enable all interrupt sources, but do not use interrupt handler */
-	iowrite32(0x0131000e, r8a7779_sysc_base + SYSCIER);
-	iowrite32(0, r8a7779_sysc_base + SYSCIMR);
+	iowrite32(0x0131000e, base + SYSCIER);
+	iowrite32(0, base + SYSCIMR);
 }
 
 #else /* CONFIG_PM || CONFIG_SMP */
@@ -158,24 +48,17 @@ static inline void r8a7779_sysc_init(void) {}
 
 static int pd_power_down(struct generic_pm_domain *genpd)
 {
-	return r8a7779_sysc_power_down(to_r8a7779_ch(genpd));
+	return rcar_sysc_power_down(to_r8a7779_ch(genpd));
 }
 
 static int pd_power_up(struct generic_pm_domain *genpd)
 {
-	return r8a7779_sysc_power_up(to_r8a7779_ch(genpd));
+	return rcar_sysc_power_up(to_r8a7779_ch(genpd));
 }
 
 static bool pd_is_off(struct generic_pm_domain *genpd)
 {
-	struct r8a7779_pm_ch *r8a7779_ch = to_r8a7779_ch(genpd);
-	unsigned int st;
-
-	st = ioread32(r8a7779_sysc_base + r8a7779_ch->chan_offs + PWRSR_OFFS);
-	if (st & (1 << r8a7779_ch->chan_bit))
-		return true;
-
-	return false;
+	return rcar_sysc_power_is_off(to_r8a7779_ch(genpd));
 }
 
 static bool pd_active_wakeup(struct device *dev)
diff --git a/arch/arm/mach-shmobile/pm-r8a7790.c b/arch/arm/mach-shmobile/pm-r8a7790.c
new file mode 100644
index 000000000000..fc82839e2c2a
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-r8a7790.c
@@ -0,0 +1,45 @@
+/*
+ * r8a7790 Power management support
+ *
+ * Copyright (C) 2013  Renesas Electronics Corporation
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  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/kernel.h>
+#include <asm/io.h>
+#include <mach/pm-rcar.h>
+#include <mach/r8a7790.h>
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init r8a7790_sysc_init(void)
+{
+	void __iomem *base = rcar_sysc_init(0xe6180000);
+
+	/* enable all interrupt sources, but do not use interrupt handler */
+	iowrite32(0x0131000e, base + SYSCIER);
+	iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_SMP */
+
+static inline void r8a7790_sysc_init(void) {}
+
+#endif /* CONFIG_SMP */
+
+void __init r8a7790_pm_init(void)
+{
+	static int once;
+
+	if (!once++)
+		r8a7790_sysc_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c
new file mode 100644
index 000000000000..1f465a12d1b1
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rcar.c
@@ -0,0 +1,141 @@
+/*
+ * R-Car SYSC Power management support
+ *
+ * Copyright (C) 2014  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/delay.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <mach/pm-rcar.h>
+
+/* SYSC */
+#define SYSCSR 0x00
+#define SYSCISR 0x04
+#define SYSCISCR 0x08
+
+#define PWRSR_OFFS 0x00
+#define PWROFFCR_OFFS 0x04
+#define PWRONCR_OFFS 0x0c
+#define PWRER_OFFS 0x14
+
+#define SYSCSR_RETRIES 100
+#define SYSCSR_DELAY_US 1
+
+#define SYSCISR_RETRIES 1000
+#define SYSCISR_DELAY_US 1
+
+#if defined(CONFIG_PM) || defined(CONFIG_SMP)
+
+static void __iomem *rcar_sysc_base;
+static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
+
+static int rcar_sysc_pwr_on_off(struct rcar_sysc_ch *sysc_ch,
+				int sr_bit, int reg_offs)
+{
+	int k;
+
+	for (k = 0; k < SYSCSR_RETRIES; k++) {
+		if (ioread32(rcar_sysc_base + SYSCSR) & (1 << sr_bit))
+			break;
+		udelay(SYSCSR_DELAY_US);
+	}
+
+	if (k == SYSCSR_RETRIES)
+		return -EAGAIN;
+
+	iowrite32(1 << sysc_ch->chan_bit,
+		  rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
+
+	return 0;
+}
+
+static int rcar_sysc_pwr_off(struct rcar_sysc_ch *sysc_ch)
+{
+	return rcar_sysc_pwr_on_off(sysc_ch, 0, PWROFFCR_OFFS);
+}
+
+static int rcar_sysc_pwr_on(struct rcar_sysc_ch *sysc_ch)
+{
+	return rcar_sysc_pwr_on_off(sysc_ch, 1, PWRONCR_OFFS);
+}
+
+static int rcar_sysc_update(struct rcar_sysc_ch *sysc_ch,
+			    int (*on_off_fn)(struct rcar_sysc_ch *))
+{
+	unsigned int isr_mask = 1 << sysc_ch->isr_bit;
+	unsigned int chan_mask = 1 << sysc_ch->chan_bit;
+	unsigned int status;
+	unsigned long flags;
+	int ret = 0;
+	int k;
+
+	spin_lock_irqsave(&rcar_sysc_lock, flags);
+
+	iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+	do {
+		ret = on_off_fn(sysc_ch);
+		if (ret)
+			goto out;
+
+		status = ioread32(rcar_sysc_base +
+				  sysc_ch->chan_offs + PWRER_OFFS);
+	} while (status & chan_mask);
+
+	for (k = 0; k < SYSCISR_RETRIES; k++) {
+		if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
+			break;
+		udelay(SYSCISR_DELAY_US);
+	}
+
+	if (k == SYSCISR_RETRIES)
+		ret = -EIO;
+
+	iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+ out:
+	spin_unlock_irqrestore(&rcar_sysc_lock, flags);
+
+	pr_debug("sysc power domain %d: %08x -> %d\n",
+		 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
+	return ret;
+}
+
+int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch)
+{
+	return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_off);
+}
+
+int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch)
+{
+	return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_on);
+}
+
+bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch)
+{
+	unsigned int st;
+
+	st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
+	if (st & (1 << sysc_ch->chan_bit))
+		return true;
+
+	return false;
+}
+
+void __iomem *rcar_sysc_init(phys_addr_t base)
+{
+	rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+	if (!rcar_sysc_base)
+		panic("unable to ioremap R-Car SYSC hardware block\n");
+
+	return rcar_sysc_base;
+}
+
+#endif /* CONFIG_PM || CONFIG_SMP */
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index c8f2a1a69a52..c71d667007b8 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -58,7 +58,7 @@ static void __init emev2_add_standard_devices_dt(void)
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *emev2_boards_compat_dt[] __initdata = {
+static const char *emev2_boards_compat_dt[] __initconst = {
 	"renesas,emev2",
 	NULL,
 };
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 6ab37aa1e919..c4616f0698c6 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -24,12 +24,100 @@
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
 #include <mach/common.h>
+#include <mach/dma-register.h>
 #include <mach/irqs.h>
 #include <mach/r8a7790.h>
 #include <asm/mach/arch.h>
 
+/* Audio-DMAC */
+#define AUDIO_DMAC_SLAVE(_id, _addr, t, r)			\
+{								\
+	.slave_id	= AUDIO_DMAC_SLAVE_## _id ##_TX,	\
+	.addr		= _addr + 0x8,				\
+	.chcr		= CHCR_TX(XMIT_SZ_32BIT),		\
+	.mid_rid	= t,					\
+}, {								\
+	.slave_id	= AUDIO_DMAC_SLAVE_## _id ##_RX,	\
+	.addr		= _addr + 0xc,				\
+	.chcr		= CHCR_RX(XMIT_SZ_32BIT),		\
+	.mid_rid	= r,					\
+}
+
+static const struct sh_dmae_slave_config r8a7790_audio_dmac_slaves[] = {
+	AUDIO_DMAC_SLAVE(SSI0, 0xec241000, 0x01, 0x02),
+	AUDIO_DMAC_SLAVE(SSI1, 0xec241040, 0x03, 0x04),
+	AUDIO_DMAC_SLAVE(SSI2, 0xec241080, 0x05, 0x06),
+	AUDIO_DMAC_SLAVE(SSI3, 0xec2410c0, 0x07, 0x08),
+	AUDIO_DMAC_SLAVE(SSI4, 0xec241100, 0x09, 0x0a),
+	AUDIO_DMAC_SLAVE(SSI5, 0xec241140, 0x0b, 0x0c),
+	AUDIO_DMAC_SLAVE(SSI6, 0xec241180, 0x0d, 0x0e),
+	AUDIO_DMAC_SLAVE(SSI7, 0xec2411c0, 0x0f, 0x10),
+	AUDIO_DMAC_SLAVE(SSI8, 0xec241200, 0x11, 0x12),
+	AUDIO_DMAC_SLAVE(SSI9, 0xec241240, 0x13, 0x14),
+};
+
+#define DMAE_CHANNEL(a, b)			\
+{						\
+	.offset		= (a) - 0x20,		\
+	.dmars		= (a) - 0x20 + 0x40,	\
+	.chclr_bit	= (b),			\
+	.chclr_offset	= 0x80 - 0x20,		\
+}
+
+static const struct sh_dmae_channel r8a7790_audio_dmac_channels[] = {
+	DMAE_CHANNEL(0x8000, 0),
+	DMAE_CHANNEL(0x8080, 1),
+	DMAE_CHANNEL(0x8100, 2),
+	DMAE_CHANNEL(0x8180, 3),
+	DMAE_CHANNEL(0x8200, 4),
+	DMAE_CHANNEL(0x8280, 5),
+	DMAE_CHANNEL(0x8300, 6),
+	DMAE_CHANNEL(0x8380, 7),
+	DMAE_CHANNEL(0x8400, 8),
+	DMAE_CHANNEL(0x8480, 9),
+	DMAE_CHANNEL(0x8500, 10),
+	DMAE_CHANNEL(0x8580, 11),
+	DMAE_CHANNEL(0x8600, 12),
+};
+
+static struct sh_dmae_pdata r8a7790_audio_dmac_platform_data = {
+	.slave		= r8a7790_audio_dmac_slaves,
+	.slave_num	= ARRAY_SIZE(r8a7790_audio_dmac_slaves),
+	.channel	= r8a7790_audio_dmac_channels,
+	.channel_num	= ARRAY_SIZE(r8a7790_audio_dmac_channels),
+	.ts_low_shift	= TS_LOW_SHIFT,
+	.ts_low_mask	= TS_LOW_BIT << TS_LOW_SHIFT,
+	.ts_high_shift	= TS_HI_SHIFT,
+	.ts_high_mask	= TS_HI_BIT << TS_HI_SHIFT,
+	.ts_shift	= dma_ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(dma_ts_shift),
+	.dmaor_init	= DMAOR_DME,
+	.chclr_present	= 1,
+	.chclr_bitwise	= 1,
+};
+
+static struct resource r8a7790_audio_dmac_resources[] = {
+	/* Channel registers and DMAOR for low */
+	DEFINE_RES_MEM(0xec700020, 0x8663 - 0x20),
+	DEFINE_RES_IRQ(gic_spi(346)),
+	DEFINE_RES_NAMED(gic_spi(320), 13, NULL, IORESOURCE_IRQ),
+
+	/* Channel registers and DMAOR for hi */
+	DEFINE_RES_MEM(0xec720020, 0x8663 - 0x20), /* hi */
+	DEFINE_RES_IRQ(gic_spi(347)),
+	DEFINE_RES_NAMED(gic_spi(333), 13, NULL, IORESOURCE_IRQ),
+};
+
+#define r8a7790_register_audio_dmac(id)				\
+	platform_device_register_resndata(			\
+		&platform_bus, "sh-dma-engine", id,		\
+		&r8a7790_audio_dmac_resources[id * 3],	3,	\
+		&r8a7790_audio_dmac_platform_data,		\
+		sizeof(r8a7790_audio_dmac_platform_data))
+
 static const struct resource pfc_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe6060000, 0x250),
 };
@@ -101,6 +189,8 @@ void __init r8a7790_pinmux_init(void)
 	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)		\
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 69ccc6c6fd33..10604480f325 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -28,7 +28,7 @@
 
 #define MODEMR 0xe6160060
 
-u32 __init rcar_gen2_read_mode_pins(void)
+u32 rcar_gen2_read_mode_pins(void)
 {
 	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
 	u32 mode;
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 627c1f0d9478..e7a3201473d0 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <mach/common.h>
+#include <mach/pm-rcar.h>
 #include <mach/r8a7779.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -33,25 +34,25 @@
 #define AVECR IOMEM(0xfe700040)
 #define R8A7779_SCU_BASE 0xf0000000
 
-static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
+static struct rcar_sysc_ch r8a7779_ch_cpu1 = {
 	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
 	.chan_bit = 1, /* ARM1 */
 	.isr_bit = 1, /* ARM1 */
 };
 
-static struct r8a7779_pm_ch r8a7779_ch_cpu2 = {
+static struct rcar_sysc_ch r8a7779_ch_cpu2 = {
 	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
 	.chan_bit = 2, /* ARM2 */
 	.isr_bit = 2, /* ARM2 */
 };
 
-static struct r8a7779_pm_ch r8a7779_ch_cpu3 = {
+static struct rcar_sysc_ch r8a7779_ch_cpu3 = {
 	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
 	.chan_bit = 3, /* ARM3 */
 	.isr_bit = 3, /* ARM3 */
 };
 
-static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
+static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = {
 	[1] = &r8a7779_ch_cpu1,
 	[2] = &r8a7779_ch_cpu2,
 	[3] = &r8a7779_ch_cpu3,
@@ -67,7 +68,7 @@ void __init r8a7779_register_twd(void)
 
 static int r8a7779_platform_cpu_kill(unsigned int cpu)
 {
-	struct r8a7779_pm_ch *ch = NULL;
+	struct rcar_sysc_ch *ch = NULL;
 	int ret = -EIO;
 
 	cpu = cpu_logical_map(cpu);
@@ -76,14 +77,14 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
 		ch = r8a7779_ch_cpu[cpu];
 
 	if (ch)
-		ret = r8a7779_sysc_power_down(ch);
+		ret = rcar_sysc_power_down(ch);
 
 	return ret ? ret : 1;
 }
 
 static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	struct r8a7779_pm_ch *ch = NULL;
+	struct rcar_sysc_ch *ch = NULL;
 	unsigned int lcpu = cpu_logical_map(cpu);
 	int ret;
 
@@ -91,7 +92,7 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 		ch = r8a7779_ch_cpu[lcpu];
 
 	if (ch)
-		ret = r8a7779_sysc_power_up(ch);
+		ret = rcar_sysc_power_up(ch);
 	else
 		ret = -EIO;
 
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
index 015e2753de1f..591052799e8f 100644
--- a/arch/arm/mach-shmobile/smp-r8a7790.c
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -19,6 +19,8 @@
 #include <linux/io.h>
 #include <asm/smp_plat.h>
 #include <mach/common.h>
+#include <mach/pm-rcar.h>
+#include <mach/r8a7790.h>
 
 #define RST		0xe6160000
 #define CA15BAR		0x0020
@@ -27,6 +29,16 @@
 #define CA7RESCNT	0x0044
 #define MERAM		0xe8080000
 
+static struct rcar_sysc_ch r8a7790_ca15_scu = {
+	.chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
+	.isr_bit = 12, /* CA15-SCU */
+};
+
+static struct rcar_sysc_ch r8a7790_ca7_scu = {
+	.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+	.isr_bit = 21, /* CA7-SCU */
+};
+
 static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
 {
 	void __iomem *p;
@@ -54,6 +66,11 @@ static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
 	writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
 		       p + CA7RESCNT);
 	iounmap(p);
+
+	/* turn on power to SCU */
+	r8a7790_pm_init();
+	rcar_sysc_power_up(&r8a7790_ca15_scu);
+	rcar_sysc_power_up(&r8a7790_ca7_scu);
 }
 
 struct smp_operations r8a7790_smp_ops __initdata = {
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index aee77f06f887..b5f8d75d51a0 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -1,17 +1,10 @@
 config ARCH_SOCFPGA
 	bool "Altera SOCFPGA family" if ARCH_MULTI_V7
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_AMBA
 	select ARM_GIC
 	select CACHE_L2X0
-	select COMMON_CLK
-	select CPU_V7
 	select DW_APB_TIMER_OF
-	select GENERIC_CLOCKEVENTS
 	select GPIO_PL061 if GPIOLIB
 	select HAVE_ARM_SCU
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
 	select MFD_SYSCON
-	select SPARSE_IRQ
-	select USE_OF
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index dd0d49cdbe09..d86231e11b34 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -29,7 +29,6 @@
 void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
 void __iomem *sys_manager_base_addr;
 void __iomem *rst_manager_base_addr;
-void __iomem *clk_mgr_base_addr;
 unsigned long cpu1start_addr;
 
 static struct map_desc scu_io_desc __initdata = {
@@ -78,9 +77,6 @@ void __init socfpga_sysmgr_init(void)
 
 	np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
 	rst_manager_base_addr = of_iomap(np, 0);
-
-	np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
-	clk_mgr_base_addr = of_iomap(np, 0);
 }
 
 static void __init socfpga_init_irq(void)
@@ -106,7 +102,6 @@ static void __init socfpga_cyclone5_init(void)
 {
 	l2x0_of_init(0, ~0UL);
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	socfpga_init_clocks();
 }
 
 static const char *altera_dt_match[] = {
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index ac1710e64d9a..5c57262b97e9 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -8,8 +8,6 @@ menuconfig PLAT_SPEAR
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
 	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 
 if PLAT_SPEAR
 
@@ -18,14 +16,10 @@ config ARCH_SPEAR13XX
 	depends on ARCH_MULTI_V7 || PLAT_SPEAR_SINGLE
 	select ARCH_HAS_CPUFREQ
 	select ARM_GIC
-	select CPU_V7
 	select GPIO_SPEAR_SPICS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
-	select USE_OF
 	help
 	  Supports for ARM's SPEAR13XX family
 
@@ -50,9 +44,7 @@ config ARCH_SPEAR3XX
 	depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
 	depends on !ARCH_SPEAR13XX
 	select ARM_VIC
-	select CPU_ARM926T
 	select PINCTRL
-	select USE_OF
 	help
 	  Supports for ARM's SPEAR3XX family
 
@@ -83,14 +75,12 @@ config ARCH_SPEAR6XX
 	depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
 	depends on !ARCH_SPEAR13XX
 	select ARM_VIC
-	select CPU_ARM926T
 	help
 	  Supports for ARM's SPEAR6XX family
 
 config MACH_SPEAR600
 	def_bool y
 	depends on ARCH_SPEAR6XX
-	select USE_OF
 	help
 	  Supports ST SPEAr600 boards configured via the device-treesource "arch/arm/mach-spear6xx/Kconfig"
 
diff --git a/arch/arm/mach-spear/include/mach/timex.h b/arch/arm/mach-spear/include/mach/timex.h
deleted file mode 100644
index ef95e5b780bd..000000000000
--- a/arch/arm/mach-spear/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/timex.h
- *
- * SPEAr platform specific timex definitions
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#ifndef __PLAT_TIMEX_H
-#define __PLAT_TIMEX_H
-
-#define CLOCK_TICK_RATE			48000000
-
-#endif /* __PLAT_TIMEX_H */
diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig
index d71654bc8d54..d2c13ba1190b 100644
--- a/arch/arm/mach-sti/Kconfig
+++ b/arch/arm/mach-sti/Kconfig
@@ -1,14 +1,10 @@
 menuconfig ARCH_STI
 	bool "STMicroelectronics Consumer Electronics SOCs with Device Trees" if ARCH_MULTI_V7
-	select GENERIC_CLOCKEVENTS
-	select CLKDEV_LOOKUP
 	select ARM_GIC
 	select ARM_GLOBAL_TIMER
 	select PINCTRL
 	select PINCTRL_ST
 	select MFD_SYSCON
-	select MIGHT_HAVE_CACHE_L2X0
-	select HAVE_SMP
 	select HAVE_ARM_SCU if SMP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_ERRATA_754322
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index b9d6cad8669b..9de27cfa688f 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -5,14 +5,9 @@ config ARCH_SUNXI
 	select ARM_GIC
 	select ARM_PSCI
 	select CLKSRC_MMIO
-	select CLKSRC_OF
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select HAVE_SMP
 	select PINCTRL
 	select PINCTRL_SUNXI
 	select RESET_CONTROLLER
-	select SPARSE_IRQ
 	select SUN4I_TIMER
 	select SUN5I_HSTIMER
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index b1232d8be6f5..92d660f9610f 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -5,24 +5,15 @@ config ARCH_TEGRA
 	select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
 	select ARM_GIC
 	select CLKSRC_MMIO
-	select CLKSRC_OF
-	select COMMON_CLK
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
 	select MIGHT_HAVE_PCI
 	select PINCTRL
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
 	select SOC_BUS
-	select SPARSE_IRQ
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB_PHY
 	select USB_ULPI_VIEWPORT if USB_PHY
-	select USE_OF
 	help
 	  This enables support for NVIDIA Tegra based systems.
 
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 019bb1758662..6fbfbb77dcd9 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -14,7 +14,6 @@ obj-y					+= sleep.o
 obj-y					+= tegra.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
 ifeq ($(CONFIG_CPU_IDLE),y)
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index e0b87300243d..b5fb7c110c64 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -19,6 +19,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/clockchips.h>
+#include <asm/firmware.h>
 
 #include <asm/cpuidle.h>
 #include <asm/suspend.h>
@@ -45,7 +46,11 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
-	cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
+	call_firmware_op(prepare_idle);
+
+	/* Do suspend by ourselves if the firmware does not implement it */
+	if (call_firmware_op(do_idle) == -ENOSYS)
+		cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index eb72ae709124..929d1046e2b4 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -114,7 +114,7 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 		/* Wait for the power to come up. */
 		timeout = jiffies + msecs_to_jiffies(100);
-		while (tegra_pmc_cpu_is_powered(cpu)) {
+		while (!tegra_pmc_cpu_is_powered(cpu)) {
 			if (time_after(jiffies, timeout))
 				return -ETIMEDOUT;
 			udelay(10);
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 3d0c537d9b94..4cefc5cd6bed 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -484,6 +484,7 @@ int tegra_io_rail_power_on(int id)
 
 	return 0;
 }
+EXPORT_SYMBOL(tegra_io_rail_power_on);
 
 int tegra_io_rail_power_off(int id)
 {
@@ -511,3 +512,4 @@ int tegra_io_rail_power_off(int id)
 
 	return 0;
 }
+EXPORT_SYMBOL(tegra_io_rail_power_off);
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
deleted file mode 100644
index 3ae4a7f1a2fb..000000000000
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.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/kernel.h>
-#include <linux/device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/tegra_emc.h>
-
-#include "tegra2_emc.h"
-#include "fuse.h"
-
-#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
-static bool emc_enable = true;
-#else
-static bool emc_enable;
-#endif
-module_param(emc_enable, bool, 0644);
-
-static struct platform_device *emc_pdev;
-static void __iomem *emc_regbase;
-
-static inline void emc_writel(u32 val, unsigned long addr)
-{
-	writel(val, emc_regbase + addr);
-}
-
-static inline u32 emc_readl(unsigned long addr)
-{
-	return readl(emc_regbase + addr);
-}
-
-static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
-	0x2c,	/* RC */
-	0x30,	/* RFC */
-	0x34,	/* RAS */
-	0x38,	/* RP */
-	0x3c,	/* R2W */
-	0x40,	/* W2R */
-	0x44,	/* R2P */
-	0x48,	/* W2P */
-	0x4c,	/* RD_RCD */
-	0x50,	/* WR_RCD */
-	0x54,	/* RRD */
-	0x58,	/* REXT */
-	0x5c,	/* WDV */
-	0x60,	/* QUSE */
-	0x64,	/* QRST */
-	0x68,	/* QSAFE */
-	0x6c,	/* RDV */
-	0x70,	/* REFRESH */
-	0x74,	/* BURST_REFRESH_NUM */
-	0x78,	/* PDEX2WR */
-	0x7c,	/* PDEX2RD */
-	0x80,	/* PCHG2PDEN */
-	0x84,	/* ACT2PDEN */
-	0x88,	/* AR2PDEN */
-	0x8c,	/* RW2PDEN */
-	0x90,	/* TXSR */
-	0x94,	/* TCKE */
-	0x98,	/* TFAW */
-	0x9c,	/* TRPAB */
-	0xa0,	/* TCLKSTABLE */
-	0xa4,	/* TCLKSTOP */
-	0xa8,	/* TREFBW */
-	0xac,	/* QUSE_EXTRA */
-	0x114,	/* FBIO_CFG6 */
-	0xb0,	/* ODT_WRITE */
-	0xb4,	/* ODT_READ */
-	0x104,	/* FBIO_CFG5 */
-	0x2bc,	/* CFG_DIG_DLL */
-	0x2c0,	/* DLL_XFORM_DQS */
-	0x2c4,	/* DLL_XFORM_QUSE */
-	0x2e0,	/* ZCAL_REF_CNT */
-	0x2e4,	/* ZCAL_WAIT_CNT */
-	0x2a8,	/* AUTO_CAL_INTERVAL */
-	0x2d0,	/* CFG_CLKTRIM_0 */
-	0x2d4,	/* CFG_CLKTRIM_1 */
-	0x2d8,	/* CFG_CLKTRIM_2 */
-};
-
-/* Select the closest EMC rate that is higher than the requested rate */
-long tegra_emc_round_rate(unsigned long rate)
-{
-	struct tegra_emc_pdata *pdata;
-	int i;
-	int best = -1;
-	unsigned long distance = ULONG_MAX;
-
-	if (!emc_pdev)
-		return -EINVAL;
-
-	pdata = emc_pdev->dev.platform_data;
-
-	pr_debug("%s: %lu\n", __func__, rate);
-
-	/*
-	 * The EMC clock rate is twice the bus rate, and the bus rate is
-	 * measured in kHz
-	 */
-	rate = rate / 2 / 1000;
-
-	for (i = 0; i < pdata->num_tables; i++) {
-		if (pdata->tables[i].rate >= rate &&
-		    (pdata->tables[i].rate - rate) < distance) {
-			distance = pdata->tables[i].rate - rate;
-			best = i;
-		}
-	}
-
-	if (best < 0)
-		return -EINVAL;
-
-	pr_debug("%s: using %lu\n", __func__, pdata->tables[best].rate);
-
-	return pdata->tables[best].rate * 2 * 1000;
-}
-
-/*
- * The EMC registers have shadow registers.  When the EMC clock is updated
- * in the clock controller, the shadow registers are copied to the active
- * registers, allowing glitchless memory bus frequency changes.
- * This function updates the shadow registers for a new clock frequency,
- * and relies on the clock lock on the emc clock to avoid races between
- * multiple frequency changes
- */
-int tegra_emc_set_rate(unsigned long rate)
-{
-	struct tegra_emc_pdata *pdata;
-	int i;
-	int j;
-
-	if (!emc_pdev)
-		return -EINVAL;
-
-	pdata = emc_pdev->dev.platform_data;
-
-	/*
-	 * The EMC clock rate is twice the bus rate, and the bus rate is
-	 * measured in kHz
-	 */
-	rate = rate / 2 / 1000;
-
-	for (i = 0; i < pdata->num_tables; i++)
-		if (pdata->tables[i].rate == rate)
-			break;
-
-	if (i >= pdata->num_tables)
-		return -EINVAL;
-
-	pr_debug("%s: setting to %lu\n", __func__, rate);
-
-	for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
-		emc_writel(pdata->tables[i].regs[j], emc_reg_addr[j]);
-
-	emc_readl(pdata->tables[i].regs[TEGRA_EMC_NUM_REGS - 1]);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static struct device_node *tegra_emc_ramcode_devnode(struct device_node *np)
-{
-	struct device_node *iter;
-	u32 reg;
-
-	for_each_child_of_node(np, iter) {
-		if (of_property_read_u32(iter, "nvidia,ram-code", &reg))
-			continue;
-		if (reg == tegra_bct_strapping)
-			return of_node_get(iter);
-	}
-
-	return NULL;
-}
-
-static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
-		struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	struct device_node *tnp, *iter;
-	struct tegra_emc_pdata *pdata;
-	int ret, i, num_tables;
-
-	if (!np)
-		return NULL;
-
-	if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
-		tnp = tegra_emc_ramcode_devnode(np);
-		if (!tnp)
-			dev_warn(&pdev->dev,
-				 "can't find emc table for ram-code 0x%02x\n",
-				 tegra_bct_strapping);
-	} else
-		tnp = of_node_get(np);
-
-	if (!tnp)
-		return NULL;
-
-	num_tables = 0;
-	for_each_child_of_node(tnp, iter)
-		if (of_device_is_compatible(iter, "nvidia,tegra20-emc-table"))
-			num_tables++;
-
-	if (!num_tables) {
-		pdata = NULL;
-		goto out;
-	}
-
-	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	pdata->tables = devm_kzalloc(&pdev->dev,
-				     sizeof(*pdata->tables) * num_tables,
-				     GFP_KERNEL);
-
-	i = 0;
-	for_each_child_of_node(tnp, iter) {
-		u32 prop;
-
-		ret = of_property_read_u32(iter, "clock-frequency", &prop);
-		if (ret) {
-			dev_err(&pdev->dev, "no clock-frequency in %s\n",
-				iter->full_name);
-			continue;
-		}
-		pdata->tables[i].rate = prop;
-
-		ret = of_property_read_u32_array(iter, "nvidia,emc-registers",
-						 pdata->tables[i].regs,
-						 TEGRA_EMC_NUM_REGS);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"malformed emc-registers property in %s\n",
-				iter->full_name);
-			continue;
-		}
-
-		i++;
-	}
-	pdata->num_tables = i;
-
-out:
-	of_node_put(tnp);
-	return pdata;
-}
-#else
-static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
-		struct platform_device *pdev)
-{
-	return NULL;
-}
-#endif
-
-static struct tegra_emc_pdata *tegra_emc_fill_pdata(struct platform_device *pdev)
-{
-	struct clk *c = clk_get_sys(NULL, "emc");
-	struct tegra_emc_pdata *pdata;
-	unsigned long khz;
-	int i;
-
-	WARN_ON(pdev->dev.platform_data);
-	BUG_ON(IS_ERR(c));
-
-	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
-				     GFP_KERNEL);
-
-	pdata->tables[0].rate = clk_get_rate(c) / 2 / 1000;
-
-	for (i = 0; i < TEGRA_EMC_NUM_REGS; i++)
-		pdata->tables[0].regs[i] = emc_readl(emc_reg_addr[i]);
-
-	pdata->num_tables = 1;
-
-	khz = pdata->tables[0].rate;
-	dev_info(&pdev->dev, "no tables provided, using %ld kHz emc, "
-		 "%ld kHz mem\n", khz * 2, khz);
-
-	return pdata;
-}
-
-static int tegra_emc_probe(struct platform_device *pdev)
-{
-	struct tegra_emc_pdata *pdata;
-	struct resource *res;
-
-	if (!emc_enable) {
-		dev_err(&pdev->dev, "disabled per module parameter\n");
-		return -ENODEV;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	emc_regbase = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(emc_regbase))
-		return PTR_ERR(emc_regbase);
-
-	pdata = pdev->dev.platform_data;
-
-	if (!pdata)
-		pdata = tegra_emc_dt_parse_pdata(pdev);
-
-	if (!pdata)
-		pdata = tegra_emc_fill_pdata(pdev);
-
-	pdev->dev.platform_data = pdata;
-
-	emc_pdev = pdev;
-
-	return 0;
-}
-
-static struct of_device_id tegra_emc_of_match[] = {
-	{ .compatible = "nvidia,tegra20-emc", },
-	{ },
-};
-
-static struct platform_driver tegra_emc_driver = {
-	.driver         = {
-		.name   = "tegra-emc",
-		.owner  = THIS_MODULE,
-		.of_match_table = tegra_emc_of_match,
-	},
-	.probe          = tegra_emc_probe,
-};
-
-static int __init tegra_emc_init(void)
-{
-	return platform_driver_register(&tegra_emc_driver);
-}
-device_initcall(tegra_emc_init);
diff --git a/arch/arm/mach-tegra/tegra2_emc.h b/arch/arm/mach-tegra/tegra2_emc.h
deleted file mode 100644
index f61409b54cb7..000000000000
--- a/arch/arm/mach-tegra/tegra2_emc.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.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.
- *
- */
-
-#ifndef __MACH_TEGRA_TEGRA2_EMC_H_
-#define __MACH_TEGRA_TEGRA2_EMC_H
-
-int tegra_emc_set_rate(unsigned long rate);
-long tegra_emc_round_rate(unsigned long rate);
-
-#endif
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index 8e23071bd1b3..e3a96d7302e9 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -3,20 +3,14 @@ config ARCH_U300
 	depends on MMU
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
-	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
 	select CLKSRC_MMIO
-	select CLKSRC_OF
-	select COMMON_CLK
 	select CPU_ARM926T
-	select GENERIC_CLOCKEVENTS
 	select HAVE_TCM
 	select PINCTRL
 	select PINCTRL_COH901
 	select PINCTRL_U300
-	select SPARSE_IRQ
 	select MFD_SYSCON
-	select USE_OF
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
 
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 0034d2cd6973..8052bd52450d 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -11,13 +11,8 @@ config ARCH_U8500
 	select ARM_GIC
 	select CACHE_L2X0
 	select CLKSRC_NOMADIK_MTU
-	select COMMON_CLK
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
 	select PINCTRL_ABX500
 	select PINCTRL_NOMADIK
@@ -76,7 +71,6 @@ config UX500_AUTO_PLATFORM
 config MACH_UX500_DT
 	bool "Generic U8500 support using device tree"
 	depends on MACH_MOP500
-	select USE_OF
 
 endmenu
 
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index d05ba759da30..de544aabf292 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o
 obj-$(CONFIG_MACH_MOP500)	+= board-mop500-sdi.o \
 				board-mop500-regulators.o \
-				board-mop500-pins.o \
 				board-mop500-audio.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
deleted file mode 100644
index f63619b69113..000000000000
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bug.h>
-#include <linux/string.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf-generic.h>
-
-#include <asm/mach-types.h>
-
-#include "board-mop500.h"
-
-/* These simply sets bias for pins */
-#define BIAS(a,b) static unsigned long a[] = { b }
-
-BIAS(abx500_out_lo, PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0));
-BIAS(abx500_in_pd, PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 1));
-BIAS(abx500_in_nopull, PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 0));
-
-#define AB8500_MUX_HOG(group, func) \
-	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-ab8500.0", group, func)
-#define AB8500_PIN_HOG(pin, conf) \
-	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-ab8500.0", pin, abx500_##conf)
-
-#define AB8500_MUX_STATE(group, func, dev, state) \
-	PIN_MAP_MUX_GROUP(dev, state, "pinctrl-ab8500.0", group, func)
-#define AB8500_PIN_STATE(pin, conf, dev, state) \
-	PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-ab8500.0", pin, abx500_##conf)
-
-#define AB8505_MUX_HOG(group, func) \
-	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-ab8505.0", group, func)
-#define AB8505_PIN_HOG(pin, conf) \
-	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-ab8505.0", pin, abx500_##conf)
-
-#define AB8505_MUX_STATE(group, func, dev, state) \
-	PIN_MAP_MUX_GROUP(dev, state, "pinctrl-ab8505.0", group, func)
-#define AB8505_PIN_STATE(pin, conf, dev, state) \
-	PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-ab8505.0", pin, abx500_##conf)
-
-static struct pinctrl_map __initdata ab8500_pinmap[] = {
-	/* Sysclkreq2 */
-	AB8500_MUX_STATE("sysclkreq2_d_1", "sysclkreq", "regulator.35", PINCTRL_STATE_DEFAULT),
-	AB8500_PIN_STATE("GPIO1_T10", in_nopull, "regulator.35", PINCTRL_STATE_DEFAULT),
-	/* sysclkreq2 disable, mux in gpio configured in input pulldown */
-	AB8500_MUX_STATE("gpio1_a_1", "gpio", "regulator.35", PINCTRL_STATE_SLEEP),
-	AB8500_PIN_STATE("GPIO1_T10", in_pd, "regulator.35", PINCTRL_STATE_SLEEP),
-
-	/* pins 2 is muxed in GPIO, configured in INPUT PULL DOWN */
-	AB8500_MUX_HOG("gpio2_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO2_T9", in_pd),
-
-	/* Sysclkreq4 */
-	AB8500_MUX_STATE("sysclkreq4_d_1", "sysclkreq", "regulator.36", PINCTRL_STATE_DEFAULT),
-	AB8500_PIN_STATE("GPIO3_U9", in_nopull, "regulator.36", PINCTRL_STATE_DEFAULT),
-	/* sysclkreq4 disable, mux in gpio configured in input pulldown */
-	AB8500_MUX_STATE("gpio3_a_1", "gpio", "regulator.36", PINCTRL_STATE_SLEEP),
-	AB8500_PIN_STATE("GPIO3_U9", in_pd, "regulator.36", PINCTRL_STATE_SLEEP),
-
-	/* pins 4 is muxed in GPIO, configured in INPUT PULL DOWN */
-	AB8500_MUX_HOG("gpio4_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO4_W2", in_pd),
-
-	/*
-	 * pins 6,7,8 and 9 are muxed in YCBCR0123
-	 * configured in INPUT PULL UP
-	 */
-	AB8500_MUX_HOG("ycbcr0123_d_1", "ycbcr"),
-	AB8500_PIN_HOG("GPIO6_Y18", in_nopull),
-	AB8500_PIN_HOG("GPIO7_AA20", in_nopull),
-	AB8500_PIN_HOG("GPIO8_W18", in_nopull),
-	AB8500_PIN_HOG("GPIO9_AA19", in_nopull),
-
-	/*
-	 * pins 10,11,12 and 13 are muxed in GPIO
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("gpio10_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO10_U17", in_pd),
-
-	AB8500_MUX_HOG("gpio11_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO11_AA18", in_pd),
-
-	AB8500_MUX_HOG("gpio12_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO12_U16", in_pd),
-
-	AB8500_MUX_HOG("gpio13_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO13_W17", in_pd),
-
-	/*
-	 * pins 14,15 are muxed in PWM1 and PWM2
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("pwmout1_d_1", "pwmout"),
-	AB8500_PIN_HOG("GPIO14_F14", in_pd),
-
-	AB8500_MUX_HOG("pwmout2_d_1", "pwmout"),
-	AB8500_PIN_HOG("GPIO15_B17", in_pd),
-
-	/*
-	 * pins 16 is muxed in GPIO
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("gpio16_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO14_F14", in_pd),
-
-	/*
-	 * pins 17,18,19 and 20 are muxed in AUDIO interface 1
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("adi1_d_1", "adi1"),
-	AB8500_PIN_HOG("GPIO17_P5", in_pd),
-	AB8500_PIN_HOG("GPIO18_R5", in_pd),
-	AB8500_PIN_HOG("GPIO19_U5", in_pd),
-	AB8500_PIN_HOG("GPIO20_T5", in_pd),
-
-	/*
-	 * pins 21,22 and 23 are muxed in USB UICC
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("usbuicc_d_1", "usbuicc"),
-	AB8500_PIN_HOG("GPIO21_H19", in_pd),
-	AB8500_PIN_HOG("GPIO22_G20", in_pd),
-	AB8500_PIN_HOG("GPIO23_G19", in_pd),
-
-	/*
-	 * pins 24,25 are muxed in GPIO
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("gpio24_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO24_T14", in_pd),
-
-	AB8500_MUX_HOG("gpio25_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO25_R16", in_pd),
-
-	/*
-	 * pins 26 is muxed in GPIO
-	 * configured in OUTPUT LOW
-	 */
-	AB8500_MUX_HOG("gpio26_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO26_M16", out_lo),
-
-	/*
-	 * pins 27,28 are muxed in DMIC12
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("dmic12_d_1", "dmic"),
-	AB8500_PIN_HOG("GPIO27_J6", in_pd),
-	AB8500_PIN_HOG("GPIO28_K6", in_pd),
-
-	/*
-	 * pins 29,30 are muxed in DMIC34
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("dmic34_d_1", "dmic"),
-	AB8500_PIN_HOG("GPIO29_G6", in_pd),
-	AB8500_PIN_HOG("GPIO30_H6", in_pd),
-
-	/*
-	 * pins 31,32 are muxed in DMIC56
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("dmic56_d_1", "dmic"),
-	AB8500_PIN_HOG("GPIO31_F5", in_pd),
-	AB8500_PIN_HOG("GPIO32_G5", in_pd),
-
-	/*
-	 * pins 34 is muxed in EXTCPENA
-	 * configured INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("extcpena_d_1", "extcpena"),
-	AB8500_PIN_HOG("GPIO34_R17", in_pd),
-
-	/*
-	 * pins 35 is muxed in GPIO
-	 * configured in OUTPUT LOW
-	 */
-	AB8500_MUX_HOG("gpio35_d_1", "gpio"),
-	AB8500_PIN_HOG("GPIO35_W15", in_pd),
-
-	/*
-	 * pins 36,37,38 and 39 are muxed in GPIO
-	 * configured in INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("gpio36_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO36_A17", in_pd),
-
-	AB8500_MUX_HOG("gpio37_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO37_E15", in_pd),
-
-	AB8500_MUX_HOG("gpio38_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO38_C17", in_pd),
-
-	AB8500_MUX_HOG("gpio39_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO39_E16", in_pd),
-
-	/*
-	 * pins 40 and 41 are muxed in MODCSLSDA
-	 * configured INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("modsclsda_d_1", "modsclsda"),
-	AB8500_PIN_HOG("GPIO40_T19", in_pd),
-	AB8500_PIN_HOG("GPIO41_U19", in_pd),
-
-	/*
-	 * pins 42 is muxed in GPIO
-	 * configured INPUT PULL DOWN
-	 */
-	AB8500_MUX_HOG("gpio42_a_1", "gpio"),
-	AB8500_PIN_HOG("GPIO42_U2", in_pd),
-};
-
-static struct pinctrl_map __initdata ab8505_pinmap[] = {
-	/* Sysclkreq2 */
-	AB8505_MUX_STATE("sysclkreq2_d_1", "sysclkreq", "regulator.36", PINCTRL_STATE_DEFAULT),
-	AB8505_PIN_STATE("GPIO1_N4", in_nopull, "regulator.36", PINCTRL_STATE_DEFAULT),
-	/* sysclkreq2 disable, mux in gpio configured in input pulldown */
-	AB8505_MUX_STATE("gpio1_a_1", "gpio", "regulator.36", PINCTRL_STATE_SLEEP),
-	AB8505_PIN_STATE("GPIO1_N4", in_pd, "regulator.36", PINCTRL_STATE_SLEEP),
-
-	/* pins 2 is muxed in GPIO, configured in INPUT PULL DOWN */
-	AB8505_MUX_HOG("gpio2_a_1", "gpio"),
-	AB8505_PIN_HOG("GPIO2_R5", in_pd),
-
-	/* Sysclkreq4 */
-	AB8505_MUX_STATE("sysclkreq4_d_1", "sysclkreq", "regulator.37", PINCTRL_STATE_DEFAULT),
-	AB8505_PIN_STATE("GPIO3_P5", in_nopull, "regulator.37", PINCTRL_STATE_DEFAULT),
-	/* sysclkreq4 disable, mux in gpio configured in input pulldown */
-	AB8505_MUX_STATE("gpio3_a_1", "gpio", "regulator.37", PINCTRL_STATE_SLEEP),
-	AB8505_PIN_STATE("GPIO3_P5", in_pd, "regulator.37", PINCTRL_STATE_SLEEP),
-
-	AB8505_MUX_HOG("gpio10_d_1", "gpio"),
-	AB8505_PIN_HOG("GPIO10_B16", in_pd),
-
-	AB8505_MUX_HOG("gpio11_d_1", "gpio"),
-	AB8505_PIN_HOG("GPIO11_B17", in_pd),
-
-	AB8505_MUX_HOG("gpio13_d_1", "gpio"),
-	AB8505_PIN_HOG("GPIO13_D17", in_nopull),
-
-	AB8505_MUX_HOG("pwmout1_d_1", "pwmout"),
-	AB8505_PIN_HOG("GPIO14_C16", in_pd),
-
-	AB8505_MUX_HOG("adi2_d_1", "adi2"),
-	AB8505_PIN_HOG("GPIO17_P2", in_pd),
-	AB8505_PIN_HOG("GPIO18_N3", in_pd),
-	AB8505_PIN_HOG("GPIO19_T1", in_pd),
-	AB8505_PIN_HOG("GPIO20_P3", in_pd),
-
-	AB8505_MUX_HOG("gpio34_a_1", "gpio"),
-	AB8505_PIN_HOG("GPIO34_H14", in_pd),
-
-	AB8505_MUX_HOG("modsclsda_d_1", "modsclsda"),
-	AB8505_PIN_HOG("GPIO40_J15", in_pd),
-	AB8505_PIN_HOG("GPIO41_J14", in_pd),
-
-	AB8505_MUX_HOG("gpio50_d_1", "gpio"),
-	AB8505_PIN_HOG("GPIO50_L4", in_nopull),
-
-	AB8505_MUX_HOG("resethw_d_1", "resethw"),
-	AB8505_PIN_HOG("GPIO52_D16", in_pd),
-
-	AB8505_MUX_HOG("service_d_1", "service"),
-	AB8505_PIN_HOG("GPIO53_D15", in_pd),
-};
-
-void __init mop500_pinmaps_init(void)
-{
-	if (machine_is_u8520())
-		pinctrl_register_mappings(ab8505_pinmap,
-					  ARRAY_SIZE(ab8505_pinmap));
-	else
-		pinctrl_register_mappings(ab8500_pinmap,
-					  ARRAY_SIZE(ab8500_pinmap));
-}
-
-void __init snowball_pinmaps_init(void)
-{
-	pinctrl_register_mappings(ab8500_pinmap,
-				  ARRAY_SIZE(ab8500_pinmap));
-}
-
-void __init hrefv60_pinmaps_init(void)
-{
-	pinctrl_register_mappings(ab8500_pinmap,
-				  ARRAY_SIZE(ab8500_pinmap));
-}
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index d48e8662c676..bb408b8f48de 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -88,8 +88,4 @@ extern struct msp_i2s_platform_data msp1_platform_data;
 extern struct msp_i2s_platform_data msp2_platform_data;
 extern struct msp_i2s_platform_data msp3_platform_data;
 
-void __init mop500_pinmaps_init(void);
-void __init snowball_pinmaps_init(void);
-void __init hrefv60_pinmaps_init(void);
-
 #endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index bc8a6183560d..180b3c59be36 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -191,16 +191,6 @@ static void __init u8500_init_machine(void)
 {
 	struct device *parent = db8500_soc_device_init();
 
-	/* Pinmaps must be in place before devices register */
-	if (of_machine_is_compatible("st-ericsson,mop500"))
-		mop500_pinmaps_init();
-	else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
-		snowball_pinmaps_init();
-	} else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
-		hrefv60_pinmaps_init();
-	else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
-		/* TODO: Add pinmaps for ccu9540 board. */
-
 	/* automatically probe child nodes of dbx5x0 devices */
 	if (of_machine_is_compatible("st-ericsson,u8540"))
 		of_platform_populate(NULL, u8500_local_bus_nodes,
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index a335126ae18f..f2c89fb8fca9 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -108,7 +108,7 @@ void __init versatile_init_irq(void)
 
 	np = of_find_matching_node_by_address(NULL, vic_of_match,
 					      VERSATILE_VIC_BASE);
-	__vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np);
+	__vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np);
 
 	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
diff --git a/arch/arm/mach-versatile/include/mach/timex.h b/arch/arm/mach-versatile/include/mach/timex.h
deleted file mode 100644
index 426199b1add5..000000000000
--- a/arch/arm/mach-versatile/include/mach/timex.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  arch/arm/mach-versatile/include/mach/timex.h
- *
- *  Versatile architecture timex specifications
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute 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
- */
-
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 4a70be485ff8..657d52d0391f 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -5,17 +5,12 @@ config ARCH_VEXPRESS
 	select ARM_AMBA
 	select ARM_GIC
 	select ARM_TIMER_SP804
-	select COMMON_CLK
 	select COMMON_CLK_VERSATILE
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select HAVE_PATA_PLATFORM
-	select HAVE_SMP
 	select ICST
-	select MIGHT_HAVE_CACHE_L2X0
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_CLCD
 	select POWER_RESET
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 0997e0b7494c..fc649bc09d0c 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -8,8 +8,11 @@ obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
 obj-$(CONFIG_ARCH_VEXPRESS_DCSCB)	+= dcscb.o	dcscb_setup.o
 CFLAGS_dcscb.o				+= -march=armv7-a
+CFLAGS_REMOVE_dcscb.o			= -pg
 obj-$(CONFIG_ARCH_VEXPRESS_SPC)		+= spc.o
+CFLAGS_REMOVE_spc.o			= -pg
 obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM)	+= tc2_pm.o
 CFLAGS_tc2_pm.o				+= -march=armv7-a
+CFLAGS_REMOVE_tc2_pm.o			= -pg
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
diff --git a/arch/arm/mach-virt/Kconfig b/arch/arm/mach-virt/Kconfig
deleted file mode 100644
index 081d46929436..000000000000
--- a/arch/arm/mach-virt/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config ARCH_VIRT
-	bool "Dummy Virtual Machine" if ARCH_MULTI_V7
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select ARM_GIC
-	select HAVE_ARM_ARCH_TIMER
-	select ARM_PSCI
-	select HAVE_SMP
-	select CPU_V7
-	select SPARSE_IRQ
-	select USE_OF
diff --git a/arch/arm/mach-virt/Makefile b/arch/arm/mach-virt/Makefile
deleted file mode 100644
index 7ddbfa60227f..000000000000
--- a/arch/arm/mach-virt/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-obj-y					:= virt.o
diff --git a/arch/arm/mach-virt/virt.c b/arch/arm/mach-virt/virt.c
deleted file mode 100644
index b184e57d1854..000000000000
--- a/arch/arm/mach-virt/virt.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Dummy Virtual Machine - does what it says on the tin.
- *
- * Copyright (C) 2012 ARM Ltd
- * Authors: Will Deacon <will.deacon@arm.com>,
- *          Marc Zyngier <marc.zyngier@arm.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/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/smp.h>
-
-#include <asm/mach/arch.h>
-
-static void __init virt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *virt_dt_match[] = {
-	"linux,dummy-virt",
-	"xen,xenvm",
-	NULL
-};
-
-DT_MACHINE_START(VIRT, "Dummy Virtual Machine")
-	.init_machine	= virt_init,
-	.dt_compat	= virt_dt_match,
-MACHINE_END
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
index 927be93b692e..08f56a41cb55 100644
--- a/arch/arm/mach-vt8500/Kconfig
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -3,8 +3,6 @@ config ARCH_VT8500
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
-	select CLKSRC_OF
-	select GENERIC_CLOCKEVENTS
 	select VT8500_TIMER
 	select PINCTRL
 	help
@@ -21,7 +19,6 @@ config ARCH_WM8750
 	bool "WonderMedia WM8750"
 	depends on ARCH_MULTI_V6
 	select ARCH_VT8500
-	select CPU_V6
 	help
 	  Support for WonderMedia WM8750 System-on-Chip.
 
@@ -29,6 +26,5 @@ config ARCH_WM8850
 	bool "WonderMedia WM8850"
 	depends on ARCH_MULTI_V7
 	select ARCH_VT8500
-	select CPU_V7
 	help
 	  Support for WonderMedia WM8850 System-on-Chip.
diff --git a/arch/arm/mach-w90x900/include/mach/timex.h b/arch/arm/mach-w90x900/include/mach/timex.h
deleted file mode 100644
index 164dce0b64db..000000000000
--- a/arch/arm/mach-w90x900/include/mach/timex.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/timex.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * This program is free software; you can redistribute 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE Now, I don't use it. */
-
-#define CLOCK_TICK_RATE 15000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index 6b04260aa142..105d39b72a25 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -2,16 +2,9 @@ config ARCH_ZYNQ
 	bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
 	select ARM_AMBA
 	select ARM_GIC
-	select COMMON_CLK
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select ICST
-	select MIGHT_HAVE_CACHE_L2X0
-	select USE_OF
-	select HAVE_SMP
-	select SPARSE_IRQ
 	select CADENCE_TTC_TIMER
 	select ARM_GLOBAL_TIMER
 	help
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 1f8fed94c2a4..0809de1e0725 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -446,7 +446,6 @@ config CPU_32v5
 
 config CPU_32v6
 	bool
-	select CPU_USE_DOMAINS if CPU_V6 && MMU
 	select TLS_REG_EMUL if !CPU_32v6K && !MMU
 
 config CPU_32v6K
@@ -671,7 +670,7 @@ config ARM_VIRT_EXT
 
 config SWP_EMULATE
 	bool "Emulate SWP/SWPB instructions"
-	depends on !CPU_USE_DOMAINS && CPU_V7
+	depends on CPU_V7
 	default y if SMP
 	select HAVE_PROC_CPU if PROC_FS
 	help
@@ -855,7 +854,7 @@ config OUTER_CACHE_SYNC
 
 config CACHE_FEROCEON_L2
 	bool "Enable the Feroceon L2 cache controller"
-	depends on ARCH_KIRKWOOD || ARCH_MV78XX0
+	depends on ARCH_KIRKWOOD || ARCH_MV78XX0 || ARCH_MVEBU
 	default y
 	select OUTER_CACHE
 	help
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index 48bc3c0a87ce..dc814a548056 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -13,10 +13,15 @@
  */
 
 #include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/highmem.h>
+#include <linux/io.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
-#include <plat/cache-feroceon-l2.h>
+#include <asm/hardware/cache-feroceon-l2.h>
+
+#define L2_WRITETHROUGH_KIRKWOOD	BIT(4)
 
 /*
  * Low-level cache maintenance operations.
@@ -331,7 +336,9 @@ static void __init enable_l2(void)
 			enable_icache();
 		if (d)
 			enable_dcache();
-	}
+	} else
+		pr_err(FW_BUG
+		       "Feroceon L2: bootloader left the L2 cache on!\n");
 }
 
 void __init feroceon_l2_init(int __l2_wt_override)
@@ -350,3 +357,41 @@ void __init feroceon_l2_init(int __l2_wt_override)
 	printk(KERN_INFO "Feroceon L2: Cache support initialised%s.\n",
 			 l2_wt_override ? ", in WT override mode" : "");
 }
+#ifdef CONFIG_OF
+static const struct of_device_id feroceon_ids[] __initconst = {
+	{ .compatible = "marvell,kirkwood-cache"},
+	{ .compatible = "marvell,feroceon-cache"},
+	{}
+};
+
+int __init feroceon_of_init(void)
+{
+	struct device_node *node;
+	void __iomem *base;
+	bool l2_wt_override = false;
+	struct resource res;
+
+#if defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH)
+	l2_wt_override = true;
+#endif
+
+	node = of_find_matching_node(NULL, feroceon_ids);
+	if (node && of_device_is_compatible(node, "marvell,kirkwood-cache")) {
+		if (of_address_to_resource(node, 0, &res))
+			return -ENODEV;
+
+		base = ioremap(res.start, resource_size(&res));
+		if (!base)
+			return -ENOMEM;
+
+		if (l2_wt_override)
+			writel(readl(base) | L2_WRITETHROUGH_KIRKWOOD, base);
+		else
+			writel(readl(base) & ~L2_WRITETHROUGH_KIRKWOOD, base);
+	}
+
+	feroceon_l2_init(l2_wt_override);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 11b3914660d2..f62aa0677e5c 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -284,9 +284,6 @@ static void __dma_free_buffer(struct page *page, size_t size)
 }
 
 #ifdef CONFIG_MMU
-#ifdef CONFIG_HUGETLB_PAGE
-#warning ARM Coherent DMA allocator does not (yet) support huge TLB
-#endif
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
@@ -1069,6 +1066,8 @@ fs_initcall(dma_debug_do_init);
 
 /* IOMMU */
 
+static int extend_iommu_mapping(struct dma_iommu_mapping *mapping);
+
 static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
 				      size_t size)
 {
@@ -1076,41 +1075,87 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
 	unsigned int align = 0;
 	unsigned int count, start;
 	unsigned long flags;
+	dma_addr_t iova;
+	int i;
 
 	if (order > CONFIG_ARM_DMA_IOMMU_ALIGNMENT)
 		order = CONFIG_ARM_DMA_IOMMU_ALIGNMENT;
 
-	count = ((PAGE_ALIGN(size) >> PAGE_SHIFT) +
-		 (1 << mapping->order) - 1) >> mapping->order;
-
-	if (order > mapping->order)
-		align = (1 << (order - mapping->order)) - 1;
+	count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	align = (1 << order) - 1;
 
 	spin_lock_irqsave(&mapping->lock, flags);
-	start = bitmap_find_next_zero_area(mapping->bitmap, mapping->bits, 0,
-					   count, align);
-	if (start > mapping->bits) {
-		spin_unlock_irqrestore(&mapping->lock, flags);
-		return DMA_ERROR_CODE;
+	for (i = 0; i < mapping->nr_bitmaps; i++) {
+		start = bitmap_find_next_zero_area(mapping->bitmaps[i],
+				mapping->bits, 0, count, align);
+
+		if (start > mapping->bits)
+			continue;
+
+		bitmap_set(mapping->bitmaps[i], start, count);
+		break;
 	}
 
-	bitmap_set(mapping->bitmap, start, count);
+	/*
+	 * No unused range found. Try to extend the existing mapping
+	 * and perform a second attempt to reserve an IO virtual
+	 * address range of size bytes.
+	 */
+	if (i == mapping->nr_bitmaps) {
+		if (extend_iommu_mapping(mapping)) {
+			spin_unlock_irqrestore(&mapping->lock, flags);
+			return DMA_ERROR_CODE;
+		}
+
+		start = bitmap_find_next_zero_area(mapping->bitmaps[i],
+				mapping->bits, 0, count, align);
+
+		if (start > mapping->bits) {
+			spin_unlock_irqrestore(&mapping->lock, flags);
+			return DMA_ERROR_CODE;
+		}
+
+		bitmap_set(mapping->bitmaps[i], start, count);
+	}
 	spin_unlock_irqrestore(&mapping->lock, flags);
 
-	return mapping->base + (start << (mapping->order + PAGE_SHIFT));
+	iova = mapping->base + (mapping->size * i);
+	iova += start << PAGE_SHIFT;
+
+	return iova;
 }
 
 static inline void __free_iova(struct dma_iommu_mapping *mapping,
 			       dma_addr_t addr, size_t size)
 {
-	unsigned int start = (addr - mapping->base) >>
-			     (mapping->order + PAGE_SHIFT);
-	unsigned int count = ((size >> PAGE_SHIFT) +
-			      (1 << mapping->order) - 1) >> mapping->order;
+	unsigned int start, count;
 	unsigned long flags;
+	dma_addr_t bitmap_base;
+	u32 bitmap_index;
+
+	if (!size)
+		return;
+
+	bitmap_index = (u32) (addr - mapping->base) / (u32) mapping->size;
+	BUG_ON(addr < mapping->base || bitmap_index > mapping->extensions);
+
+	bitmap_base = mapping->base + mapping->size * bitmap_index;
+
+	start = (addr - bitmap_base) >>	PAGE_SHIFT;
+
+	if (addr + size > bitmap_base + mapping->size) {
+		/*
+		 * The address range to be freed reaches into the iova
+		 * range of the next bitmap. This should not happen as
+		 * we don't allow this in __alloc_iova (at the
+		 * moment).
+		 */
+		BUG();
+	} else
+		count = size >> PAGE_SHIFT;
 
 	spin_lock_irqsave(&mapping->lock, flags);
-	bitmap_clear(mapping->bitmap, start, count);
+	bitmap_clear(mapping->bitmaps[bitmap_index], start, count);
 	spin_unlock_irqrestore(&mapping->lock, flags);
 }
 
@@ -1875,8 +1920,7 @@ struct dma_map_ops iommu_coherent_ops = {
  * arm_iommu_create_mapping
  * @bus: pointer to the bus holding the client device (for IOMMU calls)
  * @base: start address of the valid IO address space
- * @size: size of the valid IO address space
- * @order: accuracy of the IO addresses allocations
+ * @size: maximum size of the valid IO address space
  *
  * Creates a mapping structure which holds information about used/unused
  * IO address ranges, which is required to perform memory allocation and
@@ -1886,38 +1930,54 @@ struct dma_map_ops iommu_coherent_ops = {
  * arm_iommu_attach_device function.
  */
 struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-			 int order)
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
 {
-	unsigned int count = size >> (PAGE_SHIFT + order);
-	unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
+	unsigned int bits = size >> PAGE_SHIFT;
+	unsigned int bitmap_size = BITS_TO_LONGS(bits) * sizeof(long);
 	struct dma_iommu_mapping *mapping;
+	int extensions = 1;
 	int err = -ENOMEM;
 
-	if (!count)
+	if (!bitmap_size)
 		return ERR_PTR(-EINVAL);
 
+	if (bitmap_size > PAGE_SIZE) {
+		extensions = bitmap_size / PAGE_SIZE;
+		bitmap_size = PAGE_SIZE;
+	}
+
 	mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
 	if (!mapping)
 		goto err;
 
-	mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!mapping->bitmap)
+	mapping->bitmap_size = bitmap_size;
+	mapping->bitmaps = kzalloc(extensions * sizeof(unsigned long *),
+				GFP_KERNEL);
+	if (!mapping->bitmaps)
 		goto err2;
 
+	mapping->bitmaps[0] = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!mapping->bitmaps[0])
+		goto err3;
+
+	mapping->nr_bitmaps = 1;
+	mapping->extensions = extensions;
 	mapping->base = base;
+	mapping->size = bitmap_size << PAGE_SHIFT;
 	mapping->bits = BITS_PER_BYTE * bitmap_size;
-	mapping->order = order;
+
 	spin_lock_init(&mapping->lock);
 
 	mapping->domain = iommu_domain_alloc(bus);
 	if (!mapping->domain)
-		goto err3;
+		goto err4;
 
 	kref_init(&mapping->kref);
 	return mapping;
+err4:
+	kfree(mapping->bitmaps[0]);
 err3:
-	kfree(mapping->bitmap);
+	kfree(mapping->bitmaps);
 err2:
 	kfree(mapping);
 err:
@@ -1927,14 +1987,35 @@ EXPORT_SYMBOL_GPL(arm_iommu_create_mapping);
 
 static void release_iommu_mapping(struct kref *kref)
 {
+	int i;
 	struct dma_iommu_mapping *mapping =
 		container_of(kref, struct dma_iommu_mapping, kref);
 
 	iommu_domain_free(mapping->domain);
-	kfree(mapping->bitmap);
+	for (i = 0; i < mapping->nr_bitmaps; i++)
+		kfree(mapping->bitmaps[i]);
+	kfree(mapping->bitmaps);
 	kfree(mapping);
 }
 
+static int extend_iommu_mapping(struct dma_iommu_mapping *mapping)
+{
+	int next_bitmap;
+
+	if (mapping->nr_bitmaps > mapping->extensions)
+		return -EINVAL;
+
+	next_bitmap = mapping->nr_bitmaps;
+	mapping->bitmaps[next_bitmap] = kzalloc(mapping->bitmap_size,
+						GFP_ATOMIC);
+	if (!mapping->bitmaps[next_bitmap])
+		return -ENOMEM;
+
+	mapping->nr_bitmaps++;
+
+	return 0;
+}
+
 void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
 {
 	if (mapping)
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
index 2b3a56414271..ef69152f9b52 100644
--- a/arch/arm/mm/dump.c
+++ b/arch/arm/mm/dump.c
@@ -264,6 +264,9 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
 			note_page(st, addr, 3, pmd_val(*pmd));
 		else
 			walk_pte(st, pmd, addr);
+
+		if (SECTION_SIZE < PMD_SIZE && pmd_large(pmd[1]))
+			note_page(st, addr + SECTION_SIZE, 3, pmd_val(pmd[1]));
 	}
 }
 
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 804d61566a53..42fc139bbed4 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;
@@ -327,7 +328,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();
@@ -576,7 +578,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/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index a623cb3ad012..b68c6b22e1c8 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -516,6 +516,16 @@ static void __init build_mem_type_table(void)
 	s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
 
 	/*
+	 * We don't use domains on ARMv6 (since this causes problems with
+	 * v6/v7 kernels), so we must use a separate memory type for user
+	 * r/o, kernel r/w to map the vectors page.
+	 */
+#ifndef CONFIG_ARM_LPAE
+	if (cpu_arch == CPU_ARCH_ARMv6)
+		vecs_pgprot |= L_PTE_MT_VECTORS;
+#endif
+
+	/*
 	 * ARMv6 and above have extended page tables.
 	 */
 	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index e3c48a3fe063..ee1d80593958 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -112,13 +112,9 @@
  *  100x   1   0   1	r/o	no acc
  *  10x0   1   0   1	r/o	no acc
  *  1011   0   0   1	r/w	no acc
- *  110x   0   1   0	r/w	r/o
- *  11x0   0   1   0	r/w	r/o
- *  1111   0   1   1	r/w	r/w
- *
- * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
  *  110x   1   1   1	r/o	r/o
  *  11x0   1   1   1	r/o	r/o
+ *  1111   0   1   1	r/w	r/w
  */
 	.macro	armv6_mt_table pfx
 \pfx\()_mt_table:
@@ -137,7 +133,7 @@
 	.long	PTE_EXT_TEX(2)					@ L_PTE_MT_DEV_NONSHARED
 	.long	0x00						@ unused
 	.long	0x00						@ unused
-	.long	0x00						@ unused
+	.long	PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX	@ L_PTE_MT_VECTORS
 	.endm
 
 	.macro	armv6_set_pte_ext pfx
@@ -158,24 +154,21 @@
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
-#ifdef CONFIG_CPU_USE_DOMAINS
-	@ allow kernel read/write access to read-only user pages
 	tstne	r3, #PTE_EXT_APX
-	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
-#endif
+
+	@ user read-only -> kernel read-only
+	bicne	r3, r3, #PTE_EXT_AP0
 
 	tst	r1, #L_PTE_XN
 	orrne	r3, r3, #PTE_EXT_XN
 
-	orr	r3, r3, r2
+	eor	r3, r3, r2
 
 	tst	r1, #L_PTE_YOUNG
 	tstne	r1, #L_PTE_PRESENT
 	moveq	r3, #0
-#ifndef CONFIG_CPU_USE_DOMAINS
 	tstne	r1, #L_PTE_NONE
 	movne	r3, #0
-#endif
 
 	str	r3, [r0]
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index bdd3be4be77a..1f52915f2b28 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext)
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
-#ifdef CONFIG_CPU_USE_DOMAINS
-	@ allow kernel read/write access to read-only user pages
-	tstne	r3, #PTE_EXT_APX
-	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
-#endif
 
 	tst	r1, #L_PTE_XN
 	orrne	r3, r3, #PTE_EXT_XN
 
 	tst	r1, #L_PTE_YOUNG
 	tstne	r1, #L_PTE_VALID
-#ifndef CONFIG_CPU_USE_DOMAINS
 	eorne	r1, r1, #L_PTE_NONE
 	tstne	r1, #L_PTE_NONE
-#endif
 	moveq	r3, #0
 
  ARM(	str	r3, [r0, #2048]! )
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 74f6033e76dd..195731d3813b 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -192,6 +192,7 @@ __v7_cr7mp_setup:
 	mov	r10, #(1 << 0)			@ Cache/TLB ops broadcasting
 	b	1f
 __v7_ca7mp_setup:
+__v7_ca12mp_setup:
 __v7_ca15mp_setup:
 	mov	r10, #0
 1:
@@ -484,6 +485,16 @@ __v7_ca7mp_proc_info:
 	.size	__v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
 
 	/*
+	 * ARM Ltd. Cortex A12 processor.
+	 */
+	.type	__v7_ca12mp_proc_info, #object
+__v7_ca12mp_proc_info:
+	.long	0x410fc0d0
+	.long	0xff0ffff0
+	__v7_proc __v7_ca12mp_setup
+	.size	__v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info
+
+	/*
 	 * ARM Ltd. Cortex A15 processor.
 	 */
 	.type	__v7_ca15mp_proc_info, #object
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 01619c2910e3..5f5b975887fc 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2000,6 +2000,12 @@ void omap_dma_global_context_restore(void)
 			omap_clear_dma(ch);
 }
 
+struct omap_system_dma_plat_info *omap_get_plat_info(void)
+{
+	return p;
+}
+EXPORT_SYMBOL_GPL(omap_get_plat_info);
+
 static int omap_system_dma_probe(struct platform_device *pdev)
 {
 	int ch, ret = 0;
@@ -2024,9 +2030,16 @@ static int omap_system_dma_probe(struct platform_device *pdev)
 
 	dma_lch_count		= d->lch_count;
 	dma_chan_count		= dma_lch_count;
-	dma_chan		= d->chan;
 	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
+	dma_chan = devm_kcalloc(&pdev->dev, dma_lch_count,
+				sizeof(struct omap_dma_lch), GFP_KERNEL);
+	if (!dma_chan) {
+		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
+
+
 	if (dma_omap2plus()) {
 		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
 						dma_lch_count, GFP_KERNEL);
@@ -2111,7 +2124,6 @@ exit_dma_irq_fail:
 	}
 
 exit_dma_lch_fail:
-	kfree(dma_chan);
 	return ret;
 }
 
@@ -2131,7 +2143,6 @@ static int omap_system_dma_remove(struct platform_device *pdev)
 			free_irq(dma_irq, (void *)(irq_rel + 1));
 		}
 	}
-	kfree(dma_chan);
 	return 0;
 }
 
diff --git a/arch/arm/plat-omap/include/plat/timex.h b/arch/arm/plat-omap/include/plat/timex.h
deleted file mode 100644
index e27d2daa7790..000000000000
--- a/arch/arm/plat-omap/include/plat/timex.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/timex.h
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author:  Greg Lonnon <glonnon@ridgerun.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 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.
- */
-
-#if !defined(__ASM_ARCH_OMAP_TIMEX_H)
-#define __ASM_ARCH_OMAP_TIMEX_H
-
-#define CLOCK_TICK_RATE		(HZ * 100000UL)
-
-#endif /* __ASM_ARCH_OMAP_TIMEX_H */
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 830ff07f3385..3ec6e8e8d368 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase)
 /*****************************************************************************
  * Watchdog
  ****************************************************************************/
-static struct resource orion_wdt_resource =
-		DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28);
+static struct resource orion_wdt_resource[] = {
+		DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04),
+		DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04),
+};
 
 static struct platform_device orion_wdt_device = {
 	.name		= "orion_wdt",
 	.id		= -1,
-	.num_resources	= 1,
-	.resource	= &orion_wdt_resource,
+	.num_resources	= ARRAY_SIZE(orion_wdt_resource),
+	.resource	= orion_wdt_resource,
 };
 
 void __init orion_wdt_init(void)
diff --git a/arch/arm/plat-orion/include/plat/cache-feroceon-l2.h b/arch/arm/plat-orion/include/plat/cache-feroceon-l2.h
deleted file mode 100644
index 06f982d55697..000000000000
--- a/arch/arm/plat-orion/include/plat/cache-feroceon-l2.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/cache-feroceon-l2.h
- *
- * Copyright (C) 2008 Marvell Semiconductor
- *
- * 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.
- */
-
-extern void __init feroceon_l2_init(int l2_wt_override);
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 58645a58d0d8..ac0366858e94 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -9,7 +9,7 @@ config PLAT_SAMSUNG
 	depends on PLAT_S3C24XX || ARCH_S3C64XX || PLAT_S5P || ARCH_EXYNOS
 	default y
 	select GENERIC_IRQ_CHIP
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	help
 	  Base platform code for all Samsung SoC based systems
 
@@ -19,7 +19,7 @@ config PLAT_S5P
 	default y
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_VIC
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select PLAT_SAMSUNG
 	select S3C_GPIO_TRACK
 	select S5P_GPIO_DRVSTR
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 47c9fad43f00..ddfebddb4105 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -52,7 +52,7 @@
 #include <plat/cpu.h>
 
 #include <linux/serial_core.h>
-#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
+#include <linux/serial_s3c.h> /* for s3c24xx_uart_devs */
 
 /* clock information */
 
diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c
index 46b426e8aff5..364963a0a344 100644
--- a/arch/arm/plat-samsung/cpu.c
+++ b/arch/arm/plat-samsung/cpu.c
@@ -28,13 +28,6 @@ unsigned int samsung_rev(void)
 }
 EXPORT_SYMBOL(samsung_rev);
 
-void __init s3c24xx_init_cpu(void)
-{
-	/* nothing here yet */
-
-	samsung_cpu_rev = 0;
-}
-
 void __init s3c64xx_init_cpu(void)
 {
 	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index ac07e871f6a7..c64a39ac1b04 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -18,6 +18,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
@@ -64,7 +65,6 @@
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/usb-phy.h>
-#include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
 #include <linux/platform_data/spi-s3c64xx.h>
 
@@ -744,10 +744,7 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
 	if (!pd) {
 		pd = &default_i2c_data;
 
-		if (soc_is_exynos4210() ||
-		    soc_is_exynos4212() || soc_is_exynos4412())
-			pd->bus_num = 8;
-		else if (soc_is_s5pv210())
+		if (soc_is_s5pv210())
 			pd->bus_num = 3;
 		else
 			pd->bus_num = 0;
@@ -764,10 +761,7 @@ void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
 {
 	struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata;
 
-	if (soc_is_exynos4210() ||
-	    soc_is_exynos4212() || soc_is_exynos4412())
-		pd->hdmiphy_bus = 8;
-	else if (soc_is_s5pv210())
+	if (soc_is_s5pv210())
 		pd->hdmiphy_bus = 3;
 	else
 		pd->hdmiphy_bus = 0;
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 335beb341355..31164b34d4c4 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -199,7 +199,6 @@ extern void s5p_init_irq(u32 *vic, u32 num_vic);
 
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
 
-extern void s3c24xx_init_cpu(void);
 extern void s3c64xx_init_cpu(void);
 extern void s5p_init_cpu(void __iomem *cpuid_addr);
 
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
deleted file mode 100644
index f05f2afa440d..000000000000
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/serial_s3c.h>
diff --git a/arch/arm/plat-samsung/include/plat/rtc-core.h b/arch/arm/plat-samsung/include/plat/rtc-core.h
deleted file mode 100644
index 7b542f7b7938..000000000000
--- a/arch/arm/plat-samsung/include/plat/rtc-core.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h
- *
- * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
- *
- * Samsung RTC Controller core functions
- *
- * 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 __ASM_PLAT_RTC_CORE_H
-#define __ASM_PLAT_RTC_CORE_H __FILE__
-
-/* These functions are only for use with the core support code, such as
- * the cpu specific initialisation code
- */
-
-/* re-define device name depending on support. */
-static inline void s3c_rtc_setname(char *name)
-{
-#if defined(CONFIG_S3C_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
-	s3c_device_rtc.name = name;
-#endif
-}
-
-#endif /* __ASM_PLAT_RTC_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h
index f48dc0a4736c..61054fd88d43 100644
--- a/arch/arm/plat-samsung/include/plat/uncompress.h
+++ b/arch/arm/plat-samsung/include/plat/uncompress.h
@@ -29,7 +29,7 @@ static void arch_detect_cpu(void);
 
 /* defines for UART registers */
 
-#include <plat/regs-serial.h>
+#include <linux/serial_s3c.h>
 
 /* working in physical space... */
 #define S3C_WDOGREG(x)	((S3C_PA_WDT + (x)))
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c
index aa9511b6914a..0ffc84aaf60e 100644
--- a/arch/arm/plat-samsung/init.c
+++ b/arch/arm/plat-samsung/init.c
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 
@@ -33,8 +34,6 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 
-#include <plat/regs-serial.h>
-
 static struct cpu_table *cpu;
 
 static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index dd4c15d0d68f..da268813901b 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -196,8 +196,7 @@ struct samsung_gpio_pm samsung_gpio_pm_2bit = {
 	.resume = samsung_gpio_pm_2bit_resume,
 };
 
-#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P) \
-	|| defined(CONFIG_ARCH_EXYNOS)
+#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
 static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
@@ -307,7 +306,7 @@ struct samsung_gpio_pm samsung_gpio_pm_4bit = {
 	.save	= samsung_gpio_pm_4bit_save,
 	.resume = samsung_gpio_pm_4bit_resume,
 };
-#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P || CONFIG_ARCH_EXYNOS */
+#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
  * samsung_pm_save_gpio() - save gpio chip data for suspend
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index e5b0f2c2d884..ae9baa2d6381 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -18,13 +18,12 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/serial_core.h>
+#include <linux/serial_s3c.h>
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
 #include <asm/suspend.h>
 
-#include <plat/regs-serial.h>
-
 #ifdef CONFIG_SAMSUNG_ATAGS
 #include <mach/hardware.h>
 #include <mach/map.h>
diff --git a/arch/arm/plat-samsung/s5p-irq-pm.c b/arch/arm/plat-samsung/s5p-irq-pm.c
index 591498035916..52b16943617e 100644
--- a/arch/arm/plat-samsung/s5p-irq-pm.c
+++ b/arch/arm/plat-samsung/s5p-irq-pm.c
@@ -22,10 +22,7 @@
 #include <mach/map.h>
 
 #include <mach/regs-gpio.h>
-
-#ifndef CONFIG_ARCH_EXYNOS
 #include <mach/regs-irq.h>
-#endif
 
 /* state for IRQs over sleep */
 
@@ -43,18 +40,8 @@ int s3c_irq_wake(struct irq_data *data, unsigned int state)
 	unsigned long irqbit;
 	unsigned int irq_rtc_tic, irq_rtc_alarm;
 
-#ifdef CONFIG_ARCH_EXYNOS
-	if (soc_is_exynos5250()) {
-		irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC;
-		irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM;
-	} else {
-		irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC;
-		irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM;
-	}
-#else
 	irq_rtc_tic = IRQ_RTC_TIC;
 	irq_rtc_alarm = IRQ_RTC_ALARM;
-#endif
 
 	if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) {
 		irqbit = 1 << (data->irq + 1 - irq_rtc_alarm);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc7202a..764d682d04ec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -26,6 +26,7 @@ config ARM64
 	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
+	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
@@ -61,7 +62,7 @@ config ARCH_PHYS_ADDR_T_64BIT
 config MMU
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config STACKTRACE_SUPPORT
@@ -85,7 +86,7 @@ config GENERIC_CSUM
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
 
-config ZONE_DMA32
+config ZONE_DMA
 	def_bool y
 
 config ARCH_DMA_ADDR_T_64BIT
@@ -303,6 +304,14 @@ source "drivers/cpuidle/Kconfig"
 
 endmenu
 
+menu "Power management options"
+
+source "kernel/power/Kconfig"
+
+source "drivers/cpufreq/Kconfig"
+
+endmenu
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 71c53ecfcc3a..3bdfdda70567 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -12,6 +12,7 @@ generic-y += dma.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += ftrace.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -22,12 +23,14 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += pci.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -38,8 +41,8 @@ generic-y += shmbuf.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += switch_to.h
 generic-y += swab.h
+generic-y += switch_to.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -49,5 +52,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 889324981aa4..4c60e64a801c 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -85,6 +85,13 @@ static inline void flush_cache_page(struct vm_area_struct *vma,
 }
 
 /*
+ * Cache maintenance functions used by the DMA API. No to be used directly.
+ */
+extern void __dma_map_area(const void *, size_t, int);
+extern void __dma_unmap_area(const void *, size_t, int);
+extern void __dma_flush_range(const void *, const void *);
+
+/*
  * Copy user data from/to a page which is mapped into a different
  * processes address space.  Really, we want to allow our "user
  * space" model to handle this.
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index 62314791570c..6e9b5b36921c 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -26,6 +26,53 @@
 #define DBG_ESR_EVT_HWWP	0x2
 #define DBG_ESR_EVT_BRK		0x6
 
+/*
+ * Break point instruction encoding
+ */
+#define BREAK_INSTR_SIZE		4
+
+/*
+ * ESR values expected for dynamic and compile time BRK instruction
+ */
+#define DBG_ESR_VAL_BRK(x)	(0xf2000000 | ((x) & 0xfffff))
+
+/*
+ * #imm16 values used for BRK instruction generation
+ * Allowed values for kgbd are 0x400 - 0x7ff
+ * 0x400: for dynamic BRK instruction
+ * 0x401: for compile time BRK instruction
+ */
+#define KGDB_DYN_DGB_BRK_IMM		0x400
+#define KDBG_COMPILED_DBG_BRK_IMM	0x401
+
+/*
+ * BRK instruction encoding
+ * The #imm16 value should be placed at bits[20:5] within BRK ins
+ */
+#define AARCH64_BREAK_MON	0xd4200000
+
+/*
+ * Extract byte from BRK instruction
+ */
+#define KGDB_DYN_DGB_BRK_INS_BYTE(x) \
+	((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff)
+
+/*
+ * Extract byte from BRK #imm16
+ */
+#define KGBD_DYN_DGB_BRK_IMM_BYTE(x) \
+	(((((KGDB_DYN_DGB_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff)
+
+#define KGDB_DYN_DGB_BRK_BYTE(x) \
+	(KGDB_DYN_DGB_BRK_INS_BYTE(x) | KGBD_DYN_DGB_BRK_IMM_BYTE(x))
+
+#define  KGDB_DYN_BRK_INS_BYTE0  KGDB_DYN_DGB_BRK_BYTE(0)
+#define  KGDB_DYN_BRK_INS_BYTE1  KGDB_DYN_DGB_BRK_BYTE(1)
+#define  KGDB_DYN_BRK_INS_BYTE2  KGDB_DYN_DGB_BRK_BYTE(2)
+#define  KGDB_DYN_BRK_INS_BYTE3  KGDB_DYN_DGB_BRK_BYTE(3)
+
+#define CACHE_FLUSH_IS_SAFE		1
+
 enum debug_el {
 	DBG_ACTIVE_EL0 = 0,
 	DBG_ACTIVE_EL1,
@@ -43,23 +90,6 @@ enum debug_el {
 #ifndef __ASSEMBLY__
 struct task_struct;
 
-#define local_dbg_save(flags)							\
-	do {									\
-		typecheck(unsigned long, flags);				\
-		asm volatile(							\
-		"mrs	%0, daif			// local_dbg_save\n"	\
-		"msr	daifset, #8"						\
-		: "=r" (flags) : : "memory");					\
-	} while (0)
-
-#define local_dbg_restore(flags)						\
-	do {									\
-		typecheck(unsigned long, flags);				\
-		asm volatile(							\
-		"msr	daif, %0			// local_dbg_restore\n"	\
-		: : "r" (flags) : "memory");					\
-	} while (0)
-
 #define DBG_ARCH_ID_RESERVED	0	/* In case of ptrace ABI updates. */
 
 #define DBG_HOOK_HANDLED	0
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index fd0c0c0e447a..3a4572ec3273 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -30,6 +30,8 @@
 
 #define DMA_ERROR_CODE	(~(dma_addr_t)0)
 extern struct dma_map_ops *dma_ops;
+extern struct dma_map_ops coherent_swiotlb_dma_ops;
+extern struct dma_map_ops noncoherent_swiotlb_dma_ops;
 
 static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
 {
@@ -47,6 +49,11 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 		return __generic_dma_ops(dev);
 }
 
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+	dev->archdata.dma_ops = ops;
+}
+
 #include <asm-generic/dma-mapping-common.h>
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 4cc813eddacb..7846a6bb0833 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -121,7 +121,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
  *  I/O port access primitives.
  */
 #define IO_SPACE_LIMIT		0xffff
-#define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_2M))
+#define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_32M))
 
 static inline u8 inb(unsigned long addr)
 {
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
index b2fcfbc51ecc..11cc941bd107 100644
--- a/arch/arm64/include/asm/irqflags.h
+++ b/arch/arm64/include/asm/irqflags.h
@@ -90,5 +90,28 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 	return flags & PSR_I_BIT;
 }
 
+/*
+ * save and restore debug state
+ */
+#define local_dbg_save(flags)						\
+	do {								\
+		typecheck(unsigned long, flags);			\
+		asm volatile(						\
+		"mrs    %0, daif		// local_dbg_save\n"	\
+		"msr    daifset, #8"					\
+		: "=r" (flags) : : "memory");				\
+	} while (0)
+
+#define local_dbg_restore(flags)					\
+	do {								\
+		typecheck(unsigned long, flags);			\
+		asm volatile(						\
+		"msr    daif, %0		// local_dbg_restore\n"	\
+		: : "r" (flags) : "memory");				\
+	} while (0)
+
+#define local_dbg_enable()	asm("msr	daifclr, #8" : : : "memory")
+#define local_dbg_disable()	asm("msr	daifset, #8" : : : "memory")
+
 #endif
 #endif
diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
new file mode 100644
index 000000000000..3c8aafc1082f
--- /dev/null
+++ b/arch/arm64/include/asm/kgdb.h
@@ -0,0 +1,84 @@
+/*
+ * AArch64 KGDB support
+ *
+ * Based on arch/arm/include/kgdb.h
+ *
+ * Copyright (C) 2013 Cavium Inc.
+ * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.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 __ARM_KGDB_H
+#define __ARM_KGDB_H
+
+#include <linux/ptrace.h>
+#include <asm/debug-monitors.h>
+
+#ifndef	__ASSEMBLY__
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm ("brk %0" : : "I" (KDBG_COMPILED_DBG_BRK_IMM));
+}
+
+extern void kgdb_handle_bus_error(void);
+extern int kgdb_fault_expected;
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * gdb is expecting the following registers layout.
+ *
+ * General purpose regs:
+ *     r0-r30: 64 bit
+ *     sp,pc : 64 bit
+ *     pstate  : 64 bit
+ *     Total: 34
+ * FPU regs:
+ *     f0-f31: 128 bit
+ *     Total: 32
+ * Extra regs
+ *     fpsr & fpcr: 32 bit
+ *     Total: 2
+ *
+ */
+
+#define _GP_REGS		34
+#define _FP_REGS		32
+#define _EXTRA_REGS		2
+/*
+ * general purpose registers size in bytes.
+ * pstate is only 4 bytes. subtract 4 bytes
+ */
+#define GP_REG_BYTES		(_GP_REGS * 8)
+#define DBG_MAX_REG_NUM		(_GP_REGS + _FP_REGS + _EXTRA_REGS)
+
+/*
+ * Size of I/O buffer for gdb packet.
+ * considering to hold all register contents, size is set
+ */
+
+#define BUFMAX			2048
+
+/*
+ * Number of bytes required for gdb_regs buffer.
+ * _GP_REGS: 8 bytes, _FP_REGS: 16 bytes and _EXTRA_REGS: 4 bytes each
+ * GDB fails to connect for size beyond this with error
+ * "'g' packet reply is too long"
+ */
+
+#define NUMREGBYTES	((_GP_REGS * 8) + (_FP_REGS * 16) + \
+			(_EXTRA_REGS * 4))
+
+#endif /* __ASM_KGDB_H */
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index e5312ea0ec1a..d15ab8b46336 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,6 +14,6 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
-int psci_init(void);
+void psci_init(void);
 
 #endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0e7fa4963735..5233966fba3d 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -164,7 +164,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs)
 	return 0;
 }
 
-#define instruction_pointer(regs)	(regs)->pc
+#define instruction_pointer(regs)	((unsigned long)(regs)->pc)
 
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 717031a762c2..72cadf52ca80 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -19,115 +19,44 @@
 #ifndef __ASM_TLB_H
 #define __ASM_TLB_H
 
-#include <linux/pagemap.h>
-#include <linux/swap.h>
 
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-
-#define MMU_GATHER_BUNDLE	8
-
-/*
- * TLB handling.  This allows us to remove pages from the page
- * tables, and efficiently handle the TLB issues.
- */
-struct mmu_gather {
-	struct mm_struct	*mm;
-	unsigned int		fullmm;
-	struct vm_area_struct	*vma;
-	unsigned long		start, end;
-	unsigned long		range_start;
-	unsigned long		range_end;
-	unsigned int		nr;
-	unsigned int		max;
-	struct page		**pages;
-	struct page		*local[MMU_GATHER_BUNDLE];
-};
+#include <asm-generic/tlb.h>
 
 /*
- * This is unnecessarily complex.  There's three ways the TLB shootdown
- * code is used:
+ * There's three ways the TLB shootdown code is used:
  *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region().
  *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called.
- *     tlb->vma will be non-NULL.
  *  2. Unmapping all vmas.  See exit_mmap().
  *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called.
- *     tlb->vma will be non-NULL.  Additionally, page tables will be freed.
+ *     Page tables will be freed.
  *  3. Unmapping argument pages.  See shift_arg_pages().
  *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called.
- *     tlb->vma will be NULL.
  */
 static inline void tlb_flush(struct mmu_gather *tlb)
 {
-	if (tlb->fullmm || !tlb->vma)
+	if (tlb->fullmm) {
 		flush_tlb_mm(tlb->mm);
-	else if (tlb->range_end > 0) {
-		flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end);
-		tlb->range_start = TASK_SIZE;
-		tlb->range_end = 0;
+	} else if (tlb->end > 0) {
+		struct vm_area_struct vma = { .vm_mm = tlb->mm, };
+		flush_tlb_range(&vma, tlb->start, tlb->end);
+		tlb->start = TASK_SIZE;
+		tlb->end = 0;
 	}
 }
 
 static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
 {
 	if (!tlb->fullmm) {
-		if (addr < tlb->range_start)
-			tlb->range_start = addr;
-		if (addr + PAGE_SIZE > tlb->range_end)
-			tlb->range_end = addr + PAGE_SIZE;
-	}
-}
-
-static inline void __tlb_alloc_page(struct mmu_gather *tlb)
-{
-	unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
-
-	if (addr) {
-		tlb->pages = (void *)addr;
-		tlb->max = PAGE_SIZE / sizeof(struct page *);
+		tlb->start = min(tlb->start, addr);
+		tlb->end = max(tlb->end, addr + PAGE_SIZE);
 	}
 }
 
-static inline void tlb_flush_mmu(struct mmu_gather *tlb)
-{
-	tlb_flush(tlb);
-	free_pages_and_swap_cache(tlb->pages, tlb->nr);
-	tlb->nr = 0;
-	if (tlb->pages == tlb->local)
-		__tlb_alloc_page(tlb);
-}
-
-static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	tlb->mm = mm;
-	tlb->fullmm = !(start | (end+1));
-	tlb->start = start;
-	tlb->end = end;
-	tlb->vma = NULL;
-	tlb->max = ARRAY_SIZE(tlb->local);
-	tlb->pages = tlb->local;
-	tlb->nr = 0;
-	__tlb_alloc_page(tlb);
-}
-
-static inline void
-tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
-{
-	tlb_flush_mmu(tlb);
-
-	/* keep the page table cache within bounds */
-	check_pgt_cache();
-
-	if (tlb->pages != tlb->local)
-		free_pages((unsigned long)tlb->pages, 0);
-}
-
 /*
  * Memorize the range for the TLB flush.
  */
-static inline void
-tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
+static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
+					  unsigned long addr)
 {
 	tlb_add_flush(tlb, addr);
 }
@@ -137,38 +66,24 @@ tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
  * case where we're doing a full MM flush.  When we're doing a munmap,
  * the vmas are adjusted to only cover the region to be torn down.
  */
-static inline void
-tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+static inline void tlb_start_vma(struct mmu_gather *tlb,
+				 struct vm_area_struct *vma)
 {
 	if (!tlb->fullmm) {
-		tlb->vma = vma;
-		tlb->range_start = TASK_SIZE;
-		tlb->range_end = 0;
+		tlb->start = TASK_SIZE;
+		tlb->end = 0;
 	}
 }
 
-static inline void
-tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+static inline void tlb_end_vma(struct mmu_gather *tlb,
+			       struct vm_area_struct *vma)
 {
 	if (!tlb->fullmm)
 		tlb_flush(tlb);
 }
 
-static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
-{
-	tlb->pages[tlb->nr++] = page;
-	VM_BUG_ON(tlb->nr > tlb->max);
-	return tlb->max - tlb->nr;
-}
-
-static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
-{
-	if (!__tlb_remove_page(tlb, page))
-		tlb_flush_mmu(tlb);
-}
-
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
-	unsigned long addr)
+				  unsigned long addr)
 {
 	pgtable_page_dtor(pte);
 	tlb_add_flush(tlb, addr);
@@ -184,16 +99,5 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
 }
 #endif
 
-#define pte_free_tlb(tlb, ptep, addr)	__pte_free_tlb(tlb, ptep, addr)
-#define pmd_free_tlb(tlb, pmdp, addr)	__pmd_free_tlb(tlb, pmdp, addr)
-#define pud_free_tlb(tlb, pudp, addr)	pud_free((tlb)->mm, pudp)
-
-#define tlb_migrate_finish(mm)		do { } while (0)
-
-static inline void
-tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
-{
-	tlb_add_flush(tlb, addr);
-}
 
 #endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b13410..e52bcdc6f097 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -20,6 +20,7 @@ arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
 arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
+arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 636ba8b6240b..13f87def8ea1 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -137,7 +137,6 @@ void disable_debug_monitors(enum debug_el el)
 static void clear_os_lock(void *unused)
 {
 	asm volatile("msr oslar_el1, %0" : : "r" (0));
-	isb();
 }
 
 static int os_lock_notify(struct notifier_block *self,
@@ -156,8 +155,9 @@ static struct notifier_block os_lock_nb = {
 static int debug_monitors_init(void)
 {
 	/* Clear the OS lock. */
-	smp_call_function(clear_os_lock, NULL, 1);
-	clear_os_lock(NULL);
+	on_each_cpu(clear_os_lock, NULL, 1);
+	isb();
+	local_dbg_enable();
 
 	/* Register hotplug handler. */
 	register_cpu_notifier(&os_lock_nb);
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 0b281fffda51..61035d6814cb 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -384,26 +384,18 @@ ENDPROC(__calc_phys_offset)
  * Preserves:	tbl, flags
  * Corrupts:	phys, start, end, pstate
  */
-	.macro	create_block_map, tbl, flags, phys, start, end, idmap=0
+	.macro	create_block_map, tbl, flags, phys, start, end
 	lsr	\phys, \phys, #BLOCK_SHIFT
-	.if	\idmap
-	and	\start, \phys, #PTRS_PER_PTE - 1	// table index
-	.else
 	lsr	\start, \start, #BLOCK_SHIFT
 	and	\start, \start, #PTRS_PER_PTE - 1	// table index
-	.endif
 	orr	\phys, \flags, \phys, lsl #BLOCK_SHIFT	// table entry
-	.ifnc	\start,\end
 	lsr	\end, \end, #BLOCK_SHIFT
 	and	\end, \end, #PTRS_PER_PTE - 1		// table end index
-	.endif
 9999:	str	\phys, [\tbl, \start, lsl #3]		// store the entry
-	.ifnc	\start,\end
 	add	\start, \start, #1			// next entry
 	add	\phys, \phys, #BLOCK_SIZE		// next block
 	cmp	\start, \end
 	b.ls	9999b
-	.endif
 	.endm
 
 /*
@@ -435,9 +427,13 @@ __create_page_tables:
 	 * Create the identity mapping.
 	 */
 	add	x0, x25, #PAGE_SIZE		// section table address
-	adr	x3, __turn_mmu_on		// virtual/physical address
+	ldr	x3, =KERNEL_START
+	add	x3, x3, x28			// __pa(KERNEL_START)
 	create_pgd_entry x25, x0, x3, x5, x6
-	create_block_map x0, x7, x3, x5, x5, idmap=1
+	ldr	x6, =KERNEL_END
+	mov	x5, x3				// __pa(KERNEL_START)
+	add	x6, x6, x28			// __pa(KERNEL_END)
+	create_block_map x0, x7, x3, x5, x6
 
 	/*
 	 * Map the kernel image (starting with PHYS_OFFSET).
@@ -445,7 +441,7 @@ __create_page_tables:
 	add	x0, x26, #PAGE_SIZE		// section table address
 	mov	x5, #PAGE_OFFSET
 	create_pgd_entry x26, x0, x5, x3, x6
-	ldr	x6, =KERNEL_END - 1
+	ldr	x6, =KERNEL_END
 	mov	x3, x24				// phys offset
 	create_block_map x0, x7, x3, x5, x6
 
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
new file mode 100644
index 000000000000..75c9cf1aafee
--- /dev/null
+++ b/arch/arm64/kernel/kgdb.c
@@ -0,0 +1,336 @@
+/*
+ * AArch64 KGDB support
+ *
+ * Based on arch/arm/kernel/kgdb.c
+ *
+ * Copyright (C) 2013 Cavium Inc.
+ * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.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/irq.h>
+#include <linux/kdebug.h>
+#include <linux/kgdb.h>
+#include <asm/traps.h>
+
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+	{ "x0", 8, offsetof(struct pt_regs, regs[0])},
+	{ "x1", 8, offsetof(struct pt_regs, regs[1])},
+	{ "x2", 8, offsetof(struct pt_regs, regs[2])},
+	{ "x3", 8, offsetof(struct pt_regs, regs[3])},
+	{ "x4", 8, offsetof(struct pt_regs, regs[4])},
+	{ "x5", 8, offsetof(struct pt_regs, regs[5])},
+	{ "x6", 8, offsetof(struct pt_regs, regs[6])},
+	{ "x7", 8, offsetof(struct pt_regs, regs[7])},
+	{ "x8", 8, offsetof(struct pt_regs, regs[8])},
+	{ "x9", 8, offsetof(struct pt_regs, regs[9])},
+	{ "x10", 8, offsetof(struct pt_regs, regs[10])},
+	{ "x11", 8, offsetof(struct pt_regs, regs[11])},
+	{ "x12", 8, offsetof(struct pt_regs, regs[12])},
+	{ "x13", 8, offsetof(struct pt_regs, regs[13])},
+	{ "x14", 8, offsetof(struct pt_regs, regs[14])},
+	{ "x15", 8, offsetof(struct pt_regs, regs[15])},
+	{ "x16", 8, offsetof(struct pt_regs, regs[16])},
+	{ "x17", 8, offsetof(struct pt_regs, regs[17])},
+	{ "x18", 8, offsetof(struct pt_regs, regs[18])},
+	{ "x19", 8, offsetof(struct pt_regs, regs[19])},
+	{ "x20", 8, offsetof(struct pt_regs, regs[20])},
+	{ "x21", 8, offsetof(struct pt_regs, regs[21])},
+	{ "x22", 8, offsetof(struct pt_regs, regs[22])},
+	{ "x23", 8, offsetof(struct pt_regs, regs[23])},
+	{ "x24", 8, offsetof(struct pt_regs, regs[24])},
+	{ "x25", 8, offsetof(struct pt_regs, regs[25])},
+	{ "x26", 8, offsetof(struct pt_regs, regs[26])},
+	{ "x27", 8, offsetof(struct pt_regs, regs[27])},
+	{ "x28", 8, offsetof(struct pt_regs, regs[28])},
+	{ "x29", 8, offsetof(struct pt_regs, regs[29])},
+	{ "x30", 8, offsetof(struct pt_regs, regs[30])},
+	{ "sp", 8, offsetof(struct pt_regs, sp)},
+	{ "pc", 8, offsetof(struct pt_regs, pc)},
+	{ "pstate", 8, offsetof(struct pt_regs, pstate)},
+	{ "v0", 16, -1 },
+	{ "v1", 16, -1 },
+	{ "v2", 16, -1 },
+	{ "v3", 16, -1 },
+	{ "v4", 16, -1 },
+	{ "v5", 16, -1 },
+	{ "v6", 16, -1 },
+	{ "v7", 16, -1 },
+	{ "v8", 16, -1 },
+	{ "v9", 16, -1 },
+	{ "v10", 16, -1 },
+	{ "v11", 16, -1 },
+	{ "v12", 16, -1 },
+	{ "v13", 16, -1 },
+	{ "v14", 16, -1 },
+	{ "v15", 16, -1 },
+	{ "v16", 16, -1 },
+	{ "v17", 16, -1 },
+	{ "v18", 16, -1 },
+	{ "v19", 16, -1 },
+	{ "v20", 16, -1 },
+	{ "v21", 16, -1 },
+	{ "v22", 16, -1 },
+	{ "v23", 16, -1 },
+	{ "v24", 16, -1 },
+	{ "v25", 16, -1 },
+	{ "v26", 16, -1 },
+	{ "v27", 16, -1 },
+	{ "v28", 16, -1 },
+	{ "v29", 16, -1 },
+	{ "v30", 16, -1 },
+	{ "v31", 16, -1 },
+	{ "fpsr", 4, -1 },
+	{ "fpcr", 4, -1 },
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return NULL;
+
+	if (dbg_reg_def[regno].offset != -1)
+		memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
+		       dbg_reg_def[regno].size);
+	else
+		memset(mem, 0, dbg_reg_def[regno].size);
+	return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return -EINVAL;
+
+	if (dbg_reg_def[regno].offset != -1)
+		memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
+		       dbg_reg_def[regno].size);
+	return 0;
+}
+
+void
+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
+{
+	struct pt_regs *thread_regs;
+
+	/* Initialize to zero */
+	memset((char *)gdb_regs, 0, NUMREGBYTES);
+	thread_regs = task_pt_regs(task);
+	memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+	regs->pc = pc;
+}
+
+static int compiled_break;
+
+static void kgdb_arch_update_addr(struct pt_regs *regs,
+				char *remcom_in_buffer)
+{
+	unsigned long addr;
+	char *ptr;
+
+	ptr = &remcom_in_buffer[1];
+	if (kgdb_hex2long(&ptr, &addr))
+		kgdb_arch_set_pc(regs, addr);
+	else if (compiled_break == 1)
+		kgdb_arch_set_pc(regs, regs->pc + 4);
+
+	compiled_break = 0;
+}
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+			       int err_code, char *remcom_in_buffer,
+			       char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	int err;
+
+	switch (remcom_in_buffer[0]) {
+	case 'D':
+	case 'k':
+		/*
+		 * Packet D (Detach), k (kill). No special handling
+		 * is required here. Handle same as c packet.
+		 */
+	case 'c':
+		/*
+		 * Packet c (Continue) to continue executing.
+		 * Set pc to required address.
+		 * Try to read optional parameter and set pc.
+		 * If this was a compiled breakpoint, we need to move
+		 * to the next instruction else we will just breakpoint
+		 * over and over again.
+		 */
+		kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
+		atomic_set(&kgdb_cpu_doing_single_step, -1);
+		kgdb_single_step =  0;
+
+		/*
+		 * Received continue command, disable single step
+		 */
+		if (kernel_active_single_step())
+			kernel_disable_single_step();
+
+		err = 0;
+		break;
+	case 's':
+		/*
+		 * Update step address value with address passed
+		 * with step packet.
+		 * On debug exception return PC is copied to ELR
+		 * So just update PC.
+		 * If no step address is passed, resume from the address
+		 * pointed by PC. Do not update PC
+		 */
+		kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
+		atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
+		kgdb_single_step =  1;
+
+		/*
+		 * Enable single step handling
+		 */
+		if (!kernel_active_single_step())
+			kernel_enable_single_step(linux_regs);
+		err = 0;
+		break;
+	default:
+		err = -1;
+	}
+	return err;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+	return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+	compiled_break = 1;
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+	return 0;
+}
+
+static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+	return 0;
+}
+
+static struct break_hook kgdb_brkpt_hook = {
+	.esr_mask	= 0xffffffff,
+	.esr_val	= DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM),
+	.fn		= kgdb_brk_fn
+};
+
+static struct break_hook kgdb_compiled_brkpt_hook = {
+	.esr_mask	= 0xffffffff,
+	.esr_val	= DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM),
+	.fn		= kgdb_compiled_brk_fn
+};
+
+static struct step_hook kgdb_step_hook = {
+	.fn		= kgdb_step_brk_fn
+};
+
+static void kgdb_call_nmi_hook(void *ignored)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_enable();
+	smp_call_function(kgdb_call_nmi_hook, NULL, 0);
+	local_irq_disable();
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	struct pt_regs *regs = args->regs;
+
+	if (kgdb_handle_exception(1, args->signr, cmd, regs))
+		return NOTIFY_DONE;
+	return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+	ret = __kgdb_notify(ptr, cmd);
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call	= kgdb_notify,
+	/*
+	 * Want to be lowest priority
+	 */
+	.priority	= -INT_MAX,
+};
+
+/*
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+	int ret = register_die_notifier(&kgdb_notifier);
+
+	if (ret != 0)
+		return ret;
+
+	register_break_hook(&kgdb_brkpt_hook);
+	register_break_hook(&kgdb_compiled_brkpt_hook);
+	register_step_hook(&kgdb_step_hook);
+	return 0;
+}
+
+/*
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+	unregister_break_hook(&kgdb_brkpt_hook);
+	unregister_break_hook(&kgdb_compiled_brkpt_hook);
+	unregister_step_hook(&kgdb_step_hook);
+	unregister_die_notifier(&kgdb_notifier);
+}
+
+/*
+ * ARM instructions are always in LE.
+ * Break instruction is encoded in LE format
+ */
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr = {
+		KGDB_DYN_BRK_INS_BYTE0,
+		KGDB_DYN_BRK_INS_BYTE1,
+		KGDB_DYN_BRK_INS_BYTE2,
+		KGDB_DYN_BRK_INS_BYTE3,
+	}
+};
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 1c0a9be2ffa8..6391485f342d 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -33,7 +33,6 @@
 #include <linux/kallsyms.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
-#include <linux/cpuidle.h>
 #include <linux/elfcore.h>
 #include <linux/pm.h>
 #include <linux/tick.h>
@@ -72,8 +71,17 @@ static void setup_restart(void)
 
 void soft_restart(unsigned long addr)
 {
+	typedef void (*phys_reset_t)(unsigned long);
+	phys_reset_t phys_reset;
+
 	setup_restart();
-	cpu_reset(addr);
+
+	/* Switch to the identity mapping */
+	phys_reset = (phys_reset_t)virt_to_phys(cpu_reset);
+	phys_reset(addr);
+
+	/* Should never get here */
+	BUG();
 }
 
 /*
@@ -94,10 +102,8 @@ void arch_cpu_idle(void)
 	 * This should do all the clock switching and wait for interrupt
 	 * tricks
 	 */
-	if (cpuidle_idle_call()) {
-		cpu_do_idle();
-		local_irq_enable();
-	}
+	cpu_do_idle();
+	local_irq_enable();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 4f97db3d7363..ea4828a4aa96 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -176,22 +176,20 @@ static const struct of_device_id psci_of_match[] __initconst = {
 	{},
 };
 
-int __init psci_init(void)
+void __init psci_init(void)
 {
 	struct device_node *np;
 	const char *method;
 	u32 id;
-	int err = 0;
 
 	np = of_find_matching_node(NULL, psci_of_match);
 	if (!np)
-		return -ENODEV;
+		return;
 
 	pr_info("probing function IDs from device-tree\n");
 
 	if (of_property_read_string(np, "method", &method)) {
 		pr_warning("missing \"method\" property\n");
-		err = -ENXIO;
 		goto out_put_node;
 	}
 
@@ -201,7 +199,6 @@ int __init psci_init(void)
 		invoke_psci_fn = __invoke_psci_fn_smc;
 	} else {
 		pr_warning("invalid \"method\" property: %s\n", method);
-		err = -EINVAL;
 		goto out_put_node;
 	}
 
@@ -227,7 +224,7 @@ int __init psci_init(void)
 
 out_put_node:
 	of_node_put(np);
-	return err;
+	return;
 }
 
 #ifdef CONFIG_SMP
@@ -251,7 +248,7 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
 {
 	int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
 	if (err)
-		pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
+		pr_err("failed to boot CPU%d (%d)\n", cpu, err);
 
 	return err;
 }
@@ -278,7 +275,7 @@ static void cpu_psci_cpu_die(unsigned int cpu)
 
 	ret = psci_ops.cpu_off(state);
 
-	pr_crit("psci: unable to power off CPU%u (%d)\n", cpu, ret);
+	pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
 }
 #endif
 
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 7cfb92a4ab66..5070dc3b65d2 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -160,6 +160,7 @@ asmlinkage void secondary_start_kernel(void)
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
+	local_dbg_enable();
 	local_irq_enable();
 	local_async_enable();
 
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index a7149cae1615..50384fec56c4 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -106,49 +106,31 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 
 static int __init vdso_init(void)
 {
-	struct page *pg;
-	char *vbase;
-	int i, ret = 0;
+	int i;
+
+	if (memcmp(&vdso_start, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		return -EINVAL;
+	}
 
 	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
 	pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
 		vdso_pages + 1, vdso_pages, 1L, &vdso_start);
 
 	/* Allocate the vDSO pagelist, plus a page for the data. */
-	vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1),
+	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
 				GFP_KERNEL);
-	if (vdso_pagelist == NULL) {
-		pr_err("Failed to allocate vDSO pagelist!\n");
+	if (vdso_pagelist == NULL)
 		return -ENOMEM;
-	}
 
 	/* Grab the vDSO code pages. */
-	for (i = 0; i < vdso_pages; i++) {
-		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
-		ClearPageReserved(pg);
-		get_page(pg);
-		vdso_pagelist[i] = pg;
-	}
-
-	/* Sanity check the shared object header. */
-	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
-	if (vbase == NULL) {
-		pr_err("Failed to map vDSO pagelist!\n");
-		return -ENOMEM;
-	} else if (memcmp(vbase, "\177ELF", 4)) {
-		pr_err("vDSO is not a valid ELF object!\n");
-		ret = -EINVAL;
-		goto unmap;
-	}
+	for (i = 0; i < vdso_pages; i++)
+		vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
 
 	/* Grab the vDSO data page. */
-	pg = virt_to_page(vdso_data);
-	get_page(pg);
-	vdso_pagelist[i] = pg;
+	vdso_pagelist[i] = virt_to_page(vdso_data);
 
-unmap:
-	vunmap(vbase);
-	return ret;
+	return 0;
 }
 arch_initcall(vdso_init);
 
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 1ea9f26d1b70..97fcef535a8a 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -166,3 +166,81 @@ ENTRY(__flush_dcache_area)
 	dsb	sy
 	ret
 ENDPROC(__flush_dcache_area)
+
+/*
+ *	__dma_inv_range(start, end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+__dma_inv_range:
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+	bic	x1, x1, x3
+1:	dc	ivac, x0			// invalidate D / U line
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__dma_inv_range)
+
+/*
+ *	__dma_clean_range(start, end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+__dma_clean_range:
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+1:	dc	cvac, x0			// clean D / U line
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__dma_clean_range)
+
+/*
+ *	__dma_flush_range(start, end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__dma_flush_range)
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+1:	dc	civac, x0			// clean & invalidate D / U line
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__dma_flush_range)
+
+/*
+ *	__dma_map_area(start, size, dir)
+ *	- start	- kernel virtual start address
+ *	- size	- size of region
+ *	- dir	- DMA direction
+ */
+ENTRY(__dma_map_area)
+	add	x1, x1, x0
+	cmp	w2, #DMA_FROM_DEVICE
+	b.eq	__dma_inv_range
+	b	__dma_clean_range
+ENDPROC(__dma_map_area)
+
+/*
+ *	__dma_unmap_area(start, size, dir)
+ *	- start	- kernel virtual start address
+ *	- size	- size of region
+ *	- dir	- DMA direction
+ */
+ENTRY(__dma_unmap_area)
+	add	x1, x1, x0
+	cmp	w2, #DMA_TO_DEVICE
+	b.ne	__dma_inv_range
+	ret
+ENDPROC(__dma_unmap_area)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index fbd76785c5db..88fbc5e5bae7 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -30,18 +30,18 @@
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
-static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
-					  dma_addr_t *dma_handle, gfp_t flags,
-					  struct dma_attrs *attrs)
+static void *__dma_alloc_coherent(struct device *dev, size_t size,
+				  dma_addr_t *dma_handle, gfp_t flags,
+				  struct dma_attrs *attrs)
 {
 	if (dev == NULL) {
 		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
 		return NULL;
 	}
 
-	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
+	if (IS_ENABLED(CONFIG_ZONE_DMA) &&
 	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-		flags |= GFP_DMA32;
+		flags |= GFP_DMA;
 	if (IS_ENABLED(CONFIG_DMA_CMA)) {
 		struct page *page;
 
@@ -58,9 +58,9 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
 	}
 }
 
-static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
-					void *vaddr, dma_addr_t dma_handle,
-					struct dma_attrs *attrs)
+static void __dma_free_coherent(struct device *dev, size_t size,
+				void *vaddr, dma_addr_t dma_handle,
+				struct dma_attrs *attrs)
 {
 	if (dev == NULL) {
 		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -78,9 +78,168 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
 	}
 }
 
-static struct dma_map_ops arm64_swiotlb_dma_ops = {
-	.alloc = arm64_swiotlb_alloc_coherent,
-	.free = arm64_swiotlb_free_coherent,
+static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
+				     dma_addr_t *dma_handle, gfp_t flags,
+				     struct dma_attrs *attrs)
+{
+	struct page *page, **map;
+	void *ptr, *coherent_ptr;
+	int order, i;
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
+	if (!ptr)
+		goto no_mem;
+	map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA);
+	if (!map)
+		goto no_map;
+
+	/* remove any dirty cache lines on the kernel alias */
+	__dma_flush_range(ptr, ptr + size);
+
+	/* create a coherent mapping */
+	page = virt_to_page(ptr);
+	for (i = 0; i < (size >> PAGE_SHIFT); i++)
+		map[i] = page + i;
+	coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP,
+			    pgprot_dmacoherent(pgprot_default));
+	kfree(map);
+	if (!coherent_ptr)
+		goto no_map;
+
+	return coherent_ptr;
+
+no_map:
+	__dma_free_coherent(dev, size, ptr, *dma_handle, attrs);
+no_mem:
+	*dma_handle = ~0;
+	return NULL;
+}
+
+static void __dma_free_noncoherent(struct device *dev, size_t size,
+				   void *vaddr, dma_addr_t dma_handle,
+				   struct dma_attrs *attrs)
+{
+	void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
+
+	vunmap(vaddr);
+	__dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
+}
+
+static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
+				     unsigned long offset, size_t size,
+				     enum dma_data_direction dir,
+				     struct dma_attrs *attrs)
+{
+	dma_addr_t dev_addr;
+
+	dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
+	__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+
+	return dev_addr;
+}
+
+
+static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
+				 size_t size, enum dma_data_direction dir,
+				 struct dma_attrs *attrs)
+{
+	__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+	swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
+}
+
+static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+				  int nelems, enum dma_data_direction dir,
+				  struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i, ret;
+
+	ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
+	for_each_sg(sgl, sg, ret, i)
+		__dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+			       sg->length, dir);
+
+	return ret;
+}
+
+static void __swiotlb_unmap_sg_attrs(struct device *dev,
+				     struct scatterlist *sgl, int nelems,
+				     enum dma_data_direction dir,
+				     struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nelems, i)
+		__dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+				 sg->length, dir);
+	swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
+}
+
+static void __swiotlb_sync_single_for_cpu(struct device *dev,
+					  dma_addr_t dev_addr, size_t size,
+					  enum dma_data_direction dir)
+{
+	__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+	swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
+}
+
+static void __swiotlb_sync_single_for_device(struct device *dev,
+					     dma_addr_t dev_addr, size_t size,
+					     enum dma_data_direction dir)
+{
+	swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
+	__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+}
+
+static void __swiotlb_sync_sg_for_cpu(struct device *dev,
+				      struct scatterlist *sgl, int nelems,
+				      enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nelems, i)
+		__dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+				 sg->length, dir);
+	swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
+}
+
+static void __swiotlb_sync_sg_for_device(struct device *dev,
+					 struct scatterlist *sgl, int nelems,
+					 enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
+	for_each_sg(sgl, sg, nelems, i)
+		__dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+			       sg->length, dir);
+}
+
+struct dma_map_ops noncoherent_swiotlb_dma_ops = {
+	.alloc = __dma_alloc_noncoherent,
+	.free = __dma_free_noncoherent,
+	.map_page = __swiotlb_map_page,
+	.unmap_page = __swiotlb_unmap_page,
+	.map_sg = __swiotlb_map_sg_attrs,
+	.unmap_sg = __swiotlb_unmap_sg_attrs,
+	.sync_single_for_cpu = __swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = __swiotlb_sync_single_for_device,
+	.sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = __swiotlb_sync_sg_for_device,
+	.dma_supported = swiotlb_dma_supported,
+	.mapping_error = swiotlb_dma_mapping_error,
+};
+EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops);
+
+struct dma_map_ops coherent_swiotlb_dma_ops = {
+	.alloc = __dma_alloc_coherent,
+	.free = __dma_free_coherent,
 	.map_page = swiotlb_map_page,
 	.unmap_page = swiotlb_unmap_page,
 	.map_sg = swiotlb_map_sg_attrs,
@@ -92,12 +251,19 @@ static struct dma_map_ops arm64_swiotlb_dma_ops = {
 	.dma_supported = swiotlb_dma_supported,
 	.mapping_error = swiotlb_dma_mapping_error,
 };
+EXPORT_SYMBOL(coherent_swiotlb_dma_ops);
 
-void __init arm64_swiotlb_init(void)
+extern int swiotlb_late_init_with_default_size(size_t default_size);
+
+static int __init swiotlb_late_init(void)
 {
-	dma_ops = &arm64_swiotlb_dma_ops;
-	swiotlb_init(1);
+	size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
+
+	dma_ops = &coherent_swiotlb_dma_ops;
+
+	return swiotlb_late_init_with_default_size(swiotlb_size);
 }
+subsys_initcall(swiotlb_late_init);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES	4096
 
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index d0b4c2efda90..88627c450a6c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -30,6 +30,7 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/of_fdt.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 
 #include <asm/sections.h>
@@ -59,22 +60,22 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
-#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
-
 static void __init zone_sizes_init(unsigned long min, unsigned long max)
 {
 	struct memblock_region *reg;
 	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-	unsigned long max_dma32 = min;
+	unsigned long max_dma = min;
 
 	memset(zone_size, 0, sizeof(zone_size));
 
-#ifdef CONFIG_ZONE_DMA32
 	/* 4GB maximum for 32-bit only capable devices */
-	max_dma32 = max(min, min(max, MAX_DMA32_PFN));
-	zone_size[ZONE_DMA32] = max_dma32 - min;
-#endif
-	zone_size[ZONE_NORMAL] = max - max_dma32;
+	if (IS_ENABLED(CONFIG_ZONE_DMA)) {
+		unsigned long max_dma_phys =
+			(unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1);
+		max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
+		zone_size[ZONE_DMA] = max_dma - min;
+	}
+	zone_size[ZONE_NORMAL] = max - max_dma;
 
 	memcpy(zhole_size, zone_size, sizeof(zhole_size));
 
@@ -84,15 +85,15 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 
 		if (start >= max)
 			continue;
-#ifdef CONFIG_ZONE_DMA32
-		if (start < max_dma32) {
-			unsigned long dma_end = min(end, max_dma32);
-			zhole_size[ZONE_DMA32] -= dma_end - start;
+
+		if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) {
+			unsigned long dma_end = min(end, max_dma);
+			zhole_size[ZONE_DMA] -= dma_end - start;
 		}
-#endif
-		if (end > max_dma32) {
+
+		if (end > max_dma) {
 			unsigned long normal_end = min(end, max);
-			unsigned long normal_start = max(start, max_dma32);
+			unsigned long normal_start = max(start, max_dma);
 			zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
 		}
 	}
@@ -261,8 +262,6 @@ static void __init free_unused_memmap(void)
  */
 void __init mem_init(void)
 {
-	arm64_swiotlb_init();
-
 	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
diff --git a/arch/avr32/boards/mimc200/Makefile b/arch/avr32/boards/mimc200/Makefile
index 79c076e168a8..c740aa116755 100644
--- a/arch/avr32/boards/mimc200/Makefile
+++ b/arch/avr32/boards/mimc200/Makefile
@@ -1 +1 @@
-obj-y				+= setup.o flash.o fram.o
+obj-y				+= setup.o flash.o
diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c
deleted file mode 100644
index c1466a872b9c..000000000000
--- a/arch/avr32/boards/mimc200/fram.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * FRAM driver for MIMC200 board
- *
- * Copyright 2008 Mark Jackson <mpfj@mimc.co.uk>
- *
- * This module adds *very* simply support for the system's FRAM device.
- * At the moment, this is hard-coded to the MIMC200 platform, and only
- * supports mmap().
- */
-
-#define FRAM_VERSION	"1.0"
-
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-
-#define FRAM_BASE	0xac000000
-#define FRAM_SIZE	0x20000
-
-/*
- * The are the file operation function for user access to /dev/fram
- */
-
-static int fram_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	int ret;
-
-	ret = remap_pfn_range(vma,
-		vma->vm_start,
-		virt_to_phys((void *)((unsigned long)FRAM_BASE)) >> PAGE_SHIFT,
-		vma->vm_end-vma->vm_start,
-		PAGE_SHARED);
-
-	if (ret != 0)
-		return -EAGAIN;
-
-	return 0;
-}
-
-static const struct file_operations fram_fops = {
-	.owner			= THIS_MODULE,
-	.mmap			= fram_mmap,
-	.llseek			= noop_llseek,
-};
-
-#define FRAM_MINOR	0
-
-static struct miscdevice fram_dev = {
-	FRAM_MINOR,
-	"fram",
-	&fram_fops
-};
-
-static int __init
-fram_init(void)
-{
-	int ret;
-
-	ret = misc_register(&fram_dev);
-	if (ret) {
-		printk(KERN_ERR "fram: can't misc_register on minor=%d\n",
-		    FRAM_MINOR);
-		return ret;
-	}
-	printk(KERN_INFO "FRAM memory driver v" FRAM_VERSION "\n");
-	return 0;
-}
-
-static void __exit
-fram_cleanup_module(void)
-{
-	misc_deregister(&fram_dev);
-}
-
-module_init(fram_init);
-module_exit(fram_cleanup_module);
-
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_MISCDEV(FRAM_MINOR);
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index c7c64a63c29f..00a0f3ccd6eb 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -1,22 +1,23 @@
 
-generic-y	+= clkdev.h
-generic-y       += cputime.h
-generic-y       += delay.h
-generic-y       += device.h
-generic-y       += div64.h
-generic-y       += emergency-restart.h
-generic-y	+= exec.h
-generic-y       += futex.h
-generic-y	+= preempt.h
-generic-y       += irq_regs.h
-generic-y	+= param.h
-generic-y       += local.h
-generic-y       += local64.h
-generic-y       += percpu.h
-generic-y       += scatterlist.h
-generic-y       += sections.h
-generic-y       += topology.h
-generic-y	+= trace_clock.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += exec.h
+generic-y += futex.h
+generic-y += hash.h
+generic-y += irq_regs.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += vga.h
-generic-y       += xor.h
-generic-y	+= hash.h
+generic-y += xor.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 359d36fdc247..0d93b9a79ca9 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -10,6 +10,7 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += fb.h
 generic-y += futex.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
@@ -17,14 +18,16 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
 generic-y += percpu.h
 generic-y += pgalloc.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -44,5 +47,3 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h
index 2fd04f10cc26..89de539ed010 100644
--- a/arch/blackfin/include/asm/irq.h
+++ b/arch/blackfin/include/asm/irq.h
@@ -20,15 +20,6 @@
 /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
 #include <mach/irq.h>
 
-/*
- * pm save bfin pint registers
- */
-struct adi_pm_pint_save {
-	u32 assign;
-	u32 edge_set;
-	u32 invert_set;
-};
-
 #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
 # define NOP_PAD_ANOMALY_05000244 "nop; nop;"
 #else
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index d73bb85ccdd3..8dbdce8421b0 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -15,6 +15,7 @@ generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += futex.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += io.h
 generic-y += ioctl.h
@@ -24,6 +25,7 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += mmu.h
 generic-y += mmu_context.h
@@ -34,6 +36,7 @@ generic-y += percpu.h
 generic-y += pgalloc.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += segment.h
@@ -56,5 +59,3 @@ generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/c6x/include/asm/cache.h b/arch/c6x/include/asm/cache.h
index 09c5a0f5f4d1..86648c083bb4 100644
--- a/arch/c6x/include/asm/cache.h
+++ b/arch/c6x/include/asm/cache.h
@@ -12,6 +12,7 @@
 #define _ASM_C6X_CACHE_H
 
 #include <linux/irqflags.h>
+#include <linux/init.h>
 
 /*
  * Cache line size
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index ed0fcdf7e990..52731e221851 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -29,7 +29,7 @@ config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config FORCE_MAX_ZONEORDER
@@ -138,6 +138,7 @@ config ETRAX_ARCH_V10
        bool
        default y if ETRAX100LX || ETRAX100LX_V2
        default n if !(ETRAX100LX || ETRAX100LX_V2)
+       select TTY
 
 config ETRAX_ARCH_V32
        bool
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 6792503aaf79..15a9ed1d579c 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -11,7 +11,6 @@ config ETRAX_ETHERNET
 config ETRAX_NO_PHY
 	bool "PHY not present"
 	depends on ETRAX_ETHERNET
-	default N
 	help
 	  This option disables all MDIO communication with an ethernet
 	  transceiver connected to the MII interface. This option shall
@@ -116,7 +115,6 @@ config ETRAX_AXISFLASHMAP
 config ETRAX_AXISFLASHMAP_MTD0WHOLE
 	bool "MTD0 is whole boot flash device"
 	depends on ETRAX_AXISFLASHMAP
-	default N
 	help
 	  When this option is not set, mtd0 refers to the first partition
 	  on the boot flash device. When set, mtd0 refers to the whole
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index f3fd8768f095..056027f38351 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -9,8 +9,9 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += kvm_para.h
 generic-y += linkage.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
+generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 32c3d248868e..905b70ea9939 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -165,6 +165,7 @@ void __init setup_arch(char **cmdline_p)
 	strcpy(init_utsname()->machine, cris_machine_name);
 }
 
+#ifdef CONFIG_PROC_FS
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
 	return *pos < nr_cpu_ids ? (void *)(int)(*pos + 1) : NULL;
@@ -188,6 +189,7 @@ const struct seq_operations cpuinfo_op = {
 	.stop  = c_stop,
 	.show  = show_cpuinfo,
 };
+#endif /* CONFIG_PROC_FS */
 
 static int __init topology_init(void)
 {
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index bc42f14c9c2e..babb9338ebf8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -1,6 +1,7 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index c28121765448..67b1d1685759 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -88,7 +88,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
 
 	/* Depth-First Search on bus tree */
 	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
-		bus = pci_bus_b(ln);
+		bus = list_entry(ln, struct pci_bus, node);
 		if ((dev = bus->self)) {
 			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
 				r = &dev->resource[idx];
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 09df2608f40a..0fd6138f6203 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -19,7 +19,7 @@ config HEXAGON
 	select GENERIC_IRQ_SHOW
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select GENERIC_IOMAP
 	select GENERIC_SMP_IDLE_THREAD
 	select STACKTRACE_SUPPORT
@@ -28,6 +28,7 @@ config HEXAGON
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select MODULES_USE_ELF_RELA
 	select GENERIC_CPU_DEVICES
+	select HAVE_DMA_ATTRS
 	---help---
 	  Qualcomm Hexagon is a processor architecture designed for high
 	  performance and low power across a wide variety of applications.
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 38ca45d3df1e..0e69796b58c7 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -25,28 +25,31 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += rwsem.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += sembuf.h
+generic-y += serial.h
 generic-y += shmbuf.h
 generic-y += shmparam.h
 generic-y += siginfo.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += statfs.h
 generic-y += stat.h
+generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -54,5 +57,5 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
+generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
index 7aae4cb2a29a..17dc63780c06 100644
--- a/arch/hexagon/include/asm/atomic.h
+++ b/arch/hexagon/include/asm/atomic.h
@@ -26,7 +26,20 @@
 #include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)		{ (i) }
-#define atomic_set(v, i)	((v)->counter = (i))
+
+/*  Normal writes in our arch don't clear lock reservations  */
+
+static inline void atomic_set(atomic_t *v, int new)
+{
+	asm volatile(
+		"1:	r6 = memw_locked(%0);\n"
+		"	memw_locked(%0,p0) = %1;\n"
+		"	if (!P0) jump 1b;\n"
+		:
+		: "r" (&v->counter), "r" (new)
+		: "memory", "p0", "r6"
+	);
+}
 
 /**
  * atomic_read - reads a word, atomically
diff --git a/arch/hexagon/include/asm/delay.h b/arch/hexagon/include/asm/delay.h
index 53079719d667..8933b9b1a3bf 100644
--- a/arch/hexagon/include/asm/delay.h
+++ b/arch/hexagon/include/asm/delay.h
@@ -21,6 +21,7 @@
 
 #include <asm/param.h>
 
+extern void __delay(unsigned long cycles);
 extern void __udelay(unsigned long usecs);
 
 #define udelay(usecs) __udelay((usecs))
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
index 85e9935660cb..16965427f6b4 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -25,7 +25,6 @@
 #include <linux/cache.h>
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
 #include <linux/dma-debug.h>
 #include <linux/dma-attrs.h>
 #include <asm/io.h>
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
index e1b933a0e121..80311e7b8ca6 100644
--- a/arch/hexagon/include/asm/elf.h
+++ b/arch/hexagon/include/asm/elf.h
@@ -1,7 +1,7 @@
 /*
  * ELF definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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 and
@@ -202,7 +202,7 @@ do {					\
 #define CORE_DUMP_USE_REGSET
 
 /* Hrm is this going to cause problems for changing PAGE_SIZE?  */
-#define ELF_EXEC_PAGESIZE	4096
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /*
  * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
index 67bb6d6f3337..1f6918b428de 100644
--- a/arch/hexagon/include/asm/hexagon_vm.h
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -55,27 +55,27 @@
 #ifndef __ASSEMBLY__
 
 enum VM_CACHE_OPS {
-	ickill,
-	dckill,
-	l2kill,
-	dccleaninva,
-	icinva,
-	idsync,
-	fetch_cfg
+	hvmc_ickill,
+	hvmc_dckill,
+	hvmc_l2kill,
+	hvmc_dccleaninva,
+	hvmc_icinva,
+	hvmc_idsync,
+	hvmc_fetch_cfg
 };
 
 enum VM_INT_OPS {
-	nop,
-	globen,
-	globdis,
-	locen,
-	locdis,
-	affinity,
-	get,
-	peek,
-	status,
-	post,
-	clear
+	hvmi_nop,
+	hvmi_globen,
+	hvmi_globdis,
+	hvmi_locen,
+	hvmi_locdis,
+	hvmi_affinity,
+	hvmi_get,
+	hvmi_peek,
+	hvmi_status,
+	hvmi_post,
+	hvmi_clear
 };
 
 extern void _K_VM_event_vector(void);
@@ -98,95 +98,95 @@ long __vmvpid(void);
 
 static inline long __vmcache_ickill(void)
 {
-	return __vmcache(ickill, 0, 0);
+	return __vmcache(hvmc_ickill, 0, 0);
 }
 
 static inline long __vmcache_dckill(void)
 {
-	return __vmcache(dckill, 0, 0);
+	return __vmcache(hvmc_dckill, 0, 0);
 }
 
 static inline long __vmcache_l2kill(void)
 {
-	return __vmcache(l2kill, 0, 0);
+	return __vmcache(hvmc_l2kill, 0, 0);
 }
 
 static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
 {
-	return __vmcache(dccleaninva, addr, len);
+	return __vmcache(hvmc_dccleaninva, addr, len);
 }
 
 static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
 {
-	return __vmcache(icinva, addr, len);
+	return __vmcache(hvmc_icinva, addr, len);
 }
 
 static inline long __vmcache_idsync(unsigned long addr,
 					   unsigned long len)
 {
-	return __vmcache(idsync, addr, len);
+	return __vmcache(hvmc_idsync, addr, len);
 }
 
 static inline long __vmcache_fetch_cfg(unsigned long val)
 {
-	return __vmcache(fetch_cfg, val, 0);
+	return __vmcache(hvmc_fetch_cfg, val, 0);
 }
 
 /* interrupt operations  */
 
 static inline long __vmintop_nop(void)
 {
-	return __vmintop(nop, 0, 0, 0, 0);
+	return __vmintop(hvmi_nop, 0, 0, 0, 0);
 }
 
 static inline long __vmintop_globen(long i)
 {
-	return __vmintop(globen, i, 0, 0, 0);
+	return __vmintop(hvmi_globen, i, 0, 0, 0);
 }
 
 static inline long __vmintop_globdis(long i)
 {
-	return __vmintop(globdis, i, 0, 0, 0);
+	return __vmintop(hvmi_globdis, i, 0, 0, 0);
 }
 
 static inline long __vmintop_locen(long i)
 {
-	return __vmintop(locen, i, 0, 0, 0);
+	return __vmintop(hvmi_locen, i, 0, 0, 0);
 }
 
 static inline long __vmintop_locdis(long i)
 {
-	return __vmintop(locdis, i, 0, 0, 0);
+	return __vmintop(hvmi_locdis, i, 0, 0, 0);
 }
 
 static inline long __vmintop_affinity(long i, long cpu)
 {
-	return __vmintop(locdis, i, cpu, 0, 0);
+	return __vmintop(hvmi_affinity, i, cpu, 0, 0);
 }
 
 static inline long __vmintop_get(void)
 {
-	return __vmintop(get, 0, 0, 0, 0);
+	return __vmintop(hvmi_get, 0, 0, 0, 0);
 }
 
 static inline long __vmintop_peek(void)
 {
-	return __vmintop(peek, 0, 0, 0, 0);
+	return __vmintop(hvmi_peek, 0, 0, 0, 0);
 }
 
 static inline long __vmintop_status(long i)
 {
-	return __vmintop(status, i, 0, 0, 0);
+	return __vmintop(hvmi_status, i, 0, 0, 0);
 }
 
 static inline long __vmintop_post(long i)
 {
-	return __vmintop(post, i, 0, 0, 0);
+	return __vmintop(hvmi_post, i, 0, 0, 0);
 }
 
 static inline long __vmintop_clear(long i)
 {
-	return __vmintop(clear, i, 0, 0, 0);
+	return __vmintop(hvmi_clear, i, 0, 0, 0);
 }
 
 #else /* Only assembly code should reference these */
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index 1b7698e19139..70298996e9b2 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -189,6 +189,8 @@ static inline void writel(u32 data, volatile void __iomem *addr)
 #define writew_relaxed __raw_writew
 #define writel_relaxed __raw_writel
 
+#define mmiowb()
+
 /*
  * Need an mtype somewhere in here, for cache type deals?
  * This is probably too long for an inline.
diff --git a/arch/hexagon/include/asm/kgdb.h b/arch/hexagon/include/asm/kgdb.h
index 32a6fb66944a..ccd3ac336b24 100644
--- a/arch/hexagon/include/asm/kgdb.h
+++ b/arch/hexagon/include/asm/kgdb.h
@@ -34,10 +34,11 @@ static inline void arch_kgdb_breakpoint(void)
  * 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
  * vm regs = psp+elr+est+badva = 4
  * syscall+restart = 2 more
- * so 48 = 42 +4 + 2
+ * also add cs0/1 = 2
+ * so 48 = 42 + 4 + 2 + 2
  */
 #define DBG_USER_REGS 42
-#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
+#define DBG_MAX_REG_NUM (DBG_USER_REGS + 8)
 #define NUMREGBYTES  (DBG_MAX_REG_NUM*4)
 
 #endif /* __HEXAGON_KGDB_H__ */
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
index 4c9d382d7798..77da3b0ae3c2 100644
--- a/arch/hexagon/include/asm/pgalloc.h
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -45,7 +45,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 	 * map with a copy of the kernel's persistent map.
 	 */
 
-	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t));
 	mm->context.generation = kmap_generation;
 
 	/* Physical version is what is passed to virtual machine on switch */
diff --git a/arch/hexagon/include/asm/smp.h b/arch/hexagon/include/asm/smp.h
index 2b9b974e0952..ca171c13891d 100644
--- a/arch/hexagon/include/asm/smp.h
+++ b/arch/hexagon/include/asm/smp.h
@@ -29,7 +29,6 @@ enum ipi_message_type {
 	IPI_NOP = 0,
 	IPI_RESCHEDULE = 1,
 	IPI_CALL_FUNC,
-	IPI_CALL_FUNC_SINGLE,
 	IPI_CPU_STOP,
 	IPI_TIMER,
 };
diff --git a/arch/hexagon/include/uapi/asm/registers.h b/arch/hexagon/include/uapi/asm/registers.h
index 487d6ceca5e7..e7be31840a90 100644
--- a/arch/hexagon/include/uapi/asm/registers.h
+++ b/arch/hexagon/include/uapi/asm/registers.h
@@ -6,8 +6,6 @@
 #ifndef _ASM_REGISTERS_H
 #define _ASM_REGISTERS_H
 
-#define SP r29
-
 #ifndef __ASSEMBLY__
 
 /*  See kernel/entry.S for further documentation.  */
@@ -215,7 +213,7 @@ struct pt_regs {
 #define pt_clr_singlestep(regs) ((regs)->hvmer.vmest &= ~(1<<HVM_VMEST_SS_SFT))
 
 #define pt_set_rte_sp(regs, sp) do {\
-	pt_psp(regs) = (regs)->SP = (sp);\
+	pt_psp(regs) = (regs)->r29 = (sp);\
 	} while (0)
 
 #define pt_set_kmode(regs) \
diff --git a/arch/hexagon/include/uapi/asm/setup.h b/arch/hexagon/include/uapi/asm/setup.h
index e48285e4af96..7e3952d6221c 100644
--- a/arch/hexagon/include/uapi/asm/setup.h
+++ b/arch/hexagon/include/uapi/asm/setup.h
@@ -19,7 +19,12 @@
 #ifndef _ASM_SETUP_H
 #define _ASM_SETUP_H
 
+#ifdef __KERNEL__
 #include <linux/init.h>
+#else
+#define __init
+#endif
+
 #include <asm-generic/setup.h>
 
 extern char external_cmdline_buffer;
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index 29fc933a7722..009228b8611c 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -15,3 +15,5 @@ obj-y += vm_vectors.o
 obj-$(CONFIG_HAS_DMA) += dma.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
+
+obj-$(CONFIG_VGA_CONSOLE) += screen_info.o
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
index 32b1379d6877..c041d8ecb1e2 100644
--- a/arch/hexagon/kernel/hexagon_ksyms.c
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -18,23 +18,39 @@
  * 02110-1301, USA.
  */
 
+#include <linux/dma-mapping.h>
 #include <asm/hexagon_vm.h>
+#include <asm/io.h>
 #include <asm/uaccess.h>
 
+/* Additional functions */
+EXPORT_SYMBOL(__clear_user_hexagon);
 EXPORT_SYMBOL(__copy_from_user_hexagon);
 EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(__strnlen_user);
 EXPORT_SYMBOL(__vmgetie);
 EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(__vmyield);
+EXPORT_SYMBOL(empty_zero_page);
+EXPORT_SYMBOL(ioremap_nocache);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 
+/* Additional variables */
+EXPORT_SYMBOL(__phys_offset);
+EXPORT_SYMBOL(_dflt_cache_att);
+EXPORT_SYMBOL(bad_dma_address);
+
 #define DECLARE_EXPORT(name)     \
 	extern void name(void); EXPORT_SYMBOL(name)
 
 /* Symbols found in libgcc that assorted kernel modules need */
 DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
 
-DECLARE_EXPORT(__hexagon_divsi3);
-DECLARE_EXPORT(__hexagon_modsi3);
-DECLARE_EXPORT(__hexagon_udivsi3);
-DECLARE_EXPORT(__hexagon_umodsi3);
+/* Additional functions */
+DECLARE_EXPORT(__divsi3);
+DECLARE_EXPORT(__modsi3);
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__umodsi3);
+DECLARE_EXPORT(csum_tcpudp_magic);
diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c
index 82d5c2593323..038580cc5abf 100644
--- a/arch/hexagon/kernel/kgdb.c
+++ b/arch/hexagon/kernel/kgdb.c
@@ -18,6 +18,8 @@
  * 02110-1301, USA.
  */
 
+#include <linux/irq.h>
+#include <linux/sched.h>
 #include <linux/kdebug.h>
 #include <linux/kgdb.h>
 
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index de829eb7f185..390a9ad14ca1 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -183,6 +183,7 @@ static const struct user_regset_view hexagon_user_view = {
 	.e_machine = ELF_ARCH,
 	.ei_osabi = ELF_OSABI,
 	.regsets = hexagon_regsets,
+	.e_flags = ELF_CORE_EFLAGS,
 	.n = ARRAY_SIZE(hexagon_regsets)
 };
 
diff --git a/arch/hexagon/kernel/reset.c b/arch/hexagon/kernel/reset.c
index 6aeabc962b3b..76483c10130d 100644
--- a/arch/hexagon/kernel/reset.c
+++ b/arch/hexagon/kernel/reset.c
@@ -33,6 +33,5 @@ void machine_restart(char *cmd)
 {
 }
 
-void pm_power_off(void)
-{
-}
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/hexagon/kernel/screen_info.c b/arch/hexagon/kernel/screen_info.c
new file mode 100644
index 000000000000..1e1ceb18bafe
--- /dev/null
+++ b/arch/hexagon/kernel/screen_info.c
@@ -0,0 +1,3 @@
+#include <linux/screen_info.h>
+
+struct screen_info screen_info;
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
index 9faaa940452b..ff759f26b96a 100644
--- a/arch/hexagon/kernel/smp.c
+++ b/arch/hexagon/kernel/smp.c
@@ -64,10 +64,6 @@ static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
 			generic_smp_call_function_interrupt();
 			break;
 
-		case IPI_CALL_FUNC_SINGLE:
-			generic_smp_call_function_single_interrupt();
-			break;
-
 		case IPI_CPU_STOP:
 			/*
 			 * call vmstop()
@@ -248,7 +244,7 @@ void smp_send_stop(void)
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-	send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+	send_ipi(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
index 9903fad997f3..17fbf45bf150 100644
--- a/arch/hexagon/kernel/time.c
+++ b/arch/hexagon/kernel/time.c
@@ -191,9 +191,6 @@ void __init time_init_deferred(void)
 {
 	struct resource *resource = NULL;
 	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
-	struct device_node *dn;
-	struct resource r;
-	int err;
 
 	ce_dev->cpumask = cpu_all_mask;
 
@@ -232,6 +229,15 @@ void __init time_init(void)
 	late_time_init = time_init_deferred;
 }
 
+void __delay(unsigned long cycles)
+{
+	unsigned long long start = __vmgettime();
+
+	while ((__vmgettime() - start) < cycles)
+		cpu_relax();
+}
+EXPORT_SYMBOL(__delay);
+
 /*
  * This could become parametric or perhaps even computed at run-time,
  * but for now we take the observed simulator jitter.
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 0c8e553e0b9f..6b83c66f51b1 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -44,6 +44,7 @@ config IA64
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
 	select ARCH_USE_CMPXCHG_LOCKREF
+	select TTY
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index efbd2929aeb7..b4efaf2bc13e 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -25,14 +25,13 @@ CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
 CONFIG_EFI_VARS=y
 CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_DOCK=y
 CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_CONTAINER=y
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 0f4e9e41f130..0fed9ae5a42a 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -26,7 +26,6 @@ CONFIG_IA64_PALINFO=y
 CONFIG_KEXEC=y
 CONFIG_EFI_VARS=y
 CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index fc7aba07c2b4..54bc72eda30d 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -16,7 +16,6 @@ CONFIG_IA64_PALINFO=y
 CONFIG_CRASH_DUMP=y
 CONFIG_EFI_VARS=y
 CONFIG_BINFMT_MISC=y
-CONFIG_ACPI_PROCFS=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 8e858b593e4f..1a871b78e570 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1140,11 +1140,13 @@ sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 
 #ifdef CONFIG_NUMA
 	{
+		int node = ioc->node;
 		struct page *page;
-		page = alloc_pages_exact_node(ioc->node == MAX_NUMNODES ?
-		                        numa_node_id() : ioc->node, flags,
-		                        get_order(size));
 
+		if (node == NUMA_NO_NODE)
+			node = numa_node_id();
+
+		page = alloc_pages_exact_node(node, flags, get_order(size));
 		if (unlikely(!page))
 			return NULL;
 
@@ -1596,7 +1598,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
 *
 ***************************************************************/
 
-static void __init
+static void
 ioc_iova_init(struct ioc *ioc)
 {
 	int tcnfg;
@@ -1807,7 +1809,7 @@ static struct ioc_iommu ioc_iommu_info[] __initdata = {
 	{ SX2000_IOC_ID, "sx2000", NULL },
 };
 
-static struct ioc * __init
+static struct ioc *
 ioc_init(unsigned long hpa, void *handle)
 {
 	struct ioc *ioc;
@@ -1914,7 +1916,7 @@ ioc_show(struct seq_file *s, void *v)
 	seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
 		ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
 #ifdef CONFIG_NUMA
-	if (ioc->node != MAX_NUMNODES)
+	if (ioc->node != NUMA_NO_NODE)
 		seq_printf(s, "NUMA node       : %d\n", ioc->node);
 #endif
 	seq_printf(s, "IOVA size       : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
@@ -2015,33 +2017,21 @@ sba_connect_bus(struct pci_bus *bus)
 	printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
 }
 
-#ifdef CONFIG_NUMA
 static void __init
 sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 {
+#ifdef CONFIG_NUMA
 	unsigned int node;
-	int pxm;
-
-	ioc->node = MAX_NUMNODES;
-
-	pxm = acpi_get_pxm(handle);
-
-	if (pxm < 0)
-		return;
-
-	node = pxm_to_node(pxm);
 
-	if (node >= MAX_NUMNODES || !node_online(node))
-		return;
+	node = acpi_get_node(handle);
+	if (node != NUMA_NO_NODE && !node_online(node))
+		node = NUMA_NO_NODE;
 
 	ioc->node = node;
-	return;
-}
-#else
-#define sba_map_ioc_to_node(ioc, handle)
 #endif
+}
 
-static int __init
+static int
 acpi_sba_ioc_add(struct acpi_device *device,
 		 const struct acpi_device_id *not_used)
 {
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 283a83154b5e..0da4aa2602ae 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -1,8 +1,9 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += kvm_para.h
-generic-y += trace_clock.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += trace_clock.h
 generic-y += vtime.h
-generic-y += hash.h
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 71fbaaa495cc..7d41cc089822 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -98,7 +98,7 @@ struct pci_controller {
 	struct acpi_device *companion;
 	void *iommu;
 	int segment;
-	int node;		/* nearest node with memory or -1 for global allocation */
+	int node;		/* nearest node with memory or NUMA_NO_NODE for global allocation */
 
 	void *platform_data;
 };
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 07d209c9507f..0d407b300762 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -54,10 +54,6 @@
 #include <asm/sal.h>
 #include <asm/cyclone.h>
 
-#define BAD_MADT_ENTRY(entry, end) (                                        \
-		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-		((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
-
 #define PREFIX			"ACPI: "
 
 unsigned int acpi_cpei_override;
@@ -803,14 +799,9 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
  *  ACPI based hotplug CPU support
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
-static
-int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
+static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
-	int pxm_id;
-	int nid;
-
-	pxm_id = acpi_get_pxm(handle);
 	/*
 	 * We don't have cpu-only-node hotadd. But if the system equips
 	 * SRAT table, pxm is already found and node is ready.
@@ -818,11 +809,10 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 	 * This code here is for the system which doesn't have full SRAT
   	 * table for possible cpus.
 	 */
-	nid = acpi_map_pxm_to_node(pxm_id);
 	node_cpuid[cpu].phys_id = physid;
-	node_cpuid[cpu].nid = nid;
+	node_cpuid[cpu].nid = acpi_get_node(handle);
 #endif
-	return (0);
+	return 0;
 }
 
 int additional_cpus __initdata = -1;
@@ -929,7 +919,7 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
 	union acpi_object *obj;
 	struct acpi_madt_io_sapic *iosapic;
 	unsigned int gsi_base;
-	int pxm, node;
+	int node;
 
 	/* Only care about objects w/ a method that returns the MADT */
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
@@ -956,17 +946,9 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
 
 	kfree(buffer.pointer);
 
-	/*
-	 * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
-	 * us which node to associate this with.
-	 */
-	pxm = acpi_get_pxm(handle);
-	if (pxm < 0)
-		return AE_OK;
-
-	node = pxm_to_node(pxm);
-
-	if (node >= MAX_NUMNODES || !node_online(node) ||
+	/* OK, it's an IOSAPIC MADT entry; associate it with a node */
+	node = acpi_get_node(handle);
+	if (node == NUMA_NO_NODE || !node_online(node) ||
 	    cpumask_empty(cpumask_of_node(node)))
 		return AE_OK;
 
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index a96bcf83a735..20e8a9b21d75 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -98,7 +98,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
 	/* attempt to allocate a granule's worth of cached memory pages */
 
 	page = alloc_pages_exact_node(nid,
-				GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+				GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
 				IA64_GRANULE_SHIFT-PAGE_SHIFT);
 	if (!page) {
 		mutex_unlock(&uc_pool->add_chunk_mutex);
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c
index 5dc969dd4ac0..eee069a0b539 100644
--- a/arch/ia64/pci/fixup.c
+++ b/arch/ia64/pci/fixup.c
@@ -5,6 +5,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/vgaarb.h>
 
 #include <asm/machvec.h>
 
@@ -19,9 +20,10 @@
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
+ * See pci_map_rom() for use of this flag. Before marking the device
+ * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * by either arch cde or vga-arbitration, if so only apply the fixup to this
+ * already determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -35,9 +37,6 @@ static void pci_fixup_video(struct pci_dev *pdev)
 		return;
 	/* Maybe, this machine supports legacy memory map. */
 
-	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-		return;
-
 	/* Is VGA routed to us? */
 	bus = pdev->bus;
 	while (bus) {
@@ -60,10 +59,14 @@ static void pci_fixup_video(struct pci_dev *pdev)
 		}
 		bus = bus->parent;
 	}
-	pci_read_config_word(pdev, PCI_COMMAND, &config);
-	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-		dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+	if (!vga_default_device() || pdev == vga_default_device()) {
+		pci_read_config_word(pdev, PCI_COMMAND, &config);
+		if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+			pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+			dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+			vga_set_default_device(pdev);
+		}
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
+				PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 9e4938d8ca4d..291a582777cf 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -126,7 +126,6 @@ static struct pci_controller *alloc_pci_controller(int seg)
 		return NULL;
 
 	controller->segment = seg;
-	controller->node = -1;
 	return controller;
 }
 
@@ -430,19 +429,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	struct pci_root_info *info = NULL;
 	int busnum = root->secondary.start;
 	struct pci_bus *pbus;
-	int pxm, ret;
+	int ret;
 
 	controller = alloc_pci_controller(domain);
 	if (!controller)
 		return NULL;
 
 	controller->companion = device;
-
-	pxm = acpi_get_pxm(device->handle);
-#ifdef CONFIG_NUMA
-	if (pxm >= 0)
-		controller->node = pxm_to_node(pxm);
-#endif
+	controller->node = acpi_get_node(device->handle);
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info) {
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index ca4504424dae..9e44bbd8051e 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -28,7 +28,7 @@ config ZONE_DMA
 	bool
 	default y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config NO_DMA
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 932435ac4e5c..5825a35b2c56 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -1,7 +1,8 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
-generic-y += trace_clock.h
 generic-y += preempt.h
-generic-y += hash.h
+generic-y += trace_clock.h
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index dbdd2231c75d..a1aebe524a67 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -51,7 +51,7 @@ config TIME_LOW_RES
 	bool
 	default y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config NO_DMA
diff --git a/arch/m68k/configs/m5208evb_defconfig b/arch/m68k/configs/m5208evb_defconfig
index c1616824e201..e7292f460af4 100644
--- a/arch/m68k/configs/m5208evb_defconfig
+++ b/arch/m68k/configs/m5208evb_defconfig
@@ -40,7 +40,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/configs/m5249evb_defconfig b/arch/m68k/configs/m5249evb_defconfig
index a6599e42facf..0cd4b39f325b 100644
--- a/arch/m68k/configs/m5249evb_defconfig
+++ b/arch/m68k/configs/m5249evb_defconfig
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/configs/m5272c3_defconfig b/arch/m68k/configs/m5272c3_defconfig
index 3fa60a57a0f9..a60cb3509135 100644
--- a/arch/m68k/configs/m5272c3_defconfig
+++ b/arch/m68k/configs/m5272c3_defconfig
@@ -36,7 +36,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/configs/m5275evb_defconfig b/arch/m68k/configs/m5275evb_defconfig
index a1230e82bb1e..e6502ab7cb2f 100644
--- a/arch/m68k/configs/m5275evb_defconfig
+++ b/arch/m68k/configs/m5275evb_defconfig
@@ -39,7 +39,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/configs/m5307c3_defconfig b/arch/m68k/configs/m5307c3_defconfig
index 43795f41f7c7..023812abd2e6 100644
--- a/arch/m68k/configs/m5307c3_defconfig
+++ b/arch/m68k/configs/m5307c3_defconfig
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/configs/m5407c3_defconfig b/arch/m68k/configs/m5407c3_defconfig
index 72746c57a571..557b39f3be90 100644
--- a/arch/m68k/configs/m5407c3_defconfig
+++ b/arch/m68k/configs/m5407c3_defconfig
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 6fb9e813a910..c67c94a2d672 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -14,8 +14,9 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += mutex.h
 generic-y += percpu.h
diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index e1534783e94e..52f7e8499172 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -55,7 +55,7 @@ static inline unsigned int _swapl(volatile unsigned long v)
 #define __raw_writew writew
 #define __raw_writel writel
 
-static inline void io_outsb(unsigned int addr, void *buf, int len)
+static inline void io_outsb(unsigned int addr, const void *buf, int len)
 {
 	volatile unsigned char *ap = (volatile unsigned char *) addr;
 	unsigned char *bp = (unsigned char *) buf;
@@ -63,7 +63,7 @@ static inline void io_outsb(unsigned int addr, void *buf, int len)
 		*ap = *bp++;
 }
 
-static inline void io_outsw(unsigned int addr, void *buf, int len)
+static inline void io_outsw(unsigned int addr, const void *buf, int len)
 {
 	volatile unsigned short *ap = (volatile unsigned short *) addr;
 	unsigned short *bp = (unsigned short *) buf;
@@ -71,7 +71,7 @@ static inline void io_outsw(unsigned int addr, void *buf, int len)
 		*ap = _swapw(*bp++);
 }
 
-static inline void io_outsl(unsigned int addr, void *buf, int len)
+static inline void io_outsl(unsigned int addr, const void *buf, int len)
 {
 	volatile unsigned int *ap = (volatile unsigned int *) addr;
 	unsigned int *bp = (unsigned int *) buf;
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index e56abd2c1b4f..4e53a6de1a4e 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -52,7 +52,7 @@ config GENERIC_HWEIGHT
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 source "init/Kconfig"
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b716d807c2ec..c29ead89a317 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -13,6 +13,7 @@ generic-y += fb.h
 generic-y += fcntl.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -23,6 +24,7 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
@@ -30,6 +32,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += sembuf.h
@@ -52,5 +55,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 2b98bc73642a..1f590ab8f323 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -3,6 +3,7 @@ generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += hash.h
-generic-y += trace_clock.h
-generic-y += syscalls.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += syscalls.h
+generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index f05df5630c84..be84a4d3917f 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -19,14 +19,12 @@ extern char cmd_line[COMMAND_LINE_SIZE];
 
 extern char *klimit;
 
-void early_printk(const char *fmt, ...);
-
 int setup_early_printk(char *opt);
 void remap_early_printk(void);
 void disable_early_printk(void);
 
-void heartbeat(void);
-void setup_heartbeat(void);
+void microblaze_heartbeat(void);
+void microblaze_setup_heartbeat(void);
 
 #   ifdef CONFIG_MMU
 extern void mmu_reset(void);
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c
index 1879a0527776..4643e3ab9414 100644
--- a/arch/microblaze/kernel/heartbeat.c
+++ b/arch/microblaze/kernel/heartbeat.c
@@ -17,7 +17,7 @@
 
 static unsigned int base_addr;
 
-void heartbeat(void)
+void microblaze_heartbeat(void)
 {
 	static unsigned int cnt, period, dist;
 
@@ -42,7 +42,7 @@ void heartbeat(void)
 	}
 }
 
-void setup_heartbeat(void)
+void microblaze_setup_heartbeat(void)
 {
 	struct device_node *gpio = NULL;
 	int *prop;
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index fb0c61443f19..717a3d90e1b8 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -140,7 +140,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = &clockevent_xilinx_timer;
 #ifdef CONFIG_HEART_BEAT
-	heartbeat();
+	microblaze_heartbeat();
 #endif
 	timer_ack();
 	evt->event_handler(evt);
@@ -274,7 +274,7 @@ static void __init xilinx_timer_init(struct device_node *timer)
 
 	setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT
-	setup_heartbeat();
+	microblaze_setup_heartbeat();
 #endif
 	xilinx_clocksource_init();
 	xilinx_clockevent_init();
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index dcae3a7035db..2cc27a88ef83 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -10,6 +10,7 @@ config MIPS
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select HAVE_FUNCTION_TRACER
@@ -62,13 +63,12 @@ config MIPS_ALCHEMY
 	select CEVT_R4K
 	select CSRC_R4K
 	select IRQ_CPU
+	select DMA_MAYBE_COHERENT	# Au1000,1500,1100 aren't, rest is
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_APM_EMULATION
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
-	select USB_ARCH_HAS_OHCI
-	select USB_ARCH_HAS_EHCI
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -175,7 +175,7 @@ config MACH_DECSTATION
 	select CPU_R4000_WORKAROUNDS if 64BIT
 	select CPU_R4400_WORKAROUNDS if 64BIT
 	select DMA_NONCOHERENT
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select IRQ_CPU
 	select SYS_HAS_CPU_R3000
 	select SYS_HAS_CPU_R4X00
@@ -235,7 +235,6 @@ config MACH_JZ4740
 	select IRQ_CPU
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_HAS_EARLY_PRINTK
-	select HAVE_PWM
 	select HAVE_CLK
 	select GENERIC_IRQ_CHIP
 
@@ -320,6 +319,7 @@ config MIPS_MALTA
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS32_R3_5
 	select SYS_HAS_CPU_MIPS64_R1
 	select SYS_HAS_CPU_MIPS64_R2
 	select SYS_HAS_CPU_NEVADA
@@ -329,6 +329,7 @@ config MIPS_MALTA
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_MIPS_CMP
+	select SYS_SUPPORTS_MIPS_CPS
 	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_SMARTMIPS
 	select SYS_SUPPORTS_ZBOOT
@@ -360,7 +361,6 @@ config MIPS_SEAD3
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_SMARTMIPS
 	select SYS_SUPPORTS_MICROMIPS
-	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	select USE_OF
@@ -718,8 +718,6 @@ config CAVIUM_OCTEON_SOC
 	select SWAP_IO_SPACE
 	select HW_HAS_PCI
 	select ZONE_DMA32
-	select USB_ARCH_HAS_OHCI
-	select USB_ARCH_HAS_EHCI
 	select HOLES_IN_ZONE
 	select ARCH_REQUIRE_GPIOLIB
 	help
@@ -756,8 +754,6 @@ config NLM_XLR_BOARD
 	select ZONE_DMA32 if 64BIT
 	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
-	select USB_ARCH_HAS_OHCI if USB_SUPPORT
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select SYS_SUPPORTS_ZBOOT
 	select SYS_SUPPORTS_ZBOOT_UART16550
 	help
@@ -868,6 +864,7 @@ config CEVT_R4K
 	bool
 
 config CEVT_GIC
+	select MIPS_CM
 	bool
 
 config CEVT_SB1250
@@ -886,6 +883,7 @@ config CSRC_R4K
 	bool
 
 config CSRC_GIC
+	select MIPS_CM
 	bool
 
 config CSRC_SB1250
@@ -949,7 +947,7 @@ config SYNC_R4K
 config MIPS_MACHINE
 	def_bool n
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool n
 
 config GENERIC_ISA_DMA
@@ -1030,6 +1028,7 @@ config IRQ_GT641XX
 	bool
 
 config IRQ_GIC
+	select MIPS_CM
 	bool
 
 config PCI_GT64XXX_PCI0
@@ -1203,6 +1202,7 @@ config CPU_MIPS32_R2
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_MSA
 	select HAVE_KVM
 	help
 	  Choose this option to build a kernel for release 2 or later of the
@@ -1238,6 +1238,7 @@ config CPU_MIPS64_R2
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HUGEPAGES
+	select CPU_SUPPORTS_MSA
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
@@ -1448,6 +1449,26 @@ config CPU_XLP
 	  Netlogic Microsystems XLP processors.
 endchoice
 
+config CPU_MIPS32_3_5_FEATURES
+	bool "MIPS32 Release 3.5 Features"
+	depends on SYS_HAS_CPU_MIPS32_R3_5
+	depends on CPU_MIPS32_R2
+	help
+	  Choose this option to build a kernel for release 2 or later of the
+	  MIPS32 architecture including features from the 3.5 release such as
+	  support for Enhanced Virtual Addressing (EVA).
+
+config CPU_MIPS32_3_5_EVA
+	bool "Enhanced Virtual Addressing (EVA)"
+	depends on CPU_MIPS32_3_5_FEATURES
+	select EVA
+	default y
+	help
+	  Choose this option if you want to enable the Enhanced Virtual
+	  Addressing (EVA) on your MIPS32 core (such as proAptiv).
+	  One of its primary benefits is an increase in the maximum size
+	  of lowmem (up to 3GB). If unsure, say 'N' here.
+
 if CPU_LOONGSON2F
 config CPU_NOP_WORKAROUNDS
 	bool
@@ -1541,6 +1562,9 @@ config SYS_HAS_CPU_MIPS32_R1
 config SYS_HAS_CPU_MIPS32_R2
 	bool
 
+config SYS_HAS_CPU_MIPS32_R3_5
+	bool
+
 config SYS_HAS_CPU_MIPS64_R1
 	bool
 
@@ -1657,6 +1681,9 @@ config CPU_MIPSR2
 	bool
 	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
 
+config EVA
+	bool
+
 config SYS_SUPPORTS_32BIT_KERNEL
 	bool
 config SYS_SUPPORTS_64BIT_KERNEL
@@ -1853,6 +1880,8 @@ config CPU_R4K_CACHE_TLB
 	bool
 	default y if !(CPU_R3000 || CPU_R8000 || CPU_SB1 || CPU_TX39XX || CPU_CAVIUM_OCTEON)
 
+source "drivers/cpuidle/Kconfig"
+
 choice
 	prompt "MIPS MT options"
 
@@ -1887,6 +1916,7 @@ config MIPS_MT_SMTC
 	bool "Use all TCs on all VPEs for SMP (DEPRECATED)"
 	depends on CPU_MIPS32_R2
 	depends on SYS_SUPPORTS_MULTITHREADING
+	depends on !MIPS_CPS
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select MIPS_MT
@@ -1994,13 +2024,45 @@ config MIPS_VPE_APSP_API_MT
 	depends on MIPS_VPE_APSP_API && !MIPS_CMP
 
 config MIPS_CMP
-	bool "MIPS CMP support"
-	depends on SYS_SUPPORTS_MIPS_CMP && MIPS_MT_SMP
+	bool "MIPS CMP framework support (DEPRECATED)"
+	depends on SYS_SUPPORTS_MIPS_CMP && !MIPS_MT_SMTC
+	select MIPS_GIC_IPI
 	select SYNC_R4K
 	select WEAK_ORDERING
 	default n
 	help
-	  Enable Coherency Manager processor (CMP) support.
+	  Select this if you are using a bootloader which implements the "CMP
+	  framework" protocol (ie. YAMON) and want your kernel to make use of
+	  its ability to start secondary CPUs.
+
+	  Unless you have a specific need, you should use CONFIG_MIPS_CPS
+	  instead of this.
+
+config MIPS_CPS
+	bool "MIPS Coherent Processing System support"
+	depends on SYS_SUPPORTS_MIPS_CPS
+	select MIPS_CM
+	select MIPS_CPC
+	select MIPS_GIC_IPI
+	select SMP
+	select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
+	select SYS_SUPPORTS_SMP
+	select WEAK_ORDERING
+	help
+	  Select this if you wish to run an SMP kernel across multiple cores
+	  within a MIPS Coherent Processing System. When this option is
+	  enabled the kernel will probe for other cores and boot them with
+	  no external assistance. It is safe to enable this when hardware
+	  support is unavailable.
+
+config MIPS_GIC_IPI
+	bool
+
+config MIPS_CM
+	bool
+
+config MIPS_CPC
+	bool
 
 config SB1_PASS_1_WORKAROUNDS
 	bool
@@ -2043,6 +2105,21 @@ config CPU_MICROMIPS
 	  When this option is enabled the kernel will be built using the
 	  microMIPS ISA
 
+config CPU_HAS_MSA
+	bool "Support for the MIPS SIMD Architecture"
+	depends on CPU_SUPPORTS_MSA
+	default y
+	help
+	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
+	  and a set of SIMD instructions to operate on them. When this option
+	  is enabled the kernel will support allocating & switching MSA
+	  vector register contexts. If you know that your kernel will only be
+	  running on CPUs which do not support MSA or that your userland will
+	  not be making use of it then you may wish to say N here to reduce
+	  the size & complexity of your kernel.
+
+	  If unsure, say Y.
+
 config CPU_HAS_WB
 	bool
 
@@ -2094,7 +2171,7 @@ config CPU_R4400_WORKAROUNDS
 #
 config HIGHMEM
 	bool "High Memory Support"
-	depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM
+	depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA
 
 config CPU_SUPPORTS_HIGHMEM
 	bool
@@ -2108,6 +2185,9 @@ config SYS_SUPPORTS_SMARTMIPS
 config SYS_SUPPORTS_MICROMIPS
 	bool
 
+config CPU_SUPPORTS_MSA
+	bool
+
 config ARCH_FLATMEM_ENABLE
 	def_bool y
 	depends on !NUMA && !CPU_LOONGSON2
@@ -2181,6 +2261,9 @@ config SMP_UP
 config SYS_SUPPORTS_MIPS_CMP
 	bool
 
+config SYS_SUPPORTS_MIPS_CPS
+	bool
+
 config SYS_SUPPORTS_SMP
 	bool
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 9b8556de9993..1a5b4032cb66 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -119,6 +119,11 @@ cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips)
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= $(call cc-option,-mno-sched-prolog) \
 				   -fno-omit-frame-pointer
 
+ifeq ($(CONFIG_CPU_HAS_MSA),y)
+toolchain-msa			:= $(call cc-option-yn,-mhard-float -mfp64 -mmsa)
+cflags-$(toolchain-msa)		+= -DTOOLCHAIN_SUPPORTS_MSA
+endif
+
 #
 # CPU-dependent compiler/assembler options for optimization.
 #
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig
index 7032ac7ecd1b..ef5368128413 100644
--- a/arch/mips/alchemy/Kconfig
+++ b/arch/mips/alchemy/Kconfig
@@ -20,32 +20,25 @@ choice
 
 config MIPS_MTX1
 	bool "4G Systems MTX-1 board"
-	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
-config MIPS_DB1000
-	bool "Alchemy DB1000/DB1500/DB1100 PB1500/1100 boards"
-	select ALCHEMY_GPIOINT_AU1000
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select SYS_HAS_EARLY_PRINTK
-
-config MIPS_DB1235
-	bool "Alchemy DB1200/PB1200/DB1300/DB1550/PB1550 boards"
+config MIPS_DB1XXX
+	bool "Alchemy DB1XXX / PB1XXX boards"
 	select ARCH_REQUIRE_GPIOLIB
 	select HW_HAS_PCI
-	select DMA_COHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
+	help
+	  Select this option if you have one of the following Alchemy
+	  development boards:  DB1000 DB1500 DB1100 DB1550 DB1200 DB1300
+			       PB1500 PB1100 PB1550 PB1200
+	  Board type is autodetected during boot.
 
 config MIPS_XXS1500
 	bool "MyCable XXS1500 board"
-	select DMA_NONCOHERENT
 	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
@@ -54,7 +47,6 @@ config MIPS_GPR
 	bool "Trapeze ITS GPR board"
 	select ALCHEMY_GPIOINT_AU1000
 	select HW_HAS_PCI
-	select DMA_NONCOHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
index b3afcdd8d77a..33c9da3b077b 100644
--- a/arch/mips/alchemy/Platform
+++ b/arch/mips/alchemy/Platform
@@ -5,18 +5,12 @@ platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/common/
 
 
 #
-# AMD Alchemy Db1000/Db1500/Pb1500/Db1100/Pb1100 eval boards
+# AMD Alchemy Db1000/Db1500/Pb1500/Db1100/Pb1100
+#             Db1550/Pb1550/Db1200/Pb1200/Db1300
 #
-platform-$(CONFIG_MIPS_DB1000)	+= alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1000)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1200/Pb1200/Db1550/Pb1550/Db1300 eval boards
-#
-platform-$(CONFIG_MIPS_DB1235)	+= alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1235)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1235)	+= 0xffffffff80100000
+platform-$(CONFIG_MIPS_DB1XXX)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1XXX)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1XXX)	+= 0xffffffff80100000
 
 #
 # 4G-Systems MTX-1 "MeshCube" wireless router
diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
index 9edc35ff8cf1..acf9a2a37f5a 100644
--- a/arch/mips/alchemy/board-gpr.c
+++ b/arch/mips/alchemy/board-gpr.c
@@ -53,10 +53,8 @@ void __init prom_init(void)
 	prom_init_cmdline();
 
 	memsize_str = prom_getenv("memsize");
-	if (!memsize_str)
+	if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
 		memsize = 0x04000000;
-	else
-		strict_strtoul(memsize_str, 0, &memsize);
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 9969dbab19e3..25a59a23547e 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -52,10 +52,8 @@ void __init prom_init(void)
 	prom_init_cmdline();
 
 	memsize_str = prom_getenv("memsize");
-	if (!memsize_str)
+	if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
 		memsize = 0x04000000;
-	else
-		strict_strtoul(memsize_str, 0, &memsize);
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index 62b4e7bbeab9..566a1743f685 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -30,6 +30,7 @@
 #include <linux/jiffies.h>
 #include <linux/module.h>
 
+#include <asm/dma-coherence.h>
 #include <asm/mipsregs.h>
 #include <asm/time.h>
 
@@ -59,6 +60,15 @@ void __init plat_mem_setup(void)
 		/* Clear to obtain best system bus performance */
 		clear_c0_config(1 << 19); /* Clear Config[OD] */
 
+	hw_coherentio = 0;
+	coherentio = 1;
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+		coherentio = 0;
+	}
+
 	board_setup();	/* board specific setup */
 
 	/* IO/MEM resources. */
diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile
index 15bf7306648b..9da3659a9d1c 100644
--- a/arch/mips/alchemy/devboards/Makefile
+++ b/arch/mips/alchemy/devboards/Makefile
@@ -2,7 +2,5 @@
 # Alchemy Develboards
 #
 
-obj-y += bcsr.o platform.o
+obj-y += bcsr.o platform.o db1000.o db1200.o db1300.o db1550.o db1xxx.o
 obj-$(CONFIG_PM)		+= pm.o
-obj-$(CONFIG_MIPS_DB1000)	+= db1000.o
-obj-$(CONFIG_MIPS_DB1235)	+= db1235.o db1200.o db1300.o db1550.o
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 5483906e0f86..92dd929d4057 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -41,42 +41,27 @@
 
 #define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
 
-struct pci_dev;
+const char *get_system_type(void);
 
-static const char *board_type_str(void)
+int __init db1000_board_setup(void)
 {
+	/* initialize board register space */
+	bcsr_init(DB1000_BCSR_PHYS_ADDR,
+		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
+
 	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
 	case BCSR_WHOAMI_DB1000:
-		return "DB1000";
 	case BCSR_WHOAMI_DB1500:
-		return "DB1500";
 	case BCSR_WHOAMI_DB1100:
-		return "DB1100";
 	case BCSR_WHOAMI_PB1500:
 	case BCSR_WHOAMI_PB1500R2:
-		return "PB1500";
 	case BCSR_WHOAMI_PB1100:
-		return "PB1100";
-	default:
-		return "(unknown)";
+		pr_info("AMD Alchemy %s Board\n", get_system_type());
+		return 0;
 	}
+	return -ENODEV;
 }
 
-const char *get_system_type(void)
-{
-	return board_type_str();
-}
-
-void __init board_setup(void)
-{
-	/* initialize board register space */
-	bcsr_init(DB1000_BCSR_PHYS_ADDR,
-		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
-
-	printk(KERN_INFO "AMD Alchemy %s Board\n", board_type_str());
-}
-
-
 static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
 {
 	if ((slot < 12) || (slot > 13) || pin == 0)
@@ -114,17 +99,10 @@ static struct platform_device db1500_pci_host_dev = {
 	.resource	= alchemy_pci_host_res,
 };
 
-static int __init db1500_pci_init(void)
+int __init db1500_pci_setup(void)
 {
-	int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
-	if ((id == BCSR_WHOAMI_DB1500) || (id == BCSR_WHOAMI_PB1500) ||
-	    (id == BCSR_WHOAMI_PB1500R2))
-		return platform_device_register(&db1500_pci_host_dev);
-	return 0;
+	return platform_device_register(&db1500_pci_host_dev);
 }
-/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
-arch_initcall(db1500_pci_init);
-
 
 static struct resource au1100_lcd_resources[] = {
 	[0] = {
@@ -513,7 +491,7 @@ static struct platform_device *db1100_devs[] = {
 	&db1000_irda_dev,
 };
 
-static int __init db1000_dev_init(void)
+int __init db1000_dev_setup(void)
 {
 	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
@@ -623,4 +601,3 @@ static int __init db1000_dev_init(void)
 	db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
 	return 0;
 }
-device_initcall(db1000_dev_init);
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index a84d98b8f96e..a60d0a3410ea 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -89,6 +89,15 @@ int __init db1200_board_setup(void)
 		return -ENODEV;
 
 	whoami = bcsr_read(BCSR_WHOAMI);
+	switch (BCSR_WHOAMI_BOARD(whoami)) {
+	case BCSR_WHOAMI_PB1200_DDR1:
+	case BCSR_WHOAMI_PB1200_DDR2:
+	case BCSR_WHOAMI_DB1200:
+		break;
+	default:
+		return -ENODEV;
+	}
+
 	printk(KERN_INFO "Alchemy/AMD/RMI %s Board, CPLD Rev %d"
 		"  Board-ID %d	Daughtercard ID %d\n", get_system_type(),
 		(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
diff --git a/arch/mips/alchemy/devboards/db1235.c b/arch/mips/alchemy/devboards/db1235.c
deleted file mode 100644
index bac19dc43d1d..000000000000
--- a/arch/mips/alchemy/devboards/db1235.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * DB1200/PB1200 / DB1550 / DB1300 board support.
- *
- * These 4 boards can reliably be supported in a single kernel image.
- */
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-db1x00/bcsr.h>
-
-int __init db1200_board_setup(void);
-int __init db1200_dev_setup(void);
-int __init db1300_board_setup(void);
-int __init db1300_dev_setup(void);
-int __init db1550_board_setup(void);
-int __init db1550_dev_setup(void);
-int __init db1550_pci_setup(int);
-
-static const char *board_type_str(void)
-{
-	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
-	case BCSR_WHOAMI_PB1200_DDR1:
-	case BCSR_WHOAMI_PB1200_DDR2:
-		return "PB1200";
-	case BCSR_WHOAMI_DB1200:
-		return "DB1200";
-	case BCSR_WHOAMI_DB1300:
-		return "DB1300";
-	case BCSR_WHOAMI_DB1550:
-		return "DB1550";
-	case BCSR_WHOAMI_PB1550_SDR:
-	case BCSR_WHOAMI_PB1550_DDR:
-		return "PB1550";
-	default:
-		return "(unknown)";
-	}
-}
-
-const char *get_system_type(void)
-{
-	return board_type_str();
-}
-
-void __init board_setup(void)
-{
-	int ret;
-
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1550:
-		ret = db1550_board_setup();
-		break;
-	case ALCHEMY_CPU_AU1200:
-		ret = db1200_board_setup();
-		break;
-	case ALCHEMY_CPU_AU1300:
-		ret = db1300_board_setup();
-		break;
-	default:
-		pr_err("unsupported CPU on board\n");
-		ret = -ENODEV;
-	}
-	if (ret)
-		panic("cannot initialize board support");
-}
-
-int __init db1235_arch_init(void)
-{
-	int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
-	if (id == BCSR_WHOAMI_DB1550)
-		return db1550_pci_setup(0);
-	else if ((id == BCSR_WHOAMI_PB1550_SDR) ||
-		 (id == BCSR_WHOAMI_PB1550_DDR))
-		return db1550_pci_setup(1);
-
-	return 0;
-}
-arch_initcall(db1235_arch_init);
-
-int __init db1235_dev_init(void)
-{
-	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
-	case BCSR_WHOAMI_PB1200_DDR1:
-	case BCSR_WHOAMI_PB1200_DDR2:
-	case BCSR_WHOAMI_DB1200:
-		return db1200_dev_setup();
-	case BCSR_WHOAMI_DB1300:
-		return db1300_dev_setup();
-	case BCSR_WHOAMI_DB1550:
-	case BCSR_WHOAMI_PB1550_SDR:
-	case BCSR_WHOAMI_PB1550_DDR:
-		return db1550_dev_setup();
-	}
-	return 0;
-}
-device_initcall(db1235_dev_init);
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index 6167e73eef9c..509602cb463a 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -759,11 +759,15 @@ int __init db1300_board_setup(void)
 {
 	unsigned short whoami;
 
-	db1300_gpio_config();
 	bcsr_init(DB1300_BCSR_PHYS_ADDR,
 		  DB1300_BCSR_PHYS_ADDR + DB1300_BCSR_HEXLED_OFS);
 
 	whoami = bcsr_read(BCSR_WHOAMI);
+	if (BCSR_WHOAMI_BOARD(whoami) != BCSR_WHOAMI_DB1300)
+		return -ENODEV;
+
+	db1300_gpio_config();
+
 	printk(KERN_INFO "NetLogic DBAu1300 Development Platform.\n\t"
 		"BoardID %d   CPLD Rev %d   DaughtercardID %d\n",
 		BCSR_WHOAMI_BOARD(whoami), BCSR_WHOAMI_CPLD(whoami),
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index 016cddacd7ea..bbd8d9884702 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -62,10 +62,16 @@ int __init db1550_board_setup(void)
 		  DB1550_BCSR_PHYS_ADDR + DB1550_BCSR_HEXLED_OFS);
 
 	whoami = bcsr_read(BCSR_WHOAMI); /* PB1550 hexled offset differs */
-	if ((BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_SDR) ||
-	    (BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_DDR))
+	switch (BCSR_WHOAMI_BOARD(whoami)) {
+	case BCSR_WHOAMI_PB1550_SDR:
+	case BCSR_WHOAMI_PB1550_DDR:
 		bcsr_init(PB1550_BCSR_PHYS_ADDR,
 			  PB1550_BCSR_PHYS_ADDR + PB1550_BCSR_HEXLED_OFS);
+	case BCSR_WHOAMI_DB1550:
+		break;
+	default:
+		return -ENODEV;
+	}
 
 	pr_info("Alchemy/AMD %s Board, CPLD Rev %d Board-ID %d	"	\
 		"Daughtercard ID %d\n", get_system_type(),
diff --git a/arch/mips/alchemy/devboards/db1xxx.c b/arch/mips/alchemy/devboards/db1xxx.c
new file mode 100644
index 000000000000..2d47f951121a
--- /dev/null
+++ b/arch/mips/alchemy/devboards/db1xxx.c
@@ -0,0 +1,121 @@
+/*
+ * Alchemy DB/PB1xxx board support.
+ */
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/bcsr.h>
+
+int __init db1000_board_setup(void);
+int __init db1000_dev_setup(void);
+int __init db1500_pci_setup(void);
+int __init db1200_board_setup(void);
+int __init db1200_dev_setup(void);
+int __init db1300_board_setup(void);
+int __init db1300_dev_setup(void);
+int __init db1550_board_setup(void);
+int __init db1550_dev_setup(void);
+int __init db1550_pci_setup(int);
+
+static const char *board_type_str(void)
+{
+	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
+	case BCSR_WHOAMI_DB1000:
+		return "DB1000";
+	case BCSR_WHOAMI_DB1500:
+		return "DB1500";
+	case BCSR_WHOAMI_DB1100:
+		return "DB1100";
+	case BCSR_WHOAMI_PB1500:
+	case BCSR_WHOAMI_PB1500R2:
+		return "PB1500";
+	case BCSR_WHOAMI_PB1100:
+		return "PB1100";
+	case BCSR_WHOAMI_PB1200_DDR1:
+	case BCSR_WHOAMI_PB1200_DDR2:
+		return "PB1200";
+	case BCSR_WHOAMI_DB1200:
+		return "DB1200";
+	case BCSR_WHOAMI_DB1300:
+		return "DB1300";
+	case BCSR_WHOAMI_DB1550:
+		return "DB1550";
+	case BCSR_WHOAMI_PB1550_SDR:
+	case BCSR_WHOAMI_PB1550_DDR:
+		return "PB1550";
+	default:
+		return "(unknown)";
+	}
+}
+
+const char *get_system_type(void)
+{
+	return board_type_str();
+}
+
+void __init board_setup(void)
+{
+	int ret;
+
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+		ret = db1000_board_setup();
+		break;
+	case ALCHEMY_CPU_AU1550:
+		ret = db1550_board_setup();
+		break;
+	case ALCHEMY_CPU_AU1200:
+		ret = db1200_board_setup();
+		break;
+	case ALCHEMY_CPU_AU1300:
+		ret = db1300_board_setup();
+		break;
+	default:
+		pr_err("unsupported CPU on board\n");
+		ret = -ENODEV;
+	}
+	if (ret)
+		panic("cannot initialize board support");
+}
+
+static int __init db1xxx_arch_init(void)
+{
+	int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
+	if (id == BCSR_WHOAMI_DB1550)
+		return db1550_pci_setup(0);
+	else if ((id == BCSR_WHOAMI_PB1550_SDR) ||
+		 (id == BCSR_WHOAMI_PB1550_DDR))
+		return db1550_pci_setup(1);
+	else if ((id == BCSR_WHOAMI_DB1500) || (id == BCSR_WHOAMI_PB1500) ||
+		 (id == BCSR_WHOAMI_PB1500R2))
+		return db1500_pci_setup();
+
+	return 0;
+}
+arch_initcall(db1xxx_arch_init);
+
+static int __init db1xxx_dev_init(void)
+{
+	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
+	case BCSR_WHOAMI_DB1000:
+	case BCSR_WHOAMI_DB1500:
+	case BCSR_WHOAMI_DB1100:
+	case BCSR_WHOAMI_PB1500:
+	case BCSR_WHOAMI_PB1500R2:
+	case BCSR_WHOAMI_PB1100:
+		return db1000_dev_setup();
+	case BCSR_WHOAMI_PB1200_DDR1:
+	case BCSR_WHOAMI_PB1200_DDR2:
+	case BCSR_WHOAMI_DB1200:
+		return db1200_dev_setup();
+	case BCSR_WHOAMI_DB1300:
+		return db1300_dev_setup();
+	case BCSR_WHOAMI_DB1550:
+	case BCSR_WHOAMI_PB1550_SDR:
+	case BCSR_WHOAMI_PB1550_DDR:
+		return db1550_dev_setup();
+	}
+	return 0;
+}
+device_initcall(db1xxx_dev_init);
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 3995e31a73e2..dfc60209dc63 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -74,34 +74,26 @@ config ATH79_MACH_UBNT_XM
 endmenu
 
 config SOC_AR71XX
-	select USB_ARCH_HAS_EHCI
-	select USB_ARCH_HAS_OHCI
 	select HW_HAS_PCI
 	def_bool n
 
 config SOC_AR724X
-	select USB_ARCH_HAS_EHCI
-	select USB_ARCH_HAS_OHCI
 	select HW_HAS_PCI
 	select PCI_AR724X if PCI
 	def_bool n
 
 config SOC_AR913X
-	select USB_ARCH_HAS_EHCI
 	def_bool n
 
 config SOC_AR933X
-	select USB_ARCH_HAS_EHCI
 	def_bool n
 
 config SOC_AR934X
-	select USB_ARCH_HAS_EHCI
 	select HW_HAS_PCI
 	select PCI_AR724X if PCI
 	def_bool n
 
 config SOC_QCA955X
-	select USB_ARCH_HAS_EHCI
 	select HW_HAS_PCI
 	select PCI_AR724X if PCI
 	def_bool n
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
index 6d612e2b949b..cdd8246f92b3 100644
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -1,3 +1,4 @@
+#include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/string.h>
 #include <bcm47xx_board.h>
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 025be218ea15..b847d0373443 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -212,7 +212,7 @@ void __init plat_mem_setup(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
-	if (c->cputype == CPU_74K) {
+	if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K)) {
 		printk(KERN_INFO "bcm47xx: using bcma bus\n");
 #ifdef CONFIG_BCM47XX_BCMA
 		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
deleted file mode 100644
index bac26b971c5e..000000000000
--- a/arch/mips/configs/db1000_defconfig
+++ /dev/null
@@ -1,359 +0,0 @@
-CONFIG_MIPS=y
-CONFIG_MIPS_ALCHEMY=y
-CONFIG_MIPS_DB1000=y
-CONFIG_SCHED_OMIT_FRAME_POINTER=y
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_HZ_100=y
-CONFIG_HZ=100
-CONFIG_PREEMPT_NONE=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_CROSS_COMPILE=""
-CONFIG_LOCALVERSION="-db1x00"
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_KERNEL_LZMA=y
-CONFIG_DEFAULT_HOSTNAME="db1x00"
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_FHANDLE=y
-CONFIG_AUDIT=y
-CONFIG_TINY_RCU=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_NAMESPACES=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
-CONFIG_SYSCTL=y
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_EMBEDDED=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_SLAB=y
-CONFIG_SLABINFO=y
-CONFIG_BLOCK=y
-CONFIG_LBDAF=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_DEFAULT_NOOP=y
-CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_FREEZER=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCCARD=y
-CONFIG_PCMCIA=y
-CONFIG_PCMCIA_LOAD_CIS=y
-CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
-CONFIG_BINFMT_ELF=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
-CONFIG_SUSPEND=y
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_PM_SLEEP=y
-CONFIG_PM_RUNTIME=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_INET_TUNNEL=y
-CONFIG_INET_LRO=y
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_IPV6=y
-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
-CONFIG_INET6_XFRM_MODE_BEET=y
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_STP=y
-CONFIG_GARP=y
-CONFIG_BRIDGE=y
-CONFIG_BRIDGE_IGMP_SNOOPING=y
-CONFIG_VLAN_8021Q=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_LLC=y
-CONFIG_LLC2=y
-CONFIG_DNS_RESOLVER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIBTUSB=y
-CONFIG_UEVENT_HELPER_PATH=""
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-CONFIG_MTD_CFI_I4=y
-CONFIG_MTD_CFI_I8=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_SCSI_MOD=y
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-CONFIG_SCSI_PROC_FS=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_ATA=y
-CONFIG_ATA_VERBOSE_ERROR=y
-CONFIG_ATA_SFF=y
-CONFIG_ATA_BMDMA=y
-CONFIG_PATA_HPT37X=y
-CONFIG_PATA_PCMCIA=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_FIREWIRE=y
-CONFIG_FIREWIRE_OHCI=y
-CONFIG_FIREWIRE_OHCI_DEBUG=y
-CONFIG_FIREWIRE_NET=y
-CONFIG_NETDEVICES=y
-CONFIG_MII=y
-CONFIG_PHYLIB=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MIPS_AU1X00_ENET=y
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=y
-CONFIG_PCMCIA_PCNET=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=y
-CONFIG_PPPOE=y
-CONFIG_INPUT=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
-CONFIG_DEVKMEM=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_TTY_PRINTK=y
-CONFIG_DEVPORT=y
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_AU1100=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x16=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_JACK=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_HRTIMER=y
-CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_AC97_BUS=y
-CONFIG_SND_SOC_AU1XAUDIO=y
-CONFIG_SND_SOC_AU1XAC97C=y
-CONFIG_SND_SOC_DB1000=y
-CONFIG_SND_SOC_AC97_CODEC=y
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-CONFIG_HIDRAW=y
-CONFIG_USB_HID=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-CONFIG_RTC_DRV_AU1XXX=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_USE_FOR_EXT23=y
-CONFIG_EXT4_FS_XATTR=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_JBD2=y
-CONFIG_FS_MBCACHE=y
-CONFIG_FS_POSIX_ACL=y
-CONFIG_EXPORTFS=y
-CONFIG_FILE_LOCKING=y
-CONFIG_FSNOTIFY=y
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY_USER=y
-CONFIG_GENERIC_ACL=y
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_MISC_FILESYSTEMS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_FS_POSIX_ACL=y
-CONFIG_JFFS2_FS_SECURITY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_RTIME=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_JFFS2_CMODE_PRIORITY=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_ZLIB=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_PNFS_FILE_LAYOUT=y
-CONFIG_PNFS_BLOCK=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFS_USE_KERNEL_DNS=y
-CONFIG_NFS_USE_NEW_IDMAPPER=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_SUNRPC_BACKCHANNEL=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="noirqdebug rootwait root=/dev/sda1 rootfstype=ext4 console=ttyS0,115200 video=au1100fb:panel:CRT_800x600_16"
-CONFIG_DEBUG_ZBOOT=y
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-CONFIG_SECURITYFS=y
-CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_DEFAULT_SECURITY=""
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_PCOMP2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
-CONFIG_CRYPTO_WORKQUEUE=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
-CONFIG_XZ_DEC=y
diff --git a/arch/mips/configs/db1235_defconfig b/arch/mips/configs/db1235_defconfig
deleted file mode 100644
index 28e49f226dc0..000000000000
--- a/arch/mips/configs/db1235_defconfig
+++ /dev/null
@@ -1,434 +0,0 @@
-CONFIG_MIPS_ALCHEMY=y
-CONFIG_MIPS_DB1235=y
-CONFIG_COMPACTION=y
-CONFIG_KSM=y
-CONFIG_HZ_100=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCALVERSION="-db1235"
-CONFIG_KERNEL_LZMA=y
-CONFIG_DEFAULT_HOSTNAME="db1235"
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_FHANDLE=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_AUDIT=y
-CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_NAMESPACES=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_JUMP_LABEL=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_LDM_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_PCI=y
-CONFIG_PCCARD=y
-CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=y
-CONFIG_XFRM_USER=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE_DEMUX=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-CONFIG_NET_IPVTI=y
-CONFIG_INET_AH=y
-CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
-CONFIG_INET_UDP_DIAG=y
-CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_HSTCP=y
-CONFIG_TCP_CONG_HYBLA=y
-CONFIG_TCP_CONG_SCALABLE=y
-CONFIG_TCP_CONG_LP=y
-CONFIG_TCP_CONG_VENO=y
-CONFIG_TCP_CONG_YEAH=y
-CONFIG_TCP_CONG_ILLINOIS=y
-CONFIG_DEFAULT_HYBLA=y
-CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_IPV6_MIP6=y
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
-CONFIG_IPV6_SIT_6RD=y
-CONFIG_IPV6_TUNNEL=y
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_IPV6_MROUTE=y
-CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IPV6_PIMSM_V2=y
-CONFIG_NETFILTER=y
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CONNTRACK_TIMEOUT=y
-CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=y
-CONFIG_NF_CONNTRACK_FTP=y
-CONFIG_NF_CONNTRACK_H323=y
-CONFIG_NF_CONNTRACK_IRC=y
-CONFIG_NF_CONNTRACK_NETBIOS_NS=y
-CONFIG_NF_CONNTRACK_SNMP=y
-CONFIG_NF_CONNTRACK_PPTP=y
-CONFIG_NF_CONNTRACK_SANE=y
-CONFIG_NF_CONNTRACK_SIP=y
-CONFIG_NF_CONNTRACK_TFTP=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NF_CT_NETLINK_TIMEOUT=y
-CONFIG_NF_CT_NETLINK_HELPER=y
-CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_HMARK=y
-CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
-CONFIG_NETFILTER_XT_TARGET_LED=y
-CONFIG_NETFILTER_XT_TARGET_LOG=y
-CONFIG_NETFILTER_XT_TARGET_MARK=y
-CONFIG_NETFILTER_XT_TARGET_NFLOG=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_TARGET_TEE=y
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
-CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
-CONFIG_NETFILTER_XT_MATCH_CLUSTER=y
-CONFIG_NETFILTER_XT_MATCH_COMMENT=y
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_CPU=y
-CONFIG_NETFILTER_XT_MATCH_DCCP=y
-CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y
-CONFIG_NETFILTER_XT_MATCH_DSCP=y
-CONFIG_NETFILTER_XT_MATCH_ESP=y
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_HELPER=y
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-CONFIG_NETFILTER_XT_MATCH_LENGTH=y
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_NFACCT=y
-CONFIG_NETFILTER_XT_MATCH_OSF=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA=y
-CONFIG_NETFILTER_XT_MATCH_RATEEST=y
-CONFIG_NETFILTER_XT_MATCH_REALM=y
-CONFIG_NETFILTER_XT_MATCH_RECENT=y
-CONFIG_NETFILTER_XT_MATCH_SCTP=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
-CONFIG_NETFILTER_XT_MATCH_STRING=y
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
-CONFIG_NETFILTER_XT_MATCH_TIME=y
-CONFIG_NETFILTER_XT_MATCH_U32=y
-CONFIG_NF_CONNTRACK_IPV4=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_AH=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_RPFILTER=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_NF_NAT=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_CLUSTERIP=y
-CONFIG_IP_NF_TARGET_ECN=y
-CONFIG_IP_NF_TARGET_TTL=y
-CONFIG_IP_NF_RAW=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_NF_CONNTRACK_IPV6=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_MATCH_AH=y
-CONFIG_IP6_NF_MATCH_EUI64=y
-CONFIG_IP6_NF_MATCH_FRAG=y
-CONFIG_IP6_NF_MATCH_OPTS=y
-CONFIG_IP6_NF_MATCH_HL=y
-CONFIG_IP6_NF_MATCH_IPV6HEADER=y
-CONFIG_IP6_NF_MATCH_MH=y
-CONFIG_IP6_NF_MATCH_RPFILTER=y
-CONFIG_IP6_NF_MATCH_RT=y
-CONFIG_IP6_NF_TARGET_HL=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_MANGLE=y
-CONFIG_IP6_NF_RAW=y
-CONFIG_BRIDGE_NF_EBTABLES=y
-CONFIG_BRIDGE_EBT_BROUTE=y
-CONFIG_BRIDGE_EBT_T_FILTER=y
-CONFIG_BRIDGE_EBT_T_NAT=y
-CONFIG_BRIDGE_EBT_802_3=y
-CONFIG_BRIDGE_EBT_AMONG=y
-CONFIG_BRIDGE_EBT_ARP=y
-CONFIG_BRIDGE_EBT_IP=y
-CONFIG_BRIDGE_EBT_IP6=y
-CONFIG_BRIDGE_EBT_LIMIT=y
-CONFIG_BRIDGE_EBT_MARK=y
-CONFIG_BRIDGE_EBT_PKTTYPE=y
-CONFIG_BRIDGE_EBT_STP=y
-CONFIG_BRIDGE_EBT_VLAN=y
-CONFIG_BRIDGE_EBT_ARPREPLY=y
-CONFIG_BRIDGE_EBT_DNAT=y
-CONFIG_BRIDGE_EBT_MARK_T=y
-CONFIG_BRIDGE_EBT_REDIRECT=y
-CONFIG_BRIDGE_EBT_SNAT=y
-CONFIG_BRIDGE_EBT_LOG=y
-CONFIG_BRIDGE_EBT_NFLOG=y
-CONFIG_L2TP=y
-CONFIG_L2TP_V3=y
-CONFIG_L2TP_IP=y
-CONFIG_L2TP_ETH=y
-CONFIG_BRIDGE=y
-CONFIG_VLAN_8021Q=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_LLC2=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=y
-CONFIG_NET_SCH_HTB=y
-CONFIG_NET_SCH_HFSC=y
-CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_MULTIQ=y
-CONFIG_NET_SCH_RED=y
-CONFIG_NET_SCH_SFB=y
-CONFIG_NET_SCH_SFQ=y
-CONFIG_NET_SCH_TEQL=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_GRED=y
-CONFIG_NET_SCH_DSMARK=y
-CONFIG_NET_SCH_NETEM=y
-CONFIG_NET_SCH_DRR=y
-CONFIG_NET_SCH_MQPRIO=y
-CONFIG_NET_SCH_CHOKE=y
-CONFIG_NET_SCH_QFQ=y
-CONFIG_NET_SCH_CODEL=y
-CONFIG_NET_SCH_FQ_CODEL=y
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NET_SCH_PLUG=y
-CONFIG_NET_CLS_BASIC=y
-CONFIG_NET_CLS_TCINDEX=y
-CONFIG_NET_CLS_ROUTE4=y
-CONFIG_NET_CLS_FW=y
-CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_PERF=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=y
-CONFIG_NET_CLS_RSVP6=y
-CONFIG_NET_CLS_FLOW=y
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_CMP=y
-CONFIG_NET_EMATCH_NBYTE=y
-CONFIG_NET_EMATCH_U32=y
-CONFIG_NET_EMATCH_META=y
-CONFIG_NET_EMATCH_TEXT=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_NET_ACT_NAT=y
-CONFIG_NET_ACT_PEDIT=y
-CONFIG_NET_ACT_SIMP=y
-CONFIG_NET_ACT_SKBEDIT=y
-CONFIG_NET_ACT_CSUM=y
-CONFIG_NET_CLS_IND=y
-CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIBTUSB=y
-CONFIG_CFG80211=y
-CONFIG_CFG80211_CERTIFICATION_ONUS=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_MAC80211=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_RFKILL=y
-CONFIG_RFKILL_INPUT=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PLATFORM=y
-CONFIG_EEPROM_AT24=y
-CONFIG_EEPROM_AT25=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE_AU1XXX=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_ATA=y
-CONFIG_PATA_HPT37X=y
-CONFIG_PATA_PCMCIA=y
-CONFIG_PATA_PLATFORM=y
-CONFIG_NETDEVICES=y
-CONFIG_MIPS_AU1X00_ENET=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_AMD_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_RT2X00=y
-CONFIG_RT73USB=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_WM97XX=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_TTY_PRINTK=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_AU1550=y
-CONFIG_SPI=y
-CONFIG_SPI_AU1550=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SENSORS_ADM1025=y
-CONFIG_SENSORS_LM70=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_HRTIMER=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_AU1XPSC=y
-CONFIG_SND_SOC_DB1200=y
-CONFIG_HIDRAW=y
-CONFIG_UHID=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_AU1X=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AU1XXX=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_CMODE_FAVOURLZO=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_STRIP_ASM_SYMS=y
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_USER=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_CRYPTD=y
-CONFIG_CRYPTO_CCM=y
-CONFIG_CRYPTO_GCM=y
-CONFIG_CRYPTO_CTS=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_XTS=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_VMAC=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_RMD128=y
-CONFIG_CRYPTO_RMD160=y
-CONFIG_CRYPTO_RMD256=y
-CONFIG_CRYPTO_RMD320=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_CAMELLIA=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_SALSA20=y
-CONFIG_CRYPTO_SEED=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=y
-CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_USER_API_SKCIPHER=y
diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig
new file mode 100644
index 000000000000..3bccd5b1f358
--- /dev/null
+++ b/arch/mips/configs/db1xxx_defconfig
@@ -0,0 +1,248 @@
+CONFIG_MIPS_ALCHEMY=y
+CONFIG_MIPS_DB1XXX=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUG=y
+CONFIG_HZ_100=y
+CONFIG_LOCALVERSION="-db1xxx"
+CONFIG_KERNEL_XZ=y
+CONFIG_DEFAULT_HOSTNAME="db1xxx"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_DEFAULT_NOOP=y
+CONFIG_PCI=y
+CONFIG_PCI_REALLOC_ENABLE_AUTO=y
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_VENO=y
+CONFIG_DEFAULT_VENO=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_VTI=y
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_BRIDGE=y
+CONFIG_NETLINK_MMAP=y
+CONFIG_NETLINK_DIAG=y
+CONFIG_IRDA=y
+CONFIG_IRLAN=y
+CONFIG_IRCOMM=y
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_AU1000_FIR=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC_BCH=y
+CONFIG_MTD_NAND_AU1550=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_IDE=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_BLK_DEV_IDE_AU1XXX=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_PATA_HPT37X=y
+CONFIG_PATA_HPT3X2N=y
+CONFIG_PATA_PCMCIA=y
+CONFIG_PATA_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_NLMON=y
+CONFIG_PCMCIA_3C589=y
+CONFIG_MIPS_AU1X00_ENET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+CONFIG_AMD_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_TOUCHSCREEN_WM97XX=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_TTY_PRINTK=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_AU1550=y
+CONFIG_SPI=y
+CONFIG_SPI_AU1550=y
+CONFIG_SPI_GPIO=y
+CONFIG_SENSORS_ADM1025=y
+CONFIG_SENSORS_LM70=y
+CONFIG_FB=y
+CONFIG_FB_AU1100=y
+CONFIG_FB_AU1200=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_HRTIMER=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=1
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_AU1XPSC=y
+CONFIG_SND_SOC_AU1XAUDIO=y
+CONFIG_SND_SOC_DB1000=y
+CONFIG_SND_SOC_DB1200=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_OTG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_AU1X=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AU1XXX=y
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_XFS_FS=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_FANOTIFY=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="local"
+CONFIG_NFS_V4_1_MIGRATION=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRC32_SLICEBY4=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index ce1d3eeeb737..b745b6a9f322 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,9 @@
 CONFIG_MIPS_MALTA=y
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_CPU_MIPS32_R2=y
+CONFIG_PAGE_SIZE_16KB=y
 CONFIG_MIPS_MT_SMP=y
+CONFIG_NR_CPUS=8
 CONFIG_HZ_100=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
@@ -42,7 +44,6 @@ CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -68,7 +69,6 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -125,7 +125,6 @@ CONFIG_IP_VS_SH=m
 CONFIG_IP_VS_SED=m
 CONFIG_IP_VS_NQ=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -185,7 +184,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_PHONET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
@@ -226,9 +224,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_MESH=y
 CONFIG_RFKILL=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_CONNECTOR=m
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_OOPS=m
 CONFIG_MTD_CFI=y
@@ -328,7 +326,6 @@ CONFIG_LIBERTAS=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HWMON is not set
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
index 341bb47204d6..4f7d952d8517 100644
--- a/arch/mips/configs/malta_kvm_defconfig
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -3,6 +3,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_CPU_MIPS32_R2=y
 CONFIG_PAGE_SIZE_16KB=y
 CONFIG_MIPS_MT_SMP=y
+CONFIG_NR_CPUS=8
 CONFIG_HZ_100=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
@@ -44,7 +45,6 @@ CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -70,7 +70,6 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -127,7 +126,6 @@ CONFIG_IP_VS_SH=m
 CONFIG_IP_VS_SED=m
 CONFIG_IP_VS_NQ=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -187,7 +185,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_PHONET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
@@ -228,9 +225,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_MESH=y
 CONFIG_RFKILL=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_CONNECTOR=m
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_OOPS=m
 CONFIG_MTD_CFI=y
@@ -300,6 +297,7 @@ CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
+CONFIG_VHOST_NET=m
 CONFIG_PCNET32=y
 CONFIG_CHELSIO_T3=m
 CONFIG_AX88796=m
@@ -329,7 +327,6 @@ CONFIG_LIBERTAS=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HWMON is not set
@@ -453,4 +450,3 @@ CONFIG_VIRTUALIZATION=y
 CONFIG_KVM=m
 CONFIG_KVM_MIPS_DYN_TRANS=y
 CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS=y
-CONFIG_VHOST_NET=m
diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig
index 2b8558b71080..e36681c24ddc 100644
--- a/arch/mips/configs/malta_kvm_guest_defconfig
+++ b/arch/mips/configs/malta_kvm_guest_defconfig
@@ -44,7 +44,6 @@ CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -70,7 +69,6 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -127,7 +125,6 @@ CONFIG_IP_VS_SH=m
 CONFIG_IP_VS_SED=m
 CONFIG_IP_VS_NQ=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -187,7 +184,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_PHONET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
@@ -228,9 +224,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_MESH=y
 CONFIG_RFKILL=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_CONNECTOR=m
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_OOPS=m
 CONFIG_MTD_CFI=y
@@ -331,7 +327,6 @@ CONFIG_LIBERTAS=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HWMON is not set
diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig
index 93057a760dfa..fb042ce86b4b 100644
--- a/arch/mips/configs/maltaaprp_defconfig
+++ b/arch/mips/configs/maltaaprp_defconfig
@@ -44,7 +44,6 @@ CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 # CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -55,7 +54,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
@@ -80,6 +78,7 @@ CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_NET_CLS_IND=y
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
diff --git a/arch/mips/configs/maltasmtc_defconfig b/arch/mips/configs/maltasmtc_defconfig
index 4e54b75d89be..eb316447588c 100644
--- a/arch/mips/configs/maltasmtc_defconfig
+++ b/arch/mips/configs/maltasmtc_defconfig
@@ -1,6 +1,7 @@
 CONFIG_MIPS_MALTA=y
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_CPU_MIPS32_R2=y
+CONFIG_PAGE_SIZE_16KB=y
 CONFIG_MIPS_MT_SMTC=y
 # CONFIG_MIPS_MT_FPAFF is not set
 CONFIG_NR_CPUS=9
@@ -45,7 +46,6 @@ CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 # CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -56,7 +56,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
@@ -81,6 +80,7 @@ CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_NET_CLS_IND=y
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig
index d75931850392..10ef3bed5f43 100644
--- a/arch/mips/configs/maltasmvp_defconfig
+++ b/arch/mips/configs/maltasmvp_defconfig
@@ -1,10 +1,11 @@
 CONFIG_MIPS_MALTA=y
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_CPU_MIPS32_R2=y
+CONFIG_PAGE_SIZE_16KB=y
 CONFIG_MIPS_MT_SMP=y
 CONFIG_SCHED_SMT=y
 CONFIG_MIPS_CMP=y
-CONFIG_NR_CPUS=2
+CONFIG_NR_CPUS=8
 CONFIG_HZ_100=y
 CONFIG_LOCALVERSION="cmp"
 CONFIG_SYSVIPC=y
@@ -47,7 +48,6 @@ CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 # CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -82,6 +82,7 @@ CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_NET_CLS_IND=y
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig
new file mode 100644
index 000000000000..2d3002cba102
--- /dev/null
+++ b/arch/mips/configs/maltasmvp_eva_defconfig
@@ -0,0 +1,200 @@
+CONFIG_MIPS_MALTA=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32_3_5_FEATURES=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_MIPS_MT_SMP=y
+CONFIG_SCHED_SMT=y
+CONFIG_MIPS_CMP=y
+CONFIG_NR_CPUS=8
+CONFIG_HZ_100=y
+CONFIG_LOCALVERSION="cmp"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=m
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+# CONFIG_INET_LRO is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_IDE=y
+# CONFIG_IDE_PROC_FS is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+CONFIG_PCNET32=y
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_VT is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_G=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig
index 9868fc9c1133..62344648eb7a 100644
--- a/arch/mips/configs/maltaup_defconfig
+++ b/arch/mips/configs/maltaup_defconfig
@@ -43,7 +43,6 @@ CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 # CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -54,7 +53,6 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
@@ -79,6 +77,7 @@ CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_NET_CLS_IND=y
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 2d7f65052c1f..05439187891d 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -2,16 +2,17 @@
 generic-y += cputime.h
 generic-y += current.h
 generic-y += emergency-restart.h
+generic-y += hash.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mutex.h
 generic-y += parport.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += ucontext.h
 generic-y += xor.h
-generic-y += hash.h
diff --git a/arch/mips/include/asm/asm-eva.h b/arch/mips/include/asm/asm-eva.h
new file mode 100644
index 000000000000..e41c56e375b1
--- /dev/null
+++ b/arch/mips/include/asm/asm-eva.h
@@ -0,0 +1,135 @@
+/*
+ * 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 Imagination Technologies Ltd.
+ *
+ */
+
+#ifndef __ASM_ASM_EVA_H
+#define __ASM_ASM_EVA_H
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_EVA
+
+#define __BUILD_EVA_INSN(insn, reg, addr)				\
+				"	.set	push\n"			\
+				"	.set	mips0\n"		\
+				"	.set	eva\n"			\
+				"	"insn" "reg", "addr "\n"	\
+				"	.set	pop\n"
+
+#define user_cache(op, base)		__BUILD_EVA_INSN("cachee", op, base)
+#define user_ll(reg, addr)		__BUILD_EVA_INSN("lle", reg, addr)
+#define user_sc(reg, addr)		__BUILD_EVA_INSN("sce", reg, addr)
+#define user_lw(reg, addr)		__BUILD_EVA_INSN("lwe", reg, addr)
+#define user_lwl(reg, addr)		__BUILD_EVA_INSN("lwle", reg, addr)
+#define user_lwr(reg, addr)		__BUILD_EVA_INSN("lwre", reg, addr)
+#define user_lh(reg, addr)		__BUILD_EVA_INSN("lhe", reg, addr)
+#define user_lb(reg, addr)		__BUILD_EVA_INSN("lbe", reg, addr)
+#define user_lbu(reg, addr)		__BUILD_EVA_INSN("lbue", reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_ld(reg, addr)		user_lw(reg, addr)
+#define user_sw(reg, addr)		__BUILD_EVA_INSN("swe", reg, addr)
+#define user_swl(reg, addr)		__BUILD_EVA_INSN("swle", reg, addr)
+#define user_swr(reg, addr)		__BUILD_EVA_INSN("swre", reg, addr)
+#define user_sh(reg, addr)		__BUILD_EVA_INSN("she", reg, addr)
+#define user_sb(reg, addr)		__BUILD_EVA_INSN("sbe", reg, addr)
+/* No 64-bit EVA instruction for storing double words */
+#define user_sd(reg, addr)		user_sw(reg, addr)
+
+#else
+
+#define user_cache(op, base)		"cache " op ", " base "\n"
+#define user_ll(reg, addr)		"ll " reg ", " addr "\n"
+#define user_sc(reg, addr)		"sc " reg ", " addr "\n"
+#define user_lw(reg, addr)		"lw " reg ", " addr "\n"
+#define user_lwl(reg, addr)		"lwl " reg ", " addr "\n"
+#define user_lwr(reg, addr)		"lwr " reg ", " addr "\n"
+#define user_lh(reg, addr)		"lh " reg ", " addr "\n"
+#define user_lb(reg, addr)		"lb " reg ", " addr "\n"
+#define user_lbu(reg, addr)		"lbu " reg ", " addr "\n"
+#define user_sw(reg, addr)		"sw " reg ", " addr "\n"
+#define user_swl(reg, addr)		"swl " reg ", " addr "\n"
+#define user_swr(reg, addr)		"swr " reg ", " addr "\n"
+#define user_sh(reg, addr)		"sh " reg ", " addr "\n"
+#define user_sb(reg, addr)		"sb " reg ", " addr "\n"
+
+#ifdef CONFIG_32BIT
+/*
+ * No 'sd' or 'ld' instructions in 32-bit but the code will
+ * do the correct thing
+ */
+#define user_sd(reg, addr)		user_sw(reg, addr)
+#define user_ld(reg, addr)		user_lw(reg, addr)
+#else
+#define user_sd(reg, addr)		"sd " reg", " addr "\n"
+#define user_ld(reg, addr)		"ld " reg", " addr "\n"
+#endif /* CONFIG_32BIT */
+
+#endif /* CONFIG_EVA */
+
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_EVA
+
+#define __BUILD_EVA_INSN(insn, reg, addr)			\
+				.set	push;			\
+				.set	mips0;			\
+				.set	eva;			\
+				insn reg, addr;			\
+				.set	pop;
+
+#define user_cache(op, base)		__BUILD_EVA_INSN(cachee, op, base)
+#define user_ll(reg, addr)		__BUILD_EVA_INSN(lle, reg, addr)
+#define user_sc(reg, addr)		__BUILD_EVA_INSN(sce, reg, addr)
+#define user_lw(reg, addr)		__BUILD_EVA_INSN(lwe, reg, addr)
+#define user_lwl(reg, addr)		__BUILD_EVA_INSN(lwle, reg, addr)
+#define user_lwr(reg, addr)		__BUILD_EVA_INSN(lwre, reg, addr)
+#define user_lh(reg, addr)		__BUILD_EVA_INSN(lhe, reg, addr)
+#define user_lb(reg, addr)		__BUILD_EVA_INSN(lbe, reg, addr)
+#define user_lbu(reg, addr)		__BUILD_EVA_INSN(lbue, reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_ld(reg, addr)		user_lw(reg, addr)
+#define user_sw(reg, addr)		__BUILD_EVA_INSN(swe, reg, addr)
+#define user_swl(reg, addr)		__BUILD_EVA_INSN(swle, reg, addr)
+#define user_swr(reg, addr)		__BUILD_EVA_INSN(swre, reg, addr)
+#define user_sh(reg, addr)		__BUILD_EVA_INSN(she, reg, addr)
+#define user_sb(reg, addr)		__BUILD_EVA_INSN(sbe, reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_sd(reg, addr)		user_sw(reg, addr)
+#else
+
+#define user_cache(op, base)		cache op, base
+#define user_ll(reg, addr)		ll reg, addr
+#define user_sc(reg, addr)		sc reg, addr
+#define user_lw(reg, addr)		lw reg, addr
+#define user_lwl(reg, addr)		lwl reg, addr
+#define user_lwr(reg, addr)		lwr reg, addr
+#define user_lh(reg, addr)		lh reg, addr
+#define user_lb(reg, addr)		lb reg, addr
+#define user_lbu(reg, addr)		lbu reg, addr
+#define user_sw(reg, addr)		sw reg, addr
+#define user_swl(reg, addr)		swl reg, addr
+#define user_swr(reg, addr)		swr reg, addr
+#define user_sh(reg, addr)		sh reg, addr
+#define user_sb(reg, addr)		sb reg, addr
+
+#ifdef CONFIG_32BIT
+/*
+ * No 'sd' or 'ld' instructions in 32-bit but the code will
+ * do the correct thing
+ */
+#define user_sd(reg, addr)		user_sw(reg, addr)
+#define user_ld(reg, addr)		user_lw(reg, addr)
+#else
+#define user_sd(reg, addr)		sd reg, addr
+#define user_ld(reg, addr)		ld reg, addr
+#endif /* CONFIG_32BIT */
+
+#endif /* CONFIG_EVA */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ASM_EVA_H */
diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index 879691d194af..b153e7991a9d 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -18,6 +18,7 @@
 #define __ASM_ASM_H
 
 #include <asm/sgidefs.h>
+#include <asm/asm-eva.h>
 
 #ifndef CAT
 #ifdef __STDC__
@@ -149,6 +150,13 @@ symbol		=	value
 		pref	hint, addr;			\
 		.set	pop
 
+#define PREFE(hint, addr)				\
+		.set	push;				\
+		.set	mips0;				\
+		.set	eva;				\
+		prefe	hint, addr;			\
+		.set	pop
+
 #define PREFX(hint,addr)				\
 		.set	push;				\
 		.set	mips4;				\
@@ -158,6 +166,7 @@ symbol		=	value
 #else /* !CONFIG_CPU_HAS_PREFETCH */
 
 #define PREF(hint, addr)
+#define PREFE(hint, addr)
 #define PREFX(hint, addr)
 
 #endif /* !CONFIG_CPU_HAS_PREFETCH */
diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h
index 70e1f176f123..e38c2811d4e2 100644
--- a/arch/mips/include/asm/asmmacro-32.h
+++ b/arch/mips/include/asm/asmmacro-32.h
@@ -14,75 +14,75 @@
 
 	.macro	fpu_save_single thread tmp=t0
 	cfc1	\tmp,  fcr31
-	swc1	$f0,  THREAD_FPR0(\thread)
-	swc1	$f1,  THREAD_FPR1(\thread)
-	swc1	$f2,  THREAD_FPR2(\thread)
-	swc1	$f3,  THREAD_FPR3(\thread)
-	swc1	$f4,  THREAD_FPR4(\thread)
-	swc1	$f5,  THREAD_FPR5(\thread)
-	swc1	$f6,  THREAD_FPR6(\thread)
-	swc1	$f7,  THREAD_FPR7(\thread)
-	swc1	$f8,  THREAD_FPR8(\thread)
-	swc1	$f9,  THREAD_FPR9(\thread)
-	swc1	$f10, THREAD_FPR10(\thread)
-	swc1	$f11, THREAD_FPR11(\thread)
-	swc1	$f12, THREAD_FPR12(\thread)
-	swc1	$f13, THREAD_FPR13(\thread)
-	swc1	$f14, THREAD_FPR14(\thread)
-	swc1	$f15, THREAD_FPR15(\thread)
-	swc1	$f16, THREAD_FPR16(\thread)
-	swc1	$f17, THREAD_FPR17(\thread)
-	swc1	$f18, THREAD_FPR18(\thread)
-	swc1	$f19, THREAD_FPR19(\thread)
-	swc1	$f20, THREAD_FPR20(\thread)
-	swc1	$f21, THREAD_FPR21(\thread)
-	swc1	$f22, THREAD_FPR22(\thread)
-	swc1	$f23, THREAD_FPR23(\thread)
-	swc1	$f24, THREAD_FPR24(\thread)
-	swc1	$f25, THREAD_FPR25(\thread)
-	swc1	$f26, THREAD_FPR26(\thread)
-	swc1	$f27, THREAD_FPR27(\thread)
-	swc1	$f28, THREAD_FPR28(\thread)
-	swc1	$f29, THREAD_FPR29(\thread)
-	swc1	$f30, THREAD_FPR30(\thread)
-	swc1	$f31, THREAD_FPR31(\thread)
+	swc1	$f0,  THREAD_FPR0_LS64(\thread)
+	swc1	$f1,  THREAD_FPR1_LS64(\thread)
+	swc1	$f2,  THREAD_FPR2_LS64(\thread)
+	swc1	$f3,  THREAD_FPR3_LS64(\thread)
+	swc1	$f4,  THREAD_FPR4_LS64(\thread)
+	swc1	$f5,  THREAD_FPR5_LS64(\thread)
+	swc1	$f6,  THREAD_FPR6_LS64(\thread)
+	swc1	$f7,  THREAD_FPR7_LS64(\thread)
+	swc1	$f8,  THREAD_FPR8_LS64(\thread)
+	swc1	$f9,  THREAD_FPR9_LS64(\thread)
+	swc1	$f10, THREAD_FPR10_LS64(\thread)
+	swc1	$f11, THREAD_FPR11_LS64(\thread)
+	swc1	$f12, THREAD_FPR12_LS64(\thread)
+	swc1	$f13, THREAD_FPR13_LS64(\thread)
+	swc1	$f14, THREAD_FPR14_LS64(\thread)
+	swc1	$f15, THREAD_FPR15_LS64(\thread)
+	swc1	$f16, THREAD_FPR16_LS64(\thread)
+	swc1	$f17, THREAD_FPR17_LS64(\thread)
+	swc1	$f18, THREAD_FPR18_LS64(\thread)
+	swc1	$f19, THREAD_FPR19_LS64(\thread)
+	swc1	$f20, THREAD_FPR20_LS64(\thread)
+	swc1	$f21, THREAD_FPR21_LS64(\thread)
+	swc1	$f22, THREAD_FPR22_LS64(\thread)
+	swc1	$f23, THREAD_FPR23_LS64(\thread)
+	swc1	$f24, THREAD_FPR24_LS64(\thread)
+	swc1	$f25, THREAD_FPR25_LS64(\thread)
+	swc1	$f26, THREAD_FPR26_LS64(\thread)
+	swc1	$f27, THREAD_FPR27_LS64(\thread)
+	swc1	$f28, THREAD_FPR28_LS64(\thread)
+	swc1	$f29, THREAD_FPR29_LS64(\thread)
+	swc1	$f30, THREAD_FPR30_LS64(\thread)
+	swc1	$f31, THREAD_FPR31_LS64(\thread)
 	sw	\tmp, THREAD_FCR31(\thread)
 	.endm
 
 	.macro	fpu_restore_single thread tmp=t0
 	lw	\tmp, THREAD_FCR31(\thread)
-	lwc1	$f0,  THREAD_FPR0(\thread)
-	lwc1	$f1,  THREAD_FPR1(\thread)
-	lwc1	$f2,  THREAD_FPR2(\thread)
-	lwc1	$f3,  THREAD_FPR3(\thread)
-	lwc1	$f4,  THREAD_FPR4(\thread)
-	lwc1	$f5,  THREAD_FPR5(\thread)
-	lwc1	$f6,  THREAD_FPR6(\thread)
-	lwc1	$f7,  THREAD_FPR7(\thread)
-	lwc1	$f8,  THREAD_FPR8(\thread)
-	lwc1	$f9,  THREAD_FPR9(\thread)
-	lwc1	$f10, THREAD_FPR10(\thread)
-	lwc1	$f11, THREAD_FPR11(\thread)
-	lwc1	$f12, THREAD_FPR12(\thread)
-	lwc1	$f13, THREAD_FPR13(\thread)
-	lwc1	$f14, THREAD_FPR14(\thread)
-	lwc1	$f15, THREAD_FPR15(\thread)
-	lwc1	$f16, THREAD_FPR16(\thread)
-	lwc1	$f17, THREAD_FPR17(\thread)
-	lwc1	$f18, THREAD_FPR18(\thread)
-	lwc1	$f19, THREAD_FPR19(\thread)
-	lwc1	$f20, THREAD_FPR20(\thread)
-	lwc1	$f21, THREAD_FPR21(\thread)
-	lwc1	$f22, THREAD_FPR22(\thread)
-	lwc1	$f23, THREAD_FPR23(\thread)
-	lwc1	$f24, THREAD_FPR24(\thread)
-	lwc1	$f25, THREAD_FPR25(\thread)
-	lwc1	$f26, THREAD_FPR26(\thread)
-	lwc1	$f27, THREAD_FPR27(\thread)
-	lwc1	$f28, THREAD_FPR28(\thread)
-	lwc1	$f29, THREAD_FPR29(\thread)
-	lwc1	$f30, THREAD_FPR30(\thread)
-	lwc1	$f31, THREAD_FPR31(\thread)
+	lwc1	$f0,  THREAD_FPR0_LS64(\thread)
+	lwc1	$f1,  THREAD_FPR1_LS64(\thread)
+	lwc1	$f2,  THREAD_FPR2_LS64(\thread)
+	lwc1	$f3,  THREAD_FPR3_LS64(\thread)
+	lwc1	$f4,  THREAD_FPR4_LS64(\thread)
+	lwc1	$f5,  THREAD_FPR5_LS64(\thread)
+	lwc1	$f6,  THREAD_FPR6_LS64(\thread)
+	lwc1	$f7,  THREAD_FPR7_LS64(\thread)
+	lwc1	$f8,  THREAD_FPR8_LS64(\thread)
+	lwc1	$f9,  THREAD_FPR9_LS64(\thread)
+	lwc1	$f10, THREAD_FPR10_LS64(\thread)
+	lwc1	$f11, THREAD_FPR11_LS64(\thread)
+	lwc1	$f12, THREAD_FPR12_LS64(\thread)
+	lwc1	$f13, THREAD_FPR13_LS64(\thread)
+	lwc1	$f14, THREAD_FPR14_LS64(\thread)
+	lwc1	$f15, THREAD_FPR15_LS64(\thread)
+	lwc1	$f16, THREAD_FPR16_LS64(\thread)
+	lwc1	$f17, THREAD_FPR17_LS64(\thread)
+	lwc1	$f18, THREAD_FPR18_LS64(\thread)
+	lwc1	$f19, THREAD_FPR19_LS64(\thread)
+	lwc1	$f20, THREAD_FPR20_LS64(\thread)
+	lwc1	$f21, THREAD_FPR21_LS64(\thread)
+	lwc1	$f22, THREAD_FPR22_LS64(\thread)
+	lwc1	$f23, THREAD_FPR23_LS64(\thread)
+	lwc1	$f24, THREAD_FPR24_LS64(\thread)
+	lwc1	$f25, THREAD_FPR25_LS64(\thread)
+	lwc1	$f26, THREAD_FPR26_LS64(\thread)
+	lwc1	$f27, THREAD_FPR27_LS64(\thread)
+	lwc1	$f28, THREAD_FPR28_LS64(\thread)
+	lwc1	$f29, THREAD_FPR29_LS64(\thread)
+	lwc1	$f30, THREAD_FPR30_LS64(\thread)
+	lwc1	$f31, THREAD_FPR31_LS64(\thread)
 	ctc1	\tmp, fcr31
 	.endm
 
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 3220c93ea981..fe3b03c793e5 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -64,44 +64,44 @@
 
 	.macro	fpu_save_16even thread tmp=t0
 	cfc1	\tmp, fcr31
-	sdc1	$f0,  THREAD_FPR0(\thread)
-	sdc1	$f2,  THREAD_FPR2(\thread)
-	sdc1	$f4,  THREAD_FPR4(\thread)
-	sdc1	$f6,  THREAD_FPR6(\thread)
-	sdc1	$f8,  THREAD_FPR8(\thread)
-	sdc1	$f10, THREAD_FPR10(\thread)
-	sdc1	$f12, THREAD_FPR12(\thread)
-	sdc1	$f14, THREAD_FPR14(\thread)
-	sdc1	$f16, THREAD_FPR16(\thread)
-	sdc1	$f18, THREAD_FPR18(\thread)
-	sdc1	$f20, THREAD_FPR20(\thread)
-	sdc1	$f22, THREAD_FPR22(\thread)
-	sdc1	$f24, THREAD_FPR24(\thread)
-	sdc1	$f26, THREAD_FPR26(\thread)
-	sdc1	$f28, THREAD_FPR28(\thread)
-	sdc1	$f30, THREAD_FPR30(\thread)
+	sdc1	$f0,  THREAD_FPR0_LS64(\thread)
+	sdc1	$f2,  THREAD_FPR2_LS64(\thread)
+	sdc1	$f4,  THREAD_FPR4_LS64(\thread)
+	sdc1	$f6,  THREAD_FPR6_LS64(\thread)
+	sdc1	$f8,  THREAD_FPR8_LS64(\thread)
+	sdc1	$f10, THREAD_FPR10_LS64(\thread)
+	sdc1	$f12, THREAD_FPR12_LS64(\thread)
+	sdc1	$f14, THREAD_FPR14_LS64(\thread)
+	sdc1	$f16, THREAD_FPR16_LS64(\thread)
+	sdc1	$f18, THREAD_FPR18_LS64(\thread)
+	sdc1	$f20, THREAD_FPR20_LS64(\thread)
+	sdc1	$f22, THREAD_FPR22_LS64(\thread)
+	sdc1	$f24, THREAD_FPR24_LS64(\thread)
+	sdc1	$f26, THREAD_FPR26_LS64(\thread)
+	sdc1	$f28, THREAD_FPR28_LS64(\thread)
+	sdc1	$f30, THREAD_FPR30_LS64(\thread)
 	sw	\tmp, THREAD_FCR31(\thread)
 	.endm
 
 	.macro	fpu_save_16odd thread
 	.set	push
 	.set	mips64r2
-	sdc1	$f1,  THREAD_FPR1(\thread)
-	sdc1	$f3,  THREAD_FPR3(\thread)
-	sdc1	$f5,  THREAD_FPR5(\thread)
-	sdc1	$f7,  THREAD_FPR7(\thread)
-	sdc1	$f9,  THREAD_FPR9(\thread)
-	sdc1	$f11, THREAD_FPR11(\thread)
-	sdc1	$f13, THREAD_FPR13(\thread)
-	sdc1	$f15, THREAD_FPR15(\thread)
-	sdc1	$f17, THREAD_FPR17(\thread)
-	sdc1	$f19, THREAD_FPR19(\thread)
-	sdc1	$f21, THREAD_FPR21(\thread)
-	sdc1	$f23, THREAD_FPR23(\thread)
-	sdc1	$f25, THREAD_FPR25(\thread)
-	sdc1	$f27, THREAD_FPR27(\thread)
-	sdc1	$f29, THREAD_FPR29(\thread)
-	sdc1	$f31, THREAD_FPR31(\thread)
+	sdc1	$f1,  THREAD_FPR1_LS64(\thread)
+	sdc1	$f3,  THREAD_FPR3_LS64(\thread)
+	sdc1	$f5,  THREAD_FPR5_LS64(\thread)
+	sdc1	$f7,  THREAD_FPR7_LS64(\thread)
+	sdc1	$f9,  THREAD_FPR9_LS64(\thread)
+	sdc1	$f11, THREAD_FPR11_LS64(\thread)
+	sdc1	$f13, THREAD_FPR13_LS64(\thread)
+	sdc1	$f15, THREAD_FPR15_LS64(\thread)
+	sdc1	$f17, THREAD_FPR17_LS64(\thread)
+	sdc1	$f19, THREAD_FPR19_LS64(\thread)
+	sdc1	$f21, THREAD_FPR21_LS64(\thread)
+	sdc1	$f23, THREAD_FPR23_LS64(\thread)
+	sdc1	$f25, THREAD_FPR25_LS64(\thread)
+	sdc1	$f27, THREAD_FPR27_LS64(\thread)
+	sdc1	$f29, THREAD_FPR29_LS64(\thread)
+	sdc1	$f31, THREAD_FPR31_LS64(\thread)
 	.set	pop
 	.endm
 
@@ -117,44 +117,44 @@
 
 	.macro	fpu_restore_16even thread tmp=t0
 	lw	\tmp, THREAD_FCR31(\thread)
-	ldc1	$f0,  THREAD_FPR0(\thread)
-	ldc1	$f2,  THREAD_FPR2(\thread)
-	ldc1	$f4,  THREAD_FPR4(\thread)
-	ldc1	$f6,  THREAD_FPR6(\thread)
-	ldc1	$f8,  THREAD_FPR8(\thread)
-	ldc1	$f10, THREAD_FPR10(\thread)
-	ldc1	$f12, THREAD_FPR12(\thread)
-	ldc1	$f14, THREAD_FPR14(\thread)
-	ldc1	$f16, THREAD_FPR16(\thread)
-	ldc1	$f18, THREAD_FPR18(\thread)
-	ldc1	$f20, THREAD_FPR20(\thread)
-	ldc1	$f22, THREAD_FPR22(\thread)
-	ldc1	$f24, THREAD_FPR24(\thread)
-	ldc1	$f26, THREAD_FPR26(\thread)
-	ldc1	$f28, THREAD_FPR28(\thread)
-	ldc1	$f30, THREAD_FPR30(\thread)
+	ldc1	$f0,  THREAD_FPR0_LS64(\thread)
+	ldc1	$f2,  THREAD_FPR2_LS64(\thread)
+	ldc1	$f4,  THREAD_FPR4_LS64(\thread)
+	ldc1	$f6,  THREAD_FPR6_LS64(\thread)
+	ldc1	$f8,  THREAD_FPR8_LS64(\thread)
+	ldc1	$f10, THREAD_FPR10_LS64(\thread)
+	ldc1	$f12, THREAD_FPR12_LS64(\thread)
+	ldc1	$f14, THREAD_FPR14_LS64(\thread)
+	ldc1	$f16, THREAD_FPR16_LS64(\thread)
+	ldc1	$f18, THREAD_FPR18_LS64(\thread)
+	ldc1	$f20, THREAD_FPR20_LS64(\thread)
+	ldc1	$f22, THREAD_FPR22_LS64(\thread)
+	ldc1	$f24, THREAD_FPR24_LS64(\thread)
+	ldc1	$f26, THREAD_FPR26_LS64(\thread)
+	ldc1	$f28, THREAD_FPR28_LS64(\thread)
+	ldc1	$f30, THREAD_FPR30_LS64(\thread)
 	ctc1	\tmp, fcr31
 	.endm
 
 	.macro	fpu_restore_16odd thread
 	.set	push
 	.set	mips64r2
-	ldc1	$f1,  THREAD_FPR1(\thread)
-	ldc1	$f3,  THREAD_FPR3(\thread)
-	ldc1	$f5,  THREAD_FPR5(\thread)
-	ldc1	$f7,  THREAD_FPR7(\thread)
-	ldc1	$f9,  THREAD_FPR9(\thread)
-	ldc1	$f11, THREAD_FPR11(\thread)
-	ldc1	$f13, THREAD_FPR13(\thread)
-	ldc1	$f15, THREAD_FPR15(\thread)
-	ldc1	$f17, THREAD_FPR17(\thread)
-	ldc1	$f19, THREAD_FPR19(\thread)
-	ldc1	$f21, THREAD_FPR21(\thread)
-	ldc1	$f23, THREAD_FPR23(\thread)
-	ldc1	$f25, THREAD_FPR25(\thread)
-	ldc1	$f27, THREAD_FPR27(\thread)
-	ldc1	$f29, THREAD_FPR29(\thread)
-	ldc1	$f31, THREAD_FPR31(\thread)
+	ldc1	$f1,  THREAD_FPR1_LS64(\thread)
+	ldc1	$f3,  THREAD_FPR3_LS64(\thread)
+	ldc1	$f5,  THREAD_FPR5_LS64(\thread)
+	ldc1	$f7,  THREAD_FPR7_LS64(\thread)
+	ldc1	$f9,  THREAD_FPR9_LS64(\thread)
+	ldc1	$f11, THREAD_FPR11_LS64(\thread)
+	ldc1	$f13, THREAD_FPR13_LS64(\thread)
+	ldc1	$f15, THREAD_FPR15_LS64(\thread)
+	ldc1	$f17, THREAD_FPR17_LS64(\thread)
+	ldc1	$f19, THREAD_FPR19_LS64(\thread)
+	ldc1	$f21, THREAD_FPR21_LS64(\thread)
+	ldc1	$f23, THREAD_FPR23_LS64(\thread)
+	ldc1	$f25, THREAD_FPR25_LS64(\thread)
+	ldc1	$f27, THREAD_FPR27_LS64(\thread)
+	ldc1	$f29, THREAD_FPR29_LS64(\thread)
+	ldc1	$f31, THREAD_FPR31_LS64(\thread)
 	.set	pop
 	.endm
 
@@ -169,6 +169,17 @@
 	fpu_restore_16even \thread \tmp
 	.endm
 
+#ifdef CONFIG_CPU_MIPSR2
+	.macro	_EXT	rd, rs, p, s
+	ext	\rd, \rs, \p, \s
+	.endm
+#else /* !CONFIG_CPU_MIPSR2 */
+	.macro	_EXT	rd, rs, p, s
+	srl	\rd, \rs, \p
+	andi	\rd, \rd, (1 << \s) - 1
+	.endm
+#endif /* !CONFIG_CPU_MIPSR2 */
+
 /*
  * Temporary until all gas have MT ASE support
  */
@@ -196,4 +207,195 @@
 	 .word	0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel)
 	.endm
 
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+	.macro	ld_d	wd, off, base
+	.set	push
+	.set	mips32r2
+	.set	msa
+	ld.d	$w\wd, \off(\base)
+	.set	pop
+	.endm
+
+	.macro	st_d	wd, off, base
+	.set	push
+	.set	mips32r2
+	.set	msa
+	st.d	$w\wd, \off(\base)
+	.set	pop
+	.endm
+
+	.macro	copy_u_w	rd, ws, n
+	.set	push
+	.set	mips32r2
+	.set	msa
+	copy_u.w \rd, $w\ws[\n]
+	.set	pop
+	.endm
+
+	.macro	copy_u_d	rd, ws, n
+	.set	push
+	.set	mips64r2
+	.set	msa
+	copy_u.d \rd, $w\ws[\n]
+	.set	pop
+	.endm
+
+	.macro	insert_w	wd, n, rs
+	.set	push
+	.set	mips32r2
+	.set	msa
+	insert.w $w\wd[\n], \rs
+	.set	pop
+	.endm
+
+	.macro	insert_d	wd, n, rs
+	.set	push
+	.set	mips64r2
+	.set	msa
+	insert.d $w\wd[\n], \rs
+	.set	pop
+	.endm
+#else
+	/*
+	 * Temporary until all toolchains in use include MSA support.
+	 */
+	.macro	cfcmsa	rd, cs
+	.set	push
+	.set	noat
+	.word	0x787e0059 | (\cs << 11)
+	move	\rd, $1
+	.set	pop
+	.endm
+
+	.macro	ctcmsa	cd, rs
+	.set	push
+	.set	noat
+	move	$1, \rs
+	.word	0x783e0819 | (\cd << 6)
+	.set	pop
+	.endm
+
+	.macro	ld_d	wd, off, base
+	.set	push
+	.set	noat
+	add	$1, \base, \off
+	.word	0x78000823 | (\wd << 6)
+	.set	pop
+	.endm
+
+	.macro	st_d	wd, off, base
+	.set	push
+	.set	noat
+	add	$1, \base, \off
+	.word	0x78000827 | (\wd << 6)
+	.set	pop
+	.endm
+
+	.macro	copy_u_w	rd, ws, n
+	.set	push
+	.set	noat
+	.word	0x78f00059 | (\n << 16) | (\ws << 11)
+	/* move triggers an assembler bug... */
+	or	\rd, $1, zero
+	.set	pop
+	.endm
+
+	.macro	copy_u_d	rd, ws, n
+	.set	push
+	.set	noat
+	.word	0x78f80059 | (\n << 16) | (\ws << 11)
+	/* move triggers an assembler bug... */
+	or	\rd, $1, zero
+	.set	pop
+	.endm
+
+	.macro	insert_w	wd, n, rs
+	.set	push
+	.set	noat
+	/* move triggers an assembler bug... */
+	or	$1, \rs, zero
+	.word	0x79300819 | (\n << 16) | (\wd << 6)
+	.set	pop
+	.endm
+
+	.macro	insert_d	wd, n, rs
+	.set	push
+	.set	noat
+	/* move triggers an assembler bug... */
+	or	$1, \rs, zero
+	.word	0x79380819 | (\n << 16) | (\wd << 6)
+	.set	pop
+	.endm
+#endif
+
+	.macro	msa_save_all	thread
+	st_d	0, THREAD_FPR0, \thread
+	st_d	1, THREAD_FPR1, \thread
+	st_d	2, THREAD_FPR2, \thread
+	st_d	3, THREAD_FPR3, \thread
+	st_d	4, THREAD_FPR4, \thread
+	st_d	5, THREAD_FPR5, \thread
+	st_d	6, THREAD_FPR6, \thread
+	st_d	7, THREAD_FPR7, \thread
+	st_d	8, THREAD_FPR8, \thread
+	st_d	9, THREAD_FPR9, \thread
+	st_d	10, THREAD_FPR10, \thread
+	st_d	11, THREAD_FPR11, \thread
+	st_d	12, THREAD_FPR12, \thread
+	st_d	13, THREAD_FPR13, \thread
+	st_d	14, THREAD_FPR14, \thread
+	st_d	15, THREAD_FPR15, \thread
+	st_d	16, THREAD_FPR16, \thread
+	st_d	17, THREAD_FPR17, \thread
+	st_d	18, THREAD_FPR18, \thread
+	st_d	19, THREAD_FPR19, \thread
+	st_d	20, THREAD_FPR20, \thread
+	st_d	21, THREAD_FPR21, \thread
+	st_d	22, THREAD_FPR22, \thread
+	st_d	23, THREAD_FPR23, \thread
+	st_d	24, THREAD_FPR24, \thread
+	st_d	25, THREAD_FPR25, \thread
+	st_d	26, THREAD_FPR26, \thread
+	st_d	27, THREAD_FPR27, \thread
+	st_d	28, THREAD_FPR28, \thread
+	st_d	29, THREAD_FPR29, \thread
+	st_d	30, THREAD_FPR30, \thread
+	st_d	31, THREAD_FPR31, \thread
+	.endm
+
+	.macro	msa_restore_all	thread
+	ld_d	0, THREAD_FPR0, \thread
+	ld_d	1, THREAD_FPR1, \thread
+	ld_d	2, THREAD_FPR2, \thread
+	ld_d	3, THREAD_FPR3, \thread
+	ld_d	4, THREAD_FPR4, \thread
+	ld_d	5, THREAD_FPR5, \thread
+	ld_d	6, THREAD_FPR6, \thread
+	ld_d	7, THREAD_FPR7, \thread
+	ld_d	8, THREAD_FPR8, \thread
+	ld_d	9, THREAD_FPR9, \thread
+	ld_d	10, THREAD_FPR10, \thread
+	ld_d	11, THREAD_FPR11, \thread
+	ld_d	12, THREAD_FPR12, \thread
+	ld_d	13, THREAD_FPR13, \thread
+	ld_d	14, THREAD_FPR14, \thread
+	ld_d	15, THREAD_FPR15, \thread
+	ld_d	16, THREAD_FPR16, \thread
+	ld_d	17, THREAD_FPR17, \thread
+	ld_d	18, THREAD_FPR18, \thread
+	ld_d	19, THREAD_FPR19, \thread
+	ld_d	20, THREAD_FPR20, \thread
+	ld_d	21, THREAD_FPR21, \thread
+	ld_d	22, THREAD_FPR22, \thread
+	ld_d	23, THREAD_FPR23, \thread
+	ld_d	24, THREAD_FPR24, \thread
+	ld_d	25, THREAD_FPR25, \thread
+	ld_d	26, THREAD_FPR26, \thread
+	ld_d	27, THREAD_FPR27, \thread
+	ld_d	28, THREAD_FPR28, \thread
+	ld_d	29, THREAD_FPR29, \thread
+	ld_d	30, THREAD_FPR30, \thread
+	ld_d	31, THREAD_FPR31, \thread
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 4d2cdea5aa37..83a4db4e3794 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -112,6 +112,8 @@ extern void prom_free_prom_memory(void);
 extern void free_init_pages(const char *what,
 			    unsigned long begin, unsigned long end);
 
+extern void (*free_init_pages_eva)(void *begin, void *end);
+
 /*
  * Initial kernel command line, usually setup by prom_init()
  */
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index ac3d2b8a20d4..3418c51e1151 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -7,6 +7,7 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2001 Thiemo Seufer.
  * Copyright (C) 2002 Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  */
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
@@ -29,9 +30,13 @@
  */
 __wsum csum_partial(const void *buff, int len, __wsum sum);
 
-__wsum __csum_partial_copy_user(const void *src, void *dst,
-				int len, __wsum sum, int *err_ptr);
+__wsum __csum_partial_copy_kernel(const void *src, void *dst,
+				  int len, __wsum sum, int *err_ptr);
 
+__wsum __csum_partial_copy_from_user(const void *src, void *dst,
+				     int len, __wsum sum, int *err_ptr);
+__wsum __csum_partial_copy_to_user(const void *src, void *dst,
+				   int len, __wsum sum, int *err_ptr);
 /*
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
@@ -41,8 +46,26 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
 				   __wsum sum, int *err_ptr)
 {
 	might_fault();
-	return __csum_partial_copy_user((__force void *)src, dst,
-					len, sum, err_ptr);
+	if (segment_eq(get_fs(), get_ds()))
+		return __csum_partial_copy_kernel((__force void *)src, dst,
+						  len, sum, err_ptr);
+	else
+		return __csum_partial_copy_from_user((__force void *)src, dst,
+						     len, sum, err_ptr);
+}
+
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+static inline
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+			       int len, __wsum sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_READ, src, len))
+		return csum_partial_copy_from_user(src, dst, len, sum,
+						   err_ptr);
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return sum;
 }
 
 /*
@@ -54,9 +77,16 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
 			     __wsum sum, int *err_ptr)
 {
 	might_fault();
-	if (access_ok(VERIFY_WRITE, dst, len))
-		return __csum_partial_copy_user(src, (__force void *)dst,
-						len, sum, err_ptr);
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (segment_eq(get_fs(), get_ds()))
+			return __csum_partial_copy_kernel(src,
+							  (__force void *)dst,
+							  len, sum, err_ptr);
+		else
+			return __csum_partial_copy_to_user(src,
+							   (__force void *)dst,
+							   len, sum, err_ptr);
+	}
 	if (len)
 		*err_ptr = -EFAULT;
 
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 6e70b03b6aab..f56cc975b92f 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -26,7 +26,9 @@
 #ifndef cpu_has_segments
 #define cpu_has_segments	(cpu_data[0].options & MIPS_CPU_SEGMENTS)
 #endif
-
+#ifndef cpu_has_eva
+#define cpu_has_eva		(cpu_data[0].options & MIPS_CPU_EVA)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
@@ -299,4 +301,10 @@
 #define cpu_has_vz		(cpu_data[0].ases & MIPS_ASE_VZ)
 #endif
 
+#if defined(CONFIG_CPU_HAS_MSA) && !defined(cpu_has_msa)
+# define cpu_has_msa		(cpu_data[0].ases & MIPS_ASE_MSA)
+#elif !defined(cpu_has_msa)
+# define cpu_has_msa		0
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index 8f7adf0ac1e3..359cea10c81e 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -49,6 +49,7 @@ struct cpuinfo_mips {
 	unsigned long		ases;
 	unsigned int		processor_id;
 	unsigned int		fpu_id;
+	unsigned int		msa_id;
 	unsigned int		cputype;
 	int			isa_level;
 	int			tlbsize;
diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index 02f591bd95ca..61f803be4c2e 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -46,6 +46,7 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_M14KEC:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 #endif
 
 #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 76411df3d971..c12d99780204 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -115,6 +115,7 @@
 #define PRID_IMP_INTERAPTIV_MP	0xa100
 #define PRID_IMP_PROAPTIV_UP	0xa200
 #define PRID_IMP_PROAPTIV_MP	0xa300
+#define PRID_IMP_P5600		0xa800
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -296,7 +297,7 @@ enum cpu_type_enum {
 	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
 	CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
 	CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
-	CPU_M14KEC, CPU_INTERAPTIV, CPU_PROAPTIV,
+	CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K,
 
 	/*
 	 * MIPS64 class processors
@@ -358,6 +359,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_MICROMIPS	0x01000000 /* CPU has microMIPS capability */
 #define MIPS_CPU_TLBINV		0x02000000 /* CPU supports TLBINV/F */
 #define MIPS_CPU_SEGMENTS	0x04000000 /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA		0x80000000 /* CPU supports Enhanced Virtual Addressing */
 
 /*
  * CPU ASE encodings
@@ -370,5 +372,6 @@ enum cpu_type_enum {
 #define MIPS_ASE_MIPSMT		0x00000020 /* CPU supports MIPS MT */
 #define MIPS_ASE_DSP2P		0x00000040 /* Signal Processing ASE Rev 2 */
 #define MIPS_ASE_VZ		0x00000080 /* Virtualization ASE */
+#define MIPS_ASE_MSA		0x00000100 /* MIPS SIMD Architecture */
 
 #endif /* _ASM_CPU_H */
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 6b9749540edf..8a3d61f0017f 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -180,7 +180,7 @@ static inline void restore_fp(struct task_struct *tsk)
 		_restore_fp(tsk);
 }
 
-static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
+static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
 {
 	if (tsk == current) {
 		preempt_disable();
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 6ea15815d3ee..1fe2cd6cdca0 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -12,6 +12,7 @@
 
 #include <linux/futex.h>
 #include <linux/uaccess.h>
+#include <asm/asm-eva.h>
 #include <asm/barrier.h>
 #include <asm/errno.h>
 #include <asm/war.h>
@@ -49,11 +50,11 @@
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	mips3				\n"	\
-		"1:	ll	%1, %4	# __futex_atomic_op	\n"	\
+		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
 		"	.set	mips3				\n"	\
-		"2:	sc	$1, %2				\n"	\
+		"2:	"user_sc("$1", "%2")"			\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
@@ -174,12 +175,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%1, %3					\n"
+		"1:	"user_ll("%1", "%3")"				\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %2					\n"
+		"2:	"user_sc("$1", "%2")"				\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
diff --git a/arch/mips/include/asm/fw/fw.h b/arch/mips/include/asm/fw/fw.h
index d6c50a7e9ede..f3e6978aad70 100644
--- a/arch/mips/include/asm/fw/fw.h
+++ b/arch/mips/include/asm/fw/fw.h
@@ -38,7 +38,7 @@ extern int *_fw_envp;
 
 extern void fw_init_cmdline(void);
 extern char *fw_getcmdline(void);
-extern fw_memblock_t *fw_getmdesc(void);
+extern fw_memblock_t *fw_getmdesc(int);
 extern void fw_meminit(void);
 extern char *fw_getenv(char *name);
 extern unsigned long fw_getenvl(char *name);
diff --git a/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h
deleted file mode 100644
index a7359f77a48e..000000000000
--- a/arch/mips/include/asm/gcmpregs.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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) 2000, 07 MIPS Technologies, Inc.
- *
- * Multiprocessor Subsystem Register Definitions
- *
- */
-#ifndef _ASM_GCMPREGS_H
-#define _ASM_GCMPREGS_H
-
-
-/* Offsets to major blocks within GCMP from GCMP base */
-#define GCMP_GCB_OFS		0x0000 /* Global Control Block */
-#define GCMP_CLCB_OFS		0x2000 /* Core Local Control Block */
-#define GCMP_COCB_OFS		0x4000 /* Core Other Control Block */
-#define GCMP_GDB_OFS		0x8000 /* Global Debug Block */
-
-/* Offsets to individual GCMP registers from GCMP base */
-#define GCMPOFS(block, tag, reg)	\
-	(GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
-#define GCMPOFSn(block, tag, reg, n) \
-	(GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS(n))
-
-#define GCMPGCBOFS(reg)		GCMPOFS(GCB, GCB, reg)
-#define GCMPGCBOFSn(reg, n)	GCMPOFSn(GCB, GCB, reg, n)
-#define GCMPCLCBOFS(reg)	GCMPOFS(CLCB, CCB, reg)
-#define GCMPCOCBOFS(reg)	GCMPOFS(COCB, CCB, reg)
-#define GCMPGDBOFS(reg)		GCMPOFS(GDB, GDB, reg)
-
-/* GCMP register access */
-#define GCMPGCB(reg)			REGP(_gcmp_base, GCMPGCBOFS(reg))
-#define GCMPGCBn(reg, n)	       REGP(_gcmp_base, GCMPGCBOFSn(reg, n))
-#define GCMPCLCB(reg)			REGP(_gcmp_base, GCMPCLCBOFS(reg))
-#define GCMPCOCB(reg)			REGP(_gcmp_base, GCMPCOCBOFS(reg))
-#define GCMPGDB(reg)			REGP(_gcmp_base, GCMPGDBOFS(reg))
-
-/* Mask generation */
-#define GCMPMSK(block, reg, bits)	(MSK(bits)<<GCMP_##block##_##reg##_SHF)
-#define GCMPGCBMSK(reg, bits)		GCMPMSK(GCB, reg, bits)
-#define GCMPCCBMSK(reg, bits)		GCMPMSK(CCB, reg, bits)
-#define GCMPGDBMSK(reg, bits)		GCMPMSK(GDB, reg, bits)
-
-/* GCB registers */
-#define GCMP_GCB_GC_OFS			0x0000	/* Global Config Register */
-#define	 GCMP_GCB_GC_NUMIOCU_SHF	8
-#define	 GCMP_GCB_GC_NUMIOCU_MSK	GCMPGCBMSK(GC_NUMIOCU, 4)
-#define	 GCMP_GCB_GC_NUMCORES_SHF	0
-#define	 GCMP_GCB_GC_NUMCORES_MSK	GCMPGCBMSK(GC_NUMCORES, 8)
-#define GCMP_GCB_GCMPB_OFS		0x0008		/* Global GCMP Base */
-#define	 GCMP_GCB_GCMPB_GCMPBASE_SHF	15
-#define	 GCMP_GCB_GCMPB_GCMPBASE_MSK	GCMPGCBMSK(GCMPB_GCMPBASE, 17)
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_SHF	0
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_MSK	GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_DISABLED	0
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_MEM		1
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_IOCU1		2
-#define	 GCMP_GCB_GCMPB_CMDEFTGT_IOCU2		3
-#define GCMP_GCB_CCMC_OFS		0x0010	/* Global CM Control */
-#define GCMP_GCB_GCSRAP_OFS		0x0020	/* Global CSR Access Privilege */
-#define	 GCMP_GCB_GCSRAP_CMACCESS_SHF	0
-#define	 GCMP_GCB_GCSRAP_CMACCESS_MSK	GCMPGCBMSK(GCSRAP_CMACCESS, 8)
-#define GCMP_GCB_GCMPREV_OFS		0x0030	/* GCMP Revision Register */
-#define GCMP_GCB_GCMEM_OFS		0x0040	/* Global CM Error Mask */
-#define GCMP_GCB_GCMEC_OFS		0x0048	/* Global CM Error Cause */
-#define	 GCMP_GCB_GMEC_ERROR_TYPE_SHF	27
-#define	 GCMP_GCB_GMEC_ERROR_TYPE_MSK	GCMPGCBMSK(GMEC_ERROR_TYPE, 5)
-#define	 GCMP_GCB_GMEC_ERROR_INFO_SHF	0
-#define	 GCMP_GCB_GMEC_ERROR_INFO_MSK	GCMPGCBMSK(GMEC_ERROR_INFO, 27)
-#define GCMP_GCB_GCMEA_OFS		0x0050	/* Global CM Error Address */
-#define GCMP_GCB_GCMEO_OFS		0x0058	/* Global CM Error Multiple */
-#define	 GCMP_GCB_GMEO_ERROR_2ND_SHF	0
-#define	 GCMP_GCB_GMEO_ERROR_2ND_MSK	GCMPGCBMSK(GMEO_ERROR_2ND, 5)
-#define GCMP_GCB_GICBA_OFS		0x0080	/* Global Interrupt Controller Base Address */
-#define	 GCMP_GCB_GICBA_BASE_SHF	17
-#define	 GCMP_GCB_GICBA_BASE_MSK	GCMPGCBMSK(GICBA_BASE, 15)
-#define	 GCMP_GCB_GICBA_EN_SHF		0
-#define	 GCMP_GCB_GICBA_EN_MSK		GCMPGCBMSK(GICBA_EN, 1)
-
-/* GCB Regions */
-#define GCMP_GCB_CMxBASE_OFS(n)		(0x0090+16*(n))		/* Global Region[0-3] Base Address */
-#define	 GCMP_GCB_CMxBASE_BASE_SHF	16
-#define	 GCMP_GCB_CMxBASE_BASE_MSK	GCMPGCBMSK(CMxBASE_BASE, 16)
-#define GCMP_GCB_CMxMASK_OFS(n)		(0x0098+16*(n))		/* Global Region[0-3] Address Mask */
-#define	 GCMP_GCB_CMxMASK_MASK_SHF	16
-#define	 GCMP_GCB_CMxMASK_MASK_MSK	GCMPGCBMSK(CMxMASK_MASK, 16)
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_SHF	0
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_MSK	GCMPGCBMSK(CMxMASK_CMREGTGT, 2)
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_MEM	 0
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_MEM1	 1
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_IOCU1 2
-#define	 GCMP_GCB_CMxMASK_CMREGTGT_IOCU2 3
-
-
-/* Core local/Core other control block registers */
-#define GCMP_CCB_RESETR_OFS		0x0000			/* Reset Release */
-#define	 GCMP_CCB_RESETR_INRESET_SHF	0
-#define	 GCMP_CCB_RESETR_INRESET_MSK	GCMPCCBMSK(RESETR_INRESET, 16)
-#define GCMP_CCB_COHCTL_OFS		0x0008			/* Coherence Control */
-#define	 GCMP_CCB_COHCTL_DOMAIN_SHF	0
-#define	 GCMP_CCB_COHCTL_DOMAIN_MSK	GCMPCCBMSK(COHCTL_DOMAIN, 8)
-#define GCMP_CCB_CFG_OFS		0x0010			/* Config */
-#define	 GCMP_CCB_CFG_IOCUTYPE_SHF	10
-#define	 GCMP_CCB_CFG_IOCUTYPE_MSK	GCMPCCBMSK(CFG_IOCUTYPE, 2)
-#define	  GCMP_CCB_CFG_IOCUTYPE_CPU	0
-#define	  GCMP_CCB_CFG_IOCUTYPE_NCIOCU	1
-#define	  GCMP_CCB_CFG_IOCUTYPE_CIOCU	2
-#define	 GCMP_CCB_CFG_NUMVPE_SHF	0
-#define	 GCMP_CCB_CFG_NUMVPE_MSK	GCMPCCBMSK(CFG_NUMVPE, 10)
-#define GCMP_CCB_OTHER_OFS		0x0018		/* Other Address */
-#define	 GCMP_CCB_OTHER_CORENUM_SHF	16
-#define	 GCMP_CCB_OTHER_CORENUM_MSK	GCMPCCBMSK(OTHER_CORENUM, 16)
-#define GCMP_CCB_RESETBASE_OFS		0x0020		/* Reset Exception Base */
-#define	 GCMP_CCB_RESETBASE_BEV_SHF	12
-#define	 GCMP_CCB_RESETBASE_BEV_MSK	GCMPCCBMSK(RESETBASE_BEV, 20)
-#define GCMP_CCB_ID_OFS			0x0028		/* Identification */
-#define GCMP_CCB_DINTGROUP_OFS		0x0030		/* DINT Group Participate */
-#define GCMP_CCB_DBGGROUP_OFS		0x0100		/* DebugBreak Group */
-
-extern int __init gcmp_probe(unsigned long, unsigned long);
-extern int __init gcmp_niocu(void);
-extern void __init gcmp_setregion(int, unsigned long, unsigned long, int);
-#endif /* _ASM_GCMPREGS_H */
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index b2e3e93dd7d8..082716690589 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -11,6 +11,9 @@
 #ifndef _ASM_GICREGS_H
 #define _ASM_GICREGS_H
 
+#include <linux/bitmap.h>
+#include <linux/threads.h>
+
 #undef	GICISBYTELITTLEENDIAN
 
 /* Constants */
diff --git a/arch/mips/include/asm/idle.h b/arch/mips/include/asm/idle.h
index d192158886b1..d9f932de80e9 100644
--- a/arch/mips/include/asm/idle.h
+++ b/arch/mips/include/asm/idle.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_IDLE_H
 #define __ASM_IDLE_H
 
+#include <linux/cpuidle.h>
 #include <linux/linkage.h>
 
 extern void (*cpu_wait)(void);
@@ -20,4 +21,17 @@ static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
 	       addr < (unsigned long)__pastwait;
 }
 
+extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
+				   struct cpuidle_driver *drv, int index);
+
+#define MIPS_CPUIDLE_WAIT_STATE {\
+	.enter			= mips_cpuidle_wait_enter,\
+	.exit_latency		= 1,\
+	.target_residency	= 1,\
+	.power_usage		= UINT_MAX,\
+	.flags			= CPUIDLE_FLAG_TIME_VALID,\
+	.name			= "wait",\
+	.desc			= "MIPS wait",\
+}
+
 #endif /* __ASM_IDLE_H  */
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 3321dd5a8872..e221d1de32f3 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -584,7 +584,7 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int
  *
  * This API used to be exported; it now is for arch code internal use only.
  */
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
 
 extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
 extern void (*_dma_cache_wback)(unsigned long start, unsigned long size);
@@ -603,7 +603,7 @@ extern void (*_dma_cache_inv)(unsigned long start, unsigned long size);
 #define dma_cache_inv(start,size)	\
 	do { (void) (start); (void) (size); } while (0)
 
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
 
 /*
  * Read a 32-bit register that requires a 64-bit read cycle on the bus.
diff --git a/arch/mips/include/asm/mach-malta/kernel-entry-init.h b/arch/mips/include/asm/mach-malta/kernel-entry-init.h
index 0b793e7bf67e..7c5e17a17849 100644
--- a/arch/mips/include/asm/mach-malta/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-malta/kernel-entry-init.h
@@ -5,10 +5,80 @@
  *
  * Chris Dearman (chris@mips.com)
  * Copyright (C) 2007 Mips Technologies, Inc.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  */
 #ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
 #define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
 
+	/*
+	 * Prepare segments for EVA boot:
+	 *
+	 * This is in case the processor boots in legacy configuration
+	 * (SI_EVAReset is de-asserted and CONFIG5.K == 0)
+	 *
+	 * On entry, t1 is loaded with CP0_CONFIG
+	 *
+	 * ========================= Mappings =============================
+	 * Virtual memory           Physical memory           Mapping
+	 * 0x00000000 - 0x7fffffff  0x80000000 - 0xfffffffff   MUSUK (kuseg)
+	 *                          Flat 2GB physical memory
+	 *
+	 * 0x80000000 - 0x9fffffff  0x00000000 - 0x1ffffffff   MUSUK (kseg0)
+	 * 0xa0000000 - 0xbf000000  0x00000000 - 0x1ffffffff   MUSUK (kseg1)
+	 * 0xc0000000 - 0xdfffffff             -                 MK  (kseg2)
+	 * 0xe0000000 - 0xffffffff             -                 MK  (kseg3)
+	 *
+	 *
+	 * Lowmem is expanded to 2GB
+	 */
+	.macro	eva_entry
+	/*
+	 * Get Config.K0 value and use it to program
+	 * the segmentation registers
+	 */
+	andi	t1, 0x7 /* CCA */
+	move	t2, t1
+	ins	t2, t1, 16, 3
+	/* SegCtl0 */
+	li      t0, ((MIPS_SEGCFG_MK << MIPS_SEGCFG_AM_SHIFT) |		\
+		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |				\
+		(((MIPS_SEGCFG_MK << MIPS_SEGCFG_AM_SHIFT) |		\
+		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	or	t0, t2
+	mtc0	t0, $5, 2
+
+	/* SegCtl1 */
+	li      t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |	\
+		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(2 << MIPS_SEGCFG_C_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |				\
+		(((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |		\
+		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	ins	t0, t1, 16, 3
+	mtc0	t0, $5, 3
+
+	/* SegCtl2 */
+	li	t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |	\
+		(6 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |				\
+		(((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |		\
+		(4 << MIPS_SEGCFG_PA_SHIFT) |				\
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	or	t0, t2
+	mtc0	t0, $5, 4
+
+	jal	mips_ihb
+	mfc0    t0, $16, 5
+	li      t2, 0x40000000      /* K bit */
+	or      t0, t0, t2
+	mtc0    t0, $16, 5
+	sync
+	jal	mips_ihb
+	.endm
+
 	.macro	kernel_entry_setup
 #ifdef CONFIG_MIPS_MT_SMTC
 	mfc0	t0, CP0_CONFIG
@@ -39,14 +109,57 @@
 nonmt_processor:
 	.asciz	"SMTC kernel requires the MT ASE to run\n"
 	__FINIT
-0:
 #endif
+
+#ifdef CONFIG_EVA
+	sync
+	ehb
+
+	mfc0    t1, CP0_CONFIG
+	bgez    t1, 9f
+	mfc0	t0, CP0_CONFIG, 1
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 2
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 3
+	sll     t0, t0, 6   /* SC bit */
+	bgez    t0, 9f
+
+	eva_entry
+	b       0f
+9:
+	/* Assume we came from YAMON... */
+	PTR_LA	v0, 0x9fc00534	/* YAMON print */
+	lw	v0, (v0)
+	move	a0, zero
+	PTR_LA  a1, nonsc_processor
+	jal	v0
+
+	PTR_LA	v0, 0x9fc00520	/* YAMON exit */
+	lw	v0, (v0)
+	li	a0, 1
+	jal	v0
+
+1:	b	1b
+	nop
+	__INITDATA
+nonsc_processor:
+	.asciz  "EVA kernel requires a MIPS core with Segment Control implemented\n"
+	__FINIT
+#endif /* CONFIG_EVA */
+0:
 	.endm
 
 /*
  * Do SMP slave processor setup necessary before we can safely execute C code.
  */
 	.macro	smp_slave_setup
+#ifdef CONFIG_EVA
+	sync
+	ehb
+	mfc0    t1, CP0_CONFIG
+	eva_entry
+#endif
 	.endm
 
 #endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/arch/mips/include/asm/mach-malta/spaces.h b/arch/mips/include/asm/mach-malta/spaces.h
new file mode 100644
index 000000000000..d7e54971ec66
--- /dev/null
+++ b/arch/mips/include/asm/mach-malta/spaces.h
@@ -0,0 +1,46 @@
+/*
+ * 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 Imagination Technologies Ltd.
+ */
+
+#ifndef _ASM_MALTA_SPACES_H
+#define _ASM_MALTA_SPACES_H
+
+#ifdef CONFIG_EVA
+
+/*
+ * Traditional Malta Board Memory Map for EVA
+ *
+ * 0x00000000 - 0x0fffffff: 1st RAM region, 256MB
+ * 0x10000000 - 0x1bffffff: GIC and CPC Control Registers
+ * 0x1c000000 - 0x1fffffff: I/O And Flash
+ * 0x20000000 - 0x7fffffff: 2nd RAM region, 1.5GB
+ * 0x80000000 - 0xffffffff: Physical memory aliases to 0x0 (2GB)
+ *
+ * The kernel is still located in 0x80000000(kseg0). However,
+ * the physical mask has been shifted to 0x80000000 which exploits the alias
+ * on the Malta board. As a result of which, we override the __pa_symbol
+ * to peform direct mapping from virtual to physical addresses. In other
+ * words, the 0x80000000 virtual address maps to 0x80000000 physical address
+ * which in turn aliases to 0x0. We do this in order to be able to use a flat
+ * 2GB of memory (0x80000000 - 0xffffffff) so we can avoid the I/O hole in
+ * 0x10000000 - 0x1fffffff.
+ * The last 64KB of physical memory are reserved for correct HIGHMEM
+ * macros arithmetics.
+ *
+ */
+
+#define PAGE_OFFSET	_AC(0x0, UL)
+#define PHYS_OFFSET	_AC(0x80000000, UL)
+#define HIGHMEM_START	_AC(0xffff0000, UL)
+
+#define __pa_symbol(x)	(RELOC_HIDE((unsigned long)(x), 0))
+
+#endif /* CONFIG_EVA */
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* _ASM_MALTA_SPACES_H */
diff --git a/arch/mips/include/asm/mips-boards/malta.h b/arch/mips/include/asm/mips-boards/malta.h
index 722bc889eab5..fd9774269a5e 100644
--- a/arch/mips/include/asm/mips-boards/malta.h
+++ b/arch/mips/include/asm/mips-boards/malta.h
@@ -64,6 +64,11 @@ static inline unsigned long get_msc_port_base(unsigned long reg)
 #define GIC_ADDRSPACE_SZ		(128 * 1024)
 
 /*
+ * CPC Specific definitions
+ */
+#define CPC_BASE_ADDR			0x1bde0000
+
+/*
  * MSC01 BIU Specific definitions
  * FIXME : These should be elsewhere ?
  */
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
new file mode 100644
index 000000000000..12cae5e294c4
--- /dev/null
+++ b/arch/mips/include/asm/mips-cm.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 __MIPS_ASM_MIPS_CM_H__
+#define __MIPS_ASM_MIPS_CM_H__
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+/* The base address of the CM GCR block */
+extern void __iomem *mips_cm_base;
+
+/* The base address of the CM L2-only sync region */
+extern void __iomem *mips_cm_l2sync_base;
+
+/**
+ * __mips_cm_phys_base - retrieve the physical base address of the CM
+ *
+ * This function returns the physical base address of the Coherence Manager
+ * global control block, or 0 if no Coherence Manager is present. It provides
+ * a default implementation which reads the CMGCRBase register where available,
+ * and may be overriden by platforms which determine this address in a
+ * different way by defining a function with the same prototype except for the
+ * name mips_cm_phys_base (without underscores).
+ */
+extern phys_t __mips_cm_phys_base(void);
+
+/**
+ * mips_cm_probe - probe for a Coherence Manager
+ *
+ * Attempt to detect the presence of a Coherence Manager. Returns 0 if a CM
+ * is successfully detected, else -errno.
+ */
+#ifdef CONFIG_MIPS_CM
+extern int mips_cm_probe(void);
+#else
+static inline int mips_cm_probe(void)
+{
+	return -ENODEV;
+}
+#endif
+
+/**
+ * mips_cm_present - determine whether a Coherence Manager is present
+ *
+ * Returns true if a CM is present in the system, else false.
+ */
+static inline bool mips_cm_present(void)
+{
+#ifdef CONFIG_MIPS_CM
+	return mips_cm_base != NULL;
+#else
+	return false;
+#endif
+}
+
+/**
+ * mips_cm_has_l2sync - determine whether an L2-only sync region is present
+ *
+ * Returns true if the system implements an L2-only sync region, else false.
+ */
+static inline bool mips_cm_has_l2sync(void)
+{
+#ifdef CONFIG_MIPS_CM
+	return mips_cm_l2sync_base != NULL;
+#else
+	return false;
+#endif
+}
+
+/* Offsets to register blocks from the CM base address */
+#define MIPS_CM_GCB_OFS		0x0000 /* Global Control Block */
+#define MIPS_CM_CLCB_OFS	0x2000 /* Core Local Control Block */
+#define MIPS_CM_COCB_OFS	0x4000 /* Core Other Control Block */
+#define MIPS_CM_GDB_OFS		0x6000 /* Global Debug Block */
+
+/* Total size of the CM memory mapped registers */
+#define MIPS_CM_GCR_SIZE	0x8000
+
+/* Size of the L2-only sync region */
+#define MIPS_CM_L2SYNC_SIZE	0x1000
+
+/* Macros to ease the creation of register access functions */
+#define BUILD_CM_R_(name, off)					\
+static inline u32 *addr_gcr_##name(void)			\
+{								\
+	return (u32 *)(mips_cm_base + (off));			\
+}								\
+								\
+static inline u32 read_gcr_##name(void)				\
+{								\
+	return readl(addr_gcr_##name());			\
+}
+
+#define BUILD_CM__W(name, off)					\
+static inline void write_gcr_##name(u32 value)			\
+{								\
+	writel(value, addr_gcr_##name());			\
+}
+
+#define BUILD_CM_RW(name, off)					\
+	BUILD_CM_R_(name, off)					\
+	BUILD_CM__W(name, off)
+
+#define BUILD_CM_Cx_R_(name, off)				\
+	BUILD_CM_R_(cl_##name, MIPS_CM_CLCB_OFS + (off))	\
+	BUILD_CM_R_(co_##name, MIPS_CM_COCB_OFS + (off))
+
+#define BUILD_CM_Cx__W(name, off)				\
+	BUILD_CM__W(cl_##name, MIPS_CM_CLCB_OFS + (off))	\
+	BUILD_CM__W(co_##name, MIPS_CM_COCB_OFS + (off))
+
+#define BUILD_CM_Cx_RW(name, off)				\
+	BUILD_CM_Cx_R_(name, off)				\
+	BUILD_CM_Cx__W(name, off)
+
+/* GCB register accessor functions */
+BUILD_CM_R_(config,		MIPS_CM_GCB_OFS + 0x00)
+BUILD_CM_RW(base,		MIPS_CM_GCB_OFS + 0x08)
+BUILD_CM_RW(access,		MIPS_CM_GCB_OFS + 0x20)
+BUILD_CM_R_(rev,		MIPS_CM_GCB_OFS + 0x30)
+BUILD_CM_RW(error_mask,		MIPS_CM_GCB_OFS + 0x40)
+BUILD_CM_RW(error_cause,	MIPS_CM_GCB_OFS + 0x48)
+BUILD_CM_RW(error_addr,		MIPS_CM_GCB_OFS + 0x50)
+BUILD_CM_RW(error_mult,		MIPS_CM_GCB_OFS + 0x58)
+BUILD_CM_RW(l2_only_sync_base,	MIPS_CM_GCB_OFS + 0x70)
+BUILD_CM_RW(gic_base,		MIPS_CM_GCB_OFS + 0x80)
+BUILD_CM_RW(cpc_base,		MIPS_CM_GCB_OFS + 0x88)
+BUILD_CM_RW(reg0_base,		MIPS_CM_GCB_OFS + 0x90)
+BUILD_CM_RW(reg0_mask,		MIPS_CM_GCB_OFS + 0x98)
+BUILD_CM_RW(reg1_base,		MIPS_CM_GCB_OFS + 0xa0)
+BUILD_CM_RW(reg1_mask,		MIPS_CM_GCB_OFS + 0xa8)
+BUILD_CM_RW(reg2_base,		MIPS_CM_GCB_OFS + 0xb0)
+BUILD_CM_RW(reg2_mask,		MIPS_CM_GCB_OFS + 0xb8)
+BUILD_CM_RW(reg3_base,		MIPS_CM_GCB_OFS + 0xc0)
+BUILD_CM_RW(reg3_mask,		MIPS_CM_GCB_OFS + 0xc8)
+BUILD_CM_R_(gic_status,		MIPS_CM_GCB_OFS + 0xd0)
+BUILD_CM_R_(cpc_status,		MIPS_CM_GCB_OFS + 0xf0)
+
+/* Core Local & Core Other register accessor functions */
+BUILD_CM_Cx_RW(reset_release,	0x00)
+BUILD_CM_Cx_RW(coherence,	0x08)
+BUILD_CM_Cx_R_(config,		0x10)
+BUILD_CM_Cx_RW(other,		0x18)
+BUILD_CM_Cx_RW(reset_base,	0x20)
+BUILD_CM_Cx_R_(id,		0x28)
+BUILD_CM_Cx_RW(reset_ext_base,	0x30)
+BUILD_CM_Cx_R_(tcid_0_priority,	0x40)
+BUILD_CM_Cx_R_(tcid_1_priority,	0x48)
+BUILD_CM_Cx_R_(tcid_2_priority,	0x50)
+BUILD_CM_Cx_R_(tcid_3_priority,	0x58)
+BUILD_CM_Cx_R_(tcid_4_priority,	0x60)
+BUILD_CM_Cx_R_(tcid_5_priority,	0x68)
+BUILD_CM_Cx_R_(tcid_6_priority,	0x70)
+BUILD_CM_Cx_R_(tcid_7_priority,	0x78)
+BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
+
+/* GCR_CONFIG register fields */
+#define CM_GCR_CONFIG_NUMIOCU_SHF		8
+#define CM_GCR_CONFIG_NUMIOCU_MSK		(_ULCAST_(0xf) << 8)
+#define CM_GCR_CONFIG_PCORES_SHF		0
+#define CM_GCR_CONFIG_PCORES_MSK		(_ULCAST_(0xff) << 0)
+
+/* GCR_BASE register fields */
+#define CM_GCR_BASE_GCRBASE_SHF			15
+#define CM_GCR_BASE_GCRBASE_MSK			(_ULCAST_(0x1ffff) << 15)
+#define CM_GCR_BASE_CMDEFTGT_SHF		0
+#define CM_GCR_BASE_CMDEFTGT_MSK		(_ULCAST_(0x3) << 0)
+#define  CM_GCR_BASE_CMDEFTGT_DISABLED		0
+#define  CM_GCR_BASE_CMDEFTGT_MEM		1
+#define  CM_GCR_BASE_CMDEFTGT_IOCU0		2
+#define  CM_GCR_BASE_CMDEFTGT_IOCU1		3
+
+/* GCR_ACCESS register fields */
+#define CM_GCR_ACCESS_ACCESSEN_SHF		0
+#define CM_GCR_ACCESS_ACCESSEN_MSK		(_ULCAST_(0xff) << 0)
+
+/* GCR_REV register fields */
+#define CM_GCR_REV_MAJOR_SHF			8
+#define CM_GCR_REV_MAJOR_MSK			(_ULCAST_(0xff) << 8)
+#define CM_GCR_REV_MINOR_SHF			0
+#define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
+
+/* GCR_ERROR_CAUSE register fields */
+#define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
+#define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
+#define CM_GCR_ERROR_CAUSE_ERRINFO_SHF		0
+#define CM_GCR_ERROR_CAUSE_ERRINGO_MSK		(_ULCAST_(0x7ffffff) << 0)
+
+/* GCR_ERROR_MULT register fields */
+#define CM_GCR_ERROR_MULT_ERR2ND_SHF		0
+#define CM_GCR_ERROR_MULT_ERR2ND_MSK		(_ULCAST_(0x1f) << 0)
+
+/* GCR_L2_ONLY_SYNC_BASE register fields */
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_SHF	12
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK	(_ULCAST_(0xfffff) << 12)
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_SHF	0
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK	(_ULCAST_(0x1) << 0)
+
+/* GCR_GIC_BASE register fields */
+#define CM_GCR_GIC_BASE_GICBASE_SHF		17
+#define CM_GCR_GIC_BASE_GICBASE_MSK		(_ULCAST_(0x7fff) << 17)
+#define CM_GCR_GIC_BASE_GICEN_SHF		0
+#define CM_GCR_GIC_BASE_GICEN_MSK		(_ULCAST_(0x1) << 0)
+
+/* GCR_CPC_BASE register fields */
+#define CM_GCR_CPC_BASE_CPCBASE_SHF		17
+#define CM_GCR_CPC_BASE_CPCBASE_MSK		(_ULCAST_(0x7fff) << 17)
+#define CM_GCR_CPC_BASE_CPCEN_SHF		0
+#define CM_GCR_CPC_BASE_CPCEN_MSK		(_ULCAST_(0x1) << 0)
+
+/* GCR_REGn_BASE register fields */
+#define CM_GCR_REGn_BASE_BASEADDR_SHF		16
+#define CM_GCR_REGn_BASE_BASEADDR_MSK		(_ULCAST_(0xffff) << 16)
+
+/* GCR_REGn_MASK register fields */
+#define CM_GCR_REGn_MASK_ADDRMASK_SHF		16
+#define CM_GCR_REGn_MASK_ADDRMASK_MSK		(_ULCAST_(0xffff) << 16)
+#define CM_GCR_REGn_MASK_CCAOVR_SHF		5
+#define CM_GCR_REGn_MASK_CCAOVR_MSK		(_ULCAST_(0x3) << 5)
+#define CM_GCR_REGn_MASK_CCAOVREN_SHF		4
+#define CM_GCR_REGn_MASK_CCAOVREN_MSK		(_ULCAST_(0x1) << 4)
+#define CM_GCR_REGn_MASK_DROPL2_SHF		2
+#define CM_GCR_REGn_MASK_DROPL2_MSK		(_ULCAST_(0x1) << 2)
+#define CM_GCR_REGn_MASK_CMTGT_SHF		0
+#define CM_GCR_REGn_MASK_CMTGT_MSK		(_ULCAST_(0x3) << 0)
+#define  CM_GCR_REGn_MASK_CMTGT_DISABLED	(_ULCAST_(0x0) << 0)
+#define  CM_GCR_REGn_MASK_CMTGT_MEM		(_ULCAST_(0x1) << 0)
+#define  CM_GCR_REGn_MASK_CMTGT_IOCU0		(_ULCAST_(0x2) << 0)
+#define  CM_GCR_REGn_MASK_CMTGT_IOCU1		(_ULCAST_(0x3) << 0)
+
+/* GCR_GIC_STATUS register fields */
+#define CM_GCR_GIC_STATUS_EX_SHF		0
+#define CM_GCR_GIC_STATUS_EX_MSK		(_ULCAST_(0x1) << 0)
+
+/* GCR_CPC_STATUS register fields */
+#define CM_GCR_CPC_STATUS_EX_SHF		0
+#define CM_GCR_CPC_STATUS_EX_MSK		(_ULCAST_(0x1) << 0)
+
+/* GCR_Cx_COHERENCE register fields */
+#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF	0
+#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK	(_ULCAST_(0xff) << 0)
+
+/* GCR_Cx_CONFIG register fields */
+#define CM_GCR_Cx_CONFIG_IOCUTYPE_SHF		10
+#define CM_GCR_Cx_CONFIG_IOCUTYPE_MSK		(_ULCAST_(0x3) << 10)
+#define CM_GCR_Cx_CONFIG_PVPE_SHF		0
+#define CM_GCR_Cx_CONFIG_PVPE_MSK		(_ULCAST_(0x1ff) << 0)
+
+/* GCR_Cx_OTHER register fields */
+#define CM_GCR_Cx_OTHER_CORENUM_SHF		16
+#define CM_GCR_Cx_OTHER_CORENUM_MSK		(_ULCAST_(0xffff) << 16)
+
+/* GCR_Cx_RESET_BASE register fields */
+#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF	12
+#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_MSK	(_ULCAST_(0xfffff) << 12)
+
+/* GCR_Cx_RESET_EXT_BASE register fields */
+#define CM_GCR_Cx_RESET_EXT_BASE_EVARESET_SHF	31
+#define CM_GCR_Cx_RESET_EXT_BASE_EVARESET_MSK	(_ULCAST_(0x1) << 31)
+#define CM_GCR_Cx_RESET_EXT_BASE_UEB_SHF	30
+#define CM_GCR_Cx_RESET_EXT_BASE_UEB_MSK	(_ULCAST_(0x1) << 30)
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCMASK_SHF	20
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCMASK_MSK	(_ULCAST_(0xff) << 20)
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCPA_SHF	1
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCPA_MSK	(_ULCAST_(0x7f) << 1)
+#define CM_GCR_Cx_RESET_EXT_BASE_PRESENT_SHF	0
+#define CM_GCR_Cx_RESET_EXT_BASE_PRESENT_MSK	(_ULCAST_(0x1) << 0)
+
+/**
+ * mips_cm_numcores - return the number of cores present in the system
+ *
+ * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
+ * zero if no Coherence Manager is present.
+ */
+static inline unsigned mips_cm_numcores(void)
+{
+	if (!mips_cm_present())
+		return 0;
+
+	return ((read_gcr_config() & CM_GCR_CONFIG_PCORES_MSK)
+		>> CM_GCR_CONFIG_PCORES_SHF) + 1;
+}
+
+/**
+ * mips_cm_numiocu - return the number of IOCUs present in the system
+ *
+ * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
+ * if no Coherence Manager is present.
+ */
+static inline unsigned mips_cm_numiocu(void)
+{
+	if (!mips_cm_present())
+		return 0;
+
+	return (read_gcr_config() & CM_GCR_CONFIG_NUMIOCU_MSK)
+		>> CM_GCR_CONFIG_NUMIOCU_SHF;
+}
+
+/**
+ * mips_cm_l2sync - perform an L2-only sync operation
+ *
+ * If an L2-only sync region is present in the system then this function
+ * performs and L2-only sync and returns zero. Otherwise it returns -ENODEV.
+ */
+static inline int mips_cm_l2sync(void)
+{
+	if (!mips_cm_has_l2sync())
+		return -ENODEV;
+
+	writel(0, mips_cm_l2sync_base);
+	return 0;
+}
+
+#endif /* __MIPS_ASM_MIPS_CM_H__ */
diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h
new file mode 100644
index 000000000000..fb78935010a3
--- /dev/null
+++ b/arch/mips/include/asm/mips-cpc.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 __MIPS_ASM_MIPS_CPC_H__
+#define __MIPS_ASM_MIPS_CPC_H__
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+/* The base address of the CPC registers */
+extern void __iomem *mips_cpc_base;
+
+/**
+ * mips_cpc_default_phys_base - retrieve the default physical base address of
+ *                              the CPC
+ *
+ * Returns the default physical base address of the Cluster Power Controller
+ * memory mapped registers. This is platform dependant & must therefore be
+ * implemented per-platform.
+ */
+extern phys_t mips_cpc_default_phys_base(void);
+
+/**
+ * mips_cpc_phys_base - retrieve the physical base address of the CPC
+ *
+ * This function returns the physical base address of the Cluster Power
+ * Controller memory mapped registers, or 0 if no Cluster Power Controller
+ * is present. It may be overriden by individual platforms which determine
+ * this address in a different way.
+ */
+extern phys_t __weak mips_cpc_phys_base(void);
+
+/**
+ * mips_cpc_probe - probe for a Cluster Power Controller
+ *
+ * Attempt to detect the presence of a Cluster Power Controller. Returns 0 if
+ * a CPC is successfully detected, else -errno.
+ */
+#ifdef CONFIG_MIPS_CPC
+extern int mips_cpc_probe(void);
+#else
+static inline int mips_cpc_probe(void)
+{
+	return -ENODEV;
+}
+#endif
+
+/**
+ * mips_cpc_present - determine whether a Cluster Power Controller is present
+ *
+ * Returns true if a CPC is present in the system, else false.
+ */
+static inline bool mips_cpc_present(void)
+{
+#ifdef CONFIG_MIPS_CPC
+	return mips_cpc_base != NULL;
+#else
+	return false;
+#endif
+}
+
+/* Offsets from the CPC base address to various control blocks */
+#define MIPS_CPC_GCB_OFS	0x0000
+#define MIPS_CPC_CLCB_OFS	0x2000
+#define MIPS_CPC_COCB_OFS	0x4000
+
+/* Macros to ease the creation of register access functions */
+#define BUILD_CPC_R_(name, off) \
+static inline u32 read_cpc_##name(void)				\
+{								\
+	return readl(mips_cpc_base + (off));			\
+}
+
+#define BUILD_CPC__W(name, off) \
+static inline void write_cpc_##name(u32 value)			\
+{								\
+	writel(value, mips_cpc_base + (off));			\
+}
+
+#define BUILD_CPC_RW(name, off)					\
+	BUILD_CPC_R_(name, off)					\
+	BUILD_CPC__W(name, off)
+
+#define BUILD_CPC_Cx_R_(name, off)				\
+	BUILD_CPC_R_(cl_##name, MIPS_CPC_CLCB_OFS + (off))	\
+	BUILD_CPC_R_(co_##name, MIPS_CPC_COCB_OFS + (off))
+
+#define BUILD_CPC_Cx__W(name, off)				\
+	BUILD_CPC__W(cl_##name, MIPS_CPC_CLCB_OFS + (off))	\
+	BUILD_CPC__W(co_##name, MIPS_CPC_COCB_OFS + (off))
+
+#define BUILD_CPC_Cx_RW(name, off)				\
+	BUILD_CPC_Cx_R_(name, off)				\
+	BUILD_CPC_Cx__W(name, off)
+
+/* GCB register accessor functions */
+BUILD_CPC_RW(access,		MIPS_CPC_GCB_OFS + 0x00)
+BUILD_CPC_RW(seqdel,		MIPS_CPC_GCB_OFS + 0x08)
+BUILD_CPC_RW(rail,		MIPS_CPC_GCB_OFS + 0x10)
+BUILD_CPC_RW(resetlen,		MIPS_CPC_GCB_OFS + 0x18)
+BUILD_CPC_R_(revision,		MIPS_CPC_GCB_OFS + 0x20)
+
+/* Core Local & Core Other accessor functions */
+BUILD_CPC_Cx_RW(cmd,		0x00)
+BUILD_CPC_Cx_RW(stat_conf,	0x08)
+BUILD_CPC_Cx_RW(other,		0x10)
+
+/* CPC_Cx_CMD register fields */
+#define CPC_Cx_CMD_SHF				0
+#define CPC_Cx_CMD_MSK				(_ULCAST_(0xf) << 0)
+#define  CPC_Cx_CMD_CLOCKOFF			(_ULCAST_(0x1) << 0)
+#define  CPC_Cx_CMD_PWRDOWN			(_ULCAST_(0x2) << 0)
+#define  CPC_Cx_CMD_PWRUP			(_ULCAST_(0x3) << 0)
+#define  CPC_Cx_CMD_RESET			(_ULCAST_(0x4) << 0)
+
+/* CPC_Cx_STAT_CONF register fields */
+#define CPC_Cx_STAT_CONF_PWRUPE_SHF		23
+#define CPC_Cx_STAT_CONF_PWRUPE_MSK		(_ULCAST_(0x1) << 23)
+#define CPC_Cx_STAT_CONF_SEQSTATE_SHF		19
+#define CPC_Cx_STAT_CONF_SEQSTATE_MSK		(_ULCAST_(0xf) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_D0		(_ULCAST_(0x0) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U0		(_ULCAST_(0x1) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U1		(_ULCAST_(0x2) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U2		(_ULCAST_(0x3) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U3		(_ULCAST_(0x4) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U4		(_ULCAST_(0x5) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U5		(_ULCAST_(0x6) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_U6		(_ULCAST_(0x7) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_D1		(_ULCAST_(0x8) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_D3		(_ULCAST_(0x9) << 19)
+#define  CPC_Cx_STAT_CONF_SEQSTATE_D2		(_ULCAST_(0xa) << 19)
+#define CPC_Cx_STAT_CONF_CLKGAT_IMPL_SHF	17
+#define CPC_Cx_STAT_CONF_CLKGAT_IMPL_MSK	(_ULCAST_(0x1) << 17)
+#define CPC_Cx_STAT_CONF_PWRDN_IMPL_SHF		16
+#define CPC_Cx_STAT_CONF_PWRDN_IMPL_MSK		(_ULCAST_(0x1) << 16)
+#define CPC_Cx_STAT_CONF_EJTAG_PROBE_SHF	15
+#define CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK	(_ULCAST_(0x1) << 15)
+
+/* CPC_Cx_OTHER register fields */
+#define CPC_Cx_OTHER_CORENUM_SHF		16
+#define CPC_Cx_OTHER_CORENUM_MSK		(_ULCAST_(0xff) << 16)
+
+#endif /* __MIPS_ASM_MIPS_CPC_H__ */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index bbc3dd4294bc..3e025b5311db 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -568,11 +568,23 @@
 #define MIPS_CONF1_PC		(_ULCAST_(1) <<	 4)
 #define MIPS_CONF1_MD		(_ULCAST_(1) <<	 5)
 #define MIPS_CONF1_C2		(_ULCAST_(1) <<	 6)
+#define MIPS_CONF1_DA_SHF	7
+#define MIPS_CONF1_DA_SZ	3
 #define MIPS_CONF1_DA		(_ULCAST_(7) <<	 7)
+#define MIPS_CONF1_DL_SHF	10
+#define MIPS_CONF1_DL_SZ	3
 #define MIPS_CONF1_DL		(_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS_SHF	13
+#define MIPS_CONF1_DS_SZ	3
 #define MIPS_CONF1_DS		(_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA_SHF	16
+#define MIPS_CONF1_IA_SZ	3
 #define MIPS_CONF1_IA		(_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL_SHF	19
+#define MIPS_CONF1_IL_SZ	3
 #define MIPS_CONF1_IL		(_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS_SHF	22
+#define MIPS_CONF1_IS_SZ	3
 #define MIPS_CONF1_IS		(_ULCAST_(7) << 22)
 #define MIPS_CONF1_TLBS_SHIFT   (25)
 #define MIPS_CONF1_TLBS_SIZE    (6)
@@ -653,9 +665,16 @@
 
 #define MIPS_CONF7_RPS		(_ULCAST_(1) << 2)
 
+#define MIPS_CONF7_IAR		(_ULCAST_(1) << 10)
+#define MIPS_CONF7_AR		(_ULCAST_(1) << 16)
+
 /*  EntryHI bit definition */
 #define MIPS_ENTRYHI_EHINV	(_ULCAST_(1) << 10)
 
+/* CMGCRBase bit definitions */
+#define MIPS_CMGCRB_BASE	11
+#define MIPS_CMGCRF_BASE	(~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
+
 /*
  * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
  */
@@ -1010,6 +1029,8 @@ do {									\
 
 #define read_c0_prid()		__read_32bit_c0_register($15, 0)
 
+#define read_c0_cmgcrbase()	__read_ulong_c0_register($15, 3)
+
 #define read_c0_config()	__read_32bit_c0_register($16, 0)
 #define read_c0_config1()	__read_32bit_c0_register($16, 1)
 #define read_c0_config2()	__read_32bit_c0_register($16, 2)
@@ -1883,6 +1904,7 @@ change_c0_##name(unsigned int change, unsigned int newbits)	\
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
+__BUILD_SET_C0(config5)
 __BUILD_SET_C0(intcontrol)
 __BUILD_SET_C0(intctl)
 __BUILD_SET_C0(srsmap)
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
new file mode 100644
index 000000000000..d7fd8e1eef96
--- /dev/null
+++ b/arch/mips/include/asm/msa.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 _ASM_MSA_H
+#define _ASM_MSA_H
+
+#include <asm/mipsregs.h>
+
+extern void _save_msa(struct task_struct *);
+extern void _restore_msa(struct task_struct *);
+
+static inline void enable_msa(void)
+{
+	if (cpu_has_msa)
+		set_c0_config5(MIPS_CONF5_MSAEN);
+}
+
+static inline void disable_msa(void)
+{
+	if (cpu_has_msa)
+		clear_c0_config5(MIPS_CONF5_MSAEN);
+}
+
+static inline int is_msa_enabled(void)
+{
+	if (!cpu_has_msa)
+		return 0;
+
+	return read_c0_config5() & MIPS_CONF5_MSAEN;
+}
+
+static inline int thread_msa_context_live(void)
+{
+	/*
+	 * Check cpu_has_msa only if it's a constant. This will allow the
+	 * compiler to optimise out code for CPUs without MSA without adding
+	 * an extra redundant check for CPUs with MSA.
+	 */
+	if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
+		return 0;
+
+	return test_thread_flag(TIF_MSA_CTX_LIVE);
+}
+
+static inline void save_msa(struct task_struct *t)
+{
+	if (cpu_has_msa)
+		_save_msa(t);
+}
+
+static inline void restore_msa(struct task_struct *t)
+{
+	if (cpu_has_msa)
+		_restore_msa(t);
+}
+
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+
+#define __BUILD_MSA_CTL_REG(name, cs)				\
+static inline unsigned int read_msa_##name(void)		\
+{								\
+	unsigned int reg;					\
+	__asm__ __volatile__(					\
+	"	.set	push\n"					\
+	"	.set	msa\n"					\
+	"	cfcmsa	%0, $" #cs "\n"				\
+	"	.set	pop\n"					\
+	: "=r"(reg));						\
+	return reg;						\
+}								\
+								\
+static inline void write_msa_##name(unsigned int val)		\
+{								\
+	__asm__ __volatile__(					\
+	"	.set	push\n"					\
+	"	.set	msa\n"					\
+	"	cfcmsa	$" #cs ", %0\n"				\
+	"	.set	pop\n"					\
+	: : "r"(val));						\
+}
+
+#else /* !TOOLCHAIN_SUPPORTS_MSA */
+
+/*
+ * Define functions using .word for the c[ft]cmsa instructions in order to
+ * allow compilation with toolchains that do not support MSA. Once all
+ * toolchains in use support MSA these can be removed.
+ */
+
+#define __BUILD_MSA_CTL_REG(name, cs)				\
+static inline unsigned int read_msa_##name(void)		\
+{								\
+	unsigned int reg;					\
+	__asm__ __volatile__(					\
+	"	.set	push\n"					\
+	"	.set	noat\n"					\
+	"	.word	0x787e0059 | (" #cs " << 11)\n"		\
+	"	move	%0, $1\n"				\
+	"	.set	pop\n"					\
+	: "=r"(reg));						\
+	return reg;						\
+}								\
+								\
+static inline void write_msa_##name(unsigned int val)		\
+{								\
+	__asm__ __volatile__(					\
+	"	.set	push\n"					\
+	"	.set	noat\n"					\
+	"	move	$1, %0\n"				\
+	"	.word	0x783e0819 | (" #cs " << 6)\n"		\
+	"	.set	pop\n"					\
+	: : "r"(val));						\
+}
+
+#endif /* !TOOLCHAIN_SUPPORTS_MSA */
+
+#define MSA_IR		0
+#define MSA_CSR		1
+#define MSA_ACCESS	2
+#define MSA_SAVE	3
+#define MSA_MODIFY	4
+#define MSA_REQUEST	5
+#define MSA_MAP		6
+#define MSA_UNMAP	7
+
+__BUILD_MSA_CTL_REG(ir, 0)
+__BUILD_MSA_CTL_REG(csr, 1)
+__BUILD_MSA_CTL_REG(access, 2)
+__BUILD_MSA_CTL_REG(save, 3)
+__BUILD_MSA_CTL_REG(modify, 4)
+__BUILD_MSA_CTL_REG(request, 5)
+__BUILD_MSA_CTL_REG(map, 6)
+__BUILD_MSA_CTL_REG(unmap, 7)
+
+/* MSA Implementation Register (MSAIR) */
+#define MSA_IR_REVB		0
+#define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
+#define MSA_IR_PROCB		8
+#define MSA_IR_PROCF		(_ULCAST_(0xff) << MSA_IR_PROCB)
+#define MSA_IR_WRPB		16
+#define MSA_IR_WRPF		(_ULCAST_(0x1) << MSA_IR_WRPB)
+
+/* MSA Control & Status Register (MSACSR) */
+#define MSA_CSR_RMB		0
+#define MSA_CSR_RMF		(_ULCAST_(0x3) << MSA_CSR_RMB)
+#define MSA_CSR_RM_NEAREST	0
+#define MSA_CSR_RM_TO_ZERO	1
+#define MSA_CSR_RM_TO_POS	2
+#define MSA_CSR_RM_TO_NEG	3
+#define MSA_CSR_FLAGSB		2
+#define MSA_CSR_FLAGSF		(_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
+#define MSA_CSR_FLAGS_IB	2
+#define MSA_CSR_FLAGS_IF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
+#define MSA_CSR_FLAGS_UB	3
+#define MSA_CSR_FLAGS_UF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
+#define MSA_CSR_FLAGS_OB	4
+#define MSA_CSR_FLAGS_OF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
+#define MSA_CSR_FLAGS_ZB	5
+#define MSA_CSR_FLAGS_ZF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
+#define MSA_CSR_FLAGS_VB	6
+#define MSA_CSR_FLAGS_VF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
+#define MSA_CSR_ENABLESB	7
+#define MSA_CSR_ENABLESF	(_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
+#define MSA_CSR_ENABLES_IB	7
+#define MSA_CSR_ENABLES_IF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
+#define MSA_CSR_ENABLES_UB	8
+#define MSA_CSR_ENABLES_UF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
+#define MSA_CSR_ENABLES_OB	9
+#define MSA_CSR_ENABLES_OF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
+#define MSA_CSR_ENABLES_ZB	10
+#define MSA_CSR_ENABLES_ZF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
+#define MSA_CSR_ENABLES_VB	11
+#define MSA_CSR_ENABLES_VF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
+#define MSA_CSR_CAUSEB		12
+#define MSA_CSR_CAUSEF		(_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
+#define MSA_CSR_CAUSE_IB	12
+#define MSA_CSR_CAUSE_IF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
+#define MSA_CSR_CAUSE_UB	13
+#define MSA_CSR_CAUSE_UF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
+#define MSA_CSR_CAUSE_OB	14
+#define MSA_CSR_CAUSE_OF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
+#define MSA_CSR_CAUSE_ZB	15
+#define MSA_CSR_CAUSE_ZF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
+#define MSA_CSR_CAUSE_VB	16
+#define MSA_CSR_CAUSE_VF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
+#define MSA_CSR_CAUSE_EB	17
+#define MSA_CSR_CAUSE_EF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
+#define MSA_CSR_NXB		18
+#define MSA_CSR_NXF		(_ULCAST_(0x1) << MSA_CSR_NXB)
+#define MSA_CSR_FSB		24
+#define MSA_CSR_FSF		(_ULCAST_(0x1) << MSA_CSR_FSB)
+
+#endif /* _ASM_MSA_H */
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 5e08bcc74897..5699ec3a71af 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -190,7 +190,9 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  * https://patchwork.linux-mips.org/patch/1541/
  */
 
+#ifndef __pa_symbol
 #define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
+#endif
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 3605b844ad87..ad70cba8daff 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -97,18 +97,48 @@ extern unsigned int vced_count, vcei_count;
 
 #define NUM_FPU_REGS	32
 
-typedef __u64 fpureg_t;
+#ifdef CONFIG_CPU_HAS_MSA
+# define FPU_REG_WIDTH	128
+#else
+# define FPU_REG_WIDTH	64
+#endif
+
+union fpureg {
+	__u32	val32[FPU_REG_WIDTH / 32];
+	__u64	val64[FPU_REG_WIDTH / 64];
+};
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# define FPR_IDX(width, idx)	(idx)
+#else
+# define FPR_IDX(width, idx)	((FPU_REG_WIDTH / (width)) - 1 - (idx))
+#endif
+
+#define BUILD_FPR_ACCESS(width) \
+static inline u##width get_fpr##width(union fpureg *fpr, unsigned idx)	\
+{									\
+	return fpr->val##width[FPR_IDX(width, idx)];			\
+}									\
+									\
+static inline void set_fpr##width(union fpureg *fpr, unsigned idx,	\
+				  u##width val)				\
+{									\
+	fpr->val##width[FPR_IDX(width, idx)] = val;			\
+}
+
+BUILD_FPR_ACCESS(32)
+BUILD_FPR_ACCESS(64)
 
 /*
- * It would be nice to add some more fields for emulator statistics, but there
- * are a number of fixed offsets in offset.h and elsewhere that would have to
- * be recalculated by hand.  So the additional information will be private to
- * the FPU emulator for now.  See asm-mips/fpu_emulator.h.
+ * It would be nice to add some more fields for emulator statistics,
+ * the additional information is private to the FPU emulator for now.
+ * See arch/mips/include/asm/fpu_emulator.h.
  */
 
 struct mips_fpu_struct {
-	fpureg_t	fpr[NUM_FPU_REGS];
+	union fpureg	fpr[NUM_FPU_REGS];
 	unsigned int	fcr31;
+	unsigned int	msacsr;
 };
 
 #define NUM_DSP_REGS   6
@@ -284,8 +314,9 @@ struct thread_struct {
 	 * Saved FPU/FPU emulator stuff				\
 	 */							\
 	.fpu			= {				\
-		.fpr		= {0,},				\
+		.fpr		= {{{0,},},},			\
 		.fcr31		= 0,				\
+		.msacsr		= 0,				\
 	},							\
 	/*							\
 	 * FPU affinity state (null if not FPAFF)		\
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 7bba9da110af..bf1ac8d35783 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -82,7 +82,7 @@ static inline long regs_return_value(struct pt_regs *regs)
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
+extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
 
 extern void die(const char *, struct pt_regs *) __noreturn;
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index c84caddb8bde..69c2ada7d4aa 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -17,6 +17,7 @@
 #include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/mipsmtregs.h>
+#include <asm/uaccess.h> /* for segment_eq() */
 
 /*
  * This macro return a properly sign-extended address suitable as base address
@@ -212,6 +213,20 @@ static inline void flush_scache_line(unsigned long addr)
 	:							\
 	: "i" (op), "r" (addr))
 
+#define protected_cachee_op(op,addr)				\
+	__asm__ __volatile__(					\
+	"	.set	push			\n"		\
+	"	.set	noreorder		\n"		\
+	"	.set	mips0			\n"		\
+	"	.set	eva			\n"		\
+	"1:	cachee	%0, (%1)		\n"		\
+	"2:	.set	pop			\n"		\
+	"	.section __ex_table,\"a\"	\n"		\
+	"	"STR(PTR)" 1b, 2b		\n"		\
+	"	.previous"					\
+	:							\
+	: "i" (op), "r" (addr))
+
 /*
  * The next two are for badland addresses like signal trampolines.
  */
@@ -223,7 +238,11 @@ static inline void protected_flush_icache_line(unsigned long addr)
 		break;
 
 	default:
+#ifdef CONFIG_EVA
+		protected_cachee_op(Hit_Invalidate_I, addr);
+#else
 		protected_cache_op(Hit_Invalidate_I, addr);
+#endif
 		break;
 	}
 }
@@ -356,6 +375,91 @@ static inline void invalidate_tcache_page(unsigned long addr)
 		: "r" (base),						\
 		  "i" (op));
 
+/*
+ * Perform the cache operation specified by op using a user mode virtual
+ * address while in kernel mode.
+ */
+#define cache16_unroll32_user(base,op)					\
+	__asm__ __volatile__(						\
+	"	.set push					\n"	\
+	"	.set noreorder					\n"	\
+	"	.set mips0					\n"	\
+	"	.set eva					\n"	\
+	"	cachee %1, 0x000(%0); cachee %1, 0x010(%0)	\n"	\
+	"	cachee %1, 0x020(%0); cachee %1, 0x030(%0)	\n"	\
+	"	cachee %1, 0x040(%0); cachee %1, 0x050(%0)	\n"	\
+	"	cachee %1, 0x060(%0); cachee %1, 0x070(%0)	\n"	\
+	"	cachee %1, 0x080(%0); cachee %1, 0x090(%0)	\n"	\
+	"	cachee %1, 0x0a0(%0); cachee %1, 0x0b0(%0)	\n"	\
+	"	cachee %1, 0x0c0(%0); cachee %1, 0x0d0(%0)	\n"	\
+	"	cachee %1, 0x0e0(%0); cachee %1, 0x0f0(%0)	\n"	\
+	"	cachee %1, 0x100(%0); cachee %1, 0x110(%0)	\n"	\
+	"	cachee %1, 0x120(%0); cachee %1, 0x130(%0)	\n"	\
+	"	cachee %1, 0x140(%0); cachee %1, 0x150(%0)	\n"	\
+	"	cachee %1, 0x160(%0); cachee %1, 0x170(%0)	\n"	\
+	"	cachee %1, 0x180(%0); cachee %1, 0x190(%0)	\n"	\
+	"	cachee %1, 0x1a0(%0); cachee %1, 0x1b0(%0)	\n"	\
+	"	cachee %1, 0x1c0(%0); cachee %1, 0x1d0(%0)	\n"	\
+	"	cachee %1, 0x1e0(%0); cachee %1, 0x1f0(%0)	\n"	\
+	"	.set pop					\n"	\
+		:							\
+		: "r" (base),						\
+		  "i" (op));
+
+#define cache32_unroll32_user(base, op)					\
+	__asm__ __volatile__(						\
+	"	.set push					\n"	\
+	"	.set noreorder					\n"	\
+	"	.set mips0					\n"	\
+	"	.set eva					\n"	\
+	"	cachee %1, 0x000(%0); cachee %1, 0x020(%0)	\n"	\
+	"	cachee %1, 0x040(%0); cachee %1, 0x060(%0)	\n"	\
+	"	cachee %1, 0x080(%0); cachee %1, 0x0a0(%0)	\n"	\
+	"	cachee %1, 0x0c0(%0); cachee %1, 0x0e0(%0)	\n"	\
+	"	cachee %1, 0x100(%0); cachee %1, 0x120(%0)	\n"	\
+	"	cachee %1, 0x140(%0); cachee %1, 0x160(%0)	\n"	\
+	"	cachee %1, 0x180(%0); cachee %1, 0x1a0(%0)	\n"	\
+	"	cachee %1, 0x1c0(%0); cachee %1, 0x1e0(%0)	\n"	\
+	"	cachee %1, 0x200(%0); cachee %1, 0x220(%0)	\n"	\
+	"	cachee %1, 0x240(%0); cachee %1, 0x260(%0)	\n"	\
+	"	cachee %1, 0x280(%0); cachee %1, 0x2a0(%0)	\n"	\
+	"	cachee %1, 0x2c0(%0); cachee %1, 0x2e0(%0)	\n"	\
+	"	cachee %1, 0x300(%0); cachee %1, 0x320(%0)	\n"	\
+	"	cachee %1, 0x340(%0); cachee %1, 0x360(%0)	\n"	\
+	"	cachee %1, 0x380(%0); cachee %1, 0x3a0(%0)	\n"	\
+	"	cachee %1, 0x3c0(%0); cachee %1, 0x3e0(%0)	\n"	\
+	"	.set pop					\n"	\
+		:							\
+		: "r" (base),						\
+		  "i" (op));
+
+#define cache64_unroll32_user(base, op)					\
+	__asm__ __volatile__(						\
+	"	.set push					\n"	\
+	"	.set noreorder					\n"	\
+	"	.set mips0					\n"	\
+	"	.set eva					\n"	\
+	"	cachee %1, 0x000(%0); cachee %1, 0x040(%0)	\n"	\
+	"	cachee %1, 0x080(%0); cachee %1, 0x0c0(%0)	\n"	\
+	"	cachee %1, 0x100(%0); cachee %1, 0x140(%0)	\n"	\
+	"	cachee %1, 0x180(%0); cachee %1, 0x1c0(%0)	\n"	\
+	"	cachee %1, 0x200(%0); cachee %1, 0x240(%0)	\n"	\
+	"	cachee %1, 0x280(%0); cachee %1, 0x2c0(%0)	\n"	\
+	"	cachee %1, 0x300(%0); cachee %1, 0x340(%0)	\n"	\
+	"	cachee %1, 0x380(%0); cachee %1, 0x3c0(%0)	\n"	\
+	"	cachee %1, 0x400(%0); cachee %1, 0x440(%0)	\n"	\
+	"	cachee %1, 0x480(%0); cachee %1, 0x4c0(%0)	\n"	\
+	"	cachee %1, 0x500(%0); cachee %1, 0x540(%0)	\n"	\
+	"	cachee %1, 0x580(%0); cachee %1, 0x5c0(%0)	\n"	\
+	"	cachee %1, 0x600(%0); cachee %1, 0x640(%0)	\n"	\
+	"	cachee %1, 0x680(%0); cachee %1, 0x6c0(%0)	\n"	\
+	"	cachee %1, 0x700(%0); cachee %1, 0x740(%0)	\n"	\
+	"	cachee %1, 0x780(%0); cachee %1, 0x7c0(%0)	\n"	\
+	"	.set pop					\n"	\
+		:							\
+		: "r" (base),						\
+		  "i" (op));
+
 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
 #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra)	\
 static inline void extra##blast_##pfx##cache##lsize(void)		\
@@ -429,6 +533,32 @@ __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
 
+#define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \
+static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \
+{									\
+	unsigned long start = page;					\
+	unsigned long end = page + PAGE_SIZE;				\
+									\
+	__##pfx##flush_prologue						\
+									\
+	do {								\
+		cache##lsize##_unroll32_user(start, hitop);             \
+		start += lsize * 32;					\
+	} while (start < end);						\
+									\
+	__##pfx##flush_epilogue						\
+}
+
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+			 16)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+			 32)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+			 64)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
+
 /* build blast_xxx_range, protected_blast_xxx_range */
 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)	\
 static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
@@ -450,12 +580,51 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start,
 	__##pfx##flush_epilogue						\
 }
 
+#ifndef CONFIG_EVA
+
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
+
+#else
+
+#define __BUILD_PROT_BLAST_CACHE_RANGE(pfx, desc, hitop)		\
+static inline void protected_blast_##pfx##cache##_range(unsigned long start,\
+							unsigned long end) \
+{									\
+	unsigned long lsize = cpu_##desc##_line_size();			\
+	unsigned long addr = start & ~(lsize - 1);			\
+	unsigned long aend = (end - 1) & ~(lsize - 1);			\
+									\
+	__##pfx##flush_prologue						\
+									\
+	if (segment_eq(get_fs(), USER_DS)) {				\
+		while (1) {						\
+			protected_cachee_op(hitop, addr);		\
+			if (addr == aend)				\
+				break;					\
+			addr += lsize;					\
+		}							\
+	} else {							\
+		while (1) {						\
+			protected_cache_op(hitop, addr);		\
+			if (addr == aend)				\
+				break;					\
+			addr += lsize;					\
+		}                                                       \
+									\
+	}								\
+	__##pfx##flush_epilogue						\
+}
+
+__BUILD_PROT_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D)
+__BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I)
+
+#endif
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
 	protected_, loongson2_)
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 /* blast_inv_dcache_range */
 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
diff --git a/arch/mips/include/asm/sigcontext.h b/arch/mips/include/asm/sigcontext.h
index eeeb0f48c767..f54bdbe85c0d 100644
--- a/arch/mips/include/asm/sigcontext.h
+++ b/arch/mips/include/asm/sigcontext.h
@@ -32,6 +32,8 @@ struct sigcontext32 {
 	__u32		sc_lo2;
 	__u32		sc_hi3;
 	__u32		sc_lo3;
+	__u64		sc_msaregs[32];	/* Most significant 64 bits */
+	__u32		sc_msa_csr;
 };
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
 #endif /* _ASM_SIGCONTEXT_H */
diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h
new file mode 100644
index 000000000000..d60d1a2180d1
--- /dev/null
+++ b/arch/mips/include/asm/smp-cps.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 __MIPS_ASM_SMP_CPS_H__
+#define __MIPS_ASM_SMP_CPS_H__
+
+#ifndef __ASSEMBLY__
+
+struct boot_config {
+	unsigned int core;
+	unsigned int vpe;
+	unsigned long pc;
+	unsigned long sp;
+	unsigned long gp;
+};
+
+extern struct boot_config mips_cps_bootcfg;
+
+extern void mips_cps_core_entry(void);
+
+#else /* __ASSEMBLY__ */
+
+.extern mips_cps_bootcfg;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __MIPS_ASM_SMP_CPS_H__ */
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index ef2a8041e78b..a042d24534bd 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -13,6 +13,8 @@
 
 #include <linux/errno.h>
 
+#include <asm/mips-cm.h>
+
 #ifdef CONFIG_SMP
 
 #include <linux/cpumask.h>
@@ -58,6 +60,9 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
 
 #endif /* !CONFIG_SMP */
 
+extern void gic_send_ipi_single(int cpu, unsigned int action);
+extern void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action);
+
 static inline int register_up_smp_ops(void)
 {
 #ifdef CONFIG_SMP_UP
@@ -76,6 +81,9 @@ static inline int register_cmp_smp_ops(void)
 #ifdef CONFIG_MIPS_CMP
 	extern struct plat_smp_ops cmp_smp_ops;
 
+	if (!mips_cm_present())
+		return -ENODEV;
+
 	register_smp_ops(&cmp_smp_ops);
 
 	return 0;
@@ -97,4 +105,13 @@ static inline int register_vsmp_smp_ops(void)
 #endif
 }
 
+#ifdef CONFIG_MIPS_CPS
+extern int register_cps_smp_ops(void);
+#else
+static inline int register_cps_smp_ops(void)
+{
+	return -ENODEV;
+}
+#endif
+
 #endif /* __ASM_SMP_OPS_H */
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index 278d45a09728..495c1041a2cc 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,22 +16,29 @@
 #include <asm/watch.h>
 #include <asm/dsp.h>
 #include <asm/cop2.h>
+#include <asm/msa.h>
 
 struct task_struct;
 
+enum {
+	FP_SAVE_NONE	= 0,
+	FP_SAVE_VECTOR	= -1,
+	FP_SAVE_SCALAR	= 1,
+};
+
 /**
  * resume - resume execution of a task
  * @prev:	The task previously executed.
  * @next:	The task to begin executing.
  * @next_ti:	task_thread_info(next).
- * @usedfpu:	Non-zero if prev's FP context should be saved.
+ * @fp_save:	Which, if any, FP context to save for prev.
  *
  * This function is used whilst scheduling to save the context of prev & load
  * the context of next. Returns prev.
  */
 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
 		struct task_struct *next, struct thread_info *next_ti,
-		u32 usedfpu);
+		s32 fp_save);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -75,7 +82,8 @@ do {									\
 
 #define switch_to(prev, next, last)					\
 do {									\
-	u32 __usedfpu, __c0_stat;					\
+	u32 __c0_stat;							\
+	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
@@ -88,8 +96,12 @@ do {									\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
-	__usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU);	\
-	(last) = resume(prev, next, task_thread_info(next), __usedfpu); \
+	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
+		__fpsave = FP_SAVE_SCALAR;				\
+	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
+		__fpsave = FP_SAVE_VECTOR;				\
+	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
+	disable_msa();							\
 } while (0)
 
 #define finish_arch_switch(prev)					\
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index 33e8dbfc1b63..c71e40a49c71 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -13,17 +13,29 @@
 #ifndef __ASM_MIPS_SYSCALL_H
 #define __ASM_MIPS_SYSCALL_H
 
+#include <linux/compiler.h>
 #include <linux/audit.h>
 #include <linux/elf-em.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <asm/ptrace.h>
+#include <asm/unistd.h>
+
+#ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */
+#define __NR_syscall 4000
+#endif
 
 static inline long syscall_get_nr(struct task_struct *task,
 				  struct pt_regs *regs)
 {
-	return regs->regs[2];
+	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+	if ((config_enabled(CONFIG_32BIT) ||
+	    test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+	    (regs->regs[2] == __NR_syscall))
+		return regs->regs[4];
+	else
+		return regs->regs[2];
 }
 
 static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
@@ -57,6 +69,8 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 	default:
 		BUG();
 	}
+
+	unreachable();
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -65,6 +79,12 @@ static inline long syscall_get_return_value(struct task_struct *task,
 	return regs->regs[2];
 }
 
+static inline void syscall_rollback(struct task_struct *task,
+				    struct pt_regs *regs)
+{
+	/* Do nothing */
+}
+
 static inline void syscall_set_return_value(struct task_struct *task,
 					    struct pt_regs *regs,
 					    int error, long val)
@@ -83,11 +103,17 @@ static inline void syscall_get_arguments(struct task_struct *task,
 					 unsigned int i, unsigned int n,
 					 unsigned long *args)
 {
-	unsigned long arg;
 	int ret;
+	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+	if ((config_enabled(CONFIG_32BIT) ||
+	    test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+	    (regs->regs[2] == __NR_syscall)) {
+		i++;
+		n++;
+	}
 
 	while (n--)
-		ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+		ret |= mips_get_syscall_arg(args++, task, regs, i++);
 
 	/*
 	 * No way to communicate an error because this is a void function.
@@ -101,11 +127,13 @@ extern const unsigned long sys_call_table[];
 extern const unsigned long sys32_call_table[];
 extern const unsigned long sysn32_call_table[];
 
-static inline int __syscall_get_arch(void)
+static inline int syscall_get_arch(struct task_struct *task,
+				   struct pt_regs *regs)
 {
 	int arch = EM_MIPS;
 #ifdef CONFIG_64BIT
-	arch |=  __AUDIT_ARCH_64BIT;
+	if (!test_tsk_thread_flag(task, TIF_32BIT_REGS))
+		arch |= __AUDIT_ARCH_64BIT;
 #endif
 #if defined(__LITTLE_ENDIAN)
 	arch |=  __AUDIT_ARCH_LE;
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 24846f9053fe..d2d961d6cb86 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -116,6 +116,8 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_LOAD_WATCH		25	/* If set, load watch registers */
 #define TIF_SYSCALL_TRACEPOINT	26	/* syscall tracepoint instrumentation */
 #define TIF_32BIT_FPREGS	27	/* 32-bit floating point registers */
+#define TIF_USEDMSA		29	/* MSA has been used this quantum */
+#define TIF_MSA_CTX_LIVE	30	/* MSA context must be preserved */
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -133,10 +135,13 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_FPUBOUND		(1<<TIF_FPUBOUND)
 #define _TIF_LOAD_WATCH		(1<<TIF_LOAD_WATCH)
 #define _TIF_32BIT_FPREGS	(1<<TIF_32BIT_FPREGS)
+#define _TIF_USEDMSA		(1<<TIF_USEDMSA)
+#define _TIF_MSA_CTX_LIVE	(1<<TIF_MSA_CTX_LIVE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
+				 _TIF_SYSCALL_AUDIT | \
+				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
 
 /* work to do in syscall_trace_leave() */
 #define _TIF_WORK_SYSCALL_EXIT	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index f3fa3750f577..a10951090234 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -6,6 +6,7 @@
  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2014, Imagination Technologies Ltd.
  */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
@@ -13,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
+#include <asm/asm-eva.h>
 
 /*
  * The fs value determines whether argument validity checking should be
@@ -222,11 +224,44 @@ struct __large_struct { unsigned long buf[100]; };
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
+#ifndef CONFIG_EVA
+#define __get_kernel_common(val, size, ptr) __get_user_common(val, size, ptr)
+#else
+/*
+ * Kernel specific functions for EVA. We need to use normal load instructions
+ * to read data from kernel when operating in EVA mode. We use these macros to
+ * avoid redefining __get_user_asm for EVA.
+ */
+#undef _loadd
+#undef _loadw
+#undef _loadh
+#undef _loadb
 #ifdef CONFIG_32BIT
-#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr)
+#define _loadd			_loadw
+#else
+#define _loadd(reg, addr)	"ld " reg ", " addr
+#endif
+#define _loadw(reg, addr)	"lw " reg ", " addr
+#define _loadh(reg, addr)	"lh " reg ", " addr
+#define _loadb(reg, addr)	"lb " reg ", " addr
+
+#define __get_kernel_common(val, size, ptr)				\
+do {									\
+	switch (size) {							\
+	case 1: __get_data_asm(val, _loadb, ptr); break;		\
+	case 2: __get_data_asm(val, _loadh, ptr); break;		\
+	case 4: __get_data_asm(val, _loadw, ptr); break;		\
+	case 8: __GET_DW(val, _loadd, ptr); break;			\
+	default: __get_user_unknown(); break;				\
+	}								\
+} while (0)
+#endif
+
+#ifdef CONFIG_32BIT
+#define __GET_DW(val, insn, ptr) __get_data_asm_ll32(val, insn, ptr)
 #endif
 #ifdef CONFIG_64BIT
-#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr)
+#define __GET_DW(val, insn, ptr) __get_data_asm(val, insn, ptr)
 #endif
 
 extern void __get_user_unknown(void);
@@ -234,10 +269,10 @@ extern void __get_user_unknown(void);
 #define __get_user_common(val, size, ptr)				\
 do {									\
 	switch (size) {							\
-	case 1: __get_user_asm(val, "lb", ptr); break;			\
-	case 2: __get_user_asm(val, "lh", ptr); break;			\
-	case 4: __get_user_asm(val, "lw", ptr); break;			\
-	case 8: __GET_USER_DW(val, ptr); break;				\
+	case 1: __get_data_asm(val, user_lb, ptr); break;		\
+	case 2: __get_data_asm(val, user_lh, ptr); break;		\
+	case 4: __get_data_asm(val, user_lw, ptr); break;		\
+	case 8: __GET_DW(val, user_ld, ptr); break;			\
 	default: __get_user_unknown(); break;				\
 	}								\
 } while (0)
@@ -246,8 +281,12 @@ do {									\
 ({									\
 	int __gu_err;							\
 									\
-	__chk_user_ptr(ptr);						\
-	__get_user_common((x), size, ptr);				\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__get_kernel_common((x), size, ptr);			\
+	} else {							\
+		__chk_user_ptr(ptr);					\
+		__get_user_common((x), size, ptr);			\
+	}								\
 	__gu_err;							\
 })
 
@@ -257,18 +296,22 @@ do {									\
 	const __typeof__(*(ptr)) __user * __gu_ptr = (ptr);		\
 									\
 	might_fault();							\
-	if (likely(access_ok(VERIFY_READ,  __gu_ptr, size)))		\
-		__get_user_common((x), size, __gu_ptr);			\
+	if (likely(access_ok(VERIFY_READ,  __gu_ptr, size))) {		\
+		if (segment_eq(get_fs(), get_ds()))			\
+			__get_kernel_common((x), size, __gu_ptr);	\
+		else							\
+			__get_user_common((x), size, __gu_ptr);		\
+	}								\
 									\
 	__gu_err;							\
 })
 
-#define __get_user_asm(val, insn, addr)					\
+#define __get_data_asm(val, insn, addr)					\
 {									\
 	long __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
-	"1:	" insn "	%1, %3				\n"	\
+	"1:	"insn("%1", "%3")"				\n"	\
 	"2:							\n"	\
 	"	.insn						\n"	\
 	"	.section .fixup,\"ax\"				\n"	\
@@ -287,7 +330,7 @@ do {									\
 /*
  * Get a long long 64 using 32 bit registers.
  */
-#define __get_user_asm_ll32(val, addr)					\
+#define __get_data_asm_ll32(val, insn, addr)				\
 {									\
 	union {								\
 		unsigned long long	l;				\
@@ -295,8 +338,8 @@ do {									\
 	} __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
-	"1:	lw	%1, (%3)				\n"	\
-	"2:	lw	%D1, 4(%3)				\n"	\
+	"1:	" insn("%1", "(%3)")"				\n"	\
+	"2:	" insn("%D1", "4(%3)")"				\n"	\
 	"3:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
@@ -315,30 +358,73 @@ do {									\
 	(val) = __gu_tmp.t;						\
 }
 
+#ifndef CONFIG_EVA
+#define __put_kernel_common(ptr, size) __put_user_common(ptr, size)
+#else
+/*
+ * Kernel specific functions for EVA. We need to use normal load instructions
+ * to read data from kernel when operating in EVA mode. We use these macros to
+ * avoid redefining __get_data_asm for EVA.
+ */
+#undef _stored
+#undef _storew
+#undef _storeh
+#undef _storeb
+#ifdef CONFIG_32BIT
+#define _stored			_storew
+#else
+#define _stored(reg, addr)	"ld " reg ", " addr
+#endif
+
+#define _storew(reg, addr)	"sw " reg ", " addr
+#define _storeh(reg, addr)	"sh " reg ", " addr
+#define _storeb(reg, addr)	"sb " reg ", " addr
+
+#define __put_kernel_common(ptr, size)					\
+do {									\
+	switch (size) {							\
+	case 1: __put_data_asm(_storeb, ptr); break;			\
+	case 2: __put_data_asm(_storeh, ptr); break;			\
+	case 4: __put_data_asm(_storew, ptr); break;			\
+	case 8: __PUT_DW(_stored, ptr); break;				\
+	default: __put_user_unknown(); break;				\
+	}								\
+} while(0)
+#endif
+
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
 #ifdef CONFIG_32BIT
-#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
+#define __PUT_DW(insn, ptr) __put_data_asm_ll32(insn, ptr)
 #endif
 #ifdef CONFIG_64BIT
-#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
+#define __PUT_DW(insn, ptr) __put_data_asm(insn, ptr)
 #endif
 
+#define __put_user_common(ptr, size)					\
+do {									\
+	switch (size) {							\
+	case 1: __put_data_asm(user_sb, ptr); break;			\
+	case 2: __put_data_asm(user_sh, ptr); break;			\
+	case 4: __put_data_asm(user_sw, ptr); break;			\
+	case 8: __PUT_DW(user_sd, ptr); break;				\
+	default: __put_user_unknown(); break;				\
+	}								\
+} while (0)
+
 #define __put_user_nocheck(x, ptr, size)				\
 ({									\
 	__typeof__(*(ptr)) __pu_val;					\
 	int __pu_err = 0;						\
 									\
-	__chk_user_ptr(ptr);						\
 	__pu_val = (x);							\
-	switch (size) {							\
-	case 1: __put_user_asm("sb", ptr); break;			\
-	case 2: __put_user_asm("sh", ptr); break;			\
-	case 4: __put_user_asm("sw", ptr); break;			\
-	case 8: __PUT_USER_DW(ptr); break;				\
-	default: __put_user_unknown(); break;				\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__put_kernel_common(ptr, size);				\
+	} else {							\
+		__chk_user_ptr(ptr);					\
+		__put_user_common(ptr, size);				\
 	}								\
 	__pu_err;							\
 })
@@ -351,21 +437,19 @@ do {									\
 									\
 	might_fault();							\
 	if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size))) {	\
-		switch (size) {						\
-		case 1: __put_user_asm("sb", __pu_addr); break;		\
-		case 2: __put_user_asm("sh", __pu_addr); break;		\
-		case 4: __put_user_asm("sw", __pu_addr); break;		\
-		case 8: __PUT_USER_DW(__pu_addr); break;		\
-		default: __put_user_unknown(); break;			\
-		}							\
+		if (segment_eq(get_fs(), get_ds()))			\
+			__put_kernel_common(__pu_addr, size);		\
+		else							\
+			__put_user_common(__pu_addr, size);		\
 	}								\
+									\
 	__pu_err;							\
 })
 
-#define __put_user_asm(insn, ptr)					\
+#define __put_data_asm(insn, ptr)					\
 {									\
 	__asm__ __volatile__(						\
-	"1:	" insn "	%z2, %3		# __put_user_asm\n"	\
+	"1:	"insn("%z2", "%3")"	# __put_data_asm	\n"	\
 	"2:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
@@ -380,11 +464,11 @@ do {									\
 	  "i" (-EFAULT));						\
 }
 
-#define __put_user_asm_ll32(ptr)					\
+#define __put_data_asm_ll32(insn, ptr)					\
 {									\
 	__asm__ __volatile__(						\
-	"1:	sw	%2, (%3)	# __put_user_asm_ll32	\n"	\
-	"2:	sw	%D2, 4(%3)				\n"	\
+	"1:	"insn("%2", "(%3)")"	# __put_data_asm_ll32	\n"	\
+	"2:	"insn("%D2", "4(%3)")"				\n"	\
 	"3:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
@@ -403,6 +487,11 @@ do {									\
 extern void __put_user_unknown(void);
 
 /*
+ * ul{b,h,w} are macros and there are no equivalent macros for EVA.
+ * EVA unaligned access is handled in the ADE exception handler.
+ */
+#ifndef CONFIG_EVA
+/*
  * put_user_unaligned: - Write a simple value into user space.
  * @x:	 Value to copy to user space.
  * @ptr: Destination address, in user space.
@@ -504,7 +593,7 @@ extern void __get_user_unaligned_unknown(void);
 #define __get_user_unaligned_common(val, size, ptr)			\
 do {									\
 	switch (size) {							\
-	case 1: __get_user_asm(val, "lb", ptr); break;			\
+	case 1: __get_data_asm(val, "lb", ptr); break;			\
 	case 2: __get_user_unaligned_asm(val, "ulh", ptr); break;	\
 	case 4: __get_user_unaligned_asm(val, "ulw", ptr); break;	\
 	case 8: __GET_USER_UNALIGNED_DW(val, ptr); break;		\
@@ -531,7 +620,7 @@ do {									\
 	__gu_err;							\
 })
 
-#define __get_user_unaligned_asm(val, insn, addr)			\
+#define __get_data_unaligned_asm(val, insn, addr)			\
 {									\
 	long __gu_tmp;							\
 									\
@@ -594,19 +683,23 @@ do {									\
 #define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm("usd", ptr)
 #endif
 
+#define __put_user_unaligned_common(ptr, size)				\
+do {									\
+	switch (size) {							\
+	case 1: __put_data_asm("sb", ptr); break;			\
+	case 2: __put_user_unaligned_asm("ush", ptr); break;		\
+	case 4: __put_user_unaligned_asm("usw", ptr); break;		\
+	case 8: __PUT_USER_UNALIGNED_DW(ptr); break;			\
+	default: __put_user_unaligned_unknown(); break;			\
+} while (0)
+
 #define __put_user_unaligned_nocheck(x,ptr,size)			\
 ({									\
 	__typeof__(*(ptr)) __pu_val;					\
 	int __pu_err = 0;						\
 									\
 	__pu_val = (x);							\
-	switch (size) {							\
-	case 1: __put_user_asm("sb", ptr); break;			\
-	case 2: __put_user_unaligned_asm("ush", ptr); break;		\
-	case 4: __put_user_unaligned_asm("usw", ptr); break;		\
-	case 8: __PUT_USER_UNALIGNED_DW(ptr); break;			\
-	default: __put_user_unaligned_unknown(); break;			\
-	}								\
+	__put_user_unaligned_common(ptr, size);				\
 	__pu_err;							\
 })
 
@@ -616,15 +709,9 @@ do {									\
 	__typeof__(*(ptr)) __pu_val = (x);				\
 	int __pu_err = -EFAULT;						\
 									\
-	if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size))) {	\
-		switch (size) {						\
-		case 1: __put_user_asm("sb", __pu_addr); break;		\
-		case 2: __put_user_unaligned_asm("ush", __pu_addr); break; \
-		case 4: __put_user_unaligned_asm("usw", __pu_addr); break; \
-		case 8: __PUT_USER_UNALGINED_DW(__pu_addr); break;	\
-		default: __put_user_unaligned_unknown(); break;		\
-		}							\
-	}								\
+	if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size)))		\
+		__put_user_unaligned_common(__pu_addr, size);		\
+									\
 	__pu_err;							\
 })
 
@@ -669,6 +756,7 @@ do {									\
 }
 
 extern void __put_user_unaligned_unknown(void);
+#endif
 
 /*
  * We're generating jump to subroutines which will be outside the range of
@@ -693,6 +781,7 @@ extern void __put_user_unaligned_unknown(void);
 
 extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 
+#ifndef CONFIG_EVA
 #define __invoke_copy_to_user(to, from, n)				\
 ({									\
 	register void __user *__cu_to_r __asm__("$4");			\
@@ -711,6 +800,11 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 	__cu_len_r;							\
 })
 
+#define __invoke_copy_to_kernel(to, from, n)				\
+	__invoke_copy_to_user(to, from, n)
+
+#endif
+
 /*
  * __copy_to_user: - Copy a block of data into user space, with less checking.
  * @to:	  Destination address, in user space.
@@ -735,7 +829,12 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 	__cu_from = (from);						\
 	__cu_len = (n);							\
 	might_fault();							\
-	__cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \
+	if (segment_eq(get_fs(), get_ds()))				\
+		__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from,	\
+						   __cu_len);		\
+	else								\
+		__cu_len = __invoke_copy_to_user(__cu_to, __cu_from,	\
+						 __cu_len);		\
 	__cu_len;							\
 })
 
@@ -750,7 +849,12 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	__cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \
+	if (segment_eq(get_fs(), get_ds()))				\
+		__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from,	\
+						   __cu_len);		\
+	else								\
+		__cu_len = __invoke_copy_to_user(__cu_to, __cu_from,	\
+						 __cu_len);		\
 	__cu_len;							\
 })
 
@@ -763,8 +867,14 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	__cu_len = __invoke_copy_from_user_inatomic(__cu_to, __cu_from, \
-						    __cu_len);		\
+	if (segment_eq(get_fs(), get_ds()))				\
+		__cu_len = __invoke_copy_from_kernel_inatomic(__cu_to,	\
+							      __cu_from,\
+							      __cu_len);\
+	else								\
+		__cu_len = __invoke_copy_from_user_inatomic(__cu_to,	\
+							    __cu_from,	\
+							    __cu_len);	\
 	__cu_len;							\
 })
 
@@ -790,14 +900,23 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) {		\
-		might_fault();						\
-		__cu_len = __invoke_copy_to_user(__cu_to, __cu_from,	\
-						 __cu_len);		\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__cu_len = __invoke_copy_to_kernel(__cu_to,		\
+						   __cu_from,		\
+						   __cu_len);		\
+	} else {							\
+		if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) {       \
+			might_fault();                                  \
+			__cu_len = __invoke_copy_to_user(__cu_to,	\
+							 __cu_from,	\
+							 __cu_len);     \
+		}							\
 	}								\
 	__cu_len;							\
 })
 
+#ifndef CONFIG_EVA
+
 #define __invoke_copy_from_user(to, from, n)				\
 ({									\
 	register void *__cu_to_r __asm__("$4");				\
@@ -821,6 +940,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_len_r;							\
 })
 
+#define __invoke_copy_from_kernel(to, from, n)				\
+	__invoke_copy_from_user(to, from, n)
+
+/* For userland <-> userland operations */
+#define ___invoke_copy_in_user(to, from, n)				\
+	__invoke_copy_from_user(to, from, n)
+
+/* For kernel <-> kernel operations */
+#define ___invoke_copy_in_kernel(to, from, n)				\
+	__invoke_copy_from_user(to, from, n)
+
 #define __invoke_copy_from_user_inatomic(to, from, n)			\
 ({									\
 	register void *__cu_to_r __asm__("$4");				\
@@ -844,6 +974,97 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_len_r;							\
 })
 
+#define __invoke_copy_from_kernel_inatomic(to, from, n)			\
+	__invoke_copy_from_user_inatomic(to, from, n)			\
+
+#else
+
+/* EVA specific functions */
+
+extern size_t __copy_user_inatomic_eva(void *__to, const void *__from,
+				       size_t __n);
+extern size_t __copy_from_user_eva(void *__to, const void *__from,
+				   size_t __n);
+extern size_t __copy_to_user_eva(void *__to, const void *__from,
+				 size_t __n);
+extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
+
+#define __invoke_copy_from_user_eva_generic(to, from, n, func_ptr)	\
+({									\
+	register void *__cu_to_r __asm__("$4");				\
+	register const void __user *__cu_from_r __asm__("$5");		\
+	register long __cu_len_r __asm__("$6");				\
+									\
+	__cu_to_r = (to);						\
+	__cu_from_r = (from);						\
+	__cu_len_r = (n);						\
+	__asm__ __volatile__(						\
+	".set\tnoreorder\n\t"						\
+	__MODULE_JAL(func_ptr)						\
+	".set\tnoat\n\t"						\
+	__UA_ADDU "\t$1, %1, %2\n\t"					\
+	".set\tat\n\t"							\
+	".set\treorder"							\
+	: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)	\
+	:								\
+	: "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",	\
+	  DADDI_SCRATCH, "memory");					\
+	__cu_len_r;							\
+})
+
+#define __invoke_copy_to_user_eva_generic(to, from, n, func_ptr)	\
+({									\
+	register void *__cu_to_r __asm__("$4");				\
+	register const void __user *__cu_from_r __asm__("$5");		\
+	register long __cu_len_r __asm__("$6");				\
+									\
+	__cu_to_r = (to);						\
+	__cu_from_r = (from);						\
+	__cu_len_r = (n);						\
+	__asm__ __volatile__(						\
+	__MODULE_JAL(func_ptr)						\
+	: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)	\
+	:								\
+	: "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",	\
+	  DADDI_SCRATCH, "memory");					\
+	__cu_len_r;							\
+})
+
+/*
+ * Source or destination address is in userland. We need to go through
+ * the TLB
+ */
+#define __invoke_copy_from_user(to, from, n)				\
+	__invoke_copy_from_user_eva_generic(to, from, n, __copy_from_user_eva)
+
+#define __invoke_copy_from_user_inatomic(to, from, n)			\
+	__invoke_copy_from_user_eva_generic(to, from, n,		\
+					    __copy_user_inatomic_eva)
+
+#define __invoke_copy_to_user(to, from, n)				\
+	__invoke_copy_to_user_eva_generic(to, from, n, __copy_to_user_eva)
+
+#define ___invoke_copy_in_user(to, from, n)				\
+	__invoke_copy_from_user_eva_generic(to, from, n, __copy_in_user_eva)
+
+/*
+ * Source or destination address in the kernel. We are not going through
+ * the TLB
+ */
+#define __invoke_copy_from_kernel(to, from, n)				\
+	__invoke_copy_from_user_eva_generic(to, from, n, __copy_user)
+
+#define __invoke_copy_from_kernel_inatomic(to, from, n)			\
+	__invoke_copy_from_user_eva_generic(to, from, n, __copy_user_inatomic)
+
+#define __invoke_copy_to_kernel(to, from, n)				\
+	__invoke_copy_to_user_eva_generic(to, from, n, __copy_user)
+
+#define ___invoke_copy_in_kernel(to, from, n)				\
+	__invoke_copy_from_user_eva_generic(to, from, n, __copy_user)
+
+#endif /* CONFIG_EVA */
+
 /*
  * __copy_from_user: - Copy a block of data from user space, with less checking.
  * @to:	  Destination address, in kernel space.
@@ -901,10 +1122,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	if (access_ok(VERIFY_READ, __cu_from, __cu_len)) {		\
-		might_fault();						\
-		__cu_len = __invoke_copy_from_user(__cu_to, __cu_from,	\
-						   __cu_len);		\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__cu_len = __invoke_copy_from_kernel(__cu_to,		\
+						     __cu_from,		\
+						     __cu_len);		\
+	} else {							\
+		if (access_ok(VERIFY_READ, __cu_from, __cu_len)) {	\
+			might_fault();                                  \
+			__cu_len = __invoke_copy_from_user(__cu_to,	\
+							   __cu_from,	\
+							   __cu_len);   \
+		}							\
 	}								\
 	__cu_len;							\
 })
@@ -918,9 +1146,14 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	might_fault();							\
-	__cu_len = __invoke_copy_from_user(__cu_to, __cu_from,		\
-					   __cu_len);			\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from,	\
+						    __cu_len);		\
+	} else {							\
+		might_fault();						\
+		__cu_len = ___invoke_copy_in_user(__cu_to, __cu_from,	\
+						  __cu_len);		\
+	}								\
 	__cu_len;							\
 })
 
@@ -933,11 +1166,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
-	if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) &&	\
-		   access_ok(VERIFY_WRITE, __cu_to, __cu_len))) {	\
-		might_fault();						\
-		__cu_len = __invoke_copy_from_user(__cu_to, __cu_from,	\
-						   __cu_len);		\
+	if (segment_eq(get_fs(), get_ds())) {				\
+		__cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from,	\
+						    __cu_len);		\
+	} else {							\
+		if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) &&\
+			   access_ok(VERIFY_WRITE, __cu_to, __cu_len))) {\
+			might_fault();					\
+			__cu_len = ___invoke_copy_in_user(__cu_to,	\
+							  __cu_from,	\
+							  __cu_len);	\
+		}							\
 	}								\
 	__cu_len;							\
 })
@@ -1007,16 +1246,28 @@ __strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
 	long res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		"move\t$5, %2\n\t"
-		"move\t$6, %3\n\t"
-		__MODULE_JAL(__strncpy_from_user_nocheck_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (__to), "r" (__from), "r" (__len)
-		: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			"move\t$6, %3\n\t"
+			__MODULE_JAL(__strncpy_from_kernel_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (__to), "r" (__from), "r" (__len)
+			: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			"move\t$6, %3\n\t"
+			__MODULE_JAL(__strncpy_from_user_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (__to), "r" (__from), "r" (__len)
+			: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	}
 
 	return res;
 }
@@ -1044,16 +1295,28 @@ strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
 	long res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		"move\t$5, %2\n\t"
-		"move\t$6, %3\n\t"
-		__MODULE_JAL(__strncpy_from_user_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (__to), "r" (__from), "r" (__len)
-		: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			"move\t$6, %3\n\t"
+			__MODULE_JAL(__strncpy_from_kernel_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (__to), "r" (__from), "r" (__len)
+			: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			"move\t$6, %3\n\t"
+			__MODULE_JAL(__strncpy_from_user_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (__to), "r" (__from), "r" (__len)
+			: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+	}
 
 	return res;
 }
@@ -1063,14 +1326,24 @@ static inline long __strlen_user(const char __user *s)
 {
 	long res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		__MODULE_JAL(__strlen_user_nocheck_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (s)
-		: "$2", "$4", __UA_t0, "$31");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			__MODULE_JAL(__strlen_kernel_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s)
+			: "$2", "$4", __UA_t0, "$31");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			__MODULE_JAL(__strlen_user_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s)
+			: "$2", "$4", __UA_t0, "$31");
+	}
 
 	return res;
 }
@@ -1093,14 +1366,24 @@ static inline long strlen_user(const char __user *s)
 {
 	long res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		__MODULE_JAL(__strlen_user_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (s)
-		: "$2", "$4", __UA_t0, "$31");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			__MODULE_JAL(__strlen_kernel_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s)
+			: "$2", "$4", __UA_t0, "$31");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			__MODULE_JAL(__strlen_kernel_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s)
+			: "$2", "$4", __UA_t0, "$31");
+	}
 
 	return res;
 }
@@ -1110,15 +1393,26 @@ static inline long __strnlen_user(const char __user *s, long n)
 {
 	long res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		"move\t$5, %2\n\t"
-		__MODULE_JAL(__strnlen_user_nocheck_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (s), "r" (n)
-		: "$2", "$4", "$5", __UA_t0, "$31");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			__MODULE_JAL(__strnlen_kernel_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s), "r" (n)
+			: "$2", "$4", "$5", __UA_t0, "$31");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			__MODULE_JAL(__strnlen_user_nocheck_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s), "r" (n)
+			: "$2", "$4", "$5", __UA_t0, "$31");
+	}
 
 	return res;
 }
@@ -1142,14 +1436,25 @@ static inline long strnlen_user(const char __user *s, long n)
 	long res;
 
 	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		"move\t$5, %2\n\t"
-		__MODULE_JAL(__strnlen_user_asm)
-		"move\t%0, $2"
-		: "=r" (res)
-		: "r" (s), "r" (n)
-		: "$2", "$4", "$5", __UA_t0, "$31");
+	if (segment_eq(get_fs(), get_ds())) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			__MODULE_JAL(__strnlen_kernel_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s), "r" (n)
+			: "$2", "$4", "$5", __UA_t0, "$31");
+	} else {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, %2\n\t"
+			__MODULE_JAL(__strnlen_user_asm)
+			"move\t%0, $2"
+			: "=r" (res)
+			: "r" (s), "r" (n)
+			: "$2", "$4", "$5", __UA_t0, "$31");
+	}
 
 	return res;
 }
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index c33a9564fb41..53bb110b7378 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -115,6 +115,7 @@ Ip_u2u1msbu3(_ins);
 Ip_u1(_j);
 Ip_u1(_jal);
 Ip_u1(_jr);
+Ip_u1(_jr_hb);
 Ip_u2s3u1(_ld);
 Ip_u3u1u2(_ldx);
 Ip_u2s3u1(_ll);
@@ -123,7 +124,9 @@ Ip_u1s2(_lui);
 Ip_u2s3u1(_lw);
 Ip_u3u1u2(_lwx);
 Ip_u1u2u3(_mfc0);
+Ip_u2u1u3(_mftc0);
 Ip_u1u2u3(_mtc0);
+Ip_u1u2u3(_mttc0);
 Ip_u3u1u2(_or);
 Ip_u2u1u3(_ori);
 Ip_u2s3u1(_pref);
@@ -137,11 +140,13 @@ Ip_u2u1u3(_sra);
 Ip_u2u1u3(_srl);
 Ip_u3u1u2(_subu);
 Ip_u2s3u1(_sw);
+Ip_u1(_sync);
 Ip_u1(_syscall);
 Ip_0(_tlbp);
 Ip_0(_tlbr);
 Ip_0(_tlbwi);
 Ip_0(_tlbwr);
+Ip_u1(_wait);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
 
@@ -264,6 +269,8 @@ void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
 		   unsigned int bit, int lid);
 void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
 		   unsigned int bit, int lid);
+void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int reg1,
+		 unsigned int reg2, int lid);
 void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index b39ba25b41cc..ef3bbfea7e81 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -8,6 +8,7 @@
  * Copyright (C) 1996, 2000 by Ralf Baechle
  * Copyright (C) 2006 by Thiemo Seufer
  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  */
 #ifndef _UAPI_ASM_INST_H
 #define _UAPI_ASM_INST_H
@@ -73,10 +74,16 @@ enum spec2_op {
 enum spec3_op {
 	ext_op, dextm_op, dextu_op, dext_op,
 	ins_op, dinsm_op, dinsu_op, dins_op,
-	lx_op = 0x0a,
-	bshfl_op = 0x20,
-	dbshfl_op = 0x24,
-	rdhwr_op = 0x3b
+	lx_op     = 0x0a, lwle_op   = 0x19,
+	lwre_op   = 0x1a, cachee_op = 0x1b,
+	sbe_op    = 0x1c, she_op    = 0x1d,
+	sce_op    = 0x1e, swe_op    = 0x1f,
+	bshfl_op  = 0x20, swle_op   = 0x21,
+	swre_op   = 0x22, prefe_op  = 0x23,
+	dbshfl_op = 0x24, lbue_op   = 0x28,
+	lhue_op   = 0x29, lbe_op    = 0x2c,
+	lhe_op    = 0x2d, lle_op    = 0x2e,
+	lwe_op    = 0x2f, rdhwr_op  = 0x3b
 };
 
 /*
@@ -101,7 +108,8 @@ enum cop_op {
 	cfc_op	      = 0x02, mfhc_op	    = 0x03,
 	mtc_op        = 0x04, dmtc_op	    = 0x05,
 	ctc_op	      = 0x06, mthc_op	    = 0x07,
-	bc_op	      = 0x08, cop_op	    = 0x10,
+	bc_op	      = 0x08, mftr_op	    = 0x08,
+	mttr_op	      = 0x0c, cop_op	    = 0x10,
 	copm_op	      = 0x18
 };
 
@@ -118,7 +126,8 @@ enum bcop_op {
 enum cop0_coi_func {
 	tlbr_op	      = 0x01, tlbwi_op	    = 0x02,
 	tlbwr_op      = 0x06, tlbp_op	    = 0x08,
-	rfe_op	      = 0x10, eret_op	    = 0x18
+	rfe_op	      = 0x10, eret_op	    = 0x18,
+	wait_op       = 0x20,
 };
 
 /*
@@ -195,6 +204,13 @@ enum lx_func {
 };
 
 /*
+ * hint/re field for jr instructions.
+ */
+enum jr_hint {
+	jr_hb_hint = 0x10,
+};
+
+/*
  * (microMIPS) Major opcodes.
  */
 enum mm_major_op {
@@ -294,7 +310,9 @@ enum mm_32axf_minor_op {
 	mm_tlbwr_op = 0x0cd,
 	mm_jalrs_op = 0x13c,
 	mm_jalrshb_op = 0x17c,
+	mm_sync_op = 0x1ad,
 	mm_syscall_op = 0x22d,
+	mm_wait_op = 0x24d,
 	mm_eret_op = 0x3cd,
 };
 
@@ -592,6 +610,15 @@ struct v_format {				/* MDMX vector format */
 	;)))))))
 };
 
+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,
+	;)))))
+};
+
 /*
  * microMIPS instruction formats (32-bit length)
  *
@@ -863,6 +890,7 @@ union mips_instruction {
 	struct b_format b_format;
 	struct ps_format ps_format;
 	struct v_format v_format;
+	struct spec3_format spec3_format;
 	struct fb_format fb_format;
 	struct fp0_format fp0_format;
 	struct mm_fp0_format mm_fp0_format;
diff --git a/arch/mips/include/uapi/asm/sigcontext.h b/arch/mips/include/uapi/asm/sigcontext.h
index 6c9906f59c6e..681c17603a48 100644
--- a/arch/mips/include/uapi/asm/sigcontext.h
+++ b/arch/mips/include/uapi/asm/sigcontext.h
@@ -12,6 +12,10 @@
 #include <linux/types.h>
 #include <asm/sgidefs.h>
 
+/* Bits which may be set in sc_used_math */
+#define USEDMATH_FP	(1 << 0)
+#define USEDMATH_MSA	(1 << 1)
+
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 
 /*
@@ -37,6 +41,8 @@ struct sigcontext {
 	unsigned long		sc_lo2;
 	unsigned long		sc_hi3;
 	unsigned long		sc_lo3;
+	unsigned long long	sc_msaregs[32];	/* Most significant 64 bits */
+	unsigned long		sc_msa_csr;
 };
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
@@ -70,6 +76,8 @@ struct sigcontext {
 	__u32	sc_used_math;
 	__u32	sc_dsp;
 	__u32	sc_reserved;
+	__u64	sc_msaregs[32];
+	__u32	sc_msa_csr;
 };
 
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 26c6175e1379..277dab301cea 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMTC)	+= smtc.o smtc-asm.o smtc-proc.o
 obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
+obj-$(CONFIG_MIPS_CPS)		+= smp-cps.o cps-vec.o
+obj-$(CONFIG_MIPS_GIC_IPI)	+= smp-gic.o
 obj-$(CONFIG_CPU_MIPSR2)	+= spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
@@ -102,6 +104,9 @@ obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_mipsxx.o
 
 obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
 
+obj-$(CONFIG_MIPS_CM)		+= mips-cm.o
+obj-$(CONFIG_MIPS_CPC)		+= mips-cpc.o
+
 #
 # DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not
 # safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 0c2e853c3db4..0ea75c244b48 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -16,6 +16,7 @@
 #include <linux/suspend.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
+#include <asm/smp-cps.h>
 
 #include <linux/kvm_host.h>
 
@@ -168,6 +169,72 @@ void output_thread_fpu_defines(void)
 	OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]);
 	OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]);
 
+	/* the least significant 64 bits of each FP register */
+	OFFSET(THREAD_FPR0_LS64, task_struct,
+	       thread.fpu.fpr[0].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR1_LS64, task_struct,
+	       thread.fpu.fpr[1].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR2_LS64, task_struct,
+	       thread.fpu.fpr[2].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR3_LS64, task_struct,
+	       thread.fpu.fpr[3].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR4_LS64, task_struct,
+	       thread.fpu.fpr[4].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR5_LS64, task_struct,
+	       thread.fpu.fpr[5].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR6_LS64, task_struct,
+	       thread.fpu.fpr[6].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR7_LS64, task_struct,
+	       thread.fpu.fpr[7].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR8_LS64, task_struct,
+	       thread.fpu.fpr[8].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR9_LS64, task_struct,
+	       thread.fpu.fpr[9].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR10_LS64, task_struct,
+	       thread.fpu.fpr[10].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR11_LS64, task_struct,
+	       thread.fpu.fpr[11].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR12_LS64, task_struct,
+	       thread.fpu.fpr[12].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR13_LS64, task_struct,
+	       thread.fpu.fpr[13].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR14_LS64, task_struct,
+	       thread.fpu.fpr[14].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR15_LS64, task_struct,
+	       thread.fpu.fpr[15].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR16_LS64, task_struct,
+	       thread.fpu.fpr[16].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR17_LS64, task_struct,
+	       thread.fpu.fpr[17].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR18_LS64, task_struct,
+	       thread.fpu.fpr[18].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR19_LS64, task_struct,
+	       thread.fpu.fpr[19].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR20_LS64, task_struct,
+	       thread.fpu.fpr[20].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR21_LS64, task_struct,
+	       thread.fpu.fpr[21].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR22_LS64, task_struct,
+	       thread.fpu.fpr[22].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR23_LS64, task_struct,
+	       thread.fpu.fpr[23].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR24_LS64, task_struct,
+	       thread.fpu.fpr[24].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR25_LS64, task_struct,
+	       thread.fpu.fpr[25].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR26_LS64, task_struct,
+	       thread.fpu.fpr[26].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR27_LS64, task_struct,
+	       thread.fpu.fpr[27].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR28_LS64, task_struct,
+	       thread.fpu.fpr[28].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR29_LS64, task_struct,
+	       thread.fpu.fpr[29].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR30_LS64, task_struct,
+	       thread.fpu.fpr[30].val64[FPR_IDX(64, 0)]);
+	OFFSET(THREAD_FPR31_LS64, task_struct,
+	       thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
+
 	OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
 	BLANK();
 }
@@ -228,6 +295,7 @@ void output_sc_defines(void)
 	OFFSET(SC_LO2, sigcontext, sc_lo2);
 	OFFSET(SC_HI3, sigcontext, sc_hi3);
 	OFFSET(SC_LO3, sigcontext, sc_lo3);
+	OFFSET(SC_MSAREGS, sigcontext, sc_msaregs);
 	BLANK();
 }
 #endif
@@ -242,6 +310,7 @@ void output_sc_defines(void)
 	OFFSET(SC_MDLO, sigcontext, sc_mdlo);
 	OFFSET(SC_PC, sigcontext, sc_pc);
 	OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr);
+	OFFSET(SC_MSAREGS, sigcontext, sc_msaregs);
 	BLANK();
 }
 #endif
@@ -253,6 +322,7 @@ void output_sc32_defines(void)
 	OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs);
 	OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr);
 	OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir);
+	OFFSET(SC32_MSAREGS, sigcontext32, sc_msaregs);
 	BLANK();
 }
 #endif
@@ -397,3 +467,15 @@ void output_kvm_defines(void)
 	OFFSET(COP0_STATUS, mips_coproc, reg[MIPS_CP0_STATUS][0]);
 	BLANK();
 }
+
+#ifdef CONFIG_MIPS_CPS
+void output_cps_defines(void)
+{
+	COMMENT(" MIPS CPS offsets. ");
+	OFFSET(BOOTCFG_CORE, boot_config, core);
+	OFFSET(BOOTCFG_VPE, boot_config, vpe);
+	OFFSET(BOOTCFG_PC, boot_config, pc);
+	OFFSET(BOOTCFG_SP, boot_config, sp);
+	OFFSET(BOOTCFG_GP, boot_config, gp);
+}
+#endif
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
new file mode 100644
index 000000000000..d873fabe61cc
--- /dev/null
+++ b/arch/mips/kernel/cps-vec.S
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+
+#define GCR_CL_COHERENCE_OFS 0x2008
+
+.section .text.cps-vec
+.balign 0x1000
+.set noreorder
+
+LEAF(mips_cps_core_entry)
+	/*
+	 * These first 8 bytes will be patched by cps_smp_setup to load the
+	 * base address of the CM GCRs into register v1.
+	 */
+	.quad	0
+
+	/* Check whether we're here due to an NMI */
+	mfc0	k0, CP0_STATUS
+	and	k0, t0, ST0_NMI
+	beqz	k0, not_nmi
+	 nop
+
+	/* This is an NMI */
+	la	k0, nmi_handler
+	jr	k0
+	 nop
+
+not_nmi:
+	/* Setup Cause */
+	li	t0, CAUSEF_IV
+	mtc0	t0, CP0_CAUSE
+
+	/* Setup Status */
+	li	t0, ST0_CU1 | ST0_CU0
+	mtc0	t0, CP0_STATUS
+
+	/*
+	 * Clear the bits used to index the caches. Note that the architecture
+	 * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
+	 * be valid for all MIPS32 CPUs, even those for which said writes are
+	 * unnecessary.
+	 */
+	mtc0	zero, CP0_TAGLO, 0
+	mtc0	zero, CP0_TAGHI, 0
+	mtc0	zero, CP0_TAGLO, 2
+	mtc0	zero, CP0_TAGHI, 2
+	ehb
+
+	/* Primary cache configuration is indicated by Config1 */
+	mfc0	v0, CP0_CONFIG, 1
+
+	/* Detect I-cache line size */
+	_EXT	t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
+	beqz	t0, icache_done
+	 li	t1, 2
+	sllv	t0, t1, t0
+
+	/* Detect I-cache size */
+	_EXT	t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
+	xori	t2, t1, 0x7
+	beqz	t2, 1f
+	 li	t3, 32
+	addi	t1, t1, 1
+	sllv	t1, t3, t1
+1:	/* At this point t1 == I-cache sets per way */
+	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
+	addi	t2, t2, 1
+	mul	t1, t1, t0
+	mul	t1, t1, t2
+
+	li	a0, KSEG0
+	add	a1, a0, t1
+1:	cache	Index_Store_Tag_I, 0(a0)
+	add	a0, a0, t0
+	bne	a0, a1, 1b
+	 nop
+icache_done:
+
+	/* Detect D-cache line size */
+	_EXT	t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
+	beqz	t0, dcache_done
+	 li	t1, 2
+	sllv	t0, t1, t0
+
+	/* Detect D-cache size */
+	_EXT	t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
+	xori	t2, t1, 0x7
+	beqz	t2, 1f
+	 li	t3, 32
+	addi	t1, t1, 1
+	sllv	t1, t3, t1
+1:	/* At this point t1 == D-cache sets per way */
+	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
+	addi	t2, t2, 1
+	mul	t1, t1, t0
+	mul	t1, t1, t2
+
+	li	a0, KSEG0
+	addu	a1, a0, t1
+	subu	a1, a1, t0
+1:	cache	Index_Store_Tag_D, 0(a0)
+	bne	a0, a1, 1b
+	 add	a0, a0, t0
+dcache_done:
+
+	/* Set Kseg0 cacheable, coherent, write-back, write-allocate */
+	mfc0	t0, CP0_CONFIG
+	ori	t0, 0x7
+	xori	t0, 0x2
+	mtc0	t0, CP0_CONFIG
+	ehb
+
+	/* Enter the coherent domain */
+	li	t0, 0xff
+	sw	t0, GCR_CL_COHERENCE_OFS(v1)
+	ehb
+
+	/* Jump to kseg0 */
+	la	t0, 1f
+	jr	t0
+	 nop
+
+1:	/* We're up, cached & coherent */
+
+	/*
+	 * TODO: We should check the VPE number we intended to boot here, and
+	 *       if non-zero we should start that VPE and stop this one. For
+	 *       the moment this doesn't matter since CPUs are brought up
+	 *       sequentially and in order, but once hotplug is implemented
+	 *       this will need revisiting.
+	 */
+
+	/* Off we go! */
+	la	t0, mips_cps_bootcfg
+	lw	t1, BOOTCFG_PC(t0)
+	lw	gp, BOOTCFG_GP(t0)
+	lw	sp, BOOTCFG_SP(t0)
+	jr	t1
+	 nop
+	END(mips_cps_core_entry)
+
+.org 0x200
+LEAF(excep_tlbfill)
+	b	.
+	 nop
+	END(excep_tlbfill)
+
+.org 0x280
+LEAF(excep_xtlbfill)
+	b	.
+	 nop
+	END(excep_xtlbfill)
+
+.org 0x300
+LEAF(excep_cache)
+	b	.
+	 nop
+	END(excep_cache)
+
+.org 0x380
+LEAF(excep_genex)
+	b	.
+	 nop
+	END(excep_genex)
+
+.org 0x400
+LEAF(excep_intex)
+	b	.
+	 nop
+	END(excep_intex)
+
+.org 0x480
+LEAF(excep_ejtag)
+	la	k0, ejtag_debug_handler
+	jr	k0
+	 nop
+	END(excep_ejtag)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 530f832de02c..e225b0d369e8 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -23,6 +23,7 @@
 #include <asm/cpu-type.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
+#include <asm/msa.h>
 #include <asm/watch.h>
 #include <asm/elf.h>
 #include <asm/spram.h>
@@ -126,6 +127,20 @@ static inline int __cpu_has_fpu(void)
 	return ((cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE);
 }
 
+static inline unsigned long cpu_get_msa_id(void)
+{
+	unsigned long status, conf5, msa_id;
+
+	status = read_c0_status();
+	__enable_fpu(FPU_64BIT);
+	conf5 = read_c0_config5();
+	enable_msa();
+	msa_id = read_msa_ir();
+	write_c0_config5(conf5);
+	write_c0_status(status);
+	return msa_id;
+}
+
 static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
 {
 #ifdef __NEED_VMBITS_PROBE
@@ -166,11 +181,12 @@ static char unknown_isa[] = KERN_ERR \
 static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
 	unsigned int config6;
-	/*
-	 * Config6 is implementation dependent and it's currently only
-	 * used by proAptiv
-	 */
-	if (c->cputype == CPU_PROAPTIV) {
+
+	/* It's implementation dependent how the FTLB can be enabled */
+	switch (c->cputype) {
+	case CPU_PROAPTIV:
+	case CPU_P5600:
+		/* proAptiv & related cores use Config6 to enable the FTLB */
 		config6 = read_c0_config6();
 		if (enable)
 			/* Enable FTLB */
@@ -179,6 +195,7 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 			/* Disable FTLB */
 			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
 		back_to_back_c0_hazard();
+		break;
 	}
 }
 
@@ -301,6 +318,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_VZ;
 	if (config3 & MIPS_CONF3_SC)
 		c->options |= MIPS_CPU_SEGMENTS;
+	if (config3 & MIPS_CONF3_MSA)
+		c->ases |= MIPS_ASE_MSA;
 
 	return config3 & MIPS_CONF_M;
 }
@@ -367,6 +386,9 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
 	config5 &= ~MIPS_CONF5_UFR;
 	write_c0_config5(config5);
 
+	if (config5 & MIPS_CONF5_EVA)
+		c->options |= MIPS_CPU_EVA;
+
 	return config5 & MIPS_CONF_M;
 }
 
@@ -398,8 +420,10 @@ static void decode_configs(struct cpuinfo_mips *c)
 
 	mips_probe_watch_registers(c);
 
+#ifndef CONFIG_MIPS_CPS
 	if (cpu_has_mips_r2)
 		c->core = read_c0_ebase() & 0x3ff;
+#endif
 }
 
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
@@ -806,7 +830,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 		__cpu_name[cpu] = "MIPS 1004Kc";
 		break;
 	case PRID_IMP_1074K:
-		c->cputype = CPU_74K;
+		c->cputype = CPU_1074K;
 		__cpu_name[cpu] = "MIPS 1074Kc";
 		break;
 	case PRID_IMP_INTERAPTIV_UP:
@@ -825,6 +849,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 		c->cputype = CPU_PROAPTIV;
 		__cpu_name[cpu] = "MIPS proAptiv (multi)";
 		break;
+	case PRID_IMP_P5600:
+		c->cputype = CPU_P5600;
+		__cpu_name[cpu] = "MIPS P5600";
+		break;
 	}
 
 	decode_configs(c);
@@ -1176,6 +1204,12 @@ void cpu_probe(void)
 	else
 		c->srsets = 1;
 
+	if (cpu_has_msa) {
+		c->msa_id = cpu_get_msa_id();
+		WARN(c->msa_id & MSA_IR_WRPF,
+		     "Vector register partitioning unimplemented!");
+	}
+
 	cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
@@ -1192,4 +1226,6 @@ void cpu_report(void)
 		smp_processor_id(), c->processor_id, cpu_name_string());
 	if (c->options & MIPS_CPU_FPU)
 		printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
+	if (cpu_has_msa)
+		pr_info("MSA revision is: %08x\n", c->msa_id);
 }
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 185ba258361b..ddcc3500248d 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -90,6 +90,7 @@ static inline void ftrace_dyn_arch_init_insns(void)
 static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
 {
 	int faulted;
+	mm_segment_t old_fs;
 
 	/* *(unsigned int *)ip = new_code; */
 	safe_store_code(new_code, ip, faulted);
@@ -97,7 +98,10 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
 	if (unlikely(faulted))
 		return -EFAULT;
 
+	old_fs = get_fs();
+	set_fs(get_ds());
 	flush_icache_range(ip, ip + 8);
+	set_fs(old_fs);
 
 	return 0;
 }
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index d84f6a509502..7365cd6be702 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -475,8 +475,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	BUILD_HANDLER cpu cpu sti silent		/* #11 */
 	BUILD_HANDLER ov ov sti silent			/* #12 */
 	BUILD_HANDLER tr tr sti silent			/* #13 */
+	BUILD_HANDLER msa_fpe msa_fpe sti silent	/* #14 */
 	BUILD_HANDLER fpe fpe fpe silent		/* #15 */
 	BUILD_HANDLER ftlb ftlb none silent		/* #16 */
+	BUILD_HANDLER msa msa sti silent		/* #21 */
 	BUILD_HANDLER mdmx mdmx sti silent		/* #22 */
 #ifdef	CONFIG_HARDWARE_WATCHPOINTS
 	/*
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 7b6a5b3e3acf..e712dcf18b2d 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -175,8 +175,8 @@ NESTED(smp_bootstrap, 16, sp)
 	DMT	10	# dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
 	jal	mips_ihb
 #endif /* CONFIG_MIPS_MT_SMTC */
-	setup_c0_status_sec
 	smp_slave_setup
+	setup_c0_status_sec
 #ifdef CONFIG_MIPS_MT_SMTC
 	andi	t2, t2, VPECONTROL_TE
 	beqz	t2, 2f
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 3553243bf9d6..4b1554b3f5a6 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -11,6 +11,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#include <linux/cpuidle.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
@@ -184,8 +185,10 @@ void __init check_wait(void)
 	case CPU_24K:
 	case CPU_34K:
 	case CPU_1004K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 		cpu_wait = r4k_wait;
 		if (read_c0_config7() & MIPS_CONF7_WII)
 			cpu_wait = r4k_wait_irqoff;
@@ -239,7 +242,7 @@ static void smtc_idle_hook(void)
 #endif
 }
 
-void arch_cpu_idle(void)
+static void mips_cpu_idle(void)
 {
 	smtc_idle_hook();
 	if (cpu_wait)
@@ -247,3 +250,20 @@ void arch_cpu_idle(void)
 	else
 		local_irq_enable();
 }
+
+void arch_cpu_idle(void)
+{
+	if (cpuidle_idle_call())
+		mips_cpu_idle();
+}
+
+#ifdef CONFIG_CPU_IDLE
+
+int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
+{
+	mips_cpu_idle();
+	return index;
+}
+
+#endif
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 5b5ddb231f26..8520dad6d4e3 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -16,7 +16,6 @@
 #include <asm/gic.h>
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/gcmpregs.h>
 #include <linux/hardirq.h>
 #include <asm-generic/bitops/find.h>
 
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index fcaac2f132f0..7afcc2f22c0d 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -32,6 +32,7 @@
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
+#include <asm/uaccess.h>
 
 static struct hard_trap_info {
 	unsigned char tt;	/* Trap type code for MIPS R3xxx and R4xxx */
@@ -208,7 +209,14 @@ void arch_kgdb_breakpoint(void)
 
 static void kgdb_call_nmi_hook(void *ignored)
 {
+	mm_segment_t old_fs;
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+
 	kgdb_nmicallback(raw_smp_processor_id(), NULL);
+
+	set_fs(old_fs);
 }
 
 void kgdb_roundup_cpus(unsigned long flags)
@@ -282,6 +290,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
 	struct die_args *args = (struct die_args *)ptr;
 	struct pt_regs *regs = args->regs;
 	int trap = (regs->cp0_cause & 0x7c) >> 2;
+	mm_segment_t old_fs;
 
 #ifdef CONFIG_KPROBES
 	/*
@@ -296,11 +305,17 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
 	if (user_mode(regs))
 		return NOTIFY_DONE;
 
+	/* Kernel mode. Set correct address limit */
+	old_fs = get_fs();
+	set_fs(get_ds());
+
 	if (atomic_read(&kgdb_active) != -1)
 		kgdb_nmicallback(smp_processor_id(), regs);
 
-	if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs))
+	if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) {
+		set_fs(old_fs);
 		return NOTIFY_DONE;
+	}
 
 	if (atomic_read(&kgdb_setting_breakpoint))
 		if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
@@ -310,6 +325,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
 	local_irq_enable();
 	__flush_cache_all();
 
+	set_fs(old_fs);
 	return NOTIFY_STOP;
 }
 
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
new file mode 100644
index 000000000000..f76f7a08412d
--- /dev/null
+++ b/arch/mips/kernel/mips-cm.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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/errno.h>
+
+#include <asm/mips-cm.h>
+#include <asm/mipsregs.h>
+
+void __iomem *mips_cm_base;
+void __iomem *mips_cm_l2sync_base;
+
+phys_t __mips_cm_phys_base(void)
+{
+	u32 config3 = read_c0_config3();
+	u32 cmgcr;
+
+	/* Check the CMGCRBase register is implemented */
+	if (!(config3 & MIPS_CONF3_CMGCR))
+		return 0;
+
+	/* Read the address from CMGCRBase */
+	cmgcr = read_c0_cmgcrbase();
+	return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32);
+}
+
+phys_t mips_cm_phys_base(void)
+	__attribute__((weak, alias("__mips_cm_phys_base")));
+
+phys_t __mips_cm_l2sync_phys_base(void)
+{
+	u32 base_reg;
+
+	/*
+	 * If the L2-only sync region is already enabled then leave it at it's
+	 * current location.
+	 */
+	base_reg = read_gcr_l2_only_sync_base();
+	if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK)
+		return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK;
+
+	/* Default to following the CM */
+	return mips_cm_phys_base() + MIPS_CM_GCR_SIZE;
+}
+
+phys_t mips_cm_l2sync_phys_base(void)
+	__attribute__((weak, alias("__mips_cm_l2sync_phys_base")));
+
+static void mips_cm_probe_l2sync(void)
+{
+	unsigned major_rev;
+	phys_t addr;
+
+	/* L2-only sync was introduced with CM major revision 6 */
+	major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >>
+		CM_GCR_REV_MAJOR_SHF;
+	if (major_rev < 6)
+		return;
+
+	/* Find a location for the L2 sync region */
+	addr = mips_cm_l2sync_phys_base();
+	BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK) != addr);
+	if (!addr)
+		return;
+
+	/* Set the region base address & enable it */
+	write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK);
+
+	/* Map the region */
+	mips_cm_l2sync_base = ioremap_nocache(addr, MIPS_CM_L2SYNC_SIZE);
+}
+
+int mips_cm_probe(void)
+{
+	phys_t addr;
+	u32 base_reg;
+
+	addr = mips_cm_phys_base();
+	BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
+	if (!addr)
+		return -ENODEV;
+
+	mips_cm_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE);
+	if (!mips_cm_base)
+		return -ENXIO;
+
+	/* sanity check that we're looking at a CM */
+	base_reg = read_gcr_base();
+	if ((base_reg & CM_GCR_BASE_GCRBASE_MSK) != addr) {
+		pr_err("GCRs appear to have been moved (expected them at 0x%08lx)!\n",
+		       (unsigned long)addr);
+		mips_cm_base = NULL;
+		return -ENODEV;
+	}
+
+	/* set default target to memory */
+	base_reg &= ~CM_GCR_BASE_CMDEFTGT_MSK;
+	base_reg |= CM_GCR_BASE_CMDEFTGT_MEM;
+	write_gcr_base(base_reg);
+
+	/* disable CM regions */
+	write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+	write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+	write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+	write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+	write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+	write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+	write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+	write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+
+	/* probe for an L2-only sync region */
+	mips_cm_probe_l2sync();
+
+	return 0;
+}
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
new file mode 100644
index 000000000000..c9dc67402969
--- /dev/null
+++ b/arch/mips/kernel/mips-cpc.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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/errno.h>
+
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+
+void __iomem *mips_cpc_base;
+
+phys_t __weak mips_cpc_phys_base(void)
+{
+	u32 cpc_base;
+
+	if (!mips_cm_present())
+		return 0;
+
+	if (!(read_gcr_cpc_status() & CM_GCR_CPC_STATUS_EX_MSK))
+		return 0;
+
+	/* If the CPC is already enabled, leave it so */
+	cpc_base = read_gcr_cpc_base();
+	if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK)
+		return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK;
+
+	/* Otherwise, give it the default address & enable it */
+	cpc_base = mips_cpc_default_phys_base();
+	write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK);
+	return cpc_base;
+}
+
+int mips_cpc_probe(void)
+{
+	phys_t addr;
+
+	addr = mips_cpc_phys_base();
+	if (!addr)
+		return -ENODEV;
+
+	mips_cpc_base = ioremap_nocache(addr, 0x8000);
+	if (!mips_cpc_base)
+		return -ENXIO;
+
+	return 0;
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 6e58e97fcd39..2607c3a4ff7e 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -16,12 +16,20 @@
 #include <asm/ftrace.h>
 
 extern void *__bzero(void *__s, size_t __count);
+extern long __strncpy_from_kernel_nocheck_asm(char *__to,
+					      const char *__from, long __len);
+extern long __strncpy_from_kernel_asm(char *__to, const char *__from,
+				      long __len);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
 					    const char *__from, long __len);
 extern long __strncpy_from_user_asm(char *__to, const char *__from,
 				    long __len);
+extern long __strlen_kernel_nocheck_asm(const char *s);
+extern long __strlen_kernel_asm(const char *s);
 extern long __strlen_user_nocheck_asm(const char *s);
 extern long __strlen_user_asm(const char *s);
+extern long __strnlen_kernel_nocheck_asm(const char *s);
+extern long __strnlen_kernel_asm(const char *s);
 extern long __strnlen_user_nocheck_asm(const char *s);
 extern long __strnlen_user_asm(const char *s);
 
@@ -43,17 +51,31 @@ EXPORT_SYMBOL(copy_page);
  */
 EXPORT_SYMBOL(__copy_user);
 EXPORT_SYMBOL(__copy_user_inatomic);
+#ifdef CONFIG_EVA
+EXPORT_SYMBOL(__copy_from_user_eva);
+EXPORT_SYMBOL(__copy_in_user_eva);
+EXPORT_SYMBOL(__copy_to_user_eva);
+EXPORT_SYMBOL(__copy_user_inatomic_eva);
+#endif
 EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strncpy_from_kernel_asm);
 EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
 EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strlen_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strlen_kernel_asm);
 EXPORT_SYMBOL(__strlen_user_nocheck_asm);
 EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strnlen_kernel_asm);
 EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
 EXPORT_SYMBOL(__strnlen_user_asm);
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
-EXPORT_SYMBOL(__csum_partial_copy_user);
+EXPORT_SYMBOL(__csum_partial_copy_kernel);
+EXPORT_SYMBOL(__csum_partial_copy_to_user);
+EXPORT_SYMBOL(__csum_partial_copy_from_user);
 
 EXPORT_SYMBOL(invalid_pte_table);
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 24cdf64789c3..17594b81a5d2 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1442,6 +1442,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 #endif
 		break;
 	case CPU_74K:
+	case CPU_1074K:
 		if (IS_BOTH_COUNTERS_74K_EVENT(base_id))
 			raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
 		else
@@ -1584,6 +1585,11 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &mipsxxcore_event_map;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map;
 		break;
+	case CPU_1074K:
+		mipspmu.name = "mips/1074K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
+		break;
 	case CPU_LOONGSON1:
 		mipspmu.name = "mips/loongson1";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 00d20974b3e7..f0df7fde37c5 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -95,6 +95,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 	if (cpu_has_mipsmt)	seq_printf(m, "%s", " mt");
 	if (cpu_has_mmips)	seq_printf(m, "%s", " micromips");
 	if (cpu_has_vz)		seq_printf(m, "%s", " vz");
+	if (cpu_has_msa)	seq_printf(m, "%s", " msa");
+	if (cpu_has_eva)	seq_printf(m, "%s", " eva");
 	seq_printf(m, "\n");
 
 	if (cpu_has_mmips) {
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6ae540e133b2..60e39dc7f1eb 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -32,6 +32,7 @@
 #include <asm/cpu.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
+#include <asm/msa.h>
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
@@ -65,6 +66,8 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 	clear_used_math();
 	clear_fpu_owner();
 	init_dsp();
+	clear_thread_flag(TIF_MSA_CTX_LIVE);
+	disable_msa();
 	regs->cp0_epc = pc;
 	regs->regs[29] = sp;
 }
@@ -89,7 +92,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
 	preempt_disable();
 
-	if (is_fpu_owner())
+	if (is_msa_enabled())
+		save_msa(p);
+	else if (is_fpu_owner())
 		save_fp(p);
 
 	if (cpu_has_dsp)
@@ -157,7 +162,13 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 /* Fill in the fpu structure for a core dump.. */
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
 {
-	memcpy(r, &current->thread.fpu, sizeof(current->thread.fpu));
+	int i;
+
+	for (i = 0; i < NUM_FPU_REGS; i++)
+		memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
+
+	memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
+	       sizeof(current->thread.fpu.fcr31));
 
 	return 1;
 }
@@ -192,7 +203,13 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 
 int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
 {
-	memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));
+	int i;
+
+	for (i = 0; i < NUM_FPU_REGS; i++)
+		memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
+
+	memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
+	       sizeof(t->thread.fpu.fcr31));
 
 	return 1;
 }
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 7da9b76db4d9..4137a49eae26 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -120,9 +120,10 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
 		return -EIO;
 
 	if (tsk_used_math(child)) {
-		fpureg_t *fregs = get_fpu_regs(child);
+		union fpureg *fregs = get_fpu_regs(child);
 		for (i = 0; i < 32; i++)
-			__put_user(fregs[i], i + (__u64 __user *) data);
+			__put_user(get_fpr64(&fregs[i], 0),
+				   i + (__u64 __user *)data);
 	} else {
 		for (i = 0; i < 32; i++)
 			__put_user((__u64) -1, i + (__u64 __user *) data);
@@ -158,7 +159,8 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
 
 int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
 {
-	fpureg_t *fregs;
+	union fpureg *fregs;
+	u64 fpr_val;
 	int i;
 
 	if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -166,8 +168,10 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
 
 	fregs = get_fpu_regs(child);
 
-	for (i = 0; i < 32; i++)
-		__get_user(fregs[i], i + (__u64 __user *) data);
+	for (i = 0; i < 32; i++) {
+		__get_user(fpr_val, i + (__u64 __user *)data);
+		set_fpr64(&fregs[i], 0, fpr_val);
+	}
 
 	__get_user(child->thread.fpu.fcr31, data + 64);
 
@@ -300,10 +304,27 @@ static int fpr_get(struct task_struct *target,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   &target->thread.fpu,
-				   0, sizeof(elf_fpregset_t));
+	unsigned i;
+	int err;
+	u64 fpr_val;
+
 	/* XXX fcr31  */
+
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					   &target->thread.fpu,
+					   0, sizeof(elf_fpregset_t));
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &fpr_val, i * sizeof(elf_fpreg_t),
+					  (i + 1) * sizeof(elf_fpreg_t));
+		if (err)
+			return err;
+	}
+
+	return 0;
 }
 
 static int fpr_set(struct task_struct *target,
@@ -311,10 +332,27 @@ static int fpr_set(struct task_struct *target,
 		   unsigned int pos, unsigned int count,
 		   const void *kbuf, const void __user *ubuf)
 {
-	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fpu,
-				  0, sizeof(elf_fpregset_t));
+	unsigned i;
+	int err;
+	u64 fpr_val;
+
 	/* XXX fcr31  */
+
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.fpu,
+					  0, sizeof(elf_fpregset_t));
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					 &fpr_val, i * sizeof(elf_fpreg_t),
+					 (i + 1) * sizeof(elf_fpreg_t));
+		if (err)
+			return err;
+		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+	}
+
+	return 0;
 }
 
 enum mips_regset {
@@ -408,7 +446,7 @@ long arch_ptrace(struct task_struct *child, long request,
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
-		fpureg_t *fregs;
+		union fpureg *fregs;
 		unsigned long tmp = 0;
 
 		regs = task_pt_regs(child);
@@ -433,14 +471,12 @@ long arch_ptrace(struct task_struct *child, long request,
 				 * order bits of the values stored in the even
 				 * registers - unless we're using r2k_switch.S.
 				 */
-				if (addr & 1)
-					tmp = fregs[(addr & ~1) - 32] >> 32;
-				else
-					tmp = fregs[addr - 32];
+				tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+						addr & 1);
 				break;
 			}
 #endif
-			tmp = fregs[addr - FPR_BASE];
+			tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
 			break;
 		case PC:
 			tmp = regs->cp0_epc;
@@ -548,7 +584,7 @@ long arch_ptrace(struct task_struct *child, long request,
 			regs->regs[addr] = data;
 			break;
 		case FPR_BASE ... FPR_BASE + 31: {
-			fpureg_t *fregs = get_fpu_regs(child);
+			union fpureg *fregs = get_fpu_regs(child);
 
 			if (!tsk_used_math(child)) {
 				/* FP not yet used  */
@@ -563,19 +599,12 @@ long arch_ptrace(struct task_struct *child, long request,
 				 * order bits of the values stored in the even
 				 * registers - unless we're using r2k_switch.S.
 				 */
-				if (addr & 1) {
-					fregs[(addr & ~1) - FPR_BASE] &=
-						0xffffffff;
-					fregs[(addr & ~1) - FPR_BASE] |=
-						((u64)data) << 32;
-				} else {
-					fregs[addr - FPR_BASE] &= ~0xffffffffLL;
-					fregs[addr - FPR_BASE] |= data;
-				}
+				set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+					  addr & 1, data);
 				break;
 			}
 #endif
-			fregs[addr - FPR_BASE] = data;
+			set_fpr64(&fregs[addr - FPR_BASE], 0, data);
 			break;
 		}
 		case PC:
@@ -662,13 +691,13 @@ long arch_ptrace(struct task_struct *child, long request,
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
-asmlinkage void syscall_trace_enter(struct pt_regs *regs)
+asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
 {
 	long ret = 0;
 	user_exit();
 
-	/* do the secure computing check first */
-	secure_computing_strict(regs->regs[2]);
+	if (secure_computing(syscall) == -1)
+		return -1;
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    tracehook_report_syscall_entry(regs))
@@ -677,10 +706,11 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_enter(regs, regs->regs[2]);
 
-	audit_syscall_entry(__syscall_get_arch(),
-			    regs->regs[2],
+	audit_syscall_entry(syscall_get_arch(current, regs),
+			    syscall,
 			    regs->regs[4], regs->regs[5],
 			    regs->regs[6], regs->regs[7]);
+	return syscall;
 }
 
 /*
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index b8aa2dd5b00b..c394d8f74265 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -80,7 +80,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
-		fpureg_t *fregs;
+		union fpureg *fregs;
 		unsigned int tmp;
 
 		regs = task_pt_regs(child);
@@ -103,13 +103,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 				 * order bits of the values stored in the even
 				 * registers - unless we're using r2k_switch.S.
 				 */
-				if (addr & 1)
-					tmp = fregs[(addr & ~1) - 32] >> 32;
-				else
-					tmp = fregs[addr - 32];
+				tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+						addr & 1);
 				break;
 			}
-			tmp = fregs[addr - FPR_BASE];
+			tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
 			break;
 		case PC:
 			tmp = regs->cp0_epc;
@@ -233,7 +231,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			regs->regs[addr] = data;
 			break;
 		case FPR_BASE ... FPR_BASE + 31: {
-			fpureg_t *fregs = get_fpu_regs(child);
+			union fpureg *fregs = get_fpu_regs(child);
 
 			if (!tsk_used_math(child)) {
 				/* FP not yet used  */
@@ -247,18 +245,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 				 * order bits of the values stored in the even
 				 * registers - unless we're using r2k_switch.S.
 				 */
-				if (addr & 1) {
-					fregs[(addr & ~1) - FPR_BASE] &=
-						0xffffffff;
-					fregs[(addr & ~1) - FPR_BASE] |=
-						((u64)data) << 32;
-				} else {
-					fregs[addr - FPR_BASE] &= ~0xffffffffLL;
-					fregs[addr - FPR_BASE] |= data;
-				}
+				set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+					  addr & 1, data);
 				break;
 			}
-			fregs[addr - FPR_BASE] = data;
+			set_fpr64(&fregs[addr - FPR_BASE], 0, data);
 			break;
 		}
 		case PC:
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 253b2fb52026..752b50a69264 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -13,6 +13,7 @@
  * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/errno.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
@@ -245,6 +246,218 @@ LEAF(_restore_fp_context32)
 	END(_restore_fp_context32)
 #endif
 
+#ifdef CONFIG_CPU_HAS_MSA
+
+	.macro	save_sc_msareg	wr, off, sc, tmp
+#ifdef CONFIG_64BIT
+	copy_u_d \tmp, \wr, 1
+	EX sd	\tmp, (\off+(\wr*8))(\sc)
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+	copy_u_w \tmp, \wr, 2
+	EX sw	\tmp, (\off+(\wr*8)+0)(\sc)
+	copy_u_w \tmp, \wr, 3
+	EX sw	\tmp, (\off+(\wr*8)+4)(\sc)
+#else /* CONFIG_CPU_BIG_ENDIAN */
+	copy_u_w \tmp, \wr, 2
+	EX sw	\tmp, (\off+(\wr*8)+4)(\sc)
+	copy_u_w \tmp, \wr, 3
+	EX sw	\tmp, (\off+(\wr*8)+0)(\sc)
+#endif
+	.endm
+
+/*
+ * int _save_msa_context(struct sigcontext *sc)
+ *
+ * Save the upper 64 bits of each vector register along with the MSA_CSR
+ * register into sc. Returns zero on success, else non-zero.
+ */
+LEAF(_save_msa_context)
+	save_sc_msareg	0, SC_MSAREGS, a0, t0
+	save_sc_msareg	1, SC_MSAREGS, a0, t0
+	save_sc_msareg	2, SC_MSAREGS, a0, t0
+	save_sc_msareg	3, SC_MSAREGS, a0, t0
+	save_sc_msareg	4, SC_MSAREGS, a0, t0
+	save_sc_msareg	5, SC_MSAREGS, a0, t0
+	save_sc_msareg	6, SC_MSAREGS, a0, t0
+	save_sc_msareg	7, SC_MSAREGS, a0, t0
+	save_sc_msareg	8, SC_MSAREGS, a0, t0
+	save_sc_msareg	9, SC_MSAREGS, a0, t0
+	save_sc_msareg	10, SC_MSAREGS, a0, t0
+	save_sc_msareg	11, SC_MSAREGS, a0, t0
+	save_sc_msareg	12, SC_MSAREGS, a0, t0
+	save_sc_msareg	13, SC_MSAREGS, a0, t0
+	save_sc_msareg	14, SC_MSAREGS, a0, t0
+	save_sc_msareg	15, SC_MSAREGS, a0, t0
+	save_sc_msareg	16, SC_MSAREGS, a0, t0
+	save_sc_msareg	17, SC_MSAREGS, a0, t0
+	save_sc_msareg	18, SC_MSAREGS, a0, t0
+	save_sc_msareg	19, SC_MSAREGS, a0, t0
+	save_sc_msareg	20, SC_MSAREGS, a0, t0
+	save_sc_msareg	21, SC_MSAREGS, a0, t0
+	save_sc_msareg	22, SC_MSAREGS, a0, t0
+	save_sc_msareg	23, SC_MSAREGS, a0, t0
+	save_sc_msareg	24, SC_MSAREGS, a0, t0
+	save_sc_msareg	25, SC_MSAREGS, a0, t0
+	save_sc_msareg	26, SC_MSAREGS, a0, t0
+	save_sc_msareg	27, SC_MSAREGS, a0, t0
+	save_sc_msareg	28, SC_MSAREGS, a0, t0
+	save_sc_msareg	29, SC_MSAREGS, a0, t0
+	save_sc_msareg	30, SC_MSAREGS, a0, t0
+	save_sc_msareg	31, SC_MSAREGS, a0, t0
+	jr	ra
+	 li	v0, 0
+	END(_save_msa_context)
+
+#ifdef CONFIG_MIPS32_COMPAT
+
+/*
+ * int _save_msa_context32(struct sigcontext32 *sc)
+ *
+ * Save the upper 64 bits of each vector register along with the MSA_CSR
+ * register into sc. Returns zero on success, else non-zero.
+ */
+LEAF(_save_msa_context32)
+	save_sc_msareg	0, SC32_MSAREGS, a0, t0
+	save_sc_msareg	1, SC32_MSAREGS, a0, t0
+	save_sc_msareg	2, SC32_MSAREGS, a0, t0
+	save_sc_msareg	3, SC32_MSAREGS, a0, t0
+	save_sc_msareg	4, SC32_MSAREGS, a0, t0
+	save_sc_msareg	5, SC32_MSAREGS, a0, t0
+	save_sc_msareg	6, SC32_MSAREGS, a0, t0
+	save_sc_msareg	7, SC32_MSAREGS, a0, t0
+	save_sc_msareg	8, SC32_MSAREGS, a0, t0
+	save_sc_msareg	9, SC32_MSAREGS, a0, t0
+	save_sc_msareg	10, SC32_MSAREGS, a0, t0
+	save_sc_msareg	11, SC32_MSAREGS, a0, t0
+	save_sc_msareg	12, SC32_MSAREGS, a0, t0
+	save_sc_msareg	13, SC32_MSAREGS, a0, t0
+	save_sc_msareg	14, SC32_MSAREGS, a0, t0
+	save_sc_msareg	15, SC32_MSAREGS, a0, t0
+	save_sc_msareg	16, SC32_MSAREGS, a0, t0
+	save_sc_msareg	17, SC32_MSAREGS, a0, t0
+	save_sc_msareg	18, SC32_MSAREGS, a0, t0
+	save_sc_msareg	19, SC32_MSAREGS, a0, t0
+	save_sc_msareg	20, SC32_MSAREGS, a0, t0
+	save_sc_msareg	21, SC32_MSAREGS, a0, t0
+	save_sc_msareg	22, SC32_MSAREGS, a0, t0
+	save_sc_msareg	23, SC32_MSAREGS, a0, t0
+	save_sc_msareg	24, SC32_MSAREGS, a0, t0
+	save_sc_msareg	25, SC32_MSAREGS, a0, t0
+	save_sc_msareg	26, SC32_MSAREGS, a0, t0
+	save_sc_msareg	27, SC32_MSAREGS, a0, t0
+	save_sc_msareg	28, SC32_MSAREGS, a0, t0
+	save_sc_msareg	29, SC32_MSAREGS, a0, t0
+	save_sc_msareg	30, SC32_MSAREGS, a0, t0
+	save_sc_msareg	31, SC32_MSAREGS, a0, t0
+	jr	ra
+	 li	v0, 0
+	END(_save_msa_context32)
+
+#endif /* CONFIG_MIPS32_COMPAT */
+
+	.macro restore_sc_msareg	wr, off, sc, tmp
+#ifdef CONFIG_64BIT
+	EX ld	\tmp, (\off+(\wr*8))(\sc)
+	insert_d \wr, 1, \tmp
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+	EX lw	\tmp, (\off+(\wr*8)+0)(\sc)
+	insert_w \wr, 2, \tmp
+	EX lw	\tmp, (\off+(\wr*8)+4)(\sc)
+	insert_w \wr, 3, \tmp
+#else /* CONFIG_CPU_BIG_ENDIAN */
+	EX lw	\tmp, (\off+(\wr*8)+4)(\sc)
+	insert_w \wr, 2, \tmp
+	EX lw	\tmp, (\off+(\wr*8)+0)(\sc)
+	insert_w \wr, 3, \tmp
+#endif
+	.endm
+
+/*
+ * int _restore_msa_context(struct sigcontext *sc)
+ */
+LEAF(_restore_msa_context)
+	restore_sc_msareg	0, SC_MSAREGS, a0, t0
+	restore_sc_msareg	1, SC_MSAREGS, a0, t0
+	restore_sc_msareg	2, SC_MSAREGS, a0, t0
+	restore_sc_msareg	3, SC_MSAREGS, a0, t0
+	restore_sc_msareg	4, SC_MSAREGS, a0, t0
+	restore_sc_msareg	5, SC_MSAREGS, a0, t0
+	restore_sc_msareg	6, SC_MSAREGS, a0, t0
+	restore_sc_msareg	7, SC_MSAREGS, a0, t0
+	restore_sc_msareg	8, SC_MSAREGS, a0, t0
+	restore_sc_msareg	9, SC_MSAREGS, a0, t0
+	restore_sc_msareg	10, SC_MSAREGS, a0, t0
+	restore_sc_msareg	11, SC_MSAREGS, a0, t0
+	restore_sc_msareg	12, SC_MSAREGS, a0, t0
+	restore_sc_msareg	13, SC_MSAREGS, a0, t0
+	restore_sc_msareg	14, SC_MSAREGS, a0, t0
+	restore_sc_msareg	15, SC_MSAREGS, a0, t0
+	restore_sc_msareg	16, SC_MSAREGS, a0, t0
+	restore_sc_msareg	17, SC_MSAREGS, a0, t0
+	restore_sc_msareg	18, SC_MSAREGS, a0, t0
+	restore_sc_msareg	19, SC_MSAREGS, a0, t0
+	restore_sc_msareg	20, SC_MSAREGS, a0, t0
+	restore_sc_msareg	21, SC_MSAREGS, a0, t0
+	restore_sc_msareg	22, SC_MSAREGS, a0, t0
+	restore_sc_msareg	23, SC_MSAREGS, a0, t0
+	restore_sc_msareg	24, SC_MSAREGS, a0, t0
+	restore_sc_msareg	25, SC_MSAREGS, a0, t0
+	restore_sc_msareg	26, SC_MSAREGS, a0, t0
+	restore_sc_msareg	27, SC_MSAREGS, a0, t0
+	restore_sc_msareg	28, SC_MSAREGS, a0, t0
+	restore_sc_msareg	29, SC_MSAREGS, a0, t0
+	restore_sc_msareg	30, SC_MSAREGS, a0, t0
+	restore_sc_msareg	31, SC_MSAREGS, a0, t0
+	jr	ra
+	 li	v0, 0
+	END(_restore_msa_context)
+
+#ifdef CONFIG_MIPS32_COMPAT
+
+/*
+ * int _restore_msa_context32(struct sigcontext32 *sc)
+ */
+LEAF(_restore_msa_context32)
+	restore_sc_msareg	0, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	1, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	2, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	3, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	4, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	5, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	6, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	7, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	8, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	9, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	10, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	11, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	12, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	13, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	14, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	15, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	16, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	17, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	18, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	19, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	20, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	21, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	22, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	23, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	24, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	25, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	26, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	27, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	28, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	29, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	30, SC32_MSAREGS, a0, t0
+	restore_sc_msareg	31, SC32_MSAREGS, a0, t0
+	jr	ra
+	 li	v0, 0
+	END(_restore_msa_context32)
+
+#endif /* CONFIG_MIPS32_COMPAT */
+
+#endif /* CONFIG_CPU_HAS_MSA */
+
 	.set	reorder
 
 	.type	fault@function
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index cc78dd9a17c7..f938ecd22af0 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -29,18 +29,8 @@
 #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
 
 /*
- * FPU context is saved iff the process has used it's FPU in the current
- * time slice as indicated by _TIF_USEDFPU.  In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
- * userland with FPU disabled after each context switch.
- *
- * FPU will be enabled as soon as the process accesses FPU again, through
- * do_cpu() trap.
- */
-
-/*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *		       struct thread_info *next_ti, int usedfpu)
+ *		       struct thread_info *next_ti, s32 fp_save)
  */
 	.align	5
 	LEAF(resume)
@@ -50,23 +40,37 @@
 	LONG_S	ra, THREAD_REG31(a0)
 
 	/*
-	 * check if we need to save FPU registers
+	 * Check whether we need to save any FP context. FP context is saved
+	 * iff the process has used the context with the scalar FPU or the MSA
+	 * ASE in the current time slice, as indicated by _TIF_USEDFPU and
+	 * _TIF_USEDMSA respectively. switch_to will have set fp_save
+	 * accordingly to an FP_SAVE_ enum value.
 	 */
+	beqz	a3, 2f
 
-	beqz	a3, 1f
-
-	PTR_L	t3, TASK_THREAD_INFO(a0)
 	/*
-	 * clear saved user stack CU1 bit
+	 * We do. Clear the saved CU1 bit for prev, such that next time it is
+	 * scheduled it will start in userland with the FPU disabled. If the
+	 * task uses the FPU then it will be enabled again via the do_cpu trap.
+	 * This allows us to lazily restore the FP context.
 	 */
+	PTR_L	t3, TASK_THREAD_INFO(a0)
 	LONG_L	t0, ST_OFF(t3)
 	li	t1, ~ST0_CU1
 	and	t0, t0, t1
 	LONG_S	t0, ST_OFF(t3)
 
+	/* Check whether we're saving scalar or vector context. */
+	bgtz	a3, 1f
+
+	/* Save 128b MSA vector context. */
+	msa_save_all	a0
+	b	2f
+
+1:	/* Save 32b/64b scalar FP context. */
 	fpu_save_double a0 t0 t1		# c0_status passed in t0
 						# clobbers t1
-1:
+2:
 
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	PTR_LA	t8, __stack_chk_guard
@@ -141,6 +145,26 @@ LEAF(_restore_fp)
 	jr	ra
 	END(_restore_fp)
 
+#ifdef CONFIG_CPU_HAS_MSA
+
+/*
+ * Save a thread's MSA vector context.
+ */
+LEAF(_save_msa)
+	msa_save_all	a0
+	jr	ra
+	END(_save_msa)
+
+/*
+ * Restore a thread's MSA vector context.
+ */
+LEAF(_restore_msa)
+	msa_restore_all	a0
+	jr	ra
+	END(_restore_msa)
+
+#endif
+
 /*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
  * the property that no matter whether considered as single or as double
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a5b14f48e1af..fdc70b400442 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -6,6 +6,7 @@
  * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org>
  * Copyright (C) 2001 MIPS Technologies, Inc.
  * Copyright (C) 2004 Thiemo Seufer
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  */
 #include <linux/errno.h>
 #include <asm/asm.h>
@@ -74,10 +75,10 @@ NESTED(handle_sys, PT_SIZE, sp)
 	.set    noreorder
 	.set	nomacro
 
-1:	lw	t5, 16(t0)		# argument #5 from usp
-4:	lw	t6, 20(t0)		# argument #6 from usp
-3:	lw	t7, 24(t0)		# argument #7 from usp
-2:	lw	t8, 28(t0)		# argument #8 from usp
+1:	user_lw(t5, 16(t0))		# argument #5 from usp
+4:	user_lw(t6, 20(t0))		# argument #6 from usp
+3:	user_lw(t7, 24(t0))		# argument #7 from usp
+2:	user_lw(t8, 28(t0))		# argument #8 from usp
 
 	sw	t5, 16(sp)		# argument #5 to ksp
 	sw	t6, 20(sp)		# argument #6 to ksp
@@ -118,7 +119,18 @@ syscall_trace_entry:
 	SAVE_STATIC
 	move	s0, t2
 	move	a0, sp
-	jal	syscall_trace_enter
+
+	/*
+	 * syscall number is in v0 unless we called syscall(__NR_###)
+	 * where the real syscall number is in a0
+	 */
+	addiu	a1, v0,  __NR_O32_Linux
+	bnez	v0, 1f /* __NR_syscall at offset 0 */
+	lw	a1, PT_R4(sp)
+
+1:	jal	syscall_trace_enter
+
+	bltz	v0, 2f			# seccomp failed? Skip syscall
 
 	move	t0, s0
 	RESTORE_STATIC
@@ -138,7 +150,7 @@ syscall_trace_entry:
 	sw	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sw	v0, PT_R2(sp)		# result
 
-	j	syscall_exit
+2:	j	syscall_exit
 
 /* ------------------------------------------------------------------------ */
 
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index b56e254beb15..dd99c3285aea 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -80,8 +80,11 @@ syscall_trace_entry:
 	SAVE_STATIC
 	move	s0, t2
 	move	a0, sp
+	daddiu	a1, v0, __NR_64_Linux
 	jal	syscall_trace_enter
 
+	bltz	v0, 2f			# seccomp failed? Skip syscall
+
 	move	t0, s0
 	RESTORE_STATIC
 	ld	a0, PT_R4(sp)		# Restore argument registers
@@ -102,7 +105,7 @@ syscall_trace_entry:
 	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
-	j	syscall_exit
+2:	j	syscall_exit
 
 illegal_syscall:
 	/* This also isn't a 64-bit syscall, throw an error.  */
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index f7e5b72cf481..f68d2f4f0090 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -72,8 +72,11 @@ n32_syscall_trace_entry:
 	SAVE_STATIC
 	move	s0, t2
 	move	a0, sp
+	daddiu	a1, v0, __NR_N32_Linux
 	jal	syscall_trace_enter
 
+	bltz	v0, 2f			# seccomp failed? Skip syscall
+
 	move	t0, s0
 	RESTORE_STATIC
 	ld	a0, PT_R4(sp)		# Restore argument registers
@@ -94,7 +97,7 @@ n32_syscall_trace_entry:
 	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
-	j	syscall_exit
+2:	j	syscall_exit
 
 not_n32_scall:
 	/* This is not an n32 compatibility syscall, pass it on to
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 6788727d91af..70f6acecd928 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -112,7 +112,20 @@ trace_a_syscall:
 
 	move	s0, t2			# Save syscall pointer
 	move	a0, sp
-	jal	syscall_trace_enter
+	/*
+	 * syscall number is in v0 unless we called syscall(__NR_###)
+	 * where the real syscall number is in a0
+	 * note: NR_syscall is the first O32 syscall but the macro is
+	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
+	 * therefore __NR_O32_Linux is used (4000)
+	 */
+	addiu	a1, v0,  __NR_O32_Linux
+	bnez	v0, 1f /* __NR_syscall at offset 0 */
+	lw	a1, PT_R4(sp)
+
+1:	jal	syscall_trace_enter
+
+	bltz	v0, 2f			# seccomp failed? Skip syscall
 
 	move	t0, s0
 	RESTORE_STATIC
@@ -136,7 +149,7 @@ trace_a_syscall:
 	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
-	j	syscall_exit
+2:	j	syscall_exit
 
 /* ------------------------------------------------------------------------ */
 
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 5199563c4403..33133d3df3e5 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -6,6 +6,7 @@
  * Copyright (C) 1991, 1992  Linus Torvalds
  * Copyright (C) 1994 - 2000  Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
  */
 #include <linux/cache.h>
 #include <linux/context_tracking.h>
@@ -30,6 +31,7 @@
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/fpu.h>
+#include <asm/msa.h>
 #include <asm/sim.h>
 #include <asm/ucontext.h>
 #include <asm/cpu-features.h>
@@ -46,8 +48,8 @@ static int (*restore_fp_context)(struct sigcontext __user *sc);
 extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
 extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
 
-extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
+extern asmlinkage int _save_msa_context(struct sigcontext __user *sc);
+extern asmlinkage int _restore_msa_context(struct sigcontext __user *sc);
 
 struct sigframe {
 	u32 sf_ass[4];		/* argument save space for o32 */
@@ -64,17 +66,95 @@ struct rt_sigframe {
 };
 
 /*
+ * Thread saved context copy to/from a signal context presumed to be on the
+ * user stack, and therefore accessed with appropriate macros from uaccess.h.
+ */
+static int copy_fp_to_sigcontext(struct sigcontext __user *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |=
+		    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+
+	return err;
+}
+
+static int copy_fp_from_sigcontext(struct sigcontext __user *sc)
+{
+	int i;
+	int err = 0;
+	u64 fpr_val;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
+		set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
+	}
+	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+
+	return err;
+}
+
+/*
+ * These functions will save only the upper 64 bits of the vector registers,
+ * since the lower 64 bits have already been saved as the scalar FP context.
+ */
+static int copy_msa_to_sigcontext(struct sigcontext __user *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |=
+		    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 1),
+			       &sc->sc_msaregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
+
+	return err;
+}
+
+static int copy_msa_from_sigcontext(struct sigcontext __user *sc)
+{
+	int i;
+	int err = 0;
+	u64 val;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |= __get_user(val, &sc->sc_msaregs[i]);
+		set_fpr64(&current->thread.fpu.fpr[i], 1, val);
+	}
+	err |= __get_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
+
+	return err;
+}
+
+/*
  * Helper routines
  */
-static int protected_save_fp_context(struct sigcontext __user *sc)
+static int protected_save_fp_context(struct sigcontext __user *sc,
+				     unsigned used_math)
 {
 	int err;
+	bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
+#ifndef CONFIG_EVA
 	while (1) {
 		lock_fpu_owner();
-		err = own_fpu_inatomic(1);
-		if (!err)
-			err = save_fp_context(sc); /* this might fail */
-		unlock_fpu_owner();
+		if (is_fpu_owner()) {
+			err = save_fp_context(sc);
+			if (save_msa && !err)
+				err = _save_msa_context(sc);
+			unlock_fpu_owner();
+		} else {
+			unlock_fpu_owner();
+			err = copy_fp_to_sigcontext(sc);
+			if (save_msa && !err)
+				err = copy_msa_to_sigcontext(sc);
+		}
 		if (likely(!err))
 			break;
 		/* touch the sigcontext and try again */
@@ -84,18 +164,44 @@ static int protected_save_fp_context(struct sigcontext __user *sc)
 		if (err)
 			break;	/* really bad sigcontext */
 	}
+#else
+	/*
+	 * EVA does not have FPU EVA instructions so saving fpu context directly
+	 * does not work.
+	 */
+	disable_msa();
+	lose_fpu(1);
+	err = save_fp_context(sc); /* this might fail */
+	if (save_msa && !err)
+		err = copy_msa_to_sigcontext(sc);
+#endif
 	return err;
 }
 
-static int protected_restore_fp_context(struct sigcontext __user *sc)
+static int protected_restore_fp_context(struct sigcontext __user *sc,
+					unsigned used_math)
 {
 	int err, tmp __maybe_unused;
+	bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
+#ifndef CONFIG_EVA
 	while (1) {
 		lock_fpu_owner();
-		err = own_fpu_inatomic(0);
-		if (!err)
-			err = restore_fp_context(sc); /* this might fail */
-		unlock_fpu_owner();
+		if (is_fpu_owner()) {
+			err = restore_fp_context(sc);
+			if (restore_msa && !err) {
+				enable_msa();
+				err = _restore_msa_context(sc);
+			} else {
+				/* signal handler may have used MSA */
+				disable_msa();
+			}
+			unlock_fpu_owner();
+		} else {
+			unlock_fpu_owner();
+			err = copy_fp_from_sigcontext(sc);
+			if (!err && (used_math & USEDMATH_MSA))
+				err = copy_msa_from_sigcontext(sc);
+		}
 		if (likely(!err))
 			break;
 		/* touch the sigcontext and try again */
@@ -105,6 +211,17 @@ static int protected_restore_fp_context(struct sigcontext __user *sc)
 		if (err)
 			break;	/* really bad sigcontext */
 	}
+#else
+	/*
+	 * EVA does not have FPU EVA instructions so restoring fpu context
+	 * directly does not work.
+	 */
+	enable_msa();
+	lose_fpu(0);
+	err = restore_fp_context(sc); /* this might fail */
+	if (restore_msa && !err)
+		err = copy_msa_from_sigcontext(sc);
+#endif
 	return err;
 }
 
@@ -135,7 +252,8 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
 	}
 
-	used_math = !!used_math();
+	used_math = used_math() ? USEDMATH_FP : 0;
+	used_math |= thread_msa_context_live() ? USEDMATH_MSA : 0;
 	err |= __put_user(used_math, &sc->sc_used_math);
 
 	if (used_math) {
@@ -143,7 +261,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 		 * Save FPU state to signal context. Signal handler
 		 * will "inherit" current FPU state.
 		 */
-		err |= protected_save_fp_context(sc);
+		err |= protected_save_fp_context(sc, used_math);
 	}
 	return err;
 }
@@ -168,14 +286,14 @@ int fpcsr_pending(unsigned int __user *fpcsr)
 }
 
 static int
-check_and_restore_fp_context(struct sigcontext __user *sc)
+check_and_restore_fp_context(struct sigcontext __user *sc, unsigned used_math)
 {
 	int err, sig;
 
 	err = sig = fpcsr_pending(&sc->sc_fpc_csr);
 	if (err > 0)
 		err = 0;
-	err |= protected_restore_fp_context(sc);
+	err |= protected_restore_fp_context(sc, used_math);
 	return err ?: sig;
 }
 
@@ -215,9 +333,10 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 	if (used_math) {
 		/* restore fpu context if we have used it before */
 		if (!err)
-			err = check_and_restore_fp_context(sc);
+			err = check_and_restore_fp_context(sc, used_math);
 	} else {
-		/* signal handler may have used FPU.  Give it up. */
+		/* signal handler may have used FPU or MSA. Disable them. */
+		disable_msa();
 		lose_fpu(0);
 	}
 
@@ -591,23 +710,26 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 }
 
 #ifdef CONFIG_SMP
+#ifndef CONFIG_EVA
 static int smp_save_fp_context(struct sigcontext __user *sc)
 {
 	return raw_cpu_has_fpu
 	       ? _save_fp_context(sc)
-	       : fpu_emulator_save_context(sc);
+	       : copy_fp_to_sigcontext(sc);
 }
 
 static int smp_restore_fp_context(struct sigcontext __user *sc)
 {
 	return raw_cpu_has_fpu
 	       ? _restore_fp_context(sc)
-	       : fpu_emulator_restore_context(sc);
+	       : copy_fp_from_sigcontext(sc);
 }
+#endif /* CONFIG_EVA */
 #endif
 
 static int signal_setup(void)
 {
+#ifndef CONFIG_EVA
 #ifdef CONFIG_SMP
 	/* For now just do the cpu_has_fpu check when the functions are invoked */
 	save_fp_context = smp_save_fp_context;
@@ -617,9 +739,13 @@ static int signal_setup(void)
 		save_fp_context = _save_fp_context;
 		restore_fp_context = _restore_fp_context;
 	} else {
-		save_fp_context = fpu_emulator_save_context;
-		restore_fp_context = fpu_emulator_restore_context;
+		save_fp_context = copy_fp_from_sigcontext;
+		restore_fp_context = copy_fp_to_sigcontext;
 	}
+#endif /* CONFIG_SMP */
+#else
+	save_fp_context = copy_fp_from_sigcontext;;
+	restore_fp_context = copy_fp_to_sigcontext;
 #endif
 
 	return 0;
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 3d60f7750fa8..299f956e4db3 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -30,6 +30,7 @@
 #include <asm/sim.h>
 #include <asm/ucontext.h>
 #include <asm/fpu.h>
+#include <asm/msa.h>
 #include <asm/war.h>
 #include <asm/vdso.h>
 #include <asm/dsp.h>
@@ -42,8 +43,8 @@ static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
 extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
 extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
 
-extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int _save_msa_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int _restore_msa_context32(struct sigcontext32 __user *sc);
 
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
@@ -78,17 +79,96 @@ struct rt_sigframe32 {
 };
 
 /*
+ * Thread saved context copy to/from a signal context presumed to be on the
+ * user stack, and therefore accessed with appropriate macros from uaccess.h.
+ */
+static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc)
+{
+	int i;
+	int err = 0;
+	int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
+
+	for (i = 0; i < NUM_FPU_REGS; i += inc) {
+		err |=
+		    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+
+	return err;
+}
+
+static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc)
+{
+	int i;
+	int err = 0;
+	int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
+	u64 fpr_val;
+
+	for (i = 0; i < NUM_FPU_REGS; i += inc) {
+		err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
+		set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
+	}
+	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+
+	return err;
+}
+
+/*
+ * These functions will save only the upper 64 bits of the vector registers,
+ * since the lower 64 bits have already been saved as the scalar FP context.
+ */
+static int copy_msa_to_sigcontext32(struct sigcontext32 __user *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |=
+		    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 1),
+			       &sc->sc_msaregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
+
+	return err;
+}
+
+static int copy_msa_from_sigcontext32(struct sigcontext32 __user *sc)
+{
+	int i;
+	int err = 0;
+	u64 val;
+
+	for (i = 0; i < NUM_FPU_REGS; i++) {
+		err |= __get_user(val, &sc->sc_msaregs[i]);
+		set_fpr64(&current->thread.fpu.fpr[i], 1, val);
+	}
+	err |= __get_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
+
+	return err;
+}
+
+/*
  * sigcontext handlers
  */
-static int protected_save_fp_context32(struct sigcontext32 __user *sc)
+static int protected_save_fp_context32(struct sigcontext32 __user *sc,
+				       unsigned used_math)
 {
 	int err;
+	bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
 	while (1) {
 		lock_fpu_owner();
-		err = own_fpu_inatomic(1);
-		if (!err)
-			err = save_fp_context32(sc); /* this might fail */
-		unlock_fpu_owner();
+		if (is_fpu_owner()) {
+			err = save_fp_context32(sc);
+			if (save_msa && !err)
+				err = _save_msa_context32(sc);
+			unlock_fpu_owner();
+		} else {
+			unlock_fpu_owner();
+			err = copy_fp_to_sigcontext32(sc);
+			if (save_msa && !err)
+				err = copy_msa_to_sigcontext32(sc);
+		}
 		if (likely(!err))
 			break;
 		/* touch the sigcontext and try again */
@@ -101,15 +181,29 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc)
 	return err;
 }
 
-static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
+static int protected_restore_fp_context32(struct sigcontext32 __user *sc,
+					  unsigned used_math)
 {
 	int err, tmp __maybe_unused;
+	bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
 	while (1) {
 		lock_fpu_owner();
-		err = own_fpu_inatomic(0);
-		if (!err)
-			err = restore_fp_context32(sc); /* this might fail */
-		unlock_fpu_owner();
+		if (is_fpu_owner()) {
+			err = restore_fp_context32(sc);
+			if (restore_msa && !err) {
+				enable_msa();
+				err = _restore_msa_context32(sc);
+			} else {
+				/* signal handler may have used MSA */
+				disable_msa();
+			}
+			unlock_fpu_owner();
+		} else {
+			unlock_fpu_owner();
+			err = copy_fp_from_sigcontext32(sc);
+			if (restore_msa && !err)
+				err = copy_msa_from_sigcontext32(sc);
+		}
 		if (likely(!err))
 			break;
 		/* touch the sigcontext and try again */
@@ -147,7 +241,8 @@ static int setup_sigcontext32(struct pt_regs *regs,
 		err |= __put_user(mflo3(), &sc->sc_lo3);
 	}
 
-	used_math = !!used_math();
+	used_math = used_math() ? USEDMATH_FP : 0;
+	used_math |= thread_msa_context_live() ? USEDMATH_MSA : 0;
 	err |= __put_user(used_math, &sc->sc_used_math);
 
 	if (used_math) {
@@ -155,20 +250,21 @@ static int setup_sigcontext32(struct pt_regs *regs,
 		 * Save FPU state to signal context.  Signal handler
 		 * will "inherit" current FPU state.
 		 */
-		err |= protected_save_fp_context32(sc);
+		err |= protected_save_fp_context32(sc, used_math);
 	}
 	return err;
 }
 
 static int
-check_and_restore_fp_context32(struct sigcontext32 __user *sc)
+check_and_restore_fp_context32(struct sigcontext32 __user *sc,
+			       unsigned used_math)
 {
 	int err, sig;
 
 	err = sig = fpcsr_pending(&sc->sc_fpc_csr);
 	if (err > 0)
 		err = 0;
-	err |= protected_restore_fp_context32(sc);
+	err |= protected_restore_fp_context32(sc, used_math);
 	return err ?: sig;
 }
 
@@ -205,9 +301,10 @@ static int restore_sigcontext32(struct pt_regs *regs,
 	if (used_math) {
 		/* restore fpu context if we have used it before */
 		if (!err)
-			err = check_and_restore_fp_context32(sc);
+			err = check_and_restore_fp_context32(sc, used_math);
 	} else {
-		/* signal handler may have used FPU.  Give it up. */
+		/* signal handler may have used FPU or MSA. Disable them. */
+		disable_msa();
 		lose_fpu(0);
 	}
 
@@ -566,8 +663,8 @@ static int signal32_init(void)
 		save_fp_context32 = _save_fp_context32;
 		restore_fp_context32 = _restore_fp_context32;
 	} else {
-		save_fp_context32 = fpu_emulator_save_context32;
-		restore_fp_context32 = fpu_emulator_restore_context32;
+		save_fp_context32 = copy_fp_to_sigcontext32;
+		restore_fp_context32 = copy_fp_from_sigcontext32;
 	}
 
 	return 0;
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index 1b925d8a610c..594660ed19dc 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -39,54 +39,6 @@
 #include <asm/amon.h>
 #include <asm/gic.h>
 
-static void ipi_call_function(unsigned int cpu)
-{
-	pr_debug("CPU%d: %s cpu %d status %08x\n",
-		 smp_processor_id(), __func__, cpu, read_c0_status());
-
-	gic_send_ipi(plat_ipi_call_int_xlate(cpu));
-}
-
-
-static void ipi_resched(unsigned int cpu)
-{
-	pr_debug("CPU%d: %s cpu %d status %08x\n",
-		 smp_processor_id(), __func__, cpu, read_c0_status());
-
-	gic_send_ipi(plat_ipi_resched_int_xlate(cpu));
-}
-
-/*
- * FIXME: This isn't restricted to CMP
- * The SMVP kernel could use GIC interrupts if available
- */
-void cmp_send_ipi_single(int cpu, unsigned int action)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (action) {
-	case SMP_CALL_FUNCTION:
-		ipi_call_function(cpu);
-		break;
-
-	case SMP_RESCHEDULE_YOURSELF:
-		ipi_resched(cpu);
-		break;
-	}
-
-	local_irq_restore(flags);
-}
-
-static void cmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
-	unsigned int i;
-
-	for_each_cpu(i, mask)
-		cmp_send_ipi_single(i, action);
-}
-
 static void cmp_init_secondary(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -210,8 +162,8 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
 }
 
 struct plat_smp_ops cmp_smp_ops = {
-	.send_ipi_single	= cmp_send_ipi_single,
-	.send_ipi_mask		= cmp_send_ipi_mask,
+	.send_ipi_single	= gic_send_ipi_single,
+	.send_ipi_mask		= gic_send_ipi_mask,
 	.init_secondary		= cmp_init_secondary,
 	.smp_finish		= cmp_smp_finish,
 	.cpus_done		= cmp_cpus_done,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
new file mode 100644
index 000000000000..299890620668
--- /dev/null
+++ b/arch/mips/kernel/smp-cps.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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/io.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/gic.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+#include <asm/mips_mt.h>
+#include <asm/mipsregs.h>
+#include <asm/smp-cps.h>
+#include <asm/time.h>
+#include <asm/uasm.h>
+
+static DECLARE_BITMAP(core_power, NR_CPUS);
+
+struct boot_config mips_cps_bootcfg;
+
+static void init_core(void)
+{
+	unsigned int nvpes, t;
+	u32 mvpconf0, vpeconf0, vpecontrol, tcstatus, tcbind, status;
+
+	if (!cpu_has_mipsmt)
+		return;
+
+	/* Enter VPE configuration state */
+	dvpe();
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* Retrieve the count of VPEs in this core */
+	mvpconf0 = read_c0_mvpconf0();
+	nvpes = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+	smp_num_siblings = nvpes;
+
+	for (t = 1; t < nvpes; t++) {
+		/* Use a 1:1 mapping of TC index to VPE index */
+		settc(t);
+
+		/* Bind 1 TC to this VPE */
+		tcbind = read_tc_c0_tcbind();
+		tcbind &= ~TCBIND_CURVPE;
+		tcbind |= t << TCBIND_CURVPE_SHIFT;
+		write_tc_c0_tcbind(tcbind);
+
+		/* Set exclusive TC, non-active, master */
+		vpeconf0 = read_vpe_c0_vpeconf0();
+		vpeconf0 &= ~(VPECONF0_XTC | VPECONF0_VPA);
+		vpeconf0 |= t << VPECONF0_XTC_SHIFT;
+		vpeconf0 |= VPECONF0_MVP;
+		write_vpe_c0_vpeconf0(vpeconf0);
+
+		/* Declare TC non-active, non-allocatable & interrupt exempt */
+		tcstatus = read_tc_c0_tcstatus();
+		tcstatus &= ~(TCSTATUS_A | TCSTATUS_DA);
+		tcstatus |= TCSTATUS_IXMT;
+		write_tc_c0_tcstatus(tcstatus);
+
+		/* Halt the TC */
+		write_tc_c0_tchalt(TCHALT_H);
+
+		/* Allow only 1 TC to execute */
+		vpecontrol = read_vpe_c0_vpecontrol();
+		vpecontrol &= ~VPECONTROL_TE;
+		write_vpe_c0_vpecontrol(vpecontrol);
+
+		/* Copy (most of) Status from VPE 0 */
+		status = read_c0_status();
+		status &= ~(ST0_IM | ST0_IE | ST0_KSU);
+		status |= ST0_CU0;
+		write_vpe_c0_status(status);
+
+		/* Copy Config from VPE 0 */
+		write_vpe_c0_config(read_c0_config());
+		write_vpe_c0_config7(read_c0_config7());
+
+		/* Ensure no software interrupts are pending */
+		write_vpe_c0_cause(0);
+
+		/* Sync Count */
+		write_vpe_c0_count(read_c0_count());
+	}
+
+	/* Leave VPE configuration state */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+static void __init cps_smp_setup(void)
+{
+	unsigned int ncores, nvpes, core_vpes;
+	int c, v;
+	u32 core_cfg, *entry_code;
+
+	/* Detect & record VPE topology */
+	ncores = mips_cm_numcores();
+	pr_info("VPE topology ");
+	for (c = nvpes = 0; c < ncores; c++) {
+		if (cpu_has_mipsmt && config_enabled(CONFIG_MIPS_MT_SMP)) {
+			write_gcr_cl_other(c << CM_GCR_Cx_OTHER_CORENUM_SHF);
+			core_cfg = read_gcr_co_config();
+			core_vpes = ((core_cfg & CM_GCR_Cx_CONFIG_PVPE_MSK) >>
+				     CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
+		} else {
+			core_vpes = 1;
+		}
+
+		pr_cont("%c%u", c ? ',' : '{', core_vpes);
+
+		for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
+			cpu_data[nvpes + v].core = c;
+			cpu_data[nvpes + v].vpe_id = v;
+		}
+
+		nvpes += core_vpes;
+	}
+	pr_cont("} total %u\n", nvpes);
+
+	/* Indicate present CPUs (CPU being synonymous with VPE) */
+	for (v = 0; v < min_t(unsigned, nvpes, NR_CPUS); v++) {
+		set_cpu_possible(v, true);
+		set_cpu_present(v, true);
+		__cpu_number_map[v] = v;
+		__cpu_logical_map[v] = v;
+	}
+
+	/* Core 0 is powered up (we're running on it) */
+	bitmap_set(core_power, 0, 1);
+
+	/* Disable MT - we only want to run 1 TC per VPE */
+	dmt();
+
+	/* Initialise core 0 */
+	init_core();
+
+	/* Patch the start of mips_cps_core_entry to provide the CM base */
+	entry_code = (u32 *)&mips_cps_core_entry;
+	UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
+
+	/* Make core 0 coherent with everything */
+	write_gcr_cl_coherence(0xff);
+}
+
+static void __init cps_prepare_cpus(unsigned int max_cpus)
+{
+	mips_mt_set_cpuoptions();
+}
+
+static void boot_core(struct boot_config *cfg)
+{
+	u32 access;
+
+	/* Select the appropriate core */
+	write_gcr_cl_other(cfg->core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+
+	/* Set its reset vector */
+	write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
+
+	/* Ensure its coherency is disabled */
+	write_gcr_co_coherence(0);
+
+	/* Ensure the core can access the GCRs */
+	access = read_gcr_access();
+	access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + cfg->core);
+	write_gcr_access(access);
+
+	/* Copy cfg */
+	mips_cps_bootcfg = *cfg;
+
+	if (mips_cpc_present()) {
+		/* Select the appropriate core */
+		write_cpc_cl_other(cfg->core << CPC_Cx_OTHER_CORENUM_SHF);
+
+		/* Reset the core */
+		write_cpc_co_cmd(CPC_Cx_CMD_RESET);
+	} else {
+		/* Take the core out of reset */
+		write_gcr_co_reset_release(0);
+	}
+
+	/* The core is now powered up */
+	bitmap_set(core_power, cfg->core, 1);
+}
+
+static void boot_vpe(void *info)
+{
+	struct boot_config *cfg = info;
+	u32 tcstatus, vpeconf0;
+
+	/* Enter VPE configuration state */
+	dvpe();
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	settc(cfg->vpe);
+
+	/* Set the TC restart PC */
+	write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+	/* Activate the TC, allow interrupts */
+	tcstatus = read_tc_c0_tcstatus();
+	tcstatus &= ~TCSTATUS_IXMT;
+	tcstatus |= TCSTATUS_A;
+	write_tc_c0_tcstatus(tcstatus);
+
+	/* Clear the TC halt bit */
+	write_tc_c0_tchalt(0);
+
+	/* Activate the VPE */
+	vpeconf0 = read_vpe_c0_vpeconf0();
+	vpeconf0 |= VPECONF0_VPA;
+	write_vpe_c0_vpeconf0(vpeconf0);
+
+	/* Set the stack & global pointer registers */
+	write_tc_gpr_sp(cfg->sp);
+	write_tc_gpr_gp(cfg->gp);
+
+	/* Leave VPE configuration state */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* Enable other VPEs to execute */
+	evpe(EVPE_ENABLE);
+}
+
+static void cps_boot_secondary(int cpu, struct task_struct *idle)
+{
+	struct boot_config cfg;
+	unsigned int remote;
+	int err;
+
+	cfg.core = cpu_data[cpu].core;
+	cfg.vpe = cpu_data[cpu].vpe_id;
+	cfg.pc = (unsigned long)&smp_bootstrap;
+	cfg.sp = __KSTK_TOS(idle);
+	cfg.gp = (unsigned long)task_thread_info(idle);
+
+	if (!test_bit(cfg.core, core_power)) {
+		/* Boot a VPE on a powered down core */
+		boot_core(&cfg);
+		return;
+	}
+
+	if (cfg.core != current_cpu_data.core) {
+		/* Boot a VPE on another powered up core */
+		for (remote = 0; remote < NR_CPUS; remote++) {
+			if (cpu_data[remote].core != cfg.core)
+				continue;
+			if (cpu_online(remote))
+				break;
+		}
+		BUG_ON(remote >= NR_CPUS);
+
+		err = smp_call_function_single(remote, boot_vpe, &cfg, 1);
+		if (err)
+			panic("Failed to call remote CPU\n");
+		return;
+	}
+
+	/* Boot a VPE on this core */
+	boot_vpe(&cfg);
+}
+
+static void cps_init_secondary(void)
+{
+	/* Disable MT - we only want to run 1 TC per VPE */
+	dmt();
+
+	/* TODO: revisit this assumption once hotplug is implemented */
+	if (current_cpu_data.vpe_id == 0)
+		init_core();
+
+	change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
+				 STATUSF_IP6 | STATUSF_IP7);
+}
+
+static void cps_smp_finish(void)
+{
+	write_c0_compare(read_c0_count() + (8 * mips_hpt_frequency / HZ));
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/* If we have an FPU, enroll ourselves in the FPU-full mask */
+	if (cpu_has_fpu)
+		cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+	local_irq_enable();
+}
+
+static void cps_cpus_done(void)
+{
+}
+
+static struct plat_smp_ops cps_smp_ops = {
+	.smp_setup		= cps_smp_setup,
+	.prepare_cpus		= cps_prepare_cpus,
+	.boot_secondary		= cps_boot_secondary,
+	.init_secondary		= cps_init_secondary,
+	.smp_finish		= cps_smp_finish,
+	.send_ipi_single	= gic_send_ipi_single,
+	.send_ipi_mask		= gic_send_ipi_mask,
+	.cpus_done		= cps_cpus_done,
+};
+
+int register_cps_smp_ops(void)
+{
+	if (!mips_cm_present()) {
+		pr_warn("MIPS CPS SMP unable to proceed without a CM\n");
+		return -ENODEV;
+	}
+
+	/* check we have a GIC - we need one for IPIs */
+	if (!(read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX_MSK)) {
+		pr_warn("MIPS CPS SMP unable to proceed without a GIC\n");
+		return -ENODEV;
+	}
+
+	register_smp_ops(&cps_smp_ops);
+	return 0;
+}
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c
new file mode 100644
index 000000000000..3bb1f92ab525
--- /dev/null
+++ b/arch/mips/kernel/smp-gic.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * Based on smp-cmp.c:
+ *  Copyright (C) 2007 MIPS Technologies, Inc.
+ *  Author: Chris Dearman (chris@mips.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/printk.h>
+
+#include <asm/gic.h>
+#include <asm/smp-ops.h>
+
+void gic_send_ipi_single(int cpu, unsigned int action)
+{
+	unsigned long flags;
+	unsigned int intr;
+
+	pr_debug("CPU%d: %s cpu %d action %u status %08x\n",
+		 smp_processor_id(), __func__, cpu, action, read_c0_status());
+
+	local_irq_save(flags);
+
+	switch (action) {
+	case SMP_CALL_FUNCTION:
+		intr = plat_ipi_call_int_xlate(cpu);
+		break;
+
+	case SMP_RESCHEDULE_YOURSELF:
+		intr = plat_ipi_resched_int_xlate(cpu);
+		break;
+
+	default:
+		BUG();
+	}
+
+	gic_send_ipi(intr);
+	local_irq_restore(flags);
+}
+
+void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+	unsigned int i;
+
+	for_each_cpu(i, mask)
+		gic_send_ipi_single(i, action);
+}
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index b242e2c10ea0..f9a693a6aaa7 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -205,8 +205,10 @@ void spram_config(void)
 	case CPU_34K:
 	case CPU_74K:
 	case CPU_1004K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e0b499694d18..074e857ced28 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -10,6 +10,7 @@
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2002, 2003, 2004, 2005, 2007  Maciej W. Rozycki
  * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
  */
 #include <linux/bug.h>
 #include <linux/compiler.h>
@@ -47,6 +48,7 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/module.h>
+#include <asm/msa.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
@@ -77,8 +79,10 @@ extern asmlinkage void handle_ri_rdhwr(void);
 extern asmlinkage void handle_cpu(void);
 extern asmlinkage void handle_ov(void);
 extern asmlinkage void handle_tr(void);
+extern asmlinkage void handle_msa_fpe(void);
 extern asmlinkage void handle_fpe(void);
 extern asmlinkage void handle_ftlb(void);
+extern asmlinkage void handle_msa(void);
 extern asmlinkage void handle_mdmx(void);
 extern asmlinkage void handle_watch(void);
 extern asmlinkage void handle_mt(void);
@@ -861,6 +865,11 @@ asmlinkage void do_bp(struct pt_regs *regs)
 	enum ctx_state prev_state;
 	unsigned long epc;
 	u16 instr[2];
+	mm_segment_t seg;
+
+	seg = get_fs();
+	if (!user_mode(regs))
+		set_fs(KERNEL_DS);
 
 	prev_state = exception_enter();
 	if (get_isa16_mode(regs->cp0_epc)) {
@@ -870,17 +879,19 @@ asmlinkage void do_bp(struct pt_regs *regs)
 			if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) ||
 			    (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))))
 				goto out_sigsegv;
-		    opcode = (instr[0] << 16) | instr[1];
+			opcode = (instr[0] << 16) | instr[1];
 		} else {
-		    /* MIPS16e mode */
-		    if (__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)))
+			/* MIPS16e mode */
+			if (__get_user(instr[0],
+				       (u16 __user *)msk_isa16_mode(epc)))
 				goto out_sigsegv;
-		    bcode = (instr[0] >> 6) & 0x3f;
-		    do_trap_or_bp(regs, bcode, "Break");
-		    goto out;
+			bcode = (instr[0] >> 6) & 0x3f;
+			do_trap_or_bp(regs, bcode, "Break");
+			goto out;
 		}
 	} else {
-		if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+		if (__get_user(opcode,
+			       (unsigned int __user *) exception_epc(regs)))
 			goto out_sigsegv;
 	}
 
@@ -918,6 +929,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
 	do_trap_or_bp(regs, bcode, "Break");
 
 out:
+	set_fs(seg);
 	exception_exit(prev_state);
 	return;
 
@@ -931,8 +943,13 @@ asmlinkage void do_tr(struct pt_regs *regs)
 	u32 opcode, tcode = 0;
 	enum ctx_state prev_state;
 	u16 instr[2];
+	mm_segment_t seg;
 	unsigned long epc = msk_isa16_mode(exception_epc(regs));
 
+	seg = get_fs();
+	if (!user_mode(regs))
+		set_fs(get_ds());
+
 	prev_state = exception_enter();
 	if (get_isa16_mode(regs->cp0_epc)) {
 		if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
@@ -953,6 +970,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
 	do_trap_or_bp(regs, tcode, "Trap");
 
 out:
+	set_fs(seg);
 	exception_exit(prev_state);
 	return;
 
@@ -1074,6 +1092,76 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 	return NOTIFY_OK;
 }
 
+static int enable_restore_fp_context(int msa)
+{
+	int err, was_fpu_owner;
+
+	if (!used_math()) {
+		/* First time FP context user. */
+		err = init_fpu();
+		if (msa && !err)
+			enable_msa();
+		if (!err)
+			set_used_math();
+		return err;
+	}
+
+	/*
+	 * This task has formerly used the FP context.
+	 *
+	 * If this thread has no live MSA vector context then we can simply
+	 * restore the scalar FP context. If it has live MSA vector context
+	 * (that is, it has or may have used MSA since last performing a
+	 * function call) then we'll need to restore the vector context. This
+	 * applies even if we're currently only executing a scalar FP
+	 * instruction. This is because if we were to later execute an MSA
+	 * instruction then we'd either have to:
+	 *
+	 *  - Restore the vector context & clobber any registers modified by
+	 *    scalar FP instructions between now & then.
+	 *
+	 * or
+	 *
+	 *  - Not restore the vector context & lose the most significant bits
+	 *    of all vector registers.
+	 *
+	 * Neither of those options is acceptable. We cannot restore the least
+	 * significant bits of the registers now & only restore the most
+	 * significant bits later because the most significant bits of any
+	 * vector registers whose aliased FP register is modified now will have
+	 * been zeroed. We'd have no way to know that when restoring the vector
+	 * context & thus may load an outdated value for the most significant
+	 * bits of a vector register.
+	 */
+	if (!msa && !thread_msa_context_live())
+		return own_fpu(1);
+
+	/*
+	 * This task is using or has previously used MSA. Thus we require
+	 * that Status.FR == 1.
+	 */
+	was_fpu_owner = is_fpu_owner();
+	err = own_fpu(0);
+	if (err)
+		return err;
+
+	enable_msa();
+	write_msa_csr(current->thread.fpu.msacsr);
+	set_thread_flag(TIF_USEDMSA);
+
+	/*
+	 * If this is the first time that the task is using MSA and it has
+	 * previously used scalar FP in this time slice then we already nave
+	 * FP context which we shouldn't clobber.
+	 */
+	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+		return 0;
+
+	/* We need to restore the vector context. */
+	restore_msa(current);
+	return 0;
+}
+
 asmlinkage void do_cpu(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
@@ -1153,12 +1241,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 		/* Fall through.  */
 
 	case 1:
-		if (used_math())	/* Using the FPU again.	 */
-			err = own_fpu(1);
-		else {			/* First time FPU user.	 */
-			err = init_fpu();
-			set_used_math();
-		}
+		err = enable_restore_fp_context(0);
 
 		if (!raw_cpu_has_fpu || err) {
 			int sig;
@@ -1183,6 +1266,37 @@ out:
 	exception_exit(prev_state);
 }
 
+asmlinkage void do_msa_fpe(struct pt_regs *regs)
+{
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
+	die_if_kernel("do_msa_fpe invoked from kernel context!", regs);
+	force_sig(SIGFPE, current);
+	exception_exit(prev_state);
+}
+
+asmlinkage void do_msa(struct pt_regs *regs)
+{
+	enum ctx_state prev_state;
+	int err;
+
+	prev_state = exception_enter();
+
+	if (!cpu_has_msa || test_thread_flag(TIF_32BIT_FPREGS)) {
+		force_sig(SIGILL, current);
+		goto out;
+	}
+
+	die_if_kernel("do_msa invoked from kernel context!", regs);
+
+	err = enable_restore_fp_context(1);
+	if (err)
+		force_sig(SIGILL, current);
+out:
+	exception_exit(prev_state);
+}
+
 asmlinkage void do_mdmx(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
@@ -1337,8 +1451,10 @@ static inline void parity_protection_init(void)
 	case CPU_34K:
 	case CPU_74K:
 	case CPU_1004K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
@@ -2017,6 +2133,7 @@ void __init trap_init(void)
 	set_except_vector(11, handle_cpu);
 	set_except_vector(12, handle_ov);
 	set_except_vector(13, handle_tr);
+	set_except_vector(14, handle_msa_fpe);
 
 	if (current_cpu_type() == CPU_R6000 ||
 	    current_cpu_type() == CPU_R6000A) {
@@ -2040,6 +2157,7 @@ void __init trap_init(void)
 		set_except_vector(15, handle_fpe);
 
 	set_except_vector(16, handle_ftlb);
+	set_except_vector(21, handle_msa);
 	set_except_vector(22, handle_mdmx);
 
 	if (cpu_has_mcheck)
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index c369a5d35527..2b3517214d6d 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  *
  * This file contains exception handler for address error exception with the
  * special capability to execute faulting instructions in software.  The
@@ -110,8 +111,8 @@ extern void show_registers(struct pt_regs *regs);
 #ifdef __BIG_ENDIAN
 #define     LoadHW(addr, value, res)  \
 		__asm__ __volatile__ (".set\tnoat\n"        \
-			"1:\tlb\t%0, 0(%2)\n"               \
-			"2:\tlbu\t$1, 1(%2)\n\t"            \
+			"1:\t"user_lb("%0", "0(%2)")"\n"    \
+			"2:\t"user_lbu("$1", "1(%2)")"\n\t" \
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
 			"li\t%1, 0\n"                       \
@@ -130,8 +131,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
-			"1:\tlwl\t%0, (%2)\n"               \
-			"2:\tlwr\t%0, 3(%2)\n\t"            \
+			"1:\t"user_lwl("%0", "(%2)")"\n"    \
+			"2:\t"user_lwr("%0", "3(%2)")"\n\t" \
 			"li\t%1, 0\n"                       \
 			"3:\n\t"                            \
 			".insn\n\t"                         \
@@ -149,8 +150,8 @@ extern void show_registers(struct pt_regs *regs);
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
-			"1:\tlbu\t%0, 0(%2)\n"              \
-			"2:\tlbu\t$1, 1(%2)\n\t"            \
+			"1:\t"user_lbu("%0", "0(%2)")"\n"   \
+			"2:\t"user_lbu("$1", "1(%2)")"\n\t" \
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
 			"li\t%1, 0\n"                       \
@@ -170,8 +171,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
-			"1:\tlwl\t%0, (%2)\n"               \
-			"2:\tlwr\t%0, 3(%2)\n\t"            \
+			"1:\t"user_lwl("%0", "(%2)")"\n"    \
+			"2:\t"user_lwr("%0", "3(%2)")"\n\t" \
 			"dsll\t%0, %0, 32\n\t"              \
 			"dsrl\t%0, %0, 32\n\t"              \
 			"li\t%1, 0\n"                       \
@@ -209,9 +210,9 @@ extern void show_registers(struct pt_regs *regs);
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
-			"1:\tsb\t%1, 1(%2)\n\t"             \
+			"1:\t"user_sb("%1", "1(%2)")"\n"    \
 			"srl\t$1, %1, 0x8\n"                \
-			"2:\tsb\t$1, 0(%2)\n\t"             \
+			"2:\t"user_sb("$1", "0(%2)")"\n"    \
 			".set\tat\n\t"                      \
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
@@ -229,8 +230,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
-			"1:\tswl\t%1,(%2)\n"                \
-			"2:\tswr\t%1, 3(%2)\n\t"            \
+			"1:\t"user_swl("%1", "(%2)")"\n"    \
+			"2:\t"user_swr("%1", "3(%2)")"\n\t" \
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
 			".insn\n\t"                         \
@@ -267,8 +268,8 @@ extern void show_registers(struct pt_regs *regs);
 #ifdef __LITTLE_ENDIAN
 #define     LoadHW(addr, value, res)  \
 		__asm__ __volatile__ (".set\tnoat\n"        \
-			"1:\tlb\t%0, 1(%2)\n"               \
-			"2:\tlbu\t$1, 0(%2)\n\t"            \
+			"1:\t"user_lb("%0", "1(%2)")"\n"    \
+			"2:\t"user_lbu("$1", "0(%2)")"\n\t" \
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
 			"li\t%1, 0\n"                       \
@@ -287,8 +288,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
-			"1:\tlwl\t%0, 3(%2)\n"              \
-			"2:\tlwr\t%0, (%2)\n\t"             \
+			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
+			"2:\t"user_lwr("%0", "(%2)")"\n\t"  \
 			"li\t%1, 0\n"                       \
 			"3:\n\t"                            \
 			".insn\n\t"                         \
@@ -306,8 +307,8 @@ extern void show_registers(struct pt_regs *regs);
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
-			"1:\tlbu\t%0, 1(%2)\n"              \
-			"2:\tlbu\t$1, 0(%2)\n\t"            \
+			"1:\t"user_lbu("%0", "1(%2)")"\n"   \
+			"2:\t"user_lbu("$1", "0(%2)")"\n\t" \
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
 			"li\t%1, 0\n"                       \
@@ -327,8 +328,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
-			"1:\tlwl\t%0, 3(%2)\n"              \
-			"2:\tlwr\t%0, (%2)\n\t"             \
+			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
+			"2:\t"user_lwr("%0", "(%2)")"\n\t"  \
 			"dsll\t%0, %0, 32\n\t"              \
 			"dsrl\t%0, %0, 32\n\t"              \
 			"li\t%1, 0\n"                       \
@@ -366,9 +367,9 @@ extern void show_registers(struct pt_regs *regs);
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
-			"1:\tsb\t%1, 0(%2)\n\t"             \
+			"1:\t"user_sb("%1", "0(%2)")"\n"    \
 			"srl\t$1,%1, 0x8\n"                 \
-			"2:\tsb\t$1, 1(%2)\n\t"             \
+			"2:\t"user_sb("$1", "1(%2)")"\n"    \
 			".set\tat\n\t"                      \
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
@@ -386,8 +387,8 @@ extern void show_registers(struct pt_regs *regs);
 
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
-			"1:\tswl\t%1, 3(%2)\n"              \
-			"2:\tswr\t%1, (%2)\n\t"             \
+			"1:\t"user_swl("%1", "3(%2)")"\n"   \
+			"2:\t"user_swr("%1", "(%2)")"\n\t"  \
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
 			".insn\n\t"                         \
@@ -430,7 +431,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	unsigned long origpc;
 	unsigned long orig31;
 	void __user *fault_addr = NULL;
-
+#ifdef	CONFIG_EVA
+	mm_segment_t seg;
+#endif
 	origpc = (unsigned long)pc;
 	orig31 = regs->regs[31];
 
@@ -475,6 +478,88 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 		 * The remaining opcodes are the ones that are really of
 		 * interest.
 		 */
+#ifdef CONFIG_EVA
+	case spec3_op:
+		/*
+		 * we can land here only from kernel accessing user memory,
+		 * so we need to "switch" the address limit to user space, so
+		 * address check can work properly.
+		 */
+		seg = get_fs();
+		set_fs(USER_DS);
+		switch (insn.spec3_format.func) {
+		case lhe_op:
+			if (!access_ok(VERIFY_READ, addr, 2)) {
+				set_fs(seg);
+				goto sigbus;
+			}
+			LoadHW(addr, value, res);
+			if (res) {
+				set_fs(seg);
+				goto fault;
+			}
+			compute_return_epc(regs);
+			regs->regs[insn.spec3_format.rt] = value;
+			break;
+		case lwe_op:
+			if (!access_ok(VERIFY_READ, addr, 4)) {
+				set_fs(seg);
+				goto sigbus;
+			}
+				LoadW(addr, value, res);
+			if (res) {
+				set_fs(seg);
+				goto fault;
+			}
+			compute_return_epc(regs);
+			regs->regs[insn.spec3_format.rt] = value;
+			break;
+		case lhue_op:
+			if (!access_ok(VERIFY_READ, addr, 2)) {
+				set_fs(seg);
+				goto sigbus;
+			}
+			LoadHWU(addr, value, res);
+			if (res) {
+				set_fs(seg);
+				goto fault;
+			}
+			compute_return_epc(regs);
+			regs->regs[insn.spec3_format.rt] = value;
+			break;
+		case she_op:
+			if (!access_ok(VERIFY_WRITE, addr, 2)) {
+				set_fs(seg);
+				goto sigbus;
+			}
+			compute_return_epc(regs);
+			value = regs->regs[insn.spec3_format.rt];
+			StoreHW(addr, value, res);
+			if (res) {
+				set_fs(seg);
+				goto fault;
+			}
+			break;
+		case swe_op:
+			if (!access_ok(VERIFY_WRITE, addr, 4)) {
+				set_fs(seg);
+				goto sigbus;
+			}
+			compute_return_epc(regs);
+			value = regs->regs[insn.spec3_format.rt];
+			StoreW(addr, value, res);
+			if (res) {
+				set_fs(seg);
+				goto fault;
+			}
+			break;
+		default:
+			set_fs(seg);
+			goto sigill;
+		}
+		set_fs(seg);
+		break;
+#endif
 	case lh_op:
 		if (!access_ok(VERIFY_READ, addr, 2))
 			goto sigbus;
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index a6adffbb4e5f..2e4825e48388 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -8,6 +8,7 @@
  * Copyright (C) 1998, 1999 Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  */
 #include <linux/errno.h>
 #include <asm/asm.h>
@@ -296,7 +297,7 @@ LEAF(csum_partial)
  * checksum and copy routines based on memcpy.S
  *
  *	csum_partial_copy_nocheck(src, dst, len, sum)
- *	__csum_partial_copy_user(src, dst, len, sum, errp)
+ *	__csum_partial_copy_kernel(src, dst, len, sum, errp)
  *
  * See "Spec" in memcpy.S for details.	Unlike __copy_user, all
  * function in this file use the standard calling convention.
@@ -327,20 +328,58 @@ LEAF(csum_partial)
  * These handlers do not need to overwrite any data.
  */
 
-#define EXC(inst_reg,addr,handler)		\
-9:	inst_reg, addr;				\
-	.section __ex_table,"a";		\
-	PTR	9b, handler;			\
-	.previous
+/* Instruction type */
+#define LD_INSN 1
+#define ST_INSN 2
+#define LEGACY_MODE 1
+#define EVA_MODE    2
+#define USEROP   1
+#define KERNELOP 2
+
+/*
+ * Wrapper to add an entry in the exception table
+ * in case the insn causes a memory exception.
+ * Arguments:
+ * insn    : Load/store instruction
+ * type    : Instruction type
+ * reg     : Register
+ * addr    : Address
+ * handler : Exception handler
+ */
+#define EXC(insn, type, reg, addr, handler)	\
+	.if \mode == LEGACY_MODE;		\
+9:		insn reg, addr;			\
+		.section __ex_table,"a";	\
+		PTR	9b, handler;		\
+		.previous;			\
+	/* This is enabled in EVA mode */	\
+	.else;					\
+		/* If loading from user or storing to user */	\
+		.if ((\from == USEROP) && (type == LD_INSN)) || \
+		    ((\to == USEROP) && (type == ST_INSN));	\
+9:			__BUILD_EVA_INSN(insn##e, reg, addr);	\
+			.section __ex_table,"a";		\
+			PTR	9b, handler;			\
+			.previous;				\
+		.else;						\
+			/* EVA without exception */		\
+			insn reg, addr;				\
+		.endif;						\
+	.endif
+
+#undef LOAD
 
 #ifdef USE_DOUBLE
 
-#define LOAD   ld
-#define LOADL  ldl
-#define LOADR  ldr
-#define STOREL sdl
-#define STORER sdr
-#define STORE  sd
+#define LOADK	ld /* No exception */
+#define LOAD(reg, addr, handler)	EXC(ld, LD_INSN, reg, addr, handler)
+#define LOADBU(reg, addr, handler)	EXC(lbu, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler)	EXC(ldl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler)	EXC(ldr, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler)	EXC(sb, ST_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler)	EXC(sdl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler)	EXC(sdr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler)	EXC(sd, ST_INSN, reg, addr, handler)
 #define ADD    daddu
 #define SUB    dsubu
 #define SRL    dsrl
@@ -352,12 +391,15 @@ LEAF(csum_partial)
 
 #else
 
-#define LOAD   lw
-#define LOADL  lwl
-#define LOADR  lwr
-#define STOREL swl
-#define STORER swr
-#define STORE  sw
+#define LOADK	lw /* No exception */
+#define LOAD(reg, addr, handler)	EXC(lw, LD_INSN, reg, addr, handler)
+#define LOADBU(reg, addr, handler)	EXC(lbu, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler)	EXC(lwl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler)	EXC(lwr, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler)	EXC(sb, ST_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler)	EXC(swl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler)	EXC(swr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler)	EXC(sw, ST_INSN, reg, addr, handler)
 #define ADD    addu
 #define SUB    subu
 #define SRL    srl
@@ -396,14 +438,20 @@ LEAF(csum_partial)
 	.set	at=v1
 #endif
 
-LEAF(__csum_partial_copy_user)
+	.macro __BUILD_CSUM_PARTIAL_COPY_USER mode, from, to, __nocheck
+
 	PTR_ADDU	AT, src, len	/* See (1) above. */
+	/* initialize __nocheck if this the first time we execute this
+	 * macro
+	 */
 #ifdef CONFIG_64BIT
 	move	errptr, a4
 #else
 	lw	errptr, 16(sp)
 #endif
-FEXPORT(csum_partial_copy_nocheck)
+	.if \__nocheck == 1
+	FEXPORT(csum_partial_copy_nocheck)
+	.endif
 	move	sum, zero
 	move	odd, zero
 	/*
@@ -419,48 +467,48 @@ FEXPORT(csum_partial_copy_nocheck)
 	 */
 	sltu	t2, len, NBYTES
 	and	t1, dst, ADDRMASK
-	bnez	t2, .Lcopy_bytes_checklen
+	bnez	t2, .Lcopy_bytes_checklen\@
 	 and	t0, src, ADDRMASK
 	andi	odd, dst, 0x1			/* odd buffer? */
-	bnez	t1, .Ldst_unaligned
+	bnez	t1, .Ldst_unaligned\@
 	 nop
-	bnez	t0, .Lsrc_unaligned_dst_aligned
+	bnez	t0, .Lsrc_unaligned_dst_aligned\@
 	/*
 	 * use delay slot for fall-through
 	 * src and dst are aligned; need to compute rem
 	 */
-.Lboth_aligned:
+.Lboth_aligned\@:
 	 SRL	t0, len, LOG_NBYTES+3	 # +3 for 8 units/iter
-	beqz	t0, .Lcleanup_both_aligned # len < 8*NBYTES
+	beqz	t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES
 	 nop
 	SUB	len, 8*NBYTES		# subtract here for bgez loop
 	.align	4
 1:
-EXC(	LOAD	t0, UNIT(0)(src),	.Ll_exc)
-EXC(	LOAD	t1, UNIT(1)(src),	.Ll_exc_copy)
-EXC(	LOAD	t2, UNIT(2)(src),	.Ll_exc_copy)
-EXC(	LOAD	t3, UNIT(3)(src),	.Ll_exc_copy)
-EXC(	LOAD	t4, UNIT(4)(src),	.Ll_exc_copy)
-EXC(	LOAD	t5, UNIT(5)(src),	.Ll_exc_copy)
-EXC(	LOAD	t6, UNIT(6)(src),	.Ll_exc_copy)
-EXC(	LOAD	t7, UNIT(7)(src),	.Ll_exc_copy)
+	LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+	LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+	LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+	LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
+	LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@)
+	LOAD(t5, UNIT(5)(src), .Ll_exc_copy\@)
+	LOAD(t6, UNIT(6)(src), .Ll_exc_copy\@)
+	LOAD(t7, UNIT(7)(src), .Ll_exc_copy\@)
 	SUB	len, len, 8*NBYTES
 	ADD	src, src, 8*NBYTES
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc\@)
 	ADDC(sum, t0)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc\@)
 	ADDC(sum, t1)
-EXC(	STORE	t2, UNIT(2)(dst),	.Ls_exc)
+	STORE(t2, UNIT(2)(dst),	.Ls_exc\@)
 	ADDC(sum, t2)
-EXC(	STORE	t3, UNIT(3)(dst),	.Ls_exc)
+	STORE(t3, UNIT(3)(dst),	.Ls_exc\@)
 	ADDC(sum, t3)
-EXC(	STORE	t4, UNIT(4)(dst),	.Ls_exc)
+	STORE(t4, UNIT(4)(dst),	.Ls_exc\@)
 	ADDC(sum, t4)
-EXC(	STORE	t5, UNIT(5)(dst),	.Ls_exc)
+	STORE(t5, UNIT(5)(dst),	.Ls_exc\@)
 	ADDC(sum, t5)
-EXC(	STORE	t6, UNIT(6)(dst),	.Ls_exc)
+	STORE(t6, UNIT(6)(dst),	.Ls_exc\@)
 	ADDC(sum, t6)
-EXC(	STORE	t7, UNIT(7)(dst),	.Ls_exc)
+	STORE(t7, UNIT(7)(dst),	.Ls_exc\@)
 	ADDC(sum, t7)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 8*NBYTES
@@ -471,44 +519,44 @@ EXC(	STORE	t7, UNIT(7)(dst),	.Ls_exc)
 	/*
 	 * len == the number of bytes left to copy < 8*NBYTES
 	 */
-.Lcleanup_both_aligned:
+.Lcleanup_both_aligned\@:
 #define rem t7
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	 sltu	t0, len, 4*NBYTES
-	bnez	t0, .Lless_than_4units
+	bnez	t0, .Lless_than_4units\@
 	 and	rem, len, (NBYTES-1)	# rem = len % NBYTES
 	/*
 	 * len >= 4*NBYTES
 	 */
-EXC(	LOAD	t0, UNIT(0)(src),	.Ll_exc)
-EXC(	LOAD	t1, UNIT(1)(src),	.Ll_exc_copy)
-EXC(	LOAD	t2, UNIT(2)(src),	.Ll_exc_copy)
-EXC(	LOAD	t3, UNIT(3)(src),	.Ll_exc_copy)
+	LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+	LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+	LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+	LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
 	SUB	len, len, 4*NBYTES
 	ADD	src, src, 4*NBYTES
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc\@)
 	ADDC(sum, t0)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc\@)
 	ADDC(sum, t1)
-EXC(	STORE	t2, UNIT(2)(dst),	.Ls_exc)
+	STORE(t2, UNIT(2)(dst),	.Ls_exc\@)
 	ADDC(sum, t2)
-EXC(	STORE	t3, UNIT(3)(dst),	.Ls_exc)
+	STORE(t3, UNIT(3)(dst),	.Ls_exc\@)
 	ADDC(sum, t3)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 4*NBYTES
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	.set	noreorder
-.Lless_than_4units:
+.Lless_than_4units\@:
 	/*
 	 * rem = len % NBYTES
 	 */
-	beq	rem, len, .Lcopy_bytes
+	beq	rem, len, .Lcopy_bytes\@
 	 nop
 1:
-EXC(	LOAD	t0, 0(src),		.Ll_exc)
+	LOAD(t0, 0(src), .Ll_exc\@)
 	ADD	src, src, NBYTES
 	SUB	len, len, NBYTES
-EXC(	STORE	t0, 0(dst),		.Ls_exc)
+	STORE(t0, 0(dst), .Ls_exc\@)
 	ADDC(sum, t0)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, NBYTES
@@ -527,20 +575,20 @@ EXC(	STORE	t0, 0(dst),		.Ls_exc)
 	 * more instruction-level parallelism.
 	 */
 #define bits t2
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	 ADD	t1, dst, len	# t1 is just past last byte of dst
 	li	bits, 8*NBYTES
 	SLL	rem, len, 3	# rem = number of bits to keep
-EXC(	LOAD	t0, 0(src),		.Ll_exc)
+	LOAD(t0, 0(src), .Ll_exc\@)
 	SUB	bits, bits, rem # bits = number of bits to discard
 	SHIFT_DISCARD t0, t0, bits
-EXC(	STREST	t0, -1(t1),		.Ls_exc)
+	STREST(t0, -1(t1), .Ls_exc\@)
 	SHIFT_DISCARD_REVERT t0, t0, bits
 	.set reorder
 	ADDC(sum, t0)
-	b	.Ldone
+	b	.Ldone\@
 	.set noreorder
-.Ldst_unaligned:
+.Ldst_unaligned\@:
 	/*
 	 * dst is unaligned
 	 * t0 = src & ADDRMASK
@@ -551,25 +599,25 @@ EXC(	STREST	t0, -1(t1),		.Ls_exc)
 	 * Set match = (src and dst have same alignment)
 	 */
 #define match rem
-EXC(	LDFIRST t3, FIRST(0)(src),	.Ll_exc)
+	LDFIRST(t3, FIRST(0)(src), .Ll_exc\@)
 	ADD	t2, zero, NBYTES
-EXC(	LDREST	t3, REST(0)(src),	.Ll_exc_copy)
+	LDREST(t3, REST(0)(src), .Ll_exc_copy\@)
 	SUB	t2, t2, t1	# t2 = number of bytes copied
 	xor	match, t0, t1
-EXC(	STFIRST t3, FIRST(0)(dst),	.Ls_exc)
+	STFIRST(t3, FIRST(0)(dst), .Ls_exc\@)
 	SLL	t4, t1, 3		# t4 = number of bits to discard
 	SHIFT_DISCARD t3, t3, t4
 	/* no SHIFT_DISCARD_REVERT to handle odd buffer properly */
 	ADDC(sum, t3)
-	beq	len, t2, .Ldone
+	beq	len, t2, .Ldone\@
 	 SUB	len, len, t2
 	ADD	dst, dst, t2
-	beqz	match, .Lboth_aligned
+	beqz	match, .Lboth_aligned\@
 	 ADD	src, src, t2
 
-.Lsrc_unaligned_dst_aligned:
+.Lsrc_unaligned_dst_aligned\@:
 	SRL	t0, len, LOG_NBYTES+2	 # +2 for 4 units/iter
-	beqz	t0, .Lcleanup_src_unaligned
+	beqz	t0, .Lcleanup_src_unaligned\@
 	 and	rem, len, (4*NBYTES-1)	 # rem = len % 4*NBYTES
 1:
 /*
@@ -578,53 +626,53 @@ EXC(	STFIRST t3, FIRST(0)(dst),	.Ls_exc)
  * It's OK to load FIRST(N+1) before REST(N) because the two addresses
  * are to the same unit (unless src is aligned, but it's not).
  */
-EXC(	LDFIRST t0, FIRST(0)(src),	.Ll_exc)
-EXC(	LDFIRST t1, FIRST(1)(src),	.Ll_exc_copy)
+	LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+	LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@)
 	SUB	len, len, 4*NBYTES
-EXC(	LDREST	t0, REST(0)(src),	.Ll_exc_copy)
-EXC(	LDREST	t1, REST(1)(src),	.Ll_exc_copy)
-EXC(	LDFIRST t2, FIRST(2)(src),	.Ll_exc_copy)
-EXC(	LDFIRST t3, FIRST(3)(src),	.Ll_exc_copy)
-EXC(	LDREST	t2, REST(2)(src),	.Ll_exc_copy)
-EXC(	LDREST	t3, REST(3)(src),	.Ll_exc_copy)
+	LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
+	LDREST(t1, REST(1)(src), .Ll_exc_copy\@)
+	LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@)
+	LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@)
+	LDREST(t2, REST(2)(src), .Ll_exc_copy\@)
+	LDREST(t3, REST(3)(src), .Ll_exc_copy\@)
 	ADD	src, src, 4*NBYTES
 #ifdef CONFIG_CPU_SB1
 	nop				# improves slotting
 #endif
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc\@)
 	ADDC(sum, t0)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc\@)
 	ADDC(sum, t1)
-EXC(	STORE	t2, UNIT(2)(dst),	.Ls_exc)
+	STORE(t2, UNIT(2)(dst),	.Ls_exc\@)
 	ADDC(sum, t2)
-EXC(	STORE	t3, UNIT(3)(dst),	.Ls_exc)
+	STORE(t3, UNIT(3)(dst),	.Ls_exc\@)
 	ADDC(sum, t3)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 4*NBYTES
 	bne	len, rem, 1b
 	.set	noreorder
 
-.Lcleanup_src_unaligned:
-	beqz	len, .Ldone
+.Lcleanup_src_unaligned\@:
+	beqz	len, .Ldone\@
 	 and	rem, len, NBYTES-1  # rem = len % NBYTES
-	beq	rem, len, .Lcopy_bytes
+	beq	rem, len, .Lcopy_bytes\@
 	 nop
 1:
-EXC(	LDFIRST t0, FIRST(0)(src),	.Ll_exc)
-EXC(	LDREST	t0, REST(0)(src),	.Ll_exc_copy)
+	LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+	LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
 	ADD	src, src, NBYTES
 	SUB	len, len, NBYTES
-EXC(	STORE	t0, 0(dst),		.Ls_exc)
+	STORE(t0, 0(dst), .Ls_exc\@)
 	ADDC(sum, t0)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, NBYTES
 	bne	len, rem, 1b
 	.set	noreorder
 
-.Lcopy_bytes_checklen:
-	beqz	len, .Ldone
+.Lcopy_bytes_checklen\@:
+	beqz	len, .Ldone\@
 	 nop
-.Lcopy_bytes:
+.Lcopy_bytes\@:
 	/* 0 < len < NBYTES  */
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 #define SHIFT_START 0
@@ -637,12 +685,12 @@ EXC(	STORE	t0, 0(dst),		.Ls_exc)
 	li	t3, SHIFT_START # shift
 /* use .Ll_exc_copy here to return correct sum on fault */
 #define COPY_BYTE(N)			\
-EXC(	lbu	t0, N(src), .Ll_exc_copy);	\
+	LOADBU(t0, N(src), .Ll_exc_copy\@);	\
 	SUB	len, len, 1;		\
-EXC(	sb	t0, N(dst), .Ls_exc);	\
+	STOREB(t0, N(dst), .Ls_exc\@);	\
 	SLLV	t0, t0, t3;		\
 	addu	t3, SHIFT_INC;		\
-	beqz	len, .Lcopy_bytes_done; \
+	beqz	len, .Lcopy_bytes_done\@; \
 	 or	t2, t0
 
 	COPY_BYTE(0)
@@ -653,14 +701,14 @@ EXC(	sb	t0, N(dst), .Ls_exc);	\
 	COPY_BYTE(4)
 	COPY_BYTE(5)
 #endif
-EXC(	lbu	t0, NBYTES-2(src), .Ll_exc_copy)
+	LOADBU(t0, NBYTES-2(src), .Ll_exc_copy\@)
 	SUB	len, len, 1
-EXC(	sb	t0, NBYTES-2(dst), .Ls_exc)
+	STOREB(t0, NBYTES-2(dst), .Ls_exc\@)
 	SLLV	t0, t0, t3
 	or	t2, t0
-.Lcopy_bytes_done:
+.Lcopy_bytes_done\@:
 	ADDC(sum, t2)
-.Ldone:
+.Ldone\@:
 	/* fold checksum */
 #ifdef USE_DOUBLE
 	dsll32	v1, sum, 0
@@ -689,7 +737,7 @@ EXC(	sb	t0, NBYTES-2(dst), .Ls_exc)
 	jr	ra
 	.set noreorder
 
-.Ll_exc_copy:
+.Ll_exc_copy\@:
 	/*
 	 * Copy bytes from src until faulting load address (or until a
 	 * lb faults)
@@ -700,11 +748,11 @@ EXC(	sb	t0, NBYTES-2(dst), .Ls_exc)
 	 *
 	 * Assumes src < THREAD_BUADDR($28)
 	 */
-	LOAD	t0, TI_TASK($28)
+	LOADK	t0, TI_TASK($28)
 	 li	t2, SHIFT_START
-	LOAD	t0, THREAD_BUADDR(t0)
+	LOADK	t0, THREAD_BUADDR(t0)
 1:
-EXC(	lbu	t1, 0(src),	.Ll_exc)
+	LOADBU(t1, 0(src), .Ll_exc\@)
 	ADD	src, src, 1
 	sb	t1, 0(dst)	# can't fault -- we're copy_from_user
 	SLLV	t1, t1, t2
@@ -714,10 +762,10 @@ EXC(	lbu	t1, 0(src),	.Ll_exc)
 	ADD	dst, dst, 1
 	bne	src, t0, 1b
 	.set	noreorder
-.Ll_exc:
-	LOAD	t0, TI_TASK($28)
+.Ll_exc\@:
+	LOADK	t0, TI_TASK($28)
 	 nop
-	LOAD	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	LOADK	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
 	 nop
 	SUB	len, AT, t0		# len number of uncopied bytes
 	/*
@@ -733,7 +781,7 @@ EXC(	lbu	t1, 0(src),	.Ll_exc)
 	 */
 	.set	reorder				/* DADDI_WAR */
 	SUB	src, len, 1
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	.set	noreorder
 1:	sb	zero, 0(dst)
 	ADD	dst, dst, 1
@@ -748,13 +796,31 @@ EXC(	lbu	t1, 0(src),	.Ll_exc)
 	 SUB	src, src, v1
 #endif
 	li	v1, -EFAULT
-	b	.Ldone
+	b	.Ldone\@
 	 sw	v1, (errptr)
 
-.Ls_exc:
+.Ls_exc\@:
 	li	v0, -1 /* invalid checksum */
 	li	v1, -EFAULT
 	jr	ra
 	 sw	v1, (errptr)
 	.set	pop
-	END(__csum_partial_copy_user)
+	.endm
+
+LEAF(__csum_partial_copy_kernel)
+#ifndef CONFIG_EVA
+FEXPORT(__csum_partial_copy_to_user)
+FEXPORT(__csum_partial_copy_from_user)
+#endif
+__BUILD_CSUM_PARTIAL_COPY_USER LEGACY_MODE USEROP USEROP 1
+END(__csum_partial_copy_kernel)
+
+#ifdef CONFIG_EVA
+LEAF(__csum_partial_copy_to_user)
+__BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE KERNELOP USEROP 0
+END(__csum_partial_copy_to_user)
+
+LEAF(__csum_partial_copy_from_user)
+__BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE USEROP KERNELOP 0
+END(__csum_partial_copy_from_user)
+#endif
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index c5c40dad0bbf..c17ef80cf65a 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -10,6 +10,7 @@
  * Copyright (C) 2002 Broadcom, Inc.
  *   memcpy/copy_user author: Mark Vandevoorde
  * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
  *
  * Mnemonic names for arguments to memcpy/__copy_user
  */
@@ -85,11 +86,51 @@
  * they're not protected.
  */
 
-#define EXC(inst_reg,addr,handler)		\
-9:	inst_reg, addr;				\
-	.section __ex_table,"a";		\
-	PTR	9b, handler;			\
-	.previous
+/* Instruction type */
+#define LD_INSN 1
+#define ST_INSN 2
+/* Pretech type */
+#define SRC_PREFETCH 1
+#define DST_PREFETCH 2
+#define LEGACY_MODE 1
+#define EVA_MODE    2
+#define USEROP   1
+#define KERNELOP 2
+
+/*
+ * Wrapper to add an entry in the exception table
+ * in case the insn causes a memory exception.
+ * Arguments:
+ * insn    : Load/store instruction
+ * type    : Instruction type
+ * reg     : Register
+ * addr    : Address
+ * handler : Exception handler
+ */
+
+#define EXC(insn, type, reg, addr, handler)			\
+	.if \mode == LEGACY_MODE;				\
+9:		insn reg, addr;					\
+		.section __ex_table,"a";			\
+		PTR	9b, handler;				\
+		.previous;					\
+	/* This is assembled in EVA mode */			\
+	.else;							\
+		/* If loading from user or storing to user */	\
+		.if ((\from == USEROP) && (type == LD_INSN)) || \
+		    ((\to == USEROP) && (type == ST_INSN));	\
+9:			__BUILD_EVA_INSN(insn##e, reg, addr);	\
+			.section __ex_table,"a";		\
+			PTR	9b, handler;			\
+			.previous;				\
+		.else;						\
+			/*					\
+			 *  Still in EVA, but no need for	\
+			 * exception handler or EVA insn	\
+			 */					\
+			insn reg, addr;				\
+		.endif;						\
+	.endif
 
 /*
  * Only on the 64-bit kernel we can made use of 64-bit registers.
@@ -100,12 +141,13 @@
 
 #ifdef USE_DOUBLE
 
-#define LOAD   ld
-#define LOADL  ldl
-#define LOADR  ldr
-#define STOREL sdl
-#define STORER sdr
-#define STORE  sd
+#define LOADK ld /* No exception */
+#define LOAD(reg, addr, handler)	EXC(ld, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler)	EXC(ldl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler)	EXC(ldr, LD_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler)	EXC(sdl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler)	EXC(sdr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler)	EXC(sd, ST_INSN, reg, addr, handler)
 #define ADD    daddu
 #define SUB    dsubu
 #define SRL    dsrl
@@ -136,12 +178,13 @@
 
 #else
 
-#define LOAD   lw
-#define LOADL  lwl
-#define LOADR  lwr
-#define STOREL swl
-#define STORER swr
-#define STORE  sw
+#define LOADK lw /* No exception */
+#define LOAD(reg, addr, handler)	EXC(lw, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler)	EXC(lwl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler)	EXC(lwr, LD_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler)	EXC(swl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler)	EXC(swr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler)	EXC(sw, ST_INSN, reg, addr, handler)
 #define ADD    addu
 #define SUB    subu
 #define SRL    srl
@@ -154,6 +197,33 @@
 
 #endif /* USE_DOUBLE */
 
+#define LOADB(reg, addr, handler)	EXC(lb, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler)	EXC(sb, ST_INSN, reg, addr, handler)
+
+#define _PREF(hint, addr, type)						\
+	.if \mode == LEGACY_MODE;					\
+		PREF(hint, addr);					\
+	.else;								\
+		.if ((\from == USEROP) && (type == SRC_PREFETCH)) ||	\
+		    ((\to == USEROP) && (type == DST_PREFETCH));	\
+			/*						\
+			 * PREFE has only 9 bits for the offset		\
+			 * compared to PREF which has 16, so it may	\
+			 * need to use the $at register but this	\
+			 * register should remain intact because it's	\
+			 * used later on. Therefore use $v1.		\
+			 */						\
+			.set at=v1;					\
+			PREFE(hint, addr);				\
+			.set noat;					\
+		.else;							\
+			PREF(hint, addr);				\
+		.endif;							\
+	.endif
+
+#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH)
+#define PREFD(hint, addr) _PREF(hint, addr, DST_PREFETCH)
+
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 #define LDFIRST LOADR
 #define LDREST	LOADL
@@ -182,27 +252,23 @@
 	.set	at=v1
 #endif
 
-/*
- * t6 is used as a flag to note inatomic mode.
- */
-LEAF(__copy_user_inatomic)
-	b	__copy_user_common
-	 li	t6, 1
-	END(__copy_user_inatomic)
-
-/*
- * A combined memcpy/__copy_user
- * __copy_user sets len to 0 for success; else to an upper bound of
- * the number of uncopied bytes.
- * memcpy sets v0 to dst.
- */
 	.align	5
-LEAF(memcpy)					/* a0=dst a1=src a2=len */
-	move	v0, dst				/* return value */
-.L__memcpy:
-FEXPORT(__copy_user)
-	li	t6, 0	/* not inatomic */
-__copy_user_common:
+
+	/*
+	 * Macro to build the __copy_user common code
+	 * Arguements:
+	 * mode : LEGACY_MODE or EVA_MODE
+	 * from : Source operand. USEROP or KERNELOP
+	 * to   : Destination operand. USEROP or KERNELOP
+	 */
+	.macro __BUILD_COPY_USER mode, from, to
+
+	/* initialize __memcpy if this the first time we execute this macro */
+	.ifnotdef __memcpy
+	.set __memcpy, 1
+	.hidden __memcpy /* make sure it does not leak */
+	.endif
+
 	/*
 	 * Note: dst & src may be unaligned, len may be 0
 	 * Temps
@@ -217,94 +283,94 @@ __copy_user_common:
 	 *
 	 * If len < NBYTES use byte operations.
 	 */
-	PREF(	0, 0(src) )
-	PREF(	1, 0(dst) )
+	PREFS(	0, 0(src) )
+	PREFD(	1, 0(dst) )
 	sltu	t2, len, NBYTES
 	and	t1, dst, ADDRMASK
-	PREF(	0, 1*32(src) )
-	PREF(	1, 1*32(dst) )
-	bnez	t2, .Lcopy_bytes_checklen
+	PREFS(	0, 1*32(src) )
+	PREFD(	1, 1*32(dst) )
+	bnez	t2, .Lcopy_bytes_checklen\@
 	 and	t0, src, ADDRMASK
-	PREF(	0, 2*32(src) )
-	PREF(	1, 2*32(dst) )
-	bnez	t1, .Ldst_unaligned
+	PREFS(	0, 2*32(src) )
+	PREFD(	1, 2*32(dst) )
+	bnez	t1, .Ldst_unaligned\@
 	 nop
-	bnez	t0, .Lsrc_unaligned_dst_aligned
+	bnez	t0, .Lsrc_unaligned_dst_aligned\@
 	/*
 	 * use delay slot for fall-through
 	 * src and dst are aligned; need to compute rem
 	 */
-.Lboth_aligned:
+.Lboth_aligned\@:
 	 SRL	t0, len, LOG_NBYTES+3	 # +3 for 8 units/iter
-	beqz	t0, .Lcleanup_both_aligned # len < 8*NBYTES
+	beqz	t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES
 	 and	rem, len, (8*NBYTES-1)	 # rem = len % (8*NBYTES)
-	PREF(	0, 3*32(src) )
-	PREF(	1, 3*32(dst) )
+	PREFS(	0, 3*32(src) )
+	PREFD(	1, 3*32(dst) )
 	.align	4
 1:
 	R10KCBARRIER(0(ra))
-EXC(	LOAD	t0, UNIT(0)(src),	.Ll_exc)
-EXC(	LOAD	t1, UNIT(1)(src),	.Ll_exc_copy)
-EXC(	LOAD	t2, UNIT(2)(src),	.Ll_exc_copy)
-EXC(	LOAD	t3, UNIT(3)(src),	.Ll_exc_copy)
+	LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+	LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+	LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+	LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
 	SUB	len, len, 8*NBYTES
-EXC(	LOAD	t4, UNIT(4)(src),	.Ll_exc_copy)
-EXC(	LOAD	t7, UNIT(5)(src),	.Ll_exc_copy)
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc_p8u)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc_p7u)
-EXC(	LOAD	t0, UNIT(6)(src),	.Ll_exc_copy)
-EXC(	LOAD	t1, UNIT(7)(src),	.Ll_exc_copy)
+	LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@)
+	LOAD(t7, UNIT(5)(src), .Ll_exc_copy\@)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc_p8u\@)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc_p7u\@)
+	LOAD(t0, UNIT(6)(src), .Ll_exc_copy\@)
+	LOAD(t1, UNIT(7)(src), .Ll_exc_copy\@)
 	ADD	src, src, 8*NBYTES
 	ADD	dst, dst, 8*NBYTES
-EXC(	STORE	t2, UNIT(-6)(dst),	.Ls_exc_p6u)
-EXC(	STORE	t3, UNIT(-5)(dst),	.Ls_exc_p5u)
-EXC(	STORE	t4, UNIT(-4)(dst),	.Ls_exc_p4u)
-EXC(	STORE	t7, UNIT(-3)(dst),	.Ls_exc_p3u)
-EXC(	STORE	t0, UNIT(-2)(dst),	.Ls_exc_p2u)
-EXC(	STORE	t1, UNIT(-1)(dst),	.Ls_exc_p1u)
-	PREF(	0, 8*32(src) )
-	PREF(	1, 8*32(dst) )
+	STORE(t2, UNIT(-6)(dst), .Ls_exc_p6u\@)
+	STORE(t3, UNIT(-5)(dst), .Ls_exc_p5u\@)
+	STORE(t4, UNIT(-4)(dst), .Ls_exc_p4u\@)
+	STORE(t7, UNIT(-3)(dst), .Ls_exc_p3u\@)
+	STORE(t0, UNIT(-2)(dst), .Ls_exc_p2u\@)
+	STORE(t1, UNIT(-1)(dst), .Ls_exc_p1u\@)
+	PREFS(	0, 8*32(src) )
+	PREFD(	1, 8*32(dst) )
 	bne	len, rem, 1b
 	 nop
 
 	/*
 	 * len == rem == the number of bytes left to copy < 8*NBYTES
 	 */
-.Lcleanup_both_aligned:
-	beqz	len, .Ldone
+.Lcleanup_both_aligned\@:
+	beqz	len, .Ldone\@
 	 sltu	t0, len, 4*NBYTES
-	bnez	t0, .Lless_than_4units
+	bnez	t0, .Lless_than_4units\@
 	 and	rem, len, (NBYTES-1)	# rem = len % NBYTES
 	/*
 	 * len >= 4*NBYTES
 	 */
-EXC(	LOAD	t0, UNIT(0)(src),	.Ll_exc)
-EXC(	LOAD	t1, UNIT(1)(src),	.Ll_exc_copy)
-EXC(	LOAD	t2, UNIT(2)(src),	.Ll_exc_copy)
-EXC(	LOAD	t3, UNIT(3)(src),	.Ll_exc_copy)
+	LOAD( t0, UNIT(0)(src),	.Ll_exc\@)
+	LOAD( t1, UNIT(1)(src),	.Ll_exc_copy\@)
+	LOAD( t2, UNIT(2)(src),	.Ll_exc_copy\@)
+	LOAD( t3, UNIT(3)(src),	.Ll_exc_copy\@)
 	SUB	len, len, 4*NBYTES
 	ADD	src, src, 4*NBYTES
 	R10KCBARRIER(0(ra))
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc_p4u)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc_p3u)
-EXC(	STORE	t2, UNIT(2)(dst),	.Ls_exc_p2u)
-EXC(	STORE	t3, UNIT(3)(dst),	.Ls_exc_p1u)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc_p4u\@)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc_p3u\@)
+	STORE(t2, UNIT(2)(dst),	.Ls_exc_p2u\@)
+	STORE(t3, UNIT(3)(dst),	.Ls_exc_p1u\@)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 4*NBYTES
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	.set	noreorder
-.Lless_than_4units:
+.Lless_than_4units\@:
 	/*
 	 * rem = len % NBYTES
 	 */
-	beq	rem, len, .Lcopy_bytes
+	beq	rem, len, .Lcopy_bytes\@
 	 nop
 1:
 	R10KCBARRIER(0(ra))
-EXC(	LOAD	t0, 0(src),		.Ll_exc)
+	LOAD(t0, 0(src), .Ll_exc\@)
 	ADD	src, src, NBYTES
 	SUB	len, len, NBYTES
-EXC(	STORE	t0, 0(dst),		.Ls_exc_p1u)
+	STORE(t0, 0(dst), .Ls_exc_p1u\@)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, NBYTES
 	bne	rem, len, 1b
@@ -322,17 +388,17 @@ EXC(	STORE	t0, 0(dst),		.Ls_exc_p1u)
 	 * more instruction-level parallelism.
 	 */
 #define bits t2
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	 ADD	t1, dst, len	# t1 is just past last byte of dst
 	li	bits, 8*NBYTES
 	SLL	rem, len, 3	# rem = number of bits to keep
-EXC(	LOAD	t0, 0(src),		.Ll_exc)
+	LOAD(t0, 0(src), .Ll_exc\@)
 	SUB	bits, bits, rem # bits = number of bits to discard
 	SHIFT_DISCARD t0, t0, bits
-EXC(	STREST	t0, -1(t1),		.Ls_exc)
+	STREST(t0, -1(t1), .Ls_exc\@)
 	jr	ra
 	 move	len, zero
-.Ldst_unaligned:
+.Ldst_unaligned\@:
 	/*
 	 * dst is unaligned
 	 * t0 = src & ADDRMASK
@@ -343,25 +409,25 @@ EXC(	STREST	t0, -1(t1),		.Ls_exc)
 	 * Set match = (src and dst have same alignment)
 	 */
 #define match rem
-EXC(	LDFIRST t3, FIRST(0)(src),	.Ll_exc)
+	LDFIRST(t3, FIRST(0)(src), .Ll_exc\@)
 	ADD	t2, zero, NBYTES
-EXC(	LDREST	t3, REST(0)(src),	.Ll_exc_copy)
+	LDREST(t3, REST(0)(src), .Ll_exc_copy\@)
 	SUB	t2, t2, t1	# t2 = number of bytes copied
 	xor	match, t0, t1
 	R10KCBARRIER(0(ra))
-EXC(	STFIRST t3, FIRST(0)(dst),	.Ls_exc)
-	beq	len, t2, .Ldone
+	STFIRST(t3, FIRST(0)(dst), .Ls_exc\@)
+	beq	len, t2, .Ldone\@
 	 SUB	len, len, t2
 	ADD	dst, dst, t2
-	beqz	match, .Lboth_aligned
+	beqz	match, .Lboth_aligned\@
 	 ADD	src, src, t2
 
-.Lsrc_unaligned_dst_aligned:
+.Lsrc_unaligned_dst_aligned\@:
 	SRL	t0, len, LOG_NBYTES+2	 # +2 for 4 units/iter
-	PREF(	0, 3*32(src) )
-	beqz	t0, .Lcleanup_src_unaligned
+	PREFS(	0, 3*32(src) )
+	beqz	t0, .Lcleanup_src_unaligned\@
 	 and	rem, len, (4*NBYTES-1)	 # rem = len % 4*NBYTES
-	PREF(	1, 3*32(dst) )
+	PREFD(	1, 3*32(dst) )
 1:
 /*
  * Avoid consecutive LD*'s to the same register since some mips
@@ -370,58 +436,58 @@ EXC(	STFIRST t3, FIRST(0)(dst),	.Ls_exc)
  * are to the same unit (unless src is aligned, but it's not).
  */
 	R10KCBARRIER(0(ra))
-EXC(	LDFIRST t0, FIRST(0)(src),	.Ll_exc)
-EXC(	LDFIRST t1, FIRST(1)(src),	.Ll_exc_copy)
+	LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+	LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@)
 	SUB	len, len, 4*NBYTES
-EXC(	LDREST	t0, REST(0)(src),	.Ll_exc_copy)
-EXC(	LDREST	t1, REST(1)(src),	.Ll_exc_copy)
-EXC(	LDFIRST t2, FIRST(2)(src),	.Ll_exc_copy)
-EXC(	LDFIRST t3, FIRST(3)(src),	.Ll_exc_copy)
-EXC(	LDREST	t2, REST(2)(src),	.Ll_exc_copy)
-EXC(	LDREST	t3, REST(3)(src),	.Ll_exc_copy)
-	PREF(	0, 9*32(src) )		# 0 is PREF_LOAD  (not streamed)
+	LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
+	LDREST(t1, REST(1)(src), .Ll_exc_copy\@)
+	LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@)
+	LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@)
+	LDREST(t2, REST(2)(src), .Ll_exc_copy\@)
+	LDREST(t3, REST(3)(src), .Ll_exc_copy\@)
+	PREFS(	0, 9*32(src) )		# 0 is PREF_LOAD  (not streamed)
 	ADD	src, src, 4*NBYTES
 #ifdef CONFIG_CPU_SB1
 	nop				# improves slotting
 #endif
-EXC(	STORE	t0, UNIT(0)(dst),	.Ls_exc_p4u)
-EXC(	STORE	t1, UNIT(1)(dst),	.Ls_exc_p3u)
-EXC(	STORE	t2, UNIT(2)(dst),	.Ls_exc_p2u)
-EXC(	STORE	t3, UNIT(3)(dst),	.Ls_exc_p1u)
-	PREF(	1, 9*32(dst) )		# 1 is PREF_STORE (not streamed)
+	STORE(t0, UNIT(0)(dst),	.Ls_exc_p4u\@)
+	STORE(t1, UNIT(1)(dst),	.Ls_exc_p3u\@)
+	STORE(t2, UNIT(2)(dst),	.Ls_exc_p2u\@)
+	STORE(t3, UNIT(3)(dst),	.Ls_exc_p1u\@)
+	PREFD(	1, 9*32(dst) )		# 1 is PREF_STORE (not streamed)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 4*NBYTES
 	bne	len, rem, 1b
 	.set	noreorder
 
-.Lcleanup_src_unaligned:
-	beqz	len, .Ldone
+.Lcleanup_src_unaligned\@:
+	beqz	len, .Ldone\@
 	 and	rem, len, NBYTES-1  # rem = len % NBYTES
-	beq	rem, len, .Lcopy_bytes
+	beq	rem, len, .Lcopy_bytes\@
 	 nop
 1:
 	R10KCBARRIER(0(ra))
-EXC(	LDFIRST t0, FIRST(0)(src),	.Ll_exc)
-EXC(	LDREST	t0, REST(0)(src),	.Ll_exc_copy)
+	LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+	LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
 	ADD	src, src, NBYTES
 	SUB	len, len, NBYTES
-EXC(	STORE	t0, 0(dst),		.Ls_exc_p1u)
+	STORE(t0, 0(dst), .Ls_exc_p1u\@)
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, NBYTES
 	bne	len, rem, 1b
 	.set	noreorder
 
-.Lcopy_bytes_checklen:
-	beqz	len, .Ldone
+.Lcopy_bytes_checklen\@:
+	beqz	len, .Ldone\@
 	 nop
-.Lcopy_bytes:
+.Lcopy_bytes\@:
 	/* 0 < len < NBYTES  */
 	R10KCBARRIER(0(ra))
 #define COPY_BYTE(N)			\
-EXC(	lb	t0, N(src), .Ll_exc);	\
+	LOADB(t0, N(src), .Ll_exc\@);	\
 	SUB	len, len, 1;		\
-	beqz	len, .Ldone;		\
-EXC(	 sb	t0, N(dst), .Ls_exc_p1)
+	beqz	len, .Ldone\@;		\
+	STOREB(t0, N(dst), .Ls_exc_p1\@)
 
 	COPY_BYTE(0)
 	COPY_BYTE(1)
@@ -431,16 +497,19 @@ EXC(	 sb	t0, N(dst), .Ls_exc_p1)
 	COPY_BYTE(4)
 	COPY_BYTE(5)
 #endif
-EXC(	lb	t0, NBYTES-2(src), .Ll_exc)
+	LOADB(t0, NBYTES-2(src), .Ll_exc\@)
 	SUB	len, len, 1
 	jr	ra
-EXC(	 sb	t0, NBYTES-2(dst), .Ls_exc_p1)
-.Ldone:
+	STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
+.Ldone\@:
 	jr	ra
-	 nop
+	.if __memcpy == 1
 	END(memcpy)
+	.set __memcpy, 0
+	.hidden __memcpy
+	.endif
 
-.Ll_exc_copy:
+.Ll_exc_copy\@:
 	/*
 	 * Copy bytes from src until faulting load address (or until a
 	 * lb faults)
@@ -451,24 +520,24 @@ EXC(	 sb	t0, NBYTES-2(dst), .Ls_exc_p1)
 	 *
 	 * Assumes src < THREAD_BUADDR($28)
 	 */
-	LOAD	t0, TI_TASK($28)
+	LOADK	t0, TI_TASK($28)
 	 nop
-	LOAD	t0, THREAD_BUADDR(t0)
+	LOADK	t0, THREAD_BUADDR(t0)
 1:
-EXC(	lb	t1, 0(src),	.Ll_exc)
+	LOADB(t1, 0(src), .Ll_exc\@)
 	ADD	src, src, 1
 	sb	t1, 0(dst)	# can't fault -- we're copy_from_user
 	.set	reorder				/* DADDI_WAR */
 	ADD	dst, dst, 1
 	bne	src, t0, 1b
 	.set	noreorder
-.Ll_exc:
-	LOAD	t0, TI_TASK($28)
+.Ll_exc\@:
+	LOADK	t0, TI_TASK($28)
 	 nop
-	LOAD	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	LOADK	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
 	 nop
 	SUB	len, AT, t0		# len number of uncopied bytes
-	bnez	t6, .Ldone	/* Skip the zeroing part if inatomic */
+	bnez	t6, .Ldone\@	/* Skip the zeroing part if inatomic */
 	/*
 	 * Here's where we rely on src and dst being incremented in tandem,
 	 *   See (3) above.
@@ -482,7 +551,7 @@ EXC(	lb	t1, 0(src),	.Ll_exc)
 	 */
 	.set	reorder				/* DADDI_WAR */
 	SUB	src, len, 1
-	beqz	len, .Ldone
+	beqz	len, .Ldone\@
 	.set	noreorder
 1:	sb	zero, 0(dst)
 	ADD	dst, dst, 1
@@ -503,7 +572,7 @@ EXC(	lb	t1, 0(src),	.Ll_exc)
 
 #define SEXC(n)							\
 	.set	reorder;			/* DADDI_WAR */ \
-.Ls_exc_p ## n ## u:						\
+.Ls_exc_p ## n ## u\@:						\
 	ADD	len, len, n*NBYTES;				\
 	jr	ra;						\
 	.set	noreorder
@@ -517,14 +586,15 @@ SEXC(3)
 SEXC(2)
 SEXC(1)
 
-.Ls_exc_p1:
+.Ls_exc_p1\@:
 	.set	reorder				/* DADDI_WAR */
 	ADD	len, len, 1
 	jr	ra
 	.set	noreorder
-.Ls_exc:
+.Ls_exc\@:
 	jr	ra
 	 nop
+	.endm
 
 	.align	5
 LEAF(memmove)
@@ -575,3 +645,71 @@ LEAF(__rmemcpy)					/* a0=dst a1=src a2=len */
 	jr	ra
 	 move	a2, zero
 	END(__rmemcpy)
+
+/*
+ * t6 is used as a flag to note inatomic mode.
+ */
+LEAF(__copy_user_inatomic)
+	b	__copy_user_common
+	li	t6, 1
+	END(__copy_user_inatomic)
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+	.align	5
+LEAF(memcpy)					/* a0=dst a1=src a2=len */
+	move	v0, dst				/* return value */
+.L__memcpy:
+FEXPORT(__copy_user)
+	li	t6, 0	/* not inatomic */
+__copy_user_common:
+	/* Legacy Mode, user <-> user */
+	__BUILD_COPY_USER LEGACY_MODE USEROP USEROP
+
+#ifdef CONFIG_EVA
+
+/*
+ * For EVA we need distinct symbols for reading and writing to user space.
+ * This is because we need to use specific EVA instructions to perform the
+ * virtual <-> physical translation when a virtual address is actually in user
+ * space
+ */
+
+LEAF(__copy_user_inatomic_eva)
+	b       __copy_from_user_common
+	li	t6, 1
+	END(__copy_user_inatomic_eva)
+
+/*
+ * __copy_from_user (EVA)
+ */
+
+LEAF(__copy_from_user_eva)
+	li	t6, 0	/* not inatomic */
+__copy_from_user_common:
+	__BUILD_COPY_USER EVA_MODE USEROP KERNELOP
+END(__copy_from_user_eva)
+
+
+
+/*
+ * __copy_to_user (EVA)
+ */
+
+LEAF(__copy_to_user_eva)
+__BUILD_COPY_USER EVA_MODE KERNELOP USEROP
+END(__copy_to_user_eva)
+
+/*
+ * __copy_in_user (EVA)
+ */
+
+LEAF(__copy_in_user_eva)
+__BUILD_COPY_USER EVA_MODE USEROP USEROP
+END(__copy_in_user_eva)
+
+#endif
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 0580194e7402..7b0e5462ca51 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -34,13 +34,27 @@
 #define FILLPTRG t0
 #endif
 
+#define LEGACY_MODE 1
+#define EVA_MODE    2
+
+/*
+ * No need to protect it with EVA #ifdefery. The generated block of code
+ * will never be assembled if EVA is not enabled.
+ */
+#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
+#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
+
 #define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
+	.if \mode == LEGACY_MODE;			\
+9:		insn	reg, addr;			\
+	.else;						\
+9:		___BUILD_EVA_INSN(insn, reg, addr);	\
+	.endif;						\
 	.section __ex_table,"a";			\
 	PTR	9b, handler;				\
 	.previous
 
-	.macro	f_fill64 dst, offset, val, fixup
+	.macro	f_fill64 dst, offset, val, fixup, mode
 	EX(LONG_S, \val, (\offset +  0 * STORSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset +  1 * STORSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset +  2 * STORSIZE)(\dst), \fixup)
@@ -63,34 +77,24 @@
 #endif
 	.endm
 
-/*
- * memset(void *s, int c, size_t n)
- *
- * a0: start of area to clear
- * a1: char to fill with
- * a2: size of area to clear
- */
 	.set	noreorder
 	.align	5
-LEAF(memset)
-	beqz		a1, 1f
-	 move		v0, a0			/* result */
 
-	andi		a1, 0xff		/* spread fillword */
-	LONG_SLL		t1, a1, 8
-	or		a1, t1
-	LONG_SLL		t1, a1, 16
-#if LONGSIZE == 8
-	or		a1, t1
-	LONG_SLL		t1, a1, 32
-#endif
-	or		a1, t1
-1:
+	/*
+	 * Macro to generate the __bzero{,_user} symbol
+	 * Arguments:
+	 * mode: LEGACY_MODE or EVA_MODE
+	 */
+	.macro __BUILD_BZERO mode
+	/* Initialize __memset if this is the first time we call this macro */
+	.ifnotdef __memset
+	.set __memset, 1
+	.hidden __memset /* Make sure it does not leak */
+	.endif
 
-FEXPORT(__bzero)
 	sltiu		t0, a2, STORSIZE	/* very small region? */
-	bnez		t0, .Lsmall_memset
-	 andi		t0, a0, STORMASK	/* aligned? */
+	bnez		t0, .Lsmall_memset\@
+	andi		t0, a0, STORMASK	/* aligned? */
 
 #ifdef CONFIG_CPU_MICROMIPS
 	move		t8, a1			/* used by 'swp' instruction */
@@ -98,39 +102,39 @@ FEXPORT(__bzero)
 #endif
 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
 	beqz		t0, 1f
-	 PTR_SUBU	t0, STORSIZE		/* alignment in bytes */
+	PTR_SUBU	t0, STORSIZE		/* alignment in bytes */
 #else
 	.set		noat
 	li		AT, STORSIZE
 	beqz		t0, 1f
-	 PTR_SUBU	t0, AT			/* alignment in bytes */
+	PTR_SUBU	t0, AT			/* alignment in bytes */
 	.set		at
 #endif
 
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
-	EX(LONG_S_L, a1, (a0), .Lfirst_fixup)	/* make word/dword aligned */
+	EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
 #endif
 #ifdef __MIPSEL__
-	EX(LONG_S_R, a1, (a0), .Lfirst_fixup)	/* make word/dword aligned */
+	EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
 #endif
 	PTR_SUBU	a0, t0			/* long align ptr */
 	PTR_ADDU	a2, t0			/* correct size */
 
 1:	ori		t1, a2, 0x3f		/* # of full blocks */
 	xori		t1, 0x3f
-	beqz		t1, .Lmemset_partial	/* no block to fill */
-	 andi		t0, a2, 0x40-STORSIZE
+	beqz		t1, .Lmemset_partial\@	/* no block to fill */
+	andi		t0, a2, 0x40-STORSIZE
 
 	PTR_ADDU	t1, a0			/* end address */
 	.set		reorder
 1:	PTR_ADDIU	a0, 64
 	R10KCBARRIER(0(ra))
-	f_fill64 a0, -64, FILL64RG, .Lfwd_fixup
+	f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
 	bne		t1, a0, 1b
 	.set		noreorder
 
-.Lmemset_partial:
+.Lmemset_partial\@:
 	R10KCBARRIER(0(ra))
 	PTR_LA		t1, 2f			/* where to start */
 #ifdef CONFIG_CPU_MICROMIPS
@@ -145,60 +149,100 @@ FEXPORT(__bzero)
 	.set		at
 #endif
 	jr		t1
-	 PTR_ADDU	a0, t0			/* dest ptr */
+	PTR_ADDU	a0, t0			/* dest ptr */
 
 	.set		push
 	.set		noreorder
 	.set		nomacro
-	f_fill64 a0, -64, FILL64RG, .Lpartial_fixup	/* ... but first do longs ... */
+	/* ... but first do longs ... */
+	f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
 2:	.set		pop
 	andi		a2, STORMASK		/* At most one long to go */
 
 	beqz		a2, 1f
-	 PTR_ADDU	a0, a2			/* What's left */
+	PTR_ADDU	a0, a2			/* What's left */
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
-	EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
+	EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
 #endif
 #ifdef __MIPSEL__
-	EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
+	EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
 #endif
 1:	jr		ra
-	 move		a2, zero
+	move		a2, zero
 
-.Lsmall_memset:
+.Lsmall_memset\@:
 	beqz		a2, 2f
-	 PTR_ADDU	t1, a0, a2
+	PTR_ADDU	t1, a0, a2
 
 1:	PTR_ADDIU	a0, 1			/* fill bytewise */
 	R10KCBARRIER(0(ra))
 	bne		t1, a0, 1b
-	 sb		a1, -1(a0)
+	sb		a1, -1(a0)
 
 2:	jr		ra			/* done */
-	 move		a2, zero
+	move		a2, zero
+	.if __memset == 1
 	END(memset)
+	.set __memset, 0
+	.hidden __memset
+	.endif
 
-.Lfirst_fixup:
+.Lfirst_fixup\@:
 	jr	ra
-	 nop
+	nop
 
-.Lfwd_fixup:
+.Lfwd_fixup\@:
 	PTR_L		t0, TI_TASK($28)
 	andi		a2, 0x3f
 	LONG_L		t0, THREAD_BUADDR(t0)
 	LONG_ADDU	a2, t1
 	jr		ra
-	 LONG_SUBU	a2, t0
+	LONG_SUBU	a2, t0
 
-.Lpartial_fixup:
+.Lpartial_fixup\@:
 	PTR_L		t0, TI_TASK($28)
 	andi		a2, STORMASK
 	LONG_L		t0, THREAD_BUADDR(t0)
 	LONG_ADDU	a2, t1
 	jr		ra
-	 LONG_SUBU	a2, t0
+	LONG_SUBU	a2, t0
 
-.Llast_fixup:
+.Llast_fixup\@:
 	jr		ra
-	 andi		v1, a2, STORMASK
+	andi		v1, a2, STORMASK
+
+	.endm
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+
+LEAF(memset)
+	beqz		a1, 1f
+	move		v0, a0			/* result */
+
+	andi		a1, 0xff		/* spread fillword */
+	LONG_SLL		t1, a1, 8
+	or		a1, t1
+	LONG_SLL		t1, a1, 16
+#if LONGSIZE == 8
+	or		a1, t1
+	LONG_SLL		t1, a1, 32
+#endif
+	or		a1, t1
+1:
+#ifndef CONFIG_EVA
+FEXPORT(__bzero)
+#endif
+	__BUILD_BZERO LEGACY_MODE
+
+#ifdef CONFIG_EVA
+LEAF(__bzero)
+	__BUILD_BZERO EVA_MODE
+END(__bzero)
+#endif
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S
index e362dcdc69d1..bef65c98df59 100644
--- a/arch/mips/lib/strlen_user.S
+++ b/arch/mips/lib/strlen_user.S
@@ -22,19 +22,43 @@
  *
  * Return 0 for error
  */
-LEAF(__strlen_user_asm)
+	.macro __BUILD_STRLEN_ASM func
+LEAF(__strlen_\func\()_asm)
 	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
 	and		v0, a0
-	bnez		v0, .Lfault
+	bnez		v0, .Lfault\@
 
-FEXPORT(__strlen_user_nocheck_asm)
+FEXPORT(__strlen_\func\()_nocheck_asm)
 	move		v0, a0
-1:	EX(lbu, v1, (v0), .Lfault)
+.ifeqs "\func", "kernel"
+1:	EX(lbu, v1, (v0), .Lfault\@)
+.else
+1:	EX(lbue, v1, (v0), .Lfault\@)
+.endif
 	PTR_ADDIU	v0, 1
 	bnez		v1, 1b
 	PTR_SUBU	v0, a0
 	jr		ra
-	END(__strlen_user_asm)
+	END(__strlen_\func\()_asm)
 
-.Lfault:	move		v0, zero
+.Lfault\@:	move		v0, zero
 	jr		ra
+	.endm
+
+#ifndef CONFIG_EVA
+	/* Set aliases */
+	.global __strlen_user_asm
+	.global __strlen_user_nocheck_asm
+	.set __strlen_user_asm, __strlen_kernel_asm
+	.set __strlen_user_nocheck_asm, __strlen_kernel_nocheck_asm
+#endif
+
+__BUILD_STRLEN_ASM kernel
+
+#ifdef CONFIG_EVA
+
+	.set push
+	.set eva
+__BUILD_STRLEN_ASM user
+	.set pop
+#endif
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index 92870b6b53ea..d3301cd1e9a5 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -28,16 +28,21 @@
  * it happens at most some bytes of the exceptions handlers will be copied.
  */
 
-LEAF(__strncpy_from_user_asm)
+	.macro __BUILD_STRNCPY_ASM func
+LEAF(__strncpy_from_\func\()_asm)
 	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
 	and		v0, a1
-	bnez		v0, .Lfault
+	bnez		v0, .Lfault\@
 
-FEXPORT(__strncpy_from_user_nocheck_asm)
+FEXPORT(__strncpy_from_\func\()_nocheck_asm)
 	.set		noreorder
 	move		t0, zero
 	move		v1, a1
-1:	EX(lbu, v0, (v1), .Lfault)
+.ifeqs "\func","kernel"
+1:	EX(lbu, v0, (v1), .Lfault\@)
+.else
+1:	EX(lbue, v0, (v1), .Lfault\@)
+.endif
 	PTR_ADDIU	v1, 1
 	R10KCBARRIER(0(ra))
 	beqz		v0, 2f
@@ -47,15 +52,34 @@ FEXPORT(__strncpy_from_user_nocheck_asm)
 	 PTR_ADDIU	a0, 1
 2:	PTR_ADDU	v0, a1, t0
 	xor		v0, a1
-	bltz		v0, .Lfault
+	bltz		v0, .Lfault\@
 	 nop
 	jr		ra			# return n
 	 move		v0, t0
-	END(__strncpy_from_user_asm)
+	END(__strncpy_from_\func\()_asm)
 
-.Lfault: jr		ra
+.Lfault\@: jr		ra
 	  li		v0, -EFAULT
 
 	.section	__ex_table,"a"
-	PTR		1b, .Lfault
+	PTR		1b, .Lfault\@
 	.previous
+
+	.endm
+
+#ifndef CONFIG_EVA
+	/* Set aliases */
+	.global __strncpy_from_user_asm
+	.global __strncpy_from_user_nocheck_asm
+	.set __strncpy_from_user_asm, __strncpy_from_kernel_asm
+	.set __strncpy_from_user_nocheck_asm, __strncpy_from_kernel_nocheck_asm
+#endif
+
+__BUILD_STRNCPY_ASM kernel
+
+#ifdef CONFIG_EVA
+	.set push
+	.set eva
+__BUILD_STRNCPY_ASM user
+	.set pop
+#endif
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S
index fcacea5e61f1..f3af6995e2a6 100644
--- a/arch/mips/lib/strnlen_user.S
+++ b/arch/mips/lib/strnlen_user.S
@@ -25,22 +25,46 @@
  *	 bytes.	 There's nothing secret there.	On 64-bit accessing beyond
  *	 the maximum is a tad hairier ...
  */
-LEAF(__strnlen_user_asm)
+	.macro __BUILD_STRNLEN_ASM func
+LEAF(__strnlen_\func\()_asm)
 	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
 	and		v0, a0
-	bnez		v0, .Lfault
+	bnez		v0, .Lfault\@
 
-FEXPORT(__strnlen_user_nocheck_asm)
+FEXPORT(__strnlen_\func\()_nocheck_asm)
 	move		v0, a0
 	PTR_ADDU	a1, a0			# stop pointer
 1:	beq		v0, a1, 1f		# limit reached?
-	EX(lb, t0, (v0), .Lfault)
+.ifeqs "\func", "kernel"
+	EX(lb, t0, (v0), .Lfault\@)
+.else
+	EX(lbe, t0, (v0), .Lfault\@)
+.endif
 	PTR_ADDIU	v0, 1
 	bnez		t0, 1b
 1:	PTR_SUBU	v0, a0
 	jr		ra
-	END(__strnlen_user_asm)
+	END(__strnlen_\func\()_asm)
 
-.Lfault:
+.Lfault\@:
 	move		v0, zero
 	jr		ra
+	.endm
+
+#ifndef CONFIG_EVA
+	/* Set aliases */
+	.global __strnlen_user_asm
+	.global __strnlen_user_nocheck_asm
+	.set __strnlen_user_asm, __strnlen_kernel_asm
+	.set __strnlen_user_nocheck_asm, __strnlen_kernel_nocheck_asm
+#endif
+
+__BUILD_STRNLEN_ASM kernel
+
+#ifdef CONFIG_EVA
+
+	.set push
+	.set eva
+__BUILD_STRNLEN_ASM user
+	.set pop
+#endif
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 506925b2c3f3..71a697c9d385 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -876,20 +876,43 @@ static inline int cop1_64bit(struct pt_regs *xcp)
 #endif
 }
 
-#define SIFROMREG(si, x) ((si) = cop1_64bit(xcp) || !(x & 1) ? \
-			(int)ctx->fpr[x] : (int)(ctx->fpr[x & ~1] >> 32))
-
-#define SITOREG(si, x)	(ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = \
-			cop1_64bit(xcp) || !(x & 1) ? \
-			ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
-			ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
-
-#define SIFROMHREG(si, x)	((si) = (int)(ctx->fpr[x] >> 32))
-#define SITOHREG(si, x)		(ctx->fpr[x] = \
-				ctx->fpr[x] << 32 >> 32 | (u64)(si) << 32)
-
-#define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)])
-#define DITOREG(di, x)	(ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di))
+#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 {						\
+	if (cop1_64bit(xcp)) {						\
+		unsigned i;						\
+		set_fpr32(&ctx->fpr[x], 0, si);				\
+		for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++)	\
+			set_fpr32(&ctx->fpr[x], i, 0);			\
+	} else {							\
+		set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si);		\
+	}								\
+} while (0)
+
+#define SIFROMHREG(si, x)	((si) = get_fpr32(&ctx->fpr[x], 1))
+
+#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) \
+	((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
+
+#define DITOREG(di, x) do {						\
+	unsigned fpr, i;						\
+	fpr = (x) & ~(cop1_64bit(xcp) == 0);				\
+	set_fpr64(&ctx->fpr[fpr], 0, di);				\
+	for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++)		\
+		set_fpr64(&ctx->fpr[fpr], i, 0);			\
+} while (0)
 
 #define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
 #define SPTOREG(sp, x)	SITOREG((sp).bits, x)
@@ -1960,15 +1983,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 #if defined(__mips64)
 	case l_fmt:{
+		u64 bits;
+		DIFROMREG(bits, MIPSInst_FS(ir));
+
 		switch (MIPSInst_FUNC(ir)) {
 		case fcvts_op:
 			/* convert long to single precision real */
-			rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+			rv.s = ieee754sp_flong(bits);
 			rfmt = s_fmt;
 			goto copcsr;
 		case fcvtd_op:
 			/* convert long to double precision real */
-			rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+			rv.d = ieee754dp_flong(bits);
 			rfmt = d_fmt;
 			goto copcsr;
 		default:
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index 3aeae07ed5b8..eb58a85b3157 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -40,78 +40,6 @@ void fpu_emulator_init_fpu(void)
 	}
 
 	current->thread.fpu.fcr31 = 0;
-	for (i = 0; i < 32; i++) {
-		current->thread.fpu.fpr[i] = SIGNALLING_NAN;
-	}
-}
-
-
-/*
- * Emulator context save/restore to/from a signal context
- * presumed to be on the user stack, and therefore accessed
- * with appropriate macros from uaccess.h
- */
-
-int fpu_emulator_save_context(struct sigcontext __user *sc)
-{
-	int i;
-	int err = 0;
-
-	for (i = 0; i < 32; i++) {
-		err |=
-		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
-	}
-	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-	return err;
-}
-
-int fpu_emulator_restore_context(struct sigcontext __user *sc)
-{
-	int i;
-	int err = 0;
-
-	for (i = 0; i < 32; i++) {
-		err |=
-		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
-	}
-	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-	return err;
-}
-
-#ifdef CONFIG_64BIT
-/*
- * This is the o32 version
- */
-
-int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
-{
-	int i;
-	int err = 0;
-	int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
-
-	for (i = 0; i < 32; i += inc) {
-		err |=
-		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
-	}
-	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-	return err;
-}
-
-int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
-{
-	int i;
-	int err = 0;
-	int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
-
-	for (i = 0; i < 32; i += inc) {
-		err |=
-		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
-	}
-	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
-	return err;
+	for (i = 0; i < 32; i++)
+		set_fpr64(&current->thread.fpu.fpr[i], 0, SIGNALLING_NAN);
 }
-#endif
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c14259edd53f..a62b6379b6ae 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -57,7 +57,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
 	preempt_enable();
 }
 
-#if defined(CONFIG_MIPS_CMP)
+#if defined(CONFIG_MIPS_CMP) || defined(CONFIG_MIPS_CPS)
 #define cpu_has_safe_index_cacheops 0
 #else
 #define cpu_has_safe_index_cacheops 1
@@ -123,6 +123,28 @@ static void r4k_blast_dcache_page_setup(void)
 		r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
 }
 
+#ifndef CONFIG_EVA
+#define r4k_blast_dcache_user_page  r4k_blast_dcache_page
+#else
+
+static void (*r4k_blast_dcache_user_page)(unsigned long addr);
+
+static void r4k_blast_dcache_user_page_setup(void)
+{
+	unsigned long  dc_lsize = cpu_dcache_line_size();
+
+	if (dc_lsize == 0)
+		r4k_blast_dcache_user_page = (void *)cache_noop;
+	else if (dc_lsize == 16)
+		r4k_blast_dcache_user_page = blast_dcache16_user_page;
+	else if (dc_lsize == 32)
+		r4k_blast_dcache_user_page = blast_dcache32_user_page;
+	else if (dc_lsize == 64)
+		r4k_blast_dcache_user_page = blast_dcache64_user_page;
+}
+
+#endif
+
 static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
 
 static void r4k_blast_dcache_page_indexed_setup(void)
@@ -245,6 +267,27 @@ static void r4k_blast_icache_page_setup(void)
 		r4k_blast_icache_page = blast_icache64_page;
 }
 
+#ifndef CONFIG_EVA
+#define r4k_blast_icache_user_page  r4k_blast_icache_page
+#else
+
+static void (*r4k_blast_icache_user_page)(unsigned long addr);
+
+static void __cpuinit r4k_blast_icache_user_page_setup(void)
+{
+	unsigned long ic_lsize = cpu_icache_line_size();
+
+	if (ic_lsize == 0)
+		r4k_blast_icache_user_page = (void *)cache_noop;
+	else if (ic_lsize == 16)
+		r4k_blast_icache_user_page = blast_icache16_user_page;
+	else if (ic_lsize == 32)
+		r4k_blast_icache_user_page = blast_icache32_user_page;
+	else if (ic_lsize == 64)
+		r4k_blast_icache_user_page = blast_icache64_user_page;
+}
+
+#endif
 
 static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
 
@@ -519,7 +562,8 @@ static inline void local_r4k_flush_cache_page(void *args)
 	}
 
 	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
-		r4k_blast_dcache_page(addr);
+		vaddr ? r4k_blast_dcache_page(addr) :
+			r4k_blast_dcache_user_page(addr);
 		if (exec && !cpu_icache_snoops_remote_store)
 			r4k_blast_scache_page(addr);
 	}
@@ -530,7 +574,8 @@ static inline void local_r4k_flush_cache_page(void *args)
 			if (cpu_context(cpu, mm) != 0)
 				drop_mmu_context(mm, cpu);
 		} else
-			r4k_blast_icache_page(addr);
+			vaddr ? r4k_blast_icache_page(addr) :
+				r4k_blast_icache_user_page(addr);
 	}
 
 	if (vaddr) {
@@ -595,6 +640,17 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
 			break;
 		}
 	}
+#ifdef CONFIG_EVA
+	/*
+	 * Due to all possible segment mappings, there might cache aliases
+	 * caused by the bootloader being in non-EVA mode, and the CPU switching
+	 * to EVA during early kernel init. It's best to flush the scache
+	 * to avoid having secondary cores fetching stale data and lead to
+	 * kernel crashes.
+	 */
+	bc_wback_inv(start, (end - start));
+	__sync();
+#endif
 }
 
 static inline void local_r4k_flush_icache_range_ipi(void *args)
@@ -617,7 +673,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 	instruction_hazard();
 }
 
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
 
 static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 {
@@ -688,7 +744,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
 	bc_inv(addr, size);
 	__sync();
 }
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
 
 /*
  * While we're protected against bad userland addresses we don't care
@@ -1113,13 +1169,20 @@ static void probe_pcache(void)
 	case CPU_34K:
 	case CPU_74K:
 	case CPU_1004K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
+	case CPU_P5600:
 	case CPU_PROAPTIV:
-		if (current_cpu_type() == CPU_74K)
+		if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
 			alias_74k_erratum(c);
-		if ((read_c0_config7() & (1 << 16))) {
-			/* effectively physically indexed dcache,
-			   thus no virtual aliases. */
+		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
+		    (c->icache.waysize > PAGE_SIZE))
+			c->icache.flags |= MIPS_CACHE_ALIASES;
+		if (read_c0_config7() & MIPS_CONF7_AR) {
+			/*
+			 * Effectively physically indexed dcache,
+			 * thus no virtual aliases.
+			*/
 			c->dcache.flags |= MIPS_CACHE_PINDEX;
 			break;
 		}
@@ -1461,6 +1524,10 @@ void r4k_cache_init(void)
 	r4k_blast_scache_page_setup();
 	r4k_blast_scache_page_indexed_setup();
 	r4k_blast_scache_setup();
+#ifdef CONFIG_EVA
+	r4k_blast_dcache_user_page_setup();
+	r4k_blast_icache_user_page_setup();
+#endif
 
 	/*
 	 * Some MIPS32 and MIPS64 processors have physically indexed caches.
@@ -1492,7 +1559,7 @@ void r4k_cache_init(void)
 	flush_icache_range	= r4k_flush_icache_range;
 	local_flush_icache_range	= local_r4k_flush_icache_range;
 
-#if defined(CONFIG_DMA_NONCOHERENT)
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
 	if (coherentio) {
 		_dma_cache_wback_inv	= (void *)cache_noop;
 		_dma_cache_wback	= (void *)cache_noop;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index fde7e56d13fe..e422b38d3113 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -49,7 +49,7 @@ EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
 EXPORT_SYMBOL(flush_data_cache_page);
 EXPORT_SYMBOL(flush_icache_all);
 
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
 
 /* DMA cache operations. */
 void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
@@ -58,7 +58,7 @@ void (*_dma_cache_inv)(unsigned long start, unsigned long size);
 
 EXPORT_SYMBOL(_dma_cache_wback_inv);
 
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
 
 /*
  * We could optimize the case where the cache argument is not BCACHE but
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 6b59617760c1..4fc74c78265a 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -422,10 +422,20 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
+void (*free_init_pages_eva)(void *begin, void *end) = NULL;
+
 void __init_refok free_initmem(void)
 {
 	prom_free_prom_memory();
-	free_initmem_default(POISON_FREE_INITMEM);
+	/*
+	 * Let the platform define a specific function to free the
+	 * init section since EVA may have used any possible mapping
+	 * between virtual and physical addresses.
+	 */
+	if (free_init_pages_eva)
+		free_init_pages_eva((void *)&__init_begin, (void *)&__init_end);
+	else
+		free_initmem_default(POISON_FREE_INITMEM);
 }
 
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 7a56aee5fce7..99eb8fabab60 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -76,8 +76,10 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 	case CPU_34K:
 	case CPU_74K:
 	case CPU_1004K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 	case CPU_BMIPS5000:
 		if (config2 & (1 << 12))
 			return 0;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index b234b1b5ccad..ccae9a46e222 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -509,7 +509,9 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		switch (current_cpu_type()) {
 		case CPU_M14KC:
 		case CPU_74K:
+		case CPU_1074K:
 		case CPU_PROAPTIV:
+		case CPU_P5600:
 			break;
 
 		default:
diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c
index b8d580ca02e5..5aff6f158544 100644
--- a/arch/mips/mm/uasm-micromips.c
+++ b/arch/mips/mm/uasm-micromips.c
@@ -79,6 +79,7 @@ static struct insn insn_table_MM[] = {
 	{ insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM },
 	{ insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM },
 	{ insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS },
+	{ insn_jr_hb, M(mm_pool32a_op, 0, 0, 0, mm_jalrhb_op, mm_pool32axf_op), RS },
 	{ insn_ld, 0, 0 },
 	{ insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM },
 	{ insn_lld, 0, 0 },
@@ -99,10 +100,12 @@ static struct insn insn_table_MM[] = {
 	{ insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD },
 	{ insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD },
 	{ insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+	{ insn_sync, M(mm_pool32a_op, 0, 0, 0, mm_sync_op, mm_pool32axf_op), RS },
 	{ insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 },
 	{ insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 },
 	{ insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 },
 	{ insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 },
+	{ insn_wait, M(mm_pool32a_op, 0, 0, 0, mm_wait_op, mm_pool32axf_op), SCIMM },
 	{ insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD },
 	{ insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
 	{ insn_dins, 0, 0 },
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index 3abd609518c9..5c7226084883 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -84,6 +84,7 @@ static struct insn insn_table[] = {
 	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),	JIMM },
 	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
 	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
+	{ insn_jr_hb,  M(spec_op, 0, 0, 0, jr_hb_hint, jr_op),  RS },
 	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
 	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
@@ -92,7 +93,9 @@ static struct insn insn_table[] = {
 	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
 	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_mftc0,  M(cop0_op, mftr_op, 0, 0, 0, 0),  RT | RD | SET},
 	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_mttc0,  M(cop0_op, mttr_op, 0, 0, 0, 0),  RT | RD | SET},
 	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),	RS | RT | UIMM },
 	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
 	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
@@ -106,11 +109,13 @@ static struct insn insn_table[] = {
 	{ insn_srl,  M(spec_op, 0, 0, 0, 0, srl_op),  RT | RD | RE },
 	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),	RS | RT | RD },
 	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_sync, M(spec_op, 0, 0, 0, 0, sync_op), RE },
 	{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
 	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
 	{ insn_tlbr,  M(cop0_op, cop_op, 0, 0, 0, tlbr_op),  0 },
 	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
 	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
+	{ insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM },
 	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
 	{ insn_invalid, 0, 0 }
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index b9d14b6c7f58..15fc2337d623 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -49,12 +49,12 @@ enum opcode {
 	insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm,
 	insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
 	insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret,
-	insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx,
-	insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0,
-	insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd,
-	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
-	insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor,
-	insn_xori,
+	insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_jr_hb, insn_ld,
+	insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0,
+	insn_mftc0, insn_mtc0, insn_mttc0, insn_or, insn_ori, insn_pref,
+	insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra,
+	insn_srl, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp,
+	insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, insn_xori,
 };
 
 struct insn {
@@ -251,13 +251,16 @@ I_u2u1msbu3(_ins)
 I_u1(_j)
 I_u1(_jal)
 I_u1(_jr)
+I_u1(_jr_hb)
 I_u2s3u1(_ld)
 I_u2s3u1(_ll)
 I_u2s3u1(_lld)
 I_u1s2(_lui)
 I_u2s3u1(_lw)
 I_u1u2u3(_mfc0)
+I_u2u1u3(_mftc0)
 I_u1u2u3(_mtc0)
+I_u1u2u3(_mttc0)
 I_u2u1u3(_ori)
 I_u3u1u2(_or)
 I_0(_rfe)
@@ -270,10 +273,12 @@ I_u2u1u3(_srl)
 I_u2u1u3(_rotr)
 I_u3u1u2(_subu)
 I_u2s3u1(_sw)
+I_u1(_sync)
 I_0(_tlbp)
 I_0(_tlbr)
 I_0(_tlbwi)
 I_0(_tlbwr)
+I_u1(_wait);
 I_u3u1u2(_xor)
 I_u2u1u3(_xori)
 I_u2u1msbu3(_dins);
@@ -469,6 +474,14 @@ void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
 }
 UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
 
+void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int reg1,
+			  unsigned int reg2, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	ISAFUNC(uasm_i_beq)(p, reg1, reg2, 0);
+}
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq));
+
 void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg,
 			   int lid)
 {
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index fcebfced26d0..4f9e44d358b7 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -20,7 +20,8 @@
 #include <asm/smp-ops.h>
 #include <asm/traps.h>
 #include <asm/fw/fw.h>
-#include <asm/gcmpregs.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/malta.h>
 
@@ -110,6 +111,11 @@ static void __init mips_ejtag_setup(void)
 	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
 }
 
+phys_t mips_cpc_default_phys_base(void)
+{
+	return CPC_BASE_ADDR;
+}
+
 extern struct plat_smp_ops msmtc_smp_ops;
 
 void __init prom_init(void)
@@ -238,10 +244,23 @@ mips_pci_controller:
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
 #endif
+#ifndef CONFIG_EVA
 		/* Fix up target memory mapping.  */
 		MSC_READ(MSC01_PCI_BAR0, mask);
 		MSC_WRITE(MSC01_PCI_P2SCMSKL, mask & MSC01_PCI_BAR0_SIZE_MSK);
+#else
+		/*
+		 * Setup the Malta max (2GB) memory for PCI DMA in host bridge
+		 * in transparent addressing mode, starting from 0x80000000.
+		 */
+		mask = PHYS_OFFSET | (1<<3);
+		MSC_WRITE(MSC01_PCI_BAR0, mask);
 
+		mask = PHYS_OFFSET;
+		MSC_WRITE(MSC01_PCI_HEAD4, mask);
+		MSC_WRITE(MSC01_PCI_P2SCMSKL, mask);
+		MSC_WRITE(MSC01_PCI_P2SCMAPL, mask);
+#endif
 		/* Don't handle target retries indefinitely.  */
 		if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
 		    MSC01_PCI_CFG_MAXRTRY_MSK)
@@ -276,10 +295,13 @@ mips_pci_controller:
 	console_config();
 #endif
 	/* Early detection of CMP support */
-	if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
-		if (!register_cmp_smp_ops())
-			return;
+	mips_cm_probe();
+	mips_cpc_probe();
 
+	if (!register_cps_smp_ops())
+		return;
+	if (!register_cmp_smp_ops())
+		return;
 	if (!register_vsmp_smp_ops())
 		return;
 
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index ca3e3a46a42f..93103f81bf57 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -26,6 +26,7 @@
 #include <asm/i8259.h>
 #include <asm/irq_cpu.h>
 #include <asm/irq_regs.h>
+#include <asm/mips-cm.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
 #include <asm/gt64120.h>
@@ -33,13 +34,10 @@
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/msc01_ic.h>
 #include <asm/gic.h>
-#include <asm/gcmpregs.h>
 #include <asm/setup.h>
 #include <asm/rtlx.h>
 
-int gcmp_present = -1;
 static unsigned long _msc01_biu_base;
-static unsigned long _gcmp_base;
 static unsigned int ipi_map[NR_CPUS];
 
 static DEFINE_RAW_SPINLOCK(mips_irq_lock);
@@ -418,48 +416,6 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
 };
 #undef X
 
-/*
- * GCMP needs to be detected before any SMP initialisation
- */
-int __init gcmp_probe(unsigned long addr, unsigned long size)
-{
-	if ((mips_revision_sconid != MIPS_REVISION_SCON_ROCIT)  &&
-	    (mips_revision_sconid != MIPS_REVISION_SCON_GT64120)) {
-		gcmp_present = 0;
-		pr_debug("GCMP NOT present\n");
-		return gcmp_present;
-	}
-
-	if (gcmp_present >= 0)
-		return gcmp_present;
-
-	_gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR,
-		GCMP_ADDRSPACE_SZ);
-	_msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE,
-		MSC01_BIU_ADDRSPACE_SZ);
-	gcmp_present = ((GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) ==
-		GCMP_BASE_ADDR);
-
-	if (gcmp_present)
-		pr_debug("GCMP present\n");
-	return gcmp_present;
-}
-
-/* Return the number of IOCU's present */
-int __init gcmp_niocu(void)
-{
-	return gcmp_present ? ((GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >>
-		GCMP_GCB_GC_NUMIOCU_SHF) : 0;
-}
-
-/* Set GCMP region attributes */
-void __init gcmp_setregion(int region, unsigned long base,
-			   unsigned long mask, int type)
-{
-	GCMPGCBn(CMxBASE, region) = base;
-	GCMPGCBn(CMxMASK, region) = mask | type;
-}
-
 #if defined(CONFIG_MIPS_MT_SMP)
 static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
 {
@@ -496,8 +452,8 @@ void __init arch_init_irq(void)
 	if (!cpu_has_veic)
 		mips_cpu_irq_init();
 
-	if (gcmp_present)  {
-		GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
+	if (mips_cm_present()) {
+		write_gcr_gic_base(GIC_BASE_ADDR | CM_GCR_GIC_BASE_GICEN_MSK);
 		gic_present = 1;
 	} else {
 		if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
@@ -584,7 +540,7 @@ void __init arch_init_irq(void)
 #endif
 		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
 				ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
-		if (!gcmp_present) {
+		if (!mips_cm_present()) {
 			/* Enable the GIC */
 			i = REG(_msc01_biu_base, MSC01_SC_CFG);
 			REG(_msc01_biu_base, MSC01_SC_CFG) =
@@ -708,16 +664,16 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 	/* This duplicates the handling in do_be which seems wrong */
 	int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
 
-	if (gcmp_present) {
-		unsigned long cm_error = GCMPGCB(GCMEC);
-		unsigned long cm_addr = GCMPGCB(GCMEA);
-		unsigned long cm_other = GCMPGCB(GCMEO);
+	if (mips_cm_present()) {
+		unsigned long cm_error = read_gcr_error_cause();
+		unsigned long cm_addr = read_gcr_error_addr();
+		unsigned long cm_other = read_gcr_error_mult();
 		unsigned long cause, ocause;
 		char buf[256];
 
-		cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
+		cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
 		if (cause != 0) {
-			cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
+			cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
 			if (cause < 16) {
 				unsigned long cca_bits = (cm_error >> 15) & 7;
 				unsigned long tr_bits = (cm_error >> 12) & 7;
@@ -748,8 +704,8 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 					 mcmd[cmd_bits], sport_bits);
 			}
 
-			ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
-				 GCMP_GCB_GMEO_ERROR_2ND_SHF;
+			ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
+				 CM_GCR_ERROR_MULT_ERR2ND_SHF;
 
 			pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
 			       causes[cause], buf);
@@ -757,7 +713,7 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 			pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
 
 			/* reprime cause register */
-			GCMPGCB(GCMEC) = 0;
+			write_gcr_error_cause(0);
 		}
 	}
 
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 1f73d63e92a7..6d0f4ab3632d 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -24,22 +24,30 @@ static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS];
 /* determined physical memory size, not overridden by command line args	 */
 unsigned long physical_memsize = 0L;
 
-fw_memblock_t * __init fw_getmdesc(void)
+fw_memblock_t * __init fw_getmdesc(int eva)
 {
-	char *memsize_str, *ptr;
-	unsigned int memsize;
+	char *memsize_str, *ememsize_str __maybe_unused = NULL, *ptr;
+	unsigned long memsize, ememsize __maybe_unused = 0;
 	static char cmdline[COMMAND_LINE_SIZE] __initdata;
-	long val;
 	int tmp;
 
 	/* otherwise look in the environment */
+
 	memsize_str = fw_getenv("memsize");
-	if (!memsize_str) {
+	if (memsize_str)
+		tmp = kstrtol(memsize_str, 0, &memsize);
+	if (eva) {
+	/* Look for ememsize for EVA */
+		ememsize_str = fw_getenv("ememsize");
+		if (ememsize_str)
+			tmp = kstrtol(ememsize_str, 0, &ememsize);
+	}
+	if (!memsize && !ememsize) {
 		pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
 		physical_memsize = 0x02000000;
 	} else {
-		tmp = kstrtol(memsize_str, 0, &val);
-		physical_memsize = (unsigned long)val;
+		/* If ememsize is set, then set physical_memsize to that */
+		physical_memsize = ememsize ? : memsize;
 	}
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -54,20 +62,30 @@ fw_memblock_t * __init fw_getmdesc(void)
 	ptr = strstr(cmdline, "memsize=");
 	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
 		ptr = strstr(ptr, " memsize=");
+	/* And now look for ememsize */
+	if (eva) {
+		ptr = strstr(cmdline, "ememsize=");
+		if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
+			ptr = strstr(ptr, " ememsize=");
+	}
 
 	if (ptr)
-		memsize = memparse(ptr + 8, &ptr);
+		memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
 	else
 		memsize = physical_memsize;
 
+	/* Last 64K for HIGHMEM arithmetics */
+	if (memsize > 0x7fff0000)
+		memsize = 0x7fff0000;
+
 	memset(mdesc, 0, sizeof(mdesc));
 
 	mdesc[0].type = fw_dontuse;
-	mdesc[0].base = 0x00000000;
+	mdesc[0].base = PHYS_OFFSET;
 	mdesc[0].size = 0x00001000;
 
 	mdesc[1].type = fw_code;
-	mdesc[1].base = 0x00001000;
+	mdesc[1].base = mdesc[0].base + 0x00001000UL;
 	mdesc[1].size = 0x000ef000;
 
 	/*
@@ -78,21 +96,27 @@ fw_memblock_t * __init fw_getmdesc(void)
 	 * devices.
 	 */
 	mdesc[2].type = fw_dontuse;
-	mdesc[2].base = 0x000f0000;
+	mdesc[2].base = mdesc[0].base + 0x000f0000UL;
 	mdesc[2].size = 0x00010000;
 
 	mdesc[3].type = fw_dontuse;
-	mdesc[3].base = 0x00100000;
+	mdesc[3].base = mdesc[0].base + 0x00100000UL;
 	mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
-		mdesc[3].base;
+		0x00100000UL;
 
 	mdesc[4].type = fw_free;
-	mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
-	mdesc[4].size = memsize - mdesc[4].base;
+	mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
+	mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);
 
 	return &mdesc[0];
 }
 
+static void free_init_pages_eva_malta(void *begin, void *end)
+{
+	free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
+			__pa_symbol((unsigned long *)end));
+}
+
 static int __init fw_memtype_classify(unsigned int type)
 {
 	switch (type) {
@@ -109,7 +133,9 @@ void __init fw_meminit(void)
 {
 	fw_memblock_t *p;
 
-	p = fw_getmdesc();
+	p = fw_getmdesc(config_enabled(CONFIG_EVA));
+	free_init_pages_eva = (config_enabled(CONFIG_EVA) ?
+			       free_init_pages_eva_malta : NULL);
 
 	while (p->size) {
 		long type;
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index c72a06936781..405ff85e4b22 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -26,12 +26,12 @@
 #include <linux/time.h>
 
 #include <asm/fw/fw.h>
+#include <asm/mips-cm.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
 #include <asm/dma.h>
 #include <asm/traps.h>
-#include <asm/gcmpregs.h>
 #ifdef CONFIG_VT
 #include <linux/console.h>
 #endif
@@ -127,7 +127,7 @@ static int __init plat_enable_iocoherency(void)
 				 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
 			pr_info("Enabled Bonito IOBC coherency\n");
 		}
-	} else if (gcmp_niocu() != 0) {
+	} else if (mips_cm_numiocu() != 0) {
 		/* Nothing special needs to be done to enable coherency */
 		pr_info("CMP IOCU detected\n");
 		if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
@@ -247,6 +247,10 @@ void __init plat_mem_setup(void)
 {
 	unsigned int i;
 
+	if (config_enabled(CONFIG_EVA))
+		/* EVA has already been configured in mach-malta/kernel-init.h */
+		pr_info("Enhanced Virtual Addressing (EVA) activated\n");
+
 	mips_pcibios_init();
 
 	/* Request I/O space for devices used on the Malta board. */
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 2a86e38872a7..e4ca70bf0573 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -86,8 +86,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	case CPU_34K:
 	case CPU_1004K:
 	case CPU_74K:
+	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
+	case CPU_P5600:
 	case CPU_LOONGSON1:
 	case CPU_SB1:
 	case CPU_SB1A:
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 4d94d75ec6f9..9797493546e4 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -372,6 +372,7 @@ static int __init mipsxx_init(void)
 		op_model_mipsxx_ops.cpu_type = "mips/34K";
 		break;
 
+	case CPU_1074K:
 	case CPU_74K:
 		op_model_mipsxx_ops.cpu_type = "mips/74K";
 		break;
@@ -384,6 +385,10 @@ static int __init mipsxx_init(void)
 		op_model_mipsxx_ops.cpu_type = "mips/proAptiv";
 		break;
 
+	case CPU_P5600:
+		op_model_mipsxx_ops.cpu_type = "mips/P5600";
+		break;
+
 	case CPU_5KC:
 		op_model_mipsxx_ops.cpu_type = "mips/5K";
 		break;
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index d1faece21b6a..563d1f61d6ee 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -16,6 +16,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/vmalloc.h>
 
+#include <asm/dma-coherence.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/tlbmisc.h>
 
@@ -411,17 +412,15 @@ static int alchemy_pci_probe(struct platform_device *pdev)
 	}
 	ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io;
 
-#ifdef CONFIG_DMA_NONCOHERENT
 	/* Au1500 revisions older than AD have borked coherent PCI */
 	if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) &&
-	    (read_c0_prid() < 0x01030202)) {
+	    (read_c0_prid() < 0x01030202) && !coherentio) {
 		val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
 		val |= PCI_CONFIG_NC;
 		__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
 		wmb();
 		dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n");
 	}
-#endif
 
 	if (pd->board_map_irq)
 		ctx->board_map_irq = pd->board_map_irq;
diff --git a/arch/mips/pci/pci-malta.c b/arch/mips/pci/pci-malta.c
index f1a73890dd4f..cfbbc3e3e914 100644
--- a/arch/mips/pci/pci-malta.c
+++ b/arch/mips/pci/pci-malta.c
@@ -27,7 +27,7 @@
 #include <linux/init.h>
 
 #include <asm/gt64120.h>
-#include <asm/gcmpregs.h>
+#include <asm/mips-cm.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
 #include <asm/mips-boards/msc01_pci.h>
@@ -201,11 +201,11 @@ void __init mips_pcibios_init(void)
 		msc_mem_resource.start = start & mask;
 		msc_mem_resource.end = (start & mask) | ~mask;
 		msc_controller.mem_offset = (start & mask) - (map & mask);
-#ifdef CONFIG_MIPS_CMP
-		if (gcmp_niocu())
-			gcmp_setregion(0, start, mask,
-				GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
-#endif
+		if (mips_cm_numiocu()) {
+			write_gcr_reg0_base(start);
+			write_gcr_reg0_mask(mask |
+					    CM_GCR_REGn_MASK_CMTGT_IOCU0);
+		}
 		MSC_READ(MSC01_PCI_SC2PIOBASL, start);
 		MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
 		MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
@@ -213,11 +213,11 @@ void __init mips_pcibios_init(void)
 		msc_io_resource.end = (map & mask) | ~mask;
 		msc_controller.io_offset = 0;
 		ioport_resource.end = ~mask;
-#ifdef CONFIG_MIPS_CMP
-		if (gcmp_niocu())
-			gcmp_setregion(1, start, mask,
-				GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
-#endif
+		if (mips_cm_numiocu()) {
+			write_gcr_reg1_base(start);
+			write_gcr_reg1_mask(mask |
+					    CM_GCR_REGn_MASK_CMTGT_IOCU0);
+		}
 		/* If ranges overlap I/O takes precedence.  */
 		start = start & mask;
 		end = start | ~mask;
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
index 1bfd1c17b3c2..4a296655f446 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -20,19 +20,13 @@ choice
 	config SOC_RT305X
 		bool "RT305x"
 		select USB_ARCH_HAS_HCD
-		select USB_ARCH_HAS_OHCI
-		select USB_ARCH_HAS_EHCI
 
 	config SOC_RT3883
 		bool "RT3883"
-		select USB_ARCH_HAS_OHCI
-		select USB_ARCH_HAS_EHCI
 		select HW_HAS_PCI
 
 	config SOC_MT7620
 		bool "MT7620"
-		select USB_ARCH_HAS_OHCI
-		select USB_ARCH_HAS_EHCI
 
 endchoice
 
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 992e989ab785..cbc6b9bf45da 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -3,5 +3,6 @@ generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += hash.h
-generic-y += trace_clock.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 9488209a5253..e71d712afb79 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -41,7 +41,7 @@ config RWSEM_XCHGADD_ALGORITHM
 config GENERIC_HWEIGHT
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config TRACE_IRQFLAGS_SUPPORT
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2e40f1ca8667..480af0d9c2f5 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -10,8 +10,8 @@ generic-y += bugs.h
 generic-y += cacheflush.h
 generic-y += checksum.h
 generic-y += clkdev.h
-generic-y += cmpxchg.h
 generic-y += cmpxchg-local.h
+generic-y += cmpxchg.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += device.h
@@ -25,6 +25,7 @@ generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -34,6 +35,7 @@ generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += module.h
 generic-y += msgbuf.h
@@ -41,6 +43,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -53,11 +56,11 @@ generic-y += siginfo.h
 generic-y += signal.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += statfs.h
 generic-y += stat.h
+generic-y += statfs.h
 generic-y += string.h
-generic-y += switch_to.h
 generic-y += swab.h
+generic-y += switch_to.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -68,5 +71,3 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 752c981bc3c7..ecf25e6678ad 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -1,9 +1,29 @@
 
+generic-y += auxvec.h
 generic-y += barrier.h
-generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
-	  segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \
-	  div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
-	  poll.h xor.h clkdev.h exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += exec.h
 generic-y += hash.h
+generic-y += hw_irq.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kvm_para.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += preempt.h
+generic-y += segment.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += user.h
+generic-y += vga.h
+generic-y += word-at-a-time.h
+generic-y += xor.h
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 957bf344c0f5..b9fcecc706ab 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -736,10 +736,6 @@ config FSL_LBC
 	  controller.  Also contains some common code used by
 	  drivers for specific local bus peripherals.
 
-config FSL_IFC
-	bool
-        depends on FSL_SOC
-
 config FSL_GTM
 	bool
 	depends on PPC_83xx || QUICC_ENGINE || CPM2
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 6c0a955a1b06..3fb1bc432f4f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -1,7 +1,8 @@
 
 generic-y += clkdev.h
+generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += vtime.h
-generic-y += hash.h
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 88dbf9659185..a6774560afe3 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -210,7 +210,6 @@ extern int is_fadump_active(void);
 extern void crash_fadump(struct pt_regs *, const char *);
 extern void fadump_cleanup(void);
 
-extern void vmcore_cleanup(void);
 #else	/* CONFIG_FA_DUMP */
 static inline int is_fadump_active(void) { return 0; }
 static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h
deleted file mode 100644
index f49ddb1b2273..000000000000
--- a/arch/powerpc/include/asm/fsl_ifc.h
+++ /dev/null
@@ -1,838 +0,0 @@
-/* Freescale Integrated Flash Controller
- *
- * Copyright 2011 Freescale Semiconductor, Inc
- *
- * Author: Dipen Dudhat <dipen.dudhat@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.
- *
- * 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 __ASM_FSL_IFC_H
-#define __ASM_FSL_IFC_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <linux/interrupt.h>
-
-#define FSL_IFC_BANK_COUNT 4
-
-/*
- * CSPR - Chip Select Property Register
- */
-#define CSPR_BA				0xFFFF0000
-#define CSPR_BA_SHIFT			16
-#define CSPR_PORT_SIZE			0x00000180
-#define CSPR_PORT_SIZE_SHIFT		7
-/* Port Size 8 bit */
-#define CSPR_PORT_SIZE_8		0x00000080
-/* Port Size 16 bit */
-#define CSPR_PORT_SIZE_16		0x00000100
-/* Port Size 32 bit */
-#define CSPR_PORT_SIZE_32		0x00000180
-/* Write Protect */
-#define CSPR_WP				0x00000040
-#define CSPR_WP_SHIFT			6
-/* Machine Select */
-#define CSPR_MSEL			0x00000006
-#define CSPR_MSEL_SHIFT			1
-/* NOR */
-#define CSPR_MSEL_NOR			0x00000000
-/* NAND */
-#define CSPR_MSEL_NAND			0x00000002
-/* GPCM */
-#define CSPR_MSEL_GPCM			0x00000004
-/* Bank Valid */
-#define CSPR_V				0x00000001
-#define CSPR_V_SHIFT			0
-
-/*
- * Address Mask Register
- */
-#define IFC_AMASK_MASK			0xFFFF0000
-#define IFC_AMASK_SHIFT			16
-#define IFC_AMASK(n)			(IFC_AMASK_MASK << \
-					(__ilog2(n) - IFC_AMASK_SHIFT))
-
-/*
- * Chip Select Option Register IFC_NAND Machine
- */
-/* Enable ECC Encoder */
-#define CSOR_NAND_ECC_ENC_EN		0x80000000
-#define CSOR_NAND_ECC_MODE_MASK		0x30000000
-/* 4 bit correction per 520 Byte sector */
-#define CSOR_NAND_ECC_MODE_4		0x00000000
-/* 8 bit correction per 528 Byte sector */
-#define CSOR_NAND_ECC_MODE_8		0x10000000
-/* Enable ECC Decoder */
-#define CSOR_NAND_ECC_DEC_EN		0x04000000
-/* Row Address Length */
-#define CSOR_NAND_RAL_MASK		0x01800000
-#define CSOR_NAND_RAL_SHIFT		20
-#define CSOR_NAND_RAL_1			0x00000000
-#define CSOR_NAND_RAL_2			0x00800000
-#define CSOR_NAND_RAL_3			0x01000000
-#define CSOR_NAND_RAL_4			0x01800000
-/* Page Size 512b, 2k, 4k */
-#define CSOR_NAND_PGS_MASK		0x00180000
-#define CSOR_NAND_PGS_SHIFT		16
-#define CSOR_NAND_PGS_512		0x00000000
-#define CSOR_NAND_PGS_2K		0x00080000
-#define CSOR_NAND_PGS_4K		0x00100000
-#define CSOR_NAND_PGS_8K		0x00180000
-/* Spare region Size */
-#define CSOR_NAND_SPRZ_MASK		0x0000E000
-#define CSOR_NAND_SPRZ_SHIFT		13
-#define CSOR_NAND_SPRZ_16		0x00000000
-#define CSOR_NAND_SPRZ_64		0x00002000
-#define CSOR_NAND_SPRZ_128		0x00004000
-#define CSOR_NAND_SPRZ_210		0x00006000
-#define CSOR_NAND_SPRZ_218		0x00008000
-#define CSOR_NAND_SPRZ_224		0x0000A000
-#define CSOR_NAND_SPRZ_CSOR_EXT		0x0000C000
-/* Pages Per Block */
-#define CSOR_NAND_PB_MASK		0x00000700
-#define CSOR_NAND_PB_SHIFT		8
-#define CSOR_NAND_PB(n)		((__ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
-/* Time for Read Enable High to Output High Impedance */
-#define CSOR_NAND_TRHZ_MASK		0x0000001C
-#define CSOR_NAND_TRHZ_SHIFT		2
-#define CSOR_NAND_TRHZ_20		0x00000000
-#define CSOR_NAND_TRHZ_40		0x00000004
-#define CSOR_NAND_TRHZ_60		0x00000008
-#define CSOR_NAND_TRHZ_80		0x0000000C
-#define CSOR_NAND_TRHZ_100		0x00000010
-/* Buffer control disable */
-#define CSOR_NAND_BCTLD			0x00000001
-
-/*
- * Chip Select Option Register - NOR Flash Mode
- */
-/* Enable Address shift Mode */
-#define CSOR_NOR_ADM_SHFT_MODE_EN	0x80000000
-/* Page Read Enable from NOR device */
-#define CSOR_NOR_PGRD_EN		0x10000000
-/* AVD Toggle Enable during Burst Program */
-#define CSOR_NOR_AVD_TGL_PGM_EN		0x01000000
-/* Address Data Multiplexing Shift */
-#define CSOR_NOR_ADM_MASK		0x0003E000
-#define CSOR_NOR_ADM_SHIFT_SHIFT	13
-#define CSOR_NOR_ADM_SHIFT(n)	((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
-/* Type of the NOR device hooked */
-#define CSOR_NOR_NOR_MODE_AYSNC_NOR	0x00000000
-#define CSOR_NOR_NOR_MODE_AVD_NOR	0x00000020
-/* Time for Read Enable High to Output High Impedance */
-#define CSOR_NOR_TRHZ_MASK		0x0000001C
-#define CSOR_NOR_TRHZ_SHIFT		2
-#define CSOR_NOR_TRHZ_20		0x00000000
-#define CSOR_NOR_TRHZ_40		0x00000004
-#define CSOR_NOR_TRHZ_60		0x00000008
-#define CSOR_NOR_TRHZ_80		0x0000000C
-#define CSOR_NOR_TRHZ_100		0x00000010
-/* Buffer control disable */
-#define CSOR_NOR_BCTLD			0x00000001
-
-/*
- * Chip Select Option Register - GPCM Mode
- */
-/* GPCM Mode - Normal */
-#define CSOR_GPCM_GPMODE_NORMAL		0x00000000
-/* GPCM Mode - GenericASIC */
-#define CSOR_GPCM_GPMODE_ASIC		0x80000000
-/* Parity Mode odd/even */
-#define CSOR_GPCM_PARITY_EVEN		0x40000000
-/* Parity Checking enable/disable */
-#define CSOR_GPCM_PAR_EN		0x20000000
-/* GPCM Timeout Count */
-#define CSOR_GPCM_GPTO_MASK		0x0F000000
-#define CSOR_GPCM_GPTO_SHIFT		24
-#define CSOR_GPCM_GPTO(n)	((__ilog2(n) - 8) << CSOR_GPCM_GPTO_SHIFT)
-/* GPCM External Access Termination mode for read access */
-#define CSOR_GPCM_RGETA_EXT		0x00080000
-/* GPCM External Access Termination mode for write access */
-#define CSOR_GPCM_WGETA_EXT		0x00040000
-/* Address Data Multiplexing Shift */
-#define CSOR_GPCM_ADM_MASK		0x0003E000
-#define CSOR_GPCM_ADM_SHIFT_SHIFT	13
-#define CSOR_GPCM_ADM_SHIFT(n)	((n) << CSOR_GPCM_ADM_SHIFT_SHIFT)
-/* Generic ASIC Parity error indication delay */
-#define CSOR_GPCM_GAPERRD_MASK		0x00000180
-#define CSOR_GPCM_GAPERRD_SHIFT		7
-#define CSOR_GPCM_GAPERRD(n)	(((n) - 1) << CSOR_GPCM_GAPERRD_SHIFT)
-/* Time for Read Enable High to Output High Impedance */
-#define CSOR_GPCM_TRHZ_MASK		0x0000001C
-#define CSOR_GPCM_TRHZ_20		0x00000000
-#define CSOR_GPCM_TRHZ_40		0x00000004
-#define CSOR_GPCM_TRHZ_60		0x00000008
-#define CSOR_GPCM_TRHZ_80		0x0000000C
-#define CSOR_GPCM_TRHZ_100		0x00000010
-/* Buffer control disable */
-#define CSOR_GPCM_BCTLD			0x00000001
-
-/*
- * Ready Busy Status Register (RB_STAT)
- */
-/* CSn is READY */
-#define IFC_RB_STAT_READY_CS0		0x80000000
-#define IFC_RB_STAT_READY_CS1		0x40000000
-#define IFC_RB_STAT_READY_CS2		0x20000000
-#define IFC_RB_STAT_READY_CS3		0x10000000
-
-/*
- * General Control Register (GCR)
- */
-#define IFC_GCR_MASK			0x8000F800
-/* reset all IFC hardware */
-#define IFC_GCR_SOFT_RST_ALL		0x80000000
-/* Turnaroud Time of external buffer */
-#define IFC_GCR_TBCTL_TRN_TIME		0x0000F800
-#define IFC_GCR_TBCTL_TRN_TIME_SHIFT	11
-
-/*
- * Common Event and Error Status Register (CM_EVTER_STAT)
- */
-/* Chip select error */
-#define IFC_CM_EVTER_STAT_CSER		0x80000000
-
-/*
- * Common Event and Error Enable Register (CM_EVTER_EN)
- */
-/* Chip select error checking enable */
-#define IFC_CM_EVTER_EN_CSEREN		0x80000000
-
-/*
- * Common Event and Error Interrupt Enable Register (CM_EVTER_INTR_EN)
- */
-/* Chip select error interrupt enable */
-#define IFC_CM_EVTER_INTR_EN_CSERIREN	0x80000000
-
-/*
- * Common Transfer Error Attribute Register-0 (CM_ERATTR0)
- */
-/* transaction type of error Read/Write */
-#define IFC_CM_ERATTR0_ERTYP_READ	0x80000000
-#define IFC_CM_ERATTR0_ERAID		0x0FF00000
-#define IFC_CM_ERATTR0_ERAID_SHIFT	20
-#define IFC_CM_ERATTR0_ESRCID		0x0000FF00
-#define IFC_CM_ERATTR0_ESRCID_SHIFT	8
-
-/*
- * Clock Control Register (CCR)
- */
-#define IFC_CCR_MASK			0x0F0F8800
-/* Clock division ratio */
-#define IFC_CCR_CLK_DIV_MASK		0x0F000000
-#define IFC_CCR_CLK_DIV_SHIFT		24
-#define IFC_CCR_CLK_DIV(n)		((n-1) << IFC_CCR_CLK_DIV_SHIFT)
-/* IFC Clock Delay */
-#define IFC_CCR_CLK_DLY_MASK		0x000F0000
-#define IFC_CCR_CLK_DLY_SHIFT		16
-#define IFC_CCR_CLK_DLY(n)		((n) << IFC_CCR_CLK_DLY_SHIFT)
-/* Invert IFC clock before sending out */
-#define IFC_CCR_INV_CLK_EN		0x00008000
-/* Fedback IFC Clock */
-#define IFC_CCR_FB_IFC_CLK_SEL		0x00000800
-
-/*
- * Clock Status Register (CSR)
- */
-/* Clk is stable */
-#define IFC_CSR_CLK_STAT_STABLE		0x80000000
-
-/*
- * IFC_NAND Machine Specific Registers
- */
-/*
- * NAND Configuration Register (NCFGR)
- */
-/* Auto Boot Mode */
-#define IFC_NAND_NCFGR_BOOT		0x80000000
-/* Addressing Mode-ROW0+n/COL0 */
-#define IFC_NAND_NCFGR_ADDR_MODE_RC0	0x00000000
-/* Addressing Mode-ROW0+n/COL0+n */
-#define IFC_NAND_NCFGR_ADDR_MODE_RC1	0x00400000
-/* Number of loop iterations of FIR sequences for multi page operations */
-#define IFC_NAND_NCFGR_NUM_LOOP_MASK	0x0000F000
-#define IFC_NAND_NCFGR_NUM_LOOP_SHIFT	12
-#define IFC_NAND_NCFGR_NUM_LOOP(n)	((n) << IFC_NAND_NCFGR_NUM_LOOP_SHIFT)
-/* Number of wait cycles */
-#define IFC_NAND_NCFGR_NUM_WAIT_MASK	0x000000FF
-#define IFC_NAND_NCFGR_NUM_WAIT_SHIFT	0
-
-/*
- * NAND Flash Command Registers (NAND_FCR0/NAND_FCR1)
- */
-/* General purpose FCM flash command bytes CMD0-CMD7 */
-#define IFC_NAND_FCR0_CMD0		0xFF000000
-#define IFC_NAND_FCR0_CMD0_SHIFT	24
-#define IFC_NAND_FCR0_CMD1		0x00FF0000
-#define IFC_NAND_FCR0_CMD1_SHIFT	16
-#define IFC_NAND_FCR0_CMD2		0x0000FF00
-#define IFC_NAND_FCR0_CMD2_SHIFT	8
-#define IFC_NAND_FCR0_CMD3		0x000000FF
-#define IFC_NAND_FCR0_CMD3_SHIFT	0
-#define IFC_NAND_FCR1_CMD4		0xFF000000
-#define IFC_NAND_FCR1_CMD4_SHIFT	24
-#define IFC_NAND_FCR1_CMD5		0x00FF0000
-#define IFC_NAND_FCR1_CMD5_SHIFT	16
-#define IFC_NAND_FCR1_CMD6		0x0000FF00
-#define IFC_NAND_FCR1_CMD6_SHIFT	8
-#define IFC_NAND_FCR1_CMD7		0x000000FF
-#define IFC_NAND_FCR1_CMD7_SHIFT	0
-
-/*
- * Flash ROW and COL Address Register (ROWn, COLn)
- */
-/* Main/spare region locator */
-#define IFC_NAND_COL_MS			0x80000000
-/* Column Address */
-#define IFC_NAND_COL_CA_MASK		0x00000FFF
-
-/*
- * NAND Flash Byte Count Register (NAND_BC)
- */
-/* Byte Count for read/Write */
-#define IFC_NAND_BC			0x000001FF
-
-/*
- * NAND Flash Instruction Registers (NAND_FIR0/NAND_FIR1/NAND_FIR2)
- */
-/* NAND Machine specific opcodes OP0-OP14*/
-#define IFC_NAND_FIR0_OP0		0xFC000000
-#define IFC_NAND_FIR0_OP0_SHIFT		26
-#define IFC_NAND_FIR0_OP1		0x03F00000
-#define IFC_NAND_FIR0_OP1_SHIFT		20
-#define IFC_NAND_FIR0_OP2		0x000FC000
-#define IFC_NAND_FIR0_OP2_SHIFT		14
-#define IFC_NAND_FIR0_OP3		0x00003F00
-#define IFC_NAND_FIR0_OP3_SHIFT		8
-#define IFC_NAND_FIR0_OP4		0x000000FC
-#define IFC_NAND_FIR0_OP4_SHIFT		2
-#define IFC_NAND_FIR1_OP5		0xFC000000
-#define IFC_NAND_FIR1_OP5_SHIFT		26
-#define IFC_NAND_FIR1_OP6		0x03F00000
-#define IFC_NAND_FIR1_OP6_SHIFT		20
-#define IFC_NAND_FIR1_OP7		0x000FC000
-#define IFC_NAND_FIR1_OP7_SHIFT		14
-#define IFC_NAND_FIR1_OP8		0x00003F00
-#define IFC_NAND_FIR1_OP8_SHIFT		8
-#define IFC_NAND_FIR1_OP9		0x000000FC
-#define IFC_NAND_FIR1_OP9_SHIFT		2
-#define IFC_NAND_FIR2_OP10		0xFC000000
-#define IFC_NAND_FIR2_OP10_SHIFT	26
-#define IFC_NAND_FIR2_OP11		0x03F00000
-#define IFC_NAND_FIR2_OP11_SHIFT	20
-#define IFC_NAND_FIR2_OP12		0x000FC000
-#define IFC_NAND_FIR2_OP12_SHIFT	14
-#define IFC_NAND_FIR2_OP13		0x00003F00
-#define IFC_NAND_FIR2_OP13_SHIFT	8
-#define IFC_NAND_FIR2_OP14		0x000000FC
-#define IFC_NAND_FIR2_OP14_SHIFT	2
-
-/*
- * Instruction opcodes to be programmed
- * in FIR registers- 6bits
- */
-enum ifc_nand_fir_opcodes {
-	IFC_FIR_OP_NOP,
-	IFC_FIR_OP_CA0,
-	IFC_FIR_OP_CA1,
-	IFC_FIR_OP_CA2,
-	IFC_FIR_OP_CA3,
-	IFC_FIR_OP_RA0,
-	IFC_FIR_OP_RA1,
-	IFC_FIR_OP_RA2,
-	IFC_FIR_OP_RA3,
-	IFC_FIR_OP_CMD0,
-	IFC_FIR_OP_CMD1,
-	IFC_FIR_OP_CMD2,
-	IFC_FIR_OP_CMD3,
-	IFC_FIR_OP_CMD4,
-	IFC_FIR_OP_CMD5,
-	IFC_FIR_OP_CMD6,
-	IFC_FIR_OP_CMD7,
-	IFC_FIR_OP_CW0,
-	IFC_FIR_OP_CW1,
-	IFC_FIR_OP_CW2,
-	IFC_FIR_OP_CW3,
-	IFC_FIR_OP_CW4,
-	IFC_FIR_OP_CW5,
-	IFC_FIR_OP_CW6,
-	IFC_FIR_OP_CW7,
-	IFC_FIR_OP_WBCD,
-	IFC_FIR_OP_RBCD,
-	IFC_FIR_OP_BTRD,
-	IFC_FIR_OP_RDSTAT,
-	IFC_FIR_OP_NWAIT,
-	IFC_FIR_OP_WFR,
-	IFC_FIR_OP_SBRD,
-	IFC_FIR_OP_UA,
-	IFC_FIR_OP_RB,
-};
-
-/*
- * NAND Chip Select Register (NAND_CSEL)
- */
-#define IFC_NAND_CSEL			0x0C000000
-#define IFC_NAND_CSEL_SHIFT		26
-#define IFC_NAND_CSEL_CS0		0x00000000
-#define IFC_NAND_CSEL_CS1		0x04000000
-#define IFC_NAND_CSEL_CS2		0x08000000
-#define IFC_NAND_CSEL_CS3		0x0C000000
-
-/*
- * NAND Operation Sequence Start (NANDSEQ_STRT)
- */
-/* NAND Flash Operation Start */
-#define IFC_NAND_SEQ_STRT_FIR_STRT	0x80000000
-/* Automatic Erase */
-#define IFC_NAND_SEQ_STRT_AUTO_ERS	0x00800000
-/* Automatic Program */
-#define IFC_NAND_SEQ_STRT_AUTO_PGM	0x00100000
-/* Automatic Copyback */
-#define IFC_NAND_SEQ_STRT_AUTO_CPB	0x00020000
-/* Automatic Read Operation */
-#define IFC_NAND_SEQ_STRT_AUTO_RD	0x00004000
-/* Automatic Status Read */
-#define IFC_NAND_SEQ_STRT_AUTO_STAT_RD	0x00000800
-
-/*
- * NAND Event and Error Status Register (NAND_EVTER_STAT)
- */
-/* Operation Complete */
-#define IFC_NAND_EVTER_STAT_OPC		0x80000000
-/* Flash Timeout Error */
-#define IFC_NAND_EVTER_STAT_FTOER	0x08000000
-/* Write Protect Error */
-#define IFC_NAND_EVTER_STAT_WPER	0x04000000
-/* ECC Error */
-#define IFC_NAND_EVTER_STAT_ECCER	0x02000000
-/* RCW Load Done */
-#define IFC_NAND_EVTER_STAT_RCW_DN	0x00008000
-/* Boot Loadr Done */
-#define IFC_NAND_EVTER_STAT_BOOT_DN	0x00004000
-/* Bad Block Indicator search select */
-#define IFC_NAND_EVTER_STAT_BBI_SRCH_SE	0x00000800
-
-/*
- * NAND Flash Page Read Completion Event Status Register
- * (PGRDCMPL_EVT_STAT)
- */
-#define PGRDCMPL_EVT_STAT_MASK		0xFFFF0000
-/* Small Page 0-15 Done */
-#define PGRDCMPL_EVT_STAT_SECTION_SP(n)	(1 << (31 - (n)))
-/* Large Page(2K) 0-3 Done */
-#define PGRDCMPL_EVT_STAT_LP_2K(n)	(0xF << (28 - (n)*4))
-/* Large Page(4K) 0-1 Done */
-#define PGRDCMPL_EVT_STAT_LP_4K(n)	(0xFF << (24 - (n)*8))
-
-/*
- * NAND Event and Error Enable Register (NAND_EVTER_EN)
- */
-/* Operation complete event enable */
-#define IFC_NAND_EVTER_EN_OPC_EN	0x80000000
-/* Page read complete event enable */
-#define IFC_NAND_EVTER_EN_PGRDCMPL_EN	0x20000000
-/* Flash Timeout error enable */
-#define IFC_NAND_EVTER_EN_FTOER_EN	0x08000000
-/* Write Protect error enable */
-#define IFC_NAND_EVTER_EN_WPER_EN	0x04000000
-/* ECC error logging enable */
-#define IFC_NAND_EVTER_EN_ECCER_EN	0x02000000
-
-/*
- * NAND Event and Error Interrupt Enable Register (NAND_EVTER_INTR_EN)
- */
-/* Enable interrupt for operation complete */
-#define IFC_NAND_EVTER_INTR_OPCIR_EN		0x80000000
-/* Enable interrupt for Page read complete */
-#define IFC_NAND_EVTER_INTR_PGRDCMPLIR_EN	0x20000000
-/* Enable interrupt for Flash timeout error */
-#define IFC_NAND_EVTER_INTR_FTOERIR_EN		0x08000000
-/* Enable interrupt for Write protect error */
-#define IFC_NAND_EVTER_INTR_WPERIR_EN		0x04000000
-/* Enable interrupt for ECC error*/
-#define IFC_NAND_EVTER_INTR_ECCERIR_EN		0x02000000
-
-/*
- * NAND Transfer Error Attribute Register-0 (NAND_ERATTR0)
- */
-#define IFC_NAND_ERATTR0_MASK		0x0C080000
-/* Error on CS0-3 for NAND */
-#define IFC_NAND_ERATTR0_ERCS_CS0	0x00000000
-#define IFC_NAND_ERATTR0_ERCS_CS1	0x04000000
-#define IFC_NAND_ERATTR0_ERCS_CS2	0x08000000
-#define IFC_NAND_ERATTR0_ERCS_CS3	0x0C000000
-/* Transaction type of error Read/Write */
-#define IFC_NAND_ERATTR0_ERTTYPE_READ	0x00080000
-
-/*
- * NAND Flash Status Register (NAND_FSR)
- */
-/* First byte of data read from read status op */
-#define IFC_NAND_NFSR_RS0		0xFF000000
-/* Second byte of data read from read status op */
-#define IFC_NAND_NFSR_RS1		0x00FF0000
-
-/*
- * ECC Error Status Registers (ECCSTAT0-ECCSTAT3)
- */
-/* Number of ECC errors on sector n (n = 0-15) */
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_MASK	0x0F000000
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_SHIFT	24
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_MASK	0x000F0000
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_SHIFT	16
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_MASK	0x00000F00
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_SHIFT	8
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_MASK	0x0000000F
-#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_SHIFT	0
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_MASK	0x0F000000
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_SHIFT	24
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_MASK	0x000F0000
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_SHIFT	16
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_MASK	0x00000F00
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_SHIFT	8
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_MASK	0x0000000F
-#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_SHIFT	0
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_MASK	0x0F000000
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_SHIFT	24
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_MASK	0x000F0000
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_SHIFT	16
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_MASK	0x00000F00
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_SHIFT	8
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_MASK	0x0000000F
-#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_SHIFT	0
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_MASK	0x0F000000
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_SHIFT	24
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_MASK	0x000F0000
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_SHIFT	16
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_MASK	0x00000F00
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_SHIFT	8
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_MASK	0x0000000F
-#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_SHIFT	0
-
-/*
- * NAND Control Register (NANDCR)
- */
-#define IFC_NAND_NCR_FTOCNT_MASK	0x1E000000
-#define IFC_NAND_NCR_FTOCNT_SHIFT	25
-#define IFC_NAND_NCR_FTOCNT(n)	((_ilog2(n) - 8)  << IFC_NAND_NCR_FTOCNT_SHIFT)
-
-/*
- * NAND_AUTOBOOT_TRGR
- */
-/* Trigger RCW load */
-#define IFC_NAND_AUTOBOOT_TRGR_RCW_LD	0x80000000
-/* Trigget Auto Boot */
-#define IFC_NAND_AUTOBOOT_TRGR_BOOT_LD	0x20000000
-
-/*
- * NAND_MDR
- */
-/* 1st read data byte when opcode SBRD */
-#define IFC_NAND_MDR_RDATA0		0xFF000000
-/* 2nd read data byte when opcode SBRD */
-#define IFC_NAND_MDR_RDATA1		0x00FF0000
-
-/*
- * NOR Machine Specific Registers
- */
-/*
- * NOR Event and Error Status Register (NOR_EVTER_STAT)
- */
-/* NOR Command Sequence Operation Complete */
-#define IFC_NOR_EVTER_STAT_OPC_NOR	0x80000000
-/* Write Protect Error */
-#define IFC_NOR_EVTER_STAT_WPER		0x04000000
-/* Command Sequence Timeout Error */
-#define IFC_NOR_EVTER_STAT_STOER	0x01000000
-
-/*
- * NOR Event and Error Enable Register (NOR_EVTER_EN)
- */
-/* NOR Command Seq complete event enable */
-#define IFC_NOR_EVTER_EN_OPCEN_NOR	0x80000000
-/* Write Protect Error Checking Enable */
-#define IFC_NOR_EVTER_EN_WPEREN		0x04000000
-/* Timeout Error Enable */
-#define IFC_NOR_EVTER_EN_STOEREN	0x01000000
-
-/*
- * NOR Event and Error Interrupt Enable Register (NOR_EVTER_INTR_EN)
- */
-/* Enable interrupt for OPC complete */
-#define IFC_NOR_EVTER_INTR_OPCEN_NOR	0x80000000
-/* Enable interrupt for write protect error */
-#define IFC_NOR_EVTER_INTR_WPEREN	0x04000000
-/* Enable interrupt for timeout error */
-#define IFC_NOR_EVTER_INTR_STOEREN	0x01000000
-
-/*
- * NOR Transfer Error Attribute Register-0 (NOR_ERATTR0)
- */
-/* Source ID for error transaction */
-#define IFC_NOR_ERATTR0_ERSRCID		0xFF000000
-/* AXI ID for error transation */
-#define IFC_NOR_ERATTR0_ERAID		0x000FF000
-/* Chip select corresponds to NOR error */
-#define IFC_NOR_ERATTR0_ERCS_CS0	0x00000000
-#define IFC_NOR_ERATTR0_ERCS_CS1	0x00000010
-#define IFC_NOR_ERATTR0_ERCS_CS2	0x00000020
-#define IFC_NOR_ERATTR0_ERCS_CS3	0x00000030
-/* Type of transaction read/write */
-#define IFC_NOR_ERATTR0_ERTYPE_READ	0x00000001
-
-/*
- * NOR Transfer Error Attribute Register-2 (NOR_ERATTR2)
- */
-#define IFC_NOR_ERATTR2_ER_NUM_PHASE_EXP	0x000F0000
-#define IFC_NOR_ERATTR2_ER_NUM_PHASE_PER	0x00000F00
-
-/*
- * NOR Control Register (NORCR)
- */
-#define IFC_NORCR_MASK			0x0F0F0000
-/* No. of Address/Data Phase */
-#define IFC_NORCR_NUM_PHASE_MASK	0x0F000000
-#define IFC_NORCR_NUM_PHASE_SHIFT	24
-#define IFC_NORCR_NUM_PHASE(n)	((n-1) << IFC_NORCR_NUM_PHASE_SHIFT)
-/* Sequence Timeout Count */
-#define IFC_NORCR_STOCNT_MASK		0x000F0000
-#define IFC_NORCR_STOCNT_SHIFT		16
-#define IFC_NORCR_STOCNT(n)	((__ilog2(n) - 8) << IFC_NORCR_STOCNT_SHIFT)
-
-/*
- * GPCM Machine specific registers
- */
-/*
- * GPCM Event and Error Status Register (GPCM_EVTER_STAT)
- */
-/* Timeout error */
-#define IFC_GPCM_EVTER_STAT_TOER	0x04000000
-/* Parity error */
-#define IFC_GPCM_EVTER_STAT_PER		0x01000000
-
-/*
- * GPCM Event and Error Enable Register (GPCM_EVTER_EN)
- */
-/* Timeout error enable */
-#define IFC_GPCM_EVTER_EN_TOER_EN	0x04000000
-/* Parity error enable */
-#define IFC_GPCM_EVTER_EN_PER_EN	0x01000000
-
-/*
- * GPCM Event and Error Interrupt Enable Register (GPCM_EVTER_INTR_EN)
- */
-/* Enable Interrupt for timeout error */
-#define IFC_GPCM_EEIER_TOERIR_EN	0x04000000
-/* Enable Interrupt for Parity error */
-#define IFC_GPCM_EEIER_PERIR_EN		0x01000000
-
-/*
- * GPCM Transfer Error Attribute Register-0 (GPCM_ERATTR0)
- */
-/* Source ID for error transaction */
-#define IFC_GPCM_ERATTR0_ERSRCID	0xFF000000
-/* AXI ID for error transaction */
-#define IFC_GPCM_ERATTR0_ERAID		0x000FF000
-/* Chip select corresponds to GPCM error */
-#define IFC_GPCM_ERATTR0_ERCS_CS0	0x00000000
-#define IFC_GPCM_ERATTR0_ERCS_CS1	0x00000040
-#define IFC_GPCM_ERATTR0_ERCS_CS2	0x00000080
-#define IFC_GPCM_ERATTR0_ERCS_CS3	0x000000C0
-/* Type of transaction read/Write */
-#define IFC_GPCM_ERATTR0_ERTYPE_READ	0x00000001
-
-/*
- * GPCM Transfer Error Attribute Register-2 (GPCM_ERATTR2)
- */
-/* On which beat of address/data parity error is observed */
-#define IFC_GPCM_ERATTR2_PERR_BEAT		0x00000C00
-/* Parity Error on byte */
-#define IFC_GPCM_ERATTR2_PERR_BYTE		0x000000F0
-/* Parity Error reported in addr or data phase */
-#define IFC_GPCM_ERATTR2_PERR_DATA_PHASE	0x00000001
-
-/*
- * GPCM Status Register (GPCM_STAT)
- */
-#define IFC_GPCM_STAT_BSY		0x80000000  /* GPCM is busy */
-
-/*
- * IFC Controller NAND Machine registers
- */
-struct fsl_ifc_nand {
-	__be32 ncfgr;
-	u32 res1[0x4];
-	__be32 nand_fcr0;
-	__be32 nand_fcr1;
-	u32 res2[0x8];
-	__be32 row0;
-	u32 res3;
-	__be32 col0;
-	u32 res4;
-	__be32 row1;
-	u32 res5;
-	__be32 col1;
-	u32 res6;
-	__be32 row2;
-	u32 res7;
-	__be32 col2;
-	u32 res8;
-	__be32 row3;
-	u32 res9;
-	__be32 col3;
-	u32 res10[0x24];
-	__be32 nand_fbcr;
-	u32 res11;
-	__be32 nand_fir0;
-	__be32 nand_fir1;
-	__be32 nand_fir2;
-	u32 res12[0x10];
-	__be32 nand_csel;
-	u32 res13;
-	__be32 nandseq_strt;
-	u32 res14;
-	__be32 nand_evter_stat;
-	u32 res15;
-	__be32 pgrdcmpl_evt_stat;
-	u32 res16[0x2];
-	__be32 nand_evter_en;
-	u32 res17[0x2];
-	__be32 nand_evter_intr_en;
-	u32 res18[0x2];
-	__be32 nand_erattr0;
-	__be32 nand_erattr1;
-	u32 res19[0x10];
-	__be32 nand_fsr;
-	u32 res20;
-	__be32 nand_eccstat[4];
-	u32 res21[0x20];
-	__be32 nanndcr;
-	u32 res22[0x2];
-	__be32 nand_autoboot_trgr;
-	u32 res23;
-	__be32 nand_mdr;
-	u32 res24[0x5C];
-};
-
-/*
- * IFC controller NOR Machine registers
- */
-struct fsl_ifc_nor {
-	__be32 nor_evter_stat;
-	u32 res1[0x2];
-	__be32 nor_evter_en;
-	u32 res2[0x2];
-	__be32 nor_evter_intr_en;
-	u32 res3[0x2];
-	__be32 nor_erattr0;
-	__be32 nor_erattr1;
-	__be32 nor_erattr2;
-	u32 res4[0x4];
-	__be32 norcr;
-	u32 res5[0xEF];
-};
-
-/*
- * IFC controller GPCM Machine registers
- */
-struct fsl_ifc_gpcm {
-	__be32 gpcm_evter_stat;
-	u32 res1[0x2];
-	__be32 gpcm_evter_en;
-	u32 res2[0x2];
-	__be32 gpcm_evter_intr_en;
-	u32 res3[0x2];
-	__be32 gpcm_erattr0;
-	__be32 gpcm_erattr1;
-	__be32 gpcm_erattr2;
-	__be32 gpcm_stat;
-	u32 res4[0x1F3];
-};
-
-/*
- * IFC Controller Registers
- */
-struct fsl_ifc_regs {
-	__be32 ifc_rev;
-	u32 res1[0x2];
-	struct {
-		__be32 cspr_ext;
-		__be32 cspr;
-		u32 res2;
-	} cspr_cs[FSL_IFC_BANK_COUNT];
-	u32 res3[0x19];
-	struct {
-		__be32 amask;
-		u32 res4[0x2];
-	} amask_cs[FSL_IFC_BANK_COUNT];
-	u32 res5[0x17];
-	struct {
-		__be32 csor_ext;
-		__be32 csor;
-		u32 res6;
-	} csor_cs[FSL_IFC_BANK_COUNT];
-	u32 res7[0x19];
-	struct {
-		__be32 ftim[4];
-		u32 res8[0x8];
-	} ftim_cs[FSL_IFC_BANK_COUNT];
-	u32 res9[0x60];
-	__be32 rb_stat;
-	u32 res10[0x2];
-	__be32 ifc_gcr;
-	u32 res11[0x2];
-	__be32 cm_evter_stat;
-	u32 res12[0x2];
-	__be32 cm_evter_en;
-	u32 res13[0x2];
-	__be32 cm_evter_intr_en;
-	u32 res14[0x2];
-	__be32 cm_erattr0;
-	__be32 cm_erattr1;
-	u32 res15[0x2];
-	__be32 ifc_ccr;
-	__be32 ifc_csr;
-	u32 res16[0x2EB];
-	struct fsl_ifc_nand ifc_nand;
-	struct fsl_ifc_nor ifc_nor;
-	struct fsl_ifc_gpcm ifc_gpcm;
-};
-
-extern unsigned int convert_ifc_address(phys_addr_t addr_base);
-extern int fsl_ifc_find(phys_addr_t addr_base);
-
-/* overview of the fsl ifc controller */
-
-struct fsl_ifc_ctrl {
-	/* device info */
-	struct device			*dev;
-	struct fsl_ifc_regs __iomem	*regs;
-	int				irq;
-	int				nand_irq;
-	spinlock_t			lock;
-	void				*nand;
-
-	u32 nand_stat;
-	wait_queue_head_t nand_wait;
-};
-
-extern struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
-
-
-#endif /* __ASM_FSL_IFC_H */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index a9e311f7a9dd..2a4779091a58 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -208,7 +208,6 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 			  unsigned long in_devfn)
 {
 	struct pci_controller* hose;
-	struct list_head *ln;
 	struct pci_bus *bus = NULL;
 	struct device_node *hose_node;
 
@@ -230,8 +229,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 	 * used on pre-domains setup. We return the first match
 	 */
 
-	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
-		bus = pci_bus_b(ln);
+	list_for_each_entry(bus, &pci_root_buses, node) {
 		if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
 			break;
 		bus = NULL;
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/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index d6c7506ec7d9..dc1a264ec6e6 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -265,7 +265,6 @@ config 440EP
 	select PPC_FPU
 	select IBM440EP_ERR42
 	select IBM_EMAC_ZMII
-	select USB_ARCH_HAS_OHCI
 
 config 440EPX
 	bool
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 434fda39bf8b..d9e2b19b7c8d 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -73,6 +73,7 @@ config PPC_BOOK3S_64
 	select SYS_SUPPORTS_HUGETLBFS
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if PPC_64K_PAGES
 	select ARCH_SUPPORTS_NUMA_BALANCING
+	select IRQ_WORK
 
 config PPC_BOOK3E_64
 	bool "Embedded processors"
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 5ec1e47a0d77..e865d748179b 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -123,7 +123,8 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order)
 
 	area->nid = nid;
 	area->order = order;
-	area->pages = alloc_pages_exact_node(area->nid, GFP_KERNEL|GFP_THISNODE,
+	area->pages = alloc_pages_exact_node(area->nid,
+						GFP_KERNEL|__GFP_THISNODE,
 						area->order);
 
 	if (!area->pages) {
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 49318385d4fa..4a0a64fe25df 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -83,7 +83,6 @@ static struct timer_list spuloadavg_timer;
 #define MIN_SPU_TIMESLICE	max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
 #define DEF_SPU_TIMESLICE	(100 * HZ / (1000 * SPUSCHED_TICK))
 
-#define MAX_USER_PRIO		(MAX_PRIO - MAX_RT_PRIO)
 #define SCALE_PRIO(x, prio) \
 	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
 
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 110f4fbd319f..81a7a0a79be7 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -26,7 +26,6 @@
 #include <linux/of_fdt.h>
 #include <linux/interrupt.h>
 #include <linux/bug.h>
-#include <linux/cpuidle.h>
 #include <linux/pci.h>
 
 #include <asm/machdep.h>
@@ -225,16 +224,6 @@ static int __init pnv_probe(void)
 	return 1;
 }
 
-void powernv_idle(void)
-{
-	/* Hook to cpuidle framework if available, else
-	 * call on default platform idle code
-	 */
-	if (cpuidle_idle_call()) {
-		power7_idle();
-	}
-}
-
 define_machine(powernv) {
 	.name			= "PowerNV",
 	.probe			= pnv_probe,
@@ -244,7 +233,7 @@ define_machine(powernv) {
 	.show_cpuinfo		= pnv_show_cpuinfo,
 	.progress		= pnv_progress,
 	.machine_shutdown	= pnv_shutdown,
-	.power_save             = powernv_idle,
+	.power_save             = power7_idle,
 	.calibrate_decr		= generic_calibrate_decr,
 	.dma_set_mask		= pnv_dma_set_mask,
 #ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index e87c19473973..56f274064d6c 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -2,10 +2,8 @@ config PPC_PS3
 	bool "Sony PS3"
 	depends on PPC64 && PPC_BOOK3S
 	select PPC_CELL
-	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_LITTLE_ENDIAN
 	select USB_OHCI_BIG_ENDIAN_MMIO
-	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	select PPC_PCI_CHOICE
 	help
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index efe61374f6ea..203cbf0dc101 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -37,15 +37,15 @@ find_bus_among_children(struct pci_bus *bus,
                         struct device_node *dn)
 {
 	struct pci_bus *child = NULL;
-	struct list_head *tmp;
+	struct pci_bus *tmp;
 	struct device_node *busdn;
 
 	busdn = pci_bus_to_OF_node(bus);
 	if (busdn == dn)
 		return bus;
 
-	list_for_each(tmp, &bus->children) {
-		child = find_bus_among_children(pci_bus_b(tmp), dn);
+	list_for_each_entry(tmp, &bus->children, node) {
+		child = find_bus_among_children(tmp, dn);
 		if (child)
 			break;
 	};
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 972df0ffd4dc..2db8cc691bf4 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -39,7 +39,6 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
-#include <linux/cpuidle.h>
 #include <linux/of.h>
 #include <linux/kexec.h>
 
@@ -356,29 +355,24 @@ early_initcall(alloc_dispatch_log_kmem_cache);
 
 static void pseries_lpar_idle(void)
 {
-	/* This would call on the cpuidle framework, and the back-end pseries
-	 * driver to  go to idle states
+	/*
+	 * Default handler to go into low thread priority and possibly
+	 * low power mode by cedeing processor to hypervisor
 	 */
-	if (cpuidle_idle_call()) {
-		/* On error, execute default handler
-		 * to go into low thread priority and possibly
-		 * low power mode by cedeing processor to hypervisor
-		 */
 
-		/* Indicate to hypervisor that we are idle. */
-		get_lppaca()->idle = 1;
+	/* Indicate to hypervisor that we are idle. */
+	get_lppaca()->idle = 1;
 
-		/*
-		 * Yield the processor to the hypervisor.  We return if
-		 * an external interrupt occurs (which are driven prior
-		 * to returning here) or if a prod occurs from another
-		 * processor. When returning here, external interrupts
-		 * are enabled.
-		 */
-		cede_processor();
+	/*
+	 * Yield the processor to the hypervisor.  We return if
+	 * an external interrupt occurs (which are driven prior
+	 * to returning here) or if a prod occurs from another
+	 * processor. When returning here, external interrupts
+	 * are enabled.
+	 */
+	cede_processor();
 
-		get_lppaca()->idle = 0;
-	}
+	get_lppaca()->idle = 0;
 }
 
 /*
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f67ac900d870..afbcc37aa094 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
-obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
diff --git a/arch/powerpc/sysdev/fsl_ifc.c b/arch/powerpc/sysdev/fsl_ifc.c
deleted file mode 100644
index fbc885b31946..000000000000
--- a/arch/powerpc/sysdev/fsl_ifc.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc
- *
- * Freescale Integrated Flash Controller
- *
- * Author: Dipen Dudhat <Dipen.Dudhat@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.
- *
- * 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.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <asm/prom.h>
-#include <asm/fsl_ifc.h>
-
-struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
-EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
-
-/*
- * convert_ifc_address - convert the base address
- * @addr_base:	base address of the memory bank
- */
-unsigned int convert_ifc_address(phys_addr_t addr_base)
-{
-	return addr_base & CSPR_BA;
-}
-EXPORT_SYMBOL(convert_ifc_address);
-
-/*
- * fsl_ifc_find - find IFC bank
- * @addr_base:	base address of the memory bank
- *
- * This function walks IFC banks comparing "Base address" field of the CSPR
- * registers with the supplied addr_base argument. When bases match this
- * function returns bank number (starting with 0), otherwise it returns
- * appropriate errno value.
- */
-int fsl_ifc_find(phys_addr_t addr_base)
-{
-	int i = 0;
-
-	if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
-		return -ENODEV;
-
-	for (i = 0; i < ARRAY_SIZE(fsl_ifc_ctrl_dev->regs->cspr_cs); i++) {
-		u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr);
-		if (cspr & CSPR_V && (cspr & CSPR_BA) ==
-				convert_ifc_address(addr_base))
-			return i;
-	}
-
-	return -ENOENT;
-}
-EXPORT_SYMBOL(fsl_ifc_find);
-
-static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
-{
-	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
-
-	/*
-	 * Clear all the common status and event registers
-	 */
-	if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER)
-		out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
-	/* enable all error and events */
-	out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN);
-
-	/* enable all error and event interrupts */
-	out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN);
-	out_be32(&ifc->cm_erattr0, 0x0);
-	out_be32(&ifc->cm_erattr1, 0x0);
-
-	return 0;
-}
-
-static int fsl_ifc_ctrl_remove(struct platform_device *dev)
-{
-	struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
-
-	free_irq(ctrl->nand_irq, ctrl);
-	free_irq(ctrl->irq, ctrl);
-
-	irq_dispose_mapping(ctrl->nand_irq);
-	irq_dispose_mapping(ctrl->irq);
-
-	iounmap(ctrl->regs);
-
-	dev_set_drvdata(&dev->dev, NULL);
-	kfree(ctrl);
-
-	return 0;
-}
-
-/*
- * NAND events are split between an operational interrupt which only
- * receives OPC, and an error interrupt that receives everything else,
- * including non-NAND errors.  Whichever interrupt gets to it first
- * records the status and wakes the wait queue.
- */
-static DEFINE_SPINLOCK(nand_irq_lock);
-
-static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
-{
-	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
-	unsigned long flags;
-	u32 stat;
-
-	spin_lock_irqsave(&nand_irq_lock, flags);
-
-	stat = in_be32(&ifc->ifc_nand.nand_evter_stat);
-	if (stat) {
-		out_be32(&ifc->ifc_nand.nand_evter_stat, stat);
-		ctrl->nand_stat = stat;
-		wake_up(&ctrl->nand_wait);
-	}
-
-	spin_unlock_irqrestore(&nand_irq_lock, flags);
-
-	return stat;
-}
-
-static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
-{
-	struct fsl_ifc_ctrl *ctrl = data;
-
-	if (check_nand_stat(ctrl))
-		return IRQ_HANDLED;
-
-	return IRQ_NONE;
-}
-
-/*
- * NOTE: This interrupt is used to report ifc events of various kinds,
- * such as transaction errors on the chipselects.
- */
-static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
-{
-	struct fsl_ifc_ctrl *ctrl = data;
-	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
-	u32 err_axiid, err_srcid, status, cs_err, err_addr;
-	irqreturn_t ret = IRQ_NONE;
-
-	/* read for chip select error */
-	cs_err = in_be32(&ifc->cm_evter_stat);
-	if (cs_err) {
-		dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
-				"any memory bank 0x%08X\n", cs_err);
-		/* clear the chip select error */
-		out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
-		/* read error attribute registers print the error information */
-		status = in_be32(&ifc->cm_erattr0);
-		err_addr = in_be32(&ifc->cm_erattr1);
-
-		if (status & IFC_CM_ERATTR0_ERTYP_READ)
-			dev_err(ctrl->dev, "Read transaction error"
-				"CM_ERATTR0 0x%08X\n", status);
-		else
-			dev_err(ctrl->dev, "Write transaction error"
-				"CM_ERATTR0 0x%08X\n", status);
-
-		err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
-					IFC_CM_ERATTR0_ERAID_SHIFT;
-		dev_err(ctrl->dev, "AXI ID of the error"
-					"transaction 0x%08X\n", err_axiid);
-
-		err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
-					IFC_CM_ERATTR0_ESRCID_SHIFT;
-		dev_err(ctrl->dev, "SRC ID of the error"
-					"transaction 0x%08X\n", err_srcid);
-
-		dev_err(ctrl->dev, "Transaction Address corresponding to error"
-					"ERADDR 0x%08X\n", err_addr);
-
-		ret = IRQ_HANDLED;
-	}
-
-	if (check_nand_stat(ctrl))
-		ret = IRQ_HANDLED;
-
-	return ret;
-}
-
-/*
- * fsl_ifc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only.  The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-static int fsl_ifc_ctrl_probe(struct platform_device *dev)
-{
-	int ret = 0;
-
-
-	dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
-
-	fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
-	if (!fsl_ifc_ctrl_dev)
-		return -ENOMEM;
-
-	dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
-
-	/* IOMAP the entire IFC region */
-	fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
-	if (!fsl_ifc_ctrl_dev->regs) {
-		dev_err(&dev->dev, "failed to get memory region\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	/* get the Controller level irq */
-	fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
-	if (fsl_ifc_ctrl_dev->irq == NO_IRQ) {
-		dev_err(&dev->dev, "failed to get irq resource "
-							"for IFC\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	/* get the nand machine irq */
-	fsl_ifc_ctrl_dev->nand_irq =
-			irq_of_parse_and_map(dev->dev.of_node, 1);
-
-	fsl_ifc_ctrl_dev->dev = &dev->dev;
-
-	ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
-	if (ret < 0)
-		goto err;
-
-	init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
-
-	ret = request_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_irq, IRQF_SHARED,
-			  "fsl-ifc", fsl_ifc_ctrl_dev);
-	if (ret != 0) {
-		dev_err(&dev->dev, "failed to install irq (%d)\n",
-			fsl_ifc_ctrl_dev->irq);
-		goto err_irq;
-	}
-
-	if (fsl_ifc_ctrl_dev->nand_irq) {
-		ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
-				0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
-		if (ret != 0) {
-			dev_err(&dev->dev, "failed to install irq (%d)\n",
-				fsl_ifc_ctrl_dev->nand_irq);
-			goto err_nandirq;
-		}
-	}
-
-	return 0;
-
-err_nandirq:
-	free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
-	irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
-err_irq:
-	free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
-	irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
-err:
-	return ret;
-}
-
-static const struct of_device_id fsl_ifc_match[] = {
-	{
-		.compatible = "fsl,ifc",
-	},
-	{},
-};
-
-static struct platform_driver fsl_ifc_ctrl_driver = {
-	.driver = {
-		.name	= "fsl-ifc",
-		.of_match_table = fsl_ifc_match,
-	},
-	.probe       = fsl_ifc_ctrl_probe,
-	.remove      = fsl_ifc_ctrl_remove,
-};
-
-module_platform_driver(fsl_ifc_ctrl_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Freescale Semiconductor");
-MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 95dd892e9904..cf2b0840a672 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -531,6 +531,7 @@ int fsl_rio_setup(struct platform_device *dev)
 		sprintf(port->name, "RIO mport %d", i);
 
 		priv->dev = &dev->dev;
+		port->dev.parent = &dev->dev;
 		port->ops = ops;
 		port->priv = priv;
 		port->phys_efptr = 0x100;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 65a07750f4f9..346d21678ffd 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -52,7 +52,7 @@ config KEXEC
 config AUDIT_ARCH
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool y
 
 config PCI_QUIRKS
@@ -117,6 +117,7 @@ config S390
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_FUTEX_CMPXCHG if FUTEX
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZ4
@@ -140,6 +141,7 @@ config S390
 	select OLD_SIGACTION
 	select OLD_SIGSUSPEND3
 	select SYSCTL_EXCEPTION_TRACE
+	select TTY
 	select VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
 
@@ -415,6 +417,10 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
 config ARCH_ENABLE_MEMORY_HOTREMOVE
 	def_bool y
 
+config ARCH_ENABLE_SPLIT_PMD_PTLOCK
+	def_bool y
+	depends on 64BIT
+
 config FORCE_MAX_ZONEORDER
 	int
 	default "9"
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8386a4a1f19a..57892a8a9055 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -1,6 +1,7 @@
 
 
 generic-y += clkdev.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h
index 4bbb5957ed1b..bd93ff6661b8 100644
--- a/arch/s390/include/asm/airq.h
+++ b/arch/s390/include/asm/airq.h
@@ -44,11 +44,21 @@ struct airq_iv {
 
 struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags);
 void airq_iv_release(struct airq_iv *iv);
-unsigned long airq_iv_alloc_bit(struct airq_iv *iv);
-void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit);
+unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num);
+void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num);
 unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
 			   unsigned long end);
 
+static inline unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
+{
+	return airq_iv_alloc(iv, 1);
+}
+
+static inline void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
+{
+	airq_iv_free(iv, bit, 1);
+}
+
 static inline unsigned long airq_iv_end(struct airq_iv *iv)
 {
 	return iv->end;
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 6e6ad0680829..ec5ef891db6b 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -13,9 +13,9 @@
  *
  * The bitop functions are defined to work on unsigned longs, so for an
  * s390x system the bits end up numbered:
- *   |63..............0|127............64|191...........128|255...........196|
+ *   |63..............0|127............64|191...........128|255...........192|
  * and on s390:
- *   |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *   |31.....0|63....32|95....64|127...96|159..128|191..160|223..192|255..224|
  *
  * There are a few little-endian macros used mostly for filesystem
  * bitmaps, these work on similar bit arrays layouts, but
@@ -30,7 +30,7 @@
  * on an s390x system the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  *
  * The main difference is that bit 0-63 (64b) or 0-31 (32b) in the bit
  * number field needs to be reversed compared to the LSB0 encoded bit
@@ -304,7 +304,7 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
  * On an s390x system the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  */
 unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size);
 unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index f201af8be580..a9c2c0686177 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -219,7 +219,9 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
 #define to_ccwdev(n) container_of(n, struct ccw_device, dev)
 #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
 
-extern struct ccw_device *ccw_device_probe_console(void);
+extern struct ccw_device *ccw_device_create_console(struct ccw_driver *);
+extern void ccw_device_destroy_console(struct ccw_device *);
+extern int ccw_device_enable_console(struct ccw_device *);
 extern void ccw_device_wait_idle(struct ccw_device *);
 extern int ccw_device_force_console(struct ccw_device *);
 
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
index 23723ce5ca7a..6e670f88d125 100644
--- a/arch/s390/include/asm/ccwgroup.h
+++ b/arch/s390/include/asm/ccwgroup.h
@@ -23,6 +23,7 @@ struct ccwgroup_device {
 	unsigned int count;
 	struct device	dev;
 	struct ccw_device *cdev[0];
+	struct work_struct ungroup_work;
 };
 
 /**
diff --git a/arch/s390/include/asm/checksum.h b/arch/s390/include/asm/checksum.h
index 4f57a4f3909a..740364856355 100644
--- a/arch/s390/include/asm/checksum.h
+++ b/arch/s390/include/asm/checksum.h
@@ -44,22 +44,15 @@ csum_partial(const void *buff, int len, __wsum sum)
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  *
- * Copy from userspace and compute checksum.  If we catch an exception
- * then zero the rest of the buffer.
+ * Copy from userspace and compute checksum.
  */
 static inline __wsum
 csum_partial_copy_from_user(const void __user *src, void *dst,
                                           int len, __wsum sum,
                                           int *err_ptr)
 {
-	int missing;
-
-	missing = copy_from_user(dst, src, len);
-	if (missing) {
-		memset(dst + len - missing, 0, missing);
+	if (unlikely(copy_from_user(dst, src, len)))
 		*err_ptr = -EFAULT;
-	}
-		
 	return csum_partial(dst, len, sum);
 }
 
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h
index d42625053c37..096339207764 100644
--- a/arch/s390/include/asm/cio.h
+++ b/arch/s390/include/asm/cio.h
@@ -199,7 +199,7 @@ struct esw_eadm {
 /**
  * struct irb - interruption response block
  * @scsw: subchannel status word
- * @esw: extened status word
+ * @esw: extended status word
  * @ecw: extended control word
  *
  * The irb that is handed to the device driver when an interrupt occurs. For
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 51bcaa0fdeef..fda46bd38c99 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -5,7 +5,10 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval);
+int __futex_atomic_op_inuser(int op, u32 __user *uaddr, int oparg, int *old);
+
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -17,7 +20,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 		oparg = 1 << oparg;
 
 	pagefault_disable();
-	ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval);
+	ret = __futex_atomic_op_inuser(op, uaddr, oparg, &oldval);
 	pagefault_enable();
 
 	if (!ret) {
@@ -34,10 +37,4 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
-						u32 oldval, u32 newval)
-{
-	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
-}
-
 #endif /* _ASM_S390_FUTEX_H */
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index eef3dd3fd9a9..26ef9c0c0f55 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -16,6 +16,7 @@
 #include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/kvm_host.h>
+#include <linux/kvm.h>
 #include <asm/debug.h>
 #include <asm/cpu.h>
 
@@ -106,7 +107,9 @@ struct kvm_s390_sie_block {
 	__u64	gbea;			/* 0x0180 */
 	__u8	reserved188[24];	/* 0x0188 */
 	__u32	fac;			/* 0x01a0 */
-	__u8	reserved1a4[68];	/* 0x01a4 */
+	__u8	reserved1a4[20];	/* 0x01a4 */
+	__u64	cbrlo;			/* 0x01b8 */
+	__u8	reserved1c0[40];	/* 0x01c0 */
 	__u64	itdba;			/* 0x01e8 */
 	__u8	reserved1f0[16];	/* 0x01f0 */
 } __attribute__((packed));
@@ -155,6 +158,7 @@ struct kvm_vcpu_stat {
 	u32 instruction_stsi;
 	u32 instruction_stfl;
 	u32 instruction_tprot;
+	u32 instruction_essa;
 	u32 instruction_sigp_sense;
 	u32 instruction_sigp_sense_running;
 	u32 instruction_sigp_external_call;
@@ -168,18 +172,6 @@ struct kvm_vcpu_stat {
 	u32 diagnose_9c;
 };
 
-struct kvm_s390_io_info {
-	__u16        subchannel_id;            /* 0x0b8 */
-	__u16        subchannel_nr;            /* 0x0ba */
-	__u32        io_int_parm;              /* 0x0bc */
-	__u32        io_int_word;              /* 0x0c0 */
-};
-
-struct kvm_s390_ext_info {
-	__u32 ext_params;
-	__u64 ext_params2;
-};
-
 #define PGM_OPERATION            0x01
 #define PGM_PRIVILEGED_OP	 0x02
 #define PGM_EXECUTE              0x03
@@ -188,27 +180,6 @@ struct kvm_s390_ext_info {
 #define PGM_SPECIFICATION        0x06
 #define PGM_DATA                 0x07
 
-struct kvm_s390_pgm_info {
-	__u16 code;
-};
-
-struct kvm_s390_prefix_info {
-	__u32 address;
-};
-
-struct kvm_s390_extcall_info {
-	__u16 code;
-};
-
-struct kvm_s390_emerg_info {
-	__u16 code;
-};
-
-struct kvm_s390_mchk_info {
-	__u64 cr14;
-	__u64 mcic;
-};
-
 struct kvm_s390_interrupt_info {
 	struct list_head list;
 	u64	type;
@@ -246,6 +217,7 @@ struct kvm_s390_float_interrupt {
 	unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1)
 				/ sizeof(long)];
 	struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS];
+	unsigned int irq_count;
 };
 
 
@@ -262,6 +234,10 @@ struct kvm_vcpu_arch {
 		u64		stidp_data;
 	};
 	struct gmap *gmap;
+#define KVM_S390_PFAULT_TOKEN_INVALID	(-1UL)
+	unsigned long pfault_token;
+	unsigned long pfault_select;
+	unsigned long pfault_compare;
 };
 
 struct kvm_vm_stat {
@@ -275,6 +251,7 @@ struct kvm_arch{
 	struct sca_block *sca;
 	debug_info_t *dbf;
 	struct kvm_s390_float_interrupt float_int;
+	struct kvm_device *flic;
 	struct gmap *gmap;
 	int css_support;
 };
@@ -287,6 +264,24 @@ static inline bool kvm_is_error_hva(unsigned long addr)
 	return IS_ERR_VALUE(addr);
 }
 
+#define ASYNC_PF_PER_VCPU	64
+struct kvm_vcpu;
+struct kvm_async_pf;
+struct kvm_arch_async_pf {
+	unsigned long pfault_token;
+};
+
+bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu);
+
+void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
+			       struct kvm_async_pf *work);
+
+void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
+				     struct kvm_async_pf *work);
+
+void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
+				 struct kvm_async_pf *work);
+
 extern int sie64a(struct kvm_s390_sie_block *, u64 *);
 extern char sie_exit;
 #endif
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 5d1f950704dc..38149b63dc44 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -48,13 +48,42 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
-	cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
-	update_mm(next, tsk);
+	int cpu = smp_processor_id();
+
+	if (prev == next)
+		return;
+	if (atomic_inc_return(&next->context.attach_count) >> 16) {
+		/* Delay update_mm until all TLB flushes are done. */
+		set_tsk_thread_flag(tsk, TIF_TLB_WAIT);
+	} else {
+		cpumask_set_cpu(cpu, mm_cpumask(next));
+		update_mm(next, tsk);
+		if (next->context.flush_mm)
+			/* Flush pending TLBs */
+			__tlb_flush_mm(next);
+	}
 	atomic_dec(&prev->context.attach_count);
 	WARN_ON(atomic_read(&prev->context.attach_count) < 0);
-	atomic_inc(&next->context.attach_count);
-	/* Check for TLBs not flushed yet */
-	__tlb_flush_mm_lazy(next);
+}
+
+#define finish_arch_post_lock_switch finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->mm;
+
+	if (!test_tsk_thread_flag(tsk, TIF_TLB_WAIT))
+		return;
+	preempt_disable();
+	clear_tsk_thread_flag(tsk, TIF_TLB_WAIT);
+	while (atomic_read(&mm->context.attach_count) >> 16)
+		cpu_relax();
+
+	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+	update_mm(mm, tsk);
+	if (mm->context.flush_mm)
+		__tlb_flush_mm(mm);
+	preempt_enable();
 }
 
 #define enter_lazy_tlb(mm,tsk)	do { } while (0)
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index e1408ddb94f8..884017cbfa9f 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -22,6 +22,7 @@ unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
 void page_table_free(struct mm_struct *, unsigned long *);
 void page_table_free_rcu(struct mmu_gather *, unsigned long *);
 
+void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long);
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
 			  unsigned long key, bool nq);
 
@@ -91,11 +92,22 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
 	unsigned long *table = crst_table_alloc(mm);
-	if (table)
-		crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+
+	if (!table)
+		return NULL;
+	crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+	if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
+		crst_table_free(mm, table);
+		return NULL;
+	}
 	return (pmd_t *) table;
 }
-#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	pgtable_pmd_page_dtor(virt_to_page(pmd));
+	crst_table_free(mm, (unsigned long *) pmd);
+}
 
 static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 {
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 2204400d0bd5..6e89ba75cbc5 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -229,6 +229,7 @@ extern unsigned long MODULES_END;
 #define _PAGE_READ	0x010		/* SW pte read bit */
 #define _PAGE_WRITE	0x020		/* SW pte write bit */
 #define _PAGE_SPECIAL	0x040		/* SW associated with special page */
+#define _PAGE_UNUSED	0x080		/* SW bit for pgste usage state */
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /* Set of bits not changed in pte_modify */
@@ -394,6 +395,12 @@ extern unsigned long MODULES_END;
 
 #endif /* CONFIG_64BIT */
 
+/* Guest Page State used for virtualization */
+#define _PGSTE_GPS_ZERO		0x0000000080000000UL
+#define _PGSTE_GPS_USAGE_MASK	0x0000000003000000UL
+#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
+#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
+
 /*
  * A user page table pointer has the space-switch-event bit, the
  * private-space-control bit and the storage-alteration-event-control
@@ -617,6 +624,14 @@ static inline int pte_none(pte_t pte)
 	return pte_val(pte) == _PAGE_INVALID;
 }
 
+static inline int pte_swap(pte_t pte)
+{
+	/* Bit pattern: (pte & 0x603) == 0x402 */
+	return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT |
+				_PAGE_TYPE | _PAGE_PRESENT))
+		== (_PAGE_INVALID | _PAGE_TYPE);
+}
+
 static inline int pte_file(pte_t pte)
 {
 	/* Bit pattern: (pte & 0x601) == 0x600 */
@@ -767,6 +782,7 @@ static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
  * @table: pointer to the page directory
  * @asce: address space control element for gmap page table
  * @crst_list: list of all crst tables used in the guest address space
+ * @pfault_enabled: defines if pfaults are applicable for the guest
  */
 struct gmap {
 	struct list_head list;
@@ -775,6 +791,7 @@ struct gmap {
 	unsigned long asce;
 	void *private;
 	struct list_head crst_list;
+	bool pfault_enabled;
 };
 
 /**
@@ -821,6 +838,7 @@ unsigned long gmap_translate(unsigned long address, struct gmap *);
 unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
+void __gmap_zap(unsigned long address, struct gmap *);
 
 void gmap_register_ipte_notifier(struct gmap_notifier *);
 void gmap_unregister_ipte_notifier(struct gmap_notifier *);
@@ -852,6 +870,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_get_lock(ptep);
+		pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
 		pgste_set_key(ptep, pgste, entry);
 		pgste_set_pte(ptep, entry);
 		pgste_set_unlock(ptep, pgste);
@@ -881,6 +900,12 @@ static inline int pte_young(pte_t pte)
 	return (pte_val(pte) & _PAGE_YOUNG) != 0;
 }
 
+#define __HAVE_ARCH_PTE_UNUSED
+static inline int pte_unused(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_UNUSED;
+}
+
 /*
  * pgd/pmd/pte modification functions
  */
@@ -1034,30 +1059,41 @@ static inline int ptep_test_and_clear_user_young(struct mm_struct *mm,
 
 static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
 {
-	if (!(pte_val(*ptep) & _PAGE_INVALID)) {
+	unsigned long pto = (unsigned long) ptep;
+
 #ifndef CONFIG_64BIT
-		/* pto must point to the start of the segment table */
-		pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00);
-#else
-		/* ipte in zarch mode can do the math */
-		pte_t *pto = ptep;
+	/* pto in ESA mode must point to the start of the segment table */
+	pto &= 0x7ffffc00;
 #endif
-		asm volatile(
-			"	ipte	%2,%3"
-			: "=m" (*ptep) : "m" (*ptep),
-			  "a" (pto), "a" (address));
-	}
+	/* Invalidation + global TLB flush for the pte */
+	asm volatile(
+		"	ipte	%2,%3"
+		: "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address));
+}
+
+static inline void ptep_flush_direct(struct mm_struct *mm,
+				     unsigned long address, pte_t *ptep)
+{
+	if (pte_val(*ptep) & _PAGE_INVALID)
+		return;
+	__ptep_ipte(address, ptep);
 }
 
 static inline void ptep_flush_lazy(struct mm_struct *mm,
 				   unsigned long address, pte_t *ptep)
 {
-	int active = (mm == current->active_mm) ? 1 : 0;
+	int active, count;
 
-	if (atomic_read(&mm->context.attach_count) > active)
-		__ptep_ipte(address, ptep);
-	else
+	if (pte_val(*ptep) & _PAGE_INVALID)
+		return;
+	active = (mm == current->active_mm) ? 1 : 0;
+	count = atomic_add_return(0x10000, &mm->context.attach_count);
+	if ((count & 0xffff) <= active) {
+		pte_val(*ptep) |= _PAGE_INVALID;
 		mm->context.flush_mm = 1;
+	} else
+		__ptep_ipte(address, ptep);
+	atomic_sub(0x10000, &mm->context.attach_count);
 }
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -1074,7 +1110,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
 	}
 
 	pte = *ptep;
-	__ptep_ipte(addr, ptep);
+	ptep_flush_direct(vma->vm_mm, addr, ptep);
 	young = pte_young(pte);
 	pte = pte_mkold(pte);
 
@@ -1145,7 +1181,6 @@ static inline pte_t ptep_modify_prot_start(struct mm_struct *mm,
 
 	pte = *ptep;
 	ptep_flush_lazy(mm, address, ptep);
-	pte_val(*ptep) |= _PAGE_INVALID;
 
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_update_all(&pte, pgste);
@@ -1182,10 +1217,13 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
 	}
 
 	pte = *ptep;
-	__ptep_ipte(address, ptep);
+	ptep_flush_direct(vma->vm_mm, address, ptep);
 	pte_val(*ptep) = _PAGE_INVALID;
 
 	if (mm_has_pgste(vma->vm_mm)) {
+		if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) ==
+		    _PGSTE_GPS_USAGE_UNUSED)
+			pte_val(pte) |= _PAGE_UNUSED;
 		pgste = pgste_update_all(&pte, pgste);
 		pgste_set_unlock(ptep, pgste);
 	}
@@ -1263,7 +1301,7 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
 		pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
 	}
 
-	__ptep_ipte(address, ptep);
+	ptep_flush_direct(vma->vm_mm, address, ptep);
 
 	if (mm_has_pgste(vma->vm_mm)) {
 		pgste_set_pte(ptep, entry);
@@ -1447,12 +1485,16 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
 static inline void pmdp_flush_lazy(struct mm_struct *mm,
 				   unsigned long address, pmd_t *pmdp)
 {
-	int active = (mm == current->active_mm) ? 1 : 0;
+	int active, count;
 
-	if ((atomic_read(&mm->context.attach_count) & 0xffff) > active)
-		__pmd_idte(address, pmdp);
-	else
+	active = (mm == current->active_mm) ? 1 : 0;
+	count = atomic_add_return(0x10000, &mm->context.attach_count);
+	if ((count & 0xffff) <= active) {
+		pmd_val(*pmdp) |= _SEGMENT_ENTRY_INVALID;
 		mm->context.flush_mm = 1;
+	} else
+		__pmd_idte(address, pmdp);
+	atomic_sub(0x10000, &mm->context.attach_count);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 0a876bc543d3..dc5fc4f90e52 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -79,6 +79,7 @@ struct thread_struct {
         unsigned long ksp;              /* kernel stack pointer             */
 	mm_segment_t mm_segment;
 	unsigned long gmap_addr;	/* address of last gmap fault. */
+	unsigned int gmap_pfault;	/* signal of a pending guest pfault */
 	struct per_regs per_user;	/* User specified PER registers */
 	struct per_event per_event;	/* Cause of the last PER trap */
 	unsigned long per_flags;	/* Flags to control debug behavior */
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 94cfbe442f12..406f3a1e63ef 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -59,7 +59,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_FLAG_DIAG44	(1UL << 4)
 #define MACHINE_FLAG_IDTE	(1UL << 5)
 #define MACHINE_FLAG_DIAG9C	(1UL << 6)
-#define MACHINE_FLAG_MVCOS	(1UL << 7)
 #define MACHINE_FLAG_KVM	(1UL << 8)
 #define MACHINE_FLAG_ESOP	(1UL << 9)
 #define MACHINE_FLAG_EDAT1	(1UL << 10)
@@ -85,7 +84,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_HAS_IDTE	(0)
 #define MACHINE_HAS_DIAG44	(1)
 #define MACHINE_HAS_MVPG	(S390_lowcore.machine_flags & MACHINE_FLAG_MVPG)
-#define MACHINE_HAS_MVCOS	(0)
 #define MACHINE_HAS_EDAT1	(0)
 #define MACHINE_HAS_EDAT2	(0)
 #define MACHINE_HAS_LPP		(0)
@@ -98,7 +96,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_HAS_IDTE	(S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)
 #define MACHINE_HAS_DIAG44	(S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
 #define MACHINE_HAS_MVPG	(1)
-#define MACHINE_HAS_MVCOS	(S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
 #define MACHINE_HAS_EDAT1	(S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
 #define MACHINE_HAS_EDAT2	(S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
 #define MACHINE_HAS_LPP		(S390_lowcore.machine_flags & MACHINE_FLAG_LPP)
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 10e0fcd3633d..d2e53d667a92 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -81,6 +81,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_TLB_WAIT		4	/* wait for TLB flush completion */
 #define TIF_PER_TRAP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
@@ -96,6 +97,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_TLB_WAIT		(1<<TIF_TLB_WAIT)
 #define _TIF_PER_TRAP		(1<<TIF_PER_TRAP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 79330af9a5f8..4133b3f72fb0 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -92,33 +92,58 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x)
 #define ARCH_HAS_SORT_EXTABLE
 #define ARCH_HAS_SEARCH_EXTABLE
 
-struct uaccess_ops {
-	size_t (*copy_from_user)(size_t, const void __user *, void *);
-	size_t (*copy_to_user)(size_t, void __user *, const void *);
-	size_t (*copy_in_user)(size_t, void __user *, const void __user *);
-	size_t (*clear_user)(size_t, void __user *);
-	size_t (*strnlen_user)(size_t, const char __user *);
-	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
-};
+int __handle_fault(unsigned long, unsigned long, int);
 
-extern struct uaccess_ops uaccess;
-extern struct uaccess_ops uaccess_mvcos;
-extern struct uaccess_ops uaccess_pt;
+/**
+ * __copy_from_user: - Copy a block of data from user space, with less checking.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:	  Number of bytes to copy.
+ *
+ * Context: User context only.	This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+unsigned long __must_check __copy_from_user(void *to, const void __user *from,
+					    unsigned long n);
+
+/**
+ * __copy_to_user: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:	  Number of bytes to copy.
+ *
+ * Context: User context only.	This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long __must_check __copy_to_user(void __user *to, const void *from,
+					  unsigned long n);
 
-extern int __handle_fault(unsigned long, unsigned long, int);
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
-static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
+static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 {
-	size = uaccess.copy_to_user(size, ptr, x);
-	return size ? -EFAULT : size;
+	size = __copy_to_user(ptr, x, size);
+	return size ? -EFAULT : 0;
 }
 
-static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
+static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 {
-	size = uaccess.copy_from_user(size, ptr, x);
-	return size ? -EFAULT : size;
+	size = __copy_from_user(x, ptr, size);
+	return size ? -EFAULT : 0;
 }
 
 /*
@@ -135,8 +160,8 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 	case 2:							\
 	case 4:							\
 	case 8:							\
-		__pu_err = __put_user_fn(sizeof (*(ptr)),	\
-					 ptr, &__x);		\
+		__pu_err = __put_user_fn(&__x, ptr,		\
+					 sizeof(*(ptr)));	\
 		break;						\
 	default:						\
 		__put_user_bad();				\
@@ -152,7 +177,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 })
 
 
-extern int __put_user_bad(void) __attribute__((noreturn));
+int __put_user_bad(void) __attribute__((noreturn));
 
 #define __get_user(x, ptr)					\
 ({								\
@@ -161,29 +186,29 @@ extern int __put_user_bad(void) __attribute__((noreturn));
 	switch (sizeof(*(ptr))) {				\
 	case 1: {						\
 		unsigned char __x;				\
-		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
-					 ptr, &__x);		\
+		__gu_err = __get_user_fn(&__x, ptr,		\
+					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 2: {						\
 		unsigned short __x;				\
-		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
-					 ptr, &__x);		\
+		__gu_err = __get_user_fn(&__x, ptr,		\
+					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 4: {						\
 		unsigned int __x;				\
-		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
-					 ptr, &__x);		\
+		__gu_err = __get_user_fn(&__x, ptr,		\
+					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 8: {						\
 		unsigned long long __x;				\
-		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
-					 ptr, &__x);		\
+		__gu_err = __get_user_fn(&__x, ptr,		\
+					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
@@ -200,35 +225,12 @@ extern int __put_user_bad(void) __attribute__((noreturn));
 	__get_user(x, ptr);					\
 })
 
-extern int __get_user_bad(void) __attribute__((noreturn));
+int __get_user_bad(void) __attribute__((noreturn));
 
 #define __put_user_unaligned __put_user
 #define __get_user_unaligned __get_user
 
 /**
- * __copy_to_user: - Copy a block of data into user space, with less checking.
- * @to:   Destination address, in user space.
- * @from: Source address, in kernel space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from kernel space to user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-static inline unsigned long __must_check
-__copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-	return uaccess.copy_to_user(n, to, from);
-}
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-/**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
  * @from: Source address, in kernel space.
@@ -248,30 +250,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
 	return __copy_to_user(to, from, n);
 }
 
-/**
- * __copy_from_user: - Copy a block of data from user space, with less checking.
- * @to:   Destination address, in kernel space.
- * @from: Source address, in user space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from user space to kernel space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- *
- * If some data could not be copied, this function will pad the copied
- * data to the requested size using zero bytes.
- */
-static inline unsigned long __must_check
-__copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-	return uaccess.copy_from_user(n, from, to);
-}
-
-extern void copy_from_user_overflow(void)
+void copy_from_user_overflow(void)
 #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
 __compiletime_warning("copy_from_user() buffer size is not provably correct")
 #endif
@@ -306,11 +285,8 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
 	return __copy_from_user(to, from, n);
 }
 
-static inline unsigned long __must_check
-__copy_in_user(void __user *to, const void __user *from, unsigned long n)
-{
-	return uaccess.copy_in_user(n, to, from);
-}
+unsigned long __must_check
+__copy_in_user(void __user *to, const void __user *from, unsigned long n);
 
 static inline unsigned long __must_check
 copy_in_user(void __user *to, const void __user *from, unsigned long n)
@@ -322,18 +298,22 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n)
 /*
  * Copy a null terminated string from userspace.
  */
+
+long __strncpy_from_user(char *dst, const char __user *src, long count);
+
 static inline long __must_check
 strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	might_fault();
-	return uaccess.strncpy_from_user(count, src, dst);
+	return __strncpy_from_user(dst, src, count);
 }
 
-static inline unsigned long
-strnlen_user(const char __user * src, unsigned long n)
+unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
+
+static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
 {
 	might_fault();
-	return uaccess.strnlen_user(n, src);
+	return __strnlen_user(src, n);
 }
 
 /**
@@ -355,21 +335,14 @@ strnlen_user(const char __user * src, unsigned long n)
 /*
  * Zero Userspace
  */
+unsigned long __must_check __clear_user(void __user *to, unsigned long size);
 
-static inline unsigned long __must_check
-__clear_user(void __user *to, unsigned long n)
-{
-	return uaccess.clear_user(n, to);
-}
-
-static inline unsigned long __must_check
-clear_user(void __user *to, unsigned long n)
+static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 {
 	might_fault();
-	return uaccess.clear_user(n, to);
+	return __clear_user(to, n);
 }
 
-extern int copy_to_user_real(void __user *dest, void *src, size_t count);
-extern int copy_from_user_real(void *dest, void __user *src, size_t count);
+int copy_to_user_real(void __user *dest, void *src, unsigned long count);
 
 #endif /* __S390_UACCESS_H */
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index d25da598ec62..cb4c1eb8a0a5 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -16,6 +16,22 @@
 
 #define __KVM_S390
 
+/* Device control API: s390-specific devices */
+#define KVM_DEV_FLIC_GET_ALL_IRQS	1
+#define KVM_DEV_FLIC_ENQUEUE		2
+#define KVM_DEV_FLIC_CLEAR_IRQS		3
+#define KVM_DEV_FLIC_APF_ENABLE		4
+#define KVM_DEV_FLIC_APF_DISABLE_WAIT	5
+/*
+ * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
+ * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
+ * There are also sclp and machine checks. This gives us
+ * sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000
+ * Lets round up to 8192 pages.
+ */
+#define KVM_S390_MAX_FLOAT_IRQS	266250
+#define KVM_S390_FLIC_MAX_BUFFER	0x2000000
+
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
 	/* general purpose regs for s390 */
@@ -57,4 +73,7 @@ struct kvm_sync_regs {
 #define KVM_REG_S390_EPOCHDIFF	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2)
 #define KVM_REG_S390_CPU_TIMER  (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3)
 #define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_S390_PFTOKEN	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_S390_PFCOMPARE	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_S390_PFSELECT	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
 #endif
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index fca20b5fe79e..6b594439cca5 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -380,8 +380,6 @@ static __init void detect_machine_facilities(void)
 		S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;
 	if (test_facility(3))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
-	if (test_facility(27))
-		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 	if (test_facility(40))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;
 	if (test_facility(50) && test_facility(73))
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 0dc2b6d0a1ec..526d3735ed29 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -43,6 +43,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
 _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
 		 _TIF_SYSCALL_TRACEPOINT)
+_TIF_TRANSFER = (_TIF_MCCK_PENDING | _TIF_TLB_WAIT)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -159,10 +160,12 @@ ENTRY(__switch_to)
 	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
 	mvc	__LC_CURRENT_PID(4,%r0),__TASK_pid(%r3)	# store pid of next
 	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
-	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
+	lhi	%r6,_TIF_TRANSFER		# transfer TIF bits
+	n	%r6,__TI_flags(%r4)		# isolate TIF bits
 	jz	0f
-	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
-	oi	__TI_flags+3(%r5),_TIF_MCCK_PENDING	# set it in next
+	o	%r6,__TI_flags(%r5)		# set TIF bits of next
+	st	%r6,__TI_flags(%r5)
+	ni	__TI_flags+3(%r4),255-_TIF_TRANSFER # clear TIF bits of prev
 0:	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
 	br	%r14
 
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 384e609b4711..e09dbe5f2901 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -48,6 +48,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
 _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
 		 _TIF_SYSCALL_TRACEPOINT)
+_TIF_TRANSFER = (_TIF_MCCK_PENDING | _TIF_TLB_WAIT)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -189,10 +190,12 @@ ENTRY(__switch_to)
 	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
 	mvc	__LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
 	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
-	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
+	llill	%r6,_TIF_TRANSFER		# transfer TIF bits
+	ng	%r6,__TI_flags(%r4)		# isolate TIF bits
 	jz	0f
-	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
-	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next
+	og	%r6,__TI_flags(%r5)		# set TIF bits of next
+	stg	%r6,__TI_flags(%r5)
+	ni	__TI_flags+7(%r4),255-_TIF_TRANSFER # clear TIF bits of prev
 0:	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
 	br	%r14
 
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 09e2f468f48b..f70f2489fa5f 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -47,7 +47,6 @@
 #include <linux/compat.h>
 
 #include <asm/ipl.h>
-#include <asm/uaccess.h>
 #include <asm/facility.h>
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
@@ -65,12 +64,6 @@
 #include "entry.h"
 
 /*
- * User copy operations.
- */
-struct uaccess_ops uaccess;
-EXPORT_SYMBOL(uaccess);
-
-/*
  * Machine setup..
  */
 unsigned int console_mode = 0;
@@ -294,14 +287,6 @@ static int __init parse_vmalloc(char *arg)
 }
 early_param("vmalloc", parse_vmalloc);
 
-static int __init early_parse_user_mode(char *p)
-{
-	if (!p || strcmp(p, "primary") == 0)
-		return 0;
-	return 1;
-}
-early_param("user_mode", early_parse_user_mode);
-
 void *restart_stack __attribute__((__section__(".data")));
 
 static void __init setup_lowcore(void)
@@ -1009,8 +994,6 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos : uaccess_pt;
-
 	parse_early_param();
 	detect_memory_layout(memory_chunk, memory_end);
 	os_info_init();
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 70b46eacf8e1..c8bacbcd2e5b 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -23,6 +23,8 @@ config KVM
 	select ANON_INODES
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select HAVE_KVM_EVENTFD
+	select KVM_ASYNC_PF
+	select KVM_ASYNC_PF_SYNC
 	---help---
 	  Support hosting paravirtualized guest machines using the SIE
 	  virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 40b4c6470f88..a47d2c355f68 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -7,7 +7,7 @@
 # as published by the Free Software Foundation.
 
 KVM := ../../../virt/kvm
-common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o
+common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  $(KVM)/async_pf.o
 
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 8216c0e0b2e2..03a05ffb662f 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -13,10 +13,12 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <asm/pgalloc.h>
 #include <asm/virtio-ccw.h>
 #include "kvm-s390.h"
 #include "trace.h"
 #include "trace-s390.h"
+#include "gaccess.h"
 
 static int diag_release_pages(struct kvm_vcpu *vcpu)
 {
@@ -46,6 +48,87 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
+{
+	struct prs_parm {
+		u16 code;
+		u16 subcode;
+		u16 parm_len;
+		u16 parm_version;
+		u64 token_addr;
+		u64 select_mask;
+		u64 compare_mask;
+		u64 zarch;
+	};
+	struct prs_parm parm;
+	int rc;
+	u16 rx = (vcpu->arch.sie_block->ipa & 0xf0) >> 4;
+	u16 ry = (vcpu->arch.sie_block->ipa & 0x0f);
+	unsigned long hva_token = KVM_HVA_ERR_BAD;
+
+	if (vcpu->run->s.regs.gprs[rx] & 7)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+	if (copy_from_guest(vcpu, &parm, vcpu->run->s.regs.gprs[rx], sizeof(parm)))
+		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+	if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+	switch (parm.subcode) {
+	case 0: /* TOKEN */
+		if (vcpu->arch.pfault_token != KVM_S390_PFAULT_TOKEN_INVALID) {
+			/*
+			 * If the pagefault handshake is already activated,
+			 * the token must not be changed.  We have to return
+			 * decimal 8 instead, as mandated in SC24-6084.
+			 */
+			vcpu->run->s.regs.gprs[ry] = 8;
+			return 0;
+		}
+
+		if ((parm.compare_mask & parm.select_mask) != parm.compare_mask ||
+		    parm.token_addr & 7 || parm.zarch != 0x8000000000000000ULL)
+			return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+		hva_token = gfn_to_hva(vcpu->kvm, gpa_to_gfn(parm.token_addr));
+		if (kvm_is_error_hva(hva_token))
+			return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+
+		vcpu->arch.pfault_token = parm.token_addr;
+		vcpu->arch.pfault_select = parm.select_mask;
+		vcpu->arch.pfault_compare = parm.compare_mask;
+		vcpu->run->s.regs.gprs[ry] = 0;
+		rc = 0;
+		break;
+	case 1: /*
+		 * CANCEL
+		 * Specification allows to let already pending tokens survive
+		 * the cancel, therefore to reduce code complexity, we assume
+		 * all outstanding tokens are already pending.
+		 */
+		if (parm.token_addr || parm.select_mask ||
+		    parm.compare_mask || parm.zarch)
+			return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+		vcpu->run->s.regs.gprs[ry] = 0;
+		/*
+		 * If the pfault handling was not established or is already
+		 * canceled SC24-6084 requests to return decimal 4.
+		 */
+		if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
+			vcpu->run->s.regs.gprs[ry] = 4;
+		else
+			vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+
+		rc = 0;
+		break;
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+
 static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
@@ -86,9 +169,11 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 	switch (subcode) {
 	case 3:
 		vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
+		page_table_reset_pgste(current->mm, 0, TASK_SIZE);
 		break;
 	case 4:
 		vcpu->run->s390_reset_flags = 0;
+		page_table_reset_pgste(current->mm, 0, TASK_SIZE);
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -150,6 +235,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
 		return __diag_time_slice_end(vcpu);
 	case 0x9c:
 		return __diag_time_slice_end_directed(vcpu);
+	case 0x258:
+		return __diag_page_ref_service(vcpu);
 	case 0x308:
 		return __diag_ipl_functions(vcpu);
 	case 0x500:
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 5f79d2d79ca7..1848080c3f34 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -31,7 +31,7 @@ static int is_ioint(u64 type)
 	return ((type & 0xfffe0000u) != 0xfffe0000u);
 }
 
-static int psw_extint_disabled(struct kvm_vcpu *vcpu)
+int psw_extint_disabled(struct kvm_vcpu *vcpu)
 {
 	return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
 }
@@ -78,11 +78,8 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
 			return 1;
 		return 0;
 	case KVM_S390_INT_SERVICE:
-		if (psw_extint_disabled(vcpu))
-			return 0;
-		if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
-			return 1;
-		return 0;
+	case KVM_S390_INT_PFAULT_INIT:
+	case KVM_S390_INT_PFAULT_DONE:
 	case KVM_S390_INT_VIRTIO:
 		if (psw_extint_disabled(vcpu))
 			return 0;
@@ -150,6 +147,8 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
 	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 	case KVM_S390_INT_SERVICE:
+	case KVM_S390_INT_PFAULT_INIT:
+	case KVM_S390_INT_PFAULT_DONE:
 	case KVM_S390_INT_VIRTIO:
 		if (psw_extint_disabled(vcpu))
 			__set_cpuflag(vcpu, CPUSTAT_EXT_INT);
@@ -223,6 +222,30 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		rc |= put_guest(vcpu, inti->ext.ext_params,
 				(u32 __user *)__LC_EXT_PARAMS);
 		break;
+	case KVM_S390_INT_PFAULT_INIT:
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
+						 inti->ext.ext_params2);
+		rc  = put_guest(vcpu, 0x2603, (u16 __user *) __LC_EXT_INT_CODE);
+		rc |= put_guest(vcpu, 0x0600, (u16 __user *) __LC_EXT_CPU_ADDR);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
+		rc |= put_guest(vcpu, inti->ext.ext_params2,
+				(u64 __user *) __LC_EXT_PARAMS2);
+		break;
+	case KVM_S390_INT_PFAULT_DONE:
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
+						 inti->ext.ext_params2);
+		rc  = put_guest(vcpu, 0x2603, (u16 __user *) __LC_EXT_INT_CODE);
+		rc |= put_guest(vcpu, 0x0680, (u16 __user *) __LC_EXT_CPU_ADDR);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
+		rc |= put_guest(vcpu, inti->ext.ext_params2,
+				(u64 __user *) __LC_EXT_PARAMS2);
+		break;
 	case KVM_S390_INT_VIRTIO:
 		VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
 			   inti->ext.ext_params, inti->ext.ext_params2);
@@ -357,7 +380,7 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
-static int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
+int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 	struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
@@ -528,6 +551,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 			list_for_each_entry_safe(inti, n, &fi->list, list) {
 				if (__interrupt_is_deliverable(vcpu, inti)) {
 					list_del(&inti->list);
+					fi->irq_count--;
 					deliver = 1;
 					break;
 				}
@@ -583,6 +607,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
 				if ((inti->type == KVM_S390_MCHK) &&
 				    __interrupt_is_deliverable(vcpu, inti)) {
 					list_del(&inti->list);
+					fi->irq_count--;
 					deliver = 1;
 					break;
 				}
@@ -650,8 +675,10 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
 		inti = iter;
 		break;
 	}
-	if (inti)
+	if (inti) {
 		list_del_init(&inti->list);
+		fi->irq_count--;
+	}
 	if (list_empty(&fi->list))
 		atomic_set(&fi->active, 0);
 	spin_unlock(&fi->lock);
@@ -659,53 +686,98 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
 	return inti;
 }
 
-int kvm_s390_inject_vm(struct kvm *kvm,
-		       struct kvm_s390_interrupt *s390int)
+static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
 {
 	struct kvm_s390_local_interrupt *li;
 	struct kvm_s390_float_interrupt *fi;
-	struct kvm_s390_interrupt_info *inti, *iter;
+	struct kvm_s390_interrupt_info *iter;
 	int sigcpu;
+	int rc = 0;
+
+	mutex_lock(&kvm->lock);
+	fi = &kvm->arch.float_int;
+	spin_lock(&fi->lock);
+	if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) {
+		rc = -EINVAL;
+		goto unlock_fi;
+	}
+	fi->irq_count++;
+	if (!is_ioint(inti->type)) {
+		list_add_tail(&inti->list, &fi->list);
+	} else {
+		u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
+
+		/* Keep I/O interrupts sorted in isc order. */
+		list_for_each_entry(iter, &fi->list, list) {
+			if (!is_ioint(iter->type))
+				continue;
+			if (int_word_to_isc_bits(iter->io.io_int_word)
+			    <= isc_bits)
+				continue;
+			break;
+		}
+		list_add_tail(&inti->list, &iter->list);
+	}
+	atomic_set(&fi->active, 1);
+	sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
+	if (sigcpu == KVM_MAX_VCPUS) {
+		do {
+			sigcpu = fi->next_rr_cpu++;
+			if (sigcpu == KVM_MAX_VCPUS)
+				sigcpu = fi->next_rr_cpu = 0;
+		} while (fi->local_int[sigcpu] == NULL);
+	}
+	li = fi->local_int[sigcpu];
+	spin_lock_bh(&li->lock);
+	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+	if (waitqueue_active(li->wq))
+		wake_up_interruptible(li->wq);
+	spin_unlock_bh(&li->lock);
+unlock_fi:
+	spin_unlock(&fi->lock);
+	mutex_unlock(&kvm->lock);
+	return rc;
+}
+
+int kvm_s390_inject_vm(struct kvm *kvm,
+		       struct kvm_s390_interrupt *s390int)
+{
+	struct kvm_s390_interrupt_info *inti;
 
 	inti = kzalloc(sizeof(*inti), GFP_KERNEL);
 	if (!inti)
 		return -ENOMEM;
 
-	switch (s390int->type) {
+	inti->type = s390int->type;
+	switch (inti->type) {
 	case KVM_S390_INT_VIRTIO:
 		VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx",
 			 s390int->parm, s390int->parm64);
-		inti->type = s390int->type;
 		inti->ext.ext_params = s390int->parm;
 		inti->ext.ext_params2 = s390int->parm64;
 		break;
 	case KVM_S390_INT_SERVICE:
 		VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
-		inti->type = s390int->type;
 		inti->ext.ext_params = s390int->parm;
 		break;
-	case KVM_S390_PROGRAM_INT:
-	case KVM_S390_SIGP_STOP:
-	case KVM_S390_INT_EXTERNAL_CALL:
-	case KVM_S390_INT_EMERGENCY:
-		kfree(inti);
-		return -EINVAL;
+	case KVM_S390_INT_PFAULT_DONE:
+		inti->type = s390int->type;
+		inti->ext.ext_params2 = s390int->parm64;
+		break;
 	case KVM_S390_MCHK:
 		VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
 			 s390int->parm64);
-		inti->type = s390int->type;
 		inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
 		inti->mchk.mcic = s390int->parm64;
 		break;
 	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-		if (s390int->type & IOINT_AI_MASK)
+		if (inti->type & IOINT_AI_MASK)
 			VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
 		else
 			VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
 				 s390int->type & IOINT_CSSID_MASK,
 				 s390int->type & IOINT_SSID_MASK,
 				 s390int->type & IOINT_SCHID_MASK);
-		inti->type = s390int->type;
 		inti->io.subchannel_id = s390int->parm >> 16;
 		inti->io.subchannel_nr = s390int->parm & 0x0000ffffu;
 		inti->io.io_int_parm = s390int->parm64 >> 32;
@@ -718,43 +790,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
 	trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
 				 2);
 
-	mutex_lock(&kvm->lock);
-	fi = &kvm->arch.float_int;
-	spin_lock(&fi->lock);
-	if (!is_ioint(inti->type))
-		list_add_tail(&inti->list, &fi->list);
-	else {
-		u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
-
-		/* Keep I/O interrupts sorted in isc order. */
-		list_for_each_entry(iter, &fi->list, list) {
-			if (!is_ioint(iter->type))
-				continue;
-			if (int_word_to_isc_bits(iter->io.io_int_word)
-			    <= isc_bits)
-				continue;
-			break;
-		}
-		list_add_tail(&inti->list, &iter->list);
-	}
-	atomic_set(&fi->active, 1);
-	sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
-	if (sigcpu == KVM_MAX_VCPUS) {
-		do {
-			sigcpu = fi->next_rr_cpu++;
-			if (sigcpu == KVM_MAX_VCPUS)
-				sigcpu = fi->next_rr_cpu = 0;
-		} while (fi->local_int[sigcpu] == NULL);
-	}
-	li = fi->local_int[sigcpu];
-	spin_lock_bh(&li->lock);
-	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
-	if (waitqueue_active(li->wq))
-		wake_up_interruptible(li->wq);
-	spin_unlock_bh(&li->lock);
-	spin_unlock(&fi->lock);
-	mutex_unlock(&kvm->lock);
-	return 0;
+	return __inject_vm(kvm, inti);
 }
 
 int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
@@ -814,6 +850,10 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 		inti->type = s390int->type;
 		inti->mchk.mcic = s390int->parm64;
 		break;
+	case KVM_S390_INT_PFAULT_INIT:
+		inti->type = s390int->type;
+		inti->ext.ext_params2 = s390int->parm64;
+		break;
 	case KVM_S390_INT_VIRTIO:
 	case KVM_S390_INT_SERVICE:
 	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
@@ -841,3 +881,232 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 	mutex_unlock(&vcpu->kvm->lock);
 	return 0;
 }
+
+static void clear_floating_interrupts(struct kvm *kvm)
+{
+	struct kvm_s390_float_interrupt *fi;
+	struct kvm_s390_interrupt_info	*n, *inti = NULL;
+
+	mutex_lock(&kvm->lock);
+	fi = &kvm->arch.float_int;
+	spin_lock(&fi->lock);
+	list_for_each_entry_safe(inti, n, &fi->list, list) {
+		list_del(&inti->list);
+		kfree(inti);
+	}
+	fi->irq_count = 0;
+	atomic_set(&fi->active, 0);
+	spin_unlock(&fi->lock);
+	mutex_unlock(&kvm->lock);
+}
+
+static inline int copy_irq_to_user(struct kvm_s390_interrupt_info *inti,
+				   u8 *addr)
+{
+	struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
+	struct kvm_s390_irq irq = {0};
+
+	irq.type = inti->type;
+	switch (inti->type) {
+	case KVM_S390_INT_PFAULT_INIT:
+	case KVM_S390_INT_PFAULT_DONE:
+	case KVM_S390_INT_VIRTIO:
+	case KVM_S390_INT_SERVICE:
+		irq.u.ext = inti->ext;
+		break;
+	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+		irq.u.io = inti->io;
+		break;
+	case KVM_S390_MCHK:
+		irq.u.mchk = inti->mchk;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (copy_to_user(uptr, &irq, sizeof(irq)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int get_all_floating_irqs(struct kvm *kvm, __u8 *buf, __u64 len)
+{
+	struct kvm_s390_interrupt_info *inti;
+	struct kvm_s390_float_interrupt *fi;
+	int ret = 0;
+	int n = 0;
+
+	mutex_lock(&kvm->lock);
+	fi = &kvm->arch.float_int;
+	spin_lock(&fi->lock);
+
+	list_for_each_entry(inti, &fi->list, list) {
+		if (len < sizeof(struct kvm_s390_irq)) {
+			/* signal userspace to try again */
+			ret = -ENOMEM;
+			break;
+		}
+		ret = copy_irq_to_user(inti, buf);
+		if (ret)
+			break;
+		buf += sizeof(struct kvm_s390_irq);
+		len -= sizeof(struct kvm_s390_irq);
+		n++;
+	}
+
+	spin_unlock(&fi->lock);
+	mutex_unlock(&kvm->lock);
+
+	return ret < 0 ? ret : n;
+}
+
+static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int r;
+
+	switch (attr->group) {
+	case KVM_DEV_FLIC_GET_ALL_IRQS:
+		r = get_all_floating_irqs(dev->kvm, (u8 *) attr->addr,
+					  attr->attr);
+		break;
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+static inline int copy_irq_from_user(struct kvm_s390_interrupt_info *inti,
+				     u64 addr)
+{
+	struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
+	void *target = NULL;
+	void __user *source;
+	u64 size;
+
+	if (get_user(inti->type, (u64 __user *)addr))
+		return -EFAULT;
+
+	switch (inti->type) {
+	case KVM_S390_INT_PFAULT_INIT:
+	case KVM_S390_INT_PFAULT_DONE:
+	case KVM_S390_INT_VIRTIO:
+	case KVM_S390_INT_SERVICE:
+		target = (void *) &inti->ext;
+		source = &uptr->u.ext;
+		size = sizeof(inti->ext);
+		break;
+	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+		target = (void *) &inti->io;
+		source = &uptr->u.io;
+		size = sizeof(inti->io);
+		break;
+	case KVM_S390_MCHK:
+		target = (void *) &inti->mchk;
+		source = &uptr->u.mchk;
+		size = sizeof(inti->mchk);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (copy_from_user(target, source, size))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int enqueue_floating_irq(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	struct kvm_s390_interrupt_info *inti = NULL;
+	int r = 0;
+	int len = attr->attr;
+
+	if (len % sizeof(struct kvm_s390_irq) != 0)
+		return -EINVAL;
+	else if (len > KVM_S390_FLIC_MAX_BUFFER)
+		return -EINVAL;
+
+	while (len >= sizeof(struct kvm_s390_irq)) {
+		inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+		if (!inti)
+			return -ENOMEM;
+
+		r = copy_irq_from_user(inti, attr->addr);
+		if (r) {
+			kfree(inti);
+			return r;
+		}
+		r = __inject_vm(dev->kvm, inti);
+		if (r) {
+			kfree(inti);
+			return r;
+		}
+		len -= sizeof(struct kvm_s390_irq);
+		attr->addr += sizeof(struct kvm_s390_irq);
+	}
+
+	return r;
+}
+
+static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int r = 0;
+	unsigned int i;
+	struct kvm_vcpu *vcpu;
+
+	switch (attr->group) {
+	case KVM_DEV_FLIC_ENQUEUE:
+		r = enqueue_floating_irq(dev, attr);
+		break;
+	case KVM_DEV_FLIC_CLEAR_IRQS:
+		r = 0;
+		clear_floating_interrupts(dev->kvm);
+		break;
+	case KVM_DEV_FLIC_APF_ENABLE:
+		dev->kvm->arch.gmap->pfault_enabled = 1;
+		break;
+	case KVM_DEV_FLIC_APF_DISABLE_WAIT:
+		dev->kvm->arch.gmap->pfault_enabled = 0;
+		/*
+		 * Make sure no async faults are in transition when
+		 * clearing the queues. So we don't need to worry
+		 * about late coming workers.
+		 */
+		synchronize_srcu(&dev->kvm->srcu);
+		kvm_for_each_vcpu(i, vcpu, dev->kvm)
+			kvm_clear_async_pf_completion_queue(vcpu);
+		break;
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+static int flic_create(struct kvm_device *dev, u32 type)
+{
+	if (!dev)
+		return -EINVAL;
+	if (dev->kvm->arch.flic)
+		return -EINVAL;
+	dev->kvm->arch.flic = dev;
+	return 0;
+}
+
+static void flic_destroy(struct kvm_device *dev)
+{
+	dev->kvm->arch.flic = NULL;
+	kfree(dev);
+}
+
+/* s390 floating irq controller (flic) */
+struct kvm_device_ops kvm_flic_ops = {
+	.name = "kvm-flic",
+	.get_attr = flic_get_attr,
+	.set_attr = flic_set_attr,
+	.create = flic_create,
+	.destroy = flic_destroy,
+};
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e0676f390d57..7679eba1ed7e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -68,6 +68,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
 	{ "instruction_stsch", VCPU_STAT(instruction_stsch) },
 	{ "instruction_chsc", VCPU_STAT(instruction_chsc) },
+	{ "instruction_essa", VCPU_STAT(instruction_essa) },
 	{ "instruction_stsi", VCPU_STAT(instruction_stsi) },
 	{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
 	{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
@@ -152,11 +153,13 @@ int kvm_dev_ioctl_check_extension(long ext)
 #ifdef CONFIG_KVM_S390_UCONTROL
 	case KVM_CAP_S390_UCONTROL:
 #endif
+	case KVM_CAP_ASYNC_PF:
 	case KVM_CAP_SYNC_REGS:
 	case KVM_CAP_ONE_REG:
 	case KVM_CAP_ENABLE_CAP:
 	case KVM_CAP_S390_CSS_SUPPORT:
 	case KVM_CAP_IOEVENTFD:
+	case KVM_CAP_DEVICE_CTRL:
 		r = 1;
 		break;
 	case KVM_CAP_NR_VCPUS:
@@ -254,6 +257,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 		if (!kvm->arch.gmap)
 			goto out_nogmap;
 		kvm->arch.gmap->private = kvm;
+		kvm->arch.gmap->pfault_enabled = 0;
 	}
 
 	kvm->arch.css_support = 0;
@@ -271,6 +275,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
 	trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
+	kvm_clear_async_pf_completion_queue(vcpu);
 	if (!kvm_is_ucontrol(vcpu->kvm)) {
 		clear_bit(63 - vcpu->vcpu_id,
 			  (unsigned long *) &vcpu->kvm->arch.sca->mcn);
@@ -283,7 +288,11 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 	if (kvm_is_ucontrol(vcpu->kvm))
 		gmap_free(vcpu->arch.gmap);
 
+	if (vcpu->arch.sie_block->cbrlo)
+		__free_page(__pfn_to_page(
+				vcpu->arch.sie_block->cbrlo >> PAGE_SHIFT));
 	free_page((unsigned long)(vcpu->arch.sie_block));
+
 	kvm_vcpu_uninit(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
@@ -320,6 +329,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+	kvm_clear_async_pf_completion_queue(vcpu);
 	if (kvm_is_ucontrol(vcpu->kvm)) {
 		vcpu->arch.gmap = gmap_alloc(current->mm);
 		if (!vcpu->arch.gmap)
@@ -380,6 +391,8 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 	vcpu->arch.guest_fpregs.fpc = 0;
 	asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
 	vcpu->arch.sie_block->gbea = 1;
+	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+	kvm_clear_async_pf_completion_queue(vcpu);
 	atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 }
 
@@ -390,6 +403,8 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
+	struct page *cbrl;
+
 	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
 						    CPUSTAT_SM |
 						    CPUSTAT_STOPPED |
@@ -401,6 +416,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	vcpu->arch.sie_block->ecb2  = 8;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
 	vcpu->arch.sie_block->fac   = (int) (long) vfacilities;
+	if (kvm_enabled_cmma()) {
+		cbrl = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (cbrl) {
+			vcpu->arch.sie_block->ecb2 |= 0x80;
+			vcpu->arch.sie_block->ecb2 &= ~0x08;
+			vcpu->arch.sie_block->cbrlo = page_to_phys(cbrl);
+		}
+	}
 	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
 		     (unsigned long) vcpu);
@@ -553,6 +576,18 @@ static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
 		r = put_user(vcpu->arch.sie_block->ckc,
 			     (u64 __user *)reg->addr);
 		break;
+	case KVM_REG_S390_PFTOKEN:
+		r = put_user(vcpu->arch.pfault_token,
+			     (u64 __user *)reg->addr);
+		break;
+	case KVM_REG_S390_PFCOMPARE:
+		r = put_user(vcpu->arch.pfault_compare,
+			     (u64 __user *)reg->addr);
+		break;
+	case KVM_REG_S390_PFSELECT:
+		r = put_user(vcpu->arch.pfault_select,
+			     (u64 __user *)reg->addr);
+		break;
 	default:
 		break;
 	}
@@ -582,6 +617,18 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
 		r = get_user(vcpu->arch.sie_block->ckc,
 			     (u64 __user *)reg->addr);
 		break;
+	case KVM_REG_S390_PFTOKEN:
+		r = get_user(vcpu->arch.pfault_token,
+			     (u64 __user *)reg->addr);
+		break;
+	case KVM_REG_S390_PFCOMPARE:
+		r = get_user(vcpu->arch.pfault_compare,
+			     (u64 __user *)reg->addr);
+		break;
+	case KVM_REG_S390_PFSELECT:
+		r = get_user(vcpu->arch.pfault_select,
+			     (u64 __user *)reg->addr);
+		break;
 	default:
 		break;
 	}
@@ -700,10 +747,100 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+static long kvm_arch_fault_in_sync(struct kvm_vcpu *vcpu)
+{
+	long rc;
+	hva_t fault = gmap_fault(current->thread.gmap_addr, vcpu->arch.gmap);
+	struct mm_struct *mm = current->mm;
+	down_read(&mm->mmap_sem);
+	rc = get_user_pages(current, mm, fault, 1, 1, 0, NULL, NULL);
+	up_read(&mm->mmap_sem);
+	return rc;
+}
+
+static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,
+				      unsigned long token)
+{
+	struct kvm_s390_interrupt inti;
+	inti.parm64 = token;
+
+	if (start_token) {
+		inti.type = KVM_S390_INT_PFAULT_INIT;
+		WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &inti));
+	} else {
+		inti.type = KVM_S390_INT_PFAULT_DONE;
+		WARN_ON_ONCE(kvm_s390_inject_vm(vcpu->kvm, &inti));
+	}
+}
+
+void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
+				     struct kvm_async_pf *work)
+{
+	trace_kvm_s390_pfault_init(vcpu, work->arch.pfault_token);
+	__kvm_inject_pfault_token(vcpu, true, work->arch.pfault_token);
+}
+
+void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
+				 struct kvm_async_pf *work)
+{
+	trace_kvm_s390_pfault_done(vcpu, work->arch.pfault_token);
+	__kvm_inject_pfault_token(vcpu, false, work->arch.pfault_token);
+}
+
+void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
+			       struct kvm_async_pf *work)
+{
+	/* s390 will always inject the page directly */
+}
+
+bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * s390 will always inject the page directly,
+	 * but we still want check_async_completion to cleanup
+	 */
+	return true;
+}
+
+static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
+{
+	hva_t hva;
+	struct kvm_arch_async_pf arch;
+	int rc;
+
+	if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
+		return 0;
+	if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) !=
+	    vcpu->arch.pfault_compare)
+		return 0;
+	if (psw_extint_disabled(vcpu))
+		return 0;
+	if (kvm_cpu_has_interrupt(vcpu))
+		return 0;
+	if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul))
+		return 0;
+	if (!vcpu->arch.gmap->pfault_enabled)
+		return 0;
+
+	hva = gmap_fault(current->thread.gmap_addr, vcpu->arch.gmap);
+	if (copy_from_guest(vcpu, &arch.pfault_token, vcpu->arch.pfault_token, 8))
+		return 0;
+
+	rc = kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch);
+	return rc;
+}
+
 static int vcpu_pre_run(struct kvm_vcpu *vcpu)
 {
 	int rc, cpuflags;
 
+	/*
+	 * On s390 notifications for arriving pages will be delivered directly
+	 * to the guest but the house keeping for completed pfaults is
+	 * handled outside the worker.
+	 */
+	kvm_check_async_pf_completion(vcpu);
+
 	memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
 
 	if (need_resched())
@@ -729,7 +866,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
 
 static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
 {
-	int rc;
+	int rc = -1;
 
 	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
 		   vcpu->arch.sie_block->icptcode);
@@ -743,7 +880,16 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
 						current->thread.gmap_addr;
 		vcpu->run->s390_ucontrol.pgm_code = 0x10;
 		rc = -EREMOTE;
-	} else {
+
+	} else if (current->thread.gmap_pfault) {
+		trace_kvm_s390_major_guest_pfault(vcpu);
+		current->thread.gmap_pfault = 0;
+		if (kvm_arch_setup_async_pf(vcpu) ||
+		    (kvm_arch_fault_in_sync(vcpu) >= 0))
+			rc = 0;
+	}
+
+	if (rc == -1) {
 		VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
 		trace_kvm_s390_sie_fault(vcpu);
 		rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
@@ -761,6 +907,16 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
 	return rc;
 }
 
+bool kvm_enabled_cmma(void)
+{
+	if (!MACHINE_IS_LPAR)
+		return false;
+	/* only enable for z10 and later */
+	if (!MACHINE_HAS_EDAT1)
+		return false;
+	return true;
+}
+
 static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
 	int rc, exit_reason;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index f9559b0bd620..b6204f643652 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -156,7 +156,13 @@ void s390_vcpu_block(struct kvm_vcpu *vcpu);
 void s390_vcpu_unblock(struct kvm_vcpu *vcpu);
 void exit_sie(struct kvm_vcpu *vcpu);
 void exit_sie_sync(struct kvm_vcpu *vcpu);
+/* are we going to support cmma? */
+bool kvm_enabled_cmma(void);
 /* implemented in diag.c */
 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
 
+/* implemented in interrupt.c */
+int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
+int psw_extint_disabled(struct kvm_vcpu *vcpu);
+
 #endif
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 75beea632a10..aacb6b129914 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -636,8 +636,49 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+static int handle_essa(struct kvm_vcpu *vcpu)
+{
+	/* entries expected to be 1FF */
+	int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
+	unsigned long *cbrlo, cbrle;
+	struct gmap *gmap;
+	int i;
+
+	VCPU_EVENT(vcpu, 5, "cmma release %d pages", entries);
+	gmap = vcpu->arch.gmap;
+	vcpu->stat.instruction_essa++;
+	if (!kvm_enabled_cmma() || !vcpu->arch.sie_block->cbrlo)
+		return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
+
+	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+	if (((vcpu->arch.sie_block->ipb & 0xf0000000) >> 28) > 6)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+	/* Rewind PSW to repeat the ESSA instruction */
+	vcpu->arch.sie_block->gpsw.addr =
+		__rewind_psw(vcpu->arch.sie_block->gpsw, 4);
+	vcpu->arch.sie_block->cbrlo &= PAGE_MASK;	/* reset nceo */
+	cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
+	down_read(&gmap->mm->mmap_sem);
+	for (i = 0; i < entries; ++i) {
+		cbrle = cbrlo[i];
+		if (unlikely(cbrle & ~PAGE_MASK || cbrle < 2 * PAGE_SIZE))
+			/* invalid entry */
+			break;
+		/* try to free backing */
+		__gmap_zap(cbrle, gmap);
+	}
+	up_read(&gmap->mm->mmap_sem);
+	if (i < entries)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+	return 0;
+}
+
 static const intercept_handler_t b9_handlers[256] = {
 	[0x8d] = handle_epsw,
+	[0xab] = handle_essa,
 	[0xaf] = handle_pfmf,
 };
 
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 87c2b3a3bd3e..fe9442d39f0e 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -224,6 +224,8 @@ unlock:
 static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
 {
 	int rc;
+	unsigned int i;
+	struct kvm_vcpu *v;
 
 	switch (parameter & 0xff) {
 	case 0:
@@ -231,6 +233,11 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
 		break;
 	case 1:
 	case 2:
+		kvm_for_each_vcpu(i, v, vcpu->kvm) {
+			v->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+			kvm_clear_async_pf_completion_queue(v);
+		}
+
 		rc = SIGP_CC_ORDER_CODE_ACCEPTED;
 		break;
 	default:
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index 3db76b2daed7..e8e7213d4cc5 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -30,6 +30,52 @@
 	TP_printk("%02d[%016lx-%016lx]: " p_str, __entry->id,		\
 		  __entry->pswmask, __entry->pswaddr, p_args)
 
+TRACE_EVENT(kvm_s390_major_guest_pfault,
+	    TP_PROTO(VCPU_PROTO_COMMON),
+	    TP_ARGS(VCPU_ARGS_COMMON),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    ),
+	    VCPU_TP_PRINTK("%s", "major fault, maybe applicable for pfault")
+	);
+
+TRACE_EVENT(kvm_s390_pfault_init,
+	    TP_PROTO(VCPU_PROTO_COMMON, long pfault_token),
+	    TP_ARGS(VCPU_ARGS_COMMON, pfault_token),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(long, pfault_token)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->pfault_token = pfault_token;
+		    ),
+	    VCPU_TP_PRINTK("init pfault token %ld", __entry->pfault_token)
+	);
+
+TRACE_EVENT(kvm_s390_pfault_done,
+	    TP_PROTO(VCPU_PROTO_COMMON, long pfault_token),
+	    TP_ARGS(VCPU_ARGS_COMMON, pfault_token),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(long, pfault_token)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->pfault_token = pfault_token;
+		    ),
+	    VCPU_TP_PRINTK("done pfault token %ld", __entry->pfault_token)
+	);
+
 /*
  * Tracepoints for SIE entry and exit.
  */
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index b068729e50ac..e3fffe1dff51 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,8 +2,7 @@
 # Makefile for s390-specific library files..
 #
 
-lib-y += delay.o string.o uaccess_pt.o find.o
+lib-y += delay.o string.o uaccess_pt.o uaccess_mvcos.o find.o
 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
 obj-$(CONFIG_64BIT) += mem64.o
-lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/find.c b/arch/s390/lib/find.c
index 620d34d6487e..922003c1b90d 100644
--- a/arch/s390/lib/find.c
+++ b/arch/s390/lib/find.c
@@ -4,7 +4,7 @@
  * On s390x the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  *
  * The reason for this bit numbering is the fact that the hardware sets bits
  * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index b1a22173d027..c7e0e81f4b4e 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -6,7 +6,11 @@
 #ifndef __ARCH_S390_LIB_UACCESS_H
 #define __ARCH_S390_LIB_UACCESS_H
 
-extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
+unsigned long copy_from_user_pt(void *to, const void __user *from, unsigned long n);
+unsigned long copy_to_user_pt(void __user *to, const void *from, unsigned long n);
+unsigned long copy_in_user_pt(void __user *to, const void __user *from, unsigned long n);
+unsigned long clear_user_pt(void __user *to, unsigned long n);
+unsigned long strnlen_user_pt(const char __user *src, unsigned long count);
+long strncpy_from_user_pt(char *dst, const char __user *src, long count);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 4b7993bf69b9..ae97b8df11aa 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -6,8 +6,11 @@
  *		 Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
 
+#include <linux/jump_label.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/mm.h>
+#include <asm/facility.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
 #include "uaccess.h"
@@ -26,7 +29,10 @@
 #define SLR	"slgr"
 #endif
 
-static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
+static struct static_key have_mvcos = STATIC_KEY_INIT_TRUE;
+
+static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr,
+						 unsigned long size)
 {
 	register unsigned long reg0 asm("0") = 0x81UL;
 	unsigned long tmp1, tmp2;
@@ -65,7 +71,16 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
 	return size;
 }
 
-static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
+unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	if (static_key_true(&have_mvcos))
+		return copy_from_user_mvcos(to, from, n);
+	return copy_from_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_from_user);
+
+static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
+					       unsigned long size)
 {
 	register unsigned long reg0 asm("0") = 0x810000UL;
 	unsigned long tmp1, tmp2;
@@ -94,8 +109,16 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
 	return size;
 }
 
-static size_t copy_in_user_mvcos(size_t size, void __user *to,
-				 const void __user *from)
+unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	if (static_key_true(&have_mvcos))
+		return copy_to_user_mvcos(to, from, n);
+	return copy_to_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_to_user);
+
+static inline unsigned long copy_in_user_mvcos(void __user *to, const void __user *from,
+					       unsigned long size)
 {
 	register unsigned long reg0 asm("0") = 0x810081UL;
 	unsigned long tmp1, tmp2;
@@ -117,7 +140,15 @@ static size_t copy_in_user_mvcos(size_t size, void __user *to,
 	return size;
 }
 
-static size_t clear_user_mvcos(size_t size, void __user *to)
+unsigned long __copy_in_user(void __user *to, const void __user *from, unsigned long n)
+{
+	if (static_key_true(&have_mvcos))
+		return copy_in_user_mvcos(to, from, n);
+	return copy_in_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_in_user);
+
+static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size)
 {
 	register unsigned long reg0 asm("0") = 0x810000UL;
 	unsigned long tmp1, tmp2;
@@ -145,17 +176,26 @@ static size_t clear_user_mvcos(size_t size, void __user *to)
 	return size;
 }
 
-static size_t strnlen_user_mvcos(size_t count, const char __user *src)
+unsigned long __clear_user(void __user *to, unsigned long size)
 {
-	size_t done, len, offset, len_str;
+	if (static_key_true(&have_mvcos))
+		return clear_user_mvcos(to, size);
+	return clear_user_pt(to, size);
+}
+EXPORT_SYMBOL(__clear_user);
+
+static inline unsigned long strnlen_user_mvcos(const char __user *src,
+					       unsigned long count)
+{
+	unsigned long done, len, offset, len_str;
 	char buf[256];
 
 	done = 0;
 	do {
-		offset = (size_t)src & ~PAGE_MASK;
+		offset = (unsigned long)src & ~PAGE_MASK;
 		len = min(256UL, PAGE_SIZE - offset);
 		len = min(count - done, len);
-		if (copy_from_user_mvcos(len, src, buf))
+		if (copy_from_user_mvcos(buf, src, len))
 			return 0;
 		len_str = strnlen(buf, len);
 		done += len_str;
@@ -164,18 +204,26 @@ static size_t strnlen_user_mvcos(size_t count, const char __user *src)
 	return done + 1;
 }
 
-static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
-				      char *dst)
+unsigned long __strnlen_user(const char __user *src, unsigned long count)
 {
-	size_t done, len, offset, len_str;
+	if (static_key_true(&have_mvcos))
+		return strnlen_user_mvcos(src, count);
+	return strnlen_user_pt(src, count);
+}
+EXPORT_SYMBOL(__strnlen_user);
 
-	if (unlikely(!count))
+static inline long strncpy_from_user_mvcos(char *dst, const char __user *src,
+					   long count)
+{
+	unsigned long done, len, offset, len_str;
+
+	if (unlikely(count <= 0))
 		return 0;
 	done = 0;
 	do {
-		offset = (size_t)src & ~PAGE_MASK;
+		offset = (unsigned long)src & ~PAGE_MASK;
 		len = min(count - done, PAGE_SIZE - offset);
-		if (copy_from_user_mvcos(len, src, dst))
+		if (copy_from_user_mvcos(dst, src, len))
 			return -EFAULT;
 		len_str = strnlen(dst, len);
 		done += len_str;
@@ -185,13 +233,31 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
 	return done;
 }
 
-struct uaccess_ops uaccess_mvcos = {
-	.copy_from_user = copy_from_user_mvcos,
-	.copy_to_user = copy_to_user_mvcos,
-	.copy_in_user = copy_in_user_mvcos,
-	.clear_user = clear_user_mvcos,
-	.strnlen_user = strnlen_user_mvcos,
-	.strncpy_from_user = strncpy_from_user_mvcos,
-	.futex_atomic_op = futex_atomic_op_pt,
-	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
-};
+long __strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	if (static_key_true(&have_mvcos))
+		return strncpy_from_user_mvcos(dst, src, count);
+	return strncpy_from_user_pt(dst, src, count);
+}
+EXPORT_SYMBOL(__strncpy_from_user);
+
+/*
+ * The uaccess page tabe walk variant can be enforced with the "uaccesspt"
+ * kernel parameter. This is mainly for debugging purposes.
+ */
+static int force_uaccess_pt __initdata;
+
+static int __init parse_uaccess_pt(char *__unused)
+{
+	force_uaccess_pt = 1;
+	return 0;
+}
+early_param("uaccesspt", parse_uaccess_pt);
+
+static int __init uaccess_init(void)
+{
+	if (IS_ENABLED(CONFIG_32BIT) || force_uaccess_pt || !test_facility(27))
+		static_key_slow_dec(&have_mvcos);
+	return 0;
+}
+early_initcall(uaccess_init);
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 61ebcc9ccb34..8d39760bae68 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -22,7 +22,7 @@
 #define SLR	"slgr"
 #endif
 
-static size_t strnlen_kernel(size_t count, const char __user *src)
+static unsigned long strnlen_kernel(const char __user *src, unsigned long count)
 {
 	register unsigned long reg0 asm("0") = 0UL;
 	unsigned long tmp1, tmp2;
@@ -42,8 +42,8 @@ static size_t strnlen_kernel(size_t count, const char __user *src)
 	return count;
 }
 
-static size_t copy_in_kernel(size_t count, void __user *to,
-			     const void __user *from)
+static unsigned long copy_in_kernel(void __user *to, const void __user *from,
+				    unsigned long count)
 {
 	unsigned long tmp1;
 
@@ -146,8 +146,8 @@ static unsigned long follow_table(struct mm_struct *mm,
 
 #endif /* CONFIG_64BIT */
 
-static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
-					     size_t n, int write_user)
+static inline unsigned long __user_copy_pt(unsigned long uaddr, void *kptr,
+					   unsigned long n, int write_user)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long offset, done, size, kaddr;
@@ -189,8 +189,7 @@ fault:
  * Do DAT for user address by page table walk, return kernel address.
  * This function needs to be called with current->mm->page_table_lock held.
  */
-static __always_inline unsigned long __dat_user_addr(unsigned long uaddr,
-						     int write)
+static inline unsigned long __dat_user_addr(unsigned long uaddr, int write)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long kaddr;
@@ -211,29 +210,29 @@ fault:
 	return 0;
 }
 
-static size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
+unsigned long copy_from_user_pt(void *to, const void __user *from, unsigned long n)
 {
-	size_t rc;
+	unsigned long rc;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return copy_in_kernel(n, (void __user *) to, from);
+		return copy_in_kernel((void __user *) to, from, n);
 	rc = __user_copy_pt((unsigned long) from, to, n, 0);
 	if (unlikely(rc))
 		memset(to + n - rc, 0, rc);
 	return rc;
 }
 
-static size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
+unsigned long copy_to_user_pt(void __user *to, const void *from, unsigned long n)
 {
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return copy_in_kernel(n, to, (void __user *) from);
+		return copy_in_kernel(to, (void __user *) from, n);
 	return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
 }
 
-static size_t clear_user_pt(size_t n, void __user *to)
+unsigned long clear_user_pt(void __user *to, unsigned long n)
 {
 	void *zpage = (void *) empty_zero_page;
-	long done, size, ret;
+	unsigned long done, size, ret;
 
 	done = 0;
 	do {
@@ -242,7 +241,7 @@ static size_t clear_user_pt(size_t n, void __user *to)
 		else
 			size = n - done;
 		if (segment_eq(get_fs(), KERNEL_DS))
-			ret = copy_in_kernel(n, to, (void __user *) zpage);
+			ret = copy_in_kernel(to, (void __user *) zpage, n);
 		else
 			ret = __user_copy_pt((unsigned long) to, zpage, size, 1);
 		done += size;
@@ -253,17 +252,17 @@ static size_t clear_user_pt(size_t n, void __user *to)
 	return 0;
 }
 
-static size_t strnlen_user_pt(size_t count, const char __user *src)
+unsigned long strnlen_user_pt(const char __user *src, unsigned long count)
 {
 	unsigned long uaddr = (unsigned long) src;
 	struct mm_struct *mm = current->mm;
 	unsigned long offset, done, len, kaddr;
-	size_t len_str;
+	unsigned long len_str;
 
 	if (unlikely(!count))
 		return 0;
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return strnlen_kernel(count, src);
+		return strnlen_kernel(src, count);
 	if (!mm)
 		return 0;
 	done = 0;
@@ -289,19 +288,18 @@ fault:
 	goto retry;
 }
 
-static size_t strncpy_from_user_pt(size_t count, const char __user *src,
-				   char *dst)
+long strncpy_from_user_pt(char *dst, const char __user *src, long count)
 {
-	size_t done, len, offset, len_str;
+	unsigned long done, len, offset, len_str;
 
-	if (unlikely(!count))
+	if (unlikely(count <= 0))
 		return 0;
 	done = 0;
 	do {
-		offset = (size_t)src & ~PAGE_MASK;
+		offset = (unsigned long)src & ~PAGE_MASK;
 		len = min(count - done, PAGE_SIZE - offset);
 		if (segment_eq(get_fs(), KERNEL_DS)) {
-			if (copy_in_kernel(len, (void __user *) dst, src))
+			if (copy_in_kernel((void __user *) dst, src, len))
 				return -EFAULT;
 		} else {
 			if (__user_copy_pt((unsigned long) src, dst, len, 0))
@@ -315,8 +313,8 @@ static size_t strncpy_from_user_pt(size_t count, const char __user *src,
 	return done;
 }
 
-static size_t copy_in_user_pt(size_t n, void __user *to,
-			      const void __user *from)
+unsigned long copy_in_user_pt(void __user *to, const void __user *from,
+			      unsigned long n)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long offset_max, uaddr, done, size, error_code;
@@ -326,7 +324,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
 	int write_user;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return copy_in_kernel(n, to, from);
+		return copy_in_kernel(to, from, n);
 	if (!mm)
 		return n;
 	done = 0;
@@ -411,7 +409,7 @@ static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
+int __futex_atomic_op_inuser(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -449,8 +447,8 @@ static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
-			    u32 oldval, u32 newval)
+int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+				  u32 oldval, u32 newval)
 {
 	int ret;
 
@@ -471,14 +469,3 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
-
-struct uaccess_ops uaccess_pt = {
-	.copy_from_user		= copy_from_user_pt,
-	.copy_to_user		= copy_to_user_pt,
-	.copy_in_user		= copy_in_user_pt,
-	.clear_user		= clear_user_pt,
-	.strnlen_user		= strnlen_user_pt,
-	.strncpy_from_user	= strncpy_from_user_pt,
-	.futex_atomic_op	= futex_atomic_op_pt,
-	.futex_atomic_cmpxchg	= futex_atomic_cmpxchg_pt,
-};
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index d95265b2719f..88cef505453b 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -50,6 +50,7 @@
 #define VM_FAULT_BADMAP		0x020000
 #define VM_FAULT_BADACCESS	0x040000
 #define VM_FAULT_SIGNAL		0x080000
+#define VM_FAULT_PFAULT		0x100000
 
 static unsigned long store_indication __read_mostly;
 
@@ -227,6 +228,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
 			return;
 		}
 	case VM_FAULT_BADCONTEXT:
+	case VM_FAULT_PFAULT:
 		do_no_context(regs);
 		break;
 	case VM_FAULT_SIGNAL:
@@ -264,6 +266,9 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
  */
 static inline int do_exception(struct pt_regs *regs, int access)
 {
+#ifdef CONFIG_PGSTE
+	struct gmap *gmap;
+#endif
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	struct vm_area_struct *vma;
@@ -304,9 +309,10 @@ static inline int do_exception(struct pt_regs *regs, int access)
 	down_read(&mm->mmap_sem);
 
 #ifdef CONFIG_PGSTE
-	if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
-		address = __gmap_fault(address,
-				     (struct gmap *) S390_lowcore.gmap);
+	gmap = (struct gmap *)
+		((current->flags & PF_VCPU) ? S390_lowcore.gmap : 0);
+	if (gmap) {
+		address = __gmap_fault(address, gmap);
 		if (address == -EFAULT) {
 			fault = VM_FAULT_BADMAP;
 			goto out_up;
@@ -315,6 +321,8 @@ static inline int do_exception(struct pt_regs *regs, int access)
 			fault = VM_FAULT_OOM;
 			goto out_up;
 		}
+		if (gmap->pfault_enabled)
+			flags |= FAULT_FLAG_RETRY_NOWAIT;
 	}
 #endif
 
@@ -371,9 +379,19 @@ retry:
 				      regs, address);
 		}
 		if (fault & VM_FAULT_RETRY) {
+#ifdef CONFIG_PGSTE
+			if (gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) {
+				/* FAULT_FLAG_RETRY_NOWAIT has been set,
+				 * mmap_sem has not been released */
+				current->thread.gmap_pfault = 1;
+				fault = VM_FAULT_PFAULT;
+				goto out_up;
+			}
+#endif
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
-			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags &= ~(FAULT_FLAG_ALLOW_RETRY |
+				   FAULT_FLAG_RETRY_NOWAIT);
 			flags |= FAULT_FLAG_TRIED;
 			down_read(&mm->mmap_sem);
 			goto retry;
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index d1e0e0c7a7e2..2a2e35416d2f 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -128,7 +128,7 @@ void memcpy_absolute(void *dest, void *src, size_t count)
 /*
  * Copy memory from kernel (real) to user (virtual)
  */
-int copy_to_user_real(void __user *dest, void *src, size_t count)
+int copy_to_user_real(void __user *dest, void *src, unsigned long count)
 {
 	int offs = 0, size, rc;
 	char *buf;
@@ -152,32 +152,6 @@ out:
 }
 
 /*
- * Copy memory from user (virtual) to kernel (real)
- */
-int copy_from_user_real(void *dest, void __user *src, size_t count)
-{
-	int offs = 0, size, rc;
-	char *buf;
-
-	buf = (char *) __get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	rc = -EFAULT;
-	while (offs < count) {
-		size = min(PAGE_SIZE, count - offs);
-		if (copy_from_user(buf, src + offs, size))
-			goto out;
-		if (memcpy_real(dest + offs, buf, size))
-			goto out;
-		offs += size;
-	}
-	rc = 0;
-out:
-	free_page((unsigned long) buf);
-	return rc;
-}
-
-/*
  * Check if physical address is within prefix or zero page
  */
 static int is_swapped(unsigned long addr)
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 3584ed9b20a1..990e93905790 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -17,6 +17,7 @@
 #include <linux/quicklist.h>
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
+#include <linux/swapops.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -504,6 +505,9 @@ static int gmap_connect_pgtable(unsigned long address, unsigned long segment,
 	if (!pmd_present(*pmd) &&
 	    __pte_alloc(mm, vma, pmd, vmaddr))
 		return -ENOMEM;
+	/* large pmds cannot yet be handled */
+	if (pmd_large(*pmd))
+		return -EFAULT;
 	/* pmd now points to a valid segment table entry. */
 	rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
 	if (!rmap)
@@ -594,6 +598,82 @@ unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
 }
 EXPORT_SYMBOL_GPL(gmap_fault);
 
+static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
+{
+	if (!non_swap_entry(entry))
+		dec_mm_counter(mm, MM_SWAPENTS);
+	else if (is_migration_entry(entry)) {
+		struct page *page = migration_entry_to_page(entry);
+
+		if (PageAnon(page))
+			dec_mm_counter(mm, MM_ANONPAGES);
+		else
+			dec_mm_counter(mm, MM_FILEPAGES);
+	}
+	free_swap_and_cache(entry);
+}
+
+/**
+ * The mm->mmap_sem lock must be held
+ */
+static void gmap_zap_unused(struct mm_struct *mm, unsigned long address)
+{
+	unsigned long ptev, pgstev;
+	spinlock_t *ptl;
+	pgste_t pgste;
+	pte_t *ptep, pte;
+
+	ptep = get_locked_pte(mm, address, &ptl);
+	if (unlikely(!ptep))
+		return;
+	pte = *ptep;
+	if (!pte_swap(pte))
+		goto out_pte;
+	/* Zap unused and logically-zero pages */
+	pgste = pgste_get_lock(ptep);
+	pgstev = pgste_val(pgste);
+	ptev = pte_val(pte);
+	if (((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED) ||
+	    ((pgstev & _PGSTE_GPS_ZERO) && (ptev & _PAGE_INVALID))) {
+		gmap_zap_swap_entry(pte_to_swp_entry(pte), mm);
+		pte_clear(mm, address, ptep);
+	}
+	pgste_set_unlock(ptep, pgste);
+out_pte:
+	pte_unmap_unlock(*ptep, ptl);
+}
+
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+void __gmap_zap(unsigned long address, struct gmap *gmap)
+{
+	unsigned long *table, *segment_ptr;
+	unsigned long segment, pgstev, ptev;
+	struct gmap_pgtable *mp;
+	struct page *page;
+
+	segment_ptr = gmap_table_walk(address, gmap);
+	if (IS_ERR(segment_ptr))
+		return;
+	segment = *segment_ptr;
+	if (segment & _SEGMENT_ENTRY_INVALID)
+		return;
+	page = pfn_to_page(segment >> PAGE_SHIFT);
+	mp = (struct gmap_pgtable *) page->index;
+	address = mp->vmaddr | (address & ~PMD_MASK);
+	/* Page table is present */
+	table = (unsigned long *)(segment & _SEGMENT_ENTRY_ORIGIN);
+	table = table + ((address >> 12) & 0xff);
+	pgstev = table[PTRS_PER_PTE];
+	ptev = table[0];
+	/* quick check, checked again with locks held */
+	if (((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED) ||
+	    ((pgstev & _PGSTE_GPS_ZERO) && (ptev & _PAGE_INVALID)))
+		gmap_zap_unused(gmap->mm, address);
+}
+EXPORT_SYMBOL_GPL(__gmap_zap);
+
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
 {
 
@@ -802,6 +882,78 @@ static inline void page_table_free_pgste(unsigned long *table)
 	__free_page(page);
 }
 
+static inline unsigned long page_table_reset_pte(struct mm_struct *mm,
+			pmd_t *pmd, unsigned long addr, unsigned long end)
+{
+	pte_t *start_pte, *pte;
+	spinlock_t *ptl;
+	pgste_t pgste;
+
+	start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+	pte = start_pte;
+	do {
+		pgste = pgste_get_lock(pte);
+		pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
+		pgste_set_unlock(pte, pgste);
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+	pte_unmap_unlock(start_pte, ptl);
+
+	return addr;
+}
+
+static inline unsigned long page_table_reset_pmd(struct mm_struct *mm,
+			pud_t *pud, unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	pmd_t *pmd;
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		if (pmd_none_or_clear_bad(pmd))
+			continue;
+		next = page_table_reset_pte(mm, pmd, addr, next);
+	} while (pmd++, addr = next, addr != end);
+
+	return addr;
+}
+
+static inline unsigned long page_table_reset_pud(struct mm_struct *mm,
+			pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	pud_t *pud;
+
+	pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		if (pud_none_or_clear_bad(pud))
+			continue;
+		next = page_table_reset_pmd(mm, pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+
+	return addr;
+}
+
+void page_table_reset_pgste(struct mm_struct *mm,
+			unsigned long start, unsigned long end)
+{
+	unsigned long addr, next;
+	pgd_t *pgd;
+
+	addr = start;
+	down_read(&mm->mmap_sem);
+	pgd = pgd_offset(mm, addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_none_or_clear_bad(pgd))
+			continue;
+		next = page_table_reset_pud(mm, pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+	up_read(&mm->mmap_sem);
+}
+EXPORT_SYMBOL(page_table_reset_pgste);
+
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
 			  unsigned long key, bool nq)
 {
@@ -1248,7 +1400,7 @@ void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
 {
 	struct list_head *lh = (struct list_head *) pgtable;
 
-	assert_spin_locked(&mm->page_table_lock);
+	assert_spin_locked(pmd_lockptr(mm, pmdp));
 
 	/* FIFO */
 	if (!pmd_huge_pte(mm, pmdp))
@@ -1264,7 +1416,7 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 	pgtable_t pgtable;
 	pte_t *ptep;
 
-	assert_spin_locked(&mm->page_table_lock);
+	assert_spin_locked(pmd_lockptr(mm, pmdp));
 
 	/* FIFO */
 	pgtable = pmd_huge_pte(mm, pmdp);
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c
index 75c69b402e05..c5c66840ac00 100644
--- a/arch/s390/pci/pci_debug.c
+++ b/arch/s390/pci/pci_debug.c
@@ -139,7 +139,7 @@ void zpci_debug_exit_device(struct zpci_dev *zdev)
 int __init zpci_debug_init(void)
 {
 	/* event trace buffer */
-	pci_debug_msg_id = debug_register("pci_msg", 16, 1, 16 * sizeof(long));
+	pci_debug_msg_id = debug_register("pci_msg", 8, 1, 8 * sizeof(long));
 	if (!pci_debug_msg_id)
 		return -EINVAL;
 	debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
index cf8a12ff733b..ab4a91393005 100644
--- a/arch/s390/pci/pci_sysfs.c
+++ b/arch/s390/pci/pci_sysfs.c
@@ -48,29 +48,27 @@ static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);
 
-static void recover_callback(struct device *dev)
+static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct zpci_dev *zdev = get_zdev(pdev);
 	int ret;
 
+	if (!device_remove_file_self(dev, attr))
+		return count;
+
 	pci_stop_and_remove_bus_device(pdev);
 	ret = zpci_disable_device(zdev);
 	if (ret)
-		return;
+		return ret;
 
 	ret = zpci_enable_device(zdev);
 	if (ret)
-		return;
+		return ret;
 
 	pci_rescan_bus(zdev->bus);
-}
-
-static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	int rc = device_schedule_callback(dev, recover_callback);
-	return rc ? rc : count;
+	return count;
 }
 static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover);
 
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 146b9d5e89f8..4630cf217b5b 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -1,10 +1,11 @@
 
 header-y +=
 
+
 generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += xor.h
-generic-y += preempt.h
-
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 6357710753d5..b2cdb203e843 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -3,7 +3,7 @@ config SUPERH
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select EXPERT
 	select CLKDEV_LOOKUP
-	select HAVE_IDE if HAS_IOPORT
+	select HAVE_IDE if HAS_IOPORT_MAP
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select ARCH_DISCARD_MEMBLOCK
@@ -147,7 +147,7 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
 	def_bool n
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool !PCI
 	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV && !SH_SHMIN && \
 		   !SH_HP6XX && !SH_SOLUTION_ENGINE
@@ -356,7 +356,6 @@ config CPU_SUBTYPE_SH7720
 	select CPU_HAS_DSP
 	select SYS_SUPPORTS_CMT
 	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_SH if USB_OHCI_HCD
 	select PINCTRL
 	help
@@ -367,7 +366,6 @@ config CPU_SUBTYPE_SH7721
 	select CPU_SH3
 	select CPU_HAS_DSP
 	select SYS_SUPPORTS_CMT
-	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_SH if USB_OHCI_HCD
 	help
 	  Select SH7721 if you have a SH3-DSP SH7721 CPU.
@@ -445,8 +443,6 @@ config CPU_SUBTYPE_SH7734
 	select CPU_SH4A
 	select CPU_SHX2
 	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select USB_ARCH_HAS_OHCI
-	select USB_ARCH_HAS_EHCI
 	select PINCTRL
 	help
 	  Select SH7734 if you have a SH4A SH7734 CPU.
@@ -456,8 +452,6 @@ config CPU_SUBTYPE_SH7757
 	select CPU_SH4A
 	select CPU_SHX2
 	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select USB_ARCH_HAS_OHCI
-	select USB_ARCH_HAS_EHCI
 	select PINCTRL
 	help
 	  Select SH7757 if you have a SH4A SH7757 CPU.
@@ -465,7 +459,6 @@ config CPU_SUBTYPE_SH7757
 config CPU_SUBTYPE_SH7763
 	bool "Support SH7763 processor"
 	select CPU_SH4A
-	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_SH if USB_OHCI_HCD
 	help
 	  Select SH7763 if you have a SH4A SH7763(R5S77631) CPU.
@@ -494,9 +487,7 @@ config CPU_SUBTYPE_SH7786
 	select CPU_HAS_PTEAEX
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
 	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_SH if USB_OHCI_HCD
-	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_SH if USB_EHCI_HCD
 	select PINCTRL
 
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index eb1cf84231a2..e331e5373b8e 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -158,7 +158,7 @@ config SH_SDK7786
 	bool "SDK7786"
 	depends on CPU_SUBTYPE_SH7786
 	select SYS_SUPPORTS_PCI
-	select NO_IOPORT if !PCI
+	select NO_IOPORT_MAP if !PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select HAVE_SRAM_POOL
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
@@ -204,7 +204,7 @@ config SH_URQUELL
 	depends on CPU_SUBTYPE_SH7786
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_SUPPORTS_PCI
-	select NO_IOPORT if !PCI
+	select NO_IOPORT_MAP if !PCI
 
 config SH_MIGOR
 	bool "Migo-R"
@@ -306,7 +306,7 @@ config SH_LBOX_RE2
 config SH_X3PROTO
 	bool "SH-X3 Prototype board"
 	depends on CPU_SUBTYPE_SHX3
-	select NO_IOPORT if !PCI
+	select NO_IOPORT_MAP if !PCI
 	select IRQ_DOMAIN
 
 config SH_MAGIC_PANEL_R2
@@ -333,7 +333,7 @@ config SH_POLARIS
 
 config SH_SH2007
 	bool "SH-2007 board"
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	depends on CPU_SUBTYPE_SH7780
 	help
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index 25c5a932f9fe..669df51a82e3 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -252,7 +252,7 @@ static struct sh_mobile_sdhi_info sdhi_info = {
 static struct resource sdhi_resources[] = {
 	[0] = {
 		.start  = 0xffe50000,
-		.end    = 0xffe501ff,
+		.end    = 0xffe500ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 0cd7198a4524..c19e47dacb31 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -8,18 +8,21 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += fcntl.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += msgbuf.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += poll.h
-generic-y += mman.h
-generic-y += msgbuf.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -34,5 +37,3 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 629db2ad7916..728c4c571f40 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -122,7 +122,7 @@ __BUILD_MEMORY_STRING(__raw_, l, u32)
 
 __BUILD_MEMORY_STRING(__raw_, q, u64)
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 
 /*
  * Slowdown I/O port space accesses for antique hardware.
@@ -218,7 +218,7 @@ __BUILD_IOPORT_STRING(w, u16)
 __BUILD_IOPORT_STRING(l, u32)
 __BUILD_IOPORT_STRING(q, u64)
 
-#else /* !CONFIG_HAS_IOPORT */
+#else /* !CONFIG_HAS_IOPORT_MAP */
 
 #include <asm/io_noioport.h>
 
diff --git a/arch/sh/include/asm/io_trapped.h b/arch/sh/include/asm/io_trapped.h
index f1251d4f0ba9..4ab94ef51071 100644
--- a/arch/sh/include/asm/io_trapped.h
+++ b/arch/sh/include/asm/io_trapped.h
@@ -36,7 +36,7 @@ __ioremap_trapped(unsigned long offset, unsigned long size)
 #define __ioremap_trapped(offset, size) NULL
 #endif
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 extern struct list_head trapped_io;
 
 static inline void __iomem *
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index eb9c20d971dd..d3324e4f372e 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -21,7 +21,7 @@ struct sh_machine_vector {
 	int (*mv_irq_demux)(int irq);
 	void (*mv_init_irq)(void);
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 	void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
 	void (*mv_ioport_unmap)(void __iomem *);
 #endif
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
index 4f97df87d7d5..4f643aa718e3 100644
--- a/arch/sh/include/asm/syscalls_32.h
+++ b/arch/sh/include/asm/syscalls_32.h
@@ -9,15 +9,9 @@
 
 struct pt_regs;
 
-asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
-			     unsigned long r6, unsigned long r7,
-			     struct pt_regs __regs);
-asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs);
-asmlinkage int sys_sh_pipe(unsigned long r4, unsigned long r5,
-			   unsigned long r6, unsigned long r7,
-			   struct pt_regs __regs);
+asmlinkage int sys_sigreturn(void);
+asmlinkage int sys_rt_sigreturn(void);
+asmlinkage int sys_sh_pipe(void);
 asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char __user *buf,
 				     size_t count, long dummy, loff_t pos);
 asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char __user *buf,
diff --git a/arch/sh/include/asm/traps_32.h b/arch/sh/include/asm/traps_32.h
index cfd55ff9dff2..17e129fe459c 100644
--- a/arch/sh/include/asm/traps_32.h
+++ b/arch/sh/include/asm/traps_32.h
@@ -42,18 +42,10 @@ static inline void trigger_address_error(void)
 asmlinkage void do_address_error(struct pt_regs *regs,
 				 unsigned long writeaccess,
 				 unsigned long address);
-asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs);
-asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs);
-asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs);
-asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
-				   unsigned long r6, unsigned long r7,
-				   struct pt_regs __regs);
+asmlinkage void do_divide_error(unsigned long r4);
+asmlinkage void do_reserved_inst(void);
+asmlinkage void do_illegal_slot_inst(void);
+asmlinkage void do_exception_error(void);
 
 #define BUILD_TRAP_HANDLER(name)					\
 asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,	\
diff --git a/arch/sh/include/cpu-sh2/cpu/cache.h b/arch/sh/include/cpu-sh2/cpu/cache.h
index 673515bc4135..aa1b2b9088a7 100644
--- a/arch/sh/include/cpu-sh2/cpu/cache.h
+++ b/arch/sh/include/cpu-sh2/cpu/cache.h
@@ -18,7 +18,7 @@
 #define SH_CACHE_ASSOC		8
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7619)
-#define CCR		0xffffffec
+#define SH_CCR		0xffffffec
 
 #define CCR_CACHE_CE	0x01	/* Cache enable */
 #define CCR_CACHE_WT	0x02    /* CCR[bit1=1,bit2=1] */
diff --git a/arch/sh/include/cpu-sh2a/cpu/cache.h b/arch/sh/include/cpu-sh2a/cpu/cache.h
index defb0baa5a06..b27ce92cb600 100644
--- a/arch/sh/include/cpu-sh2a/cpu/cache.h
+++ b/arch/sh/include/cpu-sh2a/cpu/cache.h
@@ -17,8 +17,8 @@
 #define SH_CACHE_COMBINED	4
 #define SH_CACHE_ASSOC		8
 
-#define CCR		0xfffc1000 /* CCR1 */
-#define CCR2		0xfffc1004
+#define SH_CCR		0xfffc1000 /* CCR1 */
+#define SH_CCR2		0xfffc1004
 
 /*
  * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not
diff --git a/arch/sh/include/cpu-sh3/cpu/cache.h b/arch/sh/include/cpu-sh3/cpu/cache.h
index bee2d81c56bf..29700fd88c75 100644
--- a/arch/sh/include/cpu-sh3/cpu/cache.h
+++ b/arch/sh/include/cpu-sh3/cpu/cache.h
@@ -17,7 +17,7 @@
 #define SH_CACHE_COMBINED	4
 #define SH_CACHE_ASSOC		8
 
-#define CCR		0xffffffec	/* Address of Cache Control Register */
+#define SH_CCR		0xffffffec	/* Address of Cache Control Register */
 
 #define CCR_CACHE_CE	0x01	/* Cache Enable */
 #define CCR_CACHE_WT	0x02	/* Write-Through (for P0,U0,P3) (else writeback) */
diff --git a/arch/sh/include/cpu-sh4/cpu/cache.h b/arch/sh/include/cpu-sh4/cpu/cache.h
index 7bfb9e8b069c..92c4cd119b66 100644
--- a/arch/sh/include/cpu-sh4/cpu/cache.h
+++ b/arch/sh/include/cpu-sh4/cpu/cache.h
@@ -17,7 +17,7 @@
 #define SH_CACHE_COMBINED	4
 #define SH_CACHE_ASSOC		8
 
-#define CCR		0xff00001c	/* Address of Cache Control Register */
+#define SH_CCR		0xff00001c	/* Address of Cache Control Register */
 #define CCR_CACHE_OCE	0x0001	/* Operand Cache Enable */
 #define CCR_CACHE_WT	0x0002	/* Write-Through (for P0,U0,P3) (else writeback)*/
 #define CCR_CACHE_CB	0x0004	/* Copy-Back (for P1) (else writethrough) */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 261c8bfd75ce..2ccf36c824c6 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -22,7 +22,7 @@ obj-y	:= debugtraps.o dma-nommu.o dumpstack.o 		\
 
 ifndef CONFIG_GENERIC_IOMAP
 obj-y				+= iomap.o
-obj-$(CONFIG_HAS_IOPORT)	+= ioport.o
+obj-$(CONFIG_HAS_IOPORT_MAP)	+= ioport.o
 endif
 
 obj-$(CONFIG_SUPERH32)		+= sys_sh32.o
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index ecf83cd158dc..0d7360d549c1 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -112,7 +112,7 @@ static void cache_init(void)
 	unsigned long ccr, flags;
 
 	jump_to_uncached();
-	ccr = __raw_readl(CCR);
+	ccr = __raw_readl(SH_CCR);
 
 	/*
 	 * At this point we don't know whether the cache is enabled or not - a
@@ -189,7 +189,7 @@ static void cache_init(void)
 
 	l2_cache_init();
 
-	__raw_writel(flags, CCR);
+	__raw_writel(flags, SH_CCR);
 	back_to_cached();
 }
 #else
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index ca46834294b7..13047a4facd2 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -193,10 +193,10 @@ syscall_trace_entry:
 	!			Reload R0-R4 from kernel stack, where the
 	!   	    	    	parent may have modified them using
 	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are
-	!   	    	    	used by the system call handler directly
-	!   	    	    	from the kernel stack anyway, so don't need
-	!   	    	    	to be reloaded here.)  This allows the parent
-	!   	    	    	to rewrite system calls and args on the fly.
+	!   	    	    	reloaded from the kernel stack by syscall_call
+	!   	    	    	below, so don't need to be reloaded here.)
+	!   	    	    	This allows the parent to rewrite system calls
+	!   	    	    	and args on the fly.
 	mov.l	@(OFF_R4,r15), r4   ! arg0
 	mov.l	@(OFF_R5,r15), r5
 	mov.l	@(OFF_R6,r15), r6
@@ -357,8 +357,15 @@ syscall_call:
 	mov.l	3f, r8		! Load the address of sys_call_table
 	add	r8, r3
 	mov.l	@r3, r8
+	mov.l	@(OFF_R2,r15), r2
+	mov.l	@(OFF_R1,r15), r1
+	mov.l	@(OFF_R0,r15), r0
+	mov.l	r2, @-r15
+	mov.l	r1, @-r15
+	mov.l	r0, @-r15
 	jsr	@r8	    	! jump to specific syscall handler
 	 nop
+	add	#12, r15
 	mov.l	@(OFF_R0,r15), r12		! save r0
 	mov.l	r0, @(OFF_R0,r15)		! save the return value
 	!
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index 2ea4483fd722..be616ee0cf87 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -16,7 +16,6 @@
 #include <linux/thread_info.h>
 #include <linux/irqflags.h>
 #include <linux/smp.h>
-#include <linux/cpuidle.h>
 #include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/smp.h>
@@ -40,8 +39,7 @@ void arch_cpu_idle_dead(void)
 
 void arch_cpu_idle(void)
 {
-	if (cpuidle_idle_call())
-		sh_idle();
+	sh_idle();
 }
 
 void __init select_idle_routine(void)
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index c0a9761f2f8a..f8ce36286cea 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -22,7 +22,7 @@
 
 #define TRAPPED_PAGES_MAX 16
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 LIST_HEAD(trapped_io);
 EXPORT_SYMBOL_GPL(trapped_io);
 #endif
@@ -90,7 +90,7 @@ int register_trapped_io(struct trapped_io *tiop)
 	tiop->magic = IO_TRAPPED_MAGIC;
 	INIT_LIST_HEAD(&tiop->list);
 	spin_lock_irq(&trapped_lock);
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 	if (flags & IORESOURCE_IO)
 		list_add(&tiop->list, &trapped_io);
 #endif
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 6af6e7c5cac8..594cd371aa28 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -148,11 +148,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
 	return err;
 }
 
-asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
-			     unsigned long r6, unsigned long r7,
-			     struct pt_regs __regs)
+asmlinkage int sys_sigreturn(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+	struct pt_regs *regs = current_pt_regs();
 	struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15];
 	sigset_t set;
 	int r0;
@@ -180,11 +178,9 @@ badframe:
 	return 0;
 }
 
-asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs)
+asmlinkage int sys_rt_sigreturn(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+	struct pt_regs *regs = current_pt_regs();
 	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
 	sigset_t set;
 	int r0;
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c
index 497bab3a0401..b66d1c62eb19 100644
--- a/arch/sh/kernel/sys_sh32.c
+++ b/arch/sh/kernel/sys_sh32.c
@@ -21,17 +21,14 @@
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way Unix traditionally does this, though.
  */
-asmlinkage int sys_sh_pipe(unsigned long r4, unsigned long r5,
-	unsigned long r6, unsigned long r7,
-	struct pt_regs __regs)
+asmlinkage int sys_sh_pipe(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	int fd[2];
 	int error;
 
 	error = do_pipe_flags(fd, 0);
 	if (!error) {
-		regs->regs[1] = fd[1];
+		current_pt_regs()->regs[1] = fd[1];
 		return fd[0];
 	}
 	return error;
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 68e99f09171d..ff639342a8be 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -594,9 +594,7 @@ int is_dsp_inst(struct pt_regs *regs)
 #endif /* CONFIG_SH_DSP */
 
 #ifdef CONFIG_CPU_SH2A
-asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs)
+asmlinkage void do_divide_error(unsigned long r4)
 {
 	siginfo_t info;
 
@@ -613,11 +611,9 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
 }
 #endif
 
-asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs)
+asmlinkage void do_reserved_inst(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+	struct pt_regs *regs = current_pt_regs();
 	unsigned long error_code;
 	struct task_struct *tsk = current;
 
@@ -701,11 +697,9 @@ static int emulate_branch(unsigned short inst, struct pt_regs *regs)
 }
 #endif
 
-asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
-				unsigned long r6, unsigned long r7,
-				struct pt_regs __regs)
+asmlinkage void do_illegal_slot_inst(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+	struct pt_regs *regs = current_pt_regs();
 	unsigned long inst;
 	struct task_struct *tsk = current;
 
@@ -730,15 +724,12 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
 	die_if_no_fixup("illegal slot instruction", regs, inst);
 }
 
-asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
-				   unsigned long r6, unsigned long r7,
-				   struct pt_regs __regs)
+asmlinkage void do_exception_error(void)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	long ex;
 
 	ex = lookup_exception_vector();
-	die_if_kernel("exception", regs, ex);
+	die_if_kernel("exception", current_pt_regs(), ex);
 }
 
 void per_cpu_trap_init(void)
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index b876780c1e1c..04aa55fa8c75 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -574,24 +574,6 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 	return 0;
 }
 
-asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5,
-			     unsigned long r6, unsigned long r7,
-			     struct pt_regs regs)
-{
-	struct task_struct *tsk = current;
-	siginfo_t info;
-
-	if (ieee_fpe_handler (&regs))
-		return;
-
-	regs.pc += 2;
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_code = FPE_FLTINV;
-	info.si_addr = (void __user *)regs.pc;
-	force_sig_info(SIGFPE, &info, tsk);
-}
-
 /**
  * fpu_init - Initialize FPU registers
  * @fpu: Pointer to software emulated FPU registers.
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index 115725198038..777e50f33c00 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -36,7 +36,7 @@ static int cache_seq_show(struct seq_file *file, void *iter)
 	 */
 	jump_to_uncached();
 
-	ccr = __raw_readl(CCR);
+	ccr = __raw_readl(SH_CCR);
 	if ((ccr & CCR_CACHE_ENABLE) == 0) {
 		back_to_cached();
 
diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c
index defcf719f2e8..a74259f2f981 100644
--- a/arch/sh/mm/cache-sh2.c
+++ b/arch/sh/mm/cache-sh2.c
@@ -63,9 +63,9 @@ static void sh2__flush_invalidate_region(void *start, int size)
 	local_irq_save(flags);
 	jump_to_uncached();
 
-	ccr = __raw_readl(CCR);
+	ccr = __raw_readl(SH_CCR);
 	ccr |= CCR_CACHE_INVALIDATE;
-	__raw_writel(ccr, CCR);
+	__raw_writel(ccr, SH_CCR);
 
 	back_to_cached();
 	local_irq_restore(flags);
diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 949e2d3138a0..ee87d081259b 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -134,7 +134,8 @@ static void sh2a__flush_invalidate_region(void *start, int size)
 
 	/* If there are too many pages then just blow the cache */
 	if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
-		__raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
+		__raw_writel(__raw_readl(SH_CCR) | CCR_OCACHE_INVALIDATE,
+			     SH_CCR);
 	} else {
 		for (v = begin; v < end; v += L1_CACHE_BYTES)
 			sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
@@ -167,7 +168,8 @@ static void sh2a_flush_icache_range(void *args)
 	/* I-Cache invalidate */
 	/* If there are too many pages then just blow the cache */
 	if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
-		__raw_writel(__raw_readl(CCR) | CCR_ICACHE_INVALIDATE, CCR);
+		__raw_writel(__raw_readl(SH_CCR) | CCR_ICACHE_INVALIDATE,
+			     SH_CCR);
 	} else {
 		for (v = start; v < end; v += L1_CACHE_BYTES)
 			sh2a_invalidate_line(CACHE_IC_ADDRESS_ARRAY, v);
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 0e529285b28d..51d8f7f31d1d 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -133,9 +133,9 @@ static void flush_icache_all(void)
 	jump_to_uncached();
 
 	/* Flush I-cache */
-	ccr = __raw_readl(CCR);
+	ccr = __raw_readl(SH_CCR);
 	ccr |= CCR_CACHE_ICI;
-	__raw_writel(ccr, CCR);
+	__raw_writel(ccr, SH_CCR);
 
 	/*
 	 * back_to_cached() will take care of the barrier for us, don't add
diff --git a/arch/sh/mm/cache-shx3.c b/arch/sh/mm/cache-shx3.c
index c0adbee97b5f..24c58b7dc022 100644
--- a/arch/sh/mm/cache-shx3.c
+++ b/arch/sh/mm/cache-shx3.c
@@ -19,7 +19,7 @@ void __init shx3_cache_init(void)
 {
 	unsigned int ccr;
 
-	ccr = __raw_readl(CCR);
+	ccr = __raw_readl(SH_CCR);
 
 	/*
 	 * If we've got cache aliases, resolve them in hardware.
@@ -40,5 +40,5 @@ void __init shx3_cache_init(void)
 	ccr |= CCR_CACHE_IBE;
 #endif
 
-	writel_uncached(ccr, CCR);
+	writel_uncached(ccr, SH_CCR);
 }
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 616966a96cba..097c2cdd117f 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -285,8 +285,8 @@ void __init cpu_cache_init(void)
 {
 	unsigned int cache_disabled = 0;
 
-#ifdef CCR
-	cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE);
+#ifdef SH_CCR
+	cache_disabled = !(__raw_readl(SH_CCR) & CCR_CACHE_ENABLE);
 #endif
 
 	compute_alias(&boot_cpu_data.icache);
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 4b60a0c325ec..a45821818003 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -6,15 +6,16 @@ generic-y += cputime.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += exec.h
-generic-y += linkage.h
-generic-y += local64.h
-generic-y += mutex.h
+generic-y += hash.h
 generic-y += irq_regs.h
+generic-y += linkage.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
+generic-y += mutex.h
+generic-y += preempt.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
index 5f0402aab7fb..24d6a4446349 100644
--- a/arch/sparc/kernel/leon_pci_grpci2.c
+++ b/arch/sparc/kernel/leon_pci_grpci2.c
@@ -8,6 +8,7 @@
 #include <linux/of_device.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <asm/io.h>
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index c5ade9d27a1d..8bb3b3fddea7 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -9,6 +9,8 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
+#include <linux/slab.h>
+
 #include <asm/timer.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index b3692ce78f90..0b0290eeb629 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -405,7 +405,7 @@ config PCI_DOMAINS
 config NO_IOMEM
 	def_bool !PCI
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool !PCI
 
 config TILE_PCI_IO
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 3793c75e45d9..0aa5675e7025 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -11,6 +11,7 @@ generic-y += errno.h
 generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -18,12 +19,14 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -38,5 +41,3 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 88a330dcdede..a5e4b6068213 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,8 +1,28 @@
-generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
-generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
-generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
-generic-y += switch_to.h clkdev.h
-generic-y += trace_clock.h
-generic-y += preempt.h
-generic-y += hash.h
 generic-y += barrier.h
+generic-y += bug.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += emergency-restart.h
+generic-y += exec.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hash.h
+generic-y += hw_irq.h
+generic-y += io.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += mcs_spinlock.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += sections.h
+generic-y += switch_to.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += xor.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/process.c b/arch/um/kernel/process.c
index eecc4142764c..f17bca8ed2ce 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -359,7 +359,7 @@ int singlestepping(void * t)
 /*
  * Only x86 and x86_64 have an arch_align_stack().
  * All other arches have "#define arch_align_stack(x) (x)"
- * in their asm/system.h
+ * in their asm/exec.h
  * As this is included in UML from asm-um/system-generic.h,
  * we can use it to behave as the subarch does.
  */
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/unicore32/Kconfig b/arch/unicore32/Kconfig
index 25c0dba508cc..aafad6fa1667 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -27,7 +27,7 @@ config UNICORE32
 config GENERIC_CSUM
 	def_bool y
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	bool
 
 config STACKTRACE_SUPPORT
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 3ef4f9d9bf5d..1e5fb872a4aa 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -16,6 +16,7 @@ generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -24,6 +25,7 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += module.h
 generic-y += msgbuf.h
@@ -32,6 +34,7 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -60,5 +63,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0af5250d914f..4b0f6012dc2c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -127,6 +127,7 @@ config X86
 	select HAVE_DEBUG_STACKOVERFLOW
 	select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
 	select HAVE_CC_STACKPROTECTOR
+	select GENERIC_CPU_AUTOPROBE
 
 config INSTRUCTION_DECODER
 	def_bool y
@@ -195,9 +196,6 @@ config ARCH_HAS_CPU_RELAX
 config ARCH_HAS_CACHE_LINE_SIZE
 	def_bool y
 
-config ARCH_HAS_CPU_AUTOPROBE
-	def_bool y
-
 config HAVE_SETUP_PER_CPU_AREA
 	def_bool y
 
@@ -346,12 +344,9 @@ config X86_EXTENDED_PLATFORM
 	  for the following (non-PC) 32 bit x86 platforms:
 		Goldfish (Android emulator)
 		AMD Elan
-		NUMAQ (IBM/Sequent)
 		RDC R-321x SoC
 		SGI 320/540 (Visual Workstation)
 		STA2X11-based (e.g. Northville)
-		Summit/EXA (IBM x440)
-		Unisys ES7000 IA32 series
 		Moorestown MID devices
 
 	  If you have one of these systems, or if you want to build a
@@ -489,49 +484,22 @@ config X86_32_NON_STANDARD
 	depends on X86_32 && SMP
 	depends on X86_EXTENDED_PLATFORM
 	---help---
-	  This option compiles in the NUMAQ, Summit, bigsmp, ES7000,
-	  STA2X11, default subarchitectures.  It is intended for a generic
-	  binary kernel. If you select them all, kernel will probe it
-	  one by one and will fallback to default.
+	  This option compiles in the bigsmp and STA2X11 default
+	  subarchitectures.  It is intended for a generic binary
+	  kernel. If you select them all, kernel will probe it one by
+	  one and will fallback to default.
 
 # Alphabetically sorted list of Non standard 32 bit platforms
 
-config X86_NUMAQ
-	bool "NUMAQ (IBM/Sequent)"
-	depends on X86_32_NON_STANDARD
-	depends on PCI
-	select NUMA
-	select X86_MPPARSE
-	---help---
-	  This option is used for getting Linux to run on a NUMAQ (IBM/Sequent)
-	  NUMA multiquad box. This changes the way that processors are
-	  bootstrapped, and uses Clustered Logical APIC addressing mode instead
-	  of Flat Logical.  You will need a new lynxer.elf file to flash your
-	  firmware with - send email to <Martin.Bligh@us.ibm.com>.
-
 config X86_SUPPORTS_MEMORY_FAILURE
 	def_bool y
 	# MCE code calls memory_failure():
 	depends on X86_MCE
 	# On 32-bit this adds too big of NODES_SHIFT and we run out of page flags:
-	depends on !X86_NUMAQ
 	# On 32-bit SPARSEMEM adds too big of SECTIONS_WIDTH:
 	depends on X86_64 || !SPARSEMEM
 	select ARCH_SUPPORTS_MEMORY_FAILURE
 
-config X86_VISWS
-	bool "SGI 320/540 (Visual Workstation)"
-	depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT
-	depends on X86_32_NON_STANDARD
-	---help---
-	  The SGI Visual Workstation series is an IA32-based workstation
-	  based on SGI systems chips with some legacy PC hardware attached.
-
-	  Say Y here to create a kernel to run on the SGI 320 or 540.
-
-	  A kernel compiled for the Visual Workstation will run on general
-	  PCs as well. See <file:Documentation/sgi-visws.txt> for details.
-
 config STA2X11
 	bool "STA2X11 Companion Chip Support"
 	depends on X86_32_NON_STANDARD && PCI
@@ -548,20 +516,6 @@ config STA2X11
 	  option is selected the kernel will still be able to boot on
 	  standard PC machines.
 
-config X86_SUMMIT
-	bool "Summit/EXA (IBM x440)"
-	depends on X86_32_NON_STANDARD
-	---help---
-	  This option is needed for IBM systems that use the Summit/EXA chipset.
-	  In particular, it is needed for the x440.
-
-config X86_ES7000
-	bool "Unisys ES7000 IA32 series"
-	depends on X86_32_NON_STANDARD && X86_BIGSMP
-	---help---
-	  Support for Unisys ES7000 systems.  Say 'Y' here if this kernel is
-	  supposed to run on an IA32-based Unisys ES7000 system.
-
 config X86_32_IRIS
 	tristate "Eurobraille/Iris poweroff module"
 	depends on X86_32
@@ -684,14 +638,6 @@ config MEMTEST
 	        memtest=4, mean do 4 test patterns.
 	  If you are unsure how to answer this question, answer N.
 
-config X86_SUMMIT_NUMA
-	def_bool y
-	depends on X86_32 && NUMA && X86_32_NON_STANDARD
-
-config X86_CYCLONE_TIMER
-	def_bool y
-	depends on X86_SUMMIT
-
 source "arch/x86/Kconfig.cpu"
 
 config HPET_TIMER
@@ -820,7 +766,7 @@ config NR_CPUS
 	range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64
 	default "1" if !SMP
 	default "8192" if MAXSMP
-	default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
+	default "32" if SMP && X86_BIGSMP
 	default "8" if SMP
 	---help---
 	  This allows you to specify the maximum number of CPUs which this
@@ -884,10 +830,6 @@ config X86_IO_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
 
-config X86_VISWS_APIC
-	def_bool y
-	depends on X86_32 && X86_VISWS
-
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 	bool "Reroute for broken boot IRQs"
 	depends on X86_IO_APIC
@@ -1105,13 +1047,11 @@ config X86_CPUID
 
 choice
 	prompt "High Memory Support"
-	default HIGHMEM64G if X86_NUMAQ
 	default HIGHMEM4G
 	depends on X86_32
 
 config NOHIGHMEM
 	bool "off"
-	depends on !X86_NUMAQ
 	---help---
 	  Linux can use up to 64 Gigabytes of physical memory on x86 systems.
 	  However, the address space of 32-bit x86 processors is only 4
@@ -1148,7 +1088,6 @@ config NOHIGHMEM
 
 config HIGHMEM4G
 	bool "4GB"
-	depends on !X86_NUMAQ
 	---help---
 	  Select this if you have a 32-bit processor and between 1 and 4
 	  gigabytes of physical RAM.
@@ -1240,8 +1179,8 @@ config DIRECT_GBPAGES
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"
 	depends on SMP
-	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI))
-	default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
+	depends on X86_64 || (X86_32 && HIGHMEM64G && X86_BIGSMP)
+	default y if X86_BIGSMP
 	---help---
 	  Enable NUMA (Non Uniform Memory Access) support.
 
@@ -1252,15 +1191,11 @@ config NUMA
 	  For 64-bit this is recommended if the system is Intel Core i7
 	  (or later), AMD Opteron, or EM64T NUMA.
 
-	  For 32-bit this is only needed on (rare) 32-bit-only platforms
-	  that support NUMA topologies, such as NUMAQ / Summit, or if you
-	  boot a 32-bit kernel on a 64-bit NUMA platform.
+	  For 32-bit this is only needed if you boot a 32-bit
+	  kernel on a 64-bit NUMA platform.
 
 	  Otherwise, you should say N.
 
-comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
-	depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
-
 config AMD_NUMA
 	def_bool y
 	prompt "Old style AMD Opteron NUMA detection"
@@ -1302,7 +1237,6 @@ config NODES_SHIFT
 	range 1 10
 	default "10" if MAXSMP
 	default "6" if X86_64
-	default "4" if X86_NUMAQ
 	default "3"
 	depends on NEED_MULTIPLE_NODES
 	---help---
@@ -2413,11 +2347,12 @@ config X86_DMA_REMAP
 	depends on STA2X11
 
 config IOSF_MBI
-	bool
+	bool "IOSF MBI support" if EXPERT
+	default y
 	depends on PCI
 	---help---
 	  To be selected by modules requiring access to the Intel OnChip System
-	  Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms
+	  Fabric (IOSF) Sideband MailBox Interface (MBI). For IOSF platforms
 	  enumerable by PCI.
 
 source "net/Kconfig"
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index c026cca5602c..3c6b17b08a18 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -363,7 +363,7 @@ config X86_P6_NOP
 
 config X86_TSC
 	def_bool y
-	depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) && !X86_NUMAQ) || X86_64
+	depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64
 
 config X86_CMPXCHG64
 	def_bool y
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index eeda43abed6e..a414b1471ffc 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -82,8 +82,8 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
-        # Don't autogenerate MMX or SSE instructions
-        KBUILD_CFLAGS += -mno-mmx -mno-sse
+        # Don't autogenerate traditional x87, MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse -mno-80387 -mno-fp-ret-in-387
 
 	# Use -mpreferred-stack-boundary=3 if supported.
 	KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index a7fef2621cc9..619e7f7426c6 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -60,7 +60,6 @@ CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
 CONFIG_PM_TRACE_RTC=y
-CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_DOCK=y
 CONFIG_CPU_FREQ=y
 # CONFIG_CPU_FREQ_STAT is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index c1119d4c1281..6181c69b786b 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -58,7 +58,6 @@ CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
 CONFIG_PM_TRACE_RTC=y
-CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_DOCK=y
 CONFIG_CPU_FREQ=y
 # CONFIG_CPU_FREQ_STAT is not set
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c
index 50ec333b70e6..8af519ed73d1 100644
--- a/arch/x86/crypto/blowfish_glue.c
+++ b/arch/x86/crypto/blowfish_glue.c
@@ -223,9 +223,6 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
 			src -= 1;
 			dst -= 1;
 		} while (nbytes >= bsize * 4);
-
-		if (nbytes < bsize)
-			goto done;
 	}
 
 	/* Handle leftovers */
diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c
index e6a3700489b9..e57e20ab5e0b 100644
--- a/arch/x86/crypto/cast5_avx_glue.c
+++ b/arch/x86/crypto/cast5_avx_glue.c
@@ -203,9 +203,6 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
 			src -= 1;
 			dst -= 1;
 		} while (nbytes >= bsize * CAST5_PARALLEL_BLOCKS);
-
-		if (nbytes < bsize)
-			goto done;
 	}
 
 	/* Handle leftovers */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 7f669853317a..a8fee078b92f 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -5,3 +5,4 @@ genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
 
 generic-y += clkdev.h
+generic-y += mcs_spinlock.h
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1d2091a226bc..19b0ebafcd3e 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -93,9 +93,6 @@ static inline int is_vsmp_box(void)
 	return 0;
 }
 #endif
-extern void xapic_wait_icr_idle(void);
-extern u32 safe_xapic_wait_icr_idle(void);
-extern void xapic_icr_write(u32, u32);
 extern int setup_profiling_timer(unsigned int);
 
 static inline void native_apic_mem_write(u32 reg, u32 v)
@@ -184,7 +181,6 @@ extern int x2apic_phys;
 extern int x2apic_preenabled;
 extern void check_x2apic(void);
 extern void enable_x2apic(void);
-extern void x2apic_icr_write(u32 low, u32 id);
 static inline int x2apic_enabled(void)
 {
 	u64 msr;
@@ -221,7 +217,6 @@ static inline void x2apic_force_phys(void)
 {
 }
 
-#define	nox2apic	0
 #define	x2apic_preenabled 0
 #define	x2apic_supported()	0
 #endif
@@ -351,7 +346,7 @@ struct apic {
 	int trampoline_phys_low;
 	int trampoline_phys_high;
 
-	void (*wait_for_init_deassert)(atomic_t *deassert);
+	bool wait_for_init_deassert;
 	void (*smp_callin_clear_local_apic)(void);
 	void (*inquire_remote_apic)(int apicid);
 
@@ -517,13 +512,6 @@ extern int default_cpu_present_to_apicid(int mps_cpu);
 extern int default_check_phys_apicid_present(int phys_apicid);
 #endif
 
-static inline void default_wait_for_init_deassert(atomic_t *deassert)
-{
-	while (!atomic_read(deassert))
-		cpu_relax();
-	return;
-}
-
 extern void generic_bigsmp_probe(void);
 
 
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index e099f9502ace..e265ff95d16d 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -37,7 +37,7 @@
 #define X86_FEATURE_PAT		(0*32+16) /* Page Attribute Table */
 #define X86_FEATURE_PSE36	(0*32+17) /* 36-bit PSEs */
 #define X86_FEATURE_PN		(0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH	(0*32+19) /* "clflush" CLFLUSH instruction */
+#define X86_FEATURE_CLFLUSH	(0*32+19) /* CLFLUSH instruction */
 #define X86_FEATURE_DS		(0*32+21) /* "dts" Debug Store */
 #define X86_FEATURE_ACPI	(0*32+22) /* ACPI via MSR */
 #define X86_FEATURE_MMX		(0*32+23) /* Multimedia Extensions */
@@ -217,9 +217,14 @@
 #define X86_FEATURE_INVPCID	(9*32+10) /* Invalidate Processor Context ID */
 #define X86_FEATURE_RTM		(9*32+11) /* Restricted Transactional Memory */
 #define X86_FEATURE_MPX		(9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_AVX512F	(9*32+16) /* AVX-512 Foundation */
 #define X86_FEATURE_RDSEED	(9*32+18) /* The RDSEED instruction */
 #define X86_FEATURE_ADX		(9*32+19) /* The ADCX and ADOX instructions */
 #define X86_FEATURE_SMAP	(9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_CLFLUSHOPT	(9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_AVX512PF	(9*32+26) /* AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER	(9*32+27) /* AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD	(9*32+28) /* AVX-512 Conflict Detection */
 
 /*
  * BUG word(s)
@@ -313,7 +318,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_pmm_enabled	boot_cpu_has(X86_FEATURE_PMM_EN)
 #define cpu_has_ds		boot_cpu_has(X86_FEATURE_DS)
 #define cpu_has_pebs		boot_cpu_has(X86_FEATURE_PEBS)
-#define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLSH)
+#define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLUSH)
 #define cpu_has_bts		boot_cpu_has(X86_FEATURE_BTS)
 #define cpu_has_gbpages		boot_cpu_has(X86_FEATURE_GBPAGES)
 #define cpu_has_arch_perfmon	boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
@@ -541,6 +546,13 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 #define static_cpu_has_bug(bit)	static_cpu_has((bit))
 #define boot_cpu_has_bug(bit)	cpu_has_bug(&boot_cpu_data, (bit))
 
+#define MAX_CPU_FEATURES	(NCAPINTS * 32)
+#define cpu_have_feature	boot_cpu_has
+
+#define CPU_FEATURE_TYPEFMT	"x86,ven%04Xfam%04Xmod%04X"
+#define CPU_FEATURE_TYPEVAL	boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
+				boot_cpu_data.x86_model
+
 #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
 
 #endif /* _ASM_X86_CPUFEATURE_H */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 7252cd339175..f690ee420bf4 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -98,12 +98,6 @@ enum fixed_addresses {
 	FIX_IO_APIC_BASE_0,
 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
 #endif
-#ifdef CONFIG_X86_VISWS_APIC
-	FIX_CO_CPU,	/* Cobalt timer */
-	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
-	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
-	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
-#endif
 	FIX_RO_IDT,	/* Virtual mapping for read-only IDT */
 #ifdef CONFIG_X86_32
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 67d69b8e2d20..a307b7530e54 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -98,7 +98,6 @@ extern void trace_call_function_single_interrupt(void);
 #define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs))
 extern unsigned long io_apic_irqs;
 
-extern void init_VISWS_APIC_irqs(void);
 extern void setup_IO_APIC(void);
 extern void disable_IO_APIC(void);
 
diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h
index 8e71c7941767..9fc5402963c1 100644
--- a/arch/x86/include/asm/iosf_mbi.h
+++ b/arch/x86/include/asm/iosf_mbi.h
@@ -5,6 +5,8 @@
 #ifndef IOSF_MBI_SYMS_H
 #define IOSF_MBI_SYMS_H
 
+#ifdef CONFIG_IOSF_MBI
+
 #define MBI_MCR_OFFSET		0xD0
 #define MBI_MDR_OFFSET		0xD4
 #define MBI_MCRX_OFFSET		0xD8
@@ -50,6 +52,8 @@
 #define BT_MBI_PCIE_READ	0x00
 #define BT_MBI_PCIE_WRITE	0x01
 
+bool iosf_mbi_available(void);
+
 /**
  * iosf_mbi_read() - MailBox Interface read command
  * @port:	port indicating subunit being accessed
@@ -87,4 +91,33 @@ int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
  */
 int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);
 
+#else /* CONFIG_IOSF_MBI is not enabled */
+static inline
+bool iosf_mbi_available(void)
+{
+	return false;
+}
+
+static inline
+int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
+{
+	WARN();
+	return -EPERM;
+}
+
+static inline
+int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr)
+{
+	WARN();
+	return -EPERM;
+}
+
+static inline
+int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
+{
+	WARN();
+	return -EPERM;
+}
+#endif /* CONFIG_IOSF_MBI */
+
 #endif /* IOSF_MBI_SYMS_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index fdf83afbb7d9..e714f8c08ccf 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -444,7 +444,6 @@ struct kvm_vcpu_arch {
 	} st;
 
 	u64 last_guest_tsc;
-	u64 last_kernel_ns;
 	u64 last_host_tsc;
 	u64 tsc_offset_adjustment;
 	u64 this_tsc_nsec;
@@ -765,6 +764,7 @@ struct kvm_x86_ops {
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage);
 	void (*handle_external_intr)(struct kvm_vcpu *vcpu);
+	bool (*mpx_supported)(void);
 };
 
 struct kvm_arch_async_pf {
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index 8a9b3e288cb4..1ec990bd7dc0 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -11,9 +11,6 @@
 #ifdef CONFIG_NUMA
 extern struct pglist_data *node_data[];
 #define NODE_DATA(nid)	(node_data[nid])
-
-#include <asm/numaq.h>
-
 #endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_DISCONTIGMEM
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 3e6b4920ef5d..f5a617956735 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -25,12 +25,6 @@ extern int pic_mode;
 
 extern unsigned int def_to_bigsmp;
 
-#ifdef CONFIG_X86_NUMAQ
-extern int mp_bus_id_to_node[MAX_MP_BUSSES];
-extern int mp_bus_id_to_local[MAX_MP_BUSSES];
-extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
-#endif
-
 #else /* CONFIG_X86_64: */
 
 #define MAX_MP_BUSSES		256
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index 86f9301903c8..5f2fc4441b11 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_X86_NMI_H
 #define _ASM_X86_NMI_H
 
+#include <linux/irq_work.h>
 #include <linux/pm.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -38,6 +39,8 @@ typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
 struct nmiaction {
 	struct list_head	list;
 	nmi_handler_t		handler;
+	u64			max_duration;
+	struct irq_work		irq_work;
 	unsigned long		flags;
 	const char		*name;
 };
diff --git a/arch/x86/include/asm/numaq.h b/arch/x86/include/asm/numaq.h
deleted file mode 100644
index c3b3c322fd87..000000000000
--- a/arch/x86/include/asm/numaq.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Written by: Patricia Gaughen, IBM Corporation
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU 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.
- *
- * Send feedback to <gone@us.ibm.com>
- */
-
-#ifndef _ASM_X86_NUMAQ_H
-#define _ASM_X86_NUMAQ_H
-
-#ifdef CONFIG_X86_NUMAQ
-
-extern int found_numaq;
-extern int numaq_numa_init(void);
-extern int pci_numaq_init(void);
-
-extern void *xquad_portio;
-
-#define XQUAD_PORTIO_BASE 0xfe400000
-#define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
-#define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
-
-/*
- * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the
- */
-#define SYS_CFG_DATA_PRIV_ADDR		0x0009d000 /* place for scd in private
-						      quad space */
-
-/*
- * Communication area for each processor on lynxer-processor tests.
- *
- * NOTE: If you change the size of this eachproc structure you need
- *       to change the definition for EACH_QUAD_SIZE.
- */
-struct eachquadmem {
-	unsigned int	priv_mem_start;		/* Starting address of this */
-						/* quad's private memory. */
-						/* This is always 0. */
-						/* In MB. */
-	unsigned int	priv_mem_size;		/* Size of this quad's */
-						/* private memory. */
-						/* In MB. */
-	unsigned int	low_shrd_mem_strp_start;/* Starting address of this */
-						/* quad's low shared block */
-						/* (untranslated). */
-						/* In MB. */
-	unsigned int	low_shrd_mem_start;	/* Starting address of this */
-						/* quad's low shared memory */
-						/* (untranslated). */
-						/* In MB. */
-	unsigned int	low_shrd_mem_size;	/* Size of this quad's low */
-						/* shared memory. */
-						/* In MB. */
-	unsigned int	lmmio_copb_start;	/* Starting address of this */
-						/* quad's local memory */
-						/* mapped I/O in the */
-						/* compatibility OPB. */
-						/* In MB. */
-	unsigned int	lmmio_copb_size;	/* Size of this quad's local */
-						/* memory mapped I/O in the */
-						/* compatibility OPB. */
-						/* In MB. */
-	unsigned int	lmmio_nopb_start;	/* Starting address of this */
-						/* quad's local memory */
-						/* mapped I/O in the */
-						/* non-compatibility OPB. */
-						/* In MB. */
-	unsigned int	lmmio_nopb_size;	/* Size of this quad's local */
-						/* memory mapped I/O in the */
-						/* non-compatibility OPB. */
-						/* In MB. */
-	unsigned int	io_apic_0_start;	/* Starting address of I/O */
-						/* APIC 0. */
-	unsigned int	io_apic_0_sz;		/* Size I/O APIC 0. */
-	unsigned int	io_apic_1_start;	/* Starting address of I/O */
-						/* APIC 1. */
-	unsigned int	io_apic_1_sz;		/* Size I/O APIC 1. */
-	unsigned int	hi_shrd_mem_start;	/* Starting address of this */
-						/* quad's high shared memory.*/
-						/* In MB. */
-	unsigned int	hi_shrd_mem_size;	/* Size of this quad's high */
-						/* shared memory. */
-						/* In MB. */
-	unsigned int	mps_table_addr;		/* Address of this quad's */
-						/* MPS tables from BIOS, */
-						/* in system space.*/
-	unsigned int	lcl_MDC_pio_addr;	/* Port-I/O address for */
-						/* local access of MDC. */
-	unsigned int	rmt_MDC_mmpio_addr;	/* MM-Port-I/O address for */
-						/* remote access of MDC. */
-	unsigned int	mm_port_io_start;	/* Starting address of this */
-						/* quad's memory mapped Port */
-						/* I/O space. */
-	unsigned int	mm_port_io_size;	/* Size of this quad's memory*/
-						/* mapped Port I/O space. */
-	unsigned int	mm_rmt_io_apic_start;	/* Starting address of this */
-						/* quad's memory mapped */
-						/* remote I/O APIC space. */
-	unsigned int	mm_rmt_io_apic_size;	/* Size of this quad's memory*/
-						/* mapped remote I/O APIC */
-						/* space. */
-	unsigned int	mm_isa_start;		/* Starting address of this */
-						/* quad's memory mapped ISA */
-						/* space (contains MDC */
-						/* memory space). */
-	unsigned int	mm_isa_size;		/* Size of this quad's memory*/
-						/* mapped ISA space (contains*/
-						/* MDC memory space). */
-	unsigned int	rmt_qmi_addr;		/* Remote addr to access QMI.*/
-	unsigned int	lcl_qmi_addr;		/* Local addr to access QMI. */
-};
-
-/*
- * Note: This structure must be NOT be changed unless the multiproc and
- * OS are changed to reflect the new structure.
- */
-struct sys_cfg_data {
-	unsigned int	quad_id;
-	unsigned int	bsp_proc_id; /* Boot Strap Processor in this quad. */
-	unsigned int	scd_version; /* Version number of this table. */
-	unsigned int	first_quad_id;
-	unsigned int	quads_present31_0; /* 1 bit for each quad */
-	unsigned int	quads_present63_32; /* 1 bit for each quad */
-	unsigned int	config_flags;
-	unsigned int	boot_flags;
-	unsigned int	csr_start_addr; /* Absolute value (not in MB) */
-	unsigned int	csr_size; /* Absolute value (not in MB) */
-	unsigned int	lcl_apic_start_addr; /* Absolute value (not in MB) */
-	unsigned int	lcl_apic_size; /* Absolute value (not in MB) */
-	unsigned int	low_shrd_mem_base; /* 0 or 512MB or 1GB */
-	unsigned int	low_shrd_mem_quad_offset; /* 0,128M,256M,512M,1G */
-					/* may not be totally populated */
-	unsigned int	split_mem_enbl; /* 0 for no low shared memory */
-	unsigned int	mmio_sz; /* Size of total system memory mapped I/O */
-				 /* (in MB). */
-	unsigned int	quad_spin_lock; /* Spare location used for quad */
-					/* bringup. */
-	unsigned int	nonzero55; /* For checksumming. */
-	unsigned int	nonzeroaa; /* For checksumming. */
-	unsigned int	scd_magic_number;
-	unsigned int	system_type;
-	unsigned int	checksum;
-	/*
-	 *	memory configuration area for each quad
-	 */
-	struct		eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
-};
-
-void numaq_tsc_disable(void);
-
-#endif /* CONFIG_X86_NUMAQ */
-#endif /* _ASM_X86_NUMAQ_H */
-
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 1ac6114c9ea5..96ae4f4040bb 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -26,11 +26,6 @@ extern int pci_routeirq;
 extern int noioapicquirk;
 extern int noioapicreroute;
 
-/* scan a bus after allocating a pci_sysdata for it */
-extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
-					    int node);
-extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
-
 #ifdef CONFIG_PCI
 
 #ifdef CONFIG_PCI_DOMAINS
@@ -70,7 +65,7 @@ extern unsigned long pci_mem_start;
 
 extern int pcibios_enabled;
 void pcibios_config_init(void);
-struct pci_bus *pcibios_scan_root(int bus);
+void pcibios_scan_root(int bus);
 
 void pcibios_set_master(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq, int active);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 1aa9ccd43223..b821f37ec234 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -17,7 +17,7 @@
 #define _PAGE_BIT_PAT		7	/* on 4KB pages */
 #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
 #define _PAGE_BIT_UNUSED1	9	/* available for programmer */
-#define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
+#define _PAGE_BIT_UNUSED2	10	/* available for programmer */
 #define _PAGE_BIT_HIDDEN	11	/* hidden by kmemcheck */
 #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
 #define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
@@ -41,7 +41,7 @@
 #define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
 #define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
 #define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
-#define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
+#define _PAGE_UNUSED2	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2)
 #define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
 #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
 #define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
@@ -164,10 +164,10 @@
 #define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
 
-#define __PAGE_KERNEL_IO		(__PAGE_KERNEL | _PAGE_IOMAP)
-#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
-#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
-#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
+#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
+#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS)
+#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC)
 
 #define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
 #define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index d62c9f809bc5..9264f04a4c55 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -39,12 +39,6 @@ static inline void vsmp_init(void) { }
 
 void setup_bios_corruption_check(void);
 
-#ifdef CONFIG_X86_VISWS
-extern void visws_early_detect(void);
-#else
-static inline void visws_early_detect(void) { }
-#endif
-
 extern unsigned long saved_video_mode;
 
 extern void reserve_standard_io_resources(void);
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 645cad2c95ff..e820c080a4e9 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -191,6 +191,14 @@ static inline void clflush(volatile void *__p)
 	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
 }
 
+static inline void clflushopt(volatile void *__p)
+{
+	alternative_io(".byte " __stringify(NOP_DS_PREFIX) "; clflush %P0",
+		       ".byte 0x66; clflush %P0",
+		       X86_FEATURE_CLFLUSHOPT,
+		       "+m" (*(volatile char __force *)__p));
+}
+
 #define nop() asm volatile ("nop")
 
 
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index d35f24e231cd..c840571afa4e 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -131,6 +131,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
 }
 
 struct pci_bus;
+int x86_pci_root_bus_node(int bus);
 void x86_pci_root_bus_resources(int bus, struct list_head *resources);
 
 #ifdef CONFIG_SMP
@@ -139,17 +140,4 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources);
 #define smt_capable()			(smp_num_siblings > 1)
 #endif
 
-#ifdef CONFIG_NUMA
-extern int get_mp_bus_to_node(int busnum);
-extern void set_mp_bus_to_node(int busnum, int node);
-#else
-static inline int get_mp_bus_to_node(int busnum)
-{
-	return 0;
-}
-static inline void set_mp_bus_to_node(int busnum, int node)
-{
-}
-#endif
-
 #endif /* _ASM_X86_TOPOLOGY_H */
diff --git a/arch/x86/include/asm/visws/cobalt.h b/arch/x86/include/asm/visws/cobalt.h
deleted file mode 100644
index 2edb37637ead..000000000000
--- a/arch/x86/include/asm/visws/cobalt.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef _ASM_X86_VISWS_COBALT_H
-#define _ASM_X86_VISWS_COBALT_H
-
-#include <asm/fixmap.h>
-
-/*
- * Cobalt SGI Visual Workstation system ASIC
- */ 
-
-#define CO_CPU_NUM_PHYS 0x1e00
-#define CO_CPU_TAB_PHYS (CO_CPU_NUM_PHYS + 2)
-
-#define CO_CPU_MAX 4
-
-#define	CO_CPU_PHYS		0xc2000000
-#define	CO_APIC_PHYS		0xc4000000
-
-/* see set_fixmap() and asm/fixmap.h */
-#define	CO_CPU_VADDR		(fix_to_virt(FIX_CO_CPU))
-#define	CO_APIC_VADDR		(fix_to_virt(FIX_CO_APIC))
-
-/* Cobalt CPU registers -- relative to CO_CPU_VADDR, use co_cpu_*() */
-#define	CO_CPU_REV		0x08
-#define	CO_CPU_CTRL		0x10
-#define	CO_CPU_STAT		0x20
-#define	CO_CPU_TIMEVAL		0x30
-
-/* CO_CPU_CTRL bits */
-#define	CO_CTRL_TIMERUN		0x04		/* 0 == disabled */
-#define	CO_CTRL_TIMEMASK	0x08		/* 0 == unmasked */
-
-/* CO_CPU_STATUS bits */
-#define	CO_STAT_TIMEINTR	0x02	/* (r) 1 == int pend, (w) 0 == clear */
-
-/* CO_CPU_TIMEVAL value */
-#define	CO_TIME_HZ		100000000	/* Cobalt core rate */
-
-/* Cobalt APIC registers -- relative to CO_APIC_VADDR, use co_apic_*() */
-#define	CO_APIC_HI(n)		(((n) * 0x10) + 4)
-#define	CO_APIC_LO(n)		((n) * 0x10)
-#define	CO_APIC_ID		0x0ffc
-
-/* CO_APIC_ID bits */
-#define	CO_APIC_ENABLE		0x00000100
-
-/* CO_APIC_LO bits */
-#define	CO_APIC_MASK		0x00010000	/* 0 = enabled */
-#define	CO_APIC_LEVEL		0x00008000	/* 0 = edge */
-
-/*
- * Where things are physically wired to Cobalt
- * #defines with no board _<type>_<rev>_ are common to all (thus far)
- */
-#define	CO_APIC_IDE0		4
-#define CO_APIC_IDE1		2		/* Only on 320 */
-
-#define	CO_APIC_8259		12		/* serial, floppy, par-l-l */
-
-/* Lithium PCI Bridge A -- "the one with 82557 Ethernet" */
-#define	CO_APIC_PCIA_BASE0	0 /* and 1 */	/* slot 0, line 0 */
-#define	CO_APIC_PCIA_BASE123	5 /* and 6 */	/* slot 0, line 1 */
-
-#define	CO_APIC_PIIX4_USB	7		/* this one is weird */
-
-/* Lithium PCI Bridge B -- "the one with PIIX4" */
-#define	CO_APIC_PCIB_BASE0	8 /* and 9-12 *//* slot 0, line 0 */
-#define	CO_APIC_PCIB_BASE123	13 /* 14.15 */	/* slot 0, line 1 */
-
-#define	CO_APIC_VIDOUT0		16
-#define	CO_APIC_VIDOUT1		17
-#define	CO_APIC_VIDIN0		18
-#define	CO_APIC_VIDIN1		19
-
-#define	CO_APIC_LI_AUDIO	22
-
-#define	CO_APIC_AS		24
-#define	CO_APIC_RE		25
-
-#define CO_APIC_CPU		28		/* Timer and Cache interrupt */
-#define	CO_APIC_NMI		29
-#define	CO_APIC_LAST		CO_APIC_NMI
-
-/*
- * This is how irqs are assigned on the Visual Workstation.
- * Legacy devices get irq's 1-15 (system clock is 0 and is CO_APIC_CPU).
- * All other devices (including PCI) go to Cobalt and are irq's 16 on up.
- */
-#define	CO_IRQ_APIC0	16			/* irq of apic entry 0 */
-#define	IS_CO_APIC(irq)	((irq) >= CO_IRQ_APIC0)
-#define	CO_IRQ(apic)	(CO_IRQ_APIC0 + (apic))	/* apic ent to irq */
-#define	CO_APIC(irq)	((irq) - CO_IRQ_APIC0)	/* irq to apic ent */
-#define CO_IRQ_IDE0	14			/* knowledge of... */
-#define CO_IRQ_IDE1	15			/* ... ide driver defaults! */
-#define	CO_IRQ_8259	CO_IRQ(CO_APIC_8259)
-
-#ifdef CONFIG_X86_VISWS_APIC
-static inline void co_cpu_write(unsigned long reg, unsigned long v)
-{
-	*((volatile unsigned long *)(CO_CPU_VADDR+reg))=v;
-}
-
-static inline unsigned long co_cpu_read(unsigned long reg)
-{
-	return *((volatile unsigned long *)(CO_CPU_VADDR+reg));
-}            
-             
-static inline void co_apic_write(unsigned long reg, unsigned long v)
-{
-	*((volatile unsigned long *)(CO_APIC_VADDR+reg))=v;
-}            
-             
-static inline unsigned long co_apic_read(unsigned long reg)
-{
-	return *((volatile unsigned long *)(CO_APIC_VADDR+reg));
-}
-#endif
-
-extern char visws_board_type;
-
-#define	VISWS_320	0
-#define	VISWS_540	1
-
-extern char visws_board_rev;
-
-extern int pci_visws_init(void);
-
-#endif /* _ASM_X86_VISWS_COBALT_H */
diff --git a/arch/x86/include/asm/visws/lithium.h b/arch/x86/include/asm/visws/lithium.h
deleted file mode 100644
index a10d89bc1270..000000000000
--- a/arch/x86/include/asm/visws/lithium.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef _ASM_X86_VISWS_LITHIUM_H
-#define _ASM_X86_VISWS_LITHIUM_H
-
-#include <asm/fixmap.h>
-
-/*
- * Lithium is the SGI Visual Workstation I/O ASIC
- */
-
-#define	LI_PCI_A_PHYS		0xfc000000	/* Enet is dev 3 */
-#define	LI_PCI_B_PHYS		0xfd000000	/* PIIX4 is here */
-
-/* see set_fixmap() and asm/fixmap.h */
-#define LI_PCIA_VADDR   (fix_to_virt(FIX_LI_PCIA))
-#define LI_PCIB_VADDR   (fix_to_virt(FIX_LI_PCIB))
-
-/* Not a standard PCI? (not in linux/pci.h) */
-#define	LI_PCI_BUSNUM	0x44			/* lo8: primary, hi8: sub */
-#define LI_PCI_INTEN    0x46
-
-/* LI_PCI_INTENT bits */
-#define	LI_INTA_0	0x0001
-#define	LI_INTA_1	0x0002
-#define	LI_INTA_2	0x0004
-#define	LI_INTA_3	0x0008
-#define	LI_INTA_4	0x0010
-#define	LI_INTB		0x0020
-#define	LI_INTC		0x0040
-#define	LI_INTD		0x0080
-
-/* More special purpose macros... */
-static inline void li_pcia_write16(unsigned long reg, unsigned short v)
-{
-	*((volatile unsigned short *)(LI_PCIA_VADDR+reg))=v;
-}
-
-static inline unsigned short li_pcia_read16(unsigned long reg)
-{
-	 return *((volatile unsigned short *)(LI_PCIA_VADDR+reg));
-}
-
-static inline void li_pcib_write16(unsigned long reg, unsigned short v)
-{
-	*((volatile unsigned short *)(LI_PCIB_VADDR+reg))=v;
-}
-
-static inline unsigned short li_pcib_read16(unsigned long reg)
-{
-	return *((volatile unsigned short *)(LI_PCIB_VADDR+reg));
-}
-
-#endif /* _ASM_X86_VISWS_LITHIUM_H */
-
diff --git a/arch/x86/include/asm/visws/piix4.h b/arch/x86/include/asm/visws/piix4.h
deleted file mode 100644
index d0af4d338e7f..000000000000
--- a/arch/x86/include/asm/visws/piix4.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef _ASM_X86_VISWS_PIIX4_H
-#define _ASM_X86_VISWS_PIIX4_H
-
-/*
- * PIIX4 as used on SGI Visual Workstations
- */
-
-#define	PIIX_PM_START		0x0F80
-
-#define	SIO_GPIO_START		0x0FC0
-
-#define	SIO_PM_START		0x0FC8
-
-#define	PMBASE			PIIX_PM_START
-#define	GPIREG0			(PMBASE+0x30)
-#define	GPIREG(x)		(GPIREG0+((x)/8))
-#define	GPIBIT(x)		(1 << ((x)%8))
-
-#define	PIIX_GPI_BD_ID1		18
-#define	PIIX_GPI_BD_ID2		19
-#define	PIIX_GPI_BD_ID3		20
-#define	PIIX_GPI_BD_ID4		21
-#define	PIIX_GPI_BD_REG		GPIREG(PIIX_GPI_BD_ID1)
-#define	PIIX_GPI_BD_MASK	(GPIBIT(PIIX_GPI_BD_ID1) | \
-				GPIBIT(PIIX_GPI_BD_ID2) | \
-				GPIBIT(PIIX_GPI_BD_ID3) | \
-				GPIBIT(PIIX_GPI_BD_ID4) )
-
-#define	PIIX_GPI_BD_SHIFT	(PIIX_GPI_BD_ID1 % 8)
-
-#define	SIO_INDEX		0x2e
-#define	SIO_DATA		0x2f
-
-#define	SIO_DEV_SEL		0x7
-#define	SIO_DEV_ENB		0x30
-#define	SIO_DEV_MSB		0x60
-#define	SIO_DEV_LSB		0x61
-
-#define	SIO_GP_DEV		0x7
-
-#define	SIO_GP_BASE		SIO_GPIO_START
-#define	SIO_GP_MSB		(SIO_GP_BASE>>8)
-#define	SIO_GP_LSB		(SIO_GP_BASE&0xff)
-
-#define	SIO_GP_DATA1		(SIO_GP_BASE+0)
-
-#define	SIO_PM_DEV		0x8
-
-#define	SIO_PM_BASE		SIO_PM_START
-#define	SIO_PM_MSB		(SIO_PM_BASE>>8)
-#define	SIO_PM_LSB		(SIO_PM_BASE&0xff)
-#define	SIO_PM_INDEX		(SIO_PM_BASE+0)
-#define	SIO_PM_DATA		(SIO_PM_BASE+1)
-
-#define	SIO_PM_FER2		0x1
-
-#define	SIO_PM_GP_EN		0x80
-
-
-
-/*
- * This is the dev/reg where generating a config cycle will
- * result in a PCI special cycle.
- */
-#define SPECIAL_DEV		0xff
-#define SPECIAL_REG		0x00
-
-/*
- * PIIX4 needs to see a special cycle with the following data
- * to be convinced the processor has gone into the stop grant
- * state.  PIIX4 insists on seeing this before it will power
- * down a system.
- */
-#define PIIX_SPECIAL_STOP		0x00120002
-
-#define PIIX4_RESET_PORT	0xcf9
-#define PIIX4_RESET_VAL		0x6
-
-#define PMSTS_PORT		0xf80	// 2 bytes	PM Status
-#define PMEN_PORT		0xf82	// 2 bytes	PM Enable
-#define	PMCNTRL_PORT		0xf84	// 2 bytes	PM Control
-
-#define PM_SUSPEND_ENABLE	0x2000	// start sequence to suspend state
-
-/*
- * PMSTS and PMEN I/O bit definitions.
- * (Bits are the same in both registers)
- */
-#define PM_STS_RSM		(1<<15)	// Resume Status
-#define PM_STS_PWRBTNOR		(1<<11)	// Power Button Override
-#define PM_STS_RTC		(1<<10)	// RTC status
-#define PM_STS_PWRBTN		(1<<8)	// Power Button Pressed?
-#define PM_STS_GBL		(1<<5)	// Global Status
-#define PM_STS_BM		(1<<4)	// Bus Master Status
-#define PM_STS_TMROF		(1<<0)	// Timer Overflow Status.
-
-/*
- * Stop clock GPI register
- */
-#define PIIX_GPIREG0			(0xf80 + 0x30)
-
-/*
- * Stop clock GPI bit in GPIREG0
- */
-#define	PIIX_GPI_STPCLK		0x4	// STPCLK signal routed back in
-
-#endif /* _ASM_X86_VISWS_PIIX4_H */
diff --git a/arch/x86/include/asm/visws/sgivw.h b/arch/x86/include/asm/visws/sgivw.h
deleted file mode 100644
index 5fbf63e1003c..000000000000
--- a/arch/x86/include/asm/visws/sgivw.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * Frame buffer position and size:
- */
-extern unsigned long sgivwfb_mem_phys;
-extern unsigned long sgivwfb_mem_size;
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 2067264fb7f5..7004d21e6219 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -85,6 +85,7 @@
 #define VM_EXIT_SAVE_IA32_EFER                  0x00100000
 #define VM_EXIT_LOAD_IA32_EFER                  0x00200000
 #define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER       0x00400000
+#define VM_EXIT_CLEAR_BNDCFGS                   0x00800000
 
 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR	0x00036dff
 
@@ -95,6 +96,7 @@
 #define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL     0x00002000
 #define VM_ENTRY_LOAD_IA32_PAT			0x00004000
 #define VM_ENTRY_LOAD_IA32_EFER                 0x00008000
+#define VM_ENTRY_LOAD_BNDCFGS                   0x00010000
 
 #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR	0x000011ff
 
@@ -174,6 +176,8 @@ enum vmcs_field {
 	GUEST_PDPTR2_HIGH               = 0x0000280f,
 	GUEST_PDPTR3                    = 0x00002810,
 	GUEST_PDPTR3_HIGH               = 0x00002811,
+	GUEST_BNDCFGS                   = 0x00002812,
+	GUEST_BNDCFGS_HIGH              = 0x00002813,
 	HOST_IA32_PAT			= 0x00002c00,
 	HOST_IA32_PAT_HIGH		= 0x00002c01,
 	HOST_IA32_EFER			= 0x00002c02,
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index 554738963b28..d949ef28c48b 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -6,13 +6,18 @@
 
 #define XSTATE_CPUID		0x0000000d
 
-#define XSTATE_FP	0x1
-#define XSTATE_SSE	0x2
-#define XSTATE_YMM	0x4
-#define XSTATE_BNDREGS	0x8
-#define XSTATE_BNDCSR	0x10
+#define XSTATE_FP		0x1
+#define XSTATE_SSE		0x2
+#define XSTATE_YMM		0x4
+#define XSTATE_BNDREGS		0x8
+#define XSTATE_BNDCSR		0x10
+#define XSTATE_OPMASK		0x20
+#define XSTATE_ZMM_Hi256	0x40
+#define XSTATE_Hi16_ZMM		0x80
 
 #define XSTATE_FPSSE	(XSTATE_FP | XSTATE_SSE)
+/* Bit 63 of XCR0 is reserved for future expansion */
+#define XSTATE_EXTEND_MASK	(~(XSTATE_FPSSE | (1ULL << 63)))
 
 #define FXSAVE_SIZE	512
 
@@ -23,7 +28,8 @@
 #define XSAVE_YMM_OFFSET    (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
 
 /* Supported features which support lazy state saving */
-#define XSTATE_LAZY	(XSTATE_FP | XSTATE_SSE | XSTATE_YMM)
+#define XSTATE_LAZY	(XSTATE_FP | XSTATE_SSE | XSTATE_YMM		      \
+			| XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
 
 /* Supported features which require eager state saving */
 #define XSTATE_EAGER	(XSTATE_BNDREGS | XSTATE_BNDCSR)
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index c19fc60ff062..ed821ed45eb6 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -295,6 +295,7 @@
 #define MSR_SMI_COUNT			0x00000034
 #define MSR_IA32_FEATURE_CONTROL        0x0000003a
 #define MSR_IA32_TSC_ADJUST             0x0000003b
+#define MSR_IA32_BNDCFGS		0x00000d90
 
 #define FEATURE_CONTROL_LOCKED				(1<<0)
 #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX	(1<<1)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 1dac94265b59..86281ffb96d6 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -53,10 +53,6 @@ EXPORT_SYMBOL(acpi_disabled);
 # include <asm/proto.h>
 #endif				/* X86 */
 
-#define BAD_MADT_ENTRY(entry, end) (					    \
-		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-		((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
-
 #define PREFIX			"ACPI: "
 
 int acpi_noirq;				/* skip ACPI IRQ initialization */
@@ -613,10 +609,10 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 	int nid;
 
 	nid = acpi_get_node(handle);
-	if (nid == -1 || !node_online(nid))
-		return;
-	set_apicid_to_node(physid, nid);
-	numa_set_node(cpu, nid);
+	if (nid != -1) {
+		set_apicid_to_node(physid, nid);
+		numa_set_node(cpu, nid);
+	}
 #endif
 }
 
@@ -907,10 +903,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
 #ifdef	CONFIG_X86_IO_APIC
 #define MP_ISA_BUS		0
 
-#ifdef CONFIG_X86_ES7000
-extern int es7000_plat;
-#endif
-
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
 	int ioapic;
@@ -960,14 +952,6 @@ void __init mp_config_acpi_legacy_irqs(void)
 	set_bit(MP_ISA_BUS, mp_bus_not_pci);
 	pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
 
-#ifdef CONFIG_X86_ES7000
-	/*
-	 * Older generations of ES7000 have no legacy identity mappings
-	 */
-	if (es7000_plat == 1)
-		return;
-#endif
-
 	/*
 	 * Use the default configuration for the IRQs 0-15.  Unless
 	 * overridden by (MADT) interrupt source override entries.
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index e69182fd01cf..4b28159e0421 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -87,7 +87,9 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
 	num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
 
 	retval = 0;
-	if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
+	/* If the HW does not support any sub-states in this C-state */
+	if (num_cstate_subtype == 0) {
+		pr_warn(FW_BUG "ACPI MWAIT C-state 0x%x not supported by HW (0x%x)\n", cx->address, edx_part);
 		retval = -1;
 		goto out;
 	}
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index dec8de4e1663..f04dbb3069b8 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -22,6 +22,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
 	{}
 };
 EXPORT_SYMBOL(amd_nb_misc_ids);
@@ -30,6 +31,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
 	{}
 };
 
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index 0ae0323b1f9c..dcb5b15401ce 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -18,10 +18,7 @@ obj-y				+= apic_flat_64.o
 endif
 
 # APIC probe will depend on the listing order here
-obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
-obj-$(CONFIG_X86_SUMMIT)	+= summit_32.o
 obj-$(CONFIG_X86_BIGSMP)	+= bigsmp_32.o
-obj-$(CONFIG_X86_ES7000)	+= es7000_32.o
 
 # For 32bit, probe_32 need to be listed last
 obj-$(CONFIG_X86_LOCAL_APIC)	+= probe_$(BITS).o
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 7f26c9a70a9e..9edae8a8ed27 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -133,6 +133,10 @@ static inline void imcr_apic_to_pic(void)
  * +1=force-enable
  */
 static int force_enable_local_apic __initdata;
+
+/* Control whether x2APIC mode is enabled or not */
+static bool nox2apic __initdata;
+
 /*
  * APIC command line parameters
  */
@@ -162,8 +166,7 @@ int x2apic_mode;
 /* x2apic enabled before OS handover */
 int x2apic_preenabled;
 static int x2apic_disabled;
-static int nox2apic;
-static __init int setup_nox2apic(char *str)
+static int __init setup_nox2apic(char *str)
 {
 	if (x2apic_enabled()) {
 		int apicid = native_apic_msr_read(APIC_ID);
@@ -178,7 +181,7 @@ static __init int setup_nox2apic(char *str)
 	} else
 		setup_clear_cpu_cap(X86_FEATURE_X2APIC);
 
-	nox2apic = 1;
+	nox2apic = true;
 
 	return 0;
 }
@@ -2129,7 +2132,6 @@ int generic_processor_info(int apicid, int version)
 	 *
 	 * - arch/x86/kernel/mpparse.c: MP_processor_info()
 	 * - arch/x86/mm/amdtopology.c: amd_numa_init()
-	 * - arch/x86/platform/visws/visws_quirks.c: MP_processor_info()
 	 *
 	 * This function is executed with the modified
 	 * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 2c621a6b901a..7c1b29479513 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -198,7 +198,7 @@ static struct apic apic_flat =  {
 
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
@@ -314,7 +314,7 @@ static struct apic apic_physflat =  {
 
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 191ce75c0e54..8c7c98249c20 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -172,8 +172,7 @@ struct apic apic_noop = {
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-	.wait_for_init_deassert		= NULL,
-
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index 3e67f9e3d7ef..a5b45df8bc88 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -248,7 +248,7 @@ static const struct apic apic_numachip __refconst = {
 	.wakeup_secondary_cpu		= numachip_wakeup_secondary,
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL, /* REMRD not supported */
 
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index d50e3640d5ae..e4840aa7a255 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -199,8 +199,7 @@ static struct apic apic_bigsmp = {
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-	.wait_for_init_deassert		= default_wait_for_init_deassert,
-
+	.wait_for_init_deassert		= true,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
deleted file mode 100644
index c55224731b2d..000000000000
--- a/arch/x86/kernel/apic/es7000_32.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * Written by: Garry Forsgren, Unisys Corporation
- *             Natalie Protasevich, Unisys Corporation
- *
- * This file contains the code to configure and interface
- * with Unisys ES7000 series hardware system manager.
- *
- * Copyright (c) 2003 Unisys Corporation.
- * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
- *
- *   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 would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Unisys Corporation, Township Line & Union Meeting
- * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
- *
- * http://www.unisys.com
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/notifier.h>
-#include <linux/spinlock.h>
-#include <linux/cpumask.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/gfp.h>
-#include <linux/nmi.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/apicdef.h>
-#include <linux/atomic.h>
-#include <asm/fixmap.h>
-#include <asm/mpspec.h>
-#include <asm/setup.h>
-#include <asm/apic.h>
-#include <asm/ipi.h>
-
-/*
- * ES7000 chipsets
- */
-
-#define NON_UNISYS			0
-#define ES7000_CLASSIC			1
-#define ES7000_ZORRO			2
-
-#define	MIP_REG				1
-#define	MIP_PSAI_REG			4
-
-#define	MIP_BUSY			1
-#define	MIP_SPIN			0xf0000
-#define	MIP_VALID			0x0100000000000000ULL
-#define	MIP_SW_APIC			0x1020b
-
-#define	MIP_PORT(val)			((val >> 32) & 0xffff)
-
-#define	MIP_RD_LO(val)			(val & 0xffffffff)
-
-struct mip_reg {
-	unsigned long long		off_0x00;
-	unsigned long long		off_0x08;
-	unsigned long long		off_0x10;
-	unsigned long long		off_0x18;
-	unsigned long long		off_0x20;
-	unsigned long long		off_0x28;
-	unsigned long long		off_0x30;
-	unsigned long long		off_0x38;
-};
-
-struct mip_reg_info {
-	unsigned long long		mip_info;
-	unsigned long long		delivery_info;
-	unsigned long long		host_reg;
-	unsigned long long		mip_reg;
-};
-
-struct psai {
-	unsigned long long		entry_type;
-	unsigned long long		addr;
-	unsigned long long		bep_addr;
-};
-
-#ifdef CONFIG_ACPI
-
-struct es7000_oem_table {
-	struct acpi_table_header	Header;
-	u32				OEMTableAddr;
-	u32				OEMTableSize;
-};
-
-static unsigned long			oem_addrX;
-static unsigned long			oem_size;
-
-#endif
-
-/*
- * ES7000 Globals
- */
-
-static volatile unsigned long		*psai;
-static struct mip_reg			*mip_reg;
-static struct mip_reg			*host_reg;
-static int 				mip_port;
-static unsigned long			mip_addr;
-static unsigned long			host_addr;
-
-int					es7000_plat;
-
-/*
- * GSI override for ES7000 platforms.
- */
-
-
-static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
-{
-	unsigned long vect = 0, psaival = 0;
-
-	if (psai == NULL)
-		return -1;
-
-	vect = ((unsigned long)__pa(eip)/0x1000) << 16;
-	psaival = (0x1000000 | vect | cpu);
-
-	while (*psai & 0x1000000)
-		;
-
-	*psai = psaival;
-
-	return 0;
-}
-
-static int es7000_apic_is_cluster(void)
-{
-	/* MPENTIUMIII */
-	if (boot_cpu_data.x86 == 6 &&
-	    (boot_cpu_data.x86_model >= 7 && boot_cpu_data.x86_model <= 11))
-		return 1;
-
-	return 0;
-}
-
-static void setup_unisys(void)
-{
-	/*
-	 * Determine the generation of the ES7000 currently running.
-	 *
-	 * es7000_plat = 1 if the machine is a 5xx ES7000 box
-	 * es7000_plat = 2 if the machine is a x86_64 ES7000 box
-	 *
-	 */
-	if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
-		es7000_plat = ES7000_ZORRO;
-	else
-		es7000_plat = ES7000_CLASSIC;
-}
-
-/*
- * Parse the OEM Table:
- */
-static int parse_unisys_oem(char *oemptr)
-{
-	int			i;
-	int 			success = 0;
-	unsigned char		type, size;
-	unsigned long		val;
-	char			*tp = NULL;
-	struct psai		*psaip = NULL;
-	struct mip_reg_info 	*mi;
-	struct mip_reg		*host, *mip;
-
-	tp = oemptr;
-
-	tp += 8;
-
-	for (i = 0; i <= 6; i++) {
-		type = *tp++;
-		size = *tp++;
-		tp -= 2;
-		switch (type) {
-		case MIP_REG:
-			mi = (struct mip_reg_info *)tp;
-			val = MIP_RD_LO(mi->host_reg);
-			host_addr = val;
-			host = (struct mip_reg *)val;
-			host_reg = __va(host);
-			val = MIP_RD_LO(mi->mip_reg);
-			mip_port = MIP_PORT(mi->mip_info);
-			mip_addr = val;
-			mip = (struct mip_reg *)val;
-			mip_reg = __va(mip);
-			pr_debug("host_reg = 0x%lx\n",
-				 (unsigned long)host_reg);
-			pr_debug("mip_reg = 0x%lx\n",
-				 (unsigned long)mip_reg);
-			success++;
-			break;
-		case MIP_PSAI_REG:
-			psaip = (struct psai *)tp;
-			if (tp != NULL) {
-				if (psaip->addr)
-					psai = __va(psaip->addr);
-				else
-					psai = NULL;
-				success++;
-			}
-			break;
-		default:
-			break;
-		}
-		tp += size;
-	}
-
-	if (success < 2)
-		es7000_plat = NON_UNISYS;
-	else
-		setup_unisys();
-
-	return es7000_plat;
-}
-
-#ifdef CONFIG_ACPI
-static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
-{
-	struct acpi_table_header *header = NULL;
-	struct es7000_oem_table *table;
-	acpi_size tbl_size;
-	acpi_status ret;
-	int i = 0;
-
-	for (;;) {
-		ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size);
-		if (!ACPI_SUCCESS(ret))
-			return -1;
-
-		if (!memcmp((char *) &header->oem_id, "UNISYS", 6))
-			break;
-
-		early_acpi_os_unmap_memory(header, tbl_size);
-	}
-
-	table = (void *)header;
-
-	oem_addrX	= table->OEMTableAddr;
-	oem_size	= table->OEMTableSize;
-
-	early_acpi_os_unmap_memory(header, tbl_size);
-
-	*oem_addr	= (unsigned long)__acpi_map_table(oem_addrX, oem_size);
-
-	return 0;
-}
-
-static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
-{
-	if (!oem_addr)
-		return;
-
-	__acpi_unmap_table((char *)oem_addr, oem_size);
-}
-
-static int es7000_check_dsdt(void)
-{
-	struct acpi_table_header header;
-
-	if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) &&
-	    !strncmp(header.oem_id, "UNISYS", 6))
-		return 1;
-	return 0;
-}
-
-static int es7000_acpi_ret;
-
-/* Hook from generic ACPI tables.c */
-static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
-	unsigned long oem_addr = 0;
-	int check_dsdt;
-	int ret = 0;
-
-	/* check dsdt at first to avoid clear fix_map for oem_addr */
-	check_dsdt = es7000_check_dsdt();
-
-	if (!find_unisys_acpi_oem_table(&oem_addr)) {
-		if (check_dsdt) {
-			ret = parse_unisys_oem((char *)oem_addr);
-		} else {
-			setup_unisys();
-			ret = 1;
-		}
-		/*
-		 * we need to unmap it
-		 */
-		unmap_unisys_acpi_oem_table(oem_addr);
-	}
-
-	es7000_acpi_ret = ret;
-
-	return ret && !es7000_apic_is_cluster();
-}
-
-static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
-{
-	int ret = es7000_acpi_ret;
-
-	return ret && es7000_apic_is_cluster();
-}
-
-#else /* !CONFIG_ACPI: */
-static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
-	return 0;
-}
-
-static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
-{
-	return 0;
-}
-#endif /* !CONFIG_ACPI */
-
-static void es7000_spin(int n)
-{
-	int i = 0;
-
-	while (i++ < n)
-		rep_nop();
-}
-
-static int es7000_mip_write(struct mip_reg *mip_reg)
-{
-	int status = 0;
-	int spin;
-
-	spin = MIP_SPIN;
-	while ((host_reg->off_0x38 & MIP_VALID) != 0) {
-		if (--spin <= 0) {
-			WARN(1,	"Timeout waiting for Host Valid Flag\n");
-			return -1;
-		}
-		es7000_spin(MIP_SPIN);
-	}
-
-	memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
-	outb(1, mip_port);
-
-	spin = MIP_SPIN;
-
-	while ((mip_reg->off_0x38 & MIP_VALID) == 0) {
-		if (--spin <= 0) {
-			WARN(1,	"Timeout waiting for MIP Valid Flag\n");
-			return -1;
-		}
-		es7000_spin(MIP_SPIN);
-	}
-
-	status = (mip_reg->off_0x00 & 0xffff0000000000ULL) >> 48;
-	mip_reg->off_0x38 &= ~MIP_VALID;
-
-	return status;
-}
-
-static void es7000_enable_apic_mode(void)
-{
-	struct mip_reg es7000_mip_reg;
-	int mip_status;
-
-	if (!es7000_plat)
-		return;
-
-	pr_info("Enabling APIC mode.\n");
-	memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
-	es7000_mip_reg.off_0x00 = MIP_SW_APIC;
-	es7000_mip_reg.off_0x38 = MIP_VALID;
-
-	while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
-		WARN(1, "Command failed, status = %x\n", mip_status);
-}
-
-static void es7000_wait_for_init_deassert(atomic_t *deassert)
-{
-	while (!atomic_read(deassert))
-		cpu_relax();
-}
-
-static unsigned int es7000_get_apic_id(unsigned long x)
-{
-	return (x >> 24) & 0xFF;
-}
-
-static void es7000_send_IPI_mask(const struct cpumask *mask, int vector)
-{
-	default_send_IPI_mask_sequence_phys(mask, vector);
-}
-
-static void es7000_send_IPI_allbutself(int vector)
-{
-	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
-}
-
-static void es7000_send_IPI_all(int vector)
-{
-	es7000_send_IPI_mask(cpu_online_mask, vector);
-}
-
-static int es7000_apic_id_registered(void)
-{
-	return 1;
-}
-
-static const struct cpumask *target_cpus_cluster(void)
-{
-	return cpu_all_mask;
-}
-
-static const struct cpumask *es7000_target_cpus(void)
-{
-	return cpumask_of(smp_processor_id());
-}
-
-static unsigned long es7000_check_apicid_used(physid_mask_t *map, int apicid)
-{
-	return 0;
-}
-
-static unsigned long es7000_check_apicid_present(int bit)
-{
-	return physid_isset(bit, phys_cpu_present_map);
-}
-
-static int es7000_early_logical_apicid(int cpu)
-{
-	/* on es7000, logical apicid is the same as physical */
-	return early_per_cpu(x86_bios_cpu_apicid, cpu);
-}
-
-static unsigned long calculate_ldr(int cpu)
-{
-	unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
-
-	return SET_APIC_LOGICAL_ID(id);
-}
-
-/*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LdR and TPR before enabling
- * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116).  So here it goes...
- */
-static void es7000_init_apic_ldr_cluster(void)
-{
-	unsigned long val;
-	int cpu = smp_processor_id();
-
-	apic_write(APIC_DFR, APIC_DFR_CLUSTER);
-	val = calculate_ldr(cpu);
-	apic_write(APIC_LDR, val);
-}
-
-static void es7000_init_apic_ldr(void)
-{
-	unsigned long val;
-	int cpu = smp_processor_id();
-
-	apic_write(APIC_DFR, APIC_DFR_FLAT);
-	val = calculate_ldr(cpu);
-	apic_write(APIC_LDR, val);
-}
-
-static void es7000_setup_apic_routing(void)
-{
-	int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
-
-	pr_info("Enabling APIC mode:  %s. Using %d I/O APICs, target cpus %lx\n",
-		(apic_version[apic] == 0x14) ?
-			"Physical Cluster" : "Logical Cluster",
-		nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
-}
-
-static int es7000_cpu_present_to_apicid(int mps_cpu)
-{
-	if (!mps_cpu)
-		return boot_cpu_physical_apicid;
-	else if (mps_cpu < nr_cpu_ids)
-		return per_cpu(x86_bios_cpu_apicid, mps_cpu);
-	else
-		return BAD_APICID;
-}
-
-static int cpu_id;
-
-static void es7000_apicid_to_cpu_present(int phys_apicid, physid_mask_t *retmap)
-{
-	physid_set_mask_of_physid(cpu_id, retmap);
-	++cpu_id;
-}
-
-static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
-{
-	/* For clustered we don't have a good way to do this yet - hack */
-	physids_promote(0xFFL, retmap);
-}
-
-static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
-{
-	boot_cpu_physical_apicid = read_apic_id();
-	return 1;
-}
-
-static inline int
-es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
-{
-	unsigned int round = 0;
-	unsigned int cpu, uninitialized_var(apicid);
-
-	/*
-	 * The cpus in the mask must all be on the apic cluster.
-	 */
-	for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
-		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
-
-		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
-			WARN(1, "Not a valid mask!");
-
-			return -EINVAL;
-		}
-		apicid |= new_apicid;
-		round++;
-	}
-	if (!round)
-		return -EINVAL;
-	*dest_id = apicid;
-	return 0;
-}
-
-static int
-es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-			      const struct cpumask *andmask,
-			      unsigned int *apicid)
-{
-	cpumask_var_t cpumask;
-	*apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
-
-	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-		return 0;
-
-	cpumask_and(cpumask, inmask, andmask);
-	es7000_cpu_mask_to_apicid(cpumask, apicid);
-
-	free_cpumask_var(cpumask);
-
-	return 0;
-}
-
-static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
-{
-	return cpuid_apic >> index_msb;
-}
-
-static int probe_es7000(void)
-{
-	/* probed later in mptable/ACPI hooks */
-	return 0;
-}
-
-static int es7000_mps_ret;
-static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem,
-		char *productid)
-{
-	int ret = 0;
-
-	if (mpc->oemptr) {
-		struct mpc_oemtable *oem_table =
-			(struct mpc_oemtable *)mpc->oemptr;
-
-		if (!strncmp(oem, "UNISYS", 6))
-			ret = parse_unisys_oem((char *)oem_table);
-	}
-
-	es7000_mps_ret = ret;
-
-	return ret && !es7000_apic_is_cluster();
-}
-
-static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
-		char *productid)
-{
-	int ret = es7000_mps_ret;
-
-	return ret && es7000_apic_is_cluster();
-}
-
-/* We've been warned by a false positive warning.Use __refdata to keep calm. */
-static struct apic __refdata apic_es7000_cluster = {
-
-	.name				= "es7000",
-	.probe				= probe_es7000,
-	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check_cluster,
-	.apic_id_valid			= default_apic_id_valid,
-	.apic_id_registered		= es7000_apic_id_registered,
-
-	.irq_delivery_mode		= dest_LowestPrio,
-	/* logical delivery broadcast to all procs: */
-	.irq_dest_mode			= 1,
-
-	.target_cpus			= target_cpus_cluster,
-	.disable_esr			= 1,
-	.dest_logical			= 0,
-	.check_apicid_used		= es7000_check_apicid_used,
-	.check_apicid_present		= es7000_check_apicid_present,
-
-	.vector_allocation_domain	= flat_vector_allocation_domain,
-	.init_apic_ldr			= es7000_init_apic_ldr_cluster,
-
-	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
-	.setup_apic_routing		= es7000_setup_apic_routing,
-	.multi_timer_check		= NULL,
-	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
-	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
-	.setup_portio_remap		= NULL,
-	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
-	.enable_apic_mode		= es7000_enable_apic_mode,
-	.phys_pkg_id			= es7000_phys_pkg_id,
-	.mps_oem_check			= es7000_mps_oem_check_cluster,
-
-	.get_apic_id			= es7000_get_apic_id,
-	.set_apic_id			= NULL,
-	.apic_id_mask			= 0xFF << 24,
-
-	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,
-
-	.send_IPI_mask			= es7000_send_IPI_mask,
-	.send_IPI_mask_allbutself	= NULL,
-	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
-	.send_IPI_all			= es7000_send_IPI_all,
-	.send_IPI_self			= default_send_IPI_self,
-
-	.wakeup_secondary_cpu		= wakeup_secondary_cpu_via_mip,
-
-	.trampoline_phys_low		= 0x467,
-	.trampoline_phys_high		= 0x469,
-
-	.wait_for_init_deassert		= NULL,
-
-	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
-	.smp_callin_clear_local_apic	= NULL,
-	.inquire_remote_apic		= default_inquire_remote_apic,
-
-	.read				= native_apic_mem_read,
-	.write				= native_apic_mem_write,
-	.eoi_write			= native_apic_mem_write,
-	.icr_read			= native_apic_icr_read,
-	.icr_write			= native_apic_icr_write,
-	.wait_icr_idle			= native_apic_wait_icr_idle,
-	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
-
-	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
-};
-
-static struct apic __refdata apic_es7000 = {
-
-	.name				= "es7000",
-	.probe				= probe_es7000,
-	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check,
-	.apic_id_valid			= default_apic_id_valid,
-	.apic_id_registered		= es7000_apic_id_registered,
-
-	.irq_delivery_mode		= dest_Fixed,
-	/* phys delivery to target CPUs: */
-	.irq_dest_mode			= 0,
-
-	.target_cpus			= es7000_target_cpus,
-	.disable_esr			= 1,
-	.dest_logical			= 0,
-	.check_apicid_used		= es7000_check_apicid_used,
-	.check_apicid_present		= es7000_check_apicid_present,
-
-	.vector_allocation_domain	= flat_vector_allocation_domain,
-	.init_apic_ldr			= es7000_init_apic_ldr,
-
-	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
-	.setup_apic_routing		= es7000_setup_apic_routing,
-	.multi_timer_check		= NULL,
-	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
-	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
-	.setup_portio_remap		= NULL,
-	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
-	.enable_apic_mode		= es7000_enable_apic_mode,
-	.phys_pkg_id			= es7000_phys_pkg_id,
-	.mps_oem_check			= es7000_mps_oem_check,
-
-	.get_apic_id			= es7000_get_apic_id,
-	.set_apic_id			= NULL,
-	.apic_id_mask			= 0xFF << 24,
-
-	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,
-
-	.send_IPI_mask			= es7000_send_IPI_mask,
-	.send_IPI_mask_allbutself	= NULL,
-	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
-	.send_IPI_all			= es7000_send_IPI_all,
-	.send_IPI_self			= default_send_IPI_self,
-
-	.trampoline_phys_low		= 0x467,
-	.trampoline_phys_high		= 0x469,
-
-	.wait_for_init_deassert		= es7000_wait_for_init_deassert,
-
-	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
-	.smp_callin_clear_local_apic	= NULL,
-	.inquire_remote_apic		= default_inquire_remote_apic,
-
-	.read				= native_apic_mem_read,
-	.write				= native_apic_mem_write,
-	.eoi_write			= native_apic_mem_write,
-	.icr_read			= native_apic_icr_read,
-	.icr_write			= native_apic_icr_write,
-	.wait_icr_idle			= native_apic_wait_icr_idle,
-	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
-
-	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
-};
-
-/*
- * Need to check for es7000 followed by es7000_cluster, so this order
- * in apic_drivers is important.
- */
-apic_drivers(apic_es7000, apic_es7000_cluster);
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
deleted file mode 100644
index 1e42e8f305ee..000000000000
--- a/arch/x86/kernel/apic/numaq_32.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Written by: Patricia Gaughen, IBM Corporation
- *
- * Copyright (C) 2002, IBM Corp.
- * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU 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.
- *
- * Send feedback to <gone@us.ibm.com>
- */
-#include <linux/nodemask.h>
-#include <linux/topology.h>
-#include <linux/bootmem.h>
-#include <linux/memblock.h>
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/kernel.h>
-#include <linux/mmzone.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/numa.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/mm.h>
-
-#include <asm/processor.h>
-#include <asm/fixmap.h>
-#include <asm/mpspec.h>
-#include <asm/numaq.h>
-#include <asm/setup.h>
-#include <asm/apic.h>
-#include <asm/e820.h>
-#include <asm/ipi.h>
-
-int found_numaq;
-
-/*
- * Have to match translation table entries to main table entries by counter
- * hence the mpc_record variable .... can't see a less disgusting way of
- * doing this ....
- */
-struct mpc_trans {
-	unsigned char			mpc_type;
-	unsigned char			trans_len;
-	unsigned char			trans_type;
-	unsigned char			trans_quad;
-	unsigned char			trans_global;
-	unsigned char			trans_local;
-	unsigned short			trans_reserved;
-};
-
-static int				mpc_record;
-
-static struct mpc_trans			*translation_table[MAX_MPC_ENTRY];
-
-int					mp_bus_id_to_node[MAX_MP_BUSSES];
-int					mp_bus_id_to_local[MAX_MP_BUSSES];
-int					quad_local_to_mp_bus_id[NR_CPUS/4][4];
-
-
-static inline void numaq_register_node(int node, struct sys_cfg_data *scd)
-{
-	struct eachquadmem *eq = scd->eq + node;
-	u64 start = (u64)(eq->hi_shrd_mem_start - eq->priv_mem_size) << 20;
-	u64 end = (u64)(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size) << 20;
-	int ret;
-
-	node_set(node, numa_nodes_parsed);
-	ret = numa_add_memblk(node, start, end);
-	BUG_ON(ret < 0);
-}
-
-/*
- * Function: smp_dump_qct()
- *
- * Description: gets memory layout from the quad config table.  This
- * function also updates numa_nodes_parsed with the nodes (quads) present.
- */
-static void __init smp_dump_qct(void)
-{
-	struct sys_cfg_data *scd;
-	int node;
-
-	scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR);
-
-	for_each_node(node) {
-		if (scd->quads_present31_0 & (1 << node))
-			numaq_register_node(node, scd);
-	}
-}
-
-void numaq_tsc_disable(void)
-{
-	if (!found_numaq)
-		return;
-
-	if (num_online_nodes() > 1) {
-		printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
-		setup_clear_cpu_cap(X86_FEATURE_TSC);
-	}
-}
-
-static void __init numaq_tsc_init(void)
-{
-	numaq_tsc_disable();
-}
-
-static inline int generate_logical_apicid(int quad, int phys_apicid)
-{
-	return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
-}
-
-/* x86_quirks member */
-static int mpc_apic_id(struct mpc_cpu *m)
-{
-	int quad = translation_table[mpc_record]->trans_quad;
-	int logical_apicid = generate_logical_apicid(quad, m->apicid);
-
-	printk(KERN_DEBUG
-		"Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
-		 m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
-		(m->cpufeature & CPU_MODEL_MASK) >> 4,
-		 m->apicver, quad, logical_apicid);
-
-	return logical_apicid;
-}
-
-/* x86_quirks member */
-static void mpc_oem_bus_info(struct mpc_bus *m, char *name)
-{
-	int quad = translation_table[mpc_record]->trans_quad;
-	int local = translation_table[mpc_record]->trans_local;
-
-	mp_bus_id_to_node[m->busid] = quad;
-	mp_bus_id_to_local[m->busid] = local;
-
-	printk(KERN_INFO "Bus #%d is %s (node %d)\n", m->busid, name, quad);
-}
-
-/* x86_quirks member */
-static void mpc_oem_pci_bus(struct mpc_bus *m)
-{
-	int quad = translation_table[mpc_record]->trans_quad;
-	int local = translation_table[mpc_record]->trans_local;
-
-	quad_local_to_mp_bus_id[quad][local] = m->busid;
-}
-
-/*
- * Called from mpparse code.
- * mode = 0: prescan
- * mode = 1: one mpc entry scanned
- */
-static void numaq_mpc_record(unsigned int mode)
-{
-	if (!mode)
-		mpc_record = 0;
-	else
-		mpc_record++;
-}
-
-static void __init MP_translation_info(struct mpc_trans *m)
-{
-	printk(KERN_INFO
-	    "Translation: record %d, type %d, quad %d, global %d, local %d\n",
-	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
-	       m->trans_local);
-
-	if (mpc_record >= MAX_MPC_ENTRY)
-		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
-	else
-		translation_table[mpc_record] = m; /* stash this for later */
-
-	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
-		node_set_online(m->trans_quad);
-}
-
-static int __init mpf_checksum(unsigned char *mp, int len)
-{
-	int sum = 0;
-
-	while (len--)
-		sum += *mp++;
-
-	return sum & 0xFF;
-}
-
-/*
- * Read/parse the MPC oem tables
- */
-static void __init smp_read_mpc_oem(struct mpc_table *mpc)
-{
-	struct mpc_oemtable *oemtable = (void *)(long)mpc->oemptr;
-	int count = sizeof(*oemtable);	/* the header size */
-	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
-
-	mpc_record = 0;
-	printk(KERN_INFO
-		"Found an OEM MPC table at %8p - parsing it...\n", oemtable);
-
-	if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) {
-		printk(KERN_WARNING
-		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
-		       oemtable->signature[0], oemtable->signature[1],
-		       oemtable->signature[2], oemtable->signature[3]);
-		return;
-	}
-
-	if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) {
-		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
-		return;
-	}
-
-	while (count < oemtable->length) {
-		switch (*oemptr) {
-		case MP_TRANSLATION:
-			{
-				struct mpc_trans *m = (void *)oemptr;
-
-				MP_translation_info(m);
-				oemptr += sizeof(*m);
-				count += sizeof(*m);
-				++mpc_record;
-				break;
-			}
-		default:
-			printk(KERN_WARNING
-			       "Unrecognised OEM table entry type! - %d\n",
-			       (int)*oemptr);
-			return;
-		}
-	}
-}
-
-static __init void early_check_numaq(void)
-{
-	/*
-	 * get boot-time SMP configuration:
-	 */
-	if (smp_found_config)
-		early_get_smp_config();
-
-	if (found_numaq) {
-		x86_init.mpparse.mpc_record = numaq_mpc_record;
-		x86_init.mpparse.setup_ioapic_ids = x86_init_noop;
-		x86_init.mpparse.mpc_apic_id = mpc_apic_id;
-		x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem;
-		x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
-		x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
-		x86_init.timers.tsc_pre_init = numaq_tsc_init;
-		x86_init.pci.init = pci_numaq_init;
-	}
-}
-
-int __init numaq_numa_init(void)
-{
-	early_check_numaq();
-	if (!found_numaq)
-		return -ENOENT;
-	smp_dump_qct();
-
-	return 0;
-}
-
-#define NUMAQ_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
-
-static inline unsigned int numaq_get_apic_id(unsigned long x)
-{
-	return (x >> 24) & 0x0F;
-}
-
-static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector)
-{
-	default_send_IPI_mask_sequence_logical(mask, vector);
-}
-
-static inline void numaq_send_IPI_allbutself(int vector)
-{
-	default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector);
-}
-
-static inline void numaq_send_IPI_all(int vector)
-{
-	numaq_send_IPI_mask(cpu_online_mask, vector);
-}
-
-#define NUMAQ_TRAMPOLINE_PHYS_LOW	(0x8)
-#define NUMAQ_TRAMPOLINE_PHYS_HIGH	(0xa)
-
-/*
- * Because we use NMIs rather than the INIT-STARTUP sequence to
- * bootstrap the CPUs, the APIC may be in a weird state. Kick it:
- */
-static inline void numaq_smp_callin_clear_local_apic(void)
-{
-	clear_local_APIC();
-}
-
-static inline const struct cpumask *numaq_target_cpus(void)
-{
-	return cpu_all_mask;
-}
-
-static unsigned long numaq_check_apicid_used(physid_mask_t *map, int apicid)
-{
-	return physid_isset(apicid, *map);
-}
-
-static inline unsigned long numaq_check_apicid_present(int bit)
-{
-	return physid_isset(bit, phys_cpu_present_map);
-}
-
-static inline int numaq_apic_id_registered(void)
-{
-	return 1;
-}
-
-static inline void numaq_init_apic_ldr(void)
-{
-	/* Already done in NUMA-Q firmware */
-}
-
-static inline void numaq_setup_apic_routing(void)
-{
-	printk(KERN_INFO
-		"Enabling APIC mode:  NUMA-Q.  Using %d I/O APICs\n",
-		nr_ioapics);
-}
-
-/*
- * Skip adding the timer int on secondary nodes, which causes
- * a small but painful rift in the time-space continuum.
- */
-static inline int numaq_multi_timer_check(int apic, int irq)
-{
-	return apic != 0 && irq == 0;
-}
-
-static inline void numaq_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
-{
-	/* We don't have a good way to do this yet - hack */
-	return physids_promote(0xFUL, retmap);
-}
-
-/*
- * Supporting over 60 cpus on NUMA-Q requires a locality-dependent
- * cpu to APIC ID relation to properly interact with the intelligent
- * mode of the cluster controller.
- */
-static inline int numaq_cpu_present_to_apicid(int mps_cpu)
-{
-	if (mps_cpu < 60)
-		return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3));
-	else
-		return BAD_APICID;
-}
-
-static inline int numaq_apicid_to_node(int logical_apicid)
-{
-	return logical_apicid >> 4;
-}
-
-static int numaq_numa_cpu_node(int cpu)
-{
-	int logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
-
-	if (logical_apicid != BAD_APICID)
-		return numaq_apicid_to_node(logical_apicid);
-	return NUMA_NO_NODE;
-}
-
-static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap)
-{
-	int node = numaq_apicid_to_node(logical_apicid);
-	int cpu = __ffs(logical_apicid & 0xf);
-
-	physid_set_mask_of_physid(cpu + 4*node, retmap);
-}
-
-/* Where the IO area was mapped on multiquad, always 0 otherwise */
-void *xquad_portio;
-
-static inline int numaq_check_phys_apicid_present(int phys_apicid)
-{
-	return 1;
-}
-
-/*
- * We use physical apicids here, not logical, so just return the default
- * physical broadcast to stop people from breaking us
- */
-static int
-numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-			     const struct cpumask *andmask,
-			     unsigned int *apicid)
-{
-	*apicid = 0x0F;
-	return 0;
-}
-
-/* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */
-static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb)
-{
-	return cpuid_apic >> index_msb;
-}
-
-static int
-numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
-{
-	if (strncmp(oem, "IBM NUMA", 8))
-		printk(KERN_ERR "Warning! Not a NUMA-Q system!\n");
-	else
-		found_numaq = 1;
-
-	return found_numaq;
-}
-
-static int probe_numaq(void)
-{
-	/* already know from get_memcfg_numaq() */
-	return found_numaq;
-}
-
-static void numaq_setup_portio_remap(void)
-{
-	int num_quads = num_online_nodes();
-
-	if (num_quads <= 1)
-		return;
-
-	printk(KERN_INFO
-		"Remapping cross-quad port I/O for %d quads\n", num_quads);
-
-	xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD);
-
-	printk(KERN_INFO
-		"xquad_portio vaddr 0x%08lx, len %08lx\n",
-		(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
-}
-
-/* Use __refdata to keep false positive warning calm.  */
-static struct apic __refdata apic_numaq = {
-
-	.name				= "NUMAQ",
-	.probe				= probe_numaq,
-	.acpi_madt_oem_check		= NULL,
-	.apic_id_valid			= default_apic_id_valid,
-	.apic_id_registered		= numaq_apic_id_registered,
-
-	.irq_delivery_mode		= dest_LowestPrio,
-	/* physical delivery on LOCAL quad: */
-	.irq_dest_mode			= 0,
-
-	.target_cpus			= numaq_target_cpus,
-	.disable_esr			= 1,
-	.dest_logical			= APIC_DEST_LOGICAL,
-	.check_apicid_used		= numaq_check_apicid_used,
-	.check_apicid_present		= numaq_check_apicid_present,
-
-	.vector_allocation_domain	= flat_vector_allocation_domain,
-	.init_apic_ldr			= numaq_init_apic_ldr,
-
-	.ioapic_phys_id_map		= numaq_ioapic_phys_id_map,
-	.setup_apic_routing		= numaq_setup_apic_routing,
-	.multi_timer_check		= numaq_multi_timer_check,
-	.cpu_present_to_apicid		= numaq_cpu_present_to_apicid,
-	.apicid_to_cpu_present		= numaq_apicid_to_cpu_present,
-	.setup_portio_remap		= numaq_setup_portio_remap,
-	.check_phys_apicid_present	= numaq_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
-	.phys_pkg_id			= numaq_phys_pkg_id,
-	.mps_oem_check			= numaq_mps_oem_check,
-
-	.get_apic_id			= numaq_get_apic_id,
-	.set_apic_id			= NULL,
-	.apic_id_mask			= 0x0F << 24,
-
-	.cpu_mask_to_apicid_and		= numaq_cpu_mask_to_apicid_and,
-
-	.send_IPI_mask			= numaq_send_IPI_mask,
-	.send_IPI_mask_allbutself	= NULL,
-	.send_IPI_allbutself		= numaq_send_IPI_allbutself,
-	.send_IPI_all			= numaq_send_IPI_all,
-	.send_IPI_self			= default_send_IPI_self,
-
-	.wakeup_secondary_cpu		= wakeup_secondary_cpu_via_nmi,
-	.trampoline_phys_low		= NUMAQ_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= NUMAQ_TRAMPOLINE_PHYS_HIGH,
-
-	/* We don't do anything here because we use NMI's to boot instead */
-	.wait_for_init_deassert		= NULL,
-
-	.smp_callin_clear_local_apic	= numaq_smp_callin_clear_local_apic,
-	.inquire_remote_apic		= NULL,
-
-	.read				= native_apic_mem_read,
-	.write				= native_apic_mem_write,
-	.eoi_write			= native_apic_mem_write,
-	.icr_read			= native_apic_icr_read,
-	.icr_write			= native_apic_icr_write,
-	.wait_icr_idle			= native_apic_wait_icr_idle,
-	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
-
-	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid,
-	.x86_32_numa_cpu_node		= numaq_numa_cpu_node,
-};
-
-apic_driver(apic_numaq);
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index eb35ef9ee63f..cceb352c968c 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -119,8 +119,7 @@ static struct apic apic_default = {
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-	.wait_for_init_deassert		= default_wait_for_init_deassert,
-
+	.wait_for_init_deassert		= true,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
deleted file mode 100644
index 00146f9b0254..000000000000
--- a/arch/x86/kernel/apic/summit_32.c
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * IBM Summit-Specific Code
- *
- * Written By: Matthew Dobson, IBM Corporation
- *
- * Copyright (c) 2003 IBM Corp.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU 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.
- *
- * Send feedback to <colpatch@us.ibm.com>
- *
- */
-
-#define pr_fmt(fmt) "summit: %s: " fmt, __func__
-
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/bios_ebda.h>
-
-/*
- * APIC driver for the IBM "Summit" chipset.
- */
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/apic.h>
-#include <asm/smp.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/ipi.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/gfp.h>
-#include <linux/smp.h>
-
-static unsigned summit_get_apic_id(unsigned long x)
-{
-	return (x >> 24) & 0xFF;
-}
-
-static inline void summit_send_IPI_mask(const struct cpumask *mask, int vector)
-{
-	default_send_IPI_mask_sequence_logical(mask, vector);
-}
-
-static void summit_send_IPI_allbutself(int vector)
-{
-	default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector);
-}
-
-static void summit_send_IPI_all(int vector)
-{
-	summit_send_IPI_mask(cpu_online_mask, vector);
-}
-
-#include <asm/tsc.h>
-
-extern int use_cyclone;
-
-#ifdef CONFIG_X86_SUMMIT_NUMA
-static void setup_summit(void);
-#else
-static inline void setup_summit(void) {}
-#endif
-
-static int summit_mps_oem_check(struct mpc_table *mpc, char *oem,
-		char *productid)
-{
-	if (!strncmp(oem, "IBM ENSW", 8) &&
-			(!strncmp(productid, "VIGIL SMP", 9)
-			 || !strncmp(productid, "EXA", 3)
-			 || !strncmp(productid, "RUTHLESS SMP", 12))){
-		mark_tsc_unstable("Summit based system");
-		use_cyclone = 1; /*enable cyclone-timer*/
-		setup_summit();
-		return 1;
-	}
-	return 0;
-}
-
-/* Hook from generic ACPI tables.c */
-static int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
-	if (!strncmp(oem_id, "IBM", 3) &&
-	    (!strncmp(oem_table_id, "SERVIGIL", 8)
-	     || !strncmp(oem_table_id, "EXA", 3))){
-		mark_tsc_unstable("Summit based system");
-		use_cyclone = 1; /*enable cyclone-timer*/
-		setup_summit();
-		return 1;
-	}
-	return 0;
-}
-
-struct rio_table_hdr {
-	unsigned char version;      /* Version number of this data structure           */
-	                            /* Version 3 adds chassis_num & WP_index           */
-	unsigned char num_scal_dev; /* # of Scalability devices (Twisters for Vigil)   */
-	unsigned char num_rio_dev;  /* # of RIO I/O devices (Cyclones and Winnipegs)   */
-} __attribute__((packed));
-
-struct scal_detail {
-	unsigned char node_id;      /* Scalability Node ID                             */
-	unsigned long CBAR;         /* Address of 1MB register space                   */
-	unsigned char port0node;    /* Node ID port connected to: 0xFF=None            */
-	unsigned char port0port;    /* Port num port connected to: 0,1,2, or 0xFF=None */
-	unsigned char port1node;    /* Node ID port connected to: 0xFF = None          */
-	unsigned char port1port;    /* Port num port connected to: 0,1,2, or 0xFF=None */
-	unsigned char port2node;    /* Node ID port connected to: 0xFF = None          */
-	unsigned char port2port;    /* Port num port connected to: 0,1,2, or 0xFF=None */
-	unsigned char chassis_num;  /* 1 based Chassis number (1 = boot node)          */
-} __attribute__((packed));
-
-struct rio_detail {
-	unsigned char node_id;      /* RIO Node ID                                     */
-	unsigned long BBAR;         /* Address of 1MB register space                   */
-	unsigned char type;         /* Type of device                                  */
-	unsigned char owner_id;     /* For WPEG: Node ID of Cyclone that owns this WPEG*/
-	                            /* For CYC:  Node ID of Twister that owns this CYC */
-	unsigned char port0node;    /* Node ID port connected to: 0xFF=None            */
-	unsigned char port0port;    /* Port num port connected to: 0,1,2, or 0xFF=None */
-	unsigned char port1node;    /* Node ID port connected to: 0xFF=None            */
-	unsigned char port1port;    /* Port num port connected to: 0,1,2, or 0xFF=None */
-	unsigned char first_slot;   /* For WPEG: Lowest slot number below this WPEG    */
-	                            /* For CYC:  0                                     */
-	unsigned char status;       /* For WPEG: Bit 0 = 1 : the XAPIC is used         */
-	                            /*                 = 0 : the XAPIC is not used, ie:*/
-	                            /*                     ints fwded to another XAPIC */
-	                            /*           Bits1:7 Reserved                      */
-	                            /* For CYC:  Bits0:7 Reserved                      */
-	unsigned char WP_index;     /* For WPEG: WPEG instance index - lower ones have */
-	                            /*           lower slot numbers/PCI bus numbers    */
-	                            /* For CYC:  No meaning                            */
-	unsigned char chassis_num;  /* 1 based Chassis number                          */
-	                            /* For LookOut WPEGs this field indicates the      */
-	                            /* Expansion Chassis #, enumerated from Boot       */
-	                            /* Node WPEG external port, then Boot Node CYC     */
-	                            /* external port, then Next Vigil chassis WPEG     */
-	                            /* external port, etc.                             */
-	                            /* Shared Lookouts have only 1 chassis number (the */
-	                            /* first one assigned)                             */
-} __attribute__((packed));
-
-
-typedef enum {
-	CompatTwister = 0,  /* Compatibility Twister               */
-	AltTwister    = 1,  /* Alternate Twister of internal 8-way */
-	CompatCyclone = 2,  /* Compatibility Cyclone               */
-	AltCyclone    = 3,  /* Alternate Cyclone of internal 8-way */
-	CompatWPEG    = 4,  /* Compatibility WPEG                  */
-	AltWPEG       = 5,  /* Second Planar WPEG                  */
-	LookOutAWPEG  = 6,  /* LookOut WPEG                        */
-	LookOutBWPEG  = 7,  /* LookOut WPEG                        */
-} node_type;
-
-static inline int is_WPEG(struct rio_detail *rio){
-	return (rio->type == CompatWPEG || rio->type == AltWPEG ||
-		rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
-}
-
-#define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
-
-static const struct cpumask *summit_target_cpus(void)
-{
-	/* CPU_MASK_ALL (0xff) has undefined behaviour with
-	 * dest_LowestPrio mode logical clustered apic interrupt routing
-	 * Just start on cpu 0.  IRQ balancing will spread load
-	 */
-	return cpumask_of(0);
-}
-
-static unsigned long summit_check_apicid_used(physid_mask_t *map, int apicid)
-{
-	return 0;
-}
-
-/* we don't use the phys_cpu_present_map to indicate apicid presence */
-static unsigned long summit_check_apicid_present(int bit)
-{
-	return 1;
-}
-
-static int summit_early_logical_apicid(int cpu)
-{
-	int count = 0;
-	u8 my_id = early_per_cpu(x86_cpu_to_apicid, cpu);
-	u8 my_cluster = APIC_CLUSTER(my_id);
-#ifdef CONFIG_SMP
-	u8 lid;
-	int i;
-
-	/* Create logical APIC IDs by counting CPUs already in cluster. */
-	for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
-		lid = early_per_cpu(x86_cpu_to_logical_apicid, i);
-		if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
-			++count;
-	}
-#endif
-	/* We only have a 4 wide bitmap in cluster mode.  If a deranged
-	 * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
-	BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
-	return my_cluster | (1UL << count);
-}
-
-static void summit_init_apic_ldr(void)
-{
-	int cpu = smp_processor_id();
-	unsigned long id = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
-	unsigned long val;
-
-	apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE);
-	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
-	val |= SET_APIC_LOGICAL_ID(id);
-	apic_write(APIC_LDR, val);
-}
-
-static int summit_apic_id_registered(void)
-{
-	return 1;
-}
-
-static void summit_setup_apic_routing(void)
-{
-	pr_info("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
-		nr_ioapics);
-}
-
-static int summit_cpu_present_to_apicid(int mps_cpu)
-{
-	if (mps_cpu < nr_cpu_ids)
-		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
-	else
-		return BAD_APICID;
-}
-
-static void summit_ioapic_phys_id_map(physid_mask_t *phys_id_map, physid_mask_t *retmap)
-{
-	/* For clustered we don't have a good way to do this yet - hack */
-	physids_promote(0x0FL, retmap);
-}
-
-static void summit_apicid_to_cpu_present(int apicid, physid_mask_t *retmap)
-{
-	physid_set_mask_of_physid(0, retmap);
-}
-
-static int summit_check_phys_apicid_present(int physical_apicid)
-{
-	return 1;
-}
-
-static inline int
-summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
-{
-	unsigned int round = 0;
-	unsigned int cpu, apicid = 0;
-
-	/*
-	 * The cpus in the mask must all be on the apic cluster.
-	 */
-	for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
-		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
-
-		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
-			pr_err("Not a valid mask!\n");
-			return -EINVAL;
-		}
-		apicid |= new_apicid;
-		round++;
-	}
-	if (!round)
-		return -EINVAL;
-	*dest_id = apicid;
-	return 0;
-}
-
-static int
-summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-			      const struct cpumask *andmask,
-			      unsigned int *apicid)
-{
-	cpumask_var_t cpumask;
-	*apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
-
-	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-		return 0;
-
-	cpumask_and(cpumask, inmask, andmask);
-	summit_cpu_mask_to_apicid(cpumask, apicid);
-
-	free_cpumask_var(cpumask);
-
-	return 0;
-}
-
-/*
- * cpuid returns the value latched in the HW at reset, not the APIC ID
- * register's value.  For any box whose BIOS changes APIC IDs, like
- * clustered APIC systems, we must use hard_smp_processor_id.
- *
- * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
- */
-static int summit_phys_pkg_id(int cpuid_apic, int index_msb)
-{
-	return hard_smp_processor_id() >> index_msb;
-}
-
-static int probe_summit(void)
-{
-	/* probed later in mptable/ACPI hooks */
-	return 0;
-}
-
-#ifdef CONFIG_X86_SUMMIT_NUMA
-static struct rio_table_hdr *rio_table_hdr;
-static struct scal_detail   *scal_devs[MAX_NUMNODES];
-static struct rio_detail    *rio_devs[MAX_NUMNODES*4];
-
-#ifndef CONFIG_X86_NUMAQ
-static int mp_bus_id_to_node[MAX_MP_BUSSES];
-#endif
-
-static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
-{
-	int twister = 0, node = 0;
-	int i, bus, num_buses;
-
-	for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
-		if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) {
-			twister = rio_devs[i]->owner_id;
-			break;
-		}
-	}
-	if (i == rio_table_hdr->num_rio_dev) {
-		pr_err("Couldn't find owner Cyclone for Winnipeg!\n");
-		return last_bus;
-	}
-
-	for (i = 0; i < rio_table_hdr->num_scal_dev; i++) {
-		if (scal_devs[i]->node_id == twister) {
-			node = scal_devs[i]->node_id;
-			break;
-		}
-	}
-	if (i == rio_table_hdr->num_scal_dev) {
-		pr_err("Couldn't find owner Twister for Cyclone!\n");
-		return last_bus;
-	}
-
-	switch (rio_devs[wpeg_num]->type) {
-	case CompatWPEG:
-		/*
-		 * The Compatibility Winnipeg controls the 2 legacy buses,
-		 * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case
-		 * a PCI-PCI bridge card is used in either slot: total 5 buses.
-		 */
-		num_buses = 5;
-		break;
-	case AltWPEG:
-		/*
-		 * The Alternate Winnipeg controls the 2 133MHz buses [1 slot
-		 * each], their 2 "extra" buses, the 100MHz bus [2 slots] and
-		 * the "extra" buses for each of those slots: total 7 buses.
-		 */
-		num_buses = 7;
-		break;
-	case LookOutAWPEG:
-	case LookOutBWPEG:
-		/*
-		 * A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
-		 * & the "extra" buses for each of those slots: total 9 buses.
-		 */
-		num_buses = 9;
-		break;
-	default:
-		pr_info("Unsupported Winnipeg type!\n");
-		return last_bus;
-	}
-
-	for (bus = last_bus; bus < last_bus + num_buses; bus++)
-		mp_bus_id_to_node[bus] = node;
-	return bus;
-}
-
-static int build_detail_arrays(void)
-{
-	unsigned long ptr;
-	int i, scal_detail_size, rio_detail_size;
-
-	if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
-		pr_warn("MAX_NUMNODES too low!  Defined as %d, but system has %d nodes\n",
-			MAX_NUMNODES, rio_table_hdr->num_scal_dev);
-		return 0;
-	}
-
-	switch (rio_table_hdr->version) {
-	default:
-		pr_warn("Invalid Rio Grande Table Version: %d\n",
-			rio_table_hdr->version);
-		return 0;
-	case 2:
-		scal_detail_size = 11;
-		rio_detail_size = 13;
-		break;
-	case 3:
-		scal_detail_size = 12;
-		rio_detail_size = 15;
-		break;
-	}
-
-	ptr = (unsigned long)rio_table_hdr + 3;
-	for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
-		scal_devs[i] = (struct scal_detail *)ptr;
-
-	for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
-		rio_devs[i] = (struct rio_detail *)ptr;
-
-	return 1;
-}
-
-void setup_summit(void)
-{
-	unsigned long		ptr;
-	unsigned short		offset;
-	int			i, next_wpeg, next_bus = 0;
-
-	/* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
-	ptr = get_bios_ebda();
-	ptr = (unsigned long)phys_to_virt(ptr);
-
-	rio_table_hdr = NULL;
-	offset = 0x180;
-	while (offset) {
-		/* The block id is stored in the 2nd word */
-		if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) {
-			/* set the pointer past the offset & block id */
-			rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
-			break;
-		}
-		/* The next offset is stored in the 1st word.  0 means no more */
-		offset = *((unsigned short *)(ptr + offset));
-	}
-	if (!rio_table_hdr) {
-		pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n");
-		return;
-	}
-
-	if (!build_detail_arrays())
-		return;
-
-	/* The first Winnipeg we're looking for has an index of 0 */
-	next_wpeg = 0;
-	do {
-		for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
-			if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) {
-				/* It's the Winnipeg we're looking for! */
-				next_bus = setup_pci_node_map_for_wpeg(i, next_bus);
-				next_wpeg++;
-				break;
-			}
-		}
-		/*
-		 * If we go through all Rio devices and don't find one with
-		 * the next index, it means we've found all the Winnipegs,
-		 * and thus all the PCI buses.
-		 */
-		if (i == rio_table_hdr->num_rio_dev)
-			next_wpeg = 0;
-	} while (next_wpeg != 0);
-}
-#endif
-
-static struct apic apic_summit = {
-
-	.name				= "summit",
-	.probe				= probe_summit,
-	.acpi_madt_oem_check		= summit_acpi_madt_oem_check,
-	.apic_id_valid			= default_apic_id_valid,
-	.apic_id_registered		= summit_apic_id_registered,
-
-	.irq_delivery_mode		= dest_LowestPrio,
-	/* logical delivery broadcast to all CPUs: */
-	.irq_dest_mode			= 1,
-
-	.target_cpus			= summit_target_cpus,
-	.disable_esr			= 1,
-	.dest_logical			= APIC_DEST_LOGICAL,
-	.check_apicid_used		= summit_check_apicid_used,
-	.check_apicid_present		= summit_check_apicid_present,
-
-	.vector_allocation_domain	= flat_vector_allocation_domain,
-	.init_apic_ldr			= summit_init_apic_ldr,
-
-	.ioapic_phys_id_map		= summit_ioapic_phys_id_map,
-	.setup_apic_routing		= summit_setup_apic_routing,
-	.multi_timer_check		= NULL,
-	.cpu_present_to_apicid		= summit_cpu_present_to_apicid,
-	.apicid_to_cpu_present		= summit_apicid_to_cpu_present,
-	.setup_portio_remap		= NULL,
-	.check_phys_apicid_present	= summit_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
-	.phys_pkg_id			= summit_phys_pkg_id,
-	.mps_oem_check			= summit_mps_oem_check,
-
-	.get_apic_id			= summit_get_apic_id,
-	.set_apic_id			= NULL,
-	.apic_id_mask			= 0xFF << 24,
-
-	.cpu_mask_to_apicid_and		= summit_cpu_mask_to_apicid_and,
-
-	.send_IPI_mask			= summit_send_IPI_mask,
-	.send_IPI_mask_allbutself	= NULL,
-	.send_IPI_allbutself		= summit_send_IPI_allbutself,
-	.send_IPI_all			= summit_send_IPI_all,
-	.send_IPI_self			= default_send_IPI_self,
-
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
-	.wait_for_init_deassert		= default_wait_for_init_deassert,
-
-	.smp_callin_clear_local_apic	= NULL,
-	.inquire_remote_apic		= default_inquire_remote_apic,
-
-	.read				= native_apic_mem_read,
-	.write				= native_apic_mem_write,
-	.eoi_write			= native_apic_mem_write,
-	.icr_read			= native_apic_icr_read,
-	.icr_write			= native_apic_icr_write,
-	.wait_icr_idle			= native_apic_wait_icr_idle,
-	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
-
-	.x86_32_early_logical_apicid	= summit_early_logical_apicid,
-};
-
-apic_driver(apic_summit);
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index cac85ee6913f..e66766bf1641 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -279,7 +279,7 @@ static struct apic apic_x2apic_cluster = {
 
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index de231e328cae..6d600ebf6c12 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -133,7 +133,7 @@ static struct apic apic_x2apic_phys = {
 
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index d263b1307de1..7834389ba5be 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -396,7 +396,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
 	.wakeup_secondary_cpu		= uv_wakeup_secondary,
 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-	.wait_for_init_deassert		= NULL,
+	.wait_for_init_deassert		= false,
 	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8e28bf2fc3ef..cca53d88762a 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1025,7 +1025,8 @@ __setup("show_msr=", setup_show_msr);
 
 static __init int setup_noclflush(char *arg)
 {
-	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+	setup_clear_cpu_cap(X86_FEATURE_CLFLUSH);
+	setup_clear_cpu_cap(X86_FEATURE_CLFLUSHOPT);
 	return 1;
 }
 __setup("noclflush", setup_noclflush);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 5cd9bfabd645..ea56e7c9abe6 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -267,10 +267,6 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 	}
 #endif
 
-#ifdef CONFIG_X86_NUMAQ
-	numaq_tsc_disable();
-#endif
-
 	intel_smp_check(c);
 }
 #else
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
index 36565373af87..afa9f0d487ea 100644
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -47,45 +47,3 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
 	return NULL;
 }
 EXPORT_SYMBOL(x86_match_cpu);
-
-ssize_t arch_print_cpu_modalias(struct device *dev,
-				struct device_attribute *attr,
-				char *bufptr)
-{
-	int size = PAGE_SIZE;
-	int i, n;
-	char *buf = bufptr;
-
-	n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
-		     "model:%04X:feature:",
-		boot_cpu_data.x86_vendor,
-		boot_cpu_data.x86,
-		boot_cpu_data.x86_model);
-	size -= n;
-	buf += n;
-	size -= 1;
-	for (i = 0; i < NCAPINTS*32; i++) {
-		if (boot_cpu_has(i)) {
-			n = snprintf(buf, size, ",%04X", i);
-			if (n >= size) {
-				WARN(1, "x86 features overflow page\n");
-				break;
-			}
-			size -= n;
-			buf += n;
-		}
-	}
-	*buf++ = '\n';
-	return buf - bufptr;
-}
-
-int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-	if (buf) {
-		arch_print_cpu_modalias(NULL, NULL, buf);
-		add_uevent_var(env, "MODALIAS=%s", buf);
-		kfree(buf);
-	}
-	return 0;
-}
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 79f9f848bee4..ae407f7226c8 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -892,7 +892,6 @@ static void x86_pmu_enable(struct pmu *pmu)
 		 * hw_perf_group_sched_in() or x86_pmu_enable()
 		 *
 		 * step1: save events moving to new counters
-		 * step2: reprogram moved events into new counters
 		 */
 		for (i = 0; i < n_running; i++) {
 			event = cpuc->event_list[i];
@@ -918,6 +917,9 @@ static void x86_pmu_enable(struct pmu *pmu)
 			x86_pmu_stop(event, PERF_EF_UPDATE);
 		}
 
+		/*
+		 * step2: reprogram moved events into new counters
+		 */
 		for (i = 0; i < cpuc->n_events; i++) {
 			event = cpuc->event_list[i];
 			hwc = &event->hw;
@@ -1043,7 +1045,7 @@ static int x86_pmu_add(struct perf_event *event, int flags)
 	/*
 	 * If group events scheduling transaction was started,
 	 * skip the schedulability test here, it will be performed
-	 * at commit time (->commit_txn) as a whole
+	 * at commit time (->commit_txn) as a whole.
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
 		goto done_collect;
@@ -1058,6 +1060,10 @@ static int x86_pmu_add(struct perf_event *event, int flags)
 	memcpy(cpuc->assign, assign, n*sizeof(int));
 
 done_collect:
+	/*
+	 * Commit the collect_events() state. See x86_pmu_del() and
+	 * x86_pmu_*_txn().
+	 */
 	cpuc->n_events = n;
 	cpuc->n_added += n - n0;
 	cpuc->n_txn += n - n0;
@@ -1183,28 +1189,38 @@ static void x86_pmu_del(struct perf_event *event, int flags)
 	 * If we're called during a txn, we don't need to do anything.
 	 * The events never got scheduled and ->cancel_txn will truncate
 	 * the event_list.
+	 *
+	 * XXX assumes any ->del() called during a TXN will only be on
+	 * an event added during that same TXN.
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
 		return;
 
+	/*
+	 * Not a TXN, therefore cleanup properly.
+	 */
 	x86_pmu_stop(event, PERF_EF_UPDATE);
 
 	for (i = 0; i < cpuc->n_events; i++) {
-		if (event == cpuc->event_list[i]) {
+		if (event == cpuc->event_list[i])
+			break;
+	}
 
-			if (i >= cpuc->n_events - cpuc->n_added)
-				--cpuc->n_added;
+	if (WARN_ON_ONCE(i == cpuc->n_events)) /* called ->del() without ->add() ? */
+		return;
 
-			if (x86_pmu.put_event_constraints)
-				x86_pmu.put_event_constraints(cpuc, event);
+	/* If we have a newly added event; make sure to decrease n_added. */
+	if (i >= cpuc->n_events - cpuc->n_added)
+		--cpuc->n_added;
 
-			while (++i < cpuc->n_events)
-				cpuc->event_list[i-1] = cpuc->event_list[i];
+	if (x86_pmu.put_event_constraints)
+		x86_pmu.put_event_constraints(cpuc, event);
+
+	/* Delete the array entry. */
+	while (++i < cpuc->n_events)
+		cpuc->event_list[i-1] = cpuc->event_list[i];
+	--cpuc->n_events;
 
-			--cpuc->n_events;
-			break;
-		}
-	}
 	perf_event_update_userpage(event);
 }
 
@@ -1598,7 +1614,8 @@ static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
 	__this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN);
 	/*
-	 * Truncate the collected events.
+	 * Truncate collected array by the number of events added in this
+	 * transaction. See x86_pmu_add() and x86_pmu_*_txn().
 	 */
 	__this_cpu_sub(cpu_hw_events.n_added, __this_cpu_read(cpu_hw_events.n_txn));
 	__this_cpu_sub(cpu_hw_events.n_events, __this_cpu_read(cpu_hw_events.n_txn));
@@ -1609,6 +1626,8 @@ static void x86_pmu_cancel_txn(struct pmu *pmu)
  * Commit group events scheduling transaction
  * Perform the group schedulability test as a whole
  * Return 0 if success
+ *
+ * Does not cancel the transaction on failure; expects the caller to do this.
  */
 static int x86_pmu_commit_txn(struct pmu *pmu)
 {
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 4972c244d0bc..3b2f9bdd974b 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -130,9 +130,11 @@ struct cpu_hw_events {
 	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
 	int			enabled;
 
-	int			n_events;
-	int			n_added;
-	int			n_txn;
+	int			n_events; /* the # of events in the below arrays */
+	int			n_added;  /* the # last events in the below arrays;
+					     they've never been enabled yet */
+	int			n_txn;    /* the # last events in the below arrays;
+					     added in the current transaction */
 	int			assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
 	u64			tags[X86_PMC_IDX_MAX];
 	struct perf_event	*event_list[X86_PMC_IDX_MAX]; /* in enabled order */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index c88f7f4b03ee..b262c6124cf3 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -66,6 +66,47 @@ DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
 DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
 DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
 
+static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
+static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
+static void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
+static void uncore_pmu_event_read(struct perf_event *event);
+
+static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
+{
+	return container_of(event->pmu, struct intel_uncore_pmu, pmu);
+}
+
+static struct intel_uncore_box *
+uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
+{
+	struct intel_uncore_box *box;
+
+	box = *per_cpu_ptr(pmu->box, cpu);
+	if (box)
+		return box;
+
+	raw_spin_lock(&uncore_box_lock);
+	list_for_each_entry(box, &pmu->box_list, list) {
+		if (box->phys_id == topology_physical_package_id(cpu)) {
+			atomic_inc(&box->refcnt);
+			*per_cpu_ptr(pmu->box, cpu) = box;
+			break;
+		}
+	}
+	raw_spin_unlock(&uncore_box_lock);
+
+	return *per_cpu_ptr(pmu->box, cpu);
+}
+
+static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
+{
+	/*
+	 * perf core schedules event on the basis of cpu, uncore events are
+	 * collected by one of the cpus inside a physical package.
+	 */
+	return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
+}
+
 static u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
 {
 	u64 count;
@@ -1639,6 +1680,345 @@ static struct intel_uncore_type *snb_msr_uncores[] = {
 	&snb_uncore_cbox,
 	NULL,
 };
+
+enum {
+	SNB_PCI_UNCORE_IMC,
+};
+
+static struct uncore_event_desc snb_uncore_imc_events[] = {
+	INTEL_UNCORE_EVENT_DESC(data_reads,  "event=0x01"),
+	INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
+	INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
+
+	INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
+	INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
+	INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
+
+	{ /* end: all zeroes */ },
+};
+
+#define SNB_UNCORE_PCI_IMC_EVENT_MASK		0xff
+#define SNB_UNCORE_PCI_IMC_BAR_OFFSET		0x48
+
+/* page size multiple covering all config regs */
+#define SNB_UNCORE_PCI_IMC_MAP_SIZE		0x6000
+
+#define SNB_UNCORE_PCI_IMC_DATA_READS		0x1
+#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE	0x5050
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES		0x2
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE	0x5054
+#define SNB_UNCORE_PCI_IMC_CTR_BASE		SNB_UNCORE_PCI_IMC_DATA_READS_BASE
+
+static struct attribute *snb_uncore_imc_formats_attr[] = {
+	&format_attr_event.attr,
+	NULL,
+};
+
+static struct attribute_group snb_uncore_imc_format_group = {
+	.name = "format",
+	.attrs = snb_uncore_imc_formats_attr,
+};
+
+static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
+{
+	struct pci_dev *pdev = box->pci_dev;
+	u32 addr_lo, addr_hi;
+	resource_size_t addr;
+
+	pci_read_config_dword(pdev, SNB_UNCORE_PCI_IMC_BAR_OFFSET, &addr_lo);
+	addr = addr_lo;
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	pci_read_config_dword(pdev, SNB_UNCORE_PCI_IMC_BAR_OFFSET+4, &addr_hi);
+	addr = ((resource_size_t)addr_hi << 32) | addr_lo;
+#endif
+
+	addr &= ~(PAGE_SIZE - 1);
+
+	box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
+	box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
+}
+
+static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
+}
+
+/*
+ * custom event_init() function because we define our own fixed, free
+ * running counters, so we do not want to conflict with generic uncore
+ * logic. Also simplifies processing
+ */
+static int snb_uncore_imc_event_init(struct perf_event *event)
+{
+	struct intel_uncore_pmu *pmu;
+	struct intel_uncore_box *box;
+	struct hw_perf_event *hwc = &event->hw;
+	u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
+	int idx, base;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	pmu = uncore_event_to_pmu(event);
+	/* no device found for this pmu */
+	if (pmu->func_id < 0)
+		return -ENOENT;
+
+	/* Sampling not supported yet */
+	if (hwc->sample_period)
+		return -EINVAL;
+
+	/* unsupported modes and filters */
+	if (event->attr.exclude_user   ||
+	    event->attr.exclude_kernel ||
+	    event->attr.exclude_hv     ||
+	    event->attr.exclude_idle   ||
+	    event->attr.exclude_host   ||
+	    event->attr.exclude_guest  ||
+	    event->attr.sample_period) /* no sampling */
+		return -EINVAL;
+
+	/*
+	 * Place all uncore events for a particular physical package
+	 * onto a single cpu
+	 */
+	if (event->cpu < 0)
+		return -EINVAL;
+
+	/* check only supported bits are set */
+	if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
+		return -EINVAL;
+
+	box = uncore_pmu_to_box(pmu, event->cpu);
+	if (!box || box->cpu < 0)
+		return -EINVAL;
+
+	event->cpu = box->cpu;
+
+	event->hw.idx = -1;
+	event->hw.last_tag = ~0ULL;
+	event->hw.extra_reg.idx = EXTRA_REG_NONE;
+	event->hw.branch_reg.idx = EXTRA_REG_NONE;
+	/*
+	 * check event is known (whitelist, determines counter)
+	 */
+	switch (cfg) {
+	case SNB_UNCORE_PCI_IMC_DATA_READS:
+		base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
+		idx = UNCORE_PMC_IDX_FIXED;
+		break;
+	case SNB_UNCORE_PCI_IMC_DATA_WRITES:
+		base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
+		idx = UNCORE_PMC_IDX_FIXED + 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* must be done before validate_group */
+	event->hw.event_base = base;
+	event->hw.config = cfg;
+	event->hw.idx = idx;
+
+	/* no group validation needed, we have free running counters */
+
+	return 0;
+}
+
+static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+	return 0;
+}
+
+static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
+{
+	struct intel_uncore_box *box = uncore_event_to_box(event);
+	u64 count;
+
+	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+		return;
+
+	event->hw.state = 0;
+	box->n_active++;
+
+	list_add_tail(&event->active_entry, &box->active_list);
+
+	count = snb_uncore_imc_read_counter(box, event);
+	local64_set(&event->hw.prev_count, count);
+
+	if (box->n_active == 1)
+		uncore_pmu_start_hrtimer(box);
+}
+
+static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
+{
+	struct intel_uncore_box *box = uncore_event_to_box(event);
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		box->n_active--;
+
+		WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+		hwc->state |= PERF_HES_STOPPED;
+
+		list_del(&event->active_entry);
+
+		if (box->n_active == 0)
+			uncore_pmu_cancel_hrtimer(box);
+	}
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		/*
+		 * Drain the remaining delta count out of a event
+		 * that we are disabling:
+		 */
+		uncore_perf_event_update(box, event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+}
+
+static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
+{
+	struct intel_uncore_box *box = uncore_event_to_box(event);
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!box)
+		return -ENODEV;
+
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+	if (!(flags & PERF_EF_START))
+		hwc->state |= PERF_HES_ARCH;
+
+	snb_uncore_imc_event_start(event, 0);
+
+	box->n_events++;
+
+	return 0;
+}
+
+static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
+{
+	struct intel_uncore_box *box = uncore_event_to_box(event);
+	int i;
+
+	snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
+
+	for (i = 0; i < box->n_events; i++) {
+		if (event == box->event_list[i]) {
+			--box->n_events;
+			break;
+		}
+	}
+}
+
+static int snb_pci2phy_map_init(int devid)
+{
+	struct pci_dev *dev = NULL;
+	int bus;
+
+	dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
+	if (!dev)
+		return -ENOTTY;
+
+	bus = dev->bus->number;
+
+	pcibus_to_physid[bus] = 0;
+
+	pci_dev_put(dev);
+
+	return 0;
+}
+
+static struct pmu snb_uncore_imc_pmu = {
+	.task_ctx_nr	= perf_invalid_context,
+	.event_init	= snb_uncore_imc_event_init,
+	.add		= snb_uncore_imc_event_add,
+	.del		= snb_uncore_imc_event_del,
+	.start		= snb_uncore_imc_event_start,
+	.stop		= snb_uncore_imc_event_stop,
+	.read		= uncore_pmu_event_read,
+};
+
+static struct intel_uncore_ops snb_uncore_imc_ops = {
+	.init_box	= snb_uncore_imc_init_box,
+	.enable_box	= snb_uncore_imc_enable_box,
+	.disable_box	= snb_uncore_imc_disable_box,
+	.disable_event	= snb_uncore_imc_disable_event,
+	.enable_event	= snb_uncore_imc_enable_event,
+	.hw_config	= snb_uncore_imc_hw_config,
+	.read_counter	= snb_uncore_imc_read_counter,
+};
+
+static struct intel_uncore_type snb_uncore_imc = {
+	.name		= "imc",
+	.num_counters   = 2,
+	.num_boxes	= 1,
+	.fixed_ctr_bits	= 32,
+	.fixed_ctr	= SNB_UNCORE_PCI_IMC_CTR_BASE,
+	.event_descs	= snb_uncore_imc_events,
+	.format_group	= &snb_uncore_imc_format_group,
+	.perf_ctr	= SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
+	.event_mask	= SNB_UNCORE_PCI_IMC_EVENT_MASK,
+	.ops		= &snb_uncore_imc_ops,
+	.pmu		= &snb_uncore_imc_pmu,
+};
+
+static struct intel_uncore_type *snb_pci_uncores[] = {
+	[SNB_PCI_UNCORE_IMC]	= &snb_uncore_imc,
+	NULL,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = {
+	{ /* IMC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
+		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+	},
+};
+
+static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = {
+	{ /* IMC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
+		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+	},
+};
+
+static DEFINE_PCI_DEVICE_TABLE(hsw_uncore_pci_ids) = {
+	{ /* IMC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
+		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+	},
+};
+
+static struct pci_driver snb_uncore_pci_driver = {
+	.name		= "snb_uncore",
+	.id_table	= snb_uncore_pci_ids,
+};
+
+static struct pci_driver ivb_uncore_pci_driver = {
+	.name		= "ivb_uncore",
+	.id_table	= ivb_uncore_pci_ids,
+};
+
+static struct pci_driver hsw_uncore_pci_driver = {
+	.name		= "hsw_uncore",
+	.id_table	= hsw_uncore_pci_ids,
+};
+
 /* end of Sandy Bridge uncore support */
 
 /* Nehalem uncore support */
@@ -2789,6 +3169,7 @@ again:
 static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
 {
 	struct intel_uncore_box *box;
+	struct perf_event *event;
 	unsigned long flags;
 	int bit;
 
@@ -2801,19 +3182,27 @@ static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
 	 */
 	local_irq_save(flags);
 
+	/*
+	 * handle boxes with an active event list as opposed to active
+	 * counters
+	 */
+	list_for_each_entry(event, &box->active_list, active_entry) {
+		uncore_perf_event_update(box, event);
+	}
+
 	for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
 		uncore_perf_event_update(box, box->events[bit]);
 
 	local_irq_restore(flags);
 
-	hrtimer_forward_now(hrtimer, ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL));
+	hrtimer_forward_now(hrtimer, ns_to_ktime(box->hrtimer_duration));
 	return HRTIMER_RESTART;
 }
 
 static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
 {
 	__hrtimer_start_range_ns(&box->hrtimer,
-			ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL), 0,
+			ns_to_ktime(box->hrtimer_duration), 0,
 			HRTIMER_MODE_REL_PINNED, 0);
 }
 
@@ -2847,43 +3236,12 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
 	box->cpu = -1;
 	box->phys_id = -1;
 
-	return box;
-}
+	/* set default hrtimer timeout */
+	box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
 
-static struct intel_uncore_box *
-uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
-{
-	struct intel_uncore_box *box;
+	INIT_LIST_HEAD(&box->active_list);
 
-	box = *per_cpu_ptr(pmu->box, cpu);
-	if (box)
-		return box;
-
-	raw_spin_lock(&uncore_box_lock);
-	list_for_each_entry(box, &pmu->box_list, list) {
-		if (box->phys_id == topology_physical_package_id(cpu)) {
-			atomic_inc(&box->refcnt);
-			*per_cpu_ptr(pmu->box, cpu) = box;
-			break;
-		}
-	}
-	raw_spin_unlock(&uncore_box_lock);
-
-	return *per_cpu_ptr(pmu->box, cpu);
-}
-
-static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
-{
-	return container_of(event->pmu, struct intel_uncore_pmu, pmu);
-}
-
-static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
-{
-	/*
-	 * perf core schedules event on the basis of cpu, uncore events are
-	 * collected by one of the cpus inside a physical package.
-	 */
-	return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
+	return box;
 }
 
 static int
@@ -3279,16 +3637,21 @@ static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
 {
 	int ret;
 
-	pmu->pmu = (struct pmu) {
-		.attr_groups	= pmu->type->attr_groups,
-		.task_ctx_nr	= perf_invalid_context,
-		.event_init	= uncore_pmu_event_init,
-		.add		= uncore_pmu_event_add,
-		.del		= uncore_pmu_event_del,
-		.start		= uncore_pmu_event_start,
-		.stop		= uncore_pmu_event_stop,
-		.read		= uncore_pmu_event_read,
-	};
+	if (!pmu->type->pmu) {
+		pmu->pmu = (struct pmu) {
+			.attr_groups	= pmu->type->attr_groups,
+			.task_ctx_nr	= perf_invalid_context,
+			.event_init	= uncore_pmu_event_init,
+			.add		= uncore_pmu_event_add,
+			.del		= uncore_pmu_event_del,
+			.start		= uncore_pmu_event_start,
+			.stop		= uncore_pmu_event_stop,
+			.read		= uncore_pmu_event_read,
+		};
+	} else {
+		pmu->pmu = *pmu->type->pmu;
+		pmu->pmu.attr_groups = pmu->type->attr_groups;
+	}
 
 	if (pmu->type->num_boxes == 1) {
 		if (strlen(pmu->type->name) > 0)
@@ -3501,6 +3864,28 @@ static int __init uncore_pci_init(void)
 		pci_uncores = ivt_pci_uncores;
 		uncore_pci_driver = &ivt_uncore_pci_driver;
 		break;
+	case 42: /* Sandy Bridge */
+		ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_SNB_IMC);
+		if (ret)
+			return ret;
+		pci_uncores = snb_pci_uncores;
+		uncore_pci_driver = &snb_uncore_pci_driver;
+		break;
+	case 58: /* Ivy Bridge */
+		ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_IVB_IMC);
+		if (ret)
+			return ret;
+		pci_uncores = snb_pci_uncores;
+		uncore_pci_driver = &ivb_uncore_pci_driver;
+		break;
+	case 60: /* Haswell */
+	case 69: /* Haswell Celeron */
+		ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_HSW_IMC);
+		if (ret)
+			return ret;
+		pci_uncores = snb_pci_uncores;
+		uncore_pci_driver = &hsw_uncore_pci_driver;
+		break;
 	default:
 		return 0;
 	}
@@ -3772,7 +4157,7 @@ static void __init uncore_cpu_setup(void *dummy)
 
 static int __init uncore_cpu_init(void)
 {
-	int ret, cpu, max_cores;
+	int ret, max_cores;
 
 	max_cores = boot_cpu_data.x86_max_cores;
 	switch (boot_cpu_data.x86_model) {
@@ -3816,29 +4201,6 @@ static int __init uncore_cpu_init(void)
 	if (ret)
 		return ret;
 
-	get_online_cpus();
-
-	for_each_online_cpu(cpu) {
-		int i, phys_id = topology_physical_package_id(cpu);
-
-		for_each_cpu(i, &uncore_cpu_mask) {
-			if (phys_id == topology_physical_package_id(i)) {
-				phys_id = -1;
-				break;
-			}
-		}
-		if (phys_id < 0)
-			continue;
-
-		uncore_cpu_prepare(cpu, phys_id);
-		uncore_event_init_cpu(cpu);
-	}
-	on_each_cpu(uncore_cpu_setup, NULL, 1);
-
-	register_cpu_notifier(&uncore_cpu_nb);
-
-	put_online_cpus();
-
 	return 0;
 }
 
@@ -3867,6 +4229,41 @@ static int __init uncore_pmus_register(void)
 	return 0;
 }
 
+static void uncore_cpumask_init(void)
+{
+	int cpu;
+
+	/*
+	 * ony invoke once from msr or pci init code
+	 */
+	if (!cpumask_empty(&uncore_cpu_mask))
+		return;
+
+	get_online_cpus();
+
+	for_each_online_cpu(cpu) {
+		int i, phys_id = topology_physical_package_id(cpu);
+
+		for_each_cpu(i, &uncore_cpu_mask) {
+			if (phys_id == topology_physical_package_id(i)) {
+				phys_id = -1;
+				break;
+			}
+		}
+		if (phys_id < 0)
+			continue;
+
+		uncore_cpu_prepare(cpu, phys_id);
+		uncore_event_init_cpu(cpu);
+	}
+	on_each_cpu(uncore_cpu_setup, NULL, 1);
+
+	register_cpu_notifier(&uncore_cpu_nb);
+
+	put_online_cpus();
+}
+
+
 static int __init intel_uncore_init(void)
 {
 	int ret;
@@ -3885,6 +4282,7 @@ static int __init intel_uncore_init(void)
 		uncore_pci_exit();
 		goto fail;
 	}
+	uncore_cpumask_init();
 
 	uncore_pmus_register();
 	return 0;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index a80ab71a883d..90236f0c94a9 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -6,6 +6,7 @@
 
 #define UNCORE_PMU_NAME_LEN		32
 #define UNCORE_PMU_HRTIMER_INTERVAL	(60LL * NSEC_PER_SEC)
+#define UNCORE_SNB_IMC_HRTIMER_INTERVAL (5ULL * NSEC_PER_SEC)
 
 #define UNCORE_FIXED_EVENT		0xff
 #define UNCORE_PMC_IDX_MAX_GENERIC	8
@@ -440,6 +441,7 @@ struct intel_uncore_type {
 	struct intel_uncore_ops *ops;
 	struct uncore_event_desc *event_descs;
 	const struct attribute_group *attr_groups[4];
+	struct pmu *pmu; /* for custom pmu ops */
 };
 
 #define pmu_group attr_groups[0]
@@ -488,8 +490,11 @@ struct intel_uncore_box {
 	u64 tags[UNCORE_PMC_IDX_MAX];
 	struct pci_dev *pci_dev;
 	struct intel_uncore_pmu *pmu;
+	u64 hrtimer_duration; /* hrtimer timeout for this box */
 	struct hrtimer hrtimer;
 	struct list_head list;
+	struct list_head active_list;
+	void *io_addr;
 	struct intel_uncore_extra_reg shared_regs[0];
 };
 
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index 3486e6660357..5d466b7d8609 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -1257,7 +1257,24 @@ again:
 			pass++;
 			goto again;
 		}
-
+		/*
+		 * Perf does test runs to see if a whole group can be assigned
+		 * together succesfully.  There can be multiple rounds of this.
+		 * Unfortunately, p4_pmu_swap_config_ts touches the hwc->config
+		 * bits, such that the next round of group assignments will
+		 * cause the above p4_should_swap_ts to pass instead of fail.
+		 * This leads to counters exclusive to thread0 being used by
+		 * thread1.
+		 *
+		 * Solve this with a cheap hack, reset the idx back to -1 to
+		 * force a new lookup (p4_next_cntr) to get the right counter
+		 * for the right thread.
+		 *
+		 * This probably doesn't comply with the general spirit of how
+		 * perf wants to work, but P4 is special. :-(
+		 */
+		if (p4_should_swap_ts(hwc->config, cpu))
+			hwc->idx = -1;
 		p4_pmu_swap_config_ts(hwc, cpu);
 		if (assign)
 			assign[i] = cntr_idx;
@@ -1322,6 +1339,7 @@ static __initconst const struct x86_pmu p4_pmu = {
 __init int p4_pmu_init(void)
 {
 	unsigned int low, high;
+	int i, reg;
 
 	/* If we get stripped -- indexing fails */
 	BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
@@ -1340,5 +1358,19 @@ __init int p4_pmu_init(void)
 
 	x86_pmu = p4_pmu;
 
+	/*
+	 * Even though the counters are configured to interrupt a particular
+	 * logical processor when an overflow happens, testing has shown that
+	 * on kdump kernels (which uses a single cpu), thread1's counter
+	 * continues to run and will report an NMI on thread0.  Due to the
+	 * overflow bug, this leads to a stream of unknown NMIs.
+	 *
+	 * Solve this by zero'ing out the registers to mimic a reset.
+	 */
+	for (i = 0; i < x86_pmu.num_counters; i++) {
+		reg = x86_pmu_config_addr(i);
+		wrmsrl_safe(reg, 0ULL);
+	}
+
 	return 0;
 }
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index bc4a088f9023..52f36e660625 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -228,7 +228,7 @@ static void __init intel_remapping_check(int num, int slot, int func)
  *
  * And yes, so far on current devices the base addr is always under 4G.
  */
-static u32 __init intel_stolen_base(int num, int slot, int func)
+static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size)
 {
 	u32 base;
 
@@ -247,6 +247,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func)
 #define MB(x)	(KB (KB (x)))
 #define GB(x)	(MB (KB (x)))
 
+static size_t __init i830_tseg_size(void)
+{
+	u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC);
+
+	if (!(tmp & TSEG_ENABLE))
+		return 0;
+
+	if (tmp & I830_TSEG_SIZE_1M)
+		return MB(1);
+	else
+		return KB(512);
+}
+
+static size_t __init i845_tseg_size(void)
+{
+	u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC);
+
+	if (!(tmp & TSEG_ENABLE))
+		return 0;
+
+	switch (tmp & I845_TSEG_SIZE_MASK) {
+	case I845_TSEG_SIZE_512K:
+		return KB(512);
+	case I845_TSEG_SIZE_1M:
+		return MB(1);
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+}
+
+static size_t __init i85x_tseg_size(void)
+{
+	u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC);
+
+	if (!(tmp & TSEG_ENABLE))
+		return 0;
+
+	return MB(1);
+}
+
+static size_t __init i830_mem_size(void)
+{
+	return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32);
+}
+
+static size_t __init i85x_mem_size(void)
+{
+	return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32);
+}
+
+/*
+ * On 830/845/85x the stolen memory base isn't available in any
+ * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size.
+ */
+static u32 __init i830_stolen_base(int num, int slot, int func, size_t stolen_size)
+{
+	return i830_mem_size() - i830_tseg_size() - stolen_size;
+}
+
+static u32 __init i845_stolen_base(int num, int slot, int func, size_t stolen_size)
+{
+	return i830_mem_size() - i845_tseg_size() - stolen_size;
+}
+
+static u32 __init i85x_stolen_base(int num, int slot, int func, size_t stolen_size)
+{
+	return i85x_mem_size() - i85x_tseg_size() - stolen_size;
+}
+
+static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size)
+{
+	/*
+	 * FIXME is the graphics stolen memory region
+	 * always at TOUD? Ie. is it always the last
+	 * one to be allocated by the BIOS?
+	 */
+	return read_pci_config_16(0, 0, 0, I865_TOUD) << 16;
+}
+
+static size_t __init i830_stolen_size(int num, int slot, int func)
+{
+	size_t stolen_size;
+	u16 gmch_ctrl;
+
+	gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
+
+	switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+	case I830_GMCH_GMS_STOLEN_512:
+		stolen_size = KB(512);
+		break;
+	case I830_GMCH_GMS_STOLEN_1024:
+		stolen_size = MB(1);
+		break;
+	case I830_GMCH_GMS_STOLEN_8192:
+		stolen_size = MB(8);
+		break;
+	case I830_GMCH_GMS_LOCAL:
+		/* local memory isn't part of the normal address space */
+		stolen_size = 0;
+		break;
+	default:
+		return 0;
+	}
+
+	return stolen_size;
+}
+
 static size_t __init gen3_stolen_size(int num, int slot, int func)
 {
 	size_t stolen_size;
@@ -313,7 +421,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func)
 	return gmch_ctrl << 25; /* 32 MB units */
 }
 
-static inline size_t gen8_stolen_size(int num, int slot, int func)
+static size_t gen8_stolen_size(int num, int slot, int func)
 {
 	u16 gmch_ctrl;
 
@@ -323,31 +431,74 @@ static inline size_t gen8_stolen_size(int num, int slot, int func)
 	return gmch_ctrl << 25; /* 32 MB units */
 }
 
-typedef size_t (*stolen_size_fn)(int num, int slot, int func);
+
+struct intel_stolen_funcs {
+	size_t (*size)(int num, int slot, int func);
+	u32 (*base)(int num, int slot, int func, size_t size);
+};
+
+static const struct intel_stolen_funcs i830_stolen_funcs = {
+	.base = i830_stolen_base,
+	.size = i830_stolen_size,
+};
+
+static const struct intel_stolen_funcs i845_stolen_funcs = {
+	.base = i845_stolen_base,
+	.size = i830_stolen_size,
+};
+
+static const struct intel_stolen_funcs i85x_stolen_funcs = {
+	.base = i85x_stolen_base,
+	.size = gen3_stolen_size,
+};
+
+static const struct intel_stolen_funcs i865_stolen_funcs = {
+	.base = i865_stolen_base,
+	.size = gen3_stolen_size,
+};
+
+static const struct intel_stolen_funcs gen3_stolen_funcs = {
+	.base = intel_stolen_base,
+	.size = gen3_stolen_size,
+};
+
+static const struct intel_stolen_funcs gen6_stolen_funcs = {
+	.base = intel_stolen_base,
+	.size = gen6_stolen_size,
+};
+
+static const struct intel_stolen_funcs gen8_stolen_funcs = {
+	.base = intel_stolen_base,
+	.size = gen8_stolen_size,
+};
 
 static struct pci_device_id intel_stolen_ids[] __initdata = {
-	INTEL_I915G_IDS(gen3_stolen_size),
-	INTEL_I915GM_IDS(gen3_stolen_size),
-	INTEL_I945G_IDS(gen3_stolen_size),
-	INTEL_I945GM_IDS(gen3_stolen_size),
-	INTEL_VLV_M_IDS(gen6_stolen_size),
-	INTEL_VLV_D_IDS(gen6_stolen_size),
-	INTEL_PINEVIEW_IDS(gen3_stolen_size),
-	INTEL_I965G_IDS(gen3_stolen_size),
-	INTEL_G33_IDS(gen3_stolen_size),
-	INTEL_I965GM_IDS(gen3_stolen_size),
-	INTEL_GM45_IDS(gen3_stolen_size),
-	INTEL_G45_IDS(gen3_stolen_size),
-	INTEL_IRONLAKE_D_IDS(gen3_stolen_size),
-	INTEL_IRONLAKE_M_IDS(gen3_stolen_size),
-	INTEL_SNB_D_IDS(gen6_stolen_size),
-	INTEL_SNB_M_IDS(gen6_stolen_size),
-	INTEL_IVB_M_IDS(gen6_stolen_size),
-	INTEL_IVB_D_IDS(gen6_stolen_size),
-	INTEL_HSW_D_IDS(gen6_stolen_size),
-	INTEL_HSW_M_IDS(gen6_stolen_size),
-	INTEL_BDW_M_IDS(gen8_stolen_size),
-	INTEL_BDW_D_IDS(gen8_stolen_size)
+	INTEL_I830_IDS(&i830_stolen_funcs),
+	INTEL_I845G_IDS(&i845_stolen_funcs),
+	INTEL_I85X_IDS(&i85x_stolen_funcs),
+	INTEL_I865G_IDS(&i865_stolen_funcs),
+	INTEL_I915G_IDS(&gen3_stolen_funcs),
+	INTEL_I915GM_IDS(&gen3_stolen_funcs),
+	INTEL_I945G_IDS(&gen3_stolen_funcs),
+	INTEL_I945GM_IDS(&gen3_stolen_funcs),
+	INTEL_VLV_M_IDS(&gen6_stolen_funcs),
+	INTEL_VLV_D_IDS(&gen6_stolen_funcs),
+	INTEL_PINEVIEW_IDS(&gen3_stolen_funcs),
+	INTEL_I965G_IDS(&gen3_stolen_funcs),
+	INTEL_G33_IDS(&gen3_stolen_funcs),
+	INTEL_I965GM_IDS(&gen3_stolen_funcs),
+	INTEL_GM45_IDS(&gen3_stolen_funcs),
+	INTEL_G45_IDS(&gen3_stolen_funcs),
+	INTEL_IRONLAKE_D_IDS(&gen3_stolen_funcs),
+	INTEL_IRONLAKE_M_IDS(&gen3_stolen_funcs),
+	INTEL_SNB_D_IDS(&gen6_stolen_funcs),
+	INTEL_SNB_M_IDS(&gen6_stolen_funcs),
+	INTEL_IVB_M_IDS(&gen6_stolen_funcs),
+	INTEL_IVB_D_IDS(&gen6_stolen_funcs),
+	INTEL_HSW_D_IDS(&gen6_stolen_funcs),
+	INTEL_HSW_M_IDS(&gen6_stolen_funcs),
+	INTEL_BDW_M_IDS(&gen8_stolen_funcs),
+	INTEL_BDW_D_IDS(&gen8_stolen_funcs)
 };
 
 static void __init intel_graphics_stolen(int num, int slot, int func)
@@ -364,11 +515,13 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
 
 	for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) {
 		if (intel_stolen_ids[i].device == device) {
-			stolen_size_fn stolen_size =
-				(stolen_size_fn)intel_stolen_ids[i].driver_data;
-			size = stolen_size(num, slot, func);
-			start = intel_stolen_base(num, slot, func);
+			const struct intel_stolen_funcs *stolen_funcs =
+				(const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data;
+			size = stolen_funcs->size(num, slot, func);
+			start = stolen_funcs->base(num, slot, func, size);
 			if (size && start) {
+				printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n",
+				       start, start + (u32)size - 1);
 				/* Mark this space as reserved */
 				e820_add_region(start, size, E820_RESERVED);
 				sanitize_e820_map(e820.map,
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index a2a4f4697889..024578db698c 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -998,7 +998,30 @@ ENTRY(xen_hypervisor_callback)
 ENTRY(xen_do_upcall)
 1:	mov %esp, %eax
 	call xen_evtchn_do_upcall
+#ifdef CONFIG_PREEMPT
 	jmp  ret_from_intr
+#else
+	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_VM86
+	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+	movb PT_CS(%esp), %al
+	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+	movl PT_CS(%esp), %eax
+	andl $SEGMENT_RPL_MASK, %eax
+#endif
+	cmpl $USER_RPL, %eax
+	jae resume_userspace		# returning to v8086 or userspace
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz resume_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz resume_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp resume_kernel
+#endif /* CONFIG_PREEMPT */
 	CFI_ENDPROC
 ENDPROC(xen_hypervisor_callback)
 
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1e96c3628bf2..d8f4fd8e3a2c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1404,7 +1404,25 @@ ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
 	popq %rsp
 	CFI_DEF_CFA_REGISTER rsp
 	decl PER_CPU_VAR(irq_count)
+#ifdef CONFIG_PREEMPT
 	jmp  error_exit
+#else
+	movl %ebx, %eax
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	testl %eax, %eax
+	je error_exit_user
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz retint_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz retint_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp retint_kernel
+#endif
 	CFI_ENDPROC
 END(xen_do_hypervisor_callback)
 
@@ -1629,6 +1647,7 @@ ENTRY(error_exit)
 	GET_THREAD_INFO(%rcx)
 	testl %eax,%eax
 	jne retint_kernel
+error_exit_user:
 	LOCKDEP_SYS_EXIT_IRQ
 	movl TI_flags(%rcx),%edx
 	movl $_TIF_WORK_MASK,%edi
diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c
index c3aae6672843..d3803c619bae 100644
--- a/arch/x86/kernel/iosf_mbi.c
+++ b/arch/x86/kernel/iosf_mbi.c
@@ -177,6 +177,12 @@ int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
 }
 EXPORT_SYMBOL(iosf_mbi_modify);
 
+bool iosf_mbi_available(void)
+{
+	return mbi_pdev;
+}
+EXPORT_SYMBOL(iosf_mbi_available);
+
 static int iosf_mbi_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *unused)
 {
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 713f1b3bad52..0331cb389d68 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -417,7 +417,6 @@ void kvm_disable_steal_time(void)
 #ifdef CONFIG_SMP
 static void __init kvm_smp_prepare_boot_cpu(void)
 {
-	WARN_ON(kvm_register_clock("primary cpu clock"));
 	kvm_guest_cpu_init();
 	native_smp_prepare_boot_cpu();
 	kvm_spinlock_init();
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index e6041094ff26..d9156ceecdff 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -242,7 +242,7 @@ void __init kvmclock_init(void)
 	hv_clock = __va(mem);
 	memset(hv_clock, 0, size);
 
-	if (kvm_register_clock("boot clock")) {
+	if (kvm_register_clock("primary cpu clock")) {
 		hv_clock = NULL;
 		memblock_free(mem, size);
 		return;
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 18be189368bb..49483137371f 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 #include <linux/jump_label.h>
+#include <linux/random.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -43,13 +44,49 @@ do {							\
 } while (0)
 #endif
 
+#ifdef CONFIG_RANDOMIZE_BASE
+static unsigned long module_load_offset;
+static int randomize_modules = 1;
+
+static int __init parse_nokaslr(char *p)
+{
+	randomize_modules = 0;
+	return 0;
+}
+early_param("nokaslr", parse_nokaslr);
+
+static unsigned long int get_module_load_offset(void)
+{
+	if (randomize_modules) {
+		mutex_lock(&module_mutex);
+		/*
+		 * Calculate the module_load_offset the first time this
+		 * code is called. Once calculated it stays the same until
+		 * reboot.
+		 */
+		if (module_load_offset == 0)
+			module_load_offset =
+				(get_random_int() % 1024 + 1) * PAGE_SIZE;
+		mutex_unlock(&module_mutex);
+	}
+	return module_load_offset;
+}
+#else
+static unsigned long int get_module_load_offset(void)
+{
+	return 0;
+}
+#endif
+
 void *module_alloc(unsigned long size)
 {
 	if (PAGE_ALIGN(size) > MODULES_LEN)
 		return NULL;
-	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-				GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
-				NUMA_NO_NODE, __builtin_return_address(0));
+	return __vmalloc_node_range(size, 1,
+				    MODULES_VADDR + get_module_load_offset(),
+				    MODULES_END, GFP_KERNEL | __GFP_HIGHMEM,
+				    PAGE_KERNEL_EXEC, NUMA_NO_NODE,
+				    __builtin_return_address(0));
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 6fcb49ce50a1..b4872b999a71 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -87,6 +87,7 @@ __setup("unknown_nmi_panic", setup_unknown_nmi_panic);
 #define nmi_to_desc(type) (&nmi_desc[type])
 
 static u64 nmi_longest_ns = 1 * NSEC_PER_MSEC;
+
 static int __init nmi_warning_debugfs(void)
 {
 	debugfs_create_u64("nmi_longest_ns", 0644,
@@ -95,6 +96,20 @@ static int __init nmi_warning_debugfs(void)
 }
 fs_initcall(nmi_warning_debugfs);
 
+static void nmi_max_handler(struct irq_work *w)
+{
+	struct nmiaction *a = container_of(w, struct nmiaction, irq_work);
+	int remainder_ns, decimal_msecs;
+	u64 whole_msecs = ACCESS_ONCE(a->max_duration);
+
+	remainder_ns = do_div(whole_msecs, (1000 * 1000));
+	decimal_msecs = remainder_ns / 1000;
+
+	printk_ratelimited(KERN_INFO
+		"INFO: NMI handler (%ps) took too long to run: %lld.%03d msecs\n",
+		a->handler, whole_msecs, decimal_msecs);
+}
+
 static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
 {
 	struct nmi_desc *desc = nmi_to_desc(type);
@@ -110,26 +125,20 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2
 	 * to handle those situations.
 	 */
 	list_for_each_entry_rcu(a, &desc->head, list) {
-		u64 before, delta, whole_msecs;
-		int remainder_ns, decimal_msecs, thishandled;
+		int thishandled;
+		u64 delta;
 
-		before = sched_clock();
+		delta = sched_clock();
 		thishandled = a->handler(type, regs);
 		handled += thishandled;
-		delta = sched_clock() - before;
+		delta = sched_clock() - delta;
 		trace_nmi_handler(a->handler, (int)delta, thishandled);
 
-		if (delta < nmi_longest_ns)
+		if (delta < nmi_longest_ns || delta < a->max_duration)
 			continue;
 
-		nmi_longest_ns = delta;
-		whole_msecs = delta;
-		remainder_ns = do_div(whole_msecs, (1000 * 1000));
-		decimal_msecs = remainder_ns / 1000;
-		printk_ratelimited(KERN_INFO
-			"INFO: NMI handler (%ps) took too long to run: "
-			"%lld.%03d msecs\n", a->handler, whole_msecs,
-			decimal_msecs);
+		a->max_duration = delta;
+		irq_work_queue(&a->irq_work);
 	}
 
 	rcu_read_unlock();
@@ -146,6 +155,8 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action)
 	if (!action->handler)
 		return -EINVAL;
 
+	init_irq_work(&action->irq_work, nmi_max_handler);
+
 	spin_lock_irqsave(&desc->lock, flags);
 
 	/*
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 3fb8d95ab8b5..4505e2a950d8 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -298,10 +298,7 @@ void arch_cpu_idle_dead(void)
  */
 void arch_cpu_idle(void)
 {
-	if (cpuidle_idle_call())
-		x86_idle();
-	else
-		local_irq_enable();
+	x86_idle();
 }
 
 /*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 06853e670354..12907ab8f33e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -869,7 +869,6 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_X86_32
 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
-	visws_early_detect();
 
 	/*
 	 * copy kernel address range established so far and switch
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index a32da804252e..e6108df7f476 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -122,8 +122,9 @@ static void smp_callin(void)
 	 * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI.
 	 */
 	cpuid = smp_processor_id();
-	if (apic->wait_for_init_deassert && cpuid != 0)
-		apic->wait_for_init_deassert(&init_deasserted);
+	if (apic->wait_for_init_deassert && cpuid)
+		while (!atomic_read(&init_deasserted))
+			cpu_relax();
 
 	/*
 	 * (This works even if the APIC is not enabled.)
@@ -1379,7 +1380,7 @@ static inline void mwait_play_dead(void)
 
 	if (!this_cpu_has(X86_FEATURE_MWAIT))
 		return;
-	if (!this_cpu_has(X86_FEATURE_CLFLSH))
+	if (!this_cpu_has(X86_FEATURE_CLFLUSH))
 		return;
 	if (__this_cpu_read(cpu_info.cpuid_level) < CPUID_MWAIT_LEAF)
 		return;
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index 24d3c91e9812..6ec91c00d84d 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -23,7 +23,7 @@
 #include <asm/time.h>
 
 #ifdef CONFIG_X86_64
-DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
+__visible DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
 #endif
 
 unsigned long profile_pc(struct pt_regs *regs)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index c6976257eff5..f1634b759e6c 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -28,7 +28,7 @@ static u32 xstate_required_size(u64 xstate_bv)
 	int feature_bit = 0;
 	u32 ret = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
 
-	xstate_bv &= ~XSTATE_FPSSE;
+	xstate_bv &= XSTATE_EXTEND_MASK;
 	while (xstate_bv) {
 		if (xstate_bv & 0x1) {
 		        u32 eax, ebx, ecx, edx;
@@ -74,8 +74,8 @@ void kvm_update_cpuid(struct kvm_vcpu *vcpu)
 		vcpu->arch.guest_supported_xcr0 =
 			(best->eax | ((u64)best->edx << 32)) &
 			host_xcr0 & KVM_SUPPORTED_XCR0;
-		vcpu->arch.guest_xstate_size =
-			xstate_required_size(vcpu->arch.guest_supported_xcr0);
+		vcpu->arch.guest_xstate_size = best->ebx =
+			xstate_required_size(vcpu->arch.xcr0);
 	}
 
 	kvm_pmu_cpuid_update(vcpu);
@@ -256,6 +256,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 #endif
 	unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
 	unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0;
+	unsigned f_mpx = kvm_x86_ops->mpx_supported ?
+			 (kvm_x86_ops->mpx_supported() ? F(MPX) : 0) : 0;
 
 	/* cpuid 1.edx */
 	const u32 kvm_supported_word0_x86_features =
@@ -263,7 +265,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		F(TSC) | F(MSR) | F(PAE) | F(MCE) |
 		F(CX8) | F(APIC) | 0 /* Reserved */ | F(SEP) |
 		F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
-		F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLSH) |
+		F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLUSH) |
 		0 /* Reserved, DS, ACPI */ | F(MMX) |
 		F(FXSR) | F(XMM) | F(XMM2) | F(SELFSNOOP) |
 		0 /* HTT, TM, Reserved, PBE */;
@@ -303,7 +305,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 	/* cpuid 7.0.ebx */
 	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(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) |
+		F(ADX);
 
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 9b531351a587..f5704d9e5ddc 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3329,7 +3329,7 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn)
 	arch.direct_map = vcpu->arch.mmu.direct_map;
 	arch.cr3 = vcpu->arch.mmu.get_cr3(vcpu);
 
-	return kvm_setup_async_pf(vcpu, gva, gfn, &arch);
+	return kvm_setup_async_pf(vcpu, gva, gfn_to_hva(vcpu->kvm, gfn), &arch);
 }
 
 static bool can_do_async_pf(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index cba218a2f08d..b1e6c1bf68d3 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -913,7 +913,8 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
  *   and kvm_mmu_notifier_invalidate_range_start detect the mapping page isn't
  *   used by guest then tlbs are not flushed, so guest is allowed to access the
  *   freed pages.
- *   And we increase kvm->tlbs_dirty to delay tlbs flush in this case.
+ *   We set tlbs_dirty to let the notifier know this change and delay the flush
+ *   until such a case actually happens.
  */
 static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
@@ -942,7 +943,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 			return -EINVAL;
 
 		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
-			vcpu->kvm->tlbs_dirty++;
+			vcpu->kvm->tlbs_dirty = true;
 			continue;
 		}
 
@@ -957,7 +958,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 
 		if (gfn != sp->gfns[i]) {
 			drop_spte(vcpu->kvm, &sp->spt[i]);
-			vcpu->kvm->tlbs_dirty++;
+			vcpu->kvm->tlbs_dirty = true;
 			continue;
 		}
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index e81df8fce027..64d9bb9590e3 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2842,6 +2842,7 @@ static int iret_interception(struct vcpu_svm *svm)
 	clr_intercept(svm, INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
 	svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
+	kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 	return 1;
 }
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 392752834751..53c324f3cc5e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -441,6 +441,7 @@ struct vcpu_vmx {
 #endif
 		int           gs_ldt_reload_needed;
 		int           fs_reload_needed;
+		u64           msr_host_bndcfgs;
 	} host_state;
 	struct {
 		int vm86_active;
@@ -1710,6 +1711,8 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
 	if (is_long_mode(&vmx->vcpu))
 		wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
 #endif
+	if (boot_cpu_has(X86_FEATURE_MPX))
+		rdmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs);
 	for (i = 0; i < vmx->save_nmsrs; ++i)
 		kvm_set_shared_msr(vmx->guest_msrs[i].index,
 				   vmx->guest_msrs[i].data,
@@ -1747,6 +1750,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 #ifdef CONFIG_X86_64
 	wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
 #endif
+	if (vmx->host_state.msr_host_bndcfgs)
+		wrmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs);
 	/*
 	 * If the FPU is not active (through the host task or
 	 * the guest vcpu), then restore the cr0.TS bit.
@@ -2479,6 +2484,9 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 	case MSR_IA32_SYSENTER_ESP:
 		data = vmcs_readl(GUEST_SYSENTER_ESP);
 		break;
+	case MSR_IA32_BNDCFGS:
+		data = vmcs_read64(GUEST_BNDCFGS);
+		break;
 	case MSR_IA32_FEATURE_CONTROL:
 		if (!nested_vmx_allowed(vcpu))
 			return 1;
@@ -2547,6 +2555,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_IA32_SYSENTER_ESP:
 		vmcs_writel(GUEST_SYSENTER_ESP, data);
 		break;
+	case MSR_IA32_BNDCFGS:
+		vmcs_write64(GUEST_BNDCFGS, data);
+		break;
 	case MSR_IA32_TSC:
 		kvm_write_tsc(vcpu, msr_info);
 		break;
@@ -2837,7 +2848,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
 	min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
 #endif
 	opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT |
-		VM_EXIT_ACK_INTR_ON_EXIT;
+		VM_EXIT_ACK_INTR_ON_EXIT | VM_EXIT_CLEAR_BNDCFGS;
 	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
 				&_vmexit_control) < 0)
 		return -EIO;
@@ -2854,7 +2865,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
 		_pin_based_exec_control &= ~PIN_BASED_POSTED_INTR;
 
 	min = 0;
-	opt = VM_ENTRY_LOAD_IA32_PAT;
+	opt = VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS;
 	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
 				&_vmentry_control) < 0)
 		return -EIO;
@@ -7052,6 +7063,12 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 		local_irq_enable();
 }
 
+static bool vmx_mpx_supported(void)
+{
+	return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
+		(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
+}
+
 static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
 {
 	u32 exit_intr_info;
@@ -8634,6 +8651,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
 
 	.check_intercept = vmx_check_intercept,
 	.handle_external_intr = vmx_handle_external_intr,
+	.mpx_supported = vmx_mpx_supported,
 };
 
 static int __init vmx_init(void)
@@ -8721,6 +8739,8 @@ static int __init vmx_init(void)
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
+	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true);
+
 	memcpy(vmx_msr_bitmap_legacy_x2apic,
 			vmx_msr_bitmap_legacy, PAGE_SIZE);
 	memcpy(vmx_msr_bitmap_longmode_x2apic,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2b8578432d5b..43ecae2d1142 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -595,13 +595,13 @@ static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
 
 int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
 {
-	u64 xcr0;
+	u64 xcr0 = xcr;
+	u64 old_xcr0 = vcpu->arch.xcr0;
 	u64 valid_bits;
 
 	/* Only support XCR_XFEATURE_ENABLED_MASK(xcr0) now  */
 	if (index != XCR_XFEATURE_ENABLED_MASK)
 		return 1;
-	xcr0 = xcr;
 	if (!(xcr0 & XSTATE_FP))
 		return 1;
 	if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE))
@@ -616,8 +616,14 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
 	if (xcr0 & ~valid_bits)
 		return 1;
 
+	if ((!(xcr0 & XSTATE_BNDREGS)) != (!(xcr0 & XSTATE_BNDCSR)))
+		return 1;
+
 	kvm_put_guest_xcr0(vcpu);
 	vcpu->arch.xcr0 = xcr0;
+
+	if ((xcr0 ^ old_xcr0) & XSTATE_EXTEND_MASK)
+		kvm_update_cpuid(vcpu);
 	return 0;
 }
 
@@ -879,7 +885,7 @@ static u32 msrs_to_save[] = {
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
 	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
-	MSR_IA32_FEATURE_CONTROL
+	MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS
 };
 
 static unsigned num_msrs_to_save;
@@ -1581,7 +1587,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 	/* With all the info we got, fill in the values */
 	vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
 	vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
-	vcpu->last_kernel_ns = kernel_ns;
 	vcpu->last_guest_tsc = tsc_timestamp;
 
 	/*
@@ -4394,6 +4399,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 	if (!exchanged)
 		return X86EMUL_CMPXCHG_FAILED;
 
+	mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT);
 	kvm_mmu_pte_write(vcpu, gpa, new, bytes);
 
 	return X86EMUL_CONTINUE;
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 8da5823bcde6..392ecbff0030 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -122,7 +122,8 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 	gva_t addr, void *val, unsigned int bytes,
 	struct x86_exception *exception);
 
-#define KVM_SUPPORTED_XCR0	(XSTATE_FP | XSTATE_SSE | XSTATE_YMM)
+#define KVM_SUPPORTED_XCR0     (XSTATE_FP | XSTATE_SSE | XSTATE_YMM \
+				| XSTATE_BNDREGS | XSTATE_BNDCSR)
 extern u64 host_xcr0;
 
 extern unsigned int min_timer_period_us;
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index e78761d6b7f8..a404b4b75533 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -4,7 +4,7 @@
 #undef memcpy
 #undef memset
 
-void *memcpy(void *to, const void *from, size_t n)
+__visible void *memcpy(void *to, const void *from, size_t n)
 {
 #ifdef CONFIG_X86_USE_3DNOW
 	return __memcpy3d(to, from, n);
@@ -14,13 +14,13 @@ void *memcpy(void *to, const void *from, size_t n)
 }
 EXPORT_SYMBOL(memcpy);
 
-void *memset(void *s, int c, size_t count)
+__visible void *memset(void *s, int c, size_t count)
 {
 	return __memset(s, c, count);
 }
 EXPORT_SYMBOL(memset);
 
-void *memmove(void *dest, const void *src, size_t n)
+__visible void *memmove(void *dest, const void *src, size_t n)
 {
 	int d0,d1,d2,d3,d4,d5;
 	char *ret = dest;
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index e39504878aec..af7259cb3c6e 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -537,7 +537,7 @@ static void __init pagetable_init(void)
 	permanent_kmaps_init(pgd_base);
 }
 
-pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
+pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
 /* user-defined highmem size */
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index f35c66c5959a..9e6fa6db3165 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -151,7 +151,7 @@ early_param("gbpages", parse_direct_gbpages_on);
  * around without checking the pgd every time.
  */
 
-pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
+pteval_t __supported_pte_mask __read_mostly = ~0;
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
 int force_personality32;
diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c
index d87dd6d042d6..dd89a13f1051 100644
--- a/arch/x86/mm/kmemcheck/kmemcheck.c
+++ b/arch/x86/mm/kmemcheck/kmemcheck.c
@@ -78,10 +78,16 @@ early_initcall(kmemcheck_init);
  */
 static int __init param_kmemcheck(char *str)
 {
+	int val;
+	int ret;
+
 	if (!str)
 		return -EINVAL;
 
-	sscanf(str, "%d", &kmemcheck_enabled);
+	ret = kstrtoint(str, 0, &val);
+	if (ret)
+		return ret;
+	kmemcheck_enabled = val;
 	return 0;
 }
 
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 27aa0455fab3..1d045f9c390f 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -687,10 +687,6 @@ static int __init dummy_numa_init(void)
 void __init x86_numa_init(void)
 {
 	if (!numa_off) {
-#ifdef CONFIG_X86_NUMAQ
-		if (!numa_init(numaq_numa_init))
-			return;
-#endif
 #ifdef CONFIG_ACPI_NUMA
 		if (!numa_init(x86_acpi_numa_init))
 			return;
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index b3b19f46c016..b1c46723b19b 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -126,8 +126,8 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  * @vaddr:	virtual start address
  * @size:	number of bytes to flush
  *
- * clflush is an unordered instruction which needs fencing with mfence
- * to avoid ordering issues.
+ * clflushopt is an unordered instruction which needs fencing with mfence or
+ * sfence to avoid ordering issues.
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
@@ -136,11 +136,11 @@ void clflush_cache_range(void *vaddr, unsigned int size)
 	mb();
 
 	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
-		clflush(vaddr);
+		clflushopt(vaddr);
 	/*
 	 * Flush any possible final partial cacheline:
 	 */
-	clflush(vend);
+	clflushopt(vend);
 
 	mb();
 }
diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 1953e9c9391a..66338a60aa6e 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -52,12 +52,18 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 	int i, j;
 
 	for (i = 0; i < slit->locality_count; i++) {
-		if (pxm_to_node(i) == NUMA_NO_NODE)
+		const int from_node = pxm_to_node(i);
+
+		if (from_node == NUMA_NO_NODE)
 			continue;
+
 		for (j = 0; j < slit->locality_count; j++) {
-			if (pxm_to_node(j) == NUMA_NO_NODE)
+			const int to_node = pxm_to_node(j);
+
+			if (to_node == NUMA_NO_NODE)
 				continue;
-			numa_set_distance(pxm_to_node(i), pxm_to_node(j),
+
+			numa_set_distance(from_node, to_node,
 				slit->entry[slit->locality_count * i + j]);
 		}
 	}
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index e063eed0f912..5c6fc3577a49 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -13,9 +13,6 @@ obj-y				+= legacy.o irq.o
 
 obj-$(CONFIG_STA2X11)           += sta2x11-fixup.o
 
-obj-$(CONFIG_X86_VISWS)		+= visws.o
-
-obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 obj-$(CONFIG_X86_NUMACHIP)	+= numachip.o
 
 obj-$(CONFIG_X86_INTEL_MID)	+= intel_mid_pci.o
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 4f25ec077552..01edac6c5e18 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -218,9 +218,8 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status
-resource_to_addr(struct acpi_resource *resource,
-			struct acpi_resource_address64 *addr)
+static acpi_status resource_to_addr(struct acpi_resource *resource,
+				    struct acpi_resource_address64 *addr)
 {
 	acpi_status status;
 	struct acpi_resource_memory24 *memory24;
@@ -265,8 +264,7 @@ resource_to_addr(struct acpi_resource *resource,
 	return AE_ERROR;
 }
 
-static acpi_status
-count_resource(struct acpi_resource *acpi_res, void *data)
+static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
 	struct acpi_resource_address64 addr;
@@ -278,8 +276,7 @@ count_resource(struct acpi_resource *acpi_res, void *data)
 	return AE_OK;
 }
 
-static acpi_status
-setup_resource(struct acpi_resource *acpi_res, void *data)
+static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
 	struct resource *res;
@@ -435,9 +432,9 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
 	__release_pci_root_info(info);
 }
 
-static void
-probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
-		    int busnum, int domain)
+static void probe_pci_root_info(struct pci_root_info *info,
+				struct acpi_device *device,
+				int busnum, int domain)
 {
 	size_t size;
 
@@ -473,16 +470,13 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	struct acpi_device *device = root->device;
-	struct pci_root_info *info = NULL;
+	struct pci_root_info *info;
 	int domain = root->segment;
 	int busnum = root->secondary.start;
 	LIST_HEAD(resources);
-	struct pci_bus *bus = NULL;
+	struct pci_bus *bus;
 	struct pci_sysdata *sd;
 	int node;
-#ifdef CONFIG_ACPI_NUMA
-	int pxm;
-#endif
 
 	if (pci_ignore_seg)
 		domain = 0;
@@ -494,19 +488,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 		return NULL;
 	}
 
-	node = -1;
-#ifdef CONFIG_ACPI_NUMA
-	pxm = acpi_get_pxm(device->handle);
-	if (pxm >= 0)
-		node = pxm_to_node(pxm);
-	if (node != -1)
-		set_mp_bus_to_node(busnum, node);
-	else
-#endif
-		node = get_mp_bus_to_node(busnum);
+	node = acpi_get_node(device->handle);
+	if (node == NUMA_NO_NODE)
+		node = x86_pci_root_bus_node(busnum);
 
-	if (node != -1 && !node_online(node))
-		node = -1;
+	if (node != NUMA_NO_NODE && !node_online(node))
+		node = NUMA_NO_NODE;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info) {
@@ -519,15 +506,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	sd->domain = domain;
 	sd->node = node;
 	sd->companion = device;
-	/*
-	 * Maybe the desired pci bus has been already scanned. In such case
-	 * it is unnecessary to scan the pci bus with the given domain,busnum.
-	 */
+
 	bus = pci_find_bus(domain, busnum);
 	if (bus) {
 		/*
-		 * If the desired bus exits, the content of bus->sysdata will
-		 * be replaced by sd.
+		 * If the desired bus has been scanned already, replace
+		 * its bus->sysdata.
 		 */
 		memcpy(bus->sysdata, sd, sizeof(*sd));
 		kfree(info);
@@ -572,15 +556,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 			pcie_bus_configure_settings(child);
 	}
 
-	if (bus && node != -1) {
-#ifdef CONFIG_ACPI_NUMA
-		if (pxm >= 0)
-			dev_printk(KERN_DEBUG, &bus->dev,
-				   "on NUMA node %d (pxm %d)\n", node, pxm);
-#else
+	if (bus && node != NUMA_NO_NODE)
 		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
-#endif
-	}
 
 	return bus;
 }
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index a48be98e9ded..a313a7fb6b86 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -44,15 +44,6 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link)
 	return NULL;
 }
 
-static void __init set_mp_bus_range_to_node(int min_bus, int max_bus, int node)
-{
-#ifdef CONFIG_NUMA
-	int j;
-
-	for (j = min_bus; j <= max_bus; j++)
-		set_mp_bus_to_node(j, node);
-#endif
-}
 /**
  * early_fill_mp_bus_to_node()
  * called before pcibios_scan_root and pci_scan_bus
@@ -117,7 +108,6 @@ static int __init early_fill_mp_bus_info(void)
 		min_bus = (reg >> 16) & 0xff;
 		max_bus = (reg >> 24) & 0xff;
 		node = (reg >> 4) & 0x07;
-		set_mp_bus_range_to_node(min_bus, max_bus, node);
 		link = (reg >> 8) & 0x03;
 
 		info = alloc_pci_root_info(min_bus, max_bus, node, link);
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index c2735feb2508..f3a2cfc14125 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -10,9 +10,6 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
 {
 	struct pci_root_info *info;
 
-	if (list_empty(&pci_root_infos))
-		return NULL;
-
 	list_for_each_entry(info, &pci_root_infos, list)
 		if (info->busn.start == bus)
 			return info;
@@ -20,6 +17,16 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
 	return NULL;
 }
 
+int x86_pci_root_bus_node(int bus)
+{
+	struct pci_root_info *info = x86_find_pci_root_info(bus);
+
+	if (!info)
+		return NUMA_NO_NODE;
+
+	return info->node;
+}
+
 void x86_pci_root_bus_resources(int bus, struct list_head *resources)
 {
 	struct pci_root_info *info = x86_find_pci_root_info(bus);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 981c2dbd72cc..059a76c29739 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -456,19 +456,25 @@ void __init dmi_check_pciprobe(void)
 	dmi_check_system(pciprobe_dmi_table);
 }
 
-struct pci_bus *pcibios_scan_root(int busnum)
+void pcibios_scan_root(int busnum)
 {
-	struct pci_bus *bus = NULL;
+	struct pci_bus *bus;
+	struct pci_sysdata *sd;
+	LIST_HEAD(resources);
 
-	while ((bus = pci_find_next_bus(bus)) != NULL) {
-		if (bus->number == busnum) {
-			/* Already scanned */
-			return bus;
-		}
+	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+	if (!sd) {
+		printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum);
+		return;
+	}
+	sd->node = x86_pci_root_bus_node(busnum);
+	x86_pci_root_bus_resources(busnum, &resources);
+	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
+	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
+	if (!bus) {
+		pci_free_resource_list(&resources);
+		kfree(sd);
 	}
-
-	return pci_scan_bus_on_node(busnum, &pci_root_ops,
-					get_mp_bus_to_node(busnum));
 }
 
 void __init pcibios_set_cache_line_size(void)
@@ -561,7 +567,6 @@ char * __init pcibios_setup(char *str)
 		pci_probe |= PCI_PROBE_NOEARLY;
 		return NULL;
 	}
-#ifndef CONFIG_X86_VISWS
 	else if (!strcmp(str, "usepirqmask")) {
 		pci_probe |= PCI_USE_PIRQ_MASK;
 		return NULL;
@@ -571,9 +576,7 @@ char * __init pcibios_setup(char *str)
 	} else if (!strncmp(str, "lastbus=", 8)) {
 		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
 		return NULL;
-	}
-#endif
-	else if (!strcmp(str, "rom")) {
+	} else if (!strcmp(str, "rom")) {
 		pci_probe |= PCI_ASSIGN_ROMS;
 		return NULL;
 	} else if (!strcmp(str, "norom")) {
@@ -677,105 +680,3 @@ int pci_ext_cfg_avail(void)
 	else
 		return 0;
 }
-
-struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
-{
-	LIST_HEAD(resources);
-	struct pci_bus *bus = NULL;
-	struct pci_sysdata *sd;
-
-	/*
-	 * Allocate per-root-bus (not per bus) arch-specific data.
-	 * TODO: leak; this memory is never freed.
-	 * It's arguable whether it's worth the trouble to care.
-	 */
-	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-	if (!sd) {
-		printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
-		return NULL;
-	}
-	sd->node = node;
-	x86_pci_root_bus_resources(busno, &resources);
-	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
-	bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
-	if (!bus) {
-		pci_free_resource_list(&resources);
-		kfree(sd);
-	}
-
-	return bus;
-}
-
-struct pci_bus *pci_scan_bus_with_sysdata(int busno)
-{
-	return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
-}
-
-/*
- * NUMA info for PCI busses
- *
- * Early arch code is responsible for filling in reasonable values here.
- * A node id of "-1" means "use current node".  In other words, if a bus
- * has a -1 node id, it's not tightly coupled to any particular chunk
- * of memory (as is the case on some Nehalem systems).
- */
-#ifdef CONFIG_NUMA
-
-#define BUS_NR 256
-
-#ifdef CONFIG_X86_64
-
-static int mp_bus_to_node[BUS_NR] = {
-	[0 ... BUS_NR - 1] = -1
-};
-
-void set_mp_bus_to_node(int busnum, int node)
-{
-	if (busnum >= 0 &&  busnum < BUS_NR)
-		mp_bus_to_node[busnum] = node;
-}
-
-int get_mp_bus_to_node(int busnum)
-{
-	int node = -1;
-
-	if (busnum < 0 || busnum > (BUS_NR - 1))
-		return node;
-
-	node = mp_bus_to_node[busnum];
-
-	/*
-	 * let numa_node_id to decide it later in dma_alloc_pages
-	 * if there is no ram on that node
-	 */
-	if (node != -1 && !node_online(node))
-		node = -1;
-
-	return node;
-}
-
-#else /* CONFIG_X86_32 */
-
-static int mp_bus_to_node[BUS_NR] = {
-	[0 ... BUS_NR - 1] = -1
-};
-
-void set_mp_bus_to_node(int busnum, int node)
-{
-	if (busnum >= 0 &&  busnum < BUS_NR)
-	mp_bus_to_node[busnum] = (unsigned char) node;
-}
-
-int get_mp_bus_to_node(int busnum)
-{
-	int node;
-
-	if (busnum < 0 || busnum > (BUS_NR - 1))
-		return 0;
-	node = mp_bus_to_node[busnum];
-	return node;
-}
-
-#endif /* CONFIG_X86_32 */
-
-#endif /* CONFIG_NUMA */
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index bca9e85daaa5..94ae9ae9574f 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -25,9 +25,9 @@ static void pci_fixup_i450nx(struct pci_dev *d)
 		dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,
 			suba, subb);
 		if (busno)
-			pci_scan_bus_with_sysdata(busno);	/* Bus A */
+			pcibios_scan_root(busno);	/* Bus A */
 		if (suba < subb)
-			pci_scan_bus_with_sysdata(suba+1);	/* Bus B */
+			pcibios_scan_root(suba+1);	/* Bus B */
 	}
 	pcibios_last_bus = -1;
 }
@@ -42,7 +42,7 @@ static void pci_fixup_i450gx(struct pci_dev *d)
 	u8 busno;
 	pci_read_config_byte(d, 0x4a, &busno);
 	dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
-	pci_scan_bus_with_sysdata(busno);
+	pcibios_scan_root(busno);
 	pcibios_last_bus = -1;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
@@ -313,9 +313,10 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC1,	pcie_r
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
+ * See pci_map_rom() for use of this flag. Before marking the device
+ * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * by either arch cde or vga-arbitration, if so only apply the fixup to this
+ * already determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -346,12 +347,13 @@ static void pci_fixup_video(struct pci_dev *pdev)
 		}
 		bus = bus->parent;
 	}
-	pci_read_config_word(pdev, PCI_COMMAND, &config);
-	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-		dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
-		if (!vga_default_device())
+	if (!vga_default_device() || pdev == vga_default_device()) {
+		pci_read_config_word(pdev, PCI_COMMAND, &config);
+		if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+			pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+			dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
 			vga_set_default_device(pdev);
+		}
 	}
 }
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index db6b1ab43255..1f642d61a788 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -433,8 +433,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 		 */
 		prot |= _PAGE_CACHE_UC_MINUS;
 
-	prot |= _PAGE_IOMAP;	/* creating a mapping for IO */
-
 	vma->vm_page_prot = __pgprot(prot);
 
 	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 372e9b8989b3..84112f55dd7a 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -136,13 +136,9 @@ static void __init pirq_peer_trick(void)
 		busmap[e->bus] = 1;
 	}
 	for (i = 1; i < 256; i++) {
-		int node;
 		if (!busmap[i] || pci_find_bus(0, i))
 			continue;
-		node = get_mp_bus_to_node(i);
-		if (pci_scan_bus_on_node(i, &pci_root_ops, node))
-			printk(KERN_INFO "PCI: Discovered primary peer "
-			       "bus %02x [IRQ]\n", i);
+		pcibios_scan_root(i);
 	}
 	pcibios_last_bus = -1;
 }
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 4db96fb1c232..5b662c0faf8c 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -37,19 +37,17 @@ int __init pci_legacy_init(void)
 void pcibios_scan_specific_bus(int busn)
 {
 	int devfn;
-	long node;
 	u32 l;
 
 	if (pci_find_bus(0, busn))
 		return;
 
-	node = get_mp_bus_to_node(busn);
 	for (devfn = 0; devfn < 256; devfn += 8) {
 		if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
 		    l != 0x0000 && l != 0xffff) {
 			DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
 			printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
-			pci_scan_bus_on_node(busn, &pci_root_ops, node);
+			pcibios_scan_root(busn);
 			return;
 		}
 	}
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
deleted file mode 100644
index 72c229f9ebcf..000000000000
--- a/arch/x86/pci/numaq_32.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * numaq_32.c - Low-level PCI access for NUMA-Q machines
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/nodemask.h>
-#include <asm/apic.h>
-#include <asm/mpspec.h>
-#include <asm/pci_x86.h>
-#include <asm/numaq.h>
-
-#define BUS2QUAD(global) (mp_bus_id_to_node[global])
-
-#define BUS2LOCAL(global) (mp_bus_id_to_local[global])
-
-#define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
-
-#define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
-	(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
-
-static void write_cf8(unsigned bus, unsigned devfn, unsigned reg)
-{
-	unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg);
-	if (xquad_portio)
-		writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus)));
-	else
-		outl(val, 0xCF8);
-}
-
-static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
-			     unsigned int devfn, int reg, int len, u32 *value)
-{
-	unsigned long flags;
-	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
-
-	WARN_ON(seg);
-	if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
-		return -EINVAL;
-
-	raw_spin_lock_irqsave(&pci_config_lock, flags);
-
-	write_cf8(bus, devfn, reg);
-
-	switch (len) {
-	case 1:
-		if (xquad_portio)
-			*value = readb(adr + (reg & 3));
-		else
-			*value = inb(0xCFC + (reg & 3));
-		break;
-	case 2:
-		if (xquad_portio)
-			*value = readw(adr + (reg & 2));
-		else
-			*value = inw(0xCFC + (reg & 2));
-		break;
-	case 4:
-		if (xquad_portio)
-			*value = readl(adr);
-		else
-			*value = inl(0xCFC);
-		break;
-	}
-
-	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
-
-	return 0;
-}
-
-static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
-			      unsigned int devfn, int reg, int len, u32 value)
-{
-	unsigned long flags;
-	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
-
-	WARN_ON(seg);
-	if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
-		return -EINVAL;
-
-	raw_spin_lock_irqsave(&pci_config_lock, flags);
-
-	write_cf8(bus, devfn, reg);
-
-	switch (len) {
-	case 1:
-		if (xquad_portio)
-			writeb(value, adr + (reg & 3));
-		else
-			outb((u8)value, 0xCFC + (reg & 3));
-		break;
-	case 2:
-		if (xquad_portio)
-			writew(value, adr + (reg & 2));
-		else
-			outw((u16)value, 0xCFC + (reg & 2));
-		break;
-	case 4:
-		if (xquad_portio)
-			writel(value, adr + reg);
-		else
-			outl((u32)value, 0xCFC);
-		break;
-	}
-
-	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
-
-	return 0;
-}
-
-#undef PCI_CONF1_MQ_ADDRESS
-
-static const struct pci_raw_ops pci_direct_conf1_mq = {
-	.read	= pci_conf1_mq_read,
-	.write	= pci_conf1_mq_write
-};
-
-
-static void pci_fixup_i450nx(struct pci_dev *d)
-{
-	/*
-	 * i450NX -- Find and scan all secondary buses on all PXB's.
-	 */
-	int pxb, reg;
-	u8 busno, suba, subb;
-	int quad = BUS2QUAD(d->bus->number);
-
-	dev_info(&d->dev, "searching for i450NX host bridges\n");
-	reg = 0xd0;
-	for(pxb=0; pxb<2; pxb++) {
-		pci_read_config_byte(d, reg++, &busno);
-		pci_read_config_byte(d, reg++, &suba);
-		pci_read_config_byte(d, reg++, &subb);
-		dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n",
-			pxb, busno, suba, subb);
-		if (busno) {
-			/* Bus A */
-			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
-		}
-		if (suba < subb) {
-			/* Bus B */
-			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
-		}
-	}
-	pcibios_last_bus = -1;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
-
-int __init pci_numaq_init(void)
-{
-	int quad;
-
-	raw_pci_ops = &pci_direct_conf1_mq;
-
-	pcibios_scan_root(0);
-	if (num_online_nodes() > 1)
-		for_each_online_node(quad) {
-			if (quad == 0)
-				continue;
-			printk("Scanning PCI bus %d for quad %d\n", 
-				QUADLOCAL2BUS(quad,0), quad);
-			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
-		}
-	return 0;
-}
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
deleted file mode 100644
index 3e6d2a6db866..000000000000
--- a/arch/x86/pci/visws.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *	Low-Level PCI Support for SGI Visual Workstation
- *
- *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/pci_x86.h>
-#include <asm/visws/cobalt.h>
-#include <asm/visws/lithium.h>
-
-static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
-static void pci_visws_disable_irq(struct pci_dev *dev) { }
-
-/* int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; */
-/* void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; */
-
-/* void __init pcibios_penalize_isa_irq(int irq, int active) {} */
-
-
-unsigned int pci_bus0, pci_bus1;
-
-static int __init visws_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int irq, bus = dev->bus->number;
-
-	pin--;
-
-	/* Nothing useful at PIIX4 pin 1 */
-	if (bus == pci_bus0 && slot == 4 && pin == 0)
-		return -1;
-
-	/* PIIX4 USB is on Bus 0, Slot 4, Line 3 */
-	if (bus == pci_bus0 && slot == 4 && pin == 3) {
-		irq = CO_IRQ(CO_APIC_PIIX4_USB);
-		goto out;
-	}
-
-	/* First pin spread down 1 APIC entry per slot */
-	if (pin == 0) {
-		irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 :
-						CO_APIC_PCIA_BASE0) + slot);
-		goto out;
-	}
-
-	/* lines 1,2,3 from any slot is shared in this twirly pattern */
-	if (bus == pci_bus1) {
-		/* lines 1-3 from devices 0 1 rotate over 2 apic entries */
-		irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2));
-	} else { /* bus == pci_bus0 */
-		/* lines 1-3 from devices 0-3 rotate over 3 apic entries */
-		if (slot == 0)
-			slot = 3; /* same pattern */
-		irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3));
-	}
-out:
-	printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq);
-	return irq;
-}
-
-int __init pci_visws_init(void)
-{
-	pcibios_enable_irq = &pci_visws_enable_irq;
-	pcibios_disable_irq = &pci_visws_disable_irq;
-
-	/* The VISWS supports configuration access type 1 only */
-	pci_probe = (pci_probe | PCI_PROBE_CONF1) &
-		    ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2);
-
-	pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;
-	pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff;
-
-	printk(KERN_INFO "PCI: Lithium bridge A bus: %u, "
-		"bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
-
-	raw_pci_ops = &pci_direct_conf1;
-	pci_scan_bus_with_sysdata(pci_bus0);
-	pci_scan_bus_with_sysdata(pci_bus1);
-	pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
-	pcibios_resource_survey();
-	/* Request bus scan */
-	return 1;
-}
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 103e702ec5a7..905956f16465 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -178,6 +178,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 	i = 0;
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
+					       (type == PCI_CAP_ID_MSI) ? nvec : 1,
 					       (type == PCI_CAP_ID_MSIX) ?
 					       "pcifront-msi-x" :
 					       "pcifront-msi",
@@ -245,6 +246,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 				"xen: msi already bound to pirq=%d\n", pirq);
 		}
 		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
+					       (type == PCI_CAP_ID_MSI) ? nvec : 1,
 					       (type == PCI_CAP_ID_MSIX) ?
 					       "msi-x" : "msi",
 					       DOMID_SELF);
@@ -269,9 +271,6 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 	int ret = 0;
 	struct msi_desc *msidesc;
 
-	if (type == PCI_CAP_ID_MSI && nvec > 1)
-		return 1;
-
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 		struct physdev_map_pirq map_irq;
 		domid_t domid;
@@ -291,7 +290,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 			      (pci_domain_nr(dev->bus) << 16);
 		map_irq.devfn = dev->devfn;
 
-		if (type == PCI_CAP_ID_MSIX) {
+		if (type == PCI_CAP_ID_MSI && nvec > 1) {
+			map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI;
+			map_irq.entry_nr = nvec;
+		} else if (type == PCI_CAP_ID_MSIX) {
 			int pos;
 			u32 table_offset, bir;
 
@@ -308,6 +310,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		if (pci_seg_supported)
 			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
 						    &map_irq);
+		if (type == PCI_CAP_ID_MSI && nvec > 1 && ret) {
+			/*
+			 * If MAP_PIRQ_TYPE_MULTI_MSI is not available
+			 * there's nothing else we can do in this case.
+			 * Just set ret > 0 so driver can retry with
+			 * single MSI.
+			 */
+			ret = 1;
+			goto out;
+		}
 		if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
 			map_irq.type = MAP_PIRQ_TYPE_MSI;
 			map_irq.index = -1;
@@ -324,11 +336,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 			goto out;
 		}
 
-		ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
-					       map_irq.pirq,
-					       (type == PCI_CAP_ID_MSIX) ?
-					       "msi-x" : "msi",
-						domid);
+		ret = xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq,
+		                               (type == PCI_CAP_ID_MSI) ? nvec : 1,
+		                               (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi",
+		                               domid);
 		if (ret < 0)
 			goto out;
 	}
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 20342d4c82ce..85afde1fa3e5 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -9,5 +9,4 @@ obj-y	+= olpc/
 obj-y	+= scx200/
 obj-y	+= sfi/
 obj-y	+= ts5500/
-obj-y	+= visws/
 obj-y	+= uv/
diff --git a/arch/x86/platform/ts5500/ts5500.c b/arch/x86/platform/ts5500/ts5500.c
index 39febb214e8c..9471b9456f25 100644
--- a/arch/x86/platform/ts5500/ts5500.c
+++ b/arch/x86/platform/ts5500/ts5500.c
@@ -88,7 +88,7 @@ struct ts5500_sbc {
 static const struct {
 	const char * const string;
 	const ssize_t offset;
-} ts5500_signatures[] __initdata = {
+} ts5500_signatures[] __initconst = {
 	{ "TS-5x00 AMD Elan", 0xb14 },
 };
 
diff --git a/arch/x86/platform/visws/Makefile b/arch/x86/platform/visws/Makefile
deleted file mode 100644
index 91bc17ab2fd5..000000000000
--- a/arch/x86/platform/visws/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c
deleted file mode 100644
index 94d8a39332ec..000000000000
--- a/arch/x86/platform/visws/visws_quirks.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- *  SGI Visual Workstation support and quirks, unmaintained.
- *
- *  Split out from setup.c by davej@suse.de
- *
- *	Copyright (C) 1999 Bent Hagemark, Ingo Molnar
- *
- *  SGI Visual Workstation interrupt controller
- *
- *  The Cobalt system ASIC in the Visual Workstation contains a "Cobalt" APIC
- *  which serves as the main interrupt controller in the system.  Non-legacy
- *  hardware in the system uses this controller directly.  Legacy devices
- *  are connected to the PIIX4 which in turn has its 8259(s) connected to
- *  a of the Cobalt APIC entry.
- *
- *  09/02/2000 - Updated for 2.4 by jbarnes@sgi.com
- *
- *  25/11/2002 - Updated for 2.5 by Andrey Panin <pazke@orbita1.ru>
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/visws/cobalt.h>
-#include <asm/visws/piix4.h>
-#include <asm/io_apic.h>
-#include <asm/fixmap.h>
-#include <asm/reboot.h>
-#include <asm/setup.h>
-#include <asm/apic.h>
-#include <asm/e820.h>
-#include <asm/time.h>
-#include <asm/io.h>
-
-#include <linux/kernel_stat.h>
-
-#include <asm/i8259.h>
-#include <asm/irq_vectors.h>
-#include <asm/visws/lithium.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-
-extern int no_broadcast;
-
-char visws_board_type	= -1;
-char visws_board_rev	= -1;
-
-static void __init visws_time_init(void)
-{
-	printk(KERN_INFO "Starting Cobalt Timer system clock\n");
-
-	/* Set the countdown value */
-	co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
-
-	/* Start the timer */
-	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
-
-	/* Enable (unmask) the timer interrupt */
-	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
-
-	setup_default_timer_irq();
-}
-
-/* Replaces the default init_ISA_irqs in the generic setup */
-static void __init visws_pre_intr_init(void);
-
-/* Quirk for machine specific memory setup. */
-
-#define MB (1024 * 1024)
-
-unsigned long sgivwfb_mem_phys;
-unsigned long sgivwfb_mem_size;
-EXPORT_SYMBOL(sgivwfb_mem_phys);
-EXPORT_SYMBOL(sgivwfb_mem_size);
-
-long long mem_size __initdata = 0;
-
-static char * __init visws_memory_setup(void)
-{
-	long long gfx_mem_size = 8 * MB;
-
-	mem_size = boot_params.alt_mem_k;
-
-	if (!mem_size) {
-		printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
-		mem_size = 128 * MB;
-	}
-
-	/*
-	 * this hardcodes the graphics memory to 8 MB
-	 * it really should be sized dynamically (or at least
-	 * set as a boot param)
-	 */
-	if (!sgivwfb_mem_size) {
-		printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
-		sgivwfb_mem_size = 8 * MB;
-	}
-
-	/*
-	 * Trim to nearest MB
-	 */
-	sgivwfb_mem_size &= ~((1 << 20) - 1);
-	sgivwfb_mem_phys = mem_size - gfx_mem_size;
-
-	e820_add_region(0, LOWMEMSIZE(), E820_RAM);
-	e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
-	e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
-
-	return "PROM";
-}
-
-static void visws_machine_emergency_restart(void)
-{
-	/*
-	 * Visual Workstations restart after this
-	 * register is poked on the PIIX4
-	 */
-	outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
-}
-
-static void visws_machine_power_off(void)
-{
-	unsigned short pm_status;
-/*	extern unsigned int pci_bus0; */
-
-	while ((pm_status = inw(PMSTS_PORT)) & 0x100)
-		outw(pm_status, PMSTS_PORT);
-
-	outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT);
-
-	mdelay(10);
-
-#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
-	(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
-
-/*	outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8); */
-	outl(PIIX_SPECIAL_STOP, 0xCFC);
-}
-
-static void __init visws_get_smp_config(unsigned int early)
-{
-}
-
-/*
- * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesn't have a BIOS(-configuration table).
- * No problem for Linux.
- */
-
-static void __init MP_processor_info(struct mpc_cpu *m)
-{
-	int ver, logical_apicid;
-	physid_mask_t apic_cpus;
-
-	if (!(m->cpuflag & CPU_ENABLED))
-		return;
-
-	logical_apicid = m->apicid;
-	printk(KERN_INFO "%sCPU #%d %u:%u APIC version %d\n",
-	       m->cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "",
-	       m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
-	       (m->cpufeature & CPU_MODEL_MASK) >> 4, m->apicver);
-
-	if (m->cpuflag & CPU_BOOTPROCESSOR)
-		boot_cpu_physical_apicid = m->apicid;
-
-	ver = m->apicver;
-	if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) {
-		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
-			m->apicid, MAX_LOCAL_APIC);
-		return;
-	}
-
-	apic->apicid_to_cpu_present(m->apicid, &apic_cpus);
-	physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
-	/*
-	 * Validate version
-	 */
-	if (ver == 0x0) {
-		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! "
-			"fixing up to 0x10. (tell your hw vendor)\n",
-			m->apicid);
-		ver = 0x10;
-	}
-	apic_version[m->apicid] = ver;
-}
-
-static void __init visws_find_smp_config(void)
-{
-	struct mpc_cpu *mp = phys_to_virt(CO_CPU_TAB_PHYS);
-	unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
-
-	if (ncpus > CO_CPU_MAX) {
-		printk(KERN_WARNING "find_visws_smp: got cpu count of %d at %p\n",
-			ncpus, mp);
-
-		ncpus = CO_CPU_MAX;
-	}
-
-	if (ncpus > setup_max_cpus)
-		ncpus = setup_max_cpus;
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	smp_found_config = 1;
-#endif
-	while (ncpus--)
-		MP_processor_info(mp++);
-
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-}
-
-static void visws_trap_init(void);
-
-void __init visws_early_detect(void)
-{
-	int raw;
-
-	visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
-							 >> PIIX_GPI_BD_SHIFT;
-
-	if (visws_board_type < 0)
-		return;
-
-	/*
-	 * Override the default platform setup functions
-	 */
-	x86_init.resources.memory_setup = visws_memory_setup;
-	x86_init.mpparse.get_smp_config = visws_get_smp_config;
-	x86_init.mpparse.find_smp_config = visws_find_smp_config;
-	x86_init.irqs.pre_vector_init = visws_pre_intr_init;
-	x86_init.irqs.trap_init = visws_trap_init;
-	x86_init.timers.timer_init = visws_time_init;
-	x86_init.pci.init = pci_visws_init;
-	x86_init.pci.init_irq = x86_init_noop;
-
-	/*
-	 * Install reboot quirks:
-	 */
-	pm_power_off			= visws_machine_power_off;
-	machine_ops.emergency_restart	= visws_machine_emergency_restart;
-
-	/*
-	 * Do not use broadcast IPIs:
-	 */
-	no_broadcast = 0;
-
-#ifdef CONFIG_X86_IO_APIC
-	/*
-	 * Turn off IO-APIC detection and initialization:
-	 */
-	skip_ioapic_setup		= 1;
-#endif
-
-	/*
-	 * Get Board rev.
-	 * First, we have to initialize the 307 part to allow us access
-	 * to the GPIO registers.  Let's map them at 0x0fc0 which is right
-	 * after the PIIX4 PM section.
-	 */
-	outb_p(SIO_DEV_SEL, SIO_INDEX);
-	outb_p(SIO_GP_DEV, SIO_DATA);	/* Talk to GPIO regs. */
-
-	outb_p(SIO_DEV_MSB, SIO_INDEX);
-	outb_p(SIO_GP_MSB, SIO_DATA);	/* MSB of GPIO base address */
-
-	outb_p(SIO_DEV_LSB, SIO_INDEX);
-	outb_p(SIO_GP_LSB, SIO_DATA);	/* LSB of GPIO base address */
-
-	outb_p(SIO_DEV_ENB, SIO_INDEX);
-	outb_p(1, SIO_DATA);		/* Enable GPIO registers. */
-
-	/*
-	 * Now, we have to map the power management section to write
-	 * a bit which enables access to the GPIO registers.
-	 * What lunatic came up with this shit?
-	 */
-	outb_p(SIO_DEV_SEL, SIO_INDEX);
-	outb_p(SIO_PM_DEV, SIO_DATA);	/* Talk to GPIO regs. */
-
-	outb_p(SIO_DEV_MSB, SIO_INDEX);
-	outb_p(SIO_PM_MSB, SIO_DATA);	/* MSB of PM base address */
-
-	outb_p(SIO_DEV_LSB, SIO_INDEX);
-	outb_p(SIO_PM_LSB, SIO_DATA);	/* LSB of PM base address */
-
-	outb_p(SIO_DEV_ENB, SIO_INDEX);
-	outb_p(1, SIO_DATA);		/* Enable PM registers. */
-
-	/*
-	 * Now, write the PM register which enables the GPIO registers.
-	 */
-	outb_p(SIO_PM_FER2, SIO_PM_INDEX);
-	outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
-
-	/*
-	 * Now, initialize the GPIO registers.
-	 * We want them all to be inputs which is the
-	 * power on default, so let's leave them alone.
-	 * So, let's just read the board rev!
-	 */
-	raw = inb_p(SIO_GP_DATA1);
-	raw &= 0x7f;	/* 7 bits of valid board revision ID. */
-
-	if (visws_board_type == VISWS_320) {
-		if (raw < 0x6) {
-			visws_board_rev = 4;
-		} else if (raw < 0xc) {
-			visws_board_rev = 5;
-		} else {
-			visws_board_rev = 6;
-		}
-	} else if (visws_board_type == VISWS_540) {
-			visws_board_rev = 2;
-		} else {
-			visws_board_rev = raw;
-		}
-
-	printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n",
-	       (visws_board_type == VISWS_320 ? "320" :
-	       (visws_board_type == VISWS_540 ? "540" :
-		"unknown")), visws_board_rev);
-}
-
-#define A01234 (LI_INTA_0 | LI_INTA_1 | LI_INTA_2 | LI_INTA_3 | LI_INTA_4)
-#define BCD (LI_INTB | LI_INTC | LI_INTD)
-#define ALLDEVS (A01234 | BCD)
-
-static __init void lithium_init(void)
-{
-	set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
-	set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
-
-	if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-	    (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
-		printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
-/*		panic("This machine is not SGI Visual Workstation 320/540"); */
-	}
-
-	if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-	    (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
-		printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
-/*		panic("This machine is not SGI Visual Workstation 320/540"); */
-	}
-
-	li_pcia_write16(LI_PCI_INTEN, ALLDEVS);
-	li_pcib_write16(LI_PCI_INTEN, ALLDEVS);
-}
-
-static __init void cobalt_init(void)
-{
-	/*
-	 * On normal SMP PC this is used only with SMP, but we have to
-	 * use it and set it up here to start the Cobalt clock
-	 */
-	set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
-	setup_local_APIC();
-	printk(KERN_INFO "Local APIC Version %#x, ID %#x\n",
-		(unsigned int)apic_read(APIC_LVR),
-		(unsigned int)apic_read(APIC_ID));
-
-	set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
-	set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
-	printk(KERN_INFO "Cobalt Revision %#lx, APIC ID %#lx\n",
-		co_cpu_read(CO_CPU_REV), co_apic_read(CO_APIC_ID));
-
-	/* Enable Cobalt APIC being careful to NOT change the ID! */
-	co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID) | CO_APIC_ENABLE);
-
-	printk(KERN_INFO "Cobalt APIC enabled: ID reg %#lx\n",
-		co_apic_read(CO_APIC_ID));
-}
-
-static void __init visws_trap_init(void)
-{
-	lithium_init();
-	cobalt_init();
-}
-
-/*
- * IRQ controller / APIC support:
- */
-
-static DEFINE_SPINLOCK(cobalt_lock);
-
-/*
- * Set the given Cobalt APIC Redirection Table entry to point
- * to the given IDT vector/index.
- */
-static inline void co_apic_set(int entry, int irq)
-{
-	co_apic_write(CO_APIC_LO(entry), CO_APIC_LEVEL | (irq + FIRST_EXTERNAL_VECTOR));
-	co_apic_write(CO_APIC_HI(entry), 0);
-}
-
-/*
- * Cobalt (IO)-APIC functions to handle PCI devices.
- */
-static inline int co_apic_ide0_hack(void)
-{
-	extern char visws_board_type;
-	extern char visws_board_rev;
-
-	if (visws_board_type == VISWS_320 && visws_board_rev == 5)
-		return 5;
-	return CO_APIC_IDE0;
-}
-
-static int is_co_apic(unsigned int irq)
-{
-	if (IS_CO_APIC(irq))
-		return CO_APIC(irq);
-
-	switch (irq) {
-		case 0: return CO_APIC_CPU;
-		case CO_IRQ_IDE0: return co_apic_ide0_hack();
-		case CO_IRQ_IDE1: return CO_APIC_IDE1;
-		default: return -1;
-	}
-}
-
-
-/*
- * This is the SGI Cobalt (IO-)APIC:
- */
-static void enable_cobalt_irq(struct irq_data *data)
-{
-	co_apic_set(is_co_apic(data->irq), data->irq);
-}
-
-static void disable_cobalt_irq(struct irq_data *data)
-{
-	int entry = is_co_apic(data->irq);
-
-	co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
-	co_apic_read(CO_APIC_LO(entry));
-}
-
-static void ack_cobalt_irq(struct irq_data *data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cobalt_lock, flags);
-	disable_cobalt_irq(data);
-	apic_write(APIC_EOI, APIC_EOI_ACK);
-	spin_unlock_irqrestore(&cobalt_lock, flags);
-}
-
-static struct irq_chip cobalt_irq_type = {
-	.name		= "Cobalt-APIC",
-	.irq_enable	= enable_cobalt_irq,
-	.irq_disable	= disable_cobalt_irq,
-	.irq_ack	= ack_cobalt_irq,
-};
-
-
-/*
- * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
- * -- not the manner expected by the code in i8259.c.
- *
- * there is a 'master' physical interrupt source that gets sent to
- * the CPU. But in the chipset there are various 'virtual' interrupts
- * waiting to be handled. We represent this to Linux through a 'master'
- * interrupt controller type, and through a special virtual interrupt-
- * controller. Device drivers only see the virtual interrupt sources.
- */
-static unsigned int startup_piix4_master_irq(struct irq_data *data)
-{
-	legacy_pic->init(0);
-	enable_cobalt_irq(data);
-	return 0;
-}
-
-static struct irq_chip piix4_master_irq_type = {
-	.name		= "PIIX4-master",
-	.irq_startup	= startup_piix4_master_irq,
-	.irq_ack	= ack_cobalt_irq,
-};
-
-static void pii4_mask(struct irq_data *data) { }
-
-static struct irq_chip piix4_virtual_irq_type = {
-	.name		= "PIIX4-virtual",
-	.irq_mask	= pii4_mask,
-};
-
-/*
- * PIIX4-8259 master/virtual functions to handle interrupt requests
- * from legacy devices: floppy, parallel, serial, rtc.
- *
- * None of these get Cobalt APIC entries, neither do they have IDT
- * entries. These interrupts are purely virtual and distributed from
- * the 'master' interrupt source: CO_IRQ_8259.
- *
- * When the 8259 interrupts its handler figures out which of these
- * devices is interrupting and dispatches to its handler.
- *
- * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/
- * enable_irq gets the right irq. This 'master' irq is never directly
- * manipulated by any driver.
- */
-static irqreturn_t piix4_master_intr(int irq, void *dev_id)
-{
-	unsigned long flags;
-	int realirq;
-
-	raw_spin_lock_irqsave(&i8259A_lock, flags);
-
-	/* Find out what's interrupting in the PIIX4 master 8259 */
-	outb(0x0c, 0x20);		/* OCW3 Poll command */
-	realirq = inb(0x20);
-
-	/*
-	 * Bit 7 == 0 means invalid/spurious
-	 */
-	if (unlikely(!(realirq & 0x80)))
-		goto out_unlock;
-
-	realirq &= 7;
-
-	if (unlikely(realirq == 2)) {
-		outb(0x0c, 0xa0);
-		realirq = inb(0xa0);
-
-		if (unlikely(!(realirq & 0x80)))
-			goto out_unlock;
-
-		realirq = (realirq & 7) + 8;
-	}
-
-	/* mask and ack interrupt */
-	cached_irq_mask |= 1 << realirq;
-	if (unlikely(realirq > 7)) {
-		inb(0xa1);
-		outb(cached_slave_mask, 0xa1);
-		outb(0x60 + (realirq & 7), 0xa0);
-		outb(0x60 + 2, 0x20);
-	} else {
-		inb(0x21);
-		outb(cached_master_mask, 0x21);
-		outb(0x60 + realirq, 0x20);
-	}
-
-	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-
-	/*
-	 * handle this 'virtual interrupt' as a Cobalt one now.
-	 */
-	generic_handle_irq(realirq);
-
-	return IRQ_HANDLED;
-
-out_unlock:
-	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-	return IRQ_NONE;
-}
-
-static struct irqaction master_action = {
-	.handler =	piix4_master_intr,
-	.name =		"PIIX4-8259",
-	.flags =	IRQF_NO_THREAD,
-};
-
-static struct irqaction cascade_action = {
-	.handler = 	no_action,
-	.name =		"cascade",
-	.flags =	IRQF_NO_THREAD,
-};
-
-static inline void set_piix4_virtual_irq_type(void)
-{
-	piix4_virtual_irq_type.irq_enable = i8259A_chip.irq_unmask;
-	piix4_virtual_irq_type.irq_disable = i8259A_chip.irq_mask;
-	piix4_virtual_irq_type.irq_unmask = i8259A_chip.irq_unmask;
-}
-
-static void __init visws_pre_intr_init(void)
-{
-	int i;
-
-	set_piix4_virtual_irq_type();
-
-	for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
-		struct irq_chip *chip = NULL;
-
-		if (i == 0)
-			chip = &cobalt_irq_type;
-		else if (i == CO_IRQ_IDE0)
-			chip = &cobalt_irq_type;
-		else if (i == CO_IRQ_IDE1)
-			chip = &cobalt_irq_type;
-		else if (i == CO_IRQ_8259)
-			chip = &piix4_master_irq_type;
-		else if (i < CO_IRQ_APIC0)
-			chip = &piix4_virtual_irq_type;
-		else if (IS_CO_APIC(i))
-			chip = &cobalt_irq_type;
-
-		if (chip)
-			irq_set_chip(i, chip);
-	}
-
-	setup_irq(CO_IRQ_8259, &master_action);
-	setup_irq(2, &cascade_action);
-}
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/Makefile b/arch/x86/vdso/Makefile
index fd14be1d1472..9206ac7961a5 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -2,6 +2,8 @@
 # Building vDSO images for x86.
 #
 
+KBUILD_CFLAGS += $(DISABLE_LTO)
+
 VDSO64-$(CONFIG_X86_64)		:= y
 VDSOX32-$(CONFIG_X86_X32_ABI)	:= y
 VDSO32-$(CONFIG_X86_32)		:= y
@@ -35,7 +37,8 @@ export CPPFLAGS_vdso.lds += -P -C
 
 VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 			-Wl,--no-undefined \
-		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+			-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 \
+			$(DISABLE_LTO)
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
 
@@ -127,7 +130,7 @@ vdso32.so-$(VDSO32-y)		+= sysenter
 vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
@@ -181,7 +184,8 @@ quiet_cmd_vdso = VDSO    $@
 		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
 		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+		$(LTO_CFLAGS)
 GCOV_PROFILE := n
 
 #
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 01b90261fa38..e88fda867a33 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -7,7 +7,7 @@ config XEN
 	depends on PARAVIRT
 	select PARAVIRT_CLOCK
 	select XEN_HAVE_PVMMU
-	depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
+	depends on X86_64 || (X86_32 && X86_PAE)
 	depends on X86_TSC
 	help
 	  This is the Linux Xen port.  Enabling this will allow the
@@ -19,11 +19,6 @@ config XEN_DOM0
 	depends on XEN && PCI_XEN && SWIOTLB_XEN
 	depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI
 
-# Dummy symbol since people have come to rely on the PRIVILEGED_GUEST
-# name in tools.
-config XEN_PRIVILEGED_GUEST
-	def_bool XEN_DOM0
-
 config XEN_PVHVM
 	def_bool y
 	depends on XEN && PCI && X86_LOCAL_APIC
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 201d09a7c46b..c5e21e36a119 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1555,8 +1555,6 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 		__supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
 
-	__supported_pte_mask |= _PAGE_IOMAP;
-
 	/*
 	 * Prevent page tables from being allocated in highmem, even
 	 * if CONFIG_HIGHPTE is enabled.
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 256282e7888b..29166622eeeb 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -399,38 +399,14 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
 		if (unlikely(mfn == INVALID_P2M_ENTRY)) {
 			mfn = 0;
 			flags = 0;
-		} else {
-			/*
-			 * Paramount to do this test _after_ the
-			 * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY &
-			 * IDENTITY_FRAME_BIT resolves to true.
-			 */
-			mfn &= ~FOREIGN_FRAME_BIT;
-			if (mfn & IDENTITY_FRAME_BIT) {
-				mfn &= ~IDENTITY_FRAME_BIT;
-				flags |= _PAGE_IOMAP;
-			}
-		}
+		} else
+			mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);
 		val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
 	}
 
 	return val;
 }
 
-static pteval_t iomap_pte(pteval_t val)
-{
-	if (val & _PAGE_PRESENT) {
-		unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
-		pteval_t flags = val & PTE_FLAGS_MASK;
-
-		/* We assume the pte frame number is a MFN, so
-		   just use it as-is. */
-		val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
-	}
-
-	return val;
-}
-
 __visible pteval_t xen_pte_val(pte_t pte)
 {
 	pteval_t pteval = pte.pte;
@@ -441,9 +417,6 @@ __visible pteval_t xen_pte_val(pte_t pte)
 		pteval = (pteval & ~_PAGE_PAT) | _PAGE_PWT;
 	}
 #endif
-	if (xen_initial_domain() && (pteval & _PAGE_IOMAP))
-		return pteval;
-
 	return pte_mfn_to_pfn(pteval);
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val);
@@ -481,7 +454,6 @@ void xen_set_pat(u64 pat)
 
 __visible pte_t xen_make_pte(pteval_t pte)
 {
-	phys_addr_t addr = (pte & PTE_PFN_MASK);
 #if 0
 	/* If Linux is trying to set a WC pte, then map to the Xen WC.
 	 * If _PAGE_PAT is set, then it probably means it is really
@@ -496,19 +468,7 @@ __visible pte_t xen_make_pte(pteval_t pte)
 			pte = (pte & ~(_PAGE_PCD | _PAGE_PWT)) | _PAGE_PAT;
 	}
 #endif
-	/*
-	 * Unprivileged domains are allowed to do IOMAPpings for
-	 * PCI passthrough, but not map ISA space.  The ISA
-	 * mappings are just dummy local mappings to keep other
-	 * parts of the kernel happy.
-	 */
-	if (unlikely(pte & _PAGE_IOMAP) &&
-	    (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
-		pte = iomap_pte(pte);
-	} else {
-		pte &= ~_PAGE_IOMAP;
-		pte = pte_pfn_to_mfn(pte);
-	}
+	pte = pte_pfn_to_mfn(pte);
 
 	return native_make_pte(pte);
 }
@@ -2096,7 +2056,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 
 	default:
 		/* By default, set_fixmap is used for hardware mappings */
-		pte = mfn_pte(phys, __pgprot(pgprot_val(prot) | _PAGE_IOMAP));
+		pte = mfn_pte(phys, prot);
 		break;
 	}
 
@@ -2523,7 +2483,7 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
 				 unsigned long addr, void *data)
 {
 	struct remap_data *rmd = data;
-	pte_t pte = pte_mkspecial(pfn_pte(rmd->mfn++, rmd->prot));
+	pte_t pte = pte_mkspecial(mfn_pte(rmd->mfn++, rmd->prot));
 
 	rmd->mmu_update->ptr = virt_to_machine(ptep).maddr;
 	rmd->mmu_update->val = pte_val_ma(pte);
@@ -2548,8 +2508,6 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return -EINVAL;
 
-	prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
-
 	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
 
 	rmd.mfn = mfn;
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 696c694986d0..bd348aaa30b6 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -36,7 +36,7 @@
  *  pfn_to_mfn(0xc0000)=0xc0000
  *
  * The benefit of this is, that we can assume for non-RAM regions (think
- * PCI BARs, or ACPI spaces), we can create mappings easily b/c we
+ * PCI BARs, or ACPI spaces), we can create mappings easily because we
  * get the PFN value to match the MFN.
  *
  * For this to work efficiently we have one new page p2m_identity and
@@ -60,7 +60,7 @@
  * There is also a digram of the P2M at the end that can help.
  * Imagine your E820 looking as so:
  *
- *                    1GB                                           2GB
+ *                    1GB                                           2GB    4GB
  * /-------------------+---------\/----\         /----------\    /---+-----\
  * | System RAM        | Sys RAM ||ACPI|         | reserved |    | Sys RAM |
  * \-------------------+---------/\----/         \----------/    \---+-----/
@@ -77,9 +77,8 @@
  * of the PFN and the end PFN (263424 and 512256 respectively). The first step
  * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page
  * covers 512^2 of page estate (1GB) and in case the start or end PFN is not
- * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn
- * to end pfn.  We reserve_brk top leaf pages if they are missing (means they
- * point to p2m_mid_missing).
+ * aligned on 512^2*PAGE_SIZE (1GB) we reserve_brk new middle and leaf pages as
+ * required to split any existing p2m_mid_missing middle pages.
  *
  * With the E820 example above, 263424 is not 1GB aligned so we allocate a
  * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000.
@@ -88,7 +87,7 @@
  * Next stage is to determine if we need to do a more granular boundary check
  * on the 4MB (or 2MB depending on architecture) off the start and end pfn's.
  * We check if the start pfn and end pfn violate that boundary check, and if
- * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer
+ * so reserve_brk a (p2m[x][y]) leaf page. This way we have a much finer
  * granularity of setting which PFNs are missing and which ones are identity.
  * In our example 263424 and 512256 both fail the check so we reserve_brk two
  * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing"
@@ -102,9 +101,10 @@
  *
  * The next step is to walk from the start pfn to the end pfn setting
  * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity.
- * If we find that the middle leaf is pointing to p2m_missing we can swap it
- * over to p2m_identity - this way covering 4MB (or 2MB) PFN space.  At this
- * point we do not need to worry about boundary aligment (so no need to
+ * If we find that the middle entry is pointing to p2m_missing we can swap it
+ * over to p2m_identity - this way covering 4MB (or 2MB) PFN space (and
+ * similarly swapping p2m_mid_missing for p2m_mid_identity for larger regions).
+ * At this point we do not need to worry about boundary aligment (so no need to
  * reserve_brk a middle page, figure out which PFNs are "missing" and which
  * ones are identity), as that has been done earlier.  If we find that the
  * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference
@@ -118,6 +118,9 @@
  * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511]
  * contain the INVALID_P2M_ENTRY value and are considered "missing."
  *
+ * Finally, the region beyond the end of of the E820 (4 GB in this example)
+ * is set to be identity (in case there are MMIO regions placed here).
+ *
  * This is what the p2m ends up looking (for the E820 above) with this
  * fabulous drawing:
  *
@@ -129,21 +132,27 @@
  *  |-----|    \                      | [p2m_identity]+\\    | ....            |
  *  |  2  |--\  \-------------------->|  ...          | \\   \----------------/
  *  |-----|   \                       \---------------/  \\
- *  |  3  |\   \                                          \\  p2m_identity
- *  |-----| \   \-------------------->/---------------\   /-----------------\
- *  | ..  +->+                        | [p2m_identity]+-->| ~0, ~0, ~0, ... |
- *  \-----/ /                         | [p2m_identity]+-->| ..., ~0         |
- *         / /---------------\        | ....          |   \-----------------/
- *        /  | IDENTITY[@0]  |      /-+-[x], ~0, ~0.. |
- *       /   | IDENTITY[@256]|<----/  \---------------/
- *      /    | ~0, ~0, ....  |
- *     |     \---------------/
- *     |
- *   p2m_mid_missing           p2m_missing
- * /-----------------\     /------------\
- * | [p2m_missing]   +---->| ~0, ~0, ~0 |
- * | [p2m_missing]   +---->| ..., ~0    |
- * \-----------------/     \------------/
+ *  |  3  |-\  \                                          \\  p2m_identity [1]
+ *  |-----|  \  \-------------------->/---------------\   /-----------------\
+ *  | ..  |\  |                       | [p2m_identity]+-->| ~0, ~0, ~0, ... |
+ *  \-----/ | |                       | [p2m_identity]+-->| ..., ~0         |
+ *          | |                       | ....          |   \-----------------/
+ *          | |                       +-[x], ~0, ~0.. +\
+ *          | |                       \---------------/ \
+ *          | |                                          \-> /---------------\
+ *          | V  p2m_mid_missing       p2m_missing           | IDENTITY[@0]  |
+ *          | /-----------------\     /------------\         | IDENTITY[@256]|
+ *          | | [p2m_missing]   +---->| ~0, ~0, ...|         | ~0, ~0, ....  |
+ *          | | [p2m_missing]   +---->| ..., ~0    |         \---------------/
+ *          | | ...             |     \------------/
+ *          | \-----------------/
+ *          |
+ *          |     p2m_mid_identity 
+ *          |   /-----------------\     
+ *          \-->| [p2m_identity]  +---->[1]
+ *              | [p2m_identity]  +---->[1]
+ *              | ...             |
+ *              \-----------------/
  *
  * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
  */
@@ -187,13 +196,15 @@ static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
 
 static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
 
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 
 /* We might hit two boundary violations at the start and end, at max each
  * boundary violation will require three middle nodes. */
-RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
+RESERVE_BRK(p2m_mid_extra, PAGE_SIZE * 2 * 3);
 
 /* When we populate back during bootup, the amount of pages can vary. The
  * max we have is seen is 395979, but that does not mean it can't be more.
@@ -242,20 +253,20 @@ static void p2m_top_mfn_p_init(unsigned long **top)
 		top[i] = p2m_mid_missing_mfn;
 }
 
-static void p2m_mid_init(unsigned long **mid)
+static void p2m_mid_init(unsigned long **mid, unsigned long *leaf)
 {
 	unsigned i;
 
 	for (i = 0; i < P2M_MID_PER_PAGE; i++)
-		mid[i] = p2m_missing;
+		mid[i] = leaf;
 }
 
-static void p2m_mid_mfn_init(unsigned long *mid)
+static void p2m_mid_mfn_init(unsigned long *mid, unsigned long *leaf)
 {
 	unsigned i;
 
 	for (i = 0; i < P2M_MID_PER_PAGE; i++)
-		mid[i] = virt_to_mfn(p2m_missing);
+		mid[i] = virt_to_mfn(leaf);
 }
 
 static void p2m_init(unsigned long *p2m)
@@ -286,7 +297,9 @@ void __ref xen_build_mfn_list_list(void)
 	/* Pre-initialize p2m_top_mfn to be completely missing */
 	if (p2m_top_mfn == NULL) {
 		p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
-		p2m_mid_mfn_init(p2m_mid_missing_mfn);
+		p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+		p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+		p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
 
 		p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
 		p2m_top_mfn_p_init(p2m_top_mfn_p);
@@ -295,7 +308,8 @@ void __ref xen_build_mfn_list_list(void)
 		p2m_top_mfn_init(p2m_top_mfn);
 	} else {
 		/* Reinitialise, mfn's all change after migration */
-		p2m_mid_mfn_init(p2m_mid_missing_mfn);
+		p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+		p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
 	}
 
 	for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -327,7 +341,7 @@ void __ref xen_build_mfn_list_list(void)
 			 * it too late.
 			 */
 			mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-			p2m_mid_mfn_init(mid_mfn_p);
+			p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
 
 			p2m_top_mfn_p[topidx] = mid_mfn_p;
 		}
@@ -365,16 +379,17 @@ void __init xen_build_dynamic_phys_to_machine(void)
 
 	p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
 	p2m_init(p2m_missing);
+	p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_init(p2m_identity);
 
 	p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
-	p2m_mid_init(p2m_mid_missing);
+	p2m_mid_init(p2m_mid_missing, p2m_missing);
+	p2m_mid_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_mid_init(p2m_mid_identity, p2m_identity);
 
 	p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
 	p2m_top_init(p2m_top);
 
-	p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
-	p2m_init(p2m_identity);
-
 	/*
 	 * The domain builder gives us a pre-constructed p2m array in
 	 * mfn_list for all the pages initially given to us, so we just
@@ -386,7 +401,7 @@ void __init xen_build_dynamic_phys_to_machine(void)
 
 		if (p2m_top[topidx] == p2m_mid_missing) {
 			unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
-			p2m_mid_init(mid);
+			p2m_mid_init(mid, p2m_missing);
 
 			p2m_top[topidx] = mid;
 		}
@@ -492,7 +507,7 @@ unsigned long get_phys_to_machine(unsigned long pfn)
 	unsigned topidx, mididx, idx;
 
 	if (unlikely(pfn >= MAX_P2M_PFN))
-		return INVALID_P2M_ENTRY;
+		return IDENTITY_FRAME(pfn);
 
 	topidx = p2m_top_index(pfn);
 	mididx = p2m_mid_index(pfn);
@@ -545,7 +560,7 @@ static bool alloc_p2m(unsigned long pfn)
 		if (!mid)
 			return false;
 
-		p2m_mid_init(mid);
+		p2m_mid_init(mid, p2m_missing);
 
 		if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
 			free_p2m_page(mid);
@@ -565,7 +580,7 @@ static bool alloc_p2m(unsigned long pfn)
 		if (!mid_mfn)
 			return false;
 
-		p2m_mid_mfn_init(mid_mfn);
+		p2m_mid_mfn_init(mid_mfn, p2m_missing);
 
 		missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
 		mid_mfn_mfn = virt_to_mfn(mid_mfn);
@@ -596,7 +611,7 @@ static bool alloc_p2m(unsigned long pfn)
 	return true;
 }
 
-static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary)
+static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
 {
 	unsigned topidx, mididx, idx;
 	unsigned long *p2m;
@@ -638,7 +653,7 @@ static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary
 	return true;
 }
 
-static bool __init early_alloc_p2m(unsigned long pfn)
+static bool __init early_alloc_p2m_middle(unsigned long pfn)
 {
 	unsigned topidx = p2m_top_index(pfn);
 	unsigned long *mid_mfn_p;
@@ -649,7 +664,7 @@ static bool __init early_alloc_p2m(unsigned long pfn)
 	if (mid == p2m_mid_missing) {
 		mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
 
-		p2m_mid_init(mid);
+		p2m_mid_init(mid, p2m_missing);
 
 		p2m_top[topidx] = mid;
 
@@ -658,12 +673,12 @@ static bool __init early_alloc_p2m(unsigned long pfn)
 	/* And the save/restore P2M tables.. */
 	if (mid_mfn_p == p2m_mid_missing_mfn) {
 		mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-		p2m_mid_mfn_init(mid_mfn_p);
+		p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
 
 		p2m_top_mfn_p[topidx] = mid_mfn_p;
 		p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
 		/* Note: we don't set mid_mfn_p[midix] here,
-		 * look in early_alloc_p2m_middle */
+		 * look in early_alloc_p2m() */
 	}
 	return true;
 }
@@ -739,7 +754,7 @@ found:
 
 	/* This shouldn't happen */
 	if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
-		early_alloc_p2m(set_pfn);
+		early_alloc_p2m_middle(set_pfn);
 
 	if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
 		return false;
@@ -754,13 +769,13 @@ found:
 bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
-		if (!early_alloc_p2m(pfn))
+		if (!early_alloc_p2m_middle(pfn))
 			return false;
 
 		if (early_can_reuse_p2m_middle(pfn, mfn))
 			return __set_phys_to_machine(pfn, mfn);
 
-		if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/))
+		if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
 			return false;
 
 		if (!__set_phys_to_machine(pfn, mfn))
@@ -769,12 +784,30 @@ bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 
 	return true;
 }
+
+static void __init early_split_p2m(unsigned long pfn)
+{
+	unsigned long mididx, idx;
+
+	mididx = p2m_mid_index(pfn);
+	idx = p2m_index(pfn);
+
+	/*
+	 * Allocate new middle and leaf pages if this pfn lies in the
+	 * middle of one.
+	 */
+	if (mididx || idx)
+		early_alloc_p2m_middle(pfn);
+	if (idx)
+		early_alloc_p2m(pfn, false);
+}
+
 unsigned long __init set_phys_range_identity(unsigned long pfn_s,
 				      unsigned long pfn_e)
 {
 	unsigned long pfn;
 
-	if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
+	if (unlikely(pfn_s >= MAX_P2M_PFN))
 		return 0;
 
 	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
@@ -783,19 +816,30 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
 	if (pfn_s > pfn_e)
 		return 0;
 
-	for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
-		pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
-		pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
-	{
-		WARN_ON(!early_alloc_p2m(pfn));
-	}
+	if (pfn_e > MAX_P2M_PFN)
+		pfn_e = MAX_P2M_PFN;
 
-	early_alloc_p2m_middle(pfn_s, true);
-	early_alloc_p2m_middle(pfn_e, true);
+	early_split_p2m(pfn_s);
+	early_split_p2m(pfn_e);
+
+	for (pfn = pfn_s; pfn < pfn_e;) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx = p2m_mid_index(pfn);
 
-	for (pfn = pfn_s; pfn < pfn_e; pfn++)
 		if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
 			break;
+		pfn++;
+
+		/*
+		 * If the PFN was set to a middle or leaf identity
+		 * page the remainder must also be identity, so skip
+		 * ahead to the next middle or leaf entry.
+		 */
+		if (p2m_top[topidx] == p2m_mid_identity)
+			pfn = ALIGN(pfn, P2M_MID_PER_PAGE * P2M_PER_PAGE);
+		else if (p2m_top[topidx][mididx] == p2m_identity)
+			pfn = ALIGN(pfn, P2M_PER_PAGE);
+	}
 
 	if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
 		"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
@@ -825,8 +869,22 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 
 	/* For sparse holes were the p2m leaf has real PFN along with
 	 * PCI holes, stick in the PFN as the MFN value.
+	 *
+	 * set_phys_range_identity() will have allocated new middle
+	 * and leaf pages as required so an existing p2m_mid_missing
+	 * or p2m_missing mean that whole range will be identity so
+	 * these can be switched to p2m_mid_identity or p2m_identity.
 	 */
 	if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
+		if (p2m_top[topidx] == p2m_mid_identity)
+			return true;
+
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			WARN_ON(cmpxchg(&p2m_top[topidx], p2m_mid_missing,
+					p2m_mid_identity) != p2m_mid_missing);
+			return true;
+		}
+
 		if (p2m_top[topidx][mididx] == p2m_identity)
 			return true;
 
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 0982233b9b84..210426a26cc0 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -89,10 +89,10 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
 	for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
 		unsigned long mfn = pfn_to_mfn(pfn);
 
-		if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
+		if (WARN_ONCE(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
 			continue;
-		WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
-			pfn, mfn);
+		WARN_ONCE(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
+			  pfn, mfn);
 
 		__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 	}
@@ -469,6 +469,15 @@ char * __init xen_memory_setup(void)
 	}
 
 	/*
+	 * Set the rest as identity mapped, in case PCI BARs are
+	 * located here.
+	 *
+	 * PFNs above MAX_P2M_PFN are considered identity mapped as
+	 * well.
+	 */
+	set_phys_range_identity(map[i-1].addr / PAGE_SIZE, ~0ul);
+
+	/*
 	 * In domU, the ISA region is normal, usable memory, but we
 	 * reserve ISA memory anyway because too many things poke
 	 * about in there.
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index c87ae7c6e5f9..02d6d29a63c1 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -41,7 +41,7 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
 	def_bool n
 
-config NO_IOPORT
+config NO_IOPORT_MAP
 	def_bool n
 
 config HZ
@@ -239,7 +239,7 @@ config XTENSA_PLATFORM_XT2000
 config XTENSA_PLATFORM_S6105
 	bool "S6105"
 	select SERIAL_CONSOLE
-	select NO_IOPORT
+	select NO_IOPORT_MAP
 
 config XTENSA_PLATFORM_XTFPGA
 	bool "XTFPGA"
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
index 4f233204faf9..d57d917ff240 100644
--- a/arch/xtensa/configs/iss_defconfig
+++ b/arch/xtensa/configs/iss_defconfig
@@ -11,7 +11,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_NO_IOPORT=y
+CONFIG_NO_IOPORT_MAP=y
 CONFIG_HZ=100
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_CONSTRUCTORS=y
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig
index d929f77a0360..583c2b0974ca 100644
--- a/arch/xtensa/configs/s6105_defconfig
+++ b/arch/xtensa/configs/s6105_defconfig
@@ -11,7 +11,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_NO_IOPORT=y
+CONFIG_NO_IOPORT_MAP=y
 CONFIG_HZ=100
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 0a337e4a8370..c3d20ba6eb86 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -9,6 +9,7 @@ generic-y += errno.h
 generic-y += exec.h
 generic-y += fcntl.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
@@ -17,7 +18,9 @@ generic-y += kvm_para.h
 generic-y += linkage.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -27,5 +30,3 @@ generic-y += termios.h
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 4e491d9b5292..e4a4145926f6 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -336,7 +336,7 @@ static void blkg_destroy(struct blkcg_gq *blkg)
 	 * under queue_lock.  If it's not pointing to @blkg now, it never
 	 * will.  Hint assignment itself can race safely.
 	 */
-	if (rcu_dereference_raw(blkcg->blkg_hint) == blkg)
+	if (rcu_access_pointer(blkcg->blkg_hint) == blkg)
 		rcu_assign_pointer(blkcg->blkg_hint, NULL);
 
 	/*
@@ -894,7 +894,7 @@ static int blkcg_can_attach(struct cgroup_subsys_state *css,
 	int ret = 0;
 
 	/* task_lock() is needed to avoid races with exit_io_context() */
-	cgroup_taskset_for_each(task, css, tset) {
+	cgroup_taskset_for_each(task, tset) {
 		task_lock(task);
 		ioc = task->io_context;
 		if (ioc && atomic_read(&ioc->nr_tasks) > 1)
@@ -906,17 +906,14 @@ static int blkcg_can_attach(struct cgroup_subsys_state *css,
 	return ret;
 }
 
-struct cgroup_subsys blkio_subsys = {
-	.name = "blkio",
+struct cgroup_subsys blkio_cgrp_subsys = {
 	.css_alloc = blkcg_css_alloc,
 	.css_offline = blkcg_css_offline,
 	.css_free = blkcg_css_free,
 	.can_attach = blkcg_can_attach,
-	.subsys_id = blkio_subsys_id,
 	.base_cftypes = blkcg_files,
-	.module = THIS_MODULE,
 };
-EXPORT_SYMBOL_GPL(blkio_subsys);
+EXPORT_SYMBOL_GPL(blkio_cgrp_subsys);
 
 /**
  * blkcg_activate_policy - activate a blkcg policy on a request_queue
@@ -1106,7 +1103,7 @@ int blkcg_policy_register(struct blkcg_policy *pol)
 
 	/* everything is in place, add intf files for the new policy */
 	if (pol->cftypes)
-		WARN_ON(cgroup_add_cftypes(&blkio_subsys, pol->cftypes));
+		WARN_ON(cgroup_add_cftypes(&blkio_cgrp_subsys, pol->cftypes));
 	ret = 0;
 out_unlock:
 	mutex_unlock(&blkcg_pol_mutex);
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 86154eab9523..15a8d640de57 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -186,7 +186,7 @@ static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css)
 
 static inline struct blkcg *task_blkcg(struct task_struct *tsk)
 {
-	return css_to_blkcg(task_css(tsk, blkio_subsys_id));
+	return css_to_blkcg(task_css(tsk, blkio_cgrp_id));
 }
 
 static inline struct blkcg *bio_blkcg(struct bio *bio)
@@ -241,12 +241,16 @@ static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd)
  */
 static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
 {
-	int ret;
+	char *p;
 
-	ret = cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
-	if (ret)
+	p = cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
+	if (!p) {
 		strncpy(buf, "<unavailable>", buflen);
-	return ret;
+		return -ENAMETOOLONG;
+	}
+
+	memmove(buf, p, buf + buflen - p);
+	return 0;
 }
 
 /**
diff --git a/block/blk-core.c b/block/blk-core.c
index 853f92749202..4db2b32b70e0 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1929,7 +1929,7 @@ EXPORT_SYMBOL(submit_bio);
  *    in some cases below, so export this function.
  *    Request stacking drivers like request-based dm may change the queue
  *    limits while requests are in the queue (e.g. dm's table swapping).
- *    Such request stacking drivers should check those requests agaist
+ *    Such request stacking drivers should check those requests against
  *    the new queue limits again when they dispatch those requests,
  *    although such checkings are also done against the old queue limits
  *    when submitting requests.
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 242df01413f6..1a27f45ec776 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -68,7 +68,7 @@ static void ioc_destroy_icq(struct io_cq *icq)
 	 * under queue_lock.  If it's not pointing to @icq now, it never
 	 * will.  Hint assignment itself can race safely.
 	 */
-	if (rcu_dereference_raw(ioc->icq_hint) == icq)
+	if (rcu_access_pointer(ioc->icq_hint) == icq)
 		rcu_assign_pointer(ioc->icq_hint, NULL);
 
 	ioc_exit_icq(icq);
diff --git a/block/blk-map.c b/block/blk-map.c
index ae4ae1047fd9..cca6356d216d 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -285,7 +285,7 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
  *
  * Description:
  *    Data will be mapped directly if possible. Otherwise a bounce
- *    buffer is used. Can be called multple times to append multple
+ *    buffer is used. Can be called multiple times to append multiple
  *    buffers.
  */
 int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 1fa9dd153fde..6468a715a0e4 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -353,7 +353,7 @@ void __blk_mq_complete_request(struct request *rq)
 		rq->csd.func = __blk_mq_complete_request_remote;
 		rq->csd.info = rq;
 		rq->csd.flags = 0;
-		__smp_call_function_single(ctx->cpu, &rq->csd, 0);
+		smp_call_function_single_async(ctx->cpu, &rq->csd);
 	} else {
 		rq->q->softirq_done_fn(rq);
 	}
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 57790c1a97eb..ebd6b6f1bdeb 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -30,8 +30,8 @@ static void blk_done_softirq(struct softirq_action *h)
 	while (!list_empty(&local_list)) {
 		struct request *rq;
 
-		rq = list_entry(local_list.next, struct request, csd.list);
-		list_del_init(&rq->csd.list);
+		rq = list_entry(local_list.next, struct request, queuelist);
+		list_del_init(&rq->queuelist);
 		rq->q->softirq_done_fn(rq);
 	}
 }
@@ -45,9 +45,14 @@ static void trigger_softirq(void *data)
 
 	local_irq_save(flags);
 	list = this_cpu_ptr(&blk_cpu_done);
-	list_add_tail(&rq->csd.list, list);
+	/*
+	 * We reuse queuelist for a list of requests to process. Since the
+	 * queuelist is used by the block layer only for requests waiting to be
+	 * submitted to the device it is unused now.
+	 */
+	list_add_tail(&rq->queuelist, list);
 
-	if (list->next == &rq->csd.list)
+	if (list->next == &rq->queuelist)
 		raise_softirq_irqoff(BLOCK_SOFTIRQ);
 
 	local_irq_restore(flags);
@@ -65,7 +70,7 @@ static int raise_blk_irq(int cpu, struct request *rq)
 		data->info = rq;
 		data->flags = 0;
 
-		__smp_call_function_single(cpu, data, 0);
+		smp_call_function_single_async(cpu, data);
 		return 0;
 	}
 
@@ -136,7 +141,7 @@ void __blk_complete_request(struct request *req)
 		struct list_head *list;
 do_local:
 		list = this_cpu_ptr(&blk_cpu_done);
-		list_add_tail(&req->csd.list, list);
+		list_add_tail(&req->queuelist, list);
 
 		/*
 		 * if the list only contains our just added request,
@@ -144,7 +149,7 @@ do_local:
 		 * entries there, someone already raised the irq but it
 		 * hasn't run yet.
 		 */
-		if (list->next == &req->csd.list)
+		if (list->next == &req->queuelist)
 			raise_softirq_irqoff(BLOCK_SOFTIRQ);
 	} else if (raise_blk_irq(ccpu, req))
 		goto do_local;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 1474c3ab7e72..861c363e4129 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1425,28 +1425,24 @@ static struct cftype throtl_files[] = {
 		.private = offsetof(struct throtl_grp, bps[READ]),
 		.seq_show = tg_print_conf_u64,
 		.write_string = tg_set_conf_u64,
-		.max_write_len = 256,
 	},
 	{
 		.name = "throttle.write_bps_device",
 		.private = offsetof(struct throtl_grp, bps[WRITE]),
 		.seq_show = tg_print_conf_u64,
 		.write_string = tg_set_conf_u64,
-		.max_write_len = 256,
 	},
 	{
 		.name = "throttle.read_iops_device",
 		.private = offsetof(struct throtl_grp, iops[READ]),
 		.seq_show = tg_print_conf_uint,
 		.write_string = tg_set_conf_uint,
-		.max_write_len = 256,
 	},
 	{
 		.name = "throttle.write_iops_device",
 		.private = offsetof(struct throtl_grp, iops[WRITE]),
 		.seq_show = tg_print_conf_uint,
 		.write_string = tg_set_conf_uint,
-		.max_write_len = 256,
 	},
 	{
 		.name = "throttle.io_service_bytes",
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 744833b630c6..c74e3454c40b 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1838,7 +1838,6 @@ static struct cftype cfq_blkcg_files[] = {
 		.flags = CFTYPE_ONLY_ON_ROOT,
 		.seq_show = cfqg_print_leaf_weight_device,
 		.write_string = cfqg_set_leaf_weight_device,
-		.max_write_len = 256,
 	},
 	{
 		.name = "weight",
@@ -1853,7 +1852,6 @@ static struct cftype cfq_blkcg_files[] = {
 		.flags = CFTYPE_NOT_ON_ROOT,
 		.seq_show = cfqg_print_weight_device,
 		.write_string = cfqg_set_weight_device,
-		.max_write_len = 256,
 	},
 	{
 		.name = "weight",
@@ -1866,7 +1864,6 @@ static struct cftype cfq_blkcg_files[] = {
 		.name = "leaf_weight_device",
 		.seq_show = cfqg_print_leaf_weight_device,
 		.write_string = cfqg_set_leaf_weight_device,
-		.max_write_len = 256,
 	},
 	{
 		.name = "leaf_weight",
@@ -2367,10 +2364,10 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
 	 * reposition in fifo if next is older than rq
 	 */
 	if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
-	    time_before(rq_fifo_time(next), rq_fifo_time(rq)) &&
+	    time_before(next->fifo_time, rq->fifo_time) &&
 	    cfqq == RQ_CFQQ(next)) {
 		list_move(&rq->queuelist, &next->queuelist);
-		rq_set_fifo_time(rq, rq_fifo_time(next));
+		rq->fifo_time = next->fifo_time;
 	}
 
 	if (cfqq->next_rq == next)
@@ -2814,7 +2811,7 @@ static struct request *cfq_check_fifo(struct cfq_queue *cfqq)
 		return NULL;
 
 	rq = rq_entry_fifo(cfqq->fifo.next);
-	if (time_before(jiffies, rq_fifo_time(rq)))
+	if (time_before(jiffies, rq->fifo_time))
 		rq = NULL;
 
 	cfq_log_cfqq(cfqq->cfqd, cfqq, "fifo=%p", rq);
@@ -3927,7 +3924,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
 	cfq_log_cfqq(cfqd, cfqq, "insert_request");
 	cfq_init_prio_data(cfqq, RQ_CIC(rq));
 
-	rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]);
+	rq->fifo_time = jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)];
 	list_add_tail(&rq->queuelist, &cfqq->fifo);
 	cfq_add_rq_rb(rq);
 	cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group,
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 9ef66406c625..a753df2b3fc2 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -106,7 +106,7 @@ deadline_add_request(struct request_queue *q, struct request *rq)
 	/*
 	 * set expire time and add to fifo list
 	 */
-	rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]);
+	rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
 	list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]);
 }
 
@@ -174,9 +174,9 @@ deadline_merged_requests(struct request_queue *q, struct request *req,
 	 * and move into next position (next will be deleted) in fifo
 	 */
 	if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
-		if (time_before(rq_fifo_time(next), rq_fifo_time(req))) {
+		if (time_before(next->fifo_time, req->fifo_time)) {
 			list_move(&req->queuelist, &next->queuelist);
-			rq_set_fifo_time(req, rq_fifo_time(next));
+			req->fifo_time = next->fifo_time;
 		}
 	}
 
@@ -230,7 +230,7 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
 	/*
 	 * rq is expired!
 	 */
-	if (time_after_eq(jiffies, rq_fifo_time(rq)))
+	if (time_after_eq(jiffies, rq->fifo_time))
 		return 1;
 
 	return 0;
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/block/partitions/atari.h b/block/partitions/atari.h
index fe2d32a89f36..f2ec43bfeec1 100644
--- a/block/partitions/atari.h
+++ b/block/partitions/atari.h
@@ -11,6 +11,8 @@
  * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de)
  */
 
+#include <linux/compiler.h>
+
 struct partition_info
 {
   u8 flg;			/* bit 0: active; bit 7: bootable */
@@ -29,6 +31,6 @@ struct rootsector
   u32 bsl_st;			/* start of bad sector list */
   u32 bsl_cnt;			/* length of bad sector list */
   u16 checksum;			/* checksum for bootable disks */
-} __attribute__((__packed__));
+} __packed;
 
 int atari_partition(struct parsed_partitions *state);
diff --git a/block/partitions/efi.h b/block/partitions/efi.h
index 4efcafba7e64..abd0b19288a6 100644
--- a/block/partitions/efi.h
+++ b/block/partitions/efi.h
@@ -32,6 +32,7 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/efi.h>
+#include <linux/compiler.h>
 
 #define MSDOS_MBR_SIGNATURE 0xaa55
 #define EFI_PMBR_OSTYPE_EFI 0xEF
@@ -87,13 +88,13 @@ typedef struct _gpt_header {
 	 *
 	 * uint8_t		reserved2[ BlockSize - 92 ];
 	 */
-} __attribute__ ((packed)) gpt_header;
+} __packed gpt_header;
 
 typedef struct _gpt_entry_attributes {
 	u64 required_to_function:1;
 	u64 reserved:47;
         u64 type_guid_specific:16;
-} __attribute__ ((packed)) gpt_entry_attributes;
+} __packed gpt_entry_attributes;
 
 typedef struct _gpt_entry {
 	efi_guid_t partition_type_guid;
@@ -102,7 +103,7 @@ typedef struct _gpt_entry {
 	__le64 ending_lba;
 	gpt_entry_attributes attributes;
 	efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
-} __attribute__ ((packed)) gpt_entry;
+} __packed gpt_entry;
 
 typedef struct _gpt_mbr_record {
 	u8	boot_indicator; /* unused by EFI, set to 0x80 for bootable */
@@ -124,7 +125,7 @@ typedef struct _legacy_mbr {
 	__le16 unknown;
 	gpt_mbr_record partition_record[4];
 	__le16 signature;
-} __attribute__ ((packed)) legacy_mbr;
+} __packed legacy_mbr;
 
 /* Functions */
 extern int efi_partition(struct parsed_partitions *state);
diff --git a/block/partitions/karma.c b/block/partitions/karma.c
index 0ea19312706b..9721fa589bb1 100644
--- a/block/partitions/karma.c
+++ b/block/partitions/karma.c
@@ -8,6 +8,7 @@
 
 #include "check.h"
 #include "karma.h"
+#include <linux/compiler.h>
 
 int karma_partition(struct parsed_partitions *state)
 {
@@ -26,7 +27,7 @@ int karma_partition(struct parsed_partitions *state)
 		} d_partitions[2];
 		u8 d_blank[208];
 		__le16 d_magic;
-	} __attribute__((packed)) *label;
+	} __packed *label;
 	struct d_partition *p;
 
 	data = read_part_sector(state, 0, &sect);
diff --git a/crypto/Makefile b/crypto/Makefile
index b29402a7b9b5..38e64231dcd3 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -81,7 +81,7 @@ obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
-obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
 obj-$(CONFIG_CRYPTO_CRC32) += crc32.o
 obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
deleted file mode 100644
index 06f7018c9d95..000000000000
--- a/crypto/crc32c.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Cryptographic API.
- *
- * CRC32C chksum
- *
- *@Article{castagnoli-crc,
- * author =       { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
- * title =        {{Optimization of Cyclic Redundancy-Check Codes with 24
- *                 and 32 Parity Bits}},
- * journal =      IEEE Transactions on Communication,
- * year =         {1993},
- * volume =       {41},
- * number =       {6},
- * pages =        {},
- * month =        {June},
- *}
- * Used by the iSCSI driver, possibly others, and derived from the
- * the iscsi-crc.c module of the linux-iscsi driver at
- * http://linux-iscsi.sourceforge.net.
- *
- * Following the example of lib/crc32, this function is intended to be
- * flexible and useful for all users.  Modules that currently have their
- * own crc32c, but hopefully may be able to use this one are:
- *  net/sctp (please add all your doco to here if you change to
- *            use this one!)
- *  <endoflist>
- *
- * Copyright (c) 2004 Cisco Systems, Inc.
- * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * This program is free software; you can redistribute 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 <crypto/internal/hash.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/crc32.h>
-
-#define CHKSUM_BLOCK_SIZE	1
-#define CHKSUM_DIGEST_SIZE	4
-
-struct chksum_ctx {
-	u32 key;
-};
-
-struct chksum_desc_ctx {
-	u32 crc;
-};
-
-/*
- * Steps through buffer one byte at at time, calculates reflected
- * crc using table.
- */
-
-static int chksum_init(struct shash_desc *desc)
-{
-	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
-	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-	ctx->crc = mctx->key;
-
-	return 0;
-}
-
-/*
- * Setting the seed allows arbitrary accumulators and flexible XOR policy
- * If your algorithm starts with ~0, then XOR with ~0 before you set
- * the seed.
- */
-static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
-			 unsigned int keylen)
-{
-	struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
-
-	if (keylen != sizeof(mctx->key)) {
-		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-		return -EINVAL;
-	}
-	mctx->key = le32_to_cpu(*(__le32 *)key);
-	return 0;
-}
-
-static int chksum_update(struct shash_desc *desc, const u8 *data,
-			 unsigned int length)
-{
-	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-	ctx->crc = __crc32c_le(ctx->crc, data, length);
-	return 0;
-}
-
-static int chksum_final(struct shash_desc *desc, u8 *out)
-{
-	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-	*(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
-	return 0;
-}
-
-static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
-{
-	*(__le32 *)out = ~cpu_to_le32(__crc32c_le(*crcp, data, len));
-	return 0;
-}
-
-static int chksum_finup(struct shash_desc *desc, const u8 *data,
-			unsigned int len, u8 *out)
-{
-	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-	return __chksum_finup(&ctx->crc, data, len, out);
-}
-
-static int chksum_digest(struct shash_desc *desc, const u8 *data,
-			 unsigned int length, u8 *out)
-{
-	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
-
-	return __chksum_finup(&mctx->key, data, length, out);
-}
-
-static int crc32c_cra_init(struct crypto_tfm *tfm)
-{
-	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
-
-	mctx->key = ~0;
-	return 0;
-}
-
-static struct shash_alg alg = {
-	.digestsize		=	CHKSUM_DIGEST_SIZE,
-	.setkey			=	chksum_setkey,
-	.init		=	chksum_init,
-	.update		=	chksum_update,
-	.final		=	chksum_final,
-	.finup		=	chksum_finup,
-	.digest		=	chksum_digest,
-	.descsize		=	sizeof(struct chksum_desc_ctx),
-	.base			=	{
-		.cra_name		=	"crc32c",
-		.cra_driver_name	=	"crc32c-generic",
-		.cra_priority		=	100,
-		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
-		.cra_alignmask		=	3,
-		.cra_ctxsize		=	sizeof(struct chksum_ctx),
-		.cra_module		=	THIS_MODULE,
-		.cra_init		=	crc32c_cra_init,
-	}
-};
-
-static int __init crc32c_mod_init(void)
-{
-	return crypto_register_shash(&alg);
-}
-
-static void __exit crc32c_mod_fini(void)
-{
-	crypto_unregister_shash(&alg);
-}
-
-module_init(crc32c_mod_init);
-module_exit(crc32c_mod_fini);
-
-MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
-MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
-MODULE_LICENSE("GPL");
diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c
new file mode 100644
index 000000000000..d9c7beba8e50
--- /dev/null
+++ b/crypto/crc32c_generic.c
@@ -0,0 +1,174 @@
+/*
+ * Cryptographic API.
+ *
+ * CRC32C chksum
+ *
+ *@Article{castagnoli-crc,
+ * author =       { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title =        {{Optimization of Cyclic Redundancy-Check Codes with 24
+ *                 and 32 Parity Bits}},
+ * journal =      IEEE Transactions on Communication,
+ * year =         {1993},
+ * volume =       {41},
+ * number =       {6},
+ * pages =        {},
+ * month =        {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users.  Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ *  net/sctp (please add all your doco to here if you change to
+ *            use this one!)
+ *  <endoflist>
+ *
+ * Copyright (c) 2004 Cisco Systems, Inc.
+ * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute 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 <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/crc32.h>
+
+#define CHKSUM_BLOCK_SIZE	1
+#define CHKSUM_DIGEST_SIZE	4
+
+struct chksum_ctx {
+	u32 key;
+};
+
+struct chksum_desc_ctx {
+	u32 crc;
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static int chksum_init(struct shash_desc *desc)
+{
+	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
+	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	ctx->crc = mctx->key;
+
+	return 0;
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
+			 unsigned int keylen)
+{
+	struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
+
+	if (keylen != sizeof(mctx->key)) {
+		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	mctx->key = le32_to_cpu(*(__le32 *)key);
+	return 0;
+}
+
+static int chksum_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int length)
+{
+	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	ctx->crc = __crc32c_le(ctx->crc, data, length);
+	return 0;
+}
+
+static int chksum_final(struct shash_desc *desc, u8 *out)
+{
+	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	*(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
+	return 0;
+}
+
+static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
+{
+	*(__le32 *)out = ~cpu_to_le32(__crc32c_le(*crcp, data, len));
+	return 0;
+}
+
+static int chksum_finup(struct shash_desc *desc, const u8 *data,
+			unsigned int len, u8 *out)
+{
+	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	return __chksum_finup(&ctx->crc, data, len, out);
+}
+
+static int chksum_digest(struct shash_desc *desc, const u8 *data,
+			 unsigned int length, u8 *out)
+{
+	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
+
+	return __chksum_finup(&mctx->key, data, length, out);
+}
+
+static int crc32c_cra_init(struct crypto_tfm *tfm)
+{
+	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
+
+	mctx->key = ~0;
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize		=	CHKSUM_DIGEST_SIZE,
+	.setkey			=	chksum_setkey,
+	.init		=	chksum_init,
+	.update		=	chksum_update,
+	.final		=	chksum_final,
+	.finup		=	chksum_finup,
+	.digest		=	chksum_digest,
+	.descsize		=	sizeof(struct chksum_desc_ctx),
+	.base			=	{
+		.cra_name		=	"crc32c",
+		.cra_driver_name	=	"crc32c-generic",
+		.cra_priority		=	100,
+		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
+		.cra_alignmask		=	3,
+		.cra_ctxsize		=	sizeof(struct chksum_ctx),
+		.cra_module		=	THIS_MODULE,
+		.cra_init		=	crc32c_cra_init,
+	}
+};
+
+static int __init crc32c_mod_init(void)
+{
+	return crypto_register_shash(&alg);
+}
+
+static void __exit crc32c_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(crc32c_mod_init);
+module_exit(crc32c_mod_fini);
+
+MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("crc32c");
+MODULE_SOFTDEP("pre: crc32c");
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b3138fbb46a4..0a0a90f52d26 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/spmi/Kconfig"
+
 source "drivers/hsi/Kconfig"
 
 source "drivers/pps/Kconfig"
@@ -170,4 +172,6 @@ source "drivers/phy/Kconfig"
 
 source "drivers/powercap/Kconfig"
 
+source "drivers/mcb/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 8e3b8b06c0b2..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/
@@ -66,6 +66,7 @@ obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-$(CONFIG_SPMI)		+= spmi/
 obj-y				+= hsi/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
@@ -155,3 +156,4 @@ obj-$(CONFIG_IPACK_BUS)		+= ipack/
 obj-$(CONFIG_NTB)		+= ntb/
 obj-$(CONFIG_FMC)		+= fmc/
 obj-$(CONFIG_POWERCAP)		+= powercap/
+obj-$(CONFIG_MCB)		+= mcb/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 4770de5707b9..f60f11d7e489 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -43,19 +43,6 @@ config ACPI_SLEEP
 	depends on SUSPEND || HIBERNATION
 	default y
 
-config ACPI_PROCFS
-	bool "Deprecated /proc/acpi files"
-	depends on PROC_FS
-	help
-	  For backwards compatibility, this option allows
-	  deprecated /proc/acpi/ files to exist, even when
-	  they have been replaced by functions in /sys.
-
-	  This option has no effect on /proc/acpi/ files
-	  and functions which do not yet exist in /sys.
-
-	  Say N to delete /proc/acpi/ files that have moved to /sys/
-
 config ACPI_EC_DEBUGFS
 	tristate "EC read/write access through /sys/kernel/debug/ec"
 	default n
@@ -343,6 +330,19 @@ config ACPI_BGRT
 	  data from the firmware boot splash. It will appear under
 	  /sys/firmware/acpi/bgrt/ .
 
+config ACPI_REDUCED_HARDWARE_ONLY
+	bool "Hardware-reduced ACPI support only" if EXPERT
+	def_bool n
+	depends on ACPI
+	help
+	This config item changes the way the ACPI code is built.  When this
+	option is selected, the kernel will use a specialized version of
+	ACPICA that ONLY supports the ACPI "reduced hardware" mode.  The
+	resulting kernel will be smaller but it will also be restricted to
+	running in ACPI reduced hardware mode ONLY.
+
+	If you are unsure what to do, do not enable this option.
+
 source "drivers/acpi/apei/Kconfig"
 
 config ACPI_EXTLOG
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 6745fe137b9e..69e29f409d4c 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -33,6 +33,13 @@ ACPI_MODULE_NAME("acpi_lpss");
 #define LPSS_GENERAL_UART_RTS_OVRD	BIT(3)
 #define LPSS_SW_LTR			0x10
 #define LPSS_AUTO_LTR			0x14
+#define LPSS_LTR_SNOOP_REQ		BIT(15)
+#define LPSS_LTR_SNOOP_MASK		0x0000FFFF
+#define LPSS_LTR_SNOOP_LAT_1US		0x800
+#define LPSS_LTR_SNOOP_LAT_32US		0xC00
+#define LPSS_LTR_SNOOP_LAT_SHIFT	5
+#define LPSS_LTR_SNOOP_LAT_CUTOFF	3000
+#define LPSS_LTR_MAX_VAL		0x3FF
 #define LPSS_TX_INT			0x20
 #define LPSS_TX_INT_MASK		BIT(1)
 
@@ -102,6 +109,16 @@ static struct lpss_device_desc lpt_sdio_dev_desc = {
 	.ltr_required = true,
 };
 
+static struct lpss_shared_clock pwm_clock = {
+	.name = "pwm_clk",
+	.rate = 25000000,
+};
+
+static struct lpss_device_desc byt_pwm_dev_desc = {
+	.clk_required = true,
+	.shared_clock = &pwm_clock,
+};
+
 static struct lpss_shared_clock uart_clock = {
 	.name = "uart_clk",
 	.rate = 44236800,
@@ -157,6 +174,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 	{ "INT33C7", },
 
 	/* BayTrail LPSS devices */
+	{ "80860F09", (unsigned long)&byt_pwm_dev_desc },
 	{ "80860F0A", (unsigned long)&byt_uart_dev_desc },
 	{ "80860F0E", (unsigned long)&byt_spi_dev_desc },
 	{ "80860F14", (unsigned long)&byt_sdio_dev_desc },
@@ -315,6 +333,17 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
 	return ret;
 }
 
+static u32 __lpss_reg_read(struct lpss_private_data *pdata, unsigned int reg)
+{
+	return readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg);
+}
+
+static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata,
+			     unsigned int reg)
+{
+	writel(val, pdata->mmio_base + pdata->dev_desc->prv_offset + reg);
+}
+
 static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val)
 {
 	struct acpi_device *adev;
@@ -336,7 +365,7 @@ static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val)
 		ret = -ENODEV;
 		goto out;
 	}
-	*val = readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg);
+	*val = __lpss_reg_read(pdata, reg);
 
  out:
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -389,6 +418,37 @@ static struct attribute_group lpss_attr_group = {
 	.name = "lpss_ltr",
 };
 
+static void acpi_lpss_set_ltr(struct device *dev, s32 val)
+{
+	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+	u32 ltr_mode, ltr_val;
+
+	ltr_mode = __lpss_reg_read(pdata, LPSS_GENERAL);
+	if (val < 0) {
+		if (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) {
+			ltr_mode &= ~LPSS_GENERAL_LTR_MODE_SW;
+			__lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL);
+		}
+		return;
+	}
+	ltr_val = __lpss_reg_read(pdata, LPSS_SW_LTR) & ~LPSS_LTR_SNOOP_MASK;
+	if (val >= LPSS_LTR_SNOOP_LAT_CUTOFF) {
+		ltr_val |= LPSS_LTR_SNOOP_LAT_32US;
+		val = LPSS_LTR_MAX_VAL;
+	} else if (val > LPSS_LTR_MAX_VAL) {
+		ltr_val |= LPSS_LTR_SNOOP_LAT_32US | LPSS_LTR_SNOOP_REQ;
+		val >>= LPSS_LTR_SNOOP_LAT_SHIFT;
+	} else {
+		ltr_val |= LPSS_LTR_SNOOP_LAT_1US | LPSS_LTR_SNOOP_REQ;
+	}
+	ltr_val |= val;
+	__lpss_reg_write(ltr_val, pdata, LPSS_SW_LTR);
+	if (!(ltr_mode & LPSS_GENERAL_LTR_MODE_SW)) {
+		ltr_mode |= LPSS_GENERAL_LTR_MODE_SW;
+		__lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL);
+	}
+}
+
 static int acpi_lpss_platform_notify(struct notifier_block *nb,
 				     unsigned long action, void *data)
 {
@@ -426,9 +486,29 @@ static struct notifier_block acpi_lpss_nb = {
 	.notifier_call = acpi_lpss_platform_notify,
 };
 
+static void acpi_lpss_bind(struct device *dev)
+{
+	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+
+	if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required)
+		return;
+
+	if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE)
+		dev->power.set_latency_tolerance = acpi_lpss_set_ltr;
+	else
+		dev_err(dev, "MMIO size insufficient to access LTR\n");
+}
+
+static void acpi_lpss_unbind(struct device *dev)
+{
+	dev->power.set_latency_tolerance = NULL;
+}
+
 static struct acpi_scan_handler lpss_handler = {
 	.ids = acpi_lpss_device_ids,
 	.attach = acpi_lpss_create_device,
+	.bind = acpi_lpss_bind,
+	.unbind = acpi_lpss_unbind,
 };
 
 void __init acpi_lpss_init(void)
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index df96a0fe4890..37d73024b82e 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -408,28 +408,14 @@ static int acpi_pad_pur(acpi_handle handle)
 	return num;
 }
 
-/* Notify firmware how many CPUs are idle */
-static void acpi_pad_ost(acpi_handle handle, int stat,
-	uint32_t idle_cpus)
-{
-	union acpi_object params[3] = {
-		{.type = ACPI_TYPE_INTEGER,},
-		{.type = ACPI_TYPE_INTEGER,},
-		{.type = ACPI_TYPE_BUFFER,},
-	};
-	struct acpi_object_list arg_list = {3, params};
-
-	params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
-	params[1].integer.value =  stat;
-	params[2].buffer.length = 4;
-	params[2].buffer.pointer = (void *)&idle_cpus;
-	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-}
-
 static void acpi_pad_handle_notify(acpi_handle handle)
 {
 	int num_cpus;
 	uint32_t idle_cpus;
+	struct acpi_buffer param = {
+		.length = 4,
+		.pointer = (void *)&idle_cpus,
+	};
 
 	mutex_lock(&isolated_cpus_lock);
 	num_cpus = acpi_pad_pur(handle);
@@ -439,7 +425,7 @@ static void acpi_pad_handle_notify(acpi_handle handle)
 	}
 	acpi_pad_idle_cpus(num_cpus);
 	idle_cpus = acpi_pad_idle_cpus_num();
-	acpi_pad_ost(handle, 0, idle_cpus);
+	acpi_evaluate_ost(handle, ACPI_PROCESSOR_AGGREGATOR_NOTIFY, 0, &param);
 	mutex_unlock(&isolated_cpus_lock);
 }
 
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 438304086ff1..b7ed86a20427 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -122,6 +122,8 @@ acpi-y +=		\
 	rsaddr.o	\
 	rscalc.o	\
 	rscreate.o	\
+	rsdump.o	\
+	rsdumpinfo.o	\
 	rsinfo.o	\
 	rsio.o		\
 	rsirq.o		\
@@ -132,8 +134,6 @@ acpi-y +=		\
 	rsutils.o	\
 	rsxface.o
 
-acpi-$(ACPI_FUTURE_USAGE) += rsdump.o rsdumpinfo.o
-
 acpi-y +=		\
 	tbfadt.o	\
 	tbfind.o	\
diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h
index 8a6c4a0d22db..6f1c616910ac 100644
--- a/drivers/acpi/acpica/accommon.h
+++ b/drivers/acpi/acpica/accommon.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 2bf3ca2b8a7a..68a91eb0fa48 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -115,6 +115,8 @@ ACPI_HW_DEPENDENT_RETURN_VOID(void
 						   char *block_arg))
 ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
 
+void acpi_db_execute_test(char *type_arg);
+
 /*
  * dbconvert - miscellaneous conversion routines
  */
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 427db72a6302..5b472c43c31d 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 0fb0adf435d6..68ec61fff188 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 4ed1aa384df2..b88771b13779 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 6357e932bfd9..2ad2351a9833 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h
index 8af8c9bdeb35..948a6800ab09 100644
--- a/drivers/acpi/acpica/acinterp.h
+++ b/drivers/acpi/acpica/acinterp.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index d95ca5449ace..52a21dafb540 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index 2a86c65d873b..4bceb11c7380 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,17 +63,21 @@
 #define ACPI_SET64(ptr, val)            (*ACPI_CAST64 (ptr) = (u64) (val))
 
 /*
- * printf() format helpers
+ * printf() format helpers. These macros are workarounds for the difficulties
+ * with emitting 64-bit integers and 64-bit pointers with the same code
+ * for both 32-bit and 64-bit hosts.
  */
-
-/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
-
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i), ACPI_LODWORD(i)
 
 #if ACPI_MACHINE_WIDTH == 64
 #define ACPI_FORMAT_NATIVE_UINT(i)      ACPI_FORMAT_UINT64(i)
+#define ACPI_FORMAT_TO_UINT(i)          ACPI_FORMAT_UINT64(i)
+#define ACPI_PRINTF_UINT                 "0x%8.8X%8.8X"
+
 #else
-#define ACPI_FORMAT_NATIVE_UINT(i)      0, (i)
+#define ACPI_FORMAT_NATIVE_UINT(i)      0, (u32) (i)
+#define ACPI_FORMAT_TO_UINT(i)          (u32) (i)
+#define ACPI_PRINTF_UINT                 "0x%8.8X"
 #endif
 
 /*
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index e6138ac4a160..ee1c040f321c 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index cc7ab6dd724e..1a4d61805ebc 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index 3fc9ca7e8aa3..dda0e6affcf1 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index aed319318835..6168b85463ed 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index f600aded7261..9c73d6c5ead2 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h
index ff97430455cb..4b008e8884a1 100644
--- a/drivers/acpi/acpica/acresrc.h
+++ b/drivers/acpi/acpica/acresrc.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h
index fc83c0a5ca70..5d2989a1b68c 100644
--- a/drivers/acpi/acpica/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index c54f42c64fe2..5fa4b2027697 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index be8180c17d7e..ceeec0b7ccb1 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@ extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[];
 
 /* Strings used by the disassembler and debugger resource dump routines */
 
-#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
+#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
 
 extern const char *acpi_gbl_bm_decode[];
 extern const char *acpi_gbl_config_decode[];
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h
index 48a3e331b72d..5908ccec6aea 100644
--- a/drivers/acpi/acpica/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index 87c26366d1df..f3f834408441 100644
--- a/drivers/acpi/acpica/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
index afdc6df17abf..720b1cdda711 100644
--- a/drivers/acpi/acpica/dsargs.c
+++ b/drivers/acpi/acpica/dsargs.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index eb56b66444b5..8daf9de82b73 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index e7a57c554e84..3661c8e90540 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c
index 14424200d246..96644d5ac0e1 100644
--- a/drivers/acpi/acpica/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 81a78ba84311..2c6d42c2bc01 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index c4b0b3657237..b67522df01ac 100644
--- a/drivers/acpi/acpica/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index b1746a68dad1..a1e7e6b6fcf7 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 5205edcf2c01..6c0759c0db47 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index d7f53fb2979a..9f74795e2268 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index 1bbb22fd6fa0..f7f5107e754d 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 2dbe109727c8..bd7811c64169 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index 7f569d573027..2ac28d297305 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c
index d67891de1b54..9d6e2c1de1f8 100644
--- a/drivers/acpi/acpica/dswscope.c
+++ b/drivers/acpi/acpica/dswscope.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index ecb12e2137ff..24f7d5ea678a 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index 83cd45f4a870..c7bffff9ed32 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c
index 4c67193a9fa7..3393a73ca0d6 100644
--- a/drivers/acpi/acpica/evglock.c
+++ b/drivers/acpi/acpica/evglock.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index a9cb4a1a4bb8..955f83da68a5 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index a31e549e64cc..caaed3c673fd 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index a3e2f38aadf6..ae779c1e871d 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index 4d764e847a08..17e4bbfdb096 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c
index e3157313eb27..78ac29351c9e 100644
--- a/drivers/acpi/acpica/evhandler.c
+++ b/drivers/acpi/acpica/evhandler.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index a5687540e9a6..5d594eb2e5ec 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 144cbb9b73bc..e31049b3e9d4 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 8354c4f7f10c..1b148a440d67 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index 9e9e3454d893..4d8a709c1fc4 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 23a7fadca412..a734b27da061 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 39d06af5e347..e286640ad4ff 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 5713da77c665..20a1392ffe06 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -583,6 +583,18 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 		goto unlock_and_exit;
 	}
 
+	/* Validate the parent device */
+
+	if (node->type != ACPI_TYPE_DEVICE) {
+		status = AE_TYPE;
+		goto unlock_and_exit;
+	}
+
+	if (node->object) {
+		status = AE_ALREADY_EXISTS;
+		goto unlock_and_exit;
+	}
+
 	/*
 	 * For user-installed GPE Block Devices, the gpe_block_base_number
 	 * is always zero
@@ -666,6 +678,13 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 		goto unlock_and_exit;
 	}
 
+	/* Validate the parent device */
+
+	if (node->type != ACPI_TYPE_DEVICE) {
+		status = AE_TYPE;
+		goto unlock_and_exit;
+	}
+
 	/* Get the device_object attached to the node */
 
 	obj_desc = acpi_ns_get_attached_object(node);
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 02ed75ac56cd..2d6f187939c7 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 06d216c8d43a..8ba1464efd11 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 69e4a8cc9b71..c545386fee96 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 3c2e6dcdad3e..95d23dabcfbb 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index 81c72a4ecd82..4cfc3d3b5c97 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 4d046faac48c..c3e419c23d17 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index cfd875243421..68d97441432c 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 49fb742d61b9..1d1b27a96c5b 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c
index 65d93607f368..2207e624f538 100644
--- a/drivers/acpi/acpica/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index 7be0205ad067..b49ea2a95f4f 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c
index 14689dec4960..dbb03b544e8c 100644
--- a/drivers/acpi/acpica/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index d74cea416ca0..1b8e94104407 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index d6fa0fce1fc9..2ede656ee26a 100644
--- a/drivers/acpi/acpica/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index bc042adf8804..363767cf01e5 100644
--- a/drivers/acpi/acpica/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index 4459e32c683d..29e9e99f7fe3 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 5a588611ab48..ee3f872870bc 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index 9d28867e60dc..cd5288a257a9 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index 7ca6925a87ca..ab060261b43e 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index 1606524312e3..3cde553bcbe1 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index be3f66973ee8..3af8de3fcea4 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index f0b09bf9887d..daf49f7ea311 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index 20d809d90c5b..04bd16c08f9e 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 26e371073b1a..fd11018b0168 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index 6578dee2e51b..841caed11c08 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index 99dc7b287d55..5b16c5484bee 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index 3d36df828f52..1e66d960fc11 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c
index 414076818d40..858fdd6be598 100644
--- a/drivers/acpi/acpica/hwesleep.c
+++ b/drivers/acpi/acpica/hwesleep.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 96540506058f..2e6caabba07a 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
index 0889a629505f..e701d8c33dbf 100644
--- a/drivers/acpi/acpica/hwpci.c
+++ b/drivers/acpi/acpica/hwpci.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index 12e6cff54f78..e0fd9b4978cd 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index e3828cc4361b..d590693eb54e 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index 3c498dc1636e..76ab5c1a814e 100644
--- a/drivers/acpi/acpica/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index eab70d58852a..6b919127cd9d 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index b4b47db2dee2..96d007df65ec 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 15dddc10fc9b..6921c7f3d208 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 14f65f6345b9..f1249e3463be 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index fd1ff54cda19..607eb9e5150d 100644
--- a/drivers/acpi/acpica/nsalloc.c
+++ b/drivers/acpi/acpica/nsalloc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c
index 74b24c82707e..80fcfc8c9c1b 100644
--- a/drivers/acpi/acpica/nsarguments.c
+++ b/drivers/acpi/acpica/nsarguments.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c
index acd2964c2690..b55642c4ee58 100644
--- a/drivers/acpi/acpica/nsconvert.c
+++ b/drivers/acpi/acpica/nsconvert.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 48b9c6f12643..3d88ef4a3e0d 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
index 283762511b73..42d37109aa5d 100644
--- a/drivers/acpi/acpica/nsdumpdv.c
+++ b/drivers/acpi/acpica/nsdumpdv.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 963ceef063f8..e634a05974db 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 3a0423af968c..5b74677bf74d 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index 89ec645e7730..7ae521ce8d3f 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index 90a0380fb8a0..7eee0a6f02f6 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c
index 7a736f4d1fd8..32845b105053 100644
--- a/drivers/acpi/acpica/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index 177857340271..e83cff31754b 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index d2855d9857c4..392910ffbed9 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c
index 3d5391f9bcb5..61faf77afc18 100644
--- a/drivers/acpi/acpica/nsprepkg.c
+++ b/drivers/acpi/acpica/nsprepkg.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index a05afff50eb9..904f7c3e8a0d 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index 6a25d320b169..53b4b42a13f2 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c
index 47420faef073..af1cc42a8aa1 100644
--- a/drivers/acpi/acpica/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index 4a0665b6bcc1..4a5e3f5c0ff7 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index e81f15ef659a..4758a1f2ce22 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index 1f0c28ba50df..4bd558bf10d2 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_data
+ * FUNCTION:    acpi_get_data_full
  *
  * PARAMETERS:  obj_handle          - Namespace node
  *              handler             - Handler used in call to attach_data
  *              data                - Where the data is returned
+ *              callback            - function to execute before returning
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node
+ *              and execute a callback before returning.
  *
  ******************************************************************************/
 acpi_status
-acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
+		   void **data, void (*callback)(void *))
 {
 	struct acpi_namespace_node *node;
 	acpi_status status;
@@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
 	}
 
 	status = acpi_ns_get_attached_data(node, handler, data);
+	if (ACPI_SUCCESS(status) && callback) {
+		callback(*data);
+	}
 
 unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return (status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_data_full)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_data
+ *
+ * PARAMETERS:  obj_handle          - Namespace node
+ *              handler             - Handler used in call to attach_data
+ *              data                - Where the data is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+{
+	return acpi_get_data_full(obj_handle, handler, data, NULL);
+}
+
 ACPI_EXPORT_SYMBOL(acpi_get_data)
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 3a4bd3ff49a3..8c6c11ce9760 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 0e6d79e462d4..dae9401be7a2 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index 91a5a69db80c..314d314340ae 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 065b44ae538f..646d1a3f6e27 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c
index 95dc608a66a8..af1f46cd37a5 100644
--- a/drivers/acpi/acpica/psobject.c
+++ b/drivers/acpi/acpica/psobject.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
index 1b659e59710a..1755d2ac5656 100644
--- a/drivers/acpi/acpica/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c
index b0c9787dbe61..0d8d37ffd04d 100644
--- a/drivers/acpi/acpica/psopinfo.c
+++ b/drivers/acpi/acpica/psopinfo.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 79d9a28dedef..6d27b597394e 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c
index 6a4b6fb39f32..32d250feea21 100644
--- a/drivers/acpi/acpica/psscope.c
+++ b/drivers/acpi/acpica/psscope.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c
index 877dc0de8df3..0b64181e7720 100644
--- a/drivers/acpi/acpica/pstree.c
+++ b/drivers/acpi/acpica/pstree.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index 91fa73a6e55e..3cd48802eede 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c
index abd65624754f..9cb07e1e76d9 100644
--- a/drivers/acpi/acpica/pswalk.c
+++ b/drivers/acpi/acpica/pswalk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index fcb7a840e996..e135acaa5e1c 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c
index f3a9276ac665..916fd095ff34 100644
--- a/drivers/acpi/acpica/rsaddr.c
+++ b/drivers/acpi/acpica/rsaddr.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index b60c9cf82862..ae9a9cf0f50f 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c
index 3a2ace93e62c..ca62804178bd 100644
--- a/drivers/acpi/acpica/rscreate.c
+++ b/drivers/acpi/acpica/rscreate.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c
index 8a2d4986b0aa..524c5a5300b8 100644
--- a/drivers/acpi/acpica/rsdump.c
+++ b/drivers/acpi/acpica/rsdump.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,8 @@
 
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsdump")
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBER) || defined(ACPI_DEBUGGER)
 /* Local prototypes */
 static void acpi_rs_out_string(char *title, char *value);
 
diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c
index 46192bd53653..2f9332d5c973 100644
--- a/drivers/acpi/acpica/rsdumpinfo.c
+++ b/drivers/acpi/acpica/rsdumpinfo.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,7 @@
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsdumpinfo")
 
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER)
 #define ACPI_RSD_OFFSET(f)          (u8) ACPI_OFFSET (union acpi_resource_data,f)
 #define ACPI_PRT_OFFSET(f)          (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f)
 #define ACPI_RSD_TABLE_SIZE(name)   (sizeof(name) / sizeof (struct acpi_rsdump_info))
diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c
index 41fed78e0de6..9d3f8a9a24bd 100644
--- a/drivers/acpi/acpica/rsinfo.c
+++ b/drivers/acpi/acpica/rsinfo.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -132,8 +132,7 @@ struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = {
 	acpi_rs_convert_uart_serial_bus,
 };
 
-#ifdef ACPI_FUTURE_USAGE
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER)
 
 /* Dispatch table for resource dump functions */
 
@@ -168,7 +167,6 @@ struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = {
 };
 #endif
 
-#endif				/* ACPI_FUTURE_USAGE */
 /*
  * Base sizes for external AML resource descriptors, indexed by internal type.
  * Includes size of the descriptor header (1 byte for small descriptors,
diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c
index ca183755a6f9..19d64873290a 100644
--- a/drivers/acpi/acpica/rsio.c
+++ b/drivers/acpi/acpica/rsio.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c
index 364decc1028a..3461f7db26df 100644
--- a/drivers/acpi/acpica/rsirq.c
+++ b/drivers/acpi/acpica/rsirq.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c
index 6053aa182093..77291293af64 100644
--- a/drivers/acpi/acpica/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c
index ebc773a1b350..eab4483ff5f8 100644
--- a/drivers/acpi/acpica/rsmemory.c
+++ b/drivers/acpi/acpica/rsmemory.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c
index c99cec9cefde..41eea4bc089c 100644
--- a/drivers/acpi/acpica/rsmisc.c
+++ b/drivers/acpi/acpica/rsmisc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c
index fe49fc43e10f..9e8407223d95 100644
--- a/drivers/acpi/acpica/rsserial.c
+++ b/drivers/acpi/acpica/rsserial.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c
index 14a7982c9961..897a5ceb0420 100644
--- a/drivers/acpi/acpica/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 01e476988aae..877ab9202133 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 8f89263ac47e..ec14588254d4 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index e4f4f02d49e7..c12003947bd5 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 634357d51fe9..e3040947e9a0 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -292,10 +292,11 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
 		new_table = acpi_os_map_memory(new_address, new_table_length);
 		if (!new_table) {
 			ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
-					"%4.4s %p Attempted physical table override failed",
+					"%4.4s " ACPI_PRINTF_UINT
+					" Attempted physical table override failed",
 					table_header->signature,
-					ACPI_CAST_PTR(void,
-						      table_desc->address)));
+					ACPI_FORMAT_TO_UINT(table_desc->
+							    address)));
 			return (NULL);
 		}
 
@@ -308,11 +309,11 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
 
 finish_override:
 
-	ACPI_INFO((AE_INFO,
-		   "%4.4s %p %s table override, new table: %p",
+	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
+		   " %s table override, new table: " ACPI_PRINTF_UINT,
 		   table_header->signature,
-		   ACPI_CAST_PTR(void, table_desc->address),
-		   override_type, new_table));
+		   ACPI_FORMAT_TO_UINT(table_desc->address),
+		   override_type, ACPI_FORMAT_TO_UINT(new_table)));
 
 	/* We can now unmap/delete the original table (if fully mapped) */
 
diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c
index 6866e767ba90..df3bb20ea325 100644
--- a/drivers/acpi/acpica/tbprint.c
+++ b/drivers/acpi/acpica/tbprint.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -128,15 +128,17 @@ acpi_tb_print_table_header(acpi_physical_address address,
 	struct acpi_table_header local_header;
 
 	/*
-	 * The reason that the Address is cast to a void pointer is so that we
-	 * can use %p which will work properly on both 32-bit and 64-bit hosts.
+	 * The reason that we use ACPI_PRINTF_UINT and ACPI_FORMAT_TO_UINT is to
+	 * support both 32-bit and 64-bit hosts/addresses in a consistent manner.
+	 * The %p specifier does not emit uniform output on all hosts. On some,
+	 * leading zeros are not supported.
 	 */
 	if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
 
 		/* FACS only has signature and length fields */
 
-		ACPI_INFO((AE_INFO, "%4.4s %p %06X",
-			   header->signature, ACPI_CAST_PTR(void, address),
+		ACPI_INFO((AE_INFO, "%-4.4s " ACPI_PRINTF_UINT " %06X",
+			   header->signature, ACPI_FORMAT_TO_UINT(address),
 			   header->length));
 	} else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 
@@ -147,8 +149,9 @@ acpi_tb_print_table_header(acpi_physical_address address,
 					  header)->oem_id, ACPI_OEM_ID_SIZE);
 		acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 
-		ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)",
-			   ACPI_CAST_PTR(void, address),
+		ACPI_INFO((AE_INFO,
+			   "RSDP " ACPI_PRINTF_UINT " %06X (v%.2d %-6.6s)",
+			   ACPI_FORMAT_TO_UINT(address),
 			   (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
 			    revision >
 			    0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
@@ -162,8 +165,9 @@ acpi_tb_print_table_header(acpi_physical_address address,
 		acpi_tb_cleanup_table_header(&local_header, header);
 
 		ACPI_INFO((AE_INFO,
-			   "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
-			   local_header.signature, ACPI_CAST_PTR(void, address),
+			   "%-4.4s " ACPI_PRINTF_UINT
+			   " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
+			   local_header.signature, ACPI_FORMAT_TO_UINT(address),
 			   local_header.length, local_header.revision,
 			   local_header.oem_id, local_header.oem_table_id,
 			   local_header.oem_revision,
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 6412d3c301cb..a4702eee91a8 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index db826eaadd1c..a1593159d9ea 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index 60b5a871833c..0909420fc776 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index e4e1468877c3..65ab8fed3d5e 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
index 2c2b6ae5dfc4..a1acec9d2ef3 100644
--- a/drivers/acpi/acpica/utaddress.c
+++ b/drivers/acpi/acpica/utaddress.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c
index 1851762fc5b5..efac83c606dc 100644
--- a/drivers/acpi/acpica/utalloc.c
+++ b/drivers/acpi/acpica/utalloc.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c
index 11fde93be120..3c1699740653 100644
--- a/drivers/acpi/acpica/utbuffer.c
+++ b/drivers/acpi/acpica/utbuffer.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
index cacd2fd9e665..78fde0aac487 100644
--- a/drivers/acpi/acpica/utcache.c
+++ b/drivers/acpi/acpica/utcache.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index edff4e653d9a..270c16464dd9 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -535,10 +535,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
 
 	case ACPI_TYPE_LOCAL_REFERENCE:
 
-		/* TBD: should validate incoming handle */
+		/* An incoming reference is defined to be a namespace node */
 
-		internal_object->reference.class = ACPI_REFCLASS_NAME;
-		internal_object->reference.node =
+		internal_object->reference.class = ACPI_REFCLASS_REFOF;
+		internal_object->reference.object =
 		    external_object->reference.handle;
 		break;
 
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index d971c8631263..21a20ac5b1e1 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index b3f31dd89a45..fbfa9eca011f 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index c07d2227ea42..ed4cb8683310 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c
index 154fdcaa5830..8e544d4688cd 100644
--- a/drivers/acpi/acpica/uterror.c
+++ b/drivers/acpi/acpica/uterror.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index 16fb90506db7..8fed1482d228 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c
index 3cf7b597edb9..0403dcaabaf2 100644
--- a/drivers/acpi/acpica/utexcep.c
+++ b/drivers/acpi/acpica/utexcep.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 030cb0dc673c..21785da2318e 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index bfca7b4b6731..4b12880e5b11 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index c5d1ac44c07d..5f56fc49021e 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c
index 5c26ad420344..dc6e96547f18 100644
--- a/drivers/acpi/acpica/utlock.c
+++ b/drivers/acpi/acpica/utlock.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c
index 909fe66e1934..d44dee6ee10a 100644
--- a/drivers/acpi/acpica/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 02f9101b65e4..2e2bb14e1099 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 08c323245584..82717fff9ffc 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index 517af700399d..dfa9009bfc87 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 8856bd37bc76..1e5525e87d34 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -74,6 +74,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
 	{"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2},	/* Windows Vista SP2 - Added 09/2010 */
 	{"Windows 2009", NULL, 0, ACPI_OSI_WIN_7},	/* Windows 7 and Server 2008 R2 - Added 09/2009 */
 	{"Windows 2012", NULL, 0, ACPI_OSI_WIN_8},	/* Windows 8 and Server 2012 - Added 08/2012 */
+	{"Windows 2013", NULL, 0, ACPI_OSI_WIN_8},	/* Windows 8.1 and Server 2012 R2 - Added 01/2014 */
 
 	/* Feature Group Strings */
 
diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c
index eb3aca761369..36bec57ebd23 100644
--- a/drivers/acpi/acpica/utownerid.c
+++ b/drivers/acpi/acpica/utownerid.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c
index 2b1ce4cd3207..db30caff130a 100644
--- a/drivers/acpi/acpica/utpredef.c
+++ b/drivers/acpi/acpica/utpredef.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c
index 2c2accb9e534..14cb6c0c8be2 100644
--- a/drivers/acpi/acpica/utresrc.c
+++ b/drivers/acpi/acpica/utresrc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,8 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utresrc")
-#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
+
+#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
 /*
  * Strings used to decode resource descriptors.
  * Used by both the disassembler and the debugger resource dump routines
diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c
index 03c4c2febd84..1cc97a752c15 100644
--- a/drivers/acpi/acpica/utstate.c
+++ b/drivers/acpi/acpica/utstate.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c
index 45c0eb26b33d..77219336c7e0 100644
--- a/drivers/acpi/acpica/utstring.c
+++ b/drivers/acpi/acpica/utstring.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
index c0027773cccb..7d0ee969d781 100644
--- a/drivers/acpi/acpica/uttrack.c
+++ b/drivers/acpi/acpica/uttrack.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -276,7 +276,8 @@ acpi_ut_free_and_track(void *allocation,
 	}
 
 	acpi_os_free(debug_block);
-	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
+			  allocation, debug_block));
 	return_VOID;
 }
 
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index be322c83643a..502a8492dc83 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
index f7edb88f6054..edd861102f1b 100644
--- a/drivers/acpi/acpica/utxferror.c
+++ b/drivers/acpi/acpica/utxferror.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
index 246ef68681f4..13380d818462 100644
--- a/drivers/acpi/acpica/utxfinit.c
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c
index 312299721ba1..2a0f9e04d3a4 100644
--- a/drivers/acpi/acpica/utxfmutex.c
+++ b/drivers/acpi/acpica/utxfmutex.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index 3650b2183227..c4dac7150960 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -12,7 +12,7 @@ config ACPI_APEI
 
 config ACPI_APEI_GHES
 	bool "APEI Generic Hardware Error Source"
-	depends on ACPI_APEI && X86
+	depends on ACPI_APEI
 	select ACPI_HED
 	select IRQ_WORK
 	select GENERIC_ALLOCATOR
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index fcb59c21c68d..4cefb98f274d 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -311,9 +311,7 @@ static void acpi_bus_osc_support(void)
 	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
 #endif
 
-#ifdef ACPI_HOTPLUG_OST
 	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
-#endif
 
 	if (!ghes_disable)
 		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
@@ -340,60 +338,77 @@ static void acpi_bus_osc_support(void)
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_device *device = NULL;
+	struct acpi_device *adev;
 	struct acpi_driver *driver;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
-			  type, handle));
+	acpi_status status;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	switch (type) {
-
 	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
 		/* TBD: Exactly what does 'light' mean? */
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto err;
 	}
 
-	acpi_bus_get_device(handle, &device);
-	if (device) {
-		driver = device->driver;
-		if (driver && driver->ops.notify &&
-		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
-			driver->ops.notify(device, type);
+	adev = acpi_bus_get_acpi_device(handle);
+	if (!adev)
+		goto err;
+
+	driver = adev->driver;
+	if (driver && driver->ops.notify &&
+	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
+		driver->ops.notify(adev, type);
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
+	default:
+		break;
 	}
+	acpi_bus_put_acpi_device(adev);
+	return;
+
+ err:
+	acpi_evaluate_ost(handle, type, ost_code, NULL);
 }
 
 /* --------------------------------------------------------------------------
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 368f9ddb8480..a55cccbc7356 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -68,6 +68,9 @@ static int container_device_attach(struct acpi_device *adev,
 	struct device *dev;
 	int ret;
 
+	if (adev->flags.is_dock_station)
+		return 0;
+
 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
 	if (!cdev)
 		return -ENOMEM;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 5bfd769fc91f..a7bd3002dbbc 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -1,7 +1,9 @@
 /*
  *  dock.c - ACPI dock station driver
  *
- *  Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
+ *  Copyright (C) 2006, 2014, Intel Corp.
+ *  Author: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -68,15 +70,10 @@ struct dock_station {
 };
 static LIST_HEAD(dock_stations);
 static int dock_station_count;
-static DEFINE_MUTEX(hotplug_lock);
 
 struct dock_dependent_device {
 	struct list_head list;
-	acpi_handle handle;
-	const struct acpi_dock_ops *hp_ops;
-	void *hp_context;
-	unsigned int hp_refcount;
-	void (*hp_release)(void *);
+	struct acpi_device *adev;
 };
 
 #define DOCK_DOCKING	0x00000001
@@ -98,13 +95,13 @@ enum dock_callback_type {
  *****************************************************************************/
 /**
  * add_dock_dependent_device - associate a device with the dock station
- * @ds: The dock station
- * @handle: handle of the dependent device
+ * @ds: Dock station.
+ * @adev: Dependent ACPI device object.
  *
  * Add the dependent device to the dock's dependent device list.
  */
-static int __init
-add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
+static int add_dock_dependent_device(struct dock_station *ds,
+				     struct acpi_device *adev)
 {
 	struct dock_dependent_device *dd;
 
@@ -112,180 +109,120 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 	if (!dd)
 		return -ENOMEM;
 
-	dd->handle = handle;
+	dd->adev = adev;
 	INIT_LIST_HEAD(&dd->list);
 	list_add_tail(&dd->list, &ds->dependent_devices);
 
 	return 0;
 }
 
-static void remove_dock_dependent_devices(struct dock_station *ds)
+static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
+			       enum dock_callback_type cb_type)
 {
-	struct dock_dependent_device *dd, *aux;
+	struct acpi_device *adev = dd->adev;
 
-	list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) {
-		list_del(&dd->list);
-		kfree(dd);
-	}
-}
+	acpi_lock_hp_context();
 
-/**
- * dock_init_hotplug - Initialize a hotplug device on a docking station.
- * @dd: Dock-dependent device.
- * @ops: Dock operations to attach to the dependent device.
- * @context: Data to pass to the @ops callbacks and @release.
- * @init: Optional initialization routine to run after setting up context.
- * @release: Optional release routine to run on removal.
- */
-static int dock_init_hotplug(struct dock_dependent_device *dd,
-			     const struct acpi_dock_ops *ops, void *context,
-			     void (*init)(void *), void (*release)(void *))
-{
-	int ret = 0;
+	if (!adev->hp)
+		goto out;
 
-	mutex_lock(&hotplug_lock);
-	if (WARN_ON(dd->hp_context)) {
-		ret = -EEXIST;
-	} else {
-		dd->hp_refcount = 1;
-		dd->hp_ops = ops;
-		dd->hp_context = context;
-		dd->hp_release = release;
-		if (init)
-			init(context);
-	}
-	mutex_unlock(&hotplug_lock);
-	return ret;
-}
+	if (cb_type == DOCK_CALL_FIXUP) {
+		void (*fixup)(struct acpi_device *);
 
-/**
- * dock_release_hotplug - Decrement hotplug reference counter of dock device.
- * @dd: Dock-dependent device.
- *
- * Decrement the reference counter of @dd and if 0, detach its hotplug
- * operations from it, reset its context pointer and run the optional release
- * routine if present.
- */
-static void dock_release_hotplug(struct dock_dependent_device *dd)
-{
-	mutex_lock(&hotplug_lock);
-	if (dd->hp_context && !--dd->hp_refcount) {
-		void (*release)(void *) = dd->hp_release;
-		void *context = dd->hp_context;
-
-		dd->hp_ops = NULL;
-		dd->hp_context = NULL;
-		dd->hp_release = NULL;
-		if (release)
-			release(context);
-	}
-	mutex_unlock(&hotplug_lock);
-}
+		fixup = adev->hp->fixup;
+		if (fixup) {
+			acpi_unlock_hp_context();
+			fixup(adev);
+			return;
+		}
+	} else if (cb_type == DOCK_CALL_UEVENT) {
+		void (*uevent)(struct acpi_device *, u32);
+
+		uevent = adev->hp->uevent;
+		if (uevent) {
+			acpi_unlock_hp_context();
+			uevent(adev, event);
+			return;
+		}
+	} else {
+		int (*notify)(struct acpi_device *, u32);
 
-static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
-			       enum dock_callback_type cb_type)
-{
-	acpi_notify_handler cb = NULL;
-	bool run = false;
-
-	mutex_lock(&hotplug_lock);
-
-	if (dd->hp_context) {
-		run = true;
-		dd->hp_refcount++;
-		if (dd->hp_ops) {
-			switch (cb_type) {
-			case DOCK_CALL_FIXUP:
-				cb = dd->hp_ops->fixup;
-				break;
-			case DOCK_CALL_UEVENT:
-				cb = dd->hp_ops->uevent;
-				break;
-			default:
-				cb = dd->hp_ops->handler;
-			}
+		notify = adev->hp->notify;
+		if (notify) {
+			acpi_unlock_hp_context();
+			notify(adev, event);
+			return;
 		}
 	}
 
-	mutex_unlock(&hotplug_lock);
+ out:
+	acpi_unlock_hp_context();
+}
 
-	if (!run)
-		return;
+static struct dock_station *find_dock_station(acpi_handle handle)
+{
+	struct dock_station *ds;
 
-	if (cb)
-		cb(dd->handle, event, dd->hp_context);
+	list_for_each_entry(ds, &dock_stations, sibling)
+		if (ds->handle == handle)
+			return ds;
 
-	dock_release_hotplug(dd);
+	return NULL;
 }
 
 /**
  * find_dock_dependent_device - get a device dependent on this dock
  * @ds: the dock station
- * @handle: the acpi_handle of the device we want
+ * @adev: ACPI device object to find.
  *
  * iterate over the dependent device list for this dock.  If the
  * dependent device matches the handle, return.
  */
 static struct dock_dependent_device *
-find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
+find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev)
 {
 	struct dock_dependent_device *dd;
 
 	list_for_each_entry(dd, &ds->dependent_devices, list)
-		if (handle == dd->handle)
+		if (adev == dd->adev)
 			return dd;
 
 	return NULL;
 }
 
-/*****************************************************************************
- *                         Dock functions                                    *
- *****************************************************************************/
-static int __init is_battery(acpi_handle handle)
+void register_dock_dependent_device(struct acpi_device *adev,
+				    acpi_handle dshandle)
 {
-	struct acpi_device_info *info;
-	int ret = 1;
+	struct dock_station *ds = find_dock_station(dshandle);
 
-	if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info)))
-		return 0;
-	if (!(info->valid & ACPI_VALID_HID))
-		ret = 0;
-	else
-		ret = !strcmp("PNP0C0A", info->hardware_id.string);
-
-	kfree(info);
-	return ret;
+	if (ds && !find_dock_dependent_device(ds, adev))
+		add_dock_dependent_device(ds, adev);
 }
 
-/* Check whether ACPI object is an ejectable battery or disk bay */
-static bool __init is_ejectable_bay(acpi_handle handle)
-{
-	if (acpi_has_method(handle, "_EJ0") && is_battery(handle))
-		return true;
-
-	return acpi_bay_match(handle);
-}
+/*****************************************************************************
+ *                         Dock functions                                    *
+ *****************************************************************************/
 
 /**
  * is_dock_device - see if a device is on a dock station
- * @handle: acpi handle of the device
+ * @adev: ACPI device object to check.
  *
  * If this device is either the dock station itself,
  * or is a device dependent on the dock station, then it
  * is a dock device
  */
-int is_dock_device(acpi_handle handle)
+int is_dock_device(struct acpi_device *adev)
 {
 	struct dock_station *dock_station;
 
 	if (!dock_station_count)
 		return 0;
 
-	if (acpi_dock_match(handle))
+	if (acpi_dock_match(adev->handle))
 		return 1;
 
 	list_for_each_entry(dock_station, &dock_stations, sibling)
-		if (find_dock_dependent_device(dock_station, handle))
+		if (find_dock_dependent_device(dock_station, adev))
 			return 1;
 
 	return 0;
@@ -313,43 +250,6 @@ static int dock_present(struct dock_station *ds)
 }
 
 /**
- * dock_create_acpi_device - add new devices to acpi
- * @handle - handle of the device to add
- *
- *  This function will create a new acpi_device for the given
- *  handle if one does not exist already.  This should cause
- *  acpi to scan for drivers for the given devices, and call
- *  matching driver's add routine.
- */
-static void dock_create_acpi_device(acpi_handle handle)
-{
-	struct acpi_device *device = NULL;
-	int ret;
-
-	acpi_bus_get_device(handle, &device);
-	if (!acpi_device_enumerated(device)) {
-		ret = acpi_bus_scan(handle);
-		if (ret)
-			pr_debug("error adding bus, %x\n", -ret);
-	}
-}
-
-/**
- * dock_remove_acpi_device - remove the acpi_device struct from acpi
- * @handle - the handle of the device to remove
- *
- *  Tell acpi to remove the acpi_device.  This should cause any loaded
- *  driver to have it's remove routine called.
- */
-static void dock_remove_acpi_device(acpi_handle handle)
-{
-	struct acpi_device *device;
-
-	if (!acpi_bus_get_device(handle, &device))
-		acpi_bus_trim(device);
-}
-
-/**
  * hot_remove_dock_devices - Remove dock station devices.
  * @ds: Dock station.
  */
@@ -366,7 +266,7 @@ static void hot_remove_dock_devices(struct dock_station *ds)
 		dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
 
 	list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
-		dock_remove_acpi_device(dd->handle);
+		acpi_bus_trim(dd->adev);
 }
 
 /**
@@ -392,12 +292,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
 		dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
 
 	/*
-	 * Now make sure that an acpi_device is created for each dependent
-	 * device.  That will cause scan handlers to be attached to device
-	 * objects or acpi_drivers to be stopped/started if they are present.
+	 * Check if all devices have been enumerated already.  If not, run
+	 * acpi_bus_scan() for them and that will cause scan handlers to be
+	 * attached to device objects or acpi_drivers to be stopped/started if
+	 * they are present.
 	 */
-	list_for_each_entry(dd, &ds->dependent_devices, list)
-		dock_create_acpi_device(dd->handle);
+	list_for_each_entry(dd, &ds->dependent_devices, list) {
+		struct acpi_device *adev = dd->adev;
+
+		if (!acpi_device_enumerated(adev)) {
+			int ret = acpi_bus_scan(adev->handle);
+			if (ret)
+				dev_dbg(&adev->dev, "scan error %d\n", -ret);
+		}
+	}
 }
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
@@ -501,71 +409,6 @@ static int dock_in_progress(struct dock_station *ds)
 }
 
 /**
- * register_hotplug_dock_device - register a hotplug function
- * @handle: the handle of the device
- * @ops: handlers to call after docking
- * @context: device specific data
- * @init: Optional initialization routine to run after registration
- * @release: Optional release routine to run on unregistration
- *
- * If a driver would like to perform a hotplug operation after a dock
- * event, they can register an acpi_notifiy_handler to be called by
- * the dock driver after _DCK is executed.
- */
-int register_hotplug_dock_device(acpi_handle handle,
-				 const struct acpi_dock_ops *ops, void *context,
-				 void (*init)(void *), void (*release)(void *))
-{
-	struct dock_dependent_device *dd;
-	struct dock_station *dock_station;
-	int ret = -EINVAL;
-
-	if (WARN_ON(!context))
-		return -EINVAL;
-
-	if (!dock_station_count)
-		return -ENODEV;
-
-	/*
-	 * make sure this handle is for a device dependent on the dock,
-	 * this would include the dock station itself
-	 */
-	list_for_each_entry(dock_station, &dock_stations, sibling) {
-		/*
-		 * An ATA bay can be in a dock and itself can be ejected
-		 * separately, so there are two 'dock stations' which need the
-		 * ops
-		 */
-		dd = find_dock_dependent_device(dock_station, handle);
-		if (dd && !dock_init_hotplug(dd, ops, context, init, release))
-			ret = 0;
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
-
-/**
- * unregister_hotplug_dock_device - remove yourself from the hotplug list
- * @handle: the acpi handle of the device
- */
-void unregister_hotplug_dock_device(acpi_handle handle)
-{
-	struct dock_dependent_device *dd;
-	struct dock_station *dock_station;
-
-	if (!dock_station_count)
-		return;
-
-	list_for_each_entry(dock_station, &dock_stations, sibling) {
-		dd = find_dock_dependent_device(dock_station, handle);
-		if (dd)
-			dock_release_hotplug(dd);
-	}
-}
-EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
-
-/**
  * handle_eject_request - handle an undock request checking for error conditions
  *
  * Check to make sure the dock device is still present, then undock and
@@ -598,20 +441,23 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 }
 
 /**
- * dock_notify - act upon an acpi dock notification
- * @ds: dock station
- * @event: the acpi event
+ * dock_notify - Handle ACPI dock notification.
+ * @adev: Dock station's ACPI device object.
+ * @event: Event code.
  *
  * If we are notified to dock, then check to see if the dock is
  * present and then dock.  Notify all drivers of the dock event,
  * and then hotplug and devices that may need hotplugging.
  */
-static void dock_notify(struct dock_station *ds, u32 event)
+int dock_notify(struct acpi_device *adev, u32 event)
 {
-	acpi_handle handle = ds->handle;
-	struct acpi_device *adev = NULL;
+	acpi_handle handle = adev->handle;
+	struct dock_station *ds = find_dock_station(handle);
 	int surprise_removal = 0;
 
+	if (!ds)
+		return -ENODEV;
+
 	/*
 	 * According to acpi spec 3.0a, if a DEVICE_CHECK notification
 	 * is sent and _DCK is present, it is assumed to mean an undock
@@ -632,7 +478,6 @@ static void dock_notify(struct dock_station *ds, u32 event)
 	switch (event) {
 	case ACPI_NOTIFY_BUS_CHECK:
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		acpi_bus_get_device(handle, &adev);
 		if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
 			begin_dock(ds);
 			dock(ds);
@@ -662,49 +507,8 @@ static void dock_notify(struct dock_station *ds, u32 event)
 		else
 			dock_event(ds, event, UNDOCK_EVENT);
 		break;
-	default:
-		acpi_handle_err(handle, "Unknown dock event %d\n", event);
 	}
-}
-
-static void acpi_dock_deferred_cb(void *data, u32 event)
-{
-	acpi_scan_lock_acquire();
-	dock_notify(data, event);
-	acpi_scan_lock_release();
-}
-
-static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
-{
-	if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
-	   && event != ACPI_NOTIFY_EJECT_REQUEST)
-		return;
-
-	acpi_hotplug_execute(acpi_dock_deferred_cb, data, event);
-}
-
-/**
- * find_dock_devices - find devices on the dock station
- * @handle: the handle of the device we are examining
- * @lvl: unused
- * @context: the dock station private data
- * @rv: unused
- *
- * This function is called by acpi_walk_namespace.  It will
- * check to see if an object has an _EJD method.  If it does, then it
- * will see if it is dependent on the dock station.
- */
-static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
-					    void *context, void **rv)
-{
-	struct dock_station *ds = context;
-	acpi_handle ejd = NULL;
-
-	acpi_bus_get_ejd(handle, &ejd);
-	if (ejd == ds->handle)
-		add_dock_dependent_device(ds, handle);
-
-	return AE_OK;
+	return 0;
 }
 
 /*
@@ -803,23 +607,28 @@ static struct attribute_group dock_attribute_group = {
 };
 
 /**
- * dock_add - add a new dock station
- * @handle: the dock station handle
+ * acpi_dock_add - Add a new dock station
+ * @adev: Dock station ACPI device object.
  *
- * allocated and initialize a new dock station device.  Find all devices
- * that are on the dock station, and register for dock event notifications.
+ * allocated and initialize a new dock station device.
  */
-static int __init dock_add(acpi_handle handle)
+void acpi_dock_add(struct acpi_device *adev)
 {
 	struct dock_station *dock_station, ds = { NULL, };
+	struct platform_device_info pdevinfo;
+	acpi_handle handle = adev->handle;
 	struct platform_device *dd;
-	acpi_status status;
 	int ret;
 
-	dd = platform_device_register_data(NULL, "dock", dock_station_count,
-					   &ds, sizeof(ds));
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	pdevinfo.name = "dock";
+	pdevinfo.id = dock_station_count;
+	pdevinfo.acpi_node.companion = adev;
+	pdevinfo.data = &ds;
+	pdevinfo.size_data = sizeof(ds);
+	dd = platform_device_register_full(&pdevinfo);
 	if (IS_ERR(dd))
-		return PTR_ERR(dd);
+		return;
 
 	dock_station = dd->dev.platform_data;
 
@@ -837,72 +646,29 @@ static int __init dock_add(acpi_handle handle)
 		dock_station->flags |= DOCK_IS_DOCK;
 	if (acpi_ata_match(handle))
 		dock_station->flags |= DOCK_IS_ATA;
-	if (is_battery(handle))
+	if (acpi_device_is_battery(adev))
 		dock_station->flags |= DOCK_IS_BAT;
 
 	ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
 	if (ret)
 		goto err_unregister;
 
-	/* Find dependent devices */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX, find_dock_devices, NULL,
-			    dock_station, NULL);
-
 	/* add the dock station as a device dependent on itself */
-	ret = add_dock_dependent_device(dock_station, handle);
+	ret = add_dock_dependent_device(dock_station, adev);
 	if (ret)
 		goto err_rmgroup;
 
-	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					     dock_notify_handler, dock_station);
-	if (ACPI_FAILURE(status)) {
-		ret = -ENODEV;
-		goto err_rmgroup;
-	}
-
 	dock_station_count++;
 	list_add(&dock_station->sibling, &dock_stations);
-	return 0;
+	adev->flags.is_dock_station = true;
+	dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n",
+		 dock_station_count);
+	return;
 
 err_rmgroup:
-	remove_dock_dependent_devices(dock_station);
 	sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
+
 err_unregister:
 	platform_device_unregister(dd);
 	acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
-	return ret;
-}
-
-/**
- * find_dock_and_bay - look for dock stations and bays
- * @handle: acpi handle of a device
- * @lvl: unused
- * @context: unused
- * @rv: unused
- *
- * This is called by acpi_walk_namespace to look for dock stations and bays.
- */
-static acpi_status __init
-find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	if (acpi_dock_match(handle) || is_ejectable_bay(handle))
-		dock_add(handle);
-
-	return AE_OK;
-}
-
-void __init acpi_dock_init(void)
-{
-	/* look for dock stations and bays */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-		ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
-
-	if (!dock_station_count) {
-		pr_info(PREFIX "No dock devices found.\n");
-		return;
-	}
-
-	pr_info(PREFIX "%s: %d docks/bays found\n",
-		ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
 }
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 09e423f3d8ad..8acf53e62966 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -55,11 +55,16 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev);
 static int acpi_fan_resume(struct device *dev);
+static struct dev_pm_ops acpi_fan_pm = {
+	.resume = acpi_fan_resume,
+	.freeze = acpi_fan_suspend,
+	.thaw = acpi_fan_resume,
+	.restore = acpi_fan_resume,
+};
+#define FAN_PM_OPS_PTR (&acpi_fan_pm)
 #else
-#define acpi_fan_suspend NULL
-#define acpi_fan_resume NULL
+#define FAN_PM_OPS_PTR NULL
 #endif
-static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
 
 static struct acpi_driver acpi_fan_driver = {
 	.name = "fan",
@@ -69,7 +74,7 @@ static struct acpi_driver acpi_fan_driver = {
 		.add = acpi_fan_add,
 		.remove = acpi_fan_remove,
 		},
-	.drv.pm = &acpi_fan_pm,
+	.drv.pm = FAN_PM_OPS_PTR,
 };
 
 /* thermal cooling device callbacks */
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 0c789224d40d..f774c65ecb8b 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -287,6 +287,7 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one);
 static int acpi_platform_notify(struct device *dev)
 {
 	struct acpi_bus_type *type = acpi_get_bus_type(dev);
+	struct acpi_device *adev;
 	int ret;
 
 	ret = acpi_bind_one(dev, NULL);
@@ -303,9 +304,14 @@ static int acpi_platform_notify(struct device *dev)
 		if (ret)
 			goto out;
 	}
+	adev = ACPI_COMPANION(dev);
+	if (!adev)
+		goto out;
 
 	if (type && type->setup)
 		type->setup(dev);
+	else if (adev->handler && adev->handler->bind)
+		adev->handler->bind(dev);
 
  out:
 #if ACPI_GLUE_DEBUG
@@ -324,11 +330,17 @@ static int acpi_platform_notify(struct device *dev)
 
 static int acpi_platform_notify_remove(struct device *dev)
 {
+	struct acpi_device *adev = ACPI_COMPANION(dev);
 	struct acpi_bus_type *type;
 
+	if (!adev)
+		return 0;
+
 	type = acpi_get_bus_type(dev);
 	if (type && type->cleanup)
 		type->cleanup(dev);
+	else if (adev->handler && adev->handler->unbind)
+		adev->handler->unbind(dev);
 
 	acpi_unbind_one(dev);
 	return 0;
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index dedbb2d802f1..4d081fc1aa24 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -37,9 +37,15 @@ void acpi_container_init(void);
 static inline void acpi_container_init(void) {}
 #endif
 #ifdef CONFIG_ACPI_DOCK
-void acpi_dock_init(void);
+void register_dock_dependent_device(struct acpi_device *adev,
+				    acpi_handle dshandle);
+int dock_notify(struct acpi_device *adev, u32 event);
+void acpi_dock_add(struct acpi_device *adev);
 #else
-static inline void acpi_dock_init(void) {}
+static inline void register_dock_dependent_device(struct acpi_device *adev,
+						  acpi_handle dshandle) {}
+static inline int dock_notify(struct acpi_device *adev, u32 event) { return -ENODEV; }
+static inline void acpi_dock_add(struct acpi_device *adev) {}
 #endif
 #ifdef CONFIG_ACPI_HOTPLUG_MEMORY
 void acpi_memory_hotplug_init(void);
@@ -73,6 +79,7 @@ static inline void acpi_lpss_init(void) {}
 #endif
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
+void acpi_device_hotplug(void *data, u32 src);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 
 /* --------------------------------------------------------------------------
@@ -90,6 +97,7 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
 int acpi_bind_one(struct device *dev, struct acpi_device *adev);
 int acpi_unbind_one(struct device *dev);
 bool acpi_device_is_present(struct acpi_device *adev);
+bool acpi_device_is_battery(struct acpi_device *adev);
 
 /* --------------------------------------------------------------------------
                                   Power Resource
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 9e6816ef280a..24b5476449a1 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -60,7 +60,7 @@ int node_to_pxm(int node)
 	return node_to_pxm_map[node];
 }
 
-void __acpi_map_pxm_to_node(int pxm, int node)
+static void __acpi_map_pxm_to_node(int pxm, int node)
 {
 	if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
 		pxm_to_node_map[pxm] = node;
@@ -193,7 +193,7 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
 	return 0;
 }
 
-void __init __attribute__ ((weak))
+void __init __weak
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 {
 	printk(KERN_WARNING PREFIX
@@ -314,7 +314,7 @@ int __init acpi_numa_init(void)
 	return 0;
 }
 
-int acpi_get_pxm(acpi_handle h)
+static int acpi_get_pxm(acpi_handle h)
 {
 	unsigned long long pxm;
 	acpi_status status;
@@ -331,14 +331,14 @@ int acpi_get_pxm(acpi_handle h)
 	return -1;
 }
 
-int acpi_get_node(acpi_handle *handle)
+int acpi_get_node(acpi_handle handle)
 {
-	int pxm, node = NUMA_NO_NODE;
+	int pxm;
 
 	pxm = acpi_get_pxm(handle);
-	if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
-		node = acpi_map_pxm_to_node(pxm);
+	if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
+		return NUMA_NO_NODE;
 
-	return node;
+	return acpi_map_pxm_to_node(pxm);
 }
 EXPORT_SYMBOL(acpi_get_node);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index fc1aa7909690..0d7b7145399e 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1780,6 +1780,17 @@ static int __init acpi_no_auto_ssdt_setup(char *s)
 
 __setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
 
+static int __init acpi_disable_return_repair(char *s)
+{
+	printk(KERN_NOTICE PREFIX
+	       "ACPI: Predefined validation mechanism disabled\n");
+	acpi_gbl_disable_auto_repair = TRUE;
+
+	return 1;
+}
+
+__setup("acpica_no_return_repair", acpi_disable_return_repair);
+
 acpi_status __init acpi_os_initialize(void)
 {
 	acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 361b40c10c3f..9c62340c2360 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -370,6 +370,30 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 	return NULL;
 }
 
+#if IS_ENABLED(CONFIG_ISA) || IS_ENABLED(CONFIG_EISA)
+static int acpi_isa_register_gsi(struct pci_dev *dev)
+{
+	u32 dev_gsi;
+
+	/* Interrupt Line values above 0xF are forbidden */
+	if (dev->irq > 0 && (dev->irq <= 0xF) &&
+	    (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
+		dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
+			 pin_name(dev->pin), dev->irq);
+		acpi_register_gsi(&dev->dev, dev_gsi,
+				  ACPI_LEVEL_SENSITIVE,
+				  ACPI_ACTIVE_LOW);
+		return 0;
+	}
+	return -EINVAL;
+}
+#else
+static inline int acpi_isa_register_gsi(struct pci_dev *dev)
+{
+	return -ENODEV;
+}
+#endif
+
 int acpi_pci_irq_enable(struct pci_dev *dev)
 {
 	struct acpi_prt_entry *entry;
@@ -416,19 +440,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	 * driver reported one, then use it. Exit in any case.
 	 */
 	if (gsi < 0) {
-		u32 dev_gsi;
-		/* Interrupt Line values above 0xF are forbidden */
-		if (dev->irq > 0 && (dev->irq <= 0xF) &&
-		    (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
-			dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
-				 pin_name(pin), dev->irq);
-			acpi_register_gsi(&dev->dev, dev_gsi,
-					  ACPI_LEVEL_SENSITIVE,
-					  ACPI_ACTIVE_LOW);
-		} else {
+		if (acpi_isa_register_gsi(dev))
 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
 				 pin_name(pin));
-		}
 
 		kfree(entry);
 		return 0;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c1c4102e6478..c288ff3c6998 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -51,7 +51,7 @@ static void acpi_pci_root_remove(struct acpi_device *device);
 
 static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
 {
-	acpiphp_check_host_bridge(adev->handle);
+	acpiphp_check_host_bridge(adev);
 	return 0;
 }
 
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index a4eea9a508d3..f1dd404463aa 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -19,24 +19,6 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
-static int __init set_no_mwait(const struct dmi_system_id *id)
-{
-	printk(KERN_NOTICE PREFIX "%s detected - "
-		"disabling mwait for CPU C-states\n", id->ident);
-	boot_option_idle_override = IDLE_NOMWAIT;
-	return 0;
-}
-
-static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
-	{
-	set_no_mwait, "Extensa 5220", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
-	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
-	{},
-};
-
 static int map_lapic_id(struct acpi_subtable_header *entry,
 		 u32 acpi_id, int *apic_id)
 {
@@ -89,6 +71,28 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
 	return 0;
 }
 
+static int map_gic_id(struct acpi_subtable_header *entry,
+		int device_declaration, u32 acpi_id, int *apic_id)
+{
+	struct acpi_madt_generic_interrupt *gic =
+		(struct acpi_madt_generic_interrupt *)entry;
+
+	if (!(gic->flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	/*
+	 * In the GIC interrupt model, logical processors are
+	 * required to have a Processor Device object in the DSDT,
+	 * so we should check device_declaration here
+	 */
+	if (device_declaration && (gic->uid == acpi_id)) {
+		*apic_id = gic->gic_id;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int map_madt_entry(int type, u32 acpi_id)
 {
 	unsigned long madt_end, entry;
@@ -124,6 +128,9 @@ static int map_madt_entry(int type, u32 acpi_id)
 		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
 			if (!map_lsapic_id(header, type, acpi_id, &apic_id))
 				break;
+		} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+			if (!map_gic_id(header, type, acpi_id, &apic_id))
+				break;
 		}
 		entry += header->length;
 	}
@@ -154,6 +161,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 		map_lapic_id(header, acpi_id, &apic_id);
 	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
 		map_lsapic_id(header, type, acpi_id, &apic_id);
+	} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+		map_gic_id(header, type, acpi_id, &apic_id);
 	}
 
 exit:
@@ -323,7 +332,7 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void)
  * _PDC is required for a BIOS-OS handshake for most of the newer
  * ACPI processor features.
  */
-static int
+static acpi_status
 acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 {
 	acpi_status status = AE_OK;
@@ -379,16 +388,43 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
 	return AE_OK;
 }
 
-void __init acpi_early_processor_set_pdc(void)
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+static int __init set_no_mwait(const struct dmi_system_id *id)
+{
+	pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n",
+		  id->ident);
+	boot_option_idle_override = IDLE_NOMWAIT;
+	return 0;
+}
+
+static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
+	{
+	set_no_mwait, "Extensa 5220", {
+	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+	{},
+};
+
+static void __init processor_dmi_check(void)
 {
 	/*
 	 * Check whether the system is DMI table. If yes, OSPM
 	 * should not use mwait for CPU-states.
 	 */
 	dmi_check_system(processor_idle_dmi_table);
+}
+#else
+static inline void processor_dmi_check(void) {}
+#endif
+
+void __init acpi_early_processor_set_pdc(void)
+{
+	processor_dmi_check();
 
 	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
 			    ACPI_UINT32_MAX,
 			    early_init_pdc, NULL, NULL, NULL);
-	acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
+	acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
 }
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index ff90054f04fd..cfc8aba72f86 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -156,17 +156,9 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
  */
 static void acpi_processor_ppc_ost(acpi_handle handle, int status)
 {
-	union acpi_object params[2] = {
-		{.type = ACPI_TYPE_INTEGER,},
-		{.type = ACPI_TYPE_INTEGER,},
-	};
-	struct acpi_object_list arg_list = {2, params};
-
-	if (acpi_has_method(handle, "_OST")) {
-		params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
-		params[1].integer.value =  status;
-		acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-	}
+	if (acpi_has_method(handle, "_OST"))
+		acpi_evaluate_ost(handle, ACPI_PROCESSOR_NOTIFY_PERFORMANCE,
+				  status, NULL);
 }
 
 int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 57b053f424d1..4789c9bedca3 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock);
 static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
+static DEFINE_MUTEX(acpi_hp_context_lock);
 
 struct acpi_device_bus_id{
 	char bus_id[15];
@@ -60,6 +61,27 @@ void acpi_scan_lock_release(void)
 }
 EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
 
+void acpi_lock_hp_context(void)
+{
+	mutex_lock(&acpi_hp_context_lock);
+}
+
+void acpi_unlock_hp_context(void)
+{
+	mutex_unlock(&acpi_hp_context_lock);
+}
+
+void acpi_initialize_hp_context(struct acpi_device *adev,
+				struct acpi_hotplug_context *hp,
+				int (*notify)(struct acpi_device *, u32),
+				void (*uevent)(struct acpi_device *, u32))
+{
+	acpi_lock_hp_context();
+	acpi_set_hp_context(adev, hp, notify, uevent, NULL);
+	acpi_unlock_hp_context();
+}
+EXPORT_SYMBOL_GPL(acpi_initialize_hp_context);
+
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
 	if (!handler || !handler->attach)
@@ -439,90 +461,76 @@ static int acpi_scan_bus_check(struct acpi_device *adev)
 	return 0;
 }
 
-static void acpi_device_hotplug(void *data, u32 src)
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			dev_info(&adev->dev, "Eject disabled\n");
+			return -EPERM;
+		}
+		acpi_evaluate_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST,
+				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
+void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
-
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
-	}
-	if (!error)
-		ost_code = ACPI_OST_SC_SUCCESS;
-
- out:
-	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
-	put_device(&adev->dev);
-	mutex_unlock(&acpi_scan_lock);
-	unlock_device_hotplug();
-}
-
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
-{
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	struct acpi_device *adev;
-	acpi_status status;
-
-	if (acpi_bus_get_device(handle, &adev))
 		goto err_out;
 
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!adev->handler)
-			goto err_out;
-
-		if (!adev->handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
+	if (adev->flags.is_dock_station) {
+		error = dock_notify(adev, src);
+	} else if (adev->flags.hotplug_notify) {
+		error = acpi_generic_hotplug_event(adev, src);
+		if (error == -EPERM) {
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
 			goto err_out;
 		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
-		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
-		return;
-	}
-	get_device(&adev->dev);
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
+	} else {
+		int (*notify)(struct acpi_device *, u32);
 
-	put_device(&adev->dev);
+		acpi_lock_hp_context();
+		notify = adev->hp ? adev->hp->notify : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (notify)
+			error = notify(adev, src);
+		else
+			goto out;
+	}
+	if (!error)
+		ost_code = ACPI_OST_SC_SUCCESS;
 
  err_out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	acpi_evaluate_ost(adev->handle, src, ost_code, NULL);
+
+ out:
+	acpi_bus_put_acpi_device(adev);
+	mutex_unlock(&acpi_scan_lock);
+	unlock_device_hotplug();
 }
 
 static ssize_t real_power_state_show(struct device *dev,
@@ -570,8 +578,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
 	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
 		return -ENODEV;
 
-	acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	get_device(&acpi_device->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
 				      ACPI_OST_EC_OSPM_EJECT);
@@ -579,8 +585,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
 		return count;
 
 	put_device(&acpi_device->dev);
-	acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-				  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
+	acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
+			  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
 	return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
 }
 
@@ -1114,14 +1120,16 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context)
 	mutex_unlock(&acpi_device_del_lock);
 }
 
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device,
+				void (*callback)(void *))
 {
 	acpi_status status;
 
 	if (!device)
 		return -EINVAL;
 
-	status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
+	status = acpi_get_data_full(handle, acpi_scan_drop_device,
+				    (void **)device, callback);
 	if (ACPI_FAILURE(status) || !*device) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
 				  handle));
@@ -1129,8 +1137,32 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
 	}
 	return 0;
 }
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+	return acpi_get_device_data(handle, device, NULL);
+}
 EXPORT_SYMBOL(acpi_bus_get_device);
 
+static void get_acpi_device(void *dev)
+{
+	if (dev)
+		get_device(&((struct acpi_device *)dev)->dev);
+}
+
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+{
+	struct acpi_device *adev = NULL;
+
+	acpi_get_device_data(handle, &adev, get_acpi_device);
+	return adev;
+}
+
+void acpi_bus_put_acpi_device(struct acpi_device *adev)
+{
+	put_device(&adev->dev);
+}
+
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *))
 {
@@ -1641,6 +1673,27 @@ bool acpi_bay_match(acpi_handle handle)
 	return acpi_ata_match(phandle);
 }
 
+bool acpi_device_is_battery(struct acpi_device *adev)
+{
+	struct acpi_hardware_id *hwid;
+
+	list_for_each_entry(hwid, &adev->pnp.ids, list)
+		if (!strcmp("PNP0C0A", hwid->id))
+			return true;
+
+	return false;
+}
+
+static bool is_ejectable_bay(struct acpi_device *adev)
+{
+	acpi_handle handle = adev->handle;
+
+	if (acpi_has_method(handle, "_EJ0") && acpi_device_is_battery(adev))
+		return true;
+
+	return acpi_bay_match(handle);
+}
+
 /*
  * acpi_dock_match - see if an acpi object has a _DCK method
  */
@@ -1706,6 +1759,20 @@ static bool acpi_ibm_smbus_match(acpi_handle handle)
 	return false;
 }
 
+static bool acpi_object_is_system_bus(acpi_handle handle)
+{
+	acpi_handle tmp;
+
+	if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_SB", &tmp)) &&
+	    tmp == handle)
+		return true;
+	if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_TZ", &tmp)) &&
+	    tmp == handle)
+		return true;
+
+	return false;
+}
+
 static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
 				int device_type)
 {
@@ -1757,8 +1824,10 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
 			acpi_add_id(pnp, ACPI_DOCK_HID);
 		else if (acpi_ibm_smbus_match(handle))
 			acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
-		else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
-			acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
+		else if (list_empty(&pnp->ids) &&
+			 acpi_object_is_system_bus(handle)) {
+			/* \_SB, \_TZ, LNXSYBUS */
+			acpi_add_id(pnp, ACPI_BUS_HID);
 			strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
 			strcpy(pnp->device_class, ACPI_BUS_CLASS);
 		}
@@ -1941,33 +2010,23 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
+static void acpi_scan_init_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device_pnp pnp = {};
 	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
 
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
+	if (acpi_dock_match(adev->handle) || is_ejectable_bay(adev)) {
+		acpi_dock_add(adev);
+		return;
+	}
+	list_for_each_entry(hwid, &adev->pnp.ids, list) {
+		struct acpi_scan_handler *handler;
 
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			adev->flags.hotplug_notify = true;
 			break;
 		}
 	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
 }
 
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
@@ -1991,12 +2050,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
 
+	acpi_scan_init_hotplug(device);
+
  out:
 	if (!*return_value)
 		*return_value = device;
@@ -2015,13 +2074,14 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
 
 		handler = acpi_scan_match_handler(hwid->id, &devid);
 		if (handler) {
+			device->handler = handler;
 			ret = handler->attach(device, devid);
-			if (ret > 0) {
-				device->handler = handler;
+			if (ret > 0)
 				break;
-			} else if (ret < 0) {
+
+			device->handler = NULL;
+			if (ret < 0)
 				break;
-			}
 		}
 	}
 	return ret;
@@ -2030,8 +2090,12 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
 static void acpi_bus_attach(struct acpi_device *device)
 {
 	struct acpi_device *child;
+	acpi_handle ejd;
 	int ret;
 
+	if (ACPI_SUCCESS(acpi_bus_get_ejd(device->handle, &ejd)))
+		register_dock_dependent_device(device, ejd);
+
 	acpi_bus_get_status(device);
 	/* Skip devices that are not present. */
 	if (!acpi_device_is_present(device)) {
@@ -2184,7 +2248,6 @@ int __init acpi_scan_init(void)
 	acpi_cmos_rtc_init();
 	acpi_container_init();
 	acpi_memory_hotplug_init();
-	acpi_dock_init();
 
 	mutex_lock(&acpi_scan_lock);
 	/*
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 85e3b612bdc0..0f5f78fa6545 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -422,7 +422,7 @@ out:
 EXPORT_SYMBOL(acpi_get_physical_device_location);
 
 /**
- * acpi_evaluate_hotplug_ost: Evaluate _OST for hotplug operations
+ * acpi_evaluate_ost: Evaluate _OST for hotplug operations
  * @handle: ACPI device handle
  * @source_event: source event code
  * @status_code: status code
@@ -433,17 +433,15 @@ EXPORT_SYMBOL(acpi_get_physical_device_location);
  * When the platform does not support _OST, this function has no effect.
  */
 acpi_status
-acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
-		u32 status_code, struct acpi_buffer *status_buf)
+acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
+		  struct acpi_buffer *status_buf)
 {
-#ifdef ACPI_HOTPLUG_OST
 	union acpi_object params[3] = {
 		{.type = ACPI_TYPE_INTEGER,},
 		{.type = ACPI_TYPE_INTEGER,},
 		{.type = ACPI_TYPE_BUFFER,}
 	};
 	struct acpi_object_list arg_list = {3, params};
-	acpi_status status;
 
 	params[0].integer.value = source_event;
 	params[1].integer.value = status_code;
@@ -455,13 +453,9 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
 		params[2].buffer.length = 0;
 	}
 
-	status = acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-	return status;
-#else
-	return AE_OK;
-#endif
+	return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
 }
-EXPORT_SYMBOL(acpi_evaluate_hotplug_ost);
+EXPORT_SYMBOL(acpi_evaluate_ost);
 
 /**
  * acpi_handle_printk: Print message with ACPI prefix and object path
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 9e6029105607..3cf61a127ee5 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -83,7 +83,7 @@ static struct device_attribute amba_dev_attrs[] = {
 	__ATTR_NULL,
 };
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 /*
  * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
  * enable/disable the bus clock at runtime PM suspend/resume as this
@@ -123,7 +123,7 @@ static const struct dev_pm_ops amba_pm = {
 	.thaw		= pm_generic_thaw,
 	.poweroff	= pm_generic_poweroff,
 	.restore	= pm_generic_restore,
-	SET_RUNTIME_PM_OPS(
+	SET_PM_RUNTIME_PM_OPS(
 		amba_pm_runtime_suspend,
 		amba_pm_runtime_resume,
 		NULL
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 1f44e56cc65d..558a239954e8 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -256,8 +256,6 @@ static int tegra_ahb_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
 	ahb->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(ahb->regs))
 		return PTR_ERR(ahb->regs);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 868429a47be4..b4a926202cca 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -11,13 +11,13 @@ config HAVE_PATA_PLATFORM
 	  to update the PATA_PLATFORM entry.
 
 menuconfig ATA
-	tristate "Serial ATA and Parallel ATA drivers"
+	tristate "Serial ATA and Parallel ATA drivers (libata)"
 	depends on HAS_IOMEM
 	depends on BLOCK
 	depends on !(M32R || M68K || S390) || BROKEN
 	select SCSI
 	---help---
-	  If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
+	  If you want to use an ATA hard disk, ATA tape drive, ATA CD-ROM or
 	  any other ATA device under Linux, say Y and make sure that you know
 	  the name of your ATA host adapter (the card inside your computer
 	  that "speaks" the ATA protocol, also called ATA controller),
@@ -106,6 +106,15 @@ config AHCI_IMX
 
 	  If unsure, say N.
 
+config AHCI_SUNXI
+	tristate "Allwinner sunxi AHCI SATA support"
+	depends on ARCH_SUNXI && SATA_AHCI_PLATFORM
+	help
+	  This option enables support for the Allwinner sunxi SoC's
+	  onboard AHCI SATA.
+
+	  If unsure, say N.
+
 config SATA_FSL
 	tristate "Freescale 3.0Gbps SATA support"
 	depends on FSL_SOC
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 46518c622460..246050b4c198 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
 obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o
 obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o
+obj-$(CONFIG_AHCI_SUNXI)	+= ahci_sunxi.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index fd665d919df2..b51605ac5974 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c81d809c111b..5a0bf8ed649b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -578,6 +577,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 				 unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	bool online;
 	int rc;
 
@@ -588,7 +588,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
 				 deadline, &online, NULL);
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 
 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
 
@@ -603,6 +603,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
 {
 	struct ata_port *ap = link->ap;
 	struct ahci_port_priv *pp = ap->private_data;
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 	struct ata_taskfile tf;
 	bool online;
@@ -618,7 +619,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
 				 deadline, &online, NULL);
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 
 	/* The pseudo configuration device on SIMG4726 attached to
 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
@@ -1165,13 +1166,13 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
 			 struct ahci_host_priv *hpriv)
 {
-	int rc, nvec;
+	int nvec;
 
 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
 		goto intx;
 
-	rc = pci_msi_vec_count(pdev);
-	if (rc < 0)
+	nvec = pci_msi_vec_count(pdev);
+	if (nvec < 0)
 		goto intx;
 
 	/*
@@ -1179,21 +1180,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
 	 * Message mode could be enforced. In this case assume that advantage
 	 * of multipe MSIs is negated and use single MSI mode instead.
 	 */
-	if (rc < n_ports)
+	if (nvec < n_ports)
 		goto single_msi;
 
-	nvec = rc;
-	rc = pci_enable_msi_block(pdev, nvec);
-	if (rc < 0)
-		goto intx;
-	else if (rc > 0)
+	nvec = pci_enable_msi_range(pdev, nvec, nvec);
+	if (nvec == -ENOSPC)
 		goto single_msi;
+	else if (nvec < 0)
+		goto intx;
 
 	return nvec;
 
 single_msi:
-	rc = pci_enable_msi(pdev);
-	if (rc)
+	if (pci_enable_msi(pdev))
 		goto intx;
 	return 1;
 
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 2289efdf8203..51af275b3388 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -37,6 +37,8 @@
 
 #include <linux/clk.h>
 #include <linux/libata.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
 
 /* Enclosure Management Control */
 #define EM_CTRL_MSG_TYPE              0x000f0000
@@ -51,6 +53,7 @@
 
 enum {
 	AHCI_MAX_PORTS		= 32,
+	AHCI_MAX_CLKS		= 3,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_MAX_CMDS		= 32,
@@ -321,8 +324,17 @@ struct ahci_host_priv {
 	u32 			em_loc; /* enclosure management location */
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
-	struct clk		*clk;		/* Only for platforms supporting clk */
+	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
+	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
+	struct regulator	*target_pwr;	/* Optional */
+	struct phy		*phy;		/* If platform uses phy */
 	void			*plat_data;	/* Other platform data */
+	/*
+	 * Optional ahci_start_engine override, if not set this gets set to the
+	 * default ahci_start_engine during ahci_save_initial_config, this can
+	 * be overridden anytime before the host is activated.
+	 */
+	void			(*start_engine)(struct ata_port *ap);
 };
 
 extern int ahci_ignore_sss;
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index dd4d6f74d7bd..3cb5d69581f1 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -42,13 +42,7 @@ enum ahci_imx_type {
 struct imx_ahci_priv {
 	struct platform_device *ahci_pdev;
 	enum ahci_imx_type type;
-
-	/* i.MX53 clock */
-	struct clk *sata_gate_clk;
-	/* Common clock */
-	struct clk *sata_ref_clk;
 	struct clk *ahb_clk;
-
 	struct regmap *gpr;
 	bool no_device;
 	bool first_time;
@@ -58,28 +52,52 @@ static int ahci_imx_hotplug;
 module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
 MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
 
-static int imx_sata_clock_enable(struct device *dev)
+static void ahci_imx_host_stop(struct ata_host *host);
+
+static int imx_sata_enable(struct ahci_host_priv *hpriv)
 {
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 	int ret;
 
-	if (imxpriv->type == AHCI_IMX53) {
-		ret = clk_prepare_enable(imxpriv->sata_gate_clk);
-		if (ret < 0) {
-			dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
-				ret);
+	if (imxpriv->no_device)
+		return 0;
+
+	if (hpriv->target_pwr) {
+		ret = regulator_enable(hpriv->target_pwr);
+		if (ret)
 			return ret;
-		}
 	}
 
-	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-	if (ret < 0) {
-		dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
-			ret);
-		goto clk_err;
-	}
+	ret = ahci_platform_enable_clks(hpriv);
+	if (ret < 0)
+		goto disable_regulator;
 
 	if (imxpriv->type == AHCI_IMX6Q) {
+		/*
+		 * set PHY Paremeters, two steps to configure the GPR13,
+		 * one write for rest of parameters, mask of first write
+		 * is 0x07ffffff, and the other one write for setting
+		 * the mpll_clk_en.
+		 */
+		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+				   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
+				   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
+				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
+				   IMX6Q_GPR13_SATA_SPD_MODE_MASK |
+				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
+				   IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
+				   IMX6Q_GPR13_SATA_TX_BOOST_MASK |
+				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
+				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
+				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
+				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
+				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
+				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
+				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
+				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -89,15 +107,19 @@ static int imx_sata_clock_enable(struct device *dev)
 
 	return 0;
 
-clk_err:
-	if (imxpriv->type == AHCI_IMX53)
-		clk_disable_unprepare(imxpriv->sata_gate_clk);
+disable_regulator:
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
+
 	return ret;
 }
 
-static void imx_sata_clock_disable(struct device *dev)
+static void imx_sata_disable(struct ahci_host_priv *hpriv)
 {
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
+
+	if (imxpriv->no_device)
+		return;
 
 	if (imxpriv->type == AHCI_IMX6Q) {
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
@@ -105,10 +127,10 @@ static void imx_sata_clock_disable(struct device *dev)
 				   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
 	}
 
-	clk_disable_unprepare(imxpriv->sata_ref_clk);
+	ahci_platform_disable_clks(hpriv);
 
-	if (imxpriv->type == AHCI_IMX53)
-		clk_disable_unprepare(imxpriv->sata_gate_clk);
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
 }
 
 static void ahci_imx_error_handler(struct ata_port *ap)
@@ -118,7 +140,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
 	struct ata_host *host = dev_get_drvdata(ap->dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 
 	ahci_error_handler(ap);
 
@@ -136,7 +158,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
 	 */
 	reg_val = readl(mmio + PORT_PHY_CTL);
 	writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
-	imx_sata_clock_disable(ap->dev);
+	imx_sata_disable(hpriv);
 	imxpriv->no_device = true;
 }
 
@@ -144,7 +166,9 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
 		       unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+	struct ata_host *host = dev_get_drvdata(ap->dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 	int ret = -EIO;
 
 	if (imxpriv->type == AHCI_IMX53)
@@ -156,7 +180,8 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
 }
 
 static struct ata_port_operations ahci_imx_ops = {
-	.inherits	= &ahci_platform_ops,
+	.inherits	= &ahci_ops,
+	.host_stop	= ahci_imx_host_stop,
 	.error_handler	= ahci_imx_error_handler,
 	.softreset	= ahci_imx_softreset,
 };
@@ -168,79 +193,6 @@ static const struct ata_port_info ahci_imx_port_info = {
 	.port_ops	= &ahci_imx_ops,
 };
 
-static int imx_sata_init(struct device *dev, void __iomem *mmio)
-{
-	int ret = 0;
-	unsigned int reg_val;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
-
-	ret = imx_sata_clock_enable(dev);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
-	 * and IP vendor specific register HOST_TIMER1MS.
-	 * Configure CAP_SSS (support stagered spin up).
-	 * Implement the port0.
-	 * Get the ahb clock rate, and configure the TIMER1MS register.
-	 */
-	reg_val = readl(mmio + HOST_CAP);
-	if (!(reg_val & HOST_CAP_SSS)) {
-		reg_val |= HOST_CAP_SSS;
-		writel(reg_val, mmio + HOST_CAP);
-	}
-	reg_val = readl(mmio + HOST_PORTS_IMPL);
-	if (!(reg_val & 0x1)) {
-		reg_val |= 0x1;
-		writel(reg_val, mmio + HOST_PORTS_IMPL);
-	}
-
-	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
-	writel(reg_val, mmio + HOST_TIMER1MS);
-
-	return 0;
-}
-
-static void imx_sata_exit(struct device *dev)
-{
-	imx_sata_clock_disable(dev);
-}
-
-static int imx_ahci_suspend(struct device *dev)
-{
-	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-
-	/*
-	 * If no_device is set, The CLKs had been gated off in the
-	 * initialization so don't do it again here.
-	 */
-	if (!imxpriv->no_device)
-		imx_sata_clock_disable(dev);
-
-	return 0;
-}
-
-static int imx_ahci_resume(struct device *dev)
-{
-	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-	int ret = 0;
-
-	if (!imxpriv->no_device)
-		ret = imx_sata_clock_enable(dev);
-
-	return ret;
-}
-
-static struct ahci_platform_data imx_sata_pdata = {
-	.init		= imx_sata_init,
-	.exit		= imx_sata_exit,
-	.ata_port_info	= &ahci_imx_port_info,
-	.suspend	= imx_ahci_suspend,
-	.resume		= imx_ahci_resume,
-
-};
-
 static const struct of_device_id imx_ahci_of_match[] = {
 	{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
 	{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
@@ -251,151 +203,122 @@ MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
 static int imx_ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct resource *mem, *irq, res[2];
 	const struct of_device_id *of_id;
-	enum ahci_imx_type type;
-	const struct ahci_platform_data *pdata = NULL;
+	struct ahci_host_priv *hpriv;
 	struct imx_ahci_priv *imxpriv;
-	struct device *ahci_dev;
-	struct platform_device *ahci_pdev;
+	unsigned int reg_val;
 	int ret;
 
 	of_id = of_match_device(imx_ahci_of_match, dev);
 	if (!of_id)
 		return -EINVAL;
 
-	type = (enum ahci_imx_type)of_id->data;
-	pdata = &imx_sata_pdata;
-
 	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
-	if (!imxpriv) {
-		dev_err(dev, "can't alloc ahci_host_priv\n");
+	if (!imxpriv)
 		return -ENOMEM;
-	}
-
-	ahci_pdev = platform_device_alloc("ahci", -1);
-	if (!ahci_pdev)
-		return -ENODEV;
-
-	ahci_dev = &ahci_pdev->dev;
-	ahci_dev->parent = dev;
 
 	imxpriv->no_device = false;
 	imxpriv->first_time = true;
-	imxpriv->type = type;
-
+	imxpriv->type = (enum ahci_imx_type)of_id->data;
 	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
 	if (IS_ERR(imxpriv->ahb_clk)) {
 		dev_err(dev, "can't get ahb clock.\n");
-		ret = PTR_ERR(imxpriv->ahb_clk);
-		goto err_out;
+		return PTR_ERR(imxpriv->ahb_clk);
 	}
 
-	if (type == AHCI_IMX53) {
-		imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
-		if (IS_ERR(imxpriv->sata_gate_clk)) {
-			dev_err(dev, "can't get sata_gate clock.\n");
-			ret = PTR_ERR(imxpriv->sata_gate_clk);
-			goto err_out;
+	if (imxpriv->type == AHCI_IMX6Q) {
+		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
+							"fsl,imx6q-iomuxc-gpr");
+		if (IS_ERR(imxpriv->gpr)) {
+			dev_err(dev,
+				"failed to find fsl,imx6q-iomux-gpr regmap\n");
+			return PTR_ERR(imxpriv->gpr);
 		}
 	}
 
-	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
-	if (IS_ERR(imxpriv->sata_ref_clk)) {
-		dev_err(dev, "can't get sata_ref clock.\n");
-		ret = PTR_ERR(imxpriv->sata_ref_clk);
-		goto err_out;
-	}
+	hpriv = ahci_platform_get_resources(pdev);
+	if (IS_ERR(hpriv))
+		return PTR_ERR(hpriv);
+
+	hpriv->plat_data = imxpriv;
 
-	imxpriv->ahci_pdev = ahci_pdev;
-	platform_set_drvdata(pdev, imxpriv);
+	ret = imx_sata_enable(hpriv);
+	if (ret)
+		return ret;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!mem || !irq) {
-		dev_err(dev, "no mmio/irq resource\n");
-		ret = -ENOMEM;
-		goto err_out;
+	/*
+	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
+	 * and IP vendor specific register HOST_TIMER1MS.
+	 * Configure CAP_SSS (support stagered spin up).
+	 * Implement the port0.
+	 * Get the ahb clock rate, and configure the TIMER1MS register.
+	 */
+	reg_val = readl(hpriv->mmio + HOST_CAP);
+	if (!(reg_val & HOST_CAP_SSS)) {
+		reg_val |= HOST_CAP_SSS;
+		writel(reg_val, hpriv->mmio + HOST_CAP);
+	}
+	reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL);
+	if (!(reg_val & 0x1)) {
+		reg_val |= 0x1;
+		writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL);
 	}
 
-	res[0] = *mem;
-	res[1] = *irq;
+	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
+	writel(reg_val, hpriv->mmio + HOST_TIMER1MS);
 
-	ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
-	ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
-	ahci_dev->of_node = dev->of_node;
+	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0);
+	if (ret)
+		imx_sata_disable(hpriv);
 
-	if (type == AHCI_IMX6Q) {
-		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
-							"fsl,imx6q-iomuxc-gpr");
-		if (IS_ERR(imxpriv->gpr)) {
-			dev_err(dev,
-				"failed to find fsl,imx6q-iomux-gpr regmap\n");
-			ret = PTR_ERR(imxpriv->gpr);
-			goto err_out;
-		}
+	return ret;
+}
 
-		/*
-		 * Set PHY Paremeters, two steps to configure the GPR13,
-		 * one write for rest of parameters, mask of first write
-		 * is 0x07fffffe, and the other one write for setting
-		 * the mpll_clk_en happens in imx_sata_clock_enable().
-		 */
-		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
-				   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
-				   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
-				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
-				   IMX6Q_GPR13_SATA_SPD_MODE_MASK |
-				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
-				   IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
-				   IMX6Q_GPR13_SATA_TX_BOOST_MASK |
-				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
-				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
-				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
-				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
-				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
-				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
-				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
-				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
-				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
-				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
-				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
-	}
+static void ahci_imx_host_stop(struct ata_host *host)
+{
+	struct ahci_host_priv *hpriv = host->private_data;
 
-	ret = platform_device_add_resources(ahci_pdev, res, 2);
-	if (ret)
-		goto err_out;
+	imx_sata_disable(hpriv);
+}
 
-	ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
-	if (ret)
-		goto err_out;
+static int imx_ahci_suspend(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int ret;
 
-	ret = platform_device_add(ahci_pdev);
-	if (ret) {
-err_out:
-		platform_device_put(ahci_pdev);
+	ret = ahci_platform_suspend_host(dev);
+	if (ret)
 		return ret;
-	}
+
+	imx_sata_disable(hpriv);
 
 	return 0;
 }
 
-static int imx_ahci_remove(struct platform_device *pdev)
+static int imx_ahci_resume(struct device *dev)
 {
-	struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
-	struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int ret;
 
-	platform_device_unregister(ahci_pdev);
-	return 0;
+	ret = imx_sata_enable(hpriv);
+	if (ret)
+		return ret;
+
+	return ahci_platform_resume_host(dev);
 }
 
+static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
+
 static struct platform_driver imx_ahci_driver = {
 	.probe = imx_ahci_probe,
-	.remove = imx_ahci_remove,
+	.remove = ata_platform_remove_one,
 	.driver = {
 		.name = "ahci-imx",
 		.owner = THIS_MODULE,
 		.of_match_table = imx_ahci_of_match,
+		.pm = &ahci_imx_pm_ops,
 	},
 };
 module_platform_driver(imx_ahci_driver);
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4b231baceb09..db24d2a08051 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -17,148 +17,312 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/libata.h>
 #include <linux/ahci_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
 #include "ahci.h"
 
 static void ahci_host_stop(struct ata_host *host);
 
-enum ahci_type {
-	AHCI,		/* standard platform ahci */
-	IMX53_AHCI,	/* ahci on i.mx53 */
-	STRICT_AHCI,	/* delayed DMA engine start */
-};
-
-static struct platform_device_id ahci_devtype[] = {
-	{
-		.name = "ahci",
-		.driver_data = AHCI,
-	}, {
-		.name = "imx53-ahci",
-		.driver_data = IMX53_AHCI,
-	}, {
-		.name = "strict-ahci",
-		.driver_data = STRICT_AHCI,
-	}, {
-		/* sentinel */
-	}
-};
-MODULE_DEVICE_TABLE(platform, ahci_devtype);
-
 struct ata_port_operations ahci_platform_ops = {
 	.inherits	= &ahci_ops,
 	.host_stop	= ahci_host_stop,
 };
 EXPORT_SYMBOL_GPL(ahci_platform_ops);
 
-static struct ata_port_operations ahci_platform_retry_srst_ops = {
-	.inherits	= &ahci_pmp_retry_srst_ops,
-	.host_stop	= ahci_host_stop,
-};
-
-static const struct ata_port_info ahci_port_info[] = {
-	/* by features */
-	[AHCI] = {
-		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= ATA_PIO4,
-		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_platform_ops,
-	},
-	[IMX53_AHCI] = {
-		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= ATA_PIO4,
-		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_platform_retry_srst_ops,
-	},
-	[STRICT_AHCI] = {
-		AHCI_HFLAGS	(AHCI_HFLAG_DELAY_ENGINE),
-		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= ATA_PIO4,
-		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_platform_ops,
-	},
+static const struct ata_port_info ahci_port_info = {
+	.flags		= AHCI_FLAG_COMMON,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_platform_ops,
 };
 
 static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT("ahci_platform"),
 };
 
-static int ahci_probe(struct platform_device *pdev)
+/**
+ * ahci_platform_enable_clks - Enable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the clks found in hpriv->clks, starting at
+ * index 0. If any clk fails to enable it disables all the clks already
+ * enabled in reverse order, and then returns an error.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
+{
+	int c, rc;
+
+	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
+		rc = clk_prepare_enable(hpriv->clks[c]);
+		if (rc)
+			goto disable_unprepare_clk;
+	}
+	return 0;
+
+disable_unprepare_clk:
+	while (--c >= 0)
+		clk_disable_unprepare(hpriv->clks[c]);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
+
+/**
+ * ahci_platform_disable_clks - Disable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all the clks found in hpriv->clks, in reverse
+ * order of ahci_platform_enable_clks (starting at the end of the array).
+ */
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
+{
+	int c;
+
+	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
+		if (hpriv->clks[c])
+			clk_disable_unprepare(hpriv->clks[c]);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
+
+/**
+ * ahci_platform_enable_resources - Enable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all ahci_platform managed resources in the
+ * following order:
+ * 1) Regulator
+ * 2) Clocks (through ahci_platform_enable_clks)
+ * 3) Phy
+ *
+ * If resource enabling fails at any point the previous enabled resources
+ * are disabled in reverse order.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
 {
-	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
-	const struct platform_device_id *id = platform_get_device_id(pdev);
-	struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
-	const struct ata_port_info *ppi[] = { &pi, NULL };
-	struct ahci_host_priv *hpriv;
-	struct ata_host *host;
-	struct resource *mem;
-	int irq;
-	int n_ports;
-	int i;
 	int rc;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(dev, "no mmio space\n");
-		return -EINVAL;
+	if (hpriv->target_pwr) {
+		rc = regulator_enable(hpriv->target_pwr);
+		if (rc)
+			return rc;
 	}
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
-		dev_err(dev, "no irq\n");
-		return -EINVAL;
+	rc = ahci_platform_enable_clks(hpriv);
+	if (rc)
+		goto disable_regulator;
+
+	if (hpriv->phy) {
+		rc = phy_init(hpriv->phy);
+		if (rc)
+			goto disable_clks;
+
+		rc = phy_power_on(hpriv->phy);
+		if (rc) {
+			phy_exit(hpriv->phy);
+			goto disable_clks;
+		}
 	}
 
-	if (pdata && pdata->ata_port_info)
-		pi = *pdata->ata_port_info;
+	return 0;
 
-	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv) {
-		dev_err(dev, "can't alloc ahci_host_priv\n");
-		return -ENOMEM;
+disable_clks:
+	ahci_platform_disable_clks(hpriv);
+
+disable_regulator:
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
+
+/**
+ * ahci_platform_disable_resources - Disable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all ahci_platform managed resources in the
+ * following order:
+ * 1) Phy
+ * 2) Clocks (through ahci_platform_disable_clks)
+ * 3) Regulator
+ */
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
+{
+	if (hpriv->phy) {
+		phy_power_off(hpriv->phy);
+		phy_exit(hpriv->phy);
 	}
 
-	hpriv->flags |= (unsigned long)pi.private_data;
+	ahci_platform_disable_clks(hpriv);
+
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
+
+static void ahci_platform_put_resources(struct device *dev, void *res)
+{
+	struct ahci_host_priv *hpriv = res;
+	int c;
+
+	if (hpriv->got_runtime_pm) {
+		pm_runtime_put_sync(dev);
+		pm_runtime_disable(dev);
+	}
+
+	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+		clk_put(hpriv->clks[c]);
+}
+
+/**
+ * ahci_platform_get_resources - Get platform resources
+ * @pdev: platform device to get resources for
+ *
+ * This function allocates an ahci_host_priv struct, and gets the following
+ * resources, storing a reference to them inside the returned struct:
+ *
+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
+ * 2) regulator for controlling the targets power (optional)
+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
+ *    or for non devicetree enabled platforms a single clock
+ *	4) phy (optional)
+ *
+ * RETURNS:
+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
+ */
+struct ahci_host_priv *ahci_platform_get_resources(
+	struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ahci_host_priv *hpriv;
+	struct clk *clk;
+	int i, rc = -ENOMEM;
+
+	if (!devres_open_group(dev, NULL, GFP_KERNEL))
+		return ERR_PTR(-ENOMEM);
+
+	hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
+			     GFP_KERNEL);
+	if (!hpriv)
+		goto err_out;
+
+	devres_add(dev, hpriv);
 
-	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
+	hpriv->mmio = devm_ioremap_resource(dev,
+			      platform_get_resource(pdev, IORESOURCE_MEM, 0));
 	if (!hpriv->mmio) {
-		dev_err(dev, "can't map %pR\n", mem);
-		return -ENOMEM;
+		dev_err(dev, "no mmio space\n");
+		goto err_out;
 	}
 
-	hpriv->clk = clk_get(dev, NULL);
-	if (IS_ERR(hpriv->clk)) {
-		dev_err(dev, "can't get clock\n");
-	} else {
-		rc = clk_prepare_enable(hpriv->clk);
-		if (rc) {
-			dev_err(dev, "clock prepare enable failed");
-			goto free_clk;
+	hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
+	if (IS_ERR(hpriv->target_pwr)) {
+		rc = PTR_ERR(hpriv->target_pwr);
+		if (rc == -EPROBE_DEFER)
+			goto err_out;
+		hpriv->target_pwr = NULL;
+	}
+
+	for (i = 0; i < AHCI_MAX_CLKS; i++) {
+		/*
+		 * For now we must use clk_get(dev, NULL) for the first clock,
+		 * because some platforms (da850, spear13xx) are not yet
+		 * converted to use devicetree for clocks.  For new platforms
+		 * this is equivalent to of_clk_get(dev->of_node, 0).
+		 */
+		if (i == 0)
+			clk = clk_get(dev, NULL);
+		else
+			clk = of_clk_get(dev->of_node, i);
+
+		if (IS_ERR(clk)) {
+			rc = PTR_ERR(clk);
+			if (rc == -EPROBE_DEFER)
+				goto err_out;
+			break;
 		}
+		hpriv->clks[i] = clk;
 	}
 
-	/*
-	 * Some platforms might need to prepare for mmio region access,
-	 * which could be done in the following init call. So, the mmio
-	 * region shouldn't be accessed before init (if provided) has
-	 * returned successfully.
-	 */
-	if (pdata && pdata->init) {
-		rc = pdata->init(dev, hpriv->mmio);
-		if (rc)
-			goto disable_unprepare_clk;
+	hpriv->phy = devm_phy_get(dev, "sata-phy");
+	if (IS_ERR(hpriv->phy)) {
+		rc = PTR_ERR(hpriv->phy);
+		switch (rc) {
+		case -ENODEV:
+		case -ENOSYS:
+			/* continue normally */
+			hpriv->phy = NULL;
+			break;
+
+		case -EPROBE_DEFER:
+			goto err_out;
+
+		default:
+			dev_err(dev, "couldn't get sata-phy\n");
+			goto err_out;
+		}
 	}
 
-	ahci_save_initial_config(dev, hpriv,
-		pdata ? pdata->force_port_map : 0,
-		pdata ? pdata->mask_port_map  : 0);
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+	hpriv->got_runtime_pm = true;
+
+	devres_remove_group(dev, NULL);
+	return hpriv;
+
+err_out:
+	devres_release_group(dev, NULL);
+	return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
+
+/**
+ * ahci_platform_init_host - Bring up an ahci-platform host
+ * @pdev: platform device pointer for the host
+ * @hpriv: ahci-host private data for the host
+ * @pi_template: template for the ata_port_info to use
+ * @force_port_map: param passed to ahci_save_initial_config
+ * @mask_port_map: param passed to ahci_save_initial_config
+ *
+ * This function does all the usual steps needed to bring up an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be initialized / enabled before calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_init_host(struct platform_device *pdev,
+			    struct ahci_host_priv *hpriv,
+			    const struct ata_port_info *pi_template,
+			    unsigned int force_port_map,
+			    unsigned int mask_port_map)
+{
+	struct device *dev = &pdev->dev;
+	struct ata_port_info pi = *pi_template;
+	const struct ata_port_info *ppi[] = { &pi, NULL };
+	struct ata_host *host;
+	int i, irq, n_ports, rc;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(dev, "no irq\n");
+		return -EINVAL;
+	}
 
 	/* prepare host */
+	hpriv->flags |= (unsigned long)pi.private_data;
+
+	ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+
 	if (hpriv->cap & HOST_CAP_NCQ)
 		pi.flags |= ATA_FLAG_NCQ;
 
@@ -175,10 +339,8 @@ static int ahci_probe(struct platform_device *pdev)
 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
 
 	host = ata_host_alloc_pinfo(dev, ppi, n_ports);
-	if (!host) {
-		rc = -ENOMEM;
-		goto pdata_exit;
-	}
+	if (!host)
+		return -ENOMEM;
 
 	host->private_data = hpriv;
 
@@ -193,7 +355,8 @@ static int ahci_probe(struct platform_device *pdev)
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
-		ata_port_desc(ap, "mmio %pR", mem);
+		ata_port_desc(ap, "mmio %pR",
+			      platform_get_resource(pdev, IORESOURCE_MEM, 0));
 		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
 
 		/* set enclosure management message type */
@@ -207,13 +370,44 @@ static int ahci_probe(struct platform_device *pdev)
 
 	rc = ahci_reset_controller(host);
 	if (rc)
-		goto pdata_exit;
+		return rc;
 
 	ahci_init_controller(host);
 	ahci_print_info(host, "platform");
 
-	rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-			       &ahci_platform_sht);
+	return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
+				 &ahci_platform_sht);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_init_host);
+
+static int ahci_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	struct ahci_host_priv *hpriv;
+	int rc;
+
+	hpriv = ahci_platform_get_resources(pdev);
+	if (IS_ERR(hpriv))
+		return PTR_ERR(hpriv);
+
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
+
+	/*
+	 * Some platforms might need to prepare for mmio region access,
+	 * which could be done in the following init call. So, the mmio
+	 * region shouldn't be accessed before init (if provided) has
+	 * returned successfully.
+	 */
+	if (pdata && pdata->init) {
+		rc = pdata->init(dev, hpriv->mmio);
+		if (rc)
+			goto disable_resources;
+	}
+
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0);
 	if (rc)
 		goto pdata_exit;
 
@@ -221,12 +415,8 @@ static int ahci_probe(struct platform_device *pdev)
 pdata_exit:
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
-disable_unprepare_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
-free_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_put(hpriv->clk);
+disable_resources:
+	ahci_platform_disable_resources(hpriv);
 	return rc;
 }
 
@@ -239,21 +429,27 @@ static void ahci_host_stop(struct ata_host *host)
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
 
-	if (!IS_ERR(hpriv->clk)) {
-		clk_disable_unprepare(hpriv->clk);
-		clk_put(hpriv->clk);
-	}
+	ahci_platform_disable_resources(hpriv);
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int ahci_suspend(struct device *dev)
+/**
+ * ahci_platform_suspend_host - Suspend an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to suspend an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be disabled after calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend_host(struct device *dev)
 {
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
 	u32 ctl;
-	int rc;
 
 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
 		dev_err(dev, "firmware update required for suspend/resume\n");
@@ -270,66 +466,124 @@ static int ahci_suspend(struct device *dev)
 	writel(ctl, mmio + HOST_CTL);
 	readl(mmio + HOST_CTL); /* flush */
 
-	rc = ata_host_suspend(host, PMSG_SUSPEND);
+	return ata_host_suspend(host, PMSG_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
+
+/**
+ * ahci_platform_resume_host - Resume an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to resume an ahci-platform
+ * host, note any necessary resources (ie clks, phy, etc.)  must be
+ * initialized / enabled before calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume_host(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	int rc;
+
+	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+		rc = ahci_reset_controller(host);
+		if (rc)
+			return rc;
+
+		ahci_init_controller(host);
+	}
+
+	ata_host_resume(host);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
+
+/**
+ * ahci_platform_suspend - Suspend an ahci-platform device
+ * @dev: the platform device to suspend
+ *
+ * This function suspends the host associated with the device, followed by
+ * disabling all the resources of the device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend(struct device *dev)
+{
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ahci_platform_suspend_host(dev);
 	if (rc)
 		return rc;
 
 	if (pdata && pdata->suspend)
 		return pdata->suspend(dev);
 
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
+	ahci_platform_disable_resources(hpriv);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ahci_platform_suspend);
 
-static int ahci_resume(struct device *dev)
+/**
+ * ahci_platform_resume - Resume an ahci-platform device
+ * @dev: the platform device to resume
+ *
+ * This function enables all the resources of the device followed by
+ * resuming the host associated with the device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume(struct device *dev)
 {
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	int rc;
 
-	if (!IS_ERR(hpriv->clk)) {
-		rc = clk_prepare_enable(hpriv->clk);
-		if (rc) {
-			dev_err(dev, "clock prepare enable failed");
-			return rc;
-		}
-	}
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
 
 	if (pdata && pdata->resume) {
 		rc = pdata->resume(dev);
 		if (rc)
-			goto disable_unprepare_clk;
+			goto disable_resources;
 	}
 
-	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
-		rc = ahci_reset_controller(host);
-		if (rc)
-			goto disable_unprepare_clk;
-
-		ahci_init_controller(host);
-	}
+	rc = ahci_platform_resume_host(dev);
+	if (rc)
+		goto disable_resources;
 
-	ata_host_resume(host);
+	/* We resumed so update PM runtime state */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
 
 	return 0;
 
-disable_unprepare_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
+disable_resources:
+	ahci_platform_disable_resources(hpriv);
 
 	return rc;
 }
+EXPORT_SYMBOL_GPL(ahci_platform_resume);
 #endif
 
-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+			 ahci_platform_resume);
 
 static const struct of_device_id ahci_of_match[] = {
 	{ .compatible = "snps,spear-ahci", },
 	{ .compatible = "snps,exynos5440-ahci", },
 	{ .compatible = "ibm,476gtr-ahci", },
+	{ .compatible = "snps,dwc-ahci", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
@@ -343,7 +597,6 @@ static struct platform_driver ahci_driver = {
 		.of_match_table = ahci_of_match,
 		.pm = &ahci_pm_ops,
 	},
-	.id_table	= ahci_devtype,
 };
 module_platform_driver(ahci_driver);
 
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
new file mode 100644
index 000000000000..d1bf3f786b02
--- /dev/null
+++ b/drivers/ata/ahci_sunxi.c
@@ -0,0 +1,249 @@
+/*
+ * Allwinner sunxi AHCI SATA platform driver
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
+ * Daniel Wang <danielwang@allwinnertech.com>
+ *
+ * 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/ahci_platform.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define AHCI_BISTAFR 0x00a0
+#define AHCI_BISTCR 0x00a4
+#define AHCI_BISTFCTR 0x00a8
+#define AHCI_BISTSR 0x00ac
+#define AHCI_BISTDECR 0x00b0
+#define AHCI_DIAGNR0 0x00b4
+#define AHCI_DIAGNR1 0x00b8
+#define AHCI_OOBR 0x00bc
+#define AHCI_PHYCS0R 0x00c0
+#define AHCI_PHYCS1R 0x00c4
+#define AHCI_PHYCS2R 0x00c8
+#define AHCI_TIMER1MS 0x00e0
+#define AHCI_GPARAM1R 0x00e8
+#define AHCI_GPARAM2R 0x00ec
+#define AHCI_PPARAMR 0x00f0
+#define AHCI_TESTR 0x00f4
+#define AHCI_VERSIONR 0x00f8
+#define AHCI_IDR 0x00fc
+#define AHCI_RWCR 0x00fc
+#define AHCI_P0DMACR 0x0170
+#define AHCI_P0PHYCR 0x0178
+#define AHCI_P0PHYSR 0x017c
+
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val &= ~(clr_val);
+	writel(reg_val, reg);
+}
+
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val |= set_val;
+	writel(reg_val, reg);
+}
+
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val &= ~(clr_val);
+	reg_val |= set_val;
+	writel(reg_val, reg);
+}
+
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
+{
+	return (readl(reg) >> shift) & mask;
+}
+
+static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+{
+	u32 reg_val;
+	int timeout;
+
+	/* This magic is from the original code */
+	writel(0, reg_base + AHCI_RWCR);
+	msleep(5);
+
+	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+			 (0x7 << 24),
+			 (0x5 << 24) | BIT(23) | BIT(18));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
+			 (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+			 (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+	sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+			 (0x7 << 20), (0x3 << 20));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+			 (0x1f << 5), (0x19 << 5));
+	msleep(5);
+
+	sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+	timeout = 250; /* Power up takes aprox 50 us */
+	do {
+		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+		if (reg_val == 0x02)
+			break;
+
+		if (--timeout == 0) {
+			dev_err(dev, "PHY power up failed.\n");
+			return -EIO;
+		}
+		udelay(1);
+	} while (1);
+
+	sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+	timeout = 100; /* Calibration takes aprox 10 us */
+	do {
+		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+		if (reg_val == 0x00)
+			break;
+
+		if (--timeout == 0) {
+			dev_err(dev, "PHY calibration failed.\n");
+			return -EIO;
+		}
+		udelay(1);
+	} while (1);
+
+	msleep(15);
+
+	writel(0x7, reg_base + AHCI_RWCR);
+
+	return 0;
+}
+
+static void ahci_sunxi_start_engine(struct ata_port *ap)
+{
+	void __iomem *port_mmio = ahci_port_base(ap);
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+
+	/* Setup DMA before DMA start */
+	sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
+
+	/* Start DMA */
+	sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
+}
+
+static const struct ata_port_info ahci_sunxi_port_info = {
+	AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+			  AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_platform_ops,
+};
+
+static int ahci_sunxi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ahci_host_priv *hpriv;
+	int rc;
+
+	hpriv = ahci_platform_get_resources(pdev);
+	if (IS_ERR(hpriv))
+		return PTR_ERR(hpriv);
+
+	hpriv->start_engine = ahci_sunxi_start_engine;
+
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
+
+	rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+	if (rc)
+		goto disable_resources;
+
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0);
+	if (rc)
+		goto disable_resources;
+
+	return 0;
+
+disable_resources:
+	ahci_platform_disable_resources(hpriv);
+	return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+int ahci_sunxi_resume(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
+
+	rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+	if (rc)
+		goto disable_resources;
+
+	rc = ahci_platform_resume_host(dev);
+	if (rc)
+		goto disable_resources;
+
+	return 0;
+
+disable_resources:
+	ahci_platform_disable_resources(hpriv);
+	return rc;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
+			 ahci_sunxi_resume);
+
+static const struct of_device_id ahci_sunxi_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-ahci", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
+
+static struct platform_driver ahci_sunxi_driver = {
+	.probe = ahci_sunxi_probe,
+	.remove = ata_platform_remove_one,
+	.driver = {
+		.name = "ahci-sunxi",
+		.owner = THIS_MODULE,
+		.of_match_table = ahci_sunxi_of_match,
+		.pm = &ahci_sunxi_pm_ops,
+	},
+};
+module_platform_driver(ahci_sunxi_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 7d196656adb5..9498a7d3846f 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 36605abe5a67..7985ae782679 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -394,6 +393,9 @@ static ssize_t ahci_show_em_supported(struct device *dev,
  *
  *	If inconsistent, config values are fixed up by this function.
  *
+ *	If it is not set already this function sets hpriv->start_engine to
+ *	ahci_start_engine.
+ *
  *	LOCKING:
  *	None.
  */
@@ -500,6 +502,9 @@ void ahci_save_initial_config(struct device *dev,
 	hpriv->cap = cap;
 	hpriv->cap2 = cap2;
 	hpriv->port_map = port_map;
+
+	if (!hpriv->start_engine)
+		hpriv->start_engine = ahci_start_engine;
 }
 EXPORT_SYMBOL_GPL(ahci_save_initial_config);
 
@@ -766,7 +771,7 @@ static void ahci_start_port(struct ata_port *ap)
 
 	/* enable DMA */
 	if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
-		ahci_start_engine(ap);
+		hpriv->start_engine(ap);
 
 	/* turn on LEDs */
 	if (ap->flags & ATA_FLAG_EM) {
@@ -1032,12 +1037,13 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
 static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
 				size_t size)
 {
-	int state;
+	unsigned int state;
 	int pmp;
 	struct ahci_port_priv *pp = ap->private_data;
 	struct ahci_em_priv *emp;
 
-	state = simple_strtoul(buf, NULL, 0);
+	if (kstrtouint(buf, 0, &state) < 0)
+		return -EINVAL;
 
 	/* get the slot number from the message */
 	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap)
 
 	/* restart engine */
  out_restart:
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_kick_engine);
@@ -1387,8 +1393,8 @@ static int ahci_bad_pmp_check_ready(struct ata_link *link)
 	return ata_check_ready(status);
 }
 
-int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
-				unsigned long deadline)
+static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+				    unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
 	void __iomem *port_mmio = ahci_port_base(ap);
@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
 	struct ata_port *ap = link->ap;
 	struct ahci_port_priv *pp = ap->private_data;
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 	struct ata_taskfile tf;
 	bool online;
@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 	rc = sata_link_hardreset(link, timing, deadline, &online,
 				 ahci_check_ready);
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 
 	if (online)
 		*class = ahci_dev_classify(ap);
@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap)
 
 void ahci_error_handler(struct ata_port *ap)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+
 	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
 		/* restart engine */
 		ahci_stop_engine(ap);
-		ahci_start_engine(ap);
+		hpriv->start_engine(ap);
 	}
 
 	sata_pmp_error_handler(ap);
@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 
 static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	void __iomem *port_mmio = ahci_port_base(ap);
 	struct ata_device *dev = ap->link.device;
 	u32 devslp, dm, dito, mdat, deto;
@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
 		   PORT_DEVSLP_ADSE);
 	writel(devslp, port_mmio + PORT_DEVSLP);
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 
 	/* enable device sleep feature for the drive */
 	err_mask = ata_dev_set_feature(dev,
@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
 
 static void ahci_enable_fbs(struct ata_port *ap)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp = ap->private_data;
 	void __iomem *port_mmio = ahci_port_base(ap);
 	u32 fbs;
@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap)
 	} else
 		dev_err(ap->host->dev, "Failed to enable FBS\n");
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 }
 
 static void ahci_disable_fbs(struct ata_port *ap)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp = ap->private_data;
 	void __iomem *port_mmio = ahci_port_base(ap);
 	u32 fbs;
@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
 		pp->fbs_enabled = false;
 	}
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 }
 
 static void ahci_pmp_attach(struct ata_port *ap)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9e69a5308693..acb95dffdb6a 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -38,6 +38,16 @@ static void ata_acpi_clear_gtf(struct ata_device *dev)
 	dev->gtf_cache = NULL;
 }
 
+struct ata_acpi_hotplug_context {
+	struct acpi_hotplug_context hp;
+	union {
+		struct ata_port *ap;
+		struct ata_device *dev;
+	} data;
+};
+
+#define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data)
+
 /**
  * ata_dev_acpi_handle - provide the acpi_handle for an ata_device
  * @dev: the acpi_handle returned will correspond to this device
@@ -121,18 +131,17 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
 		ata_port_wait_eh(ap);
 }
 
-static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
+static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event)
 {
-	struct ata_device *dev = data;
-
+	struct ata_device *dev = ata_hotplug_data(adev->hp).dev;
 	ata_acpi_handle_hotplug(dev->link->ap, dev, event);
+	return 0;
 }
 
-static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
+static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event)
 {
-	struct ata_port *ap = data;
-
-	ata_acpi_handle_hotplug(ap, NULL, event);
+	ata_acpi_handle_hotplug(ata_hotplug_data(adev->hp).ap, NULL, event);
+	return 0;
 }
 
 static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
@@ -154,31 +163,23 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
 	}
 }
 
-static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event)
 {
-	ata_acpi_uevent(data, NULL, event);
+	ata_acpi_uevent(ata_hotplug_data(adev->hp).ap, NULL, event);
 }
 
-static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event)
 {
-	struct ata_device *dev = data;
+	struct ata_device *dev = ata_hotplug_data(adev->hp).dev;
 	ata_acpi_uevent(dev->link->ap, dev, event);
 }
 
-static const struct acpi_dock_ops ata_acpi_dev_dock_ops = {
-	.handler = ata_acpi_dev_notify_dock,
-	.uevent = ata_acpi_dev_uevent,
-};
-
-static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
-	.handler = ata_acpi_ap_notify_dock,
-	.uevent = ata_acpi_ap_uevent,
-};
-
 /* bind acpi handle to pata port */
 void ata_acpi_bind_port(struct ata_port *ap)
 {
 	struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev);
+	struct acpi_device *adev;
+	struct ata_acpi_hotplug_context *context;
 
 	if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion)
 		return;
@@ -188,9 +189,17 @@ void ata_acpi_bind_port(struct ata_port *ap)
 	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
 		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
 
-	/* we might be on a docking station */
-	register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev),
-				     &ata_acpi_ap_dock_ops, ap, NULL, NULL);
+	adev = ACPI_COMPANION(&ap->tdev);
+	if (!adev || adev->hp)
+		return;
+
+	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
+		return;
+
+	context->data.ap = ap;
+	acpi_initialize_hp_context(adev, &context->hp, ata_acpi_ap_notify_dock,
+				   ata_acpi_ap_uevent);
 }
 
 void ata_acpi_bind_dev(struct ata_device *dev)
@@ -198,7 +207,8 @@ void ata_acpi_bind_dev(struct ata_device *dev)
 	struct ata_port *ap = dev->link->ap;
 	struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev);
 	struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev);
-	struct acpi_device *parent;
+	struct acpi_device *parent, *adev;
+	struct ata_acpi_hotplug_context *context;
 	u64 adr;
 
 	/*
@@ -221,9 +231,17 @@ void ata_acpi_bind_dev(struct ata_device *dev)
 	}
 
 	acpi_preset_companion(&dev->tdev, parent, adr);
+	adev = ACPI_COMPANION(&dev->tdev);
+	if (!adev || adev->hp)
+		return;
+
+	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
+		return;
 
-	register_hotplug_dock_device(ata_dev_acpi_handle(dev),
-				     &ata_acpi_dev_dock_ops, dev, NULL, NULL);
+	context->data.dev = dev;
+	acpi_initialize_hp_context(adev, &context->hp, ata_acpi_dev_notify_dock,
+				   ata_acpi_dev_uevent);
 }
 
 /**
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1a3dbd1b196e..8e09062326b9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1524,7 +1524,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
  *	@dev: Device to which the command is sent
  *	@tf: Taskfile registers for the command and the result
  *	@cdb: CDB for packet command
- *	@dma_dir: Data tranfer direction of the command
+ *	@dma_dir: Data transfer direction of the command
  *	@sgl: sg list for the data buffer of the command
  *	@n_elem: Number of sg entries
  *	@timeout: Timeout in msecs (0 for default)
@@ -1712,7 +1712,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
  *	@dev: Device to which the command is sent
  *	@tf: Taskfile registers for the command and the result
  *	@cdb: CDB for packet command
- *	@dma_dir: Data tranfer direction of the command
+ *	@dma_dir: Data transfer direction of the command
  *	@buf: Data buffer of the command
  *	@buflen: Length of data buffer
  *	@timeout: Timeout in msecs (0 for default)
@@ -4225,6 +4225,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 	/* devices that don't properly handle queued TRIM commands */
 	{ "Micron_M500*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
 	{ "Crucial_CT???M500SSD1",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Crucial_CT???M500SSD3",	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_acpi.c b/drivers/ata/pata_acpi.c
index 62c9ac80c6e9..5108b8744dce 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index d23e2b3ca0b6..1206fa6b62ca 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 1581dee2967a..3aa4e655e3c6 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index d63ee8f41a4f..e9c87274a781 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -18,7 +18,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/gfp.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 24e51056ac26..30fa4ca4cef6 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c
index 2ca5026f2c15..7e73a0f1e323 100644
--- a/drivers/ata/pata_atp867x.c
+++ b/drivers/ata/pata_atp867x.c
@@ -29,7 +29,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 8fb69e5ca1b7..57f1be64dbf2 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 1275a8d4dedc..6bca3505b9e9 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index f10baabbf5db..bcde4b786807 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -34,7 +34,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index f07f2296acdc..8afe854a5a50 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 997e16a3a63f..2c0986fa4bb2 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index 0448860a2077..32ddcae5a360 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/libata.h>
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 810bc9964dde..3435bd6a5cc9 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 3c12fd7acd41..f440892225f4 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 980b88e109fc..cad9d45749c4 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -34,7 +34,6 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 35b521348d31..8e76f79689d3 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index a9d74eff5fc4..3ba843f5cdc0 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 4be0398c153d..b93c0f0729e7 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 85cf2861e0b7..255c5aaff3a8 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
index b0b18ec5465f..fa8e69c86af7 100644
--- a/drivers/ata/pata_imx.c
+++ b/drivers/ata/pata_imx.c
@@ -15,7 +15,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
@@ -100,13 +99,9 @@ static int pata_imx_probe(struct platform_device *pdev)
 	struct resource *io_res;
 	int ret;
 
-	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (io_res == NULL)
-		return -EINVAL;
-
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
-		return -EINVAL;
+	if (irq < 0)
+		return irq;
 
 	priv = devm_kzalloc(&pdev->dev,
 				sizeof(struct pata_imx_priv), GFP_KERNEL);
@@ -136,10 +131,9 @@ static int pata_imx_probe(struct platform_device *pdev)
 	ap->pio_mask = ATA_PIO0;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
-	priv->host_regs = devm_ioremap(&pdev->dev, io_res->start,
-		resource_size(io_res));
+	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->host_regs = devm_ioremap_resource(&pdev->dev, io_res);
 	if (!priv->host_regs) {
-		dev_err(&pdev->dev, "failed to map IO/CTL base\n");
 		ret = -EBUSY;
 		goto err;
 	}
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 2a8dd9527ecc..81369d187a5c 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 581e04d80367..dc3d7877f29d 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -72,7 +72,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 76e739b031b6..b1cfa0258fd3 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index a4f5e781c8c2..6bad3df3a13c 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 1f5f28bb0bb8..f39a5379e816 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index ad1a0febd620..e3b97093ef9a 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 9513e071040d..56201a69af12 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 0c424dae56e7..6154c3ee11a5 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index 16dc3a63a23d..d44df7ccfe43 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index d77b2e1054ef..319b64491b7b 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 4ea70cd22aee..fb042e0519d0 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 78ede3fd1875..bb71ea214b99 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 40254f4df584..bcc4b968c049 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 9d874c85d64d..1151f23177bb 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index c34fc50070a6..defa050e1784 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_piccolo.c b/drivers/ata/pata_piccolo.c
index 2beb6b5045f8..0b46be117051 100644
--- a/drivers/ata/pata_piccolo.c
+++ b/drivers/ata/pata_piccolo.c
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 02794885de10..a5579b55e332 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -13,7 +13,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index a6f05acad61e..73259bfda1e3 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -20,7 +20,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/ata.h>
 #include <linux/libata.h>
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index f582ba180a7d..be3f10240dca 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 79a970f05a2e..521b2137ea3e 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -24,7 +24,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 040b093617a4..caedc90855b2 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index ce2f828c17b3..96a232fffae6 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index f35f15f4d83e..f1f5b5ae3382 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index d3830c45a369..5a1cde0ea360 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 96c6a79ef606..e27f31fe1b67 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -34,7 +34,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index c4b0b073ba8e..73fe362d9716 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 1e8363640bf5..78d913aa93c8 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 6816911ac422..900f0e4a1faf 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index 94473da68c02..7bc78e264f9e 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index c3ab9a6c3965..f6c9632bdff6 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -55,7 +55,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 8ea6e6afd041..f10631beffa8 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 523524b68022..73510d0d1406 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -29,7 +29,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 870b11eadc6d..d4df0bf9a55a 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -403,6 +402,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
 	static const unsigned long timing[] = { 5, 100, 500};
 	struct ata_port *ap = link->ap;
 	struct ahci_port_priv *pp = ap->private_data;
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 	struct ata_taskfile tf;
 	bool online;
@@ -431,7 +431,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
 			break;
 	} while (!online && retry--);
 
-	ahci_start_engine(ap);
+	hpriv->start_engine(ap);
 
 	if (online)
 		*class = ahci_dev_classify(ap);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index d74def823d3e..ba5f27120332 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 97f4acb54ad6..3638887476f6 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 3b0dd57984e1..9a6bd4cd29a0 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index b7695e804635..3062f8605b29 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 1ad2f62d34b9..b513428171b3 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index dc4f70179e7d..c630fa812624 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 9947010afc0f..6cd0312be484 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -82,7 +82,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 6d6489118873..08f98c3ed5c8 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 87f056e54a9d..f72e84228c5c 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 44f304b3de63..29e847aac34b 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 62a76076b548..f1a9198dfe5a 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1925,7 +1925,7 @@ static int ucode_init(loader_block *lb, amb_dev *dev)
   const struct firmware *fw;
   unsigned long start_address;
   const struct ihex_binrec *rec;
-  const char *errmsg = 0;
+  const char *errmsg = NULL;
   int res;
 
   res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev);
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index b41c9481b67b..f43e1c13b300 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -736,8 +736,8 @@ static void process_txdone_queue (struct fs_dev *dev, struct queue *q)
       
 			skb = td->skb;
 			if (skb == FS_VCC (ATM_SKB(skb)->vcc)->last_skb) {
-				wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait);
 				FS_VCC (ATM_SKB(skb)->vcc)->last_skb = NULL;
+				wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait);
 			}
 			td->dev->ntxpckts--;
 
@@ -1123,7 +1123,7 @@ static void fs_close(struct atm_vcc *atm_vcc)
 		   this sleep_on, we'll lose any reference to these packets. Memory leak!
 		   On the other hand, it's awfully convenient that we can abort a "close" that
 		   is taking too long. Maybe just use non-interruptible sleep on? -- REW */
-		interruptible_sleep_on (& vcc->close_wait);
+		wait_event_interruptible(vcc->close_wait, !vcc->last_skb);
 	}
 
 	txtp = &atm_vcc->qos.txtp;
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 9587e959ce1a..9988ac98b6d8 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -639,9 +639,9 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
 	card->hbnr.init = NUM_HB;
 	card->hbnr.max = MAX_HB;
 
-	card->sm_handle = 0x00000000;
+	card->sm_handle = NULL;
 	card->sm_addr = 0x00000000;
-	card->lg_handle = 0x00000000;
+	card->lg_handle = NULL;
 	card->lg_addr = 0x00000000;
 
 	card->efbie = 1;	/* To prevent push_rxbufs from enabling the interrupt */
@@ -979,7 +979,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
 				addr2 = card->sm_addr;
 				handle2 = card->sm_handle;
 				card->sm_addr = 0x00000000;
-				card->sm_handle = 0x00000000;
+				card->sm_handle = NULL;
 			} else {	/* (!sm_addr) */
 
 				card->sm_addr = addr1;
@@ -993,7 +993,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
 				addr2 = card->lg_addr;
 				handle2 = card->lg_handle;
 				card->lg_addr = 0x00000000;
-				card->lg_handle = 0x00000000;
+				card->lg_handle = NULL;
 			} else {	/* (!lg_addr) */
 
 				card->lg_addr = addr1;
@@ -1739,10 +1739,10 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
 		}
 
 		scq->full = 1;
-		spin_unlock_irqrestore(&scq->lock, flags);
-		interruptible_sleep_on_timeout(&scq->scqfull_waitq,
-					       SCQFULL_TIMEOUT);
-		spin_lock_irqsave(&scq->lock, flags);
+		wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
+							  scq->tail != scq->next,
+							  scq->lock,
+							  SCQFULL_TIMEOUT);
 
 		if (scq->full) {
 			spin_unlock_irqrestore(&scq->lock, flags);
@@ -1789,10 +1789,10 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
 			scq->full = 1;
 			if (has_run++)
 				break;
-			spin_unlock_irqrestore(&scq->lock, flags);
-			interruptible_sleep_on_timeout(&scq->scqfull_waitq,
-						       SCQFULL_TIMEOUT);
-			spin_lock_irqsave(&scq->lock, flags);
+			wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
+								  scq->tail != scq->next,
+								  scq->lock,
+								  SCQFULL_TIMEOUT);
 		}
 
 		if (!scq->full) {
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index e3fb496c7163..943cf0d6abaf 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -760,7 +760,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
-void solos_bh(unsigned long card_arg)
+static void solos_bh(unsigned long card_arg)
 {
 	struct solos_card *card = (void *)card_arg;
 	uint32_t card_flags;
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ec36e7772e57..8fa8deab6449 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -185,6 +185,9 @@ config GENERIC_CPU_DEVICES
 	bool
 	default n
 
+config GENERIC_CPU_AUTOPROBE
+	bool
+
 config SOC_BUS
 	bool
 
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ecc1929d7f6a..b84ca8f13f9e 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/attribute_container.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 59dc8086e4fa..83e910a57563 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -1218,7 +1218,7 @@ err_dev:
  * with the name of the subsystem. The root device can carry subsystem-
  * wide attributes. All registered devices are below this single root
  * device and are named after the subsystem with a simple enumeration
- * number appended. The registered devices are not explicitely named;
+ * number appended. The registered devices are not explicitly named;
  * only 'id' in the device needs to be set.
  *
  * Do not use this interface for anything new, it exists for compatibility
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 2b567177ef78..80b6a9b22f3e 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -571,6 +571,23 @@ void device_remove_file(struct device *dev,
 EXPORT_SYMBOL_GPL(device_remove_file);
 
 /**
+ * device_remove_file_self - remove sysfs attribute file from its own method.
+ * @dev: device.
+ * @attr: device attribute descriptor.
+ *
+ * See kernfs_remove_self() for details.
+ */
+bool device_remove_file_self(struct device *dev,
+			     const struct device_attribute *attr)
+{
+	if (dev)
+		return sysfs_remove_file_self(&dev->kobj, &attr->attr);
+	else
+		return false;
+}
+EXPORT_SYMBOL_GPL(device_remove_file_self);
+
+/**
  * device_create_bin_file - create sysfs binary attribute file for device.
  * @dev: device.
  * @attr: device binary attribute descriptor.
@@ -598,39 +615,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);
@@ -2058,7 +2042,6 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
 
 	return pos;
 }
-EXPORT_SYMBOL(create_syslog_header);
 
 int dev_vprintk_emit(int level, const struct device *dev,
 		     const char *fmt, va_list args)
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index f48370dfc908..006b1bc5297d 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -15,6 +15,7 @@
 #include <linux/percpu.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
+#include <linux/cpufeature.h>
 
 #include "base.h"
 
@@ -286,6 +287,41 @@ static void cpu_device_release(struct device *dev)
 	 */
 }
 
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+static ssize_t print_cpu_modalias(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	ssize_t n;
+	u32 i;
+
+	n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
+		    CPU_FEATURE_TYPEVAL);
+
+	for (i = 0; i < MAX_CPU_FEATURES; i++)
+		if (cpu_have_feature(i)) {
+			if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
+				WARN(1, "CPU features overflow page\n");
+				break;
+			}
+			n += sprintf(&buf[n], ",%04X", i);
+		}
+	buf[n++] = '\n';
+	return n;
+}
+
+static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (buf) {
+		print_cpu_modalias(NULL, NULL, buf);
+		add_uevent_var(env, "MODALIAS=%s", buf);
+		kfree(buf);
+	}
+	return 0;
+}
+#endif
+
 /*
  * register_cpu - Setup a sysfs device for a CPU.
  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -306,8 +342,8 @@ int register_cpu(struct cpu *cpu, int num)
 	cpu->dev.offline_disabled = !cpu->hotpluggable;
 	cpu->dev.offline = !cpu_online(num);
 	cpu->dev.of_node = of_get_cpu_node(num, NULL);
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-	cpu->dev.bus->uevent = arch_cpu_uevent;
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+	cpu->dev.bus->uevent = cpu_uevent;
 #endif
 	cpu->dev.groups = common_cpu_attr_groups;
 	if (cpu->hotpluggable)
@@ -330,8 +366,8 @@ struct device *get_cpu_device(unsigned cpu)
 }
 EXPORT_SYMBOL_GPL(get_cpu_device);
 
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
 #endif
 
 static struct attribute *cpu_root_attrs[] = {
@@ -344,7 +380,7 @@ static struct attribute *cpu_root_attrs[] = {
 	&cpu_attrs[2].attr.attr,
 	&dev_attr_kernel_max.attr,
 	&dev_attr_offline.attr,
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
 	&dev_attr_modalias.attr,
 #endif
 	NULL
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 545c4de412c3..db4e264eecb6 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -791,6 +791,32 @@ void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
 EXPORT_SYMBOL_GPL(devm_kmalloc);
 
 /**
+ * devm_kstrdup - Allocate resource managed space and
+ *                copy an existing string into that.
+ * @dev: Device to allocate memory for
+ * @s: the string to duplicate
+ * @gfp: the GFP mask used in the devm_kmalloc() call when
+ *       allocating memory
+ * RETURNS:
+ * Pointer to allocated string on success, NULL on failure.
+ */
+char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
+{
+	size_t size;
+	char *buf;
+
+	if (!s)
+		return NULL;
+
+	size = strlen(s) + 1;
+	buf = devm_kmalloc(dev, size, gfp);
+	if (buf)
+		memcpy(buf, s, size);
+	return buf;
+}
+EXPORT_SYMBOL_GPL(devm_kstrdup);
+
+/**
  * devm_kfree - Resource-managed kfree
  * @dev: Device this memory belongs to
  * @p: Memory to free
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 61d6d62cc0d3..ea77701deda4 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -251,9 +251,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
  * @dmabuf:	[in]	buffer to attach device to.
  * @dev:	[in]	device to be attached.
  *
- * Returns struct dma_buf_attachment * for this attachment; may return negative
- * error codes.
- *
+ * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
+ * error.
  */
 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 					  struct device *dev)
@@ -319,9 +318,8 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
  * @attach:	[in]	attachment whose scatterlist is to be returned
  * @direction:	[in]	direction of DMA transfer
  *
- * Returns sg_table containing the scatterlist to be returned; may return NULL
- * or ERR_PTR.
- *
+ * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
+ * on error.
  */
 struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 					enum dma_data_direction direction)
@@ -334,6 +332,8 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 		return ERR_PTR(-EINVAL);
 
 	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
+	if (!sg_table)
+		sg_table = ERR_PTR(-ENOMEM);
 
 	return sg_table;
 }
@@ -544,6 +544,8 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
  * These calls are optional in drivers. The intended use for them
  * is for mapping objects linear in kernel space for high use objects.
  * Please attempt to use kmap/kunmap before thinking about these interfaces.
+ *
+ * Returns NULL on error.
  */
 void *dma_buf_vmap(struct dma_buf *dmabuf)
 {
@@ -566,7 +568,9 @@ void *dma_buf_vmap(struct dma_buf *dmabuf)
 	BUG_ON(dmabuf->vmap_ptr);
 
 	ptr = dmabuf->ops->vmap(dmabuf);
-	if (IS_ERR_OR_NULL(ptr))
+	if (WARN_ON_ONCE(IS_ERR(ptr)))
+		ptr = NULL;
+	if (!ptr)
 		goto out_unlock;
 
 	dmabuf->vmap_ptr = ptr;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index c30df50e4440..d276e33880be 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -649,7 +649,9 @@ static ssize_t firmware_loading_store(struct device *dev,
 			 * see the mapped 'buf->data' once the loading
 			 * is completed.
 			 * */
-			fw_map_pages_buf(fw_buf);
+			if (fw_map_pages_buf(fw_buf))
+				dev_err(dev, "%s: map pages failed\n",
+					__func__);
 			list_del_init(&fw_buf->pending_list);
 			complete_all(&fw_buf->completion);
 			break;
@@ -900,7 +902,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
 		dev_set_uevent_suppress(f_dev, false);
 		dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
 		if (timeout != MAX_SCHEDULE_TIMEOUT)
-			schedule_delayed_work(&fw_priv->timeout_work, timeout);
+			queue_delayed_work(system_power_efficient_wq,
+					   &fw_priv->timeout_work, timeout);
 
 		kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
 	}
@@ -908,6 +911,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
 	wait_for_completion(&buf->completion);
 
 	cancel_delayed_work_sync(&fw_priv->timeout_work);
+	if (!buf->data)
+		retval = -ENOMEM;
 
 	device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
@@ -1570,8 +1575,8 @@ static void device_uncache_fw_images_work(struct work_struct *work)
  */
 static void device_uncache_fw_images_delay(unsigned long delay)
 {
-	schedule_delayed_work(&fw_cache.work,
-			msecs_to_jiffies(delay));
+	queue_delayed_work(system_power_efficient_wq, &fw_cache.work,
+			   msecs_to_jiffies(delay));
 }
 
 static int fw_pm_notify(struct notifier_block *notify_block,
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index bc78848dd59a..e714709704e4 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -481,11 +481,10 @@ static int platform_drv_probe(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
-	if (ACPI_HANDLE(_dev))
-		acpi_dev_pm_attach(_dev, true);
+	acpi_dev_pm_attach(_dev, true);
 
 	ret = drv->probe(dev);
-	if (ret && ACPI_HANDLE(_dev))
+	if (ret)
 		acpi_dev_pm_detach(_dev, true);
 
 	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
@@ -508,8 +507,7 @@ static int platform_drv_remove(struct device *_dev)
 	int ret;
 
 	ret = drv->remove(dev);
-	if (ACPI_HANDLE(_dev))
-		acpi_dev_pm_detach(_dev, true);
+	acpi_dev_pm_detach(_dev, true);
 
 	return ret;
 }
@@ -520,8 +518,7 @@ static void platform_drv_shutdown(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 
 	drv->shutdown(dev);
-	if (ACPI_HANDLE(_dev))
-		acpi_dev_pm_detach(_dev, true);
+	acpi_dev_pm_detach(_dev, true);
 }
 
 /**
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index e870bbe9ec4e..b99e6c06ee67 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -6,7 +6,6 @@
  * This file is released under the GPLv2.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/io.h>
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 5da914041305..df2e5eeaeb05 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -6,7 +6,6 @@
  * This file is released under the GPLv2.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/export.h>
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index bfb8955c406c..921b19234a4d 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -6,7 +6,6 @@
  * This file is released under the GPLv2.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 28dee3053f1f..a089e3bcdfbc 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -6,7 +6,6 @@
  * This file is released under the GPLv2.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_qos.h>
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 1b41fca3d65a..42355e442a5d 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -91,6 +91,8 @@ void device_pm_sleep_init(struct device *dev)
 {
 	dev->power.is_prepared = false;
 	dev->power.is_suspended = false;
+	dev->power.is_noirq_suspended = false;
+	dev->power.is_late_suspended = false;
 	init_completion(&dev->power.completion);
 	complete_all(&dev->power.completion);
 	dev->power.wakeup = NULL;
@@ -467,7 +469,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
  */
-static int device_resume_noirq(struct device *dev, pm_message_t state)
+static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback = NULL;
 	char *info = NULL;
@@ -479,6 +481,11 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 	if (dev->power.syscore)
 		goto Out;
 
+	if (!dev->power.is_noirq_suspended)
+		goto Out;
+
+	dpm_wait(dev->parent, async);
+
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
 		callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -499,12 +506,32 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 	}
 
 	error = dpm_run_callback(callback, dev, state, info);
+	dev->power.is_noirq_suspended = false;
 
  Out:
+	complete_all(&dev->power.completion);
 	TRACE_RESUME(error);
 	return error;
 }
 
+static bool is_async(struct device *dev)
+{
+	return dev->power.async_suspend && pm_async_enabled
+		&& !pm_trace_is_enabled();
+}
+
+static void async_resume_noirq(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+	int error;
+
+	error = device_resume_noirq(dev, pm_transition, true);
+	if (error)
+		pm_dev_err(dev, pm_transition, " async", error);
+
+	put_device(dev);
+}
+
 /**
  * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
  * @state: PM transition of the system being carried out.
@@ -514,29 +541,48 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
  */
 static void dpm_resume_noirq(pm_message_t state)
 {
+	struct device *dev;
 	ktime_t starttime = ktime_get();
 
 	mutex_lock(&dpm_list_mtx);
-	while (!list_empty(&dpm_noirq_list)) {
-		struct device *dev = to_device(dpm_noirq_list.next);
-		int error;
+	pm_transition = state;
 
+	/*
+	 * Advanced the async threads upfront,
+	 * in case the starting of async threads is
+	 * delayed by non-async resuming devices.
+	 */
+	list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
+		reinit_completion(&dev->power.completion);
+		if (is_async(dev)) {
+			get_device(dev);
+			async_schedule(async_resume_noirq, dev);
+		}
+	}
+
+	while (!list_empty(&dpm_noirq_list)) {
+		dev = to_device(dpm_noirq_list.next);
 		get_device(dev);
 		list_move_tail(&dev->power.entry, &dpm_late_early_list);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = device_resume_noirq(dev, state);
-		if (error) {
-			suspend_stats.failed_resume_noirq++;
-			dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
-			dpm_save_failed_dev(dev_name(dev));
-			pm_dev_err(dev, state, " noirq", error);
+		if (!is_async(dev)) {
+			int error;
+
+			error = device_resume_noirq(dev, state, false);
+			if (error) {
+				suspend_stats.failed_resume_noirq++;
+				dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+				dpm_save_failed_dev(dev_name(dev));
+				pm_dev_err(dev, state, " noirq", error);
+			}
 		}
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
 	mutex_unlock(&dpm_list_mtx);
+	async_synchronize_full();
 	dpm_show_time(starttime, state, "noirq");
 	resume_device_irqs();
 	cpuidle_resume();
@@ -549,7 +595,7 @@ static void dpm_resume_noirq(pm_message_t state)
  *
  * Runtime PM is disabled for @dev while this function is being executed.
  */
-static int device_resume_early(struct device *dev, pm_message_t state)
+static int device_resume_early(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback = NULL;
 	char *info = NULL;
@@ -561,6 +607,11 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 	if (dev->power.syscore)
 		goto Out;
 
+	if (!dev->power.is_late_suspended)
+		goto Out;
+
+	dpm_wait(dev->parent, async);
+
 	if (dev->pm_domain) {
 		info = "early power domain ";
 		callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -581,43 +632,75 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 	}
 
 	error = dpm_run_callback(callback, dev, state, info);
+	dev->power.is_late_suspended = false;
 
  Out:
 	TRACE_RESUME(error);
 
 	pm_runtime_enable(dev);
+	complete_all(&dev->power.completion);
 	return error;
 }
 
+static void async_resume_early(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+	int error;
+
+	error = device_resume_early(dev, pm_transition, true);
+	if (error)
+		pm_dev_err(dev, pm_transition, " async", error);
+
+	put_device(dev);
+}
+
 /**
  * dpm_resume_early - Execute "early resume" callbacks for all devices.
  * @state: PM transition of the system being carried out.
  */
 static void dpm_resume_early(pm_message_t state)
 {
+	struct device *dev;
 	ktime_t starttime = ktime_get();
 
 	mutex_lock(&dpm_list_mtx);
-	while (!list_empty(&dpm_late_early_list)) {
-		struct device *dev = to_device(dpm_late_early_list.next);
-		int error;
+	pm_transition = state;
+
+	/*
+	 * Advanced the async threads upfront,
+	 * in case the starting of async threads is
+	 * delayed by non-async resuming devices.
+	 */
+	list_for_each_entry(dev, &dpm_late_early_list, power.entry) {
+		reinit_completion(&dev->power.completion);
+		if (is_async(dev)) {
+			get_device(dev);
+			async_schedule(async_resume_early, dev);
+		}
+	}
 
+	while (!list_empty(&dpm_late_early_list)) {
+		dev = to_device(dpm_late_early_list.next);
 		get_device(dev);
 		list_move_tail(&dev->power.entry, &dpm_suspended_list);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = device_resume_early(dev, state);
-		if (error) {
-			suspend_stats.failed_resume_early++;
-			dpm_save_failed_step(SUSPEND_RESUME_EARLY);
-			dpm_save_failed_dev(dev_name(dev));
-			pm_dev_err(dev, state, " early", error);
-		}
+		if (!is_async(dev)) {
+			int error;
 
+			error = device_resume_early(dev, state, false);
+			if (error) {
+				suspend_stats.failed_resume_early++;
+				dpm_save_failed_step(SUSPEND_RESUME_EARLY);
+				dpm_save_failed_dev(dev_name(dev));
+				pm_dev_err(dev, state, " early", error);
+			}
+		}
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
 	mutex_unlock(&dpm_list_mtx);
+	async_synchronize_full();
 	dpm_show_time(starttime, state, "early");
 }
 
@@ -732,12 +815,6 @@ static void async_resume(void *data, async_cookie_t cookie)
 	put_device(dev);
 }
 
-static bool is_async(struct device *dev)
-{
-	return dev->power.async_suspend && pm_async_enabled
-		&& !pm_trace_is_enabled();
-}
-
 /**
  * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
  * @state: PM transition of the system being carried out.
@@ -913,13 +990,24 @@ static pm_message_t resume_event(pm_message_t sleep_state)
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
  */
-static int device_suspend_noirq(struct device *dev, pm_message_t state)
+static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback = NULL;
 	char *info = NULL;
+	int error = 0;
+
+	if (async_error)
+		goto Complete;
+
+	if (pm_wakeup_pending()) {
+		async_error = -EBUSY;
+		goto Complete;
+	}
 
 	if (dev->power.syscore)
-		return 0;
+		goto Complete;
+
+	dpm_wait_for_children(dev, async);
 
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
@@ -940,7 +1028,41 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 		callback = pm_noirq_op(dev->driver->pm, state);
 	}
 
-	return dpm_run_callback(callback, dev, state, info);
+	error = dpm_run_callback(callback, dev, state, info);
+	if (!error)
+		dev->power.is_noirq_suspended = true;
+	else
+		async_error = error;
+
+Complete:
+	complete_all(&dev->power.completion);
+	return error;
+}
+
+static void async_suspend_noirq(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+	int error;
+
+	error = __device_suspend_noirq(dev, pm_transition, true);
+	if (error) {
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, pm_transition, " async", error);
+	}
+
+	put_device(dev);
+}
+
+static int device_suspend_noirq(struct device *dev)
+{
+	reinit_completion(&dev->power.completion);
+
+	if (pm_async_enabled && dev->power.async_suspend) {
+		get_device(dev);
+		async_schedule(async_suspend_noirq, dev);
+		return 0;
+	}
+	return __device_suspend_noirq(dev, pm_transition, false);
 }
 
 /**
@@ -958,19 +1080,20 @@ static int dpm_suspend_noirq(pm_message_t state)
 	cpuidle_pause();
 	suspend_device_irqs();
 	mutex_lock(&dpm_list_mtx);
+	pm_transition = state;
+	async_error = 0;
+
 	while (!list_empty(&dpm_late_early_list)) {
 		struct device *dev = to_device(dpm_late_early_list.prev);
 
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = device_suspend_noirq(dev, state);
+		error = device_suspend_noirq(dev);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, " noirq", error);
-			suspend_stats.failed_suspend_noirq++;
-			dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
 			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
@@ -979,16 +1102,21 @@ static int dpm_suspend_noirq(pm_message_t state)
 			list_move(&dev->power.entry, &dpm_noirq_list);
 		put_device(dev);
 
-		if (pm_wakeup_pending()) {
-			error = -EBUSY;
+		if (async_error)
 			break;
-		}
 	}
 	mutex_unlock(&dpm_list_mtx);
-	if (error)
+	async_synchronize_full();
+	if (!error)
+		error = async_error;
+
+	if (error) {
+		suspend_stats.failed_suspend_noirq++;
+		dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
 		dpm_resume_noirq(resume_event(state));
-	else
+	} else {
 		dpm_show_time(starttime, state, "noirq");
+	}
 	return error;
 }
 
@@ -999,15 +1127,26 @@ static int dpm_suspend_noirq(pm_message_t state)
  *
  * Runtime PM is disabled for @dev while this function is being executed.
  */
-static int device_suspend_late(struct device *dev, pm_message_t state)
+static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback = NULL;
 	char *info = NULL;
+	int error = 0;
 
 	__pm_runtime_disable(dev, false);
 
+	if (async_error)
+		goto Complete;
+
+	if (pm_wakeup_pending()) {
+		async_error = -EBUSY;
+		goto Complete;
+	}
+
 	if (dev->power.syscore)
-		return 0;
+		goto Complete;
+
+	dpm_wait_for_children(dev, async);
 
 	if (dev->pm_domain) {
 		info = "late power domain ";
@@ -1028,7 +1167,41 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
 		callback = pm_late_early_op(dev->driver->pm, state);
 	}
 
-	return dpm_run_callback(callback, dev, state, info);
+	error = dpm_run_callback(callback, dev, state, info);
+	if (!error)
+		dev->power.is_late_suspended = true;
+	else
+		async_error = error;
+
+Complete:
+	complete_all(&dev->power.completion);
+	return error;
+}
+
+static void async_suspend_late(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+	int error;
+
+	error = __device_suspend_late(dev, pm_transition, true);
+	if (error) {
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, pm_transition, " async", error);
+	}
+	put_device(dev);
+}
+
+static int device_suspend_late(struct device *dev)
+{
+	reinit_completion(&dev->power.completion);
+
+	if (pm_async_enabled && dev->power.async_suspend) {
+		get_device(dev);
+		async_schedule(async_suspend_late, dev);
+		return 0;
+	}
+
+	return __device_suspend_late(dev, pm_transition, false);
 }
 
 /**
@@ -1041,19 +1214,20 @@ static int dpm_suspend_late(pm_message_t state)
 	int error = 0;
 
 	mutex_lock(&dpm_list_mtx);
+	pm_transition = state;
+	async_error = 0;
+
 	while (!list_empty(&dpm_suspended_list)) {
 		struct device *dev = to_device(dpm_suspended_list.prev);
 
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = device_suspend_late(dev, state);
+		error = device_suspend_late(dev);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
-			suspend_stats.failed_suspend_late++;
-			dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
 			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
@@ -1062,17 +1236,18 @@ static int dpm_suspend_late(pm_message_t state)
 			list_move(&dev->power.entry, &dpm_late_early_list);
 		put_device(dev);
 
-		if (pm_wakeup_pending()) {
-			error = -EBUSY;
+		if (async_error)
 			break;
-		}
 	}
 	mutex_unlock(&dpm_list_mtx);
-	if (error)
+	async_synchronize_full();
+	if (error) {
+		suspend_stats.failed_suspend_late++;
+		dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
 		dpm_resume_early(resume_event(state));
-	else
+	} else {
 		dpm_show_time(starttime, state, "late");
-
+	}
 	return error;
 }
 
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index fa4187418440..25538675d59e 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
 #include <linux/device.h>
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index cfc3226ec492..a21223d95926 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -89,8 +89,8 @@ extern void dpm_sysfs_remove(struct device *dev);
 extern void rpm_sysfs_remove(struct device *dev);
 extern int wakeup_sysfs_add(struct device *dev);
 extern void wakeup_sysfs_remove(struct device *dev);
-extern int pm_qos_sysfs_add_latency(struct device *dev);
-extern void pm_qos_sysfs_remove_latency(struct device *dev);
+extern int pm_qos_sysfs_add_resume_latency(struct device *dev);
+extern void pm_qos_sysfs_remove_resume_latency(struct device *dev);
 extern int pm_qos_sysfs_add_flags(struct device *dev);
 extern void pm_qos_sysfs_remove_flags(struct device *dev);
 
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 5c1361a9e5dd..36b9eb4862cb 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -105,7 +105,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
 s32 __dev_pm_qos_read_value(struct device *dev)
 {
 	return IS_ERR_OR_NULL(dev->power.qos) ?
-		0 : pm_qos_read_value(&dev->power.qos->latency);
+		0 : pm_qos_read_value(&dev->power.qos->resume_latency);
 }
 
 /**
@@ -141,16 +141,24 @@ static int apply_constraint(struct dev_pm_qos_request *req,
 	int ret;
 
 	switch(req->type) {
-	case DEV_PM_QOS_LATENCY:
-		ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
-					   action, value);
+	case DEV_PM_QOS_RESUME_LATENCY:
+		ret = pm_qos_update_target(&qos->resume_latency,
+					   &req->data.pnode, action, value);
 		if (ret) {
-			value = pm_qos_read_value(&qos->latency);
+			value = pm_qos_read_value(&qos->resume_latency);
 			blocking_notifier_call_chain(&dev_pm_notifiers,
 						     (unsigned long)value,
 						     req);
 		}
 		break;
+	case DEV_PM_QOS_LATENCY_TOLERANCE:
+		ret = pm_qos_update_target(&qos->latency_tolerance,
+					   &req->data.pnode, action, value);
+		if (ret) {
+			value = pm_qos_read_value(&qos->latency_tolerance);
+			req->dev->power.set_latency_tolerance(req->dev, value);
+		}
+		break;
 	case DEV_PM_QOS_FLAGS:
 		ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
 					  action, value);
@@ -186,13 +194,21 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
 	}
 	BLOCKING_INIT_NOTIFIER_HEAD(n);
 
-	c = &qos->latency;
+	c = &qos->resume_latency;
 	plist_head_init(&c->list);
-	c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
-	c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
+	c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
+	c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
 	c->type = PM_QOS_MIN;
 	c->notifiers = n;
 
+	c = &qos->latency_tolerance;
+	plist_head_init(&c->list);
+	c->target_value = PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE;
+	c->default_value = PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE;
+	c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
+	c->type = PM_QOS_MIN;
+
 	INIT_LIST_HEAD(&qos->flags.list);
 
 	spin_lock_irq(&dev->power.lock);
@@ -224,7 +240,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 	 * If the device's PM QoS resume latency limit or PM QoS flags have been
 	 * exposed to user space, they have to be hidden at this point.
 	 */
-	pm_qos_sysfs_remove_latency(dev);
+	pm_qos_sysfs_remove_resume_latency(dev);
 	pm_qos_sysfs_remove_flags(dev);
 
 	mutex_lock(&dev_pm_qos_mtx);
@@ -237,7 +253,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 		goto out;
 
 	/* Flush the constraints lists for the device. */
-	c = &qos->latency;
+	c = &qos->resume_latency;
 	plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
 		/*
 		 * Update constraints list and call the notification
@@ -246,6 +262,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
 		memset(req, 0, sizeof(*req));
 	}
+	c = &qos->latency_tolerance;
+	plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
+		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	}
 	f = &qos->flags;
 	list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
 		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
@@ -265,6 +286,40 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 
+static bool dev_pm_qos_invalid_request(struct device *dev,
+				       struct dev_pm_qos_request *req)
+{
+	return !req || (req->type == DEV_PM_QOS_LATENCY_TOLERANCE
+			&& !dev->power.set_latency_tolerance);
+}
+
+static int __dev_pm_qos_add_request(struct device *dev,
+				    struct dev_pm_qos_request *req,
+				    enum dev_pm_qos_req_type type, s32 value)
+{
+	int ret = 0;
+
+	if (!dev || dev_pm_qos_invalid_request(dev, req))
+		return -EINVAL;
+
+	if (WARN(dev_pm_qos_request_active(req),
+		 "%s() called for already added request\n", __func__))
+		return -EINVAL;
+
+	if (IS_ERR(dev->power.qos))
+		ret = -ENODEV;
+	else if (!dev->power.qos)
+		ret = dev_pm_qos_constraints_allocate(dev);
+
+	trace_dev_pm_qos_add_request(dev_name(dev), type, value);
+	if (!ret) {
+		req->dev = dev;
+		req->type = type;
+		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+	}
+	return ret;
+}
+
 /**
  * dev_pm_qos_add_request - inserts new qos request into the list
  * @dev: target device for the constraint
@@ -290,31 +345,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 			   enum dev_pm_qos_req_type type, s32 value)
 {
-	int ret = 0;
-
-	if (!dev || !req) /*guard against callers passing in null */
-		return -EINVAL;
-
-	if (WARN(dev_pm_qos_request_active(req),
-		 "%s() called for already added request\n", __func__))
-		return -EINVAL;
+	int ret;
 
 	mutex_lock(&dev_pm_qos_mtx);
-
-	if (IS_ERR(dev->power.qos))
-		ret = -ENODEV;
-	else if (!dev->power.qos)
-		ret = dev_pm_qos_constraints_allocate(dev);
-
-	trace_dev_pm_qos_add_request(dev_name(dev), type, value);
-	if (!ret) {
-		req->dev = dev;
-		req->type = type;
-		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
-	}
-
+	ret = __dev_pm_qos_add_request(dev, req, type, value);
 	mutex_unlock(&dev_pm_qos_mtx);
-
 	return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
@@ -341,7 +376,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
 		return -ENODEV;
 
 	switch(req->type) {
-	case DEV_PM_QOS_LATENCY:
+	case DEV_PM_QOS_RESUME_LATENCY:
+	case DEV_PM_QOS_LATENCY_TOLERANCE:
 		curr_value = req->data.pnode.prio;
 		break;
 	case DEV_PM_QOS_FLAGS:
@@ -460,8 +496,8 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
 		ret = dev_pm_qos_constraints_allocate(dev);
 
 	if (!ret)
-		ret = blocking_notifier_chain_register(
-				dev->power.qos->latency.notifiers, notifier);
+		ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
+						       notifier);
 
 	mutex_unlock(&dev_pm_qos_mtx);
 	return ret;
@@ -487,9 +523,8 @@ int dev_pm_qos_remove_notifier(struct device *dev,
 
 	/* Silently return if the constraints object is not present. */
 	if (!IS_ERR_OR_NULL(dev->power.qos))
-		retval = blocking_notifier_chain_unregister(
-				dev->power.qos->latency.notifiers,
-				notifier);
+		retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
+							    notifier);
 
 	mutex_unlock(&dev_pm_qos_mtx);
 	return retval;
@@ -530,20 +565,32 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
  * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
  * @dev: Device whose ancestor to add the request for.
  * @req: Pointer to the preallocated handle.
+ * @type: Type of the request.
  * @value: Constraint latency value.
  */
 int dev_pm_qos_add_ancestor_request(struct device *dev,
-				    struct dev_pm_qos_request *req, s32 value)
+				    struct dev_pm_qos_request *req,
+				    enum dev_pm_qos_req_type type, s32 value)
 {
 	struct device *ancestor = dev->parent;
 	int ret = -ENODEV;
 
-	while (ancestor && !ancestor->power.ignore_children)
-		ancestor = ancestor->parent;
+	switch (type) {
+	case DEV_PM_QOS_RESUME_LATENCY:
+		while (ancestor && !ancestor->power.ignore_children)
+			ancestor = ancestor->parent;
 
+		break;
+	case DEV_PM_QOS_LATENCY_TOLERANCE:
+		while (ancestor && !ancestor->power.set_latency_tolerance)
+			ancestor = ancestor->parent;
+
+		break;
+	default:
+		ancestor = NULL;
+	}
 	if (ancestor)
-		ret = dev_pm_qos_add_request(ancestor, req,
-					     DEV_PM_QOS_LATENCY, value);
+		ret = dev_pm_qos_add_request(ancestor, req, type, value);
 
 	if (ret < 0)
 		req->dev = NULL;
@@ -559,9 +606,13 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
 	struct dev_pm_qos_request *req = NULL;
 
 	switch(type) {
-	case DEV_PM_QOS_LATENCY:
-		req = dev->power.qos->latency_req;
-		dev->power.qos->latency_req = NULL;
+	case DEV_PM_QOS_RESUME_LATENCY:
+		req = dev->power.qos->resume_latency_req;
+		dev->power.qos->resume_latency_req = NULL;
+		break;
+	case DEV_PM_QOS_LATENCY_TOLERANCE:
+		req = dev->power.qos->latency_tolerance_req;
+		dev->power.qos->latency_tolerance_req = NULL;
 		break;
 	case DEV_PM_QOS_FLAGS:
 		req = dev->power.qos->flags_req;
@@ -597,7 +648,7 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 	if (!req)
 		return -ENOMEM;
 
-	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
+	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_RESUME_LATENCY, value);
 	if (ret < 0) {
 		kfree(req);
 		return ret;
@@ -609,7 +660,7 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 
 	if (IS_ERR_OR_NULL(dev->power.qos))
 		ret = -ENODEV;
-	else if (dev->power.qos->latency_req)
+	else if (dev->power.qos->resume_latency_req)
 		ret = -EEXIST;
 
 	if (ret < 0) {
@@ -618,13 +669,13 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 		mutex_unlock(&dev_pm_qos_mtx);
 		goto out;
 	}
-	dev->power.qos->latency_req = req;
+	dev->power.qos->resume_latency_req = req;
 
 	mutex_unlock(&dev_pm_qos_mtx);
 
-	ret = pm_qos_sysfs_add_latency(dev);
+	ret = pm_qos_sysfs_add_resume_latency(dev);
 	if (ret)
-		dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+		dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY);
 
  out:
 	mutex_unlock(&dev_pm_qos_sysfs_mtx);
@@ -634,8 +685,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
 static void __dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
-		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->resume_latency_req)
+		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY);
 }
 
 /**
@@ -646,7 +697,7 @@ void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
 	mutex_lock(&dev_pm_qos_sysfs_mtx);
 
-	pm_qos_sysfs_remove_latency(dev);
+	pm_qos_sysfs_remove_resume_latency(dev);
 
 	mutex_lock(&dev_pm_qos_mtx);
 	__dev_pm_qos_hide_latency_limit(dev);
@@ -768,6 +819,67 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
 	pm_runtime_put(dev);
 	return ret;
 }
+
+/**
+ * dev_pm_qos_get_user_latency_tolerance - Get user space latency tolerance.
+ * @dev: Device to obtain the user space latency tolerance for.
+ */
+s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev)
+{
+	s32 ret;
+
+	mutex_lock(&dev_pm_qos_mtx);
+	ret = IS_ERR_OR_NULL(dev->power.qos)
+		|| !dev->power.qos->latency_tolerance_req ?
+			PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT :
+			dev->power.qos->latency_tolerance_req->data.pnode.prio;
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
+
+/**
+ * dev_pm_qos_update_user_latency_tolerance - Update user space latency tolerance.
+ * @dev: Device to update the user space latency tolerance for.
+ * @val: New user space latency tolerance for @dev (negative values disable).
+ */
+int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
+{
+	int ret;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (IS_ERR_OR_NULL(dev->power.qos)
+	    || !dev->power.qos->latency_tolerance_req) {
+		struct dev_pm_qos_request *req;
+
+		if (val < 0) {
+			ret = -EINVAL;
+			goto out;
+		}
+		req = kzalloc(sizeof(*req), GFP_KERNEL);
+		if (!req) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		ret = __dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY_TOLERANCE, val);
+		if (ret < 0) {
+			kfree(req);
+			goto out;
+		}
+		dev->power.qos->latency_tolerance_req = req;
+	} else {
+		if (val < 0) {
+			__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY_TOLERANCE);
+			ret = 0;
+		} else {
+			ret = __dev_pm_qos_update_request(dev->power.qos->latency_tolerance_req, val);
+		}
+	}
+
+ out:
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
 #else /* !CONFIG_PM_RUNTIME */
 static void __dev_pm_qos_hide_latency_limit(struct device *dev) {}
 static void __dev_pm_qos_hide_flags(struct device *dev) {}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 03e089ade5ce..95b181d1ca6d 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -218,15 +218,16 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
 static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
 		autosuspend_delay_ms_store);
 
-static ssize_t pm_qos_latency_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+static ssize_t pm_qos_resume_latency_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
 {
-	return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev));
+	return sprintf(buf, "%d\n", dev_pm_qos_requested_resume_latency(dev));
 }
 
-static ssize_t pm_qos_latency_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t n)
+static ssize_t pm_qos_resume_latency_store(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf, size_t n)
 {
 	s32 value;
 	int ret;
@@ -237,12 +238,47 @@ static ssize_t pm_qos_latency_store(struct device *dev,
 	if (value < 0)
 		return -EINVAL;
 
-	ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value);
+	ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req,
+					value);
 	return ret < 0 ? ret : n;
 }
 
 static DEVICE_ATTR(pm_qos_resume_latency_us, 0644,
-		   pm_qos_latency_show, pm_qos_latency_store);
+		   pm_qos_resume_latency_show, pm_qos_resume_latency_store);
+
+static ssize_t pm_qos_latency_tolerance_show(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	s32 value = dev_pm_qos_get_user_latency_tolerance(dev);
+
+	if (value < 0)
+		return sprintf(buf, "auto\n");
+	else if (value == PM_QOS_LATENCY_ANY)
+		return sprintf(buf, "any\n");
+
+	return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t pm_qos_latency_tolerance_store(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t n)
+{
+	s32 value;
+	int ret;
+
+	if (kstrtos32(buf, 0, &value)) {
+		if (!strcmp(buf, "auto") || !strcmp(buf, "auto\n"))
+			value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
+		else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
+			value = PM_QOS_LATENCY_ANY;
+	}
+	ret = dev_pm_qos_update_user_latency_tolerance(dev, value);
+	return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_latency_tolerance_us, 0644,
+		   pm_qos_latency_tolerance_show, pm_qos_latency_tolerance_store);
 
 static ssize_t pm_qos_no_power_off_show(struct device *dev,
 					struct device_attribute *attr,
@@ -618,15 +654,26 @@ static struct attribute_group pm_runtime_attr_group = {
 	.attrs	= runtime_attrs,
 };
 
-static struct attribute *pm_qos_latency_attrs[] = {
+static struct attribute *pm_qos_resume_latency_attrs[] = {
 #ifdef CONFIG_PM_RUNTIME
 	&dev_attr_pm_qos_resume_latency_us.attr,
 #endif /* CONFIG_PM_RUNTIME */
 	NULL,
 };
-static struct attribute_group pm_qos_latency_attr_group = {
+static struct attribute_group pm_qos_resume_latency_attr_group = {
+	.name	= power_group_name,
+	.attrs	= pm_qos_resume_latency_attrs,
+};
+
+static struct attribute *pm_qos_latency_tolerance_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
+	&dev_attr_pm_qos_latency_tolerance_us.attr,
+#endif /* CONFIG_PM_RUNTIME */
+	NULL,
+};
+static struct attribute_group pm_qos_latency_tolerance_attr_group = {
 	.name	= power_group_name,
-	.attrs	= pm_qos_latency_attrs,
+	.attrs	= pm_qos_latency_tolerance_attrs,
 };
 
 static struct attribute *pm_qos_flags_attrs[] = {
@@ -654,18 +701,23 @@ int dpm_sysfs_add(struct device *dev)
 		if (rc)
 			goto err_out;
 	}
-
 	if (device_can_wakeup(dev)) {
 		rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
-		if (rc) {
-			if (pm_runtime_callbacks_present(dev))
-				sysfs_unmerge_group(&dev->kobj,
-						    &pm_runtime_attr_group);
-			goto err_out;
-		}
+		if (rc)
+			goto err_runtime;
+	}
+	if (dev->power.set_latency_tolerance) {
+		rc = sysfs_merge_group(&dev->kobj,
+				       &pm_qos_latency_tolerance_attr_group);
+		if (rc)
+			goto err_wakeup;
 	}
 	return 0;
 
+ err_wakeup:
+	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
+ err_runtime:
+	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
  err_out:
 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 	return rc;
@@ -681,14 +733,14 @@ void wakeup_sysfs_remove(struct device *dev)
 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-int pm_qos_sysfs_add_latency(struct device *dev)
+int pm_qos_sysfs_add_resume_latency(struct device *dev)
 {
-	return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group);
+	return sysfs_merge_group(&dev->kobj, &pm_qos_resume_latency_attr_group);
 }
 
-void pm_qos_sysfs_remove_latency(struct device *dev)
+void pm_qos_sysfs_remove_resume_latency(struct device *dev)
 {
-	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_qos_resume_latency_attr_group);
 }
 
 int pm_qos_sysfs_add_flags(struct device *dev)
@@ -708,6 +760,7 @@ void rpm_sysfs_remove(struct device *dev)
 
 void dpm_sysfs_remove(struct device *dev)
 {
+	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
 	dev_pm_qos_constraints_destroy(dev);
 	rpm_sysfs_remove(dev);
 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d4dd77134814..c6b1ac1c5982 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -312,10 +312,6 @@ int regcache_sync(struct regmap *map)
 	/* Apply any patch first */
 	map->cache_bypass = 1;
 	for (i = 0; i < map->patch_regs; i++) {
-		if (map->patch[i].reg % map->reg_stride) {
-			ret = -EINVAL;
-			goto out;
-		}
 		ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
 		if (ret != 0) {
 			dev_err(map->dev, "Failed to write %x = %x: %d\n",
@@ -636,10 +632,10 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
 	if (*data == NULL)
 		return 0;
 
-	count = cur - base;
+	count = (cur - base) / map->reg_stride;
 
 	dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n",
-		count * val_bytes, count, base, cur - 1);
+		count * val_bytes, count, base, cur - map->reg_stride);
 
 	map->cache_bypass = 1;
 
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index c5471cd6ebb7..45d812c0ea77 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -511,7 +511,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 	debugfs_create_file("range", 0400, map->debugfs,
 			    map, &regmap_reg_ranges_fops);
 
-	if (map->max_register) {
+	if (map->max_register || regmap_readable(map, 0)) {
 		debugfs_create_file("registers", 0400, map->debugfs,
 				    map, &regmap_map_fops);
 		debugfs_create_file("access", 0400, map->debugfs,
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index fa6bf5279d28..ebd189529760 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -13,7 +13,6 @@
 #include <linux/regmap.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/init.h>
 
 static int regmap_i2c_write(void *context, const void *data, size_t count)
 {
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 82692068d3cb..52ce0c17c68b 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -533,7 +533,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 		return;
 
 	free_irq(irq, d);
-	/* We should unmap the domain but... */
+	irq_domain_remove(d->domain);
 	kfree(d->wake_buf);
 	kfree(d->mask_buf_def);
 	kfree(d->mask_buf);
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 81f977510775..4410cb2d7d82 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -18,7 +18,6 @@
 
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 37f12ae7aada..0eb3097c0d76 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -12,7 +12,6 @@
 
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
-#include <linux/init.h>
 #include <linux/module.h>
 
 #include "internal.h"
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
index ac2391013db1..d7026dc33388 100644
--- a/drivers/base/regmap/regmap-spmi.c
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -22,69 +22,235 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-static int regmap_spmi_read(void *context,
-			    const void *reg, size_t reg_size,
-			    void *val, size_t val_size)
+static int regmap_spmi_base_read(void *context,
+				 const void *reg, size_t reg_size,
+				 void *val, size_t val_size)
 {
+	u8 addr = *(u8 *)reg;
+	int err = 0;
+
+	BUG_ON(reg_size != 1);
+
+	while (val_size-- && !err)
+		err = spmi_register_read(context, addr++, val++);
+
+	return err;
+}
+
+static int regmap_spmi_base_gather_write(void *context,
+					 const void *reg, size_t reg_size,
+					 const void *val, size_t val_size)
+{
+	const u8 *data = val;
+	u8 addr = *(u8 *)reg;
+	int err = 0;
+
+	BUG_ON(reg_size != 1);
+
+	/*
+	 * SPMI defines a more bandwidth-efficient 'Register 0 Write' sequence,
+	 * use it when possible.
+	 */
+	if (addr == 0 && val_size) {
+		err = spmi_register_zero_write(context, *data);
+		if (err)
+			goto err_out;
+
+		data++;
+		addr++;
+		val_size--;
+	}
+
+	while (val_size) {
+		err = spmi_register_write(context, addr, *data);
+		if (err)
+			goto err_out;
+
+		data++;
+		addr++;
+		val_size--;
+	}
+
+err_out:
+	return err;
+}
+
+static int regmap_spmi_base_write(void *context, const void *data,
+				  size_t count)
+{
+	BUG_ON(count < 1);
+	return regmap_spmi_base_gather_write(context, data, 1, data + 1,
+					     count - 1);
+}
+
+static struct regmap_bus regmap_spmi_base = {
+	.read				= regmap_spmi_base_read,
+	.write				= regmap_spmi_base_write,
+	.gather_write			= regmap_spmi_base_gather_write,
+	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+};
+
+/**
+ * regmap_init_spmi_base(): Create regmap for the Base register space
+ * @sdev:	SPMI device that will be interacted with
+ * @config:	Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_spmi_base(struct spmi_device *sdev,
+				     const struct regmap_config *config)
+{
+	return regmap_init(&sdev->dev, &regmap_spmi_base, sdev, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_spmi_base);
+
+/**
+ * devm_regmap_init_spmi_base(): Create managed regmap for Base register space
+ * @sdev:	SPMI device that will be interacted with
+ * @config:	Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap.  The regmap will be automatically freed by the
+ * device management code.
+ */
+struct regmap *devm_regmap_init_spmi_base(struct spmi_device *sdev,
+					  const struct regmap_config *config)
+{
+	return devm_regmap_init(&sdev->dev, &regmap_spmi_base, sdev, config);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_base);
+
+static int regmap_spmi_ext_read(void *context,
+				const void *reg, size_t reg_size,
+				void *val, size_t val_size)
+{
+	int err = 0;
+	size_t len;
+	u16 addr;
+
 	BUG_ON(reg_size != 2);
-	return spmi_ext_register_readl(context, *(u16 *)reg,
-				       val, val_size);
+
+	addr = *(u16 *)reg;
+
+	/*
+	 * Split accesses into two to take advantage of the more
+	 * bandwidth-efficient 'Extended Register Read' command when possible
+	 */
+	while (addr <= 0xFF && val_size) {
+		len = min_t(size_t, val_size, 16);
+
+		err = spmi_ext_register_read(context, addr, val, len);
+		if (err)
+			goto err_out;
+
+		addr += len;
+		val += len;
+		val_size -= len;
+	}
+
+	while (val_size) {
+		len = min_t(size_t, val_size, 8);
+
+		err = spmi_ext_register_readl(context, addr, val, val_size);
+		if (err)
+			goto err_out;
+
+		addr += len;
+		val += len;
+		val_size -= len;
+	}
+
+err_out:
+	return err;
 }
 
-static int regmap_spmi_gather_write(void *context,
-				    const void *reg, size_t reg_size,
-				    const void *val, size_t val_size)
+static int regmap_spmi_ext_gather_write(void *context,
+					const void *reg, size_t reg_size,
+					const void *val, size_t val_size)
 {
+	int err = 0;
+	size_t len;
+	u16 addr;
+
 	BUG_ON(reg_size != 2);
-	return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size);
+
+	addr = *(u16 *)reg;
+
+	while (addr <= 0xFF && val_size) {
+		len = min_t(size_t, val_size, 16);
+
+		err = spmi_ext_register_write(context, addr, val, len);
+		if (err)
+			goto err_out;
+
+		addr += len;
+		val += len;
+		val_size -= len;
+	}
+
+	while (val_size) {
+		len = min_t(size_t, val_size, 8);
+
+		err = spmi_ext_register_writel(context, addr, val, len);
+		if (err)
+			goto err_out;
+
+		addr += len;
+		val += len;
+		val_size -= len;
+	}
+
+err_out:
+	return err;
 }
 
-static int regmap_spmi_write(void *context, const void *data,
-			     size_t count)
+static int regmap_spmi_ext_write(void *context, const void *data,
+				 size_t count)
 {
 	BUG_ON(count < 2);
-	return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2);
+	return regmap_spmi_ext_gather_write(context, data, 2, data + 2,
+					    count - 2);
 }
 
-static struct regmap_bus regmap_spmi = {
-	.read				= regmap_spmi_read,
-	.write				= regmap_spmi_write,
-	.gather_write			= regmap_spmi_gather_write,
+static struct regmap_bus regmap_spmi_ext = {
+	.read				= regmap_spmi_ext_read,
+	.write				= regmap_spmi_ext_write,
+	.gather_write			= regmap_spmi_ext_gather_write,
 	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
 	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
 };
 
 /**
- * regmap_init_spmi(): Initialize register map
- *
- * @sdev: Device that will be interacted with
- * @config: Configuration for register map
+ * regmap_init_spmi_ext(): Create regmap for Ext register space
+ * @sdev:	Device that will be interacted with
+ * @config:	Configuration for register map
  *
  * The return value will be an ERR_PTR() on error or a valid pointer to
  * a struct regmap.
  */
-struct regmap *regmap_init_spmi(struct spmi_device *sdev,
-				const struct regmap_config *config)
+struct regmap *regmap_init_spmi_ext(struct spmi_device *sdev,
+				    const struct regmap_config *config)
 {
-	return regmap_init(&sdev->dev, &regmap_spmi, sdev, config);
+	return regmap_init(&sdev->dev, &regmap_spmi_ext, sdev, config);
 }
-EXPORT_SYMBOL_GPL(regmap_init_spmi);
+EXPORT_SYMBOL_GPL(regmap_init_spmi_ext);
 
 /**
- * devm_regmap_init_spmi(): Initialise managed register map
- *
- * @sdev: Device that will be interacted with
- * @config: Configuration for register map
+ * devm_regmap_init_spmi_ext(): Create managed regmap for Ext register space
+ * @sdev:	SPMI device that will be interacted with
+ * @config:	Configuration for register map
  *
  * The return value will be an ERR_PTR() on error or a valid pointer
  * to a struct regmap.  The regmap will be automatically freed by the
  * device management code.
  */
-struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev,
+struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *sdev,
 				     const struct regmap_config *config)
 {
-	return devm_regmap_init(&sdev->dev, &regmap_spmi, sdev, config);
+	return devm_regmap_init(&sdev->dev, &regmap_spmi_ext, sdev, config);
 }
-EXPORT_SYMBOL_GPL(devm_regmap_init_spmi);
+EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_ext);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 6a19515f8a45..0e5c8338b8fc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -380,6 +380,28 @@ static void regmap_range_exit(struct regmap *map)
 	kfree(map->selector_work_buf);
 }
 
+int regmap_attach_dev(struct device *dev, struct regmap *map,
+		      const struct regmap_config *config)
+{
+	struct regmap **m;
+
+	map->dev = dev;
+
+	regmap_debugfs_init(map, config->name);
+
+	/* Add a devres resource for dev_get_regmap() */
+	m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
+	if (!m) {
+		regmap_debugfs_exit(map);
+		return -ENOMEM;
+	}
+	*m = map;
+	devres_add(dev, m);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(regmap_attach_dev);
+
 /**
  * regmap_init(): Initialise register map
  *
@@ -397,7 +419,7 @@ struct regmap *regmap_init(struct device *dev,
 			   void *bus_context,
 			   const struct regmap_config *config)
 {
-	struct regmap *map, **m;
+	struct regmap *map;
 	int ret = -EINVAL;
 	enum regmap_endian reg_endian, val_endian;
 	int i, j;
@@ -718,7 +740,7 @@ skip_format_initialization:
 		new->window_start = range_cfg->window_start;
 		new->window_len = range_cfg->window_len;
 
-		if (_regmap_range_add(map, new) == false) {
+		if (!_regmap_range_add(map, new)) {
 			dev_err(map->dev, "Failed to add range %d\n", i);
 			kfree(new);
 			goto err_range;
@@ -734,25 +756,18 @@ skip_format_initialization:
 		}
 	}
 
-	regmap_debugfs_init(map, config->name);
-
 	ret = regcache_init(map, config);
 	if (ret != 0)
 		goto err_range;
 
-	/* Add a devres resource for dev_get_regmap() */
-	m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
-	if (!m) {
-		ret = -ENOMEM;
-		goto err_debugfs;
-	}
-	*m = map;
-	devres_add(dev, m);
+	if (dev)
+		ret = regmap_attach_dev(dev, map, config);
+		if (ret != 0)
+			goto err_regcache;
 
 	return map;
 
-err_debugfs:
-	regmap_debugfs_exit(map);
+err_regcache:
 	regcache_exit(map);
 err_range:
 	regmap_range_exit(map);
@@ -1576,6 +1591,26 @@ out:
 }
 EXPORT_SYMBOL_GPL(regmap_bulk_write);
 
+static int _regmap_multi_reg_write(struct regmap *map,
+				   const struct reg_default *regs,
+				   int num_regs)
+{
+	int i, ret;
+
+	for (i = 0; i < num_regs; i++) {
+		if (regs[i].reg % map->reg_stride)
+			return -EINVAL;
+		ret = _regmap_write(map, regs[i].reg, regs[i].def);
+		if (ret != 0) {
+			dev_err(map->dev, "Failed to write %x = %x: %d\n",
+				regs[i].reg, regs[i].def, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * regmap_multi_reg_write(): Write multiple registers to the device
  *
@@ -1592,31 +1627,60 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
  */
-int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs,
-				int num_regs)
+int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
+			   int num_regs)
 {
-	int ret = 0, i;
-
-	for (i = 0; i < num_regs; i++) {
-		int reg = regs[i].reg;
-		if (reg % map->reg_stride)
-			return -EINVAL;
-	}
+	int ret;
 
 	map->lock(map->lock_arg);
 
-	for (i = 0; i < num_regs; i++) {
-		ret = _regmap_write(map, regs[i].reg, regs[i].def);
-		if (ret != 0)
-			goto out;
-	}
-out:
+	ret = _regmap_multi_reg_write(map, regs, num_regs);
+
 	map->unlock(map->lock_arg);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
 
+/*
+ * regmap_multi_reg_write_bypassed(): Write multiple registers to the
+ *                                    device but not the cache
+ *
+ * where the set of register are supplied in any order
+ *
+ * @map: Register map to write to
+ * @regs: Array of structures containing register,value to be written
+ * @num_regs: Number of registers to write
+ *
+ * This function is intended to be used for writing a large block of data
+ * atomically to the device in single transfer for those I2C client devices
+ * that implement this alternative block write mode.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_multi_reg_write_bypassed(struct regmap *map,
+				    const struct reg_default *regs,
+				    int num_regs)
+{
+	int ret;
+	bool bypass;
+
+	map->lock(map->lock_arg);
+
+	bypass = map->cache_bypass;
+	map->cache_bypass = true;
+
+	ret = _regmap_multi_reg_write(map, regs, num_regs);
+
+	map->cache_bypass = bypass;
+
+	map->unlock(map->lock_arg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed);
+
 /**
  * regmap_raw_write_async(): Write raw values to one or more registers
  *                           asynchronously
@@ -1736,6 +1800,9 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
 	if (map->cache_only)
 		return -EBUSY;
 
+	if (!regmap_readable(map, reg))
+		return -EIO;
+
 	ret = map->reg_read(context, reg, val);
 	if (ret == 0) {
 #ifdef LOG_DEVICE
@@ -1966,9 +2033,11 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
 
 	if (tmp != orig) {
 		ret = _regmap_write(map, reg, tmp);
-		*change = true;
+		if (change)
+			*change = true;
 	} else {
-		*change = false;
+		if (change)
+			*change = false;
 	}
 
 	return ret;
@@ -1987,11 +2056,10 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
 int regmap_update_bits(struct regmap *map, unsigned int reg,
 		       unsigned int mask, unsigned int val)
 {
-	bool change;
 	int ret;
 
 	map->lock(map->lock_arg);
-	ret = _regmap_update_bits(map, reg, mask, val, &change);
+	ret = _regmap_update_bits(map, reg, mask, val, NULL);
 	map->unlock(map->lock_arg);
 
 	return ret;
@@ -2016,14 +2084,13 @@ EXPORT_SYMBOL_GPL(regmap_update_bits);
 int regmap_update_bits_async(struct regmap *map, unsigned int reg,
 			     unsigned int mask, unsigned int val)
 {
-	bool change;
 	int ret;
 
 	map->lock(map->lock_arg);
 
 	map->async = true;
 
-	ret = _regmap_update_bits(map, reg, mask, val, &change);
+	ret = _regmap_update_bits(map, reg, mask, val, NULL);
 
 	map->async = false;
 
@@ -2178,7 +2245,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 			  int num_regs)
 {
 	struct reg_default *p;
-	int i, ret;
+	int ret;
 	bool bypass;
 
 	if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n",
@@ -2192,15 +2259,9 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 	map->cache_bypass = true;
 	map->async = true;
 
-	/* Write out first; it's useful to apply even if we fail later. */
-	for (i = 0; i < num_regs; i++) {
-		ret = _regmap_write(map, regs[i].reg, regs[i].def);
-		if (ret != 0) {
-			dev_err(map->dev, "Failed to write %x = %x: %d\n",
-				regs[i].reg, regs[i].def, ret);
-			goto out;
-		}
-	}
+	ret = _regmap_multi_reg_write(map, regs, num_regs);
+	if (ret != 0)
+		goto out;
 
 	p = krealloc(map->patch,
 		     sizeof(struct reg_default) * (map->patch_regs + num_regs),
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 94ffee378f10..ad9d17762664 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -23,7 +23,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-#include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index eb3950113e42..125d84505738 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -6411,12 +6411,12 @@ static bool DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
 					.ScatterGatherSegments[0]
 					.SegmentByteCount =
 	    CommandMailbox->ControllerInfo.DataTransferSize;
-	  DAC960_ExecuteCommand(Command);
-	  while (Controller->V2.NewControllerInformation->PhysicalScanActive)
-	    {
-	      DAC960_ExecuteCommand(Command);
-	      sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
-	    }
+	  while (1) {
+	    DAC960_ExecuteCommand(Command);
+	    if (!Controller->V2.NewControllerInformation->PhysicalScanActive)
+		break;
+	    msleep(1000);
+	  }
 	  DAC960_UserCritical("Discovery Completed\n", Controller);
  	}
     }
@@ -7035,18 +7035,16 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
 		ErrorCode = -EFAULT;
 		break;
 	}
-	while (Controller->V2.HealthStatusBuffer->StatusChangeCounter
-	       == HealthStatusBuffer.StatusChangeCounter &&
-	       Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
-	       == HealthStatusBuffer.NextEventSequenceNumber)
-	  {
-	    interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue,
-					   DAC960_MonitoringTimerInterval);
-	    if (signal_pending(current)) {
-	    	ErrorCode = -EINTR;
-	    	break;
-	    }
-	  }
+	ErrorCode = wait_event_interruptible_timeout(Controller->HealthStatusWaitQueue,
+			!(Controller->V2.HealthStatusBuffer->StatusChangeCounter
+			    == HealthStatusBuffer.StatusChangeCounter &&
+			  Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
+			    == HealthStatusBuffer.NextEventSequenceNumber),
+			DAC960_MonitoringTimerInterval);
+	if (ErrorCode == -ERESTARTSYS) {
+		ErrorCode = -EINTR;
+		break;
+	}
 	if (copy_to_user(GetHealthStatus.HealthStatusBuffer,
 			 Controller->V2.HealthStatusBuffer,
 			 sizeof(DAC960_V2_HealthStatusBuffer_T)))
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 8184451b57c0..422b7d84f686 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -874,7 +874,7 @@ bio_pageinc(struct bio *bio)
 		/* Non-zero page count for non-head members of
 		 * compound pages is no longer allowed by the kernel.
 		 */
-		page = compound_trans_head(bv.bv_page);
+		page = compound_head(bv.bv_page);
 		atomic_inc(&page->_count);
 	}
 }
@@ -887,7 +887,7 @@ bio_pagedec(struct bio *bio)
 	struct bvec_iter iter;
 
 	bio_for_each_segment(bv, bio, iter) {
-		page = compound_trans_head(bv.bv_page);
+		page = compound_head(bv.bv_page);
 		atomic_dec(&page->_count);
 	}
 }
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 0e30c6e5492a..96b629e1f0c9 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -68,6 +68,8 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/wait.h>
 
 #include <asm/atafd.h>
 #include <asm/atafdreg.h>
@@ -301,7 +303,7 @@ module_param_array(UserSteprate, int, NULL, 0);
 /* Synchronization of FDC access. */
 static volatile int fdc_busy = 0;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
-static DECLARE_WAIT_QUEUE_HEAD(format_wait);
+static DECLARE_COMPLETION(format_wait);
 
 static unsigned long changed_floppies = 0xff, fake_change = 0;
 #define	CHECK_CHANGE_DELAY	HZ/2
@@ -608,7 +610,7 @@ static void fd_error( void )
 	if (IsFormatting) {
 		IsFormatting = 0;
 		FormatError = 1;
-		wake_up( &format_wait );
+		complete(&format_wait);
 		return;
 	}
 
@@ -650,9 +652,8 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
 	DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
 		drive, desc->track, desc->head, desc->sect_offset ));
 
+	wait_event(fdc_wait, cmpxchg(&fdc_busy, 0, 1) == 0);
 	local_irq_save(flags);
-	while( fdc_busy ) sleep_on( &fdc_wait );
-	fdc_busy = 1;
 	stdma_lock(floppy_irq, NULL);
 	atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
 	local_irq_restore(flags);
@@ -706,7 +707,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
 	ReqSide  = desc->head;
 	do_fd_action( drive );
 
-	sleep_on( &format_wait );
+	wait_for_completion(&format_wait);
 
 	redo_fd_request();
 	return( FormatError ? -EIO : 0 );	
@@ -1229,7 +1230,7 @@ static void fd_writetrack_done( int status )
 		goto err_end;
 	}
 
-	wake_up( &format_wait );
+	complete(&format_wait);
 	return;
 
   err_end:
@@ -1497,8 +1498,7 @@ repeat:
 void do_fd_request(struct request_queue * q)
 {
 	DPRINT(("do_fd_request for pid %d\n",current->pid));
-	while( fdc_busy ) sleep_on( &fdc_wait );
-	fdc_busy = 1;
+	wait_event(fdc_wait, cmpxchg(&fdc_busy, 0, 1) == 0);
 	stdma_lock(floppy_irq, NULL);
 
 	atari_disable_irq( IRQ_MFP_FDC );
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index a9b13f2cc420..90ae4ba8f9ee 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -95,34 +95,36 @@ struct __packed al_transaction_on_disk {
 
 struct update_odbm_work {
 	struct drbd_work w;
+	struct drbd_device *device;
 	unsigned int enr;
 };
 
 struct update_al_work {
 	struct drbd_work w;
+	struct drbd_device *device;
 	struct completion event;
 	int err;
 };
 
 
-void *drbd_md_get_buffer(struct drbd_conf *mdev)
+void *drbd_md_get_buffer(struct drbd_device *device)
 {
 	int r;
 
-	wait_event(mdev->misc_wait,
-		   (r = atomic_cmpxchg(&mdev->md_io_in_use, 0, 1)) == 0 ||
-		   mdev->state.disk <= D_FAILED);
+	wait_event(device->misc_wait,
+		   (r = atomic_cmpxchg(&device->md_io_in_use, 0, 1)) == 0 ||
+		   device->state.disk <= D_FAILED);
 
-	return r ? NULL : page_address(mdev->md_io_page);
+	return r ? NULL : page_address(device->md_io_page);
 }
 
-void drbd_md_put_buffer(struct drbd_conf *mdev)
+void drbd_md_put_buffer(struct drbd_device *device)
 {
-	if (atomic_dec_and_test(&mdev->md_io_in_use))
-		wake_up(&mdev->misc_wait);
+	if (atomic_dec_and_test(&device->md_io_in_use))
+		wake_up(&device->misc_wait);
 }
 
-void wait_until_done_or_force_detached(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
+void wait_until_done_or_force_detached(struct drbd_device *device, struct drbd_backing_dev *bdev,
 				     unsigned int *done)
 {
 	long dt;
@@ -134,15 +136,15 @@ void wait_until_done_or_force_detached(struct drbd_conf *mdev, struct drbd_backi
 	if (dt == 0)
 		dt = MAX_SCHEDULE_TIMEOUT;
 
-	dt = wait_event_timeout(mdev->misc_wait,
-			*done || test_bit(FORCE_DETACH, &mdev->flags), dt);
+	dt = wait_event_timeout(device->misc_wait,
+			*done || test_bit(FORCE_DETACH, &device->flags), dt);
 	if (dt == 0) {
-		dev_err(DEV, "meta-data IO operation timed out\n");
-		drbd_chk_io_error(mdev, 1, DRBD_FORCE_DETACH);
+		drbd_err(device, "meta-data IO operation timed out\n");
+		drbd_chk_io_error(device, 1, DRBD_FORCE_DETACH);
 	}
 }
 
-static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
+static int _drbd_md_sync_page_io(struct drbd_device *device,
 				 struct drbd_backing_dev *bdev,
 				 struct page *page, sector_t sector,
 				 int rw, int size)
@@ -150,10 +152,10 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 	struct bio *bio;
 	int err;
 
-	mdev->md_io.done = 0;
-	mdev->md_io.error = -ENODEV;
+	device->md_io.done = 0;
+	device->md_io.error = -ENODEV;
 
-	if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags))
+	if ((rw & WRITE) && !test_bit(MD_NO_FUA, &device->flags))
 		rw |= REQ_FUA | REQ_FLUSH;
 	rw |= REQ_SYNC;
 
@@ -163,69 +165,69 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 	err = -EIO;
 	if (bio_add_page(bio, page, size, 0) != size)
 		goto out;
-	bio->bi_private = &mdev->md_io;
+	bio->bi_private = &device->md_io;
 	bio->bi_end_io = drbd_md_io_complete;
 	bio->bi_rw = rw;
 
-	if (!(rw & WRITE) && mdev->state.disk == D_DISKLESS && mdev->ldev == NULL)
+	if (!(rw & WRITE) && device->state.disk == D_DISKLESS && device->ldev == NULL)
 		/* special case, drbd_md_read() during drbd_adm_attach(): no get_ldev */
 		;
-	else if (!get_ldev_if_state(mdev, D_ATTACHING)) {
+	else if (!get_ldev_if_state(device, D_ATTACHING)) {
 		/* Corresponding put_ldev in drbd_md_io_complete() */
-		dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
+		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
 		err = -ENODEV;
 		goto out;
 	}
 
 	bio_get(bio); /* one bio_put() is in the completion handler */
-	atomic_inc(&mdev->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
-	if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
+	atomic_inc(&device->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
+	if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
 		bio_endio(bio, -EIO);
 	else
 		submit_bio(rw, bio);
-	wait_until_done_or_force_detached(mdev, bdev, &mdev->md_io.done);
+	wait_until_done_or_force_detached(device, bdev, &device->md_io.done);
 	if (bio_flagged(bio, BIO_UPTODATE))
-		err = mdev->md_io.error;
+		err = device->md_io.error;
 
  out:
 	bio_put(bio);
 	return err;
 }
 
-int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
+int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bdev,
 			 sector_t sector, int rw)
 {
 	int err;
-	struct page *iop = mdev->md_io_page;
+	struct page *iop = device->md_io_page;
 
-	D_ASSERT(atomic_read(&mdev->md_io_in_use) == 1);
+	D_ASSERT(device, atomic_read(&device->md_io_in_use) == 1);
 
 	BUG_ON(!bdev->md_bdev);
 
-	dev_dbg(DEV, "meta_data io: %s [%d]:%s(,%llus,%s) %pS\n",
+	drbd_dbg(device, "meta_data io: %s [%d]:%s(,%llus,%s) %pS\n",
 	     current->comm, current->pid, __func__,
 	     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ",
 	     (void*)_RET_IP_ );
 
 	if (sector < drbd_md_first_sector(bdev) ||
 	    sector + 7 > drbd_md_last_sector(bdev))
-		dev_alert(DEV, "%s [%d]:%s(,%llus,%s) out of range md access!\n",
+		drbd_alert(device, "%s [%d]:%s(,%llus,%s) out of range md access!\n",
 		     current->comm, current->pid, __func__,
 		     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
 
 	/* we do all our meta data IO in aligned 4k blocks. */
-	err = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, 4096);
+	err = _drbd_md_sync_page_io(device, bdev, iop, sector, rw, 4096);
 	if (err) {
-		dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
+		drbd_err(device, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
 		    (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err);
 	}
 	return err;
 }
 
-static struct bm_extent *find_active_resync_extent(struct drbd_conf *mdev, unsigned int enr)
+static struct bm_extent *find_active_resync_extent(struct drbd_device *device, unsigned int enr)
 {
 	struct lc_element *tmp;
-	tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
+	tmp = lc_find(device->resync, enr/AL_EXT_PER_BM_SECT);
 	if (unlikely(tmp != NULL)) {
 		struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
 		if (test_bit(BME_NO_WRITES, &bm_ext->flags))
@@ -234,47 +236,48 @@ static struct bm_extent *find_active_resync_extent(struct drbd_conf *mdev, unsig
 	return NULL;
 }
 
-static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr, bool nonblock)
+static struct lc_element *_al_get(struct drbd_device *device, unsigned int enr, bool nonblock)
 {
 	struct lc_element *al_ext;
 	struct bm_extent *bm_ext;
 	int wake;
 
-	spin_lock_irq(&mdev->al_lock);
-	bm_ext = find_active_resync_extent(mdev, enr);
+	spin_lock_irq(&device->al_lock);
+	bm_ext = find_active_resync_extent(device, enr);
 	if (bm_ext) {
 		wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
-		spin_unlock_irq(&mdev->al_lock);
+		spin_unlock_irq(&device->al_lock);
 		if (wake)
-			wake_up(&mdev->al_wait);
+			wake_up(&device->al_wait);
 		return NULL;
 	}
 	if (nonblock)
-		al_ext = lc_try_get(mdev->act_log, enr);
+		al_ext = lc_try_get(device->act_log, enr);
 	else
-		al_ext = lc_get(mdev->act_log, enr);
-	spin_unlock_irq(&mdev->al_lock);
+		al_ext = lc_get(device->act_log, enr);
+	spin_unlock_irq(&device->al_lock);
 	return al_ext;
 }
 
-bool drbd_al_begin_io_fastpath(struct drbd_conf *mdev, struct drbd_interval *i)
+bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i)
 {
 	/* for bios crossing activity log extent boundaries,
 	 * we may need to activate two extents in one go */
 	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
 	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
 
-	D_ASSERT((unsigned)(last - first) <= 1);
-	D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
+	D_ASSERT(device, (unsigned)(last - first) <= 1);
+	D_ASSERT(device, atomic_read(&device->local_cnt) > 0);
 
 	/* FIXME figure out a fast path for bios crossing AL extent boundaries */
 	if (first != last)
 		return false;
 
-	return _al_get(mdev, first, true);
+	return _al_get(device, first, true);
 }
 
-bool drbd_al_begin_io_prepare(struct drbd_conf *mdev, struct drbd_interval *i)
+static
+bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval *i)
 {
 	/* for bios crossing activity log extent boundaries,
 	 * we may need to activate two extents in one go */
@@ -283,20 +286,20 @@ bool drbd_al_begin_io_prepare(struct drbd_conf *mdev, struct drbd_interval *i)
 	unsigned enr;
 	bool need_transaction = false;
 
-	D_ASSERT(first <= last);
-	D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
+	D_ASSERT(device, first <= last);
+	D_ASSERT(device, atomic_read(&device->local_cnt) > 0);
 
 	for (enr = first; enr <= last; enr++) {
 		struct lc_element *al_ext;
-		wait_event(mdev->al_wait,
-				(al_ext = _al_get(mdev, enr, false)) != NULL);
+		wait_event(device->al_wait,
+				(al_ext = _al_get(device, enr, false)) != NULL);
 		if (al_ext->lc_number != enr)
 			need_transaction = true;
 	}
 	return need_transaction;
 }
 
-static int al_write_transaction(struct drbd_conf *mdev, bool delegate);
+static int al_write_transaction(struct drbd_device *device, bool delegate);
 
 /* When called through generic_make_request(), we must delegate
  * activity log I/O to the worker thread: a further request
@@ -310,58 +313,58 @@ static int al_write_transaction(struct drbd_conf *mdev, bool delegate);
 /*
  * @delegate:   delegate activity log I/O to the worker thread
  */
-void drbd_al_begin_io_commit(struct drbd_conf *mdev, bool delegate)
+void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
 {
 	bool locked = false;
 
-	BUG_ON(delegate && current == mdev->tconn->worker.task);
+	BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
 
 	/* Serialize multiple transactions.
 	 * This uses test_and_set_bit, memory barrier is implicit.
 	 */
-	wait_event(mdev->al_wait,
-			mdev->act_log->pending_changes == 0 ||
-			(locked = lc_try_lock_for_transaction(mdev->act_log)));
+	wait_event(device->al_wait,
+			device->act_log->pending_changes == 0 ||
+			(locked = lc_try_lock_for_transaction(device->act_log)));
 
 	if (locked) {
 		/* Double check: it may have been committed by someone else,
 		 * while we have been waiting for the lock. */
-		if (mdev->act_log->pending_changes) {
+		if (device->act_log->pending_changes) {
 			bool write_al_updates;
 
 			rcu_read_lock();
-			write_al_updates = rcu_dereference(mdev->ldev->disk_conf)->al_updates;
+			write_al_updates = rcu_dereference(device->ldev->disk_conf)->al_updates;
 			rcu_read_unlock();
 
 			if (write_al_updates)
-				al_write_transaction(mdev, delegate);
-			spin_lock_irq(&mdev->al_lock);
+				al_write_transaction(device, delegate);
+			spin_lock_irq(&device->al_lock);
 			/* FIXME
 			if (err)
 				we need an "lc_cancel" here;
 			*/
-			lc_committed(mdev->act_log);
-			spin_unlock_irq(&mdev->al_lock);
+			lc_committed(device->act_log);
+			spin_unlock_irq(&device->al_lock);
 		}
-		lc_unlock(mdev->act_log);
-		wake_up(&mdev->al_wait);
+		lc_unlock(device->act_log);
+		wake_up(&device->al_wait);
 	}
 }
 
 /*
  * @delegate:   delegate activity log I/O to the worker thread
  */
-void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate)
+void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate)
 {
-	BUG_ON(delegate && current == mdev->tconn->worker.task);
+	BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
 
-	if (drbd_al_begin_io_prepare(mdev, i))
-		drbd_al_begin_io_commit(mdev, delegate);
+	if (drbd_al_begin_io_prepare(device, i))
+		drbd_al_begin_io_commit(device, delegate);
 }
 
-int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i)
+int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
 {
-	struct lru_cache *al = mdev->act_log;
+	struct lru_cache *al = device->act_log;
 	/* for bios crossing activity log extent boundaries,
 	 * we may need to activate two extents in one go */
 	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
@@ -370,7 +373,7 @@ int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i)
 	unsigned available_update_slots;
 	unsigned enr;
 
-	D_ASSERT(first <= last);
+	D_ASSERT(device, first <= last);
 
 	nr_al_extents = 1 + last - first; /* worst case: all touched extends are cold. */
 	available_update_slots = min(al->nr_elements - al->used,
@@ -385,7 +388,7 @@ int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i)
 	/* Is resync active in this area? */
 	for (enr = first; enr <= last; enr++) {
 		struct lc_element *tmp;
-		tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
+		tmp = lc_find(device->resync, enr/AL_EXT_PER_BM_SECT);
 		if (unlikely(tmp != NULL)) {
 			struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
 			if (test_bit(BME_NO_WRITES, &bm_ext->flags)) {
@@ -401,14 +404,14 @@ int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i)
 	 * this has to be successful. */
 	for (enr = first; enr <= last; enr++) {
 		struct lc_element *al_ext;
-		al_ext = lc_get_cumulative(mdev->act_log, enr);
+		al_ext = lc_get_cumulative(device->act_log, enr);
 		if (!al_ext)
-			dev_info(DEV, "LOGIC BUG for enr=%u\n", enr);
+			drbd_info(device, "LOGIC BUG for enr=%u\n", enr);
 	}
 	return 0;
 }
 
-void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
+void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i)
 {
 	/* for bios crossing activity log extent boundaries,
 	 * we may need to activate two extents in one go */
@@ -418,19 +421,19 @@ void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
 	struct lc_element *extent;
 	unsigned long flags;
 
-	D_ASSERT(first <= last);
-	spin_lock_irqsave(&mdev->al_lock, flags);
+	D_ASSERT(device, first <= last);
+	spin_lock_irqsave(&device->al_lock, flags);
 
 	for (enr = first; enr <= last; enr++) {
-		extent = lc_find(mdev->act_log, enr);
+		extent = lc_find(device->act_log, enr);
 		if (!extent) {
-			dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr);
+			drbd_err(device, "al_complete_io() called on inactive extent %u\n", enr);
 			continue;
 		}
-		lc_put(mdev->act_log, extent);
+		lc_put(device->act_log, extent);
 	}
-	spin_unlock_irqrestore(&mdev->al_lock, flags);
-	wake_up(&mdev->al_wait);
+	spin_unlock_irqrestore(&device->al_lock, flags);
+	wake_up(&device->al_wait);
 }
 
 #if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)
@@ -460,13 +463,13 @@ static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
 		 (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
 }
 
-static sector_t al_tr_number_to_on_disk_sector(struct drbd_conf *mdev)
+static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device)
 {
-	const unsigned int stripes = mdev->ldev->md.al_stripes;
-	const unsigned int stripe_size_4kB = mdev->ldev->md.al_stripe_size_4k;
+	const unsigned int stripes = device->ldev->md.al_stripes;
+	const unsigned int stripe_size_4kB = device->ldev->md.al_stripe_size_4k;
 
 	/* transaction number, modulo on-disk ring buffer wrap around */
-	unsigned int t = mdev->al_tr_number % (mdev->ldev->md.al_size_4k);
+	unsigned int t = device->al_tr_number % (device->ldev->md.al_size_4k);
 
 	/* ... to aligned 4k on disk block */
 	t = ((t % stripes) * stripe_size_4kB) + t/stripes;
@@ -475,11 +478,11 @@ static sector_t al_tr_number_to_on_disk_sector(struct drbd_conf *mdev)
 	t *= 8;
 
 	/* ... plus offset to the on disk position */
-	return mdev->ldev->md.md_offset + mdev->ldev->md.al_offset + t;
+	return device->ldev->md.md_offset + device->ldev->md.al_offset + t;
 }
 
 static int
-_al_write_transaction(struct drbd_conf *mdev)
+_al_write_transaction(struct drbd_device *device)
 {
 	struct al_transaction_on_disk *buffer;
 	struct lc_element *e;
@@ -489,31 +492,31 @@ _al_write_transaction(struct drbd_conf *mdev)
 	unsigned crc = 0;
 	int err = 0;
 
-	if (!get_ldev(mdev)) {
-		dev_err(DEV, "disk is %s, cannot start al transaction\n",
-			drbd_disk_str(mdev->state.disk));
+	if (!get_ldev(device)) {
+		drbd_err(device, "disk is %s, cannot start al transaction\n",
+			drbd_disk_str(device->state.disk));
 		return -EIO;
 	}
 
 	/* The bitmap write may have failed, causing a state change. */
-	if (mdev->state.disk < D_INCONSISTENT) {
-		dev_err(DEV,
+	if (device->state.disk < D_INCONSISTENT) {
+		drbd_err(device,
 			"disk is %s, cannot write al transaction\n",
-			drbd_disk_str(mdev->state.disk));
-		put_ldev(mdev);
+			drbd_disk_str(device->state.disk));
+		put_ldev(device);
 		return -EIO;
 	}
 
-	buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */
+	buffer = drbd_md_get_buffer(device); /* protects md_io_buffer, al_tr_cycle, ... */
 	if (!buffer) {
-		dev_err(DEV, "disk failed while waiting for md_io buffer\n");
-		put_ldev(mdev);
+		drbd_err(device, "disk failed while waiting for md_io buffer\n");
+		put_ldev(device);
 		return -ENODEV;
 	}
 
 	memset(buffer, 0, sizeof(*buffer));
 	buffer->magic = cpu_to_be32(DRBD_AL_MAGIC);
-	buffer->tr_number = cpu_to_be32(mdev->al_tr_number);
+	buffer->tr_number = cpu_to_be32(device->al_tr_number);
 
 	i = 0;
 
@@ -521,8 +524,8 @@ _al_write_transaction(struct drbd_conf *mdev)
 	 * once we set the LC_LOCKED -- from drbd_al_begin_io(),
 	 * lc_try_lock_for_transaction() --, someone may still
 	 * be in the process of changing it. */
-	spin_lock_irq(&mdev->al_lock);
-	list_for_each_entry(e, &mdev->act_log->to_be_changed, list) {
+	spin_lock_irq(&device->al_lock);
+	list_for_each_entry(e, &device->act_log->to_be_changed, list) {
 		if (i == AL_UPDATES_PER_TRANSACTION) {
 			i++;
 			break;
@@ -530,11 +533,11 @@ _al_write_transaction(struct drbd_conf *mdev)
 		buffer->update_slot_nr[i] = cpu_to_be16(e->lc_index);
 		buffer->update_extent_nr[i] = cpu_to_be32(e->lc_new_number);
 		if (e->lc_number != LC_FREE)
-			drbd_bm_mark_for_writeout(mdev,
+			drbd_bm_mark_for_writeout(device,
 					al_extent_to_bm_page(e->lc_number));
 		i++;
 	}
-	spin_unlock_irq(&mdev->al_lock);
+	spin_unlock_irq(&device->al_lock);
 	BUG_ON(i > AL_UPDATES_PER_TRANSACTION);
 
 	buffer->n_updates = cpu_to_be16(i);
@@ -543,48 +546,48 @@ _al_write_transaction(struct drbd_conf *mdev)
 		buffer->update_extent_nr[i] = cpu_to_be32(LC_FREE);
 	}
 
-	buffer->context_size = cpu_to_be16(mdev->act_log->nr_elements);
-	buffer->context_start_slot_nr = cpu_to_be16(mdev->al_tr_cycle);
+	buffer->context_size = cpu_to_be16(device->act_log->nr_elements);
+	buffer->context_start_slot_nr = cpu_to_be16(device->al_tr_cycle);
 
 	mx = min_t(int, AL_CONTEXT_PER_TRANSACTION,
-		   mdev->act_log->nr_elements - mdev->al_tr_cycle);
+		   device->act_log->nr_elements - device->al_tr_cycle);
 	for (i = 0; i < mx; i++) {
-		unsigned idx = mdev->al_tr_cycle + i;
-		extent_nr = lc_element_by_index(mdev->act_log, idx)->lc_number;
+		unsigned idx = device->al_tr_cycle + i;
+		extent_nr = lc_element_by_index(device->act_log, idx)->lc_number;
 		buffer->context[i] = cpu_to_be32(extent_nr);
 	}
 	for (; i < AL_CONTEXT_PER_TRANSACTION; i++)
 		buffer->context[i] = cpu_to_be32(LC_FREE);
 
-	mdev->al_tr_cycle += AL_CONTEXT_PER_TRANSACTION;
-	if (mdev->al_tr_cycle >= mdev->act_log->nr_elements)
-		mdev->al_tr_cycle = 0;
+	device->al_tr_cycle += AL_CONTEXT_PER_TRANSACTION;
+	if (device->al_tr_cycle >= device->act_log->nr_elements)
+		device->al_tr_cycle = 0;
 
-	sector = al_tr_number_to_on_disk_sector(mdev);
+	sector = al_tr_number_to_on_disk_sector(device);
 
 	crc = crc32c(0, buffer, 4096);
 	buffer->crc32c = cpu_to_be32(crc);
 
-	if (drbd_bm_write_hinted(mdev))
+	if (drbd_bm_write_hinted(device))
 		err = -EIO;
 	else {
 		bool write_al_updates;
 		rcu_read_lock();
-		write_al_updates = rcu_dereference(mdev->ldev->disk_conf)->al_updates;
+		write_al_updates = rcu_dereference(device->ldev->disk_conf)->al_updates;
 		rcu_read_unlock();
 		if (write_al_updates) {
-			if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
+			if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) {
 				err = -EIO;
-				drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+				drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
 			} else {
-				mdev->al_tr_number++;
-				mdev->al_writ_cnt++;
+				device->al_tr_number++;
+				device->al_writ_cnt++;
 			}
 		}
 	}
 
-	drbd_md_put_buffer(mdev);
-	put_ldev(mdev);
+	drbd_md_put_buffer(device);
+	put_ldev(device);
 
 	return err;
 }
@@ -593,10 +596,10 @@ _al_write_transaction(struct drbd_conf *mdev)
 static int w_al_write_transaction(struct drbd_work *w, int unused)
 {
 	struct update_al_work *aw = container_of(w, struct update_al_work, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device = aw->device;
 	int err;
 
-	err = _al_write_transaction(mdev);
+	err = _al_write_transaction(device);
 	aw->err = err;
 	complete(&aw->event);
 
@@ -606,63 +609,64 @@ static int w_al_write_transaction(struct drbd_work *w, int unused)
 /* Calls from worker context (see w_restart_disk_io()) need to write the
    transaction directly. Others came through generic_make_request(),
    those need to delegate it to the worker. */
-static int al_write_transaction(struct drbd_conf *mdev, bool delegate)
+static int al_write_transaction(struct drbd_device *device, bool delegate)
 {
 	if (delegate) {
 		struct update_al_work al_work;
 		init_completion(&al_work.event);
 		al_work.w.cb = w_al_write_transaction;
-		al_work.w.mdev = mdev;
-		drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
+		al_work.device = device;
+		drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
+				      &al_work.w);
 		wait_for_completion(&al_work.event);
 		return al_work.err;
 	} else
-		return _al_write_transaction(mdev);
+		return _al_write_transaction(device);
 }
 
-static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
+static int _try_lc_del(struct drbd_device *device, struct lc_element *al_ext)
 {
 	int rv;
 
-	spin_lock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
 	rv = (al_ext->refcnt == 0);
 	if (likely(rv))
-		lc_del(mdev->act_log, al_ext);
-	spin_unlock_irq(&mdev->al_lock);
+		lc_del(device->act_log, al_ext);
+	spin_unlock_irq(&device->al_lock);
 
 	return rv;
 }
 
 /**
  * drbd_al_shrink() - Removes all active extents form the activity log
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Removes all active extents form the activity log, waiting until
  * the reference count of each entry dropped to 0 first, of course.
  *
- * You need to lock mdev->act_log with lc_try_lock() / lc_unlock()
+ * You need to lock device->act_log with lc_try_lock() / lc_unlock()
  */
-void drbd_al_shrink(struct drbd_conf *mdev)
+void drbd_al_shrink(struct drbd_device *device)
 {
 	struct lc_element *al_ext;
 	int i;
 
-	D_ASSERT(test_bit(__LC_LOCKED, &mdev->act_log->flags));
+	D_ASSERT(device, test_bit(__LC_LOCKED, &device->act_log->flags));
 
-	for (i = 0; i < mdev->act_log->nr_elements; i++) {
-		al_ext = lc_element_by_index(mdev->act_log, i);
+	for (i = 0; i < device->act_log->nr_elements; i++) {
+		al_ext = lc_element_by_index(device->act_log, i);
 		if (al_ext->lc_number == LC_FREE)
 			continue;
-		wait_event(mdev->al_wait, _try_lc_del(mdev, al_ext));
+		wait_event(device->al_wait, _try_lc_del(device, al_ext));
 	}
 
-	wake_up(&mdev->al_wait);
+	wake_up(&device->al_wait);
 }
 
-int drbd_initialize_al(struct drbd_conf *mdev, void *buffer)
+int drbd_initialize_al(struct drbd_device *device, void *buffer)
 {
 	struct al_transaction_on_disk *al = buffer;
-	struct drbd_md *md = &mdev->ldev->md;
+	struct drbd_md *md = &device->ldev->md;
 	sector_t al_base = md->md_offset + md->al_offset;
 	int al_size_4k = md->al_stripes * md->al_stripe_size_4k;
 	int i;
@@ -673,7 +677,7 @@ int drbd_initialize_al(struct drbd_conf *mdev, void *buffer)
 	al->crc32c = cpu_to_be32(crc32c(0, al, 4096));
 
 	for (i = 0; i < al_size_4k; i++) {
-		int err = drbd_md_sync_page_io(mdev, mdev->ldev, al_base + i * 8, WRITE);
+		int err = drbd_md_sync_page_io(device, device->ldev, al_base + i * 8, WRITE);
 		if (err)
 			return err;
 	}
@@ -683,32 +687,32 @@ int drbd_initialize_al(struct drbd_conf *mdev, void *buffer)
 static int w_update_odbm(struct drbd_work *w, int unused)
 {
 	struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device = udw->device;
 	struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
 
-	if (!get_ldev(mdev)) {
+	if (!get_ldev(device)) {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_warn(DEV, "Can not update on disk bitmap, local IO disabled.\n");
+			drbd_warn(device, "Can not update on disk bitmap, local IO disabled.\n");
 		kfree(udw);
 		return 0;
 	}
 
-	drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr));
-	put_ldev(mdev);
+	drbd_bm_write_page(device, rs_extent_to_bm_page(udw->enr));
+	put_ldev(device);
 
 	kfree(udw);
 
-	if (drbd_bm_total_weight(mdev) <= mdev->rs_failed) {
-		switch (mdev->state.conn) {
+	if (drbd_bm_total_weight(device) <= device->rs_failed) {
+		switch (device->state.conn) {
 		case C_SYNC_SOURCE:  case C_SYNC_TARGET:
 		case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_T:
-			drbd_resync_finished(mdev);
+			drbd_resync_finished(device);
 		default:
 			/* nothing to do */
 			break;
 		}
 	}
-	drbd_bcast_event(mdev, &sib);
+	drbd_bcast_event(device, &sib);
 
 	return 0;
 }
@@ -720,7 +724,7 @@ static int w_update_odbm(struct drbd_work *w, int unused)
  *
  * TODO will be obsoleted once we have a caching lru of the on disk bitmap
  */
-static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
+static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t sector,
 				      int count, int success)
 {
 	struct lc_element *e;
@@ -728,13 +732,13 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 
 	unsigned int enr;
 
-	D_ASSERT(atomic_read(&mdev->local_cnt));
+	D_ASSERT(device, atomic_read(&device->local_cnt));
 
 	/* I simply assume that a sector/size pair never crosses
 	 * a 16 MB extent border. (Currently this is true...) */
 	enr = BM_SECT_TO_EXT(sector);
 
-	e = lc_get(mdev->resync, enr);
+	e = lc_get(device->resync, enr);
 	if (e) {
 		struct bm_extent *ext = lc_entry(e, struct bm_extent, lce);
 		if (ext->lce.lc_number == enr) {
@@ -743,12 +747,12 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			else
 				ext->rs_failed += count;
 			if (ext->rs_left < ext->rs_failed) {
-				dev_warn(DEV, "BAD! sector=%llus enr=%u rs_left=%d "
+				drbd_warn(device, "BAD! sector=%llus enr=%u rs_left=%d "
 				    "rs_failed=%d count=%d cstate=%s\n",
 				     (unsigned long long)sector,
 				     ext->lce.lc_number, ext->rs_left,
 				     ext->rs_failed, count,
-				     drbd_conn_str(mdev->state.conn));
+				     drbd_conn_str(device->state.conn));
 
 				/* We don't expect to be able to clear more bits
 				 * than have been set when we originally counted
@@ -756,7 +760,7 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 				 * Whatever the reason (disconnect during resync,
 				 * delayed local completion of an application write),
 				 * try to fix it up by recounting here. */
-				ext->rs_left = drbd_bm_e_weight(mdev, enr);
+				ext->rs_left = drbd_bm_e_weight(device, enr);
 			}
 		} else {
 			/* Normally this element should be in the cache,
@@ -765,16 +769,16 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			 * But maybe an application write finished, and we set
 			 * something outside the resync lru_cache in sync.
 			 */
-			int rs_left = drbd_bm_e_weight(mdev, enr);
+			int rs_left = drbd_bm_e_weight(device, enr);
 			if (ext->flags != 0) {
-				dev_warn(DEV, "changing resync lce: %d[%u;%02lx]"
+				drbd_warn(device, "changing resync lce: %d[%u;%02lx]"
 				     " -> %d[%u;00]\n",
 				     ext->lce.lc_number, ext->rs_left,
 				     ext->flags, enr, rs_left);
 				ext->flags = 0;
 			}
 			if (ext->rs_failed) {
-				dev_warn(DEV, "Kicking resync_lru element enr=%u "
+				drbd_warn(device, "Kicking resync_lru element enr=%u "
 				     "out with rs_failed=%d\n",
 				     ext->lce.lc_number, ext->rs_failed);
 			}
@@ -782,9 +786,9 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			ext->rs_failed = success ? 0 : count;
 			/* we don't keep a persistent log of the resync lru,
 			 * we can commit any change right away. */
-			lc_committed(mdev->resync);
+			lc_committed(device->resync);
 		}
-		lc_put(mdev->resync, &ext->lce);
+		lc_put(device->resync, &ext->lce);
 		/* no race, we are within the al_lock! */
 
 		if (ext->rs_left == ext->rs_failed) {
@@ -794,32 +798,33 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			if (udw) {
 				udw->enr = ext->lce.lc_number;
 				udw->w.cb = w_update_odbm;
-				udw->w.mdev = mdev;
-				drbd_queue_work_front(&mdev->tconn->sender_work, &udw->w);
+				udw->device = device;
+				drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
+						      &udw->w);
 			} else {
-				dev_warn(DEV, "Could not kmalloc an udw\n");
+				drbd_warn(device, "Could not kmalloc an udw\n");
 			}
 		}
 	} else {
-		dev_err(DEV, "lc_get() failed! locked=%d/%d flags=%lu\n",
-		    mdev->resync_locked,
-		    mdev->resync->nr_elements,
-		    mdev->resync->flags);
+		drbd_err(device, "lc_get() failed! locked=%d/%d flags=%lu\n",
+		    device->resync_locked,
+		    device->resync->nr_elements,
+		    device->resync->flags);
 	}
 }
 
-void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go)
+void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go)
 {
 	unsigned long now = jiffies;
-	unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
-	int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+	unsigned long last = device->rs_mark_time[device->rs_last_mark];
+	int next = (device->rs_last_mark + 1) % DRBD_SYNC_MARKS;
 	if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
-		if (mdev->rs_mark_left[mdev->rs_last_mark] != still_to_go &&
-		    mdev->state.conn != C_PAUSED_SYNC_T &&
-		    mdev->state.conn != C_PAUSED_SYNC_S) {
-			mdev->rs_mark_time[next] = now;
-			mdev->rs_mark_left[next] = still_to_go;
-			mdev->rs_last_mark = next;
+		if (device->rs_mark_left[device->rs_last_mark] != still_to_go &&
+		    device->state.conn != C_PAUSED_SYNC_T &&
+		    device->state.conn != C_PAUSED_SYNC_S) {
+			device->rs_mark_time[next] = now;
+			device->rs_mark_left[next] = still_to_go;
+			device->rs_last_mark = next;
 		}
 	}
 }
@@ -831,7 +836,7 @@ void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go)
  * called by worker on C_SYNC_TARGET and receiver on SyncSource.
  *
  */
-void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
+void __drbd_set_in_sync(struct drbd_device *device, sector_t sector, int size,
 		       const char *file, const unsigned int line)
 {
 	/* Is called from worker and receiver context _only_ */
@@ -842,15 +847,15 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	unsigned long flags;
 
 	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
-		dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
+		drbd_err(device, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
 	}
 
-	if (!get_ldev(mdev))
+	if (!get_ldev(device))
 		return; /* no disk, no metadata, no bitmap to clear bits in */
 
-	nr_sectors = drbd_get_capacity(mdev->this_bdev);
+	nr_sectors = drbd_get_capacity(device->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
 	if (!expect(sector < nr_sectors))
@@ -878,21 +883,21 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	 * ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.
 	 */
-	count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
+	count = drbd_bm_clear_bits(device, sbnr, ebnr);
 	if (count) {
-		drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev));
-		spin_lock_irqsave(&mdev->al_lock, flags);
-		drbd_try_clear_on_disk_bm(mdev, sector, count, true);
-		spin_unlock_irqrestore(&mdev->al_lock, flags);
+		drbd_advance_rs_marks(device, drbd_bm_total_weight(device));
+		spin_lock_irqsave(&device->al_lock, flags);
+		drbd_try_clear_on_disk_bm(device, sector, count, true);
+		spin_unlock_irqrestore(&device->al_lock, flags);
 
 		/* just wake_up unconditional now, various lc_chaged(),
 		 * lc_put() in drbd_try_clear_on_disk_bm(). */
 		wake_up = 1;
 	}
 out:
-	put_ldev(mdev);
+	put_ldev(device);
 	if (wake_up)
-		wake_up(&mdev->al_wait);
+		wake_up(&device->al_wait);
 }
 
 /*
@@ -903,7 +908,7 @@ out:
  * called by tl_clear and drbd_send_dblock (==drbd_make_request).
  * so this can be _any_ process.
  */
-int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
+int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector, int size,
 			    const char *file, const unsigned int line)
 {
 	unsigned long sbnr, ebnr, flags;
@@ -916,15 +921,15 @@ int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 		return 0;
 
 	if (size < 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
-		dev_err(DEV, "sector: %llus, size: %d\n",
+		drbd_err(device, "sector: %llus, size: %d\n",
 			(unsigned long long)sector, size);
 		return 0;
 	}
 
-	if (!get_ldev(mdev))
+	if (!get_ldev(device))
 		return 0; /* no disk, no metadata, no bitmap to set bits in */
 
-	nr_sectors = drbd_get_capacity(mdev->this_bdev);
+	nr_sectors = drbd_get_capacity(device->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
 	if (!expect(sector < nr_sectors))
@@ -939,55 +944,55 @@ int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 
 	/* ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.  */
-	spin_lock_irqsave(&mdev->al_lock, flags);
-	count = drbd_bm_set_bits(mdev, sbnr, ebnr);
+	spin_lock_irqsave(&device->al_lock, flags);
+	count = drbd_bm_set_bits(device, sbnr, ebnr);
 
 	enr = BM_SECT_TO_EXT(sector);
-	e = lc_find(mdev->resync, enr);
+	e = lc_find(device->resync, enr);
 	if (e)
 		lc_entry(e, struct bm_extent, lce)->rs_left += count;
-	spin_unlock_irqrestore(&mdev->al_lock, flags);
+	spin_unlock_irqrestore(&device->al_lock, flags);
 
 out:
-	put_ldev(mdev);
+	put_ldev(device);
 
 	return count;
 }
 
 static
-struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr)
+struct bm_extent *_bme_get(struct drbd_device *device, unsigned int enr)
 {
 	struct lc_element *e;
 	struct bm_extent *bm_ext;
 	int wakeup = 0;
 	unsigned long rs_flags;
 
-	spin_lock_irq(&mdev->al_lock);
-	if (mdev->resync_locked > mdev->resync->nr_elements/2) {
-		spin_unlock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
+	if (device->resync_locked > device->resync->nr_elements/2) {
+		spin_unlock_irq(&device->al_lock);
 		return NULL;
 	}
-	e = lc_get(mdev->resync, enr);
+	e = lc_get(device->resync, enr);
 	bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
 	if (bm_ext) {
 		if (bm_ext->lce.lc_number != enr) {
-			bm_ext->rs_left = drbd_bm_e_weight(mdev, enr);
+			bm_ext->rs_left = drbd_bm_e_weight(device, enr);
 			bm_ext->rs_failed = 0;
-			lc_committed(mdev->resync);
+			lc_committed(device->resync);
 			wakeup = 1;
 		}
 		if (bm_ext->lce.refcnt == 1)
-			mdev->resync_locked++;
+			device->resync_locked++;
 		set_bit(BME_NO_WRITES, &bm_ext->flags);
 	}
-	rs_flags = mdev->resync->flags;
-	spin_unlock_irq(&mdev->al_lock);
+	rs_flags = device->resync->flags;
+	spin_unlock_irq(&device->al_lock);
 	if (wakeup)
-		wake_up(&mdev->al_wait);
+		wake_up(&device->al_wait);
 
 	if (!bm_ext) {
 		if (rs_flags & LC_STARVING)
-			dev_warn(DEV, "Have to wait for element"
+			drbd_warn(device, "Have to wait for element"
 			     " (resync LRU too small?)\n");
 		BUG_ON(rs_flags & LC_LOCKED);
 	}
@@ -995,25 +1000,25 @@ struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr)
 	return bm_ext;
 }
 
-static int _is_in_al(struct drbd_conf *mdev, unsigned int enr)
+static int _is_in_al(struct drbd_device *device, unsigned int enr)
 {
 	int rv;
 
-	spin_lock_irq(&mdev->al_lock);
-	rv = lc_is_used(mdev->act_log, enr);
-	spin_unlock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
+	rv = lc_is_used(device->act_log, enr);
+	spin_unlock_irq(&device->al_lock);
 
 	return rv;
 }
 
 /**
  * drbd_rs_begin_io() - Gets an extent in the resync LRU cache and sets it to BME_LOCKED
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @sector:	The sector number.
  *
  * This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
  */
-int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
+int drbd_rs_begin_io(struct drbd_device *device, sector_t sector)
 {
 	unsigned int enr = BM_SECT_TO_EXT(sector);
 	struct bm_extent *bm_ext;
@@ -1022,8 +1027,8 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 			 200 times -> 20 seconds. */
 
 retry:
-	sig = wait_event_interruptible(mdev->al_wait,
-			(bm_ext = _bme_get(mdev, enr)));
+	sig = wait_event_interruptible(device->al_wait,
+			(bm_ext = _bme_get(device, enr)));
 	if (sig)
 		return -EINTR;
 
@@ -1031,24 +1036,24 @@ retry:
 		return 0;
 
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
-		sig = wait_event_interruptible(mdev->al_wait,
-					       !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i) ||
+		sig = wait_event_interruptible(device->al_wait,
+					       !_is_in_al(device, enr * AL_EXT_PER_BM_SECT + i) ||
 					       test_bit(BME_PRIORITY, &bm_ext->flags));
 
 		if (sig || (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)) {
-			spin_lock_irq(&mdev->al_lock);
-			if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
+			spin_lock_irq(&device->al_lock);
+			if (lc_put(device->resync, &bm_ext->lce) == 0) {
 				bm_ext->flags = 0; /* clears BME_NO_WRITES and eventually BME_PRIORITY */
-				mdev->resync_locked--;
-				wake_up(&mdev->al_wait);
+				device->resync_locked--;
+				wake_up(&device->al_wait);
 			}
-			spin_unlock_irq(&mdev->al_lock);
+			spin_unlock_irq(&device->al_lock);
 			if (sig)
 				return -EINTR;
 			if (schedule_timeout_interruptible(HZ/10))
 				return -EINTR;
 			if (sa && --sa == 0)
-				dev_warn(DEV,"drbd_rs_begin_io() stepped aside for 20sec."
+				drbd_warn(device, "drbd_rs_begin_io() stepped aside for 20sec."
 					 "Resync stalled?\n");
 			goto retry;
 		}
@@ -1059,14 +1064,14 @@ retry:
 
 /**
  * drbd_try_rs_begin_io() - Gets an extent in the resync LRU cache, does not sleep
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @sector:	The sector number.
  *
  * Gets an extent in the resync LRU cache, sets it to BME_NO_WRITES, then
  * tries to set it to BME_LOCKED. Returns 0 upon success, and -EAGAIN
  * if there is still application IO going on in this area.
  */
-int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
+int drbd_try_rs_begin_io(struct drbd_device *device, sector_t sector)
 {
 	unsigned int enr = BM_SECT_TO_EXT(sector);
 	const unsigned int al_enr = enr*AL_EXT_PER_BM_SECT;
@@ -1074,8 +1079,8 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 	struct bm_extent *bm_ext;
 	int i;
 
-	spin_lock_irq(&mdev->al_lock);
-	if (mdev->resync_wenr != LC_FREE && mdev->resync_wenr != enr) {
+	spin_lock_irq(&device->al_lock);
+	if (device->resync_wenr != LC_FREE && device->resync_wenr != enr) {
 		/* in case you have very heavy scattered io, it may
 		 * stall the syncer undefined if we give up the ref count
 		 * when we try again and requeue.
@@ -1089,193 +1094,193 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 		 * the lc_put here...
 		 * we also have to wake_up
 		 */
-		e = lc_find(mdev->resync, mdev->resync_wenr);
+		e = lc_find(device->resync, device->resync_wenr);
 		bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
 		if (bm_ext) {
-			D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags));
-			D_ASSERT(test_bit(BME_NO_WRITES, &bm_ext->flags));
+			D_ASSERT(device, !test_bit(BME_LOCKED, &bm_ext->flags));
+			D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
 			clear_bit(BME_NO_WRITES, &bm_ext->flags);
-			mdev->resync_wenr = LC_FREE;
-			if (lc_put(mdev->resync, &bm_ext->lce) == 0)
-				mdev->resync_locked--;
-			wake_up(&mdev->al_wait);
+			device->resync_wenr = LC_FREE;
+			if (lc_put(device->resync, &bm_ext->lce) == 0)
+				device->resync_locked--;
+			wake_up(&device->al_wait);
 		} else {
-			dev_alert(DEV, "LOGIC BUG\n");
+			drbd_alert(device, "LOGIC BUG\n");
 		}
 	}
 	/* TRY. */
-	e = lc_try_get(mdev->resync, enr);
+	e = lc_try_get(device->resync, enr);
 	bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
 	if (bm_ext) {
 		if (test_bit(BME_LOCKED, &bm_ext->flags))
 			goto proceed;
 		if (!test_and_set_bit(BME_NO_WRITES, &bm_ext->flags)) {
-			mdev->resync_locked++;
+			device->resync_locked++;
 		} else {
 			/* we did set the BME_NO_WRITES,
 			 * but then could not set BME_LOCKED,
 			 * so we tried again.
 			 * drop the extra reference. */
 			bm_ext->lce.refcnt--;
-			D_ASSERT(bm_ext->lce.refcnt > 0);
+			D_ASSERT(device, bm_ext->lce.refcnt > 0);
 		}
 		goto check_al;
 	} else {
 		/* do we rather want to try later? */
-		if (mdev->resync_locked > mdev->resync->nr_elements-3)
+		if (device->resync_locked > device->resync->nr_elements-3)
 			goto try_again;
 		/* Do or do not. There is no try. -- Yoda */
-		e = lc_get(mdev->resync, enr);
+		e = lc_get(device->resync, enr);
 		bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
 		if (!bm_ext) {
-			const unsigned long rs_flags = mdev->resync->flags;
+			const unsigned long rs_flags = device->resync->flags;
 			if (rs_flags & LC_STARVING)
-				dev_warn(DEV, "Have to wait for element"
+				drbd_warn(device, "Have to wait for element"
 				     " (resync LRU too small?)\n");
 			BUG_ON(rs_flags & LC_LOCKED);
 			goto try_again;
 		}
 		if (bm_ext->lce.lc_number != enr) {
-			bm_ext->rs_left = drbd_bm_e_weight(mdev, enr);
+			bm_ext->rs_left = drbd_bm_e_weight(device, enr);
 			bm_ext->rs_failed = 0;
-			lc_committed(mdev->resync);
-			wake_up(&mdev->al_wait);
-			D_ASSERT(test_bit(BME_LOCKED, &bm_ext->flags) == 0);
+			lc_committed(device->resync);
+			wake_up(&device->al_wait);
+			D_ASSERT(device, test_bit(BME_LOCKED, &bm_ext->flags) == 0);
 		}
 		set_bit(BME_NO_WRITES, &bm_ext->flags);
-		D_ASSERT(bm_ext->lce.refcnt == 1);
-		mdev->resync_locked++;
+		D_ASSERT(device, bm_ext->lce.refcnt == 1);
+		device->resync_locked++;
 		goto check_al;
 	}
 check_al:
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
-		if (lc_is_used(mdev->act_log, al_enr+i))
+		if (lc_is_used(device->act_log, al_enr+i))
 			goto try_again;
 	}
 	set_bit(BME_LOCKED, &bm_ext->flags);
 proceed:
-	mdev->resync_wenr = LC_FREE;
-	spin_unlock_irq(&mdev->al_lock);
+	device->resync_wenr = LC_FREE;
+	spin_unlock_irq(&device->al_lock);
 	return 0;
 
 try_again:
 	if (bm_ext)
-		mdev->resync_wenr = enr;
-	spin_unlock_irq(&mdev->al_lock);
+		device->resync_wenr = enr;
+	spin_unlock_irq(&device->al_lock);
 	return -EAGAIN;
 }
 
-void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector)
+void drbd_rs_complete_io(struct drbd_device *device, sector_t sector)
 {
 	unsigned int enr = BM_SECT_TO_EXT(sector);
 	struct lc_element *e;
 	struct bm_extent *bm_ext;
 	unsigned long flags;
 
-	spin_lock_irqsave(&mdev->al_lock, flags);
-	e = lc_find(mdev->resync, enr);
+	spin_lock_irqsave(&device->al_lock, flags);
+	e = lc_find(device->resync, enr);
 	bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
 	if (!bm_ext) {
-		spin_unlock_irqrestore(&mdev->al_lock, flags);
+		spin_unlock_irqrestore(&device->al_lock, flags);
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "drbd_rs_complete_io() called, but extent not found\n");
+			drbd_err(device, "drbd_rs_complete_io() called, but extent not found\n");
 		return;
 	}
 
 	if (bm_ext->lce.refcnt == 0) {
-		spin_unlock_irqrestore(&mdev->al_lock, flags);
-		dev_err(DEV, "drbd_rs_complete_io(,%llu [=%u]) called, "
+		spin_unlock_irqrestore(&device->al_lock, flags);
+		drbd_err(device, "drbd_rs_complete_io(,%llu [=%u]) called, "
 		    "but refcnt is 0!?\n",
 		    (unsigned long long)sector, enr);
 		return;
 	}
 
-	if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
+	if (lc_put(device->resync, &bm_ext->lce) == 0) {
 		bm_ext->flags = 0; /* clear BME_LOCKED, BME_NO_WRITES and BME_PRIORITY */
-		mdev->resync_locked--;
-		wake_up(&mdev->al_wait);
+		device->resync_locked--;
+		wake_up(&device->al_wait);
 	}
 
-	spin_unlock_irqrestore(&mdev->al_lock, flags);
+	spin_unlock_irqrestore(&device->al_lock, flags);
 }
 
 /**
  * drbd_rs_cancel_all() - Removes all extents from the resync LRU (even BME_LOCKED)
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  */
-void drbd_rs_cancel_all(struct drbd_conf *mdev)
+void drbd_rs_cancel_all(struct drbd_device *device)
 {
-	spin_lock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
 
-	if (get_ldev_if_state(mdev, D_FAILED)) { /* Makes sure ->resync is there. */
-		lc_reset(mdev->resync);
-		put_ldev(mdev);
+	if (get_ldev_if_state(device, D_FAILED)) { /* Makes sure ->resync is there. */
+		lc_reset(device->resync);
+		put_ldev(device);
 	}
-	mdev->resync_locked = 0;
-	mdev->resync_wenr = LC_FREE;
-	spin_unlock_irq(&mdev->al_lock);
-	wake_up(&mdev->al_wait);
+	device->resync_locked = 0;
+	device->resync_wenr = LC_FREE;
+	spin_unlock_irq(&device->al_lock);
+	wake_up(&device->al_wait);
 }
 
 /**
  * drbd_rs_del_all() - Gracefully remove all extents from the resync LRU
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Returns 0 upon success, -EAGAIN if at least one reference count was
  * not zero.
  */
-int drbd_rs_del_all(struct drbd_conf *mdev)
+int drbd_rs_del_all(struct drbd_device *device)
 {
 	struct lc_element *e;
 	struct bm_extent *bm_ext;
 	int i;
 
-	spin_lock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
 
-	if (get_ldev_if_state(mdev, D_FAILED)) {
+	if (get_ldev_if_state(device, D_FAILED)) {
 		/* ok, ->resync is there. */
-		for (i = 0; i < mdev->resync->nr_elements; i++) {
-			e = lc_element_by_index(mdev->resync, i);
+		for (i = 0; i < device->resync->nr_elements; i++) {
+			e = lc_element_by_index(device->resync, i);
 			bm_ext = lc_entry(e, struct bm_extent, lce);
 			if (bm_ext->lce.lc_number == LC_FREE)
 				continue;
-			if (bm_ext->lce.lc_number == mdev->resync_wenr) {
-				dev_info(DEV, "dropping %u in drbd_rs_del_all, apparently"
+			if (bm_ext->lce.lc_number == device->resync_wenr) {
+				drbd_info(device, "dropping %u in drbd_rs_del_all, apparently"
 				     " got 'synced' by application io\n",
-				     mdev->resync_wenr);
-				D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags));
-				D_ASSERT(test_bit(BME_NO_WRITES, &bm_ext->flags));
+				     device->resync_wenr);
+				D_ASSERT(device, !test_bit(BME_LOCKED, &bm_ext->flags));
+				D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
 				clear_bit(BME_NO_WRITES, &bm_ext->flags);
-				mdev->resync_wenr = LC_FREE;
-				lc_put(mdev->resync, &bm_ext->lce);
+				device->resync_wenr = LC_FREE;
+				lc_put(device->resync, &bm_ext->lce);
 			}
 			if (bm_ext->lce.refcnt != 0) {
-				dev_info(DEV, "Retrying drbd_rs_del_all() later. "
+				drbd_info(device, "Retrying drbd_rs_del_all() later. "
 				     "refcnt=%d\n", bm_ext->lce.refcnt);
-				put_ldev(mdev);
-				spin_unlock_irq(&mdev->al_lock);
+				put_ldev(device);
+				spin_unlock_irq(&device->al_lock);
 				return -EAGAIN;
 			}
-			D_ASSERT(!test_bit(BME_LOCKED, &bm_ext->flags));
-			D_ASSERT(!test_bit(BME_NO_WRITES, &bm_ext->flags));
-			lc_del(mdev->resync, &bm_ext->lce);
+			D_ASSERT(device, !test_bit(BME_LOCKED, &bm_ext->flags));
+			D_ASSERT(device, !test_bit(BME_NO_WRITES, &bm_ext->flags));
+			lc_del(device->resync, &bm_ext->lce);
 		}
-		D_ASSERT(mdev->resync->used == 0);
-		put_ldev(mdev);
+		D_ASSERT(device, device->resync->used == 0);
+		put_ldev(device);
 	}
-	spin_unlock_irq(&mdev->al_lock);
-	wake_up(&mdev->al_wait);
+	spin_unlock_irq(&device->al_lock);
+	wake_up(&device->al_wait);
 
 	return 0;
 }
 
 /**
  * drbd_rs_failed_io() - Record information on a failure to resync the specified blocks
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @sector:	The sector number.
  * @size:	Size of failed IO operation, in byte.
  */
-void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
+void drbd_rs_failed_io(struct drbd_device *device, sector_t sector, int size)
 {
 	/* Is called from worker and receiver context _only_ */
 	unsigned long sbnr, ebnr, lbnr;
@@ -1284,11 +1289,11 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
 	int wake_up = 0;
 
 	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
-		dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
+		drbd_err(device, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
 	}
-	nr_sectors = drbd_get_capacity(mdev->this_bdev);
+	nr_sectors = drbd_get_capacity(device->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
 	if (!expect(sector < nr_sectors))
@@ -1316,21 +1321,21 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
 	 * ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.
 	 */
-	spin_lock_irq(&mdev->al_lock);
-	count = drbd_bm_count_bits(mdev, sbnr, ebnr);
+	spin_lock_irq(&device->al_lock);
+	count = drbd_bm_count_bits(device, sbnr, ebnr);
 	if (count) {
-		mdev->rs_failed += count;
+		device->rs_failed += count;
 
-		if (get_ldev(mdev)) {
-			drbd_try_clear_on_disk_bm(mdev, sector, count, false);
-			put_ldev(mdev);
+		if (get_ldev(device)) {
+			drbd_try_clear_on_disk_bm(device, sector, count, false);
+			put_ldev(device);
 		}
 
 		/* just wake_up unconditional now, various lc_chaged(),
 		 * lc_put() in drbd_try_clear_on_disk_bm(). */
 		wake_up = 1;
 	}
-	spin_unlock_irq(&mdev->al_lock);
+	spin_unlock_irq(&device->al_lock);
 	if (wake_up)
-		wake_up(&mdev->al_wait);
+		wake_up(&device->al_wait);
 }
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 597f111df67b..1aa29f8fdfe1 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -113,54 +113,54 @@ struct drbd_bitmap {
 };
 
 #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__)
-static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func)
+static void __bm_print_lock_info(struct drbd_device *device, const char *func)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!__ratelimit(&drbd_ratelimit_state))
 		return;
-	dev_err(DEV, "FIXME %s in %s, bitmap locked for '%s' by %s\n",
-		drbd_task_to_thread_name(mdev->tconn, current),
-		func, b->bm_why ?: "?",
-		drbd_task_to_thread_name(mdev->tconn, b->bm_task));
+	drbd_err(device, "FIXME %s[%d] in %s, bitmap locked for '%s' by %s[%d]\n",
+		 current->comm, task_pid_nr(current),
+		 func, b->bm_why ?: "?",
+		 b->bm_task->comm, task_pid_nr(b->bm_task));
 }
 
-void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags)
+void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	int trylock_failed;
 
 	if (!b) {
-		dev_err(DEV, "FIXME no bitmap in drbd_bm_lock!?\n");
+		drbd_err(device, "FIXME no bitmap in drbd_bm_lock!?\n");
 		return;
 	}
 
 	trylock_failed = !mutex_trylock(&b->bm_change);
 
 	if (trylock_failed) {
-		dev_warn(DEV, "%s going to '%s' but bitmap already locked for '%s' by %s\n",
-			 drbd_task_to_thread_name(mdev->tconn, current),
-			 why, b->bm_why ?: "?",
-			 drbd_task_to_thread_name(mdev->tconn, b->bm_task));
+		drbd_warn(device, "%s[%d] going to '%s' but bitmap already locked for '%s' by %s[%d]\n",
+			  current->comm, task_pid_nr(current),
+			  why, b->bm_why ?: "?",
+			  b->bm_task->comm, task_pid_nr(b->bm_task));
 		mutex_lock(&b->bm_change);
 	}
 	if (BM_LOCKED_MASK & b->bm_flags)
-		dev_err(DEV, "FIXME bitmap already locked in bm_lock\n");
+		drbd_err(device, "FIXME bitmap already locked in bm_lock\n");
 	b->bm_flags |= flags & BM_LOCKED_MASK;
 
 	b->bm_why  = why;
 	b->bm_task = current;
 }
 
-void drbd_bm_unlock(struct drbd_conf *mdev)
+void drbd_bm_unlock(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!b) {
-		dev_err(DEV, "FIXME no bitmap in drbd_bm_unlock!?\n");
+		drbd_err(device, "FIXME no bitmap in drbd_bm_unlock!?\n");
 		return;
 	}
 
-	if (!(BM_LOCKED_MASK & mdev->bitmap->bm_flags))
-		dev_err(DEV, "FIXME bitmap not locked in bm_unlock\n");
+	if (!(BM_LOCKED_MASK & device->bitmap->bm_flags))
+		drbd_err(device, "FIXME bitmap not locked in bm_unlock\n");
 
 	b->bm_flags &= ~BM_LOCKED_MASK;
 	b->bm_why  = NULL;
@@ -211,19 +211,19 @@ static unsigned long bm_page_to_idx(struct page *page)
 /* As is very unlikely that the same page is under IO from more than one
  * context, we can get away with a bit per page and one wait queue per bitmap.
  */
-static void bm_page_lock_io(struct drbd_conf *mdev, int page_nr)
+static void bm_page_lock_io(struct drbd_device *device, int page_nr)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	void *addr = &page_private(b->bm_pages[page_nr]);
 	wait_event(b->bm_io_wait, !test_and_set_bit(BM_PAGE_IO_LOCK, addr));
 }
 
-static void bm_page_unlock_io(struct drbd_conf *mdev, int page_nr)
+static void bm_page_unlock_io(struct drbd_device *device, int page_nr)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	void *addr = &page_private(b->bm_pages[page_nr]);
 	clear_bit_unlock(BM_PAGE_IO_LOCK, addr);
-	wake_up(&mdev->bitmap->bm_io_wait);
+	wake_up(&device->bitmap->bm_io_wait);
 }
 
 /* set _before_ submit_io, so it may be reset due to being changed
@@ -242,22 +242,22 @@ static void bm_set_page_need_writeout(struct page *page)
 
 /**
  * drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @page_nr:	the bitmap page to mark with the "hint" flag
  *
  * From within an activity log transaction, we mark a few pages with these
  * hints, then call drbd_bm_write_hinted(), which will only write out changed
  * pages which are flagged with this mark.
  */
-void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr)
+void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr)
 {
 	struct page *page;
-	if (page_nr >= mdev->bitmap->bm_number_of_pages) {
-		dev_warn(DEV, "BAD: page_nr: %u, number_of_pages: %u\n",
-			 page_nr, (int)mdev->bitmap->bm_number_of_pages);
+	if (page_nr >= device->bitmap->bm_number_of_pages) {
+		drbd_warn(device, "BAD: page_nr: %u, number_of_pages: %u\n",
+			 page_nr, (int)device->bitmap->bm_number_of_pages);
 		return;
 	}
-	page = mdev->bitmap->bm_pages[page_nr];
+	page = device->bitmap->bm_pages[page_nr];
 	set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page));
 }
 
@@ -340,7 +340,7 @@ static void bm_unmap(unsigned long *p_addr)
 
 /*
  * actually most functions herein should take a struct drbd_bitmap*, not a
- * struct drbd_conf*, but for the debug macros I like to have the mdev around
+ * struct drbd_device*, but for the debug macros I like to have the device around
  * to be able to report device specific.
  */
 
@@ -436,11 +436,11 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
 
 /*
  * called on driver init only. TODO call when a device is created.
- * allocates the drbd_bitmap, and stores it in mdev->bitmap.
+ * allocates the drbd_bitmap, and stores it in device->bitmap.
  */
-int drbd_bm_init(struct drbd_conf *mdev)
+int drbd_bm_init(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	WARN_ON(b != NULL);
 	b = kzalloc(sizeof(struct drbd_bitmap), GFP_KERNEL);
 	if (!b)
@@ -449,28 +449,28 @@ int drbd_bm_init(struct drbd_conf *mdev)
 	mutex_init(&b->bm_change);
 	init_waitqueue_head(&b->bm_io_wait);
 
-	mdev->bitmap = b;
+	device->bitmap = b;
 
 	return 0;
 }
 
-sector_t drbd_bm_capacity(struct drbd_conf *mdev)
+sector_t drbd_bm_capacity(struct drbd_device *device)
 {
-	if (!expect(mdev->bitmap))
+	if (!expect(device->bitmap))
 		return 0;
-	return mdev->bitmap->bm_dev_capacity;
+	return device->bitmap->bm_dev_capacity;
 }
 
 /* called on driver unload. TODO: call when a device is destroyed.
  */
-void drbd_bm_cleanup(struct drbd_conf *mdev)
+void drbd_bm_cleanup(struct drbd_device *device)
 {
-	if (!expect(mdev->bitmap))
+	if (!expect(device->bitmap))
 		return;
-	bm_free_pages(mdev->bitmap->bm_pages, mdev->bitmap->bm_number_of_pages);
-	bm_vk_free(mdev->bitmap->bm_pages, (BM_P_VMALLOCED & mdev->bitmap->bm_flags));
-	kfree(mdev->bitmap);
-	mdev->bitmap = NULL;
+	bm_free_pages(device->bitmap->bm_pages, device->bitmap->bm_number_of_pages);
+	bm_vk_free(device->bitmap->bm_pages, (BM_P_VMALLOCED & device->bitmap->bm_flags));
+	kfree(device->bitmap);
+	device->bitmap = NULL;
 }
 
 /*
@@ -631,9 +631,9 @@ static u64 drbd_md_on_disk_bits(struct drbd_backing_dev *ldev)
  * In case this is actually a resize, we copy the old bitmap into the new one.
  * Otherwise, the bitmap is initialized to all bits set.
  */
-int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
+int drbd_bm_resize(struct drbd_device *device, sector_t capacity, int set_new_bits)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long bits, words, owords, obits;
 	unsigned long want, have, onpages; /* number of pages */
 	struct page **npages, **opages = NULL;
@@ -643,9 +643,9 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 	if (!expect(b))
 		return -ENOMEM;
 
-	drbd_bm_lock(mdev, "resize", BM_LOCKED_MASK);
+	drbd_bm_lock(device, "resize", BM_LOCKED_MASK);
 
-	dev_info(DEV, "drbd_bm_resize called with capacity == %llu\n",
+	drbd_info(device, "drbd_bm_resize called with capacity == %llu\n",
 			(unsigned long long)capacity);
 
 	if (capacity == b->bm_dev_capacity)
@@ -678,12 +678,12 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 	*/
 	words = ALIGN(bits, 64) >> LN2_BPL;
 
-	if (get_ldev(mdev)) {
-		u64 bits_on_disk = drbd_md_on_disk_bits(mdev->ldev);
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		u64 bits_on_disk = drbd_md_on_disk_bits(device->ldev);
+		put_ldev(device);
 		if (bits > bits_on_disk) {
-			dev_info(DEV, "bits = %lu\n", bits);
-			dev_info(DEV, "bits_on_disk = %llu\n", bits_on_disk);
+			drbd_info(device, "bits = %lu\n", bits);
+			drbd_info(device, "bits_on_disk = %llu\n", bits_on_disk);
 			err = -ENOSPC;
 			goto out;
 		}
@@ -692,10 +692,10 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 	want = ALIGN(words*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT;
 	have = b->bm_number_of_pages;
 	if (want == have) {
-		D_ASSERT(b->bm_pages != NULL);
+		D_ASSERT(device, b->bm_pages != NULL);
 		npages = b->bm_pages;
 	} else {
-		if (drbd_insert_fault(mdev, DRBD_FAULT_BM_ALLOC))
+		if (drbd_insert_fault(device, DRBD_FAULT_BM_ALLOC))
 			npages = NULL;
 		else
 			npages = bm_realloc_pages(b, want);
@@ -742,10 +742,10 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 		bm_vk_free(opages, opages_vmalloced);
 	if (!growing)
 		b->bm_set = bm_count_bits(b);
-	dev_info(DEV, "resync bitmap: bits=%lu words=%lu pages=%lu\n", bits, words, want);
+	drbd_info(device, "resync bitmap: bits=%lu words=%lu pages=%lu\n", bits, words, want);
 
  out:
-	drbd_bm_unlock(mdev);
+	drbd_bm_unlock(device);
 	return err;
 }
 
@@ -757,9 +757,9 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
  *
  * maybe bm_set should be atomic_t ?
  */
-unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
+unsigned long _drbd_bm_total_weight(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long s;
 	unsigned long flags;
 
@@ -775,20 +775,20 @@ unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
 	return s;
 }
 
-unsigned long drbd_bm_total_weight(struct drbd_conf *mdev)
+unsigned long drbd_bm_total_weight(struct drbd_device *device)
 {
 	unsigned long s;
 	/* if I don't have a disk, I don't know about out-of-sync status */
-	if (!get_ldev_if_state(mdev, D_NEGOTIATING))
+	if (!get_ldev_if_state(device, D_NEGOTIATING))
 		return 0;
-	s = _drbd_bm_total_weight(mdev);
-	put_ldev(mdev);
+	s = _drbd_bm_total_weight(device);
+	put_ldev(device);
 	return s;
 }
 
-size_t drbd_bm_words(struct drbd_conf *mdev)
+size_t drbd_bm_words(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!expect(b))
 		return 0;
 	if (!expect(b->bm_pages))
@@ -797,9 +797,9 @@ size_t drbd_bm_words(struct drbd_conf *mdev)
 	return b->bm_words;
 }
 
-unsigned long drbd_bm_bits(struct drbd_conf *mdev)
+unsigned long drbd_bm_bits(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!expect(b))
 		return 0;
 
@@ -811,10 +811,10 @@ unsigned long drbd_bm_bits(struct drbd_conf *mdev)
  * bitmap must be locked by drbd_bm_lock.
  * currently only used from receive_bitmap.
  */
-void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
+void drbd_bm_merge_lel(struct drbd_device *device, size_t offset, size_t number,
 			unsigned long *buffer)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr, *bm;
 	unsigned long word, bits;
 	unsigned int idx;
@@ -860,10 +860,10 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 /* copy number words from the bitmap starting at offset into the buffer.
  * buffer[i] will be little endian unsigned long.
  */
-void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
+void drbd_bm_get_lel(struct drbd_device *device, size_t offset, size_t number,
 		     unsigned long *buffer)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr, *bm;
 	size_t end, do_now;
 
@@ -878,7 +878,7 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 	if ((offset >= b->bm_words) ||
 	    (end    >  b->bm_words) ||
 	    (number <= 0))
-		dev_err(DEV, "offset=%lu number=%lu bm_words=%lu\n",
+		drbd_err(device, "offset=%lu number=%lu bm_words=%lu\n",
 			(unsigned long)	offset,
 			(unsigned long)	number,
 			(unsigned long) b->bm_words);
@@ -897,9 +897,9 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 }
 
 /* set all bits in the bitmap */
-void drbd_bm_set_all(struct drbd_conf *mdev)
+void drbd_bm_set_all(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!expect(b))
 		return;
 	if (!expect(b->bm_pages))
@@ -913,9 +913,9 @@ void drbd_bm_set_all(struct drbd_conf *mdev)
 }
 
 /* clear all bits in the bitmap */
-void drbd_bm_clear_all(struct drbd_conf *mdev)
+void drbd_bm_clear_all(struct drbd_device *device)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	if (!expect(b))
 		return;
 	if (!expect(b->bm_pages))
@@ -928,7 +928,7 @@ void drbd_bm_clear_all(struct drbd_conf *mdev)
 }
 
 struct bm_aio_ctx {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	atomic_t in_flight;
 	unsigned int done;
 	unsigned flags;
@@ -943,7 +943,7 @@ static void bm_aio_ctx_destroy(struct kref *kref)
 {
 	struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref);
 
-	put_ldev(ctx->mdev);
+	put_ldev(ctx->device);
 	kfree(ctx);
 }
 
@@ -951,8 +951,8 @@ static void bm_aio_ctx_destroy(struct kref *kref)
 static void bm_async_io_complete(struct bio *bio, int error)
 {
 	struct bm_aio_ctx *ctx = bio->bi_private;
-	struct drbd_conf *mdev = ctx->mdev;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_device *device = ctx->device;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page);
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -966,7 +966,7 @@ static void bm_async_io_complete(struct bio *bio, int error)
 
 	if ((ctx->flags & BM_AIO_COPY_PAGES) == 0 &&
 	    !bm_test_page_unchanged(b->bm_pages[idx]))
-		dev_warn(DEV, "bitmap page idx %u changed during IO!\n", idx);
+		drbd_warn(device, "bitmap page idx %u changed during IO!\n", idx);
 
 	if (error) {
 		/* ctx error will hold the completed-last non-zero error code,
@@ -976,14 +976,14 @@ static void bm_async_io_complete(struct bio *bio, int error)
 		/* Not identical to on disk version of it.
 		 * Is BM_PAGE_IO_ERROR enough? */
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "IO ERROR %d on bitmap page idx %u\n",
+			drbd_err(device, "IO ERROR %d on bitmap page idx %u\n",
 					error, idx);
 	} else {
 		bm_clear_page_io_err(b->bm_pages[idx]);
-		dynamic_dev_dbg(DEV, "bitmap page idx %u completed\n", idx);
+		dynamic_drbd_dbg(device, "bitmap page idx %u completed\n", idx);
 	}
 
-	bm_page_unlock_io(mdev, idx);
+	bm_page_unlock_io(device, idx);
 
 	if (ctx->flags & BM_AIO_COPY_PAGES)
 		mempool_free(bio->bi_io_vec[0].bv_page, drbd_md_io_page_pool);
@@ -992,7 +992,7 @@ static void bm_async_io_complete(struct bio *bio, int error)
 
 	if (atomic_dec_and_test(&ctx->in_flight)) {
 		ctx->done = 1;
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 		kref_put(&ctx->kref, &bm_aio_ctx_destroy);
 	}
 }
@@ -1000,23 +1000,23 @@ static void bm_async_io_complete(struct bio *bio, int error)
 static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local)
 {
 	struct bio *bio = bio_alloc_drbd(GFP_NOIO);
-	struct drbd_conf *mdev = ctx->mdev;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_device *device = ctx->device;
+	struct drbd_bitmap *b = device->bitmap;
 	struct page *page;
 	unsigned int len;
 
 	sector_t on_disk_sector =
-		mdev->ldev->md.md_offset + mdev->ldev->md.bm_offset;
+		device->ldev->md.md_offset + device->ldev->md.bm_offset;
 	on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9);
 
 	/* this might happen with very small
 	 * flexible external meta data device,
 	 * or with PAGE_SIZE > 4k */
 	len = min_t(unsigned int, PAGE_SIZE,
-		(drbd_md_last_sector(mdev->ldev) - on_disk_sector + 1)<<9);
+		(drbd_md_last_sector(device->ldev) - on_disk_sector + 1)<<9);
 
 	/* serialize IO on this page */
-	bm_page_lock_io(mdev, page_nr);
+	bm_page_lock_io(device, page_nr);
 	/* before memcpy and submit,
 	 * so it can be redirtied any time */
 	bm_set_page_unchanged(b->bm_pages[page_nr]);
@@ -1027,7 +1027,7 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
 		bm_store_page_idx(page, page_nr);
 	} else
 		page = b->bm_pages[page_nr];
-	bio->bi_bdev = mdev->ldev->md_bdev;
+	bio->bi_bdev = device->ldev->md_bdev;
 	bio->bi_iter.bi_sector = on_disk_sector;
 	/* bio_add_page of a single page to an empty bio will always succeed,
 	 * according to api.  Do we want to assert that? */
@@ -1035,24 +1035,24 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
 	bio->bi_private = ctx;
 	bio->bi_end_io = bm_async_io_complete;
 
-	if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
+	if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
 		bio->bi_rw |= rw;
 		bio_endio(bio, -EIO);
 	} else {
 		submit_bio(rw, bio);
 		/* this should not count as user activity and cause the
 		 * resync to throttle -- see drbd_rs_should_slow_down(). */
-		atomic_add(len >> 9, &mdev->rs_sect_ev);
+		atomic_add(len >> 9, &device->rs_sect_ev);
 	}
 }
 
 /*
  * bm_rw: read/write the whole bitmap from/to its on disk location.
  */
-static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
+static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
 {
 	struct bm_aio_ctx *ctx;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	int num_pages, i, count = 0;
 	unsigned long now;
 	char ppb[10];
@@ -1072,7 +1072,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 		return -ENOMEM;
 
 	*ctx = (struct bm_aio_ctx) {
-		.mdev = mdev,
+		.device = device,
 		.in_flight = ATOMIC_INIT(1),
 		.done = 0,
 		.flags = flags,
@@ -1080,8 +1080,8 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 		.kref = { ATOMIC_INIT(2) },
 	};
 
-	if (!get_ldev_if_state(mdev, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
-		dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n");
+	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
+		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n");
 		kfree(ctx);
 		return -ENODEV;
 	}
@@ -1106,14 +1106,14 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 
 			if (!(flags & BM_WRITE_ALL_PAGES) &&
 			    bm_test_page_unchanged(b->bm_pages[i])) {
-				dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
+				dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i);
 				continue;
 			}
 			/* during lazy writeout,
 			 * ignore those pages not marked for lazy writeout. */
 			if (lazy_writeout_upper_idx &&
 			    !bm_test_page_lazy_writeout(b->bm_pages[i])) {
-				dynamic_dev_dbg(DEV, "skipped bm lazy write for idx %u\n", i);
+				dynamic_drbd_dbg(device, "skipped bm lazy write for idx %u\n", i);
 				continue;
 			}
 		}
@@ -1132,19 +1132,19 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 	 * "in_flight reached zero, all done" event.
 	 */
 	if (!atomic_dec_and_test(&ctx->in_flight))
-		wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
+		wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
 	else
 		kref_put(&ctx->kref, &bm_aio_ctx_destroy);
 
 	/* summary for global bitmap IO */
 	if (flags == 0)
-		dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
+		drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n",
 			 rw == WRITE ? "WRITE" : "READ",
 			 count, jiffies - now);
 
 	if (ctx->error) {
-		dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n");
-		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+		drbd_alert(device, "we had at least one MD IO ERROR during bitmap IO\n");
+		drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
 		err = -EIO; /* ctx->error ? */
 	}
 
@@ -1153,16 +1153,16 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 
 	now = jiffies;
 	if (rw == WRITE) {
-		drbd_md_flush(mdev);
+		drbd_md_flush(device);
 	} else /* rw == READ */ {
 		b->bm_set = bm_count_bits(b);
-		dev_info(DEV, "recounting of set bits took additional %lu jiffies\n",
+		drbd_info(device, "recounting of set bits took additional %lu jiffies\n",
 		     jiffies - now);
 	}
 	now = b->bm_set;
 
 	if (flags == 0)
-		dev_info(DEV, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
+		drbd_info(device, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
 		     ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
 
 	kref_put(&ctx->kref, &bm_aio_ctx_destroy);
@@ -1171,48 +1171,38 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 
 /**
  * drbd_bm_read() - Read the whole bitmap from its on disk location.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  */
-int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local)
+int drbd_bm_read(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(mdev, READ, 0, 0);
+	return bm_rw(device, READ, 0, 0);
 }
 
 /**
  * drbd_bm_write() - Write the whole bitmap to its on disk location.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Will only write pages that have changed since last IO.
  */
-int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
+int drbd_bm_write(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(mdev, WRITE, 0, 0);
+	return bm_rw(device, WRITE, 0, 0);
 }
 
 /**
  * drbd_bm_write_all() - Write the whole bitmap to its on disk location.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Will write all pages.
  */
-int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local)
+int drbd_bm_write_all(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(mdev, WRITE, BM_WRITE_ALL_PAGES, 0);
-}
-
-/**
- * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
- * @mdev:	DRBD device.
- * @upper_idx:	0: write all changed pages; +ve: page index to stop scanning for changed pages
- */
-int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local)
-{
-	return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, upper_idx);
+	return bm_rw(device, WRITE, BM_WRITE_ALL_PAGES, 0);
 }
 
 /**
  * drbd_bm_write_copy_pages() - Write the whole bitmap to its on disk location.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Will only write pages that have changed since last IO.
  * In contrast to drbd_bm_write(), this will copy the bitmap pages
@@ -1221,23 +1211,23 @@ int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(l
  * verify is aborted due to a failed peer disk, while local IO continues, or
  * pending resync acks are still being processed.
  */
-int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local)
+int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, 0);
+	return bm_rw(device, WRITE, BM_AIO_COPY_PAGES, 0);
 }
 
 /**
  * drbd_bm_write_hinted() - Write bitmap pages with "hint" marks, if they have changed.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  */
-int drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local)
+int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(mdev, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
+	return bm_rw(device, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
 }
 
 /**
  * drbd_bm_write_page() - Writes a PAGE_SIZE aligned piece of bitmap
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @idx:	bitmap page index
  *
  * We don't want to special case on logical_block_size of the backend device,
@@ -1247,13 +1237,13 @@ int drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local)
  * In case this becomes an issue on systems with larger PAGE_SIZE,
  * we may want to change this again to write 4k aligned 4k pieces.
  */
-int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local)
+int drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local)
 {
 	struct bm_aio_ctx *ctx;
 	int err;
 
-	if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) {
-		dynamic_dev_dbg(DEV, "skipped bm page write for idx %u\n", idx);
+	if (bm_test_page_unchanged(device->bitmap->bm_pages[idx])) {
+		dynamic_drbd_dbg(device, "skipped bm page write for idx %u\n", idx);
 		return 0;
 	}
 
@@ -1262,7 +1252,7 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
 		return -ENOMEM;
 
 	*ctx = (struct bm_aio_ctx) {
-		.mdev = mdev,
+		.device = device,
 		.in_flight = ATOMIC_INIT(1),
 		.done = 0,
 		.flags = BM_AIO_COPY_PAGES,
@@ -1270,21 +1260,21 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
 		.kref = { ATOMIC_INIT(2) },
 	};
 
-	if (!get_ldev_if_state(mdev, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
-		dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in drbd_bm_write_page()\n");
+	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
+		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in drbd_bm_write_page()\n");
 		kfree(ctx);
 		return -ENODEV;
 	}
 
 	bm_page_io_async(ctx, idx, WRITE_SYNC);
-	wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
+	wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
 
 	if (ctx->error)
-		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+		drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
 		/* that causes us to detach, so the in memory bitmap will be
 		 * gone in a moment as well. */
 
-	mdev->bm_writ_cnt++;
+	device->bm_writ_cnt++;
 	err = atomic_read(&ctx->in_flight) ? -EIO : ctx->error;
 	kref_put(&ctx->kref, &bm_aio_ctx_destroy);
 	return err;
@@ -1298,17 +1288,17 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
  *
  * this returns a bit number, NOT a sector!
  */
-static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
+static unsigned long __bm_find_next(struct drbd_device *device, unsigned long bm_fo,
 	const int find_zero_bit)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr;
 	unsigned long bit_offset;
 	unsigned i;
 
 
 	if (bm_fo > b->bm_bits) {
-		dev_err(DEV, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits);
+		drbd_err(device, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits);
 		bm_fo = DRBD_END_OF_BITMAP;
 	} else {
 		while (bm_fo < b->bm_bits) {
@@ -1338,10 +1328,10 @@ static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
 	return bm_fo;
 }
 
-static unsigned long bm_find_next(struct drbd_conf *mdev,
+static unsigned long bm_find_next(struct drbd_device *device,
 	unsigned long bm_fo, const int find_zero_bit)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long i = DRBD_END_OF_BITMAP;
 
 	if (!expect(b))
@@ -1351,39 +1341,39 @@ static unsigned long bm_find_next(struct drbd_conf *mdev,
 
 	spin_lock_irq(&b->bm_lock);
 	if (BM_DONT_TEST & b->bm_flags)
-		bm_print_lock_info(mdev);
+		bm_print_lock_info(device);
 
-	i = __bm_find_next(mdev, bm_fo, find_zero_bit);
+	i = __bm_find_next(device, bm_fo, find_zero_bit);
 
 	spin_unlock_irq(&b->bm_lock);
 	return i;
 }
 
-unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo)
+unsigned long drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo)
 {
-	return bm_find_next(mdev, bm_fo, 0);
+	return bm_find_next(device, bm_fo, 0);
 }
 
 #if 0
 /* not yet needed for anything. */
-unsigned long drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo)
+unsigned long drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo)
 {
-	return bm_find_next(mdev, bm_fo, 1);
+	return bm_find_next(device, bm_fo, 1);
 }
 #endif
 
 /* does not spin_lock_irqsave.
  * you must take drbd_bm_lock() first */
-unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo)
+unsigned long _drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo)
 {
-	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
-	return __bm_find_next(mdev, bm_fo, 0);
+	/* WARN_ON(!(BM_DONT_SET & device->b->bm_flags)); */
+	return __bm_find_next(device, bm_fo, 0);
 }
 
-unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo)
+unsigned long _drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo)
 {
-	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
-	return __bm_find_next(mdev, bm_fo, 1);
+	/* WARN_ON(!(BM_DONT_SET & device->b->bm_flags)); */
+	return __bm_find_next(device, bm_fo, 1);
 }
 
 /* returns number of bits actually changed.
@@ -1392,10 +1382,10 @@ unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_f
  * wants bitnr, not sector.
  * expected to be called for only a few bits (e - s about BITS_PER_LONG).
  * Must hold bitmap lock already. */
-static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
+static int __bm_change_bits_to(struct drbd_device *device, const unsigned long s,
 	unsigned long e, int val)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr = NULL;
 	unsigned long bitnr;
 	unsigned int last_page_nr = -1U;
@@ -1403,7 +1393,7 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 	int changed_total = 0;
 
 	if (e >= b->bm_bits) {
-		dev_err(DEV, "ASSERT FAILED: bit_s=%lu bit_e=%lu bm_bits=%lu\n",
+		drbd_err(device, "ASSERT FAILED: bit_s=%lu bit_e=%lu bm_bits=%lu\n",
 				s, e, b->bm_bits);
 		e = b->bm_bits ? b->bm_bits -1 : 0;
 	}
@@ -1441,11 +1431,11 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
  * for val != 0, we change 0 -> 1, return code positive
  * for val == 0, we change 1 -> 0, return code negative
  * wants bitnr, not sector */
-static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
+static int bm_change_bits_to(struct drbd_device *device, const unsigned long s,
 	const unsigned long e, int val)
 {
 	unsigned long flags;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	int c = 0;
 
 	if (!expect(b))
@@ -1455,24 +1445,24 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags)
-		bm_print_lock_info(mdev);
+		bm_print_lock_info(device);
 
-	c = __bm_change_bits_to(mdev, s, e, val);
+	c = __bm_change_bits_to(device, s, e, val);
 
 	spin_unlock_irqrestore(&b->bm_lock, flags);
 	return c;
 }
 
 /* returns number of bits changed 0 -> 1 */
-int drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e)
+int drbd_bm_set_bits(struct drbd_device *device, const unsigned long s, const unsigned long e)
 {
-	return bm_change_bits_to(mdev, s, e, 1);
+	return bm_change_bits_to(device, s, e, 1);
 }
 
 /* returns number of bits changed 1 -> 0 */
-int drbd_bm_clear_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e)
+int drbd_bm_clear_bits(struct drbd_device *device, const unsigned long s, const unsigned long e)
 {
-	return -bm_change_bits_to(mdev, s, e, 0);
+	return -bm_change_bits_to(device, s, e, 0);
 }
 
 /* sets all bits in full words,
@@ -1504,7 +1494,7 @@ static inline void bm_set_full_words_within_one_page(struct drbd_bitmap *b,
  * You must first drbd_bm_lock().
  * Can be called to set the whole bitmap in one go.
  * Sets bits from s to e _inclusive_. */
-void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e)
+void _drbd_bm_set_bits(struct drbd_device *device, const unsigned long s, const unsigned long e)
 {
 	/* First set_bit from the first bit (s)
 	 * up to the next long boundary (sl),
@@ -1514,7 +1504,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 	 * Do not use memset, because we must account for changes,
 	 * so we need to loop over the words with hweight() anyways.
 	 */
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long sl = ALIGN(s,BITS_PER_LONG);
 	unsigned long el = (e+1) & ~((unsigned long)BITS_PER_LONG-1);
 	int first_page;
@@ -1526,7 +1516,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 	if (e - s <= 3*BITS_PER_LONG) {
 		/* don't bother; el and sl may even be wrong. */
 		spin_lock_irq(&b->bm_lock);
-		__bm_change_bits_to(mdev, s, e, 1);
+		__bm_change_bits_to(device, s, e, 1);
 		spin_unlock_irq(&b->bm_lock);
 		return;
 	}
@@ -1537,7 +1527,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 
 	/* bits filling the current long */
 	if (sl)
-		__bm_change_bits_to(mdev, s, sl-1, 1);
+		__bm_change_bits_to(device, s, sl-1, 1);
 
 	first_page = sl >> (3 + PAGE_SHIFT);
 	last_page = el >> (3 + PAGE_SHIFT);
@@ -1549,7 +1539,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 
 	/* first and full pages, unless first page == last page */
 	for (page_nr = first_page; page_nr < last_page; page_nr++) {
-		bm_set_full_words_within_one_page(mdev->bitmap, page_nr, first_word, last_word);
+		bm_set_full_words_within_one_page(device->bitmap, page_nr, first_word, last_word);
 		spin_unlock_irq(&b->bm_lock);
 		cond_resched();
 		first_word = 0;
@@ -1565,7 +1555,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 	 * as we did not allocate it, it is not present in bitmap->bm_pages.
 	 */
 	if (last_word)
-		bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word);
+		bm_set_full_words_within_one_page(device->bitmap, last_page, first_word, last_word);
 
 	/* possibly trailing bits.
 	 * example: (e & 63) == 63, el will be e+1.
@@ -1573,7 +1563,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 	 * it would trigger an assert in __bm_change_bits_to()
 	 */
 	if (el <= e)
-		__bm_change_bits_to(mdev, el, e, 1);
+		__bm_change_bits_to(device, el, e, 1);
 	spin_unlock_irq(&b->bm_lock);
 }
 
@@ -1584,10 +1574,10 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
  *  0 ... bit not set
  * -1 ... first out of bounds access, stop testing for bits!
  */
-int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
+int drbd_bm_test_bit(struct drbd_device *device, const unsigned long bitnr)
 {
 	unsigned long flags;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr;
 	int i;
 
@@ -1598,7 +1588,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
-		bm_print_lock_info(mdev);
+		bm_print_lock_info(device);
 	if (bitnr < b->bm_bits) {
 		p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr));
 		i = test_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr) ? 1 : 0;
@@ -1606,7 +1596,7 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
 	} else if (bitnr == b->bm_bits) {
 		i = -1;
 	} else { /* (bitnr > b->bm_bits) */
-		dev_err(DEV, "bitnr=%lu > bm_bits=%lu\n", bitnr, b->bm_bits);
+		drbd_err(device, "bitnr=%lu > bm_bits=%lu\n", bitnr, b->bm_bits);
 		i = 0;
 	}
 
@@ -1615,10 +1605,10 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
 }
 
 /* returns number of bits set in the range [s, e] */
-int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e)
+int drbd_bm_count_bits(struct drbd_device *device, const unsigned long s, const unsigned long e)
 {
 	unsigned long flags;
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	unsigned long *p_addr = NULL;
 	unsigned long bitnr;
 	unsigned int page_nr = -1U;
@@ -1635,7 +1625,7 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
-		bm_print_lock_info(mdev);
+		bm_print_lock_info(device);
 	for (bitnr = s; bitnr <= e; bitnr++) {
 		unsigned int idx = bm_bit_to_page_idx(b, bitnr);
 		if (page_nr != idx) {
@@ -1647,7 +1637,7 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 		if (expect(bitnr < b->bm_bits))
 			c += (0 != test_bit_le(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
 		else
-			dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
+			drbd_err(device, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
 	}
 	if (p_addr)
 		bm_unmap(p_addr);
@@ -1670,9 +1660,9 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
  * reference count of some bitmap extent element from some lru instead...
  *
  */
-int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
+int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr)
 {
-	struct drbd_bitmap *b = mdev->bitmap;
+	struct drbd_bitmap *b = device->bitmap;
 	int count, s, e;
 	unsigned long flags;
 	unsigned long *p_addr, *bm;
@@ -1684,7 +1674,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
-		bm_print_lock_info(mdev);
+		bm_print_lock_info(device);
 
 	s = S2W(enr);
 	e = min((size_t)S2W(enr+1), b->bm_words);
@@ -1697,7 +1687,7 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
 			count += hweight_long(*bm++);
 		bm_unmap(p_addr);
 	} else {
-		dev_err(DEV, "start offset (%d) too large in drbd_bm_e_weight\n", s);
+		drbd_err(device, "start offset (%d) too large in drbd_bm_e_weight\n", s);
 	}
 	spin_unlock_irqrestore(&b->bm_lock, flags);
 	return count;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 0e06f0c5dd1e..e7093d4291f1 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -45,7 +45,9 @@
 #include <linux/prefetch.h>
 #include <linux/drbd_genl_api.h>
 #include <linux/drbd.h>
+#include "drbd_strings.h"
 #include "drbd_state.h"
+#include "drbd_protocol.h"
 
 #ifdef __CHECKER__
 # define __protected_by(x)       __attribute__((require_context(x,1,999,"rdwr")))
@@ -65,6 +67,7 @@
 extern unsigned int minor_count;
 extern bool disable_sendpage;
 extern bool allow_oos;
+void tl_abort_disk_io(struct drbd_device *device);
 
 #ifdef CONFIG_DRBD_FAULT_INJECTION
 extern int enable_faults;
@@ -95,25 +98,60 @@ extern char usermode_helper[];
 
 #define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL)
 
-struct drbd_conf;
-struct drbd_tconn;
-
-
-/* to shorten dev_warn(DEV, "msg"); and relatives statements */
-#define DEV (disk_to_dev(mdev->vdisk))
-
-#define conn_printk(LEVEL, TCONN, FMT, ARGS...) \
-	printk(LEVEL "d-con %s: " FMT, TCONN->name , ## ARGS)
-#define conn_alert(TCONN, FMT, ARGS...)  conn_printk(KERN_ALERT, TCONN, FMT, ## ARGS)
-#define conn_crit(TCONN, FMT, ARGS...)   conn_printk(KERN_CRIT, TCONN, FMT, ## ARGS)
-#define conn_err(TCONN, FMT, ARGS...)    conn_printk(KERN_ERR, TCONN, FMT, ## ARGS)
-#define conn_warn(TCONN, FMT, ARGS...)   conn_printk(KERN_WARNING, TCONN, FMT, ## ARGS)
-#define conn_notice(TCONN, FMT, ARGS...) conn_printk(KERN_NOTICE, TCONN, FMT, ## ARGS)
-#define conn_info(TCONN, FMT, ARGS...)   conn_printk(KERN_INFO, TCONN, FMT, ## ARGS)
-#define conn_dbg(TCONN, FMT, ARGS...)    conn_printk(KERN_DEBUG, TCONN, FMT, ## ARGS)
-
-#define D_ASSERT(exp)	if (!(exp)) \
-	 dev_err(DEV, "ASSERT( " #exp " ) in %s:%d\n", __FILE__, __LINE__)
+struct drbd_device;
+struct drbd_connection;
+
+#define __drbd_printk_device(level, device, fmt, args...) \
+	dev_printk(level, disk_to_dev((device)->vdisk), fmt, ## args)
+#define __drbd_printk_peer_device(level, peer_device, fmt, args...) \
+	dev_printk(level, disk_to_dev((peer_device)->device->vdisk), fmt, ## args)
+#define __drbd_printk_resource(level, resource, fmt, args...) \
+	printk(level "drbd %s: " fmt, (resource)->name, ## args)
+#define __drbd_printk_connection(level, connection, fmt, args...) \
+	printk(level "drbd %s: " fmt, (connection)->resource->name, ## args)
+
+void drbd_printk_with_wrong_object_type(void);
+
+#define __drbd_printk_if_same_type(obj, type, func, level, fmt, args...) \
+	(__builtin_types_compatible_p(typeof(obj), type) || \
+	 __builtin_types_compatible_p(typeof(obj), const type)), \
+	func(level, (const type)(obj), fmt, ## args)
+
+#define drbd_printk(level, obj, fmt, args...) \
+	__builtin_choose_expr( \
+	  __drbd_printk_if_same_type(obj, struct drbd_device *, \
+			     __drbd_printk_device, level, fmt, ## args), \
+	  __builtin_choose_expr( \
+	    __drbd_printk_if_same_type(obj, struct drbd_resource *, \
+			       __drbd_printk_resource, level, fmt, ## args), \
+	    __builtin_choose_expr( \
+	      __drbd_printk_if_same_type(obj, struct drbd_connection *, \
+				 __drbd_printk_connection, level, fmt, ## args), \
+	      __builtin_choose_expr( \
+		__drbd_printk_if_same_type(obj, struct drbd_peer_device *, \
+				 __drbd_printk_peer_device, level, fmt, ## args), \
+		drbd_printk_with_wrong_object_type()))))
+
+#define drbd_dbg(obj, fmt, args...) \
+	drbd_printk(KERN_DEBUG, obj, fmt, ## args)
+#define drbd_alert(obj, fmt, args...) \
+	drbd_printk(KERN_ALERT, obj, fmt, ## args)
+#define drbd_err(obj, fmt, args...) \
+	drbd_printk(KERN_ERR, obj, fmt, ## args)
+#define drbd_warn(obj, fmt, args...) \
+	drbd_printk(KERN_WARNING, obj, fmt, ## args)
+#define drbd_info(obj, fmt, args...) \
+	drbd_printk(KERN_INFO, obj, fmt, ## args)
+#define drbd_emerg(obj, fmt, args...) \
+	drbd_printk(KERN_EMERG, obj, fmt, ## args)
+
+#define dynamic_drbd_dbg(device, fmt, args...) \
+	dynamic_dev_dbg(disk_to_dev(device->vdisk), fmt, ## args)
+
+#define D_ASSERT(device, exp)	do { \
+	if (!(exp)) \
+		drbd_err(device, "ASSERT( " #exp " ) in %s:%d\n", __FILE__, __LINE__); \
+	} while (0)
 
 /**
  * expect  -  Make an assertion
@@ -123,7 +161,7 @@ struct drbd_tconn;
 #define expect(exp) ({								\
 		bool _bool = (exp);						\
 		if (!_bool)							\
-			dev_err(DEV, "ASSERTION %s FAILED in %s\n",		\
+			drbd_err(device, "ASSERTION %s FAILED in %s\n",		\
 			        #exp, __func__);				\
 		_bool;								\
 		})
@@ -145,14 +183,14 @@ enum {
 };
 
 extern unsigned int
-_drbd_insert_fault(struct drbd_conf *mdev, unsigned int type);
+_drbd_insert_fault(struct drbd_device *device, unsigned int type);
 
 static inline int
-drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
+drbd_insert_fault(struct drbd_device *device, unsigned int type) {
 #ifdef CONFIG_DRBD_FAULT_INJECTION
 	return fault_rate &&
 		(enable_faults & (1<<type)) &&
-		_drbd_insert_fault(mdev, type);
+		_drbd_insert_fault(device, type);
 #else
 	return 0;
 #endif
@@ -164,74 +202,8 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
 #define div_floor(A, B) ((A)/(B))
 
 extern struct ratelimit_state drbd_ratelimit_state;
-extern struct idr minors; /* RCU, updates: genl_lock() */
-extern struct list_head drbd_tconns; /* RCU, updates: genl_lock() */
-
-/* on the wire */
-enum drbd_packet {
-	/* receiver (data socket) */
-	P_DATA		      = 0x00,
-	P_DATA_REPLY	      = 0x01, /* Response to P_DATA_REQUEST */
-	P_RS_DATA_REPLY	      = 0x02, /* Response to P_RS_DATA_REQUEST */
-	P_BARRIER	      = 0x03,
-	P_BITMAP	      = 0x04,
-	P_BECOME_SYNC_TARGET  = 0x05,
-	P_BECOME_SYNC_SOURCE  = 0x06,
-	P_UNPLUG_REMOTE	      = 0x07, /* Used at various times to hint the peer */
-	P_DATA_REQUEST	      = 0x08, /* Used to ask for a data block */
-	P_RS_DATA_REQUEST     = 0x09, /* Used to ask for a data block for resync */
-	P_SYNC_PARAM	      = 0x0a,
-	P_PROTOCOL	      = 0x0b,
-	P_UUIDS		      = 0x0c,
-	P_SIZES		      = 0x0d,
-	P_STATE		      = 0x0e,
-	P_SYNC_UUID	      = 0x0f,
-	P_AUTH_CHALLENGE      = 0x10,
-	P_AUTH_RESPONSE	      = 0x11,
-	P_STATE_CHG_REQ	      = 0x12,
-
-	/* asender (meta socket */
-	P_PING		      = 0x13,
-	P_PING_ACK	      = 0x14,
-	P_RECV_ACK	      = 0x15, /* Used in protocol B */
-	P_WRITE_ACK	      = 0x16, /* Used in protocol C */
-	P_RS_WRITE_ACK	      = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */
-	P_SUPERSEDED	      = 0x18, /* Used in proto C, two-primaries conflict detection */
-	P_NEG_ACK	      = 0x19, /* Sent if local disk is unusable */
-	P_NEG_DREPLY	      = 0x1a, /* Local disk is broken... */
-	P_NEG_RS_DREPLY	      = 0x1b, /* Local disk is broken... */
-	P_BARRIER_ACK	      = 0x1c,
-	P_STATE_CHG_REPLY     = 0x1d,
-
-	/* "new" commands, no longer fitting into the ordering scheme above */
-
-	P_OV_REQUEST	      = 0x1e, /* data socket */
-	P_OV_REPLY	      = 0x1f,
-	P_OV_RESULT	      = 0x20, /* meta socket */
-	P_CSUM_RS_REQUEST     = 0x21, /* data socket */
-	P_RS_IS_IN_SYNC	      = 0x22, /* meta socket */
-	P_SYNC_PARAM89	      = 0x23, /* data socket, protocol version 89 replacement for P_SYNC_PARAM */
-	P_COMPRESSED_BITMAP   = 0x24, /* compressed or otherwise encoded bitmap transfer */
-	/* P_CKPT_FENCE_REQ      = 0x25, * currently reserved for protocol D */
-	/* P_CKPT_DISABLE_REQ    = 0x26, * currently reserved for protocol D */
-	P_DELAY_PROBE         = 0x27, /* is used on BOTH sockets */
-	P_OUT_OF_SYNC         = 0x28, /* Mark as out of sync (Outrunning), data socket */
-	P_RS_CANCEL           = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */
-	P_CONN_ST_CHG_REQ     = 0x2a, /* data sock: Connection wide state request */
-	P_CONN_ST_CHG_REPLY   = 0x2b, /* meta sock: Connection side state req reply */
-	P_RETRY_WRITE	      = 0x2c, /* Protocol C: retry conflicting write request */
-	P_PROTOCOL_UPDATE     = 0x2d, /* data sock: is used in established connections */
-
-	P_MAY_IGNORE	      = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
-	P_MAX_OPT_CMD	      = 0x101,
-
-	/* special command ids for handshake */
-
-	P_INITIAL_META	      = 0xfff1, /* First Packet on the MetaSock */
-	P_INITIAL_DATA	      = 0xfff2, /* First Packet on the Socket */
-
-	P_CONNECTION_FEATURES = 0xfffe	/* FIXED for the next century! */
-};
+extern struct idr drbd_devices; /* RCU, updates: genl_lock() */
+extern struct list_head drbd_resources; /* RCU, updates: genl_lock() */
 
 extern const char *cmdname(enum drbd_packet cmd);
 
@@ -253,7 +225,7 @@ struct bm_xfer_ctx {
 	unsigned bytes[2];
 };
 
-extern void INFO_bm_xfer_stats(struct drbd_conf *mdev,
+extern void INFO_bm_xfer_stats(struct drbd_device *device,
 		const char *direction, struct bm_xfer_ctx *c);
 
 static inline void bm_xfer_ctx_bit_to_word_offset(struct bm_xfer_ctx *c)
@@ -275,233 +247,7 @@ static inline void bm_xfer_ctx_bit_to_word_offset(struct bm_xfer_ctx *c)
 #endif
 }
 
-#ifndef __packed
-#define __packed __attribute__((packed))
-#endif
-
-/* This is the layout for a packet on the wire.
- * The byteorder is the network byte order.
- *     (except block_id and barrier fields.
- *	these are pointers to local structs
- *	and have no relevance for the partner,
- *	which just echoes them as received.)
- *
- * NOTE that the payload starts at a long aligned offset,
- * regardless of 32 or 64 bit arch!
- */
-struct p_header80 {
-	u32	  magic;
-	u16	  command;
-	u16	  length;	/* bytes of data after this header */
-} __packed;
-
-/* Header for big packets, Used for data packets exceeding 64kB */
-struct p_header95 {
-	u16	  magic;	/* use DRBD_MAGIC_BIG here */
-	u16	  command;
-	u32	  length;
-} __packed;
-
-struct p_header100 {
-	u32	  magic;
-	u16	  volume;
-	u16	  command;
-	u32	  length;
-	u32	  pad;
-} __packed;
-
-extern unsigned int drbd_header_size(struct drbd_tconn *tconn);
-
-/* these defines must not be changed without changing the protocol version */
-#define DP_HARDBARRIER	      1 /* depricated */
-#define DP_RW_SYNC	      2 /* equals REQ_SYNC    */
-#define DP_MAY_SET_IN_SYNC    4
-#define DP_UNPLUG             8 /* not used anymore   */
-#define DP_FUA               16 /* equals REQ_FUA     */
-#define DP_FLUSH             32 /* equals REQ_FLUSH   */
-#define DP_DISCARD           64 /* equals REQ_DISCARD */
-#define DP_SEND_RECEIVE_ACK 128 /* This is a proto B write request */
-#define DP_SEND_WRITE_ACK   256 /* This is a proto C write request */
-
-struct p_data {
-	u64	    sector;    /* 64 bits sector number */
-	u64	    block_id;  /* to identify the request in protocol B&C */
-	u32	    seq_num;
-	u32	    dp_flags;
-} __packed;
-
-/*
- * commands which share a struct:
- *  p_block_ack:
- *   P_RECV_ACK (proto B), P_WRITE_ACK (proto C),
- *   P_SUPERSEDED (proto C, two-primaries conflict detection)
- *  p_block_req:
- *   P_DATA_REQUEST, P_RS_DATA_REQUEST
- */
-struct p_block_ack {
-	u64	    sector;
-	u64	    block_id;
-	u32	    blksize;
-	u32	    seq_num;
-} __packed;
-
-struct p_block_req {
-	u64 sector;
-	u64 block_id;
-	u32 blksize;
-	u32 pad;	/* to multiple of 8 Byte */
-} __packed;
-
-/*
- * commands with their own struct for additional fields:
- *   P_CONNECTION_FEATURES
- *   P_BARRIER
- *   P_BARRIER_ACK
- *   P_SYNC_PARAM
- *   ReportParams
- */
-
-struct p_connection_features {
-	u32 protocol_min;
-	u32 feature_flags;
-	u32 protocol_max;
-
-	/* should be more than enough for future enhancements
-	 * for now, feature_flags and the reserved array shall be zero.
-	 */
-
-	u32 _pad;
-	u64 reserved[7];
-} __packed;
-
-struct p_barrier {
-	u32 barrier;	/* barrier number _handle_ only */
-	u32 pad;	/* to multiple of 8 Byte */
-} __packed;
-
-struct p_barrier_ack {
-	u32 barrier;
-	u32 set_size;
-} __packed;
-
-struct p_rs_param {
-	u32 resync_rate;
-
-	      /* Since protocol version 88 and higher. */
-	char verify_alg[0];
-} __packed;
-
-struct p_rs_param_89 {
-	u32 resync_rate;
-        /* protocol version 89: */
-	char verify_alg[SHARED_SECRET_MAX];
-	char csums_alg[SHARED_SECRET_MAX];
-} __packed;
-
-struct p_rs_param_95 {
-	u32 resync_rate;
-	char verify_alg[SHARED_SECRET_MAX];
-	char csums_alg[SHARED_SECRET_MAX];
-	u32 c_plan_ahead;
-	u32 c_delay_target;
-	u32 c_fill_target;
-	u32 c_max_rate;
-} __packed;
-
-enum drbd_conn_flags {
-	CF_DISCARD_MY_DATA = 1,
-	CF_DRY_RUN = 2,
-};
-
-struct p_protocol {
-	u32 protocol;
-	u32 after_sb_0p;
-	u32 after_sb_1p;
-	u32 after_sb_2p;
-	u32 conn_flags;
-	u32 two_primaries;
-
-              /* Since protocol version 87 and higher. */
-	char integrity_alg[0];
-
-} __packed;
-
-struct p_uuids {
-	u64 uuid[UI_EXTENDED_SIZE];
-} __packed;
-
-struct p_rs_uuid {
-	u64	    uuid;
-} __packed;
-
-struct p_sizes {
-	u64	    d_size;  /* size of disk */
-	u64	    u_size;  /* user requested size */
-	u64	    c_size;  /* current exported size */
-	u32	    max_bio_size;  /* Maximal size of a BIO */
-	u16	    queue_order_type;  /* not yet implemented in DRBD*/
-	u16	    dds_flags; /* use enum dds_flags here. */
-} __packed;
-
-struct p_state {
-	u32	    state;
-} __packed;
-
-struct p_req_state {
-	u32	    mask;
-	u32	    val;
-} __packed;
-
-struct p_req_state_reply {
-	u32	    retcode;
-} __packed;
-
-struct p_drbd06_param {
-	u64	  size;
-	u32	  state;
-	u32	  blksize;
-	u32	  protocol;
-	u32	  version;
-	u32	  gen_cnt[5];
-	u32	  bit_map_gen[5];
-} __packed;
-
-struct p_block_desc {
-	u64 sector;
-	u32 blksize;
-	u32 pad;	/* to multiple of 8 Byte */
-} __packed;
-
-/* Valid values for the encoding field.
- * Bump proto version when changing this. */
-enum drbd_bitmap_code {
-	/* RLE_VLI_Bytes = 0,
-	 * and other bit variants had been defined during
-	 * algorithm evaluation. */
-	RLE_VLI_Bits = 2,
-};
-
-struct p_compressed_bm {
-	/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
-	 * (encoding & 0x80): polarity (set/unset) of first runlength
-	 * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
-	 * used to pad up to head.length bytes
-	 */
-	u8 encoding;
-
-	u8 code[0];
-} __packed;
-
-struct p_delay_probe93 {
-	u32     seq_num; /* sequence number to match the two probe packets */
-	u32     offset;  /* usecs the probe got sent after the reference time point */
-} __packed;
-
-/*
- * Bitmap packets need to fit within a single page on the sender and receiver,
- * so we are limited to 4 KiB (and not to PAGE_SIZE, which can be bigger).
- */
-#define DRBD_SOCKET_BUFFER_SIZE 4096
+extern unsigned int drbd_header_size(struct drbd_connection *connection);
 
 /**********************************************************************/
 enum drbd_thread_state {
@@ -517,9 +263,10 @@ struct drbd_thread {
 	struct completion stop;
 	enum drbd_thread_state t_state;
 	int (*function) (struct drbd_thread *);
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 	int reset_cpu_mask;
-	char name[9];
+	const char *name;
 };
 
 static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
@@ -535,18 +282,20 @@ static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
 struct drbd_work {
 	struct list_head list;
 	int (*cb)(struct drbd_work *, int cancel);
-	union {
-		struct drbd_conf *mdev;
-		struct drbd_tconn *tconn;
-	};
+};
+
+struct drbd_device_work {
+	struct drbd_work w;
+	struct drbd_device *device;
 };
 
 #include "drbd_interval.h"
 
-extern int drbd_wait_misc(struct drbd_conf *, struct drbd_interval *);
+extern int drbd_wait_misc(struct drbd_device *, struct drbd_interval *);
 
 struct drbd_request {
 	struct drbd_work w;
+	struct drbd_device *device;
 
 	/* if local IO is not allowed, will be NULL.
 	 * if local IO _is_ allowed, holds the locally submitted bio clone,
@@ -579,7 +328,7 @@ struct drbd_request {
 };
 
 struct drbd_epoch {
-	struct drbd_tconn *tconn;
+	struct drbd_connection *connection;
 	struct list_head list;
 	unsigned int barrier_nr;
 	atomic_t epoch_size; /* increased on every request added. */
@@ -587,6 +336,10 @@ struct drbd_epoch {
 	unsigned long flags;
 };
 
+/* Prototype declaration of function defined in drbd_receiver.c */
+int drbdd_init(struct drbd_thread *);
+int drbd_asender(struct drbd_thread *);
+
 /* drbd_epoch flag bits */
 enum {
 	DE_HAVE_BARRIER_NUMBER,
@@ -599,11 +352,6 @@ enum epoch_event {
 	EV_CLEANUP = 32, /* used as flag */
 };
 
-struct drbd_wq_barrier {
-	struct drbd_work w;
-	struct completion done;
-};
-
 struct digest_info {
 	int digest_size;
 	void *digest;
@@ -611,6 +359,7 @@ struct digest_info {
 
 struct drbd_peer_request {
 	struct drbd_work w;
+	struct drbd_peer_device *peer_device;
 	struct drbd_epoch *epoch; /* for writes */
 	struct page *pages;
 	atomic_t pending_bios;
@@ -663,7 +412,7 @@ enum {
 #define EE_SEND_WRITE_ACK	(1<<__EE_SEND_WRITE_ACK)
 #define EE_IN_INTERVAL_TREE	(1<<__EE_IN_INTERVAL_TREE)
 
-/* flag bits per mdev */
+/* flag bits per device */
 enum {
 	UNPLUG_REMOTE,		/* sending a "UnplugRemote" could help */
 	MD_DIRTY,		/* current uuids and flags not yet on disk */
@@ -695,7 +444,7 @@ enum {
 	READ_BALANCE_RR,
 };
 
-struct drbd_bitmap; /* opaque for drbd_conf */
+struct drbd_bitmap; /* opaque for drbd_device */
 
 /* definition of bits in bm_flags to be used in drbd_bm_lock
  * and drbd_bitmap_io and friends. */
@@ -769,7 +518,7 @@ struct drbd_backing_dev {
 	struct block_device *backing_bdev;
 	struct block_device *md_bdev;
 	struct drbd_md md;
-	struct disk_conf *disk_conf; /* RCU, for updates: mdev->tconn->conf_update */
+	struct disk_conf *disk_conf; /* RCU, for updates: resource->conf_update */
 	sector_t known_size; /* last known size of that backing device */
 };
 
@@ -782,8 +531,8 @@ struct bm_io_work {
 	struct drbd_work w;
 	char *why;
 	enum bm_flag flags;
-	int (*io_fn)(struct drbd_conf *mdev);
-	void (*done)(struct drbd_conf *mdev, int rv);
+	int (*io_fn)(struct drbd_device *device);
+	void (*done)(struct drbd_device *device, int rv);
 };
 
 enum write_ordering_e {
@@ -800,7 +549,7 @@ struct fifo_buffer {
 };
 extern struct fifo_buffer *fifo_alloc(int fifo_size);
 
-/* flag bits per tconn */
+/* flag bits per connection */
 enum {
 	NET_CONGESTED,		/* The data socket is congested */
 	RESOLVE_CONFLICTS,	/* Set on one node, cleared on the peer! */
@@ -822,23 +571,35 @@ enum {
 	DISCONNECT_SENT,
 };
 
-struct drbd_tconn {			/* is a resource from the config file */
-	char *name;			/* Resource name */
-	struct list_head all_tconn;	/* linked on global drbd_tconns */
+struct drbd_resource {
+	char *name;
 	struct kref kref;
-	struct idr volumes;		/* <tconn, vnr> to mdev mapping */
-	enum drbd_conns cstate;		/* Only C_STANDALONE to C_WF_REPORT_PARAMS */
+	struct idr devices;		/* volume number to device mapping */
+	struct list_head connections;
+	struct list_head resources;
+	struct res_opts res_opts;
+	struct mutex conf_update;	/* mutex for ready-copy-update of net_conf and disk_conf */
+	spinlock_t req_lock;
+
 	unsigned susp:1;		/* IO suspended by user */
 	unsigned susp_nod:1;		/* IO suspended because no data */
 	unsigned susp_fen:1;		/* IO suspended because fence peer handler runs */
+
+	cpumask_var_t cpu_mask;
+};
+
+struct drbd_connection {
+	struct list_head connections;
+	struct drbd_resource *resource;
+	struct kref kref;
+	struct idr peer_devices;	/* volume number to peer device mapping */
+	enum drbd_conns cstate;		/* Only C_STANDALONE to C_WF_REPORT_PARAMS */
 	struct mutex cstate_mutex;	/* Protects graceful disconnects */
 	unsigned int connect_cnt;	/* Inc each time a connection is established */
 
 	unsigned long flags;
 	struct net_conf *net_conf;	/* content protected by rcu */
-	struct mutex conf_update;	/* mutex for ready-copy-update of net_conf and disk_conf */
 	wait_queue_head_t ping_wait;	/* Woken upon reception of a ping, and a state change */
-	struct res_opts res_opts;
 
 	struct sockaddr_storage my_addr;
 	int my_addr_len;
@@ -851,12 +612,10 @@ struct drbd_tconn {			/* is a resource from the config file */
 	unsigned long last_received;	/* in jiffies, either socket */
 	unsigned int ko_count;
 
-	spinlock_t req_lock;
-
 	struct list_head transfer_log;	/* all requests not yet fully processed */
 
 	struct crypto_hash *cram_hmac_tfm;
-	struct crypto_hash *integrity_tfm;  /* checksums we compute, updates protected by tconn->data->mutex */
+	struct crypto_hash *integrity_tfm;  /* checksums we compute, updates protected by connection->data->mutex */
 	struct crypto_hash *peer_integrity_tfm;  /* checksums we verify, only accessed from receiver thread  */
 	struct crypto_hash *csums_tfm;
 	struct crypto_hash *verify_tfm;
@@ -875,7 +634,6 @@ struct drbd_tconn {			/* is a resource from the config file */
 	struct drbd_thread receiver;
 	struct drbd_thread worker;
 	struct drbd_thread asender;
-	cpumask_var_t cpu_mask;
 
 	/* sender side */
 	struct drbd_work_queue sender_work;
@@ -903,8 +661,15 @@ struct submit_worker {
 	struct list_head writes;
 };
 
-struct drbd_conf {
-	struct drbd_tconn *tconn;
+struct drbd_peer_device {
+	struct list_head peer_devices;
+	struct drbd_device *device;
+	struct drbd_connection *connection;
+};
+
+struct drbd_device {
+	struct drbd_resource *resource;
+	struct list_head peer_devices;
 	int vnr;			/* volume number within the connection */
 	struct kref kref;
 
@@ -920,11 +685,11 @@ struct drbd_conf {
 	struct gendisk	    *vdisk;
 
 	unsigned long last_reattach_jif;
-	struct drbd_work  resync_work,
-			  unplug_work,
-			  go_diskless,
-			  md_sync_work,
-			  start_resync_work;
+	struct drbd_work resync_work;
+	struct drbd_work unplug_work;
+	struct drbd_work go_diskless;
+	struct drbd_work md_sync_work;
+	struct drbd_work start_resync_work;
 	struct timer_list resync_timer;
 	struct timer_list md_sync_timer;
 	struct timer_list start_resync_timer;
@@ -1030,7 +795,7 @@ struct drbd_conf {
 	struct bm_io_work bm_io_work;
 	u64 ed_uuid; /* UUID of the exposed data */
 	struct mutex own_state_mutex;
-	struct mutex *state_mutex; /* either own_state_mutex or mdev->tconn->cstate_mutex */
+	struct mutex *state_mutex; /* either own_state_mutex or first_peer_device(device)->connection->cstate_mutex */
 	char congestion_reason;  /* Why we where congested... */
 	atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
 	atomic_t rs_sect_ev; /* for submitted resync data rate, both */
@@ -1038,7 +803,7 @@ struct drbd_conf {
 	int rs_last_events;  /* counter of read or write "events" (unit sectors)
 			      * on the lower level device when we last looked. */
 	int c_sync_rate; /* current resync rate after syncer throttle magic */
-	struct fifo_buffer *rs_plan_s; /* correction values of resync planer (RCU, tconn->conn_update) */
+	struct fifo_buffer *rs_plan_s; /* correction values of resync planer (RCU, connection->conn_update) */
 	int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
 	atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
 	unsigned int peer_max_bio_size;
@@ -1049,19 +814,46 @@ struct drbd_conf {
 	struct submit_worker submit;
 };
 
-static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
+static inline struct drbd_device *minor_to_device(unsigned int minor)
 {
-	return (struct drbd_conf *)idr_find(&minors, minor);
+	return (struct drbd_device *)idr_find(&drbd_devices, minor);
 }
 
-static inline unsigned int mdev_to_minor(struct drbd_conf *mdev)
+static inline struct drbd_peer_device *first_peer_device(struct drbd_device *device)
 {
-	return mdev->minor;
+	return list_first_entry(&device->peer_devices, struct drbd_peer_device, peer_devices);
 }
 
-static inline struct drbd_conf *vnr_to_mdev(struct drbd_tconn *tconn, int vnr)
+#define for_each_resource(resource, _resources) \
+	list_for_each_entry(resource, _resources, resources)
+
+#define for_each_resource_rcu(resource, _resources) \
+	list_for_each_entry_rcu(resource, _resources, resources)
+
+#define for_each_resource_safe(resource, tmp, _resources) \
+	list_for_each_entry_safe(resource, tmp, _resources, resources)
+
+#define for_each_connection(connection, resource) \
+	list_for_each_entry(connection, &resource->connections, connections)
+
+#define for_each_connection_rcu(connection, resource) \
+	list_for_each_entry_rcu(connection, &resource->connections, connections)
+
+#define for_each_connection_safe(connection, tmp, resource) \
+	list_for_each_entry_safe(connection, tmp, &resource->connections, connections)
+
+#define for_each_peer_device(peer_device, device) \
+	list_for_each_entry(peer_device, &device->peer_devices, peer_devices)
+
+#define for_each_peer_device_rcu(peer_device, device) \
+	list_for_each_entry_rcu(peer_device, &device->peer_devices, peer_devices)
+
+#define for_each_peer_device_safe(peer_device, tmp, device) \
+	list_for_each_entry_safe(peer_device, tmp, &device->peer_devices, peer_devices)
+
+static inline unsigned int device_to_minor(struct drbd_device *device)
 {
-	return (struct drbd_conf *)idr_find(&tconn->volumes, vnr);
+	return device->minor;
 }
 
 /*
@@ -1075,96 +867,93 @@ enum dds_flags {
 	DDSF_NO_RESYNC = 2, /* Do not run a resync for the new space */
 };
 
-extern void drbd_init_set_defaults(struct drbd_conf *mdev);
+extern void drbd_init_set_defaults(struct drbd_device *device);
 extern int  drbd_thread_start(struct drbd_thread *thi);
 extern void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait);
-extern char *drbd_task_to_thread_name(struct drbd_tconn *tconn, struct task_struct *task);
 #ifdef CONFIG_SMP
 extern void drbd_thread_current_set_cpu(struct drbd_thread *thi);
-extern void drbd_calc_cpu_mask(struct drbd_tconn *tconn);
 #else
 #define drbd_thread_current_set_cpu(A) ({})
-#define drbd_calc_cpu_mask(A) ({})
 #endif
-extern void tl_release(struct drbd_tconn *, unsigned int barrier_nr,
+extern void tl_release(struct drbd_connection *, unsigned int barrier_nr,
 		       unsigned int set_size);
-extern void tl_clear(struct drbd_tconn *);
-extern void drbd_free_sock(struct drbd_tconn *tconn);
-extern int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
+extern void tl_clear(struct drbd_connection *);
+extern void drbd_free_sock(struct drbd_connection *connection);
+extern int drbd_send(struct drbd_connection *connection, struct socket *sock,
 		     void *buf, size_t size, unsigned msg_flags);
-extern int drbd_send_all(struct drbd_tconn *, struct socket *, void *, size_t,
+extern int drbd_send_all(struct drbd_connection *, struct socket *, void *, size_t,
 			 unsigned);
 
-extern int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd);
-extern int drbd_send_protocol(struct drbd_tconn *tconn);
-extern int drbd_send_uuids(struct drbd_conf *mdev);
-extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev);
-extern void drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
-extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags);
-extern int drbd_send_state(struct drbd_conf *mdev, union drbd_state s);
-extern int drbd_send_current_state(struct drbd_conf *mdev);
-extern int drbd_send_sync_param(struct drbd_conf *mdev);
-extern void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr,
+extern int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cmd);
+extern int drbd_send_protocol(struct drbd_connection *connection);
+extern int drbd_send_uuids(struct drbd_peer_device *);
+extern int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *);
+extern void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *);
+extern int drbd_send_sizes(struct drbd_peer_device *, int trigger_reply, enum dds_flags flags);
+extern int drbd_send_state(struct drbd_peer_device *, union drbd_state s);
+extern int drbd_send_current_state(struct drbd_peer_device *);
+extern int drbd_send_sync_param(struct drbd_peer_device *);
+extern void drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr,
 			    u32 set_size);
-extern int drbd_send_ack(struct drbd_conf *, enum drbd_packet,
+extern int drbd_send_ack(struct drbd_peer_device *, enum drbd_packet,
 			 struct drbd_peer_request *);
-extern void drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packet cmd,
+extern void drbd_send_ack_rp(struct drbd_peer_device *, enum drbd_packet,
 			     struct p_block_req *rp);
-extern void drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packet cmd,
+extern void drbd_send_ack_dp(struct drbd_peer_device *, enum drbd_packet,
 			     struct p_data *dp, int data_size);
-extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packet cmd,
+extern int drbd_send_ack_ex(struct drbd_peer_device *, enum drbd_packet,
 			    sector_t sector, int blksize, u64 block_id);
-extern int drbd_send_out_of_sync(struct drbd_conf *, struct drbd_request *);
-extern int drbd_send_block(struct drbd_conf *, enum drbd_packet,
+extern int drbd_send_out_of_sync(struct drbd_peer_device *, struct drbd_request *);
+extern int drbd_send_block(struct drbd_peer_device *, enum drbd_packet,
 			   struct drbd_peer_request *);
-extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req);
-extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
+extern int drbd_send_dblock(struct drbd_peer_device *, struct drbd_request *req);
+extern int drbd_send_drequest(struct drbd_peer_device *, int cmd,
 			      sector_t sector, int size, u64 block_id);
-extern int drbd_send_drequest_csum(struct drbd_conf *mdev, sector_t sector,
+extern int drbd_send_drequest_csum(struct drbd_peer_device *, sector_t sector,
 				   int size, void *digest, int digest_size,
 				   enum drbd_packet cmd);
-extern int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size);
+extern int drbd_send_ov_request(struct drbd_peer_device *, sector_t sector, int size);
 
-extern int drbd_send_bitmap(struct drbd_conf *mdev);
-extern void drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode);
-extern void conn_send_sr_reply(struct drbd_tconn *tconn, enum drbd_state_rv retcode);
+extern int drbd_send_bitmap(struct drbd_device *device);
+extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
+extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode);
 extern void drbd_free_bc(struct drbd_backing_dev *ldev);
-extern void drbd_mdev_cleanup(struct drbd_conf *mdev);
-void drbd_print_uuids(struct drbd_conf *mdev, const char *text);
-
-extern void conn_md_sync(struct drbd_tconn *tconn);
-extern void drbd_md_write(struct drbd_conf *mdev, void *buffer);
-extern void drbd_md_sync(struct drbd_conf *mdev);
-extern int  drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
-extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
-extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
-extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
-extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local);
-extern void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local);
-extern void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
-extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
-extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
+extern void drbd_device_cleanup(struct drbd_device *device);
+void drbd_print_uuids(struct drbd_device *device, const char *text);
+
+extern void conn_md_sync(struct drbd_connection *connection);
+extern void drbd_md_write(struct drbd_device *device, void *buffer);
+extern void drbd_md_sync(struct drbd_device *device);
+extern int  drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev);
+extern void drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
+extern void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
+extern void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local);
+extern void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local);
+extern void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local);
+extern void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
+extern void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
+extern void drbd_md_clear_flag(struct drbd_device *device, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
 #ifndef DRBD_DEBUG_MD_SYNC
-extern void drbd_md_mark_dirty(struct drbd_conf *mdev);
+extern void drbd_md_mark_dirty(struct drbd_device *device);
 #else
 #define drbd_md_mark_dirty(m)	drbd_md_mark_dirty_(m, __LINE__ , __func__ )
-extern void drbd_md_mark_dirty_(struct drbd_conf *mdev,
+extern void drbd_md_mark_dirty_(struct drbd_device *device,
 		unsigned int line, const char *func);
 #endif
-extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
-				 int (*io_fn)(struct drbd_conf *),
-				 void (*done)(struct drbd_conf *, int),
+extern void drbd_queue_bitmap_io(struct drbd_device *device,
+				 int (*io_fn)(struct drbd_device *),
+				 void (*done)(struct drbd_device *, int),
 				 char *why, enum bm_flag flags);
-extern int drbd_bitmap_io(struct drbd_conf *mdev,
-		int (*io_fn)(struct drbd_conf *),
+extern int drbd_bitmap_io(struct drbd_device *device,
+		int (*io_fn)(struct drbd_device *),
 		char *why, enum bm_flag flags);
-extern int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
-		int (*io_fn)(struct drbd_conf *),
+extern int drbd_bitmap_io_from_worker(struct drbd_device *device,
+		int (*io_fn)(struct drbd_device *),
 		char *why, enum bm_flag flags);
-extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
-extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
-extern void drbd_ldev_destroy(struct drbd_conf *mdev);
+extern int drbd_bmio_set_n_write(struct drbd_device *device);
+extern int drbd_bmio_clear_n_write(struct drbd_device *device);
+extern void drbd_ldev_destroy(struct drbd_device *device);
 
 /* Meta data layout
  *
@@ -1350,52 +1139,52 @@ struct bm_extent {
 #define DRBD_MAX_SIZE_H80_PACKET (1U << 15) /* Header 80 only allows packets up to 32KiB data */
 #define DRBD_MAX_BIO_SIZE_P95    (1U << 17) /* Protocol 95 to 99 allows bios up to 128KiB */
 
-extern int  drbd_bm_init(struct drbd_conf *mdev);
-extern int  drbd_bm_resize(struct drbd_conf *mdev, sector_t sectors, int set_new_bits);
-extern void drbd_bm_cleanup(struct drbd_conf *mdev);
-extern void drbd_bm_set_all(struct drbd_conf *mdev);
-extern void drbd_bm_clear_all(struct drbd_conf *mdev);
+extern int  drbd_bm_init(struct drbd_device *device);
+extern int  drbd_bm_resize(struct drbd_device *device, sector_t sectors, int set_new_bits);
+extern void drbd_bm_cleanup(struct drbd_device *device);
+extern void drbd_bm_set_all(struct drbd_device *device);
+extern void drbd_bm_clear_all(struct drbd_device *device);
 /* set/clear/test only a few bits at a time */
 extern int  drbd_bm_set_bits(
-		struct drbd_conf *mdev, unsigned long s, unsigned long e);
+		struct drbd_device *device, unsigned long s, unsigned long e);
 extern int  drbd_bm_clear_bits(
-		struct drbd_conf *mdev, unsigned long s, unsigned long e);
+		struct drbd_device *device, unsigned long s, unsigned long e);
 extern int drbd_bm_count_bits(
-	struct drbd_conf *mdev, const unsigned long s, const unsigned long e);
+	struct drbd_device *device, const unsigned long s, const unsigned long e);
 /* bm_set_bits variant for use while holding drbd_bm_lock,
  * may process the whole bitmap in one go */
-extern void _drbd_bm_set_bits(struct drbd_conf *mdev,
+extern void _drbd_bm_set_bits(struct drbd_device *device,
 		const unsigned long s, const unsigned long e);
-extern int  drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr);
-extern int  drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
-extern int  drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
-extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
-extern void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr);
-extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
-extern int  drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local);
-extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local);
-extern int  drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
-extern size_t	     drbd_bm_words(struct drbd_conf *mdev);
-extern unsigned long drbd_bm_bits(struct drbd_conf *mdev);
-extern sector_t      drbd_bm_capacity(struct drbd_conf *mdev);
+extern int  drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
+extern int  drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
+extern int  drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local);
+extern int  drbd_bm_read(struct drbd_device *device) __must_hold(local);
+extern void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
+extern int  drbd_bm_write(struct drbd_device *device) __must_hold(local);
+extern int  drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
+extern int drbd_bm_write_all(struct drbd_device *device) __must_hold(local);
+extern int  drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local);
+extern size_t	     drbd_bm_words(struct drbd_device *device);
+extern unsigned long drbd_bm_bits(struct drbd_device *device);
+extern sector_t      drbd_bm_capacity(struct drbd_device *device);
 
 #define DRBD_END_OF_BITMAP	(~(unsigned long)0)
-extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
+extern unsigned long drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo);
 /* bm_find_next variants for use while you hold drbd_bm_lock() */
-extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
-extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo);
-extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev);
-extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev);
-extern int drbd_bm_rs_done(struct drbd_conf *mdev);
+extern unsigned long _drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo);
+extern unsigned long _drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo);
+extern unsigned long _drbd_bm_total_weight(struct drbd_device *device);
+extern unsigned long drbd_bm_total_weight(struct drbd_device *device);
+extern int drbd_bm_rs_done(struct drbd_device *device);
 /* for receive_bitmap */
-extern void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset,
+extern void drbd_bm_merge_lel(struct drbd_device *device, size_t offset,
 		size_t number, unsigned long *buffer);
 /* for _drbd_send_bitmap */
-extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset,
+extern void drbd_bm_get_lel(struct drbd_device *device, size_t offset,
 		size_t number, unsigned long *buffer);
 
-extern void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags);
-extern void drbd_bm_unlock(struct drbd_conf *mdev);
+extern void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags);
+extern void drbd_bm_unlock(struct drbd_device *device);
 /* drbd_main.c */
 
 extern struct kmem_cache *drbd_request_cache;
@@ -1439,35 +1228,40 @@ extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
 
 extern rwlock_t global_state_lock;
 
-extern int conn_lowest_minor(struct drbd_tconn *tconn);
-enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr);
-extern void drbd_minor_destroy(struct kref *kref);
+extern int conn_lowest_minor(struct drbd_connection *connection);
+enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned int minor, int vnr);
+extern void drbd_destroy_device(struct kref *kref);
+extern void drbd_delete_device(struct drbd_device *mdev);
+
+extern struct drbd_resource *drbd_create_resource(const char *name);
+extern void drbd_free_resource(struct drbd_resource *resource);
 
-extern int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts);
-extern struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts);
-extern void conn_destroy(struct kref *kref);
-struct drbd_tconn *conn_get_by_name(const char *name);
-extern struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+extern int set_resource_options(struct drbd_resource *resource, struct res_opts *res_opts);
+extern struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts);
+extern void drbd_destroy_connection(struct kref *kref);
+extern struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
 					    void *peer_addr, int peer_addr_len);
-extern void conn_free_crypto(struct drbd_tconn *tconn);
+extern struct drbd_resource *drbd_find_resource(const char *name);
+extern void drbd_destroy_resource(struct kref *kref);
+extern void conn_free_crypto(struct drbd_connection *connection);
 
 extern int proc_details;
 
 /* drbd_req */
 extern void do_submit(struct work_struct *ws);
-extern void __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
+extern void __drbd_make_request(struct drbd_device *, struct bio *, unsigned long);
 extern void drbd_make_request(struct request_queue *q, struct bio *bio);
-extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
+extern int drbd_read_remote(struct drbd_device *device, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
 
 
 /* drbd_nl.c */
 extern int drbd_msg_put_info(const char *info);
-extern void drbd_suspend_io(struct drbd_conf *mdev);
-extern void drbd_resume_io(struct drbd_conf *mdev);
+extern void drbd_suspend_io(struct drbd_device *device);
+extern void drbd_resume_io(struct drbd_device *device);
 extern char *ppsize(char *buf, unsigned long long size);
-extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, sector_t, int);
+extern sector_t drbd_new_dev_size(struct drbd_device *, struct drbd_backing_dev *, sector_t, int);
 enum determine_dev_size {
 	DS_ERROR_SHRINK = -3,
 	DS_ERROR_SPACE_MD = -2,
@@ -1478,48 +1272,47 @@ enum determine_dev_size {
 	DS_GREW_FROM_ZERO = 3,
 };
 extern enum determine_dev_size
-drbd_determine_dev_size(struct drbd_conf *, enum dds_flags, struct resize_parms *) __must_hold(local);
-extern void resync_after_online_grow(struct drbd_conf *);
-extern void drbd_reconsider_max_bio_size(struct drbd_conf *mdev);
-extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev,
+drbd_determine_dev_size(struct drbd_device *, enum dds_flags, struct resize_parms *) __must_hold(local);
+extern void resync_after_online_grow(struct drbd_device *);
+extern void drbd_reconsider_max_bio_size(struct drbd_device *device);
+extern enum drbd_state_rv drbd_set_role(struct drbd_device *device,
 					enum drbd_role new_role,
 					int force);
-extern bool conn_try_outdate_peer(struct drbd_tconn *tconn);
-extern void conn_try_outdate_peer_async(struct drbd_tconn *tconn);
-extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
+extern bool conn_try_outdate_peer(struct drbd_connection *connection);
+extern void conn_try_outdate_peer_async(struct drbd_connection *connection);
+extern int drbd_khelper(struct drbd_device *device, char *cmd);
 
 /* drbd_worker.c */
 extern int drbd_worker(struct drbd_thread *thi);
-enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor);
-void drbd_resync_after_changed(struct drbd_conf *mdev);
-extern void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side);
-extern void resume_next_sg(struct drbd_conf *mdev);
-extern void suspend_other_sg(struct drbd_conf *mdev);
-extern int drbd_resync_finished(struct drbd_conf *mdev);
+enum drbd_ret_code drbd_resync_after_valid(struct drbd_device *device, int o_minor);
+void drbd_resync_after_changed(struct drbd_device *device);
+extern void drbd_start_resync(struct drbd_device *device, enum drbd_conns side);
+extern void resume_next_sg(struct drbd_device *device);
+extern void suspend_other_sg(struct drbd_device *device);
+extern int drbd_resync_finished(struct drbd_device *device);
 /* maybe rather drbd_main.c ? */
-extern void *drbd_md_get_buffer(struct drbd_conf *mdev);
-extern void drbd_md_put_buffer(struct drbd_conf *mdev);
-extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
+extern void *drbd_md_get_buffer(struct drbd_device *device);
+extern void drbd_md_put_buffer(struct drbd_device *device);
+extern int drbd_md_sync_page_io(struct drbd_device *device,
 		struct drbd_backing_dev *bdev, sector_t sector, int rw);
-extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int);
-extern void wait_until_done_or_force_detached(struct drbd_conf *mdev,
+extern void drbd_ov_out_of_sync_found(struct drbd_device *, sector_t, int);
+extern void wait_until_done_or_force_detached(struct drbd_device *device,
 		struct drbd_backing_dev *bdev, unsigned int *done);
-extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
+extern void drbd_rs_controller_reset(struct drbd_device *device);
 
-static inline void ov_out_of_sync_print(struct drbd_conf *mdev)
+static inline void ov_out_of_sync_print(struct drbd_device *device)
 {
-	if (mdev->ov_last_oos_size) {
-		dev_err(DEV, "Out of sync: start=%llu, size=%lu (sectors)\n",
-		     (unsigned long long)mdev->ov_last_oos_start,
-		     (unsigned long)mdev->ov_last_oos_size);
+	if (device->ov_last_oos_size) {
+		drbd_err(device, "Out of sync: start=%llu, size=%lu (sectors)\n",
+		     (unsigned long long)device->ov_last_oos_start,
+		     (unsigned long)device->ov_last_oos_size);
 	}
-	mdev->ov_last_oos_size=0;
+	device->ov_last_oos_size = 0;
 }
 
 
-extern void drbd_csum_bio(struct drbd_conf *, struct crypto_hash *, struct bio *, void *);
-extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *,
-			 struct drbd_peer_request *, void *);
+extern void drbd_csum_bio(struct crypto_hash *, struct bio *, void *);
+extern void drbd_csum_ee(struct crypto_hash *, struct drbd_peer_request *, void *);
 /* worker callbacks */
 extern int w_e_end_data_req(struct drbd_work *, int);
 extern int w_e_end_rsdata_req(struct drbd_work *, int);
@@ -1529,10 +1322,8 @@ extern int w_e_end_ov_req(struct drbd_work *, int);
 extern int w_ov_finished(struct drbd_work *, int);
 extern int w_resync_timer(struct drbd_work *, int);
 extern int w_send_write_hint(struct drbd_work *, int);
-extern int w_make_resync_request(struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_work *, int);
 extern int w_send_read_req(struct drbd_work *, int);
-extern int w_prev_work_done(struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_work *, int);
 extern int w_restart_disk_io(struct drbd_work *, int);
 extern int w_send_out_of_sync(struct drbd_work *, int);
@@ -1542,27 +1333,24 @@ extern void resync_timer_fn(unsigned long data);
 extern void start_resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
-extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector);
-extern int drbd_submit_peer_request(struct drbd_conf *,
+extern int drbd_receiver(struct drbd_thread *thi);
+extern int drbd_asender(struct drbd_thread *thi);
+extern int drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector);
+extern int drbd_submit_peer_request(struct drbd_device *,
 				    struct drbd_peer_request *, const unsigned,
 				    const int);
-extern int drbd_free_peer_reqs(struct drbd_conf *, struct list_head *);
-extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_conf *, u64,
+extern int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
+extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
 						     sector_t, unsigned int,
 						     gfp_t) __must_hold(local);
-extern void __drbd_free_peer_req(struct drbd_conf *, struct drbd_peer_request *,
+extern void __drbd_free_peer_req(struct drbd_device *, struct drbd_peer_request *,
 				 int);
 #define drbd_free_peer_req(m,e) __drbd_free_peer_req(m, e, 0)
 #define drbd_free_net_peer_req(m,e) __drbd_free_peer_req(m, e, 1)
-extern struct page *drbd_alloc_pages(struct drbd_conf *, unsigned int, bool);
-extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
-extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
-extern void conn_flush_workqueue(struct drbd_tconn *tconn);
-extern int drbd_connected(struct drbd_conf *mdev);
-static inline void drbd_flush_workqueue(struct drbd_conf *mdev)
-{
-	conn_flush_workqueue(mdev->tconn);
-}
+extern struct page *drbd_alloc_pages(struct drbd_peer_device *, unsigned int, bool);
+extern void drbd_set_recv_tcq(struct drbd_device *device, int tcq_enabled);
+extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed);
+extern int drbd_connected(struct drbd_peer_device *);
 
 /* Yes, there is kernel_setsockopt, but only since 2.6.18.
  * So we have our own copy of it here. */
@@ -1613,7 +1401,7 @@ static inline void drbd_tcp_quickack(struct socket *sock)
 			(char*)&val, sizeof(val));
 }
 
-void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
@@ -1622,29 +1410,29 @@ extern const char *drbd_conn_str(enum drbd_conns s);
 extern const char *drbd_role_str(enum drbd_role s);
 
 /* drbd_actlog.c */
-extern int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i);
-extern void drbd_al_begin_io_commit(struct drbd_conf *mdev, bool delegate);
-extern bool drbd_al_begin_io_fastpath(struct drbd_conf *mdev, struct drbd_interval *i);
-extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate);
-extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i);
-extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector);
-extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
-extern int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
-extern void drbd_rs_cancel_all(struct drbd_conf *mdev);
-extern int drbd_rs_del_all(struct drbd_conf *mdev);
-extern void drbd_rs_failed_io(struct drbd_conf *mdev,
+extern int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i);
+extern void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate);
+extern bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i);
+extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate);
+extern void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i);
+extern void drbd_rs_complete_io(struct drbd_device *device, sector_t sector);
+extern int drbd_rs_begin_io(struct drbd_device *device, sector_t sector);
+extern int drbd_try_rs_begin_io(struct drbd_device *device, sector_t sector);
+extern void drbd_rs_cancel_all(struct drbd_device *device);
+extern int drbd_rs_del_all(struct drbd_device *device);
+extern void drbd_rs_failed_io(struct drbd_device *device,
 		sector_t sector, int size);
-extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go);
-extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector,
+extern void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go);
+extern void __drbd_set_in_sync(struct drbd_device *device, sector_t sector,
 		int size, const char *file, const unsigned int line);
-#define drbd_set_in_sync(mdev, sector, size) \
-	__drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__)
-extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
+#define drbd_set_in_sync(device, sector, size) \
+	__drbd_set_in_sync(device, sector, size, __FILE__, __LINE__)
+extern int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector,
 		int size, const char *file, const unsigned int line);
-#define drbd_set_out_of_sync(mdev, sector, size) \
-	__drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__)
-extern void drbd_al_shrink(struct drbd_conf *mdev);
-extern int drbd_initialize_al(struct drbd_conf *, void *);
+#define drbd_set_out_of_sync(device, sector, size) \
+	__drbd_set_out_of_sync(device, sector, size, __FILE__, __LINE__)
+extern void drbd_al_shrink(struct drbd_device *device);
+extern int drbd_initialize_al(struct drbd_device *, void *);
 
 /* drbd_nl.c */
 /* state info broadcast */
@@ -1661,7 +1449,7 @@ struct sib_info {
 		};
 	};
 };
-void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib);
+void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
 
 /*
  * inline helper functions
@@ -1690,26 +1478,27 @@ static inline int drbd_peer_req_has_active_page(struct drbd_peer_request *peer_r
 }
 
 static inline enum drbd_state_rv
-_drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+_drbd_set_state(struct drbd_device *device, union drbd_state ns,
 		enum chg_state_flags flags, struct completion *done)
 {
 	enum drbd_state_rv rv;
 
 	read_lock(&global_state_lock);
-	rv = __drbd_set_state(mdev, ns, flags, done);
+	rv = __drbd_set_state(device, ns, flags, done);
 	read_unlock(&global_state_lock);
 
 	return rv;
 }
 
-static inline union drbd_state drbd_read_state(struct drbd_conf *mdev)
+static inline union drbd_state drbd_read_state(struct drbd_device *device)
 {
+	struct drbd_resource *resource = device->resource;
 	union drbd_state rv;
 
-	rv.i = mdev->state.i;
-	rv.susp = mdev->tconn->susp;
-	rv.susp_nod = mdev->tconn->susp_nod;
-	rv.susp_fen = mdev->tconn->susp_fen;
+	rv.i = device->state.i;
+	rv.susp = resource->susp;
+	rv.susp_nod = resource->susp_nod;
+	rv.susp_fen = resource->susp_fen;
 
 	return rv;
 }
@@ -1722,22 +1511,22 @@ enum drbd_force_detach_flags {
 };
 
 #define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__)
-static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
+static inline void __drbd_chk_io_error_(struct drbd_device *device,
 		enum drbd_force_detach_flags df,
 		const char *where)
 {
 	enum drbd_io_error_p ep;
 
 	rcu_read_lock();
-	ep = rcu_dereference(mdev->ldev->disk_conf)->on_io_error;
+	ep = rcu_dereference(device->ldev->disk_conf)->on_io_error;
 	rcu_read_unlock();
 	switch (ep) {
 	case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */
 		if (df == DRBD_READ_ERROR || df == DRBD_WRITE_ERROR) {
 			if (__ratelimit(&drbd_ratelimit_state))
-				dev_err(DEV, "Local IO failed in %s.\n", where);
-			if (mdev->state.disk > D_INCONSISTENT)
-				_drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_HARD, NULL);
+				drbd_err(device, "Local IO failed in %s.\n", where);
+			if (device->state.disk > D_INCONSISTENT)
+				_drbd_set_state(_NS(device, disk, D_INCONSISTENT), CS_HARD, NULL);
 			break;
 		}
 		/* NOTE fall through for DRBD_META_IO_ERROR or DRBD_FORCE_DETACH */
@@ -1763,14 +1552,14 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
 		 * we read meta data only once during attach,
 		 * which will fail in case of errors.
 		 */
-		set_bit(WAS_IO_ERROR, &mdev->flags);
+		set_bit(WAS_IO_ERROR, &device->flags);
 		if (df == DRBD_READ_ERROR)
-			set_bit(WAS_READ_ERROR, &mdev->flags);
+			set_bit(WAS_READ_ERROR, &device->flags);
 		if (df == DRBD_FORCE_DETACH)
-			set_bit(FORCE_DETACH, &mdev->flags);
-		if (mdev->state.disk > D_FAILED) {
-			_drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL);
-			dev_err(DEV,
+			set_bit(FORCE_DETACH, &device->flags);
+		if (device->state.disk > D_FAILED) {
+			_drbd_set_state(_NS(device, disk, D_FAILED), CS_HARD, NULL);
+			drbd_err(device,
 				"Local IO failed in %s. Detaching...\n", where);
 		}
 		break;
@@ -1779,21 +1568,21 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
 
 /**
  * drbd_chk_io_error: Handle the on_io_error setting, should be called from all io completion handlers
- * @mdev:	 DRBD device.
+ * @device:	 DRBD device.
  * @error:	 Error code passed to the IO completion callback
  * @forcedetach: Force detach. I.e. the error happened while accessing the meta data
  *
  * See also drbd_main.c:after_state_ch() if (os.disk > D_FAILED && ns.disk == D_FAILED)
  */
 #define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__)
-static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
+static inline void drbd_chk_io_error_(struct drbd_device *device,
 	int error, enum drbd_force_detach_flags forcedetach, const char *where)
 {
 	if (error) {
 		unsigned long flags;
-		spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-		__drbd_chk_io_error_(mdev, forcedetach, where);
-		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		spin_lock_irqsave(&device->resource->req_lock, flags);
+		__drbd_chk_io_error_(device, forcedetach, where);
+		spin_unlock_irqrestore(&device->resource->req_lock, flags);
 	}
 }
 
@@ -1916,31 +1705,33 @@ drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 	wake_up(&q->q_wait);
 }
 
-static inline void wake_asender(struct drbd_tconn *tconn)
+extern void drbd_flush_workqueue(struct drbd_work_queue *work_queue);
+
+static inline void wake_asender(struct drbd_connection *connection)
 {
-	if (test_bit(SIGNAL_ASENDER, &tconn->flags))
-		force_sig(DRBD_SIG, tconn->asender.task);
+	if (test_bit(SIGNAL_ASENDER, &connection->flags))
+		force_sig(DRBD_SIG, connection->asender.task);
 }
 
-static inline void request_ping(struct drbd_tconn *tconn)
+static inline void request_ping(struct drbd_connection *connection)
 {
-	set_bit(SEND_PING, &tconn->flags);
-	wake_asender(tconn);
+	set_bit(SEND_PING, &connection->flags);
+	wake_asender(connection);
 }
 
-extern void *conn_prepare_command(struct drbd_tconn *, struct drbd_socket *);
-extern void *drbd_prepare_command(struct drbd_conf *, struct drbd_socket *);
-extern int conn_send_command(struct drbd_tconn *, struct drbd_socket *,
+extern void *conn_prepare_command(struct drbd_connection *, struct drbd_socket *);
+extern void *drbd_prepare_command(struct drbd_peer_device *, struct drbd_socket *);
+extern int conn_send_command(struct drbd_connection *, struct drbd_socket *,
 			     enum drbd_packet, unsigned int, void *,
 			     unsigned int);
-extern int drbd_send_command(struct drbd_conf *, struct drbd_socket *,
+extern int drbd_send_command(struct drbd_peer_device *, struct drbd_socket *,
 			     enum drbd_packet, unsigned int, void *,
 			     unsigned int);
 
-extern int drbd_send_ping(struct drbd_tconn *tconn);
-extern int drbd_send_ping_ack(struct drbd_tconn *tconn);
-extern int drbd_send_state_req(struct drbd_conf *, union drbd_state, union drbd_state);
-extern int conn_send_state_req(struct drbd_tconn *, union drbd_state, union drbd_state);
+extern int drbd_send_ping(struct drbd_connection *connection);
+extern int drbd_send_ping_ack(struct drbd_connection *connection);
+extern int drbd_send_state_req(struct drbd_peer_device *, union drbd_state, union drbd_state);
+extern int conn_send_state_req(struct drbd_connection *, union drbd_state, union drbd_state);
 
 static inline void drbd_thread_stop(struct drbd_thread *thi)
 {
@@ -1979,22 +1770,22 @@ static inline void drbd_thread_restart_nowait(struct drbd_thread *thi)
  *  _req_mod(req, CONNECTION_LOST_WHILE_PENDING)
  *     [from tl_clear_barrier]
  */
-static inline void inc_ap_pending(struct drbd_conf *mdev)
+static inline void inc_ap_pending(struct drbd_device *device)
 {
-	atomic_inc(&mdev->ap_pending_cnt);
+	atomic_inc(&device->ap_pending_cnt);
 }
 
 #define ERR_IF_CNT_IS_NEGATIVE(which, func, line)			\
-	if (atomic_read(&mdev->which) < 0)				\
-		dev_err(DEV, "in %s:%d: " #which " = %d < 0 !\n",	\
+	if (atomic_read(&device->which) < 0)				\
+		drbd_err(device, "in %s:%d: " #which " = %d < 0 !\n",	\
 			func, line,					\
-			atomic_read(&mdev->which))
+			atomic_read(&device->which))
 
-#define dec_ap_pending(mdev) _dec_ap_pending(mdev, __FUNCTION__, __LINE__)
-static inline void _dec_ap_pending(struct drbd_conf *mdev, const char *func, int line)
+#define dec_ap_pending(device) _dec_ap_pending(device, __FUNCTION__, __LINE__)
+static inline void _dec_ap_pending(struct drbd_device *device, const char *func, int line)
 {
-	if (atomic_dec_and_test(&mdev->ap_pending_cnt))
-		wake_up(&mdev->misc_wait);
+	if (atomic_dec_and_test(&device->ap_pending_cnt))
+		wake_up(&device->misc_wait);
 	ERR_IF_CNT_IS_NEGATIVE(ap_pending_cnt, func, line);
 }
 
@@ -2004,15 +1795,15 @@ static inline void _dec_ap_pending(struct drbd_conf *mdev, const char *func, int
  * C_SYNC_SOURCE sends P_RS_DATA_REPLY   (and expects P_WRITE_ACK with ID_SYNCER)
  *					   (or P_NEG_ACK with ID_SYNCER)
  */
-static inline void inc_rs_pending(struct drbd_conf *mdev)
+static inline void inc_rs_pending(struct drbd_device *device)
 {
-	atomic_inc(&mdev->rs_pending_cnt);
+	atomic_inc(&device->rs_pending_cnt);
 }
 
-#define dec_rs_pending(mdev) _dec_rs_pending(mdev, __FUNCTION__, __LINE__)
-static inline void _dec_rs_pending(struct drbd_conf *mdev, const char *func, int line)
+#define dec_rs_pending(device) _dec_rs_pending(device, __FUNCTION__, __LINE__)
+static inline void _dec_rs_pending(struct drbd_device *device, const char *func, int line)
 {
-	atomic_dec(&mdev->rs_pending_cnt);
+	atomic_dec(&device->rs_pending_cnt);
 	ERR_IF_CNT_IS_NEGATIVE(rs_pending_cnt, func, line);
 }
 
@@ -2025,103 +1816,104 @@ static inline void _dec_rs_pending(struct drbd_conf *mdev, const char *func, int
  *  receive_DataRequest (receive_RSDataRequest) we need to send back P_DATA
  *  receive_Barrier_*	we need to send a P_BARRIER_ACK
  */
-static inline void inc_unacked(struct drbd_conf *mdev)
+static inline void inc_unacked(struct drbd_device *device)
 {
-	atomic_inc(&mdev->unacked_cnt);
+	atomic_inc(&device->unacked_cnt);
 }
 
-#define dec_unacked(mdev) _dec_unacked(mdev, __FUNCTION__, __LINE__)
-static inline void _dec_unacked(struct drbd_conf *mdev, const char *func, int line)
+#define dec_unacked(device) _dec_unacked(device, __FUNCTION__, __LINE__)
+static inline void _dec_unacked(struct drbd_device *device, const char *func, int line)
 {
-	atomic_dec(&mdev->unacked_cnt);
+	atomic_dec(&device->unacked_cnt);
 	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
-#define sub_unacked(mdev, n) _sub_unacked(mdev, n, __FUNCTION__, __LINE__)
-static inline void _sub_unacked(struct drbd_conf *mdev, int n, const char *func, int line)
+#define sub_unacked(device, n) _sub_unacked(device, n, __FUNCTION__, __LINE__)
+static inline void _sub_unacked(struct drbd_device *device, int n, const char *func, int line)
 {
-	atomic_sub(n, &mdev->unacked_cnt);
+	atomic_sub(n, &device->unacked_cnt);
 	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
 /**
- * get_ldev() - Increase the ref count on mdev->ldev. Returns 0 if there is no ldev
+ * get_ldev() - Increase the ref count on device->ldev. Returns 0 if there is no ldev
  * @M:		DRBD device.
  *
- * You have to call put_ldev() when finished working with mdev->ldev.
+ * You have to call put_ldev() when finished working with device->ldev.
  */
 #define get_ldev(M) __cond_lock(local, _get_ldev_if_state(M,D_INCONSISTENT))
 #define get_ldev_if_state(M,MINS) __cond_lock(local, _get_ldev_if_state(M,MINS))
 
-static inline void put_ldev(struct drbd_conf *mdev)
+static inline void put_ldev(struct drbd_device *device)
 {
-	int i = atomic_dec_return(&mdev->local_cnt);
+	int i = atomic_dec_return(&device->local_cnt);
 
 	/* This may be called from some endio handler,
 	 * so we must not sleep here. */
 
 	__release(local);
-	D_ASSERT(i >= 0);
+	D_ASSERT(device, i >= 0);
 	if (i == 0) {
-		if (mdev->state.disk == D_DISKLESS)
+		if (device->state.disk == D_DISKLESS)
 			/* even internal references gone, safe to destroy */
-			drbd_ldev_destroy(mdev);
-		if (mdev->state.disk == D_FAILED) {
+			drbd_ldev_destroy(device);
+		if (device->state.disk == D_FAILED) {
 			/* all application IO references gone. */
-			if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
-				drbd_queue_work(&mdev->tconn->sender_work, &mdev->go_diskless);
+			if (!test_and_set_bit(GO_DISKLESS, &device->flags))
+				drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+						&device->go_diskless);
 		}
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 	}
 }
 
 #ifndef __CHECKER__
-static inline int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
+static inline int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins)
 {
 	int io_allowed;
 
 	/* never get a reference while D_DISKLESS */
-	if (mdev->state.disk == D_DISKLESS)
+	if (device->state.disk == D_DISKLESS)
 		return 0;
 
-	atomic_inc(&mdev->local_cnt);
-	io_allowed = (mdev->state.disk >= mins);
+	atomic_inc(&device->local_cnt);
+	io_allowed = (device->state.disk >= mins);
 	if (!io_allowed)
-		put_ldev(mdev);
+		put_ldev(device);
 	return io_allowed;
 }
 #else
-extern int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins);
+extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins);
 #endif
 
 /* you must have an "get_ldev" reference */
-static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
+static inline void drbd_get_syncer_progress(struct drbd_device *device,
 		unsigned long *bits_left, unsigned int *per_mil_done)
 {
 	/* this is to break it at compile time when we change that, in case we
 	 * want to support more than (1<<32) bits on a 32bit arch. */
-	typecheck(unsigned long, mdev->rs_total);
+	typecheck(unsigned long, device->rs_total);
 
 	/* note: both rs_total and rs_left are in bits, i.e. in
 	 * units of BM_BLOCK_SIZE.
 	 * for the percentage, we don't care. */
 
-	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
-		*bits_left = mdev->ov_left;
+	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
+		*bits_left = device->ov_left;
 	else
-		*bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+		*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
 	/* >> 10 to prevent overflow,
 	 * +1 to prevent division by zero */
-	if (*bits_left > mdev->rs_total) {
+	if (*bits_left > device->rs_total) {
 		/* doh. maybe a logic bug somewhere.
 		 * may also be just a race condition
 		 * between this and a disconnect during sync.
 		 * for now, just prevent in-kernel buffer overflow.
 		 */
 		smp_rmb();
-		dev_warn(DEV, "cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n",
-				drbd_conn_str(mdev->state.conn),
-				*bits_left, mdev->rs_total, mdev->rs_failed);
+		drbd_warn(device, "cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n",
+				drbd_conn_str(device->state.conn),
+				*bits_left, device->rs_total, device->rs_failed);
 		*per_mil_done = 0;
 	} else {
 		/* Make sure the division happens in long context.
@@ -2133,9 +1925,9 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
 		 * Note: currently we don't support such large bitmaps on 32bit
 		 * arch anyways, but no harm done to be prepared for it here.
 		 */
-		unsigned int shift = mdev->rs_total > UINT_MAX ? 16 : 10;
+		unsigned int shift = device->rs_total > UINT_MAX ? 16 : 10;
 		unsigned long left = *bits_left >> shift;
-		unsigned long total = 1UL + (mdev->rs_total >> shift);
+		unsigned long total = 1UL + (device->rs_total >> shift);
 		unsigned long tmp = 1000UL - left * 1000UL/total;
 		*per_mil_done = tmp;
 	}
@@ -2145,22 +1937,22 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
 /* this throttles on-the-fly application requests
  * according to max_buffers settings;
  * maybe re-implement using semaphores? */
-static inline int drbd_get_max_buffers(struct drbd_conf *mdev)
+static inline int drbd_get_max_buffers(struct drbd_device *device)
 {
 	struct net_conf *nc;
 	int mxb;
 
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 	mxb = nc ? nc->max_buffers : 1000000;  /* arbitrary limit on open requests */
 	rcu_read_unlock();
 
 	return mxb;
 }
 
-static inline int drbd_state_is_stable(struct drbd_conf *mdev)
+static inline int drbd_state_is_stable(struct drbd_device *device)
 {
-	union drbd_dev_state s = mdev->state;
+	union drbd_dev_state s = device->state;
 
 	/* DO NOT add a default clause, we want the compiler to warn us
 	 * for any newly introduced state we may have forgotten to add here */
@@ -2194,7 +1986,7 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 
 		/* Allow IO in BM exchange states with new protocols */
 	case C_WF_BITMAP_S:
-		if (mdev->tconn->agreed_pro_version < 96)
+		if (first_peer_device(device)->connection->agreed_pro_version < 96)
 			return 0;
 		break;
 
@@ -2228,20 +2020,20 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 	return 1;
 }
 
-static inline int drbd_suspended(struct drbd_conf *mdev)
+static inline int drbd_suspended(struct drbd_device *device)
 {
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_resource *resource = device->resource;
 
-	return tconn->susp || tconn->susp_fen || tconn->susp_nod;
+	return resource->susp || resource->susp_fen || resource->susp_nod;
 }
 
-static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
+static inline bool may_inc_ap_bio(struct drbd_device *device)
 {
-	int mxb = drbd_get_max_buffers(mdev);
+	int mxb = drbd_get_max_buffers(device);
 
-	if (drbd_suspended(mdev))
+	if (drbd_suspended(device))
 		return false;
-	if (test_bit(SUSPEND_IO, &mdev->flags))
+	if (test_bit(SUSPEND_IO, &device->flags))
 		return false;
 
 	/* to avoid potential deadlock or bitmap corruption,
@@ -2249,32 +2041,32 @@ static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
 	 * to start during "stable" states. */
 
 	/* no new io accepted when attaching or detaching the disk */
-	if (!drbd_state_is_stable(mdev))
+	if (!drbd_state_is_stable(device))
 		return false;
 
 	/* since some older kernels don't have atomic_add_unless,
 	 * and we are within the spinlock anyways, we have this workaround.  */
-	if (atomic_read(&mdev->ap_bio_cnt) > mxb)
+	if (atomic_read(&device->ap_bio_cnt) > mxb)
 		return false;
-	if (test_bit(BITMAP_IO, &mdev->flags))
+	if (test_bit(BITMAP_IO, &device->flags))
 		return false;
 	return true;
 }
 
-static inline bool inc_ap_bio_cond(struct drbd_conf *mdev)
+static inline bool inc_ap_bio_cond(struct drbd_device *device)
 {
 	bool rv = false;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	rv = may_inc_ap_bio(mdev);
+	spin_lock_irq(&device->resource->req_lock);
+	rv = may_inc_ap_bio(device);
 	if (rv)
-		atomic_inc(&mdev->ap_bio_cnt);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+		atomic_inc(&device->ap_bio_cnt);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	return rv;
 }
 
-static inline void inc_ap_bio(struct drbd_conf *mdev)
+static inline void inc_ap_bio(struct drbd_device *device)
 {
 	/* we wait here
 	 *    as long as the device is suspended
@@ -2284,42 +2076,44 @@ static inline void inc_ap_bio(struct drbd_conf *mdev)
 	 * to avoid races with the reconnect code,
 	 * we need to atomic_inc within the spinlock. */
 
-	wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev));
+	wait_event(device->misc_wait, inc_ap_bio_cond(device));
 }
 
-static inline void dec_ap_bio(struct drbd_conf *mdev)
+static inline void dec_ap_bio(struct drbd_device *device)
 {
-	int mxb = drbd_get_max_buffers(mdev);
-	int ap_bio = atomic_dec_return(&mdev->ap_bio_cnt);
+	int mxb = drbd_get_max_buffers(device);
+	int ap_bio = atomic_dec_return(&device->ap_bio_cnt);
 
-	D_ASSERT(ap_bio >= 0);
+	D_ASSERT(device, ap_bio >= 0);
 
-	if (ap_bio == 0 && test_bit(BITMAP_IO, &mdev->flags)) {
-		if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
-			drbd_queue_work(&mdev->tconn->sender_work, &mdev->bm_io_work.w);
+	if (ap_bio == 0 && test_bit(BITMAP_IO, &device->flags)) {
+		if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
+			drbd_queue_work(&first_peer_device(device)->
+				connection->sender_work,
+				&device->bm_io_work.w);
 	}
 
 	/* this currently does wake_up for every dec_ap_bio!
 	 * maybe rather introduce some type of hysteresis?
 	 * e.g. (ap_bio == mxb/2 || ap_bio == 0) ? */
 	if (ap_bio < mxb)
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 }
 
-static inline bool verify_can_do_stop_sector(struct drbd_conf *mdev)
+static inline bool verify_can_do_stop_sector(struct drbd_device *device)
 {
-	return mdev->tconn->agreed_pro_version >= 97 &&
-		mdev->tconn->agreed_pro_version != 100;
+	return first_peer_device(device)->connection->agreed_pro_version >= 97 &&
+		first_peer_device(device)->connection->agreed_pro_version != 100;
 }
 
-static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
+static inline int drbd_set_ed_uuid(struct drbd_device *device, u64 val)
 {
-	int changed = mdev->ed_uuid != val;
-	mdev->ed_uuid = val;
+	int changed = device->ed_uuid != val;
+	device->ed_uuid = val;
 	return changed;
 }
 
-static inline int drbd_queue_order_type(struct drbd_conf *mdev)
+static inline int drbd_queue_order_type(struct drbd_device *device)
 {
 	/* sorry, we currently have no working implementation
 	 * of distributed TCQ stuff */
@@ -2329,23 +2123,29 @@ static inline int drbd_queue_order_type(struct drbd_conf *mdev)
 	return QUEUE_ORDERED_NONE;
 }
 
-static inline void drbd_md_flush(struct drbd_conf *mdev)
+static inline void drbd_md_flush(struct drbd_device *device)
 {
 	int r;
 
-	if (mdev->ldev == NULL) {
-		dev_warn(DEV, "mdev->ldev == NULL in drbd_md_flush\n");
+	if (device->ldev == NULL) {
+		drbd_warn(device, "device->ldev == NULL in drbd_md_flush\n");
 		return;
 	}
 
-	if (test_bit(MD_NO_FUA, &mdev->flags))
+	if (test_bit(MD_NO_FUA, &device->flags))
 		return;
 
-	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_NOIO, NULL);
+	r = blkdev_issue_flush(device->ldev->md_bdev, GFP_NOIO, NULL);
 	if (r) {
-		set_bit(MD_NO_FUA, &mdev->flags);
-		dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
+		set_bit(MD_NO_FUA, &device->flags);
+		drbd_err(device, "meta data flush failed with status %d, disabling md-flushes\n", r);
 	}
 }
 
+static inline struct drbd_connection *first_connection(struct drbd_resource *resource)
+{
+	return list_first_entry(&resource->connections,
+				struct drbd_connection, connections);
+}
+
 #endif
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 929468e1512a..331e5cc1227d 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -52,16 +52,12 @@
 
 #include <linux/drbd_limits.h>
 #include "drbd_int.h"
+#include "drbd_protocol.h"
 #include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */
 
 #include "drbd_vli.h"
 
 static DEFINE_MUTEX(drbd_main_mutex);
-int drbdd_init(struct drbd_thread *);
-int drbd_worker(struct drbd_thread *);
-int drbd_asender(struct drbd_thread *);
-
-int drbd_init(void);
 static int drbd_open(struct block_device *bdev, fmode_t mode);
 static void drbd_release(struct gendisk *gd, fmode_t mode);
 static int w_md_sync(struct drbd_work *w, int unused);
@@ -118,8 +114,8 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0
 /* in 2.6.x, our device mapping and config info contains our virtual gendisks
  * as member "struct gendisk *vdisk;"
  */
-struct idr minors;
-struct list_head drbd_tconns;  /* list of struct drbd_tconn */
+struct idr drbd_devices;
+struct list_head drbd_resources;
 
 struct kmem_cache *drbd_request_cache;
 struct kmem_cache *drbd_ee_cache;	/* peer requests */
@@ -166,15 +162,15 @@ struct bio *bio_alloc_drbd(gfp_t gfp_mask)
 /* When checking with sparse, and this is an inline function, sparse will
    give tons of false positives. When this is a real functions sparse works.
  */
-int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
+int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins)
 {
 	int io_allowed;
 
-	atomic_inc(&mdev->local_cnt);
-	io_allowed = (mdev->state.disk >= mins);
+	atomic_inc(&device->local_cnt);
+	io_allowed = (device->state.disk >= mins);
 	if (!io_allowed) {
-		if (atomic_dec_and_test(&mdev->local_cnt))
-			wake_up(&mdev->misc_wait);
+		if (atomic_dec_and_test(&device->local_cnt))
+			wake_up(&device->misc_wait);
 	}
 	return io_allowed;
 }
@@ -183,7 +179,7 @@ int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
 
 /**
  * tl_release() - mark as BARRIER_ACKED all requests in the corresponding transfer log epoch
- * @tconn:	DRBD connection.
+ * @connection:	DRBD connection.
  * @barrier_nr:	Expected identifier of the DRBD write barrier packet.
  * @set_size:	Expected number of requests before that barrier.
  *
@@ -191,7 +187,7 @@ int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
  * epoch of not yet barrier-acked requests, this function will cause a
  * termination of the connection.
  */
-void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
+void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
 		unsigned int set_size)
 {
 	struct drbd_request *r;
@@ -199,11 +195,11 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
 	int expect_epoch = 0;
 	int expect_size = 0;
 
-	spin_lock_irq(&tconn->req_lock);
+	spin_lock_irq(&connection->resource->req_lock);
 
 	/* find oldest not yet barrier-acked write request,
 	 * count writes in its epoch. */
-	list_for_each_entry(r, &tconn->transfer_log, tl_requests) {
+	list_for_each_entry(r, &connection->transfer_log, tl_requests) {
 		const unsigned s = r->rq_state;
 		if (!req) {
 			if (!(s & RQ_WRITE))
@@ -228,18 +224,18 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
 
 	/* first some paranoia code */
 	if (req == NULL) {
-		conn_err(tconn, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
+		drbd_err(connection, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
 			 barrier_nr);
 		goto bail;
 	}
 	if (expect_epoch != barrier_nr) {
-		conn_err(tconn, "BAD! BarrierAck #%u received, expected #%u!\n",
+		drbd_err(connection, "BAD! BarrierAck #%u received, expected #%u!\n",
 			 barrier_nr, expect_epoch);
 		goto bail;
 	}
 
 	if (expect_size != set_size) {
-		conn_err(tconn, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+		drbd_err(connection, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
 			 barrier_nr, set_size, expect_size);
 		goto bail;
 	}
@@ -248,90 +244,91 @@ void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
 	/* this extra list walk restart is paranoia,
 	 * to catch requests being barrier-acked "unexpectedly".
 	 * It usually should find the same req again, or some READ preceding it. */
-	list_for_each_entry(req, &tconn->transfer_log, tl_requests)
+	list_for_each_entry(req, &connection->transfer_log, tl_requests)
 		if (req->epoch == expect_epoch)
 			break;
-	list_for_each_entry_safe_from(req, r, &tconn->transfer_log, tl_requests) {
+	list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
 		if (req->epoch != expect_epoch)
 			break;
 		_req_mod(req, BARRIER_ACKED);
 	}
-	spin_unlock_irq(&tconn->req_lock);
+	spin_unlock_irq(&connection->resource->req_lock);
 
 	return;
 
 bail:
-	spin_unlock_irq(&tconn->req_lock);
-	conn_request_state(tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
+	spin_unlock_irq(&connection->resource->req_lock);
+	conn_request_state(connection, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 }
 
 
 /**
  * _tl_restart() - Walks the transfer log, and applies an action to all requests
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @what:       The action/event to perform with all request objects
  *
  * @what might be one of CONNECTION_LOST_WHILE_PENDING, RESEND, FAIL_FROZEN_DISK_IO,
  * RESTART_FROZEN_DISK_IO.
  */
 /* must hold resource->req_lock */
-void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
 {
 	struct drbd_request *req, *r;
 
-	list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests)
+	list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests)
 		_req_mod(req, what);
 }
 
-void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+void tl_restart(struct drbd_connection *connection, enum drbd_req_event what)
 {
-	spin_lock_irq(&tconn->req_lock);
-	_tl_restart(tconn, what);
-	spin_unlock_irq(&tconn->req_lock);
+	spin_lock_irq(&connection->resource->req_lock);
+	_tl_restart(connection, what);
+	spin_unlock_irq(&connection->resource->req_lock);
 }
 
 /**
  * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * This is called after the connection to the peer was lost. The storage covered
  * by the requests on the transfer gets marked as our of sync. Called from the
  * receiver thread and the worker thread.
  */
-void tl_clear(struct drbd_tconn *tconn)
+void tl_clear(struct drbd_connection *connection)
 {
-	tl_restart(tconn, CONNECTION_LOST_WHILE_PENDING);
+	tl_restart(connection, CONNECTION_LOST_WHILE_PENDING);
 }
 
 /**
- * tl_abort_disk_io() - Abort disk I/O for all requests for a certain mdev in the TL
- * @mdev:	DRBD device.
+ * tl_abort_disk_io() - Abort disk I/O for all requests for a certain device in the TL
+ * @device:	DRBD device.
  */
-void tl_abort_disk_io(struct drbd_conf *mdev)
+void tl_abort_disk_io(struct drbd_device *device)
 {
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	struct drbd_request *req, *r;
 
-	spin_lock_irq(&tconn->req_lock);
-	list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests) {
+	spin_lock_irq(&connection->resource->req_lock);
+	list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests) {
 		if (!(req->rq_state & RQ_LOCAL_PENDING))
 			continue;
-		if (req->w.mdev != mdev)
+		if (req->device != device)
 			continue;
 		_req_mod(req, ABORT_DISK_IO);
 	}
-	spin_unlock_irq(&tconn->req_lock);
+	spin_unlock_irq(&connection->resource->req_lock);
 }
 
 static int drbd_thread_setup(void *arg)
 {
 	struct drbd_thread *thi = (struct drbd_thread *) arg;
-	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_resource *resource = thi->resource;
 	unsigned long flags;
 	int retval;
 
 	snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s",
-		 thi->name[0], thi->tconn->name);
+		 thi->name[0],
+		 resource->name);
 
 restart:
 	retval = thi->function(thi);
@@ -349,7 +346,7 @@ restart:
 	 */
 
 	if (thi->t_state == RESTARTING) {
-		conn_info(tconn, "Restarting %s thread\n", thi->name);
+		drbd_info(resource, "Restarting %s thread\n", thi->name);
 		thi->t_state = RUNNING;
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		goto restart;
@@ -361,29 +358,32 @@ restart:
 	complete_all(&thi->stop);
 	spin_unlock_irqrestore(&thi->t_lock, flags);
 
-	conn_info(tconn, "Terminating %s\n", current->comm);
+	drbd_info(resource, "Terminating %s\n", current->comm);
 
 	/* Release mod reference taken when thread was started */
 
-	kref_put(&tconn->kref, &conn_destroy);
+	if (thi->connection)
+		kref_put(&thi->connection->kref, drbd_destroy_connection);
+	kref_put(&resource->kref, drbd_destroy_resource);
 	module_put(THIS_MODULE);
 	return retval;
 }
 
-static void drbd_thread_init(struct drbd_tconn *tconn, struct drbd_thread *thi,
-			     int (*func) (struct drbd_thread *), char *name)
+static void drbd_thread_init(struct drbd_resource *resource, struct drbd_thread *thi,
+			     int (*func) (struct drbd_thread *), const char *name)
 {
 	spin_lock_init(&thi->t_lock);
 	thi->task    = NULL;
 	thi->t_state = NONE;
 	thi->function = func;
-	thi->tconn = tconn;
-	strncpy(thi->name, name, ARRAY_SIZE(thi->name));
+	thi->resource = resource;
+	thi->connection = NULL;
+	thi->name = name;
 }
 
 int drbd_thread_start(struct drbd_thread *thi)
 {
-	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_resource *resource = thi->resource;
 	struct task_struct *nt;
 	unsigned long flags;
 
@@ -393,17 +393,19 @@ int drbd_thread_start(struct drbd_thread *thi)
 
 	switch (thi->t_state) {
 	case NONE:
-		conn_info(tconn, "Starting %s thread (from %s [%d])\n",
+		drbd_info(resource, "Starting %s thread (from %s [%d])\n",
 			 thi->name, current->comm, current->pid);
 
 		/* Get ref on module for thread - this is released when thread exits */
 		if (!try_module_get(THIS_MODULE)) {
-			conn_err(tconn, "Failed to get module reference in drbd_thread_start\n");
+			drbd_err(resource, "Failed to get module reference in drbd_thread_start\n");
 			spin_unlock_irqrestore(&thi->t_lock, flags);
 			return false;
 		}
 
-		kref_get(&thi->tconn->kref);
+		kref_get(&resource->kref);
+		if (thi->connection)
+			kref_get(&thi->connection->kref);
 
 		init_completion(&thi->stop);
 		thi->reset_cpu_mask = 1;
@@ -412,12 +414,14 @@ int drbd_thread_start(struct drbd_thread *thi)
 		flush_signals(current); /* otherw. may get -ERESTARTNOINTR */
 
 		nt = kthread_create(drbd_thread_setup, (void *) thi,
-				    "drbd_%c_%s", thi->name[0], thi->tconn->name);
+				    "drbd_%c_%s", thi->name[0], thi->resource->name);
 
 		if (IS_ERR(nt)) {
-			conn_err(tconn, "Couldn't start thread\n");
+			drbd_err(resource, "Couldn't start thread\n");
 
-			kref_put(&tconn->kref, &conn_destroy);
+			if (thi->connection)
+				kref_put(&thi->connection->kref, drbd_destroy_connection);
+			kref_put(&resource->kref, drbd_destroy_resource);
 			module_put(THIS_MODULE);
 			return false;
 		}
@@ -429,7 +433,7 @@ int drbd_thread_start(struct drbd_thread *thi)
 		break;
 	case EXITING:
 		thi->t_state = RESTARTING;
-		conn_info(tconn, "Restarting %s thread (from %s [%d])\n",
+		drbd_info(resource, "Restarting %s thread (from %s [%d])\n",
 				thi->name, current->comm, current->pid);
 		/* fall through */
 	case RUNNING:
@@ -478,65 +482,60 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
 		wait_for_completion(&thi->stop);
 }
 
-static struct drbd_thread *drbd_task_to_thread(struct drbd_tconn *tconn, struct task_struct *task)
-{
-	struct drbd_thread *thi =
-		task == tconn->receiver.task ? &tconn->receiver :
-		task == tconn->asender.task  ? &tconn->asender :
-		task == tconn->worker.task   ? &tconn->worker : NULL;
-
-	return thi;
-}
-
-char *drbd_task_to_thread_name(struct drbd_tconn *tconn, struct task_struct *task)
+int conn_lowest_minor(struct drbd_connection *connection)
 {
-	struct drbd_thread *thi = drbd_task_to_thread(tconn, task);
-	return thi ? thi->name : task->comm;
-}
-
-int conn_lowest_minor(struct drbd_tconn *tconn)
-{
-	struct drbd_conf *mdev;
-	int vnr = 0, m;
+	struct drbd_peer_device *peer_device;
+	int vnr = 0, minor = -1;
 
 	rcu_read_lock();
-	mdev = idr_get_next(&tconn->volumes, &vnr);
-	m = mdev ? mdev_to_minor(mdev) : -1;
+	peer_device = idr_get_next(&connection->peer_devices, &vnr);
+	if (peer_device)
+		minor = device_to_minor(peer_device->device);
 	rcu_read_unlock();
 
-	return m;
+	return minor;
 }
 
 #ifdef CONFIG_SMP
 /**
  * drbd_calc_cpu_mask() - Generate CPU masks, spread over all CPUs
- * @mdev:	DRBD device.
  *
- * Forces all threads of a device onto the same CPU. This is beneficial for
+ * Forces all threads of a resource onto the same CPU. This is beneficial for
  * DRBD's performance. May be overwritten by user's configuration.
  */
-void drbd_calc_cpu_mask(struct drbd_tconn *tconn)
+static void drbd_calc_cpu_mask(cpumask_var_t *cpu_mask)
 {
-	int ord, cpu;
+	unsigned int *resources_per_cpu, min_index = ~0;
 
-	/* user override. */
-	if (cpumask_weight(tconn->cpu_mask))
-		return;
+	resources_per_cpu = kzalloc(nr_cpu_ids * sizeof(*resources_per_cpu), GFP_KERNEL);
+	if (resources_per_cpu) {
+		struct drbd_resource *resource;
+		unsigned int cpu, min = ~0;
 
-	ord = conn_lowest_minor(tconn) % cpumask_weight(cpu_online_mask);
-	for_each_online_cpu(cpu) {
-		if (ord-- == 0) {
-			cpumask_set_cpu(cpu, tconn->cpu_mask);
-			return;
+		rcu_read_lock();
+		for_each_resource_rcu(resource, &drbd_resources) {
+			for_each_cpu(cpu, resource->cpu_mask)
+				resources_per_cpu[cpu]++;
 		}
+		rcu_read_unlock();
+		for_each_online_cpu(cpu) {
+			if (resources_per_cpu[cpu] < min) {
+				min = resources_per_cpu[cpu];
+				min_index = cpu;
+			}
+		}
+		kfree(resources_per_cpu);
 	}
-	/* should not be reached */
-	cpumask_setall(tconn->cpu_mask);
+	if (min_index == ~0) {
+		cpumask_setall(*cpu_mask);
+		return;
+	}
+	cpumask_set_cpu(min_index, *cpu_mask);
 }
 
 /**
  * drbd_thread_current_set_cpu() - modifies the cpu mask of the _current_ thread
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @thi:	drbd_thread object
  *
  * call in the "main loop" of _all_ threads, no need for any mutex, current won't die
@@ -544,13 +543,16 @@ void drbd_calc_cpu_mask(struct drbd_tconn *tconn)
  */
 void drbd_thread_current_set_cpu(struct drbd_thread *thi)
 {
+	struct drbd_resource *resource = thi->resource;
 	struct task_struct *p = current;
 
 	if (!thi->reset_cpu_mask)
 		return;
 	thi->reset_cpu_mask = 0;
-	set_cpus_allowed_ptr(p, thi->tconn->cpu_mask);
+	set_cpus_allowed_ptr(p, resource->cpu_mask);
 }
+#else
+#define drbd_calc_cpu_mask(A) ({})
 #endif
 
 /**
@@ -560,9 +562,9 @@ void drbd_thread_current_set_cpu(struct drbd_thread *thi)
  * word aligned on 64-bit architectures.  (The bitmap send and receive code
  * relies on this.)
  */
-unsigned int drbd_header_size(struct drbd_tconn *tconn)
+unsigned int drbd_header_size(struct drbd_connection *connection)
 {
-	if (tconn->agreed_pro_version >= 100) {
+	if (connection->agreed_pro_version >= 100) {
 		BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header100), 8));
 		return sizeof(struct p_header100);
 	} else {
@@ -600,44 +602,44 @@ static unsigned int prepare_header100(struct p_header100 *h, enum drbd_packet cm
 	return sizeof(struct p_header100);
 }
 
-static unsigned int prepare_header(struct drbd_tconn *tconn, int vnr,
+static unsigned int prepare_header(struct drbd_connection *connection, int vnr,
 				   void *buffer, enum drbd_packet cmd, int size)
 {
-	if (tconn->agreed_pro_version >= 100)
+	if (connection->agreed_pro_version >= 100)
 		return prepare_header100(buffer, cmd, size, vnr);
-	else if (tconn->agreed_pro_version >= 95 &&
+	else if (connection->agreed_pro_version >= 95 &&
 		 size > DRBD_MAX_SIZE_H80_PACKET)
 		return prepare_header95(buffer, cmd, size);
 	else
 		return prepare_header80(buffer, cmd, size);
 }
 
-static void *__conn_prepare_command(struct drbd_tconn *tconn,
+static void *__conn_prepare_command(struct drbd_connection *connection,
 				    struct drbd_socket *sock)
 {
 	if (!sock->socket)
 		return NULL;
-	return sock->sbuf + drbd_header_size(tconn);
+	return sock->sbuf + drbd_header_size(connection);
 }
 
-void *conn_prepare_command(struct drbd_tconn *tconn, struct drbd_socket *sock)
+void *conn_prepare_command(struct drbd_connection *connection, struct drbd_socket *sock)
 {
 	void *p;
 
 	mutex_lock(&sock->mutex);
-	p = __conn_prepare_command(tconn, sock);
+	p = __conn_prepare_command(connection, sock);
 	if (!p)
 		mutex_unlock(&sock->mutex);
 
 	return p;
 }
 
-void *drbd_prepare_command(struct drbd_conf *mdev, struct drbd_socket *sock)
+void *drbd_prepare_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock)
 {
-	return conn_prepare_command(mdev->tconn, sock);
+	return conn_prepare_command(peer_device->connection, sock);
 }
 
-static int __send_command(struct drbd_tconn *tconn, int vnr,
+static int __send_command(struct drbd_connection *connection, int vnr,
 			  struct drbd_socket *sock, enum drbd_packet cmd,
 			  unsigned int header_size, void *data,
 			  unsigned int size)
@@ -654,82 +656,82 @@ static int __send_command(struct drbd_tconn *tconn, int vnr,
 	 */
 	msg_flags = data ? MSG_MORE : 0;
 
-	header_size += prepare_header(tconn, vnr, sock->sbuf, cmd,
+	header_size += prepare_header(connection, vnr, sock->sbuf, cmd,
 				      header_size + size);
-	err = drbd_send_all(tconn, sock->socket, sock->sbuf, header_size,
+	err = drbd_send_all(connection, sock->socket, sock->sbuf, header_size,
 			    msg_flags);
 	if (data && !err)
-		err = drbd_send_all(tconn, sock->socket, data, size, 0);
+		err = drbd_send_all(connection, sock->socket, data, size, 0);
 	return err;
 }
 
-static int __conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+static int __conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
 			       enum drbd_packet cmd, unsigned int header_size,
 			       void *data, unsigned int size)
 {
-	return __send_command(tconn, 0, sock, cmd, header_size, data, size);
+	return __send_command(connection, 0, sock, cmd, header_size, data, size);
 }
 
-int conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+int conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
 		      enum drbd_packet cmd, unsigned int header_size,
 		      void *data, unsigned int size)
 {
 	int err;
 
-	err = __conn_send_command(tconn, sock, cmd, header_size, data, size);
+	err = __conn_send_command(connection, sock, cmd, header_size, data, size);
 	mutex_unlock(&sock->mutex);
 	return err;
 }
 
-int drbd_send_command(struct drbd_conf *mdev, struct drbd_socket *sock,
+int drbd_send_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock,
 		      enum drbd_packet cmd, unsigned int header_size,
 		      void *data, unsigned int size)
 {
 	int err;
 
-	err = __send_command(mdev->tconn, mdev->vnr, sock, cmd, header_size,
-			     data, size);
+	err = __send_command(peer_device->connection, peer_device->device->vnr,
+			     sock, cmd, header_size, data, size);
 	mutex_unlock(&sock->mutex);
 	return err;
 }
 
-int drbd_send_ping(struct drbd_tconn *tconn)
+int drbd_send_ping(struct drbd_connection *connection)
 {
 	struct drbd_socket *sock;
 
-	sock = &tconn->meta;
-	if (!conn_prepare_command(tconn, sock))
+	sock = &connection->meta;
+	if (!conn_prepare_command(connection, sock))
 		return -EIO;
-	return conn_send_command(tconn, sock, P_PING, 0, NULL, 0);
+	return conn_send_command(connection, sock, P_PING, 0, NULL, 0);
 }
 
-int drbd_send_ping_ack(struct drbd_tconn *tconn)
+int drbd_send_ping_ack(struct drbd_connection *connection)
 {
 	struct drbd_socket *sock;
 
-	sock = &tconn->meta;
-	if (!conn_prepare_command(tconn, sock))
+	sock = &connection->meta;
+	if (!conn_prepare_command(connection, sock))
 		return -EIO;
-	return conn_send_command(tconn, sock, P_PING_ACK, 0, NULL, 0);
+	return conn_send_command(connection, sock, P_PING_ACK, 0, NULL, 0);
 }
 
-int drbd_send_sync_param(struct drbd_conf *mdev)
+int drbd_send_sync_param(struct drbd_peer_device *peer_device)
 {
 	struct drbd_socket *sock;
 	struct p_rs_param_95 *p;
 	int size;
-	const int apv = mdev->tconn->agreed_pro_version;
+	const int apv = peer_device->connection->agreed_pro_version;
 	enum drbd_packet cmd;
 	struct net_conf *nc;
 	struct disk_conf *dc;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(peer_device->connection->net_conf);
 
 	size = apv <= 87 ? sizeof(struct p_rs_param)
 		: apv == 88 ? sizeof(struct p_rs_param)
@@ -742,14 +744,14 @@ int drbd_send_sync_param(struct drbd_conf *mdev)
 	/* initialize verify_alg and csums_alg */
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-	if (get_ldev(mdev)) {
-		dc = rcu_dereference(mdev->ldev->disk_conf);
+	if (get_ldev(peer_device->device)) {
+		dc = rcu_dereference(peer_device->device->ldev->disk_conf);
 		p->resync_rate = cpu_to_be32(dc->resync_rate);
 		p->c_plan_ahead = cpu_to_be32(dc->c_plan_ahead);
 		p->c_delay_target = cpu_to_be32(dc->c_delay_target);
 		p->c_fill_target = cpu_to_be32(dc->c_fill_target);
 		p->c_max_rate = cpu_to_be32(dc->c_max_rate);
-		put_ldev(mdev);
+		put_ldev(peer_device->device);
 	} else {
 		p->resync_rate = cpu_to_be32(DRBD_RESYNC_RATE_DEF);
 		p->c_plan_ahead = cpu_to_be32(DRBD_C_PLAN_AHEAD_DEF);
@@ -764,33 +766,33 @@ int drbd_send_sync_param(struct drbd_conf *mdev)
 		strcpy(p->csums_alg, nc->csums_alg);
 	rcu_read_unlock();
 
-	return drbd_send_command(mdev, sock, cmd, size, NULL, 0);
+	return drbd_send_command(peer_device, sock, cmd, size, NULL, 0);
 }
 
-int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd)
+int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cmd)
 {
 	struct drbd_socket *sock;
 	struct p_protocol *p;
 	struct net_conf *nc;
 	int size, cf;
 
-	sock = &tconn->data;
-	p = __conn_prepare_command(tconn, sock);
+	sock = &connection->data;
+	p = __conn_prepare_command(connection, sock);
 	if (!p)
 		return -EIO;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 
-	if (nc->tentative && tconn->agreed_pro_version < 92) {
+	if (nc->tentative && connection->agreed_pro_version < 92) {
 		rcu_read_unlock();
 		mutex_unlock(&sock->mutex);
-		conn_err(tconn, "--dry-run is not supported by peer");
+		drbd_err(connection, "--dry-run is not supported by peer");
 		return -EOPNOTSUPP;
 	}
 
 	size = sizeof(*p);
-	if (tconn->agreed_pro_version >= 87)
+	if (connection->agreed_pro_version >= 87)
 		size += strlen(nc->integrity_alg) + 1;
 
 	p->protocol      = cpu_to_be32(nc->wire_protocol);
@@ -805,128 +807,131 @@ int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd)
 		cf |= CF_DRY_RUN;
 	p->conn_flags    = cpu_to_be32(cf);
 
-	if (tconn->agreed_pro_version >= 87)
+	if (connection->agreed_pro_version >= 87)
 		strcpy(p->integrity_alg, nc->integrity_alg);
 	rcu_read_unlock();
 
-	return __conn_send_command(tconn, sock, cmd, size, NULL, 0);
+	return __conn_send_command(connection, sock, cmd, size, NULL, 0);
 }
 
-int drbd_send_protocol(struct drbd_tconn *tconn)
+int drbd_send_protocol(struct drbd_connection *connection)
 {
 	int err;
 
-	mutex_lock(&tconn->data.mutex);
-	err = __drbd_send_protocol(tconn, P_PROTOCOL);
-	mutex_unlock(&tconn->data.mutex);
+	mutex_lock(&connection->data.mutex);
+	err = __drbd_send_protocol(connection, P_PROTOCOL);
+	mutex_unlock(&connection->data.mutex);
 
 	return err;
 }
 
-int _drbd_send_uuids(struct drbd_conf *mdev, u64 uuid_flags)
+static int _drbd_send_uuids(struct drbd_peer_device *peer_device, u64 uuid_flags)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
 	struct p_uuids *p;
 	int i;
 
-	if (!get_ldev_if_state(mdev, D_NEGOTIATING))
+	if (!get_ldev_if_state(device, D_NEGOTIATING))
 		return 0;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p) {
-		put_ldev(mdev);
+		put_ldev(device);
 		return -EIO;
 	}
-	spin_lock_irq(&mdev->ldev->md.uuid_lock);
+	spin_lock_irq(&device->ldev->md.uuid_lock);
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
-		p->uuid[i] = cpu_to_be64(mdev->ldev->md.uuid[i]);
-	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
+		p->uuid[i] = cpu_to_be64(device->ldev->md.uuid[i]);
+	spin_unlock_irq(&device->ldev->md.uuid_lock);
 
-	mdev->comm_bm_set = drbd_bm_total_weight(mdev);
-	p->uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set);
+	device->comm_bm_set = drbd_bm_total_weight(device);
+	p->uuid[UI_SIZE] = cpu_to_be64(device->comm_bm_set);
 	rcu_read_lock();
-	uuid_flags |= rcu_dereference(mdev->tconn->net_conf)->discard_my_data ? 1 : 0;
+	uuid_flags |= rcu_dereference(peer_device->connection->net_conf)->discard_my_data ? 1 : 0;
 	rcu_read_unlock();
-	uuid_flags |= test_bit(CRASHED_PRIMARY, &mdev->flags) ? 2 : 0;
-	uuid_flags |= mdev->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
+	uuid_flags |= test_bit(CRASHED_PRIMARY, &device->flags) ? 2 : 0;
+	uuid_flags |= device->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
 	p->uuid[UI_FLAGS] = cpu_to_be64(uuid_flags);
 
-	put_ldev(mdev);
-	return drbd_send_command(mdev, sock, P_UUIDS, sizeof(*p), NULL, 0);
+	put_ldev(device);
+	return drbd_send_command(peer_device, sock, P_UUIDS, sizeof(*p), NULL, 0);
 }
 
-int drbd_send_uuids(struct drbd_conf *mdev)
+int drbd_send_uuids(struct drbd_peer_device *peer_device)
 {
-	return _drbd_send_uuids(mdev, 0);
+	return _drbd_send_uuids(peer_device, 0);
 }
 
-int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev)
+int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *peer_device)
 {
-	return _drbd_send_uuids(mdev, 8);
+	return _drbd_send_uuids(peer_device, 8);
 }
 
-void drbd_print_uuids(struct drbd_conf *mdev, const char *text)
+void drbd_print_uuids(struct drbd_device *device, const char *text)
 {
-	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
-		u64 *uuid = mdev->ldev->md.uuid;
-		dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX\n",
+	if (get_ldev_if_state(device, D_NEGOTIATING)) {
+		u64 *uuid = device->ldev->md.uuid;
+		drbd_info(device, "%s %016llX:%016llX:%016llX:%016llX\n",
 		     text,
 		     (unsigned long long)uuid[UI_CURRENT],
 		     (unsigned long long)uuid[UI_BITMAP],
 		     (unsigned long long)uuid[UI_HISTORY_START],
 		     (unsigned long long)uuid[UI_HISTORY_END]);
-		put_ldev(mdev);
+		put_ldev(device);
 	} else {
-		dev_info(DEV, "%s effective data uuid: %016llX\n",
+		drbd_info(device, "%s effective data uuid: %016llX\n",
 				text,
-				(unsigned long long)mdev->ed_uuid);
+				(unsigned long long)device->ed_uuid);
 	}
 }
 
-void drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
+void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *peer_device)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
 	struct p_rs_uuid *p;
 	u64 uuid;
 
-	D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
+	D_ASSERT(device, device->state.disk == D_UP_TO_DATE);
 
-	uuid = mdev->ldev->md.uuid[UI_BITMAP];
+	uuid = device->ldev->md.uuid[UI_BITMAP];
 	if (uuid && uuid != UUID_JUST_CREATED)
 		uuid = uuid + UUID_NEW_BM_OFFSET;
 	else
 		get_random_bytes(&uuid, sizeof(u64));
-	drbd_uuid_set(mdev, UI_BITMAP, uuid);
-	drbd_print_uuids(mdev, "updated sync UUID");
-	drbd_md_sync(mdev);
+	drbd_uuid_set(device, UI_BITMAP, uuid);
+	drbd_print_uuids(device, "updated sync UUID");
+	drbd_md_sync(device);
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (p) {
 		p->uuid = cpu_to_be64(uuid);
-		drbd_send_command(mdev, sock, P_SYNC_UUID, sizeof(*p), NULL, 0);
+		drbd_send_command(peer_device, sock, P_SYNC_UUID, sizeof(*p), NULL, 0);
 	}
 }
 
-int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags)
+int drbd_send_sizes(struct drbd_peer_device *peer_device, int trigger_reply, enum dds_flags flags)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
 	struct p_sizes *p;
 	sector_t d_size, u_size;
 	int q_order_type;
 	unsigned int max_bio_size;
 
-	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
-		D_ASSERT(mdev->ldev->backing_bdev);
-		d_size = drbd_get_max_capacity(mdev->ldev);
+	if (get_ldev_if_state(device, D_NEGOTIATING)) {
+		D_ASSERT(device, device->ldev->backing_bdev);
+		d_size = drbd_get_max_capacity(device->ldev);
 		rcu_read_lock();
-		u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+		u_size = rcu_dereference(device->ldev->disk_conf)->disk_size;
 		rcu_read_unlock();
-		q_order_type = drbd_queue_order_type(mdev);
-		max_bio_size = queue_max_hw_sectors(mdev->ldev->backing_bdev->bd_disk->queue) << 9;
+		q_order_type = drbd_queue_order_type(device);
+		max_bio_size = queue_max_hw_sectors(device->ldev->backing_bdev->bd_disk->queue) << 9;
 		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE);
-		put_ldev(mdev);
+		put_ldev(device);
 	} else {
 		d_size = 0;
 		u_size = 0;
@@ -934,45 +939,45 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
 		max_bio_size = DRBD_MAX_BIO_SIZE; /* ... multiple BIOs per peer_request */
 	}
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 
-	if (mdev->tconn->agreed_pro_version <= 94)
+	if (peer_device->connection->agreed_pro_version <= 94)
 		max_bio_size = min(max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
-	else if (mdev->tconn->agreed_pro_version < 100)
+	else if (peer_device->connection->agreed_pro_version < 100)
 		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE_P95);
 
 	p->d_size = cpu_to_be64(d_size);
 	p->u_size = cpu_to_be64(u_size);
-	p->c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
+	p->c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(device->this_bdev));
 	p->max_bio_size = cpu_to_be32(max_bio_size);
 	p->queue_order_type = cpu_to_be16(q_order_type);
 	p->dds_flags = cpu_to_be16(flags);
-	return drbd_send_command(mdev, sock, P_SIZES, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, P_SIZES, sizeof(*p), NULL, 0);
 }
 
 /**
  * drbd_send_current_state() - Sends the drbd state to the peer
- * @mdev:	DRBD device.
+ * @peer_device:	DRBD peer device.
  */
-int drbd_send_current_state(struct drbd_conf *mdev)
+int drbd_send_current_state(struct drbd_peer_device *peer_device)
 {
 	struct drbd_socket *sock;
 	struct p_state *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
-	p->state = cpu_to_be32(mdev->state.i); /* Within the send mutex */
-	return drbd_send_command(mdev, sock, P_STATE, sizeof(*p), NULL, 0);
+	p->state = cpu_to_be32(peer_device->device->state.i); /* Within the send mutex */
+	return drbd_send_command(peer_device, sock, P_STATE, sizeof(*p), NULL, 0);
 }
 
 /**
  * drbd_send_state() - After a state change, sends the new state to the peer
- * @mdev:      DRBD device.
+ * @peer_device:      DRBD peer device.
  * @state:     the state to send, not necessarily the current state.
  *
  * Each state change queues an "after_state_ch" work, which will eventually
@@ -980,73 +985,73 @@ int drbd_send_current_state(struct drbd_conf *mdev)
  * between queuing and processing of the after_state_ch work, we still
  * want to send each intermediary state in the order it occurred.
  */
-int drbd_send_state(struct drbd_conf *mdev, union drbd_state state)
+int drbd_send_state(struct drbd_peer_device *peer_device, union drbd_state state)
 {
 	struct drbd_socket *sock;
 	struct p_state *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->state = cpu_to_be32(state.i); /* Within the send mutex */
-	return drbd_send_command(mdev, sock, P_STATE, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, P_STATE, sizeof(*p), NULL, 0);
 }
 
-int drbd_send_state_req(struct drbd_conf *mdev, union drbd_state mask, union drbd_state val)
+int drbd_send_state_req(struct drbd_peer_device *peer_device, union drbd_state mask, union drbd_state val)
 {
 	struct drbd_socket *sock;
 	struct p_req_state *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->mask = cpu_to_be32(mask.i);
 	p->val = cpu_to_be32(val.i);
-	return drbd_send_command(mdev, sock, P_STATE_CHG_REQ, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, P_STATE_CHG_REQ, sizeof(*p), NULL, 0);
 }
 
-int conn_send_state_req(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
+int conn_send_state_req(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
 {
 	enum drbd_packet cmd;
 	struct drbd_socket *sock;
 	struct p_req_state *p;
 
-	cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
-	sock = &tconn->data;
-	p = conn_prepare_command(tconn, sock);
+	cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
+	sock = &connection->data;
+	p = conn_prepare_command(connection, sock);
 	if (!p)
 		return -EIO;
 	p->mask = cpu_to_be32(mask.i);
 	p->val = cpu_to_be32(val.i);
-	return conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
+	return conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
 }
 
-void drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode)
+void drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv retcode)
 {
 	struct drbd_socket *sock;
 	struct p_req_state_reply *p;
 
-	sock = &mdev->tconn->meta;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->meta;
+	p = drbd_prepare_command(peer_device, sock);
 	if (p) {
 		p->retcode = cpu_to_be32(retcode);
-		drbd_send_command(mdev, sock, P_STATE_CHG_REPLY, sizeof(*p), NULL, 0);
+		drbd_send_command(peer_device, sock, P_STATE_CHG_REPLY, sizeof(*p), NULL, 0);
 	}
 }
 
-void conn_send_sr_reply(struct drbd_tconn *tconn, enum drbd_state_rv retcode)
+void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode)
 {
 	struct drbd_socket *sock;
 	struct p_req_state_reply *p;
-	enum drbd_packet cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
+	enum drbd_packet cmd = connection->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
 
-	sock = &tconn->meta;
-	p = conn_prepare_command(tconn, sock);
+	sock = &connection->meta;
+	p = conn_prepare_command(connection, sock);
 	if (p) {
 		p->retcode = cpu_to_be32(retcode);
-		conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
+		conn_send_command(connection, sock, cmd, sizeof(*p), NULL, 0);
 	}
 }
 
@@ -1067,7 +1072,7 @@ static void dcbp_set_pad_bits(struct p_compressed_bm *p, int n)
 	p->encoding = (p->encoding & (~0x7 << 4)) | (n << 4);
 }
 
-int fill_bitmap_rle_bits(struct drbd_conf *mdev,
+static int fill_bitmap_rle_bits(struct drbd_device *device,
 			 struct p_compressed_bm *p,
 			 unsigned int size,
 			 struct bm_xfer_ctx *c)
@@ -1082,9 +1087,9 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 
 	/* may we use this feature? */
 	rcu_read_lock();
-	use_rle = rcu_dereference(mdev->tconn->net_conf)->use_rle;
+	use_rle = rcu_dereference(first_peer_device(device)->connection->net_conf)->use_rle;
 	rcu_read_unlock();
-	if (!use_rle || mdev->tconn->agreed_pro_version < 90)
+	if (!use_rle || first_peer_device(device)->connection->agreed_pro_version < 90)
 		return 0;
 
 	if (c->bit_offset >= c->bm_bits)
@@ -1104,8 +1109,8 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 	/* see how much plain bits we can stuff into one packet
 	 * using RLE and VLI. */
 	do {
-		tmp = (toggle == 0) ? _drbd_bm_find_next_zero(mdev, c->bit_offset)
-				    : _drbd_bm_find_next(mdev, c->bit_offset);
+		tmp = (toggle == 0) ? _drbd_bm_find_next_zero(device, c->bit_offset)
+				    : _drbd_bm_find_next(device, c->bit_offset);
 		if (tmp == -1UL)
 			tmp = c->bm_bits;
 		rl = tmp - c->bit_offset;
@@ -1125,7 +1130,7 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 		/* paranoia: catch zero runlength.
 		 * can only happen if bitmap is modified while we scan it. */
 		if (rl == 0) {
-			dev_err(DEV, "unexpected zero runlength while encoding bitmap "
+			drbd_err(device, "unexpected zero runlength while encoding bitmap "
 			    "t:%u bo:%lu\n", toggle, c->bit_offset);
 			return -1;
 		}
@@ -1134,7 +1139,7 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 		if (bits == -ENOBUFS) /* buffer full */
 			break;
 		if (bits <= 0) {
-			dev_err(DEV, "error while encoding bitmap: %d\n", bits);
+			drbd_err(device, "error while encoding bitmap: %d\n", bits);
 			return 0;
 		}
 
@@ -1171,21 +1176,21 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
  * code upon failure.
  */
 static int
-send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
+send_bitmap_rle_or_plain(struct drbd_device *device, struct bm_xfer_ctx *c)
 {
-	struct drbd_socket *sock = &mdev->tconn->data;
-	unsigned int header_size = drbd_header_size(mdev->tconn);
+	struct drbd_socket *sock = &first_peer_device(device)->connection->data;
+	unsigned int header_size = drbd_header_size(first_peer_device(device)->connection);
 	struct p_compressed_bm *p = sock->sbuf + header_size;
 	int len, err;
 
-	len = fill_bitmap_rle_bits(mdev, p,
+	len = fill_bitmap_rle_bits(device, p,
 			DRBD_SOCKET_BUFFER_SIZE - header_size - sizeof(*p), c);
 	if (len < 0)
 		return -EIO;
 
 	if (len) {
 		dcbp_set_code(p, RLE_VLI_Bits);
-		err = __send_command(mdev->tconn, mdev->vnr, sock,
+		err = __send_command(first_peer_device(device)->connection, device->vnr, sock,
 				     P_COMPRESSED_BITMAP, sizeof(*p) + len,
 				     NULL, 0);
 		c->packets[0]++;
@@ -1205,8 +1210,8 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
 				  c->bm_words - c->word_offset);
 		len = num_words * sizeof(*p);
 		if (len)
-			drbd_bm_get_lel(mdev, c->word_offset, num_words, p);
-		err = __send_command(mdev->tconn, mdev->vnr, sock, P_BITMAP, len, NULL, 0);
+			drbd_bm_get_lel(device, c->word_offset, num_words, p);
+		err = __send_command(first_peer_device(device)->connection, device->vnr, sock, P_BITMAP, len, NULL, 0);
 		c->word_offset += num_words;
 		c->bit_offset = c->word_offset * BITS_PER_LONG;
 
@@ -1218,7 +1223,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
 	}
 	if (!err) {
 		if (len == 0) {
-			INFO_bm_xfer_stats(mdev, "send", c);
+			INFO_bm_xfer_stats(device, "send", c);
 			return 0;
 		} else
 			return 1;
@@ -1227,128 +1232,128 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
 }
 
 /* See the comment at receive_bitmap() */
-static int _drbd_send_bitmap(struct drbd_conf *mdev)
+static int _drbd_send_bitmap(struct drbd_device *device)
 {
 	struct bm_xfer_ctx c;
 	int err;
 
-	if (!expect(mdev->bitmap))
+	if (!expect(device->bitmap))
 		return false;
 
-	if (get_ldev(mdev)) {
-		if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) {
-			dev_info(DEV, "Writing the whole bitmap, MDF_FullSync was set.\n");
-			drbd_bm_set_all(mdev);
-			if (drbd_bm_write(mdev)) {
+	if (get_ldev(device)) {
+		if (drbd_md_test_flag(device->ldev, MDF_FULL_SYNC)) {
+			drbd_info(device, "Writing the whole bitmap, MDF_FullSync was set.\n");
+			drbd_bm_set_all(device);
+			if (drbd_bm_write(device)) {
 				/* write_bm did fail! Leave full sync flag set in Meta P_DATA
 				 * but otherwise process as per normal - need to tell other
 				 * side that a full resync is required! */
-				dev_err(DEV, "Failed to write bitmap to disk!\n");
+				drbd_err(device, "Failed to write bitmap to disk!\n");
 			} else {
-				drbd_md_clear_flag(mdev, MDF_FULL_SYNC);
-				drbd_md_sync(mdev);
+				drbd_md_clear_flag(device, MDF_FULL_SYNC);
+				drbd_md_sync(device);
 			}
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	c = (struct bm_xfer_ctx) {
-		.bm_bits = drbd_bm_bits(mdev),
-		.bm_words = drbd_bm_words(mdev),
+		.bm_bits = drbd_bm_bits(device),
+		.bm_words = drbd_bm_words(device),
 	};
 
 	do {
-		err = send_bitmap_rle_or_plain(mdev, &c);
+		err = send_bitmap_rle_or_plain(device, &c);
 	} while (err > 0);
 
 	return err == 0;
 }
 
-int drbd_send_bitmap(struct drbd_conf *mdev)
+int drbd_send_bitmap(struct drbd_device *device)
 {
-	struct drbd_socket *sock = &mdev->tconn->data;
+	struct drbd_socket *sock = &first_peer_device(device)->connection->data;
 	int err = -1;
 
 	mutex_lock(&sock->mutex);
 	if (sock->socket)
-		err = !_drbd_send_bitmap(mdev);
+		err = !_drbd_send_bitmap(device);
 	mutex_unlock(&sock->mutex);
 	return err;
 }
 
-void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr, u32 set_size)
+void drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr, u32 set_size)
 {
 	struct drbd_socket *sock;
 	struct p_barrier_ack *p;
 
-	if (tconn->cstate < C_WF_REPORT_PARAMS)
+	if (connection->cstate < C_WF_REPORT_PARAMS)
 		return;
 
-	sock = &tconn->meta;
-	p = conn_prepare_command(tconn, sock);
+	sock = &connection->meta;
+	p = conn_prepare_command(connection, sock);
 	if (!p)
 		return;
 	p->barrier = barrier_nr;
 	p->set_size = cpu_to_be32(set_size);
-	conn_send_command(tconn, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
+	conn_send_command(connection, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
 }
 
 /**
  * _drbd_send_ack() - Sends an ack packet
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @cmd:	Packet command code.
  * @sector:	sector, needs to be in big endian byte order
  * @blksize:	size in byte, needs to be in big endian byte order
  * @block_id:	Id, big endian byte order
  */
-static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd,
+static int _drbd_send_ack(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 			  u64 sector, u32 blksize, u64 block_id)
 {
 	struct drbd_socket *sock;
 	struct p_block_ack *p;
 
-	if (mdev->state.conn < C_CONNECTED)
+	if (peer_device->device->state.conn < C_CONNECTED)
 		return -EIO;
 
-	sock = &mdev->tconn->meta;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->meta;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->sector = sector;
 	p->block_id = block_id;
 	p->blksize = blksize;
-	p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq));
-	return drbd_send_command(mdev, sock, cmd, sizeof(*p), NULL, 0);
+	p->seq_num = cpu_to_be32(atomic_inc_return(&peer_device->device->packet_seq));
+	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), NULL, 0);
 }
 
 /* dp->sector and dp->block_id already/still in network byte order,
  * data_size is payload size according to dp->head,
  * and may need to be corrected for digest size. */
-void drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packet cmd,
+void drbd_send_ack_dp(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 		      struct p_data *dp, int data_size)
 {
-	if (mdev->tconn->peer_integrity_tfm)
-		data_size -= crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
-	_drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
+	if (peer_device->connection->peer_integrity_tfm)
+		data_size -= crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm);
+	_drbd_send_ack(peer_device, cmd, dp->sector, cpu_to_be32(data_size),
 		       dp->block_id);
 }
 
-void drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packet cmd,
+void drbd_send_ack_rp(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 		      struct p_block_req *rp)
 {
-	_drbd_send_ack(mdev, cmd, rp->sector, rp->blksize, rp->block_id);
+	_drbd_send_ack(peer_device, cmd, rp->sector, rp->blksize, rp->block_id);
 }
 
 /**
  * drbd_send_ack() - Sends an ack packet
- * @mdev:	DRBD device
+ * @device:	DRBD device
  * @cmd:	packet command code
  * @peer_req:	peer request
  */
-int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd,
+int drbd_send_ack(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 		  struct drbd_peer_request *peer_req)
 {
-	return _drbd_send_ack(mdev, cmd,
+	return _drbd_send_ack(peer_device, cmd,
 			      cpu_to_be64(peer_req->i.sector),
 			      cpu_to_be32(peer_req->i.size),
 			      peer_req->block_id);
@@ -1356,32 +1361,32 @@ int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd,
 
 /* This function misuses the block_id field to signal if the blocks
  * are is sync or not. */
-int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packet cmd,
+int drbd_send_ack_ex(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 		     sector_t sector, int blksize, u64 block_id)
 {
-	return _drbd_send_ack(mdev, cmd,
+	return _drbd_send_ack(peer_device, cmd,
 			      cpu_to_be64(sector),
 			      cpu_to_be32(blksize),
 			      cpu_to_be64(block_id));
 }
 
-int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
+int drbd_send_drequest(struct drbd_peer_device *peer_device, int cmd,
 		       sector_t sector, int size, u64 block_id)
 {
 	struct drbd_socket *sock;
 	struct p_block_req *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->sector = cpu_to_be64(sector);
 	p->block_id = block_id;
 	p->blksize = cpu_to_be32(size);
-	return drbd_send_command(mdev, sock, cmd, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), NULL, 0);
 }
 
-int drbd_send_drequest_csum(struct drbd_conf *mdev, sector_t sector, int size,
+int drbd_send_drequest_csum(struct drbd_peer_device *peer_device, sector_t sector, int size,
 			    void *digest, int digest_size, enum drbd_packet cmd)
 {
 	struct drbd_socket *sock;
@@ -1389,64 +1394,63 @@ int drbd_send_drequest_csum(struct drbd_conf *mdev, sector_t sector, int size,
 
 	/* FIXME: Put the digest into the preallocated socket buffer.  */
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->sector = cpu_to_be64(sector);
 	p->block_id = ID_SYNCER /* unused */;
 	p->blksize = cpu_to_be32(size);
-	return drbd_send_command(mdev, sock, cmd, sizeof(*p),
-				 digest, digest_size);
+	return drbd_send_command(peer_device, sock, cmd, sizeof(*p), digest, digest_size);
 }
 
-int drbd_send_ov_request(struct drbd_conf *mdev, sector_t sector, int size)
+int drbd_send_ov_request(struct drbd_peer_device *peer_device, sector_t sector, int size)
 {
 	struct drbd_socket *sock;
 	struct p_block_req *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->sector = cpu_to_be64(sector);
 	p->block_id = ID_SYNCER /* unused */;
 	p->blksize = cpu_to_be32(size);
-	return drbd_send_command(mdev, sock, P_OV_REQUEST, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, P_OV_REQUEST, sizeof(*p), NULL, 0);
 }
 
 /* called on sndtimeo
  * returns false if we should retry,
  * true if we think connection is dead
  */
-static int we_should_drop_the_connection(struct drbd_tconn *tconn, struct socket *sock)
+static int we_should_drop_the_connection(struct drbd_connection *connection, struct socket *sock)
 {
 	int drop_it;
-	/* long elapsed = (long)(jiffies - mdev->last_received); */
+	/* long elapsed = (long)(jiffies - device->last_received); */
 
-	drop_it =   tconn->meta.socket == sock
-		|| !tconn->asender.task
-		|| get_t_state(&tconn->asender) != RUNNING
-		|| tconn->cstate < C_WF_REPORT_PARAMS;
+	drop_it =   connection->meta.socket == sock
+		|| !connection->asender.task
+		|| get_t_state(&connection->asender) != RUNNING
+		|| connection->cstate < C_WF_REPORT_PARAMS;
 
 	if (drop_it)
 		return true;
 
-	drop_it = !--tconn->ko_count;
+	drop_it = !--connection->ko_count;
 	if (!drop_it) {
-		conn_err(tconn, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
-			 current->comm, current->pid, tconn->ko_count);
-		request_ping(tconn);
+		drbd_err(connection, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
+			 current->comm, current->pid, connection->ko_count);
+		request_ping(connection);
 	}
 
-	return drop_it; /* && (mdev->state == R_PRIMARY) */;
+	return drop_it; /* && (device->state == R_PRIMARY) */;
 }
 
-static void drbd_update_congested(struct drbd_tconn *tconn)
+static void drbd_update_congested(struct drbd_connection *connection)
 {
-	struct sock *sk = tconn->data.socket->sk;
+	struct sock *sk = connection->data.socket->sk;
 	if (sk->sk_wmem_queued > sk->sk_sndbuf * 4 / 5)
-		set_bit(NET_CONGESTED, &tconn->flags);
+		set_bit(NET_CONGESTED, &connection->flags);
 }
 
 /* The idea of sendpage seems to be to put some kind of reference
@@ -1470,26 +1474,26 @@ static void drbd_update_congested(struct drbd_tconn *tconn)
  * As a workaround, we disable sendpage on pages
  * with page_count == 0 or PageSlab.
  */
-static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
+static int _drbd_no_send_page(struct drbd_peer_device *peer_device, struct page *page,
 			      int offset, size_t size, unsigned msg_flags)
 {
 	struct socket *socket;
 	void *addr;
 	int err;
 
-	socket = mdev->tconn->data.socket;
+	socket = peer_device->connection->data.socket;
 	addr = kmap(page) + offset;
-	err = drbd_send_all(mdev->tconn, socket, addr, size, msg_flags);
+	err = drbd_send_all(peer_device->connection, socket, addr, size, msg_flags);
 	kunmap(page);
 	if (!err)
-		mdev->send_cnt += size >> 9;
+		peer_device->device->send_cnt += size >> 9;
 	return err;
 }
 
-static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
+static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *page,
 		    int offset, size_t size, unsigned msg_flags)
 {
-	struct socket *socket = mdev->tconn->data.socket;
+	struct socket *socket = peer_device->connection->data.socket;
 	mm_segment_t oldfs = get_fs();
 	int len = size;
 	int err = -EIO;
@@ -1501,10 +1505,10 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 	 * __page_cache_release a page that would actually still be referenced
 	 * by someone, leading to some obscure delayed Oops somewhere else. */
 	if (disable_sendpage || (page_count(page) < 1) || PageSlab(page))
-		return _drbd_no_send_page(mdev, page, offset, size, msg_flags);
+		return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
 
 	msg_flags |= MSG_NOSIGNAL;
-	drbd_update_congested(mdev->tconn);
+	drbd_update_congested(peer_device->connection);
 	set_fs(KERNEL_DS);
 	do {
 		int sent;
@@ -1512,11 +1516,11 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 		sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
 		if (sent <= 0) {
 			if (sent == -EAGAIN) {
-				if (we_should_drop_the_connection(mdev->tconn, socket))
+				if (we_should_drop_the_connection(peer_device->connection, socket))
 					break;
 				continue;
 			}
-			dev_warn(DEV, "%s: size=%d len=%d sent=%d\n",
+			drbd_warn(peer_device->device, "%s: size=%d len=%d sent=%d\n",
 			     __func__, (int)size, len, sent);
 			if (sent < 0)
 				err = sent;
@@ -1524,18 +1528,18 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 		}
 		len    -= sent;
 		offset += sent;
-	} while (len > 0 /* THINK && mdev->cstate >= C_CONNECTED*/);
+	} while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/);
 	set_fs(oldfs);
-	clear_bit(NET_CONGESTED, &mdev->tconn->flags);
+	clear_bit(NET_CONGESTED, &peer_device->connection->flags);
 
 	if (len == 0) {
 		err = 0;
-		mdev->send_cnt += size >> 9;
+		peer_device->device->send_cnt += size >> 9;
 	}
 	return err;
 }
 
-static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
+static int _drbd_send_bio(struct drbd_peer_device *peer_device, struct bio *bio)
 {
 	struct bio_vec bvec;
 	struct bvec_iter iter;
@@ -1544,7 +1548,7 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 	bio_for_each_segment(bvec, bio, iter) {
 		int err;
 
-		err = _drbd_no_send_page(mdev, bvec.bv_page,
+		err = _drbd_no_send_page(peer_device, bvec.bv_page,
 					 bvec.bv_offset, bvec.bv_len,
 					 bio_iter_last(bvec, iter)
 					 ? 0 : MSG_MORE);
@@ -1554,7 +1558,7 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 	return 0;
 }
 
-static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
+static int _drbd_send_zc_bio(struct drbd_peer_device *peer_device, struct bio *bio)
 {
 	struct bio_vec bvec;
 	struct bvec_iter iter;
@@ -1563,7 +1567,7 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
 	bio_for_each_segment(bvec, bio, iter) {
 		int err;
 
-		err = _drbd_send_page(mdev, bvec.bv_page,
+		err = _drbd_send_page(peer_device, bvec.bv_page,
 				      bvec.bv_offset, bvec.bv_len,
 				      bio_iter_last(bvec, iter) ? 0 : MSG_MORE);
 		if (err)
@@ -1572,7 +1576,7 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
 	return 0;
 }
 
-static int _drbd_send_zc_ee(struct drbd_conf *mdev,
+static int _drbd_send_zc_ee(struct drbd_peer_device *peer_device,
 			    struct drbd_peer_request *peer_req)
 {
 	struct page *page = peer_req->pages;
@@ -1583,7 +1587,7 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev,
 	page_chain_for_each(page) {
 		unsigned l = min_t(unsigned, len, PAGE_SIZE);
 
-		err = _drbd_send_page(mdev, page, 0, l,
+		err = _drbd_send_page(peer_device, page, 0, l,
 				      page_chain_next(page) ? MSG_MORE : 0);
 		if (err)
 			return err;
@@ -1592,9 +1596,9 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev,
 	return 0;
 }
 
-static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
+static u32 bio_flags_to_wire(struct drbd_connection *connection, unsigned long bi_rw)
 {
-	if (mdev->tconn->agreed_pro_version >= 95)
+	if (connection->agreed_pro_version >= 95)
 		return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
 			(bi_rw & REQ_FUA ? DP_FUA : 0) |
 			(bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
@@ -1606,28 +1610,30 @@ static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
 /* Used to send write requests
  * R_PRIMARY -> Peer	(P_DATA)
  */
-int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
+int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *req)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
 	struct p_data *p;
 	unsigned int dp_flags = 0;
 	int dgs;
 	int err;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
-	dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
+	dgs = peer_device->connection->integrity_tfm ?
+	      crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0;
 
 	if (!p)
 		return -EIO;
 	p->sector = cpu_to_be64(req->i.sector);
 	p->block_id = (unsigned long)req;
-	p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq));
-	dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
-	if (mdev->state.conn >= C_SYNC_SOURCE &&
-	    mdev->state.conn <= C_PAUSED_SYNC_T)
+	p->seq_num = cpu_to_be32(atomic_inc_return(&device->packet_seq));
+	dp_flags = bio_flags_to_wire(peer_device->connection, req->master_bio->bi_rw);
+	if (device->state.conn >= C_SYNC_SOURCE &&
+	    device->state.conn <= C_PAUSED_SYNC_T)
 		dp_flags |= DP_MAY_SET_IN_SYNC;
-	if (mdev->tconn->agreed_pro_version >= 100) {
+	if (peer_device->connection->agreed_pro_version >= 100) {
 		if (req->rq_state & RQ_EXP_RECEIVE_ACK)
 			dp_flags |= DP_SEND_RECEIVE_ACK;
 		if (req->rq_state & RQ_EXP_WRITE_ACK)
@@ -1635,8 +1641,8 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
 	}
 	p->dp_flags = cpu_to_be32(dp_flags);
 	if (dgs)
-		drbd_csum_bio(mdev, mdev->tconn->integrity_tfm, req->master_bio, p + 1);
-	err = __send_command(mdev->tconn, mdev->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
+		drbd_csum_bio(peer_device->connection->integrity_tfm, req->master_bio, p + 1);
+	err = __send_command(peer_device->connection, device->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
 	if (!err) {
 		/* For protocol A, we have to memcpy the payload into
 		 * socket buffers, as we may complete right away
@@ -1650,18 +1656,18 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
 		 * receiving side, we sure have detected corruption elsewhere.
 		 */
 		if (!(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK)) || dgs)
-			err = _drbd_send_bio(mdev, req->master_bio);
+			err = _drbd_send_bio(peer_device, req->master_bio);
 		else
-			err = _drbd_send_zc_bio(mdev, req->master_bio);
+			err = _drbd_send_zc_bio(peer_device, req->master_bio);
 
 		/* double check digest, sometimes buffers have been modified in flight. */
 		if (dgs > 0 && dgs <= 64) {
 			/* 64 byte, 512 bit, is the largest digest size
 			 * currently supported in kernel crypto. */
 			unsigned char digest[64];
-			drbd_csum_bio(mdev, mdev->tconn->integrity_tfm, req->master_bio, digest);
+			drbd_csum_bio(peer_device->connection->integrity_tfm, req->master_bio, digest);
 			if (memcmp(p + 1, digest, dgs)) {
-				dev_warn(DEV,
+				drbd_warn(device,
 					"Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
 					(unsigned long long)req->i.sector, req->i.size);
 			}
@@ -1678,18 +1684,20 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
  *  Peer       -> (diskless) R_PRIMARY   (P_DATA_REPLY)
  *  C_SYNC_SOURCE -> C_SYNC_TARGET         (P_RS_DATA_REPLY)
  */
-int drbd_send_block(struct drbd_conf *mdev, enum drbd_packet cmd,
+int drbd_send_block(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 		    struct drbd_peer_request *peer_req)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
 	struct p_data *p;
 	int err;
 	int dgs;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 
-	dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
+	dgs = peer_device->connection->integrity_tfm ?
+	      crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0;
 
 	if (!p)
 		return -EIO;
@@ -1698,27 +1706,27 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packet cmd,
 	p->seq_num = 0;  /* unused */
 	p->dp_flags = 0;
 	if (dgs)
-		drbd_csum_ee(mdev, mdev->tconn->integrity_tfm, peer_req, p + 1);
-	err = __send_command(mdev->tconn, mdev->vnr, sock, cmd, sizeof(*p) + dgs, NULL, peer_req->i.size);
+		drbd_csum_ee(peer_device->connection->integrity_tfm, peer_req, p + 1);
+	err = __send_command(peer_device->connection, device->vnr, sock, cmd, sizeof(*p) + dgs, NULL, peer_req->i.size);
 	if (!err)
-		err = _drbd_send_zc_ee(mdev, peer_req);
+		err = _drbd_send_zc_ee(peer_device, peer_req);
 	mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
 
 	return err;
 }
 
-int drbd_send_out_of_sync(struct drbd_conf *mdev, struct drbd_request *req)
+int drbd_send_out_of_sync(struct drbd_peer_device *peer_device, struct drbd_request *req)
 {
 	struct drbd_socket *sock;
 	struct p_block_desc *p;
 
-	sock = &mdev->tconn->data;
-	p = drbd_prepare_command(mdev, sock);
+	sock = &peer_device->connection->data;
+	p = drbd_prepare_command(peer_device, sock);
 	if (!p)
 		return -EIO;
 	p->sector = cpu_to_be64(req->i.sector);
 	p->blksize = cpu_to_be32(req->i.size);
-	return drbd_send_command(mdev, sock, P_OUT_OF_SYNC, sizeof(*p), NULL, 0);
+	return drbd_send_command(peer_device, sock, P_OUT_OF_SYNC, sizeof(*p), NULL, 0);
 }
 
 /*
@@ -1737,7 +1745,7 @@ int drbd_send_out_of_sync(struct drbd_conf *mdev, struct drbd_request *req)
 /*
  * you must have down()ed the appropriate [m]sock_mutex elsewhere!
  */
-int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
+int drbd_send(struct drbd_connection *connection, struct socket *sock,
 	      void *buf, size_t size, unsigned msg_flags)
 {
 	struct kvec iov;
@@ -1758,11 +1766,11 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
 	msg.msg_controllen = 0;
 	msg.msg_flags      = msg_flags | MSG_NOSIGNAL;
 
-	if (sock == tconn->data.socket) {
+	if (sock == connection->data.socket) {
 		rcu_read_lock();
-		tconn->ko_count = rcu_dereference(tconn->net_conf)->ko_count;
+		connection->ko_count = rcu_dereference(connection->net_conf)->ko_count;
 		rcu_read_unlock();
-		drbd_update_congested(tconn);
+		drbd_update_congested(connection);
 	}
 	do {
 		/* STRANGE
@@ -1776,7 +1784,7 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
  */
 		rv = kernel_sendmsg(sock, &msg, &iov, 1, size);
 		if (rv == -EAGAIN) {
-			if (we_should_drop_the_connection(tconn, sock))
+			if (we_should_drop_the_connection(connection, sock))
 				break;
 			else
 				continue;
@@ -1792,17 +1800,17 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
 		iov.iov_len  -= rv;
 	} while (sent < size);
 
-	if (sock == tconn->data.socket)
-		clear_bit(NET_CONGESTED, &tconn->flags);
+	if (sock == connection->data.socket)
+		clear_bit(NET_CONGESTED, &connection->flags);
 
 	if (rv <= 0) {
 		if (rv != -EAGAIN) {
-			conn_err(tconn, "%s_sendmsg returned %d\n",
-				 sock == tconn->meta.socket ? "msock" : "sock",
+			drbd_err(connection, "%s_sendmsg returned %d\n",
+				 sock == connection->meta.socket ? "msock" : "sock",
 				 rv);
-			conn_request_state(tconn, NS(conn, C_BROKEN_PIPE), CS_HARD);
+			conn_request_state(connection, NS(conn, C_BROKEN_PIPE), CS_HARD);
 		} else
-			conn_request_state(tconn, NS(conn, C_TIMEOUT), CS_HARD);
+			conn_request_state(connection, NS(conn, C_TIMEOUT), CS_HARD);
 	}
 
 	return sent;
@@ -1813,12 +1821,12 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
  *
  * Returns 0 upon success and a negative error value otherwise.
  */
-int drbd_send_all(struct drbd_tconn *tconn, struct socket *sock, void *buffer,
+int drbd_send_all(struct drbd_connection *connection, struct socket *sock, void *buffer,
 		  size_t size, unsigned msg_flags)
 {
 	int err;
 
-	err = drbd_send(tconn, sock, buffer, size, msg_flags);
+	err = drbd_send(connection, sock, buffer, size, msg_flags);
 	if (err < 0)
 		return err;
 	if (err != size)
@@ -1828,16 +1836,16 @@ int drbd_send_all(struct drbd_tconn *tconn, struct socket *sock, void *buffer,
 
 static int drbd_open(struct block_device *bdev, fmode_t mode)
 {
-	struct drbd_conf *mdev = bdev->bd_disk->private_data;
+	struct drbd_device *device = bdev->bd_disk->private_data;
 	unsigned long flags;
 	int rv = 0;
 
 	mutex_lock(&drbd_main_mutex);
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	/* to have a stable mdev->state.role
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	/* to have a stable device->state.role
 	 * and no race with updating open_cnt */
 
-	if (mdev->state.role != R_PRIMARY) {
+	if (device->state.role != R_PRIMARY) {
 		if (mode & FMODE_WRITE)
 			rv = -EROFS;
 		else if (!allow_oos)
@@ -1845,8 +1853,8 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 	}
 
 	if (!rv)
-		mdev->open_cnt++;
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		device->open_cnt++;
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 	mutex_unlock(&drbd_main_mutex);
 
 	return rv;
@@ -1854,17 +1862,17 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 
 static void drbd_release(struct gendisk *gd, fmode_t mode)
 {
-	struct drbd_conf *mdev = gd->private_data;
+	struct drbd_device *device = gd->private_data;
 	mutex_lock(&drbd_main_mutex);
-	mdev->open_cnt--;
+	device->open_cnt--;
 	mutex_unlock(&drbd_main_mutex);
 }
 
-static void drbd_set_defaults(struct drbd_conf *mdev)
+static void drbd_set_defaults(struct drbd_device *device)
 {
 	/* Beware! The actual layout differs
 	 * between big endian and little endian */
-	mdev->state = (union drbd_dev_state) {
+	device->state = (union drbd_dev_state) {
 		{ .role = R_SECONDARY,
 		  .peer = R_UNKNOWN,
 		  .conn = C_STANDALONE,
@@ -1873,130 +1881,123 @@ static void drbd_set_defaults(struct drbd_conf *mdev)
 		} };
 }
 
-void drbd_init_set_defaults(struct drbd_conf *mdev)
+void drbd_init_set_defaults(struct drbd_device *device)
 {
 	/* the memset(,0,) did most of this.
 	 * note: only assignments, no allocation in here */
 
-	drbd_set_defaults(mdev);
-
-	atomic_set(&mdev->ap_bio_cnt, 0);
-	atomic_set(&mdev->ap_pending_cnt, 0);
-	atomic_set(&mdev->rs_pending_cnt, 0);
-	atomic_set(&mdev->unacked_cnt, 0);
-	atomic_set(&mdev->local_cnt, 0);
-	atomic_set(&mdev->pp_in_use_by_net, 0);
-	atomic_set(&mdev->rs_sect_in, 0);
-	atomic_set(&mdev->rs_sect_ev, 0);
-	atomic_set(&mdev->ap_in_flight, 0);
-	atomic_set(&mdev->md_io_in_use, 0);
-
-	mutex_init(&mdev->own_state_mutex);
-	mdev->state_mutex = &mdev->own_state_mutex;
-
-	spin_lock_init(&mdev->al_lock);
-	spin_lock_init(&mdev->peer_seq_lock);
-
-	INIT_LIST_HEAD(&mdev->active_ee);
-	INIT_LIST_HEAD(&mdev->sync_ee);
-	INIT_LIST_HEAD(&mdev->done_ee);
-	INIT_LIST_HEAD(&mdev->read_ee);
-	INIT_LIST_HEAD(&mdev->net_ee);
-	INIT_LIST_HEAD(&mdev->resync_reads);
-	INIT_LIST_HEAD(&mdev->resync_work.list);
-	INIT_LIST_HEAD(&mdev->unplug_work.list);
-	INIT_LIST_HEAD(&mdev->go_diskless.list);
-	INIT_LIST_HEAD(&mdev->md_sync_work.list);
-	INIT_LIST_HEAD(&mdev->start_resync_work.list);
-	INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
-
-	mdev->resync_work.cb  = w_resync_timer;
-	mdev->unplug_work.cb  = w_send_write_hint;
-	mdev->go_diskless.cb  = w_go_diskless;
-	mdev->md_sync_work.cb = w_md_sync;
-	mdev->bm_io_work.w.cb = w_bitmap_io;
-	mdev->start_resync_work.cb = w_start_resync;
-
-	mdev->resync_work.mdev  = mdev;
-	mdev->unplug_work.mdev  = mdev;
-	mdev->go_diskless.mdev  = mdev;
-	mdev->md_sync_work.mdev = mdev;
-	mdev->bm_io_work.w.mdev = mdev;
-	mdev->start_resync_work.mdev = mdev;
-
-	init_timer(&mdev->resync_timer);
-	init_timer(&mdev->md_sync_timer);
-	init_timer(&mdev->start_resync_timer);
-	init_timer(&mdev->request_timer);
-	mdev->resync_timer.function = resync_timer_fn;
-	mdev->resync_timer.data = (unsigned long) mdev;
-	mdev->md_sync_timer.function = md_sync_timer_fn;
-	mdev->md_sync_timer.data = (unsigned long) mdev;
-	mdev->start_resync_timer.function = start_resync_timer_fn;
-	mdev->start_resync_timer.data = (unsigned long) mdev;
-	mdev->request_timer.function = request_timer_fn;
-	mdev->request_timer.data = (unsigned long) mdev;
-
-	init_waitqueue_head(&mdev->misc_wait);
-	init_waitqueue_head(&mdev->state_wait);
-	init_waitqueue_head(&mdev->ee_wait);
-	init_waitqueue_head(&mdev->al_wait);
-	init_waitqueue_head(&mdev->seq_wait);
-
-	mdev->resync_wenr = LC_FREE;
-	mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
-	mdev->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
-}
-
-void drbd_mdev_cleanup(struct drbd_conf *mdev)
+	drbd_set_defaults(device);
+
+	atomic_set(&device->ap_bio_cnt, 0);
+	atomic_set(&device->ap_pending_cnt, 0);
+	atomic_set(&device->rs_pending_cnt, 0);
+	atomic_set(&device->unacked_cnt, 0);
+	atomic_set(&device->local_cnt, 0);
+	atomic_set(&device->pp_in_use_by_net, 0);
+	atomic_set(&device->rs_sect_in, 0);
+	atomic_set(&device->rs_sect_ev, 0);
+	atomic_set(&device->ap_in_flight, 0);
+	atomic_set(&device->md_io_in_use, 0);
+
+	mutex_init(&device->own_state_mutex);
+	device->state_mutex = &device->own_state_mutex;
+
+	spin_lock_init(&device->al_lock);
+	spin_lock_init(&device->peer_seq_lock);
+
+	INIT_LIST_HEAD(&device->active_ee);
+	INIT_LIST_HEAD(&device->sync_ee);
+	INIT_LIST_HEAD(&device->done_ee);
+	INIT_LIST_HEAD(&device->read_ee);
+	INIT_LIST_HEAD(&device->net_ee);
+	INIT_LIST_HEAD(&device->resync_reads);
+	INIT_LIST_HEAD(&device->resync_work.list);
+	INIT_LIST_HEAD(&device->unplug_work.list);
+	INIT_LIST_HEAD(&device->go_diskless.list);
+	INIT_LIST_HEAD(&device->md_sync_work.list);
+	INIT_LIST_HEAD(&device->start_resync_work.list);
+	INIT_LIST_HEAD(&device->bm_io_work.w.list);
+
+	device->resync_work.cb  = w_resync_timer;
+	device->unplug_work.cb  = w_send_write_hint;
+	device->go_diskless.cb  = w_go_diskless;
+	device->md_sync_work.cb = w_md_sync;
+	device->bm_io_work.w.cb = w_bitmap_io;
+	device->start_resync_work.cb = w_start_resync;
+
+	init_timer(&device->resync_timer);
+	init_timer(&device->md_sync_timer);
+	init_timer(&device->start_resync_timer);
+	init_timer(&device->request_timer);
+	device->resync_timer.function = resync_timer_fn;
+	device->resync_timer.data = (unsigned long) device;
+	device->md_sync_timer.function = md_sync_timer_fn;
+	device->md_sync_timer.data = (unsigned long) device;
+	device->start_resync_timer.function = start_resync_timer_fn;
+	device->start_resync_timer.data = (unsigned long) device;
+	device->request_timer.function = request_timer_fn;
+	device->request_timer.data = (unsigned long) device;
+
+	init_waitqueue_head(&device->misc_wait);
+	init_waitqueue_head(&device->state_wait);
+	init_waitqueue_head(&device->ee_wait);
+	init_waitqueue_head(&device->al_wait);
+	init_waitqueue_head(&device->seq_wait);
+
+	device->resync_wenr = LC_FREE;
+	device->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
+	device->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
+}
+
+void drbd_device_cleanup(struct drbd_device *device)
 {
 	int i;
-	if (mdev->tconn->receiver.t_state != NONE)
-		dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
-				mdev->tconn->receiver.t_state);
-
-	mdev->al_writ_cnt  =
-	mdev->bm_writ_cnt  =
-	mdev->read_cnt     =
-	mdev->recv_cnt     =
-	mdev->send_cnt     =
-	mdev->writ_cnt     =
-	mdev->p_size       =
-	mdev->rs_start     =
-	mdev->rs_total     =
-	mdev->rs_failed    = 0;
-	mdev->rs_last_events = 0;
-	mdev->rs_last_sect_ev = 0;
+	if (first_peer_device(device)->connection->receiver.t_state != NONE)
+		drbd_err(device, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
+				first_peer_device(device)->connection->receiver.t_state);
+
+	device->al_writ_cnt  =
+	device->bm_writ_cnt  =
+	device->read_cnt     =
+	device->recv_cnt     =
+	device->send_cnt     =
+	device->writ_cnt     =
+	device->p_size       =
+	device->rs_start     =
+	device->rs_total     =
+	device->rs_failed    = 0;
+	device->rs_last_events = 0;
+	device->rs_last_sect_ev = 0;
 	for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-		mdev->rs_mark_left[i] = 0;
-		mdev->rs_mark_time[i] = 0;
+		device->rs_mark_left[i] = 0;
+		device->rs_mark_time[i] = 0;
 	}
-	D_ASSERT(mdev->tconn->net_conf == NULL);
+	D_ASSERT(device, first_peer_device(device)->connection->net_conf == NULL);
 
-	drbd_set_my_capacity(mdev, 0);
-	if (mdev->bitmap) {
+	drbd_set_my_capacity(device, 0);
+	if (device->bitmap) {
 		/* maybe never allocated. */
-		drbd_bm_resize(mdev, 0, 1);
-		drbd_bm_cleanup(mdev);
+		drbd_bm_resize(device, 0, 1);
+		drbd_bm_cleanup(device);
 	}
 
-	drbd_free_bc(mdev->ldev);
-	mdev->ldev = NULL;
+	drbd_free_bc(device->ldev);
+	device->ldev = NULL;
 
-	clear_bit(AL_SUSPENDED, &mdev->flags);
+	clear_bit(AL_SUSPENDED, &device->flags);
 
-	D_ASSERT(list_empty(&mdev->active_ee));
-	D_ASSERT(list_empty(&mdev->sync_ee));
-	D_ASSERT(list_empty(&mdev->done_ee));
-	D_ASSERT(list_empty(&mdev->read_ee));
-	D_ASSERT(list_empty(&mdev->net_ee));
-	D_ASSERT(list_empty(&mdev->resync_reads));
-	D_ASSERT(list_empty(&mdev->tconn->sender_work.q));
-	D_ASSERT(list_empty(&mdev->resync_work.list));
-	D_ASSERT(list_empty(&mdev->unplug_work.list));
-	D_ASSERT(list_empty(&mdev->go_diskless.list));
+	D_ASSERT(device, list_empty(&device->active_ee));
+	D_ASSERT(device, list_empty(&device->sync_ee));
+	D_ASSERT(device, list_empty(&device->done_ee));
+	D_ASSERT(device, list_empty(&device->read_ee));
+	D_ASSERT(device, list_empty(&device->net_ee));
+	D_ASSERT(device, list_empty(&device->resync_reads));
+	D_ASSERT(device, list_empty(&first_peer_device(device)->connection->sender_work.q));
+	D_ASSERT(device, list_empty(&device->resync_work.list));
+	D_ASSERT(device, list_empty(&device->unplug_work.list));
+	D_ASSERT(device, list_empty(&device->go_diskless.list));
 
-	drbd_set_defaults(mdev);
+	drbd_set_defaults(device);
 }
 
 
@@ -2011,7 +2012,7 @@ static void drbd_destroy_mempools(void)
 		drbd_pp_vacant--;
 	}
 
-	/* D_ASSERT(atomic_read(&drbd_pp_vacant)==0); */
+	/* D_ASSERT(device, atomic_read(&drbd_pp_vacant)==0); */
 
 	if (drbd_md_io_bio_set)
 		bioset_free(drbd_md_io_bio_set);
@@ -2131,69 +2132,73 @@ static struct notifier_block drbd_notifier = {
 	.notifier_call = drbd_notify_sys,
 };
 
-static void drbd_release_all_peer_reqs(struct drbd_conf *mdev)
+static void drbd_release_all_peer_reqs(struct drbd_device *device)
 {
 	int rr;
 
-	rr = drbd_free_peer_reqs(mdev, &mdev->active_ee);
+	rr = drbd_free_peer_reqs(device, &device->active_ee);
 	if (rr)
-		dev_err(DEV, "%d EEs in active list found!\n", rr);
+		drbd_err(device, "%d EEs in active list found!\n", rr);
 
-	rr = drbd_free_peer_reqs(mdev, &mdev->sync_ee);
+	rr = drbd_free_peer_reqs(device, &device->sync_ee);
 	if (rr)
-		dev_err(DEV, "%d EEs in sync list found!\n", rr);
+		drbd_err(device, "%d EEs in sync list found!\n", rr);
 
-	rr = drbd_free_peer_reqs(mdev, &mdev->read_ee);
+	rr = drbd_free_peer_reqs(device, &device->read_ee);
 	if (rr)
-		dev_err(DEV, "%d EEs in read list found!\n", rr);
+		drbd_err(device, "%d EEs in read list found!\n", rr);
 
-	rr = drbd_free_peer_reqs(mdev, &mdev->done_ee);
+	rr = drbd_free_peer_reqs(device, &device->done_ee);
 	if (rr)
-		dev_err(DEV, "%d EEs in done list found!\n", rr);
+		drbd_err(device, "%d EEs in done list found!\n", rr);
 
-	rr = drbd_free_peer_reqs(mdev, &mdev->net_ee);
+	rr = drbd_free_peer_reqs(device, &device->net_ee);
 	if (rr)
-		dev_err(DEV, "%d EEs in net list found!\n", rr);
+		drbd_err(device, "%d EEs in net list found!\n", rr);
 }
 
 /* caution. no locking. */
-void drbd_minor_destroy(struct kref *kref)
+void drbd_destroy_device(struct kref *kref)
 {
-	struct drbd_conf *mdev = container_of(kref, struct drbd_conf, kref);
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_device *device = container_of(kref, struct drbd_device, kref);
+	struct drbd_resource *resource = device->resource;
+	struct drbd_connection *connection;
 
-	del_timer_sync(&mdev->request_timer);
+	del_timer_sync(&device->request_timer);
 
 	/* paranoia asserts */
-	D_ASSERT(mdev->open_cnt == 0);
+	D_ASSERT(device, device->open_cnt == 0);
 	/* end paranoia asserts */
 
 	/* cleanup stuff that may have been allocated during
 	 * device (re-)configuration or state changes */
 
-	if (mdev->this_bdev)
-		bdput(mdev->this_bdev);
+	if (device->this_bdev)
+		bdput(device->this_bdev);
 
-	drbd_free_bc(mdev->ldev);
-	mdev->ldev = NULL;
+	drbd_free_bc(device->ldev);
+	device->ldev = NULL;
 
-	drbd_release_all_peer_reqs(mdev);
+	drbd_release_all_peer_reqs(device);
 
-	lc_destroy(mdev->act_log);
-	lc_destroy(mdev->resync);
+	lc_destroy(device->act_log);
+	lc_destroy(device->resync);
 
-	kfree(mdev->p_uuid);
-	/* mdev->p_uuid = NULL; */
+	kfree(device->p_uuid);
+	/* device->p_uuid = NULL; */
 
-	if (mdev->bitmap) /* should no longer be there. */
-		drbd_bm_cleanup(mdev);
-	__free_page(mdev->md_io_page);
-	put_disk(mdev->vdisk);
-	blk_cleanup_queue(mdev->rq_queue);
-	kfree(mdev->rs_plan_s);
-	kfree(mdev);
+	if (device->bitmap) /* should no longer be there. */
+		drbd_bm_cleanup(device);
+	__free_page(device->md_io_page);
+	put_disk(device->vdisk);
+	blk_cleanup_queue(device->rq_queue);
+	kfree(device->rs_plan_s);
+	kfree(first_peer_device(device));
+	kfree(device);
 
-	kref_put(&tconn->kref, &conn_destroy);
+	for_each_connection(connection, resource)
+		kref_put(&connection->kref, drbd_destroy_connection);
+	kref_put(&resource->kref, drbd_destroy_resource);
 }
 
 /* One global retry thread, if we need to push back some bio and have it
@@ -2218,19 +2223,19 @@ static void do_retry(struct work_struct *ws)
 	spin_unlock_irq(&retry->lock);
 
 	list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
-		struct drbd_conf *mdev = req->w.mdev;
+		struct drbd_device *device = req->device;
 		struct bio *bio = req->master_bio;
 		unsigned long start_time = req->start_time;
 		bool expected;
 
-		expected = 
+		expected =
 			expect(atomic_read(&req->completion_ref) == 0) &&
 			expect(req->rq_state & RQ_POSTPONED) &&
 			expect((req->rq_state & RQ_LOCAL_PENDING) == 0 ||
 				(req->rq_state & RQ_LOCAL_ABORTED) != 0);
 
 		if (!expected)
-			dev_err(DEV, "req=%p completion_ref=%d rq_state=%x\n",
+			drbd_err(device, "req=%p completion_ref=%d rq_state=%x\n",
 				req, atomic_read(&req->completion_ref),
 				req->rq_state);
 
@@ -2254,8 +2259,8 @@ static void do_retry(struct work_struct *ws)
 
 		/* We are not just doing generic_make_request(),
 		 * as we want to keep the start_time information. */
-		inc_ap_bio(mdev);
-		__drbd_make_request(mdev, bio, start_time);
+		inc_ap_bio(device);
+		__drbd_make_request(device, bio, start_time);
 	}
 }
 
@@ -2269,17 +2274,38 @@ void drbd_restart_request(struct drbd_request *req)
 	/* Drop the extra reference that would otherwise
 	 * have been dropped by complete_master_bio.
 	 * do_retry() needs to grab a new one. */
-	dec_ap_bio(req->w.mdev);
+	dec_ap_bio(req->device);
 
 	queue_work(retry.wq, &retry.worker);
 }
 
+void drbd_destroy_resource(struct kref *kref)
+{
+	struct drbd_resource *resource =
+		container_of(kref, struct drbd_resource, kref);
+
+	idr_destroy(&resource->devices);
+	free_cpumask_var(resource->cpu_mask);
+	kfree(resource->name);
+	kfree(resource);
+}
+
+void drbd_free_resource(struct drbd_resource *resource)
+{
+	struct drbd_connection *connection, *tmp;
+
+	for_each_connection_safe(connection, tmp, resource) {
+		list_del(&connection->connections);
+		kref_put(&connection->kref, drbd_destroy_connection);
+	}
+	kref_put(&resource->kref, drbd_destroy_resource);
+}
 
 static void drbd_cleanup(void)
 {
 	unsigned int i;
-	struct drbd_conf *mdev;
-	struct drbd_tconn *tconn, *tmp;
+	struct drbd_device *device;
+	struct drbd_resource *resource, *tmp;
 
 	unregister_reboot_notifier(&drbd_notifier);
 
@@ -2299,26 +2325,19 @@ static void drbd_cleanup(void)
 
 	drbd_genl_unregister();
 
-	idr_for_each_entry(&minors, mdev, i) {
-		idr_remove(&minors, mdev_to_minor(mdev));
-		idr_remove(&mdev->tconn->volumes, mdev->vnr);
-		destroy_workqueue(mdev->submit.wq);
-		del_gendisk(mdev->vdisk);
-		/* synchronize_rcu(); No other threads running at this point */
-		kref_put(&mdev->kref, &drbd_minor_destroy);
-	}
+	idr_for_each_entry(&drbd_devices, device, i)
+		drbd_delete_device(device);
 
 	/* not _rcu since, no other updater anymore. Genl already unregistered */
-	list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
-		list_del(&tconn->all_tconn); /* not _rcu no proc, not other threads */
-		/* synchronize_rcu(); */
-		kref_put(&tconn->kref, &conn_destroy);
+	for_each_resource_safe(resource, tmp, &drbd_resources) {
+		list_del(&resource->resources);
+		drbd_free_resource(resource);
 	}
 
 	drbd_destroy_mempools();
 	unregister_blkdev(DRBD_MAJOR, "drbd");
 
-	idr_destroy(&minors);
+	idr_destroy(&drbd_devices);
 
 	printk(KERN_INFO "drbd: module cleanup done.\n");
 }
@@ -2332,49 +2351,50 @@ static void drbd_cleanup(void)
  */
 static int drbd_congested(void *congested_data, int bdi_bits)
 {
-	struct drbd_conf *mdev = congested_data;
+	struct drbd_device *device = congested_data;
 	struct request_queue *q;
 	char reason = '-';
 	int r = 0;
 
-	if (!may_inc_ap_bio(mdev)) {
+	if (!may_inc_ap_bio(device)) {
 		/* DRBD has frozen IO */
 		r = bdi_bits;
 		reason = 'd';
 		goto out;
 	}
 
-	if (test_bit(CALLBACK_PENDING, &mdev->tconn->flags)) {
+	if (test_bit(CALLBACK_PENDING, &first_peer_device(device)->connection->flags)) {
 		r |= (1 << BDI_async_congested);
 		/* Without good local data, we would need to read from remote,
 		 * and that would need the worker thread as well, which is
 		 * currently blocked waiting for that usermode helper to
 		 * finish.
 		 */
-		if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
+		if (!get_ldev_if_state(device, D_UP_TO_DATE))
 			r |= (1 << BDI_sync_congested);
 		else
-			put_ldev(mdev);
+			put_ldev(device);
 		r &= bdi_bits;
 		reason = 'c';
 		goto out;
 	}
 
-	if (get_ldev(mdev)) {
-		q = bdev_get_queue(mdev->ldev->backing_bdev);
+	if (get_ldev(device)) {
+		q = bdev_get_queue(device->ldev->backing_bdev);
 		r = bdi_congested(&q->backing_dev_info, bdi_bits);
-		put_ldev(mdev);
+		put_ldev(device);
 		if (r)
 			reason = 'b';
 	}
 
-	if (bdi_bits & (1 << BDI_async_congested) && test_bit(NET_CONGESTED, &mdev->tconn->flags)) {
+	if (bdi_bits & (1 << BDI_async_congested) &&
+	    test_bit(NET_CONGESTED, &first_peer_device(device)->connection->flags)) {
 		r |= (1 << BDI_async_congested);
 		reason = reason == 'b' ? 'a' : 'n';
 	}
 
 out:
-	mdev->congestion_reason = reason;
+	device->congestion_reason = reason;
 	return r;
 }
 
@@ -2385,45 +2405,72 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq)
 	init_waitqueue_head(&wq->q_wait);
 }
 
-struct drbd_tconn *conn_get_by_name(const char *name)
+struct completion_work {
+	struct drbd_work w;
+	struct completion done;
+};
+
+static int w_complete(struct drbd_work *w, int cancel)
+{
+	struct completion_work *completion_work =
+		container_of(w, struct completion_work, w);
+
+	complete(&completion_work->done);
+	return 0;
+}
+
+void drbd_flush_workqueue(struct drbd_work_queue *work_queue)
+{
+	struct completion_work completion_work;
+
+	completion_work.w.cb = w_complete;
+	init_completion(&completion_work.done);
+	drbd_queue_work(work_queue, &completion_work.w);
+	wait_for_completion(&completion_work.done);
+}
+
+struct drbd_resource *drbd_find_resource(const char *name)
 {
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
 
 	if (!name || !name[0])
 		return NULL;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
-		if (!strcmp(tconn->name, name)) {
-			kref_get(&tconn->kref);
+	for_each_resource_rcu(resource, &drbd_resources) {
+		if (!strcmp(resource->name, name)) {
+			kref_get(&resource->kref);
 			goto found;
 		}
 	}
-	tconn = NULL;
+	resource = NULL;
 found:
 	rcu_read_unlock();
-	return tconn;
+	return resource;
 }
 
-struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
 				     void *peer_addr, int peer_addr_len)
 {
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
-		if (tconn->my_addr_len == my_addr_len &&
-		    tconn->peer_addr_len == peer_addr_len &&
-		    !memcmp(&tconn->my_addr, my_addr, my_addr_len) &&
-		    !memcmp(&tconn->peer_addr, peer_addr, peer_addr_len)) {
-			kref_get(&tconn->kref);
-			goto found;
+	for_each_resource_rcu(resource, &drbd_resources) {
+		for_each_connection_rcu(connection, resource) {
+			if (connection->my_addr_len == my_addr_len &&
+			    connection->peer_addr_len == peer_addr_len &&
+			    !memcmp(&connection->my_addr, my_addr, my_addr_len) &&
+			    !memcmp(&connection->peer_addr, peer_addr, peer_addr_len)) {
+				kref_get(&connection->kref);
+				goto found;
+			}
 		}
 	}
-	tconn = NULL;
+	connection = NULL;
 found:
 	rcu_read_unlock();
-	return tconn;
+	return connection;
 }
 
 static int drbd_alloc_socket(struct drbd_socket *socket)
@@ -2443,29 +2490,30 @@ static void drbd_free_socket(struct drbd_socket *socket)
 	free_page((unsigned long) socket->rbuf);
 }
 
-void conn_free_crypto(struct drbd_tconn *tconn)
+void conn_free_crypto(struct drbd_connection *connection)
 {
-	drbd_free_sock(tconn);
+	drbd_free_sock(connection);
 
-	crypto_free_hash(tconn->csums_tfm);
-	crypto_free_hash(tconn->verify_tfm);
-	crypto_free_hash(tconn->cram_hmac_tfm);
-	crypto_free_hash(tconn->integrity_tfm);
-	crypto_free_hash(tconn->peer_integrity_tfm);
-	kfree(tconn->int_dig_in);
-	kfree(tconn->int_dig_vv);
+	crypto_free_hash(connection->csums_tfm);
+	crypto_free_hash(connection->verify_tfm);
+	crypto_free_hash(connection->cram_hmac_tfm);
+	crypto_free_hash(connection->integrity_tfm);
+	crypto_free_hash(connection->peer_integrity_tfm);
+	kfree(connection->int_dig_in);
+	kfree(connection->int_dig_vv);
 
-	tconn->csums_tfm = NULL;
-	tconn->verify_tfm = NULL;
-	tconn->cram_hmac_tfm = NULL;
-	tconn->integrity_tfm = NULL;
-	tconn->peer_integrity_tfm = NULL;
-	tconn->int_dig_in = NULL;
-	tconn->int_dig_vv = NULL;
+	connection->csums_tfm = NULL;
+	connection->verify_tfm = NULL;
+	connection->cram_hmac_tfm = NULL;
+	connection->integrity_tfm = NULL;
+	connection->peer_integrity_tfm = NULL;
+	connection->int_dig_in = NULL;
+	connection->int_dig_vv = NULL;
 }
 
-int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts)
+int set_resource_options(struct drbd_resource *resource, struct res_opts *res_opts)
 {
+	struct drbd_connection *connection;
 	cpumask_var_t new_cpu_mask;
 	int err;
 
@@ -2478,22 +2526,24 @@ int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts)
 
 	/* silently ignore cpu mask on UP kernel */
 	if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
-		/* FIXME: Get rid of constant 32 here */
-		err = bitmap_parse(res_opts->cpu_mask, 32,
+		err = bitmap_parse(res_opts->cpu_mask, DRBD_CPU_MASK_SIZE,
 				   cpumask_bits(new_cpu_mask), nr_cpu_ids);
 		if (err) {
-			conn_warn(tconn, "bitmap_parse() failed with %d\n", err);
+			drbd_warn(resource, "bitmap_parse() failed with %d\n", err);
 			/* retcode = ERR_CPU_MASK_PARSE; */
 			goto fail;
 		}
 	}
-	tconn->res_opts = *res_opts;
-	if (!cpumask_equal(tconn->cpu_mask, new_cpu_mask)) {
-		cpumask_copy(tconn->cpu_mask, new_cpu_mask);
-		drbd_calc_cpu_mask(tconn);
-		tconn->receiver.reset_cpu_mask = 1;
-		tconn->asender.reset_cpu_mask = 1;
-		tconn->worker.reset_cpu_mask = 1;
+	resource->res_opts = *res_opts;
+	if (cpumask_empty(new_cpu_mask))
+		drbd_calc_cpu_mask(&new_cpu_mask);
+	if (!cpumask_equal(resource->cpu_mask, new_cpu_mask)) {
+		cpumask_copy(resource->cpu_mask, new_cpu_mask);
+		for_each_connection_rcu(connection, resource) {
+			connection->receiver.reset_cpu_mask = 1;
+			connection->asender.reset_cpu_mask = 1;
+			connection->worker.reset_cpu_mask = 1;
+		}
 	}
 	err = 0;
 
@@ -2503,146 +2553,177 @@ fail:
 
 }
 
+struct drbd_resource *drbd_create_resource(const char *name)
+{
+	struct drbd_resource *resource;
+
+	resource = kzalloc(sizeof(struct drbd_resource), GFP_KERNEL);
+	if (!resource)
+		goto fail;
+	resource->name = kstrdup(name, GFP_KERNEL);
+	if (!resource->name)
+		goto fail_free_resource;
+	if (!zalloc_cpumask_var(&resource->cpu_mask, GFP_KERNEL))
+		goto fail_free_name;
+	kref_init(&resource->kref);
+	idr_init(&resource->devices);
+	INIT_LIST_HEAD(&resource->connections);
+	list_add_tail_rcu(&resource->resources, &drbd_resources);
+	mutex_init(&resource->conf_update);
+	spin_lock_init(&resource->req_lock);
+	return resource;
+
+fail_free_name:
+	kfree(resource->name);
+fail_free_resource:
+	kfree(resource);
+fail:
+	return NULL;
+}
+
 /* caller must be under genl_lock() */
-struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts)
+struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
 {
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 
-	tconn = kzalloc(sizeof(struct drbd_tconn), GFP_KERNEL);
-	if (!tconn)
+	connection = kzalloc(sizeof(struct drbd_connection), GFP_KERNEL);
+	if (!connection)
 		return NULL;
 
-	tconn->name = kstrdup(name, GFP_KERNEL);
-	if (!tconn->name)
+	if (drbd_alloc_socket(&connection->data))
 		goto fail;
-
-	if (drbd_alloc_socket(&tconn->data))
-		goto fail;
-	if (drbd_alloc_socket(&tconn->meta))
+	if (drbd_alloc_socket(&connection->meta))
 		goto fail;
 
-	if (!zalloc_cpumask_var(&tconn->cpu_mask, GFP_KERNEL))
+	connection->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
+	if (!connection->current_epoch)
 		goto fail;
 
-	if (set_resource_options(tconn, res_opts))
-		goto fail;
+	INIT_LIST_HEAD(&connection->transfer_log);
 
-	tconn->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
-	if (!tconn->current_epoch)
-		goto fail;
+	INIT_LIST_HEAD(&connection->current_epoch->list);
+	connection->epochs = 1;
+	spin_lock_init(&connection->epoch_lock);
+	connection->write_ordering = WO_bdev_flush;
 
-	INIT_LIST_HEAD(&tconn->transfer_log);
+	connection->send.seen_any_write_yet = false;
+	connection->send.current_epoch_nr = 0;
+	connection->send.current_epoch_writes = 0;
 
-	INIT_LIST_HEAD(&tconn->current_epoch->list);
-	tconn->epochs = 1;
-	spin_lock_init(&tconn->epoch_lock);
-	tconn->write_ordering = WO_bdev_flush;
+	resource = drbd_create_resource(name);
+	if (!resource)
+		goto fail;
 
-	tconn->send.seen_any_write_yet = false;
-	tconn->send.current_epoch_nr = 0;
-	tconn->send.current_epoch_writes = 0;
+	connection->cstate = C_STANDALONE;
+	mutex_init(&connection->cstate_mutex);
+	init_waitqueue_head(&connection->ping_wait);
+	idr_init(&connection->peer_devices);
 
-	tconn->cstate = C_STANDALONE;
-	mutex_init(&tconn->cstate_mutex);
-	spin_lock_init(&tconn->req_lock);
-	mutex_init(&tconn->conf_update);
-	init_waitqueue_head(&tconn->ping_wait);
-	idr_init(&tconn->volumes);
+	drbd_init_workqueue(&connection->sender_work);
+	mutex_init(&connection->data.mutex);
+	mutex_init(&connection->meta.mutex);
 
-	drbd_init_workqueue(&tconn->sender_work);
-	mutex_init(&tconn->data.mutex);
-	mutex_init(&tconn->meta.mutex);
+	drbd_thread_init(resource, &connection->receiver, drbd_receiver, "receiver");
+	connection->receiver.connection = connection;
+	drbd_thread_init(resource, &connection->worker, drbd_worker, "worker");
+	connection->worker.connection = connection;
+	drbd_thread_init(resource, &connection->asender, drbd_asender, "asender");
+	connection->asender.connection = connection;
 
-	drbd_thread_init(tconn, &tconn->receiver, drbdd_init, "receiver");
-	drbd_thread_init(tconn, &tconn->worker, drbd_worker, "worker");
-	drbd_thread_init(tconn, &tconn->asender, drbd_asender, "asender");
+	kref_init(&connection->kref);
 
-	kref_init(&tconn->kref);
-	list_add_tail_rcu(&tconn->all_tconn, &drbd_tconns);
+	connection->resource = resource;
 
-	return tconn;
+	if (set_resource_options(resource, res_opts))
+		goto fail_resource;
 
-fail:
-	kfree(tconn->current_epoch);
-	free_cpumask_var(tconn->cpu_mask);
-	drbd_free_socket(&tconn->meta);
-	drbd_free_socket(&tconn->data);
-	kfree(tconn->name);
-	kfree(tconn);
+	kref_get(&resource->kref);
+	list_add_tail_rcu(&connection->connections, &resource->connections);
+	return connection;
 
+fail_resource:
+	list_del(&resource->resources);
+	drbd_free_resource(resource);
+fail:
+	kfree(connection->current_epoch);
+	drbd_free_socket(&connection->meta);
+	drbd_free_socket(&connection->data);
+	kfree(connection);
 	return NULL;
 }
 
-void conn_destroy(struct kref *kref)
+void drbd_destroy_connection(struct kref *kref)
 {
-	struct drbd_tconn *tconn = container_of(kref, struct drbd_tconn, kref);
+	struct drbd_connection *connection = container_of(kref, struct drbd_connection, kref);
+	struct drbd_resource *resource = connection->resource;
 
-	if (atomic_read(&tconn->current_epoch->epoch_size) !=  0)
-		conn_err(tconn, "epoch_size:%d\n", atomic_read(&tconn->current_epoch->epoch_size));
-	kfree(tconn->current_epoch);
+	if (atomic_read(&connection->current_epoch->epoch_size) !=  0)
+		drbd_err(connection, "epoch_size:%d\n", atomic_read(&connection->current_epoch->epoch_size));
+	kfree(connection->current_epoch);
 
-	idr_destroy(&tconn->volumes);
+	idr_destroy(&connection->peer_devices);
 
-	free_cpumask_var(tconn->cpu_mask);
-	drbd_free_socket(&tconn->meta);
-	drbd_free_socket(&tconn->data);
-	kfree(tconn->name);
-	kfree(tconn->int_dig_in);
-	kfree(tconn->int_dig_vv);
-	kfree(tconn);
+	drbd_free_socket(&connection->meta);
+	drbd_free_socket(&connection->data);
+	kfree(connection->int_dig_in);
+	kfree(connection->int_dig_vv);
+	kfree(connection);
+	kref_put(&resource->kref, drbd_destroy_resource);
 }
 
-int init_submitter(struct drbd_conf *mdev)
+static int init_submitter(struct drbd_device *device)
 {
 	/* opencoded create_singlethread_workqueue(),
 	 * to be able to say "drbd%d", ..., minor */
-	mdev->submit.wq = alloc_workqueue("drbd%u_submit",
-			WQ_UNBOUND | WQ_MEM_RECLAIM, 1, mdev->minor);
-	if (!mdev->submit.wq)
+	device->submit.wq = alloc_workqueue("drbd%u_submit",
+			WQ_UNBOUND | WQ_MEM_RECLAIM, 1, device->minor);
+	if (!device->submit.wq)
 		return -ENOMEM;
 
-	INIT_WORK(&mdev->submit.worker, do_submit);
-	spin_lock_init(&mdev->submit.lock);
-	INIT_LIST_HEAD(&mdev->submit.writes);
+	INIT_WORK(&device->submit.worker, do_submit);
+	spin_lock_init(&device->submit.lock);
+	INIT_LIST_HEAD(&device->submit.writes);
 	return 0;
 }
 
-enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr)
+enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned int minor, int vnr)
 {
-	struct drbd_conf *mdev;
+	struct drbd_connection *connection;
+	struct drbd_device *device;
+	struct drbd_peer_device *peer_device, *tmp_peer_device;
 	struct gendisk *disk;
 	struct request_queue *q;
-	int vnr_got = vnr;
-	int minor_got = minor;
+	int id;
 	enum drbd_ret_code err = ERR_NOMEM;
 
-	mdev = minor_to_mdev(minor);
-	if (mdev)
+	device = minor_to_device(minor);
+	if (device)
 		return ERR_MINOR_EXISTS;
 
 	/* GFP_KERNEL, we are outside of all write-out paths */
-	mdev = kzalloc(sizeof(struct drbd_conf), GFP_KERNEL);
-	if (!mdev)
+	device = kzalloc(sizeof(struct drbd_device), GFP_KERNEL);
+	if (!device)
 		return ERR_NOMEM;
+	kref_init(&device->kref);
 
-	kref_get(&tconn->kref);
-	mdev->tconn = tconn;
+	kref_get(&resource->kref);
+	device->resource = resource;
+	device->minor = minor;
+	device->vnr = vnr;
 
-	mdev->minor = minor;
-	mdev->vnr = vnr;
-
-	drbd_init_set_defaults(mdev);
+	drbd_init_set_defaults(device);
 
 	q = blk_alloc_queue(GFP_KERNEL);
 	if (!q)
 		goto out_no_q;
-	mdev->rq_queue = q;
-	q->queuedata   = mdev;
+	device->rq_queue = q;
+	q->queuedata   = device;
 
 	disk = alloc_disk(1);
 	if (!disk)
 		goto out_no_disk;
-	mdev->vdisk = disk;
+	device->vdisk = disk;
 
 	set_disk_ro(disk, true);
 
@@ -2651,14 +2732,14 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
 	disk->first_minor = minor;
 	disk->fops = &drbd_ops;
 	sprintf(disk->disk_name, "drbd%d", minor);
-	disk->private_data = mdev;
+	disk->private_data = device;
 
-	mdev->this_bdev = bdget(MKDEV(DRBD_MAJOR, minor));
+	device->this_bdev = bdget(MKDEV(DRBD_MAJOR, minor));
 	/* we have no partitions. we contain only ourselves. */
-	mdev->this_bdev->bd_contains = mdev->this_bdev;
+	device->this_bdev->bd_contains = device->this_bdev;
 
 	q->backing_dev_info.congested_fn = drbd_congested;
-	q->backing_dev_info.congested_data = mdev;
+	q->backing_dev_info.congested_data = device;
 
 	blk_queue_make_request(q, drbd_make_request);
 	blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
@@ -2667,70 +2748,125 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
 	blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
 	blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
 	blk_queue_merge_bvec(q, drbd_merge_bvec);
-	q->queue_lock = &mdev->tconn->req_lock; /* needed since we use */
+	q->queue_lock = &resource->req_lock;
 
-	mdev->md_io_page = alloc_page(GFP_KERNEL);
-	if (!mdev->md_io_page)
+	device->md_io_page = alloc_page(GFP_KERNEL);
+	if (!device->md_io_page)
 		goto out_no_io_page;
 
-	if (drbd_bm_init(mdev))
+	if (drbd_bm_init(device))
 		goto out_no_bitmap;
-	mdev->read_requests = RB_ROOT;
-	mdev->write_requests = RB_ROOT;
+	device->read_requests = RB_ROOT;
+	device->write_requests = RB_ROOT;
 
-	minor_got = idr_alloc(&minors, mdev, minor, minor + 1, GFP_KERNEL);
-	if (minor_got < 0) {
-		if (minor_got == -ENOSPC) {
+	id = idr_alloc(&drbd_devices, device, minor, minor + 1, GFP_KERNEL);
+	if (id < 0) {
+		if (id == -ENOSPC) {
 			err = ERR_MINOR_EXISTS;
 			drbd_msg_put_info("requested minor exists already");
 		}
 		goto out_no_minor_idr;
 	}
+	kref_get(&device->kref);
 
-	vnr_got = idr_alloc(&tconn->volumes, mdev, vnr, vnr + 1, GFP_KERNEL);
-	if (vnr_got < 0) {
-		if (vnr_got == -ENOSPC) {
-			err = ERR_INVALID_REQUEST;
-			drbd_msg_put_info("requested volume exists already");
+	id = idr_alloc(&resource->devices, device, vnr, vnr + 1, GFP_KERNEL);
+	if (id < 0) {
+		if (id == -ENOSPC) {
+			err = ERR_MINOR_EXISTS;
+			drbd_msg_put_info("requested minor exists already");
 		}
 		goto out_idr_remove_minor;
 	}
+	kref_get(&device->kref);
+
+	INIT_LIST_HEAD(&device->peer_devices);
+	for_each_connection(connection, resource) {
+		peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
+		if (!peer_device)
+			goto out_idr_remove_from_resource;
+		peer_device->connection = connection;
+		peer_device->device = device;
+
+		list_add(&peer_device->peer_devices, &device->peer_devices);
+		kref_get(&device->kref);
 
-	if (init_submitter(mdev)) {
+		id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
+		if (id < 0) {
+			if (id == -ENOSPC) {
+				err = ERR_INVALID_REQUEST;
+				drbd_msg_put_info("requested volume exists already");
+			}
+			goto out_idr_remove_from_resource;
+		}
+		kref_get(&connection->kref);
+	}
+
+	if (init_submitter(device)) {
 		err = ERR_NOMEM;
 		drbd_msg_put_info("unable to create submit workqueue");
 		goto out_idr_remove_vol;
 	}
 
 	add_disk(disk);
-	kref_init(&mdev->kref); /* one ref for both idrs and the the add_disk */
 
 	/* inherit the connection state */
-	mdev->state.conn = tconn->cstate;
-	if (mdev->state.conn == C_WF_REPORT_PARAMS)
-		drbd_connected(mdev);
+	device->state.conn = first_connection(resource)->cstate;
+	if (device->state.conn == C_WF_REPORT_PARAMS) {
+		for_each_peer_device(peer_device, device)
+			drbd_connected(peer_device);
+	}
 
 	return NO_ERROR;
 
 out_idr_remove_vol:
-	idr_remove(&tconn->volumes, vnr_got);
+	idr_remove(&connection->peer_devices, vnr);
+out_idr_remove_from_resource:
+	for_each_connection(connection, resource) {
+		peer_device = idr_find(&connection->peer_devices, vnr);
+		if (peer_device) {
+			idr_remove(&connection->peer_devices, vnr);
+			kref_put(&connection->kref, drbd_destroy_connection);
+		}
+	}
+	for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
+		list_del(&peer_device->peer_devices);
+		kfree(peer_device);
+	}
+	idr_remove(&resource->devices, vnr);
 out_idr_remove_minor:
-	idr_remove(&minors, minor_got);
+	idr_remove(&drbd_devices, minor);
 	synchronize_rcu();
 out_no_minor_idr:
-	drbd_bm_cleanup(mdev);
+	drbd_bm_cleanup(device);
 out_no_bitmap:
-	__free_page(mdev->md_io_page);
+	__free_page(device->md_io_page);
 out_no_io_page:
 	put_disk(disk);
 out_no_disk:
 	blk_cleanup_queue(q);
 out_no_q:
-	kfree(mdev);
-	kref_put(&tconn->kref, &conn_destroy);
+	kref_put(&resource->kref, drbd_destroy_resource);
+	kfree(device);
 	return err;
 }
 
+void drbd_delete_device(struct drbd_device *device)
+{
+	struct drbd_resource *resource = device->resource;
+	struct drbd_connection *connection;
+	int refs = 3;
+
+	for_each_connection(connection, resource) {
+		idr_remove(&connection->peer_devices, device->vnr);
+		refs++;
+	}
+	idr_remove(&resource->devices, device->vnr);
+	idr_remove(&drbd_devices, device_to_minor(device));
+	del_gendisk(device->vdisk);
+	synchronize_rcu();
+	kref_sub(&device->kref, refs, drbd_destroy_device);
+}
+
 int __init drbd_init(void)
 {
 	int err;
@@ -2761,10 +2897,10 @@ int __init drbd_init(void)
 	init_waitqueue_head(&drbd_pp_wait);
 
 	drbd_proc = NULL; /* play safe for drbd_cleanup */
-	idr_init(&minors);
+	idr_init(&drbd_devices);
 
 	rwlock_init(&global_state_lock);
-	INIT_LIST_HEAD(&drbd_tconns);
+	INIT_LIST_HEAD(&drbd_resources);
 
 	err = drbd_genl_register();
 	if (err) {
@@ -2822,37 +2958,39 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
 	kfree(ldev);
 }
 
-void drbd_free_sock(struct drbd_tconn *tconn)
+void drbd_free_sock(struct drbd_connection *connection)
 {
-	if (tconn->data.socket) {
-		mutex_lock(&tconn->data.mutex);
-		kernel_sock_shutdown(tconn->data.socket, SHUT_RDWR);
-		sock_release(tconn->data.socket);
-		tconn->data.socket = NULL;
-		mutex_unlock(&tconn->data.mutex);
+	if (connection->data.socket) {
+		mutex_lock(&connection->data.mutex);
+		kernel_sock_shutdown(connection->data.socket, SHUT_RDWR);
+		sock_release(connection->data.socket);
+		connection->data.socket = NULL;
+		mutex_unlock(&connection->data.mutex);
 	}
-	if (tconn->meta.socket) {
-		mutex_lock(&tconn->meta.mutex);
-		kernel_sock_shutdown(tconn->meta.socket, SHUT_RDWR);
-		sock_release(tconn->meta.socket);
-		tconn->meta.socket = NULL;
-		mutex_unlock(&tconn->meta.mutex);
+	if (connection->meta.socket) {
+		mutex_lock(&connection->meta.mutex);
+		kernel_sock_shutdown(connection->meta.socket, SHUT_RDWR);
+		sock_release(connection->meta.socket);
+		connection->meta.socket = NULL;
+		mutex_unlock(&connection->meta.mutex);
 	}
 }
 
 /* meta data management */
 
-void conn_md_sync(struct drbd_tconn *tconn)
+void conn_md_sync(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		kref_get(&mdev->kref);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+
+		kref_get(&device->kref);
 		rcu_read_unlock();
-		drbd_md_sync(mdev);
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_md_sync(device);
+		kref_put(&device->kref, drbd_destroy_device);
 		rcu_read_lock();
 	}
 	rcu_read_unlock();
@@ -2883,7 +3021,7 @@ struct meta_data_on_disk {
 
 
 
-void drbd_md_write(struct drbd_conf *mdev, void *b)
+void drbd_md_write(struct drbd_device *device, void *b)
 {
 	struct meta_data_on_disk *buffer = b;
 	sector_t sector;
@@ -2891,39 +3029,39 @@ void drbd_md_write(struct drbd_conf *mdev, void *b)
 
 	memset(buffer, 0, sizeof(*buffer));
 
-	buffer->la_size_sect = cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
+	buffer->la_size_sect = cpu_to_be64(drbd_get_capacity(device->this_bdev));
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
-		buffer->uuid[i] = cpu_to_be64(mdev->ldev->md.uuid[i]);
-	buffer->flags = cpu_to_be32(mdev->ldev->md.flags);
+		buffer->uuid[i] = cpu_to_be64(device->ldev->md.uuid[i]);
+	buffer->flags = cpu_to_be32(device->ldev->md.flags);
 	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC_84_UNCLEAN);
 
-	buffer->md_size_sect  = cpu_to_be32(mdev->ldev->md.md_size_sect);
-	buffer->al_offset     = cpu_to_be32(mdev->ldev->md.al_offset);
-	buffer->al_nr_extents = cpu_to_be32(mdev->act_log->nr_elements);
+	buffer->md_size_sect  = cpu_to_be32(device->ldev->md.md_size_sect);
+	buffer->al_offset     = cpu_to_be32(device->ldev->md.al_offset);
+	buffer->al_nr_extents = cpu_to_be32(device->act_log->nr_elements);
 	buffer->bm_bytes_per_bit = cpu_to_be32(BM_BLOCK_SIZE);
-	buffer->device_uuid = cpu_to_be64(mdev->ldev->md.device_uuid);
+	buffer->device_uuid = cpu_to_be64(device->ldev->md.device_uuid);
 
-	buffer->bm_offset = cpu_to_be32(mdev->ldev->md.bm_offset);
-	buffer->la_peer_max_bio_size = cpu_to_be32(mdev->peer_max_bio_size);
+	buffer->bm_offset = cpu_to_be32(device->ldev->md.bm_offset);
+	buffer->la_peer_max_bio_size = cpu_to_be32(device->peer_max_bio_size);
 
-	buffer->al_stripes = cpu_to_be32(mdev->ldev->md.al_stripes);
-	buffer->al_stripe_size_4k = cpu_to_be32(mdev->ldev->md.al_stripe_size_4k);
+	buffer->al_stripes = cpu_to_be32(device->ldev->md.al_stripes);
+	buffer->al_stripe_size_4k = cpu_to_be32(device->ldev->md.al_stripe_size_4k);
 
-	D_ASSERT(drbd_md_ss(mdev->ldev) == mdev->ldev->md.md_offset);
-	sector = mdev->ldev->md.md_offset;
+	D_ASSERT(device, drbd_md_ss(device->ldev) == device->ldev->md.md_offset);
+	sector = device->ldev->md.md_offset;
 
-	if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
+	if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) {
 		/* this was a try anyways ... */
-		dev_err(DEV, "meta data update failed!\n");
-		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+		drbd_err(device, "meta data update failed!\n");
+		drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
 	}
 }
 
 /**
  * drbd_md_sync() - Writes the meta data super block if the MD_DIRTY flag bit is set
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  */
-void drbd_md_sync(struct drbd_conf *mdev)
+void drbd_md_sync(struct drbd_device *device)
 {
 	struct meta_data_on_disk *buffer;
 
@@ -2931,32 +3069,32 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	BUILD_BUG_ON(UI_SIZE != 4);
 	BUILD_BUG_ON(sizeof(struct meta_data_on_disk) != 4096);
 
-	del_timer(&mdev->md_sync_timer);
+	del_timer(&device->md_sync_timer);
 	/* timer may be rearmed by drbd_md_mark_dirty() now. */
-	if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
+	if (!test_and_clear_bit(MD_DIRTY, &device->flags))
 		return;
 
 	/* We use here D_FAILED and not D_ATTACHING because we try to write
 	 * metadata even if we detach due to a disk failure! */
-	if (!get_ldev_if_state(mdev, D_FAILED))
+	if (!get_ldev_if_state(device, D_FAILED))
 		return;
 
-	buffer = drbd_md_get_buffer(mdev);
+	buffer = drbd_md_get_buffer(device);
 	if (!buffer)
 		goto out;
 
-	drbd_md_write(mdev, buffer);
+	drbd_md_write(device, buffer);
 
-	/* Update mdev->ldev->md.la_size_sect,
+	/* Update device->ldev->md.la_size_sect,
 	 * since we updated it on metadata. */
-	mdev->ldev->md.la_size_sect = drbd_get_capacity(mdev->this_bdev);
+	device->ldev->md.la_size_sect = drbd_get_capacity(device->this_bdev);
 
-	drbd_md_put_buffer(mdev);
+	drbd_md_put_buffer(device);
 out:
-	put_ldev(mdev);
+	put_ldev(device);
 }
 
-static int check_activity_log_stripe_size(struct drbd_conf *mdev,
+static int check_activity_log_stripe_size(struct drbd_device *device,
 		struct meta_data_on_disk *on_disk,
 		struct drbd_md *in_core)
 {
@@ -2996,12 +3134,12 @@ static int check_activity_log_stripe_size(struct drbd_conf *mdev,
 
 	return 0;
 err:
-	dev_err(DEV, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
+	drbd_err(device, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
 			al_stripes, al_stripe_size_4k);
 	return -EINVAL;
 }
 
-static int check_offsets_and_sizes(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
+static int check_offsets_and_sizes(struct drbd_device *device, struct drbd_backing_dev *bdev)
 {
 	sector_t capacity = drbd_get_capacity(bdev->md_bdev);
 	struct drbd_md *in_core = &bdev->md;
@@ -3068,7 +3206,7 @@ static int check_offsets_and_sizes(struct drbd_conf *mdev, struct drbd_backing_d
 	return 0;
 
 err:
-	dev_err(DEV, "meta data offsets don't make sense: idx=%d "
+	drbd_err(device, "meta data offsets don't make sense: idx=%d "
 			"al_s=%u, al_sz4k=%u, al_offset=%d, bm_offset=%d, "
 			"md_size_sect=%u, la_size=%llu, md_capacity=%llu\n",
 			in_core->meta_dev_idx,
@@ -3083,25 +3221,25 @@ err:
 
 /**
  * drbd_md_read() - Reads in the meta data super block
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @bdev:	Device from which the meta data should be read in.
  *
  * Return NO_ERROR on success, and an enum drbd_ret_code in case
  * something goes wrong.
  *
  * Called exactly once during drbd_adm_attach(), while still being D_DISKLESS,
- * even before @bdev is assigned to @mdev->ldev.
+ * even before @bdev is assigned to @device->ldev.
  */
-int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
+int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
 {
 	struct meta_data_on_disk *buffer;
 	u32 magic, flags;
 	int i, rv = NO_ERROR;
 
-	if (mdev->state.disk != D_DISKLESS)
+	if (device->state.disk != D_DISKLESS)
 		return ERR_DISK_CONFIGURED;
 
-	buffer = drbd_md_get_buffer(mdev);
+	buffer = drbd_md_get_buffer(device);
 	if (!buffer)
 		return ERR_NOMEM;
 
@@ -3110,10 +3248,10 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	bdev->md.meta_dev_idx = bdev->disk_conf->meta_dev_idx;
 	bdev->md.md_offset = drbd_md_ss(bdev);
 
-	if (drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
+	if (drbd_md_sync_page_io(device, bdev, bdev->md.md_offset, READ)) {
 		/* NOTE: can't do normal error processing here as this is
 		   called BEFORE disk is attached */
-		dev_err(DEV, "Error while reading metadata.\n");
+		drbd_err(device, "Error while reading metadata.\n");
 		rv = ERR_IO_MD_DISK;
 		goto err;
 	}
@@ -3123,7 +3261,7 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	if (magic == DRBD_MD_MAGIC_84_UNCLEAN ||
 	    (magic == DRBD_MD_MAGIC_08 && !(flags & MDF_AL_CLEAN))) {
 			/* btw: that's Activity Log clean, not "all" clean. */
-		dev_err(DEV, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
+		drbd_err(device, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
 		rv = ERR_MD_UNCLEAN;
 		goto err;
 	}
@@ -3131,14 +3269,14 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	rv = ERR_MD_INVALID;
 	if (magic != DRBD_MD_MAGIC_08) {
 		if (magic == DRBD_MD_MAGIC_07)
-			dev_err(DEV, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
+			drbd_err(device, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
 		else
-			dev_err(DEV, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
+			drbd_err(device, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
 		goto err;
 	}
 
 	if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
-		dev_err(DEV, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
+		drbd_err(device, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
 		    be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
 		goto err;
 	}
@@ -3155,182 +3293,182 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	bdev->md.al_offset = be32_to_cpu(buffer->al_offset);
 	bdev->md.bm_offset = be32_to_cpu(buffer->bm_offset);
 
-	if (check_activity_log_stripe_size(mdev, buffer, &bdev->md))
+	if (check_activity_log_stripe_size(device, buffer, &bdev->md))
 		goto err;
-	if (check_offsets_and_sizes(mdev, bdev))
+	if (check_offsets_and_sizes(device, bdev))
 		goto err;
 
 	if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) {
-		dev_err(DEV, "unexpected bm_offset: %d (expected %d)\n",
+		drbd_err(device, "unexpected bm_offset: %d (expected %d)\n",
 		    be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset);
 		goto err;
 	}
 	if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) {
-		dev_err(DEV, "unexpected md_size: %u (expected %u)\n",
+		drbd_err(device, "unexpected md_size: %u (expected %u)\n",
 		    be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect);
 		goto err;
 	}
 
 	rv = NO_ERROR;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	if (mdev->state.conn < C_CONNECTED) {
+	spin_lock_irq(&device->resource->req_lock);
+	if (device->state.conn < C_CONNECTED) {
 		unsigned int peer;
 		peer = be32_to_cpu(buffer->la_peer_max_bio_size);
 		peer = max(peer, DRBD_MAX_BIO_SIZE_SAFE);
-		mdev->peer_max_bio_size = peer;
+		device->peer_max_bio_size = peer;
 	}
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
  err:
-	drbd_md_put_buffer(mdev);
+	drbd_md_put_buffer(device);
 
 	return rv;
 }
 
 /**
  * drbd_md_mark_dirty() - Mark meta data super block as dirty
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Call this function if you change anything that should be written to
  * the meta-data super block. This function sets MD_DIRTY, and starts a
  * timer that ensures that within five seconds you have to call drbd_md_sync().
  */
 #ifdef DEBUG
-void drbd_md_mark_dirty_(struct drbd_conf *mdev, unsigned int line, const char *func)
+void drbd_md_mark_dirty_(struct drbd_device *device, unsigned int line, const char *func)
 {
-	if (!test_and_set_bit(MD_DIRTY, &mdev->flags)) {
-		mod_timer(&mdev->md_sync_timer, jiffies + HZ);
-		mdev->last_md_mark_dirty.line = line;
-		mdev->last_md_mark_dirty.func = func;
+	if (!test_and_set_bit(MD_DIRTY, &device->flags)) {
+		mod_timer(&device->md_sync_timer, jiffies + HZ);
+		device->last_md_mark_dirty.line = line;
+		device->last_md_mark_dirty.func = func;
 	}
 }
 #else
-void drbd_md_mark_dirty(struct drbd_conf *mdev)
+void drbd_md_mark_dirty(struct drbd_device *device)
 {
-	if (!test_and_set_bit(MD_DIRTY, &mdev->flags))
-		mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
+	if (!test_and_set_bit(MD_DIRTY, &device->flags))
+		mod_timer(&device->md_sync_timer, jiffies + 5*HZ);
 }
 #endif
 
-void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
+void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local)
 {
 	int i;
 
 	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
-		mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
+		device->ldev->md.uuid[i+1] = device->ldev->md.uuid[i];
 }
 
-void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
+void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
 {
 	if (idx == UI_CURRENT) {
-		if (mdev->state.role == R_PRIMARY)
+		if (device->state.role == R_PRIMARY)
 			val |= 1;
 		else
 			val &= ~((u64)1);
 
-		drbd_set_ed_uuid(mdev, val);
+		drbd_set_ed_uuid(device, val);
 	}
 
-	mdev->ldev->md.uuid[idx] = val;
-	drbd_md_mark_dirty(mdev);
+	device->ldev->md.uuid[idx] = val;
+	drbd_md_mark_dirty(device);
 }
 
-void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
+void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
-	__drbd_uuid_set(mdev, idx, val);
-	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
+	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
+	__drbd_uuid_set(device, idx, val);
+	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
 }
 
-void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
+void drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
-	if (mdev->ldev->md.uuid[idx]) {
-		drbd_uuid_move_history(mdev);
-		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
+	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
+	if (device->ldev->md.uuid[idx]) {
+		drbd_uuid_move_history(device);
+		device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[idx];
 	}
-	__drbd_uuid_set(mdev, idx, val);
-	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
+	__drbd_uuid_set(device, idx, val);
+	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
 }
 
 /**
  * drbd_uuid_new_current() - Creates a new current UUID
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Creates a new current UUID, and rotates the old current UUID into
  * the bitmap slot. Causes an incremental resync upon next connect.
  */
-void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
+void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
 {
 	u64 val;
 	unsigned long long bm_uuid;
 
 	get_random_bytes(&val, sizeof(u64));
 
-	spin_lock_irq(&mdev->ldev->md.uuid_lock);
-	bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+	spin_lock_irq(&device->ldev->md.uuid_lock);
+	bm_uuid = device->ldev->md.uuid[UI_BITMAP];
 
 	if (bm_uuid)
-		dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
+		drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
 
-	mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
-	__drbd_uuid_set(mdev, UI_CURRENT, val);
-	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
+	device->ldev->md.uuid[UI_BITMAP] = device->ldev->md.uuid[UI_CURRENT];
+	__drbd_uuid_set(device, UI_CURRENT, val);
+	spin_unlock_irq(&device->ldev->md.uuid_lock);
 
-	drbd_print_uuids(mdev, "new current UUID");
+	drbd_print_uuids(device, "new current UUID");
 	/* get it to stable storage _now_ */
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 }
 
-void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
+void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
 {
 	unsigned long flags;
-	if (mdev->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
+	if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
 		return;
 
-	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
+	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
 	if (val == 0) {
-		drbd_uuid_move_history(mdev);
-		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
-		mdev->ldev->md.uuid[UI_BITMAP] = 0;
+		drbd_uuid_move_history(device);
+		device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];
+		device->ldev->md.uuid[UI_BITMAP] = 0;
 	} else {
-		unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+		unsigned long long bm_uuid = device->ldev->md.uuid[UI_BITMAP];
 		if (bm_uuid)
-			dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
+			drbd_warn(device, "bm UUID was already set: %llX\n", bm_uuid);
 
-		mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
+		device->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
 	}
-	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
+	spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
 
-	drbd_md_mark_dirty(mdev);
+	drbd_md_mark_dirty(device);
 }
 
 /**
  * drbd_bmio_set_n_write() - io_fn for drbd_queue_bitmap_io() or drbd_bitmap_io()
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Sets all bits in the bitmap and writes the whole bitmap to stable storage.
  */
-int drbd_bmio_set_n_write(struct drbd_conf *mdev)
+int drbd_bmio_set_n_write(struct drbd_device *device)
 {
 	int rv = -EIO;
 
-	if (get_ldev_if_state(mdev, D_ATTACHING)) {
-		drbd_md_set_flag(mdev, MDF_FULL_SYNC);
-		drbd_md_sync(mdev);
-		drbd_bm_set_all(mdev);
+	if (get_ldev_if_state(device, D_ATTACHING)) {
+		drbd_md_set_flag(device, MDF_FULL_SYNC);
+		drbd_md_sync(device);
+		drbd_bm_set_all(device);
 
-		rv = drbd_bm_write(mdev);
+		rv = drbd_bm_write(device);
 
 		if (!rv) {
-			drbd_md_clear_flag(mdev, MDF_FULL_SYNC);
-			drbd_md_sync(mdev);
+			drbd_md_clear_flag(device, MDF_FULL_SYNC);
+			drbd_md_sync(device);
 		}
 
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	return rv;
@@ -3338,19 +3476,19 @@ int drbd_bmio_set_n_write(struct drbd_conf *mdev)
 
 /**
  * drbd_bmio_clear_n_write() - io_fn for drbd_queue_bitmap_io() or drbd_bitmap_io()
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Clears all bits in the bitmap and writes the whole bitmap to stable storage.
  */
-int drbd_bmio_clear_n_write(struct drbd_conf *mdev)
+int drbd_bmio_clear_n_write(struct drbd_device *device)
 {
 	int rv = -EIO;
 
-	drbd_resume_al(mdev);
-	if (get_ldev_if_state(mdev, D_ATTACHING)) {
-		drbd_bm_clear_all(mdev);
-		rv = drbd_bm_write(mdev);
-		put_ldev(mdev);
+	drbd_resume_al(device);
+	if (get_ldev_if_state(device, D_ATTACHING)) {
+		drbd_bm_clear_all(device);
+		rv = drbd_bm_write(device);
+		put_ldev(device);
 	}
 
 	return rv;
@@ -3358,50 +3496,52 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev)
 
 static int w_bitmap_io(struct drbd_work *w, int unused)
 {
-	struct bm_io_work *work = container_of(w, struct bm_io_work, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, bm_io_work.w);
+	struct bm_io_work *work = &device->bm_io_work;
 	int rv = -EIO;
 
-	D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0);
+	D_ASSERT(device, atomic_read(&device->ap_bio_cnt) == 0);
 
-	if (get_ldev(mdev)) {
-		drbd_bm_lock(mdev, work->why, work->flags);
-		rv = work->io_fn(mdev);
-		drbd_bm_unlock(mdev);
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		drbd_bm_lock(device, work->why, work->flags);
+		rv = work->io_fn(device);
+		drbd_bm_unlock(device);
+		put_ldev(device);
 	}
 
-	clear_bit_unlock(BITMAP_IO, &mdev->flags);
-	wake_up(&mdev->misc_wait);
+	clear_bit_unlock(BITMAP_IO, &device->flags);
+	wake_up(&device->misc_wait);
 
 	if (work->done)
-		work->done(mdev, rv);
+		work->done(device, rv);
 
-	clear_bit(BITMAP_IO_QUEUED, &mdev->flags);
+	clear_bit(BITMAP_IO_QUEUED, &device->flags);
 	work->why = NULL;
 	work->flags = 0;
 
 	return 0;
 }
 
-void drbd_ldev_destroy(struct drbd_conf *mdev)
+void drbd_ldev_destroy(struct drbd_device *device)
 {
-	lc_destroy(mdev->resync);
-	mdev->resync = NULL;
-	lc_destroy(mdev->act_log);
-	mdev->act_log = NULL;
+	lc_destroy(device->resync);
+	device->resync = NULL;
+	lc_destroy(device->act_log);
+	device->act_log = NULL;
 	__no_warn(local,
-		drbd_free_bc(mdev->ldev);
-		mdev->ldev = NULL;);
+		drbd_free_bc(device->ldev);
+		device->ldev = NULL;);
 
-	clear_bit(GO_DISKLESS, &mdev->flags);
+	clear_bit(GO_DISKLESS, &device->flags);
 }
 
 static int w_go_diskless(struct drbd_work *w, int unused)
 {
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, go_diskless);
 
-	D_ASSERT(mdev->state.disk == D_FAILED);
+	D_ASSERT(device, device->state.disk == D_FAILED);
 	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
 	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
 	 * the protected members anymore, though, so once put_ldev reaches zero
@@ -3420,27 +3560,27 @@ static int w_go_diskless(struct drbd_work *w, int unused)
 	 * We still need to check if both bitmap and ldev are present, we may
 	 * end up here after a failed attach, before ldev was even assigned.
 	 */
-	if (mdev->bitmap && mdev->ldev) {
+	if (device->bitmap && device->ldev) {
 		/* An interrupted resync or similar is allowed to recounts bits
 		 * while we detach.
 		 * Any modifications would not be expected anymore, though.
 		 */
-		if (drbd_bitmap_io_from_worker(mdev, drbd_bm_write,
+		if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
 					"detach", BM_LOCKED_TEST_ALLOWED)) {
-			if (test_bit(WAS_READ_ERROR, &mdev->flags)) {
-				drbd_md_set_flag(mdev, MDF_FULL_SYNC);
-				drbd_md_sync(mdev);
+			if (test_bit(WAS_READ_ERROR, &device->flags)) {
+				drbd_md_set_flag(device, MDF_FULL_SYNC);
+				drbd_md_sync(device);
 			}
 		}
 	}
 
-	drbd_force_state(mdev, NS(disk, D_DISKLESS));
+	drbd_force_state(device, NS(disk, D_DISKLESS));
 	return 0;
 }
 
 /**
  * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @io_fn:	IO callback to be called when bitmap IO is possible
  * @done:	callback to be called after the bitmap IO was performed
  * @why:	Descriptive text of the reason for doing the IO
@@ -3450,76 +3590,77 @@ static int w_go_diskless(struct drbd_work *w, int unused)
  * called from worker context. It MUST NOT be used while a previous such
  * work is still pending!
  */
-void drbd_queue_bitmap_io(struct drbd_conf *mdev,
-			  int (*io_fn)(struct drbd_conf *),
-			  void (*done)(struct drbd_conf *, int),
+void drbd_queue_bitmap_io(struct drbd_device *device,
+			  int (*io_fn)(struct drbd_device *),
+			  void (*done)(struct drbd_device *, int),
 			  char *why, enum bm_flag flags)
 {
-	D_ASSERT(current == mdev->tconn->worker.task);
+	D_ASSERT(device, current == first_peer_device(device)->connection->worker.task);
 
-	D_ASSERT(!test_bit(BITMAP_IO_QUEUED, &mdev->flags));
-	D_ASSERT(!test_bit(BITMAP_IO, &mdev->flags));
-	D_ASSERT(list_empty(&mdev->bm_io_work.w.list));
-	if (mdev->bm_io_work.why)
-		dev_err(DEV, "FIXME going to queue '%s' but '%s' still pending?\n",
-			why, mdev->bm_io_work.why);
+	D_ASSERT(device, !test_bit(BITMAP_IO_QUEUED, &device->flags));
+	D_ASSERT(device, !test_bit(BITMAP_IO, &device->flags));
+	D_ASSERT(device, list_empty(&device->bm_io_work.w.list));
+	if (device->bm_io_work.why)
+		drbd_err(device, "FIXME going to queue '%s' but '%s' still pending?\n",
+			why, device->bm_io_work.why);
 
-	mdev->bm_io_work.io_fn = io_fn;
-	mdev->bm_io_work.done = done;
-	mdev->bm_io_work.why = why;
-	mdev->bm_io_work.flags = flags;
+	device->bm_io_work.io_fn = io_fn;
+	device->bm_io_work.done = done;
+	device->bm_io_work.why = why;
+	device->bm_io_work.flags = flags;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	set_bit(BITMAP_IO, &mdev->flags);
-	if (atomic_read(&mdev->ap_bio_cnt) == 0) {
-		if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
-			drbd_queue_work(&mdev->tconn->sender_work, &mdev->bm_io_work.w);
+	spin_lock_irq(&device->resource->req_lock);
+	set_bit(BITMAP_IO, &device->flags);
+	if (atomic_read(&device->ap_bio_cnt) == 0) {
+		if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
+			drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+					&device->bm_io_work.w);
 	}
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 }
 
 /**
  * drbd_bitmap_io() -  Does an IO operation on the whole bitmap
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @io_fn:	IO callback to be called when bitmap IO is possible
  * @why:	Descriptive text of the reason for doing the IO
  *
  * freezes application IO while that the actual IO operations runs. This
  * functions MAY NOT be called from worker context.
  */
-int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *),
+int drbd_bitmap_io(struct drbd_device *device, int (*io_fn)(struct drbd_device *),
 		char *why, enum bm_flag flags)
 {
 	int rv;
 
-	D_ASSERT(current != mdev->tconn->worker.task);
+	D_ASSERT(device, current != first_peer_device(device)->connection->worker.task);
 
 	if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
-		drbd_suspend_io(mdev);
+		drbd_suspend_io(device);
 
-	drbd_bm_lock(mdev, why, flags);
-	rv = io_fn(mdev);
-	drbd_bm_unlock(mdev);
+	drbd_bm_lock(device, why, flags);
+	rv = io_fn(device);
+	drbd_bm_unlock(device);
 
 	if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
-		drbd_resume_io(mdev);
+		drbd_resume_io(device);
 
 	return rv;
 }
 
-void drbd_md_set_flag(struct drbd_conf *mdev, int flag) __must_hold(local)
+void drbd_md_set_flag(struct drbd_device *device, int flag) __must_hold(local)
 {
-	if ((mdev->ldev->md.flags & flag) != flag) {
-		drbd_md_mark_dirty(mdev);
-		mdev->ldev->md.flags |= flag;
+	if ((device->ldev->md.flags & flag) != flag) {
+		drbd_md_mark_dirty(device);
+		device->ldev->md.flags |= flag;
 	}
 }
 
-void drbd_md_clear_flag(struct drbd_conf *mdev, int flag) __must_hold(local)
+void drbd_md_clear_flag(struct drbd_device *device, int flag) __must_hold(local)
 {
-	if ((mdev->ldev->md.flags & flag) != 0) {
-		drbd_md_mark_dirty(mdev);
-		mdev->ldev->md.flags &= ~flag;
+	if ((device->ldev->md.flags & flag) != 0) {
+		drbd_md_mark_dirty(device);
+		device->ldev->md.flags &= ~flag;
 	}
 }
 int drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag)
@@ -3529,23 +3670,25 @@ int drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag)
 
 static void md_sync_timer_fn(unsigned long data)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
+	struct drbd_device *device = (struct drbd_device *) data;
 
 	/* must not double-queue! */
-	if (list_empty(&mdev->md_sync_work.list))
-		drbd_queue_work_front(&mdev->tconn->sender_work, &mdev->md_sync_work);
+	if (list_empty(&device->md_sync_work.list))
+		drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
+				      &device->md_sync_work);
 }
 
 static int w_md_sync(struct drbd_work *w, int unused)
 {
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, md_sync_work);
 
-	dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+	drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
 #ifdef DEBUG
-	dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
-		mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
+	drbd_warn(device, "last md_mark_dirty: %s:%u\n",
+		device->last_md_mark_dirty.func, device->last_md_mark_dirty.line);
 #endif
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 	return 0;
 }
 
@@ -3621,18 +3764,18 @@ const char *cmdname(enum drbd_packet cmd)
 
 /**
  * drbd_wait_misc  -  wait for a request to make progress
- * @mdev:	device associated with the request
+ * @device:	device associated with the request
  * @i:		the struct drbd_interval embedded in struct drbd_request or
  *		struct drbd_peer_request
  */
-int drbd_wait_misc(struct drbd_conf *mdev, struct drbd_interval *i)
+int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
 {
 	struct net_conf *nc;
 	DEFINE_WAIT(wait);
 	long timeout;
 
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 	if (!nc) {
 		rcu_read_unlock();
 		return -ETIMEDOUT;
@@ -3640,14 +3783,14 @@ int drbd_wait_misc(struct drbd_conf *mdev, struct drbd_interval *i)
 	timeout = nc->ko_count ? nc->timeout * HZ / 10 * nc->ko_count : MAX_SCHEDULE_TIMEOUT;
 	rcu_read_unlock();
 
-	/* Indicate to wake up mdev->misc_wait on progress.  */
+	/* Indicate to wake up device->misc_wait on progress.  */
 	i->waiting = true;
-	prepare_to_wait(&mdev->misc_wait, &wait, TASK_INTERRUPTIBLE);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	prepare_to_wait(&device->misc_wait, &wait, TASK_INTERRUPTIBLE);
+	spin_unlock_irq(&device->resource->req_lock);
 	timeout = schedule_timeout(timeout);
-	finish_wait(&mdev->misc_wait, &wait);
-	spin_lock_irq(&mdev->tconn->req_lock);
-	if (!timeout || mdev->state.conn < C_CONNECTED)
+	finish_wait(&device->misc_wait, &wait);
+	spin_lock_irq(&device->resource->req_lock);
+	if (!timeout || device->state.conn < C_CONNECTED)
 		return -ETIMEDOUT;
 	if (signal_pending(current))
 		return -ERESTARTSYS;
@@ -3703,20 +3846,20 @@ _drbd_fault_str(unsigned int type) {
 }
 
 unsigned int
-_drbd_insert_fault(struct drbd_conf *mdev, unsigned int type)
+_drbd_insert_fault(struct drbd_device *device, unsigned int type)
 {
 	static struct fault_random_state rrs = {0, 0};
 
 	unsigned int ret = (
 		(fault_devs == 0 ||
-			((1 << mdev_to_minor(mdev)) & fault_devs) != 0) &&
+			((1 << device_to_minor(device)) & fault_devs) != 0) &&
 		(((_drbd_fault_random(&rrs) % 100) + 1) <= fault_rate));
 
 	if (ret) {
 		fault_count++;
 
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_warn(DEV, "***Simulating %s failure\n",
+			drbd_warn(device, "***Simulating %s failure\n",
 				_drbd_fault_str(type));
 	}
 
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index c706d50a8b06..526414bc2cab 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -32,6 +32,7 @@
 #include <linux/blkpg.h>
 #include <linux/cpumask.h>
 #include "drbd_int.h"
+#include "drbd_protocol.h"
 #include "drbd_req.h"
 #include "drbd_wrappers.h"
 #include <asm/unaligned.h>
@@ -44,8 +45,8 @@
 // int drbd_adm_create_resource(struct sk_buff *skb, struct genl_info *info);
 // int drbd_adm_delete_resource(struct sk_buff *skb, struct genl_info *info);
 
-int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info);
-int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_del_minor(struct sk_buff *skb, struct genl_info *info);
 
 int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info);
 int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info);
@@ -102,8 +103,9 @@ static struct drbd_config_context {
 	/* pointer into reply buffer */
 	struct drbd_genlmsghdr *reply_dh;
 	/* resolved from attributes, if possible */
-	struct drbd_conf *mdev;
-	struct drbd_tconn *tconn;
+	struct drbd_device *device;
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 } adm_ctx;
 
 static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info)
@@ -202,62 +204,67 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
 		adm_ctx.my_addr = nested_attr_tb[__nla_type(T_ctx_my_addr)];
 		adm_ctx.peer_addr = nested_attr_tb[__nla_type(T_ctx_peer_addr)];
 		if ((adm_ctx.my_addr &&
-		     nla_len(adm_ctx.my_addr) > sizeof(adm_ctx.tconn->my_addr)) ||
+		     nla_len(adm_ctx.my_addr) > sizeof(adm_ctx.connection->my_addr)) ||
 		    (adm_ctx.peer_addr &&
-		     nla_len(adm_ctx.peer_addr) > sizeof(adm_ctx.tconn->peer_addr))) {
+		     nla_len(adm_ctx.peer_addr) > sizeof(adm_ctx.connection->peer_addr))) {
 			err = -EINVAL;
 			goto fail;
 		}
 	}
 
 	adm_ctx.minor = d_in->minor;
-	adm_ctx.mdev = minor_to_mdev(d_in->minor);
-	adm_ctx.tconn = conn_get_by_name(adm_ctx.resource_name);
+	adm_ctx.device = minor_to_device(d_in->minor);
+	if (adm_ctx.resource_name) {
+		adm_ctx.resource = drbd_find_resource(adm_ctx.resource_name);
+	}
 
-	if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) {
+	if (!adm_ctx.device && (flags & DRBD_ADM_NEED_MINOR)) {
 		drbd_msg_put_info("unknown minor");
 		return ERR_MINOR_INVALID;
 	}
-	if (!adm_ctx.tconn && (flags & DRBD_ADM_NEED_RESOURCE)) {
+	if (!adm_ctx.resource && (flags & DRBD_ADM_NEED_RESOURCE)) {
 		drbd_msg_put_info("unknown resource");
+		if (adm_ctx.resource_name)
+			return ERR_RES_NOT_KNOWN;
 		return ERR_INVALID_REQUEST;
 	}
 
 	if (flags & DRBD_ADM_NEED_CONNECTION) {
-		if (adm_ctx.tconn && !(flags & DRBD_ADM_NEED_RESOURCE)) {
+		if (adm_ctx.resource) {
 			drbd_msg_put_info("no resource name expected");
 			return ERR_INVALID_REQUEST;
 		}
-		if (adm_ctx.mdev) {
+		if (adm_ctx.device) {
 			drbd_msg_put_info("no minor number expected");
 			return ERR_INVALID_REQUEST;
 		}
 		if (adm_ctx.my_addr && adm_ctx.peer_addr)
-			adm_ctx.tconn = conn_get_by_addrs(nla_data(adm_ctx.my_addr),
+			adm_ctx.connection = conn_get_by_addrs(nla_data(adm_ctx.my_addr),
 							  nla_len(adm_ctx.my_addr),
 							  nla_data(adm_ctx.peer_addr),
 							  nla_len(adm_ctx.peer_addr));
-		if (!adm_ctx.tconn) {
+		if (!adm_ctx.connection) {
 			drbd_msg_put_info("unknown connection");
 			return ERR_INVALID_REQUEST;
 		}
 	}
 
 	/* some more paranoia, if the request was over-determined */
-	if (adm_ctx.mdev && adm_ctx.tconn &&
-	    adm_ctx.mdev->tconn != adm_ctx.tconn) {
-		pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n",
-				adm_ctx.minor, adm_ctx.resource_name,
-				adm_ctx.mdev->tconn->name);
+	if (adm_ctx.device && adm_ctx.resource &&
+	    adm_ctx.device->resource != adm_ctx.resource) {
+		pr_warning("request: minor=%u, resource=%s; but that minor belongs to resource %s\n",
+				adm_ctx.minor, adm_ctx.resource->name,
+				adm_ctx.device->resource->name);
 		drbd_msg_put_info("minor exists in different resource");
 		return ERR_INVALID_REQUEST;
 	}
-	if (adm_ctx.mdev &&
+	if (adm_ctx.device &&
 	    adm_ctx.volume != VOLUME_UNSPECIFIED &&
-	    adm_ctx.volume != adm_ctx.mdev->vnr) {
+	    adm_ctx.volume != adm_ctx.device->vnr) {
 		pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n",
 				adm_ctx.minor, adm_ctx.volume,
-				adm_ctx.mdev->vnr, adm_ctx.mdev->tconn->name);
+				adm_ctx.device->vnr,
+				adm_ctx.device->resource->name);
 		drbd_msg_put_info("minor exists as different volume");
 		return ERR_INVALID_REQUEST;
 	}
@@ -272,9 +279,13 @@ fail:
 
 static int drbd_adm_finish(struct genl_info *info, int retcode)
 {
-	if (adm_ctx.tconn) {
-		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
-		adm_ctx.tconn = NULL;
+	if (adm_ctx.connection) {
+		kref_put(&adm_ctx.connection->kref, drbd_destroy_connection);
+		adm_ctx.connection = NULL;
+	}
+	if (adm_ctx.resource) {
+		kref_put(&adm_ctx.resource->kref, drbd_destroy_resource);
+		adm_ctx.resource = NULL;
 	}
 
 	if (!adm_ctx.reply_skb)
@@ -285,34 +296,34 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
 	return 0;
 }
 
-static void setup_khelper_env(struct drbd_tconn *tconn, char **envp)
+static void setup_khelper_env(struct drbd_connection *connection, char **envp)
 {
 	char *afs;
 
 	/* FIXME: A future version will not allow this case. */
-	if (tconn->my_addr_len == 0 || tconn->peer_addr_len == 0)
+	if (connection->my_addr_len == 0 || connection->peer_addr_len == 0)
 		return;
 
-	switch (((struct sockaddr *)&tconn->peer_addr)->sa_family) {
+	switch (((struct sockaddr *)&connection->peer_addr)->sa_family) {
 	case AF_INET6:
 		afs = "ipv6";
 		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI6",
-			 &((struct sockaddr_in6 *)&tconn->peer_addr)->sin6_addr);
+			 &((struct sockaddr_in6 *)&connection->peer_addr)->sin6_addr);
 		break;
 	case AF_INET:
 		afs = "ipv4";
 		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
-			 &((struct sockaddr_in *)&tconn->peer_addr)->sin_addr);
+			 &((struct sockaddr_in *)&connection->peer_addr)->sin_addr);
 		break;
 	default:
 		afs = "ssocks";
 		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
-			 &((struct sockaddr_in *)&tconn->peer_addr)->sin_addr);
+			 &((struct sockaddr_in *)&connection->peer_addr)->sin_addr);
 	}
 	snprintf(envp[3], 20, "DRBD_PEER_AF=%s", afs);
 }
 
-int drbd_khelper(struct drbd_conf *mdev, char *cmd)
+int drbd_khelper(struct drbd_device *device, char *cmd)
 {
 	char *envp[] = { "HOME=/",
 			"TERM=linux",
@@ -322,39 +333,39 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 			NULL };
 	char mb[12];
 	char *argv[] = {usermode_helper, cmd, mb, NULL };
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	struct sib_info sib;
 	int ret;
 
-	if (current == tconn->worker.task)
-		set_bit(CALLBACK_PENDING, &tconn->flags);
+	if (current == connection->worker.task)
+		set_bit(CALLBACK_PENDING, &connection->flags);
 
-	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
-	setup_khelper_env(tconn, envp);
+	snprintf(mb, 12, "minor-%d", device_to_minor(device));
+	setup_khelper_env(connection, envp);
 
 	/* The helper may take some time.
 	 * write out any unsynced meta data changes now */
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
-	dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
+	drbd_info(device, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
 	sib.sib_reason = SIB_HELPER_PRE;
 	sib.helper_name = cmd;
-	drbd_bcast_event(mdev, &sib);
+	drbd_bcast_event(device, &sib);
 	ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
 	if (ret)
-		dev_warn(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
+		drbd_warn(device, "helper command: %s %s %s exit code %u (0x%x)\n",
 				usermode_helper, cmd, mb,
 				(ret >> 8) & 0xff, ret);
 	else
-		dev_info(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
+		drbd_info(device, "helper command: %s %s %s exit code %u (0x%x)\n",
 				usermode_helper, cmd, mb,
 				(ret >> 8) & 0xff, ret);
 	sib.sib_reason = SIB_HELPER_POST;
 	sib.helper_exit_code = ret;
-	drbd_bcast_event(mdev, &sib);
+	drbd_bcast_event(device, &sib);
 
-	if (current == tconn->worker.task)
-		clear_bit(CALLBACK_PENDING, &tconn->flags);
+	if (current == connection->worker.task)
+		clear_bit(CALLBACK_PENDING, &connection->flags);
 
 	if (ret < 0) /* Ignore any ERRNOs we got. */
 		ret = 0;
@@ -362,7 +373,7 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 	return ret;
 }
 
-int conn_khelper(struct drbd_tconn *tconn, char *cmd)
+static int conn_khelper(struct drbd_connection *connection, char *cmd)
 {
 	char *envp[] = { "HOME=/",
 			"TERM=linux",
@@ -370,23 +381,24 @@ int conn_khelper(struct drbd_tconn *tconn, char *cmd)
 			 (char[20]) { }, /* address family */
 			 (char[60]) { }, /* address */
 			NULL };
-	char *argv[] = {usermode_helper, cmd, tconn->name, NULL };
+	char *resource_name = connection->resource->name;
+	char *argv[] = {usermode_helper, cmd, resource_name, NULL };
 	int ret;
 
-	setup_khelper_env(tconn, envp);
-	conn_md_sync(tconn);
+	setup_khelper_env(connection, envp);
+	conn_md_sync(connection);
 
-	conn_info(tconn, "helper command: %s %s %s\n", usermode_helper, cmd, tconn->name);
+	drbd_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, resource_name);
 	/* TODO: conn_bcast_event() ?? */
 
 	ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
 	if (ret)
-		conn_warn(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
-			  usermode_helper, cmd, tconn->name,
+		drbd_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, resource_name,
 			  (ret >> 8) & 0xff, ret);
 	else
-		conn_info(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
-			  usermode_helper, cmd, tconn->name,
+		drbd_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, resource_name,
 			  (ret >> 8) & 0xff, ret);
 	/* TODO: conn_bcast_event() ?? */
 
@@ -396,18 +408,20 @@ int conn_khelper(struct drbd_tconn *tconn, char *cmd)
 	return ret;
 }
 
-static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn)
+static enum drbd_fencing_p highest_fencing_policy(struct drbd_connection *connection)
 {
 	enum drbd_fencing_p fp = FP_NOT_AVAIL;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (get_ldev_if_state(mdev, D_CONSISTENT)) {
-			fp = max_t(enum drbd_fencing_p, fp,
-				   rcu_dereference(mdev->ldev->disk_conf)->fencing);
-			put_ldev(mdev);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		if (get_ldev_if_state(device, D_CONSISTENT)) {
+			struct disk_conf *disk_conf =
+				rcu_dereference(peer_device->device->ldev->disk_conf);
+			fp = max_t(enum drbd_fencing_p, fp, disk_conf->fencing);
+			put_ldev(device);
 		}
 	}
 	rcu_read_unlock();
@@ -415,7 +429,7 @@ static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn)
 	return fp;
 }
 
-bool conn_try_outdate_peer(struct drbd_tconn *tconn)
+bool conn_try_outdate_peer(struct drbd_connection *connection)
 {
 	unsigned int connect_cnt;
 	union drbd_state mask = { };
@@ -424,26 +438,26 @@ bool conn_try_outdate_peer(struct drbd_tconn *tconn)
 	char *ex_to_string;
 	int r;
 
-	if (tconn->cstate >= C_WF_REPORT_PARAMS) {
-		conn_err(tconn, "Expected cstate < C_WF_REPORT_PARAMS\n");
+	if (connection->cstate >= C_WF_REPORT_PARAMS) {
+		drbd_err(connection, "Expected cstate < C_WF_REPORT_PARAMS\n");
 		return false;
 	}
 
-	spin_lock_irq(&tconn->req_lock);
-	connect_cnt = tconn->connect_cnt;
-	spin_unlock_irq(&tconn->req_lock);
+	spin_lock_irq(&connection->resource->req_lock);
+	connect_cnt = connection->connect_cnt;
+	spin_unlock_irq(&connection->resource->req_lock);
 
-	fp = highest_fencing_policy(tconn);
+	fp = highest_fencing_policy(connection);
 	switch (fp) {
 	case FP_NOT_AVAIL:
-		conn_warn(tconn, "Not fencing peer, I'm not even Consistent myself.\n");
+		drbd_warn(connection, "Not fencing peer, I'm not even Consistent myself.\n");
 		goto out;
 	case FP_DONT_CARE:
 		return true;
 	default: ;
 	}
 
-	r = conn_khelper(tconn, "fence-peer");
+	r = conn_khelper(connection, "fence-peer");
 
 	switch ((r>>8) & 0xff) {
 	case 3: /* peer is inconsistent */
@@ -457,7 +471,7 @@ bool conn_try_outdate_peer(struct drbd_tconn *tconn)
 		val.pdsk = D_OUTDATED;
 		break;
 	case 5: /* peer was down */
-		if (conn_highest_disk(tconn) == D_UP_TO_DATE) {
+		if (conn_highest_disk(connection) == D_UP_TO_DATE) {
 			/* we will(have) create(d) a new UUID anyways... */
 			ex_to_string = "peer is unreachable, assumed to be dead";
 			mask.pdsk = D_MASK;
@@ -470,70 +484,70 @@ bool conn_try_outdate_peer(struct drbd_tconn *tconn)
 		 * This is useful when an unconnected R_SECONDARY is asked to
 		 * become R_PRIMARY, but finds the other peer being active. */
 		ex_to_string = "peer is active";
-		conn_warn(tconn, "Peer is primary, outdating myself.\n");
+		drbd_warn(connection, "Peer is primary, outdating myself.\n");
 		mask.disk = D_MASK;
 		val.disk = D_OUTDATED;
 		break;
 	case 7:
 		if (fp != FP_STONITH)
-			conn_err(tconn, "fence-peer() = 7 && fencing != Stonith !!!\n");
+			drbd_err(connection, "fence-peer() = 7 && fencing != Stonith !!!\n");
 		ex_to_string = "peer was stonithed";
 		mask.pdsk = D_MASK;
 		val.pdsk = D_OUTDATED;
 		break;
 	default:
 		/* The script is broken ... */
-		conn_err(tconn, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
+		drbd_err(connection, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
 		return false; /* Eventually leave IO frozen */
 	}
 
-	conn_info(tconn, "fence-peer helper returned %d (%s)\n",
+	drbd_info(connection, "fence-peer helper returned %d (%s)\n",
 		  (r>>8) & 0xff, ex_to_string);
 
  out:
 
 	/* Not using
-	   conn_request_state(tconn, mask, val, CS_VERBOSE);
+	   conn_request_state(connection, mask, val, CS_VERBOSE);
 	   here, because we might were able to re-establish the connection in the
 	   meantime. */
-	spin_lock_irq(&tconn->req_lock);
-	if (tconn->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &tconn->flags)) {
-		if (tconn->connect_cnt != connect_cnt)
+	spin_lock_irq(&connection->resource->req_lock);
+	if (connection->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &connection->flags)) {
+		if (connection->connect_cnt != connect_cnt)
 			/* In case the connection was established and droped
 			   while the fence-peer handler was running, ignore it */
-			conn_info(tconn, "Ignoring fence-peer exit code\n");
+			drbd_info(connection, "Ignoring fence-peer exit code\n");
 		else
-			_conn_request_state(tconn, mask, val, CS_VERBOSE);
+			_conn_request_state(connection, mask, val, CS_VERBOSE);
 	}
-	spin_unlock_irq(&tconn->req_lock);
+	spin_unlock_irq(&connection->resource->req_lock);
 
-	return conn_highest_pdsk(tconn) <= D_OUTDATED;
+	return conn_highest_pdsk(connection) <= D_OUTDATED;
 }
 
 static int _try_outdate_peer_async(void *data)
 {
-	struct drbd_tconn *tconn = (struct drbd_tconn *)data;
+	struct drbd_connection *connection = (struct drbd_connection *)data;
 
-	conn_try_outdate_peer(tconn);
+	conn_try_outdate_peer(connection);
 
-	kref_put(&tconn->kref, &conn_destroy);
+	kref_put(&connection->kref, drbd_destroy_connection);
 	return 0;
 }
 
-void conn_try_outdate_peer_async(struct drbd_tconn *tconn)
+void conn_try_outdate_peer_async(struct drbd_connection *connection)
 {
 	struct task_struct *opa;
 
-	kref_get(&tconn->kref);
-	opa = kthread_run(_try_outdate_peer_async, tconn, "drbd_async_h");
+	kref_get(&connection->kref);
+	opa = kthread_run(_try_outdate_peer_async, connection, "drbd_async_h");
 	if (IS_ERR(opa)) {
-		conn_err(tconn, "out of mem, failed to invoke fence-peer helper\n");
-		kref_put(&tconn->kref, &conn_destroy);
+		drbd_err(connection, "out of mem, failed to invoke fence-peer helper\n");
+		kref_put(&connection->kref, drbd_destroy_connection);
 	}
 }
 
 enum drbd_state_rv
-drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
+drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
 {
 	const int max_tries = 4;
 	enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
@@ -542,16 +556,24 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 	int forced = 0;
 	union drbd_state mask, val;
 
-	if (new_role == R_PRIMARY)
-		request_ping(mdev->tconn); /* Detect a dead peer ASAP */
+	if (new_role == R_PRIMARY) {
+		struct drbd_connection *connection;
 
-	mutex_lock(mdev->state_mutex);
+		/* Detect dead peers as soon as possible.  */
+
+		rcu_read_lock();
+		for_each_connection(connection, device->resource)
+			request_ping(connection);
+		rcu_read_unlock();
+	}
+
+	mutex_lock(device->state_mutex);
 
 	mask.i = 0; mask.role = R_MASK;
 	val.i  = 0; val.role  = new_role;
 
 	while (try++ < max_tries) {
-		rv = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE);
+		rv = _drbd_request_state(device, mask, val, CS_WAIT_COMPLETE);
 
 		/* in case we first succeeded to outdate,
 		 * but now suddenly could establish a connection */
@@ -562,8 +584,8 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 		}
 
 		if (rv == SS_NO_UP_TO_DATE_DISK && force &&
-		    (mdev->state.disk < D_UP_TO_DATE &&
-		     mdev->state.disk >= D_INCONSISTENT)) {
+		    (device->state.disk < D_UP_TO_DATE &&
+		     device->state.disk >= D_INCONSISTENT)) {
 			mask.disk = D_MASK;
 			val.disk  = D_UP_TO_DATE;
 			forced = 1;
@@ -571,10 +593,10 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 		}
 
 		if (rv == SS_NO_UP_TO_DATE_DISK &&
-		    mdev->state.disk == D_CONSISTENT && mask.pdsk == 0) {
-			D_ASSERT(mdev->state.pdsk == D_UNKNOWN);
+		    device->state.disk == D_CONSISTENT && mask.pdsk == 0) {
+			D_ASSERT(device, device->state.pdsk == D_UNKNOWN);
 
-			if (conn_try_outdate_peer(mdev->tconn)) {
+			if (conn_try_outdate_peer(first_peer_device(device)->connection)) {
 				val.disk = D_UP_TO_DATE;
 				mask.disk = D_MASK;
 			}
@@ -584,8 +606,8 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 		if (rv == SS_NOTHING_TO_DO)
 			goto out;
 		if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
-			if (!conn_try_outdate_peer(mdev->tconn) && force) {
-				dev_warn(DEV, "Forced into split brain situation!\n");
+			if (!conn_try_outdate_peer(first_peer_device(device)->connection) && force) {
+				drbd_warn(device, "Forced into split brain situation!\n");
 				mask.pdsk = D_MASK;
 				val.pdsk  = D_OUTDATED;
 
@@ -597,7 +619,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 			   retry at most once more in this case. */
 			int timeo;
 			rcu_read_lock();
-			nc = rcu_dereference(mdev->tconn->net_conf);
+			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 			timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
 			rcu_read_unlock();
 			schedule_timeout_interruptible(timeo);
@@ -606,7 +628,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 			continue;
 		}
 		if (rv < SS_SUCCESS) {
-			rv = _drbd_request_state(mdev, mask, val,
+			rv = _drbd_request_state(device, mask, val,
 						CS_VERBOSE + CS_WAIT_COMPLETE);
 			if (rv < SS_SUCCESS)
 				goto out;
@@ -618,53 +640,53 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 		goto out;
 
 	if (forced)
-		dev_warn(DEV, "Forced to consider local data as UpToDate!\n");
+		drbd_warn(device, "Forced to consider local data as UpToDate!\n");
 
 	/* Wait until nothing is on the fly :) */
-	wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0);
+	wait_event(device->misc_wait, atomic_read(&device->ap_pending_cnt) == 0);
 
 	/* FIXME also wait for all pending P_BARRIER_ACK? */
 
 	if (new_role == R_SECONDARY) {
-		set_disk_ro(mdev->vdisk, true);
-		if (get_ldev(mdev)) {
-			mdev->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
-			put_ldev(mdev);
+		set_disk_ro(device->vdisk, true);
+		if (get_ldev(device)) {
+			device->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
+			put_ldev(device);
 		}
 	} else {
-		mutex_lock(&mdev->tconn->conf_update);
-		nc = mdev->tconn->net_conf;
+		mutex_lock(&device->resource->conf_update);
+		nc = first_peer_device(device)->connection->net_conf;
 		if (nc)
 			nc->discard_my_data = 0; /* without copy; single bit op is atomic */
-		mutex_unlock(&mdev->tconn->conf_update);
+		mutex_unlock(&device->resource->conf_update);
 
-		set_disk_ro(mdev->vdisk, false);
-		if (get_ldev(mdev)) {
-			if (((mdev->state.conn < C_CONNECTED ||
-			       mdev->state.pdsk <= D_FAILED)
-			      && mdev->ldev->md.uuid[UI_BITMAP] == 0) || forced)
-				drbd_uuid_new_current(mdev);
+		set_disk_ro(device->vdisk, false);
+		if (get_ldev(device)) {
+			if (((device->state.conn < C_CONNECTED ||
+			       device->state.pdsk <= D_FAILED)
+			      && device->ldev->md.uuid[UI_BITMAP] == 0) || forced)
+				drbd_uuid_new_current(device);
 
-			mdev->ldev->md.uuid[UI_CURRENT] |=  (u64)1;
-			put_ldev(mdev);
+			device->ldev->md.uuid[UI_CURRENT] |=  (u64)1;
+			put_ldev(device);
 		}
 	}
 
 	/* writeout of activity log covered areas of the bitmap
 	 * to stable storage done in after state change already */
 
-	if (mdev->state.conn >= C_WF_REPORT_PARAMS) {
+	if (device->state.conn >= C_WF_REPORT_PARAMS) {
 		/* if this was forced, we should consider sync */
 		if (forced)
-			drbd_send_uuids(mdev);
-		drbd_send_current_state(mdev);
+			drbd_send_uuids(first_peer_device(device));
+		drbd_send_current_state(first_peer_device(device));
 	}
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
-	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
+	kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
 out:
-	mutex_unlock(mdev->state_mutex);
+	mutex_unlock(device->state_mutex);
 	return rv;
 }
 
@@ -699,9 +721,9 @@ int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	if (info->genlhdr->cmd == DRBD_ADM_PRIMARY)
-		retcode = drbd_set_role(adm_ctx.mdev, R_PRIMARY, parms.assume_uptodate);
+		retcode = drbd_set_role(adm_ctx.device, R_PRIMARY, parms.assume_uptodate);
 	else
-		retcode = drbd_set_role(adm_ctx.mdev, R_SECONDARY, 0);
+		retcode = drbd_set_role(adm_ctx.device, R_SECONDARY, 0);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -728,7 +750,7 @@ out:
  *  Activity log size used to be fixed 32kB,
  *  but is about to become configurable.
  */
-static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
+static void drbd_md_set_sector_offsets(struct drbd_device *device,
 				       struct drbd_backing_dev *bdev)
 {
 	sector_t md_size_sect = 0;
@@ -804,35 +826,35 @@ char *ppsize(char *buf, unsigned long long size)
  * drbd_adm_suspend_io/drbd_adm_resume_io,
  * which are (sub) state changes triggered by admin (drbdsetup),
  * and can be long lived.
- * This changes an mdev->flag, is triggered by drbd internals,
+ * This changes an device->flag, is triggered by drbd internals,
  * and should be short-lived. */
-void drbd_suspend_io(struct drbd_conf *mdev)
+void drbd_suspend_io(struct drbd_device *device)
 {
-	set_bit(SUSPEND_IO, &mdev->flags);
-	if (drbd_suspended(mdev))
+	set_bit(SUSPEND_IO, &device->flags);
+	if (drbd_suspended(device))
 		return;
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
+	wait_event(device->misc_wait, !atomic_read(&device->ap_bio_cnt));
 }
 
-void drbd_resume_io(struct drbd_conf *mdev)
+void drbd_resume_io(struct drbd_device *device)
 {
-	clear_bit(SUSPEND_IO, &mdev->flags);
-	wake_up(&mdev->misc_wait);
+	clear_bit(SUSPEND_IO, &device->flags);
+	wake_up(&device->misc_wait);
 }
 
 /**
  * drbd_determine_dev_size() -  Sets the right device size obeying all constraints
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Returns 0 on success, negative return values indicate errors.
  * You should call drbd_md_sync() after calling this function.
  */
 enum determine_dev_size
-drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct resize_parms *rs) __must_hold(local)
+drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct resize_parms *rs) __must_hold(local)
 {
 	sector_t prev_first_sect, prev_size; /* previous meta location */
 	sector_t la_size_sect, u_size;
-	struct drbd_md *md = &mdev->ldev->md;
+	struct drbd_md *md = &device->ldev->md;
 	u32 prev_al_stripe_size_4k;
 	u32 prev_al_stripes;
 	sector_t size;
@@ -851,19 +873,19 @@ drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct res
 	 * Suspend IO right here.
 	 * still lock the act_log to not trigger ASSERTs there.
 	 */
-	drbd_suspend_io(mdev);
-	buffer = drbd_md_get_buffer(mdev); /* Lock meta-data IO */
+	drbd_suspend_io(device);
+	buffer = drbd_md_get_buffer(device); /* Lock meta-data IO */
 	if (!buffer) {
-		drbd_resume_io(mdev);
+		drbd_resume_io(device);
 		return DS_ERROR;
 	}
 
 	/* no wait necessary anymore, actually we could assert that */
-	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
+	wait_event(device->al_wait, lc_try_lock(device->act_log));
 
-	prev_first_sect = drbd_md_first_sector(mdev->ldev);
-	prev_size = mdev->ldev->md.md_size_sect;
-	la_size_sect = mdev->ldev->md.la_size_sect;
+	prev_first_sect = drbd_md_first_sector(device->ldev);
+	prev_size = device->ldev->md.md_size_sect;
+	la_size_sect = device->ldev->md.la_size_sect;
 
 	if (rs) {
 		/* rs is non NULL if we should change the AL layout only */
@@ -876,18 +898,18 @@ drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct res
 		md->al_size_4k = (u64)rs->al_stripes * rs->al_stripe_size / 4;
 	}
 
-	drbd_md_set_sector_offsets(mdev, mdev->ldev);
+	drbd_md_set_sector_offsets(device, device->ldev);
 
 	rcu_read_lock();
-	u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+	u_size = rcu_dereference(device->ldev->disk_conf)->disk_size;
 	rcu_read_unlock();
-	size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED);
+	size = drbd_new_dev_size(device, device->ldev, u_size, flags & DDSF_FORCED);
 
 	if (size < la_size_sect) {
 		if (rs && u_size == 0) {
 			/* Remove "rs &&" later. This check should always be active, but
 			   right now the receiver expects the permissive behavior */
-			dev_warn(DEV, "Implicit shrink not allowed. "
+			drbd_warn(device, "Implicit shrink not allowed. "
 				 "Use --size=%llus for explicit shrink.\n",
 				 (unsigned long long)size);
 			rv = DS_ERROR_SHRINK;
@@ -898,60 +920,60 @@ drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct res
 			goto err_out;
 	}
 
-	if (drbd_get_capacity(mdev->this_bdev) != size ||
-	    drbd_bm_capacity(mdev) != size) {
+	if (drbd_get_capacity(device->this_bdev) != size ||
+	    drbd_bm_capacity(device) != size) {
 		int err;
-		err = drbd_bm_resize(mdev, size, !(flags & DDSF_NO_RESYNC));
+		err = drbd_bm_resize(device, size, !(flags & DDSF_NO_RESYNC));
 		if (unlikely(err)) {
 			/* currently there is only one error: ENOMEM! */
-			size = drbd_bm_capacity(mdev)>>1;
+			size = drbd_bm_capacity(device)>>1;
 			if (size == 0) {
-				dev_err(DEV, "OUT OF MEMORY! "
+				drbd_err(device, "OUT OF MEMORY! "
 				    "Could not allocate bitmap!\n");
 			} else {
-				dev_err(DEV, "BM resizing failed. "
+				drbd_err(device, "BM resizing failed. "
 				    "Leaving size unchanged at size = %lu KB\n",
 				    (unsigned long)size);
 			}
 			rv = DS_ERROR;
 		}
 		/* racy, see comments above. */
-		drbd_set_my_capacity(mdev, size);
-		mdev->ldev->md.la_size_sect = size;
-		dev_info(DEV, "size = %s (%llu KB)\n", ppsize(ppb, size>>1),
+		drbd_set_my_capacity(device, size);
+		device->ldev->md.la_size_sect = size;
+		drbd_info(device, "size = %s (%llu KB)\n", ppsize(ppb, size>>1),
 		     (unsigned long long)size>>1);
 	}
 	if (rv <= DS_ERROR)
 		goto err_out;
 
-	la_size_changed = (la_size_sect != mdev->ldev->md.la_size_sect);
+	la_size_changed = (la_size_sect != device->ldev->md.la_size_sect);
 
-	md_moved = prev_first_sect != drbd_md_first_sector(mdev->ldev)
-		|| prev_size	   != mdev->ldev->md.md_size_sect;
+	md_moved = prev_first_sect != drbd_md_first_sector(device->ldev)
+		|| prev_size	   != device->ldev->md.md_size_sect;
 
 	if (la_size_changed || md_moved || rs) {
 		u32 prev_flags;
 
-		drbd_al_shrink(mdev); /* All extents inactive. */
+		drbd_al_shrink(device); /* All extents inactive. */
 
 		prev_flags = md->flags;
 		md->flags &= ~MDF_PRIMARY_IND;
-		drbd_md_write(mdev, buffer);
+		drbd_md_write(device, buffer);
 
-		dev_info(DEV, "Writing the whole bitmap, %s\n",
+		drbd_info(device, "Writing the whole bitmap, %s\n",
 			 la_size_changed && md_moved ? "size changed and md moved" :
 			 la_size_changed ? "size changed" : "md moved");
 		/* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
-		drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write,
+		drbd_bitmap_io(device, md_moved ? &drbd_bm_write_all : &drbd_bm_write,
 			       "size changed", BM_LOCKED_MASK);
-		drbd_initialize_al(mdev, buffer);
+		drbd_initialize_al(device, buffer);
 
 		md->flags = prev_flags;
-		drbd_md_write(mdev, buffer);
+		drbd_md_write(device, buffer);
 
 		if (rs)
-			dev_info(DEV, "Changed AL layout to al-stripes = %d, al-stripe-size-kB = %d\n",
-				 md->al_stripes, md->al_stripe_size_4k * 4);
+			drbd_info(device, "Changed AL layout to al-stripes = %d, al-stripe-size-kB = %d\n",
+				  md->al_stripes, md->al_stripe_size_4k * 4);
 	}
 
 	if (size > la_size_sect)
@@ -966,30 +988,30 @@ drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct res
 			md->al_stripe_size_4k = prev_al_stripe_size_4k;
 			md->al_size_4k = (u64)prev_al_stripes * prev_al_stripe_size_4k;
 
-			drbd_md_set_sector_offsets(mdev, mdev->ldev);
+			drbd_md_set_sector_offsets(device, device->ldev);
 		}
 	}
-	lc_unlock(mdev->act_log);
-	wake_up(&mdev->al_wait);
-	drbd_md_put_buffer(mdev);
-	drbd_resume_io(mdev);
+	lc_unlock(device->act_log);
+	wake_up(&device->al_wait);
+	drbd_md_put_buffer(device);
+	drbd_resume_io(device);
 
 	return rv;
 }
 
 sector_t
-drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
+drbd_new_dev_size(struct drbd_device *device, struct drbd_backing_dev *bdev,
 		  sector_t u_size, int assume_peer_has_space)
 {
-	sector_t p_size = mdev->p_size;   /* partner's disk size. */
+	sector_t p_size = device->p_size;   /* partner's disk size. */
 	sector_t la_size_sect = bdev->md.la_size_sect; /* last agreed size. */
 	sector_t m_size; /* my size */
 	sector_t size = 0;
 
 	m_size = drbd_get_max_capacity(bdev);
 
-	if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) {
-		dev_warn(DEV, "Resize while not connected was forced by the user!\n");
+	if (device->state.conn < C_CONNECTED && assume_peer_has_space) {
+		drbd_warn(device, "Resize while not connected was forced by the user!\n");
 		p_size = m_size;
 	}
 
@@ -1011,11 +1033,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 	}
 
 	if (size == 0)
-		dev_err(DEV, "Both nodes diskless!\n");
+		drbd_err(device, "Both nodes diskless!\n");
 
 	if (u_size) {
 		if (u_size > size)
-			dev_err(DEV, "Requested disk size is too big (%lu > %lu)\n",
+			drbd_err(device, "Requested disk size is too big (%lu > %lu)\n",
 			    (unsigned long)u_size>>1, (unsigned long)size>>1);
 		else
 			size = u_size;
@@ -1026,71 +1048,71 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 
 /**
  * drbd_check_al_size() - Ensures that the AL is of the right size
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Returns -EBUSY if current al lru is still used, -ENOMEM when allocation
  * failed, and 0 on success. You should call drbd_md_sync() after you called
  * this function.
  */
-static int drbd_check_al_size(struct drbd_conf *mdev, struct disk_conf *dc)
+static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
 {
 	struct lru_cache *n, *t;
 	struct lc_element *e;
 	unsigned int in_use;
 	int i;
 
-	if (mdev->act_log &&
-	    mdev->act_log->nr_elements == dc->al_extents)
+	if (device->act_log &&
+	    device->act_log->nr_elements == dc->al_extents)
 		return 0;
 
 	in_use = 0;
-	t = mdev->act_log;
+	t = device->act_log;
 	n = lc_create("act_log", drbd_al_ext_cache, AL_UPDATES_PER_TRANSACTION,
 		dc->al_extents, sizeof(struct lc_element), 0);
 
 	if (n == NULL) {
-		dev_err(DEV, "Cannot allocate act_log lru!\n");
+		drbd_err(device, "Cannot allocate act_log lru!\n");
 		return -ENOMEM;
 	}
-	spin_lock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
 	if (t) {
 		for (i = 0; i < t->nr_elements; i++) {
 			e = lc_element_by_index(t, i);
 			if (e->refcnt)
-				dev_err(DEV, "refcnt(%d)==%d\n",
+				drbd_err(device, "refcnt(%d)==%d\n",
 				    e->lc_number, e->refcnt);
 			in_use += e->refcnt;
 		}
 	}
 	if (!in_use)
-		mdev->act_log = n;
-	spin_unlock_irq(&mdev->al_lock);
+		device->act_log = n;
+	spin_unlock_irq(&device->al_lock);
 	if (in_use) {
-		dev_err(DEV, "Activity log still in use!\n");
+		drbd_err(device, "Activity log still in use!\n");
 		lc_destroy(n);
 		return -EBUSY;
 	} else {
 		if (t)
 			lc_destroy(t);
 	}
-	drbd_md_mark_dirty(mdev); /* we changed mdev->act_log->nr_elemens */
+	drbd_md_mark_dirty(device); /* we changed device->act_log->nr_elemens */
 	return 0;
 }
 
-static void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size)
+static void drbd_setup_queue_param(struct drbd_device *device, unsigned int max_bio_size)
 {
-	struct request_queue * const q = mdev->rq_queue;
+	struct request_queue * const q = device->rq_queue;
 	unsigned int max_hw_sectors = max_bio_size >> 9;
 	unsigned int max_segments = 0;
 
-	if (get_ldev_if_state(mdev, D_ATTACHING)) {
-		struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
+	if (get_ldev_if_state(device, D_ATTACHING)) {
+		struct request_queue * const b = device->ldev->backing_bdev->bd_disk->queue;
 
 		max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
 		rcu_read_lock();
-		max_segments = rcu_dereference(mdev->ldev->disk_conf)->max_bio_bvecs;
+		max_segments = rcu_dereference(device->ldev->disk_conf)->max_bio_bvecs;
 		rcu_read_unlock();
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	blk_queue_logical_block_size(q, 512);
@@ -1099,46 +1121,46 @@ static void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_
 	blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
 	blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1);
 
-	if (get_ldev_if_state(mdev, D_ATTACHING)) {
-		struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
+	if (get_ldev_if_state(device, D_ATTACHING)) {
+		struct request_queue * const b = device->ldev->backing_bdev->bd_disk->queue;
 
 		blk_queue_stack_limits(q, b);
 
 		if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
-			dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
+			drbd_info(device, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
 				 q->backing_dev_info.ra_pages,
 				 b->backing_dev_info.ra_pages);
 			q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 }
 
-void drbd_reconsider_max_bio_size(struct drbd_conf *mdev)
+void drbd_reconsider_max_bio_size(struct drbd_device *device)
 {
 	unsigned int now, new, local, peer;
 
-	now = queue_max_hw_sectors(mdev->rq_queue) << 9;
-	local = mdev->local_max_bio_size; /* Eventually last known value, from volatile memory */
-	peer = mdev->peer_max_bio_size; /* Eventually last known value, from meta data */
+	now = queue_max_hw_sectors(device->rq_queue) << 9;
+	local = device->local_max_bio_size; /* Eventually last known value, from volatile memory */
+	peer = device->peer_max_bio_size; /* Eventually last known value, from meta data */
 
-	if (get_ldev_if_state(mdev, D_ATTACHING)) {
-		local = queue_max_hw_sectors(mdev->ldev->backing_bdev->bd_disk->queue) << 9;
-		mdev->local_max_bio_size = local;
-		put_ldev(mdev);
+	if (get_ldev_if_state(device, D_ATTACHING)) {
+		local = queue_max_hw_sectors(device->ldev->backing_bdev->bd_disk->queue) << 9;
+		device->local_max_bio_size = local;
+		put_ldev(device);
 	}
 	local = min(local, DRBD_MAX_BIO_SIZE);
 
 	/* We may ignore peer limits if the peer is modern enough.
 	   Because new from 8.3.8 onwards the peer can use multiple
 	   BIOs for a single peer_request */
-	if (mdev->state.conn >= C_WF_REPORT_PARAMS) {
-		if (mdev->tconn->agreed_pro_version < 94)
-			peer = min(mdev->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+	if (device->state.conn >= C_WF_REPORT_PARAMS) {
+		if (first_peer_device(device)->connection->agreed_pro_version < 94)
+			peer = min(device->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
 			/* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */
-		else if (mdev->tconn->agreed_pro_version == 94)
+		else if (first_peer_device(device)->connection->agreed_pro_version == 94)
 			peer = DRBD_MAX_SIZE_H80_PACKET;
-		else if (mdev->tconn->agreed_pro_version < 100)
+		else if (first_peer_device(device)->connection->agreed_pro_version < 100)
 			peer = DRBD_MAX_BIO_SIZE_P95;  /* drbd 8.3.8 onwards, before 8.4.0 */
 		else
 			peer = DRBD_MAX_BIO_SIZE;
@@ -1146,57 +1168,57 @@ void drbd_reconsider_max_bio_size(struct drbd_conf *mdev)
 
 	new = min(local, peer);
 
-	if (mdev->state.role == R_PRIMARY && new < now)
-		dev_err(DEV, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
+	if (device->state.role == R_PRIMARY && new < now)
+		drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
 
 	if (new != now)
-		dev_info(DEV, "max BIO size = %u\n", new);
+		drbd_info(device, "max BIO size = %u\n", new);
 
-	drbd_setup_queue_param(mdev, new);
+	drbd_setup_queue_param(device, new);
 }
 
 /* Starts the worker thread */
-static void conn_reconfig_start(struct drbd_tconn *tconn)
+static void conn_reconfig_start(struct drbd_connection *connection)
 {
-	drbd_thread_start(&tconn->worker);
-	conn_flush_workqueue(tconn);
+	drbd_thread_start(&connection->worker);
+	drbd_flush_workqueue(&connection->sender_work);
 }
 
 /* if still unconfigured, stops worker again. */
-static void conn_reconfig_done(struct drbd_tconn *tconn)
+static void conn_reconfig_done(struct drbd_connection *connection)
 {
 	bool stop_threads;
-	spin_lock_irq(&tconn->req_lock);
-	stop_threads = conn_all_vols_unconf(tconn) &&
-		tconn->cstate == C_STANDALONE;
-	spin_unlock_irq(&tconn->req_lock);
+	spin_lock_irq(&connection->resource->req_lock);
+	stop_threads = conn_all_vols_unconf(connection) &&
+		connection->cstate == C_STANDALONE;
+	spin_unlock_irq(&connection->resource->req_lock);
 	if (stop_threads) {
 		/* asender is implicitly stopped by receiver
 		 * in conn_disconnect() */
-		drbd_thread_stop(&tconn->receiver);
-		drbd_thread_stop(&tconn->worker);
+		drbd_thread_stop(&connection->receiver);
+		drbd_thread_stop(&connection->worker);
 	}
 }
 
 /* Make sure IO is suspended before calling this function(). */
-static void drbd_suspend_al(struct drbd_conf *mdev)
+static void drbd_suspend_al(struct drbd_device *device)
 {
 	int s = 0;
 
-	if (!lc_try_lock(mdev->act_log)) {
-		dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
+	if (!lc_try_lock(device->act_log)) {
+		drbd_warn(device, "Failed to lock al in drbd_suspend_al()\n");
 		return;
 	}
 
-	drbd_al_shrink(mdev);
-	spin_lock_irq(&mdev->tconn->req_lock);
-	if (mdev->state.conn < C_CONNECTED)
-		s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags);
-	spin_unlock_irq(&mdev->tconn->req_lock);
-	lc_unlock(mdev->act_log);
+	drbd_al_shrink(device);
+	spin_lock_irq(&device->resource->req_lock);
+	if (device->state.conn < C_CONNECTED)
+		s = !test_and_set_bit(AL_SUSPENDED, &device->flags);
+	spin_unlock_irq(&device->resource->req_lock);
+	lc_unlock(device->act_log);
 
 	if (s)
-		dev_info(DEV, "Suspended AL updates\n");
+		drbd_info(device, "Suspended AL updates\n");
 }
 
 
@@ -1237,7 +1259,7 @@ static unsigned int drbd_al_extents_max(struct drbd_backing_dev *bdev)
 int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 {
 	enum drbd_ret_code retcode;
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	struct disk_conf *new_disk_conf, *old_disk_conf;
 	struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
 	int err, fifo_size;
@@ -1248,11 +1270,11 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mdev = adm_ctx.mdev;
+	device = adm_ctx.device;
 
 	/* we also need a disk
 	 * to change the options on */
-	if (!get_ldev(mdev)) {
+	if (!get_ldev(device)) {
 		retcode = ERR_NO_DISK;
 		goto out;
 	}
@@ -1263,8 +1285,8 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
-	mutex_lock(&mdev->tconn->conf_update);
-	old_disk_conf = mdev->ldev->disk_conf;
+	mutex_lock(&device->resource->conf_update);
+	old_disk_conf = device->ldev->disk_conf;
 	*new_disk_conf = *old_disk_conf;
 	if (should_set_defaults(info))
 		set_disk_conf_defaults(new_disk_conf);
@@ -1273,6 +1295,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 	if (err && err != -ENOMSG) {
 		retcode = ERR_MANDATORY_TAG;
 		drbd_msg_put_info(from_attrs_err_to_txt(err));
+		goto fail_unlock;
 	}
 
 	if (!expect(new_disk_conf->resync_rate >= 1))
@@ -1280,29 +1303,29 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 
 	if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN)
 		new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN;
-	if (new_disk_conf->al_extents > drbd_al_extents_max(mdev->ldev))
-		new_disk_conf->al_extents = drbd_al_extents_max(mdev->ldev);
+	if (new_disk_conf->al_extents > drbd_al_extents_max(device->ldev))
+		new_disk_conf->al_extents = drbd_al_extents_max(device->ldev);
 
 	if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
 		new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
 
 	fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
-	if (fifo_size != mdev->rs_plan_s->size) {
+	if (fifo_size != device->rs_plan_s->size) {
 		new_plan = fifo_alloc(fifo_size);
 		if (!new_plan) {
-			dev_err(DEV, "kmalloc of fifo_buffer failed");
+			drbd_err(device, "kmalloc of fifo_buffer failed");
 			retcode = ERR_NOMEM;
 			goto fail_unlock;
 		}
 	}
 
-	drbd_suspend_io(mdev);
-	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-	drbd_al_shrink(mdev);
-	err = drbd_check_al_size(mdev, new_disk_conf);
-	lc_unlock(mdev->act_log);
-	wake_up(&mdev->al_wait);
-	drbd_resume_io(mdev);
+	drbd_suspend_io(device);
+	wait_event(device->al_wait, lc_try_lock(device->act_log));
+	drbd_al_shrink(device);
+	err = drbd_check_al_size(device, new_disk_conf);
+	lc_unlock(device->act_log);
+	wake_up(&device->al_wait);
+	drbd_resume_io(device);
 
 	if (err) {
 		retcode = ERR_NOMEM;
@@ -1310,10 +1333,10 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	write_lock_irq(&global_state_lock);
-	retcode = drbd_resync_after_valid(mdev, new_disk_conf->resync_after);
+	retcode = drbd_resync_after_valid(device, new_disk_conf->resync_after);
 	if (retcode == NO_ERROR) {
-		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
-		drbd_resync_after_changed(mdev);
+		rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
+		drbd_resync_after_changed(device);
 	}
 	write_unlock_irq(&global_state_lock);
 
@@ -1321,42 +1344,46 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 		goto fail_unlock;
 
 	if (new_plan) {
-		old_plan = mdev->rs_plan_s;
-		rcu_assign_pointer(mdev->rs_plan_s, new_plan);
+		old_plan = device->rs_plan_s;
+		rcu_assign_pointer(device->rs_plan_s, new_plan);
 	}
 
-	mutex_unlock(&mdev->tconn->conf_update);
+	mutex_unlock(&device->resource->conf_update);
 
 	if (new_disk_conf->al_updates)
-		mdev->ldev->md.flags &= ~MDF_AL_DISABLED;
+		device->ldev->md.flags &= ~MDF_AL_DISABLED;
 	else
-		mdev->ldev->md.flags |= MDF_AL_DISABLED;
+		device->ldev->md.flags |= MDF_AL_DISABLED;
 
 	if (new_disk_conf->md_flushes)
-		clear_bit(MD_NO_FUA, &mdev->flags);
+		clear_bit(MD_NO_FUA, &device->flags);
 	else
-		set_bit(MD_NO_FUA, &mdev->flags);
+		set_bit(MD_NO_FUA, &device->flags);
 
-	drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
+	drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
-	if (mdev->state.conn >= C_CONNECTED)
-		drbd_send_sync_param(mdev);
+	if (device->state.conn >= C_CONNECTED) {
+		struct drbd_peer_device *peer_device;
+
+		for_each_peer_device(peer_device, device)
+			drbd_send_sync_param(peer_device);
+	}
 
 	synchronize_rcu();
 	kfree(old_disk_conf);
 	kfree(old_plan);
-	mod_timer(&mdev->request_timer, jiffies + HZ);
+	mod_timer(&device->request_timer, jiffies + HZ);
 	goto success;
 
 fail_unlock:
-	mutex_unlock(&mdev->tconn->conf_update);
+	mutex_unlock(&device->resource->conf_update);
  fail:
 	kfree(new_disk_conf);
 	kfree(new_plan);
 success:
-	put_ldev(mdev);
+	put_ldev(device);
  out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -1364,7 +1391,7 @@ success:
 
 int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	int err;
 	enum drbd_ret_code retcode;
 	enum determine_dev_size dd;
@@ -1385,11 +1412,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto finish;
 
-	mdev = adm_ctx.mdev;
-	conn_reconfig_start(mdev->tconn);
+	device = adm_ctx.device;
+	conn_reconfig_start(first_peer_device(device)->connection);
 
 	/* if you want to reconfigure, please tear down first */
-	if (mdev->state.disk > D_DISKLESS) {
+	if (device->state.disk > D_DISKLESS) {
 		retcode = ERR_DISK_CONFIGURED;
 		goto fail;
 	}
@@ -1397,17 +1424,17 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	 * drbd_ldev_destroy is done already, we may end up here very fast,
 	 * e.g. if someone calls attach from the on-io-error handler,
 	 * to realize a "hot spare" feature (not that I'd recommend that) */
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
+	wait_event(device->misc_wait, !atomic_read(&device->local_cnt));
 
 	/* make sure there is no leftover from previous force-detach attempts */
-	clear_bit(FORCE_DETACH, &mdev->flags);
-	clear_bit(WAS_IO_ERROR, &mdev->flags);
-	clear_bit(WAS_READ_ERROR, &mdev->flags);
+	clear_bit(FORCE_DETACH, &device->flags);
+	clear_bit(WAS_IO_ERROR, &device->flags);
+	clear_bit(WAS_READ_ERROR, &device->flags);
 
 	/* and no leftover from previously aborted resync or verify, either */
-	mdev->rs_total = 0;
-	mdev->rs_failed = 0;
-	atomic_set(&mdev->rs_pending_cnt, 0);
+	device->rs_total = 0;
+	device->rs_failed = 0;
+	atomic_set(&device->rs_pending_cnt, 0);
 
 	/* allocation not in the IO path, drbdsetup context */
 	nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL);
@@ -1447,13 +1474,13 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	write_lock_irq(&global_state_lock);
-	retcode = drbd_resync_after_valid(mdev, new_disk_conf->resync_after);
+	retcode = drbd_resync_after_valid(device, new_disk_conf->resync_after);
 	write_unlock_irq(&global_state_lock);
 	if (retcode != NO_ERROR)
 		goto fail;
 
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 	if (nc) {
 		if (new_disk_conf->fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) {
 			rcu_read_unlock();
@@ -1464,9 +1491,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	rcu_read_unlock();
 
 	bdev = blkdev_get_by_path(new_disk_conf->backing_dev,
-				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev);
+				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, device);
 	if (IS_ERR(bdev)) {
-		dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
+		drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
 			PTR_ERR(bdev));
 		retcode = ERR_OPEN_DISK;
 		goto fail;
@@ -1484,9 +1511,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	bdev = blkdev_get_by_path(new_disk_conf->meta_dev,
 				  FMODE_READ | FMODE_WRITE | FMODE_EXCL,
 				  (new_disk_conf->meta_dev_idx < 0) ?
-				  (void *)mdev : (void *)drbd_m_holder);
+				  (void *)device : (void *)drbd_m_holder);
 	if (IS_ERR(bdev)) {
-		dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
+		drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
 			PTR_ERR(bdev));
 		retcode = ERR_OPEN_MD_DISK;
 		goto fail;
@@ -1510,7 +1537,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 
 	/* Read our meta data super block early.
 	 * This also sets other on-disk offsets. */
-	retcode = drbd_md_read(mdev, nbc);
+	retcode = drbd_md_read(device, nbc);
 	if (retcode != NO_ERROR)
 		goto fail;
 
@@ -1520,7 +1547,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		new_disk_conf->al_extents = drbd_al_extents_max(nbc);
 
 	if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) {
-		dev_err(DEV, "max capacity %llu smaller than disk size %llu\n",
+		drbd_err(device, "max capacity %llu smaller than disk size %llu\n",
 			(unsigned long long) drbd_get_max_capacity(nbc),
 			(unsigned long long) new_disk_conf->disk_size);
 		retcode = ERR_DISK_TOO_SMALL;
@@ -1538,7 +1565,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 
 	if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) {
 		retcode = ERR_MD_DISK_TOO_SMALL;
-		dev_warn(DEV, "refusing attach: md-device too small, "
+		drbd_warn(device, "refusing attach: md-device too small, "
 		     "at least %llu sectors needed for this meta-disk type\n",
 		     (unsigned long long) min_md_device_sectors);
 		goto fail;
@@ -1547,7 +1574,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	/* Make sure the new disk is big enough
 	 * (we may currently be R_PRIMARY with no local disk...) */
 	if (drbd_get_max_capacity(nbc) <
-	    drbd_get_capacity(mdev->this_bdev)) {
+	    drbd_get_capacity(device->this_bdev)) {
 		retcode = ERR_DISK_TOO_SMALL;
 		goto fail;
 	}
@@ -1555,15 +1582,15 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
 
 	if (nbc->known_size > max_possible_sectors) {
-		dev_warn(DEV, "==> truncating very big lower level device "
+		drbd_warn(device, "==> truncating very big lower level device "
 			"to currently maximum possible %llu sectors <==\n",
 			(unsigned long long) max_possible_sectors);
 		if (new_disk_conf->meta_dev_idx >= 0)
-			dev_warn(DEV, "==>> using internal or flexible "
+			drbd_warn(device, "==>> using internal or flexible "
 				      "meta data may help <<==\n");
 	}
 
-	drbd_suspend_io(mdev);
+	drbd_suspend_io(device);
 	/* also wait for the last barrier ack. */
 	/* FIXME see also https://daiquiri.linbit/cgi-bin/bugzilla/show_bug.cgi?id=171
 	 * We need a way to either ignore barrier acks for barriers sent before a device
@@ -1571,45 +1598,45 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	 * As barriers are counted per resource,
 	 * we'd need to suspend io on all devices of a resource.
 	 */
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || drbd_suspended(mdev));
+	wait_event(device->misc_wait, !atomic_read(&device->ap_pending_cnt) || drbd_suspended(device));
 	/* and for any other previously queued work */
-	drbd_flush_workqueue(mdev);
+	drbd_flush_workqueue(&first_peer_device(device)->connection->sender_work);
 
-	rv = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
+	rv = _drbd_request_state(device, NS(disk, D_ATTACHING), CS_VERBOSE);
 	retcode = rv;  /* FIXME: Type mismatch. */
-	drbd_resume_io(mdev);
+	drbd_resume_io(device);
 	if (rv < SS_SUCCESS)
 		goto fail;
 
-	if (!get_ldev_if_state(mdev, D_ATTACHING))
+	if (!get_ldev_if_state(device, D_ATTACHING))
 		goto force_diskless;
 
-	if (!mdev->bitmap) {
-		if (drbd_bm_init(mdev)) {
+	if (!device->bitmap) {
+		if (drbd_bm_init(device)) {
 			retcode = ERR_NOMEM;
 			goto force_diskless_dec;
 		}
 	}
 
-	if (mdev->state.conn < C_CONNECTED &&
-	    mdev->state.role == R_PRIMARY &&
-	    (mdev->ed_uuid & ~((u64)1)) != (nbc->md.uuid[UI_CURRENT] & ~((u64)1))) {
-		dev_err(DEV, "Can only attach to data with current UUID=%016llX\n",
-		    (unsigned long long)mdev->ed_uuid);
+	if (device->state.conn < C_CONNECTED &&
+	    device->state.role == R_PRIMARY &&
+	    (device->ed_uuid & ~((u64)1)) != (nbc->md.uuid[UI_CURRENT] & ~((u64)1))) {
+		drbd_err(device, "Can only attach to data with current UUID=%016llX\n",
+		    (unsigned long long)device->ed_uuid);
 		retcode = ERR_DATA_NOT_CURRENT;
 		goto force_diskless_dec;
 	}
 
 	/* Since we are diskless, fix the activity log first... */
-	if (drbd_check_al_size(mdev, new_disk_conf)) {
+	if (drbd_check_al_size(device, new_disk_conf)) {
 		retcode = ERR_NOMEM;
 		goto force_diskless_dec;
 	}
 
 	/* Prevent shrinking of consistent devices ! */
 	if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
-	    drbd_new_dev_size(mdev, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) {
-		dev_warn(DEV, "refusing to truncate a consistent device\n");
+	    drbd_new_dev_size(device, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) {
+		drbd_warn(device, "refusing to truncate a consistent device\n");
 		retcode = ERR_DISK_TOO_SMALL;
 		goto force_diskless_dec;
 	}
@@ -1617,40 +1644,40 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	/* Reset the "barriers don't work" bits here, then force meta data to
 	 * be written, to ensure we determine if barriers are supported. */
 	if (new_disk_conf->md_flushes)
-		clear_bit(MD_NO_FUA, &mdev->flags);
+		clear_bit(MD_NO_FUA, &device->flags);
 	else
-		set_bit(MD_NO_FUA, &mdev->flags);
+		set_bit(MD_NO_FUA, &device->flags);
 
 	/* Point of no return reached.
 	 * Devices and memory are no longer released by error cleanup below.
-	 * now mdev takes over responsibility, and the state engine should
+	 * now device takes over responsibility, and the state engine should
 	 * clean it up somewhere.  */
-	D_ASSERT(mdev->ldev == NULL);
-	mdev->ldev = nbc;
-	mdev->resync = resync_lru;
-	mdev->rs_plan_s = new_plan;
+	D_ASSERT(device, device->ldev == NULL);
+	device->ldev = nbc;
+	device->resync = resync_lru;
+	device->rs_plan_s = new_plan;
 	nbc = NULL;
 	resync_lru = NULL;
 	new_disk_conf = NULL;
 	new_plan = NULL;
 
-	drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
+	drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY))
-		set_bit(CRASHED_PRIMARY, &mdev->flags);
+	if (drbd_md_test_flag(device->ldev, MDF_CRASHED_PRIMARY))
+		set_bit(CRASHED_PRIMARY, &device->flags);
 	else
-		clear_bit(CRASHED_PRIMARY, &mdev->flags);
+		clear_bit(CRASHED_PRIMARY, &device->flags);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
-	    !(mdev->state.role == R_PRIMARY && mdev->tconn->susp_nod))
-		set_bit(CRASHED_PRIMARY, &mdev->flags);
+	if (drbd_md_test_flag(device->ldev, MDF_PRIMARY_IND) &&
+	    !(device->state.role == R_PRIMARY && device->resource->susp_nod))
+		set_bit(CRASHED_PRIMARY, &device->flags);
 
-	mdev->send_cnt = 0;
-	mdev->recv_cnt = 0;
-	mdev->read_cnt = 0;
-	mdev->writ_cnt = 0;
+	device->send_cnt = 0;
+	device->recv_cnt = 0;
+	device->read_cnt = 0;
+	device->writ_cnt = 0;
 
-	drbd_reconsider_max_bio_size(mdev);
+	drbd_reconsider_max_bio_size(device);
 
 	/* If I am currently not R_PRIMARY,
 	 * but meta data primary indicator is set,
@@ -1666,50 +1693,50 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	 * so we can automatically recover from a crash of a
 	 * degraded but active "cluster" after a certain timeout.
 	 */
-	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
-	if (mdev->state.role != R_PRIMARY &&
-	     drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
-	    !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND))
-		set_bit(USE_DEGR_WFC_T, &mdev->flags);
+	clear_bit(USE_DEGR_WFC_T, &device->flags);
+	if (device->state.role != R_PRIMARY &&
+	     drbd_md_test_flag(device->ldev, MDF_PRIMARY_IND) &&
+	    !drbd_md_test_flag(device->ldev, MDF_CONNECTED_IND))
+		set_bit(USE_DEGR_WFC_T, &device->flags);
 
-	dd = drbd_determine_dev_size(mdev, 0, NULL);
+	dd = drbd_determine_dev_size(device, 0, NULL);
 	if (dd <= DS_ERROR) {
 		retcode = ERR_NOMEM_BITMAP;
 		goto force_diskless_dec;
 	} else if (dd == DS_GREW)
-		set_bit(RESYNC_AFTER_NEG, &mdev->flags);
+		set_bit(RESYNC_AFTER_NEG, &device->flags);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC) ||
-	    (test_bit(CRASHED_PRIMARY, &mdev->flags) &&
-	     drbd_md_test_flag(mdev->ldev, MDF_AL_DISABLED))) {
-		dev_info(DEV, "Assuming that all blocks are out of sync "
+	if (drbd_md_test_flag(device->ldev, MDF_FULL_SYNC) ||
+	    (test_bit(CRASHED_PRIMARY, &device->flags) &&
+	     drbd_md_test_flag(device->ldev, MDF_AL_DISABLED))) {
+		drbd_info(device, "Assuming that all blocks are out of sync "
 		     "(aka FullSync)\n");
-		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
+		if (drbd_bitmap_io(device, &drbd_bmio_set_n_write,
 			"set_n_write from attaching", BM_LOCKED_MASK)) {
 			retcode = ERR_IO_MD_DISK;
 			goto force_diskless_dec;
 		}
 	} else {
-		if (drbd_bitmap_io(mdev, &drbd_bm_read,
+		if (drbd_bitmap_io(device, &drbd_bm_read,
 			"read from attaching", BM_LOCKED_MASK)) {
 			retcode = ERR_IO_MD_DISK;
 			goto force_diskless_dec;
 		}
 	}
 
-	if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
-		drbd_suspend_al(mdev); /* IO is still suspended here... */
+	if (_drbd_bm_total_weight(device) == drbd_bm_bits(device))
+		drbd_suspend_al(device); /* IO is still suspended here... */
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	os = drbd_read_state(mdev);
+	spin_lock_irq(&device->resource->req_lock);
+	os = drbd_read_state(device);
 	ns = os;
 	/* If MDF_CONSISTENT is not set go into inconsistent state,
 	   otherwise investigate MDF_WasUpToDate...
 	   If MDF_WAS_UP_TO_DATE is not set go into D_OUTDATED disk state,
 	   otherwise into D_CONSISTENT state.
 	*/
-	if (drbd_md_test_flag(mdev->ldev, MDF_CONSISTENT)) {
-		if (drbd_md_test_flag(mdev->ldev, MDF_WAS_UP_TO_DATE))
+	if (drbd_md_test_flag(device->ldev, MDF_CONSISTENT)) {
+		if (drbd_md_test_flag(device->ldev, MDF_WAS_UP_TO_DATE))
 			ns.disk = D_CONSISTENT;
 		else
 			ns.disk = D_OUTDATED;
@@ -1717,12 +1744,12 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		ns.disk = D_INCONSISTENT;
 	}
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_PEER_OUT_DATED))
+	if (drbd_md_test_flag(device->ldev, MDF_PEER_OUT_DATED))
 		ns.pdsk = D_OUTDATED;
 
 	rcu_read_lock();
 	if (ns.disk == D_CONSISTENT &&
-	    (ns.pdsk == D_OUTDATED || rcu_dereference(mdev->ldev->disk_conf)->fencing == FP_DONT_CARE))
+	    (ns.pdsk == D_OUTDATED || rcu_dereference(device->ldev->disk_conf)->fencing == FP_DONT_CARE))
 		ns.disk = D_UP_TO_DATE;
 
 	/* All tests on MDF_PRIMARY_IND, MDF_CONNECTED_IND,
@@ -1730,56 +1757,56 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	   this point, because drbd_request_state() modifies these
 	   flags. */
 
-	if (rcu_dereference(mdev->ldev->disk_conf)->al_updates)
-		mdev->ldev->md.flags &= ~MDF_AL_DISABLED;
+	if (rcu_dereference(device->ldev->disk_conf)->al_updates)
+		device->ldev->md.flags &= ~MDF_AL_DISABLED;
 	else
-		mdev->ldev->md.flags |= MDF_AL_DISABLED;
+		device->ldev->md.flags |= MDF_AL_DISABLED;
 
 	rcu_read_unlock();
 
 	/* In case we are C_CONNECTED postpone any decision on the new disk
 	   state after the negotiation phase. */
-	if (mdev->state.conn == C_CONNECTED) {
-		mdev->new_state_tmp.i = ns.i;
+	if (device->state.conn == C_CONNECTED) {
+		device->new_state_tmp.i = ns.i;
 		ns.i = os.i;
 		ns.disk = D_NEGOTIATING;
 
 		/* We expect to receive up-to-date UUIDs soon.
 		   To avoid a race in receive_state, free p_uuid while
 		   holding req_lock. I.e. atomic with the state change */
-		kfree(mdev->p_uuid);
-		mdev->p_uuid = NULL;
+		kfree(device->p_uuid);
+		device->p_uuid = NULL;
 	}
 
-	rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	rv = _drbd_set_state(device, ns, CS_VERBOSE, NULL);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	if (rv < SS_SUCCESS)
 		goto force_diskless_dec;
 
-	mod_timer(&mdev->request_timer, jiffies + HZ);
+	mod_timer(&device->request_timer, jiffies + HZ);
 
-	if (mdev->state.role == R_PRIMARY)
-		mdev->ldev->md.uuid[UI_CURRENT] |=  (u64)1;
+	if (device->state.role == R_PRIMARY)
+		device->ldev->md.uuid[UI_CURRENT] |=  (u64)1;
 	else
-		mdev->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
+		device->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
 
-	drbd_md_mark_dirty(mdev);
-	drbd_md_sync(mdev);
+	drbd_md_mark_dirty(device);
+	drbd_md_sync(device);
 
-	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
-	put_ldev(mdev);
-	conn_reconfig_done(mdev->tconn);
+	kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
+	put_ldev(device);
+	conn_reconfig_done(first_peer_device(device)->connection);
 	drbd_adm_finish(info, retcode);
 	return 0;
 
  force_diskless_dec:
-	put_ldev(mdev);
+	put_ldev(device);
  force_diskless:
-	drbd_force_state(mdev, NS(disk, D_DISKLESS));
-	drbd_md_sync(mdev);
+	drbd_force_state(device, NS(disk, D_DISKLESS));
+	drbd_md_sync(device);
  fail:
-	conn_reconfig_done(mdev->tconn);
+	conn_reconfig_done(first_peer_device(device)->connection);
 	if (nbc) {
 		if (nbc->backing_bdev)
 			blkdev_put(nbc->backing_bdev,
@@ -1798,26 +1825,26 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	return 0;
 }
 
-static int adm_detach(struct drbd_conf *mdev, int force)
+static int adm_detach(struct drbd_device *device, int force)
 {
 	enum drbd_state_rv retcode;
 	int ret;
 
 	if (force) {
-		set_bit(FORCE_DETACH, &mdev->flags);
-		drbd_force_state(mdev, NS(disk, D_FAILED));
+		set_bit(FORCE_DETACH, &device->flags);
+		drbd_force_state(device, NS(disk, D_FAILED));
 		retcode = SS_SUCCESS;
 		goto out;
 	}
 
-	drbd_suspend_io(mdev); /* so no-one is stuck in drbd_al_begin_io */
-	drbd_md_get_buffer(mdev); /* make sure there is no in-flight meta-data IO */
-	retcode = drbd_request_state(mdev, NS(disk, D_FAILED));
-	drbd_md_put_buffer(mdev);
+	drbd_suspend_io(device); /* so no-one is stuck in drbd_al_begin_io */
+	drbd_md_get_buffer(device); /* make sure there is no in-flight meta-data IO */
+	retcode = drbd_request_state(device, NS(disk, D_FAILED));
+	drbd_md_put_buffer(device);
 	/* D_FAILED will transition to DISKLESS. */
-	ret = wait_event_interruptible(mdev->misc_wait,
-			mdev->state.disk != D_FAILED);
-	drbd_resume_io(mdev);
+	ret = wait_event_interruptible(device->misc_wait,
+			device->state.disk != D_FAILED);
+	drbd_resume_io(device);
 	if ((int)retcode == (int)SS_IS_DISKLESS)
 		retcode = SS_NOTHING_TO_DO;
 	if (ret)
@@ -1852,24 +1879,25 @@ int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	retcode = adm_detach(adm_ctx.mdev, parms.force_detach);
+	retcode = adm_detach(adm_ctx.device, parms.force_detach);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static bool conn_resync_running(struct drbd_tconn *tconn)
+static bool conn_resync_running(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	bool rv = false;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (mdev->state.conn == C_SYNC_SOURCE ||
-		    mdev->state.conn == C_SYNC_TARGET ||
-		    mdev->state.conn == C_PAUSED_SYNC_S ||
-		    mdev->state.conn == C_PAUSED_SYNC_T) {
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		if (device->state.conn == C_SYNC_SOURCE ||
+		    device->state.conn == C_SYNC_TARGET ||
+		    device->state.conn == C_PAUSED_SYNC_S ||
+		    device->state.conn == C_PAUSED_SYNC_T) {
 			rv = true;
 			break;
 		}
@@ -1879,16 +1907,17 @@ static bool conn_resync_running(struct drbd_tconn *tconn)
 	return rv;
 }
 
-static bool conn_ov_running(struct drbd_tconn *tconn)
+static bool conn_ov_running(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	bool rv = false;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (mdev->state.conn == C_VERIFY_S ||
-		    mdev->state.conn == C_VERIFY_T) {
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		if (device->state.conn == C_VERIFY_S ||
+		    device->state.conn == C_VERIFY_T) {
 			rv = true;
 			break;
 		}
@@ -1899,63 +1928,65 @@ static bool conn_ov_running(struct drbd_tconn *tconn)
 }
 
 static enum drbd_ret_code
-_check_net_options(struct drbd_tconn *tconn, struct net_conf *old_conf, struct net_conf *new_conf)
+_check_net_options(struct drbd_connection *connection, struct net_conf *old_net_conf, struct net_conf *new_net_conf)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int i;
 
-	if (old_conf && tconn->cstate == C_WF_REPORT_PARAMS && tconn->agreed_pro_version < 100) {
-		if (new_conf->wire_protocol != old_conf->wire_protocol)
+	if (old_net_conf && connection->cstate == C_WF_REPORT_PARAMS && connection->agreed_pro_version < 100) {
+		if (new_net_conf->wire_protocol != old_net_conf->wire_protocol)
 			return ERR_NEED_APV_100;
 
-		if (new_conf->two_primaries != old_conf->two_primaries)
+		if (new_net_conf->two_primaries != old_net_conf->two_primaries)
 			return ERR_NEED_APV_100;
 
-		if (strcmp(new_conf->integrity_alg, old_conf->integrity_alg))
+		if (strcmp(new_net_conf->integrity_alg, old_net_conf->integrity_alg))
 			return ERR_NEED_APV_100;
 	}
 
-	if (!new_conf->two_primaries &&
-	    conn_highest_role(tconn) == R_PRIMARY &&
-	    conn_highest_peer(tconn) == R_PRIMARY)
+	if (!new_net_conf->two_primaries &&
+	    conn_highest_role(connection) == R_PRIMARY &&
+	    conn_highest_peer(connection) == R_PRIMARY)
 		return ERR_NEED_ALLOW_TWO_PRI;
 
-	if (new_conf->two_primaries &&
-	    (new_conf->wire_protocol != DRBD_PROT_C))
+	if (new_net_conf->two_primaries &&
+	    (new_net_conf->wire_protocol != DRBD_PROT_C))
 		return ERR_NOT_PROTO_C;
 
-	idr_for_each_entry(&tconn->volumes, mdev, i) {
-		if (get_ldev(mdev)) {
-			enum drbd_fencing_p fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
-			put_ldev(mdev);
-			if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH)
+	idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+		struct drbd_device *device = peer_device->device;
+		if (get_ldev(device)) {
+			enum drbd_fencing_p fp = rcu_dereference(device->ldev->disk_conf)->fencing;
+			put_ldev(device);
+			if (new_net_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH)
 				return ERR_STONITH_AND_PROT_A;
 		}
-		if (mdev->state.role == R_PRIMARY && new_conf->discard_my_data)
+		if (device->state.role == R_PRIMARY && new_net_conf->discard_my_data)
 			return ERR_DISCARD_IMPOSSIBLE;
 	}
 
-	if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A)
+	if (new_net_conf->on_congestion != OC_BLOCK && new_net_conf->wire_protocol != DRBD_PROT_A)
 		return ERR_CONG_NOT_PROTO_A;
 
 	return NO_ERROR;
 }
 
 static enum drbd_ret_code
-check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf)
+check_net_options(struct drbd_connection *connection, struct net_conf *new_net_conf)
 {
 	static enum drbd_ret_code rv;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int i;
 
 	rcu_read_lock();
-	rv = _check_net_options(tconn, rcu_dereference(tconn->net_conf), new_conf);
+	rv = _check_net_options(connection, rcu_dereference(connection->net_conf), new_net_conf);
 	rcu_read_unlock();
 
-	/* tconn->volumes protected by genl_lock() here */
-	idr_for_each_entry(&tconn->volumes, mdev, i) {
-		if (!mdev->bitmap) {
-			if(drbd_bm_init(mdev))
+	/* connection->volumes protected by genl_lock() here */
+	idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+		struct drbd_device *device = peer_device->device;
+		if (!device->bitmap) {
+			if (drbd_bm_init(device))
 				return ERR_NOMEM;
 		}
 	}
@@ -1986,26 +2017,26 @@ alloc_hash(struct crypto_hash **tfm, char *tfm_name, int err_alg)
 }
 
 static enum drbd_ret_code
-alloc_crypto(struct crypto *crypto, struct net_conf *new_conf)
+alloc_crypto(struct crypto *crypto, struct net_conf *new_net_conf)
 {
 	char hmac_name[CRYPTO_MAX_ALG_NAME];
 	enum drbd_ret_code rv;
 
-	rv = alloc_hash(&crypto->csums_tfm, new_conf->csums_alg,
+	rv = alloc_hash(&crypto->csums_tfm, new_net_conf->csums_alg,
 		       ERR_CSUMS_ALG);
 	if (rv != NO_ERROR)
 		return rv;
-	rv = alloc_hash(&crypto->verify_tfm, new_conf->verify_alg,
+	rv = alloc_hash(&crypto->verify_tfm, new_net_conf->verify_alg,
 		       ERR_VERIFY_ALG);
 	if (rv != NO_ERROR)
 		return rv;
-	rv = alloc_hash(&crypto->integrity_tfm, new_conf->integrity_alg,
+	rv = alloc_hash(&crypto->integrity_tfm, new_net_conf->integrity_alg,
 		       ERR_INTEGRITY_ALG);
 	if (rv != NO_ERROR)
 		return rv;
-	if (new_conf->cram_hmac_alg[0] != 0) {
+	if (new_net_conf->cram_hmac_alg[0] != 0) {
 		snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
-			 new_conf->cram_hmac_alg);
+			 new_net_conf->cram_hmac_alg);
 
 		rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name,
 			       ERR_AUTH_ALG);
@@ -2025,8 +2056,8 @@ static void free_crypto(struct crypto *crypto)
 int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
 {
 	enum drbd_ret_code retcode;
-	struct drbd_tconn *tconn;
-	struct net_conf *old_conf, *new_conf = NULL;
+	struct drbd_connection *connection;
+	struct net_conf *old_net_conf, *new_net_conf = NULL;
 	int err;
 	int ovr; /* online verify running */
 	int rsr; /* re-sync running */
@@ -2038,98 +2069,103 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	tconn = adm_ctx.tconn;
+	connection = adm_ctx.connection;
 
-	new_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
-	if (!new_conf) {
+	new_net_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
+	if (!new_net_conf) {
 		retcode = ERR_NOMEM;
 		goto out;
 	}
 
-	conn_reconfig_start(tconn);
+	conn_reconfig_start(connection);
 
-	mutex_lock(&tconn->data.mutex);
-	mutex_lock(&tconn->conf_update);
-	old_conf = tconn->net_conf;
+	mutex_lock(&connection->data.mutex);
+	mutex_lock(&connection->resource->conf_update);
+	old_net_conf = connection->net_conf;
 
-	if (!old_conf) {
+	if (!old_net_conf) {
 		drbd_msg_put_info("net conf missing, try connect");
 		retcode = ERR_INVALID_REQUEST;
 		goto fail;
 	}
 
-	*new_conf = *old_conf;
+	*new_net_conf = *old_net_conf;
 	if (should_set_defaults(info))
-		set_net_conf_defaults(new_conf);
+		set_net_conf_defaults(new_net_conf);
 
-	err = net_conf_from_attrs_for_change(new_conf, info);
+	err = net_conf_from_attrs_for_change(new_net_conf, info);
 	if (err && err != -ENOMSG) {
 		retcode = ERR_MANDATORY_TAG;
 		drbd_msg_put_info(from_attrs_err_to_txt(err));
 		goto fail;
 	}
 
-	retcode = check_net_options(tconn, new_conf);
+	retcode = check_net_options(connection, new_net_conf);
 	if (retcode != NO_ERROR)
 		goto fail;
 
 	/* re-sync running */
-	rsr = conn_resync_running(tconn);
-	if (rsr && strcmp(new_conf->csums_alg, old_conf->csums_alg)) {
+	rsr = conn_resync_running(connection);
+	if (rsr && strcmp(new_net_conf->csums_alg, old_net_conf->csums_alg)) {
 		retcode = ERR_CSUMS_RESYNC_RUNNING;
 		goto fail;
 	}
 
 	/* online verify running */
-	ovr = conn_ov_running(tconn);
-	if (ovr && strcmp(new_conf->verify_alg, old_conf->verify_alg)) {
+	ovr = conn_ov_running(connection);
+	if (ovr && strcmp(new_net_conf->verify_alg, old_net_conf->verify_alg)) {
 		retcode = ERR_VERIFY_RUNNING;
 		goto fail;
 	}
 
-	retcode = alloc_crypto(&crypto, new_conf);
+	retcode = alloc_crypto(&crypto, new_net_conf);
 	if (retcode != NO_ERROR)
 		goto fail;
 
-	rcu_assign_pointer(tconn->net_conf, new_conf);
+	rcu_assign_pointer(connection->net_conf, new_net_conf);
 
 	if (!rsr) {
-		crypto_free_hash(tconn->csums_tfm);
-		tconn->csums_tfm = crypto.csums_tfm;
+		crypto_free_hash(connection->csums_tfm);
+		connection->csums_tfm = crypto.csums_tfm;
 		crypto.csums_tfm = NULL;
 	}
 	if (!ovr) {
-		crypto_free_hash(tconn->verify_tfm);
-		tconn->verify_tfm = crypto.verify_tfm;
+		crypto_free_hash(connection->verify_tfm);
+		connection->verify_tfm = crypto.verify_tfm;
 		crypto.verify_tfm = NULL;
 	}
 
-	crypto_free_hash(tconn->integrity_tfm);
-	tconn->integrity_tfm = crypto.integrity_tfm;
-	if (tconn->cstate >= C_WF_REPORT_PARAMS && tconn->agreed_pro_version >= 100)
-		/* Do this without trying to take tconn->data.mutex again.  */
-		__drbd_send_protocol(tconn, P_PROTOCOL_UPDATE);
+	crypto_free_hash(connection->integrity_tfm);
+	connection->integrity_tfm = crypto.integrity_tfm;
+	if (connection->cstate >= C_WF_REPORT_PARAMS && connection->agreed_pro_version >= 100)
+		/* Do this without trying to take connection->data.mutex again.  */
+		__drbd_send_protocol(connection, P_PROTOCOL_UPDATE);
 
-	crypto_free_hash(tconn->cram_hmac_tfm);
-	tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
+	crypto_free_hash(connection->cram_hmac_tfm);
+	connection->cram_hmac_tfm = crypto.cram_hmac_tfm;
 
-	mutex_unlock(&tconn->conf_update);
-	mutex_unlock(&tconn->data.mutex);
+	mutex_unlock(&connection->resource->conf_update);
+	mutex_unlock(&connection->data.mutex);
 	synchronize_rcu();
-	kfree(old_conf);
+	kfree(old_net_conf);
+
+	if (connection->cstate >= C_WF_REPORT_PARAMS) {
+		struct drbd_peer_device *peer_device;
+		int vnr;
 
-	if (tconn->cstate >= C_WF_REPORT_PARAMS)
-		drbd_send_sync_param(minor_to_mdev(conn_lowest_minor(tconn)));
+		idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
+			drbd_send_sync_param(peer_device);
+	}
 
 	goto done;
 
  fail:
-	mutex_unlock(&tconn->conf_update);
-	mutex_unlock(&tconn->data.mutex);
+	mutex_unlock(&connection->resource->conf_update);
+	mutex_unlock(&connection->data.mutex);
 	free_crypto(&crypto);
-	kfree(new_conf);
+	kfree(new_net_conf);
  done:
-	conn_reconfig_done(tconn);
+	conn_reconfig_done(connection);
  out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -2137,10 +2173,11 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
 
 int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
-	struct net_conf *old_conf, *new_conf = NULL;
+	struct drbd_peer_device *peer_device;
+	struct net_conf *old_net_conf, *new_net_conf = NULL;
 	struct crypto crypto = { };
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 	enum drbd_ret_code retcode;
 	int i;
 	int err;
@@ -2160,106 +2197,111 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
 	/* No need for _rcu here. All reconfiguration is
 	 * strictly serialized on genl_lock(). We are protected against
 	 * concurrent reconfiguration/addition/deletion */
-	list_for_each_entry(tconn, &drbd_tconns, all_tconn) {
-		if (nla_len(adm_ctx.my_addr) == tconn->my_addr_len &&
-		    !memcmp(nla_data(adm_ctx.my_addr), &tconn->my_addr, tconn->my_addr_len)) {
-			retcode = ERR_LOCAL_ADDR;
-			goto out;
-		}
+	for_each_resource(resource, &drbd_resources) {
+		for_each_connection(connection, resource) {
+			if (nla_len(adm_ctx.my_addr) == connection->my_addr_len &&
+			    !memcmp(nla_data(adm_ctx.my_addr), &connection->my_addr,
+				    connection->my_addr_len)) {
+				retcode = ERR_LOCAL_ADDR;
+				goto out;
+			}
 
-		if (nla_len(adm_ctx.peer_addr) == tconn->peer_addr_len &&
-		    !memcmp(nla_data(adm_ctx.peer_addr), &tconn->peer_addr, tconn->peer_addr_len)) {
-			retcode = ERR_PEER_ADDR;
-			goto out;
+			if (nla_len(adm_ctx.peer_addr) == connection->peer_addr_len &&
+			    !memcmp(nla_data(adm_ctx.peer_addr), &connection->peer_addr,
+				    connection->peer_addr_len)) {
+				retcode = ERR_PEER_ADDR;
+				goto out;
+			}
 		}
 	}
 
-	tconn = adm_ctx.tconn;
-	conn_reconfig_start(tconn);
+	connection = first_connection(adm_ctx.resource);
+	conn_reconfig_start(connection);
 
-	if (tconn->cstate > C_STANDALONE) {
+	if (connection->cstate > C_STANDALONE) {
 		retcode = ERR_NET_CONFIGURED;
 		goto fail;
 	}
 
 	/* allocation not in the IO path, drbdsetup / netlink process context */
-	new_conf = kzalloc(sizeof(*new_conf), GFP_KERNEL);
-	if (!new_conf) {
+	new_net_conf = kzalloc(sizeof(*new_net_conf), GFP_KERNEL);
+	if (!new_net_conf) {
 		retcode = ERR_NOMEM;
 		goto fail;
 	}
 
-	set_net_conf_defaults(new_conf);
+	set_net_conf_defaults(new_net_conf);
 
-	err = net_conf_from_attrs(new_conf, info);
+	err = net_conf_from_attrs(new_net_conf, info);
 	if (err && err != -ENOMSG) {
 		retcode = ERR_MANDATORY_TAG;
 		drbd_msg_put_info(from_attrs_err_to_txt(err));
 		goto fail;
 	}
 
-	retcode = check_net_options(tconn, new_conf);
+	retcode = check_net_options(connection, new_net_conf);
 	if (retcode != NO_ERROR)
 		goto fail;
 
-	retcode = alloc_crypto(&crypto, new_conf);
+	retcode = alloc_crypto(&crypto, new_net_conf);
 	if (retcode != NO_ERROR)
 		goto fail;
 
-	((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0;
+	((char *)new_net_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0;
 
-	conn_flush_workqueue(tconn);
+	drbd_flush_workqueue(&connection->sender_work);
 
-	mutex_lock(&tconn->conf_update);
-	old_conf = tconn->net_conf;
-	if (old_conf) {
+	mutex_lock(&adm_ctx.resource->conf_update);
+	old_net_conf = connection->net_conf;
+	if (old_net_conf) {
 		retcode = ERR_NET_CONFIGURED;
-		mutex_unlock(&tconn->conf_update);
+		mutex_unlock(&adm_ctx.resource->conf_update);
 		goto fail;
 	}
-	rcu_assign_pointer(tconn->net_conf, new_conf);
+	rcu_assign_pointer(connection->net_conf, new_net_conf);
 
-	conn_free_crypto(tconn);
-	tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
-	tconn->integrity_tfm = crypto.integrity_tfm;
-	tconn->csums_tfm = crypto.csums_tfm;
-	tconn->verify_tfm = crypto.verify_tfm;
+	conn_free_crypto(connection);
+	connection->cram_hmac_tfm = crypto.cram_hmac_tfm;
+	connection->integrity_tfm = crypto.integrity_tfm;
+	connection->csums_tfm = crypto.csums_tfm;
+	connection->verify_tfm = crypto.verify_tfm;
 
-	tconn->my_addr_len = nla_len(adm_ctx.my_addr);
-	memcpy(&tconn->my_addr, nla_data(adm_ctx.my_addr), tconn->my_addr_len);
-	tconn->peer_addr_len = nla_len(adm_ctx.peer_addr);
-	memcpy(&tconn->peer_addr, nla_data(adm_ctx.peer_addr), tconn->peer_addr_len);
+	connection->my_addr_len = nla_len(adm_ctx.my_addr);
+	memcpy(&connection->my_addr, nla_data(adm_ctx.my_addr), connection->my_addr_len);
+	connection->peer_addr_len = nla_len(adm_ctx.peer_addr);
+	memcpy(&connection->peer_addr, nla_data(adm_ctx.peer_addr), connection->peer_addr_len);
 
-	mutex_unlock(&tconn->conf_update);
+	mutex_unlock(&adm_ctx.resource->conf_update);
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, i) {
-		mdev->send_cnt = 0;
-		mdev->recv_cnt = 0;
+	idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+		struct drbd_device *device = peer_device->device;
+		device->send_cnt = 0;
+		device->recv_cnt = 0;
 	}
 	rcu_read_unlock();
 
-	retcode = conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE);
+	retcode = conn_request_state(connection, NS(conn, C_UNCONNECTED), CS_VERBOSE);
 
-	conn_reconfig_done(tconn);
+	conn_reconfig_done(connection);
 	drbd_adm_finish(info, retcode);
 	return 0;
 
 fail:
 	free_crypto(&crypto);
-	kfree(new_conf);
+	kfree(new_net_conf);
 
-	conn_reconfig_done(tconn);
+	conn_reconfig_done(connection);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool force)
+static enum drbd_state_rv conn_try_disconnect(struct drbd_connection *connection, bool force)
 {
 	enum drbd_state_rv rv;
 
-	rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING),
+	rv = conn_request_state(connection, NS(conn, C_DISCONNECTING),
 			force ? CS_HARD : 0);
 
 	switch (rv) {
@@ -2269,18 +2311,18 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool for
 		return SS_SUCCESS;
 	case SS_PRIMARY_NOP:
 		/* Our state checking code wants to see the peer outdated. */
-		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING, pdsk, D_OUTDATED), 0);
+		rv = conn_request_state(connection, NS2(conn, C_DISCONNECTING, pdsk, D_OUTDATED), 0);
 
 		if (rv == SS_OUTDATE_WO_CONN) /* lost connection before graceful disconnect succeeded */
-			rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_VERBOSE);
+			rv = conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_VERBOSE);
 
 		break;
 	case SS_CW_FAILED_BY_PEER:
 		/* The peer probably wants to see us outdated. */
-		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
+		rv = conn_request_state(connection, NS2(conn, C_DISCONNECTING,
 							disk, D_OUTDATED), 0);
 		if (rv == SS_IS_DISKLESS || rv == SS_LOWER_THAN_OUTDATED) {
-			rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING),
+			rv = conn_request_state(connection, NS(conn, C_DISCONNECTING),
 					CS_HARD);
 		}
 		break;
@@ -2294,18 +2336,18 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool for
 		 * The state handling only uses drbd_thread_stop_nowait(),
 		 * we want to really wait here until the receiver is no more.
 		 */
-		drbd_thread_stop(&adm_ctx.tconn->receiver);
+		drbd_thread_stop(&connection->receiver);
 
 		/* Race breaker.  This additional state change request may be
 		 * necessary, if this was a forced disconnect during a receiver
 		 * restart.  We may have "killed" the receiver thread just
-		 * after drbdd_init() returned.  Typically, we should be
+		 * after drbd_receiver() returned.  Typically, we should be
 		 * C_STANDALONE already, now, and this becomes a no-op.
 		 */
-		rv2 = conn_request_state(tconn, NS(conn, C_STANDALONE),
+		rv2 = conn_request_state(connection, NS(conn, C_STANDALONE),
 				CS_VERBOSE | CS_HARD);
 		if (rv2 < SS_SUCCESS)
-			conn_err(tconn,
+			drbd_err(connection,
 				"unexpected rv2=%d in conn_try_disconnect()\n",
 				rv2);
 	}
@@ -2315,7 +2357,7 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool for
 int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info)
 {
 	struct disconnect_parms parms;
-	struct drbd_tconn *tconn;
+	struct drbd_connection *connection;
 	enum drbd_state_rv rv;
 	enum drbd_ret_code retcode;
 	int err;
@@ -2326,7 +2368,7 @@ int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto fail;
 
-	tconn = adm_ctx.tconn;
+	connection = adm_ctx.connection;
 	memset(&parms, 0, sizeof(parms));
 	if (info->attrs[DRBD_NLA_DISCONNECT_PARMS]) {
 		err = disconnect_parms_from_attrs(&parms, info);
@@ -2337,7 +2379,7 @@ int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	rv = conn_try_disconnect(tconn, parms.force_disconnect);
+	rv = conn_try_disconnect(connection, parms.force_disconnect);
 	if (rv < SS_SUCCESS)
 		retcode = rv;  /* FIXME: Type mismatch. */
 	else
@@ -2347,27 +2389,27 @@ int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info)
 	return 0;
 }
 
-void resync_after_online_grow(struct drbd_conf *mdev)
+void resync_after_online_grow(struct drbd_device *device)
 {
 	int iass; /* I am sync source */
 
-	dev_info(DEV, "Resync of new storage after online grow\n");
-	if (mdev->state.role != mdev->state.peer)
-		iass = (mdev->state.role == R_PRIMARY);
+	drbd_info(device, "Resync of new storage after online grow\n");
+	if (device->state.role != device->state.peer)
+		iass = (device->state.role == R_PRIMARY);
 	else
-		iass = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags);
+		iass = test_bit(RESOLVE_CONFLICTS, &first_peer_device(device)->connection->flags);
 
 	if (iass)
-		drbd_start_resync(mdev, C_SYNC_SOURCE);
+		drbd_start_resync(device, C_SYNC_SOURCE);
 	else
-		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE + CS_SERIALIZE);
+		_drbd_request_state(device, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE + CS_SERIALIZE);
 }
 
 int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 {
 	struct disk_conf *old_disk_conf, *new_disk_conf = NULL;
 	struct resize_parms rs;
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	enum drbd_ret_code retcode;
 	enum determine_dev_size dd;
 	bool change_al_layout = false;
@@ -2381,15 +2423,15 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto fail;
 
-	mdev = adm_ctx.mdev;
-	if (!get_ldev(mdev)) {
+	device = adm_ctx.device;
+	if (!get_ldev(device)) {
 		retcode = ERR_NO_DISK;
 		goto fail;
 	}
 
 	memset(&rs, 0, sizeof(struct resize_parms));
-	rs.al_stripes = mdev->ldev->md.al_stripes;
-	rs.al_stripe_size = mdev->ldev->md.al_stripe_size_4k * 4;
+	rs.al_stripes = device->ldev->md.al_stripes;
+	rs.al_stripe_size = device->ldev->md.al_stripe_size_4k * 4;
 	if (info->attrs[DRBD_NLA_RESIZE_PARMS]) {
 		err = resize_parms_from_attrs(&rs, info);
 		if (err) {
@@ -2399,24 +2441,24 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	if (mdev->state.conn > C_CONNECTED) {
+	if (device->state.conn > C_CONNECTED) {
 		retcode = ERR_RESIZE_RESYNC;
 		goto fail_ldev;
 	}
 
-	if (mdev->state.role == R_SECONDARY &&
-	    mdev->state.peer == R_SECONDARY) {
+	if (device->state.role == R_SECONDARY &&
+	    device->state.peer == R_SECONDARY) {
 		retcode = ERR_NO_PRIMARY;
 		goto fail_ldev;
 	}
 
-	if (rs.no_resync && mdev->tconn->agreed_pro_version < 93) {
+	if (rs.no_resync && first_peer_device(device)->connection->agreed_pro_version < 93) {
 		retcode = ERR_NEED_APV_93;
 		goto fail_ldev;
 	}
 
 	rcu_read_lock();
-	u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+	u_size = rcu_dereference(device->ldev->disk_conf)->disk_size;
 	rcu_read_unlock();
 	if (u_size != (sector_t)rs.resize_size) {
 		new_disk_conf = kmalloc(sizeof(struct disk_conf), GFP_KERNEL);
@@ -2426,8 +2468,8 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	if (mdev->ldev->md.al_stripes != rs.al_stripes ||
-	    mdev->ldev->md.al_stripe_size_4k != rs.al_stripe_size / 4) {
+	if (device->ldev->md.al_stripes != rs.al_stripes ||
+	    device->ldev->md.al_stripe_size_4k != rs.al_stripe_size / 4) {
 		u32 al_size_k = rs.al_stripes * rs.al_stripe_size;
 
 		if (al_size_k > (16 * 1024 * 1024)) {
@@ -2440,7 +2482,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 			goto fail_ldev;
 		}
 
-		if (mdev->state.conn != C_CONNECTED) {
+		if (device->state.conn != C_CONNECTED) {
 			retcode = ERR_MD_LAYOUT_CONNECTED;
 			goto fail_ldev;
 		}
@@ -2448,24 +2490,24 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 		change_al_layout = true;
 	}
 
-	if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev))
-		mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev);
+	if (device->ldev->known_size != drbd_get_capacity(device->ldev->backing_bdev))
+		device->ldev->known_size = drbd_get_capacity(device->ldev->backing_bdev);
 
 	if (new_disk_conf) {
-		mutex_lock(&mdev->tconn->conf_update);
-		old_disk_conf = mdev->ldev->disk_conf;
+		mutex_lock(&device->resource->conf_update);
+		old_disk_conf = device->ldev->disk_conf;
 		*new_disk_conf = *old_disk_conf;
 		new_disk_conf->disk_size = (sector_t)rs.resize_size;
-		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
-		mutex_unlock(&mdev->tconn->conf_update);
+		rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
+		mutex_unlock(&device->resource->conf_update);
 		synchronize_rcu();
 		kfree(old_disk_conf);
 	}
 
 	ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0);
-	dd = drbd_determine_dev_size(mdev, ddsf, change_al_layout ? &rs : NULL);
-	drbd_md_sync(mdev);
-	put_ldev(mdev);
+	dd = drbd_determine_dev_size(device, ddsf, change_al_layout ? &rs : NULL);
+	drbd_md_sync(device);
+	put_ldev(device);
 	if (dd == DS_ERROR) {
 		retcode = ERR_NOMEM_BITMAP;
 		goto fail;
@@ -2477,12 +2519,12 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
-	if (mdev->state.conn == C_CONNECTED) {
+	if (device->state.conn == C_CONNECTED) {
 		if (dd == DS_GREW)
-			set_bit(RESIZE_PENDING, &mdev->flags);
+			set_bit(RESIZE_PENDING, &device->flags);
 
-		drbd_send_uuids(mdev);
-		drbd_send_sizes(mdev, 1, ddsf);
+		drbd_send_uuids(first_peer_device(device));
+		drbd_send_sizes(first_peer_device(device), 1, ddsf);
 	}
 
  fail:
@@ -2490,14 +2532,13 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
 	return 0;
 
  fail_ldev:
-	put_ldev(mdev);
+	put_ldev(device);
 	goto fail;
 }
 
 int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
 {
 	enum drbd_ret_code retcode;
-	struct drbd_tconn *tconn;
 	struct res_opts res_opts;
 	int err;
 
@@ -2506,9 +2547,8 @@ int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
 		return retcode;
 	if (retcode != NO_ERROR)
 		goto fail;
-	tconn = adm_ctx.tconn;
 
-	res_opts = tconn->res_opts;
+	res_opts = adm_ctx.resource->res_opts;
 	if (should_set_defaults(info))
 		set_res_opts_defaults(&res_opts);
 
@@ -2519,7 +2559,7 @@ int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
-	err = set_resource_options(tconn, &res_opts);
+	err = set_resource_options(adm_ctx.resource, &res_opts);
 	if (err) {
 		retcode = ERR_INVALID_REQUEST;
 		if (err == -ENOMEM)
@@ -2533,7 +2573,7 @@ fail:
 
 int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
 
 	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
@@ -2542,29 +2582,29 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mdev = adm_ctx.mdev;
+	device = adm_ctx.device;
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
 	 * Also wait for it's after_state_ch(). */
-	drbd_suspend_io(mdev);
-	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
-	drbd_flush_workqueue(mdev);
+	drbd_suspend_io(device);
+	wait_event(device->misc_wait, !test_bit(BITMAP_IO, &device->flags));
+	drbd_flush_workqueue(&first_peer_device(device)->connection->sender_work);
 
 	/* If we happen to be C_STANDALONE R_SECONDARY, just change to
 	 * D_INCONSISTENT, and set all bits in the bitmap.  Otherwise,
 	 * try to start a resync handshake as sync target for full sync.
 	 */
-	if (mdev->state.conn == C_STANDALONE && mdev->state.role == R_SECONDARY) {
-		retcode = drbd_request_state(mdev, NS(disk, D_INCONSISTENT));
+	if (device->state.conn == C_STANDALONE && device->state.role == R_SECONDARY) {
+		retcode = drbd_request_state(device, NS(disk, D_INCONSISTENT));
 		if (retcode >= SS_SUCCESS) {
-			if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
+			if (drbd_bitmap_io(device, &drbd_bmio_set_n_write,
 				"set_n_write from invalidate", BM_LOCKED_MASK))
 				retcode = ERR_IO_MD_DISK;
 		}
 	} else
-		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T));
-	drbd_resume_io(mdev);
+		retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_T));
+	drbd_resume_io(device);
 
 out:
 	drbd_adm_finish(info, retcode);
@@ -2582,25 +2622,25 @@ static int drbd_adm_simple_request_state(struct sk_buff *skb, struct genl_info *
 	if (retcode != NO_ERROR)
 		goto out;
 
-	retcode = drbd_request_state(adm_ctx.mdev, mask, val);
+	retcode = drbd_request_state(adm_ctx.device, mask, val);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_bmio_set_susp_al(struct drbd_conf *mdev)
+static int drbd_bmio_set_susp_al(struct drbd_device *device)
 {
 	int rv;
 
-	rv = drbd_bmio_set_n_write(mdev);
-	drbd_suspend_al(mdev);
+	rv = drbd_bmio_set_n_write(device);
+	drbd_suspend_al(device);
 	return rv;
 }
 
 int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
 {
 	int retcode; /* drbd_ret_code, drbd_state_rv */
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 
 	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
 	if (!adm_ctx.reply_skb)
@@ -2608,32 +2648,32 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mdev = adm_ctx.mdev;
+	device = adm_ctx.device;
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
 	 * Also wait for it's after_state_ch(). */
-	drbd_suspend_io(mdev);
-	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
-	drbd_flush_workqueue(mdev);
+	drbd_suspend_io(device);
+	wait_event(device->misc_wait, !test_bit(BITMAP_IO, &device->flags));
+	drbd_flush_workqueue(&first_peer_device(device)->connection->sender_work);
 
 	/* If we happen to be C_STANDALONE R_PRIMARY, just set all bits
 	 * in the bitmap.  Otherwise, try to start a resync handshake
 	 * as sync source for full sync.
 	 */
-	if (mdev->state.conn == C_STANDALONE && mdev->state.role == R_PRIMARY) {
+	if (device->state.conn == C_STANDALONE && device->state.role == R_PRIMARY) {
 		/* The peer will get a resync upon connect anyways. Just make that
 		   into a full resync. */
-		retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
+		retcode = drbd_request_state(device, NS(pdsk, D_INCONSISTENT));
 		if (retcode >= SS_SUCCESS) {
-			if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
+			if (drbd_bitmap_io(device, &drbd_bmio_set_susp_al,
 				"set_n_write from invalidate_peer",
 				BM_LOCKED_SET_ALLOWED))
 				retcode = ERR_IO_MD_DISK;
 		}
 	} else
-		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
-	drbd_resume_io(mdev);
+		retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_S));
+	drbd_resume_io(device);
 
 out:
 	drbd_adm_finish(info, retcode);
@@ -2650,7 +2690,7 @@ int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	if (drbd_request_state(adm_ctx.mdev, NS(user_isp, 1)) == SS_NOTHING_TO_DO)
+	if (drbd_request_state(adm_ctx.device, NS(user_isp, 1)) == SS_NOTHING_TO_DO)
 		retcode = ERR_PAUSE_IS_SET;
 out:
 	drbd_adm_finish(info, retcode);
@@ -2668,8 +2708,8 @@ int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	if (drbd_request_state(adm_ctx.mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
-		s = adm_ctx.mdev->state;
+	if (drbd_request_state(adm_ctx.device, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
+		s = adm_ctx.device->state;
 		if (s.conn == C_PAUSED_SYNC_S || s.conn == C_PAUSED_SYNC_T) {
 			retcode = s.aftr_isp ? ERR_PIC_AFTER_DEP :
 				  s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR;
@@ -2690,7 +2730,7 @@ int drbd_adm_suspend_io(struct sk_buff *skb, struct genl_info *info)
 
 int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
 
 	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
@@ -2699,20 +2739,20 @@ int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mdev = adm_ctx.mdev;
-	if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
-		drbd_uuid_new_current(mdev);
-		clear_bit(NEW_CUR_UUID, &mdev->flags);
+	device = adm_ctx.device;
+	if (test_bit(NEW_CUR_UUID, &device->flags)) {
+		drbd_uuid_new_current(device);
+		clear_bit(NEW_CUR_UUID, &device->flags);
 	}
-	drbd_suspend_io(mdev);
-	retcode = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
+	drbd_suspend_io(device);
+	retcode = drbd_request_state(device, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
 	if (retcode == SS_SUCCESS) {
-		if (mdev->state.conn < C_CONNECTED)
-			tl_clear(mdev->tconn);
-		if (mdev->state.disk == D_DISKLESS || mdev->state.disk == D_FAILED)
-			tl_restart(mdev->tconn, FAIL_FROZEN_DISK_IO);
+		if (device->state.conn < C_CONNECTED)
+			tl_clear(first_peer_device(device)->connection);
+		if (device->state.disk == D_DISKLESS || device->state.disk == D_FAILED)
+			tl_restart(first_peer_device(device)->connection, FAIL_FROZEN_DISK_IO);
 	}
-	drbd_resume_io(mdev);
+	drbd_resume_io(device);
 
 out:
 	drbd_adm_finish(info, retcode);
@@ -2724,23 +2764,28 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info)
 	return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED));
 }
 
-int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_tconn *tconn, unsigned vnr)
+static int nla_put_drbd_cfg_context(struct sk_buff *skb,
+				    struct drbd_resource *resource,
+				    struct drbd_connection *connection,
+				    struct drbd_device *device)
 {
 	struct nlattr *nla;
 	nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT);
 	if (!nla)
 		goto nla_put_failure;
-	if (vnr != VOLUME_UNSPECIFIED &&
-	    nla_put_u32(skb, T_ctx_volume, vnr))
-		goto nla_put_failure;
-	if (nla_put_string(skb, T_ctx_resource_name, tconn->name))
-		goto nla_put_failure;
-	if (tconn->my_addr_len &&
-	    nla_put(skb, T_ctx_my_addr, tconn->my_addr_len, &tconn->my_addr))
+	if (device &&
+	    nla_put_u32(skb, T_ctx_volume, device->vnr))
 		goto nla_put_failure;
-	if (tconn->peer_addr_len &&
-	    nla_put(skb, T_ctx_peer_addr, tconn->peer_addr_len, &tconn->peer_addr))
+	if (nla_put_string(skb, T_ctx_resource_name, resource->name))
 		goto nla_put_failure;
+	if (connection) {
+		if (connection->my_addr_len &&
+		    nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
+			goto nla_put_failure;
+		if (connection->peer_addr_len &&
+		    nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
+			goto nla_put_failure;
+	}
 	nla_nest_end(skb, nla);
 	return 0;
 
@@ -2750,9 +2795,22 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
-int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
+/*
+ * Return the connection of @resource if @resource has exactly one connection.
+ */
+static struct drbd_connection *the_only_connection(struct drbd_resource *resource)
+{
+	struct list_head *connections = &resource->connections;
+
+	if (list_empty(connections) || connections->next->next != connections)
+		return NULL;
+	return list_first_entry(&resource->connections, struct drbd_connection, connections);
+}
+
+int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
 		const struct sib_info *sib)
 {
+	struct drbd_resource *resource = device->resource;
 	struct state_info *si = NULL; /* for sizeof(si->member); */
 	struct nlattr *nla;
 	int got_ldev;
@@ -2772,27 +2830,27 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
 	 * always in the context of the receiving process */
 	exclude_sensitive = sib || !capable(CAP_SYS_ADMIN);
 
-	got_ldev = get_ldev(mdev);
+	got_ldev = get_ldev(device);
 
 	/* We need to add connection name and volume number information still.
 	 * Minor number is in drbd_genlmsghdr. */
-	if (nla_put_drbd_cfg_context(skb, mdev->tconn, mdev->vnr))
+	if (nla_put_drbd_cfg_context(skb, resource, the_only_connection(resource), device))
 		goto nla_put_failure;
 
-	if (res_opts_to_skb(skb, &mdev->tconn->res_opts, exclude_sensitive))
+	if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive))
 		goto nla_put_failure;
 
 	rcu_read_lock();
 	if (got_ldev) {
 		struct disk_conf *disk_conf;
 
-		disk_conf = rcu_dereference(mdev->ldev->disk_conf);
+		disk_conf = rcu_dereference(device->ldev->disk_conf);
 		err = disk_conf_to_skb(skb, disk_conf, exclude_sensitive);
 	}
 	if (!err) {
 		struct net_conf *nc;
 
-		nc = rcu_dereference(mdev->tconn->net_conf);
+		nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 		if (nc)
 			err = net_conf_to_skb(skb, nc, exclude_sensitive);
 	}
@@ -2804,38 +2862,38 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
 	if (!nla)
 		goto nla_put_failure;
 	if (nla_put_u32(skb, T_sib_reason, sib ? sib->sib_reason : SIB_GET_STATUS_REPLY) ||
-	    nla_put_u32(skb, T_current_state, mdev->state.i) ||
-	    nla_put_u64(skb, T_ed_uuid, mdev->ed_uuid) ||
-	    nla_put_u64(skb, T_capacity, drbd_get_capacity(mdev->this_bdev)) ||
-	    nla_put_u64(skb, T_send_cnt, mdev->send_cnt) ||
-	    nla_put_u64(skb, T_recv_cnt, mdev->recv_cnt) ||
-	    nla_put_u64(skb, T_read_cnt, mdev->read_cnt) ||
-	    nla_put_u64(skb, T_writ_cnt, mdev->writ_cnt) ||
-	    nla_put_u64(skb, T_al_writ_cnt, mdev->al_writ_cnt) ||
-	    nla_put_u64(skb, T_bm_writ_cnt, mdev->bm_writ_cnt) ||
-	    nla_put_u32(skb, T_ap_bio_cnt, atomic_read(&mdev->ap_bio_cnt)) ||
-	    nla_put_u32(skb, T_ap_pending_cnt, atomic_read(&mdev->ap_pending_cnt)) ||
-	    nla_put_u32(skb, T_rs_pending_cnt, atomic_read(&mdev->rs_pending_cnt)))
+	    nla_put_u32(skb, T_current_state, device->state.i) ||
+	    nla_put_u64(skb, T_ed_uuid, device->ed_uuid) ||
+	    nla_put_u64(skb, T_capacity, drbd_get_capacity(device->this_bdev)) ||
+	    nla_put_u64(skb, T_send_cnt, device->send_cnt) ||
+	    nla_put_u64(skb, T_recv_cnt, device->recv_cnt) ||
+	    nla_put_u64(skb, T_read_cnt, device->read_cnt) ||
+	    nla_put_u64(skb, T_writ_cnt, device->writ_cnt) ||
+	    nla_put_u64(skb, T_al_writ_cnt, device->al_writ_cnt) ||
+	    nla_put_u64(skb, T_bm_writ_cnt, device->bm_writ_cnt) ||
+	    nla_put_u32(skb, T_ap_bio_cnt, atomic_read(&device->ap_bio_cnt)) ||
+	    nla_put_u32(skb, T_ap_pending_cnt, atomic_read(&device->ap_pending_cnt)) ||
+	    nla_put_u32(skb, T_rs_pending_cnt, atomic_read(&device->rs_pending_cnt)))
 		goto nla_put_failure;
 
 	if (got_ldev) {
 		int err;
 
-		spin_lock_irq(&mdev->ldev->md.uuid_lock);
-		err = nla_put(skb, T_uuids, sizeof(si->uuids), mdev->ldev->md.uuid);
-		spin_unlock_irq(&mdev->ldev->md.uuid_lock);
+		spin_lock_irq(&device->ldev->md.uuid_lock);
+		err = nla_put(skb, T_uuids, sizeof(si->uuids), device->ldev->md.uuid);
+		spin_unlock_irq(&device->ldev->md.uuid_lock);
 
 		if (err)
 			goto nla_put_failure;
 
-		if (nla_put_u32(skb, T_disk_flags, mdev->ldev->md.flags) ||
-		    nla_put_u64(skb, T_bits_total, drbd_bm_bits(mdev)) ||
-		    nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(mdev)))
+		if (nla_put_u32(skb, T_disk_flags, device->ldev->md.flags) ||
+		    nla_put_u64(skb, T_bits_total, drbd_bm_bits(device)) ||
+		    nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(device)))
 			goto nla_put_failure;
-		if (C_SYNC_SOURCE <= mdev->state.conn &&
-		    C_PAUSED_SYNC_T >= mdev->state.conn) {
-			if (nla_put_u64(skb, T_bits_rs_total, mdev->rs_total) ||
-			    nla_put_u64(skb, T_bits_rs_failed, mdev->rs_failed))
+		if (C_SYNC_SOURCE <= device->state.conn &&
+		    C_PAUSED_SYNC_T >= device->state.conn) {
+			if (nla_put_u64(skb, T_bits_rs_total, device->rs_total) ||
+			    nla_put_u64(skb, T_bits_rs_failed, device->rs_failed))
 				goto nla_put_failure;
 		}
 	}
@@ -2867,7 +2925,7 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
 nla_put_failure:
 		err = -EMSGSIZE;
 	if (got_ldev)
-		put_ldev(mdev);
+		put_ldev(device);
 	return err;
 }
 
@@ -2882,7 +2940,7 @@ int drbd_adm_get_status(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	err = nla_put_status_info(adm_ctx.reply_skb, adm_ctx.mdev, NULL);
+	err = nla_put_status_info(adm_ctx.reply_skb, adm_ctx.device, NULL);
 	if (err) {
 		nlmsg_free(adm_ctx.reply_skb);
 		return err;
@@ -2892,22 +2950,23 @@ out:
 	return 0;
 }
 
-int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
+static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	struct drbd_genlmsghdr *dh;
-	struct drbd_tconn *pos = (struct drbd_tconn*)cb->args[0];
-	struct drbd_tconn *tconn = NULL;
-	struct drbd_tconn *tmp;
+	struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
+	struct drbd_resource *resource = NULL;
+	struct drbd_resource *tmp;
 	unsigned volume = cb->args[1];
 
 	/* Open coded, deferred, iteration:
-	 * list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
-	 *	idr_for_each_entry(&tconn->volumes, mdev, i) {
+	 * for_each_resource_safe(resource, tmp, &drbd_resources) {
+	 *      connection = "first connection of resource or undefined";
+	 *	idr_for_each_entry(&resource->devices, device, i) {
 	 *	  ...
 	 *	}
 	 * }
-	 * where tconn is cb->args[0];
+	 * where resource is cb->args[0];
 	 * and i is cb->args[1];
 	 *
 	 * cb->args[2] indicates if we shall loop over all resources,
@@ -2916,44 +2975,44 @@ int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
 	 * This may miss entries inserted after this dump started,
 	 * or entries deleted before they are reached.
 	 *
-	 * We need to make sure the mdev won't disappear while
+	 * We need to make sure the device won't disappear while
 	 * we are looking at it, and revalidate our iterators
 	 * on each iteration.
 	 */
 
-	/* synchronize with conn_create()/conn_destroy() */
+	/* synchronize with conn_create()/drbd_destroy_connection() */
 	rcu_read_lock();
 	/* revalidate iterator position */
-	list_for_each_entry_rcu(tmp, &drbd_tconns, all_tconn) {
+	for_each_resource_rcu(tmp, &drbd_resources) {
 		if (pos == NULL) {
 			/* first iteration */
 			pos = tmp;
-			tconn = pos;
+			resource = pos;
 			break;
 		}
 		if (tmp == pos) {
-			tconn = pos;
+			resource = pos;
 			break;
 		}
 	}
-	if (tconn) {
-next_tconn:
-		mdev = idr_get_next(&tconn->volumes, &volume);
-		if (!mdev) {
-			/* No more volumes to dump on this tconn.
-			 * Advance tconn iterator. */
-			pos = list_entry_rcu(tconn->all_tconn.next,
-					     struct drbd_tconn, all_tconn);
-			/* Did we dump any volume on this tconn yet? */
+	if (resource) {
+next_resource:
+		device = idr_get_next(&resource->devices, &volume);
+		if (!device) {
+			/* No more volumes to dump on this resource.
+			 * Advance resource iterator. */
+			pos = list_entry_rcu(resource->resources.next,
+					     struct drbd_resource, resources);
+			/* Did we dump any volume of this resource yet? */
 			if (volume != 0) {
 				/* If we reached the end of the list,
 				 * or only a single resource dump was requested,
 				 * we are done. */
-				if (&pos->all_tconn == &drbd_tconns || cb->args[2])
+				if (&pos->resources == &drbd_resources || cb->args[2])
 					goto out;
 				volume = 0;
-				tconn = pos;
-				goto next_tconn;
+				resource = pos;
+				goto next_resource;
 			}
 		}
 
@@ -2963,43 +3022,49 @@ next_tconn:
 		if (!dh)
 			goto out;
 
-		if (!mdev) {
-			/* This is a tconn without a single volume.
+		if (!device) {
+			/* This is a connection without a single volume.
 			 * Suprisingly enough, it may have a network
 			 * configuration. */
-			struct net_conf *nc;
+			struct drbd_connection *connection;
+
 			dh->minor = -1U;
 			dh->ret_code = NO_ERROR;
-			if (nla_put_drbd_cfg_context(skb, tconn, VOLUME_UNSPECIFIED))
-				goto cancel;
-			nc = rcu_dereference(tconn->net_conf);
-			if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+			connection = the_only_connection(resource);
+			if (nla_put_drbd_cfg_context(skb, resource, connection, NULL))
 				goto cancel;
+			if (connection) {
+				struct net_conf *nc;
+
+				nc = rcu_dereference(connection->net_conf);
+				if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+					goto cancel;
+			}
 			goto done;
 		}
 
-		D_ASSERT(mdev->vnr == volume);
-		D_ASSERT(mdev->tconn == tconn);
+		D_ASSERT(device, device->vnr == volume);
+		D_ASSERT(device, device->resource == resource);
 
-		dh->minor = mdev_to_minor(mdev);
+		dh->minor = device_to_minor(device);
 		dh->ret_code = NO_ERROR;
 
-		if (nla_put_status_info(skb, mdev, NULL)) {
+		if (nla_put_status_info(skb, device, NULL)) {
 cancel:
 			genlmsg_cancel(skb, dh);
 			goto out;
 		}
 done:
 		genlmsg_end(skb, dh);
-        }
+	}
 
 out:
 	rcu_read_unlock();
 	/* where to start the next iteration */
-        cb->args[0] = (long)pos;
-        cb->args[1] = (pos == tconn) ? volume + 1 : 0;
+	cb->args[0] = (long)pos;
+	cb->args[1] = (pos == resource) ? volume + 1 : 0;
 
-	/* No more tconns/volumes/minors found results in an empty skb.
+	/* No more resources/volumes/minors found results in an empty skb.
 	 * Which will terminate the dump. */
         return skb->len;
 }
@@ -3019,7 +3084,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
 	const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ;
 	struct nlattr *nla;
 	const char *resource_name;
-	struct drbd_tconn *tconn;
+	struct drbd_resource *resource;
 	int maxtype;
 
 	/* Is this a followup call? */
@@ -3048,18 +3113,19 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
 	if (!nla)
 		return -EINVAL;
 	resource_name = nla_data(nla);
-	tconn = conn_get_by_name(resource_name);
-
-	if (!tconn)
+	if (!*resource_name)
+		return -ENODEV;
+	resource = drbd_find_resource(resource_name);
+	if (!resource)
 		return -ENODEV;
 
-	kref_put(&tconn->kref, &conn_destroy); /* get_one_status() (re)validates tconn by itself */
+	kref_put(&resource->kref, drbd_destroy_resource); /* get_one_status() revalidates the resource */
 
 	/* prime iterators, and set "filter" mode mark:
-	 * only dump this tconn. */
-	cb->args[0] = (long)tconn;
+	 * only dump this connection. */
+	cb->args[0] = (long)resource;
 	/* cb->args[1] = 0; passed in this way. */
-	cb->args[2] = (long)tconn;
+	cb->args[2] = (long)resource;
 
 dump:
 	return get_one_status(skb, cb);
@@ -3078,8 +3144,8 @@ int drbd_adm_get_timeout_type(struct sk_buff *skb, struct genl_info *info)
 		goto out;
 
 	tp.timeout_type =
-		adm_ctx.mdev->state.pdsk == D_OUTDATED ? UT_PEER_OUTDATED :
-		test_bit(USE_DEGR_WFC_T, &adm_ctx.mdev->flags) ? UT_DEGRADED :
+		adm_ctx.device->state.pdsk == D_OUTDATED ? UT_PEER_OUTDATED :
+		test_bit(USE_DEGR_WFC_T, &adm_ctx.device->flags) ? UT_DEGRADED :
 		UT_DEFAULT;
 
 	err = timeout_parms_to_priv_skb(adm_ctx.reply_skb, &tp);
@@ -3094,7 +3160,7 @@ out:
 
 int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	enum drbd_ret_code retcode;
 	struct start_ov_parms parms;
 
@@ -3104,10 +3170,10 @@ int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mdev = adm_ctx.mdev;
+	device = adm_ctx.device;
 
 	/* resume from last known position, if possible */
-	parms.ov_start_sector = mdev->ov_start_sector;
+	parms.ov_start_sector = device->ov_start_sector;
 	parms.ov_stop_sector = ULLONG_MAX;
 	if (info->attrs[DRBD_NLA_START_OV_PARMS]) {
 		int err = start_ov_parms_from_attrs(&parms, info);
@@ -3118,15 +3184,15 @@ int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 	/* w_make_ov_request expects position to be aligned */
-	mdev->ov_start_sector = parms.ov_start_sector & ~(BM_SECT_PER_BIT-1);
-	mdev->ov_stop_sector = parms.ov_stop_sector;
+	device->ov_start_sector = parms.ov_start_sector & ~(BM_SECT_PER_BIT-1);
+	device->ov_stop_sector = parms.ov_stop_sector;
 
 	/* If there is still bitmap IO pending, e.g. previous resync or verify
 	 * just being finished, wait for it before requesting a new resync. */
-	drbd_suspend_io(mdev);
-	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
-	retcode = drbd_request_state(mdev,NS(conn,C_VERIFY_S));
-	drbd_resume_io(mdev);
+	drbd_suspend_io(device);
+	wait_event(device->misc_wait, !test_bit(BITMAP_IO, &device->flags));
+	retcode = drbd_request_state(device, NS(conn, C_VERIFY_S));
+	drbd_resume_io(device);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -3135,7 +3201,7 @@ out:
 
 int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
 {
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	enum drbd_ret_code retcode;
 	int skip_initial_sync = 0;
 	int err;
@@ -3147,7 +3213,7 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out_nolock;
 
-	mdev = adm_ctx.mdev;
+	device = adm_ctx.device;
 	memset(&args, 0, sizeof(args));
 	if (info->attrs[DRBD_NLA_NEW_C_UUID_PARMS]) {
 		err = new_c_uuid_parms_from_attrs(&args, info);
@@ -3158,49 +3224,50 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	mutex_lock(mdev->state_mutex); /* Protects us against serialized state changes. */
+	mutex_lock(device->state_mutex); /* Protects us against serialized state changes. */
 
-	if (!get_ldev(mdev)) {
+	if (!get_ldev(device)) {
 		retcode = ERR_NO_DISK;
 		goto out;
 	}
 
 	/* this is "skip initial sync", assume to be clean */
-	if (mdev->state.conn == C_CONNECTED && mdev->tconn->agreed_pro_version >= 90 &&
-	    mdev->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && args.clear_bm) {
-		dev_info(DEV, "Preparing to skip initial sync\n");
+	if (device->state.conn == C_CONNECTED &&
+	    first_peer_device(device)->connection->agreed_pro_version >= 90 &&
+	    device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && args.clear_bm) {
+		drbd_info(device, "Preparing to skip initial sync\n");
 		skip_initial_sync = 1;
-	} else if (mdev->state.conn != C_STANDALONE) {
+	} else if (device->state.conn != C_STANDALONE) {
 		retcode = ERR_CONNECTED;
 		goto out_dec;
 	}
 
-	drbd_uuid_set(mdev, UI_BITMAP, 0); /* Rotate UI_BITMAP to History 1, etc... */
-	drbd_uuid_new_current(mdev); /* New current, previous to UI_BITMAP */
+	drbd_uuid_set(device, UI_BITMAP, 0); /* Rotate UI_BITMAP to History 1, etc... */
+	drbd_uuid_new_current(device); /* New current, previous to UI_BITMAP */
 
 	if (args.clear_bm) {
-		err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
+		err = drbd_bitmap_io(device, &drbd_bmio_clear_n_write,
 			"clear_n_write from new_c_uuid", BM_LOCKED_MASK);
 		if (err) {
-			dev_err(DEV, "Writing bitmap failed with %d\n",err);
+			drbd_err(device, "Writing bitmap failed with %d\n", err);
 			retcode = ERR_IO_MD_DISK;
 		}
 		if (skip_initial_sync) {
-			drbd_send_uuids_skip_initial_sync(mdev);
-			_drbd_uuid_set(mdev, UI_BITMAP, 0);
-			drbd_print_uuids(mdev, "cleared bitmap UUID");
-			spin_lock_irq(&mdev->tconn->req_lock);
-			_drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
+			drbd_send_uuids_skip_initial_sync(first_peer_device(device));
+			_drbd_uuid_set(device, UI_BITMAP, 0);
+			drbd_print_uuids(device, "cleared bitmap UUID");
+			spin_lock_irq(&device->resource->req_lock);
+			_drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
 					CS_VERBOSE, NULL);
-			spin_unlock_irq(&mdev->tconn->req_lock);
+			spin_unlock_irq(&device->resource->req_lock);
 		}
 	}
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 out_dec:
-	put_ldev(mdev);
+	put_ldev(device);
 out:
-	mutex_unlock(mdev->state_mutex);
+	mutex_unlock(device->state_mutex);
 out_nolock:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -3246,7 +3313,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	if (adm_ctx.tconn) {
+	if (adm_ctx.resource) {
 		if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) {
 			retcode = ERR_INVALID_REQUEST;
 			drbd_msg_put_info("resource exists");
@@ -3262,7 +3329,7 @@ out:
 	return 0;
 }
 
-int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info)
+int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
 {
 	struct drbd_genlmsghdr *dh = info->userhdr;
 	enum drbd_ret_code retcode;
@@ -3285,41 +3352,36 @@ int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	/* drbd_adm_prepare made sure already
-	 * that mdev->tconn and mdev->vnr match the request. */
-	if (adm_ctx.mdev) {
+	 * that first_peer_device(device)->connection and device->vnr match the request. */
+	if (adm_ctx.device) {
 		if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
 			retcode = ERR_MINOR_EXISTS;
 		/* else: still NO_ERROR */
 		goto out;
 	}
 
-	retcode = conn_new_minor(adm_ctx.tconn, dh->minor, adm_ctx.volume);
+	retcode = drbd_create_device(adm_ctx.resource, dh->minor, adm_ctx.volume);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static enum drbd_ret_code adm_delete_minor(struct drbd_conf *mdev)
+static enum drbd_ret_code adm_del_minor(struct drbd_device *device)
 {
-	if (mdev->state.disk == D_DISKLESS &&
-	    /* no need to be mdev->state.conn == C_STANDALONE &&
+	if (device->state.disk == D_DISKLESS &&
+	    /* no need to be device->state.conn == C_STANDALONE &&
 	     * we may want to delete a minor from a live replication group.
 	     */
-	    mdev->state.role == R_SECONDARY) {
-		_drbd_request_state(mdev, NS(conn, C_WF_REPORT_PARAMS),
+	    device->state.role == R_SECONDARY) {
+		_drbd_request_state(device, NS(conn, C_WF_REPORT_PARAMS),
 				    CS_VERBOSE + CS_WAIT_COMPLETE);
-		idr_remove(&mdev->tconn->volumes, mdev->vnr);
-		idr_remove(&minors, mdev_to_minor(mdev));
-		destroy_workqueue(mdev->submit.wq);
-		del_gendisk(mdev->vdisk);
-		synchronize_rcu();
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_delete_device(device);
 		return NO_ERROR;
 	} else
 		return ERR_MINOR_CONFIGURED;
 }
 
-int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info)
+int drbd_adm_del_minor(struct sk_buff *skb, struct genl_info *info)
 {
 	enum drbd_ret_code retcode;
 
@@ -3329,7 +3391,7 @@ int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	retcode = adm_delete_minor(adm_ctx.mdev);
+	retcode = adm_del_minor(adm_ctx.device);
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -3337,55 +3399,58 @@ out:
 
 int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
 {
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
+	struct drbd_device *device;
 	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
-	struct drbd_conf *mdev;
 	unsigned i;
 
-	retcode = drbd_adm_prepare(skb, info, 0);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
 	if (!adm_ctx.reply_skb)
 		return retcode;
 	if (retcode != NO_ERROR)
 		goto out;
 
-	if (!adm_ctx.tconn) {
-		retcode = ERR_RES_NOT_KNOWN;
-		goto out;
-	}
-
+	resource = adm_ctx.resource;
 	/* demote */
-	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
-		retcode = drbd_set_role(mdev, R_SECONDARY, 0);
+	for_each_connection(connection, resource) {
+		struct drbd_peer_device *peer_device;
+
+		idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+			retcode = drbd_set_role(peer_device->device, R_SECONDARY, 0);
+			if (retcode < SS_SUCCESS) {
+				drbd_msg_put_info("failed to demote");
+				goto out;
+			}
+		}
+
+		retcode = conn_try_disconnect(connection, 0);
 		if (retcode < SS_SUCCESS) {
-			drbd_msg_put_info("failed to demote");
+			drbd_msg_put_info("failed to disconnect");
 			goto out;
 		}
 	}
 
-	retcode = conn_try_disconnect(adm_ctx.tconn, 0);
-	if (retcode < SS_SUCCESS) {
-		drbd_msg_put_info("failed to disconnect");
-		goto out;
-	}
-
 	/* detach */
-	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
-		retcode = adm_detach(mdev, 0);
+	idr_for_each_entry(&resource->devices, device, i) {
+		retcode = adm_detach(device, 0);
 		if (retcode < SS_SUCCESS || retcode > NO_ERROR) {
 			drbd_msg_put_info("failed to detach");
 			goto out;
 		}
 	}
 
-	/* If we reach this, all volumes (of this tconn) are Secondary,
+	/* If we reach this, all volumes (of this connection) are Secondary,
 	 * Disconnected, Diskless, aka Unconfigured. Make sure all threads have
 	 * actually stopped, state handling only does drbd_thread_stop_nowait(). */
-	drbd_thread_stop(&adm_ctx.tconn->worker);
+	for_each_connection(connection, resource)
+		drbd_thread_stop(&connection->worker);
 
 	/* Now, nothing can fail anymore */
 
 	/* delete volumes */
-	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
-		retcode = adm_delete_minor(mdev);
+	idr_for_each_entry(&resource->devices, device, i) {
+		retcode = adm_del_minor(device);
 		if (retcode != NO_ERROR) {
 			/* "can not happen" */
 			drbd_msg_put_info("failed to delete volume");
@@ -3393,19 +3458,11 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	/* delete connection */
-	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
-		list_del_rcu(&adm_ctx.tconn->all_tconn);
-		synchronize_rcu();
-		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
+	list_del_rcu(&resource->resources);
+	synchronize_rcu();
+	drbd_free_resource(resource);
+	retcode = NO_ERROR;
 
-		retcode = NO_ERROR;
-	} else {
-		/* "can not happen" */
-		retcode = ERR_RES_IN_USE;
-		drbd_msg_put_info("failed to delete connection");
-	}
-	goto out;
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
@@ -3413,6 +3470,8 @@ out:
 
 int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
 {
+	struct drbd_resource *resource;
+	struct drbd_connection *connection;
 	enum drbd_ret_code retcode;
 
 	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
@@ -3421,24 +3480,30 @@ int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
 	if (retcode != NO_ERROR)
 		goto out;
 
-	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
-		list_del_rcu(&adm_ctx.tconn->all_tconn);
-		synchronize_rcu();
-		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
-
-		retcode = NO_ERROR;
-	} else {
+	resource = adm_ctx.resource;
+	for_each_connection(connection, resource) {
+		if (connection->cstate > C_STANDALONE) {
+			retcode = ERR_NET_CONFIGURED;
+			goto out;
+		}
+	}
+	if (!idr_is_empty(&resource->devices)) {
 		retcode = ERR_RES_IN_USE;
+		goto out;
 	}
 
-	if (retcode == NO_ERROR)
-		drbd_thread_stop(&adm_ctx.tconn->worker);
+	list_del_rcu(&resource->resources);
+	for_each_connection(connection, resource)
+		drbd_thread_stop(&connection->worker);
+	synchronize_rcu();
+	drbd_free_resource(resource);
+	retcode = NO_ERROR;
 out:
 	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib)
+void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib)
 {
 	static atomic_t drbd_genl_seq = ATOMIC_INIT(2); /* two. */
 	struct sk_buff *msg;
@@ -3447,8 +3512,8 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib)
 	int err = -ENOMEM;
 
 	if (sib->sib_reason == SIB_SYNC_PROGRESS) {
-		if (time_after(jiffies, mdev->rs_last_bcast + HZ))
-			mdev->rs_last_bcast = jiffies;
+		if (time_after(jiffies, device->rs_last_bcast + HZ))
+			device->rs_last_bcast = jiffies;
 		else
 			return;
 	}
@@ -3462,10 +3527,10 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib)
 	d_out = genlmsg_put(msg, 0, seq, &drbd_genl_family, 0, DRBD_EVENT);
 	if (!d_out) /* cannot happen, but anyways. */
 		goto nla_put_failure;
-	d_out->minor = mdev_to_minor(mdev);
+	d_out->minor = device_to_minor(device);
 	d_out->ret_code = NO_ERROR;
 
-	if (nla_put_status_info(msg, mdev, sib))
+	if (nla_put_status_info(msg, device, sib))
 		goto nla_put_failure;
 	genlmsg_end(msg, d_out);
 	err = drbd_genl_multicast_events(msg, 0);
@@ -3478,7 +3543,7 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib)
 nla_put_failure:
 	nlmsg_free(msg);
 failed:
-	dev_err(DEV, "Error %d while broadcasting event. "
+	drbd_err(device, "Error %d while broadcasting event. "
 			"Event seq:%u sib_reason:%u\n",
 			err, seq, sib->sib_reason);
 }
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index bf31d41dbaad..2f26e8ffa45b 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -46,7 +46,7 @@ const struct file_operations drbd_proc_fops = {
 	.release	= drbd_proc_release,
 };
 
-void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
+static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
 {
 	/* v is in kB/sec. We don't expect TiByte/sec yet. */
 	if (unlikely(v >= 1000000)) {
@@ -66,14 +66,14 @@ void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
  *	[=====>..............] 33.5% (23456/123456)
  *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
  */
-static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
+static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq)
 {
 	unsigned long db, dt, dbdt, rt, rs_left;
 	unsigned int res;
 	int i, x, y;
 	int stalled = 0;
 
-	drbd_get_syncer_progress(mdev, &rs_left, &res);
+	drbd_get_syncer_progress(device, &rs_left, &res);
 
 	x = res/50;
 	y = 20-x;
@@ -85,21 +85,21 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
 		seq_printf(seq, ".");
 	seq_printf(seq, "] ");
 
-	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
 		seq_printf(seq, "verified:");
 	else
 		seq_printf(seq, "sync'ed:");
 	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
 
 	/* if more than a few GB, display in MB */
-	if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
+	if (device->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
 		seq_printf(seq, "(%lu/%lu)M",
 			    (unsigned long) Bit2KB(rs_left >> 10),
-			    (unsigned long) Bit2KB(mdev->rs_total >> 10));
+			    (unsigned long) Bit2KB(device->rs_total >> 10));
 	else
 		seq_printf(seq, "(%lu/%lu)K\n\t",
 			    (unsigned long) Bit2KB(rs_left),
-			    (unsigned long) Bit2KB(mdev->rs_total));
+			    (unsigned long) Bit2KB(device->rs_total));
 
 	/* see drivers/md/md.c
 	 * We do not want to overflow, so the order of operands and
@@ -114,14 +114,14 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
 	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
 	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
 	/* ------------------------ ~18s average ------------------------ */
-	i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
-	dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+	i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
+	dt = (jiffies - device->rs_mark_time[i]) / HZ;
 	if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
 		stalled = 1;
 
 	if (!dt)
 		dt++;
-	db = mdev->rs_mark_left[i] - rs_left;
+	db = device->rs_mark_left[i] - rs_left;
 	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
 
 	seq_printf(seq, "finish: %lu:%02lu:%02lu",
@@ -134,11 +134,11 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
 	/* ------------------------- ~3s average ------------------------ */
 	if (proc_details >= 1) {
 		/* this is what drbd_rs_should_slow_down() uses */
-		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
-		dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+		i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+		dt = (jiffies - device->rs_mark_time[i]) / HZ;
 		if (!dt)
 			dt++;
-		db = mdev->rs_mark_left[i] - rs_left;
+		db = device->rs_mark_left[i] - rs_left;
 		dbdt = Bit2KB(db/dt);
 		seq_printf_with_thousands_grouping(seq, dbdt);
 		seq_printf(seq, " -- ");
@@ -147,34 +147,34 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
 	/* --------------------- long term average ---------------------- */
 	/* mean speed since syncer started
 	 * we do account for PausedSync periods */
-	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
+	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
 	if (dt == 0)
 		dt = 1;
-	db = mdev->rs_total - rs_left;
+	db = device->rs_total - rs_left;
 	dbdt = Bit2KB(db/dt);
 	seq_printf_with_thousands_grouping(seq, dbdt);
 	seq_printf(seq, ")");
 
-	if (mdev->state.conn == C_SYNC_TARGET ||
-	    mdev->state.conn == C_VERIFY_S) {
+	if (device->state.conn == C_SYNC_TARGET ||
+	    device->state.conn == C_VERIFY_S) {
 		seq_printf(seq, " want: ");
-		seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate);
+		seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
 	}
 	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
 
 	if (proc_details >= 1) {
 		/* 64 bit:
 		 * we convert to sectors in the display below. */
-		unsigned long bm_bits = drbd_bm_bits(mdev);
+		unsigned long bm_bits = drbd_bm_bits(device);
 		unsigned long bit_pos;
 		unsigned long long stop_sector = 0;
-		if (mdev->state.conn == C_VERIFY_S ||
-		    mdev->state.conn == C_VERIFY_T) {
-			bit_pos = bm_bits - mdev->ov_left;
-			if (verify_can_do_stop_sector(mdev))
-				stop_sector = mdev->ov_stop_sector;
+		if (device->state.conn == C_VERIFY_S ||
+		    device->state.conn == C_VERIFY_T) {
+			bit_pos = bm_bits - device->ov_left;
+			if (verify_can_do_stop_sector(device))
+				stop_sector = device->ov_stop_sector;
 		} else
-			bit_pos = mdev->bm_resync_fo;
+			bit_pos = device->bm_resync_fo;
 		/* Total sectors may be slightly off for oddly
 		 * sized devices. So what. */
 		seq_printf(seq,
@@ -202,7 +202,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 {
 	int i, prev_i = -1;
 	const char *sn;
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 	struct net_conf *nc;
 	char wp;
 
@@ -236,72 +236,72 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 	*/
 
 	rcu_read_lock();
-	idr_for_each_entry(&minors, mdev, i) {
+	idr_for_each_entry(&drbd_devices, device, i) {
 		if (prev_i != i - 1)
 			seq_printf(seq, "\n");
 		prev_i = i;
 
-		sn = drbd_conn_str(mdev->state.conn);
+		sn = drbd_conn_str(device->state.conn);
 
-		if (mdev->state.conn == C_STANDALONE &&
-		    mdev->state.disk == D_DISKLESS &&
-		    mdev->state.role == R_SECONDARY) {
+		if (device->state.conn == C_STANDALONE &&
+		    device->state.disk == D_DISKLESS &&
+		    device->state.role == R_SECONDARY) {
 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 		} else {
-			/* reset mdev->congestion_reason */
-			bdi_rw_congested(&mdev->rq_queue->backing_dev_info);
+			/* reset device->congestion_reason */
+			bdi_rw_congested(&device->rq_queue->backing_dev_info);
 
-			nc = rcu_dereference(mdev->tconn->net_conf);
+			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
 			seq_printf(seq,
 			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
 			   i, sn,
-			   drbd_role_str(mdev->state.role),
-			   drbd_role_str(mdev->state.peer),
-			   drbd_disk_str(mdev->state.disk),
-			   drbd_disk_str(mdev->state.pdsk),
+			   drbd_role_str(device->state.role),
+			   drbd_role_str(device->state.peer),
+			   drbd_disk_str(device->state.disk),
+			   drbd_disk_str(device->state.pdsk),
 			   wp,
-			   drbd_suspended(mdev) ? 's' : 'r',
-			   mdev->state.aftr_isp ? 'a' : '-',
-			   mdev->state.peer_isp ? 'p' : '-',
-			   mdev->state.user_isp ? 'u' : '-',
-			   mdev->congestion_reason ?: '-',
-			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
-			   mdev->send_cnt/2,
-			   mdev->recv_cnt/2,
-			   mdev->writ_cnt/2,
-			   mdev->read_cnt/2,
-			   mdev->al_writ_cnt,
-			   mdev->bm_writ_cnt,
-			   atomic_read(&mdev->local_cnt),
-			   atomic_read(&mdev->ap_pending_cnt) +
-			   atomic_read(&mdev->rs_pending_cnt),
-			   atomic_read(&mdev->unacked_cnt),
-			   atomic_read(&mdev->ap_bio_cnt),
-			   mdev->tconn->epochs,
-			   write_ordering_chars[mdev->tconn->write_ordering]
+			   drbd_suspended(device) ? 's' : 'r',
+			   device->state.aftr_isp ? 'a' : '-',
+			   device->state.peer_isp ? 'p' : '-',
+			   device->state.user_isp ? 'u' : '-',
+			   device->congestion_reason ?: '-',
+			   test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
+			   device->send_cnt/2,
+			   device->recv_cnt/2,
+			   device->writ_cnt/2,
+			   device->read_cnt/2,
+			   device->al_writ_cnt,
+			   device->bm_writ_cnt,
+			   atomic_read(&device->local_cnt),
+			   atomic_read(&device->ap_pending_cnt) +
+			   atomic_read(&device->rs_pending_cnt),
+			   atomic_read(&device->unacked_cnt),
+			   atomic_read(&device->ap_bio_cnt),
+			   first_peer_device(device)->connection->epochs,
+			   write_ordering_chars[first_peer_device(device)->connection->write_ordering]
 			);
 			seq_printf(seq, " oos:%llu\n",
 				   Bit2KB((unsigned long long)
-					   drbd_bm_total_weight(mdev)));
+					   drbd_bm_total_weight(device)));
 		}
-		if (mdev->state.conn == C_SYNC_SOURCE ||
-		    mdev->state.conn == C_SYNC_TARGET ||
-		    mdev->state.conn == C_VERIFY_S ||
-		    mdev->state.conn == C_VERIFY_T)
-			drbd_syncer_progress(mdev, seq);
-
-		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
-			lc_seq_printf_stats(seq, mdev->resync);
-			lc_seq_printf_stats(seq, mdev->act_log);
-			put_ldev(mdev);
+		if (device->state.conn == C_SYNC_SOURCE ||
+		    device->state.conn == C_SYNC_TARGET ||
+		    device->state.conn == C_VERIFY_S ||
+		    device->state.conn == C_VERIFY_T)
+			drbd_syncer_progress(device, seq);
+
+		if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
+			lc_seq_printf_stats(seq, device->resync);
+			lc_seq_printf_stats(seq, device->act_log);
+			put_ldev(device);
 		}
 
 		if (proc_details >= 2) {
-			if (mdev->resync) {
-				lc_seq_dump_details(seq, mdev->resync, "rs_left",
+			if (device->resync) {
+				lc_seq_dump_details(seq, device->resync, "rs_left",
 					resync_dump_detail);
 			}
 		}
diff --git a/drivers/block/drbd/drbd_protocol.h b/drivers/block/drbd/drbd_protocol.h
new file mode 100644
index 000000000000..3c04ec0ea333
--- /dev/null
+++ b/drivers/block/drbd/drbd_protocol.h
@@ -0,0 +1,295 @@
+#ifndef __DRBD_PROTOCOL_H
+#define __DRBD_PROTOCOL_H
+
+enum drbd_packet {
+	/* receiver (data socket) */
+	P_DATA		      = 0x00,
+	P_DATA_REPLY	      = 0x01, /* Response to P_DATA_REQUEST */
+	P_RS_DATA_REPLY	      = 0x02, /* Response to P_RS_DATA_REQUEST */
+	P_BARRIER	      = 0x03,
+	P_BITMAP	      = 0x04,
+	P_BECOME_SYNC_TARGET  = 0x05,
+	P_BECOME_SYNC_SOURCE  = 0x06,
+	P_UNPLUG_REMOTE	      = 0x07, /* Used at various times to hint the peer */
+	P_DATA_REQUEST	      = 0x08, /* Used to ask for a data block */
+	P_RS_DATA_REQUEST     = 0x09, /* Used to ask for a data block for resync */
+	P_SYNC_PARAM	      = 0x0a,
+	P_PROTOCOL	      = 0x0b,
+	P_UUIDS		      = 0x0c,
+	P_SIZES		      = 0x0d,
+	P_STATE		      = 0x0e,
+	P_SYNC_UUID	      = 0x0f,
+	P_AUTH_CHALLENGE      = 0x10,
+	P_AUTH_RESPONSE	      = 0x11,
+	P_STATE_CHG_REQ	      = 0x12,
+
+	/* asender (meta socket */
+	P_PING		      = 0x13,
+	P_PING_ACK	      = 0x14,
+	P_RECV_ACK	      = 0x15, /* Used in protocol B */
+	P_WRITE_ACK	      = 0x16, /* Used in protocol C */
+	P_RS_WRITE_ACK	      = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */
+	P_SUPERSEDED	      = 0x18, /* Used in proto C, two-primaries conflict detection */
+	P_NEG_ACK	      = 0x19, /* Sent if local disk is unusable */
+	P_NEG_DREPLY	      = 0x1a, /* Local disk is broken... */
+	P_NEG_RS_DREPLY	      = 0x1b, /* Local disk is broken... */
+	P_BARRIER_ACK	      = 0x1c,
+	P_STATE_CHG_REPLY     = 0x1d,
+
+	/* "new" commands, no longer fitting into the ordering scheme above */
+
+	P_OV_REQUEST	      = 0x1e, /* data socket */
+	P_OV_REPLY	      = 0x1f,
+	P_OV_RESULT	      = 0x20, /* meta socket */
+	P_CSUM_RS_REQUEST     = 0x21, /* data socket */
+	P_RS_IS_IN_SYNC	      = 0x22, /* meta socket */
+	P_SYNC_PARAM89	      = 0x23, /* data socket, protocol version 89 replacement for P_SYNC_PARAM */
+	P_COMPRESSED_BITMAP   = 0x24, /* compressed or otherwise encoded bitmap transfer */
+	/* P_CKPT_FENCE_REQ      = 0x25, * currently reserved for protocol D */
+	/* P_CKPT_DISABLE_REQ    = 0x26, * currently reserved for protocol D */
+	P_DELAY_PROBE         = 0x27, /* is used on BOTH sockets */
+	P_OUT_OF_SYNC         = 0x28, /* Mark as out of sync (Outrunning), data socket */
+	P_RS_CANCEL           = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */
+	P_CONN_ST_CHG_REQ     = 0x2a, /* data sock: Connection wide state request */
+	P_CONN_ST_CHG_REPLY   = 0x2b, /* meta sock: Connection side state req reply */
+	P_RETRY_WRITE	      = 0x2c, /* Protocol C: retry conflicting write request */
+	P_PROTOCOL_UPDATE     = 0x2d, /* data sock: is used in established connections */
+
+	P_MAY_IGNORE	      = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
+	P_MAX_OPT_CMD	      = 0x101,
+
+	/* special command ids for handshake */
+
+	P_INITIAL_META	      = 0xfff1, /* First Packet on the MetaSock */
+	P_INITIAL_DATA	      = 0xfff2, /* First Packet on the Socket */
+
+	P_CONNECTION_FEATURES = 0xfffe	/* FIXED for the next century! */
+};
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+/* This is the layout for a packet on the wire.
+ * The byteorder is the network byte order.
+ *     (except block_id and barrier fields.
+ *	these are pointers to local structs
+ *	and have no relevance for the partner,
+ *	which just echoes them as received.)
+ *
+ * NOTE that the payload starts at a long aligned offset,
+ * regardless of 32 or 64 bit arch!
+ */
+struct p_header80 {
+	u32	  magic;
+	u16	  command;
+	u16	  length;	/* bytes of data after this header */
+} __packed;
+
+/* Header for big packets, Used for data packets exceeding 64kB */
+struct p_header95 {
+	u16	  magic;	/* use DRBD_MAGIC_BIG here */
+	u16	  command;
+	u32	  length;
+} __packed;
+
+struct p_header100 {
+	u32	  magic;
+	u16	  volume;
+	u16	  command;
+	u32	  length;
+	u32	  pad;
+} __packed;
+
+/* these defines must not be changed without changing the protocol version */
+#define DP_HARDBARRIER	      1 /* depricated */
+#define DP_RW_SYNC	      2 /* equals REQ_SYNC    */
+#define DP_MAY_SET_IN_SYNC    4
+#define DP_UNPLUG             8 /* not used anymore   */
+#define DP_FUA               16 /* equals REQ_FUA     */
+#define DP_FLUSH             32 /* equals REQ_FLUSH   */
+#define DP_DISCARD           64 /* equals REQ_DISCARD */
+#define DP_SEND_RECEIVE_ACK 128 /* This is a proto B write request */
+#define DP_SEND_WRITE_ACK   256 /* This is a proto C write request */
+
+struct p_data {
+	u64	    sector;    /* 64 bits sector number */
+	u64	    block_id;  /* to identify the request in protocol B&C */
+	u32	    seq_num;
+	u32	    dp_flags;
+} __packed;
+
+/*
+ * commands which share a struct:
+ *  p_block_ack:
+ *   P_RECV_ACK (proto B), P_WRITE_ACK (proto C),
+ *   P_SUPERSEDED (proto C, two-primaries conflict detection)
+ *  p_block_req:
+ *   P_DATA_REQUEST, P_RS_DATA_REQUEST
+ */
+struct p_block_ack {
+	u64	    sector;
+	u64	    block_id;
+	u32	    blksize;
+	u32	    seq_num;
+} __packed;
+
+struct p_block_req {
+	u64 sector;
+	u64 block_id;
+	u32 blksize;
+	u32 pad;	/* to multiple of 8 Byte */
+} __packed;
+
+/*
+ * commands with their own struct for additional fields:
+ *   P_CONNECTION_FEATURES
+ *   P_BARRIER
+ *   P_BARRIER_ACK
+ *   P_SYNC_PARAM
+ *   ReportParams
+ */
+
+struct p_connection_features {
+	u32 protocol_min;
+	u32 feature_flags;
+	u32 protocol_max;
+
+	/* should be more than enough for future enhancements
+	 * for now, feature_flags and the reserved array shall be zero.
+	 */
+
+	u32 _pad;
+	u64 reserved[7];
+} __packed;
+
+struct p_barrier {
+	u32 barrier;	/* barrier number _handle_ only */
+	u32 pad;	/* to multiple of 8 Byte */
+} __packed;
+
+struct p_barrier_ack {
+	u32 barrier;
+	u32 set_size;
+} __packed;
+
+struct p_rs_param {
+	u32 resync_rate;
+
+	      /* Since protocol version 88 and higher. */
+	char verify_alg[0];
+} __packed;
+
+struct p_rs_param_89 {
+	u32 resync_rate;
+	/* protocol version 89: */
+	char verify_alg[SHARED_SECRET_MAX];
+	char csums_alg[SHARED_SECRET_MAX];
+} __packed;
+
+struct p_rs_param_95 {
+	u32 resync_rate;
+	char verify_alg[SHARED_SECRET_MAX];
+	char csums_alg[SHARED_SECRET_MAX];
+	u32 c_plan_ahead;
+	u32 c_delay_target;
+	u32 c_fill_target;
+	u32 c_max_rate;
+} __packed;
+
+enum drbd_conn_flags {
+	CF_DISCARD_MY_DATA = 1,
+	CF_DRY_RUN = 2,
+};
+
+struct p_protocol {
+	u32 protocol;
+	u32 after_sb_0p;
+	u32 after_sb_1p;
+	u32 after_sb_2p;
+	u32 conn_flags;
+	u32 two_primaries;
+
+	/* Since protocol version 87 and higher. */
+	char integrity_alg[0];
+
+} __packed;
+
+struct p_uuids {
+	u64 uuid[UI_EXTENDED_SIZE];
+} __packed;
+
+struct p_rs_uuid {
+	u64	    uuid;
+} __packed;
+
+struct p_sizes {
+	u64	    d_size;  /* size of disk */
+	u64	    u_size;  /* user requested size */
+	u64	    c_size;  /* current exported size */
+	u32	    max_bio_size;  /* Maximal size of a BIO */
+	u16	    queue_order_type;  /* not yet implemented in DRBD*/
+	u16	    dds_flags; /* use enum dds_flags here. */
+} __packed;
+
+struct p_state {
+	u32	    state;
+} __packed;
+
+struct p_req_state {
+	u32	    mask;
+	u32	    val;
+} __packed;
+
+struct p_req_state_reply {
+	u32	    retcode;
+} __packed;
+
+struct p_drbd06_param {
+	u64	  size;
+	u32	  state;
+	u32	  blksize;
+	u32	  protocol;
+	u32	  version;
+	u32	  gen_cnt[5];
+	u32	  bit_map_gen[5];
+} __packed;
+
+struct p_block_desc {
+	u64 sector;
+	u32 blksize;
+	u32 pad;	/* to multiple of 8 Byte */
+} __packed;
+
+/* Valid values for the encoding field.
+ * Bump proto version when changing this. */
+enum drbd_bitmap_code {
+	/* RLE_VLI_Bytes = 0,
+	 * and other bit variants had been defined during
+	 * algorithm evaluation. */
+	RLE_VLI_Bits = 2,
+};
+
+struct p_compressed_bm {
+	/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
+	 * (encoding & 0x80): polarity (set/unset) of first runlength
+	 * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
+	 * used to pad up to head.length bytes
+	 */
+	u8 encoding;
+
+	u8 code[0];
+} __packed;
+
+struct p_delay_probe93 {
+	u32     seq_num; /* sequence number to match the two probe packets */
+	u32     offset;  /* usecs the probe got sent after the reference time point */
+} __packed;
+
+/*
+ * Bitmap packets need to fit within a single page on the sender and receiver,
+ * so we are limited to 4 KiB (and not to PAGE_SIZE, which can be bigger).
+ */
+#define DRBD_SOCKET_BUFFER_SIZE 4096
+
+#endif  /* __DRBD_PROTOCOL_H */
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index d073305ffd5e..18c76e84d540 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -44,6 +44,7 @@
 #include <linux/string.h>
 #include <linux/scatterlist.h>
 #include "drbd_int.h"
+#include "drbd_protocol.h"
 #include "drbd_req.h"
 
 #include "drbd_vli.h"
@@ -61,11 +62,11 @@ enum finish_epoch {
 	FE_RECYCLED,
 };
 
-static int drbd_do_features(struct drbd_tconn *tconn);
-static int drbd_do_auth(struct drbd_tconn *tconn);
-static int drbd_disconnected(struct drbd_conf *mdev);
+static int drbd_do_features(struct drbd_connection *connection);
+static int drbd_do_auth(struct drbd_connection *connection);
+static int drbd_disconnected(struct drbd_peer_device *);
 
-static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *, struct drbd_epoch *, enum epoch_event);
+static enum finish_epoch drbd_may_finish_epoch(struct drbd_connection *, struct drbd_epoch *, enum epoch_event);
 static int e_end_block(struct drbd_work *, int);
 
 
@@ -150,7 +151,7 @@ static void page_chain_add(struct page **head,
 	*head = chain_first;
 }
 
-static struct page *__drbd_alloc_pages(struct drbd_conf *mdev,
+static struct page *__drbd_alloc_pages(struct drbd_device *device,
 				       unsigned int number)
 {
 	struct page *page = NULL;
@@ -196,41 +197,39 @@ static struct page *__drbd_alloc_pages(struct drbd_conf *mdev,
 	return NULL;
 }
 
-static void reclaim_finished_net_peer_reqs(struct drbd_conf *mdev,
+static void reclaim_finished_net_peer_reqs(struct drbd_device *device,
 					   struct list_head *to_be_freed)
 {
-	struct drbd_peer_request *peer_req;
-	struct list_head *le, *tle;
+	struct drbd_peer_request *peer_req, *tmp;
 
 	/* The EEs are always appended to the end of the list. Since
 	   they are sent in order over the wire, they have to finish
 	   in order. As soon as we see the first not finished we can
 	   stop to examine the list... */
 
-	list_for_each_safe(le, tle, &mdev->net_ee) {
-		peer_req = list_entry(le, struct drbd_peer_request, w.list);
+	list_for_each_entry_safe(peer_req, tmp, &device->net_ee, w.list) {
 		if (drbd_peer_req_has_active_page(peer_req))
 			break;
-		list_move(le, to_be_freed);
+		list_move(&peer_req->w.list, to_be_freed);
 	}
 }
 
-static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
+static void drbd_kick_lo_and_reclaim_net(struct drbd_device *device)
 {
 	LIST_HEAD(reclaimed);
 	struct drbd_peer_request *peer_req, *t;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	reclaim_finished_net_peer_reqs(mdev, &reclaimed);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	reclaim_finished_net_peer_reqs(device, &reclaimed);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	list_for_each_entry_safe(peer_req, t, &reclaimed, w.list)
-		drbd_free_net_peer_req(mdev, peer_req);
+		drbd_free_net_peer_req(device, peer_req);
 }
 
 /**
  * drbd_alloc_pages() - Returns @number pages, retries forever (or until signalled)
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @number:	number of pages requested
  * @retry:	whether to retry, if not enough pages are available right now
  *
@@ -240,9 +239,10 @@ static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
  *
  * Returns a page chain linked via page->private.
  */
-struct page *drbd_alloc_pages(struct drbd_conf *mdev, unsigned int number,
+struct page *drbd_alloc_pages(struct drbd_peer_device *peer_device, unsigned int number,
 			      bool retry)
 {
+	struct drbd_device *device = peer_device->device;
 	struct page *page = NULL;
 	struct net_conf *nc;
 	DEFINE_WAIT(wait);
@@ -251,20 +251,20 @@ struct page *drbd_alloc_pages(struct drbd_conf *mdev, unsigned int number,
 	/* Yes, we may run up to @number over max_buffers. If we
 	 * follow it strictly, the admin will get it wrong anyways. */
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(peer_device->connection->net_conf);
 	mxb = nc ? nc->max_buffers : 1000000;
 	rcu_read_unlock();
 
-	if (atomic_read(&mdev->pp_in_use) < mxb)
-		page = __drbd_alloc_pages(mdev, number);
+	if (atomic_read(&device->pp_in_use) < mxb)
+		page = __drbd_alloc_pages(device, number);
 
 	while (page == NULL) {
 		prepare_to_wait(&drbd_pp_wait, &wait, TASK_INTERRUPTIBLE);
 
-		drbd_kick_lo_and_reclaim_net(mdev);
+		drbd_kick_lo_and_reclaim_net(device);
 
-		if (atomic_read(&mdev->pp_in_use) < mxb) {
-			page = __drbd_alloc_pages(mdev, number);
+		if (atomic_read(&device->pp_in_use) < mxb) {
+			page = __drbd_alloc_pages(device, number);
 			if (page)
 				break;
 		}
@@ -273,7 +273,7 @@ struct page *drbd_alloc_pages(struct drbd_conf *mdev, unsigned int number,
 			break;
 
 		if (signal_pending(current)) {
-			dev_warn(DEV, "drbd_alloc_pages interrupted!\n");
+			drbd_warn(device, "drbd_alloc_pages interrupted!\n");
 			break;
 		}
 
@@ -282,17 +282,17 @@ struct page *drbd_alloc_pages(struct drbd_conf *mdev, unsigned int number,
 	finish_wait(&drbd_pp_wait, &wait);
 
 	if (page)
-		atomic_add(number, &mdev->pp_in_use);
+		atomic_add(number, &device->pp_in_use);
 	return page;
 }
 
 /* Must not be used from irq, as that may deadlock: see drbd_alloc_pages.
- * Is also used from inside an other spin_lock_irq(&mdev->tconn->req_lock);
+ * Is also used from inside an other spin_lock_irq(&resource->req_lock);
  * Either links the page chain back to the global pool,
  * or returns all pages to the system. */
-static void drbd_free_pages(struct drbd_conf *mdev, struct page *page, int is_net)
+static void drbd_free_pages(struct drbd_device *device, struct page *page, int is_net)
 {
-	atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
+	atomic_t *a = is_net ? &device->pp_in_use_by_net : &device->pp_in_use;
 	int i;
 
 	if (page == NULL)
@@ -310,7 +310,7 @@ static void drbd_free_pages(struct drbd_conf *mdev, struct page *page, int is_ne
 	}
 	i = atomic_sub_return(i, a);
 	if (i < 0)
-		dev_warn(DEV, "ASSERTION FAILED: %s: %d < 0\n",
+		drbd_warn(device, "ASSERTION FAILED: %s: %d < 0\n",
 			is_net ? "pp_in_use_by_net" : "pp_in_use", i);
 	wake_up(&drbd_pp_wait);
 }
@@ -330,25 +330,26 @@ You must not have the req_lock:
 */
 
 struct drbd_peer_request *
-drbd_alloc_peer_req(struct drbd_conf *mdev, u64 id, sector_t sector,
+drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
 		    unsigned int data_size, gfp_t gfp_mask) __must_hold(local)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_peer_request *peer_req;
 	struct page *page = NULL;
 	unsigned nr_pages = (data_size + PAGE_SIZE -1) >> PAGE_SHIFT;
 
-	if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE))
+	if (drbd_insert_fault(device, DRBD_FAULT_AL_EE))
 		return NULL;
 
 	peer_req = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM);
 	if (!peer_req) {
 		if (!(gfp_mask & __GFP_NOWARN))
-			dev_err(DEV, "%s: allocation failed\n", __func__);
+			drbd_err(device, "%s: allocation failed\n", __func__);
 		return NULL;
 	}
 
 	if (data_size) {
-		page = drbd_alloc_pages(mdev, nr_pages, (gfp_mask & __GFP_WAIT));
+		page = drbd_alloc_pages(peer_device, nr_pages, (gfp_mask & __GFP_WAIT));
 		if (!page)
 			goto fail;
 	}
@@ -360,7 +361,7 @@ drbd_alloc_peer_req(struct drbd_conf *mdev, u64 id, sector_t sector,
 	peer_req->i.waiting = false;
 
 	peer_req->epoch = NULL;
-	peer_req->w.mdev = mdev;
+	peer_req->peer_device = peer_device;
 	peer_req->pages = page;
 	atomic_set(&peer_req->pending_bios, 0);
 	peer_req->flags = 0;
@@ -377,30 +378,30 @@ drbd_alloc_peer_req(struct drbd_conf *mdev, u64 id, sector_t sector,
 	return NULL;
 }
 
-void __drbd_free_peer_req(struct drbd_conf *mdev, struct drbd_peer_request *peer_req,
+void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req,
 		       int is_net)
 {
 	if (peer_req->flags & EE_HAS_DIGEST)
 		kfree(peer_req->digest);
-	drbd_free_pages(mdev, peer_req->pages, is_net);
-	D_ASSERT(atomic_read(&peer_req->pending_bios) == 0);
-	D_ASSERT(drbd_interval_empty(&peer_req->i));
+	drbd_free_pages(device, peer_req->pages, is_net);
+	D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0);
+	D_ASSERT(device, drbd_interval_empty(&peer_req->i));
 	mempool_free(peer_req, drbd_ee_mempool);
 }
 
-int drbd_free_peer_reqs(struct drbd_conf *mdev, struct list_head *list)
+int drbd_free_peer_reqs(struct drbd_device *device, struct list_head *list)
 {
 	LIST_HEAD(work_list);
 	struct drbd_peer_request *peer_req, *t;
 	int count = 0;
-	int is_net = list == &mdev->net_ee;
+	int is_net = list == &device->net_ee;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
 	list_splice_init(list, &work_list);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	list_for_each_entry_safe(peer_req, t, &work_list, w.list) {
-		__drbd_free_peer_req(mdev, peer_req, is_net);
+		__drbd_free_peer_req(device, peer_req, is_net);
 		count++;
 	}
 	return count;
@@ -409,20 +410,20 @@ int drbd_free_peer_reqs(struct drbd_conf *mdev, struct list_head *list)
 /*
  * See also comments in _req_mod(,BARRIER_ACKED) and receive_Barrier.
  */
-static int drbd_finish_peer_reqs(struct drbd_conf *mdev)
+static int drbd_finish_peer_reqs(struct drbd_device *device)
 {
 	LIST_HEAD(work_list);
 	LIST_HEAD(reclaimed);
 	struct drbd_peer_request *peer_req, *t;
 	int err = 0;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	reclaim_finished_net_peer_reqs(mdev, &reclaimed);
-	list_splice_init(&mdev->done_ee, &work_list);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	reclaim_finished_net_peer_reqs(device, &reclaimed);
+	list_splice_init(&device->done_ee, &work_list);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	list_for_each_entry_safe(peer_req, t, &reclaimed, w.list)
-		drbd_free_net_peer_req(mdev, peer_req);
+		drbd_free_net_peer_req(device, peer_req);
 
 	/* possible callbacks here:
 	 * e_end_block, and e_end_resync_block, e_send_superseded.
@@ -435,14 +436,14 @@ static int drbd_finish_peer_reqs(struct drbd_conf *mdev)
 		err2 = peer_req->w.cb(&peer_req->w, !!err);
 		if (!err)
 			err = err2;
-		drbd_free_peer_req(mdev, peer_req);
+		drbd_free_peer_req(device, peer_req);
 	}
-	wake_up(&mdev->ee_wait);
+	wake_up(&device->ee_wait);
 
 	return err;
 }
 
-static void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
+static void _drbd_wait_ee_list_empty(struct drbd_device *device,
 				     struct list_head *head)
 {
 	DEFINE_WAIT(wait);
@@ -450,20 +451,20 @@ static void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
 	/* avoids spin_lock/unlock
 	 * and calling prepare_to_wait in the fast path */
 	while (!list_empty(head)) {
-		prepare_to_wait(&mdev->ee_wait, &wait, TASK_UNINTERRUPTIBLE);
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		prepare_to_wait(&device->ee_wait, &wait, TASK_UNINTERRUPTIBLE);
+		spin_unlock_irq(&device->resource->req_lock);
 		io_schedule();
-		finish_wait(&mdev->ee_wait, &wait);
-		spin_lock_irq(&mdev->tconn->req_lock);
+		finish_wait(&device->ee_wait, &wait);
+		spin_lock_irq(&device->resource->req_lock);
 	}
 }
 
-static void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
+static void drbd_wait_ee_list_empty(struct drbd_device *device,
 				    struct list_head *head)
 {
-	spin_lock_irq(&mdev->tconn->req_lock);
-	_drbd_wait_ee_list_empty(mdev, head);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	_drbd_wait_ee_list_empty(device, head);
+	spin_unlock_irq(&device->resource->req_lock);
 }
 
 static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flags)
@@ -488,44 +489,44 @@ static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flag
 	return rv;
 }
 
-static int drbd_recv(struct drbd_tconn *tconn, void *buf, size_t size)
+static int drbd_recv(struct drbd_connection *connection, void *buf, size_t size)
 {
 	int rv;
 
-	rv = drbd_recv_short(tconn->data.socket, buf, size, 0);
+	rv = drbd_recv_short(connection->data.socket, buf, size, 0);
 
 	if (rv < 0) {
 		if (rv == -ECONNRESET)
-			conn_info(tconn, "sock was reset by peer\n");
+			drbd_info(connection, "sock was reset by peer\n");
 		else if (rv != -ERESTARTSYS)
-			conn_err(tconn, "sock_recvmsg returned %d\n", rv);
+			drbd_err(connection, "sock_recvmsg returned %d\n", rv);
 	} else if (rv == 0) {
-		if (test_bit(DISCONNECT_SENT, &tconn->flags)) {
+		if (test_bit(DISCONNECT_SENT, &connection->flags)) {
 			long t;
 			rcu_read_lock();
-			t = rcu_dereference(tconn->net_conf)->ping_timeo * HZ/10;
+			t = rcu_dereference(connection->net_conf)->ping_timeo * HZ/10;
 			rcu_read_unlock();
 
-			t = wait_event_timeout(tconn->ping_wait, tconn->cstate < C_WF_REPORT_PARAMS, t);
+			t = wait_event_timeout(connection->ping_wait, connection->cstate < C_WF_REPORT_PARAMS, t);
 
 			if (t)
 				goto out;
 		}
-		conn_info(tconn, "sock was shut down by peer\n");
+		drbd_info(connection, "sock was shut down by peer\n");
 	}
 
 	if (rv != size)
-		conn_request_state(tconn, NS(conn, C_BROKEN_PIPE), CS_HARD);
+		conn_request_state(connection, NS(conn, C_BROKEN_PIPE), CS_HARD);
 
 out:
 	return rv;
 }
 
-static int drbd_recv_all(struct drbd_tconn *tconn, void *buf, size_t size)
+static int drbd_recv_all(struct drbd_connection *connection, void *buf, size_t size)
 {
 	int err;
 
-	err = drbd_recv(tconn, buf, size);
+	err = drbd_recv(connection, buf, size);
 	if (err != size) {
 		if (err >= 0)
 			err = -EIO;
@@ -534,13 +535,13 @@ static int drbd_recv_all(struct drbd_tconn *tconn, void *buf, size_t size)
 	return err;
 }
 
-static int drbd_recv_all_warn(struct drbd_tconn *tconn, void *buf, size_t size)
+static int drbd_recv_all_warn(struct drbd_connection *connection, void *buf, size_t size)
 {
 	int err;
 
-	err = drbd_recv_all(tconn, buf, size);
+	err = drbd_recv_all(connection, buf, size);
 	if (err && !signal_pending(current))
-		conn_warn(tconn, "short read (expected size %d)\n", (int)size);
+		drbd_warn(connection, "short read (expected size %d)\n", (int)size);
 	return err;
 }
 
@@ -563,7 +564,7 @@ static void drbd_setbufsize(struct socket *sock, unsigned int snd,
 	}
 }
 
-static struct socket *drbd_try_connect(struct drbd_tconn *tconn)
+static struct socket *drbd_try_connect(struct drbd_connection *connection)
 {
 	const char *what;
 	struct socket *sock;
@@ -575,7 +576,7 @@ static struct socket *drbd_try_connect(struct drbd_tconn *tconn)
 	int disconnect_on_error = 1;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	if (!nc) {
 		rcu_read_unlock();
 		return NULL;
@@ -585,16 +586,16 @@ static struct socket *drbd_try_connect(struct drbd_tconn *tconn)
 	connect_int = nc->connect_int;
 	rcu_read_unlock();
 
-	my_addr_len = min_t(int, tconn->my_addr_len, sizeof(src_in6));
-	memcpy(&src_in6, &tconn->my_addr, my_addr_len);
+	my_addr_len = min_t(int, connection->my_addr_len, sizeof(src_in6));
+	memcpy(&src_in6, &connection->my_addr, my_addr_len);
 
-	if (((struct sockaddr *)&tconn->my_addr)->sa_family == AF_INET6)
+	if (((struct sockaddr *)&connection->my_addr)->sa_family == AF_INET6)
 		src_in6.sin6_port = 0;
 	else
 		((struct sockaddr_in *)&src_in6)->sin_port = 0; /* AF_INET & AF_SCI */
 
-	peer_addr_len = min_t(int, tconn->peer_addr_len, sizeof(src_in6));
-	memcpy(&peer_in6, &tconn->peer_addr, peer_addr_len);
+	peer_addr_len = min_t(int, connection->peer_addr_len, sizeof(src_in6));
+	memcpy(&peer_in6, &connection->peer_addr, peer_addr_len);
 
 	what = "sock_create_kern";
 	err = sock_create_kern(((struct sockaddr *)&src_in6)->sa_family,
@@ -642,17 +643,17 @@ out:
 			disconnect_on_error = 0;
 			break;
 		default:
-			conn_err(tconn, "%s failed, err = %d\n", what, err);
+			drbd_err(connection, "%s failed, err = %d\n", what, err);
 		}
 		if (disconnect_on_error)
-			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+			conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 	}
 
 	return sock;
 }
 
 struct accept_wait_data {
-	struct drbd_tconn *tconn;
+	struct drbd_connection *connection;
 	struct socket *s_listen;
 	struct completion door_bell;
 	void (*original_sk_state_change)(struct sock *sk);
@@ -670,7 +671,7 @@ static void drbd_incoming_connection(struct sock *sk)
 	state_change(sk);
 }
 
-static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_data *ad)
+static int prepare_listen_socket(struct drbd_connection *connection, struct accept_wait_data *ad)
 {
 	int err, sndbuf_size, rcvbuf_size, my_addr_len;
 	struct sockaddr_in6 my_addr;
@@ -679,7 +680,7 @@ static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_da
 	const char *what;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	if (!nc) {
 		rcu_read_unlock();
 		return -EIO;
@@ -688,8 +689,8 @@ static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_da
 	rcvbuf_size = nc->rcvbuf_size;
 	rcu_read_unlock();
 
-	my_addr_len = min_t(int, tconn->my_addr_len, sizeof(struct sockaddr_in6));
-	memcpy(&my_addr, &tconn->my_addr, my_addr_len);
+	my_addr_len = min_t(int, connection->my_addr_len, sizeof(struct sockaddr_in6));
+	memcpy(&my_addr, &connection->my_addr, my_addr_len);
 
 	what = "sock_create_kern";
 	err = sock_create_kern(((struct sockaddr *)&my_addr)->sa_family,
@@ -725,8 +726,8 @@ out:
 		sock_release(s_listen);
 	if (err < 0) {
 		if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
-			conn_err(tconn, "%s failed, err = %d\n", what, err);
-			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+			drbd_err(connection, "%s failed, err = %d\n", what, err);
+			conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 		}
 	}
 
@@ -741,14 +742,14 @@ static void unregister_state_change(struct sock *sk, struct accept_wait_data *ad
 	write_unlock_bh(&sk->sk_callback_lock);
 }
 
-static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad)
+static struct socket *drbd_wait_for_connect(struct drbd_connection *connection, struct accept_wait_data *ad)
 {
 	int timeo, connect_int, err = 0;
 	struct socket *s_estab = NULL;
 	struct net_conf *nc;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	if (!nc) {
 		rcu_read_unlock();
 		return NULL;
@@ -767,8 +768,8 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc
 	err = kernel_accept(ad->s_listen, &s_estab, 0);
 	if (err < 0) {
 		if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
-			conn_err(tconn, "accept failed, err = %d\n", err);
-			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+			drbd_err(connection, "accept failed, err = %d\n", err);
+			conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 		}
 	}
 
@@ -778,29 +779,29 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc
 	return s_estab;
 }
 
-static int decode_header(struct drbd_tconn *, void *, struct packet_info *);
+static int decode_header(struct drbd_connection *, void *, struct packet_info *);
 
-static int send_first_packet(struct drbd_tconn *tconn, struct drbd_socket *sock,
+static int send_first_packet(struct drbd_connection *connection, struct drbd_socket *sock,
 			     enum drbd_packet cmd)
 {
-	if (!conn_prepare_command(tconn, sock))
+	if (!conn_prepare_command(connection, sock))
 		return -EIO;
-	return conn_send_command(tconn, sock, cmd, 0, NULL, 0);
+	return conn_send_command(connection, sock, cmd, 0, NULL, 0);
 }
 
-static int receive_first_packet(struct drbd_tconn *tconn, struct socket *sock)
+static int receive_first_packet(struct drbd_connection *connection, struct socket *sock)
 {
-	unsigned int header_size = drbd_header_size(tconn);
+	unsigned int header_size = drbd_header_size(connection);
 	struct packet_info pi;
 	int err;
 
-	err = drbd_recv_short(sock, tconn->data.rbuf, header_size, 0);
+	err = drbd_recv_short(sock, connection->data.rbuf, header_size, 0);
 	if (err != header_size) {
 		if (err >= 0)
 			err = -EIO;
 		return err;
 	}
-	err = decode_header(tconn, tconn->data.rbuf, &pi);
+	err = decode_header(connection, connection->data.rbuf, &pi);
 	if (err)
 		return err;
 	return pi.cmd;
@@ -830,28 +831,29 @@ static int drbd_socket_okay(struct socket **sock)
 }
 /* Gets called if a connection is established, or if a new minor gets created
    in a connection */
-int drbd_connected(struct drbd_conf *mdev)
+int drbd_connected(struct drbd_peer_device *peer_device)
 {
+	struct drbd_device *device = peer_device->device;
 	int err;
 
-	atomic_set(&mdev->packet_seq, 0);
-	mdev->peer_seq = 0;
+	atomic_set(&device->packet_seq, 0);
+	device->peer_seq = 0;
 
-	mdev->state_mutex = mdev->tconn->agreed_pro_version < 100 ?
-		&mdev->tconn->cstate_mutex :
-		&mdev->own_state_mutex;
+	device->state_mutex = peer_device->connection->agreed_pro_version < 100 ?
+		&peer_device->connection->cstate_mutex :
+		&device->own_state_mutex;
 
-	err = drbd_send_sync_param(mdev);
+	err = drbd_send_sync_param(peer_device);
 	if (!err)
-		err = drbd_send_sizes(mdev, 0, 0);
+		err = drbd_send_sizes(peer_device, 0, 0);
 	if (!err)
-		err = drbd_send_uuids(mdev);
+		err = drbd_send_uuids(peer_device);
 	if (!err)
-		err = drbd_send_current_state(mdev);
-	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
-	clear_bit(RESIZE_PENDING, &mdev->flags);
-	atomic_set(&mdev->ap_in_flight, 0);
-	mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
+		err = drbd_send_current_state(peer_device);
+	clear_bit(USE_DEGR_WFC_T, &device->flags);
+	clear_bit(RESIZE_PENDING, &device->flags);
+	atomic_set(&device->ap_in_flight, 0);
+	mod_timer(&device->request_timer, jiffies + HZ); /* just start it here. */
 	return err;
 }
 
@@ -863,59 +865,59 @@ int drbd_connected(struct drbd_conf *mdev)
  *     no point in trying again, please go standalone.
  *  -2 We do not have a network config...
  */
-static int conn_connect(struct drbd_tconn *tconn)
+static int conn_connect(struct drbd_connection *connection)
 {
 	struct drbd_socket sock, msock;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	struct net_conf *nc;
 	int vnr, timeout, h, ok;
 	bool discard_my_data;
 	enum drbd_state_rv rv;
 	struct accept_wait_data ad = {
-		.tconn = tconn,
+		.connection = connection,
 		.door_bell = COMPLETION_INITIALIZER_ONSTACK(ad.door_bell),
 	};
 
-	clear_bit(DISCONNECT_SENT, &tconn->flags);
-	if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS)
+	clear_bit(DISCONNECT_SENT, &connection->flags);
+	if (conn_request_state(connection, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS)
 		return -2;
 
 	mutex_init(&sock.mutex);
-	sock.sbuf = tconn->data.sbuf;
-	sock.rbuf = tconn->data.rbuf;
+	sock.sbuf = connection->data.sbuf;
+	sock.rbuf = connection->data.rbuf;
 	sock.socket = NULL;
 	mutex_init(&msock.mutex);
-	msock.sbuf = tconn->meta.sbuf;
-	msock.rbuf = tconn->meta.rbuf;
+	msock.sbuf = connection->meta.sbuf;
+	msock.rbuf = connection->meta.rbuf;
 	msock.socket = NULL;
 
 	/* Assume that the peer only understands protocol 80 until we know better.  */
-	tconn->agreed_pro_version = 80;
+	connection->agreed_pro_version = 80;
 
-	if (prepare_listen_socket(tconn, &ad))
+	if (prepare_listen_socket(connection, &ad))
 		return 0;
 
 	do {
 		struct socket *s;
 
-		s = drbd_try_connect(tconn);
+		s = drbd_try_connect(connection);
 		if (s) {
 			if (!sock.socket) {
 				sock.socket = s;
-				send_first_packet(tconn, &sock, P_INITIAL_DATA);
+				send_first_packet(connection, &sock, P_INITIAL_DATA);
 			} else if (!msock.socket) {
-				clear_bit(RESOLVE_CONFLICTS, &tconn->flags);
+				clear_bit(RESOLVE_CONFLICTS, &connection->flags);
 				msock.socket = s;
-				send_first_packet(tconn, &msock, P_INITIAL_META);
+				send_first_packet(connection, &msock, P_INITIAL_META);
 			} else {
-				conn_err(tconn, "Logic error in conn_connect()\n");
+				drbd_err(connection, "Logic error in conn_connect()\n");
 				goto out_release_sockets;
 			}
 		}
 
 		if (sock.socket && msock.socket) {
 			rcu_read_lock();
-			nc = rcu_dereference(tconn->net_conf);
+			nc = rcu_dereference(connection->net_conf);
 			timeout = nc->ping_timeo * HZ / 10;
 			rcu_read_unlock();
 			schedule_timeout_interruptible(timeout);
@@ -926,15 +928,15 @@ static int conn_connect(struct drbd_tconn *tconn)
 		}
 
 retry:
-		s = drbd_wait_for_connect(tconn, &ad);
+		s = drbd_wait_for_connect(connection, &ad);
 		if (s) {
-			int fp = receive_first_packet(tconn, s);
+			int fp = receive_first_packet(connection, s);
 			drbd_socket_okay(&sock.socket);
 			drbd_socket_okay(&msock.socket);
 			switch (fp) {
 			case P_INITIAL_DATA:
 				if (sock.socket) {
-					conn_warn(tconn, "initial packet S crossed\n");
+					drbd_warn(connection, "initial packet S crossed\n");
 					sock_release(sock.socket);
 					sock.socket = s;
 					goto randomize;
@@ -942,9 +944,9 @@ retry:
 				sock.socket = s;
 				break;
 			case P_INITIAL_META:
-				set_bit(RESOLVE_CONFLICTS, &tconn->flags);
+				set_bit(RESOLVE_CONFLICTS, &connection->flags);
 				if (msock.socket) {
-					conn_warn(tconn, "initial packet M crossed\n");
+					drbd_warn(connection, "initial packet M crossed\n");
 					sock_release(msock.socket);
 					msock.socket = s;
 					goto randomize;
@@ -952,7 +954,7 @@ retry:
 				msock.socket = s;
 				break;
 			default:
-				conn_warn(tconn, "Error receiving initial packet\n");
+				drbd_warn(connection, "Error receiving initial packet\n");
 				sock_release(s);
 randomize:
 				if (prandom_u32() & 1)
@@ -960,12 +962,12 @@ randomize:
 			}
 		}
 
-		if (tconn->cstate <= C_DISCONNECTING)
+		if (connection->cstate <= C_DISCONNECTING)
 			goto out_release_sockets;
 		if (signal_pending(current)) {
 			flush_signals(current);
 			smp_rmb();
-			if (get_t_state(&tconn->receiver) == EXITING)
+			if (get_t_state(&connection->receiver) == EXITING)
 				goto out_release_sockets;
 		}
 
@@ -986,12 +988,12 @@ randomize:
 	msock.socket->sk->sk_priority = TC_PRIO_INTERACTIVE;
 
 	/* NOT YET ...
-	 * sock.socket->sk->sk_sndtimeo = tconn->net_conf->timeout*HZ/10;
+	 * sock.socket->sk->sk_sndtimeo = connection->net_conf->timeout*HZ/10;
 	 * sock.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
 	 * first set it to the P_CONNECTION_FEATURES timeout,
 	 * which we set to 4x the configured ping_timeout. */
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 
 	sock.socket->sk->sk_sndtimeo =
 	sock.socket->sk->sk_rcvtimeo = nc->ping_timeo*4*HZ/10;
@@ -1008,37 +1010,38 @@ randomize:
 	drbd_tcp_nodelay(sock.socket);
 	drbd_tcp_nodelay(msock.socket);
 
-	tconn->data.socket = sock.socket;
-	tconn->meta.socket = msock.socket;
-	tconn->last_received = jiffies;
+	connection->data.socket = sock.socket;
+	connection->meta.socket = msock.socket;
+	connection->last_received = jiffies;
 
-	h = drbd_do_features(tconn);
+	h = drbd_do_features(connection);
 	if (h <= 0)
 		return h;
 
-	if (tconn->cram_hmac_tfm) {
-		/* drbd_request_state(mdev, NS(conn, WFAuth)); */
-		switch (drbd_do_auth(tconn)) {
+	if (connection->cram_hmac_tfm) {
+		/* drbd_request_state(device, NS(conn, WFAuth)); */
+		switch (drbd_do_auth(connection)) {
 		case -1:
-			conn_err(tconn, "Authentication of peer failed\n");
+			drbd_err(connection, "Authentication of peer failed\n");
 			return -1;
 		case 0:
-			conn_err(tconn, "Authentication of peer failed, trying again.\n");
+			drbd_err(connection, "Authentication of peer failed, trying again.\n");
 			return 0;
 		}
 	}
 
-	tconn->data.socket->sk->sk_sndtimeo = timeout;
-	tconn->data.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
+	connection->data.socket->sk->sk_sndtimeo = timeout;
+	connection->data.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
 
-	if (drbd_send_protocol(tconn) == -EOPNOTSUPP)
+	if (drbd_send_protocol(connection) == -EOPNOTSUPP)
 		return -1;
 
-	set_bit(STATE_SENT, &tconn->flags);
+	set_bit(STATE_SENT, &connection->flags);
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		kref_get(&mdev->kref);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		kref_get(&device->kref);
 		rcu_read_unlock();
 
 		/* Prevent a race between resync-handshake and
@@ -1048,35 +1051,35 @@ randomize:
 		 * drbd_set_role() is finished, and any incoming drbd_set_role
 		 * will see the STATE_SENT flag, and wait for it to be cleared.
 		 */
-		mutex_lock(mdev->state_mutex);
-		mutex_unlock(mdev->state_mutex);
+		mutex_lock(device->state_mutex);
+		mutex_unlock(device->state_mutex);
 
 		if (discard_my_data)
-			set_bit(DISCARD_MY_DATA, &mdev->flags);
+			set_bit(DISCARD_MY_DATA, &device->flags);
 		else
-			clear_bit(DISCARD_MY_DATA, &mdev->flags);
+			clear_bit(DISCARD_MY_DATA, &device->flags);
 
-		drbd_connected(mdev);
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_connected(peer_device);
+		kref_put(&device->kref, drbd_destroy_device);
 		rcu_read_lock();
 	}
 	rcu_read_unlock();
 
-	rv = conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE);
-	if (rv < SS_SUCCESS || tconn->cstate != C_WF_REPORT_PARAMS) {
-		clear_bit(STATE_SENT, &tconn->flags);
+	rv = conn_request_state(connection, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE);
+	if (rv < SS_SUCCESS || connection->cstate != C_WF_REPORT_PARAMS) {
+		clear_bit(STATE_SENT, &connection->flags);
 		return 0;
 	}
 
-	drbd_thread_start(&tconn->asender);
+	drbd_thread_start(&connection->asender);
 
-	mutex_lock(&tconn->conf_update);
+	mutex_lock(&connection->resource->conf_update);
 	/* The discard_my_data flag is a single-shot modifier to the next
 	 * connection attempt, the handshake of which is now well underway.
 	 * No need for rcu style copying of the whole struct
 	 * just to clear a single value. */
-	tconn->net_conf->discard_my_data = 0;
-	mutex_unlock(&tconn->conf_update);
+	connection->net_conf->discard_my_data = 0;
+	mutex_unlock(&connection->resource->conf_update);
 
 	return h;
 
@@ -1090,15 +1093,15 @@ out_release_sockets:
 	return -1;
 }
 
-static int decode_header(struct drbd_tconn *tconn, void *header, struct packet_info *pi)
+static int decode_header(struct drbd_connection *connection, void *header, struct packet_info *pi)
 {
-	unsigned int header_size = drbd_header_size(tconn);
+	unsigned int header_size = drbd_header_size(connection);
 
 	if (header_size == sizeof(struct p_header100) &&
 	    *(__be32 *)header == cpu_to_be32(DRBD_MAGIC_100)) {
 		struct p_header100 *h = header;
 		if (h->pad != 0) {
-			conn_err(tconn, "Header padding is not zero\n");
+			drbd_err(connection, "Header padding is not zero\n");
 			return -EINVAL;
 		}
 		pi->vnr = be16_to_cpu(h->volume);
@@ -1117,55 +1120,57 @@ static int decode_header(struct drbd_tconn *tconn, void *header, struct packet_i
 		pi->size = be16_to_cpu(h->length);
 		pi->vnr = 0;
 	} else {
-		conn_err(tconn, "Wrong magic value 0x%08x in protocol version %d\n",
+		drbd_err(connection, "Wrong magic value 0x%08x in protocol version %d\n",
 			 be32_to_cpu(*(__be32 *)header),
-			 tconn->agreed_pro_version);
+			 connection->agreed_pro_version);
 		return -EINVAL;
 	}
 	pi->data = header + header_size;
 	return 0;
 }
 
-static int drbd_recv_header(struct drbd_tconn *tconn, struct packet_info *pi)
+static int drbd_recv_header(struct drbd_connection *connection, struct packet_info *pi)
 {
-	void *buffer = tconn->data.rbuf;
+	void *buffer = connection->data.rbuf;
 	int err;
 
-	err = drbd_recv_all_warn(tconn, buffer, drbd_header_size(tconn));
+	err = drbd_recv_all_warn(connection, buffer, drbd_header_size(connection));
 	if (err)
 		return err;
 
-	err = decode_header(tconn, buffer, pi);
-	tconn->last_received = jiffies;
+	err = decode_header(connection, buffer, pi);
+	connection->last_received = jiffies;
 
 	return err;
 }
 
-static void drbd_flush(struct drbd_tconn *tconn)
+static void drbd_flush(struct drbd_connection *connection)
 {
 	int rv;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
-	if (tconn->write_ordering >= WO_bdev_flush) {
+	if (connection->write_ordering >= WO_bdev_flush) {
 		rcu_read_lock();
-		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-			if (!get_ldev(mdev))
+		idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+			struct drbd_device *device = peer_device->device;
+
+			if (!get_ldev(device))
 				continue;
-			kref_get(&mdev->kref);
+			kref_get(&device->kref);
 			rcu_read_unlock();
 
-			rv = blkdev_issue_flush(mdev->ldev->backing_bdev,
+			rv = blkdev_issue_flush(device->ldev->backing_bdev,
 					GFP_NOIO, NULL);
 			if (rv) {
-				dev_info(DEV, "local disk flush failed with status %d\n", rv);
+				drbd_info(device, "local disk flush failed with status %d\n", rv);
 				/* would rather check on EOPNOTSUPP, but that is not reliable.
 				 * don't try again for ANY return value != 0
 				 * if (rv == -EOPNOTSUPP) */
-				drbd_bump_write_ordering(tconn, WO_drain_io);
+				drbd_bump_write_ordering(connection, WO_drain_io);
 			}
-			put_ldev(mdev);
-			kref_put(&mdev->kref, &drbd_minor_destroy);
+			put_ldev(device);
+			kref_put(&device->kref, drbd_destroy_device);
 
 			rcu_read_lock();
 			if (rv)
@@ -1177,11 +1182,11 @@ static void drbd_flush(struct drbd_tconn *tconn)
 
 /**
  * drbd_may_finish_epoch() - Applies an epoch_event to the epoch's state, eventually finishes it.
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @epoch:	Epoch object.
  * @ev:		Epoch event.
  */
-static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn,
+static enum finish_epoch drbd_may_finish_epoch(struct drbd_connection *connection,
 					       struct drbd_epoch *epoch,
 					       enum epoch_event ev)
 {
@@ -1189,7 +1194,7 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn,
 	struct drbd_epoch *next_epoch;
 	enum finish_epoch rv = FE_STILL_LIVE;
 
-	spin_lock(&tconn->epoch_lock);
+	spin_lock(&connection->epoch_lock);
 	do {
 		next_epoch = NULL;
 
@@ -1211,22 +1216,22 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn,
 		    atomic_read(&epoch->active) == 0 &&
 		    (test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags) || ev & EV_CLEANUP)) {
 			if (!(ev & EV_CLEANUP)) {
-				spin_unlock(&tconn->epoch_lock);
-				drbd_send_b_ack(epoch->tconn, epoch->barrier_nr, epoch_size);
-				spin_lock(&tconn->epoch_lock);
+				spin_unlock(&connection->epoch_lock);
+				drbd_send_b_ack(epoch->connection, epoch->barrier_nr, epoch_size);
+				spin_lock(&connection->epoch_lock);
 			}
 #if 0
 			/* FIXME: dec unacked on connection, once we have
 			 * something to count pending connection packets in. */
 			if (test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags))
-				dec_unacked(epoch->tconn);
+				dec_unacked(epoch->connection);
 #endif
 
-			if (tconn->current_epoch != epoch) {
+			if (connection->current_epoch != epoch) {
 				next_epoch = list_entry(epoch->list.next, struct drbd_epoch, list);
 				list_del(&epoch->list);
 				ev = EV_BECAME_LAST | (ev & EV_CLEANUP);
-				tconn->epochs--;
+				connection->epochs--;
 				kfree(epoch);
 
 				if (rv == FE_STILL_LIVE)
@@ -1246,20 +1251,20 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn,
 		epoch = next_epoch;
 	} while (1);
 
-	spin_unlock(&tconn->epoch_lock);
+	spin_unlock(&connection->epoch_lock);
 
 	return rv;
 }
 
 /**
  * drbd_bump_write_ordering() - Fall back to an other write ordering method
- * @tconn:	DRBD connection.
+ * @connection:	DRBD connection.
  * @wo:		Write ordering method to try.
  */
-void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo)
+void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo)
 {
 	struct disk_conf *dc;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	enum write_ordering_e pwo;
 	int vnr;
 	static char *write_ordering_str[] = {
@@ -1268,29 +1273,31 @@ void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo
 		[WO_bdev_flush] = "flush",
 	};
 
-	pwo = tconn->write_ordering;
+	pwo = connection->write_ordering;
 	wo = min(pwo, wo);
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (!get_ldev_if_state(mdev, D_ATTACHING))
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+
+		if (!get_ldev_if_state(device, D_ATTACHING))
 			continue;
-		dc = rcu_dereference(mdev->ldev->disk_conf);
+		dc = rcu_dereference(device->ldev->disk_conf);
 
 		if (wo == WO_bdev_flush && !dc->disk_flushes)
 			wo = WO_drain_io;
 		if (wo == WO_drain_io && !dc->disk_drain)
 			wo = WO_none;
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 	rcu_read_unlock();
-	tconn->write_ordering = wo;
-	if (pwo != tconn->write_ordering || wo == WO_bdev_flush)
-		conn_info(tconn, "Method to ensure write ordering: %s\n", write_ordering_str[tconn->write_ordering]);
+	connection->write_ordering = wo;
+	if (pwo != connection->write_ordering || wo == WO_bdev_flush)
+		drbd_info(connection, "Method to ensure write ordering: %s\n", write_ordering_str[connection->write_ordering]);
 }
 
 /**
  * drbd_submit_peer_request()
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @peer_req:	peer request
  * @rw:		flag field, see bio->bi_rw
  *
@@ -1305,7 +1312,7 @@ void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo
  *  on certain Xen deployments.
  */
 /* TODO allocate from our own bio_set. */
-int drbd_submit_peer_request(struct drbd_conf *mdev,
+int drbd_submit_peer_request(struct drbd_device *device,
 			     struct drbd_peer_request *peer_req,
 			     const unsigned rw, const int fault_type)
 {
@@ -1329,12 +1336,12 @@ int drbd_submit_peer_request(struct drbd_conf *mdev,
 next_bio:
 	bio = bio_alloc(GFP_NOIO, nr_pages);
 	if (!bio) {
-		dev_err(DEV, "submit_ee: Allocation of a bio failed\n");
+		drbd_err(device, "submit_ee: Allocation of a bio failed\n");
 		goto fail;
 	}
 	/* > peer_req->i.sector, unless this is the first bio */
 	bio->bi_iter.bi_sector = sector;
-	bio->bi_bdev = mdev->ldev->backing_bdev;
+	bio->bi_bdev = device->ldev->backing_bdev;
 	bio->bi_rw = rw;
 	bio->bi_private = peer_req;
 	bio->bi_end_io = drbd_peer_request_endio;
@@ -1350,7 +1357,7 @@ next_bio:
 			 * But in case it fails anyways,
 			 * we deal with it, and complain (below). */
 			if (bio->bi_vcnt == 0) {
-				dev_err(DEV,
+				drbd_err(device,
 					"bio_add_page failed for len=%u, "
 					"bi_vcnt=0 (bi_sector=%llu)\n",
 					len, (uint64_t)bio->bi_iter.bi_sector);
@@ -1363,8 +1370,8 @@ next_bio:
 		sector += len >> 9;
 		--nr_pages;
 	}
-	D_ASSERT(page == NULL);
-	D_ASSERT(ds == 0);
+	D_ASSERT(device, page == NULL);
+	D_ASSERT(device, ds == 0);
 
 	atomic_set(&peer_req->pending_bios, n_bios);
 	do {
@@ -1372,7 +1379,7 @@ next_bio:
 		bios = bios->bi_next;
 		bio->bi_next = NULL;
 
-		drbd_generic_make_request(mdev, fault_type, bio);
+		drbd_generic_make_request(device, fault_type, bio);
 	} while (bios);
 	return 0;
 
@@ -1385,36 +1392,44 @@ fail:
 	return err;
 }
 
-static void drbd_remove_epoch_entry_interval(struct drbd_conf *mdev,
+static void drbd_remove_epoch_entry_interval(struct drbd_device *device,
 					     struct drbd_peer_request *peer_req)
 {
 	struct drbd_interval *i = &peer_req->i;
 
-	drbd_remove_interval(&mdev->write_requests, i);
+	drbd_remove_interval(&device->write_requests, i);
 	drbd_clear_interval(i);
 
 	/* Wake up any processes waiting for this peer request to complete.  */
 	if (i->waiting)
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 }
 
-void conn_wait_active_ee_empty(struct drbd_tconn *tconn)
+static void conn_wait_active_ee_empty(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		kref_get(&mdev->kref);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+
+		kref_get(&device->kref);
 		rcu_read_unlock();
-		drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_wait_ee_list_empty(device, &device->active_ee);
+		kref_put(&device->kref, drbd_destroy_device);
 		rcu_read_lock();
 	}
 	rcu_read_unlock();
 }
 
-static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
+static struct drbd_peer_device *
+conn_peer_device(struct drbd_connection *connection, int volume_number)
+{
+	return idr_find(&connection->peer_devices, volume_number);
+}
+
+static int receive_Barrier(struct drbd_connection *connection, struct packet_info *pi)
 {
 	int rv;
 	struct p_barrier *p = pi->data;
@@ -1423,16 +1438,16 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 	/* FIXME these are unacked on connection,
 	 * not a specific (peer)device.
 	 */
-	tconn->current_epoch->barrier_nr = p->barrier;
-	tconn->current_epoch->tconn = tconn;
-	rv = drbd_may_finish_epoch(tconn, tconn->current_epoch, EV_GOT_BARRIER_NR);
+	connection->current_epoch->barrier_nr = p->barrier;
+	connection->current_epoch->connection = connection;
+	rv = drbd_may_finish_epoch(connection, connection->current_epoch, EV_GOT_BARRIER_NR);
 
 	/* P_BARRIER_ACK may imply that the corresponding extent is dropped from
 	 * the activity log, which means it would not be resynced in case the
 	 * R_PRIMARY crashes now.
 	 * Therefore we must send the barrier_ack after the barrier request was
 	 * completed. */
-	switch (tconn->write_ordering) {
+	switch (connection->write_ordering) {
 	case WO_none:
 		if (rv == FE_RECYCLED)
 			return 0;
@@ -1443,15 +1458,15 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 		if (epoch)
 			break;
 		else
-			conn_warn(tconn, "Allocation of an epoch failed, slowing down\n");
+			drbd_warn(connection, "Allocation of an epoch failed, slowing down\n");
 			/* Fall through */
 
 	case WO_bdev_flush:
 	case WO_drain_io:
-		conn_wait_active_ee_empty(tconn);
-		drbd_flush(tconn);
+		conn_wait_active_ee_empty(connection);
+		drbd_flush(connection);
 
-		if (atomic_read(&tconn->current_epoch->epoch_size)) {
+		if (atomic_read(&connection->current_epoch->epoch_size)) {
 			epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO);
 			if (epoch)
 				break;
@@ -1459,7 +1474,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 
 		return 0;
 	default:
-		conn_err(tconn, "Strangeness in tconn->write_ordering %d\n", tconn->write_ordering);
+		drbd_err(connection, "Strangeness in connection->write_ordering %d\n", connection->write_ordering);
 		return -EIO;
 	}
 
@@ -1467,16 +1482,16 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 	atomic_set(&epoch->epoch_size, 0);
 	atomic_set(&epoch->active, 0);
 
-	spin_lock(&tconn->epoch_lock);
-	if (atomic_read(&tconn->current_epoch->epoch_size)) {
-		list_add(&epoch->list, &tconn->current_epoch->list);
-		tconn->current_epoch = epoch;
-		tconn->epochs++;
+	spin_lock(&connection->epoch_lock);
+	if (atomic_read(&connection->current_epoch->epoch_size)) {
+		list_add(&epoch->list, &connection->current_epoch->list);
+		connection->current_epoch = epoch;
+		connection->epochs++;
 	} else {
 		/* The current_epoch got recycled while we allocated this one... */
 		kfree(epoch);
 	}
-	spin_unlock(&tconn->epoch_lock);
+	spin_unlock(&connection->epoch_lock);
 
 	return 0;
 }
@@ -1484,25 +1499,26 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 /* used from receive_RSDataReply (recv_resync_read)
  * and from receive_Data */
 static struct drbd_peer_request *
-read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector,
+read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
 	      int data_size) __must_hold(local)
 {
-	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
+	struct drbd_device *device = peer_device->device;
+	const sector_t capacity = drbd_get_capacity(device->this_bdev);
 	struct drbd_peer_request *peer_req;
 	struct page *page;
 	int dgs, ds, err;
-	void *dig_in = mdev->tconn->int_dig_in;
-	void *dig_vv = mdev->tconn->int_dig_vv;
+	void *dig_in = peer_device->connection->int_dig_in;
+	void *dig_vv = peer_device->connection->int_dig_vv;
 	unsigned long *data;
 
 	dgs = 0;
-	if (mdev->tconn->peer_integrity_tfm) {
-		dgs = crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
+	if (peer_device->connection->peer_integrity_tfm) {
+		dgs = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm);
 		/*
 		 * FIXME: Receive the incoming digest into the receive buffer
 		 *	  here, together with its struct p_data?
 		 */
-		err = drbd_recv_all_warn(mdev->tconn, dig_in, dgs);
+		err = drbd_recv_all_warn(peer_device->connection, dig_in, dgs);
 		if (err)
 			return NULL;
 		data_size -= dgs;
@@ -1516,7 +1532,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector,
 	/* even though we trust out peer,
 	 * we sometimes have to double check. */
 	if (sector + (data_size>>9) > capacity) {
-		dev_err(DEV, "request from peer beyond end of local disk: "
+		drbd_err(device, "request from peer beyond end of local disk: "
 			"capacity: %llus < sector: %llus + size: %u\n",
 			(unsigned long long)capacity,
 			(unsigned long long)sector, data_size);
@@ -1526,7 +1542,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector,
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
 	 * "criss-cross" setup, that might cause write-out on some other DRBD,
 	 * which in turn might block on the other node at this very place.  */
-	peer_req = drbd_alloc_peer_req(mdev, id, sector, data_size, GFP_NOIO);
+	peer_req = drbd_alloc_peer_req(peer_device, id, sector, data_size, GFP_NOIO);
 	if (!peer_req)
 		return NULL;
 
@@ -1538,36 +1554,36 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector,
 	page_chain_for_each(page) {
 		unsigned len = min_t(int, ds, PAGE_SIZE);
 		data = kmap(page);
-		err = drbd_recv_all_warn(mdev->tconn, data, len);
-		if (drbd_insert_fault(mdev, DRBD_FAULT_RECEIVE)) {
-			dev_err(DEV, "Fault injection: Corrupting data on receive\n");
+		err = drbd_recv_all_warn(peer_device->connection, data, len);
+		if (drbd_insert_fault(device, DRBD_FAULT_RECEIVE)) {
+			drbd_err(device, "Fault injection: Corrupting data on receive\n");
 			data[0] = data[0] ^ (unsigned long)-1;
 		}
 		kunmap(page);
 		if (err) {
-			drbd_free_peer_req(mdev, peer_req);
+			drbd_free_peer_req(device, peer_req);
 			return NULL;
 		}
 		ds -= len;
 	}
 
 	if (dgs) {
-		drbd_csum_ee(mdev, mdev->tconn->peer_integrity_tfm, peer_req, dig_vv);
+		drbd_csum_ee(peer_device->connection->peer_integrity_tfm, peer_req, dig_vv);
 		if (memcmp(dig_in, dig_vv, dgs)) {
-			dev_err(DEV, "Digest integrity check FAILED: %llus +%u\n",
+			drbd_err(device, "Digest integrity check FAILED: %llus +%u\n",
 				(unsigned long long)sector, data_size);
-			drbd_free_peer_req(mdev, peer_req);
+			drbd_free_peer_req(device, peer_req);
 			return NULL;
 		}
 	}
-	mdev->recv_cnt += data_size>>9;
+	device->recv_cnt += data_size>>9;
 	return peer_req;
 }
 
 /* drbd_drain_block() just takes a data block
  * out of the socket input buffer, and discards it.
  */
-static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
+static int drbd_drain_block(struct drbd_peer_device *peer_device, int data_size)
 {
 	struct page *page;
 	int err = 0;
@@ -1576,36 +1592,36 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
 	if (!data_size)
 		return 0;
 
-	page = drbd_alloc_pages(mdev, 1, 1);
+	page = drbd_alloc_pages(peer_device, 1, 1);
 
 	data = kmap(page);
 	while (data_size) {
 		unsigned int len = min_t(int, data_size, PAGE_SIZE);
 
-		err = drbd_recv_all_warn(mdev->tconn, data, len);
+		err = drbd_recv_all_warn(peer_device->connection, data, len);
 		if (err)
 			break;
 		data_size -= len;
 	}
 	kunmap(page);
-	drbd_free_pages(mdev, page, 0);
+	drbd_free_pages(peer_device->device, page, 0);
 	return err;
 }
 
-static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
+static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_request *req,
 			   sector_t sector, int data_size)
 {
 	struct bio_vec bvec;
 	struct bvec_iter iter;
 	struct bio *bio;
 	int dgs, err, expect;
-	void *dig_in = mdev->tconn->int_dig_in;
-	void *dig_vv = mdev->tconn->int_dig_vv;
+	void *dig_in = peer_device->connection->int_dig_in;
+	void *dig_vv = peer_device->connection->int_dig_vv;
 
 	dgs = 0;
-	if (mdev->tconn->peer_integrity_tfm) {
-		dgs = crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
-		err = drbd_recv_all_warn(mdev->tconn, dig_in, dgs);
+	if (peer_device->connection->peer_integrity_tfm) {
+		dgs = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm);
+		err = drbd_recv_all_warn(peer_device->connection, dig_in, dgs);
 		if (err)
 			return err;
 		data_size -= dgs;
@@ -1613,15 +1629,15 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
 
 	/* optimistically update recv_cnt.  if receiving fails below,
 	 * we disconnect anyways, and counters will be reset. */
-	mdev->recv_cnt += data_size>>9;
+	peer_device->device->recv_cnt += data_size>>9;
 
 	bio = req->master_bio;
-	D_ASSERT(sector == bio->bi_iter.bi_sector);
+	D_ASSERT(peer_device->device, sector == bio->bi_iter.bi_sector);
 
 	bio_for_each_segment(bvec, bio, iter) {
 		void *mapped = kmap(bvec.bv_page) + bvec.bv_offset;
 		expect = min_t(int, data_size, bvec.bv_len);
-		err = drbd_recv_all_warn(mdev->tconn, mapped, expect);
+		err = drbd_recv_all_warn(peer_device->connection, mapped, expect);
 		kunmap(bvec.bv_page);
 		if (err)
 			return err;
@@ -1629,14 +1645,14 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
 	}
 
 	if (dgs) {
-		drbd_csum_bio(mdev, mdev->tconn->peer_integrity_tfm, bio, dig_vv);
+		drbd_csum_bio(peer_device->connection->peer_integrity_tfm, bio, dig_vv);
 		if (memcmp(dig_in, dig_vv, dgs)) {
-			dev_err(DEV, "Digest integrity check FAILED. Broken NICs?\n");
+			drbd_err(peer_device, "Digest integrity check FAILED. Broken NICs?\n");
 			return -EINVAL;
 		}
 	}
 
-	D_ASSERT(data_size == 0);
+	D_ASSERT(peer_device->device, data_size == 0);
 	return 0;
 }
 
@@ -1648,64 +1664,67 @@ static int e_end_resync_block(struct drbd_work *w, int unused)
 {
 	struct drbd_peer_request *peer_req =
 		container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	sector_t sector = peer_req->i.sector;
 	int err;
 
-	D_ASSERT(drbd_interval_empty(&peer_req->i));
+	D_ASSERT(device, drbd_interval_empty(&peer_req->i));
 
 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
-		drbd_set_in_sync(mdev, sector, peer_req->i.size);
-		err = drbd_send_ack(mdev, P_RS_WRITE_ACK, peer_req);
+		drbd_set_in_sync(device, sector, peer_req->i.size);
+		err = drbd_send_ack(peer_device, P_RS_WRITE_ACK, peer_req);
 	} else {
 		/* Record failure to sync */
-		drbd_rs_failed_io(mdev, sector, peer_req->i.size);
+		drbd_rs_failed_io(device, sector, peer_req->i.size);
 
-		err  = drbd_send_ack(mdev, P_NEG_ACK, peer_req);
+		err  = drbd_send_ack(peer_device, P_NEG_ACK, peer_req);
 	}
-	dec_unacked(mdev);
+	dec_unacked(device);
 
 	return err;
 }
 
-static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_size) __releases(local)
+static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t sector,
+			    int data_size) __releases(local)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_peer_request *peer_req;
 
-	peer_req = read_in_block(mdev, ID_SYNCER, sector, data_size);
+	peer_req = read_in_block(peer_device, ID_SYNCER, sector, data_size);
 	if (!peer_req)
 		goto fail;
 
-	dec_rs_pending(mdev);
+	dec_rs_pending(device);
 
-	inc_unacked(mdev);
+	inc_unacked(device);
 	/* corresponding dec_unacked() in e_end_resync_block()
 	 * respective _drbd_clear_done_ee */
 
 	peer_req->w.cb = e_end_resync_block;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	list_add(&peer_req->w.list, &mdev->sync_ee);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	list_add(&peer_req->w.list, &device->sync_ee);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	atomic_add(data_size >> 9, &mdev->rs_sect_ev);
-	if (drbd_submit_peer_request(mdev, peer_req, WRITE, DRBD_FAULT_RS_WR) == 0)
+	atomic_add(data_size >> 9, &device->rs_sect_ev);
+	if (drbd_submit_peer_request(device, peer_req, WRITE, DRBD_FAULT_RS_WR) == 0)
 		return 0;
 
 	/* don't care for the reason here */
-	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->tconn->req_lock);
+	drbd_err(device, "submit failed, triggering re-connect\n");
+	spin_lock_irq(&device->resource->req_lock);
 	list_del(&peer_req->w.list);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	drbd_free_peer_req(mdev, peer_req);
+	drbd_free_peer_req(device, peer_req);
 fail:
-	put_ldev(mdev);
+	put_ldev(device);
 	return -EIO;
 }
 
 static struct drbd_request *
-find_request(struct drbd_conf *mdev, struct rb_root *root, u64 id,
+find_request(struct drbd_device *device, struct rb_root *root, u64 id,
 	     sector_t sector, bool missing_ok, const char *func)
 {
 	struct drbd_request *req;
@@ -1715,36 +1734,38 @@ find_request(struct drbd_conf *mdev, struct rb_root *root, u64 id,
 	if (drbd_contains_interval(root, sector, &req->i) && req->i.local)
 		return req;
 	if (!missing_ok) {
-		dev_err(DEV, "%s: failed to find request 0x%lx, sector %llus\n", func,
+		drbd_err(device, "%s: failed to find request 0x%lx, sector %llus\n", func,
 			(unsigned long)id, (unsigned long long)sector);
 	}
 	return NULL;
 }
 
-static int receive_DataReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_DataReply(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct drbd_request *req;
 	sector_t sector;
 	int err;
 	struct p_data *p = pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
 	sector = be64_to_cpu(p->sector);
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	req = find_request(mdev, &mdev->read_requests, p->block_id, sector, false, __func__);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	req = find_request(device, &device->read_requests, p->block_id, sector, false, __func__);
+	spin_unlock_irq(&device->resource->req_lock);
 	if (unlikely(!req))
 		return -EIO;
 
 	/* hlist_del(&req->collision) is done in _req_may_be_done, to avoid
 	 * special casing it there for the various failure cases.
 	 * still no race with drbd_fail_pending_reads */
-	err = recv_dless_read(mdev, req, sector, pi->size);
+	err = recv_dless_read(peer_device, req, sector, pi->size);
 	if (!err)
 		req_mod(req, DATA_RECEIVED);
 	/* else: nothing. handled from drbd_disconnect...
@@ -1754,46 +1775,48 @@ static int receive_DataReply(struct drbd_tconn *tconn, struct packet_info *pi)
 	return err;
 }
 
-static int receive_RSDataReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_RSDataReply(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	sector_t sector;
 	int err;
 	struct p_data *p = pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
 	sector = be64_to_cpu(p->sector);
-	D_ASSERT(p->block_id == ID_SYNCER);
+	D_ASSERT(device, p->block_id == ID_SYNCER);
 
-	if (get_ldev(mdev)) {
+	if (get_ldev(device)) {
 		/* data is submitted to disk within recv_resync_read.
 		 * corresponding put_ldev done below on error,
 		 * or in drbd_peer_request_endio. */
-		err = recv_resync_read(mdev, sector, pi->size);
+		err = recv_resync_read(peer_device, sector, pi->size);
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Can not write resync data to local disk.\n");
+			drbd_err(device, "Can not write resync data to local disk.\n");
 
-		err = drbd_drain_block(mdev, pi->size);
+		err = drbd_drain_block(peer_device, pi->size);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p, pi->size);
+		drbd_send_ack_dp(peer_device, P_NEG_ACK, p, pi->size);
 	}
 
-	atomic_add(pi->size >> 9, &mdev->rs_sect_in);
+	atomic_add(pi->size >> 9, &device->rs_sect_in);
 
 	return err;
 }
 
-static void restart_conflicting_writes(struct drbd_conf *mdev,
+static void restart_conflicting_writes(struct drbd_device *device,
 				       sector_t sector, int size)
 {
 	struct drbd_interval *i;
 	struct drbd_request *req;
 
-	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+	drbd_for_each_overlap(i, &device->write_requests, sector, size) {
 		if (!i->local)
 			continue;
 		req = container_of(i, struct drbd_request, i);
@@ -1813,52 +1836,53 @@ static int e_end_block(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req =
 		container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	sector_t sector = peer_req->i.sector;
 	int err = 0, pcmd;
 
 	if (peer_req->flags & EE_SEND_WRITE_ACK) {
 		if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
-			pcmd = (mdev->state.conn >= C_SYNC_SOURCE &&
-				mdev->state.conn <= C_PAUSED_SYNC_T &&
+			pcmd = (device->state.conn >= C_SYNC_SOURCE &&
+				device->state.conn <= C_PAUSED_SYNC_T &&
 				peer_req->flags & EE_MAY_SET_IN_SYNC) ?
 				P_RS_WRITE_ACK : P_WRITE_ACK;
-			err = drbd_send_ack(mdev, pcmd, peer_req);
+			err = drbd_send_ack(peer_device, pcmd, peer_req);
 			if (pcmd == P_RS_WRITE_ACK)
-				drbd_set_in_sync(mdev, sector, peer_req->i.size);
+				drbd_set_in_sync(device, sector, peer_req->i.size);
 		} else {
-			err = drbd_send_ack(mdev, P_NEG_ACK, peer_req);
+			err = drbd_send_ack(peer_device, P_NEG_ACK, peer_req);
 			/* we expect it to be marked out of sync anyways...
 			 * maybe assert this?  */
 		}
-		dec_unacked(mdev);
+		dec_unacked(device);
 	}
 	/* we delete from the conflict detection hash _after_ we sent out the
 	 * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right.  */
 	if (peer_req->flags & EE_IN_INTERVAL_TREE) {
-		spin_lock_irq(&mdev->tconn->req_lock);
-		D_ASSERT(!drbd_interval_empty(&peer_req->i));
-		drbd_remove_epoch_entry_interval(mdev, peer_req);
+		spin_lock_irq(&device->resource->req_lock);
+		D_ASSERT(device, !drbd_interval_empty(&peer_req->i));
+		drbd_remove_epoch_entry_interval(device, peer_req);
 		if (peer_req->flags & EE_RESTART_REQUESTS)
-			restart_conflicting_writes(mdev, sector, peer_req->i.size);
-		spin_unlock_irq(&mdev->tconn->req_lock);
+			restart_conflicting_writes(device, sector, peer_req->i.size);
+		spin_unlock_irq(&device->resource->req_lock);
 	} else
-		D_ASSERT(drbd_interval_empty(&peer_req->i));
+		D_ASSERT(device, drbd_interval_empty(&peer_req->i));
 
-	drbd_may_finish_epoch(mdev->tconn, peer_req->epoch, EV_PUT + (cancel ? EV_CLEANUP : 0));
+	drbd_may_finish_epoch(first_peer_device(device)->connection, peer_req->epoch, EV_PUT + (cancel ? EV_CLEANUP : 0));
 
 	return err;
 }
 
 static int e_send_ack(struct drbd_work *w, enum drbd_packet ack)
 {
-	struct drbd_conf *mdev = w->mdev;
 	struct drbd_peer_request *peer_req =
 		container_of(w, struct drbd_peer_request, w);
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
 	int err;
 
-	err = drbd_send_ack(mdev, ack, peer_req);
-	dec_unacked(mdev);
+	err = drbd_send_ack(peer_device, ack, peer_req);
+	dec_unacked(peer_device->device);
 
 	return err;
 }
@@ -1870,9 +1894,11 @@ static int e_send_superseded(struct drbd_work *w, int unused)
 
 static int e_send_retry_write(struct drbd_work *w, int unused)
 {
-	struct drbd_tconn *tconn = w->mdev->tconn;
+	struct drbd_peer_request *peer_req =
+		container_of(w, struct drbd_peer_request, w);
+	struct drbd_connection *connection = peer_req->peer_device->connection;
 
-	return e_send_ack(w, tconn->agreed_pro_version >= 100 ?
+	return e_send_ack(w, connection->agreed_pro_version >= 100 ?
 			     P_RETRY_WRITE : P_SUPERSEDED);
 }
 
@@ -1891,18 +1917,19 @@ static u32 seq_max(u32 a, u32 b)
 	return seq_greater(a, b) ? a : b;
 }
 
-static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq)
+static void update_peer_seq(struct drbd_peer_device *peer_device, unsigned int peer_seq)
 {
+	struct drbd_device *device = peer_device->device;
 	unsigned int newest_peer_seq;
 
-	if (test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)) {
-		spin_lock(&mdev->peer_seq_lock);
-		newest_peer_seq = seq_max(mdev->peer_seq, peer_seq);
-		mdev->peer_seq = newest_peer_seq;
-		spin_unlock(&mdev->peer_seq_lock);
-		/* wake up only if we actually changed mdev->peer_seq */
+	if (test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags)) {
+		spin_lock(&device->peer_seq_lock);
+		newest_peer_seq = seq_max(device->peer_seq, peer_seq);
+		device->peer_seq = newest_peer_seq;
+		spin_unlock(&device->peer_seq_lock);
+		/* wake up only if we actually changed device->peer_seq */
 		if (peer_seq == newest_peer_seq)
-			wake_up(&mdev->seq_wait);
+			wake_up(&device->seq_wait);
 	}
 }
 
@@ -1912,20 +1939,20 @@ static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2)
 }
 
 /* maybe change sync_ee into interval trees as well? */
-static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_peer_request *peer_req)
+static bool overlapping_resync_write(struct drbd_device *device, struct drbd_peer_request *peer_req)
 {
 	struct drbd_peer_request *rs_req;
 	bool rv = 0;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
+	spin_lock_irq(&device->resource->req_lock);
+	list_for_each_entry(rs_req, &device->sync_ee, w.list) {
 		if (overlaps(peer_req->i.sector, peer_req->i.size,
 			     rs_req->i.sector, rs_req->i.size)) {
 			rv = 1;
 			break;
 		}
 	}
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	return rv;
 }
@@ -1939,9 +1966,9 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_peer_re
  *
  * Note: we don't care for Ack packets overtaking P_DATA packets.
  *
- * In case packet_seq is larger than mdev->peer_seq number, there are
+ * In case packet_seq is larger than device->peer_seq number, there are
  * outstanding packets on the msock. We wait for them to arrive.
- * In case we are the logically next packet, we update mdev->peer_seq
+ * In case we are the logically next packet, we update device->peer_seq
  * ourselves. Correctly handles 32bit wrap around.
  *
  * Assume we have a 10 GBit connection, that is about 1<<30 byte per second,
@@ -1951,19 +1978,20 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_peer_re
  *
  * returns 0 if we may process the packet,
  * -ERESTARTSYS if we were interrupted (by disconnect signal). */
-static int wait_for_and_update_peer_seq(struct drbd_conf *mdev, const u32 peer_seq)
+static int wait_for_and_update_peer_seq(struct drbd_peer_device *peer_device, const u32 peer_seq)
 {
+	struct drbd_device *device = peer_device->device;
 	DEFINE_WAIT(wait);
 	long timeout;
 	int ret = 0, tp;
 
-	if (!test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags))
+	if (!test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags))
 		return 0;
 
-	spin_lock(&mdev->peer_seq_lock);
+	spin_lock(&device->peer_seq_lock);
 	for (;;) {
-		if (!seq_greater(peer_seq - 1, mdev->peer_seq)) {
-			mdev->peer_seq = seq_max(mdev->peer_seq, peer_seq);
+		if (!seq_greater(peer_seq - 1, device->peer_seq)) {
+			device->peer_seq = seq_max(device->peer_seq, peer_seq);
 			break;
 		}
 
@@ -1973,35 +2001,35 @@ static int wait_for_and_update_peer_seq(struct drbd_conf *mdev, const u32 peer_s
 		}
 
 		rcu_read_lock();
-		tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries;
+		tp = rcu_dereference(first_peer_device(device)->connection->net_conf)->two_primaries;
 		rcu_read_unlock();
 
 		if (!tp)
 			break;
 
 		/* Only need to wait if two_primaries is enabled */
-		prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE);
-		spin_unlock(&mdev->peer_seq_lock);
+		prepare_to_wait(&device->seq_wait, &wait, TASK_INTERRUPTIBLE);
+		spin_unlock(&device->peer_seq_lock);
 		rcu_read_lock();
-		timeout = rcu_dereference(mdev->tconn->net_conf)->ping_timeo*HZ/10;
+		timeout = rcu_dereference(peer_device->connection->net_conf)->ping_timeo*HZ/10;
 		rcu_read_unlock();
 		timeout = schedule_timeout(timeout);
-		spin_lock(&mdev->peer_seq_lock);
+		spin_lock(&device->peer_seq_lock);
 		if (!timeout) {
 			ret = -ETIMEDOUT;
-			dev_err(DEV, "Timed out waiting for missing ack packets; disconnecting\n");
+			drbd_err(device, "Timed out waiting for missing ack packets; disconnecting\n");
 			break;
 		}
 	}
-	spin_unlock(&mdev->peer_seq_lock);
-	finish_wait(&mdev->seq_wait, &wait);
+	spin_unlock(&device->peer_seq_lock);
+	finish_wait(&device->seq_wait, &wait);
 	return ret;
 }
 
 /* see also bio_flags_to_wire()
  * DRBD_REQ_*, because we need to semantically map the flags to data packet
  * flags and back. We may replicate to other kernel versions. */
-static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+static unsigned long wire_flags_to_bio(u32 dpf)
 {
 	return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
 		(dpf & DP_FUA ? REQ_FUA : 0) |
@@ -2009,13 +2037,13 @@ static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
 		(dpf & DP_DISCARD ? REQ_DISCARD : 0);
 }
 
-static void fail_postponed_requests(struct drbd_conf *mdev, sector_t sector,
+static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
 				    unsigned int size)
 {
 	struct drbd_interval *i;
 
     repeat:
-	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+	drbd_for_each_overlap(i, &device->write_requests, sector, size) {
 		struct drbd_request *req;
 		struct bio_and_error m;
 
@@ -2026,19 +2054,19 @@ static void fail_postponed_requests(struct drbd_conf *mdev, sector_t sector,
 			continue;
 		req->rq_state &= ~RQ_POSTPONED;
 		__req_mod(req, NEG_ACKED, &m);
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 		if (m.bio)
-			complete_master_bio(mdev, &m);
-		spin_lock_irq(&mdev->tconn->req_lock);
+			complete_master_bio(device, &m);
+		spin_lock_irq(&device->resource->req_lock);
 		goto repeat;
 	}
 }
 
-static int handle_write_conflicts(struct drbd_conf *mdev,
+static int handle_write_conflicts(struct drbd_device *device,
 				  struct drbd_peer_request *peer_req)
 {
-	struct drbd_tconn *tconn = mdev->tconn;
-	bool resolve_conflicts = test_bit(RESOLVE_CONFLICTS, &tconn->flags);
+	struct drbd_connection *connection = peer_req->peer_device->connection;
+	bool resolve_conflicts = test_bit(RESOLVE_CONFLICTS, &connection->flags);
 	sector_t sector = peer_req->i.sector;
 	const unsigned int size = peer_req->i.size;
 	struct drbd_interval *i;
@@ -2049,10 +2077,10 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 	 * Inserting the peer request into the write_requests tree will prevent
 	 * new conflicting local requests from being added.
 	 */
-	drbd_insert_interval(&mdev->write_requests, &peer_req->i);
+	drbd_insert_interval(&device->write_requests, &peer_req->i);
 
     repeat:
-	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+	drbd_for_each_overlap(i, &device->write_requests, sector, size) {
 		if (i == &peer_req->i)
 			continue;
 
@@ -2062,7 +2090,7 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 			 * should not happen in a two-node setup.  Wait for the
 			 * earlier peer request to complete.
 			 */
-			err = drbd_wait_misc(mdev, i);
+			err = drbd_wait_misc(device, i);
 			if (err)
 				goto out;
 			goto repeat;
@@ -2080,18 +2108,18 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 				       (i->size >> 9) >= sector + (size >> 9);
 
 			if (!equal)
-				dev_alert(DEV, "Concurrent writes detected: "
+				drbd_alert(device, "Concurrent writes detected: "
 					       "local=%llus +%u, remote=%llus +%u, "
 					       "assuming %s came first\n",
 					  (unsigned long long)i->sector, i->size,
 					  (unsigned long long)sector, size,
 					  superseded ? "local" : "remote");
 
-			inc_unacked(mdev);
+			inc_unacked(device);
 			peer_req->w.cb = superseded ? e_send_superseded :
 						   e_send_retry_write;
-			list_add_tail(&peer_req->w.list, &mdev->done_ee);
-			wake_asender(mdev->tconn);
+			list_add_tail(&peer_req->w.list, &device->done_ee);
+			wake_asender(connection);
 
 			err = -ENOENT;
 			goto out;
@@ -2100,7 +2128,7 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 				container_of(i, struct drbd_request, i);
 
 			if (!equal)
-				dev_alert(DEV, "Concurrent writes detected: "
+				drbd_alert(device, "Concurrent writes detected: "
 					       "local=%llus +%u, remote=%llus +%u\n",
 					  (unsigned long long)i->sector, i->size,
 					  (unsigned long long)sector, size);
@@ -2118,12 +2146,10 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 				 * request to finish locally before submitting
 				 * the conflicting peer request.
 				 */
-				err = drbd_wait_misc(mdev, &req->i);
+				err = drbd_wait_misc(device, &req->i);
 				if (err) {
-					_conn_request_state(mdev->tconn,
-							    NS(conn, C_TIMEOUT),
-							    CS_HARD);
-					fail_postponed_requests(mdev, sector, size);
+					_conn_request_state(connection, NS(conn, C_TIMEOUT), CS_HARD);
+					fail_postponed_requests(device, sector, size);
 					goto out;
 				}
 				goto repeat;
@@ -2139,14 +2165,15 @@ static int handle_write_conflicts(struct drbd_conf *mdev,
 
     out:
 	if (err)
-		drbd_remove_epoch_entry_interval(mdev, peer_req);
+		drbd_remove_epoch_entry_interval(device, peer_req);
 	return err;
 }
 
 /* mirrored write */
-static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_Data(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	sector_t sector;
 	struct drbd_peer_request *peer_req;
 	struct p_data *p = pi->data;
@@ -2155,17 +2182,18 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 	u32 dp_flags;
 	int err, tp;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	if (!get_ldev(mdev)) {
+	if (!get_ldev(device)) {
 		int err2;
 
-		err = wait_for_and_update_peer_seq(mdev, peer_seq);
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p, pi->size);
-		atomic_inc(&tconn->current_epoch->epoch_size);
-		err2 = drbd_drain_block(mdev, pi->size);
+		err = wait_for_and_update_peer_seq(peer_device, peer_seq);
+		drbd_send_ack_dp(peer_device, P_NEG_ACK, p, pi->size);
+		atomic_inc(&connection->current_epoch->epoch_size);
+		err2 = drbd_drain_block(peer_device, pi->size);
 		if (!err)
 			err = err2;
 		return err;
@@ -2178,61 +2206,61 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 	 */
 
 	sector = be64_to_cpu(p->sector);
-	peer_req = read_in_block(mdev, p->block_id, sector, pi->size);
+	peer_req = read_in_block(peer_device, p->block_id, sector, pi->size);
 	if (!peer_req) {
-		put_ldev(mdev);
+		put_ldev(device);
 		return -EIO;
 	}
 
 	peer_req->w.cb = e_end_block;
 
 	dp_flags = be32_to_cpu(p->dp_flags);
-	rw |= wire_flags_to_bio(mdev, dp_flags);
+	rw |= wire_flags_to_bio(dp_flags);
 	if (peer_req->pages == NULL) {
-		D_ASSERT(peer_req->i.size == 0);
-		D_ASSERT(dp_flags & DP_FLUSH);
+		D_ASSERT(device, peer_req->i.size == 0);
+		D_ASSERT(device, dp_flags & DP_FLUSH);
 	}
 
 	if (dp_flags & DP_MAY_SET_IN_SYNC)
 		peer_req->flags |= EE_MAY_SET_IN_SYNC;
 
-	spin_lock(&tconn->epoch_lock);
-	peer_req->epoch = tconn->current_epoch;
+	spin_lock(&connection->epoch_lock);
+	peer_req->epoch = connection->current_epoch;
 	atomic_inc(&peer_req->epoch->epoch_size);
 	atomic_inc(&peer_req->epoch->active);
-	spin_unlock(&tconn->epoch_lock);
+	spin_unlock(&connection->epoch_lock);
 
 	rcu_read_lock();
-	tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries;
+	tp = rcu_dereference(peer_device->connection->net_conf)->two_primaries;
 	rcu_read_unlock();
 	if (tp) {
 		peer_req->flags |= EE_IN_INTERVAL_TREE;
-		err = wait_for_and_update_peer_seq(mdev, peer_seq);
+		err = wait_for_and_update_peer_seq(peer_device, peer_seq);
 		if (err)
 			goto out_interrupted;
-		spin_lock_irq(&mdev->tconn->req_lock);
-		err = handle_write_conflicts(mdev, peer_req);
+		spin_lock_irq(&device->resource->req_lock);
+		err = handle_write_conflicts(device, peer_req);
 		if (err) {
-			spin_unlock_irq(&mdev->tconn->req_lock);
+			spin_unlock_irq(&device->resource->req_lock);
 			if (err == -ENOENT) {
-				put_ldev(mdev);
+				put_ldev(device);
 				return 0;
 			}
 			goto out_interrupted;
 		}
 	} else {
-		update_peer_seq(mdev, peer_seq);
-		spin_lock_irq(&mdev->tconn->req_lock);
+		update_peer_seq(peer_device, peer_seq);
+		spin_lock_irq(&device->resource->req_lock);
 	}
-	list_add(&peer_req->w.list, &mdev->active_ee);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	list_add(&peer_req->w.list, &device->active_ee);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	if (mdev->state.conn == C_SYNC_TARGET)
-		wait_event(mdev->ee_wait, !overlapping_resync_write(mdev, peer_req));
+	if (device->state.conn == C_SYNC_TARGET)
+		wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req));
 
-	if (mdev->tconn->agreed_pro_version < 100) {
+	if (peer_device->connection->agreed_pro_version < 100) {
 		rcu_read_lock();
-		switch (rcu_dereference(mdev->tconn->net_conf)->wire_protocol) {
+		switch (rcu_dereference(peer_device->connection->net_conf)->wire_protocol) {
 		case DRBD_PROT_C:
 			dp_flags |= DP_SEND_WRITE_ACK;
 			break;
@@ -2245,7 +2273,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 
 	if (dp_flags & DP_SEND_WRITE_ACK) {
 		peer_req->flags |= EE_SEND_WRITE_ACK;
-		inc_unacked(mdev);
+		inc_unacked(device);
 		/* corresponding dec_unacked() in e_end_block()
 		 * respective _drbd_clear_done_ee */
 	}
@@ -2253,34 +2281,34 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 	if (dp_flags & DP_SEND_RECEIVE_ACK) {
 		/* I really don't like it that the receiver thread
 		 * sends on the msock, but anyways */
-		drbd_send_ack(mdev, P_RECV_ACK, peer_req);
+		drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
 	}
 
-	if (mdev->state.pdsk < D_INCONSISTENT) {
+	if (device->state.pdsk < D_INCONSISTENT) {
 		/* In case we have the only disk of the cluster, */
-		drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size);
+		drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size);
 		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
 		peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
-		drbd_al_begin_io(mdev, &peer_req->i, true);
+		drbd_al_begin_io(device, &peer_req->i, true);
 	}
 
-	err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR);
+	err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR);
 	if (!err)
 		return 0;
 
 	/* don't care for the reason here */
-	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->tconn->req_lock);
+	drbd_err(device, "submit failed, triggering re-connect\n");
+	spin_lock_irq(&device->resource->req_lock);
 	list_del(&peer_req->w.list);
-	drbd_remove_epoch_entry_interval(mdev, peer_req);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	drbd_remove_epoch_entry_interval(device, peer_req);
+	spin_unlock_irq(&device->resource->req_lock);
 	if (peer_req->flags & EE_CALL_AL_COMPLETE_IO)
-		drbd_al_complete_io(mdev, &peer_req->i);
+		drbd_al_complete_io(device, &peer_req->i);
 
 out_interrupted:
-	drbd_may_finish_epoch(tconn, peer_req->epoch, EV_PUT + EV_CLEANUP);
-	put_ldev(mdev);
-	drbd_free_peer_req(mdev, peer_req);
+	drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT + EV_CLEANUP);
+	put_ldev(device);
+	drbd_free_peer_req(device, peer_req);
 	return err;
 }
 
@@ -2295,9 +2323,9 @@ out_interrupted:
  * The current sync rate used here uses only the most recent two step marks,
  * to have a short time average so we can react faster.
  */
-int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
+int drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector)
 {
-	struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
+	struct gendisk *disk = device->ldev->backing_bdev->bd_contains->bd_disk;
 	unsigned long db, dt, dbdt;
 	struct lc_element *tmp;
 	int curr_events;
@@ -2305,48 +2333,48 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 	unsigned int c_min_rate;
 
 	rcu_read_lock();
-	c_min_rate = rcu_dereference(mdev->ldev->disk_conf)->c_min_rate;
+	c_min_rate = rcu_dereference(device->ldev->disk_conf)->c_min_rate;
 	rcu_read_unlock();
 
 	/* feature disabled? */
 	if (c_min_rate == 0)
 		return 0;
 
-	spin_lock_irq(&mdev->al_lock);
-	tmp = lc_find(mdev->resync, BM_SECT_TO_EXT(sector));
+	spin_lock_irq(&device->al_lock);
+	tmp = lc_find(device->resync, BM_SECT_TO_EXT(sector));
 	if (tmp) {
 		struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce);
 		if (test_bit(BME_PRIORITY, &bm_ext->flags)) {
-			spin_unlock_irq(&mdev->al_lock);
+			spin_unlock_irq(&device->al_lock);
 			return 0;
 		}
 		/* Do not slow down if app IO is already waiting for this extent */
 	}
-	spin_unlock_irq(&mdev->al_lock);
+	spin_unlock_irq(&device->al_lock);
 
 	curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
 		      (int)part_stat_read(&disk->part0, sectors[1]) -
-			atomic_read(&mdev->rs_sect_ev);
+			atomic_read(&device->rs_sect_ev);
 
-	if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
+	if (!device->rs_last_events || curr_events - device->rs_last_events > 64) {
 		unsigned long rs_left;
 		int i;
 
-		mdev->rs_last_events = curr_events;
+		device->rs_last_events = curr_events;
 
 		/* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
 		 * approx. */
-		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+		i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
 
-		if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
-			rs_left = mdev->ov_left;
+		if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
+			rs_left = device->ov_left;
 		else
-			rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+			rs_left = drbd_bm_total_weight(device) - device->rs_failed;
 
-		dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
+		dt = ((long)jiffies - (long)device->rs_mark_time[i]) / HZ;
 		if (!dt)
 			dt++;
-		db = mdev->rs_mark_left[i] - rs_left;
+		db = device->rs_mark_left[i] - rs_left;
 		dbdt = Bit2KB(db/dt);
 
 		if (dbdt > c_min_rate)
@@ -2356,9 +2384,10 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 }
 
 
-static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_DataRequest(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	sector_t sector;
 	sector_t capacity;
 	struct drbd_peer_request *peer_req;
@@ -2367,58 +2396,59 @@ static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 	unsigned int fault_type;
 	struct p_block_req *p =	pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
-	capacity = drbd_get_capacity(mdev->this_bdev);
+	device = peer_device->device;
+	capacity = drbd_get_capacity(device->this_bdev);
 
 	sector = be64_to_cpu(p->sector);
 	size   = be32_to_cpu(p->blksize);
 
 	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
-		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
+		drbd_err(device, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
 		return -EINVAL;
 	}
 	if (sector + (size>>9) > capacity) {
-		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
+		drbd_err(device, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
 		return -EINVAL;
 	}
 
-	if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
+	if (!get_ldev_if_state(device, D_UP_TO_DATE)) {
 		verb = 1;
 		switch (pi->cmd) {
 		case P_DATA_REQUEST:
-			drbd_send_ack_rp(mdev, P_NEG_DREPLY, p);
+			drbd_send_ack_rp(peer_device, P_NEG_DREPLY, p);
 			break;
 		case P_RS_DATA_REQUEST:
 		case P_CSUM_RS_REQUEST:
 		case P_OV_REQUEST:
-			drbd_send_ack_rp(mdev, P_NEG_RS_DREPLY , p);
+			drbd_send_ack_rp(peer_device, P_NEG_RS_DREPLY , p);
 			break;
 		case P_OV_REPLY:
 			verb = 0;
-			dec_rs_pending(mdev);
-			drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, ID_IN_SYNC);
+			dec_rs_pending(device);
+			drbd_send_ack_ex(peer_device, P_OV_RESULT, sector, size, ID_IN_SYNC);
 			break;
 		default:
 			BUG();
 		}
 		if (verb && __ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Can not satisfy peer's read request, "
+			drbd_err(device, "Can not satisfy peer's read request, "
 			    "no local data.\n");
 
 		/* drain possibly payload */
-		return drbd_drain_block(mdev, pi->size);
+		return drbd_drain_block(peer_device, pi->size);
 	}
 
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
 	 * "criss-cross" setup, that might cause write-out on some other DRBD,
 	 * which in turn might block on the other node at this very place.  */
-	peer_req = drbd_alloc_peer_req(mdev, p->block_id, sector, size, GFP_NOIO);
+	peer_req = drbd_alloc_peer_req(peer_device, p->block_id, sector, size, GFP_NOIO);
 	if (!peer_req) {
-		put_ldev(mdev);
+		put_ldev(device);
 		return -ENOMEM;
 	}
 
@@ -2433,7 +2463,7 @@ static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 		peer_req->w.cb = w_e_end_rsdata_req;
 		fault_type = DRBD_FAULT_RS_RD;
 		/* used in the sector offset progress display */
-		mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+		device->bm_resync_fo = BM_SECT_TO_BIT(sector);
 		break;
 
 	case P_OV_REPLY:
@@ -2449,19 +2479,19 @@ static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 		peer_req->digest = di;
 		peer_req->flags |= EE_HAS_DIGEST;
 
-		if (drbd_recv_all(mdev->tconn, di->digest, pi->size))
+		if (drbd_recv_all(peer_device->connection, di->digest, pi->size))
 			goto out_free_e;
 
 		if (pi->cmd == P_CSUM_RS_REQUEST) {
-			D_ASSERT(mdev->tconn->agreed_pro_version >= 89);
+			D_ASSERT(device, peer_device->connection->agreed_pro_version >= 89);
 			peer_req->w.cb = w_e_end_csum_rs_req;
 			/* used in the sector offset progress display */
-			mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+			device->bm_resync_fo = BM_SECT_TO_BIT(sector);
 		} else if (pi->cmd == P_OV_REPLY) {
 			/* track progress, we may need to throttle */
-			atomic_add(size >> 9, &mdev->rs_sect_in);
+			atomic_add(size >> 9, &device->rs_sect_in);
 			peer_req->w.cb = w_e_end_ov_reply;
-			dec_rs_pending(mdev);
+			dec_rs_pending(device);
 			/* drbd_rs_begin_io done when we sent this request,
 			 * but accounting still needs to be done. */
 			goto submit_for_resync;
@@ -2469,19 +2499,19 @@ static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 		break;
 
 	case P_OV_REQUEST:
-		if (mdev->ov_start_sector == ~(sector_t)0 &&
-		    mdev->tconn->agreed_pro_version >= 90) {
+		if (device->ov_start_sector == ~(sector_t)0 &&
+		    peer_device->connection->agreed_pro_version >= 90) {
 			unsigned long now = jiffies;
 			int i;
-			mdev->ov_start_sector = sector;
-			mdev->ov_position = sector;
-			mdev->ov_left = drbd_bm_bits(mdev) - BM_SECT_TO_BIT(sector);
-			mdev->rs_total = mdev->ov_left;
+			device->ov_start_sector = sector;
+			device->ov_position = sector;
+			device->ov_left = drbd_bm_bits(device) - BM_SECT_TO_BIT(sector);
+			device->rs_total = device->ov_left;
 			for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-				mdev->rs_mark_left[i] = mdev->ov_left;
-				mdev->rs_mark_time[i] = now;
+				device->rs_mark_left[i] = device->ov_left;
+				device->rs_mark_time[i] = now;
 			}
-			dev_info(DEV, "Online Verify start sector: %llu\n",
+			drbd_info(device, "Online Verify start sector: %llu\n",
 					(unsigned long long)sector);
 		}
 		peer_req->w.cb = w_e_end_ov_req;
@@ -2514,57 +2544,61 @@ static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 	 * we would also throttle its application reads.
 	 * In that case, throttling is done on the SyncTarget only.
 	 */
-	if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev, sector))
+	if (device->state.peer != R_PRIMARY && drbd_rs_should_slow_down(device, sector))
 		schedule_timeout_uninterruptible(HZ/10);
-	if (drbd_rs_begin_io(mdev, sector))
+	if (drbd_rs_begin_io(device, sector))
 		goto out_free_e;
 
 submit_for_resync:
-	atomic_add(size >> 9, &mdev->rs_sect_ev);
+	atomic_add(size >> 9, &device->rs_sect_ev);
 
 submit:
-	inc_unacked(mdev);
-	spin_lock_irq(&mdev->tconn->req_lock);
-	list_add_tail(&peer_req->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	inc_unacked(device);
+	spin_lock_irq(&device->resource->req_lock);
+	list_add_tail(&peer_req->w.list, &device->read_ee);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	if (drbd_submit_peer_request(mdev, peer_req, READ, fault_type) == 0)
+	if (drbd_submit_peer_request(device, peer_req, READ, fault_type) == 0)
 		return 0;
 
 	/* don't care for the reason here */
-	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->tconn->req_lock);
+	drbd_err(device, "submit failed, triggering re-connect\n");
+	spin_lock_irq(&device->resource->req_lock);
 	list_del(&peer_req->w.list);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 	/* no drbd_rs_complete_io(), we are dropping the connection anyways */
 
 out_free_e:
-	put_ldev(mdev);
-	drbd_free_peer_req(mdev, peer_req);
+	put_ldev(device);
+	drbd_free_peer_req(device, peer_req);
 	return -EIO;
 }
 
-static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
+/**
+ * drbd_asb_recover_0p  -  Recover after split-brain with no remaining primaries
+ */
+static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold(local)
 {
+	struct drbd_device *device = peer_device->device;
 	int self, peer, rv = -100;
 	unsigned long ch_self, ch_peer;
 	enum drbd_after_sb_p after_sb_0p;
 
-	self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
-	peer = mdev->p_uuid[UI_BITMAP] & 1;
+	self = device->ldev->md.uuid[UI_BITMAP] & 1;
+	peer = device->p_uuid[UI_BITMAP] & 1;
 
-	ch_peer = mdev->p_uuid[UI_SIZE];
-	ch_self = mdev->comm_bm_set;
+	ch_peer = device->p_uuid[UI_SIZE];
+	ch_self = device->comm_bm_set;
 
 	rcu_read_lock();
-	after_sb_0p = rcu_dereference(mdev->tconn->net_conf)->after_sb_0p;
+	after_sb_0p = rcu_dereference(peer_device->connection->net_conf)->after_sb_0p;
 	rcu_read_unlock();
 	switch (after_sb_0p) {
 	case ASB_CONSENSUS:
 	case ASB_DISCARD_SECONDARY:
 	case ASB_CALL_HELPER:
 	case ASB_VIOLENTLY:
-		dev_err(DEV, "Configuration error.\n");
+		drbd_err(device, "Configuration error.\n");
 		break;
 	case ASB_DISCONNECT:
 		break;
@@ -2588,11 +2622,11 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 			break;
 		}
 		/* Else fall through to one of the other strategies... */
-		dev_warn(DEV, "Discard younger/older primary did not find a decision\n"
+		drbd_warn(device, "Discard younger/older primary did not find a decision\n"
 		     "Using discard-least-changes instead\n");
 	case ASB_DISCARD_ZERO_CHG:
 		if (ch_peer == 0 && ch_self == 0) {
-			rv = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)
+			rv = test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags)
 				? -1 : 1;
 			break;
 		} else {
@@ -2608,7 +2642,7 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 			rv =  1;
 		else /* ( ch_self == ch_peer ) */
 		     /* Well, then use something else. */
-			rv = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)
+			rv = test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags)
 				? -1 : 1;
 		break;
 	case ASB_DISCARD_LOCAL:
@@ -2621,13 +2655,17 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 	return rv;
 }
 
-static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
+/**
+ * drbd_asb_recover_1p  -  Recover after split-brain with one remaining primary
+ */
+static int drbd_asb_recover_1p(struct drbd_peer_device *peer_device) __must_hold(local)
 {
+	struct drbd_device *device = peer_device->device;
 	int hg, rv = -100;
 	enum drbd_after_sb_p after_sb_1p;
 
 	rcu_read_lock();
-	after_sb_1p = rcu_dereference(mdev->tconn->net_conf)->after_sb_1p;
+	after_sb_1p = rcu_dereference(peer_device->connection->net_conf)->after_sb_1p;
 	rcu_read_unlock();
 	switch (after_sb_1p) {
 	case ASB_DISCARD_YOUNGER_PRI:
@@ -2636,35 +2674,35 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 	case ASB_DISCARD_LOCAL:
 	case ASB_DISCARD_REMOTE:
 	case ASB_DISCARD_ZERO_CHG:
-		dev_err(DEV, "Configuration error.\n");
+		drbd_err(device, "Configuration error.\n");
 		break;
 	case ASB_DISCONNECT:
 		break;
 	case ASB_CONSENSUS:
-		hg = drbd_asb_recover_0p(mdev);
-		if (hg == -1 && mdev->state.role == R_SECONDARY)
+		hg = drbd_asb_recover_0p(peer_device);
+		if (hg == -1 && device->state.role == R_SECONDARY)
 			rv = hg;
-		if (hg == 1  && mdev->state.role == R_PRIMARY)
+		if (hg == 1  && device->state.role == R_PRIMARY)
 			rv = hg;
 		break;
 	case ASB_VIOLENTLY:
-		rv = drbd_asb_recover_0p(mdev);
+		rv = drbd_asb_recover_0p(peer_device);
 		break;
 	case ASB_DISCARD_SECONDARY:
-		return mdev->state.role == R_PRIMARY ? 1 : -1;
+		return device->state.role == R_PRIMARY ? 1 : -1;
 	case ASB_CALL_HELPER:
-		hg = drbd_asb_recover_0p(mdev);
-		if (hg == -1 && mdev->state.role == R_PRIMARY) {
+		hg = drbd_asb_recover_0p(peer_device);
+		if (hg == -1 && device->state.role == R_PRIMARY) {
 			enum drbd_state_rv rv2;
 
 			 /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
 			  * we might be here in C_WF_REPORT_PARAMS which is transient.
 			  * we do not need to wait for the after state change work either. */
-			rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+			rv2 = drbd_change_state(device, CS_VERBOSE, NS(role, R_SECONDARY));
 			if (rv2 != SS_SUCCESS) {
-				drbd_khelper(mdev, "pri-lost-after-sb");
+				drbd_khelper(device, "pri-lost-after-sb");
 			} else {
-				dev_warn(DEV, "Successfully gave up primary role.\n");
+				drbd_warn(device, "Successfully gave up primary role.\n");
 				rv = hg;
 			}
 		} else
@@ -2674,13 +2712,17 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 	return rv;
 }
 
-static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
+/**
+ * drbd_asb_recover_2p  -  Recover after split-brain with two remaining primaries
+ */
+static int drbd_asb_recover_2p(struct drbd_peer_device *peer_device) __must_hold(local)
 {
+	struct drbd_device *device = peer_device->device;
 	int hg, rv = -100;
 	enum drbd_after_sb_p after_sb_2p;
 
 	rcu_read_lock();
-	after_sb_2p = rcu_dereference(mdev->tconn->net_conf)->after_sb_2p;
+	after_sb_2p = rcu_dereference(peer_device->connection->net_conf)->after_sb_2p;
 	rcu_read_unlock();
 	switch (after_sb_2p) {
 	case ASB_DISCARD_YOUNGER_PRI:
@@ -2691,26 +2733,26 @@ static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 	case ASB_CONSENSUS:
 	case ASB_DISCARD_SECONDARY:
 	case ASB_DISCARD_ZERO_CHG:
-		dev_err(DEV, "Configuration error.\n");
+		drbd_err(device, "Configuration error.\n");
 		break;
 	case ASB_VIOLENTLY:
-		rv = drbd_asb_recover_0p(mdev);
+		rv = drbd_asb_recover_0p(peer_device);
 		break;
 	case ASB_DISCONNECT:
 		break;
 	case ASB_CALL_HELPER:
-		hg = drbd_asb_recover_0p(mdev);
+		hg = drbd_asb_recover_0p(peer_device);
 		if (hg == -1) {
 			enum drbd_state_rv rv2;
 
 			 /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
 			  * we might be here in C_WF_REPORT_PARAMS which is transient.
 			  * we do not need to wait for the after state change work either. */
-			rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+			rv2 = drbd_change_state(device, CS_VERBOSE, NS(role, R_SECONDARY));
 			if (rv2 != SS_SUCCESS) {
-				drbd_khelper(mdev, "pri-lost-after-sb");
+				drbd_khelper(device, "pri-lost-after-sb");
 			} else {
-				dev_warn(DEV, "Successfully gave up primary role.\n");
+				drbd_warn(device, "Successfully gave up primary role.\n");
 				rv = hg;
 			}
 		} else
@@ -2720,14 +2762,14 @@ static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 	return rv;
 }
 
-static void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid,
+static void drbd_uuid_dump(struct drbd_device *device, char *text, u64 *uuid,
 			   u64 bits, u64 flags)
 {
 	if (!uuid) {
-		dev_info(DEV, "%s uuid info vanished while I was looking!\n", text);
+		drbd_info(device, "%s uuid info vanished while I was looking!\n", text);
 		return;
 	}
-	dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX bits:%llu flags:%llX\n",
+	drbd_info(device, "%s %016llX:%016llX:%016llX:%016llX bits:%llu flags:%llX\n",
 	     text,
 	     (unsigned long long)uuid[UI_CURRENT],
 	     (unsigned long long)uuid[UI_BITMAP],
@@ -2749,13 +2791,13 @@ static void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid,
 -1091   requires proto 91
 -1096   requires proto 96
  */
-static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local)
+static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_hold(local)
 {
 	u64 self, peer;
 	int i, j;
 
-	self = mdev->ldev->md.uuid[UI_CURRENT] & ~((u64)1);
-	peer = mdev->p_uuid[UI_CURRENT] & ~((u64)1);
+	self = device->ldev->md.uuid[UI_CURRENT] & ~((u64)1);
+	peer = device->p_uuid[UI_CURRENT] & ~((u64)1);
 
 	*rule_nr = 10;
 	if (self == UUID_JUST_CREATED && peer == UUID_JUST_CREATED)
@@ -2774,46 +2816,46 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 	if (self == peer) {
 		int rct, dc; /* roles at crash time */
 
-		if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) {
+		if (device->p_uuid[UI_BITMAP] == (u64)0 && device->ldev->md.uuid[UI_BITMAP] != (u64)0) {
 
-			if (mdev->tconn->agreed_pro_version < 91)
+			if (first_peer_device(device)->connection->agreed_pro_version < 91)
 				return -1091;
 
-			if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
-			    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
-				dev_info(DEV, "was SyncSource, missed the resync finished event, corrected myself:\n");
-				drbd_uuid_move_history(mdev);
-				mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
-				mdev->ldev->md.uuid[UI_BITMAP] = 0;
+			if ((device->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (device->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
+			    (device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (device->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
+				drbd_info(device, "was SyncSource, missed the resync finished event, corrected myself:\n");
+				drbd_uuid_move_history(device);
+				device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];
+				device->ldev->md.uuid[UI_BITMAP] = 0;
 
-				drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
-					       mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
+				drbd_uuid_dump(device, "self", device->ldev->md.uuid,
+					       device->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(device) : 0, 0);
 				*rule_nr = 34;
 			} else {
-				dev_info(DEV, "was SyncSource (peer failed to write sync_uuid)\n");
+				drbd_info(device, "was SyncSource (peer failed to write sync_uuid)\n");
 				*rule_nr = 36;
 			}
 
 			return 1;
 		}
 
-		if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) {
+		if (device->ldev->md.uuid[UI_BITMAP] == (u64)0 && device->p_uuid[UI_BITMAP] != (u64)0) {
 
-			if (mdev->tconn->agreed_pro_version < 91)
+			if (first_peer_device(device)->connection->agreed_pro_version < 91)
 				return -1091;
 
-			if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) &&
-			    (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) {
-				dev_info(DEV, "was SyncTarget, peer missed the resync finished event, corrected peer:\n");
+			if ((device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (device->p_uuid[UI_BITMAP] & ~((u64)1)) &&
+			    (device->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (device->p_uuid[UI_HISTORY_START] & ~((u64)1))) {
+				drbd_info(device, "was SyncTarget, peer missed the resync finished event, corrected peer:\n");
 
-				mdev->p_uuid[UI_HISTORY_START + 1] = mdev->p_uuid[UI_HISTORY_START];
-				mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_BITMAP];
-				mdev->p_uuid[UI_BITMAP] = 0UL;
+				device->p_uuid[UI_HISTORY_START + 1] = device->p_uuid[UI_HISTORY_START];
+				device->p_uuid[UI_HISTORY_START] = device->p_uuid[UI_BITMAP];
+				device->p_uuid[UI_BITMAP] = 0UL;
 
-				drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
+				drbd_uuid_dump(device, "peer", device->p_uuid, device->p_uuid[UI_SIZE], device->p_uuid[UI_FLAGS]);
 				*rule_nr = 35;
 			} else {
-				dev_info(DEV, "was SyncTarget (failed to write sync_uuid)\n");
+				drbd_info(device, "was SyncTarget (failed to write sync_uuid)\n");
 				*rule_nr = 37;
 			}
 
@@ -2821,8 +2863,8 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 		}
 
 		/* Common power [off|failure] */
-		rct = (test_bit(CRASHED_PRIMARY, &mdev->flags) ? 1 : 0) +
-			(mdev->p_uuid[UI_FLAGS] & 2);
+		rct = (test_bit(CRASHED_PRIMARY, &device->flags) ? 1 : 0) +
+			(device->p_uuid[UI_FLAGS] & 2);
 		/* lowest bit is set when we were primary,
 		 * next bit (weight 2) is set when peer was primary */
 		*rule_nr = 40;
@@ -2832,72 +2874,72 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 		case 1: /*  self_pri && !peer_pri */ return 1;
 		case 2: /* !self_pri &&  peer_pri */ return -1;
 		case 3: /*  self_pri &&  peer_pri */
-			dc = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags);
+			dc = test_bit(RESOLVE_CONFLICTS, &first_peer_device(device)->connection->flags);
 			return dc ? -1 : 1;
 		}
 	}
 
 	*rule_nr = 50;
-	peer = mdev->p_uuid[UI_BITMAP] & ~((u64)1);
+	peer = device->p_uuid[UI_BITMAP] & ~((u64)1);
 	if (self == peer)
 		return -1;
 
 	*rule_nr = 51;
-	peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
+	peer = device->p_uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (mdev->tconn->agreed_pro_version < 96 ?
-		    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
-		    (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
-		    peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) {
+		if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+		    (device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
+		    (device->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
+		    peer + UUID_NEW_BM_OFFSET == (device->p_uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of the peer's UUIDs. */
 
-			if (mdev->tconn->agreed_pro_version < 91)
+			if (first_peer_device(device)->connection->agreed_pro_version < 91)
 				return -1091;
 
-			mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START];
-			mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1];
+			device->p_uuid[UI_BITMAP] = device->p_uuid[UI_HISTORY_START];
+			device->p_uuid[UI_HISTORY_START] = device->p_uuid[UI_HISTORY_START + 1];
 
-			dev_info(DEV, "Lost last syncUUID packet, corrected:\n");
-			drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
+			drbd_info(device, "Lost last syncUUID packet, corrected:\n");
+			drbd_uuid_dump(device, "peer", device->p_uuid, device->p_uuid[UI_SIZE], device->p_uuid[UI_FLAGS]);
 
 			return -1;
 		}
 	}
 
 	*rule_nr = 60;
-	self = mdev->ldev->md.uuid[UI_CURRENT] & ~((u64)1);
+	self = device->ldev->md.uuid[UI_CURRENT] & ~((u64)1);
 	for (i = UI_HISTORY_START; i <= UI_HISTORY_END; i++) {
-		peer = mdev->p_uuid[i] & ~((u64)1);
+		peer = device->p_uuid[i] & ~((u64)1);
 		if (self == peer)
 			return -2;
 	}
 
 	*rule_nr = 70;
-	self = mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1);
-	peer = mdev->p_uuid[UI_CURRENT] & ~((u64)1);
+	self = device->ldev->md.uuid[UI_BITMAP] & ~((u64)1);
+	peer = device->p_uuid[UI_CURRENT] & ~((u64)1);
 	if (self == peer)
 		return 1;
 
 	*rule_nr = 71;
-	self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
+	self = device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (mdev->tconn->agreed_pro_version < 96 ?
-		    (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
-		    (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
-		    self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
+		if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+		    (device->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
+		    (device->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
+		    self + UUID_NEW_BM_OFFSET == (device->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of our UUIDs. */
 
-			if (mdev->tconn->agreed_pro_version < 91)
+			if (first_peer_device(device)->connection->agreed_pro_version < 91)
 				return -1091;
 
-			__drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
-			__drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
+			__drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_HISTORY_START]);
+			__drbd_uuid_set(device, UI_HISTORY_START, device->ldev->md.uuid[UI_HISTORY_START + 1]);
 
-			dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
-			drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
-				       mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
+			drbd_info(device, "Last syncUUID did not get through, corrected:\n");
+			drbd_uuid_dump(device, "self", device->ldev->md.uuid,
+				       device->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(device) : 0, 0);
 
 			return 1;
 		}
@@ -2905,24 +2947,24 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 
 
 	*rule_nr = 80;
-	peer = mdev->p_uuid[UI_CURRENT] & ~((u64)1);
+	peer = device->p_uuid[UI_CURRENT] & ~((u64)1);
 	for (i = UI_HISTORY_START; i <= UI_HISTORY_END; i++) {
-		self = mdev->ldev->md.uuid[i] & ~((u64)1);
+		self = device->ldev->md.uuid[i] & ~((u64)1);
 		if (self == peer)
 			return 2;
 	}
 
 	*rule_nr = 90;
-	self = mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1);
-	peer = mdev->p_uuid[UI_BITMAP] & ~((u64)1);
+	self = device->ldev->md.uuid[UI_BITMAP] & ~((u64)1);
+	peer = device->p_uuid[UI_BITMAP] & ~((u64)1);
 	if (self == peer && self != ((u64)0))
 		return 100;
 
 	*rule_nr = 100;
 	for (i = UI_HISTORY_START; i <= UI_HISTORY_END; i++) {
-		self = mdev->ldev->md.uuid[i] & ~((u64)1);
+		self = device->ldev->md.uuid[i] & ~((u64)1);
 		for (j = UI_HISTORY_START; j <= UI_HISTORY_END; j++) {
-			peer = mdev->p_uuid[j] & ~((u64)1);
+			peer = device->p_uuid[j] & ~((u64)1);
 			if (self == peer)
 				return -100;
 		}
@@ -2934,36 +2976,38 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 /* drbd_sync_handshake() returns the new conn state on success, or
    CONN_MASK (-1) on failure.
  */
-static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_role peer_role,
+static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
+					   enum drbd_role peer_role,
 					   enum drbd_disk_state peer_disk) __must_hold(local)
 {
+	struct drbd_device *device = peer_device->device;
 	enum drbd_conns rv = C_MASK;
 	enum drbd_disk_state mydisk;
 	struct net_conf *nc;
 	int hg, rule_nr, rr_conflict, tentative;
 
-	mydisk = mdev->state.disk;
+	mydisk = device->state.disk;
 	if (mydisk == D_NEGOTIATING)
-		mydisk = mdev->new_state_tmp.disk;
+		mydisk = device->new_state_tmp.disk;
 
-	dev_info(DEV, "drbd_sync_handshake:\n");
+	drbd_info(device, "drbd_sync_handshake:\n");
 
-	spin_lock_irq(&mdev->ldev->md.uuid_lock);
-	drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, mdev->comm_bm_set, 0);
-	drbd_uuid_dump(mdev, "peer", mdev->p_uuid,
-		       mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
+	spin_lock_irq(&device->ldev->md.uuid_lock);
+	drbd_uuid_dump(device, "self", device->ldev->md.uuid, device->comm_bm_set, 0);
+	drbd_uuid_dump(device, "peer", device->p_uuid,
+		       device->p_uuid[UI_SIZE], device->p_uuid[UI_FLAGS]);
 
-	hg = drbd_uuid_compare(mdev, &rule_nr);
-	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
+	hg = drbd_uuid_compare(device, &rule_nr);
+	spin_unlock_irq(&device->ldev->md.uuid_lock);
 
-	dev_info(DEV, "uuid_compare()=%d by rule %d\n", hg, rule_nr);
+	drbd_info(device, "uuid_compare()=%d by rule %d\n", hg, rule_nr);
 
 	if (hg == -1000) {
-		dev_alert(DEV, "Unrelated data, aborting!\n");
+		drbd_alert(device, "Unrelated data, aborting!\n");
 		return C_MASK;
 	}
 	if (hg < -1000) {
-		dev_alert(DEV, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000);
+		drbd_alert(device, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000);
 		return C_MASK;
 	}
 
@@ -2973,38 +3017,38 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 		hg = mydisk > D_INCONSISTENT ? 1 : -1;
 		if (f)
 			hg = hg*2;
-		dev_info(DEV, "Becoming sync %s due to disk states.\n",
+		drbd_info(device, "Becoming sync %s due to disk states.\n",
 		     hg > 0 ? "source" : "target");
 	}
 
 	if (abs(hg) == 100)
-		drbd_khelper(mdev, "initial-split-brain");
+		drbd_khelper(device, "initial-split-brain");
 
 	rcu_read_lock();
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(peer_device->connection->net_conf);
 
 	if (hg == 100 || (hg == -100 && nc->always_asbp)) {
-		int pcount = (mdev->state.role == R_PRIMARY)
+		int pcount = (device->state.role == R_PRIMARY)
 			   + (peer_role == R_PRIMARY);
 		int forced = (hg == -100);
 
 		switch (pcount) {
 		case 0:
-			hg = drbd_asb_recover_0p(mdev);
+			hg = drbd_asb_recover_0p(peer_device);
 			break;
 		case 1:
-			hg = drbd_asb_recover_1p(mdev);
+			hg = drbd_asb_recover_1p(peer_device);
 			break;
 		case 2:
-			hg = drbd_asb_recover_2p(mdev);
+			hg = drbd_asb_recover_2p(peer_device);
 			break;
 		}
 		if (abs(hg) < 100) {
-			dev_warn(DEV, "Split-Brain detected, %d primaries, "
+			drbd_warn(device, "Split-Brain detected, %d primaries, "
 			     "automatically solved. Sync from %s node\n",
 			     pcount, (hg < 0) ? "peer" : "this");
 			if (forced) {
-				dev_warn(DEV, "Doing a full sync, since"
+				drbd_warn(device, "Doing a full sync, since"
 				     " UUIDs where ambiguous.\n");
 				hg = hg*2;
 			}
@@ -3012,13 +3056,13 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 	}
 
 	if (hg == -100) {
-		if (test_bit(DISCARD_MY_DATA, &mdev->flags) && !(mdev->p_uuid[UI_FLAGS]&1))
+		if (test_bit(DISCARD_MY_DATA, &device->flags) && !(device->p_uuid[UI_FLAGS]&1))
 			hg = -1;
-		if (!test_bit(DISCARD_MY_DATA, &mdev->flags) && (mdev->p_uuid[UI_FLAGS]&1))
+		if (!test_bit(DISCARD_MY_DATA, &device->flags) && (device->p_uuid[UI_FLAGS]&1))
 			hg = 1;
 
 		if (abs(hg) < 100)
-			dev_warn(DEV, "Split-Brain detected, manually solved. "
+			drbd_warn(device, "Split-Brain detected, manually solved. "
 			     "Sync from %s node\n",
 			     (hg < 0) ? "peer" : "this");
 	}
@@ -3031,44 +3075,44 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 		 * after an attempted attach on a diskless node.
 		 * We just refuse to attach -- well, we drop the "connection"
 		 * to that disk, in a way... */
-		dev_alert(DEV, "Split-Brain detected but unresolved, dropping connection!\n");
-		drbd_khelper(mdev, "split-brain");
+		drbd_alert(device, "Split-Brain detected but unresolved, dropping connection!\n");
+		drbd_khelper(device, "split-brain");
 		return C_MASK;
 	}
 
 	if (hg > 0 && mydisk <= D_INCONSISTENT) {
-		dev_err(DEV, "I shall become SyncSource, but I am inconsistent!\n");
+		drbd_err(device, "I shall become SyncSource, but I am inconsistent!\n");
 		return C_MASK;
 	}
 
 	if (hg < 0 && /* by intention we do not use mydisk here. */
-	    mdev->state.role == R_PRIMARY && mdev->state.disk >= D_CONSISTENT) {
+	    device->state.role == R_PRIMARY && device->state.disk >= D_CONSISTENT) {
 		switch (rr_conflict) {
 		case ASB_CALL_HELPER:
-			drbd_khelper(mdev, "pri-lost");
+			drbd_khelper(device, "pri-lost");
 			/* fall through */
 		case ASB_DISCONNECT:
-			dev_err(DEV, "I shall become SyncTarget, but I am primary!\n");
+			drbd_err(device, "I shall become SyncTarget, but I am primary!\n");
 			return C_MASK;
 		case ASB_VIOLENTLY:
-			dev_warn(DEV, "Becoming SyncTarget, violating the stable-data"
+			drbd_warn(device, "Becoming SyncTarget, violating the stable-data"
 			     "assumption\n");
 		}
 	}
 
-	if (tentative || test_bit(CONN_DRY_RUN, &mdev->tconn->flags)) {
+	if (tentative || test_bit(CONN_DRY_RUN, &peer_device->connection->flags)) {
 		if (hg == 0)
-			dev_info(DEV, "dry-run connect: No resync, would become Connected immediately.\n");
+			drbd_info(device, "dry-run connect: No resync, would become Connected immediately.\n");
 		else
-			dev_info(DEV, "dry-run connect: Would become %s, doing a %s resync.",
+			drbd_info(device, "dry-run connect: Would become %s, doing a %s resync.",
 				 drbd_conn_str(hg > 0 ? C_SYNC_SOURCE : C_SYNC_TARGET),
 				 abs(hg) >= 2 ? "full" : "bit-map based");
 		return C_MASK;
 	}
 
 	if (abs(hg) >= 2) {
-		dev_info(DEV, "Writing the whole bitmap, full sync required after drbd_sync_handshake.\n");
-		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake",
+		drbd_info(device, "Writing the whole bitmap, full sync required after drbd_sync_handshake.\n");
+		if (drbd_bitmap_io(device, &drbd_bmio_set_n_write, "set_n_write from sync_handshake",
 					BM_LOCKED_SET_ALLOWED))
 			return C_MASK;
 	}
@@ -3079,9 +3123,9 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 		rv = C_WF_BITMAP_T;
 	} else {
 		rv = C_CONNECTED;
-		if (drbd_bm_total_weight(mdev)) {
-			dev_info(DEV, "No resync, but %lu bits in bitmap!\n",
-			     drbd_bm_total_weight(mdev));
+		if (drbd_bm_total_weight(device)) {
+			drbd_info(device, "No resync, but %lu bits in bitmap!\n",
+			     drbd_bm_total_weight(device));
 		}
 	}
 
@@ -3102,7 +3146,7 @@ static enum drbd_after_sb_p convert_after_sb(enum drbd_after_sb_p peer)
 	return peer;
 }
 
-static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_protocol(struct drbd_connection *connection, struct packet_info *pi)
 {
 	struct p_protocol *p = pi->data;
 	enum drbd_after_sb_p p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
@@ -3120,58 +3164,58 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
 	cf		= be32_to_cpu(p->conn_flags);
 	p_discard_my_data = cf & CF_DISCARD_MY_DATA;
 
-	if (tconn->agreed_pro_version >= 87) {
+	if (connection->agreed_pro_version >= 87) {
 		int err;
 
 		if (pi->size > sizeof(integrity_alg))
 			return -EIO;
-		err = drbd_recv_all(tconn, integrity_alg, pi->size);
+		err = drbd_recv_all(connection, integrity_alg, pi->size);
 		if (err)
 			return err;
 		integrity_alg[SHARED_SECRET_MAX - 1] = 0;
 	}
 
 	if (pi->cmd != P_PROTOCOL_UPDATE) {
-		clear_bit(CONN_DRY_RUN, &tconn->flags);
+		clear_bit(CONN_DRY_RUN, &connection->flags);
 
 		if (cf & CF_DRY_RUN)
-			set_bit(CONN_DRY_RUN, &tconn->flags);
+			set_bit(CONN_DRY_RUN, &connection->flags);
 
 		rcu_read_lock();
-		nc = rcu_dereference(tconn->net_conf);
+		nc = rcu_dereference(connection->net_conf);
 
 		if (p_proto != nc->wire_protocol) {
-			conn_err(tconn, "incompatible %s settings\n", "protocol");
+			drbd_err(connection, "incompatible %s settings\n", "protocol");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (convert_after_sb(p_after_sb_0p) != nc->after_sb_0p) {
-			conn_err(tconn, "incompatible %s settings\n", "after-sb-0pri");
+			drbd_err(connection, "incompatible %s settings\n", "after-sb-0pri");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (convert_after_sb(p_after_sb_1p) != nc->after_sb_1p) {
-			conn_err(tconn, "incompatible %s settings\n", "after-sb-1pri");
+			drbd_err(connection, "incompatible %s settings\n", "after-sb-1pri");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (convert_after_sb(p_after_sb_2p) != nc->after_sb_2p) {
-			conn_err(tconn, "incompatible %s settings\n", "after-sb-2pri");
+			drbd_err(connection, "incompatible %s settings\n", "after-sb-2pri");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (p_discard_my_data && nc->discard_my_data) {
-			conn_err(tconn, "incompatible %s settings\n", "discard-my-data");
+			drbd_err(connection, "incompatible %s settings\n", "discard-my-data");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (p_two_primaries != nc->two_primaries) {
-			conn_err(tconn, "incompatible %s settings\n", "allow-two-primaries");
+			drbd_err(connection, "incompatible %s settings\n", "allow-two-primaries");
 			goto disconnect_rcu_unlock;
 		}
 
 		if (strcmp(integrity_alg, nc->integrity_alg)) {
-			conn_err(tconn, "incompatible %s settings\n", "data-integrity-alg");
+			drbd_err(connection, "incompatible %s settings\n", "data-integrity-alg");
 			goto disconnect_rcu_unlock;
 		}
 
@@ -3192,7 +3236,7 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
 
 		peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC);
 		if (!peer_integrity_tfm) {
-			conn_err(tconn, "peer data-integrity-alg %s not supported\n",
+			drbd_err(connection, "peer data-integrity-alg %s not supported\n",
 				 integrity_alg);
 			goto disconnect;
 		}
@@ -3201,20 +3245,20 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
 		int_dig_in = kmalloc(hash_size, GFP_KERNEL);
 		int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
 		if (!(int_dig_in && int_dig_vv)) {
-			conn_err(tconn, "Allocation of buffers for data integrity checking failed\n");
+			drbd_err(connection, "Allocation of buffers for data integrity checking failed\n");
 			goto disconnect;
 		}
 	}
 
 	new_net_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL);
 	if (!new_net_conf) {
-		conn_err(tconn, "Allocation of new net_conf failed\n");
+		drbd_err(connection, "Allocation of new net_conf failed\n");
 		goto disconnect;
 	}
 
-	mutex_lock(&tconn->data.mutex);
-	mutex_lock(&tconn->conf_update);
-	old_net_conf = tconn->net_conf;
+	mutex_lock(&connection->data.mutex);
+	mutex_lock(&connection->resource->conf_update);
+	old_net_conf = connection->net_conf;
 	*new_net_conf = *old_net_conf;
 
 	new_net_conf->wire_protocol = p_proto;
@@ -3223,19 +3267,19 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
 	new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p);
 	new_net_conf->two_primaries = p_two_primaries;
 
-	rcu_assign_pointer(tconn->net_conf, new_net_conf);
-	mutex_unlock(&tconn->conf_update);
-	mutex_unlock(&tconn->data.mutex);
+	rcu_assign_pointer(connection->net_conf, new_net_conf);
+	mutex_unlock(&connection->resource->conf_update);
+	mutex_unlock(&connection->data.mutex);
 
-	crypto_free_hash(tconn->peer_integrity_tfm);
-	kfree(tconn->int_dig_in);
-	kfree(tconn->int_dig_vv);
-	tconn->peer_integrity_tfm = peer_integrity_tfm;
-	tconn->int_dig_in = int_dig_in;
-	tconn->int_dig_vv = int_dig_vv;
+	crypto_free_hash(connection->peer_integrity_tfm);
+	kfree(connection->int_dig_in);
+	kfree(connection->int_dig_vv);
+	connection->peer_integrity_tfm = peer_integrity_tfm;
+	connection->int_dig_in = int_dig_in;
+	connection->int_dig_vv = int_dig_vv;
 
 	if (strcmp(old_net_conf->integrity_alg, integrity_alg))
-		conn_info(tconn, "peer data-integrity-alg: %s\n",
+		drbd_info(connection, "peer data-integrity-alg: %s\n",
 			  integrity_alg[0] ? integrity_alg : "(none)");
 
 	synchronize_rcu();
@@ -3248,7 +3292,7 @@ disconnect:
 	crypto_free_hash(peer_integrity_tfm);
 	kfree(int_dig_in);
 	kfree(int_dig_vv);
-	conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+	conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 	return -EIO;
 }
 
@@ -3257,7 +3301,8 @@ disconnect:
  * return: NULL (alg name was "")
  *         ERR_PTR(error) if something goes wrong
  *         or the crypto hash ptr, if it worked out ok. */
-struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev,
+static
+struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device,
 		const char *alg, const char *name)
 {
 	struct crypto_hash *tfm;
@@ -3267,21 +3312,21 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev,
 
 	tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(tfm)) {
-		dev_err(DEV, "Can not allocate \"%s\" as %s (reason: %ld)\n",
+		drbd_err(device, "Can not allocate \"%s\" as %s (reason: %ld)\n",
 			alg, name, PTR_ERR(tfm));
 		return tfm;
 	}
 	return tfm;
 }
 
-static int ignore_remaining_packet(struct drbd_tconn *tconn, struct packet_info *pi)
+static int ignore_remaining_packet(struct drbd_connection *connection, struct packet_info *pi)
 {
-	void *buffer = tconn->data.rbuf;
+	void *buffer = connection->data.rbuf;
 	int size = pi->size;
 
 	while (size) {
 		int s = min_t(int, size, DRBD_SOCKET_BUFFER_SIZE);
-		s = drbd_recv(tconn, buffer, s);
+		s = drbd_recv(connection, buffer, s);
 		if (s <= 0) {
 			if (s < 0)
 				return s;
@@ -3305,30 +3350,32 @@ static int ignore_remaining_packet(struct drbd_tconn *tconn, struct packet_info
  *
  * (We can also end up here if drbd is misconfigured.)
  */
-static int config_unknown_volume(struct drbd_tconn *tconn, struct packet_info *pi)
+static int config_unknown_volume(struct drbd_connection *connection, struct packet_info *pi)
 {
-	conn_warn(tconn, "%s packet received for volume %u, which is not configured locally\n",
+	drbd_warn(connection, "%s packet received for volume %u, which is not configured locally\n",
 		  cmdname(pi->cmd), pi->vnr);
-	return ignore_remaining_packet(tconn, pi);
+	return ignore_remaining_packet(connection, pi);
 }
 
-static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_SyncParam(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_rs_param_95 *p;
 	unsigned int header_size, data_size, exp_max_sz;
 	struct crypto_hash *verify_tfm = NULL;
 	struct crypto_hash *csums_tfm = NULL;
 	struct net_conf *old_net_conf, *new_net_conf = NULL;
 	struct disk_conf *old_disk_conf = NULL, *new_disk_conf = NULL;
-	const int apv = tconn->agreed_pro_version;
+	const int apv = connection->agreed_pro_version;
 	struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
 	int fifo_size = 0;
 	int err;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
-		return config_unknown_volume(tconn, pi);
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
+		return config_unknown_volume(connection, pi);
+	device = peer_device->device;
 
 	exp_max_sz  = apv <= 87 ? sizeof(struct p_rs_param)
 		    : apv == 88 ? sizeof(struct p_rs_param)
@@ -3337,7 +3384,7 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 		    : /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
 	if (pi->size > exp_max_sz) {
-		dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
+		drbd_err(device, "SyncParam packet too long: received %u, expected <= %u bytes\n",
 		    pi->size, exp_max_sz);
 		return -EIO;
 	}
@@ -3348,33 +3395,33 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 	} else if (apv <= 94) {
 		header_size = sizeof(struct p_rs_param_89);
 		data_size = pi->size - header_size;
-		D_ASSERT(data_size == 0);
+		D_ASSERT(device, data_size == 0);
 	} else {
 		header_size = sizeof(struct p_rs_param_95);
 		data_size = pi->size - header_size;
-		D_ASSERT(data_size == 0);
+		D_ASSERT(device, data_size == 0);
 	}
 
 	/* initialize verify_alg and csums_alg */
 	p = pi->data;
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-	err = drbd_recv_all(mdev->tconn, p, header_size);
+	err = drbd_recv_all(peer_device->connection, p, header_size);
 	if (err)
 		return err;
 
-	mutex_lock(&mdev->tconn->conf_update);
-	old_net_conf = mdev->tconn->net_conf;
-	if (get_ldev(mdev)) {
+	mutex_lock(&connection->resource->conf_update);
+	old_net_conf = peer_device->connection->net_conf;
+	if (get_ldev(device)) {
 		new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
 		if (!new_disk_conf) {
-			put_ldev(mdev);
-			mutex_unlock(&mdev->tconn->conf_update);
-			dev_err(DEV, "Allocation of new disk_conf failed\n");
+			put_ldev(device);
+			mutex_unlock(&connection->resource->conf_update);
+			drbd_err(device, "Allocation of new disk_conf failed\n");
 			return -ENOMEM;
 		}
 
-		old_disk_conf = mdev->ldev->disk_conf;
+		old_disk_conf = device->ldev->disk_conf;
 		*new_disk_conf = *old_disk_conf;
 
 		new_disk_conf->resync_rate = be32_to_cpu(p->resync_rate);
@@ -3383,37 +3430,37 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 	if (apv >= 88) {
 		if (apv == 88) {
 			if (data_size > SHARED_SECRET_MAX || data_size == 0) {
-				dev_err(DEV, "verify-alg of wrong size, "
+				drbd_err(device, "verify-alg of wrong size, "
 					"peer wants %u, accepting only up to %u byte\n",
 					data_size, SHARED_SECRET_MAX);
 				err = -EIO;
 				goto reconnect;
 			}
 
-			err = drbd_recv_all(mdev->tconn, p->verify_alg, data_size);
+			err = drbd_recv_all(peer_device->connection, p->verify_alg, data_size);
 			if (err)
 				goto reconnect;
 			/* we expect NUL terminated string */
 			/* but just in case someone tries to be evil */
-			D_ASSERT(p->verify_alg[data_size-1] == 0);
+			D_ASSERT(device, p->verify_alg[data_size-1] == 0);
 			p->verify_alg[data_size-1] = 0;
 
 		} else /* apv >= 89 */ {
 			/* we still expect NUL terminated strings */
 			/* but just in case someone tries to be evil */
-			D_ASSERT(p->verify_alg[SHARED_SECRET_MAX-1] == 0);
-			D_ASSERT(p->csums_alg[SHARED_SECRET_MAX-1] == 0);
+			D_ASSERT(device, p->verify_alg[SHARED_SECRET_MAX-1] == 0);
+			D_ASSERT(device, p->csums_alg[SHARED_SECRET_MAX-1] == 0);
 			p->verify_alg[SHARED_SECRET_MAX-1] = 0;
 			p->csums_alg[SHARED_SECRET_MAX-1] = 0;
 		}
 
 		if (strcmp(old_net_conf->verify_alg, p->verify_alg)) {
-			if (mdev->state.conn == C_WF_REPORT_PARAMS) {
-				dev_err(DEV, "Different verify-alg settings. me=\"%s\" peer=\"%s\"\n",
+			if (device->state.conn == C_WF_REPORT_PARAMS) {
+				drbd_err(device, "Different verify-alg settings. me=\"%s\" peer=\"%s\"\n",
 				    old_net_conf->verify_alg, p->verify_alg);
 				goto disconnect;
 			}
-			verify_tfm = drbd_crypto_alloc_digest_safe(mdev,
+			verify_tfm = drbd_crypto_alloc_digest_safe(device,
 					p->verify_alg, "verify-alg");
 			if (IS_ERR(verify_tfm)) {
 				verify_tfm = NULL;
@@ -3422,12 +3469,12 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 		}
 
 		if (apv >= 89 && strcmp(old_net_conf->csums_alg, p->csums_alg)) {
-			if (mdev->state.conn == C_WF_REPORT_PARAMS) {
-				dev_err(DEV, "Different csums-alg settings. me=\"%s\" peer=\"%s\"\n",
+			if (device->state.conn == C_WF_REPORT_PARAMS) {
+				drbd_err(device, "Different csums-alg settings. me=\"%s\" peer=\"%s\"\n",
 				    old_net_conf->csums_alg, p->csums_alg);
 				goto disconnect;
 			}
-			csums_tfm = drbd_crypto_alloc_digest_safe(mdev,
+			csums_tfm = drbd_crypto_alloc_digest_safe(device,
 					p->csums_alg, "csums-alg");
 			if (IS_ERR(csums_tfm)) {
 				csums_tfm = NULL;
@@ -3442,11 +3489,11 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 			new_disk_conf->c_max_rate = be32_to_cpu(p->c_max_rate);
 
 			fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
-			if (fifo_size != mdev->rs_plan_s->size) {
+			if (fifo_size != device->rs_plan_s->size) {
 				new_plan = fifo_alloc(fifo_size);
 				if (!new_plan) {
-					dev_err(DEV, "kmalloc of fifo_buffer failed");
-					put_ldev(mdev);
+					drbd_err(device, "kmalloc of fifo_buffer failed");
+					put_ldev(device);
 					goto disconnect;
 				}
 			}
@@ -3455,7 +3502,7 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 		if (verify_tfm || csums_tfm) {
 			new_net_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
 			if (!new_net_conf) {
-				dev_err(DEV, "Allocation of new net_conf failed\n");
+				drbd_err(device, "Allocation of new net_conf failed\n");
 				goto disconnect;
 			}
 
@@ -3464,32 +3511,32 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 			if (verify_tfm) {
 				strcpy(new_net_conf->verify_alg, p->verify_alg);
 				new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1;
-				crypto_free_hash(mdev->tconn->verify_tfm);
-				mdev->tconn->verify_tfm = verify_tfm;
-				dev_info(DEV, "using verify-alg: \"%s\"\n", p->verify_alg);
+				crypto_free_hash(peer_device->connection->verify_tfm);
+				peer_device->connection->verify_tfm = verify_tfm;
+				drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg);
 			}
 			if (csums_tfm) {
 				strcpy(new_net_conf->csums_alg, p->csums_alg);
 				new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1;
-				crypto_free_hash(mdev->tconn->csums_tfm);
-				mdev->tconn->csums_tfm = csums_tfm;
-				dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
+				crypto_free_hash(peer_device->connection->csums_tfm);
+				peer_device->connection->csums_tfm = csums_tfm;
+				drbd_info(device, "using csums-alg: \"%s\"\n", p->csums_alg);
 			}
-			rcu_assign_pointer(tconn->net_conf, new_net_conf);
+			rcu_assign_pointer(connection->net_conf, new_net_conf);
 		}
 	}
 
 	if (new_disk_conf) {
-		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
-		put_ldev(mdev);
+		rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
+		put_ldev(device);
 	}
 
 	if (new_plan) {
-		old_plan = mdev->rs_plan_s;
-		rcu_assign_pointer(mdev->rs_plan_s, new_plan);
+		old_plan = device->rs_plan_s;
+		rcu_assign_pointer(device->rs_plan_s, new_plan);
 	}
 
-	mutex_unlock(&mdev->tconn->conf_update);
+	mutex_unlock(&connection->resource->conf_update);
 	synchronize_rcu();
 	if (new_net_conf)
 		kfree(old_net_conf);
@@ -3500,30 +3547,30 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 
 reconnect:
 	if (new_disk_conf) {
-		put_ldev(mdev);
+		put_ldev(device);
 		kfree(new_disk_conf);
 	}
-	mutex_unlock(&mdev->tconn->conf_update);
+	mutex_unlock(&connection->resource->conf_update);
 	return -EIO;
 
 disconnect:
 	kfree(new_plan);
 	if (new_disk_conf) {
-		put_ldev(mdev);
+		put_ldev(device);
 		kfree(new_disk_conf);
 	}
-	mutex_unlock(&mdev->tconn->conf_update);
+	mutex_unlock(&connection->resource->conf_update);
 	/* just for completeness: actually not needed,
 	 * as this is not reached if csums_tfm was ok. */
 	crypto_free_hash(csums_tfm);
 	/* but free the verify_tfm again, if csums_tfm did not work out */
 	crypto_free_hash(verify_tfm);
-	conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+	conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD);
 	return -EIO;
 }
 
 /* warn if the arguments differ by more than 12.5% */
-static void warn_if_differ_considerably(struct drbd_conf *mdev,
+static void warn_if_differ_considerably(struct drbd_device *device,
 	const char *s, sector_t a, sector_t b)
 {
 	sector_t d;
@@ -3531,54 +3578,56 @@ static void warn_if_differ_considerably(struct drbd_conf *mdev,
 		return;
 	d = (a > b) ? (a - b) : (b - a);
 	if (d > (a>>3) || d > (b>>3))
-		dev_warn(DEV, "Considerable difference in %s: %llus vs. %llus\n", s,
+		drbd_warn(device, "Considerable difference in %s: %llus vs. %llus\n", s,
 		     (unsigned long long)a, (unsigned long long)b);
 }
 
-static int receive_sizes(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_sizes(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_sizes *p = pi->data;
 	enum determine_dev_size dd = DS_UNCHANGED;
 	sector_t p_size, p_usize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
-		return config_unknown_volume(tconn, pi);
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
+		return config_unknown_volume(connection, pi);
+	device = peer_device->device;
 
 	p_size = be64_to_cpu(p->d_size);
 	p_usize = be64_to_cpu(p->u_size);
 
 	/* just store the peer's disk size for now.
 	 * we still need to figure out whether we accept that. */
-	mdev->p_size = p_size;
+	device->p_size = p_size;
 
-	if (get_ldev(mdev)) {
+	if (get_ldev(device)) {
 		rcu_read_lock();
-		my_usize = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+		my_usize = rcu_dereference(device->ldev->disk_conf)->disk_size;
 		rcu_read_unlock();
 
-		warn_if_differ_considerably(mdev, "lower level device sizes",
-			   p_size, drbd_get_max_capacity(mdev->ldev));
-		warn_if_differ_considerably(mdev, "user requested size",
+		warn_if_differ_considerably(device, "lower level device sizes",
+			   p_size, drbd_get_max_capacity(device->ldev));
+		warn_if_differ_considerably(device, "user requested size",
 					    p_usize, my_usize);
 
 		/* if this is the first connect, or an otherwise expected
 		 * param exchange, choose the minimum */
-		if (mdev->state.conn == C_WF_REPORT_PARAMS)
+		if (device->state.conn == C_WF_REPORT_PARAMS)
 			p_usize = min_not_zero(my_usize, p_usize);
 
 		/* Never shrink a device with usable data during connect.
 		   But allow online shrinking if we are connected. */
-		if (drbd_new_dev_size(mdev, mdev->ldev, p_usize, 0) <
-		    drbd_get_capacity(mdev->this_bdev) &&
-		    mdev->state.disk >= D_OUTDATED &&
-		    mdev->state.conn < C_CONNECTED) {
-			dev_err(DEV, "The peer's disk size is too small!\n");
-			conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
-			put_ldev(mdev);
+		if (drbd_new_dev_size(device, device->ldev, p_usize, 0) <
+		    drbd_get_capacity(device->this_bdev) &&
+		    device->state.disk >= D_OUTDATED &&
+		    device->state.conn < C_CONNECTED) {
+			drbd_err(device, "The peer's disk size is too small!\n");
+			conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD);
+			put_ldev(device);
 			return -EIO;
 		}
 
@@ -3587,145 +3636,147 @@ static int receive_sizes(struct drbd_tconn *tconn, struct packet_info *pi)
 
 			new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
 			if (!new_disk_conf) {
-				dev_err(DEV, "Allocation of new disk_conf failed\n");
-				put_ldev(mdev);
+				drbd_err(device, "Allocation of new disk_conf failed\n");
+				put_ldev(device);
 				return -ENOMEM;
 			}
 
-			mutex_lock(&mdev->tconn->conf_update);
-			old_disk_conf = mdev->ldev->disk_conf;
+			mutex_lock(&connection->resource->conf_update);
+			old_disk_conf = device->ldev->disk_conf;
 			*new_disk_conf = *old_disk_conf;
 			new_disk_conf->disk_size = p_usize;
 
-			rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
-			mutex_unlock(&mdev->tconn->conf_update);
+			rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
+			mutex_unlock(&connection->resource->conf_update);
 			synchronize_rcu();
 			kfree(old_disk_conf);
 
-			dev_info(DEV, "Peer sets u_size to %lu sectors\n",
+			drbd_info(device, "Peer sets u_size to %lu sectors\n",
 				 (unsigned long)my_usize);
 		}
 
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	ddsf = be16_to_cpu(p->dds_flags);
-	if (get_ldev(mdev)) {
-		dd = drbd_determine_dev_size(mdev, ddsf, NULL);
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		dd = drbd_determine_dev_size(device, ddsf, NULL);
+		put_ldev(device);
 		if (dd == DS_ERROR)
 			return -EIO;
-		drbd_md_sync(mdev);
+		drbd_md_sync(device);
 	} else {
 		/* I am diskless, need to accept the peer's size. */
-		drbd_set_my_capacity(mdev, p_size);
+		drbd_set_my_capacity(device, p_size);
 	}
 
-	mdev->peer_max_bio_size = be32_to_cpu(p->max_bio_size);
-	drbd_reconsider_max_bio_size(mdev);
+	device->peer_max_bio_size = be32_to_cpu(p->max_bio_size);
+	drbd_reconsider_max_bio_size(device);
 
-	if (get_ldev(mdev)) {
-		if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) {
-			mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev);
+	if (get_ldev(device)) {
+		if (device->ldev->known_size != drbd_get_capacity(device->ldev->backing_bdev)) {
+			device->ldev->known_size = drbd_get_capacity(device->ldev->backing_bdev);
 			ldsc = 1;
 		}
 
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
-	if (mdev->state.conn > C_WF_REPORT_PARAMS) {
+	if (device->state.conn > C_WF_REPORT_PARAMS) {
 		if (be64_to_cpu(p->c_size) !=
-		    drbd_get_capacity(mdev->this_bdev) || ldsc) {
+		    drbd_get_capacity(device->this_bdev) || ldsc) {
 			/* we have different sizes, probably peer
 			 * needs to know my new size... */
-			drbd_send_sizes(mdev, 0, ddsf);
+			drbd_send_sizes(peer_device, 0, ddsf);
 		}
-		if (test_and_clear_bit(RESIZE_PENDING, &mdev->flags) ||
-		    (dd == DS_GREW && mdev->state.conn == C_CONNECTED)) {
-			if (mdev->state.pdsk >= D_INCONSISTENT &&
-			    mdev->state.disk >= D_INCONSISTENT) {
+		if (test_and_clear_bit(RESIZE_PENDING, &device->flags) ||
+		    (dd == DS_GREW && device->state.conn == C_CONNECTED)) {
+			if (device->state.pdsk >= D_INCONSISTENT &&
+			    device->state.disk >= D_INCONSISTENT) {
 				if (ddsf & DDSF_NO_RESYNC)
-					dev_info(DEV, "Resync of new storage suppressed with --assume-clean\n");
+					drbd_info(device, "Resync of new storage suppressed with --assume-clean\n");
 				else
-					resync_after_online_grow(mdev);
+					resync_after_online_grow(device);
 			} else
-				set_bit(RESYNC_AFTER_NEG, &mdev->flags);
+				set_bit(RESYNC_AFTER_NEG, &device->flags);
 		}
 	}
 
 	return 0;
 }
 
-static int receive_uuids(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_uuids(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_uuids *p = pi->data;
 	u64 *p_uuid;
 	int i, updated_uuids = 0;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
-		return config_unknown_volume(tconn, pi);
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
+		return config_unknown_volume(connection, pi);
+	device = peer_device->device;
 
 	p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
 	if (!p_uuid) {
-		dev_err(DEV, "kmalloc of p_uuid failed\n");
+		drbd_err(device, "kmalloc of p_uuid failed\n");
 		return false;
 	}
 
 	for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++)
 		p_uuid[i] = be64_to_cpu(p->uuid[i]);
 
-	kfree(mdev->p_uuid);
-	mdev->p_uuid = p_uuid;
+	kfree(device->p_uuid);
+	device->p_uuid = p_uuid;
 
-	if (mdev->state.conn < C_CONNECTED &&
-	    mdev->state.disk < D_INCONSISTENT &&
-	    mdev->state.role == R_PRIMARY &&
-	    (mdev->ed_uuid & ~((u64)1)) != (p_uuid[UI_CURRENT] & ~((u64)1))) {
-		dev_err(DEV, "Can only connect to data with current UUID=%016llX\n",
-		    (unsigned long long)mdev->ed_uuid);
-		conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+	if (device->state.conn < C_CONNECTED &&
+	    device->state.disk < D_INCONSISTENT &&
+	    device->state.role == R_PRIMARY &&
+	    (device->ed_uuid & ~((u64)1)) != (p_uuid[UI_CURRENT] & ~((u64)1))) {
+		drbd_err(device, "Can only connect to data with current UUID=%016llX\n",
+		    (unsigned long long)device->ed_uuid);
+		conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD);
 		return -EIO;
 	}
 
-	if (get_ldev(mdev)) {
+	if (get_ldev(device)) {
 		int skip_initial_sync =
-			mdev->state.conn == C_CONNECTED &&
-			mdev->tconn->agreed_pro_version >= 90 &&
-			mdev->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED &&
+			device->state.conn == C_CONNECTED &&
+			peer_device->connection->agreed_pro_version >= 90 &&
+			device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED &&
 			(p_uuid[UI_FLAGS] & 8);
 		if (skip_initial_sync) {
-			dev_info(DEV, "Accepted new current UUID, preparing to skip initial sync\n");
-			drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
+			drbd_info(device, "Accepted new current UUID, preparing to skip initial sync\n");
+			drbd_bitmap_io(device, &drbd_bmio_clear_n_write,
 					"clear_n_write from receive_uuids",
 					BM_LOCKED_TEST_ALLOWED);
-			_drbd_uuid_set(mdev, UI_CURRENT, p_uuid[UI_CURRENT]);
-			_drbd_uuid_set(mdev, UI_BITMAP, 0);
-			_drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
+			_drbd_uuid_set(device, UI_CURRENT, p_uuid[UI_CURRENT]);
+			_drbd_uuid_set(device, UI_BITMAP, 0);
+			_drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
 					CS_VERBOSE, NULL);
-			drbd_md_sync(mdev);
+			drbd_md_sync(device);
 			updated_uuids = 1;
 		}
-		put_ldev(mdev);
-	} else if (mdev->state.disk < D_INCONSISTENT &&
-		   mdev->state.role == R_PRIMARY) {
+		put_ldev(device);
+	} else if (device->state.disk < D_INCONSISTENT &&
+		   device->state.role == R_PRIMARY) {
 		/* I am a diskless primary, the peer just created a new current UUID
 		   for me. */
-		updated_uuids = drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+		updated_uuids = drbd_set_ed_uuid(device, p_uuid[UI_CURRENT]);
 	}
 
 	/* Before we test for the disk state, we should wait until an eventually
 	   ongoing cluster wide state change is finished. That is important if
 	   we are primary and are detaching from our disk. We need to see the
 	   new disk state... */
-	mutex_lock(mdev->state_mutex);
-	mutex_unlock(mdev->state_mutex);
-	if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT)
-		updated_uuids |= drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+	mutex_lock(device->state_mutex);
+	mutex_unlock(device->state_mutex);
+	if (device->state.conn >= C_CONNECTED && device->state.disk < D_INCONSISTENT)
+		updated_uuids |= drbd_set_ed_uuid(device, p_uuid[UI_CURRENT]);
 
 	if (updated_uuids)
-		drbd_print_uuids(mdev, "receiver updated UUIDs to");
+		drbd_print_uuids(device, "receiver updated UUIDs to");
 
 	return 0;
 }
@@ -3761,38 +3812,40 @@ static union drbd_state convert_state(union drbd_state ps)
 	return ms;
 }
 
-static int receive_req_state(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_req_state(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_req_state *p = pi->data;
 	union drbd_state mask, val;
 	enum drbd_state_rv rv;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
 
-	if (test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags) &&
-	    mutex_is_locked(mdev->state_mutex)) {
-		drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG);
+	if (test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags) &&
+	    mutex_is_locked(device->state_mutex)) {
+		drbd_send_sr_reply(peer_device, SS_CONCURRENT_ST_CHG);
 		return 0;
 	}
 
 	mask = convert_state(mask);
 	val = convert_state(val);
 
-	rv = drbd_change_state(mdev, CS_VERBOSE, mask, val);
-	drbd_send_sr_reply(mdev, rv);
+	rv = drbd_change_state(device, CS_VERBOSE, mask, val);
+	drbd_send_sr_reply(peer_device, rv);
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
 	return 0;
 }
 
-static int receive_req_conn_state(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_req_conn_state(struct drbd_connection *connection, struct packet_info *pi)
 {
 	struct p_req_state *p = pi->data;
 	union drbd_state mask, val;
@@ -3801,46 +3854,48 @@ static int receive_req_conn_state(struct drbd_tconn *tconn, struct packet_info *
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
 
-	if (test_bit(RESOLVE_CONFLICTS, &tconn->flags) &&
-	    mutex_is_locked(&tconn->cstate_mutex)) {
-		conn_send_sr_reply(tconn, SS_CONCURRENT_ST_CHG);
+	if (test_bit(RESOLVE_CONFLICTS, &connection->flags) &&
+	    mutex_is_locked(&connection->cstate_mutex)) {
+		conn_send_sr_reply(connection, SS_CONCURRENT_ST_CHG);
 		return 0;
 	}
 
 	mask = convert_state(mask);
 	val = convert_state(val);
 
-	rv = conn_request_state(tconn, mask, val, CS_VERBOSE | CS_LOCAL_ONLY | CS_IGN_OUTD_FAIL);
-	conn_send_sr_reply(tconn, rv);
+	rv = conn_request_state(connection, mask, val, CS_VERBOSE | CS_LOCAL_ONLY | CS_IGN_OUTD_FAIL);
+	conn_send_sr_reply(connection, rv);
 
 	return 0;
 }
 
-static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_state(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_state *p = pi->data;
 	union drbd_state os, ns, peer_state;
 	enum drbd_disk_state real_peer_disk;
 	enum chg_state_flags cs_flags;
 	int rv;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
-		return config_unknown_volume(tconn, pi);
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
+		return config_unknown_volume(connection, pi);
+	device = peer_device->device;
 
 	peer_state.i = be32_to_cpu(p->state);
 
 	real_peer_disk = peer_state.disk;
 	if (peer_state.disk == D_NEGOTIATING) {
-		real_peer_disk = mdev->p_uuid[UI_FLAGS] & 4 ? D_INCONSISTENT : D_CONSISTENT;
-		dev_info(DEV, "real peer disk state = %s\n", drbd_disk_str(real_peer_disk));
+		real_peer_disk = device->p_uuid[UI_FLAGS] & 4 ? D_INCONSISTENT : D_CONSISTENT;
+		drbd_info(device, "real peer disk state = %s\n", drbd_disk_str(real_peer_disk));
 	}
 
-	spin_lock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
  retry:
-	os = ns = drbd_read_state(mdev);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	os = ns = drbd_read_state(device);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	/* If some other part of the code (asender thread, timeout)
 	 * already decided to close the connection again,
@@ -3872,8 +3927,8 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 		 * Maybe we should finish it up, too? */
 		else if (os.conn >= C_SYNC_SOURCE &&
 			 peer_state.conn == C_CONNECTED) {
-			if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
-				drbd_resync_finished(mdev);
+			if (drbd_bm_total_weight(device) <= device->rs_failed)
+				drbd_resync_finished(device);
 			return 0;
 		}
 	}
@@ -3881,8 +3936,8 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 	/* explicit verify finished notification, stop sector reached. */
 	if (os.conn == C_VERIFY_T && os.disk == D_UP_TO_DATE &&
 	    peer_state.conn == C_CONNECTED && real_peer_disk == D_UP_TO_DATE) {
-		ov_out_of_sync_print(mdev);
-		drbd_resync_finished(mdev);
+		ov_out_of_sync_print(device);
+		drbd_resync_finished(device);
 		return 0;
 	}
 
@@ -3901,8 +3956,8 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 	if (peer_state.conn == C_AHEAD)
 		ns.conn = C_BEHIND;
 
-	if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
-	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
+	if (device->p_uuid && peer_state.disk >= D_NEGOTIATING &&
+	    get_ldev_if_state(device, D_NEGOTIATING)) {
 		int cr; /* consider resync */
 
 		/* if we established a new connection */
@@ -3914,7 +3969,7 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 			os.disk == D_NEGOTIATING));
 		/* if we have both been inconsistent, and the peer has been
 		 * forced to be UpToDate with --overwrite-data */
-		cr |= test_bit(CONSIDER_RESYNC, &mdev->flags);
+		cr |= test_bit(CONSIDER_RESYNC, &device->flags);
 		/* if we had been plain connected, and the admin requested to
 		 * start a sync by "invalidate" or "invalidate-remote" */
 		cr |= (os.conn == C_CONNECTED &&
@@ -3922,55 +3977,55 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 				 peer_state.conn <= C_WF_BITMAP_T));
 
 		if (cr)
-			ns.conn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
+			ns.conn = drbd_sync_handshake(peer_device, peer_state.role, real_peer_disk);
 
-		put_ldev(mdev);
+		put_ldev(device);
 		if (ns.conn == C_MASK) {
 			ns.conn = C_CONNECTED;
-			if (mdev->state.disk == D_NEGOTIATING) {
-				drbd_force_state(mdev, NS(disk, D_FAILED));
+			if (device->state.disk == D_NEGOTIATING) {
+				drbd_force_state(device, NS(disk, D_FAILED));
 			} else if (peer_state.disk == D_NEGOTIATING) {
-				dev_err(DEV, "Disk attach process on the peer node was aborted.\n");
+				drbd_err(device, "Disk attach process on the peer node was aborted.\n");
 				peer_state.disk = D_DISKLESS;
 				real_peer_disk = D_DISKLESS;
 			} else {
-				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->tconn->flags))
+				if (test_and_clear_bit(CONN_DRY_RUN, &peer_device->connection->flags))
 					return -EIO;
-				D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
-				conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+				D_ASSERT(device, os.conn == C_WF_REPORT_PARAMS);
+				conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD);
 				return -EIO;
 			}
 		}
 	}
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	if (os.i != drbd_read_state(mdev).i)
+	spin_lock_irq(&device->resource->req_lock);
+	if (os.i != drbd_read_state(device).i)
 		goto retry;
-	clear_bit(CONSIDER_RESYNC, &mdev->flags);
+	clear_bit(CONSIDER_RESYNC, &device->flags);
 	ns.peer = peer_state.role;
 	ns.pdsk = real_peer_disk;
 	ns.peer_isp = (peer_state.aftr_isp | peer_state.user_isp);
 	if ((ns.conn == C_CONNECTED || ns.conn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
-		ns.disk = mdev->new_state_tmp.disk;
+		ns.disk = device->new_state_tmp.disk;
 	cs_flags = CS_VERBOSE + (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED ? 0 : CS_HARD);
-	if (ns.pdsk == D_CONSISTENT && drbd_suspended(mdev) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
-	    test_bit(NEW_CUR_UUID, &mdev->flags)) {
+	if (ns.pdsk == D_CONSISTENT && drbd_suspended(device) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
+	    test_bit(NEW_CUR_UUID, &device->flags)) {
 		/* Do not allow tl_restart(RESEND) for a rebooted peer. We can only allow this
 		   for temporal network outages! */
-		spin_unlock_irq(&mdev->tconn->req_lock);
-		dev_err(DEV, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
-		tl_clear(mdev->tconn);
-		drbd_uuid_new_current(mdev);
-		clear_bit(NEW_CUR_UUID, &mdev->flags);
-		conn_request_state(mdev->tconn, NS2(conn, C_PROTOCOL_ERROR, susp, 0), CS_HARD);
+		spin_unlock_irq(&device->resource->req_lock);
+		drbd_err(device, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
+		tl_clear(peer_device->connection);
+		drbd_uuid_new_current(device);
+		clear_bit(NEW_CUR_UUID, &device->flags);
+		conn_request_state(peer_device->connection, NS2(conn, C_PROTOCOL_ERROR, susp, 0), CS_HARD);
 		return -EIO;
 	}
-	rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
-	ns = drbd_read_state(mdev);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	rv = _drbd_set_state(device, ns, cs_flags, NULL);
+	ns = drbd_read_state(device);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	if (rv < SS_SUCCESS) {
-		conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+		conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD);
 		return -EIO;
 	}
 
@@ -3980,47 +4035,49 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 			/* we want resync, peer has not yet decided to sync... */
 			/* Nowadays only used when forcing a node into primary role and
 			   setting its disk to UpToDate with that */
-			drbd_send_uuids(mdev);
-			drbd_send_current_state(mdev);
+			drbd_send_uuids(peer_device);
+			drbd_send_current_state(peer_device);
 		}
 	}
 
-	clear_bit(DISCARD_MY_DATA, &mdev->flags);
+	clear_bit(DISCARD_MY_DATA, &device->flags);
 
-	drbd_md_sync(mdev); /* update connected indicator, la_size_sect, ... */
+	drbd_md_sync(device); /* update connected indicator, la_size_sect, ... */
 
 	return 0;
 }
 
-static int receive_sync_uuid(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_sync_uuid(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_rs_uuid *p = pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	wait_event(mdev->misc_wait,
-		   mdev->state.conn == C_WF_SYNC_UUID ||
-		   mdev->state.conn == C_BEHIND ||
-		   mdev->state.conn < C_CONNECTED ||
-		   mdev->state.disk < D_NEGOTIATING);
+	wait_event(device->misc_wait,
+		   device->state.conn == C_WF_SYNC_UUID ||
+		   device->state.conn == C_BEHIND ||
+		   device->state.conn < C_CONNECTED ||
+		   device->state.disk < D_NEGOTIATING);
 
-	/* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */
+	/* D_ASSERT(device,  device->state.conn == C_WF_SYNC_UUID ); */
 
 	/* Here the _drbd_uuid_ functions are right, current should
 	   _not_ be rotated into the history */
-	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
-		_drbd_uuid_set(mdev, UI_CURRENT, be64_to_cpu(p->uuid));
-		_drbd_uuid_set(mdev, UI_BITMAP, 0UL);
+	if (get_ldev_if_state(device, D_NEGOTIATING)) {
+		_drbd_uuid_set(device, UI_CURRENT, be64_to_cpu(p->uuid));
+		_drbd_uuid_set(device, UI_BITMAP, 0UL);
 
-		drbd_print_uuids(mdev, "updated sync uuid");
-		drbd_start_resync(mdev, C_SYNC_TARGET);
+		drbd_print_uuids(device, "updated sync uuid");
+		drbd_start_resync(device, C_SYNC_TARGET);
 
-		put_ldev(mdev);
+		put_ldev(device);
 	} else
-		dev_err(DEV, "Ignoring SyncUUID packet!\n");
+		drbd_err(device, "Ignoring SyncUUID packet!\n");
 
 	return 0;
 }
@@ -4032,27 +4089,27 @@ static int receive_sync_uuid(struct drbd_tconn *tconn, struct packet_info *pi)
  * code upon failure.
  */
 static int
-receive_bitmap_plain(struct drbd_conf *mdev, unsigned int size,
+receive_bitmap_plain(struct drbd_peer_device *peer_device, unsigned int size,
 		     unsigned long *p, struct bm_xfer_ctx *c)
 {
 	unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE -
-				 drbd_header_size(mdev->tconn);
+				 drbd_header_size(peer_device->connection);
 	unsigned int num_words = min_t(size_t, data_size / sizeof(*p),
 				       c->bm_words - c->word_offset);
 	unsigned int want = num_words * sizeof(*p);
 	int err;
 
 	if (want != size) {
-		dev_err(DEV, "%s:want (%u) != size (%u)\n", __func__, want, size);
+		drbd_err(peer_device, "%s:want (%u) != size (%u)\n", __func__, want, size);
 		return -EIO;
 	}
 	if (want == 0)
 		return 0;
-	err = drbd_recv_all(mdev->tconn, p, want);
+	err = drbd_recv_all(peer_device->connection, p, want);
 	if (err)
 		return err;
 
-	drbd_bm_merge_lel(mdev, c->word_offset, num_words, p);
+	drbd_bm_merge_lel(peer_device->device, c->word_offset, num_words, p);
 
 	c->word_offset += num_words;
 	c->bit_offset = c->word_offset * BITS_PER_LONG;
@@ -4084,7 +4141,7 @@ static int dcbp_get_pad_bits(struct p_compressed_bm *p)
  * code upon failure.
  */
 static int
-recv_bm_rle_bits(struct drbd_conf *mdev,
+recv_bm_rle_bits(struct drbd_peer_device *peer_device,
 		struct p_compressed_bm *p,
 		 struct bm_xfer_ctx *c,
 		 unsigned int len)
@@ -4113,14 +4170,14 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
 		if (toggle) {
 			e = s + rl -1;
 			if (e >= c->bm_bits) {
-				dev_err(DEV, "bitmap overflow (e:%lu) while decoding bm RLE packet\n", e);
+				drbd_err(peer_device, "bitmap overflow (e:%lu) while decoding bm RLE packet\n", e);
 				return -EIO;
 			}
-			_drbd_bm_set_bits(mdev, s, e);
+			_drbd_bm_set_bits(peer_device->device, s, e);
 		}
 
 		if (have < bits) {
-			dev_err(DEV, "bitmap decoding error: h:%d b:%d la:0x%08llx l:%u/%u\n",
+			drbd_err(peer_device, "bitmap decoding error: h:%d b:%d la:0x%08llx l:%u/%u\n",
 				have, bits, look_ahead,
 				(unsigned int)(bs.cur.b - p->code),
 				(unsigned int)bs.buf_len);
@@ -4153,28 +4210,28 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
  * code upon failure.
  */
 static int
-decode_bitmap_c(struct drbd_conf *mdev,
+decode_bitmap_c(struct drbd_peer_device *peer_device,
 		struct p_compressed_bm *p,
 		struct bm_xfer_ctx *c,
 		unsigned int len)
 {
 	if (dcbp_get_code(p) == RLE_VLI_Bits)
-		return recv_bm_rle_bits(mdev, p, c, len - sizeof(*p));
+		return recv_bm_rle_bits(peer_device, p, c, len - sizeof(*p));
 
 	/* other variants had been implemented for evaluation,
 	 * but have been dropped as this one turned out to be "best"
 	 * during all our tests. */
 
-	dev_err(DEV, "receive_bitmap_c: unknown encoding %u\n", p->encoding);
-	conn_request_state(mdev->tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
+	drbd_err(peer_device, "receive_bitmap_c: unknown encoding %u\n", p->encoding);
+	conn_request_state(peer_device->connection, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 	return -EIO;
 }
 
-void INFO_bm_xfer_stats(struct drbd_conf *mdev,
+void INFO_bm_xfer_stats(struct drbd_device *device,
 		const char *direction, struct bm_xfer_ctx *c)
 {
 	/* what would it take to transfer it "plaintext" */
-	unsigned int header_size = drbd_header_size(mdev->tconn);
+	unsigned int header_size = drbd_header_size(first_peer_device(device)->connection);
 	unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
 	unsigned int plain =
 		header_size * (DIV_ROUND_UP(c->bm_words, data_size) + 1) +
@@ -4198,7 +4255,7 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
 		r = 1000;
 
 	r = 1000 - r;
-	dev_info(DEV, "%s bitmap stats [Bytes(packets)]: plain %u(%u), RLE %u(%u), "
+	drbd_info(device, "%s bitmap stats [Bytes(packets)]: plain %u(%u), RLE %u(%u), "
 	     "total %u; compression: %u.%u%%\n",
 			direction,
 			c->bytes[1], c->packets[1],
@@ -4214,129 +4271,133 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
    in order to be agnostic to the 32 vs 64 bits issue.
 
    returns 0 on failure, 1 if we successfully received it. */
-static int receive_bitmap(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_bitmap(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct bm_xfer_ctx c;
 	int err;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED);
+	drbd_bm_lock(device, "receive bitmap", BM_LOCKED_SET_ALLOWED);
 	/* you are supposed to send additional out-of-sync information
 	 * if you actually set bits during this phase */
 
 	c = (struct bm_xfer_ctx) {
-		.bm_bits = drbd_bm_bits(mdev),
-		.bm_words = drbd_bm_words(mdev),
+		.bm_bits = drbd_bm_bits(device),
+		.bm_words = drbd_bm_words(device),
 	};
 
 	for(;;) {
 		if (pi->cmd == P_BITMAP)
-			err = receive_bitmap_plain(mdev, pi->size, pi->data, &c);
+			err = receive_bitmap_plain(peer_device, pi->size, pi->data, &c);
 		else if (pi->cmd == P_COMPRESSED_BITMAP) {
 			/* MAYBE: sanity check that we speak proto >= 90,
 			 * and the feature is enabled! */
 			struct p_compressed_bm *p = pi->data;
 
-			if (pi->size > DRBD_SOCKET_BUFFER_SIZE - drbd_header_size(tconn)) {
-				dev_err(DEV, "ReportCBitmap packet too large\n");
+			if (pi->size > DRBD_SOCKET_BUFFER_SIZE - drbd_header_size(connection)) {
+				drbd_err(device, "ReportCBitmap packet too large\n");
 				err = -EIO;
 				goto out;
 			}
 			if (pi->size <= sizeof(*p)) {
-				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", pi->size);
+				drbd_err(device, "ReportCBitmap packet too small (l:%u)\n", pi->size);
 				err = -EIO;
 				goto out;
 			}
-			err = drbd_recv_all(mdev->tconn, p, pi->size);
+			err = drbd_recv_all(peer_device->connection, p, pi->size);
 			if (err)
 			       goto out;
-			err = decode_bitmap_c(mdev, p, &c, pi->size);
+			err = decode_bitmap_c(peer_device, p, &c, pi->size);
 		} else {
-			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", pi->cmd);
+			drbd_warn(device, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", pi->cmd);
 			err = -EIO;
 			goto out;
 		}
 
 		c.packets[pi->cmd == P_BITMAP]++;
-		c.bytes[pi->cmd == P_BITMAP] += drbd_header_size(tconn) + pi->size;
+		c.bytes[pi->cmd == P_BITMAP] += drbd_header_size(connection) + pi->size;
 
 		if (err <= 0) {
 			if (err < 0)
 				goto out;
 			break;
 		}
-		err = drbd_recv_header(mdev->tconn, pi);
+		err = drbd_recv_header(peer_device->connection, pi);
 		if (err)
 			goto out;
 	}
 
-	INFO_bm_xfer_stats(mdev, "receive", &c);
+	INFO_bm_xfer_stats(device, "receive", &c);
 
-	if (mdev->state.conn == C_WF_BITMAP_T) {
+	if (device->state.conn == C_WF_BITMAP_T) {
 		enum drbd_state_rv rv;
 
-		err = drbd_send_bitmap(mdev);
+		err = drbd_send_bitmap(device);
 		if (err)
 			goto out;
 		/* Omit CS_ORDERED with this state transition to avoid deadlocks. */
-		rv = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
-		D_ASSERT(rv == SS_SUCCESS);
-	} else if (mdev->state.conn != C_WF_BITMAP_S) {
+		rv = _drbd_request_state(device, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
+		D_ASSERT(device, rv == SS_SUCCESS);
+	} else if (device->state.conn != C_WF_BITMAP_S) {
 		/* admin may have requested C_DISCONNECTING,
 		 * other threads may have noticed network errors */
-		dev_info(DEV, "unexpected cstate (%s) in receive_bitmap\n",
-		    drbd_conn_str(mdev->state.conn));
+		drbd_info(device, "unexpected cstate (%s) in receive_bitmap\n",
+		    drbd_conn_str(device->state.conn));
 	}
 	err = 0;
 
  out:
-	drbd_bm_unlock(mdev);
-	if (!err && mdev->state.conn == C_WF_BITMAP_S)
-		drbd_start_resync(mdev, C_SYNC_SOURCE);
+	drbd_bm_unlock(device);
+	if (!err && device->state.conn == C_WF_BITMAP_S)
+		drbd_start_resync(device, C_SYNC_SOURCE);
 	return err;
 }
 
-static int receive_skip(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_skip(struct drbd_connection *connection, struct packet_info *pi)
 {
-	conn_warn(tconn, "skipping unknown optional packet type %d, l: %d!\n",
+	drbd_warn(connection, "skipping unknown optional packet type %d, l: %d!\n",
 		 pi->cmd, pi->size);
 
-	return ignore_remaining_packet(tconn, pi);
+	return ignore_remaining_packet(connection, pi);
 }
 
-static int receive_UnplugRemote(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_UnplugRemote(struct drbd_connection *connection, struct packet_info *pi)
 {
 	/* Make sure we've acked all the TCP data associated
 	 * with the data requests being unplugged */
-	drbd_tcp_quickack(tconn->data.socket);
+	drbd_tcp_quickack(connection->data.socket);
 
 	return 0;
 }
 
-static int receive_out_of_sync(struct drbd_tconn *tconn, struct packet_info *pi)
+static int receive_out_of_sync(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_desc *p = pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	switch (mdev->state.conn) {
+	switch (device->state.conn) {
 	case C_WF_SYNC_UUID:
 	case C_WF_BITMAP_T:
 	case C_BEHIND:
 			break;
 	default:
-		dev_err(DEV, "ASSERT FAILED cstate = %s, expected: WFSyncUUID|WFBitMapT|Behind\n",
-				drbd_conn_str(mdev->state.conn));
+		drbd_err(device, "ASSERT FAILED cstate = %s, expected: WFSyncUUID|WFBitMapT|Behind\n",
+				drbd_conn_str(device->state.conn));
 	}
 
-	drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize));
+	drbd_set_out_of_sync(device, be64_to_cpu(p->sector), be32_to_cpu(p->blksize));
 
 	return 0;
 }
@@ -4344,7 +4405,7 @@ static int receive_out_of_sync(struct drbd_tconn *tconn, struct packet_info *pi)
 struct data_cmd {
 	int expect_payload;
 	size_t pkt_size;
-	int (*fn)(struct drbd_tconn *, struct packet_info *);
+	int (*fn)(struct drbd_connection *, struct packet_info *);
 };
 
 static struct data_cmd drbd_cmd_handler[] = {
@@ -4374,43 +4435,43 @@ static struct data_cmd drbd_cmd_handler[] = {
 	[P_PROTOCOL_UPDATE] = { 1, sizeof(struct p_protocol), receive_protocol },
 };
 
-static void drbdd(struct drbd_tconn *tconn)
+static void drbdd(struct drbd_connection *connection)
 {
 	struct packet_info pi;
 	size_t shs; /* sub header size */
 	int err;
 
-	while (get_t_state(&tconn->receiver) == RUNNING) {
+	while (get_t_state(&connection->receiver) == RUNNING) {
 		struct data_cmd *cmd;
 
-		drbd_thread_current_set_cpu(&tconn->receiver);
-		if (drbd_recv_header(tconn, &pi))
+		drbd_thread_current_set_cpu(&connection->receiver);
+		if (drbd_recv_header(connection, &pi))
 			goto err_out;
 
 		cmd = &drbd_cmd_handler[pi.cmd];
 		if (unlikely(pi.cmd >= ARRAY_SIZE(drbd_cmd_handler) || !cmd->fn)) {
-			conn_err(tconn, "Unexpected data packet %s (0x%04x)",
+			drbd_err(connection, "Unexpected data packet %s (0x%04x)",
 				 cmdname(pi.cmd), pi.cmd);
 			goto err_out;
 		}
 
 		shs = cmd->pkt_size;
 		if (pi.size > shs && !cmd->expect_payload) {
-			conn_err(tconn, "No payload expected %s l:%d\n",
+			drbd_err(connection, "No payload expected %s l:%d\n",
 				 cmdname(pi.cmd), pi.size);
 			goto err_out;
 		}
 
 		if (shs) {
-			err = drbd_recv_all_warn(tconn, pi.data, shs);
+			err = drbd_recv_all_warn(connection, pi.data, shs);
 			if (err)
 				goto err_out;
 			pi.size -= shs;
 		}
 
-		err = cmd->fn(tconn, &pi);
+		err = cmd->fn(connection, &pi);
 		if (err) {
-			conn_err(tconn, "error receiving %s, e: %d l: %d!\n",
+			drbd_err(connection, "error receiving %s, e: %d l: %d!\n",
 				 cmdname(pi.cmd), err, pi.size);
 			goto err_out;
 		}
@@ -4418,27 +4479,16 @@ static void drbdd(struct drbd_tconn *tconn)
 	return;
 
     err_out:
-	conn_request_state(tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
-}
-
-void conn_flush_workqueue(struct drbd_tconn *tconn)
-{
-	struct drbd_wq_barrier barr;
-
-	barr.w.cb = w_prev_work_done;
-	barr.w.tconn = tconn;
-	init_completion(&barr.done);
-	drbd_queue_work(&tconn->sender_work, &barr.w);
-	wait_for_completion(&barr.done);
+	conn_request_state(connection, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 }
 
-static void conn_disconnect(struct drbd_tconn *tconn)
+static void conn_disconnect(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	enum drbd_conns oc;
 	int vnr;
 
-	if (tconn->cstate == C_STANDALONE)
+	if (connection->cstate == C_STANDALONE)
 		return;
 
 	/* We are about to start the cleanup after connection loss.
@@ -4446,54 +4496,56 @@ static void conn_disconnect(struct drbd_tconn *tconn)
 	 * Usually we should be in some network failure state already,
 	 * but just in case we are not, we fix it up here.
 	 */
-	conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
+	conn_request_state(connection, NS(conn, C_NETWORK_FAILURE), CS_HARD);
 
 	/* asender does not clean up anything. it must not interfere, either */
-	drbd_thread_stop(&tconn->asender);
-	drbd_free_sock(tconn);
+	drbd_thread_stop(&connection->asender);
+	drbd_free_sock(connection);
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		kref_get(&mdev->kref);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		kref_get(&device->kref);
 		rcu_read_unlock();
-		drbd_disconnected(mdev);
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_disconnected(peer_device);
+		kref_put(&device->kref, drbd_destroy_device);
 		rcu_read_lock();
 	}
 	rcu_read_unlock();
 
-	if (!list_empty(&tconn->current_epoch->list))
-		conn_err(tconn, "ASSERTION FAILED: tconn->current_epoch->list not empty\n");
+	if (!list_empty(&connection->current_epoch->list))
+		drbd_err(connection, "ASSERTION FAILED: connection->current_epoch->list not empty\n");
 	/* ok, no more ee's on the fly, it is safe to reset the epoch_size */
-	atomic_set(&tconn->current_epoch->epoch_size, 0);
-	tconn->send.seen_any_write_yet = false;
+	atomic_set(&connection->current_epoch->epoch_size, 0);
+	connection->send.seen_any_write_yet = false;
 
-	conn_info(tconn, "Connection closed\n");
+	drbd_info(connection, "Connection closed\n");
 
-	if (conn_highest_role(tconn) == R_PRIMARY && conn_highest_pdsk(tconn) >= D_UNKNOWN)
-		conn_try_outdate_peer_async(tconn);
+	if (conn_highest_role(connection) == R_PRIMARY && conn_highest_pdsk(connection) >= D_UNKNOWN)
+		conn_try_outdate_peer_async(connection);
 
-	spin_lock_irq(&tconn->req_lock);
-	oc = tconn->cstate;
+	spin_lock_irq(&connection->resource->req_lock);
+	oc = connection->cstate;
 	if (oc >= C_UNCONNECTED)
-		_conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE);
+		_conn_request_state(connection, NS(conn, C_UNCONNECTED), CS_VERBOSE);
 
-	spin_unlock_irq(&tconn->req_lock);
+	spin_unlock_irq(&connection->resource->req_lock);
 
 	if (oc == C_DISCONNECTING)
-		conn_request_state(tconn, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD);
+		conn_request_state(connection, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD);
 }
 
-static int drbd_disconnected(struct drbd_conf *mdev)
+static int drbd_disconnected(struct drbd_peer_device *peer_device)
 {
+	struct drbd_device *device = peer_device->device;
 	unsigned int i;
 
 	/* wait for current activity to cease. */
-	spin_lock_irq(&mdev->tconn->req_lock);
-	_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
-	_drbd_wait_ee_list_empty(mdev, &mdev->sync_ee);
-	_drbd_wait_ee_list_empty(mdev, &mdev->read_ee);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	_drbd_wait_ee_list_empty(device, &device->active_ee);
+	_drbd_wait_ee_list_empty(device, &device->sync_ee);
+	_drbd_wait_ee_list_empty(device, &device->read_ee);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	/* We do not have data structures that would allow us to
 	 * get the rs_pending_cnt down to 0 again.
@@ -4505,42 +4557,42 @@ static int drbd_disconnected(struct drbd_conf *mdev)
 	 *  resync_LRU. The resync_LRU tracks the whole operation including
 	 *  the disk-IO, while the rs_pending_cnt only tracks the blocks
 	 *  on the fly. */
-	drbd_rs_cancel_all(mdev);
-	mdev->rs_total = 0;
-	mdev->rs_failed = 0;
-	atomic_set(&mdev->rs_pending_cnt, 0);
-	wake_up(&mdev->misc_wait);
+	drbd_rs_cancel_all(device);
+	device->rs_total = 0;
+	device->rs_failed = 0;
+	atomic_set(&device->rs_pending_cnt, 0);
+	wake_up(&device->misc_wait);
 
-	del_timer_sync(&mdev->resync_timer);
-	resync_timer_fn((unsigned long)mdev);
+	del_timer_sync(&device->resync_timer);
+	resync_timer_fn((unsigned long)device);
 
 	/* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier,
 	 * w_make_resync_request etc. which may still be on the worker queue
 	 * to be "canceled" */
-	drbd_flush_workqueue(mdev);
+	drbd_flush_workqueue(&peer_device->connection->sender_work);
 
-	drbd_finish_peer_reqs(mdev);
+	drbd_finish_peer_reqs(device);
 
 	/* This second workqueue flush is necessary, since drbd_finish_peer_reqs()
 	   might have issued a work again. The one before drbd_finish_peer_reqs() is
 	   necessary to reclain net_ee in drbd_finish_peer_reqs(). */
-	drbd_flush_workqueue(mdev);
+	drbd_flush_workqueue(&peer_device->connection->sender_work);
 
 	/* need to do it again, drbd_finish_peer_reqs() may have populated it
 	 * again via drbd_try_clear_on_disk_bm(). */
-	drbd_rs_cancel_all(mdev);
+	drbd_rs_cancel_all(device);
 
-	kfree(mdev->p_uuid);
-	mdev->p_uuid = NULL;
+	kfree(device->p_uuid);
+	device->p_uuid = NULL;
 
-	if (!drbd_suspended(mdev))
-		tl_clear(mdev->tconn);
+	if (!drbd_suspended(device))
+		tl_clear(peer_device->connection);
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
 	/* serialize with bitmap writeout triggered by the state change,
 	 * if any. */
-	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+	wait_event(device->misc_wait, !test_bit(BITMAP_IO, &device->flags));
 
 	/* tcp_close and release of sendpage pages can be deferred.  I don't
 	 * want to use SO_LINGER, because apparently it can be deferred for
@@ -4549,20 +4601,20 @@ static int drbd_disconnected(struct drbd_conf *mdev)
 	 * Actually we don't care for exactly when the network stack does its
 	 * put_page(), but release our reference on these pages right here.
 	 */
-	i = drbd_free_peer_reqs(mdev, &mdev->net_ee);
+	i = drbd_free_peer_reqs(device, &device->net_ee);
 	if (i)
-		dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
-	i = atomic_read(&mdev->pp_in_use_by_net);
+		drbd_info(device, "net_ee not empty, killed %u entries\n", i);
+	i = atomic_read(&device->pp_in_use_by_net);
 	if (i)
-		dev_info(DEV, "pp_in_use_by_net = %d, expected 0\n", i);
-	i = atomic_read(&mdev->pp_in_use);
+		drbd_info(device, "pp_in_use_by_net = %d, expected 0\n", i);
+	i = atomic_read(&device->pp_in_use);
 	if (i)
-		dev_info(DEV, "pp_in_use = %d, expected 0\n", i);
+		drbd_info(device, "pp_in_use = %d, expected 0\n", i);
 
-	D_ASSERT(list_empty(&mdev->read_ee));
-	D_ASSERT(list_empty(&mdev->active_ee));
-	D_ASSERT(list_empty(&mdev->sync_ee));
-	D_ASSERT(list_empty(&mdev->done_ee));
+	D_ASSERT(device, list_empty(&device->read_ee));
+	D_ASSERT(device, list_empty(&device->active_ee));
+	D_ASSERT(device, list_empty(&device->sync_ee));
+	D_ASSERT(device, list_empty(&device->done_ee));
 
 	return 0;
 }
@@ -4576,19 +4628,19 @@ static int drbd_disconnected(struct drbd_conf *mdev)
  *
  * for now, they are expected to be zero, but ignored.
  */
-static int drbd_send_features(struct drbd_tconn *tconn)
+static int drbd_send_features(struct drbd_connection *connection)
 {
 	struct drbd_socket *sock;
 	struct p_connection_features *p;
 
-	sock = &tconn->data;
-	p = conn_prepare_command(tconn, sock);
+	sock = &connection->data;
+	p = conn_prepare_command(connection, sock);
 	if (!p)
 		return -EIO;
 	memset(p, 0, sizeof(*p));
 	p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
 	p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
-	return conn_send_command(tconn, sock, P_CONNECTION_FEATURES, sizeof(*p), NULL, 0);
+	return conn_send_command(connection, sock, P_CONNECTION_FEATURES, sizeof(*p), NULL, 0);
 }
 
 /*
@@ -4598,36 +4650,36 @@ static int drbd_send_features(struct drbd_tconn *tconn)
  *  -1 peer talks different language,
  *     no point in trying again, please go standalone.
  */
-static int drbd_do_features(struct drbd_tconn *tconn)
+static int drbd_do_features(struct drbd_connection *connection)
 {
-	/* ASSERT current == tconn->receiver ... */
+	/* ASSERT current == connection->receiver ... */
 	struct p_connection_features *p;
 	const int expect = sizeof(struct p_connection_features);
 	struct packet_info pi;
 	int err;
 
-	err = drbd_send_features(tconn);
+	err = drbd_send_features(connection);
 	if (err)
 		return 0;
 
-	err = drbd_recv_header(tconn, &pi);
+	err = drbd_recv_header(connection, &pi);
 	if (err)
 		return 0;
 
 	if (pi.cmd != P_CONNECTION_FEATURES) {
-		conn_err(tconn, "expected ConnectionFeatures packet, received: %s (0x%04x)\n",
+		drbd_err(connection, "expected ConnectionFeatures packet, received: %s (0x%04x)\n",
 			 cmdname(pi.cmd), pi.cmd);
 		return -1;
 	}
 
 	if (pi.size != expect) {
-		conn_err(tconn, "expected ConnectionFeatures length: %u, received: %u\n",
+		drbd_err(connection, "expected ConnectionFeatures length: %u, received: %u\n",
 		     expect, pi.size);
 		return -1;
 	}
 
 	p = pi.data;
-	err = drbd_recv_all_warn(tconn, p, expect);
+	err = drbd_recv_all_warn(connection, p, expect);
 	if (err)
 		return 0;
 
@@ -4640,15 +4692,15 @@ static int drbd_do_features(struct drbd_tconn *tconn)
 	    PRO_VERSION_MIN > p->protocol_max)
 		goto incompat;
 
-	tconn->agreed_pro_version = min_t(int, PRO_VERSION_MAX, p->protocol_max);
+	connection->agreed_pro_version = min_t(int, PRO_VERSION_MAX, p->protocol_max);
 
-	conn_info(tconn, "Handshake successful: "
-	     "Agreed network protocol version %d\n", tconn->agreed_pro_version);
+	drbd_info(connection, "Handshake successful: "
+	     "Agreed network protocol version %d\n", connection->agreed_pro_version);
 
 	return 1;
 
  incompat:
-	conn_err(tconn, "incompatible DRBD dialects: "
+	drbd_err(connection, "incompatible DRBD dialects: "
 	    "I support %d-%d, peer supports %d-%d\n",
 	    PRO_VERSION_MIN, PRO_VERSION_MAX,
 	    p->protocol_min, p->protocol_max);
@@ -4656,10 +4708,10 @@ static int drbd_do_features(struct drbd_tconn *tconn)
 }
 
 #if !defined(CONFIG_CRYPTO_HMAC) && !defined(CONFIG_CRYPTO_HMAC_MODULE)
-static int drbd_do_auth(struct drbd_tconn *tconn)
+static int drbd_do_auth(struct drbd_connection *connection)
 {
-	conn_err(tconn, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
-	conn_err(tconn, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
+	drbd_err(connection, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
+	drbd_err(connection, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
 	return -1;
 }
 #else
@@ -4671,7 +4723,7 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 	-1 - auth failed, don't try again.
 */
 
-static int drbd_do_auth(struct drbd_tconn *tconn)
+static int drbd_do_auth(struct drbd_connection *connection)
 {
 	struct drbd_socket *sock;
 	char my_challenge[CHALLENGE_LEN];  /* 64 Bytes... */
@@ -4690,69 +4742,69 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 	/* FIXME: Put the challenge/response into the preallocated socket buffer.  */
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	key_len = strlen(nc->shared_secret);
 	memcpy(secret, nc->shared_secret, key_len);
 	rcu_read_unlock();
 
-	desc.tfm = tconn->cram_hmac_tfm;
+	desc.tfm = connection->cram_hmac_tfm;
 	desc.flags = 0;
 
-	rv = crypto_hash_setkey(tconn->cram_hmac_tfm, (u8 *)secret, key_len);
+	rv = crypto_hash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len);
 	if (rv) {
-		conn_err(tconn, "crypto_hash_setkey() failed with %d\n", rv);
+		drbd_err(connection, "crypto_hash_setkey() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
 
 	get_random_bytes(my_challenge, CHALLENGE_LEN);
 
-	sock = &tconn->data;
-	if (!conn_prepare_command(tconn, sock)) {
+	sock = &connection->data;
+	if (!conn_prepare_command(connection, sock)) {
 		rv = 0;
 		goto fail;
 	}
-	rv = !conn_send_command(tconn, sock, P_AUTH_CHALLENGE, 0,
+	rv = !conn_send_command(connection, sock, P_AUTH_CHALLENGE, 0,
 				my_challenge, CHALLENGE_LEN);
 	if (!rv)
 		goto fail;
 
-	err = drbd_recv_header(tconn, &pi);
+	err = drbd_recv_header(connection, &pi);
 	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
 	if (pi.cmd != P_AUTH_CHALLENGE) {
-		conn_err(tconn, "expected AuthChallenge packet, received: %s (0x%04x)\n",
+		drbd_err(connection, "expected AuthChallenge packet, received: %s (0x%04x)\n",
 			 cmdname(pi.cmd), pi.cmd);
 		rv = 0;
 		goto fail;
 	}
 
 	if (pi.size > CHALLENGE_LEN * 2) {
-		conn_err(tconn, "expected AuthChallenge payload too big.\n");
+		drbd_err(connection, "expected AuthChallenge payload too big.\n");
 		rv = -1;
 		goto fail;
 	}
 
 	peers_ch = kmalloc(pi.size, GFP_NOIO);
 	if (peers_ch == NULL) {
-		conn_err(tconn, "kmalloc of peers_ch failed\n");
+		drbd_err(connection, "kmalloc of peers_ch failed\n");
 		rv = -1;
 		goto fail;
 	}
 
-	err = drbd_recv_all_warn(tconn, peers_ch, pi.size);
+	err = drbd_recv_all_warn(connection, peers_ch, pi.size);
 	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
-	resp_size = crypto_hash_digestsize(tconn->cram_hmac_tfm);
+	resp_size = crypto_hash_digestsize(connection->cram_hmac_tfm);
 	response = kmalloc(resp_size, GFP_NOIO);
 	if (response == NULL) {
-		conn_err(tconn, "kmalloc of response failed\n");
+		drbd_err(connection, "kmalloc of response failed\n");
 		rv = -1;
 		goto fail;
 	}
@@ -4762,40 +4814,40 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, response);
 	if (rv) {
-		conn_err(tconn, "crypto_hash_digest() failed with %d\n", rv);
+		drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
 
-	if (!conn_prepare_command(tconn, sock)) {
+	if (!conn_prepare_command(connection, sock)) {
 		rv = 0;
 		goto fail;
 	}
-	rv = !conn_send_command(tconn, sock, P_AUTH_RESPONSE, 0,
+	rv = !conn_send_command(connection, sock, P_AUTH_RESPONSE, 0,
 				response, resp_size);
 	if (!rv)
 		goto fail;
 
-	err = drbd_recv_header(tconn, &pi);
+	err = drbd_recv_header(connection, &pi);
 	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
 	if (pi.cmd != P_AUTH_RESPONSE) {
-		conn_err(tconn, "expected AuthResponse packet, received: %s (0x%04x)\n",
+		drbd_err(connection, "expected AuthResponse packet, received: %s (0x%04x)\n",
 			 cmdname(pi.cmd), pi.cmd);
 		rv = 0;
 		goto fail;
 	}
 
 	if (pi.size != resp_size) {
-		conn_err(tconn, "expected AuthResponse payload of wrong size\n");
+		drbd_err(connection, "expected AuthResponse payload of wrong size\n");
 		rv = 0;
 		goto fail;
 	}
 
-	err = drbd_recv_all_warn(tconn, response , resp_size);
+	err = drbd_recv_all_warn(connection, response , resp_size);
 	if (err) {
 		rv = 0;
 		goto fail;
@@ -4803,7 +4855,7 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 
 	right_response = kmalloc(resp_size, GFP_NOIO);
 	if (right_response == NULL) {
-		conn_err(tconn, "kmalloc of right_response failed\n");
+		drbd_err(connection, "kmalloc of right_response failed\n");
 		rv = -1;
 		goto fail;
 	}
@@ -4812,7 +4864,7 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, right_response);
 	if (rv) {
-		conn_err(tconn, "crypto_hash_digest() failed with %d\n", rv);
+		drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
@@ -4820,7 +4872,7 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 	rv = !memcmp(response, right_response, resp_size);
 
 	if (rv)
-		conn_info(tconn, "Peer authenticated using %d bytes HMAC\n",
+		drbd_info(connection, "Peer authenticated using %d bytes HMAC\n",
 		     resp_size);
 	else
 		rv = -1;
@@ -4834,163 +4886,169 @@ static int drbd_do_auth(struct drbd_tconn *tconn)
 }
 #endif
 
-int drbdd_init(struct drbd_thread *thi)
+int drbd_receiver(struct drbd_thread *thi)
 {
-	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_connection *connection = thi->connection;
 	int h;
 
-	conn_info(tconn, "receiver (re)started\n");
+	drbd_info(connection, "receiver (re)started\n");
 
 	do {
-		h = conn_connect(tconn);
+		h = conn_connect(connection);
 		if (h == 0) {
-			conn_disconnect(tconn);
+			conn_disconnect(connection);
 			schedule_timeout_interruptible(HZ);
 		}
 		if (h == -1) {
-			conn_warn(tconn, "Discarding network configuration.\n");
-			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+			drbd_warn(connection, "Discarding network configuration.\n");
+			conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 		}
 	} while (h == 0);
 
 	if (h > 0)
-		drbdd(tconn);
+		drbdd(connection);
 
-	conn_disconnect(tconn);
+	conn_disconnect(connection);
 
-	conn_info(tconn, "receiver terminated\n");
+	drbd_info(connection, "receiver terminated\n");
 	return 0;
 }
 
 /* ********* acknowledge sender ******** */
 
-static int got_conn_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_conn_RqSReply(struct drbd_connection *connection, struct packet_info *pi)
 {
 	struct p_req_state_reply *p = pi->data;
 	int retcode = be32_to_cpu(p->retcode);
 
 	if (retcode >= SS_SUCCESS) {
-		set_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags);
+		set_bit(CONN_WD_ST_CHG_OKAY, &connection->flags);
 	} else {
-		set_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags);
-		conn_err(tconn, "Requested state change failed by peer: %s (%d)\n",
+		set_bit(CONN_WD_ST_CHG_FAIL, &connection->flags);
+		drbd_err(connection, "Requested state change failed by peer: %s (%d)\n",
 			 drbd_set_st_err_str(retcode), retcode);
 	}
-	wake_up(&tconn->ping_wait);
+	wake_up(&connection->ping_wait);
 
 	return 0;
 }
 
-static int got_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_RqSReply(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_req_state_reply *p = pi->data;
 	int retcode = be32_to_cpu(p->retcode);
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	if (test_bit(CONN_WD_ST_CHG_REQ, &tconn->flags)) {
-		D_ASSERT(tconn->agreed_pro_version < 100);
-		return got_conn_RqSReply(tconn, pi);
+	if (test_bit(CONN_WD_ST_CHG_REQ, &connection->flags)) {
+		D_ASSERT(device, connection->agreed_pro_version < 100);
+		return got_conn_RqSReply(connection, pi);
 	}
 
 	if (retcode >= SS_SUCCESS) {
-		set_bit(CL_ST_CHG_SUCCESS, &mdev->flags);
+		set_bit(CL_ST_CHG_SUCCESS, &device->flags);
 	} else {
-		set_bit(CL_ST_CHG_FAIL, &mdev->flags);
-		dev_err(DEV, "Requested state change failed by peer: %s (%d)\n",
+		set_bit(CL_ST_CHG_FAIL, &device->flags);
+		drbd_err(device, "Requested state change failed by peer: %s (%d)\n",
 			drbd_set_st_err_str(retcode), retcode);
 	}
-	wake_up(&mdev->state_wait);
+	wake_up(&device->state_wait);
 
 	return 0;
 }
 
-static int got_Ping(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_Ping(struct drbd_connection *connection, struct packet_info *pi)
 {
-	return drbd_send_ping_ack(tconn);
+	return drbd_send_ping_ack(connection);
 
 }
 
-static int got_PingAck(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_PingAck(struct drbd_connection *connection, struct packet_info *pi)
 {
 	/* restore idle timeout */
-	tconn->meta.socket->sk->sk_rcvtimeo = tconn->net_conf->ping_int*HZ;
-	if (!test_and_set_bit(GOT_PING_ACK, &tconn->flags))
-		wake_up(&tconn->ping_wait);
+	connection->meta.socket->sk->sk_rcvtimeo = connection->net_conf->ping_int*HZ;
+	if (!test_and_set_bit(GOT_PING_ACK, &connection->flags))
+		wake_up(&connection->ping_wait);
 
 	return 0;
 }
 
-static int got_IsInSync(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_IsInSync(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	D_ASSERT(mdev->tconn->agreed_pro_version >= 89);
+	D_ASSERT(device, peer_device->connection->agreed_pro_version >= 89);
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
-	if (get_ldev(mdev)) {
-		drbd_rs_complete_io(mdev, sector);
-		drbd_set_in_sync(mdev, sector, blksize);
+	if (get_ldev(device)) {
+		drbd_rs_complete_io(device, sector);
+		drbd_set_in_sync(device, sector, blksize);
 		/* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
-		mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
-		put_ldev(mdev);
+		device->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+		put_ldev(device);
 	}
-	dec_rs_pending(mdev);
-	atomic_add(blksize >> 9, &mdev->rs_sect_in);
+	dec_rs_pending(device);
+	atomic_add(blksize >> 9, &device->rs_sect_in);
 
 	return 0;
 }
 
 static int
-validate_req_change_req_state(struct drbd_conf *mdev, u64 id, sector_t sector,
+validate_req_change_req_state(struct drbd_device *device, u64 id, sector_t sector,
 			      struct rb_root *root, const char *func,
 			      enum drbd_req_event what, bool missing_ok)
 {
 	struct drbd_request *req;
 	struct bio_and_error m;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	req = find_request(mdev, root, id, sector, missing_ok, func);
+	spin_lock_irq(&device->resource->req_lock);
+	req = find_request(device, root, id, sector, missing_ok, func);
 	if (unlikely(!req)) {
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 		return -EIO;
 	}
 	__req_mod(req, what, &m);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	if (m.bio)
-		complete_master_bio(mdev, &m);
+		complete_master_bio(device, &m);
 	return 0;
 }
 
-static int got_BlockAck(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_BlockAck(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 	enum drbd_req_event what;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
 	if (p->block_id == ID_SYNCER) {
-		drbd_set_in_sync(mdev, sector, blksize);
-		dec_rs_pending(mdev);
+		drbd_set_in_sync(device, sector, blksize);
+		dec_rs_pending(device);
 		return 0;
 	}
 	switch (pi->cmd) {
@@ -5013,33 +5071,35 @@ static int got_BlockAck(struct drbd_tconn *tconn, struct packet_info *pi)
 		BUG();
 	}
 
-	return validate_req_change_req_state(mdev, p->block_id, sector,
-					     &mdev->write_requests, __func__,
+	return validate_req_change_req_state(device, p->block_id, sector,
+					     &device->write_requests, __func__,
 					     what, false);
 }
 
-static int got_NegAck(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_NegAck(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int size = be32_to_cpu(p->blksize);
 	int err;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
 	if (p->block_id == ID_SYNCER) {
-		dec_rs_pending(mdev);
-		drbd_rs_failed_io(mdev, sector, size);
+		dec_rs_pending(device);
+		drbd_rs_failed_io(device, sector, size);
 		return 0;
 	}
 
-	err = validate_req_change_req_state(mdev, p->block_id, sector,
-					    &mdev->write_requests, __func__,
+	err = validate_req_change_req_state(device, p->block_id, sector,
+					    &device->write_requests, __func__,
 					    NEG_ACKED, true);
 	if (err) {
 		/* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
@@ -5047,80 +5107,86 @@ static int got_NegAck(struct drbd_tconn *tconn, struct packet_info *pi)
 		   request is no longer in the collision hash. */
 		/* In Protocol B we might already have got a P_RECV_ACK
 		   but then get a P_NEG_ACK afterwards. */
-		drbd_set_out_of_sync(mdev, sector, size);
+		drbd_set_out_of_sync(device, sector, size);
 	}
 	return 0;
 }
 
-static int got_NegDReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_NegDReply(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
-	dev_err(DEV, "Got NegDReply; Sector %llus, len %u.\n",
+	drbd_err(device, "Got NegDReply; Sector %llus, len %u.\n",
 	    (unsigned long long)sector, be32_to_cpu(p->blksize));
 
-	return validate_req_change_req_state(mdev, p->block_id, sector,
-					     &mdev->read_requests, __func__,
+	return validate_req_change_req_state(device, p->block_id, sector,
+					     &device->read_requests, __func__,
 					     NEG_ACKED, false);
 }
 
-static int got_NegRSDReply(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_NegRSDReply(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	sector_t sector;
 	int size;
 	struct p_block_ack *p = pi->data;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
 	sector = be64_to_cpu(p->sector);
 	size = be32_to_cpu(p->blksize);
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
-	dec_rs_pending(mdev);
+	dec_rs_pending(device);
 
-	if (get_ldev_if_state(mdev, D_FAILED)) {
-		drbd_rs_complete_io(mdev, sector);
+	if (get_ldev_if_state(device, D_FAILED)) {
+		drbd_rs_complete_io(device, sector);
 		switch (pi->cmd) {
 		case P_NEG_RS_DREPLY:
-			drbd_rs_failed_io(mdev, sector, size);
+			drbd_rs_failed_io(device, sector, size);
 		case P_RS_CANCEL:
 			break;
 		default:
 			BUG();
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	return 0;
 }
 
-static int got_BarrierAck(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_BarrierAck(struct drbd_connection *connection, struct packet_info *pi)
 {
 	struct p_barrier_ack *p = pi->data;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
-	tl_release(tconn, p->barrier, be32_to_cpu(p->set_size));
+	tl_release(connection, p->barrier, be32_to_cpu(p->set_size));
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (mdev->state.conn == C_AHEAD &&
-		    atomic_read(&mdev->ap_in_flight) == 0 &&
-		    !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags)) {
-			mdev->start_resync_timer.expires = jiffies + HZ;
-			add_timer(&mdev->start_resync_timer);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+
+		if (device->state.conn == C_AHEAD &&
+		    atomic_read(&device->ap_in_flight) == 0 &&
+		    !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &device->flags)) {
+			device->start_resync_timer.expires = jiffies + HZ;
+			add_timer(&device->start_resync_timer);
 		}
 	}
 	rcu_read_unlock();
@@ -5128,90 +5194,94 @@ static int got_BarrierAck(struct drbd_tconn *tconn, struct packet_info *pi)
 	return 0;
 }
 
-static int got_OVResult(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_OVResult(struct drbd_connection *connection, struct packet_info *pi)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	struct p_block_ack *p = pi->data;
-	struct drbd_work *w;
+	struct drbd_device_work *dw;
 	sector_t sector;
 	int size;
 
-	mdev = vnr_to_mdev(tconn, pi->vnr);
-	if (!mdev)
+	peer_device = conn_peer_device(connection, pi->vnr);
+	if (!peer_device)
 		return -EIO;
+	device = peer_device->device;
 
 	sector = be64_to_cpu(p->sector);
 	size = be32_to_cpu(p->blksize);
 
-	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
+	update_peer_seq(peer_device, be32_to_cpu(p->seq_num));
 
 	if (be64_to_cpu(p->block_id) == ID_OUT_OF_SYNC)
-		drbd_ov_out_of_sync_found(mdev, sector, size);
+		drbd_ov_out_of_sync_found(device, sector, size);
 	else
-		ov_out_of_sync_print(mdev);
+		ov_out_of_sync_print(device);
 
-	if (!get_ldev(mdev))
+	if (!get_ldev(device))
 		return 0;
 
-	drbd_rs_complete_io(mdev, sector);
-	dec_rs_pending(mdev);
+	drbd_rs_complete_io(device, sector);
+	dec_rs_pending(device);
 
-	--mdev->ov_left;
+	--device->ov_left;
 
 	/* let's advance progress step marks only for every other megabyte */
-	if ((mdev->ov_left & 0x200) == 0x200)
-		drbd_advance_rs_marks(mdev, mdev->ov_left);
-
-	if (mdev->ov_left == 0) {
-		w = kmalloc(sizeof(*w), GFP_NOIO);
-		if (w) {
-			w->cb = w_ov_finished;
-			w->mdev = mdev;
-			drbd_queue_work(&mdev->tconn->sender_work, w);
+	if ((device->ov_left & 0x200) == 0x200)
+		drbd_advance_rs_marks(device, device->ov_left);
+
+	if (device->ov_left == 0) {
+		dw = kmalloc(sizeof(*dw), GFP_NOIO);
+		if (dw) {
+			dw->w.cb = w_ov_finished;
+			dw->device = device;
+			drbd_queue_work(&peer_device->connection->sender_work, &dw->w);
 		} else {
-			dev_err(DEV, "kmalloc(w) failed.");
-			ov_out_of_sync_print(mdev);
-			drbd_resync_finished(mdev);
+			drbd_err(device, "kmalloc(dw) failed.");
+			ov_out_of_sync_print(device);
+			drbd_resync_finished(device);
 		}
 	}
-	put_ldev(mdev);
+	put_ldev(device);
 	return 0;
 }
 
-static int got_skip(struct drbd_tconn *tconn, struct packet_info *pi)
+static int got_skip(struct drbd_connection *connection, struct packet_info *pi)
 {
 	return 0;
 }
 
-static int tconn_finish_peer_reqs(struct drbd_tconn *tconn)
+static int connection_finish_peer_reqs(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr, not_empty = 0;
 
 	do {
-		clear_bit(SIGNAL_ASENDER, &tconn->flags);
+		clear_bit(SIGNAL_ASENDER, &connection->flags);
 		flush_signals(current);
 
 		rcu_read_lock();
-		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-			kref_get(&mdev->kref);
+		idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+			struct drbd_device *device = peer_device->device;
+			kref_get(&device->kref);
 			rcu_read_unlock();
-			if (drbd_finish_peer_reqs(mdev)) {
-				kref_put(&mdev->kref, &drbd_minor_destroy);
+			if (drbd_finish_peer_reqs(device)) {
+				kref_put(&device->kref, drbd_destroy_device);
 				return 1;
 			}
-			kref_put(&mdev->kref, &drbd_minor_destroy);
+			kref_put(&device->kref, drbd_destroy_device);
 			rcu_read_lock();
 		}
-		set_bit(SIGNAL_ASENDER, &tconn->flags);
+		set_bit(SIGNAL_ASENDER, &connection->flags);
 
-		spin_lock_irq(&tconn->req_lock);
-		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-			not_empty = !list_empty(&mdev->done_ee);
+		spin_lock_irq(&connection->resource->req_lock);
+		idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+			struct drbd_device *device = peer_device->device;
+			not_empty = !list_empty(&device->done_ee);
 			if (not_empty)
 				break;
 		}
-		spin_unlock_irq(&tconn->req_lock);
+		spin_unlock_irq(&connection->resource->req_lock);
 		rcu_read_unlock();
 	} while (not_empty);
 
@@ -5220,7 +5290,7 @@ static int tconn_finish_peer_reqs(struct drbd_tconn *tconn)
 
 struct asender_cmd {
 	size_t pkt_size;
-	int (*fn)(struct drbd_tconn *tconn, struct packet_info *);
+	int (*fn)(struct drbd_connection *connection, struct packet_info *);
 };
 
 static struct asender_cmd asender_tbl[] = {
@@ -5245,13 +5315,13 @@ static struct asender_cmd asender_tbl[] = {
 
 int drbd_asender(struct drbd_thread *thi)
 {
-	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_connection *connection = thi->connection;
 	struct asender_cmd *cmd = NULL;
 	struct packet_info pi;
 	int rv;
-	void *buf    = tconn->meta.rbuf;
+	void *buf    = connection->meta.rbuf;
 	int received = 0;
-	unsigned int header_size = drbd_header_size(tconn);
+	unsigned int header_size = drbd_header_size(connection);
 	int expect   = header_size;
 	bool ping_timeout_active = false;
 	struct net_conf *nc;
@@ -5260,45 +5330,45 @@ int drbd_asender(struct drbd_thread *thi)
 
 	rv = sched_setscheduler(current, SCHED_RR, &param);
 	if (rv < 0)
-		conn_err(tconn, "drbd_asender: ERROR set priority, ret=%d\n", rv);
+		drbd_err(connection, "drbd_asender: ERROR set priority, ret=%d\n", rv);
 
 	while (get_t_state(thi) == RUNNING) {
 		drbd_thread_current_set_cpu(thi);
 
 		rcu_read_lock();
-		nc = rcu_dereference(tconn->net_conf);
+		nc = rcu_dereference(connection->net_conf);
 		ping_timeo = nc->ping_timeo;
 		tcp_cork = nc->tcp_cork;
 		ping_int = nc->ping_int;
 		rcu_read_unlock();
 
-		if (test_and_clear_bit(SEND_PING, &tconn->flags)) {
-			if (drbd_send_ping(tconn)) {
-				conn_err(tconn, "drbd_send_ping has failed\n");
+		if (test_and_clear_bit(SEND_PING, &connection->flags)) {
+			if (drbd_send_ping(connection)) {
+				drbd_err(connection, "drbd_send_ping has failed\n");
 				goto reconnect;
 			}
-			tconn->meta.socket->sk->sk_rcvtimeo = ping_timeo * HZ / 10;
+			connection->meta.socket->sk->sk_rcvtimeo = ping_timeo * HZ / 10;
 			ping_timeout_active = true;
 		}
 
 		/* TODO: conditionally cork; it may hurt latency if we cork without
 		   much to send */
 		if (tcp_cork)
-			drbd_tcp_cork(tconn->meta.socket);
-		if (tconn_finish_peer_reqs(tconn)) {
-			conn_err(tconn, "tconn_finish_peer_reqs() failed\n");
+			drbd_tcp_cork(connection->meta.socket);
+		if (connection_finish_peer_reqs(connection)) {
+			drbd_err(connection, "connection_finish_peer_reqs() failed\n");
 			goto reconnect;
 		}
 		/* but unconditionally uncork unless disabled */
 		if (tcp_cork)
-			drbd_tcp_uncork(tconn->meta.socket);
+			drbd_tcp_uncork(connection->meta.socket);
 
 		/* short circuit, recv_msg would return EINTR anyways. */
 		if (signal_pending(current))
 			continue;
 
-		rv = drbd_recv_short(tconn->meta.socket, buf, expect-received, 0);
-		clear_bit(SIGNAL_ASENDER, &tconn->flags);
+		rv = drbd_recv_short(connection->meta.socket, buf, expect-received, 0);
+		clear_bit(SIGNAL_ASENDER, &connection->flags);
 
 		flush_signals(current);
 
@@ -5316,51 +5386,51 @@ int drbd_asender(struct drbd_thread *thi)
 			received += rv;
 			buf	 += rv;
 		} else if (rv == 0) {
-			if (test_bit(DISCONNECT_SENT, &tconn->flags)) {
+			if (test_bit(DISCONNECT_SENT, &connection->flags)) {
 				long t;
 				rcu_read_lock();
-				t = rcu_dereference(tconn->net_conf)->ping_timeo * HZ/10;
+				t = rcu_dereference(connection->net_conf)->ping_timeo * HZ/10;
 				rcu_read_unlock();
 
-				t = wait_event_timeout(tconn->ping_wait,
-						       tconn->cstate < C_WF_REPORT_PARAMS,
+				t = wait_event_timeout(connection->ping_wait,
+						       connection->cstate < C_WF_REPORT_PARAMS,
 						       t);
 				if (t)
 					break;
 			}
-			conn_err(tconn, "meta connection shut down by peer.\n");
+			drbd_err(connection, "meta connection shut down by peer.\n");
 			goto reconnect;
 		} else if (rv == -EAGAIN) {
 			/* If the data socket received something meanwhile,
 			 * that is good enough: peer is still alive. */
-			if (time_after(tconn->last_received,
-				jiffies - tconn->meta.socket->sk->sk_rcvtimeo))
+			if (time_after(connection->last_received,
+				jiffies - connection->meta.socket->sk->sk_rcvtimeo))
 				continue;
 			if (ping_timeout_active) {
-				conn_err(tconn, "PingAck did not arrive in time.\n");
+				drbd_err(connection, "PingAck did not arrive in time.\n");
 				goto reconnect;
 			}
-			set_bit(SEND_PING, &tconn->flags);
+			set_bit(SEND_PING, &connection->flags);
 			continue;
 		} else if (rv == -EINTR) {
 			continue;
 		} else {
-			conn_err(tconn, "sock_recvmsg returned %d\n", rv);
+			drbd_err(connection, "sock_recvmsg returned %d\n", rv);
 			goto reconnect;
 		}
 
 		if (received == expect && cmd == NULL) {
-			if (decode_header(tconn, tconn->meta.rbuf, &pi))
+			if (decode_header(connection, connection->meta.rbuf, &pi))
 				goto reconnect;
 			cmd = &asender_tbl[pi.cmd];
 			if (pi.cmd >= ARRAY_SIZE(asender_tbl) || !cmd->fn) {
-				conn_err(tconn, "Unexpected meta packet %s (0x%04x)\n",
+				drbd_err(connection, "Unexpected meta packet %s (0x%04x)\n",
 					 cmdname(pi.cmd), pi.cmd);
 				goto disconnect;
 			}
 			expect = header_size + cmd->pkt_size;
 			if (pi.size != expect - header_size) {
-				conn_err(tconn, "Wrong packet size on meta (c: %d, l: %d)\n",
+				drbd_err(connection, "Wrong packet size on meta (c: %d, l: %d)\n",
 					pi.cmd, pi.size);
 				goto reconnect;
 			}
@@ -5368,21 +5438,21 @@ int drbd_asender(struct drbd_thread *thi)
 		if (received == expect) {
 			bool err;
 
-			err = cmd->fn(tconn, &pi);
+			err = cmd->fn(connection, &pi);
 			if (err) {
-				conn_err(tconn, "%pf failed\n", cmd->fn);
+				drbd_err(connection, "%pf failed\n", cmd->fn);
 				goto reconnect;
 			}
 
-			tconn->last_received = jiffies;
+			connection->last_received = jiffies;
 
 			if (cmd == &asender_tbl[P_PING_ACK]) {
 				/* restore idle timeout */
-				tconn->meta.socket->sk->sk_rcvtimeo = ping_int * HZ;
+				connection->meta.socket->sk->sk_rcvtimeo = ping_int * HZ;
 				ping_timeout_active = false;
 			}
 
-			buf	 = tconn->meta.rbuf;
+			buf	 = connection->meta.rbuf;
 			received = 0;
 			expect	 = header_size;
 			cmd	 = NULL;
@@ -5391,16 +5461,16 @@ int drbd_asender(struct drbd_thread *thi)
 
 	if (0) {
 reconnect:
-		conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
-		conn_md_sync(tconn);
+		conn_request_state(connection, NS(conn, C_NETWORK_FAILURE), CS_HARD);
+		conn_md_sync(connection);
 	}
 	if (0) {
 disconnect:
-		conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+		conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 	}
-	clear_bit(SIGNAL_ASENDER, &tconn->flags);
+	clear_bit(SIGNAL_ASENDER, &connection->flags);
 
-	conn_info(tconn, "asender terminated\n");
+	drbd_info(connection, "asender terminated\n");
 
 	return 0;
 }
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 104a040f24de..3779c8d2875b 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -31,37 +31,37 @@
 #include "drbd_req.h"
 
 
-static bool drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size);
+static bool drbd_may_do_local_read(struct drbd_device *device, sector_t sector, int size);
 
 /* Update disk stats at start of I/O request */
-static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req)
+static void _drbd_start_io_acct(struct drbd_device *device, struct drbd_request *req)
 {
 	const int rw = bio_data_dir(req->master_bio);
 	int cpu;
 	cpu = part_stat_lock();
-	part_round_stats(cpu, &mdev->vdisk->part0);
-	part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]);
-	part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], req->i.size >> 9);
+	part_round_stats(cpu, &device->vdisk->part0);
+	part_stat_inc(cpu, &device->vdisk->part0, ios[rw]);
+	part_stat_add(cpu, &device->vdisk->part0, sectors[rw], req->i.size >> 9);
 	(void) cpu; /* The macro invocations above want the cpu argument, I do not like
 		       the compiler warning about cpu only assigned but never used... */
-	part_inc_in_flight(&mdev->vdisk->part0, rw);
+	part_inc_in_flight(&device->vdisk->part0, rw);
 	part_stat_unlock();
 }
 
 /* Update disk stats when completing request upwards */
-static void _drbd_end_io_acct(struct drbd_conf *mdev, struct drbd_request *req)
+static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req)
 {
 	int rw = bio_data_dir(req->master_bio);
 	unsigned long duration = jiffies - req->start_time;
 	int cpu;
 	cpu = part_stat_lock();
-	part_stat_add(cpu, &mdev->vdisk->part0, ticks[rw], duration);
-	part_round_stats(cpu, &mdev->vdisk->part0);
-	part_dec_in_flight(&mdev->vdisk->part0, rw);
+	part_stat_add(cpu, &device->vdisk->part0, ticks[rw], duration);
+	part_round_stats(cpu, &device->vdisk->part0);
+	part_dec_in_flight(&device->vdisk->part0, rw);
 	part_stat_unlock();
 }
 
-static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
+static struct drbd_request *drbd_req_new(struct drbd_device *device,
 					       struct bio *bio_src)
 {
 	struct drbd_request *req;
@@ -72,7 +72,7 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
 
 	drbd_req_make_private_bio(req, bio_src);
 	req->rq_state    = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
-	req->w.mdev      = mdev;
+	req->device   = device;
 	req->master_bio  = bio_src;
 	req->epoch       = 0;
 
@@ -95,14 +95,14 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
 void drbd_req_destroy(struct kref *kref)
 {
 	struct drbd_request *req = container_of(kref, struct drbd_request, kref);
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	const unsigned s = req->rq_state;
 
 	if ((req->master_bio && !(s & RQ_POSTPONED)) ||
 		atomic_read(&req->completion_ref) ||
 		(s & RQ_LOCAL_PENDING) ||
 		((s & RQ_NET_MASK) && !(s & RQ_NET_DONE))) {
-		dev_err(DEV, "drbd_req_destroy: Logic BUG rq_state = 0x%x, completion_ref = %d\n",
+		drbd_err(device, "drbd_req_destroy: Logic BUG rq_state = 0x%x, completion_ref = %d\n",
 				s, atomic_read(&req->completion_ref));
 		return;
 	}
@@ -132,10 +132,10 @@ void drbd_req_destroy(struct kref *kref)
 		 */
 		if ((s & (RQ_POSTPONED|RQ_LOCAL_MASK|RQ_NET_MASK)) != RQ_POSTPONED) {
 			if (!(s & RQ_NET_OK) || !(s & RQ_LOCAL_OK))
-				drbd_set_out_of_sync(mdev, req->i.sector, req->i.size);
+				drbd_set_out_of_sync(device, req->i.sector, req->i.size);
 
 			if ((s & RQ_NET_OK) && (s & RQ_LOCAL_OK) && (s & RQ_NET_SIS))
-				drbd_set_in_sync(mdev, req->i.sector, req->i.size);
+				drbd_set_in_sync(device, req->i.sector, req->i.size);
 		}
 
 		/* one might be tempted to move the drbd_al_complete_io
@@ -149,11 +149,11 @@ void drbd_req_destroy(struct kref *kref)
 		 * we would forget to resync the corresponding extent.
 		 */
 		if (s & RQ_IN_ACT_LOG) {
-			if (get_ldev_if_state(mdev, D_FAILED)) {
-				drbd_al_complete_io(mdev, &req->i);
-				put_ldev(mdev);
+			if (get_ldev_if_state(device, D_FAILED)) {
+				drbd_al_complete_io(device, &req->i);
+				put_ldev(device);
 			} else if (__ratelimit(&drbd_ratelimit_state)) {
-				dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu, %u), "
+				drbd_warn(device, "Should have called drbd_al_complete_io(, %llu, %u), "
 					 "but my Disk seems to have failed :(\n",
 					 (unsigned long long) req->i.sector, req->i.size);
 			}
@@ -163,41 +163,42 @@ void drbd_req_destroy(struct kref *kref)
 	mempool_free(req, drbd_request_mempool);
 }
 
-static void wake_all_senders(struct drbd_tconn *tconn) {
-	wake_up(&tconn->sender_work.q_wait);
+static void wake_all_senders(struct drbd_connection *connection)
+{
+	wake_up(&connection->sender_work.q_wait);
 }
 
 /* must hold resource->req_lock */
-void start_new_tl_epoch(struct drbd_tconn *tconn)
+void start_new_tl_epoch(struct drbd_connection *connection)
 {
 	/* no point closing an epoch, if it is empty, anyways. */
-	if (tconn->current_tle_writes == 0)
+	if (connection->current_tle_writes == 0)
 		return;
 
-	tconn->current_tle_writes = 0;
-	atomic_inc(&tconn->current_tle_nr);
-	wake_all_senders(tconn);
+	connection->current_tle_writes = 0;
+	atomic_inc(&connection->current_tle_nr);
+	wake_all_senders(connection);
 }
 
-void complete_master_bio(struct drbd_conf *mdev,
+void complete_master_bio(struct drbd_device *device,
 		struct bio_and_error *m)
 {
 	bio_endio(m->bio, m->error);
-	dec_ap_bio(mdev);
+	dec_ap_bio(device);
 }
 
 
 static void drbd_remove_request_interval(struct rb_root *root,
 					 struct drbd_request *req)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct drbd_interval *i = &req->i;
 
 	drbd_remove_interval(root, i);
 
 	/* Wake up any processes waiting for this request to complete.  */
 	if (i->waiting)
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 }
 
 /* Helper for __req_mod().
@@ -210,7 +211,7 @@ static
 void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 {
 	const unsigned s = req->rq_state;
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	int rw;
 	int error, ok;
 
@@ -226,12 +227,12 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 	if ((s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED)) ||
 	    (s & RQ_NET_QUEUED) || (s & RQ_NET_PENDING) ||
 	    (s & RQ_COMPLETION_SUSP)) {
-		dev_err(DEV, "drbd_req_complete: Logic BUG rq_state = 0x%x\n", s);
+		drbd_err(device, "drbd_req_complete: Logic BUG rq_state = 0x%x\n", s);
 		return;
 	}
 
 	if (!req->master_bio) {
-		dev_err(DEV, "drbd_req_complete: Logic BUG, master_bio == NULL!\n");
+		drbd_err(device, "drbd_req_complete: Logic BUG, master_bio == NULL!\n");
 		return;
 	}
 
@@ -259,9 +260,9 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 		struct rb_root *root;
 
 		if (rw == WRITE)
-			root = &mdev->write_requests;
+			root = &device->write_requests;
 		else
-			root = &mdev->read_requests;
+			root = &device->read_requests;
 		drbd_remove_request_interval(root, req);
 	}
 
@@ -273,11 +274,11 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 	 * and reset the transfer log epoch write_cnt.
 	 */
 	if (rw == WRITE &&
-	    req->epoch == atomic_read(&mdev->tconn->current_tle_nr))
-		start_new_tl_epoch(mdev->tconn);
+	    req->epoch == atomic_read(&first_peer_device(device)->connection->current_tle_nr))
+		start_new_tl_epoch(first_peer_device(device)->connection);
 
 	/* Update disk stats */
-	_drbd_end_io_acct(mdev, req);
+	_drbd_end_io_acct(device, req);
 
 	/* If READ failed,
 	 * have it be pushed back to the retry work queue,
@@ -305,8 +306,8 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 
 static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
 {
-	struct drbd_conf *mdev = req->w.mdev;
-	D_ASSERT(m || (req->rq_state & RQ_POSTPONED));
+	struct drbd_device *device = req->device;
+	D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED));
 
 	if (!atomic_sub_and_test(put, &req->completion_ref))
 		return 0;
@@ -328,12 +329,12 @@ static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_
 static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		int clear, int set)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	unsigned s = req->rq_state;
 	int c_put = 0;
 	int k_put = 0;
 
-	if (drbd_suspended(mdev) && !((s | clear) & RQ_COMPLETION_SUSP))
+	if (drbd_suspended(device) && !((s | clear) & RQ_COMPLETION_SUSP))
 		set |= RQ_COMPLETION_SUSP;
 
 	/* apply */
@@ -351,7 +352,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		atomic_inc(&req->completion_ref);
 
 	if (!(s & RQ_NET_PENDING) && (set & RQ_NET_PENDING)) {
-		inc_ap_pending(mdev);
+		inc_ap_pending(device);
 		atomic_inc(&req->completion_ref);
 	}
 
@@ -362,7 +363,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		kref_get(&req->kref); /* wait for the DONE */
 
 	if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT))
-		atomic_add(req->i.size >> 9, &mdev->ap_in_flight);
+		atomic_add(req->i.size >> 9, &device->ap_in_flight);
 
 	if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
 		atomic_inc(&req->completion_ref);
@@ -373,7 +374,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		++c_put;
 
 	if (!(s & RQ_LOCAL_ABORTED) && (set & RQ_LOCAL_ABORTED)) {
-		D_ASSERT(req->rq_state & RQ_LOCAL_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_LOCAL_PENDING);
 		/* local completion may still come in later,
 		 * we need to keep the req object around. */
 		kref_get(&req->kref);
@@ -388,7 +389,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 	}
 
 	if ((s & RQ_NET_PENDING) && (clear & RQ_NET_PENDING)) {
-		dec_ap_pending(mdev);
+		dec_ap_pending(device);
 		++c_put;
 	}
 
@@ -397,7 +398,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 
 	if ((s & RQ_EXP_BARR_ACK) && !(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
 		if (req->rq_state & RQ_NET_SENT)
-			atomic_sub(req->i.size >> 9, &mdev->ap_in_flight);
+			atomic_sub(req->i.size >> 9, &device->ap_in_flight);
 		++k_put;
 	}
 
@@ -409,14 +410,14 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		int at_least = k_put + !!c_put;
 		int refcount = atomic_read(&req->kref.refcount);
 		if (refcount < at_least)
-			dev_err(DEV,
+			drbd_err(device,
 				"mod_rq_state: Logic BUG: %x -> %x: refcount = %d, should be >= %d\n",
 				s, req->rq_state, refcount, at_least);
 	}
 
 	/* If we made progress, retry conflicting peer requests, if any. */
 	if (req->i.waiting)
-		wake_up(&mdev->misc_wait);
+		wake_up(&device->misc_wait);
 
 	if (c_put)
 		k_put += drbd_req_put_completion_ref(req, m, c_put);
@@ -424,18 +425,18 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		kref_sub(&req->kref, k_put, drbd_req_destroy);
 }
 
-static void drbd_report_io_error(struct drbd_conf *mdev, struct drbd_request *req)
+static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
 {
         char b[BDEVNAME_SIZE];
 
 	if (!__ratelimit(&drbd_ratelimit_state))
 		return;
 
-	dev_warn(DEV, "local %s IO error sector %llu+%u on %s\n",
+	drbd_warn(device, "local %s IO error sector %llu+%u on %s\n",
 			(req->rq_state & RQ_WRITE) ? "WRITE" : "READ",
 			(unsigned long long)req->i.sector,
 			req->i.size >> 9,
-			bdevname(mdev->ldev->backing_bdev, b));
+			bdevname(device->ldev->backing_bdev, b));
 }
 
 /* obviously this could be coded as many single functions
@@ -453,7 +454,7 @@ static void drbd_report_io_error(struct drbd_conf *mdev, struct drbd_request *re
 int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct net_conf *nc;
 	int p, rv = 0;
 
@@ -462,7 +463,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
 	switch (what) {
 	default:
-		dev_err(DEV, "LOGIC BUG in %s:%u\n", __FILE__ , __LINE__);
+		drbd_err(device, "LOGIC BUG in %s:%u\n", __FILE__ , __LINE__);
 		break;
 
 	/* does not happen...
@@ -474,9 +475,9 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 	case TO_BE_SENT: /* via network */
 		/* reached via __drbd_make_request
 		 * and from w_read_retry_remote */
-		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
+		D_ASSERT(device, !(req->rq_state & RQ_NET_MASK));
 		rcu_read_lock();
-		nc = rcu_dereference(mdev->tconn->net_conf);
+		nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 		p = nc->wire_protocol;
 		rcu_read_unlock();
 		req->rq_state |=
@@ -487,15 +488,15 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
 	case TO_BE_SUBMITTED: /* locally */
 		/* reached via __drbd_make_request */
-		D_ASSERT(!(req->rq_state & RQ_LOCAL_MASK));
+		D_ASSERT(device, !(req->rq_state & RQ_LOCAL_MASK));
 		mod_rq_state(req, m, 0, RQ_LOCAL_PENDING);
 		break;
 
 	case COMPLETED_OK:
 		if (req->rq_state & RQ_WRITE)
-			mdev->writ_cnt += req->i.size >> 9;
+			device->writ_cnt += req->i.size >> 9;
 		else
-			mdev->read_cnt += req->i.size >> 9;
+			device->read_cnt += req->i.size >> 9;
 
 		mod_rq_state(req, m, RQ_LOCAL_PENDING,
 				RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
@@ -506,15 +507,15 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		break;
 
 	case WRITE_COMPLETED_WITH_ERROR:
-		drbd_report_io_error(mdev, req);
-		__drbd_chk_io_error(mdev, DRBD_WRITE_ERROR);
+		drbd_report_io_error(device, req);
+		__drbd_chk_io_error(device, DRBD_WRITE_ERROR);
 		mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED);
 		break;
 
 	case READ_COMPLETED_WITH_ERROR:
-		drbd_set_out_of_sync(mdev, req->i.sector, req->i.size);
-		drbd_report_io_error(mdev, req);
-		__drbd_chk_io_error(mdev, DRBD_READ_ERROR);
+		drbd_set_out_of_sync(device, req->i.sector, req->i.size);
+		drbd_report_io_error(device, req);
+		__drbd_chk_io_error(device, DRBD_READ_ERROR);
 		/* fall through. */
 	case READ_AHEAD_COMPLETED_WITH_ERROR:
 		/* it is legal to fail READA, no __drbd_chk_io_error in that case. */
@@ -532,16 +533,17 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		/* So we can verify the handle in the answer packet.
 		 * Corresponding drbd_remove_request_interval is in
 		 * drbd_req_complete() */
-		D_ASSERT(drbd_interval_empty(&req->i));
-		drbd_insert_interval(&mdev->read_requests, &req->i);
+		D_ASSERT(device, drbd_interval_empty(&req->i));
+		drbd_insert_interval(&device->read_requests, &req->i);
 
-		set_bit(UNPLUG_REMOTE, &mdev->flags);
+		set_bit(UNPLUG_REMOTE, &device->flags);
 
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		D_ASSERT((req->rq_state & RQ_LOCAL_MASK) == 0);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, (req->rq_state & RQ_LOCAL_MASK) == 0);
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
 		req->w.cb = w_send_read_req;
-		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&req->w);
 		break;
 
 	case QUEUE_FOR_NET_WRITE:
@@ -550,8 +552,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
 		/* Corresponding drbd_remove_request_interval is in
 		 * drbd_req_complete() */
-		D_ASSERT(drbd_interval_empty(&req->i));
-		drbd_insert_interval(&mdev->write_requests, &req->i);
+		D_ASSERT(device, drbd_interval_empty(&req->i));
+		drbd_insert_interval(&device->write_requests, &req->i);
 
 		/* NOTE
 		 * In case the req ended up on the transfer log before being
@@ -570,28 +572,30 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		/* otherwise we may lose an unplug, which may cause some remote
 		 * io-scheduler timeout to expire, increasing maximum latency,
 		 * hurting performance. */
-		set_bit(UNPLUG_REMOTE, &mdev->flags);
+		set_bit(UNPLUG_REMOTE, &device->flags);
 
 		/* queue work item to send data */
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED|RQ_EXP_BARR_ACK);
 		req->w.cb =  w_send_dblock;
-		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&req->w);
 
 		/* close the epoch, in case it outgrew the limit */
 		rcu_read_lock();
-		nc = rcu_dereference(mdev->tconn->net_conf);
+		nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 		p = nc->max_epoch_size;
 		rcu_read_unlock();
-		if (mdev->tconn->current_tle_writes >= p)
-			start_new_tl_epoch(mdev->tconn);
+		if (first_peer_device(device)->connection->current_tle_writes >= p)
+			start_new_tl_epoch(first_peer_device(device)->connection);
 
 		break;
 
 	case QUEUE_FOR_SEND_OOS:
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
 		req->w.cb =  w_send_out_of_sync;
-		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&req->w);
 		break;
 
 	case READ_RETRY_REMOTE_CANCELED:
@@ -639,15 +643,15 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		 * If this request had been marked as RQ_POSTPONED before,
 		 * it will actually not be completed, but "restarted",
 		 * resubmitted from the retry worker context. */
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_EXP_WRITE_ACK);
 		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_DONE|RQ_NET_OK);
 		break;
 
 	case WRITE_ACKED_BY_PEER_AND_SIS:
 		req->rq_state |= RQ_NET_SIS;
 	case WRITE_ACKED_BY_PEER:
-		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
+		D_ASSERT(device, req->rq_state & RQ_EXP_WRITE_ACK);
 		/* protocol C; successfully written on peer.
 		 * Nothing more to do here.
 		 * We want to keep the tl in place for all protocols, to cater
@@ -655,25 +659,25 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
 		goto ack_common;
 	case RECV_ACKED_BY_PEER:
-		D_ASSERT(req->rq_state & RQ_EXP_RECEIVE_ACK);
+		D_ASSERT(device, req->rq_state & RQ_EXP_RECEIVE_ACK);
 		/* protocol B; pretends to be successfully written on peer.
 		 * see also notes above in HANDED_OVER_TO_NETWORK about
 		 * protocol != C */
 	ack_common:
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
 		break;
 
 	case POSTPONE_WRITE:
-		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
+		D_ASSERT(device, req->rq_state & RQ_EXP_WRITE_ACK);
 		/* If this node has already detected the write conflict, the
 		 * worker will be waiting on misc_wait.  Wake it up once this
 		 * request has completed locally.
 		 */
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		req->rq_state |= RQ_POSTPONED;
 		if (req->i.waiting)
-			wake_up(&mdev->misc_wait);
+			wake_up(&device->misc_wait);
 		/* Do not clear RQ_NET_PENDING. This request will make further
 		 * progress via restart_conflicting_writes() or
 		 * fail_postponed_requests(). Hopefully. */
@@ -701,9 +705,10 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		if (bio_data_dir(req->master_bio) == WRITE)
 			rv = MR_WRITE;
 
-		get_ldev(mdev); /* always succeeds in this call path */
+		get_ldev(device); /* always succeeds in this call path */
 		req->w.cb = w_restart_disk_io;
-		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&req->w);
 		break;
 
 	case RESEND:
@@ -719,12 +724,13 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		   Throwing them out of the TL here by pretending we got a BARRIER_ACK.
 		   During connection handshake, we ensure that the peer was not rebooted. */
 		if (!(req->rq_state & RQ_NET_OK)) {
-			/* FIXME could this possibly be a req->w.cb == w_send_out_of_sync?
+			/* FIXME could this possibly be a req->dw.cb == w_send_out_of_sync?
 			 * in that case we must not set RQ_NET_PENDING. */
 
 			mod_rq_state(req, m, RQ_COMPLETION_SUSP, RQ_NET_QUEUED|RQ_NET_PENDING);
 			if (req->w.cb) {
-				drbd_queue_work(&mdev->tconn->sender_work, &req->w);
+				drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+						&req->w);
 				rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
 			} /* else: FIXME can this happen? */
 			break;
@@ -740,7 +746,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 			/* barrier came in before all requests were acked.
 			 * this is bad, because if the connection is lost now,
 			 * we won't be able to clean them up... */
-			dev_err(DEV, "FIXME (BARRIER_ACKED but pending)\n");
+			drbd_err(device, "FIXME (BARRIER_ACKED but pending)\n");
 		}
 		/* Allowed to complete requests, even while suspended.
 		 * As this is called for all requests within a matching epoch,
@@ -751,12 +757,12 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		break;
 
 	case DATA_RECEIVED:
-		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK|RQ_NET_DONE);
 		break;
 
 	case QUEUE_AS_DRBD_BARRIER:
-		start_new_tl_epoch(mdev->tconn);
+		start_new_tl_epoch(first_peer_device(device)->connection);
 		mod_rq_state(req, m, 0, RQ_NET_OK|RQ_NET_DONE);
 		break;
 	};
@@ -771,27 +777,27 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
  *   since size may be bigger than BM_BLOCK_SIZE,
  *   we may need to check several bits.
  */
-static bool drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size)
+static bool drbd_may_do_local_read(struct drbd_device *device, sector_t sector, int size)
 {
 	unsigned long sbnr, ebnr;
 	sector_t esector, nr_sectors;
 
-	if (mdev->state.disk == D_UP_TO_DATE)
+	if (device->state.disk == D_UP_TO_DATE)
 		return true;
-	if (mdev->state.disk != D_INCONSISTENT)
+	if (device->state.disk != D_INCONSISTENT)
 		return false;
 	esector = sector + (size >> 9) - 1;
-	nr_sectors = drbd_get_capacity(mdev->this_bdev);
-	D_ASSERT(sector  < nr_sectors);
-	D_ASSERT(esector < nr_sectors);
+	nr_sectors = drbd_get_capacity(device->this_bdev);
+	D_ASSERT(device, sector  < nr_sectors);
+	D_ASSERT(device, esector < nr_sectors);
 
 	sbnr = BM_SECT_TO_BIT(sector);
 	ebnr = BM_SECT_TO_BIT(esector);
 
-	return drbd_bm_count_bits(mdev, sbnr, ebnr) == 0;
+	return drbd_bm_count_bits(device, sbnr, ebnr) == 0;
 }
 
-static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector,
+static bool remote_due_to_read_balancing(struct drbd_device *device, sector_t sector,
 		enum drbd_read_balancing rbm)
 {
 	struct backing_dev_info *bdi;
@@ -799,11 +805,11 @@ static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector
 
 	switch (rbm) {
 	case RB_CONGESTED_REMOTE:
-		bdi = &mdev->ldev->backing_bdev->bd_disk->queue->backing_dev_info;
+		bdi = &device->ldev->backing_bdev->bd_disk->queue->backing_dev_info;
 		return bdi_read_congested(bdi);
 	case RB_LEAST_PENDING:
-		return atomic_read(&mdev->local_cnt) >
-			atomic_read(&mdev->ap_pending_cnt) + atomic_read(&mdev->rs_pending_cnt);
+		return atomic_read(&device->local_cnt) >
+			atomic_read(&device->ap_pending_cnt) + atomic_read(&device->rs_pending_cnt);
 	case RB_32K_STRIPING:  /* stripe_shift = 15 */
 	case RB_64K_STRIPING:
 	case RB_128K_STRIPING:
@@ -813,7 +819,7 @@ static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector
 		stripe_shift = (rbm - RB_32K_STRIPING + 15);
 		return (sector >> (stripe_shift - 9)) & 1;
 	case RB_ROUND_ROBIN:
-		return test_and_change_bit(READ_BALANCE_RR, &mdev->flags);
+		return test_and_change_bit(READ_BALANCE_RR, &device->flags);
 	case RB_PREFER_REMOTE:
 		return true;
 	case RB_PREFER_LOCAL:
@@ -834,73 +840,73 @@ static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector
 static void complete_conflicting_writes(struct drbd_request *req)
 {
 	DEFINE_WAIT(wait);
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct drbd_interval *i;
 	sector_t sector = req->i.sector;
 	int size = req->i.size;
 
-	i = drbd_find_overlap(&mdev->write_requests, sector, size);
+	i = drbd_find_overlap(&device->write_requests, sector, size);
 	if (!i)
 		return;
 
 	for (;;) {
-		prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
-		i = drbd_find_overlap(&mdev->write_requests, sector, size);
+		prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
+		i = drbd_find_overlap(&device->write_requests, sector, size);
 		if (!i)
 			break;
 		/* Indicate to wake up device->misc_wait on progress.  */
 		i->waiting = true;
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 		schedule();
-		spin_lock_irq(&mdev->tconn->req_lock);
+		spin_lock_irq(&device->resource->req_lock);
 	}
-	finish_wait(&mdev->misc_wait, &wait);
+	finish_wait(&device->misc_wait, &wait);
 }
 
 /* called within req_lock and rcu_read_lock() */
-static void maybe_pull_ahead(struct drbd_conf *mdev)
+static void maybe_pull_ahead(struct drbd_device *device)
 {
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	struct net_conf *nc;
 	bool congested = false;
 	enum drbd_on_congestion on_congestion;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	on_congestion = nc ? nc->on_congestion : OC_BLOCK;
 	rcu_read_unlock();
 	if (on_congestion == OC_BLOCK ||
-	    tconn->agreed_pro_version < 96)
+	    connection->agreed_pro_version < 96)
 		return;
 
 	/* If I don't even have good local storage, we can not reasonably try
 	 * to pull ahead of the peer. We also need the local reference to make
-	 * sure mdev->act_log is there.
+	 * sure device->act_log is there.
 	 */
-	if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
+	if (!get_ldev_if_state(device, D_UP_TO_DATE))
 		return;
 
 	if (nc->cong_fill &&
-	    atomic_read(&mdev->ap_in_flight) >= nc->cong_fill) {
-		dev_info(DEV, "Congestion-fill threshold reached\n");
+	    atomic_read(&device->ap_in_flight) >= nc->cong_fill) {
+		drbd_info(device, "Congestion-fill threshold reached\n");
 		congested = true;
 	}
 
-	if (mdev->act_log->used >= nc->cong_extents) {
-		dev_info(DEV, "Congestion-extents threshold reached\n");
+	if (device->act_log->used >= nc->cong_extents) {
+		drbd_info(device, "Congestion-extents threshold reached\n");
 		congested = true;
 	}
 
 	if (congested) {
 		/* start a new epoch for non-mirrored writes */
-		start_new_tl_epoch(mdev->tconn);
+		start_new_tl_epoch(first_peer_device(device)->connection);
 
 		if (on_congestion == OC_PULL_AHEAD)
-			_drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
+			_drbd_set_state(_NS(device, conn, C_AHEAD), 0, NULL);
 		else  /*nc->on_congestion == OC_DISCONNECT */
-			_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
+			_drbd_set_state(_NS(device, conn, C_DISCONNECTING), 0, NULL);
 	}
-	put_ldev(mdev);
+	put_ldev(device);
 }
 
 /* If this returns false, and req->private_bio is still set,
@@ -914,19 +920,19 @@ static void maybe_pull_ahead(struct drbd_conf *mdev)
  */
 static bool do_remote_read(struct drbd_request *req)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	enum drbd_read_balancing rbm;
 
 	if (req->private_bio) {
-		if (!drbd_may_do_local_read(mdev,
+		if (!drbd_may_do_local_read(device,
 					req->i.sector, req->i.size)) {
 			bio_put(req->private_bio);
 			req->private_bio = NULL;
-			put_ldev(mdev);
+			put_ldev(device);
 		}
 	}
 
-	if (mdev->state.pdsk != D_UP_TO_DATE)
+	if (device->state.pdsk != D_UP_TO_DATE)
 		return false;
 
 	if (req->private_bio == NULL)
@@ -936,17 +942,17 @@ static bool do_remote_read(struct drbd_request *req)
 	 * protocol, pending requests etc. */
 
 	rcu_read_lock();
-	rbm = rcu_dereference(mdev->ldev->disk_conf)->read_balancing;
+	rbm = rcu_dereference(device->ldev->disk_conf)->read_balancing;
 	rcu_read_unlock();
 
 	if (rbm == RB_PREFER_LOCAL && req->private_bio)
 		return false; /* submit locally */
 
-	if (remote_due_to_read_balancing(mdev, req->i.sector, rbm)) {
+	if (remote_due_to_read_balancing(device, req->i.sector, rbm)) {
 		if (req->private_bio) {
 			bio_put(req->private_bio);
 			req->private_bio = NULL;
-			put_ldev(mdev);
+			put_ldev(device);
 		}
 		return true;
 	}
@@ -959,11 +965,11 @@ static bool do_remote_read(struct drbd_request *req)
  * which does NOT include those that we are L_AHEAD for. */
 static int drbd_process_write_request(struct drbd_request *req)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	int remote, send_oos;
 
-	remote = drbd_should_do_remote(mdev->state);
-	send_oos = drbd_should_send_out_of_sync(mdev->state);
+	remote = drbd_should_do_remote(device->state);
+	send_oos = drbd_should_send_out_of_sync(device->state);
 
 	/* Need to replicate writes.  Unless it is an empty flush,
 	 * which is better mapped to a DRBD P_BARRIER packet,
@@ -973,7 +979,7 @@ static int drbd_process_write_request(struct drbd_request *req)
 	 * replicating, in which case there is no point. */
 	if (unlikely(req->i.size == 0)) {
 		/* The only size==0 bios we expect are empty flushes. */
-		D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH);
+		D_ASSERT(device, req->master_bio->bi_rw & REQ_FLUSH);
 		if (remote)
 			_req_mod(req, QUEUE_AS_DRBD_BARRIER);
 		return remote;
@@ -982,12 +988,12 @@ static int drbd_process_write_request(struct drbd_request *req)
 	if (!remote && !send_oos)
 		return 0;
 
-	D_ASSERT(!(remote && send_oos));
+	D_ASSERT(device, !(remote && send_oos));
 
 	if (remote) {
 		_req_mod(req, TO_BE_SENT);
 		_req_mod(req, QUEUE_FOR_NET_WRITE);
-	} else if (drbd_set_out_of_sync(mdev, req->i.sector, req->i.size))
+	} else if (drbd_set_out_of_sync(device, req->i.sector, req->i.size))
 		_req_mod(req, QUEUE_FOR_SEND_OOS);
 
 	return remote;
@@ -996,36 +1002,36 @@ static int drbd_process_write_request(struct drbd_request *req)
 static void
 drbd_submit_req_private_bio(struct drbd_request *req)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct bio *bio = req->private_bio;
 	const int rw = bio_rw(bio);
 
-	bio->bi_bdev = mdev->ldev->backing_bdev;
+	bio->bi_bdev = device->ldev->backing_bdev;
 
 	/* State may have changed since we grabbed our reference on the
 	 * ->ldev member. Double check, and short-circuit to endio.
 	 * In case the last activity log transaction failed to get on
 	 * stable storage, and this is a WRITE, we may not even submit
 	 * this bio. */
-	if (get_ldev(mdev)) {
-		if (drbd_insert_fault(mdev,
+	if (get_ldev(device)) {
+		if (drbd_insert_fault(device,
 				      rw == WRITE ? DRBD_FAULT_DT_WR
 				    : rw == READ  ? DRBD_FAULT_DT_RD
 				    :               DRBD_FAULT_DT_RA))
 			bio_endio(bio, -EIO);
 		else
 			generic_make_request(bio);
-		put_ldev(mdev);
+		put_ldev(device);
 	} else
 		bio_endio(bio, -EIO);
 }
 
-static void drbd_queue_write(struct drbd_conf *mdev, struct drbd_request *req)
+static void drbd_queue_write(struct drbd_device *device, struct drbd_request *req)
 {
-	spin_lock(&mdev->submit.lock);
-	list_add_tail(&req->tl_requests, &mdev->submit.writes);
-	spin_unlock(&mdev->submit.lock);
-	queue_work(mdev->submit.wq, &mdev->submit.worker);
+	spin_lock(&device->submit.lock);
+	list_add_tail(&req->tl_requests, &device->submit.writes);
+	spin_unlock(&device->submit.lock);
+	queue_work(device->submit.wq, &device->submit.worker);
 }
 
 /* returns the new drbd_request pointer, if the caller is expected to
@@ -1033,36 +1039,36 @@ static void drbd_queue_write(struct drbd_conf *mdev, struct drbd_request *req)
  * request on the submitter thread.
  * Returns ERR_PTR(-ENOMEM) if we cannot allocate a drbd_request.
  */
-struct drbd_request *
-drbd_request_prepare(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+static struct drbd_request *
+drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long start_time)
 {
 	const int rw = bio_data_dir(bio);
 	struct drbd_request *req;
 
 	/* allocate outside of all locks; */
-	req = drbd_req_new(mdev, bio);
+	req = drbd_req_new(device, bio);
 	if (!req) {
-		dec_ap_bio(mdev);
+		dec_ap_bio(device);
 		/* only pass the error to the upper layers.
 		 * if user cannot handle io errors, that's not our business. */
-		dev_err(DEV, "could not kmalloc() req\n");
+		drbd_err(device, "could not kmalloc() req\n");
 		bio_endio(bio, -ENOMEM);
 		return ERR_PTR(-ENOMEM);
 	}
 	req->start_time = start_time;
 
-	if (!get_ldev(mdev)) {
+	if (!get_ldev(device)) {
 		bio_put(req->private_bio);
 		req->private_bio = NULL;
 	}
 
 	/* Update disk stats */
-	_drbd_start_io_acct(mdev, req);
+	_drbd_start_io_acct(device, req);
 
 	if (rw == WRITE && req->private_bio && req->i.size
-	&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
-		if (!drbd_al_begin_io_fastpath(mdev, &req->i)) {
-			drbd_queue_write(mdev, req);
+	&& !test_bit(AL_SUSPENDED, &device->flags)) {
+		if (!drbd_al_begin_io_fastpath(device, &req->i)) {
+			drbd_queue_write(device, req);
 			return NULL;
 		}
 		req->rq_state |= RQ_IN_ACT_LOG;
@@ -1071,13 +1077,13 @@ drbd_request_prepare(struct drbd_conf *mdev, struct bio *bio, unsigned long star
 	return req;
 }
 
-static void drbd_send_and_submit(struct drbd_conf *mdev, struct drbd_request *req)
+static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req)
 {
 	const int rw = bio_rw(req->master_bio);
 	struct bio_and_error m = { NULL, };
 	bool no_remote = false;
 
-	spin_lock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
 	if (rw == WRITE) {
 		/* This may temporarily give up the req_lock,
 		 * but will re-aquire it before it returns here.
@@ -1087,17 +1093,17 @@ static void drbd_send_and_submit(struct drbd_conf *mdev, struct drbd_request *re
 
 		/* check for congestion, and potentially stop sending
 		 * full data updates, but start sending "dirty bits" only. */
-		maybe_pull_ahead(mdev);
+		maybe_pull_ahead(device);
 	}
 
 
-	if (drbd_suspended(mdev)) {
+	if (drbd_suspended(device)) {
 		/* push back and retry: */
 		req->rq_state |= RQ_POSTPONED;
 		if (req->private_bio) {
 			bio_put(req->private_bio);
 			req->private_bio = NULL;
-			put_ldev(mdev);
+			put_ldev(device);
 		}
 		goto out;
 	}
@@ -1111,15 +1117,15 @@ static void drbd_send_and_submit(struct drbd_conf *mdev, struct drbd_request *re
 	}
 
 	/* which transfer log epoch does this belong to? */
-	req->epoch = atomic_read(&mdev->tconn->current_tle_nr);
+	req->epoch = atomic_read(&first_peer_device(device)->connection->current_tle_nr);
 
 	/* no point in adding empty flushes to the transfer log,
 	 * they are mapped to drbd barriers already. */
 	if (likely(req->i.size!=0)) {
 		if (rw == WRITE)
-			mdev->tconn->current_tle_writes++;
+			first_peer_device(device)->connection->current_tle_writes++;
 
-		list_add_tail(&req->tl_requests, &mdev->tconn->transfer_log);
+		list_add_tail(&req->tl_requests, &first_peer_device(device)->connection->transfer_log);
 	}
 
 	if (rw == WRITE) {
@@ -1139,13 +1145,13 @@ static void drbd_send_and_submit(struct drbd_conf *mdev, struct drbd_request *re
 		/* needs to be marked within the same spinlock */
 		_req_mod(req, TO_BE_SUBMITTED);
 		/* but we need to give up the spinlock to submit */
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 		drbd_submit_req_private_bio(req);
-		spin_lock_irq(&mdev->tconn->req_lock);
+		spin_lock_irq(&device->resource->req_lock);
 	} else if (no_remote) {
 nodata:
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "IO ERROR: neither local nor remote data, sector %llu+%u\n",
+			drbd_err(device, "IO ERROR: neither local nor remote data, sector %llu+%u\n",
 					(unsigned long long)req->i.sector, req->i.size >> 9);
 		/* A write may have been queued for send_oos, however.
 		 * So we can not simply free it, we must go through drbd_req_put_completion_ref() */
@@ -1154,21 +1160,21 @@ nodata:
 out:
 	if (drbd_req_put_completion_ref(req, &m, 1))
 		kref_put(&req->kref, drbd_req_destroy);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	if (m.bio)
-		complete_master_bio(mdev, &m);
+		complete_master_bio(device, &m);
 }
 
-void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+void __drbd_make_request(struct drbd_device *device, struct bio *bio, unsigned long start_time)
 {
-	struct drbd_request *req = drbd_request_prepare(mdev, bio, start_time);
+	struct drbd_request *req = drbd_request_prepare(device, bio, start_time);
 	if (IS_ERR_OR_NULL(req))
 		return;
-	drbd_send_and_submit(mdev, req);
+	drbd_send_and_submit(device, req);
 }
 
-static void submit_fast_path(struct drbd_conf *mdev, struct list_head *incoming)
+static void submit_fast_path(struct drbd_device *device, struct list_head *incoming)
 {
 	struct drbd_request *req, *tmp;
 	list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
@@ -1176,19 +1182,19 @@ static void submit_fast_path(struct drbd_conf *mdev, struct list_head *incoming)
 
 		if (rw == WRITE /* rw != WRITE should not even end up here! */
 		&& req->private_bio && req->i.size
-		&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
-			if (!drbd_al_begin_io_fastpath(mdev, &req->i))
+		&& !test_bit(AL_SUSPENDED, &device->flags)) {
+			if (!drbd_al_begin_io_fastpath(device, &req->i))
 				continue;
 
 			req->rq_state |= RQ_IN_ACT_LOG;
 		}
 
 		list_del_init(&req->tl_requests);
-		drbd_send_and_submit(mdev, req);
+		drbd_send_and_submit(device, req);
 	}
 }
 
-static bool prepare_al_transaction_nonblock(struct drbd_conf *mdev,
+static bool prepare_al_transaction_nonblock(struct drbd_device *device,
 					    struct list_head *incoming,
 					    struct list_head *pending)
 {
@@ -1196,9 +1202,9 @@ static bool prepare_al_transaction_nonblock(struct drbd_conf *mdev,
 	int wake = 0;
 	int err;
 
-	spin_lock_irq(&mdev->al_lock);
+	spin_lock_irq(&device->al_lock);
 	list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
-		err = drbd_al_begin_io_nonblock(mdev, &req->i);
+		err = drbd_al_begin_io_nonblock(device, &req->i);
 		if (err == -EBUSY)
 			wake = 1;
 		if (err)
@@ -1206,30 +1212,30 @@ static bool prepare_al_transaction_nonblock(struct drbd_conf *mdev,
 		req->rq_state |= RQ_IN_ACT_LOG;
 		list_move_tail(&req->tl_requests, pending);
 	}
-	spin_unlock_irq(&mdev->al_lock);
+	spin_unlock_irq(&device->al_lock);
 	if (wake)
-		wake_up(&mdev->al_wait);
+		wake_up(&device->al_wait);
 
 	return !list_empty(pending);
 }
 
 void do_submit(struct work_struct *ws)
 {
-	struct drbd_conf *mdev = container_of(ws, struct drbd_conf, submit.worker);
+	struct drbd_device *device = container_of(ws, struct drbd_device, submit.worker);
 	LIST_HEAD(incoming);
 	LIST_HEAD(pending);
 	struct drbd_request *req, *tmp;
 
 	for (;;) {
-		spin_lock(&mdev->submit.lock);
-		list_splice_tail_init(&mdev->submit.writes, &incoming);
-		spin_unlock(&mdev->submit.lock);
+		spin_lock(&device->submit.lock);
+		list_splice_tail_init(&device->submit.writes, &incoming);
+		spin_unlock(&device->submit.lock);
 
-		submit_fast_path(mdev, &incoming);
+		submit_fast_path(device, &incoming);
 		if (list_empty(&incoming))
 			break;
 
-		wait_event(mdev->al_wait, prepare_al_transaction_nonblock(mdev, &incoming, &pending));
+		wait_event(device->al_wait, prepare_al_transaction_nonblock(device, &incoming, &pending));
 		/* Maybe more was queued, while we prepared the transaction?
 		 * Try to stuff them into this transaction as well.
 		 * Be strictly non-blocking here, no wait_event, we already
@@ -1243,17 +1249,17 @@ void do_submit(struct work_struct *ws)
 
 			/* It is ok to look outside the lock,
 			 * it's only an optimization anyways */
-			if (list_empty(&mdev->submit.writes))
+			if (list_empty(&device->submit.writes))
 				break;
 
-			spin_lock(&mdev->submit.lock);
-			list_splice_tail_init(&mdev->submit.writes, &more_incoming);
-			spin_unlock(&mdev->submit.lock);
+			spin_lock(&device->submit.lock);
+			list_splice_tail_init(&device->submit.writes, &more_incoming);
+			spin_unlock(&device->submit.lock);
 
 			if (list_empty(&more_incoming))
 				break;
 
-			made_progress = prepare_al_transaction_nonblock(mdev, &more_incoming, &more_pending);
+			made_progress = prepare_al_transaction_nonblock(device, &more_incoming, &more_pending);
 
 			list_splice_tail_init(&more_pending, &pending);
 			list_splice_tail_init(&more_incoming, &incoming);
@@ -1261,18 +1267,18 @@ void do_submit(struct work_struct *ws)
 			if (!made_progress)
 				break;
 		}
-		drbd_al_begin_io_commit(mdev, false);
+		drbd_al_begin_io_commit(device, false);
 
 		list_for_each_entry_safe(req, tmp, &pending, tl_requests) {
 			list_del_init(&req->tl_requests);
-			drbd_send_and_submit(mdev, req);
+			drbd_send_and_submit(device, req);
 		}
 	}
 }
 
 void drbd_make_request(struct request_queue *q, struct bio *bio)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
+	struct drbd_device *device = (struct drbd_device *) q->queuedata;
 	unsigned long start_time;
 
 	start_time = jiffies;
@@ -1280,10 +1286,10 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
 	/*
 	 * what we "blindly" assume:
 	 */
-	D_ASSERT(IS_ALIGNED(bio->bi_iter.bi_size, 512));
+	D_ASSERT(device, IS_ALIGNED(bio->bi_iter.bi_size, 512));
 
-	inc_ap_bio(mdev);
-	__drbd_make_request(mdev, bio, start_time);
+	inc_ap_bio(device);
+	__drbd_make_request(device, bio, start_time);
 }
 
 /* This is called by bio_add_page().
@@ -1300,32 +1306,32 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
  */
 int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
+	struct drbd_device *device = (struct drbd_device *) q->queuedata;
 	unsigned int bio_size = bvm->bi_size;
 	int limit = DRBD_MAX_BIO_SIZE;
 	int backing_limit;
 
-	if (bio_size && get_ldev(mdev)) {
+	if (bio_size && get_ldev(device)) {
 		unsigned int max_hw_sectors = queue_max_hw_sectors(q);
 		struct request_queue * const b =
-			mdev->ldev->backing_bdev->bd_disk->queue;
+			device->ldev->backing_bdev->bd_disk->queue;
 		if (b->merge_bvec_fn) {
 			backing_limit = b->merge_bvec_fn(b, bvm, bvec);
 			limit = min(limit, backing_limit);
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 		if ((limit >> 9) > max_hw_sectors)
 			limit = max_hw_sectors << 9;
 	}
 	return limit;
 }
 
-struct drbd_request *find_oldest_request(struct drbd_tconn *tconn)
+static struct drbd_request *find_oldest_request(struct drbd_connection *connection)
 {
 	/* Walk the transfer log,
 	 * and find the oldest not yet completed request */
 	struct drbd_request *r;
-	list_for_each_entry(r, &tconn->transfer_log, tl_requests) {
+	list_for_each_entry(r, &connection->transfer_log, tl_requests) {
 		if (atomic_read(&r->completion_ref))
 			return r;
 	}
@@ -1334,21 +1340,21 @@ struct drbd_request *find_oldest_request(struct drbd_tconn *tconn)
 
 void request_timer_fn(unsigned long data)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_device *device = (struct drbd_device *) data;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	struct drbd_request *req; /* oldest request */
 	struct net_conf *nc;
 	unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */
 	unsigned long now;
 
 	rcu_read_lock();
-	nc = rcu_dereference(tconn->net_conf);
-	if (nc && mdev->state.conn >= C_WF_REPORT_PARAMS)
+	nc = rcu_dereference(connection->net_conf);
+	if (nc && device->state.conn >= C_WF_REPORT_PARAMS)
 		ent = nc->timeout * HZ/10 * nc->ko_count;
 
-	if (get_ldev(mdev)) { /* implicit state.disk >= D_INCONSISTENT */
-		dt = rcu_dereference(mdev->ldev->disk_conf)->disk_timeout * HZ / 10;
-		put_ldev(mdev);
+	if (get_ldev(device)) { /* implicit state.disk >= D_INCONSISTENT */
+		dt = rcu_dereference(device->ldev->disk_conf)->disk_timeout * HZ / 10;
+		put_ldev(device);
 	}
 	rcu_read_unlock();
 
@@ -1359,11 +1365,11 @@ void request_timer_fn(unsigned long data)
 
 	now = jiffies;
 
-	spin_lock_irq(&tconn->req_lock);
-	req = find_oldest_request(tconn);
+	spin_lock_irq(&device->resource->req_lock);
+	req = find_oldest_request(connection);
 	if (!req) {
-		spin_unlock_irq(&tconn->req_lock);
-		mod_timer(&mdev->request_timer, now + et);
+		spin_unlock_irq(&device->resource->req_lock);
+		mod_timer(&device->request_timer, now + et);
 		return;
 	}
 
@@ -1385,17 +1391,17 @@ void request_timer_fn(unsigned long data)
 	 */
 	if (ent && req->rq_state & RQ_NET_PENDING &&
 		 time_after(now, req->start_time + ent) &&
-		!time_in_range(now, tconn->last_reconnect_jif, tconn->last_reconnect_jif + ent)) {
-		dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
-		_drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
+		!time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) {
+		drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
+		_drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
 	}
-	if (dt && req->rq_state & RQ_LOCAL_PENDING && req->w.mdev == mdev &&
+	if (dt && req->rq_state & RQ_LOCAL_PENDING && req->device == device &&
 		 time_after(now, req->start_time + dt) &&
-		!time_in_range(now, mdev->last_reattach_jif, mdev->last_reattach_jif + dt)) {
-		dev_warn(DEV, "Local backing device failed to meet the disk-timeout\n");
-		__drbd_chk_io_error(mdev, DRBD_FORCE_DETACH);
+		!time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) {
+		drbd_warn(device, "Local backing device failed to meet the disk-timeout\n");
+		__drbd_chk_io_error(device, DRBD_FORCE_DETACH);
 	}
 	nt = (time_after(now, req->start_time + et) ? now : req->start_time) + et;
-	spin_unlock_irq(&tconn->req_lock);
-	mod_timer(&mdev->request_timer, nt);
+	spin_unlock_irq(&connection->resource->req_lock);
+	mod_timer(&device->request_timer, nt);
 }
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 28e15d91197a..c684c963538e 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -275,17 +275,17 @@ struct bio_and_error {
 	int error;
 };
 
-extern void start_new_tl_epoch(struct drbd_tconn *tconn);
+extern void start_new_tl_epoch(struct drbd_connection *connection);
 extern void drbd_req_destroy(struct kref *kref);
 extern void _req_may_be_done(struct drbd_request *req,
 		struct bio_and_error *m);
 extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m);
-extern void complete_master_bio(struct drbd_conf *mdev,
+extern void complete_master_bio(struct drbd_device *device,
 		struct bio_and_error *m);
 extern void request_timer_fn(unsigned long data);
-extern void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what);
-extern void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what);
+extern void tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
+extern void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
 
 /* this is in drbd_main.c */
 extern void drbd_restart_request(struct drbd_request *req);
@@ -294,14 +294,14 @@ extern void drbd_restart_request(struct drbd_request *req);
  * outside the spinlock, e.g. when walking some list on cleanup. */
 static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 {
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct bio_and_error m;
 	int rv;
 
 	/* __req_mod possibly frees req, do not touch req after that! */
 	rv = __req_mod(req, what, &m);
 	if (m.bio)
-		complete_master_bio(mdev, &m);
+		complete_master_bio(device, &m);
 
 	return rv;
 }
@@ -314,16 +314,16 @@ static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 {
 	unsigned long flags;
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct bio_and_error m;
 	int rv;
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
 	rv = __req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 	if (m.bio)
-		complete_master_bio(mdev, &m);
+		complete_master_bio(device, &m);
 
 	return rv;
 }
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 216d47b7e88b..1a84345a3868 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -27,13 +27,12 @@
 
 #include <linux/drbd_limits.h>
 #include "drbd_int.h"
+#include "drbd_protocol.h"
 #include "drbd_req.h"
 
-/* in drbd_main.c */
-extern void tl_abort_disk_io(struct drbd_conf *mdev);
-
 struct after_state_chg_work {
 	struct drbd_work w;
+	struct drbd_device *device;
 	union drbd_state os;
 	union drbd_state ns;
 	enum chg_state_flags flags;
@@ -50,12 +49,12 @@ enum sanitize_state_warnings {
 };
 
 static int w_after_state_ch(struct drbd_work *w, int unused);
-static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
+static void after_state_ch(struct drbd_device *device, union drbd_state os,
 			   union drbd_state ns, enum chg_state_flags flags);
-static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
-static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state, struct drbd_tconn *);
+static enum drbd_state_rv is_valid_state(struct drbd_device *, union drbd_state);
+static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state, struct drbd_connection *);
 static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns);
-static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ns,
+static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state ns,
 				       enum sanitize_state_warnings *warn);
 
 static inline bool is_susp(union drbd_state s)
@@ -63,17 +62,18 @@ static inline bool is_susp(union drbd_state s)
         return s.susp || s.susp_nod || s.susp_fen;
 }
 
-bool conn_all_vols_unconf(struct drbd_tconn *tconn)
+bool conn_all_vols_unconf(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	bool rv = true;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		if (mdev->state.disk != D_DISKLESS ||
-		    mdev->state.conn != C_STANDALONE ||
-		    mdev->state.role != R_SECONDARY) {
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		if (device->state.disk != D_DISKLESS ||
+		    device->state.conn != C_STANDALONE ||
+		    device->state.role != R_SECONDARY) {
 			rv = false;
 			break;
 		}
@@ -102,99 +102,111 @@ static enum drbd_role min_role(enum drbd_role role1, enum drbd_role role2)
 	return R_PRIMARY;
 }
 
-enum drbd_role conn_highest_role(struct drbd_tconn *tconn)
+enum drbd_role conn_highest_role(struct drbd_connection *connection)
 {
 	enum drbd_role role = R_UNKNOWN;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		role = max_role(role, mdev->state.role);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		role = max_role(role, device->state.role);
+	}
 	rcu_read_unlock();
 
 	return role;
 }
 
-enum drbd_role conn_highest_peer(struct drbd_tconn *tconn)
+enum drbd_role conn_highest_peer(struct drbd_connection *connection)
 {
 	enum drbd_role peer = R_UNKNOWN;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		peer = max_role(peer, mdev->state.peer);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		peer = max_role(peer, device->state.peer);
+	}
 	rcu_read_unlock();
 
 	return peer;
 }
 
-enum drbd_disk_state conn_highest_disk(struct drbd_tconn *tconn)
+enum drbd_disk_state conn_highest_disk(struct drbd_connection *connection)
 {
 	enum drbd_disk_state ds = D_DISKLESS;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		ds = max_t(enum drbd_disk_state, ds, mdev->state.disk);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		ds = max_t(enum drbd_disk_state, ds, device->state.disk);
+	}
 	rcu_read_unlock();
 
 	return ds;
 }
 
-enum drbd_disk_state conn_lowest_disk(struct drbd_tconn *tconn)
+enum drbd_disk_state conn_lowest_disk(struct drbd_connection *connection)
 {
 	enum drbd_disk_state ds = D_MASK;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		ds = min_t(enum drbd_disk_state, ds, mdev->state.disk);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		ds = min_t(enum drbd_disk_state, ds, device->state.disk);
+	}
 	rcu_read_unlock();
 
 	return ds;
 }
 
-enum drbd_disk_state conn_highest_pdsk(struct drbd_tconn *tconn)
+enum drbd_disk_state conn_highest_pdsk(struct drbd_connection *connection)
 {
 	enum drbd_disk_state ds = D_DISKLESS;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		ds = max_t(enum drbd_disk_state, ds, mdev->state.pdsk);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		ds = max_t(enum drbd_disk_state, ds, device->state.pdsk);
+	}
 	rcu_read_unlock();
 
 	return ds;
 }
 
-enum drbd_conns conn_lowest_conn(struct drbd_tconn *tconn)
+enum drbd_conns conn_lowest_conn(struct drbd_connection *connection)
 {
 	enum drbd_conns conn = C_MASK;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		conn = min_t(enum drbd_conns, conn, mdev->state.conn);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		conn = min_t(enum drbd_conns, conn, device->state.conn);
+	}
 	rcu_read_unlock();
 
 	return conn;
 }
 
-static bool no_peer_wf_report_params(struct drbd_tconn *tconn)
+static bool no_peer_wf_report_params(struct drbd_connection *connection)
 {
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 	bool rv = true;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr)
-		if (mdev->state.conn == C_WF_REPORT_PARAMS) {
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
+		if (peer_device->device->state.conn == C_WF_REPORT_PARAMS) {
 			rv = false;
 			break;
 		}
@@ -206,11 +218,11 @@ static bool no_peer_wf_report_params(struct drbd_tconn *tconn)
 
 /**
  * cl_wide_st_chg() - true if the state change is a cluster wide one
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @os:		old (current) state.
  * @ns:		new (wanted) state.
  */
-static int cl_wide_st_chg(struct drbd_conf *mdev,
+static int cl_wide_st_chg(struct drbd_device *device,
 			  union drbd_state os, union drbd_state ns)
 {
 	return (os.conn >= C_CONNECTED && ns.conn >= C_CONNECTED &&
@@ -232,72 +244,72 @@ apply_mask_val(union drbd_state os, union drbd_state mask, union drbd_state val)
 }
 
 enum drbd_state_rv
-drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
+drbd_change_state(struct drbd_device *device, enum chg_state_flags f,
 		  union drbd_state mask, union drbd_state val)
 {
 	unsigned long flags;
 	union drbd_state ns;
 	enum drbd_state_rv rv;
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	ns = apply_mask_val(drbd_read_state(mdev), mask, val);
-	rv = _drbd_set_state(mdev, ns, f, NULL);
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	ns = apply_mask_val(drbd_read_state(device), mask, val);
+	rv = _drbd_set_state(device, ns, f, NULL);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 	return rv;
 }
 
 /**
  * drbd_force_state() - Impose a change which happens outside our control on our state
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @mask:	mask of state bits to change.
  * @val:	value of new state bits.
  */
-void drbd_force_state(struct drbd_conf *mdev,
+void drbd_force_state(struct drbd_device *device,
 	union drbd_state mask, union drbd_state val)
 {
-	drbd_change_state(mdev, CS_HARD, mask, val);
+	drbd_change_state(device, CS_HARD, mask, val);
 }
 
 static enum drbd_state_rv
-_req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
+_req_st_cond(struct drbd_device *device, union drbd_state mask,
 	     union drbd_state val)
 {
 	union drbd_state os, ns;
 	unsigned long flags;
 	enum drbd_state_rv rv;
 
-	if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags))
+	if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &device->flags))
 		return SS_CW_SUCCESS;
 
-	if (test_and_clear_bit(CL_ST_CHG_FAIL, &mdev->flags))
+	if (test_and_clear_bit(CL_ST_CHG_FAIL, &device->flags))
 		return SS_CW_FAILED_BY_PEER;
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	os = drbd_read_state(mdev);
-	ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	os = drbd_read_state(device);
+	ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL);
 	rv = is_valid_transition(os, ns);
 	if (rv >= SS_SUCCESS)
 		rv = SS_UNKNOWN_ERROR;  /* cont waiting, otherwise fail. */
 
-	if (!cl_wide_st_chg(mdev, os, ns))
+	if (!cl_wide_st_chg(device, os, ns))
 		rv = SS_CW_NO_NEED;
 	if (rv == SS_UNKNOWN_ERROR) {
-		rv = is_valid_state(mdev, ns);
+		rv = is_valid_state(device, ns);
 		if (rv >= SS_SUCCESS) {
-			rv = is_valid_soft_transition(os, ns, mdev->tconn);
+			rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
 			if (rv >= SS_SUCCESS)
 				rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
 		}
 	}
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 	return rv;
 }
 
 /**
  * drbd_req_state() - Perform an eventually cluster wide state change
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @mask:	mask of state bits to change.
  * @val:	value of new state bits.
  * @f:		flags
@@ -306,7 +318,7 @@ _req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
  * _drbd_request_state().
  */
 static enum drbd_state_rv
-drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
+drbd_req_state(struct drbd_device *device, union drbd_state mask,
 	       union drbd_state val, enum chg_state_flags f)
 {
 	struct completion done;
@@ -317,68 +329,68 @@ drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
 	init_completion(&done);
 
 	if (f & CS_SERIALIZE)
-		mutex_lock(mdev->state_mutex);
+		mutex_lock(device->state_mutex);
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	os = drbd_read_state(mdev);
-	ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	os = drbd_read_state(device);
+	ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL);
 	rv = is_valid_transition(os, ns);
 	if (rv < SS_SUCCESS) {
-		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		spin_unlock_irqrestore(&device->resource->req_lock, flags);
 		goto abort;
 	}
 
-	if (cl_wide_st_chg(mdev, os, ns)) {
-		rv = is_valid_state(mdev, ns);
+	if (cl_wide_st_chg(device, os, ns)) {
+		rv = is_valid_state(device, ns);
 		if (rv == SS_SUCCESS)
-			rv = is_valid_soft_transition(os, ns, mdev->tconn);
-		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+			rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
+		spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 		if (rv < SS_SUCCESS) {
 			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
+				print_st_err(device, os, ns, rv);
 			goto abort;
 		}
 
-		if (drbd_send_state_req(mdev, mask, val)) {
+		if (drbd_send_state_req(first_peer_device(device), mask, val)) {
 			rv = SS_CW_FAILED_BY_PEER;
 			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
+				print_st_err(device, os, ns, rv);
 			goto abort;
 		}
 
-		wait_event(mdev->state_wait,
-			(rv = _req_st_cond(mdev, mask, val)));
+		wait_event(device->state_wait,
+			(rv = _req_st_cond(device, mask, val)));
 
 		if (rv < SS_SUCCESS) {
 			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
+				print_st_err(device, os, ns, rv);
 			goto abort;
 		}
-		spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-		ns = apply_mask_val(drbd_read_state(mdev), mask, val);
-		rv = _drbd_set_state(mdev, ns, f, &done);
+		spin_lock_irqsave(&device->resource->req_lock, flags);
+		ns = apply_mask_val(drbd_read_state(device), mask, val);
+		rv = _drbd_set_state(device, ns, f, &done);
 	} else {
-		rv = _drbd_set_state(mdev, ns, f, &done);
+		rv = _drbd_set_state(device, ns, f, &done);
 	}
 
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 	if (f & CS_WAIT_COMPLETE && rv == SS_SUCCESS) {
-		D_ASSERT(current != mdev->tconn->worker.task);
+		D_ASSERT(device, current != first_peer_device(device)->connection->worker.task);
 		wait_for_completion(&done);
 	}
 
 abort:
 	if (f & CS_SERIALIZE)
-		mutex_unlock(mdev->state_mutex);
+		mutex_unlock(device->state_mutex);
 
 	return rv;
 }
 
 /**
  * _drbd_request_state() - Request a state change (with flags)
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @mask:	mask of state bits to change.
  * @val:	value of new state bits.
  * @f:		flags
@@ -387,20 +399,20 @@ abort:
  * flag, or when logging of failed state change requests is not desired.
  */
 enum drbd_state_rv
-_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask,
+_drbd_request_state(struct drbd_device *device, union drbd_state mask,
 		    union drbd_state val, enum chg_state_flags f)
 {
 	enum drbd_state_rv rv;
 
-	wait_event(mdev->state_wait,
-		   (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE);
+	wait_event(device->state_wait,
+		   (rv = drbd_req_state(device, mask, val, f)) != SS_IN_TRANSIENT_STATE);
 
 	return rv;
 }
 
-static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
+static void print_st(struct drbd_device *device, char *name, union drbd_state ns)
 {
-	dev_err(DEV, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c%c%c }\n",
+	drbd_err(device, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c%c%c }\n",
 	    name,
 	    drbd_conn_str(ns.conn),
 	    drbd_role_str(ns.role),
@@ -416,14 +428,14 @@ static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
 	    );
 }
 
-void print_st_err(struct drbd_conf *mdev, union drbd_state os,
+void print_st_err(struct drbd_device *device, union drbd_state os,
 	          union drbd_state ns, enum drbd_state_rv err)
 {
 	if (err == SS_IN_TRANSIENT_STATE)
 		return;
-	dev_err(DEV, "State change failed: %s\n", drbd_set_st_err_str(err));
-	print_st(mdev, " state", os);
-	print_st(mdev, "wanted", ns);
+	drbd_err(device, "State change failed: %s\n", drbd_set_st_err_str(err));
+	print_st(device, " state", os);
+	print_st(device, "wanted", ns);
 }
 
 static long print_state_change(char *pb, union drbd_state os, union drbd_state ns,
@@ -457,7 +469,7 @@ static long print_state_change(char *pb, union drbd_state os, union drbd_state n
 	return pbp - pb;
 }
 
-static void drbd_pr_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns,
+static void drbd_pr_state_change(struct drbd_device *device, union drbd_state os, union drbd_state ns,
 				 enum chg_state_flags flags)
 {
 	char pb[300];
@@ -479,10 +491,10 @@ static void drbd_pr_state_change(struct drbd_conf *mdev, union drbd_state os, un
 			       ns.user_isp);
 
 	if (pbp != pb)
-		dev_info(DEV, "%s\n", pb);
+		drbd_info(device, "%s\n", pb);
 }
 
-static void conn_pr_state_change(struct drbd_tconn *tconn, union drbd_state os, union drbd_state ns,
+static void conn_pr_state_change(struct drbd_connection *connection, union drbd_state os, union drbd_state ns,
 				 enum chg_state_flags flags)
 {
 	char pb[300];
@@ -496,17 +508,17 @@ static void conn_pr_state_change(struct drbd_tconn *tconn, union drbd_state os,
 			       is_susp(ns));
 
 	if (pbp != pb)
-		conn_info(tconn, "%s\n", pb);
+		drbd_info(connection, "%s\n", pb);
 }
 
 
 /**
  * is_valid_state() - Returns an SS_ error code if ns is not valid
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @ns:		State to consider.
  */
 static enum drbd_state_rv
-is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
+is_valid_state(struct drbd_device *device, union drbd_state ns)
 {
 	/* See drbd_state_sw_errors in drbd_strings.c */
 
@@ -516,24 +528,24 @@ is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
 
 	rcu_read_lock();
 	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
-		fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		fp = rcu_dereference(device->ldev->disk_conf)->fencing;
+		put_ldev(device);
 	}
 
-	nc = rcu_dereference(mdev->tconn->net_conf);
+	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 	if (nc) {
 		if (!nc->two_primaries && ns.role == R_PRIMARY) {
 			if (ns.peer == R_PRIMARY)
 				rv = SS_TWO_PRIMARIES;
-			else if (conn_highest_peer(mdev->tconn) == R_PRIMARY)
+			else if (conn_highest_peer(first_peer_device(device)->connection) == R_PRIMARY)
 				rv = SS_O_VOL_PEER_PRI;
 		}
 	}
 
 	if (rv <= 0)
 		/* already found a reason to abort */;
-	else if (ns.role == R_SECONDARY && mdev->open_cnt)
+	else if (ns.role == R_SECONDARY && device->open_cnt)
 		rv = SS_DEVICE_IN_USE;
 
 	else if (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.disk < D_UP_TO_DATE)
@@ -567,7 +579,7 @@ is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
 		rv = SS_NO_VERIFY_ALG;
 
 	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
-		  mdev->tconn->agreed_pro_version < 88)
+		  first_peer_device(device)->connection->agreed_pro_version < 88)
 		rv = SS_NOT_SUPPORTED;
 
 	else if (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE)
@@ -589,12 +601,12 @@ is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
  * is_valid_soft_transition() - Returns an SS_ error code if the state transition is not possible
  * This function limits state transitions that may be declined by DRBD. I.e.
  * user requests (aka soft transitions).
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @ns:		new state.
  * @os:		old state.
  */
 static enum drbd_state_rv
-is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_tconn *tconn)
+is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_connection *connection)
 {
 	enum drbd_state_rv rv = SS_SUCCESS;
 
@@ -622,7 +634,7 @@ is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_t
 
 	/* While establishing a connection only allow cstate to change.
 	   Delay/refuse role changes, detach attach etc... */
-	if (test_bit(STATE_SENT, &tconn->flags) &&
+	if (test_bit(STATE_SENT, &connection->flags) &&
 	    !(os.conn == C_WF_REPORT_PARAMS ||
 	      (ns.conn == C_WF_REPORT_PARAMS && os.conn == C_WF_CONNECTION)))
 		rv = SS_IN_TRANSIENT_STATE;
@@ -703,7 +715,7 @@ is_valid_transition(union drbd_state os, union drbd_state ns)
 	return rv;
 }
 
-static void print_sanitize_warnings(struct drbd_conf *mdev, enum sanitize_state_warnings warn)
+static void print_sanitize_warnings(struct drbd_device *device, enum sanitize_state_warnings warn)
 {
 	static const char *msg_table[] = {
 		[NO_WARNING] = "",
@@ -715,12 +727,12 @@ static void print_sanitize_warnings(struct drbd_conf *mdev, enum sanitize_state_
 	};
 
 	if (warn != NO_WARNING)
-		dev_warn(DEV, "%s\n", msg_table[warn]);
+		drbd_warn(device, "%s\n", msg_table[warn]);
 }
 
 /**
  * sanitize_state() - Resolves implicitly necessary additional changes to a state transition
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @os:		old state.
  * @ns:		new state.
  * @warn_sync_abort:
@@ -728,7 +740,7 @@ static void print_sanitize_warnings(struct drbd_conf *mdev, enum sanitize_state_
  * When we loose connection, we have to set the state of the peers disk (pdsk)
  * to D_UNKNOWN. This rule and many more along those lines are in this function.
  */
-static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ns,
+static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state ns,
 				       enum sanitize_state_warnings *warn)
 {
 	enum drbd_fencing_p fp;
@@ -738,11 +750,11 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
 		*warn = NO_WARNING;
 
 	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
+	if (get_ldev(device)) {
 		rcu_read_lock();
-		fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
+		fp = rcu_dereference(device->ldev->disk_conf)->fencing;
 		rcu_read_unlock();
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	/* Implications from connection to peer and peer_isp */
@@ -768,17 +780,17 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
 
 	/* Connection breaks down before we finished "Negotiating" */
 	if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
-	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
-		if (mdev->ed_uuid == mdev->ldev->md.uuid[UI_CURRENT]) {
-			ns.disk = mdev->new_state_tmp.disk;
-			ns.pdsk = mdev->new_state_tmp.pdsk;
+	    get_ldev_if_state(device, D_NEGOTIATING)) {
+		if (device->ed_uuid == device->ldev->md.uuid[UI_CURRENT]) {
+			ns.disk = device->new_state_tmp.disk;
+			ns.pdsk = device->new_state_tmp.pdsk;
 		} else {
 			if (warn)
 				*warn = CONNECTION_LOST_NEGOTIATING;
 			ns.disk = D_DISKLESS;
 			ns.pdsk = D_UNKNOWN;
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	/* D_CONSISTENT and D_OUTDATED vanish when we get connected */
@@ -873,7 +885,7 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
 	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED))
 		ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
 
-	if (mdev->tconn->res_opts.on_no_data == OND_SUSPEND_IO &&
+	if (device->resource->res_opts.on_no_data == OND_SUSPEND_IO &&
 	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE))
 		ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
 
@@ -892,42 +904,42 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
 	return ns;
 }
 
-void drbd_resume_al(struct drbd_conf *mdev)
+void drbd_resume_al(struct drbd_device *device)
 {
-	if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
-		dev_info(DEV, "Resumed AL updates\n");
+	if (test_and_clear_bit(AL_SUSPENDED, &device->flags))
+		drbd_info(device, "Resumed AL updates\n");
 }
 
 /* helper for __drbd_set_state */
-static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
+static void set_ov_position(struct drbd_device *device, enum drbd_conns cs)
 {
-	if (mdev->tconn->agreed_pro_version < 90)
-		mdev->ov_start_sector = 0;
-	mdev->rs_total = drbd_bm_bits(mdev);
-	mdev->ov_position = 0;
+	if (first_peer_device(device)->connection->agreed_pro_version < 90)
+		device->ov_start_sector = 0;
+	device->rs_total = drbd_bm_bits(device);
+	device->ov_position = 0;
 	if (cs == C_VERIFY_T) {
 		/* starting online verify from an arbitrary position
 		 * does not fit well into the existing protocol.
 		 * on C_VERIFY_T, we initialize ov_left and friends
 		 * implicitly in receive_DataRequest once the
 		 * first P_OV_REQUEST is received */
-		mdev->ov_start_sector = ~(sector_t)0;
+		device->ov_start_sector = ~(sector_t)0;
 	} else {
-		unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector);
-		if (bit >= mdev->rs_total) {
-			mdev->ov_start_sector =
-				BM_BIT_TO_SECT(mdev->rs_total - 1);
-			mdev->rs_total = 1;
+		unsigned long bit = BM_SECT_TO_BIT(device->ov_start_sector);
+		if (bit >= device->rs_total) {
+			device->ov_start_sector =
+				BM_BIT_TO_SECT(device->rs_total - 1);
+			device->rs_total = 1;
 		} else
-			mdev->rs_total -= bit;
-		mdev->ov_position = mdev->ov_start_sector;
+			device->rs_total -= bit;
+		device->ov_position = device->ov_start_sector;
 	}
-	mdev->ov_left = mdev->rs_total;
+	device->ov_left = device->rs_total;
 }
 
 /**
  * __drbd_set_state() - Set a new DRBD state
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @ns:		new state.
  * @flags:	Flags
  * @done:	Optional completion, that will get completed after the after_state_ch() finished
@@ -935,7 +947,7 @@ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
  * Caller needs to hold req_lock, and global_state_lock. Do not call directly.
  */
 enum drbd_state_rv
-__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+__drbd_set_state(struct drbd_device *device, union drbd_state ns,
 	         enum chg_state_flags flags, struct completion *done)
 {
 	union drbd_state os;
@@ -944,9 +956,9 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 	struct after_state_chg_work *ascw;
 	bool did_remote, should_do_remote;
 
-	os = drbd_read_state(mdev);
+	os = drbd_read_state(device);
 
-	ns = sanitize_state(mdev, ns, &ssw);
+	ns = sanitize_state(device, ns, &ssw);
 	if (ns.i == os.i)
 		return SS_NOTHING_TO_DO;
 
@@ -958,32 +970,33 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 		/*  pre-state-change checks ; only look at ns  */
 		/* See drbd_state_sw_errors in drbd_strings.c */
 
-		rv = is_valid_state(mdev, ns);
+		rv = is_valid_state(device, ns);
 		if (rv < SS_SUCCESS) {
 			/* If the old state was illegal as well, then let
 			   this happen...*/
 
-			if (is_valid_state(mdev, os) == rv)
-				rv = is_valid_soft_transition(os, ns, mdev->tconn);
+			if (is_valid_state(device, os) == rv)
+				rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
 		} else
-			rv = is_valid_soft_transition(os, ns, mdev->tconn);
+			rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
 	}
 
 	if (rv < SS_SUCCESS) {
 		if (flags & CS_VERBOSE)
-			print_st_err(mdev, os, ns, rv);
+			print_st_err(device, os, ns, rv);
 		return rv;
 	}
 
-	print_sanitize_warnings(mdev, ssw);
+	print_sanitize_warnings(device, ssw);
 
-	drbd_pr_state_change(mdev, os, ns, flags);
+	drbd_pr_state_change(device, os, ns, flags);
 
 	/* Display changes to the susp* flags that where caused by the call to
 	   sanitize_state(). Only display it here if we where not called from
 	   _conn_request_state() */
 	if (!(flags & CS_DC_SUSP))
-		conn_pr_state_change(mdev->tconn, os, ns, (flags & ~CS_DC_MASK) | CS_DC_SUSP);
+		conn_pr_state_change(first_peer_device(device)->connection, os, ns,
+				     (flags & ~CS_DC_MASK) | CS_DC_SUSP);
 
 	/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
 	 * on the ldev here, to be sure the transition -> D_DISKLESS resp.
@@ -991,55 +1004,55 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 	 * after_state_ch works run, where we put_ldev again. */
 	if ((os.disk != D_FAILED && ns.disk == D_FAILED) ||
 	    (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
-		atomic_inc(&mdev->local_cnt);
+		atomic_inc(&device->local_cnt);
 
-	did_remote = drbd_should_do_remote(mdev->state);
-	mdev->state.i = ns.i;
-	should_do_remote = drbd_should_do_remote(mdev->state);
-	mdev->tconn->susp = ns.susp;
-	mdev->tconn->susp_nod = ns.susp_nod;
-	mdev->tconn->susp_fen = ns.susp_fen;
+	did_remote = drbd_should_do_remote(device->state);
+	device->state.i = ns.i;
+	should_do_remote = drbd_should_do_remote(device->state);
+	device->resource->susp = ns.susp;
+	device->resource->susp_nod = ns.susp_nod;
+	device->resource->susp_fen = ns.susp_fen;
 
 	/* put replicated vs not-replicated requests in seperate epochs */
 	if (did_remote != should_do_remote)
-		start_new_tl_epoch(mdev->tconn);
+		start_new_tl_epoch(first_peer_device(device)->connection);
 
 	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
-		drbd_print_uuids(mdev, "attached to UUIDs");
+		drbd_print_uuids(device, "attached to UUIDs");
 
 	/* Wake up role changes, that were delayed because of connection establishing */
 	if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS &&
-	    no_peer_wf_report_params(mdev->tconn))
-		clear_bit(STATE_SENT, &mdev->tconn->flags);
+	    no_peer_wf_report_params(first_peer_device(device)->connection))
+		clear_bit(STATE_SENT, &first_peer_device(device)->connection->flags);
 
-	wake_up(&mdev->misc_wait);
-	wake_up(&mdev->state_wait);
-	wake_up(&mdev->tconn->ping_wait);
+	wake_up(&device->misc_wait);
+	wake_up(&device->state_wait);
+	wake_up(&first_peer_device(device)->connection->ping_wait);
 
 	/* Aborted verify run, or we reached the stop sector.
 	 * Log the last position, unless end-of-device. */
 	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
 	    ns.conn <= C_CONNECTED) {
-		mdev->ov_start_sector =
-			BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left);
-		if (mdev->ov_left)
-			dev_info(DEV, "Online Verify reached sector %llu\n",
-				(unsigned long long)mdev->ov_start_sector);
+		device->ov_start_sector =
+			BM_BIT_TO_SECT(drbd_bm_bits(device) - device->ov_left);
+		if (device->ov_left)
+			drbd_info(device, "Online Verify reached sector %llu\n",
+				(unsigned long long)device->ov_start_sector);
 	}
 
 	if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
 	    (ns.conn == C_SYNC_TARGET  || ns.conn == C_SYNC_SOURCE)) {
-		dev_info(DEV, "Syncer continues.\n");
-		mdev->rs_paused += (long)jiffies
-				  -(long)mdev->rs_mark_time[mdev->rs_last_mark];
+		drbd_info(device, "Syncer continues.\n");
+		device->rs_paused += (long)jiffies
+				  -(long)device->rs_mark_time[device->rs_last_mark];
 		if (ns.conn == C_SYNC_TARGET)
-			mod_timer(&mdev->resync_timer, jiffies);
+			mod_timer(&device->resync_timer, jiffies);
 	}
 
 	if ((os.conn == C_SYNC_TARGET  || os.conn == C_SYNC_SOURCE) &&
 	    (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
-		dev_info(DEV, "Resync suspended\n");
-		mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
+		drbd_info(device, "Resync suspended\n");
+		device->rs_mark_time[device->rs_last_mark] = jiffies;
 	}
 
 	if (os.conn == C_CONNECTED &&
@@ -1047,77 +1060,77 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 		unsigned long now = jiffies;
 		int i;
 
-		set_ov_position(mdev, ns.conn);
-		mdev->rs_start = now;
-		mdev->rs_last_events = 0;
-		mdev->rs_last_sect_ev = 0;
-		mdev->ov_last_oos_size = 0;
-		mdev->ov_last_oos_start = 0;
+		set_ov_position(device, ns.conn);
+		device->rs_start = now;
+		device->rs_last_events = 0;
+		device->rs_last_sect_ev = 0;
+		device->ov_last_oos_size = 0;
+		device->ov_last_oos_start = 0;
 
 		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-			mdev->rs_mark_left[i] = mdev->ov_left;
-			mdev->rs_mark_time[i] = now;
+			device->rs_mark_left[i] = device->ov_left;
+			device->rs_mark_time[i] = now;
 		}
 
-		drbd_rs_controller_reset(mdev);
+		drbd_rs_controller_reset(device);
 
 		if (ns.conn == C_VERIFY_S) {
-			dev_info(DEV, "Starting Online Verify from sector %llu\n",
-					(unsigned long long)mdev->ov_position);
-			mod_timer(&mdev->resync_timer, jiffies);
+			drbd_info(device, "Starting Online Verify from sector %llu\n",
+					(unsigned long long)device->ov_position);
+			mod_timer(&device->resync_timer, jiffies);
 		}
 	}
 
-	if (get_ldev(mdev)) {
-		u32 mdf = mdev->ldev->md.flags & ~(MDF_CONSISTENT|MDF_PRIMARY_IND|
+	if (get_ldev(device)) {
+		u32 mdf = device->ldev->md.flags & ~(MDF_CONSISTENT|MDF_PRIMARY_IND|
 						 MDF_CONNECTED_IND|MDF_WAS_UP_TO_DATE|
 						 MDF_PEER_OUT_DATED|MDF_CRASHED_PRIMARY);
 
 		mdf &= ~MDF_AL_CLEAN;
-		if (test_bit(CRASHED_PRIMARY, &mdev->flags))
+		if (test_bit(CRASHED_PRIMARY, &device->flags))
 			mdf |= MDF_CRASHED_PRIMARY;
-		if (mdev->state.role == R_PRIMARY ||
-		    (mdev->state.pdsk < D_INCONSISTENT && mdev->state.peer == R_PRIMARY))
+		if (device->state.role == R_PRIMARY ||
+		    (device->state.pdsk < D_INCONSISTENT && device->state.peer == R_PRIMARY))
 			mdf |= MDF_PRIMARY_IND;
-		if (mdev->state.conn > C_WF_REPORT_PARAMS)
+		if (device->state.conn > C_WF_REPORT_PARAMS)
 			mdf |= MDF_CONNECTED_IND;
-		if (mdev->state.disk > D_INCONSISTENT)
+		if (device->state.disk > D_INCONSISTENT)
 			mdf |= MDF_CONSISTENT;
-		if (mdev->state.disk > D_OUTDATED)
+		if (device->state.disk > D_OUTDATED)
 			mdf |= MDF_WAS_UP_TO_DATE;
-		if (mdev->state.pdsk <= D_OUTDATED && mdev->state.pdsk >= D_INCONSISTENT)
+		if (device->state.pdsk <= D_OUTDATED && device->state.pdsk >= D_INCONSISTENT)
 			mdf |= MDF_PEER_OUT_DATED;
-		if (mdf != mdev->ldev->md.flags) {
-			mdev->ldev->md.flags = mdf;
-			drbd_md_mark_dirty(mdev);
+		if (mdf != device->ldev->md.flags) {
+			device->ldev->md.flags = mdf;
+			drbd_md_mark_dirty(device);
 		}
 		if (os.disk < D_CONSISTENT && ns.disk >= D_CONSISTENT)
-			drbd_set_ed_uuid(mdev, mdev->ldev->md.uuid[UI_CURRENT]);
-		put_ldev(mdev);
+			drbd_set_ed_uuid(device, device->ldev->md.uuid[UI_CURRENT]);
+		put_ldev(device);
 	}
 
 	/* Peer was forced D_UP_TO_DATE & R_PRIMARY, consider to resync */
 	if (os.disk == D_INCONSISTENT && os.pdsk == D_INCONSISTENT &&
 	    os.peer == R_SECONDARY && ns.peer == R_PRIMARY)
-		set_bit(CONSIDER_RESYNC, &mdev->flags);
+		set_bit(CONSIDER_RESYNC, &device->flags);
 
 	/* Receiver should clean up itself */
 	if (os.conn != C_DISCONNECTING && ns.conn == C_DISCONNECTING)
-		drbd_thread_stop_nowait(&mdev->tconn->receiver);
+		drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
 
 	/* Now the receiver finished cleaning up itself, it should die */
 	if (os.conn != C_STANDALONE && ns.conn == C_STANDALONE)
-		drbd_thread_stop_nowait(&mdev->tconn->receiver);
+		drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
 
 	/* Upon network failure, we need to restart the receiver. */
 	if (os.conn > C_WF_CONNECTION &&
 	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
-		drbd_thread_restart_nowait(&mdev->tconn->receiver);
+		drbd_thread_restart_nowait(&first_peer_device(device)->connection->receiver);
 
 	/* Resume AL writing if we get a connection */
 	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
-		drbd_resume_al(mdev);
-		mdev->tconn->connect_cnt++;
+		drbd_resume_al(device);
+		first_peer_device(device)->connection->connect_cnt++;
 	}
 
 	/* remember last attach time so request_timer_fn() won't
@@ -1125,7 +1138,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 	 * previously frozen IO */
 	if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
 	    ns.disk > D_NEGOTIATING)
-		mdev->last_reattach_jif = jiffies;
+		device->last_reattach_jif = jiffies;
 
 	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
 	if (ascw) {
@@ -1133,11 +1146,12 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 		ascw->ns = ns;
 		ascw->flags = flags;
 		ascw->w.cb = w_after_state_ch;
-		ascw->w.mdev = mdev;
+		ascw->device = device;
 		ascw->done = done;
-		drbd_queue_work(&mdev->tconn->sender_work, &ascw->w);
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&ascw->w);
 	} else {
-		dev_err(DEV, "Could not kmalloc an ascw\n");
+		drbd_err(device, "Could not kmalloc an ascw\n");
 	}
 
 	return rv;
@@ -1147,66 +1161,65 @@ static int w_after_state_ch(struct drbd_work *w, int unused)
 {
 	struct after_state_chg_work *ascw =
 		container_of(w, struct after_state_chg_work, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device = ascw->device;
 
-	after_state_ch(mdev, ascw->os, ascw->ns, ascw->flags);
-	if (ascw->flags & CS_WAIT_COMPLETE) {
-		D_ASSERT(ascw->done != NULL);
+	after_state_ch(device, ascw->os, ascw->ns, ascw->flags);
+	if (ascw->flags & CS_WAIT_COMPLETE)
 		complete(ascw->done);
-	}
 	kfree(ascw);
 
 	return 0;
 }
 
-static void abw_start_sync(struct drbd_conf *mdev, int rv)
+static void abw_start_sync(struct drbd_device *device, int rv)
 {
 	if (rv) {
-		dev_err(DEV, "Writing the bitmap failed not starting resync.\n");
-		_drbd_request_state(mdev, NS(conn, C_CONNECTED), CS_VERBOSE);
+		drbd_err(device, "Writing the bitmap failed not starting resync.\n");
+		_drbd_request_state(device, NS(conn, C_CONNECTED), CS_VERBOSE);
 		return;
 	}
 
-	switch (mdev->state.conn) {
+	switch (device->state.conn) {
 	case C_STARTING_SYNC_T:
-		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
+		_drbd_request_state(device, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
 		break;
 	case C_STARTING_SYNC_S:
-		drbd_start_resync(mdev, C_SYNC_SOURCE);
+		drbd_start_resync(device, C_SYNC_SOURCE);
 		break;
 	}
 }
 
-int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
-		int (*io_fn)(struct drbd_conf *),
+int drbd_bitmap_io_from_worker(struct drbd_device *device,
+		int (*io_fn)(struct drbd_device *),
 		char *why, enum bm_flag flags)
 {
 	int rv;
 
-	D_ASSERT(current == mdev->tconn->worker.task);
+	D_ASSERT(device, current == first_peer_device(device)->connection->worker.task);
 
-	/* open coded non-blocking drbd_suspend_io(mdev); */
-	set_bit(SUSPEND_IO, &mdev->flags);
+	/* open coded non-blocking drbd_suspend_io(device); */
+	set_bit(SUSPEND_IO, &device->flags);
 
-	drbd_bm_lock(mdev, why, flags);
-	rv = io_fn(mdev);
-	drbd_bm_unlock(mdev);
+	drbd_bm_lock(device, why, flags);
+	rv = io_fn(device);
+	drbd_bm_unlock(device);
 
-	drbd_resume_io(mdev);
+	drbd_resume_io(device);
 
 	return rv;
 }
 
 /**
  * after_state_ch() - Perform after state change actions that may sleep
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @os:		old state.
  * @ns:		new state.
  * @flags:	Flags
  */
-static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
+static void after_state_ch(struct drbd_device *device, union drbd_state os,
 			   union drbd_state ns, enum chg_state_flags flags)
 {
+	struct drbd_resource *resource = device->resource;
 	struct sib_info sib;
 
 	sib.sib_reason = SIB_STATE_CHANGE;
@@ -1214,63 +1227,63 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 	sib.ns = ns;
 
 	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
-		clear_bit(CRASHED_PRIMARY, &mdev->flags);
-		if (mdev->p_uuid)
-			mdev->p_uuid[UI_FLAGS] &= ~((u64)2);
+		clear_bit(CRASHED_PRIMARY, &device->flags);
+		if (device->p_uuid)
+			device->p_uuid[UI_FLAGS] &= ~((u64)2);
 	}
 
 	/* Inform userspace about the change... */
-	drbd_bcast_event(mdev, &sib);
+	drbd_bcast_event(device, &sib);
 
 	if (!(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE) &&
 	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE))
-		drbd_khelper(mdev, "pri-on-incon-degr");
+		drbd_khelper(device, "pri-on-incon-degr");
 
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 
 	if (ns.susp_nod) {
-		struct drbd_tconn *tconn = mdev->tconn;
+		struct drbd_connection *connection = first_peer_device(device)->connection;
 		enum drbd_req_event what = NOTHING;
 
-		spin_lock_irq(&tconn->req_lock);
-		if (os.conn < C_CONNECTED && conn_lowest_conn(tconn) >= C_CONNECTED)
+		spin_lock_irq(&device->resource->req_lock);
+		if (os.conn < C_CONNECTED && conn_lowest_conn(connection) >= C_CONNECTED)
 			what = RESEND;
 
 		if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
-		    conn_lowest_disk(tconn) > D_NEGOTIATING)
+		    conn_lowest_disk(connection) > D_NEGOTIATING)
 			what = RESTART_FROZEN_DISK_IO;
 
-		if (tconn->susp_nod && what != NOTHING) {
-			_tl_restart(tconn, what);
-			_conn_request_state(tconn,
+		if (resource->susp_nod && what != NOTHING) {
+			_tl_restart(connection, what);
+			_conn_request_state(connection,
 					    (union drbd_state) { { .susp_nod = 1 } },
 					    (union drbd_state) { { .susp_nod = 0 } },
 					    CS_VERBOSE);
 		}
-		spin_unlock_irq(&tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 	}
 
 	if (ns.susp_fen) {
-		struct drbd_tconn *tconn = mdev->tconn;
+		struct drbd_connection *connection = first_peer_device(device)->connection;
 
-		spin_lock_irq(&tconn->req_lock);
-		if (tconn->susp_fen && conn_lowest_conn(tconn) >= C_CONNECTED) {
+		spin_lock_irq(&device->resource->req_lock);
+		if (resource->susp_fen && conn_lowest_conn(connection) >= C_CONNECTED) {
 			/* case2: The connection was established again: */
-			struct drbd_conf *odev;
+			struct drbd_peer_device *peer_device;
 			int vnr;
 
 			rcu_read_lock();
-			idr_for_each_entry(&tconn->volumes, odev, vnr)
-				clear_bit(NEW_CUR_UUID, &odev->flags);
+			idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
+				clear_bit(NEW_CUR_UUID, &peer_device->device->flags);
 			rcu_read_unlock();
-			_tl_restart(tconn, RESEND);
-			_conn_request_state(tconn,
+			_tl_restart(connection, RESEND);
+			_conn_request_state(connection,
 					    (union drbd_state) { { .susp_fen = 1 } },
 					    (union drbd_state) { { .susp_fen = 0 } },
 					    CS_VERBOSE);
 		}
-		spin_unlock_irq(&tconn->req_lock);
+		spin_unlock_irq(&device->resource->req_lock);
 	}
 
 	/* Became sync source.  With protocol >= 96, we still need to send out
@@ -1279,9 +1292,9 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 	 * which is unexpected. */
 	if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
 	    (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
-	    mdev->tconn->agreed_pro_version >= 96 && get_ldev(mdev)) {
-		drbd_gen_and_send_sync_uuid(mdev);
-		put_ldev(mdev);
+	    first_peer_device(device)->connection->agreed_pro_version >= 96 && get_ldev(device)) {
+		drbd_gen_and_send_sync_uuid(first_peer_device(device));
+		put_ldev(device);
 	}
 
 	/* Do not change the order of the if above and the two below... */
@@ -1289,20 +1302,20 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 	    ns.pdsk > D_DISKLESS && ns.pdsk != D_UNKNOWN) {      /* attach on the peer */
 		/* we probably will start a resync soon.
 		 * make sure those things are properly reset. */
-		mdev->rs_total = 0;
-		mdev->rs_failed = 0;
-		atomic_set(&mdev->rs_pending_cnt, 0);
-		drbd_rs_cancel_all(mdev);
+		device->rs_total = 0;
+		device->rs_failed = 0;
+		atomic_set(&device->rs_pending_cnt, 0);
+		drbd_rs_cancel_all(device);
 
-		drbd_send_uuids(mdev);
-		drbd_send_state(mdev, ns);
+		drbd_send_uuids(first_peer_device(device));
+		drbd_send_state(first_peer_device(device), ns);
 	}
 	/* No point in queuing send_bitmap if we don't have a connection
 	 * anymore, so check also the _current_ state, not only the new state
 	 * at the time this work was queued. */
 	if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S &&
-	    mdev->state.conn == C_WF_BITMAP_S)
-		drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL,
+	    device->state.conn == C_WF_BITMAP_S)
+		drbd_queue_bitmap_io(device, &drbd_send_bitmap, NULL,
 				"send_bitmap (WFBitMapS)",
 				BM_LOCKED_TEST_ALLOWED);
 
@@ -1313,80 +1326,80 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 	&&  (ns.pdsk < D_INCONSISTENT ||
 	     ns.pdsk == D_UNKNOWN ||
 	     ns.pdsk == D_OUTDATED)) {
-		if (get_ldev(mdev)) {
+		if (get_ldev(device)) {
 			if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
-			    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-				if (drbd_suspended(mdev)) {
-					set_bit(NEW_CUR_UUID, &mdev->flags);
+			    device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+				if (drbd_suspended(device)) {
+					set_bit(NEW_CUR_UUID, &device->flags);
 				} else {
-					drbd_uuid_new_current(mdev);
-					drbd_send_uuids(mdev);
+					drbd_uuid_new_current(device);
+					drbd_send_uuids(first_peer_device(device));
 				}
 			}
-			put_ldev(mdev);
+			put_ldev(device);
 		}
 	}
 
-	if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
+	if (ns.pdsk < D_INCONSISTENT && get_ldev(device)) {
 		if (os.peer == R_SECONDARY && ns.peer == R_PRIMARY &&
-		    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-			drbd_uuid_new_current(mdev);
-			drbd_send_uuids(mdev);
+		    device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+			drbd_uuid_new_current(device);
+			drbd_send_uuids(first_peer_device(device));
 		}
 		/* D_DISKLESS Peer becomes secondary */
 		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
 			/* We may still be Primary ourselves.
 			 * No harm done if the bitmap still changes,
 			 * redirtied pages will follow later. */
-			drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+			drbd_bitmap_io_from_worker(device, &drbd_bm_write,
 				"demote diskless peer", BM_LOCKED_SET_ALLOWED);
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	/* Write out all changed bits on demote.
 	 * Though, no need to da that just yet
 	 * if there is a resync going on still */
 	if (os.role == R_PRIMARY && ns.role == R_SECONDARY &&
-		mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) {
+		device->state.conn <= C_CONNECTED && get_ldev(device)) {
 		/* No changes to the bitmap expected this time, so assert that,
 		 * even though no harm was done if it did change. */
-		drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+		drbd_bitmap_io_from_worker(device, &drbd_bm_write,
 				"demote", BM_LOCKED_TEST_ALLOWED);
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	/* Last part of the attaching process ... */
 	if (ns.conn >= C_CONNECTED &&
 	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
-		drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
-		drbd_send_uuids(mdev);
-		drbd_send_state(mdev, ns);
+		drbd_send_sizes(first_peer_device(device), 0, 0);  /* to start sync... */
+		drbd_send_uuids(first_peer_device(device));
+		drbd_send_state(first_peer_device(device), ns);
 	}
 
 	/* We want to pause/continue resync, tell peer. */
 	if (ns.conn >= C_CONNECTED &&
 	     ((os.aftr_isp != ns.aftr_isp) ||
 	      (os.user_isp != ns.user_isp)))
-		drbd_send_state(mdev, ns);
+		drbd_send_state(first_peer_device(device), ns);
 
 	/* In case one of the isp bits got set, suspend other devices. */
 	if ((!os.aftr_isp && !os.peer_isp && !os.user_isp) &&
 	    (ns.aftr_isp || ns.peer_isp || ns.user_isp))
-		suspend_other_sg(mdev);
+		suspend_other_sg(device);
 
 	/* Make sure the peer gets informed about eventual state
 	   changes (ISP bits) while we were in WFReportParams. */
 	if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
-		drbd_send_state(mdev, ns);
+		drbd_send_state(first_peer_device(device), ns);
 
 	if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
-		drbd_send_state(mdev, ns);
+		drbd_send_state(first_peer_device(device), ns);
 
 	/* We are in the progress to start a full sync... */
 	if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
 	    (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S))
 		/* no other bitmap changes expected during this phase */
-		drbd_queue_bitmap_io(mdev,
+		drbd_queue_bitmap_io(device,
 			&drbd_bmio_set_n_write, &abw_start_sync,
 			"set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
 
@@ -1399,15 +1412,15 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 		 * our cleanup here with the transition to D_DISKLESS.
 		 * But is is still not save to dreference ldev here, since
 		 * we might come from an failed Attach before ldev was set. */
-		if (mdev->ldev) {
+		if (device->ldev) {
 			rcu_read_lock();
-			eh = rcu_dereference(mdev->ldev->disk_conf)->on_io_error;
+			eh = rcu_dereference(device->ldev->disk_conf)->on_io_error;
 			rcu_read_unlock();
 
-			was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags);
+			was_io_error = test_and_clear_bit(WAS_IO_ERROR, &device->flags);
 
 			if (was_io_error && eh == EP_CALL_HELPER)
-				drbd_khelper(mdev, "local-io-error");
+				drbd_khelper(device, "local-io-error");
 
 			/* Immediately allow completion of all application IO,
 			 * that waits for completion from the local disk,
@@ -1422,76 +1435,76 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 			 * So aborting local requests may cause crashes,
 			 * or even worse, silent data corruption.
 			 */
-			if (test_and_clear_bit(FORCE_DETACH, &mdev->flags))
-				tl_abort_disk_io(mdev);
+			if (test_and_clear_bit(FORCE_DETACH, &device->flags))
+				tl_abort_disk_io(device);
 
 			/* current state still has to be D_FAILED,
 			 * there is only one way out: to D_DISKLESS,
 			 * and that may only happen after our put_ldev below. */
-			if (mdev->state.disk != D_FAILED)
-				dev_err(DEV,
+			if (device->state.disk != D_FAILED)
+				drbd_err(device,
 					"ASSERT FAILED: disk is %s during detach\n",
-					drbd_disk_str(mdev->state.disk));
+					drbd_disk_str(device->state.disk));
 
 			if (ns.conn >= C_CONNECTED)
-				drbd_send_state(mdev, ns);
+				drbd_send_state(first_peer_device(device), ns);
 
-			drbd_rs_cancel_all(mdev);
+			drbd_rs_cancel_all(device);
 
 			/* In case we want to get something to stable storage still,
 			 * this may be the last chance.
 			 * Following put_ldev may transition to D_DISKLESS. */
-			drbd_md_sync(mdev);
+			drbd_md_sync(device);
 		}
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
-        /* second half of local IO error, failure to attach,
-         * or administrative detach,
-         * after local_cnt references have reached zero again */
-        if (os.disk != D_DISKLESS && ns.disk == D_DISKLESS) {
-                /* We must still be diskless,
-                 * re-attach has to be serialized with this! */
-                if (mdev->state.disk != D_DISKLESS)
-                        dev_err(DEV,
-                                "ASSERT FAILED: disk is %s while going diskless\n",
-                                drbd_disk_str(mdev->state.disk));
+	/* second half of local IO error, failure to attach,
+	 * or administrative detach,
+	 * after local_cnt references have reached zero again */
+	if (os.disk != D_DISKLESS && ns.disk == D_DISKLESS) {
+		/* We must still be diskless,
+		 * re-attach has to be serialized with this! */
+		if (device->state.disk != D_DISKLESS)
+			drbd_err(device,
+				 "ASSERT FAILED: disk is %s while going diskless\n",
+				 drbd_disk_str(device->state.disk));
 
 		if (ns.conn >= C_CONNECTED)
-			drbd_send_state(mdev, ns);
+			drbd_send_state(first_peer_device(device), ns);
 		/* corresponding get_ldev in __drbd_set_state
 		 * this may finally trigger drbd_ldev_destroy. */
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	/* Notify peer that I had a local IO error, and did not detached.. */
 	if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT && ns.conn >= C_CONNECTED)
-		drbd_send_state(mdev, ns);
+		drbd_send_state(first_peer_device(device), ns);
 
 	/* Disks got bigger while they were detached */
 	if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING &&
-	    test_and_clear_bit(RESYNC_AFTER_NEG, &mdev->flags)) {
+	    test_and_clear_bit(RESYNC_AFTER_NEG, &device->flags)) {
 		if (ns.conn == C_CONNECTED)
-			resync_after_online_grow(mdev);
+			resync_after_online_grow(device);
 	}
 
 	/* A resync finished or aborted, wake paused devices... */
 	if ((os.conn > C_CONNECTED && ns.conn <= C_CONNECTED) ||
 	    (os.peer_isp && !ns.peer_isp) ||
 	    (os.user_isp && !ns.user_isp))
-		resume_next_sg(mdev);
+		resume_next_sg(device);
 
 	/* sync target done with resync.  Explicitly notify peer, even though
 	 * it should (at least for non-empty resyncs) already know itself. */
 	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
-		drbd_send_state(mdev, ns);
+		drbd_send_state(first_peer_device(device), ns);
 
 	/* Verify finished, or reached stop sector.  Peer did not know about
 	 * the stop sector, and we may even have changed the stop sector during
 	 * verify to interrupt/stop early.  Send the new state. */
 	if (os.conn == C_VERIFY_S && ns.conn == C_CONNECTED
-	&& verify_can_do_stop_sector(mdev))
-		drbd_send_state(mdev, ns);
+	&& verify_can_do_stop_sector(device))
+		drbd_send_state(first_peer_device(device), ns);
 
 	/* This triggers bitmap writeout of potentially still unwritten pages
 	 * if the resync finished cleanly, or aborted because of peer disk
@@ -1500,56 +1513,57 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 	 * any bitmap writeout anymore.
 	 * No harm done if some bits change during this phase.
 	 */
-	if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
-		drbd_queue_bitmap_io(mdev, &drbd_bm_write_copy_pages, NULL,
+	if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(device)) {
+		drbd_queue_bitmap_io(device, &drbd_bm_write_copy_pages, NULL,
 			"write from resync_finished", BM_LOCKED_CHANGE_ALLOWED);
-		put_ldev(mdev);
+		put_ldev(device);
 	}
 
 	if (ns.disk == D_DISKLESS &&
 	    ns.conn == C_STANDALONE &&
 	    ns.role == R_SECONDARY) {
 		if (os.aftr_isp != ns.aftr_isp)
-			resume_next_sg(mdev);
+			resume_next_sg(device);
 	}
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 }
 
 struct after_conn_state_chg_work {
 	struct drbd_work w;
 	enum drbd_conns oc;
 	union drbd_state ns_min;
-	union drbd_state ns_max; /* new, max state, over all mdevs */
+	union drbd_state ns_max; /* new, max state, over all devices */
 	enum chg_state_flags flags;
+	struct drbd_connection *connection;
 };
 
 static int w_after_conn_state_ch(struct drbd_work *w, int unused)
 {
 	struct after_conn_state_chg_work *acscw =
 		container_of(w, struct after_conn_state_chg_work, w);
-	struct drbd_tconn *tconn = w->tconn;
+	struct drbd_connection *connection = acscw->connection;
 	enum drbd_conns oc = acscw->oc;
 	union drbd_state ns_max = acscw->ns_max;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	kfree(acscw);
 
 	/* Upon network configuration, we need to start the receiver */
 	if (oc == C_STANDALONE && ns_max.conn == C_UNCONNECTED)
-		drbd_thread_start(&tconn->receiver);
+		drbd_thread_start(&connection->receiver);
 
 	if (oc == C_DISCONNECTING && ns_max.conn == C_STANDALONE) {
 		struct net_conf *old_conf;
 
-		mutex_lock(&tconn->conf_update);
-		old_conf = tconn->net_conf;
-		tconn->my_addr_len = 0;
-		tconn->peer_addr_len = 0;
-		rcu_assign_pointer(tconn->net_conf, NULL);
-		conn_free_crypto(tconn);
-		mutex_unlock(&tconn->conf_update);
+		mutex_lock(&connection->resource->conf_update);
+		old_conf = connection->net_conf;
+		connection->my_addr_len = 0;
+		connection->peer_addr_len = 0;
+		rcu_assign_pointer(connection->net_conf, NULL);
+		conn_free_crypto(connection);
+		mutex_unlock(&connection->resource->conf_update);
 
 		synchronize_rcu();
 		kfree(old_conf);
@@ -1559,45 +1573,47 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused)
 		/* case1: The outdate peer handler is successful: */
 		if (ns_max.pdsk <= D_OUTDATED) {
 			rcu_read_lock();
-			idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-				if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
-					drbd_uuid_new_current(mdev);
-					clear_bit(NEW_CUR_UUID, &mdev->flags);
+			idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+				struct drbd_device *device = peer_device->device;
+				if (test_bit(NEW_CUR_UUID, &device->flags)) {
+					drbd_uuid_new_current(device);
+					clear_bit(NEW_CUR_UUID, &device->flags);
 				}
 			}
 			rcu_read_unlock();
-			spin_lock_irq(&tconn->req_lock);
-			_tl_restart(tconn, CONNECTION_LOST_WHILE_PENDING);
-			_conn_request_state(tconn,
+			spin_lock_irq(&connection->resource->req_lock);
+			_tl_restart(connection, CONNECTION_LOST_WHILE_PENDING);
+			_conn_request_state(connection,
 					    (union drbd_state) { { .susp_fen = 1 } },
 					    (union drbd_state) { { .susp_fen = 0 } },
 					    CS_VERBOSE);
-			spin_unlock_irq(&tconn->req_lock);
+			spin_unlock_irq(&connection->resource->req_lock);
 		}
 	}
-	kref_put(&tconn->kref, &conn_destroy);
+	kref_put(&connection->kref, drbd_destroy_connection);
 
-	conn_md_sync(tconn);
+	conn_md_sync(connection);
 
 	return 0;
 }
 
-void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, enum chg_state_flags *pf)
+void conn_old_common_state(struct drbd_connection *connection, union drbd_state *pcs, enum chg_state_flags *pf)
 {
 	enum chg_state_flags flags = ~0;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr, first_vol = 1;
 	union drbd_dev_state os, cs = {
 		{ .role = R_SECONDARY,
 		  .peer = R_UNKNOWN,
-		  .conn = tconn->cstate,
+		  .conn = connection->cstate,
 		  .disk = D_DISKLESS,
 		  .pdsk = D_UNKNOWN,
 		} };
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		os = mdev->state;
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		os = device->state;
 
 		if (first_vol) {
 			cs = os;
@@ -1628,18 +1644,19 @@ void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, enum
 }
 
 static enum drbd_state_rv
-conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+conn_is_valid_transition(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 			 enum chg_state_flags flags)
 {
 	enum drbd_state_rv rv = SS_SUCCESS;
 	union drbd_state ns, os;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	int vnr;
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		os = drbd_read_state(mdev);
-		ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		os = drbd_read_state(device);
+		ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL);
 
 		if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
 			ns.disk = os.disk;
@@ -1648,30 +1665,29 @@ conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union
 			continue;
 
 		rv = is_valid_transition(os, ns);
-		if (rv < SS_SUCCESS)
-			break;
 
-		if (!(flags & CS_HARD)) {
-			rv = is_valid_state(mdev, ns);
+		if (rv >= SS_SUCCESS && !(flags & CS_HARD)) {
+			rv = is_valid_state(device, ns);
 			if (rv < SS_SUCCESS) {
-				if (is_valid_state(mdev, os) == rv)
-					rv = is_valid_soft_transition(os, ns, tconn);
+				if (is_valid_state(device, os) == rv)
+					rv = is_valid_soft_transition(os, ns, connection);
 			} else
-				rv = is_valid_soft_transition(os, ns, tconn);
+				rv = is_valid_soft_transition(os, ns, connection);
 		}
-		if (rv < SS_SUCCESS)
+
+		if (rv < SS_SUCCESS) {
+			if (flags & CS_VERBOSE)
+				print_st_err(device, os, ns, rv);
 			break;
+		}
 	}
 	rcu_read_unlock();
 
-	if (rv < SS_SUCCESS && flags & CS_VERBOSE)
-		print_st_err(mdev, os, ns, rv);
-
 	return rv;
 }
 
 void
-conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+conn_set_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 	       union drbd_state *pns_min, union drbd_state *pns_max, enum chg_state_flags flags)
 {
 	union drbd_state ns, os, ns_max = { };
@@ -1682,7 +1698,7 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
 		  .disk = D_MASK,
 		  .pdsk = D_MASK
 		} };
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	enum drbd_state_rv rv;
 	int vnr, number_of_volumes = 0;
 
@@ -1690,27 +1706,28 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
 		/* remember last connect time so request_timer_fn() won't
 		 * kill newly established sessions while we are still trying to thaw
 		 * previously frozen IO */
-		if (tconn->cstate != C_WF_REPORT_PARAMS && val.conn == C_WF_REPORT_PARAMS)
-			tconn->last_reconnect_jif = jiffies;
+		if (connection->cstate != C_WF_REPORT_PARAMS && val.conn == C_WF_REPORT_PARAMS)
+			connection->last_reconnect_jif = jiffies;
 
-		tconn->cstate = val.conn;
+		connection->cstate = val.conn;
 	}
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
 		number_of_volumes++;
-		os = drbd_read_state(mdev);
+		os = drbd_read_state(device);
 		ns = apply_mask_val(os, mask, val);
-		ns = sanitize_state(mdev, ns, NULL);
+		ns = sanitize_state(device, ns, NULL);
 
 		if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
 			ns.disk = os.disk;
 
-		rv = __drbd_set_state(mdev, ns, flags, NULL);
+		rv = __drbd_set_state(device, ns, flags, NULL);
 		if (rv < SS_SUCCESS)
 			BUG();
 
-		ns.i = mdev->state.i;
+		ns.i = device->state.i;
 		ns_max.role = max_role(ns.role, ns_max.role);
 		ns_max.peer = max_role(ns.peer, ns_max.peer);
 		ns_max.conn = max_t(enum drbd_conns, ns.conn, ns_max.conn);
@@ -1735,39 +1752,39 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
 			} };
 	}
 
-	ns_min.susp = ns_max.susp = tconn->susp;
-	ns_min.susp_nod = ns_max.susp_nod = tconn->susp_nod;
-	ns_min.susp_fen = ns_max.susp_fen = tconn->susp_fen;
+	ns_min.susp = ns_max.susp = connection->resource->susp;
+	ns_min.susp_nod = ns_max.susp_nod = connection->resource->susp_nod;
+	ns_min.susp_fen = ns_max.susp_fen = connection->resource->susp_fen;
 
 	*pns_min = ns_min;
 	*pns_max = ns_max;
 }
 
 static enum drbd_state_rv
-_conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
+_conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
 {
 	enum drbd_state_rv rv;
 
-	if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags))
+	if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &connection->flags))
 		return SS_CW_SUCCESS;
 
-	if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags))
+	if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &connection->flags))
 		return SS_CW_FAILED_BY_PEER;
 
-	rv = conn_is_valid_transition(tconn, mask, val, 0);
-	if (rv == SS_SUCCESS && tconn->cstate == C_WF_REPORT_PARAMS)
+	rv = conn_is_valid_transition(connection, mask, val, 0);
+	if (rv == SS_SUCCESS && connection->cstate == C_WF_REPORT_PARAMS)
 		rv = SS_UNKNOWN_ERROR; /* continue waiting */
 
 	return rv;
 }
 
 enum drbd_state_rv
-_conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+_conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 		    enum chg_state_flags flags)
 {
 	enum drbd_state_rv rv = SS_SUCCESS;
 	struct after_conn_state_chg_work *acscw;
-	enum drbd_conns oc = tconn->cstate;
+	enum drbd_conns oc = connection->cstate;
 	union drbd_state ns_max, ns_min, os;
 	bool have_mutex = false;
 
@@ -1777,7 +1794,7 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
 			goto abort;
 	}
 
-	rv = conn_is_valid_transition(tconn, mask, val, flags);
+	rv = conn_is_valid_transition(connection, mask, val, flags);
 	if (rv < SS_SUCCESS)
 		goto abort;
 
@@ -1787,38 +1804,38 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
 		/* This will be a cluster-wide state change.
 		 * Need to give up the spinlock, grab the mutex,
 		 * then send the state change request, ... */
-		spin_unlock_irq(&tconn->req_lock);
-		mutex_lock(&tconn->cstate_mutex);
+		spin_unlock_irq(&connection->resource->req_lock);
+		mutex_lock(&connection->cstate_mutex);
 		have_mutex = true;
 
-		set_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
-		if (conn_send_state_req(tconn, mask, val)) {
+		set_bit(CONN_WD_ST_CHG_REQ, &connection->flags);
+		if (conn_send_state_req(connection, mask, val)) {
 			/* sending failed. */
-			clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
+			clear_bit(CONN_WD_ST_CHG_REQ, &connection->flags);
 			rv = SS_CW_FAILED_BY_PEER;
 			/* need to re-aquire the spin lock, though */
 			goto abort_unlocked;
 		}
 
 		if (val.conn == C_DISCONNECTING)
-			set_bit(DISCONNECT_SENT, &tconn->flags);
+			set_bit(DISCONNECT_SENT, &connection->flags);
 
 		/* ... and re-aquire the spinlock.
 		 * If _conn_rq_cond() returned >= SS_SUCCESS, we must call
 		 * conn_set_state() within the same spinlock. */
-		spin_lock_irq(&tconn->req_lock);
-		wait_event_lock_irq(tconn->ping_wait,
-				(rv = _conn_rq_cond(tconn, mask, val)),
-				tconn->req_lock);
-		clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
+		spin_lock_irq(&connection->resource->req_lock);
+		wait_event_lock_irq(connection->ping_wait,
+				(rv = _conn_rq_cond(connection, mask, val)),
+				connection->resource->req_lock);
+		clear_bit(CONN_WD_ST_CHG_REQ, &connection->flags);
 		if (rv < SS_SUCCESS)
 			goto abort;
 	}
 
-	conn_old_common_state(tconn, &os, &flags);
+	conn_old_common_state(connection, &os, &flags);
 	flags |= CS_DC_SUSP;
-	conn_set_state(tconn, mask, val, &ns_min, &ns_max, flags);
-	conn_pr_state_change(tconn, os, ns_max, flags);
+	conn_set_state(connection, mask, val, &ns_min, &ns_max, flags);
+	conn_pr_state_change(connection, os, ns_max, flags);
 
 	acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC);
 	if (acscw) {
@@ -1827,39 +1844,39 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
 		acscw->ns_max = ns_max;
 		acscw->flags = flags;
 		acscw->w.cb = w_after_conn_state_ch;
-		kref_get(&tconn->kref);
-		acscw->w.tconn = tconn;
-		drbd_queue_work(&tconn->sender_work, &acscw->w);
+		kref_get(&connection->kref);
+		acscw->connection = connection;
+		drbd_queue_work(&connection->sender_work, &acscw->w);
 	} else {
-		conn_err(tconn, "Could not kmalloc an acscw\n");
+		drbd_err(connection, "Could not kmalloc an acscw\n");
 	}
 
  abort:
 	if (have_mutex) {
 		/* mutex_unlock() "... must not be used in interrupt context.",
 		 * so give up the spinlock, then re-aquire it */
-		spin_unlock_irq(&tconn->req_lock);
+		spin_unlock_irq(&connection->resource->req_lock);
  abort_unlocked:
-		mutex_unlock(&tconn->cstate_mutex);
-		spin_lock_irq(&tconn->req_lock);
+		mutex_unlock(&connection->cstate_mutex);
+		spin_lock_irq(&connection->resource->req_lock);
 	}
 	if (rv < SS_SUCCESS && flags & CS_VERBOSE) {
-		conn_err(tconn, "State change failed: %s\n", drbd_set_st_err_str(rv));
-		conn_err(tconn, " mask = 0x%x val = 0x%x\n", mask.i, val.i);
-		conn_err(tconn, " old_conn:%s wanted_conn:%s\n", drbd_conn_str(oc), drbd_conn_str(val.conn));
+		drbd_err(connection, "State change failed: %s\n", drbd_set_st_err_str(rv));
+		drbd_err(connection, " mask = 0x%x val = 0x%x\n", mask.i, val.i);
+		drbd_err(connection, " old_conn:%s wanted_conn:%s\n", drbd_conn_str(oc), drbd_conn_str(val.conn));
 	}
 	return rv;
 }
 
 enum drbd_state_rv
-conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 		   enum chg_state_flags flags)
 {
 	enum drbd_state_rv rv;
 
-	spin_lock_irq(&tconn->req_lock);
-	rv = _conn_request_state(tconn, mask, val, flags);
-	spin_unlock_irq(&tconn->req_lock);
+	spin_lock_irq(&connection->resource->req_lock);
+	rv = _conn_request_state(connection, mask, val, flags);
+	spin_unlock_irq(&connection->resource->req_lock);
 
 	return rv;
 }
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index a3c361bbc4b6..cc41605ba21c 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -1,8 +1,8 @@
 #ifndef DRBD_STATE_H
 #define DRBD_STATE_H
 
-struct drbd_conf;
-struct drbd_tconn;
+struct drbd_device;
+struct drbd_connection;
 
 /**
  * DOC: DRBD State macros
@@ -107,36 +107,36 @@ union drbd_dev_state {
 	unsigned int i;
 };
 
-extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
+extern enum drbd_state_rv drbd_change_state(struct drbd_device *device,
 					    enum chg_state_flags f,
 					    union drbd_state mask,
 					    union drbd_state val);
-extern void drbd_force_state(struct drbd_conf *, union drbd_state,
+extern void drbd_force_state(struct drbd_device *, union drbd_state,
 			union drbd_state);
-extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
+extern enum drbd_state_rv _drbd_request_state(struct drbd_device *,
 					      union drbd_state,
 					      union drbd_state,
 					      enum chg_state_flags);
-extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
+extern enum drbd_state_rv __drbd_set_state(struct drbd_device *, union drbd_state,
 					   enum chg_state_flags,
 					   struct completion *done);
-extern void print_st_err(struct drbd_conf *, union drbd_state,
+extern void print_st_err(struct drbd_device *, union drbd_state,
 			union drbd_state, int);
 
 enum drbd_state_rv
-_conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+_conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 		    enum chg_state_flags flags);
 
 enum drbd_state_rv
-conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 		   enum chg_state_flags flags);
 
-extern void drbd_resume_al(struct drbd_conf *mdev);
-extern bool conn_all_vols_unconf(struct drbd_tconn *tconn);
+extern void drbd_resume_al(struct drbd_device *device);
+extern bool conn_all_vols_unconf(struct drbd_connection *connection);
 
 /**
  * drbd_request_state() - Reqest a state change
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @mask:	mask of state bits to change.
  * @val:	value of new state bits.
  *
@@ -144,18 +144,18 @@ extern bool conn_all_vols_unconf(struct drbd_tconn *tconn);
  * quite verbose in case the state change is not possible, and all those
  * state changes are globally serialized.
  */
-static inline int drbd_request_state(struct drbd_conf *mdev,
+static inline int drbd_request_state(struct drbd_device *device,
 				     union drbd_state mask,
 				     union drbd_state val)
 {
-	return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED);
+	return _drbd_request_state(device, mask, val, CS_VERBOSE + CS_ORDERED);
 }
 
-enum drbd_role conn_highest_role(struct drbd_tconn *tconn);
-enum drbd_role conn_highest_peer(struct drbd_tconn *tconn);
-enum drbd_disk_state conn_highest_disk(struct drbd_tconn *tconn);
-enum drbd_disk_state conn_lowest_disk(struct drbd_tconn *tconn);
-enum drbd_disk_state conn_highest_pdsk(struct drbd_tconn *tconn);
-enum drbd_conns conn_lowest_conn(struct drbd_tconn *tconn);
+enum drbd_role conn_highest_role(struct drbd_connection *connection);
+enum drbd_role conn_highest_peer(struct drbd_connection *connection);
+enum drbd_disk_state conn_highest_disk(struct drbd_connection *connection);
+enum drbd_disk_state conn_lowest_disk(struct drbd_connection *connection);
+enum drbd_disk_state conn_highest_pdsk(struct drbd_connection *connection);
+enum drbd_conns conn_lowest_conn(struct drbd_connection *connection);
 
 #endif
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c
index 58e08ff2b2ce..80b0f63c7075 100644
--- a/drivers/block/drbd/drbd_strings.c
+++ b/drivers/block/drbd/drbd_strings.c
@@ -24,6 +24,7 @@
 */
 
 #include <linux/drbd.h>
+#include "drbd_strings.h"
 
 static const char *drbd_conn_s_names[] = {
 	[C_STANDALONE]       = "StandAlone",
diff --git a/drivers/block/drbd/drbd_strings.h b/drivers/block/drbd/drbd_strings.h
new file mode 100644
index 000000000000..f9923cc88afb
--- /dev/null
+++ b/drivers/block/drbd/drbd_strings.h
@@ -0,0 +1,9 @@
+#ifndef __DRBD_STRINGS_H
+#define __DRBD_STRINGS_H
+
+extern const char *drbd_conn_str(enum drbd_conns);
+extern const char *drbd_role_str(enum drbd_role);
+extern const char *drbd_disk_str(enum drbd_disk_state);
+extern const char *drbd_set_st_err_str(enum drbd_state_rv);
+
+#endif  /* __DRBD_STRINGS_H */
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 84d3175d493a..2c4ce42c3657 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -21,7 +21,7 @@
    along with drbd; see the file COPYING.  If not, write to
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
- */
+*/
 
 #include <linux/module.h>
 #include <linux/drbd.h>
@@ -36,10 +36,11 @@
 #include <linux/scatterlist.h>
 
 #include "drbd_int.h"
+#include "drbd_protocol.h"
 #include "drbd_req.h"
 
-static int w_make_ov_request(struct drbd_work *w, int cancel);
-
+static int make_ov_request(struct drbd_device *, int);
+static int make_resync_request(struct drbd_device *, int);
 
 /* endio handlers:
  *   drbd_md_io_complete (defined here)
@@ -67,10 +68,10 @@ rwlock_t global_state_lock;
 void drbd_md_io_complete(struct bio *bio, int error)
 {
 	struct drbd_md_io *md_io;
-	struct drbd_conf *mdev;
+	struct drbd_device *device;
 
 	md_io = (struct drbd_md_io *)bio->bi_private;
-	mdev = container_of(md_io, struct drbd_conf, md_io);
+	device = container_of(md_io, struct drbd_device, md_io);
 
 	md_io->error = error;
 
@@ -83,35 +84,36 @@ void drbd_md_io_complete(struct bio *bio, int error)
 	 * Make sure we first drop the reference, and only then signal
 	 * completion, or we may (in drbd_al_read_log()) cycle so fast into the
 	 * next drbd_md_sync_page_io(), that we trigger the
-	 * ASSERT(atomic_read(&mdev->md_io_in_use) == 1) there.
+	 * ASSERT(atomic_read(&device->md_io_in_use) == 1) there.
 	 */
-	drbd_md_put_buffer(mdev);
+	drbd_md_put_buffer(device);
 	md_io->done = 1;
-	wake_up(&mdev->misc_wait);
+	wake_up(&device->misc_wait);
 	bio_put(bio);
-	if (mdev->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
-		put_ldev(mdev);
+	if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
+		put_ldev(device);
 }
 
 /* reads on behalf of the partner,
  * "submitted" by the receiver
  */
-void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
+static void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
 {
 	unsigned long flags = 0;
-	struct drbd_conf *mdev = peer_req->w.mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	mdev->read_cnt += peer_req->i.size >> 9;
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	device->read_cnt += peer_req->i.size >> 9;
 	list_del(&peer_req->w.list);
-	if (list_empty(&mdev->read_ee))
-		wake_up(&mdev->ee_wait);
+	if (list_empty(&device->read_ee))
+		wake_up(&device->ee_wait);
 	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
-		__drbd_chk_io_error(mdev, DRBD_READ_ERROR);
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		__drbd_chk_io_error(device, DRBD_READ_ERROR);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
-	drbd_queue_work(&mdev->tconn->sender_work, &peer_req->w);
-	put_ldev(mdev);
+	drbd_queue_work(&peer_device->connection->sender_work, &peer_req->w);
+	put_ldev(device);
 }
 
 /* writes on behalf of the partner, or resync writes,
@@ -119,7 +121,8 @@ void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(lo
 static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(local)
 {
 	unsigned long flags = 0;
-	struct drbd_conf *mdev = peer_req->w.mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	struct drbd_interval i;
 	int do_wake;
 	u64 block_id;
@@ -133,35 +136,35 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
 	do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
 	block_id = peer_req->block_id;
 
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
-	mdev->writ_cnt += peer_req->i.size >> 9;
-	list_move_tail(&peer_req->w.list, &mdev->done_ee);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
+	device->writ_cnt += peer_req->i.size >> 9;
+	list_move_tail(&peer_req->w.list, &device->done_ee);
 
 	/*
 	 * Do not remove from the write_requests tree here: we did not send the
 	 * Ack yet and did not wake possibly waiting conflicting requests.
 	 * Removed from the tree from "drbd_process_done_ee" within the
-	 * appropriate w.cb (e_end_block/e_end_resync_block) or from
+	 * appropriate dw.cb (e_end_block/e_end_resync_block) or from
 	 * _drbd_clear_done_ee.
 	 */
 
-	do_wake = list_empty(block_id == ID_SYNCER ? &mdev->sync_ee : &mdev->active_ee);
+	do_wake = list_empty(block_id == ID_SYNCER ? &device->sync_ee : &device->active_ee);
 
 	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
-		__drbd_chk_io_error(mdev, DRBD_WRITE_ERROR);
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		__drbd_chk_io_error(device, DRBD_WRITE_ERROR);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
 
 	if (block_id == ID_SYNCER)
-		drbd_rs_complete_io(mdev, i.sector);
+		drbd_rs_complete_io(device, i.sector);
 
 	if (do_wake)
-		wake_up(&mdev->ee_wait);
+		wake_up(&device->ee_wait);
 
 	if (do_al_complete_io)
-		drbd_al_complete_io(mdev, &i);
+		drbd_al_complete_io(device, &i);
 
-	wake_asender(mdev->tconn);
-	put_ldev(mdev);
+	wake_asender(peer_device->connection);
+	put_ldev(device);
 }
 
 /* writes on behalf of the partner, or resync writes,
@@ -170,17 +173,17 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
 void drbd_peer_request_endio(struct bio *bio, int error)
 {
 	struct drbd_peer_request *peer_req = bio->bi_private;
-	struct drbd_conf *mdev = peer_req->w.mdev;
+	struct drbd_device *device = peer_req->peer_device->device;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 	int is_write = bio_data_dir(bio) == WRITE;
 
 	if (error && __ratelimit(&drbd_ratelimit_state))
-		dev_warn(DEV, "%s: error=%d s=%llus\n",
+		drbd_warn(device, "%s: error=%d s=%llus\n",
 				is_write ? "write" : "read", error,
 				(unsigned long long)peer_req->i.sector);
 	if (!error && !uptodate) {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
+			drbd_warn(device, "%s: setting error to -EIO s=%llus\n",
 					is_write ? "write" : "read",
 					(unsigned long long)peer_req->i.sector);
 		/* strange behavior of some lower level drivers...
@@ -207,13 +210,13 @@ void drbd_request_endio(struct bio *bio, int error)
 {
 	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
-	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_device *device = req->device;
 	struct bio_and_error m;
 	enum drbd_req_event what;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
 	if (!error && !uptodate) {
-		dev_warn(DEV, "p %s: setting error to -EIO\n",
+		drbd_warn(device, "p %s: setting error to -EIO\n",
 			 bio_data_dir(bio) == WRITE ? "write" : "read");
 		/* strange behavior of some lower level drivers...
 		 * fail the request by clearing the uptodate flag,
@@ -252,7 +255,7 @@ void drbd_request_endio(struct bio *bio, int error)
 	 */
 	if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_emerg(DEV, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
+			drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
 
 		if (!error)
 			panic("possible random memory corruption caused by delayed completion of aborted local request\n");
@@ -272,17 +275,16 @@ void drbd_request_endio(struct bio *bio, int error)
 	req->private_bio = ERR_PTR(error);
 
 	/* not req_mod(), we need irqsave here! */
-	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	spin_lock_irqsave(&device->resource->req_lock, flags);
 	__req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
-	put_ldev(mdev);
+	spin_unlock_irqrestore(&device->resource->req_lock, flags);
+	put_ldev(device);
 
 	if (m.bio)
-		complete_master_bio(mdev, &m);
+		complete_master_bio(device, &m);
 }
 
-void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm,
-		  struct drbd_peer_request *peer_req, void *digest)
+void drbd_csum_ee(struct crypto_hash *tfm, struct drbd_peer_request *peer_req, void *digest)
 {
 	struct hash_desc desc;
 	struct scatterlist sg;
@@ -309,7 +311,7 @@ void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm,
 	crypto_hash_final(&desc, digest);
 }
 
-void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *bio, void *digest)
+void drbd_csum_bio(struct crypto_hash *tfm, struct bio *bio, void *digest)
 {
 	struct hash_desc desc;
 	struct scatterlist sg;
@@ -333,7 +335,8 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *
 static int w_e_send_csum(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	int digest_size;
 	void *digest;
 	int err = 0;
@@ -344,89 +347,92 @@ static int w_e_send_csum(struct drbd_work *w, int cancel)
 	if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0))
 		goto out;
 
-	digest_size = crypto_hash_digestsize(mdev->tconn->csums_tfm);
+	digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm);
 	digest = kmalloc(digest_size, GFP_NOIO);
 	if (digest) {
 		sector_t sector = peer_req->i.sector;
 		unsigned int size = peer_req->i.size;
-		drbd_csum_ee(mdev, mdev->tconn->csums_tfm, peer_req, digest);
+		drbd_csum_ee(peer_device->connection->csums_tfm, peer_req, digest);
 		/* Free peer_req and pages before send.
 		 * In case we block on congestion, we could otherwise run into
 		 * some distributed deadlock, if the other side blocks on
 		 * congestion as well, because our receiver blocks in
 		 * drbd_alloc_pages due to pp_in_use > max_buffers. */
-		drbd_free_peer_req(mdev, peer_req);
+		drbd_free_peer_req(device, peer_req);
 		peer_req = NULL;
-		inc_rs_pending(mdev);
-		err = drbd_send_drequest_csum(mdev, sector, size,
+		inc_rs_pending(device);
+		err = drbd_send_drequest_csum(peer_device, sector, size,
 					      digest, digest_size,
 					      P_CSUM_RS_REQUEST);
 		kfree(digest);
 	} else {
-		dev_err(DEV, "kmalloc() of digest failed.\n");
+		drbd_err(device, "kmalloc() of digest failed.\n");
 		err = -ENOMEM;
 	}
 
 out:
 	if (peer_req)
-		drbd_free_peer_req(mdev, peer_req);
+		drbd_free_peer_req(device, peer_req);
 
 	if (unlikely(err))
-		dev_err(DEV, "drbd_send_drequest(..., csum) failed\n");
+		drbd_err(device, "drbd_send_drequest(..., csum) failed\n");
 	return err;
 }
 
 #define GFP_TRY	(__GFP_HIGHMEM | __GFP_NOWARN)
 
-static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
+static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector, int size)
 {
+	struct drbd_device *device = peer_device->device;
 	struct drbd_peer_request *peer_req;
 
-	if (!get_ldev(mdev))
+	if (!get_ldev(device))
 		return -EIO;
 
-	if (drbd_rs_should_slow_down(mdev, sector))
+	if (drbd_rs_should_slow_down(device, sector))
 		goto defer;
 
 	/* GFP_TRY, because if there is no memory available right now, this may
 	 * be rescheduled for later. It is "only" background resync, after all. */
-	peer_req = drbd_alloc_peer_req(mdev, ID_SYNCER /* unused */, sector,
+	peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER /* unused */, sector,
 				       size, GFP_TRY);
 	if (!peer_req)
 		goto defer;
 
 	peer_req->w.cb = w_e_send_csum;
-	spin_lock_irq(&mdev->tconn->req_lock);
-	list_add(&peer_req->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
+	list_add(&peer_req->w.list, &device->read_ee);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	atomic_add(size >> 9, &mdev->rs_sect_ev);
-	if (drbd_submit_peer_request(mdev, peer_req, READ, DRBD_FAULT_RS_RD) == 0)
+	atomic_add(size >> 9, &device->rs_sect_ev);
+	if (drbd_submit_peer_request(device, peer_req, READ, DRBD_FAULT_RS_RD) == 0)
 		return 0;
 
 	/* If it failed because of ENOMEM, retry should help.  If it failed
 	 * because bio_add_page failed (probably broken lower level driver),
 	 * retry may or may not help.
 	 * If it does not, you may need to force disconnect. */
-	spin_lock_irq(&mdev->tconn->req_lock);
+	spin_lock_irq(&device->resource->req_lock);
 	list_del(&peer_req->w.list);
-	spin_unlock_irq(&mdev->tconn->req_lock);
+	spin_unlock_irq(&device->resource->req_lock);
 
-	drbd_free_peer_req(mdev, peer_req);
+	drbd_free_peer_req(device, peer_req);
 defer:
-	put_ldev(mdev);
+	put_ldev(device);
 	return -EAGAIN;
 }
 
 int w_resync_timer(struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
-	switch (mdev->state.conn) {
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, resync_work);
+
+	switch (device->state.conn) {
 	case C_VERIFY_S:
-		w_make_ov_request(w, cancel);
+		make_ov_request(device, cancel);
 		break;
 	case C_SYNC_TARGET:
-		w_make_resync_request(w, cancel);
+		make_resync_request(device, cancel);
 		break;
 	}
 
@@ -435,10 +441,11 @@ int w_resync_timer(struct drbd_work *w, int cancel)
 
 void resync_timer_fn(unsigned long data)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
+	struct drbd_device *device = (struct drbd_device *) data;
 
-	if (list_empty(&mdev->resync_work.list))
-		drbd_queue_work(&mdev->tconn->sender_work, &mdev->resync_work);
+	if (list_empty(&device->resync_work.list))
+		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				&device->resync_work);
 }
 
 static void fifo_set(struct fifo_buffer *fb, int value)
@@ -485,7 +492,7 @@ struct fifo_buffer *fifo_alloc(int fifo_size)
 	return fb;
 }
 
-static int drbd_rs_controller(struct drbd_conf *mdev)
+static int drbd_rs_controller(struct drbd_device *device)
 {
 	struct disk_conf *dc;
 	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
@@ -498,22 +505,22 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
 	int max_sect;
 	struct fifo_buffer *plan;
 
-	sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
-	mdev->rs_in_flight -= sect_in;
+	sect_in = atomic_xchg(&device->rs_sect_in, 0); /* Number of sectors that came in */
+	device->rs_in_flight -= sect_in;
 
-	dc = rcu_dereference(mdev->ldev->disk_conf);
-	plan = rcu_dereference(mdev->rs_plan_s);
+	dc = rcu_dereference(device->ldev->disk_conf);
+	plan = rcu_dereference(device->rs_plan_s);
 
 	steps = plan->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
 
-	if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
+	if (device->rs_in_flight + sect_in == 0) { /* At start of resync */
 		want = ((dc->resync_rate * 2 * SLEEP_TIME) / HZ) * steps;
 	} else { /* normal path */
 		want = dc->c_fill_target ? dc->c_fill_target :
 			sect_in * dc->c_delay_target * HZ / (SLEEP_TIME * 10);
 	}
 
-	correction = want - mdev->rs_in_flight - plan->total;
+	correction = want - device->rs_in_flight - plan->total;
 
 	/* Plan ahead */
 	cps = correction / steps;
@@ -533,25 +540,25 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
 		req_sect = max_sect;
 
 	/*
-	dev_warn(DEV, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
-		 sect_in, mdev->rs_in_flight, want, correction,
-		 steps, cps, mdev->rs_planed, curr_corr, req_sect);
+	drbd_warn(device, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
+		 sect_in, device->rs_in_flight, want, correction,
+		 steps, cps, device->rs_planed, curr_corr, req_sect);
 	*/
 
 	return req_sect;
 }
 
-static int drbd_rs_number_requests(struct drbd_conf *mdev)
+static int drbd_rs_number_requests(struct drbd_device *device)
 {
 	int number;
 
 	rcu_read_lock();
-	if (rcu_dereference(mdev->rs_plan_s)->size) {
-		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
-		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+	if (rcu_dereference(device->rs_plan_s)->size) {
+		number = drbd_rs_controller(device) >> (BM_BLOCK_SHIFT - 9);
+		device->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
 	} else {
-		mdev->c_sync_rate = rcu_dereference(mdev->ldev->disk_conf)->resync_rate;
-		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
+		device->c_sync_rate = rcu_dereference(device->ldev->disk_conf)->resync_rate;
+		number = SLEEP_TIME * device->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
 	}
 	rcu_read_unlock();
 
@@ -560,12 +567,11 @@ static int drbd_rs_number_requests(struct drbd_conf *mdev)
 	return number;
 }
 
-int w_make_resync_request(struct drbd_work *w, int cancel)
+static int make_resync_request(struct drbd_device *device, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
 	unsigned long bit;
 	sector_t sector;
-	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
+	const sector_t capacity = drbd_get_capacity(device->this_bdev);
 	int max_bio_size;
 	int number, rollback_i, size;
 	int align, queued, sndbuf;
@@ -574,61 +580,61 @@ int w_make_resync_request(struct drbd_work *w, int cancel)
 	if (unlikely(cancel))
 		return 0;
 
-	if (mdev->rs_total == 0) {
+	if (device->rs_total == 0) {
 		/* empty resync? */
-		drbd_resync_finished(mdev);
+		drbd_resync_finished(device);
 		return 0;
 	}
 
-	if (!get_ldev(mdev)) {
-		/* Since we only need to access mdev->rsync a
-		   get_ldev_if_state(mdev,D_FAILED) would be sufficient, but
+	if (!get_ldev(device)) {
+		/* Since we only need to access device->rsync a
+		   get_ldev_if_state(device,D_FAILED) would be sufficient, but
 		   to continue resync with a broken disk makes no sense at
 		   all */
-		dev_err(DEV, "Disk broke down during resync!\n");
+		drbd_err(device, "Disk broke down during resync!\n");
 		return 0;
 	}
 
-	max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9;
-	number = drbd_rs_number_requests(mdev);
+	max_bio_size = queue_max_hw_sectors(device->rq_queue) << 9;
+	number = drbd_rs_number_requests(device);
 	if (number == 0)
 		goto requeue;
 
 	for (i = 0; i < number; i++) {
 		/* Stop generating RS requests, when half of the send buffer is filled */
-		mutex_lock(&mdev->tconn->data.mutex);
-		if (mdev->tconn->data.socket) {
-			queued = mdev->tconn->data.socket->sk->sk_wmem_queued;
-			sndbuf = mdev->tconn->data.socket->sk->sk_sndbuf;
+		mutex_lock(&first_peer_device(device)->connection->data.mutex);
+		if (first_peer_device(device)->connection->data.socket) {
+			queued = first_peer_device(device)->connection->data.socket->sk->sk_wmem_queued;
+			sndbuf = first_peer_device(device)->connection->data.socket->sk->sk_sndbuf;
 		} else {
 			queued = 1;
 			sndbuf = 0;
 		}
-		mutex_unlock(&mdev->tconn->data.mutex);
+		mutex_unlock(&first_peer_device(device)->connection->data.mutex);
 		if (queued > sndbuf / 2)
 			goto requeue;
 
 next_sector:
 		size = BM_BLOCK_SIZE;
-		bit  = drbd_bm_find_next(mdev, mdev->bm_resync_fo);
+		bit  = drbd_bm_find_next(device, device->bm_resync_fo);
 
 		if (bit == DRBD_END_OF_BITMAP) {
-			mdev->bm_resync_fo = drbd_bm_bits(mdev);
-			put_ldev(mdev);
+			device->bm_resync_fo = drbd_bm_bits(device);
+			put_ldev(device);
 			return 0;
 		}
 
 		sector = BM_BIT_TO_SECT(bit);
 
-		if (drbd_rs_should_slow_down(mdev, sector) ||
-		    drbd_try_rs_begin_io(mdev, sector)) {
-			mdev->bm_resync_fo = bit;
+		if (drbd_rs_should_slow_down(device, sector) ||
+		    drbd_try_rs_begin_io(device, sector)) {
+			device->bm_resync_fo = bit;
 			goto requeue;
 		}
-		mdev->bm_resync_fo = bit + 1;
+		device->bm_resync_fo = bit + 1;
 
-		if (unlikely(drbd_bm_test_bit(mdev, bit) == 0)) {
-			drbd_rs_complete_io(mdev, sector);
+		if (unlikely(drbd_bm_test_bit(device, bit) == 0)) {
+			drbd_rs_complete_io(device, sector);
 			goto next_sector;
 		}
 
@@ -657,7 +663,7 @@ next_sector:
 			 * obscure reason; ( b == 0 ) would get the out-of-band
 			 * only accidentally right because of the "oddly sized"
 			 * adjustment below */
-			if (drbd_bm_test_bit(mdev, bit+1) != 1)
+			if (drbd_bm_test_bit(device, bit+1) != 1)
 				break;
 			bit++;
 			size += BM_BLOCK_SIZE;
@@ -668,20 +674,21 @@ next_sector:
 		/* if we merged some,
 		 * reset the offset to start the next drbd_bm_find_next from */
 		if (size > BM_BLOCK_SIZE)
-			mdev->bm_resync_fo = bit + 1;
+			device->bm_resync_fo = bit + 1;
 #endif
 
 		/* adjust very last sectors, in case we are oddly sized */
 		if (sector + (size>>9) > capacity)
 			size = (capacity-sector)<<9;
-		if (mdev->tconn->agreed_pro_version >= 89 && mdev->tconn->csums_tfm) {
-			switch (read_for_csum(mdev, sector, size)) {
+		if (first_peer_device(device)->connection->agreed_pro_version >= 89 &&
+		    first_peer_device(device)->connection->csums_tfm) {
+			switch (read_for_csum(first_peer_device(device), sector, size)) {
 			case -EIO: /* Disk failure */
-				put_ldev(mdev);
+				put_ldev(device);
 				return -EIO;
 			case -EAGAIN: /* allocation failed, or ldev busy */
-				drbd_rs_complete_io(mdev, sector);
-				mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+				drbd_rs_complete_io(device, sector);
+				device->bm_resync_fo = BM_SECT_TO_BIT(sector);
 				i = rollback_i;
 				goto requeue;
 			case 0:
@@ -693,50 +700,49 @@ next_sector:
 		} else {
 			int err;
 
-			inc_rs_pending(mdev);
-			err = drbd_send_drequest(mdev, P_RS_DATA_REQUEST,
+			inc_rs_pending(device);
+			err = drbd_send_drequest(first_peer_device(device), P_RS_DATA_REQUEST,
 						 sector, size, ID_SYNCER);
 			if (err) {
-				dev_err(DEV, "drbd_send_drequest() failed, aborting...\n");
-				dec_rs_pending(mdev);
-				put_ldev(mdev);
+				drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
+				dec_rs_pending(device);
+				put_ldev(device);
 				return err;
 			}
 		}
 	}
 
-	if (mdev->bm_resync_fo >= drbd_bm_bits(mdev)) {
+	if (device->bm_resync_fo >= drbd_bm_bits(device)) {
 		/* last syncer _request_ was sent,
 		 * but the P_RS_DATA_REPLY not yet received.  sync will end (and
 		 * next sync group will resume), as soon as we receive the last
 		 * resync data block, and the last bit is cleared.
 		 * until then resync "work" is "inactive" ...
 		 */
-		put_ldev(mdev);
+		put_ldev(device);
 		return 0;
 	}
 
  requeue:
-	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
-	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
-	put_ldev(mdev);
+	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
+	mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
+	put_ldev(device);
 	return 0;
 }
 
-static int w_make_ov_request(struct drbd_work *w, int cancel)
+static int make_ov_request(struct drbd_device *device, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
 	int number, i, size;
 	sector_t sector;
-	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
+	const sector_t capacity = drbd_get_capacity(device->this_bdev);
 	bool stop_sector_reached = false;
 
 	if (unlikely(cancel))
 		return 1;
 
-	number = drbd_rs_number_requests(mdev);
+	number = drbd_rs_number_requests(device);
 
-	sector = mdev->ov_position;
+	sector = device->ov_position;
 	for (i = 0; i < number; i++) {
 		if (sector >= capacity)
 			return 1;
@@ -745,116 +751,121 @@ static int w_make_ov_request(struct drbd_work *w, int cancel)
 		 * w_e_end_ov_reply().
 		 * We need to send at least one request out. */
 		stop_sector_reached = i > 0
-			&& verify_can_do_stop_sector(mdev)
-			&& sector >= mdev->ov_stop_sector;
+			&& verify_can_do_stop_sector(device)
+			&& sector >= device->ov_stop_sector;
 		if (stop_sector_reached)
 			break;
 
 		size = BM_BLOCK_SIZE;
 
-		if (drbd_rs_should_slow_down(mdev, sector) ||
-		    drbd_try_rs_begin_io(mdev, sector)) {
-			mdev->ov_position = sector;
+		if (drbd_rs_should_slow_down(device, sector) ||
+		    drbd_try_rs_begin_io(device, sector)) {
+			device->ov_position = sector;
 			goto requeue;
 		}
 
 		if (sector + (size>>9) > capacity)
 			size = (capacity-sector)<<9;
 
-		inc_rs_pending(mdev);
-		if (drbd_send_ov_request(mdev, sector, size)) {
-			dec_rs_pending(mdev);
+		inc_rs_pending(device);
+		if (drbd_send_ov_request(first_peer_device(device), sector, size)) {
+			dec_rs_pending(device);
 			return 0;
 		}
 		sector += BM_SECT_PER_BIT;
 	}
-	mdev->ov_position = sector;
+	device->ov_position = sector;
 
  requeue:
-	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
+	device->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
 	if (i == 0 || !stop_sector_reached)
-		mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
+		mod_timer(&device->resync_timer, jiffies + SLEEP_TIME);
 	return 1;
 }
 
 int w_ov_finished(struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
-	kfree(w);
-	ov_out_of_sync_print(mdev);
-	drbd_resync_finished(mdev);
+	struct drbd_device_work *dw =
+		container_of(w, struct drbd_device_work, w);
+	struct drbd_device *device = dw->device;
+	kfree(dw);
+	ov_out_of_sync_print(device);
+	drbd_resync_finished(device);
 
 	return 0;
 }
 
 static int w_resync_finished(struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
-	kfree(w);
+	struct drbd_device_work *dw =
+		container_of(w, struct drbd_device_work, w);
+	struct drbd_device *device = dw->device;
+	kfree(dw);
 
-	drbd_resync_finished(mdev);
+	drbd_resync_finished(device);
 
 	return 0;
 }
 
-static void ping_peer(struct drbd_conf *mdev)
+static void ping_peer(struct drbd_device *device)
 {
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 
-	clear_bit(GOT_PING_ACK, &tconn->flags);
-	request_ping(tconn);
-	wait_event(tconn->ping_wait,
-		   test_bit(GOT_PING_ACK, &tconn->flags) || mdev->state.conn < C_CONNECTED);
+	clear_bit(GOT_PING_ACK, &connection->flags);
+	request_ping(connection);
+	wait_event(connection->ping_wait,
+		   test_bit(GOT_PING_ACK, &connection->flags) || device->state.conn < C_CONNECTED);
 }
 
-int drbd_resync_finished(struct drbd_conf *mdev)
+int drbd_resync_finished(struct drbd_device *device)
 {
 	unsigned long db, dt, dbdt;
 	unsigned long n_oos;
 	union drbd_state os, ns;
-	struct drbd_work *w;
+	struct drbd_device_work *dw;
 	char *khelper_cmd = NULL;
 	int verify_done = 0;
 
 	/* Remove all elements from the resync LRU. Since future actions
 	 * might set bits in the (main) bitmap, then the entries in the
 	 * resync LRU would be wrong. */
-	if (drbd_rs_del_all(mdev)) {
+	if (drbd_rs_del_all(device)) {
 		/* In case this is not possible now, most probably because
 		 * there are P_RS_DATA_REPLY Packets lingering on the worker's
 		 * queue (or even the read operations for those packets
 		 * is not finished by now).   Retry in 100ms. */
 
 		schedule_timeout_interruptible(HZ / 10);
-		w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC);
-		if (w) {
-			w->cb = w_resync_finished;
-			w->mdev = mdev;
-			drbd_queue_work(&mdev->tconn->sender_work, w);
+		dw = kmalloc(sizeof(struct drbd_device_work), GFP_ATOMIC);
+		if (dw) {
+			dw->w.cb = w_resync_finished;
+			dw->device = device;
+			drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+					&dw->w);
 			return 1;
 		}
-		dev_err(DEV, "Warn failed to drbd_rs_del_all() and to kmalloc(w).\n");
+		drbd_err(device, "Warn failed to drbd_rs_del_all() and to kmalloc(dw).\n");
 	}
 
-	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
+	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
 	if (dt <= 0)
 		dt = 1;
-	
-	db = mdev->rs_total;
+
+	db = device->rs_total;
 	/* adjust for verify start and stop sectors, respective reached position */
-	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
-		db -= mdev->ov_left;
+	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
+		db -= device->ov_left;
 
 	dbdt = Bit2KB(db/dt);
-	mdev->rs_paused /= HZ;
+	device->rs_paused /= HZ;
 
-	if (!get_ldev(mdev))
+	if (!get_ldev(device))
 		goto out;
 
-	ping_peer(mdev);
+	ping_peer(device);
 
-	spin_lock_irq(&mdev->tconn->req_lock);
-	os = drbd_read_state(mdev);
+	spin_lock_irq(&device->resource->req_lock);
+	os = drbd_read_state(device);
 
 	verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
 
@@ -866,41 +877,41 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 	ns = os;
 	ns.conn = C_CONNECTED;
 
-	dev_info(DEV, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
+	drbd_info(device, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
 	     verify_done ? "Online verify" : "Resync",
-	     dt + mdev->rs_paused, mdev->rs_paused, dbdt);
+	     dt + device->rs_paused, device->rs_paused, dbdt);
 
-	n_oos = drbd_bm_total_weight(mdev);
+	n_oos = drbd_bm_total_weight(device);
 
 	if (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) {
 		if (n_oos) {
-			dev_alert(DEV, "Online verify found %lu %dk block out of sync!\n",
+			drbd_alert(device, "Online verify found %lu %dk block out of sync!\n",
 			      n_oos, Bit2KB(1));
 			khelper_cmd = "out-of-sync";
 		}
 	} else {
-		D_ASSERT((n_oos - mdev->rs_failed) == 0);
+		D_ASSERT(device, (n_oos - device->rs_failed) == 0);
 
 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
 			khelper_cmd = "after-resync-target";
 
-		if (mdev->tconn->csums_tfm && mdev->rs_total) {
-			const unsigned long s = mdev->rs_same_csum;
-			const unsigned long t = mdev->rs_total;
+		if (first_peer_device(device)->connection->csums_tfm && device->rs_total) {
+			const unsigned long s = device->rs_same_csum;
+			const unsigned long t = device->rs_total;
 			const int ratio =
 				(t == 0)     ? 0 :
 			(t < 100000) ? ((s*100)/t) : (s/(t/100));
-			dev_info(DEV, "%u %% had equal checksums, eliminated: %luK; "
+			drbd_info(device, "%u %% had equal checksums, eliminated: %luK; "
 			     "transferred %luK total %luK\n",
 			     ratio,
-			     Bit2KB(mdev->rs_same_csum),
-			     Bit2KB(mdev->rs_total - mdev->rs_same_csum),
-			     Bit2KB(mdev->rs_total));
+			     Bit2KB(device->rs_same_csum),
+			     Bit2KB(device->rs_total - device->rs_same_csum),
+			     Bit2KB(device->rs_total));
 		}
 	}
 
-	if (mdev->rs_failed) {
-		dev_info(DEV, "            %lu failed blocks\n", mdev->rs_failed);
+	if (device->rs_failed) {
+		drbd_info(device, "            %lu failed blocks\n", device->rs_failed);
 
 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
 			ns.disk = D_INCONSISTENT;
@@ -914,179 +925,181 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 		ns.pdsk = D_UP_TO_DATE;
 
 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T) {
-			if (mdev->p_uuid) {
+			if (device->p_uuid) {
 				int i;
 				for (i = UI_BITMAP ; i <= UI_HISTORY_END ; i++)
-					_drbd_uuid_set(mdev, i, mdev->p_uuid[i]);
-				drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_CURRENT]);
-				_drbd_uuid_set(mdev, UI_CURRENT, mdev->p_uuid[UI_CURRENT]);
+					_drbd_uuid_set(device, i, device->p_uuid[i]);
+				drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_CURRENT]);
+				_drbd_uuid_set(device, UI_CURRENT, device->p_uuid[UI_CURRENT]);
 			} else {
-				dev_err(DEV, "mdev->p_uuid is NULL! BUG\n");
+				drbd_err(device, "device->p_uuid is NULL! BUG\n");
 			}
 		}
 
 		if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) {
 			/* for verify runs, we don't update uuids here,
 			 * so there would be nothing to report. */
-			drbd_uuid_set_bm(mdev, 0UL);
-			drbd_print_uuids(mdev, "updated UUIDs");
-			if (mdev->p_uuid) {
+			drbd_uuid_set_bm(device, 0UL);
+			drbd_print_uuids(device, "updated UUIDs");
+			if (device->p_uuid) {
 				/* Now the two UUID sets are equal, update what we
 				 * know of the peer. */
 				int i;
 				for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
-					mdev->p_uuid[i] = mdev->ldev->md.uuid[i];
+					device->p_uuid[i] = device->ldev->md.uuid[i];
 			}
 		}
 	}
 
-	_drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
+	_drbd_set_state(device, ns, CS_VERBOSE, NULL);
 out_unlock:
-	spin_unlock_irq(&mdev->tconn->req_lock);
-	put_ldev(mdev);
+	spin_unlock_irq(&device->resource->req_lock);
+	put_ldev(device);
 out:
-	mdev->rs_total  = 0;
-	mdev->rs_failed = 0;
-	mdev->rs_paused = 0;
+	device->rs_total  = 0;
+	device->rs_failed = 0;
+	device->rs_paused = 0;
 
 	/* reset start sector, if we reached end of device */
-	if (verify_done && mdev->ov_left == 0)
-		mdev->ov_start_sector = 0;
+	if (verify_done && device->ov_left == 0)
+		device->ov_start_sector = 0;
 
-	drbd_md_sync(mdev);
+	drbd_md_sync(device);
 
 	if (khelper_cmd)
-		drbd_khelper(mdev, khelper_cmd);
+		drbd_khelper(device, khelper_cmd);
 
 	return 1;
 }
 
 /* helper */
-static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_peer_request *peer_req)
+static void move_to_net_ee_or_free(struct drbd_device *device, struct drbd_peer_request *peer_req)
 {
 	if (drbd_peer_req_has_active_page(peer_req)) {
 		/* This might happen if sendpage() has not finished */
 		int i = (peer_req->i.size + PAGE_SIZE -1) >> PAGE_SHIFT;
-		atomic_add(i, &mdev->pp_in_use_by_net);
-		atomic_sub(i, &mdev->pp_in_use);
-		spin_lock_irq(&mdev->tconn->req_lock);
-		list_add_tail(&peer_req->w.list, &mdev->net_ee);
-		spin_unlock_irq(&mdev->tconn->req_lock);
+		atomic_add(i, &device->pp_in_use_by_net);
+		atomic_sub(i, &device->pp_in_use);
+		spin_lock_irq(&device->resource->req_lock);
+		list_add_tail(&peer_req->w.list, &device->net_ee);
+		spin_unlock_irq(&device->resource->req_lock);
 		wake_up(&drbd_pp_wait);
 	} else
-		drbd_free_peer_req(mdev, peer_req);
+		drbd_free_peer_req(device, peer_req);
 }
 
 /**
  * w_e_end_data_req() - Worker callback, to send a P_DATA_REPLY packet in response to a P_DATA_REQUEST
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
 int w_e_end_data_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	int err;
 
 	if (unlikely(cancel)) {
-		drbd_free_peer_req(mdev, peer_req);
-		dec_unacked(mdev);
+		drbd_free_peer_req(device, peer_req);
+		dec_unacked(device);
 		return 0;
 	}
 
 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
-		err = drbd_send_block(mdev, P_DATA_REPLY, peer_req);
+		err = drbd_send_block(peer_device, P_DATA_REPLY, peer_req);
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sending NegDReply. sector=%llus.\n",
+			drbd_err(device, "Sending NegDReply. sector=%llus.\n",
 			    (unsigned long long)peer_req->i.sector);
 
-		err = drbd_send_ack(mdev, P_NEG_DREPLY, peer_req);
+		err = drbd_send_ack(peer_device, P_NEG_DREPLY, peer_req);
 	}
 
-	dec_unacked(mdev);
+	dec_unacked(device);
 
-	move_to_net_ee_or_free(mdev, peer_req);
+	move_to_net_ee_or_free(device, peer_req);
 
 	if (unlikely(err))
-		dev_err(DEV, "drbd_send_block() failed\n");
+		drbd_err(device, "drbd_send_block() failed\n");
 	return err;
 }
 
 /**
  * w_e_end_rsdata_req() - Worker callback to send a P_RS_DATA_REPLY packet in response to a P_RS_DATA_REQUEST
- * @mdev:	DRBD device.
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
 int w_e_end_rsdata_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	int err;
 
 	if (unlikely(cancel)) {
-		drbd_free_peer_req(mdev, peer_req);
-		dec_unacked(mdev);
+		drbd_free_peer_req(device, peer_req);
+		dec_unacked(device);
 		return 0;
 	}
 
-	if (get_ldev_if_state(mdev, D_FAILED)) {
-		drbd_rs_complete_io(mdev, peer_req->i.sector);
-		put_ldev(mdev);
+	if (get_ldev_if_state(device, D_FAILED)) {
+		drbd_rs_complete_io(device, peer_req->i.sector);
+		put_ldev(device);
 	}
 
-	if (mdev->state.conn == C_AHEAD) {
-		err = drbd_send_ack(mdev, P_RS_CANCEL, peer_req);
+	if (device->state.conn == C_AHEAD) {
+		err = drbd_send_ack(peer_device, P_RS_CANCEL, peer_req);
 	} else if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
-		if (likely(mdev->state.pdsk >= D_INCONSISTENT)) {
-			inc_rs_pending(mdev);
-			err = drbd_send_block(mdev, P_RS_DATA_REPLY, peer_req);
+		if (likely(device->state.pdsk >= D_INCONSISTENT)) {
+			inc_rs_pending(device);
+			err = drbd_send_block(peer_device, P_RS_DATA_REPLY, peer_req);
 		} else {
 			if (__ratelimit(&drbd_ratelimit_state))
-				dev_err(DEV, "Not sending RSDataReply, "
+				drbd_err(device, "Not sending RSDataReply, "
 				    "partner DISKLESS!\n");
 			err = 0;
 		}
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sending NegRSDReply. sector %llus.\n",
+			drbd_err(device, "Sending NegRSDReply. sector %llus.\n",
 			    (unsigned long long)peer_req->i.sector);
 
-		err = drbd_send_ack(mdev, P_NEG_RS_DREPLY, peer_req);
+		err = drbd_send_ack(peer_device, P_NEG_RS_DREPLY, peer_req);
 
 		/* update resync data with failure */
-		drbd_rs_failed_io(mdev, peer_req->i.sector, peer_req->i.size);
+		drbd_rs_failed_io(device, peer_req->i.sector, peer_req->i.size);
 	}
 
-	dec_unacked(mdev);
+	dec_unacked(device);
 
-	move_to_net_ee_or_free(mdev, peer_req);
+	move_to_net_ee_or_free(device, peer_req);
 
 	if (unlikely(err))
-		dev_err(DEV, "drbd_send_block() failed\n");
+		drbd_err(device, "drbd_send_block() failed\n");
 	return err;
 }
 
 int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	struct digest_info *di;
 	int digest_size;
 	void *digest = NULL;
 	int err, eq = 0;
 
 	if (unlikely(cancel)) {
-		drbd_free_peer_req(mdev, peer_req);
-		dec_unacked(mdev);
+		drbd_free_peer_req(device, peer_req);
+		dec_unacked(device);
 		return 0;
 	}
 
-	if (get_ldev(mdev)) {
-		drbd_rs_complete_io(mdev, peer_req->i.sector);
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		drbd_rs_complete_io(device, peer_req->i.sector);
+		put_ldev(device);
 	}
 
 	di = peer_req->digest;
@@ -1095,47 +1108,48 @@ int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
 		/* quick hack to try to avoid a race against reconfiguration.
 		 * a real fix would be much more involved,
 		 * introducing more locking mechanisms */
-		if (mdev->tconn->csums_tfm) {
-			digest_size = crypto_hash_digestsize(mdev->tconn->csums_tfm);
-			D_ASSERT(digest_size == di->digest_size);
+		if (peer_device->connection->csums_tfm) {
+			digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm);
+			D_ASSERT(device, digest_size == di->digest_size);
 			digest = kmalloc(digest_size, GFP_NOIO);
 		}
 		if (digest) {
-			drbd_csum_ee(mdev, mdev->tconn->csums_tfm, peer_req, digest);
+			drbd_csum_ee(peer_device->connection->csums_tfm, peer_req, digest);
 			eq = !memcmp(digest, di->digest, digest_size);
 			kfree(digest);
 		}
 
 		if (eq) {
-			drbd_set_in_sync(mdev, peer_req->i.sector, peer_req->i.size);
+			drbd_set_in_sync(device, peer_req->i.sector, peer_req->i.size);
 			/* rs_same_csums unit is BM_BLOCK_SIZE */
-			mdev->rs_same_csum += peer_req->i.size >> BM_BLOCK_SHIFT;
-			err = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, peer_req);
+			device->rs_same_csum += peer_req->i.size >> BM_BLOCK_SHIFT;
+			err = drbd_send_ack(peer_device, P_RS_IS_IN_SYNC, peer_req);
 		} else {
-			inc_rs_pending(mdev);
+			inc_rs_pending(device);
 			peer_req->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
 			peer_req->flags &= ~EE_HAS_DIGEST; /* This peer request no longer has a digest pointer */
 			kfree(di);
-			err = drbd_send_block(mdev, P_RS_DATA_REPLY, peer_req);
+			err = drbd_send_block(peer_device, P_RS_DATA_REPLY, peer_req);
 		}
 	} else {
-		err = drbd_send_ack(mdev, P_NEG_RS_DREPLY, peer_req);
+		err = drbd_send_ack(peer_device, P_NEG_RS_DREPLY, peer_req);
 		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sending NegDReply. I guess it gets messy.\n");
+			drbd_err(device, "Sending NegDReply. I guess it gets messy.\n");
 	}
 
-	dec_unacked(mdev);
-	move_to_net_ee_or_free(mdev, peer_req);
+	dec_unacked(device);
+	move_to_net_ee_or_free(device, peer_req);
 
 	if (unlikely(err))
-		dev_err(DEV, "drbd_send_block/ack() failed\n");
+		drbd_err(device, "drbd_send_block/ack() failed\n");
 	return err;
 }
 
 int w_e_end_ov_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	sector_t sector = peer_req->i.sector;
 	unsigned int size = peer_req->i.size;
 	int digest_size;
@@ -1145,7 +1159,7 @@ int w_e_end_ov_req(struct drbd_work *w, int cancel)
 	if (unlikely(cancel))
 		goto out;
 
-	digest_size = crypto_hash_digestsize(mdev->tconn->verify_tfm);
+	digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm);
 	digest = kmalloc(digest_size, GFP_NOIO);
 	if (!digest) {
 		err = 1;	/* terminate the connection in case the allocation failed */
@@ -1153,7 +1167,7 @@ int w_e_end_ov_req(struct drbd_work *w, int cancel)
 	}
 
 	if (likely(!(peer_req->flags & EE_WAS_ERROR)))
-		drbd_csum_ee(mdev, mdev->tconn->verify_tfm, peer_req, digest);
+		drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest);
 	else
 		memset(digest, 0, digest_size);
 
@@ -1162,36 +1176,37 @@ int w_e_end_ov_req(struct drbd_work *w, int cancel)
 	 * some distributed deadlock, if the other side blocks on
 	 * congestion as well, because our receiver blocks in
 	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
-	drbd_free_peer_req(mdev, peer_req);
+	drbd_free_peer_req(device, peer_req);
 	peer_req = NULL;
-	inc_rs_pending(mdev);
-	err = drbd_send_drequest_csum(mdev, sector, size, digest, digest_size, P_OV_REPLY);
+	inc_rs_pending(device);
+	err = drbd_send_drequest_csum(peer_device, sector, size, digest, digest_size, P_OV_REPLY);
 	if (err)
-		dec_rs_pending(mdev);
+		dec_rs_pending(device);
 	kfree(digest);
 
 out:
 	if (peer_req)
-		drbd_free_peer_req(mdev, peer_req);
-	dec_unacked(mdev);
+		drbd_free_peer_req(device, peer_req);
+	dec_unacked(device);
 	return err;
 }
 
-void drbd_ov_out_of_sync_found(struct drbd_conf *mdev, sector_t sector, int size)
+void drbd_ov_out_of_sync_found(struct drbd_device *device, sector_t sector, int size)
 {
-	if (mdev->ov_last_oos_start + mdev->ov_last_oos_size == sector) {
-		mdev->ov_last_oos_size += size>>9;
+	if (device->ov_last_oos_start + device->ov_last_oos_size == sector) {
+		device->ov_last_oos_size += size>>9;
 	} else {
-		mdev->ov_last_oos_start = sector;
-		mdev->ov_last_oos_size = size>>9;
+		device->ov_last_oos_start = sector;
+		device->ov_last_oos_size = size>>9;
 	}
-	drbd_set_out_of_sync(mdev, sector, size);
+	drbd_set_out_of_sync(device, sector, size);
 }
 
 int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 {
 	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_device *peer_device = peer_req->peer_device;
+	struct drbd_device *device = peer_device->device;
 	struct digest_info *di;
 	void *digest;
 	sector_t sector = peer_req->i.sector;
@@ -1201,27 +1216,27 @@ int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 	bool stop_sector_reached = false;
 
 	if (unlikely(cancel)) {
-		drbd_free_peer_req(mdev, peer_req);
-		dec_unacked(mdev);
+		drbd_free_peer_req(device, peer_req);
+		dec_unacked(device);
 		return 0;
 	}
 
 	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
 	 * the resync lru has been cleaned up already */
-	if (get_ldev(mdev)) {
-		drbd_rs_complete_io(mdev, peer_req->i.sector);
-		put_ldev(mdev);
+	if (get_ldev(device)) {
+		drbd_rs_complete_io(device, peer_req->i.sector);
+		put_ldev(device);
 	}
 
 	di = peer_req->digest;
 
 	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
-		digest_size = crypto_hash_digestsize(mdev->tconn->verify_tfm);
+		digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm);
 		digest = kmalloc(digest_size, GFP_NOIO);
 		if (digest) {
-			drbd_csum_ee(mdev, mdev->tconn->verify_tfm, peer_req, digest);
+			drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest);
 
-			D_ASSERT(digest_size == di->digest_size);
+			D_ASSERT(device, digest_size == di->digest_size);
 			eq = !memcmp(digest, di->digest, digest_size);
 			kfree(digest);
 		}
@@ -1232,102 +1247,95 @@ int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 	 * some distributed deadlock, if the other side blocks on
 	 * congestion as well, because our receiver blocks in
 	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
-	drbd_free_peer_req(mdev, peer_req);
+	drbd_free_peer_req(device, peer_req);
 	if (!eq)
-		drbd_ov_out_of_sync_found(mdev, sector, size);
+		drbd_ov_out_of_sync_found(device, sector, size);
 	else
-		ov_out_of_sync_print(mdev);
+		ov_out_of_sync_print(device);
 
-	err = drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size,
+	err = drbd_send_ack_ex(peer_device, P_OV_RESULT, sector, size,
 			       eq ? ID_IN_SYNC : ID_OUT_OF_SYNC);
 
-	dec_unacked(mdev);
+	dec_unacked(device);
 
-	--mdev->ov_left;
+	--device->ov_left;
 
 	/* let's advance progress step marks only for every other megabyte */
-	if ((mdev->ov_left & 0x200) == 0x200)
-		drbd_advance_rs_marks(mdev, mdev->ov_left);
+	if ((device->ov_left & 0x200) == 0x200)
+		drbd_advance_rs_marks(device, device->ov_left);
 
-	stop_sector_reached = verify_can_do_stop_sector(mdev) &&
-		(sector + (size>>9)) >= mdev->ov_stop_sector;
+	stop_sector_reached = verify_can_do_stop_sector(device) &&
+		(sector + (size>>9)) >= device->ov_stop_sector;
 
-	if (mdev->ov_left == 0 || stop_sector_reached) {
-		ov_out_of_sync_print(mdev);
-		drbd_resync_finished(mdev);
+	if (device->ov_left == 0 || stop_sector_reached) {
+		ov_out_of_sync_print(device);
+		drbd_resync_finished(device);
 	}
 
 	return err;
 }
 
-int w_prev_work_done(struct drbd_work *w, int cancel)
-{
-	struct drbd_wq_barrier *b = container_of(w, struct drbd_wq_barrier, w);
-
-	complete(&b->done);
-	return 0;
-}
-
 /* FIXME
  * We need to track the number of pending barrier acks,
  * and to be able to wait for them.
  * See also comment in drbd_adm_attach before drbd_suspend_io.
  */
-int drbd_send_barrier(struct drbd_tconn *tconn)
+static int drbd_send_barrier(struct drbd_connection *connection)
 {
 	struct p_barrier *p;
 	struct drbd_socket *sock;
 
-	sock = &tconn->data;
-	p = conn_prepare_command(tconn, sock);
+	sock = &connection->data;
+	p = conn_prepare_command(connection, sock);
 	if (!p)
 		return -EIO;
-	p->barrier = tconn->send.current_epoch_nr;
+	p->barrier = connection->send.current_epoch_nr;
 	p->pad = 0;
-	tconn->send.current_epoch_writes = 0;
+	connection->send.current_epoch_writes = 0;
 
-	return conn_send_command(tconn, sock, P_BARRIER, sizeof(*p), NULL, 0);
+	return conn_send_command(connection, sock, P_BARRIER, sizeof(*p), NULL, 0);
 }
 
 int w_send_write_hint(struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, unplug_work);
 	struct drbd_socket *sock;
 
 	if (cancel)
 		return 0;
-	sock = &mdev->tconn->data;
-	if (!drbd_prepare_command(mdev, sock))
+	sock = &first_peer_device(device)->connection->data;
+	if (!drbd_prepare_command(first_peer_device(device), sock))
 		return -EIO;
-	return drbd_send_command(mdev, sock, P_UNPLUG_REMOTE, 0, NULL, 0);
+	return drbd_send_command(first_peer_device(device), sock, P_UNPLUG_REMOTE, 0, NULL, 0);
 }
 
-static void re_init_if_first_write(struct drbd_tconn *tconn, unsigned int epoch)
+static void re_init_if_first_write(struct drbd_connection *connection, unsigned int epoch)
 {
-	if (!tconn->send.seen_any_write_yet) {
-		tconn->send.seen_any_write_yet = true;
-		tconn->send.current_epoch_nr = epoch;
-		tconn->send.current_epoch_writes = 0;
+	if (!connection->send.seen_any_write_yet) {
+		connection->send.seen_any_write_yet = true;
+		connection->send.current_epoch_nr = epoch;
+		connection->send.current_epoch_writes = 0;
 	}
 }
 
-static void maybe_send_barrier(struct drbd_tconn *tconn, unsigned int epoch)
+static void maybe_send_barrier(struct drbd_connection *connection, unsigned int epoch)
 {
 	/* re-init if first write on this connection */
-	if (!tconn->send.seen_any_write_yet)
+	if (!connection->send.seen_any_write_yet)
 		return;
-	if (tconn->send.current_epoch_nr != epoch) {
-		if (tconn->send.current_epoch_writes)
-			drbd_send_barrier(tconn);
-		tconn->send.current_epoch_nr = epoch;
+	if (connection->send.current_epoch_nr != epoch) {
+		if (connection->send.current_epoch_writes)
+			drbd_send_barrier(connection);
+		connection->send.current_epoch_nr = epoch;
 	}
 }
 
 int w_send_out_of_sync(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	struct drbd_conf *mdev = w->mdev;
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_device *device = req->device;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	int err;
 
 	if (unlikely(cancel)) {
@@ -1335,13 +1343,13 @@ int w_send_out_of_sync(struct drbd_work *w, int cancel)
 		return 0;
 	}
 
-	/* this time, no tconn->send.current_epoch_writes++;
+	/* this time, no connection->send.current_epoch_writes++;
 	 * If it was sent, it was the closing barrier for the last
 	 * replicated epoch, before we went into AHEAD mode.
 	 * No more barriers will be sent, until we leave AHEAD mode again. */
-	maybe_send_barrier(tconn, req->epoch);
+	maybe_send_barrier(connection, req->epoch);
 
-	err = drbd_send_out_of_sync(mdev, req);
+	err = drbd_send_out_of_sync(first_peer_device(device), req);
 	req_mod(req, OOS_HANDED_TO_NETWORK);
 
 	return err;
@@ -1349,15 +1357,14 @@ int w_send_out_of_sync(struct drbd_work *w, int cancel)
 
 /**
  * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request
- * @mdev:	DRBD device.
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
 int w_send_dblock(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	struct drbd_conf *mdev = w->mdev;
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_device *device = req->device;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	int err;
 
 	if (unlikely(cancel)) {
@@ -1365,11 +1372,11 @@ int w_send_dblock(struct drbd_work *w, int cancel)
 		return 0;
 	}
 
-	re_init_if_first_write(tconn, req->epoch);
-	maybe_send_barrier(tconn, req->epoch);
-	tconn->send.current_epoch_writes++;
+	re_init_if_first_write(connection, req->epoch);
+	maybe_send_barrier(connection, req->epoch);
+	connection->send.current_epoch_writes++;
 
-	err = drbd_send_dblock(mdev, req);
+	err = drbd_send_dblock(first_peer_device(device), req);
 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
 
 	return err;
@@ -1377,15 +1384,14 @@ int w_send_dblock(struct drbd_work *w, int cancel)
 
 /**
  * w_send_read_req() - Worker callback to send a read request (P_DATA_REQUEST) packet
- * @mdev:	DRBD device.
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
 int w_send_read_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	struct drbd_conf *mdev = w->mdev;
-	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_device *device = req->device;
+	struct drbd_connection *connection = first_peer_device(device)->connection;
 	int err;
 
 	if (unlikely(cancel)) {
@@ -1395,9 +1401,9 @@ int w_send_read_req(struct drbd_work *w, int cancel)
 
 	/* Even read requests may close a write epoch,
 	 * if there was any yet. */
-	maybe_send_barrier(tconn, req->epoch);
+	maybe_send_barrier(connection, req->epoch);
 
-	err = drbd_send_drequest(mdev, P_DATA_REQUEST, req->i.sector, req->i.size,
+	err = drbd_send_drequest(first_peer_device(device), P_DATA_REQUEST, req->i.sector, req->i.size,
 				 (unsigned long)req);
 
 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
@@ -1408,21 +1414,21 @@ int w_send_read_req(struct drbd_work *w, int cancel)
 int w_restart_disk_io(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device = req->device;
 
 	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
-		drbd_al_begin_io(mdev, &req->i, false);
+		drbd_al_begin_io(device, &req->i, false);
 
 	drbd_req_make_private_bio(req, req->master_bio);
-	req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
+	req->private_bio->bi_bdev = device->ldev->backing_bdev;
 	generic_make_request(req->private_bio);
 
 	return 0;
 }
 
-static int _drbd_may_sync_now(struct drbd_conf *mdev)
+static int _drbd_may_sync_now(struct drbd_device *device)
 {
-	struct drbd_conf *odev = mdev;
+	struct drbd_device *odev = device;
 	int resync_after;
 
 	while (1) {
@@ -1433,7 +1439,7 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev)
 		rcu_read_unlock();
 		if (resync_after == -1)
 			return 1;
-		odev = minor_to_mdev(resync_after);
+		odev = minor_to_device(resync_after);
 		if (!odev)
 			return 1;
 		if ((odev->state.conn >= C_SYNC_SOURCE &&
@@ -1446,17 +1452,17 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev)
 
 /**
  * _drbd_pause_after() - Pause resync on all devices that may not resync now
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Called from process context only (admin command and after_state_ch).
  */
-static int _drbd_pause_after(struct drbd_conf *mdev)
+static int _drbd_pause_after(struct drbd_device *device)
 {
-	struct drbd_conf *odev;
+	struct drbd_device *odev;
 	int i, rv = 0;
 
 	rcu_read_lock();
-	idr_for_each_entry(&minors, odev, i) {
+	idr_for_each_entry(&drbd_devices, odev, i) {
 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
 			continue;
 		if (!_drbd_may_sync_now(odev))
@@ -1470,17 +1476,17 @@ static int _drbd_pause_after(struct drbd_conf *mdev)
 
 /**
  * _drbd_resume_next() - Resume resync on all devices that may resync now
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  *
  * Called from process context only (admin command and worker).
  */
-static int _drbd_resume_next(struct drbd_conf *mdev)
+static int _drbd_resume_next(struct drbd_device *device)
 {
-	struct drbd_conf *odev;
+	struct drbd_device *odev;
 	int i, rv = 0;
 
 	rcu_read_lock();
-	idr_for_each_entry(&minors, odev, i) {
+	idr_for_each_entry(&drbd_devices, odev, i) {
 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
 			continue;
 		if (odev->state.aftr_isp) {
@@ -1494,24 +1500,24 @@ static int _drbd_resume_next(struct drbd_conf *mdev)
 	return rv;
 }
 
-void resume_next_sg(struct drbd_conf *mdev)
+void resume_next_sg(struct drbd_device *device)
 {
 	write_lock_irq(&global_state_lock);
-	_drbd_resume_next(mdev);
+	_drbd_resume_next(device);
 	write_unlock_irq(&global_state_lock);
 }
 
-void suspend_other_sg(struct drbd_conf *mdev)
+void suspend_other_sg(struct drbd_device *device)
 {
 	write_lock_irq(&global_state_lock);
-	_drbd_pause_after(mdev);
+	_drbd_pause_after(device);
 	write_unlock_irq(&global_state_lock);
 }
 
 /* caller must hold global_state_lock */
-enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
+enum drbd_ret_code drbd_resync_after_valid(struct drbd_device *device, int o_minor)
 {
-	struct drbd_conf *odev;
+	struct drbd_device *odev;
 	int resync_after;
 
 	if (o_minor == -1)
@@ -1520,9 +1526,9 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
 		return ERR_RESYNC_AFTER;
 
 	/* check for loops */
-	odev = minor_to_mdev(o_minor);
+	odev = minor_to_device(o_minor);
 	while (1) {
-		if (odev == mdev)
+		if (odev == device)
 			return ERR_RESYNC_AFTER_CYCLE;
 
 		/* You are free to depend on diskless, non-existing,
@@ -1542,35 +1548,35 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
 			return NO_ERROR;
 
 		/* follow the dependency chain */
-		odev = minor_to_mdev(resync_after);
+		odev = minor_to_device(resync_after);
 	}
 }
 
 /* caller must hold global_state_lock */
-void drbd_resync_after_changed(struct drbd_conf *mdev)
+void drbd_resync_after_changed(struct drbd_device *device)
 {
 	int changes;
 
 	do {
-		changes  = _drbd_pause_after(mdev);
-		changes |= _drbd_resume_next(mdev);
+		changes  = _drbd_pause_after(device);
+		changes |= _drbd_resume_next(device);
 	} while (changes);
 }
 
-void drbd_rs_controller_reset(struct drbd_conf *mdev)
+void drbd_rs_controller_reset(struct drbd_device *device)
 {
 	struct fifo_buffer *plan;
 
-	atomic_set(&mdev->rs_sect_in, 0);
-	atomic_set(&mdev->rs_sect_ev, 0);
-	mdev->rs_in_flight = 0;
+	atomic_set(&device->rs_sect_in, 0);
+	atomic_set(&device->rs_sect_ev, 0);
+	device->rs_in_flight = 0;
 
 	/* Updating the RCU protected object in place is necessary since
 	   this function gets called from atomic context.
 	   It is valid since all other updates also lead to an completely
 	   empty fifo */
 	rcu_read_lock();
-	plan = rcu_dereference(mdev->rs_plan_s);
+	plan = rcu_dereference(device->rs_plan_s);
 	plan->total = 0;
 	fifo_set(plan, 0);
 	rcu_read_unlock();
@@ -1578,101 +1584,104 @@ void drbd_rs_controller_reset(struct drbd_conf *mdev)
 
 void start_resync_timer_fn(unsigned long data)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
+	struct drbd_device *device = (struct drbd_device *) data;
 
-	drbd_queue_work(&mdev->tconn->sender_work, &mdev->start_resync_work);
+	drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+			&device->start_resync_work);
 }
 
 int w_start_resync(struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = w->mdev;
+	struct drbd_device *device =
+		container_of(w, struct drbd_device, start_resync_work);
 
-	if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) {
-		dev_warn(DEV, "w_start_resync later...\n");
-		mdev->start_resync_timer.expires = jiffies + HZ/10;
-		add_timer(&mdev->start_resync_timer);
+	if (atomic_read(&device->unacked_cnt) || atomic_read(&device->rs_pending_cnt)) {
+		drbd_warn(device, "w_start_resync later...\n");
+		device->start_resync_timer.expires = jiffies + HZ/10;
+		add_timer(&device->start_resync_timer);
 		return 0;
 	}
 
-	drbd_start_resync(mdev, C_SYNC_SOURCE);
-	clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags);
+	drbd_start_resync(device, C_SYNC_SOURCE);
+	clear_bit(AHEAD_TO_SYNC_SOURCE, &device->flags);
 	return 0;
 }
 
 /**
  * drbd_start_resync() - Start the resync process
- * @mdev:	DRBD device.
+ * @device:	DRBD device.
  * @side:	Either C_SYNC_SOURCE or C_SYNC_TARGET
  *
  * This function might bring you directly into one of the
  * C_PAUSED_SYNC_* states.
  */
-void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
+void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
 {
 	union drbd_state ns;
 	int r;
 
-	if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn < C_AHEAD) {
-		dev_err(DEV, "Resync already running!\n");
+	if (device->state.conn >= C_SYNC_SOURCE && device->state.conn < C_AHEAD) {
+		drbd_err(device, "Resync already running!\n");
 		return;
 	}
 
-	if (!test_bit(B_RS_H_DONE, &mdev->flags)) {
+	if (!test_bit(B_RS_H_DONE, &device->flags)) {
 		if (side == C_SYNC_TARGET) {
 			/* Since application IO was locked out during C_WF_BITMAP_T and
 			   C_WF_SYNC_UUID we are still unmodified. Before going to C_SYNC_TARGET
 			   we check that we might make the data inconsistent. */
-			r = drbd_khelper(mdev, "before-resync-target");
+			r = drbd_khelper(device, "before-resync-target");
 			r = (r >> 8) & 0xff;
 			if (r > 0) {
-				dev_info(DEV, "before-resync-target handler returned %d, "
+				drbd_info(device, "before-resync-target handler returned %d, "
 					 "dropping connection.\n", r);
-				conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+				conn_request_state(first_peer_device(device)->connection, NS(conn, C_DISCONNECTING), CS_HARD);
 				return;
 			}
 		} else /* C_SYNC_SOURCE */ {
-			r = drbd_khelper(mdev, "before-resync-source");
+			r = drbd_khelper(device, "before-resync-source");
 			r = (r >> 8) & 0xff;
 			if (r > 0) {
 				if (r == 3) {
-					dev_info(DEV, "before-resync-source handler returned %d, "
+					drbd_info(device, "before-resync-source handler returned %d, "
 						 "ignoring. Old userland tools?", r);
 				} else {
-					dev_info(DEV, "before-resync-source handler returned %d, "
+					drbd_info(device, "before-resync-source handler returned %d, "
 						 "dropping connection.\n", r);
-					conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+					conn_request_state(first_peer_device(device)->connection,
+							   NS(conn, C_DISCONNECTING), CS_HARD);
 					return;
 				}
 			}
 		}
 	}
 
-	if (current == mdev->tconn->worker.task) {
+	if (current == first_peer_device(device)->connection->worker.task) {
 		/* The worker should not sleep waiting for state_mutex,
 		   that can take long */
-		if (!mutex_trylock(mdev->state_mutex)) {
-			set_bit(B_RS_H_DONE, &mdev->flags);
-			mdev->start_resync_timer.expires = jiffies + HZ/5;
-			add_timer(&mdev->start_resync_timer);
+		if (!mutex_trylock(device->state_mutex)) {
+			set_bit(B_RS_H_DONE, &device->flags);
+			device->start_resync_timer.expires = jiffies + HZ/5;
+			add_timer(&device->start_resync_timer);
 			return;
 		}
 	} else {
-		mutex_lock(mdev->state_mutex);
+		mutex_lock(device->state_mutex);
 	}
-	clear_bit(B_RS_H_DONE, &mdev->flags);
+	clear_bit(B_RS_H_DONE, &device->flags);
 
 	write_lock_irq(&global_state_lock);
 	/* Did some connection breakage or IO error race with us? */
-	if (mdev->state.conn < C_CONNECTED
-	|| !get_ldev_if_state(mdev, D_NEGOTIATING)) {
+	if (device->state.conn < C_CONNECTED
+	|| !get_ldev_if_state(device, D_NEGOTIATING)) {
 		write_unlock_irq(&global_state_lock);
-		mutex_unlock(mdev->state_mutex);
+		mutex_unlock(device->state_mutex);
 		return;
 	}
 
-	ns = drbd_read_state(mdev);
+	ns = drbd_read_state(device);
 
-	ns.aftr_isp = !_drbd_may_sync_now(mdev);
+	ns.aftr_isp = !_drbd_may_sync_now(device);
 
 	ns.conn = side;
 
@@ -1681,43 +1690,43 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 	else /* side == C_SYNC_SOURCE */
 		ns.pdsk = D_INCONSISTENT;
 
-	r = __drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	ns = drbd_read_state(mdev);
+	r = __drbd_set_state(device, ns, CS_VERBOSE, NULL);
+	ns = drbd_read_state(device);
 
 	if (ns.conn < C_CONNECTED)
 		r = SS_UNKNOWN_ERROR;
 
 	if (r == SS_SUCCESS) {
-		unsigned long tw = drbd_bm_total_weight(mdev);
+		unsigned long tw = drbd_bm_total_weight(device);
 		unsigned long now = jiffies;
 		int i;
 
-		mdev->rs_failed    = 0;
-		mdev->rs_paused    = 0;
-		mdev->rs_same_csum = 0;
-		mdev->rs_last_events = 0;
-		mdev->rs_last_sect_ev = 0;
-		mdev->rs_total     = tw;
-		mdev->rs_start     = now;
+		device->rs_failed    = 0;
+		device->rs_paused    = 0;
+		device->rs_same_csum = 0;
+		device->rs_last_events = 0;
+		device->rs_last_sect_ev = 0;
+		device->rs_total     = tw;
+		device->rs_start     = now;
 		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-			mdev->rs_mark_left[i] = tw;
-			mdev->rs_mark_time[i] = now;
+			device->rs_mark_left[i] = tw;
+			device->rs_mark_time[i] = now;
 		}
-		_drbd_pause_after(mdev);
+		_drbd_pause_after(device);
 	}
 	write_unlock_irq(&global_state_lock);
 
 	if (r == SS_SUCCESS) {
 		/* reset rs_last_bcast when a resync or verify is started,
 		 * to deal with potential jiffies wrap. */
-		mdev->rs_last_bcast = jiffies - HZ;
+		device->rs_last_bcast = jiffies - HZ;
 
-		dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
+		drbd_info(device, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
 		     drbd_conn_str(ns.conn),
-		     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
-		     (unsigned long) mdev->rs_total);
+		     (unsigned long) device->rs_total << (BM_BLOCK_SHIFT-10),
+		     (unsigned long) device->rs_total);
 		if (side == C_SYNC_TARGET)
-			mdev->bm_resync_fo = 0;
+			device->bm_resync_fo = 0;
 
 		/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
 		 * with w_send_oos, or the sync target will get confused as to
@@ -1726,10 +1735,12 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 		 * drbd_resync_finished from here in that case.
 		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
 		 * and from after_state_ch otherwise. */
-		if (side == C_SYNC_SOURCE && mdev->tconn->agreed_pro_version < 96)
-			drbd_gen_and_send_sync_uuid(mdev);
+		if (side == C_SYNC_SOURCE &&
+		    first_peer_device(device)->connection->agreed_pro_version < 96)
+			drbd_gen_and_send_sync_uuid(first_peer_device(device));
 
-		if (mdev->tconn->agreed_pro_version < 95 && mdev->rs_total == 0) {
+		if (first_peer_device(device)->connection->agreed_pro_version < 95 &&
+		    device->rs_total == 0) {
 			/* This still has a race (about when exactly the peers
 			 * detect connection loss) that can lead to a full sync
 			 * on next handshake. In 8.3.9 we fixed this with explicit
@@ -1745,33 +1756,33 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 				int timeo;
 
 				rcu_read_lock();
-				nc = rcu_dereference(mdev->tconn->net_conf);
+				nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 				timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
 				rcu_read_unlock();
 				schedule_timeout_interruptible(timeo);
 			}
-			drbd_resync_finished(mdev);
+			drbd_resync_finished(device);
 		}
 
-		drbd_rs_controller_reset(mdev);
-		/* ns.conn may already be != mdev->state.conn,
+		drbd_rs_controller_reset(device);
+		/* ns.conn may already be != device->state.conn,
 		 * we may have been paused in between, or become paused until
 		 * the timer triggers.
 		 * No matter, that is handled in resync_timer_fn() */
 		if (ns.conn == C_SYNC_TARGET)
-			mod_timer(&mdev->resync_timer, jiffies);
+			mod_timer(&device->resync_timer, jiffies);
 
-		drbd_md_sync(mdev);
+		drbd_md_sync(device);
 	}
-	put_ldev(mdev);
-	mutex_unlock(mdev->state_mutex);
+	put_ldev(device);
+	mutex_unlock(device->state_mutex);
 }
 
 /* If the resource already closed the current epoch, but we did not
  * (because we have not yet seen new requests), we should send the
  * corresponding barrier now.  Must be checked within the same spinlock
  * that is used to check for new requests. */
-bool need_to_send_barrier(struct drbd_tconn *connection)
+static bool need_to_send_barrier(struct drbd_connection *connection)
 {
 	if (!connection->send.seen_any_write_yet)
 		return false;
@@ -1795,7 +1806,7 @@ bool need_to_send_barrier(struct drbd_tconn *connection)
 	return true;
 }
 
-bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
+static bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
 {
 	spin_lock_irq(&queue->q_lock);
 	list_splice_init(&queue->q, work_list);
@@ -1803,7 +1814,7 @@ bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_li
 	return !list_empty(work_list);
 }
 
-bool dequeue_work_item(struct drbd_work_queue *queue, struct list_head *work_list)
+static bool dequeue_work_item(struct drbd_work_queue *queue, struct list_head *work_list)
 {
 	spin_lock_irq(&queue->q_lock);
 	if (!list_empty(&queue->q))
@@ -1812,7 +1823,7 @@ bool dequeue_work_item(struct drbd_work_queue *queue, struct list_head *work_lis
 	return !list_empty(work_list);
 }
 
-void wait_for_work(struct drbd_tconn *connection, struct list_head *work_list)
+static void wait_for_work(struct drbd_connection *connection, struct list_head *work_list)
 {
 	DEFINE_WAIT(wait);
 	struct net_conf *nc;
@@ -1842,7 +1853,7 @@ void wait_for_work(struct drbd_tconn *connection, struct list_head *work_list)
 	for (;;) {
 		int send_barrier;
 		prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE);
-		spin_lock_irq(&connection->req_lock);
+		spin_lock_irq(&connection->resource->req_lock);
 		spin_lock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
 		/* dequeue single item only,
 		 * we still use drbd_queue_work_front() in some places */
@@ -1850,11 +1861,11 @@ void wait_for_work(struct drbd_tconn *connection, struct list_head *work_list)
 			list_move(connection->sender_work.q.next, work_list);
 		spin_unlock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
 		if (!list_empty(work_list) || signal_pending(current)) {
-			spin_unlock_irq(&connection->req_lock);
+			spin_unlock_irq(&connection->resource->req_lock);
 			break;
 		}
 		send_barrier = need_to_send_barrier(connection);
-		spin_unlock_irq(&connection->req_lock);
+		spin_unlock_irq(&connection->resource->req_lock);
 		if (send_barrier) {
 			drbd_send_barrier(connection);
 			connection->send.current_epoch_nr++;
@@ -1883,9 +1894,9 @@ void wait_for_work(struct drbd_tconn *connection, struct list_head *work_list)
 
 int drbd_worker(struct drbd_thread *thi)
 {
-	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_connection *connection = thi->connection;
 	struct drbd_work *w = NULL;
-	struct drbd_conf *mdev;
+	struct drbd_peer_device *peer_device;
 	LIST_HEAD(work_list);
 	int vnr;
 
@@ -1895,12 +1906,12 @@ int drbd_worker(struct drbd_thread *thi)
 		/* as long as we use drbd_queue_work_front(),
 		 * we may only dequeue single work items here, not batches. */
 		if (list_empty(&work_list))
-			wait_for_work(tconn, &work_list);
+			wait_for_work(connection, &work_list);
 
 		if (signal_pending(current)) {
 			flush_signals(current);
 			if (get_t_state(thi) == RUNNING) {
-				conn_warn(tconn, "Worker got an unexpected signal\n");
+				drbd_warn(connection, "Worker got an unexpected signal\n");
 				continue;
 			}
 			break;
@@ -1912,10 +1923,10 @@ int drbd_worker(struct drbd_thread *thi)
 		while (!list_empty(&work_list)) {
 			w = list_first_entry(&work_list, struct drbd_work, list);
 			list_del_init(&w->list);
-			if (w->cb(w, tconn->cstate < C_WF_REPORT_PARAMS) == 0)
+			if (w->cb(w, connection->cstate < C_WF_REPORT_PARAMS) == 0)
 				continue;
-			if (tconn->cstate >= C_WF_REPORT_PARAMS)
-				conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
+			if (connection->cstate >= C_WF_REPORT_PARAMS)
+				conn_request_state(connection, NS(conn, C_NETWORK_FAILURE), CS_HARD);
 		}
 	}
 
@@ -1925,16 +1936,17 @@ int drbd_worker(struct drbd_thread *thi)
 			list_del_init(&w->list);
 			w->cb(w, 1);
 		}
-		dequeue_work_batch(&tconn->sender_work, &work_list);
+		dequeue_work_batch(&connection->sender_work, &work_list);
 	} while (!list_empty(&work_list));
 
 	rcu_read_lock();
-	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
-		D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
-		kref_get(&mdev->kref);
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		D_ASSERT(device, device->state.disk == D_DISKLESS && device->state.conn == C_STANDALONE);
+		kref_get(&device->kref);
 		rcu_read_unlock();
-		drbd_mdev_cleanup(mdev);
-		kref_put(&mdev->kref, &drbd_minor_destroy);
+		drbd_device_cleanup(device);
+		kref_put(&device->kref, drbd_destroy_device);
 		rcu_read_lock();
 	}
 	rcu_read_unlock();
diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h
index 328f18e4b4ee..3db9ebaf64f6 100644
--- a/drivers/block/drbd/drbd_wrappers.h
+++ b/drivers/block/drbd/drbd_wrappers.h
@@ -9,12 +9,12 @@
 extern char *drbd_sec_holder;
 
 /* sets the number of 512 byte sectors of our virtual device */
-static inline void drbd_set_my_capacity(struct drbd_conf *mdev,
+static inline void drbd_set_my_capacity(struct drbd_device *device,
 					sector_t size)
 {
-	/* set_capacity(mdev->this_bdev->bd_disk, size); */
-	set_capacity(mdev->vdisk, size);
-	mdev->this_bdev->bd_inode->i_size = (loff_t)size << 9;
+	/* set_capacity(device->this_bdev->bd_disk, size); */
+	set_capacity(device->vdisk, size);
+	device->this_bdev->bd_inode->i_size = (loff_t)size << 9;
 }
 
 #define drbd_bio_uptodate(bio) bio_flagged(bio, BIO_UPTODATE)
@@ -27,20 +27,20 @@ extern void drbd_request_endio(struct bio *bio, int error);
 /*
  * used to submit our private bio
  */
-static inline void drbd_generic_make_request(struct drbd_conf *mdev,
+static inline void drbd_generic_make_request(struct drbd_device *device,
 					     int fault_type, struct bio *bio)
 {
 	__release(local);
 	if (!bio->bi_bdev) {
 		printk(KERN_ERR "drbd%d: drbd_generic_make_request: "
 				"bio->bi_bdev == NULL\n",
-		       mdev_to_minor(mdev));
+		       device_to_minor(device));
 		dump_stack();
 		bio_endio(bio, -ENODEV);
 		return;
 	}
 
-	if (drbd_insert_fault(mdev, fault_type))
+	if (drbd_insert_fault(device, fault_type))
 		bio_endio(bio, -EIO);
 	else
 		generic_make_request(bio);
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 516026954be6..5299a65182db 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -4615,7 +4615,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
 	if (rv) {
 		dev_warn(&pdev->dev,
 			"Unable to enable MSI interrupt.\n");
-		goto block_initialize_err;
+		goto msi_initialize_err;
 	}
 
 	/* Initialize the block layer. */
@@ -4645,6 +4645,8 @@ static int mtip_pci_probe(struct pci_dev *pdev,
 
 block_initialize_err:
 	pci_disable_msi(pdev);
+
+msi_initialize_err:
 	if (dd->isr_workq) {
 		flush_workqueue(dd->isr_workq);
 		destroy_workqueue(dd->isr_workq);
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index eb6e1e0e8db2..c244c5bc804a 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -3910,18 +3910,22 @@ static void skd_release_msix(struct skd_device *skdev)
 	struct skd_msix_entry *qentry;
 	int i;
 
-	if (skdev->msix_entries == NULL)
-		return;
-	for (i = 0; i < skdev->msix_count; i++) {
-		qentry = &skdev->msix_entries[i];
-		skdev = qentry->rsp;
+	if (skdev->msix_entries) {
+		for (i = 0; i < skdev->msix_count; i++) {
+			qentry = &skdev->msix_entries[i];
+			skdev = qentry->rsp;
+
+			if (qentry->have_irq)
+				devm_free_irq(&skdev->pdev->dev,
+					      qentry->vector, qentry->rsp);
+		}
 
-		if (qentry->have_irq)
-			devm_free_irq(&skdev->pdev->dev,
-				      qentry->vector, qentry->rsp);
+		kfree(skdev->msix_entries);
 	}
-	pci_disable_msix(skdev->pdev);
-	kfree(skdev->msix_entries);
+
+	if (skdev->msix_count)
+		pci_disable_msix(skdev->pdev);
+
 	skdev->msix_count = 0;
 	skdev->msix_entries = NULL;
 }
@@ -3929,12 +3933,10 @@ static void skd_release_msix(struct skd_device *skdev)
 static int skd_acquire_msix(struct skd_device *skdev)
 {
 	int i, rc;
-	struct pci_dev *pdev;
-	struct msix_entry *entries = NULL;
+	struct pci_dev *pdev = skdev->pdev;
+	struct msix_entry *entries;
 	struct skd_msix_entry *qentry;
 
-	pdev = skdev->pdev;
-	skdev->msix_count = SKD_MAX_MSIX_COUNT;
 	entries = kzalloc(sizeof(struct msix_entry) * SKD_MAX_MSIX_COUNT,
 			  GFP_KERNEL);
 	if (!entries)
@@ -3943,40 +3945,25 @@ static int skd_acquire_msix(struct skd_device *skdev)
 	for (i = 0; i < SKD_MAX_MSIX_COUNT; i++)
 		entries[i].entry = i;
 
-	rc = pci_enable_msix(pdev, entries, SKD_MAX_MSIX_COUNT);
-	if (rc < 0)
-		goto msix_out;
+	rc = pci_enable_msix_exact(pdev, entries, SKD_MAX_MSIX_COUNT);
 	if (rc) {
-		if (rc < SKD_MIN_MSIX_COUNT) {
-			pr_err("(%s): failed to enable MSI-X %d\n",
-			       skd_name(skdev), rc);
-			goto msix_out;
-		}
-		pr_debug("%s:%s:%d %s: <%s> allocated %d MSI-X vectors\n",
-			 skdev->name, __func__, __LINE__,
-			 pci_name(pdev), skdev->name, rc);
-
-		skdev->msix_count = rc;
-		rc = pci_enable_msix(pdev, entries, skdev->msix_count);
-		if (rc) {
-			pr_err("(%s): failed to enable MSI-X "
-			       "support (%d) %d\n",
-			       skd_name(skdev), skdev->msix_count, rc);
-			goto msix_out;
-		}
+		pr_err("(%s): failed to enable MSI-X %d\n",
+		       skd_name(skdev), rc);
+		goto msix_out;
 	}
+
+	skdev->msix_count = SKD_MAX_MSIX_COUNT;
 	skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) *
 				      skdev->msix_count, GFP_KERNEL);
 	if (!skdev->msix_entries) {
 		rc = -ENOMEM;
-		skdev->msix_count = 0;
 		pr_err("(%s): msix table allocation error\n",
 		       skd_name(skdev));
 		goto msix_out;
 	}
 
-	qentry = skdev->msix_entries;
 	for (i = 0; i < skdev->msix_count; i++) {
+		qentry = &skdev->msix_entries[i];
 		qentry->vector = entries[i].vector;
 		qentry->entry = entries[i].entry;
 		qentry->rsp = NULL;
@@ -3985,11 +3972,10 @@ static int skd_acquire_msix(struct skd_device *skdev)
 			 skdev->name, __func__, __LINE__,
 			 pci_name(pdev), skdev->name,
 			 i, qentry->vector, qentry->entry);
-		qentry++;
 	}
 
 	/* Enable MSI-X vectors for the base queue */
-	for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+	for (i = 0; i < skdev->msix_count; i++) {
 		qentry = &skdev->msix_entries[i];
 		snprintf(qentry->isr_name, sizeof(qentry->isr_name),
 			 "%s%d-msix %s", DRV_NAME, skdev->devno,
@@ -4045,8 +4031,8 @@ RETRY_IRQ_TYPE:
 	case SKD_IRQ_MSI:
 		snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d-msi",
 			 DRV_NAME, skdev->devno);
-		rc = pci_enable_msi(pdev);
-		if (!rc) {
+		rc = pci_enable_msi_range(pdev, 1, 1);
+		if (rc > 0) {
 			rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr, 0,
 					      skdev->isr_name, skdev);
 			if (rc) {
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 20e061c3e023..c74f7b56e7c4 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -30,6 +30,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/prom.h>
@@ -840,14 +841,17 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
 	spin_lock_irqsave(&swim3_lock, flags);
 	if (fs->state != idle && fs->state != available) {
 		++fs->wanted;
-		while (fs->state != available) {
+		/* this will enable irqs in order to sleep */
+		if (!interruptible)
+			wait_event_lock_irq(fs->wait,
+                                        fs->state == available,
+                                        swim3_lock);
+		else if (wait_event_interruptible_lock_irq(fs->wait,
+					fs->state == available,
+					swim3_lock)) {
+			--fs->wanted;
 			spin_unlock_irqrestore(&swim3_lock, flags);
-			if (interruptible && signal_pending(current)) {
-				--fs->wanted;
-				return -EINTR;
-			}
-			interruptible_sleep_on(&fs->wait);
-			spin_lock_irqsave(&swim3_lock, flags);
+			return -EINTR;
 		}
 		--fs->wanted;
 	}
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 3450be850399..6489c0fd0ea6 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -15,6 +15,16 @@ config ZRAM
 
 	  See zram.txt for more information.
 
+config ZRAM_LZ4_COMPRESS
+	bool "Enable LZ4 algorithm support"
+	depends on ZRAM
+	select LZ4_COMPRESS
+	select LZ4_DECOMPRESS
+	default n
+	help
+	  This option enables LZ4 compression algorithm support. Compression
+	  algorithm can be changed using `comp_algorithm' device attribute.
+
 config ZRAM_DEBUG
 	bool "Compressed RAM block device debug support"
 	depends on ZRAM
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index cb0f9ced6a93..be0763ff57a2 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -1,3 +1,5 @@
-zram-y	:=	zram_drv.o
+zram-y	:=	zcomp_lzo.o zcomp.o zram_drv.o
+
+zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o
 
 obj-$(CONFIG_ZRAM)	+=	zram.o
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
new file mode 100644
index 000000000000..d5919031ca8b
--- /dev/null
+++ b/drivers/block/zram/zcomp.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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/string.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "zcomp.h"
+#include "zcomp_lzo.h"
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+#include "zcomp_lz4.h"
+#endif
+
+/*
+ * single zcomp_strm backend
+ */
+struct zcomp_strm_single {
+	struct mutex strm_lock;
+	struct zcomp_strm *zstrm;
+};
+
+/*
+ * multi zcomp_strm backend
+ */
+struct zcomp_strm_multi {
+	/* protect strm list */
+	spinlock_t strm_lock;
+	/* max possible number of zstrm streams */
+	int max_strm;
+	/* number of available zstrm streams */
+	int avail_strm;
+	/* list of available strms */
+	struct list_head idle_strm;
+	wait_queue_head_t strm_wait;
+};
+
+static struct zcomp_backend *backends[] = {
+	&zcomp_lzo,
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+	&zcomp_lz4,
+#endif
+	NULL
+};
+
+static struct zcomp_backend *find_backend(const char *compress)
+{
+	int i = 0;
+	while (backends[i]) {
+		if (sysfs_streq(compress, backends[i]->name))
+			break;
+		i++;
+	}
+	return backends[i];
+}
+
+static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+	if (zstrm->private)
+		comp->backend->destroy(zstrm->private);
+	free_pages((unsigned long)zstrm->buffer, 1);
+	kfree(zstrm);
+}
+
+/*
+ * allocate new zcomp_strm structure with ->private initialized by
+ * backend, return NULL on error
+ */
+static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
+{
+	struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
+	if (!zstrm)
+		return NULL;
+
+	zstrm->private = comp->backend->create();
+	/*
+	 * allocate 2 pages. 1 for compressed data, plus 1 extra for the
+	 * case when compressed size is larger than the original one
+	 */
+	zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+	if (!zstrm->private || !zstrm->buffer) {
+		zcomp_strm_free(comp, zstrm);
+		zstrm = NULL;
+	}
+	return zstrm;
+}
+
+/*
+ * get idle zcomp_strm or wait until other process release
+ * (zcomp_strm_release()) one for us
+ */
+static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
+{
+	struct zcomp_strm_multi *zs = comp->stream;
+	struct zcomp_strm *zstrm;
+
+	while (1) {
+		spin_lock(&zs->strm_lock);
+		if (!list_empty(&zs->idle_strm)) {
+			zstrm = list_entry(zs->idle_strm.next,
+					struct zcomp_strm, list);
+			list_del(&zstrm->list);
+			spin_unlock(&zs->strm_lock);
+			return zstrm;
+		}
+		/* zstrm streams limit reached, wait for idle stream */
+		if (zs->avail_strm >= zs->max_strm) {
+			spin_unlock(&zs->strm_lock);
+			wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+			continue;
+		}
+		/* allocate new zstrm stream */
+		zs->avail_strm++;
+		spin_unlock(&zs->strm_lock);
+
+		zstrm = zcomp_strm_alloc(comp);
+		if (!zstrm) {
+			spin_lock(&zs->strm_lock);
+			zs->avail_strm--;
+			spin_unlock(&zs->strm_lock);
+			wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+			continue;
+		}
+		break;
+	}
+	return zstrm;
+}
+
+/* add stream back to idle list and wake up waiter or free the stream */
+static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+	struct zcomp_strm_multi *zs = comp->stream;
+
+	spin_lock(&zs->strm_lock);
+	if (zs->avail_strm <= zs->max_strm) {
+		list_add(&zstrm->list, &zs->idle_strm);
+		spin_unlock(&zs->strm_lock);
+		wake_up(&zs->strm_wait);
+		return;
+	}
+
+	zs->avail_strm--;
+	spin_unlock(&zs->strm_lock);
+	zcomp_strm_free(comp, zstrm);
+}
+
+/* change max_strm limit */
+static int zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
+{
+	struct zcomp_strm_multi *zs = comp->stream;
+	struct zcomp_strm *zstrm;
+
+	spin_lock(&zs->strm_lock);
+	zs->max_strm = num_strm;
+	/*
+	 * if user has lowered the limit and there are idle streams,
+	 * immediately free as much streams (and memory) as we can.
+	 */
+	while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
+		zstrm = list_entry(zs->idle_strm.next,
+				struct zcomp_strm, list);
+		list_del(&zstrm->list);
+		zcomp_strm_free(comp, zstrm);
+		zs->avail_strm--;
+	}
+	spin_unlock(&zs->strm_lock);
+	return 0;
+}
+
+static void zcomp_strm_multi_destroy(struct zcomp *comp)
+{
+	struct zcomp_strm_multi *zs = comp->stream;
+	struct zcomp_strm *zstrm;
+
+	while (!list_empty(&zs->idle_strm)) {
+		zstrm = list_entry(zs->idle_strm.next,
+				struct zcomp_strm, list);
+		list_del(&zstrm->list);
+		zcomp_strm_free(comp, zstrm);
+	}
+	kfree(zs);
+}
+
+static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
+{
+	struct zcomp_strm *zstrm;
+	struct zcomp_strm_multi *zs;
+
+	comp->destroy = zcomp_strm_multi_destroy;
+	comp->strm_find = zcomp_strm_multi_find;
+	comp->strm_release = zcomp_strm_multi_release;
+	comp->set_max_streams = zcomp_strm_multi_set_max_streams;
+	zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
+	if (!zs)
+		return -ENOMEM;
+
+	comp->stream = zs;
+	spin_lock_init(&zs->strm_lock);
+	INIT_LIST_HEAD(&zs->idle_strm);
+	init_waitqueue_head(&zs->strm_wait);
+	zs->max_strm = max_strm;
+	zs->avail_strm = 1;
+
+	zstrm = zcomp_strm_alloc(comp);
+	if (!zstrm) {
+		kfree(zs);
+		return -ENOMEM;
+	}
+	list_add(&zstrm->list, &zs->idle_strm);
+	return 0;
+}
+
+static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
+{
+	struct zcomp_strm_single *zs = comp->stream;
+	mutex_lock(&zs->strm_lock);
+	return zs->zstrm;
+}
+
+static void zcomp_strm_single_release(struct zcomp *comp,
+		struct zcomp_strm *zstrm)
+{
+	struct zcomp_strm_single *zs = comp->stream;
+	mutex_unlock(&zs->strm_lock);
+}
+
+static int zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
+{
+	/* zcomp_strm_single support only max_comp_streams == 1 */
+	return -ENOTSUPP;
+}
+
+static void zcomp_strm_single_destroy(struct zcomp *comp)
+{
+	struct zcomp_strm_single *zs = comp->stream;
+	zcomp_strm_free(comp, zs->zstrm);
+	kfree(zs);
+}
+
+static int zcomp_strm_single_create(struct zcomp *comp)
+{
+	struct zcomp_strm_single *zs;
+
+	comp->destroy = zcomp_strm_single_destroy;
+	comp->strm_find = zcomp_strm_single_find;
+	comp->strm_release = zcomp_strm_single_release;
+	comp->set_max_streams = zcomp_strm_single_set_max_streams;
+	zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
+	if (!zs)
+		return -ENOMEM;
+
+	comp->stream = zs;
+	mutex_init(&zs->strm_lock);
+	zs->zstrm = zcomp_strm_alloc(comp);
+	if (!zs->zstrm) {
+		kfree(zs);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/* show available compressors */
+ssize_t zcomp_available_show(const char *comp, char *buf)
+{
+	ssize_t sz = 0;
+	int i = 0;
+
+	while (backends[i]) {
+		if (sysfs_streq(comp, backends[i]->name))
+			sz += sprintf(buf + sz, "[%s] ", backends[i]->name);
+		else
+			sz += sprintf(buf + sz, "%s ", backends[i]->name);
+		i++;
+	}
+	sz += sprintf(buf + sz, "\n");
+	return sz;
+}
+
+int zcomp_set_max_streams(struct zcomp *comp, int num_strm)
+{
+	return comp->set_max_streams(comp, num_strm);
+}
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
+{
+	return comp->strm_find(comp);
+}
+
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+	comp->strm_release(comp, zstrm);
+}
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+		const unsigned char *src, size_t *dst_len)
+{
+	return comp->backend->compress(src, zstrm->buffer, dst_len,
+			zstrm->private);
+}
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+		size_t src_len, unsigned char *dst)
+{
+	return comp->backend->decompress(src, src_len, dst);
+}
+
+void zcomp_destroy(struct zcomp *comp)
+{
+	comp->destroy(comp);
+	kfree(comp);
+}
+
+/*
+ * search available compressors for requested algorithm.
+ * allocate new zcomp and initialize it. return NULL
+ * if requested algorithm is not supported or in case
+ * of init error
+ */
+struct zcomp *zcomp_create(const char *compress, int max_strm)
+{
+	struct zcomp *comp;
+	struct zcomp_backend *backend;
+
+	backend = find_backend(compress);
+	if (!backend)
+		return NULL;
+
+	comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
+	if (!comp)
+		return NULL;
+
+	comp->backend = backend;
+	if (max_strm > 1)
+		zcomp_strm_multi_create(comp, max_strm);
+	else
+		zcomp_strm_single_create(comp);
+	if (!comp->stream) {
+		kfree(comp);
+		return NULL;
+	}
+	return comp;
+}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
new file mode 100644
index 000000000000..8b8997f8613b
--- /dev/null
+++ b/drivers/block/zram/zcomp.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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 _ZCOMP_H_
+#define _ZCOMP_H_
+
+#include <linux/mutex.h>
+
+struct zcomp_strm {
+	/* compression/decompression buffer */
+	void *buffer;
+	/*
+	 * The private data of the compression stream, only compression
+	 * stream backend can touch this (e.g. compression algorithm
+	 * working memory)
+	 */
+	void *private;
+	/* used in multi stream backend, protected by backend strm_lock */
+	struct list_head list;
+};
+
+/* static compression backend */
+struct zcomp_backend {
+	int (*compress)(const unsigned char *src, unsigned char *dst,
+			size_t *dst_len, void *private);
+
+	int (*decompress)(const unsigned char *src, size_t src_len,
+			unsigned char *dst);
+
+	void *(*create)(void);
+	void (*destroy)(void *private);
+
+	const char *name;
+};
+
+/* dynamic per-device compression frontend */
+struct zcomp {
+	void *stream;
+	struct zcomp_backend *backend;
+
+	struct zcomp_strm *(*strm_find)(struct zcomp *comp);
+	void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
+	int (*set_max_streams)(struct zcomp *comp, int num_strm);
+	void (*destroy)(struct zcomp *comp);
+};
+
+ssize_t zcomp_available_show(const char *comp, char *buf);
+
+struct zcomp *zcomp_create(const char *comp, int max_strm);
+void zcomp_destroy(struct zcomp *comp);
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+		const unsigned char *src, size_t *dst_len);
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+		size_t src_len, unsigned char *dst);
+
+int zcomp_set_max_streams(struct zcomp *comp, int num_strm);
+#endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c
new file mode 100644
index 000000000000..f2afb7e988c3
--- /dev/null
+++ b/drivers/block/zram/zcomp_lz4.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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/slab.h>
+#include <linux/lz4.h>
+
+#include "zcomp_lz4.h"
+
+static void *zcomp_lz4_create(void)
+{
+	return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void zcomp_lz4_destroy(void *private)
+{
+	kfree(private);
+}
+
+static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
+		size_t *dst_len, void *private)
+{
+	/* return  : Success if return 0 */
+	return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
+}
+
+static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
+		unsigned char *dst)
+{
+	size_t dst_len = PAGE_SIZE;
+	/* return  : Success if return 0 */
+	return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
+}
+
+struct zcomp_backend zcomp_lz4 = {
+	.compress = zcomp_lz4_compress,
+	.decompress = zcomp_lz4_decompress,
+	.create = zcomp_lz4_create,
+	.destroy = zcomp_lz4_destroy,
+	.name = "lz4",
+};
diff --git a/drivers/block/zram/zcomp_lz4.h b/drivers/block/zram/zcomp_lz4.h
new file mode 100644
index 000000000000..60613fb29dd8
--- /dev/null
+++ b/drivers/block/zram/zcomp_lz4.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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 _ZCOMP_LZ4_H_
+#define _ZCOMP_LZ4_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lz4;
+
+#endif /* _ZCOMP_LZ4_H_ */
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
new file mode 100644
index 000000000000..da1bc47d588e
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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/slab.h>
+#include <linux/lzo.h>
+
+#include "zcomp_lzo.h"
+
+static void *lzo_create(void)
+{
+	return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void lzo_destroy(void *private)
+{
+	kfree(private);
+}
+
+static int lzo_compress(const unsigned char *src, unsigned char *dst,
+		size_t *dst_len, void *private)
+{
+	int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
+	return ret == LZO_E_OK ? 0 : ret;
+}
+
+static int lzo_decompress(const unsigned char *src, size_t src_len,
+		unsigned char *dst)
+{
+	size_t dst_len = PAGE_SIZE;
+	int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+	return ret == LZO_E_OK ? 0 : ret;
+}
+
+struct zcomp_backend zcomp_lzo = {
+	.compress = lzo_compress,
+	.decompress = lzo_decompress,
+	.create = lzo_create,
+	.destroy = lzo_destroy,
+	.name = "lzo",
+};
diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h
new file mode 100644
index 000000000000..128c5807fa14
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute 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 _ZCOMP_LZO_H_
+#define _ZCOMP_LZO_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lzo;
+
+#endif /* _ZCOMP_LZO_H_ */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 011e55d820b1..15d46f2e158c 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -29,7 +29,6 @@
 #include <linux/genhd.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
-#include <linux/lzo.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 
@@ -38,10 +37,27 @@
 /* Globals */
 static int zram_major;
 static struct zram *zram_devices;
+static const char *default_compressor = "lzo";
 
 /* Module params (documentation at end) */
 static unsigned int num_devices = 1;
 
+#define ZRAM_ATTR_RO(name)						\
+static ssize_t zram_attr_##name##_show(struct device *d,		\
+				struct device_attribute *attr, char *b)	\
+{									\
+	struct zram *zram = dev_to_zram(d);				\
+	return sprintf(b, "%llu\n",					\
+		(u64)atomic64_read(&zram->stats.name));			\
+}									\
+static struct device_attribute dev_attr_##name =			\
+	__ATTR(name, S_IRUGO, zram_attr_##name##_show, NULL);
+
+static inline int init_done(struct zram *zram)
+{
+	return zram->meta != NULL;
+}
+
 static inline struct zram *dev_to_zram(struct device *dev)
 {
 	return (struct zram *)dev_to_disk(dev)->private_data;
@@ -58,86 +74,99 @@ static ssize_t disksize_show(struct device *dev,
 static ssize_t initstate_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
+	u32 val;
 	struct zram *zram = dev_to_zram(dev);
 
-	return sprintf(buf, "%u\n", zram->init_done);
-}
-
-static ssize_t num_reads_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct zram *zram = dev_to_zram(dev);
+	down_read(&zram->init_lock);
+	val = init_done(zram);
+	up_read(&zram->init_lock);
 
-	return sprintf(buf, "%llu\n",
-			(u64)atomic64_read(&zram->stats.num_reads));
+	return sprintf(buf, "%u\n", val);
 }
 
-static ssize_t num_writes_show(struct device *dev,
+static ssize_t orig_data_size_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct zram *zram = dev_to_zram(dev);
 
 	return sprintf(buf, "%llu\n",
-			(u64)atomic64_read(&zram->stats.num_writes));
+		(u64)(atomic64_read(&zram->stats.pages_stored)) << PAGE_SHIFT);
 }
 
-static ssize_t invalid_io_show(struct device *dev,
+static ssize_t mem_used_total_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
+	u64 val = 0;
 	struct zram *zram = dev_to_zram(dev);
+	struct zram_meta *meta = zram->meta;
 
-	return sprintf(buf, "%llu\n",
-			(u64)atomic64_read(&zram->stats.invalid_io));
-}
-
-static ssize_t notify_free_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct zram *zram = dev_to_zram(dev);
+	down_read(&zram->init_lock);
+	if (init_done(zram))
+		val = zs_get_total_size_bytes(meta->mem_pool);
+	up_read(&zram->init_lock);
 
-	return sprintf(buf, "%llu\n",
-			(u64)atomic64_read(&zram->stats.notify_free));
+	return sprintf(buf, "%llu\n", val);
 }
 
-static ssize_t zero_pages_show(struct device *dev,
+static ssize_t max_comp_streams_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
+	int val;
 	struct zram *zram = dev_to_zram(dev);
 
-	return sprintf(buf, "%u\n", atomic_read(&zram->stats.pages_zero));
-}
-
-static ssize_t orig_data_size_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct zram *zram = dev_to_zram(dev);
+	down_read(&zram->init_lock);
+	val = zram->max_comp_streams;
+	up_read(&zram->init_lock);
 
-	return sprintf(buf, "%llu\n",
-		(u64)(atomic_read(&zram->stats.pages_stored)) << PAGE_SHIFT);
+	return sprintf(buf, "%d\n", val);
 }
 
-static ssize_t compr_data_size_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t max_comp_streams_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t len)
 {
+	int num;
 	struct zram *zram = dev_to_zram(dev);
 
-	return sprintf(buf, "%llu\n",
-			(u64)atomic64_read(&zram->stats.compr_size));
+	if (kstrtoint(buf, 0, &num))
+		return -EINVAL;
+	if (num < 1)
+		return -EINVAL;
+	down_write(&zram->init_lock);
+	if (init_done(zram)) {
+		if (zcomp_set_max_streams(zram->comp, num))
+			pr_info("Cannot change max compression streams\n");
+	}
+	zram->max_comp_streams = num;
+	up_write(&zram->init_lock);
+	return len;
 }
 
-static ssize_t mem_used_total_show(struct device *dev,
+static ssize_t comp_algorithm_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	u64 val = 0;
+	size_t sz;
 	struct zram *zram = dev_to_zram(dev);
-	struct zram_meta *meta = zram->meta;
 
 	down_read(&zram->init_lock);
-	if (zram->init_done)
-		val = zs_get_total_size_bytes(meta->mem_pool);
+	sz = zcomp_available_show(zram->compressor, buf);
 	up_read(&zram->init_lock);
 
-	return sprintf(buf, "%llu\n", val);
+	return sz;
+}
+
+static ssize_t comp_algorithm_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct zram *zram = dev_to_zram(dev);
+	down_write(&zram->init_lock);
+	if (init_done(zram)) {
+		up_write(&zram->init_lock);
+		pr_info("Can't change algorithm for initialized device\n");
+		return -EBUSY;
+	}
+	strlcpy(zram->compressor, buf, sizeof(zram->compressor));
+	up_write(&zram->init_lock);
+	return len;
 }
 
 /* flag operations needs meta->tb_lock */
@@ -192,8 +221,6 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio)
 static void zram_meta_free(struct zram_meta *meta)
 {
 	zs_destroy_pool(meta->mem_pool);
-	kfree(meta->compress_workmem);
-	free_pages((unsigned long)meta->compress_buffer, 1);
 	vfree(meta->table);
 	kfree(meta);
 }
@@ -205,22 +232,11 @@ static struct zram_meta *zram_meta_alloc(u64 disksize)
 	if (!meta)
 		goto out;
 
-	meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
-	if (!meta->compress_workmem)
-		goto free_meta;
-
-	meta->compress_buffer =
-		(void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
-	if (!meta->compress_buffer) {
-		pr_err("Error allocating compressor buffer space\n");
-		goto free_workmem;
-	}
-
 	num_pages = disksize >> PAGE_SHIFT;
 	meta->table = vzalloc(num_pages * sizeof(*meta->table));
 	if (!meta->table) {
 		pr_err("Error allocating zram address table\n");
-		goto free_buffer;
+		goto free_meta;
 	}
 
 	meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM);
@@ -230,15 +246,10 @@ static struct zram_meta *zram_meta_alloc(u64 disksize)
 	}
 
 	rwlock_init(&meta->tb_lock);
-	mutex_init(&meta->buffer_lock);
 	return meta;
 
 free_table:
 	vfree(meta->table);
-free_buffer:
-	free_pages((unsigned long)meta->compress_buffer, 1);
-free_workmem:
-	kfree(meta->compress_workmem);
 free_meta:
 	kfree(meta);
 	meta = NULL;
@@ -288,7 +299,6 @@ static void zram_free_page(struct zram *zram, size_t index)
 {
 	struct zram_meta *meta = zram->meta;
 	unsigned long handle = meta->table[index].handle;
-	u16 size = meta->table[index].size;
 
 	if (unlikely(!handle)) {
 		/*
@@ -297,21 +307,15 @@ static void zram_free_page(struct zram *zram, size_t index)
 		 */
 		if (zram_test_flag(meta, index, ZRAM_ZERO)) {
 			zram_clear_flag(meta, index, ZRAM_ZERO);
-			atomic_dec(&zram->stats.pages_zero);
+			atomic64_dec(&zram->stats.zero_pages);
 		}
 		return;
 	}
 
-	if (unlikely(size > max_zpage_size))
-		atomic_dec(&zram->stats.bad_compress);
-
 	zs_free(meta->mem_pool, handle);
 
-	if (size <= PAGE_SIZE / 2)
-		atomic_dec(&zram->stats.good_compress);
-
-	atomic64_sub(meta->table[index].size, &zram->stats.compr_size);
-	atomic_dec(&zram->stats.pages_stored);
+	atomic64_sub(meta->table[index].size, &zram->stats.compr_data_size);
+	atomic64_dec(&zram->stats.pages_stored);
 
 	meta->table[index].handle = 0;
 	meta->table[index].size = 0;
@@ -319,8 +323,7 @@ static void zram_free_page(struct zram *zram, size_t index)
 
 static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 {
-	int ret = LZO_E_OK;
-	size_t clen = PAGE_SIZE;
+	int ret = 0;
 	unsigned char *cmem;
 	struct zram_meta *meta = zram->meta;
 	unsigned long handle;
@@ -340,12 +343,12 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 	if (size == PAGE_SIZE)
 		copy_page(mem, cmem);
 	else
-		ret = lzo1x_decompress_safe(cmem, size,	mem, &clen);
+		ret = zcomp_decompress(zram->comp, cmem, size, mem);
 	zs_unmap_object(meta->mem_pool, handle);
 	read_unlock(&meta->tb_lock);
 
 	/* Should NEVER happen. Return bio error if it does. */
-	if (unlikely(ret != LZO_E_OK)) {
+	if (unlikely(ret)) {
 		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
 		atomic64_inc(&zram->stats.failed_reads);
 		return ret;
@@ -388,7 +391,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 
 	ret = zram_decompress_page(zram, uncmem, index);
 	/* Should NEVER happen. Return bio error if it does. */
-	if (unlikely(ret != LZO_E_OK))
+	if (unlikely(ret))
 		goto out_cleanup;
 
 	if (is_partial_io(bvec))
@@ -413,11 +416,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 	struct page *page;
 	unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
 	struct zram_meta *meta = zram->meta;
+	struct zcomp_strm *zstrm;
 	bool locked = false;
 
 	page = bvec->bv_page;
-	src = meta->compress_buffer;
-
 	if (is_partial_io(bvec)) {
 		/*
 		 * This is a partial IO. We need to read the full page
@@ -433,7 +435,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 			goto out;
 	}
 
-	mutex_lock(&meta->buffer_lock);
+	zstrm = zcomp_strm_find(zram->comp);
 	locked = true;
 	user_mem = kmap_atomic(page);
 
@@ -454,28 +456,25 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		zram_set_flag(meta, index, ZRAM_ZERO);
 		write_unlock(&zram->meta->tb_lock);
 
-		atomic_inc(&zram->stats.pages_zero);
+		atomic64_inc(&zram->stats.zero_pages);
 		ret = 0;
 		goto out;
 	}
 
-	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
-			       meta->compress_workmem);
+	ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen);
 	if (!is_partial_io(bvec)) {
 		kunmap_atomic(user_mem);
 		user_mem = NULL;
 		uncmem = NULL;
 	}
 
-	if (unlikely(ret != LZO_E_OK)) {
+	if (unlikely(ret)) {
 		pr_err("Compression failed! err=%d\n", ret);
 		goto out;
 	}
-
+	src = zstrm->buffer;
 	if (unlikely(clen > max_zpage_size)) {
-		atomic_inc(&zram->stats.bad_compress);
 		clen = PAGE_SIZE;
-		src = NULL;
 		if (is_partial_io(bvec))
 			src = uncmem;
 	}
@@ -497,6 +496,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		memcpy(cmem, src, clen);
 	}
 
+	zcomp_strm_release(zram->comp, zstrm);
+	locked = false;
 	zs_unmap_object(meta->mem_pool, handle);
 
 	/*
@@ -511,31 +512,31 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 	write_unlock(&zram->meta->tb_lock);
 
 	/* Update stats */
-	atomic64_add(clen, &zram->stats.compr_size);
-	atomic_inc(&zram->stats.pages_stored);
-	if (clen <= PAGE_SIZE / 2)
-		atomic_inc(&zram->stats.good_compress);
-
+	atomic64_add(clen, &zram->stats.compr_data_size);
+	atomic64_inc(&zram->stats.pages_stored);
 out:
 	if (locked)
-		mutex_unlock(&meta->buffer_lock);
+		zcomp_strm_release(zram->comp, zstrm);
 	if (is_partial_io(bvec))
 		kfree(uncmem);
-
 	if (ret)
 		atomic64_inc(&zram->stats.failed_writes);
 	return ret;
 }
 
 static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
-			int offset, struct bio *bio, int rw)
+			int offset, struct bio *bio)
 {
 	int ret;
+	int rw = bio_data_dir(bio);
 
-	if (rw == READ)
+	if (rw == READ) {
+		atomic64_inc(&zram->stats.num_reads);
 		ret = zram_bvec_read(zram, bvec, index, offset, bio);
-	else
+	} else {
+		atomic64_inc(&zram->stats.num_writes);
 		ret = zram_bvec_write(zram, bvec, index, offset);
+	}
 
 	return ret;
 }
@@ -546,14 +547,12 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
 	struct zram_meta *meta;
 
 	down_write(&zram->init_lock);
-	if (!zram->init_done) {
+	if (!init_done(zram)) {
 		up_write(&zram->init_lock);
 		return;
 	}
 
 	meta = zram->meta;
-	zram->init_done = 0;
-
 	/* Free all pages that are still in this zram device */
 	for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
 		unsigned long handle = meta->table[index].handle;
@@ -563,6 +562,9 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
 		zs_free(meta->mem_pool, handle);
 	}
 
+	zcomp_destroy(zram->comp);
+	zram->max_comp_streams = 1;
+
 	zram_meta_free(zram->meta);
 	zram->meta = NULL;
 	/* Reset stats */
@@ -574,37 +576,13 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
 	up_write(&zram->init_lock);
 }
 
-static void zram_init_device(struct zram *zram, struct zram_meta *meta)
-{
-	if (zram->disksize > 2 * (totalram_pages << PAGE_SHIFT)) {
-		pr_info(
-		"There is little point creating a zram of greater than "
-		"twice the size of memory since we expect a 2:1 compression "
-		"ratio. Note that zram uses about 0.1%% of the size of "
-		"the disk when not in use so a huge zram is "
-		"wasteful.\n"
-		"\tMemory Size: %lu kB\n"
-		"\tSize you selected: %llu kB\n"
-		"Continuing anyway ...\n",
-		(totalram_pages << PAGE_SHIFT) >> 10, zram->disksize >> 10
-		);
-	}
-
-	/* zram devices sort of resembles non-rotational disks */
-	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
-
-	zram->meta = meta;
-	zram->init_done = 1;
-
-	pr_debug("Initialization done!\n");
-}
-
 static ssize_t disksize_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t len)
 {
 	u64 disksize;
 	struct zram_meta *meta;
 	struct zram *zram = dev_to_zram(dev);
+	int err;
 
 	disksize = memparse(buf, NULL);
 	if (!disksize)
@@ -612,20 +590,35 @@ static ssize_t disksize_store(struct device *dev,
 
 	disksize = PAGE_ALIGN(disksize);
 	meta = zram_meta_alloc(disksize);
+	if (!meta)
+		return -ENOMEM;
+
 	down_write(&zram->init_lock);
-	if (zram->init_done) {
-		up_write(&zram->init_lock);
-		zram_meta_free(meta);
+	if (init_done(zram)) {
 		pr_info("Cannot change disksize for initialized device\n");
-		return -EBUSY;
+		err = -EBUSY;
+		goto out_free_meta;
 	}
 
+	zram->comp = zcomp_create(zram->compressor, zram->max_comp_streams);
+	if (!zram->comp) {
+		pr_info("Cannot initialise %s compressing backend\n",
+				zram->compressor);
+		err = -EINVAL;
+		goto out_free_meta;
+	}
+
+	zram->meta = meta;
 	zram->disksize = disksize;
 	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
-	zram_init_device(zram, meta);
 	up_write(&zram->init_lock);
 
 	return len;
+
+out_free_meta:
+	up_write(&zram->init_lock);
+	zram_meta_free(meta);
+	return err;
 }
 
 static ssize_t reset_store(struct device *dev,
@@ -669,22 +662,13 @@ out:
 	return ret;
 }
 
-static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
+static void __zram_make_request(struct zram *zram, struct bio *bio)
 {
 	int offset;
 	u32 index;
 	struct bio_vec bvec;
 	struct bvec_iter iter;
 
-	switch (rw) {
-	case READ:
-		atomic64_inc(&zram->stats.num_reads);
-		break;
-	case WRITE:
-		atomic64_inc(&zram->stats.num_writes);
-		break;
-	}
-
 	index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
 	offset = (bio->bi_iter.bi_sector &
 		  (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
@@ -703,16 +687,15 @@ static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
 			bv.bv_len = max_transfer_size;
 			bv.bv_offset = bvec.bv_offset;
 
-			if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0)
+			if (zram_bvec_rw(zram, &bv, index, offset, bio) < 0)
 				goto out;
 
 			bv.bv_len = bvec.bv_len - max_transfer_size;
 			bv.bv_offset += max_transfer_size;
-			if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0)
+			if (zram_bvec_rw(zram, &bv, index + 1, 0, bio) < 0)
 				goto out;
 		} else
-			if (zram_bvec_rw(zram, &bvec, index, offset, bio, rw)
-			    < 0)
+			if (zram_bvec_rw(zram, &bvec, index, offset, bio) < 0)
 				goto out;
 
 		update_position(&index, &offset, &bvec);
@@ -734,7 +717,7 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio)
 	struct zram *zram = queue->queuedata;
 
 	down_read(&zram->init_lock);
-	if (unlikely(!zram->init_done))
+	if (unlikely(!init_done(zram)))
 		goto error;
 
 	if (!valid_io_request(zram, bio)) {
@@ -742,7 +725,7 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio)
 		goto error;
 	}
 
-	__zram_make_request(zram, bio, bio_data_dir(bio));
+	__zram_make_request(zram, bio);
 	up_read(&zram->init_lock);
 
 	return;
@@ -776,14 +759,21 @@ static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
 		disksize_show, disksize_store);
 static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
 static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
-static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL);
-static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL);
-static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL);
-static DEVICE_ATTR(notify_free, S_IRUGO, notify_free_show, NULL);
-static DEVICE_ATTR(zero_pages, S_IRUGO, zero_pages_show, NULL);
 static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
-static DEVICE_ATTR(compr_data_size, S_IRUGO, compr_data_size_show, NULL);
 static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
+static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
+		max_comp_streams_show, max_comp_streams_store);
+static DEVICE_ATTR(comp_algorithm, S_IRUGO | S_IWUSR,
+		comp_algorithm_show, comp_algorithm_store);
+
+ZRAM_ATTR_RO(num_reads);
+ZRAM_ATTR_RO(num_writes);
+ZRAM_ATTR_RO(failed_reads);
+ZRAM_ATTR_RO(failed_writes);
+ZRAM_ATTR_RO(invalid_io);
+ZRAM_ATTR_RO(notify_free);
+ZRAM_ATTR_RO(zero_pages);
+ZRAM_ATTR_RO(compr_data_size);
 
 static struct attribute *zram_disk_attrs[] = {
 	&dev_attr_disksize.attr,
@@ -791,12 +781,16 @@ static struct attribute *zram_disk_attrs[] = {
 	&dev_attr_reset.attr,
 	&dev_attr_num_reads.attr,
 	&dev_attr_num_writes.attr,
+	&dev_attr_failed_reads.attr,
+	&dev_attr_failed_writes.attr,
 	&dev_attr_invalid_io.attr,
 	&dev_attr_notify_free.attr,
 	&dev_attr_zero_pages.attr,
 	&dev_attr_orig_data_size.attr,
 	&dev_attr_compr_data_size.attr,
 	&dev_attr_mem_used_total.attr,
+	&dev_attr_max_comp_streams.attr,
+	&dev_attr_comp_algorithm.attr,
 	NULL,
 };
 
@@ -837,7 +831,8 @@ static int create_device(struct zram *zram, int device_id)
 
 	/* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
 	set_capacity(zram->disk, 0);
-
+	/* zram devices sort of resembles non-rotational disks */
+	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
 	/*
 	 * To ensure that we always get PAGE_SIZE aligned
 	 * and n*PAGE_SIZED sized I/O requests.
@@ -856,8 +851,9 @@ static int create_device(struct zram *zram, int device_id)
 		pr_warn("Error creating sysfs group");
 		goto out_free_disk;
 	}
-
-	zram->init_done = 0;
+	strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
+	zram->meta = NULL;
+	zram->max_comp_streams = 1;
 	return 0;
 
 out_free_disk:
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index ad8aa35bae00..7f21c145e317 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -16,9 +16,10 @@
 #define _ZRAM_DRV_H_
 
 #include <linux/spinlock.h>
-#include <linux/mutex.h>
 #include <linux/zsmalloc.h>
 
+#include "zcomp.h"
+
 /*
  * Some arbitrary value. This is just to catch
  * invalid value for num_devices module parameter.
@@ -64,38 +65,33 @@ enum zram_pageflags {
 struct table {
 	unsigned long handle;
 	u16 size;	/* object size (excluding header) */
-	u8 count;	/* object ref count (not yet used) */
 	u8 flags;
 } __aligned(4);
 
 struct zram_stats {
-	atomic64_t compr_size;	/* compressed size of pages stored */
+	atomic64_t compr_data_size;	/* compressed size of pages stored */
 	atomic64_t num_reads;	/* failed + successful */
 	atomic64_t num_writes;	/* --do-- */
 	atomic64_t failed_reads;	/* should NEVER! happen */
 	atomic64_t failed_writes;	/* can happen when memory is too low */
 	atomic64_t invalid_io;	/* non-page-aligned I/O requests */
 	atomic64_t notify_free;	/* no. of swap slot free notifications */
-	atomic_t pages_zero;		/* no. of zero filled pages */
-	atomic_t pages_stored;	/* no. of pages currently stored */
-	atomic_t good_compress;	/* % of pages with compression ratio<=50% */
-	atomic_t bad_compress;	/* % of pages with compression ratio>=75% */
+	atomic64_t zero_pages;		/* no. of zero filled pages */
+	atomic64_t pages_stored;	/* no. of pages currently stored */
 };
 
 struct zram_meta {
 	rwlock_t tb_lock;	/* protect table */
-	void *compress_workmem;
-	void *compress_buffer;
 	struct table *table;
 	struct zs_pool *mem_pool;
-	struct mutex buffer_lock; /* protect compress buffers */
 };
 
 struct zram {
 	struct zram_meta *meta;
 	struct request_queue *queue;
 	struct gendisk *disk;
-	int init_done;
+	struct zcomp *comp;
+
 	/* Prevent concurrent execution of device init, reset and R/W request */
 	struct rw_semaphore init_lock;
 	/*
@@ -103,7 +99,8 @@ struct zram {
 	 * we can store in a disk.
 	 */
 	u64 disksize;	/* bytes */
-
+	int max_comp_streams;
 	struct zram_stats stats;
+	char compressor[10];
 };
 #endif
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 106d1d8e16ad..4f78a9d39dc8 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -62,50 +62,53 @@ static const struct usb_device_id ath3k_table[] = {
 	{ USB_DEVICE(0x0CF3, 0x3000) },
 
 	/* Atheros AR3011 with sflash firmware*/
+	{ USB_DEVICE(0x0489, 0xE027) },
+	{ USB_DEVICE(0x0489, 0xE03D) },
+	{ USB_DEVICE(0x0930, 0x0215) },
 	{ USB_DEVICE(0x0CF3, 0x3002) },
 	{ USB_DEVICE(0x0CF3, 0xE019) },
 	{ USB_DEVICE(0x13d3, 0x3304) },
-	{ USB_DEVICE(0x0930, 0x0215) },
-	{ USB_DEVICE(0x0489, 0xE03D) },
-	{ USB_DEVICE(0x0489, 0xE027) },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
 
 	/* Atheros AR3012 with sflash firmware*/
-	{ USB_DEVICE(0x0CF3, 0x0036) },
-	{ USB_DEVICE(0x0CF3, 0x3004) },
-	{ USB_DEVICE(0x0CF3, 0x3008) },
-	{ USB_DEVICE(0x0CF3, 0x311D) },
-	{ USB_DEVICE(0x0CF3, 0x817a) },
-	{ USB_DEVICE(0x13d3, 0x3375) },
+	{ USB_DEVICE(0x0489, 0xe04d) },
+	{ USB_DEVICE(0x0489, 0xe04e) },
+	{ USB_DEVICE(0x0489, 0xe057) },
+	{ USB_DEVICE(0x0489, 0xe056) },
+	{ USB_DEVICE(0x0489, 0xe05f) },
+	{ USB_DEVICE(0x04c5, 0x1330) },
 	{ USB_DEVICE(0x04CA, 0x3004) },
 	{ USB_DEVICE(0x04CA, 0x3005) },
 	{ USB_DEVICE(0x04CA, 0x3006) },
 	{ USB_DEVICE(0x04CA, 0x3008) },
 	{ USB_DEVICE(0x04CA, 0x300b) },
-	{ USB_DEVICE(0x13d3, 0x3362) },
-	{ USB_DEVICE(0x0CF3, 0xE004) },
-	{ USB_DEVICE(0x0CF3, 0xE005) },
 	{ USB_DEVICE(0x0930, 0x0219) },
 	{ USB_DEVICE(0x0930, 0x0220) },
-	{ USB_DEVICE(0x0489, 0xe057) },
-	{ USB_DEVICE(0x13d3, 0x3393) },
-	{ USB_DEVICE(0x0489, 0xe04e) },
-	{ USB_DEVICE(0x0489, 0xe056) },
-	{ USB_DEVICE(0x0489, 0xe04d) },
-	{ USB_DEVICE(0x04c5, 0x1330) },
-	{ USB_DEVICE(0x13d3, 0x3402) },
+	{ USB_DEVICE(0x0b05, 0x17d0) },
+	{ USB_DEVICE(0x0CF3, 0x0036) },
+	{ USB_DEVICE(0x0CF3, 0x3004) },
+	{ USB_DEVICE(0x0CF3, 0x3008) },
+	{ USB_DEVICE(0x0CF3, 0x311D) },
+	{ USB_DEVICE(0x0CF3, 0x311E) },
+	{ USB_DEVICE(0x0CF3, 0x311F) },
 	{ USB_DEVICE(0x0cf3, 0x3121) },
+	{ USB_DEVICE(0x0CF3, 0x817a) },
 	{ USB_DEVICE(0x0cf3, 0xe003) },
-	{ USB_DEVICE(0x0489, 0xe05f) },
+	{ USB_DEVICE(0x0CF3, 0xE004) },
+	{ USB_DEVICE(0x0CF3, 0xE005) },
+	{ USB_DEVICE(0x13d3, 0x3362) },
+	{ USB_DEVICE(0x13d3, 0x3375) },
+	{ USB_DEVICE(0x13d3, 0x3393) },
+	{ USB_DEVICE(0x13d3, 0x3402) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
 
 	/* Atheros AR5BBU22 with sflash firmware */
-	{ USB_DEVICE(0x0489, 0xE03C) },
 	{ USB_DEVICE(0x0489, 0xE036) },
+	{ USB_DEVICE(0x0489, 0xE03C) },
 
 	{ }	/* Terminating entry */
 };
@@ -118,36 +121,39 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
 static const struct usb_device_id ath3k_blist_tbl[] = {
 
 	/* Atheros AR3012 with sflash firmware*/
-	{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
-	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
 
 	{ }	/* Terminating entry */
 };
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index baeaaed299e4..199b9d42489c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -101,21 +101,24 @@ static const struct usb_device_id btusb_table[] = {
 	{ USB_DEVICE(0x0c10, 0x0000) },
 
 	/* Broadcom BCM20702A0 */
+	{ USB_DEVICE(0x0489, 0xe042) },
+	{ USB_DEVICE(0x04ca, 0x2003) },
 	{ USB_DEVICE(0x0b05, 0x17b5) },
 	{ USB_DEVICE(0x0b05, 0x17cb) },
-	{ USB_DEVICE(0x04ca, 0x2003) },
-	{ USB_DEVICE(0x0489, 0xe042) },
 	{ USB_DEVICE(0x413c, 0x8197) },
 
 	/* Foxconn - Hon Hai */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
 
-	/*Broadcom devices with vendor specific id */
+	/* Broadcom devices with vendor specific id */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
 
 	/* Belkin F8065bf - Broadcom based */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
 
+	/* IMC Networks - Broadcom based */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
+
 	{ }	/* Terminating entry */
 };
 
@@ -129,55 +132,58 @@ static const struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros 3011 with sflash firmware */
+	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
-	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
-	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
-	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros 3012 with sflash firmware */
-	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros AR5BBU12 with sflash firmware */
-	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
 
 	/* Broadcom BCM2035 */
-	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
-	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
+	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
 
 	/* Broadcom BCM2045 */
 	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 1ef6990a5c7e..add1c6a72063 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = {
 static struct miscdevice vhci_miscdev= {
 	.name	= "vhci",
 	.fops	= &vhci_fops,
-	.minor	= MISC_DYNAMIC_MINOR,
+	.minor	= VHCI_MINOR,
 };
 
 static int __init vhci_init(void)
@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("devname:vhci");
+MODULE_ALIAS_MISCDEV(VHCI_MINOR);
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 962fd35cbd8d..5a86da97a70b 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -31,7 +31,6 @@
 
 #define DRIVER_NAME		"CCI-400"
 #define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
-#define PMU_NAME		"CCI_400"
 
 #define CCI_PORT_CTRL		0x0
 #define CCI_CTRL_STATUS		0xc
@@ -88,8 +87,7 @@ static unsigned long cci_ctrl_phys;
 
 #define CCI_REV_R0		0
 #define CCI_REV_R1		1
-#define CCI_REV_R0_P4		4
-#define CCI_REV_R1_P2		6
+#define CCI_REV_R1_PX		5
 
 #define CCI_PMU_EVT_SEL		0x000
 #define CCI_PMU_CNTR		0x004
@@ -163,6 +161,15 @@ static struct pmu_port_event_ranges port_event_range[] = {
 	},
 };
 
+/*
+ * Export different PMU names for the different revisions so userspace knows
+ * because the event ids are different
+ */
+static char *const pmu_names[] = {
+	[CCI_REV_R0] = "CCI_400",
+	[CCI_REV_R1] = "CCI_400_r1",
+};
+
 struct cci_pmu_drv_data {
 	void __iomem *base;
 	struct arm_pmu *cci_pmu;
@@ -193,21 +200,16 @@ static int probe_cci_revision(void)
 	rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
 	rev >>= CCI_PID2_REV_SHIFT;
 
-	if (rev <= CCI_REV_R0_P4)
+	if (rev < CCI_REV_R1_PX)
 		return CCI_REV_R0;
-	else if (rev <= CCI_REV_R1_P2)
+	else
 		return CCI_REV_R1;
-
-	return -ENOENT;
 }
 
 static struct pmu_port_event_ranges *port_range_by_rev(void)
 {
 	int rev = probe_cci_revision();
 
-	if (rev < 0)
-		return NULL;
-
 	return &port_event_range[rev];
 }
 
@@ -526,7 +528,7 @@ static void pmu_write_counter(struct perf_event *event, u32 value)
 static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev)
 {
 	*cci_pmu = (struct arm_pmu){
-		.name             = PMU_NAME,
+		.name		  = pmu_names[probe_cci_revision()],
 		.max_period       = (1LLU << 32) - 1,
 		.get_hw_events    = pmu_get_hw_events,
 		.get_event_idx    = pmu_get_event_idx,
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 3ef58c8dbf11..f8ee13c7bf7b 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -11,6 +11,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/regmap.h>
 
 struct imx_weim_devtype {
 	unsigned int	cs_count;
@@ -56,6 +59,55 @@ static const struct of_device_id weim_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, weim_id_table);
 
+static int __init imx_weim_gpr_setup(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct property *prop;
+	const __be32 *p;
+	struct regmap *gpr;
+	u32 gprvals[4] = {
+		05,	/* CS0(128M) CS1(0M)  CS2(0M)  CS3(0M)  */
+		033,	/* CS0(64M)  CS1(64M) CS2(0M)  CS3(0M)  */
+		0113,	/* CS0(64M)  CS1(32M) CS2(32M) CS3(0M)  */
+		01111,	/* CS0(32M)  CS1(32M) CS2(32M) CS3(32M) */
+	};
+	u32 gprval = 0;
+	u32 val;
+	int cs = 0;
+	int i = 0;
+
+	gpr = syscon_regmap_lookup_by_phandle(np, "fsl,weim-cs-gpr");
+	if (IS_ERR(gpr)) {
+		dev_dbg(&pdev->dev, "failed to find weim-cs-gpr\n");
+		return 0;
+	}
+
+	of_property_for_each_u32(np, "ranges", prop, p, val) {
+		if (i % 4 == 0) {
+			cs = val;
+		} else if (i % 4 == 3 && val) {
+			val = (val / SZ_32M) | 1;
+			gprval |= val << cs * 3;
+		}
+		i++;
+	}
+
+	if (i == 0 || i % 4)
+		goto err;
+
+	for (i = 0; i < ARRAY_SIZE(gprvals); i++) {
+		if (gprval == gprvals[i]) {
+			/* Found it. Set up IOMUXC_GPR1[11:0] with it. */
+			regmap_update_bits(gpr, IOMUXC_GPR1, 0xfff, gprval);
+			return 0;
+		}
+	}
+
+err:
+	dev_err(&pdev->dev, "Invalid 'ranges' configuration\n");
+	return -EINVAL;
+}
+
 /* Parse and set the timing for this device. */
 static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
 				    const struct imx_weim_devtype *devtype)
@@ -92,6 +144,12 @@ static int __init weim_parse_dt(struct platform_device *pdev,
 	struct device_node *child;
 	int ret;
 
+	if (devtype == &imx50_weim_devtype) {
+		ret = imx_weim_gpr_setup(pdev);
+		if (ret)
+			return ret;
+	}
+
 	for_each_child_of_node(pdev->dev.of_node, child) {
 		if (!child->name)
 			continue;
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 725c46162bbd..293e2e0a0a87 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -870,14 +870,14 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
 	ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		mem->start = reg[0];
-		mem->end = mem->start + reg[1];
+		mem->end = mem->start + reg[1] - 1;
 		mem->flags = IORESOURCE_MEM;
 	}
 
 	ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		io->start = reg[0];
-		io->end = io->start + reg[1];
+		io->end = io->start + reg[1] - 1;
 		io->flags = IORESOURCE_IO;
 	}
 }
@@ -890,13 +890,12 @@ int __init mvebu_mbus_dt_init(void)
 	const __be32 *prop;
 	int ret;
 
-	np = of_find_matching_node(NULL, of_mvebu_mbus_ids);
+	np = of_find_matching_node_and_match(NULL, of_mvebu_mbus_ids, &of_id);
 	if (!np) {
 		pr_err("could not find a matching SoC family\n");
 		return -ENODEV;
 	}
 
-	of_id = of_match_node(of_mvebu_mbus_ids, np);
 	mbus_state.soc = of_id->data;
 
 	prop = of_get_property(np, "controller", NULL);
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 1b192395a90c..8121b4c70ede 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/agp_backend.h>
 #include <linux/agpgart.h>
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f39437addb58..0fbccce1cee9 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -29,7 +29,6 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/miscdevice.h>
 #include <linux/pm.h>
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 5c85350f4c3d..9a024f899dd4 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 05b8d0241bde..3051c73bc383 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/agp_backend.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 2f2b08457c67..244759bbd7b7 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -342,11 +342,11 @@ config HW_RANDOM_TPM
 	  If unsure, say Y.
 
 config HW_RANDOM_MSM
-	tristate "Qualcomm MSM Random Number Generator support"
-	depends on HW_RANDOM && ARCH_MSM
+	tristate "Qualcomm SoCs Random Number Generator support"
+	depends on HW_RANDOM && ARCH_QCOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on Qualcomm MSM SoCs.
+	  Generator hardware found on Qualcomm SoCs.
 
 	  To compile this driver as a module, choose M here. the
 	  module will be called msm-rng.
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index bf9fc6b79328..dfeddf2c00b7 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -54,21 +54,14 @@ static int atmel_trng_probe(struct platform_device *pdev)
 	struct resource *res;
 	int ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -EINVAL;
-
 	trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
 	if (!trng)
 		return -ENOMEM;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res), pdev->name))
-		return -EBUSY;
-
-	trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!trng->base)
-		return -EBUSY;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	trng->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(trng->base))
+		return PTR_ERR(trng->base);
 
 	trng->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(trng->clk))
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 43577ca780e3..8c3b255e629a 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/hw_random.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index a0f7724852eb..463382036a01 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -302,7 +301,6 @@ err_misc_dereg:
 
 int hwrng_register(struct hwrng *rng)
 {
-	int must_register_misc;
 	int err = -EINVAL;
 	struct hwrng *old_rng, *tmp;
 
@@ -327,7 +325,6 @@ int hwrng_register(struct hwrng *rng)
 			goto out_unlock;
 	}
 
-	must_register_misc = (current_rng == NULL);
 	old_rng = current_rng;
 	if (!old_rng) {
 		err = hwrng_init(rng);
@@ -336,13 +333,11 @@ int hwrng_register(struct hwrng *rng)
 		current_rng = rng;
 	}
 	err = 0;
-	if (must_register_misc) {
+	if (!old_rng) {
 		err = register_miscdev();
 		if (err) {
-			if (!old_rng) {
-				hwrng_cleanup(rng);
-				current_rng = NULL;
-			}
+			hwrng_cleanup(rng);
+			current_rng = NULL;
 			goto out_unlock;
 		}
 	}
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index 402ccfb625c5..9f8277cc44b4 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -22,7 +22,6 @@
 #include <linux/hw_random.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index f9beed54d0c8..432232eefe05 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -7,7 +7,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/preempt.h>
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
index 232b87fb5fc9..00e9d2d46634 100644
--- a/drivers/char/hw_random/nomadik-rng.c
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -10,7 +10,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/hw_random.h>
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index f2885dbe1849..b5cc3420c659 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/hw_random.h>
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
index 3d4c2293c6f5..c03beeeb1aea 100644
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -104,22 +104,9 @@ static int picoxcell_trng_probe(struct platform_device *pdev)
 	int ret;
 	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	if (!mem) {
-		dev_warn(&pdev->dev, "no memory resource\n");
-		return -ENOMEM;
-	}
-
-	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
-				     "picoxcell_trng")) {
-		dev_warn(&pdev->dev, "unable to request io mem\n");
-		return -EBUSY;
-	}
-
-	rng_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
-	if (!rng_base) {
-		dev_warn(&pdev->dev, "unable to remap io mem\n");
-		return -ENOMEM;
-	}
+	rng_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(rng_base))
+		return PTR_ERR(rng_base);
 
 	rng_clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(rng_clk)) {
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 03f41896d090..b7efd3c1a882 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -61,7 +61,6 @@
 #include <linux/ipmi_smi.h>
 #include <asm/io.h>
 #include "ipmi_si_sm.h"
-#include <linux/init.h>
 #include <linux/dmi.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 92c5937f80c3..917403fe10da 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -99,6 +99,9 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 	ssize_t read, sz;
 	char *ptr;
 
+	if (p != *ppos)
+		return 0;
+
 	if (!valid_phys_addr_range(p, count))
 		return -EFAULT;
 	read = 0;
@@ -157,6 +160,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
 	unsigned long copied;
 	void *ptr;
 
+	if (p != *ppos)
+		return -EFBIG;
+
 	if (!valid_phys_addr_range(p, count))
 		return -EFAULT;
 
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index 881c9e595939..28740046bc83 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -50,7 +50,6 @@
 #include <linux/unistd.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/sched.h>	/* cond_resched() */
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 429b75bb60e8..d07575c99a5f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -295,17 +295,17 @@
  * The minimum number of bits of entropy before we wake up a read on
  * /dev/random.  Should be enough to do a significant reseed.
  */
-static int random_read_wakeup_thresh = 64;
+static int random_read_wakeup_bits = 64;
 
 /*
  * If the entropy count falls under this number of bits, then we
  * should wake up processes which are selecting or polling on write
  * access to /dev/random.
  */
-static int random_write_wakeup_thresh = 28 * OUTPUT_POOL_WORDS;
+static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
 
 /*
- * The minimum number of seconds between urandom pool resending.  We
+ * The minimum number of seconds between urandom pool reseeding.  We
  * do this to limit the amount of entropy that can be drained from the
  * input pool even if there are heavy demands on /dev/urandom.
  */
@@ -322,7 +322,7 @@ static int random_min_urandom_seed = 60;
  * Register.  (See M. Matsumoto & Y. Kurita, 1992.  Twisted GFSR
  * generators.  ACM Transactions on Modeling and Computer Simulation
  * 2(3):179-194.  Also see M. Matsumoto & Y. Kurita, 1994.  Twisted
- * GFSR generators II.  ACM Transactions on Mdeling and Computer
+ * GFSR generators II.  ACM Transactions on Modeling and Computer
  * Simulation 4:254-266)
  *
  * Thanks to Colin Plumb for suggesting this.
@@ -666,10 +666,10 @@ retry:
 				  r->entropy_total, _RET_IP_);
 
 	if (r == &input_pool) {
-		int entropy_bytes = entropy_count >> ENTROPY_SHIFT;
+		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
 
 		/* should we wake readers? */
-		if (entropy_bytes >= random_read_wakeup_thresh) {
+		if (entropy_bits >= random_read_wakeup_bits) {
 			wake_up_interruptible(&random_read_wait);
 			kill_fasync(&fasync, SIGIO, POLL_IN);
 		}
@@ -678,9 +678,9 @@ retry:
 		 * forth between them, until the output pools are 75%
 		 * full.
 		 */
-		if (entropy_bytes > random_write_wakeup_thresh &&
+		if (entropy_bits > random_write_wakeup_bits &&
 		    r->initialized &&
-		    r->entropy_total >= 2*random_read_wakeup_thresh) {
+		    r->entropy_total >= 2*random_read_wakeup_bits) {
 			static struct entropy_store *last = &blocking_pool;
 			struct entropy_store *other = &blocking_pool;
 
@@ -924,19 +924,19 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
 	__u32	tmp[OUTPUT_POOL_WORDS];
 
-	/* For /dev/random's pool, always leave two wakeup worth's BITS */
-	int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
+	/* For /dev/random's pool, always leave two wakeups' worth */
+	int rsvd_bytes = r->limit ? 0 : random_read_wakeup_bits / 4;
 	int bytes = nbytes;
 
-	/* pull at least as many as BYTES as wakeup BITS */
-	bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+	/* pull at least as much as a wakeup */
+	bytes = max_t(int, bytes, random_read_wakeup_bits / 8);
 	/* but never more than the buffer size */
 	bytes = min_t(int, bytes, sizeof(tmp));
 
 	trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
 				  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
 	bytes = extract_entropy(r->pull, tmp, bytes,
-				random_read_wakeup_thresh / 8, rsvd);
+				random_read_wakeup_bits / 8, rsvd_bytes);
 	mix_pool_bytes(r, tmp, bytes, NULL);
 	credit_entropy_bits(r, bytes*8);
 }
@@ -952,35 +952,22 @@ static void push_to_pool(struct work_struct *work)
 	struct entropy_store *r = container_of(work, struct entropy_store,
 					      push_work);
 	BUG_ON(!r);
-	_xfer_secondary_pool(r, random_read_wakeup_thresh/8);
+	_xfer_secondary_pool(r, random_read_wakeup_bits/8);
 	trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
 			   r->pull->entropy_count >> ENTROPY_SHIFT);
 }
 
 /*
- * These functions extracts randomness from the "entropy pool", and
- * returns it in a buffer.
- *
- * The min parameter specifies the minimum amount we can pull before
- * failing to avoid races that defeat catastrophic reseeding while the
- * reserved parameter indicates how much entropy we must leave in the
- * pool after each pull to avoid starving other readers.
- *
- * Note: extract_entropy() assumes that .poolwords is a multiple of 16 words.
+ * This function decides how many bytes to actually take from the
+ * given pool, and also debits the entropy count accordingly.
  */
-
 static size_t account(struct entropy_store *r, size_t nbytes, int min,
 		      int reserved)
 {
-	unsigned long flags;
-	int wakeup_write = 0;
 	int have_bytes;
 	int entropy_count, orig;
 	size_t ibytes;
 
-	/* Hold lock while accounting */
-	spin_lock_irqsave(&r->lock, flags);
-
 	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
 
 	/* Can we pull enough? */
@@ -988,29 +975,19 @@ retry:
 	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
 	have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
 	ibytes = nbytes;
-	if (have_bytes < min + reserved) {
+	/* If limited, never pull more than available */
+	if (r->limit)
+		ibytes = min_t(size_t, ibytes, have_bytes - reserved);
+	if (ibytes < min)
 		ibytes = 0;
-	} else {
-		/* If limited, never pull more than available */
-		if (r->limit && ibytes + reserved >= have_bytes)
-			ibytes = have_bytes - reserved;
-
-		if (have_bytes >= ibytes + reserved)
-			entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
-		else
-			entropy_count = reserved << (ENTROPY_SHIFT + 3);
-
-		if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
-			goto retry;
-
-		if ((r->entropy_count >> ENTROPY_SHIFT)
-		    < random_write_wakeup_thresh)
-			wakeup_write = 1;
-	}
-	spin_unlock_irqrestore(&r->lock, flags);
+	entropy_count = max_t(int, 0,
+			      entropy_count - (ibytes << (ENTROPY_SHIFT + 3)));
+	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+		goto retry;
 
 	trace_debit_entropy(r->name, 8 * ibytes);
-	if (wakeup_write) {
+	if (ibytes &&
+	    (r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
 		wake_up_interruptible(&random_write_wait);
 		kill_fasync(&fasync, SIGIO, POLL_OUT);
 	}
@@ -1018,6 +995,12 @@ retry:
 	return ibytes;
 }
 
+/*
+ * This function does the actual extraction for extract_entropy and
+ * extract_entropy_user.
+ *
+ * Note: we assume that .poolwords is a multiple of 16 words.
+ */
 static void extract_buf(struct entropy_store *r, __u8 *out)
 {
 	int i;
@@ -1029,23 +1012,23 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 	__u8 extract[64];
 	unsigned long flags;
 
-	/* Generate a hash across the pool, 16 words (512 bits) at a time */
-	sha_init(hash.w);
-	spin_lock_irqsave(&r->lock, flags);
-	for (i = 0; i < r->poolinfo->poolwords; i += 16)
-		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
-
 	/*
-	 * If we have a architectural hardware random number
-	 * generator, mix that in, too.
+	 * If we have an architectural hardware random number
+	 * generator, use it for SHA's initial vector
 	 */
+	sha_init(hash.w);
 	for (i = 0; i < LONGS(20); i++) {
 		unsigned long v;
 		if (!arch_get_random_long(&v))
 			break;
-		hash.l[i] ^= v;
+		hash.l[i] = v;
 	}
 
+	/* Generate a hash across the pool, 16 words (512 bits) at a time */
+	spin_lock_irqsave(&r->lock, flags);
+	for (i = 0; i < r->poolinfo->poolwords; i += 16)
+		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
+
 	/*
 	 * We mix the hash back into the pool to prevent backtracking
 	 * attacks (where the attacker knows the state of the pool
@@ -1079,6 +1062,15 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 	memset(&hash, 0, sizeof(hash));
 }
 
+/*
+ * This function extracts randomness from the "entropy pool", and
+ * returns it in a buffer.
+ *
+ * The min parameter specifies the minimum amount we can pull before
+ * failing to avoid races that defeat catastrophic reseeding while the
+ * reserved parameter indicates how much entropy we must leave in the
+ * pool after each pull to avoid starving other readers.
+ */
 static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 				 size_t nbytes, int min, int reserved)
 {
@@ -1129,6 +1121,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 	return ret;
 }
 
+/*
+ * This function extracts randomness from the "entropy pool", and
+ * returns it in a userspace buffer.
+ */
 static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
 				    size_t nbytes)
 {
@@ -1170,8 +1166,9 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
 /*
  * This function is the exported kernel interface.  It returns some
  * number of good random numbers, suitable for key generation, seeding
- * TCP sequence numbers, etc.  It does not use the hw random number
- * generator, if available; use get_random_bytes_arch() for that.
+ * TCP sequence numbers, etc.  It does not rely on the hardware random
+ * number generator.  For random bytes direct from the hardware RNG
+ * (when available), use get_random_bytes_arch().
  */
 void get_random_bytes(void *buf, int nbytes)
 {
@@ -1284,53 +1281,32 @@ void rand_initialize_disk(struct gendisk *disk)
 static ssize_t
 random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	ssize_t n, retval = 0, count = 0;
+	ssize_t n;
 
 	if (nbytes == 0)
 		return 0;
 
-	while (nbytes > 0) {
-		n = nbytes;
-		if (n > SEC_XFER_SIZE)
-			n = SEC_XFER_SIZE;
-
-		n = extract_entropy_user(&blocking_pool, buf, n);
-
-		if (n < 0) {
-			retval = n;
-			break;
-		}
-
+	nbytes = min_t(size_t, nbytes, SEC_XFER_SIZE);
+	while (1) {
+		n = extract_entropy_user(&blocking_pool, buf, nbytes);
+		if (n < 0)
+			return n;
 		trace_random_read(n*8, (nbytes-n)*8,
 				  ENTROPY_BITS(&blocking_pool),
 				  ENTROPY_BITS(&input_pool));
-
-		if (n == 0) {
-			if (file->f_flags & O_NONBLOCK) {
-				retval = -EAGAIN;
-				break;
-			}
-
-			wait_event_interruptible(random_read_wait,
-				ENTROPY_BITS(&input_pool) >=
-				random_read_wakeup_thresh);
-
-			if (signal_pending(current)) {
-				retval = -ERESTARTSYS;
-				break;
-			}
-
-			continue;
-		}
-
-		count += n;
-		buf += n;
-		nbytes -= n;
-		break;		/* This break makes the device work */
-				/* like a named pipe */
+		if (n > 0)
+			return n;
+		/* Pool is (near) empty.  Maybe wait and retry. */
+
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		wait_event_interruptible(random_read_wait,
+			ENTROPY_BITS(&input_pool) >=
+			random_read_wakeup_bits);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
 	}
-
-	return (count ? count : retval);
 }
 
 static ssize_t
@@ -1358,9 +1334,9 @@ random_poll(struct file *file, poll_table * wait)
 	poll_wait(file, &random_read_wait, wait);
 	poll_wait(file, &random_write_wait, wait);
 	mask = 0;
-	if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_thresh)
+	if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
 		mask |= POLLIN | POLLRDNORM;
-	if (ENTROPY_BITS(&input_pool) < random_write_wakeup_thresh)
+	if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
 		mask |= POLLOUT | POLLWRNORM;
 	return mask;
 }
@@ -1507,18 +1483,18 @@ EXPORT_SYMBOL(generate_random_uuid);
 #include <linux/sysctl.h>
 
 static int min_read_thresh = 8, min_write_thresh;
-static int max_read_thresh = INPUT_POOL_WORDS * 32;
+static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
 static int max_write_thresh = INPUT_POOL_WORDS * 32;
 static char sysctl_bootid[16];
 
 /*
- * These functions is used to return both the bootid UUID, and random
+ * This function is used to return both the bootid UUID, and random
  * UUID.  The difference is in whether table->data is NULL; if it is,
  * then a new UUID is generated and returned to the user.
  *
- * If the user accesses this via the proc interface, it will be returned
- * as an ASCII string in the standard UUID format.  If accesses via the
- * sysctl system call, it is returned as 16 bytes of binary data.
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
  */
 static int proc_do_uuid(struct ctl_table *table, int write,
 			void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -1583,7 +1559,7 @@ struct ctl_table random_table[] = {
 	},
 	{
 		.procname	= "read_wakeup_threshold",
-		.data		= &random_read_wakeup_thresh,
+		.data		= &random_read_wakeup_bits,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_minmax,
@@ -1592,7 +1568,7 @@ struct ctl_table random_table[] = {
 	},
 	{
 		.procname	= "write_wakeup_threshold",
-		.data		= &random_write_wakeup_thresh,
+		.data		= &random_write_wakeup_bits,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_minmax,
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 0e506bad1986..bd377472dcfb 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
 #include <linux/kernel.h>	/* printk() */
 #include <linux/slab.h>		/* kmalloc() */
 #include <linux/fs.h>		/* everything... */
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 1a65838888cd..c54cac3f8bc8 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -74,7 +74,7 @@ config TCG_NSC
 
 config TCG_ATMEL
 	tristate "Atmel TPM Interface"
-	depends on PPC64 || HAS_IOPORT
+	depends on PPC64 || HAS_IOPORT_MAP
 	---help---
 	  If you have a TPM security chip from Atmel say Yes and it 
 	  will be accessible from within Linux.  To compile this driver 
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 52b9b2b2f300..472af4bb1b61 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -21,7 +21,6 @@
  *
  *
  */
-#include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/wait.h>
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
index 5b0dd8ef74c0..3b7bf2162898 100644
--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
+++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
@@ -38,7 +38,6 @@
 #include <linux/miscdevice.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index bd313f7816a8..c1af80bcdf20 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -242,7 +242,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 
 	irq = irq_of_parse_and_map(np, 0);
 	if (!irq)
-		return;
+		goto out_free_characteristics;
 
 	clk = at91_clk_register_master(pmc, irq, name, num_parents,
 				       parent_names, layout,
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 8137327847c3..1127ee46b802 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -17,23 +17,75 @@
 #include <linux/module.h>
 #include <linux/err.h>
 
-#define AXI_CLKGEN_REG_UPDATE_ENABLE	0x04
-#define AXI_CLKGEN_REG_CLK_OUT1		0x08
-#define AXI_CLKGEN_REG_CLK_OUT2		0x0c
-#define AXI_CLKGEN_REG_CLK_DIV		0x10
-#define AXI_CLKGEN_REG_CLK_FB1		0x14
-#define AXI_CLKGEN_REG_CLK_FB2		0x18
-#define AXI_CLKGEN_REG_LOCK1		0x1c
-#define AXI_CLKGEN_REG_LOCK2		0x20
-#define AXI_CLKGEN_REG_LOCK3		0x24
-#define AXI_CLKGEN_REG_FILTER1		0x28
-#define AXI_CLKGEN_REG_FILTER2		0x2c
+#define AXI_CLKGEN_V1_REG_UPDATE_ENABLE	0x04
+#define AXI_CLKGEN_V1_REG_CLK_OUT1	0x08
+#define AXI_CLKGEN_V1_REG_CLK_OUT2	0x0c
+#define AXI_CLKGEN_V1_REG_CLK_DIV	0x10
+#define AXI_CLKGEN_V1_REG_CLK_FB1	0x14
+#define AXI_CLKGEN_V1_REG_CLK_FB2	0x18
+#define AXI_CLKGEN_V1_REG_LOCK1		0x1c
+#define AXI_CLKGEN_V1_REG_LOCK2		0x20
+#define AXI_CLKGEN_V1_REG_LOCK3		0x24
+#define AXI_CLKGEN_V1_REG_FILTER1	0x28
+#define AXI_CLKGEN_V1_REG_FILTER2	0x2c
+
+#define AXI_CLKGEN_V2_REG_RESET		0x40
+#define AXI_CLKGEN_V2_REG_DRP_CNTRL	0x70
+#define AXI_CLKGEN_V2_REG_DRP_STATUS	0x74
+
+#define AXI_CLKGEN_V2_RESET_MMCM_ENABLE	BIT(1)
+#define AXI_CLKGEN_V2_RESET_ENABLE	BIT(0)
+
+#define AXI_CLKGEN_V2_DRP_CNTRL_SEL	BIT(29)
+#define AXI_CLKGEN_V2_DRP_CNTRL_READ	BIT(28)
+
+#define AXI_CLKGEN_V2_DRP_STATUS_BUSY	BIT(16)
+
+#define MMCM_REG_CLKOUT0_1	0x08
+#define MMCM_REG_CLKOUT0_2	0x09
+#define MMCM_REG_CLK_FB1	0x14
+#define MMCM_REG_CLK_FB2	0x15
+#define MMCM_REG_CLK_DIV	0x16
+#define MMCM_REG_LOCK1		0x18
+#define MMCM_REG_LOCK2		0x19
+#define MMCM_REG_LOCK3		0x1a
+#define MMCM_REG_FILTER1	0x4e
+#define MMCM_REG_FILTER2	0x4f
+
+struct axi_clkgen;
+
+struct axi_clkgen_mmcm_ops {
+	void (*enable)(struct axi_clkgen *axi_clkgen, bool enable);
+	int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg,
+		     unsigned int val, unsigned int mask);
+	int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg,
+		    unsigned int *val);
+};
 
 struct axi_clkgen {
 	void __iomem *base;
+	const struct axi_clkgen_mmcm_ops *mmcm_ops;
 	struct clk_hw clk_hw;
 };
 
+static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen,
+	bool enable)
+{
+	axi_clkgen->mmcm_ops->enable(axi_clkgen, enable);
+}
+
+static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int val, unsigned int mask)
+{
+	return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask);
+}
+
+static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int *val)
+{
+	return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val);
+}
+
 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
 {
 	switch (m) {
@@ -156,6 +208,148 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
 	*val = readl(axi_clkgen->base + reg);
 }
 
+static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg)
+{
+	switch (reg) {
+	case MMCM_REG_CLKOUT0_1:
+		return AXI_CLKGEN_V1_REG_CLK_OUT1;
+	case MMCM_REG_CLKOUT0_2:
+		return AXI_CLKGEN_V1_REG_CLK_OUT2;
+	case MMCM_REG_CLK_FB1:
+		return AXI_CLKGEN_V1_REG_CLK_FB1;
+	case MMCM_REG_CLK_FB2:
+		return AXI_CLKGEN_V1_REG_CLK_FB2;
+	case MMCM_REG_CLK_DIV:
+		return AXI_CLKGEN_V1_REG_CLK_DIV;
+	case MMCM_REG_LOCK1:
+		return AXI_CLKGEN_V1_REG_LOCK1;
+	case MMCM_REG_LOCK2:
+		return AXI_CLKGEN_V1_REG_LOCK2;
+	case MMCM_REG_LOCK3:
+		return AXI_CLKGEN_V1_REG_LOCK3;
+	case MMCM_REG_FILTER1:
+		return AXI_CLKGEN_V1_REG_FILTER1;
+	case MMCM_REG_FILTER2:
+		return AXI_CLKGEN_V1_REG_FILTER2;
+	default:
+		return 0;
+	}
+}
+
+static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int val, unsigned int mask)
+{
+	reg = axi_clkgen_v1_map_mmcm_reg(reg);
+	if (reg == 0)
+		return -EINVAL;
+
+	axi_clkgen_write(axi_clkgen, reg, val);
+
+	return 0;
+}
+
+static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int *val)
+{
+	reg = axi_clkgen_v1_map_mmcm_reg(reg);
+	if (reg == 0)
+		return -EINVAL;
+
+	axi_clkgen_read(axi_clkgen, reg, val);
+
+	return 0;
+}
+
+static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen,
+	bool enable)
+{
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable);
+}
+
+static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = {
+	.write = axi_clkgen_v1_mmcm_write,
+	.read = axi_clkgen_v1_mmcm_read,
+	.enable = axi_clkgen_v1_mmcm_enable,
+};
+
+static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
+{
+	unsigned int timeout = 10000;
+	unsigned int val;
+
+	do {
+		axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val);
+	} while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout);
+
+	if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY)
+		return -EIO;
+
+	return val & 0xffff;
+}
+
+static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int *val)
+{
+	unsigned int reg_val;
+	int ret;
+
+	ret = axi_clkgen_wait_non_busy(axi_clkgen);
+	if (ret < 0)
+		return ret;
+
+	reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ;
+	reg_val |= (reg << 16);
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
+
+	ret = axi_clkgen_wait_non_busy(axi_clkgen);
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+
+	return 0;
+}
+
+static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int val, unsigned int mask)
+{
+	unsigned int reg_val = 0;
+	int ret;
+
+	ret = axi_clkgen_wait_non_busy(axi_clkgen);
+	if (ret < 0)
+		return ret;
+
+	if (mask != 0xffff) {
+		axi_clkgen_v2_mmcm_read(axi_clkgen, reg, &reg_val);
+		reg_val &= ~mask;
+	}
+
+	reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask);
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
+
+	return 0;
+}
+
+static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen,
+	bool enable)
+{
+	unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE;
+
+	if (enable)
+		val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE;
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val);
+}
+
+static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = {
+	.write = axi_clkgen_v2_mmcm_write,
+	.read = axi_clkgen_v2_mmcm_read,
+	.enable = axi_clkgen_v2_mmcm_enable,
+};
+
 static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
 {
 	return container_of(clk_hw, struct axi_clkgen, clk_hw);
@@ -184,33 +378,29 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
 	filter = axi_clkgen_lookup_filter(m - 1);
 	lock = axi_clkgen_lookup_lock(m - 1);
 
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0);
-
 	axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1,
-		(high << 6) | low);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2,
-		(edge << 7) | (nocount << 6));
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1,
+		(high << 6) | low, 0xefff);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2,
+		(edge << 7) | (nocount << 6), 0x03ff);
 
 	axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV,
-		(edge << 13) | (nocount << 12) | (high << 6) | low);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
+		(edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff);
 
 	axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1,
-		(high << 6) | low);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2,
-		(edge << 7) | (nocount << 6));
-
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2,
-		(((lock >> 16) & 0x1f) << 10) | 0x1);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3,
-		(((lock >> 24) & 0x1f) << 10) | 0x3e9);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16);
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter);
-
-	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1,
+		(high << 6) | low, 0xefff);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2,
+		(edge << 7) | (nocount << 6), 0x03ff);
+
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
+		(((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3,
+		(((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900);
+	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900);
 
 	return 0;
 }
@@ -236,11 +426,11 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	unsigned int reg;
 	unsigned long long tmp;
 
-	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, &reg);
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
 	dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, &reg);
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
 	d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
-	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, &reg);
+	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
 	m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
 
 	if (d == 0 || dout == 0)
@@ -255,14 +445,45 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
 	return tmp;
 }
 
+static int axi_clkgen_enable(struct clk_hw *clk_hw)
+{
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+
+	axi_clkgen_mmcm_enable(axi_clkgen, true);
+
+	return 0;
+}
+
+static void axi_clkgen_disable(struct clk_hw *clk_hw)
+{
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+
+	axi_clkgen_mmcm_enable(axi_clkgen, false);
+}
+
 static const struct clk_ops axi_clkgen_ops = {
 	.recalc_rate = axi_clkgen_recalc_rate,
 	.round_rate = axi_clkgen_round_rate,
 	.set_rate = axi_clkgen_set_rate,
+	.enable = axi_clkgen_enable,
+	.disable = axi_clkgen_disable,
 };
 
+static const struct of_device_id axi_clkgen_ids[] = {
+	{
+		.compatible = "adi,axi-clkgen-1.00.a",
+		.data = &axi_clkgen_v1_mmcm_ops
+	}, {
+		.compatible = "adi,axi-clkgen-2.00.a",
+		.data = &axi_clkgen_v2_mmcm_ops,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
+
 static int axi_clkgen_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *id;
 	struct axi_clkgen *axi_clkgen;
 	struct clk_init_data init;
 	const char *parent_name;
@@ -270,10 +491,19 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 	struct resource *mem;
 	struct clk *clk;
 
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	id = of_match_node(axi_clkgen_ids, pdev->dev.of_node);
+	if (!id)
+		return -ENODEV;
+
 	axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
 	if (!axi_clkgen)
 		return -ENOMEM;
 
+	axi_clkgen->mmcm_ops = id->data;
+
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(axi_clkgen->base))
@@ -289,10 +519,12 @@ static int axi_clkgen_probe(struct platform_device *pdev)
 
 	init.name = clk_name;
 	init.ops = &axi_clkgen_ops;
-	init.flags = 0;
+	init.flags = CLK_SET_RATE_GATE;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
 
+	axi_clkgen_mmcm_enable(axi_clkgen, false);
+
 	axi_clkgen->clk_hw.init = &init;
 	clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw);
 	if (IS_ERR(clk))
@@ -309,12 +541,6 @@ static int axi_clkgen_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id axi_clkgen_ids[] = {
-	{ .compatible = "adi,axi-clkgen-1.00.a" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
-
 static struct platform_driver axi_clkgen_driver = {
 	.driver = {
 		.name = "adi-axi-clkgen",
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 5543b7df8e16..ec22112e569f 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -24,7 +24,7 @@
  * Traits of this clock:
  * prepare - clk_prepare only ensures that parents are prepared
  * enable - clk_enable only ensures that parents are enabled
- * rate - rate is adjustable.  clk->rate = parent->rate / divisor
+ * rate - rate is adjustable.  clk->rate = DIV_ROUND_UP(parent->rate / divisor)
  * parent - fixed parent.  No clk_set_parent support
  */
 
@@ -115,7 +115,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 		return parent_rate;
 	}
 
-	return parent_rate / div;
+	return DIV_ROUND_UP(parent_rate, div);
 }
 
 /*
@@ -185,7 +185,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 		}
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
 				MULT_ROUND_UP(rate, i));
-		now = parent_rate / i;
+		now = DIV_ROUND_UP(parent_rate, i);
 		if (now <= rate && now > best) {
 			bestdiv = i;
 			best = now;
@@ -207,7 +207,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 	int div;
 	div = clk_divider_bestdiv(hw, rate, prate);
 
-	return *prate / div;
+	return DIV_ROUND_UP(*prate, div);
 }
 
 static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -218,7 +218,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags = 0;
 	u32 val;
 
-	div = parent_rate / rate;
+	div = DIV_ROUND_UP(parent_rate, rate);
 	value = _get_val(divider, div);
 
 	if (value > div_mask(divider))
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
index 6a934a5296bd..05e04ce0f148 100644
--- a/drivers/clk/clk-nomadik.c
+++ b/drivers/clk/clk-nomadik.c
@@ -494,6 +494,9 @@ static const struct file_operations nomadik_src_clk_debugfs_ops = {
 
 static int __init nomadik_src_clk_init_debugfs(void)
 {
+	/* Vital for multiplatform */
+	if (!src_base)
+		return -ENODEV;
 	src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
 	src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
 	debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5517944495d8..895b3d204e22 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1339,8 +1339,11 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
 	if (clk->notifier_count)
 		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
 
-	if (ret & NOTIFY_STOP_MASK)
+	if (ret & NOTIFY_STOP_MASK) {
+		pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n",
+				__func__, clk->name, ret);
 		goto out;
+	}
 
 	hlist_for_each_entry(child, &clk->children, child_node) {
 		ret = __clk_speculate_rates(child, new_rate);
@@ -2226,24 +2229,25 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
  */
 int __clk_get(struct clk *clk)
 {
-	if (clk && !try_module_get(clk->owner))
-		return 0;
+	if (clk) {
+		if (!try_module_get(clk->owner))
+			return 0;
 
-	kref_get(&clk->ref);
+		kref_get(&clk->ref);
+	}
 	return 1;
 }
 
 void __clk_put(struct clk *clk)
 {
-	if (WARN_ON_ONCE(IS_ERR(clk)))
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
 		return;
 
 	clk_prepare_lock();
 	kref_put(&clk->ref, __clk_release);
 	clk_prepare_unlock();
 
-	if (clk)
-		module_put(clk->owner);
+	module_put(clk->owner);
 }
 
 /***        clk rate change notifiers        ***/
@@ -2259,20 +2263,11 @@ void __clk_put(struct clk *clk)
  * re-enter into the clk framework by calling any top-level clk APIs;
  * this will cause a nested prepare_lock mutex.
  *
- * Pre-change notifier callbacks will be passed the current, pre-change
- * rate of the clk via struct clk_notifier_data.old_rate.  The new,
- * post-change rate of the clk is passed via struct
+ * In all notification cases cases (pre, post and abort rate change) the
+ * original clock rate is passed to the callback via struct
+ * clk_notifier_data.old_rate and the new frequency is passed via struct
  * clk_notifier_data.new_rate.
  *
- * Post-change notifiers will pass the now-current, post-change rate of
- * the clk in both struct clk_notifier_data.old_rate and struct
- * clk_notifier_data.new_rate.
- *
- * Abort-change notifiers are effectively the opposite of pre-change
- * notifiers: the original pre-change clk rate is passed in via struct
- * clk_notifier_data.new_rate and the failed post-change rate is passed
- * in via struct clk_notifier_data.old_rate.
- *
  * clk_notifier_register() must be called from non-atomic context.
  * Returns -EINVAL if called with null arguments, -ENOMEM upon
  * allocation failure; otherwise, passes along the return value of
@@ -2472,7 +2467,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider);
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
 	struct of_clk_provider *provider;
-	struct clk *clk = ERR_PTR(-ENOENT);
+	struct clk *clk = ERR_PTR(-EPROBE_DEFER);
 
 	/* Check if we have such a provider in our array */
 	list_for_each_entry(provider, &of_clk_providers, link) {
@@ -2505,8 +2500,12 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_count);
 const char *of_clk_get_parent_name(struct device_node *np, int index)
 {
 	struct of_phandle_args clkspec;
+	struct property *prop;
 	const char *clk_name;
+	const __be32 *vp;
+	u32 pv;
 	int rc;
+	int count;
 
 	if (index < 0)
 		return NULL;
@@ -2516,8 +2515,22 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
 	if (rc)
 		return NULL;
 
+	index = clkspec.args_count ? clkspec.args[0] : 0;
+	count = 0;
+
+	/* if there is an indices property, use it to transfer the index
+	 * specified into an array offset for the clock-output-names property.
+	 */
+	of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) {
+		if (index == pv) {
+			index = count;
+			break;
+		}
+		count++;
+	}
+
 	if (of_property_read_string_index(clkspec.np, "clock-output-names",
-					  clkspec.args_count ? clkspec.args[0] : 0,
+					  index,
 					  &clk_name) < 0)
 		clk_name = clkspec.np->name;
 
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 48f67218247c..a360b2eca5cb 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -167,6 +167,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 		clk = of_clk_get_by_name(dev->of_node, con_id);
 		if (!IS_ERR(clk))
 			return clk;
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return clk;
 	}
 
 	return clk_get_sys(dev_id, con_id);
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..38faa469d288 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np)
 				   base);
 }
 CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	u32			clken_reg;
+	u32			clken_bit;
+	u32			div_reg;
+	u32			div_off;
+	u32			div_bits;
+	u32			drv_reg;
+	u32			drv_off;
+	u32			drv_bits;
+	u32			sam_reg;
+	u32			sam_off;
+	u32			sam_bits;
+};
+
+struct clk_mmc {
+	struct clk_hw	hw;
+	u32		id;
+	void __iomem	*clken_reg;
+	u32		clken_bit;
+	void __iomem	*div_reg;
+	u32		div_off;
+	u32		div_bits;
+	void __iomem	*drv_reg;
+	u32		drv_off;
+	u32		drv_bits;
+	void __iomem	*sam_reg;
+	u32		sam_off;
+	u32		sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+	{ HI3620_SD_CIUCLK,	"sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+	{ HI3620_MMC_CIUCLK1,   "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+	{ HI3620_MMC_CIUCLK2,   "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+	{ HI3620_MMC_CIUCLK3,   "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+		       unsigned long parent_rate)
+{
+	switch (parent_rate) {
+	case 26000000:
+		return 13000000;
+	case 180000000:
+		return 25000000;
+	case 360000000:
+		return 50000000;
+	case 720000000:
+		return 100000000;
+	case 1440000000:
+		return 180000000;
+	default:
+		return parent_rate;
+	}
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *best_parent_rate,
+			      struct clk **best_parent_p)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long best = 0;
+
+	if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+		rate = 13000000;
+		best = 26000000;
+	} else if (rate <= 26000000) {
+		rate = 25000000;
+		best = 180000000;
+	} else if (rate <= 52000000) {
+		rate = 50000000;
+		best = 360000000;
+	} else if (rate <= 100000000) {
+		rate = 100000000;
+		best = 720000000;
+	} else {
+		/* max is 180M */
+		rate = 180000000;
+		best = 1440000000;
+	}
+	*best_parent_rate = best;
+	return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+	u32 i;
+
+	if (para >= 0) {
+		for (i = 0; i < len; i++) {
+			if (para % 2)
+				val |= 1 << (off + i);
+			else
+				val &= ~(1 << (off + i));
+			para = para >> 1;
+		}
+	}
+	return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long flags;
+	u32 sam, drv, div, val;
+	static DEFINE_SPINLOCK(mmc_clk_lock);
+
+	switch (rate) {
+	case 13000000:
+		sam = 3;
+		drv = 1;
+		div = 1;
+		break;
+	case 25000000:
+		sam = 13;
+		drv = 6;
+		div = 6;
+		break;
+	case 50000000:
+		sam = 3;
+		drv = 6;
+		div = 6;
+		break;
+	case 100000000:
+		sam = 6;
+		drv = 4;
+		div = 6;
+		break;
+	case 180000000:
+		sam = 6;
+		drv = 4;
+		div = 7;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&mmc_clk_lock, flags);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val &= ~(1 << mclk->clken_bit);
+	writel_relaxed(val, mclk->clken_reg);
+
+	val = readl_relaxed(mclk->sam_reg);
+	val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+	writel_relaxed(val, mclk->sam_reg);
+
+	val = readl_relaxed(mclk->drv_reg);
+	val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+	writel_relaxed(val, mclk->drv_reg);
+
+	val = readl_relaxed(mclk->div_reg);
+	val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+	writel_relaxed(val, mclk->div_reg);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val |= 1 << mclk->clken_bit;
+	writel_relaxed(val, mclk->clken_reg);
+
+	spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+	return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long rate;
+
+	if (mclk->id == HI3620_MMC_CIUCLK1)
+		rate = 13000000;
+	else
+		rate = 25000000;
+
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+	.prepare = mmc_clk_prepare,
+	.determine_rate = mmc_clk_determine_rate,
+	.set_rate = mmc_clk_set_rate,
+	.recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+			void __iomem *base, struct device_node *np)
+{
+	struct clk_mmc *mclk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+	if (!mclk) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = mmc_clk->name;
+	init.ops = &clk_mmc_ops;
+	init.flags = mmc_clk->flags | CLK_IS_BASIC;
+	init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+	init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+	mclk->hw.init = &init;
+
+	mclk->id = mmc_clk->id;
+	mclk->clken_reg = base + mmc_clk->clken_reg;
+	mclk->clken_bit = mmc_clk->clken_bit;
+	mclk->div_reg = base + mmc_clk->div_reg;
+	mclk->div_off = mmc_clk->div_off;
+	mclk->div_bits = mmc_clk->div_bits;
+	mclk->drv_reg = base + mmc_clk->drv_reg;
+	mclk->drv_off = mmc_clk->drv_off;
+	mclk->drv_bits = mmc_clk->drv_bits;
+	mclk->sam_reg = base + mmc_clk->sam_reg;
+	mclk->sam_off = mmc_clk->sam_off;
+	mclk->sam_bits = mmc_clk->sam_bits;
+
+	clk = clk_register(NULL, &mclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		kfree(mclk);
+	return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+	void __iomem *base;
+	int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+	struct clk_onecell_data *clk_data;
+
+	if (!node) {
+		pr_err("failed to find pctrl node in DTS\n");
+		return;
+	}
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("failed to map pctrl\n");
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (WARN_ON(!clk_data))
+		return;
+
+	clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+	if (!clk_data->clks) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num; i++) {
+		struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+		clk_data->clks[mmc_clk->id] =
+			hisi_register_clk_mmc(mmc_clk, base, node);
+	}
+
+	clk_data->clk_num = num;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
index 17a598398a53..86f1e362eafb 100644
--- a/drivers/clk/keystone/gate.c
+++ b/drivers/clk/keystone/gate.c
@@ -179,6 +179,7 @@ static struct clk *clk_register_psc(struct device *dev,
 
 	init.name = name;
 	init.ops = &clk_psc_ops;
+	init.flags = 0;
 	init.parent_names = (parent_name ? &parent_name : NULL);
 	init.num_parents = (parent_name ? 1 : 0);
 
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
index c339b829d3e3..693f7be129f1 100644
--- a/drivers/clk/mvebu/Kconfig
+++ b/drivers/clk/mvebu/Kconfig
@@ -13,6 +13,14 @@ config ARMADA_370_CLK
 	select MVEBU_CLK_CPU
 	select MVEBU_CLK_COREDIV
 
+config ARMADA_375_CLK
+	bool
+	select MVEBU_CLK_COMMON
+
+config ARMADA_38X_CLK
+	bool
+	select MVEBU_CLK_COMMON
+
 config ARMADA_XP_CLK
 	bool
 	select MVEBU_CLK_COMMON
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 21bbfb4a9f42..4c66162fb0b4 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -3,6 +3,8 @@ obj-$(CONFIG_MVEBU_CLK_CPU) 	+= clk-cpu.o
 obj-$(CONFIG_MVEBU_CLK_COREDIV)	+= clk-corediv.o
 
 obj-$(CONFIG_ARMADA_370_CLK)	+= armada-370.o
+obj-$(CONFIG_ARMADA_375_CLK)	+= armada-375.o
+obj-$(CONFIG_ARMADA_38X_CLK)	+= armada-38x.o
 obj-$(CONFIG_ARMADA_XP_CLK)	+= armada-xp.o
 obj-$(CONFIG_DOVE_CLK)		+= dove.o
 obj-$(CONFIG_KIRKWOOD_CLK)	+= kirkwood.o
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index 81a202d12a7a..bef198a83863 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -141,13 +141,6 @@ static const struct coreclk_soc_desc a370_coreclks = {
 	.num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
 };
 
-static void __init a370_coreclk_init(struct device_node *np)
-{
-	mvebu_coreclk_setup(np, &a370_coreclks);
-}
-CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock",
-	       a370_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -168,9 +161,15 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
 	{ }
 };
 
-static void __init a370_clk_gating_init(struct device_node *np)
+static void __init a370_clk_init(struct device_node *np)
 {
-	mvebu_clk_gating_setup(np, a370_gating_desc);
+	struct device_node *cgnp =
+		of_find_compatible_node(NULL, NULL, "marvell,armada-370-gating-clock");
+
+	mvebu_coreclk_setup(np, &a370_coreclks);
+
+	if (cgnp)
+		mvebu_clk_gating_setup(cgnp, a370_gating_desc);
 }
-CLK_OF_DECLARE(a370_clk_gating, "marvell,armada-370-gating-clock",
-	       a370_clk_gating_init);
+CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init);
+
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c
new file mode 100644
index 000000000000..c991a4d95e10
--- /dev/null
+++ b/drivers/clk/mvebu/armada-375.c
@@ -0,0 +1,184 @@
+/*
+ * Marvell Armada 375 SoC clocks
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include "common.h"
+
+/*
+ * Core Clocks
+ */
+
+/*
+ * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are
+ * all modified at the same time, and not separately as for the Armada
+ * 370 or the Armada XP SoCs.
+ *
+ * SAR0[21:17]   : CPU frequency    DDR frequency   L2 frequency
+ *		 6   =  400 MHz	    400 MHz	    200 MHz
+ *		 15  =  600 MHz	    600 MHz	    300 MHz
+ *		 21  =  800 MHz	    534 MHz	    400 MHz
+ *		 25  = 1000 MHz	    500 MHz	    500 MHz
+ *		 others reserved.
+ *
+ * SAR0[22]   : TCLK frequency
+ *		 0 = 166 MHz
+ *		 1 = 200 MHz
+ */
+
+#define SAR1_A375_TCLK_FREQ_OPT		   22
+#define SAR1_A375_TCLK_FREQ_OPT_MASK	   0x1
+#define SAR1_A375_CPU_DDR_L2_FREQ_OPT	   17
+#define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
+
+static const u32 armada_375_tclk_frequencies[] __initconst = {
+	166000000,
+	200000000,
+};
+
+static u32 __init armada_375_get_tclk_freq(void __iomem *sar)
+{
+	u8 tclk_freq_select;
+
+	tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) &
+			    SAR1_A375_TCLK_FREQ_OPT_MASK);
+	return armada_375_tclk_frequencies[tclk_freq_select];
+}
+
+
+static const u32 armada_375_cpu_frequencies[] __initconst = {
+	0, 0, 0, 0, 0, 0,
+	400000000,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	600000000,
+	0, 0, 0, 0, 0,
+	800000000,
+	0, 0, 0,
+	1000000000,
+};
+
+static u32 __init armada_375_get_cpu_freq(void __iomem *sar)
+{
+	u8 cpu_freq_select;
+
+	cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
+			   SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
+	if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) {
+		pr_err("Selected CPU frequency (%d) unsupported\n",
+			cpu_freq_select);
+		return 0;
+	} else
+		return armada_375_cpu_frequencies[cpu_freq_select];
+}
+
+enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 };
+
+static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = {
+	{ .id = A375_CPU_TO_L2,	 .name = "l2clk" },
+	{ .id = A375_CPU_TO_DDR, .name = "ddrclk" },
+};
+
+static const int armada_375_cpu_l2_ratios[32][2] __initconst = {
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {1, 2}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {1, 2},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {1, 2}, {0, 1}, {0, 1},
+	{0, 1}, {1, 2}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int armada_375_cpu_ddr_ratios[32][2] __initconst = {
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {1, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {2, 3},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {2, 3}, {0, 1}, {0, 1},
+	{0, 1}, {1, 2}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static void __init armada_375_get_clk_ratio(
+	void __iomem *sar, int id, int *mult, int *div)
+{
+	u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
+		SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
+
+	switch (id) {
+	case A375_CPU_TO_L2:
+		*mult = armada_375_cpu_l2_ratios[opt][0];
+		*div = armada_375_cpu_l2_ratios[opt][1];
+		break;
+	case A375_CPU_TO_DDR:
+		*mult = armada_375_cpu_ddr_ratios[opt][0];
+		*div = armada_375_cpu_ddr_ratios[opt][1];
+		break;
+	}
+}
+
+static const struct coreclk_soc_desc armada_375_coreclks = {
+	.get_tclk_freq = armada_375_get_tclk_freq,
+	.get_cpu_freq = armada_375_get_cpu_freq,
+	.get_clk_ratio = armada_375_get_clk_ratio,
+	.ratios = armada_375_coreclk_ratios,
+	.num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios),
+};
+
+static void __init armada_375_coreclk_init(struct device_node *np)
+{
+	mvebu_coreclk_setup(np, &armada_375_coreclks);
+}
+CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock",
+	       armada_375_coreclk_init);
+
+/*
+ * Clock Gating Control
+ */
+static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = {
+	{ "mu", NULL, 2 },
+	{ "pp", NULL, 3 },
+	{ "ptp", NULL, 4 },
+	{ "pex0", NULL, 5 },
+	{ "pex1", NULL, 6 },
+	{ "audio", NULL, 8 },
+	{ "nd_clk", "nand", 11 },
+	{ "sata0_link", "sata0_core", 14 },
+	{ "sata0_core", NULL, 15 },
+	{ "usb3", NULL, 16 },
+	{ "sdio", NULL, 17 },
+	{ "usb", NULL, 18 },
+	{ "gop", NULL, 19 },
+	{ "sata1_link", "sata1_core", 20 },
+	{ "sata1_core", NULL, 21 },
+	{ "xor0", NULL, 22 },
+	{ "xor1", NULL, 23 },
+	{ "copro", NULL, 24 },
+	{ "tdm", NULL, 25 },
+	{ "crypto0_enc", NULL, 28 },
+	{ "crypto0_core", NULL, 29 },
+	{ "crypto1_enc", NULL, 30 },
+	{ "crypto1_core", NULL, 31 },
+	{ }
+};
+
+static void __init armada_375_clk_gating_init(struct device_node *np)
+{
+	mvebu_clk_gating_setup(np, armada_375_gating_desc);
+}
+CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock",
+	       armada_375_clk_gating_init);
diff --git a/drivers/clk/mvebu/armada-38x.c b/drivers/clk/mvebu/armada-38x.c
new file mode 100644
index 000000000000..8bccf4ecdab6
--- /dev/null
+++ b/drivers/clk/mvebu/armada-38x.c
@@ -0,0 +1,167 @@
+/*
+ * Marvell Armada 380/385 SoC clocks
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include "common.h"
+
+/*
+ * SAR[14:10] : Ratios between PCLK0, NBCLK, HCLK and DRAM clocks
+ *
+ * SAR[15]    : TCLK frequency
+ *		 0 = 250 MHz
+ *		 1 = 200 MHz
+ */
+
+#define SAR_A380_TCLK_FREQ_OPT		  15
+#define SAR_A380_TCLK_FREQ_OPT_MASK	  0x1
+#define SAR_A380_CPU_DDR_L2_FREQ_OPT	  10
+#define SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
+
+static const u32 armada_38x_tclk_frequencies[] __initconst = {
+	250000000,
+	200000000,
+};
+
+static u32 __init armada_38x_get_tclk_freq(void __iomem *sar)
+{
+	u8 tclk_freq_select;
+
+	tclk_freq_select = ((readl(sar) >> SAR_A380_TCLK_FREQ_OPT) &
+			    SAR_A380_TCLK_FREQ_OPT_MASK);
+	return armada_38x_tclk_frequencies[tclk_freq_select];
+}
+
+static const u32 armada_38x_cpu_frequencies[] __initconst = {
+	0, 0, 0, 0,
+	1066 * 1000 * 1000, 0, 0, 0,
+	1332 * 1000 * 1000, 0, 0, 0,
+	1600 * 1000 * 1000,
+};
+
+static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
+{
+	u8 cpu_freq_select;
+
+	cpu_freq_select = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) &
+			   SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK);
+	if (cpu_freq_select >= ARRAY_SIZE(armada_38x_cpu_frequencies)) {
+		pr_err("Selected CPU frequency (%d) unsupported\n",
+			cpu_freq_select);
+		return 0;
+	}
+
+	return armada_38x_cpu_frequencies[cpu_freq_select];
+}
+
+enum { A380_CPU_TO_DDR, A380_CPU_TO_L2 };
+
+static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = {
+	{ .id = A380_CPU_TO_L2,	 .name = "l2clk" },
+	{ .id = A380_CPU_TO_DDR, .name = "ddrclk" },
+};
+
+static const int armada_38x_cpu_l2_ratios[32][2] __initconst = {
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = {
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static void __init armada_38x_get_clk_ratio(
+	void __iomem *sar, int id, int *mult, int *div)
+{
+	u32 opt = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) &
+		SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK);
+
+	switch (id) {
+	case A380_CPU_TO_L2:
+		*mult = armada_38x_cpu_l2_ratios[opt][0];
+		*div = armada_38x_cpu_l2_ratios[opt][1];
+		break;
+	case A380_CPU_TO_DDR:
+		*mult = armada_38x_cpu_ddr_ratios[opt][0];
+		*div = armada_38x_cpu_ddr_ratios[opt][1];
+		break;
+	}
+}
+
+static const struct coreclk_soc_desc armada_38x_coreclks = {
+	.get_tclk_freq = armada_38x_get_tclk_freq,
+	.get_cpu_freq = armada_38x_get_cpu_freq,
+	.get_clk_ratio = armada_38x_get_clk_ratio,
+	.ratios = armada_38x_coreclk_ratios,
+	.num_ratios = ARRAY_SIZE(armada_38x_coreclk_ratios),
+};
+
+static void __init armada_38x_coreclk_init(struct device_node *np)
+{
+	mvebu_coreclk_setup(np, &armada_38x_coreclks);
+}
+CLK_OF_DECLARE(armada_38x_core_clk, "marvell,armada-380-core-clock",
+	       armada_38x_coreclk_init);
+
+/*
+ * Clock Gating Control
+ */
+static const struct clk_gating_soc_desc armada_38x_gating_desc[] __initconst = {
+	{ "audio", NULL, 0 },
+	{ "ge2", NULL, 2 },
+	{ "ge1", NULL, 3 },
+	{ "ge0", NULL, 4 },
+	{ "pex1", NULL, 5 },
+	{ "pex2", NULL, 6 },
+	{ "pex3", NULL, 7 },
+	{ "pex0", NULL, 8 },
+	{ "usb3h0", NULL, 9 },
+	{ "usb3h1", NULL, 10 },
+	{ "usb3d", NULL, 11 },
+	{ "bm", NULL, 13 },
+	{ "crypto0z", NULL, 14 },
+	{ "sata0", NULL, 15 },
+	{ "crypto1z", NULL, 16 },
+	{ "sdio", NULL, 17 },
+	{ "usb2", NULL, 18 },
+	{ "crypto1", NULL, 21 },
+	{ "xor0", NULL, 22 },
+	{ "crypto0", NULL, 23 },
+	{ "tdm", NULL, 25 },
+	{ "xor1", NULL, 28 },
+	{ "sata1", NULL, 30 },
+	{ }
+};
+
+static void __init armada_38x_clk_gating_init(struct device_node *np)
+{
+	mvebu_clk_gating_setup(np, armada_38x_gating_desc);
+}
+CLK_OF_DECLARE(armada_38x_clk_gating, "marvell,armada-380-gating-clock",
+	       armada_38x_clk_gating_init);
diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c
index 9922c4475aa8..b3094315a3c0 100644
--- a/drivers/clk/mvebu/armada-xp.c
+++ b/drivers/clk/mvebu/armada-xp.c
@@ -158,13 +158,6 @@ static const struct coreclk_soc_desc axp_coreclks = {
 	.num_ratios = ARRAY_SIZE(axp_coreclk_ratios),
 };
 
-static void __init axp_coreclk_init(struct device_node *np)
-{
-	mvebu_coreclk_setup(np, &axp_coreclks);
-}
-CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock",
-	       axp_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -202,9 +195,14 @@ static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = {
 	{ }
 };
 
-static void __init axp_clk_gating_init(struct device_node *np)
+static void __init axp_clk_init(struct device_node *np)
 {
-	mvebu_clk_gating_setup(np, axp_gating_desc);
+	struct device_node *cgnp =
+		of_find_compatible_node(NULL, NULL, "marvell,armada-xp-gating-clock");
+
+	mvebu_coreclk_setup(np, &axp_coreclks);
+
+	if (cgnp)
+		mvebu_clk_gating_setup(cgnp, axp_gating_desc);
 }
-CLK_OF_DECLARE(axp_clk_gating, "marvell,armada-xp-gating-clock",
-	       axp_clk_gating_init);
+CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init);
diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c
index 7162615bcdcd..4da60760be10 100644
--- a/drivers/clk/mvebu/clk-corediv.c
+++ b/drivers/clk/mvebu/clk-corediv.c
@@ -18,26 +18,56 @@
 #include "common.h"
 
 #define CORE_CLK_DIV_RATIO_MASK		0xff
-#define CORE_CLK_DIV_RATIO_RELOAD	BIT(8)
-#define CORE_CLK_DIV_ENABLE_OFFSET	24
-#define CORE_CLK_DIV_RATIO_OFFSET	0x8
 
+/*
+ * This structure describes the hardware details (bit offset and mask)
+ * to configure one particular core divider clock. Those hardware
+ * details may differ from one SoC to another. This structure is
+ * therefore typically instantiated statically to describe the
+ * hardware details.
+ */
 struct clk_corediv_desc {
 	unsigned int mask;
 	unsigned int offset;
 	unsigned int fieldbit;
 };
 
+/*
+ * This structure describes the hardware details to configure the core
+ * divider clocks on a given SoC. Amongst others, it points to the
+ * array of core divider clock descriptors for this SoC, as well as
+ * the corresponding operations to manipulate them.
+ */
+struct clk_corediv_soc_desc {
+	const struct clk_corediv_desc *descs;
+	unsigned int ndescs;
+	const struct clk_ops ops;
+	u32 ratio_reload;
+	u32 enable_bit_offset;
+	u32 ratio_offset;
+};
+
+/*
+ * This structure represents one core divider clock for the clock
+ * framework, and is dynamically allocated for each core divider clock
+ * existing in the current SoC.
+ */
 struct clk_corediv {
 	struct clk_hw hw;
 	void __iomem *reg;
-	struct clk_corediv_desc desc;
+	const struct clk_corediv_desc *desc;
+	const struct clk_corediv_soc_desc *soc_desc;
 	spinlock_t lock;
 };
 
 static struct clk_onecell_data clk_data;
 
-static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = {
+/*
+ * Description of the core divider clocks available. For now, we
+ * support only NAND, and it is available at the same register
+ * locations regardless of the SoC.
+ */
+static const struct clk_corediv_desc mvebu_corediv_desc[] = {
 	{ .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */
 };
 
@@ -46,8 +76,9 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = {
 static int clk_corediv_is_enabled(struct clk_hw *hwclk)
 {
 	struct clk_corediv *corediv = to_corediv_clk(hwclk);
-	struct clk_corediv_desc *desc = &corediv->desc;
-	u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET;
+	const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
+	const struct clk_corediv_desc *desc = corediv->desc;
+	u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset;
 
 	return !!(readl(corediv->reg) & enable_mask);
 }
@@ -55,14 +86,15 @@ static int clk_corediv_is_enabled(struct clk_hw *hwclk)
 static int clk_corediv_enable(struct clk_hw *hwclk)
 {
 	struct clk_corediv *corediv = to_corediv_clk(hwclk);
-	struct clk_corediv_desc *desc = &corediv->desc;
+	const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
+	const struct clk_corediv_desc *desc = corediv->desc;
 	unsigned long flags = 0;
 	u32 reg;
 
 	spin_lock_irqsave(&corediv->lock, flags);
 
 	reg = readl(corediv->reg);
-	reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
+	reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset);
 	writel(reg, corediv->reg);
 
 	spin_unlock_irqrestore(&corediv->lock, flags);
@@ -73,14 +105,15 @@ static int clk_corediv_enable(struct clk_hw *hwclk)
 static void clk_corediv_disable(struct clk_hw *hwclk)
 {
 	struct clk_corediv *corediv = to_corediv_clk(hwclk);
-	struct clk_corediv_desc *desc = &corediv->desc;
+	const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
+	const struct clk_corediv_desc *desc = corediv->desc;
 	unsigned long flags = 0;
 	u32 reg;
 
 	spin_lock_irqsave(&corediv->lock, flags);
 
 	reg = readl(corediv->reg);
-	reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
+	reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset);
 	writel(reg, corediv->reg);
 
 	spin_unlock_irqrestore(&corediv->lock, flags);
@@ -90,10 +123,11 @@ static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk,
 					 unsigned long parent_rate)
 {
 	struct clk_corediv *corediv = to_corediv_clk(hwclk);
-	struct clk_corediv_desc *desc = &corediv->desc;
+	const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
+	const struct clk_corediv_desc *desc = corediv->desc;
 	u32 reg, div;
 
-	reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+	reg = readl(corediv->reg + soc_desc->ratio_offset);
 	div = (reg >> desc->offset) & desc->mask;
 	return parent_rate / div;
 }
@@ -117,7 +151,8 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
 			    unsigned long parent_rate)
 {
 	struct clk_corediv *corediv = to_corediv_clk(hwclk);
-	struct clk_corediv_desc *desc = &corediv->desc;
+	const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
+	const struct clk_corediv_desc *desc = corediv->desc;
 	unsigned long flags = 0;
 	u32 reg, div;
 
@@ -126,17 +161,17 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
 	spin_lock_irqsave(&corediv->lock, flags);
 
 	/* Write new divider to the divider ratio register */
-	reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+	reg = readl(corediv->reg + soc_desc->ratio_offset);
 	reg &= ~(desc->mask << desc->offset);
 	reg |= (div & desc->mask) << desc->offset;
-	writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+	writel(reg, corediv->reg + soc_desc->ratio_offset);
 
 	/* Set reload-force for this clock */
 	reg = readl(corediv->reg) | BIT(desc->fieldbit);
 	writel(reg, corediv->reg);
 
 	/* Now trigger the clock update */
-	reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD;
+	reg = readl(corediv->reg) | soc_desc->ratio_reload;
 	writel(reg, corediv->reg);
 
 	/*
@@ -144,7 +179,7 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
 	 * ratios request and the reload request.
 	 */
 	udelay(1000);
-	reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD);
+	reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload);
 	writel(reg, corediv->reg);
 	udelay(1000);
 
@@ -153,16 +188,37 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
 	return 0;
 }
 
-static const struct clk_ops corediv_ops = {
-	.enable = clk_corediv_enable,
-	.disable = clk_corediv_disable,
-	.is_enabled = clk_corediv_is_enabled,
-	.recalc_rate = clk_corediv_recalc_rate,
-	.round_rate = clk_corediv_round_rate,
-	.set_rate = clk_corediv_set_rate,
+static const struct clk_corediv_soc_desc armada370_corediv_soc = {
+	.descs = mvebu_corediv_desc,
+	.ndescs = ARRAY_SIZE(mvebu_corediv_desc),
+	.ops = {
+		.enable = clk_corediv_enable,
+		.disable = clk_corediv_disable,
+		.is_enabled = clk_corediv_is_enabled,
+		.recalc_rate = clk_corediv_recalc_rate,
+		.round_rate = clk_corediv_round_rate,
+		.set_rate = clk_corediv_set_rate,
+	},
+	.ratio_reload = BIT(8),
+	.enable_bit_offset = 24,
+	.ratio_offset = 0x8,
+};
+
+static const struct clk_corediv_soc_desc armada375_corediv_soc = {
+	.descs = mvebu_corediv_desc,
+	.ndescs = ARRAY_SIZE(mvebu_corediv_desc),
+	.ops = {
+		.recalc_rate = clk_corediv_recalc_rate,
+		.round_rate = clk_corediv_round_rate,
+		.set_rate = clk_corediv_set_rate,
+	},
+	.ratio_reload = BIT(8),
+	.ratio_offset = 0x8,
 };
 
-static void __init mvebu_corediv_clk_init(struct device_node *node)
+static void __init
+mvebu_corediv_clk_init(struct device_node *node,
+		       const struct clk_corediv_soc_desc *soc_desc)
 {
 	struct clk_init_data init;
 	struct clk_corediv *corediv;
@@ -178,7 +234,7 @@ static void __init mvebu_corediv_clk_init(struct device_node *node)
 
 	parent_name = of_clk_get_parent_name(node, 0);
 
-	clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc);
+	clk_data.clk_num = soc_desc->ndescs;
 
 	/* clks holds the clock array */
 	clks = kcalloc(clk_data.clk_num, sizeof(struct clk *),
@@ -199,10 +255,11 @@ static void __init mvebu_corediv_clk_init(struct device_node *node)
 		init.num_parents = 1;
 		init.parent_names = &parent_name;
 		init.name = clk_name;
-		init.ops = &corediv_ops;
+		init.ops = &soc_desc->ops;
 		init.flags = 0;
 
-		corediv[i].desc = mvebu_corediv_desc[i];
+		corediv[i].soc_desc = soc_desc;
+		corediv[i].desc = soc_desc->descs + i;
 		corediv[i].reg = base;
 		corediv[i].hw.init = &init;
 
@@ -219,5 +276,17 @@ err_free_clks:
 err_unmap:
 	iounmap(base);
 }
-CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock",
-	       mvebu_corediv_clk_init);
+
+static void __init armada370_corediv_clk_init(struct device_node *node)
+{
+	return mvebu_corediv_clk_init(node, &armada370_corediv_soc);
+}
+CLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock",
+	       armada370_corediv_clk_init);
+
+static void __init armada375_corediv_clk_init(struct device_node *node)
+{
+	return mvebu_corediv_clk_init(node, &armada375_corediv_soc);
+}
+CLK_OF_DECLARE(armada375_corediv_clk, "marvell,armada-375-corediv-clock",
+	       armada375_corediv_clk_init);
diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c
index 38aee1e3f242..b8c2424ac926 100644
--- a/drivers/clk/mvebu/dove.c
+++ b/drivers/clk/mvebu/dove.c
@@ -154,12 +154,6 @@ static const struct coreclk_soc_desc dove_coreclks = {
 	.num_ratios = ARRAY_SIZE(dove_coreclk_ratios),
 };
 
-static void __init dove_coreclk_init(struct device_node *np)
-{
-	mvebu_coreclk_setup(np, &dove_coreclks);
-}
-CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -186,9 +180,14 @@ static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = {
 	{ }
 };
 
-static void __init dove_clk_gating_init(struct device_node *np)
+static void __init dove_clk_init(struct device_node *np)
 {
-	mvebu_clk_gating_setup(np, dove_gating_desc);
+	struct device_node *cgnp =
+		of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
+
+	mvebu_coreclk_setup(np, &dove_coreclks);
+
+	if (cgnp)
+		mvebu_clk_gating_setup(cgnp, dove_gating_desc);
 }
-CLK_OF_DECLARE(dove_clk_gating, "marvell,dove-gating-clock",
-	       dove_clk_gating_init);
+CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init);
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
index 2636a55f29f9..ddb666a86500 100644
--- a/drivers/clk/mvebu/kirkwood.c
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -193,13 +193,6 @@ static const struct coreclk_soc_desc kirkwood_coreclks = {
 	.num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
 };
 
-static void __init kirkwood_coreclk_init(struct device_node *np)
-{
-	mvebu_coreclk_setup(np, &kirkwood_coreclks);
-}
-CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock",
-	       kirkwood_coreclk_init);
-
 static const struct coreclk_soc_desc mv88f6180_coreclks = {
 	.get_tclk_freq = kirkwood_get_tclk_freq,
 	.get_cpu_freq = mv88f6180_get_cpu_freq,
@@ -208,13 +201,6 @@ static const struct coreclk_soc_desc mv88f6180_coreclks = {
 	.num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
 };
 
-static void __init mv88f6180_coreclk_init(struct device_node *np)
-{
-	mvebu_coreclk_setup(np, &mv88f6180_coreclks);
-}
-CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock",
-	       mv88f6180_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -239,9 +225,21 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
 	{ }
 };
 
-static void __init kirkwood_clk_gating_init(struct device_node *np)
+static void __init kirkwood_clk_init(struct device_node *np)
 {
-	mvebu_clk_gating_setup(np, kirkwood_gating_desc);
+	struct device_node *cgnp =
+		of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock");
+
+
+	if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock"))
+		mvebu_coreclk_setup(np, &mv88f6180_coreclks);
+	else
+		mvebu_coreclk_setup(np, &kirkwood_coreclks);
+
+	if (cgnp)
+		mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
 }
-CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock",
-	       kirkwood_clk_gating_init);
+CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
+	       kirkwood_clk_init);
+CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
+	       kirkwood_clk_init);
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 8eb4799237f0..77313e27bc39 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -8,4 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250)	+= clk-exynos5250.o
 obj-$(CONFIG_SOC_EXYNOS5420)	+= clk-exynos5420.o
 obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
 obj-$(CONFIG_ARCH_EXYNOS)	+= clk-exynos-audss.o
+obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
+obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
 obj-$(CONFIG_ARCH_S3C64XX)	+= clk-s3c64xx.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 010f071af883..b4f967210175 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -16,6 +16,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include "clk.h"
 
@@ -130,6 +131,17 @@ enum exynos4_plls {
 	nr_plls			/* number of PLLs */
 };
 
+static void __iomem *reg_base;
+static enum exynos4_soc exynos4_soc;
+
+/*
+ * Support for CMU save/restore across system suspends
+ */
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos4_save_common;
+static struct samsung_clk_reg_dump *exynos4_save_soc;
+static struct samsung_clk_reg_dump *exynos4_save_pll;
+
 /*
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
@@ -154,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
 	E4X12_MPLL_CON0,
 };
 
+static unsigned long exynos4_clk_pll_regs[] __initdata = {
+	EPLL_LOCK,
+	VPLL_LOCK,
+	EPLL_CON0,
+	EPLL_CON1,
+	EPLL_CON2,
+	VPLL_CON0,
+	VPLL_CON1,
+	VPLL_CON2,
+};
+
 static unsigned long exynos4_clk_regs[] __initdata = {
 	SRC_LEFTBUS,
 	DIV_LEFTBUS,
@@ -161,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = {
 	SRC_RIGHTBUS,
 	DIV_RIGHTBUS,
 	GATE_IP_RIGHTBUS,
-	EPLL_CON0,
-	EPLL_CON1,
-	EPLL_CON2,
-	VPLL_CON0,
-	VPLL_CON1,
-	VPLL_CON2,
 	SRC_TOP0,
 	SRC_TOP1,
 	SRC_CAM,
@@ -227,6 +244,124 @@ static unsigned long exynos4_clk_regs[] __initdata = {
 	GATE_IP_CPU,
 };
 
+static const struct samsung_clk_reg_dump src_mask_suspend[] = {
+	{ .offset = SRC_MASK_TOP,		.value = 0x00000001, },
+	{ .offset = SRC_MASK_CAM,		.value = 0x11111111, },
+	{ .offset = SRC_MASK_TV,		.value = 0x00000111, },
+	{ .offset = SRC_MASK_LCD0,		.value = 0x00001111, },
+	{ .offset = SRC_MASK_MAUDIO,		.value = 0x00000001, },
+	{ .offset = SRC_MASK_FSYS,		.value = 0x01011111, },
+	{ .offset = SRC_MASK_PERIL0,		.value = 0x01111111, },
+	{ .offset = SRC_MASK_PERIL1,		.value = 0x01110111, },
+	{ .offset = SRC_MASK_DMC,		.value = 0x00010000, },
+};
+
+static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
+	{ .offset = E4210_SRC_MASK_LCD1,	.value = 0x00001111, },
+};
+
+#define PLL_ENABLED	(1 << 31)
+#define PLL_LOCKED	(1 << 29)
+
+static void exynos4_clk_wait_for_pll(u32 reg)
+{
+	u32 pll_con;
+
+	pll_con = readl(reg_base + reg);
+	if (!(pll_con & PLL_ENABLED))
+		return;
+
+	while (!(pll_con & PLL_LOCKED)) {
+		cpu_relax();
+		pll_con = readl(reg_base + reg);
+	}
+}
+
+static int exynos4_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, exynos4_save_common,
+				ARRAY_SIZE(exynos4_clk_regs));
+	samsung_clk_save(reg_base, exynos4_save_pll,
+				ARRAY_SIZE(exynos4_clk_pll_regs));
+
+	if (exynos4_soc == EXYNOS4210) {
+		samsung_clk_save(reg_base, exynos4_save_soc,
+					ARRAY_SIZE(exynos4210_clk_save));
+		samsung_clk_restore(reg_base, src_mask_suspend_e4210,
+					ARRAY_SIZE(src_mask_suspend_e4210));
+	} else {
+		samsung_clk_save(reg_base, exynos4_save_soc,
+					ARRAY_SIZE(exynos4x12_clk_save));
+	}
+
+	samsung_clk_restore(reg_base, src_mask_suspend,
+					ARRAY_SIZE(src_mask_suspend));
+
+	return 0;
+}
+
+static void exynos4_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, exynos4_save_pll,
+				ARRAY_SIZE(exynos4_clk_pll_regs));
+
+	exynos4_clk_wait_for_pll(EPLL_CON0);
+	exynos4_clk_wait_for_pll(VPLL_CON0);
+
+	samsung_clk_restore(reg_base, exynos4_save_common,
+				ARRAY_SIZE(exynos4_clk_regs));
+
+	if (exynos4_soc == EXYNOS4210)
+		samsung_clk_restore(reg_base, exynos4_save_soc,
+					ARRAY_SIZE(exynos4210_clk_save));
+	else
+		samsung_clk_restore(reg_base, exynos4_save_soc,
+					ARRAY_SIZE(exynos4x12_clk_save));
+}
+
+static struct syscore_ops exynos4_clk_syscore_ops = {
+	.suspend = exynos4_clk_suspend,
+	.resume = exynos4_clk_resume,
+};
+
+static void exynos4_clk_sleep_init(void)
+{
+	exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs,
+					ARRAY_SIZE(exynos4_clk_regs));
+	if (!exynos4_save_common)
+		goto err_warn;
+
+	if (exynos4_soc == EXYNOS4210)
+		exynos4_save_soc = samsung_clk_alloc_reg_dump(
+					exynos4210_clk_save,
+					ARRAY_SIZE(exynos4210_clk_save));
+	else
+		exynos4_save_soc = samsung_clk_alloc_reg_dump(
+					exynos4x12_clk_save,
+					ARRAY_SIZE(exynos4x12_clk_save));
+	if (!exynos4_save_soc)
+		goto err_common;
+
+	exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
+					ARRAY_SIZE(exynos4_clk_pll_regs));
+	if (!exynos4_save_pll)
+		goto err_soc;
+
+	register_syscore_ops(&exynos4_clk_syscore_ops);
+	return;
+
+err_soc:
+	kfree(exynos4_save_soc);
+err_common:
+	kfree(exynos4_save_common);
+err_warn:
+	pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+		__func__);
+}
+#else
+static void exynos4_clk_sleep_init(void) {}
+#endif
+
 /* list of all parent clock list */
 PNAME(mout_apll_p)	= { "fin_pll", "fout_apll", };
 PNAME(mout_mpll_p)	= { "fin_pll", "fout_mpll", };
@@ -908,12 +1043,13 @@ static unsigned long exynos4_get_xom(void)
 	return xom;
 }
 
-static void __init exynos4_clk_register_finpll(unsigned long xom)
+static void __init exynos4_clk_register_finpll(void)
 {
 	struct samsung_fixed_rate_clock fclk;
 	struct clk *clk;
 	unsigned long finpll_f = 24000000;
 	char *parent_name;
+	unsigned int xom = exynos4_get_xom();
 
 	parent_name = xom & 1 ? "xusbxti" : "xxti";
 	clk = clk_get(NULL, parent_name);
@@ -1038,27 +1174,21 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
 
 /* register exynos4 clocks */
 static void __init exynos4_clk_init(struct device_node *np,
-				    enum exynos4_soc exynos4_soc,
-				    void __iomem *reg_base, unsigned long xom)
+				    enum exynos4_soc soc)
 {
+	exynos4_soc = soc;
+
 	reg_base = of_iomap(np, 0);
 	if (!reg_base)
 		panic("%s: failed to map registers\n", __func__);
 
-	if (exynos4_soc == EXYNOS4210)
-		samsung_clk_init(np, reg_base, CLK_NR_CLKS,
-			exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
-			exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save));
-	else
-		samsung_clk_init(np, reg_base, CLK_NR_CLKS,
-			exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
-			exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
+	samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 
 	samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
 			ext_clk_match);
 
-	exynos4_clk_register_finpll(xom);
+	exynos4_clk_register_finpll();
 
 	if (exynos4_soc == EXYNOS4210) {
 		samsung_clk_register_mux(exynos4210_mux_early,
@@ -1125,6 +1255,8 @@ static void __init exynos4_clk_init(struct device_node *np,
 	samsung_clk_register_alias(exynos4_aliases,
 			ARRAY_SIZE(exynos4_aliases));
 
+	exynos4_clk_sleep_init();
+
 	pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
 		"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
 		exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
@@ -1136,12 +1268,12 @@ static void __init exynos4_clk_init(struct device_node *np,
 
 static void __init exynos4210_clk_init(struct device_node *np)
 {
-	exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom());
+	exynos4_clk_init(np, EXYNOS4210);
 }
 CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init);
 
 static void __init exynos4412_clk_init(struct device_node *np)
 {
-	exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom());
+	exynos4_clk_init(np, EXYNOS4X12);
 }
 CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index ff4beebe1f0b..e7ee4420da81 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -16,6 +16,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include "clk.h"
 
@@ -85,6 +86,11 @@ enum exynos5250_plls {
 	nr_plls			/* number of PLLs */
 };
 
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos5250_save;
+
 /*
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
@@ -137,6 +143,41 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
 	GATE_IP_ACP,
 };
 
+static int exynos5250_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, exynos5250_save,
+				ARRAY_SIZE(exynos5250_clk_regs));
+
+	return 0;
+}
+
+static void exynos5250_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, exynos5250_save,
+				ARRAY_SIZE(exynos5250_clk_regs));
+}
+
+static struct syscore_ops exynos5250_clk_syscore_ops = {
+	.suspend = exynos5250_clk_suspend,
+	.resume = exynos5250_clk_resume,
+};
+
+static void exynos5250_clk_sleep_init(void)
+{
+	exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
+					ARRAY_SIZE(exynos5250_clk_regs));
+	if (!exynos5250_save) {
+		pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+			__func__);
+		return;
+	}
+
+	register_syscore_ops(&exynos5250_clk_syscore_ops);
+}
+#else
+static void exynos5250_clk_sleep_init(void) {}
+#endif
+
 /* list of all parent clock list */
 PNAME(mout_apll_p)	= { "fin_pll", "fout_apll", };
 PNAME(mout_cpu_p)	= { "mout_apll", "mout_mpll", };
@@ -645,8 +686,6 @@ static struct of_device_id ext_clk_match[] __initdata = {
 /* register exynox5250 clocks */
 static void __init exynos5250_clk_init(struct device_node *np)
 {
-	void __iomem *reg_base;
-
 	if (np) {
 		reg_base = of_iomap(np, 0);
 		if (!reg_base)
@@ -655,9 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
 		panic("%s: unable to determine soc\n", __func__);
 	}
 
-	samsung_clk_init(np, reg_base, CLK_NR_CLKS,
-			exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
-			NULL, 0);
+	samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
 			ext_clk_match);
@@ -685,6 +722,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
 	samsung_clk_register_gate(exynos5250_gate_clks,
 			ARRAY_SIZE(exynos5250_gate_clks));
 
+	exynos5250_clk_sleep_init();
+
 	pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
 			_get_rate("div_arm2"));
 }
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index ab4f2f7d88ef..60b26819bed5 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -16,6 +16,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include "clk.h"
 
@@ -108,6 +109,11 @@ enum exynos5420_plls {
 	nr_plls			/* number of PLLs */
 };
 
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos5420_save;
+
 /*
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
@@ -174,6 +180,41 @@ static unsigned long exynos5420_clk_regs[] __initdata = {
 	DIV_KFC0,
 };
 
+static int exynos5420_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, exynos5420_save,
+				ARRAY_SIZE(exynos5420_clk_regs));
+
+	return 0;
+}
+
+static void exynos5420_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, exynos5420_save,
+				ARRAY_SIZE(exynos5420_clk_regs));
+}
+
+static struct syscore_ops exynos5420_clk_syscore_ops = {
+	.suspend = exynos5420_clk_suspend,
+	.resume = exynos5420_clk_resume,
+};
+
+static void exynos5420_clk_sleep_init(void)
+{
+	exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs,
+					ARRAY_SIZE(exynos5420_clk_regs));
+	if (!exynos5420_save) {
+		pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+			__func__);
+		return;
+	}
+
+	register_syscore_ops(&exynos5420_clk_syscore_ops);
+}
+#else
+static void exynos5420_clk_sleep_init(void) {}
+#endif
+
 /* list of all parent clocks */
 PNAME(mspll_cpu_p)	= { "sclk_cpll", "sclk_dpll",
 				"sclk_mpll", "sclk_spll" };
@@ -737,8 +778,6 @@ static struct of_device_id ext_clk_match[] __initdata = {
 /* register exynos5420 clocks */
 static void __init exynos5420_clk_init(struct device_node *np)
 {
-	void __iomem *reg_base;
-
 	if (np) {
 		reg_base = of_iomap(np, 0);
 		if (!reg_base)
@@ -747,9 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np)
 		panic("%s: unable to determine soc\n", __func__);
 	}
 
-	samsung_clk_init(np, reg_base, CLK_NR_CLKS,
-			exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
-			NULL, 0);
+	samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 	samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
 			ext_clk_match);
@@ -765,5 +802,7 @@ static void __init exynos5420_clk_init(struct device_node *np)
 			ARRAY_SIZE(exynos5420_div_clks));
 	samsung_clk_register_gate(exynos5420_gate_clks,
 			ARRAY_SIZE(exynos5420_gate_clks));
+
+	exynos5420_clk_sleep_init();
 }
 CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index cbc15b56891d..2bfad5a993d0 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -101,7 +101,7 @@ static void __init exynos5440_clk_init(struct device_node *np)
 		return;
 	}
 
-	samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
+	samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 	samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
 		ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
 
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 81e6d2f49aa0..7fb0a28e65d5 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -11,6 +11,7 @@
 
 #include <linux/errno.h>
 #include <linux/hrtimer.h>
+#include <linux/delay.h>
 #include "clk.h"
 #include "clk-pll.h"
 
@@ -59,6 +60,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
 }
 
 /*
+ * PLL2126 Clock Type
+ */
+
+#define PLL2126_MDIV_MASK	(0xff)
+#define PLL2126_PDIV_MASK	(0x3f)
+#define PLL2126_SDIV_MASK	(0x3)
+#define PLL2126_MDIV_SHIFT	(16)
+#define PLL2126_PDIV_SHIFT	(8)
+#define PLL2126_SDIV_SHIFT	(0)
+
+static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
+	pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
+	sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
+
+	fvco *= (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll2126_clk_ops = {
+	.recalc_rate = samsung_pll2126_recalc_rate,
+};
+
+/*
+ * PLL3000 Clock Type
+ */
+
+#define PLL3000_MDIV_MASK	(0xff)
+#define PLL3000_PDIV_MASK	(0x3)
+#define PLL3000_SDIV_MASK	(0x3)
+#define PLL3000_MDIV_SHIFT	(16)
+#define PLL3000_PDIV_SHIFT	(8)
+#define PLL3000_SDIV_SHIFT	(0)
+
+static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
+	pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
+	sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
+
+	fvco *= (2 * (mdiv + 8));
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll3000_clk_ops = {
+	.recalc_rate = samsung_pll3000_recalc_rate,
+};
+
+/*
  * PLL35xx Clock Type
  */
 /* Maximum lock time can be 270 * PDIV cycles */
@@ -564,7 +631,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = {
 #define PLL6552_PDIV_MASK	0x3f
 #define PLL6552_SDIV_MASK	0x7
 #define PLL6552_MDIV_SHIFT	16
+#define PLL6552_MDIV_SHIFT_2416	14
 #define PLL6552_PDIV_SHIFT	8
+#define PLL6552_PDIV_SHIFT_2416	5
 #define PLL6552_SDIV_SHIFT	0
 
 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
@@ -575,8 +644,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
 	u64 fvco = parent_rate;
 
 	pll_con = __raw_readl(pll->con_reg);
-	mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
-	pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
+	if (pll->type == pll_6552_s3c2416) {
+		mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
+		pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
+	} else {
+		mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
+		pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
+	}
 	sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
 
 	fvco *= mdiv;
@@ -628,6 +702,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = {
 };
 
 /*
+ * PLL Clock Type of S3C24XX before S3C2443
+ */
+
+#define PLLS3C2410_MDIV_MASK		(0xff)
+#define PLLS3C2410_PDIV_MASK		(0x1f)
+#define PLLS3C2410_SDIV_MASK		(0x3)
+#define PLLS3C2410_MDIV_SHIFT		(12)
+#define PLLS3C2410_PDIV_SHIFT		(4)
+#define PLLS3C2410_SDIV_SHIFT		(0)
+
+#define PLLS3C2410_ENABLE_REG_OFFSET	0x10
+
+static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
+	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
+	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
+
+	fvco *= (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
+	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
+	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
+
+	fvco *= (2 * (mdiv + 8));
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	const struct samsung_pll_rate_table *rate;
+	u32 tmp;
+
+	/* Get required rate settings from table */
+	rate = samsung_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	tmp = __raw_readl(pll->con_reg);
+
+	/* Change PLL PMS values */
+	tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
+			(PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
+			(PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
+	tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
+			(rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
+			(rate->sdiv << PLLS3C2410_SDIV_SHIFT);
+	__raw_writel(tmp, pll->con_reg);
+
+	/* Time to settle according to the manual */
+	udelay(300);
+
+	return 0;
+}
+
+static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+	u32 pll_en_orig = pll_en;
+
+	if (enable)
+		pll_en &= ~BIT(bit);
+	else
+		pll_en |= BIT(bit);
+
+	__raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+
+	/* if we started the UPLL, then allow to settle */
+	if (enable && (pll_en_orig & BIT(bit)))
+		udelay(300);
+
+	return 0;
+}
+
+static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
+{
+	return samsung_s3c2410_pll_enable(hw, 5, true);
+}
+
+static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
+{
+	samsung_s3c2410_pll_enable(hw, 5, false);
+}
+
+static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
+{
+	return samsung_s3c2410_pll_enable(hw, 7, true);
+}
+
+static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
+{
+	samsung_s3c2410_pll_enable(hw, 7, false);
+}
+
+static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
+	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
+	.enable = samsung_s3c2410_mpll_enable,
+	.disable = samsung_s3c2410_mpll_disable,
+};
+
+static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
+	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
+	.enable = samsung_s3c2410_upll_enable,
+	.disable = samsung_s3c2410_upll_disable,
+};
+
+static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
+	.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
+	.enable = samsung_s3c2410_mpll_enable,
+	.disable = samsung_s3c2410_mpll_disable,
+};
+
+static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
+	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
+	.enable = samsung_s3c2410_mpll_enable,
+	.disable = samsung_s3c2410_mpll_disable,
+	.round_rate = samsung_pll_round_rate,
+	.set_rate = samsung_s3c2410_pll_set_rate,
+};
+
+static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
+	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
+	.enable = samsung_s3c2410_upll_enable,
+	.disable = samsung_s3c2410_upll_disable,
+	.round_rate = samsung_pll_round_rate,
+	.set_rate = samsung_s3c2410_pll_set_rate,
+};
+
+static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
+	.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
+	.enable = samsung_s3c2410_mpll_enable,
+	.disable = samsung_s3c2410_mpll_disable,
+	.round_rate = samsung_pll_round_rate,
+	.set_rate = samsung_s3c2410_pll_set_rate,
+};
+
+/*
  * PLL2550x Clock Type
  */
 
@@ -746,6 +983,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
 	}
 
 	switch (pll_clk->type) {
+	case pll_2126:
+		init.ops = &samsung_pll2126_clk_ops;
+		break;
+	case pll_3000:
+		init.ops = &samsung_pll3000_clk_ops;
+		break;
 	/* clk_ops for 35xx and 2550 are similar */
 	case pll_35xx:
 	case pll_2550:
@@ -773,6 +1016,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
 			init.ops = &samsung_pll36xx_clk_ops;
 		break;
 	case pll_6552:
+	case pll_6552_s3c2416:
 		init.ops = &samsung_pll6552_clk_ops;
 		break;
 	case pll_6553:
@@ -786,6 +1030,24 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
 		else
 			init.ops = &samsung_pll46xx_clk_ops;
 		break;
+	case pll_s3c2410_mpll:
+		if (!pll->rate_table)
+			init.ops = &samsung_s3c2410_mpll_clk_min_ops;
+		else
+			init.ops = &samsung_s3c2410_mpll_clk_ops;
+		break;
+	case pll_s3c2410_upll:
+		if (!pll->rate_table)
+			init.ops = &samsung_s3c2410_upll_clk_min_ops;
+		else
+			init.ops = &samsung_s3c2410_upll_clk_ops;
+		break;
+	case pll_s3c2440_mpll:
+		if (!pll->rate_table)
+			init.ops = &samsung_s3c2440_mpll_clk_min_ops;
+		else
+			init.ops = &samsung_s3c2440_mpll_clk_ops;
+		break;
 	default:
 		pr_warn("%s: Unknown pll type for pll clk %s\n",
 			__func__, pll_clk->name);
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 6c39030080fb..6428bcc6df6f 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -13,6 +13,8 @@
 #define __SAMSUNG_CLK_PLL_H
 
 enum samsung_pll_type {
+	pll_2126,
+	pll_3000,
 	pll_35xx,
 	pll_36xx,
 	pll_2550,
@@ -24,7 +26,11 @@ enum samsung_pll_type {
 	pll_4650,
 	pll_4650c,
 	pll_6552,
+	pll_6552_s3c2416,
 	pll_6553,
+	pll_s3c2410_mpll,
+	pll_s3c2410_upll,
+	pll_s3c2440_mpll,
 };
 
 #define PLL_35XX_RATE(_rate, _m, _p, _s)			\
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
new file mode 100644
index 000000000000..0f11a07d5c01
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2013 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.
+ *
+ * Common Clock Framework support for S3C2412 and S3C2413.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#include <dt-bindings/clock/s3c2412.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#define LOCKTIME	0x00
+#define MPLLCON		0x04
+#define UPLLCON		0x08
+#define CLKCON		0x0c
+#define CLKDIVN		0x14
+#define CLKSRC		0x1c
+
+/* list of PLLs to be registered */
+enum s3c2412_plls {
+	mpll, upll,
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s3c2412_save;
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static unsigned long s3c2412_clk_regs[] __initdata = {
+	LOCKTIME,
+	MPLLCON,
+	UPLLCON,
+	CLKCON,
+	CLKDIVN,
+	CLKSRC,
+};
+
+static int s3c2412_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, s3c2412_save,
+				ARRAY_SIZE(s3c2412_clk_regs));
+
+	return 0;
+}
+
+static void s3c2412_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, s3c2412_save,
+				ARRAY_SIZE(s3c2412_clk_regs));
+}
+
+static struct syscore_ops s3c2412_clk_syscore_ops = {
+	.suspend = s3c2412_clk_suspend,
+	.resume = s3c2412_clk_resume,
+};
+
+static void s3c2412_clk_sleep_init(void)
+{
+	s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs,
+						ARRAY_SIZE(s3c2412_clk_regs));
+	if (!s3c2412_save) {
+		pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+			__func__);
+		return;
+	}
+
+	register_syscore_ops(&s3c2412_clk_syscore_ops);
+	return;
+}
+#else
+static void s3c2412_clk_sleep_init(void) {}
+#endif
+
+static struct clk_div_table divxti_d[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 6 },
+	{ .val = 4, .div = 8 },
+	{ .val = 5, .div = 10 },
+	{ .val = 6, .div = 12 },
+	{ .val = 7, .div = 14 },
+	{ /* sentinel */ },
+};
+
+struct samsung_div_clock s3c2412_dividers[] __initdata = {
+	DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
+	DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
+	DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
+	DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4),
+	DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1),
+	DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1),
+	DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1),
+	DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1),
+	DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
+};
+
+struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
+	FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
+};
+
+/*
+ * The first two use the OM[4] setting, which is not readable from
+ * software, so assume it is set to xti.
+ */
+PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" };
+PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" };
+
+PNAME(camclk_p) = { "usysclk", "hclk" };
+PNAME(usbclk_p) = { "usysclk", "hclk" };
+PNAME(i2sclk_p) = { "erefclk", "mpll" };
+PNAME(uartclk_p) = { "erefclk", "mpll" };
+PNAME(usysclk_p) = { "urefclk", "upll" };
+PNAME(msysclk_p) = { "mdivclk", "mpll" };
+PNAME(mdivclk_p) = { "xti", "div_xti" };
+PNAME(armclk_p) = { "armdiv", "hclk" };
+
+struct samsung_mux_clock s3c2412_muxes[] __initdata = {
+	MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
+	MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
+	MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
+	MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1),
+	MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1),
+	MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1),
+	MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1),
+	MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1),
+	MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1),
+	MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1),
+};
+
+static struct samsung_pll_clock s3c2412_plls[] __initdata = {
+	[mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
+						LOCKTIME, MPLLCON, NULL),
+	[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
+						LOCKTIME, UPLLCON, NULL),
+};
+
+struct samsung_gate_clock s3c2412_gates[] __initdata = {
+	GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
+	GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
+	GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
+	GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0),
+	GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0),
+	GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0),
+	GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0),
+	GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0),
+	GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0),
+	GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0),
+	GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0),
+	GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0),
+	GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0),
+	GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0),
+	GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0),
+	GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0),
+	GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0),
+	GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0),
+	GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
+	GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
+	GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
+	GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+struct samsung_clock_alias s3c2412_aliases[] __initdata = {
+	ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
+	ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
+	ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
+	ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"),
+	ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"),
+	ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"),
+	ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
+	ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
+	ALIAS(PCLK_ADC, NULL, "adc"),
+	ALIAS(PCLK_RTC, NULL, "rtc"),
+	ALIAS(PCLK_PWM, NULL, "timers"),
+	ALIAS(HCLK_LCD, NULL, "lcd"),
+	ALIAS(PCLK_USBD, NULL, "usb-device"),
+	ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"),
+	ALIAS(HCLK_USBH, NULL, "usb-host"),
+	ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
+	ALIAS(ARMCLK, NULL, "armclk"),
+	ALIAS(HCLK, NULL, "hclk"),
+	ALIAS(MPLL, NULL, "mpll"),
+	ALIAS(MSYSCLK, NULL, "fclk"),
+};
+
+/*
+ * fixed rate clocks generated outside the soc
+ * Only necessary until the devicetree-move is complete
+ */
+#define XTI	1
+struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
+	FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
+	FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
+};
+
+static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f,
+							 unsigned long ext_f)
+{
+	/* xtal alias is necessary for the current cpufreq driver */
+	struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
+
+	s3c2412_common_frate_clks[0].fixed_rate = xti_f;
+	s3c2412_common_frate_clks[1].fixed_rate = ext_f;
+	samsung_clk_register_fixed_rate(s3c2412_common_frate_clks,
+				ARRAY_SIZE(s3c2412_common_frate_clks));
+
+	samsung_clk_register_alias(&xti_alias, 1);
+}
+
+void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
+				    unsigned long ext_f, void __iomem *base)
+{
+	reg_base = base;
+
+	if (np) {
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	}
+
+	samsung_clk_init(np, reg_base, NR_CLKS);
+
+	/* Register external clocks only in non-dt cases */
+	if (!np)
+		s3c2412_common_clk_register_fixed_ext(xti_f, ext_f);
+
+	/* Register PLLs. */
+	samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls),
+				 reg_base);
+
+	/* Register common internal clocks. */
+	samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes));
+	samsung_clk_register_div(s3c2412_dividers,
+					  ARRAY_SIZE(s3c2412_dividers));
+	samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates));
+	samsung_clk_register_fixed_factor(s3c2412_ffactor,
+					  ARRAY_SIZE(s3c2412_ffactor));
+	samsung_clk_register_alias(s3c2412_aliases,
+				   ARRAY_SIZE(s3c2412_aliases));
+
+	s3c2412_clk_sleep_init();
+}
+
+static void __init s3c2412_clk_init(struct device_node *np)
+{
+	s3c2412_common_clk_init(np, 0, 0, 0);
+}
+CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
new file mode 100644
index 000000000000..8e4f4517e95c
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2013 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.
+ *
+ * Common Clock Framework support for S3C2443 and following SoCs.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#include <dt-bindings/clock/s3c2443.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+/* S3C2416 clock controller register offsets */
+#define LOCKCON0	0x00
+#define LOCKCON1	0x04
+#define MPLLCON		0x10
+#define EPLLCON		0x18
+#define EPLLCON_K	0x1C
+#define CLKSRC		0x20
+#define CLKDIV0		0x24
+#define CLKDIV1		0x28
+#define CLKDIV2		0x2C
+#define HCLKCON		0x30
+#define PCLKCON		0x34
+#define SCLKCON		0x38
+
+/* the soc types */
+enum supported_socs {
+	S3C2416,
+	S3C2443,
+	S3C2450,
+};
+
+/* list of PLLs to be registered */
+enum s3c2443_plls {
+	mpll, epll,
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s3c2443_save;
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static unsigned long s3c2443_clk_regs[] __initdata = {
+	LOCKCON0,
+	LOCKCON1,
+	MPLLCON,
+	EPLLCON,
+	EPLLCON_K,
+	CLKSRC,
+	CLKDIV0,
+	CLKDIV1,
+	CLKDIV2,
+	PCLKCON,
+	HCLKCON,
+	SCLKCON,
+};
+
+static int s3c2443_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, s3c2443_save,
+				ARRAY_SIZE(s3c2443_clk_regs));
+
+	return 0;
+}
+
+static void s3c2443_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, s3c2443_save,
+				ARRAY_SIZE(s3c2443_clk_regs));
+}
+
+static struct syscore_ops s3c2443_clk_syscore_ops = {
+	.suspend = s3c2443_clk_suspend,
+	.resume = s3c2443_clk_resume,
+};
+
+static void s3c2443_clk_sleep_init(void)
+{
+	s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs,
+						ARRAY_SIZE(s3c2443_clk_regs));
+	if (!s3c2443_save) {
+		pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+			__func__);
+		return;
+	}
+
+	register_syscore_ops(&s3c2443_clk_syscore_ops);
+	return;
+}
+#else
+static void s3c2443_clk_sleep_init(void) {}
+#endif
+
+PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" };
+PNAME(esysclk_p) = { "epllref", "epll" };
+PNAME(mpllref_p) = { "xti", "mdivclk" };
+PNAME(msysclk_p) = { "mpllref", "mpll" };
+PNAME(armclk_p) = { "armdiv" , "hclk" };
+PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
+
+struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
+	MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
+	MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
+	MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
+	MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"),
+	MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"),
+	MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2),
+};
+
+static struct clk_div_table hclk_d[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 3, .div = 4 },
+	{ /* sentinel */ },
+};
+
+static struct clk_div_table mdivclk_d[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 3 },
+	{ .val = 2, .div = 5 },
+	{ .val = 3, .div = 7 },
+	{ .val = 4, .div = 9 },
+	{ .val = 5, .div = 11 },
+	{ .val = 6, .div = 13 },
+	{ .val = 7, .div = 15 },
+	{ /* sentinel */ },
+};
+
+struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
+	DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
+	DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
+	DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
+	DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1),
+	DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2),
+	DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8),
+	DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4),
+	DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4),
+	DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2),
+	DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
+};
+
+struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
+	GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
+	GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
+	GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
+	GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0),
+	GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0),
+	GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0),
+	GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0),
+	GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0),
+	GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0),
+	GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0),
+	GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0),
+	GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0),
+	GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0),
+	GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0),
+	GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0),
+	GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0),
+	GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0),
+	GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0),
+	GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0),
+	GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0),
+	GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0),
+	GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0),
+	GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0),
+	GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
+};
+
+struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
+	ALIAS(HCLK, NULL, "hclk"),
+	ALIAS(HCLK_SSMC, NULL, "nand"),
+	ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
+	ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
+	ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
+	ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"),
+	ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
+	ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
+	ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
+	ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"),
+	ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
+	ALIAS(PCLK_PWM, NULL, "timers"),
+	ALIAS(PCLK_RTC, NULL, "rtc"),
+	ALIAS(PCLK_WDT, NULL, "watchdog"),
+	ALIAS(PCLK_ADC, NULL, "adc"),
+	ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"),
+	ALIAS(HCLK_USBD, NULL, "usb-device"),
+	ALIAS(HCLK_USBH, NULL, "usb-host"),
+	ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
+	ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"),
+	ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"),
+	ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
+	ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
+	ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"),
+	ALIAS(SCLK_I2S0, NULL, "i2s-if"),
+	ALIAS(HCLK_LCD, NULL, "lcd"),
+	ALIAS(SCLK_FIMD, NULL, "sclk_fimd"),
+};
+
+/* S3C2416 specific clocks */
+
+static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
+	[mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref",
+						LOCKCON0, MPLLCON, NULL),
+	[epll] = PLL(pll_6553, 0, "epll", "epllref",
+						LOCKCON1, EPLLCON, NULL),
+};
+
+PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
+PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" };
+PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" };
+
+static struct clk_div_table armdiv_s3c2416_d[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 3, .div = 4 },
+	{ .val = 5, .div = 6 },
+	{ .val = 7, .div = 8 },
+	{ /* sentinel */ },
+};
+
+struct samsung_div_clock s3c2416_dividers[] __initdata = {
+	DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
+	DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
+	DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
+};
+
+struct samsung_mux_clock s3c2416_muxes[] __initdata = {
+	MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
+	MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
+	MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
+};
+
+struct samsung_gate_clock s3c2416_gates[] __initdata = {
+	GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
+	GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
+	GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
+	GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0),
+	GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0),
+	GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0),
+	GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
+};
+
+struct samsung_clock_alias s3c2416_aliases[] __initdata = {
+	ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
+	ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
+	ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
+	ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
+	ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
+	ALIAS(ARMDIV, NULL, "armdiv"),
+};
+
+/* S3C2443 specific clocks */
+
+static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
+	[mpll] = PLL(pll_3000, 0, "mpll", "mpllref",
+						LOCKCON0, MPLLCON, NULL),
+	[epll] = PLL(pll_2126, 0, "epll", "epllref",
+						LOCKCON1, EPLLCON, NULL),
+};
+
+static struct clk_div_table armdiv_s3c2443_d[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 8, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 9, .div = 4 },
+	{ .val = 10, .div = 6 },
+	{ .val = 11, .div = 8 },
+	{ .val = 13, .div = 12 },
+	{ .val = 15, .div = 16 },
+	{ /* sentinel */ },
+};
+
+struct samsung_div_clock s3c2443_dividers[] __initdata = {
+	DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
+	DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
+};
+
+struct samsung_gate_clock s3c2443_gates[] __initdata = {
+	GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
+	GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
+	GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
+	GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0),
+	GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
+};
+
+struct samsung_clock_alias s3c2443_aliases[] __initdata = {
+	ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
+	ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
+	ALIAS(SCLK_CAM, NULL, "camif-upll"),
+	ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"),
+	ALIAS(PCLK_SDI, NULL, "sdi"),
+	ALIAS(HCLK_CFC, NULL, "cfc"),
+	ALIAS(ARMDIV, NULL, "armdiv"),
+};
+
+/* S3C2450 specific clocks */
+
+PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
+PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
+PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
+
+struct samsung_div_clock s3c2450_dividers[] __initdata = {
+	DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
+	DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
+	DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
+	DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
+};
+
+struct samsung_mux_clock s3c2450_muxes[] __initdata = {
+	MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
+	MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
+	MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
+};
+
+struct samsung_gate_clock s3c2450_gates[] __initdata = {
+	GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
+	GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
+	GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
+	GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0),
+	GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0),
+	GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0),
+	GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0),
+	GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
+};
+
+struct samsung_clock_alias s3c2450_aliases[] __initdata = {
+	ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
+	ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
+	ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
+	ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
+};
+
+/*
+ * fixed rate clocks generated outside the soc
+ * Only necessary until the devicetree-move is complete
+ */
+struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
+	FRATE(0, "xti", NULL, CLK_IS_ROOT, 0),
+	FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
+	FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0),
+	FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0),
+};
+
+static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f)
+{
+	s3c2443_common_frate_clks[0].fixed_rate = xti_f;
+	samsung_clk_register_fixed_rate(s3c2443_common_frate_clks,
+				ARRAY_SIZE(s3c2443_common_frate_clks));
+}
+
+void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
+				    int current_soc,
+				    void __iomem *base)
+{
+	reg_base = base;
+
+	if (np) {
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	}
+
+	samsung_clk_init(np, reg_base, NR_CLKS);
+
+	/* Register external clocks only in non-dt cases */
+	if (!np)
+		s3c2443_common_clk_register_fixed_ext(xti_f);
+
+	/* Register PLLs. */
+	if (current_soc == S3C2416 || current_soc == S3C2450)
+		samsung_clk_register_pll(s3c2416_pll_clks,
+				ARRAY_SIZE(s3c2416_pll_clks), reg_base);
+	else
+		samsung_clk_register_pll(s3c2443_pll_clks,
+				ARRAY_SIZE(s3c2443_pll_clks), reg_base);
+
+	/* Register common internal clocks. */
+	samsung_clk_register_mux(s3c2443_common_muxes,
+			ARRAY_SIZE(s3c2443_common_muxes));
+	samsung_clk_register_div(s3c2443_common_dividers,
+			ARRAY_SIZE(s3c2443_common_dividers));
+	samsung_clk_register_gate(s3c2443_common_gates,
+		ARRAY_SIZE(s3c2443_common_gates));
+	samsung_clk_register_alias(s3c2443_common_aliases,
+		ARRAY_SIZE(s3c2443_common_aliases));
+
+	/* Register SoC-specific clocks. */
+	switch (current_soc) {
+	case S3C2450:
+		samsung_clk_register_div(s3c2450_dividers,
+				ARRAY_SIZE(s3c2450_dividers));
+		samsung_clk_register_mux(s3c2450_muxes,
+				ARRAY_SIZE(s3c2450_muxes));
+		samsung_clk_register_gate(s3c2450_gates,
+				ARRAY_SIZE(s3c2450_gates));
+		samsung_clk_register_alias(s3c2450_aliases,
+				ARRAY_SIZE(s3c2450_aliases));
+		/* fall through, as s3c2450 extends the s3c2416 clocks */
+	case S3C2416:
+		samsung_clk_register_div(s3c2416_dividers,
+				ARRAY_SIZE(s3c2416_dividers));
+		samsung_clk_register_mux(s3c2416_muxes,
+				ARRAY_SIZE(s3c2416_muxes));
+		samsung_clk_register_gate(s3c2416_gates,
+				ARRAY_SIZE(s3c2416_gates));
+		samsung_clk_register_alias(s3c2416_aliases,
+				ARRAY_SIZE(s3c2416_aliases));
+		break;
+	case S3C2443:
+		samsung_clk_register_div(s3c2443_dividers,
+				ARRAY_SIZE(s3c2443_dividers));
+		samsung_clk_register_gate(s3c2443_gates,
+				ARRAY_SIZE(s3c2443_gates));
+		samsung_clk_register_alias(s3c2443_aliases,
+				ARRAY_SIZE(s3c2443_aliases));
+		break;
+	}
+
+	s3c2443_clk_sleep_init();
+}
+
+static void __init s3c2416_clk_init(struct device_node *np)
+{
+	s3c2443_common_clk_init(np, 0, S3C2416, 0);
+}
+CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
+
+static void __init s3c2443_clk_init(struct device_node *np)
+{
+	s3c2443_common_clk_init(np, 0, S3C2443, 0);
+}
+CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
+
+static void __init s3c2450_clk_init(struct device_node *np)
+{
+	s3c2443_common_clk_init(np, 0, S3C2450, 0);
+}
+CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 8e27aee6887e..8bda658137a8 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -13,6 +13,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include <dt-bindings/clock/samsung,s3c64xx-clock.h>
 
@@ -61,6 +62,13 @@ enum s3c64xx_plls {
 	apll, mpll, epll,
 };
 
+static void __iomem *reg_base;
+static bool is_s3c6400;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s3c64xx_save_common;
+static struct samsung_clk_reg_dump *s3c64xx_save_soc;
+
 /*
  * List of controller registers to be saved and restored during
  * a suspend/resume cycle.
@@ -87,6 +95,60 @@ static unsigned long s3c6410_clk_regs[] __initdata = {
 	MEM0_GATE,
 };
 
+static int s3c64xx_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, s3c64xx_save_common,
+				ARRAY_SIZE(s3c64xx_clk_regs));
+
+	if (!is_s3c6400)
+		samsung_clk_save(reg_base, s3c64xx_save_soc,
+					ARRAY_SIZE(s3c6410_clk_regs));
+
+	return 0;
+}
+
+static void s3c64xx_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, s3c64xx_save_common,
+				ARRAY_SIZE(s3c64xx_clk_regs));
+
+	if (!is_s3c6400)
+		samsung_clk_restore(reg_base, s3c64xx_save_soc,
+					ARRAY_SIZE(s3c6410_clk_regs));
+}
+
+static struct syscore_ops s3c64xx_clk_syscore_ops = {
+	.suspend = s3c64xx_clk_suspend,
+	.resume = s3c64xx_clk_resume,
+};
+
+static void s3c64xx_clk_sleep_init(void)
+{
+	s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs,
+						ARRAY_SIZE(s3c64xx_clk_regs));
+	if (!s3c64xx_save_common)
+		goto err_warn;
+
+	if (!is_s3c6400) {
+		s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs,
+						ARRAY_SIZE(s3c6410_clk_regs));
+		if (!s3c64xx_save_soc)
+			goto err_soc;
+	}
+
+	register_syscore_ops(&s3c64xx_clk_syscore_ops);
+	return;
+
+err_soc:
+	kfree(s3c64xx_save_common);
+err_warn:
+	pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+		__func__);
+}
+#else
+static void s3c64xx_clk_sleep_init(void) {}
+#endif
+
 /* List of parent clocks common for all S3C64xx SoCs. */
 PNAME(spi_mmc_p)	= { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
 PNAME(uart_p)		= { "mout_epll", "dout_mpll" };
@@ -391,11 +453,11 @@ static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
 
 /* Register s3c64xx clocks. */
 void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
-			     unsigned long xusbxti_f, bool is_s3c6400,
-			     void __iomem *reg_base)
+			     unsigned long xusbxti_f, bool s3c6400,
+			     void __iomem *base)
 {
-	unsigned long *soc_regs = NULL;
-	unsigned long nr_soc_regs = 0;
+	reg_base = base;
+	is_s3c6400 = s3c6400;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -403,13 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
 			panic("%s: failed to map registers\n", __func__);
 	}
 
-	if (!is_s3c6400) {
-		soc_regs = s3c6410_clk_regs;
-		nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
-	}
-
-	samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
-			ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs);
+	samsung_clk_init(np, reg_base, NR_CLKS);
 
 	/* Register external clocks. */
 	if (!np)
@@ -452,6 +508,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
 
 	samsung_clk_register_alias(s3c64xx_clock_aliases,
 					ARRAY_SIZE(s3c64xx_clock_aliases));
+	s3c64xx_clk_sleep_init();
 
 	pr_info("%s clocks: apll = %lu, mpll = %lu\n"
 		"\tepll = %lu, arm_clk = %lu\n",
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index f503f32e2f80..91bec3ebdc8f 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -21,64 +21,45 @@ static void __iomem *reg_base;
 static struct clk_onecell_data clk_data;
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *reg_dump;
-static unsigned long nr_reg_dump;
-
-static int samsung_clk_suspend(void)
+void samsung_clk_save(void __iomem *base,
+				    struct samsung_clk_reg_dump *rd,
+				    unsigned int num_regs)
 {
-	struct samsung_clk_reg_dump *rd = reg_dump;
-	unsigned long i;
-
-	for (i = 0; i < nr_reg_dump; i++, rd++)
-		rd->value = __raw_readl(reg_base + rd->offset);
+	for (; num_regs > 0; --num_regs, ++rd)
+		rd->value = readl(base + rd->offset);
+}
 
-	return 0;
+void samsung_clk_restore(void __iomem *base,
+				      const struct samsung_clk_reg_dump *rd,
+				      unsigned int num_regs)
+{
+	for (; num_regs > 0; --num_regs, ++rd)
+		writel(rd->value, base + rd->offset);
 }
 
-static void samsung_clk_resume(void)
+struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
+						const unsigned long *rdump,
+						unsigned long nr_rdump)
 {
-	struct samsung_clk_reg_dump *rd = reg_dump;
-	unsigned long i;
+	struct samsung_clk_reg_dump *rd;
+	unsigned int i;
 
-	for (i = 0; i < nr_reg_dump; i++, rd++)
-		__raw_writel(rd->value, reg_base + rd->offset);
-}
+	rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
+	if (!rd)
+		return NULL;
+
+	for (i = 0; i < nr_rdump; ++i)
+		rd[i].offset = rdump[i];
 
-static struct syscore_ops samsung_clk_syscore_ops = {
-	.suspend	= samsung_clk_suspend,
-	.resume		= samsung_clk_resume,
-};
-#endif /* CONFIG_PM_SLEEP */
+	return rd;
+}
 
 /* setup the essentials required to support clock lookup using ccf */
 void __init samsung_clk_init(struct device_node *np, void __iomem *base,
-		unsigned long nr_clks, unsigned long *rdump,
-		unsigned long nr_rdump, unsigned long *soc_rdump,
-		unsigned long nr_soc_rdump)
+			     unsigned long nr_clks)
 {
 	reg_base = base;
 
-#ifdef CONFIG_PM_SLEEP
-	if (rdump && nr_rdump) {
-		unsigned int idx;
-		reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
-				* (nr_rdump + nr_soc_rdump), GFP_KERNEL);
-		if (!reg_dump) {
-			pr_err("%s: memory alloc for register dump failed\n",
-					__func__);
-			return;
-		}
-
-		for (idx = 0; idx < nr_rdump; idx++)
-			reg_dump[idx].offset = rdump[idx];
-		for (idx = 0; idx < nr_soc_rdump; idx++)
-			reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
-		nr_reg_dump = nr_rdump + nr_soc_rdump;
-		register_syscore_ops(&samsung_clk_syscore_ops);
-	}
-#endif
-
 	clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
 	if (!clk_table)
 		panic("could not allocate clock lookup table\n");
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 31b4174e7a5b..c7141ba826e0 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -313,9 +313,7 @@ struct samsung_pll_clock {
 		_lock, _con, _rtable, _alias)
 
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
-		unsigned long nr_clks, unsigned long *rdump,
-		unsigned long nr_rdump, unsigned long *soc_rdump,
-		unsigned long nr_soc_rdump);
+				    unsigned long nr_clks);
 extern void __init samsung_clk_of_register_fixed_ext(
 		struct samsung_fixed_rate_clock *fixed_rate_clk,
 		unsigned int nr_fixed_rate_clk,
@@ -340,4 +338,14 @@ extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
 
 extern unsigned long _get_rate(const char *clk_name);
 
+extern void samsung_clk_save(void __iomem *base,
+			     struct samsung_clk_reg_dump *rd,
+			     unsigned int num_regs);
+extern void samsung_clk_restore(void __iomem *base,
+				const struct samsung_clk_reg_dump *rd,
+				unsigned int num_regs);
+extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
+						const unsigned long *rdump,
+						unsigned long nr_rdump);
+
 #endif /* __SAMSUNG_CLK_H */
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c
index aac4756ec52e..f065f694cb65 100644
--- a/drivers/clk/shmobile/clk-div6.c
+++ b/drivers/clk/shmobile/clk-div6.c
@@ -23,7 +23,7 @@
 #define CPG_DIV6_DIV_MASK	0x3f
 
 /**
- * struct div6_clock - MSTP gating clock
+ * struct div6_clock - CPG 6 bit divider clock
  * @hw: handle between common and hardware-specific interfaces
  * @reg: IO-remapped register
  * @div: divisor value (1-64)
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index a59ec217a124..dd272a0d1446 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -186,7 +186,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
 			     const char *name)
 {
 	const struct clk_div_table *table = NULL;
-	const char *parent_name = "main";
+	const char *parent_name;
 	unsigned int shift;
 	unsigned int mult = 1;
 	unsigned int div = 1;
@@ -201,23 +201,31 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
 		 * the multiplier value.
 		 */
 		u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+		parent_name = "main";
 		mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
 	} else if (!strcmp(name, "pll1")) {
+		parent_name = "main";
 		mult = config->pll1_mult / 2;
 	} else if (!strcmp(name, "pll3")) {
+		parent_name = "main";
 		mult = config->pll3_mult;
 	} else if (!strcmp(name, "lb")) {
+		parent_name = "pll1_div2";
 		div = cpg_mode & BIT(18) ? 36 : 24;
 	} else if (!strcmp(name, "qspi")) {
+		parent_name = "pll1_div2";
 		div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2)
-		    ? 16 : 20;
+		    ? 8 : 10;
 	} else if (!strcmp(name, "sdh")) {
+		parent_name = "pll1_div2";
 		table = cpg_sdh_div_table;
 		shift = 8;
 	} else if (!strcmp(name, "sd0")) {
+		parent_name = "pll1_div2";
 		table = cpg_sd01_div_table;
 		shift = 4;
 	} else if (!strcmp(name, "sd1")) {
+		parent_name = "pll1_div2";
 		table = cpg_sd01_div_table;
 		shift = 0;
 	} else if (!strcmp(name, "z")) {
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 0303c0b99cd0..7e2d15a0c7b8 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -1 +1,4 @@
 obj-y += clk.o
+obj-y += clk-gate.o
+obj-y += clk-pll.o
+obj-y += clk-periph.o
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
new file mode 100644
index 000000000000..501d513bf890
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -0,0 +1,263 @@
+/*
+ *  Copyright 2011-2012 Calxeda, Inc.
+ *  Copyright (C) 2012-2013 Altera Corporation <www.altera.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.
+ *
+ * Based from clk-highbank.c
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#include "clk.h"
+
+#define SOCFPGA_L4_MP_CLK		"l4_mp_clk"
+#define SOCFPGA_L4_SP_CLK		"l4_sp_clk"
+#define SOCFPGA_NAND_CLK		"nand_clk"
+#define SOCFPGA_NAND_X_CLK		"nand_x_clk"
+#define SOCFPGA_MMC_CLK			"sdmmc_clk"
+#define SOCFPGA_GPIO_DB_CLK_OFFSET	0xA8
+
+#define div_mask(width)	((1 << (width)) - 1)
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+/* SDMMC Group for System Manager defines */
+#define SYSMGR_SDMMCGRP_CTRL_OFFSET    0x108
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
+
+static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
+{
+	u32 l4_src;
+	u32 perpll_src;
+
+	if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
+		l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
+		return l4_src &= 0x1;
+	}
+	if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
+		l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
+		return !!(l4_src & 2);
+	}
+
+	perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
+	if (streq(hwclk->init->name, SOCFPGA_MMC_CLK))
+		return perpll_src &= 0x3;
+	if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
+			streq(hwclk->init->name, SOCFPGA_NAND_X_CLK))
+			return (perpll_src >> 2) & 3;
+
+	/* QSPI clock */
+	return (perpll_src >> 4) & 3;
+
+}
+
+static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent)
+{
+	u32 src_reg;
+
+	if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
+		src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
+		src_reg &= ~0x1;
+		src_reg |= parent;
+		writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
+	} else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
+		src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
+		src_reg &= ~0x2;
+		src_reg |= (parent << 1);
+		writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
+	} else {
+		src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
+		if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) {
+			src_reg &= ~0x3;
+			src_reg |= parent;
+		} else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
+			streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) {
+			src_reg &= ~0xC;
+			src_reg |= (parent << 2);
+		} else {/* QSPI clock */
+			src_reg &= ~0x30;
+			src_reg |= (parent << 4);
+		}
+		writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
+	}
+
+	return 0;
+}
+
+static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
+	unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div)
+		div = socfpgaclk->fixed_div;
+	else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= div_mask(socfpgaclk->width);
+		/* Check for GPIO_DB_CLK by its offset */
+		if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET)
+			div = val + 1;
+		else
+			div = (1 << val);
+	}
+
+	return parent_rate / div;
+}
+
+static int socfpga_clk_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	struct regmap *sys_mgr_base_addr;
+	int i;
+	u32 hs_timing;
+	u32 clk_phase[2];
+
+	if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
+		sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+		if (IS_ERR(sys_mgr_base_addr)) {
+			pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < 2; i++) {
+			switch (socfpgaclk->clk_phase[i]) {
+			case 0:
+				clk_phase[i] = 0;
+				break;
+			case 45:
+				clk_phase[i] = 1;
+				break;
+			case 90:
+				clk_phase[i] = 2;
+				break;
+			case 135:
+				clk_phase[i] = 3;
+				break;
+			case 180:
+				clk_phase[i] = 4;
+				break;
+			case 225:
+				clk_phase[i] = 5;
+				break;
+			case 270:
+				clk_phase[i] = 6;
+				break;
+			case 315:
+				clk_phase[i] = 7;
+				break;
+			default:
+				clk_phase[i] = 0;
+				break;
+			}
+		}
+		hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+		regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET,
+			hs_timing);
+	}
+	return 0;
+}
+
+static struct clk_ops gateclk_ops = {
+	.prepare = socfpga_clk_prepare,
+	.recalc_rate = socfpga_clk_recalc_rate,
+	.get_parent = socfpga_clk_get_parent,
+	.set_parent = socfpga_clk_set_parent,
+};
+
+static void __init __socfpga_gate_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 clk_gate[2];
+	u32 div_reg[3];
+	u32 clk_phase[2];
+	u32 fixed_div;
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFPGA_MAX_PARENTS];
+	struct clk_init_data init;
+	int rc;
+	int i = 0;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return;
+
+	rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
+	if (rc)
+		clk_gate[0] = 0;
+
+	if (clk_gate[0]) {
+		socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0];
+		socfpga_clk->hw.bit_idx = clk_gate[1];
+
+		gateclk_ops.enable = clk_gate_ops.enable;
+		gateclk_ops.disable = clk_gate_ops.disable;
+	}
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		socfpga_clk->fixed_div = 0;
+	else
+		socfpga_clk->fixed_div = fixed_div;
+
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0];
+		socfpga_clk->shift = div_reg[1];
+		socfpga_clk->width = div_reg[2];
+	} else {
+		socfpga_clk->div_reg = 0;
+	}
+
+	rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
+	if (!rc) {
+		socfpga_clk->clk_phase[0] = clk_phase[0];
+		socfpga_clk->clk_phase[1] = clk_phase[1];
+	}
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	init.parent_names = parent_name;
+	init.num_parents = i;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (WARN_ON(rc))
+		return;
+}
+
+void __init socfpga_gate_init(struct device_node *node)
+{
+	__socfpga_gate_init(node, &gateclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
new file mode 100644
index 000000000000..81623a3736f9
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -0,0 +1,94 @@
+/*
+ *  Copyright 2011-2012 Calxeda, Inc.
+ *  Copyright (C) 2012-2013 Altera Corporation <www.altera.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.
+ *
+ * Based from clk-highbank.c
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+	u32 div;
+
+	if (socfpgaclk->fixed_div)
+		div = socfpgaclk->fixed_div;
+	else
+		div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
+
+	return parent_rate / div;
+}
+
+static const struct clk_ops periclk_ops = {
+	.recalc_rate = clk_periclk_recalc_rate,
+};
+
+static __init void __socfpga_periph_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+	u32 fixed_div;
+
+	of_property_read_u32(node, "reg", &reg);
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return;
+
+	periph_clk->hw.reg = clk_mgr_base_addr + reg;
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		periph_clk->fixed_div = 0;
+	else
+		periph_clk->fixed_div = fixed_div;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+void __init socfpga_periph_init(struct device_node *node)
+{
+	__socfpga_periph_init(node, &periclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
new file mode 100644
index 000000000000..88dafb5e9627
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -0,0 +1,131 @@
+/*
+ *  Copyright 2011-2012 Calxeda, Inc.
+ *  Copyright (C) 2012-2013 Altera Corporation <www.altera.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.
+ *
+ * Based from clk-highbank.c
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+/* Clock bypass bits */
+#define MAINPLL_BYPASS		(1<<0)
+#define SDRAMPLL_BYPASS		(1<<1)
+#define SDRAMPLL_SRC_BYPASS	(1<<2)
+#define PERPLL_BYPASS		(1<<3)
+#define PERPLL_SRC_BYPASS	(1<<4)
+
+#define SOCFPGA_PLL_BG_PWRDWN		0
+#define SOCFPGA_PLL_EXT_ENA		1
+#define SOCFPGA_PLL_PWR_DOWN		2
+#define SOCFPGA_PLL_DIVF_MASK		0x0000FFF8
+#define SOCFPGA_PLL_DIVF_SHIFT		3
+#define SOCFPGA_PLL_DIVQ_MASK		0x003F0000
+#define SOCFPGA_PLL_DIVQ_SHIFT		16
+
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	22
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long divf, divq, reg;
+	unsigned long long vco_freq;
+	unsigned long bypass;
+
+	reg = readl(socfpgaclk->hw.reg);
+	bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
+	if (bypass & MAINPLL_BYPASS)
+		return parent_rate;
+
+	divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
+	divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (divf + 1);
+	do_div(vco_freq, (1 + divq));
+	return (unsigned long)vco_freq;
+}
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	u32 pll_src;
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+			CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+};
+
+static __init struct clk *__socfpga_pll_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFPGA_MAX_PARENTS];
+	struct clk_init_data init;
+	int rc;
+	int i = 0;
+
+	of_property_read_u32(node, "reg", &reg);
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	pll_clk->hw.reg = clk_mgr_base_addr + reg;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+
+	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	init.num_parents = i;
+	init.parent_names = parent_name;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return clk;
+}
+
+void __init socfpga_pll_init(struct device_node *node)
+{
+	__socfpga_pll_init(node, &clk_pll_ops);
+}
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 5983a26a8c5f..6217d5dc6644 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -22,325 +22,23 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
-/* Clock Manager offsets */
-#define CLKMGR_CTRL	0x0
-#define CLKMGR_BYPASS	0x4
-#define CLKMGR_L4SRC	0x70
-#define CLKMGR_PERPLL_SRC	0xAC
+#include "clk.h"
 
-/* Clock bypass bits */
-#define MAINPLL_BYPASS		(1<<0)
-#define SDRAMPLL_BYPASS		(1<<1)
-#define SDRAMPLL_SRC_BYPASS	(1<<2)
-#define PERPLL_BYPASS		(1<<3)
-#define PERPLL_SRC_BYPASS	(1<<4)
+void __iomem *clk_mgr_base_addr;
 
-#define SOCFPGA_PLL_BG_PWRDWN		0
-#define SOCFPGA_PLL_EXT_ENA		1
-#define SOCFPGA_PLL_PWR_DOWN		2
-#define SOCFPGA_PLL_DIVF_MASK		0x0000FFF8
-#define SOCFPGA_PLL_DIVF_SHIFT	3
-#define SOCFPGA_PLL_DIVQ_MASK		0x003F0000
-#define SOCFPGA_PLL_DIVQ_SHIFT	16
-#define SOCFGPA_MAX_PARENTS	3
-
-#define SOCFPGA_L4_MP_CLK		"l4_mp_clk"
-#define SOCFPGA_L4_SP_CLK		"l4_sp_clk"
-#define SOCFPGA_NAND_CLK		"nand_clk"
-#define SOCFPGA_NAND_X_CLK		"nand_x_clk"
-#define SOCFPGA_MMC_CLK			"sdmmc_clk"
-#define SOCFPGA_DB_CLK			"gpio_db_clk"
-
-#define div_mask(width)	((1 << (width)) - 1)
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-extern void __iomem *clk_mgr_base_addr;
-
-struct socfpga_clk {
-	struct clk_gate hw;
-	char *parent_name;
-	char *clk_name;
-	u32 fixed_div;
-	void __iomem *div_reg;
-	u32 width;	/* only valid if div_reg != 0 */
-	u32 shift;	/* only valid if div_reg != 0 */
-};
-#define to_socfpga_clk(p) container_of(p, struct socfpga_clk, hw.hw)
-
-static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
-					 unsigned long parent_rate)
-{
-	struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
-	unsigned long divf, divq, vco_freq, reg;
-	unsigned long bypass;
-
-	reg = readl(socfpgaclk->hw.reg);
-	bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
-	if (bypass & MAINPLL_BYPASS)
-		return parent_rate;
-
-	divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
-	divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
-	vco_freq = parent_rate * (divf + 1);
-	return vco_freq / (1 + divq);
-}
-
-
-static struct clk_ops clk_pll_ops = {
-	.recalc_rate = clk_pll_recalc_rate,
-};
-
-static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
-					     unsigned long parent_rate)
-{
-	struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
-	u32 div;
-
-	if (socfpgaclk->fixed_div)
-		div = socfpgaclk->fixed_div;
-	else
-		div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
-
-	return parent_rate / div;
-}
-
-static const struct clk_ops periclk_ops = {
-	.recalc_rate = clk_periclk_recalc_rate,
-};
-
-static __init struct clk *socfpga_clk_init(struct device_node *node,
-	const struct clk_ops *ops)
-{
-	u32 reg;
-	struct clk *clk;
-	struct socfpga_clk *socfpga_clk;
-	const char *clk_name = node->name;
-	const char *parent_name;
-	struct clk_init_data init;
-	int rc;
-	u32 fixed_div;
-
-	of_property_read_u32(node, "reg", &reg);
-
-	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
-	if (WARN_ON(!socfpga_clk))
-		return NULL;
-
-	socfpga_clk->hw.reg = clk_mgr_base_addr + reg;
-
-	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
-	if (rc)
-		socfpga_clk->fixed_div = 0;
-	else
-		socfpga_clk->fixed_div = fixed_div;
-
-	of_property_read_string(node, "clock-output-names", &clk_name);
-
-	init.name = clk_name;
-	init.ops = ops;
-	init.flags = 0;
-	parent_name = of_clk_get_parent_name(node, 0);
-	init.parent_names = &parent_name;
-	init.num_parents = 1;
-
-	socfpga_clk->hw.hw.init = &init;
-
-	if (streq(clk_name, "main_pll") ||
-		streq(clk_name, "periph_pll") ||
-		streq(clk_name, "sdram_pll")) {
-		socfpga_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
-		clk_pll_ops.enable = clk_gate_ops.enable;
-		clk_pll_ops.disable = clk_gate_ops.disable;
-	}
-
-	clk = clk_register(NULL, &socfpga_clk->hw.hw);
-	if (WARN_ON(IS_ERR(clk))) {
-		kfree(socfpga_clk);
-		return NULL;
-	}
-	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	return clk;
-}
-
-static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
-{
-	u32 l4_src;
-	u32 perpll_src;
-
-	if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
-		l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
-		return l4_src &= 0x1;
-	}
-	if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
-		l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
-		return !!(l4_src & 2);
-	}
-
-	perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
-	if (streq(hwclk->init->name, SOCFPGA_MMC_CLK))
-		return perpll_src &= 0x3;
-	if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
-			streq(hwclk->init->name, SOCFPGA_NAND_X_CLK))
-			return (perpll_src >> 2) & 3;
-
-	/* QSPI clock */
-	return (perpll_src >> 4) & 3;
-
-}
-
-static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent)
-{
-	u32 src_reg;
-
-	if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
-		src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
-		src_reg &= ~0x1;
-		src_reg |= parent;
-		writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
-	} else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
-		src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
-		src_reg &= ~0x2;
-		src_reg |= (parent << 1);
-		writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
-	} else {
-		src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
-		if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) {
-			src_reg &= ~0x3;
-			src_reg |= parent;
-		} else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
-			streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) {
-			src_reg &= ~0xC;
-			src_reg |= (parent << 2);
-		} else {/* QSPI clock */
-			src_reg &= ~0x30;
-			src_reg |= (parent << 4);
-		}
-		writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
-	}
-
-	return 0;
-}
-
-static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
-	unsigned long parent_rate)
-{
-	struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
-	u32 div = 1, val;
-
-	if (socfpgaclk->fixed_div)
-		div = socfpgaclk->fixed_div;
-	else if (socfpgaclk->div_reg) {
-		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-		val &= div_mask(socfpgaclk->width);
-		if (streq(hwclk->init->name, SOCFPGA_DB_CLK))
-			div = val + 1;
-		else
-			div = (1 << val);
-	}
-
-	return parent_rate / div;
-}
-
-static struct clk_ops gateclk_ops = {
-	.recalc_rate = socfpga_clk_recalc_rate,
-	.get_parent = socfpga_clk_get_parent,
-	.set_parent = socfpga_clk_set_parent,
+static struct of_device_id socfpga_child_clocks[] = {
+	{ .compatible = "altr,socfpga-pll-clock", socfpga_pll_init, },
+	{ .compatible = "altr,socfpga-perip-clk", socfpga_periph_init, },
+	{ .compatible = "altr,socfpga-gate-clk", socfpga_gate_init, },
+	{},
 };
 
-static void __init socfpga_gate_clk_init(struct device_node *node,
-	const struct clk_ops *ops)
-{
-	u32 clk_gate[2];
-	u32 div_reg[3];
-	u32 fixed_div;
-	struct clk *clk;
-	struct socfpga_clk *socfpga_clk;
-	const char *clk_name = node->name;
-	const char *parent_name[SOCFGPA_MAX_PARENTS];
-	struct clk_init_data init;
-	int rc;
-	int i = 0;
-
-	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
-	if (WARN_ON(!socfpga_clk))
-		return;
-
-	rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
-	if (rc)
-		clk_gate[0] = 0;
-
-	if (clk_gate[0]) {
-		socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0];
-		socfpga_clk->hw.bit_idx = clk_gate[1];
-
-		gateclk_ops.enable = clk_gate_ops.enable;
-		gateclk_ops.disable = clk_gate_ops.disable;
-	}
-
-	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
-	if (rc)
-		socfpga_clk->fixed_div = 0;
-	else
-		socfpga_clk->fixed_div = fixed_div;
-
-	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
-	if (!rc) {
-		socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0];
-		socfpga_clk->shift = div_reg[1];
-		socfpga_clk->width = div_reg[2];
-	} else {
-		socfpga_clk->div_reg = NULL;
-	}
-
-	of_property_read_string(node, "clock-output-names", &clk_name);
-
-	init.name = clk_name;
-	init.ops = ops;
-	init.flags = 0;
-	while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
-			of_clk_get_parent_name(node, i)) != NULL)
-		i++;
-
-	init.parent_names = parent_name;
-	init.num_parents = i;
-	socfpga_clk->hw.hw.init = &init;
-
-	clk = clk_register(NULL, &socfpga_clk->hw.hw);
-	if (WARN_ON(IS_ERR(clk))) {
-		kfree(socfpga_clk);
-		return;
-	}
-	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	if (WARN_ON(rc))
-		return;
-}
-
-static void __init socfpga_pll_init(struct device_node *node)
+static void __init socfpga_clkmgr_init(struct device_node *node)
 {
-	socfpga_clk_init(node, &clk_pll_ops);
+	clk_mgr_base_addr = of_iomap(node, 0);
+	of_clk_init(socfpga_child_clocks);
 }
-CLK_OF_DECLARE(socfpga_pll, "altr,socfpga-pll-clock", socfpga_pll_init);
+CLK_OF_DECLARE(socfpga_mgr, "altr,clk-mgr", socfpga_clkmgr_init);
 
-static void __init socfpga_periph_init(struct device_node *node)
-{
-	socfpga_clk_init(node, &periclk_ops);
-}
-CLK_OF_DECLARE(socfpga_periph, "altr,socfpga-perip-clk", socfpga_periph_init);
-
-static void __init socfpga_gate_init(struct device_node *node)
-{
-	socfpga_gate_clk_init(node, &gateclk_ops);
-}
-CLK_OF_DECLARE(socfpga_gate, "altr,socfpga-gate-clk", socfpga_gate_init);
-
-void __init socfpga_init_clocks(void)
-{
-	struct clk *clk;
-	int ret;
-
-	clk = clk_register_fixed_factor(NULL, "smp_twd", "mpuclk", 0, 1, 4);
-	ret = clk_register_clkdev(clk, NULL, "smp_twd");
-	if (ret)
-		pr_err("smp_twd alias not registered\n");
-}
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
new file mode 100644
index 000000000000..d2e54019c94f
--- /dev/null
+++ b/drivers/clk/socfpga/clk.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * based on drivers/clk/tegra/clk.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef __SOCFPGA_CLK_H
+#define __SOCFPGA_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+/* Clock Manager offsets */
+#define CLKMGR_CTRL		0x0
+#define CLKMGR_BYPASS		0x4
+#define CLKMGR_L4SRC		0x70
+#define CLKMGR_PERPLL_SRC	0xAC
+
+#define SOCFPGA_MAX_PARENTS		3
+
+extern void __iomem *clk_mgr_base_addr;
+
+void __init socfpga_pll_init(struct device_node *node);
+void __init socfpga_periph_init(struct device_node *node);
+void __init socfpga_gate_init(struct device_node *node);
+
+struct socfpga_pll {
+	struct clk_gate	hw;
+};
+
+struct socfpga_gate_clk {
+	struct clk_gate hw;
+	char *parent_name;
+	u32 fixed_div;
+	void __iomem *div_reg;
+	u32 width;	/* only valid if div_reg != 0 */
+	u32 shift;	/* only valid if div_reg != 0 */
+	u32 clk_phase[2];
+};
+
+struct socfpga_periph_clk {
+	struct clk_gate hw;
+	char *parent_name;
+	u32 fixed_div;
+};
+
+#endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index 4d75b1f37e3a..290f9c1a3749 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -59,7 +59,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate,
 		return 0;
 
 	if (divider_ux1 > get_max_div(divider))
-		return -EINVAL;
+		return get_max_div(divider);
 
 	return divider_ux1;
 }
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index cf0c323f2c36..c39613c519af 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -180,9 +180,13 @@ enum clk_id {
 	tegra_clk_sbc6_8,
 	tegra_clk_sclk,
 	tegra_clk_sdmmc1,
+	tegra_clk_sdmmc1_8,
 	tegra_clk_sdmmc2,
+	tegra_clk_sdmmc2_8,
 	tegra_clk_sdmmc3,
+	tegra_clk_sdmmc3_8,
 	tegra_clk_sdmmc4,
+	tegra_clk_sdmmc4_8,
 	tegra_clk_se,
 	tegra_clk_soc_therm,
 	tegra_clk_sor0,
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 356e9b804421..9e899c18af86 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -130,7 +130,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = {
 	.disable = clk_periph_disable,
 };
 
-const struct clk_ops tegra_clk_periph_no_gate_ops = {
+static const struct clk_ops tegra_clk_periph_no_gate_ops = {
 	.get_parent = clk_periph_get_parent,
 	.set_parent = clk_periph_set_parent,
 	.recalc_rate = clk_periph_recalc_rate,
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index 5c35885f4a7c..1fa5c3f33b20 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -371,9 +371,7 @@ static const char *mux_pllp3_pllc_clkm[] = {
 static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = {
 	"pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m"
 };
-static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = {
-	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
-};
+#define mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx NULL
 
 static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = {
 	"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4",
@@ -465,6 +463,10 @@ static struct tegra_periph_init_data periph_clks[] = {
 	MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
 	MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
 	MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+	MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8),
+	MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8),
+	MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8),
+	MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4_8),
 	MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
 	MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
 	MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
@@ -492,7 +494,7 @@ static struct tegra_periph_init_data periph_clks[] = {
 	UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
 	UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
 	UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
-	UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte),
+	UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte),
 	XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
 	XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
 	XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c
index 05dce4aa2c11..feb3201c85ce 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -120,7 +120,7 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
 					ARRAY_SIZE(cclk_lp_parents),
 					CLK_SET_RATE_PARENT,
 					clk_base + CCLKLP_BURST_POLICY,
-					0, 4, 8, 9, NULL);
+					TEGRA_DIVIDER_2, 4, 8, 9, NULL);
 		*dt_clk = clk;
 	}
 
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 90d9d25f2228..80431f0fb268 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -682,12 +682,12 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true },
 	[tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true },
 	[tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true },
-	[tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true },
+	[tegra_clk_sdmmc2_8] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true },
 	[tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true },
 	[tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true },
 	[tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true },
-	[tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true },
-	[tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true },
+	[tegra_clk_sdmmc1_8] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true },
+	[tegra_clk_sdmmc4_8] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true },
 	[tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true },
 	[tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true },
 	[tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true },
@@ -723,7 +723,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true },
 	[tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true },
 	[tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true },
-	[tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true },
+	[tegra_clk_sdmmc3_8] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true },
 	[tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true },
 	[tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true },
 	[tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true },
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index aff86b5bc745..166e02f16c8a 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -516,11 +516,11 @@ static struct div_nmp pllp_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{12000000, 216000000, 432, 12, 1, 8},
-	{13000000, 216000000, 432, 13, 1, 8},
-	{16800000, 216000000, 360, 14, 1, 8},
-	{19200000, 216000000, 360, 16, 1, 8},
-	{26000000, 216000000, 432, 26, 1, 8},
+	{12000000, 408000000, 408, 12, 0, 8},
+	{13000000, 408000000, 408, 13, 0, 8},
+	{16800000, 408000000, 340, 14, 0, 8},
+	{19200000, 408000000, 340, 16, 0, 8},
+	{26000000, 408000000, 408, 26, 0, 8},
 	{0, 0, 0, 0, 0, 0},
 };
 
@@ -570,6 +570,15 @@ static struct tegra_clk_pll_params pll_a_params = {
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
 };
 
+static struct div_nmp plld_nmp = {
+	.divm_shift = 0,
+	.divm_width = 5,
+	.divn_shift = 8,
+	.divn_width = 11,
+	.divp_shift = 20,
+	.divp_width = 3,
+};
+
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
 	{12000000, 216000000, 864, 12, 4, 12},
 	{13000000, 216000000, 864, 13, 4, 12},
@@ -603,19 +612,18 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.lock_mask = PLL_BASE_LOCK,
 	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
 	.lock_delay = 1000,
-	.div_nmp = &pllp_nmp,
+	.div_nmp = &plld_nmp,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
 		 TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = {
-	{ 12000000, 148500000,  99, 1, 8},
-	{ 12000000, 594000000,  99, 1, 1},
-	{ 13000000, 594000000,  91, 1, 1},      /* actual: 591.5 MHz */
-	{ 16800000, 594000000,  71, 1, 1},      /* actual: 596.4 MHz */
-	{ 19200000, 594000000,  62, 1, 1},      /* actual: 595.2 MHz */
-	{ 26000000, 594000000,  91, 2, 1},      /* actual: 591.5 MHz */
+	{ 12000000, 594000000,  99, 1, 2},
+	{ 13000000, 594000000,  91, 1, 2},      /* actual: 591.5 MHz */
+	{ 16800000, 594000000,  71, 1, 2},      /* actual: 596.4 MHz */
+	{ 19200000, 594000000,  62, 1, 2},      /* actual: 595.2 MHz */
+	{ 26000000, 594000000,  91, 2, 2},      /* actual: 591.5 MHz */
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -753,21 +761,19 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true },
 	[tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true },
 	[tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true },
-	[tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
+	[tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
 	[tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true },
 	[tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true },
 	[tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true },
-	[tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
-	[tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
+	[tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
+	[tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
 	[tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true },
 	[tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true },
-	[tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true },
 	[tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true },
 	[tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true },
-	[tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true },
 	[tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true },
 	[tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true },
-	[tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true },
+	[tegra_clk_host1x_8] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true },
 	[tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true },
 	[tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true },
 	[tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true },
@@ -794,7 +800,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true },
 	[tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true },
 	[tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true },
-	[tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true },
+	[tegra_clk_sdmmc3_8] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true },
 	[tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true },
 	[tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true },
 	[tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true },
@@ -1286,9 +1292,9 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
 	clk_register_clkdev(clk, "pll_d2", NULL);
 	clks[TEGRA124_CLK_PLL_D2] = clk;
 
-	/* PLLD2_OUT0 ?? */
+	/* PLLD2_OUT0 */
 	clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
-					CLK_SET_RATE_PARENT, 1, 2);
+					CLK_SET_RATE_PARENT, 1, 1);
 	clk_register_clkdev(clk, "pll_d2_out0", NULL);
 	clks[TEGRA124_CLK_PLL_D2_OUT0] = clk;
 
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index dbace152b2fa..dace2b1b5ae6 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -574,6 +574,8 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true },
 	[tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true },
 	[tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
+	[tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
+	[tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
index 776ee4594bd4..028b33783d38 100644
--- a/drivers/clk/ti/clk-33xx.c
+++ b/drivers/clk/ti/clk-33xx.c
@@ -34,7 +34,6 @@ static struct ti_dt_clk am33xx_clks[] = {
 	DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"),
 	DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"),
 	DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
-	DT_CLK("cpu0", NULL, "dpll_mpu_ck"),
 	DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
 	DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"),
 	DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"),
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index a15e445570b2..e6aa10db7bba 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -112,7 +112,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
 		return parent_rate;
 	}
 
-	return parent_rate / div;
+	return DIV_ROUND_UP(parent_rate, div);
 }
 
 /*
@@ -182,7 +182,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 		}
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
 				MULT_ROUND_UP(rate, i));
-		now = parent_rate / i;
+		now = DIV_ROUND_UP(parent_rate, i);
 		if (now <= rate && now > best) {
 			bestdiv = i;
 			best = now;
@@ -205,7 +205,7 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 	int div;
 	div = ti_clk_divider_bestdiv(hw, rate, prate);
 
-	return *prate / div;
+	return DIV_ROUND_UP(*prate, div);
 }
 
 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -216,7 +216,7 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags = 0;
 	u32 val;
 
-	div = parent_rate / rate;
+	div = DIV_ROUND_UP(parent_rate, rate);
 	value = _get_val(divider, div);
 
 	if (value > div_mask(divider))
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index cdeff299de26..7b55ef89baa5 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -29,7 +29,8 @@ static struct clk *prcc_kclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_C
 #define PRCC_KCLK_STORE(clk, base, bit)        \
 	prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk
 
-struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, void *data)
+static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec,
+				     void *data)
 {
 	struct clk **clk_data = data;
 	unsigned int base, bit;
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index 8cbfcf88fae3..a820b0cfcf57 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -33,7 +33,7 @@ struct clk_icst {
 	struct clk_hw hw;
 	void __iomem *vcoreg;
 	void __iomem *lockreg;
-	const struct icst_params *params;
+	struct icst_params *params;
 	unsigned long rate;
 };
 
@@ -84,6 +84,8 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw,
 	struct clk_icst *icst = to_icst(hw);
 	struct icst_vco vco;
 
+	if (parent_rate)
+		icst->params->ref = parent_rate;
 	vco = vco_get(icst->vcoreg);
 	icst->rate = icst_hz(icst->params, vco);
 	return icst->rate;
@@ -105,6 +107,8 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_icst *icst = to_icst(hw);
 	struct icst_vco vco;
 
+	if (parent_rate)
+		icst->params->ref = parent_rate;
 	vco = icst_hz_to_vco(icst->params, rate);
 	icst->rate = icst_hz(icst->params, vco);
 	vco_set(icst->lockreg, icst->vcoreg, vco);
@@ -120,24 +124,33 @@ static const struct clk_ops icst_ops = {
 struct clk *icst_clk_register(struct device *dev,
 			const struct clk_icst_desc *desc,
 			const char *name,
+			const char *parent_name,
 			void __iomem *base)
 {
 	struct clk *clk;
 	struct clk_icst *icst;
 	struct clk_init_data init;
+	struct icst_params *pclone;
 
 	icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
 	if (!icst) {
 		pr_err("could not allocate ICST clock!\n");
 		return ERR_PTR(-ENOMEM);
 	}
+
+	pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
+	if (!pclone) {
+		pr_err("could not clone ICST params\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
 	init.name = name;
 	init.ops = &icst_ops;
 	init.flags = CLK_IS_ROOT;
-	init.parent_names = NULL;
-	init.num_parents = 0;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
 	icst->hw.init = &init;
-	icst->params = desc->params;
+	icst->params = pclone;
 	icst->vcoreg = base + desc->vco_offset;
 	icst->lockreg = base + desc->lock_offset;
 
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
index be99dd0da785..04e6f0aef588 100644
--- a/drivers/clk/versatile/clk-icst.h
+++ b/drivers/clk/versatile/clk-icst.h
@@ -16,4 +16,5 @@ struct clk_icst_desc {
 struct clk *icst_clk_register(struct device *dev,
 			      const struct clk_icst_desc *desc,
 			      const char *name,
+			      const char *parent_name,
 			      void __iomem *base);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
index 844f8d711a12..6d8b8e1a080a 100644
--- a/drivers/clk/versatile/clk-impd1.c
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -93,13 +93,15 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
 	imc = &impd1_clks[id];
 
 	imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
-	clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base);
+	clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL,
+				base);
 	imc->vco1clk = clk;
 	imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
 
 	/* VCO2 is also called "CLK2" */
 	imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
-	clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base);
+	clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, NULL,
+				base);
 	imc->vco2clk = clk;
 
 	/* MMCI uses CLK2 right off */
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
index bda8967e09c2..734c4b8fe6ab 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -10,21 +10,17 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
-#include <linux/platform_data/clk-integrator.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "clk-icst.h"
 
-/*
- * Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
- * Inspired by portions of:
- * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
- */
+#define INTEGRATOR_HDR_LOCK_OFFSET	0x14
 
-static const struct icst_params cp_auxvco_params = {
-	.ref		= 24000000,
+/* Base offset for the core module */
+static void __iomem *cm_base;
+
+static const struct icst_params cp_auxosc_params = {
 	.vco_max	= ICST525_VCO_MAX_5V,
 	.vco_min	= ICST525_VCO_MIN,
 	.vd_min 	= 8,
@@ -35,50 +31,39 @@ static const struct icst_params cp_auxvco_params = {
 	.idx2s		= icst525_idx2s,
 };
 
-static const struct clk_icst_desc __initdata cp_icst_desc = {
-	.params = &cp_auxvco_params,
+static const struct clk_icst_desc __initdata cm_auxosc_desc = {
+	.params = &cp_auxosc_params,
 	.vco_offset = 0x1c,
 	.lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
 };
 
-/*
- * integrator_clk_init() - set up the integrator clock tree
- * @is_cp: pass true if it's the Integrator/CP else AP is assumed
- */
-void __init integrator_clk_init(bool is_cp)
+static void __init of_integrator_cm_osc_setup(struct device_node *np)
 {
-	struct clk *clk;
-
-	/* APB clock dummy */
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
-	/* UART reference clock */
-	clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
-				14745600);
-	clk_register_clkdev(clk, NULL, "uart0");
-	clk_register_clkdev(clk, NULL, "uart1");
-	if (is_cp)
-		clk_register_clkdev(clk, NULL, "mmci");
-
-	/* 24 MHz clock */
-	clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
-				24000000);
-	clk_register_clkdev(clk, NULL, "kmi0");
-	clk_register_clkdev(clk, NULL, "kmi1");
-	if (!is_cp)
-		clk_register_clkdev(clk, NULL, "ap_timer");
+	struct clk *clk = ERR_PTR(-EINVAL);
+	const char *clk_name = np->name;
+	const struct clk_icst_desc *desc = &cm_auxosc_desc;
+	const char *parent_name;
 
-	if (!is_cp)
-		return;
+	if (!cm_base) {
+		/* Remap the core module base if not done yet */
+		struct device_node *parent;
 
-	/* 1 MHz clock */
-	clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
-				1000000);
-	clk_register_clkdev(clk, NULL, "sp804");
+		parent = of_get_parent(np);
+		if (!np) {
+			pr_err("no parent on core module clock\n");
+			return;
+		}
+		cm_base = of_iomap(parent, 0);
+		if (!cm_base) {
+			pr_err("could not remap core module base\n");
+			return;
+		}
+	}
 
-	/* ICST VCO clock used on the Integrator/CP CLCD */
-	clk = icst_clk_register(NULL, &cp_icst_desc, "icst",
-				__io_address(INTEGRATOR_HDR_BASE));
-	clk_register_clkdev(clk, NULL, "clcd");
+	parent_name = of_clk_get_parent_name(np, 0);
+	clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base);
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(integrator_cm_auxosc_clk,
+	"arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
index 747e7b31117c..c8b523117fb7 100644
--- a/drivers/clk/versatile/clk-realview.c
+++ b/drivers/clk/versatile/clk-realview.c
@@ -85,10 +85,10 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
 	/* ICST VCO clock */
 	if (is_pb1176)
 		clk = icst_clk_register(NULL, &realview_osc0_desc,
-					"osc0", sysbase);
+					"osc0", NULL, sysbase);
 	else
 		clk = icst_clk_register(NULL, &realview_osc4_desc,
-					"osc4", sysbase);
+					"osc4", NULL, sysbase);
 
 	clk_register_clkdev(clk, NULL, "dev:clcd");
 	clk_register_clkdev(clk, NULL, "issp:clcd");
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 09dd0173ea0a..e726c1b11218 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -148,7 +148,7 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
 	clks[fclk] = clk_register_gate(NULL, clk_name,
 			div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg,
 			0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock);
-	enable_reg = readl(fclk_gate_reg) & 1;
+	enable_reg = clk_readl(fclk_gate_reg) & 1;
 	if (enable && !enable_reg) {
 		if (clk_prepare_enable(clks[fclk]))
 			pr_warn("%s: FCLK%u enable failed\n", __func__,
@@ -277,7 +277,7 @@ static void __init zynq_clk_setup(struct device_node *np)
 			SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock);
 
 	/* CPU clocks */
-	tmp = readl(SLCR_621_TRUE) & 1;
+	tmp = clk_readl(SLCR_621_TRUE) & 1;
 	clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4,
 			CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0,
 			&armclk_lock);
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c
index 3226f54fa595..cec97596fe65 100644
--- a/drivers/clk/zynq/pll.c
+++ b/drivers/clk/zynq/pll.c
@@ -90,7 +90,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
 	 * makes probably sense to redundantly save fbdiv in the struct
 	 * zynq_pll to save the IO access.
 	 */
-	fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
+	fbdiv = (clk_readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
 			PLLCTRL_FBDIV_SHIFT;
 
 	return parent_rate * fbdiv;
@@ -112,7 +112,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw)
 
 	spin_lock_irqsave(clk->lock, flags);
 
-	reg = readl(clk->pll_ctrl);
+	reg = clk_readl(clk->pll_ctrl);
 
 	spin_unlock_irqrestore(clk->lock, flags);
 
@@ -138,10 +138,10 @@ static int zynq_pll_enable(struct clk_hw *hw)
 	/* Power up PLL and wait for lock */
 	spin_lock_irqsave(clk->lock, flags);
 
-	reg = readl(clk->pll_ctrl);
+	reg = clk_readl(clk->pll_ctrl);
 	reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
-	writel(reg, clk->pll_ctrl);
-	while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
+	clk_writel(reg, clk->pll_ctrl);
+	while (!(clk_readl(clk->pll_status) & (1 << clk->lockbit)))
 		;
 
 	spin_unlock_irqrestore(clk->lock, flags);
@@ -168,9 +168,9 @@ static void zynq_pll_disable(struct clk_hw *hw)
 	/* shut down PLL */
 	spin_lock_irqsave(clk->lock, flags);
 
-	reg = readl(clk->pll_ctrl);
+	reg = clk_readl(clk->pll_ctrl);
 	reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
-	writel(reg, clk->pll_ctrl);
+	clk_writel(reg, clk->pll_ctrl);
 
 	spin_unlock_irqrestore(clk->lock, flags);
 }
@@ -225,9 +225,9 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent,
 
 	spin_lock_irqsave(pll->lock, flags);
 
-	reg = readl(pll->pll_ctrl);
+	reg = clk_readl(pll->pll_ctrl);
 	reg &= ~PLLCTRL_BPQUAL_MASK;
-	writel(reg, pll->pll_ctrl);
+	clk_writel(reg, pll->pll_ctrl);
 
 	spin_unlock_irqrestore(pll->lock, flags);
 
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cd6950fd8caf..6510ec4f45ff 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -140,3 +140,6 @@ config VF_PIT_TIMER
 	bool
 	help
 	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
+
+config CLKSRC_QCOM
+	bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index c7ca50a9c232..fb0d82e08358 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,6 +1,5 @@
 obj-$(CONFIG_CLKSRC_OF)	+= clksrc-of.o
 obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o
-obj-$(CONFIG_X86_CYCLONE_TIMER)	+= cyclone.o
 obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
 obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
@@ -32,6 +31,7 @@ obj-$(CONFIG_CLKSRC_EFM32)	+= time-efm32.o
 obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= samsung_pwm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o
+obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
deleted file mode 100644
index 9e0998f22885..000000000000
--- a/drivers/clocksource/cyclone.c
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <linux/clocksource.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/timex.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#include <asm/mach_timer.h>
-
-#define CYCLONE_CBAR_ADDR	0xFEB00CD0	/* base address ptr */
-#define CYCLONE_PMCC_OFFSET	0x51A0		/* offset to control register */
-#define CYCLONE_MPCS_OFFSET	0x51A8		/* offset to select register */
-#define CYCLONE_MPMC_OFFSET	0x51D0		/* offset to count register */
-#define CYCLONE_TIMER_FREQ	99780000	/* 100Mhz, but not really */
-#define CYCLONE_TIMER_MASK	CLOCKSOURCE_MASK(32) /* 32 bit mask */
-
-int use_cyclone = 0;
-static void __iomem *cyclone_ptr;
-
-static cycle_t read_cyclone(struct clocksource *cs)
-{
-	return (cycle_t)readl(cyclone_ptr);
-}
-
-static struct clocksource clocksource_cyclone = {
-	.name		= "cyclone",
-	.rating		= 250,
-	.read		= read_cyclone,
-	.mask		= CYCLONE_TIMER_MASK,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init init_cyclone_clocksource(void)
-{
-	unsigned long base;	/* saved value from CBAR */
-	unsigned long offset;
-	u32 __iomem* volatile cyclone_timer;	/* Cyclone MPMC0 register */
-	u32 __iomem* reg;
-	int i;
-
-	/* make sure we're on a summit box: */
-	if (!use_cyclone)
-		return -ENODEV;
-
-	printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
-
-	/* find base address: */
-	offset = CYCLONE_CBAR_ADDR;
-	reg = ioremap_nocache(offset, sizeof(reg));
-	if (!reg) {
-		printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
-		return -ENODEV;
-	}
-	/* even on 64bit systems, this is only 32bits: */
-	base = readl(reg);
-	iounmap(reg);
-	if (!base) {
-		printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
-		return -ENODEV;
-	}
-
-	/* setup PMCC: */
-	offset = base + CYCLONE_PMCC_OFFSET;
-	reg = ioremap_nocache(offset, sizeof(reg));
-	if (!reg) {
-		printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
-		return -ENODEV;
-	}
-	writel(0x00000001,reg);
-	iounmap(reg);
-
-	/* setup MPCS: */
-	offset = base + CYCLONE_MPCS_OFFSET;
-	reg = ioremap_nocache(offset, sizeof(reg));
-	if (!reg) {
-		printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
-		return -ENODEV;
-	}
-	writel(0x00000001,reg);
-	iounmap(reg);
-
-	/* map in cyclone_timer: */
-	offset = base + CYCLONE_MPMC_OFFSET;
-	cyclone_timer = ioremap_nocache(offset, sizeof(u64));
-	if (!cyclone_timer) {
-		printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
-		return -ENODEV;
-	}
-
-	/* quick test to make sure its ticking: */
-	for (i = 0; i < 3; i++){
-		u32 old = readl(cyclone_timer);
-		int stall = 100;
-
-		while (stall--)
-			barrier();
-
-		if (readl(cyclone_timer) == old) {
-			printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
-			iounmap(cyclone_timer);
-			cyclone_timer = NULL;
-			return -ENODEV;
-		}
-	}
-	cyclone_ptr = cyclone_timer;
-
-	return clocksource_register_hz(&clocksource_cyclone,
-					CYCLONE_TIMER_FREQ);
-}
-
-arch_initcall(init_cyclone_clocksource);
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 48f76bc05da0..ed49b25fa552 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -25,8 +25,6 @@
 #include <linux/of_address.h>
 #include <linux/clocksource.h>
 
-#include <asm/mach/time.h>
-
 #define EXYNOS4_MCTREG(x)		(x)
 #define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
 #define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
new file mode 100644
index 000000000000..e807acf4c665
--- /dev/null
+++ b/drivers/clocksource/qcom-timer.c
@@ -0,0 +1,330 @@
+/*
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved.
+ *
+ * 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/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#define TIMER_MATCH_VAL			0x0000
+#define TIMER_COUNT_VAL			0x0004
+#define TIMER_ENABLE			0x0008
+#define TIMER_ENABLE_CLR_ON_MATCH_EN	BIT(1)
+#define TIMER_ENABLE_EN			BIT(0)
+#define TIMER_CLEAR			0x000C
+#define DGT_CLK_CTL			0x10
+#define DGT_CLK_CTL_DIV_4		0x3
+#define TIMER_STS_GPT0_CLR_PEND		BIT(10)
+
+#define GPT_HZ 32768
+
+#define MSM_DGT_SHIFT 5
+
+static void __iomem *event_base;
+static void __iomem *sts_base;
+
+static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	/* Stop the timer tick */
+	if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
+		u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+		ctrl &= ~TIMER_ENABLE_EN;
+		writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+	}
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static int msm_timer_set_next_event(unsigned long cycles,
+				    struct clock_event_device *evt)
+{
+	u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+
+	ctrl &= ~TIMER_ENABLE_EN;
+	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+
+	writel_relaxed(ctrl, event_base + TIMER_CLEAR);
+	writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
+
+	if (sts_base)
+		while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
+			cpu_relax();
+
+	writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
+	return 0;
+}
+
+static void msm_timer_set_mode(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
+{
+	u32 ctrl;
+
+	ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+	ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* Timer is enabled in set_next_event */
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+	}
+	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+}
+
+static struct clock_event_device __percpu *msm_evt;
+
+static void __iomem *source_base;
+
+static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
+{
+	return readl_relaxed(source_base + TIMER_COUNT_VAL);
+}
+
+static struct clocksource msm_clocksource = {
+	.name	= "dg_timer",
+	.rating	= 300,
+	.read	= msm_read_timer_count,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int msm_timer_irq;
+static int msm_timer_has_ppi;
+
+static int msm_local_timer_setup(struct clock_event_device *evt)
+{
+	int cpu = smp_processor_id();
+	int err;
+
+	evt->irq = msm_timer_irq;
+	evt->name = "msm_timer";
+	evt->features = CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = 200;
+	evt->set_mode = msm_timer_set_mode;
+	evt->set_next_event = msm_timer_set_next_event;
+	evt->cpumask = cpumask_of(cpu);
+
+	clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
+
+	if (msm_timer_has_ppi) {
+		enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
+	} else {
+		err = request_irq(evt->irq, msm_timer_interrupt,
+				IRQF_TIMER | IRQF_NOBALANCING |
+				IRQF_TRIGGER_RISING, "gp_timer", evt);
+		if (err)
+			pr_err("request_irq failed\n");
+	}
+
+	return 0;
+}
+
+static void msm_local_timer_stop(struct clock_event_device *evt)
+{
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	disable_percpu_irq(evt->irq);
+}
+
+static int msm_timer_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		msm_local_timer_setup(this_cpu_ptr(msm_evt));
+		break;
+	case CPU_DYING:
+		msm_local_timer_stop(this_cpu_ptr(msm_evt));
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block msm_timer_cpu_nb = {
+	.notifier_call = msm_timer_cpu_notify,
+};
+
+static u64 notrace msm_sched_clock_read(void)
+{
+	return msm_clocksource.read(&msm_clocksource);
+}
+
+static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
+				  bool percpu)
+{
+	struct clocksource *cs = &msm_clocksource;
+	int res = 0;
+
+	msm_timer_irq = irq;
+	msm_timer_has_ppi = percpu;
+
+	msm_evt = alloc_percpu(struct clock_event_device);
+	if (!msm_evt) {
+		pr_err("memory allocation failed for clockevents\n");
+		goto err;
+	}
+
+	if (percpu)
+		res = request_percpu_irq(irq, msm_timer_interrupt,
+					 "gp_timer", msm_evt);
+
+	if (res) {
+		pr_err("request_percpu_irq failed\n");
+	} else {
+		res = register_cpu_notifier(&msm_timer_cpu_nb);
+		if (res) {
+			free_percpu_irq(irq, msm_evt);
+			goto err;
+		}
+
+		/* Immediately configure the timer on the boot CPU */
+		msm_local_timer_setup(__this_cpu_ptr(msm_evt));
+	}
+
+err:
+	writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
+	res = clocksource_register_hz(cs, dgt_hz);
+	if (res)
+		pr_err("clocksource_register failed\n");
+	sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
+}
+
+#ifdef CONFIG_ARCH_QCOM
+static void __init msm_dt_timer_init(struct device_node *np)
+{
+	u32 freq;
+	int irq;
+	struct resource res;
+	u32 percpu_offset;
+	void __iomem *base;
+	void __iomem *cpu0_base;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("Failed to map event base\n");
+		return;
+	}
+
+	/* We use GPT0 for the clockevent */
+	irq = irq_of_parse_and_map(np, 1);
+	if (irq <= 0) {
+		pr_err("Can't get irq\n");
+		return;
+	}
+
+	/* We use CPU0's DGT for the clocksource */
+	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
+		percpu_offset = 0;
+
+	if (of_address_to_resource(np, 0, &res)) {
+		pr_err("Failed to parse DGT resource\n");
+		return;
+	}
+
+	cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
+	if (!cpu0_base) {
+		pr_err("Failed to map source base\n");
+		return;
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &freq)) {
+		pr_err("Unknown frequency\n");
+		return;
+	}
+
+	event_base = base + 0x4;
+	sts_base = base + 0x88;
+	source_base = cpu0_base + 0x24;
+	freq /= 4;
+	writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
+
+	msm_timer_init(freq, 32, irq, !!percpu_offset);
+}
+CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
+CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
+#else
+
+static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
+				u32 sts)
+{
+	void __iomem *base;
+
+	base = ioremap(addr, SZ_256);
+	if (!base) {
+		pr_err("Failed to map timer base\n");
+		return -ENOMEM;
+	}
+	event_base = base + event;
+	source_base = base + source;
+	if (sts)
+		sts_base = base + sts;
+
+	return 0;
+}
+
+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
+{
+	/*
+	 * Shift timer count down by a constant due to unreliable lower bits
+	 * on some targets.
+	 */
+	return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
+}
+
+void __init msm7x01_timer_init(void)
+{
+	struct clocksource *cs = &msm_clocksource;
+
+	if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
+		return;
+	cs->read = msm_read_timer_count_shift;
+	cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
+	/* 600 KHz */
+	msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
+			false);
+}
+
+void __init msm7x30_timer_init(void)
+{
+	if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
+		return;
+	msm_timer_init(24576000 / 4, 32, 1, false);
+}
+
+void __init qsd8x50_timer_init(void)
+{
+	if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
+		return;
+	msm_timer_init(19200000 / 4, 32, 7, false);
+}
+#endif
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index 09a17d9a6594..b52e1c078b99 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -19,7 +19,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/sched_clock.h>
-#include <asm/mach/time.h>
+
+#define MARCO_CLOCK_FREQ 1000000
 
 #define SIRFSOC_TIMER_32COUNTER_0_CTRL			0x0000
 #define SIRFSOC_TIMER_32COUNTER_1_CTRL			0x0004
@@ -191,7 +192,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
 	ce->rating = 200;
 	ce->set_mode = sirfsoc_timer_set_mode;
 	ce->set_next_event = sirfsoc_timer_set_next_event;
-	clockevents_calc_mult_shift(ce, CLOCK_TICK_RATE, 60);
+	clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60);
 	ce->max_delta_ns = clockevent_delta2ns(-2, ce);
 	ce->min_delta_ns = clockevent_delta2ns(2, ce);
 	ce->cpumask = cpumask_of(cpu);
@@ -263,11 +264,11 @@ static void __init sirfsoc_marco_timer_init(void)
 	BUG_ON(IS_ERR(clk));
 	rate = clk_get_rate(clk);
 
-	BUG_ON(rate < CLOCK_TICK_RATE);
-	BUG_ON(rate % CLOCK_TICK_RATE);
+	BUG_ON(rate < MARCO_CLOCK_FREQ);
+	BUG_ON(rate % MARCO_CLOCK_FREQ);
 
 	/* Initialize the timer dividers */
-	timer_div = rate / CLOCK_TICK_RATE - 1;
+	timer_div = rate / MARCO_CLOCK_FREQ - 1;
 	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
 	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
 	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
@@ -283,7 +284,7 @@ static void __init sirfsoc_marco_timer_init(void)
 	/* Clear all interrupts */
 	writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
 
-	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, MARCO_CLOCK_FREQ));
 
 	sirfsoc_clockevent_init();
 }
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index 8a492d34ff9f..1a6b2d6356d6 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -21,6 +21,8 @@
 #include <linux/sched_clock.h>
 #include <asm/mach/time.h>
 
+#define PRIMA2_CLOCK_FREQ 1000000
+
 #define SIRFSOC_TIMER_COUNTER_LO	0x0000
 #define SIRFSOC_TIMER_COUNTER_HI	0x0004
 #define SIRFSOC_TIMER_MATCH_0		0x0008
@@ -173,7 +175,7 @@ static u64 notrace sirfsoc_read_sched_clock(void)
 static void __init sirfsoc_clockevent_init(void)
 {
 	sirfsoc_clockevent.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
+	clockevents_config_and_register(&sirfsoc_clockevent, PRIMA2_CLOCK_FREQ,
 					2, -2);
 }
 
@@ -190,8 +192,8 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np)
 
 	rate = clk_get_rate(clk);
 
-	BUG_ON(rate < CLOCK_TICK_RATE);
-	BUG_ON(rate % CLOCK_TICK_RATE);
+	BUG_ON(rate < PRIMA2_CLOCK_FREQ);
+	BUG_ON(rate % PRIMA2_CLOCK_FREQ);
 
 	sirfsoc_timer_base = of_iomap(np, 0);
 	if (!sirfsoc_timer_base)
@@ -199,14 +201,16 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np)
 
 	sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
 
-	writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
+	writel_relaxed(rate / PRIMA2_CLOCK_FREQ / 2 - 1,
+		       sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
 	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
 	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
 	writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
 
-	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource,
+				       PRIMA2_CLOCK_FREQ));
 
-	sched_clock_register(sirfsoc_read_sched_clock, 64, CLOCK_TICK_RATE);
+	sched_clock_register(sirfsoc_read_sched_clock, 64, PRIMA2_CLOCK_FREQ);
 
 	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
 
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 18c5b9b16645..148d707a1d43 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -95,7 +95,7 @@ void proc_fork_connector(struct task_struct *task)
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
 	/*  If cn_netlink_send() failed, the data is not sent */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_exec_connector(struct task_struct *task)
@@ -122,7 +122,7 @@ void proc_exec_connector(struct task_struct *task)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_id_connector(struct task_struct *task, int which_id)
@@ -163,7 +163,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_sid_connector(struct task_struct *task)
@@ -190,7 +190,7 @@ void proc_sid_connector(struct task_struct *task)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
@@ -225,7 +225,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_comm_connector(struct task_struct *task)
@@ -253,7 +253,7 @@ void proc_comm_connector(struct task_struct *task)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_coredump_connector(struct task_struct *task)
@@ -280,7 +280,7 @@ void proc_coredump_connector(struct task_struct *task)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 void proc_exit_connector(struct task_struct *task)
@@ -309,7 +309,7 @@ void proc_exit_connector(struct task_struct *task)
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 /*
@@ -343,7 +343,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
 	msg->ack = rcvd_ack + 1;
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
 }
 
 /**
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a36749f1e44a..b14f1d36f897 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -50,7 +50,7 @@ static int cn_already_initialized;
  *
  * Sequence number is incremented with each message to be sent.
  *
- * If we expect reply to our message then the sequence number in
+ * If we expect a reply to our message then the sequence number in
  * received message MUST be the same as in original message, and
  * acknowledge number MUST be the same + 1.
  *
@@ -62,8 +62,11 @@ static int cn_already_initialized;
  * the acknowledgement number in the original message + 1, then it is
  * a new message.
  *
+ * The message is sent to, the portid if given, the group if given, both if
+ * both, or if both are zero then the group is looked up and sent there.
  */
-int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
+int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group,
+	gfp_t gfp_mask)
 {
 	struct cn_callback_entry *__cbq;
 	unsigned int size;
@@ -74,7 +77,9 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 	u32 group = 0;
 	int found = 0;
 
-	if (!__group) {
+	if (portid || __group) {
+		group = __group;
+	} else {
 		spin_lock_bh(&dev->cbdev->queue_lock);
 		list_for_each_entry(__cbq, &dev->cbdev->queue_list,
 				    callback_entry) {
@@ -88,11 +93,9 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 
 		if (!found)
 			return -ENODEV;
-	} else {
-		group = __group;
 	}
 
-	if (!netlink_has_listeners(dev->nls, group))
+	if (!portid && !netlink_has_listeners(dev->nls, group))
 		return -ESRCH;
 
 	size = sizeof(*msg) + msg->len;
@@ -113,7 +116,10 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 
 	NETLINK_CB(skb).dst_group = group;
 
-	return netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
+	if (group)
+		return netlink_broadcast(dev->nls, skb, portid, group,
+					 gfp_mask);
+	return netlink_unicast(dev->nls, skb, portid, !(gfp_mask&__GFP_WAIT));
 }
 EXPORT_SYMBOL_GPL(cn_netlink_send);
 
@@ -139,7 +145,6 @@ static int cn_call_callback(struct sk_buff *skb)
 	spin_unlock_bh(&dev->cbdev->queue_lock);
 
 	if (cbq != NULL) {
-		err = 0;
 		cbq->callback(msg, nsp);
 		kfree_skb(skb);
 		cn_queue_release_callback(cbq);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 4b029c0944af..1fbe11f2a146 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86"
 endmenu
 
 menu "ARM CPU frequency scaling drivers"
-depends on ARM
+depends on ARM || ARM64
 source "drivers/cpufreq/Kconfig.arm"
 endmenu
 
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 31297499a60a..077db3aa985b 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -113,7 +113,7 @@ config ARM_INTEGRATOR
 	  If in doubt, say Y.
 
 config ARM_KIRKWOOD_CPUFREQ
-	def_bool ARCH_KIRKWOOD && OF
+	def_bool MACH_KIRKWOOD
 	help
 	  This adds the CPUFreq driver for Marvell Kirkwood
 	  SoCs.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index cb003a6b72c8..c755b5fe317c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2017,22 +2017,21 @@ EXPORT_SYMBOL(cpufreq_get_policy);
 static int cpufreq_set_policy(struct cpufreq_policy *policy,
 				struct cpufreq_policy *new_policy)
 {
-	int ret = 0, failed = 1;
+	struct cpufreq_governor *old_gov;
+	int ret;
 
 	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu,
 		new_policy->min, new_policy->max);
 
 	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
 
-	if (new_policy->min > policy->max || new_policy->max < policy->min) {
-		ret = -EINVAL;
-		goto error_out;
-	}
+	if (new_policy->min > policy->max || new_policy->max < policy->min)
+		return -EINVAL;
 
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
-		goto error_out;
+		return ret;
 
 	/* adjust if necessary - all reasons */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
@@ -2048,7 +2047,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 	 */
 	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
-		goto error_out;
+		return ret;
 
 	/* notification of the new policy */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
@@ -2063,58 +2062,48 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 	if (cpufreq_driver->setpolicy) {
 		policy->policy = new_policy->policy;
 		pr_debug("setting range\n");
-		ret = cpufreq_driver->setpolicy(new_policy);
-	} else {
-		if (new_policy->governor != policy->governor) {
-			/* save old, working values */
-			struct cpufreq_governor *old_gov = policy->governor;
-
-			pr_debug("governor switch\n");
-
-			/* end old governor */
-			if (policy->governor) {
-				__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-				up_write(&policy->rwsem);
-				__cpufreq_governor(policy,
-						CPUFREQ_GOV_POLICY_EXIT);
-				down_write(&policy->rwsem);
-			}
+		return cpufreq_driver->setpolicy(new_policy);
+	}
 
-			/* start new governor */
-			policy->governor = new_policy->governor;
-			if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
-				if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
-					failed = 0;
-				} else {
-					up_write(&policy->rwsem);
-					__cpufreq_governor(policy,
-							CPUFREQ_GOV_POLICY_EXIT);
-					down_write(&policy->rwsem);
-				}
-			}
+	if (new_policy->governor == policy->governor)
+		goto out;
 
-			if (failed) {
-				/* new governor failed, so re-start old one */
-				pr_debug("starting governor %s failed\n",
-							policy->governor->name);
-				if (old_gov) {
-					policy->governor = old_gov;
-					__cpufreq_governor(policy,
-							CPUFREQ_GOV_POLICY_INIT);
-					__cpufreq_governor(policy,
-							   CPUFREQ_GOV_START);
-				}
-				ret = -EINVAL;
-				goto error_out;
-			}
-			/* might be a policy change, too, so fall through */
-		}
-		pr_debug("governor: change or update limits\n");
-		ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+	pr_debug("governor switch\n");
+
+	/* save old, working values */
+	old_gov = policy->governor;
+	/* end old governor */
+	if (old_gov) {
+		__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+		up_write(&policy->rwsem);
+		__cpufreq_governor(policy,CPUFREQ_GOV_POLICY_EXIT);
+		down_write(&policy->rwsem);
 	}
 
-error_out:
-	return ret;
+	/* start new governor */
+	policy->governor = new_policy->governor;
+	if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
+		if (!__cpufreq_governor(policy, CPUFREQ_GOV_START))
+			goto out;
+
+		up_write(&policy->rwsem);
+		__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+		down_write(&policy->rwsem);
+	}
+
+	/* new governor failed, so re-start old one */
+	pr_debug("starting governor %s failed\n", policy->governor->name);
+	if (old_gov) {
+		policy->governor = old_gov;
+		__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
+		__cpufreq_governor(policy, CPUFREQ_GOV_START);
+	}
+
+	return -EINVAL;
+
+ out:
+	pr_debug("governor: change or update limits\n");
+	return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 }
 
 /**
@@ -2186,7 +2175,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
 		switch (action & ~CPU_TASKS_FROZEN) {
 		case CPU_ONLINE:
 			__cpufreq_add_dev(dev, NULL, frozen);
-			cpufreq_update_policy(cpu);
 			break;
 
 		case CPU_DOWN_PREPARE:
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index f04e25f6c98d..aee9fafbb055 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -40,6 +40,11 @@ depends on PPC
 source "drivers/cpuidle/Kconfig.powerpc"
 endmenu
 
+menu "MIPS CPU Idle Drivers"
+depends on MIPS
+source "drivers/cpuidle/Kconfig.mips"
+endmenu
+
 endif
 
 config ARCH_NEEDS_CPU_IDLE_COUPLED
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index d988948a89a0..97ccc31dbdd8 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -22,7 +22,7 @@ config ARM_HIGHBANK_CPUIDLE
 
 config ARM_KIRKWOOD_CPUIDLE
 	bool "CPU Idle Driver for Marvell Kirkwood SoCs"
-	depends on ARCH_KIRKWOOD
+	depends on ARCH_KIRKWOOD || MACH_KIRKWOOD
 	help
 	  This adds the CPU Idle driver for Marvell Kirkwood SoCs.
 
diff --git a/drivers/cpuidle/Kconfig.mips b/drivers/cpuidle/Kconfig.mips
new file mode 100644
index 000000000000..dc9669139511
--- /dev/null
+++ b/drivers/cpuidle/Kconfig.mips
@@ -0,0 +1,14 @@
+#
+# MIPS CPU Idle drivers
+#
+
+config MIPS_CPS_CPUIDLE
+	bool "Support for MIPS Coherent Processing Systems"
+	depends on SYS_SUPPORTS_MIPS_CPS && CPU_MIPSR2 && !MIPS_MT_SMTC
+	select ARCH_NEEDS_CPU_IDLE_COUPLED if MIPS_MT
+	select MIPS_CM
+	help
+	  Select this option to enable CPU idle driver for systems based
+	  around the MIPS Coherent Processing System architecture - that
+	  is, those with a Coherence Manager & optionally a Cluster
+	  Power Controller.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index f71ae1b373c5..743d7de59c73 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -15,6 +15,10 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
 obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
 
 ###############################################################################
+# MIPS drivers
+obj-$(CONFIG_MIPS_CPS_CPUIDLE)		+= cpuidle-mips-cps.o
+
+###############################################################################
 # POWERPC drivers
 obj-$(CONFIG_PSERIES_CPUIDLE)		+= cpuidle-pseries.o
 obj-$(CONFIG_POWERNV_CPUIDLE)		+= cpuidle-powernv.o
diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c
index e952936418d0..cb6654bfad77 100644
--- a/drivers/cpuidle/coupled.c
+++ b/drivers/cpuidle/coupled.c
@@ -323,7 +323,7 @@ static void cpuidle_coupled_poke(int cpu)
 	struct call_single_data *csd = &per_cpu(cpuidle_coupled_poke_cb, cpu);
 
 	if (!cpumask_test_and_set_cpu(cpu, &cpuidle_coupled_poke_pending))
-		__smp_call_function_single(cpu, csd, 0);
+		smp_call_function_single_async(cpu, csd);
 }
 
 /**
diff --git a/drivers/cpuidle/cpuidle-mips-cps.c b/drivers/cpuidle/cpuidle-mips-cps.c
new file mode 100644
index 000000000000..a78bfb4faa6e
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-mips-cps.c
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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/cpuidle.h>
+#include <linux/init.h>
+#include <linux/kconfig.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cacheops.h>
+#include <asm/idle.h>
+#include <asm/mips-cm.h>
+#include <asm/mipsmtregs.h>
+#include <asm/uasm.h>
+
+/*
+ * The CM & CPC can only handle coherence & power control on a per-core basis,
+ * thus in an MT system the VPEs within each core are coupled and can only
+ * enter or exit states requiring CM or CPC assistance in unison.
+ */
+#ifdef CONFIG_MIPS_MT
+# define coupled_coherence cpu_has_mipsmt
+#else
+# define coupled_coherence 0
+#endif
+
+/*
+ * cps_nc_entry_fn - type of a generated non-coherent state entry function
+ * @vpe_mask: a bitmap of online coupled VPEs, excluding this one
+ * @online: the count of online coupled VPEs (weight of vpe_mask + 1)
+ *
+ * The code entering & exiting non-coherent states is generated at runtime
+ * using uasm, in order to ensure that the compiler cannot insert a stray
+ * memory access at an unfortunate time and to allow the generation of optimal
+ * core-specific code particularly for cache routines. If coupled_coherence
+ * is non-zero, returns the number of VPEs that were in the wait state at the
+ * point this VPE left it. Returns garbage if coupled_coherence is zero.
+ */
+typedef unsigned (*cps_nc_entry_fn)(unsigned vpe_mask, unsigned online);
+
+/*
+ * The entry point of the generated non-coherent wait entry/exit function.
+ * Actually per-core rather than per-CPU.
+ */
+static DEFINE_PER_CPU_READ_MOSTLY(cps_nc_entry_fn, ncwait_asm_enter);
+
+/*
+ * Indicates the number of coupled VPEs ready to operate in a non-coherent
+ * state. Actually per-core rather than per-CPU.
+ */
+static DEFINE_PER_CPU_ALIGNED(u32, nc_ready_count);
+
+/* A somewhat arbitrary number of labels & relocs for uasm */
+static struct uasm_label labels[32] __initdata;
+static struct uasm_reloc relocs[32] __initdata;
+
+/* CPU dependant sync types */
+static unsigned stype_intervention;
+static unsigned stype_memory;
+static unsigned stype_ordering;
+
+enum mips_reg {
+	zero, at, v0, v1, a0, a1, a2, a3,
+	t0, t1, t2, t3, t4, t5, t6, t7,
+	s0, s1, s2, s3, s4, s5, s6, s7,
+	t8, t9, k0, k1, gp, sp, fp, ra,
+};
+
+static int cps_ncwait_enter(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
+{
+	unsigned core = cpu_data[dev->cpu].core;
+	unsigned online, first_cpu, num_left;
+	cpumask_var_t coupled_mask, vpe_mask;
+
+	if (!alloc_cpumask_var(&coupled_mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (!alloc_cpumask_var(&vpe_mask, GFP_KERNEL)) {
+		free_cpumask_var(coupled_mask);
+		return -ENOMEM;
+	}
+
+	/* Calculate which coupled CPUs (VPEs) are online */
+#ifdef CONFIG_MIPS_MT
+	cpumask_and(coupled_mask, cpu_online_mask, &dev->coupled_cpus);
+	first_cpu = cpumask_first(coupled_mask);
+	online = cpumask_weight(coupled_mask);
+	cpumask_clear_cpu(dev->cpu, coupled_mask);
+	cpumask_shift_right(vpe_mask, coupled_mask,
+			    cpumask_first(&dev->coupled_cpus));
+#else
+	cpumask_clear(coupled_mask);
+	cpumask_clear(vpe_mask);
+	first_cpu = dev->cpu;
+	online = 1;
+#endif
+
+	/*
+	 * Run the generated entry code. Note that we assume the number of VPEs
+	 * within this core does not exceed the width in bits of a long. Since
+	 * MVPConf0.PVPE is 4 bits wide this seems like a safe assumption.
+	 */
+	num_left = per_cpu(ncwait_asm_enter, core)(vpe_mask->bits[0], online);
+
+	/*
+	 * If this VPE is the first to leave the non-coherent wait state then
+	 * it needs to wake up any coupled VPEs still running their wait
+	 * instruction so that they return to cpuidle, which can then complete
+	 * coordination between the coupled VPEs & provide the governor with
+	 * a chance to reflect on the length of time the VPEs were in the
+	 * idle state.
+	 */
+	if (coupled_coherence && (num_left == online))
+		arch_send_call_function_ipi_mask(coupled_mask);
+
+	free_cpumask_var(vpe_mask);
+	free_cpumask_var(coupled_mask);
+	return index;
+}
+
+static struct cpuidle_driver cps_driver = {
+	.name			= "cpc_cpuidle",
+	.owner			= THIS_MODULE,
+	.states = {
+		MIPS_CPUIDLE_WAIT_STATE,
+		{
+			.enter	= cps_ncwait_enter,
+			.exit_latency		= 200,
+			.target_residency	= 450,
+			.flags	= CPUIDLE_FLAG_TIME_VALID,
+			.name	= "nc-wait",
+			.desc	= "non-coherent MIPS wait",
+		},
+	},
+	.state_count		= 2,
+	.safe_state_index	= 0,
+};
+
+static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl,
+					 struct uasm_reloc **pr,
+					 const struct cache_desc *cache,
+					 unsigned op, int lbl)
+{
+	unsigned cache_size = cache->ways << cache->waybit;
+	unsigned i;
+	const unsigned unroll_lines = 32;
+
+	/* If the cache isn't present this function has it easy */
+	if (cache->flags & MIPS_CACHE_NOT_PRESENT)
+		return;
+
+	/* Load base address */
+	UASM_i_LA(pp, t0, (long)CKSEG0);
+
+	/* Calculate end address */
+	if (cache_size < 0x8000)
+		uasm_i_addiu(pp, t1, t0, cache_size);
+	else
+		UASM_i_LA(pp, t1, (long)(CKSEG0 + cache_size));
+
+	/* Start of cache op loop */
+	uasm_build_label(pl, *pp, lbl);
+
+	/* Generate the cache ops */
+	for (i = 0; i < unroll_lines; i++)
+		uasm_i_cache(pp, op, i * cache->linesz, t0);
+
+	/* Update the base address */
+	uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz);
+
+	/* Loop if we haven't reached the end address yet */
+	uasm_il_bne(pp, pr, t0, t1, lbl);
+	uasm_i_nop(pp);
+}
+
+static void * __init cps_gen_entry_code(struct cpuidle_device *dev)
+{
+	unsigned core = cpu_data[dev->cpu].core;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
+	u32 *buf, *p;
+	const unsigned r_vpemask = a0;
+	const unsigned r_online = a1;
+	const unsigned r_pcount = t6;
+	const unsigned r_pcohctl = t7;
+	const unsigned max_instrs = 256;
+	enum {
+		lbl_incready = 1,
+		lbl_lastvpe,
+		lbl_vpehalt_loop,
+		lbl_vpehalt_poll,
+		lbl_vpehalt_next,
+		lbl_disable_coherence,
+		lbl_invicache,
+		lbl_flushdcache,
+		lbl_vpeactivate_loop,
+		lbl_vpeactivate_next,
+		lbl_wait,
+		lbl_decready,
+	};
+
+	/* Allocate a buffer to hold the generated code */
+	p = buf = kcalloc(max_instrs, sizeof(u32), GFP_KERNEL);
+	if (!buf)
+		return NULL;
+
+	/* Clear labels & relocs ready for (re)use */
+	memset(labels, 0, sizeof(labels));
+	memset(relocs, 0, sizeof(relocs));
+
+	/*
+	 * Load address of the CM GCR_CL_COHERENCE register. This is done early
+	 * because it's needed in both the enable & disable coherence steps but
+	 * in the coupled case the enable step will only run on one VPE.
+	 */
+	UASM_i_LA(&p, r_pcohctl, (long)addr_gcr_cl_coherence());
+
+	if (coupled_coherence) {
+		/* Load address of nc_ready_count */
+		UASM_i_LA(&p, r_pcount, (long)&per_cpu(nc_ready_count, core));
+
+		/* Increment nc_ready_count */
+		uasm_build_label(&l, p, lbl_incready);
+		uasm_i_sync(&p, stype_ordering);
+		uasm_i_ll(&p, t1, 0, r_pcount);
+		uasm_i_addiu(&p, t2, t1, 1);
+		uasm_i_sc(&p, t2, 0, r_pcount);
+		uasm_il_beqz(&p, &r, t2, lbl_incready);
+		uasm_i_addiu(&p, t1, t1, 1);
+
+		/*
+		 * If this is the last VPE to become ready for non-coherence
+		 * then it should branch below.
+		 */
+		uasm_il_beq(&p, &r, t1, r_online, lbl_lastvpe);
+		uasm_i_nop(&p);
+
+		/*
+		 * Otherwise this is not the last VPE to become ready for
+		 * non-coherence. It needs to wait until coherence has been
+		 * disabled before executing a wait instruction, otherwise it
+		 * may return from wait quickly & re-enable coherence causing
+		 * a race with the VPE disabling coherence. It can't simply
+		 * poll the CPC sequencer for a non-coherent state as that
+		 * would race with any other VPE which may spot the
+		 * non-coherent state, run wait, return quickly & re-enable
+		 * coherence before this VPE ever saw the non-coherent state.
+		 * Instead this VPE will halt its TC such that it ceases to
+		 * execute for the moment.
+		 */
+		uasm_i_addiu(&p, t0, zero, TCHALT_H);
+		uasm_i_mtc0(&p, t0, 2, 4); /* TCHalt */
+
+		/* instruction_hazard(), to ensure the TC halts */
+		UASM_i_LA(&p, t0, (long)p + 12);
+		uasm_i_jr_hb(&p, t0);
+		uasm_i_nop(&p);
+
+		/*
+		 * The VPE which disables coherence will then clear the halt
+		 * bit for this VPE's TC once coherence has been disabled and
+		 * it can safely proceed to execute the wait instruction.
+		 */
+		uasm_il_b(&p, &r, lbl_wait);
+		uasm_i_nop(&p);
+
+		/*
+		 * The last VPE to increment nc_ready_count will continue from
+		 * here and must spin until all other VPEs within the core have
+		 * been halted, at which point it can be sure that it is safe
+		 * to disable coherence.
+		 *
+		 *   t0: number of VPEs left to handle
+		 *   t1: (shifted) mask of online VPEs
+		 *   t2: current VPE index
+		 */
+		uasm_build_label(&l, p, lbl_lastvpe);
+		uasm_i_addiu(&p, t0, r_online, -1);
+		uasm_il_beqz(&p, &r, t0, lbl_disable_coherence);
+		uasm_i_move(&p, t1, r_vpemask);
+		uasm_i_move(&p, t2, zero);
+
+		/*
+		 * Now loop through all VPEs within the core checking whether
+		 * they are online & not this VPE, which can be determined by
+		 * checking the vpe_mask argument. If a VPE is offline or is
+		 * this VPE, skip it.
+		 */
+		uasm_build_label(&l, p, lbl_vpehalt_loop);
+		uasm_i_andi(&p, t3, t1, 1);
+		uasm_il_beqz(&p, &r, t3, lbl_vpehalt_next);
+
+		/* settc(vpe) */
+		uasm_i_mfc0(&p, t3, 1, 1); /* VPEControl */
+		uasm_i_ins(&p, t3, t2, 0, 8);
+		uasm_i_mtc0(&p, t3, 1, 1); /* VPEControl */
+		uasm_i_ehb(&p);
+
+		/*
+		 * It's very likely that the VPE has already halted itself
+		 * by now, but there's theoretically a chance that it may not
+		 * have. Wait until the VPE's TC is halted.
+		 */
+		uasm_build_label(&l, p, lbl_vpehalt_poll);
+		uasm_i_mftc0(&p, t3, 2, 4); /* TCHalt */
+		uasm_il_beqz(&p, &r, t3, lbl_vpehalt_poll);
+		uasm_i_nop(&p);
+
+		/* Decrement the count of VPEs to be handled */
+		uasm_i_addiu(&p, t0, t0, -1);
+
+		/* Proceed to the next VPE, if there is one */
+		uasm_build_label(&l, p, lbl_vpehalt_next);
+		uasm_i_srl(&p, t1, t1, 1);
+		uasm_il_bnez(&p, &r, t0, lbl_vpehalt_loop);
+		uasm_i_addiu(&p, t2, t2, 1);
+	}
+
+	/*
+	 * This is the point of no return - this VPE will now proceed to
+	 * disable coherence. At this point we *must* be sure that no other
+	 * VPE within the core will interfere with the L1 dcache.
+	 */
+	uasm_build_label(&l, p, lbl_disable_coherence);
+
+	/* Completion barrier */
+	uasm_i_sync(&p, stype_memory);
+
+	/* Invalidate the L1 icache */
+	cps_gen_cache_routine(&p, &l, &r, &cpu_data[dev->cpu].icache,
+			      Index_Invalidate_I, lbl_invicache);
+
+	/* Writeback & invalidate the L1 dcache */
+	cps_gen_cache_routine(&p, &l, &r, &cpu_data[dev->cpu].dcache,
+			      Index_Writeback_Inv_D, lbl_flushdcache);
+
+	/*
+	 * Disable all but self interventions. The load from COHCTL is defined
+	 * by the interAptiv & proAptiv SUMs as ensuring that the operation
+	 * resulting from the preceeding store is complete.
+	 */
+	uasm_i_addiu(&p, t0, zero, 1 << cpu_data[dev->cpu].core);
+	uasm_i_sw(&p, t0, 0, r_pcohctl);
+	uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+	/* Sync to ensure previous interventions are complete */
+	uasm_i_sync(&p, stype_intervention);
+
+	/* Disable coherence */
+	uasm_i_sw(&p, zero, 0, r_pcohctl);
+	uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+	if (coupled_coherence) {
+		/*
+		 * Now that coherence is disabled it is safe for all VPEs to
+		 * proceed with executing their wait instruction, so this VPE
+		 * will go ahead and clear the halt bit of the TCs associated
+		 * with all other online VPEs within the core. Start by
+		 * initialising variables used throughout the loop, and
+		 * skipping the loop entirely if there are no VPEs to handle.
+		 *
+		 *   t0: number of VPEs left to handle
+		 *   t1: (shifted) mask of online VPEs
+		 *   t2: current VPE index
+		 */
+		uasm_i_addiu(&p, t0, r_online, -1);
+		uasm_il_beqz(&p, &r, t0, lbl_wait);
+		uasm_i_move(&p, t1, r_vpemask);
+		uasm_i_move(&p, t2, zero);
+
+		/*
+		 * Now loop through all VPEs within the core checking whether
+		 * they are online & not this VPE, which can be determined by
+		 * checking the vpe_mask argument. If a VPE is offline or is
+		 * this VPE, skip it.
+		 */
+		uasm_build_label(&l, p, lbl_vpeactivate_loop);
+		uasm_i_andi(&p, t3, t1, 1);
+		uasm_il_beqz(&p, &r, t3, lbl_vpeactivate_next);
+
+		/* settc(vpe) */
+		uasm_i_mfc0(&p, t3, 1, 1); /* VPEControl */
+		uasm_i_ins(&p, t3, t2, 0, 8);
+		uasm_i_mtc0(&p, t3, 1, 1); /* VPEControl */
+		uasm_i_ehb(&p);
+
+		/* Clear TCHalt */
+		uasm_i_mttc0(&p, zero, 2, 4); /* TCHalt */
+
+		/* Decrement the count of VPEs to be handled */
+		uasm_i_addiu(&p, t0, t0, -1);
+
+		/* Proceed to the next VPE, if there is one */
+		uasm_build_label(&l, p, lbl_vpeactivate_next);
+		uasm_i_srl(&p, t1, t1, 1);
+		uasm_il_bnez(&p, &r, t0, lbl_vpeactivate_loop);
+		uasm_i_addiu(&p, t2, t2, 1);
+	}
+
+	/* Now perform our wait */
+	uasm_build_label(&l, p, lbl_wait);
+	uasm_i_wait(&p, 0);
+
+	/*
+	 * Re-enable coherence. Note that all coupled VPEs will run this, the
+	 * first will actually re-enable coherence & the rest will just be
+	 * performing a rather unusual nop.
+	 */
+	uasm_i_addiu(&p, t0, zero, CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK);
+	uasm_i_sw(&p, t0, 0, r_pcohctl);
+	uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+	/* Ordering barrier */
+	uasm_i_sync(&p, stype_ordering);
+
+	if (coupled_coherence) {
+		/* Decrement nc_ready_count */
+		uasm_build_label(&l, p, lbl_decready);
+		uasm_i_sync(&p, stype_ordering);
+		uasm_i_ll(&p, t1, 0, r_pcount);
+		uasm_i_addiu(&p, t2, t1, -1);
+		uasm_i_sc(&p, t2, 0, r_pcount);
+		uasm_il_beqz(&p, &r, t2, lbl_decready);
+		uasm_i_move(&p, v0, t1);
+	}
+
+	/* The core is coherent, time to return to C code */
+	uasm_i_jr(&p, ra);
+	uasm_i_nop(&p);
+
+	/* Ensure the code didn't exceed the resources allocated for it */
+	BUG_ON((p - buf) > max_instrs);
+	BUG_ON((l - labels) > ARRAY_SIZE(labels));
+	BUG_ON((r - relocs) > ARRAY_SIZE(relocs));
+
+	/* Patch branch offsets */
+	uasm_resolve_relocs(relocs, labels);
+
+	/* Flush the icache */
+	local_flush_icache_range((unsigned long)buf, (unsigned long)p);
+
+	return buf;
+}
+
+static void __init cps_cpuidle_unregister(void)
+{
+	int cpu;
+	struct cpuidle_device *device;
+	cps_nc_entry_fn *fn;
+
+	for_each_possible_cpu(cpu) {
+		device = &per_cpu(cpuidle_dev, cpu);
+		cpuidle_unregister_device(device);
+
+		/* Free entry code */
+		fn = &per_cpu(ncwait_asm_enter, cpu_data[cpu].core);
+		kfree(*fn);
+		*fn = NULL;
+	}
+
+	cpuidle_unregister_driver(&cps_driver);
+}
+
+static int __init cps_cpuidle_init(void)
+{
+	int err, cpu, core, i;
+	struct cpuidle_device *device;
+	void *core_entry;
+
+	/*
+	 * If interrupts were enabled whilst running the wait instruction then
+	 * the VPE may end up processing interrupts whilst non-coherent.
+	 */
+	if (cpu_wait != r4k_wait_irqoff) {
+		pr_warn("cpuidle-cps requires that masked interrupts restart the CPU pipeline following a wait\n");
+		return -ENODEV;
+	}
+
+	/* Detect appropriate sync types for the system */
+	switch (current_cpu_data.cputype) {
+	case CPU_INTERAPTIV:
+	case CPU_PROAPTIV:
+		stype_intervention = 0x2;
+		stype_memory = 0x3;
+		stype_ordering = 0x10;
+		break;
+
+	default:
+		pr_warn("cpuidle-cps using heavyweight sync 0\n");
+	}
+
+	/*
+	 * Set the coupled flag on the appropriate states if this system
+	 * requires it.
+	 */
+	if (coupled_coherence)
+		for (i = 1; i < cps_driver.state_count; i++)
+			cps_driver.states[i].flags |= CPUIDLE_FLAG_COUPLED;
+
+	err = cpuidle_register_driver(&cps_driver);
+	if (err) {
+		pr_err("Failed to register CPS cpuidle driver\n");
+		return err;
+	}
+
+	for_each_possible_cpu(cpu) {
+		core = cpu_data[cpu].core;
+		device = &per_cpu(cpuidle_dev, cpu);
+		device->cpu = cpu;
+#ifdef CONFIG_MIPS_MT
+		cpumask_copy(&device->coupled_cpus, &cpu_sibling_map[cpu]);
+#endif
+		if (!per_cpu(ncwait_asm_enter, core)) {
+			core_entry = cps_gen_entry_code(device);
+			if (!core_entry) {
+				pr_err("Failed to generate core %u entry\n",
+				       core);
+				err = -ENOMEM;
+				goto err_out;
+			}
+			per_cpu(ncwait_asm_enter, core) = core_entry;
+		}
+
+		err = cpuidle_register_device(device);
+		if (err) {
+			pr_err("Failed to register CPU%d cpuidle device\n",
+			       cpu);
+			goto err_out;
+		}
+	}
+
+	return 0;
+err_out:
+	cps_cpuidle_unregister();
+	return err;
+}
+device_initcall(cps_cpuidle_init);
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 78fd174c57e8..f48607cd2540 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -14,6 +14,7 @@
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 
 struct cpuidle_driver powernv_idle_driver = {
 	.name             = "powernv_idle",
@@ -30,12 +31,14 @@ static int snooze_loop(struct cpuidle_device *dev,
 	local_irq_enable();
 	set_thread_flag(TIF_POLLING_NRFLAG);
 
+	ppc64_runlatch_off();
 	while (!need_resched()) {
 		HMT_low();
 		HMT_very_low();
 	}
 
 	HMT_medium();
+	ppc64_runlatch_on();
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 	smp_mb();
 	return index;
@@ -45,7 +48,9 @@ static int nap_loop(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv,
 			int index)
 {
+	ppc64_runlatch_off();
 	power7_idle();
+	ppc64_runlatch_on();
 	return index;
 }
 
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index 7ab564aa0b1c..6f7b01956885 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -17,6 +17,7 @@
 #include <asm/reg.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 #include <asm/plpar_wrappers.h>
 
 struct cpuidle_driver pseries_idle_driver = {
@@ -29,6 +30,7 @@ static struct cpuidle_state *cpuidle_state_table;
 
 static inline void idle_loop_prolog(unsigned long *in_purr)
 {
+	ppc64_runlatch_off();
 	*in_purr = mfspr(SPRN_PURR);
 	/*
 	 * Indicate to the HV that we are idle. Now would be
@@ -45,6 +47,10 @@ static inline void idle_loop_epilog(unsigned long in_purr)
 	wait_cycles += mfspr(SPRN_PURR) - in_purr;
 	get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);
 	get_lppaca()->idle = 0;
+
+	if (irqs_disabled())
+		local_irq_enable();
+	ppc64_runlatch_on();
 }
 
 static int snooze_loop(struct cpuidle_device *dev,
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index a55e68f2cfc8..09d05ab262be 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -140,12 +140,14 @@ int cpuidle_idle_call(void)
 		return 0;
 	}
 
-	trace_cpu_idle_rcuidle(next_state, dev->cpu);
-
 	broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
 
-	if (broadcast)
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	if (broadcast &&
+	    clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
+		return -EBUSY;
+
+
+	trace_cpu_idle_rcuidle(next_state, dev->cpu);
 
 	if (cpuidle_state_is_coupled(dev, drv, next_state))
 		entered_state = cpuidle_enter_state_coupled(dev, drv,
@@ -153,11 +155,11 @@ int cpuidle_idle_call(void)
 	else
 		entered_state = cpuidle_enter_state(dev, drv, next_state);
 
+	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
+
 	if (broadcast)
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
-	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
-
 	/* give the governor an opportunity to reflect on the outcome */
 	if (cpuidle_curr_governor->reflect)
 		cpuidle_curr_governor->reflect(dev, entered_state);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 13857f5d28f7..03ccdb0ccf9e 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -262,6 +262,17 @@ config CRYPTO_DEV_OMAP_AES
 	  OMAP processors have AES module accelerator. Select this if you
 	  want to use the OMAP module for AES algorithms.
 
+config CRYPTO_DEV_OMAP_DES
+	tristate "Support for OMAP DES3DES hw engine"
+	depends on ARCH_OMAP2PLUS
+	select CRYPTO_DES
+	select CRYPTO_BLKCIPHER2
+	help
+	  OMAP processors have DES/3DES module accelerator. Select this if you
+	  want to use the OMAP module for DES and 3DES algorithms. Currently
+	  the ECB and CBC modes of operation supported by the driver. Also
+	  accesses made on unaligned boundaries are also supported.
+
 config CRYPTO_DEV_PICOXCELL
 	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
 	depends on ARCH_PICOXCELL && HAVE_CLK
@@ -300,17 +311,6 @@ config CRYPTO_DEV_S5P
 	  Select this to offload Samsung S5PV210 or S5PC110 from AES
 	  algorithms execution.
 
-config CRYPTO_DEV_TEGRA_AES
-	tristate "Support for TEGRA AES hw engine"
-	depends on ARCH_TEGRA
-	select CRYPTO_AES
-	help
-	  TEGRA processors have AES module accelerator. Select this if you
-	  want to use the TEGRA module for AES algorithms.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called tegra-aes.
-
 config CRYPTO_DEV_NX
 	bool "Support for IBM Power7+ in-Nest cryptographic acceleration"
 	depends on PPC64 && IBMVIO
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 0bc6aa0a54d7..482f090d16d0 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
 n2_crypto-y := n2_core.o n2_asm.o
 obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
 obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
+obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
@@ -21,5 +22,4 @@ obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
 obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
 obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
-obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
 obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 63fb1af2c431..1c38f86bf63a 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -14,7 +14,6 @@
 #include "jr.h"
 #include "desc_constr.h"
 #include "error.h"
-#include "ctrl.h"
 
 /*
  * Descriptor to instantiate RNG State Handle 0 in normal mode and
@@ -352,32 +351,17 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
 
 /**
  * caam_get_era() - Return the ERA of the SEC on SoC, based
- * on the SEC_VID register.
- * Returns the ERA number (1..4) or -ENOTSUPP if the ERA is unknown.
- * @caam_id - the value of the SEC_VID register
+ * on "sec-era" propery in the DTS. This property is updated by u-boot.
  **/
-int caam_get_era(u64 caam_id)
+int caam_get_era(void)
 {
-	struct sec_vid *sec_vid = (struct sec_vid *)&caam_id;
-	static const struct {
-		u16 ip_id;
-		u8 maj_rev;
-		u8 era;
-	} caam_eras[] = {
-		{0x0A10, 1, 1},
-		{0x0A10, 2, 2},
-		{0x0A12, 1, 3},
-		{0x0A14, 1, 3},
-		{0x0A14, 2, 4},
-		{0x0A16, 1, 4},
-		{0x0A11, 1, 4}
-	};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(caam_eras); i++)
-		if (caam_eras[i].ip_id == sec_vid->ip_id &&
-			caam_eras[i].maj_rev == sec_vid->maj_rev)
-				return caam_eras[i].era;
+	struct device_node *caam_node;
+	for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
+		const uint32_t *prop = (uint32_t *)of_get_property(caam_node,
+				"fsl,sec-era",
+				NULL);
+		return prop ? *prop : -ENOTSUPP;
+	}
 
 	return -ENOTSUPP;
 }
@@ -443,13 +427,10 @@ static int caam_probe(struct platform_device *pdev)
 	 * for all, then go probe each one.
 	 */
 	rspec = 0;
-	for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring")
-		rspec++;
-	if (!rspec) {
-		/* for backward compatible with device trees */
-		for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring")
+	for_each_available_child_of_node(nprop, np)
+		if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") ||
+		    of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
 			rspec++;
-	}
 
 	ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
 								GFP_KERNEL);
@@ -460,18 +441,9 @@ static int caam_probe(struct platform_device *pdev)
 
 	ring = 0;
 	ctrlpriv->total_jobrs = 0;
-	for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") {
-		ctrlpriv->jrpdev[ring] =
-				of_platform_device_create(np, NULL, dev);
-		if (!ctrlpriv->jrpdev[ring]) {
-			pr_warn("JR%d Platform device creation error\n", ring);
-			continue;
-		}
-		ctrlpriv->total_jobrs++;
-		ring++;
-	}
-	if (!ring) {
-		for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") {
+	for_each_available_child_of_node(nprop, np)
+		if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") ||
+		    of_device_is_compatible(np, "fsl,sec4.0-job-ring")) {
 			ctrlpriv->jrpdev[ring] =
 				of_platform_device_create(np, NULL, dev);
 			if (!ctrlpriv->jrpdev[ring]) {
@@ -482,7 +454,6 @@ static int caam_probe(struct platform_device *pdev)
 			ctrlpriv->total_jobrs++;
 			ring++;
 		}
-	}
 
 	/* Check to see if QI present. If so, enable */
 	ctrlpriv->qi_present = !!(rd_reg64(&topregs->ctrl.perfmon.comp_parms) &
@@ -564,7 +535,7 @@ static int caam_probe(struct platform_device *pdev)
 
 	/* Report "alive" for developer to see */
 	dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
-		 caam_get_era(caam_id));
+		 caam_get_era());
 	dev_info(dev, "job rings = %d, qi = %d\n",
 		 ctrlpriv->total_jobrs, ctrlpriv->qi_present);
 
diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h
index 980d44eaaf40..cac5402a46eb 100644
--- a/drivers/crypto/caam/ctrl.h
+++ b/drivers/crypto/caam/ctrl.h
@@ -8,6 +8,6 @@
 #define CTRL_H
 
 /* Prototypes for backend-level services exposed to APIs */
-int caam_get_era(u64 caam_id);
+int caam_get_era(void);
 
 #endif /* CTRL_H */
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index d50174f45b21..cbde8b95a6f8 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -74,10 +74,10 @@
 #endif
 #else
 #ifdef __LITTLE_ENDIAN
-#define wr_reg32(reg, data) __raw_writel(reg, data)
+#define wr_reg32(reg, data) __raw_writel(data, reg)
 #define rd_reg32(reg) __raw_readl(reg)
 #ifdef CONFIG_64BIT
-#define wr_reg64(reg, data) __raw_writeq(reg, data)
+#define wr_reg64(reg, data) __raw_writeq(data, reg)
 #define rd_reg64(reg) __raw_readq(reg)
 #endif
 #endif
diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c
index 2636f044789d..20dc848481e7 100644
--- a/drivers/crypto/ccp/ccp-crypto-main.c
+++ b/drivers/crypto/ccp/ccp-crypto-main.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ccp.h>
@@ -24,28 +25,33 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION("1.0.0");
 MODULE_DESCRIPTION("AMD Cryptographic Coprocessor crypto API support");
 
+static unsigned int aes_disable;
+module_param(aes_disable, uint, 0444);
+MODULE_PARM_DESC(aes_disable, "Disable use of AES - any non-zero value");
+
+static unsigned int sha_disable;
+module_param(sha_disable, uint, 0444);
+MODULE_PARM_DESC(sha_disable, "Disable use of SHA - any non-zero value");
+
 
 /* List heads for the supported algorithms */
 static LIST_HEAD(hash_algs);
 static LIST_HEAD(cipher_algs);
 
-/* For any tfm, requests for that tfm on the same CPU must be returned
- * in the order received.  With multiple queues available, the CCP can
- * process more than one cmd at a time.  Therefore we must maintain
- * a cmd list to insure the proper ordering of requests on a given tfm/cpu
- * combination.
+/* For any tfm, requests for that tfm must be returned on the order
+ * received.  With multiple queues available, the CCP can process more
+ * than one cmd at a time.  Therefore we must maintain a cmd list to insure
+ * the proper ordering of requests on a given tfm.
  */
-struct ccp_crypto_cpu_queue {
+struct ccp_crypto_queue {
 	struct list_head cmds;
 	struct list_head *backlog;
 	unsigned int cmd_count;
 };
-#define CCP_CRYPTO_MAX_QLEN	50
+#define CCP_CRYPTO_MAX_QLEN	100
 
-struct ccp_crypto_percpu_queue {
-	struct ccp_crypto_cpu_queue __percpu *cpu_queue;
-};
-static struct ccp_crypto_percpu_queue req_queue;
+static struct ccp_crypto_queue req_queue;
+static spinlock_t req_queue_lock;
 
 struct ccp_crypto_cmd {
 	struct list_head entry;
@@ -62,8 +68,6 @@ struct ccp_crypto_cmd {
 
 	/* Used for held command processing to determine state */
 	int ret;
-
-	int cpu;
 };
 
 struct ccp_crypto_cpu {
@@ -82,25 +86,21 @@ static inline bool ccp_crypto_success(int err)
 	return true;
 }
 
-/*
- * ccp_crypto_cmd_complete must be called while running on the appropriate
- * cpu and the caller must have done a get_cpu to disable preemption
- */
 static struct ccp_crypto_cmd *ccp_crypto_cmd_complete(
 	struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog)
 {
-	struct ccp_crypto_cpu_queue *cpu_queue;
 	struct ccp_crypto_cmd *held = NULL, *tmp;
+	unsigned long flags;
 
 	*backlog = NULL;
 
-	cpu_queue = this_cpu_ptr(req_queue.cpu_queue);
+	spin_lock_irqsave(&req_queue_lock, flags);
 
 	/* Held cmds will be after the current cmd in the queue so start
 	 * searching for a cmd with a matching tfm for submission.
 	 */
 	tmp = crypto_cmd;
-	list_for_each_entry_continue(tmp, &cpu_queue->cmds, entry) {
+	list_for_each_entry_continue(tmp, &req_queue.cmds, entry) {
 		if (crypto_cmd->tfm != tmp->tfm)
 			continue;
 		held = tmp;
@@ -111,47 +111,45 @@ static struct ccp_crypto_cmd *ccp_crypto_cmd_complete(
 	 *   Because cmds can be executed from any point in the cmd list
 	 *   special precautions have to be taken when handling the backlog.
 	 */
-	if (cpu_queue->backlog != &cpu_queue->cmds) {
+	if (req_queue.backlog != &req_queue.cmds) {
 		/* Skip over this cmd if it is the next backlog cmd */
-		if (cpu_queue->backlog == &crypto_cmd->entry)
-			cpu_queue->backlog = crypto_cmd->entry.next;
+		if (req_queue.backlog == &crypto_cmd->entry)
+			req_queue.backlog = crypto_cmd->entry.next;
 
-		*backlog = container_of(cpu_queue->backlog,
+		*backlog = container_of(req_queue.backlog,
 					struct ccp_crypto_cmd, entry);
-		cpu_queue->backlog = cpu_queue->backlog->next;
+		req_queue.backlog = req_queue.backlog->next;
 
 		/* Skip over this cmd if it is now the next backlog cmd */
-		if (cpu_queue->backlog == &crypto_cmd->entry)
-			cpu_queue->backlog = crypto_cmd->entry.next;
+		if (req_queue.backlog == &crypto_cmd->entry)
+			req_queue.backlog = crypto_cmd->entry.next;
 	}
 
 	/* Remove the cmd entry from the list of cmds */
-	cpu_queue->cmd_count--;
+	req_queue.cmd_count--;
 	list_del(&crypto_cmd->entry);
 
+	spin_unlock_irqrestore(&req_queue_lock, flags);
+
 	return held;
 }
 
-static void ccp_crypto_complete_on_cpu(struct work_struct *work)
+static void ccp_crypto_complete(void *data, int err)
 {
-	struct ccp_crypto_cpu *cpu_work =
-		container_of(work, struct ccp_crypto_cpu, work);
-	struct ccp_crypto_cmd *crypto_cmd = cpu_work->crypto_cmd;
+	struct ccp_crypto_cmd *crypto_cmd = data;
 	struct ccp_crypto_cmd *held, *next, *backlog;
 	struct crypto_async_request *req = crypto_cmd->req;
 	struct ccp_ctx *ctx = crypto_tfm_ctx(req->tfm);
-	int cpu, ret;
-
-	cpu = get_cpu();
+	int ret;
 
-	if (cpu_work->err == -EINPROGRESS) {
+	if (err == -EINPROGRESS) {
 		/* Only propogate the -EINPROGRESS if necessary */
 		if (crypto_cmd->ret == -EBUSY) {
 			crypto_cmd->ret = -EINPROGRESS;
 			req->complete(req, -EINPROGRESS);
 		}
 
-		goto e_cpu;
+		return;
 	}
 
 	/* Operation has completed - update the queue before invoking
@@ -169,18 +167,25 @@ static void ccp_crypto_complete_on_cpu(struct work_struct *work)
 		req->complete(req, -EINPROGRESS);
 
 	/* Completion callbacks */
-	ret = cpu_work->err;
+	ret = err;
 	if (ctx->complete)
 		ret = ctx->complete(req, ret);
 	req->complete(req, ret);
 
 	/* Submit the next cmd */
 	while (held) {
+		/* Since we have already queued the cmd, we must indicate that
+		 * we can backlog so as not to "lose" this request.
+		 */
+		held->cmd->flags |= CCP_CMD_MAY_BACKLOG;
 		ret = ccp_enqueue_cmd(held->cmd);
 		if (ccp_crypto_success(ret))
 			break;
 
 		/* Error occurred, report it and get the next entry */
+		ctx = crypto_tfm_ctx(held->req->tfm);
+		if (ctx->complete)
+			ret = ctx->complete(held->req, ret);
 		held->req->complete(held->req, ret);
 
 		next = ccp_crypto_cmd_complete(held, &backlog);
@@ -194,52 +199,29 @@ static void ccp_crypto_complete_on_cpu(struct work_struct *work)
 	}
 
 	kfree(crypto_cmd);
-
-e_cpu:
-	put_cpu();
-
-	complete(&cpu_work->completion);
-}
-
-static void ccp_crypto_complete(void *data, int err)
-{
-	struct ccp_crypto_cmd *crypto_cmd = data;
-	struct ccp_crypto_cpu cpu_work;
-
-	INIT_WORK(&cpu_work.work, ccp_crypto_complete_on_cpu);
-	init_completion(&cpu_work.completion);
-	cpu_work.crypto_cmd = crypto_cmd;
-	cpu_work.err = err;
-
-	schedule_work_on(crypto_cmd->cpu, &cpu_work.work);
-
-	/* Keep the completion call synchronous */
-	wait_for_completion(&cpu_work.completion);
 }
 
 static int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd)
 {
-	struct ccp_crypto_cpu_queue *cpu_queue;
 	struct ccp_crypto_cmd *active = NULL, *tmp;
-	int cpu, ret;
-
-	cpu = get_cpu();
-	crypto_cmd->cpu = cpu;
+	unsigned long flags;
+	bool free_cmd = true;
+	int ret;
 
-	cpu_queue = this_cpu_ptr(req_queue.cpu_queue);
+	spin_lock_irqsave(&req_queue_lock, flags);
 
 	/* Check if the cmd can/should be queued */
-	if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) {
+	if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) {
 		ret = -EBUSY;
 		if (!(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG))
-			goto e_cpu;
+			goto e_lock;
 	}
 
 	/* Look for an entry with the same tfm.  If there is a cmd
-	 * with the same tfm in the list for this cpu then the current
-	 * cmd cannot be submitted to the CCP yet.
+	 * with the same tfm in the list then the current cmd cannot
+	 * be submitted to the CCP yet.
 	 */
-	list_for_each_entry(tmp, &cpu_queue->cmds, entry) {
+	list_for_each_entry(tmp, &req_queue.cmds, entry) {
 		if (crypto_cmd->tfm != tmp->tfm)
 			continue;
 		active = tmp;
@@ -250,21 +232,29 @@ static int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd)
 	if (!active) {
 		ret = ccp_enqueue_cmd(crypto_cmd->cmd);
 		if (!ccp_crypto_success(ret))
-			goto e_cpu;
+			goto e_lock;	/* Error, don't queue it */
+		if ((ret == -EBUSY) &&
+		    !(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG))
+			goto e_lock;	/* Not backlogging, don't queue it */
 	}
 
-	if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) {
+	if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) {
 		ret = -EBUSY;
-		if (cpu_queue->backlog == &cpu_queue->cmds)
-			cpu_queue->backlog = &crypto_cmd->entry;
+		if (req_queue.backlog == &req_queue.cmds)
+			req_queue.backlog = &crypto_cmd->entry;
 	}
 	crypto_cmd->ret = ret;
 
-	cpu_queue->cmd_count++;
-	list_add_tail(&crypto_cmd->entry, &cpu_queue->cmds);
+	req_queue.cmd_count++;
+	list_add_tail(&crypto_cmd->entry, &req_queue.cmds);
+
+	free_cmd = false;
 
-e_cpu:
-	put_cpu();
+e_lock:
+	spin_unlock_irqrestore(&req_queue_lock, flags);
+
+	if (free_cmd)
+		kfree(crypto_cmd);
 
 	return ret;
 }
@@ -281,7 +271,6 @@ int ccp_crypto_enqueue_request(struct crypto_async_request *req,
 {
 	struct ccp_crypto_cmd *crypto_cmd;
 	gfp_t gfp;
-	int ret;
 
 	gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
 
@@ -306,11 +295,7 @@ int ccp_crypto_enqueue_request(struct crypto_async_request *req,
 	else
 		cmd->flags &= ~CCP_CMD_MAY_BACKLOG;
 
-	ret = ccp_crypto_enqueue_cmd(crypto_cmd);
-	if (!ccp_crypto_success(ret))
-		kfree(crypto_cmd);
-
-	return ret;
+	return ccp_crypto_enqueue_cmd(crypto_cmd);
 }
 
 struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
@@ -337,21 +322,25 @@ static int ccp_register_algs(void)
 {
 	int ret;
 
-	ret = ccp_register_aes_algs(&cipher_algs);
-	if (ret)
-		return ret;
+	if (!aes_disable) {
+		ret = ccp_register_aes_algs(&cipher_algs);
+		if (ret)
+			return ret;
 
-	ret = ccp_register_aes_cmac_algs(&hash_algs);
-	if (ret)
-		return ret;
+		ret = ccp_register_aes_cmac_algs(&hash_algs);
+		if (ret)
+			return ret;
 
-	ret = ccp_register_aes_xts_algs(&cipher_algs);
-	if (ret)
-		return ret;
+		ret = ccp_register_aes_xts_algs(&cipher_algs);
+		if (ret)
+			return ret;
+	}
 
-	ret = ccp_register_sha_algs(&hash_algs);
-	if (ret)
-		return ret;
+	if (!sha_disable) {
+		ret = ccp_register_sha_algs(&hash_algs);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
@@ -374,50 +363,18 @@ static void ccp_unregister_algs(void)
 	}
 }
 
-static int ccp_init_queues(void)
-{
-	struct ccp_crypto_cpu_queue *cpu_queue;
-	int cpu;
-
-	req_queue.cpu_queue = alloc_percpu(struct ccp_crypto_cpu_queue);
-	if (!req_queue.cpu_queue)
-		return -ENOMEM;
-
-	for_each_possible_cpu(cpu) {
-		cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu);
-		INIT_LIST_HEAD(&cpu_queue->cmds);
-		cpu_queue->backlog = &cpu_queue->cmds;
-		cpu_queue->cmd_count = 0;
-	}
-
-	return 0;
-}
-
-static void ccp_fini_queue(void)
-{
-	struct ccp_crypto_cpu_queue *cpu_queue;
-	int cpu;
-
-	for_each_possible_cpu(cpu) {
-		cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu);
-		BUG_ON(!list_empty(&cpu_queue->cmds));
-	}
-	free_percpu(req_queue.cpu_queue);
-}
-
 static int ccp_crypto_init(void)
 {
 	int ret;
 
-	ret = ccp_init_queues();
-	if (ret)
-		return ret;
+	spin_lock_init(&req_queue_lock);
+	INIT_LIST_HEAD(&req_queue.cmds);
+	req_queue.backlog = &req_queue.cmds;
+	req_queue.cmd_count = 0;
 
 	ret = ccp_register_algs();
-	if (ret) {
+	if (ret)
 		ccp_unregister_algs();
-		ccp_fini_queue();
-	}
 
 	return ret;
 }
@@ -425,7 +382,6 @@ static int ccp_crypto_init(void)
 static void ccp_crypto_exit(void)
 {
 	ccp_unregister_algs();
-	ccp_fini_queue();
 }
 
 module_init(ccp_crypto_init);
diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
index 3867290b3531..873f23425245 100644
--- a/drivers/crypto/ccp/ccp-crypto-sha.c
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -24,75 +24,10 @@
 #include "ccp-crypto.h"
 
 
-struct ccp_sha_result {
-	struct completion completion;
-	int err;
-};
-
-static void ccp_sync_hash_complete(struct crypto_async_request *req, int err)
-{
-	struct ccp_sha_result *result = req->data;
-
-	if (err == -EINPROGRESS)
-		return;
-
-	result->err = err;
-	complete(&result->completion);
-}
-
-static int ccp_sync_hash(struct crypto_ahash *tfm, u8 *buf,
-			 struct scatterlist *sg, unsigned int len)
-{
-	struct ccp_sha_result result;
-	struct ahash_request *req;
-	int ret;
-
-	init_completion(&result.completion);
-
-	req = ahash_request_alloc(tfm, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
-
-	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-				   ccp_sync_hash_complete, &result);
-	ahash_request_set_crypt(req, sg, buf, len);
-
-	ret = crypto_ahash_digest(req);
-	if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
-		ret = wait_for_completion_interruptible(&result.completion);
-		if (!ret)
-			ret = result.err;
-	}
-
-	ahash_request_free(req);
-
-	return ret;
-}
-
-static int ccp_sha_finish_hmac(struct crypto_async_request *async_req)
-{
-	struct ahash_request *req = ahash_request_cast(async_req);
-	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
-	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct scatterlist sg[2];
-	unsigned int block_size =
-		crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
-	unsigned int digest_size = crypto_ahash_digestsize(tfm);
-
-	sg_init_table(sg, ARRAY_SIZE(sg));
-	sg_set_buf(&sg[0], ctx->u.sha.opad, block_size);
-	sg_set_buf(&sg[1], rctx->ctx, digest_size);
-
-	return ccp_sync_hash(ctx->u.sha.hmac_tfm, req->result, sg,
-			     block_size + digest_size);
-}
-
 static int ccp_sha_complete(struct crypto_async_request *async_req, int ret)
 {
 	struct ahash_request *req = ahash_request_cast(async_req);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
 	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
 	unsigned int digest_size = crypto_ahash_digestsize(tfm);
 
@@ -112,10 +47,6 @@ static int ccp_sha_complete(struct crypto_async_request *async_req, int ret)
 	if (req->result)
 		memcpy(req->result, rctx->ctx, digest_size);
 
-	/* If we're doing an HMAC, we need to perform that on the final op */
-	if (rctx->final && ctx->u.sha.key_len)
-		ret = ccp_sha_finish_hmac(async_req);
-
 e_free:
 	sg_free_table(&rctx->data_sg);
 
@@ -126,6 +57,7 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
 			     unsigned int final)
 {
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
 	struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
 	struct scatterlist *sg;
 	unsigned int block_size =
@@ -196,6 +128,11 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
 	rctx->cmd.u.sha.ctx_len = sizeof(rctx->ctx);
 	rctx->cmd.u.sha.src = sg;
 	rctx->cmd.u.sha.src_len = rctx->hash_cnt;
+	rctx->cmd.u.sha.opad = ctx->u.sha.key_len ?
+		&ctx->u.sha.opad_sg : NULL;
+	rctx->cmd.u.sha.opad_len = ctx->u.sha.key_len ?
+		ctx->u.sha.opad_count : 0;
+	rctx->cmd.u.sha.first = rctx->first;
 	rctx->cmd.u.sha.final = rctx->final;
 	rctx->cmd.u.sha.msg_bits = rctx->msg_bits;
 
@@ -218,7 +155,6 @@ static int ccp_sha_init(struct ahash_request *req)
 
 	memset(rctx, 0, sizeof(*rctx));
 
-	memcpy(rctx->ctx, alg->init, sizeof(rctx->ctx));
 	rctx->type = alg->type;
 	rctx->first = 1;
 
@@ -261,10 +197,13 @@ static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
 			  unsigned int key_len)
 {
 	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
-	struct scatterlist sg;
-	unsigned int block_size =
-		crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
-	unsigned int digest_size = crypto_ahash_digestsize(tfm);
+	struct crypto_shash *shash = ctx->u.sha.hmac_tfm;
+	struct {
+		struct shash_desc sdesc;
+		char ctx[crypto_shash_descsize(shash)];
+	} desc;
+	unsigned int block_size = crypto_shash_blocksize(shash);
+	unsigned int digest_size = crypto_shash_digestsize(shash);
 	int i, ret;
 
 	/* Set to zero until complete */
@@ -277,8 +216,12 @@ static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
 
 	if (key_len > block_size) {
 		/* Must hash the input key */
-		sg_init_one(&sg, key, key_len);
-		ret = ccp_sync_hash(tfm, ctx->u.sha.key, &sg, key_len);
+		desc.sdesc.tfm = shash;
+		desc.sdesc.flags = crypto_ahash_get_flags(tfm) &
+			CRYPTO_TFM_REQ_MAY_SLEEP;
+
+		ret = crypto_shash_digest(&desc.sdesc, key, key_len,
+					  ctx->u.sha.key);
 		if (ret) {
 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 			return -EINVAL;
@@ -293,6 +236,9 @@ static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
 		ctx->u.sha.opad[i] = ctx->u.sha.key[i] ^ 0x5c;
 	}
 
+	sg_init_one(&ctx->u.sha.opad_sg, ctx->u.sha.opad, block_size);
+	ctx->u.sha.opad_count = block_size;
+
 	ctx->u.sha.key_len = key_len;
 
 	return 0;
@@ -319,10 +265,9 @@ static int ccp_hmac_sha_cra_init(struct crypto_tfm *tfm)
 {
 	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
 	struct ccp_crypto_ahash_alg *alg = ccp_crypto_ahash_alg(tfm);
-	struct crypto_ahash *hmac_tfm;
+	struct crypto_shash *hmac_tfm;
 
-	hmac_tfm = crypto_alloc_ahash(alg->child_alg,
-				      CRYPTO_ALG_TYPE_AHASH, 0);
+	hmac_tfm = crypto_alloc_shash(alg->child_alg, 0, 0);
 	if (IS_ERR(hmac_tfm)) {
 		pr_warn("could not load driver %s need for HMAC support\n",
 			alg->child_alg);
@@ -339,35 +284,14 @@ static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm)
 	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	if (ctx->u.sha.hmac_tfm)
-		crypto_free_ahash(ctx->u.sha.hmac_tfm);
+		crypto_free_shash(ctx->u.sha.hmac_tfm);
 
 	ccp_sha_cra_exit(tfm);
 }
 
-static const __be32 sha1_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
-	cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
-	cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
-	cpu_to_be32(SHA1_H4), 0, 0, 0,
-};
-
-static const __be32 sha224_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
-	cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
-	cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
-	cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
-	cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
-};
-
-static const __be32 sha256_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
-	cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
-	cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
-	cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
-	cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
-};
-
 struct ccp_sha_def {
 	const char *name;
 	const char *drv_name;
-	const __be32 *init;
 	enum ccp_sha_type type;
 	u32 digest_size;
 	u32 block_size;
@@ -377,7 +301,6 @@ static struct ccp_sha_def sha_algs[] = {
 	{
 		.name		= "sha1",
 		.drv_name	= "sha1-ccp",
-		.init		= sha1_init,
 		.type		= CCP_SHA_TYPE_1,
 		.digest_size	= SHA1_DIGEST_SIZE,
 		.block_size	= SHA1_BLOCK_SIZE,
@@ -385,7 +308,6 @@ static struct ccp_sha_def sha_algs[] = {
 	{
 		.name		= "sha224",
 		.drv_name	= "sha224-ccp",
-		.init		= sha224_init,
 		.type		= CCP_SHA_TYPE_224,
 		.digest_size	= SHA224_DIGEST_SIZE,
 		.block_size	= SHA224_BLOCK_SIZE,
@@ -393,7 +315,6 @@ static struct ccp_sha_def sha_algs[] = {
 	{
 		.name		= "sha256",
 		.drv_name	= "sha256-ccp",
-		.init		= sha256_init,
 		.type		= CCP_SHA_TYPE_256,
 		.digest_size	= SHA256_DIGEST_SIZE,
 		.block_size	= SHA256_BLOCK_SIZE,
@@ -460,7 +381,6 @@ static int ccp_register_sha_alg(struct list_head *head,
 
 	INIT_LIST_HEAD(&ccp_alg->entry);
 
-	ccp_alg->init = def->init;
 	ccp_alg->type = def->type;
 
 	alg = &ccp_alg->alg;
diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h
index b222231b6169..9aa4ae184f7f 100644
--- a/drivers/crypto/ccp/ccp-crypto.h
+++ b/drivers/crypto/ccp/ccp-crypto.h
@@ -137,11 +137,14 @@ struct ccp_aes_cmac_req_ctx {
 #define MAX_SHA_BLOCK_SIZE	SHA256_BLOCK_SIZE
 
 struct ccp_sha_ctx {
+	struct scatterlist opad_sg;
+	unsigned int opad_count;
+
 	unsigned int key_len;
 	u8 key[MAX_SHA_BLOCK_SIZE];
 	u8 ipad[MAX_SHA_BLOCK_SIZE];
 	u8 opad[MAX_SHA_BLOCK_SIZE];
-	struct crypto_ahash *hmac_tfm;
+	struct crypto_shash *hmac_tfm;
 };
 
 struct ccp_sha_req_ctx {
@@ -167,9 +170,6 @@ struct ccp_sha_req_ctx {
 	unsigned int buf_count;
 	u8 buf[MAX_SHA_BLOCK_SIZE];
 
-	/* HMAC support field */
-	struct scatterlist pad_sg;
-
 	/* CCP driver command */
 	struct ccp_cmd cmd;
 };
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index c3bc21264600..2c7816149b01 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -30,6 +30,11 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION("1.0.0");
 MODULE_DESCRIPTION("AMD Cryptographic Coprocessor driver");
 
+struct ccp_tasklet_data {
+	struct completion completion;
+	struct ccp_cmd *cmd;
+};
+
 
 static struct ccp_device *ccp_dev;
 static inline struct ccp_device *ccp_get_device(void)
@@ -192,17 +197,23 @@ static struct ccp_cmd *ccp_dequeue_cmd(struct ccp_cmd_queue *cmd_q)
 	return cmd;
 }
 
-static void ccp_do_cmd_complete(struct work_struct *work)
+static void ccp_do_cmd_complete(unsigned long data)
 {
-	struct ccp_cmd *cmd = container_of(work, struct ccp_cmd, work);
+	struct ccp_tasklet_data *tdata = (struct ccp_tasklet_data *)data;
+	struct ccp_cmd *cmd = tdata->cmd;
 
 	cmd->callback(cmd->data, cmd->ret);
+	complete(&tdata->completion);
 }
 
 static int ccp_cmd_queue_thread(void *data)
 {
 	struct ccp_cmd_queue *cmd_q = (struct ccp_cmd_queue *)data;
 	struct ccp_cmd *cmd;
+	struct ccp_tasklet_data tdata;
+	struct tasklet_struct tasklet;
+
+	tasklet_init(&tasklet, ccp_do_cmd_complete, (unsigned long)&tdata);
 
 	set_current_state(TASK_INTERRUPTIBLE);
 	while (!kthread_should_stop()) {
@@ -220,8 +231,10 @@ static int ccp_cmd_queue_thread(void *data)
 		cmd->ret = ccp_run_cmd(cmd_q, cmd);
 
 		/* Schedule the completion callback */
-		INIT_WORK(&cmd->work, ccp_do_cmd_complete);
-		schedule_work(&cmd->work);
+		tdata.cmd = cmd;
+		init_completion(&tdata.completion);
+		tasklet_schedule(&tasklet);
+		wait_for_completion(&tdata.completion);
 	}
 
 	__set_current_state(TASK_RUNNING);
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index 71ed3ade7e12..9ae006d69df4 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -23,6 +23,7 @@
 #include <linux/ccp.h>
 #include <linux/scatterlist.h>
 #include <crypto/scatterwalk.h>
+#include <crypto/sha.h>
 
 #include "ccp-dev.h"
 
@@ -132,6 +133,27 @@ struct ccp_op {
 	} u;
 };
 
+/* SHA initial context values */
+static const __be32 ccp_sha1_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
+	cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
+	cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
+	cpu_to_be32(SHA1_H4), 0, 0, 0,
+};
+
+static const __be32 ccp_sha224_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
+	cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
+	cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
+	cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
+	cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
+};
+
+static const __be32 ccp_sha256_init[CCP_SHA_CTXSIZE / sizeof(__be32)] = {
+	cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
+	cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
+	cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
+	cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
+};
+
 /* The CCP cannot perform zero-length sha operations so the caller
  * is required to buffer data for the final operation.  However, a
  * sha operation for a message with a total length of zero is valid
@@ -1411,7 +1433,27 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
 	if (ret)
 		return ret;
 
-	ccp_set_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len);
+	if (sha->first) {
+		const __be32 *init;
+
+		switch (sha->type) {
+		case CCP_SHA_TYPE_1:
+			init = ccp_sha1_init;
+			break;
+		case CCP_SHA_TYPE_224:
+			init = ccp_sha224_init;
+			break;
+		case CCP_SHA_TYPE_256:
+			init = ccp_sha256_init;
+			break;
+		default:
+			ret = -EINVAL;
+			goto e_ctx;
+		}
+		memcpy(ctx.address, init, CCP_SHA_CTXSIZE);
+	} else
+		ccp_set_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len);
+
 	ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
 			      CCP_PASSTHRU_BYTESWAP_256BIT);
 	if (ret) {
@@ -1451,6 +1493,66 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
 
 	ccp_get_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len);
 
+	if (sha->final && sha->opad) {
+		/* HMAC operation, recursively perform final SHA */
+		struct ccp_cmd hmac_cmd;
+		struct scatterlist sg;
+		u64 block_size, digest_size;
+		u8 *hmac_buf;
+
+		switch (sha->type) {
+		case CCP_SHA_TYPE_1:
+			block_size = SHA1_BLOCK_SIZE;
+			digest_size = SHA1_DIGEST_SIZE;
+			break;
+		case CCP_SHA_TYPE_224:
+			block_size = SHA224_BLOCK_SIZE;
+			digest_size = SHA224_DIGEST_SIZE;
+			break;
+		case CCP_SHA_TYPE_256:
+			block_size = SHA256_BLOCK_SIZE;
+			digest_size = SHA256_DIGEST_SIZE;
+			break;
+		default:
+			ret = -EINVAL;
+			goto e_data;
+		}
+
+		if (sha->opad_len != block_size) {
+			ret = -EINVAL;
+			goto e_data;
+		}
+
+		hmac_buf = kmalloc(block_size + digest_size, GFP_KERNEL);
+		if (!hmac_buf) {
+			ret = -ENOMEM;
+			goto e_data;
+		}
+		sg_init_one(&sg, hmac_buf, block_size + digest_size);
+
+		scatterwalk_map_and_copy(hmac_buf, sha->opad, 0, block_size, 0);
+		memcpy(hmac_buf + block_size, ctx.address, digest_size);
+
+		memset(&hmac_cmd, 0, sizeof(hmac_cmd));
+		hmac_cmd.engine = CCP_ENGINE_SHA;
+		hmac_cmd.u.sha.type = sha->type;
+		hmac_cmd.u.sha.ctx = sha->ctx;
+		hmac_cmd.u.sha.ctx_len = sha->ctx_len;
+		hmac_cmd.u.sha.src = &sg;
+		hmac_cmd.u.sha.src_len = block_size + digest_size;
+		hmac_cmd.u.sha.opad = NULL;
+		hmac_cmd.u.sha.opad_len = 0;
+		hmac_cmd.u.sha.first = 1;
+		hmac_cmd.u.sha.final = 1;
+		hmac_cmd.u.sha.msg_bits = (block_size + digest_size) << 3;
+
+		ret = ccp_run_sha_cmd(cmd_q, &hmac_cmd);
+		if (ret)
+			cmd->engine_error = hmac_cmd.engine_error;
+
+		kfree(hmac_buf);
+	}
+
 e_data:
 	ccp_free_data(&src, cmd_q);
 
@@ -1666,8 +1768,8 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q,
 
 		op.dst.type = CCP_MEMTYPE_SYSTEM;
 		op.dst.u.dma.address = sg_dma_address(dst.sg_wa.sg);
-		op.src.u.dma.offset = dst.sg_wa.sg_used;
-		op.src.u.dma.length = op.src.u.dma.length;
+		op.dst.u.dma.offset = dst.sg_wa.sg_used;
+		op.dst.u.dma.length = op.src.u.dma.length;
 
 		ret = ccp_perform_passthru(&op);
 		if (ret) {
diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
index a6db7fa6f891..08761d61d4f5 100644
--- a/drivers/crypto/mxs-dcp.c
+++ b/drivers/crypto/mxs-dcp.c
@@ -83,13 +83,16 @@ struct dcp_async_ctx {
 	unsigned int			hot:1;
 
 	/* Crypto-specific context */
-	unsigned int			enc:1;
-	unsigned int			ecb:1;
 	struct crypto_ablkcipher	*fallback;
 	unsigned int			key_len;
 	uint8_t				key[AES_KEYSIZE_128];
 };
 
+struct dcp_aes_req_ctx {
+	unsigned int	enc:1;
+	unsigned int	ecb:1;
+};
+
 struct dcp_sha_req_ctx {
 	unsigned int	init:1;
 	unsigned int	fini:1;
@@ -190,10 +193,12 @@ static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
 /*
  * Encryption (AES128)
  */
-static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, int init)
+static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
+			   struct ablkcipher_request *req, int init)
 {
 	struct dcp *sdcp = global_sdcp;
 	struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
+	struct dcp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 	int ret;
 
 	dma_addr_t key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
@@ -212,14 +217,14 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, int init)
 	/* Payload contains the key. */
 	desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY;
 
-	if (actx->enc)
+	if (rctx->enc)
 		desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT;
 	if (init)
 		desc->control0 |= MXS_DCP_CONTROL0_CIPHER_INIT;
 
 	desc->control1 = MXS_DCP_CONTROL1_CIPHER_SELECT_AES128;
 
-	if (actx->ecb)
+	if (rctx->ecb)
 		desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_ECB;
 	else
 		desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC;
@@ -247,6 +252,7 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
 
 	struct ablkcipher_request *req = ablkcipher_request_cast(arq);
 	struct dcp_async_ctx *actx = crypto_tfm_ctx(arq->tfm);
+	struct dcp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 
 	struct scatterlist *dst = req->dst;
 	struct scatterlist *src = req->src;
@@ -271,7 +277,7 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
 	/* Copy the key from the temporary location. */
 	memcpy(key, actx->key, actx->key_len);
 
-	if (!actx->ecb) {
+	if (!rctx->ecb) {
 		/* Copy the CBC IV just past the key. */
 		memcpy(key + AES_KEYSIZE_128, req->info, AES_KEYSIZE_128);
 		/* CBC needs the INIT set. */
@@ -300,7 +306,7 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
 			 * submit the buffer.
 			 */
 			if (actx->fill == out_off || sg_is_last(src)) {
-				ret = mxs_dcp_run_aes(actx, init);
+				ret = mxs_dcp_run_aes(actx, req, init);
 				if (ret)
 					return ret;
 				init = 0;
@@ -391,13 +397,14 @@ static int mxs_dcp_aes_enqueue(struct ablkcipher_request *req, int enc, int ecb)
 	struct dcp *sdcp = global_sdcp;
 	struct crypto_async_request *arq = &req->base;
 	struct dcp_async_ctx *actx = crypto_tfm_ctx(arq->tfm);
+	struct dcp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 	int ret;
 
 	if (unlikely(actx->key_len != AES_KEYSIZE_128))
 		return mxs_dcp_block_fallback(req, enc);
 
-	actx->enc = enc;
-	actx->ecb = ecb;
+	rctx->enc = enc;
+	rctx->ecb = ecb;
 	actx->chan = DCP_CHAN_CRYPTO;
 
 	mutex_lock(&sdcp->mutex[actx->chan]);
@@ -484,7 +491,7 @@ static int mxs_dcp_aes_fallback_init(struct crypto_tfm *tfm)
 		return PTR_ERR(blk);
 
 	actx->fallback = blk;
-	tfm->crt_ablkcipher.reqsize = sizeof(struct dcp_async_ctx);
+	tfm->crt_ablkcipher.reqsize = sizeof(struct dcp_aes_req_ctx);
 	return 0;
 }
 
@@ -901,9 +908,14 @@ static int mxs_dcp_probe(struct platform_device *pdev)
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dcp_vmi_irq = platform_get_irq(pdev, 0);
+	if (dcp_vmi_irq < 0) {
+		ret = dcp_vmi_irq;
+		goto err_mutex;
+	}
+
 	dcp_irq = platform_get_irq(pdev, 1);
-	if (dcp_vmi_irq < 0 || dcp_irq < 0) {
-		ret = -EINVAL;
+	if (dcp_irq < 0) {
+		ret = dcp_irq;
 		goto err_mutex;
 	}
 
@@ -935,15 +947,16 @@ static int mxs_dcp_probe(struct platform_device *pdev)
 	}
 
 	/* Allocate coherent helper block. */
-	sdcp->coh = kzalloc(sizeof(struct dcp_coherent_block), GFP_KERNEL);
+	sdcp->coh = devm_kzalloc(dev, sizeof(*sdcp->coh), GFP_KERNEL);
 	if (!sdcp->coh) {
-		dev_err(dev, "Error allocating coherent block\n");
 		ret = -ENOMEM;
 		goto err_mutex;
 	}
 
 	/* Restart the DCP block. */
-	stmp_reset_block(sdcp->base);
+	ret = stmp_reset_block(sdcp->base);
+	if (ret)
+		goto err_mutex;
 
 	/* Initialize control register. */
 	writel(MXS_DCP_CTRL_GATHER_RESIDUAL_WRITES |
@@ -982,7 +995,7 @@ static int mxs_dcp_probe(struct platform_device *pdev)
 	if (IS_ERR(sdcp->thread[DCP_CHAN_HASH_SHA])) {
 		dev_err(dev, "Error starting SHA thread!\n");
 		ret = PTR_ERR(sdcp->thread[DCP_CHAN_HASH_SHA]);
-		goto err_free_coherent;
+		goto err_mutex;
 	}
 
 	sdcp->thread[DCP_CHAN_CRYPTO] = kthread_run(dcp_chan_thread_aes,
@@ -1040,8 +1053,6 @@ err_destroy_aes_thread:
 err_destroy_sha_thread:
 	kthread_stop(sdcp->thread[DCP_CHAN_HASH_SHA]);
 
-err_free_coherent:
-	kfree(sdcp->coh);
 err_mutex:
 	mutex_unlock(&global_mutex);
 	return ret;
@@ -1051,8 +1062,6 @@ static int mxs_dcp_remove(struct platform_device *pdev)
 {
 	struct dcp *sdcp = platform_get_drvdata(pdev);
 
-	kfree(sdcp->coh);
-
 	if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA256)
 		crypto_unregister_ahash(&dcp_sha256_alg);
 
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
new file mode 100644
index 000000000000..006d9144485f
--- /dev/null
+++ b/drivers/crypto/omap-des.c
@@ -0,0 +1,1218 @@
+/*
+ * Support for OMAP DES and Triple DES HW acceleration.
+ *
+ * Copyright (c) 2013 Texas Instruments Incorporated
+ * Author: Joel Fernandes <joelf@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 pr_fmt(fmt) "%s: " fmt, __func__
+
+#ifdef DEBUG
+#define prn(num) printk(#num "=%d\n", num)
+#define prx(num) printk(#num "=%x\n", num)
+#else
+#define prn(num) do { } while (0)
+#define prx(num)  do { } while (0)
+#endif
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/des.h>
+
+#define DST_MAXBURST			2
+
+#define DES_BLOCK_WORDS		(DES_BLOCK_SIZE >> 2)
+
+#define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset)
+
+#define DES_REG_KEY(dd, x)		((dd)->pdata->key_ofs - \
+						((x ^ 0x01) * 0x04))
+
+#define DES_REG_IV(dd, x)		((dd)->pdata->iv_ofs + ((x) * 0x04))
+
+#define DES_REG_CTRL(dd)		((dd)->pdata->ctrl_ofs)
+#define DES_REG_CTRL_CBC		BIT(4)
+#define DES_REG_CTRL_TDES		BIT(3)
+#define DES_REG_CTRL_DIRECTION		BIT(2)
+#define DES_REG_CTRL_INPUT_READY	BIT(1)
+#define DES_REG_CTRL_OUTPUT_READY	BIT(0)
+
+#define DES_REG_DATA_N(dd, x)		((dd)->pdata->data_ofs + ((x) * 0x04))
+
+#define DES_REG_REV(dd)			((dd)->pdata->rev_ofs)
+
+#define DES_REG_MASK(dd)		((dd)->pdata->mask_ofs)
+
+#define DES_REG_LENGTH_N(x)		(0x24 + ((x) * 0x04))
+
+#define DES_REG_IRQ_STATUS(dd)         ((dd)->pdata->irq_status_ofs)
+#define DES_REG_IRQ_ENABLE(dd)         ((dd)->pdata->irq_enable_ofs)
+#define DES_REG_IRQ_DATA_IN            BIT(1)
+#define DES_REG_IRQ_DATA_OUT           BIT(2)
+
+#define FLAGS_MODE_MASK		0x000f
+#define FLAGS_ENCRYPT		BIT(0)
+#define FLAGS_CBC		BIT(1)
+#define FLAGS_INIT		BIT(4)
+#define FLAGS_BUSY		BIT(6)
+
+struct omap_des_ctx {
+	struct omap_des_dev *dd;
+
+	int		keylen;
+	u32		key[(3 * DES_KEY_SIZE) / sizeof(u32)];
+	unsigned long	flags;
+};
+
+struct omap_des_reqctx {
+	unsigned long mode;
+};
+
+#define OMAP_DES_QUEUE_LENGTH	1
+#define OMAP_DES_CACHE_SIZE	0
+
+struct omap_des_algs_info {
+	struct crypto_alg	*algs_list;
+	unsigned int		size;
+	unsigned int		registered;
+};
+
+struct omap_des_pdata {
+	struct omap_des_algs_info	*algs_info;
+	unsigned int	algs_info_size;
+
+	void		(*trigger)(struct omap_des_dev *dd, int length);
+
+	u32		key_ofs;
+	u32		iv_ofs;
+	u32		ctrl_ofs;
+	u32		data_ofs;
+	u32		rev_ofs;
+	u32		mask_ofs;
+	u32             irq_enable_ofs;
+	u32             irq_status_ofs;
+
+	u32		dma_enable_in;
+	u32		dma_enable_out;
+	u32		dma_start;
+
+	u32		major_mask;
+	u32		major_shift;
+	u32		minor_mask;
+	u32		minor_shift;
+};
+
+struct omap_des_dev {
+	struct list_head	list;
+	unsigned long		phys_base;
+	void __iomem		*io_base;
+	struct omap_des_ctx	*ctx;
+	struct device		*dev;
+	unsigned long		flags;
+	int			err;
+
+	/* spinlock used for queues */
+	spinlock_t		lock;
+	struct crypto_queue	queue;
+
+	struct tasklet_struct	done_task;
+	struct tasklet_struct	queue_task;
+
+	struct ablkcipher_request	*req;
+	/*
+	 * total is used by PIO mode for book keeping so introduce
+	 * variable total_save as need it to calc page_order
+	 */
+	size_t                          total;
+	size_t                          total_save;
+
+	struct scatterlist		*in_sg;
+	struct scatterlist		*out_sg;
+
+	/* Buffers for copying for unaligned cases */
+	struct scatterlist		in_sgl;
+	struct scatterlist		out_sgl;
+	struct scatterlist		*orig_out;
+	int				sgs_copied;
+
+	struct scatter_walk		in_walk;
+	struct scatter_walk		out_walk;
+	int			dma_in;
+	struct dma_chan		*dma_lch_in;
+	int			dma_out;
+	struct dma_chan		*dma_lch_out;
+	int			in_sg_len;
+	int			out_sg_len;
+	int			pio_only;
+	const struct omap_des_pdata	*pdata;
+};
+
+/* keep registered devices data here */
+static LIST_HEAD(dev_list);
+static DEFINE_SPINLOCK(list_lock);
+
+#ifdef DEBUG
+#define omap_des_read(dd, offset)                               \
+	({                                                              \
+	 int _read_ret;                                          \
+	 _read_ret = __raw_readl(dd->io_base + offset);          \
+	 pr_err("omap_des_read(" #offset "=%#x)= %#x\n",       \
+		 offset, _read_ret);                            \
+	 _read_ret;                                              \
+	 })
+#else
+static inline u32 omap_des_read(struct omap_des_dev *dd, u32 offset)
+{
+	return __raw_readl(dd->io_base + offset);
+}
+#endif
+
+#ifdef DEBUG
+#define omap_des_write(dd, offset, value)                               \
+	do {                                                            \
+		pr_err("omap_des_write(" #offset "=%#x) value=%#x\n", \
+				offset, value);                                \
+		__raw_writel(value, dd->io_base + offset);              \
+	} while (0)
+#else
+static inline void omap_des_write(struct omap_des_dev *dd, u32 offset,
+		u32 value)
+{
+	__raw_writel(value, dd->io_base + offset);
+}
+#endif
+
+static inline void omap_des_write_mask(struct omap_des_dev *dd, u32 offset,
+					u32 value, u32 mask)
+{
+	u32 val;
+
+	val = omap_des_read(dd, offset);
+	val &= ~mask;
+	val |= value;
+	omap_des_write(dd, offset, val);
+}
+
+static void omap_des_write_n(struct omap_des_dev *dd, u32 offset,
+					u32 *value, int count)
+{
+	for (; count--; value++, offset += 4)
+		omap_des_write(dd, offset, *value);
+}
+
+static int omap_des_hw_init(struct omap_des_dev *dd)
+{
+	/*
+	 * 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);
+
+	if (!(dd->flags & FLAGS_INIT)) {
+		dd->flags |= FLAGS_INIT;
+		dd->err = 0;
+	}
+
+	return 0;
+}
+
+static int omap_des_write_ctrl(struct omap_des_dev *dd)
+{
+	unsigned int key32;
+	int i, err;
+	u32 val = 0, mask = 0;
+
+	err = omap_des_hw_init(dd);
+	if (err)
+		return err;
+
+	key32 = dd->ctx->keylen / sizeof(u32);
+
+	/* it seems a key should always be set even if it has not changed */
+	for (i = 0; i < key32; i++) {
+		omap_des_write(dd, DES_REG_KEY(dd, i),
+			       __le32_to_cpu(dd->ctx->key[i]));
+	}
+
+	if ((dd->flags & FLAGS_CBC) && dd->req->info)
+		omap_des_write_n(dd, DES_REG_IV(dd, 0), dd->req->info, 2);
+
+	if (dd->flags & FLAGS_CBC)
+		val |= DES_REG_CTRL_CBC;
+	if (dd->flags & FLAGS_ENCRYPT)
+		val |= DES_REG_CTRL_DIRECTION;
+	if (key32 == 6)
+		val |= DES_REG_CTRL_TDES;
+
+	mask |= DES_REG_CTRL_CBC | DES_REG_CTRL_DIRECTION | DES_REG_CTRL_TDES;
+
+	omap_des_write_mask(dd, DES_REG_CTRL(dd), val, mask);
+
+	return 0;
+}
+
+static void omap_des_dma_trigger_omap4(struct omap_des_dev *dd, int length)
+{
+	u32 mask, val;
+
+	omap_des_write(dd, DES_REG_LENGTH_N(0), length);
+
+	val = dd->pdata->dma_start;
+
+	if (dd->dma_lch_out != NULL)
+		val |= dd->pdata->dma_enable_out;
+	if (dd->dma_lch_in != NULL)
+		val |= dd->pdata->dma_enable_in;
+
+	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
+	       dd->pdata->dma_start;
+
+	omap_des_write_mask(dd, DES_REG_MASK(dd), val, mask);
+}
+
+static void omap_des_dma_stop(struct omap_des_dev *dd)
+{
+	u32 mask;
+
+	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
+	       dd->pdata->dma_start;
+
+	omap_des_write_mask(dd, DES_REG_MASK(dd), 0, mask);
+}
+
+static struct omap_des_dev *omap_des_find_dev(struct omap_des_ctx *ctx)
+{
+	struct omap_des_dev *dd = NULL, *tmp;
+
+	spin_lock_bh(&list_lock);
+	if (!ctx->dd) {
+		list_for_each_entry(tmp, &dev_list, list) {
+			/* FIXME: take fist available des core */
+			dd = tmp;
+			break;
+		}
+		ctx->dd = dd;
+	} else {
+		/* already found before */
+		dd = ctx->dd;
+	}
+	spin_unlock_bh(&list_lock);
+
+	return dd;
+}
+
+static void omap_des_dma_out_callback(void *data)
+{
+	struct omap_des_dev *dd = data;
+
+	/* dma_lch_out - completed */
+	tasklet_schedule(&dd->done_task);
+}
+
+static int omap_des_dma_init(struct omap_des_dev *dd)
+{
+	int err = -ENOMEM;
+	dma_cap_mask_t mask;
+
+	dd->dma_lch_out = NULL;
+	dd->dma_lch_in = NULL;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	dd->dma_lch_in = dma_request_slave_channel_compat(mask,
+							  omap_dma_filter_fn,
+							  &dd->dma_in,
+							  dd->dev, "rx");
+	if (!dd->dma_lch_in) {
+		dev_err(dd->dev, "Unable to request in DMA channel\n");
+		goto err_dma_in;
+	}
+
+	dd->dma_lch_out = dma_request_slave_channel_compat(mask,
+							   omap_dma_filter_fn,
+							   &dd->dma_out,
+							   dd->dev, "tx");
+	if (!dd->dma_lch_out) {
+		dev_err(dd->dev, "Unable to request out DMA channel\n");
+		goto err_dma_out;
+	}
+
+	return 0;
+
+err_dma_out:
+	dma_release_channel(dd->dma_lch_in);
+err_dma_in:
+	if (err)
+		pr_err("error: %d\n", err);
+	return err;
+}
+
+static void omap_des_dma_cleanup(struct omap_des_dev *dd)
+{
+	dma_release_channel(dd->dma_lch_out);
+	dma_release_channel(dd->dma_lch_in);
+}
+
+static void sg_copy_buf(void *buf, struct scatterlist *sg,
+			      unsigned int start, unsigned int nbytes, int out)
+{
+	struct scatter_walk walk;
+
+	if (!nbytes)
+		return;
+
+	scatterwalk_start(&walk, sg);
+	scatterwalk_advance(&walk, start);
+	scatterwalk_copychunks(buf, &walk, nbytes, out);
+	scatterwalk_done(&walk, out, 0);
+}
+
+static int omap_des_crypt_dma(struct crypto_tfm *tfm,
+		struct scatterlist *in_sg, struct scatterlist *out_sg,
+		int in_sg_len, int out_sg_len)
+{
+	struct omap_des_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct omap_des_dev *dd = ctx->dd;
+	struct dma_async_tx_descriptor *tx_in, *tx_out;
+	struct dma_slave_config cfg;
+	int ret;
+
+	if (dd->pio_only) {
+		scatterwalk_start(&dd->in_walk, dd->in_sg);
+		scatterwalk_start(&dd->out_walk, dd->out_sg);
+
+		/* Enable DATAIN interrupt and let it take
+		   care of the rest */
+		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
+		return 0;
+	}
+
+	dma_sync_sg_for_device(dd->dev, dd->in_sg, in_sg_len, DMA_TO_DEVICE);
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.src_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
+	cfg.dst_addr = dd->phys_base + DES_REG_DATA_N(dd, 0);
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.src_maxburst = DST_MAXBURST;
+	cfg.dst_maxburst = DST_MAXBURST;
+
+	/* IN */
+	ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
+	if (ret) {
+		dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
+			ret);
+		return ret;
+	}
+
+	tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, in_sg_len,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx_in) {
+		dev_err(dd->dev, "IN prep_slave_sg() failed\n");
+		return -EINVAL;
+	}
+
+	/* No callback necessary */
+	tx_in->callback_param = dd;
+
+	/* OUT */
+	ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
+	if (ret) {
+		dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
+			ret);
+		return ret;
+	}
+
+	tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len,
+					DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx_out) {
+		dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
+		return -EINVAL;
+	}
+
+	tx_out->callback = omap_des_dma_out_callback;
+	tx_out->callback_param = dd;
+
+	dmaengine_submit(tx_in);
+	dmaengine_submit(tx_out);
+
+	dma_async_issue_pending(dd->dma_lch_in);
+	dma_async_issue_pending(dd->dma_lch_out);
+
+	/* start DMA */
+	dd->pdata->trigger(dd, dd->total);
+
+	return 0;
+}
+
+static int omap_des_crypt_dma_start(struct omap_des_dev *dd)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
+					crypto_ablkcipher_reqtfm(dd->req));
+	int err;
+
+	pr_debug("total: %d\n", dd->total);
+
+	if (!dd->pio_only) {
+		err = dma_map_sg(dd->dev, dd->in_sg, dd->in_sg_len,
+				 DMA_TO_DEVICE);
+		if (!err) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			return -EINVAL;
+		}
+
+		err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len,
+				 DMA_FROM_DEVICE);
+		if (!err) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			return -EINVAL;
+		}
+	}
+
+	err = omap_des_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len,
+				 dd->out_sg_len);
+	if (err && !dd->pio_only) {
+		dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
+		dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
+			     DMA_FROM_DEVICE);
+	}
+
+	return err;
+}
+
+static void omap_des_finish_req(struct omap_des_dev *dd, int err)
+{
+	struct ablkcipher_request *req = dd->req;
+
+	pr_debug("err: %d\n", err);
+
+	pm_runtime_put(dd->dev);
+	dd->flags &= ~FLAGS_BUSY;
+
+	req->base.complete(&req->base, err);
+}
+
+static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
+{
+	int err = 0;
+
+	pr_debug("total: %d\n", dd->total);
+
+	omap_des_dma_stop(dd);
+
+	dmaengine_terminate_all(dd->dma_lch_in);
+	dmaengine_terminate_all(dd->dma_lch_out);
+
+	dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
+	dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
+
+	return err;
+}
+
+int omap_des_copy_needed(struct scatterlist *sg)
+{
+	while (sg) {
+		if (!IS_ALIGNED(sg->offset, 4))
+			return -1;
+		if (!IS_ALIGNED(sg->length, DES_BLOCK_SIZE))
+			return -1;
+		sg = sg_next(sg);
+	}
+	return 0;
+}
+
+int omap_des_copy_sgs(struct omap_des_dev *dd)
+{
+	void *buf_in, *buf_out;
+	int pages;
+
+	pages = dd->total >> PAGE_SHIFT;
+
+	if (dd->total & (PAGE_SIZE-1))
+		pages++;
+
+	BUG_ON(!pages);
+
+	buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
+	buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
+
+	if (!buf_in || !buf_out) {
+		pr_err("Couldn't allocated pages for unaligned cases.\n");
+		return -1;
+	}
+
+	dd->orig_out = dd->out_sg;
+
+	sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0);
+
+	sg_init_table(&dd->in_sgl, 1);
+	sg_set_buf(&dd->in_sgl, buf_in, dd->total);
+	dd->in_sg = &dd->in_sgl;
+
+	sg_init_table(&dd->out_sgl, 1);
+	sg_set_buf(&dd->out_sgl, buf_out, dd->total);
+	dd->out_sg = &dd->out_sgl;
+
+	return 0;
+}
+
+static int omap_des_handle_queue(struct omap_des_dev *dd,
+			       struct ablkcipher_request *req)
+{
+	struct crypto_async_request *async_req, *backlog;
+	struct omap_des_ctx *ctx;
+	struct omap_des_reqctx *rctx;
+	unsigned long flags;
+	int err, ret = 0;
+
+	spin_lock_irqsave(&dd->lock, flags);
+	if (req)
+		ret = ablkcipher_enqueue_request(&dd->queue, req);
+	if (dd->flags & FLAGS_BUSY) {
+		spin_unlock_irqrestore(&dd->lock, flags);
+		return ret;
+	}
+	backlog = crypto_get_backlog(&dd->queue);
+	async_req = crypto_dequeue_request(&dd->queue);
+	if (async_req)
+		dd->flags |= FLAGS_BUSY;
+	spin_unlock_irqrestore(&dd->lock, flags);
+
+	if (!async_req)
+		return ret;
+
+	if (backlog)
+		backlog->complete(backlog, -EINPROGRESS);
+
+	req = ablkcipher_request_cast(async_req);
+
+	/* assign new request to device */
+	dd->req = req;
+	dd->total = req->nbytes;
+	dd->total_save = req->nbytes;
+	dd->in_sg = req->src;
+	dd->out_sg = req->dst;
+
+	if (omap_des_copy_needed(dd->in_sg) ||
+	    omap_des_copy_needed(dd->out_sg)) {
+		if (omap_des_copy_sgs(dd))
+			pr_err("Failed to copy SGs for unaligned cases\n");
+		dd->sgs_copied = 1;
+	} else {
+		dd->sgs_copied = 0;
+	}
+
+	dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total);
+	dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total);
+	BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0);
+
+	rctx = ablkcipher_request_ctx(req);
+	ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
+	rctx->mode &= FLAGS_MODE_MASK;
+	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
+
+	dd->ctx = ctx;
+	ctx->dd = dd;
+
+	err = omap_des_write_ctrl(dd);
+	if (!err)
+		err = omap_des_crypt_dma_start(dd);
+	if (err) {
+		/* des_task will not finish it, so do it here */
+		omap_des_finish_req(dd, err);
+		tasklet_schedule(&dd->queue_task);
+	}
+
+	return ret; /* return ret, which is enqueue return value */
+}
+
+static void omap_des_done_task(unsigned long data)
+{
+	struct omap_des_dev *dd = (struct omap_des_dev *)data;
+	void *buf_in, *buf_out;
+	int pages;
+
+	pr_debug("enter done_task\n");
+
+	if (!dd->pio_only) {
+		dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len,
+				       DMA_FROM_DEVICE);
+		dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
+		dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
+			     DMA_FROM_DEVICE);
+		omap_des_crypt_dma_stop(dd);
+	}
+
+	if (dd->sgs_copied) {
+		buf_in = sg_virt(&dd->in_sgl);
+		buf_out = sg_virt(&dd->out_sgl);
+
+		sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
+
+		pages = get_order(dd->total_save);
+		free_pages((unsigned long)buf_in, pages);
+		free_pages((unsigned long)buf_out, pages);
+	}
+
+	omap_des_finish_req(dd, 0);
+	omap_des_handle_queue(dd, NULL);
+
+	pr_debug("exit\n");
+}
+
+static void omap_des_queue_task(unsigned long data)
+{
+	struct omap_des_dev *dd = (struct omap_des_dev *)data;
+
+	omap_des_handle_queue(dd, NULL);
+}
+
+static int omap_des_crypt(struct ablkcipher_request *req, unsigned long mode)
+{
+	struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(
+			crypto_ablkcipher_reqtfm(req));
+	struct omap_des_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct omap_des_dev *dd;
+
+	pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
+		 !!(mode & FLAGS_ENCRYPT),
+		 !!(mode & FLAGS_CBC));
+
+	if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
+		pr_err("request size is not exact amount of DES blocks\n");
+		return -EINVAL;
+	}
+
+	dd = omap_des_find_dev(ctx);
+	if (!dd)
+		return -ENODEV;
+
+	rctx->mode = mode;
+
+	return omap_des_handle_queue(dd, req);
+}
+
+/* ********************** ALG API ************************************ */
+
+static int omap_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			   unsigned int keylen)
+{
+	struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+
+	if (keylen != DES_KEY_SIZE && keylen != (3*DES_KEY_SIZE))
+		return -EINVAL;
+
+	pr_debug("enter, keylen: %d\n", keylen);
+
+	memcpy(ctx->key, key, keylen);
+	ctx->keylen = keylen;
+
+	return 0;
+}
+
+static int omap_des_ecb_encrypt(struct ablkcipher_request *req)
+{
+	return omap_des_crypt(req, FLAGS_ENCRYPT);
+}
+
+static int omap_des_ecb_decrypt(struct ablkcipher_request *req)
+{
+	return omap_des_crypt(req, 0);
+}
+
+static int omap_des_cbc_encrypt(struct ablkcipher_request *req)
+{
+	return omap_des_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
+}
+
+static int omap_des_cbc_decrypt(struct ablkcipher_request *req)
+{
+	return omap_des_crypt(req, FLAGS_CBC);
+}
+
+static int omap_des_cra_init(struct crypto_tfm *tfm)
+{
+	pr_debug("enter\n");
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct omap_des_reqctx);
+
+	return 0;
+}
+
+static void omap_des_cra_exit(struct crypto_tfm *tfm)
+{
+	pr_debug("enter\n");
+}
+
+/* ********************** ALGS ************************************ */
+
+static struct crypto_alg algs_ecb_cbc[] = {
+{
+	.cra_name		= "ecb(des)",
+	.cra_driver_name	= "ecb-des-omap",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct omap_des_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= omap_des_cra_init,
+	.cra_exit		= omap_des_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= DES_KEY_SIZE,
+		.max_keysize	= DES_KEY_SIZE,
+		.setkey		= omap_des_setkey,
+		.encrypt	= omap_des_ecb_encrypt,
+		.decrypt	= omap_des_ecb_decrypt,
+	}
+},
+{
+	.cra_name		= "cbc(des)",
+	.cra_driver_name	= "cbc-des-omap",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct omap_des_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= omap_des_cra_init,
+	.cra_exit		= omap_des_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= DES_KEY_SIZE,
+		.max_keysize	= DES_KEY_SIZE,
+		.ivsize		= DES_BLOCK_SIZE,
+		.setkey		= omap_des_setkey,
+		.encrypt	= omap_des_cbc_encrypt,
+		.decrypt	= omap_des_cbc_decrypt,
+	}
+},
+{
+	.cra_name		= "ecb(des3_ede)",
+	.cra_driver_name	= "ecb-des3-omap",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct omap_des_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= omap_des_cra_init,
+	.cra_exit		= omap_des_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= 3*DES_KEY_SIZE,
+		.max_keysize	= 3*DES_KEY_SIZE,
+		.setkey		= omap_des_setkey,
+		.encrypt	= omap_des_ecb_encrypt,
+		.decrypt	= omap_des_ecb_decrypt,
+	}
+},
+{
+	.cra_name		= "cbc(des3_ede)",
+	.cra_driver_name	= "cbc-des3-omap",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct omap_des_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= omap_des_cra_init,
+	.cra_exit		= omap_des_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= 3*DES_KEY_SIZE,
+		.max_keysize	= 3*DES_KEY_SIZE,
+		.ivsize		= DES_BLOCK_SIZE,
+		.setkey		= omap_des_setkey,
+		.encrypt	= omap_des_cbc_encrypt,
+		.decrypt	= omap_des_cbc_decrypt,
+	}
+}
+};
+
+static struct omap_des_algs_info omap_des_algs_info_ecb_cbc[] = {
+	{
+		.algs_list	= algs_ecb_cbc,
+		.size		= ARRAY_SIZE(algs_ecb_cbc),
+	},
+};
+
+#ifdef CONFIG_OF
+static const struct omap_des_pdata omap_des_pdata_omap4 = {
+	.algs_info	= omap_des_algs_info_ecb_cbc,
+	.algs_info_size	= ARRAY_SIZE(omap_des_algs_info_ecb_cbc),
+	.trigger	= omap_des_dma_trigger_omap4,
+	.key_ofs	= 0x14,
+	.iv_ofs		= 0x18,
+	.ctrl_ofs	= 0x20,
+	.data_ofs	= 0x28,
+	.rev_ofs	= 0x30,
+	.mask_ofs	= 0x34,
+	.irq_status_ofs = 0x3c,
+	.irq_enable_ofs = 0x40,
+	.dma_enable_in	= BIT(5),
+	.dma_enable_out	= BIT(6),
+	.major_mask	= 0x0700,
+	.major_shift	= 8,
+	.minor_mask	= 0x003f,
+	.minor_shift	= 0,
+};
+
+static irqreturn_t omap_des_irq(int irq, void *dev_id)
+{
+	struct omap_des_dev *dd = dev_id;
+	u32 status, i;
+	u32 *src, *dst;
+
+	status = omap_des_read(dd, DES_REG_IRQ_STATUS(dd));
+	if (status & DES_REG_IRQ_DATA_IN) {
+		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
+
+		BUG_ON(!dd->in_sg);
+
+		BUG_ON(_calc_walked(in) > dd->in_sg->length);
+
+		src = sg_virt(dd->in_sg) + _calc_walked(in);
+
+		for (i = 0; i < DES_BLOCK_WORDS; i++) {
+			omap_des_write(dd, DES_REG_DATA_N(dd, i), *src);
+
+			scatterwalk_advance(&dd->in_walk, 4);
+			if (dd->in_sg->length == _calc_walked(in)) {
+				dd->in_sg = scatterwalk_sg_next(dd->in_sg);
+				if (dd->in_sg) {
+					scatterwalk_start(&dd->in_walk,
+							  dd->in_sg);
+					src = sg_virt(dd->in_sg) +
+					      _calc_walked(in);
+				}
+			} else {
+				src++;
+			}
+		}
+
+		/* Clear IRQ status */
+		status &= ~DES_REG_IRQ_DATA_IN;
+		omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
+
+		/* Enable DATA_OUT interrupt */
+		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x4);
+
+	} else if (status & DES_REG_IRQ_DATA_OUT) {
+		omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0);
+
+		BUG_ON(!dd->out_sg);
+
+		BUG_ON(_calc_walked(out) > dd->out_sg->length);
+
+		dst = sg_virt(dd->out_sg) + _calc_walked(out);
+
+		for (i = 0; i < DES_BLOCK_WORDS; i++) {
+			*dst = omap_des_read(dd, DES_REG_DATA_N(dd, i));
+			scatterwalk_advance(&dd->out_walk, 4);
+			if (dd->out_sg->length == _calc_walked(out)) {
+				dd->out_sg = scatterwalk_sg_next(dd->out_sg);
+				if (dd->out_sg) {
+					scatterwalk_start(&dd->out_walk,
+							  dd->out_sg);
+					dst = sg_virt(dd->out_sg) +
+					      _calc_walked(out);
+				}
+			} else {
+				dst++;
+			}
+		}
+
+		dd->total -= DES_BLOCK_SIZE;
+
+		BUG_ON(dd->total < 0);
+
+		/* Clear IRQ status */
+		status &= ~DES_REG_IRQ_DATA_OUT;
+		omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status);
+
+		if (!dd->total)
+			/* All bytes read! */
+			tasklet_schedule(&dd->done_task);
+		else
+			/* Enable DATA_IN interrupt for next block */
+			omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static const struct of_device_id omap_des_of_match[] = {
+	{
+		.compatible	= "ti,omap4-des",
+		.data		= &omap_des_pdata_omap4,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_des_of_match);
+
+static int omap_des_get_of(struct omap_des_dev *dd,
+		struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(omap_des_of_match), &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "no compatible OF match\n");
+		return -EINVAL;
+	}
+
+	dd->dma_out = -1; /* Dummy value that's unused */
+	dd->dma_in = -1; /* Dummy value that's unused */
+	dd->pdata = match->data;
+
+	return 0;
+}
+#else
+static int omap_des_get_of(struct omap_des_dev *dd,
+		struct device *dev)
+{
+	return -EINVAL;
+}
+#endif
+
+static int omap_des_get_pdev(struct omap_des_dev *dd,
+		struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	int err = 0;
+
+	/* Get the DMA out channel */
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!r) {
+		dev_err(dev, "no DMA out resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	dd->dma_out = r->start;
+
+	/* Get the DMA in channel */
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!r) {
+		dev_err(dev, "no DMA in resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	dd->dma_in = r->start;
+
+	/* non-DT devices get pdata from pdev */
+	dd->pdata = pdev->dev.platform_data;
+
+err:
+	return err;
+}
+
+static int omap_des_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct omap_des_dev *dd;
+	struct crypto_alg *algp;
+	struct resource *res;
+	int err = -ENOMEM, i, j, irq = -1;
+	u32 reg;
+
+	dd = devm_kzalloc(dev, sizeof(struct omap_des_dev), GFP_KERNEL);
+	if (dd == NULL) {
+		dev_err(dev, "unable to alloc data struct.\n");
+		goto err_data;
+	}
+	dd->dev = dev;
+	platform_set_drvdata(pdev, dd);
+
+	spin_lock_init(&dd->lock);
+	crypto_init_queue(&dd->queue, OMAP_DES_QUEUE_LENGTH);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no MEM resource info\n");
+		goto err_res;
+	}
+
+	err = (dev->of_node) ? omap_des_get_of(dd, pdev) :
+			       omap_des_get_pdev(dd, 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;
+		goto err_res;
+	}
+	dd->phys_base = res->start;
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	omap_des_dma_stop(dd);
+
+	reg = omap_des_read(dd, DES_REG_REV(dd));
+
+	pm_runtime_put_sync(dev);
+
+	dev_info(dev, "OMAP DES hw accel rev: %u.%u\n",
+		 (reg & dd->pdata->major_mask) >> dd->pdata->major_shift,
+		 (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
+
+	tasklet_init(&dd->done_task, omap_des_done_task, (unsigned long)dd);
+	tasklet_init(&dd->queue_task, omap_des_queue_task, (unsigned long)dd);
+
+	err = omap_des_dma_init(dd);
+	if (err && DES_REG_IRQ_STATUS(dd) && DES_REG_IRQ_ENABLE(dd)) {
+		dd->pio_only = 1;
+
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0) {
+			dev_err(dev, "can't get IRQ resource\n");
+			goto err_irq;
+		}
+
+		err = devm_request_irq(dev, irq, omap_des_irq, 0,
+				dev_name(dev), dd);
+		if (err) {
+			dev_err(dev, "Unable to grab omap-des IRQ\n");
+			goto err_irq;
+		}
+	}
+
+
+	INIT_LIST_HEAD(&dd->list);
+	spin_lock(&list_lock);
+	list_add_tail(&dd->list, &dev_list);
+	spin_unlock(&list_lock);
+
+	for (i = 0; i < dd->pdata->algs_info_size; i++) {
+		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
+			algp = &dd->pdata->algs_info[i].algs_list[j];
+
+			pr_debug("reg alg: %s\n", algp->cra_name);
+			INIT_LIST_HEAD(&algp->cra_list);
+
+			err = crypto_register_alg(algp);
+			if (err)
+				goto err_algs;
+
+			dd->pdata->algs_info[i].registered++;
+		}
+	}
+
+	return 0;
+err_algs:
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_alg(
+					&dd->pdata->algs_info[i].algs_list[j]);
+	if (!dd->pio_only)
+		omap_des_dma_cleanup(dd);
+err_irq:
+	tasklet_kill(&dd->done_task);
+	tasklet_kill(&dd->queue_task);
+	pm_runtime_disable(dev);
+err_res:
+	dd = NULL;
+err_data:
+	dev_err(dev, "initialization failed.\n");
+	return err;
+}
+
+static int omap_des_remove(struct platform_device *pdev)
+{
+	struct omap_des_dev *dd = platform_get_drvdata(pdev);
+	int i, j;
+
+	if (!dd)
+		return -ENODEV;
+
+	spin_lock(&list_lock);
+	list_del(&dd->list);
+	spin_unlock(&list_lock);
+
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_alg(
+					&dd->pdata->algs_info[i].algs_list[j]);
+
+	tasklet_kill(&dd->done_task);
+	tasklet_kill(&dd->queue_task);
+	omap_des_dma_cleanup(dd);
+	pm_runtime_disable(dd->dev);
+	dd = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int omap_des_suspend(struct device *dev)
+{
+	pm_runtime_put_sync(dev);
+	return 0;
+}
+
+static int omap_des_resume(struct device *dev)
+{
+	pm_runtime_get_sync(dev);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap_des_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_des_suspend, omap_des_resume)
+};
+
+static struct platform_driver omap_des_driver = {
+	.probe	= omap_des_probe,
+	.remove	= omap_des_remove,
+	.driver	= {
+		.name	= "omap-des",
+		.owner	= THIS_MODULE,
+		.pm	= &omap_des_pm_ops,
+		.of_match_table	= of_match_ptr(omap_des_of_match),
+	},
+};
+
+module_platform_driver(omap_des_driver);
+
+MODULE_DESCRIPTION("OMAP DES hw acceleration support.");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Joel Fernandes <joelf@ti.com>");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index a6175ba6d238..5da5b98b8f29 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1720,22 +1720,16 @@ static int spacc_probe(struct platform_device *pdev)
 	engine->name = dev_name(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	engine->regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(engine->regs))
+		return PTR_ERR(engine->regs);
+
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!mem || !irq) {
+	if (!irq) {
 		dev_err(&pdev->dev, "no memory/irq resource for engine\n");
 		return -ENXIO;
 	}
 
-	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
-				     engine->name))
-		return -ENOMEM;
-
-	engine->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
-	if (!engine->regs) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		return -ENOMEM;
-	}
-
 	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
 			     engine->name, engine)) {
 		dev_err(engine->dev, "failed to request IRQ\n");
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index cf149b19ff47..be45762f390a 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -568,17 +568,14 @@ static int s5p_aes_probe(struct platform_device *pdev)
 	if (s5p_dev)
 		return -EEXIST;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	if (!devm_request_mem_region(dev, res->start,
-				     resource_size(res), pdev->name))
-		return -EBUSY;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pdata->ioaddr))
+		return PTR_ERR(pdata->ioaddr);
 
 	pdata->clk = devm_clk_get(dev, "secss");
 	if (IS_ERR(pdata->clk)) {
@@ -589,8 +586,6 @@ static int s5p_aes_probe(struct platform_device *pdev)
 	clk_enable(pdata->clk);
 
 	spin_lock_init(&pdata->lock);
-	pdata->ioaddr = devm_ioremap(dev, res->start,
-				     resource_size(res));
 
 	pdata->irq_hash = platform_get_irq_byname(pdev, "hash");
 	if (pdata->irq_hash < 0) {
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index 785a9ded7bdf..894468fdb02d 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -885,22 +885,9 @@ static int sahara_probe(struct platform_device *pdev)
 
 	/* Get the base address */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get memory region resource\n");
-		return -ENODEV;
-	}
-
-	if (devm_request_mem_region(&pdev->dev, res->start,
-			resource_size(res), SAHARA_NAME) == NULL) {
-		dev_err(&pdev->dev, "failed to request memory region\n");
-		return -ENOENT;
-	}
-	dev->regs_base = devm_ioremap(&pdev->dev, res->start,
-				      resource_size(res));
-	if (!dev->regs_base) {
-		dev_err(&pdev->dev, "failed to ioremap address region\n");
-		return -ENOENT;
-	}
+	dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dev->regs_base))
+		return PTR_ERR(dev->regs_base);
 
 	/* Get the IRQ */
 	irq = platform_get_irq(pdev,  0);
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 5967667e1a8f..624b8be0c365 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -2637,6 +2637,8 @@ static int talitos_probe(struct platform_device *ofdev)
 	if (!priv)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&priv->alg_list);
+
 	dev_set_drvdata(dev, priv);
 
 	priv->ofdev = ofdev;
@@ -2657,8 +2659,6 @@ static int talitos_probe(struct platform_device *ofdev)
 			     (unsigned long)dev);
 	}
 
-	INIT_LIST_HEAD(&priv->alg_list);
-
 	priv->reg = of_iomap(np, 0);
 	if (!priv->reg) {
 		dev_err(dev, "failed to of_iomap\n");
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
deleted file mode 100644
index 060eecc5dbc3..000000000000
--- a/drivers/crypto/tegra-aes.c
+++ /dev/null
@@ -1,1087 +0,0 @@
-/*
- * drivers/crypto/tegra-aes.c
- *
- * Driver for NVIDIA Tegra AES hardware engine residing inside the
- * Bit Stream Engine for Video (BSEV) hardware block.
- *
- * The programming sequence for this engine is with the help
- * of commands which travel via a command queue residing between the
- * CPU and the BSEV block. The BSEV engine has an internal RAM (VRAM)
- * where the final input plaintext, keys and the IV have to be copied
- * before starting the encrypt/decrypt operation.
- *
- * Copyright (c) 2010, NVIDIA 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; 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/workqueue.h>
-
-#include <crypto/scatterwalk.h>
-#include <crypto/aes.h>
-#include <crypto/internal/rng.h>
-
-#include "tegra-aes.h"
-
-#define FLAGS_MODE_MASK			0x00FF
-#define FLAGS_ENCRYPT			BIT(0)
-#define FLAGS_CBC			BIT(1)
-#define FLAGS_GIV			BIT(2)
-#define FLAGS_RNG			BIT(3)
-#define FLAGS_OFB			BIT(4)
-#define FLAGS_NEW_KEY			BIT(5)
-#define FLAGS_NEW_IV			BIT(6)
-#define FLAGS_INIT			BIT(7)
-#define FLAGS_FAST			BIT(8)
-#define FLAGS_BUSY			9
-
-/*
- * Defines AES engine Max process bytes size in one go, which takes 1 msec.
- * AES engine spends about 176 cycles/16-bytes or 11 cycles/byte
- * The duration CPU can use the BSE to 1 msec, then the number of available
- * cycles of AVP/BSE is 216K. In this duration, AES can process 216/11 ~= 19KB
- * Based on this AES_HW_DMA_BUFFER_SIZE_BYTES is configured to 16KB.
- */
-#define AES_HW_DMA_BUFFER_SIZE_BYTES 0x4000
-
-/*
- * The key table length is 64 bytes
- * (This includes first upto 32 bytes key + 16 bytes original initial vector
- * and 16 bytes updated initial vector)
- */
-#define AES_HW_KEY_TABLE_LENGTH_BYTES 64
-
-/*
- * The memory being used is divides as follows:
- * 1. Key - 32 bytes
- * 2. Original IV - 16 bytes
- * 3. Updated IV - 16 bytes
- * 4. Key schedule - 256 bytes
- *
- * 1+2+3 constitute the hw key table.
- */
-#define AES_HW_IV_SIZE 16
-#define AES_HW_KEYSCHEDULE_LEN 256
-#define AES_IVKEY_SIZE (AES_HW_KEY_TABLE_LENGTH_BYTES + AES_HW_KEYSCHEDULE_LEN)
-
-/* Define commands required for AES operation */
-enum {
-	CMD_BLKSTARTENGINE = 0x0E,
-	CMD_DMASETUP = 0x10,
-	CMD_DMACOMPLETE = 0x11,
-	CMD_SETTABLE = 0x15,
-	CMD_MEMDMAVD = 0x22,
-};
-
-/* Define sub-commands */
-enum {
-	SUBCMD_VRAM_SEL = 0x1,
-	SUBCMD_CRYPTO_TABLE_SEL = 0x3,
-	SUBCMD_KEY_TABLE_SEL = 0x8,
-};
-
-/* memdma_vd command */
-#define MEMDMA_DIR_DTOVRAM		0 /* sdram -> vram */
-#define MEMDMA_DIR_VTODRAM		1 /* vram -> sdram */
-#define MEMDMA_DIR_SHIFT		25
-#define MEMDMA_NUM_WORDS_SHIFT		12
-
-/* command queue bit shifts */
-enum {
-	CMDQ_KEYTABLEADDR_SHIFT = 0,
-	CMDQ_KEYTABLEID_SHIFT = 17,
-	CMDQ_VRAMSEL_SHIFT = 23,
-	CMDQ_TABLESEL_SHIFT = 24,
-	CMDQ_OPCODE_SHIFT = 26,
-};
-
-/*
- * The secure key slot contains a unique secure key generated
- * and loaded by the bootloader. This slot is marked as non-accessible
- * to the kernel.
- */
-#define SSK_SLOT_NUM		4
-
-#define AES_NR_KEYSLOTS		8
-#define TEGRA_AES_QUEUE_LENGTH	50
-#define DEFAULT_RNG_BLK_SZ	16
-
-/* The command queue depth */
-#define AES_HW_MAX_ICQ_LENGTH	5
-
-struct tegra_aes_slot {
-	struct list_head node;
-	int slot_num;
-};
-
-static struct tegra_aes_slot ssk = {
-	.slot_num = SSK_SLOT_NUM,
-};
-
-struct tegra_aes_reqctx {
-	unsigned long mode;
-};
-
-struct tegra_aes_dev {
-	struct device *dev;
-	void __iomem *io_base;
-	dma_addr_t ivkey_phys_base;
-	void __iomem *ivkey_base;
-	struct clk *aes_clk;
-	struct tegra_aes_ctx *ctx;
-	int irq;
-	unsigned long flags;
-	struct completion op_complete;
-	u32 *buf_in;
-	dma_addr_t dma_buf_in;
-	u32 *buf_out;
-	dma_addr_t dma_buf_out;
-	u8 *iv;
-	u8 dt[DEFAULT_RNG_BLK_SZ];
-	int ivlen;
-	u64 ctr;
-	spinlock_t lock;
-	struct crypto_queue queue;
-	struct tegra_aes_slot *slots;
-	struct ablkcipher_request *req;
-	size_t total;
-	struct scatterlist *in_sg;
-	size_t in_offset;
-	struct scatterlist *out_sg;
-	size_t out_offset;
-};
-
-static struct tegra_aes_dev *aes_dev;
-
-struct tegra_aes_ctx {
-	struct tegra_aes_dev *dd;
-	unsigned long flags;
-	struct tegra_aes_slot *slot;
-	u8 key[AES_MAX_KEY_SIZE];
-	size_t keylen;
-};
-
-static struct tegra_aes_ctx rng_ctx = {
-	.flags = FLAGS_NEW_KEY,
-	.keylen = AES_KEYSIZE_128,
-};
-
-/* keep registered devices data here */
-static struct list_head dev_list;
-static DEFINE_SPINLOCK(list_lock);
-static DEFINE_MUTEX(aes_lock);
-
-static void aes_workqueue_handler(struct work_struct *work);
-static DECLARE_WORK(aes_work, aes_workqueue_handler);
-static struct workqueue_struct *aes_wq;
-
-static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset)
-{
-	return readl(dd->io_base + offset);
-}
-
-static inline void aes_writel(struct tegra_aes_dev *dd, u32 val, u32 offset)
-{
-	writel(val, dd->io_base + offset);
-}
-
-static int aes_start_crypt(struct tegra_aes_dev *dd, u32 in_addr, u32 out_addr,
-	int nblocks, int mode, bool upd_iv)
-{
-	u32 cmdq[AES_HW_MAX_ICQ_LENGTH];
-	int i, eng_busy, icq_empty, ret;
-	u32 value;
-
-	/* reset all the interrupt bits */
-	aes_writel(dd, 0xFFFFFFFF, TEGRA_AES_INTR_STATUS);
-
-	/* enable error, dma xfer complete interrupts */
-	aes_writel(dd, 0x33, TEGRA_AES_INT_ENB);
-
-	cmdq[0] = CMD_DMASETUP << CMDQ_OPCODE_SHIFT;
-	cmdq[1] = in_addr;
-	cmdq[2] = CMD_BLKSTARTENGINE << CMDQ_OPCODE_SHIFT | (nblocks-1);
-	cmdq[3] = CMD_DMACOMPLETE << CMDQ_OPCODE_SHIFT;
-
-	value = aes_readl(dd, TEGRA_AES_CMDQUE_CONTROL);
-	/* access SDRAM through AHB */
-	value &= ~TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD;
-	value &= ~TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD;
-	value |= TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD |
-		 TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD |
-		 TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD;
-	aes_writel(dd, value, TEGRA_AES_CMDQUE_CONTROL);
-	dev_dbg(dd->dev, "cmd_q_ctrl=0x%x", value);
-
-	value = (0x1 << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT) |
-		((dd->ctx->keylen * 8) <<
-			TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT) |
-		((u32)upd_iv << TEGRA_AES_SECURE_IV_SELECT_SHIFT);
-
-	if (mode & FLAGS_CBC) {
-		value |= ((((mode & FLAGS_ENCRYPT) ? 2 : 3)
-				<< TEGRA_AES_SECURE_XOR_POS_SHIFT) |
-			(((mode & FLAGS_ENCRYPT) ? 2 : 3)
-				<< TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT) |
-			((mode & FLAGS_ENCRYPT) ? 1 : 0)
-				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT);
-	} else if (mode & FLAGS_OFB) {
-		value |= ((TEGRA_AES_SECURE_XOR_POS_FIELD) |
-			(2 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT) |
-			(TEGRA_AES_SECURE_CORE_SEL_FIELD));
-	} else if (mode & FLAGS_RNG) {
-		value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0)
-				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT |
-			  TEGRA_AES_SECURE_RNG_ENB_FIELD);
-	} else {
-		value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0)
-				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT);
-	}
-
-	dev_dbg(dd->dev, "secure_in_sel=0x%x", value);
-	aes_writel(dd, value, TEGRA_AES_SECURE_INPUT_SELECT);
-
-	aes_writel(dd, out_addr, TEGRA_AES_SECURE_DEST_ADDR);
-	reinit_completion(&dd->op_complete);
-
-	for (i = 0; i < AES_HW_MAX_ICQ_LENGTH - 1; i++) {
-		do {
-			value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
-			eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
-			icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
-		} while (eng_busy && !icq_empty);
-		aes_writel(dd, cmdq[i], TEGRA_AES_ICMDQUE_WR);
-	}
-
-	ret = wait_for_completion_timeout(&dd->op_complete,
-					  msecs_to_jiffies(150));
-	if (ret == 0) {
-		dev_err(dd->dev, "timed out (0x%x)\n",
-			aes_readl(dd, TEGRA_AES_INTR_STATUS));
-		return -ETIMEDOUT;
-	}
-
-	aes_writel(dd, cmdq[AES_HW_MAX_ICQ_LENGTH - 1], TEGRA_AES_ICMDQUE_WR);
-	return 0;
-}
-
-static void aes_release_key_slot(struct tegra_aes_slot *slot)
-{
-	if (slot->slot_num == SSK_SLOT_NUM)
-		return;
-
-	spin_lock(&list_lock);
-	list_add_tail(&slot->node, &dev_list);
-	slot = NULL;
-	spin_unlock(&list_lock);
-}
-
-static struct tegra_aes_slot *aes_find_key_slot(void)
-{
-	struct tegra_aes_slot *slot = NULL;
-	struct list_head *new_head;
-	int empty;
-
-	spin_lock(&list_lock);
-	empty = list_empty(&dev_list);
-	if (!empty) {
-		slot = list_entry(&dev_list, struct tegra_aes_slot, node);
-		new_head = dev_list.next;
-		list_del(&dev_list);
-		dev_list.next = new_head->next;
-		dev_list.prev = NULL;
-	}
-	spin_unlock(&list_lock);
-
-	return slot;
-}
-
-static int aes_set_key(struct tegra_aes_dev *dd)
-{
-	u32 value, cmdq[2];
-	struct tegra_aes_ctx *ctx = dd->ctx;
-	int eng_busy, icq_empty, dma_busy;
-	bool use_ssk = false;
-
-	/* use ssk? */
-	if (!dd->ctx->slot) {
-		dev_dbg(dd->dev, "using ssk");
-		dd->ctx->slot = &ssk;
-		use_ssk = true;
-	}
-
-	/* enable key schedule generation in hardware */
-	value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG_EXT);
-	value &= ~TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD;
-	aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG_EXT);
-
-	/* select the key slot */
-	value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG);
-	value &= ~TEGRA_AES_SECURE_KEY_INDEX_FIELD;
-	value |= (ctx->slot->slot_num << TEGRA_AES_SECURE_KEY_INDEX_SHIFT);
-	aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG);
-
-	if (use_ssk)
-		return 0;
-
-	/* copy the key table from sdram to vram */
-	cmdq[0] = CMD_MEMDMAVD << CMDQ_OPCODE_SHIFT |
-		MEMDMA_DIR_DTOVRAM << MEMDMA_DIR_SHIFT |
-		AES_HW_KEY_TABLE_LENGTH_BYTES / sizeof(u32) <<
-			MEMDMA_NUM_WORDS_SHIFT;
-	cmdq[1] = (u32)dd->ivkey_phys_base;
-
-	aes_writel(dd, cmdq[0], TEGRA_AES_ICMDQUE_WR);
-	aes_writel(dd, cmdq[1], TEGRA_AES_ICMDQUE_WR);
-
-	do {
-		value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
-		eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
-		icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
-		dma_busy = value & TEGRA_AES_DMA_BUSY_FIELD;
-	} while (eng_busy && !icq_empty && dma_busy);
-
-	/* settable command to get key into internal registers */
-	value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT |
-		SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT |
-		SUBCMD_VRAM_SEL << CMDQ_VRAMSEL_SHIFT |
-		(SUBCMD_KEY_TABLE_SEL | ctx->slot->slot_num) <<
-			CMDQ_KEYTABLEID_SHIFT;
-	aes_writel(dd, value, TEGRA_AES_ICMDQUE_WR);
-
-	do {
-		value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
-		eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
-		icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
-	} while (eng_busy && !icq_empty);
-
-	return 0;
-}
-
-static int tegra_aes_handle_req(struct tegra_aes_dev *dd)
-{
-	struct crypto_async_request *async_req, *backlog;
-	struct crypto_ablkcipher *tfm;
-	struct tegra_aes_ctx *ctx;
-	struct tegra_aes_reqctx *rctx;
-	struct ablkcipher_request *req;
-	unsigned long flags;
-	int dma_max = AES_HW_DMA_BUFFER_SIZE_BYTES;
-	int ret = 0, nblocks, total;
-	int count = 0;
-	dma_addr_t addr_in, addr_out;
-	struct scatterlist *in_sg, *out_sg;
-
-	if (!dd)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dd->lock, flags);
-	backlog = crypto_get_backlog(&dd->queue);
-	async_req = crypto_dequeue_request(&dd->queue);
-	if (!async_req)
-		clear_bit(FLAGS_BUSY, &dd->flags);
-	spin_unlock_irqrestore(&dd->lock, flags);
-
-	if (!async_req)
-		return -ENODATA;
-
-	if (backlog)
-		backlog->complete(backlog, -EINPROGRESS);
-
-	req = ablkcipher_request_cast(async_req);
-
-	dev_dbg(dd->dev, "%s: get new req\n", __func__);
-
-	if (!req->src || !req->dst)
-		return -EINVAL;
-
-	/* take mutex to access the aes hw */
-	mutex_lock(&aes_lock);
-
-	/* assign new request to device */
-	dd->req = req;
-	dd->total = req->nbytes;
-	dd->in_offset = 0;
-	dd->in_sg = req->src;
-	dd->out_offset = 0;
-	dd->out_sg = req->dst;
-
-	in_sg = dd->in_sg;
-	out_sg = dd->out_sg;
-
-	total = dd->total;
-
-	tfm = crypto_ablkcipher_reqtfm(req);
-	rctx = ablkcipher_request_ctx(req);
-	ctx = crypto_ablkcipher_ctx(tfm);
-	rctx->mode &= FLAGS_MODE_MASK;
-	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
-
-	dd->iv = (u8 *)req->info;
-	dd->ivlen = crypto_ablkcipher_ivsize(tfm);
-
-	/* assign new context to device */
-	ctx->dd = dd;
-	dd->ctx = ctx;
-
-	if (ctx->flags & FLAGS_NEW_KEY) {
-		/* copy the key */
-		memcpy(dd->ivkey_base, ctx->key, ctx->keylen);
-		memset(dd->ivkey_base + ctx->keylen, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - ctx->keylen);
-		aes_set_key(dd);
-		ctx->flags &= ~FLAGS_NEW_KEY;
-	}
-
-	if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && dd->iv) {
-		/* set iv to the aes hw slot
-		 * Hw generates updated iv only after iv is set in slot.
-		 * So key and iv is passed asynchronously.
-		 */
-		memcpy(dd->buf_in, dd->iv, dd->ivlen);
-
-		ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
-				      dd->dma_buf_out, 1, FLAGS_CBC, false);
-		if (ret < 0) {
-			dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
-			goto out;
-		}
-	}
-
-	while (total) {
-		dev_dbg(dd->dev, "remain: %d\n", total);
-		ret = dma_map_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE);
-		if (!ret) {
-			dev_err(dd->dev, "dma_map_sg() error\n");
-			goto out;
-		}
-
-		ret = dma_map_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE);
-		if (!ret) {
-			dev_err(dd->dev, "dma_map_sg() error\n");
-			dma_unmap_sg(dd->dev, dd->in_sg,
-				1, DMA_TO_DEVICE);
-			goto out;
-		}
-
-		addr_in = sg_dma_address(in_sg);
-		addr_out = sg_dma_address(out_sg);
-		dd->flags |= FLAGS_FAST;
-		count = min_t(int, sg_dma_len(in_sg), dma_max);
-		WARN_ON(sg_dma_len(in_sg) != sg_dma_len(out_sg));
-		nblocks = DIV_ROUND_UP(count, AES_BLOCK_SIZE);
-
-		ret = aes_start_crypt(dd, addr_in, addr_out, nblocks,
-			dd->flags, true);
-
-		dma_unmap_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE);
-		dma_unmap_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE);
-
-		if (ret < 0) {
-			dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
-			goto out;
-		}
-		dd->flags &= ~FLAGS_FAST;
-
-		dev_dbg(dd->dev, "out: copied %d\n", count);
-		total -= count;
-		in_sg = sg_next(in_sg);
-		out_sg = sg_next(out_sg);
-		WARN_ON(((total != 0) && (!in_sg || !out_sg)));
-	}
-
-out:
-	mutex_unlock(&aes_lock);
-
-	dd->total = total;
-
-	if (dd->req->base.complete)
-		dd->req->base.complete(&dd->req->base, ret);
-
-	dev_dbg(dd->dev, "%s: exit\n", __func__);
-	return ret;
-}
-
-static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
-			    unsigned int keylen)
-{
-	struct tegra_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-	struct tegra_aes_dev *dd = aes_dev;
-	struct tegra_aes_slot *key_slot;
-
-	if ((keylen != AES_KEYSIZE_128) && (keylen != AES_KEYSIZE_192) &&
-		(keylen != AES_KEYSIZE_256)) {
-		dev_err(dd->dev, "unsupported key size\n");
-		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-		return -EINVAL;
-	}
-
-	dev_dbg(dd->dev, "keylen: %d\n", keylen);
-
-	ctx->dd = dd;
-
-	if (key) {
-		if (!ctx->slot) {
-			key_slot = aes_find_key_slot();
-			if (!key_slot) {
-				dev_err(dd->dev, "no empty slot\n");
-				return -ENOMEM;
-			}
-
-			ctx->slot = key_slot;
-		}
-
-		memcpy(ctx->key, key, keylen);
-		ctx->keylen = keylen;
-	}
-
-	ctx->flags |= FLAGS_NEW_KEY;
-	dev_dbg(dd->dev, "done\n");
-	return 0;
-}
-
-static void aes_workqueue_handler(struct work_struct *work)
-{
-	struct tegra_aes_dev *dd = aes_dev;
-	int ret;
-
-	ret = clk_prepare_enable(dd->aes_clk);
-	if (ret)
-		BUG_ON("clock enable failed");
-
-	/* empty the crypto queue and then return */
-	do {
-		ret = tegra_aes_handle_req(dd);
-	} while (!ret);
-
-	clk_disable_unprepare(dd->aes_clk);
-}
-
-static irqreturn_t aes_irq(int irq, void *dev_id)
-{
-	struct tegra_aes_dev *dd = (struct tegra_aes_dev *)dev_id;
-	u32 value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
-	int busy = test_bit(FLAGS_BUSY, &dd->flags);
-
-	if (!busy) {
-		dev_dbg(dd->dev, "spurious interrupt\n");
-		return IRQ_NONE;
-	}
-
-	dev_dbg(dd->dev, "irq_stat: 0x%x\n", value);
-	if (value & TEGRA_AES_INT_ERROR_MASK)
-		aes_writel(dd, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS);
-
-	if (!(value & TEGRA_AES_ENGINE_BUSY_FIELD))
-		complete(&dd->op_complete);
-	else
-		return IRQ_NONE;
-
-	return IRQ_HANDLED;
-}
-
-static int tegra_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
-{
-	struct tegra_aes_reqctx *rctx = ablkcipher_request_ctx(req);
-	struct tegra_aes_dev *dd = aes_dev;
-	unsigned long flags;
-	int err = 0;
-	int busy;
-
-	dev_dbg(dd->dev, "nbytes: %d, enc: %d, cbc: %d, ofb: %d\n",
-		req->nbytes, !!(mode & FLAGS_ENCRYPT),
-		!!(mode & FLAGS_CBC), !!(mode & FLAGS_OFB));
-
-	rctx->mode = mode;
-
-	spin_lock_irqsave(&dd->lock, flags);
-	err = ablkcipher_enqueue_request(&dd->queue, req);
-	busy = test_and_set_bit(FLAGS_BUSY, &dd->flags);
-	spin_unlock_irqrestore(&dd->lock, flags);
-
-	if (!busy)
-		queue_work(aes_wq, &aes_work);
-
-	return err;
-}
-
-static int tegra_aes_ecb_encrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, FLAGS_ENCRYPT);
-}
-
-static int tegra_aes_ecb_decrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, 0);
-}
-
-static int tegra_aes_cbc_encrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
-}
-
-static int tegra_aes_cbc_decrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, FLAGS_CBC);
-}
-
-static int tegra_aes_ofb_encrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_OFB);
-}
-
-static int tegra_aes_ofb_decrypt(struct ablkcipher_request *req)
-{
-	return tegra_aes_crypt(req, FLAGS_OFB);
-}
-
-static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
-				unsigned int dlen)
-{
-	struct tegra_aes_dev *dd = aes_dev;
-	struct tegra_aes_ctx *ctx = &rng_ctx;
-	int ret, i;
-	u8 *dest = rdata, *dt = dd->dt;
-
-	/* take mutex to access the aes hw */
-	mutex_lock(&aes_lock);
-
-	ret = clk_prepare_enable(dd->aes_clk);
-	if (ret) {
-		mutex_unlock(&aes_lock);
-		return ret;
-	}
-
-	ctx->dd = dd;
-	dd->ctx = ctx;
-	dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
-
-	memcpy(dd->buf_in, dt, DEFAULT_RNG_BLK_SZ);
-
-	ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
-			      (u32)dd->dma_buf_out, 1, dd->flags, true);
-	if (ret < 0) {
-		dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
-		dlen = ret;
-		goto out;
-	}
-	memcpy(dest, dd->buf_out, dlen);
-
-	/* update the DT */
-	for (i = DEFAULT_RNG_BLK_SZ - 1; i >= 0; i--) {
-		dt[i] += 1;
-		if (dt[i] != 0)
-			break;
-	}
-
-out:
-	clk_disable_unprepare(dd->aes_clk);
-	mutex_unlock(&aes_lock);
-
-	dev_dbg(dd->dev, "%s: done\n", __func__);
-	return dlen;
-}
-
-static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
-			       unsigned int slen)
-{
-	struct tegra_aes_dev *dd = aes_dev;
-	struct tegra_aes_ctx *ctx = &rng_ctx;
-	struct tegra_aes_slot *key_slot;
-	int ret = 0;
-	u8 tmp[16]; /* 16 bytes = 128 bits of entropy */
-	u8 *dt;
-
-	if (!ctx || !dd) {
-		pr_err("ctx=0x%x, dd=0x%x\n",
-			(unsigned int)ctx, (unsigned int)dd);
-		return -EINVAL;
-	}
-
-	if (slen < (DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
-		dev_err(dd->dev, "seed size invalid");
-		return -ENOMEM;
-	}
-
-	/* take mutex to access the aes hw */
-	mutex_lock(&aes_lock);
-
-	if (!ctx->slot) {
-		key_slot = aes_find_key_slot();
-		if (!key_slot) {
-			dev_err(dd->dev, "no empty slot\n");
-			mutex_unlock(&aes_lock);
-			return -ENOMEM;
-		}
-		ctx->slot = key_slot;
-	}
-
-	ctx->dd = dd;
-	dd->ctx = ctx;
-	dd->ctr = 0;
-
-	ctx->keylen = AES_KEYSIZE_128;
-	ctx->flags |= FLAGS_NEW_KEY;
-
-	/* copy the key to the key slot */
-	memcpy(dd->ivkey_base, seed + DEFAULT_RNG_BLK_SZ, AES_KEYSIZE_128);
-	memset(dd->ivkey_base + AES_KEYSIZE_128, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - AES_KEYSIZE_128);
-
-	dd->iv = seed;
-	dd->ivlen = slen;
-
-	dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
-
-	ret = clk_prepare_enable(dd->aes_clk);
-	if (ret) {
-		mutex_unlock(&aes_lock);
-		return ret;
-	}
-
-	aes_set_key(dd);
-
-	/* set seed to the aes hw slot */
-	memcpy(dd->buf_in, dd->iv, DEFAULT_RNG_BLK_SZ);
-	ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
-			      dd->dma_buf_out, 1, FLAGS_CBC, false);
-	if (ret < 0) {
-		dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
-		goto out;
-	}
-
-	if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
-		dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128;
-	} else {
-		get_random_bytes(tmp, sizeof(tmp));
-		dt = tmp;
-	}
-	memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
-
-out:
-	clk_disable_unprepare(dd->aes_clk);
-	mutex_unlock(&aes_lock);
-
-	dev_dbg(dd->dev, "%s: done\n", __func__);
-	return ret;
-}
-
-static int tegra_aes_cra_init(struct crypto_tfm *tfm)
-{
-	tfm->crt_ablkcipher.reqsize = sizeof(struct tegra_aes_reqctx);
-
-	return 0;
-}
-
-static void tegra_aes_cra_exit(struct crypto_tfm *tfm)
-{
-	struct tegra_aes_ctx *ctx =
-		crypto_ablkcipher_ctx((struct crypto_ablkcipher *)tfm);
-
-	if (ctx && ctx->slot)
-		aes_release_key_slot(ctx->slot);
-}
-
-static struct crypto_alg algs[] = {
-	{
-		.cra_name = "ecb(aes)",
-		.cra_driver_name = "ecb-aes-tegra",
-		.cra_priority = 300,
-		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-		.cra_blocksize = AES_BLOCK_SIZE,
-		.cra_alignmask = 3,
-		.cra_type = &crypto_ablkcipher_type,
-		.cra_u.ablkcipher = {
-			.min_keysize = AES_MIN_KEY_SIZE,
-			.max_keysize = AES_MAX_KEY_SIZE,
-			.setkey = tegra_aes_setkey,
-			.encrypt = tegra_aes_ecb_encrypt,
-			.decrypt = tegra_aes_ecb_decrypt,
-		},
-	}, {
-		.cra_name = "cbc(aes)",
-		.cra_driver_name = "cbc-aes-tegra",
-		.cra_priority = 300,
-		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-		.cra_blocksize = AES_BLOCK_SIZE,
-		.cra_alignmask = 3,
-		.cra_type = &crypto_ablkcipher_type,
-		.cra_u.ablkcipher = {
-			.min_keysize = AES_MIN_KEY_SIZE,
-			.max_keysize = AES_MAX_KEY_SIZE,
-			.ivsize = AES_MIN_KEY_SIZE,
-			.setkey = tegra_aes_setkey,
-			.encrypt = tegra_aes_cbc_encrypt,
-			.decrypt = tegra_aes_cbc_decrypt,
-		}
-	}, {
-		.cra_name = "ofb(aes)",
-		.cra_driver_name = "ofb-aes-tegra",
-		.cra_priority = 300,
-		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-		.cra_blocksize = AES_BLOCK_SIZE,
-		.cra_alignmask = 3,
-		.cra_type = &crypto_ablkcipher_type,
-		.cra_u.ablkcipher = {
-			.min_keysize = AES_MIN_KEY_SIZE,
-			.max_keysize = AES_MAX_KEY_SIZE,
-			.ivsize = AES_MIN_KEY_SIZE,
-			.setkey = tegra_aes_setkey,
-			.encrypt = tegra_aes_ofb_encrypt,
-			.decrypt = tegra_aes_ofb_decrypt,
-		}
-	}, {
-		.cra_name = "ansi_cprng",
-		.cra_driver_name = "rng-aes-tegra",
-		.cra_flags = CRYPTO_ALG_TYPE_RNG,
-		.cra_ctxsize = sizeof(struct tegra_aes_ctx),
-		.cra_type = &crypto_rng_type,
-		.cra_u.rng = {
-			.rng_make_random = tegra_aes_get_random,
-			.rng_reset = tegra_aes_rng_reset,
-			.seedsize = AES_KEYSIZE_128 + (2 * DEFAULT_RNG_BLK_SZ),
-		}
-	}
-};
-
-static int tegra_aes_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct tegra_aes_dev *dd;
-	struct resource *res;
-	int err = -ENOMEM, i = 0, j;
-
-	dd = devm_kzalloc(dev, sizeof(struct tegra_aes_dev), GFP_KERNEL);
-	if (dd == NULL) {
-		dev_err(dev, "unable to alloc data struct.\n");
-		return err;
-	}
-
-	dd->dev = dev;
-	platform_set_drvdata(pdev, dd);
-
-	dd->slots = devm_kzalloc(dev, sizeof(struct tegra_aes_slot) *
-				 AES_NR_KEYSLOTS, GFP_KERNEL);
-	if (dd->slots == NULL) {
-		dev_err(dev, "unable to alloc slot struct.\n");
-		goto out;
-	}
-
-	spin_lock_init(&dd->lock);
-	crypto_init_queue(&dd->queue, TEGRA_AES_QUEUE_LENGTH);
-
-	/* Get the module base address */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "invalid resource type: base\n");
-		err = -ENODEV;
-		goto out;
-	}
-
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res),
-				     dev_name(&pdev->dev))) {
-		dev_err(&pdev->dev, "Couldn't request MEM resource\n");
-		return -ENODEV;
-	}
-
-	dd->io_base = devm_ioremap(dev, res->start, resource_size(res));
-	if (!dd->io_base) {
-		dev_err(dev, "can't ioremap register space\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	/* Initialize the vde clock */
-	dd->aes_clk = devm_clk_get(dev, "vde");
-	if (IS_ERR(dd->aes_clk)) {
-		dev_err(dev, "iclock intialization failed.\n");
-		err = -ENODEV;
-		goto out;
-	}
-
-	err = clk_set_rate(dd->aes_clk, ULONG_MAX);
-	if (err) {
-		dev_err(dd->dev, "iclk set_rate fail(%d)\n", err);
-		goto out;
-	}
-
-	/*
-	 * the foll contiguous memory is allocated as follows -
-	 * - hardware key table
-	 * - key schedule
-	 */
-	dd->ivkey_base = dma_alloc_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
-					    &dd->ivkey_phys_base,
-		GFP_KERNEL);
-	if (!dd->ivkey_base) {
-		dev_err(dev, "can not allocate iv/key buffer\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	dd->buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-					&dd->dma_buf_in, GFP_KERNEL);
-	if (!dd->buf_in) {
-		dev_err(dev, "can not allocate dma-in buffer\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	dd->buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-					 &dd->dma_buf_out, GFP_KERNEL);
-	if (!dd->buf_out) {
-		dev_err(dev, "can not allocate dma-out buffer\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	init_completion(&dd->op_complete);
-	aes_wq = alloc_workqueue("tegra_aes_wq", WQ_HIGHPRI | WQ_UNBOUND, 1);
-	if (!aes_wq) {
-		dev_err(dev, "alloc_workqueue failed\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	/* get the irq */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(dev, "invalid resource type: base\n");
-		err = -ENODEV;
-		goto out;
-	}
-	dd->irq = res->start;
-
-	err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH |
-				IRQF_SHARED, "tegra-aes", dd);
-	if (err) {
-		dev_err(dev, "request_irq failed\n");
-		goto out;
-	}
-
-	mutex_init(&aes_lock);
-	INIT_LIST_HEAD(&dev_list);
-
-	spin_lock_init(&list_lock);
-	spin_lock(&list_lock);
-	for (i = 0; i < AES_NR_KEYSLOTS; i++) {
-		if (i == SSK_SLOT_NUM)
-			continue;
-		dd->slots[i].slot_num = i;
-		INIT_LIST_HEAD(&dd->slots[i].node);
-		list_add_tail(&dd->slots[i].node, &dev_list);
-	}
-	spin_unlock(&list_lock);
-
-	aes_dev = dd;
-	for (i = 0; i < ARRAY_SIZE(algs); i++) {
-		algs[i].cra_priority = 300;
-		algs[i].cra_ctxsize = sizeof(struct tegra_aes_ctx);
-		algs[i].cra_module = THIS_MODULE;
-		algs[i].cra_init = tegra_aes_cra_init;
-		algs[i].cra_exit = tegra_aes_cra_exit;
-
-		err = crypto_register_alg(&algs[i]);
-		if (err)
-			goto out;
-	}
-
-	dev_info(dev, "registered");
-	return 0;
-
-out:
-	for (j = 0; j < i; j++)
-		crypto_unregister_alg(&algs[j]);
-	if (dd->ivkey_base)
-		dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
-			dd->ivkey_base, dd->ivkey_phys_base);
-	if (dd->buf_in)
-		dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-			dd->buf_in, dd->dma_buf_in);
-	if (dd->buf_out)
-		dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-			dd->buf_out, dd->dma_buf_out);
-	if (aes_wq)
-		destroy_workqueue(aes_wq);
-	spin_lock(&list_lock);
-	list_del(&dev_list);
-	spin_unlock(&list_lock);
-
-	aes_dev = NULL;
-
-	dev_err(dev, "%s: initialization failed.\n", __func__);
-	return err;
-}
-
-static int tegra_aes_remove(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct tegra_aes_dev *dd = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(algs); i++)
-		crypto_unregister_alg(&algs[i]);
-
-	cancel_work_sync(&aes_work);
-	destroy_workqueue(aes_wq);
-	spin_lock(&list_lock);
-	list_del(&dev_list);
-	spin_unlock(&list_lock);
-
-	dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
-			  dd->ivkey_base, dd->ivkey_phys_base);
-	dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-			  dd->buf_in, dd->dma_buf_in);
-	dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
-			  dd->buf_out, dd->dma_buf_out);
-	aes_dev = NULL;
-
-	return 0;
-}
-
-static struct of_device_id tegra_aes_of_match[] = {
-	{ .compatible = "nvidia,tegra20-aes", },
-	{ .compatible = "nvidia,tegra30-aes", },
-	{ },
-};
-
-static struct platform_driver tegra_aes_driver = {
-	.probe  = tegra_aes_probe,
-	.remove = tegra_aes_remove,
-	.driver = {
-		.name   = "tegra-aes",
-		.owner  = THIS_MODULE,
-		.of_match_table = tegra_aes_of_match,
-	},
-};
-
-module_platform_driver(tegra_aes_driver);
-
-MODULE_DESCRIPTION("Tegra AES/OFB/CPRNG hw acceleration support.");
-MODULE_AUTHOR("NVIDIA Corporation");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/tegra-aes.h b/drivers/crypto/tegra-aes.h
deleted file mode 100644
index 6006333a8934..000000000000
--- a/drivers/crypto/tegra-aes.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2010, NVIDIA 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; 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.
- */
-
-#ifndef __CRYPTODEV_TEGRA_AES_H
-#define __CRYPTODEV_TEGRA_AES_H
-
-#define TEGRA_AES_ICMDQUE_WR			0x1000
-#define TEGRA_AES_CMDQUE_CONTROL		0x1008
-#define TEGRA_AES_INTR_STATUS			0x1018
-#define TEGRA_AES_INT_ENB			0x1040
-#define TEGRA_AES_CONFIG			0x1044
-#define TEGRA_AES_IRAM_ACCESS_CFG		0x10A0
-#define TEGRA_AES_SECURE_DEST_ADDR		0x1100
-#define TEGRA_AES_SECURE_INPUT_SELECT		0x1104
-#define TEGRA_AES_SECURE_CONFIG			0x1108
-#define TEGRA_AES_SECURE_CONFIG_EXT		0x110C
-#define TEGRA_AES_SECURE_SECURITY		0x1110
-#define TEGRA_AES_SECURE_HASH_RESULT0		0x1120
-#define TEGRA_AES_SECURE_HASH_RESULT1		0x1124
-#define TEGRA_AES_SECURE_HASH_RESULT2		0x1128
-#define TEGRA_AES_SECURE_HASH_RESULT3		0x112C
-#define TEGRA_AES_SECURE_SEC_SEL0		0x1140
-#define TEGRA_AES_SECURE_SEC_SEL1		0x1144
-#define TEGRA_AES_SECURE_SEC_SEL2		0x1148
-#define TEGRA_AES_SECURE_SEC_SEL3		0x114C
-#define TEGRA_AES_SECURE_SEC_SEL4		0x1150
-#define TEGRA_AES_SECURE_SEC_SEL5		0x1154
-#define TEGRA_AES_SECURE_SEC_SEL6		0x1158
-#define TEGRA_AES_SECURE_SEC_SEL7		0x115C
-
-/* interrupt status reg masks and shifts */
-#define TEGRA_AES_ENGINE_BUSY_FIELD		BIT(0)
-#define TEGRA_AES_ICQ_EMPTY_FIELD		BIT(3)
-#define TEGRA_AES_DMA_BUSY_FIELD		BIT(23)
-
-/* secure select reg masks and shifts */
-#define TEGRA_AES_SECURE_SEL0_KEYREAD_ENB0_FIELD	BIT(0)
-
-/* secure config ext masks and shifts */
-#define TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD	BIT(15)
-
-/* secure config masks and shifts */
-#define TEGRA_AES_SECURE_KEY_INDEX_SHIFT	20
-#define TEGRA_AES_SECURE_KEY_INDEX_FIELD	(0x1F << TEGRA_AES_SECURE_KEY_INDEX_SHIFT)
-#define TEGRA_AES_SECURE_BLOCK_CNT_SHIFT	0
-#define TEGRA_AES_SECURE_BLOCK_CNT_FIELD	(0xFFFFF << TEGRA_AES_SECURE_BLOCK_CNT_SHIFT)
-
-/* stream interface select masks and shifts */
-#define TEGRA_AES_CMDQ_CTRL_UCMDQEN_FIELD	BIT(0)
-#define TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD	BIT(1)
-#define TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD	BIT(4)
-#define TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD	BIT(5)
-
-/* config register masks and shifts */
-#define TEGRA_AES_CONFIG_ENDIAN_ENB_FIELD	BIT(10)
-#define TEGRA_AES_CONFIG_MODE_SEL_SHIFT		0
-#define TEGRA_AES_CONFIG_MODE_SEL_FIELD		(0x1F << TEGRA_AES_CONFIG_MODE_SEL_SHIFT)
-
-/* extended config */
-#define TEGRA_AES_SECURE_OFFSET_CNT_SHIFT	24
-#define TEGRA_AES_SECURE_OFFSET_CNT_FIELD	(0xFF << TEGRA_AES_SECURE_OFFSET_CNT_SHIFT)
-#define TEGRA_AES_SECURE_KEYSCHED_GEN_FIELD	BIT(15)
-
-/* init vector select */
-#define TEGRA_AES_SECURE_IV_SELECT_SHIFT	10
-#define TEGRA_AES_SECURE_IV_SELECT_FIELD	BIT(10)
-
-/* secure engine input */
-#define TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT	28
-#define TEGRA_AES_SECURE_INPUT_ALG_SEL_FIELD	(0xF << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT)
-#define TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT	16
-#define TEGRA_AES_SECURE_INPUT_KEY_LEN_FIELD	(0xFFF << TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT)
-#define TEGRA_AES_SECURE_RNG_ENB_FIELD		BIT(11)
-#define TEGRA_AES_SECURE_CORE_SEL_SHIFT		9
-#define TEGRA_AES_SECURE_CORE_SEL_FIELD		BIT(9)
-#define TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT	7
-#define TEGRA_AES_SECURE_VCTRAM_SEL_FIELD	(0x3 << TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT)
-#define TEGRA_AES_SECURE_INPUT_SEL_SHIFT	5
-#define TEGRA_AES_SECURE_INPUT_SEL_FIELD	(0x3 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT)
-#define TEGRA_AES_SECURE_XOR_POS_SHIFT		3
-#define TEGRA_AES_SECURE_XOR_POS_FIELD		(0x3 << TEGRA_AES_SECURE_XOR_POS_SHIFT)
-#define TEGRA_AES_SECURE_HASH_ENB_FIELD		BIT(2)
-#define TEGRA_AES_SECURE_ON_THE_FLY_FIELD	BIT(0)
-
-/* interrupt error mask */
-#define TEGRA_AES_INT_ERROR_MASK		0xFFF000
-
-#endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 605b016bcea4..3efaf201c29d 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -308,7 +308,7 @@ config DMA_OMAP
 
 config DMA_BCM2835
 	tristate "BCM2835 DMA engine support"
-	depends on (ARCH_BCM2835 || MACH_BCM2708)
+	depends on ARCH_BCM2835
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 
@@ -350,6 +350,16 @@ config MOXART_DMA
 	select DMA_VIRTUAL_CHANNELS
 	help
 	  Enable support for the MOXA ART SoC DMA controller.
+ 
+config FSL_EDMA
+	tristate "Freescale eDMA engine support"
+	depends on OF
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Support the Freescale eDMA engine with programmable channel
+	  multiplexing capability for DMA request sources(slot).
+	  This module can be found on Freescale Vybrid and LS-1 SoCs.
 
 config DMA_ENGINE
 	bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index a029d0f4a1be..995946283f8d 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
 obj-$(CONFIG_TI_CPPI41) += cppi41.o
 obj-$(CONFIG_K3_DMA) += k3dma.o
 obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
+obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index 1e506afa33f5..de361a156b34 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -265,7 +266,7 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
  */
 void devm_acpi_dma_controller_free(struct device *dev)
 {
-	WARN_ON(devres_destroy(dev, devm_acpi_dma_release, NULL, NULL));
+	WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL));
 }
 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
 
@@ -343,7 +344,7 @@ static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data)
  * @index:	index of FixedDMA descriptor for @dev
  *
  * Return:
- * Pointer to appropriate dma channel on success or NULL on error.
+ * Pointer to appropriate dma channel on success or an error pointer.
  */
 struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
 		size_t index)
@@ -358,10 +359,10 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
 
 	/* Check if the device was enumerated by ACPI */
 	if (!dev || !ACPI_HANDLE(dev))
-		return NULL;
+		return ERR_PTR(-ENODEV);
 
 	if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
-		return NULL;
+		return ERR_PTR(-ENODEV);
 
 	memset(&pdata, 0, sizeof(pdata));
 	pdata.index = index;
@@ -376,7 +377,7 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
 	acpi_dev_free_resource_list(&resource_list);
 
 	if (dma_spec->slave_id < 0 || dma_spec->chan_id < 0)
-		return NULL;
+		return ERR_PTR(-ENODEV);
 
 	mutex_lock(&acpi_dma_lock);
 
@@ -399,7 +400,7 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
 	}
 
 	mutex_unlock(&acpi_dma_lock);
-	return chan;
+	return chan ? chan : ERR_PTR(-EPROBE_DEFER);
 }
 EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
 
@@ -413,7 +414,7 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
  * the first FixedDMA descriptor is TX and second is RX.
  *
  * Return:
- * Pointer to appropriate dma channel on success or NULL on error.
+ * Pointer to appropriate dma channel on success or an error pointer.
  */
 struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
 		const char *name)
@@ -425,7 +426,7 @@ struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
 	else if (!strcmp(name, "rx"))
 		index = 1;
 	else
-		return NULL;
+		return ERR_PTR(-ENODEV);
 
 	return acpi_dma_request_slave_chan_by_index(dev, index);
 }
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index ed610b497518..a886713937fd 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -627,18 +627,13 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
 struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
 						  const char *name)
 {
-	struct dma_chan *chan;
-
 	/* If device-tree is present get slave info from here */
 	if (dev->of_node)
 		return of_dma_request_slave_channel(dev->of_node, name);
 
 	/* If device was enumerated by ACPI get slave info from here */
-	if (ACPI_HANDLE(dev)) {
-		chan = acpi_dma_request_slave_chan_by_name(dev, name);
-		if (chan)
-			return chan;
-	}
+	if (ACPI_HANDLE(dev))
+		return acpi_dma_request_slave_chan_by_name(dev, name);
 
 	return ERR_PTR(-ENODEV);
 }
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 13ac3f240e79..1b4509712847 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -33,8 +33,8 @@
  * of which use ARM any more).  See the "Databook" from Synopsys for
  * information beyond what licensees probably provide.
  *
- * The driver has currently been tested only with the Atmel AT32AP7000,
- * which does not support descriptor writeback.
+ * The driver has been tested with the Atmel AT32AP7000, which does not
+ * support descriptor writeback.
  */
 
 static inline bool is_request_line_unset(struct dw_dma_chan *dwc)
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c
index e89fc24b8293..755cc6b54453 100644
--- a/drivers/dma/dw/pci.c
+++ b/drivers/dma/dw/pci.c
@@ -83,6 +83,9 @@ static DEFINE_PCI_DEVICE_TABLE(dw_pci_id_table) = {
 	/* BayTrail */
 	{ PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_pdata },
 	{ PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_pdata },
+
+	/* Haswell */
+	{ PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_pdata },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, dw_pci_id_table);
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
new file mode 100644
index 000000000000..9025300a1670
--- /dev/null
+++ b/drivers/dma/fsl-edma.c
@@ -0,0 +1,975 @@
+/*
+ * drivers/dma/fsl-edma.c
+ *
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * Driver for the Freescale eDMA engine with flexible channel multiplexing
+ * capability for DMA request sources. The eDMA block can be found on some
+ * Vybrid and Layerscape SoCs.
+ *
+ * This program is free software; you can redistribute  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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_dma.h>
+
+#include "virt-dma.h"
+
+#define EDMA_CR			0x00
+#define EDMA_ES			0x04
+#define EDMA_ERQ		0x0C
+#define EDMA_EEI		0x14
+#define EDMA_SERQ		0x1B
+#define EDMA_CERQ		0x1A
+#define EDMA_SEEI		0x19
+#define EDMA_CEEI		0x18
+#define EDMA_CINT		0x1F
+#define EDMA_CERR		0x1E
+#define EDMA_SSRT		0x1D
+#define EDMA_CDNE		0x1C
+#define EDMA_INTR		0x24
+#define EDMA_ERR		0x2C
+
+#define EDMA_TCD_SADDR(x)	(0x1000 + 32 * (x))
+#define EDMA_TCD_SOFF(x)	(0x1004 + 32 * (x))
+#define EDMA_TCD_ATTR(x)	(0x1006 + 32 * (x))
+#define EDMA_TCD_NBYTES(x)	(0x1008 + 32 * (x))
+#define EDMA_TCD_SLAST(x)	(0x100C + 32 * (x))
+#define EDMA_TCD_DADDR(x)	(0x1010 + 32 * (x))
+#define EDMA_TCD_DOFF(x)	(0x1014 + 32 * (x))
+#define EDMA_TCD_CITER_ELINK(x)	(0x1016 + 32 * (x))
+#define EDMA_TCD_CITER(x)	(0x1016 + 32 * (x))
+#define EDMA_TCD_DLAST_SGA(x)	(0x1018 + 32 * (x))
+#define EDMA_TCD_CSR(x)		(0x101C + 32 * (x))
+#define EDMA_TCD_BITER_ELINK(x)	(0x101E + 32 * (x))
+#define EDMA_TCD_BITER(x)	(0x101E + 32 * (x))
+
+#define EDMA_CR_EDBG		BIT(1)
+#define EDMA_CR_ERCA		BIT(2)
+#define EDMA_CR_ERGA		BIT(3)
+#define EDMA_CR_HOE		BIT(4)
+#define EDMA_CR_HALT		BIT(5)
+#define EDMA_CR_CLM		BIT(6)
+#define EDMA_CR_EMLM		BIT(7)
+#define EDMA_CR_ECX		BIT(16)
+#define EDMA_CR_CX		BIT(17)
+
+#define EDMA_SEEI_SEEI(x)	((x) & 0x1F)
+#define EDMA_CEEI_CEEI(x)	((x) & 0x1F)
+#define EDMA_CINT_CINT(x)	((x) & 0x1F)
+#define EDMA_CERR_CERR(x)	((x) & 0x1F)
+
+#define EDMA_TCD_ATTR_DSIZE(x)		(((x) & 0x0007))
+#define EDMA_TCD_ATTR_DMOD(x)		(((x) & 0x001F) << 3)
+#define EDMA_TCD_ATTR_SSIZE(x)		(((x) & 0x0007) << 8)
+#define EDMA_TCD_ATTR_SMOD(x)		(((x) & 0x001F) << 11)
+#define EDMA_TCD_ATTR_SSIZE_8BIT	(0x0000)
+#define EDMA_TCD_ATTR_SSIZE_16BIT	(0x0100)
+#define EDMA_TCD_ATTR_SSIZE_32BIT	(0x0200)
+#define EDMA_TCD_ATTR_SSIZE_64BIT	(0x0300)
+#define EDMA_TCD_ATTR_SSIZE_32BYTE	(0x0500)
+#define EDMA_TCD_ATTR_DSIZE_8BIT	(0x0000)
+#define EDMA_TCD_ATTR_DSIZE_16BIT	(0x0001)
+#define EDMA_TCD_ATTR_DSIZE_32BIT	(0x0002)
+#define EDMA_TCD_ATTR_DSIZE_64BIT	(0x0003)
+#define EDMA_TCD_ATTR_DSIZE_32BYTE	(0x0005)
+
+#define EDMA_TCD_SOFF_SOFF(x)		(x)
+#define EDMA_TCD_NBYTES_NBYTES(x)	(x)
+#define EDMA_TCD_SLAST_SLAST(x)		(x)
+#define EDMA_TCD_DADDR_DADDR(x)		(x)
+#define EDMA_TCD_CITER_CITER(x)		((x) & 0x7FFF)
+#define EDMA_TCD_DOFF_DOFF(x)		(x)
+#define EDMA_TCD_DLAST_SGA_DLAST_SGA(x)	(x)
+#define EDMA_TCD_BITER_BITER(x)		((x) & 0x7FFF)
+
+#define EDMA_TCD_CSR_START		BIT(0)
+#define EDMA_TCD_CSR_INT_MAJOR		BIT(1)
+#define EDMA_TCD_CSR_INT_HALF		BIT(2)
+#define EDMA_TCD_CSR_D_REQ		BIT(3)
+#define EDMA_TCD_CSR_E_SG		BIT(4)
+#define EDMA_TCD_CSR_E_LINK		BIT(5)
+#define EDMA_TCD_CSR_ACTIVE		BIT(6)
+#define EDMA_TCD_CSR_DONE		BIT(7)
+
+#define EDMAMUX_CHCFG_DIS		0x0
+#define EDMAMUX_CHCFG_ENBL		0x80
+#define EDMAMUX_CHCFG_SOURCE(n)		((n) & 0x3F)
+
+#define DMAMUX_NR	2
+
+#define FSL_EDMA_BUSWIDTHS	BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+				BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+				BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
+				BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
+
+struct fsl_edma_hw_tcd {
+	u32	saddr;
+	u16	soff;
+	u16	attr;
+	u32	nbytes;
+	u32	slast;
+	u32	daddr;
+	u16	doff;
+	u16	citer;
+	u32	dlast_sga;
+	u16	csr;
+	u16	biter;
+};
+
+struct fsl_edma_sw_tcd {
+	dma_addr_t			ptcd;
+	struct fsl_edma_hw_tcd		*vtcd;
+};
+
+struct fsl_edma_slave_config {
+	enum dma_transfer_direction	dir;
+	enum dma_slave_buswidth		addr_width;
+	u32				dev_addr;
+	u32				burst;
+	u32				attr;
+};
+
+struct fsl_edma_chan {
+	struct virt_dma_chan		vchan;
+	enum dma_status			status;
+	struct fsl_edma_engine		*edma;
+	struct fsl_edma_desc		*edesc;
+	struct fsl_edma_slave_config	fsc;
+	struct dma_pool			*tcd_pool;
+};
+
+struct fsl_edma_desc {
+	struct virt_dma_desc		vdesc;
+	struct fsl_edma_chan		*echan;
+	bool				iscyclic;
+	unsigned int			n_tcds;
+	struct fsl_edma_sw_tcd		tcd[];
+};
+
+struct fsl_edma_engine {
+	struct dma_device	dma_dev;
+	void __iomem		*membase;
+	void __iomem		*muxbase[DMAMUX_NR];
+	struct clk		*muxclk[DMAMUX_NR];
+	struct mutex		fsl_edma_mutex;
+	u32			n_chans;
+	int			txirq;
+	int			errirq;
+	bool			big_endian;
+	struct fsl_edma_chan	chans[];
+};
+
+/*
+ * R/W functions for big- or little-endian registers
+ * the eDMA controller's endian is independent of the CPU core's endian.
+ */
+
+static u16 edma_readw(struct fsl_edma_engine *edma, void __iomem *addr)
+{
+	if (edma->big_endian)
+		return ioread16be(addr);
+	else
+		return ioread16(addr);
+}
+
+static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
+{
+	if (edma->big_endian)
+		return ioread32be(addr);
+	else
+		return ioread32(addr);
+}
+
+static void edma_writeb(struct fsl_edma_engine *edma, u8 val, void __iomem *addr)
+{
+	iowrite8(val, addr);
+}
+
+static void edma_writew(struct fsl_edma_engine *edma, u16 val, void __iomem *addr)
+{
+	if (edma->big_endian)
+		iowrite16be(val, addr);
+	else
+		iowrite16(val, addr);
+}
+
+static void edma_writel(struct fsl_edma_engine *edma, u32 val, void __iomem *addr)
+{
+	if (edma->big_endian)
+		iowrite32be(val, addr);
+	else
+		iowrite32(val, addr);
+}
+
+static struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct fsl_edma_chan, vchan.chan);
+}
+
+static struct fsl_edma_desc *to_fsl_edma_desc(struct virt_dma_desc *vd)
+{
+	return container_of(vd, struct fsl_edma_desc, vdesc);
+}
+
+static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan)
+{
+	void __iomem *addr = fsl_chan->edma->membase;
+	u32 ch = fsl_chan->vchan.chan.chan_id;
+
+	edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), addr + EDMA_SEEI);
+	edma_writeb(fsl_chan->edma, ch, addr + EDMA_SERQ);
+}
+
+static void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
+{
+	void __iomem *addr = fsl_chan->edma->membase;
+	u32 ch = fsl_chan->vchan.chan.chan_id;
+
+	edma_writeb(fsl_chan->edma, ch, addr + EDMA_CERQ);
+	edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), addr + EDMA_CEEI);
+}
+
+static void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
+			unsigned int slot, bool enable)
+{
+	u32 ch = fsl_chan->vchan.chan.chan_id;
+	void __iomem *muxaddr = fsl_chan->edma->muxbase[ch / DMAMUX_NR];
+	unsigned chans_per_mux, ch_off;
+
+	chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
+	ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
+
+	if (enable)
+		edma_writeb(fsl_chan->edma,
+				EDMAMUX_CHCFG_ENBL | EDMAMUX_CHCFG_SOURCE(slot),
+				muxaddr + ch_off);
+	else
+		edma_writeb(fsl_chan->edma, EDMAMUX_CHCFG_DIS, muxaddr + ch_off);
+}
+
+static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth addr_width)
+{
+	switch (addr_width) {
+	case 1:
+		return EDMA_TCD_ATTR_SSIZE_8BIT | EDMA_TCD_ATTR_DSIZE_8BIT;
+	case 2:
+		return EDMA_TCD_ATTR_SSIZE_16BIT | EDMA_TCD_ATTR_DSIZE_16BIT;
+	case 4:
+		return EDMA_TCD_ATTR_SSIZE_32BIT | EDMA_TCD_ATTR_DSIZE_32BIT;
+	case 8:
+		return EDMA_TCD_ATTR_SSIZE_64BIT | EDMA_TCD_ATTR_DSIZE_64BIT;
+	default:
+		return EDMA_TCD_ATTR_SSIZE_32BIT | EDMA_TCD_ATTR_DSIZE_32BIT;
+	}
+}
+
+static void fsl_edma_free_desc(struct virt_dma_desc *vdesc)
+{
+	struct fsl_edma_desc *fsl_desc;
+	int i;
+
+	fsl_desc = to_fsl_edma_desc(vdesc);
+	for (i = 0; i < fsl_desc->n_tcds; i++)
+			dma_pool_free(fsl_desc->echan->tcd_pool,
+					fsl_desc->tcd[i].vtcd,
+					fsl_desc->tcd[i].ptcd);
+	kfree(fsl_desc);
+}
+
+static int fsl_edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+		unsigned long arg)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	struct dma_slave_config *cfg = (void *)arg;
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+		fsl_edma_disable_request(fsl_chan);
+		fsl_chan->edesc = NULL;
+		vchan_get_all_descriptors(&fsl_chan->vchan, &head);
+		spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+		vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
+		return 0;
+
+	case DMA_SLAVE_CONFIG:
+		fsl_chan->fsc.dir = cfg->direction;
+		if (cfg->direction == DMA_DEV_TO_MEM) {
+			fsl_chan->fsc.dev_addr = cfg->src_addr;
+			fsl_chan->fsc.addr_width = cfg->src_addr_width;
+			fsl_chan->fsc.burst = cfg->src_maxburst;
+			fsl_chan->fsc.attr = fsl_edma_get_tcd_attr(cfg->src_addr_width);
+		} else if (cfg->direction == DMA_MEM_TO_DEV) {
+			fsl_chan->fsc.dev_addr = cfg->dst_addr;
+			fsl_chan->fsc.addr_width = cfg->dst_addr_width;
+			fsl_chan->fsc.burst = cfg->dst_maxburst;
+			fsl_chan->fsc.attr = fsl_edma_get_tcd_attr(cfg->dst_addr_width);
+		} else {
+			return -EINVAL;
+		}
+		return 0;
+
+	case DMA_PAUSE:
+		spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+		if (fsl_chan->edesc) {
+			fsl_edma_disable_request(fsl_chan);
+			fsl_chan->status = DMA_PAUSED;
+		}
+		spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+		return 0;
+
+	case DMA_RESUME:
+		spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+		if (fsl_chan->edesc) {
+			fsl_edma_enable_request(fsl_chan);
+			fsl_chan->status = DMA_IN_PROGRESS;
+		}
+		spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+		return 0;
+
+	default:
+		return -ENXIO;
+	}
+}
+
+static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
+		struct virt_dma_desc *vdesc, bool in_progress)
+{
+	struct fsl_edma_desc *edesc = fsl_chan->edesc;
+	void __iomem *addr = fsl_chan->edma->membase;
+	u32 ch = fsl_chan->vchan.chan.chan_id;
+	enum dma_transfer_direction dir = fsl_chan->fsc.dir;
+	dma_addr_t cur_addr, dma_addr;
+	size_t len, size;
+	int i;
+
+	/* calculate the total size in this desc */
+	for (len = i = 0; i < fsl_chan->edesc->n_tcds; i++)
+		len += edma_readl(fsl_chan->edma, &(edesc->tcd[i].vtcd->nbytes))
+			* edma_readw(fsl_chan->edma, &(edesc->tcd[i].vtcd->biter));
+
+	if (!in_progress)
+		return len;
+
+	if (dir == DMA_MEM_TO_DEV)
+		cur_addr = edma_readl(fsl_chan->edma, addr + EDMA_TCD_SADDR(ch));
+	else
+		cur_addr = edma_readl(fsl_chan->edma, addr + EDMA_TCD_DADDR(ch));
+
+	/* figure out the finished and calculate the residue */
+	for (i = 0; i < fsl_chan->edesc->n_tcds; i++) {
+		size = edma_readl(fsl_chan->edma, &(edesc->tcd[i].vtcd->nbytes))
+			* edma_readw(fsl_chan->edma, &(edesc->tcd[i].vtcd->biter));
+		if (dir == DMA_MEM_TO_DEV)
+			dma_addr = edma_readl(fsl_chan->edma,
+					&(edesc->tcd[i].vtcd->saddr));
+		else
+			dma_addr = edma_readl(fsl_chan->edma,
+					&(edesc->tcd[i].vtcd->daddr));
+
+		len -= size;
+		if (cur_addr > dma_addr && cur_addr < dma_addr + size) {
+			len += dma_addr + size - cur_addr;
+			break;
+		}
+	}
+
+	return len;
+}
+
+static enum dma_status fsl_edma_tx_status(struct dma_chan *chan,
+		dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	struct virt_dma_desc *vdesc;
+	enum dma_status status;
+	unsigned long flags;
+
+	status = dma_cookie_status(chan, cookie, txstate);
+	if (status == DMA_COMPLETE)
+		return status;
+
+	if (!txstate)
+		return fsl_chan->status;
+
+	spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+	vdesc = vchan_find_desc(&fsl_chan->vchan, cookie);
+	if (fsl_chan->edesc && cookie == fsl_chan->edesc->vdesc.tx.cookie)
+		txstate->residue = fsl_edma_desc_residue(fsl_chan, vdesc, true);
+	else if (vdesc)
+		txstate->residue = fsl_edma_desc_residue(fsl_chan, vdesc, false);
+	else
+		txstate->residue = 0;
+
+	spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+
+	return fsl_chan->status;
+}
+
+static void fsl_edma_set_tcd_params(struct fsl_edma_chan *fsl_chan,
+		u32 src, u32 dst, u16 attr, u16 soff, u32 nbytes,
+		u32 slast, u16 citer, u16 biter, u32 doff, u32 dlast_sga,
+		u16 csr)
+{
+	void __iomem *addr = fsl_chan->edma->membase;
+	u32 ch = fsl_chan->vchan.chan.chan_id;
+
+	/*
+	 * TCD parameters have been swapped in fill_tcd_params(),
+	 * so just write them to registers in the cpu endian here
+	 */
+	writew(0, addr + EDMA_TCD_CSR(ch));
+	writel(src, addr + EDMA_TCD_SADDR(ch));
+	writel(dst, addr + EDMA_TCD_DADDR(ch));
+	writew(attr, addr + EDMA_TCD_ATTR(ch));
+	writew(soff, addr + EDMA_TCD_SOFF(ch));
+	writel(nbytes, addr + EDMA_TCD_NBYTES(ch));
+	writel(slast, addr + EDMA_TCD_SLAST(ch));
+	writew(citer, addr + EDMA_TCD_CITER(ch));
+	writew(biter, addr + EDMA_TCD_BITER(ch));
+	writew(doff, addr + EDMA_TCD_DOFF(ch));
+	writel(dlast_sga, addr + EDMA_TCD_DLAST_SGA(ch));
+	writew(csr, addr + EDMA_TCD_CSR(ch));
+}
+
+static void fill_tcd_params(struct fsl_edma_engine *edma,
+		struct fsl_edma_hw_tcd *tcd, u32 src, u32 dst,
+		u16 attr, u16 soff, u32 nbytes, u32 slast, u16 citer,
+		u16 biter, u16 doff, u32 dlast_sga, bool major_int,
+		bool disable_req, bool enable_sg)
+{
+	u16 csr = 0;
+
+	/*
+	 * eDMA hardware SGs require the TCD parameters stored in memory
+	 * the same endian as the eDMA module so that they can be loaded
+	 * automatically by the engine
+	 */
+	edma_writel(edma, src, &(tcd->saddr));
+	edma_writel(edma, dst, &(tcd->daddr));
+	edma_writew(edma, attr, &(tcd->attr));
+	edma_writew(edma, EDMA_TCD_SOFF_SOFF(soff), &(tcd->soff));
+	edma_writel(edma, EDMA_TCD_NBYTES_NBYTES(nbytes), &(tcd->nbytes));
+	edma_writel(edma, EDMA_TCD_SLAST_SLAST(slast), &(tcd->slast));
+	edma_writew(edma, EDMA_TCD_CITER_CITER(citer), &(tcd->citer));
+	edma_writew(edma, EDMA_TCD_DOFF_DOFF(doff), &(tcd->doff));
+	edma_writel(edma, EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga), &(tcd->dlast_sga));
+	edma_writew(edma, EDMA_TCD_BITER_BITER(biter), &(tcd->biter));
+	if (major_int)
+		csr |= EDMA_TCD_CSR_INT_MAJOR;
+
+	if (disable_req)
+		csr |= EDMA_TCD_CSR_D_REQ;
+
+	if (enable_sg)
+		csr |= EDMA_TCD_CSR_E_SG;
+
+	edma_writew(edma, csr, &(tcd->csr));
+}
+
+static struct fsl_edma_desc *fsl_edma_alloc_desc(struct fsl_edma_chan *fsl_chan,
+		int sg_len)
+{
+	struct fsl_edma_desc *fsl_desc;
+	int i;
+
+	fsl_desc = kzalloc(sizeof(*fsl_desc) + sizeof(struct fsl_edma_sw_tcd) * sg_len,
+				GFP_NOWAIT);
+	if (!fsl_desc)
+		return NULL;
+
+	fsl_desc->echan = fsl_chan;
+	fsl_desc->n_tcds = sg_len;
+	for (i = 0; i < sg_len; i++) {
+		fsl_desc->tcd[i].vtcd = dma_pool_alloc(fsl_chan->tcd_pool,
+					GFP_NOWAIT, &fsl_desc->tcd[i].ptcd);
+		if (!fsl_desc->tcd[i].vtcd)
+			goto err;
+	}
+	return fsl_desc;
+
+err:
+	while (--i >= 0)
+		dma_pool_free(fsl_chan->tcd_pool, fsl_desc->tcd[i].vtcd,
+				fsl_desc->tcd[i].ptcd);
+	kfree(fsl_desc);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
+		size_t period_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	struct fsl_edma_desc *fsl_desc;
+	dma_addr_t dma_buf_next;
+	int sg_len, i;
+	u32 src_addr, dst_addr, last_sg, nbytes;
+	u16 soff, doff, iter;
+
+	if (!is_slave_direction(fsl_chan->fsc.dir))
+		return NULL;
+
+	sg_len = buf_len / period_len;
+	fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len);
+	if (!fsl_desc)
+		return NULL;
+	fsl_desc->iscyclic = true;
+
+	dma_buf_next = dma_addr;
+	nbytes = fsl_chan->fsc.addr_width * fsl_chan->fsc.burst;
+	iter = period_len / nbytes;
+
+	for (i = 0; i < sg_len; i++) {
+		if (dma_buf_next >= dma_addr + buf_len)
+			dma_buf_next = dma_addr;
+
+		/* get next sg's physical address */
+		last_sg = fsl_desc->tcd[(i + 1) % sg_len].ptcd;
+
+		if (fsl_chan->fsc.dir == DMA_MEM_TO_DEV) {
+			src_addr = dma_buf_next;
+			dst_addr = fsl_chan->fsc.dev_addr;
+			soff = fsl_chan->fsc.addr_width;
+			doff = 0;
+		} else {
+			src_addr = fsl_chan->fsc.dev_addr;
+			dst_addr = dma_buf_next;
+			soff = 0;
+			doff = fsl_chan->fsc.addr_width;
+		}
+
+		fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd, src_addr,
+				dst_addr, fsl_chan->fsc.attr, soff, nbytes, 0,
+				iter, iter, doff, last_sg, true, false, true);
+		dma_buf_next += period_len;
+	}
+
+	return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	struct fsl_edma_desc *fsl_desc;
+	struct scatterlist *sg;
+	u32 src_addr, dst_addr, last_sg, nbytes;
+	u16 soff, doff, iter;
+	int i;
+
+	if (!is_slave_direction(fsl_chan->fsc.dir))
+		return NULL;
+
+	fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len);
+	if (!fsl_desc)
+		return NULL;
+	fsl_desc->iscyclic = false;
+
+	nbytes = fsl_chan->fsc.addr_width * fsl_chan->fsc.burst;
+	for_each_sg(sgl, sg, sg_len, i) {
+		/* get next sg's physical address */
+		last_sg = fsl_desc->tcd[(i + 1) % sg_len].ptcd;
+
+		if (fsl_chan->fsc.dir == DMA_MEM_TO_DEV) {
+			src_addr = sg_dma_address(sg);
+			dst_addr = fsl_chan->fsc.dev_addr;
+			soff = fsl_chan->fsc.addr_width;
+			doff = 0;
+		} else {
+			src_addr = fsl_chan->fsc.dev_addr;
+			dst_addr = sg_dma_address(sg);
+			soff = 0;
+			doff = fsl_chan->fsc.addr_width;
+		}
+
+		iter = sg_dma_len(sg) / nbytes;
+		if (i < sg_len - 1) {
+			last_sg = fsl_desc->tcd[(i + 1)].ptcd;
+			fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd,
+					src_addr, dst_addr, fsl_chan->fsc.attr,
+					soff, nbytes, 0, iter, iter, doff, last_sg,
+					false, false, true);
+		} else {
+			last_sg = 0;
+			fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd,
+					src_addr, dst_addr, fsl_chan->fsc.attr,
+					soff, nbytes, 0, iter, iter, doff, last_sg,
+					true, true, false);
+		}
+	}
+
+	return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags);
+}
+
+static void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
+{
+	struct fsl_edma_hw_tcd *tcd;
+	struct virt_dma_desc *vdesc;
+
+	vdesc = vchan_next_desc(&fsl_chan->vchan);
+	if (!vdesc)
+		return;
+	fsl_chan->edesc = to_fsl_edma_desc(vdesc);
+	tcd = fsl_chan->edesc->tcd[0].vtcd;
+	fsl_edma_set_tcd_params(fsl_chan, tcd->saddr, tcd->daddr, tcd->attr,
+			tcd->soff, tcd->nbytes, tcd->slast, tcd->citer,
+			tcd->biter, tcd->doff, tcd->dlast_sga, tcd->csr);
+	fsl_edma_enable_request(fsl_chan);
+	fsl_chan->status = DMA_IN_PROGRESS;
+}
+
+static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
+{
+	struct fsl_edma_engine *fsl_edma = dev_id;
+	unsigned int intr, ch;
+	void __iomem *base_addr;
+	struct fsl_edma_chan *fsl_chan;
+
+	base_addr = fsl_edma->membase;
+
+	intr = edma_readl(fsl_edma, base_addr + EDMA_INTR);
+	if (!intr)
+		return IRQ_NONE;
+
+	for (ch = 0; ch < fsl_edma->n_chans; ch++) {
+		if (intr & (0x1 << ch)) {
+			edma_writeb(fsl_edma, EDMA_CINT_CINT(ch),
+				base_addr + EDMA_CINT);
+
+			fsl_chan = &fsl_edma->chans[ch];
+
+			spin_lock(&fsl_chan->vchan.lock);
+			if (!fsl_chan->edesc->iscyclic) {
+				list_del(&fsl_chan->edesc->vdesc.node);
+				vchan_cookie_complete(&fsl_chan->edesc->vdesc);
+				fsl_chan->edesc = NULL;
+				fsl_chan->status = DMA_COMPLETE;
+			} else {
+				vchan_cyclic_callback(&fsl_chan->edesc->vdesc);
+			}
+
+			if (!fsl_chan->edesc)
+				fsl_edma_xfer_desc(fsl_chan);
+
+			spin_unlock(&fsl_chan->vchan.lock);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsl_edma_err_handler(int irq, void *dev_id)
+{
+	struct fsl_edma_engine *fsl_edma = dev_id;
+	unsigned int err, ch;
+
+	err = edma_readl(fsl_edma, fsl_edma->membase + EDMA_ERR);
+	if (!err)
+		return IRQ_NONE;
+
+	for (ch = 0; ch < fsl_edma->n_chans; ch++) {
+		if (err & (0x1 << ch)) {
+			fsl_edma_disable_request(&fsl_edma->chans[ch]);
+			edma_writeb(fsl_edma, EDMA_CERR_CERR(ch),
+				fsl_edma->membase + EDMA_CERR);
+			fsl_edma->chans[ch].status = DMA_ERROR;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsl_edma_irq_handler(int irq, void *dev_id)
+{
+	if (fsl_edma_tx_handler(irq, dev_id) == IRQ_HANDLED)
+		return IRQ_HANDLED;
+
+	return fsl_edma_err_handler(irq, dev_id);
+}
+
+static void fsl_edma_issue_pending(struct dma_chan *chan)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+
+	if (vchan_issue_pending(&fsl_chan->vchan) && !fsl_chan->edesc)
+		fsl_edma_xfer_desc(fsl_chan);
+
+	spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+}
+
+static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
+		struct of_dma *ofdma)
+{
+	struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
+	struct dma_chan *chan;
+
+	if (dma_spec->args_count != 2)
+		return NULL;
+
+	mutex_lock(&fsl_edma->fsl_edma_mutex);
+	list_for_each_entry(chan, &fsl_edma->dma_dev.channels, device_node) {
+		if (chan->client_count)
+			continue;
+		if ((chan->chan_id / DMAMUX_NR) == dma_spec->args[0]) {
+			chan = dma_get_slave_channel(chan);
+			if (chan) {
+				chan->device->privatecnt++;
+				fsl_edma_chan_mux(to_fsl_edma_chan(chan),
+					dma_spec->args[1], true);
+				mutex_unlock(&fsl_edma->fsl_edma_mutex);
+				return chan;
+			}
+		}
+	}
+	mutex_unlock(&fsl_edma->fsl_edma_mutex);
+	return NULL;
+}
+
+static int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+
+	fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev,
+				sizeof(struct fsl_edma_hw_tcd),
+				32, 0);
+	return 0;
+}
+
+static void fsl_edma_free_chan_resources(struct dma_chan *chan)
+{
+	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+	fsl_edma_disable_request(fsl_chan);
+	fsl_edma_chan_mux(fsl_chan, 0, false);
+	fsl_chan->edesc = NULL;
+	vchan_get_all_descriptors(&fsl_chan->vchan, &head);
+	spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
+
+	vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
+	dma_pool_destroy(fsl_chan->tcd_pool);
+	fsl_chan->tcd_pool = NULL;
+}
+
+static int fsl_dma_device_slave_caps(struct dma_chan *dchan,
+		struct dma_slave_caps *caps)
+{
+	caps->src_addr_widths = FSL_EDMA_BUSWIDTHS;
+	caps->dstn_addr_widths = FSL_EDMA_BUSWIDTHS;
+	caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	caps->cmd_pause = true;
+	caps->cmd_terminate = true;
+
+	return 0;
+}
+
+static int
+fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
+{
+	int ret;
+
+	fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
+	if (fsl_edma->txirq < 0) {
+		dev_err(&pdev->dev, "Can't get edma-tx irq.\n");
+		return fsl_edma->txirq;
+	}
+
+	fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
+	if (fsl_edma->errirq < 0) {
+		dev_err(&pdev->dev, "Can't get edma-err irq.\n");
+		return fsl_edma->errirq;
+	}
+
+	if (fsl_edma->txirq == fsl_edma->errirq) {
+		ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
+				fsl_edma_irq_handler, 0, "eDMA", fsl_edma);
+		if (ret) {
+			dev_err(&pdev->dev, "Can't register eDMA IRQ.\n");
+			 return  ret;
+		}
+	} else {
+		ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
+				fsl_edma_tx_handler, 0, "eDMA tx", fsl_edma);
+		if (ret) {
+			dev_err(&pdev->dev, "Can't register eDMA tx IRQ.\n");
+			return  ret;
+		}
+
+		ret = devm_request_irq(&pdev->dev, fsl_edma->errirq,
+				fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
+		if (ret) {
+			dev_err(&pdev->dev, "Can't register eDMA err IRQ.\n");
+			return  ret;
+		}
+	}
+
+	return 0;
+}
+
+static int fsl_edma_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct fsl_edma_engine *fsl_edma;
+	struct fsl_edma_chan *fsl_chan;
+	struct resource *res;
+	int len, chans;
+	int ret, i;
+
+	ret = of_property_read_u32(np, "dma-channels", &chans);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't get dma-channels.\n");
+		return ret;
+	}
+
+	len = sizeof(*fsl_edma) + sizeof(*fsl_chan) * chans;
+	fsl_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+	if (!fsl_edma)
+		return -ENOMEM;
+
+	fsl_edma->n_chans = chans;
+	mutex_init(&fsl_edma->fsl_edma_mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fsl_edma->membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fsl_edma->membase))
+		return PTR_ERR(fsl_edma->membase);
+
+	for (i = 0; i < DMAMUX_NR; i++) {
+		char clkname[32];
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+		fsl_edma->muxbase[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(fsl_edma->muxbase[i]))
+			return PTR_ERR(fsl_edma->muxbase[i]);
+
+		sprintf(clkname, "dmamux%d", i);
+		fsl_edma->muxclk[i] = devm_clk_get(&pdev->dev, clkname);
+		if (IS_ERR(fsl_edma->muxclk[i])) {
+			dev_err(&pdev->dev, "Missing DMAMUX block clock.\n");
+			return PTR_ERR(fsl_edma->muxclk[i]);
+		}
+
+		ret = clk_prepare_enable(fsl_edma->muxclk[i]);
+		if (ret) {
+			dev_err(&pdev->dev, "DMAMUX clk block failed.\n");
+			return ret;
+		}
+
+	}
+
+	ret = fsl_edma_irq_init(pdev, fsl_edma);
+	if (ret)
+		return ret;
+
+	fsl_edma->big_endian = of_property_read_bool(np, "big-endian");
+
+	INIT_LIST_HEAD(&fsl_edma->dma_dev.channels);
+	for (i = 0; i < fsl_edma->n_chans; i++) {
+		struct fsl_edma_chan *fsl_chan = &fsl_edma->chans[i];
+
+		fsl_chan->edma = fsl_edma;
+
+		fsl_chan->vchan.desc_free = fsl_edma_free_desc;
+		vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
+
+		edma_writew(fsl_edma, 0x0, fsl_edma->membase + EDMA_TCD_CSR(i));
+		fsl_edma_chan_mux(fsl_chan, 0, false);
+	}
+
+	dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
+	dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
+	dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
+
+	fsl_edma->dma_dev.dev = &pdev->dev;
+	fsl_edma->dma_dev.device_alloc_chan_resources
+		= fsl_edma_alloc_chan_resources;
+	fsl_edma->dma_dev.device_free_chan_resources
+		= fsl_edma_free_chan_resources;
+	fsl_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
+	fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
+	fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
+	fsl_edma->dma_dev.device_control = fsl_edma_control;
+	fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
+	fsl_edma->dma_dev.device_slave_caps = fsl_dma_device_slave_caps;
+
+	platform_set_drvdata(pdev, fsl_edma);
+
+	ret = dma_async_device_register(&fsl_edma->dma_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't register Freescale eDMA engine.\n");
+		return ret;
+	}
+
+	ret = of_dma_controller_register(np, fsl_edma_xlate, fsl_edma);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't register Freescale eDMA of_dma.\n");
+		dma_async_device_unregister(&fsl_edma->dma_dev);
+		return ret;
+	}
+
+	/* enable round robin arbitration */
+	edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, fsl_edma->membase + EDMA_CR);
+
+	return 0;
+}
+
+static int fsl_edma_remove(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev);
+	int i;
+
+	of_dma_controller_free(np);
+	dma_async_device_unregister(&fsl_edma->dma_dev);
+
+	for (i = 0; i < DMAMUX_NR; i++)
+		clk_disable_unprepare(fsl_edma->muxclk[i]);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_edma_dt_ids[] = {
+	{ .compatible = "fsl,vf610-edma", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
+
+static struct platform_driver fsl_edma_driver = {
+	.driver		= {
+		.name	= "fsl-edma",
+		.owner  = THIS_MODULE,
+		.of_match_table = fsl_edma_dt_ids,
+	},
+	.probe          = fsl_edma_probe,
+	.remove		= fsl_edma_remove,
+};
+
+module_platform_driver(fsl_edma_driver);
+
+MODULE_ALIAS("platform:fsl-edma");
+MODULE_DESCRIPTION("Freescale eDMA engine driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 362e7c49f2e1..64ceca2920b8 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -5,6 +5,7 @@
  * 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/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
@@ -26,11 +27,21 @@ struct omap_dmadev {
 	spinlock_t lock;
 	struct tasklet_struct task;
 	struct list_head pending;
+	void __iomem *base;
+	const struct omap_dma_reg *reg_map;
+	struct omap_system_dma_plat_info *plat;
+	bool legacy;
+	spinlock_t irq_lock;
+	uint32_t irq_enable_mask;
+	struct omap_chan *lch_map[32];
 };
 
 struct omap_chan {
 	struct virt_dma_chan vc;
 	struct list_head node;
+	void __iomem *channel_base;
+	const struct omap_dma_reg *reg_map;
+	uint32_t ccr;
 
 	struct dma_slave_config	cfg;
 	unsigned dma_sig;
@@ -54,19 +65,93 @@ struct omap_desc {
 	dma_addr_t dev_addr;
 
 	int16_t fi;		/* for OMAP_DMA_SYNC_PACKET */
-	uint8_t es;		/* OMAP_DMA_DATA_TYPE_xxx */
-	uint8_t sync_mode;	/* OMAP_DMA_SYNC_xxx */
-	uint8_t sync_type;	/* OMAP_DMA_xxx_SYNC* */
-	uint8_t periph_port;	/* Peripheral port */
+	uint8_t es;		/* CSDP_DATA_TYPE_xxx */
+	uint32_t ccr;		/* CCR value */
+	uint16_t clnk_ctrl;	/* CLNK_CTRL value */
+	uint16_t cicr;		/* CICR value */
+	uint32_t csdp;		/* CSDP value */
 
 	unsigned sglen;
 	struct omap_sg sg[0];
 };
 
+enum {
+	CCR_FS			= BIT(5),
+	CCR_READ_PRIORITY	= BIT(6),
+	CCR_ENABLE		= BIT(7),
+	CCR_AUTO_INIT		= BIT(8),	/* OMAP1 only */
+	CCR_REPEAT		= BIT(9),	/* OMAP1 only */
+	CCR_OMAP31_DISABLE	= BIT(10),	/* OMAP1 only */
+	CCR_SUSPEND_SENSITIVE	= BIT(8),	/* OMAP2+ only */
+	CCR_RD_ACTIVE		= BIT(9),	/* OMAP2+ only */
+	CCR_WR_ACTIVE		= BIT(10),	/* OMAP2+ only */
+	CCR_SRC_AMODE_CONSTANT	= 0 << 12,
+	CCR_SRC_AMODE_POSTINC	= 1 << 12,
+	CCR_SRC_AMODE_SGLIDX	= 2 << 12,
+	CCR_SRC_AMODE_DBLIDX	= 3 << 12,
+	CCR_DST_AMODE_CONSTANT	= 0 << 14,
+	CCR_DST_AMODE_POSTINC	= 1 << 14,
+	CCR_DST_AMODE_SGLIDX	= 2 << 14,
+	CCR_DST_AMODE_DBLIDX	= 3 << 14,
+	CCR_CONSTANT_FILL	= BIT(16),
+	CCR_TRANSPARENT_COPY	= BIT(17),
+	CCR_BS			= BIT(18),
+	CCR_SUPERVISOR		= BIT(22),
+	CCR_PREFETCH		= BIT(23),
+	CCR_TRIGGER_SRC		= BIT(24),
+	CCR_BUFFERING_DISABLE	= BIT(25),
+	CCR_WRITE_PRIORITY	= BIT(26),
+	CCR_SYNC_ELEMENT	= 0,
+	CCR_SYNC_FRAME		= CCR_FS,
+	CCR_SYNC_BLOCK		= CCR_BS,
+	CCR_SYNC_PACKET		= CCR_BS | CCR_FS,
+
+	CSDP_DATA_TYPE_8	= 0,
+	CSDP_DATA_TYPE_16	= 1,
+	CSDP_DATA_TYPE_32	= 2,
+	CSDP_SRC_PORT_EMIFF	= 0 << 2, /* OMAP1 only */
+	CSDP_SRC_PORT_EMIFS	= 1 << 2, /* OMAP1 only */
+	CSDP_SRC_PORT_OCP_T1	= 2 << 2, /* OMAP1 only */
+	CSDP_SRC_PORT_TIPB	= 3 << 2, /* OMAP1 only */
+	CSDP_SRC_PORT_OCP_T2	= 4 << 2, /* OMAP1 only */
+	CSDP_SRC_PORT_MPUI	= 5 << 2, /* OMAP1 only */
+	CSDP_SRC_PACKED		= BIT(6),
+	CSDP_SRC_BURST_1	= 0 << 7,
+	CSDP_SRC_BURST_16	= 1 << 7,
+	CSDP_SRC_BURST_32	= 2 << 7,
+	CSDP_SRC_BURST_64	= 3 << 7,
+	CSDP_DST_PORT_EMIFF	= 0 << 9, /* OMAP1 only */
+	CSDP_DST_PORT_EMIFS	= 1 << 9, /* OMAP1 only */
+	CSDP_DST_PORT_OCP_T1	= 2 << 9, /* OMAP1 only */
+	CSDP_DST_PORT_TIPB	= 3 << 9, /* OMAP1 only */
+	CSDP_DST_PORT_OCP_T2	= 4 << 9, /* OMAP1 only */
+	CSDP_DST_PORT_MPUI	= 5 << 9, /* OMAP1 only */
+	CSDP_DST_PACKED		= BIT(13),
+	CSDP_DST_BURST_1	= 0 << 14,
+	CSDP_DST_BURST_16	= 1 << 14,
+	CSDP_DST_BURST_32	= 2 << 14,
+	CSDP_DST_BURST_64	= 3 << 14,
+
+	CICR_TOUT_IE		= BIT(0),	/* OMAP1 only */
+	CICR_DROP_IE		= BIT(1),
+	CICR_HALF_IE		= BIT(2),
+	CICR_FRAME_IE		= BIT(3),
+	CICR_LAST_IE		= BIT(4),
+	CICR_BLOCK_IE		= BIT(5),
+	CICR_PKT_IE		= BIT(7),	/* OMAP2+ only */
+	CICR_TRANS_ERR_IE	= BIT(8),	/* OMAP2+ only */
+	CICR_SUPERVISOR_ERR_IE	= BIT(10),	/* OMAP2+ only */
+	CICR_MISALIGNED_ERR_IE	= BIT(11),	/* OMAP2+ only */
+	CICR_DRAIN_IE		= BIT(12),	/* OMAP2+ only */
+	CICR_SUPER_BLOCK_IE	= BIT(14),	/* OMAP2+ only */
+
+	CLNK_CTRL_ENABLE_LNK	= BIT(15),
+};
+
 static const unsigned es_bytes[] = {
-	[OMAP_DMA_DATA_TYPE_S8] = 1,
-	[OMAP_DMA_DATA_TYPE_S16] = 2,
-	[OMAP_DMA_DATA_TYPE_S32] = 4,
+	[CSDP_DATA_TYPE_8] = 1,
+	[CSDP_DATA_TYPE_16] = 2,
+	[CSDP_DATA_TYPE_32] = 4,
 };
 
 static struct of_dma_filter_info omap_dma_info = {
@@ -93,28 +178,214 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
 	kfree(container_of(vd, struct omap_desc, vd));
 }
 
+static void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr)
+{
+	switch (type) {
+	case OMAP_DMA_REG_16BIT:
+		writew_relaxed(val, addr);
+		break;
+	case OMAP_DMA_REG_2X16BIT:
+		writew_relaxed(val, addr);
+		writew_relaxed(val >> 16, addr + 2);
+		break;
+	case OMAP_DMA_REG_32BIT:
+		writel_relaxed(val, addr);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+
+static unsigned omap_dma_read(unsigned type, void __iomem *addr)
+{
+	unsigned val;
+
+	switch (type) {
+	case OMAP_DMA_REG_16BIT:
+		val = readw_relaxed(addr);
+		break;
+	case OMAP_DMA_REG_2X16BIT:
+		val = readw_relaxed(addr);
+		val |= readw_relaxed(addr + 2) << 16;
+		break;
+	case OMAP_DMA_REG_32BIT:
+		val = readl_relaxed(addr);
+		break;
+	default:
+		WARN_ON(1);
+		val = 0;
+	}
+
+	return val;
+}
+
+static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val)
+{
+	const struct omap_dma_reg *r = od->reg_map + reg;
+
+	WARN_ON(r->stride);
+
+	omap_dma_write(val, r->type, od->base + r->offset);
+}
+
+static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg)
+{
+	const struct omap_dma_reg *r = od->reg_map + reg;
+
+	WARN_ON(r->stride);
+
+	return omap_dma_read(r->type, od->base + r->offset);
+}
+
+static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val)
+{
+	const struct omap_dma_reg *r = c->reg_map + reg;
+
+	omap_dma_write(val, r->type, c->channel_base + r->offset);
+}
+
+static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg)
+{
+	const struct omap_dma_reg *r = c->reg_map + reg;
+
+	return omap_dma_read(r->type, c->channel_base + r->offset);
+}
+
+static void omap_dma_clear_csr(struct omap_chan *c)
+{
+	if (dma_omap1())
+		omap_dma_chan_read(c, CSR);
+	else
+		omap_dma_chan_write(c, CSR, ~0);
+}
+
+static unsigned omap_dma_get_csr(struct omap_chan *c)
+{
+	unsigned val = omap_dma_chan_read(c, CSR);
+
+	if (!dma_omap1())
+		omap_dma_chan_write(c, CSR, val);
+
+	return val;
+}
+
+static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c,
+	unsigned lch)
+{
+	c->channel_base = od->base + od->plat->channel_stride * lch;
+
+	od->lch_map[lch] = c;
+}
+
+static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
+{
+	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+
+	if (__dma_omap15xx(od->plat->dma_attr))
+		omap_dma_chan_write(c, CPC, 0);
+	else
+		omap_dma_chan_write(c, CDAC, 0);
+
+	omap_dma_clear_csr(c);
+
+	/* Enable interrupts */
+	omap_dma_chan_write(c, CICR, d->cicr);
+
+	/* Enable channel */
+	omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE);
+}
+
+static void omap_dma_stop(struct omap_chan *c)
+{
+	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+	uint32_t val;
+
+	/* disable irq */
+	omap_dma_chan_write(c, CICR, 0);
+
+	omap_dma_clear_csr(c);
+
+	val = omap_dma_chan_read(c, CCR);
+	if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) {
+		uint32_t sysconfig;
+		unsigned i;
+
+		sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG);
+		val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+		omap_dma_glbl_write(od, OCP_SYSCONFIG, val);
+
+		val = omap_dma_chan_read(c, CCR);
+		val &= ~CCR_ENABLE;
+		omap_dma_chan_write(c, CCR, val);
+
+		/* Wait for sDMA FIFO to drain */
+		for (i = 0; ; i++) {
+			val = omap_dma_chan_read(c, CCR);
+			if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)))
+				break;
+
+			if (i > 100)
+				break;
+
+			udelay(5);
+		}
+
+		if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))
+			dev_err(c->vc.chan.device->dev,
+				"DMA drain did not complete on lch %d\n",
+			        c->dma_ch);
+
+		omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig);
+	} else {
+		val &= ~CCR_ENABLE;
+		omap_dma_chan_write(c, CCR, val);
+	}
+
+	mb();
+
+	if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) {
+		val = omap_dma_chan_read(c, CLNK_CTRL);
+
+		if (dma_omap1())
+			val |= 1 << 14; /* set the STOP_LNK bit */
+		else
+			val &= ~CLNK_CTRL_ENABLE_LNK;
+
+		omap_dma_chan_write(c, CLNK_CTRL, val);
+	}
+}
+
 static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
 	unsigned idx)
 {
 	struct omap_sg *sg = d->sg + idx;
+	unsigned cxsa, cxei, cxfi;
 
-	if (d->dir == DMA_DEV_TO_MEM)
-		omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF,
-			OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0);
-	else
-		omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF,
-			OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0);
+	if (d->dir == DMA_DEV_TO_MEM) {
+		cxsa = CDSA;
+		cxei = CDEI;
+		cxfi = CDFI;
+	} else {
+		cxsa = CSSA;
+		cxei = CSEI;
+		cxfi = CSFI;
+	}
 
-	omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn,
-		d->sync_mode, c->dma_sig, d->sync_type);
+	omap_dma_chan_write(c, cxsa, sg->addr);
+	omap_dma_chan_write(c, cxei, 0);
+	omap_dma_chan_write(c, cxfi, 0);
+	omap_dma_chan_write(c, CEN, sg->en);
+	omap_dma_chan_write(c, CFN, sg->fn);
 
-	omap_start_dma(c->dma_ch);
+	omap_dma_start(c, d);
 }
 
 static void omap_dma_start_desc(struct omap_chan *c)
 {
 	struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
 	struct omap_desc *d;
+	unsigned cxsa, cxei, cxfi;
 
 	if (!vd) {
 		c->desc = NULL;
@@ -126,12 +397,32 @@ static void omap_dma_start_desc(struct omap_chan *c)
 	c->desc = d = to_omap_dma_desc(&vd->tx);
 	c->sgidx = 0;
 
-	if (d->dir == DMA_DEV_TO_MEM)
-		omap_set_dma_src_params(c->dma_ch, d->periph_port,
-			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
-	else
-		omap_set_dma_dest_params(c->dma_ch, d->periph_port,
-			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
+	/*
+	 * This provides the necessary barrier to ensure data held in
+	 * DMA coherent memory is visible to the DMA engine prior to
+	 * the transfer starting.
+	 */
+	mb();
+
+	omap_dma_chan_write(c, CCR, d->ccr);
+	if (dma_omap1())
+		omap_dma_chan_write(c, CCR2, d->ccr >> 16);
+
+	if (d->dir == DMA_DEV_TO_MEM) {
+		cxsa = CSSA;
+		cxei = CSEI;
+		cxfi = CSFI;
+	} else {
+		cxsa = CDSA;
+		cxei = CDEI;
+		cxfi = CDFI;
+	}
+
+	omap_dma_chan_write(c, cxsa, d->dev_addr);
+	omap_dma_chan_write(c, cxei, 0);
+	omap_dma_chan_write(c, cxfi, d->fi);
+	omap_dma_chan_write(c, CSDP, d->csdp);
+	omap_dma_chan_write(c, CLNK_CTRL, d->clnk_ctrl);
 
 	omap_dma_start_sg(c, d, 0);
 }
@@ -186,24 +477,118 @@ static void omap_dma_sched(unsigned long data)
 	}
 }
 
+static irqreturn_t omap_dma_irq(int irq, void *devid)
+{
+	struct omap_dmadev *od = devid;
+	unsigned status, channel;
+
+	spin_lock(&od->irq_lock);
+
+	status = omap_dma_glbl_read(od, IRQSTATUS_L1);
+	status &= od->irq_enable_mask;
+	if (status == 0) {
+		spin_unlock(&od->irq_lock);
+		return IRQ_NONE;
+	}
+
+	while ((channel = ffs(status)) != 0) {
+		unsigned mask, csr;
+		struct omap_chan *c;
+
+		channel -= 1;
+		mask = BIT(channel);
+		status &= ~mask;
+
+		c = od->lch_map[channel];
+		if (c == NULL) {
+			/* This should never happen */
+			dev_err(od->ddev.dev, "invalid channel %u\n", channel);
+			continue;
+		}
+
+		csr = omap_dma_get_csr(c);
+		omap_dma_glbl_write(od, IRQSTATUS_L1, mask);
+
+		omap_dma_callback(channel, csr, c);
+	}
+
+	spin_unlock(&od->irq_lock);
+
+	return IRQ_HANDLED;
+}
+
 static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
+	int ret;
+
+	if (od->legacy) {
+		ret = omap_request_dma(c->dma_sig, "DMA engine",
+				       omap_dma_callback, c, &c->dma_ch);
+	} else {
+		ret = omap_request_dma(c->dma_sig, "DMA engine", NULL, NULL,
+				       &c->dma_ch);
+	}
+
+	dev_dbg(od->ddev.dev, "allocating channel %u for %u\n",
+		c->dma_ch, c->dma_sig);
 
-	dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig);
+	if (ret >= 0) {
+		omap_dma_assign(od, c, c->dma_ch);
 
-	return omap_request_dma(c->dma_sig, "DMA engine",
-		omap_dma_callback, c, &c->dma_ch);
+		if (!od->legacy) {
+			unsigned val;
+
+			spin_lock_irq(&od->irq_lock);
+			val = BIT(c->dma_ch);
+			omap_dma_glbl_write(od, IRQSTATUS_L1, val);
+			od->irq_enable_mask |= val;
+			omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask);
+
+			val = omap_dma_glbl_read(od, IRQENABLE_L0);
+			val &= ~BIT(c->dma_ch);
+			omap_dma_glbl_write(od, IRQENABLE_L0, val);
+			spin_unlock_irq(&od->irq_lock);
+		}
+	}
+
+	if (dma_omap1()) {
+		if (__dma_omap16xx(od->plat->dma_attr)) {
+			c->ccr = CCR_OMAP31_DISABLE;
+			/* Duplicate what plat-omap/dma.c does */
+			c->ccr |= c->dma_ch + 1;
+		} else {
+			c->ccr = c->dma_sig & 0x1f;
+		}
+	} else {
+		c->ccr = c->dma_sig & 0x1f;
+		c->ccr |= (c->dma_sig & ~0x1f) << 14;
+	}
+	if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
+		c->ccr |= CCR_BUFFERING_DISABLE;
+
+	return ret;
 }
 
 static void omap_dma_free_chan_resources(struct dma_chan *chan)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
 
+	if (!od->legacy) {
+		spin_lock_irq(&od->irq_lock);
+		od->irq_enable_mask &= ~BIT(c->dma_ch);
+		omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask);
+		spin_unlock_irq(&od->irq_lock);
+	}
+
+	c->channel_base = NULL;
+	od->lch_map[c->dma_ch] = NULL;
 	vchan_free_chan_resources(&c->vc);
 	omap_free_dma(c->dma_ch);
 
-	dev_dbg(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig);
+	dev_dbg(od->ddev.dev, "freeing channel for %u\n", c->dma_sig);
 }
 
 static size_t omap_dma_sg_size(struct omap_sg *sg)
@@ -239,6 +624,74 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)
 	return size;
 }
 
+/*
+ * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+static uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg)
+{
+	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+	uint32_t val;
+
+	val = omap_dma_chan_read(c, reg);
+	if (val == 0 && od->plat->errata & DMA_ERRATA_3_3)
+		val = omap_dma_chan_read(c, reg);
+
+	return val;
+}
+
+static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)
+{
+	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+	dma_addr_t addr, cdac;
+
+	if (__dma_omap15xx(od->plat->dma_attr)) {
+		addr = omap_dma_chan_read(c, CPC);
+	} else {
+		addr = omap_dma_chan_read_3_3(c, CSAC);
+		cdac = omap_dma_chan_read_3_3(c, CDAC);
+
+		/*
+		 * CDAC == 0 indicates that the DMA transfer on the channel has
+		 * not been started (no data has been transferred so far).
+		 * Return the programmed source start address in this case.
+		 */
+		if (cdac == 0)
+			addr = omap_dma_chan_read(c, CSSA);
+	}
+
+	if (dma_omap1())
+		addr |= omap_dma_chan_read(c, CSSA) & 0xffff0000;
+
+	return addr;
+}
+
+static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)
+{
+	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+	dma_addr_t addr;
+
+	if (__dma_omap15xx(od->plat->dma_attr)) {
+		addr = omap_dma_chan_read(c, CPC);
+	} else {
+		addr = omap_dma_chan_read_3_3(c, CDAC);
+
+		/*
+		 * CDAC == 0 indicates that the DMA transfer on the channel
+		 * has not been started (no data has been transferred so
+		 * far).  Return the programmed destination start address in
+		 * this case.
+		 */
+		if (addr == 0)
+			addr = omap_dma_chan_read(c, CDSA);
+	}
+
+	if (dma_omap1())
+		addr |= omap_dma_chan_read(c, CDSA) & 0xffff0000;
+
+	return addr;
+}
+
 static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
 	dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
@@ -260,9 +713,9 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
 		dma_addr_t pos;
 
 		if (d->dir == DMA_MEM_TO_DEV)
-			pos = omap_get_dma_src_pos(c->dma_ch);
+			pos = omap_dma_get_src_pos(c);
 		else if (d->dir == DMA_DEV_TO_MEM)
-			pos = omap_get_dma_dst_pos(c->dma_ch);
+			pos = omap_dma_get_dst_pos(c);
 		else
 			pos = 0;
 
@@ -304,24 +757,23 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen,
 	enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
 	enum dma_slave_buswidth dev_width;
 	struct scatterlist *sgent;
 	struct omap_desc *d;
 	dma_addr_t dev_addr;
-	unsigned i, j = 0, es, en, frame_bytes, sync_type;
+	unsigned i, j = 0, es, en, frame_bytes;
 	u32 burst;
 
 	if (dir == DMA_DEV_TO_MEM) {
 		dev_addr = c->cfg.src_addr;
 		dev_width = c->cfg.src_addr_width;
 		burst = c->cfg.src_maxburst;
-		sync_type = OMAP_DMA_SRC_SYNC;
 	} else if (dir == DMA_MEM_TO_DEV) {
 		dev_addr = c->cfg.dst_addr;
 		dev_width = c->cfg.dst_addr_width;
 		burst = c->cfg.dst_maxburst;
-		sync_type = OMAP_DMA_DST_SYNC;
 	} else {
 		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
 		return NULL;
@@ -330,13 +782,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	/* Bus width translates to the element size (ES) */
 	switch (dev_width) {
 	case DMA_SLAVE_BUSWIDTH_1_BYTE:
-		es = OMAP_DMA_DATA_TYPE_S8;
+		es = CSDP_DATA_TYPE_8;
 		break;
 	case DMA_SLAVE_BUSWIDTH_2_BYTES:
-		es = OMAP_DMA_DATA_TYPE_S16;
+		es = CSDP_DATA_TYPE_16;
 		break;
 	case DMA_SLAVE_BUSWIDTH_4_BYTES:
-		es = OMAP_DMA_DATA_TYPE_S32;
+		es = CSDP_DATA_TYPE_32;
 		break;
 	default: /* not reached */
 		return NULL;
@@ -350,9 +802,31 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	d->dir = dir;
 	d->dev_addr = dev_addr;
 	d->es = es;
-	d->sync_mode = OMAP_DMA_SYNC_FRAME;
-	d->sync_type = sync_type;
-	d->periph_port = OMAP_DMA_PORT_TIPB;
+
+	d->ccr = c->ccr | CCR_SYNC_FRAME;
+	if (dir == DMA_DEV_TO_MEM)
+		d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
+	else
+		d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
+
+	d->cicr = CICR_DROP_IE | CICR_BLOCK_IE;
+	d->csdp = es;
+
+	if (dma_omap1()) {
+		d->cicr |= CICR_TOUT_IE;
+
+		if (dir == DMA_DEV_TO_MEM)
+			d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_TIPB;
+		else
+			d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF;
+	} else {
+		if (dir == DMA_DEV_TO_MEM)
+			d->ccr |= CCR_TRIGGER_SRC;
+
+		d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
+	}
+	if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
+		d->clnk_ctrl = c->dma_ch;
 
 	/*
 	 * Build our scatterlist entries: each contains the address,
@@ -382,23 +856,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	size_t period_len, enum dma_transfer_direction dir, unsigned long flags,
 	void *context)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
 	enum dma_slave_buswidth dev_width;
 	struct omap_desc *d;
 	dma_addr_t dev_addr;
-	unsigned es, sync_type;
+	unsigned es;
 	u32 burst;
 
 	if (dir == DMA_DEV_TO_MEM) {
 		dev_addr = c->cfg.src_addr;
 		dev_width = c->cfg.src_addr_width;
 		burst = c->cfg.src_maxburst;
-		sync_type = OMAP_DMA_SRC_SYNC;
 	} else if (dir == DMA_MEM_TO_DEV) {
 		dev_addr = c->cfg.dst_addr;
 		dev_width = c->cfg.dst_addr_width;
 		burst = c->cfg.dst_maxburst;
-		sync_type = OMAP_DMA_DST_SYNC;
 	} else {
 		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
 		return NULL;
@@ -407,13 +880,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	/* Bus width translates to the element size (ES) */
 	switch (dev_width) {
 	case DMA_SLAVE_BUSWIDTH_1_BYTE:
-		es = OMAP_DMA_DATA_TYPE_S8;
+		es = CSDP_DATA_TYPE_8;
 		break;
 	case DMA_SLAVE_BUSWIDTH_2_BYTES:
-		es = OMAP_DMA_DATA_TYPE_S16;
+		es = CSDP_DATA_TYPE_16;
 		break;
 	case DMA_SLAVE_BUSWIDTH_4_BYTES:
-		es = OMAP_DMA_DATA_TYPE_S32;
+		es = CSDP_DATA_TYPE_32;
 		break;
 	default: /* not reached */
 		return NULL;
@@ -428,32 +901,51 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	d->dev_addr = dev_addr;
 	d->fi = burst;
 	d->es = es;
-	if (burst)
-		d->sync_mode = OMAP_DMA_SYNC_PACKET;
-	else
-		d->sync_mode = OMAP_DMA_SYNC_ELEMENT;
-	d->sync_type = sync_type;
-	d->periph_port = OMAP_DMA_PORT_MPUI;
 	d->sg[0].addr = buf_addr;
 	d->sg[0].en = period_len / es_bytes[es];
 	d->sg[0].fn = buf_len / period_len;
 	d->sglen = 1;
 
-	if (!c->cyclic) {
-		c->cyclic = true;
-		omap_dma_link_lch(c->dma_ch, c->dma_ch);
+	d->ccr = c->ccr;
+	if (dir == DMA_DEV_TO_MEM)
+		d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
+	else
+		d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
 
-		if (flags & DMA_PREP_INTERRUPT)
-			omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ);
+	d->cicr = CICR_DROP_IE;
+	if (flags & DMA_PREP_INTERRUPT)
+		d->cicr |= CICR_FRAME_IE;
 
-		omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
-	}
+	d->csdp = es;
+
+	if (dma_omap1()) {
+		d->cicr |= CICR_TOUT_IE;
+
+		if (dir == DMA_DEV_TO_MEM)
+			d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_MPUI;
+		else
+			d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF;
+	} else {
+		if (burst)
+			d->ccr |= CCR_SYNC_PACKET;
+		else
+			d->ccr |= CCR_SYNC_ELEMENT;
+
+		if (dir == DMA_DEV_TO_MEM)
+			d->ccr |= CCR_TRIGGER_SRC;
+
+		d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
 
-	if (dma_omap2plus()) {
-		omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
-		omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
+		d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64;
 	}
 
+	if (__dma_omap15xx(od->plat->dma_attr))
+		d->ccr |= CCR_AUTO_INIT | CCR_REPEAT;
+	else
+		d->clnk_ctrl = c->dma_ch | CLNK_CTRL_ENABLE_LNK;
+
+	c->cyclic = true;
+
 	return vchan_tx_prep(&c->vc, &d->vd, flags);
 }
 
@@ -483,20 +975,19 @@ static int omap_dma_terminate_all(struct omap_chan *c)
 
 	/*
 	 * Stop DMA activity: we assume the callback will not be called
-	 * after omap_stop_dma() returns (even if it does, it will see
+	 * after omap_dma_stop() returns (even if it does, it will see
 	 * c->desc is NULL and exit.)
 	 */
 	if (c->desc) {
 		c->desc = NULL;
 		/* Avoid stopping the dma twice */
 		if (!c->paused)
-			omap_stop_dma(c->dma_ch);
+			omap_dma_stop(c);
 	}
 
 	if (c->cyclic) {
 		c->cyclic = false;
 		c->paused = false;
-		omap_dma_unlink_lch(c->dma_ch, c->dma_ch);
 	}
 
 	vchan_get_all_descriptors(&c->vc, &head);
@@ -513,7 +1004,7 @@ static int omap_dma_pause(struct omap_chan *c)
 		return -EINVAL;
 
 	if (!c->paused) {
-		omap_stop_dma(c->dma_ch);
+		omap_dma_stop(c);
 		c->paused = true;
 	}
 
@@ -527,7 +1018,7 @@ static int omap_dma_resume(struct omap_chan *c)
 		return -EINVAL;
 
 	if (c->paused) {
-		omap_start_dma(c->dma_ch);
+		omap_dma_start(c, c->desc);
 		c->paused = false;
 	}
 
@@ -573,6 +1064,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig)
 	if (!c)
 		return -ENOMEM;
 
+	c->reg_map = od->reg_map;
 	c->dma_sig = dma_sig;
 	c->vc.desc_free = omap_dma_desc_free;
 	vchan_init(&c->vc, &od->ddev);
@@ -594,18 +1086,29 @@ static void omap_dma_free(struct omap_dmadev *od)
 		tasklet_kill(&c->vc.task);
 		kfree(c);
 	}
-	kfree(od);
 }
 
 static int omap_dma_probe(struct platform_device *pdev)
 {
 	struct omap_dmadev *od;
-	int rc, i;
+	struct resource *res;
+	int rc, i, irq;
 
-	od = kzalloc(sizeof(*od), GFP_KERNEL);
+	od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
 	if (!od)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	od->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(od->base))
+		return PTR_ERR(od->base);
+
+	od->plat = omap_get_plat_info();
+	if (!od->plat)
+		return -EPROBE_DEFER;
+
+	od->reg_map = od->plat->reg_map;
+
 	dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
 	dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
 	od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources;
@@ -619,6 +1122,7 @@ static int omap_dma_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&od->ddev.channels);
 	INIT_LIST_HEAD(&od->pending);
 	spin_lock_init(&od->lock);
+	spin_lock_init(&od->irq_lock);
 
 	tasklet_init(&od->task, omap_dma_sched, (unsigned long)od);
 
@@ -630,6 +1134,21 @@ static int omap_dma_probe(struct platform_device *pdev)
 		}
 	}
 
+	irq = platform_get_irq(pdev, 1);
+	if (irq <= 0) {
+		dev_info(&pdev->dev, "failed to get L1 IRQ: %d\n", irq);
+		od->legacy = true;
+	} else {
+		/* Disable all interrupts */
+		od->irq_enable_mask = 0;
+		omap_dma_glbl_write(od, IRQENABLE_L1, 0);
+
+		rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
+				      IRQF_SHARED, "omap-dma-engine", od);
+		if (rc)
+			return rc;
+	}
+
 	rc = dma_async_device_register(&od->ddev);
 	if (rc) {
 		pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n",
@@ -666,6 +1185,12 @@ static int omap_dma_remove(struct platform_device *pdev)
 		of_dma_controller_free(pdev->dev.of_node);
 
 	dma_async_device_unregister(&od->ddev);
+
+	if (!od->legacy) {
+		/* Disable all interrupts */
+		omap_dma_glbl_write(od, IRQENABLE_L0, 0);
+	}
+
 	omap_dma_free(od);
 
 	return 0;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 98e14ee4833c..f8bf00010d45 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1239,9 +1239,17 @@ static u8 f15_m30h_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
 	if (num_dcts_intlv == 2) {
 		select = (sys_addr >> 8) & 0x3;
 		channel = select ? 0x3 : 0;
-	} else if (num_dcts_intlv == 4)
-		channel = (sys_addr >> 8) & 0x7;
-
+	} else if (num_dcts_intlv == 4) {
+		u8 intlv_addr = dct_sel_interleave_addr(pvt);
+		switch (intlv_addr) {
+		case 0x4:
+			channel = (sys_addr >> 8) & 0x3;
+			break;
+		case 0x5:
+			channel = (sys_addr >> 9) & 0x3;
+			break;
+		}
+	}
 	return channel;
 }
 
@@ -1799,6 +1807,17 @@ static struct amd64_family_type family_types[] = {
 			.read_dct_pci_cfg	= f10_read_dct_pci_cfg,
 		}
 	},
+	[F16_M30H_CPUS] = {
+		.ctl_name = "F16h_M30h",
+		.f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1,
+		.f3_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F3,
+		.ops = {
+			.early_channel_count	= f1x_early_channel_count,
+			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
+			.dbam_to_cs		= f16_dbam_to_chip_select,
+			.read_dct_pci_cfg	= f10_read_dct_pci_cfg,
+		}
+	},
 };
 
 /*
@@ -2578,6 +2597,11 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
 		break;
 
 	case 0x16:
+		if (pvt->model == 0x30) {
+			fam_type = &family_types[F16_M30H_CPUS];
+			pvt->ops = &family_types[F16_M30H_CPUS].ops;
+			break;
+		}
 		fam_type	= &family_types[F16_CPUS];
 		pvt->ops	= &family_types[F16_CPUS].ops;
 		break;
@@ -2830,6 +2854,14 @@ static const struct pci_device_id amd64_pci_table[] = {
 		.class		= 0,
 		.class_mask	= 0,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+	},
 
 	{0, }
 };
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 6dc1fcc25afb..d903e0c21144 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -168,6 +168,8 @@
 #define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
 #define PCI_DEVICE_ID_AMD_16H_NB_F1	0x1531
 #define PCI_DEVICE_ID_AMD_16H_NB_F2	0x1532
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F2 0x1582
 
 /*
  * Function 1 - Address Map
@@ -300,6 +302,7 @@ enum amd_families {
 	F15_CPUS,
 	F15_M30H_CPUS,
 	F16_CPUS,
+	F16_M30H_CPUS,
 	NUM_FAMILIES,
 };
 
diff --git a/drivers/edac/amd8111_edac.c b/drivers/edac/amd8111_edac.c
index ddd890052ce2..2b63f7c2d6d2 100644
--- a/drivers/edac/amd8111_edac.c
+++ b/drivers/edac/amd8111_edac.c
@@ -350,6 +350,7 @@ static int amd8111_dev_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	struct amd8111_dev_info *dev_info = &amd8111_devices[id->driver_data];
+	int ret = -ENODEV;
 
 	dev_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
 					dev_info->err_dev, NULL);
@@ -359,16 +360,15 @@ static int amd8111_dev_probe(struct pci_dev *dev,
 			"vendor %x, device %x, name %s\n",
 			PCI_VENDOR_ID_AMD, dev_info->err_dev,
 			dev_info->ctl_name);
-		return -ENODEV;
+		goto err;
 	}
 
 	if (pci_enable_device(dev_info->dev)) {
-		pci_dev_put(dev_info->dev);
 		printk(KERN_ERR "failed to enable:"
 			"vendor %x, device %x, name %s\n",
 			PCI_VENDOR_ID_AMD, dev_info->err_dev,
 			dev_info->ctl_name);
-		return -ENODEV;
+		goto err_dev_put;
 	}
 
 	/*
@@ -381,8 +381,10 @@ static int amd8111_dev_probe(struct pci_dev *dev,
 		edac_device_alloc_ctl_info(0, dev_info->ctl_name, 1,
 					   NULL, 0, 0,
 					   NULL, 0, dev_info->edac_idx);
-	if (!dev_info->edac_dev)
-		return -ENOMEM;
+	if (!dev_info->edac_dev) {
+		ret = -ENOMEM;
+		goto err_dev_put;
+	}
 
 	dev_info->edac_dev->pvt_info = dev_info;
 	dev_info->edac_dev->dev = &dev_info->dev->dev;
@@ -399,8 +401,7 @@ static int amd8111_dev_probe(struct pci_dev *dev,
 	if (edac_device_add_device(dev_info->edac_dev) > 0) {
 		printk(KERN_ERR "failed to add edac_dev for %s\n",
 			dev_info->ctl_name);
-		edac_device_free_ctl_info(dev_info->edac_dev);
-		return -ENODEV;
+		goto err_edac_free_ctl;
 	}
 
 	printk(KERN_INFO "added one edac_dev on AMD8111 "
@@ -409,6 +410,13 @@ static int amd8111_dev_probe(struct pci_dev *dev,
 		dev_info->ctl_name);
 
 	return 0;
+
+err_edac_free_ctl:
+	edac_device_free_ctl_info(dev_info->edac_dev);
+err_dev_put:
+	pci_dev_put(dev_info->dev);
+err:
+	return ret;
 }
 
 static void amd8111_dev_remove(struct pci_dev *dev)
@@ -437,6 +445,7 @@ static int amd8111_pci_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	struct amd8111_pci_info *pci_info = &amd8111_pcis[id->driver_data];
+	int ret = -ENODEV;
 
 	pci_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
 					pci_info->err_dev, NULL);
@@ -446,16 +455,15 @@ static int amd8111_pci_probe(struct pci_dev *dev,
 			"vendor %x, device %x, name %s\n",
 			PCI_VENDOR_ID_AMD, pci_info->err_dev,
 			pci_info->ctl_name);
-		return -ENODEV;
+		goto err;
 	}
 
 	if (pci_enable_device(pci_info->dev)) {
-		pci_dev_put(pci_info->dev);
 		printk(KERN_ERR "failed to enable:"
 			"vendor %x, device %x, name %s\n",
 			PCI_VENDOR_ID_AMD, pci_info->err_dev,
 			pci_info->ctl_name);
-		return -ENODEV;
+		goto err_dev_put;
 	}
 
 	/*
@@ -465,8 +473,10 @@ static int amd8111_pci_probe(struct pci_dev *dev,
 	*/
 	pci_info->edac_idx = edac_pci_alloc_index();
 	pci_info->edac_dev = edac_pci_alloc_ctl_info(0, pci_info->ctl_name);
-	if (!pci_info->edac_dev)
-		return -ENOMEM;
+	if (!pci_info->edac_dev) {
+		ret = -ENOMEM;
+		goto err_dev_put;
+	}
 
 	pci_info->edac_dev->pvt_info = pci_info;
 	pci_info->edac_dev->dev = &pci_info->dev->dev;
@@ -483,8 +493,7 @@ static int amd8111_pci_probe(struct pci_dev *dev,
 	if (edac_pci_add_device(pci_info->edac_dev, pci_info->edac_idx) > 0) {
 		printk(KERN_ERR "failed to add edac_pci for %s\n",
 			pci_info->ctl_name);
-		edac_pci_free_ctl_info(pci_info->edac_dev);
-		return -ENODEV;
+		goto err_edac_free_ctl;
 	}
 
 	printk(KERN_INFO "added one edac_pci on AMD8111 "
@@ -493,6 +502,13 @@ static int amd8111_pci_probe(struct pci_dev *dev,
 		pci_info->ctl_name);
 
 	return 0;
+
+err_edac_free_ctl:
+	edac_pci_free_ctl_info(pci_info->edac_dev);
+err_dev_put:
+	pci_dev_put(pci_info->dev);
+err:
+	return ret;
 }
 
 static void amd8111_pci_remove(struct pci_dev *dev)
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 92d54fa65f93..b2d71388172b 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -209,7 +209,6 @@ enum e752x_chips {
  */
 
 struct e752x_pvt {
-	struct pci_dev *bridge_ck;
 	struct pci_dev *dev_d0f0;
 	struct pci_dev *dev_d0f1;
 	u32 tolm;
@@ -891,7 +890,7 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
 					info->buf_ferr);
 
 		if (info->dram_ferr)
-			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
+			pci_write_bits16(pvt->dev_d0f1, E752X_DRAM_FERR,
 					 info->dram_ferr, info->dram_ferr);
 
 		pci_write_config_dword(dev, E752X_FERR_GLOBAL,
@@ -936,7 +935,7 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
 					info->buf_nerr);
 
 		if (info->dram_nerr)
-			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
+			pci_write_bits16(pvt->dev_d0f1, E752X_DRAM_NERR,
 					 info->dram_nerr, info->dram_nerr);
 
 		pci_write_config_dword(dev, E752X_NERR_GLOBAL,
@@ -1177,38 +1176,33 @@ static void e752x_init_mem_map_table(struct pci_dev *pdev,
 static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
 			struct e752x_pvt *pvt)
 {
-	struct pci_dev *dev;
-
-	pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
-				pvt->dev_info->err_dev, pvt->bridge_ck);
+	pvt->dev_d0f1 = pci_get_device(PCI_VENDOR_ID_INTEL,
+				pvt->dev_info->err_dev, NULL);
 
-	if (pvt->bridge_ck == NULL) {
-		pvt->bridge_ck = pci_scan_single_device(pdev->bus,
+	if (pvt->dev_d0f1 == NULL) {
+		pvt->dev_d0f1 = pci_scan_single_device(pdev->bus,
 							PCI_DEVFN(0, 1));
-		pci_dev_get(pvt->bridge_ck);
+		pci_dev_get(pvt->dev_d0f1);
 	}
 
-	if (pvt->bridge_ck == NULL) {
+	if (pvt->dev_d0f1 == NULL) {
 		e752x_printk(KERN_ERR, "error reporting device not found:"
 			"vendor %x device 0x%x (broken BIOS?)\n",
 			PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
 		return 1;
 	}
 
-	dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+	pvt->dev_d0f0 = pci_get_device(PCI_VENDOR_ID_INTEL,
 				e752x_devs[dev_idx].ctl_dev,
 				NULL);
 
-	if (dev == NULL)
+	if (pvt->dev_d0f0 == NULL)
 		goto fail;
 
-	pvt->dev_d0f0 = dev;
-	pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
-
 	return 0;
 
 fail:
-	pci_dev_put(pvt->bridge_ck);
+	pci_dev_put(pvt->dev_d0f1);
 	return 1;
 }
 
@@ -1385,7 +1379,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
 fail:
 	pci_dev_put(pvt->dev_d0f0);
 	pci_dev_put(pvt->dev_d0f1);
-	pci_dev_put(pvt->bridge_ck);
 	edac_mc_free(mci);
 
 	return -ENODEV;
@@ -1419,7 +1412,6 @@ static void e752x_remove_one(struct pci_dev *pdev)
 	pvt = (struct e752x_pvt *)mci->pvt_info;
 	pci_dev_put(pvt->dev_d0f0);
 	pci_dev_put(pvt->dev_d0f1);
-	pci_dev_put(pvt->bridge_ck);
 	edac_mc_free(mci);
 }
 
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c
index fa1326e5a4b0..022a70273ada 100644
--- a/drivers/edac/i3200_edac.c
+++ b/drivers/edac/i3200_edac.c
@@ -464,6 +464,8 @@ static void i3200_remove_one(struct pci_dev *pdev)
 	iounmap(priv->window);
 
 	edac_mc_free(mci);
+
+	pci_disable_device(pdev);
 }
 
 static const struct pci_device_id i3200_pci_tbl[] = {
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index 36a38ee94fa8..6247d186177e 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -869,16 +869,13 @@ static void i5100_init_csrows(struct mem_ctl_info *mci)
 			       chan, rank, 0);
 
 		dimm->nr_pages = npages;
-		if (npages) {
-			dimm->grain = 32;
-			dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
-					DEV_X4 : DEV_X8;
-			dimm->mtype = MEM_RDDR2;
-			dimm->edac_mode = EDAC_SECDED;
-			snprintf(dimm->label, sizeof(dimm->label),
-				"DIMM%u",
-				i5100_rank_to_slot(mci, chan, rank));
-		}
+		dimm->grain = 32;
+		dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
+				DEV_X4 : DEV_X8;
+		dimm->mtype = MEM_RDDR2;
+		dimm->edac_mode = EDAC_SECDED;
+		snprintf(dimm->label, sizeof(dimm->label), "DIMM%u",
+			 i5100_rank_to_slot(mci, chan, rank));
 
 		edac_dbg(2, "dimm channel %d, rank %d, size %ld\n",
 			 chan, rank, (long)PAGES_TO_MiB(npages));
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index e080cbfa8fc9..5381e98d9c0c 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -1408,6 +1408,8 @@ static void i5400_remove_one(struct pci_dev *pdev)
 	/* retrieve references to resources, and free those resources */
 	i5400_put_devices(mci);
 
+	pci_disable_device(pdev);
+
 	edac_mc_free(mci);
 }
 
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index d871275196f6..8bc83b99974b 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1708,7 +1708,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
 				    const struct mce *m)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
-	char *type, *optype, *err;
+	char *optype, *err;
 	enum hw_event_mc_err_type tp_event;
 	unsigned long error = m->status & 0x1ff0000l;
 	bool uncorrected_error = m->mcgstatus & 1ll << 61;
@@ -1721,15 +1721,11 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
 	u32 errnum = find_first_bit(&error, 32);
 
 	if (uncorrected_error) {
-		if (ripv) {
-			type = "FATAL";
+		if (ripv)
 			tp_event = HW_EVENT_ERR_FATAL;
-		} else {
-			type = "NON_FATAL";
+		else
 			tp_event = HW_EVENT_ERR_UNCORRECTED;
-		}
 	} else {
-		type = "CORRECTED";
 		tp_event = HW_EVENT_ERR_CORRECTED;
 	}
 
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index 80573df0a4d7..8d0450b9b9af 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -406,8 +406,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
 
 	edac_dbg(0, "\n");
 
-	ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
-
 	if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window))
 		return -ENODEV;
 	drc = readl(ovrfl_window + I82875P_DRC);
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 30f7309446a6..51b9caa0b024 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -741,6 +741,36 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
 
+	pr_emerg(HW_ERR "%s\n", decode_error_status(m));
+
+	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
+		m->extcpu,
+		c->x86, c->x86_model, c->x86_mask,
+		m->bank,
+		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
+		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
+		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
+		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
+		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
+
+	if (c->x86 == 0x15 || c->x86 == 0x16)
+		pr_cont("|%s|%s",
+			((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
+			((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
+
+	/* do the two bits[14:13] together */
+	ecc = (m->status >> 45) & 0x3;
+	if (ecc)
+		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
+
+	pr_cont("]: 0x%016llx\n", m->status);
+
+	if (m->status & MCI_STATUS_ADDRV)
+		pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
+
+	if (!fam_ops)
+		goto err_code;
+
 	switch (m->bank) {
 	case 0:
 		decode_mc0_mce(m);
@@ -774,33 +804,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 		break;
 	}
 
-	pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
-
-	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
-		m->extcpu,
-		c->x86, c->x86_model, c->x86_mask,
-		m->bank,
-		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
-		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
-		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
-		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
-		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
-
-	if (c->x86 == 0x15 || c->x86 == 0x16)
-		pr_cont("|%s|%s",
-			((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
-			((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
-
-	/* do the two bits[14:13] together */
-	ecc = (m->status >> 45) & 0x3;
-	if (ecc)
-		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
-
-	pr_cont("]: 0x%016llx\n", m->status);
-
-	if (m->status & MCI_STATUS_ADDRV)
-		pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
-
+ err_code:
 	amd_decode_err_code(m->status & 0xffff);
 
 	return NOTIFY_STOP;
@@ -816,10 +820,7 @@ static int __init mce_amd_init(void)
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
 	if (c->x86_vendor != X86_VENDOR_AMD)
-		return 0;
-
-	if (c->x86 < 0xf || c->x86 > 0x16)
-		return 0;
+		return -ENODEV;
 
 	fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
 	if (!fam_ops)
@@ -874,7 +875,7 @@ static int __init mce_amd_init(void)
 	default:
 		printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
 		kfree(fam_ops);
-		return -EINVAL;
+		fam_ops = NULL;
 	}
 
 	pr_info("MCE: In-kernel MCE decoding enabled.\n");
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 8f9182179a7c..f4aec2e6ef56 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -357,7 +357,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
 		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
 		res = devm_request_irq(&op->dev, pdata->irq,
 				       mpc85xx_pci_isr,
-				       IRQF_DISABLED | IRQF_SHARED,
+				       IRQF_SHARED,
 				       "[EDAC] PCI err", pci);
 		if (res < 0) {
 			printk(KERN_ERR
@@ -633,7 +633,7 @@ static int mpc85xx_l2_err_probe(struct platform_device *op)
 	if (edac_op_state == EDAC_OPSTATE_INT) {
 		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
 		res = devm_request_irq(&op->dev, pdata->irq,
-				       mpc85xx_l2_isr, IRQF_DISABLED,
+				       mpc85xx_l2_isr, 0,
 				       "[EDAC] L2 err", edac_dev);
 		if (res < 0) {
 			printk(KERN_ERR
@@ -1133,7 +1133,7 @@ static int mpc85xx_mc_err_probe(struct platform_device *op)
 		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
 		res = devm_request_irq(&op->dev, pdata->irq,
 				       mpc85xx_mc_isr,
-					IRQF_DISABLED | IRQF_SHARED,
+				       IRQF_SHARED,
 				       "[EDAC] MC err", mci);
 		if (res < 0) {
 			printk(KERN_ERR "%s: Unable to request irq %d for "
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 54e2abe671f7..347c7a1c2725 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -1263,7 +1263,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 	struct pci_dev *pdev = NULL;
 	u8 bus = 0;
 
-	sbridge_printk(KERN_INFO,
+	sbridge_printk(KERN_DEBUG,
 		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
 		dev_descr->dev, dev_descr->func,
 		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 6b895986dc22..4af0a7bad7f2 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -929,8 +929,6 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
 	if (rcode == RCODE_COMPLETE) {
 		fwnet_transmit_packet_done(ptask);
 	} else {
-		fwnet_transmit_packet_failed(ptask);
-
 		if (printk_timed_ratelimit(&j,  1000) || rcode != last_rcode) {
 			dev_err(&ptask->dev->netdev->dev,
 				"fwnet_write_complete failed: %x (skipped %d)\n",
@@ -938,8 +936,10 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
 
 			errors_skipped = 0;
 			last_rcode = rcode;
-		} else
+		} else {
 			errors_skipped++;
+		}
+		fwnet_transmit_packet_failed(ptask);
 	}
 }
 
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 1b5e8e46226d..7160c43c59fc 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -584,7 +584,7 @@ static struct platform_driver dcdbas_driver = {
 	.remove		= dcdbas_remove,
 };
 
-static const struct platform_device_info dcdbas_dev_info __initdata = {
+static const struct platform_device_info dcdbas_dev_info __initconst = {
 	.name		= DRIVER_NAME,
 	.id		= -1,
 	.dma_mask	= DMA_BIT_MASK(32),
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index e5a67b24587a..f1ab05ea56bb 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -892,13 +892,6 @@ static __init int gsmi_init(void)
 		goto out_remove_sysfs_files;
 	}
 
-	ret = efivars_sysfs_init();
-	if (ret) {
-		printk(KERN_INFO "gsmi: Failed to create efivars files\n");
-		efivars_unregister(&efivars);
-		goto out_remove_sysfs_files;
-	}
-
 	register_reboot_notifier(&gsmi_reboot_notifier);
 	register_die_notifier(&gsmi_die_notifier);
 	atomic_notifier_chain_register(&panic_notifier_list,
diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c
index 2a90ba613613..2f569aaed4c7 100644
--- a/drivers/firmware/google/memconsole.c
+++ b/drivers/firmware/google/memconsole.c
@@ -15,6 +15,7 @@
 #include <linux/kobject.h>
 #include <linux/module.h>
 #include <linux/dmi.h>
+#include <linux/io.h>
 #include <asm/bios_ebda.h>
 
 #define BIOS_MEMCONSOLE_V1_MAGIC	0xDEADBABE
@@ -41,15 +42,25 @@ struct biosmemcon_ebda {
 	};
 } __packed;
 
-static char *memconsole_baseaddr;
+static u32 memconsole_baseaddr;
 static size_t memconsole_length;
 
 static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
 			       struct bin_attribute *bin_attr, char *buf,
 			       loff_t pos, size_t count)
 {
-	return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
-				       memconsole_length);
+	char *memconsole;
+	ssize_t ret;
+
+	memconsole = ioremap_cache(memconsole_baseaddr, memconsole_length);
+	if (!memconsole) {
+		pr_err("memconsole: ioremap_cache failed\n");
+		return -ENOMEM;
+	}
+	ret = memory_read_from_buffer(buf, count, &pos, memconsole,
+				      memconsole_length);
+	iounmap(memconsole);
+	return ret;
 }
 
 static struct bin_attribute memconsole_bin_attr = {
@@ -58,43 +69,42 @@ static struct bin_attribute memconsole_bin_attr = {
 };
 
 
-static void found_v1_header(struct biosmemcon_ebda *hdr)
+static void __init found_v1_header(struct biosmemcon_ebda *hdr)
 {
-	printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr);
-	printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
+	pr_info("BIOS console v1 EBDA structure found at %p\n", hdr);
+	pr_info("BIOS console buffer at 0x%.8x, "
 	       "start = %d, end = %d, num = %d\n",
 	       hdr->v1.buffer_addr, hdr->v1.start,
 	       hdr->v1.end, hdr->v1.num_chars);
 
 	memconsole_length = hdr->v1.num_chars;
-	memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
+	memconsole_baseaddr = hdr->v1.buffer_addr;
 }
 
-static void found_v2_header(struct biosmemcon_ebda *hdr)
+static void __init found_v2_header(struct biosmemcon_ebda *hdr)
 {
-	printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr);
-	printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
+	pr_info("BIOS console v2 EBDA structure found at %p\n", hdr);
+	pr_info("BIOS console buffer at 0x%.8x, "
 	       "start = %d, end = %d, num_bytes = %d\n",
 	       hdr->v2.buffer_addr, hdr->v2.start,
 	       hdr->v2.end, hdr->v2.num_bytes);
 
 	memconsole_length = hdr->v2.end - hdr->v2.start;
-	memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr
-					   + hdr->v2.start);
+	memconsole_baseaddr = hdr->v2.buffer_addr + hdr->v2.start;
 }
 
 /*
  * Search through the EBDA for the BIOS Memory Console, and
  * set the global variables to point to it.  Return true if found.
  */
-static bool found_memconsole(void)
+static bool __init found_memconsole(void)
 {
 	unsigned int address;
 	size_t length, cur;
 
 	address = get_bios_ebda();
 	if (!address) {
-		printk(KERN_INFO "BIOS EBDA non-existent.\n");
+		pr_info("BIOS EBDA non-existent.\n");
 		return false;
 	}
 
@@ -122,7 +132,7 @@ static bool found_memconsole(void)
 		}
 	}
 
-	printk(KERN_INFO "BIOS console EBDA structure not found!\n");
+	pr_info("BIOS console EBDA structure not found!\n");
 	return false;
 }
 
@@ -139,8 +149,6 @@ MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
 
 static int __init memconsole_init(void)
 {
-	int ret;
-
 	if (!dmi_check_system(memconsole_dmi_table))
 		return -ENODEV;
 
@@ -148,10 +156,7 @@ static int __init memconsole_init(void)
 		return -ENODEV;
 
 	memconsole_bin_attr.size = memconsole_length;
-
-	ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
-
-	return ret;
+	return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
 }
 
 static void __exit memconsole_exit(void)
diff --git a/drivers/fmc/fmc-core.c b/drivers/fmc/fmc-core.c
index 24d52497524d..353fc546fb08 100644
--- a/drivers/fmc/fmc-core.c
+++ b/drivers/fmc/fmc-core.c
@@ -99,10 +99,23 @@ static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
 	return count;
 }
 
+static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count)
+{
+	struct device *dev;
+	struct fmc_device *fmc;
+
+	dev = container_of(kobj, struct device, kobj);
+	fmc = container_of(dev, struct fmc_device, dev);
+	return fmc->op->write_ee(fmc, off, buf, count);
+}
+
 static struct bin_attribute fmc_eeprom_attr = {
-	.attr = { .name = "eeprom", .mode = S_IRUGO, },
+	.attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
 	.size = 8192, /* more or less standard */
 	.read = fmc_read_eeprom,
+	.write = fmc_write_eeprom,
 };
 
 /*
@@ -154,7 +167,7 @@ int fmc_device_register_n(struct fmc_device **devs, int n)
 			ret = -EINVAL;
 			break;
 		}
-		if (fmc->flags == FMC_DEVICE_NO_MEZZANINE) {
+		if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) {
 			dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
 				 fmc->slot_id);
 			continue;
@@ -189,9 +202,6 @@ int fmc_device_register_n(struct fmc_device **devs, int n)
 	for (i = 0; i < n; i++) {
 		fmc = devarray[i];
 
-		if (fmc->flags == FMC_DEVICE_NO_MEZZANINE)
-			continue; /* dev_info already done above */
-
 		fmc->nr_slots = n; /* each slot must know how many are there */
 		fmc->devarray = devarray;
 
@@ -263,8 +273,6 @@ void fmc_device_unregister_n(struct fmc_device **devs, int n)
 	kfree(devs[0]->devarray);
 
 	for (i = 0; i < n; i++) {
-		if (devs[i]->flags == FMC_DEVICE_NO_MEZZANINE)
-			continue;
 		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
 		device_del(&devs[i]->dev);
 		fmc_free_id_info(devs[i]);
diff --git a/drivers/fmc/fmc-sdb.c b/drivers/fmc/fmc-sdb.c
index 79adc39221ea..4603fdb74465 100644
--- a/drivers/fmc/fmc-sdb.c
+++ b/drivers/fmc/fmc-sdb.c
@@ -150,23 +150,36 @@ int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
 }
 EXPORT_SYMBOL(fmc_reprogram);
 
+static char *__strip_trailing_space(char *buf, char *str, int len)
+{
+	int i = len - 1;
+
+	memcpy(buf, str, len);
+	while(i >= 0 && buf[i] == ' ')
+		buf[i--] = '\0';
+	return buf;
+}
+
+#define __sdb_string(buf, field) ({			\
+	BUILD_BUG_ON(sizeof(buf) < sizeof(field));	\
+	__strip_trailing_space(buf, (void *)(field), sizeof(field));	\
+		})
+
 static void __fmc_show_sdb_tree(const struct fmc_device *fmc,
 				const struct sdb_array *arr)
 {
+	unsigned long base = arr->baseaddr;
 	int i, j, n = arr->len, level = arr->level;
-	const struct sdb_array *ap;
+	char buf[64];
 
 	for (i = 0; i < n; i++) {
-		unsigned long base;
 		union  sdb_record *r;
 		struct sdb_product *p;
 		struct sdb_component *c;
 		r = &arr->record[i];
 		c = &r->dev.sdb_component;
 		p = &c->product;
-		base = 0;
-		for (ap = arr; ap; ap = ap->parent)
-			base += ap->baseaddr;
+
 		dev_info(&fmc->dev, "SDB: ");
 
 		for (j = 0; j < level; j++)
@@ -193,8 +206,8 @@ static void __fmc_show_sdb_tree(const struct fmc_device *fmc,
 			       p->name,
 			       __be64_to_cpu(c->addr_first) + base);
 			if (IS_ERR(arr->subtree[i])) {
-				printk(KERN_CONT "(bridge error %li)\n",
-				       PTR_ERR(arr->subtree[i]));
+				dev_info(&fmc->dev, "SDB: (bridge error %li)\n",
+					 PTR_ERR(arr->subtree[i]));
 				break;
 			}
 			__fmc_show_sdb_tree(fmc, arr->subtree[i]);
@@ -203,10 +216,20 @@ static void __fmc_show_sdb_tree(const struct fmc_device *fmc,
 			printk(KERN_CONT "integration\n");
 			break;
 		case sdb_type_repo_url:
-			printk(KERN_CONT "repo-url\n");
+			printk(KERN_CONT "Synthesis repository: %s\n",
+			       __sdb_string(buf, r->repo_url.repo_url));
 			break;
 		case sdb_type_synthesis:
-			printk(KERN_CONT "synthesis-info\n");
+			printk(KERN_CONT "Bitstream '%s' ",
+			       __sdb_string(buf, r->synthesis.syn_name));
+			printk(KERN_CONT "synthesized %08x by %s ",
+			       __be32_to_cpu(r->synthesis.date),
+			       __sdb_string(buf, r->synthesis.user_name));
+			printk(KERN_CONT "(%s version %x), ",
+			       __sdb_string(buf, r->synthesis.tool_name),
+			       __be32_to_cpu(r->synthesis.tool_version));
+			printk(KERN_CONT "commit %pm\n",
+			       r->synthesis.commit_id);
 			break;
 		case sdb_type_empty:
 			printk(KERN_CONT "empty\n");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 903f24d28ba0..611daad654ad 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -192,7 +192,7 @@ config GPIO_MSM_V1
 
 config GPIO_MSM_V2
 	tristate "Qualcomm MSM GPIO v2"
-	depends on GPIOLIB && OF && ARCH_MSM
+	depends on GPIOLIB && OF && ARCH_QCOM
 	help
 	  Say yes here to support the GPIO interface on ARM v7 based
 	  Qualcomm MSM chips.  Most of the pins on the MSM can be
@@ -228,7 +228,7 @@ config GPIO_OCTEON
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
 	depends on ARM_AMBA
-	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
 
@@ -462,7 +462,7 @@ config GPIO_MC9S08DZ60
 	  Select this to enable the MC9S08DZ60 GPIO driver
 
 config GPIO_PCA953X
-	tristate "PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports"
+	tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
 	depends on I2C
 	help
 	  Say yes here to provide access to several register-oriented
@@ -472,11 +472,15 @@ config GPIO_PCA953X
 	  4 bits:	pca9536, pca9537
 
 	  8 bits:	max7310, max7315, pca6107, pca9534, pca9538, pca9554,
-			pca9556, pca9557, pca9574, tca6408
+			pca9556, pca9557, pca9574, tca6408, xra1202
 
 	  16 bits:	max7312, max7313, pca9535, pca9539, pca9555, pca9575,
 			tca6416
 
+	  24 bits:	tca6424
+
+	  40 bits:	pca9505, pca9698
+
 config GPIO_PCA953X_IRQ
 	bool "Interrupt controller support for PCA953x"
 	depends on GPIO_PCA953X=y
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index 3f190e68f973..d974020b78bb 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -67,9 +67,20 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
 {
 	struct adp5588_gpio *dev =
 	    container_of(chip, struct adp5588_gpio, gpio_chip);
+	unsigned bank = ADP5588_BANK(off);
+	unsigned bit = ADP5588_BIT(off);
+	int val;
 
-	return !!(adp5588_gpio_read(dev->client,
-		  GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
+	mutex_lock(&dev->lock);
+
+	if (dev->dir[bank] & bit)
+		val = dev->dat_out[bank];
+	else
+		val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank);
+
+	mutex_unlock(&dev->lock);
+
+	return !!(val & bit);
 }
 
 static void adp5588_gpio_set_value(struct gpio_chip *chip,
@@ -386,6 +397,7 @@ static int adp5588_gpio_probe(struct i2c_client *client,
 	gc->ngpio = ADP5588_MAXGPIO;
 	gc->label = client->name;
 	gc->owner = THIS_MODULE;
+	gc->names = pdata->names;
 
 	mutex_init(&dev->lock);
 
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index f32357e2d78d..5622cfb8325a 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -28,6 +28,10 @@
 #define GPIO_BANK(gpio)				((gpio) >> 5)
 #define GPIO_BIT(gpio)				((gpio) & (GPIO_PER_BANK - 1))
 
+/* There is a GPIO control register for each GPIO */
+#define GPIO_CONTROL(gpio)			(0x00000100 + ((gpio) << 2))
+
+/* The remaining registers are per GPIO bank */
 #define GPIO_OUT_STATUS(bank)			(0x00000000 + ((bank) << 2))
 #define GPIO_IN_STATUS(bank)			(0x00000020 + ((bank) << 2))
 #define GPIO_OUT_SET(bank)			(0x00000040 + ((bank) << 2))
@@ -35,7 +39,6 @@
 #define GPIO_INT_STATUS(bank)			(0x00000080 + ((bank) << 2))
 #define GPIO_INT_MASK(bank)			(0x000000a0 + ((bank) << 2))
 #define GPIO_INT_MSKCLR(bank)			(0x000000c0 + ((bank) << 2))
-#define GPIO_CONTROL(bank)			(0x00000100 + ((bank) << 2))
 #define GPIO_PWD_STATUS(bank)			(0x00000500 + ((bank) << 2))
 
 #define GPIO_GPPWR_OFFSET			0x00000520
@@ -80,22 +83,43 @@ static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip)
 	return container_of(chip, struct bcm_kona_gpio, gpio_chip);
 }
 
-static void bcm_kona_gpio_set_lockcode_bank(void __iomem *reg_base,
-					    int bank_id, int lockcode)
+static inline void bcm_kona_gpio_write_lock_regs(void __iomem *reg_base,
+						int bank_id, u32 lockcode)
 {
 	writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
 	writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
 }
 
-static inline void bcm_kona_gpio_lock_bank(void __iomem *reg_base, int bank_id)
+static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
+					unsigned gpio)
 {
-	bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, LOCK_CODE);
+	u32 val;
+	unsigned long flags;
+	int bank_id = GPIO_BANK(gpio);
+
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+
+	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
+	val |= BIT(gpio);
+	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
+
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
-static inline void bcm_kona_gpio_unlock_bank(void __iomem *reg_base,
-					     int bank_id)
+static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
+					unsigned gpio)
 {
-	bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, UNLOCK_CODE);
+	u32 val;
+	unsigned long flags;
+	int bank_id = GPIO_BANK(gpio);
+
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+
+	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
+	val &= ~BIT(gpio);
+	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
+
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
@@ -110,7 +134,6 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
 	kona_gpio = to_kona_gpio(chip);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	/* determine the GPIO pin direction */
 	val = readl(reg_base + GPIO_CONTROL(gpio));
@@ -127,7 +150,6 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
 	writel(val, reg_base + reg_offset);
 
 out:
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
@@ -143,7 +165,6 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
 	kona_gpio = to_kona_gpio(chip);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	/* determine the GPIO pin direction */
 	val = readl(reg_base + GPIO_CONTROL(gpio));
@@ -154,32 +175,43 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
 	    GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
 	val = readl(reg_base + reg_offset);
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	/* return the specified bit status */
 	return !!(val & BIT(bit));
 }
 
+static int bcm_kona_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip);
+
+	bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
+	return 0;
+}
+
+static void bcm_kona_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip);
+
+	bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
+}
+
 static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 {
 	struct bcm_kona_gpio *kona_gpio;
 	void __iomem *reg_base;
 	u32 val;
 	unsigned long flags;
-	int bank_id = GPIO_BANK(gpio);
 
 	kona_gpio = to_kona_gpio(chip);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
 	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
@@ -198,7 +230,6 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 	kona_gpio = to_kona_gpio(chip);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
@@ -210,7 +241,6 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 	val |= BIT(bit);
 	writel(val, reg_base + reg_offset);
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
@@ -233,7 +263,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 	void __iomem *reg_base;
 	u32 val, res;
 	unsigned long flags;
-	int bank_id = GPIO_BANK(gpio);
 
 	kona_gpio = to_kona_gpio(chip);
 	reg_base = kona_gpio->reg_base;
@@ -257,7 +286,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 
 	/* spin lock for read-modify-write of the GPIO register */
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_DBR_MASK;
@@ -272,7 +300,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
@@ -281,6 +308,8 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 static struct gpio_chip template_chip = {
 	.label = "bcm-kona-gpio",
 	.owner = THIS_MODULE,
+	.request = bcm_kona_gpio_request,
+	.free = bcm_kona_gpio_free,
 	.direction_input = bcm_kona_gpio_direction_input,
 	.get = bcm_kona_gpio_get,
 	.direction_output = bcm_kona_gpio_direction_output,
@@ -294,7 +323,7 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
 {
 	struct bcm_kona_gpio *kona_gpio;
 	void __iomem *reg_base;
-	int gpio = d->hwirq;
+	unsigned gpio = d->hwirq;
 	int bank_id = GPIO_BANK(gpio);
 	int bit = GPIO_BIT(gpio);
 	u32 val;
@@ -303,13 +332,11 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_INT_STATUS(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_STATUS(bank_id));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
@@ -317,7 +344,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
 {
 	struct bcm_kona_gpio *kona_gpio;
 	void __iomem *reg_base;
-	int gpio = d->hwirq;
+	unsigned gpio = d->hwirq;
 	int bank_id = GPIO_BANK(gpio);
 	int bit = GPIO_BIT(gpio);
 	u32 val;
@@ -326,13 +353,11 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_INT_MASK(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MASK(bank_id));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
@@ -340,7 +365,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
 {
 	struct bcm_kona_gpio *kona_gpio;
 	void __iomem *reg_base;
-	int gpio = d->hwirq;
+	unsigned gpio = d->hwirq;
 	int bank_id = GPIO_BANK(gpio);
 	int bit = GPIO_BIT(gpio);
 	u32 val;
@@ -349,13 +374,11 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
@@ -363,11 +386,10 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct bcm_kona_gpio *kona_gpio;
 	void __iomem *reg_base;
-	int gpio = d->hwirq;
+	unsigned gpio = d->hwirq;
 	u32 lvl_type;
 	u32 val;
 	unsigned long flags;
-	int bank_id = GPIO_BANK(gpio);
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
@@ -394,14 +416,12 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	}
 
 	spin_lock_irqsave(&kona_gpio->lock, flags);
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_ITR_MASK;
 	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
 	spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
@@ -424,7 +444,6 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	 */
 	reg_base = bank->kona_gpio->reg_base;
 	bank_id = bank->id;
-	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
 
 	while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
 		    (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
@@ -444,8 +463,6 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 		}
 	}
 
-	bcm_kona_gpio_lock_bank(reg_base, bank_id);
-
 	chained_irq_exit(chip, desc);
 }
 
@@ -531,10 +548,12 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
 	reg_base = kona_gpio->reg_base;
 	/* disable interrupts and clear status */
 	for (i = 0; i < kona_gpio->num_bank; i++) {
-		bcm_kona_gpio_unlock_bank(reg_base, i);
+		/* Unlock the entire bank first */
+		bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
 		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
 		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
-		bcm_kona_gpio_lock_bank(reg_base, i);
+		/* Now re-lock the bank */
+		bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
 	}
 }
 
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
index 3c2ba2ad0ada..e1e861239e95 100644
--- a/drivers/gpio/gpio-clps711x.c
+++ b/drivers/gpio/gpio-clps711x.c
@@ -65,6 +65,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev)
 	}
 
 	bgc->gc.base = id * 8;
+	bgc->gc.owner = THIS_MODULE;
 	platform_set_drvdata(pdev, bgc);
 
 	return gpiochip_add(&bgc->gc);
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 7629b4f12b7f..29321eea3c44 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -423,7 +423,8 @@ static const struct irq_domain_ops davinci_gpio_irq_ops = {
 
 static int davinci_gpio_irq_setup(struct platform_device *pdev)
 {
-	unsigned	gpio, irq, bank;
+	unsigned	gpio, bank;
+	int		irq;
 	struct clk	*clk;
 	u32		binten = 0;
 	unsigned	ngpio, bank_irq;
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index d2196bf73847..d815dd25eb47 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -139,7 +139,7 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct bgpio_chip *bgc = to_bgpio_chip(gc);
 
-	return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
+	return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
 }
 
 static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
@@ -531,6 +531,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 		return err;
 
 	if (pdata) {
+		if (pdata->label)
+			bgc->gc.label = pdata->label;
 		bgc->gc.base = pdata->base;
 		if (pdata->ngpio > 0)
 			bgc->gc.ngpio = pdata->ngpio;
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index f5bf3c38bca6..bfef20f8ab48 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -62,6 +62,13 @@ struct ichx_desc {
 	/* Max GPIO pins the chipset can have */
 	uint ngpio;
 
+	/* chipset registers */
+	const u8 (*regs)[3];
+	const u8 *reglen;
+
+	/* GPO_BLINK is available on this chipset */
+	bool have_blink;
+
 	/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */
 	bool uses_gpe0;
 
@@ -71,6 +78,12 @@ struct ichx_desc {
 	/* Some chipsets have quirks, let these use their own request/get */
 	int (*request)(struct gpio_chip *chip, unsigned offset);
 	int (*get)(struct gpio_chip *chip, unsigned offset);
+
+	/*
+	 * Some chipsets don't let reading output values on GPIO_LVL register
+	 * this option allows driver caching written output values
+	 */
+	bool use_outlvl_cache;
 };
 
 static struct {
@@ -82,6 +95,7 @@ static struct {
 	struct ichx_desc *desc;	/* Pointer to chipset-specific description */
 	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */
 	u8 use_gpio;		/* Which GPIO groups are usable */
+	int outlvl_cache[3];	/* cached output values */
 } ichx_priv;
 
 static int modparam_gpiobase = -1;	/* dynamic */
@@ -99,13 +113,23 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
 
 	spin_lock_irqsave(&ichx_priv.lock, flags);
 
-	data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
+	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
+		data = ichx_priv.outlvl_cache[reg_nr];
+	else
+		data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
+				 ichx_priv.gpio_base);
+
 	if (val)
 		data |= 1 << bit;
 	else
 		data &= ~(1 << bit);
-	ICHX_WRITE(data, ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
-	tmp = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
+	ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
+			 ichx_priv.gpio_base);
+	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
+		ichx_priv.outlvl_cache[reg_nr] = data;
+
+	tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
+			ichx_priv.gpio_base);
 	if (verify && data != tmp)
 		ret = -EPERM;
 
@@ -123,7 +147,11 @@ static int ichx_read_bit(int reg, unsigned nr)
 
 	spin_lock_irqsave(&ichx_priv.lock, flags);
 
-	data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
+	data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
+			 ichx_priv.gpio_base);
+
+	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
+		data = ichx_priv.outlvl_cache[reg_nr] | data;
 
 	spin_unlock_irqrestore(&ichx_priv.lock, flags);
 
@@ -151,7 +179,7 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 					int val)
 {
 	/* Disable blink hardware which is available for GPIOs from 0 to 31. */
-	if (nr < 32)
+	if (nr < 32 && ichx_priv.desc->have_blink)
 		ichx_write_bit(GPO_BLINK, nr, 0, 0);
 
 	/* Set GPIO output value. */
@@ -266,6 +294,7 @@ static struct ichx_desc ich6_desc = {
 	.uses_gpe0 = true,
 
 	.ngpio = 50,
+	.have_blink = true,
 };
 
 /* Intel 3100 */
@@ -290,24 +319,38 @@ static struct ichx_desc i3100_desc = {
 /* ICH7 and ICH8-based */
 static struct ichx_desc ich7_desc = {
 	.ngpio = 50,
+	.have_blink = true,
+	.regs = ichx_regs,
+	.reglen = ichx_reglen,
 };
 
 /* ICH9-based */
 static struct ichx_desc ich9_desc = {
 	.ngpio = 61,
+	.have_blink = true,
+	.regs = ichx_regs,
+	.reglen = ichx_reglen,
 };
 
 /* ICH10-based - Consumer/corporate versions have different amount of GPIO */
 static struct ichx_desc ich10_cons_desc = {
 	.ngpio = 61,
+	.have_blink = true,
+	.regs = ichx_regs,
+	.reglen = ichx_reglen,
 };
 static struct ichx_desc ich10_corp_desc = {
 	.ngpio = 72,
+	.have_blink = true,
+	.regs = ichx_regs,
+	.reglen = ichx_reglen,
 };
 
 /* Intel 5 series, 6 series, 3400 series, and C200 series */
 static struct ichx_desc intel5_desc = {
 	.ngpio = 76,
+	.regs = ichx_regs,
+	.reglen = ichx_reglen,
 };
 
 static int ichx_gpio_request_regions(struct resource *res_base,
@@ -318,11 +361,12 @@ static int ichx_gpio_request_regions(struct resource *res_base,
 	if (!res_base || !res_base->start || !res_base->end)
 		return -ENODEV;
 
-	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
 		if (!(use_gpio & (1 << i)))
 			continue;
-		if (!request_region(res_base->start + ichx_regs[0][i],
-				    ichx_reglen[i], name))
+		if (!request_region(
+				res_base->start + ichx_priv.desc->regs[0][i],
+				ichx_priv.desc->reglen[i], name))
 			goto request_err;
 	}
 	return 0;
@@ -332,8 +376,8 @@ request_err:
 	for (i--; i >= 0; i--) {
 		if (!(use_gpio & (1 << i)))
 			continue;
-		release_region(res_base->start + ichx_regs[0][i],
-			       ichx_reglen[i]);
+		release_region(res_base->start + ichx_priv.desc->regs[0][i],
+			       ichx_priv.desc->reglen[i]);
 	}
 	return -EBUSY;
 }
@@ -342,11 +386,11 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
 		if (!(use_gpio & (1 << i)))
 			continue;
-		release_region(res_base->start + ichx_regs[0][i],
-			       ichx_reglen[i]);
+		release_region(res_base->start + ichx_priv.desc->regs[0][i],
+			       ichx_priv.desc->reglen[i]);
 	}
 }
 
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index e585163f1ad5..3a34bb151fd4 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -1,7 +1,7 @@
 /*
- * Moorestown platform Langwell chip GPIO driver
+ * Intel MID GPIO driver
  *
- * Copyright (c) 2008, 2009, 2013, Intel Corporation.
+ * Copyright (c) 2008-2014 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
@@ -11,10 +11,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.
  */
 
 /* Supports:
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 3b1fd1ce460f..d42509422394 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -44,6 +44,7 @@
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/irqchip/chained_irq.h>
 
 /*
  * GPIO unit register offsets.
@@ -438,12 +439,15 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	u32 cause, type;
 	int i;
 
 	if (mvchip == NULL)
 		return;
 
+	chained_irq_enter(chip, desc);
+
 	cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
 		readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
 	cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
@@ -466,8 +470,11 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 			polarity ^= 1 << i;
 			writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
 		}
+
 		generic_handle_irq(irq);
 	}
+
+	chained_irq_exit(chip, desc);
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 424319061e09..19b886c21b1d 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1214,24 +1214,10 @@ static int omap_gpio_probe(struct platform_device *pdev)
 
 	/* Static mapping, never released */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(!res)) {
-		dev_err(dev, "Invalid mem resource\n");
-		irq_domain_remove(bank->domain);
-		return -ENODEV;
-	}
-
-	if (!devm_request_mem_region(dev, res->start, resource_size(res),
-				     pdev->name)) {
-		dev_err(dev, "Region already claimed\n");
+	bank->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(bank->base)) {
 		irq_domain_remove(bank->domain);
-		return -EBUSY;
-	}
-
-	bank->base = devm_ioremap(dev, res->start, resource_size(res));
-	if (!bank->base) {
-		dev_err(dev, "Could not ioremap\n");
-		irq_domain_remove(bank->domain);
-		return -ENOMEM;
+		return PTR_ERR(bank->base);
 	}
 
 	platform_set_drvdata(pdev, bank);
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 019b23b955a2..d550d8e58705 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1,5 +1,5 @@
 /*
- *  PCA953x 4/8/16 bit I/O ports
+ *  PCA953x 4/8/16/24/40 bit I/O ports
  *
  *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
  *  Copyright (C) 2007 Marvell International Ltd.
@@ -59,6 +59,7 @@ static const struct i2c_device_id pca953x_id[] = {
 	{ "pca9557", 8  | PCA953X_TYPE, },
 	{ "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
 	{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+	{ "pca9698", 40 | PCA953X_TYPE, },
 
 	{ "max7310", 8  | PCA953X_TYPE, },
 	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
@@ -68,6 +69,7 @@ static const struct i2c_device_id pca953x_id[] = {
 	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
 	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
+	{ "xra1202", 8  | PCA953X_TYPE },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
@@ -625,11 +627,12 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
 	const __be32 *val;
 	int size;
 
+	*gpio_base = -1;
+
 	node = client->dev.of_node;
 	if (node == NULL)
 		return;
 
-	*gpio_base = -1;
 	val = of_get_property(node, "linux,gpio-base", &size);
 	WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
 	if (val) {
@@ -812,6 +815,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
 	{ .compatible = "nxp,pca9557", },
 	{ .compatible = "nxp,pca9574", },
 	{ .compatible = "nxp,pca9575", },
+	{ .compatible = "nxp,pca9698", },
 
 	{ .compatible = "maxim,max7310", },
 	{ .compatible = "maxim,max7312", },
@@ -822,6 +826,8 @@ static const struct of_device_id pca953x_dt_ids[] = {
 	{ .compatible = "ti,tca6408", },
 	{ .compatible = "ti,tca6416", },
 	{ .compatible = "ti,tca6424", },
+
+	{ .compatible = "exar,xra1202", },
 	{ }
 };
 
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b4d42112d02d..e528cb2b12aa 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -150,6 +150,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 	int offset = irqd_to_hwirq(d);
 	unsigned long flags;
 	u8 gpiois, gpioibe, gpioiev;
+	u8 bit = BIT(offset);
 
 	if (offset < 0 || offset >= PL061_GPIO_NR)
 		return -EINVAL;
@@ -157,30 +158,31 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 	spin_lock_irqsave(&chip->lock, flags);
 
 	gpioiev = readb(chip->base + GPIOIEV);
-
 	gpiois = readb(chip->base + GPIOIS);
+	gpioibe = readb(chip->base + GPIOIBE);
+
 	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		gpiois |= 1 << offset;
+		gpiois |= bit;
 		if (trigger & IRQ_TYPE_LEVEL_HIGH)
-			gpioiev |= 1 << offset;
+			gpioiev |= bit;
 		else
-			gpioiev &= ~(1 << offset);
+			gpioiev &= ~bit;
 	} else
-		gpiois &= ~(1 << offset);
-	writeb(gpiois, chip->base + GPIOIS);
+		gpiois &= ~bit;
 
-	gpioibe = readb(chip->base + GPIOIBE);
 	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		gpioibe |= 1 << offset;
+		/* Setting this makes GPIOEV be ignored */
+		gpioibe |= bit;
 	else {
-		gpioibe &= ~(1 << offset);
+		gpioibe &= ~bit;
 		if (trigger & IRQ_TYPE_EDGE_RISING)
-			gpioiev |= 1 << offset;
+			gpioiev |= bit;
 		else if (trigger & IRQ_TYPE_EDGE_FALLING)
-			gpioiev &= ~(1 << offset);
+			gpioiev &= ~bit;
 	}
-	writeb(gpioibe, chip->base + GPIOIBE);
 
+	writeb(gpiois, chip->base + GPIOIS);
+	writeb(gpioibe, chip->base + GPIOIBE);
 	writeb(gpioiev, chip->base + GPIOIEV);
 
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -231,11 +233,33 @@ static void pl061_irq_unmask(struct irq_data *d)
 	spin_unlock(&chip->lock);
 }
 
+static unsigned int pl061_irq_startup(struct irq_data *d)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+
+	if (gpio_lock_as_irq(&chip->gc, irqd_to_hwirq(d)))
+		dev_err(chip->gc.dev,
+			"unable to lock HW IRQ %lu for IRQ\n",
+			irqd_to_hwirq(d));
+	pl061_irq_unmask(d);
+	return 0;
+}
+
+static void pl061_irq_shutdown(struct irq_data *d)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+
+	pl061_irq_mask(d);
+	gpio_unlock_as_irq(&chip->gc, irqd_to_hwirq(d));
+}
+
 static struct irq_chip pl061_irqchip = {
-	.name		= "pl061 gpio",
+	.name		= "pl061",
 	.irq_mask	= pl061_irq_mask,
 	.irq_unmask	= pl061_irq_unmask,
 	.irq_set_type	= pl061_irq_type,
+	.irq_startup	= pl061_irq_startup,
+	.irq_shutdown	= pl061_irq_shutdown,
 };
 
 static int pl061_irq_map(struct irq_domain *d, unsigned int irq,
@@ -243,8 +267,7 @@ static int pl061_irq_map(struct irq_domain *d, unsigned int irq,
 {
 	struct pl061_gpio *chip = d->host_data;
 
-	irq_set_chip_and_handler_name(irq, &pl061_irqchip, handle_simple_irq,
-				      "pl061");
+	irq_set_chip_and_handler(irq, &pl061_irqchip, handle_simple_irq);
 	irq_set_chip_data(irq, chip);
 	irq_set_irq_type(irq, IRQ_TYPE_NONE);
 
@@ -270,21 +293,18 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	if (pdata) {
 		chip->gc.base = pdata->gpio_base;
 		irq_base = pdata->irq_base;
-		if (irq_base <= 0)
+		if (irq_base <= 0) {
+			dev_err(&adev->dev, "invalid IRQ base in pdata\n");
 			return -ENODEV;
+		}
 	} else {
 		chip->gc.base = -1;
 		irq_base = 0;
 	}
 
-	if (!devm_request_mem_region(dev, adev->res.start,
-				     resource_size(&adev->res), "pl061"))
-		return -EBUSY;
-
-	chip->base = devm_ioremap(dev, adev->res.start,
-				  resource_size(&adev->res));
-	if (!chip->base)
-		return -ENOMEM;
+	chip->base = devm_ioremap_resource(dev, &adev->res);
+	if (IS_ERR(chip->base))
+		return PTR_ERR(chip->base);
 
 	spin_lock_init(&chip->lock);
 
@@ -309,16 +329,20 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	 */
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
 	irq = adev->irq[0];
-	if (irq < 0)
+	if (irq < 0) {
+		dev_err(&adev->dev, "invalid IRQ\n");
 		return -ENODEV;
+	}
 
 	irq_set_chained_handler(irq, pl061_irq_handler);
 	irq_set_handler_data(irq, chip);
 
 	chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
 					     irq_base, &pl061_domain_ops, chip);
-	if (!chip->domain)
+	if (!chip->domain) {
+		dev_err(&adev->dev, "no irq domain\n");
 		return -ENODEV;
+	}
 
 	for (i = 0; i < PL061_GPIO_NR; i++) {
 		if (pdata) {
@@ -331,6 +355,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	}
 
 	amba_set_drvdata(adev, chip);
+	dev_info(&adev->dev, "PL061 GPIO chip @%08x registered\n",
+		adev->res.start);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 122b776fdc0b..9b423173ab50 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -97,7 +97,7 @@ static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 {
 	struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
 
-	if ((offset >= 0) && (offset < 8))
+	if (offset < RC5T583_MAX_GPIO)
 		return rc5t583_gpio->rc5t583->irq_base +
 				RC5T583_IRQ_GPIO0 + offset;
 	return -EINVAL;
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 716ee9843110..b7db098ba060 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -60,7 +60,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 	if (pin < 0 || pin > chip->ngpio)
 		return ERR_PTR(-EINVAL);
 
-	return gpio_to_desc(chip->base + pin);
+	return gpiochip_get_desc(chip, pin);
 }
 
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index e0a98f581f58..2024d45e5503 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -90,7 +91,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 
 	of_node_put(gg_data.gpiospec.np);
 	pr_debug("%s exited with status %d\n", __func__,
-		 PTR_RET(gg_data.out_gpio));
+		 PTR_ERR_OR_ZERO(gg_data.out_gpio));
 	return gg_data.out_gpio;
 }
 EXPORT_SYMBOL(of_get_named_gpiod_flags);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 50c4922fe53a..9cd7082cca08 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -164,16 +164,17 @@ struct gpio_desc *gpio_to_desc(unsigned gpio)
 EXPORT_SYMBOL_GPL(gpio_to_desc);
 
 /**
- * Convert an offset on a certain chip to a corresponding descriptor
+ * Get the GPIO descriptor corresponding to the given hw number for this chip.
  */
-static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip,
-						 unsigned int offset)
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
+				    u16 hwnum)
 {
-	if (offset >= chip->ngpio)
+	if (hwnum >= chip->ngpio)
 		return ERR_PTR(-EINVAL);
 
-	return &chip->desc[offset];
+	return &chip->desc[hwnum];
 }
+EXPORT_SYMBOL_GPL(gpiochip_get_desc);
 
 /**
  * Convert a GPIO descriptor to the integer namespace.
@@ -350,9 +351,9 @@ static ssize_t gpio_direction_store(struct device *dev,
 	if (!test_bit(FLAG_EXPORT, &desc->flags))
 		status = -EIO;
 	else if (sysfs_streq(buf, "high"))
-		status = gpiod_direction_output(desc, 1);
+		status = gpiod_direction_output_raw(desc, 1);
 	else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
-		status = gpiod_direction_output(desc, 0);
+		status = gpiod_direction_output_raw(desc, 0);
 	else if (sysfs_streq(buf, "in"))
 		status = gpiod_direction_input(desc);
 	else
@@ -1590,7 +1591,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
 	if (flags & GPIOF_DIR_IN)
 		err = gpiod_direction_input(desc);
 	else
-		err = gpiod_direction_output(desc,
+		err = gpiod_direction_output_raw(desc,
 				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
 	if (err)
@@ -1756,28 +1757,13 @@ fail:
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
-/**
- * gpiod_direction_output - set the GPIO direction to input
- * @desc:	GPIO to set to output
- * @value:	initial output value of the GPIO
- *
- * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
- * be called safely on it. The initial value of the output must be specified.
- *
- * Return 0 in case of success, else an error code.
- */
-int gpiod_direction_output(struct gpio_desc *desc, int value)
+static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
 	unsigned long		flags;
 	struct gpio_chip	*chip;
 	int			status = -EINVAL;
 	int offset;
 
-	if (!desc || !desc->chip) {
-		pr_warn("%s: invalid GPIO\n", __func__);
-		return -EINVAL;
-	}
-
 	/* GPIOs used for IRQs shall not be set as output */
 	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
 		gpiod_err(desc,
@@ -1840,6 +1826,50 @@ fail:
 		gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
 	return status;
 }
+
+/**
+ * gpiod_direction_output_raw - set the GPIO direction to output
+ * @desc:	GPIO to set to output
+ * @value:	initial output value of the GPIO
+ *
+ * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+ * be called safely on it. The initial value of the output must be specified
+ * as raw value on the physical line without regard for the ACTIVE_LOW status.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
+{
+	if (!desc || !desc->chip) {
+		pr_warn("%s: invalid GPIO\n", __func__);
+		return -EINVAL;
+	}
+	return _gpiod_direction_output_raw(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
+
+/**
+ * gpiod_direction_output - set the GPIO direction to output
+ * @desc:	GPIO to set to output
+ * @value:	initial output value of the GPIO
+ *
+ * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+ * be called safely on it. The initial value of the output must be specified
+ * as the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+ * account.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_output(struct gpio_desc *desc, int value)
+{
+	if (!desc || !desc->chip) {
+		pr_warn("%s: invalid GPIO\n", __func__);
+		return -EINVAL;
+	}
+	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+		value = !value;
+	return _gpiod_direction_output_raw(desc, value);
+}
 EXPORT_SYMBOL_GPL(gpiod_direction_output);
 
 /**
@@ -2161,7 +2191,7 @@ EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
 
 int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	return gpiod_lock_as_irq(gpiochip_offset_to_desc(chip, offset));
+	return gpiod_lock_as_irq(gpiochip_get_desc(chip, offset));
 }
 EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
 
@@ -2183,7 +2213,7 @@ EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
 
 void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	return gpiod_unlock_as_irq(gpiochip_offset_to_desc(chip, offset));
+	return gpiod_unlock_as_irq(gpiochip_get_desc(chip, offset));
 }
 EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
 
@@ -2404,7 +2434,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
 			return ERR_PTR(-EINVAL);
 		}
 
-		desc = gpiochip_offset_to_desc(chip, p->chip_hwnum);
+		desc = gpiochip_get_desc(chip, p->chip_hwnum);
 		*flags = p->flags;
 
 		return desc;
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index bb8f58012189..534cb89b160d 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -32,6 +32,12 @@
 #include <drm/drmP.h>
 
 #if defined(CONFIG_X86)
+
+/*
+ * clflushopt is an unordered instruction which needs fencing with mfence or
+ * sfence to avoid ordering issues.  For drm_clflush_page this fencing happens
+ * in the caller.
+ */
 static void
 drm_clflush_page(struct page *page)
 {
@@ -44,7 +50,7 @@ drm_clflush_page(struct page *page)
 
 	page_virtual = kmap_atomic(page);
 	for (i = 0; i < PAGE_SIZE; i += size)
-		clflush(page_virtual + i);
+		clflushopt(page_virtual + i);
 	kunmap_atomic(page_virtual);
 }
 
@@ -133,7 +139,7 @@ drm_clflush_virt_range(char *addr, unsigned long length)
 		mb();
 		for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
 			clflush(addr);
-		clflush(end - 1);
+		clflushopt(end - 1);
 		mb();
 		return;
 	}
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3b7d32da1604..35ea15d5ffff 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -215,6 +215,16 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] =
 	{ DRM_MODE_ENCODER_DSI, "DSI" },
 };
 
+static const struct drm_prop_enum_list drm_subpixel_enum_list[] =
+{
+	{ SubPixelUnknown, "Unknown" },
+	{ SubPixelHorizontalRGB, "Horizontal RGB" },
+	{ SubPixelHorizontalBGR, "Horizontal BGR" },
+	{ SubPixelVerticalRGB, "Vertical RGB" },
+	{ SubPixelVerticalBGR, "Vertical BGR" },
+	{ SubPixelNone, "None" },
+};
+
 void drm_connector_ida_init(void)
 {
 	int i;
@@ -264,6 +274,19 @@ const char *drm_get_connector_status_name(enum drm_connector_status status)
 }
 EXPORT_SYMBOL(drm_get_connector_status_name);
 
+/**
+ * drm_get_subpixel_order_name - return a string for a given subpixel enum
+ * @order: enum of subpixel_order
+ *
+ * Note you could abuse this and return something out of bounds, but that
+ * would be a caller error.  No unscrubbed user data should make it here.
+ */
+const char *drm_get_subpixel_order_name(enum subpixel_order order)
+{
+	return drm_subpixel_enum_list[order].name;
+}
+EXPORT_SYMBOL(drm_get_subpixel_order_name);
+
 static char printable_char(int c)
 {
 	return isascii(c) && isprint(c) ? c : '?';
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ea92b827e787..f7a81209beb3 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -564,7 +564,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
  * Caller must hold mode config lock.
  *
  * Setup a new configuration, provided by the upper layers (either an ioctl call
- * from userspace or internally e.g. from the fbdev suppport code) in @set, and
+ * from userspace or internally e.g. from the fbdev support code) in @set, and
  * enable it. This is the main helper functions for drivers that implement
  * kernel mode setting with the crtc helper functions and the assorted
  * ->prepare(), ->modeset() and ->commit() helper callbacks.
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 9e978aae8972..35251af3b14e 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -346,3 +346,398 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
 	}
 }
 EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
+
+/**
+ * DOC: dp helpers
+ *
+ * The DisplayPort AUX channel is an abstraction to allow generic, driver-
+ * independent access to AUX functionality. Drivers can take advantage of
+ * this by filling in the fields of the drm_dp_aux structure.
+ *
+ * Transactions are described using a hardware-independent drm_dp_aux_msg
+ * structure, which is passed into a driver's .transfer() implementation.
+ * Both native and I2C-over-AUX transactions are supported.
+ */
+
+static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
+			      unsigned int offset, void *buffer, size_t size)
+{
+	struct drm_dp_aux_msg msg;
+	unsigned int retry;
+	int err;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.address = offset;
+	msg.request = request;
+	msg.buffer = buffer;
+	msg.size = size;
+
+	/*
+	 * The specification doesn't give any recommendation on how often to
+	 * retry native transactions, so retry 7 times like for I2C-over-AUX
+	 * transactions.
+	 */
+	for (retry = 0; retry < 7; retry++) {
+		err = aux->transfer(aux, &msg);
+		if (err < 0) {
+			if (err == -EBUSY)
+				continue;
+
+			return err;
+		}
+
+		if (err < size)
+			return -EPROTO;
+
+		switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
+		case DP_AUX_NATIVE_REPLY_ACK:
+			return err;
+
+		case DP_AUX_NATIVE_REPLY_NACK:
+			return -EIO;
+
+		case DP_AUX_NATIVE_REPLY_DEFER:
+			usleep_range(400, 500);
+			break;
+		}
+	}
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EIO;
+}
+
+/**
+ * drm_dp_dpcd_read() - read a series of bytes from the DPCD
+ * @aux: DisplayPort AUX channel
+ * @offset: address of the (first) register to read
+ * @buffer: buffer to store the register values
+ * @size: number of bytes in @buffer
+ *
+ * Returns the number of bytes transferred on success, or a negative error
+ * code on failure. -EIO is returned if the request was NAKed by the sink or
+ * if the retry count was exceeded. If not all bytes were transferred, this
+ * function returns -EPROTO. Errors from the underlying AUX channel transfer
+ * function, with the exception of -EBUSY (which causes the transaction to
+ * be retried), are propagated to the caller.
+ */
+ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
+			 void *buffer, size_t size)
+{
+	return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
+				  size);
+}
+EXPORT_SYMBOL(drm_dp_dpcd_read);
+
+/**
+ * drm_dp_dpcd_write() - write a series of bytes to the DPCD
+ * @aux: DisplayPort AUX channel
+ * @offset: address of the (first) register to write
+ * @buffer: buffer containing the values to write
+ * @size: number of bytes in @buffer
+ *
+ * Returns the number of bytes transferred on success, or a negative error
+ * code on failure. -EIO is returned if the request was NAKed by the sink or
+ * if the retry count was exceeded. If not all bytes were transferred, this
+ * function returns -EPROTO. Errors from the underlying AUX channel transfer
+ * function, with the exception of -EBUSY (which causes the transaction to
+ * be retried), are propagated to the caller.
+ */
+ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
+			  void *buffer, size_t size)
+{
+	return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
+				  size);
+}
+EXPORT_SYMBOL(drm_dp_dpcd_write);
+
+/**
+ * drm_dp_dpcd_read_link_status() - read DPCD link status (bytes 0x202-0x207)
+ * @aux: DisplayPort AUX channel
+ * @status: buffer to store the link status in (must be at least 6 bytes)
+ *
+ * Returns the number of bytes transferred on success or a negative error
+ * code on failure.
+ */
+int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
+				 u8 status[DP_LINK_STATUS_SIZE])
+{
+	return drm_dp_dpcd_read(aux, DP_LANE0_1_STATUS, status,
+				DP_LINK_STATUS_SIZE);
+}
+EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
+
+/**
+ * drm_dp_link_probe() - probe a DisplayPort link for capabilities
+ * @aux: DisplayPort AUX channel
+ * @link: pointer to structure in which to return link capabilities
+ *
+ * The structure filled in by this function can usually be passed directly
+ * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
+ * configure the link based on the link's capabilities.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
+{
+	u8 values[3];
+	int err;
+
+	memset(link, 0, sizeof(*link));
+
+	err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
+	if (err < 0)
+		return err;
+
+	link->revision = values[0];
+	link->rate = drm_dp_bw_code_to_link_rate(values[1]);
+	link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
+
+	if (values[2] & DP_ENHANCED_FRAME_CAP)
+		link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_link_probe);
+
+/**
+ * drm_dp_link_power_up() - power up a DisplayPort link
+ * @aux: DisplayPort AUX channel
+ * @link: pointer to a structure containing the link configuration
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
+{
+	u8 value;
+	int err;
+
+	/* DP_SET_POWER register is only available on DPCD v1.1 and later */
+	if (link->revision < 0x11)
+		return 0;
+
+	err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
+	if (err < 0)
+		return err;
+
+	value &= ~DP_SET_POWER_MASK;
+	value |= DP_SET_POWER_D0;
+
+	err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
+	if (err < 0)
+		return err;
+
+	/*
+	 * According to the DP 1.1 specification, a "Sink Device must exit the
+	 * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
+	 * Control Field" (register 0x600).
+	 */
+	usleep_range(1000, 2000);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_link_power_up);
+
+/**
+ * drm_dp_link_configure() - configure a DisplayPort link
+ * @aux: DisplayPort AUX channel
+ * @link: pointer to a structure containing the link configuration
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
+{
+	u8 values[2];
+	int err;
+
+	values[0] = drm_dp_link_rate_to_bw_code(link->rate);
+	values[1] = link->num_lanes;
+
+	if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
+		values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+
+	err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_link_configure);
+
+/*
+ * I2C-over-AUX implementation
+ */
+
+static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	       I2C_FUNC_10BIT_ADDR;
+}
+
+/*
+ * Transfer a single I2C-over-AUX message and handle various error conditions,
+ * retrying the transaction as appropriate.
+ */
+static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	unsigned int retry;
+	int err;
+
+	/*
+	 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
+	 * is required to retry at least seven times upon receiving AUX_DEFER
+	 * before giving up the AUX transaction.
+	 */
+	for (retry = 0; retry < 7; retry++) {
+		err = aux->transfer(aux, msg);
+		if (err < 0) {
+			if (err == -EBUSY)
+				continue;
+
+			DRM_DEBUG_KMS("transaction failed: %d\n", err);
+			return err;
+		}
+
+		if (err < msg->size)
+			return -EPROTO;
+
+		switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) {
+		case DP_AUX_NATIVE_REPLY_ACK:
+			/*
+			 * For I2C-over-AUX transactions this isn't enough, we
+			 * need to check for the I2C ACK reply.
+			 */
+			break;
+
+		case DP_AUX_NATIVE_REPLY_NACK:
+			DRM_DEBUG_KMS("native nack\n");
+			return -EREMOTEIO;
+
+		case DP_AUX_NATIVE_REPLY_DEFER:
+			DRM_DEBUG_KMS("native defer");
+			/*
+			 * We could check for I2C bit rate capabilities and if
+			 * available adjust this interval. We could also be
+			 * more careful with DP-to-legacy adapters where a
+			 * long legacy cable may force very low I2C bit rates.
+			 *
+			 * For now just defer for long enough to hopefully be
+			 * safe for all use-cases.
+			 */
+			usleep_range(500, 600);
+			continue;
+
+		default:
+			DRM_ERROR("invalid native reply %#04x\n", msg->reply);
+			return -EREMOTEIO;
+		}
+
+		switch (msg->reply & DP_AUX_I2C_REPLY_MASK) {
+		case DP_AUX_I2C_REPLY_ACK:
+			/*
+			 * Both native ACK and I2C ACK replies received. We
+			 * can assume the transfer was successful.
+			 */
+			return 0;
+
+		case DP_AUX_I2C_REPLY_NACK:
+			DRM_DEBUG_KMS("I2C nack\n");
+			return -EREMOTEIO;
+
+		case DP_AUX_I2C_REPLY_DEFER:
+			DRM_DEBUG_KMS("I2C defer\n");
+			usleep_range(400, 500);
+			continue;
+
+		default:
+			DRM_ERROR("invalid I2C reply %#04x\n", msg->reply);
+			return -EREMOTEIO;
+		}
+	}
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EREMOTEIO;
+}
+
+static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+			   int num)
+{
+	struct drm_dp_aux *aux = adapter->algo_data;
+	unsigned int i, j;
+
+	for (i = 0; i < num; i++) {
+		struct drm_dp_aux_msg msg;
+		int err;
+
+		/*
+		 * Many hardware implementations support FIFOs larger than a
+		 * single byte, but it has been empirically determined that
+		 * transferring data in larger chunks can actually lead to
+		 * decreased performance. Therefore each message is simply
+		 * transferred byte-by-byte.
+		 */
+		for (j = 0; j < msgs[i].len; j++) {
+			memset(&msg, 0, sizeof(msg));
+			msg.address = msgs[i].addr;
+
+			msg.request = (msgs[i].flags & I2C_M_RD) ?
+					DP_AUX_I2C_READ :
+					DP_AUX_I2C_WRITE;
+
+			/*
+			 * All messages except the last one are middle-of-
+			 * transfer messages.
+			 */
+			if ((i < num - 1) || (j < msgs[i].len - 1))
+				msg.request |= DP_AUX_I2C_MOT;
+
+			msg.buffer = msgs[i].buf + j;
+			msg.size = 1;
+
+			err = drm_dp_i2c_do_msg(aux, &msg);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return num;
+}
+
+static const struct i2c_algorithm drm_dp_i2c_algo = {
+	.functionality = drm_dp_i2c_functionality,
+	.master_xfer = drm_dp_i2c_xfer,
+};
+
+/**
+ * drm_dp_aux_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
+ * @aux: DisplayPort AUX channel
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux)
+{
+	aux->ddc.algo = &drm_dp_i2c_algo;
+	aux->ddc.algo_data = aux;
+	aux->ddc.retries = 3;
+
+	aux->ddc.class = I2C_CLASS_DDC;
+	aux->ddc.owner = THIS_MODULE;
+	aux->ddc.dev.parent = aux->dev;
+	aux->ddc.dev.of_node = aux->dev->of_node;
+
+	strncpy(aux->ddc.name, dev_name(aux->dev), sizeof(aux->ddc.name));
+
+	return i2c_add_adapter(&aux->ddc);
+}
+EXPORT_SYMBOL(drm_dp_aux_register_i2c_bus);
+
+/**
+ * drm_dp_aux_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
+ * @aux: DisplayPort AUX channel
+ */
+void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux)
+{
+	i2c_del_adapter(&aux->ddc);
+}
+EXPORT_SYMBOL(drm_dp_aux_unregister_i2c_bus);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 98a03639b413..d99df15a78bc 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1136,7 +1136,7 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
 	return count;
 }
 
-static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
+struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
 {
 	struct drm_display_mode *mode;
 
@@ -1149,6 +1149,7 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_conn
 	}
 	return NULL;
 }
+EXPORT_SYMBOL(drm_has_preferred_mode);
 
 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 {
@@ -1157,7 +1158,7 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 	return cmdline_mode->specified;
 }
 
-static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
+struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
 						      int width, int height)
 {
 	struct drm_cmdline_mode *cmdline_mode;
@@ -1197,6 +1198,7 @@ create_mode:
 	list_add(&mode->head, &fb_helper_conn->connector->modes);
 	return mode;
 }
+EXPORT_SYMBOL(drm_pick_cmdline_mode);
 
 static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
 {
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7f2af9aca038..309023f12d7f 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -319,7 +319,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 			pci_dev_put(pci_dev);
 		}
 		if (!dev->hose) {
-			struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+			struct pci_bus *b = list_entry(pci_root_buses.next,
+				struct pci_bus, node);
 			if (b)
 				dev->hose = b->sysdata;
 		}
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 56805c39c906..bb516fdd195d 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -471,7 +471,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
 	get_dma_buf(dma_buf);
 
 	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
-	if (IS_ERR_OR_NULL(sgt)) {
+	if (IS_ERR(sgt)) {
 		ret = PTR_ERR(sgt);
 		goto fail_detach;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 59827cc5e770..c786cd4f457b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -224,7 +224,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 	get_dma_buf(dma_buf);
 
 	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
-	if (IS_ERR_OR_NULL(sgt)) {
+	if (IS_ERR(sgt)) {
 		ret = PTR_ERR(sgt);
 		goto err_buf_detach;
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 0eaf5a27e120..a8f9dba2a816 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -237,7 +237,6 @@ struct drm_exynos_file_private {
  *	otherwise default one.
  * @da_space_size: size of device address space.
  *	if 0 then default value is used for it.
- * @da_space_order: order to device address space.
  */
 struct exynos_drm_private {
 	struct drm_fb_helper *fb_helper;
@@ -255,7 +254,6 @@ struct exynos_drm_private {
 
 	unsigned long da_start;
 	unsigned long da_space_size;
-	unsigned long da_space_order;
 };
 
 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index fb8db0378274..b32b291f88ff 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -36,12 +36,10 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
 		priv->da_start = EXYNOS_DEV_ADDR_START;
 	if (!priv->da_space_size)
 		priv->da_space_size = EXYNOS_DEV_ADDR_SIZE;
-	if (!priv->da_space_order)
-		priv->da_space_order = EXYNOS_DEV_ADDR_ORDER;
 
 	mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
-						priv->da_space_size,
-						priv->da_space_order);
+						priv->da_space_size);
+
 	if (IS_ERR(mapping))
 		return PTR_ERR(mapping);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index 598e60f57d4b..72376d41c512 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -14,7 +14,6 @@
 
 #define EXYNOS_DEV_ADDR_START	0x20000000
 #define EXYNOS_DEV_ADDR_SIZE	0x40000000
-#define EXYNOS_DEV_ADDR_ORDER	0x0
 
 #ifdef CONFIG_DRM_EXYNOS_IOMMU
 
diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c
index 49bac41beefb..c3e67ba94446 100644
--- a/drivers/gpu/drm/gma500/mmu.c
+++ b/drivers/gpu/drm/gma500/mmu.c
@@ -520,7 +520,7 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
 
 	driver->has_clflush = 0;
 
-	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+	if (boot_cpu_has(X86_FEATURE_CLFLUSH)) {
 		uint32_t tfms, misc, cap0, cap4, clflush_size;
 
 		/*
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index faa77f543a07..48af5cac1902 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -19,6 +19,8 @@
 
 #include <linux/hdmi.h>
 #include <linux/module.h>
+#include <linux/irq.h>
+#include <sound/asoundef.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
@@ -30,6 +32,7 @@
 
 struct tda998x_priv {
 	struct i2c_client *cec;
+	struct i2c_client *hdmi;
 	uint16_t rev;
 	uint8_t current_page;
 	int dpms;
@@ -38,6 +41,10 @@ struct tda998x_priv {
 	u8 vip_cntrl_1;
 	u8 vip_cntrl_2;
 	struct tda998x_encoder_params params;
+
+	wait_queue_head_t wq_edid;
+	volatile int wq_edid_wait;
+	struct drm_encoder *encoder;
 };
 
 #define to_tda998x_priv(x)  ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -120,6 +127,8 @@ struct tda998x_priv {
 # define VIP_CNTRL_5_CKCASE       (1 << 0)
 # define VIP_CNTRL_5_SP_CNT(x)    (((x) & 3) << 1)
 #define REG_MUX_AP                REG(0x00, 0x26)     /* read/write */
+# define MUX_AP_SELECT_I2S	  0x64
+# define MUX_AP_SELECT_SPDIF	  0x40
 #define REG_MUX_VP_VIP_OUT        REG(0x00, 0x27)     /* read/write */
 #define REG_MAT_CONTRL            REG(0x00, 0x80)     /* write */
 # define MAT_CONTRL_MAT_SC(x)     (((x) & 3) << 0)
@@ -197,10 +206,11 @@ struct tda998x_priv {
 #define REG_I2S_FORMAT            REG(0x00, 0xfc)     /* read/write */
 # define I2S_FORMAT(x)            (((x) & 3) << 0)
 #define REG_AIP_CLKSEL            REG(0x00, 0xfd)     /* write */
-# define AIP_CLKSEL_FS(x)         (((x) & 3) << 0)
-# define AIP_CLKSEL_CLK_POL(x)    (((x) & 1) << 2)
-# define AIP_CLKSEL_AIP(x)        (((x) & 7) << 3)
-
+# define AIP_CLKSEL_AIP_SPDIF	  (0 << 3)
+# define AIP_CLKSEL_AIP_I2S	  (1 << 3)
+# define AIP_CLKSEL_FS_ACLK	  (0 << 0)
+# define AIP_CLKSEL_FS_MCLK	  (1 << 0)
+# define AIP_CLKSEL_FS_FS64SPDIF  (2 << 0)
 
 /* Page 02h: PLL settings */
 #define REG_PLL_SERIAL_1          REG(0x02, 0x00)     /* read/write */
@@ -304,11 +314,16 @@ struct tda998x_priv {
 
 /* CEC registers: (not paged)
  */
+#define REG_CEC_INTSTATUS	  0xee		      /* read */
+# define CEC_INTSTATUS_CEC	  (1 << 0)
+# define CEC_INTSTATUS_HDMI	  (1 << 1)
 #define REG_CEC_FRO_IM_CLK_CTRL   0xfb                /* read/write */
 # define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
 # define CEC_FRO_IM_CLK_CTRL_ENA_OTP   (1 << 6)
 # define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
 # define CEC_FRO_IM_CLK_CTRL_FRO_DIV   (1 << 0)
+#define REG_CEC_RXSHPDINTENA	  0xfc		      /* read/write */
+#define REG_CEC_RXSHPDINT	  0xfd		      /* read */
 #define REG_CEC_RXSHPDLEV         0xfe                /* read */
 # define CEC_RXSHPDLEV_RXSENS     (1 << 0)
 # define CEC_RXSHPDLEV_HPD        (1 << 1)
@@ -328,21 +343,21 @@ struct tda998x_priv {
 #define TDA19988                  0x0301
 
 static void
-cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
+cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val)
 {
-	struct i2c_client *client = to_tda998x_priv(encoder)->cec;
+	struct i2c_client *client = priv->cec;
 	uint8_t buf[] = {addr, val};
 	int ret;
 
-	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	ret = i2c_master_send(client, buf, sizeof(buf));
 	if (ret < 0)
 		dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
 }
 
 static uint8_t
-cec_read(struct drm_encoder *encoder, uint8_t addr)
+cec_read(struct tda998x_priv *priv, uint8_t addr)
 {
-	struct i2c_client *client = to_tda998x_priv(encoder)->cec;
+	struct i2c_client *client = priv->cec;
 	uint8_t val;
 	int ret;
 
@@ -361,32 +376,36 @@ fail:
 	return 0;
 }
 
-static void
-set_page(struct drm_encoder *encoder, uint16_t reg)
+static int
+set_page(struct tda998x_priv *priv, uint16_t reg)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
 	if (REG2PAGE(reg) != priv->current_page) {
-		struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+		struct i2c_client *client = priv->hdmi;
 		uint8_t buf[] = {
 				REG_CURPAGE, REG2PAGE(reg)
 		};
 		int ret = i2c_master_send(client, buf, sizeof(buf));
-		if (ret < 0)
-			dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret);
+		if (ret < 0) {
+			dev_err(&client->dev, "setpage %04x err %d\n",
+					reg, ret);
+			return ret;
+		}
 
 		priv->current_page = REG2PAGE(reg);
 	}
+	return 0;
 }
 
 static int
-reg_read_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
+reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt)
 {
-	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct i2c_client *client = priv->hdmi;
 	uint8_t addr = REG2ADDR(reg);
 	int ret;
 
-	set_page(encoder, reg);
+	ret = set_page(priv, reg);
+	if (ret < 0)
+		return ret;
 
 	ret = i2c_master_send(client, &addr, sizeof(addr));
 	if (ret < 0)
@@ -404,100 +423,147 @@ fail:
 }
 
 static void
-reg_write_range(struct drm_encoder *encoder, uint16_t reg, uint8_t *p, int cnt)
+reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt)
 {
-	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct i2c_client *client = priv->hdmi;
 	uint8_t buf[cnt+1];
 	int ret;
 
 	buf[0] = REG2ADDR(reg);
 	memcpy(&buf[1], p, cnt);
 
-	set_page(encoder, reg);
+	ret = set_page(priv, reg);
+	if (ret < 0)
+		return;
 
 	ret = i2c_master_send(client, buf, cnt + 1);
 	if (ret < 0)
 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
 }
 
-static uint8_t
-reg_read(struct drm_encoder *encoder, uint16_t reg)
+static int
+reg_read(struct tda998x_priv *priv, uint16_t reg)
 {
 	uint8_t val = 0;
-	reg_read_range(encoder, reg, &val, sizeof(val));
+	int ret;
+
+	ret = reg_read_range(priv, reg, &val, sizeof(val));
+	if (ret < 0)
+		return ret;
 	return val;
 }
 
 static void
-reg_write(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
 {
-	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct i2c_client *client = priv->hdmi;
 	uint8_t buf[] = {REG2ADDR(reg), val};
 	int ret;
 
-	set_page(encoder, reg);
+	ret = set_page(priv, reg);
+	if (ret < 0)
+		return;
 
-	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	ret = i2c_master_send(client, buf, sizeof(buf));
 	if (ret < 0)
 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
 }
 
 static void
-reg_write16(struct drm_encoder *encoder, uint16_t reg, uint16_t val)
+reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val)
 {
-	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct i2c_client *client = priv->hdmi;
 	uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
 	int ret;
 
-	set_page(encoder, reg);
+	ret = set_page(priv, reg);
+	if (ret < 0)
+		return;
 
-	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	ret = i2c_master_send(client, buf, sizeof(buf));
 	if (ret < 0)
 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
 }
 
 static void
-reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
 {
-	reg_write(encoder, reg, reg_read(encoder, reg) | val);
+	int old_val;
+
+	old_val = reg_read(priv, reg);
+	if (old_val >= 0)
+		reg_write(priv, reg, old_val | val);
 }
 
 static void
-reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
 {
-	reg_write(encoder, reg, reg_read(encoder, reg) & ~val);
+	int old_val;
+
+	old_val = reg_read(priv, reg);
+	if (old_val >= 0)
+		reg_write(priv, reg, old_val & ~val);
 }
 
 static void
-tda998x_reset(struct drm_encoder *encoder)
+tda998x_reset(struct tda998x_priv *priv)
 {
 	/* reset audio and i2c master: */
-	reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
+	reg_write(priv, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
 	msleep(50);
-	reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
+	reg_write(priv, REG_SOFTRESET, 0);
 	msleep(50);
 
 	/* reset transmitter: */
-	reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
-	reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+	reg_set(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+	reg_clear(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
 
 	/* PLL registers common configuration */
-	reg_write(encoder, REG_PLL_SERIAL_1, 0x00);
-	reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
-	reg_write(encoder, REG_PLL_SERIAL_3, 0x00);
-	reg_write(encoder, REG_SERIALIZER,   0x00);
-	reg_write(encoder, REG_BUFFER_OUT,   0x00);
-	reg_write(encoder, REG_PLL_SCG1,     0x00);
-	reg_write(encoder, REG_AUDIO_DIV,    AUDIO_DIV_SERCLK_8);
-	reg_write(encoder, REG_SEL_CLK,      SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
-	reg_write(encoder, REG_PLL_SCGN1,    0xfa);
-	reg_write(encoder, REG_PLL_SCGN2,    0x00);
-	reg_write(encoder, REG_PLL_SCGR1,    0x5b);
-	reg_write(encoder, REG_PLL_SCGR2,    0x00);
-	reg_write(encoder, REG_PLL_SCG2,     0x10);
+	reg_write(priv, REG_PLL_SERIAL_1, 0x00);
+	reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
+	reg_write(priv, REG_PLL_SERIAL_3, 0x00);
+	reg_write(priv, REG_SERIALIZER,   0x00);
+	reg_write(priv, REG_BUFFER_OUT,   0x00);
+	reg_write(priv, REG_PLL_SCG1,     0x00);
+	reg_write(priv, REG_AUDIO_DIV,    AUDIO_DIV_SERCLK_8);
+	reg_write(priv, REG_SEL_CLK,      SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+	reg_write(priv, REG_PLL_SCGN1,    0xfa);
+	reg_write(priv, REG_PLL_SCGN2,    0x00);
+	reg_write(priv, REG_PLL_SCGR1,    0x5b);
+	reg_write(priv, REG_PLL_SCGR2,    0x00);
+	reg_write(priv, REG_PLL_SCG2,     0x10);
 
 	/* Write the default value MUX register */
-	reg_write(encoder, REG_MUX_VP_VIP_OUT, 0x24);
+	reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
+}
+
+/*
+ * only 2 interrupts may occur: screen plug/unplug and EDID read
+ */
+static irqreturn_t tda998x_irq_thread(int irq, void *data)
+{
+	struct tda998x_priv *priv = data;
+	u8 sta, cec, lvl, flag0, flag1, flag2;
+
+	if (!priv)
+		return IRQ_HANDLED;
+	sta = cec_read(priv, REG_CEC_INTSTATUS);
+	cec = cec_read(priv, REG_CEC_RXSHPDINT);
+	lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
+	flag0 = reg_read(priv, REG_INT_FLAGS_0);
+	flag1 = reg_read(priv, REG_INT_FLAGS_1);
+	flag2 = reg_read(priv, REG_INT_FLAGS_2);
+	DRM_DEBUG_DRIVER(
+		"tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
+		sta, cec, lvl, flag0, flag1, flag2);
+	if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
+		priv->wq_edid_wait = 0;
+		wake_up(&priv->wq_edid);
+	} else if (cec != 0) {			/* HPD change */
+		if (priv->encoder && priv->encoder->dev)
+			drm_helper_hpd_irq_event(priv->encoder->dev);
+	}
+	return IRQ_HANDLED;
 }
 
 static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
@@ -513,91 +579,88 @@ static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
 #define PB(x) (HB(2) + 1 + (x))
 
 static void
-tda998x_write_if(struct drm_encoder *encoder, uint8_t bit, uint16_t addr,
+tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr,
 		 uint8_t *buf, size_t size)
 {
 	buf[PB(0)] = tda998x_cksum(buf, size);
 
-	reg_clear(encoder, REG_DIP_IF_FLAGS, bit);
-	reg_write_range(encoder, addr, buf, size);
-	reg_set(encoder, REG_DIP_IF_FLAGS, bit);
+	reg_clear(priv, REG_DIP_IF_FLAGS, bit);
+	reg_write_range(priv, addr, buf, size);
+	reg_set(priv, REG_DIP_IF_FLAGS, bit);
 }
 
 static void
-tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
+tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p)
 {
-	uint8_t buf[PB(5) + 1];
+	u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1];
 
 	memset(buf, 0, sizeof(buf));
-	buf[HB(0)] = 0x84;
+	buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO;
 	buf[HB(1)] = 0x01;
-	buf[HB(2)] = 10;
+	buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE;
 	buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
 	buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
 	buf[PB(4)] = p->audio_frame[4];
 	buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
 
-	tda998x_write_if(encoder, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
+	tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
 			 sizeof(buf));
 }
 
 static void
-tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
+tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
 {
-	uint8_t buf[PB(13) + 1];
+	u8 buf[PB(HDMI_AVI_INFOFRAME_SIZE) + 1];
 
 	memset(buf, 0, sizeof(buf));
-	buf[HB(0)] = 0x82;
+	buf[HB(0)] = HDMI_INFOFRAME_TYPE_AVI;
 	buf[HB(1)] = 0x02;
-	buf[HB(2)] = 13;
+	buf[HB(2)] = HDMI_AVI_INFOFRAME_SIZE;
 	buf[PB(1)] = HDMI_SCAN_MODE_UNDERSCAN;
+	buf[PB(2)] = HDMI_ACTIVE_ASPECT_PICTURE;
 	buf[PB(3)] = HDMI_QUANTIZATION_RANGE_FULL << 2;
 	buf[PB(4)] = drm_match_cea_mode(mode);
 
-	tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
+	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
 			 sizeof(buf));
 }
 
-static void tda998x_audio_mute(struct drm_encoder *encoder, bool on)
+static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
 {
 	if (on) {
-		reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
-		reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
-		reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+		reg_set(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
+		reg_clear(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
+		reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
 	} else {
-		reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+		reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
 	}
 }
 
 static void
-tda998x_configure_audio(struct drm_encoder *encoder,
+tda998x_configure_audio(struct tda998x_priv *priv,
 		struct drm_display_mode *mode, struct tda998x_encoder_params *p)
 {
-	uint8_t buf[6], clksel_aip, clksel_fs, ca_i2s, cts_n, adiv;
+	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv;
 	uint32_t n;
 
 	/* Enable audio ports */
-	reg_write(encoder, REG_ENA_AP, p->audio_cfg);
-	reg_write(encoder, REG_ENA_ACLK, p->audio_clk_cfg);
+	reg_write(priv, REG_ENA_AP, p->audio_cfg);
+	reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
 
 	/* Set audio input source */
 	switch (p->audio_format) {
 	case AFMT_SPDIF:
-		reg_write(encoder, REG_MUX_AP, 0x40);
-		clksel_aip = AIP_CLKSEL_AIP(0);
-		/* FS64SPDIF */
-		clksel_fs = AIP_CLKSEL_FS(2);
+		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
+		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
+		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
-		ca_i2s = 0;
 		break;
 
 	case AFMT_I2S:
-		reg_write(encoder, REG_MUX_AP, 0x64);
-		clksel_aip = AIP_CLKSEL_AIP(1);
-		/* ACLK */
-		clksel_fs = AIP_CLKSEL_FS(0);
+		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
+		clksel_aip = AIP_CLKSEL_AIP_I2S;
+		clksel_fs = AIP_CLKSEL_FS_ACLK;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
-		ca_i2s = CA_I2S_CA_I2S(0);
 		break;
 
 	default:
@@ -605,12 +668,10 @@ tda998x_configure_audio(struct drm_encoder *encoder,
 		return;
 	}
 
-	reg_write(encoder, REG_AIP_CLKSEL, clksel_aip);
-	reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT);
-
-	/* Enable automatic CTS generation */
-	reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_ACR_MAN);
-	reg_write(encoder, REG_CTS_N, cts_n);
+	reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
+	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
+					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
+	reg_write(priv, REG_CTS_N, cts_n);
 
 	/*
 	 * Audio input somehow depends on HDMI line rate which is
@@ -619,11 +680,15 @@ tda998x_configure_audio(struct drm_encoder *encoder,
 	 * There is no detailed info in the datasheet, so we just
 	 * assume 100MHz requires larger divider.
 	 */
+	adiv = AUDIO_DIV_SERCLK_8;
 	if (mode->clock > 100000)
-		adiv = AUDIO_DIV_SERCLK_16;
-	else
-		adiv = AUDIO_DIV_SERCLK_8;
-	reg_write(encoder, REG_AUDIO_DIV, adiv);
+		adiv++;			/* AUDIO_DIV_SERCLK_16 */
+
+	/* S/PDIF asks for a larger divider */
+	if (p->audio_format == AFMT_SPDIF)
+		adiv++;			/* AUDIO_DIV_SERCLK_16 or _32 */
+
+	reg_write(priv, REG_AUDIO_DIV, adiv);
 
 	/*
 	 * This is the approximate value of N, which happens to be
@@ -638,28 +703,29 @@ tda998x_configure_audio(struct drm_encoder *encoder,
 	buf[3] = n;
 	buf[4] = n >> 8;
 	buf[5] = n >> 16;
-	reg_write_range(encoder, REG_ACR_CTS_0, buf, 6);
+	reg_write_range(priv, REG_ACR_CTS_0, buf, 6);
 
 	/* Set CTS clock reference */
-	reg_write(encoder, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
+	reg_write(priv, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
 
 	/* Reset CTS generator */
-	reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
-	reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
 
 	/* Write the channel status */
-	buf[0] = 0x04;
+	buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
 	buf[1] = 0x00;
-	buf[2] = 0x00;
-	buf[3] = 0xf1;
-	reg_write_range(encoder, REG_CH_STAT_B(0), buf, 4);
+	buf[2] = IEC958_AES3_CON_FS_NOTID;
+	buf[3] = IEC958_AES4_CON_ORIGFS_NOTID |
+			IEC958_AES4_CON_MAX_WORDLEN_24;
+	reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
 
-	tda998x_audio_mute(encoder, true);
-	mdelay(20);
-	tda998x_audio_mute(encoder, false);
+	tda998x_audio_mute(priv, true);
+	msleep(20);
+	tda998x_audio_mute(priv, false);
 
 	/* Write the audio information packet */
-	tda998x_write_aif(encoder, p);
+	tda998x_write_aif(priv, p);
 }
 
 /* DRM encoder functions */
@@ -701,19 +767,19 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		/* enable video ports, audio will be enabled later */
-		reg_write(encoder, REG_ENA_VP_0, 0xff);
-		reg_write(encoder, REG_ENA_VP_1, 0xff);
-		reg_write(encoder, REG_ENA_VP_2, 0xff);
+		reg_write(priv, REG_ENA_VP_0, 0xff);
+		reg_write(priv, REG_ENA_VP_1, 0xff);
+		reg_write(priv, REG_ENA_VP_2, 0xff);
 		/* set muxing after enabling ports: */
-		reg_write(encoder, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
-		reg_write(encoder, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
-		reg_write(encoder, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
+		reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
+		reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
+		reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
 		break;
 	case DRM_MODE_DPMS_OFF:
 		/* disable video ports */
-		reg_write(encoder, REG_ENA_VP_0, 0x00);
-		reg_write(encoder, REG_ENA_VP_1, 0x00);
-		reg_write(encoder, REG_ENA_VP_2, 0x00);
+		reg_write(priv, REG_ENA_VP_0, 0x00);
+		reg_write(priv, REG_ENA_VP_1, 0x00);
+		reg_write(priv, REG_ENA_VP_2, 0x00);
 		break;
 	}
 
@@ -831,110 +897,110 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 	}
 
 	/* mute the audio FIFO: */
-	reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
 
 	/* set HDMI HDCP mode off: */
-	reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
-	reg_clear(encoder, REG_TX33, TX33_HDMI);
+	reg_write(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+	reg_clear(priv, REG_TX33, TX33_HDMI);
+	reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
 
-	reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
 	/* no pre-filter or interpolator: */
-	reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
+	reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
 			HVF_CNTRL_0_INTPOL(0));
-	reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
-	reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
+	reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
+	reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
 			VIP_CNTRL_4_BLC(0));
-	reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
 
-	reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
-	reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
-	reg_write(encoder, REG_SERIALIZER, 0);
-	reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
+	reg_clear(priv, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
+	reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR |
+					  PLL_SERIAL_3_SRL_DE);
+	reg_write(priv, REG_SERIALIZER, 0);
+	reg_write(priv, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
 
 	/* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
 	rep = 0;
-	reg_write(encoder, REG_RPT_CNTRL, 0);
-	reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
+	reg_write(priv, REG_RPT_CNTRL, 0);
+	reg_write(priv, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
 			SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
 
-	reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
+	reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
 			PLL_SERIAL_2_SRL_PR(rep));
 
 	/* set color matrix bypass flag: */
-	reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP);
+	reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
+				MAT_CONTRL_MAT_SC(1));
 
 	/* set BIAS tmds value: */
-	reg_write(encoder, REG_ANA_GENERAL, 0x09);
-
-	reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
+	reg_write(priv, REG_ANA_GENERAL, 0x09);
 
 	/*
 	 * Sync on rising HSYNC/VSYNC
 	 */
-	reg_write(encoder, REG_VIP_CNTRL_3, 0);
-	reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS);
+	reg = VIP_CNTRL_3_SYNC_HS;
 
 	/*
 	 * TDA19988 requires high-active sync at input stage,
 	 * so invert low-active sync provided by master encoder here
 	 */
 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-		reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
+		reg |= VIP_CNTRL_3_H_TGL;
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-		reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
+		reg |= VIP_CNTRL_3_V_TGL;
+	reg_write(priv, REG_VIP_CNTRL_3, reg);
+
+	reg_write(priv, REG_VIDFORMAT, 0x00);
+	reg_write16(priv, REG_REFPIX_MSB, ref_pix);
+	reg_write16(priv, REG_REFLINE_MSB, ref_line);
+	reg_write16(priv, REG_NPIX_MSB, n_pix);
+	reg_write16(priv, REG_NLINE_MSB, n_line);
+	reg_write16(priv, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
+	reg_write16(priv, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
+	reg_write16(priv, REG_VS_LINE_END_1_MSB, vs1_line_e);
+	reg_write16(priv, REG_VS_PIX_END_1_MSB, vs1_pix_e);
+	reg_write16(priv, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
+	reg_write16(priv, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
+	reg_write16(priv, REG_VS_LINE_END_2_MSB, vs2_line_e);
+	reg_write16(priv, REG_VS_PIX_END_2_MSB, vs2_pix_e);
+	reg_write16(priv, REG_HS_PIX_START_MSB, hs_pix_s);
+	reg_write16(priv, REG_HS_PIX_STOP_MSB, hs_pix_e);
+	reg_write16(priv, REG_VWIN_START_1_MSB, vwin1_line_s);
+	reg_write16(priv, REG_VWIN_END_1_MSB, vwin1_line_e);
+	reg_write16(priv, REG_VWIN_START_2_MSB, vwin2_line_s);
+	reg_write16(priv, REG_VWIN_END_2_MSB, vwin2_line_e);
+	reg_write16(priv, REG_DE_START_MSB, de_pix_s);
+	reg_write16(priv, REG_DE_STOP_MSB, de_pix_e);
+
+	if (priv->rev == TDA19988) {
+		/* let incoming pixels fill the active space (if any) */
+		reg_write(priv, REG_ENABLE_SPACE, 0x00);
+	}
 
 	/*
 	 * Always generate sync polarity relative to input sync and
 	 * revert input stage toggled sync at output stage
 	 */
-	reg = TBG_CNTRL_1_TGL_EN;
+	reg = TBG_CNTRL_1_DWIN_DIS | TBG_CNTRL_1_TGL_EN;
 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 		reg |= TBG_CNTRL_1_H_TGL;
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		reg |= TBG_CNTRL_1_V_TGL;
-	reg_write(encoder, REG_TBG_CNTRL_1, reg);
-
-	reg_write(encoder, REG_VIDFORMAT, 0x00);
-	reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
-	reg_write16(encoder, REG_REFLINE_MSB, ref_line);
-	reg_write16(encoder, REG_NPIX_MSB, n_pix);
-	reg_write16(encoder, REG_NLINE_MSB, n_line);
-	reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
-	reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
-	reg_write16(encoder, REG_VS_LINE_END_1_MSB, vs1_line_e);
-	reg_write16(encoder, REG_VS_PIX_END_1_MSB, vs1_pix_e);
-	reg_write16(encoder, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
-	reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
-	reg_write16(encoder, REG_VS_LINE_END_2_MSB, vs2_line_e);
-	reg_write16(encoder, REG_VS_PIX_END_2_MSB, vs2_pix_e);
-	reg_write16(encoder, REG_HS_PIX_START_MSB, hs_pix_s);
-	reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_pix_e);
-	reg_write16(encoder, REG_VWIN_START_1_MSB, vwin1_line_s);
-	reg_write16(encoder, REG_VWIN_END_1_MSB, vwin1_line_e);
-	reg_write16(encoder, REG_VWIN_START_2_MSB, vwin2_line_s);
-	reg_write16(encoder, REG_VWIN_END_2_MSB, vwin2_line_e);
-	reg_write16(encoder, REG_DE_START_MSB, de_pix_s);
-	reg_write16(encoder, REG_DE_STOP_MSB, de_pix_e);
-
-	if (priv->rev == TDA19988) {
-		/* let incoming pixels fill the active space (if any) */
-		reg_write(encoder, REG_ENABLE_SPACE, 0x00);
-	}
+	reg_write(priv, REG_TBG_CNTRL_1, reg);
 
 	/* must be last register set: */
-	reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
+	reg_write(priv, REG_TBG_CNTRL_0, 0);
 
 	/* Only setup the info frames if the sink is HDMI */
 	if (priv->is_hdmi_sink) {
 		/* We need to turn HDMI HDCP stuff on to get audio through */
-		reg_clear(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
-		reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
-		reg_set(encoder, REG_TX33, TX33_HDMI);
+		reg &= ~TBG_CNTRL_1_DWIN_DIS;
+		reg_write(priv, REG_TBG_CNTRL_1, reg);
+		reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
+		reg_set(priv, REG_TX33, TX33_HDMI);
 
-		tda998x_write_avi(encoder, adjusted_mode);
+		tda998x_write_avi(priv, adjusted_mode);
 
 		if (priv->params.audio_cfg)
-			tda998x_configure_audio(encoder, adjusted_mode,
+			tda998x_configure_audio(priv, adjusted_mode,
 						&priv->params);
 	}
 }
@@ -943,7 +1009,9 @@ static enum drm_connector_status
 tda998x_encoder_detect(struct drm_encoder *encoder,
 		      struct drm_connector *connector)
 {
-	uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV);
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+	uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV);
+
 	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
 			connector_status_disconnected;
 }
@@ -951,46 +1019,57 @@ tda998x_encoder_detect(struct drm_encoder *encoder,
 static int
 read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
 {
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	uint8_t offset, segptr;
 	int ret, i;
 
-	/* enable EDID read irq: */
-	reg_set(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
-
 	offset = (blk & 1) ? 128 : 0;
 	segptr = blk / 2;
 
-	reg_write(encoder, REG_DDC_ADDR, 0xa0);
-	reg_write(encoder, REG_DDC_OFFS, offset);
-	reg_write(encoder, REG_DDC_SEGM_ADDR, 0x60);
-	reg_write(encoder, REG_DDC_SEGM, segptr);
+	reg_write(priv, REG_DDC_ADDR, 0xa0);
+	reg_write(priv, REG_DDC_OFFS, offset);
+	reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
+	reg_write(priv, REG_DDC_SEGM, segptr);
 
 	/* enable reading EDID: */
-	reg_write(encoder, REG_EDID_CTRL, 0x1);
+	priv->wq_edid_wait = 1;
+	reg_write(priv, REG_EDID_CTRL, 0x1);
 
 	/* flag must be cleared by sw: */
-	reg_write(encoder, REG_EDID_CTRL, 0x0);
+	reg_write(priv, REG_EDID_CTRL, 0x0);
 
 	/* wait for block read to complete: */
-	for (i = 100; i > 0; i--) {
-		uint8_t val = reg_read(encoder, REG_INT_FLAGS_2);
-		if (val & INT_FLAGS_2_EDID_BLK_RD)
-			break;
-		msleep(1);
+	if (priv->hdmi->irq) {
+		i = wait_event_timeout(priv->wq_edid,
+					!priv->wq_edid_wait,
+					msecs_to_jiffies(100));
+		if (i < 0) {
+			dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
+			return i;
+		}
+	} else {
+		for (i = 10; i > 0; i--) {
+			msleep(10);
+			ret = reg_read(priv, REG_INT_FLAGS_2);
+			if (ret < 0)
+				return ret;
+			if (ret & INT_FLAGS_2_EDID_BLK_RD)
+				break;
+		}
 	}
 
-	if (i == 0)
+	if (i == 0) {
+		dev_err(&priv->hdmi->dev, "read edid timeout\n");
 		return -ETIMEDOUT;
+	}
 
-	ret = reg_read_range(encoder, REG_EDID_DATA_0, buf, EDID_LENGTH);
+	ret = reg_read_range(priv, REG_EDID_DATA_0, buf, EDID_LENGTH);
 	if (ret != EDID_LENGTH) {
-		dev_err(encoder->dev->dev, "failed to read edid block %d: %d",
-				blk, ret);
+		dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
+			blk, ret);
 		return ret;
 	}
 
-	reg_clear(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
-
 	return 0;
 }
 
@@ -998,7 +1077,7 @@ static uint8_t *
 do_get_edid(struct drm_encoder *encoder)
 {
 	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-	int j = 0, valid_extensions = 0;
+	int j, valid_extensions = 0;
 	uint8_t *block, *new;
 	bool print_bad_edid = drm_debug & DRM_UT_KMS;
 
@@ -1006,7 +1085,7 @@ do_get_edid(struct drm_encoder *encoder)
 		return NULL;
 
 	if (priv->rev == TDA19988)
-		reg_clear(encoder, REG_TX4, TX4_PD_RAM);
+		reg_clear(priv, REG_TX4, TX4_PD_RAM);
 
 	/* base block fetch */
 	if (read_edid_block(encoder, block, 0))
@@ -1046,14 +1125,14 @@ do_get_edid(struct drm_encoder *encoder)
 
 done:
 	if (priv->rev == TDA19988)
-		reg_set(encoder, REG_TX4, TX4_PD_RAM);
+		reg_set(priv, REG_TX4, TX4_PD_RAM);
 
 	return block;
 
 fail:
 	if (priv->rev == TDA19988)
-		reg_set(encoder, REG_TX4, TX4_PD_RAM);
-	dev_warn(encoder->dev->dev, "failed to read EDID\n");
+		reg_set(priv, REG_TX4, TX4_PD_RAM);
+	dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
 	kfree(block);
 	return NULL;
 }
@@ -1080,7 +1159,13 @@ static int
 tda998x_encoder_create_resources(struct drm_encoder *encoder,
 				struct drm_connector *connector)
 {
-	DBG("");
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+
+	if (priv->hdmi->irq)
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	else
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			DRM_CONNECTOR_POLL_DISCONNECT;
 	return 0;
 }
 
@@ -1099,6 +1184,13 @@ tda998x_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	drm_i2c_encoder_destroy(encoder);
+
+	/* disable all IRQs and free the IRQ handler */
+	cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
+	reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+	if (priv->hdmi->irq)
+		free_irq(priv->hdmi->irq, priv);
+
 	if (priv->cec)
 		i2c_unregister_device(priv->cec);
 	kfree(priv);
@@ -1138,8 +1230,10 @@ tda998x_encoder_init(struct i2c_client *client,
 		    struct drm_device *dev,
 		    struct drm_encoder_slave *encoder_slave)
 {
-	struct drm_encoder *encoder = &encoder_slave->base;
 	struct tda998x_priv *priv;
+	struct device_node *np = client->dev.of_node;
+	u32 video;
+	int rev_lo, rev_hi, ret;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -1150,52 +1244,113 @@ tda998x_encoder_init(struct i2c_client *client,
 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
 	priv->current_page = 0xff;
+	priv->hdmi = client;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
 	if (!priv->cec) {
 		kfree(priv);
 		return -ENODEV;
 	}
+
+	priv->encoder = &encoder_slave->base;
 	priv->dpms = DRM_MODE_DPMS_OFF;
 
 	encoder_slave->slave_priv = priv;
 	encoder_slave->slave_funcs = &tda998x_encoder_funcs;
 
 	/* wake up the device: */
-	cec_write(encoder, REG_CEC_ENAMODS,
+	cec_write(priv, REG_CEC_ENAMODS,
 			CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
 
-	tda998x_reset(encoder);
+	tda998x_reset(priv);
 
 	/* read version: */
-	priv->rev = reg_read(encoder, REG_VERSION_LSB) |
-			reg_read(encoder, REG_VERSION_MSB) << 8;
+	rev_lo = reg_read(priv, REG_VERSION_LSB);
+	rev_hi = reg_read(priv, REG_VERSION_MSB);
+	if (rev_lo < 0 || rev_hi < 0) {
+		ret = rev_lo < 0 ? rev_lo : rev_hi;
+		goto fail;
+	}
+
+	priv->rev = rev_lo | rev_hi << 8;
 
 	/* mask off feature bits: */
 	priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
 
 	switch (priv->rev) {
-	case TDA9989N2:  dev_info(dev->dev, "found TDA9989 n2");  break;
-	case TDA19989:   dev_info(dev->dev, "found TDA19989");    break;
-	case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break;
-	case TDA19988:   dev_info(dev->dev, "found TDA19988");    break;
+	case TDA9989N2:
+		dev_info(&client->dev, "found TDA9989 n2");
+		break;
+	case TDA19989:
+		dev_info(&client->dev, "found TDA19989");
+		break;
+	case TDA19989N2:
+		dev_info(&client->dev, "found TDA19989 n2");
+		break;
+	case TDA19988:
+		dev_info(&client->dev, "found TDA19988");
+		break;
 	default:
-		DBG("found unsupported device: %04x", priv->rev);
+		dev_err(&client->dev, "found unsupported device: %04x\n",
+			priv->rev);
 		goto fail;
 	}
 
 	/* after reset, enable DDC: */
-	reg_write(encoder, REG_DDC_DISABLE, 0x00);
+	reg_write(priv, REG_DDC_DISABLE, 0x00);
 
 	/* set clock on DDC channel: */
-	reg_write(encoder, REG_TX3, 39);
+	reg_write(priv, REG_TX3, 39);
 
 	/* if necessary, disable multi-master: */
 	if (priv->rev == TDA19989)
-		reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
+		reg_set(priv, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
 
-	cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL,
+	cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
 			CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
 
+	/* initialize the optional IRQ */
+	if (client->irq) {
+		int irqf_trigger;
+
+		/* init read EDID waitqueue */
+		init_waitqueue_head(&priv->wq_edid);
+
+		/* clear pending interrupts */
+		reg_read(priv, REG_INT_FLAGS_0);
+		reg_read(priv, REG_INT_FLAGS_1);
+		reg_read(priv, REG_INT_FLAGS_2);
+
+		irqf_trigger =
+			irqd_get_trigger_type(irq_get_irq_data(client->irq));
+		ret = request_threaded_irq(client->irq, NULL,
+					   tda998x_irq_thread,
+					   irqf_trigger | IRQF_ONESHOT,
+					   "tda998x", priv);
+		if (ret) {
+			dev_err(&client->dev,
+				"failed to request IRQ#%u: %d\n",
+				client->irq, ret);
+			goto fail;
+		}
+
+		/* enable HPD irq */
+		cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
+	}
+
+	/* enable EDID read irq: */
+	reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+
+	if (!np)
+		return 0;		/* non-DT */
+
+	/* get the optional video properties */
+	ret = of_property_read_u32(np, "video-ports", &video);
+	if (ret == 0) {
+		priv->vip_cntrl_0 = video >> 16;
+		priv->vip_cntrl_1 = video >> 8;
+		priv->vip_cntrl_2 = video;
+	}
+
 	return 0;
 
 fail:
@@ -1210,6 +1365,14 @@ fail:
 	return -ENXIO;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id tda998x_dt_ids[] = {
+	{ .compatible = "nxp,tda998x", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tda998x_dt_ids);
+#endif
+
 static struct i2c_device_id tda998x_ids[] = {
 	{ "tda998x", 0 },
 	{ }
@@ -1222,6 +1385,7 @@ static struct drm_i2c_encoder_driver tda998x_driver = {
 		.remove = tda998x_remove,
 		.driver = {
 			.name = "tda998x",
+			.of_match_table = of_match_ptr(tda998x_dt_ids),
 		},
 		.id_table = tda998x_ids,
 	},
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 9fd44f5f3b3b..f33902ff2c22 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -14,6 +14,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  i915_gem_gtt.o \
 	  i915_gem_stolen.o \
 	  i915_gem_tiling.o \
+	  i915_params.o \
 	  i915_sysfs.o \
 	  i915_trace_points.o \
 	  i915_ums.o \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b2b46c52294c..d90a70744d93 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -98,7 +98,7 @@ static const char *get_pin_flag(struct drm_i915_gem_object *obj)
 {
 	if (obj->user_pin_count > 0)
 		return "P";
-	else if (obj->pin_count > 0)
+	else if (i915_gem_obj_is_pinned(obj))
 		return "p";
 	else
 		return " ";
@@ -123,6 +123,8 @@ static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
 	struct i915_vma *vma;
+	int pin_count = 0;
+
 	seq_printf(m, "%pK: %s%s%s %8zdKiB %02x %02x %u %u %u%s%s%s",
 		   &obj->base,
 		   get_pin_flag(obj),
@@ -139,8 +141,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 		   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
 	if (obj->base.name)
 		seq_printf(m, " (name: %d)", obj->base.name);
-	if (obj->pin_count)
-		seq_printf(m, " (pinned x %d)", obj->pin_count);
+	list_for_each_entry(vma, &obj->vma_list, vma_link)
+		if (vma->pin_count > 0)
+			pin_count++;
+		seq_printf(m, " (pinned x %d)", pin_count);
 	if (obj->pin_display)
 		seq_printf(m, " (display)");
 	if (obj->fence_reg != I915_FENCE_REG_NONE)
@@ -447,7 +451,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
 
 	total_obj_size = total_gtt_size = count = 0;
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
-		if (list == PINNED_LIST && obj->pin_count == 0)
+		if (list == PINNED_LIST && !i915_gem_obj_is_pinned(obj))
 			continue;
 
 		seq_puts(m, "   ");
@@ -712,8 +716,6 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 		seq_printf(m, "Graphics Interrupt mask:		%08x\n",
 			   I915_READ(GTIMR));
 	}
-	seq_printf(m, "Interrupts received: %d\n",
-		   atomic_read(&dev_priv->irq_received));
 	for_each_ring(ring, dev_priv, i) {
 		if (INTEL_INFO(dev)->gen >= 6) {
 			seq_printf(m,
@@ -1733,6 +1735,17 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int per_file_ctx(int id, void *ptr, void *data)
+{
+	struct i915_hw_context *ctx = ptr;
+	struct seq_file *m = data;
+	struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(ctx);
+
+	ppgtt->debug_dump(ppgtt, m);
+
+	return 0;
+}
+
 static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1762,6 +1775,7 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
+	struct drm_file *file;
 	int i;
 
 	if (INTEL_INFO(dev)->gen == 6)
@@ -1780,6 +1794,20 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 
 		seq_puts(m, "aliasing PPGTT:\n");
 		seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd_offset);
+
+		ppgtt->debug_dump(ppgtt, m);
+	} else
+		return;
+
+	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
+		struct drm_i915_file_private *file_priv = file->driver_priv;
+		struct i915_hw_ppgtt *pvt_ppgtt;
+
+		pvt_ppgtt = ctx_to_ppgtt(file_priv->private_default_ctx);
+		seq_printf(m, "proc: %s\n",
+			   get_pid_task(file->pid, PIDTYPE_PID)->comm);
+		seq_puts(m, "  default context:\n");
+		idr_for_each(&file_priv->context_idr, per_file_ctx, m);
 	}
 	seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
 }
@@ -1892,6 +1920,47 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_sink_crc(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+	struct intel_dp *intel_dp = NULL;
+	int ret;
+	u8 crc[6];
+
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+
+		if (connector->base.dpms != DRM_MODE_DPMS_ON)
+			continue;
+
+		if (!connector->base.encoder)
+			continue;
+
+		encoder = to_intel_encoder(connector->base.encoder);
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+
+		ret = intel_dp_sink_crc(intel_dp, crc);
+		if (ret)
+			goto out;
+
+		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
+			   crc[0], crc[1], crc[2],
+			   crc[3], crc[4], crc[5]);
+		goto out;
+	}
+	ret = -ENODEV;
+out:
+	drm_modeset_unlock_all(dev);
+	return ret;
+}
+
 static int i915_energy_uJ(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = m->private;
@@ -2008,6 +2077,164 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static void intel_seq_print_mode(struct seq_file *m, int tabs,
+				 struct drm_display_mode *mode)
+{
+	int i;
+
+	for (i = 0; i < tabs; i++)
+		seq_putc(m, '\t');
+
+	seq_printf(m, "id %d:\"%s\" freq %d clock %d hdisp %d hss %d hse %d htot %d vdisp %d vss %d vse %d vtot %d type 0x%x flags 0x%x\n",
+		   mode->base.id, mode->name,
+		   mode->vrefresh, mode->clock,
+		   mode->hdisplay, mode->hsync_start,
+		   mode->hsync_end, mode->htotal,
+		   mode->vdisplay, mode->vsync_start,
+		   mode->vsync_end, mode->vtotal,
+		   mode->type, mode->flags);
+}
+
+static void intel_encoder_info(struct seq_file *m,
+			       struct intel_crtc *intel_crtc,
+			       struct intel_encoder *intel_encoder)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct intel_connector *intel_connector;
+	struct drm_encoder *encoder;
+
+	encoder = &intel_encoder->base;
+	seq_printf(m, "\tencoder %d: type: %s, connectors:\n",
+		   encoder->base.id, drm_get_encoder_name(encoder));
+	for_each_connector_on_encoder(dev, encoder, intel_connector) {
+		struct drm_connector *connector = &intel_connector->base;
+		seq_printf(m, "\t\tconnector %d: type: %s, status: %s",
+			   connector->base.id,
+			   drm_get_connector_name(connector),
+			   drm_get_connector_status_name(connector->status));
+		if (connector->status == connector_status_connected) {
+			struct drm_display_mode *mode = &crtc->mode;
+			seq_printf(m, ", mode:\n");
+			intel_seq_print_mode(m, 2, mode);
+		} else {
+			seq_putc(m, '\n');
+		}
+	}
+}
+
+static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct intel_encoder *intel_encoder;
+
+	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
+		   crtc->fb->base.id, crtc->x, crtc->y,
+		   crtc->fb->width, crtc->fb->height);
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		intel_encoder_info(m, intel_crtc, intel_encoder);
+}
+
+static void intel_panel_info(struct seq_file *m, struct intel_panel *panel)
+{
+	struct drm_display_mode *mode = panel->fixed_mode;
+
+	seq_printf(m, "\tfixed mode:\n");
+	intel_seq_print_mode(m, 2, mode);
+}
+
+static void intel_dp_info(struct seq_file *m,
+			  struct intel_connector *intel_connector)
+{
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
+	seq_printf(m, "\taudio support: %s\n", intel_dp->has_audio ? "yes" :
+		   "no");
+	if (intel_encoder->type == INTEL_OUTPUT_EDP)
+		intel_panel_info(m, &intel_connector->panel);
+}
+
+static void intel_hdmi_info(struct seq_file *m,
+			    struct intel_connector *intel_connector)
+{
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
+
+	seq_printf(m, "\taudio support: %s\n", intel_hdmi->has_audio ? "yes" :
+		   "no");
+}
+
+static void intel_lvds_info(struct seq_file *m,
+			    struct intel_connector *intel_connector)
+{
+	intel_panel_info(m, &intel_connector->panel);
+}
+
+static void intel_connector_info(struct seq_file *m,
+				 struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+
+	seq_printf(m, "connector %d: type %s, status: %s\n",
+		   connector->base.id, drm_get_connector_name(connector),
+		   drm_get_connector_status_name(connector->status));
+	if (connector->status == connector_status_connected) {
+		seq_printf(m, "\tname: %s\n", connector->display_info.name);
+		seq_printf(m, "\tphysical dimensions: %dx%dmm\n",
+			   connector->display_info.width_mm,
+			   connector->display_info.height_mm);
+		seq_printf(m, "\tsubpixel order: %s\n",
+			   drm_get_subpixel_order_name(connector->display_info.subpixel_order));
+		seq_printf(m, "\tCEA rev: %d\n",
+			   connector->display_info.cea_rev);
+	}
+	if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+	    intel_encoder->type == INTEL_OUTPUT_EDP)
+		intel_dp_info(m, intel_connector);
+	else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+		intel_hdmi_info(m, intel_connector);
+	else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
+		intel_lvds_info(m, intel_connector);
+
+}
+
+static int i915_display_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;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	drm_modeset_lock_all(dev);
+	seq_printf(m, "CRTC info\n");
+	seq_printf(m, "---------\n");
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		seq_printf(m, "CRTC %d: pipe: %c, active: %s\n",
+			   crtc->base.id, pipe_name(intel_crtc->pipe),
+			   intel_crtc->active ? "yes" : "no");
+		if (intel_crtc->active)
+			intel_crtc_info(m, intel_crtc);
+	}
+
+	seq_printf(m, "\n");
+	seq_printf(m, "Connector info\n");
+	seq_printf(m, "--------------\n");
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		intel_connector_info(m, connector);
+	}
+	drm_modeset_unlock_all(dev);
+
+	return 0;
+}
+
 struct pipe_crc_info {
 	const char *name;
 	struct drm_device *dev;
@@ -2756,6 +2983,174 @@ static const struct file_operations i915_display_crc_ctl_fops = {
 	.write = display_crc_ctl_write
 };
 
+static void wm_latency_show(struct seq_file *m, const uint16_t wm[5])
+{
+	struct drm_device *dev = m->private;
+	int num_levels = IS_HASWELL(dev) || IS_BROADWELL(dev) ? 5 : 4;
+	int level;
+
+	drm_modeset_lock_all(dev);
+
+	for (level = 0; level < num_levels; level++) {
+		unsigned int latency = wm[level];
+
+		/* WM1+ latency values in 0.5us units */
+		if (level > 0)
+			latency *= 5;
+
+		seq_printf(m, "WM%d %u (%u.%u usec)\n",
+			   level, wm[level],
+			   latency / 10, latency % 10);
+	}
+
+	drm_modeset_unlock_all(dev);
+}
+
+static int pri_wm_latency_show(struct seq_file *m, void *data)
+{
+	struct drm_device *dev = m->private;
+
+	wm_latency_show(m, to_i915(dev)->wm.pri_latency);
+
+	return 0;
+}
+
+static int spr_wm_latency_show(struct seq_file *m, void *data)
+{
+	struct drm_device *dev = m->private;
+
+	wm_latency_show(m, to_i915(dev)->wm.spr_latency);
+
+	return 0;
+}
+
+static int cur_wm_latency_show(struct seq_file *m, void *data)
+{
+	struct drm_device *dev = m->private;
+
+	wm_latency_show(m, to_i915(dev)->wm.cur_latency);
+
+	return 0;
+}
+
+static int pri_wm_latency_open(struct inode *inode, struct file *file)
+{
+	struct drm_device *dev = inode->i_private;
+
+	if (!HAS_PCH_SPLIT(dev))
+		return -ENODEV;
+
+	return single_open(file, pri_wm_latency_show, dev);
+}
+
+static int spr_wm_latency_open(struct inode *inode, struct file *file)
+{
+	struct drm_device *dev = inode->i_private;
+
+	if (!HAS_PCH_SPLIT(dev))
+		return -ENODEV;
+
+	return single_open(file, spr_wm_latency_show, dev);
+}
+
+static int cur_wm_latency_open(struct inode *inode, struct file *file)
+{
+	struct drm_device *dev = inode->i_private;
+
+	if (!HAS_PCH_SPLIT(dev))
+		return -ENODEV;
+
+	return single_open(file, cur_wm_latency_show, dev);
+}
+
+static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
+				size_t len, loff_t *offp, uint16_t wm[5])
+{
+	struct seq_file *m = file->private_data;
+	struct drm_device *dev = m->private;
+	uint16_t new[5] = { 0 };
+	int num_levels = IS_HASWELL(dev) || IS_BROADWELL(dev) ? 5 : 4;
+	int level;
+	int ret;
+	char tmp[32];
+
+	if (len >= sizeof(tmp))
+		return -EINVAL;
+
+	if (copy_from_user(tmp, ubuf, len))
+		return -EFAULT;
+
+	tmp[len] = '\0';
+
+	ret = sscanf(tmp, "%hu %hu %hu %hu %hu", &new[0], &new[1], &new[2], &new[3], &new[4]);
+	if (ret != num_levels)
+		return -EINVAL;
+
+	drm_modeset_lock_all(dev);
+
+	for (level = 0; level < num_levels; level++)
+		wm[level] = new[level];
+
+	drm_modeset_unlock_all(dev);
+
+	return len;
+}
+
+
+static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf,
+				    size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_device *dev = m->private;
+
+	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.pri_latency);
+}
+
+static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
+				    size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_device *dev = m->private;
+
+	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.spr_latency);
+}
+
+static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
+				    size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_device *dev = m->private;
+
+	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.cur_latency);
+}
+
+static const struct file_operations i915_pri_wm_latency_fops = {
+	.owner = THIS_MODULE,
+	.open = pri_wm_latency_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = pri_wm_latency_write
+};
+
+static const struct file_operations i915_spr_wm_latency_fops = {
+	.owner = THIS_MODULE,
+	.open = spr_wm_latency_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = spr_wm_latency_write
+};
+
+static const struct file_operations i915_cur_wm_latency_fops = {
+	.owner = THIS_MODULE,
+	.open = cur_wm_latency_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = cur_wm_latency_write
+};
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2929,7 +3324,7 @@ i915_drop_caches_set(void *data, u64 val)
 		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
 			list_for_each_entry_safe(vma, x, &vm->inactive_list,
 						 mm_list) {
-				if (vma->obj->pin_count)
+				if (vma->pin_count)
 					continue;
 
 				ret = i915_vma_unbind(vma);
@@ -2989,6 +3384,7 @@ i915_max_freq_set(void *data, u64 val)
 {
 	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 rp_state_cap, hw_max, hw_min;
 	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
@@ -3007,14 +3403,29 @@ i915_max_freq_set(void *data, u64 val)
 	 */
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
-		dev_priv->rps.max_delay = val;
-		valleyview_set_rps(dev, val);
+
+		hw_max = valleyview_rps_max_freq(dev_priv);
+		hw_min = valleyview_rps_min_freq(dev_priv);
 	} else {
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
-		dev_priv->rps.max_delay = val;
-		gen6_set_rps(dev, val);
+
+		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		hw_max = dev_priv->rps.hw_max;
+		hw_min = (rp_state_cap >> 16) & 0xff;
+	}
+
+	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
+		mutex_unlock(&dev_priv->rps.hw_lock);
+		return -EINVAL;
 	}
 
+	dev_priv->rps.max_delay = val;
+
+	if (IS_VALLEYVIEW(dev))
+		valleyview_set_rps(dev, val);
+	else
+		gen6_set_rps(dev, val);
+
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3054,6 +3465,7 @@ i915_min_freq_set(void *data, u64 val)
 {
 	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 rp_state_cap, hw_max, hw_min;
 	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
@@ -3072,13 +3484,29 @@ i915_min_freq_set(void *data, u64 val)
 	 */
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
-		dev_priv->rps.min_delay = val;
-		valleyview_set_rps(dev, val);
+
+		hw_max = valleyview_rps_max_freq(dev_priv);
+		hw_min = valleyview_rps_min_freq(dev_priv);
 	} else {
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
-		dev_priv->rps.min_delay = val;
-		gen6_set_rps(dev, val);
+
+		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		hw_max = dev_priv->rps.hw_max;
+		hw_min = (rp_state_cap >> 16) & 0xff;
+	}
+
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+		mutex_unlock(&dev_priv->rps.hw_lock);
+		return -EINVAL;
 	}
+
+	dev_priv->rps.min_delay = val;
+
+	if (IS_VALLEYVIEW(dev))
+		valleyview_set_rps(dev, val);
+	else
+		gen6_set_rps(dev, val);
+
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3248,9 +3676,11 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_dpio", i915_dpio_info, 0},
 	{"i915_llc", i915_llc, 0},
 	{"i915_edp_psr_status", i915_edp_psr_status, 0},
+	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_pc8_status", i915_pc8_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
+	{"i915_display_info", i915_display_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -3269,6 +3699,9 @@ static const struct i915_debugfs_files {
 	{"i915_error_state", &i915_error_state_fops},
 	{"i915_next_seqno", &i915_next_seqno_fops},
 	{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
+	{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
+	{"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
+	{"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
 };
 
 void intel_display_crc_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 15a74f979b4b..7688abc83fc0 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -626,9 +626,8 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-	    master_priv->sarea_priv;
+	struct drm_i915_master_private *master_priv;
+	drm_i915_sarea_t *sarea_priv;
 	drm_i915_batchbuffer_t *batch = data;
 	int ret;
 	struct drm_clip_rect *cliprects = NULL;
@@ -636,6 +635,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return -ENODEV;
 
+	master_priv = dev->primary->master->driver_priv;
+	sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
 	if (!dev_priv->dri1.allow_batchbuffer) {
 		DRM_ERROR("Batchbuffer ioctl disabled\n");
 		return -EINVAL;
@@ -682,9 +684,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-	    master_priv->sarea_priv;
+	struct drm_i915_master_private *master_priv;
+	drm_i915_sarea_t *sarea_priv;
 	drm_i915_cmdbuffer_t *cmdbuf = data;
 	struct drm_clip_rect *cliprects = NULL;
 	void *batch_data;
@@ -696,6 +697,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return -ENODEV;
 
+	master_priv = dev->primary->master->driver_priv;
+	sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
 	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 	if (cmdbuf->num_cliprects < 0)
@@ -990,7 +994,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 		value = HAS_WT(dev);
 		break;
 	case I915_PARAM_HAS_ALIASING_PPGTT:
-		value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
+		value = dev_priv->mm.aliasing_ppgtt || USES_FULL_PPGTT(dev);
 		break;
 	case I915_PARAM_HAS_WAIT_TIMEOUT:
 		value = 1;
@@ -1374,7 +1378,7 @@ cleanup_gem:
 	i915_gem_cleanup_ringbuffer(dev);
 	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
-	i915_gem_cleanup_aliasing_ppgtt(dev);
+	WARN_ON(dev_priv->mm.aliasing_ppgtt);
 	drm_mm_takedown(&dev_priv->gtt.base.mm);
 cleanup_power:
 	intel_display_power_put(dev, POWER_DOMAIN_VGA);
@@ -1442,7 +1446,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 
 static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 {
-	const struct intel_device_info *info = dev_priv->info;
+	const struct intel_device_info *info = &dev_priv->info;
 
 #define PRINT_S(name) "%s"
 #define SEP_EMPTY
@@ -1459,6 +1463,58 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 #undef SEP_COMMA
 }
 
+/*
+ * Determine various intel_device_info fields at runtime.
+ *
+ * Use it when either:
+ *   - it's judged too laborious to fill n static structures with the limit
+ *     when a simple if statement does the job,
+ *   - run-time checks (eg read fuse/strap registers) are needed.
+ *
+ * This function needs to be called:
+ *   - after the MMIO has been setup as we are reading registers,
+ *   - after the PCH has been detected,
+ *   - before the first usage of the fields it can tweak.
+ */
+static void intel_device_info_runtime_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_device_info *info;
+
+	info = (struct intel_device_info *)&dev_priv->info;
+
+	info->num_sprites = 1;
+	if (IS_VALLEYVIEW(dev))
+		info->num_sprites = 2;
+
+	if (i915.disable_display) {
+		DRM_INFO("Display disabled (module parameter)\n");
+		info->num_pipes = 0;
+	} else if (info->num_pipes > 0 &&
+		   (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
+		   !IS_VALLEYVIEW(dev)) {
+		u32 fuse_strap = I915_READ(FUSE_STRAP);
+		u32 sfuse_strap = I915_READ(SFUSE_STRAP);
+
+		/*
+		 * SFUSE_STRAP is supposed to have a bit signalling the display
+		 * is fused off. Unfortunately it seems that, at least in
+		 * certain cases, fused off display means that PCH display
+		 * reads don't land anywhere. In that case, we read 0s.
+		 *
+		 * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
+		 * should be set when taking over after the firmware.
+		 */
+		if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
+		    sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
+		    (dev_priv->pch_type == PCH_CPT &&
+		     !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
+			DRM_INFO("Display fused off, disabling\n");
+			info->num_pipes = 0;
+		}
+	}
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1473,7 +1529,7 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	struct drm_i915_private *dev_priv;
-	struct intel_device_info *info;
+	struct intel_device_info *info, *device_info;
 	int ret = 0, mmio_bar, mmio_size;
 	uint32_t aperture_size;
 
@@ -1496,7 +1552,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	dev->dev_private = (void *)dev_priv;
 	dev_priv->dev = dev;
-	dev_priv->info = info;
+
+	/* copy initial configuration to dev_priv->info */
+	device_info = (struct intel_device_info *)&dev_priv->info;
+	*device_info = *info;
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->gpu_error.lock);
@@ -1635,9 +1694,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (!IS_I945G(dev) && !IS_I945GM(dev))
 		pci_enable_msi(dev->pdev);
 
-	dev_priv->num_plane = 1;
-	if (IS_VALLEYVIEW(dev))
-		dev_priv->num_plane = 2;
+	intel_device_info_runtime_init(dev);
 
 	if (INTEL_INFO(dev)->num_pipes) {
 		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
@@ -1776,8 +1833,8 @@ int i915_driver_unload(struct drm_device *dev)
 		i915_gem_free_all_phys_object(dev);
 		i915_gem_cleanup_ringbuffer(dev);
 		i915_gem_context_fini(dev);
+		WARN_ON(dev_priv->mm.aliasing_ppgtt);
 		mutex_unlock(&dev->struct_mutex);
-		i915_gem_cleanup_aliasing_ppgtt(dev);
 		i915_gem_cleanup_stolen(dev);
 
 		if (!I915_NEED_GFX_HWS(dev))
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 04f1f02c4019..08052f3d7c51 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -38,134 +38,30 @@
 #include <linux/module.h>
 #include <drm/drm_crtc_helper.h>
 
-static int i915_modeset __read_mostly = -1;
-module_param_named(modeset, i915_modeset, int, 0400);
-MODULE_PARM_DESC(modeset,
-		"Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, "
-		"1=on, -1=force vga console preference [default])");
-
-unsigned int i915_fbpercrtc __always_unused = 0;
-module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
-
-int i915_panel_ignore_lid __read_mostly = 1;
-module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
-MODULE_PARM_DESC(panel_ignore_lid,
-		"Override lid status (0=autodetect, 1=autodetect disabled [default], "
-		"-1=force lid closed, -2=force lid open)");
-
-unsigned int i915_powersave __read_mostly = 1;
-module_param_named(powersave, i915_powersave, int, 0600);
-MODULE_PARM_DESC(powersave,
-		"Enable powersavings, fbc, downclocking, etc. (default: true)");
-
-int i915_semaphores __read_mostly = -1;
-module_param_named(semaphores, i915_semaphores, int, 0400);
-MODULE_PARM_DESC(semaphores,
-		"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
-
-int i915_enable_rc6 __read_mostly = -1;
-module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400);
-MODULE_PARM_DESC(i915_enable_rc6,
-		"Enable power-saving render C-state 6. "
-		"Different stages can be selected via bitmask values "
-		"(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). "
-		"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
-		"default: -1 (use per-chip default)");
-
-int i915_enable_fbc __read_mostly = -1;
-module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
-MODULE_PARM_DESC(i915_enable_fbc,
-		"Enable frame buffer compression for power savings "
-		"(default: -1 (use per-chip default))");
-
-unsigned int i915_lvds_downclock __read_mostly = 0;
-module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
-MODULE_PARM_DESC(lvds_downclock,
-		"Use panel (LVDS/eDP) downclocking for power savings "
-		"(default: false)");
-
-int i915_lvds_channel_mode __read_mostly;
-module_param_named(lvds_channel_mode, i915_lvds_channel_mode, int, 0600);
-MODULE_PARM_DESC(lvds_channel_mode,
-		 "Specify LVDS channel mode "
-		 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
-
-int i915_panel_use_ssc __read_mostly = -1;
-module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
-MODULE_PARM_DESC(lvds_use_ssc,
-		"Use Spread Spectrum Clock with panels [LVDS/eDP] "
-		"(default: auto from VBT)");
-
-int i915_vbt_sdvo_panel_type __read_mostly = -1;
-module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
-MODULE_PARM_DESC(vbt_sdvo_panel_type,
-		"Override/Ignore selection of SDVO panel mode in the VBT "
-		"(-2=ignore, -1=auto [default], index in VBT BIOS table)");
-
-static bool i915_try_reset __read_mostly = true;
-module_param_named(reset, i915_try_reset, bool, 0600);
-MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
-
-bool i915_enable_hangcheck __read_mostly = true;
-module_param_named(enable_hangcheck, i915_enable_hangcheck, bool, 0644);
-MODULE_PARM_DESC(enable_hangcheck,
-		"Periodically check GPU activity for detecting hangs. "
-		"WARNING: Disabling this can cause system wide hangs. "
-		"(default: true)");
-
-int i915_enable_ppgtt __read_mostly = -1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400);
-MODULE_PARM_DESC(i915_enable_ppgtt,
-		"Enable PPGTT (default: true)");
-
-int i915_enable_psr __read_mostly = 0;
-module_param_named(enable_psr, i915_enable_psr, int, 0600);
-MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)");
-
-unsigned int i915_preliminary_hw_support __read_mostly = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT);
-module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
-MODULE_PARM_DESC(preliminary_hw_support,
-		"Enable preliminary hardware support.");
-
-int i915_disable_power_well __read_mostly = 1;
-module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
-MODULE_PARM_DESC(disable_power_well,
-		 "Disable the power well when possible (default: true)");
-
-int i915_enable_ips __read_mostly = 1;
-module_param_named(enable_ips, i915_enable_ips, int, 0600);
-MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
-
-bool i915_fastboot __read_mostly = 0;
-module_param_named(fastboot, i915_fastboot, bool, 0600);
-MODULE_PARM_DESC(fastboot, "Try to skip unnecessary mode sets at boot time "
-		 "(default: false)");
-
-int i915_enable_pc8 __read_mostly = 1;
-module_param_named(enable_pc8, i915_enable_pc8, int, 0600);
-MODULE_PARM_DESC(enable_pc8, "Enable support for low power package C states (PC8+) (default: true)");
-
-int i915_pc8_timeout __read_mostly = 5000;
-module_param_named(pc8_timeout, i915_pc8_timeout, int, 0600);
-MODULE_PARM_DESC(pc8_timeout, "Number of msecs of idleness required to enter PC8+ (default: 5000)");
-
-bool i915_prefault_disable __read_mostly;
-module_param_named(prefault_disable, i915_prefault_disable, bool, 0600);
-MODULE_PARM_DESC(prefault_disable,
-		"Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
-
 static struct drm_driver driver;
 
+#define GEN_DEFAULT_PIPEOFFSETS \
+	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
+			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
+	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
+			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
+	.dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET }, \
+	.dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET }, \
+	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
+
+
 static const struct intel_device_info intel_i830_info = {
 	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_845g_info = {
 	.gen = 2, .num_pipes = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_i85x_info = {
@@ -174,18 +70,21 @@ static const struct intel_device_info intel_i85x_info = {
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_i865g_info = {
 	.gen = 2, .num_pipes = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_i915g_info = {
 	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 static const struct intel_device_info intel_i915gm_info = {
 	.gen = 3, .is_mobile = 1, .num_pipes = 2,
@@ -194,11 +93,13 @@ static const struct intel_device_info intel_i915gm_info = {
 	.supports_tv = 1,
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 static const struct intel_device_info intel_i945g_info = {
 	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 static const struct intel_device_info intel_i945gm_info = {
 	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
@@ -207,6 +108,7 @@ static const struct intel_device_info intel_i945gm_info = {
 	.supports_tv = 1,
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_i965g_info = {
@@ -214,6 +116,7 @@ static const struct intel_device_info intel_i965g_info = {
 	.has_hotplug = 1,
 	.has_overlay = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_i965gm_info = {
@@ -222,6 +125,7 @@ static const struct intel_device_info intel_i965gm_info = {
 	.has_overlay = 1,
 	.supports_tv = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_g33_info = {
@@ -229,12 +133,14 @@ static const struct intel_device_info intel_g33_info = {
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_overlay = 1,
 	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_g45_info = {
 	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
 	.has_pipe_cxsr = 1, .has_hotplug = 1,
 	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_gm45_info = {
@@ -243,18 +149,21 @@ static const struct intel_device_info intel_gm45_info = {
 	.has_pipe_cxsr = 1, .has_hotplug = 1,
 	.supports_tv = 1,
 	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_pineview_info = {
 	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_overlay = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_ironlake_d_info = {
 	.gen = 5, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
@@ -262,6 +171,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
@@ -270,6 +180,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
 	.has_llc = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
@@ -278,6 +189,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 	.has_fbc = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
 	.has_llc = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 #define GEN7_FEATURES  \
@@ -290,18 +202,21 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 static const struct intel_device_info intel_ivybridge_d_info = {
 	GEN7_FEATURES,
 	.is_ivybridge = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_ivybridge_m_info = {
 	GEN7_FEATURES,
 	.is_ivybridge = 1,
 	.is_mobile = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
 	GEN7_FEATURES,
 	.is_ivybridge = 1,
 	.num_pipes = 0, /* legal, last one wins */
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_valleyview_m_info = {
@@ -312,6 +227,7 @@ static const struct intel_device_info intel_valleyview_m_info = {
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 	.has_fbc = 0, /* legal, last one wins */
 	.has_llc = 0, /* legal, last one wins */
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_valleyview_d_info = {
@@ -321,6 +237,7 @@ static const struct intel_device_info intel_valleyview_d_info = {
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 	.has_fbc = 0, /* legal, last one wins */
 	.has_llc = 0, /* legal, last one wins */
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_haswell_d_info = {
@@ -329,6 +246,7 @@ static const struct intel_device_info intel_haswell_d_info = {
 	.has_ddi = 1,
 	.has_fpga_dbg = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_haswell_m_info = {
@@ -338,6 +256,7 @@ static const struct intel_device_info intel_haswell_m_info = {
 	.has_ddi = 1,
 	.has_fpga_dbg = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_broadwell_d_info = {
@@ -346,6 +265,7 @@ static const struct intel_device_info intel_broadwell_d_info = {
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 static const struct intel_device_info intel_broadwell_m_info = {
@@ -354,6 +274,7 @@ static const struct intel_device_info intel_broadwell_m_info = {
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
 };
 
 /*
@@ -403,7 +324,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 void intel_detect_pch(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct pci_dev *pch;
+	struct pci_dev *pch = NULL;
 
 	/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
 	 * (which really amounts to a PCH but no South Display).
@@ -424,12 +345,9 @@ void intel_detect_pch(struct drm_device *dev)
 	 * all the ISA bridge devices and check for the first match, instead
 	 * of only checking the first one.
 	 */
-	pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-	while (pch) {
-		struct pci_dev *curr = pch;
+	while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
 		if (pch->vendor == PCI_VENDOR_ID_INTEL) {
-			unsigned short id;
-			id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
+			unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
 			dev_priv->pch_id = id;
 
 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
@@ -461,18 +379,16 @@ void intel_detect_pch(struct drm_device *dev)
 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
 				WARN_ON(!IS_HASWELL(dev));
 				WARN_ON(!IS_ULT(dev));
-			} else {
-				goto check_next;
-			}
-			pci_dev_put(pch);
+			} else
+				continue;
+
 			break;
 		}
-check_next:
-		pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
-		pci_dev_put(curr);
 	}
 	if (!pch)
-		DRM_DEBUG_KMS("No PCH found?\n");
+		DRM_DEBUG_KMS("No PCH found.\n");
+
+	pci_dev_put(pch);
 }
 
 bool i915_semaphore_is_enabled(struct drm_device *dev)
@@ -482,12 +398,12 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
 
 	/* Until we get further testing... */
 	if (IS_GEN8(dev)) {
-		WARN_ON(!i915_preliminary_hw_support);
+		WARN_ON(!i915.preliminary_hw_support);
 		return false;
 	}
 
-	if (i915_semaphores >= 0)
-		return i915_semaphores;
+	if (i915.semaphores >= 0)
+		return i915.semaphores;
 
 #ifdef CONFIG_INTEL_IOMMU
 	/* Enable semaphores on SNB when IO remapping is off */
@@ -643,6 +559,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 	/* KMS EnterVT equivalent */
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		intel_init_pch_refclk(dev);
+		drm_mode_config_reset(dev);
 
 		mutex_lock(&dev->struct_mutex);
 
@@ -655,7 +572,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 		intel_modeset_init_hw(dev);
 
 		drm_modeset_lock_all(dev);
-		drm_mode_config_reset(dev);
 		intel_modeset_setup_hw_state(dev, true);
 		drm_modeset_unlock_all(dev);
 
@@ -752,7 +668,7 @@ int i915_reset(struct drm_device *dev)
 	bool simulated;
 	int ret;
 
-	if (!i915_try_reset)
+	if (!i915.reset)
 		return 0;
 
 	mutex_lock(&dev->struct_mutex);
@@ -807,6 +723,17 @@ int i915_reset(struct drm_device *dev)
 
 		drm_irq_uninstall(dev);
 		drm_irq_install(dev);
+
+		/* rps/rc6 re-init is necessary to restore state lost after the
+		 * reset and the re-install of drm irq. Skip for ironlake per
+		 * previous concerns that it doesn't respond well to some forms
+		 * of re-init after reset. */
+		if (INTEL_INFO(dev)->gen > 5) {
+			mutex_lock(&dev->struct_mutex);
+			intel_enable_gt_powersave(dev);
+			mutex_unlock(&dev->struct_mutex);
+		}
+
 		intel_hpd_init(dev);
 	} else {
 		mutex_unlock(&dev->struct_mutex);
@@ -820,7 +747,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct intel_device_info *intel_info =
 		(struct intel_device_info *) ent->driver_data;
 
-	if (IS_PRELIMINARY_HW(intel_info) && !i915_preliminary_hw_support) {
+	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
 		DRM_INFO("This hardware requires preliminary hardware support.\n"
 			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
 		return -ENODEV;
@@ -1051,14 +978,14 @@ static int __init i915_init(void)
 	 * the default behavior.
 	 */
 #if defined(CONFIG_DRM_I915_KMS)
-	if (i915_modeset != 0)
+	if (i915.modeset != 0)
 		driver.driver_features |= DRIVER_MODESET;
 #endif
-	if (i915_modeset == 1)
+	if (i915.modeset == 1)
 		driver.driver_features |= DRIVER_MODESET;
 
 #ifdef CONFIG_VGA_CONSOLE
-	if (vgacon_text_force() && i915_modeset == -1)
+	if (vgacon_text_force() && i915.modeset == -1)
 		driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index df77e20e3c3d..05cfcc163a72 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -58,7 +58,8 @@ enum pipe {
 	PIPE_A = 0,
 	PIPE_B,
 	PIPE_C,
-	I915_MAX_PIPES
+	_PIPE_EDP,
+	I915_MAX_PIPES = _PIPE_EDP
 };
 #define pipe_name(p) ((p) + 'A')
 
@@ -66,7 +67,8 @@ enum transcoder {
 	TRANSCODER_A = 0,
 	TRANSCODER_B,
 	TRANSCODER_C,
-	TRANSCODER_EDP = 0xF,
+	TRANSCODER_EDP,
+	I915_MAX_TRANSCODERS
 };
 #define transcoder_name(t) ((t) + 'A')
 
@@ -77,7 +79,7 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
-#define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A')
+#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites + (s) + 'A')
 
 enum port {
 	PORT_A = 0,
@@ -162,6 +164,10 @@ enum hpd_pin {
 	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
 		if ((intel_encoder)->base.crtc == (__crtc))
 
+#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
+	list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
+		if ((intel_connector)->base.encoder == (__encoder))
+
 struct drm_i915_private;
 
 enum intel_dpll_id {
@@ -295,53 +301,80 @@ struct intel_display_error_state;
 
 struct drm_i915_error_state {
 	struct kref ref;
+	struct timeval time;
+
+	/* Generic register state */
 	u32 eir;
 	u32 pgtbl_er;
 	u32 ier;
 	u32 ccid;
 	u32 derrmr;
 	u32 forcewake;
-	bool waiting[I915_NUM_RINGS];
-	u32 pipestat[I915_MAX_PIPES];
-	u32 tail[I915_NUM_RINGS];
-	u32 head[I915_NUM_RINGS];
-	u32 ctl[I915_NUM_RINGS];
-	u32 ipeir[I915_NUM_RINGS];
-	u32 ipehr[I915_NUM_RINGS];
-	u32 instdone[I915_NUM_RINGS];
-	u32 acthd[I915_NUM_RINGS];
-	u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1];
-	u32 semaphore_seqno[I915_NUM_RINGS][I915_NUM_RINGS - 1];
-	u32 rc_psmi[I915_NUM_RINGS]; /* sleep state */
-	/* our own tracking of ring head and tail */
-	u32 cpu_ring_head[I915_NUM_RINGS];
-	u32 cpu_ring_tail[I915_NUM_RINGS];
 	u32 error; /* gen6+ */
 	u32 err_int; /* gen7 */
-	u32 bbstate[I915_NUM_RINGS];
-	u32 instpm[I915_NUM_RINGS];
-	u32 instps[I915_NUM_RINGS];
-	u32 extra_instdone[I915_NUM_INSTDONE_REG];
-	u32 seqno[I915_NUM_RINGS];
-	u64 bbaddr[I915_NUM_RINGS];
-	u32 fault_reg[I915_NUM_RINGS];
 	u32 done_reg;
-	u32 faddr[I915_NUM_RINGS];
+	u32 gac_eco;
+	u32 gam_ecochk;
+	u32 gab_ctl;
+	u32 gfx_mode;
+	u32 extra_instdone[I915_NUM_INSTDONE_REG];
+	u32 pipestat[I915_MAX_PIPES];
 	u64 fence[I915_MAX_NUM_FENCES];
-	struct timeval time;
+	struct intel_overlay_error_state *overlay;
+	struct intel_display_error_state *display;
+
 	struct drm_i915_error_ring {
 		bool valid;
+		/* Software tracked state */
+		bool waiting;
+		int hangcheck_score;
+		enum intel_ring_hangcheck_action hangcheck_action;
+		int num_requests;
+
+		/* our own tracking of ring head and tail */
+		u32 cpu_ring_head;
+		u32 cpu_ring_tail;
+
+		u32 semaphore_seqno[I915_NUM_RINGS - 1];
+
+		/* Register state */
+		u32 tail;
+		u32 head;
+		u32 ctl;
+		u32 hws;
+		u32 ipeir;
+		u32 ipehr;
+		u32 instdone;
+		u32 acthd;
+		u32 bbstate;
+		u32 instpm;
+		u32 instps;
+		u32 seqno;
+		u64 bbaddr;
+		u32 fault_reg;
+		u32 faddr;
+		u32 rc_psmi; /* sleep state */
+		u32 semaphore_mboxes[I915_NUM_RINGS - 1];
+
 		struct drm_i915_error_object {
 			int page_count;
 			u32 gtt_offset;
 			u32 *pages[0];
-		} *ringbuffer, *batchbuffer, *ctx;
+		} *ringbuffer, *batchbuffer, *ctx, *hws_page;
+
 		struct drm_i915_error_request {
 			long jiffies;
 			u32 seqno;
 			u32 tail;
 		} *requests;
-		int num_requests;
+
+		struct {
+			u32 gfx_mode;
+			union {
+				u64 pdp[4];
+				u32 pp_dir_base;
+			};
+		} vm_info;
 	} ring[I915_NUM_RINGS];
 	struct drm_i915_error_buffer {
 		u32 size;
@@ -358,11 +391,8 @@ struct drm_i915_error_state {
 		s32 ring:4;
 		u32 cache_level:3;
 	} **active_bo, **pinned_bo;
+
 	u32 *active_bo_count, *pinned_bo_count;
-	struct intel_overlay_error_state *overlay;
-	struct intel_display_error_state *display;
-	int hangcheck_score[I915_NUM_RINGS];
-	enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS];
 };
 
 struct intel_connector;
@@ -504,9 +534,16 @@ struct intel_uncore {
 struct intel_device_info {
 	u32 display_mmio_offset;
 	u8 num_pipes:3;
+	u8 num_sprites:2;
 	u8 gen;
 	u8 ring_mask; /* Rings supported by the HW */
 	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
+	/* Register offsets for the various display pipes and transcoders */
+	int pipe_offsets[I915_MAX_TRANSCODERS];
+	int trans_offsets[I915_MAX_TRANSCODERS];
+	int dpll_offsets[I915_MAX_PIPES];
+	int dpll_md_offsets[I915_MAX_PIPES];
+	int palette_offsets[I915_MAX_PIPES];
 };
 
 #undef DEFINE_FLAG
@@ -524,6 +561,57 @@ enum i915_cache_level {
 
 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;
@@ -605,6 +693,8 @@ struct i915_gtt {
 
 struct i915_hw_ppgtt {
 	struct i915_address_space base;
+	struct kref ref;
+	struct drm_mm_node node;
 	unsigned num_pd_entries;
 	union {
 		struct page **pt_pages;
@@ -621,37 +711,12 @@ struct i915_hw_ppgtt {
 		dma_addr_t *pt_dma_addr;
 		dma_addr_t *gen8_pt_dma_addr[4];
 	};
-	int (*enable)(struct drm_device *dev);
-};
-
-/**
- * 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;
 
+	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 {
@@ -676,9 +741,10 @@ struct i915_hw_context {
 	bool is_initialized;
 	uint8_t remap_slice;
 	struct drm_i915_file_private *file_priv;
-	struct intel_ring_buffer *ring;
+	struct intel_ring_buffer *last_ring;
 	struct drm_i915_gem_object *obj;
 	struct i915_ctx_hang_stats hang_stats;
+	struct i915_address_space *vm;
 
 	struct list_head link;
 };
@@ -831,11 +897,7 @@ struct i915_suspend_saved_registers {
 	u32 savePFIT_CONTROL;
 	u32 save_palette_a[256];
 	u32 save_palette_b[256];
-	u32 saveDPFC_CB_BASE;
-	u32 saveFBC_CFB_BASE;
-	u32 saveFBC_LL_BASE;
 	u32 saveFBC_CONTROL;
-	u32 saveFBC_CONTROL2;
 	u32 saveIER;
 	u32 saveIIR;
 	u32 saveIMR;
@@ -905,8 +967,6 @@ struct intel_gen6_power_mgmt {
 	struct work_struct work;
 	u32 pm_iir;
 
-	/* The below variables an all the rps hw state are protected by
-	 * dev->struct mutext. */
 	u8 cur_delay;
 	u8 min_delay;
 	u8 max_delay;
@@ -915,6 +975,9 @@ struct intel_gen6_power_mgmt {
 	u8 rp0_delay;
 	u8 hw_max;
 
+	bool rp_up_masked;
+	bool rp_down_masked;
+
 	int last_adj;
 	enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
 
@@ -1332,7 +1395,7 @@ typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
 
-	const struct intel_device_info *info;
+	const struct intel_device_info info;
 
 	int relative_constants_mode;
 
@@ -1361,8 +1424,6 @@ typedef struct drm_i915_private {
 	drm_dma_handle_t *status_page_dmah;
 	struct resource mch_res;
 
-	atomic_t irq_received;
-
 	/* protects the irq masks */
 	spinlock_t irq_lock;
 
@@ -1379,6 +1440,7 @@ typedef struct drm_i915_private {
 	};
 	u32 gt_irq_mask;
 	u32 pm_irq_mask;
+	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
 	struct work_struct hotplug_work;
 	bool enable_hotplug_processing;
@@ -1394,8 +1456,6 @@ typedef struct drm_i915_private {
 	u32 hpd_event_bits;
 	struct timer_list hotplug_reenable_timer;
 
-	int num_plane;
-
 	struct i915_fbc fbc;
 	struct intel_opregion opregion;
 	struct intel_vbt_data vbt;
@@ -1445,8 +1505,8 @@ typedef struct drm_i915_private {
 
 	struct sdvo_device_mapping sdvo_mappings[2];
 
-	struct drm_crtc *plane_to_crtc_mapping[3];
-	struct drm_crtc *pipe_to_crtc_mapping[3];
+	struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
+	struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
 	wait_queue_head_t pending_flip_queue;
 
 #ifdef CONFIG_DEBUG_FS
@@ -1627,18 +1687,6 @@ struct drm_i915_gem_object {
 	 */
 	unsigned int fence_dirty:1;
 
-	/** 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
-
 	/**
 	 * Is the object at the current location in the gtt mappable and
 	 * fenceable? Used to avoid costly recalculations.
@@ -1751,11 +1799,11 @@ struct drm_i915_file_private {
 	} mm;
 	struct idr context_idr;
 
-	struct i915_ctx_hang_stats hang_stats;
+	struct i915_hw_context *private_default_ctx;
 	atomic_t rps_wait_boost;
 };
 
-#define INTEL_INFO(dev)	(to_i915(dev)->info)
+#define INTEL_INFO(dev)	(&to_i915(dev)->info)
 
 #define IS_I830(dev)		((dev)->pdev->device == 0x3577)
 #define IS_845G(dev)		((dev)->pdev->device == 0x2562)
@@ -1824,7 +1872,11 @@ struct drm_i915_file_private {
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
 #define HAS_HW_CONTEXTS(dev)	(INTEL_INFO(dev)->gen >= 6)
-#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev))
+#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev))
+#define HAS_PPGTT(dev)		(INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) \
+				 && !IS_BROADWELL(dev))
+#define USES_PPGTT(dev)		intel_enable_ppgtt(dev, false)
+#define USES_FULL_PPGTT(dev)	intel_enable_ppgtt(dev, true)
 
 #define HAS_OVERLAY(dev)		(INTEL_INFO(dev)->has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->overlay_needs_physical)
@@ -1887,32 +1939,41 @@ struct drm_i915_file_private {
 
 extern const struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
-extern unsigned int i915_fbpercrtc __always_unused;
-extern int i915_panel_ignore_lid __read_mostly;
-extern unsigned int i915_powersave __read_mostly;
-extern int i915_semaphores __read_mostly;
-extern unsigned int i915_lvds_downclock __read_mostly;
-extern int i915_lvds_channel_mode __read_mostly;
-extern int i915_panel_use_ssc __read_mostly;
-extern int i915_vbt_sdvo_panel_type __read_mostly;
-extern int i915_enable_rc6 __read_mostly;
-extern int i915_enable_fbc __read_mostly;
-extern bool i915_enable_hangcheck __read_mostly;
-extern int i915_enable_ppgtt __read_mostly;
-extern int i915_enable_psr __read_mostly;
-extern unsigned int i915_preliminary_hw_support __read_mostly;
-extern int i915_disable_power_well __read_mostly;
-extern int i915_enable_ips __read_mostly;
-extern bool i915_fastboot __read_mostly;
-extern int i915_enable_pc8 __read_mostly;
-extern int i915_pc8_timeout __read_mostly;
-extern bool i915_prefault_disable __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
 extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
 extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
 
+/* i915_params.c */
+struct i915_params {
+	int modeset;
+	int panel_ignore_lid;
+	unsigned int powersave;
+	int semaphores;
+	unsigned int lvds_downclock;
+	int lvds_channel_mode;
+	int panel_use_ssc;
+	int vbt_sdvo_panel_type;
+	int enable_rc6;
+	int enable_fbc;
+	int enable_ppgtt;
+	int enable_psr;
+	unsigned int preliminary_hw_support;
+	int disable_power_well;
+	int enable_ips;
+	int enable_pc8;
+	int pc8_timeout;
+	int invert_brightness;
+	/* leave bools at the end to not create holes */
+	bool enable_hangcheck;
+	bool fastboot;
+	bool prefault_disable;
+	bool reset;
+	bool disable_display;
+};
+extern struct i915_params i915 __read_mostly;
+
 				/* i915_dma.c */
 void i915_update_dri1_breadcrumb(struct drm_device *dev);
 extern void i915_kernel_lost_context(struct drm_device * dev);
@@ -1945,6 +2006,8 @@ extern void intel_console_resume(struct work_struct *work);
 void i915_queue_hangcheck(struct drm_device *dev);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
+void gen6_set_pm_mask(struct drm_i915_private *dev_priv, u32 pm_iir,
+							int new_delay);
 extern void intel_irq_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
 
@@ -1955,10 +2018,12 @@ extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
 
 void
-i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+		     u32 status_mask);
 
 void
-i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+		      u32 status_mask);
 
 /* i915_gem.c */
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
@@ -2014,17 +2079,19 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			 const struct drm_i915_gem_object_ops *ops);
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 						  size_t size);
+void i915_init_vm(struct drm_i915_private *dev_priv,
+		  struct i915_address_space *vm);
 void i915_gem_free_object(struct drm_gem_object *obj);
 void i915_gem_vma_destroy(struct i915_vma *vma);
 
+#define PIN_MAPPABLE 0x1
+#define PIN_NONBLOCK 0x2
+#define PIN_GLOBAL 0x4
 int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
 				     struct i915_address_space *vm,
 				     uint32_t alignment,
-				     bool map_and_fenceable,
-				     bool nonblocking);
-void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
+				     unsigned flags);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
-int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
 void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
@@ -2186,6 +2253,13 @@ i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
 				  struct i915_address_space *vm);
 
 struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
+static inline bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) {
+	struct i915_vma *vma;
+	list_for_each_entry(vma, &obj->vma_list, vma_link)
+		if (vma->pin_count > 0)
+			return true;
+	return false;
+}
 
 /* Some GGTT VM helpers */
 #define obj_to_ggtt(obj) \
@@ -2217,54 +2291,69 @@ i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
 static inline int __must_check
 i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
 		      uint32_t alignment,
-		      bool map_and_fenceable,
-		      bool nonblocking)
+		      unsigned flags)
 {
-	return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
-				   map_and_fenceable, nonblocking);
+	return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, flags | PIN_GLOBAL);
 }
 
+static inline int
+i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
+{
+	return i915_vma_unbind(i915_gem_obj_to_ggtt(obj));
+}
+
+void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
+
 /* i915_gem_context.c */
+#define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
 int __must_check i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
+void i915_gem_context_reset(struct drm_device *dev);
+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, int to_id);
+			struct drm_file *file, 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)
 {
-	kref_get(&ctx->ref);
+	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
+		kref_get(&ctx->ref);
 }
 
 static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
 {
-	kref_put(&ctx->ref, i915_gem_context_free);
+	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
+		kref_put(&ctx->ref, i915_gem_context_free);
+}
+
+static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
+{
+	return c->id == DEFAULT_CONTEXT_ID;
 }
 
-struct i915_ctx_hang_stats * __must_check
-i915_gem_context_get_hang_stats(struct drm_device *dev,
-				struct drm_file *file,
-				u32 id);
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file);
 int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
 				   struct drm_file *file);
 
-/* i915_gem_gtt.c */
-void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev);
-void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
-			    struct drm_i915_gem_object *obj,
-			    enum i915_cache_level cache_level);
-void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
-			      struct drm_i915_gem_object *obj);
+/* i915_gem_evict.c */
+int __must_check i915_gem_evict_something(struct drm_device *dev,
+					  struct i915_address_space *vm,
+					  int min_size,
+					  unsigned alignment,
+					  unsigned cache_level,
+					  unsigned flags);
+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_bind_object(struct drm_i915_gem_object *obj,
-				enum i915_cache_level cache_level);
-void i915_gem_gtt_unbind_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,
@@ -2275,18 +2364,64 @@ 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);
+static inline bool intel_enable_ppgtt(struct drm_device *dev, bool full)
+{
+	if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
+		return false;
 
+	if (i915.enable_ppgtt == 1 && full)
+		return false;
 
-/* i915_gem_evict.c */
-int __must_check i915_gem_evict_something(struct drm_device *dev,
-					  struct i915_address_space *vm,
-					  int min_size,
-					  unsigned alignment,
-					  unsigned cache_level,
-					  bool mappable,
-					  bool nonblock);
-int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
-int i915_gem_evict_everything(struct drm_device *dev);
+#ifdef CONFIG_INTEL_IOMMU
+	/* Disable ppgtt on SNB if VT-d is on. */
+	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
+		DRM_INFO("Disabling PPGTT because VT-d is on\n");
+		return false;
+	}
+#endif
+
+	if (full)
+		return HAS_PPGTT(dev);
+	else
+		return HAS_ALIASING_PPGTT(dev);
+}
+
+static inline void ppgtt_release(struct kref *kref)
+{
+	struct i915_hw_ppgtt *ppgtt = container_of(kref, struct i915_hw_ppgtt, ref);
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_address_space *vm = &ppgtt->base;
+
+	if (ppgtt == dev_priv->mm.aliasing_ppgtt ||
+	    (list_empty(&vm->active_list) && list_empty(&vm->inactive_list))) {
+		ppgtt->base.cleanup(&ppgtt->base);
+		return;
+	}
+
+	/*
+	 * Make sure vmas are unbound before we take down the drm_mm
+	 *
+	 * FIXME: Proper refcounting should take care of this, this shouldn't be
+	 * needed at all.
+	 */
+	if (!list_empty(&vm->active_list)) {
+		struct i915_vma *vma;
+
+		list_for_each_entry(vma, &vm->active_list, mm_list)
+			if (WARN_ON(list_empty(&vma->vma_link) ||
+				    list_is_singular(&vma->vma_link)))
+				break;
+
+		i915_gem_evict_vm(&ppgtt->base, true);
+	} else {
+		i915_gem_retire_requests(dev);
+		i915_gem_evict_vm(&ppgtt->base, false);
+	}
+
+	ppgtt->base.cleanup(&ppgtt->base);
+}
 
 /* i915_gem_stolen.c */
 int i915_gem_init_stolen(struct drm_device *dev);
@@ -2425,6 +2560,7 @@ extern void intel_modeset_suspend_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
+extern void intel_connector_unregister(struct intel_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_modeset_setup_hw_state(struct drm_device *dev,
 					 bool force_restore);
@@ -2566,4 +2702,31 @@ timespec_to_jiffies_timeout(const struct timespec *value)
 	return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
 }
 
+/*
+ * If you need to wait X milliseconds between events A and B, but event B
+ * doesn't happen exactly after event A, you record the timestamp (jiffies) of
+ * when event A happened, then just before event B you call this function and
+ * pass the timestamp as the first argument, and X as the second argument.
+ */
+static inline void
+wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
+{
+	unsigned long target_jiffies, tmp_jiffies, remaining_jiffies;
+
+	/*
+	 * Don't re-read the value of "jiffies" every time since it may change
+	 * behind our back and break the math.
+	 */
+	tmp_jiffies = jiffies;
+	target_jiffies = timestamp_jiffies +
+			 msecs_to_jiffies_timeout(to_wait_ms);
+
+	if (time_after(target_jiffies, tmp_jiffies)) {
+		remaining_jiffies = target_jiffies - tmp_jiffies;
+		while (remaining_jiffies)
+			remaining_jiffies =
+			    schedule_timeout_uninterruptible(remaining_jiffies);
+	}
+}
+
 #endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 00c836154725..3618bb0cda0a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -43,12 +43,6 @@ static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *o
 static __must_check int
 i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
 			       bool readonly);
-static __must_check int
-i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
-			   struct i915_address_space *vm,
-			   unsigned alignment,
-			   bool map_and_fenceable,
-			   bool nonblocking);
 static int i915_gem_phys_pwrite(struct drm_device *dev,
 				struct drm_i915_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
@@ -204,7 +198,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 	pinned = 0;
 	mutex_lock(&dev->struct_mutex);
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
-		if (obj->pin_count)
+		if (i915_gem_obj_is_pinned(obj))
 			pinned += i915_gem_obj_ggtt_size(obj);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -476,7 +470,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
 
 		mutex_unlock(&dev->struct_mutex);
 
-		if (likely(!i915_prefault_disable) && !prefaulted) {
+		if (likely(!i915.prefault_disable) && !prefaulted) {
 			ret = fault_in_multipages_writeable(user_data, remain);
 			/* Userspace is tricking us, but we've already clobbered
 			 * its pages with the prefault and promised to write the
@@ -605,7 +599,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	char __user *user_data;
 	int page_offset, page_length, ret;
 
-	ret = i915_gem_obj_ggtt_pin(obj, 0, true, true);
+	ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE | PIN_NONBLOCK);
 	if (ret)
 		goto out;
 
@@ -651,7 +645,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	}
 
 out_unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 out:
 	return ret;
 }
@@ -868,7 +862,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		       args->size))
 		return -EFAULT;
 
-	if (likely(!i915_prefault_disable)) {
+	if (likely(!i915.prefault_disable)) {
 		ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr),
 						   args->size);
 		if (ret)
@@ -1014,7 +1008,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
 			struct timespec *timeout,
 			struct drm_i915_file_private *file_priv)
 {
-	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	const bool irq_test_in_progress =
 		ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
 	struct timespec before, now;
@@ -1029,7 +1024,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
 
 	timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
 
-	if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
+	if (INTEL_INFO(dev)->gen >= 6 && can_wait_boost(file_priv)) {
 		gen6_rps_boost(dev_priv);
 		if (file_priv)
 			mod_delayed_work(dev_priv->wq,
@@ -1184,7 +1179,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
  */
 static __must_check int
 i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
-					    struct drm_file *file,
+					    struct drm_i915_file_private *file_priv,
 					    bool readonly)
 {
 	struct drm_device *dev = obj->base.dev;
@@ -1211,7 +1206,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
 
 	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 	mutex_unlock(&dev->struct_mutex);
-	ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file->driver_priv);
+	ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file_priv);
 	mutex_lock(&dev->struct_mutex);
 	if (ret)
 		return ret;
@@ -1260,7 +1255,9 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	 * We will repeat the flush holding the lock in the normal manner
 	 * to catch cases where we are gazumped.
 	 */
-	ret = i915_gem_object_wait_rendering__nonblocking(obj, file, !write_domain);
+	ret = i915_gem_object_wait_rendering__nonblocking(obj,
+							  file->driver_priv,
+							  !write_domain);
 	if (ret)
 		goto unref;
 
@@ -1392,6 +1389,15 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	trace_i915_gem_object_fault(obj, page_offset, true, write);
 
+	/* Try to flush the object off the GPU first without holding the lock.
+	 * Upon reacquiring the lock, we will perform our sanity checks and then
+	 * repeat the flush holding the lock in the normal manner to catch cases
+	 * where we are gazumped.
+	 */
+	ret = i915_gem_object_wait_rendering__nonblocking(obj, NULL, !write);
+	if (ret)
+		goto unlock;
+
 	/* Access to snoopable pages through the GTT is incoherent. */
 	if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
 		ret = -EINVAL;
@@ -1399,7 +1405,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	}
 
 	/* Now bind it into the GTT if needed */
-	ret = i915_gem_obj_ggtt_pin(obj,  0, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE);
 	if (ret)
 		goto unlock;
 
@@ -1420,7 +1426,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	/* Finally, remap it using the new GTT offset */
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 out:
@@ -1453,6 +1459,7 @@ out:
 		ret = VM_FAULT_OOM;
 		break;
 	case -ENOSPC:
+	case -EFAULT:
 		ret = VM_FAULT_SIGBUS;
 		break;
 	default:
@@ -1617,8 +1624,8 @@ i915_gem_mmap_gtt(struct drm_file *file,
 	}
 
 	if (obj->madv != I915_MADV_WILLNEED) {
-		DRM_ERROR("Attempting to mmap a purgeable buffer\n");
-		ret = -EINVAL;
+		DRM_DEBUG("Attempting to mmap a purgeable buffer\n");
+		ret = -EFAULT;
 		goto out;
 	}
 
@@ -1971,8 +1978,8 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 		return 0;
 
 	if (obj->madv != I915_MADV_WILLNEED) {
-		DRM_ERROR("Attempting to obtain a purgeable object\n");
-		return -EINVAL;
+		DRM_DEBUG("Attempting to obtain a purgeable object\n");
+		return -EFAULT;
 	}
 
 	BUG_ON(obj->pages_pin_count);
@@ -2035,13 +2042,17 @@ static void
 i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-	struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
-	struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
+	struct i915_address_space *vm;
+	struct i915_vma *vma;
 
 	BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
 	BUG_ON(!obj->active);
 
-	list_move_tail(&vma->mm_list, &ggtt_vm->inactive_list);
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		vma = i915_gem_obj_to_vma(obj, vm);
+		if (vma && !list_empty(&vma->mm_list))
+			list_move_tail(&vma->mm_list, &vm->inactive_list);
+	}
 
 	list_del_init(&obj->ring_list);
 	obj->ring = NULL;
@@ -2237,125 +2248,47 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
 	spin_unlock(&file_priv->mm.lock);
 }
 
-static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj,
-				    struct i915_address_space *vm)
-{
-	if (acthd >= i915_gem_obj_offset(obj, vm) &&
-	    acthd < i915_gem_obj_offset(obj, vm) + obj->base.size)
-		return true;
-
-	return false;
-}
-
-static bool i915_head_inside_request(const u32 acthd_unmasked,
-				     const u32 request_start,
-				     const u32 request_end)
-{
-	const u32 acthd = acthd_unmasked & HEAD_ADDR;
-
-	if (request_start < request_end) {
-		if (acthd >= request_start && acthd < request_end)
-			return true;
-	} else if (request_start > request_end) {
-		if (acthd >= request_start || acthd < request_end)
-			return true;
-	}
-
-	return false;
-}
-
-static struct i915_address_space *
-request_to_vm(struct drm_i915_gem_request *request)
-{
-	struct drm_i915_private *dev_priv = request->ring->dev->dev_private;
-	struct i915_address_space *vm;
-
-	vm = &dev_priv->gtt.base;
-
-	return vm;
-}
-
-static bool i915_request_guilty(struct drm_i915_gem_request *request,
-				const u32 acthd, bool *inside)
+static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
+				   const struct i915_hw_context *ctx)
 {
-	/* There is a possibility that unmasked head address
-	 * pointing inside the ring, matches the batch_obj address range.
-	 * However this is extremely unlikely.
-	 */
-	if (request->batch_obj) {
-		if (i915_head_inside_object(acthd, request->batch_obj,
-					    request_to_vm(request))) {
-			*inside = true;
-			return true;
-		}
-	}
-
-	if (i915_head_inside_request(acthd, request->head, request->tail)) {
-		*inside = false;
-		return true;
-	}
-
-	return false;
-}
+	unsigned long elapsed;
 
-static bool i915_context_is_banned(const struct i915_ctx_hang_stats *hs)
-{
-	const unsigned long elapsed = get_seconds() - hs->guilty_ts;
+	elapsed = get_seconds() - ctx->hang_stats.guilty_ts;
 
-	if (hs->banned)
+	if (ctx->hang_stats.banned)
 		return true;
 
 	if (elapsed <= DRM_I915_CTX_BAN_PERIOD) {
-		DRM_ERROR("context hanging too fast, declaring banned!\n");
+		if (dev_priv->gpu_error.stop_rings == 0 &&
+		    i915_gem_context_is_default(ctx)) {
+			DRM_ERROR("gpu hanging too fast, banning!\n");
+		} else {
+			DRM_DEBUG("context hanging too fast, banning!\n");
+		}
+
 		return true;
 	}
 
 	return false;
 }
 
-static void i915_set_reset_status(struct intel_ring_buffer *ring,
-				  struct drm_i915_gem_request *request,
-				  u32 acthd)
+static void i915_set_reset_status(struct drm_i915_private *dev_priv,
+				  struct i915_hw_context *ctx,
+				  const bool guilty)
 {
-	struct i915_ctx_hang_stats *hs = NULL;
-	bool inside, guilty;
-	unsigned long offset = 0;
-
-	/* Innocent until proven guilty */
-	guilty = false;
-
-	if (request->batch_obj)
-		offset = i915_gem_obj_offset(request->batch_obj,
-					     request_to_vm(request));
+	struct i915_ctx_hang_stats *hs;
 
-	if (ring->hangcheck.action != HANGCHECK_WAIT &&
-	    i915_request_guilty(request, acthd, &inside)) {
-		DRM_DEBUG("%s hung %s bo (0x%lx ctx %d) at 0x%x\n",
-			  ring->name,
-			  inside ? "inside" : "flushing",
-			  offset,
-			  request->ctx ? request->ctx->id : 0,
-			  acthd);
+	if (WARN_ON(!ctx))
+		return;
 
-		guilty = true;
-	}
+	hs = &ctx->hang_stats;
 
-	/* If contexts are disabled or this is the default context, use
-	 * file_priv->reset_state
-	 */
-	if (request->ctx && request->ctx->id != DEFAULT_CONTEXT_ID)
-		hs = &request->ctx->hang_stats;
-	else if (request->file_priv)
-		hs = &request->file_priv->hang_stats;
-
-	if (hs) {
-		if (guilty) {
-			hs->banned = i915_context_is_banned(hs);
-			hs->batch_active++;
-			hs->guilty_ts = get_seconds();
-		} else {
-			hs->batch_pending++;
-		}
+	if (guilty) {
+		hs->banned = i915_context_is_banned(dev_priv, ctx);
+		hs->batch_active++;
+		hs->guilty_ts = get_seconds();
+	} else {
+		hs->batch_pending++;
 	}
 }
 
@@ -2370,19 +2303,39 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
 	kfree(request);
 }
 
-static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
-				       struct intel_ring_buffer *ring)
+static struct drm_i915_gem_request *
+i915_gem_find_first_non_complete(struct intel_ring_buffer *ring)
 {
-	u32 completed_seqno = ring->get_seqno(ring, false);
-	u32 acthd = intel_ring_get_active_head(ring);
 	struct drm_i915_gem_request *request;
+	const u32 completed_seqno = ring->get_seqno(ring, false);
 
 	list_for_each_entry(request, &ring->request_list, list) {
 		if (i915_seqno_passed(completed_seqno, request->seqno))
 			continue;
 
-		i915_set_reset_status(ring, request, acthd);
+		return request;
 	}
+
+	return NULL;
+}
+
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+				       struct intel_ring_buffer *ring)
+{
+	struct drm_i915_gem_request *request;
+	bool ring_hung;
+
+	request = i915_gem_find_first_non_complete(ring);
+
+	if (request == NULL)
+		return;
+
+	ring_hung = ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
+
+	i915_set_reset_status(dev_priv, request->ctx, ring_hung);
+
+	list_for_each_entry_continue(request, &ring->request_list, list)
+		i915_set_reset_status(dev_priv, request->ctx, false);
 }
 
 static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
@@ -2456,6 +2409,8 @@ void i915_gem_reset(struct drm_device *dev)
 
 	i915_gem_cleanup_ringbuffer(dev);
 
+	i915_gem_context_reset(dev);
+
 	i915_gem_restore_fences(dev);
 }
 
@@ -2474,6 +2429,24 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 
 	seqno = ring->get_seqno(ring, true);
 
+	/* Move any buffers on the active list that are no longer referenced
+	 * by the ringbuffer to the flushing/inactive lists as appropriate,
+	 * before we free the context associated with the requests.
+	 */
+	while (!list_empty(&ring->active_list)) {
+		struct drm_i915_gem_object *obj;
+
+		obj = list_first_entry(&ring->active_list,
+				      struct drm_i915_gem_object,
+				      ring_list);
+
+		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
+			break;
+
+		i915_gem_object_move_to_inactive(obj);
+	}
+
+
 	while (!list_empty(&ring->request_list)) {
 		struct drm_i915_gem_request *request;
 
@@ -2495,22 +2468,6 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		i915_gem_free_request(request);
 	}
 
-	/* Move any buffers on the active list that are no longer referenced
-	 * by the ringbuffer to the flushing/inactive lists as appropriate.
-	 */
-	while (!list_empty(&ring->active_list)) {
-		struct drm_i915_gem_object *obj;
-
-		obj = list_first_entry(&ring->active_list,
-				      struct drm_i915_gem_object,
-				      ring_list);
-
-		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
-			break;
-
-		i915_gem_object_move_to_inactive(obj);
-	}
-
 	if (unlikely(ring->trace_irq_seqno &&
 		     i915_seqno_passed(seqno, ring->trace_irq_seqno))) {
 		ring->irq_put(ring);
@@ -2753,19 +2710,15 @@ int i915_vma_unbind(struct i915_vma *vma)
 	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
 	int ret;
 
-	/* For now we only ever use 1 vma per object */
-	WARN_ON(!list_is_singular(&obj->vma_list));
-
 	if (list_empty(&vma->vma_link))
 		return 0;
 
 	if (!drm_mm_node_allocated(&vma->node)) {
 		i915_gem_vma_destroy(vma);
-
 		return 0;
 	}
 
-	if (obj->pin_count)
+	if (vma->pin_count)
 		return -EBUSY;
 
 	BUG_ON(obj->pages == NULL);
@@ -2787,12 +2740,8 @@ int i915_vma_unbind(struct i915_vma *vma)
 
 	trace_i915_vma_unbind(vma);
 
-	if (obj->has_global_gtt_mapping)
-		i915_gem_gtt_unbind_object(obj);
-	if (obj->has_aliasing_ppgtt_mapping) {
-		i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
-		obj->has_aliasing_ppgtt_mapping = 0;
-	}
+	vma->unbind_vma(vma);
+
 	i915_gem_gtt_finish_object(obj);
 
 	list_del(&vma->mm_list);
@@ -2817,26 +2766,6 @@ int i915_vma_unbind(struct i915_vma *vma)
 	return 0;
 }
 
-/**
- * Unbinds an object from the global GTT aperture.
- */
-int
-i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
-{
-	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-	struct i915_address_space *ggtt = &dev_priv->gtt.base;
-
-	if (!i915_gem_obj_ggtt_bound(obj))
-		return 0;
-
-	if (obj->pin_count)
-		return -EBUSY;
-
-	BUG_ON(obj->pages == NULL);
-
-	return i915_vma_unbind(i915_gem_obj_to_vma(obj, ggtt));
-}
-
 int i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -2845,7 +2774,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, DEFAULT_CONTEXT_ID);
+		ret = i915_switch_context(ring, NULL, ring->default_context);
 		if (ret)
 			return ret;
 
@@ -3259,18 +3188,17 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
 /**
  * Finds free space in the GTT aperture and binds the object there.
  */
-static int
+static struct i915_vma *
 i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
 			   struct i915_address_space *vm,
 			   unsigned alignment,
-			   bool map_and_fenceable,
-			   bool nonblocking)
+			   unsigned flags)
 {
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 size, fence_size, fence_alignment, unfenced_alignment;
 	size_t gtt_max =
-		map_and_fenceable ? dev_priv->gtt.mappable_end : vm->total;
+		flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total;
 	struct i915_vma *vma;
 	int ret;
 
@@ -3282,46 +3210,39 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
 						     obj->tiling_mode, true);
 	unfenced_alignment =
 		i915_gem_get_gtt_alignment(dev,
-						    obj->base.size,
-						    obj->tiling_mode, false);
+					   obj->base.size,
+					   obj->tiling_mode, false);
 
 	if (alignment == 0)
-		alignment = map_and_fenceable ? fence_alignment :
+		alignment = flags & PIN_MAPPABLE ? fence_alignment :
 						unfenced_alignment;
-	if (map_and_fenceable && alignment & (fence_alignment - 1)) {
-		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
-		return -EINVAL;
+	if (flags & PIN_MAPPABLE && alignment & (fence_alignment - 1)) {
+		DRM_DEBUG("Invalid object alignment requested %u\n", alignment);
+		return ERR_PTR(-EINVAL);
 	}
 
-	size = map_and_fenceable ? fence_size : obj->base.size;
+	size = flags & PIN_MAPPABLE ? fence_size : obj->base.size;
 
 	/* If the object is bigger than the entire aperture, reject it early
 	 * before evicting everything in a vain attempt to find space.
 	 */
 	if (obj->base.size > gtt_max) {
-		DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
+		DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
 			  obj->base.size,
-			  map_and_fenceable ? "mappable" : "total",
+			  flags & PIN_MAPPABLE ? "mappable" : "total",
 			  gtt_max);
-		return -E2BIG;
+		return ERR_PTR(-E2BIG);
 	}
 
 	ret = i915_gem_object_get_pages(obj);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
 
 	i915_gem_object_pin_pages(obj);
 
-	BUG_ON(!i915_is_ggtt(vm));
-
 	vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
-	if (IS_ERR(vma)) {
-		ret = PTR_ERR(vma);
+	if (IS_ERR(vma))
 		goto err_unpin;
-	}
-
-	/* For now we only ever use 1 vma per object */
-	WARN_ON(!list_is_singular(&obj->vma_list));
 
 search_free:
 	ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
@@ -3330,9 +3251,7 @@ search_free:
 						  DRM_MM_SEARCH_DEFAULT);
 	if (ret) {
 		ret = i915_gem_evict_something(dev, vm, size, alignment,
-					       obj->cache_level,
-					       map_and_fenceable,
-					       nonblocking);
+					       obj->cache_level, flags);
 		if (ret == 0)
 			goto search_free;
 
@@ -3363,19 +3282,23 @@ search_free:
 		obj->map_and_fenceable = mappable && fenceable;
 	}
 
-	WARN_ON(map_and_fenceable && !obj->map_and_fenceable);
+	WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
+
+	trace_i915_vma_bind(vma, flags);
+	vma->bind_vma(vma, obj->cache_level,
+		      flags & (PIN_MAPPABLE | PIN_GLOBAL) ? GLOBAL_BIND : 0);
 
-	trace_i915_vma_bind(vma, map_and_fenceable);
 	i915_gem_verify_gtt(dev);
-	return 0;
+	return vma;
 
 err_remove_node:
 	drm_mm_remove_node(&vma->node);
 err_free_vma:
 	i915_gem_vma_destroy(vma);
+	vma = ERR_PTR(ret);
 err_unpin:
 	i915_gem_object_unpin_pages(obj);
-	return ret;
+	return vma;
 }
 
 bool
@@ -3528,14 +3451,13 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 				    enum i915_cache_level cache_level)
 {
 	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct i915_vma *vma;
 	int ret;
 
 	if (obj->cache_level == cache_level)
 		return 0;
 
-	if (obj->pin_count) {
+	if (i915_gem_obj_is_pinned(obj)) {
 		DRM_DEBUG("can not change the cache level of pinned objects\n");
 		return -EBUSY;
 	}
@@ -3567,11 +3489,10 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 				return ret;
 		}
 
-		if (obj->has_global_gtt_mapping)
-			i915_gem_gtt_bind_object(obj, cache_level);
-		if (obj->has_aliasing_ppgtt_mapping)
-			i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
-					       obj, cache_level);
+		list_for_each_entry(vma, &obj->vma_list, vma_link)
+			if (drm_mm_node_allocated(&vma->node))
+				vma->bind_vma(vma, cache_level,
+					      obj->has_global_gtt_mapping ? GLOBAL_BIND : 0);
 	}
 
 	list_for_each_entry(vma, &obj->vma_list, vma_link)
@@ -3695,7 +3616,7 @@ static bool is_pin_display(struct drm_i915_gem_object *obj)
 	 * subtracting the potential reference by the user, any pin_count
 	 * remains, it must be due to another use by the display engine.
 	 */
-	return obj->pin_count - !!obj->user_pin_count;
+	return i915_gem_obj_to_ggtt(obj)->pin_count - !!obj->user_pin_count;
 }
 
 /*
@@ -3740,7 +3661,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	 * (e.g. libkms for the bootup splash), we have to ensure that we
 	 * always use map_and_fenceable for all scanout buffers.
 	 */
-	ret = i915_gem_obj_ggtt_pin(obj, alignment, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, alignment, PIN_MAPPABLE);
 	if (ret)
 		goto err_unpin_display;
 
@@ -3769,7 +3690,7 @@ err_unpin_display:
 void
 i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj)
 {
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 	obj->pin_display = is_pin_display(obj);
 }
 
@@ -3896,65 +3817,63 @@ int
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
 		    struct i915_address_space *vm,
 		    uint32_t alignment,
-		    bool map_and_fenceable,
-		    bool nonblocking)
+		    unsigned flags)
 {
 	struct i915_vma *vma;
 	int ret;
 
-	if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
-		return -EBUSY;
-
-	WARN_ON(map_and_fenceable && !i915_is_ggtt(vm));
+	if (WARN_ON(flags & (PIN_GLOBAL | PIN_MAPPABLE) && !i915_is_ggtt(vm)))
+		return -EINVAL;
 
 	vma = i915_gem_obj_to_vma(obj, vm);
-
 	if (vma) {
+		if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
+			return -EBUSY;
+
 		if ((alignment &&
 		     vma->node.start & (alignment - 1)) ||
-		    (map_and_fenceable && !obj->map_and_fenceable)) {
-			WARN(obj->pin_count,
+		    (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) {
+			WARN(vma->pin_count,
 			     "bo is already pinned with incorrect alignment:"
 			     " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
 			     " obj->map_and_fenceable=%d\n",
 			     i915_gem_obj_offset(obj, vm), alignment,
-			     map_and_fenceable,
+			     flags & PIN_MAPPABLE,
 			     obj->map_and_fenceable);
 			ret = i915_vma_unbind(vma);
 			if (ret)
 				return ret;
+
+			vma = NULL;
 		}
 	}
 
-	if (!i915_gem_obj_bound(obj, vm)) {
-		struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-
-		ret = i915_gem_object_bind_to_vm(obj, vm, alignment,
-						 map_and_fenceable,
-						 nonblocking);
-		if (ret)
-			return ret;
-
-		if (!dev_priv->mm.aliasing_ppgtt)
-			i915_gem_gtt_bind_object(obj, obj->cache_level);
+	if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
+		vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags);
+		if (IS_ERR(vma))
+			return PTR_ERR(vma);
 	}
 
-	if (!obj->has_global_gtt_mapping && map_and_fenceable)
-		i915_gem_gtt_bind_object(obj, obj->cache_level);
+	if (flags & PIN_GLOBAL && !obj->has_global_gtt_mapping)
+		vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
 
-	obj->pin_count++;
-	obj->pin_mappable |= map_and_fenceable;
+	vma->pin_count++;
+	if (flags & PIN_MAPPABLE)
+		obj->pin_mappable |= true;
 
 	return 0;
 }
 
 void
-i915_gem_object_unpin(struct drm_i915_gem_object *obj)
+i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj)
 {
-	BUG_ON(obj->pin_count == 0);
-	BUG_ON(!i915_gem_obj_bound_any(obj));
+	struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
+
+	BUG_ON(!vma);
+	BUG_ON(vma->pin_count == 0);
+	BUG_ON(!i915_gem_obj_ggtt_bound(obj));
 
-	if (--obj->pin_count == 0)
+	if (--vma->pin_count == 0)
 		obj->pin_mappable = false;
 }
 
@@ -3966,6 +3885,9 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_gem_object *obj;
 	int ret;
 
+	if (INTEL_INFO(dev)->gen >= 6)
+		return -ENODEV;
+
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
@@ -3977,13 +3899,13 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	}
 
 	if (obj->madv != I915_MADV_WILLNEED) {
-		DRM_ERROR("Attempting to pin a purgeable buffer\n");
-		ret = -EINVAL;
+		DRM_DEBUG("Attempting to pin a purgeable buffer\n");
+		ret = -EFAULT;
 		goto out;
 	}
 
 	if (obj->pin_filp != NULL && obj->pin_filp != file) {
-		DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
+		DRM_DEBUG("Already pinned in i915_gem_pin_ioctl(): %d\n",
 			  args->handle);
 		ret = -EINVAL;
 		goto out;
@@ -3995,7 +3917,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	}
 
 	if (obj->user_pin_count == 0) {
-		ret = i915_gem_obj_ggtt_pin(obj, args->alignment, true, false);
+		ret = i915_gem_obj_ggtt_pin(obj, args->alignment, PIN_MAPPABLE);
 		if (ret)
 			goto out;
 	}
@@ -4030,7 +3952,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
 	}
 
 	if (obj->pin_filp != file) {
-		DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
+		DRM_DEBUG("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
 			  args->handle);
 		ret = -EINVAL;
 		goto out;
@@ -4038,7 +3960,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
 	obj->user_pin_count--;
 	if (obj->user_pin_count == 0) {
 		obj->pin_filp = NULL;
-		i915_gem_object_unpin(obj);
+		i915_gem_object_ggtt_unpin(obj);
 	}
 
 out:
@@ -4118,7 +4040,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 		goto unlock;
 	}
 
-	if (obj->pin_count) {
+	if (i915_gem_obj_is_pinned(obj)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -4229,12 +4151,11 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	if (obj->phys_obj)
 		i915_gem_detach_phys_object(dev, obj);
 
-	obj->pin_count = 0;
-	/* NB: 0 or 1 elements */
-	WARN_ON(!list_empty(&obj->vma_list) &&
-		!list_is_singular(&obj->vma_list));
 	list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) {
-		int ret = i915_vma_unbind(vma);
+		int ret;
+
+		vma->pin_count = 0;
+		ret = i915_vma_unbind(vma);
 		if (WARN_ON(ret == -ERESTARTSYS)) {
 			bool was_interruptible;
 
@@ -4283,41 +4204,6 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
 	return NULL;
 }
 
-static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
-					      struct i915_address_space *vm)
-{
-	struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
-	if (vma == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	INIT_LIST_HEAD(&vma->vma_link);
-	INIT_LIST_HEAD(&vma->mm_list);
-	INIT_LIST_HEAD(&vma->exec_list);
-	vma->vm = vm;
-	vma->obj = obj;
-
-	/* Keep GGTT vmas first to make debug easier */
-	if (i915_is_ggtt(vm))
-		list_add(&vma->vma_link, &obj->vma_list);
-	else
-		list_add_tail(&vma->vma_link, &obj->vma_list);
-
-	return vma;
-}
-
-struct i915_vma *
-i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
-				  struct i915_address_space *vm)
-{
-	struct i915_vma *vma;
-
-	vma = i915_gem_obj_to_vma(obj, vm);
-	if (!vma)
-		vma = __i915_gem_vma_create(obj, vm);
-
-	return vma;
-}
-
 void i915_gem_vma_destroy(struct i915_vma *vma)
 {
 	WARN_ON(vma->node.allocated);
@@ -4508,9 +4394,15 @@ i915_gem_init_hw(struct drm_device *dev)
 			   LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
 
 	if (HAS_PCH_NOP(dev)) {
-		u32 temp = I915_READ(GEN7_MSG_CTL);
-		temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
-		I915_WRITE(GEN7_MSG_CTL, temp);
+		if (IS_IVYBRIDGE(dev)) {
+			u32 temp = I915_READ(GEN7_MSG_CTL);
+			temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
+			I915_WRITE(GEN7_MSG_CTL, temp);
+		} else if (INTEL_INFO(dev)->gen >= 7) {
+			u32 temp = I915_READ(HSW_NDE_RSTWRN_OPT);
+			temp &= ~RESET_PCH_HANDSHAKE_ENABLE;
+			I915_WRITE(HSW_NDE_RSTWRN_OPT, temp);
+		}
 	}
 
 	i915_gem_init_swizzling(dev);
@@ -4523,25 +4415,23 @@ i915_gem_init_hw(struct drm_device *dev)
 		i915_gem_l3_remap(&dev_priv->ring[RCS], i);
 
 	/*
-	 * XXX: There was some w/a described somewhere suggesting loading
-	 * contexts before PPGTT.
+	 * XXX: Contexts should only be initialized once. Doing a switch to the
+	 * default context switch however is something we'd like to do after
+	 * reset or thaw (the latter may not actually be necessary for HW, but
+	 * goes with our code better). Context switching requires rings (for
+	 * the do_switch), but before enabling PPGTT. So don't move this.
 	 */
-	ret = i915_gem_context_init(dev);
+	ret = i915_gem_context_enable(dev_priv);
 	if (ret) {
-		i915_gem_cleanup_ringbuffer(dev);
-		DRM_ERROR("Context initialization failed %d\n", ret);
-		return ret;
-	}
-
-	if (dev_priv->mm.aliasing_ppgtt) {
-		ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
-		if (ret) {
-			i915_gem_cleanup_aliasing_ppgtt(dev);
-			DRM_INFO("PPGTT enable failed. This is not fatal, but unexpected\n");
-		}
+		DRM_ERROR("Context enable failed %d\n", ret);
+		goto err_out;
 	}
 
 	return 0;
+
+err_out:
+	i915_gem_cleanup_ringbuffer(dev);
+	return ret;
 }
 
 int i915_gem_init(struct drm_device *dev)
@@ -4560,10 +4450,18 @@ int i915_gem_init(struct drm_device *dev)
 
 	i915_gem_init_global_gtt(dev);
 
+	ret = i915_gem_context_init(dev);
+	if (ret) {
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
 	ret = i915_gem_init_hw(dev);
 	mutex_unlock(&dev->struct_mutex);
 	if (ret) {
-		i915_gem_cleanup_aliasing_ppgtt(dev);
+		WARN_ON(dev_priv->mm.aliasing_ppgtt);
+		i915_gem_context_fini(dev);
+		drm_mm_takedown(&dev_priv->gtt.base.mm);
 		return ret;
 	}
 
@@ -4658,14 +4556,16 @@ init_ring_lists(struct intel_ring_buffer *ring)
 	INIT_LIST_HEAD(&ring->request_list);
 }
 
-static void i915_init_vm(struct drm_i915_private *dev_priv,
-			 struct i915_address_space *vm)
+void i915_init_vm(struct drm_i915_private *dev_priv,
+		  struct i915_address_space *vm)
 {
+	if (!i915_is_ggtt(vm))
+		drm_mm_init(&vm->mm, vm->start, vm->total);
 	vm->dev = dev_priv->dev;
 	INIT_LIST_HEAD(&vm->active_list);
 	INIT_LIST_HEAD(&vm->inactive_list);
 	INIT_LIST_HEAD(&vm->global_link);
-	list_add(&vm->global_link, &dev_priv->vm_list);
+	list_add_tail(&vm->global_link, &dev_priv->vm_list);
 }
 
 void
@@ -4950,6 +4850,7 @@ i915_gem_file_idle_work_handler(struct work_struct *work)
 int i915_gem_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv;
+	int ret;
 
 	DRM_DEBUG_DRIVER("\n");
 
@@ -4965,9 +4866,11 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file)
 	INIT_DELAYED_WORK(&file_priv->mm.idle_work,
 			  i915_gem_file_idle_work_handler);
 
-	idr_init(&file_priv->context_idr);
+	ret = i915_gem_context_open(dev, file);
+	if (ret)
+		kfree(file_priv);
 
-	return 0;
+	return ret;
 }
 
 static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
@@ -5014,7 +4917,7 @@ i915_gem_inactive_count(struct shrinker *shrinker, struct shrink_control *sc)
 		if (obj->active)
 			continue;
 
-		if (obj->pin_count == 0 && obj->pages_pin_count == 0)
+		if (!i915_gem_obj_is_pinned(obj) && obj->pages_pin_count == 0)
 			count += obj->base.size >> PAGE_SHIFT;
 	}
 
@@ -5031,7 +4934,8 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
 	struct drm_i915_private *dev_priv = o->base.dev->dev_private;
 	struct i915_vma *vma;
 
-	if (vm == &dev_priv->mm.aliasing_ppgtt->base)
+	if (!dev_priv->mm.aliasing_ppgtt ||
+	    vm == &dev_priv->mm.aliasing_ppgtt->base)
 		vm = &dev_priv->gtt.base;
 
 	BUG_ON(list_empty(&o->vma_list));
@@ -5072,7 +4976,8 @@ unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
 	struct drm_i915_private *dev_priv = o->base.dev->dev_private;
 	struct i915_vma *vma;
 
-	if (vm == &dev_priv->mm.aliasing_ppgtt->base)
+	if (!dev_priv->mm.aliasing_ppgtt ||
+	    vm == &dev_priv->mm.aliasing_ppgtt->base)
 		vm = &dev_priv->gtt.base;
 
 	BUG_ON(list_empty(&o->vma_list));
@@ -5127,7 +5032,7 @@ struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
 		return NULL;
 
 	vma = list_first_entry(&obj->vma_list, typeof(*vma), vma_link);
-	if (WARN_ON(vma->vm != obj_to_ggtt(obj)))
+	if (vma->vm != obj_to_ggtt(obj))
 		return NULL;
 
 	return vma;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index e08acaba5402..f8c21a6dd663 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -93,11 +93,19 @@
  * I've seen in a spec to date, and that was a workaround for a non-shipping
  * part. It should be safe to decrease this, but it's more future proof as is.
  */
-#define CONTEXT_ALIGN (64<<10)
+#define GEN6_CONTEXT_ALIGN (64<<10)
+#define GEN7_CONTEXT_ALIGN 4096
 
-static struct i915_hw_context *
-i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
-static int do_switch(struct i915_hw_context *to);
+static int do_switch(struct intel_ring_buffer *ring,
+		     struct i915_hw_context *to);
+
+static size_t get_context_alignment(struct drm_device *dev)
+{
+	if (IS_GEN6(dev))
+		return GEN6_CONTEXT_ALIGN;
+
+	return GEN7_CONTEXT_ALIGN;
+}
 
 static int get_context_size(struct drm_device *dev)
 {
@@ -131,14 +139,43 @@ void i915_gem_context_free(struct kref *ctx_ref)
 {
 	struct i915_hw_context *ctx = container_of(ctx_ref,
 						   typeof(*ctx), ref);
+	struct i915_hw_ppgtt *ppgtt = NULL;
 
-	list_del(&ctx->link);
+	/* 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);
+
+	if (ppgtt)
+		kref_put(&ppgtt->ref, ppgtt_release);
+	list_del(&ctx->link);
 	kfree(ctx);
 }
 
+static struct i915_hw_ppgtt *
+create_vm_for_ctx(struct drm_device *dev, struct i915_hw_context *ctx)
+{
+	struct i915_hw_ppgtt *ppgtt;
+	int ret;
+
+	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
+	if (!ppgtt)
+		return ERR_PTR(-ENOMEM);
+
+	ret = i915_gem_init_ppgtt(dev, ppgtt);
+	if (ret) {
+		kfree(ppgtt);
+		return ERR_PTR(ret);
+	}
+
+	return ppgtt;
+}
+
 static struct i915_hw_context *
-create_hw_context(struct drm_device *dev,
+__create_hw_context(struct drm_device *dev,
 		  struct drm_i915_file_private *file_priv)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -166,18 +203,13 @@ create_hw_context(struct drm_device *dev,
 			goto err_out;
 	}
 
-	/* The ring associated with the context object is handled by the normal
-	 * object tracking code. We give an initial ring value simple to pass an
-	 * assertion in the context switch code.
-	 */
-	ctx->ring = &dev_priv->ring[RCS];
 	list_add_tail(&ctx->link, &dev_priv->context_list);
 
 	/* 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 + 1, 0,
+	ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
 			GFP_KERNEL);
 	if (ret < 0)
 		goto err_out;
@@ -196,67 +228,136 @@ err_out:
 	return ERR_PTR(ret);
 }
 
-static inline bool is_default_context(struct i915_hw_context *ctx)
-{
-	return (ctx == ctx->ring->default_context);
-}
-
 /**
  * The default context needs to exist per ring that uses contexts. It stores the
  * context state of the GPU for applications that don't utilize HW contexts, as
  * well as an idle case.
  */
-static int create_default_context(struct drm_i915_private *dev_priv)
+static struct i915_hw_context *
+i915_gem_create_context(struct drm_device *dev,
+			struct drm_i915_file_private *file_priv,
+			bool create_vm)
 {
+	const bool is_global_default_ctx = file_priv == NULL;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_hw_context *ctx;
-	int ret;
+	int ret = 0;
 
-	BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	ctx = create_hw_context(dev_priv->dev, NULL);
+	ctx = __create_hw_context(dev, file_priv);
 	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
-
-	/* 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 default context also requires GTT space which
-	 * may not be available. To avoid this we always pin the
-	 * default context.
-	 */
-	ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false);
-	if (ret) {
-		DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
-		goto err_destroy;
-	}
+		return ctx;
 
-	ret = do_switch(ctx);
-	if (ret) {
-		DRM_DEBUG_DRIVER("Switch failed %d\n", ret);
-		goto err_unpin;
+	if (is_global_default_ctx) {
+		/* 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
+		 * default context also requires GTT space which may not
+		 * be available. To avoid this we always pin the default
+		 * context.
+		 */
+		ret = i915_gem_obj_ggtt_pin(ctx->obj,
+					    get_context_alignment(dev), 0);
+		if (ret) {
+			DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
+			goto err_destroy;
+		}
 	}
 
-	dev_priv->ring[RCS].default_context = ctx;
+	if (create_vm) {
+		struct i915_hw_ppgtt *ppgtt = create_vm_for_ctx(dev, ctx);
+
+		if (IS_ERR_OR_NULL(ppgtt)) {
+			DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
+					 PTR_ERR(ppgtt));
+			ret = PTR_ERR(ppgtt);
+			goto err_unpin;
+		} else
+			ctx->vm = &ppgtt->base;
+
+		/* This case is reserved for the global default context and
+		 * should only happen once. */
+		if (is_global_default_ctx) {
+			if (WARN_ON(dev_priv->mm.aliasing_ppgtt)) {
+				ret = -EEXIST;
+				goto err_unpin;
+			}
+
+			dev_priv->mm.aliasing_ppgtt = ppgtt;
+		}
+	} else if (USES_PPGTT(dev)) {
+		/* For platforms which only have aliasing PPGTT, we fake the
+		 * address space and refcounting. */
+		ctx->vm = &dev_priv->mm.aliasing_ppgtt->base;
+		kref_get(&dev_priv->mm.aliasing_ppgtt->ref);
+	} else
+		ctx->vm = &dev_priv->gtt.base;
 
-	DRM_DEBUG_DRIVER("Default HW context loaded\n");
-	return 0;
+	return ctx;
 
 err_unpin:
-	i915_gem_object_unpin(ctx->obj);
+	if (is_global_default_ctx)
+		i915_gem_object_ggtt_unpin(ctx->obj);
 err_destroy:
 	i915_gem_context_unreference(ctx);
-	return ret;
+	return ERR_PTR(ret);
+}
+
+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;
+
+		/* Do a fake switch to the default context */
+		ring = &dev_priv->ring[i];
+		dctx = ring->default_context;
+		if (WARN_ON(!dctx))
+			continue;
+
+		if (!ring->last_context)
+			continue;
+
+		if (ring->last_context == dctx)
+			continue;
+
+		if (i == RCS) {
+			WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
+						      get_context_alignment(dev), 0));
+			/* Fake a finish/inactive */
+			dctx->obj->base.write_domain = 0;
+			dctx->obj->active = 0;
+		}
+
+		i915_gem_context_unreference(ring->last_context);
+		i915_gem_context_reference(dctx);
+		ring->last_context = dctx;
+	}
 }
 
 int i915_gem_context_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
+	struct intel_ring_buffer *ring;
+	int i;
 
 	if (!HAS_HW_CONTEXTS(dev))
 		return 0;
 
-	/* If called from reset, or thaw... we've been here already */
-	if (dev_priv->ring[RCS].default_context)
+	/* 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);
@@ -266,11 +367,23 @@ int i915_gem_context_init(struct drm_device *dev)
 		return -E2BIG;
 	}
 
-	ret = create_default_context(dev_priv);
-	if (ret) {
-		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n",
-				 ret);
-		return ret;
+	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);
+	}
+
+	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;
 	}
 
 	DRM_DEBUG_DRIVER("HW context support initialized\n");
@@ -281,6 +394,7 @@ void i915_gem_context_fini(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
+	int i;
 
 	if (!HAS_HW_CONTEXTS(dev))
 		return;
@@ -300,59 +414,129 @@ void i915_gem_context_fini(struct drm_device *dev)
 	if (dev_priv->ring[RCS].last_context == dctx) {
 		/* Fake switch to NULL context */
 		WARN_ON(dctx->obj->active);
-		i915_gem_object_unpin(dctx->obj);
+		i915_gem_object_ggtt_unpin(dctx->obj);
 		i915_gem_context_unreference(dctx);
+		dev_priv->ring[RCS].last_context = NULL;
 	}
 
-	i915_gem_object_unpin(dctx->obj);
+	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);
+
+		ring->default_context = NULL;
+		ring->last_context = NULL;
+	}
+
+	i915_gem_object_ggtt_unpin(dctx->obj);
 	i915_gem_context_unreference(dctx);
-	dev_priv->ring[RCS].default_context = NULL;
-	dev_priv->ring[RCS].last_context = NULL;
+	dev_priv->mm.aliasing_ppgtt = NULL;
+}
+
+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) {
+		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+		ppgtt->enable(ppgtt);
+	}
+
+	/* FIXME: We should make this work, even in reset */
+	if (i915_reset_in_progress(&dev_priv->gpu_error))
+		return 0;
+
+	BUG_ON(!dev_priv->ring[RCS].default_context);
+
+	for_each_ring(ring, dev_priv, i) {
+		ret = do_switch(ring, ring->default_context);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 static int context_idr_cleanup(int id, void *p, void *data)
 {
 	struct i915_hw_context *ctx = p;
 
-	BUG_ON(id == DEFAULT_CONTEXT_ID);
+	/* Ignore the default context because close will handle it */
+	if (i915_gem_context_is_default(ctx))
+		return 0;
 
 	i915_gem_context_unreference(ctx);
 	return 0;
 }
 
-struct i915_ctx_hang_stats *
-i915_gem_context_get_hang_stats(struct drm_device *dev,
-				struct drm_file *file,
-				u32 id)
+int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv = file->driver_priv;
-	struct i915_hw_context *ctx;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (id == DEFAULT_CONTEXT_ID)
-		return &file_priv->hang_stats;
+	if (!HAS_HW_CONTEXTS(dev)) {
+		/* Cheat for hang stats */
+		file_priv->private_default_ctx =
+			kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL);
 
-	if (!HAS_HW_CONTEXTS(dev))
-		return ERR_PTR(-ENOENT);
+		if (file_priv->private_default_ctx == NULL)
+			return -ENOMEM;
 
-	ctx = i915_gem_context_get(file->driver_priv, id);
-	if (ctx == NULL)
-		return ERR_PTR(-ENOENT);
+		file_priv->private_default_ctx->vm = &dev_priv->gtt.base;
+		return 0;
+	}
 
-	return &ctx->hang_stats;
+	idr_init(&file_priv->context_idr);
+
+	mutex_lock(&dev->struct_mutex);
+	file_priv->private_default_ctx =
+		i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev));
+	mutex_unlock(&dev->struct_mutex);
+
+	if (IS_ERR(file_priv->private_default_ctx)) {
+		idr_destroy(&file_priv->context_idr);
+		return PTR_ERR(file_priv->private_default_ctx);
+	}
+
+	return 0;
 }
 
 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);
 }
 
-static struct i915_hw_context *
+struct i915_hw_context *
 i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
 {
-	return (struct i915_hw_context *)idr_find(&file_priv->context_idr, 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);
+
+	return ctx;
 }
 
 static inline int
@@ -390,7 +574,10 @@ mi_set_context(struct intel_ring_buffer *ring,
 			MI_SAVE_EXT_STATE_EN |
 			MI_RESTORE_EXT_STATE_EN |
 			hw_flags);
-	/* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */
+	/*
+	 * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
+	 * WaMiSetContext_Hang:snb,ivb,vlv
+	 */
 	intel_ring_emit(ring, MI_NOOP);
 
 	if (IS_GEN7(ring->dev))
@@ -403,21 +590,30 @@ mi_set_context(struct intel_ring_buffer *ring,
 	return ret;
 }
 
-static int do_switch(struct i915_hw_context *to)
+static int do_switch(struct intel_ring_buffer *ring,
+		     struct i915_hw_context *to)
 {
-	struct intel_ring_buffer *ring = to->ring;
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct i915_hw_context *from = ring->last_context;
+	struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to);
 	u32 hw_flags = 0;
 	int ret, i;
 
-	BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0);
+	if (from != NULL && ring == &dev_priv->ring[RCS]) {
+		BUG_ON(from->obj == NULL);
+		BUG_ON(!i915_gem_obj_is_pinned(from->obj));
+	}
 
-	if (from == to && !to->remap_slice)
+	if (from == to && from->last_ring == ring && !to->remap_slice)
 		return 0;
 
-	ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false);
-	if (ret)
-		return ret;
+	/* Trying to pin first makes error handling easier. */
+	if (ring == &dev_priv->ring[RCS]) {
+		ret = i915_gem_obj_ggtt_pin(to->obj,
+					    get_context_alignment(ring->dev), 0);
+		if (ret)
+			return ret;
+	}
 
 	/*
 	 * Pin can switch back to the default context if we end up calling into
@@ -426,6 +622,18 @@ static int do_switch(struct i915_hw_context *to)
 	 */
 	from = ring->last_context;
 
+	if (USES_FULL_PPGTT(ring->dev)) {
+		ret = ppgtt->switch_mm(ppgtt, ring, false);
+		if (ret)
+			goto unpin_out;
+	}
+
+	if (ring != &dev_priv->ring[RCS]) {
+		if (from)
+			i915_gem_context_unreference(from);
+		goto done;
+	}
+
 	/*
 	 * Clear this page out of any CPU caches for coherent swap-in/out. Note
 	 * that thanks to write = false in this call and us not setting any gpu
@@ -435,22 +643,21 @@ static int do_switch(struct i915_hw_context *to)
 	 * XXX: We need a real interface to do this instead of trickery.
 	 */
 	ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
-	if (ret) {
-		i915_gem_object_unpin(to->obj);
-		return ret;
-	}
+	if (ret)
+		goto unpin_out;
 
-	if (!to->obj->has_global_gtt_mapping)
-		i915_gem_gtt_bind_object(to->obj, to->obj->cache_level);
+	if (!to->obj->has_global_gtt_mapping) {
+		struct i915_vma *vma = i915_gem_obj_to_vma(to->obj,
+							   &dev_priv->gtt.base);
+		vma->bind_vma(vma, to->obj->cache_level, GLOBAL_BIND);
+	}
 
-	if (!to->is_initialized || is_default_context(to))
+	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
 	ret = mi_set_context(ring, to, hw_flags);
-	if (ret) {
-		i915_gem_object_unpin(to->obj);
-		return ret;
-	}
+	if (ret)
+		goto unpin_out;
 
 	for (i = 0; i < MAX_L3_SLICES; i++) {
 		if (!(to->remap_slice & (1<<i)))
@@ -484,15 +691,23 @@ static int do_switch(struct i915_hw_context *to)
 		BUG_ON(from->obj->ring != ring);
 
 		/* obj is kept alive until the next request by its active ref */
-		i915_gem_object_unpin(from->obj);
+		i915_gem_object_ggtt_unpin(from->obj);
 		i915_gem_context_unreference(from);
 	}
 
+	to->is_initialized = true;
+
+done:
 	i915_gem_context_reference(to);
 	ring->last_context = to;
-	to->is_initialized = true;
+	to->last_ring = ring;
 
 	return 0;
+
+unpin_out:
+	if (ring->id == RCS)
+		i915_gem_object_ggtt_unpin(to->obj);
+	return ret;
 }
 
 /**
@@ -508,31 +723,19 @@ static int do_switch(struct i915_hw_context *to)
  */
 int i915_switch_context(struct intel_ring_buffer *ring,
 			struct drm_file *file,
-			int to_id)
+			struct i915_hw_context *to)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	struct i915_hw_context *to;
-
-	if (!HAS_HW_CONTEXTS(ring->dev))
-		return 0;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-	if (ring != &dev_priv->ring[RCS])
-		return 0;
-
-	if (to_id == DEFAULT_CONTEXT_ID) {
-		to = ring->default_context;
-	} else {
-		if (file == NULL)
-			return -EINVAL;
+	BUG_ON(file && to == NULL);
 
-		to = i915_gem_context_get(file->driver_priv, to_id);
-		if (to == NULL)
-			return -ENOENT;
-	}
+	/* We have the fake context, but don't supports switching. */
+	if (!HAS_HW_CONTEXTS(ring->dev))
+		return 0;
 
-	return do_switch(to);
+	return do_switch(ring, to);
 }
 
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -553,7 +756,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 	if (ret)
 		return ret;
 
-	ctx = create_hw_context(dev, file_priv);
+	ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev));
 	mutex_unlock(&dev->struct_mutex);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
@@ -575,14 +778,17 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
 	if (!(dev->driver->driver_features & DRIVER_GEM))
 		return -ENODEV;
 
+	if (args->ctx_id == DEFAULT_CONTEXT_ID)
+		return -ENOENT;
+
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
 
 	ctx = i915_gem_context_get(file_priv, args->ctx_id);
-	if (!ctx) {
+	if (IS_ERR(ctx)) {
 		mutex_unlock(&dev->struct_mutex);
-		return -ENOENT;
+		return PTR_ERR(ctx);
 	}
 
 	idr_remove(&ctx->file_priv->context_idr, ctx->id);
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 2ca280f9ee53..8a78f7885cba 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -36,7 +36,7 @@
 static bool
 mark_free(struct i915_vma *vma, struct list_head *unwind)
 {
-	if (vma->obj->pin_count)
+	if (vma->pin_count)
 		return false;
 
 	if (WARN_ON(!list_empty(&vma->exec_list)))
@@ -46,10 +46,29 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
 	return drm_mm_scan_add_block(&vma->node);
 }
 
+/**
+ * i915_gem_evict_something - Evict vmas to make room for binding a new one
+ * @dev: drm_device
+ * @vm: address space to evict from
+ * @size: size of the desired free space
+ * @alignment: alignment constraint of the desired free space
+ * @cache_level: cache_level for the desired space
+ * @mappable: whether the free space must be mappable
+ * @nonblocking: whether evicting active objects is allowed or not
+ *
+ * This function will try to evict vmas until a free space satisfying the
+ * requirements is found. Callers must check first whether any such hole exists
+ * already before calling this function.
+ *
+ * This function is used by the object/vma binding code.
+ *
+ * To clarify: This is for freeing up virtual address space, not for freeing
+ * memory in e.g. the shrinker.
+ */
 int
 i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
 			 int min_size, unsigned alignment, unsigned cache_level,
-			 bool mappable, bool nonblocking)
+			 unsigned flags)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
@@ -57,7 +76,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
 	int ret = 0;
 	int pass = 0;
 
-	trace_i915_gem_evict(dev, min_size, alignment, mappable);
+	trace_i915_gem_evict(dev, min_size, alignment, flags);
 
 	/*
 	 * The goal is to evict objects and amalgamate space in LRU order.
@@ -83,7 +102,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
 	 */
 
 	INIT_LIST_HEAD(&unwind_list);
-	if (mappable) {
+	if (flags & PIN_MAPPABLE) {
 		BUG_ON(!i915_is_ggtt(vm));
 		drm_mm_init_scan_with_range(&vm->mm, min_size,
 					    alignment, cache_level, 0,
@@ -98,7 +117,7 @@ search_again:
 			goto found;
 	}
 
-	if (nonblocking)
+	if (flags & PIN_NONBLOCK)
 		goto none;
 
 	/* Now merge in the soon-to-be-expired objects... */
@@ -122,7 +141,7 @@ none:
 	/* Can we unpin some objects such as idle hw contents,
 	 * or pending flips?
 	 */
-	if (nonblocking)
+	if (flags & PIN_NONBLOCK)
 		return -ENOSPC;
 
 	/* Only idle the GPU and repeat the search once */
@@ -177,19 +196,19 @@ found:
 }
 
 /**
- * i915_gem_evict_vm - Try to free up VM space
+ * i915_gem_evict_vm - Evict all idle vmas from a vm
  *
- * @vm: Address space to evict from
+ * @vm: Address space to cleanse
  * @do_idle: Boolean directing whether to idle first.
  *
- * VM eviction is about freeing up virtual address space. If one wants fine
- * grained eviction, they should see evict something for more details. In terms
- * of freeing up actual system memory, this function may not accomplish the
- * desired result. An object may be shared in multiple address space, and this
- * function will not assert those objects be freed.
+ * This function evicts all idles vmas from a vm. If all unpinned vmas should be
+ * evicted the @do_idle needs to be set to true.
  *
- * Using do_idle will result in a more complete eviction because it retires, and
- * inactivates current BOs.
+ * This is used by the execbuf code as a last-ditch effort to defragment the
+ * address space.
+ *
+ * To clarify: This is for freeing up virtual address space, not for freeing
+ * memory in e.g. the shrinker.
  */
 int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
 {
@@ -207,12 +226,20 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
 	}
 
 	list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
-		if (vma->obj->pin_count == 0)
+		if (vma->pin_count == 0)
 			WARN_ON(i915_vma_unbind(vma));
 
 	return 0;
 }
 
+/**
+ * i915_gem_evict_everything - Try to evict all objects
+ * @dev: Device to evict objects for
+ *
+ * This functions tries to evict all gem objects from all address spaces. Used
+ * by the shrinker as a last-ditch effort and for suspend, before releasing the
+ * backing storage of all unbound objects.
+ */
 int
 i915_gem_evict_everything(struct drm_device *dev)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d269ecf46e26..d7229ad2bd22 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -91,6 +91,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 	       struct i915_address_space *vm,
 	       struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	struct drm_i915_gem_object *obj;
 	struct list_head objects;
 	int i, ret;
@@ -125,6 +126,20 @@ eb_lookup_vmas(struct eb_vmas *eb,
 	i = 0;
 	while (!list_empty(&objects)) {
 		struct i915_vma *vma;
+		struct i915_address_space *bind_vm = vm;
+
+		if (exec[i].flags & EXEC_OBJECT_NEEDS_GTT &&
+		    USES_FULL_PPGTT(vm->dev)) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		/* If we have secure dispatch, or the userspace assures us that
+		 * they know what they're doing, use the GGTT VM.
+		 */
+		if (((args->flags & I915_EXEC_SECURE) &&
+		    (i == (args->buffer_count - 1))))
+			bind_vm = &dev_priv->gtt.base;
 
 		obj = list_first_entry(&objects,
 				       struct drm_i915_gem_object,
@@ -138,7 +153,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 		 * from the (obj, vm) we don't run the risk of creating
 		 * duplicated vmas for the same vm.
 		 */
-		vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
+		vma = i915_gem_obj_lookup_or_create_vma(obj, bind_vm);
 		if (IS_ERR(vma)) {
 			DRM_DEBUG("Failed to lookup VMA\n");
 			ret = PTR_ERR(vma);
@@ -217,7 +232,7 @@ i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
 		i915_gem_object_unpin_fence(obj);
 
 	if (entry->flags & __EXEC_OBJECT_HAS_PIN)
-		i915_gem_object_unpin(obj);
+		vma->pin_count--;
 
 	entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
 }
@@ -327,8 +342,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
 static int
 i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 				   struct eb_vmas *eb,
-				   struct drm_i915_gem_relocation_entry *reloc,
-				   struct i915_address_space *vm)
+				   struct drm_i915_gem_relocation_entry *reloc)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_gem_object *target_obj;
@@ -352,8 +366,10 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 	if (unlikely(IS_GEN6(dev) &&
 	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
 	    !target_i915_obj->has_global_gtt_mapping)) {
-		i915_gem_gtt_bind_object(target_i915_obj,
-					 target_i915_obj->cache_level);
+		struct i915_vma *vma =
+			list_first_entry(&target_i915_obj->vma_list,
+					 typeof(*vma), vma_link);
+		vma->bind_vma(vma, target_i915_obj->cache_level, GLOBAL_BIND);
 	}
 
 	/* Validate that the target is in a valid r/w GPU domain */
@@ -451,8 +467,7 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
 		do {
 			u64 offset = r->presumed_offset;
 
-			ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r,
-								 vma->vm);
+			ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r);
 			if (ret)
 				return ret;
 
@@ -481,8 +496,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
 	int i, ret;
 
 	for (i = 0; i < entry->relocation_count; i++) {
-		ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i],
-							 vma->vm);
+		ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i]);
 		if (ret)
 			return ret;
 	}
@@ -527,21 +541,26 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
 				struct intel_ring_buffer *ring,
 				bool *need_reloc)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_gem_object *obj = vma->obj;
 	struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
 	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
-	bool need_fence, need_mappable;
-	struct drm_i915_gem_object *obj = vma->obj;
+	bool need_fence;
+	unsigned flags;
 	int ret;
 
+	flags = 0;
+
 	need_fence =
 		has_fenced_gpu_access &&
 		entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
 		obj->tiling_mode != I915_TILING_NONE;
-	need_mappable = need_fence || need_reloc_mappable(vma);
+	if (need_fence || need_reloc_mappable(vma))
+		flags |= PIN_MAPPABLE;
+
+	if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
+		flags |= PIN_GLOBAL;
 
-	ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, need_mappable,
-				  false);
+	ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags);
 	if (ret)
 		return ret;
 
@@ -560,14 +579,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
 		}
 	}
 
-	/* Ensure ppgtt mapping exists if needed */
-	if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
-		i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
-				       obj, obj->cache_level);
-
-		obj->has_aliasing_ppgtt_mapping = 1;
-	}
-
 	if (entry->offset != vma->node.start) {
 		entry->offset = vma->node.start;
 		*need_reloc = true;
@@ -578,10 +589,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
 		obj->base.pending_write_domain = I915_GEM_DOMAIN_RENDER;
 	}
 
-	if (entry->flags & EXEC_OBJECT_NEEDS_GTT &&
-	    !obj->has_global_gtt_mapping)
-		i915_gem_gtt_bind_object(obj, obj->cache_level);
-
 	return 0;
 }
 
@@ -891,7 +898,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 		if (!access_ok(VERIFY_WRITE, ptr, length))
 			return -EFAULT;
 
-		if (likely(!i915_prefault_disable)) {
+		if (likely(!i915.prefault_disable)) {
 			if (fault_in_multipages_readable(ptr, length))
 				return -EFAULT;
 		}
@@ -900,22 +907,27 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 	return 0;
 }
 
-static int
+static struct i915_hw_context *
 i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
-			  const u32 ctx_id)
+			  struct intel_ring_buffer *ring, const u32 ctx_id)
 {
+	struct i915_hw_context *ctx = NULL;
 	struct i915_ctx_hang_stats *hs;
 
-	hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
-	if (IS_ERR(hs))
-		return PTR_ERR(hs);
+	if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_ID)
+		return ERR_PTR(-EINVAL);
+
+	ctx = i915_gem_context_get(file->driver_priv, ctx_id);
+	if (IS_ERR(ctx))
+		return ctx;
 
+	hs = &ctx->hang_stats;
 	if (hs->banned) {
 		DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
-		return -EIO;
+		return ERR_PTR(-EIO);
 	}
 
-	return 0;
+	return ctx;
 }
 
 static void
@@ -939,7 +951,9 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
 		if (obj->base.write_domain) {
 			obj->dirty = 1;
 			obj->last_write_seqno = intel_ring_get_seqno(ring);
-			if (obj->pin_count) /* check for potential scanout */
+			/* check for potential scanout */
+			if (i915_gem_obj_ggtt_bound(obj) &&
+			    i915_gem_obj_to_ggtt(obj)->pin_count)
 				intel_mark_fb_busy(obj, ring);
 		}
 
@@ -989,16 +1003,17 @@ static int
 i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		       struct drm_file *file,
 		       struct drm_i915_gem_execbuffer2 *args,
-		       struct drm_i915_gem_exec_object2 *exec,
-		       struct i915_address_space *vm)
+		       struct drm_i915_gem_exec_object2 *exec)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct eb_vmas *eb;
 	struct drm_i915_gem_object *batch_obj;
 	struct drm_clip_rect *cliprects = NULL;
 	struct intel_ring_buffer *ring;
+	struct i915_hw_context *ctx;
+	struct i915_address_space *vm;
 	const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
-	u32 exec_start, exec_len;
+	u32 exec_start = args->batch_start_offset, exec_len;
 	u32 mask, flags;
 	int ret, mode, i;
 	bool need_relocs;
@@ -1020,41 +1035,17 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (args->flags & I915_EXEC_IS_PINNED)
 		flags |= I915_DISPATCH_PINNED;
 
-	switch (args->flags & I915_EXEC_RING_MASK) {
-	case I915_EXEC_DEFAULT:
-	case I915_EXEC_RENDER:
-		ring = &dev_priv->ring[RCS];
-		break;
-	case I915_EXEC_BSD:
-		ring = &dev_priv->ring[VCS];
-		if (ctx_id != DEFAULT_CONTEXT_ID) {
-			DRM_DEBUG("Ring %s doesn't support contexts\n",
-				  ring->name);
-			return -EPERM;
-		}
-		break;
-	case I915_EXEC_BLT:
-		ring = &dev_priv->ring[BCS];
-		if (ctx_id != DEFAULT_CONTEXT_ID) {
-			DRM_DEBUG("Ring %s doesn't support contexts\n",
-				  ring->name);
-			return -EPERM;
-		}
-		break;
-	case I915_EXEC_VEBOX:
-		ring = &dev_priv->ring[VECS];
-		if (ctx_id != DEFAULT_CONTEXT_ID) {
-			DRM_DEBUG("Ring %s doesn't support contexts\n",
-				  ring->name);
-			return -EPERM;
-		}
-		break;
-
-	default:
+	if ((args->flags & I915_EXEC_RING_MASK) > I915_NUM_RINGS) {
 		DRM_DEBUG("execbuf with unknown ring: %d\n",
 			  (int)(args->flags & I915_EXEC_RING_MASK));
 		return -EINVAL;
 	}
+
+	if ((args->flags & I915_EXEC_RING_MASK) == I915_EXEC_DEFAULT)
+		ring = &dev_priv->ring[RCS];
+	else
+		ring = &dev_priv->ring[(args->flags & I915_EXEC_RING_MASK) - 1];
+
 	if (!intel_ring_initialized(ring)) {
 		DRM_DEBUG("execbuf with invalid ring: %d\n",
 			  (int)(args->flags & I915_EXEC_RING_MASK));
@@ -1136,11 +1127,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		goto pre_mutex_err;
 	}
 
-	ret = i915_gem_validate_context(dev, file, ctx_id);
-	if (ret) {
+	ctx = i915_gem_validate_context(dev, file, ring, ctx_id);
+	if (IS_ERR(ctx)) {
 		mutex_unlock(&dev->struct_mutex);
+		ret = PTR_ERR(ctx);
 		goto pre_mutex_err;
-	}
+	} 
+
+	i915_gem_context_reference(ctx);
+
+	vm = ctx->vm;
+	if (!USES_FULL_PPGTT(dev))
+		vm = &dev_priv->gtt.base;
 
 	eb = eb_create(args);
 	if (eb == NULL) {
@@ -1187,14 +1185,25 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
 	 * batch" bit. Hence we need to pin secure batches into the global gtt.
 	 * hsw should have this fixed, but bdw mucks it up again. */
-	if (flags & I915_DISPATCH_SECURE && !batch_obj->has_global_gtt_mapping)
-		i915_gem_gtt_bind_object(batch_obj, batch_obj->cache_level);
+	if (flags & I915_DISPATCH_SECURE &&
+	    !batch_obj->has_global_gtt_mapping) {
+		/* When we have multiple VMs, we'll need to make sure that we
+		 * allocate space first */
+		struct i915_vma *vma = i915_gem_obj_to_ggtt(batch_obj);
+		BUG_ON(!vma);
+		vma->bind_vma(vma, batch_obj->cache_level, GLOBAL_BIND);
+	}
+
+	if (flags & I915_DISPATCH_SECURE)
+		exec_start += i915_gem_obj_ggtt_offset(batch_obj);
+	else
+		exec_start += i915_gem_obj_offset(batch_obj, vm);
 
 	ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas);
 	if (ret)
 		goto err;
 
-	ret = i915_switch_context(ring, file, ctx_id);
+	ret = i915_switch_context(ring, file, ctx);
 	if (ret)
 		goto err;
 
@@ -1219,8 +1228,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			goto err;
 	}
 
-	exec_start = i915_gem_obj_offset(batch_obj, vm) +
-		args->batch_start_offset;
+
 	exec_len = args->batch_len;
 	if (cliprects) {
 		for (i = 0; i < args->num_cliprects; i++) {
@@ -1249,6 +1257,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
 
 err:
+	/* the request owns the ref now */
+	i915_gem_context_unreference(ctx);
 	eb_destroy(eb);
 
 	mutex_unlock(&dev->struct_mutex);
@@ -1270,7 +1280,6 @@ int
 i915_gem_execbuffer(struct drm_device *dev, void *data,
 		    struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_execbuffer *args = data;
 	struct drm_i915_gem_execbuffer2 exec2;
 	struct drm_i915_gem_exec_object *exec_list = NULL;
@@ -1326,8 +1335,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 	exec2.flags = I915_EXEC_RENDER;
 	i915_execbuffer2_set_context_id(exec2, 0);
 
-	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list,
-				     &dev_priv->gtt.base);
+	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		for (i = 0; i < args->buffer_count; i++)
@@ -1353,7 +1361,6 @@ int
 i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		     struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_execbuffer2 *args = data;
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret;
@@ -1384,8 +1391,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		return -EFAULT;
 	}
 
-	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
-				     &dev_priv->gtt.base);
+	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		ret = copy_to_user(to_user_ptr(args->buffers_ptr),
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 40a2b36b276b..9673cffb07f3 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/seq_file.h>
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
@@ -70,6 +71,12 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
 #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,
+			   u32 flags);
+static void ppgtt_unbind_vma(struct i915_vma *vma);
+static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt);
+
 static inline gen8_gtt_pte_t gen8_pte_encode(dma_addr_t addr,
 					     enum i915_cache_level level,
 					     bool valid)
@@ -199,12 +206,19 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
 
 /* Broadwell Page Directory Pointer Descriptors */
 static int gen8_write_pdp(struct intel_ring_buffer *ring, unsigned entry,
-			   uint64_t val)
+			   uint64_t val, bool synchronous)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	int ret;
 
 	BUG_ON(entry >= 4);
 
+	if (synchronous) {
+		I915_WRITE(GEN8_RING_PDP_UDW(ring, entry), val >> 32);
+		I915_WRITE(GEN8_RING_PDP_LDW(ring, entry), (u32)val);
+		return 0;
+	}
+
 	ret = intel_ring_begin(ring, 6);
 	if (ret)
 		return ret;
@@ -220,36 +234,23 @@ static int gen8_write_pdp(struct intel_ring_buffer *ring, unsigned entry,
 	return 0;
 }
 
-static int gen8_ppgtt_enable(struct drm_device *dev)
+static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt,
+			  struct intel_ring_buffer *ring,
+			  bool synchronous)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *ring;
-	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-	int i, j, ret;
+	int i, ret;
 
 	/* bit of a hack to find the actual last used pd */
 	int used_pd = ppgtt->num_pd_entries / GEN8_PDES_PER_PAGE;
 
-	for_each_ring(ring, dev_priv, j) {
-		I915_WRITE(RING_MODE_GEN7(ring),
-			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
-	}
-
 	for (i = used_pd - 1; i >= 0; i--) {
 		dma_addr_t addr = ppgtt->pd_dma_addr[i];
-		for_each_ring(ring, dev_priv, j) {
-			ret = gen8_write_pdp(ring, i, addr);
-			if (ret)
-				goto err_out;
-		}
+		ret = gen8_write_pdp(ring, i, addr, synchronous);
+		if (ret)
+			return ret;
 	}
-	return 0;
 
-err_out:
-	for_each_ring(ring, dev_priv, j)
-		I915_WRITE(RING_MODE_GEN7(ring),
-			   _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE));
-	return ret;
+	return 0;
 }
 
 static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
@@ -318,35 +319,53 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
 		kunmap_atomic(pt_vaddr);
 }
 
-static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
+{
+	int i;
+
+	for (i = 0; i < ppgtt->num_pd_pages ; i++)
+		kfree(ppgtt->gen8_pt_dma_addr[i]);
+
+	__free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+	__free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+}
+
+static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
 	int i, j;
 
-	drm_mm_takedown(&vm->mm);
+	for (i = 0; i < ppgtt->num_pd_pages; i++) {
+		/* TODO: In the future we'll support sparse mappings, so this
+		 * will have to change. */
+		if (!ppgtt->pd_dma_addr[i])
+			continue;
 
-	for (i = 0; i < ppgtt->num_pd_pages ; i++) {
-		if (ppgtt->pd_dma_addr[i]) {
-			pci_unmap_page(ppgtt->base.dev->pdev,
-				       ppgtt->pd_dma_addr[i],
-				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		pci_unmap_page(ppgtt->base.dev->pdev,
+			       ppgtt->pd_dma_addr[i],
+			       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 
-			for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
-				dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
-				if (addr)
-					pci_unmap_page(ppgtt->base.dev->pdev,
-						       addr,
-						       PAGE_SIZE,
-						       PCI_DMA_BIDIRECTIONAL);
+		for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
+			dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
+			if (addr)
+				pci_unmap_page(ppgtt->base.dev->pdev,
+				       addr,
+				       PAGE_SIZE,
+				       PCI_DMA_BIDIRECTIONAL);
 
-			}
 		}
-		kfree(ppgtt->gen8_pt_dma_addr[i]);
 	}
+}
 
-	__free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
-	__free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+{
+	struct i915_hw_ppgtt *ppgtt =
+		container_of(vm, struct i915_hw_ppgtt, base);
+
+	list_del(&vm->global_link);
+	drm_mm_takedown(&vm->mm);
+
+	gen8_ppgtt_unmap_pages(ppgtt);
+	gen8_ppgtt_free(ppgtt);
 }
 
 /**
@@ -386,6 +405,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
 	ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT);
 	ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE;
 	ppgtt->enable = gen8_ppgtt_enable;
+	ppgtt->switch_mm = gen8_mm_switch;
 	ppgtt->base.clear_range = gen8_ppgtt_clear_range;
 	ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
 	ppgtt->base.cleanup = gen8_ppgtt_cleanup;
@@ -458,6 +478,62 @@ err_out:
 	return ret;
 }
 
+static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
+{
+	struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private;
+	struct i915_address_space *vm = &ppgtt->base;
+	gen6_gtt_pte_t __iomem *pd_addr;
+	gen6_gtt_pte_t scratch_pte;
+	uint32_t pd_entry;
+	int pte, pde;
+
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+
+	pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm +
+		ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
+
+	seq_printf(m, "  VM %p (pd_offset %x-%x):\n", vm,
+		   ppgtt->pd_offset, ppgtt->pd_offset + ppgtt->num_pd_entries);
+	for (pde = 0; pde < ppgtt->num_pd_entries; pde++) {
+		u32 expected;
+		gen6_gtt_pte_t *pt_vaddr;
+		dma_addr_t pt_addr = ppgtt->pt_dma_addr[pde];
+		pd_entry = readl(pd_addr + pde);
+		expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID);
+
+		if (pd_entry != expected)
+			seq_printf(m, "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n",
+				   pde,
+				   pd_entry,
+				   expected);
+		seq_printf(m, "\tPDE: %x\n", pd_entry);
+
+		pt_vaddr = kmap_atomic(ppgtt->pt_pages[pde]);
+		for (pte = 0; pte < I915_PPGTT_PT_ENTRIES; pte+=4) {
+			unsigned long va =
+				(pde * PAGE_SIZE * I915_PPGTT_PT_ENTRIES) +
+				(pte * PAGE_SIZE);
+			int i;
+			bool found = false;
+			for (i = 0; i < 4; i++)
+				if (pt_vaddr[pte + i] != scratch_pte)
+					found = true;
+			if (!found)
+				continue;
+
+			seq_printf(m, "\t\t0x%lx [%03d,%04d]: =", va, pde, pte);
+			for (i = 0; i < 4; i++) {
+				if (pt_vaddr[pte + i] != scratch_pte)
+					seq_printf(m, " %08x", pt_vaddr[pte + i]);
+				else
+					seq_puts(m, "  SCRATCH ");
+			}
+			seq_puts(m, "\n");
+		}
+		kunmap_atomic(pt_vaddr);
+	}
+}
+
 static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 {
 	struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private;
@@ -480,61 +556,221 @@ static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 	readl(pd_addr);
 }
 
-static int gen6_ppgtt_enable(struct drm_device *dev)
+static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t pd_offset;
+	BUG_ON(ppgtt->pd_offset & 0x3f);
+
+	return (ppgtt->pd_offset / 64) << 16;
+}
+
+static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
+			 struct intel_ring_buffer *ring,
+			 bool synchronous)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* If we're in reset, we can assume the GPU is sufficiently idle to
+	 * manually frob these bits. Ideally we could use the ring functions,
+	 * except our error handling makes it quite difficult (can't use
+	 * intel_ring_begin, ring->flush, or intel_ring_advance)
+	 *
+	 * FIXME: We should try not to special case reset
+	 */
+	if (synchronous ||
+	    i915_reset_in_progress(&dev_priv->gpu_error)) {
+		WARN_ON(ppgtt != dev_priv->mm.aliasing_ppgtt);
+		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+		I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+		POSTING_READ(RING_PP_DIR_BASE(ring));
+		return 0;
+	}
+
+	/* NB: TLBs must be flushed and invalidated before a switch */
+	ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	if (ret)
+		return ret;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
+	intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
+	intel_ring_emit(ring, PP_DIR_DCLV_2G);
+	intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
+	intel_ring_emit(ring, get_pd_offset(ppgtt));
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
+			  struct intel_ring_buffer *ring,
+			  bool synchronous)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* If we're in reset, we can assume the GPU is sufficiently idle to
+	 * manually frob these bits. Ideally we could use the ring functions,
+	 * except our error handling makes it quite difficult (can't use
+	 * intel_ring_begin, ring->flush, or intel_ring_advance)
+	 *
+	 * FIXME: We should try not to special case reset
+	 */
+	if (synchronous ||
+	    i915_reset_in_progress(&dev_priv->gpu_error)) {
+		WARN_ON(ppgtt != dev_priv->mm.aliasing_ppgtt);
+		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+		I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+		POSTING_READ(RING_PP_DIR_BASE(ring));
+		return 0;
+	}
+
+	/* NB: TLBs must be flushed and invalidated before a switch */
+	ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	if (ret)
+		return ret;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
+	intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
+	intel_ring_emit(ring, PP_DIR_DCLV_2G);
+	intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
+	intel_ring_emit(ring, get_pd_offset(ppgtt));
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	/* XXX: RCS is the only one to auto invalidate the TLBs? */
+	if (ring->id != RCS) {
+		ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
+			  struct intel_ring_buffer *ring,
+			  bool synchronous)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!synchronous)
+		return 0;
+
+	I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+	I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+
+	POSTING_READ(RING_PP_DIR_DCLV(ring));
+
+	return 0;
+}
+
+static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-	int i;
+	int j, ret;
 
-	BUG_ON(ppgtt->pd_offset & 0x3f);
+	for_each_ring(ring, dev_priv, j) {
+		I915_WRITE(RING_MODE_GEN7(ring),
+			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 
-	gen6_write_pdes(ppgtt);
+		/* We promise to do a switch later with FULL PPGTT. If this is
+		 * aliasing, this is the one and only switch we'll do */
+		if (USES_FULL_PPGTT(dev))
+			continue;
 
-	pd_offset = ppgtt->pd_offset;
-	pd_offset /= 64; /* in cachelines, */
-	pd_offset <<= 16;
+		ret = ppgtt->switch_mm(ppgtt, ring, true);
+		if (ret)
+			goto err_out;
+	}
 
-	if (INTEL_INFO(dev)->gen == 6) {
-		uint32_t ecochk, gab_ctl, ecobits;
+	return 0;
 
-		ecobits = I915_READ(GAC_ECO_BITS);
-		I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT |
-					 ECOBITS_PPGTT_CACHE64B);
+err_out:
+	for_each_ring(ring, dev_priv, j)
+		I915_WRITE(RING_MODE_GEN7(ring),
+			   _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE));
+	return ret;
+}
 
-		gab_ctl = I915_READ(GAB_CTL);
-		I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
+static int gen7_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	uint32_t ecochk, ecobits;
+	int i;
 
-		ecochk = I915_READ(GAM_ECOCHK);
-		I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
-				       ECOCHK_PPGTT_CACHE64B);
-		I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
-	} else if (INTEL_INFO(dev)->gen >= 7) {
-		uint32_t ecochk, ecobits;
+	ecobits = I915_READ(GAC_ECO_BITS);
+	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
 
-		ecobits = I915_READ(GAC_ECO_BITS);
-		I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
+	ecochk = I915_READ(GAM_ECOCHK);
+	if (IS_HASWELL(dev)) {
+		ecochk |= ECOCHK_PPGTT_WB_HSW;
+	} else {
+		ecochk |= ECOCHK_PPGTT_LLC_IVB;
+		ecochk &= ~ECOCHK_PPGTT_GFDT_IVB;
+	}
+	I915_WRITE(GAM_ECOCHK, ecochk);
 
-		ecochk = I915_READ(GAM_ECOCHK);
-		if (IS_HASWELL(dev)) {
-			ecochk |= ECOCHK_PPGTT_WB_HSW;
-		} else {
-			ecochk |= ECOCHK_PPGTT_LLC_IVB;
-			ecochk &= ~ECOCHK_PPGTT_GFDT_IVB;
-		}
-		I915_WRITE(GAM_ECOCHK, ecochk);
+	for_each_ring(ring, dev_priv, i) {
+		int ret;
 		/* GFX_MODE is per-ring on gen7+ */
+		I915_WRITE(RING_MODE_GEN7(ring),
+			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+
+		/* We promise to do a switch later with FULL PPGTT. If this is
+		 * aliasing, this is the one and only switch we'll do */
+		if (USES_FULL_PPGTT(dev))
+			continue;
+
+		ret = ppgtt->switch_mm(ppgtt, ring, true);
+		if (ret)
+			return ret;
 	}
 
-	for_each_ring(ring, dev_priv, i) {
-		if (INTEL_INFO(dev)->gen >= 7)
-			I915_WRITE(RING_MODE_GEN7(ring),
-				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+	return 0;
+}
 
-		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-		I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
+static int gen6_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	uint32_t ecochk, gab_ctl, ecobits;
+	int i;
+
+	ecobits = I915_READ(GAC_ECO_BITS);
+	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT |
+		   ECOBITS_PPGTT_CACHE64B);
+
+	gab_ctl = I915_READ(GAB_CTL);
+	I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
+
+	ecochk = I915_READ(GAM_ECOCHK);
+	I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B);
+
+	I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+
+	for_each_ring(ring, dev_priv, i) {
+		int ret = ppgtt->switch_mm(ppgtt, ring, true);
+		if (ret)
+			return ret;
 	}
+
 	return 0;
 }
 
@@ -608,7 +844,9 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 		container_of(vm, struct i915_hw_ppgtt, base);
 	int i;
 
+	list_del(&vm->global_link);
 	drm_mm_takedown(&ppgtt->base.mm);
+	drm_mm_remove_node(&ppgtt->node);
 
 	if (ppgtt->pt_dma_addr) {
 		for (i = 0; i < ppgtt->num_pd_entries; i++)
@@ -626,20 +864,51 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 
 static int gen6_ppgtt_init(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;
-	unsigned first_pd_entry_in_global_pt;
-	int i;
-	int ret = -ENOMEM;
+	bool retried = false;
+	int i, ret;
+
+	/* PPGTT PDEs reside in the GGTT and consists of 512 entries. The
+	 * allocator works in address space sizes, so it's multiplied by page
+	 * size. We allocate at the top of the GTT to avoid fragmentation.
+	 */
+	BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm));
+alloc:
+	ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm,
+						  &ppgtt->node, GEN6_PD_SIZE,
+						  GEN6_PD_ALIGN, 0,
+						  0, dev_priv->gtt.base.total,
+						  DRM_MM_SEARCH_DEFAULT);
+	if (ret == -ENOSPC && !retried) {
+		ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
+					       GEN6_PD_SIZE, GEN6_PD_ALIGN,
+					       I915_CACHE_NONE, 0);
+		if (ret)
+			return ret;
+
+		retried = true;
+		goto alloc;
+	}
 
-	/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
-	 * entries. For aliasing ppgtt support we just steal them at the end for
-	 * now. */
-	first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
+	if (ppgtt->node.start < dev_priv->gtt.mappable_end)
+		DRM_DEBUG("Forced to use aperture for PDEs\n");
 
 	ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
 	ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
-	ppgtt->enable = gen6_ppgtt_enable;
+	if (IS_GEN6(dev)) {
+		ppgtt->enable = gen6_ppgtt_enable;
+		ppgtt->switch_mm = gen6_mm_switch;
+	} else if (IS_HASWELL(dev)) {
+		ppgtt->enable = gen7_ppgtt_enable;
+		ppgtt->switch_mm = hsw_mm_switch;
+	} else if (IS_GEN7(dev)) {
+		ppgtt->enable = gen7_ppgtt_enable;
+		ppgtt->switch_mm = gen7_mm_switch;
+	} else
+		BUG();
 	ppgtt->base.clear_range = gen6_ppgtt_clear_range;
 	ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
 	ppgtt->base.cleanup = gen6_ppgtt_cleanup;
@@ -648,8 +917,10 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 	ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
 	ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
 				  GFP_KERNEL);
-	if (!ppgtt->pt_pages)
+	if (!ppgtt->pt_pages) {
+		drm_mm_remove_node(&ppgtt->node);
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < ppgtt->num_pd_entries; i++) {
 		ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL);
@@ -678,8 +949,13 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 
 	ppgtt->base.clear_range(&ppgtt->base, 0,
 				ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
+	ppgtt->debug_dump = gen6_dump_ppgtt;
 
-	ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
+	DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n",
+			 ppgtt->node.size >> 20,
+			 ppgtt->node.start / PAGE_SIZE);
+	ppgtt->pd_offset =
+		ppgtt->node.start / PAGE_SIZE * sizeof(gen6_gtt_pte_t);
 
 	return 0;
 
@@ -696,19 +972,15 @@ err_pt_alloc:
 			__free_page(ppgtt->pt_pages[i]);
 	}
 	kfree(ppgtt->pt_pages);
+	drm_mm_remove_node(&ppgtt->node);
 
 	return ret;
 }
 
-static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
+int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_hw_ppgtt *ppgtt;
-	int ret;
-
-	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
-	if (!ppgtt)
-		return -ENOMEM;
+	int ret = 0;
 
 	ppgtt->base.dev = dev;
 
@@ -719,45 +991,42 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 	else
 		BUG();
 
-	if (ret)
-		kfree(ppgtt);
-	else {
-		dev_priv->mm.aliasing_ppgtt = ppgtt;
+	if (!ret) {
+		struct drm_i915_private *dev_priv = dev->dev_private;
+		kref_init(&ppgtt->ref);
 		drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
 			    ppgtt->base.total);
+		i915_init_vm(dev_priv, &ppgtt->base);
+		if (INTEL_INFO(dev)->gen < 8) {
+			gen6_write_pdes(ppgtt);
+			DRM_DEBUG("Adding PPGTT at offset %x\n",
+				  ppgtt->pd_offset << 10);
+		}
 	}
 
 	return ret;
 }
 
-void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
+static void
+ppgtt_bind_vma(struct i915_vma *vma,
+	       enum i915_cache_level cache_level,
+	       u32 flags)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+	const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 
-	if (!ppgtt)
-		return;
+	WARN_ON(flags);
 
-	ppgtt->base.cleanup(&ppgtt->base);
-	dev_priv->mm.aliasing_ppgtt = NULL;
+	vma->vm->insert_entries(vma->vm, vma->obj->pages, entry, cache_level);
 }
 
-void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
-			    struct drm_i915_gem_object *obj,
-			    enum i915_cache_level cache_level)
+static void ppgtt_unbind_vma(struct i915_vma *vma)
 {
-	ppgtt->base.insert_entries(&ppgtt->base, obj->pages,
-				   i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
-				   cache_level);
-}
+	const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 
-void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
-			      struct drm_i915_gem_object *obj)
-{
-	ppgtt->base.clear_range(&ppgtt->base,
-				i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
-				obj->base.size >> PAGE_SHIFT,
-				true);
+	vma->vm->clear_range(vma->vm,
+			     entry,
+			     vma->obj->base.size >> PAGE_SHIFT,
+			     true);
 }
 
 extern int intel_iommu_gfx_mapped;
@@ -849,6 +1118,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
+	struct i915_address_space *vm;
 
 	i915_check_and_clear_faults(dev);
 
@@ -859,8 +1129,33 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 				       true);
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		struct i915_vma *vma = i915_gem_obj_to_vma(obj,
+							   &dev_priv->gtt.base);
+		if (!vma)
+			continue;
+
 		i915_gem_clflush_object(obj, obj->pin_display);
-		i915_gem_gtt_bind_object(obj, obj->cache_level);
+		/* The bind_vma code tries to be smart about tracking mappings.
+		 * Unfortunately above, we've just wiped out the mappings
+		 * without telling our object about it. So we need to fake it.
+		 */
+		obj->has_global_gtt_mapping = 0;
+		vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
+	}
+
+
+	if (INTEL_INFO(dev)->gen >= 8)
+		return;
+
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		/* TODO: Perhaps it shouldn't be gen6 specific */
+		if (i915_is_ggtt(vm)) {
+			if (dev_priv->mm.aliasing_ppgtt)
+				gen6_write_pdes(dev_priv->mm.aliasing_ppgtt);
+			continue;
+		}
+
+		gen6_write_pdes(container_of(vm, struct i915_hw_ppgtt, base));
 	}
 
 	i915_gem_chipset_flush(dev);
@@ -1017,16 +1312,18 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
 	readl(gtt_base);
 }
 
-static void i915_ggtt_insert_entries(struct i915_address_space *vm,
-				     struct sg_table *st,
-				     unsigned int pg_start,
-				     enum i915_cache_level cache_level)
+
+static void i915_ggtt_bind_vma(struct i915_vma *vma,
+			       enum i915_cache_level cache_level,
+			       u32 unused)
 {
+	const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
 
-	intel_gtt_insert_sg_entries(st, pg_start, flags);
-
+	BUG_ON(!i915_is_ggtt(vma->vm));
+	intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags);
+	vma->obj->has_global_gtt_mapping = 1;
 }
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
@@ -1037,33 +1334,77 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm,
 	intel_gtt_clear_range(first_entry, num_entries);
 }
 
+static void i915_ggtt_unbind_vma(struct i915_vma *vma)
+{
+	const unsigned int first = vma->node.start >> PAGE_SHIFT;
+	const unsigned int size = vma->obj->base.size >> PAGE_SHIFT;
+
+	BUG_ON(!i915_is_ggtt(vma->vm));
+	vma->obj->has_global_gtt_mapping = 0;
+	intel_gtt_clear_range(first, size);
+}
 
-void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
-			      enum i915_cache_level cache_level)
+static void ggtt_bind_vma(struct i915_vma *vma,
+			  enum i915_cache_level cache_level,
+			  u32 flags)
 {
-	struct drm_device *dev = obj->base.dev;
+	struct drm_device *dev = vma->vm->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
+	struct drm_i915_gem_object *obj = vma->obj;
+	const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 
-	dev_priv->gtt.base.insert_entries(&dev_priv->gtt.base, obj->pages,
-					  entry,
-					  cache_level);
+	/* If there is no aliasing PPGTT, or the caller needs a global mapping,
+	 * or we have a global mapping already but the cacheability flags have
+	 * changed, set the global PTEs.
+	 *
+	 * If there is an aliasing PPGTT it is anecdotally faster, so use that
+	 * instead if none of the above hold true.
+	 *
+	 * NB: A global mapping should only be needed for special regions like
+	 * "gtt mappable", SNB errata, or if specified via special execbuf
+	 * flags. At all other times, the GPU will use the aliasing PPGTT.
+	 */
+	if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+		if (!obj->has_global_gtt_mapping ||
+		    (cache_level != obj->cache_level)) {
+			vma->vm->insert_entries(vma->vm, obj->pages, entry,
+						cache_level);
+			obj->has_global_gtt_mapping = 1;
+		}
+	}
 
-	obj->has_global_gtt_mapping = 1;
+	if (dev_priv->mm.aliasing_ppgtt &&
+	    (!obj->has_aliasing_ppgtt_mapping ||
+	     (cache_level != obj->cache_level))) {
+		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
+		appgtt->base.insert_entries(&appgtt->base,
+					    vma->obj->pages, entry, cache_level);
+		vma->obj->has_aliasing_ppgtt_mapping = 1;
+	}
 }
 
-void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
+static void ggtt_unbind_vma(struct i915_vma *vma)
 {
-	struct drm_device *dev = obj->base.dev;
+	struct drm_device *dev = vma->vm->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
-
-	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
-				       entry,
-				       obj->base.size >> PAGE_SHIFT,
-				       true);
+	struct drm_i915_gem_object *obj = vma->obj;
+	const unsigned long entry = vma->node.start >> PAGE_SHIFT;
+
+	if (obj->has_global_gtt_mapping) {
+		vma->vm->clear_range(vma->vm, entry,
+				     vma->obj->base.size >> PAGE_SHIFT,
+				     true);
+		obj->has_global_gtt_mapping = 0;
+	}
 
-	obj->has_global_gtt_mapping = 0;
+	if (obj->has_aliasing_ppgtt_mapping) {
+		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
+		appgtt->base.clear_range(&appgtt->base,
+					 entry,
+					 obj->base.size >> PAGE_SHIFT,
+					 true);
+		obj->has_aliasing_ppgtt_mapping = 0;
+	}
 }
 
 void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
@@ -1155,21 +1496,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
 	ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
 }
 
-static bool
-intel_enable_ppgtt(struct drm_device *dev)
-{
-	if (i915_enable_ppgtt >= 0)
-		return i915_enable_ppgtt;
-
-#ifdef CONFIG_INTEL_IOMMU
-	/* Disable ppgtt on SNB if VT-d is on. */
-	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
-		return false;
-#endif
-
-	return true;
-}
-
 void i915_gem_init_global_gtt(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1178,26 +1504,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 	gtt_size = dev_priv->gtt.base.total;
 	mappable_size = dev_priv->gtt.mappable_end;
 
-	if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
-		int ret;
-
-		if (INTEL_INFO(dev)->gen <= 7) {
-			/* PPGTT pdes are stolen from global gtt ptes, so shrink the
-			 * aperture accordingly when using aliasing ppgtt. */
-			gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
-		}
-
-		i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
-
-		ret = i915_gem_init_aliasing_ppgtt(dev);
-		if (!ret)
-			return;
-
-		DRM_ERROR("Aliased PPGTT setup failed %d\n", ret);
-		drm_mm_takedown(&dev_priv->gtt.base.mm);
-		if (INTEL_INFO(dev)->gen < 8)
-			gtt_size += GEN6_PPGTT_PD_ENTRIES*PAGE_SIZE;
-	}
 	i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
 }
 
@@ -1253,7 +1559,7 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
 	if (bdw_gmch_ctl)
 		bdw_gmch_ctl = 1 << bdw_gmch_ctl;
 	if (bdw_gmch_ctl > 4) {
-		WARN_ON(!i915_preliminary_hw_support);
+		WARN_ON(!i915.preliminary_hw_support);
 		return 4<<20;
 	}
 
@@ -1438,7 +1744,6 @@ static int i915_gmch_probe(struct drm_device *dev,
 
 	dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
 	dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
-	dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
 
 	if (unlikely(dev_priv->gtt.do_idle_maps))
 		DRM_INFO("applying Ironlake quirks for intel_iommu\n");
@@ -1493,3 +1798,62 @@ int i915_gem_gtt_init(struct drm_device *dev)
 
 	return 0;
 }
+
+static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
+					      struct i915_address_space *vm)
+{
+	struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+	if (vma == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&vma->vma_link);
+	INIT_LIST_HEAD(&vma->mm_list);
+	INIT_LIST_HEAD(&vma->exec_list);
+	vma->vm = vm;
+	vma->obj = obj;
+
+	switch (INTEL_INFO(vm->dev)->gen) {
+	case 8:
+	case 7:
+	case 6:
+		if (i915_is_ggtt(vm)) {
+			vma->unbind_vma = ggtt_unbind_vma;
+			vma->bind_vma = ggtt_bind_vma;
+		} else {
+			vma->unbind_vma = ppgtt_unbind_vma;
+			vma->bind_vma = ppgtt_bind_vma;
+		}
+		break;
+	case 5:
+	case 4:
+	case 3:
+	case 2:
+		BUG_ON(!i915_is_ggtt(vm));
+		vma->unbind_vma = i915_ggtt_unbind_vma;
+		vma->bind_vma = i915_ggtt_bind_vma;
+		break;
+	default:
+		BUG();
+	}
+
+	/* Keep GGTT vmas first to make debug easier */
+	if (i915_is_ggtt(vm))
+		list_add(&vma->vma_link, &obj->vma_list);
+	else
+		list_add_tail(&vma->vma_link, &obj->vma_list);
+
+	return vma;
+}
+
+struct i915_vma *
+i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
+				  struct i915_address_space *vm)
+{
+	struct i915_vma *vma;
+
+	vma = i915_gem_obj_to_vma(obj, vm);
+	if (!vma)
+		vma = __i915_gem_vma_create(obj, vm);
+
+	return vma;
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 1a24e84f2315..d58b4e287e32 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -82,9 +82,22 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 	r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
 				    "Graphics Stolen Memory");
 	if (r == NULL) {
-		DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
-			  base, base + (uint32_t)dev_priv->gtt.stolen_size);
-		base = 0;
+		/*
+		 * One more attempt but this time requesting region from
+		 * base + 1, as we have seen that this resolves the region
+		 * conflict with the PCI Bus.
+		 * This is a BIOS w/a: Some BIOS wrap stolen in the root
+		 * PCI bus, but have an off-by-one error. Hence retry the
+		 * reservation starting from 1 instead of 0.
+		 */
+		r = devm_request_mem_region(dev->dev, base + 1,
+					    dev_priv->gtt.stolen_size - 1,
+					    "Graphics Stolen Memory");
+		if (r == NULL) {
+			DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
+				  base, base + (uint32_t)dev_priv->gtt.stolen_size);
+			base = 0;
+		}
 	}
 
 	return base;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index b13905348048..eb993584aa6b 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -308,7 +308,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 		return -EINVAL;
 	}
 
-	if (obj->pin_count || obj->framebuffer_references) {
+	if (i915_gem_obj_is_pinned(obj) || obj->framebuffer_references) {
 		drm_gem_object_unreference_unlocked(&obj->base);
 		return -EBUSY;
 	}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 990cf8f43efd..000b3694f349 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -238,50 +238,61 @@ static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a)
 
 static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
 				  struct drm_device *dev,
-				  struct drm_i915_error_state *error,
-				  unsigned ring)
+				  struct drm_i915_error_ring *ring)
 {
-	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
-	if (!error->ring[ring].valid)
+	if (!ring->valid)
 		return;
 
-	err_printf(m, "%s command stream:\n", ring_str(ring));
-	err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
-	err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
-	err_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
-	err_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
-	err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
-	err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
-	err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
+	err_printf(m, "  HEAD: 0x%08x\n", ring->head);
+	err_printf(m, "  TAIL: 0x%08x\n", ring->tail);
+	err_printf(m, "  CTL: 0x%08x\n", ring->ctl);
+	err_printf(m, "  HWS: 0x%08x\n", ring->hws);
+	err_printf(m, "  ACTHD: 0x%08x\n", ring->acthd);
+	err_printf(m, "  IPEIR: 0x%08x\n", ring->ipeir);
+	err_printf(m, "  IPEHR: 0x%08x\n", ring->ipehr);
+	err_printf(m, "  INSTDONE: 0x%08x\n", ring->instdone);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr[ring]);
-		err_printf(m, "  BB_STATE: 0x%08x\n", error->bbstate[ring]);
-		err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+		err_printf(m, "  BBADDR: 0x%08llx\n", ring->bbaddr);
+		err_printf(m, "  BB_STATE: 0x%08x\n", ring->bbstate);
+		err_printf(m, "  INSTPS: 0x%08x\n", ring->instps);
 	}
-	err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
-	err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
+	err_printf(m, "  INSTPM: 0x%08x\n", ring->instpm);
+	err_printf(m, "  FADDR: 0x%08x\n", ring->faddr);
 	if (INTEL_INFO(dev)->gen >= 6) {
-		err_printf(m, "  RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
-		err_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
+		err_printf(m, "  RC PSMI: 0x%08x\n", ring->rc_psmi);
+		err_printf(m, "  FAULT_REG: 0x%08x\n", ring->fault_reg);
 		err_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
-			   error->semaphore_mboxes[ring][0],
-			   error->semaphore_seqno[ring][0]);
+			   ring->semaphore_mboxes[0],
+			   ring->semaphore_seqno[0]);
 		err_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
-			   error->semaphore_mboxes[ring][1],
-			   error->semaphore_seqno[ring][1]);
+			   ring->semaphore_mboxes[1],
+			   ring->semaphore_seqno[1]);
 		if (HAS_VEBOX(dev)) {
 			err_printf(m, "  SYNC_2: 0x%08x [last synced 0x%08x]\n",
-				   error->semaphore_mboxes[ring][2],
-				   error->semaphore_seqno[ring][2]);
+				   ring->semaphore_mboxes[2],
+				   ring->semaphore_seqno[2]);
 		}
 	}
-	err_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
-	err_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
-	err_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
-	err_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
+	if (USES_PPGTT(dev)) {
+		err_printf(m, "  GFX_MODE: 0x%08x\n", ring->vm_info.gfx_mode);
+
+		if (INTEL_INFO(dev)->gen >= 8) {
+			int i;
+			for (i = 0; i < 4; i++)
+				err_printf(m, "  PDP%d: 0x%016llx\n",
+					   i, ring->vm_info.pdp[i]);
+		} else {
+			err_printf(m, "  PP_DIR_BASE: 0x%08x\n",
+				   ring->vm_info.pp_dir_base);
+		}
+	}
+	err_printf(m, "  seqno: 0x%08x\n", ring->seqno);
+	err_printf(m, "  waiting: %s\n", yesno(ring->waiting));
+	err_printf(m, "  ring->head: 0x%08x\n", ring->cpu_ring_head);
+	err_printf(m, "  ring->tail: 0x%08x\n", ring->cpu_ring_tail);
 	err_printf(m, "  hangcheck: %s [%d]\n",
-		   hangcheck_action_to_str(error->hangcheck_action[ring]),
-		   error->hangcheck_score[ring]);
+		   hangcheck_action_to_str(ring->hangcheck_action),
+		   ring->hangcheck_score);
 }
 
 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -333,8 +344,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 	if (INTEL_INFO(dev)->gen == 7)
 		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
-	for (i = 0; i < ARRAY_SIZE(error->ring); i++)
-		i915_ring_error_state(m, dev, error, i);
+	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
+		err_printf(m, "%s command stream:\n", ring_str(i));
+		i915_ring_error_state(m, dev, &error->ring[i]);
+	}
 
 	if (error->active_bo)
 		print_error_buffers(m, "Active",
@@ -390,6 +403,22 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 			}
 		}
 
+		if ((obj = error->ring[i].hws_page)) {
+			err_printf(m, "%s --- HW Status = 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;
+			}
+		}
+
 		if ((obj = error->ring[i].ctx)) {
 			err_printf(m, "%s --- HW Context = 0x%08x\n",
 				   dev_priv->ring[i].name,
@@ -472,6 +501,7 @@ static void i915_error_state_free(struct kref *error_ref)
 	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
 		i915_error_object_free(error->ring[i].batchbuffer);
 		i915_error_object_free(error->ring[i].ringbuffer);
+		i915_error_object_free(error->ring[i].hws_page);
 		i915_error_object_free(error->ring[i].ctx);
 		kfree(error->ring[i].requests);
 	}
@@ -485,6 +515,7 @@ static void i915_error_state_free(struct kref *error_ref)
 static struct drm_i915_error_object *
 i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 			       struct drm_i915_gem_object *src,
+			       struct i915_address_space *vm,
 			       const int num_pages)
 {
 	struct drm_i915_error_object *dst;
@@ -498,7 +529,7 @@ i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 	if (dst == NULL)
 		return NULL;
 
-	reloc_offset = dst->gtt_offset = i915_gem_obj_ggtt_offset(src);
+	reloc_offset = dst->gtt_offset = i915_gem_obj_offset(src, vm);
 	for (i = 0; i < num_pages; i++) {
 		unsigned long flags;
 		void *d;
@@ -508,8 +539,10 @@ i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 			goto unwind;
 
 		local_irq_save(flags);
-		if (reloc_offset < dev_priv->gtt.mappable_end &&
-		    src->has_global_gtt_mapping) {
+		if (src->cache_level == I915_CACHE_NONE &&
+		    reloc_offset < dev_priv->gtt.mappable_end &&
+		    src->has_global_gtt_mapping &&
+		    i915_is_ggtt(vm)) {
 			void __iomem *s;
 
 			/* Simply ignore tiling or any overlapping fence.
@@ -559,8 +592,12 @@ unwind:
 	kfree(dst);
 	return NULL;
 }
-#define i915_error_object_create(dev_priv, src) \
-	i915_error_object_create_sized((dev_priv), (src), \
+#define i915_error_object_create(dev_priv, src, vm) \
+	i915_error_object_create_sized((dev_priv), (src), (vm), \
+				       (src)->base.size>>PAGE_SHIFT)
+
+#define i915_error_ggtt_object_create(dev_priv, src) \
+	i915_error_object_create_sized((dev_priv), (src), &(dev_priv)->gtt.base, \
 				       (src)->base.size>>PAGE_SHIFT)
 
 static void capture_bo(struct drm_i915_error_buffer *err,
@@ -575,7 +612,7 @@ static void capture_bo(struct drm_i915_error_buffer *err,
 	err->write_domain = obj->base.write_domain;
 	err->fence_reg = obj->fence_reg;
 	err->pinned = 0;
-	if (obj->pin_count > 0)
+	if (i915_gem_obj_is_pinned(obj))
 		err->pinned = 1;
 	if (obj->user_pin_count > 0)
 		err->pinned = -1;
@@ -608,7 +645,7 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
 	int i = 0;
 
 	list_for_each_entry(obj, head, global_list) {
-		if (obj->pin_count == 0)
+		if (!i915_gem_obj_is_pinned(obj))
 			continue;
 
 		capture_bo(err++, obj);
@@ -619,6 +656,33 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
 	return i;
 }
 
+/* Generate a semi-unique error code. The code is not meant to have meaning, The
+ * code's only purpose is to try to prevent false duplicated bug reports by
+ * grossly estimating a GPU error state.
+ *
+ * TODO Ideally, hashing the batchbuffer would be a very nice way to determine
+ * the hang if we could strip the GTT offset information from it.
+ *
+ * It's only a small step better than a random number in its current form.
+ */
+static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv,
+					 struct drm_i915_error_state *error)
+{
+	uint32_t error_code = 0;
+	int i;
+
+	/* IPEHR would be an ideal way to detect errors, as it's the gross
+	 * measure of "the command that hung." However, has some very common
+	 * synchronization commands which almost always appear in the case
+	 * strictly a client bug. Use instdone to differentiate those some.
+	 */
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		if (error->ring[i].hangcheck_action == HANGCHECK_HUNG)
+			return error->ring[i].ipehr ^ error->ring[i].instdone;
+
+	return error_code;
+}
+
 static void i915_gem_record_fences(struct drm_device *dev,
 				   struct drm_i915_error_state *error)
 {
@@ -652,6 +716,32 @@ static void i915_gem_record_fences(struct drm_device *dev,
 	}
 }
 
+/* This assumes all batchbuffers are executed from the PPGTT. It might have to
+ * change in the future. */
+static bool is_active_vm(struct i915_address_space *vm,
+			 struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_hw_ppgtt *ppgtt;
+
+	if (INTEL_INFO(dev)->gen < 7)
+		return i915_is_ggtt(vm);
+
+	/* FIXME: This ignores that the global gtt vm is also on this list. */
+	ppgtt = container_of(vm, struct i915_hw_ppgtt, base);
+
+	if (INTEL_INFO(dev)->gen >= 8) {
+		u64 pdp0 = (u64)I915_READ(GEN8_RING_PDP_UDW(ring, 0)) << 32;
+		pdp0 |=  I915_READ(GEN8_RING_PDP_LDW(ring, 0));
+		return pdp0 == ppgtt->pd_dma_addr[0];
+	} else {
+		u32 pp_db;
+		pp_db = I915_READ(RING_PP_DIR_BASE(ring));
+		return (pp_db >> 10) == ppgtt->pd_offset;
+	}
+}
+
 static struct drm_i915_error_object *
 i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 			     struct intel_ring_buffer *ring)
@@ -659,6 +749,7 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 	struct i915_address_space *vm;
 	struct i915_vma *vma;
 	struct drm_i915_gem_object *obj;
+	bool found_active = false;
 	u32 seqno;
 
 	if (!ring->get_seqno)
@@ -674,11 +765,16 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 		if (obj != NULL &&
 		    acthd >= i915_gem_obj_ggtt_offset(obj) &&
 		    acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
-			return i915_error_object_create(dev_priv, obj);
+			return i915_error_ggtt_object_create(dev_priv, obj);
 	}
 
 	seqno = ring->get_seqno(ring, false);
 	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		if (!is_active_vm(vm, ring))
+			continue;
+
+		found_active = true;
+
 		list_for_each_entry(vma, &vm->active_list, mm_list) {
 			obj = vma->obj;
 			if (obj->ring != ring)
@@ -693,66 +789,120 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 			/* We need to copy these to an anonymous buffer as the simplest
 			 * method to avoid being overwritten by userspace.
 			 */
-			return i915_error_object_create(dev_priv, obj);
+			return i915_error_object_create(dev_priv, obj, vm);
 		}
 	}
 
+	WARN_ON(!found_active);
 	return NULL;
 }
 
 static void i915_record_ring_state(struct drm_device *dev,
-				   struct drm_i915_error_state *error,
-				   struct intel_ring_buffer *ring)
+				   struct intel_ring_buffer *ring,
+				   struct drm_i915_error_ring *ering)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (INTEL_INFO(dev)->gen >= 6) {
-		error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
-		error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
-		error->semaphore_mboxes[ring->id][0]
+		ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
+		ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
+		ering->semaphore_mboxes[0]
 			= I915_READ(RING_SYNC_0(ring->mmio_base));
-		error->semaphore_mboxes[ring->id][1]
+		ering->semaphore_mboxes[1]
 			= I915_READ(RING_SYNC_1(ring->mmio_base));
-		error->semaphore_seqno[ring->id][0] = ring->sync_seqno[0];
-		error->semaphore_seqno[ring->id][1] = ring->sync_seqno[1];
+		ering->semaphore_seqno[0] = ring->sync_seqno[0];
+		ering->semaphore_seqno[1] = ring->sync_seqno[1];
 	}
 
 	if (HAS_VEBOX(dev)) {
-		error->semaphore_mboxes[ring->id][2] =
+		ering->semaphore_mboxes[2] =
 			I915_READ(RING_SYNC_2(ring->mmio_base));
-		error->semaphore_seqno[ring->id][2] = ring->sync_seqno[2];
+		ering->semaphore_seqno[2] = ring->sync_seqno[2];
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
-		error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
-		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
-		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
-		error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-		error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
+		ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base));
+		ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base));
+		ering->ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
+		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)
-			error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
-		error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
+			ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
+		ering->bbstate = I915_READ(RING_BBSTATE(ring->mmio_base));
 	} else {
-		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
-		error->ipeir[ring->id] = I915_READ(IPEIR);
-		error->ipehr[ring->id] = I915_READ(IPEHR);
-		error->instdone[ring->id] = I915_READ(INSTDONE);
+		ering->faddr = I915_READ(DMA_FADD_I8XX);
+		ering->ipeir = I915_READ(IPEIR);
+		ering->ipehr = I915_READ(IPEHR);
+		ering->instdone = I915_READ(INSTDONE);
 	}
 
-	error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
-	error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
-	error->seqno[ring->id] = ring->get_seqno(ring, false);
-	error->acthd[ring->id] = intel_ring_get_active_head(ring);
-	error->head[ring->id] = I915_READ_HEAD(ring);
-	error->tail[ring->id] = I915_READ_TAIL(ring);
-	error->ctl[ring->id] = I915_READ_CTL(ring);
+	ering->waiting = waitqueue_active(&ring->irq_queue);
+	ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base));
+	ering->seqno = ring->get_seqno(ring, false);
+	ering->acthd = intel_ring_get_active_head(ring);
+	ering->head = I915_READ_HEAD(ring);
+	ering->tail = I915_READ_TAIL(ring);
+	ering->ctl = I915_READ_CTL(ring);
+
+	if (I915_NEED_GFX_HWS(dev)) {
+		int mmio;
+
+		if (IS_GEN7(dev)) {
+			switch (ring->id) {
+			default:
+			case RCS:
+				mmio = RENDER_HWS_PGA_GEN7;
+				break;
+			case BCS:
+				mmio = BLT_HWS_PGA_GEN7;
+				break;
+			case VCS:
+				mmio = BSD_HWS_PGA_GEN7;
+				break;
+			case VECS:
+				mmio = VEBOX_HWS_PGA_GEN7;
+				break;
+			}
+		} else if (IS_GEN6(ring->dev)) {
+			mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
+		} else {
+			/* XXX: gen8 returns to sanity */
+			mmio = RING_HWS_PGA(ring->mmio_base);
+		}
+
+		ering->hws = I915_READ(mmio);
+	}
+
+	ering->cpu_ring_head = ring->head;
+	ering->cpu_ring_tail = ring->tail;
+
+	ering->hangcheck_score = ring->hangcheck.score;
+	ering->hangcheck_action = ring->hangcheck.action;
+
+	if (USES_PPGTT(dev)) {
+		int i;
 
-	error->cpu_ring_head[ring->id] = ring->head;
-	error->cpu_ring_tail[ring->id] = ring->tail;
+		ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring));
 
-	error->hangcheck_score[ring->id] = ring->hangcheck.score;
-	error->hangcheck_action[ring->id] = ring->hangcheck.action;
+		switch (INTEL_INFO(dev)->gen) {
+		case 8:
+			for (i = 0; i < 4; i++) {
+				ering->vm_info.pdp[i] =
+					I915_READ(GEN8_RING_PDP_UDW(ring, i));
+				ering->vm_info.pdp[i] <<= 32;
+				ering->vm_info.pdp[i] |=
+					I915_READ(GEN8_RING_PDP_LDW(ring, i));
+			}
+			break;
+		case 7:
+			ering->vm_info.pp_dir_base = RING_PP_DIR_BASE(ring);
+			break;
+		case 6:
+			ering->vm_info.pp_dir_base = RING_PP_DIR_BASE_READ(ring);
+			break;
+		}
+	}
 }
 
 
@@ -770,7 +920,9 @@ 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, 1);
+								    obj,
+								    &dev_priv->gtt.base,
+								    1);
 			break;
 		}
 	}
@@ -791,14 +943,17 @@ static void i915_gem_record_rings(struct drm_device *dev,
 
 		error->ring[i].valid = true;
 
-		i915_record_ring_state(dev, error, ring);
+		i915_record_ring_state(dev, ring, &error->ring[i]);
 
 		error->ring[i].batchbuffer =
 			i915_error_first_batchbuffer(dev_priv, ring);
 
 		error->ring[i].ringbuffer =
-			i915_error_object_create(dev_priv, ring->obj);
+			i915_error_ggtt_object_create(dev_priv, ring->obj);
 
+		if (ring->status_page.obj)
+			error->ring[i].hws_page =
+				i915_error_ggtt_object_create(dev_priv, ring->status_page.obj);
 
 		i915_gem_record_active_context(ring, error, &error->ring[i]);
 
@@ -845,7 +1000,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
 		i++;
 	error->active_bo_count[ndx] = i;
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
-		if (obj->pin_count)
+		if (i915_gem_obj_is_pinned(obj))
 			i++;
 	error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
 
@@ -879,11 +1034,6 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
 	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
 		cnt++;
 
-	if (WARN(cnt > 1, "Multiple VMs not yet supported\n"))
-		cnt = 1;
-
-	vm = &dev_priv->gtt.base;
-
 	error->active_bo = kcalloc(cnt, sizeof(*error->active_bo), GFP_ATOMIC);
 	error->pinned_bo = kcalloc(cnt, sizeof(*error->pinned_bo), GFP_ATOMIC);
 	error->active_bo_count = kcalloc(cnt, sizeof(*error->active_bo_count),
@@ -895,6 +1045,74 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
 		i915_gem_capture_vm(dev_priv, error, vm, i++);
 }
 
+/* Capture all registers which don't fit into another category. */
+static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
+				   struct drm_i915_error_state *error)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int pipe;
+
+	/* General organization
+	 * 1. Registers specific to a single generation
+	 * 2. Registers which belong to multiple generations
+	 * 3. Feature specific registers.
+	 * 4. Everything else
+	 * Please try to follow the order.
+	 */
+
+	/* 1: Registers specific to a single generation */
+	if (IS_VALLEYVIEW(dev)) {
+		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+		error->forcewake = I915_READ(FORCEWAKE_VLV);
+	}
+
+	if (IS_GEN7(dev))
+		error->err_int = I915_READ(GEN7_ERR_INT);
+
+	if (IS_GEN6(dev)) {
+		error->forcewake = I915_READ(FORCEWAKE);
+		error->gab_ctl = I915_READ(GAB_CTL);
+		error->gfx_mode = I915_READ(GFX_MODE);
+	}
+
+	if (IS_GEN2(dev))
+		error->ier = I915_READ16(IER);
+
+	/* 2: Registers which belong to multiple generations */
+	if (INTEL_INFO(dev)->gen >= 7)
+		error->forcewake = I915_READ(FORCEWAKE_MT);
+
+	if (INTEL_INFO(dev)->gen >= 6) {
+		error->derrmr = I915_READ(DERRMR);
+		error->error = I915_READ(ERROR_GEN6);
+		error->done_reg = I915_READ(DONE_REG);
+	}
+
+	/* 3: Feature specific registers */
+	if (IS_GEN6(dev) || IS_GEN7(dev)) {
+		error->gam_ecochk = I915_READ(GAM_ECOCHK);
+		error->gac_eco = I915_READ(GAC_ECO_BITS);
+	}
+
+	/* 4: Everything else */
+	if (HAS_HW_CONTEXTS(dev))
+		error->ccid = I915_READ(CCID);
+
+	if (HAS_PCH_SPLIT(dev))
+		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
+	else {
+		error->ier = I915_READ(IER);
+		for_each_pipe(pipe)
+			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
+	}
+
+	/* 4: Everything else */
+	error->eir = I915_READ(EIR);
+	error->pgtbl_er = I915_READ(PGTBL_ER);
+
+	i915_get_extra_instdone(dev, error->extra_instdone);
+}
+
 /**
  * i915_capture_error_state - capture an error record for later analysis
  * @dev: drm device
@@ -906,10 +1124,11 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
  */
 void i915_capture_error_state(struct drm_device *dev)
 {
+	static bool warned;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error;
 	unsigned long flags;
-	int pipe;
+	uint32_t ecode;
 
 	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
 	error = dev_priv->gpu_error.first_error;
@@ -926,53 +1145,22 @@ void i915_capture_error_state(struct drm_device *dev)
 
 	DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n",
 		 dev->primary->index);
-	DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
-	DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
-	DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
-	DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
-
 	kref_init(&error->ref);
-	error->eir = I915_READ(EIR);
-	error->pgtbl_er = I915_READ(PGTBL_ER);
-	if (HAS_HW_CONTEXTS(dev))
-		error->ccid = I915_READ(CCID);
-
-	if (HAS_PCH_SPLIT(dev))
-		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
-	else if (IS_VALLEYVIEW(dev))
-		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
-	else if (IS_GEN2(dev))
-		error->ier = I915_READ16(IER);
-	else
-		error->ier = I915_READ(IER);
-
-	if (INTEL_INFO(dev)->gen >= 6)
-		error->derrmr = I915_READ(DERRMR);
-
-	if (IS_VALLEYVIEW(dev))
-		error->forcewake = I915_READ(FORCEWAKE_VLV);
-	else if (INTEL_INFO(dev)->gen >= 7)
-		error->forcewake = I915_READ(FORCEWAKE_MT);
-	else if (INTEL_INFO(dev)->gen == 6)
-		error->forcewake = I915_READ(FORCEWAKE);
-
-	if (!HAS_PCH_SPLIT(dev))
-		for_each_pipe(pipe)
-			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
-
-	if (INTEL_INFO(dev)->gen >= 6) {
-		error->error = I915_READ(ERROR_GEN6);
-		error->done_reg = I915_READ(DONE_REG);
-	}
-
-	if (INTEL_INFO(dev)->gen == 7)
-		error->err_int = I915_READ(GEN7_ERR_INT);
-
-	i915_get_extra_instdone(dev, error->extra_instdone);
 
+	i915_capture_reg_state(dev_priv, error);
 	i915_gem_capture_buffers(dev_priv, error);
 	i915_gem_record_fences(dev, error);
 	i915_gem_record_rings(dev, error);
+	ecode = i915_error_generate_code(dev_priv, error);
+
+	if (!warned) {
+		DRM_INFO("GPU HANG [%x]\n", ecode);
+		DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
+		DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
+		DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
+		DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
+		warned = true;
+	}
 
 	do_gettimeofday(&error->time);
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9fec71175571..331f89cbed94 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -232,6 +232,18 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
 	return true;
 }
 
+static void i9xx_clear_fifo_underrun(struct drm_device *dev, enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg = PIPESTAT(pipe);
+	u32 pipestat = I915_READ(reg) & 0x7fff0000;
+
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
+	POSTING_READ(reg);
+}
+
 static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
 						 enum pipe pipe, bool enable)
 {
@@ -393,7 +405,9 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 
 	intel_crtc->cpu_fifo_underrun_disabled = !enable;
 
-	if (IS_GEN5(dev) || IS_GEN6(dev))
+	if (enable && (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)))
+		i9xx_clear_fifo_underrun(dev, pipe);
+	else if (IS_GEN5(dev) || IS_GEN6(dev))
 		ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
 	else if (IS_GEN7(dev))
 		ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
@@ -405,6 +419,16 @@ done:
 	return ret;
 }
 
+static bool __cpu_fifo_underrun_reporting_enabled(struct drm_device *dev,
+						  enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	return !intel_crtc->cpu_fifo_underrun_disabled;
+}
+
 /**
  * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
  * @dev: drm device
@@ -458,39 +482,103 @@ done:
 }
 
 
-void
-i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+static void
+__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+		       u32 enable_mask, u32 status_mask)
 {
 	u32 reg = PIPESTAT(pipe);
-	u32 pipestat = I915_READ(reg) & 0x7fff0000;
+	u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if ((pipestat & mask) == mask)
+	if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+	                 status_mask & ~PIPESTAT_INT_STATUS_MASK))
+		return;
+
+	if ((pipestat & enable_mask) == enable_mask)
 		return;
 
+	dev_priv->pipestat_irq_mask[pipe] |= status_mask;
+
 	/* Enable the interrupt, clear any pending status */
-	pipestat |= mask | (mask >> 16);
+	pipestat |= enable_mask | status_mask;
 	I915_WRITE(reg, pipestat);
 	POSTING_READ(reg);
 }
 
-void
-i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+static void
+__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+		        u32 enable_mask, u32 status_mask)
 {
 	u32 reg = PIPESTAT(pipe);
-	u32 pipestat = I915_READ(reg) & 0x7fff0000;
+	u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if ((pipestat & mask) == 0)
+	if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+	                 status_mask & ~PIPESTAT_INT_STATUS_MASK))
 		return;
 
-	pipestat &= ~mask;
+	if ((pipestat & enable_mask) == 0)
+		return;
+
+	dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
+
+	pipestat &= ~enable_mask;
 	I915_WRITE(reg, pipestat);
 	POSTING_READ(reg);
 }
 
+static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask)
+{
+	u32 enable_mask = status_mask << 16;
+
+	/*
+	 * On pipe A we don't support the PSR interrupt yet, on pipe B the
+	 * same bit MBZ.
+	 */
+	if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV))
+		return 0;
+
+	enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
+			 SPRITE0_FLIP_DONE_INT_EN_VLV |
+			 SPRITE1_FLIP_DONE_INT_EN_VLV);
+	if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
+		enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
+	if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
+		enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
+
+	return enable_mask;
+}
+
+void
+i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+		     u32 status_mask)
+{
+	u32 enable_mask;
+
+	if (IS_VALLEYVIEW(dev_priv->dev))
+		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+							   status_mask);
+	else
+		enable_mask = status_mask << 16;
+	__i915_enable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+}
+
+void
+i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+		      u32 status_mask)
+{
+	u32 enable_mask;
+
+	if (IS_VALLEYVIEW(dev_priv->dev))
+		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+							   status_mask);
+	else
+		enable_mask = status_mask << 16;
+	__i915_disable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+}
+
 /**
  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
  */
@@ -504,10 +592,10 @@ static void i915_enable_asle_pipestat(struct drm_device *dev)
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
-	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_ENABLE);
+	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
 	if (INTEL_INFO(dev)->gen >= 4)
 		i915_enable_pipestat(dev_priv, PIPE_A,
-				     PIPE_LEGACY_BLC_EVENT_ENABLE);
+				     PIPE_LEGACY_BLC_EVENT_STATUS);
 
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
@@ -915,6 +1003,11 @@ static void i915_hotplug_work_func(struct work_struct *work)
 		drm_kms_helper_hotplug_event(dev);
 }
 
+static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv)
+{
+	del_timer_sync(&dev_priv->hotplug_reenable_timer);
+}
+
 static void ironlake_rps_change_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -966,6 +1059,43 @@ static void notify_ring(struct drm_device *dev,
 	i915_queue_hangcheck(dev);
 }
 
+void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
+			     u32 pm_iir, int new_delay)
+{
+	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
+		if (new_delay >= dev_priv->rps.max_delay) {
+			/* Mask UP THRESHOLD Interrupts */
+			I915_WRITE(GEN6_PMINTRMSK,
+				   I915_READ(GEN6_PMINTRMSK) |
+				   GEN6_PM_RP_UP_THRESHOLD);
+			dev_priv->rps.rp_up_masked = true;
+		}
+		if (dev_priv->rps.rp_down_masked) {
+			/* UnMask DOWN THRESHOLD Interrupts */
+			I915_WRITE(GEN6_PMINTRMSK,
+				   I915_READ(GEN6_PMINTRMSK) &
+				   ~GEN6_PM_RP_DOWN_THRESHOLD);
+			dev_priv->rps.rp_down_masked = false;
+		}
+	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
+		if (new_delay <= dev_priv->rps.min_delay) {
+			/* Mask DOWN THRESHOLD Interrupts */
+			I915_WRITE(GEN6_PMINTRMSK,
+				   I915_READ(GEN6_PMINTRMSK) |
+				   GEN6_PM_RP_DOWN_THRESHOLD);
+			dev_priv->rps.rp_down_masked = true;
+		}
+
+		if (dev_priv->rps.rp_up_masked) {
+			/* UnMask UP THRESHOLD Interrupts */
+			I915_WRITE(GEN6_PMINTRMSK,
+				   I915_READ(GEN6_PMINTRMSK) &
+				   ~GEN6_PM_RP_UP_THRESHOLD);
+			dev_priv->rps.rp_up_masked = false;
+		}
+	}
+}
+
 static void gen6_pm_rps_work(struct work_struct *work)
 {
 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
@@ -1023,6 +1153,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	 */
 	new_delay = clamp_t(int, new_delay,
 			    dev_priv->rps.min_delay, dev_priv->rps.max_delay);
+
+	gen6_set_pm_mask(dev_priv, pm_iir, new_delay);
 	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
 
 	if (IS_VALLEYVIEW(dev_priv->dev))
@@ -1236,6 +1368,9 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
 	if (!hotplug_trigger)
 		return;
 
+	DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
+			  hotplug_trigger);
+
 	spin_lock(&dev_priv->irq_lock);
 	for (i = 1; i < HPD_NUM_PINS; i++) {
 
@@ -1415,17 +1550,82 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
 	}
 }
 
+static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pipe_stats[I915_MAX_PIPES] = { };
+	int pipe;
+
+	spin_lock(&dev_priv->irq_lock);
+	for_each_pipe(pipe) {
+		int reg;
+		u32 mask, iir_bit = 0;
+
+		/*
+		 * PIPESTAT bits get signalled even when the interrupt is
+		 * disabled with the mask bits, and some of the status bits do
+		 * not generate interrupts at all (like the underrun bit). Hence
+		 * we need to be careful that we only handle what we want to
+		 * handle.
+		 */
+		mask = 0;
+		if (__cpu_fifo_underrun_reporting_enabled(dev, pipe))
+			mask |= PIPE_FIFO_UNDERRUN_STATUS;
+
+		switch (pipe) {
+		case PIPE_A:
+			iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+			break;
+		case PIPE_B:
+			iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+			break;
+		}
+		if (iir & iir_bit)
+			mask |= dev_priv->pipestat_irq_mask[pipe];
+
+		if (!mask)
+			continue;
+
+		reg = PIPESTAT(pipe);
+		mask |= PIPESTAT_INT_ENABLE_MASK;
+		pipe_stats[pipe] = I915_READ(reg) & mask;
+
+		/*
+		 * Clear the PIPE*STAT regs before the IIR
+		 */
+		if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS |
+					PIPESTAT_INT_STATUS_MASK))
+			I915_WRITE(reg, pipe_stats[pipe]);
+	}
+	spin_unlock(&dev_priv->irq_lock);
+
+	for_each_pipe(pipe) {
+		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
+			drm_handle_vblank(dev, pipe);
+
+		if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) {
+			intel_prepare_page_flip(dev, pipe);
+			intel_finish_page_flip(dev, pipe);
+		}
+
+		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
+			i9xx_pipe_crc_irq_handler(dev, pipe);
+
+		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+		    intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+			DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
+	}
+
+	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
+		gmbus_irq_handler(dev);
+}
+
 static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 iir, gt_iir, pm_iir;
 	irqreturn_t ret = IRQ_NONE;
-	unsigned long irqflags;
-	int pipe;
-	u32 pipe_stats[I915_MAX_PIPES];
-
-	atomic_inc(&dev_priv->irq_received);
 
 	while (true) {
 		iir = I915_READ(VLV_IIR);
@@ -1439,44 +1639,13 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 
 		snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
-		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		for_each_pipe(pipe) {
-			int reg = PIPESTAT(pipe);
-			pipe_stats[pipe] = I915_READ(reg);
-
-			/*
-			 * Clear the PIPE*STAT regs before the IIR
-			 */
-			if (pipe_stats[pipe] & 0x8000ffff) {
-				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-					DRM_DEBUG_DRIVER("pipe %c underrun\n",
-							 pipe_name(pipe));
-				I915_WRITE(reg, pipe_stats[pipe]);
-			}
-		}
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-		for_each_pipe(pipe) {
-			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
-				drm_handle_vblank(dev, pipe);
-
-			if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
-				intel_prepare_page_flip(dev, pipe);
-				intel_finish_page_flip(dev, pipe);
-			}
-
-			if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
-				i9xx_pipe_crc_irq_handler(dev, pipe);
-		}
+		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;
 
-			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-					 hotplug_status);
-
 			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
 
 			if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
@@ -1486,8 +1655,6 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 			I915_READ(PORT_HOTPLUG_STAT);
 		}
 
-		if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
-			gmbus_irq_handler(dev);
 
 		if (pm_iir)
 			gen6_rps_irq_handler(dev_priv, pm_iir);
@@ -1546,12 +1713,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
 	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
 							  false))
-			DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
+			DRM_ERROR("PCH transcoder A FIFO underrun\n");
 
 	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
 							  false))
-			DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
+			DRM_ERROR("PCH transcoder B FIFO underrun\n");
 }
 
 static void ivb_err_int_handler(struct drm_device *dev)
@@ -1567,8 +1734,8 @@ static void ivb_err_int_handler(struct drm_device *dev)
 		if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) {
 			if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
 								  false))
-				DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n",
-						 pipe_name(pipe));
+				DRM_ERROR("Pipe %c FIFO underrun\n",
+					  pipe_name(pipe));
 		}
 
 		if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
@@ -1593,17 +1760,17 @@ static void cpt_serr_int_handler(struct drm_device *dev)
 	if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN)
 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
 							  false))
-			DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
+			DRM_ERROR("PCH transcoder A FIFO underrun\n");
 
 	if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN)
 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
 							  false))
-			DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
+			DRM_ERROR("PCH transcoder B FIFO underrun\n");
 
 	if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN)
 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C,
 							  false))
-			DRM_DEBUG_DRIVER("PCH transcoder C FIFO underrun\n");
+			DRM_ERROR("PCH transcoder C FIFO underrun\n");
 
 	I915_WRITE(SERR_INT, serr_int);
 }
@@ -1665,8 +1832,8 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
 
 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
 			if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
-				DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n",
-						 pipe_name(pipe));
+				DRM_ERROR("Pipe %c FIFO underrun\n",
+					  pipe_name(pipe));
 
 		if (de_iir & DE_PIPE_CRC_DONE(pipe))
 			i9xx_pipe_crc_irq_handler(dev, pipe);
@@ -1738,8 +1905,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
 	irqreturn_t ret = IRQ_NONE;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	/* We get interrupts on unclaimed registers, so check for this before we
 	 * do any I915_{READ,WRITE}. */
 	intel_uncore_check_errors(dev);
@@ -1808,8 +1973,6 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 	uint32_t tmp = 0;
 	enum pipe pipe;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	master_ctl = I915_READ(GEN8_MASTER_IRQ);
 	master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
 	if (!master_ctl)
@@ -1871,8 +2034,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 		if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
 			if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
 								  false))
-				DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n",
-						 pipe_name(pipe));
+				DRM_ERROR("Pipe %c FIFO underrun\n",
+					  pipe_name(pipe));
 		}
 
 		if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
@@ -2210,13 +2373,13 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	if (INTEL_INFO(dev)->gen >= 4)
 		i915_enable_pipestat(dev_priv, pipe,
-				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
+				     PIPE_START_VBLANK_INTERRUPT_STATUS);
 	else
 		i915_enable_pipestat(dev_priv, pipe,
-				     PIPE_VBLANK_INTERRUPT_ENABLE);
+				     PIPE_VBLANK_INTERRUPT_STATUS);
 
 	/* maintain vblank delivery even in deep C-states */
-	if (dev_priv->info->gen == 3)
+	if (INTEL_INFO(dev)->gen == 3)
 		I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -2244,20 +2407,13 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
-	u32 imr;
 
 	if (!i915_pipe_enabled(dev, pipe))
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	imr = I915_READ(VLV_IMR);
-	if (pipe == PIPE_A)
-		imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-	else
-		imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-	I915_WRITE(VLV_IMR, imr);
 	i915_enable_pipestat(dev_priv, pipe,
-			     PIPE_START_VBLANK_INTERRUPT_ENABLE);
+			     PIPE_START_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -2288,12 +2444,12 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	if (dev_priv->info->gen == 3)
+	if (INTEL_INFO(dev)->gen == 3)
 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
 
 	i915_disable_pipestat(dev_priv, pipe,
-			      PIPE_VBLANK_INTERRUPT_ENABLE |
-			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
+			      PIPE_VBLANK_INTERRUPT_STATUS |
+			      PIPE_START_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2313,17 +2469,10 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
-	u32 imr;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_disable_pipestat(dev_priv, pipe,
-			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
-	imr = I915_READ(VLV_IMR);
-	if (pipe == PIPE_A)
-		imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-	else
-		imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-	I915_WRITE(VLV_IMR, imr);
+			      PIPE_START_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2479,9 +2628,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
 #define BUSY 1
 #define KICK 5
 #define HUNG 20
-#define FIRE 30
 
-	if (!i915_enable_hangcheck)
+	if (!i915.enable_hangcheck)
 		return;
 
 	for_each_ring(ring, dev_priv, i) {
@@ -2563,7 +2711,7 @@ static void i915_hangcheck_elapsed(unsigned long data)
 	}
 
 	for_each_ring(ring, dev_priv, i) {
-		if (ring->hangcheck.score > FIRE) {
+		if (ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
 			DRM_INFO("%s on %s\n",
 				 stuck[i] ? "stuck" : "no progress",
 				 ring->name);
@@ -2583,7 +2731,7 @@ static void i915_hangcheck_elapsed(unsigned long data)
 void i915_queue_hangcheck(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	if (!i915_enable_hangcheck)
+	if (!i915.enable_hangcheck)
 		return;
 
 	mod_timer(&dev_priv->gpu_error.hangcheck_timer,
@@ -2632,8 +2780,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	I915_WRITE(HWSTAM, 0xeffe);
 
 	I915_WRITE(DEIMR, 0xffffffff);
@@ -2650,8 +2796,6 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	/* VLV magic */
 	I915_WRITE(VLV_IMR, 0);
 	I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
@@ -2681,8 +2825,6 @@ static void gen8_irq_preinstall(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	I915_WRITE(GEN8_MASTER_IRQ, 0);
 	POSTING_READ(GEN8_MASTER_IRQ);
 
@@ -2878,8 +3020,8 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask;
-	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV |
-		PIPE_CRC_DONE_ENABLE;
+	u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
+		PIPE_CRC_DONE_INTERRUPT_STATUS;
 	unsigned long irqflags;
 
 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
@@ -2910,7 +3052,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	 * just to make the assert_spin_locked check happy. */
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
 	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -3007,8 +3149,6 @@ static void gen8_irq_uninstall(struct drm_device *dev)
 	if (!dev_priv)
 		return;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	I915_WRITE(GEN8_MASTER_IRQ, 0);
 
 #define GEN8_IRQ_FINI_NDX(type, which) do { \
@@ -3049,7 +3189,7 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
 	if (!dev_priv)
 		return;
 
-	del_timer_sync(&dev_priv->hotplug_reenable_timer);
+	intel_hpd_irq_uninstall(dev_priv);
 
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0xffff);
@@ -3072,7 +3212,7 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
 	if (!dev_priv)
 		return;
 
-	del_timer_sync(&dev_priv->hotplug_reenable_timer);
+	intel_hpd_irq_uninstall(dev_priv);
 
 	I915_WRITE(HWSTAM, 0xffffffff);
 
@@ -3101,8 +3241,6 @@ static void i8xx_irq_preinstall(struct drm_device * dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE16(IMR, 0xffff);
@@ -3137,8 +3275,8 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
 	/* Interrupt setup is already guaranteed to be single-threaded, this is
 	 * just to make the assert_spin_locked check happy. */
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -3187,8 +3325,6 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	iir = I915_READ16(IIR);
 	if (iir == 0)
 		return IRQ_NONE;
@@ -3210,12 +3346,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 			/*
 			 * Clear the PIPE*STAT regs before the IIR
 			 */
-			if (pipe_stats[pipe] & 0x8000ffff) {
-				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-					DRM_DEBUG_DRIVER("pipe %c underrun\n",
-							 pipe_name(pipe));
+			if (pipe_stats[pipe] & 0x8000ffff)
 				I915_WRITE(reg, pipe_stats[pipe]);
-			}
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -3238,6 +3370,10 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 
 			if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
 				i9xx_pipe_crc_irq_handler(dev, pipe);
+
+			if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+			    intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+				DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
 		}
 
 		iir = new_iir;
@@ -3266,8 +3402,6 @@ static void i915_irq_preinstall(struct drm_device * dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -3324,8 +3458,8 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	/* Interrupt setup is already guaranteed to be single-threaded, this is
 	 * just to make the assert_spin_locked check happy. */
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -3373,8 +3507,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
 	int pipe, ret = IRQ_NONE;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	iir = I915_READ(IIR);
 	do {
 		bool irq_received = (iir & ~flip_mask) != 0;
@@ -3395,9 +3527,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
 			/* Clear the PIPE*STAT regs before the IIR */
 			if (pipe_stats[pipe] & 0x8000ffff) {
-				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-					DRM_DEBUG_DRIVER("pipe %c underrun\n",
-							 pipe_name(pipe));
 				I915_WRITE(reg, pipe_stats[pipe]);
 				irq_received = true;
 			}
@@ -3413,9 +3542,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
 			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
 
-			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-				  hotplug_status);
-
 			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
 
 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
@@ -3442,6 +3568,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
 			if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
 				i9xx_pipe_crc_irq_handler(dev, pipe);
+
+			if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+			    intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+				DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
 		}
 
 		if (blc_event || (iir & I915_ASLE_INTERRUPT))
@@ -3476,7 +3606,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	del_timer_sync(&dev_priv->hotplug_reenable_timer);
+	intel_hpd_irq_uninstall(dev_priv);
 
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
@@ -3500,8 +3630,6 @@ static void i965_irq_preinstall(struct drm_device * dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	atomic_set(&dev_priv->irq_received, 0);
-
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
@@ -3540,9 +3668,9 @@ static int i965_irq_postinstall(struct drm_device *dev)
 	/* Interrupt setup is already guaranteed to be single-threaded, this is
 	 * just to make the assert_spin_locked check happy. */
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	/*
@@ -3610,21 +3738,17 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 	u32 iir, new_iir;
 	u32 pipe_stats[I915_MAX_PIPES];
 	unsigned long irqflags;
-	int irq_received;
 	int ret = IRQ_NONE, pipe;
 	u32 flip_mask =
 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	iir = I915_READ(IIR);
 
 	for (;;) {
+		bool irq_received = (iir & ~flip_mask) != 0;
 		bool blc_event = false;
 
-		irq_received = (iir & ~flip_mask) != 0;
-
 		/* Can't rely on pipestat interrupt bit in iir as it might
 		 * have been cleared after the pipestat interrupt was received.
 		 * It doesn't set the bit in iir again, but it still produces
@@ -3642,11 +3766,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 			 * Clear the PIPE*STAT regs before the IIR
 			 */
 			if (pipe_stats[pipe] & 0x8000ffff) {
-				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-					DRM_DEBUG_DRIVER("pipe %c underrun\n",
-							 pipe_name(pipe));
 				I915_WRITE(reg, pipe_stats[pipe]);
-				irq_received = 1;
+				irq_received = true;
 			}
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -3663,9 +3784,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 								  HOTPLUG_INT_STATUS_G4X :
 								  HOTPLUG_INT_STATUS_I915);
 
-			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-				  hotplug_status);
-
 			intel_hpd_irq_handler(dev, hotplug_trigger,
 					      IS_G4X(dev) ? hpd_status_g4x : hpd_status_i915);
 
@@ -3695,8 +3813,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 
 			if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
 				i9xx_pipe_crc_irq_handler(dev, pipe);
-		}
 
+			if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+			    intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+				DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
+		}
 
 		if (blc_event || (iir & I915_ASLE_INTERRUPT))
 			intel_opregion_asle_intr(dev);
@@ -3735,7 +3856,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
 	if (!dev_priv)
 		return;
 
-	del_timer_sync(&dev_priv->hotplug_reenable_timer);
+	intel_hpd_irq_uninstall(dev_priv);
 
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -3752,7 +3873,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
 	I915_WRITE(IIR, I915_READ(IIR));
 }
 
-static void i915_reenable_hotplug_timer_func(unsigned long data)
+static void intel_hpd_irq_reenable(unsigned long data)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *)data;
 	struct drm_device *dev = dev_priv->dev;
@@ -3799,7 +3920,7 @@ void intel_irq_init(struct drm_device *dev)
 	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
 		    i915_hangcheck_elapsed,
 		    (unsigned long) dev);
-	setup_timer(&dev_priv->hotplug_reenable_timer, i915_reenable_hotplug_timer_func,
+	setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable,
 		    (unsigned long) dev_priv);
 
 	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
new file mode 100644
index 000000000000..3b482585c5ae
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -0,0 +1,159 @@
+/*
+ * 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, 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 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.
+ */
+
+#include "i915_drv.h"
+
+struct i915_params i915 __read_mostly = {
+	.modeset = -1,
+	.panel_ignore_lid = 1,
+	.powersave = 1,
+	.semaphores = -1,
+	.lvds_downclock = 0,
+	.lvds_channel_mode = 0,
+	.panel_use_ssc = -1,
+	.vbt_sdvo_panel_type = -1,
+	.enable_rc6 = -1,
+	.enable_fbc = -1,
+	.enable_hangcheck = true,
+	.enable_ppgtt = -1,
+	.enable_psr = 0,
+	.preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
+	.disable_power_well = 1,
+	.enable_ips = 1,
+	.fastboot = 0,
+	.enable_pc8 = 1,
+	.pc8_timeout = 5000,
+	.prefault_disable = 0,
+	.reset = true,
+	.invert_brightness = 0,
+	.disable_display = 0,
+};
+
+module_param_named(modeset, i915.modeset, int, 0400);
+MODULE_PARM_DESC(modeset,
+	"Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, "
+	"1=on, -1=force vga console preference [default])");
+
+module_param_named(panel_ignore_lid, i915.panel_ignore_lid, int, 0600);
+MODULE_PARM_DESC(panel_ignore_lid,
+	"Override lid status (0=autodetect, 1=autodetect disabled [default], "
+	"-1=force lid closed, -2=force lid open)");
+
+module_param_named(powersave, i915.powersave, int, 0600);
+MODULE_PARM_DESC(powersave,
+	"Enable powersavings, fbc, downclocking, etc. (default: true)");
+
+module_param_named(semaphores, i915.semaphores, int, 0400);
+MODULE_PARM_DESC(semaphores,
+	"Use semaphores for inter-ring sync "
+	"(default: -1 (use per-chip defaults))");
+
+module_param_named(enable_rc6, i915.enable_rc6, int, 0400);
+MODULE_PARM_DESC(enable_rc6,
+	"Enable power-saving render C-state 6. "
+	"Different stages can be selected via bitmask values "
+	"(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). "
+	"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
+	"default: -1 (use per-chip default)");
+
+module_param_named(enable_fbc, i915.enable_fbc, int, 0600);
+MODULE_PARM_DESC(enable_fbc,
+	"Enable frame buffer compression for power savings "
+	"(default: -1 (use per-chip default))");
+
+module_param_named(lvds_downclock, i915.lvds_downclock, int, 0400);
+MODULE_PARM_DESC(lvds_downclock,
+	"Use panel (LVDS/eDP) downclocking for power savings "
+	"(default: false)");
+
+module_param_named(lvds_channel_mode, i915.lvds_channel_mode, int, 0600);
+MODULE_PARM_DESC(lvds_channel_mode,
+	 "Specify LVDS channel mode "
+	 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
+
+module_param_named(lvds_use_ssc, i915.panel_use_ssc, int, 0600);
+MODULE_PARM_DESC(lvds_use_ssc,
+	"Use Spread Spectrum Clock with panels [LVDS/eDP] "
+	"(default: auto from VBT)");
+
+module_param_named(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600);
+MODULE_PARM_DESC(vbt_sdvo_panel_type,
+	"Override/Ignore selection of SDVO panel mode in the VBT "
+	"(-2=ignore, -1=auto [default], index in VBT BIOS table)");
+
+module_param_named(reset, i915.reset, bool, 0600);
+MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
+
+module_param_named(enable_hangcheck, i915.enable_hangcheck, bool, 0644);
+MODULE_PARM_DESC(enable_hangcheck,
+	"Periodically check GPU activity for detecting hangs. "
+	"WARNING: Disabling this can cause system wide hangs. "
+	"(default: true)");
+
+module_param_named(enable_ppgtt, i915.enable_ppgtt, int, 0400);
+MODULE_PARM_DESC(enable_ppgtt,
+	"Override PPGTT usage. "
+	"(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
+
+module_param_named(enable_psr, i915.enable_psr, int, 0600);
+MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)");
+
+module_param_named(preliminary_hw_support, i915.preliminary_hw_support, int, 0600);
+MODULE_PARM_DESC(preliminary_hw_support,
+	"Enable preliminary hardware support.");
+
+module_param_named(disable_power_well, i915.disable_power_well, int, 0600);
+MODULE_PARM_DESC(disable_power_well,
+	"Disable the power well when possible (default: true)");
+
+module_param_named(enable_ips, i915.enable_ips, int, 0600);
+MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
+
+module_param_named(fastboot, i915.fastboot, bool, 0600);
+MODULE_PARM_DESC(fastboot,
+	"Try to skip unnecessary mode sets at boot time (default: false)");
+
+module_param_named(enable_pc8, i915.enable_pc8, int, 0600);
+MODULE_PARM_DESC(enable_pc8,
+	"Enable support for low power package C states (PC8+) (default: true)");
+
+module_param_named(pc8_timeout, i915.pc8_timeout, int, 0600);
+MODULE_PARM_DESC(pc8_timeout,
+	"Number of msecs of idleness required to enter PC8+ (default: 5000)");
+
+module_param_named(prefault_disable, i915.prefault_disable, bool, 0600);
+MODULE_PARM_DESC(prefault_disable,
+	"Disable page prefaulting for pread/pwrite/reloc (default:false). "
+	"For developers only.");
+
+module_param_named(invert_brightness, i915.invert_brightness, int, 0600);
+MODULE_PARM_DESC(invert_brightness,
+	"Invert backlight brightness "
+	"(-1 force normal, 0 machine defaults, 1 force inversion), please "
+	"report PCI device ID, subsystem vendor and subsystem device ID "
+	"to dri-devel@lists.freedesktop.org, if your machine needs it. "
+	"It will then be included in an upcoming module version.");
+
+module_param_named(disable_display, i915.disable_display, bool, 0600);
+MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a48b7cad6f11..2f564ce37d2c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -26,7 +26,6 @@
 #define _I915_REG_H_
 
 #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
-#define _PIPE_INC(pipe, base, inc) ((base) + (pipe)*(inc))
 #define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
 
 #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
@@ -73,7 +72,8 @@
 #define   I915_GC_RENDER_CLOCK_166_MHZ	(0 << 0)
 #define   I915_GC_RENDER_CLOCK_200_MHZ	(1 << 0)
 #define   I915_GC_RENDER_CLOCK_333_MHZ	(4 << 0)
-#define LBB	0xf4
+#define PCI_LBPC 0xf4 /* legacy/combination backlight modes, also called LBB */
+
 
 /* Graphics reset regs */
 #define I965_GDRST 0xc0 /* PCI config register */
@@ -789,7 +789,8 @@
 #define _3D_CHICKEN3	0x02090
 #define  _3D_CHICKEN_SF_DISABLE_OBJEND_CULL		(1 << 10)
 #define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL		(1 << 5)
-#define  _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x)	((x)<<1)
+#define  _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x)	((x)<<1) /* gen8+ */
+#define  _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH	(1 << 1) /* gen6 */
 
 #define MI_MODE		0x0209c
 # define VS_TIMER_DISPATCH				(1 << 6)
@@ -934,6 +935,8 @@
 #define   ECO_GATING_CX_ONLY	(1<<3)
 #define   ECO_FLIP_DONE		(1<<0)
 
+#define CACHE_MODE_0_GEN7	0x7000 /* IVB+ */
+#define   HIZ_RAW_STALL_OPT_DISABLE (1<<2)
 #define CACHE_MODE_1		0x7004 /* IVB+ */
 #define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6)
 
@@ -1046,9 +1049,8 @@
 #define   FBC_CTL_IDLE_LINE	(2<<2)
 #define   FBC_CTL_IDLE_DEBUG	(3<<2)
 #define   FBC_CTL_CPU_FENCE	(1<<1)
-#define   FBC_CTL_PLANEA	(0<<0)
-#define   FBC_CTL_PLANEB	(1<<0)
-#define FBC_FENCE_OFF		0x0321b
+#define   FBC_CTL_PLANE(plane)	((plane)<<0)
+#define FBC_FENCE_OFF		0x03218 /* BSpec typo has 321Bh */
 #define FBC_TAG			0x03300
 
 #define FBC_LL_SIZE		(1536)
@@ -1057,9 +1059,8 @@
 #define DPFC_CB_BASE		0x3200
 #define DPFC_CONTROL		0x3208
 #define   DPFC_CTL_EN		(1<<31)
-#define   DPFC_CTL_PLANEA	(0<<30)
-#define   DPFC_CTL_PLANEB	(1<<30)
-#define   IVB_DPFC_CTL_PLANE_SHIFT	(29)
+#define   DPFC_CTL_PLANE(plane)	((plane)<<30)
+#define   IVB_DPFC_CTL_PLANE(plane)	((plane)<<29)
 #define   DPFC_CTL_FENCE_EN	(1<<29)
 #define   IVB_DPFC_CTL_FENCE_EN	(1<<28)
 #define   DPFC_CTL_PERSISTENT_MODE	(1<<25)
@@ -1202,6 +1203,10 @@
 /*
  * Clock control & power management
  */
+#define DPLL_A_OFFSET 0x6014
+#define DPLL_B_OFFSET 0x6018
+#define DPLL(pipe) (dev_priv->info.dpll_offsets[pipe] + \
+		    dev_priv->info.display_mmio_offset)
 
 #define VGA0	0x6000
 #define VGA1	0x6004
@@ -1214,9 +1219,6 @@
 #define   VGA1_PD_P1_DIV_2	(1 << 13)
 #define   VGA1_PD_P1_SHIFT	8
 #define   VGA1_PD_P1_MASK	(0x1f << 8)
-#define _DPLL_A	(dev_priv->info->display_mmio_offset + 0x6014)
-#define _DPLL_B	(dev_priv->info->display_mmio_offset + 0x6018)
-#define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)
 #define   DPLL_VCO_ENABLE		(1 << 31)
 #define   DPLL_SDVO_HIGH_SPEED		(1 << 30)
 #define   DPLL_DVO_2X_MODE		(1 << 30)
@@ -1278,7 +1280,12 @@
 #define   SDVO_MULTIPLIER_MASK			0x000000ff
 #define   SDVO_MULTIPLIER_SHIFT_HIRES		4
 #define   SDVO_MULTIPLIER_SHIFT_VGA		0
-#define _DPLL_A_MD (dev_priv->info->display_mmio_offset + 0x601c) /* 965+ only */
+
+#define DPLL_A_MD_OFFSET 0x601c /* 965+ only */
+#define DPLL_B_MD_OFFSET 0x6020 /* 965+ only */
+#define DPLL_MD(pipe) (dev_priv->info.dpll_md_offsets[pipe] + \
+		       dev_priv->info.display_mmio_offset)
+
 /*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
  *
@@ -1315,8 +1322,6 @@
  */
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
-#define _DPLL_B_MD (dev_priv->info->display_mmio_offset + 0x6020) /* 965+ only */
-#define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD)
 
 #define _FPA0	0x06040
 #define _FPA1	0x06044
@@ -1348,7 +1353,7 @@
 #define  DSTATE_PLL_D3_OFF			(1<<3)
 #define  DSTATE_GFX_CLOCK_GATING		(1<<1)
 #define  DSTATE_DOT_CLOCK_GATING		(1<<0)
-#define DSPCLK_GATE_D	(dev_priv->info->display_mmio_offset + 0x6200)
+#define DSPCLK_GATE_D	(dev_priv->info.display_mmio_offset + 0x6200)
 # define DPUNIT_B_CLOCK_GATE_DISABLE		(1 << 30) /* 965 */
 # define VSUNIT_CLOCK_GATE_DISABLE		(1 << 29) /* 965 */
 # define VRHUNIT_CLOCK_GATE_DISABLE		(1 << 28) /* 965 */
@@ -1472,10 +1477,10 @@
 /*
  * Palette regs
  */
-
-#define _PALETTE_A		(dev_priv->info->display_mmio_offset + 0xa000)
-#define _PALETTE_B		(dev_priv->info->display_mmio_offset + 0xa800)
-#define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B)
+#define PALETTE_A_OFFSET 0xa000
+#define PALETTE_B_OFFSET 0xa800
+#define PALETTE(pipe) (dev_priv->info.palette_offsets[pipe] + \
+		       dev_priv->info.display_mmio_offset)
 
 /* MCH MMIO space */
 
@@ -1862,7 +1867,7 @@
  */
 
 /* Pipe A CRC regs */
-#define _PIPE_CRC_CTL_A		(dev_priv->info->display_mmio_offset + 0x60050)
+#define _PIPE_CRC_CTL_A			0x60050
 #define   PIPE_CRC_ENABLE		(1 << 31)
 /* ivb+ source selection */
 #define   PIPE_CRC_SOURCE_PRIMARY_IVB	(0 << 29)
@@ -1902,11 +1907,11 @@
 #define _PIPE_CRC_RES_4_A_IVB		0x60070
 #define _PIPE_CRC_RES_5_A_IVB		0x60074
 
-#define _PIPE_CRC_RES_RED_A		(dev_priv->info->display_mmio_offset + 0x60060)
-#define _PIPE_CRC_RES_GREEN_A		(dev_priv->info->display_mmio_offset + 0x60064)
-#define _PIPE_CRC_RES_BLUE_A		(dev_priv->info->display_mmio_offset + 0x60068)
-#define _PIPE_CRC_RES_RES1_A_I915	(dev_priv->info->display_mmio_offset + 0x6006c)
-#define _PIPE_CRC_RES_RES2_A_G4X	(dev_priv->info->display_mmio_offset + 0x60080)
+#define _PIPE_CRC_RES_RED_A		0x60060
+#define _PIPE_CRC_RES_GREEN_A		0x60064
+#define _PIPE_CRC_RES_BLUE_A		0x60068
+#define _PIPE_CRC_RES_RES1_A_I915	0x6006c
+#define _PIPE_CRC_RES_RES2_A_G4X	0x60080
 
 /* Pipe B CRC regs */
 #define _PIPE_CRC_RES_1_B_IVB		0x61064
@@ -1915,59 +1920,69 @@
 #define _PIPE_CRC_RES_4_B_IVB		0x61070
 #define _PIPE_CRC_RES_5_B_IVB		0x61074
 
-#define PIPE_CRC_CTL(pipe)	_PIPE_INC(pipe, _PIPE_CRC_CTL_A, 0x01000)
+#define PIPE_CRC_CTL(pipe) _TRANSCODER2(pipe, _PIPE_CRC_CTL_A)
 #define PIPE_CRC_RES_1_IVB(pipe)	\
-	_PIPE(pipe, _PIPE_CRC_RES_1_A_IVB, _PIPE_CRC_RES_1_B_IVB)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_1_A_IVB)
 #define PIPE_CRC_RES_2_IVB(pipe)	\
-	_PIPE(pipe, _PIPE_CRC_RES_2_A_IVB, _PIPE_CRC_RES_2_B_IVB)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_2_A_IVB)
 #define PIPE_CRC_RES_3_IVB(pipe)	\
-	_PIPE(pipe, _PIPE_CRC_RES_3_A_IVB, _PIPE_CRC_RES_3_B_IVB)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_3_A_IVB)
 #define PIPE_CRC_RES_4_IVB(pipe)	\
-	_PIPE(pipe, _PIPE_CRC_RES_4_A_IVB, _PIPE_CRC_RES_4_B_IVB)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_4_A_IVB)
 #define PIPE_CRC_RES_5_IVB(pipe)	\
-	_PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_5_A_IVB)
 
 #define PIPE_CRC_RES_RED(pipe) \
-	_PIPE_INC(pipe, _PIPE_CRC_RES_RED_A, 0x01000)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_RED_A)
 #define PIPE_CRC_RES_GREEN(pipe) \
-	_PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A, 0x01000)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_GREEN_A)
 #define PIPE_CRC_RES_BLUE(pipe) \
-	_PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A, 0x01000)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_BLUE_A)
 #define PIPE_CRC_RES_RES1_I915(pipe) \
-	_PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_I915, 0x01000)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_RES1_A_I915)
 #define PIPE_CRC_RES_RES2_G4X(pipe) \
-	_PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_G4X, 0x01000)
+	_TRANSCODER2(pipe, _PIPE_CRC_RES_RES2_A_G4X)
 
 /* Pipe A timing regs */
-#define _HTOTAL_A	(dev_priv->info->display_mmio_offset + 0x60000)
-#define _HBLANK_A	(dev_priv->info->display_mmio_offset + 0x60004)
-#define _HSYNC_A	(dev_priv->info->display_mmio_offset + 0x60008)
-#define _VTOTAL_A	(dev_priv->info->display_mmio_offset + 0x6000c)
-#define _VBLANK_A	(dev_priv->info->display_mmio_offset + 0x60010)
-#define _VSYNC_A	(dev_priv->info->display_mmio_offset + 0x60014)
-#define _PIPEASRC	(dev_priv->info->display_mmio_offset + 0x6001c)
-#define _BCLRPAT_A	(dev_priv->info->display_mmio_offset + 0x60020)
-#define _VSYNCSHIFT_A	(dev_priv->info->display_mmio_offset + 0x60028)
+#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 _PIPEASRC	0x6001c
+#define _BCLRPAT_A	0x60020
+#define _VSYNCSHIFT_A	0x60028
 
 /* Pipe B timing regs */
-#define _HTOTAL_B	(dev_priv->info->display_mmio_offset + 0x61000)
-#define _HBLANK_B	(dev_priv->info->display_mmio_offset + 0x61004)
-#define _HSYNC_B	(dev_priv->info->display_mmio_offset + 0x61008)
-#define _VTOTAL_B	(dev_priv->info->display_mmio_offset + 0x6100c)
-#define _VBLANK_B	(dev_priv->info->display_mmio_offset + 0x61010)
-#define _VSYNC_B	(dev_priv->info->display_mmio_offset + 0x61014)
-#define _PIPEBSRC	(dev_priv->info->display_mmio_offset + 0x6101c)
-#define _BCLRPAT_B	(dev_priv->info->display_mmio_offset + 0x61020)
-#define _VSYNCSHIFT_B	(dev_priv->info->display_mmio_offset + 0x61028)
-
-#define HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B)
-#define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B)
-#define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B)
-#define VTOTAL(trans) _TRANSCODER(trans, _VTOTAL_A, _VTOTAL_B)
-#define VBLANK(trans) _TRANSCODER(trans, _VBLANK_A, _VBLANK_B)
-#define VSYNC(trans) _TRANSCODER(trans, _VSYNC_A, _VSYNC_B)
-#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
-#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
+#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 _PIPEBSRC	0x6101c
+#define _BCLRPAT_B	0x61020
+#define _VSYNCSHIFT_B	0x61028
+
+#define TRANSCODER_A_OFFSET 0x60000
+#define TRANSCODER_B_OFFSET 0x61000
+#define TRANSCODER_C_OFFSET 0x62000
+#define TRANSCODER_EDP_OFFSET 0x6f000
+
+#define _TRANSCODER2(pipe, reg) (dev_priv->info.trans_offsets[(pipe)] - \
+	dev_priv->info.trans_offsets[TRANSCODER_A] + (reg) + \
+	dev_priv->info.display_mmio_offset)
+
+#define HTOTAL(trans) _TRANSCODER2(trans, _HTOTAL_A)
+#define HBLANK(trans) _TRANSCODER2(trans, _HBLANK_A)
+#define HSYNC(trans) _TRANSCODER2(trans, _HSYNC_A)
+#define VTOTAL(trans) _TRANSCODER2(trans, _VTOTAL_A)
+#define VBLANK(trans) _TRANSCODER2(trans, _VBLANK_A)
+#define VSYNC(trans) _TRANSCODER2(trans, _VSYNC_A)
+#define BCLRPAT(trans) _TRANSCODER2(trans, _BCLRPAT_A)
+#define VSYNCSHIFT(trans) _TRANSCODER2(trans, _VSYNCSHIFT_A)
+#define PIPESRC(trans) _TRANSCODER2(trans, _PIPEASRC)
 
 /* HSW+ eDP PSR registers */
 #define EDP_PSR_BASE(dev)                       (IS_HASWELL(dev) ? 0x64800 : 0x6f800)
@@ -2084,7 +2099,7 @@
 
 
 /* Hotplug control (945+ only) */
-#define PORT_HOTPLUG_EN		(dev_priv->info->display_mmio_offset + 0x61110)
+#define PORT_HOTPLUG_EN		(dev_priv->info.display_mmio_offset + 0x61110)
 #define   PORTB_HOTPLUG_INT_EN			(1 << 29)
 #define   PORTC_HOTPLUG_INT_EN			(1 << 28)
 #define   PORTD_HOTPLUG_INT_EN			(1 << 27)
@@ -2114,7 +2129,7 @@
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
 
-#define PORT_HOTPLUG_STAT	(dev_priv->info->display_mmio_offset + 0x61114)
+#define PORT_HOTPLUG_STAT	(dev_priv->info.display_mmio_offset + 0x61114)
 /*
  * HDMI/DP bits are gen4+
  *
@@ -2332,9 +2347,7 @@
 #define VIDEO_DIP_CTL		0x61170
 /* Pre HSW: */
 #define   VIDEO_DIP_ENABLE		(1 << 31)
-#define   VIDEO_DIP_PORT_B		(1 << 29)
-#define   VIDEO_DIP_PORT_C		(2 << 29)
-#define   VIDEO_DIP_PORT_D		(3 << 29)
+#define   VIDEO_DIP_PORT(port)		((port) << 29)
 #define   VIDEO_DIP_PORT_MASK		(3 << 29)
 #define   VIDEO_DIP_ENABLE_GCP		(1 << 25)
 #define   VIDEO_DIP_ENABLE_AVI		(1 << 21)
@@ -2391,7 +2404,7 @@
 #define PP_DIVISOR	0x61210
 
 /* Panel fitting */
-#define PFIT_CONTROL	(dev_priv->info->display_mmio_offset + 0x61230)
+#define PFIT_CONTROL	(dev_priv->info.display_mmio_offset + 0x61230)
 #define   PFIT_ENABLE		(1 << 31)
 #define   PFIT_PIPE_MASK	(3 << 29)
 #define   PFIT_PIPE_SHIFT	29
@@ -2409,7 +2422,7 @@
 #define   PFIT_SCALING_PROGRAMMED (1 << 26)
 #define   PFIT_SCALING_PILLAR	(2 << 26)
 #define   PFIT_SCALING_LETTER	(3 << 26)
-#define PFIT_PGM_RATIOS	(dev_priv->info->display_mmio_offset + 0x61234)
+#define PFIT_PGM_RATIOS	(dev_priv->info.display_mmio_offset + 0x61234)
 /* Pre-965 */
 #define		PFIT_VERT_SCALE_SHIFT		20
 #define		PFIT_VERT_SCALE_MASK		0xfff00000
@@ -2421,25 +2434,25 @@
 #define		PFIT_HORIZ_SCALE_SHIFT_965	0
 #define		PFIT_HORIZ_SCALE_MASK_965	0x00001fff
 
-#define PFIT_AUTO_RATIOS (dev_priv->info->display_mmio_offset + 0x61238)
+#define PFIT_AUTO_RATIOS (dev_priv->info.display_mmio_offset + 0x61238)
 
-#define _VLV_BLC_PWM_CTL2_A (dev_priv->info->display_mmio_offset + 0x61250)
-#define _VLV_BLC_PWM_CTL2_B (dev_priv->info->display_mmio_offset + 0x61350)
+#define _VLV_BLC_PWM_CTL2_A (dev_priv->info.display_mmio_offset + 0x61250)
+#define _VLV_BLC_PWM_CTL2_B (dev_priv->info.display_mmio_offset + 0x61350)
 #define VLV_BLC_PWM_CTL2(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
 				     _VLV_BLC_PWM_CTL2_B)
 
-#define _VLV_BLC_PWM_CTL_A (dev_priv->info->display_mmio_offset + 0x61254)
-#define _VLV_BLC_PWM_CTL_B (dev_priv->info->display_mmio_offset + 0x61354)
+#define _VLV_BLC_PWM_CTL_A (dev_priv->info.display_mmio_offset + 0x61254)
+#define _VLV_BLC_PWM_CTL_B (dev_priv->info.display_mmio_offset + 0x61354)
 #define VLV_BLC_PWM_CTL(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
 				    _VLV_BLC_PWM_CTL_B)
 
-#define _VLV_BLC_HIST_CTL_A (dev_priv->info->display_mmio_offset + 0x61260)
-#define _VLV_BLC_HIST_CTL_B (dev_priv->info->display_mmio_offset + 0x61360)
+#define _VLV_BLC_HIST_CTL_A (dev_priv->info.display_mmio_offset + 0x61260)
+#define _VLV_BLC_HIST_CTL_B (dev_priv->info.display_mmio_offset + 0x61360)
 #define VLV_BLC_HIST_CTL(pipe) _PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
 				     _VLV_BLC_HIST_CTL_B)
 
 /* Backlight control */
-#define BLC_PWM_CTL2	(dev_priv->info->display_mmio_offset + 0x61250) /* 965+ only */
+#define BLC_PWM_CTL2	(dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */
 #define   BLM_PWM_ENABLE		(1 << 31)
 #define   BLM_COMBINATION_MODE		(1 << 30) /* gen4 only */
 #define   BLM_PIPE_SELECT		(1 << 29)
@@ -2462,7 +2475,7 @@
 #define   BLM_PHASE_IN_COUNT_MASK	(0xff << 8)
 #define   BLM_PHASE_IN_INCR_SHIFT	(0)
 #define   BLM_PHASE_IN_INCR_MASK	(0xff << 0)
-#define BLC_PWM_CTL	(dev_priv->info->display_mmio_offset + 0x61254)
+#define BLC_PWM_CTL	(dev_priv->info.display_mmio_offset + 0x61254)
 /*
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
@@ -2484,7 +2497,7 @@
 #define   BACKLIGHT_DUTY_CYCLE_MASK_PNV		(0xfffe)
 #define   BLM_POLARITY_PNV			(1 << 0) /* pnv only */
 
-#define BLC_HIST_CTL	(dev_priv->info->display_mmio_offset + 0x61260)
+#define BLC_HIST_CTL	(dev_priv->info.display_mmio_offset + 0x61260)
 
 /* New registers for PCH-split platforms. Safe where new bits show up, the
  * register layout machtes with gen4 BLC_PWM_CTL[12]. */
@@ -3178,10 +3191,10 @@
 /* Display & cursor control */
 
 /* Pipe A */
-#define _PIPEADSL		(dev_priv->info->display_mmio_offset + 0x70000)
+#define _PIPEADSL		0x70000
 #define   DSL_LINEMASK_GEN2	0x00000fff
 #define   DSL_LINEMASK_GEN3	0x00001fff
-#define _PIPEACONF		(dev_priv->info->display_mmio_offset + 0x70008)
+#define _PIPEACONF		0x70008
 #define   PIPECONF_ENABLE	(1<<31)
 #define   PIPECONF_DISABLE	0
 #define   PIPECONF_DOUBLE_WIDE	(1<<30)
@@ -3224,9 +3237,9 @@
 #define   PIPECONF_DITHER_TYPE_ST1 (1<<2)
 #define   PIPECONF_DITHER_TYPE_ST2 (2<<2)
 #define   PIPECONF_DITHER_TYPE_TEMP (3<<2)
-#define _PIPEASTAT		(dev_priv->info->display_mmio_offset + 0x70024)
+#define _PIPEASTAT		0x70024
 #define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31)
-#define   SPRITE1_FLIPDONE_INT_EN_VLV		(1UL<<30)
+#define   SPRITE1_FLIP_DONE_INT_EN_VLV		(1UL<<30)
 #define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)
 #define   PIPE_CRC_DONE_ENABLE			(1UL<<28)
 #define   PIPE_GMBUS_EVENT_ENABLE		(1UL<<27)
@@ -3239,35 +3252,55 @@
 #define   PIPE_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
 #define   PIPE_ODD_FIELD_INTERRUPT_ENABLE	(1UL<<21)
 #define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define   PIPE_B_PSR_INTERRUPT_ENABLE_VLV	(1UL<<19)
 #define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE	(1UL<<18) /* pre-965 */
 #define   PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18) /* 965 or later */
 #define   PIPE_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
 #define   PIPEA_HBLANK_INT_EN_VLV		(1UL<<16)
 #define   PIPE_OVERLAY_UPDATED_ENABLE		(1UL<<16)
-#define   SPRITE1_FLIPDONE_INT_STATUS_VLV	(1UL<<15)
-#define   SPRITE0_FLIPDONE_INT_STATUS_VLV	(1UL<<14)
+#define   SPRITE1_FLIP_DONE_INT_STATUS_VLV	(1UL<<15)
+#define   SPRITE0_FLIP_DONE_INT_STATUS_VLV	(1UL<<14)
 #define   PIPE_CRC_ERROR_INTERRUPT_STATUS	(1UL<<13)
 #define   PIPE_CRC_DONE_INTERRUPT_STATUS	(1UL<<12)
 #define   PIPE_GMBUS_INTERRUPT_STATUS		(1UL<<11)
-#define   PLANE_FLIPDONE_INT_STATUS_VLV		(1UL<<10)
+#define   PLANE_FLIP_DONE_INT_STATUS_VLV	(1UL<<10)
 #define   PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL<<10)
 #define   PIPE_VSYNC_INTERRUPT_STATUS		(1UL<<9)
 #define   PIPE_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
 #define   PIPE_DPST_EVENT_STATUS		(1UL<<7)
 #define   PIPE_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define   PIPE_A_PSR_STATUS_VLV			(1UL<<6)
 #define   PIPE_ODD_FIELD_INTERRUPT_STATUS	(1UL<<5)
 #define   PIPE_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define   PIPE_B_PSR_STATUS_VLV			(1UL<<3)
 #define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS	(1UL<<2) /* pre-965 */
 #define   PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL<<2) /* 965 or later */
 #define   PIPE_VBLANK_INTERRUPT_STATUS		(1UL<<1)
 #define   PIPE_OVERLAY_UPDATED_STATUS		(1UL<<0)
 
-#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
-#define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF)
-#define PIPEDSL(pipe)  _PIPE(pipe, _PIPEADSL, _PIPEBDSL)
-#define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH)
-#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
-#define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT)
+#define PIPESTAT_INT_ENABLE_MASK		0x7fff0000
+#define PIPESTAT_INT_STATUS_MASK		0x0000ffff
+
+#define PIPE_A_OFFSET	0x70000
+#define PIPE_B_OFFSET	0x71000
+#define PIPE_C_OFFSET	0x72000
+/*
+ * There's actually no pipe EDP. Some pipe registers have
+ * simply shifted from the pipe to the transcoder, while
+ * keeping their original offset. Thus we need PIPE_EDP_OFFSET
+ * to access such registers in transcoder EDP.
+ */
+#define PIPE_EDP_OFFSET	0x7f000
+
+#define _PIPE2(pipe, reg) (dev_priv->info.pipe_offsets[pipe] - \
+	dev_priv->info.pipe_offsets[PIPE_A] + (reg) + \
+	dev_priv->info.display_mmio_offset)
+
+#define PIPECONF(pipe) _PIPE2(pipe, _PIPEACONF)
+#define PIPEDSL(pipe)  _PIPE2(pipe, _PIPEADSL)
+#define PIPEFRAME(pipe) _PIPE2(pipe, _PIPEAFRAMEHIGH)
+#define PIPEFRAMEPIXEL(pipe)  _PIPE2(pipe, _PIPEAFRAMEPIXEL)
+#define PIPESTAT(pipe) _PIPE2(pipe, _PIPEASTAT)
 
 #define _PIPE_MISC_A			0x70030
 #define _PIPE_MISC_B			0x71030
@@ -3279,20 +3312,20 @@
 #define   PIPEMISC_DITHER_ENABLE	(1<<4)
 #define   PIPEMISC_DITHER_TYPE_MASK	(3<<2)
 #define   PIPEMISC_DITHER_TYPE_SP	(0<<2)
-#define PIPEMISC(pipe) _PIPE(pipe, _PIPE_MISC_A, _PIPE_MISC_B)
+#define PIPEMISC(pipe) _PIPE2(pipe, _PIPE_MISC_A)
 
 #define VLV_DPFLIPSTAT				(VLV_DISPLAY_BASE + 0x70028)
 #define   PIPEB_LINE_COMPARE_INT_EN		(1<<29)
 #define   PIPEB_HLINE_INT_EN			(1<<28)
 #define   PIPEB_VBLANK_INT_EN			(1<<27)
-#define   SPRITED_FLIPDONE_INT_EN		(1<<26)
-#define   SPRITEC_FLIPDONE_INT_EN		(1<<25)
-#define   PLANEB_FLIPDONE_INT_EN		(1<<24)
+#define   SPRITED_FLIP_DONE_INT_EN		(1<<26)
+#define   SPRITEC_FLIP_DONE_INT_EN		(1<<25)
+#define   PLANEB_FLIP_DONE_INT_EN		(1<<24)
 #define   PIPEA_LINE_COMPARE_INT_EN		(1<<21)
 #define   PIPEA_HLINE_INT_EN			(1<<20)
 #define   PIPEA_VBLANK_INT_EN			(1<<19)
-#define   SPRITEB_FLIPDONE_INT_EN		(1<<18)
-#define   SPRITEA_FLIPDONE_INT_EN		(1<<17)
+#define   SPRITEB_FLIP_DONE_INT_EN		(1<<18)
+#define   SPRITEA_FLIP_DONE_INT_EN		(1<<17)
 #define   PLANEA_FLIPDONE_INT_EN		(1<<16)
 
 #define DPINVGTT				(VLV_DISPLAY_BASE + 0x7002c) /* VLV only */
@@ -3323,7 +3356,7 @@
 #define   DSPARB_BEND_SHIFT	9 /* on 855 */
 #define   DSPARB_AEND_SHIFT	0
 
-#define DSPFW1			(dev_priv->info->display_mmio_offset + 0x70034)
+#define DSPFW1			(dev_priv->info.display_mmio_offset + 0x70034)
 #define   DSPFW_SR_SHIFT	23
 #define   DSPFW_SR_MASK		(0x1ff<<23)
 #define   DSPFW_CURSORB_SHIFT	16
@@ -3331,11 +3364,11 @@
 #define   DSPFW_PLANEB_SHIFT	8
 #define   DSPFW_PLANEB_MASK	(0x7f<<8)
 #define   DSPFW_PLANEA_MASK	(0x7f)
-#define DSPFW2			(dev_priv->info->display_mmio_offset + 0x70038)
+#define DSPFW2			(dev_priv->info.display_mmio_offset + 0x70038)
 #define   DSPFW_CURSORA_MASK	0x00003f00
 #define   DSPFW_CURSORA_SHIFT	8
 #define   DSPFW_PLANEC_MASK	(0x7f)
-#define DSPFW3			(dev_priv->info->display_mmio_offset + 0x7003c)
+#define DSPFW3			(dev_priv->info.display_mmio_offset + 0x7003c)
 #define   DSPFW_HPLL_SR_EN	(1<<31)
 #define   DSPFW_CURSOR_SR_SHIFT	24
 #define   PINEVIEW_SELF_REFRESH_EN	(1<<30)
@@ -3343,8 +3376,8 @@
 #define   DSPFW_HPLL_CURSOR_SHIFT	16
 #define   DSPFW_HPLL_CURSOR_MASK	(0x3f<<16)
 #define   DSPFW_HPLL_SR_MASK		(0x1ff)
-#define DSPFW4			(dev_priv->info->display_mmio_offset + 0x70070)
-#define DSPFW7			(dev_priv->info->display_mmio_offset + 0x7007c)
+#define DSPFW4			(dev_priv->info.display_mmio_offset + 0x70070)
+#define DSPFW7			(dev_priv->info.display_mmio_offset + 0x7007c)
 
 /* drain latency register values*/
 #define DRAIN_LATENCY_PRECISION_32	32
@@ -3468,12 +3501,12 @@
 #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 _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)
 
 /* Cursor A & B regs */
-#define _CURACNTR		(dev_priv->info->display_mmio_offset + 0x70080)
+#define _CURACNTR		(dev_priv->info.display_mmio_offset + 0x70080)
 /* Old style CUR*CNTR flags (desktop 8xx) */
 #define   CURSOR_ENABLE		0x80000000
 #define   CURSOR_GAMMA_ENABLE	0x40000000
@@ -3496,16 +3529,16 @@
 #define   MCURSOR_PIPE_B	(1 << 28)
 #define   MCURSOR_GAMMA_ENABLE  (1 << 26)
 #define   CURSOR_TRICKLE_FEED_DISABLE	(1 << 14)
-#define _CURABASE		(dev_priv->info->display_mmio_offset + 0x70084)
-#define _CURAPOS		(dev_priv->info->display_mmio_offset + 0x70088)
+#define _CURABASE		(dev_priv->info.display_mmio_offset + 0x70084)
+#define _CURAPOS		(dev_priv->info.display_mmio_offset + 0x70088)
 #define   CURSOR_POS_MASK       0x007FF
 #define   CURSOR_POS_SIGN       0x8000
 #define   CURSOR_X_SHIFT        0
 #define   CURSOR_Y_SHIFT        16
 #define CURSIZE			0x700a0
-#define _CURBCNTR		(dev_priv->info->display_mmio_offset + 0x700c0)
-#define _CURBBASE		(dev_priv->info->display_mmio_offset + 0x700c4)
-#define _CURBPOS		(dev_priv->info->display_mmio_offset + 0x700c8)
+#define _CURBCNTR		(dev_priv->info.display_mmio_offset + 0x700c0)
+#define _CURBBASE		(dev_priv->info.display_mmio_offset + 0x700c4)
+#define _CURBPOS		(dev_priv->info.display_mmio_offset + 0x700c8)
 
 #define _CURBCNTR_IVB		0x71080
 #define _CURBBASE_IVB		0x71084
@@ -3520,7 +3553,7 @@
 #define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
 
 /* Display A control */
-#define _DSPACNTR                (dev_priv->info->display_mmio_offset + 0x70180)
+#define _DSPACNTR				0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
 #define   DISPLAY_PLANE_DISABLE			0
 #define   DISPPLANE_GAMMA_ENABLE		(1<<30)
@@ -3554,25 +3587,25 @@
 #define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
 #define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* Ironlake */
 #define   DISPPLANE_TILED			(1<<10)
-#define _DSPAADDR		(dev_priv->info->display_mmio_offset + 0x70184)
-#define _DSPASTRIDE		(dev_priv->info->display_mmio_offset + 0x70188)
-#define _DSPAPOS		(dev_priv->info->display_mmio_offset + 0x7018C) /* reserved */
-#define _DSPASIZE		(dev_priv->info->display_mmio_offset + 0x70190)
-#define _DSPASURF		(dev_priv->info->display_mmio_offset + 0x7019C) /* 965+ only */
-#define _DSPATILEOFF		(dev_priv->info->display_mmio_offset + 0x701A4) /* 965+ only */
-#define _DSPAOFFSET		(dev_priv->info->display_mmio_offset + 0x701A4) /* HSW */
-#define _DSPASURFLIVE		(dev_priv->info->display_mmio_offset + 0x701AC)
-
-#define DSPCNTR(plane) _PIPE(plane, _DSPACNTR, _DSPBCNTR)
-#define DSPADDR(plane) _PIPE(plane, _DSPAADDR, _DSPBADDR)
-#define DSPSTRIDE(plane) _PIPE(plane, _DSPASTRIDE, _DSPBSTRIDE)
-#define DSPPOS(plane) _PIPE(plane, _DSPAPOS, _DSPBPOS)
-#define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE)
-#define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF)
-#define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF)
+#define _DSPAADDR				0x70184
+#define _DSPASTRIDE				0x70188
+#define _DSPAPOS				0x7018C /* reserved */
+#define _DSPASIZE				0x70190
+#define _DSPASURF				0x7019C /* 965+ only */
+#define _DSPATILEOFF				0x701A4 /* 965+ only */
+#define _DSPAOFFSET				0x701A4 /* HSW */
+#define _DSPASURFLIVE				0x701AC
+
+#define DSPCNTR(plane) _PIPE2(plane, _DSPACNTR)
+#define DSPADDR(plane) _PIPE2(plane, _DSPAADDR)
+#define DSPSTRIDE(plane) _PIPE2(plane, _DSPASTRIDE)
+#define DSPPOS(plane) _PIPE2(plane, _DSPAPOS)
+#define DSPSIZE(plane) _PIPE2(plane, _DSPASIZE)
+#define DSPSURF(plane) _PIPE2(plane, _DSPASURF)
+#define DSPTILEOFF(plane) _PIPE2(plane, _DSPATILEOFF)
 #define DSPLINOFF(plane) DSPADDR(plane)
-#define DSPOFFSET(plane) _PIPE(plane, _DSPAOFFSET, _DSPBOFFSET)
-#define DSPSURFLIVE(plane) _PIPE(plane, _DSPASURFLIVE, _DSPBSURFLIVE)
+#define DSPOFFSET(plane) _PIPE2(plane, _DSPAOFFSET)
+#define DSPSURFLIVE(plane) _PIPE2(plane, _DSPASURFLIVE)
 
 /* Display/Sprite base address macros */
 #define DISP_BASEADDR_MASK	(0xfffff000)
@@ -3580,44 +3613,44 @@
 #define I915_HI_DISPBASE(val)	(val & DISP_BASEADDR_MASK)
 
 /* VBIOS flags */
-#define SWF00			(dev_priv->info->display_mmio_offset + 0x71410)
-#define SWF01			(dev_priv->info->display_mmio_offset + 0x71414)
-#define SWF02			(dev_priv->info->display_mmio_offset + 0x71418)
-#define SWF03			(dev_priv->info->display_mmio_offset + 0x7141c)
-#define SWF04			(dev_priv->info->display_mmio_offset + 0x71420)
-#define SWF05			(dev_priv->info->display_mmio_offset + 0x71424)
-#define SWF06			(dev_priv->info->display_mmio_offset + 0x71428)
-#define SWF10			(dev_priv->info->display_mmio_offset + 0x70410)
-#define SWF11			(dev_priv->info->display_mmio_offset + 0x70414)
-#define SWF14			(dev_priv->info->display_mmio_offset + 0x71420)
-#define SWF30			(dev_priv->info->display_mmio_offset + 0x72414)
-#define SWF31			(dev_priv->info->display_mmio_offset + 0x72418)
-#define SWF32			(dev_priv->info->display_mmio_offset + 0x7241c)
+#define SWF00			(dev_priv->info.display_mmio_offset + 0x71410)
+#define SWF01			(dev_priv->info.display_mmio_offset + 0x71414)
+#define SWF02			(dev_priv->info.display_mmio_offset + 0x71418)
+#define SWF03			(dev_priv->info.display_mmio_offset + 0x7141c)
+#define SWF04			(dev_priv->info.display_mmio_offset + 0x71420)
+#define SWF05			(dev_priv->info.display_mmio_offset + 0x71424)
+#define SWF06			(dev_priv->info.display_mmio_offset + 0x71428)
+#define SWF10			(dev_priv->info.display_mmio_offset + 0x70410)
+#define SWF11			(dev_priv->info.display_mmio_offset + 0x70414)
+#define SWF14			(dev_priv->info.display_mmio_offset + 0x71420)
+#define SWF30			(dev_priv->info.display_mmio_offset + 0x72414)
+#define SWF31			(dev_priv->info.display_mmio_offset + 0x72418)
+#define SWF32			(dev_priv->info.display_mmio_offset + 0x7241c)
 
 /* Pipe B */
-#define _PIPEBDSL		(dev_priv->info->display_mmio_offset + 0x71000)
-#define _PIPEBCONF		(dev_priv->info->display_mmio_offset + 0x71008)
-#define _PIPEBSTAT		(dev_priv->info->display_mmio_offset + 0x71024)
+#define _PIPEBDSL		(dev_priv->info.display_mmio_offset + 0x71000)
+#define _PIPEBCONF		(dev_priv->info.display_mmio_offset + 0x71008)
+#define _PIPEBSTAT		(dev_priv->info.display_mmio_offset + 0x71024)
 #define _PIPEBFRAMEHIGH		0x71040
 #define _PIPEBFRAMEPIXEL	0x71044
-#define _PIPEB_FRMCOUNT_GM45	(dev_priv->info->display_mmio_offset + 0x71040)
-#define _PIPEB_FLIPCOUNT_GM45	(dev_priv->info->display_mmio_offset + 0x71044)
+#define _PIPEB_FRMCOUNT_GM45	(dev_priv->info.display_mmio_offset + 0x71040)
+#define _PIPEB_FLIPCOUNT_GM45	(dev_priv->info.display_mmio_offset + 0x71044)
 
 
 /* Display B control */
-#define _DSPBCNTR		(dev_priv->info->display_mmio_offset + 0x71180)
+#define _DSPBCNTR		(dev_priv->info.display_mmio_offset + 0x71180)
 #define   DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
 #define   DISPPLANE_ALPHA_TRANS_DISABLE		0
 #define   DISPPLANE_SPRITE_ABOVE_DISPLAY	0
 #define   DISPPLANE_SPRITE_ABOVE_OVERLAY	(1)
-#define _DSPBADDR		(dev_priv->info->display_mmio_offset + 0x71184)
-#define _DSPBSTRIDE		(dev_priv->info->display_mmio_offset + 0x71188)
-#define _DSPBPOS		(dev_priv->info->display_mmio_offset + 0x7118C)
-#define _DSPBSIZE		(dev_priv->info->display_mmio_offset + 0x71190)
-#define _DSPBSURF		(dev_priv->info->display_mmio_offset + 0x7119C)
-#define _DSPBTILEOFF		(dev_priv->info->display_mmio_offset + 0x711A4)
-#define _DSPBOFFSET		(dev_priv->info->display_mmio_offset + 0x711A4)
-#define _DSPBSURFLIVE		(dev_priv->info->display_mmio_offset + 0x711AC)
+#define _DSPBADDR		(dev_priv->info.display_mmio_offset + 0x71184)
+#define _DSPBSTRIDE		(dev_priv->info.display_mmio_offset + 0x71188)
+#define _DSPBPOS		(dev_priv->info.display_mmio_offset + 0x7118C)
+#define _DSPBSIZE		(dev_priv->info.display_mmio_offset + 0x71190)
+#define _DSPBSURF		(dev_priv->info.display_mmio_offset + 0x7119C)
+#define _DSPBTILEOFF		(dev_priv->info.display_mmio_offset + 0x711A4)
+#define _DSPBOFFSET		(dev_priv->info.display_mmio_offset + 0x711A4)
+#define _DSPBSURFLIVE		(dev_priv->info.display_mmio_offset + 0x711AC)
 
 /* Sprite A control */
 #define _DVSACNTR		0x72180
@@ -3866,48 +3899,45 @@
 #define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK  0xff
 
 
-#define _PIPEA_DATA_M1           (dev_priv->info->display_mmio_offset + 0x60030)
+#define _PIPEA_DATA_M1		0x60030
 #define  PIPE_DATA_M1_OFFSET    0
-#define _PIPEA_DATA_N1           (dev_priv->info->display_mmio_offset + 0x60034)
+#define _PIPEA_DATA_N1		0x60034
 #define  PIPE_DATA_N1_OFFSET    0
 
-#define _PIPEA_DATA_M2           (dev_priv->info->display_mmio_offset + 0x60038)
+#define _PIPEA_DATA_M2		0x60038
 #define  PIPE_DATA_M2_OFFSET    0
-#define _PIPEA_DATA_N2           (dev_priv->info->display_mmio_offset + 0x6003c)
+#define _PIPEA_DATA_N2		0x6003c
 #define  PIPE_DATA_N2_OFFSET    0
 
-#define _PIPEA_LINK_M1           (dev_priv->info->display_mmio_offset + 0x60040)
+#define _PIPEA_LINK_M1		0x60040
 #define  PIPE_LINK_M1_OFFSET    0
-#define _PIPEA_LINK_N1           (dev_priv->info->display_mmio_offset + 0x60044)
+#define _PIPEA_LINK_N1		0x60044
 #define  PIPE_LINK_N1_OFFSET    0
 
-#define _PIPEA_LINK_M2           (dev_priv->info->display_mmio_offset + 0x60048)
+#define _PIPEA_LINK_M2		0x60048
 #define  PIPE_LINK_M2_OFFSET    0
-#define _PIPEA_LINK_N2           (dev_priv->info->display_mmio_offset + 0x6004c)
+#define _PIPEA_LINK_N2		0x6004c
 #define  PIPE_LINK_N2_OFFSET    0
 
 /* PIPEB timing regs are same start from 0x61000 */
 
-#define _PIPEB_DATA_M1           (dev_priv->info->display_mmio_offset + 0x61030)
-#define _PIPEB_DATA_N1           (dev_priv->info->display_mmio_offset + 0x61034)
-
-#define _PIPEB_DATA_M2           (dev_priv->info->display_mmio_offset + 0x61038)
-#define _PIPEB_DATA_N2           (dev_priv->info->display_mmio_offset + 0x6103c)
-
-#define _PIPEB_LINK_M1           (dev_priv->info->display_mmio_offset + 0x61040)
-#define _PIPEB_LINK_N1           (dev_priv->info->display_mmio_offset + 0x61044)
-
-#define _PIPEB_LINK_M2           (dev_priv->info->display_mmio_offset + 0x61048)
-#define _PIPEB_LINK_N2           (dev_priv->info->display_mmio_offset + 0x6104c)
-
-#define PIPE_DATA_M1(tran) _TRANSCODER(tran, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
-#define PIPE_DATA_N1(tran) _TRANSCODER(tran, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
-#define PIPE_DATA_M2(tran) _TRANSCODER(tran, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
-#define PIPE_DATA_N2(tran) _TRANSCODER(tran, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
-#define PIPE_LINK_M1(tran) _TRANSCODER(tran, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
-#define PIPE_LINK_N1(tran) _TRANSCODER(tran, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
-#define PIPE_LINK_M2(tran) _TRANSCODER(tran, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
-#define PIPE_LINK_N2(tran) _TRANSCODER(tran, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
+#define _PIPEB_DATA_M1		0x61030
+#define _PIPEB_DATA_N1		0x61034
+#define _PIPEB_DATA_M2		0x61038
+#define _PIPEB_DATA_N2		0x6103c
+#define _PIPEB_LINK_M1		0x61040
+#define _PIPEB_LINK_N1		0x61044
+#define _PIPEB_LINK_M2		0x61048
+#define _PIPEB_LINK_N2		0x6104c
+
+#define PIPE_DATA_M1(tran) _TRANSCODER2(tran, _PIPEA_DATA_M1)
+#define PIPE_DATA_N1(tran) _TRANSCODER2(tran, _PIPEA_DATA_N1)
+#define PIPE_DATA_M2(tran) _TRANSCODER2(tran, _PIPEA_DATA_M2)
+#define PIPE_DATA_N2(tran) _TRANSCODER2(tran, _PIPEA_DATA_N2)
+#define PIPE_LINK_M1(tran) _TRANSCODER2(tran, _PIPEA_LINK_M1)
+#define PIPE_LINK_N1(tran) _TRANSCODER2(tran, _PIPEA_LINK_N1)
+#define PIPE_LINK_M2(tran) _TRANSCODER2(tran, _PIPEA_LINK_M2)
+#define PIPE_LINK_N2(tran) _TRANSCODER2(tran, _PIPEA_LINK_N2)
 
 /* CPU panel fitter */
 /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
@@ -4084,13 +4114,14 @@
 #define  ILK_ELPIN_409_SELECT	(1 << 25)
 #define  ILK_DPARB_GATE	(1<<22)
 #define  ILK_VSDPFD_FULL	(1<<21)
-#define ILK_DISPLAY_CHICKEN_FUSES	0x42014
-#define  ILK_INTERNAL_GRAPHICS_DISABLE	(1<<31)
-#define  ILK_INTERNAL_DISPLAY_DISABLE	(1<<30)
-#define  ILK_DISPLAY_DEBUG_DISABLE	(1<<29)
-#define  ILK_HDCP_DISABLE		(1<<25)
-#define  ILK_eDP_A_DISABLE		(1<<24)
-#define  ILK_DESKTOP			(1<<23)
+#define FUSE_STRAP			0x42014
+#define  ILK_INTERNAL_GRAPHICS_DISABLE	(1 << 31)
+#define  ILK_INTERNAL_DISPLAY_DISABLE	(1 << 30)
+#define  ILK_DISPLAY_DEBUG_DISABLE	(1 << 29)
+#define  ILK_HDCP_DISABLE		(1 << 25)
+#define  ILK_eDP_A_DISABLE		(1 << 24)
+#define  HSW_CDCLK_LIMIT		(1 << 24)
+#define  ILK_DESKTOP			(1 << 23)
 
 #define ILK_DSPCLK_GATE_D			0x42020
 #define   ILK_VRHUNIT_CLOCK_GATE_DISABLE	(1 << 28)
@@ -4120,6 +4151,8 @@
 #define GEN7_MSG_CTL	0x45010
 #define  WAIT_FOR_PCH_RESET_ACK		(1<<1)
 #define  WAIT_FOR_PCH_FLR_ACK		(1<<0)
+#define HSW_NDE_RSTWRN_OPT	0x46408
+#define  RESET_PCH_HANDSHAKE_ENABLE	(1<<4)
 
 /* GEN7 chicken */
 #define GEN7_COMMON_SLICE_CHICKEN1		0x7010
@@ -4127,6 +4160,9 @@
 #define COMMON_SLICE_CHICKEN2			0x7014
 # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE	(1<<0)
 
+#define GEN7_L3SQCREG1				0xB010
+#define  VLV_B0_WA_L3SQCREG1_VALUE		0x00D30000
+
 #define GEN7_L3CNTLREG1				0xB01C
 #define  GEN7_WA_FOR_GEN7_L3_CONTROL			0x3C4FFF8C
 #define  GEN7_L3AGDIS				(1<<19)
@@ -4148,9 +4184,6 @@
 #define HSW_SCRATCH1				0xb038
 #define  HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE	(1<<27)
 
-#define HSW_FUSE_STRAP		0x42014
-#define  HSW_CDCLK_LIMIT	(1 << 24)
-
 /* PCH */
 
 /* south display engine interrupt: IBX */
@@ -4436,24 +4469,24 @@
 #define HSW_VIDEO_DIP_GCP_B		0x61210
 
 #define HSW_TVIDEO_DIP_CTL(trans) \
-	 _TRANSCODER(trans, HSW_VIDEO_DIP_CTL_A, HSW_VIDEO_DIP_CTL_B)
+	 _TRANSCODER2(trans, HSW_VIDEO_DIP_CTL_A)
 #define HSW_TVIDEO_DIP_AVI_DATA(trans) \
-	 _TRANSCODER(trans, HSW_VIDEO_DIP_AVI_DATA_A, HSW_VIDEO_DIP_AVI_DATA_B)
+	 _TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A)
 #define HSW_TVIDEO_DIP_VS_DATA(trans) \
-	 _TRANSCODER(trans, HSW_VIDEO_DIP_VS_DATA_A, HSW_VIDEO_DIP_VS_DATA_B)
+	 _TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A)
 #define HSW_TVIDEO_DIP_SPD_DATA(trans) \
-	 _TRANSCODER(trans, HSW_VIDEO_DIP_SPD_DATA_A, HSW_VIDEO_DIP_SPD_DATA_B)
+	 _TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A)
 #define HSW_TVIDEO_DIP_GCP(trans) \
-	_TRANSCODER(trans, HSW_VIDEO_DIP_GCP_A, HSW_VIDEO_DIP_GCP_B)
+	_TRANSCODER2(trans, HSW_VIDEO_DIP_GCP_A)
 #define HSW_TVIDEO_DIP_VSC_DATA(trans) \
-	 _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B)
+	 _TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A)
 
 #define HSW_STEREO_3D_CTL_A	0x70020
 #define   S3D_ENABLE		(1<<31)
 #define HSW_STEREO_3D_CTL_B	0x71020
 
 #define HSW_STEREO_3D_CTL(trans) \
-	_TRANSCODER(trans, HSW_STEREO_3D_CTL_A, HSW_STEREO_3D_CTL_A)
+	_PIPE2(trans, HSW_STEREO_3D_CTL_A)
 
 #define _PCH_TRANS_HTOTAL_B          0xe1000
 #define _PCH_TRANS_HBLANK_B          0xe1004
@@ -4945,6 +4978,10 @@
 						 GEN6_PM_RP_DOWN_THRESHOLD | \
 						 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define VLV_GTLC_SURVIVABILITY_REG              0x130098
+#define VLV_GFX_CLK_STATUS_BIT			(1<<3)
+#define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
+
 #define GEN6_GT_GFX_RC6_LOCKED			0x138104
 #define VLV_COUNTER_CONTROL			0x138104
 #define   VLV_COUNT_RANGE_HIGH			(1<<15)
@@ -5017,7 +5054,7 @@
 #define   GEN8_CENTROID_PIXEL_OPT_DIS	(1<<8)
 #define   GEN8_SAMPLER_POWER_BYPASS_DIS	(1<<1)
 
-#define G4X_AUD_VID_DID			(dev_priv->info->display_mmio_offset + 0x62020)
+#define G4X_AUD_VID_DID			(dev_priv->info.display_mmio_offset + 0x62020)
 #define INTEL_AUDIO_DEVCL		0x808629FB
 #define INTEL_AUDIO_DEVBLC		0x80862801
 #define INTEL_AUDIO_DEVCTG		0x80862802
@@ -5178,8 +5215,8 @@
 #define TRANS_DDI_FUNC_CTL_B		0x61400
 #define TRANS_DDI_FUNC_CTL_C		0x62400
 #define TRANS_DDI_FUNC_CTL_EDP		0x6F400
-#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER(tran, TRANS_DDI_FUNC_CTL_A, \
-						   TRANS_DDI_FUNC_CTL_B)
+#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER2(tran, TRANS_DDI_FUNC_CTL_A)
+
 #define  TRANS_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
 #define  TRANS_DDI_PORT_MASK		(7<<28)
@@ -5311,8 +5348,12 @@
 #define  SPLL_PLL_ENABLE		(1<<31)
 #define  SPLL_PLL_SSC			(1<<28)
 #define  SPLL_PLL_NON_SSC		(2<<28)
+#define  SPLL_PLL_LCPLL			(3<<28)
+#define  SPLL_PLL_REF_MASK		(3<<28)
 #define  SPLL_PLL_FREQ_810MHz		(0<<26)
 #define  SPLL_PLL_FREQ_1350MHz		(1<<26)
+#define  SPLL_PLL_FREQ_2700MHz		(2<<26)
+#define  SPLL_PLL_FREQ_MASK		(3<<26)
 
 /* WRPLL */
 #define WRPLL_CTL1			0x46040
@@ -5323,8 +5364,13 @@
 #define  WRPLL_PLL_SELECT_LCPLL_2700	(0x03<<28)
 /* WRPLL divider programming */
 #define  WRPLL_DIVIDER_REFERENCE(x)	((x)<<0)
+#define  WRPLL_DIVIDER_REF_MASK		(0xff)
 #define  WRPLL_DIVIDER_POST(x)		((x)<<8)
+#define  WRPLL_DIVIDER_POST_MASK	(0x3f<<8)
+#define  WRPLL_DIVIDER_POST_SHIFT	8
 #define  WRPLL_DIVIDER_FEEDBACK(x)	((x)<<16)
+#define  WRPLL_DIVIDER_FB_SHIFT		16
+#define  WRPLL_DIVIDER_FB_MASK		(0xff<<16)
 
 /* Port clock selection */
 #define PORT_CLK_SEL_A			0x46100
@@ -5337,6 +5383,7 @@
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
 #define  PORT_CLK_SEL_NONE		(7<<29)
+#define  PORT_CLK_SEL_MASK		(7<<29)
 
 /* Transcoder clock selection */
 #define TRANS_CLK_SEL_A			0x46140
@@ -5346,10 +5393,12 @@
 #define  TRANS_CLK_SEL_DISABLED		(0x0<<29)
 #define  TRANS_CLK_SEL_PORT(x)		((x+1)<<29)
 
-#define _TRANSA_MSA_MISC		0x60410
-#define _TRANSB_MSA_MISC		0x61410
-#define TRANS_MSA_MISC(tran) _TRANSCODER(tran, _TRANSA_MSA_MISC, \
-					       _TRANSB_MSA_MISC)
+#define TRANSA_MSA_MISC			0x60410
+#define TRANSB_MSA_MISC			0x61410
+#define TRANSC_MSA_MISC			0x62410
+#define TRANS_EDP_MSA_MISC		0x6f410
+#define TRANS_MSA_MISC(tran) _TRANSCODER2(tran, TRANSA_MSA_MISC)
+
 #define  TRANS_MSA_SYNC_CLK		(1<<0)
 #define  TRANS_MSA_6_BPC		(0<<5)
 #define  TRANS_MSA_8_BPC		(1<<5)
@@ -5389,6 +5438,8 @@
 
 /* SFUSE_STRAP */
 #define SFUSE_STRAP			0xc2014
+#define  SFUSE_STRAP_FUSE_LOCK		(1<<13)
+#define  SFUSE_STRAP_DISPLAY_DISABLED	(1<<7)
 #define  SFUSE_STRAP_DDIB_DETECTED	(1<<2)
 #define  SFUSE_STRAP_DDIC_DETECTED	(1<<1)
 #define  SFUSE_STRAP_DDID_DETECTED	(1<<0)
@@ -5857,4 +5908,12 @@
 #define MIPI_READ_DATA_VALID(pipe)	_PIPE(pipe, _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
 #define  READ_DATA_VALID(n)				(1 << (n))
 
+/* For UMS only (deprecated): */
+#define _PALETTE_A (dev_priv->info.display_mmio_offset + 0xa000)
+#define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800)
+#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
+#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
+#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
+#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
+
 #endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 8150fdc08d49..56785e8fb2eb 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -236,19 +236,9 @@ static void i915_save_display(struct drm_device *dev)
 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
 	}
 
-	/* Only regfile.save FBC state on the platform that supports FBC */
-	if (HAS_FBC(dev)) {
-		if (HAS_PCH_SPLIT(dev)) {
-			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
-		} else if (IS_GM45(dev)) {
-			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
-		} else {
-			dev_priv->regfile.saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
-			dev_priv->regfile.saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
-			dev_priv->regfile.saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
-			dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-		}
-	}
+	/* save FBC interval */
+	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+		dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_save_vga(dev);
@@ -300,18 +290,10 @@ static void i915_restore_display(struct drm_device *dev)
 
 	/* only restore FBC info on the platform that supports FBC*/
 	intel_disable_fbc(dev);
-	if (HAS_FBC(dev)) {
-		if (HAS_PCH_SPLIT(dev)) {
-			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
-		} else if (IS_GM45(dev)) {
-			I915_WRITE(DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
-		} else {
-			I915_WRITE(FBC_CFB_BASE, dev_priv->regfile.saveFBC_CFB_BASE);
-			I915_WRITE(FBC_LL_BASE, dev_priv->regfile.saveFBC_LL_BASE);
-			I915_WRITE(FBC_CONTROL2, dev_priv->regfile.saveFBC_CONTROL2);
-			I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
-		}
-	}
+
+	/* restore FBC interval */
+	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+		I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_restore_vga(dev);
@@ -324,10 +306,6 @@ int i915_save_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	if (INTEL_INFO(dev)->gen <= 4)
-		pci_read_config_byte(dev->pdev, LBB,
-				     &dev_priv->regfile.saveLBB);
-
 	mutex_lock(&dev->struct_mutex);
 
 	i915_save_display(dev);
@@ -377,10 +355,6 @@ int i915_restore_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	if (INTEL_INFO(dev)->gen <= 4)
-		pci_write_config_byte(dev->pdev, LBB,
-				      dev_priv->regfile.saveLBB);
-
 	mutex_lock(&dev->struct_mutex);
 
 	i915_gem_restore_fences(dev);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 33bcae314bf8..0c741f4eefb0 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -357,6 +357,11 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		else
 			gen6_set_rps(dev, val);
 	}
+	else if (!IS_VALLEYVIEW(dev))
+		/* We still need gen6_set_rps to process the new max_delay
+		   and update the interrupt limits even though frequency
+		   request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_delay);
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -426,6 +431,11 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 		else
 			gen6_set_rps(dev, val);
 	}
+	else if (!IS_VALLEYVIEW(dev))
+		/* We still need gen6_set_rps to process the new min_delay
+		   and update the interrupt limits even though frequency
+		   request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_delay);
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 6e580c98dede..b95a380958db 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -34,15 +34,15 @@ TRACE_EVENT(i915_gem_object_create,
 );
 
 TRACE_EVENT(i915_vma_bind,
-	    TP_PROTO(struct i915_vma *vma, bool mappable),
-	    TP_ARGS(vma, mappable),
+	    TP_PROTO(struct i915_vma *vma, unsigned flags),
+	    TP_ARGS(vma, flags),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
 			     __field(struct i915_address_space *, vm)
 			     __field(u32, offset)
 			     __field(u32, size)
-			     __field(bool, mappable)
+			     __field(unsigned, flags)
 			     ),
 
 	    TP_fast_assign(
@@ -50,12 +50,12 @@ TRACE_EVENT(i915_vma_bind,
 			   __entry->vm = vma->vm;
 			   __entry->offset = vma->node.start;
 			   __entry->size = vma->node.size;
-			   __entry->mappable = mappable;
+			   __entry->flags = flags;
 			   ),
 
 	    TP_printk("obj=%p, offset=%08x size=%x%s vm=%p",
 		      __entry->obj, __entry->offset, __entry->size,
-		      __entry->mappable ? ", mappable" : "",
+		      __entry->flags & PIN_MAPPABLE ? ", mappable" : "",
 		      __entry->vm)
 );
 
@@ -196,26 +196,26 @@ DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
 );
 
 TRACE_EVENT(i915_gem_evict,
-	    TP_PROTO(struct drm_device *dev, u32 size, u32 align, bool mappable),
-	    TP_ARGS(dev, size, align, mappable),
+	    TP_PROTO(struct drm_device *dev, u32 size, u32 align, unsigned flags),
+	    TP_ARGS(dev, size, align, flags),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
 			     __field(u32, size)
 			     __field(u32, align)
-			     __field(bool, mappable)
+			     __field(unsigned, flags)
 			    ),
 
 	    TP_fast_assign(
 			   __entry->dev = dev->primary->index;
 			   __entry->size = size;
 			   __entry->align = align;
-			   __entry->mappable = mappable;
+			   __entry->flags = flags;
 			  ),
 
 	    TP_printk("dev=%d, size=%d, align=%d %s",
 		      __entry->dev, __entry->size, __entry->align,
-		      __entry->mappable ? ", mappable" : "")
+		      __entry->flags & PIN_MAPPABLE ? ", mappable" : "")
 );
 
 TRACE_EVENT(i915_gem_evict_everything,
diff --git a/drivers/gpu/drm/i915/i915_ums.c b/drivers/gpu/drm/i915/i915_ums.c
index caa18e855815..480da593e6c0 100644
--- a/drivers/gpu/drm/i915/i915_ums.c
+++ b/drivers/gpu/drm/i915/i915_ums.c
@@ -271,6 +271,10 @@ void i915_save_display_reg(struct drm_device *dev)
 	/* FIXME: regfile.save TV & SDVO state */
 
 	/* Backlight */
+	if (INTEL_INFO(dev)->gen <= 4)
+		pci_read_config_byte(dev->pdev, PCI_LBPC,
+				     &dev_priv->regfile.saveLBB);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
 		dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
@@ -293,6 +297,10 @@ void i915_restore_display_reg(struct drm_device *dev)
 	int i;
 
 	/* Backlight */
+	if (INTEL_INFO(dev)->gen <= 4)
+		pci_write_config_byte(dev->pdev, PCI_LBPC,
+				      dev_priv->regfile.saveLBB);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
 		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index f22041973f3a..86b95ca413d1 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -259,7 +259,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 			downclock = dvo_timing->clock;
 	}
 
-	if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) {
+	if (downclock < panel_dvo_timing->clock && i915.lvds_downclock) {
 		dev_priv->lvds_downclock_avail = 1;
 		dev_priv->lvds_downclock = downclock * 10;
 		DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
@@ -318,7 +318,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 	struct drm_display_mode *panel_fixed_mode;
 	int index;
 
-	index = i915_vbt_sdvo_panel_type;
+	index = i915.vbt_sdvo_panel_type;
 	if (index == -2) {
 		DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n");
 		return;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index e2e39e65f109..9864aa1ccbe8 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -833,6 +833,7 @@ void intel_crt_init(struct drm_device *dev)
 		crt->base.get_hw_state = intel_crt_get_hw_state;
 	}
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
@@ -857,4 +858,6 @@ void intel_crt_init(struct drm_device *dev)
 
 		dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config;
 	}
+
+	intel_crt_reset(connector);
 }
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index e06b9e017d6b..2643d3b8b67d 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -633,6 +633,97 @@ static void wrpll_update_rnp(uint64_t freq2k, unsigned budget,
 	/* Otherwise a < c && b >= d, do nothing */
 }
 
+static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
+				     int reg)
+{
+	int refclk = LC_FREQ;
+	int n, p, r;
+	u32 wrpll;
+
+	wrpll = I915_READ(reg);
+	switch (wrpll & SPLL_PLL_REF_MASK) {
+	case SPLL_PLL_SSC:
+	case SPLL_PLL_NON_SSC:
+		/*
+		 * We could calculate spread here, but our checking
+		 * code only cares about 5% accuracy, and spread is a max of
+		 * 0.5% downspread.
+		 */
+		refclk = 135;
+		break;
+	case SPLL_PLL_LCPLL:
+		refclk = LC_FREQ;
+		break;
+	default:
+		WARN(1, "bad wrpll refclk\n");
+		return 0;
+	}
+
+	r = wrpll & WRPLL_DIVIDER_REF_MASK;
+	p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT;
+	n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT;
+
+	/* Convert to KHz, p & r have a fixed point portion */
+	return (refclk * n * 100) / (p * r);
+}
+
+static void intel_ddi_clock_get(struct intel_encoder *encoder,
+				struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	enum port port = intel_ddi_get_encoder_port(encoder);
+	int link_clock = 0;
+	u32 val, pll;
+
+	val = I915_READ(PORT_CLK_SEL(port));
+	switch (val & PORT_CLK_SEL_MASK) {
+	case PORT_CLK_SEL_LCPLL_810:
+		link_clock = 81000;
+		break;
+	case PORT_CLK_SEL_LCPLL_1350:
+		link_clock = 135000;
+		break;
+	case PORT_CLK_SEL_LCPLL_2700:
+		link_clock = 270000;
+		break;
+	case PORT_CLK_SEL_WRPLL1:
+		link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1);
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2);
+		break;
+	case PORT_CLK_SEL_SPLL:
+		pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK;
+		if (pll == SPLL_PLL_FREQ_810MHz)
+			link_clock = 81000;
+		else if (pll == SPLL_PLL_FREQ_1350MHz)
+			link_clock = 135000;
+		else if (pll == SPLL_PLL_FREQ_2700MHz)
+			link_clock = 270000;
+		else {
+			WARN(1, "bad spll freq\n");
+			return;
+		}
+		break;
+	default:
+		WARN(1, "bad port clock sel\n");
+		return;
+	}
+
+	pipe_config->port_clock = link_clock * 2;
+
+	if (pipe_config->has_pch_encoder)
+		pipe_config->adjusted_mode.crtc_clock =
+			intel_dotclock_calculate(pipe_config->port_clock,
+						 &pipe_config->fdi_m_n);
+	else if (pipe_config->has_dp_encoder)
+		pipe_config->adjusted_mode.crtc_clock =
+			intel_dotclock_calculate(pipe_config->port_clock,
+						 &pipe_config->dp_m_n);
+	else
+		pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock;
+}
+
 static void
 intel_ddi_calculate_wrpll(int clock /* in Hz */,
 			  unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
@@ -1200,7 +1291,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		ironlake_edp_panel_on(intel_dp);
+		intel_edp_panel_on(intel_dp);
 	}
 
 	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
@@ -1244,7 +1335,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
-		ironlake_edp_panel_off(intel_dp);
+		intel_edp_panel_off(intel_dp);
 	}
 
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
@@ -1279,7 +1370,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 		if (port == PORT_A)
 			intel_dp_stop_link_train(intel_dp);
 
-		ironlake_edp_backlight_on(intel_dp);
+		intel_edp_backlight_on(intel_dp);
 		intel_edp_psr_enable(intel_dp);
 	}
 
@@ -1312,7 +1403,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		intel_edp_psr_disable(intel_dp);
-		ironlake_edp_backlight_off(intel_dp);
+		intel_edp_backlight_off(intel_dp);
 	}
 }
 
@@ -1324,7 +1415,7 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
 
 	if (lcpll & LCPLL_CD_SOURCE_FCLK) {
 		return 800000;
-	} else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) {
+	} else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) {
 		return 450000;
 	} else if (freq == LCPLL_CLK_FREQ_450) {
 		return 450000;
@@ -1509,6 +1600,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
 			      pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
 		dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
 	}
+
+	intel_ddi_clock_get(encoder, pipe_config);
 }
 
 static void intel_ddi_destroy(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4c1672809493..6f156278c4ed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -51,7 +51,10 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
 
 static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			  int x, int y, struct drm_framebuffer *old_fb);
-
+static int intel_framebuffer_init(struct drm_device *dev,
+				  struct intel_framebuffer *ifb,
+				  struct drm_mode_fb_cmd2 *mode_cmd,
+				  struct drm_i915_gem_object *obj);
 
 typedef struct {
 	int	min, max;
@@ -1030,7 +1033,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
 	u32 val;
 
 	/* ILK FDI PLL is always enabled */
-	if (dev_priv->info->gen == 5)
+	if (INTEL_INFO(dev_priv->dev)->gen == 5)
 		return;
 
 	/* On Haswell, DDI ports are responsible for the FDI PLL setup */
@@ -1092,12 +1095,12 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
 	struct drm_device *dev = dev_priv->dev;
 	bool cur_state;
 
-	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-		cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
-	else if (IS_845G(dev) || IS_I865G(dev))
+	if (IS_845G(dev) || IS_I865G(dev))
 		cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
-	else
+	else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev))
 		cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
+	else
+		cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
 
 	WARN(cur_state != state,
 	     "cursor on pipe %c assertion failure (expected %s, current %s)\n",
@@ -1189,7 +1192,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
 	u32 val;
 
 	if (IS_VALLEYVIEW(dev)) {
-		for (i = 0; i < dev_priv->num_plane; i++) {
+		for (i = 0; i < INTEL_INFO(dev)->num_sprites; i++) {
 			reg = SPCNTR(pipe, i);
 			val = I915_READ(reg);
 			WARN((val & SP_ENABLE),
@@ -1443,7 +1446,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
 	assert_pipe_disabled(dev_priv, crtc->pipe);
 
 	/* No really, not for ILK+ */
-	BUG_ON(dev_priv->info->gen >= 5);
+	BUG_ON(INTEL_INFO(dev)->gen >= 5);
 
 	/* PLL is protected by panel, make sure we can write it */
 	if (IS_MOBILE(dev) && !IS_I830(dev))
@@ -1549,11 +1552,12 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
  */
 static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
 	/* PCH PLLs only available on ILK, SNB and IVB */
-	BUG_ON(dev_priv->info->gen < 5);
+	BUG_ON(INTEL_INFO(dev)->gen < 5);
 	if (WARN_ON(pll == NULL))
 		return;
 
@@ -1578,11 +1582,12 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
 
 static void intel_disable_shared_dpll(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
 	/* PCH only available on ILK+ */
-	BUG_ON(dev_priv->info->gen < 5);
+	BUG_ON(INTEL_INFO(dev)->gen < 5);
 	if (WARN_ON(pll == NULL))
 	       return;
 
@@ -1617,7 +1622,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 	uint32_t reg, val, pipeconf_val;
 
 	/* PCH only available on ILK+ */
-	BUG_ON(dev_priv->info->gen < 5);
+	BUG_ON(INTEL_INFO(dev)->gen < 5);
 
 	/* Make sure PCH DPLL is enabled */
 	assert_shared_dpll_enabled(dev_priv,
@@ -1670,7 +1675,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 	u32 val, pipeconf_val;
 
 	/* PCH only available on ILK+ */
-	BUG_ON(dev_priv->info->gen < 5);
+	BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
 
 	/* FDI must be feeding us bits for PCH ports */
 	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
@@ -1744,21 +1749,16 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
 
 /**
  * intel_enable_pipe - enable a pipe, asserting requirements
- * @dev_priv: i915 private structure
- * @pipe: pipe to enable
- * @pch_port: on ILK+, is this pipe driving a PCH port or not
+ * @crtc: crtc responsible for the pipe
  *
- * Enable @pipe, making sure that various hardware specific requirements
+ * Enable @crtc's pipe, making sure that various hardware specific requirements
  * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
- *
- * @pipe should be %PIPE_A or %PIPE_B.
- *
- * Will wait until the pipe is actually running (i.e. first vblank) before
- * returning.
  */
-static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
-			      bool pch_port, bool dsi)
+static void intel_enable_pipe(struct intel_crtc *crtc)
 {
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe = crtc->pipe;
 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
 								      pipe);
 	enum pipe pch_transcoder;
@@ -1780,12 +1780,12 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 	 * need the check.
 	 */
 	if (!HAS_PCH_SPLIT(dev_priv->dev))
-		if (dsi)
+		if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DSI))
 			assert_dsi_pll_enabled(dev_priv);
 		else
 			assert_pll_enabled(dev_priv, pipe);
 	else {
-		if (pch_port) {
+		if (crtc->config.has_pch_encoder) {
 			/* if driving the PCH, we need FDI enabled */
 			assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
 			assert_fdi_tx_pll_enabled(dev_priv,
@@ -1796,11 +1796,24 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 
 	reg = PIPECONF(cpu_transcoder);
 	val = I915_READ(reg);
-	if (val & PIPECONF_ENABLE)
+	if (val & PIPECONF_ENABLE) {
+		WARN_ON(!(pipe == PIPE_A &&
+			  dev_priv->quirks & QUIRK_PIPEA_FORCE));
 		return;
+	}
 
 	I915_WRITE(reg, val | PIPECONF_ENABLE);
-	intel_wait_for_vblank(dev_priv->dev, pipe);
+	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);
 }
 
 /**
@@ -1851,7 +1864,8 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
 			       enum plane plane)
 {
-	u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
+	struct drm_device *dev = dev_priv->dev;
+	u32 reg = INTEL_INFO(dev)->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
 
 	I915_WRITE(reg, I915_READ(reg));
 	POSTING_READ(reg);
@@ -1929,6 +1943,14 @@ static bool need_vtd_wa(struct drm_device *dev)
 	return false;
 }
 
+static int intel_align_height(struct drm_device *dev, int height, bool tiled)
+{
+	int tile_height;
+
+	tile_height = tiled ? (IS_GEN2(dev) ? 16 : 8) : 1;
+	return ALIGN(height, tile_height);
+}
+
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			   struct drm_i915_gem_object *obj,
@@ -2299,33 +2321,6 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 	return ret;
 }
 
-static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_master_private *master_priv;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	if (!dev->primary->master)
-		return;
-
-	master_priv = dev->primary->master->driver_priv;
-	if (!master_priv->sarea_priv)
-		return;
-
-	switch (intel_crtc->pipe) {
-	case 0:
-		master_priv->sarea_priv->pipeA_x = x;
-		master_priv->sarea_priv->pipeA_y = y;
-		break;
-	case 1:
-		master_priv->sarea_priv->pipeB_x = x;
-		master_priv->sarea_priv->pipeB_y = y;
-		break;
-	default:
-		break;
-	}
-}
-
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		    struct drm_framebuffer *fb)
@@ -2372,7 +2367,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	 * whether the platform allows pfit disable with pipe active, and only
 	 * then update the pipesrc and pfit state, even on the flip path.
 	 */
-	if (i915_fastboot) {
+	if (i915.fastboot) {
 		const struct drm_display_mode *adjusted_mode =
 			&intel_crtc->config.adjusted_mode;
 
@@ -2413,8 +2408,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 
-	intel_crtc_update_sarea_pos(crtc, x, y);
-
 	return 0;
 }
 
@@ -3587,8 +3580,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_load_lut(crtc);
 
 	intel_update_watermarks(crtc);
-	intel_enable_pipe(dev_priv, pipe,
-			  intel_crtc->config.has_pch_encoder, false);
+	intel_enable_pipe(intel_crtc);
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
@@ -3733,8 +3725,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_enable_transcoder_func(crtc);
 
 	intel_update_watermarks(crtc);
-	intel_enable_pipe(dev_priv, pipe,
-			  intel_crtc->config.has_pch_encoder, false);
+	intel_enable_pipe(intel_crtc);
 
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
@@ -3748,16 +3739,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	 * to change the workaround. */
 	haswell_mode_set_planes_workaround(intel_crtc);
 	haswell_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
-	 * away (as if the pipe is off) instead of waiting for vblank. As soon
-	 * as the first vblank happend, everything works as expected. Hence just
-	 * wait for one vblank before returning to avoid strange things
-	 * happening.
-	 */
-	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -4088,9 +4069,8 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
 	/* Looks like the 200MHz CDclk freq doesn't work on some configs */
 }
 
-static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv,
-				 unsigned modeset_pipes,
-				 struct intel_crtc_config *pipe_config)
+/* compute the max pixel clock for new configuration */
+static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct intel_crtc *intel_crtc;
@@ -4098,31 +4078,26 @@ static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv,
 
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		if (modeset_pipes & (1 << intel_crtc->pipe))
-			max_pixclk = max(max_pixclk,
-					 pipe_config->adjusted_mode.crtc_clock);
-		else if (intel_crtc->base.enabled)
+		if (intel_crtc->new_enabled)
 			max_pixclk = max(max_pixclk,
-					 intel_crtc->config.adjusted_mode.crtc_clock);
+					 intel_crtc->new_config->adjusted_mode.crtc_clock);
 	}
 
 	return max_pixclk;
 }
 
 static void valleyview_modeset_global_pipes(struct drm_device *dev,
-					    unsigned *prepare_pipes,
-					    unsigned modeset_pipes,
-					    struct intel_crtc_config *pipe_config)
+					    unsigned *prepare_pipes)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
-	int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes,
-					       pipe_config);
+	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)
 		return;
 
+	/* disable/enable all currently active pipes while we change cdclk */
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head)
 		if (intel_crtc->base.enabled)
@@ -4132,7 +4107,7 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev,
 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, 0, NULL);
+	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);
 
@@ -4175,7 +4150,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_load_lut(crtc);
 
 	intel_update_watermarks(crtc);
-	intel_enable_pipe(dev_priv, pipe, false, is_dsi);
+	intel_enable_pipe(intel_crtc);
+	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
@@ -4213,7 +4189,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_load_lut(crtc);
 
 	intel_update_watermarks(crtc);
-	intel_enable_pipe(dev_priv, pipe, false, false);
+	intel_enable_pipe(intel_crtc);
+	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	/* The fixup needs to happen before cursor is enabled */
@@ -4272,6 +4249,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_disable_planes(crtc);
 	intel_disable_primary_plane(dev_priv, plane, pipe);
 
+	intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
 	intel_disable_pipe(dev_priv, pipe);
 
 	i9xx_pfit_disable(intel_crtc);
@@ -4583,7 +4561,7 @@ retry:
 static void hsw_compute_ips_config(struct intel_crtc *crtc,
 				   struct intel_crtc_config *pipe_config)
 {
-	pipe_config->ips_enabled = i915_enable_ips &&
+	pipe_config->ips_enabled = i915.enable_ips &&
 				   hsw_crtc_supports_ips(crtc) &&
 				   pipe_config->pipe_bpp <= 24;
 }
@@ -4784,8 +4762,8 @@ intel_link_compute_m_n(int bits_per_pixel, int nlanes,
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
-	if (i915_panel_use_ssc >= 0)
-		return i915_panel_use_ssc != 0;
+	if (i915.panel_use_ssc >= 0)
+		return i915.panel_use_ssc != 0;
 	return dev_priv->vbt.lvds_use_ssc
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
@@ -4844,7 +4822,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
 
 	crtc->lowfreq_avail = false;
 	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
-	    reduced_clock && i915_powersave) {
+	    reduced_clock && i915.powersave) {
 		I915_WRITE(FP1(pipe), fp2);
 		crtc->config.dpll_hw_state.fp1 = fp2;
 		crtc->lowfreq_avail = true;
@@ -5259,25 +5237,23 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
 	pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w;
 }
 
-static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
-					     struct intel_crtc_config *pipe_config)
+void intel_mode_from_pipe_config(struct drm_display_mode *mode,
+				 struct intel_crtc_config *pipe_config)
 {
-	struct drm_crtc *crtc = &intel_crtc->base;
+	mode->hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
+	mode->htotal = pipe_config->adjusted_mode.crtc_htotal;
+	mode->hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
+	mode->hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
 
-	crtc->mode.hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
-	crtc->mode.htotal = pipe_config->adjusted_mode.crtc_htotal;
-	crtc->mode.hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
-	crtc->mode.hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
+	mode->vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
+	mode->vtotal = pipe_config->adjusted_mode.crtc_vtotal;
+	mode->vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
+	mode->vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
 
-	crtc->mode.vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
-	crtc->mode.vtotal = pipe_config->adjusted_mode.crtc_vtotal;
-	crtc->mode.vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
-	crtc->mode.vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
+	mode->flags = pipe_config->adjusted_mode.flags;
 
-	crtc->mode.flags = pipe_config->adjusted_mode.flags;
-
-	crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock;
-	crtc->mode.flags |= pipe_config->adjusted_mode.flags;
+	mode->clock = pipe_config->adjusted_mode.crtc_clock;
+	mode->flags |= pipe_config->adjusted_mode.flags;
 }
 
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
@@ -6348,7 +6324,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (intel_crtc->config.has_dp_encoder)
 		intel_dp_set_m_n(intel_crtc);
 
-	if (is_lvds && has_reduced_clock && i915_powersave)
+	if (is_lvds && has_reduced_clock && i915.powersave)
 		intel_crtc->lowfreq_avail = true;
 	else
 		intel_crtc->lowfreq_avail = false;
@@ -6716,7 +6692,7 @@ static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
 		return;
 
 	schedule_delayed_work(&dev_priv->pc8.enable_work,
-			      msecs_to_jiffies(i915_pc8_timeout));
+			      msecs_to_jiffies(i915.pc8_timeout));
 }
 
 static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
@@ -6815,7 +6791,7 @@ static void hsw_update_package_c8(struct drm_device *dev)
 	if (!HAS_PC8(dev_priv->dev))
 		return;
 
-	if (!i915_enable_pc8)
+	if (!i915.enable_pc8)
 		return;
 
 	mutex_lock(&dev_priv->pc8.lock);
@@ -7573,18 +7549,18 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 		return -ENOENT;
 
 	if (obj->base.size < width * height * 4) {
-		DRM_ERROR("buffer is to small\n");
+		DRM_DEBUG_KMS("buffer is to small\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
 
 	/* we only need to pin inside GTT if cursor is non-phy */
 	mutex_lock(&dev->struct_mutex);
-	if (!dev_priv->info->cursor_needs_physical) {
+	if (!INTEL_INFO(dev)->cursor_needs_physical) {
 		unsigned alignment;
 
 		if (obj->tiling_mode) {
-			DRM_ERROR("cursor cannot be tiled\n");
+			DRM_DEBUG_KMS("cursor cannot be tiled\n");
 			ret = -EINVAL;
 			goto fail_locked;
 		}
@@ -7600,13 +7576,13 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
 		ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
 		if (ret) {
-			DRM_ERROR("failed to move cursor bo into the GTT\n");
+			DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
 			goto fail_locked;
 		}
 
 		ret = i915_gem_object_put_fence(obj);
 		if (ret) {
-			DRM_ERROR("failed to release fence for cursor");
+			DRM_DEBUG_KMS("failed to release fence for cursor");
 			goto fail_unpin;
 		}
 
@@ -7617,7 +7593,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 						  (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
 						  align);
 		if (ret) {
-			DRM_ERROR("failed to attach phys object\n");
+			DRM_DEBUG_KMS("failed to attach phys object\n");
 			goto fail_locked;
 		}
 		addr = obj->phys_obj->handle->busaddr;
@@ -7628,7 +7604,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
  finish:
 	if (intel_crtc->cursor_bo) {
-		if (dev_priv->info->cursor_needs_physical) {
+		if (INTEL_INFO(dev)->cursor_needs_physical) {
 			if (intel_crtc->cursor_bo != obj)
 				i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
 		} else
@@ -7690,10 +7666,10 @@ static struct drm_display_mode load_detect_mode = {
 		 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
 };
 
-static struct drm_framebuffer *
-intel_framebuffer_create(struct drm_device *dev,
-			 struct drm_mode_fb_cmd2 *mode_cmd,
-			 struct drm_i915_gem_object *obj)
+struct drm_framebuffer *
+__intel_framebuffer_create(struct drm_device *dev,
+			   struct drm_mode_fb_cmd2 *mode_cmd,
+			   struct drm_i915_gem_object *obj)
 {
 	struct intel_framebuffer *intel_fb;
 	int ret;
@@ -7704,12 +7680,7 @@ intel_framebuffer_create(struct drm_device *dev,
 		return ERR_PTR(-ENOMEM);
 	}
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		goto err;
-
 	ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
-	mutex_unlock(&dev->struct_mutex);
 	if (ret)
 		goto err;
 
@@ -7721,6 +7692,23 @@ err:
 	return ERR_PTR(ret);
 }
 
+static struct drm_framebuffer *
+intel_framebuffer_create(struct drm_device *dev,
+			 struct drm_mode_fb_cmd2 *mode_cmd,
+			 struct drm_i915_gem_object *obj)
+{
+	struct drm_framebuffer *fb;
+	int ret;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return ERR_PTR(ret);
+	fb = __intel_framebuffer_create(dev, mode_cmd, obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return fb;
+}
+
 static u32
 intel_framebuffer_pitch_for_width(int width, int bpp)
 {
@@ -7766,14 +7754,16 @@ mode_fits_in_fbdev(struct drm_device *dev,
 	struct drm_i915_gem_object *obj;
 	struct drm_framebuffer *fb;
 
-	if (dev_priv->fbdev == NULL)
+	if (!dev_priv->fbdev)
 		return NULL;
 
-	obj = dev_priv->fbdev->ifb.obj;
-	if (obj == NULL)
+	if (!dev_priv->fbdev->fb)
 		return NULL;
 
-	fb = &dev_priv->fbdev->ifb.base;
+	obj = dev_priv->fbdev->fb->obj;
+	BUG_ON(!obj);
+
+	fb = &dev_priv->fbdev->fb->base;
 	if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
 							       fb->bits_per_pixel))
 		return NULL;
@@ -7855,6 +7845,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	to_intel_connector(connector)->new_encoder = intel_encoder;
 
 	intel_crtc = to_intel_crtc(crtc);
+	intel_crtc->new_enabled = true;
+	intel_crtc->new_config = &intel_crtc->config;
 	old->dpms_mode = connector->dpms;
 	old->load_detect_temp = true;
 	old->release_fb = NULL;
@@ -7878,21 +7870,28 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
 	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-		mutex_unlock(&crtc->mutex);
-		return false;
+		goto fail;
 	}
 
 	if (intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
-		mutex_unlock(&crtc->mutex);
-		return false;
+		goto fail;
 	}
 
 	/* let the connector get through one full cycle before testing */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 	return true;
+
+ fail:
+	intel_crtc->new_enabled = crtc->enabled;
+	if (intel_crtc->new_enabled)
+		intel_crtc->new_config = &intel_crtc->config;
+	else
+		intel_crtc->new_config = NULL;
+	mutex_unlock(&crtc->mutex);
+	return false;
 }
 
 void intel_release_load_detect_pipe(struct drm_connector *connector,
@@ -7902,6 +7901,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
 		intel_attached_encoder(connector);
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector),
@@ -7910,6 +7910,8 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
 	if (old->load_detect_temp) {
 		to_intel_connector(connector)->new_encoder = NULL;
 		intel_encoder->new_crtc = NULL;
+		intel_crtc->new_enabled = false;
+		intel_crtc->new_config = NULL;
 		intel_set_mode(crtc, NULL, 0, 0, NULL);
 
 		if (old->release_fb) {
@@ -8201,7 +8203,7 @@ void intel_mark_idle(struct drm_device *dev)
 
 	hsw_package_c8_gpu_idle(dev_priv);
 
-	if (!i915_powersave)
+	if (!i915.powersave)
 		return;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -8211,7 +8213,7 @@ void intel_mark_idle(struct drm_device *dev)
 		intel_decrease_pllclock(crtc);
 	}
 
-	if (dev_priv->info->gen >= 6)
+	if (INTEL_INFO(dev)->gen >= 6)
 		gen6_rps_idle(dev->dev_private);
 }
 
@@ -8221,7 +8223,7 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
 	struct drm_device *dev = obj->base.dev;
 	struct drm_crtc *crtc;
 
-	if (!i915_powersave)
+	if (!i915.powersave)
 		return;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -8766,6 +8768,7 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
  */
 static void intel_modeset_update_staged_output_state(struct drm_device *dev)
 {
+	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 
@@ -8780,6 +8783,16 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
 		encoder->new_crtc =
 			to_intel_crtc(encoder->base.crtc);
 	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		crtc->new_enabled = crtc->base.enabled;
+
+		if (crtc->new_enabled)
+			crtc->new_config = &crtc->config;
+		else
+			crtc->new_config = NULL;
+	}
 }
 
 /**
@@ -8789,6 +8802,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
  */
 static void intel_modeset_commit_output_state(struct drm_device *dev)
 {
+	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 
@@ -8801,6 +8815,11 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 			    base.head) {
 		encoder->base.crtc = &encoder->new_crtc->base;
 	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		crtc->base.enabled = crtc->new_enabled;
+	}
 }
 
 static void
@@ -9127,29 +9146,22 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
 	}
 
-	/* Check for any pipes that will be fully disabled ... */
+	/* Check for pipes that will be enabled/disabled ... */
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		bool used = false;
-
-		/* Don't try to disable disabled crtcs. */
-		if (!intel_crtc->base.enabled)
+		if (intel_crtc->base.enabled == intel_crtc->new_enabled)
 			continue;
 
-		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
-				    base.head) {
-			if (encoder->new_crtc == intel_crtc)
-				used = true;
-		}
-
-		if (!used)
+		if (!intel_crtc->new_enabled)
 			*disable_pipes |= 1 << intel_crtc->pipe;
+		else
+			*prepare_pipes |= 1 << intel_crtc->pipe;
 	}
 
 
 	/* set_mode is also used to update properties on life display pipes. */
 	intel_crtc = to_intel_crtc(crtc);
-	if (crtc->enabled)
+	if (intel_crtc->new_enabled)
 		*prepare_pipes |= 1 << intel_crtc->pipe;
 
 	/*
@@ -9208,10 +9220,13 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 
 	intel_modeset_commit_output_state(dev);
 
-	/* Update computed state. */
+	/* Double check state. */
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
+		WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base));
+		WARN_ON(intel_crtc->new_config &&
+			intel_crtc->new_config != &intel_crtc->config);
+		WARN_ON(intel_crtc->base.enabled != !!intel_crtc->new_config);
 	}
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -9380,10 +9395,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
 		PIPE_CONF_CHECK_I(pipe_bpp);
 
-	if (!HAS_DDI(dev)) {
-		PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
-		PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
-	}
+	PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
+	PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
 
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
@@ -9643,6 +9656,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 		}
 		intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
 				       "[modeset]");
+		to_intel_crtc(crtc)->new_config = pipe_config;
 	}
 
 	/*
@@ -9653,8 +9667,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 	 * adjusted_mode bits in the crtc directly.
 	 */
 	if (IS_VALLEYVIEW(dev)) {
-		valleyview_modeset_global_pipes(dev, &prepare_pipes,
-						modeset_pipes, pipe_config);
+		valleyview_modeset_global_pipes(dev, &prepare_pipes);
 
 		/* may have added more to prepare_pipes than we should */
 		prepare_pipes &= ~disable_pipes;
@@ -9676,6 +9689,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 		/* mode_set/enable/disable functions rely on a correct pipe
 		 * config. */
 		to_intel_crtc(crtc)->config = *pipe_config;
+		to_intel_crtc(crtc)->new_config = &to_intel_crtc(crtc)->config;
 
 		/*
 		 * Calculate and store various constants which
@@ -9746,16 +9760,24 @@ static void intel_set_config_free(struct intel_set_config *config)
 
 	kfree(config->save_connector_encoders);
 	kfree(config->save_encoder_crtcs);
+	kfree(config->save_crtc_enabled);
 	kfree(config);
 }
 
 static int intel_set_config_save_state(struct drm_device *dev,
 				       struct intel_set_config *config)
 {
+	struct drm_crtc *crtc;
 	struct drm_encoder *encoder;
 	struct drm_connector *connector;
 	int count;
 
+	config->save_crtc_enabled =
+		kcalloc(dev->mode_config.num_crtc,
+			sizeof(bool), GFP_KERNEL);
+	if (!config->save_crtc_enabled)
+		return -ENOMEM;
+
 	config->save_encoder_crtcs =
 		kcalloc(dev->mode_config.num_encoder,
 			sizeof(struct drm_crtc *), GFP_KERNEL);
@@ -9773,6 +9795,11 @@ static int intel_set_config_save_state(struct drm_device *dev,
 	 * restored, not the drivers personal bookkeeping.
 	 */
 	count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		config->save_crtc_enabled[count++] = crtc->enabled;
+	}
+
+	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		config->save_encoder_crtcs[count++] = encoder->crtc;
 	}
@@ -9788,11 +9815,22 @@ static int intel_set_config_save_state(struct drm_device *dev,
 static void intel_set_config_restore_state(struct drm_device *dev,
 					   struct intel_set_config *config)
 {
+	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 	int count;
 
 	count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+		crtc->new_enabled = config->save_crtc_enabled[count++];
+
+		if (crtc->new_enabled)
+			crtc->new_config = &crtc->config;
+		else
+			crtc->new_config = NULL;
+	}
+
+	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->new_crtc =
 			to_intel_crtc(config->save_encoder_crtcs[count++]);
@@ -9840,7 +9878,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 			struct intel_crtc *intel_crtc =
 				to_intel_crtc(set->crtc);
 
-			if (intel_crtc->active && i915_fastboot) {
+			if (intel_crtc->active && i915.fastboot) {
 				DRM_DEBUG_KMS("crtc has no fb, will flip\n");
 				config->fb_changed = true;
 			} else {
@@ -9876,9 +9914,9 @@ intel_modeset_stage_output_state(struct drm_device *dev,
 				 struct drm_mode_set *set,
 				 struct intel_set_config *config)
 {
-	struct drm_crtc *new_crtc;
 	struct intel_connector *connector;
 	struct intel_encoder *encoder;
+	struct intel_crtc *crtc;
 	int ro;
 
 	/* The upper layers ensure that we either disable a crtc or have a list
@@ -9921,6 +9959,8 @@ intel_modeset_stage_output_state(struct drm_device *dev,
 	/* Update crtc of enabled connectors. */
 	list_for_each_entry(connector, &dev->mode_config.connector_list,
 			    base.head) {
+		struct drm_crtc *new_crtc;
+
 		if (!connector->new_encoder)
 			continue;
 
@@ -9971,9 +10011,58 @@ intel_modeset_stage_output_state(struct drm_device *dev,
 	}
 	/* Now we've also updated encoder->new_crtc for all encoders. */
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		crtc->new_enabled = false;
+
+		list_for_each_entry(encoder,
+				    &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->new_crtc == crtc) {
+				crtc->new_enabled = true;
+				break;
+			}
+		}
+
+		if (crtc->new_enabled != crtc->base.enabled) {
+			DRM_DEBUG_KMS("crtc %sabled, full mode switch\n",
+				      crtc->new_enabled ? "en" : "dis");
+			config->mode_changed = true;
+		}
+
+		if (crtc->new_enabled)
+			crtc->new_config = &crtc->config;
+		else
+			crtc->new_config = NULL;
+	}
+
 	return 0;
 }
 
+static void disable_crtc_nofb(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	DRM_DEBUG_KMS("Trying to restore without FB -> disabling pipe %c\n",
+		      pipe_name(crtc->pipe));
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+		if (connector->new_encoder &&
+		    connector->new_encoder->new_crtc == crtc)
+			connector->new_encoder = NULL;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		if (encoder->new_crtc == crtc)
+			encoder->new_crtc = NULL;
+	}
+
+	crtc->new_enabled = false;
+	crtc->new_config = NULL;
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
@@ -10040,7 +10129,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		 * flipping, so increasing its cost here shouldn't be a big
 		 * deal).
 		 */
-		if (i915_fastboot && ret == 0)
+		if (i915.fastboot && ret == 0)
 			intel_modeset_check_state(set->crtc->dev);
 	}
 
@@ -10050,6 +10139,15 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 fail:
 		intel_set_config_restore_state(dev, config);
 
+		/*
+		 * HACK: if the pipe was on, but we didn't have a framebuffer,
+		 * force the pipe off to avoid oopsing in the modeset code
+		 * due to fb==NULL. This should only happen during boot since
+		 * we don't yet reconstruct the FB from the hardware state.
+		 */
+		if (to_intel_crtc(save_set.crtc)->new_enabled && !save_set.fb)
+			disable_crtc_nofb(to_intel_crtc(save_set.crtc));
+
 		/* Try to restore the config */
 		if (config->mode_changed &&
 		    intel_set_mode(save_set.crtc, save_set.mode,
@@ -10279,8 +10377,7 @@ static bool has_edp_a(struct drm_device *dev)
 	if ((I915_READ(DP_A) & DP_DETECTED) == 0)
 		return false;
 
-	if (IS_GEN5(dev) &&
-	    (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+	if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
 		return false;
 
 	return true;
@@ -10433,18 +10530,13 @@ static void intel_setup_outputs(struct drm_device *dev)
 	drm_helper_move_panel_connectors_to_head(dev);
 }
 
-void intel_framebuffer_fini(struct intel_framebuffer *fb)
-{
-	drm_framebuffer_cleanup(&fb->base);
-	WARN_ON(!fb->obj->framebuffer_references--);
-	drm_gem_object_unreference_unlocked(&fb->obj->base);
-}
-
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
-	intel_framebuffer_fini(intel_fb);
+	drm_framebuffer_cleanup(fb);
+	WARN_ON(!intel_fb->obj->framebuffer_references--);
+	drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
 	kfree(intel_fb);
 }
 
@@ -10463,12 +10555,12 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
 	.create_handle = intel_user_framebuffer_create_handle,
 };
 
-int intel_framebuffer_init(struct drm_device *dev,
-			   struct intel_framebuffer *intel_fb,
-			   struct drm_mode_fb_cmd2 *mode_cmd,
-			   struct drm_i915_gem_object *obj)
+static int intel_framebuffer_init(struct drm_device *dev,
+				  struct intel_framebuffer *intel_fb,
+				  struct drm_mode_fb_cmd2 *mode_cmd,
+				  struct drm_i915_gem_object *obj)
 {
-	int aligned_height, tile_height;
+	int aligned_height;
 	int pitch_limit;
 	int ret;
 
@@ -10562,9 +10654,8 @@ int intel_framebuffer_init(struct drm_device *dev,
 	if (mode_cmd->offsets[0] != 0)
 		return -EINVAL;
 
-	tile_height = IS_GEN2(dev) ? 16 : 8;
-	aligned_height = ALIGN(mode_cmd->height,
-			       obj->tiling_mode ? tile_height : 1);
+	aligned_height = intel_align_height(dev, mode_cmd->height,
+					    obj->tiling_mode);
 	/* FIXME drm helper for size checks (especially planar formats)? */
 	if (obj->base.size < aligned_height * mode_cmd->pitches[0])
 		return -EINVAL;
@@ -10839,6 +10930,9 @@ static struct intel_quirk intel_quirks[] = {
 
 	/* Acer Aspire 4736Z */
 	{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
+
+	/* Acer Aspire 5336 */
+	{ 0x2a42, 0x1025, 0x048a, quirk_invert_brightness },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -10869,6 +10963,7 @@ static void i915_disable_vga(struct drm_device *dev)
 	u8 sr1;
 	u32 vga_reg = i915_vgacntrl_reg(dev);
 
+	/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
 	vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
 	outb(SR01, VGA_SR_INDEX);
 	sr1 = inb(VGA_SR_DATA);
@@ -10940,7 +11035,7 @@ void intel_modeset_init(struct drm_device *dev)
 
 	for_each_pipe(i) {
 		intel_crtc_init(dev, i);
-		for (j = 0; j < dev_priv->num_plane; j++) {
+		for (j = 0; j < INTEL_INFO(dev)->num_sprites; j++) {
 			ret = intel_plane_init(dev, i, j);
 			if (ret)
 				DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
@@ -10960,6 +11055,8 @@ void intel_modeset_init(struct drm_device *dev)
 
 	/* Just in case the BIOS is doing something questionable. */
 	intel_disable_fbc(dev);
+
+	intel_modeset_setup_hw_state(dev, false);
 }
 
 static void
@@ -11265,9 +11362,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 	 */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		if (crtc->active && i915_fastboot) {
-			intel_crtc_mode_from_pipe_config(crtc, &crtc->config);
-
+		if (crtc->active && i915.fastboot) {
+			intel_mode_from_pipe_config(&crtc->base.mode, &crtc->config);
 			DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
 				      crtc->base.base.id);
 			drm_mode_debug_printmodeline(&crtc->base.mode);
@@ -11327,11 +11423,14 @@ void intel_modeset_gem_init(struct drm_device *dev)
 	intel_modeset_init_hw(dev);
 
 	intel_setup_overlay(dev);
+}
 
-	mutex_lock(&dev->mode_config.mutex);
-	drm_mode_config_reset(dev);
-	intel_modeset_setup_hw_state(dev, false);
-	mutex_unlock(&dev->mode_config.mutex);
+void intel_connector_unregister(struct intel_connector *intel_connector)
+{
+	struct drm_connector *connector = &intel_connector->base;
+
+	intel_panel_destroy_backlight(connector);
+	drm_sysfs_connector_remove(connector);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11378,8 +11477,10 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
 	/* destroy the backlight and sysfs files before encoders/connectors */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		intel_panel_destroy_backlight(connector);
-		drm_sysfs_connector_remove(connector);
+		struct intel_connector *intel_connector;
+
+		intel_connector = to_intel_connector(connector);
+		intel_connector->unregister(intel_connector);
 	}
 
 	drm_mode_config_cleanup(dev);
@@ -11412,12 +11513,24 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 	unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
 	u16 gmch_ctrl;
 
-	pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
+	if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
+		DRM_ERROR("failed to read control word\n");
+		return -EIO;
+	}
+
+	if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !state)
+		return 0;
+
 	if (state)
 		gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
 	else
 		gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-	pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
+
+	if (pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl)) {
+		DRM_ERROR("failed to write control word\n");
+		return -EIO;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 57552eb386b0..c512d78af271 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -91,18 +91,25 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 }
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
+static void edp_panel_vdd_on(struct intel_dp *intel_dp);
+static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 
 static int
 intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
 	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
+	struct drm_device *dev = intel_dp->attached_connector->base.dev;
 
 	switch (max_link_bw) {
 	case DP_LINK_BW_1_62:
 	case DP_LINK_BW_2_7:
 		break;
 	case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */
-		max_link_bw = DP_LINK_BW_2_7;
+		if ((IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) &&
+		    intel_dp->dpcd[DP_DPCD_REV] >= 0x12)
+			max_link_bw = DP_LINK_BW_5_4;
+		else
+			max_link_bw = DP_LINK_BW_2_7;
 		break;
 	default:
 		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
@@ -294,7 +301,7 @@ static u32 _pp_stat_reg(struct intel_dp *intel_dp)
 		return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp));
 }
 
-static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
+static bool edp_have_panel_power(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -302,7 +309,7 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
 }
 
-static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
+static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -319,7 +326,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp))
 		return;
 
-	if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
+	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
 		WARN(1, "eDP powered off while attempting aux channel communication.\n");
 		DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
 			      I915_READ(_pp_stat_reg(intel_dp)),
@@ -351,31 +358,46 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 	return status;
 }
 
-static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp,
-				      int index)
+static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/* The clock divider is based off the hrawclk,
-	 * and would like to run at 2MHz. So, take the
-	 * hrawclk value and divide by 2 and use that
-	 *
-	 * Note that PCH attached eDP panels should use a 125MHz input
-	 * clock divider.
+	/*
+	 * The clock divider is based off the hrawclk, and would like to run at
+	 * 2MHz.  So, take the hrawclk value and divide by 2 and use that
 	 */
-	if (IS_VALLEYVIEW(dev)) {
-		return index ? 0 : 100;
-	} else if (intel_dig_port->port == PORT_A) {
-		if (index)
-			return 0;
-		if (HAS_DDI(dev))
-			return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000);
-		else if (IS_GEN6(dev) || IS_GEN7(dev))
+	return index ? 0 : intel_hrawclk(dev) / 2;
+}
+
+static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+
+	if (index)
+		return 0;
+
+	if (intel_dig_port->port == PORT_A) {
+		if (IS_GEN6(dev) || IS_GEN7(dev))
 			return 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			return 225; /* eDP input clock at 450Mhz */
+	} else {
+		return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
+	}
+}
+
+static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (intel_dig_port->port == PORT_A) {
+		if (index)
+			return 0;
+		return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000);
 	} else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 		/* Workaround for non-ULT HSW */
 		switch (index) {
@@ -383,13 +405,46 @@ static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp,
 		case 1: return 72;
 		default: return 0;
 		}
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else  {
 		return index ? 0 : DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
-	} else {
-		return index ? 0 :intel_hrawclk(dev) / 2;
 	}
 }
 
+static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	return index ? 0 : 100;
+}
+
+static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
+				      bool has_aux_irq,
+				      int send_bytes,
+				      uint32_t aux_clock_divider)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	uint32_t precharge, timeout;
+
+	if (IS_GEN6(dev))
+		precharge = 3;
+	else
+		precharge = 5;
+
+	if (IS_BROADWELL(dev) && intel_dp->aux_ch_ctl_reg == DPA_AUX_CH_CTL)
+		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
+	else
+		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
+
+	return DP_AUX_CH_CTL_SEND_BUSY |
+	       DP_AUX_CH_CTL_DONE |
+	       (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
+	       DP_AUX_CH_CTL_TIME_OUT_ERROR |
+	       timeout |
+	       DP_AUX_CH_CTL_RECEIVE_ERROR |
+	       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+	       (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *send, int send_bytes,
@@ -403,9 +458,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	uint32_t aux_clock_divider;
 	int i, ret, recv_bytes;
 	uint32_t status;
-	int try, precharge, clock = 0;
+	int try, clock = 0;
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
-	uint32_t timeout;
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
 	 * lowest possible wakeup latency and so prevent the cpu from going into
@@ -415,16 +469,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 
 	intel_dp_check_edp(intel_dp);
 
-	if (IS_GEN6(dev))
-		precharge = 3;
-	else
-		precharge = 5;
-
-	if (IS_BROADWELL(dev) && ch_ctl == DPA_AUX_CH_CTL)
-		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
-	else
-		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
-
 	intel_aux_display_runtime_get(dev_priv);
 
 	/* Try to wait for any previous AUX channel activity */
@@ -448,7 +492,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		goto out;
 	}
 
-	while ((aux_clock_divider = get_aux_clock_divider(intel_dp, clock++))) {
+	while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) {
+		u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
+							  has_aux_irq,
+							  send_bytes,
+							  aux_clock_divider);
+
 		/* Must try at least 3 times according to DP spec */
 		for (try = 0; try < 5; try++) {
 			/* Load the send data into the aux channel data registers */
@@ -457,16 +506,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 					   pack_aux(send + i, send_bytes - i));
 
 			/* Send the command and wait for it to complete */
-			I915_WRITE(ch_ctl,
-				   DP_AUX_CH_CTL_SEND_BUSY |
-				   (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
-				   timeout |
-				   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-				   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
-				   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
-				   DP_AUX_CH_CTL_DONE |
-				   DP_AUX_CH_CTL_TIME_OUT_ERROR |
-				   DP_AUX_CH_CTL_RECEIVE_ERROR);
+			I915_WRITE(ch_ctl, send_ctl);
 
 			status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);
 
@@ -637,7 +677,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	int reply_bytes;
 	int ret;
 
-	ironlake_edp_panel_vdd_on(intel_dp);
+	edp_panel_vdd_on(intel_dp);
 	intel_dp_check_edp(intel_dp);
 	/* Set up the command byte */
 	if (mode & MODE_I2C_READ)
@@ -740,10 +780,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	ret = -EREMOTEIO;
 
 out:
-	ironlake_edp_panel_vdd_off(intel_dp, false);
+	edp_panel_vdd_off(intel_dp, false);
 	return ret;
 }
 
+static void
+intel_dp_connector_unregister(struct intel_connector *intel_connector)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
+
+	sysfs_remove_link(&intel_connector->base.kdev->kobj,
+			  intel_dp->adapter.dev.kobj.name);
+	intel_connector_unregister(intel_connector);
+}
+
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
 		  struct intel_connector *intel_connector, const char *name)
@@ -761,9 +811,19 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 	strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
 	intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
 	intel_dp->adapter.algo_data = &intel_dp->algo;
-	intel_dp->adapter.dev.parent = intel_connector->base.kdev;
+	intel_dp->adapter.dev.parent = intel_connector->base.dev->dev;
 
 	ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+	if (ret < 0)
+		return ret;
+
+	ret = sysfs_create_link(&intel_connector->base.kdev->kobj,
+				&intel_dp->adapter.dev.kobj,
+				intel_dp->adapter.dev.kobj.name);
+
+	if (ret < 0)
+		i2c_del_adapter(&intel_dp->adapter);
+
 	return ret;
 }
 
@@ -812,9 +872,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	int lane_count, clock;
 	int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
-	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
+	/* Conveniently, the link BW constants become indices with a shift...*/
+	int max_clock = intel_dp_max_link_bw(intel_dp) >> 3;
 	int bpp, mode_rate;
-	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+	static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
 	int link_avail, link_clock;
 
 	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
@@ -1015,16 +1076,16 @@ static void intel_dp_mode_set(struct intel_encoder *encoder)
 		ironlake_set_pll_cpu_edp(intel_dp);
 }
 
-#define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
-#define IDLE_ON_VALUE   	(PP_ON | 0 	  | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
 
-#define IDLE_OFF_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
-#define IDLE_OFF_VALUE		(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
+#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
 
-#define IDLE_CYCLE_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
-#define IDLE_CYCLE_VALUE	(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
 
-static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
+static void wait_panel_status(struct intel_dp *intel_dp,
 				       u32 mask,
 				       u32 value)
 {
@@ -1049,24 +1110,41 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
 	DRM_DEBUG_KMS("Wait complete\n");
 }
 
-static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
+static void wait_panel_on(struct intel_dp *intel_dp)
 {
 	DRM_DEBUG_KMS("Wait for panel power on\n");
-	ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
 }
 
-static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+static void wait_panel_off(struct intel_dp *intel_dp)
 {
 	DRM_DEBUG_KMS("Wait for panel power off time\n");
-	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
 }
 
-static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
+static void wait_panel_power_cycle(struct intel_dp *intel_dp)
 {
 	DRM_DEBUG_KMS("Wait for panel power cycle\n");
-	ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+
+	/* When we disable the VDD override bit last we have to do the manual
+	 * wait. */
+	wait_remaining_ms_from_jiffies(intel_dp->last_power_cycle,
+				       intel_dp->panel_power_cycle_delay);
+
+	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
 }
 
+static void wait_backlight_on(struct intel_dp *intel_dp)
+{
+	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
+				       intel_dp->backlight_on_delay);
+}
+
+static void edp_wait_backlight_off(struct intel_dp *intel_dp)
+{
+	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
+				       intel_dp->backlight_off_delay);
+}
 
 /* Read the current pp_control value, unlocking the register if it
  * is locked
@@ -1084,7 +1162,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
-void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+static void edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1099,15 +1177,15 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 	intel_dp->want_panel_vdd = true;
 
-	if (ironlake_edp_have_panel_vdd(intel_dp))
+	if (edp_have_panel_vdd(intel_dp))
 		return;
 
 	intel_runtime_pm_get(dev_priv);
 
 	DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
-	if (!ironlake_edp_have_panel_power(intel_dp))
-		ironlake_wait_panel_power_cycle(intel_dp);
+	if (!edp_have_panel_power(intel_dp))
+		wait_panel_power_cycle(intel_dp);
 
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_FORCE_VDD;
@@ -1122,13 +1200,13 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 	/*
 	 * If the panel wasn't on, delay before accessing aux channel
 	 */
-	if (!ironlake_edp_have_panel_power(intel_dp)) {
+	if (!edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP was not running\n");
 		msleep(intel_dp->panel_power_up_delay);
 	}
 }
 
-static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
+static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1137,7 +1215,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 
 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
-	if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
+	if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
 		DRM_DEBUG_KMS("Turning eDP VDD off\n");
 
 		pp = ironlake_get_pp_control(intel_dp);
@@ -1154,24 +1232,24 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 
 		if ((pp & POWER_TARGET_ON) == 0)
-			msleep(intel_dp->panel_power_cycle_delay);
+			intel_dp->last_power_cycle = jiffies;
 
 		intel_runtime_pm_put(dev_priv);
 	}
 }
 
-static void ironlake_panel_vdd_work(struct work_struct *__work)
+static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	mutex_lock(&dev->mode_config.mutex);
-	ironlake_panel_vdd_off_sync(intel_dp);
+	edp_panel_vdd_off_sync(intel_dp);
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
-void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	if (!is_edp(intel_dp))
 		return;
@@ -1181,7 +1259,7 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 	intel_dp->want_panel_vdd = false;
 
 	if (sync) {
-		ironlake_panel_vdd_off_sync(intel_dp);
+		edp_panel_vdd_off_sync(intel_dp);
 	} else {
 		/*
 		 * Queue the timer to fire a long
@@ -1193,7 +1271,7 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 	}
 }
 
-void ironlake_edp_panel_on(struct intel_dp *intel_dp)
+void intel_edp_panel_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1205,12 +1283,12 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
-	if (ironlake_edp_have_panel_power(intel_dp)) {
+	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
 		return;
 	}
 
-	ironlake_wait_panel_power_cycle(intel_dp);
+	wait_panel_power_cycle(intel_dp);
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1228,7 +1306,8 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	ironlake_wait_panel_on(intel_dp);
+	wait_panel_on(intel_dp);
+	intel_dp->last_power_on = jiffies;
 
 	if (IS_GEN5(dev)) {
 		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
@@ -1237,7 +1316,7 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	}
 }
 
-void ironlake_edp_panel_off(struct intel_dp *intel_dp)
+void intel_edp_panel_off(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1249,6 +1328,8 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
+	edp_wait_backlight_off(intel_dp);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 	 * panels get very unhappy and cease to work. */
@@ -1259,10 +1340,11 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	ironlake_wait_panel_off(intel_dp);
+	intel_dp->last_power_cycle = jiffies;
+	wait_panel_off(intel_dp);
 }
 
-void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
+void intel_edp_backlight_on(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -1280,7 +1362,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	 * link.  So delay a bit to make sure the image is solid before
 	 * allowing it to appear.
 	 */
-	msleep(intel_dp->backlight_on_delay);
+	wait_backlight_on(intel_dp);
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
 
@@ -1292,7 +1374,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	intel_panel_enable_backlight(intel_dp->attached_connector);
 }
 
-void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
+void intel_edp_backlight_off(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1312,7 +1394,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-	msleep(intel_dp->backlight_off_delay);
+	intel_dp->last_backlight_off = jiffies;
 }
 
 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
@@ -1597,10 +1679,12 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp, 0);
+	uint32_t aux_clock_divider;
 	int precharge = 0x3;
 	int msg_size = 5;       /* Header(4) + Message(1) */
 
+	aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
+
 	/* Enable PSR in sink */
 	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
 		intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
@@ -1668,7 +1752,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 		return false;
 	}
 
-	if (!i915_enable_psr) {
+	if (!i915.enable_psr) {
 		DRM_DEBUG_KMS("PSR disable by flag\n");
 		return false;
 	}
@@ -1784,9 +1868,9 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
-	ironlake_edp_backlight_off(intel_dp);
+	intel_edp_backlight_off(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
-	ironlake_edp_panel_off(intel_dp);
+	intel_edp_panel_off(intel_dp);
 
 	/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
 	if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
@@ -1816,11 +1900,11 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	if (WARN_ON(dp_reg & DP_PORT_EN))
 		return;
 
-	ironlake_edp_panel_vdd_on(intel_dp);
+	edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
-	ironlake_edp_panel_on(intel_dp);
-	ironlake_edp_panel_vdd_off(intel_dp, true);
+	intel_edp_panel_on(intel_dp);
+	edp_panel_vdd_off(intel_dp, true);
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 }
@@ -1830,14 +1914,14 @@ static void g4x_enable_dp(struct intel_encoder *encoder)
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
 	intel_enable_dp(encoder);
-	ironlake_edp_backlight_on(intel_dp);
+	intel_edp_backlight_on(intel_dp);
 }
 
 static void vlv_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
-	ironlake_edp_backlight_on(intel_dp);
+	intel_edp_backlight_on(intel_dp);
 }
 
 static void g4x_pre_enable_dp(struct intel_encoder *encoder)
@@ -2630,10 +2714,15 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 	bool channel_eq = false;
 	int tries, cr_tries;
 	uint32_t DP = intel_dp->DP;
+	uint32_t training_pattern = DP_TRAINING_PATTERN_2;
+
+	/* Training Pattern 3 for HBR2 ot 1.2 devices that support it*/
+	if (intel_dp->link_bw == DP_LINK_BW_5_4 || intel_dp->use_tps3)
+		training_pattern = DP_TRAINING_PATTERN_3;
 
 	/* channel equalization */
 	if (!intel_dp_set_link_train(intel_dp, &DP,
-				     DP_TRAINING_PATTERN_2 |
+				     training_pattern |
 				     DP_LINK_SCRAMBLING_DISABLE)) {
 		DRM_ERROR("failed to start channel equalization\n");
 		return;
@@ -2660,7 +2749,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 		if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			intel_dp_start_link_train(intel_dp);
 			intel_dp_set_link_train(intel_dp, &DP,
-						DP_TRAINING_PATTERN_2 |
+						training_pattern |
 						DP_LINK_SCRAMBLING_DISABLE);
 			cr_tries++;
 			continue;
@@ -2676,7 +2765,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			intel_dp_link_down(intel_dp);
 			intel_dp_start_link_train(intel_dp);
 			intel_dp_set_link_train(intel_dp, &DP,
-						DP_TRAINING_PATTERN_2 |
+						training_pattern |
 						DP_LINK_SCRAMBLING_DISABLE);
 			tries = 0;
 			cr_tries++;
@@ -2818,6 +2907,14 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 		}
 	}
 
+	/* Training Pattern 3 support */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 &&
+	    intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) {
+		intel_dp->use_tps3 = true;
+		DRM_DEBUG_KMS("Displayport TPS3 supported");
+	} else
+		intel_dp->use_tps3 = false;
+
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
@@ -2841,7 +2938,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 	if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
 		return;
 
-	ironlake_edp_panel_vdd_on(intel_dp);
+	edp_panel_vdd_on(intel_dp);
 
 	if (intel_dp_aux_native_read_retry(intel_dp, DP_SINK_OUI, buf, 3))
 		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
@@ -2851,7 +2948,36 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	ironlake_edp_panel_vdd_off(intel_dp, false);
+	edp_panel_vdd_off(intel_dp, false);
+}
+
+int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(intel_dig_port->base.base.crtc);
+	u8 buf[1];
+
+	if (!intel_dp_aux_native_read(intel_dp, DP_TEST_SINK_MISC, buf, 1))
+		return -EAGAIN;
+
+	if (!(buf[0] & DP_TEST_CRC_SUPPORTED))
+		return -ENOTTY;
+
+	if (!intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK,
+					 DP_TEST_SINK_START))
+		return -EAGAIN;
+
+	/* Wait 2 vblanks to be sure we will have the correct CRC value */
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+	if (!intel_dp_aux_native_read(intel_dp, DP_TEST_CRC_R_CR, crc, 6))
+		return -EAGAIN;
+
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK, 0);
+	return 0;
 }
 
 static bool
@@ -3295,7 +3421,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 		mutex_lock(&dev->mode_config.mutex);
-		ironlake_panel_vdd_off_sync(intel_dp);
+		edp_panel_vdd_off_sync(intel_dp);
 		mutex_unlock(&dev->mode_config.mutex);
 	}
 	kfree(intel_dig_port);
@@ -3394,6 +3520,13 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 	}
 }
 
+static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
+{
+	intel_dp->last_power_cycle = jiffies;
+	intel_dp->last_power_on = jiffies;
+	intel_dp->last_backlight_off = jiffies;
+}
+
 static void
 intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 				    struct intel_dp *intel_dp,
@@ -3516,10 +3649,17 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 		pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
 	}
 
-	/* And finally store the new values in the power sequencer. */
+	/*
+	 * And finally store the new values in the power sequencer. The
+	 * backlight delays are set to 1 because we do manual waits on them. For
+	 * T8, even BSpec recommends doing it. For T9, if we don't do this,
+	 * we'll end up waiting for the backlight off delay twice: once when we
+	 * do the manual sleep, and once when we disable the panel and wait for
+	 * the PP_STATUS bit to become zero.
+	 */
 	pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
-		(seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
-	pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+		(1 << PANEL_LIGHT_ON_DELAY_SHIFT);
+	pp_off = (1 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
 		 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
 	/* Compute the divisor for the pp clock, simply match the Bspec
 	 * formula. */
@@ -3554,14 +3694,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
-				     struct intel_connector *intel_connector)
+				     struct intel_connector *intel_connector,
+				     struct edp_power_seq *power_seq)
 {
 	struct drm_connector *connector = &intel_connector->base;
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(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 edp_power_seq power_seq = { 0 };
 	bool has_dpcd;
 	struct drm_display_mode *scan;
 	struct edid *edid;
@@ -3569,12 +3709,10 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	if (!is_edp(intel_dp))
 		return true;
 
-	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-
 	/* Cache DPCD and EDID for edp. */
-	ironlake_edp_panel_vdd_on(intel_dp);
+	edp_panel_vdd_on(intel_dp);
 	has_dpcd = intel_dp_get_dpcd(intel_dp);
-	ironlake_edp_panel_vdd_off(intel_dp, false);
+	edp_panel_vdd_off(intel_dp, false);
 
 	if (has_dpcd) {
 		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
@@ -3588,8 +3726,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-						      &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
 
 	edid = drm_get_edid(connector, &intel_dp->adapter);
 	if (edid) {
@@ -3622,7 +3759,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 	}
 
-	intel_panel_init(&intel_connector->panel, fixed_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 	intel_panel_setup_backlight(connector);
 
 	return true;
@@ -3638,9 +3775,22 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
+	struct edp_power_seq power_seq = { 0 };
 	const char *name = NULL;
 	int type, error;
 
+	/* intel_dp vfuncs */
+	if (IS_VALLEYVIEW(dev))
+		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
+	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
+	else if (HAS_PCH_SPLIT(dev))
+		intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
+	else
+		intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider;
+
+	intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
+
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
 	intel_dp->attached_connector = intel_connector;
@@ -3669,7 +3819,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	connector->doublescan_allowed = 0;
 
 	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-			  ironlake_panel_vdd_work);
+			  edp_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
@@ -3678,6 +3828,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_dp_connector_unregister;
 
 	intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
 	if (HAS_DDI(dev)) {
@@ -3721,18 +3872,23 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		BUG();
 	}
 
+	if (is_edp(intel_dp)) {
+		intel_dp_init_panel_power_timestamps(intel_dp);
+		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	}
+
 	error = intel_dp_i2c_init(intel_dp, intel_connector, name);
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
 	intel_dp->psr_setup_done = false;
 
-	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 			mutex_lock(&dev->mode_config.mutex);
-			ironlake_panel_vdd_off_sync(intel_dp);
+			edp_panel_vdd_off_sync(intel_dp);
 			mutex_unlock(&dev->mode_config.mutex);
 		}
 		drm_sysfs_connector_remove(connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fbfaaba5cc3b..a4ffc021c317 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -110,7 +110,7 @@ struct intel_framebuffer {
 
 struct intel_fbdev {
 	struct drm_fb_helper helper;
-	struct intel_framebuffer ifb;
+	struct intel_framebuffer *fb;
 	struct list_head fbdev_list;
 	struct drm_display_mode *our_mode;
 };
@@ -187,6 +187,14 @@ struct intel_connector {
 	 * and active (i.e. dpms ON state). */
 	bool (*get_hw_state)(struct intel_connector *);
 
+	/*
+	 * Removes all interfaces through which the connector is accessible
+	 * - like sysfs, debugfs entries -, so that no new operations can be
+	 * started on the connector. Also makes sure all currently pending
+	 * operations finish before returing.
+	 */
+	void (*unregister)(struct intel_connector *);
+
 	/* Panel info for eDP and LVDS */
 	struct intel_panel panel;
 
@@ -359,6 +367,8 @@ struct intel_crtc {
 	bool cursor_visible;
 
 	struct intel_crtc_config config;
+	struct intel_crtc_config *new_config;
+	bool new_enabled;
 
 	uint32_t ddi_pll_sel;
 
@@ -485,8 +495,22 @@ struct intel_dp {
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
+	unsigned long last_power_cycle;
+	unsigned long last_power_on;
+	unsigned long last_backlight_off;
 	bool psr_setup_done;
+	bool use_tps3;
 	struct intel_connector *attached_connector;
+
+	uint32_t (*get_aux_clock_divider)(struct intel_dp *dp, int index);
+	/*
+	 * This function returns the value we have to program the AUX_CTL
+	 * register with to kick off an AUX transaction.
+	 */
+	uint32_t (*get_aux_send_ctl)(struct intel_dp *dp,
+				     bool has_aux_irq,
+				     int send_bytes,
+				     uint32_t aux_clock_divider);
 };
 
 struct intel_digital_port {
@@ -540,6 +564,7 @@ struct intel_unpin_work {
 struct intel_set_config {
 	struct drm_encoder **save_connector_encoders;
 	struct drm_crtc **save_encoder_crtcs;
+	bool *save_crtc_enabled;
 
 	bool fb_changed;
 	bool mode_changed;
@@ -664,11 +689,10 @@ int intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			       struct drm_i915_gem_object *obj,
 			       struct intel_ring_buffer *pipelined);
 void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
-int intel_framebuffer_init(struct drm_device *dev,
-			   struct intel_framebuffer *ifb,
+struct drm_framebuffer *
+__intel_framebuffer_create(struct drm_device *dev,
 			   struct drm_mode_fb_cmd2 *mode_cmd,
 			   struct drm_i915_gem_object *obj);
-void intel_framebuffer_fini(struct intel_framebuffer *fb);
 void intel_prepare_page_flip(struct drm_device *dev, int plane);
 void intel_finish_page_flip(struct drm_device *dev, int pipe);
 void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
@@ -710,6 +734,8 @@ void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
+void intel_mode_from_pipe_config(struct drm_display_mode *mode,
+				 struct intel_crtc_config *pipe_config);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
@@ -721,15 +747,14 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 void intel_dp_check_link_status(struct intel_dp *intel_dp);
+int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc);
 bool intel_dp_compute_config(struct intel_encoder *encoder,
 			     struct intel_crtc_config *pipe_config);
 bool intel_dp_is_edp(struct drm_device *dev, enum port port);
-void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
-void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
-void ironlake_edp_panel_on(struct intel_dp *intel_dp);
-void ironlake_edp_panel_off(struct intel_dp *intel_dp);
-void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
-void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+void intel_edp_backlight_on(struct intel_dp *intel_dp);
+void intel_edp_backlight_off(struct intel_dp *intel_dp);
+void intel_edp_panel_on(struct intel_dp *intel_dp);
+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);
@@ -808,7 +833,8 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
 
 /* intel_panel.c */
 int intel_panel_init(struct intel_panel *panel,
-		     struct drm_display_mode *fixed_mode);
+		     struct drm_display_mode *fixed_mode,
+		     struct drm_display_mode *downclock_mode);
 void intel_panel_fini(struct intel_panel *panel);
 void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
 			    struct drm_display_mode *adjusted_mode);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index fabbf0d895cf..3ee1db1407b0 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -586,6 +586,7 @@ bool intel_dsi_init(struct drm_device *dev)
 	intel_encoder->get_config = intel_dsi_get_config;
 
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) {
 		dsi = &intel_dsi_devices[i];
@@ -624,7 +625,7 @@ bool intel_dsi_init(struct drm_device *dev)
 	}
 
 	fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
-	intel_panel_init(&intel_connector->panel, fixed_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 
 	return true;
 
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index eeff998e52ef..86eeb8b7d435 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -477,6 +477,7 @@ void intel_dvo_init(struct drm_device *dev)
 	intel_encoder->compute_config = intel_dvo_compute_config;
 	intel_encoder->mode_set = intel_dvo_mode_set;
 	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	/* Now, try to find a controller */
 	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 39eac9937a4a..19be4bfbcc59 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -62,6 +62,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
 {
 	struct intel_fbdev *ifbdev =
 		container_of(helper, struct intel_fbdev, helper);
+	struct drm_framebuffer *fb;
 	struct drm_device *dev = helper->dev;
 	struct drm_mode_fb_cmd2 mode_cmd = {};
 	struct drm_i915_gem_object *obj;
@@ -93,18 +94,22 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
 	/* Flush everything out, we'll be doing GTT only from now on */
 	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
 	if (ret) {
-		DRM_ERROR("failed to pin fb: %d\n", ret);
+		DRM_ERROR("failed to pin obj: %d\n", ret);
 		goto out_unref;
 	}
 
-	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
-	if (ret)
+	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
+	if (IS_ERR(fb)) {
+		ret = PTR_ERR(fb);
 		goto out_unpin;
+	}
+
+	ifbdev->fb = to_intel_framebuffer(fb);
 
 	return 0;
 
 out_unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 out_unref:
 	drm_gem_object_unreference(&obj->base);
 out:
@@ -116,7 +121,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 {
 	struct intel_fbdev *ifbdev =
 		container_of(helper, struct intel_fbdev, helper);
-	struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+	struct intel_framebuffer *intel_fb = ifbdev->fb;
 	struct drm_device *dev = helper->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
@@ -126,11 +131,12 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
 	mutex_lock(&dev->struct_mutex);
 
-	if (!intel_fb->obj) {
+	if (!intel_fb || WARN_ON(!intel_fb->obj)) {
 		DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
 		ret = intelfb_alloc(helper, sizes);
 		if (ret)
 			goto out_unlock;
+		intel_fb = ifbdev->fb;
 	} else {
 		DRM_DEBUG_KMS("re-using BIOS fb\n");
 		sizes->fb_width = intel_fb->base.width;
@@ -148,7 +154,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
 	info->par = helper;
 
-	fb = &ifbdev->ifb.base;
+	fb = &ifbdev->fb->base;
 
 	ifbdev->helper.fb = fb;
 	ifbdev->helper.fbdev = info;
@@ -194,7 +200,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	 * If the object is stolen however, it will be full of whatever
 	 * garbage was left in there.
 	 */
-	if (ifbdev->ifb.obj->stolen)
+	if (ifbdev->fb->obj->stolen)
 		memset_io(info->screen_base, 0, info->screen_size);
 
 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@@ -208,7 +214,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	return 0;
 
 out_unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
@@ -236,7 +242,152 @@ static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 	*blue = intel_crtc->lut_b[regno] << 8;
 }
 
+static struct drm_fb_helper_crtc *
+intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
+{
+	int i;
+
+	for (i = 0; i < fb_helper->crtc_count; i++)
+		if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
+			return &fb_helper->crtc_info[i];
+
+	return NULL;
+}
+
+/*
+ * Try to read the BIOS display configuration and use it for the initial
+ * fb configuration.
+ *
+ * The BIOS or boot loader will generally create an initial display
+ * configuration for us that includes some set of active pipes and displays.
+ * This routine tries to figure out which pipes and connectors are active
+ * and stuffs them into the crtcs and modes array given to us by the
+ * drm_fb_helper code.
+ *
+ * The overall sequence is:
+ *   intel_fbdev_init - from driver load
+ *     intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data
+ *     drm_fb_helper_init - build fb helper structs
+ *     drm_fb_helper_single_add_all_connectors - more fb helper structs
+ *   intel_fbdev_initial_config - apply the config
+ *     drm_fb_helper_initial_config - call ->probe then register_framebuffer()
+ *         drm_setup_crtcs - build crtc config for fbdev
+ *           intel_fb_initial_config - find active connectors etc
+ *         drm_fb_helper_single_fb_probe - set up fbdev
+ *           intelfb_create - re-use or alloc fb, build out fbdev structs
+ *
+ * Note that we don't make special consideration whether we could actually
+ * switch to the selected modes without a full modeset. E.g. when the display
+ * is in VGA mode we need to recalculate watermarks and set a new high-res
+ * framebuffer anyway.
+ */
+static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
+				    struct drm_fb_helper_crtc **crtcs,
+				    struct drm_display_mode **modes,
+				    bool *enabled, int width, int height)
+{
+	struct drm_device *dev = fb_helper->dev;
+	int i, j;
+	bool *save_enabled;
+	bool any_enabled = false;
+
+	save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
+			       GFP_KERNEL);
+	if (!save_enabled)
+		return false;
+
+	memcpy(save_enabled, enabled, dev->mode_config.num_connector);
+
+	for (i = 0; i < fb_helper->connector_count; i++) {
+		struct drm_fb_helper_connector *fb_conn;
+		struct drm_connector *connector;
+		struct drm_encoder *encoder;
+		struct drm_fb_helper_crtc *new_crtc;
+
+		fb_conn = fb_helper->connector_info[i];
+		connector = fb_conn->connector;
+		if (!enabled[i]) {
+			DRM_DEBUG_KMS("connector %d not enabled, skipping\n",
+				      connector->base.id);
+			continue;
+		}
+
+		encoder = connector->encoder;
+		if (!encoder || WARN_ON(!encoder->crtc)) {
+			DRM_DEBUG_KMS("connector %d has no encoder or crtc, skipping\n",
+				      connector->base.id);
+			enabled[i] = false;
+			continue;
+		}
+
+		new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc);
+
+		/*
+		 * Make sure we're not trying to drive multiple connectors
+		 * with a single CRTC, since our cloning support may not
+		 * match the BIOS.
+		 */
+		for (j = 0; j < fb_helper->connector_count; j++) {
+			if (crtcs[j] == new_crtc) {
+				any_enabled = false;
+				goto out;
+			}
+		}
+
+		DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
+			      fb_conn->connector->base.id);
+
+		/* go for command line mode first */
+		modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);
+
+		/* try for preferred next */
+		if (!modes[i]) {
+			DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
+				      fb_conn->connector->base.id);
+			modes[i] = drm_has_preferred_mode(fb_conn, width,
+							  height);
+		}
+
+		/* last resort: use current mode */
+		if (!modes[i]) {
+			/*
+			 * IMPORTANT: We want to use the adjusted mode (i.e.
+			 * after the panel fitter upscaling) as the initial
+			 * config, not the input mode, which is what crtc->mode
+			 * usually contains. But since our current fastboot
+			 * code puts a mode derived from the post-pfit timings
+			 * into crtc->mode this works out correctly. We don't
+			 * use hwmode anywhere right now, so use it for this
+			 * since the fb helper layer wants a pointer to
+			 * something we own.
+			 */
+			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
+						    &to_intel_crtc(encoder->crtc)->config);
+			modes[i] = &encoder->crtc->hwmode;
+		}
+		crtcs[i] = new_crtc;
+
+		DRM_DEBUG_KMS("connector %s on crtc %d: %s\n",
+			      drm_get_connector_name(connector),
+			      encoder->crtc->base.id,
+			      modes[i]->name);
+
+		any_enabled = true;
+	}
+
+out:
+	if (!any_enabled) {
+		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
+		kfree(save_enabled);
+		return false;
+	}
+
+	kfree(save_enabled);
+	return true;
+}
+
 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+	.initial_config = intel_fb_initial_config,
 	.gamma_set = intel_crtc_fb_gamma_set,
 	.gamma_get = intel_crtc_fb_gamma_get,
 	.fb_probe = intelfb_create,
@@ -258,8 +409,8 @@ static void intel_fbdev_destroy(struct drm_device *dev,
 
 	drm_fb_helper_fini(&ifbdev->helper);
 
-	drm_framebuffer_unregister_private(&ifbdev->ifb.base);
-	intel_framebuffer_fini(&ifbdev->ifb);
+	drm_framebuffer_unregister_private(&ifbdev->fb->base);
+	drm_framebuffer_remove(&ifbdev->fb->base);
 }
 
 int intel_fbdev_init(struct drm_device *dev)
@@ -322,7 +473,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
 	 * been restored from swap. If the object is stolen however, it will be
 	 * full of whatever garbage was left in there.
 	 */
-	if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen)
+	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
 		memset_io(info->screen_base, 0, info->screen_size);
 
 	fb_set_suspend(info, state);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 6db0d9d17f47..aa4641d1898e 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -113,7 +113,8 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
 }
 
 static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
-				  enum transcoder cpu_transcoder)
+				  enum transcoder cpu_transcoder,
+				  struct drm_i915_private *dev_priv)
 {
 	switch (type) {
 	case HDMI_INFOFRAME_TYPE_AVI:
@@ -296,7 +297,8 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
 	u32 val = I915_READ(ctl_reg);
 
 	data_reg = hsw_infoframe_data_reg(type,
-					  intel_crtc->config.cpu_transcoder);
+					  intel_crtc->config.cpu_transcoder,
+					  dev_priv);
 	if (data_reg == 0)
 		return;
 
@@ -423,7 +425,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
 	u32 reg = VIDEO_DIP_CTL;
 	u32 val = I915_READ(reg);
-	u32 port;
+	u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
 
 	assert_hdmi_port_disabled(intel_hdmi);
 
@@ -447,18 +449,6 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
 		return;
 	}
 
-	switch (intel_dig_port->port) {
-	case PORT_B:
-		port = VIDEO_DIP_PORT_B;
-		break;
-	case PORT_C:
-		port = VIDEO_DIP_PORT_C;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
 	if (port != (val & VIDEO_DIP_PORT_MASK)) {
 		if (val & VIDEO_DIP_ENABLE) {
 			val &= ~VIDEO_DIP_ENABLE;
@@ -489,7 +479,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
 	u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
 	u32 val = I915_READ(reg);
-	u32 port;
+	u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
 
 	assert_hdmi_port_disabled(intel_hdmi);
 
@@ -505,21 +495,6 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 		return;
 	}
 
-	switch (intel_dig_port->port) {
-	case PORT_B:
-		port = VIDEO_DIP_PORT_B;
-		break;
-	case PORT_C:
-		port = VIDEO_DIP_PORT_C;
-		break;
-	case PORT_D:
-		port = VIDEO_DIP_PORT_D;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
 	if (port != (val & VIDEO_DIP_PORT_MASK)) {
 		if (val & VIDEO_DIP_ENABLE) {
 			val &= ~VIDEO_DIP_ENABLE;
@@ -845,7 +820,7 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
 {
 	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
 
-	if (IS_G4X(dev))
+	if (!hdmi->has_hdmi_sink || IS_G4X(dev))
 		return 165000;
 	else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
 		return 300000;
@@ -899,8 +874,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	 * outputs. We also need to check that the higher clock still fits
 	 * within limits.
 	 */
-	if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit
-	    && HAS_PCH_SPLIT(dev)) {
+	if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink &&
+	    clock_12bpc <= portclock_limit && HAS_PCH_SPLIT(dev)) {
 		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
 		desired_bpp = 12*3;
 
@@ -1261,6 +1236,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 8bcb93a2a9f6..fecff3c2b9e1 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -848,8 +848,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* use the module option value if specified */
-	if (i915_lvds_channel_mode > 0)
-		return i915_lvds_channel_mode == 2;
+	if (i915.lvds_channel_mode > 0)
+		return i915.lvds_channel_mode == 2;
 
 	if (dmi_check_system(intel_dual_link_lvds))
 		return true;
@@ -899,6 +899,7 @@ void intel_lvds_init(struct drm_device *dev)
 	struct drm_encoder *encoder;
 	struct drm_display_mode *scan; /* *modes, *bios_mode; */
 	struct drm_display_mode *fixed_mode = NULL;
+	struct drm_display_mode *downclock_mode = NULL;
 	struct edid *edid;
 	struct drm_crtc *crtc;
 	u32 lvds;
@@ -957,6 +958,7 @@ void intel_lvds_init(struct drm_device *dev)
 	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
 	intel_encoder->get_config = intel_lvds_get_config;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
@@ -1032,15 +1034,14 @@ void intel_lvds_init(struct drm_device *dev)
 
 			fixed_mode = drm_mode_duplicate(dev, scan);
 			if (fixed_mode) {
-				intel_connector->panel.downclock_mode =
+				downclock_mode =
 					intel_find_panel_downclock(dev,
 					fixed_mode, connector);
-				if (intel_connector->panel.downclock_mode !=
-					NULL &&	i915_lvds_downclock) {
+				if (downclock_mode != NULL &&
+					i915.lvds_downclock) {
 					/* We found the downclock for LVDS. */
 					dev_priv->lvds_downclock_avail = true;
 					dev_priv->lvds_downclock =
-						intel_connector->panel.
 						downclock_mode->clock;
 					DRM_DEBUG_KMS("LVDS downclock is found"
 					" in EDID. Normal clock %dKhz, "
@@ -1116,7 +1117,7 @@ out:
 	}
 	drm_sysfs_connector_add(connector);
 
-	intel_panel_init(&intel_connector->panel, fixed_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
 	intel_panel_setup_backlight(connector);
 
 	return;
@@ -1125,8 +1126,6 @@ failed:
 	DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
 	drm_connector_cleanup(connector);
 	drm_encoder_cleanup(encoder);
-	if (fixed_mode)
-		drm_mode_destroy(dev, fixed_mode);
 	kfree(lvds_encoder);
 	kfree(lvds_connector);
 	return;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index a759ecdb7a6e..312961a8472e 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -293,7 +293,7 @@ static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
 {
 	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
 
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
 
 	overlay->old_vid_bo = NULL;
@@ -306,7 +306,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
 	/* never have the overlay hw on without showing a frame */
 	BUG_ON(!overlay->vid_bo);
 
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
 	overlay->vid_bo = NULL;
 
@@ -782,7 +782,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	return 0;
 
 out_unpin:
-	i915_gem_object_unpin(new_bo);
+	i915_gem_object_ggtt_unpin(new_bo);
 	return ret;
 }
 
@@ -1076,7 +1076,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 	mutex_lock(&dev->struct_mutex);
 
 	if (new_bo->tiling_mode) {
-		DRM_ERROR("buffer used for overlay image can not be tiled\n");
+		DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
 		ret = -EINVAL;
 		goto out_unlock;
 	}
@@ -1349,7 +1349,7 @@ void intel_setup_overlay(struct drm_device *dev)
 		}
 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
-		ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, true, false);
+		ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
 		if (ret) {
 			DRM_ERROR("failed to pin overlay register bo\n");
 			goto out_free_bo;
@@ -1386,7 +1386,7 @@ void intel_setup_overlay(struct drm_device *dev)
 
 out_unpin_bo:
 	if (!OVERLAY_NEEDS_PHYSICAL(dev))
-		i915_gem_object_unpin(reg_bo);
+		i915_gem_object_ggtt_unpin(reg_bo);
 out_free_bo:
 	drm_gem_object_unreference(&reg_bo->base);
 out_free:
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 350de359123a..cb058408c70e 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -33,8 +33,6 @@
 #include <linux/moduleparam.h>
 #include "intel_drv.h"
 
-#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
-
 void
 intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
 		       struct drm_display_mode *adjusted_mode)
@@ -325,13 +323,6 @@ out:
 	pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
-static int i915_panel_invert_brightness;
-MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
-	"(-1 force normal, 0 machine defaults, 1 force inversion), please "
-	"report PCI device ID, subsystem vendor and subsystem device ID "
-	"to dri-devel@lists.freedesktop.org, if your machine needs it. "
-	"It will then be included in an upcoming module version.");
-module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 					  u32 val)
 {
@@ -341,10 +332,10 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 
 	WARN_ON(panel->backlight.max == 0);
 
-	if (i915_panel_invert_brightness < 0)
+	if (i915.invert_brightness < 0)
 		return val;
 
-	if (i915_panel_invert_brightness > 0 ||
+	if (i915.invert_brightness > 0 ||
 	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
 		return panel->backlight.max - val;
 	}
@@ -698,7 +689,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
 		freq /= 0xff;
 
 	ctl = freq << 17;
-	if (IS_GEN2(dev) && panel->backlight.combination_mode)
+	if (panel->backlight.combination_mode)
 		ctl |= BLM_LEGACY_MODE;
 	if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
 		ctl |= BLM_POLARITY_PNV;
@@ -810,13 +801,13 @@ intel_panel_detect(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* Assume that the BIOS does not lie through the OpRegion... */
-	if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
+	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
 		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
 			connector_status_connected :
 			connector_status_disconnected;
 	}
 
-	switch (i915_panel_ignore_lid) {
+	switch (i915.panel_ignore_lid) {
 	case -2:
 		return connector_status_connected;
 	case -1:
@@ -979,7 +970,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
 
 	ctl = I915_READ(BLC_PWM_CTL);
 
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
 		panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
 
 	if (IS_PINEVIEW(dev))
@@ -1199,9 +1190,11 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
 }
 
 int intel_panel_init(struct intel_panel *panel,
-		     struct drm_display_mode *fixed_mode)
+		     struct drm_display_mode *fixed_mode,
+		     struct drm_display_mode *downclock_mode)
 {
 	panel->fixed_mode = fixed_mode;
+	panel->downclock_mode = downclock_mode;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d77cc81900f9..c8347ae2ffa2 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -97,7 +97,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int cfb_pitch;
-	int plane, i;
+	int i;
 	u32 fbc_ctl;
 
 	cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
@@ -109,7 +109,6 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
 		cfb_pitch = (cfb_pitch / 32) - 1;
 	else
 		cfb_pitch = (cfb_pitch / 64) - 1;
-	plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
 	/* Clear old tags */
 	for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
@@ -120,7 +119,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
 
 		/* Set it up... */
 		fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
-		fbc_ctl2 |= plane;
+		fbc_ctl2 |= FBC_CTL_PLANE(intel_crtc->plane);
 		I915_WRITE(FBC_CONTROL2, fbc_ctl2);
 		I915_WRITE(FBC_FENCE_OFF, crtc->y);
 	}
@@ -135,7 +134,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
 	fbc_ctl |= obj->fence_reg;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
-	DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c, ",
+	DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n",
 		      cfb_pitch, crtc->y, plane_name(intel_crtc->plane));
 }
 
@@ -154,17 +153,19 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
 	u32 dpfc_ctl;
 
-	dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
+	dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane) | DPFC_SR_EN;
+	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
+	else
+		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
 	dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
-	I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 
 	I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
 
 	/* enable it... */
-	I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
+	I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
 	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
 }
@@ -224,18 +225,16 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
 	u32 dpfc_ctl;
 
-	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
-	dpfc_ctl &= DPFC_RESERVED;
-	dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
-	/* Set persistent mode for front-buffer rendering, ala X. */
-	dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
+	dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane);
+	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
+	else
+		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
 	dpfc_ctl |= DPFC_CTL_FENCE_EN;
 	if (IS_GEN5(dev))
 		dpfc_ctl |= obj->fence_reg;
-	I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
 	I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
 	I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
@@ -282,12 +281,16 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	u32 dpfc_ctl;
 
-	I915_WRITE(IVB_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj));
+	dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane);
+	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
+	else
+		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+	dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
 
-	I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X |
-		   IVB_DPFC_CTL_FENCE_EN |
-		   intel_crtc->plane << IVB_DPFC_CTL_PLANE_SHIFT);
+	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
 	if (IS_IVYBRIDGE(dev)) {
 		/* WaFbcAsynchFlipDisableFbcQueue:ivb */
@@ -466,7 +469,7 @@ void intel_update_fbc(struct drm_device *dev)
 		return;
 	}
 
-	if (!i915_powersave) {
+	if (!i915.powersave) {
 		if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM))
 			DRM_DEBUG_KMS("fbc disabled per module param\n");
 		return;
@@ -505,13 +508,13 @@ void intel_update_fbc(struct drm_device *dev)
 	obj = intel_fb->obj;
 	adjusted_mode = &intel_crtc->config.adjusted_mode;
 
-	if (i915_enable_fbc < 0 &&
+	if (i915.enable_fbc < 0 &&
 	    INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) {
 		if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT))
 			DRM_DEBUG_KMS("disabled per chip default\n");
 		goto out_disable;
 	}
-	if (!i915_enable_fbc) {
+	if (!i915.enable_fbc) {
 		if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM))
 			DRM_DEBUG_KMS("fbc disabled per module param\n");
 		goto out_disable;
@@ -1886,7 +1889,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
 }
 
 /* Calculate the maximum FBC watermark */
-static unsigned int ilk_fbc_wm_max(struct drm_device *dev)
+static unsigned int ilk_fbc_wm_max(const struct drm_device *dev)
 {
 	/* max that registers can hold */
 	if (INTEL_INFO(dev)->gen >= 8)
@@ -1895,7 +1898,7 @@ static unsigned int ilk_fbc_wm_max(struct drm_device *dev)
 		return 15;
 }
 
-static void ilk_compute_wm_maximums(struct drm_device *dev,
+static void ilk_compute_wm_maximums(const struct drm_device *dev,
 				    int level,
 				    const struct intel_wm_config *config,
 				    enum intel_ddb_partitioning ddb_partitioning,
@@ -1948,7 +1951,7 @@ static bool ilk_validate_wm_level(int level,
 	return ret;
 }
 
-static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
+static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
 				 int level,
 				 const struct ilk_pipe_wm_parameters *p,
 				 struct intel_wm_level *result)
@@ -2140,7 +2143,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 				  struct intel_pipe_wm *pipe_wm)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	const struct drm_i915_private *dev_priv = dev->dev_private;
 	int level, max_level = ilk_wm_max_level(dev);
 	/* LP0 watermark maximums depend on this pipe alone */
 	struct intel_wm_config config = {
@@ -2738,7 +2741,7 @@ intel_alloc_context_page(struct drm_device *dev)
 		return NULL;
 	}
 
-	ret = i915_gem_obj_ggtt_pin(ctx, 4096, true, false);
+	ret = i915_gem_obj_ggtt_pin(ctx, 4096, 0);
 	if (ret) {
 		DRM_ERROR("failed to pin power context: %d\n", ret);
 		goto err_unref;
@@ -2753,7 +2756,7 @@ intel_alloc_context_page(struct drm_device *dev)
 	return ctx;
 
 err_unpin:
-	i915_gem_object_unpin(ctx);
+	i915_gem_object_ggtt_unpin(ctx);
 err_unref:
 	drm_gem_object_unreference(&ctx->base);
 	return NULL;
@@ -3000,6 +3003,9 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 	dev_priv->rps.last_adj = 0;
 }
 
+/* gen6_set_rps is called to update the frequency request, but should also be
+ * called when the range (min_delay and max_delay) is modified so that we can
+ * update the GEN6_RP_INTERRUPT_LIMITS register accordingly. */
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3008,8 +3014,14 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	WARN_ON(val > dev_priv->rps.max_delay);
 	WARN_ON(val < dev_priv->rps.min_delay);
 
-	if (val == dev_priv->rps.cur_delay)
+	if (val == dev_priv->rps.cur_delay) {
+		/* min/max delay may still have been modified so be sure to
+		 * write the limits value */
+		I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+			   gen6_rps_limits(dev_priv, val));
+
 		return;
+	}
 
 	gen6_set_rps_thresholds(dev_priv, val);
 
@@ -3035,6 +3047,58 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(val * 50);
 }
 
+/* vlv_set_rps_idle: Set the frequency to Rpn if Gfx clocks are down
+ *
+ * * If Gfx is Idle, then
+ * 1. Mask Turbo interrupts
+ * 2. Bring up Gfx clock
+ * 3. Change the freq to Rpn and wait till P-Unit updates freq
+ * 4. Clear the Force GFX CLK ON bit so that Gfx can down
+ * 5. Unmask Turbo interrupts
+*/
+static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
+{
+	/*
+	 * When we are idle.  Drop to min voltage state.
+	 */
+
+	if (dev_priv->rps.cur_delay <= dev_priv->rps.min_delay)
+		return;
+
+	/* Mask turbo interrupt so that they will not come in between */
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+
+	/* Bring up the Gfx clock */
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
+				VLV_GFX_CLK_FORCE_ON_BIT);
+
+	if (wait_for(((VLV_GFX_CLK_STATUS_BIT &
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 5)) {
+			DRM_ERROR("GFX_CLK_ON request timed out\n");
+		return;
+	}
+
+	dev_priv->rps.cur_delay = dev_priv->rps.min_delay;
+
+	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ,
+					dev_priv->rps.min_delay);
+
+	if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS))
+				& GENFREQSTATUS) == 0, 5))
+		DRM_ERROR("timed out waiting for Punit\n");
+
+	/* Release the Gfx clock */
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
+				~VLV_GFX_CLK_FORCE_ON_BIT);
+
+	/* Unmask Up interrupts */
+	dev_priv->rps.rp_up_masked = true;
+	gen6_set_pm_mask(dev_priv, GEN6_PM_RP_DOWN_THRESHOLD,
+						dev_priv->rps.min_delay);
+}
+
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -3042,7 +3106,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
 		if (IS_VALLEYVIEW(dev))
-			valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+			vlv_set_rps_idle(dev_priv);
 		else
 			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
 		dev_priv->rps.last_adj = 0;
@@ -3132,16 +3196,10 @@ static void valleyview_disable_rps(struct drm_device *dev)
 
 static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 {
-	if (IS_GEN6(dev))
-		DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
-
-	if (IS_HASWELL(dev))
-		DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
-
 	DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
-			(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
-			(mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
-			(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+		 (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
+		 (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
+		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
 int intel_enable_rc6(const struct drm_device *dev)
@@ -3151,21 +3209,17 @@ int intel_enable_rc6(const struct drm_device *dev)
 		return 0;
 
 	/* Respect the kernel parameter if it is set */
-	if (i915_enable_rc6 >= 0)
-		return i915_enable_rc6;
+	if (i915.enable_rc6 >= 0)
+		return i915.enable_rc6;
 
 	/* Disable RC6 on Ironlake */
 	if (INTEL_INFO(dev)->gen == 5)
 		return 0;
 
-	if (IS_HASWELL(dev))
-		return INTEL_RC6_ENABLE;
-
-	/* snb/ivb have more than one rc6 state. */
-	if (INTEL_INFO(dev)->gen == 6)
-		return INTEL_RC6_ENABLE;
+	if (IS_IVYBRIDGE(dev))
+		return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 
-	return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
+	return INTEL_RC6_ENABLE;
 }
 
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
@@ -3222,10 +3276,10 @@ static void gen8_enable_rps(struct drm_device *dev)
 	/* 3: Enable RC6 */
 	if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
 		rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
-	DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
+	intel_print_rc6_info(dev, rc6_mask);
 	I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
-			GEN6_RC_CTL_EI_MODE(1) |
-			rc6_mask);
+				    GEN6_RC_CTL_EI_MODE(1) |
+				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
 	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
@@ -3267,7 +3321,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 rp_state_cap;
+	u32 rp_state_cap, hw_max, hw_min;
 	u32 gt_perf_status;
 	u32 rc6vids, pcu_mbox, rc6_mask = 0;
 	u32 gtfifodbg;
@@ -3296,13 +3350,20 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* In units of 50MHz */
-	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
-	dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
+	hw_min = (rp_state_cap >> 16) & 0xff;
 	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
 	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
 	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
 	dev_priv->rps.cur_delay = 0;
 
+	/* Preserve min/max settings in case of re-init */
+	if (dev_priv->rps.max_delay == 0)
+		dev_priv->rps.max_delay = hw_max;
+
+	if (dev_priv->rps.min_delay == 0)
+		dev_priv->rps.min_delay = hw_min;
+
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
@@ -3493,6 +3554,8 @@ static void valleyview_setup_pctx(struct drm_device *dev)
 	u32 pcbr;
 	int pctx_size = 24*1024;
 
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
 	pcbr = I915_READ(VLV_PCBR);
 	if (pcbr) {
 		/* BIOS set it up already, grab the pre-alloc'd space */
@@ -3531,7 +3594,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 gtfifodbg, val, rc6_mode = 0;
+	u32 gtfifodbg, val, hw_max, hw_min, rc6_mode = 0;
 	int i;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -3542,8 +3605,6 @@ static void valleyview_enable_rps(struct drm_device *dev)
 		I915_WRITE(GTFIFODBG, gtfifodbg);
 	}
 
-	valleyview_setup_pctx(dev);
-
 	/* If VLV, Forcewake all wells, else re-direct to regular path */
 	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
@@ -3593,21 +3654,27 @@ static void valleyview_enable_rps(struct drm_device *dev)
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
 			 dev_priv->rps.cur_delay);
 
-	dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv);
-	dev_priv->rps.hw_max = dev_priv->rps.max_delay;
+	dev_priv->rps.hw_max = hw_max = valleyview_rps_max_freq(dev_priv);
 	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay),
-			 dev_priv->rps.max_delay);
+			 vlv_gpu_freq(dev_priv, hw_max),
+			 hw_max);
 
 	dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
 	DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
 			 dev_priv->rps.rpe_delay);
 
-	dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv);
+	hw_min = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay),
-			 dev_priv->rps.min_delay);
+			 vlv_gpu_freq(dev_priv, hw_min),
+			 hw_min);
+
+	/* Preserve min/max settings in case of re-init */
+	if (dev_priv->rps.max_delay == 0)
+		dev_priv->rps.max_delay = hw_max;
+
+	if (dev_priv->rps.min_delay == 0)
+		dev_priv->rps.min_delay = hw_min;
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
@@ -3615,6 +3682,9 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
 	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
+	dev_priv->rps.rp_up_masked = false;
+	dev_priv->rps.rp_down_masked = false;
+
 	gen6_enable_rps_interrupts(dev);
 
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
@@ -3625,13 +3695,13 @@ void ironlake_teardown_rc6(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->ips.renderctx) {
-		i915_gem_object_unpin(dev_priv->ips.renderctx);
+		i915_gem_object_ggtt_unpin(dev_priv->ips.renderctx);
 		drm_gem_object_unreference(&dev_priv->ips.renderctx->base);
 		dev_priv->ips.renderctx = NULL;
 	}
 
 	if (dev_priv->ips.pwrctx) {
-		i915_gem_object_unpin(dev_priv->ips.pwrctx);
+		i915_gem_object_ggtt_unpin(dev_priv->ips.pwrctx);
 		drm_gem_object_unreference(&dev_priv->ips.pwrctx->base);
 		dev_priv->ips.pwrctx = NULL;
 	}
@@ -3823,9 +3893,10 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
 	unsigned long val;
 
-	if (dev_priv->info->gen != 5)
+	if (INTEL_INFO(dev)->gen != 5)
 		return 0;
 
 	spin_lock_irq(&mchdev_lock);
@@ -3854,6 +3925,7 @@ unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
 
 static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
 {
+	struct drm_device *dev = dev_priv->dev;
 	static const struct v_table {
 		u16 vd; /* in .1 mil */
 		u16 vm; /* in .1 mil */
@@ -3987,7 +4059,7 @@ static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
 		{ 16000, 14875, },
 		{ 16125, 15000, },
 	};
-	if (dev_priv->info->is_mobile)
+	if (INTEL_INFO(dev)->is_mobile)
 		return v_table[pxvid].vm;
 	else
 		return v_table[pxvid].vd;
@@ -4030,7 +4102,9 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
 void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
-	if (dev_priv->info->gen != 5)
+	struct drm_device *dev = dev_priv->dev;
+
+	if (INTEL_INFO(dev)->gen != 5)
 		return;
 
 	spin_lock_irq(&mchdev_lock);
@@ -4079,9 +4153,10 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
 	unsigned long val;
 
-	if (dev_priv->info->gen != 5)
+	if (INTEL_INFO(dev)->gen != 5)
 		return 0;
 
 	spin_lock_irq(&mchdev_lock);
@@ -4270,6 +4345,7 @@ void intel_gpu_ips_teardown(void)
 	i915_mch_dev = NULL;
 	spin_unlock_irq(&mchdev_lock);
 }
+
 static void intel_init_emon(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4395,6 +4471,8 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+		if (IS_VALLEYVIEW(dev))
+			valleyview_setup_pctx(dev);
 		/*
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
@@ -4605,11 +4683,10 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 	 * According to the spec, bit 11 (RCCUNIT) must also be set,
 	 * but we didn't debug actual testcases to find it out.
 	 *
-	 * Also apply WaDisableVDSUnitClockGating:snb and
-	 * WaDisableRCPBUnitClockGating:snb.
+	 * WaDisableRCCUnitClockGating:snb
+	 * WaDisableRCPBUnitClockGating:snb
 	 */
 	I915_WRITE(GEN6_UCGCTL2,
-		   GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
 		   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
 		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
@@ -4618,6 +4695,14 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 		   _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);
 
 	/*
+	 * Bspec says:
+	 * "This bit must be set if 3DSTATE_CLIP clip mode is set to normal and
+	 * 3DSTATE_SF number of SF output attributes is more than 16."
+	 */
+	I915_WRITE(_3D_CHICKEN3,
+		   _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH));
+
+	/*
 	 * According to the spec the following bits should be
 	 * set in order to enable memory self-refresh and fbc:
 	 * The bit21 and bit22 of 0x42000
@@ -4655,14 +4740,17 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
 {
 	uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE);
 
+	/*
+	 * WaVSThreadDispatchOverride:ivb,vlv
+	 *
+	 * This actually overrides the dispatch
+	 * mode for all thread types.
+	 */
 	reg &= ~GEN7_FF_SCHED_MASK;
 	reg |= GEN7_FF_TS_SCHED_HW;
 	reg |= GEN7_FF_VS_SCHED_HW;
 	reg |= GEN7_FF_DS_SCHED_HW;
 
-	if (IS_HASWELL(dev_priv->dev))
-		reg &= ~GEN7_FF_VS_REF_CNT_FFME;
-
 	I915_WRITE(GEN7_FF_THREAD_MODE, reg);
 }
 
@@ -4709,8 +4797,10 @@ static void gen8_init_clock_gating(struct drm_device *dev)
 	/* FIXME(BDW): Check all the w/a, some might only apply to
 	 * pre-production hw. */
 
-	WARN(!i915_preliminary_hw_support,
-	     "GEN8_CENTROID_PIXEL_OPT_DIS not be needed for production\n");
+	/*
+	 * This GEN8_CENTROID_PIXEL_OPT_DIS W/A is only needed for
+	 * pre-production hardware
+	 */
 	I915_WRITE(HALF_SLICE_CHICKEN3,
 		   _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS));
 	I915_WRITE(HALF_SLICE_CHICKEN3,
@@ -4761,21 +4851,6 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 
 	ilk_init_lp_watermarks(dev);
 
-	/* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
-	 * This implements the WaDisableRCZUnitClockGating:hsw workaround.
-	 */
-	I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
-
-	/* Apply the WaDisableRHWOOptimizationForRenderHang:hsw workaround. */
-	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
-		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
-
-	/* WaApplyL3ControlAndL3ChickenMode:hsw */
-	I915_WRITE(GEN7_L3CNTLREG1,
-			GEN7_WA_FOR_GEN7_L3_CONTROL);
-	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
-			GEN7_WA_L3_CHICKEN_MODE);
-
 	/* L3 caching of data atomics doesn't work -- disable it. */
 	I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
 	I915_WRITE(HSW_ROW_CHICKEN3,
@@ -4787,7 +4862,12 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 			GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
 	/* WaVSRefCountFullforceMissDisable:hsw */
-	gen7_setup_fixed_func_scheduler(dev_priv);
+	I915_WRITE(GEN7_FF_THREAD_MODE,
+		   I915_READ(GEN7_FF_THREAD_MODE) & ~GEN7_FF_VS_REF_CNT_FFME);
+
+	/* enable HiZ Raw Stall Optimization */
+	I915_WRITE(CACHE_MODE_0_GEN7,
+		   _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
 
 	/* WaDisable4x2SubspanOptimization:hsw */
 	I915_WRITE(CACHE_MODE_1,
@@ -4825,9 +4905,6 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 	if (IS_IVB_GT1(dev))
 		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
 			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
-	else
-		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2,
-			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
 	/* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
@@ -4841,31 +4918,24 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 	if (IS_IVB_GT1(dev))
 		I915_WRITE(GEN7_ROW_CHICKEN2,
 			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
-	else
+	else {
+		/* must write both registers */
+		I915_WRITE(GEN7_ROW_CHICKEN2,
+			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
 		I915_WRITE(GEN7_ROW_CHICKEN2_GT2,
 			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
-
+	}
 
 	/* WaForceL3Serialization:ivb */
 	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
 		   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
 
-	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
-	 * gating disable must be set.  Failure to set it results in
-	 * flickering pixels due to Z write ordering failures after
-	 * some amount of runtime in the Mesa "fire" demo, and Unigine
-	 * Sanctuary and Tropics, and apparently anything else with
-	 * alpha test or pixel discard.
-	 *
-	 * According to the spec, bit 11 (RCCUNIT) must also be set,
-	 * but we didn't debug actual testcases to find it out.
-	 *
+	/*
 	 * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
 	 * This implements the WaDisableRCZUnitClockGating:ivb workaround.
 	 */
 	I915_WRITE(GEN6_UCGCTL2,
-		   GEN6_RCZUNIT_CLOCK_GATE_DISABLE |
-		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+		   GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
 
 	/* This is required by WaCatErrorRejectionIssue:ivb */
 	I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
@@ -4874,9 +4944,12 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 
 	g4x_disable_trickle_feed(dev);
 
-	/* WaVSRefCountFullforceMissDisable:ivb */
 	gen7_setup_fixed_func_scheduler(dev_priv);
 
+	/* enable HiZ Raw Stall Optimization */
+	I915_WRITE(CACHE_MODE_0_GEN7,
+		   _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
+
 	/* WaDisable4x2SubspanOptimization:ivb */
 	I915_WRITE(CACHE_MODE_1,
 		   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
@@ -4927,18 +5000,14 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
 		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
+	/* WaPsdDispatchEnable:vlv */
 	/* WaDisablePSDDualDispatchEnable:vlv */
 	I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
 		   _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
 				      GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
-	/* Apply the WaDisableRHWOOptimizationForRenderHang:vlv workaround. */
-	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
-		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
-
-	/* WaApplyL3ControlAndL3ChickenMode:vlv */
+	/* WaDisableL3CacheAging:vlv */
 	I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS);
-	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
 
 	/* WaForceL3Serialization:vlv */
 	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
@@ -4953,51 +5022,39 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
 		   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
-	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
-	 * gating disable must be set.  Failure to set it results in
-	 * flickering pixels due to Z write ordering failures after
-	 * some amount of runtime in the Mesa "fire" demo, and Unigine
-	 * Sanctuary and Tropics, and apparently anything else with
-	 * alpha test or pixel discard.
-	 *
-	 * According to the spec, bit 11 (RCCUNIT) must also be set,
-	 * but we didn't debug actual testcases to find it out.
-	 *
+	gen7_setup_fixed_func_scheduler(dev_priv);
+
+	/*
 	 * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
 	 * This implements the WaDisableRCZUnitClockGating:vlv workaround.
-	 *
-	 * Also apply WaDisableVDSUnitClockGating:vlv and
-	 * WaDisableRCPBUnitClockGating:vlv.
 	 */
 	I915_WRITE(GEN6_UCGCTL2,
-		   GEN7_VDSUNIT_CLOCK_GATE_DISABLE |
-		   GEN7_TDLUNIT_CLOCK_GATE_DISABLE |
-		   GEN6_RCZUNIT_CLOCK_GATE_DISABLE |
-		   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
-		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+		   GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
 
+	/* WaDisableL3Bank2xClockGate:vlv */
 	I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
 
 	I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
 
+	/*
+	 * BSpec says this must be set, even though
+	 * WaDisable4x2SubspanOptimization isn't listed for VLV.
+	 */
 	I915_WRITE(CACHE_MODE_1,
 		   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
 
 	/*
+	 * WaIncreaseL3CreditsForVLVB0:vlv
+	 * This is the hardware default actually.
+	 */
+	I915_WRITE(GEN7_L3SQCREG1, VLV_B0_WA_L3SQCREG1_VALUE);
+
+	/*
 	 * WaDisableVLVClockGating_VBIIssue:vlv
 	 * Disable clock gating on th GCFG unit to prevent a delay
 	 * in the reporting of vblank events.
 	 */
-	I915_WRITE(VLV_GUNIT_CLOCK_GATE, 0xffffffff);
-
-	/* Conservative clock gating settings for now */
-	I915_WRITE(0x9400, 0xffffffff);
-	I915_WRITE(0x9404, 0xffffffff);
-	I915_WRITE(0x9408, 0xffffffff);
-	I915_WRITE(0x940c, 0xffffffff);
-	I915_WRITE(0x9410, 0xffffffff);
-	I915_WRITE(0x9414, 0xffffffff);
-	I915_WRITE(0x9418, 0xffffffff);
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -5272,7 +5329,7 @@ static void __intel_power_well_put(struct drm_device *dev,
 	WARN_ON(!power_well->count);
 
 	if (!--power_well->count && power_well->set &&
-	    i915_disable_power_well) {
+	    i915.disable_power_well) {
 		power_well->set(dev, power_well, false);
 		hsw_enable_package_c8(dev_priv);
 	}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 31b36c5ac894..b340c7587629 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -531,9 +531,11 @@ init_pipe_control(struct intel_ring_buffer *ring)
 		goto err;
 	}
 
-	i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+	ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+	if (ret)
+		goto err_unref;
 
-	ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, true, false);
+	ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
 	if (ret)
 		goto err_unref;
 
@@ -549,7 +551,7 @@ init_pipe_control(struct intel_ring_buffer *ring)
 	return 0;
 
 err_unpin:
-	i915_gem_object_unpin(ring->scratch.obj);
+	i915_gem_object_ggtt_unpin(ring->scratch.obj);
 err_unref:
 	drm_gem_object_unreference(&ring->scratch.obj->base);
 err:
@@ -625,7 +627,7 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
 
 	if (INTEL_INFO(dev)->gen >= 5) {
 		kunmap(sg_page(ring->scratch.obj->pages->sgl));
-		i915_gem_object_unpin(ring->scratch.obj);
+		i915_gem_object_ggtt_unpin(ring->scratch.obj);
 	}
 
 	drm_gem_object_unreference(&ring->scratch.obj->base);
@@ -1253,7 +1255,7 @@ static void cleanup_status_page(struct intel_ring_buffer *ring)
 		return;
 
 	kunmap(sg_page(obj->pages->sgl));
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
 	ring->status_page.obj = NULL;
 }
@@ -1271,12 +1273,13 @@ static int init_status_page(struct intel_ring_buffer *ring)
 		goto err;
 	}
 
-	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+	ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+	if (ret)
+		goto err_unref;
 
-	ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false);
-	if (ret != 0) {
+	ret = i915_gem_obj_ggtt_pin(obj, 4096, 0);
+	if (ret)
 		goto err_unref;
-	}
 
 	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
 	ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
@@ -1293,7 +1296,7 @@ static int init_status_page(struct intel_ring_buffer *ring)
 	return 0;
 
 err_unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 err_unref:
 	drm_gem_object_unreference(&obj->base);
 err:
@@ -1356,7 +1359,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
 	ring->obj = obj;
 
-	ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
 	if (ret)
 		goto err_unref;
 
@@ -1390,7 +1393,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 err_unmap:
 	iounmap(ring->virtual_start);
 err_unpin:
-	i915_gem_object_unpin(obj);
+	i915_gem_object_ggtt_unpin(obj);
 err_unref:
 	drm_gem_object_unreference(&obj->base);
 	ring->obj = NULL;
@@ -1418,7 +1421,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 
 	iounmap(ring->virtual_start);
 
-	i915_gem_object_unpin(ring->obj);
+	i915_gem_object_ggtt_unpin(ring->obj);
 	drm_gem_object_unreference(&ring->obj->base);
 	ring->obj = NULL;
 	ring->preallocated_lazy_request = NULL;
@@ -1430,28 +1433,16 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 	cleanup_status_page(ring);
 }
 
-static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
-{
-	int ret;
-
-	ret = i915_wait_seqno(ring, seqno);
-	if (!ret)
-		i915_gem_retire_requests_ring(ring);
-
-	return ret;
-}
-
 static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
 {
 	struct drm_i915_gem_request *request;
-	u32 seqno = 0;
+	u32 seqno = 0, tail;
 	int ret;
 
-	i915_gem_retire_requests_ring(ring);
-
 	if (ring->last_retired_head != -1) {
 		ring->head = ring->last_retired_head;
 		ring->last_retired_head = -1;
+
 		ring->space = ring_space(ring);
 		if (ring->space >= n)
 			return 0;
@@ -1468,6 +1459,7 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
 			space += ring->size;
 		if (space >= n) {
 			seqno = request->seqno;
+			tail = request->tail;
 			break;
 		}
 
@@ -1482,15 +1474,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
 	if (seqno == 0)
 		return -ENOSPC;
 
-	ret = intel_ring_wait_seqno(ring, seqno);
+	ret = i915_wait_seqno(ring, seqno);
 	if (ret)
 		return ret;
 
-	if (WARN_ON(ring->last_retired_head == -1))
-		return -ENOSPC;
-
-	ring->head = ring->last_retired_head;
-	ring->last_retired_head = -1;
+	ring->head = tail;
 	ring->space = ring_space(ring);
 	if (WARN_ON(ring->space < n))
 		return -ENOSPC;
@@ -1528,7 +1516,8 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n)
 			return 0;
 		}
 
-		if (dev->primary->master) {
+		if (!drm_core_check_feature(dev, DRIVER_MODESET) &&
+		    dev->primary->master) {
 			struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 			if (master_priv->sarea_priv)
 				master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
@@ -1954,7 +1943,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 			return -ENOMEM;
 		}
 
-		ret = i915_gem_obj_ggtt_pin(obj, 0, true, false);
+		ret = i915_gem_obj_ggtt_pin(obj, 0, 0);
 		if (ret != 0) {
 			drm_gem_object_unreference(&obj->base);
 			DRM_ERROR("Failed to ping batch bo\n");
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 0b243ce33714..08b91c6ac70a 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -41,6 +41,8 @@ enum intel_ring_hangcheck_action {
 	HANGCHECK_HUNG,
 };
 
+#define HANGCHECK_SCORE_RING_HUNG 31
+
 struct intel_ring_hangcheck {
 	bool deadlock;
 	u32 seqno;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 95bdfb3c431c..825853d82a4d 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2382,24 +2382,62 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
 }
 
 static void
+intel_sdvo_connector_unregister(struct intel_connector *intel_connector)
+{
+	struct drm_connector *drm_connector;
+	struct intel_sdvo *sdvo_encoder;
+
+	drm_connector = &intel_connector->base;
+	sdvo_encoder = intel_attached_sdvo(&intel_connector->base);
+
+	sysfs_remove_link(&drm_connector->kdev->kobj,
+			  sdvo_encoder->ddc.dev.kobj.name);
+	intel_connector_unregister(intel_connector);
+}
+
+static int
 intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 			  struct intel_sdvo *encoder)
 {
-	drm_connector_init(encoder->base.base.dev,
-			   &connector->base.base,
+	struct drm_connector *drm_connector;
+	int ret;
+
+	drm_connector = &connector->base.base;
+	ret = drm_connector_init(encoder->base.base.dev,
+			   drm_connector,
 			   &intel_sdvo_connector_funcs,
 			   connector->base.base.connector_type);
+	if (ret < 0)
+		return ret;
 
-	drm_connector_helper_add(&connector->base.base,
+	drm_connector_helper_add(drm_connector,
 				 &intel_sdvo_connector_helper_funcs);
 
 	connector->base.base.interlace_allowed = 1;
 	connector->base.base.doublescan_allowed = 0;
 	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
+	connector->base.unregister = intel_sdvo_connector_unregister;
 
 	intel_connector_attach_encoder(&connector->base, &encoder->base);
-	drm_sysfs_connector_add(&connector->base.base);
+	ret = drm_sysfs_connector_add(drm_connector);
+	if (ret < 0)
+		goto err1;
+
+	ret = sysfs_create_link(&encoder->ddc.dev.kobj,
+				&drm_connector->kdev->kobj,
+				encoder->ddc.dev.kobj.name);
+	if (ret < 0)
+		goto err2;
+
+	return 0;
+
+err2:
+	drm_sysfs_connector_remove(drm_connector);
+err1:
+	drm_connector_cleanup(drm_connector);
+
+	return ret;
 }
 
 static void
@@ -2459,7 +2497,11 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo->is_hdmi = true;
 	}
 
-	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+		kfree(intel_sdvo_connector);
+		return false;
+	}
+
 	if (intel_sdvo->is_hdmi)
 		intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector);
 
@@ -2490,7 +2532,10 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
 	intel_sdvo->is_tv = true;
 
-	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+		kfree(intel_sdvo_connector);
+		return false;
+	}
 
 	if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type))
 		goto err;
@@ -2534,8 +2579,11 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
 	}
 
-	intel_sdvo_connector_init(intel_sdvo_connector,
-				  intel_sdvo);
+	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+		kfree(intel_sdvo_connector);
+		return false;
+	}
+
 	return true;
 }
 
@@ -2566,7 +2614,11 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
 	}
 
-	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+		kfree(intel_sdvo_connector);
+		return false;
+	}
+
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
 		goto err;
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 716a3c9c0751..336ae6c602f2 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -124,9 +124,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_w--;
 	crtc_h--;
 
-	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
-	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
-
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
 							obj->tiling_mode,
@@ -134,6 +131,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 							fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
+	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
+	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
+
 	if (obj->tiling_mode != I915_TILING_NONE)
 		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
 	else
@@ -293,15 +293,15 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
-	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
-
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset =
 		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
+	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
+	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
+
 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 	 * register */
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
@@ -472,15 +472,15 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
-	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
-
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
 		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
+	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
+	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
+
 	if (obj->tiling_mode != I915_TILING_NONE)
 		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
 	else
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 22cf0f4ba248..b64fc1c6ff3f 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1189,8 +1189,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
 	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 		i915_disable_pipestat(dev_priv, 0,
-				      PIPE_HOTPLUG_INTERRUPT_ENABLE |
-				      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+				      PIPE_HOTPLUG_INTERRUPT_STATUS |
+				      PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 	}
 
@@ -1266,8 +1266,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
 	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 		i915_enable_pipestat(dev_priv, 0,
-				     PIPE_HOTPLUG_INTERRUPT_ENABLE |
-				     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+				     PIPE_HOTPLUG_INTERRUPT_STATUS |
+				     PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 	}
 
@@ -1634,6 +1634,7 @@ intel_tv_init(struct drm_device *dev)
 	intel_encoder->disable = intel_disable_tv;
 	intel_encoder->get_hw_state = intel_tv_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	intel_connector->unregister = intel_connector_unregister;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 87df68f5f504..c62841404c82 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -852,6 +852,7 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_reset_stats *args = data;
 	struct i915_ctx_hang_stats *hs;
+	struct i915_hw_context *ctx;
 	int ret;
 
 	if (args->flags || args->pad)
@@ -864,11 +865,12 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id);
-	if (IS_ERR(hs)) {
+	ctx = i915_gem_context_get(file->driver_priv, args->ctx_id);
+	if (IS_ERR(ctx)) {
 		mutex_unlock(&dev->struct_mutex);
-		return PTR_ERR(hs);
+		return PTR_ERR(ctx);
 	}
+	hs = &ctx->hang_stats;
 
 	if (capable(CAP_SYS_ADMIN))
 		args->reset_count = i915_reset_count(&dev_priv->gpu_error);
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index c69d1e07a3a6..b6984971ce0c 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -3,7 +3,7 @@ config DRM_MSM
 	tristate "MSM DRM"
 	depends on DRM
 	depends on MSM_IOMMU
-	depends on (ARCH_MSM && ARCH_MSM8960) || (ARM && COMPILE_TEST)
+	depends on ARCH_MSM8960 || (ARM && COMPILE_TEST)
 	select DRM_KMS_HELPER
 	select SHMEM
 	select TMPFS
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 59d52ca2c67f..0231945c2934 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -361,6 +361,28 @@ static const struct panel_desc chunghwa_claa101wb01 = {
 	},
 };
 
+static const struct drm_display_mode lg_lp129qe_mode = {
+	.clock = 285250,
+	.hdisplay = 2560,
+	.hsync_start = 2560 + 48,
+	.hsync_end = 2560 + 48 + 32,
+	.htotal = 2560 + 48 + 32 + 80,
+	.vdisplay = 1700,
+	.vsync_start = 1700 + 3,
+	.vsync_end = 1700 + 3 + 10,
+	.vtotal = 1700 + 3 + 10 + 36,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc lg_lp129qe = {
+	.modes = &lg_lp129qe_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 272,
+		.height = 181,
+	},
+};
+
 static const struct drm_display_mode samsung_ltn101nt05_mode = {
 	.clock = 54030,
 	.hdisplay = 1024,
@@ -394,6 +416,9 @@ static const struct of_device_id platform_of_match[] = {
 		.compatible = "chunghwa,claa101wb01",
 		.data = &chunghwa_claa101wb01
 	}, {
+		.compatible = "lg,lp129qe",
+		.data = &lg_lp129qe,
+	}, {
 		.compatible = "samsung,ltn101nt05",
 		.data = &samsung_ltn101nt05,
 	}, {
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 306364a1ecda..ed60caa32518 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -99,6 +99,12 @@ radeon-y += \
 	uvd_v3_1.o \
 	uvd_v4_2.o
 
+# add VCE block
+radeon-y += \
+	radeon_vce.o \
+	vce_v1_0.o \
+	vce_v2_0.o \
+
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
 radeon-$(CONFIG_ACPI) += radeon_acpi.o
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
index ea103ccdf4bd..f81d7ca134db 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.c
+++ b/drivers/gpu/drm/radeon/btc_dpm.c
@@ -2601,6 +2601,10 @@ int btc_dpm_init(struct radeon_device *rdev)
 	pi->min_vddc_in_table = 0;
 	pi->max_vddc_in_table = 0;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = rv7xx_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 8d49104ca6c2..cad89a977527 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -172,6 +172,8 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
 extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev);
 extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev);
 extern int ci_mc_load_microcode(struct radeon_device *rdev);
+extern void cik_update_cg(struct radeon_device *rdev,
+			  u32 block, bool enable);
 
 static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev,
 					 struct atom_voltage_table_entry *voltage_table,
@@ -746,6 +748,14 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
 	u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
 	int i;
 
+	if (rps->vce_active) {
+		rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
+		rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
+	} else {
+		rps->evclk = 0;
+		rps->ecclk = 0;
+	}
+
 	if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
 	    ci_dpm_vblank_too_short(rdev))
 		disable_mclk_switching = true;
@@ -804,6 +814,13 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
 		sclk = ps->performance_levels[0].sclk;
 	}
 
+	if (rps->vce_active) {
+		if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
+			sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
+		if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
+			mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
+	}
+
 	ps->performance_levels[0].sclk = sclk;
 	ps->performance_levels[0].mclk = mclk;
 
@@ -3468,7 +3485,6 @@ static int ci_enable_uvd_dpm(struct radeon_device *rdev, bool enable)
 		0 : -EINVAL;
 }
 
-#if 0
 static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
 {
 	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3501,6 +3517,7 @@ static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
 		0 : -EINVAL;
 }
 
+#if 0
 static int ci_enable_samu_dpm(struct radeon_device *rdev, bool enable)
 {
 	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3587,7 +3604,6 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate)
 	return ci_enable_uvd_dpm(rdev, !gate);
 }
 
-#if 0
 static u8 ci_get_vce_boot_level(struct radeon_device *rdev)
 {
 	u8 i;
@@ -3608,15 +3624,15 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,
 			     struct radeon_ps *radeon_current_state)
 {
 	struct ci_power_info *pi = ci_get_pi(rdev);
-	bool new_vce_clock_non_zero = (radeon_new_state->evclk != 0);
-	bool old_vce_clock_non_zero = (radeon_current_state->evclk != 0);
 	int ret = 0;
 	u32 tmp;
 
-	if (new_vce_clock_non_zero != old_vce_clock_non_zero) {
-		if (new_vce_clock_non_zero) {
-			pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
+	if (radeon_current_state->evclk != radeon_new_state->evclk) {
+		if (radeon_new_state->evclk) {
+			/* turn the clocks on when encoding */
+			cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false);
 
+			pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
 			tmp = RREG32_SMC(DPM_TABLE_475);
 			tmp &= ~VceBootLevel_MASK;
 			tmp |= VceBootLevel(pi->smc_state_table.VceBootLevel);
@@ -3624,12 +3640,16 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,
 
 			ret = ci_enable_vce_dpm(rdev, true);
 		} else {
+			/* turn the clocks off when not encoding */
+			cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true);
+
 			ret = ci_enable_vce_dpm(rdev, false);
 		}
 	}
 	return ret;
 }
 
+#if 0
 static int ci_update_samu_dpm(struct radeon_device *rdev, bool gate)
 {
 	return ci_enable_samu_dpm(rdev, gate);
@@ -4752,13 +4772,13 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
 		DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n");
 		return ret;
 	}
-#if 0
+
 	ret = ci_update_vce_dpm(rdev, new_ps, old_ps);
 	if (ret) {
 		DRM_ERROR("ci_update_vce_dpm failed\n");
 		return ret;
 	}
-#endif
+
 	ret = ci_update_sclk_t(rdev);
 	if (ret) {
 		DRM_ERROR("ci_update_sclk_t failed\n");
@@ -4959,9 +4979,6 @@ static int ci_parse_power_table(struct radeon_device *rdev)
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
@@ -4998,6 +5015,21 @@ static int ci_parse_power_table(struct radeon_device *rdev)
 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
 	}
 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
+
+	/* fill in the vce power states */
+	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
+		u32 sclk, mclk;
+		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
+		clock_info = (union pplib_clock_info *)
+			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
+		sclk = le16_to_cpu(clock_info->ci.usEngineClockLow);
+		sclk |= clock_info->ci.ucEngineClockHigh << 16;
+		mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow);
+		mclk |= clock_info->ci.ucMemoryClockHigh << 16;
+		rdev->pm.dpm.vce_states[i].sclk = sclk;
+		rdev->pm.dpm.vce_states[i].mclk = mclk;
+	}
+
 	return 0;
 }
 
@@ -5077,17 +5109,25 @@ int ci_dpm_init(struct radeon_device *rdev)
 		ci_dpm_fini(rdev);
 		return ret;
 	}
-	ret = ci_parse_power_table(rdev);
+
+	ret = r600_get_platform_caps(rdev);
 	if (ret) {
 		ci_dpm_fini(rdev);
 		return ret;
 	}
+
 	ret = r600_parse_extended_power_table(rdev);
 	if (ret) {
 		ci_dpm_fini(rdev);
 		return ret;
 	}
 
+	ret = ci_parse_power_table(rdev);
+	if (ret) {
+		ci_dpm_fini(rdev);
+		return ret;
+	}
+
         pi->dll_default_on = false;
         pi->sram_end = SMC_RAM_END;
 
@@ -5120,6 +5160,7 @@ int ci_dpm_init(struct radeon_device *rdev)
 	pi->caps_sclk_throttle_low_notification = false;
 
 	pi->caps_uvd_dpm = true;
+	pi->caps_vce_dpm = true;
 
         ci_get_leakage_voltages(rdev);
         ci_patch_dependency_tables_with_leakage(rdev);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index e6419ca7cd37..92e38b54efb9 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -75,6 +75,7 @@ extern void si_init_uvd_internal_cg(struct radeon_device *rdev);
 extern int cik_sdma_resume(struct radeon_device *rdev);
 extern void cik_sdma_enable(struct radeon_device *rdev, bool enable);
 extern void cik_sdma_fini(struct radeon_device *rdev);
+extern void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable);
 static void cik_rlc_stop(struct radeon_device *rdev);
 static void cik_pcie_gen3_enable(struct radeon_device *rdev);
 static void cik_program_aspm(struct radeon_device *rdev);
@@ -4030,8 +4031,6 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
 	WREG32(CP_RB0_BASE, rb_addr);
 	WREG32(CP_RB0_BASE_HI, upper_32_bits(rb_addr));
 
-	ring->rptr = RREG32(CP_RB0_RPTR);
-
 	/* start the ring */
 	cik_cp_gfx_start(rdev);
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
@@ -4586,8 +4585,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
 		rdev->ring[idx].wptr = 0;
 		mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr;
 		WREG32(CP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr);
-		rdev->ring[idx].rptr = RREG32(CP_HQD_PQ_RPTR);
-		mqd->queue_state.cp_hqd_pq_rptr = rdev->ring[idx].rptr;
+		mqd->queue_state.cp_hqd_pq_rptr = RREG32(CP_HQD_PQ_RPTR);
 
 		/* set the vmid for the queue */
 		mqd->queue_state.cp_hqd_vmid = 0;
@@ -5117,11 +5115,9 @@ bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 	if (!(reset_mask & (RADEON_RESET_GFX |
 			    RADEON_RESET_COMPUTE |
 			    RADEON_RESET_CP))) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
@@ -6141,6 +6137,10 @@ void cik_update_cg(struct radeon_device *rdev,
 		cik_enable_hdp_mgcg(rdev, enable);
 		cik_enable_hdp_ls(rdev, enable);
 	}
+
+	if (block & RADEON_CG_BLOCK_VCE) {
+		vce_v2_0_enable_mgcg(rdev, enable);
+	}
 }
 
 static void cik_init_cg(struct radeon_device *rdev)
@@ -7490,6 +7490,20 @@ restart_ih:
 			/* reset addr and status */
 			WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
 			break;
+		case 167: /* VCE */
+			DRM_DEBUG("IH: VCE int: 0x%08x\n", src_data);
+			switch (src_data) {
+			case 0:
+				radeon_fence_process(rdev, TN_RING_TYPE_VCE1_INDEX);
+				break;
+			case 1:
+				radeon_fence_process(rdev, TN_RING_TYPE_VCE2_INDEX);
+				break;
+			default:
+				DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
+				break;
+			}
+			break;
 		case 176: /* GFX RB CP_INT */
 		case 177: /* GFX IB CP_INT */
 			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
@@ -7789,6 +7803,22 @@ static int cik_startup(struct radeon_device *rdev)
 	if (r)
 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
+	r = radeon_vce_resume(rdev);
+	if (!r) {
+		r = vce_v2_0_resume(rdev);
+		if (!r)
+			r = radeon_fence_driver_start_ring(rdev,
+							   TN_RING_TYPE_VCE1_INDEX);
+		if (!r)
+			r = radeon_fence_driver_start_ring(rdev,
+							   TN_RING_TYPE_VCE2_INDEX);
+	}
+	if (r) {
+		dev_err(rdev->dev, "VCE init error (%d).\n", r);
+		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+	}
+
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
 		r = radeon_irq_kms_init(rdev);
@@ -7864,6 +7894,23 @@ static int cik_startup(struct radeon_device *rdev)
 			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
 	}
 
+	r = -ENOENT;
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	if (ring->ring_size)
+		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+				     VCE_CMD_NO_OP);
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	if (ring->ring_size)
+		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+				     VCE_CMD_NO_OP);
+
+	if (!r)
+		r = vce_v1_0_init(rdev);
+	else if (r != -ENOENT)
+		DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
+
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -7934,6 +7981,7 @@ int cik_suspend(struct radeon_device *rdev)
 	cik_sdma_enable(rdev, false);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_suspend(rdev);
+	radeon_vce_suspend(rdev);
 	cik_fini_pg(rdev);
 	cik_fini_cg(rdev);
 	cik_irq_suspend(rdev);
@@ -8066,6 +8114,17 @@ int cik_init(struct radeon_device *rdev)
 		r600_ring_init(rdev, ring, 4096);
 	}
 
+	r = radeon_vce_init(rdev);
+	if (!r) {
+		ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+		ring->ring_obj = NULL;
+		r600_ring_init(rdev, ring, 4096);
+
+		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+		ring->ring_obj = NULL;
+		r600_ring_init(rdev, ring, 4096);
+	}
+
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
 
@@ -8127,6 +8186,7 @@ void cik_fini(struct radeon_device *rdev)
 	radeon_irq_kms_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_fini(rdev);
+	radeon_vce_fini(rdev);
 	cik_pcie_gart_fini(rdev);
 	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
@@ -8865,6 +8925,41 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
 	return r;
 }
 
+int cik_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
+{
+	int r, i;
+	struct atom_clock_dividers dividers;
+	u32 tmp;
+
+	r = radeon_atom_get_clock_dividers(rdev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
+					   ecclk, false, &dividers);
+	if (r)
+		return r;
+
+	for (i = 0; i < 100; i++) {
+		if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS)
+			break;
+		mdelay(10);
+	}
+	if (i == 100)
+		return -ETIMEDOUT;
+
+	tmp = RREG32_SMC(CG_ECLK_CNTL);
+	tmp &= ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK);
+	tmp |= dividers.post_divider;
+	WREG32_SMC(CG_ECLK_CNTL, tmp);
+
+	for (i = 0; i < 100; i++) {
+		if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS)
+			break;
+		mdelay(10);
+	}
+	if (i == 100)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static void cik_pcie_gen3_enable(struct radeon_device *rdev)
 {
 	struct pci_dev *root = rdev->pdev->bus->self;
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
index 1ecb3f1070e3..00150ac49cd2 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -362,8 +362,6 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev)
 		ring->wptr = 0;
 		WREG32(SDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2);
 
-		ring->rptr = RREG32(SDMA0_GFX_RB_RPTR + reg_offset) >> 2;
-
 		/* enable DMA RB */
 		WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl | SDMA_RB_ENABLE);
 
@@ -713,11 +711,9 @@ bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 		mask = RADEON_RESET_DMA1;
 
 	if (!(reset_mask & mask)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force ring activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index 98bae9d7b74d..213873270d5f 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -203,6 +203,12 @@
 #define		CTF_TEMP_MASK				0x0003fe00
 #define		CTF_TEMP_SHIFT				9
 
+#define CG_ECLK_CNTL                                    0xC05000AC
+#       define ECLK_DIVIDER_MASK                        0x7f
+#       define ECLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_ECLK_STATUS                                  0xC05000B0
+#       define ECLK_STATUS                              (1 << 0)
+
 #define	CG_SPLL_FUNC_CNTL				0xC0500140
 #define		SPLL_RESET				(1 << 0)
 #define		SPLL_PWRON				(1 << 1)
@@ -2010,4 +2016,47 @@
 /* UVD CTX indirect */
 #define	UVD_CGC_MEM_CTRL				0xC0
 
+/* VCE */
+
+#define VCE_VCPU_CACHE_OFFSET0		0x20024
+#define VCE_VCPU_CACHE_SIZE0		0x20028
+#define VCE_VCPU_CACHE_OFFSET1		0x2002c
+#define VCE_VCPU_CACHE_SIZE1		0x20030
+#define VCE_VCPU_CACHE_OFFSET2		0x20034
+#define VCE_VCPU_CACHE_SIZE2		0x20038
+#define VCE_RB_RPTR2			0x20178
+#define VCE_RB_WPTR2			0x2017c
+#define VCE_RB_RPTR			0x2018c
+#define VCE_RB_WPTR			0x20190
+#define VCE_CLOCK_GATING_A		0x202f8
+#	define CGC_CLK_GATE_DLY_TIMER_MASK	(0xf << 0)
+#	define CGC_CLK_GATE_DLY_TIMER(x)	((x) << 0)
+#	define CGC_CLK_GATER_OFF_DLY_TIMER_MASK	(0xff << 4)
+#	define CGC_CLK_GATER_OFF_DLY_TIMER(x)	((x) << 4)
+#	define CGC_UENC_WAIT_AWAKE	(1 << 18)
+#define VCE_CLOCK_GATING_B		0x202fc
+#define VCE_CGTT_CLK_OVERRIDE		0x207a0
+#define VCE_UENC_CLOCK_GATING		0x207bc
+#	define CLOCK_ON_DELAY_MASK	(0xf << 0)
+#	define CLOCK_ON_DELAY(x)	((x) << 0)
+#	define CLOCK_OFF_DELAY_MASK	(0xff << 4)
+#	define CLOCK_OFF_DELAY(x)	((x) << 4)
+#define VCE_UENC_REG_CLOCK_GATING	0x207c0
+#define VCE_SYS_INT_EN			0x21300
+#	define VCE_SYS_INT_TRAP_INTERRUPT_EN	(1 << 3)
+#define VCE_LMI_CTRL2			0x21474
+#define VCE_LMI_CTRL			0x21498
+#define VCE_LMI_VM_CTRL			0x214a0
+#define VCE_LMI_SWAP_CNTL		0x214b4
+#define VCE_LMI_SWAP_CNTL1		0x214b8
+#define VCE_LMI_CACHE_CTRL		0x214f4
+
+#define VCE_CMD_NO_OP		0x00000000
+#define VCE_CMD_END		0x00000001
+#define VCE_CMD_IB		0x00000002
+#define VCE_CMD_FENCE		0x00000003
+#define VCE_CMD_TRAP		0x00000004
+#define VCE_CMD_IB_AUTO		0x00000005
+#define VCE_CMD_SEMAPHORE	0x00000006
+
 #endif
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c
index cf783fc0ef21..5a9a5f4d7888 100644
--- a/drivers/gpu/drm/radeon/cypress_dpm.c
+++ b/drivers/gpu/drm/radeon/cypress_dpm.c
@@ -2036,6 +2036,10 @@ int cypress_dpm_init(struct radeon_device *rdev)
 	pi->min_vddc_in_table = 0;
 	pi->max_vddc_in_table = 0;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = rv7xx_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 8a2c010b7dc5..98e41b32cc1f 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2990,8 +2990,6 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
 	WREG32(CP_RB_BASE, ring->gpu_addr >> 8);
 	WREG32(CP_DEBUG, (1 << 27) | (1 << 28));
 
-	ring->rptr = RREG32(CP_RB_RPTR);
-
 	evergreen_cp_start(rdev);
 	ring->ready = true;
 	r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
@@ -3952,11 +3950,9 @@ bool evergreen_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
 	if (!(reset_mask & (RADEON_RESET_GFX |
 			    RADEON_RESET_COMPUTE |
 			    RADEON_RESET_CP))) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c
index a37b54436382..287fe966d7de 100644
--- a/drivers/gpu/drm/radeon/evergreen_dma.c
+++ b/drivers/gpu/drm/radeon/evergreen_dma.c
@@ -174,11 +174,9 @@ bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
 	u32 reset_mask = evergreen_gpu_check_soft_reset(rdev);
 
 	if (!(reset_mask & RADEON_RESET_DMA)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force ring activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
index 351db361239d..16ec9d56a234 100644
--- a/drivers/gpu/drm/radeon/kv_dpm.c
+++ b/drivers/gpu/drm/radeon/kv_dpm.c
@@ -1338,13 +1338,11 @@ static int kv_enable_uvd_dpm(struct radeon_device *rdev, bool enable)
 					PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable);
 }
 
-#if 0
 static int kv_enable_vce_dpm(struct radeon_device *rdev, bool enable)
 {
 	return kv_notify_message_to_smu(rdev, enable ?
 					PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable);
 }
-#endif
 
 static int kv_enable_samu_dpm(struct radeon_device *rdev, bool enable)
 {
@@ -1389,7 +1387,6 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate)
 	return kv_enable_uvd_dpm(rdev, !gate);
 }
 
-#if 0
 static u8 kv_get_vce_boot_level(struct radeon_device *rdev)
 {
 	u8 i;
@@ -1414,6 +1411,9 @@ static int kv_update_vce_dpm(struct radeon_device *rdev,
 	int ret;
 
 	if (radeon_new_state->evclk > 0 && radeon_current_state->evclk == 0) {
+		kv_dpm_powergate_vce(rdev, false);
+		/* turn the clocks on when encoding */
+		cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false);
 		if (pi->caps_stable_p_state)
 			pi->vce_boot_level = table->count - 1;
 		else
@@ -1436,11 +1436,13 @@ static int kv_update_vce_dpm(struct radeon_device *rdev,
 		kv_enable_vce_dpm(rdev, true);
 	} else if (radeon_new_state->evclk == 0 && radeon_current_state->evclk > 0) {
 		kv_enable_vce_dpm(rdev, false);
+		/* turn the clocks off when not encoding */
+		cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true);
+		kv_dpm_powergate_vce(rdev, true);
 	}
 
 	return 0;
 }
-#endif
 
 static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate)
 {
@@ -1575,11 +1577,16 @@ static void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate)
 	pi->vce_power_gated = gate;
 
 	if (gate) {
-		if (pi->caps_vce_pg)
+		if (pi->caps_vce_pg) {
+			/* XXX do we need a vce_v1_0_stop() ?  */
 			kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerOFF);
+		}
 	} else {
-		if (pi->caps_vce_pg)
+		if (pi->caps_vce_pg) {
 			kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerON);
+			vce_v2_0_resume(rdev);
+			vce_v1_0_start(rdev);
+		}
 	}
 }
 
@@ -1768,7 +1775,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
 {
 	struct kv_power_info *pi = kv_get_pi(rdev);
 	struct radeon_ps *new_ps = &pi->requested_rps;
-	/*struct radeon_ps *old_ps = &pi->current_rps;*/
+	struct radeon_ps *old_ps = &pi->current_rps;
 	int ret;
 
 	if (pi->bapm_enable) {
@@ -1798,13 +1805,12 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
 			kv_set_enabled_levels(rdev);
 			kv_force_lowest_valid(rdev);
 			kv_unforce_levels(rdev);
-#if 0
+
 			ret = kv_update_vce_dpm(rdev, new_ps, old_ps);
 			if (ret) {
 				DRM_ERROR("kv_update_vce_dpm failed\n");
 				return ret;
 			}
-#endif
 			kv_update_sclk_t(rdev);
 		}
 	} else {
@@ -1823,13 +1829,11 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
 			kv_program_nbps_index_settings(rdev, new_ps);
 			kv_freeze_sclk_dpm(rdev, false);
 			kv_set_enabled_levels(rdev);
-#if 0
 			ret = kv_update_vce_dpm(rdev, new_ps, old_ps);
 			if (ret) {
 				DRM_ERROR("kv_update_vce_dpm failed\n");
 				return ret;
 			}
-#endif
 			kv_update_acp_boot_level(rdev);
 			kv_update_sclk_t(rdev);
 			kv_enable_nb_dpm(rdev);
@@ -2037,6 +2041,14 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
 	struct radeon_clock_and_voltage_limits *max_limits =
 		&rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
 
+	if (new_rps->vce_active) {
+		new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
+		new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
+	} else {
+		new_rps->evclk = 0;
+		new_rps->ecclk = 0;
+	}
+
 	mclk = max_limits->mclk;
 	sclk = min_sclk;
 
@@ -2056,6 +2068,11 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
 		sclk = stable_p_state_sclk;
 	}
 
+	if (new_rps->vce_active) {
+		if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
+			sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
+	}
+
 	ps->need_dfs_bypass = true;
 
 	for (i = 0; i < ps->num_levels; i++) {
@@ -2092,7 +2109,8 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
 		}
 	}
 
-	pi->video_start = new_rps->dclk || new_rps->vclk;
+	pi->video_start = new_rps->dclk || new_rps->vclk ||
+		new_rps->evclk || new_rps->ecclk;
 
 	if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
 	    ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)
@@ -2538,9 +2556,6 @@ static int kv_parse_power_table(struct radeon_device *rdev)
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
@@ -2577,6 +2592,19 @@ static int kv_parse_power_table(struct radeon_device *rdev)
 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
 	}
 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
+
+	/* fill in the vce power states */
+	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
+		u32 sclk;
+		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
+		clock_info = (union pplib_clock_info *)
+			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
+		sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
+		sclk |= clock_info->sumo.ucEngineClockHigh << 16;
+		rdev->pm.dpm.vce_states[i].sclk = sclk;
+		rdev->pm.dpm.vce_states[i].mclk = 0;
+	}
+
 	return 0;
 }
 
@@ -2590,6 +2618,10 @@ int kv_dpm_init(struct radeon_device *rdev)
 		return -ENOMEM;
 	rdev->pm.dpm.priv = pi;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = r600_parse_extended_power_table(rdev);
 	if (ret)
 		return ret;
@@ -2623,7 +2655,7 @@ int kv_dpm_init(struct radeon_device *rdev)
 	pi->caps_fps = false; /* true? */
 	pi->caps_uvd_pg = true;
 	pi->caps_uvd_dpm = true;
-	pi->caps_vce_pg = false;
+	pi->caps_vce_pg = false; /* XXX true */
 	pi->caps_samu_pg = false;
 	pi->caps_acp_pg = false;
 	pi->caps_stable_p_state = false;
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index ea932ac66fc6..85168ecd216b 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1642,8 +1642,8 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 		ring = &rdev->ring[ridx[i]];
 		WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
 
-		ring->rptr = ring->wptr = 0;
-		WREG32(cp_rb_rptr[i], ring->rptr);
+		ring->wptr = 0;
+		WREG32(cp_rb_rptr[i], 0);
 		WREG32(cp_rb_wptr[i], ring->wptr);
 
 		mdelay(1);
@@ -1917,11 +1917,9 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 	if (!(reset_mask & (RADEON_RESET_GFX |
 			    RADEON_RESET_COMPUTE |
 			    RADEON_RESET_CP))) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
index 7cf96b15377f..6378e0276691 100644
--- a/drivers/gpu/drm/radeon/ni_dma.c
+++ b/drivers/gpu/drm/radeon/ni_dma.c
@@ -248,8 +248,6 @@ int cayman_dma_resume(struct radeon_device *rdev)
 		ring->wptr = 0;
 		WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2);
 
-		ring->rptr = RREG32(DMA_RB_RPTR + reg_offset) >> 2;
-
 		WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE);
 
 		ring->ready = true;
@@ -302,11 +300,9 @@ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 		mask = RADEON_RESET_DMA1;
 
 	if (!(reset_mask & mask)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force ring activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
index ca814276b075..004c931606c4 100644
--- a/drivers/gpu/drm/radeon/ni_dpm.c
+++ b/drivers/gpu/drm/radeon/ni_dpm.c
@@ -4025,9 +4025,6 @@ static int ni_parse_power_table(struct radeon_device *rdev)
 				  power_info->pplib.ucNumStates, GFP_KERNEL);
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 
 	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
 		power_state = (union pplib_power_state *)
@@ -4089,6 +4086,10 @@ int ni_dpm_init(struct radeon_device *rdev)
 	pi->min_vddc_in_table = 0;
 	pi->max_vddc_in_table = 0;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = ni_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ef024ce3f7cc..1690a2dc0721 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1193,7 +1193,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
 
 	WREG32(RADEON_CP_RB_CNTL, tmp);
 	udelay(10);
-	ring->rptr = RREG32(RADEON_CP_RB_RPTR);
 	/* Set cp mode to bus mastering & enable cp*/
 	WREG32(RADEON_CP_CSQ_MODE,
 	       REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
@@ -2523,11 +2522,9 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 
 	rbbm_status = RREG32(R_000E40_RBBM_STATUS);
 	if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index cdbc4171fe73..0f4ab928a15a 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1748,11 +1748,9 @@ bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 	if (!(reset_mask & (RADEON_RESET_GFX |
 			    RADEON_RESET_COMPUTE |
 			    RADEON_RESET_CP))) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
@@ -2604,8 +2602,6 @@ int r600_cp_resume(struct radeon_device *rdev)
 	WREG32(CP_RB_BASE, ring->gpu_addr >> 8);
 	WREG32(CP_DEBUG, (1 << 27) | (1 << 28));
 
-	ring->rptr = RREG32(CP_RB_RPTR);
-
 	r600_cp_start(rdev);
 	ring->ready = true;
 	r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c
index b2d4c91e6272..53fcb28f5578 100644
--- a/drivers/gpu/drm/radeon/r600_dma.c
+++ b/drivers/gpu/drm/radeon/r600_dma.c
@@ -176,8 +176,6 @@ int r600_dma_resume(struct radeon_device *rdev)
 	ring->wptr = 0;
 	WREG32(DMA_RB_WPTR, ring->wptr << 2);
 
-	ring->rptr = RREG32(DMA_RB_RPTR) >> 2;
-
 	WREG32(DMA_RB_CNTL, rb_cntl | DMA_RB_ENABLE);
 
 	ring->ready = true;
@@ -221,11 +219,9 @@ bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 	u32 reset_mask = r600_gpu_check_soft_reset(rdev);
 
 	if (!(reset_mask & RADEON_RESET_DMA)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force ring activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
index e4cc9b314ce9..cbf7e3269f84 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -834,6 +834,26 @@ static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependen
 	return 0;
 }
 
+int r600_get_platform_caps(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	union power_info *power_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+        u16 data_offset;
+	u8 frev, crev;
+
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return -EINVAL;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+
+	return 0;
+}
+
 /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
@@ -1043,7 +1063,15 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
 				(mode_info->atom_context->bios + data_offset +
 				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
 				 1 + array->ucNumEntries * sizeof(VCEClockInfo));
+			ATOM_PPLIB_VCE_State_Table *states =
+				(ATOM_PPLIB_VCE_State_Table *)
+				(mode_info->atom_context->bios + data_offset +
+				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
+				 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
+				 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
 			ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
+			ATOM_PPLIB_VCE_State_Record *state_entry;
+			VCEClockInfo *vce_clk;
 			u32 size = limits->numEntries *
 				sizeof(struct radeon_vce_clock_voltage_dependency_entry);
 			rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
@@ -1055,8 +1083,9 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
 			rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
 				limits->numEntries;
 			entry = &limits->entries[0];
+			state_entry = &states->entries[0];
 			for (i = 0; i < limits->numEntries; i++) {
-				VCEClockInfo *vce_clk = (VCEClockInfo *)
+				vce_clk = (VCEClockInfo *)
 					((u8 *)&array->entries[0] +
 					 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
 				rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
@@ -1068,6 +1097,23 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
 				entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
 					((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
 			}
+			for (i = 0; i < states->numEntries; i++) {
+				if (i >= RADEON_MAX_VCE_LEVELS)
+					break;
+				vce_clk = (VCEClockInfo *)
+					((u8 *)&array->entries[0] +
+					 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
+				rdev->pm.dpm.vce_states[i].evclk =
+					le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
+				rdev->pm.dpm.vce_states[i].ecclk =
+					le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
+				rdev->pm.dpm.vce_states[i].clk_idx =
+					state_entry->ucClockInfoIndex & 0x3f;
+				rdev->pm.dpm.vce_states[i].pstate =
+					(state_entry->ucClockInfoIndex & 0xc0) >> 6;
+				state_entry = (ATOM_PPLIB_VCE_State_Record *)
+					((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
+			}
 		}
 		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
 			ext_hdr->usUVDTableOffset) {
diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h
index 07eab2b04e81..46b9d2a03018 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.h
+++ b/drivers/gpu/drm/radeon/r600_dpm.h
@@ -215,6 +215,8 @@ void r600_stop_dpm(struct radeon_device *rdev);
 
 bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
 
+int r600_get_platform_caps(struct radeon_device *rdev);
+
 int r600_parse_extended_power_table(struct radeon_device *rdev);
 void r600_free_extended_power_table(struct radeon_device *rdev);
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e887d027b6d0..2340d95e6c95 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -113,19 +113,16 @@ extern int radeon_hard_reset;
 #define RADEONFB_CONN_LIMIT			4
 #define RADEON_BIOS_NUM_SCRATCH			8
 
-/* max number of rings */
-#define RADEON_NUM_RINGS			6
-
 /* fence seq are set to this number when signaled */
 #define RADEON_FENCE_SIGNALED_SEQ		0LL
 
 /* internal ring indices */
 /* r1xx+ has gfx CP ring */
-#define RADEON_RING_TYPE_GFX_INDEX	0
+#define RADEON_RING_TYPE_GFX_INDEX		0
 
 /* cayman has 2 compute CP rings */
-#define CAYMAN_RING_TYPE_CP1_INDEX	1
-#define CAYMAN_RING_TYPE_CP2_INDEX	2
+#define CAYMAN_RING_TYPE_CP1_INDEX		1
+#define CAYMAN_RING_TYPE_CP2_INDEX		2
 
 /* R600+ has an async dma ring */
 #define R600_RING_TYPE_DMA_INDEX		3
@@ -133,7 +130,17 @@ extern int radeon_hard_reset;
 #define CAYMAN_RING_TYPE_DMA1_INDEX		4
 
 /* R600+ */
-#define R600_RING_TYPE_UVD_INDEX	5
+#define R600_RING_TYPE_UVD_INDEX		5
+
+/* TN+ */
+#define TN_RING_TYPE_VCE1_INDEX			6
+#define TN_RING_TYPE_VCE2_INDEX			7
+
+/* max number of rings */
+#define RADEON_NUM_RINGS			8
+
+/* number of hw syncs before falling back on blocking */
+#define RADEON_NUM_SYNCS			4
 
 /* number of hw syncs before falling back on blocking */
 #define RADEON_NUM_SYNCS			4
@@ -789,7 +796,6 @@ struct radeon_ib {
 struct radeon_ring {
 	struct radeon_bo	*ring_obj;
 	volatile uint32_t	*ring;
-	unsigned		rptr;
 	unsigned		rptr_offs;
 	unsigned		rptr_save_reg;
 	u64			next_rptr_gpu_addr;
@@ -953,8 +959,8 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *c
 void radeon_ring_undo(struct radeon_ring *ring);
 void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
-void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring);
-void radeon_ring_lockup_update(struct radeon_ring *ring);
+void radeon_ring_lockup_update(struct radeon_device *rdev,
+			       struct radeon_ring *ring);
 bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring,
 			    uint32_t **data);
@@ -1255,6 +1261,17 @@ enum radeon_dpm_event_src {
 	RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
 };
 
+#define RADEON_MAX_VCE_LEVELS 6
+
+enum radeon_vce_level {
+	RADEON_VCE_LEVEL_AC_ALL = 0,     /* AC, All cases */
+	RADEON_VCE_LEVEL_DC_EE = 1,      /* DC, entropy encoding */
+	RADEON_VCE_LEVEL_DC_LL_LOW = 2,  /* DC, low latency queue, res <= 720 */
+	RADEON_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
+	RADEON_VCE_LEVEL_DC_GP_LOW = 4,  /* DC, general purpose queue, res <= 720 */
+	RADEON_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
+};
+
 struct radeon_ps {
 	u32 caps; /* vbios flags */
 	u32 class; /* vbios flags */
@@ -1265,6 +1282,8 @@ struct radeon_ps {
 	/* VCE clocks */
 	u32 evclk;
 	u32 ecclk;
+	bool vce_active;
+	enum radeon_vce_level vce_level;
 	/* asic priv */
 	void *ps_priv;
 };
@@ -1439,6 +1458,17 @@ enum radeon_dpm_forced_level {
 	RADEON_DPM_FORCED_LEVEL_HIGH = 2,
 };
 
+struct radeon_vce_state {
+	/* vce clocks */
+	u32 evclk;
+	u32 ecclk;
+	/* gpu clocks */
+	u32 sclk;
+	u32 mclk;
+	u8 clk_idx;
+	u8 pstate;
+};
+
 struct radeon_dpm {
 	struct radeon_ps        *ps;
 	/* number of valid power states */
@@ -1451,6 +1481,9 @@ struct radeon_dpm {
 	struct radeon_ps        *boot_ps;
 	/* default uvd power state */
 	struct radeon_ps        *uvd_ps;
+	/* vce requirements */
+	struct radeon_vce_state vce_states[RADEON_MAX_VCE_LEVELS];
+	enum radeon_vce_level vce_level;
 	enum radeon_pm_state_type state;
 	enum radeon_pm_state_type user_state;
 	u32                     platform_caps;
@@ -1476,6 +1509,7 @@ struct radeon_dpm {
 	/* special states active */
 	bool                    thermal_active;
 	bool                    uvd_active;
+	bool                    vce_active;
 	/* thermal handling */
 	struct radeon_dpm_thermal thermal;
 	/* forced levels */
@@ -1486,6 +1520,7 @@ struct radeon_dpm {
 };
 
 void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable);
+void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable);
 
 struct radeon_pm {
 	struct mutex		mutex;
@@ -1591,6 +1626,46 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
 int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
                                 unsigned cg_upll_func_cntl);
 
+/*
+ * VCE
+ */
+#define RADEON_MAX_VCE_HANDLES	16
+#define RADEON_VCE_STACK_SIZE	(1024*1024)
+#define RADEON_VCE_HEAP_SIZE	(4*1024*1024)
+
+struct radeon_vce {
+	struct radeon_bo	*vcpu_bo;
+	void			*cpu_addr;
+	uint64_t		gpu_addr;
+	unsigned		fw_version;
+	unsigned		fb_version;
+	atomic_t		handles[RADEON_MAX_VCE_HANDLES];
+	struct drm_file		*filp[RADEON_MAX_VCE_HANDLES];
+	struct delayed_work	idle_work;
+};
+
+int radeon_vce_init(struct radeon_device *rdev);
+void radeon_vce_fini(struct radeon_device *rdev);
+int radeon_vce_suspend(struct radeon_device *rdev);
+int radeon_vce_resume(struct radeon_device *rdev);
+int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
+			      uint32_t handle, struct radeon_fence **fence);
+int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
+			       uint32_t handle, struct radeon_fence **fence);
+void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
+void radeon_vce_note_usage(struct radeon_device *rdev);
+int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
+int radeon_vce_cs_parse(struct radeon_cs_parser *p);
+bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
+			       struct radeon_ring *ring,
+			       struct radeon_semaphore *semaphore,
+			       bool emit_wait);
+void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
+void radeon_vce_fence_emit(struct radeon_device *rdev,
+			   struct radeon_fence *fence);
+int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
+int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
+
 struct r600_audio_pin {
 	int			channels;
 	int			rate;
@@ -1780,6 +1855,7 @@ struct radeon_asic {
 		void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
 		void (*set_clock_gating)(struct radeon_device *rdev, int enable);
 		int (*set_uvd_clocks)(struct radeon_device *rdev, u32 vclk, u32 dclk);
+		int (*set_vce_clocks)(struct radeon_device *rdev, u32 evclk, u32 ecclk);
 		int (*get_temperature)(struct radeon_device *rdev);
 	} pm;
 	/* dynamic power management */
@@ -2186,6 +2262,7 @@ struct radeon_device {
 	struct radeon_gem		gem;
 	struct radeon_pm		pm;
 	struct radeon_uvd		uvd;
+	struct radeon_vce		vce;
 	uint32_t			bios_scratch[RADEON_BIOS_NUM_SCRATCH];
 	struct radeon_wb		wb;
 	struct radeon_dummy_page	dummy_page;
@@ -2205,6 +2282,7 @@ struct radeon_device {
 	const struct firmware *sdma_fw;	/* CIK SDMA firmware */
 	const struct firmware *smc_fw;	/* SMC firmware */
 	const struct firmware *uvd_fw;	/* UVD firmware */
+	const struct firmware *vce_fw;	/* VCE firmware */
 	struct r600_vram_scratch vram_scratch;
 	int msi_enabled; /* msi enabled */
 	struct r600_ih ih; /* r6/700 interrupt ring */
@@ -2639,6 +2717,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l))
 #define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e))
 #define radeon_set_uvd_clocks(rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d))
+#define radeon_set_vce_clocks(rdev, ev, ec) (rdev)->asic->pm.set_vce_clocks((rdev), (ev), (ec))
 #define radeon_get_temperature(rdev) (rdev)->asic->pm.get_temperature((rdev))
 #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s)))
 #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r)))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index dda02bfc10a4..b8a24a75d4ff 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1987,6 +1987,19 @@ static struct radeon_asic_ring ci_dma_ring = {
 	.set_wptr = &cik_sdma_set_wptr,
 };
 
+static struct radeon_asic_ring ci_vce_ring = {
+	.ib_execute = &radeon_vce_ib_execute,
+	.emit_fence = &radeon_vce_fence_emit,
+	.emit_semaphore = &radeon_vce_semaphore_emit,
+	.cs_parse = &radeon_vce_cs_parse,
+	.ring_test = &radeon_vce_ring_test,
+	.ib_test = &radeon_vce_ib_test,
+	.is_lockup = &radeon_ring_test_lockup,
+	.get_rptr = &vce_v1_0_get_rptr,
+	.get_wptr = &vce_v1_0_get_wptr,
+	.set_wptr = &vce_v1_0_set_wptr,
+};
+
 static struct radeon_asic ci_asic = {
 	.init = &cik_init,
 	.fini = &cik_fini,
@@ -2015,6 +2028,8 @@ static struct radeon_asic ci_asic = {
 		[R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
 		[CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
 		[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
+		[TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
+		[TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
 	},
 	.irq = {
 		.set = &cik_irq_set,
@@ -2061,6 +2076,7 @@ static struct radeon_asic ci_asic = {
 		.set_pcie_lanes = NULL,
 		.set_clock_gating = NULL,
 		.set_uvd_clocks = &cik_set_uvd_clocks,
+		.set_vce_clocks = &cik_set_vce_clocks,
 		.get_temperature = &ci_get_temp,
 	},
 	.dpm = {
@@ -2117,6 +2133,8 @@ static struct radeon_asic kv_asic = {
 		[R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
 		[CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
 		[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
+		[TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
+		[TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
 	},
 	.irq = {
 		.set = &cik_irq_set,
@@ -2163,6 +2181,7 @@ static struct radeon_asic kv_asic = {
 		.set_pcie_lanes = NULL,
 		.set_clock_gating = NULL,
 		.set_uvd_clocks = &cik_set_uvd_clocks,
+		.set_vce_clocks = &cik_set_vce_clocks,
 		.get_temperature = &kv_get_temp,
 	},
 	.dpm = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index ae637cfda783..3d55a3a39e82 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -717,6 +717,7 @@ u32 cik_get_xclk(struct radeon_device *rdev);
 uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
 void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
+int cik_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk);
 void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
 			      struct radeon_fence *fence);
 bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
@@ -863,4 +864,17 @@ bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
 /* uvd v4.2 */
 int uvd_v4_2_resume(struct radeon_device *rdev);
 
+/* vce v1.0 */
+uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
+			   struct radeon_ring *ring);
+uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
+			   struct radeon_ring *ring);
+void vce_v1_0_set_wptr(struct radeon_device *rdev,
+		       struct radeon_ring *ring);
+int vce_v1_0_init(struct radeon_device *rdev);
+int vce_v1_0_start(struct radeon_device *rdev);
+
+/* vce v2.0 */
+int vce_v2_0_resume(struct radeon_device *rdev);
+
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index dfb5a1db87d4..f28a8d82fa19 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -147,6 +147,10 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
 	case RADEON_CS_RING_UVD:
 		p->ring = R600_RING_TYPE_UVD_INDEX;
 		break;
+	case RADEON_CS_RING_VCE:
+		/* TODO: only use the low priority ring for now */
+		p->ring = TN_RING_TYPE_VCE1_INDEX;
+		break;
 	}
 	return 0;
 }
@@ -343,6 +347,9 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
 
 	if (parser->ring == R600_RING_TYPE_UVD_INDEX)
 		radeon_uvd_note_usage(rdev);
+	else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) ||
+		 (parser->ring == TN_RING_TYPE_VCE2_INDEX))
+		radeon_vce_note_usage(rdev);
 
 	radeon_cs_sync_rings(parser);
 	r = radeon_ib_schedule(rdev, &parser->ib, NULL);
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 2aecd6dc2610..eea70b06e032 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -433,6 +433,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
 		case RADEON_CS_RING_UVD:
 			*value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
 			break;
+		case RADEON_CS_RING_VCE:
+			*value = rdev->ring[TN_RING_TYPE_VCE1_INDEX].ready;
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -477,6 +480,12 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
 		else
 			*value = rdev->pm.default_sclk * 10;
 		break;
+	case RADEON_INFO_VCE_FW_VERSION:
+		*value = rdev->vce.fw_version;
+		break;
+	case RADEON_INFO_VCE_FB_VERSION:
+		*value = rdev->vce.fb_version;
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
@@ -616,6 +625,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
 	if (rdev->cmask_filp == file_priv)
 		rdev->cmask_filp = NULL;
 	radeon_uvd_free_handles(rdev, file_priv);
+	radeon_vce_free_handles(rdev, file_priv);
 }
 
 /*
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 8e8153e471c2..4ad9af9fc517 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -826,6 +826,9 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
 	/* no need to reprogram if nothing changed unless we are on BTC+ */
 	if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) {
+		/* vce just modifies an existing state so force a change */
+		if (ps->vce_active != rdev->pm.dpm.vce_active)
+			goto force;
 		if ((rdev->family < CHIP_BARTS) || (rdev->flags & RADEON_IS_IGP)) {
 			/* for pre-BTC and APUs if the num crtcs changed but state is the same,
 			 * all we need to do is update the display configuration.
@@ -862,16 +865,21 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 		}
 	}
 
+force:
 	if (radeon_dpm == 1) {
 		printk("switching from power state:\n");
 		radeon_dpm_print_power_state(rdev, rdev->pm.dpm.current_ps);
 		printk("switching to power state:\n");
 		radeon_dpm_print_power_state(rdev, rdev->pm.dpm.requested_ps);
 	}
+
 	mutex_lock(&rdev->ddev->struct_mutex);
 	down_write(&rdev->pm.mclk_lock);
 	mutex_lock(&rdev->ring_lock);
 
+	/* update whether vce is active */
+	ps->vce_active = rdev->pm.dpm.vce_active;
+
 	ret = radeon_dpm_pre_set_power_state(rdev);
 	if (ret)
 		goto done;
@@ -960,6 +968,23 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
 	}
 }
 
+void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable)
+{
+	if (enable) {
+		mutex_lock(&rdev->pm.mutex);
+		rdev->pm.dpm.vce_active = true;
+		/* XXX select vce level based on ring/task */
+		rdev->pm.dpm.vce_level = RADEON_VCE_LEVEL_AC_ALL;
+		mutex_unlock(&rdev->pm.mutex);
+	} else {
+		mutex_lock(&rdev->pm.mutex);
+		rdev->pm.dpm.vce_active = false;
+		mutex_unlock(&rdev->pm.mutex);
+	}
+
+	radeon_pm_compute_clocks(rdev);
+}
+
 static void radeon_pm_suspend_old(struct radeon_device *rdev)
 {
 	mutex_lock(&rdev->pm.mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 15e44a7281ab..b14c86d57607 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -342,13 +342,17 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
  */
 void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-	ring->rptr = radeon_ring_get_rptr(rdev, ring);
+	uint32_t rptr = radeon_ring_get_rptr(rdev, ring);
+
 	/* This works because ring_size is a power of 2 */
-	ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4));
+	ring->ring_free_dw = rptr + (ring->ring_size / 4);
 	ring->ring_free_dw -= ring->wptr;
 	ring->ring_free_dw &= ring->ptr_mask;
 	if (!ring->ring_free_dw) {
+		/* this is an empty ring */
 		ring->ring_free_dw = ring->ring_size / 4;
+		/*  update lockup info to avoid false positive */
+		radeon_ring_lockup_update(rdev, ring);
 	}
 }
 
@@ -372,12 +376,6 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
 	/* Align requested size with padding so unlock_commit can
 	 * pad safely */
 	radeon_ring_free_size(rdev, ring);
-	if (ring->ring_free_dw == (ring->ring_size / 4)) {
-		/* This is an empty ring update lockup info to avoid
-		 * false positive.
-		 */
-		radeon_ring_lockup_update(ring);
-	}
 	ndw = (ndw + ring->align_mask) & ~ring->align_mask;
 	while (ndw > (ring->ring_free_dw - 1)) {
 		radeon_ring_free_size(rdev, ring);
@@ -478,38 +476,16 @@ void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *rin
 }
 
 /**
- * radeon_ring_force_activity - add some nop packets to the ring
- *
- * @rdev: radeon_device pointer
- * @ring: radeon_ring structure holding ring information
- *
- * Add some nop packets to the ring to force activity (all asics).
- * Used for lockup detection to see if the rptr is advancing.
- */
-void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-	int r;
-
-	radeon_ring_free_size(rdev, ring);
-	if (ring->rptr == ring->wptr) {
-		r = radeon_ring_alloc(rdev, ring, 1);
-		if (!r) {
-			radeon_ring_write(ring, ring->nop);
-			radeon_ring_commit(rdev, ring);
-		}
-	}
-}
-
-/**
  * radeon_ring_lockup_update - update lockup variables
  *
  * @ring: radeon_ring structure holding ring information
  *
  * Update the last rptr value and timestamp (all asics).
  */
-void radeon_ring_lockup_update(struct radeon_ring *ring)
+void radeon_ring_lockup_update(struct radeon_device *rdev,
+			       struct radeon_ring *ring)
 {
-	ring->last_rptr = ring->rptr;
+	ring->last_rptr = radeon_ring_get_rptr(rdev, ring);
 	ring->last_activity = jiffies;
 }
 
@@ -518,35 +494,21 @@ void radeon_ring_lockup_update(struct radeon_ring *ring)
  * @rdev:       radeon device structure
  * @ring:       radeon_ring structure holding ring information
  *
- * We don't need to initialize the lockup tracking information as we will either
- * have CP rptr to a different value of jiffies wrap around which will force
- * initialization of the lockup tracking informations.
- *
- * A possible false positivie is if we get call after while and last_cp_rptr ==
- * the current CP rptr, even if it's unlikely it might happen. To avoid this
- * if the elapsed time since last call is bigger than 2 second than we return
- * false and update the tracking information. Due to this the caller must call
- * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported
- * the fencing code should be cautious about that.
- *
- * Caller should write to the ring to force CP to do something so we don't get
- * false positive when CP is just gived nothing to do.
- *
- **/
+ */
 bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
+	uint32_t rptr = radeon_ring_get_rptr(rdev, ring);
 	unsigned long cjiffies, elapsed;
 
 	cjiffies = jiffies;
 	if (!time_after(cjiffies, ring->last_activity)) {
 		/* likely a wrap around */
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	ring->rptr = radeon_ring_get_rptr(rdev, ring);
-	if (ring->rptr != ring->last_rptr) {
+	if (rptr != ring->last_rptr) {
 		/* CP is still working no lockup */
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
 	elapsed = jiffies_to_msecs(cjiffies - ring->last_activity);
@@ -709,7 +671,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
 	if (radeon_debugfs_ring_init(rdev, ring)) {
 		DRM_ERROR("Failed to register debugfs file for rings !\n");
 	}
-	radeon_ring_lockup_update(ring);
+	radeon_ring_lockup_update(rdev, ring);
 	return 0;
 }
 
@@ -780,8 +742,6 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 
 	seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n",
 		   ring->wptr, ring->wptr);
-	seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n",
-		   ring->rptr, ring->rptr);
 	seq_printf(m, "last semaphore signal addr : 0x%016llx\n",
 		   ring->last_semaphore_signal_addr);
 	seq_printf(m, "last semaphore wait addr   : 0x%016llx\n",
@@ -814,6 +774,8 @@ static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX;
 static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX;
 static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX;
 static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX;
+static int si_vce1_index = TN_RING_TYPE_VCE1_INDEX;
+static int si_vce2_index = TN_RING_TYPE_VCE2_INDEX;
 
 static struct drm_info_list radeon_debugfs_ring_info_list[] = {
 	{"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index},
@@ -822,6 +784,8 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = {
 	{"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index},
 	{"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index},
 	{"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index},
+	{"radeon_ring_vce1", radeon_debugfs_ring_info, 0, &si_vce1_index},
+	{"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index},
 };
 
 static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index 12e8099a0823..3a13e0d1055c 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -257,20 +257,36 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
 					     struct radeon_ring *ring,
 					     struct radeon_fence **fence)
 {
+	uint32_t handle = ring->idx ^ 0xdeafbeef;
 	int r;
 
 	if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
-		r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
+		r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL);
 		if (r) {
 			DRM_ERROR("Failed to get dummy create msg\n");
 			return r;
 		}
 
-		r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence);
+		r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence);
 		if (r) {
 			DRM_ERROR("Failed to get dummy destroy msg\n");
 			return r;
 		}
+
+	} else if (ring->idx == TN_RING_TYPE_VCE1_INDEX ||
+		   ring->idx == TN_RING_TYPE_VCE2_INDEX) {
+		r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL);
+		if (r) {
+			DRM_ERROR("Failed to get dummy create msg\n");
+			return r;
+		}
+
+		r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence);
+		if (r) {
+			DRM_ERROR("Failed to get dummy destroy msg\n");
+			return r;
+		}
+
 	} else {
 		r = radeon_ring_lock(rdev, ring, 64);
 		if (r) {
@@ -486,6 +502,16 @@ out_cleanup:
 		printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
 }
 
+static bool radeon_test_sync_possible(struct radeon_ring *ringA,
+				      struct radeon_ring *ringB)
+{
+	if (ringA->idx == TN_RING_TYPE_VCE2_INDEX &&
+	    ringB->idx == TN_RING_TYPE_VCE1_INDEX)
+		return false;
+
+	return true;
+}
+
 void radeon_test_syncing(struct radeon_device *rdev)
 {
 	int i, j, k;
@@ -500,6 +526,9 @@ void radeon_test_syncing(struct radeon_device *rdev)
 			if (!ringB->ready)
 				continue;
 
+			if (!radeon_test_sync_possible(ringA, ringB))
+				continue;
+
 			DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
 			radeon_test_ring_sync(rdev, ringA, ringB);
 
@@ -511,6 +540,12 @@ void radeon_test_syncing(struct radeon_device *rdev)
 				if (!ringC->ready)
 					continue;
 
+				if (!radeon_test_sync_possible(ringA, ringC))
+					continue;
+
+				if (!radeon_test_sync_possible(ringB, ringC))
+					continue;
+
 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
 				radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
 
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
new file mode 100644
index 000000000000..d130432e313a
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -0,0 +1,694 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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 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, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * Authors: Christian König <christian.koenig@amd.com>
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "sid.h"
+
+/* 1 second timeout */
+#define VCE_IDLE_TIMEOUT_MS	1000
+
+/* Firmware Names */
+#define FIRMWARE_BONAIRE	"radeon/BONAIRE_vce.bin"
+
+MODULE_FIRMWARE(FIRMWARE_BONAIRE);
+
+static void radeon_vce_idle_work_handler(struct work_struct *work);
+
+/**
+ * radeon_vce_init - allocate memory, load vce firmware
+ *
+ * @rdev: radeon_device pointer
+ *
+ * First step to get VCE online, allocate memory and load the firmware
+ */
+int radeon_vce_init(struct radeon_device *rdev)
+{
+	static const char *fw_version = "[ATI LIB=VCEFW,";
+	static const char *fb_version = "[ATI LIB=VCEFWSTATS,";
+	unsigned long size;
+	const char *fw_name, *c;
+	uint8_t start, mid, end;
+	int i, r;
+
+	INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler);
+
+	switch (rdev->family) {
+	case CHIP_BONAIRE:
+	case CHIP_KAVERI:
+	case CHIP_KABINI:
+		fw_name = FIRMWARE_BONAIRE;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	r = request_firmware(&rdev->vce_fw, fw_name, rdev->dev);
+	if (r) {
+		dev_err(rdev->dev, "radeon_vce: Can't load firmware \"%s\"\n",
+			fw_name);
+		return r;
+	}
+
+	/* search for firmware version */
+
+	size = rdev->vce_fw->size - strlen(fw_version) - 9;
+	c = rdev->vce_fw->data;
+	for (;size > 0; --size, ++c)
+		if (strncmp(c, fw_version, strlen(fw_version)) == 0)
+			break;
+
+	if (size == 0)
+		return -EINVAL;
+
+	c += strlen(fw_version);
+	if (sscanf(c, "%2hhd.%2hhd.%2hhd]", &start, &mid, &end) != 3)
+		return -EINVAL;
+
+	/* search for feedback version */
+
+	size = rdev->vce_fw->size - strlen(fb_version) - 3;
+	c = rdev->vce_fw->data;
+	for (;size > 0; --size, ++c)
+		if (strncmp(c, fb_version, strlen(fb_version)) == 0)
+			break;
+
+	if (size == 0)
+		return -EINVAL;
+
+	c += strlen(fb_version);
+	if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1)
+		return -EINVAL;
+
+	DRM_INFO("Found VCE firmware/feedback version %hhd.%hhd.%hhd / %d!\n",
+		 start, mid, end, rdev->vce.fb_version);
+
+	rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
+
+	/* we can only work with this fw version for now */
+	if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8)))
+		return -EINVAL;
+
+	/* load firmware into VRAM */
+
+	size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
+	       RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
+			     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
+	if (r) {
+		dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
+		return r;
+	}
+
+	r = radeon_vce_resume(rdev);
+	if (r)
+		return r;
+
+	memset(rdev->vce.cpu_addr, 0, size);
+	memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
+
+	r = radeon_vce_suspend(rdev);
+	if (r)
+		return r;
+
+	for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+		atomic_set(&rdev->vce.handles[i], 0);
+		rdev->vce.filp[i] = NULL;
+        }
+
+	return 0;
+}
+
+/**
+ * radeon_vce_fini - free memory
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Last step on VCE teardown, free firmware memory
+ */
+void radeon_vce_fini(struct radeon_device *rdev)
+{
+	radeon_vce_suspend(rdev);
+	radeon_bo_unref(&rdev->vce.vcpu_bo);
+}
+
+/**
+ * radeon_vce_suspend - unpin VCE fw memory
+ *
+ * @rdev: radeon_device pointer
+ *
+ * TODO: Test VCE suspend/resume
+ */
+int radeon_vce_suspend(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vce.vcpu_bo == NULL)
+		return 0;
+
+	r = radeon_bo_reserve(rdev->vce.vcpu_bo, false);
+	if (!r) {
+		radeon_bo_kunmap(rdev->vce.vcpu_bo);
+		radeon_bo_unpin(rdev->vce.vcpu_bo);
+		radeon_bo_unreserve(rdev->vce.vcpu_bo);
+	}
+	return r;
+}
+
+/**
+ * radeon_vce_resume - pin VCE fw memory
+ *
+ * @rdev: radeon_device pointer
+ *
+ * TODO: Test VCE suspend/resume
+ */
+int radeon_vce_resume(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vce.vcpu_bo == NULL)
+		return -EINVAL;
+
+	r = radeon_bo_reserve(rdev->vce.vcpu_bo, false);
+	if (r) {
+		radeon_bo_unref(&rdev->vce.vcpu_bo);
+		dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r);
+		return r;
+	}
+
+	r = radeon_bo_pin(rdev->vce.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
+			  &rdev->vce.gpu_addr);
+	if (r) {
+		radeon_bo_unreserve(rdev->vce.vcpu_bo);
+		radeon_bo_unref(&rdev->vce.vcpu_bo);
+		dev_err(rdev->dev, "(%d) VCE bo pin failed\n", r);
+		return r;
+	}
+
+	r = radeon_bo_kmap(rdev->vce.vcpu_bo, &rdev->vce.cpu_addr);
+	if (r) {
+		dev_err(rdev->dev, "(%d) VCE map failed\n", r);
+		return r;
+	}
+
+	radeon_bo_unreserve(rdev->vce.vcpu_bo);
+
+	return 0;
+}
+
+/**
+ * radeon_vce_idle_work_handler - power off VCE
+ *
+ * @work: pointer to work structure
+ *
+ * power of VCE when it's not used any more
+ */
+static void radeon_vce_idle_work_handler(struct work_struct *work)
+{
+	struct radeon_device *rdev =
+		container_of(work, struct radeon_device, vce.idle_work.work);
+
+	if ((radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE1_INDEX) == 0) &&
+	    (radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE2_INDEX) == 0)) {
+		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+			radeon_dpm_enable_vce(rdev, false);
+		} else {
+			radeon_set_vce_clocks(rdev, 0, 0);
+		}
+	} else {
+		schedule_delayed_work(&rdev->vce.idle_work,
+				      msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
+	}
+}
+
+/**
+ * radeon_vce_note_usage - power up VCE
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Make sure VCE is powerd up when we want to use it
+ */
+void radeon_vce_note_usage(struct radeon_device *rdev)
+{
+	bool streams_changed = false;
+	bool set_clocks = !cancel_delayed_work_sync(&rdev->vce.idle_work);
+	set_clocks &= schedule_delayed_work(&rdev->vce.idle_work,
+					    msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
+
+	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+		/* XXX figure out if the streams changed */
+		streams_changed = false;
+	}
+
+	if (set_clocks || streams_changed) {
+		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+			radeon_dpm_enable_vce(rdev, true);
+		} else {
+			radeon_set_vce_clocks(rdev, 53300, 40000);
+		}
+	}
+}
+
+/**
+ * radeon_vce_free_handles - free still open VCE handles
+ *
+ * @rdev: radeon_device pointer
+ * @filp: drm file pointer
+ *
+ * Close all VCE handles still open by this file pointer
+ */
+void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp)
+{
+	int i, r;
+	for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+		uint32_t handle = atomic_read(&rdev->vce.handles[i]);
+		if (!handle || rdev->vce.filp[i] != filp)
+			continue;
+
+		radeon_vce_note_usage(rdev);
+
+		r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX,
+					       handle, NULL);
+		if (r)
+			DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
+
+		rdev->vce.filp[i] = NULL;
+		atomic_set(&rdev->vce.handles[i], 0);
+	}
+}
+
+/**
+ * radeon_vce_get_create_msg - generate a VCE create msg
+ *
+ * @rdev: radeon_device pointer
+ * @ring: ring we should submit the msg to
+ * @handle: VCE session handle to use
+ * @fence: optional fence to return
+ *
+ * Open up a stream for HW test
+ */
+int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
+			      uint32_t handle, struct radeon_fence **fence)
+{
+	const unsigned ib_size_dw = 1024;
+	struct radeon_ib ib;
+	uint64_t dummy;
+	int i, r;
+
+	r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4);
+	if (r) {
+		DRM_ERROR("radeon: failed to get ib (%d).\n", r);
+		return r;
+	}
+
+	dummy = ib.gpu_addr + 1024;
+
+	/* stitch together an VCE create msg */
+	ib.length_dw = 0;
+	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
+	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
+	ib.ptr[ib.length_dw++] = handle;
+
+	ib.ptr[ib.length_dw++] = 0x00000030; /* len */
+	ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */
+	ib.ptr[ib.length_dw++] = 0x00000000;
+	ib.ptr[ib.length_dw++] = 0x00000042;
+	ib.ptr[ib.length_dw++] = 0x0000000a;
+	ib.ptr[ib.length_dw++] = 0x00000001;
+	ib.ptr[ib.length_dw++] = 0x00000080;
+	ib.ptr[ib.length_dw++] = 0x00000060;
+	ib.ptr[ib.length_dw++] = 0x00000100;
+	ib.ptr[ib.length_dw++] = 0x00000100;
+	ib.ptr[ib.length_dw++] = 0x0000000c;
+	ib.ptr[ib.length_dw++] = 0x00000000;
+
+	ib.ptr[ib.length_dw++] = 0x00000014; /* len */
+	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
+	ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
+	ib.ptr[ib.length_dw++] = dummy;
+	ib.ptr[ib.length_dw++] = 0x00000001;
+
+	for (i = ib.length_dw; i < ib_size_dw; ++i)
+		ib.ptr[i] = 0x0;
+
+	r = radeon_ib_schedule(rdev, &ib, NULL);
+	if (r) {
+	        DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
+	}
+
+	if (fence)
+		*fence = radeon_fence_ref(ib.fence);
+
+	radeon_ib_free(rdev, &ib);
+
+	return r;
+}
+
+/**
+ * radeon_vce_get_destroy_msg - generate a VCE destroy msg
+ *
+ * @rdev: radeon_device pointer
+ * @ring: ring we should submit the msg to
+ * @handle: VCE session handle to use
+ * @fence: optional fence to return
+ *
+ * Close up a stream for HW test or if userspace failed to do so
+ */
+int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
+			       uint32_t handle, struct radeon_fence **fence)
+{
+	const unsigned ib_size_dw = 1024;
+	struct radeon_ib ib;
+	uint64_t dummy;
+	int i, r;
+
+	r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4);
+	if (r) {
+		DRM_ERROR("radeon: failed to get ib (%d).\n", r);
+		return r;
+	}
+
+	dummy = ib.gpu_addr + 1024;
+
+	/* stitch together an VCE destroy msg */
+	ib.length_dw = 0;
+	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
+	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
+	ib.ptr[ib.length_dw++] = handle;
+
+	ib.ptr[ib.length_dw++] = 0x00000014; /* len */
+	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
+	ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
+	ib.ptr[ib.length_dw++] = dummy;
+	ib.ptr[ib.length_dw++] = 0x00000001;
+
+	ib.ptr[ib.length_dw++] = 0x00000008; /* len */
+	ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */
+
+	for (i = ib.length_dw; i < ib_size_dw; ++i)
+		ib.ptr[i] = 0x0;
+
+	r = radeon_ib_schedule(rdev, &ib, NULL);
+	if (r) {
+	        DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
+	}
+
+	if (fence)
+		*fence = radeon_fence_ref(ib.fence);
+
+	radeon_ib_free(rdev, &ib);
+
+	return r;
+}
+
+/**
+ * radeon_vce_cs_reloc - command submission relocation
+ *
+ * @p: parser context
+ * @lo: address of lower dword
+ * @hi: address of higher dword
+ *
+ * Patch relocation inside command stream with real buffer address
+ */
+int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi)
+{
+	struct radeon_cs_chunk *relocs_chunk;
+	uint64_t offset;
+	unsigned idx;
+
+	relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+	offset = radeon_get_ib_value(p, lo);
+	idx = radeon_get_ib_value(p, hi);
+
+	if (idx >= relocs_chunk->length_dw) {
+		DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+			  idx, relocs_chunk->length_dw);
+		return -EINVAL;
+	}
+
+	offset += p->relocs_ptr[(idx / 4)]->lobj.gpu_offset;
+
+        p->ib.ptr[lo] = offset & 0xFFFFFFFF;
+        p->ib.ptr[hi] = offset >> 32;
+
+	return 0;
+}
+
+/**
+ * radeon_vce_cs_parse - parse and validate the command stream
+ *
+ * @p: parser context
+ *
+ */
+int radeon_vce_cs_parse(struct radeon_cs_parser *p)
+{
+	uint32_t handle = 0;
+	bool destroy = false;
+	int i, r;
+
+	while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) {
+		uint32_t len = radeon_get_ib_value(p, p->idx);
+		uint32_t cmd = radeon_get_ib_value(p, p->idx + 1);
+
+		if ((len < 8) || (len & 3)) {
+			DRM_ERROR("invalid VCE command length (%d)!\n", len);
+                	return -EINVAL;
+		}
+
+		switch (cmd) {
+		case 0x00000001: // session
+			handle = radeon_get_ib_value(p, p->idx + 2);
+			break;
+
+		case 0x00000002: // task info
+		case 0x01000001: // create
+		case 0x04000001: // config extension
+		case 0x04000002: // pic control
+		case 0x04000005: // rate control
+		case 0x04000007: // motion estimation
+		case 0x04000008: // rdo
+			break;
+
+		case 0x03000001: // encode
+			r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9);
+			if (r)
+				return r;
+
+			r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11);
+			if (r)
+				return r;
+			break;
+
+		case 0x02000001: // destroy
+			destroy = true;
+			break;
+
+		case 0x05000001: // context buffer
+		case 0x05000004: // video bitstream buffer
+		case 0x05000005: // feedback buffer
+			r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2);
+			if (r)
+				return r;
+			break;
+
+		default:
+			DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
+			return -EINVAL;
+		}
+
+		p->idx += len / 4;
+	}
+
+	if (destroy) {
+		/* IB contains a destroy msg, free the handle */
+		for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
+			atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
+
+		return 0;
+        }
+
+	/* create or encode, validate the handle */
+	for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+		if (atomic_read(&p->rdev->vce.handles[i]) == handle)
+			return 0;
+	}
+
+	/* handle not found try to alloc a new one */
+	for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+		if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
+			p->rdev->vce.filp[i] = p->filp;
+			return 0;
+		}
+	}
+
+	DRM_ERROR("No more free VCE handles!\n");
+	return -EINVAL;
+}
+
+/**
+ * radeon_vce_semaphore_emit - emit a semaphore command
+ *
+ * @rdev: radeon_device pointer
+ * @ring: engine to use
+ * @semaphore: address of semaphore
+ * @emit_wait: true=emit wait, false=emit signal
+ *
+ */
+bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
+			       struct radeon_ring *ring,
+			       struct radeon_semaphore *semaphore,
+			       bool emit_wait)
+{
+	uint64_t addr = semaphore->gpu_addr;
+
+	radeon_ring_write(ring, VCE_CMD_SEMAPHORE);
+	radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
+	radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
+	radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0));
+	if (!emit_wait)
+		radeon_ring_write(ring, VCE_CMD_END);
+
+	return true;
+}
+
+/**
+ * radeon_vce_ib_execute - execute indirect buffer
+ *
+ * @rdev: radeon_device pointer
+ * @ib: the IB to execute
+ *
+ */
+void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	struct radeon_ring *ring = &rdev->ring[ib->ring];
+	radeon_ring_write(ring, VCE_CMD_IB);
+	radeon_ring_write(ring, ib->gpu_addr);
+	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr));
+	radeon_ring_write(ring, ib->length_dw);
+}
+
+/**
+ * radeon_vce_fence_emit - add a fence command to the ring
+ *
+ * @rdev: radeon_device pointer
+ * @fence: the fence
+ *
+ */
+void radeon_vce_fence_emit(struct radeon_device *rdev,
+			   struct radeon_fence *fence)
+{
+	struct radeon_ring *ring = &rdev->ring[fence->ring];
+	uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
+
+	radeon_ring_write(ring, VCE_CMD_FENCE);
+	radeon_ring_write(ring, addr);
+	radeon_ring_write(ring, upper_32_bits(addr));
+	radeon_ring_write(ring, fence->seq);
+	radeon_ring_write(ring, VCE_CMD_TRAP);
+	radeon_ring_write(ring, VCE_CMD_END);
+}
+
+/**
+ * radeon_vce_ring_test - test if VCE ring is working
+ *
+ * @rdev: radeon_device pointer
+ * @ring: the engine to test on
+ *
+ */
+int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+	uint32_t rptr = vce_v1_0_get_rptr(rdev, ring);
+	unsigned i;
+	int r;
+
+	r = radeon_ring_lock(rdev, ring, 16);
+	if (r) {
+		DRM_ERROR("radeon: vce failed to lock ring %d (%d).\n",
+			  ring->idx, r);
+		return r;
+	}
+	radeon_ring_write(ring, VCE_CMD_END);
+	radeon_ring_unlock_commit(rdev, ring);
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+	        if (vce_v1_0_get_rptr(rdev, ring) != rptr)
+	                break;
+	        DRM_UDELAY(1);
+	}
+
+	if (i < rdev->usec_timeout) {
+	        DRM_INFO("ring test on %d succeeded in %d usecs\n",
+	                 ring->idx, i);
+	} else {
+	        DRM_ERROR("radeon: ring %d test failed\n",
+	                  ring->idx);
+	        r = -ETIMEDOUT;
+	}
+
+	return r;
+}
+
+/**
+ * radeon_vce_ib_test - test if VCE IBs are working
+ *
+ * @rdev: radeon_device pointer
+ * @ring: the engine to test on
+ *
+ */
+int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+	struct radeon_fence *fence = NULL;
+	int r;
+
+	r = radeon_vce_get_create_msg(rdev, ring->idx, 1, NULL);
+	if (r) {
+		DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
+		goto error;
+	}
+
+	r = radeon_vce_get_destroy_msg(rdev, ring->idx, 1, &fence);
+	if (r) {
+		DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
+		goto error;
+	}
+
+	r = radeon_fence_wait(fence, false);
+	if (r) {
+		DRM_ERROR("radeon: fence wait failed (%d).\n", r);
+	} else {
+	        DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
+	}
+error:
+	radeon_fence_unref(&fence);
+	return r;
+}
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c
index 8512085b0aef..02f7710de470 100644
--- a/drivers/gpu/drm/radeon/rs780_dpm.c
+++ b/drivers/gpu/drm/radeon/rs780_dpm.c
@@ -807,9 +807,6 @@ static int rs780_parse_power_table(struct radeon_device *rdev)
 				  power_info->pplib.ucNumStates, GFP_KERNEL);
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 
 	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
 		power_state = (union pplib_power_state *)
@@ -859,6 +856,10 @@ int rs780_dpm_init(struct radeon_device *rdev)
 		return -ENOMEM;
 	rdev->pm.dpm.priv = pi;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = rs780_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c
index bebf31c4d841..e7045b085715 100644
--- a/drivers/gpu/drm/radeon/rv6xx_dpm.c
+++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c
@@ -1891,9 +1891,6 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev)
 				  power_info->pplib.ucNumStates, GFP_KERNEL);
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 
 	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
 		power_state = (union pplib_power_state *)
@@ -1943,6 +1940,10 @@ int rv6xx_dpm_init(struct radeon_device *rdev)
 		return -ENOMEM;
 	rdev->pm.dpm.priv = pi;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = rv6xx_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
index b5f63f5e22a3..da041a43d82e 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -2281,9 +2281,6 @@ int rv7xx_parse_power_table(struct radeon_device *rdev)
 				  power_info->pplib.ucNumStates, GFP_KERNEL);
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 
 	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
 		power_state = (union pplib_power_state *)
@@ -2361,6 +2358,10 @@ int rv770_dpm_init(struct radeon_device *rdev)
 	pi->min_vddc_in_table = 0;
 	pi->max_vddc_in_table = 0;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = rv7xx_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 83578324e5d1..8008cb8d5324 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -3434,8 +3434,6 @@ static int si_cp_resume(struct radeon_device *rdev)
 
 	WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
 
-	ring->rptr = RREG32(CP_RB0_RPTR);
-
 	/* ring1  - compute only */
 	/* Set ring buffer size */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
@@ -3460,8 +3458,6 @@ static int si_cp_resume(struct radeon_device *rdev)
 
 	WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
 
-	ring->rptr = RREG32(CP_RB1_RPTR);
-
 	/* ring2 - compute only */
 	/* Set ring buffer size */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
@@ -3486,8 +3482,6 @@ static int si_cp_resume(struct radeon_device *rdev)
 
 	WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
 
-	ring->rptr = RREG32(CP_RB2_RPTR);
-
 	/* start the rings */
 	si_cp_start(rdev);
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
@@ -3872,11 +3866,9 @@ bool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 	if (!(reset_mask & (RADEON_RESET_GFX |
 			    RADEON_RESET_COMPUTE |
 			    RADEON_RESET_CP))) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force CP activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
index 59be2cfcbb47..cf0fdad8c278 100644
--- a/drivers/gpu/drm/radeon/si_dma.c
+++ b/drivers/gpu/drm/radeon/si_dma.c
@@ -49,11 +49,9 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 		mask = RADEON_RESET_DMA1;
 
 	if (!(reset_mask & mask)) {
-		radeon_ring_lockup_update(ring);
+		radeon_ring_lockup_update(rdev, ring);
 		return false;
 	}
-	/* force ring activities */
-	radeon_ring_force_activity(rdev, ring);
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 0a2f5b4bca43..9a3567bedaae 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -6271,9 +6271,6 @@ static int si_parse_power_table(struct radeon_device *rdev)
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
@@ -6350,6 +6347,10 @@ int si_dpm_init(struct radeon_device *rdev)
 	pi->min_vddc_in_table = 0;
 	pi->max_vddc_in_table = 0;
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = si_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 9239a6d29128..683532f84931 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -1798,4 +1798,51 @@
 #define	DMA_PACKET_CONSTANT_FILL			  0xd
 #define	DMA_PACKET_NOP					  0xf
 
+#define VCE_STATUS					0x20004
+#define VCE_VCPU_CNTL					0x20014
+#define		VCE_CLK_EN				(1 << 0)
+#define VCE_VCPU_CACHE_OFFSET0				0x20024
+#define VCE_VCPU_CACHE_SIZE0				0x20028
+#define VCE_VCPU_CACHE_OFFSET1				0x2002c
+#define VCE_VCPU_CACHE_SIZE1				0x20030
+#define VCE_VCPU_CACHE_OFFSET2				0x20034
+#define VCE_VCPU_CACHE_SIZE2				0x20038
+#define VCE_SOFT_RESET					0x20120
+#define 	VCE_ECPU_SOFT_RESET			(1 << 0)
+#define 	VCE_FME_SOFT_RESET			(1 << 2)
+#define VCE_RB_BASE_LO2					0x2016c
+#define VCE_RB_BASE_HI2					0x20170
+#define VCE_RB_SIZE2					0x20174
+#define VCE_RB_RPTR2					0x20178
+#define VCE_RB_WPTR2					0x2017c
+#define VCE_RB_BASE_LO					0x20180
+#define VCE_RB_BASE_HI					0x20184
+#define VCE_RB_SIZE					0x20188
+#define VCE_RB_RPTR					0x2018c
+#define VCE_RB_WPTR					0x20190
+#define VCE_CLOCK_GATING_A				0x202f8
+#define VCE_CLOCK_GATING_B				0x202fc
+#define VCE_UENC_CLOCK_GATING				0x205bc
+#define VCE_UENC_REG_CLOCK_GATING			0x205c0
+#define VCE_FW_REG_STATUS				0x20e10
+#	define VCE_FW_REG_STATUS_BUSY			(1 << 0)
+#	define VCE_FW_REG_STATUS_PASS			(1 << 3)
+#	define VCE_FW_REG_STATUS_DONE			(1 << 11)
+#define VCE_LMI_FW_START_KEYSEL				0x20e18
+#define VCE_LMI_FW_PERIODIC_CTRL			0x20e20
+#define VCE_LMI_CTRL2					0x20e74
+#define VCE_LMI_CTRL					0x20e98
+#define VCE_LMI_VM_CTRL					0x20ea0
+#define VCE_LMI_SWAP_CNTL				0x20eb4
+#define VCE_LMI_SWAP_CNTL1				0x20eb8
+#define VCE_LMI_CACHE_CTRL				0x20ef4
+
+#define VCE_CMD_NO_OP					0x00000000
+#define VCE_CMD_END					0x00000001
+#define VCE_CMD_IB					0x00000002
+#define VCE_CMD_FENCE					0x00000003
+#define VCE_CMD_TRAP					0x00000004
+#define VCE_CMD_IB_AUTO					0x00000005
+#define VCE_CMD_SEMAPHORE				0x00000006
+
 #endif
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
index 8b47b3cd0357..3f0e8d7b8dbe 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.c
+++ b/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -1484,9 +1484,6 @@ static int sumo_parse_power_table(struct radeon_device *rdev)
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
@@ -1772,6 +1769,10 @@ int sumo_dpm_init(struct radeon_device *rdev)
 
 	sumo_construct_boot_and_acpi_state(rdev);
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = sumo_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
index 2da0e17eb960..2a2822c03329 100644
--- a/drivers/gpu/drm/radeon/trinity_dpm.c
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -1694,9 +1694,6 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
@@ -1895,6 +1892,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
 
 	trinity_construct_boot_state(rdev);
 
+	ret = r600_get_platform_caps(rdev);
+	if (ret)
+		return ret;
+
 	ret = trinity_parse_power_table(rdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
index d4a68af1a279..0a243f0e5d68 100644
--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -262,7 +262,7 @@ int uvd_v1_0_start(struct radeon_device *rdev)
 	/* Initialize the ring buffer's read and write pointers */
 	WREG32(UVD_RBC_RB_RPTR, 0x0);
 
-	ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR);
+	ring->wptr = RREG32(UVD_RBC_RB_RPTR);
 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
 
 	/* set the ring address */
diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c
new file mode 100644
index 000000000000..b44d9c842f7b
--- /dev/null
+++ b/drivers/gpu/drm/radeon/vce_v1_0.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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 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, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * Authors: Christian König <christian.koenig@amd.com>
+ */
+
+#include <linux/firmware.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "sid.h"
+
+/**
+ * vce_v1_0_get_rptr - get read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Returns the current hardware read pointer
+ */
+uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
+			   struct radeon_ring *ring)
+{
+	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
+		return RREG32(VCE_RB_RPTR);
+	else
+		return RREG32(VCE_RB_RPTR2);
+}
+
+/**
+ * vce_v1_0_get_wptr - get write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Returns the current hardware write pointer
+ */
+uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
+			   struct radeon_ring *ring)
+{
+	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
+		return RREG32(VCE_RB_WPTR);
+	else
+		return RREG32(VCE_RB_WPTR2);
+}
+
+/**
+ * vce_v1_0_set_wptr - set write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Commits the write pointer to the hardware
+ */
+void vce_v1_0_set_wptr(struct radeon_device *rdev,
+		       struct radeon_ring *ring)
+{
+	if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
+		WREG32(VCE_RB_WPTR, ring->wptr);
+	else
+		WREG32(VCE_RB_WPTR2, ring->wptr);
+}
+
+/**
+ * vce_v1_0_start - start VCE block
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Setup and start the VCE block
+ */
+int vce_v1_0_start(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int i, j, r;
+
+	/* set BUSY flag */
+	WREG32_P(VCE_STATUS, 1, ~1);
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	WREG32(VCE_RB_RPTR, ring->wptr);
+	WREG32(VCE_RB_WPTR, ring->wptr);
+	WREG32(VCE_RB_BASE_LO, ring->gpu_addr);
+	WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32(VCE_RB_SIZE, ring->ring_size / 4);
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	WREG32(VCE_RB_RPTR2, ring->wptr);
+	WREG32(VCE_RB_WPTR2, ring->wptr);
+	WREG32(VCE_RB_BASE_LO2, ring->gpu_addr);
+	WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
+	WREG32(VCE_RB_SIZE2, ring->ring_size / 4);
+
+	WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN);
+
+	WREG32_P(VCE_SOFT_RESET,
+		 VCE_ECPU_SOFT_RESET |
+		 VCE_FME_SOFT_RESET, ~(
+		 VCE_ECPU_SOFT_RESET |
+		 VCE_FME_SOFT_RESET));
+
+	mdelay(100);
+
+	WREG32_P(VCE_SOFT_RESET, 0, ~(
+		 VCE_ECPU_SOFT_RESET |
+		 VCE_FME_SOFT_RESET));
+
+	for (i = 0; i < 10; ++i) {
+		uint32_t status;
+		for (j = 0; j < 100; ++j) {
+			status = RREG32(VCE_STATUS);
+			if (status & 2)
+				break;
+			mdelay(10);
+		}
+		r = 0;
+		if (status & 2)
+			break;
+
+		DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
+		WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET);
+		mdelay(10);
+		WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET);
+		mdelay(10);
+		r = -1;
+	}
+
+	/* clear BUSY flag */
+	WREG32_P(VCE_STATUS, 0, ~1);
+
+	if (r) {
+		DRM_ERROR("VCE not responding, giving up!!!\n");
+		return r;
+	}
+
+	return 0;
+}
+
+int vce_v1_0_init(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	r = vce_v1_0_start(rdev);
+	if (r)
+		return r;
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	ring->ready = true;
+	r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring);
+	if (r) {
+		ring->ready = false;
+		return r;
+	}
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	ring->ready = true;
+	r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring);
+	if (r) {
+		ring->ready = false;
+		return r;
+	}
+
+	DRM_INFO("VCE initialized successfully.\n");
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/radeon/vce_v2_0.c b/drivers/gpu/drm/radeon/vce_v2_0.c
new file mode 100644
index 000000000000..1ac7bb825a1b
--- /dev/null
+++ b/drivers/gpu/drm/radeon/vce_v2_0.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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 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, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * Authors: Christian König <christian.koenig@amd.com>
+ */
+
+#include <linux/firmware.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "cikd.h"
+
+static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated)
+{
+	u32 tmp;
+
+	if (gated) {
+		tmp = RREG32(VCE_CLOCK_GATING_B);
+		tmp |= 0xe70000;
+		WREG32(VCE_CLOCK_GATING_B, tmp);
+
+		tmp = RREG32(VCE_UENC_CLOCK_GATING);
+		tmp |= 0xff000000;
+		WREG32(VCE_UENC_CLOCK_GATING, tmp);
+
+		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
+		tmp &= ~0x3fc;
+		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
+
+		WREG32(VCE_CGTT_CLK_OVERRIDE, 0);
+    } else {
+		tmp = RREG32(VCE_CLOCK_GATING_B);
+		tmp |= 0xe7;
+		tmp &= ~0xe70000;
+		WREG32(VCE_CLOCK_GATING_B, tmp);
+
+		tmp = RREG32(VCE_UENC_CLOCK_GATING);
+		tmp |= 0x1fe000;
+		tmp &= ~0xff000000;
+		WREG32(VCE_UENC_CLOCK_GATING, tmp);
+
+		tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
+		tmp |= 0x3fc;
+		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
+	}
+}
+
+static void vce_v2_0_set_dyn_cg(struct radeon_device *rdev, bool gated)
+{
+	u32 orig, tmp;
+
+	tmp = RREG32(VCE_CLOCK_GATING_B);
+	tmp &= ~0x00060006;
+	if (gated) {
+		tmp |= 0xe10000;
+	} else {
+		tmp |= 0xe1;
+		tmp &= ~0xe10000;
+	}
+	WREG32(VCE_CLOCK_GATING_B, tmp);
+
+	orig = tmp = RREG32(VCE_UENC_CLOCK_GATING);
+	tmp &= ~0x1fe000;
+	tmp &= ~0xff000000;
+	if (tmp != orig)
+		WREG32(VCE_UENC_CLOCK_GATING, tmp);
+
+	orig = tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
+	tmp &= ~0x3fc;
+	if (tmp != orig)
+		WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
+
+	if (gated)
+		WREG32(VCE_CGTT_CLK_OVERRIDE, 0);
+}
+
+static void vce_v2_0_disable_cg(struct radeon_device *rdev)
+{
+	WREG32(VCE_CGTT_CLK_OVERRIDE, 7);
+}
+
+void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable)
+{
+	bool sw_cg = false;
+
+	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) {
+		if (sw_cg)
+			vce_v2_0_set_sw_cg(rdev, true);
+		else
+			vce_v2_0_set_dyn_cg(rdev, true);
+	} else {
+		vce_v2_0_disable_cg(rdev);
+
+		if (sw_cg)
+			vce_v2_0_set_sw_cg(rdev, false);
+		else
+			vce_v2_0_set_dyn_cg(rdev, false);
+	}
+}
+
+static void vce_v2_0_init_cg(struct radeon_device *rdev)
+{
+	u32 tmp;
+
+	tmp = RREG32(VCE_CLOCK_GATING_A);
+	tmp &= ~(CGC_CLK_GATE_DLY_TIMER_MASK | CGC_CLK_GATER_OFF_DLY_TIMER_MASK);
+	tmp |= (CGC_CLK_GATE_DLY_TIMER(0) | CGC_CLK_GATER_OFF_DLY_TIMER(4));
+	tmp |= CGC_UENC_WAIT_AWAKE;
+	WREG32(VCE_CLOCK_GATING_A, tmp);
+
+	tmp = RREG32(VCE_UENC_CLOCK_GATING);
+	tmp &= ~(CLOCK_ON_DELAY_MASK | CLOCK_OFF_DELAY_MASK);
+	tmp |= (CLOCK_ON_DELAY(0) | CLOCK_OFF_DELAY(4));
+	WREG32(VCE_UENC_CLOCK_GATING, tmp);
+
+	tmp = RREG32(VCE_CLOCK_GATING_B);
+	tmp |= 0x10;
+	tmp &= ~0x100000;
+	WREG32(VCE_CLOCK_GATING_B, tmp);
+}
+
+int vce_v2_0_resume(struct radeon_device *rdev)
+{
+	uint64_t addr = rdev->vce.gpu_addr;
+	uint32_t size;
+
+	WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16));
+	WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
+	WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
+	WREG32(VCE_CLOCK_GATING_B, 0xf7);
+
+	WREG32(VCE_LMI_CTRL, 0x00398000);
+	WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1);
+	WREG32(VCE_LMI_SWAP_CNTL, 0);
+	WREG32(VCE_LMI_SWAP_CNTL1, 0);
+	WREG32(VCE_LMI_VM_CTRL, 0);
+
+	size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size);
+	WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
+	WREG32(VCE_VCPU_CACHE_SIZE0, size);
+
+	addr += size;
+	size = RADEON_VCE_STACK_SIZE;
+	WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
+	WREG32(VCE_VCPU_CACHE_SIZE1, size);
+
+	addr += size;
+	size = RADEON_VCE_HEAP_SIZE;
+	WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
+	WREG32(VCE_VCPU_CACHE_SIZE2, size);
+
+	WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100);
+
+	WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN,
+		 ~VCE_SYS_INT_TRAP_INTERRUPT_EN);
+
+	vce_v2_0_init_cg(rdev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 8d220afbd85f..d43f21bb4596 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -11,6 +11,8 @@ tegra-drm-y := \
 	hdmi.o \
 	mipi-phy.o \
 	dsi.o \
+	sor.o \
+	dpaux.o \
 	gr2d.o \
 	gr3d.o
 
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3c2c0ea1cd87..c94101494826 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -118,6 +118,7 @@
 #define DC_DISP_DISP_WIN_OPTIONS		0x402
 #define HDMI_ENABLE (1 << 30)
 #define DSI_ENABLE  (1 << 29)
+#define SOR_ENABLE  (1 << 25)
 
 #define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403
 #define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
new file mode 100644
index 000000000000..d536ed381fbd
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2013 NVIDIA 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_panel.h>
+
+#include "dpaux.h"
+#include "drm.h"
+
+static DEFINE_MUTEX(dpaux_lock);
+static LIST_HEAD(dpaux_list);
+
+struct tegra_dpaux {
+	struct drm_dp_aux aux;
+	struct device *dev;
+
+	void __iomem *regs;
+	int irq;
+
+	struct tegra_output *output;
+
+	struct reset_control *rst;
+	struct clk *clk_parent;
+	struct clk *clk;
+
+	struct regulator *vdd;
+
+	struct completion complete;
+	struct list_head list;
+};
+
+static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
+{
+	return container_of(aux, struct tegra_dpaux, aux);
+}
+
+static inline unsigned long tegra_dpaux_readl(struct tegra_dpaux *dpaux,
+					      unsigned long offset)
+{
+	return readl(dpaux->regs + (offset << 2));
+}
+
+static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
+				      unsigned long value,
+				      unsigned long offset)
+{
+	writel(value, dpaux->regs + (offset << 2));
+}
+
+static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
+				   size_t size)
+{
+	unsigned long offset = DPAUX_DP_AUXDATA_WRITE(0);
+	size_t i, j;
+
+	for (i = 0; i < size; i += 4) {
+		size_t num = min_t(size_t, size - i, 4);
+		unsigned long value = 0;
+
+		for (j = 0; j < num; j++)
+			value |= buffer[i + j] << (j * 8);
+
+		tegra_dpaux_writel(dpaux, value, offset++);
+	}
+}
+
+static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
+				  size_t size)
+{
+	unsigned long offset = DPAUX_DP_AUXDATA_READ(0);
+	size_t i, j;
+
+	for (i = 0; i < size; i += 4) {
+		size_t num = min_t(size_t, size - i, 4);
+		unsigned long value;
+
+		value = tegra_dpaux_readl(dpaux, offset++);
+
+		for (j = 0; j < num; j++)
+			buffer[i + j] = value >> (j * 8);
+	}
+}
+
+static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
+				    struct drm_dp_aux_msg *msg)
+{
+	unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ;
+	unsigned long timeout = msecs_to_jiffies(250);
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
+	unsigned long status;
+	ssize_t ret = 0;
+
+	if (msg->size < 1 || msg->size > 16)
+		return -EINVAL;
+
+	tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
+
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_I2C_WRITE:
+		if (msg->request & DP_AUX_I2C_MOT)
+			value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
+		else
+			value = DPAUX_DP_AUXCTL_CMD_I2C_WR;
+
+		break;
+
+	case DP_AUX_I2C_READ:
+		if (msg->request & DP_AUX_I2C_MOT)
+			value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
+		else
+			value = DPAUX_DP_AUXCTL_CMD_I2C_RD;
+
+		break;
+
+	case DP_AUX_I2C_STATUS:
+		if (msg->request & DP_AUX_I2C_MOT)
+			value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
+		else
+			value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;
+
+		break;
+
+	case DP_AUX_NATIVE_WRITE:
+		value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
+		break;
+
+	case DP_AUX_NATIVE_READ:
+		value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
+	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
+
+	if ((msg->request & DP_AUX_I2C_READ) == 0) {
+		tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
+		ret = msg->size;
+	}
+
+	/* start transaction */
+	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
+	value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
+	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
+
+	status = wait_for_completion_timeout(&dpaux->complete, timeout);
+	if (!status)
+		return -ETIMEDOUT;
+
+	/* read status and clear errors */
+	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
+	tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);
+
+	if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
+		return -ETIMEDOUT;
+
+	if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
+	    (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
+	    (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
+		return -EIO;
+
+	switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
+	case 0x00:
+		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+		break;
+
+	case 0x01:
+		msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+		break;
+
+	case 0x02:
+		msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+		break;
+
+	case 0x04:
+		msg->reply = DP_AUX_I2C_REPLY_NACK;
+		break;
+
+	case 0x08:
+		msg->reply = DP_AUX_I2C_REPLY_DEFER;
+		break;
+	}
+
+	if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
+		if (msg->request & DP_AUX_I2C_READ) {
+			size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
+
+			if (WARN_ON(count != msg->size))
+				count = min_t(size_t, count, msg->size);
+
+			tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
+			ret = count;
+		}
+	}
+
+	return ret;
+}
+
+static irqreturn_t tegra_dpaux_irq(int irq, void *data)
+{
+	struct tegra_dpaux *dpaux = data;
+	irqreturn_t ret = IRQ_HANDLED;
+	unsigned long value;
+
+	/* clear interrupts */
+	value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
+	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
+
+	if (value & DPAUX_INTR_PLUG_EVENT) {
+		if (dpaux->output) {
+			drm_helper_hpd_irq_event(dpaux->output->connector.dev);
+		}
+	}
+
+	if (value & DPAUX_INTR_UNPLUG_EVENT) {
+		if (dpaux->output)
+			drm_helper_hpd_irq_event(dpaux->output->connector.dev);
+	}
+
+	if (value & DPAUX_INTR_IRQ_EVENT) {
+		/* TODO: handle this */
+	}
+
+	if (value & DPAUX_INTR_AUX_DONE)
+		complete(&dpaux->complete);
+
+	return ret;
+}
+
+static int tegra_dpaux_probe(struct platform_device *pdev)
+{
+	struct tegra_dpaux *dpaux;
+	struct resource *regs;
+	unsigned long value;
+	int err;
+
+	dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
+	if (!dpaux)
+		return -ENOMEM;
+
+	init_completion(&dpaux->complete);
+	INIT_LIST_HEAD(&dpaux->list);
+	dpaux->dev = &pdev->dev;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
+	if (IS_ERR(dpaux->regs))
+		return PTR_ERR(dpaux->regs);
+
+	dpaux->irq = platform_get_irq(pdev, 0);
+	if (dpaux->irq < 0) {
+		dev_err(&pdev->dev, "failed to get IRQ\n");
+		return -ENXIO;
+	}
+
+	dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
+	if (IS_ERR(dpaux->rst))
+		return PTR_ERR(dpaux->rst);
+
+	dpaux->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dpaux->clk))
+		return PTR_ERR(dpaux->clk);
+
+	err = clk_prepare_enable(dpaux->clk);
+	if (err < 0)
+		return err;
+
+	reset_control_deassert(dpaux->rst);
+
+	dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
+	if (IS_ERR(dpaux->clk_parent))
+		return PTR_ERR(dpaux->clk_parent);
+
+	err = clk_prepare_enable(dpaux->clk_parent);
+	if (err < 0)
+		return err;
+
+	err = clk_set_rate(dpaux->clk_parent, 270000000);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
+			err);
+		return err;
+	}
+
+	dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(dpaux->vdd))
+		return PTR_ERR(dpaux->vdd);
+
+	err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
+			       dev_name(dpaux->dev), dpaux);
+	if (err < 0) {
+		dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
+			dpaux->irq, err);
+		return err;
+	}
+
+	dpaux->aux.transfer = tegra_dpaux_transfer;
+	dpaux->aux.dev = &pdev->dev;
+
+	err = drm_dp_aux_register_i2c_bus(&dpaux->aux);
+	if (err < 0)
+		return err;
+
+	/* enable and clear all interrupts */
+	value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
+		DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
+	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
+	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
+
+	mutex_lock(&dpaux_lock);
+	list_add_tail(&dpaux->list, &dpaux_list);
+	mutex_unlock(&dpaux_lock);
+
+	platform_set_drvdata(pdev, dpaux);
+
+	return 0;
+}
+
+static int tegra_dpaux_remove(struct platform_device *pdev)
+{
+	struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
+
+	drm_dp_aux_unregister_i2c_bus(&dpaux->aux);
+
+	mutex_lock(&dpaux_lock);
+	list_del(&dpaux->list);
+	mutex_unlock(&dpaux_lock);
+
+	clk_disable_unprepare(dpaux->clk_parent);
+	reset_control_assert(dpaux->rst);
+	clk_disable_unprepare(dpaux->clk);
+
+	return 0;
+}
+
+static const struct of_device_id tegra_dpaux_of_match[] = {
+	{ .compatible = "nvidia,tegra124-dpaux", },
+	{ },
+};
+
+struct platform_driver tegra_dpaux_driver = {
+	.driver = {
+		.name = "tegra-dpaux",
+		.of_match_table = tegra_dpaux_of_match,
+	},
+	.probe = tegra_dpaux_probe,
+	.remove = tegra_dpaux_remove,
+};
+
+struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
+{
+	struct tegra_dpaux *dpaux;
+
+	mutex_lock(&dpaux_lock);
+
+	list_for_each_entry(dpaux, &dpaux_list, list)
+		if (np == dpaux->dev->of_node) {
+			mutex_unlock(&dpaux_lock);
+			return dpaux;
+		}
+
+	mutex_unlock(&dpaux_lock);
+
+	return NULL;
+}
+
+int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
+{
+	unsigned long timeout;
+	int err;
+
+	dpaux->output = output;
+
+	err = regulator_enable(dpaux->vdd);
+	if (err < 0)
+		return err;
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		enum drm_connector_status status;
+
+		status = tegra_dpaux_detect(dpaux);
+		if (status == connector_status_connected)
+			return 0;
+
+		usleep_range(1000, 2000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
+{
+	unsigned long timeout;
+	int err;
+
+	err = regulator_disable(dpaux->vdd);
+	if (err < 0)
+		return err;
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		enum drm_connector_status status;
+
+		status = tegra_dpaux_detect(dpaux);
+		if (status == connector_status_disconnected) {
+			dpaux->output = NULL;
+			return 0;
+		}
+
+		usleep_range(1000, 2000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
+{
+	unsigned long value;
+
+	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
+
+	if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
+		return connector_status_connected;
+
+	return connector_status_disconnected;
+}
+
+int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
+{
+	unsigned long value;
+
+	value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
+		DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
+		DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
+		DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
+		DPAUX_HYBRID_PADCTL_MODE_AUX;
+	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
+
+	value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
+	value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
+	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
+
+	return 0;
+}
+
+int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
+{
+	unsigned long value;
+
+	value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
+	value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
+	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
+
+	return 0;
+}
+
+int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
+{
+	int err;
+
+	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+				 encoding);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
+		      u8 pattern)
+{
+	u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
+	u8 status[DP_LINK_STATUS_SIZE], values[4];
+	unsigned int i;
+	int err;
+
+	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern);
+	if (err < 0)
+		return err;
+
+	if (tp == DP_TRAINING_PATTERN_DISABLE)
+		return 0;
+
+	for (i = 0; i < link->num_lanes; i++)
+		values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
+			    DP_TRAIN_PRE_EMPHASIS_0 |
+			    DP_TRAIN_MAX_SWING_REACHED |
+			    DP_TRAIN_VOLTAGE_SWING_400;
+
+	err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values,
+				link->num_lanes);
+	if (err < 0)
+		return err;
+
+	usleep_range(500, 1000);
+
+	err = drm_dp_dpcd_read_link_status(&dpaux->aux, status);
+	if (err < 0)
+		return err;
+
+	switch (tp) {
+	case DP_TRAINING_PATTERN_1:
+		if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
+			return -EAGAIN;
+
+		break;
+
+	case DP_TRAINING_PATTERN_2:
+		if (!drm_dp_channel_eq_ok(status, link->num_lanes))
+			return -EAGAIN;
+
+		break;
+
+	default:
+		dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
+		return -EINVAL;
+	}
+
+	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h
new file mode 100644
index 000000000000..4f5bf10fdff9
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 NVIDIA 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.
+ */
+
+#ifndef DRM_TEGRA_DPAUX_H
+#define DRM_TEGRA_DPAUX_H
+
+#define DPAUX_CTXSW 0x00
+
+#define DPAUX_INTR_EN_AUX 0x01
+#define DPAUX_INTR_AUX 0x05
+#define DPAUX_INTR_AUX_DONE (1 << 3)
+#define DPAUX_INTR_IRQ_EVENT (1 << 2)
+#define DPAUX_INTR_UNPLUG_EVENT (1 << 1)
+#define DPAUX_INTR_PLUG_EVENT (1 << 0)
+
+#define DPAUX_DP_AUXDATA_WRITE(x) (0x09 + ((x) << 2))
+#define DPAUX_DP_AUXDATA_READ(x) (0x19 + ((x) << 2))
+#define DPAUX_DP_AUXADDR 0x29
+
+#define DPAUX_DP_AUXCTL 0x2d
+#define DPAUX_DP_AUXCTL_TRANSACTREQ (1 << 16)
+#define DPAUX_DP_AUXCTL_CMD_AUX_RD (9 << 12)
+#define DPAUX_DP_AUXCTL_CMD_AUX_WR (8 << 12)
+#define DPAUX_DP_AUXCTL_CMD_MOT_RQ (6 << 12)
+#define DPAUX_DP_AUXCTL_CMD_MOT_RD (5 << 12)
+#define DPAUX_DP_AUXCTL_CMD_MOT_WR (4 << 12)
+#define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12)
+#define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12)
+#define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12)
+#define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)
+
+#define DPAUX_DP_AUXSTAT 0x31
+#define DPAUX_DP_AUXSTAT_HPD_STATUS (1 << 28)
+#define DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK (0xf0000)
+#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR (1 << 11)
+#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR (1 << 10)
+#define DPAUX_DP_AUXSTAT_RX_ERROR (1 << 9)
+#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR (1 << 8)
+#define DPAUX_DP_AUXSTAT_REPLY_MASK (0xff)
+
+#define DPAUX_DP_AUX_SINKSTAT_LO 0x35
+#define DPAUX_DP_AUX_SINKSTAT_HI 0x39
+
+#define DPAUX_HPD_CONFIG 0x3d
+#define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME(x) (((x) & 0xffff) << 16)
+#define DPAUX_HPD_CONFIG_PLUG_MIN_TIME(x) ((x) & 0xffff)
+
+#define DPAUX_HPD_IRQ_CONFIG 0x41
+#define DPAUX_HPD_IRQ_CONFIG_MIN_LOW_TIME(x) ((x) & 0xffff)
+
+#define DPAUX_DP_AUX_CONFIG 0x45
+
+#define DPAUX_HYBRID_PADCTL 0x49
+#define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12)
+#define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8)
+#define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2)
+#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV (1 << 1)
+#define DPAUX_HYBRID_PADCTL_MODE_I2C (1 << 0)
+#define DPAUX_HYBRID_PADCTL_MODE_AUX (0 << 0)
+
+#define DPAUX_HYBRID_SPARE 0x4d
+#define DPAUX_HYBRID_SPARE_PAD_POWER_DOWN (1 << 0)
+
+#define DPAUX_SCRATCH_REG0 0x51
+#define DPAUX_SCRATCH_REG1 0x55
+#define DPAUX_SCRATCH_REG2 0x59
+
+#endif
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index c71594754f46..6f5b6e2f552e 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -665,6 +665,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra114-hdmi", },
 	{ .compatible = "nvidia,tegra114-gr3d", },
 	{ .compatible = "nvidia,tegra124-dc", },
+	{ .compatible = "nvidia,tegra124-sor", },
 	{ /* sentinel */ }
 };
 
@@ -691,14 +692,22 @@ static int __init host1x_drm_init(void)
 	if (err < 0)
 		goto unregister_dc;
 
-	err = platform_driver_register(&tegra_hdmi_driver);
+	err = platform_driver_register(&tegra_sor_driver);
 	if (err < 0)
 		goto unregister_dsi;
 
-	err = platform_driver_register(&tegra_gr2d_driver);
+	err = platform_driver_register(&tegra_hdmi_driver);
+	if (err < 0)
+		goto unregister_sor;
+
+	err = platform_driver_register(&tegra_dpaux_driver);
 	if (err < 0)
 		goto unregister_hdmi;
 
+	err = platform_driver_register(&tegra_gr2d_driver);
+	if (err < 0)
+		goto unregister_dpaux;
+
 	err = platform_driver_register(&tegra_gr3d_driver);
 	if (err < 0)
 		goto unregister_gr2d;
@@ -707,8 +716,12 @@ static int __init host1x_drm_init(void)
 
 unregister_gr2d:
 	platform_driver_unregister(&tegra_gr2d_driver);
+unregister_dpaux:
+	platform_driver_unregister(&tegra_dpaux_driver);
 unregister_hdmi:
 	platform_driver_unregister(&tegra_hdmi_driver);
+unregister_sor:
+	platform_driver_unregister(&tegra_sor_driver);
 unregister_dsi:
 	platform_driver_unregister(&tegra_dsi_driver);
 unregister_dc:
@@ -723,7 +736,9 @@ static void __exit host1x_drm_exit(void)
 {
 	platform_driver_unregister(&tegra_gr3d_driver);
 	platform_driver_unregister(&tegra_gr2d_driver);
+	platform_driver_unregister(&tegra_dpaux_driver);
 	platform_driver_unregister(&tegra_hdmi_driver);
+	platform_driver_unregister(&tegra_sor_driver);
 	platform_driver_unregister(&tegra_dsi_driver);
 	platform_driver_unregister(&tegra_dc_driver);
 	host1x_driver_unregister(&host1x_drm_driver);
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index bf1cac7658f8..126332c3ecbb 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -179,12 +179,14 @@ struct tegra_output_ops {
 	int (*check_mode)(struct tegra_output *output,
 			  struct drm_display_mode *mode,
 			  enum drm_mode_status *status);
+	enum drm_connector_status (*detect)(struct tegra_output *output);
 };
 
 enum tegra_output_type {
 	TEGRA_OUTPUT_RGB,
 	TEGRA_OUTPUT_HDMI,
 	TEGRA_OUTPUT_DSI,
+	TEGRA_OUTPUT_EDP,
 };
 
 struct tegra_output {
@@ -265,6 +267,22 @@ extern int tegra_output_remove(struct tegra_output *output);
 extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
 extern int tegra_output_exit(struct tegra_output *output);
 
+/* from dpaux.c */
+
+struct tegra_dpaux;
+struct drm_dp_link;
+struct drm_dp_aux;
+
+struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np);
+enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux);
+int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output);
+int tegra_dpaux_detach(struct tegra_dpaux *dpaux);
+int tegra_dpaux_enable(struct tegra_dpaux *dpaux);
+int tegra_dpaux_disable(struct tegra_dpaux *dpaux);
+int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding);
+int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
+		      u8 pattern);
+
 /* from fb.c */
 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
 				    unsigned int index);
@@ -278,7 +296,9 @@ extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 
 extern struct platform_driver tegra_dc_driver;
 extern struct platform_driver tegra_dsi_driver;
+extern struct platform_driver tegra_sor_driver;
 extern struct platform_driver tegra_hdmi_driver;
+extern struct platform_driver tegra_dpaux_driver;
 extern struct platform_driver tegra_gr2d_driver;
 extern struct platform_driver tegra_gr3d_driver;
 
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index ef853e558036..29913eb9b25d 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -394,6 +394,18 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
 	return -EINVAL;
 }
 
+static void *tegra_gem_prime_vmap(struct dma_buf *buf)
+{
+	struct drm_gem_object *gem = buf->priv;
+	struct tegra_bo *bo = to_tegra_bo(gem);
+
+	return bo->vaddr;
+}
+
+static void tegra_gem_prime_vunmap(struct dma_buf *buf, void *vaddr)
+{
+}
+
 static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
 	.map_dma_buf = tegra_gem_prime_map_dma_buf,
 	.unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
@@ -403,6 +415,8 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
 	.kmap = tegra_gem_prime_kmap,
 	.kunmap = tegra_gem_prime_kunmap,
 	.mmap = tegra_gem_prime_mmap,
+	.vmap = tegra_gem_prime_vmap,
+	.vunmap = tegra_gem_prime_vunmap,
 };
 
 struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 57cecbd18ca8..a3e4f1eca6f7 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -77,6 +77,9 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
 	struct tegra_output *output = connector_to_output(connector);
 	enum drm_connector_status status = connector_status_unknown;
 
+	if (output->ops->detect)
+		return output->ops->detect(output);
+
 	if (gpio_is_valid(output->hpd_gpio)) {
 		if (gpio_get_value(output->hpd_gpio) == 0)
 			status = connector_status_disconnected;
@@ -292,6 +295,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
 		encoder = DRM_MODE_ENCODER_DSI;
 		break;
 
+	case TEGRA_OUTPUT_EDP:
+		connector = DRM_MODE_CONNECTOR_eDP;
+		encoder = DRM_MODE_ENCODER_TMDS;
+		break;
+
 	default:
 		connector = DRM_MODE_CONNECTOR_Unknown;
 		encoder = DRM_MODE_ENCODER_NONE;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
new file mode 100644
index 000000000000..49ef5729f435
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (C) 2013 NVIDIA 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/tegra-powergate.h>
+
+#include <drm/drm_dp_helper.h>
+
+#include "dc.h"
+#include "drm.h"
+#include "sor.h"
+
+struct tegra_sor {
+	struct host1x_client client;
+	struct tegra_output output;
+	struct device *dev;
+
+	void __iomem *regs;
+
+	struct reset_control *rst;
+	struct clk *clk_parent;
+	struct clk *clk_safe;
+	struct clk *clk_dp;
+	struct clk *clk;
+
+	struct tegra_dpaux *dpaux;
+
+	bool enabled;
+};
+
+static inline struct tegra_sor *
+host1x_client_to_sor(struct host1x_client *client)
+{
+	return container_of(client, struct tegra_sor, client);
+}
+
+static inline struct tegra_sor *to_sor(struct tegra_output *output)
+{
+	return container_of(output, struct tegra_sor, output);
+}
+
+static inline unsigned long tegra_sor_readl(struct tegra_sor *sor,
+					    unsigned long offset)
+{
+	return readl(sor->regs + (offset << 2));
+}
+
+static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value,
+				    unsigned long offset)
+{
+	writel(value, sor->regs + (offset << 2));
+}
+
+static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
+				   struct drm_dp_link *link)
+{
+	unsigned long value;
+	unsigned int i;
+	u8 pattern;
+	int err;
+
+	/* setup lane parameters */
+	value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
+		SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
+		SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
+		SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
+	tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT_0);
+
+	value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
+		SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
+		SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
+		SOR_LANE_PREEMPHASIS_LANE0(0x0f);
+	tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS_0);
+
+	value = SOR_LANE_POST_CURSOR_LANE3(0x00) |
+		SOR_LANE_POST_CURSOR_LANE2(0x00) |
+		SOR_LANE_POST_CURSOR_LANE1(0x00) |
+		SOR_LANE_POST_CURSOR_LANE0(0x00);
+	tegra_sor_writel(sor, value, SOR_LANE_POST_CURSOR_0);
+
+	/* disable LVDS mode */
+	tegra_sor_writel(sor, 0, SOR_LVDS);
+
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value |= SOR_DP_PADCTL_TX_PU_ENABLE;
+	value &= ~SOR_DP_PADCTL_TX_PU_MASK;
+	value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
+		 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	usleep_range(10, 100);
+
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
+		   SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
+	if (err < 0)
+		return err;
+
+	for (i = 0, value = 0; i < link->num_lanes; i++) {
+		unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+				     SOR_DP_TPG_SCRAMBLER_NONE |
+				     SOR_DP_TPG_PATTERN_TRAIN1;
+		value = (value << 8) | lane;
+	}
+
+	tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+	pattern = DP_TRAINING_PATTERN_1;
+
+	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	if (err < 0)
+		return err;
+
+	value = tegra_sor_readl(sor, SOR_DP_SPARE_0);
+	value |= SOR_DP_SPARE_SEQ_ENABLE;
+	value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
+	value |= SOR_DP_SPARE_MACRO_SOR_CLK;
+	tegra_sor_writel(sor, value, SOR_DP_SPARE_0);
+
+	for (i = 0, value = 0; i < link->num_lanes; i++) {
+		unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+				     SOR_DP_TPG_SCRAMBLER_NONE |
+				     SOR_DP_TPG_PATTERN_TRAIN2;
+		value = (value << 8) | lane;
+	}
+
+	tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+	pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
+
+	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	if (err < 0)
+		return err;
+
+	for (i = 0, value = 0; i < link->num_lanes; i++) {
+		unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+				     SOR_DP_TPG_SCRAMBLER_GALIOS |
+				     SOR_DP_TPG_PATTERN_NONE;
+		value = (value << 8) | lane;
+	}
+
+	tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+	pattern = DP_TRAINING_PATTERN_DISABLE;
+
+	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static void tegra_sor_super_update(struct tegra_sor *sor)
+{
+	tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
+	tegra_sor_writel(sor, 1, SOR_SUPER_STATE_0);
+	tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
+}
+
+static void tegra_sor_update(struct tegra_sor *sor)
+{
+	tegra_sor_writel(sor, 0, SOR_STATE_0);
+	tegra_sor_writel(sor, 1, SOR_STATE_0);
+	tegra_sor_writel(sor, 0, SOR_STATE_0);
+}
+
+static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
+{
+	unsigned long value;
+
+	value = tegra_sor_readl(sor, SOR_PWM_DIV);
+	value &= ~SOR_PWM_DIV_MASK;
+	value |= 0x400; /* period */
+	tegra_sor_writel(sor, value, SOR_PWM_DIV);
+
+	value = tegra_sor_readl(sor, SOR_PWM_CTL);
+	value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
+	value |= 0x400; /* duty cycle */
+	value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
+	value |= SOR_PWM_CTL_TRIGGER;
+	tegra_sor_writel(sor, value, SOR_PWM_CTL);
+
+	timeout = jiffies + msecs_to_jiffies(timeout);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_PWM_CTL);
+		if ((value & SOR_PWM_CTL_TRIGGER) == 0)
+			return 0;
+
+		usleep_range(25, 100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int tegra_sor_attach(struct tegra_sor *sor)
+{
+	unsigned long value, timeout;
+
+	/* wake up in normal mode */
+	value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
+	value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
+	value |= SOR_SUPER_STATE_MODE_NORMAL;
+	tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
+	tegra_sor_super_update(sor);
+
+	/* attach */
+	value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
+	value |= SOR_SUPER_STATE_ATTACHED;
+	tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
+	tegra_sor_super_update(sor);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_TEST);
+		if ((value & SOR_TEST_ATTACHED) != 0)
+			return 0;
+
+		usleep_range(25, 100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int tegra_sor_wakeup(struct tegra_sor *sor)
+{
+	struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
+	unsigned long value, timeout;
+
+	/* enable display controller outputs */
+	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+	value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+		 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	/* wait for head to wake up */
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_TEST);
+		value &= SOR_TEST_HEAD_MODE_MASK;
+
+		if (value == SOR_TEST_HEAD_MODE_AWAKE)
+			return 0;
+
+		usleep_range(25, 100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
+{
+	unsigned long value;
+
+	value = tegra_sor_readl(sor, SOR_PWR);
+	value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
+	tegra_sor_writel(sor, value, SOR_PWR);
+
+	timeout = jiffies + msecs_to_jiffies(timeout);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_PWR);
+		if ((value & SOR_PWR_TRIGGER) == 0)
+			return 0;
+
+		usleep_range(25, 100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int tegra_output_sor_enable(struct tegra_output *output)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+	struct drm_display_mode *mode = &dc->base.mode;
+	unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
+	struct tegra_sor *sor = to_sor(output);
+	unsigned long value;
+	int err;
+
+	if (sor->enabled)
+		return 0;
+
+	err = clk_prepare_enable(sor->clk);
+	if (err < 0)
+		return err;
+
+	reset_control_deassert(sor->rst);
+
+	if (sor->dpaux) {
+		err = tegra_dpaux_enable(sor->dpaux);
+		if (err < 0)
+			dev_err(sor->dev, "failed to enable DP: %d\n", err);
+	}
+
+	err = clk_set_parent(sor->clk, sor->clk_safe);
+	if (err < 0)
+		dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
+
+	value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
+	value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
+	value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
+	tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+	usleep_range(20, 100);
+
+	value = tegra_sor_readl(sor, SOR_PLL_3);
+	value |= SOR_PLL_3_PLL_VDD_MODE_V3_3;
+	tegra_sor_writel(sor, value, SOR_PLL_3);
+
+	value = SOR_PLL_0_ICHPMP(0xf) | SOR_PLL_0_VCOCAP_RST |
+		SOR_PLL_0_PLLREG_LEVEL_V45 | SOR_PLL_0_RESISTOR_EXT;
+	tegra_sor_writel(sor, value, SOR_PLL_0);
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value |= SOR_PLL_2_SEQ_PLLCAPPD;
+	value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
+	value |= SOR_PLL_2_LVDS_ENABLE;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	value = SOR_PLL_1_TERM_COMPOUT | SOR_PLL_1_TMDS_TERM;
+	tegra_sor_writel(sor, value, SOR_PLL_1);
+
+	while (true) {
+		value = tegra_sor_readl(sor, SOR_PLL_2);
+		if ((value & SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE) == 0)
+			break;
+
+		usleep_range(250, 1000);
+	}
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value &= ~SOR_PLL_2_POWERDOWN_OVERRIDE;
+	value &= ~SOR_PLL_2_PORT_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	/*
+	 * power up
+	 */
+
+	/* set safe link bandwidth (1.62 Gbps) */
+	value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
+	value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
+	value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
+	tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
+
+	/* step 1 */
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL_2_PORT_POWERDOWN |
+		 SOR_PLL_2_BANDGAP_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	value = tegra_sor_readl(sor, SOR_PLL_0);
+	value |= SOR_PLL_0_VCOPD | SOR_PLL_0_POWER_OFF;
+	tegra_sor_writel(sor, value, SOR_PLL_0);
+
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	/* step 2 */
+	err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to power on I/O rail: %d\n", err);
+		return err;
+	}
+
+	usleep_range(5, 100);
+
+	/* step 3 */
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	usleep_range(20, 100);
+
+	/* step 4 */
+	value = tegra_sor_readl(sor, SOR_PLL_0);
+	value &= ~SOR_PLL_0_POWER_OFF;
+	value &= ~SOR_PLL_0_VCOPD;
+	tegra_sor_writel(sor, value, SOR_PLL_0);
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	usleep_range(200, 1000);
+
+	/* step 5 */
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value &= ~SOR_PLL_2_PORT_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	/* switch to DP clock */
+	err = clk_set_parent(sor->clk, sor->clk_dp);
+	if (err < 0)
+		dev_err(sor->dev, "failed to set DP parent clock: %d\n", err);
+
+	/* power dplanes (XXX parameterize based on link?) */
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
+		 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
+	value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
+	value |= SOR_DP_LINKCTL_LANE_COUNT(4);
+	tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
+
+	/* start lane sequencer */
+	value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
+		SOR_LANE_SEQ_CTL_POWER_STATE_UP;
+	tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
+
+	while (true) {
+		value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
+		if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
+			break;
+
+		usleep_range(250, 1000);
+	}
+
+	/* set link bandwidth (2.7 GHz, XXX: parameterize based on link?) */
+	value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
+	value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
+	value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
+	tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
+
+	/* set linkctl */
+	value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
+	value |= SOR_DP_LINKCTL_ENABLE;
+
+	value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
+	value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */
+
+	value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
+	tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
+
+	for (i = 0, value = 0; i < 4; i++) {
+		unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+				     SOR_DP_TPG_SCRAMBLER_GALIOS |
+				     SOR_DP_TPG_PATTERN_NONE;
+		value = (value << 8) | lane;
+	}
+
+	tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+	value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
+	value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
+	value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */
+
+	value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
+	value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */
+
+	value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
+	value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */
+
+	value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */
+
+	value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
+	value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
+	tegra_sor_writel(sor, value, SOR_DP_CONFIG_0);
+
+	value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
+	value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
+	value |= 137; /* XXX: don't hardcode? */
+	tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
+
+	value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
+	value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
+	value |= 2368; /* XXX: don't hardcode? */
+	tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
+
+	/* enable pad calibration logic */
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value |= SOR_DP_PADCTL_PAD_CAL_PD;
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	if (sor->dpaux) {
+		/* FIXME: properly convert to struct drm_dp_aux */
+		struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
+		struct drm_dp_link link;
+		u8 rate, lanes;
+
+		err = drm_dp_link_probe(aux, &link);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to probe eDP link: %d\n",
+				err);
+			return err;
+		}
+
+		err = drm_dp_link_power_up(aux, &link);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to power up eDP link: %d\n",
+				err);
+			return err;
+		}
+
+		err = drm_dp_link_configure(aux, &link);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to configure eDP link: %d\n",
+				err);
+			return err;
+		}
+
+		rate = drm_dp_link_rate_to_bw_code(link.rate);
+		lanes = link.num_lanes;
+
+		value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
+		value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
+		value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
+		tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
+
+		value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
+		value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
+		value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
+
+		if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
+			value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
+
+		tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
+
+		/* disable training pattern generator */
+
+		for (i = 0; i < link.num_lanes; i++) {
+			unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+					     SOR_DP_TPG_SCRAMBLER_GALIOS |
+					     SOR_DP_TPG_PATTERN_NONE;
+			value = (value << 8) | lane;
+		}
+
+		tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+		err = tegra_sor_dp_train_fast(sor, &link);
+		if (err < 0) {
+			dev_err(sor->dev, "DP fast link training failed: %d\n",
+				err);
+			return err;
+		}
+
+		dev_dbg(sor->dev, "fast link training succeeded\n");
+	}
+
+	err = tegra_sor_power_up(sor, 250);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to power up SOR: %d\n", err);
+		return err;
+	}
+
+	/* start display controller in continuous mode */
+	value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
+	value |= WRITE_MUX;
+	tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
+
+	tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
+	tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
+
+	value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
+	value &= ~WRITE_MUX;
+	tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
+
+	/*
+	 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
+	 * raster, associate with display controller)
+	 */
+	value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 |
+		SOR_STATE_ASY_VSYNCPOL |
+		SOR_STATE_ASY_HSYNCPOL |
+		SOR_STATE_ASY_PROTOCOL_DP_A |
+		SOR_STATE_ASY_CRC_MODE_COMPLETE |
+		SOR_STATE_ASY_OWNER(dc->pipe + 1);
+	tegra_sor_writel(sor, value, SOR_STATE_1);
+
+	/*
+	 * TODO: The video timing programming below doesn't seem to match the
+	 * register definitions.
+	 */
+
+	value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
+	tegra_sor_writel(sor, value, SOR_HEAD_STATE_1(0));
+
+	vse = mode->vsync_end - mode->vsync_start - 1;
+	hse = mode->hsync_end - mode->hsync_start - 1;
+
+	value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
+	tegra_sor_writel(sor, value, SOR_HEAD_STATE_2(0));
+
+	vbe = vse + (mode->vsync_start - mode->vdisplay);
+	hbe = hse + (mode->hsync_start - mode->hdisplay);
+
+	value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
+	tegra_sor_writel(sor, value, SOR_HEAD_STATE_3(0));
+
+	vbs = vbe + mode->vdisplay;
+	hbs = hbe + mode->hdisplay;
+
+	value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
+	tegra_sor_writel(sor, value, SOR_HEAD_STATE_4(0));
+
+	/* XXX interlaced mode */
+	tegra_sor_writel(sor, 0x00000001, SOR_HEAD_STATE_5(0));
+
+	/* CSTM (LVDS, link A/B, upper) */
+	value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_B | SOR_CSTM_LINK_ACT_B |
+		SOR_CSTM_UPPER;
+	tegra_sor_writel(sor, value, SOR_CSTM);
+
+	/* PWM setup */
+	err = tegra_sor_setup_pwm(sor, 250);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to setup PWM: %d\n", err);
+		return err;
+	}
+
+	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+	value |= SOR_ENABLE;
+	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+	tegra_sor_update(sor);
+
+	err = tegra_sor_attach(sor);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to attach SOR: %d\n", err);
+		return err;
+	}
+
+	err = tegra_sor_wakeup(sor);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to enable DC: %d\n", err);
+		return err;
+	}
+
+	sor->enabled = true;
+
+	return 0;
+}
+
+static int tegra_sor_detach(struct tegra_sor *sor)
+{
+	unsigned long value, timeout;
+
+	/* switch to safe mode */
+	value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
+	value &= ~SOR_SUPER_STATE_MODE_NORMAL;
+	tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
+	tegra_sor_super_update(sor);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_PWR);
+		if (value & SOR_PWR_MODE_SAFE)
+			break;
+	}
+
+	if ((value & SOR_PWR_MODE_SAFE) == 0)
+		return -ETIMEDOUT;
+
+	/* go to sleep */
+	value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
+	value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
+	tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
+	tegra_sor_super_update(sor);
+
+	/* detach */
+	value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
+	value &= ~SOR_SUPER_STATE_ATTACHED;
+	tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
+	tegra_sor_super_update(sor);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_TEST);
+		if ((value & SOR_TEST_ATTACHED) == 0)
+			break;
+
+		usleep_range(25, 100);
+	}
+
+	if ((value & SOR_TEST_ATTACHED) != 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int tegra_sor_power_down(struct tegra_sor *sor)
+{
+	unsigned long value, timeout;
+	int err;
+
+	value = tegra_sor_readl(sor, SOR_PWR);
+	value &= ~SOR_PWR_NORMAL_STATE_PU;
+	value |= SOR_PWR_TRIGGER;
+	tegra_sor_writel(sor, value, SOR_PWR);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_PWR);
+		if ((value & SOR_PWR_TRIGGER) == 0)
+			return 0;
+
+		usleep_range(25, 100);
+	}
+
+	if ((value & SOR_PWR_TRIGGER) != 0)
+		return -ETIMEDOUT;
+
+	err = clk_set_parent(sor->clk, sor->clk_safe);
+	if (err < 0)
+		dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
+
+	value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
+	value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
+		   SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
+	tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
+
+	/* stop lane sequencer */
+	value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
+		SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
+	tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
+
+	timeout = jiffies + msecs_to_jiffies(250);
+
+	while (time_before(jiffies, timeout)) {
+		value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
+		if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
+			break;
+
+		usleep_range(25, 100);
+	}
+
+	if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
+		return -ETIMEDOUT;
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value |= SOR_PLL_2_PORT_POWERDOWN;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	usleep_range(20, 100);
+
+	value = tegra_sor_readl(sor, SOR_PLL_0);
+	value |= SOR_PLL_0_POWER_OFF;
+	value |= SOR_PLL_0_VCOPD;
+	tegra_sor_writel(sor, value, SOR_PLL_0);
+
+	value = tegra_sor_readl(sor, SOR_PLL_2);
+	value |= SOR_PLL_2_SEQ_PLLCAPPD;
+	value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
+	tegra_sor_writel(sor, value, SOR_PLL_2);
+
+	usleep_range(20, 100);
+
+	return 0;
+}
+
+static int tegra_output_sor_disable(struct tegra_output *output)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+	struct tegra_sor *sor = to_sor(output);
+	unsigned long value;
+	int err;
+
+	if (!sor->enabled)
+		return 0;
+
+	err = tegra_sor_detach(sor);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to detach SOR: %d\n", err);
+		return err;
+	}
+
+	tegra_sor_writel(sor, 0, SOR_STATE_1);
+	tegra_sor_update(sor);
+
+	/*
+	 * The following accesses registers of the display controller, so make
+	 * sure it's only executed when the output is attached to one.
+	 */
+	if (dc) {
+		/*
+		 * XXX: We can't do this here because it causes the SOR to go
+		 * into an erroneous state and the output will look scrambled
+		 * the next time it is enabled. Presumably this is because we
+		 * should be doing this only on the next VBLANK. A possible
+		 * solution would be to queue a "power-off" event to trigger
+		 * this code to be run during the next VBLANK.
+		 */
+		/*
+		value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+		value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+			   PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
+		tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+		*/
+
+		value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+		value &= ~DISP_CTRL_MODE_MASK;
+		tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+		value &= ~SOR_ENABLE;
+		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+		tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+		tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+	}
+
+	err = tegra_sor_power_down(sor);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to power down SOR: %d\n", err);
+		return err;
+	}
+
+	if (sor->dpaux) {
+		err = tegra_dpaux_disable(sor->dpaux);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to disable DP: %d\n", err);
+			return err;
+		}
+	}
+
+	err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to power off I/O rail: %d\n", err);
+		return err;
+	}
+
+	reset_control_assert(sor->rst);
+	clk_disable_unprepare(sor->clk);
+
+	sor->enabled = false;
+
+	return 0;
+}
+
+static int tegra_output_sor_setup_clock(struct tegra_output *output,
+					struct clk *clk, unsigned long pclk)
+{
+	struct tegra_sor *sor = to_sor(output);
+	int err;
+
+	/* round to next MHz */
+	pclk = DIV_ROUND_UP(pclk / 2, 1000000) * 1000000;
+
+	err = clk_set_parent(clk, sor->clk_parent);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to set parent clock: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_rate(sor->clk_parent, pclk);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to set base clock rate to %lu Hz\n",
+			pclk * 2);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_output_sor_check_mode(struct tegra_output *output,
+				       struct drm_display_mode *mode,
+				       enum drm_mode_status *status)
+{
+	/*
+	 * FIXME: For now, always assume that the mode is okay.
+	 */
+
+	*status = MODE_OK;
+
+	return 0;
+}
+
+static enum drm_connector_status
+tegra_output_sor_detect(struct tegra_output *output)
+{
+	struct tegra_sor *sor = to_sor(output);
+
+	if (sor->dpaux)
+		return tegra_dpaux_detect(sor->dpaux);
+
+	return connector_status_unknown;
+}
+
+static const struct tegra_output_ops sor_ops = {
+	.enable = tegra_output_sor_enable,
+	.disable = tegra_output_sor_disable,
+	.setup_clock = tegra_output_sor_setup_clock,
+	.check_mode = tegra_output_sor_check_mode,
+	.detect = tegra_output_sor_detect,
+};
+
+static int tegra_sor_init(struct host1x_client *client)
+{
+	struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+	struct tegra_sor *sor = host1x_client_to_sor(client);
+	int err;
+
+	if (!sor->dpaux)
+		return -ENODEV;
+
+	sor->output.type = TEGRA_OUTPUT_EDP;
+
+	sor->output.dev = sor->dev;
+	sor->output.ops = &sor_ops;
+
+	err = tegra_output_init(tegra->drm, &sor->output);
+	if (err < 0) {
+		dev_err(sor->dev, "output setup failed: %d\n", err);
+		return err;
+	}
+
+	if (sor->dpaux) {
+		err = tegra_dpaux_attach(sor->dpaux, &sor->output);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to attach DP: %d\n", err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int tegra_sor_exit(struct host1x_client *client)
+{
+	struct tegra_sor *sor = host1x_client_to_sor(client);
+	int err;
+
+	err = tegra_output_disable(&sor->output);
+	if (err < 0) {
+		dev_err(sor->dev, "output failed to disable: %d\n", err);
+		return err;
+	}
+
+	if (sor->dpaux) {
+		err = tegra_dpaux_detach(sor->dpaux);
+		if (err < 0) {
+			dev_err(sor->dev, "failed to detach DP: %d\n", err);
+			return err;
+		}
+	}
+
+	err = tegra_output_exit(&sor->output);
+	if (err < 0) {
+		dev_err(sor->dev, "output cleanup failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct host1x_client_ops sor_client_ops = {
+	.init = tegra_sor_init,
+	.exit = tegra_sor_exit,
+};
+
+static int tegra_sor_probe(struct platform_device *pdev)
+{
+	struct device_node *np;
+	struct tegra_sor *sor;
+	struct resource *regs;
+	int err;
+
+	sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
+	if (!sor)
+		return -ENOMEM;
+
+	sor->output.dev = sor->dev = &pdev->dev;
+
+	np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
+	if (np) {
+		sor->dpaux = tegra_dpaux_find_by_of_node(np);
+		of_node_put(np);
+
+		if (!sor->dpaux)
+			return -EPROBE_DEFER;
+	}
+
+	err = tegra_output_probe(&sor->output);
+	if (err < 0)
+		return err;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sor->regs = devm_ioremap_resource(&pdev->dev, regs);
+	if (IS_ERR(sor->regs))
+		return PTR_ERR(sor->regs);
+
+	sor->rst = devm_reset_control_get(&pdev->dev, "sor");
+	if (IS_ERR(sor->rst))
+		return PTR_ERR(sor->rst);
+
+	sor->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(sor->clk))
+		return PTR_ERR(sor->clk);
+
+	sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
+	if (IS_ERR(sor->clk_parent))
+		return PTR_ERR(sor->clk_parent);
+
+	err = clk_prepare_enable(sor->clk_parent);
+	if (err < 0)
+		return err;
+
+	sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
+	if (IS_ERR(sor->clk_safe))
+		return PTR_ERR(sor->clk_safe);
+
+	err = clk_prepare_enable(sor->clk_safe);
+	if (err < 0)
+		return err;
+
+	sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
+	if (IS_ERR(sor->clk_dp))
+		return PTR_ERR(sor->clk_dp);
+
+	err = clk_prepare_enable(sor->clk_dp);
+	if (err < 0)
+		return err;
+
+	INIT_LIST_HEAD(&sor->client.list);
+	sor->client.ops = &sor_client_ops;
+	sor->client.dev = &pdev->dev;
+
+	err = host1x_client_register(&sor->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, sor);
+
+	return 0;
+}
+
+static int tegra_sor_remove(struct platform_device *pdev)
+{
+	struct tegra_sor *sor = platform_get_drvdata(pdev);
+	int err;
+
+	err = host1x_client_unregister(&sor->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	clk_disable_unprepare(sor->clk_parent);
+	clk_disable_unprepare(sor->clk_safe);
+	clk_disable_unprepare(sor->clk_dp);
+	clk_disable_unprepare(sor->clk);
+
+	return 0;
+}
+
+static const struct of_device_id tegra_sor_of_match[] = {
+	{ .compatible = "nvidia,tegra124-sor", },
+	{ },
+};
+
+struct platform_driver tegra_sor_driver = {
+	.driver = {
+		.name = "tegra-sor",
+		.of_match_table = tegra_sor_of_match,
+	},
+	.probe = tegra_sor_probe,
+	.remove = tegra_sor_remove,
+};
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
new file mode 100644
index 000000000000..f4156d54cd05
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2013 NVIDIA 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.
+ */
+
+#ifndef DRM_TEGRA_SOR_H
+#define DRM_TEGRA_SOR_H
+
+#define SOR_CTXSW 0x00
+
+#define SOR_SUPER_STATE_0 0x01
+
+#define SOR_SUPER_STATE_1 0x02
+#define  SOR_SUPER_STATE_ATTACHED		(1 << 3)
+#define  SOR_SUPER_STATE_MODE_NORMAL		(1 << 2)
+#define  SOR_SUPER_STATE_HEAD_MODE_MASK		(3 << 0)
+#define  SOR_SUPER_STATE_HEAD_MODE_AWAKE	(2 << 0)
+#define  SOR_SUPER_STATE_HEAD_MODE_SNOOZE	(1 << 0)
+#define  SOR_SUPER_STATE_HEAD_MODE_SLEEP	(0 << 0)
+
+#define SOR_STATE_0 0x03
+
+#define SOR_STATE_1 0x04
+#define  SOR_STATE_ASY_PIXELDEPTH_MASK		(0xf << 17)
+#define  SOR_STATE_ASY_PIXELDEPTH_BPP_18_444	(0x2 << 17)
+#define  SOR_STATE_ASY_PIXELDEPTH_BPP_24_444	(0x5 << 17)
+#define  SOR_STATE_ASY_VSYNCPOL			(1 << 13)
+#define  SOR_STATE_ASY_HSYNCPOL			(1 << 12)
+#define  SOR_STATE_ASY_PROTOCOL_MASK		(0xf << 8)
+#define  SOR_STATE_ASY_PROTOCOL_CUSTOM		(0xf << 8)
+#define  SOR_STATE_ASY_PROTOCOL_DP_A		(0x8 << 8)
+#define  SOR_STATE_ASY_PROTOCOL_DP_B		(0x9 << 8)
+#define  SOR_STATE_ASY_PROTOCOL_LVDS		(0x0 << 8)
+#define  SOR_STATE_ASY_CRC_MODE_MASK		(0x3 << 6)
+#define  SOR_STATE_ASY_CRC_MODE_NON_ACTIVE	(0x2 << 6)
+#define  SOR_STATE_ASY_CRC_MODE_COMPLETE	(0x1 << 6)
+#define  SOR_STATE_ASY_CRC_MODE_ACTIVE		(0x0 << 6)
+#define  SOR_STATE_ASY_OWNER(x)			(((x) & 0xf) << 0)
+
+#define SOR_HEAD_STATE_0(x) (0x05 + (x))
+#define SOR_HEAD_STATE_1(x) (0x07 + (x))
+#define SOR_HEAD_STATE_2(x) (0x09 + (x))
+#define SOR_HEAD_STATE_3(x) (0x0b + (x))
+#define SOR_HEAD_STATE_4(x) (0x0d + (x))
+#define SOR_HEAD_STATE_5(x) (0x0f + (x))
+#define SOR_CRC_CNTRL 0x11
+#define SOR_DP_DEBUG_MVID 0x12
+
+#define SOR_CLK_CNTRL 0x13
+#define  SOR_CLK_CNTRL_DP_LINK_SPEED_MASK	(0x1f << 2)
+#define  SOR_CLK_CNTRL_DP_LINK_SPEED(x)		(((x) & 0x1f) << 2)
+#define  SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62	(0x06 << 2)
+#define  SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70	(0x0a << 2)
+#define  SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40	(0x14 << 2)
+#define  SOR_CLK_CNTRL_DP_CLK_SEL_MASK		(3 << 0)
+#define  SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK	(0 << 0)
+#define  SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK	(1 << 0)
+#define  SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK	(2 << 0)
+#define  SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK	(3 << 0)
+
+#define SOR_CAP 0x14
+
+#define SOR_PWR 0x15
+#define  SOR_PWR_TRIGGER			(1 << 31)
+#define  SOR_PWR_MODE_SAFE			(1 << 28)
+#define  SOR_PWR_NORMAL_STATE_PU		(1 << 0)
+
+#define SOR_TEST 0x16
+#define  SOR_TEST_ATTACHED			(1 << 10)
+#define  SOR_TEST_HEAD_MODE_MASK		(3 << 8)
+#define  SOR_TEST_HEAD_MODE_AWAKE		(2 << 8)
+
+#define SOR_PLL_0 0x17
+#define  SOR_PLL_0_ICHPMP_MASK			(0xf << 24)
+#define  SOR_PLL_0_ICHPMP(x)			(((x) & 0xf) << 24)
+#define  SOR_PLL_0_VCOCAP_MASK			(0xf << 8)
+#define  SOR_PLL_0_VCOCAP(x)			(((x) & 0xf) << 8)
+#define  SOR_PLL_0_VCOCAP_RST			SOR_PLL_0_VCOCAP(3)
+#define  SOR_PLL_0_PLLREG_MASK			(0x3 << 6)
+#define  SOR_PLL_0_PLLREG_LEVEL(x)		(((x) & 0x3) << 6)
+#define  SOR_PLL_0_PLLREG_LEVEL_V25		SOR_PLL_0_PLLREG_LEVEL(0)
+#define  SOR_PLL_0_PLLREG_LEVEL_V15		SOR_PLL_0_PLLREG_LEVEL(1)
+#define  SOR_PLL_0_PLLREG_LEVEL_V35		SOR_PLL_0_PLLREG_LEVEL(2)
+#define  SOR_PLL_0_PLLREG_LEVEL_V45		SOR_PLL_0_PLLREG_LEVEL(3)
+#define  SOR_PLL_0_PULLDOWN			(1 << 5)
+#define  SOR_PLL_0_RESISTOR_EXT			(1 << 4)
+#define  SOR_PLL_0_VCOPD			(1 << 2)
+#define  SOR_PLL_0_POWER_OFF			(1 << 0)
+
+#define SOR_PLL_1 0x18
+/* XXX: read-only bit? */
+#define  SOR_PLL_1_TERM_COMPOUT			(1 << 15)
+#define  SOR_PLL_1_TMDS_TERM			(1 << 8)
+
+#define SOR_PLL_2 0x19
+#define  SOR_PLL_2_LVDS_ENABLE			(1 << 25)
+#define  SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE		(1 << 24)
+#define  SOR_PLL_2_PORT_POWERDOWN		(1 << 23)
+#define  SOR_PLL_2_BANDGAP_POWERDOWN		(1 << 22)
+#define  SOR_PLL_2_POWERDOWN_OVERRIDE		(1 << 18)
+#define  SOR_PLL_2_SEQ_PLLCAPPD			(1 << 17)
+
+#define SOR_PLL_3 0x1a
+#define  SOR_PLL_3_PLL_VDD_MODE_V1_8 (0 << 13)
+#define  SOR_PLL_3_PLL_VDD_MODE_V3_3 (1 << 13)
+
+#define SOR_CSTM 0x1b
+#define  SOR_CSTM_LVDS				(1 << 16)
+#define  SOR_CSTM_LINK_ACT_B			(1 << 15)
+#define  SOR_CSTM_LINK_ACT_A			(1 << 14)
+#define  SOR_CSTM_UPPER				(1 << 11)
+
+#define SOR_LVDS 0x1c
+#define SOR_CRC_A 0x1d
+#define SOR_CRC_B 0x1e
+#define SOR_BLANK 0x1f
+#define SOR_SEQ_CTL 0x20
+
+#define SOR_LANE_SEQ_CTL 0x21
+#define  SOR_LANE_SEQ_CTL_TRIGGER		(1 << 31)
+#define  SOR_LANE_SEQ_CTL_SEQUENCE_UP		(0 << 20)
+#define  SOR_LANE_SEQ_CTL_SEQUENCE_DOWN		(1 << 20)
+#define  SOR_LANE_SEQ_CTL_POWER_STATE_UP	(0 << 16)
+#define  SOR_LANE_SEQ_CTL_POWER_STATE_DOWN	(1 << 16)
+
+#define SOR_SEQ_INST(x) (0x22 + (x))
+
+#define SOR_PWM_DIV 0x32
+#define  SOR_PWM_DIV_MASK			0xffffff
+
+#define SOR_PWM_CTL 0x33
+#define  SOR_PWM_CTL_TRIGGER			(1 << 31)
+#define  SOR_PWM_CTL_CLK_SEL			(1 << 30)
+#define  SOR_PWM_CTL_DUTY_CYCLE_MASK		0xffffff
+
+#define SOR_VCRC_A_0 0x34
+#define SOR_VCRC_A_1 0x35
+#define SOR_VCRC_B_0 0x36
+#define SOR_VCRC_B_1 0x37
+#define SOR_CCRC_A_0 0x38
+#define SOR_CCRC_A_1 0x39
+#define SOR_CCRC_B_0 0x3a
+#define SOR_CCRC_B_1 0x3b
+#define SOR_EDATA_A_0 0x3c
+#define SOR_EDATA_A_1 0x3d
+#define SOR_EDATA_B_0 0x3e
+#define SOR_EDATA_B_1 0x3f
+#define SOR_COUNT_A_0 0x40
+#define SOR_COUNT_A_1 0x41
+#define SOR_COUNT_B_0 0x42
+#define SOR_COUNT_B_1 0x43
+#define SOR_DEBUG_A_0 0x44
+#define SOR_DEBUG_A_1 0x45
+#define SOR_DEBUG_B_0 0x46
+#define SOR_DEBUG_B_1 0x47
+#define SOR_TRIG 0x48
+#define SOR_MSCHECK 0x49
+#define SOR_XBAR_CTRL 0x4a
+#define SOR_XBAR_POL 0x4b
+
+#define SOR_DP_LINKCTL_0 0x4c
+#define  SOR_DP_LINKCTL_LANE_COUNT_MASK		(0x1f << 16)
+#define  SOR_DP_LINKCTL_LANE_COUNT(x)		(((1 << (x)) - 1) << 16)
+#define  SOR_DP_LINKCTL_ENHANCED_FRAME		(1 << 14)
+#define  SOR_DP_LINKCTL_TU_SIZE_MASK		(0x7f << 2)
+#define  SOR_DP_LINKCTL_TU_SIZE(x)		(((x) & 0x7f) << 2)
+#define  SOR_DP_LINKCTL_ENABLE			(1 << 0)
+
+#define SOR_DP_LINKCTL_1 0x4d
+
+#define SOR_LANE_DRIVE_CURRENT_0 0x4e
+#define SOR_LANE_DRIVE_CURRENT_1 0x4f
+#define SOR_LANE4_DRIVE_CURRENT_0 0x50
+#define SOR_LANE4_DRIVE_CURRENT_1 0x51
+#define  SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24)
+#define  SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16)
+#define  SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8)
+#define  SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0)
+
+#define SOR_LANE_PREEMPHASIS_0 0x52
+#define SOR_LANE_PREEMPHASIS_1 0x53
+#define SOR_LANE4_PREEMPHASIS_0 0x54
+#define SOR_LANE4_PREEMPHASIS_1 0x55
+#define  SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24)
+#define  SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16)
+#define  SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8)
+#define  SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0)
+
+#define SOR_LANE_POST_CURSOR_0 0x56
+#define SOR_LANE_POST_CURSOR_1 0x57
+#define  SOR_LANE_POST_CURSOR_LANE3(x) (((x) & 0xff) << 24)
+#define  SOR_LANE_POST_CURSOR_LANE2(x) (((x) & 0xff) << 16)
+#define  SOR_LANE_POST_CURSOR_LANE1(x) (((x) & 0xff) << 8)
+#define  SOR_LANE_POST_CURSOR_LANE0(x) (((x) & 0xff) << 0)
+
+#define SOR_DP_CONFIG_0 0x58
+#define SOR_DP_CONFIG_DISPARITY_NEGATIVE	(1 << 31)
+#define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE		(1 << 26)
+#define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY	(1 << 24)
+#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK	(0xf << 16)
+#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC(x)	(((x) & 0xf) << 16)
+#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK	(0x7f << 8)
+#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT(x)	(((x) & 0x7f) << 8)
+#define SOR_DP_CONFIG_WATERMARK_MASK	(0x3f << 0)
+#define SOR_DP_CONFIG_WATERMARK(x)	(((x) & 0x3f) << 0)
+
+#define SOR_DP_CONFIG_1 0x59
+#define SOR_DP_MN_0 0x5a
+#define SOR_DP_MN_1 0x5b
+
+#define SOR_DP_PADCTL_0 0x5c
+#define  SOR_DP_PADCTL_PAD_CAL_PD	(1 << 23)
+#define  SOR_DP_PADCTL_TX_PU_ENABLE	(1 << 22)
+#define  SOR_DP_PADCTL_TX_PU_MASK	(0xff << 8)
+#define  SOR_DP_PADCTL_TX_PU(x)		(((x) & 0xff) << 8)
+#define  SOR_DP_PADCTL_CM_TXD_3		(1 << 7)
+#define  SOR_DP_PADCTL_CM_TXD_2		(1 << 6)
+#define  SOR_DP_PADCTL_CM_TXD_1		(1 << 5)
+#define  SOR_DP_PADCTL_CM_TXD_0		(1 << 4)
+#define  SOR_DP_PADCTL_PD_TXD_3		(1 << 3)
+#define  SOR_DP_PADCTL_PD_TXD_0		(1 << 2)
+#define  SOR_DP_PADCTL_PD_TXD_1		(1 << 1)
+#define  SOR_DP_PADCTL_PD_TXD_2		(1 << 0)
+
+#define SOR_DP_PADCTL_1 0x5d
+
+#define SOR_DP_DEBUG_0 0x5e
+#define SOR_DP_DEBUG_1 0x5f
+
+#define SOR_DP_SPARE_0 0x60
+#define  SOR_DP_SPARE_MACRO_SOR_CLK	(1 << 2)
+#define  SOR_DP_SPARE_PANEL_INTERNAL	(1 << 1)
+#define  SOR_DP_SPARE_SEQ_ENABLE	(1 << 0)
+
+#define SOR_DP_SPARE_1 0x61
+#define SOR_DP_AUDIO_CTRL 0x62
+
+#define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63
+#define SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x01ffff << 0)
+
+#define SOR_DP_AUDIO_VBLANK_SYMBOLS 0x64
+#define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0)
+
+#define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_0 0x66
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_1 0x67
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_2 0x68
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_3 0x69
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_4 0x6a
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_5 0x6b
+#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_6 0x6c
+
+#define SOR_DP_TPG 0x6d
+#define  SOR_DP_TPG_CHANNEL_CODING	(1 << 6)
+#define  SOR_DP_TPG_SCRAMBLER_MASK	(3 << 4)
+#define  SOR_DP_TPG_SCRAMBLER_FIBONACCI	(2 << 4)
+#define  SOR_DP_TPG_SCRAMBLER_GALIOS	(1 << 4)
+#define  SOR_DP_TPG_SCRAMBLER_NONE	(0 << 4)
+#define  SOR_DP_TPG_PATTERN_MASK	(0xf << 0)
+#define  SOR_DP_TPG_PATTERN_HBR2	(0x8 << 0)
+#define  SOR_DP_TPG_PATTERN_CSTM	(0x7 << 0)
+#define  SOR_DP_TPG_PATTERN_PRBS7	(0x6 << 0)
+#define  SOR_DP_TPG_PATTERN_SBLERRRATE	(0x5 << 0)
+#define  SOR_DP_TPG_PATTERN_D102	(0x4 << 0)
+#define  SOR_DP_TPG_PATTERN_TRAIN3	(0x3 << 0)
+#define  SOR_DP_TPG_PATTERN_TRAIN2	(0x2 << 0)
+#define  SOR_DP_TPG_PATTERN_TRAIN1	(0x1 << 0)
+#define  SOR_DP_TPG_PATTERN_NONE	(0x0 << 0)
+
+#define SOR_DP_TPG_CONFIG 0x6e
+#define SOR_DP_LQ_CSTM_0 0x6f
+#define SOR_DP_LQ_CSTM_1 0x70
+#define SOR_DP_LQ_CSTM_2 0x71
+
+#endif
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index bfb09d802abd..b10550ee1d89 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -102,6 +102,7 @@ u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)
 {
 	return (u32)atomic_add_return(incrs, &sp->max_val);
 }
+EXPORT_SYMBOL(host1x_syncpt_incr_max);
 
  /*
  * Write cached syncpoint and waitbase values to hardware.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f7220011a00b..7af9d0b5dea1 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -175,6 +175,15 @@ config HID_PRODIKEYS
 	  multimedia keyboard, but will lack support for the musical keyboard
 	  and some additional multimedia keys.
 
+config HID_CP2112
+	tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
+	depends on USB_HID && I2C && GPIOLIB
+	---help---
+	Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
+	This is a HID device driver which registers as an i2c adapter
+	and gpiochip to expose these functions of the CP2112. The
+	customizable USB descriptor fields are exposed as sysfs attributes.
+
 config HID_CYPRESS
 	tristate "Cypress mouse and barcode readers" if EXPERT
 	depends on HID
@@ -608,25 +617,27 @@ config HID_SAMSUNG
 	Support for Samsung InfraRed remote control or keyboards.
 
 config HID_SONY
-	tristate "Sony PS2/3 accessories"
+	tristate "Sony PS2/3/4 accessories"
 	depends on USB_HID
 	depends on NEW_LEDS
 	depends on LEDS_CLASS
+	select POWER_SUPPLY
 	---help---
 	Support for
 
 	  * Sony PS3 6-axis controllers
+	  * Sony PS4 DualShock 4 controllers
 	  * Buzz controllers
 	  * Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
 	  * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
 
 config SONY_FF
-	bool "Sony PS2/3 accessories force feedback support"
+	bool "Sony PS2/3/4 accessories force feedback support" 
 	depends on HID_SONY
 	select INPUT_FF_MEMLESS
 	---help---
-	Say Y here if you have a Sony PS2/3 accessory and want to enable force
-	feedback support for it.
+	Say Y here if you have a Sony PS2/3/4 accessory and want to enable
+	force feedback support for it.
 
 config HID_SPEEDLINK
 	tristate "Speedlink VAD Cezanne mouse support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 30e44318f87f..fc712dde02a4 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_HID_AUREAL)        += hid-aureal.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
+obj-$(CONFIG_HID_CP2112)	+= hid-cp2112.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)	+= hid-dr.o
 obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index cc32a6f96c64..9e8064205bc7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1248,6 +1248,11 @@ void hid_output_report(struct hid_report *report, __u8 *data)
 }
 EXPORT_SYMBOL_GPL(hid_output_report);
 
+static int hid_report_len(struct hid_report *report)
+{
+	return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+}
+
 /*
  * Allocator for buffer that is going to be passed to hid_output_report()
  */
@@ -1258,7 +1263,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
 	 * of implement() working on 8 byte chunks
 	 */
 
-	int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+	int len = hid_report_len(report);
 
 	return kmalloc(len, flags);
 }
@@ -1314,6 +1319,41 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
 	return report;
 }
 
+/*
+ * Implement a generic .request() callback, using .raw_request()
+ * DO NOT USE in hid drivers directly, but through hid_hw_request instead.
+ */
+void __hid_request(struct hid_device *hid, struct hid_report *report,
+		int reqtype)
+{
+	char *buf;
+	int ret;
+	int len;
+
+	buf = hid_alloc_report_buf(report, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	len = hid_report_len(report);
+
+	if (reqtype == HID_REQ_SET_REPORT)
+		hid_output_report(report, buf);
+
+	ret = hid->ll_driver->raw_request(hid, report->id, buf, len,
+					  report->type, reqtype);
+	if (ret < 0) {
+		dbg_hid("unable to complete request: %d\n", ret);
+		goto out;
+	}
+
+	if (reqtype == HID_REQ_GET_REPORT)
+		hid_input_report(hid, report->type, buf, ret, 0);
+
+out:
+	kfree(buf);
+}
+EXPORT_SYMBOL_GPL(__hid_request);
+
 int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 		int interrupt)
 {
@@ -1693,6 +1733,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
@@ -1782,6 +1823,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
@@ -2278,6 +2320,7 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
 	{ }
 };
 
@@ -2433,6 +2476,14 @@ int hid_add_device(struct hid_device *hdev)
 		return -ENODEV;
 
 	/*
+	 * Check for the mandatory transport channel.
+	 */
+	 if (!hdev->ll_driver->raw_request) {
+		hid_err(hdev, "transport driver missing .raw_request()\n");
+		return -EINVAL;
+	 }
+
+	/*
 	 * Read the device report descriptor once and use as template
 	 * for the driver-specific modifications.
 	 */
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
new file mode 100644
index 000000000000..1025982c7fd3
--- /dev/null
+++ b/drivers/hid/hid-cp2112.c
@@ -0,0 +1,1068 @@
+/*
+ * hid-cp2112.c - Silicon Labs HID USB to SMBus master bridge
+ * Copyright (c) 2013,2014 Uplogix, Inc.
+ * David Barksdale <dbarksdale@uplogix.com>
+ *
+ * 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.
+ */
+
+/*
+ * The Silicon Labs CP2112 chip is a USB HID device which provides an
+ * SMBus controller for talking to slave devices and 8 GPIO pins. The
+ * host communicates with the CP2112 via raw HID reports.
+ *
+ * Data Sheet:
+ *   http://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf
+ * Programming Interface Specification:
+ *   http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf
+ */
+
+#include <linux/gpio.h>
+#include <linux/hid.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/nls.h>
+#include <linux/usb/ch9.h>
+#include "hid-ids.h"
+
+enum {
+	CP2112_GPIO_CONFIG		= 0x02,
+	CP2112_GPIO_GET			= 0x03,
+	CP2112_GPIO_SET			= 0x04,
+	CP2112_GET_VERSION_INFO		= 0x05,
+	CP2112_SMBUS_CONFIG		= 0x06,
+	CP2112_DATA_READ_REQUEST	= 0x10,
+	CP2112_DATA_WRITE_READ_REQUEST	= 0x11,
+	CP2112_DATA_READ_FORCE_SEND	= 0x12,
+	CP2112_DATA_READ_RESPONSE	= 0x13,
+	CP2112_DATA_WRITE_REQUEST	= 0x14,
+	CP2112_TRANSFER_STATUS_REQUEST	= 0x15,
+	CP2112_TRANSFER_STATUS_RESPONSE	= 0x16,
+	CP2112_CANCEL_TRANSFER		= 0x17,
+	CP2112_LOCK_BYTE		= 0x20,
+	CP2112_USB_CONFIG		= 0x21,
+	CP2112_MANUFACTURER_STRING	= 0x22,
+	CP2112_PRODUCT_STRING		= 0x23,
+	CP2112_SERIAL_STRING		= 0x24,
+};
+
+enum {
+	STATUS0_IDLE		= 0x00,
+	STATUS0_BUSY		= 0x01,
+	STATUS0_COMPLETE	= 0x02,
+	STATUS0_ERROR		= 0x03,
+};
+
+enum {
+	STATUS1_TIMEOUT_NACK		= 0x00,
+	STATUS1_TIMEOUT_BUS		= 0x01,
+	STATUS1_ARBITRATION_LOST	= 0x02,
+	STATUS1_READ_INCOMPLETE		= 0x03,
+	STATUS1_WRITE_INCOMPLETE	= 0x04,
+	STATUS1_SUCCESS			= 0x05,
+};
+
+struct cp2112_smbus_config_report {
+	u8 report;		/* CP2112_SMBUS_CONFIG */
+	__be32 clock_speed;	/* Hz */
+	u8 device_address;	/* Stored in the upper 7 bits */
+	u8 auto_send_read;	/* 1 = enabled, 0 = disabled */
+	__be16 write_timeout;	/* ms, 0 = no timeout */
+	__be16 read_timeout;	/* ms, 0 = no timeout */
+	u8 scl_low_timeout;	/* 1 = enabled, 0 = disabled */
+	__be16 retry_time;	/* # of retries, 0 = no limit */
+} __packed;
+
+struct cp2112_usb_config_report {
+	u8 report;	/* CP2112_USB_CONFIG */
+	__le16 vid;	/* Vendor ID */
+	__le16 pid;	/* Product ID */
+	u8 max_power;	/* Power requested in 2mA units */
+	u8 power_mode;	/* 0x00 = bus powered
+			   0x01 = self powered & regulator off
+			   0x02 = self powered & regulator on */
+	u8 release_major;
+	u8 release_minor;
+	u8 mask;	/* What fields to program */
+} __packed;
+
+struct cp2112_read_req_report {
+	u8 report;	/* CP2112_DATA_READ_REQUEST */
+	u8 slave_address;
+	__be16 length;
+} __packed;
+
+struct cp2112_write_read_req_report {
+	u8 report;	/* CP2112_DATA_WRITE_READ_REQUEST */
+	u8 slave_address;
+	__be16 length;
+	u8 target_address_length;
+	u8 target_address[16];
+} __packed;
+
+struct cp2112_write_req_report {
+	u8 report;	/* CP2112_DATA_WRITE_REQUEST */
+	u8 slave_address;
+	u8 length;
+	u8 data[61];
+} __packed;
+
+struct cp2112_force_read_report {
+	u8 report;	/* CP2112_DATA_READ_FORCE_SEND */
+	__be16 length;
+} __packed;
+
+struct cp2112_xfer_status_report {
+	u8 report;	/* CP2112_TRANSFER_STATUS_RESPONSE */
+	u8 status0;	/* STATUS0_* */
+	u8 status1;	/* STATUS1_* */
+	__be16 retries;
+	__be16 length;
+} __packed;
+
+struct cp2112_string_report {
+	u8 dummy;		/* force .string to be aligned */
+	u8 report;		/* CP2112_*_STRING */
+	u8 length;		/* length in bytes of everyting after .report */
+	u8 type;		/* USB_DT_STRING */
+	wchar_t string[30];	/* UTF16_LITTLE_ENDIAN string */
+} __packed;
+
+/* Number of times to request transfer status before giving up waiting for a
+   transfer to complete. This may need to be changed if SMBUS clock, retries,
+   or read/write/scl_low timeout settings are changed. */
+static const int XFER_STATUS_RETRIES = 10;
+
+/* Time in ms to wait for a CP2112_DATA_READ_RESPONSE or
+   CP2112_TRANSFER_STATUS_RESPONSE. */
+static const int RESPONSE_TIMEOUT = 50;
+
+static const struct hid_device_id cp2112_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, cp2112_devices);
+
+struct cp2112_device {
+	struct i2c_adapter adap;
+	struct hid_device *hdev;
+	wait_queue_head_t wait;
+	u8 read_data[61];
+	u8 read_length;
+	int xfer_status;
+	atomic_t read_avail;
+	atomic_t xfer_avail;
+	struct gpio_chip gc;
+};
+
+static int gpio_push_pull = 0xFF;
+module_param(gpio_push_pull, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gpio_push_pull, "GPIO push-pull configuration bitmask");
+
+static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct cp2112_device *dev = container_of(chip, struct cp2112_device,
+						 gc);
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[5];
+	int ret;
+
+	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
+				       sizeof(buf), HID_FEATURE_REPORT,
+				       HID_REQ_GET_REPORT);
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "error requesting GPIO config: %d\n", ret);
+		return ret;
+	}
+
+	buf[1] &= ~(1 << offset);
+	buf[2] = gpio_push_pull;
+
+	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
+					  HID_FEATURE_REPORT);
+	if (ret < 0) {
+		hid_err(hdev, "error setting GPIO config: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct cp2112_device *dev = container_of(chip, struct cp2112_device,
+						 gc);
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[3];
+	int ret;
+
+	buf[0] = CP2112_GPIO_SET;
+	buf[1] = value ? 0xff : 0;
+	buf[2] = 1 << offset;
+
+	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
+					  HID_FEATURE_REPORT);
+	if (ret < 0)
+		hid_err(hdev, "error setting GPIO values: %d\n", ret);
+}
+
+static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct cp2112_device *dev = container_of(chip, struct cp2112_device,
+						 gc);
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[2];
+	int ret;
+
+	ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, sizeof(buf),
+				       HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "error requesting GPIO values: %d\n", ret);
+		return ret;
+	}
+
+	return (buf[1] >> offset) & 1;
+}
+
+static int cp2112_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct cp2112_device *dev = container_of(chip, struct cp2112_device,
+						 gc);
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[5];
+	int ret;
+
+	cp2112_gpio_set(chip, offset, value);
+
+	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
+				       sizeof(buf), HID_FEATURE_REPORT,
+				       HID_REQ_GET_REPORT);
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "error requesting GPIO config: %d\n", ret);
+		return ret;
+	}
+
+	buf[1] |= 1 << offset;
+	buf[2] = gpio_push_pull;
+
+	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
+					  HID_FEATURE_REPORT);
+	if (ret < 0) {
+		hid_err(hdev, "error setting GPIO config: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
+			  u8 *data, size_t count, unsigned char report_type)
+{
+	u8 *buf;
+	int ret;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = hid_hw_raw_request(hdev, report_number, buf, count,
+				       report_type, HID_REQ_GET_REPORT);
+	memcpy(data, buf, count);
+	kfree(buf);
+	return ret;
+}
+
+static int cp2112_hid_output(struct hid_device *hdev, u8 *data, size_t count,
+			     unsigned char report_type)
+{
+	u8 *buf;
+	int ret;
+
+	buf = kmemdup(data, count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = hdev->hid_output_raw_report(hdev, buf, count, report_type);
+	kfree(buf);
+	return ret;
+}
+
+static int cp2112_wait(struct cp2112_device *dev, atomic_t *avail)
+{
+	int ret = 0;
+
+	/* We have sent either a CP2112_TRANSFER_STATUS_REQUEST or a
+	 * CP2112_DATA_READ_FORCE_SEND and we are waiting for the response to
+	 * come in cp2112_raw_event or timeout. There will only be one of these
+	 * in flight at any one time. The timeout is extremely large and is a
+	 * last resort if the CP2112 has died. If we do timeout we don't expect
+	 * to receive the response which would cause data races, it's not like
+	 * we can do anything about it anyway.
+	 */
+	ret = wait_event_interruptible_timeout(dev->wait,
+		atomic_read(avail), msecs_to_jiffies(RESPONSE_TIMEOUT));
+	if (-ERESTARTSYS == ret)
+		return ret;
+	if (!ret)
+		return -ETIMEDOUT;
+
+	atomic_set(avail, 0);
+	return 0;
+}
+
+static int cp2112_xfer_status(struct cp2112_device *dev)
+{
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[2];
+	int ret;
+
+	buf[0] = CP2112_TRANSFER_STATUS_REQUEST;
+	buf[1] = 0x01;
+	atomic_set(&dev->xfer_avail, 0);
+
+	ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
+	if (ret < 0) {
+		hid_warn(hdev, "Error requesting status: %d\n", ret);
+		return ret;
+	}
+
+	ret = cp2112_wait(dev, &dev->xfer_avail);
+	if (ret)
+		return ret;
+
+	return dev->xfer_status;
+}
+
+static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size)
+{
+	struct hid_device *hdev = dev->hdev;
+	struct cp2112_force_read_report report;
+	int ret;
+
+	report.report = CP2112_DATA_READ_FORCE_SEND;
+	report.length = cpu_to_be16(size);
+
+	atomic_set(&dev->read_avail, 0);
+
+	ret = cp2112_hid_output(hdev, &report.report, sizeof(report),
+				HID_OUTPUT_REPORT);
+	if (ret < 0) {
+		hid_warn(hdev, "Error requesting data: %d\n", ret);
+		return ret;
+	}
+
+	ret = cp2112_wait(dev, &dev->read_avail);
+	if (ret)
+		return ret;
+
+	hid_dbg(hdev, "read %d of %zd bytes requested\n",
+		dev->read_length, size);
+
+	if (size > dev->read_length)
+		size = dev->read_length;
+
+	memcpy(data, dev->read_data, size);
+	return dev->read_length;
+}
+
+static int cp2112_read_req(void *buf, u8 slave_address, u16 length)
+{
+	struct cp2112_read_req_report *report = buf;
+
+	if (length < 1 || length > 512)
+		return -EINVAL;
+
+	report->report = CP2112_DATA_READ_REQUEST;
+	report->slave_address = slave_address << 1;
+	report->length = cpu_to_be16(length);
+	return sizeof(*report);
+}
+
+static int cp2112_write_read_req(void *buf, u8 slave_address, u16 length,
+				 u8 command, u8 *data, u8 data_length)
+{
+	struct cp2112_write_read_req_report *report = buf;
+
+	if (length < 1 || length > 512
+	    || data_length > sizeof(report->target_address) - 1)
+		return -EINVAL;
+
+	report->report = CP2112_DATA_WRITE_READ_REQUEST;
+	report->slave_address = slave_address << 1;
+	report->length = cpu_to_be16(length);
+	report->target_address_length = data_length + 1;
+	report->target_address[0] = command;
+	memcpy(&report->target_address[1], data, data_length);
+	return data_length + 6;
+}
+
+static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
+			    u8 data_length)
+{
+	struct cp2112_write_req_report *report = buf;
+
+	if (data_length > sizeof(report->data) - 1)
+		return -EINVAL;
+
+	report->report = CP2112_DATA_WRITE_REQUEST;
+	report->slave_address = slave_address << 1;
+	report->length = data_length + 1;
+	report->data[0] = command;
+	memcpy(&report->data[1], data, data_length);
+	return data_length + 4;
+}
+
+static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
+		       unsigned short flags, char read_write, u8 command,
+		       int size, union i2c_smbus_data *data)
+{
+	struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[64];
+	__be16 word;
+	ssize_t count;
+	size_t read_length = 0;
+	unsigned int retries;
+	int ret;
+
+	hid_dbg(hdev, "%s addr 0x%x flags 0x%x cmd 0x%x size %d\n",
+		read_write == I2C_SMBUS_WRITE ? "write" : "read",
+		addr, flags, command, size);
+
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+		read_length = 1;
+
+		if (I2C_SMBUS_READ == read_write)
+			count = cp2112_read_req(buf, addr, read_length);
+		else
+			count = cp2112_write_req(buf, addr, data->byte, NULL,
+						 0);
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		read_length = 1;
+
+		if (I2C_SMBUS_READ == read_write)
+			count = cp2112_write_read_req(buf, addr, read_length,
+						      command, NULL, 0);
+		else
+			count = cp2112_write_req(buf, addr, command,
+						 &data->byte, 1);
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		read_length = 2;
+		word = cpu_to_be16(data->word);
+
+		if (I2C_SMBUS_READ == read_write)
+			count = cp2112_write_read_req(buf, addr, read_length,
+						      command, NULL, 0);
+		else
+			count = cp2112_write_req(buf, addr, command,
+						 (u8 *)&word, 2);
+		break;
+	case I2C_SMBUS_PROC_CALL:
+		size = I2C_SMBUS_WORD_DATA;
+		read_write = I2C_SMBUS_READ;
+		read_length = 2;
+		word = cpu_to_be16(data->word);
+
+		count = cp2112_write_read_req(buf, addr, read_length, command,
+					      (u8 *)&word, 2);
+		break;
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+		size = I2C_SMBUS_BLOCK_DATA;
+		/* fallthrough */
+	case I2C_SMBUS_BLOCK_DATA:
+		if (I2C_SMBUS_READ == read_write) {
+			count = cp2112_write_read_req(buf, addr,
+						      I2C_SMBUS_BLOCK_MAX,
+						      command, NULL, 0);
+		} else {
+			count = cp2112_write_req(buf, addr, command,
+						 data->block,
+						 data->block[0] + 1);
+		}
+		break;
+	case I2C_SMBUS_BLOCK_PROC_CALL:
+		size = I2C_SMBUS_BLOCK_DATA;
+		read_write = I2C_SMBUS_READ;
+
+		count = cp2112_write_read_req(buf, addr, I2C_SMBUS_BLOCK_MAX,
+					      command, data->block,
+					      data->block[0] + 1);
+		break;
+	default:
+		hid_warn(hdev, "Unsupported transaction %d\n", size);
+		return -EOPNOTSUPP;
+	}
+
+	if (count < 0)
+		return count;
+
+	ret = hid_hw_power(hdev, PM_HINT_FULLON);
+	if (ret < 0) {
+		hid_err(hdev, "power management error: %d\n", ret);
+		return ret;
+	}
+
+	ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
+	if (ret < 0) {
+		hid_warn(hdev, "Error starting transaction: %d\n", ret);
+		goto power_normal;
+	}
+
+	for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
+		ret = cp2112_xfer_status(dev);
+		if (-EBUSY == ret)
+			continue;
+		if (ret < 0)
+			goto power_normal;
+		break;
+	}
+
+	if (XFER_STATUS_RETRIES <= retries) {
+		hid_warn(hdev, "Transfer timed out, cancelling.\n");
+		buf[0] = CP2112_CANCEL_TRANSFER;
+		buf[1] = 0x01;
+
+		ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
+		if (ret < 0)
+			hid_warn(hdev, "Error cancelling transaction: %d\n",
+				 ret);
+
+		ret = -ETIMEDOUT;
+		goto power_normal;
+	}
+
+	if (I2C_SMBUS_WRITE == read_write) {
+		ret = 0;
+		goto power_normal;
+	}
+
+	if (I2C_SMBUS_BLOCK_DATA == size)
+		read_length = ret;
+
+	ret = cp2112_read(dev, buf, read_length);
+	if (ret < 0)
+		goto power_normal;
+	if (ret != read_length) {
+		hid_warn(hdev, "short read: %d < %zd\n", ret, read_length);
+		ret = -EIO;
+		goto power_normal;
+	}
+
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+	case I2C_SMBUS_BYTE_DATA:
+		data->byte = buf[0];
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		data->word = be16_to_cpup((__be16 *)buf);
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		if (read_length > I2C_SMBUS_BLOCK_MAX) {
+			ret = -EPROTO;
+			goto power_normal;
+		}
+
+		memcpy(data->block, buf, read_length);
+		break;
+	}
+
+	ret = 0;
+power_normal:
+	hid_hw_power(hdev, PM_HINT_NORMAL);
+	hid_dbg(hdev, "transfer finished: %d\n", ret);
+	return ret;
+}
+
+static u32 cp2112_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_BLOCK_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK |
+		I2C_FUNC_SMBUS_PROC_CALL |
+		I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+	.smbus_xfer	= cp2112_xfer,
+	.functionality	= cp2112_functionality,
+};
+
+static int cp2112_get_usb_config(struct hid_device *hdev,
+				 struct cp2112_usb_config_report *cfg)
+{
+	int ret;
+
+	ret = cp2112_hid_get(hdev, CP2112_USB_CONFIG, (u8 *)cfg, sizeof(*cfg),
+			     HID_FEATURE_REPORT);
+	if (ret != sizeof(*cfg)) {
+		hid_err(hdev, "error reading usb config: %d\n", ret);
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int cp2112_set_usb_config(struct hid_device *hdev,
+				 struct cp2112_usb_config_report *cfg)
+{
+	int ret;
+
+	BUG_ON(cfg->report != CP2112_USB_CONFIG);
+
+	ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg),
+				HID_FEATURE_REPORT);
+	if (ret != sizeof(*cfg)) {
+		hid_err(hdev, "error writing usb config: %d\n", ret);
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void chmod_sysfs_attrs(struct hid_device *hdev);
+
+#define CP2112_CONFIG_ATTR(name, store, format, ...) \
+static ssize_t name##_store(struct device *kdev, \
+			    struct device_attribute *attr, const char *buf, \
+			    size_t count) \
+{ \
+	struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
+	struct cp2112_usb_config_report cfg; \
+	int ret = cp2112_get_usb_config(hdev, &cfg); \
+	if (ret) \
+		return ret; \
+	store; \
+	ret = cp2112_set_usb_config(hdev, &cfg); \
+	if (ret) \
+		return ret; \
+	chmod_sysfs_attrs(hdev); \
+	return count; \
+} \
+static ssize_t name##_show(struct device *kdev, \
+			   struct device_attribute *attr, char *buf) \
+{ \
+	struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
+	struct cp2112_usb_config_report cfg; \
+	int ret = cp2112_get_usb_config(hdev, &cfg); \
+	if (ret) \
+		return ret; \
+	return scnprintf(buf, PAGE_SIZE, format, ##__VA_ARGS__); \
+} \
+static DEVICE_ATTR_RW(name);
+
+CP2112_CONFIG_ATTR(vendor_id, ({
+	u16 vid;
+
+	if (sscanf(buf, "%hi", &vid) != 1)
+		return -EINVAL;
+
+	cfg.vid = cpu_to_le16(vid);
+	cfg.mask = 0x01;
+}), "0x%04x\n", le16_to_cpu(cfg.vid));
+
+CP2112_CONFIG_ATTR(product_id, ({
+	u16 pid;
+
+	if (sscanf(buf, "%hi", &pid) != 1)
+		return -EINVAL;
+
+	cfg.pid = cpu_to_le16(pid);
+	cfg.mask = 0x02;
+}), "0x%04x\n", le16_to_cpu(cfg.pid));
+
+CP2112_CONFIG_ATTR(max_power, ({
+	int mA;
+
+	if (sscanf(buf, "%i", &mA) != 1)
+		return -EINVAL;
+
+	cfg.max_power = (mA + 1) / 2;
+	cfg.mask = 0x04;
+}), "%u mA\n", cfg.max_power * 2);
+
+CP2112_CONFIG_ATTR(power_mode, ({
+	if (sscanf(buf, "%hhi", &cfg.power_mode) != 1)
+		return -EINVAL;
+
+	cfg.mask = 0x08;
+}), "%u\n", cfg.power_mode);
+
+CP2112_CONFIG_ATTR(release_version, ({
+	if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor)
+	    != 2)
+		return -EINVAL;
+
+	cfg.mask = 0x10;
+}), "%u.%u\n", cfg.release_major, cfg.release_minor);
+
+#undef CP2112_CONFIG_ATTR
+
+struct cp2112_pstring_attribute {
+	struct device_attribute attr;
+	unsigned char report;
+};
+
+static ssize_t pstr_store(struct device *kdev,
+			  struct device_attribute *kattr, const char *buf,
+			  size_t count)
+{
+	struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
+	struct cp2112_pstring_attribute *attr =
+		container_of(kattr, struct cp2112_pstring_attribute, attr);
+	struct cp2112_string_report report;
+	int ret;
+
+	memset(&report, 0, sizeof(report));
+
+	ret = utf8s_to_utf16s(buf, count, UTF16_LITTLE_ENDIAN,
+			      report.string, ARRAY_SIZE(report.string));
+	report.report = attr->report;
+	report.length = ret * sizeof(report.string[0]) + 2;
+	report.type = USB_DT_STRING;
+
+	ret = cp2112_hid_output(hdev, &report.report, report.length + 1,
+				HID_FEATURE_REPORT);
+	if (ret != report.length + 1) {
+		hid_err(hdev, "error writing %s string: %d\n", kattr->attr.name,
+			ret);
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+
+	chmod_sysfs_attrs(hdev);
+	return count;
+}
+
+static ssize_t pstr_show(struct device *kdev,
+			 struct device_attribute *kattr, char *buf)
+{
+	struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
+	struct cp2112_pstring_attribute *attr =
+		container_of(kattr, struct cp2112_pstring_attribute, attr);
+	struct cp2112_string_report report;
+	u8 length;
+	int ret;
+
+	ret = cp2112_hid_get(hdev, attr->report, &report.report,
+			     sizeof(report) - 1, HID_FEATURE_REPORT);
+	if (ret < 3) {
+		hid_err(hdev, "error reading %s string: %d\n", kattr->attr.name,
+			ret);
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+
+	if (report.length < 2) {
+		hid_err(hdev, "invalid %s string length: %d\n",
+			kattr->attr.name, report.length);
+		return -EIO;
+	}
+
+	length = report.length > ret - 1 ? ret - 1 : report.length;
+	length = (length - 2) / sizeof(report.string[0]);
+	ret = utf16s_to_utf8s(report.string, length, UTF16_LITTLE_ENDIAN, buf,
+			      PAGE_SIZE - 1);
+	buf[ret++] = '\n';
+	return ret;
+}
+
+#define CP2112_PSTR_ATTR(name, _report) \
+static struct cp2112_pstring_attribute dev_attr_##name = { \
+	.attr = __ATTR(name, (S_IWUSR | S_IRUGO), pstr_show, pstr_store), \
+	.report = _report, \
+};
+
+CP2112_PSTR_ATTR(manufacturer,	CP2112_MANUFACTURER_STRING);
+CP2112_PSTR_ATTR(product,	CP2112_PRODUCT_STRING);
+CP2112_PSTR_ATTR(serial,	CP2112_SERIAL_STRING);
+
+#undef CP2112_PSTR_ATTR
+
+static const struct attribute_group cp2112_attr_group = {
+	.attrs = (struct attribute *[]){
+		&dev_attr_vendor_id.attr,
+		&dev_attr_product_id.attr,
+		&dev_attr_max_power.attr,
+		&dev_attr_power_mode.attr,
+		&dev_attr_release_version.attr,
+		&dev_attr_manufacturer.attr.attr,
+		&dev_attr_product.attr.attr,
+		&dev_attr_serial.attr.attr,
+		NULL
+	}
+};
+
+/* Chmoding our sysfs attributes is simply a way to expose which fields in the
+ * PROM have already been programmed. We do not depend on this preventing
+ * writing to these attributes since the CP2112 will simply ignore writes to
+ * already-programmed fields. This is why there is no sense in fixing this
+ * racy behaviour.
+ */
+static void chmod_sysfs_attrs(struct hid_device *hdev)
+{
+	struct attribute **attr;
+	u8 buf[2];
+	int ret;
+
+	ret = cp2112_hid_get(hdev, CP2112_LOCK_BYTE, buf, sizeof(buf),
+			     HID_FEATURE_REPORT);
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "error reading lock byte: %d\n", ret);
+		return;
+	}
+
+	for (attr = cp2112_attr_group.attrs; *attr; ++attr) {
+		umode_t mode = (buf[1] & 1) ? S_IWUSR | S_IRUGO : S_IRUGO;
+		ret = sysfs_chmod_file(&hdev->dev.kobj, *attr, mode);
+		if (ret < 0)
+			hid_err(hdev, "error chmoding sysfs file %s\n",
+				(*attr)->name);
+		buf[1] >>= 1;
+	}
+}
+
+static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	struct cp2112_device *dev;
+	u8 buf[3];
+	struct cp2112_smbus_config_report config;
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	ret = hid_hw_open(hdev);
+	if (ret) {
+		hid_err(hdev, "hw open failed\n");
+		goto err_hid_stop;
+	}
+
+	ret = hid_hw_power(hdev, PM_HINT_FULLON);
+	if (ret < 0) {
+		hid_err(hdev, "power management error: %d\n", ret);
+		goto err_hid_close;
+	}
+
+	ret = cp2112_hid_get(hdev, CP2112_GET_VERSION_INFO, buf, sizeof(buf),
+			     HID_FEATURE_REPORT);
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "error requesting version\n");
+		if (ret >= 0)
+			ret = -EIO;
+		goto err_power_normal;
+	}
+
+	hid_info(hdev, "Part Number: 0x%02X Device Version: 0x%02X\n",
+		 buf[1], buf[2]);
+
+	ret = cp2112_hid_get(hdev, CP2112_SMBUS_CONFIG, (u8 *)&config,
+			     sizeof(config), HID_FEATURE_REPORT);
+	if (ret != sizeof(config)) {
+		hid_err(hdev, "error requesting SMBus config\n");
+		if (ret >= 0)
+			ret = -EIO;
+		goto err_power_normal;
+	}
+
+	config.retry_time = cpu_to_be16(1);
+
+	ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),
+				HID_FEATURE_REPORT);
+	if (ret != sizeof(config)) {
+		hid_err(hdev, "error setting SMBus config\n");
+		if (ret >= 0)
+			ret = -EIO;
+		goto err_power_normal;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		ret = -ENOMEM;
+		goto err_power_normal;
+	}
+
+	hid_set_drvdata(hdev, (void *)dev);
+	dev->hdev		= hdev;
+	dev->adap.owner		= THIS_MODULE;
+	dev->adap.class		= I2C_CLASS_HWMON;
+	dev->adap.algo		= &smbus_algorithm;
+	dev->adap.algo_data	= dev;
+	dev->adap.dev.parent	= &hdev->dev;
+	snprintf(dev->adap.name, sizeof(dev->adap.name),
+		 "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
+	init_waitqueue_head(&dev->wait);
+
+	hid_device_io_start(hdev);
+	ret = i2c_add_adapter(&dev->adap);
+	hid_device_io_stop(hdev);
+
+	if (ret) {
+		hid_err(hdev, "error registering i2c adapter\n");
+		goto err_free_dev;
+	}
+
+	hid_dbg(hdev, "adapter registered\n");
+
+	dev->gc.label			= "cp2112_gpio";
+	dev->gc.direction_input		= cp2112_gpio_direction_input;
+	dev->gc.direction_output	= cp2112_gpio_direction_output;
+	dev->gc.set			= cp2112_gpio_set;
+	dev->gc.get			= cp2112_gpio_get;
+	dev->gc.base			= -1;
+	dev->gc.ngpio			= 8;
+	dev->gc.can_sleep		= 1;
+	dev->gc.dev			= &hdev->dev;
+
+	ret = gpiochip_add(&dev->gc);
+	if (ret < 0) {
+		hid_err(hdev, "error registering gpio chip\n");
+		goto err_free_i2c;
+	}
+
+	ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group);
+	if (ret < 0) {
+		hid_err(hdev, "error creating sysfs attrs\n");
+		goto err_gpiochip_remove;
+	}
+
+	chmod_sysfs_attrs(hdev);
+	hid_hw_power(hdev, PM_HINT_NORMAL);
+
+	return ret;
+
+err_gpiochip_remove:
+	if (gpiochip_remove(&dev->gc) < 0)
+		hid_err(hdev, "error removing gpio chip\n");
+err_free_i2c:
+	i2c_del_adapter(&dev->adap);
+err_free_dev:
+	kfree(dev);
+err_power_normal:
+	hid_hw_power(hdev, PM_HINT_NORMAL);
+err_hid_close:
+	hid_hw_close(hdev);
+err_hid_stop:
+	hid_hw_stop(hdev);
+	return ret;
+}
+
+static void cp2112_remove(struct hid_device *hdev)
+{
+	struct cp2112_device *dev = hid_get_drvdata(hdev);
+
+	sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
+	if (gpiochip_remove(&dev->gc))
+		hid_err(hdev, "unable to remove gpio chip\n");
+	i2c_del_adapter(&dev->adap);
+	/* i2c_del_adapter has finished removing all i2c devices from our
+	 * adapter. Well behaved devices should no longer call our cp2112_xfer
+	 * and should have waited for any pending calls to finish. It has also
+	 * waited for device_unregister(&adap->dev) to complete. Therefore we
+	 * can safely free our struct cp2112_device.
+	 */
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+	kfree(dev);
+}
+
+static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
+			    u8 *data, int size)
+{
+	struct cp2112_device *dev = hid_get_drvdata(hdev);
+	struct cp2112_xfer_status_report *xfer = (void *)data;
+
+	switch (data[0]) {
+	case CP2112_TRANSFER_STATUS_RESPONSE:
+		hid_dbg(hdev, "xfer status: %02x %02x %04x %04x\n",
+			xfer->status0, xfer->status1,
+			be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length));
+
+		switch (xfer->status0) {
+		case STATUS0_IDLE:
+			dev->xfer_status = -EAGAIN;
+			break;
+		case STATUS0_BUSY:
+			dev->xfer_status = -EBUSY;
+			break;
+		case STATUS0_COMPLETE:
+			dev->xfer_status = be16_to_cpu(xfer->length);
+			break;
+		case STATUS0_ERROR:
+			switch (xfer->status1) {
+			case STATUS1_TIMEOUT_NACK:
+			case STATUS1_TIMEOUT_BUS:
+				dev->xfer_status = -ETIMEDOUT;
+				break;
+			default:
+				dev->xfer_status = -EIO;
+				break;
+			}
+			break;
+		default:
+			dev->xfer_status = -EINVAL;
+			break;
+		}
+
+		atomic_set(&dev->xfer_avail, 1);
+		break;
+	case CP2112_DATA_READ_RESPONSE:
+		hid_dbg(hdev, "read response: %02x %02x\n", data[1], data[2]);
+
+		dev->read_length = data[2];
+		if (dev->read_length > sizeof(dev->read_data))
+			dev->read_length = sizeof(dev->read_data);
+
+		memcpy(dev->read_data, &data[3], dev->read_length);
+		atomic_set(&dev->read_avail, 1);
+		break;
+	default:
+		hid_err(hdev, "unknown report\n");
+
+		return 0;
+	}
+
+	wake_up_interruptible(&dev->wait);
+	return 1;
+}
+
+static struct hid_driver cp2112_driver = {
+	.name		= "cp2112",
+	.id_table	= cp2112_devices,
+	.probe		= cp2112_probe,
+	.remove		= cp2112_remove,
+	.raw_event	= cp2112_raw_event,
+};
+
+module_hid_driver(cp2112_driver);
+MODULE_DESCRIPTION("Silicon Labs HID USB to SMBus master bridge");
+MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 22f28d6b33a8..917adb233cf1 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -244,6 +244,7 @@
 #define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH	0x81b9
 
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI4713       0x8244
+#define USB_DEVICE_ID_CYGNAL_CP2112	0xea90
 
 #define USB_VENDOR_ID_CYPRESS		0x04b4
 #define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
@@ -616,6 +617,7 @@
 
 #define USB_VENDOR_ID_MICROSOFT		0x045e
 #define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
+#define USB_DEVICE_ID_MS_OFFICE_KB	0x0048
 #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
 #define USB_DEVICE_ID_MS_NE4K		0x00db
 #define USB_DEVICE_ID_MS_NE4K_JP	0x00dc
@@ -961,4 +963,7 @@
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
 
 
+#define USB_VENDOR_ID_RISO_KAGAKU	0x1294	/* Riso Kagaku Corp. */
+#define USB_DEVICE_ID_RI_KA_WEBMAIL	0x1320	/* Webmail Notifier */
+
 #endif
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a713e6211419..e7e8b19a9284 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -350,9 +350,9 @@ static int hidinput_get_battery_property(struct power_supply *psy,
 			ret = -ENOMEM;
 			break;
 		}
-		ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
-					      buf, 2,
-					      dev->battery_report_type);
+		ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
+					 dev->battery_report_type,
+					 HID_REQ_GET_REPORT);
 
 		if (ret != 2) {
 			ret = -ENODATA;
@@ -789,10 +789,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		case 0x199: map_key_clear(KEY_CHAT);		break;
 		case 0x19c: map_key_clear(KEY_LOGOFF);		break;
 		case 0x19e: map_key_clear(KEY_COFFEE);		break;
+		case 0x1a3: map_key_clear(KEY_NEXT);		break;
+		case 0x1a4: map_key_clear(KEY_PREVIOUS);	break;
 		case 0x1a6: map_key_clear(KEY_HELP);		break;
 		case 0x1a7: map_key_clear(KEY_DOCUMENTS);	break;
 		case 0x1ab: map_key_clear(KEY_SPELLCHECK);	break;
 		case 0x1ae: map_key_clear(KEY_KEYBOARD);	break;
+		case 0x1b4: map_key_clear(KEY_FILE);		break;
 		case 0x1b6: map_key_clear(KEY_IMAGES);		break;
 		case 0x1b7: map_key_clear(KEY_AUDIO);		break;
 		case 0x1b8: map_key_clear(KEY_VIDEO);		break;
@@ -1150,7 +1153,7 @@ static void hidinput_led_worker(struct work_struct *work)
 					      led_work);
 	struct hid_field *field;
 	struct hid_report *report;
-	int len;
+	int len, ret;
 	__u8 *buf;
 
 	field = hidinput_get_led_field(hid);
@@ -1184,7 +1187,10 @@ static void hidinput_led_worker(struct work_struct *work)
 
 	hid_output_report(report, buf);
 	/* synchronous output report */
-	hid->hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT);
+	ret = hid_hw_output_report(hid, buf, len);
+	if (ret == -ENOSYS)
+		hid_hw_raw_request(hid, report->id, buf, len, HID_OUTPUT_REPORT,
+				HID_REQ_SET_REPORT);
 	kfree(buf);
 }
 
@@ -1263,10 +1269,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
 	}
 
 	input_set_drvdata(input_dev, hid);
-	if (hid->ll_driver->hidinput_input_event)
-		input_dev->event = hid->ll_driver->hidinput_input_event;
-	else if (hid->ll_driver->request || hid->hid_output_raw_report)
-		input_dev->event = hidinput_input_event;
+	input_dev->event = hidinput_input_event;
 	input_dev->open = hidinput_open;
 	input_dev->close = hidinput_close;
 	input_dev->setkeycode = hidinput_setkeycode;
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 9fe9d4ac3114..a976f48263f6 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -692,7 +692,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
 		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
+		ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 
 		if (ret >= 0) {
 			/* insert a little delay of 10 jiffies ~ 40ms */
@@ -704,7 +705,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 			buf[1] = 0xB2;
 			get_random_bytes(&buf[2], 2);
 
-			ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
+			ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 		}
 	}
 
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index f45279c3b11a..486dbde2ba2d 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = {
 	0x19, 0xE0,		/*   USAGE_MINIMUM (Left Control)   */
 	0x29, 0xE7,		/*   USAGE_MAXIMUM (Right GUI)      */
 	0x81, 0x02,		/*   INPUT (Data,Var,Abs)       */
-	0x95, 0x05,		/*   REPORT COUNT (5)           */
-	0x05, 0x08,		/*   USAGE PAGE (LED page)      */
-	0x19, 0x01,		/*   USAGE MINIMUM (1)          */
-	0x29, 0x05,		/*   USAGE MAXIMUM (5)          */
-	0x91, 0x02,		/*   OUTPUT (Data, Variable, Absolute)  */
-	0x95, 0x01,		/*   REPORT COUNT (1)           */
-	0x75, 0x03,		/*   REPORT SIZE (3)            */
-	0x91, 0x01,		/*   OUTPUT (Constant)          */
 	0x95, 0x06,		/*   REPORT_COUNT (6)           */
 	0x75, 0x08,		/*   REPORT_SIZE (8)            */
 	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
@@ -60,6 +52,18 @@ static const char kbd_descriptor[] = {
 	0x19, 0x00,		/*   USAGE_MINIMUM (no event)       */
 	0x2A, 0xFF, 0x00,	/*   USAGE_MAXIMUM (reserved)       */
 	0x81, 0x00,		/*   INPUT (Data,Ary,Abs)       */
+	0x85, 0x0e,		/* REPORT_ID (14)               */
+	0x05, 0x08,		/*   USAGE PAGE (LED page)      */
+	0x95, 0x05,		/*   REPORT COUNT (5)           */
+	0x75, 0x01,		/*   REPORT SIZE (1)            */
+	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
+	0x25, 0x01,		/*   LOGICAL_MAXIMUM (1)        */
+	0x19, 0x01,		/*   USAGE MINIMUM (1)          */
+	0x29, 0x05,		/*   USAGE MAXIMUM (5)          */
+	0x91, 0x02,		/*   OUTPUT (Data, Variable, Absolute)  */
+	0x95, 0x01,		/*   REPORT COUNT (1)           */
+	0x75, 0x03,		/*   REPORT SIZE (3)            */
+	0x91, 0x01,		/*   OUTPUT (Constant)          */
 	0xC0
 };
 
@@ -189,9 +193,6 @@ static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
 
 static struct hid_ll_driver logi_dj_ll_driver;
 
-static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
-					size_t count,
-					unsigned char report_type);
 static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
 
 static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
@@ -258,7 +259,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 	}
 
 	dj_hiddev->ll_driver = &logi_dj_ll_driver;
-	dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;
 
 	dj_hiddev->dev.parent = &djrcv_hdev->dev;
 	dj_hiddev->bus = BUS_USB;
@@ -540,14 +540,35 @@ static void logi_dj_ll_close(struct hid_device *hid)
 	dbg_hid("%s:%s\n", __func__, hid->phys);
 }
 
-static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
-					size_t count,
-					unsigned char report_type)
+static int logi_dj_ll_raw_request(struct hid_device *hid,
+				  unsigned char reportnum, __u8 *buf,
+				  size_t count, unsigned char report_type,
+				  int reqtype)
 {
-	/* Called by hid raw to send data */
-	dbg_hid("%s\n", __func__);
+	struct dj_device *djdev = hid->driver_data;
+	struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
+	u8 *out_buf;
+	int ret;
 
-	return 0;
+	if (buf[0] != REPORT_TYPE_LEDS)
+		return -EINVAL;
+
+	out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
+	if (!out_buf)
+		return -ENOMEM;
+
+	if (count < DJREPORT_SHORT_LENGTH - 2)
+		count = DJREPORT_SHORT_LENGTH - 2;
+
+	out_buf[0] = REPORT_ID_DJ_SHORT;
+	out_buf[1] = djdev->device_index;
+	memcpy(out_buf + 2, buf, count);
+
+	ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf,
+		DJREPORT_SHORT_LENGTH, report_type, reqtype);
+
+	kfree(out_buf);
+	return ret;
 }
 
 static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size)
@@ -613,58 +634,6 @@ static int logi_dj_ll_parse(struct hid_device *hid)
 	return retval;
 }
 
-static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
-				  unsigned int code, int value)
-{
-	/* Sent by the input layer to handle leds and Force Feedback */
-	struct hid_device *dj_hiddev = input_get_drvdata(dev);
-	struct dj_device *dj_dev = dj_hiddev->driver_data;
-
-	struct dj_receiver_dev *djrcv_dev =
-	    dev_get_drvdata(dj_hiddev->dev.parent);
-	struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
-	struct hid_report_enum *output_report_enum;
-
-	struct hid_field *field;
-	struct hid_report *report;
-	unsigned char *data;
-	int offset;
-
-	dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
-		__func__, dev->phys, type, code, value);
-
-	if (type != EV_LED)
-		return -1;
-
-	offset = hidinput_find_field(dj_hiddev, type, code, &field);
-
-	if (offset == -1) {
-		dev_warn(&dev->dev, "event field not found\n");
-		return -1;
-	}
-	hid_set_field(field, offset, value);
-
-	data = hid_alloc_report_buf(field->report, GFP_ATOMIC);
-	if (!data) {
-		dev_warn(&dev->dev, "failed to allocate report buf memory\n");
-		return -1;
-	}
-
-	hid_output_report(field->report, &data[0]);
-
-	output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
-	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
-	hid_set_field(report->field[0], 0, dj_dev->device_index);
-	hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
-	hid_set_field(report->field[0], 2, data[1]);
-
-	hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
-
-	kfree(data);
-
-	return 0;
-}
-
 static int logi_dj_ll_start(struct hid_device *hid)
 {
 	dbg_hid("%s\n", __func__);
@@ -683,7 +652,7 @@ static struct hid_ll_driver logi_dj_ll_driver = {
 	.stop = logi_dj_ll_stop,
 	.open = logi_dj_ll_open,
 	.close = logi_dj_ll_close,
-	.hidinput_input_event = logi_dj_ll_input_event,
+	.raw_request = logi_dj_ll_raw_request,
 };
 
 
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 3b43d1cfa936..ecc2cbf300cc 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -538,8 +538,8 @@ static int magicmouse_probe(struct hid_device *hdev,
 	 * but there seems to be no other way of switching the mode.
 	 * Thus the super-ugly hacky success check below.
 	 */
-	ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
-			HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, feature[0], feature, sizeof(feature),
+				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	if (ret != -EIO && ret != sizeof(feature)) {
 		hid_err(hdev, "unable to request touch data (%d)\n", ret);
 		goto err_stop_hw;
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 404a3a8a82f1..6fd58175a291 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -62,9 +62,48 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
 {
 	struct input_dev *input = hi->input;
 
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
+		switch (usage->hid & HID_USAGE) {
+		/*
+		 * Microsoft uses these 2 reserved usage ids for 2 keys on
+		 * the MS office kb labelled "Office Home" and "Task Pane".
+		 */
+		case 0x29d:
+			ms_map_key_clear(KEY_PROG1);
+			return 1;
+		case 0x29e:
+			ms_map_key_clear(KEY_PROG2);
+			return 1;
+		}
+		return 0;
+	}
+
+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+		return 0;
+
 	switch (usage->hid & HID_USAGE) {
 	case 0xfd06: ms_map_key_clear(KEY_CHAT);	break;
 	case 0xfd07: ms_map_key_clear(KEY_PHONE);	break;
+	case 0xff00:
+		/* Special keypad keys */
+		ms_map_key_clear(KEY_KPEQUAL);
+		set_bit(KEY_KPLEFTPAREN, input->keybit);
+		set_bit(KEY_KPRIGHTPAREN, input->keybit);
+		break;
+	case 0xff01:
+		/* Scroll wheel */
+		hid_map_usage_clear(hi, usage, bit, max, EV_REL, REL_WHEEL);
+		break;
+	case 0xff02:
+		/*
+		 * This byte contains a copy of the modifier keys byte of a
+		 * standard hid keyboard report, as send by interface 0
+		 * (this usage is found on interface 1).
+		 *
+		 * This byte only gets send when another key in the same report
+		 * changes state, and as such is useless, ignore it.
+		 */
+		return -1;
 	case 0xff05:
 		set_bit(EV_REP, input->evbit);
 		ms_map_key_clear(KEY_F13);
@@ -83,6 +122,9 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
 static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+		return 0;
+
 	set_bit(EV_REP, hi->input->evbit);
 	switch (usage->hid & HID_USAGE) {
 	case 0xfd08: ms_map_key_clear(KEY_FORWARD);	break;
@@ -102,9 +144,6 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 {
 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
-	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-		return 0;
-
 	if (quirks & MS_ERGONOMY) {
 		int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
 		if (ret)
@@ -134,14 +173,39 @@ static int ms_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	struct input_dev *input;
 
 	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
 			!usage->type)
 		return 0;
 
+	input = field->hidinput->input;
+
 	/* Handling MS keyboards special buttons */
+	if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff00)) {
+		/* Special keypad keys */
+		input_report_key(input, KEY_KPEQUAL, value & 0x01);
+		input_report_key(input, KEY_KPLEFTPAREN, value & 0x02);
+		input_report_key(input, KEY_KPRIGHTPAREN, value & 0x04);
+		return 1;
+	}
+
+	if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff01)) {
+		/* Scroll wheel */
+		int step = ((value & 0x60) >> 5) + 1;
+
+		switch (value & 0x1f) {
+		case 0x01:
+			input_report_rel(input, REL_WHEEL, step);
+			break;
+		case 0x1f:
+			input_report_rel(input, REL_WHEEL, -step);
+			break;
+		}
+		return 1;
+	}
+
 	if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
-		struct input_dev *input = field->hidinput->input;
 		static unsigned int last_key = 0;
 		unsigned int key = 0;
 		switch (value) {
@@ -194,6 +258,8 @@ err_free:
 static const struct hid_device_id ms_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
 		.driver_data = MS_HIDINPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB),
+		.driver_data = MS_ERGONOMY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
 		.driver_data = MS_ERGONOMY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP),
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index 7ed828056414..91fab975063c 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -624,7 +624,8 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
 
 	/* Setup sound card */
 
-	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	err = snd_card_new(&pm->pk->hdev->dev, index[dev], id[dev],
+			   THIS_MODULE, 0, &card);
 	if (err < 0) {
 		pk_error("failed to create pc-midi sound card\n");
 		err = -ENOMEM;
@@ -660,8 +661,6 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
 	snd_rawmidi_set_ops(rwmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 		&pcmidi_in_ops);
 
-	snd_card_set_dev(card, &pm->pk->hdev->dev);
-
 	/* create sysfs variables */
 	err = device_create_file(&pm->pk->hdev->dev,
 				 sysfs_device_attr_channel);
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 9c22e14c57f0..642dbca3349e 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -56,9 +56,9 @@ struct sensor_hub_pending {
  * @dyn_callback_lock:	spin lock to protect callback list
  * @hid_sensor_hub_client_devs:	Stores all MFD cells for a hub instance.
  * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached).
+ * @ref_cnt:		Number of MFD clients have opened this device
  */
 struct sensor_hub_data {
-	struct hid_sensor_hub_device *hsdev;
 	struct mutex mutex;
 	spinlock_t lock;
 	struct sensor_hub_pending pending;
@@ -67,6 +67,7 @@ struct sensor_hub_data {
 	struct mfd_cell *hid_sensor_hub_client_devs;
 	int hid_sensor_client_cnt;
 	unsigned long quirks;
+	int ref_cnt;
 };
 
 /**
@@ -79,6 +80,7 @@ struct sensor_hub_data {
 struct hid_sensor_hub_callbacks_list {
 	struct list_head list;
 	u32 usage_id;
+	struct hid_sensor_hub_device *hsdev;
 	struct hid_sensor_hub_callbacks *usage_callback;
 	void *priv;
 };
@@ -97,20 +99,18 @@ static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
 	return NULL;
 }
 
-static int sensor_hub_get_physical_device_count(
-				struct hid_report_enum *report_enum)
+static int sensor_hub_get_physical_device_count(struct hid_device *hdev)
 {
-	struct hid_report *report;
-	struct hid_field *field;
-	int cnt = 0;
+	int i;
+	int count = 0;
 
-	list_for_each_entry(report, &report_enum->report_list, list) {
-		field = report->field[0];
-		if (report->maxfield && field && field->physical)
-			cnt++;
+	for (i = 0; i < hdev->maxcollection; ++i) {
+		struct hid_collection *collection = &hdev->collection[i];
+		if (collection->type == HID_COLLECTION_PHYSICAL)
+			++count;
 	}
 
-	return cnt;
+	return count;
 }
 
 static void sensor_hub_fill_attr_info(
@@ -128,15 +128,23 @@ static void sensor_hub_fill_attr_info(
 
 static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
 					struct hid_device *hdev,
-					u32 usage_id, void **priv)
+					u32 usage_id,
+					int collection_index,
+					struct hid_sensor_hub_device **hsdev,
+					void **priv)
 {
 	struct hid_sensor_hub_callbacks_list *callback;
 	struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
 
 	spin_lock(&pdata->dyn_callback_lock);
 	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-		if (callback->usage_id == usage_id) {
+		if (callback->usage_id == usage_id &&
+			(collection_index >=
+				callback->hsdev->start_collection_index) &&
+			(collection_index <
+				callback->hsdev->end_collection_index)) {
 			*priv = callback->priv;
+			*hsdev = callback->hsdev;
 			spin_unlock(&pdata->dyn_callback_lock);
 			return callback->usage_callback;
 		}
@@ -154,7 +162,8 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
 
 	spin_lock(&pdata->dyn_callback_lock);
 	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-		if (callback->usage_id == usage_id) {
+		if (callback->usage_id == usage_id &&
+						callback->hsdev == hsdev) {
 			spin_unlock(&pdata->dyn_callback_lock);
 			return -EINVAL;
 		}
@@ -163,6 +172,7 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
 		spin_unlock(&pdata->dyn_callback_lock);
 		return -ENOMEM;
 	}
+	callback->hsdev = hsdev;
 	callback->usage_callback = usage_callback;
 	callback->usage_id = usage_id;
 	callback->priv = NULL;
@@ -181,7 +191,8 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
 
 	spin_lock(&pdata->dyn_callback_lock);
 	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-		if (callback->usage_id == usage_id) {
+		if (callback->usage_id == usage_id &&
+						callback->hsdev == hsdev) {
 			list_del(&callback->list);
 			kfree(callback);
 			break;
@@ -291,6 +302,28 @@ err_free:
 }
 EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value);
 
+int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev,
+				u32 report_id, int field_index, u32 usage_id)
+{
+	struct hid_report *report;
+	struct hid_field *field;
+	int i;
+
+	report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
+	if (!report || (field_index >= report->maxfield))
+		goto done_proc;
+
+	field = report->field[field_index];
+	for (i = 0; i < field->maxusage; ++i) {
+		if (field->usage[i].hid == usage_id)
+			return field->usage[i].usage_index;
+	}
+
+done_proc:
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(hid_sensor_get_usage_index);
+
 int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 				u8 type,
 				u32 usage_id,
@@ -298,8 +331,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 				struct hid_sensor_hub_attribute_info *info)
 {
 	int ret = -1;
-	int i, j;
-	int collection_index = -1;
+	int i;
 	struct hid_report *report;
 	struct hid_field *field;
 	struct hid_report_enum *report_enum;
@@ -313,44 +345,31 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 	info->units = -1;
 	info->unit_expo = -1;
 
-	for (i = 0; i < hdev->maxcollection; ++i) {
-		struct hid_collection *collection = &hdev->collection[i];
-		if (usage_id == collection->usage) {
-			collection_index = i;
-			break;
-		}
-	}
-	if (collection_index == -1)
-		goto err_ret;
-
 	report_enum = &hdev->report_enum[type];
 	list_for_each_entry(report, &report_enum->report_list, list) {
 		for (i = 0; i < report->maxfield; ++i) {
 			field = report->field[i];
-			if (field->physical == usage_id &&
-				field->logical == attr_usage_id) {
-				sensor_hub_fill_attr_info(info, i, report->id,
-							  field);
-				ret = 0;
-			} else {
-				for (j = 0; j < field->maxusage; ++j) {
-					if (field->usage[j].hid ==
-					attr_usage_id &&
-					field->usage[j].collection_index ==
-					collection_index) {
-						sensor_hub_fill_attr_info(info,
-							  i, report->id, field);
-						ret = 0;
-						break;
-					}
+			if (field->maxusage) {
+				if (field->physical == usage_id &&
+					(field->logical == attr_usage_id ||
+					field->usage[0].hid ==
+							attr_usage_id) &&
+					(field->usage[0].collection_index >=
+					hsdev->start_collection_index) &&
+					(field->usage[0].collection_index <
+					hsdev->end_collection_index)) {
+
+					sensor_hub_fill_attr_info(info, i,
+								report->id,
+								field);
+					ret = 0;
+					break;
 				}
 			}
-			if (ret == 0)
-				break;
 		}
+
 	}
 
-err_ret:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info);
@@ -366,7 +385,7 @@ static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message)
 	list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
 		if (callback->usage_callback->suspend)
 			callback->usage_callback->suspend(
-					pdata->hsdev, callback->priv);
+					callback->hsdev, callback->priv);
 	}
 	spin_unlock(&pdata->dyn_callback_lock);
 
@@ -383,7 +402,7 @@ static int sensor_hub_resume(struct hid_device *hdev)
 	list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
 		if (callback->usage_callback->resume)
 			callback->usage_callback->resume(
-					pdata->hsdev, callback->priv);
+					callback->hsdev, callback->priv);
 	}
 	spin_unlock(&pdata->dyn_callback_lock);
 
@@ -410,6 +429,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 	struct hid_sensor_hub_callbacks *callback = NULL;
 	struct hid_collection *collection = NULL;
 	void *priv = NULL;
+	struct hid_sensor_hub_device *hsdev = NULL;
 
 	hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
 			 report->id, size, report->type);
@@ -444,23 +464,26 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 				report->field[i]->usage->collection_index];
 		hid_dbg(hdev, "collection->usage %x\n",
 					collection->usage);
-		callback = sensor_hub_get_callback(pdata->hsdev->hdev,
-						report->field[i]->physical,
-							&priv);
+
+		callback = sensor_hub_get_callback(hdev,
+				report->field[i]->physical,
+				report->field[i]->usage[0].collection_index,
+				&hsdev, &priv);
+
 		if (callback && callback->capture_sample) {
 			if (report->field[i]->logical)
-				callback->capture_sample(pdata->hsdev,
+				callback->capture_sample(hsdev,
 					report->field[i]->logical, sz, ptr,
 					callback->pdev);
 			else
-				callback->capture_sample(pdata->hsdev,
+				callback->capture_sample(hsdev,
 					report->field[i]->usage->hid, sz, ptr,
 					callback->pdev);
 		}
 		ptr += sz;
 	}
 	if (callback && collection && callback->send_event)
-		callback->send_event(pdata->hsdev, collection->usage,
+		callback->send_event(hsdev, collection->usage,
 				callback->pdev);
 	spin_unlock_irqrestore(&pdata->lock, flags);
 
@@ -473,7 +496,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
 	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
 
 	mutex_lock(&data->mutex);
-	if (!hsdev->ref_cnt) {
+	if (!data->ref_cnt) {
 		ret = hid_hw_open(hsdev->hdev);
 		if (ret) {
 			hid_err(hsdev->hdev, "failed to open hid device\n");
@@ -481,7 +504,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
 			return ret;
 		}
 	}
-	hsdev->ref_cnt++;
+	data->ref_cnt++;
 	mutex_unlock(&data->mutex);
 
 	return ret;
@@ -493,8 +516,8 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)
 	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
 
 	mutex_lock(&data->mutex);
-	hsdev->ref_cnt--;
-	if (!hsdev->ref_cnt)
+	data->ref_cnt--;
+	if (!data->ref_cnt)
 		hid_hw_close(hsdev->hdev);
 	mutex_unlock(&data->mutex);
 }
@@ -541,26 +564,19 @@ static int sensor_hub_probe(struct hid_device *hdev,
 	struct sensor_hub_data *sd;
 	int i;
 	char *name;
-	struct hid_report *report;
-	struct hid_report_enum *report_enum;
-	struct hid_field *field;
 	int dev_cnt;
+	struct hid_sensor_hub_device *hsdev;
+	struct hid_sensor_hub_device *last_hsdev = NULL;
 
 	sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
 	if (!sd) {
 		hid_err(hdev, "cannot allocate Sensor data\n");
 		return -ENOMEM;
 	}
-	sd->hsdev = devm_kzalloc(&hdev->dev, sizeof(*sd->hsdev), GFP_KERNEL);
-	if (!sd->hsdev) {
-		hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
-		return -ENOMEM;
-	}
+
 	hid_set_drvdata(hdev, sd);
 	sd->quirks = id->driver_data;
-	sd->hsdev->hdev = hdev;
-	sd->hsdev->vendor_id = hdev->vendor;
-	sd->hsdev->product_id = hdev->product;
+
 	spin_lock_init(&sd->lock);
 	spin_lock_init(&sd->dyn_callback_lock);
 	mutex_init(&sd->mutex);
@@ -578,9 +594,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
 	}
 	INIT_LIST_HEAD(&sd->dyn_callback_list);
 	sd->hid_sensor_client_cnt = 0;
-	report_enum = &hdev->report_enum[HID_INPUT_REPORT];
 
-	dev_cnt = sensor_hub_get_physical_device_count(report_enum);
+	dev_cnt = sensor_hub_get_physical_device_count(hdev);
 	if (dev_cnt > HID_MAX_PHY_DEVICES) {
 		hid_err(hdev, "Invalid Physical device count\n");
 		ret = -EINVAL;
@@ -594,42 +609,63 @@ static int sensor_hub_probe(struct hid_device *hdev,
 			ret = -ENOMEM;
 			goto err_stop_hw;
 	}
-	list_for_each_entry(report, &report_enum->report_list, list) {
-		hid_dbg(hdev, "Report id:%x\n", report->id);
-		field = report->field[0];
-		if (report->maxfield && field &&
-					field->physical) {
+
+	for (i = 0; i < hdev->maxcollection; ++i) {
+		struct hid_collection *collection = &hdev->collection[i];
+
+		if (collection->type == HID_COLLECTION_PHYSICAL) {
+
+			hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
+			if (!hsdev) {
+				hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
+				ret = -ENOMEM;
+				goto err_no_mem;
+			}
+			hsdev->hdev = hdev;
+			hsdev->vendor_id = hdev->vendor;
+			hsdev->product_id = hdev->product;
+			hsdev->start_collection_index = i;
+			if (last_hsdev)
+				last_hsdev->end_collection_index = i;
+			last_hsdev = hsdev;
 			name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
-						field->physical);
+					collection->usage);
 			if (name == NULL) {
 				hid_err(hdev, "Failed MFD device name\n");
 					ret = -ENOMEM;
-					goto err_free_names;
+					goto err_no_mem;
 			}
 			sd->hid_sensor_hub_client_devs[
-				sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO;
+				sd->hid_sensor_client_cnt].id =
+							PLATFORM_DEVID_AUTO;
 			sd->hid_sensor_hub_client_devs[
 				sd->hid_sensor_client_cnt].name = name;
 			sd->hid_sensor_hub_client_devs[
 				sd->hid_sensor_client_cnt].platform_data =
-						sd->hsdev;
+							hsdev;
 			sd->hid_sensor_hub_client_devs[
 				sd->hid_sensor_client_cnt].pdata_size =
-						sizeof(*sd->hsdev);
-			hid_dbg(hdev, "Adding %s:%p\n", name, sd);
+							sizeof(*hsdev);
+			hid_dbg(hdev, "Adding %s:%d\n", name,
+					hsdev->start_collection_index);
 			sd->hid_sensor_client_cnt++;
 		}
 	}
+	if (last_hsdev)
+		last_hsdev->end_collection_index = i;
+
 	ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
 		sd->hid_sensor_client_cnt, NULL, 0, NULL);
 	if (ret < 0)
-		goto err_free_names;
+		goto err_no_mem;
 
 	return ret;
 
-err_free_names:
-	for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
+err_no_mem:
+	for (i = 0; i < sd->hid_sensor_client_cnt; ++i) {
 		kfree(sd->hid_sensor_hub_client_devs[i].name);
+		kfree(sd->hid_sensor_hub_client_devs[i].platform_data);
+	}
 	kfree(sd->hid_sensor_hub_client_devs);
 err_stop_hw:
 	hid_hw_stop(hdev);
@@ -651,8 +687,10 @@ static void sensor_hub_remove(struct hid_device *hdev)
 		complete(&data->pending.ready);
 	spin_unlock_irqrestore(&data->lock, flags);
 	mfd_remove_devices(&hdev->dev);
-	for (i = 0; i < data->hid_sensor_client_cnt ; ++i)
+	for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
 		kfree(data->hid_sensor_hub_client_devs[i].name);
+		kfree(data->hid_sensor_hub_client_devs[i].platform_data);
+	}
 	kfree(data->hid_sensor_hub_client_devs);
 	hid_set_drvdata(hdev, NULL);
 	mutex_destroy(&data->mutex);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 12354055d474..b5fe65e70dc4 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -17,7 +17,8 @@
  * any later version.
  */
 
-/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
+/*
+ * NOTE: in order for the Sony PS3 BD Remote Control to be found by
  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
  *
@@ -30,6 +31,10 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/leds.h>
+#include <linux/power_supply.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/input/mt.h>
 
 #include "hid-ids.h"
 
@@ -41,7 +46,13 @@
 #define DUALSHOCK4_CONTROLLER_USB BIT(5)
 #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
 
-#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
+#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
+#define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
+				DUALSHOCK4_CONTROLLER_BT)
+#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
+				DUALSHOCK4_CONTROLLER)
+#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
+#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
 
 #define MAX_LEDS 4
 
@@ -73,7 +84,8 @@ static const u8 sixaxis_rdesc_fixup2[] = {
 	0xb1, 0x02, 0xc0, 0xc0,
 };
 
-/* The default descriptor doesn't provide mapping for the accelerometers
+/*
+ * The default descriptor doesn't provide mapping for the accelerometers
  * or orientation sensors.  This fixed descriptor maps the accelerometers
  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
  * to usage values 0x43, 0x44 and 0x45.
@@ -332,6 +344,217 @@ static u8 dualshock4_usb_rdesc[] = {
 	0xC0                /*  End Collection                      */
 };
 
+/*
+ * The default behavior of the Dualshock 4 is to send reports using report
+ * type 1 when running over Bluetooth. However, as soon as it receives a
+ * report of type 17 to set the LEDs or rumble it starts returning it's state
+ * in report 17 instead of 1.  Since report 17 is undefined in the default HID
+ * descriptor the button and axis definitions must be moved to report 17 or
+ * the HID layer won't process the received input once a report is sent.
+ */
+static u8 dualshock4_bt_rdesc[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),               */
+	0x09, 0x05,         /*  Usage (Gamepad),                    */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x01,         /*      Report ID (1),                  */
+	0x75, 0x08,         /*      Report Size (8),                */
+	0x95, 0x0A,         /*      Report Count (9),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
+	0x85, 0x02,         /*      Report ID (2),                  */
+	0x09, 0x24,         /*      Usage (24h),                    */
+	0x95, 0x24,         /*      Report Count (36),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xA3,         /*      Report ID (163),                */
+	0x09, 0x25,         /*      Usage (25h),                    */
+	0x95, 0x30,         /*      Report Count (48),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x05,         /*      Report ID (5),                  */
+	0x09, 0x26,         /*      Usage (26h),                    */
+	0x95, 0x28,         /*      Report Count (40),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x06,         /*      Report ID (6),                  */
+	0x09, 0x27,         /*      Usage (27h),                    */
+	0x95, 0x34,         /*      Report Count (52),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x07,         /*      Report ID (7),                  */
+	0x09, 0x28,         /*      Usage (28h),                    */
+	0x95, 0x30,         /*      Report Count (48),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x08,         /*      Report ID (8),                  */
+	0x09, 0x29,         /*      Usage (29h),                    */
+	0x95, 0x2F,         /*      Report Count (47),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
+	0x85, 0x03,         /*      Report ID (3),                  */
+	0x09, 0x21,         /*      Usage (21h),                    */
+	0x95, 0x26,         /*      Report Count (38),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x04,         /*      Report ID (4),                  */
+	0x09, 0x22,         /*      Usage (22h),                    */
+	0x95, 0x2E,         /*      Report Count (46),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xF0,         /*      Report ID (240),                */
+	0x09, 0x47,         /*      Usage (47h),                    */
+	0x95, 0x3F,         /*      Report Count (63),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xF1,         /*      Report ID (241),                */
+	0x09, 0x48,         /*      Usage (48h),                    */
+	0x95, 0x3F,         /*      Report Count (63),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xF2,         /*      Report ID (242),                */
+	0x09, 0x49,         /*      Usage (49h),                    */
+	0x95, 0x0F,         /*      Report Count (15),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x11,         /*      Report ID (17),                 */
+	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
+	0x09, 0x20,         /*      Usage (20h),                    */
+	0x95, 0x02,         /*      Report Count (2),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x05, 0x01,         /*      Usage Page (Desktop),           */
+	0x09, 0x30,         /*      Usage (X),                      */
+	0x09, 0x31,         /*      Usage (Y),                      */
+	0x09, 0x32,         /*      Usage (Z),                      */
+	0x09, 0x35,         /*      Usage (Rz),                     */
+	0x15, 0x00,         /*      Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
+	0x75, 0x08,         /*      Report Size (8),                */
+	0x95, 0x04,         /*      Report Count (4),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x39,         /*      Usage (Hat Switch),             */
+	0x15, 0x00,         /*      Logical Minimum (0),            */
+	0x25, 0x07,         /*      Logical Maximum (7),            */
+	0x75, 0x04,         /*      Report Size (4),                */
+	0x95, 0x01,         /*      Report Count (1),               */
+	0x81, 0x42,         /*      Input (Variable, Null State),   */
+	0x05, 0x09,         /*      Usage Page (Button),            */
+	0x19, 0x01,         /*      Usage Minimum (01h),            */
+	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
+	0x15, 0x00,         /*      Logical Minimum (0),            */
+	0x25, 0x01,         /*      Logical Maximum (1),            */
+	0x75, 0x01,         /*      Report Size (1),                */
+	0x95, 0x0E,         /*      Report Count (14),              */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x75, 0x06,         /*      Report Size (6),                */
+	0x95, 0x01,         /*      Report Count (1),               */
+	0x81, 0x01,         /*      Input (Constant),               */
+	0x05, 0x01,         /*      Usage Page (Desktop),           */
+	0x09, 0x33,         /*      Usage (Rx),                     */
+	0x09, 0x34,         /*      Usage (Ry),                     */
+	0x15, 0x00,         /*      Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
+	0x75, 0x08,         /*      Report Size (8),                */
+	0x95, 0x02,         /*      Report Count (2),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
+	0x09, 0x20,         /*      Usage (20h),                    */
+	0x95, 0x03,         /*      Report Count (3),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x05, 0x01,         /*      Usage Page (Desktop),           */
+	0x19, 0x40,         /*      Usage Minimum (40h),            */
+	0x29, 0x42,         /*      Usage Maximum (42h),            */
+	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
+	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
+	0x75, 0x10,         /*      Report Size (16),               */
+	0x95, 0x03,         /*      Report Count (3),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x19, 0x43,         /*      Usage Minimum (43h),            */
+	0x29, 0x45,         /*      Usage Maximum (45h),            */
+	0x16, 0xFF, 0xBF,   /*      Logical Minimum (-16385),       */
+	0x26, 0x00, 0x40,   /*      Logical Maximum (16384),        */
+	0x95, 0x03,         /*      Report Count (3),               */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
+	0x09, 0x20,         /*      Usage (20h),                    */
+	0x15, 0x00,         /*      Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
+	0x75, 0x08,         /*      Report Size (8),                */
+	0x95, 0x31,         /*      Report Count (51),              */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x21,         /*      Usage (21h),                    */
+	0x75, 0x08,         /*      Report Size (8),                */
+	0x95, 0x4D,         /*      Report Count (77),              */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x12,         /*      Report ID (18),                 */
+	0x09, 0x22,         /*      Usage (22h),                    */
+	0x95, 0x8D,         /*      Report Count (141),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x23,         /*      Usage (23h),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x13,         /*      Report ID (19),                 */
+	0x09, 0x24,         /*      Usage (24h),                    */
+	0x95, 0xCD,         /*      Report Count (205),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x25,         /*      Usage (25h),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x14,         /*      Report ID (20),                 */
+	0x09, 0x26,         /*      Usage (26h),                    */
+	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x27,         /*      Usage (27h),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x15,         /*      Report ID (21),                 */
+	0x09, 0x28,         /*      Usage (28h),                    */
+	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x29,         /*      Usage (29h),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x16,         /*      Report ID (22),                 */
+	0x09, 0x2A,         /*      Usage (2Ah),                    */
+	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x2B,         /*      Usage (2Bh),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x17,         /*      Report ID (23),                 */
+	0x09, 0x2C,         /*      Usage (2Ch),                    */
+	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x2D,         /*      Usage (2Dh),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x18,         /*      Report ID (24),                 */
+	0x09, 0x2E,         /*      Usage (2Eh),                    */
+	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x2F,         /*      Usage (2Fh),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x85, 0x19,         /*      Report ID (25),                 */
+	0x09, 0x30,         /*      Usage (30h),                    */
+	0x96, 0x22, 0x02,   /*      Report Count (546),             */
+	0x81, 0x02,         /*      Input (Variable),               */
+	0x09, 0x31,         /*      Usage (31h),                    */
+	0x91, 0x02,         /*      Output (Variable),              */
+	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
+	0x85, 0x82,         /*      Report ID (130),                */
+	0x09, 0x22,         /*      Usage (22h),                    */
+	0x95, 0x3F,         /*      Report Count (63),              */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x83,         /*      Report ID (131),                */
+	0x09, 0x23,         /*      Usage (23h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x84,         /*      Report ID (132),                */
+	0x09, 0x24,         /*      Usage (24h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x90,         /*      Report ID (144),                */
+	0x09, 0x30,         /*      Usage (30h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x91,         /*      Report ID (145),                */
+	0x09, 0x31,         /*      Usage (31h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x92,         /*      Report ID (146),                */
+	0x09, 0x32,         /*      Usage (32h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0x93,         /*      Report ID (147),                */
+	0x09, 0x33,         /*      Usage (33h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xA0,         /*      Report ID (160),                */
+	0x09, 0x40,         /*      Usage (40h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0x85, 0xA4,         /*      Report ID (164),                */
+	0x09, 0x44,         /*      Usage (44h),                    */
+	0xB1, 0x02,         /*      Feature (Variable),             */
+	0xC0                /*  End Collection                      */
+};
+
 static __u8 ps3remote_rdesc[] = {
 	0x05, 0x01,          /* GUsagePage Generic Desktop */
 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
@@ -449,7 +672,8 @@ static const unsigned int ps3remote_keymap_remote_buttons[] = {
 };
 
 static const unsigned int buzz_keymap[] = {
-	/* The controller has 4 remote buzzers, each with one LED and 5
+	/*
+	 * The controller has 4 remote buzzers, each with one LED and 5
 	 * buttons.
 	 * 
 	 * We use the mapping chosen by the controller, which is:
@@ -487,18 +711,35 @@ static const unsigned int buzz_keymap[] = {
 	[20] = BTN_TRIGGER_HAPPY20,
 };
 
+static enum power_supply_property sony_battery_props[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_STATUS,
+};
+
+static spinlock_t sony_dev_list_lock;
+static LIST_HEAD(sony_device_list);
+
 struct sony_sc {
+	spinlock_t lock;
+	struct list_head list_node;
 	struct hid_device *hdev;
 	struct led_classdev *leds[MAX_LEDS];
-	struct hid_report *output_report;
 	unsigned long quirks;
 	struct work_struct state_worker;
+	struct power_supply battery;
 
 #ifdef CONFIG_SONY_FF
 	__u8 left;
 	__u8 right;
 #endif
 
+	__u8 mac_address[6];
+	__u8 worker_initialized;
+	__u8 cable_state;
+	__u8 battery_charging;
+	__u8 battery_capacity;
 	__u8 led_state[MAX_LEDS];
 	__u8 led_count;
 };
@@ -576,6 +817,10 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
 		rdesc = dualshock4_usb_rdesc;
 		*rsize = sizeof(dualshock4_usb_rdesc);
+	} else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) {
+		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
+		rdesc = dualshock4_bt_rdesc;
+		*rsize = sizeof(dualshock4_bt_rdesc);
 	}
 
 	/* The HID descriptor exposed over BT has a trailing zero byte */
@@ -599,20 +844,127 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 	return rdesc;
 }
 
+static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
+{
+	static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
+	unsigned long flags;
+	__u8 cable_state, battery_capacity, battery_charging;
+
+	/*
+	 * The sixaxis is charging if the battery value is 0xee
+	 * and it is fully charged if the value is 0xef.
+	 * It does not report the actual level while charging so it
+	 * is set to 100% while charging is in progress.
+	 */
+	if (rd[30] >= 0xee) {
+		battery_capacity = 100;
+		battery_charging = !(rd[30] & 0x01);
+	} else {
+		__u8 index = rd[30] <= 5 ? rd[30] : 5;
+		battery_capacity = sixaxis_battery_capacity[index];
+		battery_charging = 0;
+	}
+	cable_state = !((rd[31] >> 4) & 0x01);
+
+	spin_lock_irqsave(&sc->lock, flags);
+	sc->cable_state = cable_state;
+	sc->battery_capacity = battery_capacity;
+	sc->battery_charging = battery_charging;
+	spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
+{
+	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
+						struct hid_input, list);
+	struct input_dev *input_dev = hidinput->input;
+	unsigned long flags;
+	int n, offset;
+	__u8 cable_state, battery_capacity, battery_charging;
+
+	/*
+	 * Battery and touchpad data starts at byte 30 in the USB report and
+	 * 32 in Bluetooth report.
+	 */
+	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
+
+	/*
+	 * The lower 4 bits of byte 30 contain the battery level
+	 * and the 5th bit contains the USB cable state.
+	 */
+	cable_state = (rd[offset] >> 4) & 0x01;
+	battery_capacity = rd[offset] & 0x0F;
+
+	/*
+	 * When a USB power source is connected the battery level ranges from
+	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
+	 * A battery level above 10 when plugged in means charge completed.
+	 */
+	if (!cable_state || battery_capacity > 10)
+		battery_charging = 0;
+	else
+		battery_charging = 1;
+
+	if (!cable_state)
+		battery_capacity++;
+	if (battery_capacity > 10)
+		battery_capacity = 10;
+
+	battery_capacity *= 10;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	sc->cable_state = cable_state;
+	sc->battery_capacity = battery_capacity;
+	sc->battery_charging = battery_charging;
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	offset += 5;
+
+	/*
+	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
+	 * and 37 on Bluetooth.
+	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
+	 * indicator that is 0 when pressed and 1 when not pressed.
+	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
+	 * The data for the second touch is in the same format and immediatly
+	 * follows the data for the first.
+	 */
+	for (n = 0; n < 2; n++) {
+		__u16 x, y;
+
+		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
+		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
+
+		input_mt_slot(input_dev, n);
+		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+					!(rd[offset] >> 7));
+		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+
+		offset += 4;
+	}
+}
+
 static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
 		__u8 *rd, int size)
 {
 	struct sony_sc *sc = hid_get_drvdata(hdev);
 
-	/* Sixaxis HID report has acclerometers/gyro with MSByte first, this
+	/*
+	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
 	 * has to be BYTE_SWAPPED before passing up to joystick interface
 	 */
-	if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
-			rd[0] == 0x01 && size == 49) {
+	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
 		swap(rd[41], rd[42]);
 		swap(rd[43], rd[44]);
 		swap(rd[45], rd[46]);
 		swap(rd[47], rd[48]);
+
+		sixaxis_parse_report(sc, rd, size);
+	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
+			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
+			&& rd[0] == 0x11 && size == 78)) {
+		dualshock4_parse_report(sc, rd, size);
 	}
 
 	return 0;
@@ -706,7 +1058,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
 	if (!buf)
 		return -ENOMEM;
 
-	ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT,
+				 HID_REQ_GET_REPORT);
 
 	if (ret < 0)
 		hid_err(hdev, "can't set operational mode\n");
@@ -719,7 +1072,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
 static int sixaxis_set_operational_bt(struct hid_device *hdev)
 {
 	unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };
-	return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
+	return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+}
+
+/*
+ * Requesting feature report 0x02 in Bluetooth mode changes the state of the
+ * controller so that it sends full input reports of type 0x11.
+ */
+static int dualshock4_set_operational_bt(struct hid_device *hdev)
+{
+	__u8 buf[37] = { 0 };
+
+	return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf),
+				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 }
 
 static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds)
@@ -749,8 +1115,7 @@ static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count)
 
 	if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) {
 		buzz_set_leds(hdev, leds);
-	} else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) ||
-		   (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB)) {
+	} else {
 		for (n = 0; n < count; n++)
 			drv_data->led_state[n] = leds[n];
 		schedule_work(&drv_data->state_worker);
@@ -790,7 +1155,6 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
 	struct sony_sc *drv_data;
 
 	int n;
-	int on = 0;
 
 	drv_data = hid_get_drvdata(hdev);
 	if (!drv_data) {
@@ -799,13 +1163,11 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
 	}
 
 	for (n = 0; n < drv_data->led_count; n++) {
-		if (led == drv_data->leds[n]) {
-			on = !!(drv_data->led_state[n]);
-			break;
-		}
+		if (led == drv_data->leds[n])
+			return drv_data->led_state[n];
 	}
 
-	return on ? LED_FULL : LED_OFF;
+	return LED_OFF;
 }
 
 static void sony_leds_remove(struct hid_device *hdev)
@@ -855,7 +1217,7 @@ static int sony_leds_init(struct hid_device *hdev)
 		/* Validate expected report characteristics. */
 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
 			return -ENODEV;
-	} else if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) {
+	} else if (drv_data->quirks & DUALSHOCK4_CONTROLLER) {
 		drv_data->led_count = 3;
 		max_brightness = 255;
 		use_colors = 1;
@@ -869,9 +1231,11 @@ static int sony_leds_init(struct hid_device *hdev)
 		name_fmt = "%s::sony%d";
 	}
 
-	/* Clear LEDs as we have no way of reading their initial state. This is
+	/*
+	 * Clear LEDs as we have no way of reading their initial state. This is
 	 * only relevant if the driver is loaded after somebody actively set the
-	 * LEDs to on */
+	 * LEDs to on
+	 */
 	sony_set_leds(hdev, initial_values, drv_data->led_count);
 
 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
@@ -941,29 +1305,48 @@ static void sixaxis_state_worker(struct work_struct *work)
 	buf[10] |= sc->led_state[2] << 3;
 	buf[10] |= sc->led_state[3] << 4;
 
-	sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
-					HID_OUTPUT_REPORT);
+	if (sc->quirks & SIXAXIS_CONTROLLER_USB)
+		hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT);
+	else
+		hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf),
+				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
 }
 
 static void dualshock4_state_worker(struct work_struct *work)
 {
 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
 	struct hid_device *hdev = sc->hdev;
-	struct hid_report *report = sc->output_report;
-	__s32 *value = report->field[0]->value;
+	int offset;
+
+	__u8 buf[78] = { 0 };
 
-	value[0] = 0x03;
+	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
+		buf[0] = 0x05;
+		buf[1] = 0x03;
+		offset = 4;
+	} else {
+		buf[0] = 0x11;
+		buf[1] = 0xB0;
+		buf[3] = 0x0F;
+		offset = 6;
+	}
 
 #ifdef CONFIG_SONY_FF
-	value[3] = sc->right;
-	value[4] = sc->left;
+	buf[offset++] = sc->right;
+	buf[offset++] = sc->left;
+#else
+	offset += 2;
 #endif
 
-	value[5] = sc->led_state[0];
-	value[6] = sc->led_state[1];
-	value[7] = sc->led_state[2];
+	buf[offset++] = sc->led_state[0];
+	buf[offset++] = sc->led_state[1];
+	buf[offset++] = sc->led_state[2];
 
-	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
+		hid_hw_output_report(hdev, buf, 32);
+	else
+		hid_hw_raw_request(hdev, 0x11, buf, 78,
+				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
 }
 
 #ifdef CONFIG_SONY_FF
@@ -993,51 +1376,252 @@ static int sony_init_ff(struct hid_device *hdev)
 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
 }
 
-static void sony_destroy_ff(struct hid_device *hdev)
+#else
+static int sony_init_ff(struct hid_device *hdev)
 {
-	struct sony_sc *sc = hid_get_drvdata(hdev);
+	return 0;
+}
+
+#endif
 
-	cancel_work_sync(&sc->state_worker);
+static int sony_battery_get_property(struct power_supply *psy,
+				     enum power_supply_property psp,
+				     union power_supply_propval *val)
+{
+	struct sony_sc *sc = container_of(psy, struct sony_sc, battery);
+	unsigned long flags;
+	int ret = 0;
+	u8 battery_charging, battery_capacity, cable_state;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	battery_charging = sc->battery_charging;
+	battery_capacity = sc->battery_capacity;
+	cable_state = sc->cable_state;
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = 1;
+		break;
+	case POWER_SUPPLY_PROP_SCOPE:
+		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = battery_capacity;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		if (battery_charging)
+			val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			if (battery_capacity == 100 && cable_state)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
 }
 
-#else
-static int sony_init_ff(struct hid_device *hdev)
+static int sony_battery_probe(struct sony_sc *sc)
 {
+	static atomic_t power_id_seq = ATOMIC_INIT(0);
+	unsigned long power_id;
+	struct hid_device *hdev = sc->hdev;
+	int ret;
+
+	/*
+	 * Set the default battery level to 100% to avoid low battery warnings
+	 * if the battery is polled before the first device report is received.
+	 */
+	sc->battery_capacity = 100;
+
+	power_id = (unsigned long)atomic_inc_return(&power_id_seq);
+
+	sc->battery.properties = sony_battery_props;
+	sc->battery.num_properties = ARRAY_SIZE(sony_battery_props);
+	sc->battery.get_property = sony_battery_get_property;
+	sc->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+	sc->battery.use_for_apm = 0;
+	sc->battery.name = kasprintf(GFP_KERNEL, "sony_controller_battery_%lu",
+				     power_id);
+	if (!sc->battery.name)
+		return -ENOMEM;
+
+	ret = power_supply_register(&hdev->dev, &sc->battery);
+	if (ret) {
+		hid_err(hdev, "Unable to register battery device\n");
+		goto err_free;
+	}
+
+	power_supply_powers(&sc->battery, &hdev->dev);
 	return 0;
+
+err_free:
+	kfree(sc->battery.name);
+	sc->battery.name = NULL;
+	return ret;
 }
 
-static void sony_destroy_ff(struct hid_device *hdev)
+static void sony_battery_remove(struct sony_sc *sc)
 {
+	if (!sc->battery.name)
+		return;
+
+	power_supply_unregister(&sc->battery);
+	kfree(sc->battery.name);
+	sc->battery.name = NULL;
 }
-#endif
 
-static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size)
+static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
+					int w, int h)
 {
-	struct list_head *head, *list;
-	struct hid_report *report;
-	struct hid_device *hdev = sc->hdev;
+	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
+						struct hid_input, list);
+	struct input_dev *input_dev = hidinput->input;
+	int ret;
+
+	ret = input_mt_init_slots(input_dev, touch_count, 0);
+	if (ret < 0) {
+		hid_err(sc->hdev, "Unable to initialize multi-touch slots\n");
+		return ret;
+	}
 
-	list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
 
-	list_for_each(head, list) {
-		report = list_entry(head, struct hid_report, list);
+	return 0;
+}
 
-		if (report->id == req_id) {
-			if (report->size < req_size) {
-				hid_err(hdev, "Output report 0x%02x (%i bits) is smaller than requested size (%i bits)\n",
-					req_id, report->size, req_size);
-				return -EINVAL;
-			}
-			sc->output_report = report;
-			return 0;
+/*
+ * If a controller is plugged in via USB while already connected via Bluetooth
+ * it will show up as two devices. A global list of connected controllers and
+ * their MAC addresses is maintained to ensure that a device is only connected
+ * once.
+ */
+static int sony_check_add_dev_list(struct sony_sc *sc)
+{
+	struct sony_sc *entry;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&sony_dev_list_lock, flags);
+
+	list_for_each_entry(entry, &sony_device_list, list_node) {
+		ret = memcmp(sc->mac_address, entry->mac_address,
+				sizeof(sc->mac_address));
+		if (!ret) {
+			ret = -EEXIST;
+			hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
+				sc->mac_address);
+			goto unlock;
 		}
 	}
 
-	hid_err(hdev, "Unable to locate output report 0x%02x\n", req_id);
+	ret = 0;
+	list_add(&(sc->list_node), &sony_device_list);
 
-	return -EINVAL;
+unlock:
+	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
+	return ret;
+}
+
+static void sony_remove_dev_list(struct sony_sc *sc)
+{
+	unsigned long flags;
+
+	if (sc->list_node.next) {
+		spin_lock_irqsave(&sony_dev_list_lock, flags);
+		list_del(&(sc->list_node));
+		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
+	}
 }
 
+static int sony_get_bt_devaddr(struct sony_sc *sc)
+{
+	int ret;
+
+	/* HIDP stores the device MAC address as a string in the uniq field. */
+	ret = strlen(sc->hdev->uniq);
+	if (ret != 17)
+		return -EINVAL;
+
+	ret = sscanf(sc->hdev->uniq,
+		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
+		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
+
+	if (ret != 6)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sony_check_add(struct sony_sc *sc)
+{
+	int n, ret;
+
+	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
+	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
+		/*
+		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
+		 * address from the uniq string where HIDP stores it.
+		 * As uniq cannot be guaranteed to be a MAC address in all cases
+		 * a failure of this function should not prevent the connection.
+		 */
+		if (sony_get_bt_devaddr(sc) < 0) {
+			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
+			return 0;
+		}
+	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
+		__u8 buf[7];
+
+		/*
+		 * The MAC address of a DS4 controller connected via USB can be
+		 * retrieved with feature report 0x81. The address begins at
+		 * offset 1.
+		 */
+		ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf),
+				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+
+		if (ret != 7) {
+			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
+			return ret < 0 ? ret : -EINVAL;
+		}
+
+		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
+	} else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
+		__u8 buf[18];
+
+		/*
+		 * The MAC address of a Sixaxis controller connected via USB can
+		 * be retrieved with feature report 0xf2. The address begins at
+		 * offset 4.
+		 */
+		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf),
+				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+
+		if (ret != 18) {
+			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
+			return ret < 0 ? ret : -EINVAL;
+		}
+
+		/*
+		 * The Sixaxis device MAC in the report is big-endian and must
+		 * be byte-swapped.
+		 */
+		for (n = 0; n < 6; n++)
+			sc->mac_address[5-n] = buf[4+n];
+	} else {
+		return 0;
+	}
+
+	return sony_check_add_dev_list(sc);
+}
+
+
 static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret;
@@ -1077,16 +1661,29 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
 		hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
 		ret = sixaxis_set_operational_usb(hdev);
+		sc->worker_initialized = 1;
 		INIT_WORK(&sc->state_worker, sixaxis_state_worker);
-	}
-	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+	} else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
 		ret = sixaxis_set_operational_bt(hdev);
-	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
-		/* Report 5 (31 bytes) is used to send data to the controller via USB */
-		ret = sony_set_output_report(sc, 0x05, 248);
+		sc->worker_initialized = 1;
+		INIT_WORK(&sc->state_worker, sixaxis_state_worker);
+	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
+		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
+			ret = dualshock4_set_operational_bt(hdev);
+			if (ret < 0) {
+				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
+				goto err_stop;
+			}
+		}
+		/*
+		 * The Dualshock 4 touchpad supports 2 touches and has a
+		 * resolution of 1920x940.
+		 */
+		ret = sony_register_touchpad(sc, 2, 1920, 940);
 		if (ret < 0)
 			goto err_stop;
 
+		sc->worker_initialized = 1;
 		INIT_WORK(&sc->state_worker, dualshock4_state_worker);
 	} else {
 		ret = 0;
@@ -1095,20 +1692,46 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (ret < 0)
 		goto err_stop;
 
+	ret = sony_check_add(sc);
+	if (ret < 0)
+		goto err_stop;
+
 	if (sc->quirks & SONY_LED_SUPPORT) {
 		ret = sony_leds_init(hdev);
 		if (ret < 0)
 			goto err_stop;
 	}
 
-	ret = sony_init_ff(hdev);
-	if (ret < 0)
-		goto err_stop;
+	if (sc->quirks & SONY_BATTERY_SUPPORT) {
+		ret = sony_battery_probe(sc);
+		if (ret < 0)
+			goto err_stop;
+
+		/* Open the device to receive reports with battery info */
+		ret = hid_hw_open(hdev);
+		if (ret < 0) {
+			hid_err(hdev, "hw open failed\n");
+			goto err_stop;
+		}
+	}
+
+	if (sc->quirks & SONY_FF_SUPPORT) {
+		ret = sony_init_ff(hdev);
+		if (ret < 0)
+			goto err_close;
+	}
 
 	return 0;
+err_close:
+	hid_hw_close(hdev);
 err_stop:
 	if (sc->quirks & SONY_LED_SUPPORT)
 		sony_leds_remove(hdev);
+	if (sc->quirks & SONY_BATTERY_SUPPORT)
+		sony_battery_remove(sc);
+	if (sc->worker_initialized)
+		cancel_work_sync(&sc->state_worker);
+	sony_remove_dev_list(sc);
 	hid_hw_stop(hdev);
 	return ret;
 }
@@ -1120,7 +1743,15 @@ static void sony_remove(struct hid_device *hdev)
 	if (sc->quirks & SONY_LED_SUPPORT)
 		sony_leds_remove(hdev);
 
-	sony_destroy_ff(hdev);
+	if (sc->quirks & SONY_BATTERY_SUPPORT) {
+		hid_hw_close(hdev);
+		sony_battery_remove(sc);
+	}
+
+	if (sc->worker_initialized)
+		cancel_work_sync(&sc->state_worker);
+
+	sony_remove_dev_list(sc);
 
 	hid_hw_stop(hdev);
 }
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
index 99342cfa0ea2..a97c78845f7b 100644
--- a/drivers/hid/hid-thingm.c
+++ b/drivers/hid/hid-thingm.c
@@ -48,8 +48,8 @@ static int blink1_send_command(struct blink1_data *data,
 			buf[0], buf[1], buf[2], buf[3], buf[4],
 			buf[5], buf[6], buf[7], buf[8]);
 
-	ret = data->hdev->hid_output_raw_report(data->hdev, buf,
-			BLINK1_CMD_SIZE, HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(data->hdev, buf[0], buf, BLINK1_CMD_SIZE,
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 
 	return ret < 0 ? ret : 0;
 }
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 60c75dcbbdb8..902013ec041b 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -128,8 +128,8 @@ static void wacom_set_image(struct hid_device *hdev, const char *image,
 
 	rep_data[0] = WAC_CMD_ICON_START_STOP;
 	rep_data[1] = 0;
-	ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
-				HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	if (ret < 0)
 		goto err;
 
@@ -143,15 +143,15 @@ static void wacom_set_image(struct hid_device *hdev, const char *image,
 			rep_data[j + 3] = p[(i << 6) + j];
 
 		rep_data[2] = i;
-		ret = hdev->hid_output_raw_report(hdev, rep_data, 67,
-					HID_FEATURE_REPORT);
+		ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 67,
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	}
 
 	rep_data[0] = WAC_CMD_ICON_START_STOP;
 	rep_data[1] = 0;
 
-	ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
-				HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 
 err:
 	return;
@@ -183,7 +183,8 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev,
 		buf[3] = value;
 		/* use fixed brightness for OLEDs */
 		buf[4] = 0x08;
-		hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT);
+		hid_hw_raw_request(hdev, buf[0], buf, 9, HID_FEATURE_REPORT,
+				   HID_REQ_SET_REPORT);
 		kfree(buf);
 	}
 
@@ -339,8 +340,8 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
 		rep_data[0] = 0x03 ; rep_data[1] = 0x00;
 		limit = 3;
 		do {
-			ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
-					HID_FEATURE_REPORT);
+			ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 		} while (ret < 0 && limit-- > 0);
 
 		if (ret >= 0) {
@@ -352,8 +353,9 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
 			rep_data[1] = 0x00;
 			limit = 3;
 			do {
-				ret = hdev->hid_output_raw_report(hdev,
-					rep_data, 2, HID_FEATURE_REPORT);
+				ret = hid_hw_raw_request(hdev, rep_data[0],
+					rep_data, 2, HID_FEATURE_REPORT,
+					HID_REQ_SET_REPORT);
 			} while (ret < 0 && limit-- > 0);
 
 			if (ret >= 0) {
@@ -378,8 +380,8 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
 		rep_data[0] = 0x03;
 		rep_data[1] = wdata->features;
 
-		ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
-					HID_FEATURE_REPORT);
+		ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 		if (ret >= 0)
 			wdata->high_speed = speed;
 		break;
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index abb20db2b443..d00391418d1a 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -28,14 +28,14 @@ static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
 	__u8 *buf;
 	int ret;
 
-	if (!hdev->hid_output_raw_report)
+	if (!hdev->ll_driver->output_report)
 		return -ENODEV;
 
 	buf = kmemdup(buffer, count, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT);
+	ret = hid_hw_output_report(hdev, buf, count);
 
 	kfree(buf);
 	return ret;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index cb0137b3718d..2cc484c0017b 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -123,10 +123,6 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
 
 	dev = hidraw_table[minor]->hid;
 
-	if (!dev->hid_output_raw_report) {
-		ret = -ENODEV;
-		goto out;
-	}
 
 	if (count > HID_MAX_BUFFER_SIZE) {
 		hid_warn(dev, "pid %d passed too large report\n",
@@ -153,7 +149,20 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
 		goto out_free;
 	}
 
-	ret = dev->hid_output_raw_report(dev, buf, count, report_type);
+	if (report_type == HID_OUTPUT_REPORT) {
+		ret = hid_hw_output_report(dev, buf, count);
+		/*
+		 * compatibility with old implementation of USB-HID and I2C-HID:
+		 * if the device does not support receiving output reports,
+		 * on an interrupt endpoint, fallback to SET_REPORT HID command.
+		 */
+		if (ret != -ENOSYS)
+			goto out_free;
+	}
+
+	ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type,
+				HID_REQ_SET_REPORT);
+
 out_free:
 	kfree(buf);
 out:
@@ -189,7 +198,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
 
 	dev = hidraw_table[minor]->hid;
 
-	if (!dev->hid_get_raw_report) {
+	if (!dev->ll_driver->raw_request) {
 		ret = -ENODEV;
 		goto out;
 	}
@@ -216,14 +225,15 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
 
 	/*
 	 * Read the first byte from the user. This is the report number,
-	 * which is passed to dev->hid_get_raw_report().
+	 * which is passed to hid_hw_raw_request().
 	 */
 	if (copy_from_user(&report_number, buffer, 1)) {
 		ret = -EFAULT;
 		goto out_free;
 	}
 
-	ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type);
+	ret = hid_hw_raw_request(dev, report_number, buf, count, report_type,
+				 HID_REQ_GET_REPORT);
 
 	if (ret < 0)
 		goto out_free;
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 42eebd14de1f..b050de41a6c6 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/err.h>
@@ -256,18 +257,27 @@ static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
 	return 0;
 }
 
-static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
-		u8 reportID, unsigned char *buf, size_t data_len)
+/**
+ * i2c_hid_set_or_send_report: forward an incoming report to the device
+ * @client: the i2c_client of the device
+ * @reportType: 0x03 for HID_FEATURE_REPORT ; 0x02 for HID_OUTPUT_REPORT
+ * @reportID: the report ID
+ * @buf: the actual data to transfer, without the report ID
+ * @len: size of buf
+ * @use_data: true: use SET_REPORT HID command, false: send plain OUTPUT report
+ */
+static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType,
+		u8 reportID, unsigned char *buf, size_t data_len, bool use_data)
 {
 	struct i2c_hid *ihid = i2c_get_clientdata(client);
 	u8 *args = ihid->argsbuf;
-	const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd;
+	const struct i2c_hid_cmd *hidcmd;
 	int ret;
 	u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
 	u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
 	u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
 
-	/* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
+	/* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */
 	u16 size =	2			/* size */ +
 			(reportID ? 1 : 0)	/* reportID */ +
 			data_len		/* buf */;
@@ -278,6 +288,9 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
 
 	i2c_hid_dbg(ihid, "%s\n", __func__);
 
+	if (!use_data && maxOutputLength == 0)
+		return -ENOSYS;
+
 	if (reportID >= 0x0F) {
 		args[index++] = reportID;
 		reportID = 0x0F;
@@ -287,9 +300,10 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
 	 * use the data register for feature reports or if the device does not
 	 * support the output register
 	 */
-	if (reportType == 0x03 || maxOutputLength == 0) {
+	if (use_data) {
 		args[index++] = dataRegister & 0xFF;
 		args[index++] = dataRegister >> 8;
+		hidcmd = &hid_set_report_cmd;
 	} else {
 		args[index++] = outputRegister & 0xFF;
 		args[index++] = outputRegister >> 8;
@@ -454,10 +468,18 @@ static void i2c_hid_init_reports(struct hid_device *hid)
 		return;
 	}
 
+	/*
+	 * The device must be powered on while we fetch initial reports
+	 * from it.
+	 */
+	pm_runtime_get_sync(&client->dev);
+
 	list_for_each_entry(report,
 		&hid->report_enum[HID_FEATURE_REPORT].report_list, list)
 		i2c_hid_init_report(report, inbuf, ihid->bufsize);
 
+	pm_runtime_put(&client->dev);
+
 	kfree(inbuf);
 }
 
@@ -550,7 +572,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
 }
 
 static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
-		size_t count, unsigned char report_type)
+		size_t count, unsigned char report_type, bool use_data)
 {
 	struct i2c_client *client = hid->driver_data;
 	int report_id = buf[0];
@@ -564,9 +586,9 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 		count--;
 	}
 
-	ret = i2c_hid_set_report(client,
+	ret = i2c_hid_set_or_send_report(client,
 				report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
-				report_id, buf, count);
+				report_id, buf, count, use_data);
 
 	if (report_id && ret >= 0)
 		ret++; /* add report_id to the number of transfered bytes */
@@ -574,34 +596,40 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 	return ret;
 }
 
-static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
-		int reqtype)
+static int __i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
+		size_t count, unsigned char report_type)
 {
 	struct i2c_client *client = hid->driver_data;
-	char *buf;
-	int ret;
-	int len = i2c_hid_get_report_length(rep) - 2;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	bool data = true; /* SET_REPORT */
 
-	buf = hid_alloc_report_buf(rep, GFP_KERNEL);
-	if (!buf)
-		return;
+	if (report_type == HID_OUTPUT_REPORT)
+		data = le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0;
+
+	return i2c_hid_output_raw_report(hid, buf, count, report_type, data);
+}
+
+static int i2c_hid_output_report(struct hid_device *hid, __u8 *buf,
+		size_t count)
+{
+	return i2c_hid_output_raw_report(hid, buf, count, HID_OUTPUT_REPORT,
+			false);
+}
 
+static int i2c_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
+			       __u8 *buf, size_t len, unsigned char rtype,
+			       int reqtype)
+{
 	switch (reqtype) {
 	case HID_REQ_GET_REPORT:
-		ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type);
-		if (ret < 0)
-			dev_err(&client->dev, "%s: unable to get report: %d\n",
-				__func__, ret);
-		else
-			hid_input_report(hid, rep->type, buf, ret, 0);
-		break;
+		return i2c_hid_get_raw_report(hid, reportnum, buf, len, rtype);
 	case HID_REQ_SET_REPORT:
-		hid_output_report(rep, buf);
-		i2c_hid_output_raw_report(hid, buf, len, rep->type);
-		break;
+		if (buf[0] != reportnum)
+			return -EINVAL;
+		return i2c_hid_output_raw_report(hid, buf, len, rtype, true);
+	default:
+		return -EIO;
 	}
-
-	kfree(buf);
 }
 
 static int i2c_hid_parse(struct hid_device *hid)
@@ -703,8 +731,8 @@ static int i2c_hid_open(struct hid_device *hid)
 
 	mutex_lock(&i2c_hid_open_mut);
 	if (!hid->open++) {
-		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
-		if (ret) {
+		ret = pm_runtime_get_sync(&client->dev);
+		if (ret < 0) {
 			hid->open--;
 			goto done;
 		}
@@ -712,7 +740,7 @@ static int i2c_hid_open(struct hid_device *hid)
 	}
 done:
 	mutex_unlock(&i2c_hid_open_mut);
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static void i2c_hid_close(struct hid_device *hid)
@@ -729,7 +757,7 @@ static void i2c_hid_close(struct hid_device *hid)
 		clear_bit(I2C_HID_STARTED, &ihid->flags);
 
 		/* Save some power */
-		i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+		pm_runtime_put(&client->dev);
 	}
 	mutex_unlock(&i2c_hid_open_mut);
 }
@@ -738,19 +766,18 @@ static int i2c_hid_power(struct hid_device *hid, int lvl)
 {
 	struct i2c_client *client = hid->driver_data;
 	struct i2c_hid *ihid = i2c_get_clientdata(client);
-	int ret = 0;
 
 	i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
 
 	switch (lvl) {
 	case PM_HINT_FULLON:
-		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+		pm_runtime_get_sync(&client->dev);
 		break;
 	case PM_HINT_NORMAL:
-		ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+		pm_runtime_put(&client->dev);
 		break;
 	}
-	return ret;
+	return 0;
 }
 
 static struct hid_ll_driver i2c_hid_ll_driver = {
@@ -760,7 +787,8 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
 	.open = i2c_hid_open,
 	.close = i2c_hid_close,
 	.power = i2c_hid_power,
-	.request = i2c_hid_request,
+	.output_report = i2c_hid_output_report,
+	.raw_request = i2c_hid_raw_request,
 };
 
 static int i2c_hid_init_irq(struct i2c_client *client)
@@ -973,13 +1001,17 @@ static int i2c_hid_probe(struct i2c_client *client,
 	if (ret < 0)
 		goto err;
 
+	pm_runtime_get_noresume(&client->dev);
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_enable(&client->dev);
+
 	ret = i2c_hid_fetch_hid_descriptor(ihid);
 	if (ret < 0)
-		goto err;
+		goto err_pm;
 
 	ret = i2c_hid_init_irq(client);
 	if (ret < 0)
-		goto err;
+		goto err_pm;
 
 	hid = hid_allocate_device();
 	if (IS_ERR(hid)) {
@@ -991,8 +1023,7 @@ static int i2c_hid_probe(struct i2c_client *client,
 
 	hid->driver_data = client;
 	hid->ll_driver = &i2c_hid_ll_driver;
-	hid->hid_get_raw_report = i2c_hid_get_raw_report;
-	hid->hid_output_raw_report = i2c_hid_output_raw_report;
+	hid->hid_output_raw_report = __i2c_hid_output_raw_report;
 	hid->dev.parent = &client->dev;
 	ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev));
 	hid->bus = BUS_I2C;
@@ -1010,6 +1041,7 @@ static int i2c_hid_probe(struct i2c_client *client,
 		goto err_mem_free;
 	}
 
+	pm_runtime_put(&client->dev);
 	return 0;
 
 err_mem_free:
@@ -1018,6 +1050,10 @@ err_mem_free:
 err_irq:
 	free_irq(client->irq, ihid);
 
+err_pm:
+	pm_runtime_put_noidle(&client->dev);
+	pm_runtime_disable(&client->dev);
+
 err:
 	i2c_hid_free_buffers(ihid);
 	kfree(ihid);
@@ -1029,6 +1065,11 @@ static int i2c_hid_remove(struct i2c_client *client)
 	struct i2c_hid *ihid = i2c_get_clientdata(client);
 	struct hid_device *hid;
 
+	pm_runtime_get_sync(&client->dev);
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+
 	hid = ihid->hid;
 	hid_destroy_device(hid);
 
@@ -1074,7 +1115,31 @@ static int i2c_hid_resume(struct device *dev)
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+#ifdef CONFIG_PM_RUNTIME
+static int i2c_hid_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+	disable_irq(client->irq);
+	return 0;
+}
+
+static int i2c_hid_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	enable_irq(client->irq);
+	i2c_hid_set_power(client, I2C_HID_PWR_ON);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops i2c_hid_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
+	SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
+			   NULL)
+};
 
 static const struct i2c_device_id i2c_hid_id_table[] = {
 	{ "hid", 0 },
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index cedc6da93c19..60acee422fdc 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -244,12 +244,35 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
 	return count;
 }
 
+static int uhid_hid_output_report(struct hid_device *hid, __u8 *buf,
+				  size_t count)
+{
+	return uhid_hid_output_raw(hid, buf, count, HID_OUTPUT_REPORT);
+}
+
+static int uhid_raw_request(struct hid_device *hid, unsigned char reportnum,
+			    __u8 *buf, size_t len, unsigned char rtype,
+			    int reqtype)
+{
+	switch (reqtype) {
+	case HID_REQ_GET_REPORT:
+		return uhid_hid_get_raw(hid, reportnum, buf, len, rtype);
+	case HID_REQ_SET_REPORT:
+		/* TODO: implement proper SET_REPORT functionality */
+		return -ENOSYS;
+	default:
+		return -EIO;
+	}
+}
+
 static struct hid_ll_driver uhid_hid_driver = {
 	.start = uhid_hid_start,
 	.stop = uhid_hid_stop,
 	.open = uhid_hid_open,
 	.close = uhid_hid_close,
 	.parse = uhid_hid_parse,
+	.output_report = uhid_hid_output_report,
+	.raw_request = uhid_raw_request,
 };
 
 #ifdef CONFIG_COMPAT
@@ -377,7 +400,6 @@ static int uhid_dev_create(struct uhid_device *uhid,
 	hid->uniq[63] = 0;
 
 	hid->ll_driver = &uhid_hid_driver;
-	hid->hid_get_raw_report = uhid_hid_get_raw;
 	hid->hid_output_raw_report = uhid_hid_output_raw;
 	hid->bus = ev->u.create.bus;
 	hid->vendor = ev->u.create.vendor;
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 44df131d390a..0d1d87533f48 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -884,58 +884,78 @@ static int usbhid_get_raw_report(struct hid_device *hid,
 	return ret;
 }
 
-static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
-		unsigned char report_type)
+static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum,
+				 __u8 *buf, size_t count, unsigned char rtype)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 	struct usb_device *dev = hid_to_usb_dev(hid);
 	struct usb_interface *intf = usbhid->intf;
 	struct usb_host_interface *interface = intf->cur_altsetting;
-	int ret;
+	int ret, skipped_report_id = 0;
 
-	if (usbhid->urbout && report_type != HID_FEATURE_REPORT) {
-		int actual_length;
-		int skipped_report_id = 0;
+	/* Byte 0 is the report number. Report data starts at byte 1.*/
+	buf[0] = reportnum;
+	if (buf[0] == 0x0) {
+		/* Don't send the Report ID */
+		buf++;
+		count--;
+		skipped_report_id = 1;
+	}
 
-		if (buf[0] == 0x0) {
-			/* Don't send the Report ID */
-			buf++;
-			count--;
-			skipped_report_id = 1;
-		}
-		ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
-			buf, count, &actual_length,
-			USB_CTRL_SET_TIMEOUT);
-		/* return the number of bytes transferred */
-		if (ret == 0) {
-			ret = actual_length;
-			/* count also the report id */
-			if (skipped_report_id)
-				ret++;
-		}
-	} else {
-		int skipped_report_id = 0;
-		int report_id = buf[0];
-		if (buf[0] == 0x0) {
-			/* Don't send the Report ID */
-			buf++;
-			count--;
-			skipped_report_id = 1;
-		}
-		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			HID_REQ_SET_REPORT,
 			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			((report_type + 1) << 8) | report_id,
+			((rtype + 1) << 8) | reportnum,
 			interface->desc.bInterfaceNumber, buf, count,
 			USB_CTRL_SET_TIMEOUT);
-		/* count also the report id, if this was a numbered report. */
-		if (ret > 0 && skipped_report_id)
+	/* count also the report id, if this was a numbered report. */
+	if (ret > 0 && skipped_report_id)
+		ret++;
+
+	return ret;
+}
+
+static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count)
+{
+	struct usbhid_device *usbhid = hid->driver_data;
+	struct usb_device *dev = hid_to_usb_dev(hid);
+	int actual_length, skipped_report_id = 0, ret;
+
+	if (!usbhid->urbout)
+		return -ENOSYS;
+
+	if (buf[0] == 0x0) {
+		/* Don't send the Report ID */
+		buf++;
+		count--;
+		skipped_report_id = 1;
+	}
+
+	ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
+				buf, count, &actual_length,
+				USB_CTRL_SET_TIMEOUT);
+	/* return the number of bytes transferred */
+	if (ret == 0) {
+		ret = actual_length;
+		/* count also the report id */
+		if (skipped_report_id)
 			ret++;
 	}
 
 	return ret;
 }
 
+static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf,
+		size_t count, unsigned char report_type)
+{
+	struct usbhid_device *usbhid = hid->driver_data;
+
+	if (usbhid->urbout && report_type != HID_FEATURE_REPORT)
+		return usbhid_output_report(hid, buf, count);
+
+	return usbhid_set_raw_report(hid, buf[0], buf, count, report_type);
+}
+
 static void usbhid_restart_queues(struct usbhid_device *usbhid)
 {
 	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
@@ -1200,6 +1220,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r
 	}
 }
 
+static int usbhid_raw_request(struct hid_device *hid, unsigned char reportnum,
+			      __u8 *buf, size_t len, unsigned char rtype,
+			      int reqtype)
+{
+	switch (reqtype) {
+	case HID_REQ_GET_REPORT:
+		return usbhid_get_raw_report(hid, reportnum, buf, len, rtype);
+	case HID_REQ_SET_REPORT:
+		return usbhid_set_raw_report(hid, reportnum, buf, len, rtype);
+	default:
+		return -EIO;
+	}
+}
+
 static int usbhid_idle(struct hid_device *hid, int report, int idle,
 		int reqtype)
 {
@@ -1223,6 +1257,8 @@ static struct hid_ll_driver usb_hid_driver = {
 	.power = usbhid_power,
 	.request = usbhid_request,
 	.wait = usbhid_wait_io,
+	.raw_request = usbhid_raw_request,
+	.output_report = usbhid_output_report,
 	.idle = usbhid_idle,
 };
 
@@ -1253,7 +1289,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 
 	usb_set_intfdata(intf, hid);
 	hid->ll_driver = &usb_hid_driver;
-	hid->hid_get_raw_report = usbhid_get_raw_report;
 	hid->hid_output_raw_report = usbhid_output_raw_report;
 	hid->ff_init = hid_pidff_init;
 #ifdef CONFIG_USB_HIDDEV
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index 0a74b5661186..5e4dfa4cfe22 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_HYPERV_BALLOON)	+= hv_balloon.o
 hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
-hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o
+hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 69ea36f07b4d..602ca86a6488 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/hyperv.h>
+#include <linux/uio.h>
 
 #include "hyperv_vmbus.h"
 
@@ -554,14 +555,14 @@ EXPORT_SYMBOL_GPL(vmbus_close);
  *
  * Mainly used by Hyper-V drivers.
  */
-int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
+int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
 			   u32 bufferlen, u64 requestid,
 			   enum vmbus_packet_type type, u32 flags)
 {
 	struct vmpacket_descriptor desc;
 	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
 	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
-	struct scatterlist bufferlist[3];
+	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
 	int ret;
 	bool signal = false;
@@ -575,11 +576,12 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
 	desc.len8 = (u16)(packetlen_aligned >> 3);
 	desc.trans_id = requestid;
 
-	sg_init_table(bufferlist, 3);
-	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
-	sg_set_buf(&bufferlist[1], buffer, bufferlen);
-	sg_set_buf(&bufferlist[2], &aligned_data,
-		   packetlen_aligned - packetlen);
+	bufferlist[0].iov_base = &desc;
+	bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor);
+	bufferlist[1].iov_base = buffer;
+	bufferlist[1].iov_len = bufferlen;
+	bufferlist[2].iov_base = &aligned_data;
+	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
 
@@ -605,7 +607,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 	u32 descsize;
 	u32 packetlen;
 	u32 packetlen_aligned;
-	struct scatterlist bufferlist[3];
+	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
 	bool signal = false;
 
@@ -637,11 +639,12 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 		desc.range[i].pfn	 = pagebuffers[i].pfn;
 	}
 
-	sg_init_table(bufferlist, 3);
-	sg_set_buf(&bufferlist[0], &desc, descsize);
-	sg_set_buf(&bufferlist[1], buffer, bufferlen);
-	sg_set_buf(&bufferlist[2], &aligned_data,
-		packetlen_aligned - packetlen);
+	bufferlist[0].iov_base = &desc;
+	bufferlist[0].iov_len = descsize;
+	bufferlist[1].iov_base = buffer;
+	bufferlist[1].iov_len = bufferlen;
+	bufferlist[2].iov_base = &aligned_data;
+	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
 
@@ -665,7 +668,7 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 	u32 descsize;
 	u32 packetlen;
 	u32 packetlen_aligned;
-	struct scatterlist bufferlist[3];
+	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
 	bool signal = false;
 	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
@@ -700,11 +703,12 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
 	       pfncount * sizeof(u64));
 
-	sg_init_table(bufferlist, 3);
-	sg_set_buf(&bufferlist[0], &desc, descsize);
-	sg_set_buf(&bufferlist[1], buffer, bufferlen);
-	sg_set_buf(&bufferlist[2], &aligned_data,
-		packetlen_aligned - packetlen);
+	bufferlist[0].iov_base = &desc;
+	bufferlist[0].iov_len = descsize;
+	bufferlist[1].iov_base = buffer;
+	bufferlist[1].iov_len = bufferlen;
+	bufferlist[2].iov_base = &aligned_data;
+	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
 
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 7e17a5495e02..7e6d78dc9437 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -1171,7 +1171,8 @@ static int dm_thread_func(void *dm_dev)
 	int t;
 
 	while (!kthread_should_stop()) {
-		t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ);
+		t = wait_for_completion_interruptible_timeout(
+						&dm_device.config_event, 1*HZ);
 		/*
 		 * The host expects us to post information on the memory
 		 * pressure every second.
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
new file mode 100644
index 000000000000..eaaa3d843b80
--- /dev/null
+++ b/drivers/hv/hv_fcopy.c
@@ -0,0 +1,414 @@
+/*
+ * An implementation of file copy service.
+ *
+ * Copyright (C) 2014, Microsoft, Inc.
+ *
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/semaphore.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+#include <linux/workqueue.h>
+#include <linux/cdev.h>
+#include <linux/hyperv.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+
+#include "hyperv_vmbus.h"
+
+#define WIN8_SRV_MAJOR		1
+#define WIN8_SRV_MINOR		1
+#define WIN8_SRV_VERSION	(WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * For a class of integration services, including the "file copy service",
+ * the specified protocol is a "request/response" protocol which means that
+ * there can only be single outstanding transaction from the host at any
+ * given point in time. We use this to simplify memory management in this
+ * driver - we cache and process only one message at a time.
+ *
+ * While the request/response protocol is guaranteed by the host, we further
+ * ensure this by serializing packet processing in this driver - we do not
+ * read additional packets from the VMBUs until the current packet is fully
+ * handled.
+ *
+ * The transaction "active" state is set when we receive a request from the
+ * host and we cleanup this state when the transaction is completed - when we
+ * respond to the host with our response. When the transaction active state is
+ * set, we defer handling incoming packets.
+ */
+
+static struct {
+	bool active; /* transaction status - active or not */
+	int recv_len; /* number of bytes received. */
+	struct hv_fcopy_hdr  *fcopy_msg; /* current message */
+	struct hv_start_fcopy  message; /*  sent to daemon */
+	struct vmbus_channel *recv_channel; /* chn we got the request */
+	u64 recv_req_id; /* request ID. */
+	void *fcopy_context; /* for the channel callback */
+	struct semaphore read_sema;
+} fcopy_transaction;
+
+static bool opened; /* currently device opened */
+
+/*
+ * Before we can accept copy messages from the host, we need
+ * to handshake with the user level daemon. This state tracks
+ * if we are in the handshake phase.
+ */
+static bool in_hand_shake = true;
+static void fcopy_send_data(void);
+static void fcopy_respond_to_host(int error);
+static void fcopy_work_func(struct work_struct *dummy);
+static DECLARE_DELAYED_WORK(fcopy_work, fcopy_work_func);
+static u8 *recv_buffer;
+
+static void fcopy_work_func(struct work_struct *dummy)
+{
+	/*
+	 * If the timer fires, the user-mode component has not responded;
+	 * process the pending transaction.
+	 */
+	fcopy_respond_to_host(HV_E_FAIL);
+}
+
+static int fcopy_handle_handshake(u32 version)
+{
+	switch (version) {
+	case FCOPY_CURRENT_VERSION:
+		break;
+	default:
+		/*
+		 * For now we will fail the registration.
+		 * If and when we have multiple versions to
+		 * deal with, we will be backward compatible.
+		 * We will add this code when needed.
+		 */
+		return -EINVAL;
+	}
+	pr_info("FCP: user-mode registering done. Daemon version: %d\n",
+		version);
+	fcopy_transaction.active = false;
+	if (fcopy_transaction.fcopy_context)
+		hv_fcopy_onchannelcallback(fcopy_transaction.fcopy_context);
+	in_hand_shake = false;
+	return 0;
+}
+
+static void fcopy_send_data(void)
+{
+	struct hv_start_fcopy *smsg_out = &fcopy_transaction.message;
+	int operation = fcopy_transaction.fcopy_msg->operation;
+	struct hv_start_fcopy *smsg_in;
+
+	/*
+	 * The  strings sent from the host are encoded in
+	 * in utf16; convert it to utf8 strings.
+	 * The host assures us that the utf16 strings will not exceed
+	 * the max lengths specified. We will however, reserve room
+	 * for the string terminating character - in the utf16s_utf8s()
+	 * function we limit the size of the buffer where the converted
+	 * string is placed to W_MAX_PATH -1 to guarantee
+	 * that the strings can be properly terminated!
+	 */
+
+	switch (operation) {
+	case START_FILE_COPY:
+		memset(smsg_out, 0, sizeof(struct hv_start_fcopy));
+		smsg_out->hdr.operation = operation;
+		smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
+
+		utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)smsg_out->file_name, W_MAX_PATH - 1);
+
+		utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)smsg_out->path_name, W_MAX_PATH - 1);
+
+		smsg_out->copy_flags = smsg_in->copy_flags;
+		smsg_out->file_size = smsg_in->file_size;
+		break;
+
+	default:
+		break;
+	}
+	up(&fcopy_transaction.read_sema);
+	return;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+fcopy_respond_to_host(int error)
+{
+	struct icmsg_hdr *icmsghdr;
+	u32 buf_len;
+	struct vmbus_channel *channel;
+	u64 req_id;
+
+	/*
+	 * Copy the global state for completing the transaction. Note that
+	 * only one transaction can be active at a time. This is guaranteed
+	 * by the file copy protocol implemented by the host. Furthermore,
+	 * the "transaction active" state we maintain ensures that there can
+	 * only be one active transaction at a time.
+	 */
+
+	buf_len = fcopy_transaction.recv_len;
+	channel = fcopy_transaction.recv_channel;
+	req_id = fcopy_transaction.recv_req_id;
+
+	fcopy_transaction.active = false;
+
+	icmsghdr = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+
+	if (channel->onchannel_callback == NULL)
+		/*
+		 * We have raced with util driver being unloaded;
+		 * silently return.
+		 */
+		return;
+
+	icmsghdr->status = error;
+	icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+}
+
+void hv_fcopy_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct hv_fcopy_hdr *fcopy_msg;
+	struct icmsg_hdr *icmsghdr;
+	struct icmsg_negotiate *negop = NULL;
+	int util_fw_version;
+	int fcopy_srv_version;
+
+	if (fcopy_transaction.active) {
+		/*
+		 * We will defer processing this callback once
+		 * the current transaction is complete.
+		 */
+		fcopy_transaction.fcopy_context = context;
+		return;
+	}
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
+			 &requestid);
+	if (recvlen <= 0)
+		return;
+
+	icmsghdr = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+	if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+		util_fw_version = UTIL_FW_VERSION;
+		fcopy_srv_version = WIN8_SRV_VERSION;
+		vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer,
+				util_fw_version, fcopy_srv_version);
+	} else {
+		fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+		/*
+		 * Stash away this global state for completing the
+		 * transaction; note transactions are serialized.
+		 */
+
+		fcopy_transaction.active = true;
+		fcopy_transaction.recv_len = recvlen;
+		fcopy_transaction.recv_channel = channel;
+		fcopy_transaction.recv_req_id = requestid;
+		fcopy_transaction.fcopy_msg = fcopy_msg;
+
+		/*
+		 * Send the information to the user-level daemon.
+		 */
+		fcopy_send_data();
+		schedule_delayed_work(&fcopy_work, 5*HZ);
+		return;
+	}
+	icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+	vmbus_sendpacket(channel, recv_buffer, recvlen, requestid,
+			VM_PKT_DATA_INBAND, 0);
+}
+
+/*
+ * Create a char device that can support read/write for passing
+ * the payload.
+ */
+
+static ssize_t fcopy_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	void *src;
+	size_t copy_size;
+	int operation;
+
+	/*
+	 * Wait until there is something to be read.
+	 */
+	if (down_interruptible(&fcopy_transaction.read_sema))
+		return -EINTR;
+
+	/*
+	 * The channel may be rescinded and in this case, we will wakeup the
+	 * the thread blocked on the semaphore and we will use the opened
+	 * state to correctly handle this case.
+	 */
+	if (!opened)
+		return -ENODEV;
+
+	operation = fcopy_transaction.fcopy_msg->operation;
+
+	if (operation == START_FILE_COPY) {
+		src = &fcopy_transaction.message;
+		copy_size = sizeof(struct hv_start_fcopy);
+		if (count < copy_size)
+			return 0;
+	} else {
+		src = fcopy_transaction.fcopy_msg;
+		copy_size = sizeof(struct hv_do_fcopy);
+		if (count < copy_size)
+			return 0;
+	}
+	if (copy_to_user(buf, src, copy_size))
+		return -EFAULT;
+
+	return copy_size;
+}
+
+static ssize_t fcopy_write(struct file *file, const char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	int response = 0;
+
+	if (count != sizeof(int))
+		return -EINVAL;
+
+	if (copy_from_user(&response, buf, sizeof(int)))
+		return -EFAULT;
+
+	if (in_hand_shake) {
+		if (fcopy_handle_handshake(response))
+			return -EINVAL;
+		return sizeof(int);
+	}
+
+	/*
+	 * Complete the transaction by forwarding the result
+	 * to the host. But first, cancel the timeout.
+	 */
+	if (cancel_delayed_work_sync(&fcopy_work))
+		fcopy_respond_to_host(response);
+
+	return sizeof(int);
+}
+
+static int fcopy_open(struct inode *inode, struct file *f)
+{
+	/*
+	 * The user level daemon that will open this device is
+	 * really an extension of this driver. We can have only
+	 * active open at a time.
+	 */
+	if (opened)
+		return -EBUSY;
+
+	/*
+	 * The daemon is alive; setup the state.
+	 */
+	opened = true;
+	return 0;
+}
+
+static int fcopy_release(struct inode *inode, struct file *f)
+{
+	/*
+	 * The daemon has exited; reset the state.
+	 */
+	in_hand_shake = true;
+	opened = false;
+	return 0;
+}
+
+
+static const struct file_operations fcopy_fops = {
+	.read           = fcopy_read,
+	.write          = fcopy_write,
+	.release	= fcopy_release,
+	.open		= fcopy_open,
+};
+
+static struct miscdevice fcopy_misc = {
+	.minor          = MISC_DYNAMIC_MINOR,
+	.name           = "vmbus/hv_fcopy",
+	.fops           = &fcopy_fops,
+};
+
+static int fcopy_dev_init(void)
+{
+	return misc_register(&fcopy_misc);
+}
+
+static void fcopy_dev_deinit(void)
+{
+
+	/*
+	 * The device is going away - perhaps because the
+	 * host has rescinded the channel. Setup state so that
+	 * user level daemon can gracefully exit if it is blocked
+	 * on the read semaphore.
+	 */
+	opened = false;
+	/*
+	 * Signal the semaphore as the device is
+	 * going away.
+	 */
+	up(&fcopy_transaction.read_sema);
+	misc_deregister(&fcopy_misc);
+}
+
+int hv_fcopy_init(struct hv_util_service *srv)
+{
+	recv_buffer = srv->recv_buffer;
+
+	/*
+	 * When this driver loads, the user level daemon that
+	 * processes the host requests may not yet be running.
+	 * Defer processing channel callbacks until the daemon
+	 * has registered.
+	 */
+	fcopy_transaction.active = true;
+	sema_init(&fcopy_transaction.read_sema, 0);
+
+	return fcopy_dev_init();
+}
+
+void hv_fcopy_deinit(void)
+{
+	cancel_delayed_work_sync(&fcopy_work);
+	fcopy_dev_deinit();
+}
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 09988b289622..ea852537307e 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -113,7 +113,7 @@ kvp_register(int reg_value)
 		kvp_msg->kvp_hdr.operation = reg_value;
 		strcpy(version, HV_DRV_VERSION);
 		msg->len = sizeof(struct hv_kvp_msg);
-		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
 		kfree(msg);
 	}
 }
@@ -435,7 +435,7 @@ kvp_send_key(struct work_struct *dummy)
 	}
 
 	msg->len = sizeof(struct hv_kvp_msg);
-	cn_netlink_send(msg, 0, GFP_ATOMIC);
+	cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
 	kfree(msg);
 
 	return;
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 0c3546224376..34f14fddb666 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -98,7 +98,7 @@ static void vss_send_op(struct work_struct *dummy)
 	vss_msg->vss_hdr.operation = op;
 	msg->len = sizeof(struct hv_vss_msg);
 
-	cn_netlink_send(msg, 0, GFP_ATOMIC);
+	cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
 	kfree(msg);
 
 	return;
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 62dfd246b948..dd761806f0e8 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -28,6 +28,7 @@
 #include <linux/reboot.h>
 #include <linux/hyperv.h>
 
+#include "hyperv_vmbus.h"
 
 #define SD_MAJOR	3
 #define SD_MINOR	0
@@ -82,6 +83,12 @@ static struct hv_util_service util_vss = {
 	.util_deinit = hv_vss_deinit,
 };
 
+static struct hv_util_service util_fcopy = {
+	.util_cb = hv_fcopy_onchannelcallback,
+	.util_init = hv_fcopy_init,
+	.util_deinit = hv_fcopy_deinit,
+};
+
 static void perform_shutdown(struct work_struct *dummy)
 {
 	orderly_poweroff(true);
@@ -401,6 +408,10 @@ static const struct hv_vmbus_device_id id_table[] = {
 	{ HV_VSS_GUID,
 	  .driver_data = (unsigned long)&util_vss
 	},
+	/* File copy GUID */
+	{ HV_FCOPY_GUID,
+	  .driver_data = (unsigned long)&util_fcopy
+	},
 	{ },
 };
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index e05517616a06..860134da8039 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -559,8 +559,8 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
 void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
 
 int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
-		    struct scatterlist *sglist,
-		    u32 sgcount, bool *signal);
+		    struct kvec *kv_list,
+		    u32 kv_count, bool *signal);
 
 int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
 		   u32 buflen);
@@ -669,5 +669,9 @@ int vmbus_set_event(struct vmbus_channel *channel);
 
 void vmbus_on_event(unsigned long data);
 
+int hv_fcopy_init(struct hv_util_service *);
+void hv_fcopy_deinit(void);
+void hv_fcopy_onchannelcallback(void *);
+
 
 #endif /* _HYPERV_VMBUS_H */
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 26c93cf9f6be..15db66b74141 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/hyperv.h>
+#include <linux/uio.h>
 
 #include "hyperv_vmbus.h"
 
@@ -387,23 +388,20 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
  *
  */
 int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
-		    struct scatterlist *sglist, u32 sgcount, bool *signal)
+		    struct kvec *kv_list, u32 kv_count, bool *signal)
 {
 	int i = 0;
 	u32 bytes_avail_towrite;
 	u32 bytes_avail_toread;
 	u32 totalbytes_towrite = 0;
 
-	struct scatterlist *sg;
 	u32 next_write_location;
 	u32 old_write;
 	u64 prev_indices = 0;
 	unsigned long flags;
 
-	for_each_sg(sglist, sg, sgcount, i)
-	{
-		totalbytes_towrite += sg->length;
-	}
+	for (i = 0; i < kv_count; i++)
+		totalbytes_towrite += kv_list[i].iov_len;
 
 	totalbytes_towrite += sizeof(u64);
 
@@ -427,12 +425,11 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
 
 	old_write = next_write_location;
 
-	for_each_sg(sglist, sg, sgcount, i)
-	{
+	for (i = 0; i < kv_count; i++) {
 		next_write_location = hv_copyto_ringbuffer(outring_info,
 						     next_write_location,
-						     sg_virt(sg),
-						     sg->length);
+						     kv_list[i].iov_base,
+						     kv_list[i].iov_len);
 	}
 
 	/* Set previous packet start */
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 077bb1bdac34..a14f60340bfc 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -44,6 +44,12 @@ static struct tasklet_struct msg_dpc;
 static struct completion probe_event;
 static int irq;
 
+struct resource hyperv_mmio = {
+	.name  = "hyperv mmio",
+	.flags = IORESOURCE_MEM,
+};
+EXPORT_SYMBOL_GPL(hyperv_mmio);
+
 static int vmbus_exists(void)
 {
 	if (hv_acpi_dev == NULL)
@@ -886,18 +892,21 @@ void vmbus_device_unregister(struct hv_device *device_obj)
 
 
 /*
- * VMBUS is an acpi enumerated device. Get the the IRQ information
- * from DSDT.
+ * VMBUS is an acpi enumerated device. Get the the information we
+ * need from DSDT.
  */
 
-static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
+static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 {
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+		irq = res->data.irq.interrupts[0];
+		break;
 
-	if (res->type == ACPI_RESOURCE_TYPE_IRQ) {
-		struct acpi_resource_irq *irqp;
-		irqp = &res->data.irq;
-
-		*((unsigned int *)irq) = irqp->interrupts[0];
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		hyperv_mmio.start = res->data.address64.minimum;
+		hyperv_mmio.end = res->data.address64.maximum;
+		break;
 	}
 
 	return AE_OK;
@@ -906,18 +915,34 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
 static int vmbus_acpi_add(struct acpi_device *device)
 {
 	acpi_status result;
+	int ret_val = -ENODEV;
 
 	hv_acpi_dev = device;
 
 	result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-					vmbus_walk_resources, &irq);
+					vmbus_walk_resources, NULL);
 
-	if (ACPI_FAILURE(result)) {
-		complete(&probe_event);
-		return -ENODEV;
+	if (ACPI_FAILURE(result))
+		goto acpi_walk_err;
+	/*
+	 * The parent of the vmbus acpi device (Gen2 firmware) is the VMOD that
+	 * has the mmio ranges. Get that.
+	 */
+	if (device->parent) {
+		result = acpi_walk_resources(device->parent->handle,
+					METHOD_NAME__CRS,
+					vmbus_walk_resources, NULL);
+
+		if (ACPI_FAILURE(result))
+			goto acpi_walk_err;
+		if (hyperv_mmio.start && hyperv_mmio.end)
+			request_resource(&iomem_resource, &hyperv_mmio);
 	}
+	ret_val = 0;
+
+acpi_walk_err:
 	complete(&probe_event);
-	return 0;
+	return ret_val;
 }
 
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5ce43d8dfa98..f288b60a87be 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -111,22 +111,6 @@ config SENSORS_AD7418
 	  This driver can also be built as a module. If so, the module
 	  will be called ad7418.
 
-config SENSORS_ADCXX
-	tristate "National Semiconductor ADCxxxSxxx"
-	depends on SPI_MASTER
-	help
-	  If you say yes here you get support for the National Semiconductor
-	  ADC<bb><c>S<sss> chip family, where
-	  * bb  is the resolution in number of bits (8, 10, 12)
-	  * c   is the number of channels (1, 2, 4, 8)
-	  * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500
-	    kSPS and 101 for 1 MSPS)
-
-	  Examples : ADC081S101, ADC124S501, ...
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called adcxx.
-
 config SENSORS_ADM1021
 	tristate "Analog Devices ADM1021 and compatibles"
 	depends on I2C
@@ -312,6 +296,31 @@ config SENSORS_FAM15H_POWER
 	  This driver can also be built as a module.  If so, the module
 	  will be called fam15h_power.
 
+config SENSORS_APPLESMC
+	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
+	depends on INPUT && X86
+	select NEW_LEDS
+	select LEDS_CLASS
+	select INPUT_POLLDEV
+	default n
+	help
+	  This driver provides support for the Apple System Management
+	  Controller, which provides an accelerometer (Apple Sudden Motion
+	  Sensor), light sensors, temperature sensors, keyboard backlight
+	  control and fan control.
+
+	  Only Intel-based Apple's computers are supported (MacBook Pro,
+	  MacBook, MacMini).
+
+	  Data from the different sensors, keyboard backlight control and fan
+	  control are accessible via sysfs.
+
+	  This driver also provides an absolute input class device, allowing
+	  the laptop to act as a pinball machine-esque joystick.
+
+	  Say Y here if you have an applicable laptop and want to experience
+	  the awesome power of applesmc.
+
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
 	depends on X86 && I2C
@@ -435,6 +444,12 @@ config SENSORS_F75375S
 	  This driver can also be built as a module.  If so, the module
 	  will be called f75375s.
 
+config SENSORS_MC13783_ADC
+        tristate "Freescale MC13783/MC13892 ADC"
+        depends on MFD_MC13XXX
+        help
+          Support for the A/D converter on MC13783 and MC13892 PMIC.
+
 config SENSORS_FSCHMD
 	tristate "Fujitsu Siemens Computers sensor chips"
 	depends on X86 && I2C
@@ -451,26 +466,6 @@ config SENSORS_FSCHMD
 	  This driver can also be built as a module.  If so, the module
 	  will be called fschmd.
 
-config SENSORS_G760A
-	tristate "GMT G760A"
-	depends on I2C
-	help
-	  If you say yes here you get support for Global Mixed-mode
-	  Technology Inc G760A fan speed PWM controller chips.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called g760a.
-
-config SENSORS_G762
-	tristate "GMT G762 and G763"
-	depends on I2C
-	help
-	  If you say yes here you get support for Global Mixed-mode
-	  Technology Inc G762 and G763 fan speed PWM controller chips.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called g762.
-
 config SENSORS_GL518SM
 	tristate "Genesys Logic GL518SM"
 	depends on I2C
@@ -492,6 +487,26 @@ config SENSORS_GL520SM
 	  This driver can also be built as a module.  If so, the module
 	  will be called gl520sm.
 
+config SENSORS_G760A
+	tristate "GMT G760A"
+	depends on I2C
+	help
+	  If you say yes here you get support for Global Mixed-mode
+	  Technology Inc G760A fan speed PWM controller chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called g760a.
+
+config SENSORS_G762
+	tristate "GMT G762 and G763"
+	depends on I2C
+	help
+	  If you say yes here you get support for Global Mixed-mode
+	  Technology Inc G762 and G763 fan speed PWM controller chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called g762.
+
 config SENSORS_GPIO_FAN
 	tristate "GPIO fan"
 	depends on GPIOLIB
@@ -511,24 +526,6 @@ config SENSORS_HIH6130
 	  This driver can also be built as a module.  If so, the module
 	  will be called hih6130.
 
-config SENSORS_HTU21
-	tristate "Measurement Specialties HTU21D humidity/temperature sensors"
-	depends on I2C
-	help
-	  If you say yes here you get support for the Measurement Specialties
-	  HTU21D humidity and temperature sensors.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called htu21.
-
-config SENSORS_CORETEMP
-	tristate "Intel Core/Core2/Atom temperature sensor"
-	depends on X86
-	help
-	  If you say yes here you get support for the temperature
-	  sensor inside your CPU. Most of the family 6 CPUs
-	  are supported. Check Documentation/hwmon/coretemp for details.
-
 config SENSORS_IBMAEM
 	tristate "IBM Active Energy Manager temperature/power sensors and control"
 	select IPMI_SI
@@ -566,6 +563,14 @@ config SENSORS_IIO_HWMON
 	  for those channels specified in the map.  This map can be provided
 	  either via platform data or the device tree bindings.
 
+config SENSORS_CORETEMP
+	tristate "Intel Core/Core2/Atom temperature sensor"
+	depends on X86
+	help
+	  If you say yes here you get support for the temperature
+	  sensor inside your CPU. Most of the family 6 CPUs
+	  are supported. Check Documentation/hwmon/coretemp for details.
+
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
 	depends on !PPC
@@ -614,374 +619,409 @@ config SENSORS_LINEAGE
 	  This driver can also be built as a module.  If so, the module
 	  will be called lineage-pem.
 
-config SENSORS_LM63
-	tristate "National Semiconductor LM63 and compatibles"
+config SENSORS_LTC2945
+	tristate "Linear Technology LTC2945"
 	depends on I2C
+	select REGMAP_I2C
+	default n
 	help
-	  If you say yes here you get support for the National
-	  Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
-	  sensors with integrated fan control.  Such chips are found
-	  on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
-	  others.
+	  If you say yes here you get support for Linear Technology LTC2945
+	  I2C System Monitor.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called lm63.
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc2945.
 
-config SENSORS_LM70
-	tristate "National Semiconductor LM70 and compatibles"
-	depends on SPI_MASTER
+config SENSORS_LTC4151
+	tristate "Linear Technology LTC4151"
+	depends on I2C
+	default n
 	help
-	  If you say yes here you get support for the National Semiconductor
-	  LM70, LM71, LM74 and Texas Instruments TMP121/TMP123 digital tempera-
-	  ture sensor chips.
+	  If you say yes here you get support for Linear Technology LTC4151
+	  High Voltage I2C Current and Voltage Monitor interface.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called lm70.
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4151.
 
-config SENSORS_LM73
-	tristate "National Semiconductor LM73"
+config SENSORS_LTC4215
+	tristate "Linear Technology LTC4215"
 	depends on I2C
+	default n
 	help
-	  If you say yes here you get support for National Semiconductor LM73
-	  sensor chips.
-	  This driver can also be built as a module.  If so, the module
-	  will be called lm73.
+	  If you say yes here you get support for Linear Technology LTC4215
+	  Hot Swap Controller I2C interface.
 
-config SENSORS_LM75
-	tristate "National Semiconductor LM75 and compatibles"
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4215.
+
+config SENSORS_LTC4222
+	tristate "Linear Technology LTC4222"
 	depends on I2C
-	depends on THERMAL || !THERMAL_OF
+	select REGMAP_I2C
+	default n
 	help
-	  If you say yes here you get support for one common type of
-	  temperature sensor chip, with models including:
+	  If you say yes here you get support for Linear Technology LTC4222
+	  Dual Hot Swap Controller I2C interface.
 
-		- Analog Devices ADT75
-		- Dallas Semiconductor DS75, DS1775 and DS7505
-		- Global Mixed-mode Technology (GMT) G751
-		- Maxim MAX6625 and MAX6626
-		- Microchip MCP980x
-		- National Semiconductor LM75, LM75A
-		- NXP's LM75A
-		- ST Microelectronics STDS75
-		- TelCom (now Microchip) TCN75
-		- Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
-		  TMP275
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4222.
 
-	  This driver supports driver model based binding through board
-	  specific I2C device tables.
+config SENSORS_LTC4245
+	tristate "Linear Technology LTC4245"
+	depends on I2C
+	default n
+	help
+	  If you say yes here you get support for Linear Technology LTC4245
+	  Multiple Supply Hot Swap Controller I2C interface.
 
-	  It also supports the "legacy" style of driver binding.  To use
-	  that with some chips which don't replicate LM75 quirks exactly,
-	  you may need the "force" module parameter.
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4245.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called lm75.
+config SENSORS_LTC4260
+	tristate "Linear Technology LTC4260"
+	depends on I2C
+	select REGMAP_I2C
+	default n
+	help
+	  If you say yes here you get support for Linear Technology LTC4260
+	  Positive Voltage Hot Swap Controller I2C interface.
 
-config SENSORS_LM77
-	tristate "National Semiconductor LM77"
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4260.
+
+config SENSORS_LTC4261
+	tristate "Linear Technology LTC4261"
 	depends on I2C
+	default n
 	help
-	  If you say yes here you get support for National Semiconductor LM77
-	  sensor chips.
+	  If you say yes here you get support for Linear Technology LTC4261
+	  Negative Voltage Hot Swap Controller I2C interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4261.
+
+config SENSORS_MAX1111
+	tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles"
+	depends on SPI_MASTER
+	help
+	  Say y here to support Maxim's MAX1110, MAX1111, MAX1112, and MAX1113
+	  ADC chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm77.
+	  will be called max1111.
 
-config SENSORS_LM78
-	tristate "National Semiconductor LM78 and compatibles"
+config SENSORS_MAX16065
+	tristate "Maxim MAX16065 System Manager and compatibles"
 	depends on I2C
-	select HWMON_VID
 	help
-	  If you say yes here you get support for National Semiconductor LM78,
-	  LM78-J and LM79.
+	  If you say yes here you get support for hardware monitoring
+	  capabilities of the following Maxim System Manager chips.
+	    MAX16065
+	    MAX16066
+	    MAX16067
+	    MAX16068
+	    MAX16070
+	    MAX16071
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm78.
+	  will be called max16065.
 
-config SENSORS_LM80
-	tristate "National Semiconductor LM80 and LM96080"
+config SENSORS_MAX1619
+	tristate "Maxim MAX1619 sensor chip"
 	depends on I2C
 	help
-	  If you say yes here you get support for National Semiconductor
-	  LM80 and LM96080 sensor chips.
+	  If you say yes here you get support for MAX1619 sensor chip.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm80.
+	  will be called max1619.
 
-config SENSORS_LM83
-	tristate "National Semiconductor LM83 and compatibles"
+config SENSORS_MAX1668
+	tristate "Maxim MAX1668 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for National Semiconductor
-	  LM82 and LM83 sensor chips.
+	  If you say yes here you get support for MAX1668, MAX1989 and
+	  MAX1805 chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm83.
+	  will be called max1668.
 
-config SENSORS_LM85
-	tristate "National Semiconductor LM85 and compatibles"
+config SENSORS_MAX197
+	tristate "Maxim MAX197 and compatibles"
+	help
+	  Support for the Maxim MAX197 A/D converter.
+	  Support will include, but not be limited to, MAX197, and MAX199.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called max197.
+
+config SENSORS_MAX6639
+	tristate "Maxim MAX6639 sensor chip"
 	depends on I2C
-	select HWMON_VID
 	help
-	  If you say yes here you get support for National Semiconductor LM85
-	  sensor chips and clones: ADM1027, ADT7463, ADT7468, EMC6D100,
-	  EMC6D101, EMC6D102, and EMC6D103.
+	  If you say yes here you get support for the MAX6639
+	  sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm85.
+	  will be called max6639.
 
-config SENSORS_LM87
-	tristate "National Semiconductor LM87 and compatibles"
+config SENSORS_MAX6642
+	tristate "Maxim MAX6642 sensor chip"
 	depends on I2C
-	select HWMON_VID
 	help
-	  If you say yes here you get support for National Semiconductor LM87
-	  and Analog Devices ADM1024 sensor chips.
+	  If you say yes here you get support for MAX6642 sensor chip.
+	  MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
+	  with Overtemperature Alarm from Maxim.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm87.
+	  will be called max6642.
 
-config SENSORS_LM90
-	tristate "National Semiconductor LM90 and compatibles"
+config SENSORS_MAX6650
+	tristate "Maxim MAX6650 sensor chip"
 	depends on I2C
 	help
-	  If you say yes here you get support for National Semiconductor LM90,
-	  LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
-	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
-	  Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, and GMT G781
+	  If you say yes here you get support for the MAX6650 / MAX6651
 	  sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm90.
+	  will be called max6650.
 
-config SENSORS_LM92
-	tristate "National Semiconductor LM92 and compatibles"
+config SENSORS_MAX6697
+	tristate "Maxim MAX6697 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for National Semiconductor LM92
-	  and Maxim MAX6635 sensor chips.
+	  If you say yes here you get support for MAX6581, MAX6602, MAX6622,
+	  MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699
+	  temperature sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm92.
+	  will be called max6697.
 
-config SENSORS_LM93
-	tristate "National Semiconductor LM93 and compatibles"
+config SENSORS_HTU21
+	tristate "Measurement Specialties HTU21D humidity/temperature sensors"
 	depends on I2C
-	select HWMON_VID
 	help
-	  If you say yes here you get support for National Semiconductor LM93,
-	  LM94, and compatible sensor chips.
+	  If you say yes here you get support for the Measurement Specialties
+	  HTU21D humidity and temperature sensors.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm93.
+	  will be called htu21.
 
-config SENSORS_LTC4151
-	tristate "Linear Technology LTC4151"
+config SENSORS_MCP3021
+	tristate "Microchip MCP3021 and compatibles"
 	depends on I2C
-	default n
 	help
-	  If you say yes here you get support for Linear Technology LTC4151
-	  High Voltage I2C Current and Voltage Monitor interface.
+	  If you say yes here you get support for MCP3021 and MCP3221.
+	  The MCP3021 is a A/D converter (ADC) with 10-bit and the MCP3221
+	  with 12-bit resolution.
 
-	  This driver can also be built as a module. If so, the module will
-	  be called ltc4151.
+	  This driver can also be built as a module.  If so, the module
+	  will be called mcp3021.
 
-config SENSORS_LTC4215
-	tristate "Linear Technology LTC4215"
-	depends on I2C
-	default n
+config SENSORS_ADCXX
+	tristate "National Semiconductor ADCxxxSxxx"
+	depends on SPI_MASTER
 	help
-	  If you say yes here you get support for Linear Technology LTC4215
-	  Hot Swap Controller I2C interface.
+	  If you say yes here you get support for the National Semiconductor
+	  ADC<bb><c>S<sss> chip family, where
+	  * bb  is the resolution in number of bits (8, 10, 12)
+	  * c   is the number of channels (1, 2, 4, 8)
+	  * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500
+	    kSPS and 101 for 1 MSPS)
 
-	  This driver can also be built as a module. If so, the module will
-	  be called ltc4215.
+	  Examples : ADC081S101, ADC124S501, ...
 
-config SENSORS_LTC4245
-	tristate "Linear Technology LTC4245"
+	  This driver can also be built as a module.  If so, the module
+	  will be called adcxx.
+
+config SENSORS_LM63
+	tristate "National Semiconductor LM63 and compatibles"
 	depends on I2C
-	default n
 	help
-	  If you say yes here you get support for Linear Technology LTC4245
-	  Multiple Supply Hot Swap Controller I2C interface.
+	  If you say yes here you get support for the National
+	  Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
+	  sensors with integrated fan control.  Such chips are found
+	  on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
+	  others.
 
-	  This driver can also be built as a module. If so, the module will
-	  be called ltc4245.
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm63.
 
-config SENSORS_LTC4261
-	tristate "Linear Technology LTC4261"
-	depends on I2C
-	default n
+config SENSORS_LM70
+	tristate "National Semiconductor LM70 and compatibles"
+	depends on SPI_MASTER
 	help
-	  If you say yes here you get support for Linear Technology LTC4261
-	  Negative Voltage Hot Swap Controller I2C interface.
+	  If you say yes here you get support for the National Semiconductor
+	  LM70, LM71, LM74 and Texas Instruments TMP121/TMP123 digital tempera-
+	  ture sensor chips.
 
-	  This driver can also be built as a module. If so, the module will
-	  be called ltc4261.
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm70.
 
-config SENSORS_LM95234
-	tristate "National Semiconductor LM95234"
+config SENSORS_LM73
+	tristate "National Semiconductor LM73"
 	depends on I2C
 	help
-	  If you say yes here you get support for the LM95234 temperature
-	  sensor.
-
+	  If you say yes here you get support for National Semiconductor LM73
+	  sensor chips.
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm95234.
+	  will be called lm73.
 
-config SENSORS_LM95241
-	tristate "National Semiconductor LM95241 and compatibles"
+config SENSORS_LM75
+	tristate "National Semiconductor LM75 and compatibles"
 	depends on I2C
+	depends on THERMAL || !THERMAL_OF
 	help
-	  If you say yes here you get support for LM95231 and LM95241 sensor
-	  chips.
+	  If you say yes here you get support for one common type of
+	  temperature sensor chip, with models including:
+
+		- Analog Devices ADT75
+		- Dallas Semiconductor DS75, DS1775 and DS7505
+		- Global Mixed-mode Technology (GMT) G751
+		- Maxim MAX6625 and MAX6626
+		- Microchip MCP980x
+		- National Semiconductor LM75, LM75A
+		- NXP's LM75A
+		- ST Microelectronics STDS75
+		- TelCom (now Microchip) TCN75
+		- Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
+		  TMP275
+
+	  This driver supports driver model based binding through board
+	  specific I2C device tables.
+
+	  It also supports the "legacy" style of driver binding.  To use
+	  that with some chips which don't replicate LM75 quirks exactly,
+	  you may need the "force" module parameter.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm95241.
+	  will be called lm75.
 
-config SENSORS_LM95245
-	tristate "National Semiconductor LM95245 sensor chip"
+config SENSORS_LM77
+	tristate "National Semiconductor LM77"
 	depends on I2C
 	help
-	  If you say yes here you get support for LM95245 sensor chip.
+	  If you say yes here you get support for National Semiconductor LM77
+	  sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called lm95245.
+	  will be called lm77.
 
-config SENSORS_MAX1111
-	tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles"
-	depends on SPI_MASTER
+config SENSORS_LM78
+	tristate "National Semiconductor LM78 and compatibles"
+	depends on I2C
+	select HWMON_VID
 	help
-	  Say y here to support Maxim's MAX1110, MAX1111, MAX1112, and MAX1113
-	  ADC chips.
+	  If you say yes here you get support for National Semiconductor LM78,
+	  LM78-J and LM79.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max1111.
+	  will be called lm78.
 
-config SENSORS_MAX16065
-	tristate "Maxim MAX16065 System Manager and compatibles"
+config SENSORS_LM80
+	tristate "National Semiconductor LM80 and LM96080"
 	depends on I2C
 	help
-	  If you say yes here you get support for hardware monitoring
-	  capabilities of the following Maxim System Manager chips.
-	    MAX16065
-	    MAX16066
-	    MAX16067
-	    MAX16068
-	    MAX16070
-	    MAX16071
+	  If you say yes here you get support for National Semiconductor
+	  LM80 and LM96080 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max16065.
+	  will be called lm80.
 
-config SENSORS_MAX1619
-	tristate "Maxim MAX1619 sensor chip"
+config SENSORS_LM83
+	tristate "National Semiconductor LM83 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for MAX1619 sensor chip.
+	  If you say yes here you get support for National Semiconductor
+	  LM82 and LM83 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max1619.
+	  will be called lm83.
 
-config SENSORS_MAX1668
-	tristate "Maxim MAX1668 and compatibles"
+config SENSORS_LM85
+	tristate "National Semiconductor LM85 and compatibles"
 	depends on I2C
+	select HWMON_VID
 	help
-	  If you say yes here you get support for MAX1668, MAX1989 and
-	  MAX1805 chips.
+	  If you say yes here you get support for National Semiconductor LM85
+	  sensor chips and clones: ADM1027, ADT7463, ADT7468, EMC6D100,
+	  EMC6D101, EMC6D102, and EMC6D103.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max1668.
-
-config SENSORS_MAX197
-	tristate "Maxim MAX197 and compatibles"
-	help
-	  Support for the Maxim MAX197 A/D converter.
-	  Support will include, but not be limited to, MAX197, and MAX199.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called max197.
+	  will be called lm85.
 
-config SENSORS_MAX6639
-	tristate "Maxim MAX6639 sensor chip"
+config SENSORS_LM87
+	tristate "National Semiconductor LM87 and compatibles"
 	depends on I2C
+	select HWMON_VID
 	help
-	  If you say yes here you get support for the MAX6639
-	  sensor chips.
+	  If you say yes here you get support for National Semiconductor LM87
+	  and Analog Devices ADM1024 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max6639.
+	  will be called lm87.
 
-config SENSORS_MAX6642
-	tristate "Maxim MAX6642 sensor chip"
+config SENSORS_LM90
+	tristate "National Semiconductor LM90 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for MAX6642 sensor chip.
-	  MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
-	  with Overtemperature Alarm from Maxim.
+	  If you say yes here you get support for National Semiconductor LM90,
+	  LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
+	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
+	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
+	  Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, and GMT G781
+	  sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max6642.
+	  will be called lm90.
 
-config SENSORS_MAX6650
-	tristate "Maxim MAX6650 sensor chip"
+config SENSORS_LM92
+	tristate "National Semiconductor LM92 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for the MAX6650 / MAX6651
-	  sensor chips.
+	  If you say yes here you get support for National Semiconductor LM92
+	  and Maxim MAX6635 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max6650.
+	  will be called lm92.
 
-config SENSORS_MAX6697
-	tristate "Maxim MAX6697 and compatibles"
+config SENSORS_LM93
+	tristate "National Semiconductor LM93 and compatibles"
 	depends on I2C
+	select HWMON_VID
 	help
-	  If you say yes here you get support for MAX6581, MAX6602, MAX6622,
-	  MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699
-	  temperature sensor chips.
+	  If you say yes here you get support for National Semiconductor LM93,
+	  LM94, and compatible sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called max6697.
+	  will be called lm93.
 
-config SENSORS_MCP3021
-	tristate "Microchip MCP3021 and compatibles"
+config SENSORS_LM95234
+	tristate "National Semiconductor LM95234"
 	depends on I2C
 	help
-	  If you say yes here you get support for MCP3021 and MCP3221.
-	  The MCP3021 is a A/D converter (ADC) with 10-bit and the MCP3221
-	  with 12-bit resolution.
+	  If you say yes here you get support for the LM95234 temperature
+	  sensor.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called mcp3021.
+	  will be called lm95234.
 
-config SENSORS_NCT6775
-	tristate "Nuvoton NCT6775F and compatibles"
-	depends on !PPC
-	select HWMON_VID
+config SENSORS_LM95241
+	tristate "National Semiconductor LM95241 and compatibles"
+	depends on I2C
 	help
-	  If you say yes here you get support for the hardware monitoring
-	  functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
-	  and compatible Super-I/O chips. This driver replaces the
-	  w83627ehf driver for NCT6775F and NCT6776F.
+	  If you say yes here you get support for LM95231 and LM95241 sensor
+	  chips.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called nct6775.
+	  will be called lm95241.
 
-config SENSORS_NTC_THERMISTOR
-	tristate "NTC thermistor support"
-	depends on (!OF && !IIO) || (OF && IIO)
+config SENSORS_LM95245
+	tristate "National Semiconductor LM95245 sensor chip"
+	depends on I2C
 	help
-	  This driver supports NTC thermistors sensor reading and its
-	  interpretation. The driver can also monitor the temperature and
-	  send notifications about the temperature.
-
-	  Currently, this driver supports
-	  NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333.
+	  If you say yes here you get support for LM95245 sensor chip.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called ntc-thermistor.
+	  will be called lm95245.
 
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
@@ -1011,6 +1051,33 @@ config SENSORS_PC87427
 	  This driver can also be built as a module.  If so, the module
 	  will be called pc87427.
 
+config SENSORS_NTC_THERMISTOR
+	tristate "NTC thermistor support"
+	depends on (!OF && !IIO) || (OF && IIO)
+	help
+	  This driver supports NTC thermistors sensor reading and its
+	  interpretation. The driver can also monitor the temperature and
+	  send notifications about the temperature.
+
+	  Currently, this driver supports
+	  NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ntc-thermistor.
+
+config SENSORS_NCT6775
+	tristate "Nuvoton NCT6775F and compatibles"
+	depends on !PPC
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
+	  and compatible Super-I/O chips. This driver replaces the
+	  w83627ehf driver for NCT6775F and NCT6776F.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called nct6775.
+
 config SENSORS_PCF8591
 	tristate "Philips PCF8591 ADC/DAC"
 	depends on I2C
@@ -1074,21 +1141,6 @@ config SENSORS_SIS5595
 	  This driver can also be built as a module.  If so, the module
 	  will be called sis5595.
 
-config SENSORS_SMM665
-	tristate "Summit Microelectronics SMM665"
-	depends on I2C
-	default n
-	help
-	  If you say yes here you get support for the hardware monitoring
-	  features of the Summit Microelectronics SMM665/SMM665B Six-Channel
-	  Active DC Output Controller / Monitor.
-
-	  Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
-	  Support for those chips is untested.
-
-	  This driver can also be built as a module. If so, the module will
-	  be called smm665.
-
 config SENSORS_DME1737
 	tristate "SMSC DME1737, SCH311x and compatibles"
 	depends on I2C && !PPC
@@ -1210,6 +1262,31 @@ config SENSORS_SCH5636
 	  This driver can also be built as a module.  If so, the module
 	  will be called sch5636.
 
+config SENSORS_SMM665
+	tristate "Summit Microelectronics SMM665"
+	depends on I2C
+	default n
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  features of the Summit Microelectronics SMM665/SMM665B Six-Channel
+	  Active DC Output Controller / Monitor.
+
+	  Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
+	  Support for those chips is untested.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called smm665.
+
+config SENSORS_ADC128D818
+	tristate "Texas Instruments ADC128D818"
+	depends on I2C
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  ADC128D818 System Monitor with Temperature Sensor chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called adc128d818.
+
 config SENSORS_ADS1015
 	tristate "Texas Instruments ADS1015"
 	depends on I2C
@@ -1525,37 +1602,6 @@ config SENSORS_ULTRA45
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.
 
-config SENSORS_APPLESMC
-	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
-	depends on INPUT && X86
-	select NEW_LEDS
-	select LEDS_CLASS
-	select INPUT_POLLDEV
-	default n
-	help
-	  This driver provides support for the Apple System Management
-	  Controller, which provides an accelerometer (Apple Sudden Motion
-	  Sensor), light sensors, temperature sensors, keyboard backlight
-	  control and fan control.
-
-	  Only Intel-based Apple's computers are supported (MacBook Pro,
-	  MacBook, MacMini).
-
-	  Data from the different sensors, keyboard backlight control and fan
-	  control are accessible via sysfs.
-
-	  This driver also provides an absolute input class device, allowing
-	  the laptop to act as a pinball machine-esque joystick.
-
-	  Say Y here if you have an applicable laptop and want to experience
-	  the awesome power of applesmc.
-
-config SENSORS_MC13783_ADC
-        tristate "Freescale MC13783/MC13892 ADC"
-        depends on MFD_MC13XXX
-        help
-          Support for the A/D converter on MC13783 and MC13892 PMIC.
-
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index ec7cde06eb52..c48f9873ac73 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
 obj-$(CONFIG_SENSORS_AD7314)	+= ad7314.o
 obj-$(CONFIG_SENSORS_AD7414)	+= ad7414.o
 obj-$(CONFIG_SENSORS_AD7418)	+= ad7418.o
+obj-$(CONFIG_SENSORS_ADC128D818) += adc128d818.o
 obj-$(CONFIG_SENSORS_ADCXX)	+= adcxx.o
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
@@ -95,9 +96,12 @@ obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
 obj-$(CONFIG_SENSORS_LM95234)	+= lm95234.o
 obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
 obj-$(CONFIG_SENSORS_LM95245)	+= lm95245.o
+obj-$(CONFIG_SENSORS_LTC2945)	+= ltc2945.o
 obj-$(CONFIG_SENSORS_LTC4151)	+= ltc4151.o
 obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
+obj-$(CONFIG_SENSORS_LTC4222)	+= ltc4222.o
 obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
+obj-$(CONFIG_SENSORS_LTC4260)	+= ltc4260.o
 obj-$(CONFIG_SENSORS_LTC4261)	+= ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX16065)	+= max16065.o
diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c
new file mode 100644
index 000000000000..5ffd81f19d01
--- /dev/null
+++ b/drivers/hwmon/adc128d818.c
@@ -0,0 +1,491 @@
+/*
+ * Driver for TI ADC128D818 System Monitor with Temperature Sensor
+ *
+ * Copyright (c) 2014 Guenter Roeck
+ *
+ * Derived from lm80.c
+ * Copyright (C) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
+ *			     and Philip Edelbrock <phil@netroedge.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.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan
+ * The chip also supports addresses 0x35..0x37. Don't scan those addresses
+ * since they are also used by some EEPROMs, which may result in false
+ * positives.
+ */
+static const unsigned short normal_i2c[] = {
+	0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* registers */
+#define ADC128_REG_IN_MAX(nr)		(0x2a + (nr) * 2)
+#define ADC128_REG_IN_MIN(nr)		(0x2b + (nr) * 2)
+#define ADC128_REG_IN(nr)		(0x20 + (nr))
+
+#define ADC128_REG_TEMP			0x27
+#define ADC128_REG_TEMP_MAX		0x38
+#define ADC128_REG_TEMP_HYST		0x39
+
+#define ADC128_REG_CONFIG		0x00
+#define ADC128_REG_ALARM		0x01
+#define ADC128_REG_MASK			0x03
+#define ADC128_REG_CONV_RATE		0x07
+#define ADC128_REG_ONESHOT		0x09
+#define ADC128_REG_SHUTDOWN		0x0a
+#define ADC128_REG_CONFIG_ADV		0x0b
+#define ADC128_REG_BUSY_STATUS		0x0c
+
+#define ADC128_REG_MAN_ID		0x3e
+#define ADC128_REG_DEV_ID		0x3f
+
+struct adc128_data {
+	struct i2c_client *client;
+	struct regulator *regulator;
+	int vref;		/* Reference voltage in mV */
+	struct mutex update_lock;
+	bool valid;		/* true if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u16 in[3][7];		/* Register value, normalized to 12 bit
+				 * 0: input voltage
+				 * 1: min limit
+				 * 2: max limit
+				 */
+	s16 temp[3];		/* Register value, normalized to 9 bit
+				 * 0: sensor 1: limit 2: hyst
+				 */
+	u8 alarms;		/* alarm register value */
+};
+
+static struct adc128_data *adc128_update_device(struct device *dev)
+{
+	struct adc128_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	struct adc128_data *ret = data;
+	int i, rv;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		for (i = 0; i < 7; i++) {
+			rv = i2c_smbus_read_word_swapped(client,
+							 ADC128_REG_IN(i));
+			if (rv < 0)
+				goto abort;
+			data->in[0][i] = rv >> 4;
+
+			rv = i2c_smbus_read_byte_data(client,
+						      ADC128_REG_IN_MIN(i));
+			if (rv < 0)
+				goto abort;
+			data->in[1][i] = rv << 4;
+
+			rv = i2c_smbus_read_byte_data(client,
+						      ADC128_REG_IN_MAX(i));
+			if (rv < 0)
+				goto abort;
+			data->in[2][i] = rv << 4;
+		}
+
+		rv = i2c_smbus_read_word_swapped(client, ADC128_REG_TEMP);
+		if (rv < 0)
+			goto abort;
+		data->temp[0] = rv >> 7;
+
+		rv = i2c_smbus_read_byte_data(client, ADC128_REG_TEMP_MAX);
+		if (rv < 0)
+			goto abort;
+		data->temp[1] = rv << 1;
+
+		rv = i2c_smbus_read_byte_data(client, ADC128_REG_TEMP_HYST);
+		if (rv < 0)
+			goto abort;
+		data->temp[2] = rv << 1;
+
+		rv = i2c_smbus_read_byte_data(client, ADC128_REG_ALARM);
+		if (rv < 0)
+			goto abort;
+		data->alarms |= rv;
+
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+	goto done;
+
+abort:
+	ret = ERR_PTR(rv);
+	data->valid = false;
+done:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t adc128_show_in(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct adc128_data *data = adc128_update_device(dev);
+	int index = to_sensor_dev_attr_2(attr)->index;
+	int nr = to_sensor_dev_attr_2(attr)->nr;
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = DIV_ROUND_CLOSEST(data->in[index][nr] * data->vref, 4095);
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t adc128_set_in(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct adc128_data *data = dev_get_drvdata(dev);
+	int index = to_sensor_dev_attr_2(attr)->index;
+	int nr = to_sensor_dev_attr_2(attr)->nr;
+	u8 reg, regval;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	/* 10 mV LSB on limit registers */
+	regval = clamp_val(DIV_ROUND_CLOSEST(val, 10), 0, 255);
+	data->in[index][nr] = regval << 4;
+	reg = index == 1 ? ADC128_REG_IN_MIN(nr) : ADC128_REG_IN_MAX(nr);
+	i2c_smbus_write_byte_data(data->client, reg, regval);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t adc128_show_temp(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct adc128_data *data = adc128_update_device(dev);
+	int index = to_sensor_dev_attr(attr)->index;
+	int temp;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	temp = (data->temp[index] << 7) >> 7;	/* sign extend */
+	return sprintf(buf, "%d\n", temp * 500);/* 0.5 degrees C resolution */
+}
+
+static ssize_t adc128_set_temp(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct adc128_data *data = dev_get_drvdata(dev);
+	int index = to_sensor_dev_attr(attr)->index;
+	long val;
+	int err;
+	s8 regval;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	regval = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+	data->temp[index] = regval << 1;
+	i2c_smbus_write_byte_data(data->client,
+				  index == 1 ? ADC128_REG_TEMP_MAX
+					     : ADC128_REG_TEMP_HYST,
+				  regval);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t adc128_show_alarm(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct adc128_data *data = adc128_update_device(dev);
+	int mask = 1 << to_sensor_dev_attr(attr)->index;
+	u8 alarms;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	/*
+	 * Clear an alarm after reporting it to user space. If it is still
+	 * active, the next update sequence will set the alarm bit again.
+	 */
+	alarms = data->alarms;
+	data->alarms &= ~mask;
+
+	return sprintf(buf, "%u\n", !!(alarms & mask));
+}
+
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 0, 0);
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 0, 1);
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 0, 2);
+
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 1, 0);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 1, 1);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 1, 2);
+
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 2, 0);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 2, 1);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 2, 2);
+
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 3, 0);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 3, 1);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 3, 2);
+
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 4, 0);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 4, 1);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(in5_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 5, 0);
+static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 5, 1);
+static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 5, 2);
+
+static SENSOR_DEVICE_ATTR_2(in6_input, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 6, 0);
+static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 6, 1);
+static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO,
+			    adc128_show_in, adc128_set_in, 6, 2);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adc128_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+			  adc128_show_temp, adc128_set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+			  adc128_show_temp, adc128_set_temp, 2);
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, adc128_show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, adc128_show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, adc128_show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, adc128_show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, adc128_show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, adc128_show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, adc128_show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adc128_show_alarm, NULL, 7);
+
+static struct attribute *adc128_attrs[] = {
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(adc128);
+
+static int adc128_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+	int man_id, dev_id;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	man_id = i2c_smbus_read_byte_data(client, ADC128_REG_MAN_ID);
+	dev_id = i2c_smbus_read_byte_data(client, ADC128_REG_DEV_ID);
+	if (man_id != 0x01 || dev_id != 0x09)
+		return -ENODEV;
+
+	/* Check unused bits for confirmation */
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_CONFIG) & 0xf4)
+		return -ENODEV;
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_CONV_RATE) & 0xfe)
+		return -ENODEV;
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_ONESHOT) & 0xfe)
+		return -ENODEV;
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_SHUTDOWN) & 0xfe)
+		return -ENODEV;
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_CONFIG_ADV) & 0xf8)
+		return -ENODEV;
+	if (i2c_smbus_read_byte_data(client, ADC128_REG_BUSY_STATUS) & 0xfc)
+		return -ENODEV;
+
+	strlcpy(info->type, "adc128d818", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int adc128_init_client(struct adc128_data *data)
+{
+	struct i2c_client *client = data->client;
+	int err;
+
+	/*
+	 * Reset chip to defaults.
+	 * This makes most other initializations unnecessary.
+	 */
+	err = i2c_smbus_write_byte_data(client, ADC128_REG_CONFIG, 0x80);
+	if (err)
+		return err;
+
+	/* Start monitoring */
+	err = i2c_smbus_write_byte_data(client, ADC128_REG_CONFIG, 0x01);
+	if (err)
+		return err;
+
+	/* If external vref is selected, configure the chip to use it */
+	if (data->regulator) {
+		err = i2c_smbus_write_byte_data(client,
+						ADC128_REG_CONFIG_ADV, 0x01);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int adc128_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct regulator *regulator;
+	struct device *hwmon_dev;
+	struct adc128_data *data;
+	int err, vref;
+
+	data = devm_kzalloc(dev, sizeof(struct adc128_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* vref is optional. If specified, is used as chip reference voltage */
+	regulator = devm_regulator_get_optional(dev, "vref");
+	if (!IS_ERR(regulator)) {
+		data->regulator = regulator;
+		err = regulator_enable(regulator);
+		if (err < 0)
+			return err;
+		vref = regulator_get_voltage(regulator);
+		if (vref < 0) {
+			err = vref;
+			goto error;
+		}
+		data->vref = DIV_ROUND_CLOSEST(vref, 1000);
+	} else {
+		data->vref = 2560;	/* 2.56V, in mV */
+	}
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Initialize the chip */
+	err = adc128_init_client(data);
+	if (err < 0)
+		goto error;
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, adc128_groups);
+	if (IS_ERR(hwmon_dev)) {
+		err = PTR_ERR(hwmon_dev);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (data->regulator)
+		regulator_disable(data->regulator);
+	return err;
+}
+
+static int adc128_remove(struct i2c_client *client)
+{
+	struct adc128_data *data = i2c_get_clientdata(client);
+
+	if (data->regulator)
+		regulator_disable(data->regulator);
+
+	return 0;
+}
+
+static const struct i2c_device_id adc128_id[] = {
+	{ "adc128d818", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adc128_id);
+
+static struct i2c_driver adc128_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adc128d818",
+	},
+	.probe		= adc128_probe,
+	.remove		= adc128_remove,
+	.id_table	= adc128_id,
+	.detect		= adc128_detect,
+	.address_list	= normal_i2c,
+};
+
+module_i2c_driver(adc128_driver);
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("Driver for ADC128D818");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 29dd9f746dfa..3eb4281689b5 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -79,9 +79,11 @@ enum chips {
 
 /* Each client has this additional data */
 struct adm1021_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	enum chips type;
 
+	const struct attribute_group *groups[3];
+
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	char low_power;		/* !=0 if device in low power mode */
@@ -101,7 +103,6 @@ static int adm1021_probe(struct i2c_client *client,
 static int adm1021_detect(struct i2c_client *client,
 			  struct i2c_board_info *info);
 static void adm1021_init_client(struct i2c_client *client);
-static int adm1021_remove(struct i2c_client *client);
 static struct adm1021_data *adm1021_update_device(struct device *dev);
 
 /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
@@ -128,7 +129,6 @@ static struct i2c_driver adm1021_driver = {
 		.name	= "adm1021",
 	},
 	.probe		= adm1021_probe,
-	.remove		= adm1021_remove,
 	.id_table	= adm1021_id,
 	.detect		= adm1021_detect,
 	.address_list	= normal_i2c,
@@ -182,8 +182,8 @@ static ssize_t set_temp_max(struct device *dev,
 			    const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1021_data *data = i2c_get_clientdata(client);
+	struct adm1021_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	int err;
 
@@ -207,8 +207,8 @@ static ssize_t set_temp_min(struct device *dev,
 			    const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1021_data *data = i2c_get_clientdata(client);
+	struct adm1021_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	int err;
 
@@ -238,8 +238,8 @@ static ssize_t set_low_power(struct device *dev,
 			     struct device_attribute *devattr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1021_data *data = i2c_get_clientdata(client);
+	struct adm1021_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	char low_power;
 	unsigned long val;
 	int err;
@@ -412,15 +412,15 @@ static int adm1021_detect(struct i2c_client *client,
 static int adm1021_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct adm1021_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct adm1021_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct adm1021_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	data->type = id->driver_data;
 	mutex_init(&data->update_lock);
 
@@ -428,29 +428,14 @@ static int adm1021_probe(struct i2c_client *client,
 	if (data->type != lm84 && !read_only)
 		adm1021_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &adm1021_group);
-	if (err)
-		return err;
-
-	if (data->type != lm84) {
-		err = sysfs_create_group(&client->dev.kobj, &adm1021_min_group);
-		if (err)
-			goto error;
-	}
+	data->groups[0] = &adm1021_group;
+	if (data->type != lm84)
+		data->groups[1] = &adm1021_min_group;
 
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
 
-	return 0;
-
-error:
-	sysfs_remove_group(&client->dev.kobj, &adm1021_min_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1021_group);
-	return err;
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static void adm1021_init_client(struct i2c_client *client)
@@ -462,21 +447,10 @@ static void adm1021_init_client(struct i2c_client *client)
 	i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
 }
 
-static int adm1021_remove(struct i2c_client *client)
-{
-	struct adm1021_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm1021_min_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1021_group);
-
-	return 0;
-}
-
 static struct adm1021_data *adm1021_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1021_data *data = i2c_get_clientdata(client);
+	struct adm1021_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -484,7 +458,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
 	    || !data->valid) {
 		int i;
 
-		dev_dbg(&client->dev, "Starting adm1021 update\n");
+		dev_dbg(dev, "Starting adm1021 update\n");
 
 		for (i = 0; i < 2; i++) {
 			data->temp[i] = 1000 *
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 8d9f2a0e8efe..71463689d163 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -1115,7 +1115,6 @@ asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the asc7621 chip */
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index ddff02e3e66f..6edce42c61d5 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -353,8 +353,6 @@ static int atxp1_probe(struct i2c_client *new_client,
 	data->vrm = vid_which_vrm();
 
 	i2c_set_clientdata(new_client, data);
-	data->valid = 0;
-
 	mutex_init(&data->update_lock);
 
 	/* Register sysfs hooks */
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index bbb0b0d463f7..f31bc4c48644 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -94,6 +94,8 @@ struct temp_data {
 	bool valid;
 	struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
 	char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
+	struct attribute *attrs[TOTAL_ATTRS + 1];
+	struct attribute_group attr_group;
 	struct mutex update_lock;
 };
 
@@ -114,12 +116,6 @@ struct pdev_entry {
 static LIST_HEAD(pdev_list);
 static DEFINE_MUTEX(pdev_list_mutex);
 
-static ssize_t show_name(struct device *dev,
-			struct device_attribute *devattr, char *buf)
-{
-	return sprintf(buf, "%s\n", DRVNAME);
-}
-
 static ssize_t show_label(struct device *dev,
 				struct device_attribute *devattr, char *buf)
 {
@@ -393,20 +389,10 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 	return adjust_tjmax(c, id, dev);
 }
 
-static int create_name_attr(struct platform_data *pdata,
-				      struct device *dev)
-{
-	sysfs_attr_init(&pdata->name_attr.attr);
-	pdata->name_attr.attr.name = "name";
-	pdata->name_attr.attr.mode = S_IRUGO;
-	pdata->name_attr.show = show_name;
-	return device_create_file(dev, &pdata->name_attr);
-}
-
 static int create_core_attrs(struct temp_data *tdata, struct device *dev,
 			     int attr_no)
 {
-	int err, i;
+	int i;
 	static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
 			struct device_attribute *devattr, char *buf) = {
 			show_label, show_crit_alarm, show_temp, show_tjmax,
@@ -424,16 +410,10 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
 		tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
 		tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
 		tdata->sd_attrs[i].index = attr_no;
-		err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
-		if (err)
-			goto exit_free;
+		tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
 	}
-	return 0;
-
-exit_free:
-	while (--i >= 0)
-		device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
-	return err;
+	tdata->attr_group.attrs = tdata->attrs;
+	return sysfs_create_group(&dev->kobj, &tdata->attr_group);
 }
 
 
@@ -548,7 +528,7 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
 	pdata->core_data[attr_no] = tdata;
 
 	/* Create sysfs interfaces */
-	err = create_core_attrs(tdata, &pdev->dev, attr_no);
+	err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no);
 	if (err)
 		goto exit_free;
 
@@ -573,14 +553,12 @@ static void coretemp_add_core(unsigned int cpu, int pkg_flag)
 }
 
 static void coretemp_remove_core(struct platform_data *pdata,
-				struct device *dev, int indx)
+				 int indx)
 {
-	int i;
 	struct temp_data *tdata = pdata->core_data[indx];
 
 	/* Remove the sysfs attributes */
-	for (i = 0; i < tdata->attr_size; i++)
-		device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
+	sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group);
 
 	kfree(pdata->core_data[indx]);
 	pdata->core_data[indx] = NULL;
@@ -588,34 +566,20 @@ static void coretemp_remove_core(struct platform_data *pdata,
 
 static int coretemp_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct platform_data *pdata;
-	int err;
 
 	/* Initialize the per-package data structures */
-	pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL);
+	pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	err = create_name_attr(pdata, &pdev->dev);
-	if (err)
-		goto exit_free;
-
 	pdata->phys_proc_id = pdev->id;
 	platform_set_drvdata(pdev, pdata);
 
-	pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(pdata->hwmon_dev)) {
-		err = PTR_ERR(pdata->hwmon_dev);
-		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
-		goto exit_name;
-	}
-	return 0;
-
-exit_name:
-	device_remove_file(&pdev->dev, &pdata->name_attr);
-exit_free:
-	kfree(pdata);
-	return err;
+	pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
+								  pdata, NULL);
+	return PTR_ERR_OR_ZERO(pdata->hwmon_dev);
 }
 
 static int coretemp_remove(struct platform_device *pdev)
@@ -625,11 +589,8 @@ static int coretemp_remove(struct platform_device *pdev)
 
 	for (i = MAX_CORE_DATA - 1; i >= 0; --i)
 		if (pdata->core_data[i])
-			coretemp_remove_core(pdata, &pdev->dev, i);
+			coretemp_remove_core(pdata, i);
 
-	device_remove_file(&pdev->dev, &pdata->name_attr);
-	hwmon_device_unregister(pdata->hwmon_dev);
-	kfree(pdata);
 	return 0;
 }
 
@@ -777,7 +738,7 @@ static void put_core_offline(unsigned int cpu)
 		return;
 
 	if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
-		coretemp_remove_core(pdata, &pdev->dev, indx);
+		coretemp_remove_core(pdata, indx);
 
 	/*
 	 * If a HT sibling of a core is taken offline, but another HT sibling
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
index 2c137b26acb4..fd892dd48e4c 100644
--- a/drivers/hwmon/emc2103.c
+++ b/drivers/hwmon/emc2103.c
@@ -349,7 +349,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 		dev_dbg(&client->dev, "reg 0x%02x, err %d\n",
 			REG_FAN_CONF1, status);
 		mutex_unlock(&data->update_lock);
-		return -EIO;
+		return status;
 	}
 	status &= 0x9F;
 	status |= (new_range_bits << 5);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 1a8aa1265262..32f5132c4652 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1648,7 +1648,7 @@ static void __exit f71805f_exit(void)
 	platform_driver_unregister(&f71805f_driver);
 }
 
-MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
+MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
 
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index 708081b68c6f..9fbb1b1fdff3 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -31,6 +31,7 @@ struct iio_hwmon_state {
 	int num_channels;
 	struct device *hwmon_dev;
 	struct attribute_group attr_group;
+	const struct attribute_group *groups[2];
 	struct attribute **attrs;
 };
 
@@ -56,19 +57,6 @@ static ssize_t iio_hwmon_read_val(struct device *dev,
 	return sprintf(buf, "%d\n", result);
 }
 
-static ssize_t show_name(struct device *dev, struct device_attribute *attr,
-			 char *buf)
-{
-	const char *name = "iio_hwmon";
-
-	if (dev->of_node && dev->of_node->name)
-		name = dev->of_node->name;
-
-	return sprintf(buf, "%s\n", name);
-}
-
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
 static int iio_hwmon_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -78,6 +66,10 @@ static int iio_hwmon_probe(struct platform_device *pdev)
 	int in_i = 1, temp_i = 1, curr_i = 1;
 	enum iio_chan_type type;
 	struct iio_channel *channels;
+	const char *name = "iio_hwmon";
+
+	if (dev->of_node && dev->of_node->name)
+		name = dev->of_node->name;
 
 	channels = iio_channel_get_all(dev);
 	if (IS_ERR(channels))
@@ -96,7 +88,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
 		st->num_channels++;
 
 	st->attrs = devm_kzalloc(dev,
-				 sizeof(*st->attrs) * (st->num_channels + 2),
+				 sizeof(*st->attrs) * (st->num_channels + 1),
 				 GFP_KERNEL);
 	if (st->attrs == NULL) {
 		ret = -ENOMEM;
@@ -144,22 +136,18 @@ static int iio_hwmon_probe(struct platform_device *pdev)
 		a->index = i;
 		st->attrs[i] = &a->dev_attr.attr;
 	}
-	st->attrs[st->num_channels] = &dev_attr_name.attr;
-	st->attr_group.attrs = st->attrs;
-	platform_set_drvdata(pdev, st);
-	ret = sysfs_create_group(&dev->kobj, &st->attr_group);
-	if (ret < 0)
-		goto error_release_channels;
 
-	st->hwmon_dev = hwmon_device_register(dev);
+	st->attr_group.attrs = st->attrs;
+	st->groups[0] = &st->attr_group;
+	st->hwmon_dev = hwmon_device_register_with_groups(dev, name, st,
+							  st->groups);
 	if (IS_ERR(st->hwmon_dev)) {
 		ret = PTR_ERR(st->hwmon_dev);
-		goto error_remove_group;
+		goto error_release_channels;
 	}
+	platform_set_drvdata(pdev, st);
 	return 0;
 
-error_remove_group:
-	sysfs_remove_group(&dev->kobj, &st->attr_group);
 error_release_channels:
 	iio_channel_release_all(channels);
 	return ret;
@@ -170,7 +158,6 @@ static int iio_hwmon_remove(struct platform_device *pdev)
 	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(st->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
 	iio_channel_release_all(st->channels);
 
 	return 0;
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
index a183e488db78..7488e36809c8 100644
--- a/drivers/hwmon/jz4740-hwmon.c
+++ b/drivers/hwmon/jz4740-hwmon.c
@@ -28,7 +28,6 @@
 #include <linux/hwmon.h>
 
 struct jz4740_hwmon {
-	struct resource *mem;
 	void __iomem *base;
 
 	int irq;
@@ -106,6 +105,7 @@ static int jz4740_hwmon_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct jz4740_hwmon *hwmon;
+	struct resource *mem;
 
 	hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
 	if (!hwmon)
@@ -120,25 +120,10 @@ static int jz4740_hwmon_probe(struct platform_device *pdev)
 		return hwmon->irq;
 	}
 
-	hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!hwmon->mem) {
-		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
-		return -ENOENT;
-	}
-
-	hwmon->mem = devm_request_mem_region(&pdev->dev, hwmon->mem->start,
-			resource_size(hwmon->mem), pdev->name);
-	if (!hwmon->mem) {
-		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-		return -EBUSY;
-	}
-
-	hwmon->base = devm_ioremap_nocache(&pdev->dev, hwmon->mem->start,
-					   resource_size(hwmon->mem));
-	if (!hwmon->base) {
-		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-		return -EBUSY;
-	}
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hwmon->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(hwmon->base))
+		return PTR_ERR(hwmon->base);
 
 	init_completion(&hwmon->read_completion);
 	mutex_init(&hwmon->lock);
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index b4ad598feb6c..848b9611151f 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -155,8 +155,9 @@ enum chips { lm63, lm64, lm96163 };
  */
 
 struct lm63_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
+	const struct attribute_group *groups[5];
 	char valid; /* zero until following fields are valid */
 	char lut_valid; /* zero until lut fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -218,9 +219,9 @@ static inline int lut_temp_to_reg(struct lm63_data *data, long val)
  * Update the lookup table register cache.
  * client->update_lock must be held when calling this function.
  */
-static void lm63_update_lut(struct i2c_client *client)
+static void lm63_update_lut(struct lm63_data *data)
 {
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct i2c_client *client = data->client;
 	int i;
 
 	if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
@@ -241,8 +242,8 @@ static void lm63_update_lut(struct i2c_client *client)
 
 static struct lm63_data *lm63_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long next_update;
 
 	mutex_lock(&data->update_lock);
@@ -310,7 +311,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
 		data->valid = 1;
 	}
 
-	lm63_update_lut(client);
+	lm63_update_lut(data);
 
 	mutex_unlock(&data->update_lock);
 
@@ -321,18 +322,17 @@ static struct lm63_data *lm63_update_device(struct device *dev)
  * Trip points in the lookup table should be in ascending order for both
  * temperatures and PWM output values.
  */
-static int lm63_lut_looks_bad(struct i2c_client *client)
+static int lm63_lut_looks_bad(struct device *dev, struct lm63_data *data)
 {
-	struct lm63_data *data = i2c_get_clientdata(client);
 	int i;
 
 	mutex_lock(&data->update_lock);
-	lm63_update_lut(client);
+	lm63_update_lut(data);
 
 	for (i = 1; i < data->lut_size; i++) {
 		if (data->pwm1[1 + i - 1] > data->pwm1[1 + i]
 		 || data->temp8[3 + i - 1] > data->temp8[3 + i]) {
-			dev_warn(&client->dev,
+			dev_warn(dev,
 				 "Lookup table doesn't look sane (check entries %d and %d)\n",
 				 i, i + 1);
 			break;
@@ -358,8 +358,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -399,8 +399,8 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr,
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = attr->index;
 	unsigned long val;
 	int err;
@@ -435,8 +435,8 @@ static ssize_t set_pwm1_enable(struct device *dev,
 			       struct device_attribute *dummy,
 			       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -450,7 +450,7 @@ static ssize_t set_pwm1_enable(struct device *dev,
 	 * Only let the user switch to automatic mode if the lookup table
 	 * looks sane.
 	 */
-	if (val == 2 && lm63_lut_looks_bad(client))
+	if (val == 2 && lm63_lut_looks_bad(dev, data))
 		return -EPERM;
 
 	mutex_lock(&data->update_lock);
@@ -461,7 +461,7 @@ static ssize_t set_pwm1_enable(struct device *dev,
 	else
 		data->config_fan &= ~0x20;
 	i2c_smbus_write_byte_data(client, LM63_REG_CONFIG_FAN,
-	data->config_fan);
+				  data->config_fan);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -505,8 +505,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
 			 const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = attr->index;
 	long val;
 	int err;
@@ -579,8 +579,8 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
 	};
 
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 	int nr = attr->index;
@@ -635,8 +635,8 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
 				   struct device_attribute *dummy,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 	long hyst;
@@ -657,11 +657,11 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
  * Set conversion rate.
  * client->update_lock must be held when calling this function.
  */
-static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
-			      unsigned int interval)
+static void lm63_set_convrate(struct lm63_data *data, unsigned int interval)
 {
-	int i;
+	struct i2c_client *client = data->client;
 	unsigned int update_interval;
+	int i;
 
 	/* Shift calculations to avoid rounding errors */
 	interval <<= 6;
@@ -689,8 +689,7 @@ static ssize_t set_update_interval(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	int err;
 
@@ -699,7 +698,7 @@ static ssize_t set_update_interval(struct device *dev,
 		return err;
 
 	mutex_lock(&data->update_lock);
-	lm63_set_convrate(client, data, clamp_val(val, 0, 100000));
+	lm63_set_convrate(data, clamp_val(val, 0, 100000));
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -708,8 +707,7 @@ static ssize_t set_update_interval(struct device *dev,
 static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, data->trutherm ? "1\n" : "2\n");
 }
@@ -717,8 +715,8 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int ret;
 	u8 reg;
@@ -915,6 +913,15 @@ static struct attribute *lm63_attributes[] = {
 	NULL
 };
 
+static struct attribute *lm63_attributes_temp2_type[] = {
+	&dev_attr_temp2_type.attr,
+	NULL
+};
+
+static const struct attribute_group lm63_group_temp2_type = {
+	.attrs = lm63_attributes_temp2_type,
+};
+
 static struct attribute *lm63_attributes_extra_lut[] = {
 	&sensor_dev_attr_pwm1_auto_point9_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_point9_temp.dev_attr.attr,
@@ -946,8 +953,7 @@ static umode_t lm63_attribute_mode(struct kobject *kobj,
 				   struct attribute *attr, int index)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct lm63_data *data = dev_get_drvdata(dev);
 
 	if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr
 	    && (data->kind == lm64 ||
@@ -1026,9 +1032,10 @@ static int lm63_detect(struct i2c_client *client,
  * Ideally we shouldn't have to initialize anything, since the BIOS
  * should have taken care of everything
  */
-static void lm63_init_client(struct i2c_client *client)
+static void lm63_init_client(struct lm63_data *data)
 {
-	struct lm63_data *data = i2c_get_clientdata(client);
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
 	u8 convrate;
 
 	data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
@@ -1037,7 +1044,7 @@ static void lm63_init_client(struct i2c_client *client)
 
 	/* Start converting if needed */
 	if (data->config & 0x40) { /* standby */
-		dev_dbg(&client->dev, "Switching to operational mode\n");
+		dev_dbg(dev, "Switching to operational mode\n");
 		data->config &= 0xA7;
 		i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
 					  data->config);
@@ -1090,13 +1097,13 @@ static void lm63_init_client(struct i2c_client *client)
 
 	/* Show some debug info about the LM63 configuration */
 	if (data->kind == lm63)
-		dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
+		dev_dbg(dev, "Alert/tach pin configured for %s\n",
 			(data->config & 0x04) ? "tachometer input" :
 			"alert output");
-	dev_dbg(&client->dev, "PWM clock %s kHz, output frequency %u Hz\n",
+	dev_dbg(dev, "PWM clock %s kHz, output frequency %u Hz\n",
 		(data->config_fan & 0x08) ? "1.4" : "360",
 		((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq);
-	dev_dbg(&client->dev, "PWM output active %s, %s mode\n",
+	dev_dbg(dev, "PWM output active %s, %s mode\n",
 		(data->config_fan & 0x10) ? "low" : "high",
 		(data->config_fan & 0x20) ? "manual" : "auto");
 }
@@ -1104,15 +1111,16 @@ static void lm63_init_client(struct i2c_client *client)
 static int lm63_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct lm63_data *data;
-	int err;
+	int groups = 0;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm63_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm63_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
-	data->valid = 0;
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Set the device type */
@@ -1121,59 +1129,21 @@ static int lm63_probe(struct i2c_client *client,
 		data->temp2_offset = 16000;
 
 	/* Initialize chip */
-	lm63_init_client(client);
+	lm63_init_client(data);
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &lm63_group);
-	if (err)
-		return err;
-	if (data->config & 0x04) { /* tachometer enabled */
-		err = sysfs_create_group(&client->dev.kobj, &lm63_group_fan1);
-		if (err)
-			goto exit_remove_files;
-	}
-	if (data->kind == lm96163) {
-		err = device_create_file(&client->dev, &dev_attr_temp2_type);
-		if (err)
-			goto exit_remove_files;
-
-		err = sysfs_create_group(&client->dev.kobj,
-					 &lm63_group_extra_lut);
-		if (err)
-			goto exit_remove_files;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
+	data->groups[groups++] = &lm63_group;
+	if (data->config & 0x04)	/* tachometer enabled */
+		data->groups[groups++] = &lm63_group_fan1;
 
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &lm63_group);
-	sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
 	if (data->kind == lm96163) {
-		device_remove_file(&client->dev, &dev_attr_temp2_type);
-		sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
+		data->groups[groups++] = &lm63_group_temp2_type;
+		data->groups[groups++] = &lm63_group_extra_lut;
 	}
-	return err;
-}
-
-static int lm63_remove(struct i2c_client *client)
-{
-	struct lm63_data *data = i2c_get_clientdata(client);
 
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm63_group);
-	sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
-	if (data->kind == lm96163) {
-		device_remove_file(&client->dev, &dev_attr_temp2_type);
-		sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
-	}
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /*
@@ -1194,7 +1164,6 @@ static struct i2c_driver lm63_driver = {
 		.name	= "lm63",
 	},
 	.probe		= lm63_probe,
-	.remove		= lm63_remove,
 	.id_table	= lm63_id,
 	.detect		= lm63_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index f17beb5e6dd6..502771c06fd9 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -348,7 +348,6 @@ static int lm77_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM77 chip */
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index eba89aac3ece..bd0a1ebbf867 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -112,7 +112,7 @@ static inline long TEMP_FROM_REG(u16 temp)
  */
 
 struct lm80_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char error;		/* !=0 if error occurred during last update */
 	char valid;		/* !=0 if following fields are valid */
@@ -140,7 +140,6 @@ static int lm80_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id);
 static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info);
 static void lm80_init_client(struct i2c_client *client);
-static int lm80_remove(struct i2c_client *client);
 static struct lm80_data *lm80_update_device(struct device *dev);
 static int lm80_read_value(struct i2c_client *client, u8 reg);
 static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
@@ -162,7 +161,6 @@ static struct i2c_driver lm80_driver = {
 		.name	= "lm80",
 	},
 	.probe		= lm80_probe,
-	.remove		= lm80_remove,
 	.id_table	= lm80_id,
 	.detect		= lm80_detect,
 	.address_list	= normal_i2c,
@@ -191,8 +189,8 @@ static ssize_t set_in_##suffix(struct device *dev, \
 	struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm80_data *data = i2c_get_clientdata(client); \
+	struct lm80_data *data = dev_get_drvdata(dev); \
+	struct i2c_client *client = data->client; \
 	long val; \
 	int err = kstrtol(buf, 10, &val); \
 	if (err < 0) \
@@ -235,8 +233,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm80_data *data = i2c_get_clientdata(client);
+	struct lm80_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err = kstrtoul(buf, 10, &val);
 	if (err < 0)
@@ -259,8 +257,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm80_data *data = i2c_get_clientdata(client);
+	struct lm80_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long min, val;
 	u8 reg;
 	int err = kstrtoul(buf, 10, &val);
@@ -286,7 +284,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		data->fan_div[nr] = 3;
 		break;
 	default:
-		dev_err(&client->dev,
+		dev_err(dev,
 			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
 			val);
 		mutex_unlock(&data->update_lock);
@@ -332,8 +330,8 @@ show_temp(os_hyst, temp_os_hyst);
 static ssize_t set_temp_##suffix(struct device *dev, \
 	struct device_attribute *attr, const char *buf, size_t count) \
 { \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm80_data *data = i2c_get_clientdata(client); \
+	struct lm80_data *data = dev_get_drvdata(dev); \
+	struct i2c_client *client = data->client; \
 	long val; \
 	int err = kstrtol(buf, 10, &val); \
 	if (err < 0) \
@@ -440,7 +438,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
  * Real code
  */
 
-static struct attribute *lm80_attributes[] = {
+static struct attribute *lm80_attrs[] = {
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
 	&sensor_dev_attr_in2_min.dev_attr.attr,
@@ -487,10 +485,7 @@ static struct attribute *lm80_attributes[] = {
 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
 	NULL
 };
-
-static const struct attribute_group lm80_group = {
-	.attrs = lm80_attributes,
-};
+ATTRIBUTE_GROUPS(lm80);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
@@ -541,14 +536,15 @@ static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
 static int lm80_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct lm80_data *data;
-	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm80_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM80 chip */
@@ -558,32 +554,10 @@ static int lm80_probe(struct i2c_client *client,
 	data->fan_min[0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
 	data->fan_min[1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &lm80_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);
-		goto error_remove;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, lm80_groups);
 
-	return 0;
-
-error_remove:
-	sysfs_remove_group(&client->dev.kobj, &lm80_group);
-	return err;
-}
-
-static int lm80_remove(struct i2c_client *client)
-{
-	struct lm80_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm80_group);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static int lm80_read_value(struct i2c_client *client, u8 reg)
@@ -614,8 +588,8 @@ static void lm80_init_client(struct i2c_client *client)
 
 static struct lm80_data *lm80_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm80_data *data = i2c_get_clientdata(client);
+	struct lm80_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int i;
 	int rv;
 	int prev_rv;
@@ -627,7 +601,7 @@ static struct lm80_data *lm80_update_device(struct device *dev)
 		lm80_init_client(client);
 
 	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
-		dev_dbg(&client->dev, "Starting lm80 update\n");
+		dev_dbg(dev, "Starting lm80 update\n");
 		for (i = 0; i <= 6; i++) {
 			rv = lm80_read_value(client, LM80_REG_IN(i));
 			if (rv < 0)
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index abd270243ba7..be02155788c3 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -349,7 +349,6 @@ static int lm83_probe(struct i2c_client *new_client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(new_client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/*
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 4c5f20231c1a..ba1d83d48056 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -903,7 +903,6 @@ static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM87 chip */
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 701e952ae523..c9ff08dbe10c 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -365,7 +365,9 @@ enum lm90_temp11_reg_index {
  */
 
 struct lm90_data {
+	struct i2c_client *client;
 	struct device *hwmon_dev;
+	const struct attribute_group *groups[6];
 	struct mutex update_lock;
 	struct regulator *regulator;
 	char valid; /* zero until following fields are valid */
@@ -513,8 +515,8 @@ static void lm90_set_convrate(struct i2c_client *client, struct lm90_data *data,
 
 static struct lm90_data *lm90_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm90_data *data = i2c_get_clientdata(client);
+	struct lm90_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long next_update;
 
 	mutex_lock(&data->update_lock);
@@ -793,8 +795,8 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
 	};
 
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm90_data *data = i2c_get_clientdata(client);
+	struct lm90_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = attr->index;
 	long val;
 	int err;
@@ -860,8 +862,8 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
 	};
 
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm90_data *data = i2c_get_clientdata(client);
+	struct lm90_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = attr->nr;
 	int index = attr->index;
 	long val;
@@ -922,8 +924,8 @@ static ssize_t show_temphyst(struct device *dev,
 static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm90_data *data = i2c_get_clientdata(client);
+	struct lm90_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 	int temp;
@@ -976,8 +978,8 @@ static ssize_t set_update_interval(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm90_data *data = i2c_get_clientdata(client);
+	struct lm90_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1057,6 +1059,15 @@ static const struct attribute_group lm90_group = {
 	.attrs = lm90_attributes,
 };
 
+static struct attribute *lm90_temp2_offset_attributes[] = {
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group lm90_temp2_offset_group = {
+	.attrs = lm90_temp2_offset_attributes,
+};
+
 /*
  * Additional attributes for devices with emergency sensors
  */
@@ -1393,22 +1404,6 @@ static int lm90_detect(struct i2c_client *client,
 	return 0;
 }
 
-static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
-{
-	struct device *dev = &client->dev;
-
-	if (data->flags & LM90_HAVE_TEMP3)
-		sysfs_remove_group(&dev->kobj, &lm90_temp3_group);
-	if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
-		sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group);
-	if (data->flags & LM90_HAVE_EMERGENCY)
-		sysfs_remove_group(&dev->kobj, &lm90_emergency_group);
-	if (data->flags & LM90_HAVE_OFFSET)
-		device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr);
-	device_remove_file(dev, &dev_attr_pec);
-	sysfs_remove_group(&dev->kobj, &lm90_group);
-}
-
 static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data)
 {
 	/* Restore initial configuration */
@@ -1418,10 +1413,9 @@ static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data)
 				  data->config_orig);
 }
 
-static void lm90_init_client(struct i2c_client *client)
+static void lm90_init_client(struct i2c_client *client, struct lm90_data *data)
 {
 	u8 config, convrate;
-	struct lm90_data *data = i2c_get_clientdata(client);
 
 	if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) {
 		dev_warn(&client->dev, "Failed to read convrate register!\n");
@@ -1519,6 +1513,7 @@ static int lm90_probe(struct i2c_client *client,
 	struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
 	struct lm90_data *data;
 	struct regulator *regulator;
+	int groups = 0;
 	int err;
 
 	regulator = devm_regulator_get(dev, "vcc");
@@ -1527,15 +1522,15 @@ static int lm90_probe(struct i2c_client *client,
 
 	err = regulator_enable(regulator);
 	if (err < 0) {
-		dev_err(&client->dev,
-			"Failed to enable regulator: %d\n", err);
+		dev_err(dev, "Failed to enable regulator: %d\n", err);
 		return err;
 	}
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm90_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
+	data->client = client;
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
@@ -1562,44 +1557,34 @@ static int lm90_probe(struct i2c_client *client,
 	data->max_convrate = lm90_params[data->kind].max_convrate;
 
 	/* Initialize the LM90 chip */
-	lm90_init_client(client);
+	lm90_init_client(client, data);
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &lm90_group);
-	if (err)
-		goto exit_restore;
+	data->groups[groups++] = &lm90_group;
+
+	if (data->flags & LM90_HAVE_OFFSET)
+		data->groups[groups++] = &lm90_temp2_offset_group;
+
+	if (data->flags & LM90_HAVE_EMERGENCY)
+		data->groups[groups++] = &lm90_emergency_group;
+
+	if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
+		data->groups[groups++] = &lm90_emergency_alarm_group;
+
+	if (data->flags & LM90_HAVE_TEMP3)
+		data->groups[groups++] = &lm90_temp3_group;
+
 	if (client->flags & I2C_CLIENT_PEC) {
 		err = device_create_file(dev, &dev_attr_pec);
 		if (err)
-			goto exit_remove_files;
-	}
-	if (data->flags & LM90_HAVE_OFFSET) {
-		err = device_create_file(dev,
-					&sensor_dev_attr_temp2_offset.dev_attr);
-		if (err)
-			goto exit_remove_files;
-	}
-	if (data->flags & LM90_HAVE_EMERGENCY) {
-		err = sysfs_create_group(&dev->kobj, &lm90_emergency_group);
-		if (err)
-			goto exit_remove_files;
-	}
-	if (data->flags & LM90_HAVE_EMERGENCY_ALARM) {
-		err = sysfs_create_group(&dev->kobj,
-					 &lm90_emergency_alarm_group);
-		if (err)
-			goto exit_remove_files;
-	}
-	if (data->flags & LM90_HAVE_TEMP3) {
-		err = sysfs_create_group(&dev->kobj, &lm90_temp3_group);
-		if (err)
-			goto exit_remove_files;
+			goto exit_restore;
 	}
 
-	data->hwmon_dev = hwmon_device_register(dev);
+	data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+							    data, data->groups);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
+		goto exit_remove_pec;
 	}
 
 	if (client->irq) {
@@ -1618,8 +1603,8 @@ static int lm90_probe(struct i2c_client *client,
 
 exit_unregister:
 	hwmon_device_unregister(data->hwmon_dev);
-exit_remove_files:
-	lm90_remove_files(client, data);
+exit_remove_pec:
+	device_remove_file(dev, &dev_attr_pec);
 exit_restore:
 	lm90_restore_conf(client, data);
 	regulator_disable(data->regulator);
@@ -1632,7 +1617,7 @@ static int lm90_remove(struct i2c_client *client)
 	struct lm90_data *data = i2c_get_clientdata(client);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	lm90_remove_files(client, data);
+	device_remove_file(&client->dev, &dev_attr_pec);
 	lm90_restore_conf(client, data);
 	regulator_disable(data->regulator);
 
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 9d0e87a4f0cb..b9022db6511a 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -380,7 +380,6 @@ static int lm92_probe(struct i2c_client *new_client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(new_client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the chipset */
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 6f1c6c0dbaf5..adf23165a6a7 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -2754,7 +2754,6 @@ static int lm93_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, data);
 
 	/* housekeeping */
-	data->valid = 0;
 	data->update = update;
 	mutex_init(&data->update_lock);
 
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 4b68fb2a31d7..cdf19adaec79 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -89,7 +89,7 @@ static const u8 lm95241_reg_address[] = {
 
 /* Client data (each client gets its own) */
 struct lm95241_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	unsigned long last_updated, interval;	/* in jiffies */
 	char valid;		/* zero until following fields are valid */
@@ -113,8 +113,8 @@ static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
 
 static struct lm95241_data *lm95241_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -122,7 +122,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev)
 	    !data->valid) {
 		int i;
 
-		dev_dbg(&client->dev, "Updating lm95241 data.\n");
+		dev_dbg(dev, "Updating lm95241 data.\n");
 		for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++)
 			data->temp[i]
 			  = i2c_smbus_read_byte_data(client,
@@ -153,8 +153,7 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr,
 static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE - 1,
 		data->model & to_sensor_dev_attr(attr)->index ? "1\n" : "2\n");
@@ -163,8 +162,8 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int shift;
 	u8 mask = to_sensor_dev_attr(attr)->index;
@@ -201,8 +200,7 @@ static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 static ssize_t show_min(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE - 1,
 			data->config & to_sensor_dev_attr(attr)->index ?
@@ -212,8 +210,7 @@ static ssize_t show_min(struct device *dev, struct device_attribute *attr,
 static ssize_t set_min(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 	long val;
 
 	if (kstrtol(buf, 10, &val) < 0)
@@ -229,7 +226,8 @@ static ssize_t set_min(struct device *dev, struct device_attribute *attr,
 		data->config &= ~to_sensor_dev_attr(attr)->index;
 	data->valid = 0;
 
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
+	i2c_smbus_write_byte_data(data->client, LM95241_REG_RW_CONFIG,
+				  data->config);
 
 	mutex_unlock(&data->update_lock);
 
@@ -239,8 +237,7 @@ static ssize_t set_min(struct device *dev, struct device_attribute *attr,
 static ssize_t show_max(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE - 1,
 			data->config & to_sensor_dev_attr(attr)->index ?
@@ -250,8 +247,7 @@ static ssize_t show_max(struct device *dev, struct device_attribute *attr,
 static ssize_t set_max(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 	long val;
 
 	if (kstrtol(buf, 10, &val) < 0)
@@ -267,7 +263,8 @@ static ssize_t set_max(struct device *dev, struct device_attribute *attr,
 		data->config &= ~to_sensor_dev_attr(attr)->index;
 	data->valid = 0;
 
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
+	i2c_smbus_write_byte_data(data->client, LM95241_REG_RW_CONFIG,
+				  data->config);
 
 	mutex_unlock(&data->update_lock);
 
@@ -286,8 +283,7 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
 static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
+	struct lm95241_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) < 0)
@@ -316,7 +312,7 @@ static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max,
 static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
 		   set_interval);
 
-static struct attribute *lm95241_attributes[] = {
+static struct attribute *lm95241_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&sensor_dev_attr_temp3_input.dev_attr.attr,
@@ -329,10 +325,7 @@ static struct attribute *lm95241_attributes[] = {
 	&dev_attr_update_interval.attr,
 	NULL
 };
-
-static const struct attribute_group lm95241_group = {
-	.attrs = lm95241_attributes,
-};
+ATTRIBUTE_GROUPS(lm95241);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm95241_detect(struct i2c_client *new_client,
@@ -366,14 +359,11 @@ static int lm95241_detect(struct i2c_client *new_client,
 	return 0;
 }
 
-static void lm95241_init_client(struct i2c_client *client)
+static void lm95241_init_client(struct i2c_client *client,
+				struct lm95241_data *data)
 {
-	struct lm95241_data *data = i2c_get_clientdata(client);
-
 	data->interval = HZ;	/* 1 sec default */
-	data->valid = 0;
 	data->config = CFG_CR0076;
-	data->model = 0;
 	data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
 
 	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
@@ -385,49 +375,27 @@ static void lm95241_init_client(struct i2c_client *client)
 				  data->model);
 }
 
-static int lm95241_probe(struct i2c_client *new_client,
+static int lm95241_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct lm95241_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&new_client->dev, sizeof(struct lm95241_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm95241_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(new_client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM95241 chip */
-	lm95241_init_client(new_client);
+	lm95241_init_client(client, data);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &lm95241_group);
-	return err;
-}
-
-static int lm95241_remove(struct i2c_client *client)
-{
-	struct lm95241_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm95241_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   lm95241_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Driver data (common to all clients) */
@@ -444,7 +412,6 @@ static struct i2c_driver lm95241_driver = {
 		.name	= DEVNAME,
 	},
 	.probe		= lm95241_probe,
-	.remove		= lm95241_remove,
 	.id_table	= lm95241_id,
 	.detect		= lm95241_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
index a6c85f0ff8f3..0ae0dfdafdff 100644
--- a/drivers/hwmon/lm95245.c
+++ b/drivers/hwmon/lm95245.c
@@ -115,7 +115,7 @@ static const u8 lm95245_reg_address[] = {
 
 /* Client data (each client gets its own) */
 struct lm95245_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	unsigned long last_updated;	/* in jiffies */
 	unsigned long interval;	/* in msecs */
@@ -140,8 +140,8 @@ static int temp_from_reg_signed(u8 val_h, u8 val_l)
 
 static struct lm95245_data *lm95245_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -149,7 +149,6 @@ static struct lm95245_data *lm95245_update_device(struct device *dev)
 		+ msecs_to_jiffies(data->interval)) || !data->valid) {
 		int i;
 
-		dev_dbg(&client->dev, "Updating lm95245 data.\n");
 		for (i = 0; i < ARRAY_SIZE(lm95245_reg_address); i++)
 			data->regs[i]
 			  = i2c_smbus_read_byte_data(client,
@@ -249,9 +248,9 @@ static ssize_t show_limit(struct device *dev, struct device_attribute *attr,
 static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = data->client;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) < 0)
@@ -272,27 +271,38 @@ static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
+static ssize_t show_crit_hyst(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct lm95245_data *data = lm95245_update_device(dev);
+	int index = to_sensor_dev_attr(attr)->index;
+	int hyst = data->regs[index] - data->regs[8];
+
+	return snprintf(buf, PAGE_SIZE - 1, "%d\n", hyst * 1000);
+}
+
 static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
+	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = data->client;
 	unsigned long val;
+	int hyst, limit;
 
 	if (kstrtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 
-	val /= 1000;
-
-	val = clamp_val(val, 0, 31);
-
 	mutex_lock(&data->update_lock);
 
-	data->valid = 0;
+	limit = i2c_smbus_read_byte_data(client, lm95245_reg_address[index]);
+	hyst = limit - val / 1000;
+	hyst = clamp_val(hyst, 0, 31);
+	data->regs[8] = hyst;
 
 	/* shared crit hysteresis */
 	i2c_smbus_write_byte_data(client, LM95245_REG_RW_COMMON_HYSTERESIS,
-		val);
+		hyst);
 
 	mutex_unlock(&data->update_lock);
 
@@ -302,8 +312,7 @@ static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr,
 static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE - 1,
 		data->config2 & CFG2_REMOTE_TT ? "1\n" : "2\n");
@@ -312,8 +321,8 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) < 0)
@@ -359,8 +368,8 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
 static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95245_data *data = i2c_get_clientdata(client);
+	struct lm95245_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) < 0)
@@ -378,16 +387,15 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit,
 		set_limit, 6);
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
-		set_crit_hyst, 8);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_crit_hyst,
+		set_crit_hyst, 6);
 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
 		STATUS1_LOC);
 
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
 static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit,
 		set_limit, 7);
-static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
-		set_crit_hyst, 8);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_crit_hyst, NULL, 7);
 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
 		STATUS1_RTCRIT);
 static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type,
@@ -398,7 +406,7 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL,
 static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
 		set_interval);
 
-static struct attribute *lm95245_attributes[] = {
+static struct attribute *lm95245_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
@@ -412,10 +420,7 @@ static struct attribute *lm95245_attributes[] = {
 	&dev_attr_update_interval.attr,
 	NULL
 };
-
-static const struct attribute_group lm95245_group = {
-	.attrs = lm95245_attributes,
-};
+ATTRIBUTE_GROUPS(lm95245);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm95245_detect(struct i2c_client *new_client,
@@ -436,11 +441,9 @@ static int lm95245_detect(struct i2c_client *new_client,
 	return 0;
 }
 
-static void lm95245_init_client(struct i2c_client *client)
+static void lm95245_init_client(struct i2c_client *client,
+				struct lm95245_data *data)
 {
-	struct lm95245_data *data = i2c_get_clientdata(client);
-
-	data->valid = 0;
 	data->interval = lm95245_read_conversion_rate(client);
 
 	data->config1 = i2c_smbus_read_byte_data(client,
@@ -456,49 +459,27 @@ static void lm95245_init_client(struct i2c_client *client)
 	}
 }
 
-static int lm95245_probe(struct i2c_client *new_client,
+static int lm95245_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct lm95245_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&new_client->dev, sizeof(struct lm95245_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm95245_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(new_client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM95245 chip */
-	lm95245_init_client(new_client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &lm95245_group);
-	return err;
-}
+	lm95245_init_client(client, data);
 
-static int lm95245_remove(struct i2c_client *client)
-{
-	struct lm95245_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm95245_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   lm95245_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Driver data (common to all clients) */
@@ -514,7 +495,6 @@ static struct i2c_driver lm95245_driver = {
 		.name	= DEVNAME,
 	},
 	.probe		= lm95245_probe,
-	.remove		= lm95245_remove,
 	.id_table	= lm95245_id,
 	.detect		= lm95245_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
new file mode 100644
index 000000000000..c104cc32989d
--- /dev/null
+++ b/drivers/hwmon/ltc2945.c
@@ -0,0 +1,519 @@
+/*
+ * Driver for Linear Technology LTC2945 I2C Power Monitor
+ *
+ * Copyright (c) 2014 Guenter Roeck
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+/* chip registers */
+#define LTC2945_CONTROL			0x00
+#define LTC2945_ALERT			0x01
+#define LTC2945_STATUS			0x02
+#define LTC2945_FAULT			0x03
+#define LTC2945_POWER_H			0x05
+#define LTC2945_MAX_POWER_H		0x08
+#define LTC2945_MIN_POWER_H		0x0b
+#define LTC2945_MAX_POWER_THRES_H	0x0e
+#define LTC2945_MIN_POWER_THRES_H	0x11
+#define LTC2945_SENSE_H			0x14
+#define LTC2945_MAX_SENSE_H		0x16
+#define LTC2945_MIN_SENSE_H		0x18
+#define LTC2945_MAX_SENSE_THRES_H	0x1a
+#define LTC2945_MIN_SENSE_THRES_H	0x1c
+#define LTC2945_VIN_H			0x1e
+#define LTC2945_MAX_VIN_H		0x20
+#define LTC2945_MIN_VIN_H		0x22
+#define LTC2945_MAX_VIN_THRES_H		0x24
+#define LTC2945_MIN_VIN_THRES_H		0x26
+#define LTC2945_ADIN_H			0x28
+#define LTC2945_MAX_ADIN_H		0x2a
+#define LTC2945_MIN_ADIN_H		0x2c
+#define LTC2945_MAX_ADIN_THRES_H	0x2e
+#define LTC2945_MIN_ADIN_THRES_H	0x30
+#define LTC2945_MIN_ADIN_THRES_L	0x31
+
+/* Fault register bits */
+
+#define FAULT_ADIN_UV		(1 << 0)
+#define FAULT_ADIN_OV		(1 << 1)
+#define FAULT_VIN_UV		(1 << 2)
+#define FAULT_VIN_OV		(1 << 3)
+#define FAULT_SENSE_UV		(1 << 4)
+#define FAULT_SENSE_OV		(1 << 5)
+#define FAULT_POWER_UV		(1 << 6)
+#define FAULT_POWER_OV		(1 << 7)
+
+/* Control register bits */
+
+#define CONTROL_MULT_SELECT	(1 << 0)
+#define CONTROL_TEST_MODE	(1 << 4)
+
+static inline bool is_power_reg(u8 reg)
+{
+	return reg < LTC2945_SENSE_H;
+}
+
+/* Return the value from the given register in uW, mV, or mA */
+static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int control;
+	u8 buf[3];
+	long long val;
+	int ret;
+
+	ret = regmap_bulk_read(regmap, reg, buf,
+			       is_power_reg(reg) ? 3 : 2);
+	if (ret < 0)
+		return ret;
+
+	if (is_power_reg(reg)) {
+		/* power */
+		val = (buf[0] << 16) + (buf[1] << 8) + buf[2];
+	} else {
+		/* current, voltage */
+		val = (buf[0] << 4) + (buf[1] >> 4);
+	}
+
+	switch (reg) {
+	case LTC2945_POWER_H:
+	case LTC2945_MAX_POWER_H:
+	case LTC2945_MIN_POWER_H:
+	case LTC2945_MAX_POWER_THRES_H:
+	case LTC2945_MIN_POWER_THRES_H:
+		/*
+		 * Convert to uW by assuming current is measured with
+		 * an 1mOhm sense resistor, similar to current
+		 * measurements.
+		 * Control register bit 0 selects if voltage at SENSE+/VDD
+		 * or voltage at ADIN is used to measure power.
+		 */
+		ret = regmap_read(regmap, LTC2945_CONTROL, &control);
+		if (ret < 0)
+			return ret;
+		if (control & CONTROL_MULT_SELECT) {
+			/* 25 mV * 25 uV = 0.625 uV resolution. */
+			val *= 625LL;
+		} else {
+			/* 0.5 mV * 25 uV = 0.0125 uV resolution. */
+			val = (val * 25LL) >> 1;
+		}
+		break;
+	case LTC2945_VIN_H:
+	case LTC2945_MAX_VIN_H:
+	case LTC2945_MIN_VIN_H:
+	case LTC2945_MAX_VIN_THRES_H:
+	case LTC2945_MIN_VIN_THRES_H:
+		/* 25 mV resolution. Convert to mV. */
+		val *= 25;
+		break;
+	case LTC2945_ADIN_H:
+	case LTC2945_MAX_ADIN_H:
+	case LTC2945_MIN_ADIN_THRES_H:
+	case LTC2945_MAX_ADIN_THRES_H:
+	case LTC2945_MIN_ADIN_H:
+		/* 0.5mV resolution. Convert to mV. */
+		val = val >> 1;
+		break;
+	case LTC2945_SENSE_H:
+	case LTC2945_MAX_SENSE_H:
+	case LTC2945_MIN_SENSE_H:
+	case LTC2945_MAX_SENSE_THRES_H:
+	case LTC2945_MIN_SENSE_THRES_H:
+		/*
+		 * 25 uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA. If a different sense
+		 * resistor is installed, calculate the actual current by
+		 * dividing the reported current by the sense resistor value
+		 * in mOhm.
+		 */
+		val *= 25;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return val;
+}
+
+static int ltc2945_val_to_reg(struct device *dev, u8 reg,
+			      unsigned long val)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int control;
+	int ret;
+
+	switch (reg) {
+	case LTC2945_POWER_H:
+	case LTC2945_MAX_POWER_H:
+	case LTC2945_MIN_POWER_H:
+	case LTC2945_MAX_POWER_THRES_H:
+	case LTC2945_MIN_POWER_THRES_H:
+		/*
+		 * Convert to register value by assuming current is measured
+		 * with an 1mOhm sense resistor, similar to current
+		 * measurements.
+		 * Control register bit 0 selects if voltage at SENSE+/VDD
+		 * or voltage at ADIN is used to measure power, which in turn
+		 * determines register calculations.
+		 */
+		ret = regmap_read(regmap, LTC2945_CONTROL, &control);
+		if (ret < 0)
+			return ret;
+		if (control & CONTROL_MULT_SELECT) {
+			/* 25 mV * 25 uV = 0.625 uV resolution. */
+			val = DIV_ROUND_CLOSEST(val, 625);
+		} else {
+			/*
+			 * 0.5 mV * 25 uV = 0.0125 uV resolution.
+			 * Divide first to avoid overflow;
+			 * accept loss of accuracy.
+			 */
+			val = DIV_ROUND_CLOSEST(val, 25) * 2;
+		}
+		break;
+	case LTC2945_VIN_H:
+	case LTC2945_MAX_VIN_H:
+	case LTC2945_MIN_VIN_H:
+	case LTC2945_MAX_VIN_THRES_H:
+	case LTC2945_MIN_VIN_THRES_H:
+		/* 25 mV resolution. */
+		val /= 25;
+		break;
+	case LTC2945_ADIN_H:
+	case LTC2945_MAX_ADIN_H:
+	case LTC2945_MIN_ADIN_THRES_H:
+	case LTC2945_MAX_ADIN_THRES_H:
+	case LTC2945_MIN_ADIN_H:
+		/* 0.5mV resolution. */
+		val *= 2;
+		break;
+	case LTC2945_SENSE_H:
+	case LTC2945_MAX_SENSE_H:
+	case LTC2945_MIN_SENSE_H:
+	case LTC2945_MAX_SENSE_THRES_H:
+	case LTC2945_MIN_SENSE_THRES_H:
+		/*
+		 * 25 uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA. If a different sense
+		 * resistor is installed, calculate the actual current by
+		 * dividing the reported current by the sense resistor value
+		 * in mOhm.
+		 */
+		val = DIV_ROUND_CLOSEST(val, 25);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return val;
+}
+
+static ssize_t ltc2945_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	long long value;
+
+	value = ltc2945_reg_to_val(dev, attr->index);
+	if (value < 0)
+		return value;
+	return snprintf(buf, PAGE_SIZE, "%lld\n", value);
+}
+
+static ssize_t ltc2945_set_value(struct device *dev,
+				     struct device_attribute *da,
+				     const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	u8 reg = attr->index;
+	unsigned long val;
+	u8 regbuf[3];
+	int num_regs;
+	int regval;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	/* convert to register value, then clamp and write result */
+	regval = ltc2945_val_to_reg(dev, reg, val);
+	if (is_power_reg(reg)) {
+		regval = clamp_val(regval, 0, 0xffffff);
+		regbuf[0] = regval >> 16;
+		regbuf[1] = (regval >> 8) & 0xff;
+		regbuf[2] = regval;
+		num_regs = 3;
+	} else {
+		regval = clamp_val(regval, 0, 0xfff) << 4;
+		regbuf[0] = regval >> 8;
+		regbuf[1] = regval & 0xff;
+		num_regs = 2;
+	}
+	ret = regmap_bulk_write(regmap, reg, regbuf, num_regs);
+	return ret < 0 ? ret : count;
+}
+
+static ssize_t ltc2945_reset_history(struct device *dev,
+				     struct device_attribute *da,
+				     const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	u8 reg = attr->index;
+	int num_regs = is_power_reg(reg) ? 3 : 2;
+	u8 buf_min[3] = { 0xff, 0xff, 0xff };
+	u8 buf_max[3] = { 0, 0, 0 };
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+	if (val != 1)
+		return -EINVAL;
+
+	ret = regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE,
+				 CONTROL_TEST_MODE);
+
+	/* Reset minimum */
+	ret = regmap_bulk_write(regmap, reg, buf_min, num_regs);
+	if (ret)
+		return ret;
+
+	switch (reg) {
+	case LTC2945_MIN_POWER_H:
+		reg = LTC2945_MAX_POWER_H;
+		break;
+	case LTC2945_MIN_SENSE_H:
+		reg = LTC2945_MAX_SENSE_H;
+		break;
+	case LTC2945_MIN_VIN_H:
+		reg = LTC2945_MAX_VIN_H;
+		break;
+	case LTC2945_MIN_ADIN_H:
+		reg = LTC2945_MAX_ADIN_H;
+		break;
+	default:
+		BUG();
+		break;
+	}
+	/* Reset maximum */
+	ret = regmap_bulk_write(regmap, reg, buf_max, num_regs);
+
+	/* Try resetting test mode even if there was an error */
+	regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 0);
+
+	return ret ? : count;
+}
+
+static ssize_t ltc2945_show_bool(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int fault;
+	int ret;
+
+	ret = regmap_read(regmap, LTC2945_FAULT, &fault);
+	if (ret < 0)
+		return ret;
+
+	fault &= attr->index;
+	if (fault)		/* Clear reported faults in chip register */
+		regmap_update_bits(regmap, LTC2945_FAULT, attr->index, 0);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+}
+
+/* Input voltages */
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_VIN_H);
+static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MIN_VIN_THRES_H);
+static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MAX_VIN_THRES_H);
+static SENSOR_DEVICE_ATTR(in1_lowest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MIN_VIN_H);
+static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MAX_VIN_H);
+static SENSOR_DEVICE_ATTR(in1_reset_history, S_IWUSR, NULL,
+			  ltc2945_reset_history, LTC2945_MIN_VIN_H);
+
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_ADIN_H);
+static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MIN_ADIN_THRES_H);
+static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MAX_ADIN_THRES_H);
+static SENSOR_DEVICE_ATTR(in2_lowest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MIN_ADIN_H);
+static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MAX_ADIN_H);
+static SENSOR_DEVICE_ATTR(in2_reset_history, S_IWUSR, NULL,
+			  ltc2945_reset_history, LTC2945_MIN_ADIN_H);
+
+/* Voltage alarms */
+
+static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_VIN_UV);
+static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_VIN_OV);
+static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_ADIN_UV);
+static SENSOR_DEVICE_ATTR(in2_max_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_ADIN_OV);
+
+/* Currents (via sense resistor) */
+
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_SENSE_H);
+static SENSOR_DEVICE_ATTR(curr1_min, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MIN_SENSE_THRES_H);
+static SENSOR_DEVICE_ATTR(curr1_max, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MAX_SENSE_THRES_H);
+static SENSOR_DEVICE_ATTR(curr1_lowest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MIN_SENSE_H);
+static SENSOR_DEVICE_ATTR(curr1_highest, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_MAX_SENSE_H);
+static SENSOR_DEVICE_ATTR(curr1_reset_history, S_IWUSR, NULL,
+			  ltc2945_reset_history, LTC2945_MIN_SENSE_H);
+
+/* Current alarms */
+
+static SENSOR_DEVICE_ATTR(curr1_min_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_SENSE_UV);
+static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_SENSE_OV);
+
+/* Power */
+
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc2945_show_value, NULL,
+			  LTC2945_POWER_H);
+static SENSOR_DEVICE_ATTR(power1_min, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MIN_POWER_THRES_H);
+static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO | S_IWUSR, ltc2945_show_value,
+			  ltc2945_set_value, LTC2945_MAX_POWER_THRES_H);
+static SENSOR_DEVICE_ATTR(power1_input_lowest, S_IRUGO, ltc2945_show_value,
+			  NULL, LTC2945_MIN_POWER_H);
+static SENSOR_DEVICE_ATTR(power1_input_highest, S_IRUGO, ltc2945_show_value,
+			  NULL, LTC2945_MAX_POWER_H);
+static SENSOR_DEVICE_ATTR(power1_reset_history, S_IWUSR, NULL,
+			  ltc2945_reset_history, LTC2945_MIN_POWER_H);
+
+/* Power alarms */
+
+static SENSOR_DEVICE_ATTR(power1_min_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_POWER_UV);
+static SENSOR_DEVICE_ATTR(power1_max_alarm, S_IRUGO, ltc2945_show_bool, NULL,
+			  FAULT_POWER_OV);
+
+static struct attribute *ltc2945_attrs[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_lowest.dev_attr.attr,
+	&sensor_dev_attr_in1_highest.dev_attr.attr,
+	&sensor_dev_attr_in1_reset_history.dev_attr.attr,
+	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_lowest.dev_attr.attr,
+	&sensor_dev_attr_in2_highest.dev_attr.attr,
+	&sensor_dev_attr_in2_reset_history.dev_attr.attr,
+	&sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_max_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_min.dev_attr.attr,
+	&sensor_dev_attr_curr1_max.dev_attr.attr,
+	&sensor_dev_attr_curr1_lowest.dev_attr.attr,
+	&sensor_dev_attr_curr1_highest.dev_attr.attr,
+	&sensor_dev_attr_curr1_reset_history.dev_attr.attr,
+	&sensor_dev_attr_curr1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_power1_input.dev_attr.attr,
+	&sensor_dev_attr_power1_min.dev_attr.attr,
+	&sensor_dev_attr_power1_max.dev_attr.attr,
+	&sensor_dev_attr_power1_input_lowest.dev_attr.attr,
+	&sensor_dev_attr_power1_input_highest.dev_attr.attr,
+	&sensor_dev_attr_power1_reset_history.dev_attr.attr,
+	&sensor_dev_attr_power1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_power1_max_alarm.dev_attr.attr,
+
+	NULL,
+};
+ATTRIBUTE_GROUPS(ltc2945);
+
+static struct regmap_config ltc2945_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = LTC2945_MIN_ADIN_THRES_L,
+};
+
+static int ltc2945_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ltc2945_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	/* Clear faults */
+	regmap_write(regmap, LTC2945_FAULT, 0x00);
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   regmap,
+							   ltc2945_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id ltc2945_id[] = {
+	{"ltc2945", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc2945_id);
+
+static struct i2c_driver ltc2945_driver = {
+	.driver = {
+		   .name = "ltc2945",
+		   },
+	.probe = ltc2945_probe,
+	.id_table = ltc2945_id,
+};
+
+module_i2c_driver(ltc2945_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("LTC2945 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
index 8a142960d69e..c8a9bd9b050f 100644
--- a/drivers/hwmon/ltc4215.c
+++ b/drivers/hwmon/ltc4215.c
@@ -33,7 +33,7 @@ enum ltc4215_cmd {
 };
 
 struct ltc4215_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 
 	struct mutex update_lock;
 	bool valid;
@@ -45,8 +45,8 @@ struct ltc4215_data {
 
 static struct ltc4215_data *ltc4215_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ltc4215_data *data = i2c_get_clientdata(client);
+	struct ltc4215_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	s32 val;
 	int i;
 
@@ -214,7 +214,7 @@ static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
  * Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
  */
-static struct attribute *ltc4215_attributes[] = {
+static struct attribute *ltc4215_attrs[] = {
 	&sensor_dev_attr_curr1_input.dev_attr.attr,
 	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 
@@ -229,57 +229,33 @@ static struct attribute *ltc4215_attributes[] = {
 
 	NULL,
 };
-
-static const struct attribute_group ltc4215_group = {
-	.attrs = ltc4215_attributes,
-};
+ATTRIBUTE_GROUPS(ltc4215);
 
 static int ltc4215_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	struct device *dev = &client->dev;
 	struct ltc4215_data *data;
-	int ret;
+	struct device *hwmon_dev;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LTC4215 chip */
 	i2c_smbus_write_byte_data(client, LTC4215_FAULT, 0x00);
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &ltc4215_group);
-	if (ret)
-		return ret;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto out_hwmon_device_register;
-	}
-
-	return 0;
-
-out_hwmon_device_register:
-	sysfs_remove_group(&client->dev.kobj, &ltc4215_group);
-	return ret;
-}
-
-static int ltc4215_remove(struct i2c_client *client)
-{
-	struct ltc4215_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ltc4215_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   ltc4215_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ltc4215_id[] = {
@@ -294,7 +270,6 @@ static struct i2c_driver ltc4215_driver = {
 		.name	= "ltc4215",
 	},
 	.probe		= ltc4215_probe,
-	.remove		= ltc4215_remove,
 	.id_table	= ltc4215_id,
 };
 
diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c
new file mode 100644
index 000000000000..07c25653659f
--- /dev/null
+++ b/drivers/hwmon/ltc4222.c
@@ -0,0 +1,237 @@
+/*
+ * Driver for Linear Technology LTC4222 Dual Hot Swap controller
+ *
+ * Copyright (c) 2014 Guenter Roeck
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+/* chip registers */
+
+#define LTC4222_CONTROL1	0xd0
+#define LTC4222_ALERT1		0xd1
+#define LTC4222_STATUS1		0xd2
+#define LTC4222_FAULT1		0xd3
+#define LTC4222_CONTROL2	0xd4
+#define LTC4222_ALERT2		0xd5
+#define LTC4222_STATUS2		0xd6
+#define LTC4222_FAULT2		0xd7
+#define LTC4222_SOURCE1		0xd8
+#define LTC4222_SOURCE2		0xda
+#define LTC4222_ADIN1		0xdc
+#define LTC4222_ADIN2		0xde
+#define LTC4222_SENSE1		0xe0
+#define LTC4222_SENSE2		0xe2
+#define LTC4222_ADC_CONTROL	0xe4
+
+/*
+ * Fault register bits
+ */
+#define FAULT_OV	BIT(0)
+#define FAULT_UV	BIT(1)
+#define FAULT_OC	BIT(2)
+#define FAULT_POWER_BAD	BIT(3)
+#define FAULT_FET_BAD	BIT(5)
+
+/* Return the voltage from the given register in mV or mA */
+static int ltc4222_get_value(struct device *dev, u8 reg)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int val;
+	u8 buf[2];
+	int ret;
+
+	ret = regmap_bulk_read(regmap, reg, buf, 2);
+	if (ret < 0)
+		return ret;
+
+	val = ((buf[0] << 8) + buf[1]) >> 6;
+
+	switch (reg) {
+	case LTC4222_ADIN1:
+	case LTC4222_ADIN2:
+		/* 1.25 mV resolution. Convert to mV. */
+		val = DIV_ROUND_CLOSEST(val * 5, 4);
+		break;
+	case LTC4222_SOURCE1:
+	case LTC4222_SOURCE2:
+		/* 31.25 mV resolution. Convert to mV. */
+		val = DIV_ROUND_CLOSEST(val * 125, 4);
+		break;
+	case LTC4222_SENSE1:
+	case LTC4222_SENSE2:
+		/*
+		 * 62.5 uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA. If a different sense
+		 * resistor is installed, calculate the actual current by
+		 * dividing the reported current by the sense resistor value
+		 * in mOhm.
+		 */
+		val = DIV_ROUND_CLOSEST(val * 125, 2);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return val;
+}
+
+static ssize_t ltc4222_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int value;
+
+	value = ltc4222_get_value(dev, attr->index);
+	if (value < 0)
+		return value;
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t ltc4222_show_bool(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int fault;
+	int ret;
+
+	ret = regmap_read(regmap, attr->nr, &fault);
+	if (ret < 0)
+		return ret;
+	fault &= attr->index;
+	if (fault)		/* Clear reported faults in chip register */
+		regmap_update_bits(regmap, attr->nr, attr->index, 0);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+}
+
+/* Voltages */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_SOURCE1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_ADIN1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_SOURCE2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_ADIN2);
+
+/*
+ * Voltage alarms
+ * UV/OV faults are associated with the input voltage, and power bad and fet
+ * faults are associated with the output voltage.
+ */
+static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT1, FAULT_UV);
+static SENSOR_DEVICE_ATTR_2(in1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT1, FAULT_OV);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT1, FAULT_POWER_BAD | FAULT_FET_BAD);
+
+static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT2, FAULT_UV);
+static SENSOR_DEVICE_ATTR_2(in3_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT2, FAULT_OV);
+static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT2, FAULT_POWER_BAD | FAULT_FET_BAD);
+
+/* Current (via sense resistor) */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_SENSE1);
+static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4222_show_value, NULL,
+			  LTC4222_SENSE2);
+
+/* Overcurrent alarm */
+static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT1, FAULT_OC);
+static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
+			    LTC4222_FAULT2, FAULT_OC);
+
+static struct attribute *ltc4222_attrs[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_curr2_input.dev_attr.attr,
+	&sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
+
+	NULL,
+};
+ATTRIBUTE_GROUPS(ltc4222);
+
+static struct regmap_config ltc4222_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = LTC4222_ADC_CONTROL,
+};
+
+static int ltc4222_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ltc4222_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	/* Clear faults */
+	regmap_write(regmap, LTC4222_FAULT1, 0x00);
+	regmap_write(regmap, LTC4222_FAULT2, 0x00);
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   regmap,
+							   ltc4222_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id ltc4222_id[] = {
+	{"ltc4222", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc4222_id);
+
+static struct i2c_driver ltc4222_driver = {
+	.driver = {
+		   .name = "ltc4222",
+		   },
+	.probe = ltc4222_probe,
+	.id_table = ltc4222_id,
+};
+
+module_i2c_driver(ltc4222_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("LTC4222 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index d4172933ce4f..681b5b7b3c3b 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -95,7 +95,6 @@ static void ltc4245_update_gpios(struct device *dev)
 	 * readings as stale by setting them to -EAGAIN
 	 */
 	if (time_after(jiffies, data->last_updated + 5 * HZ)) {
-		dev_dbg(&client->dev, "Marking GPIOs invalid\n");
 		for (i = 0; i < ARRAY_SIZE(data->gpios); i++)
 			data->gpios[i] = -EAGAIN;
 	}
@@ -141,8 +140,6 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
 
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 
-		dev_dbg(&client->dev, "Starting ltc4245 update\n");
-
 		/* Read control registers -- 0x00 to 0x07 */
 		for (i = 0; i < ARRAY_SIZE(data->cregs); i++) {
 			val = i2c_smbus_read_byte_data(client, i);
@@ -470,19 +467,15 @@ static void ltc4245_sysfs_add_groups(struct ltc4245_data *data)
 static bool ltc4245_use_extra_gpios(struct i2c_client *client)
 {
 	struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev);
-#ifdef CONFIG_OF
 	struct device_node *np = client->dev.of_node;
-#endif
 
 	/* prefer platform data */
 	if (pdata)
 		return pdata->use_extra_gpios;
 
-#ifdef CONFIG_OF
 	/* fallback on OF */
 	if (of_find_property(np, "ltc4245,use-extra-gpios", NULL))
 		return true;
-#endif
 
 	return false;
 }
@@ -512,24 +505,10 @@ static int ltc4245_probe(struct i2c_client *client,
 	/* Add sysfs hooks */
 	ltc4245_sysfs_add_groups(data);
 
-	hwmon_dev = hwmon_device_register_with_groups(&client->dev,
-						      client->name, data,
-						      data->groups);
-	if (IS_ERR(hwmon_dev))
-		return PTR_ERR(hwmon_dev);
-
-	i2c_set_clientdata(client, hwmon_dev);
-
-	return 0;
-}
-
-static int ltc4245_remove(struct i2c_client *client)
-{
-	struct device *hwmon_dev = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(hwmon_dev);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name, data,
+							   data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ltc4245_id[] = {
@@ -544,7 +523,6 @@ static struct i2c_driver ltc4245_driver = {
 		.name	= "ltc4245",
 	},
 	.probe		= ltc4245_probe,
-	.remove		= ltc4245_remove,
 	.id_table	= ltc4245_id,
 };
 
diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c
new file mode 100644
index 000000000000..453a250d9df5
--- /dev/null
+++ b/drivers/hwmon/ltc4260.c
@@ -0,0 +1,200 @@
+/*
+ * Driver for Linear Technology LTC4260 I2C Positive Voltage Hot Swap Controller
+ *
+ * Copyright (c) 2014 Guenter Roeck
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+/* chip registers */
+#define LTC4260_CONTROL	0x00
+#define LTC4260_ALERT	0x01
+#define LTC4260_STATUS	0x02
+#define LTC4260_FAULT	0x03
+#define LTC4260_SENSE	0x04
+#define LTC4260_SOURCE	0x05
+#define LTC4260_ADIN	0x06
+
+/*
+ * Fault register bits
+ */
+#define FAULT_OV	(1 << 0)
+#define FAULT_UV	(1 << 1)
+#define FAULT_OC	(1 << 2)
+#define FAULT_POWER_BAD	(1 << 3)
+#define FAULT_FET_SHORT	(1 << 5)
+
+/* Return the voltage from the given register in mV or mA */
+static int ltc4260_get_value(struct device *dev, u8 reg)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(regmap, reg, &val);
+	if (ret < 0)
+		return ret;
+
+	switch (reg) {
+	case LTC4260_ADIN:
+		/* 10 mV resolution. Convert to mV. */
+		val = val * 10;
+		break;
+	case LTC4260_SOURCE:
+		/* 400 mV resolution. Convert to mV. */
+		val = val * 400;
+		break;
+	case LTC4260_SENSE:
+		/*
+		 * 300 uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA. If a different sense
+		 * resistor is installed, calculate the actual current by
+		 * dividing the reported current by the sense resistor value
+		 * in mOhm.
+		 */
+		val = val * 300;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return val;
+}
+
+static ssize_t ltc4260_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int value;
+
+	value = ltc4260_get_value(dev, attr->index);
+	if (value < 0)
+		return value;
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t ltc4260_show_bool(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int fault;
+	int ret;
+
+	ret = regmap_read(regmap, LTC4260_FAULT, &fault);
+	if (ret < 0)
+		return ret;
+
+	fault &= attr->index;
+	if (fault)		/* Clear reported faults in chip register */
+		regmap_update_bits(regmap, LTC4260_FAULT, attr->index, 0);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+}
+
+/* Voltages */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4260_show_value, NULL,
+			  LTC4260_SOURCE);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4260_show_value, NULL,
+			  LTC4260_ADIN);
+
+/*
+ * Voltage alarms
+ * UV/OV faults are associated with the input voltage, and the POWER BAD and
+ * FET SHORT faults are associated with the output voltage.
+ */
+static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4260_show_bool, NULL,
+			  FAULT_UV);
+static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4260_show_bool, NULL,
+			  FAULT_OV);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, ltc4260_show_bool, NULL,
+			  FAULT_POWER_BAD | FAULT_FET_SHORT);
+
+/* Current (via sense resistor) */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4260_show_value, NULL,
+			  LTC4260_SENSE);
+
+/* Overcurrent alarm */
+static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4260_show_bool, NULL,
+			  FAULT_OC);
+
+static struct attribute *ltc4260_attrs[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+
+	NULL,
+};
+ATTRIBUTE_GROUPS(ltc4260);
+
+static struct regmap_config ltc4260_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = LTC4260_ADIN,
+};
+
+static int ltc4260_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ltc4260_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	/* Clear faults */
+	regmap_write(regmap, LTC4260_FAULT, 0x00);
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   regmap,
+							   ltc4260_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id ltc4260_id[] = {
+	{"ltc4260", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc4260_id);
+
+static struct i2c_driver ltc4260_driver = {
+	.driver = {
+		   .name = "ltc4260",
+		   },
+	.probe = ltc4260_probe,
+	.id_table = ltc4260_id,
+};
+
+module_i2c_driver(ltc4260_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("LTC4260 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 6638e997f83f..4c23afe113e2 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -273,7 +273,6 @@ static int max1619_probe(struct i2c_client *new_client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(new_client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the MAX1619 chip */
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index 029b65e6c589..e3ed0a5b6d94 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -66,7 +66,8 @@ MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
 enum chips { max1668, max1805, max1989 };
 
 struct max1668_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	enum chips type;
 
 	struct mutex update_lock;
@@ -82,8 +83,8 @@ struct max1668_data {
 
 static struct max1668_data *max1668_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max1668_data *data = i2c_get_clientdata(client);
+	struct max1668_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct max1668_data *ret = data;
 	s32 val;
 	int i;
@@ -205,8 +206,8 @@ static ssize_t set_temp_max(struct device *dev,
 			    const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max1668_data *data = i2c_get_clientdata(client);
+	struct max1668_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	int ret;
 
@@ -216,10 +217,11 @@ static ssize_t set_temp_max(struct device *dev,
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[index] = clamp_val(temp/1000, -128, 127);
-	if (i2c_smbus_write_byte_data(client,
+	ret = i2c_smbus_write_byte_data(client,
 					MAX1668_REG_LIMH_WR(index),
-					data->temp_max[index]))
-		count = -EIO;
+					data->temp_max[index]);
+	if (ret < 0)
+		count = ret;
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -230,8 +232,8 @@ static ssize_t set_temp_min(struct device *dev,
 			    const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max1668_data *data = i2c_get_clientdata(client);
+	struct max1668_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	int ret;
 
@@ -241,10 +243,11 @@ static ssize_t set_temp_min(struct device *dev,
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[index] = clamp_val(temp/1000, -128, 127);
-	if (i2c_smbus_write_byte_data(client,
+	ret = i2c_smbus_write_byte_data(client,
 					MAX1668_REG_LIML_WR(index),
-					data->temp_min[index]))
-		count = -EIO;
+					data->temp_min[index]);
+	if (ret < 0)
+		count = ret;
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -405,60 +408,29 @@ static int max1668_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct max1668_data *data;
-	int err;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct max1668_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct max1668_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	data->type = id->driver_data;
 	mutex_init(&data->update_lock);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &max1668_group_common);
-	if (err)
-		return err;
-
-	if (data->type == max1668 || data->type == max1989) {
-		err = sysfs_create_group(&client->dev.kobj,
-					 &max1668_group_unique);
-		if (err)
-			goto error_sysrem0;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error_sysrem1;
-	}
-
-	return 0;
-
-error_sysrem1:
+	/* sysfs hooks */
+	data->groups[0] = &max1668_group_common;
 	if (data->type == max1668 || data->type == max1989)
-		sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
-error_sysrem0:
-	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
-	return err;
-}
-
-static int max1668_remove(struct i2c_client *client)
-{
-	struct max1668_data *data = i2c_get_clientdata(client);
+		data->groups[1] = &max1668_group_unique;
 
-	hwmon_device_unregister(data->hwmon_dev);
-	if (data->type == max1668 || data->type == max1989)
-		sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
-
-	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id max1668_id[] = {
@@ -476,7 +448,6 @@ static struct i2c_driver max1668_driver = {
 		  .name	= "max1668",
 		  },
 	.probe = max1668_probe,
-	.remove	= max1668_remove,
 	.id_table = max1668_id,
 	.detect	= max1668_detect,
 	.address_list = max1668_addr_list,
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index 066e587a18a5..70650de2cbd1 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -80,7 +80,7 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
  * Client data (each client gets its own)
  */
 struct max6639_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -104,8 +104,8 @@ struct max6639_data {
 
 static struct max6639_data *max6639_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
+	struct max6639_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct max6639_data *ret = data;
 	int i;
 	int status_reg;
@@ -191,9 +191,8 @@ static ssize_t show_temp_fault(struct device *dev,
 static ssize_t show_temp_max(struct device *dev,
 			     struct device_attribute *dev_attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000));
 }
@@ -202,9 +201,9 @@ static ssize_t set_temp_max(struct device *dev,
 			    struct device_attribute *dev_attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int res;
 
@@ -224,9 +223,8 @@ static ssize_t set_temp_max(struct device *dev,
 static ssize_t show_temp_crit(struct device *dev,
 			      struct device_attribute *dev_attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000));
 }
@@ -235,9 +233,9 @@ static ssize_t set_temp_crit(struct device *dev,
 			     struct device_attribute *dev_attr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int res;
 
@@ -258,9 +256,8 @@ static ssize_t show_temp_emergency(struct device *dev,
 				   struct device_attribute *dev_attr,
 				   char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000));
 }
@@ -269,9 +266,9 @@ static ssize_t set_temp_emergency(struct device *dev,
 				  struct device_attribute *dev_attr,
 				  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int res;
 
@@ -291,9 +288,8 @@ static ssize_t set_temp_emergency(struct device *dev,
 static ssize_t show_pwm(struct device *dev,
 			struct device_attribute *dev_attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120);
 }
@@ -302,9 +298,9 @@ static ssize_t set_pwm(struct device *dev,
 		       struct device_attribute *dev_attr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6639_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int res;
 
@@ -378,7 +374,7 @@ static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5);
 static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4);
 
 
-static struct attribute *max6639_attributes[] = {
+static struct attribute *max6639_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_fault.dev_attr.attr,
@@ -403,10 +399,7 @@ static struct attribute *max6639_attributes[] = {
 	&sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr,
 	NULL
 };
-
-static const struct attribute_group max6639_group = {
-	.attrs = max6639_attributes,
-};
+ATTRIBUTE_GROUPS(max6639);
 
 /*
  *  returns respective index in rpm_ranges table
@@ -424,9 +417,9 @@ static int rpm_range_to_reg(int range)
 	return 1; /* default: 4000 RPM */
 }
 
-static int max6639_init_client(struct i2c_client *client)
+static int max6639_init_client(struct i2c_client *client,
+			       struct max6639_data *data)
 {
-	struct max6639_data *data = i2c_get_clientdata(client);
 	struct max6639_platform_data *max6639_info =
 		dev_get_platdata(&client->dev);
 	int i;
@@ -545,50 +538,27 @@ static int max6639_detect(struct i2c_client *client,
 static int max6639_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct max6639_data *data;
+	struct device *hwmon_dev;
 	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct max6639_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct max6639_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the max6639 chip */
-	err = max6639_init_client(client);
+	err = max6639_init_client(client, data);
 	if (err < 0)
 		return err;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &max6639_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);
-		goto error_remove;
-	}
-
-	dev_info(&client->dev, "temperature sensor and fan control found\n");
-
-	return 0;
-
-error_remove:
-	sysfs_remove_group(&client->dev.kobj, &max6639_group);
-	return err;
-}
-
-static int max6639_remove(struct i2c_client *client)
-{
-	struct max6639_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &max6639_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   max6639_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -622,9 +592,7 @@ static const struct i2c_device_id max6639_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, max6639_id);
 
-static const struct dev_pm_ops max6639_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(max6639_suspend, max6639_resume)
-};
+static SIMPLE_DEV_PM_OPS(max6639_pm_ops, max6639_suspend, max6639_resume);
 
 static struct i2c_driver max6639_driver = {
 	.class = I2C_CLASS_HWMON,
@@ -633,7 +601,6 @@ static struct i2c_driver max6639_driver = {
 		   .pm = &max6639_pm_ops,
 		   },
 	.probe = max6639_probe,
-	.remove = max6639_remove,
 	.id_table = max6639_id,
 	.detect = max6639_detect,
 	.address_list = normal_i2c,
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 0cafc390db4d..162a520f4bd6 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -105,38 +105,13 @@ module_param(clock, int, S_IRUGO);
 
 #define DIV_FROM_REG(reg) (1 << (reg & 7))
 
-static int max6650_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int max6650_init_client(struct i2c_client *client);
-static int max6650_remove(struct i2c_client *client);
-static struct max6650_data *max6650_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id max6650_id[] = {
-	{ "max6650", 1 },
-	{ "max6651", 4 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, max6650_id);
-
-static struct i2c_driver max6650_driver = {
-	.driver = {
-		.name	= "max6650",
-	},
-	.probe		= max6650_probe,
-	.remove		= max6650_remove,
-	.id_table	= max6650_id,
-};
-
 /*
  * Client data (each client gets its own)
  */
 
 struct max6650_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	int nr_fans;
 	char valid; /* zero until following fields are valid */
@@ -151,6 +126,51 @@ struct max6650_data {
 	u8 alarm;
 };
 
+static const u8 tach_reg[] = {
+	MAX6650_REG_TACH0,
+	MAX6650_REG_TACH1,
+	MAX6650_REG_TACH2,
+	MAX6650_REG_TACH3,
+};
+
+static struct max6650_data *max6650_update_device(struct device *dev)
+{
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		data->speed = i2c_smbus_read_byte_data(client,
+						       MAX6650_REG_SPEED);
+		data->config = i2c_smbus_read_byte_data(client,
+							MAX6650_REG_CONFIG);
+		for (i = 0; i < data->nr_fans; i++) {
+			data->tach[i] = i2c_smbus_read_byte_data(client,
+								 tach_reg[i]);
+		}
+		data->count = i2c_smbus_read_byte_data(client,
+							MAX6650_REG_COUNT);
+		data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
+
+		/*
+		 * Alarms are cleared on read in case the condition that
+		 * caused the alarm is removed. Keep the value latched here
+		 * for providing the register through different alarm files.
+		 */
+		data->alarm |= i2c_smbus_read_byte_data(client,
+							MAX6650_REG_ALARM);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
 static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
 		       char *buf)
 {
@@ -235,8 +255,8 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
 			 const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6650_data *data = i2c_get_clientdata(client);
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int kscale, ktach;
 	unsigned long rpm;
 	int err;
@@ -304,8 +324,8 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6650_data *data = i2c_get_clientdata(client);
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long pwm;
 	int err;
 
@@ -350,8 +370,8 @@ static ssize_t get_enable(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_enable(struct device *dev, struct device_attribute *devattr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6650_data *data = i2c_get_clientdata(client);
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int max6650_modes[3] = {0, 3, 2};
 	unsigned long mode;
 	int err;
@@ -400,8 +420,8 @@ static ssize_t get_div(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6650_data *data = i2c_get_clientdata(client);
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long div;
 	int err;
 
@@ -446,7 +466,7 @@ static ssize_t get_alarm(struct device *dev, struct device_attribute *devattr,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct max6650_data *data = max6650_update_device(dev);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = data->client;
 	int alarm = 0;
 
 	if (data->alarm & attr->index) {
@@ -484,7 +504,8 @@ static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
 				    int n)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct max6650_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN);
 	struct device_attribute *devattr;
 
@@ -519,7 +540,7 @@ static struct attribute *max6650_attrs[] = {
 	NULL
 };
 
-static struct attribute_group max6650_attr_grp = {
+static const struct attribute_group max6650_group = {
 	.attrs = max6650_attrs,
 	.is_visible = max6650_attrs_visible,
 };
@@ -531,7 +552,7 @@ static struct attribute *max6651_attrs[] = {
 	NULL
 };
 
-static const struct attribute_group max6651_attr_grp = {
+static const struct attribute_group max6651_group = {
 	.attrs = max6651_attrs,
 };
 
@@ -539,74 +560,17 @@ static const struct attribute_group max6651_attr_grp = {
  * Real code
  */
 
-static int max6650_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct max6650_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct max6650_data),
-			    GFP_KERNEL);
-	if (!data) {
-		dev_err(&client->dev, "out of memory.\n");
-		return -ENOMEM;
-	}
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-	data->nr_fans = id->driver_data;
-
-	/*
-	 * Initialize the max6650 chip
-	 */
-	err = max6650_init_client(client);
-	if (err)
-		return err;
-
-	err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp);
-	if (err)
-		return err;
-	/* 3 additional fan inputs for the MAX6651 */
-	if (data->nr_fans == 4) {
-		err = sysfs_create_group(&client->dev.kobj, &max6651_attr_grp);
-		if (err)
-			goto err_remove;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (!IS_ERR(data->hwmon_dev))
-		return 0;
-
-	err = PTR_ERR(data->hwmon_dev);
-	dev_err(&client->dev, "error registering hwmon device.\n");
-	if (data->nr_fans == 4)
-		sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp);
-err_remove:
-	sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
-	return err;
-}
-
-static int max6650_remove(struct i2c_client *client)
+static int max6650_init_client(struct max6650_data *data,
+			       struct i2c_client *client)
 {
-	struct max6650_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	if (data->nr_fans == 4)
-		sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp);
-	sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp);
-	return 0;
-}
-
-static int max6650_init_client(struct i2c_client *client)
-{
-	struct max6650_data *data = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
 	int config;
 	int err = -EIO;
 
 	config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
 
 	if (config < 0) {
-		dev_err(&client->dev, "Error reading config, aborting.\n");
+		dev_err(dev, "Error reading config, aborting.\n");
 		return err;
 	}
 
@@ -620,11 +584,11 @@ static int max6650_init_client(struct i2c_client *client)
 		config |= MAX6650_CFG_V12;
 		break;
 	default:
-		dev_err(&client->dev, "illegal value for fan_voltage (%d)\n",
+		dev_err(dev, "illegal value for fan_voltage (%d)\n",
 			fan_voltage);
 	}
 
-	dev_info(&client->dev, "Fan voltage is set to %dV.\n",
+	dev_info(dev, "Fan voltage is set to %dV.\n",
 		 (config & MAX6650_CFG_V12) ? 12 : 5);
 
 	switch (prescaler) {
@@ -650,11 +614,10 @@ static int max6650_init_client(struct i2c_client *client)
 			 | MAX6650_CFG_PRESCALER_16;
 		break;
 	default:
-		dev_err(&client->dev, "illegal value for prescaler (%d)\n",
-			prescaler);
+		dev_err(dev, "illegal value for prescaler (%d)\n", prescaler);
 	}
 
-	dev_info(&client->dev, "Prescaler is set to %d.\n",
+	dev_info(dev, "Prescaler is set to %d.\n",
 		 1 << (config & MAX6650_CFG_PRESCALER_MASK));
 
 	/*
@@ -664,17 +627,17 @@ static int max6650_init_client(struct i2c_client *client)
 	 */
 
 	if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
-		dev_dbg(&client->dev, "Change mode to open loop, full off.\n");
+		dev_dbg(dev, "Change mode to open loop, full off.\n");
 		config = (config & ~MAX6650_CFG_MODE_MASK)
 			 | MAX6650_CFG_MODE_OPEN_LOOP;
 		if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) {
-			dev_err(&client->dev, "DAC write error, aborting.\n");
+			dev_err(dev, "DAC write error, aborting.\n");
 			return err;
 		}
 	}
 
 	if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) {
-		dev_err(&client->dev, "Config write error, aborting.\n");
+		dev_err(dev, "Config write error, aborting.\n");
 		return err;
 	}
 
@@ -684,51 +647,55 @@ static int max6650_init_client(struct i2c_client *client)
 	return 0;
 }
 
-static const u8 tach_reg[] = {
-	MAX6650_REG_TACH0,
-	MAX6650_REG_TACH1,
-	MAX6650_REG_TACH2,
-	MAX6650_REG_TACH3,
-};
-
-static struct max6650_data *max6650_update_device(struct device *dev)
+static int max6650_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
-	int i;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6650_data *data = i2c_get_clientdata(client);
-
-	mutex_lock(&data->update_lock);
+	struct device *dev = &client->dev;
+	struct max6650_data *data;
+	struct device *hwmon_dev;
+	int err;
 
-	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-		data->speed = i2c_smbus_read_byte_data(client,
-						       MAX6650_REG_SPEED);
-		data->config = i2c_smbus_read_byte_data(client,
-							MAX6650_REG_CONFIG);
-		for (i = 0; i < data->nr_fans; i++) {
-			data->tach[i] = i2c_smbus_read_byte_data(client,
-								 tach_reg[i]);
-		}
-		data->count = i2c_smbus_read_byte_data(client,
-							MAX6650_REG_COUNT);
-		data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
+	data = devm_kzalloc(dev, sizeof(struct max6650_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-		/*
-		 * Alarms are cleared on read in case the condition that
-		 * caused the alarm is removed. Keep the value latched here
-		 * for providing the register through different alarm files.
-		 */
-		data->alarm |= i2c_smbus_read_byte_data(client,
-							MAX6650_REG_ALARM);
+	data->client = client;
+	mutex_init(&data->update_lock);
+	data->nr_fans = id->driver_data;
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	/*
+	 * Initialize the max6650 chip
+	 */
+	err = max6650_init_client(data, client);
+	if (err)
+		return err;
 
-	mutex_unlock(&data->update_lock);
+	data->groups[0] = &max6650_group;
+	/* 3 additional fan inputs for the MAX6651 */
+	if (data->nr_fans == 4)
+		data->groups[1] = &max6651_group;
 
-	return data;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+							   client->name, data,
+							   data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
+static const struct i2c_device_id max6650_id[] = {
+	{ "max6650", 1 },
+	{ "max6651", 4 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max6650_id);
+
+static struct i2c_driver max6650_driver = {
+	.driver = {
+		.name	= "max6650",
+	},
+	.probe		= max6650_probe,
+	.id_table	= max6650_id,
+};
+
 module_i2c_driver(max6650_driver);
 
 MODULE_AUTHOR("Hans J. Koch");
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 330fe117e219..988181e4cfcd 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1225,7 +1225,7 @@ static int pc87360_probe(struct platform_device *pdev)
 	int i;
 	struct pc87360_data *data;
 	int err = 0;
-	const char *name = "pc87360";
+	const char *name;
 	int use_thermistors = 0;
 	struct device *dev = &pdev->dev;
 
@@ -1233,13 +1233,14 @@ static int pc87360_probe(struct platform_device *pdev)
 	if (!data)
 		return -ENOMEM;
 
-	data->fannr = 2;
-	data->innr = 0;
-	data->tempnr = 0;
-
 	switch (devid) {
+	default:
+		name = "pc87360";
+		data->fannr = 2;
+		break;
 	case 0xe8:
 		name = "pc87363";
+		data->fannr = 2;
 		break;
 	case 0xe4:
 		name = "pc87364";
@@ -1260,7 +1261,6 @@ static int pc87360_probe(struct platform_device *pdev)
 	}
 
 	data->name = name;
-	data->valid = 0;
 	mutex_init(&data->lock);
 	mutex_init(&data->update_lock);
 	platform_set_drvdata(pdev, data);
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index d9e1b7de78da..4ef5802df6d8 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -222,7 +222,7 @@ static int smm665_read_adc(struct smm665_data *data, int adc)
 	rv = i2c_smbus_read_word_swapped(client, 0);
 	if (rv < 0) {
 		dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
-		return -1;
+		return rv;
 	}
 	/*
 	 * Validate/verify readback adc channel (in bit 11..14).
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index df585808adb6..4068db4d9580 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1376,7 +1376,6 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	err = w83792d_detect_subclients(client);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 6384b268f590..ac3043122011 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -188,12 +188,8 @@ static int w83l785ts_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
-	/* Default values in case the first read fails (unlikely). */
-	data->temp[1] = data->temp[0] = 0;
-
 	/*
 	 * Initialize the W83L785TS chip
 	 * Nothing yet, assume it is already started.
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f5ed03164d86..75c3c0bd6ffa 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -936,7 +936,7 @@ config I2C_ACORN
 
 config I2C_ELEKTOR
 	tristate "Elektor ISA card"
-	depends on ISA && HAS_IOPORT && BROKEN_ON_SMP
+	depends on ISA && HAS_IOPORT_MAP && BROKEN_ON_SMP
 	select I2C_ALGOPCF
 	help
 	  This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 0282d4d42805..cc60bc6c1b46 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -638,6 +638,7 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
 	{ .compatible = "renesas,i2c-r8a7778", .data = (void *)I2C_RCAR_GEN1 },
 	{ .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
 	{ .compatible = "renesas,i2c-r8a7790", .data = (void *)I2C_RCAR_GEN2 },
+	{ .compatible = "renesas,i2c-r8a7791", .data = (void *)I2C_RCAR_GEN2 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 8e1939f564f4..aeddfc46c831 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -196,6 +196,53 @@ static struct cpuidle_state snb_cstates[] = {
 		.enter = NULL }
 };
 
+static struct cpuidle_state byt_cstates[] = {
+	{
+		.name = "C1-BYT",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
+		.exit_latency = 1,
+		.target_residency = 1,
+		.enter = &intel_idle },
+	{
+		.name = "C1E-BYT",
+		.desc = "MWAIT 0x01",
+		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+		.exit_latency = 15,
+		.target_residency = 30,
+		.enter = &intel_idle },
+	{
+		.name = "C6N-BYT",
+		.desc = "MWAIT 0x58",
+		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 40,
+		.target_residency = 275,
+		.enter = &intel_idle },
+	{
+		.name = "C6S-BYT",
+		.desc = "MWAIT 0x52",
+		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 140,
+		.target_residency = 560,
+		.enter = &intel_idle },
+	{
+		.name = "C7-BYT",
+		.desc = "MWAIT 0x60",
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 1200,
+		.target_residency = 1500,
+		.enter = &intel_idle },
+	{
+		.name = "C7S-BYT",
+		.desc = "MWAIT 0x64",
+		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 10000,
+		.target_residency = 20000,
+		.enter = &intel_idle },
+	{
+		.enter = NULL }
+};
+
 static struct cpuidle_state ivb_cstates[] = {
 	{
 		.name = "C1-IVB",
@@ -464,6 +511,11 @@ static const struct idle_cpu idle_cpu_snb = {
 	.disable_promotion_to_c1e = true,
 };
 
+static const struct idle_cpu idle_cpu_byt = {
+	.state_table = byt_cstates,
+	.disable_promotion_to_c1e = true,
+};
+
 static const struct idle_cpu idle_cpu_ivb = {
 	.state_table = ivb_cstates,
 	.disable_promotion_to_c1e = true,
@@ -494,6 +546,7 @@ static const struct x86_cpu_id intel_idle_ids[] = {
 	ICPU(0x2f, idle_cpu_nehalem),
 	ICPU(0x2a, idle_cpu_snb),
 	ICPU(0x2d, idle_cpu_snb),
+	ICPU(0x37, idle_cpu_byt),
 	ICPU(0x3a, idle_cpu_ivb),
 	ICPU(0x3e, idle_cpu_ivb),
 	ICPU(0x3c, idle_cpu_hsw),
@@ -584,7 +637,7 @@ static int __init intel_idle_cpuidle_driver_init(void)
 	drv->state_count = 1;
 
 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
-		int num_substates, mwait_hint, mwait_cstate, mwait_substate;
+		int num_substates, mwait_hint, mwait_cstate;
 
 		if (cpuidle_state_table[cstate].enter == NULL)
 			break;
@@ -597,14 +650,13 @@ static int __init intel_idle_cpuidle_driver_init(void)
 
 		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
 		mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint);
-		mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint);
 
-		/* does the state exist in CPUID.MWAIT? */
+		/* number of sub-states for this state in CPUID.MWAIT */
 		num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4))
 					& MWAIT_SUBSTATE_MASK;
 
-		/* if sub-state in table is not enumerated by CPUID */
-		if ((mwait_substate + 1) > num_substates)
+		/* if NO sub-states for this state in CPUID, skip it */
+		if (num_substates == 0)
 			continue;
 
 		if (((mwait_cstate + 1) > 2) &&
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index bfec313492b3..a7e68c81f89d 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -451,9 +451,9 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
 	.type = IIO_ACCEL,						\
 	.modified = 1,							\
 	.channel2 = IIO_MOD_##_axis,					\
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |		\
 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
 	.scan_index = AXIS_##_axis,					\
 	.scan_type = {							\
 		.sign = 's',						\
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 2209f28441e9..c02c4fb4cd1d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -197,6 +197,16 @@ config TWL6030_GPADC
 	  This driver can also be built as a module. If so, the module will be
 	  called twl6030-gpadc.
 
+config VF610_ADC
+	tristate "Freescale vf610 ADC driver"
+	depends on OF
+	help
+	  Say yes here to support for Vybrid board analog-to-digital converter.
+	  Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called vf610_adc.
+
 config VIPERBOARD_ADC
 	tristate "Viperboard ADC support"
 	depends on MFD_VIPERBOARD && USB
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ba9a10a24cd0..6d96b0fd2a25 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -21,4 +21,5 @@ obj-$(CONFIG_NAU7802) += nau7802.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
+obj-$(CONFIG_VF610_ADC) += vf610_adc.o
 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 360259266d4f..9cf3229a7272 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -8,17 +8,11 @@
   * based on linux/drivers/acron/char/pcf8583.c
   * Copyright (C) 2000 Russell King
   *
+  * Driver for max1363 and similar chips.
+  *
   * 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.
-  *
-  * max1363.c
-  *
-  * Partial support for max1363 and similar chips.
-  *
-  * Not currently implemented.
-  *
-  * - Control of internal reference.
   */
 
 #include <linux/interrupt.h>
@@ -1253,7 +1247,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 	},
 	[max11604] = {
 		.bits = 8,
-		.int_vref_mv = 4098,
+		.int_vref_mv = 4096,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
@@ -1313,7 +1307,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 	},
 	[max11610] = {
 		.bits = 10,
-		.int_vref_mv = 4098,
+		.int_vref_mv = 4096,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
@@ -1373,7 +1367,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
 	},
 	[max11616] = {
 		.bits = 12,
-		.int_vref_mv = 4098,
+		.int_vref_mv = 4096,
 		.mode_list = max1238_mode_list,
 		.num_modes = ARRAY_SIZE(max1238_mode_list),
 		.default_mode = s0to11,
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 31e786e3999b..a4db3026bec6 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -13,7 +13,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/module.h>
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 53a24ebb92c3..15282f148b3b 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -28,7 +28,6 @@
  * 02110-1301 USA
  *
  */
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
new file mode 100644
index 000000000000..37f542e8233c
--- /dev/null
+++ b/drivers/iio/adc/vf610_adc.c
@@ -0,0 +1,711 @@
+/*
+ * Freescale Vybrid vf610 ADC driver
+ *
+ * Copyright 2013 Freescale Semiconductor, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/driver.h>
+
+/* This will be the driver name the kernel reports */
+#define DRIVER_NAME "vf610-adc"
+
+/* Vybrid/IMX ADC registers */
+#define VF610_REG_ADC_HC0		0x00
+#define VF610_REG_ADC_HC1		0x04
+#define VF610_REG_ADC_HS		0x08
+#define VF610_REG_ADC_R0		0x0c
+#define VF610_REG_ADC_R1		0x10
+#define VF610_REG_ADC_CFG		0x14
+#define VF610_REG_ADC_GC		0x18
+#define VF610_REG_ADC_GS		0x1c
+#define VF610_REG_ADC_CV		0x20
+#define VF610_REG_ADC_OFS		0x24
+#define VF610_REG_ADC_CAL		0x28
+#define VF610_REG_ADC_PCTL		0x30
+
+/* Configuration register field define */
+#define VF610_ADC_MODE_BIT8		0x00
+#define VF610_ADC_MODE_BIT10		0x04
+#define VF610_ADC_MODE_BIT12		0x08
+#define VF610_ADC_MODE_MASK		0x0c
+#define VF610_ADC_BUSCLK2_SEL		0x01
+#define VF610_ADC_ALTCLK_SEL		0x02
+#define VF610_ADC_ADACK_SEL		0x03
+#define VF610_ADC_ADCCLK_MASK		0x03
+#define VF610_ADC_CLK_DIV2		0x20
+#define VF610_ADC_CLK_DIV4		0x40
+#define VF610_ADC_CLK_DIV8		0x60
+#define VF610_ADC_CLK_MASK		0x60
+#define VF610_ADC_ADLSMP_LONG		0x10
+#define VF610_ADC_ADSTS_MASK		0x300
+#define VF610_ADC_ADLPC_EN		0x80
+#define VF610_ADC_ADHSC_EN		0x400
+#define VF610_ADC_REFSEL_VALT		0x100
+#define VF610_ADC_REFSEL_VBG		0x1000
+#define VF610_ADC_ADTRG_HARD		0x2000
+#define VF610_ADC_AVGS_8		0x4000
+#define VF610_ADC_AVGS_16		0x8000
+#define VF610_ADC_AVGS_32		0xC000
+#define VF610_ADC_AVGS_MASK		0xC000
+#define VF610_ADC_OVWREN		0x10000
+
+/* General control register field define */
+#define VF610_ADC_ADACKEN		0x1
+#define VF610_ADC_DMAEN			0x2
+#define VF610_ADC_ACREN			0x4
+#define VF610_ADC_ACFGT			0x8
+#define VF610_ADC_ACFE			0x10
+#define VF610_ADC_AVGEN			0x20
+#define VF610_ADC_ADCON			0x40
+#define VF610_ADC_CAL			0x80
+
+/* Other field define */
+#define VF610_ADC_ADCHC(x)		((x) & 0xF)
+#define VF610_ADC_AIEN			(0x1 << 7)
+#define VF610_ADC_CONV_DISABLE		0x1F
+#define VF610_ADC_HS_COCO0		0x1
+#define VF610_ADC_CALF			0x2
+#define VF610_ADC_TIMEOUT		msecs_to_jiffies(100)
+
+enum clk_sel {
+	VF610_ADCIOC_BUSCLK_SET,
+	VF610_ADCIOC_ALTCLK_SET,
+	VF610_ADCIOC_ADACK_SET,
+};
+
+enum vol_ref {
+	VF610_ADCIOC_VR_VREF_SET,
+	VF610_ADCIOC_VR_VALT_SET,
+	VF610_ADCIOC_VR_VBG_SET,
+};
+
+enum average_sel {
+	VF610_ADC_SAMPLE_1,
+	VF610_ADC_SAMPLE_4,
+	VF610_ADC_SAMPLE_8,
+	VF610_ADC_SAMPLE_16,
+	VF610_ADC_SAMPLE_32,
+};
+
+struct vf610_adc_feature {
+	enum clk_sel	clk_sel;
+	enum vol_ref	vol_ref;
+
+	int	clk_div;
+	int     sample_rate;
+	int	res_mode;
+
+	bool	lpm;
+	bool	calibration;
+	bool	ovwren;
+};
+
+struct vf610_adc {
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *clk;
+
+	u32 vref_uv;
+	u32 value;
+	struct regulator *vref;
+	struct vf610_adc_feature adc_feature;
+
+	struct completion completion;
+};
+
+#define VF610_ADC_CHAN(_idx, _chan_type) {			\
+	.type = (_chan_type),					\
+	.indexed = 1,						\
+	.channel = (_idx),					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
+}
+
+static const struct iio_chan_spec vf610_adc_iio_channels[] = {
+	VF610_ADC_CHAN(0, IIO_VOLTAGE),
+	VF610_ADC_CHAN(1, IIO_VOLTAGE),
+	VF610_ADC_CHAN(2, IIO_VOLTAGE),
+	VF610_ADC_CHAN(3, IIO_VOLTAGE),
+	VF610_ADC_CHAN(4, IIO_VOLTAGE),
+	VF610_ADC_CHAN(5, IIO_VOLTAGE),
+	VF610_ADC_CHAN(6, IIO_VOLTAGE),
+	VF610_ADC_CHAN(7, IIO_VOLTAGE),
+	VF610_ADC_CHAN(8, IIO_VOLTAGE),
+	VF610_ADC_CHAN(9, IIO_VOLTAGE),
+	VF610_ADC_CHAN(10, IIO_VOLTAGE),
+	VF610_ADC_CHAN(11, IIO_VOLTAGE),
+	VF610_ADC_CHAN(12, IIO_VOLTAGE),
+	VF610_ADC_CHAN(13, IIO_VOLTAGE),
+	VF610_ADC_CHAN(14, IIO_VOLTAGE),
+	VF610_ADC_CHAN(15, IIO_VOLTAGE),
+	/* sentinel */
+};
+
+/*
+ * ADC sample frequency, unit is ADCK cycles.
+ * ADC clk source is ipg clock, which is the same as bus clock.
+ *
+ * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
+ * SFCAdder: fixed to 6 ADCK cycles
+ * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
+ * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
+ * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
+ *
+ * By default, enable 12 bit resolution mode, clock source
+ * set to ipg clock, So get below frequency group:
+ */
+static const u32 vf610_sample_freq_avail[5] =
+{1941176, 559332, 286957, 145374, 73171};
+
+static inline void vf610_adc_cfg_init(struct vf610_adc *info)
+{
+	/* set default Configuration for ADC controller */
+	info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET;
+	info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET;
+
+	info->adc_feature.calibration = true;
+	info->adc_feature.ovwren = true;
+
+	info->adc_feature.clk_div = 1;
+	info->adc_feature.res_mode = 12;
+	info->adc_feature.sample_rate = 1;
+	info->adc_feature.lpm = true;
+}
+
+static void vf610_adc_cfg_post_set(struct vf610_adc *info)
+{
+	struct vf610_adc_feature *adc_feature = &info->adc_feature;
+	int cfg_data = 0;
+	int gc_data = 0;
+
+	switch (adc_feature->clk_sel) {
+	case VF610_ADCIOC_ALTCLK_SET:
+		cfg_data |= VF610_ADC_ALTCLK_SEL;
+		break;
+	case VF610_ADCIOC_ADACK_SET:
+		cfg_data |= VF610_ADC_ADACK_SEL;
+		break;
+	default:
+		break;
+	}
+
+	/* low power set for calibration */
+	cfg_data |= VF610_ADC_ADLPC_EN;
+
+	/* enable high speed for calibration */
+	cfg_data |= VF610_ADC_ADHSC_EN;
+
+	/* voltage reference */
+	switch (adc_feature->vol_ref) {
+	case VF610_ADCIOC_VR_VREF_SET:
+		break;
+	case VF610_ADCIOC_VR_VALT_SET:
+		cfg_data |= VF610_ADC_REFSEL_VALT;
+		break;
+	case VF610_ADCIOC_VR_VBG_SET:
+		cfg_data |= VF610_ADC_REFSEL_VBG;
+		break;
+	default:
+		dev_err(info->dev, "error voltage reference\n");
+	}
+
+	/* data overwrite enable */
+	if (adc_feature->ovwren)
+		cfg_data |= VF610_ADC_OVWREN;
+
+	writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
+	writel(gc_data, info->regs + VF610_REG_ADC_GC);
+}
+
+static void vf610_adc_calibration(struct vf610_adc *info)
+{
+	int adc_gc, hc_cfg;
+	int timeout;
+
+	if (!info->adc_feature.calibration)
+		return;
+
+	/* enable calibration interrupt */
+	hc_cfg = VF610_ADC_AIEN | VF610_ADC_CONV_DISABLE;
+	writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
+
+	adc_gc = readl(info->regs + VF610_REG_ADC_GC);
+	writel(adc_gc | VF610_ADC_CAL, info->regs + VF610_REG_ADC_GC);
+
+	timeout = wait_for_completion_timeout
+			(&info->completion, VF610_ADC_TIMEOUT);
+	if (timeout == 0)
+		dev_err(info->dev, "Timeout for adc calibration\n");
+
+	adc_gc = readl(info->regs + VF610_REG_ADC_GS);
+	if (adc_gc & VF610_ADC_CALF)
+		dev_err(info->dev, "ADC calibration failed\n");
+
+	info->adc_feature.calibration = false;
+}
+
+static void vf610_adc_cfg_set(struct vf610_adc *info)
+{
+	struct vf610_adc_feature *adc_feature = &(info->adc_feature);
+	int cfg_data;
+
+	cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
+
+	/* low power configuration */
+	cfg_data &= ~VF610_ADC_ADLPC_EN;
+	if (adc_feature->lpm)
+		cfg_data |= VF610_ADC_ADLPC_EN;
+
+	/* disable high speed */
+	cfg_data &= ~VF610_ADC_ADHSC_EN;
+
+	writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
+}
+
+static void vf610_adc_sample_set(struct vf610_adc *info)
+{
+	struct vf610_adc_feature *adc_feature = &(info->adc_feature);
+	int cfg_data, gc_data;
+
+	cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
+	gc_data = readl(info->regs + VF610_REG_ADC_GC);
+
+	/* resolution mode */
+	cfg_data &= ~VF610_ADC_MODE_MASK;
+	switch (adc_feature->res_mode) {
+	case 8:
+		cfg_data |= VF610_ADC_MODE_BIT8;
+		break;
+	case 10:
+		cfg_data |= VF610_ADC_MODE_BIT10;
+		break;
+	case 12:
+		cfg_data |= VF610_ADC_MODE_BIT12;
+		break;
+	default:
+		dev_err(info->dev, "error resolution mode\n");
+		break;
+	}
+
+	/* clock select and clock divider */
+	cfg_data &= ~(VF610_ADC_CLK_MASK | VF610_ADC_ADCCLK_MASK);
+	switch (adc_feature->clk_div) {
+	case 1:
+		break;
+	case 2:
+		cfg_data |= VF610_ADC_CLK_DIV2;
+		break;
+	case 4:
+		cfg_data |= VF610_ADC_CLK_DIV4;
+		break;
+	case 8:
+		cfg_data |= VF610_ADC_CLK_DIV8;
+		break;
+	case 16:
+		switch (adc_feature->clk_sel) {
+		case VF610_ADCIOC_BUSCLK_SET:
+			cfg_data |= VF610_ADC_BUSCLK2_SEL | VF610_ADC_CLK_DIV8;
+			break;
+		default:
+			dev_err(info->dev, "error clk divider\n");
+			break;
+		}
+		break;
+	}
+
+	/* Use the short sample mode */
+	cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
+
+	/* update hardware average selection */
+	cfg_data &= ~VF610_ADC_AVGS_MASK;
+	gc_data &= ~VF610_ADC_AVGEN;
+	switch (adc_feature->sample_rate) {
+	case VF610_ADC_SAMPLE_1:
+		break;
+	case VF610_ADC_SAMPLE_4:
+		gc_data |= VF610_ADC_AVGEN;
+		break;
+	case VF610_ADC_SAMPLE_8:
+		gc_data |= VF610_ADC_AVGEN;
+		cfg_data |= VF610_ADC_AVGS_8;
+		break;
+	case VF610_ADC_SAMPLE_16:
+		gc_data |= VF610_ADC_AVGEN;
+		cfg_data |= VF610_ADC_AVGS_16;
+		break;
+	case VF610_ADC_SAMPLE_32:
+		gc_data |= VF610_ADC_AVGEN;
+		cfg_data |= VF610_ADC_AVGS_32;
+		break;
+	default:
+		dev_err(info->dev,
+			"error hardware sample average select\n");
+	}
+
+	writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
+	writel(gc_data, info->regs + VF610_REG_ADC_GC);
+}
+
+static void vf610_adc_hw_init(struct vf610_adc *info)
+{
+	/* CFG: Feature set */
+	vf610_adc_cfg_post_set(info);
+	vf610_adc_sample_set(info);
+
+	/* adc calibration */
+	vf610_adc_calibration(info);
+
+	/* CFG: power and speed set */
+	vf610_adc_cfg_set(info);
+}
+
+static int vf610_adc_read_data(struct vf610_adc *info)
+{
+	int result;
+
+	result = readl(info->regs + VF610_REG_ADC_R0);
+
+	switch (info->adc_feature.res_mode) {
+	case 8:
+		result &= 0xFF;
+		break;
+	case 10:
+		result &= 0x3FF;
+		break;
+	case 12:
+		result &= 0xFFF;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
+{
+	struct vf610_adc *info = (struct vf610_adc *)dev_id;
+	int coco;
+
+	coco = readl(info->regs + VF610_REG_ADC_HS);
+	if (coco & VF610_ADC_HS_COCO0) {
+		info->value = vf610_adc_read_data(info);
+		complete(&info->completion);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1941176, 559332, 286957, 145374, 73171");
+
+static struct attribute *vf610_attributes[] = {
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group vf610_attribute_group = {
+	.attrs = vf610_attributes,
+};
+
+static int vf610_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val,
+			int *val2,
+			long mask)
+{
+	struct vf610_adc *info = iio_priv(indio_dev);
+	unsigned int hc_cfg;
+	unsigned long ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+		reinit_completion(&info->completion);
+
+		hc_cfg = VF610_ADC_ADCHC(chan->channel);
+		hc_cfg |= VF610_ADC_AIEN;
+		writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
+		ret = wait_for_completion_interruptible_timeout
+				(&info->completion, VF610_ADC_TIMEOUT);
+		if (ret == 0) {
+			mutex_unlock(&indio_dev->mlock);
+			return -ETIMEDOUT;
+		}
+		if (ret < 0) {
+			mutex_unlock(&indio_dev->mlock);
+			return ret;
+		}
+
+		*val = info->value;
+		mutex_unlock(&indio_dev->mlock);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = info->vref_uv / 1000;
+		*val2 = info->adc_feature.res_mode;
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = vf610_sample_freq_avail[info->adc_feature.sample_rate];
+		*val2 = 0;
+		return IIO_VAL_INT;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int vf610_write_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int val,
+			int val2,
+			long mask)
+{
+	struct vf610_adc *info = iio_priv(indio_dev);
+	int i;
+
+	switch (mask) {
+		case IIO_CHAN_INFO_SAMP_FREQ:
+			for (i = 0;
+				i < ARRAY_SIZE(vf610_sample_freq_avail);
+				i++)
+				if (val == vf610_sample_freq_avail[i]) {
+					info->adc_feature.sample_rate = i;
+					vf610_adc_sample_set(info);
+					return 0;
+				}
+			break;
+
+		default:
+			break;
+	}
+
+	return -EINVAL;
+}
+
+static int vf610_adc_reg_access(struct iio_dev *indio_dev,
+			unsigned reg, unsigned writeval,
+			unsigned *readval)
+{
+	struct vf610_adc *info = iio_priv(indio_dev);
+
+	if ((readval == NULL) ||
+		(!(reg % 4) || (reg > VF610_REG_ADC_PCTL)))
+		return -EINVAL;
+
+	*readval = readl(info->regs + reg);
+
+	return 0;
+}
+
+static const struct iio_info vf610_adc_iio_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &vf610_read_raw,
+	.write_raw = &vf610_write_raw,
+	.debugfs_reg_access = &vf610_adc_reg_access,
+	.attrs = &vf610_attribute_group,
+};
+
+static const struct of_device_id vf610_adc_match[] = {
+	{ .compatible = "fsl,vf610-adc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vf610_adc_match);
+
+static int vf610_adc_probe(struct platform_device *pdev)
+{
+	struct vf610_adc *info;
+	struct iio_dev *indio_dev;
+	struct resource *mem;
+	int irq;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct vf610_adc));
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "Failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	info = iio_priv(indio_dev);
+	info->dev = &pdev->dev;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(info->regs))
+		return PTR_ERR(info->regs);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(info->dev, irq,
+				vf610_adc_isr, 0,
+				dev_name(&pdev->dev), info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq);
+		return ret;
+	}
+
+	info->clk = devm_clk_get(&pdev->dev, "adc");
+	if (IS_ERR(info->clk)) {
+		dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
+						PTR_ERR(info->clk));
+		ret = PTR_ERR(info->clk);
+		return ret;
+	}
+
+	info->vref = devm_regulator_get(&pdev->dev, "vref");
+	if (IS_ERR(info->vref))
+		return PTR_ERR(info->vref);
+
+	ret = regulator_enable(info->vref);
+	if (ret)
+		return ret;
+
+	info->vref_uv = regulator_get_voltage(info->vref);
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	init_completion(&info->completion);
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &vf610_adc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = vf610_adc_iio_channels;
+	indio_dev->num_channels = ARRAY_SIZE(vf610_adc_iio_channels);
+
+	ret = clk_prepare_enable(info->clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Could not prepare or enable the clock.\n");
+		goto error_adc_clk_enable;
+	}
+
+	vf610_adc_cfg_init(info);
+	vf610_adc_hw_init(info);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't register the device.\n");
+		goto error_iio_device_register;
+	}
+
+	return 0;
+
+
+error_iio_device_register:
+	clk_disable_unprepare(info->clk);
+error_adc_clk_enable:
+	regulator_disable(info->vref);
+
+	return ret;
+}
+
+static int vf610_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct vf610_adc *info = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	regulator_disable(info->vref);
+	clk_disable_unprepare(info->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int vf610_adc_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct vf610_adc *info = iio_priv(indio_dev);
+	int hc_cfg;
+
+	/* ADC controller enters to stop mode */
+	hc_cfg = readl(info->regs + VF610_REG_ADC_HC0);
+	hc_cfg |= VF610_ADC_CONV_DISABLE;
+	writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
+
+	clk_disable_unprepare(info->clk);
+	regulator_disable(info->vref);
+
+	return 0;
+}
+
+static int vf610_adc_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct vf610_adc *info = iio_priv(indio_dev);
+	int ret;
+
+	ret = regulator_enable(info->vref);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(info->clk);
+	if (ret)
+		return ret;
+
+	vf610_adc_hw_init(info);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops,
+			vf610_adc_suspend,
+			vf610_adc_resume);
+
+static struct platform_driver vf610_adc_driver = {
+	.probe          = vf610_adc_probe,
+	.remove         = vf610_adc_remove,
+	.driver         = {
+		.name   = DRIVER_NAME,
+		.owner  = THIS_MODULE,
+		.of_match_table = vf610_adc_match,
+		.pm     = &vf610_adc_pm_ops,
+	},
+};
+
+module_platform_driver(vf610_adc_driver);
+
+MODULE_AUTHOR("Fugang Duan <B38611@freescale.com>");
+MODULE_DESCRIPTION("Freescale VF610 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
index d0add8f9416b..9acf6b6d705b 100644
--- a/drivers/iio/adc/viperboard_adc.c
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -139,8 +139,6 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	platform_set_drvdata(pdev, indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c
index 2d9c6f8c06db..eb46e728aa2e 100644
--- a/drivers/iio/buffer_cb.c
+++ b/drivers/iio/buffer_cb.c
@@ -46,10 +46,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
 	struct iio_channel *chan;
 
 	cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);
-	if (cb_buff == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	if (cb_buff == NULL)
+		return ERR_PTR(-ENOMEM);
 
 	iio_buffer_init(&cb_buff->buffer);
 
@@ -91,7 +89,6 @@ error_release_channels:
 	iio_channel_release_all(cb_buff->channels);
 error_free_cb_buff:
 	kfree(cb_buff);
-error_ret:
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 7dcf83998e6f..dbefbdaf7cd1 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -38,29 +38,40 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 	if (state) {
 		if (sensor_hub_device_open(st->hsdev))
 			return -EIO;
-		state_val =
-		HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
-		report_val =
-		HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
-
+		state_val = hid_sensor_get_usage_index(st->hsdev,
+			st->power_state.report_id,
+			st->power_state.index,
+			HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM);
+		report_val = hid_sensor_get_usage_index(st->hsdev,
+			st->report_state.report_id,
+			st->report_state.index,
+			HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
 	} else {
 		sensor_hub_device_close(st->hsdev);
-		state_val =
-		HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
-		report_val =
-		HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+		state_val = hid_sensor_get_usage_index(st->hsdev,
+			st->power_state.report_id,
+			st->power_state.index,
+			HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM);
+		report_val = hid_sensor_get_usage_index(st->hsdev,
+			st->report_state.report_id,
+			st->report_state.index,
+			HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM);
 	}
-
 	st->data_ready = state;
-	state_val += st->power_state.logical_minimum;
-	report_val += st->report_state.logical_minimum;
-	sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
+
+	if (state_val >= 0) {
+		state_val += st->power_state.logical_minimum;
+		sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
 					st->power_state.index,
 					(s32)state_val);
+	}
 
-	sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
+	if (report_val >= 0) {
+		report_val += st->report_state.logical_minimum;
+		sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
 					st->report_state.index,
 					(s32)report_val);
+	}
 
 	return 0;
 }
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index d0505fd22ef4..fa2810032968 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -92,7 +92,7 @@ static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
 	ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);
 
 	mutex_unlock(&indio_dev->mlock);
-	return ret ? ret : len;
+	return len;
 }
 
 static int ad7303_get_vref(struct ad7303_state *st,
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index de76e6a34c1e..9a82a7255ebb 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -19,7 +19,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 7d9f5c31d2fc..43d14588448d 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -15,7 +15,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/delay.h>
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
index 463c4d9da79e..e116bd8dd0e4 100644
--- a/drivers/iio/humidity/Kconfig
+++ b/drivers/iio/humidity/Kconfig
@@ -12,4 +12,14 @@ config DHT11
 	  Other sensors should work as well as long as they speak the
 	  same protocol.
 
+config SI7005
+	tristate "SI7005 relative humidity and temperature sensor"
+	depends on I2C
+	help
+	  Say yes here to build support for the Silabs Si7005 relative
+	  humidity and temperature sensor.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called si7005.
+
 endmenu
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
index d5d36c0c95f9..e3f3d942e646 100644
--- a/drivers/iio/humidity/Makefile
+++ b/drivers/iio/humidity/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_DHT11) += dht11.o
+obj-$(CONFIG_SI7005) += si7005.o
diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c
new file mode 100644
index 000000000000..bdd586e6d955
--- /dev/null
+++ b/drivers/iio/humidity/si7005.c
@@ -0,0 +1,189 @@
+/*
+ * si7005.c - Support for Silabs Si7005 humidity and temperature sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * 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.
+ *
+ * (7-bit I2C slave address 0x40)
+ *
+ * TODO: heater, fast mode, processed mode (temp. / linearity compensation)
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define SI7005_STATUS 0x00
+#define SI7005_DATA 0x01 /* 16-bit, MSB */
+#define SI7005_CONFIG 0x03
+#define SI7005_ID 0x11
+
+#define SI7005_STATUS_NRDY BIT(0)
+#define SI7005_CONFIG_TEMP BIT(4)
+#define SI7005_CONFIG_START BIT(0)
+
+#define SI7005_ID_7005 0x50
+#define SI7005_ID_7015 0xf0
+
+struct si7005_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	u8 config;
+};
+
+static int si7005_read_measurement(struct si7005_data *data, bool temp)
+{
+	int tries = 50;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	ret = i2c_smbus_write_byte_data(data->client, SI7005_CONFIG,
+		data->config | SI7005_CONFIG_START |
+		(temp ? SI7005_CONFIG_TEMP : 0));
+	if (ret < 0)
+		goto done;
+
+	while (tries-- > 0) {
+		msleep(20);
+		ret = i2c_smbus_read_byte_data(data->client, SI7005_STATUS);
+		if (ret < 0)
+			goto done;
+		if (!(ret & SI7005_STATUS_NRDY))
+			break;
+	}
+	if (tries < 0) {
+		ret = -EIO;
+		goto done;
+	}
+
+	ret = i2c_smbus_read_word_swapped(data->client, SI7005_DATA);
+
+done:
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int si7005_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan, int *val,
+			    int *val2, long mask)
+{
+	struct si7005_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = si7005_read_measurement(data, chan->type == IIO_TEMP);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type == IIO_TEMP) {
+			*val = 7;
+			*val2 = 812500;
+		} else {
+			*val = 3;
+			*val2 = 906250;
+		}
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_OFFSET:
+		if (chan->type == IIO_TEMP)
+			*val = -50 * 32 * 4;
+		else
+			*val = -24 * 16 * 16;
+		return IIO_VAL_INT;
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_chan_spec si7005_channels[] = {
+	{
+		.type = IIO_HUMIDITYRELATIVE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+	}
+};
+
+static const struct iio_info si7005_info = {
+	.read_raw = si7005_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int si7005_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct si7005_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &si7005_info;
+
+	indio_dev->channels = si7005_channels;
+	indio_dev->num_channels = ARRAY_SIZE(si7005_channels);
+
+	ret = i2c_smbus_read_byte_data(client, SI7005_ID);
+	if (ret < 0)
+		return ret;
+	if (ret != SI7005_ID_7005 && ret != SI7005_ID_7015)
+		return -ENODEV;
+
+	ret = i2c_smbus_read_byte_data(client, SI7005_CONFIG);
+	if (ret < 0)
+		return ret;
+	data->config = ret;
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id si7005_id[] = {
+	{ "si7005", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, si7005_id);
+
+static struct i2c_driver si7005_driver = {
+	.driver = {
+		.name	= "si7005",
+		.owner	= THIS_MODULE,
+	},
+	.probe = si7005_probe,
+	.id_table = si7005_id,
+};
+module_i2c_driver(si7005_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("Silabs Si7005 humidity and temperature sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 663e88a1a3c1..2b0e45133e9d 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -25,6 +25,8 @@ config ADIS16480
 	  Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
 	  ADIS16485, ADIS16488 inertial sensors.
 
+source "drivers/iio/imu/inv_mpu6050/Kconfig"
+
 endmenu
 
 config IIO_ADIS_LIB
@@ -38,5 +40,3 @@ config IIO_ADIS_LIB_BUFFER
 	help
 	  A set of buffer helper functions for the Analog Devices ADIS* device
 	  family.
-
-source "drivers/iio/imu/inv_mpu6050/Kconfig"
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index 7c582f7ae34e..433583b6f800 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -281,7 +281,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
 	st->variant->set_freq(st, val);
 	mutex_unlock(&indio_dev->mlock);
 
-	return ret ? ret : len;
+	return len;
 }
 
 /* Power down the device */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index df7f1e1157ae..cb9f96b446a5 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -12,7 +12,6 @@
 */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
@@ -117,7 +116,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
 		return result;
 
 	if (en) {
-		/* Wait for output stablize */
+		/* Wait for output stabilize */
 		msleep(INV_MPU6050_TEMP_UP_TIME);
 		if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
 			/* switch internal clock to PLL */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index f38395529a44..0ab382be1e64 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -126,35 +126,35 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_REG_SAMPLE_RATE_DIV     0x19
 #define INV_MPU6050_REG_CONFIG              0x1A
 #define INV_MPU6050_REG_GYRO_CONFIG         0x1B
-#define INV_MPU6050_REG_ACCEL_CONFIG	    0x1C
+#define INV_MPU6050_REG_ACCEL_CONFIG        0x1C
 
 #define INV_MPU6050_REG_FIFO_EN             0x23
-#define INV_MPU6050_BIT_ACCEL_OUT                   0x08
-#define INV_MPU6050_BITS_GYRO_OUT                   0x70
+#define INV_MPU6050_BIT_ACCEL_OUT           0x08
+#define INV_MPU6050_BITS_GYRO_OUT           0x70
 
 #define INV_MPU6050_REG_INT_ENABLE          0x38
-#define INV_MPU6050_BIT_DATA_RDY_EN                 0x01
-#define INV_MPU6050_BIT_DMP_INT_EN                  0x02
+#define INV_MPU6050_BIT_DATA_RDY_EN         0x01
+#define INV_MPU6050_BIT_DMP_INT_EN          0x02
 
 #define INV_MPU6050_REG_RAW_ACCEL           0x3B
 #define INV_MPU6050_REG_TEMPERATURE         0x41
 #define INV_MPU6050_REG_RAW_GYRO            0x43
 
 #define INV_MPU6050_REG_USER_CTRL           0x6A
-#define INV_MPU6050_BIT_FIFO_RST                    0x04
-#define INV_MPU6050_BIT_DMP_RST                     0x08
-#define INV_MPU6050_BIT_I2C_MST_EN                  0x20
-#define INV_MPU6050_BIT_FIFO_EN                     0x40
-#define INV_MPU6050_BIT_DMP_EN                      0x80
+#define INV_MPU6050_BIT_FIFO_RST            0x04
+#define INV_MPU6050_BIT_DMP_RST             0x08
+#define INV_MPU6050_BIT_I2C_MST_EN          0x20
+#define INV_MPU6050_BIT_FIFO_EN             0x40
+#define INV_MPU6050_BIT_DMP_EN              0x80
 
 #define INV_MPU6050_REG_PWR_MGMT_1          0x6B
-#define INV_MPU6050_BIT_H_RESET                     0x80
-#define INV_MPU6050_BIT_SLEEP                       0x40
-#define INV_MPU6050_BIT_CLK_MASK                    0x7
+#define INV_MPU6050_BIT_H_RESET             0x80
+#define INV_MPU6050_BIT_SLEEP               0x40
+#define INV_MPU6050_BIT_CLK_MASK            0x7
 
 #define INV_MPU6050_REG_PWR_MGMT_2          0x6C
-#define INV_MPU6050_BIT_PWR_ACCL_STBY               0x38
-#define INV_MPU6050_BIT_PWR_GYRO_STBY               0x07
+#define INV_MPU6050_BIT_PWR_ACCL_STBY       0x38
+#define INV_MPU6050_BIT_PWR_GYRO_STBY       0x07
 
 #define INV_MPU6050_REG_FIFO_COUNT_H        0x72
 #define INV_MPU6050_REG_FIFO_R_W            0x74
@@ -180,10 +180,10 @@ struct inv_mpu6050_state {
 
 /* init parameters */
 #define INV_MPU6050_INIT_FIFO_RATE           50
-#define INV_MPU6050_TIME_STAMP_TOR                        5
-#define INV_MPU6050_MAX_FIFO_RATE                         1000
-#define INV_MPU6050_MIN_FIFO_RATE                         4
-#define INV_MPU6050_ONE_K_HZ                              1000
+#define INV_MPU6050_TIME_STAMP_TOR           5
+#define INV_MPU6050_MAX_FIFO_RATE            1000
+#define INV_MPU6050_MIN_FIFO_RATE            4
+#define INV_MPU6050_ONE_K_HZ                 1000
 
 /* scan element definition */
 enum inv_mpu6050_scan {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 429517117eff..0cd306a72a6e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -12,7 +12,6 @@
 */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index c67d83bdc8f0..e108f2a9d827 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -264,7 +264,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
 				     &indio_dev->dev,
 				     &buffer->scan_el_dev_attr_list);
 	if (ret)
-		goto error_ret;
+		return ret;
 	attrcount++;
 	ret = __iio_add_chan_devattr("type",
 				     chan,
@@ -275,7 +275,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
 				     &indio_dev->dev,
 				     &buffer->scan_el_dev_attr_list);
 	if (ret)
-		goto error_ret;
+		return ret;
 	attrcount++;
 	if (chan->type != IIO_TIMESTAMP)
 		ret = __iio_add_chan_devattr("en",
@@ -296,10 +296,9 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
 					     &indio_dev->dev,
 					     &buffer->scan_el_dev_attr_list);
 	if (ret)
-		goto error_ret;
+		return ret;
 	attrcount++;
 	ret = attrcount;
-error_ret:
 	return ret;
 }
 
@@ -553,13 +552,13 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
 		if (indio_dev->setup_ops->predisable) {
 			ret = indio_dev->setup_ops->predisable(indio_dev);
 			if (ret)
-				goto error_ret;
+				return ret;
 		}
 		indio_dev->currentmode = INDIO_DIRECT_MODE;
 		if (indio_dev->setup_ops->postdisable) {
 			ret = indio_dev->setup_ops->postdisable(indio_dev);
 			if (ret)
-				goto error_ret;
+				return ret;
 		}
 	}
 	/* Keep a copy of current setup to allow roll back */
@@ -613,7 +612,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
 			else {
 				kfree(compound_mask);
 				ret = -EINVAL;
-				goto error_ret;
+				return ret;
 			}
 		}
 	} else {
@@ -696,13 +695,10 @@ error_run_postdisable:
 	if (indio_dev->setup_ops->postdisable)
 		indio_dev->setup_ops->postdisable(indio_dev);
 error_remove_inserted:
-
 	if (insert_buffer)
 		iio_buffer_deactivate(insert_buffer);
 	indio_dev->active_scan_mask = old_mask;
 	kfree(compound_mask);
-error_ret:
-
 	return ret;
 }
 
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index acc911a836ca..ede16aec20fb 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -540,7 +540,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 			   enum iio_shared_by shared_by)
 {
 	int ret = 0;
-	char *name_format = NULL;
+	char *name = NULL;
 	char *full_postfix;
 	sysfs_attr_init(&dev_attr->attr);
 
@@ -558,7 +558,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 								    ->channel2],
 						 postfix);
 	} else {
-		if (chan->extend_name == NULL)
+		if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
 			full_postfix = kstrdup(postfix, GFP_KERNEL);
 		else
 			full_postfix = kasprintf(GFP_KERNEL,
@@ -572,16 +572,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 	if (chan->differential) { /* Differential can not have modifier */
 		switch (shared_by) {
 		case IIO_SHARED_BY_ALL:
-			name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+			name = kasprintf(GFP_KERNEL, "%s", full_postfix);
 			break;
 		case IIO_SHARED_BY_DIR:
-			name_format = kasprintf(GFP_KERNEL, "%s_%s",
+			name = kasprintf(GFP_KERNEL, "%s_%s",
 						iio_direction[chan->output],
 						full_postfix);
 			break;
 		case IIO_SHARED_BY_TYPE:
-			name_format
-				= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
+			name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
 					    iio_chan_type_name_spec[chan->type],
@@ -593,8 +592,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 				ret = -EINVAL;
 				goto error_free_full_postfix;
 			}
-			name_format
-				= kasprintf(GFP_KERNEL,
+			name = kasprintf(GFP_KERNEL,
 					    "%s_%s%d-%s%d_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
@@ -607,16 +605,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 	} else { /* Single ended */
 		switch (shared_by) {
 		case IIO_SHARED_BY_ALL:
-			name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+			name = kasprintf(GFP_KERNEL, "%s", full_postfix);
 			break;
 		case IIO_SHARED_BY_DIR:
-			name_format = kasprintf(GFP_KERNEL, "%s_%s",
+			name = kasprintf(GFP_KERNEL, "%s_%s",
 						iio_direction[chan->output],
 						full_postfix);
 			break;
 		case IIO_SHARED_BY_TYPE:
-			name_format
-				= kasprintf(GFP_KERNEL, "%s_%s_%s",
+			name = kasprintf(GFP_KERNEL, "%s_%s_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
 					    full_postfix);
@@ -624,33 +621,24 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 
 		case IIO_SEPARATE:
 			if (chan->indexed)
-				name_format
-					= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
+				name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
 						    iio_direction[chan->output],
 						    iio_chan_type_name_spec[chan->type],
 						    chan->channel,
 						    full_postfix);
 			else
-				name_format
-					= kasprintf(GFP_KERNEL, "%s_%s_%s",
+				name = kasprintf(GFP_KERNEL, "%s_%s_%s",
 						    iio_direction[chan->output],
 						    iio_chan_type_name_spec[chan->type],
 						    full_postfix);
 			break;
 		}
 	}
-	if (name_format == NULL) {
+	if (name == NULL) {
 		ret = -ENOMEM;
 		goto error_free_full_postfix;
 	}
-	dev_attr->attr.name = kasprintf(GFP_KERNEL,
-					name_format,
-					chan->channel,
-					chan->channel2);
-	if (dev_attr->attr.name == NULL) {
-		ret = -ENOMEM;
-		goto error_free_name_format;
-	}
+	dev_attr->attr.name = name;
 
 	if (readfunc) {
 		dev_attr->attr.mode |= S_IRUGO;
@@ -661,8 +649,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
 		dev_attr->attr.mode |= S_IWUSR;
 		dev_attr->store = writefunc;
 	}
-error_free_name_format:
-	kfree(name_format);
+
 error_free_full_postfix:
 	kfree(full_postfix);
 
@@ -692,10 +679,8 @@ int __iio_add_chan_devattr(const char *postfix,
 	struct iio_dev_attr *iio_attr, *t;
 
 	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
-	if (iio_attr == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	if (iio_attr == NULL)
+		return -ENOMEM;
 	ret = __iio_device_attr_init(&iio_attr->dev_attr,
 				     postfix, chan,
 				     readfunc, writefunc, shared_by);
@@ -720,7 +705,6 @@ error_device_attr_deinit:
 	__iio_device_attr_deinit(&iio_attr->dev_attr);
 error_iio_dev_attr_free:
 	kfree(iio_attr);
-error_ret:
 	return ret;
 }
 
@@ -1134,7 +1118,7 @@ int iio_device_register(struct iio_dev *indio_dev)
 	if (ret) {
 		dev_err(indio_dev->dev.parent,
 			"Failed to register debugfs interfaces\n");
-		goto error_ret;
+		return ret;
 	}
 	ret = iio_device_register_sysfs(indio_dev);
 	if (ret) {
@@ -1175,7 +1159,6 @@ error_free_sysfs:
 	iio_device_unregister_sysfs(indio_dev);
 error_unreg_debugfs:
 	iio_device_unregister_debugfs(indio_dev);
-error_ret:
 	return ret;
 }
 EXPORT_SYMBOL(iio_device_register);
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index c9c1419fe6e0..ea6e06b9c7d4 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -40,6 +40,7 @@ struct iio_event_interface {
 	struct list_head	dev_attr_list;
 	unsigned long		flags;
 	struct attribute_group	group;
+	struct mutex		read_lock;
 };
 
 /**
@@ -47,16 +48,17 @@ struct iio_event_interface {
  * @indio_dev:		IIO device structure
  * @ev_code:		What event
  * @timestamp:		When the event occurred
+ *
+ * Note: The caller must make sure that this function is not running
+ * concurrently for the same indio_dev more than once.
  **/
 int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 {
 	struct iio_event_interface *ev_int = indio_dev->event_interface;
 	struct iio_event_data ev;
-	unsigned long flags;
 	int copied;
 
 	/* Does anyone care? */
-	spin_lock_irqsave(&ev_int->wait.lock, flags);
 	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
 
 		ev.id = ev_code;
@@ -64,9 +66,8 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 
 		copied = kfifo_put(&ev_int->det_events, ev);
 		if (copied != 0)
-			wake_up_locked_poll(&ev_int->wait, POLLIN);
+			wake_up_poll(&ev_int->wait, POLLIN);
 	}
-	spin_unlock_irqrestore(&ev_int->wait.lock, flags);
 
 	return 0;
 }
@@ -87,10 +88,8 @@ static unsigned int iio_event_poll(struct file *filep,
 
 	poll_wait(filep, &ev_int->wait, wait);
 
-	spin_lock_irq(&ev_int->wait.lock);
 	if (!kfifo_is_empty(&ev_int->det_events))
 		events = POLLIN | POLLRDNORM;
-	spin_unlock_irq(&ev_int->wait.lock);
 
 	return events;
 }
@@ -111,31 +110,40 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
 	if (count < sizeof(struct iio_event_data))
 		return -EINVAL;
 
-	spin_lock_irq(&ev_int->wait.lock);
-	if (kfifo_is_empty(&ev_int->det_events)) {
-		if (filep->f_flags & O_NONBLOCK) {
-			ret = -EAGAIN;
-			goto error_unlock;
-		}
-		/* Blocking on device; waiting for something to be there */
-		ret = wait_event_interruptible_locked_irq(ev_int->wait,
+	do {
+		if (kfifo_is_empty(&ev_int->det_events)) {
+			if (filep->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			ret = wait_event_interruptible(ev_int->wait,
 					!kfifo_is_empty(&ev_int->det_events) ||
 					indio_dev->info == NULL);
-		if (ret)
-			goto error_unlock;
-		if (indio_dev->info == NULL) {
-			ret = -ENODEV;
-			goto error_unlock;
+			if (ret)
+				return ret;
+			if (indio_dev->info == NULL)
+				return -ENODEV;
 		}
-		/* Single access device so no one else can get the data */
-	}
 
-	ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
+		if (mutex_lock_interruptible(&ev_int->read_lock))
+			return -ERESTARTSYS;
+		ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
+		mutex_unlock(&ev_int->read_lock);
 
-error_unlock:
-	spin_unlock_irq(&ev_int->wait.lock);
+		if (ret)
+			return ret;
+
+		/*
+		 * If we couldn't read anything from the fifo (a different
+		 * thread might have been faster) we either return -EAGAIN if
+		 * the file descriptor is non-blocking, otherwise we go back to
+		 * sleep and wait for more data to arrive.
+		 */
+		if (copied == 0 && (filep->f_flags & O_NONBLOCK))
+			return -EAGAIN;
 
-	return ret ? ret : copied;
+	} while (copied == 0);
+
+	return copied;
 }
 
 static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
@@ -143,15 +151,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 	struct iio_dev *indio_dev = filep->private_data;
 	struct iio_event_interface *ev_int = indio_dev->event_interface;
 
-	spin_lock_irq(&ev_int->wait.lock);
-	__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
-	/*
-	 * In order to maintain a clean state for reopening,
-	 * clear out any awaiting events. The mask will prevent
-	 * any new __iio_push_event calls running.
-	 */
-	kfifo_reset_out(&ev_int->det_events);
-	spin_unlock_irq(&ev_int->wait.lock);
+	clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
 
 	iio_device_put(indio_dev);
 
@@ -174,22 +174,20 @@ int iio_event_getfd(struct iio_dev *indio_dev)
 	if (ev_int == NULL)
 		return -ENODEV;
 
-	spin_lock_irq(&ev_int->wait.lock);
-	if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
-		spin_unlock_irq(&ev_int->wait.lock);
+	if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags))
 		return -EBUSY;
-	}
-	spin_unlock_irq(&ev_int->wait.lock);
+
 	iio_device_get(indio_dev);
 
 	fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
 				indio_dev, O_RDONLY | O_CLOEXEC);
 	if (fd < 0) {
-		spin_lock_irq(&ev_int->wait.lock);
-		__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
-		spin_unlock_irq(&ev_int->wait.lock);
+		clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
 		iio_device_put(indio_dev);
+	} else {
+		kfifo_reset_out(&ev_int->det_events);
 	}
+
 	return fd;
 }
 
@@ -366,32 +364,31 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
 		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
 			IIO_SEPARATE, &chan->event_spec[i].mask_separate);
 		if (ret < 0)
-			goto error_ret;
+			return ret;
 		attrcount += ret;
 
 		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
 			IIO_SHARED_BY_TYPE,
 			&chan->event_spec[i].mask_shared_by_type);
 		if (ret < 0)
-			goto error_ret;
+			return ret;
 		attrcount += ret;
 
 		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
 			IIO_SHARED_BY_DIR,
 			&chan->event_spec[i].mask_shared_by_dir);
 		if (ret < 0)
-			goto error_ret;
+			return ret;
 		attrcount += ret;
 
 		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
 			IIO_SHARED_BY_ALL,
 			&chan->event_spec[i].mask_shared_by_all);
 		if (ret < 0)
-			goto error_ret;
+			return ret;
 		attrcount += ret;
 	}
 	ret = attrcount;
-error_ret:
 	return ret;
 }
 
@@ -425,6 +422,7 @@ static void iio_setup_ev_int(struct iio_event_interface *ev_int)
 {
 	INIT_KFIFO(ev_int->det_events);
 	init_waitqueue_head(&ev_int->wait);
+	mutex_init(&ev_int->read_lock);
 }
 
 static const char *iio_event_group_name = "events";
@@ -440,10 +438,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
 
 	indio_dev->event_interface =
 		kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
-	if (indio_dev->event_interface == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	if (indio_dev->event_interface == NULL)
+		return -ENOMEM;
 
 	INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
 
@@ -489,8 +485,6 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
 error_free_setup_event_lines:
 	iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
 	kfree(indio_dev->event_interface);
-error_ret:
-
 	return ret;
 }
 
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 766fab24b720..3383b025f62e 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -62,10 +62,9 @@ int iio_trigger_register(struct iio_trigger *trig_info)
 	int ret;
 
 	trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL);
-	if (trig_info->id < 0) {
-		ret = trig_info->id;
-		goto error_ret;
-	}
+	if (trig_info->id < 0)
+		return trig_info->id;
+
 	/* Set the name used for the sysfs directory etc */
 	dev_set_name(&trig_info->dev, "trigger%ld",
 		     (unsigned long) trig_info->id);
@@ -83,7 +82,6 @@ int iio_trigger_register(struct iio_trigger *trig_info)
 
 error_unregister_id:
 	ida_simple_remove(&iio_trigger_ida, trig_info->id);
-error_ret:
 	return ret;
 }
 EXPORT_SYMBOL(iio_trigger_register);
@@ -234,13 +232,12 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
 	if (trig->ops && trig->ops->set_trigger_state && no_other_users) {
 		ret = trig->ops->set_trigger_state(trig, false);
 		if (ret)
-			goto error_ret;
+			return ret;
 	}
 	iio_trigger_put_irq(trig, pf->irq);
 	free_irq(pf->irq, pf);
 	module_put(pf->indio_dev->info->driver_module);
 
-error_ret:
 	return ret;
 }
 
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index d12b2a0dbfbc..c89740d4748f 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -73,6 +73,20 @@ config HID_SENSOR_ALS
 	  Say yes here to build support for the HID SENSOR
 	  Ambient light sensor.
 
+config HID_SENSOR_PROX
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
+	tristate "HID PROX"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Proximity sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hid-sensor-prox.
+
 config SENSORS_LM3533
 	tristate "LM3533 ambient light sensor"
 	depends on MFD_LM3533
@@ -90,6 +104,18 @@ config SENSORS_LM3533
 	  changes. The ALS-control output values can be set per zone for the
 	  three current output channels.
 
+config LTR501
+	tristate "LTR-501ALS-01 light sensor"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	 If you say yes here you get support for the Lite-On LTR-501ALS-01
+	 ambient light and proximity sensor.
+
+	 This driver can also be built as a module.  If so, the module
+         will be called ltr501.
+
 config TCS3472
 	tristate "TAOS TCS3472 color light-to-digital converter"
 	depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 60e35ac07ff0..3eb36e5151fa 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -9,7 +9,9 @@ obj-$(CONFIG_CM32181)		+= cm32181.o
 obj-$(CONFIG_CM36651)		+= cm36651.o
 obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
 obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
+obj-$(CONFIG_HID_SENSOR_PROX)	+= hid-sensor-prox.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
+obj-$(CONFIG_LTR501)		+= ltr501.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
 obj-$(CONFIG_TCS3472)		+= tcs3472.o
 obj-$(CONFIG_TSL4531)		+= tsl4531.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index f3068477b466..09ad5f1ce539 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
@@ -120,7 +119,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adjd_s311_data *data = iio_priv(indio_dev);
 	s64 time_ns = iio_get_time_ns();
-	int len = 0;
 	int i, j = 0;
 
 	int ret = adjd_s311_req_data(indio_dev);
@@ -135,7 +133,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 			goto done;
 
 		data->buffer[j++] = ret & ADJD_S311_DATA_MASK;
-		len += 2;
 	}
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns);
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
new file mode 100644
index 000000000000..1894ab196f97
--- /dev/null
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -0,0 +1,375 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+#define CHANNEL_SCAN_INDEX_PRESENCE 0
+
+struct prox_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_common common_attributes;
+	struct hid_sensor_hub_attribute_info prox_attr;
+	u32 human_presence;
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec prox_channels[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.modified = 1,
+		.channel2 = IIO_NO_MOD,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
+		.scan_index = CHANNEL_SCAN_INDEX_PRESENCE,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void prox_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+					int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int prox_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct prox_state *prox_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->scan_index) {
+		case  CHANNEL_SCAN_INDEX_PRESENCE:
+			report_id = prox_state->prox_attr.report_id;
+			address =
+			HID_USAGE_SENSOR_HUMAN_PRESENCE;
+			break;
+		default:
+			report_id = -1;
+			break;
+		}
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				prox_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_PROX, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = prox_state->prox_attr.units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+				prox_state->prox_attr.unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+				&prox_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+				&prox_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int prox_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct prox_state *prox_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&prox_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&prox_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct iio_info prox_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &prox_read_raw,
+	.write_raw = &prox_write_raw,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+					int len)
+{
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	iio_push_to_buffers(indio_dev, data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct prox_state *prox_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "prox_proc_event [%d]\n",
+				prox_state->common_attributes.data_ready);
+	if (prox_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				&prox_state->human_presence,
+				sizeof(prox_state->human_presence));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct prox_state *prox_state = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_HUMAN_PRESENCE:
+		prox_state->human_presence = *(u32 *)raw_data;
+		ret = 0;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int prox_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct prox_state *st)
+{
+	int ret;
+
+	ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
+			usage_id,
+			HID_USAGE_SENSOR_HUMAN_PRESENCE,
+			&st->prox_attr);
+	if (ret < 0)
+		return ret;
+	prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE,
+					st->prox_attr.size);
+
+	dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index,
+			st->prox_attr.report_id);
+
+	/* Set Sensitivity field ids, when there is no individual modifier */
+	if (st->common_attributes.sensitivity.index < 0) {
+		sensor_hub_input_get_attribute_info(hsdev,
+			HID_FEATURE_REPORT, usage_id,
+			HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
+			HID_USAGE_SENSOR_DATA_PRESENCE,
+			&st->common_attributes.sensitivity);
+		dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n",
+			st->common_attributes.sensitivity.index,
+			st->common_attributes.sensitivity.report_id);
+	}
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int hid_prox_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static const char *name = "prox";
+	struct iio_dev *indio_dev;
+	struct prox_state *prox_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+				sizeof(struct prox_state));
+	if (!indio_dev)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, indio_dev);
+
+	prox_state = iio_priv(indio_dev);
+	prox_state->common_attributes.hsdev = hsdev;
+	prox_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_PROX,
+					&prox_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		return ret;
+	}
+
+	channels = kmemdup(prox_channels, sizeof(prox_channels), GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		return -ENOMEM;
+	}
+
+	ret = prox_parse_report(pdev, hsdev, channels,
+				HID_USAGE_SENSOR_PROX, prox_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels =
+				ARRAY_SIZE(prox_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &prox_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	prox_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+				&prox_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	prox_state->callbacks.send_event = prox_proc_event;
+	prox_state->callbacks.capture_sample = prox_capture_sample;
+	prox_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_PROX,
+					&prox_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(&prox_state->common_attributes);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int hid_prox_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct prox_state *prox_state = iio_priv(indio_dev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PROX);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(&prox_state->common_attributes);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+
+	return 0;
+}
+
+static struct platform_device_id hid_prox_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200011",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_prox_ids);
+
+static struct platform_driver hid_prox_platform_driver = {
+	.id_table = hid_prox_ids,
+	.driver = {
+		.name	= KBUILD_MODNAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_prox_probe,
+	.remove		= hid_prox_remove,
+};
+module_platform_driver(hid_prox_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Proximity");
+MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
new file mode 100644
index 000000000000..62b7072af4de
--- /dev/null
+++ b/drivers/iio/light/ltr501.c
@@ -0,0 +1,445 @@
+/*
+ * ltr501.c - Support for Lite-On LTR501 ambient light and proximity sensor
+ *
+ * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * 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.
+ *
+ * 7-bit I2C slave address 0x23
+ *
+ * TODO: interrupt, threshold, measurement rate, IR LED characteristics
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define LTR501_DRV_NAME "ltr501"
+
+#define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */
+#define LTR501_PS_CONTR 0x81 /* PS operation mode */
+#define LTR501_PART_ID 0x86
+#define LTR501_MANUFAC_ID 0x87
+#define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */
+#define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */
+#define LTR501_ALS_PS_STATUS 0x8c
+#define LTR501_PS_DATA 0x8d /* 16-bit, little endian */
+
+#define LTR501_ALS_CONTR_SW_RESET BIT(2)
+#define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2))
+#define LTR501_CONTR_PS_GAIN_SHIFT 2
+#define LTR501_CONTR_ALS_GAIN_MASK BIT(3)
+#define LTR501_CONTR_ACTIVE BIT(1)
+
+#define LTR501_STATUS_ALS_RDY BIT(2)
+#define LTR501_STATUS_PS_RDY BIT(0)
+
+#define LTR501_PS_DATA_MASK 0x7ff
+
+struct ltr501_data {
+	struct i2c_client *client;
+	struct mutex lock_als, lock_ps;
+	u8 als_contr, ps_contr;
+};
+
+static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
+{
+	int tries = 100;
+	int ret;
+
+	while (tries--) {
+		ret = i2c_smbus_read_byte_data(data->client,
+			LTR501_ALS_PS_STATUS);
+		if (ret < 0)
+			return ret;
+		if ((ret & drdy_mask) == drdy_mask)
+			return 0;
+		msleep(25);
+	}
+
+	dev_err(&data->client->dev, "ltr501_drdy() failed, data not ready\n");
+	return -EIO;
+}
+
+static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2])
+{
+	int ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY);
+	if (ret < 0)
+		return ret;
+	/* always read both ALS channels in given order */
+	return i2c_smbus_read_i2c_block_data(data->client,
+		LTR501_ALS_DATA1, 2 * sizeof(__le16), (u8 *) buf);
+}
+
+static int ltr501_read_ps(struct ltr501_data *data)
+{
+	int ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY);
+	if (ret < 0)
+		return ret;
+	return i2c_smbus_read_word_data(data->client, LTR501_PS_DATA);
+}
+
+#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared) { \
+	.type = IIO_INTENSITY, \
+	.modified = 1, \
+	.address = (_addr), \
+	.channel2 = (_mod), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = (_shared), \
+	.scan_index = (_idx), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	} \
+}
+
+static const struct iio_chan_spec ltr501_channels[] = {
+	LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0),
+	LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR,
+		BIT(IIO_CHAN_INFO_SCALE)),
+	{
+		.type = IIO_PROXIMITY,
+		.address = LTR501_PS_DATA,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 2,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 11,
+			.storagebits = 16,
+			.endianness = IIO_CPU,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const int ltr501_ps_gain[4][2] = {
+	{1, 0}, {0, 250000}, {0, 125000}, {0, 62500}
+};
+
+static int ltr501_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct ltr501_data *data = iio_priv(indio_dev);
+	__le16 buf[2];
+	int ret, i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (iio_buffer_enabled(indio_dev))
+			return -EBUSY;
+
+		switch (chan->type) {
+		case IIO_INTENSITY:
+			mutex_lock(&data->lock_als);
+			ret = ltr501_read_als(data, buf);
+			mutex_unlock(&data->lock_als);
+			if (ret < 0)
+				return ret;
+			*val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ?
+				buf[0] : buf[1]);
+			return IIO_VAL_INT;
+		case IIO_PROXIMITY:
+			mutex_lock(&data->lock_ps);
+			ret = ltr501_read_ps(data);
+			mutex_unlock(&data->lock_ps);
+			if (ret < 0)
+				return ret;
+			*val = ret & LTR501_PS_DATA_MASK;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_INTENSITY:
+			if (data->als_contr & LTR501_CONTR_ALS_GAIN_MASK) {
+				*val = 0;
+				*val2 = 5000;
+				return IIO_VAL_INT_PLUS_MICRO;
+			} else {
+				*val = 1;
+				*val2 = 0;
+				return IIO_VAL_INT;
+			}
+		case IIO_PROXIMITY:
+			i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >>
+				LTR501_CONTR_PS_GAIN_SHIFT;
+			*val = ltr501_ps_gain[i][0];
+			*val2 = ltr501_ps_gain[i][1];
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
+	}
+	return -EINVAL;
+}
+
+static int ltr501_get_ps_gain_index(int val, int val2)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ltr501_ps_gain); i++)
+		if (val == ltr501_ps_gain[i][0] && val2 == ltr501_ps_gain[i][1])
+			return i;
+
+	return -1;
+}
+
+static int ltr501_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	struct ltr501_data *data = iio_priv(indio_dev);
+	int i;
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_INTENSITY:
+			if (val == 0 && val2 == 5000)
+				data->als_contr |= LTR501_CONTR_ALS_GAIN_MASK;
+			else if (val == 1 && val2 == 0)
+				data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK;
+			else
+				return -EINVAL;
+			return i2c_smbus_write_byte_data(data->client,
+				LTR501_ALS_CONTR, data->als_contr);
+		case IIO_PROXIMITY:
+			i = ltr501_get_ps_gain_index(val, val2);
+			if (i < 0)
+				return -EINVAL;
+			data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK;
+			data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT;
+			return i2c_smbus_write_byte_data(data->client,
+				LTR501_PS_CONTR, data->ps_contr);
+		default:
+			return -EINVAL;
+		}
+	}
+	return -EINVAL;
+}
+
+static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625");
+static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005");
+
+static struct attribute *ltr501_attributes[] = {
+	&iio_const_attr_in_proximity_scale_available.dev_attr.attr,
+	&iio_const_attr_in_intensity_scale_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ltr501_attribute_group = {
+	.attrs = ltr501_attributes,
+};
+
+static const struct iio_info ltr501_info = {
+	.read_raw = ltr501_read_raw,
+	.write_raw = ltr501_write_raw,
+	.attrs = &ltr501_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int ltr501_write_contr(struct i2c_client *client, u8 als_val, u8 ps_val)
+{
+	int ret = i2c_smbus_write_byte_data(client, LTR501_ALS_CONTR, als_val);
+	if (ret < 0)
+		return ret;
+
+	return i2c_smbus_write_byte_data(client, LTR501_PS_CONTR, ps_val);
+}
+
+static irqreturn_t ltr501_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ltr501_data *data = iio_priv(indio_dev);
+	u16 buf[8];
+	__le16 als_buf[2];
+	u8 mask = 0;
+	int j = 0;
+	int ret;
+
+	memset(buf, 0, sizeof(buf));
+
+	/* figure out which data needs to be ready */
+	if (test_bit(0, indio_dev->active_scan_mask) ||
+		test_bit(1, indio_dev->active_scan_mask))
+		mask |= LTR501_STATUS_ALS_RDY;
+	if (test_bit(2, indio_dev->active_scan_mask))
+		mask |= LTR501_STATUS_PS_RDY;
+
+	ret = ltr501_drdy(data, mask);
+	if (ret < 0)
+		goto done;
+
+	if (mask & LTR501_STATUS_ALS_RDY) {
+		ret = i2c_smbus_read_i2c_block_data(data->client,
+			LTR501_ALS_DATA1, sizeof(als_buf), (u8 *) als_buf);
+		if (ret < 0)
+			return ret;
+		if (test_bit(0, indio_dev->active_scan_mask))
+			buf[j++] = le16_to_cpu(als_buf[1]);
+		if (test_bit(1, indio_dev->active_scan_mask))
+			buf[j++] = le16_to_cpu(als_buf[0]);
+	}
+
+	if (mask & LTR501_STATUS_PS_RDY) {
+		ret = i2c_smbus_read_word_data(data->client, LTR501_PS_DATA);
+		if (ret < 0)
+			goto done;
+		buf[j++] = ret & LTR501_PS_DATA_MASK;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int ltr501_init(struct ltr501_data *data)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, LTR501_ALS_CONTR);
+	if (ret < 0)
+		return ret;
+	data->als_contr = ret | LTR501_CONTR_ACTIVE;
+
+	ret = i2c_smbus_read_byte_data(data->client, LTR501_PS_CONTR);
+	if (ret < 0)
+		return ret;
+	data->ps_contr = ret | LTR501_CONTR_ACTIVE;
+
+	return ltr501_write_contr(data->client, data->als_contr,
+		data->ps_contr);
+}
+
+static int ltr501_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct ltr501_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	mutex_init(&data->lock_als);
+	mutex_init(&data->lock_ps);
+
+	ret = i2c_smbus_read_byte_data(data->client, LTR501_PART_ID);
+	if (ret < 0)
+		return ret;
+	if ((ret >> 4) != 0x8)
+		return -ENODEV;
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ltr501_info;
+	indio_dev->channels = ltr501_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ltr501_channels);
+	indio_dev->name = LTR501_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = ltr501_init(data);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		ltr501_trigger_handler, NULL);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unreg_buffer;
+
+	return 0;
+
+error_unreg_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int ltr501_powerdown(struct ltr501_data *data)
+{
+	return ltr501_write_contr(data->client,
+		data->als_contr & ~LTR501_CONTR_ACTIVE,
+		data->ps_contr & ~LTR501_CONTR_ACTIVE);
+}
+
+static int ltr501_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	ltr501_powerdown(iio_priv(indio_dev));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ltr501_suspend(struct device *dev)
+{
+	struct ltr501_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return ltr501_powerdown(data);
+}
+
+static int ltr501_resume(struct device *dev)
+{
+	struct ltr501_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+
+	return ltr501_write_contr(data->client, data->als_contr,
+		data->ps_contr);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
+
+static const struct i2c_device_id ltr501_id[] = {
+	{ "ltr501", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ltr501_id);
+
+static struct i2c_driver ltr501_driver = {
+	.driver = {
+		.name   = LTR501_DRV_NAME,
+		.pm	= &ltr501_pm_ops,
+		.owner  = THIS_MODULE,
+	},
+	.probe  = ltr501_probe,
+	.remove	= ltr501_remove,
+	.id_table = ltr501_id,
+};
+
+module_i2c_driver(ltr501_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("Lite-On LTR501 ambient light and proximity sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 887fecf1f9bb..fe063a0a21cd 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -179,7 +179,6 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct tcs3472_data *data = iio_priv(indio_dev);
-	int len = 0;
 	int i, j = 0;
 
 	int ret = tcs3472_req_data(data);
@@ -194,7 +193,6 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
 			goto done;
 
 		data->buffer[j++] = ret;
-		len += 2;
 	}
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 05423543f89d..74866d1efd1b 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -513,6 +513,7 @@ static int ak8975_probe(struct i2c_client *client,
 	indio_dev->channels = ak8975_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
 	indio_dev->info = &ak8975_info;
+	indio_dev->name = id->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	err = iio_device_register(indio_dev);
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
index f66955fb3509..02e4f9765889 100644
--- a/drivers/iio/magnetometer/mag3110.c
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -183,8 +183,17 @@ static int mag3110_read_raw(struct iio_dev *indio_dev,
 			return -EINVAL;
 		}
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = 1000;
+		switch (chan->type) {
+		case IIO_MAGN:
+			*val = 0;
+			*val2 = 1000;
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			*val = 1000;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
@@ -270,7 +279,8 @@ static const struct iio_chan_spec mag3110_channels[] = {
 	MAG3110_CHANNEL(Z, 2),
 	{
 		.type = IIO_TEMP,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = 3,
 		.scan_type = {
 			.sign = 's',
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index a8b9cae5c173..d88ff17fedb2 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -5,6 +5,20 @@
 
 menu "Pressure sensors"
 
+config HID_SENSOR_PRESS
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
+	tristate "HID PRESS"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Pressure driver
+
+          To compile this driver as a module, choose M here: the module
+          will be called hid-sensor-press.
+
 config MPL3115
 	tristate "Freescale MPL3115A2 pressure sensor driver"
 	depends on I2C
@@ -26,7 +40,7 @@ config IIO_ST_PRESS
 	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
 	help
 	  Say yes here to build support for STMicroelectronics pressure
-	  sensors: LPS001WP, LPS331AP.
+	  sensors: LPS001WP, LPS25H, LPS331AP.
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index 42bb9fcf5436..4a57bf65b04b 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -3,6 +3,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
 obj-$(CONFIG_MPL3115) += mpl3115.o
 obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
new file mode 100644
index 000000000000..e0e6409aa94e
--- /dev/null
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -0,0 +1,376 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+#define CHANNEL_SCAN_INDEX_PRESSURE 0
+
+struct press_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_common common_attributes;
+	struct hid_sensor_hub_attribute_info press_attr;
+	u32 press_data;
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec press_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.modified = 1,
+		.channel2 = IIO_NO_MOD,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
+		.scan_index = CHANNEL_SCAN_INDEX_PRESSURE,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void press_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+					int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int press_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct press_state *press_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->scan_index) {
+		case  CHANNEL_SCAN_INDEX_PRESSURE:
+			report_id = press_state->press_attr.report_id;
+			address =
+			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
+			break;
+		default:
+			report_id = -1;
+			break;
+		}
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				press_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_PRESSURE, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = press_state->press_attr.units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+				press_state->press_attr.unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+				&press_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+				&press_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int press_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct press_state *press_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&press_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&press_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct iio_info press_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &press_read_raw,
+	.write_raw = &press_write_raw,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+					int len)
+{
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	iio_push_to_buffers(indio_dev, data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int press_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct press_state *press_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "press_proc_event [%d]\n",
+				press_state->common_attributes.data_ready);
+	if (press_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				&press_state->press_data,
+				sizeof(press_state->press_data));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct press_state *press_state = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE:
+		press_state->press_data = *(u32 *)raw_data;
+		ret = 0;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int press_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct press_state *st)
+{
+	int ret;
+
+	ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
+			usage_id,
+			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE,
+			&st->press_attr);
+	if (ret < 0)
+		return ret;
+	press_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESSURE,
+					st->press_attr.size);
+
+	dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index,
+			st->press_attr.report_id);
+
+	/* Set Sensitivity field ids, when there is no individual modifier */
+	if (st->common_attributes.sensitivity.index < 0) {
+		sensor_hub_input_get_attribute_info(hsdev,
+			HID_FEATURE_REPORT, usage_id,
+			HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
+			HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE,
+			&st->common_attributes.sensitivity);
+		dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n",
+			st->common_attributes.sensitivity.index,
+			st->common_attributes.sensitivity.report_id);
+	}
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int hid_press_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static const char *name = "press";
+	struct iio_dev *indio_dev;
+	struct press_state *press_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+				sizeof(struct press_state));
+	if (!indio_dev)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, indio_dev);
+
+	press_state = iio_priv(indio_dev);
+	press_state->common_attributes.hsdev = hsdev;
+	press_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev,
+					HID_USAGE_SENSOR_PRESSURE,
+					&press_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		return ret;
+	}
+
+	channels = kmemdup(press_channels, sizeof(press_channels), GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		return -ENOMEM;
+	}
+
+	ret = press_parse_report(pdev, hsdev, channels,
+				HID_USAGE_SENSOR_PRESSURE, press_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels =
+				ARRAY_SIZE(press_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &press_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	press_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+				&press_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	press_state->callbacks.send_event = press_proc_event;
+	press_state->callbacks.capture_sample = press_capture_sample;
+	press_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_PRESSURE,
+					&press_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(&press_state->common_attributes);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int hid_press_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct press_state *press_state = iio_priv(indio_dev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(&press_state->common_attributes);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+
+	return 0;
+}
+
+static struct platform_device_id hid_press_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200031",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_press_ids);
+
+static struct platform_driver hid_press_platform_driver = {
+	.id_table = hid_press_ids,
+	.driver = {
+		.name	= KBUILD_MODNAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_press_probe,
+	.remove		= hid_press_remove,
+};
+module_platform_driver(hid_press_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Pressure");
+MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
index ac8c8ab723e5..ba6d0c520e63 100644
--- a/drivers/iio/pressure/mpl3115.c
+++ b/drivers/iio/pressure/mpl3115.c
@@ -77,7 +77,7 @@ static int mpl3115_read_raw(struct iio_dev *indio_dev,
 			    int *val, int *val2, long mask)
 {
 	struct mpl3115_data *data = iio_priv(indio_dev);
-	s32 tmp = 0;
+	__be32 tmp = 0;
 	int ret;
 
 	switch (mask) {
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index 049c21acf1f0..242943c0c4e4 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -15,6 +15,7 @@
 #include <linux/iio/common/st_sensors.h>
 
 #define LPS001WP_PRESS_DEV_NAME		"lps001wp"
+#define LPS25H_PRESS_DEV_NAME		"lps25h"
 #define LPS331AP_PRESS_DEV_NAME		"lps331ap"
 
 /**
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 58083f9d51c5..7418768ed49c 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -40,6 +40,9 @@
 /* FULLSCALE */
 #define ST_PRESS_FS_AVL_1260MB			1260
 
+#define ST_PRESS_1_OUT_XL_ADDR			0x28
+#define ST_TEMP_1_OUT_L_ADDR			0x2b
+
 /* CUSTOM VALUES FOR LPS331AP SENSOR */
 #define ST_PRESS_LPS331AP_WAI_EXP		0xbb
 #define ST_PRESS_LPS331AP_ODR_ADDR		0x20
@@ -62,8 +65,6 @@
 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
 #define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
 #define ST_PRESS_LPS331AP_TEMP_OFFSET		42500
-#define ST_PRESS_LPS331AP_OUT_XL_ADDR		0x28
-#define ST_TEMP_LPS331AP_OUT_L_ADDR		0x2b
 
 /* CUSTOM VALUES FOR LPS001WP SENSOR */
 #define ST_PRESS_LPS001WP_WAI_EXP		0xba
@@ -80,11 +81,36 @@
 #define ST_PRESS_LPS001WP_OUT_L_ADDR		0x28
 #define ST_TEMP_LPS001WP_OUT_L_ADDR		0x2a
 
-static const struct iio_chan_spec st_press_lps331ap_channels[] = {
+/* CUSTOM VALUES FOR LPS25H SENSOR */
+#define ST_PRESS_LPS25H_WAI_EXP			0xbd
+#define ST_PRESS_LPS25H_ODR_ADDR		0x20
+#define ST_PRESS_LPS25H_ODR_MASK		0x70
+#define ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL		0x01
+#define ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL		0x02
+#define ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL	0x03
+#define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL	0x04
+#define ST_PRESS_LPS25H_PW_ADDR			0x20
+#define ST_PRESS_LPS25H_PW_MASK			0x80
+#define ST_PRESS_LPS25H_FS_ADDR			0x00
+#define ST_PRESS_LPS25H_FS_MASK			0x00
+#define ST_PRESS_LPS25H_FS_AVL_1260_VAL		0x00
+#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
+#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
+#define ST_PRESS_LPS25H_BDU_ADDR		0x20
+#define ST_PRESS_LPS25H_BDU_MASK		0x04
+#define ST_PRESS_LPS25H_DRDY_IRQ_ADDR		0x23
+#define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK	0x01
+#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK	0x10
+#define ST_PRESS_LPS25H_MULTIREAD_BIT		true
+#define ST_PRESS_LPS25H_TEMP_OFFSET		42500
+#define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
+#define ST_TEMP_LPS25H_OUT_L_ADDR		0x2b
+
+static const struct iio_chan_spec st_press_1_channels[] = {
 	{
 		.type = IIO_PRESSURE,
 		.channel2 = IIO_NO_MOD,
-		.address = ST_PRESS_LPS331AP_OUT_XL_ADDR,
+		.address = ST_PRESS_1_OUT_XL_ADDR,
 		.scan_index = ST_SENSORS_SCAN_X,
 		.scan_type = {
 			.sign = 'u',
@@ -99,7 +125,7 @@ static const struct iio_chan_spec st_press_lps331ap_channels[] = {
 	{
 		.type = IIO_TEMP,
 		.channel2 = IIO_NO_MOD,
-		.address = ST_TEMP_LPS331AP_OUT_L_ADDR,
+		.address = ST_TEMP_1_OUT_L_ADDR,
 		.scan_index = -1,
 		.scan_type = {
 			.sign = 'u',
@@ -156,8 +182,8 @@ static const struct st_sensors st_press_sensors[] = {
 		.sensors_supported = {
 			[0] = LPS331AP_PRESS_DEV_NAME,
 		},
-		.ch = (struct iio_chan_spec *)st_press_lps331ap_channels,
-		.num_ch = ARRAY_SIZE(st_press_lps331ap_channels),
+		.ch = (struct iio_chan_spec *)st_press_1_channels,
+		.num_ch = ARRAY_SIZE(st_press_1_channels),
 		.odr = {
 			.addr = ST_PRESS_LPS331AP_ODR_ADDR,
 			.mask = ST_PRESS_LPS331AP_ODR_MASK,
@@ -233,6 +259,53 @@ static const struct st_sensors st_press_sensors[] = {
 		.multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT,
 		.bootime = 2,
 	},
+	{
+		.wai = ST_PRESS_LPS25H_WAI_EXP,
+		.sensors_supported = {
+			[0] = LPS25H_PRESS_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_press_1_channels,
+		.num_ch = ARRAY_SIZE(st_press_1_channels),
+		.odr = {
+			.addr = ST_PRESS_LPS25H_ODR_ADDR,
+			.mask = ST_PRESS_LPS25H_ODR_MASK,
+			.odr_avl = {
+				{ 1, ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL, },
+				{ 7, ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL, },
+				{ 13, ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL, },
+				{ 25, ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_PRESS_LPS25H_PW_ADDR,
+			.mask = ST_PRESS_LPS25H_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.fs = {
+			.addr = ST_PRESS_LPS25H_FS_ADDR,
+			.mask = ST_PRESS_LPS25H_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_PRESS_FS_AVL_1260MB,
+					.value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
+					.gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
+					.gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_PRESS_LPS25H_BDU_ADDR,
+			.mask = ST_PRESS_LPS25H_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
+		},
+		.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
+		.bootime = 2,
+	},
 };
 
 static int st_press_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 51eab7fcb194..3cd73e39b840 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -50,6 +50,7 @@ static int st_press_i2c_remove(struct i2c_client *client)
 
 static const struct i2c_device_id st_press_id_table[] = {
 	{ LPS001WP_PRESS_DEV_NAME },
+	{ LPS25H_PRESS_DEV_NAME },
 	{ LPS331AP_PRESS_DEV_NAME },
 	{},
 };
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 27322af6d665..f45d430ec529 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -49,6 +49,7 @@ static int st_press_spi_remove(struct spi_device *spi)
 
 static const struct spi_device_id st_press_id_table[] = {
 	{ LPS001WP_PRESS_DEV_NAME },
+	{ LPS25H_PRESS_DEV_NAME },
 	{ LPS331AP_PRESS_DEV_NAME },
 	{},
 };
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index e81c5547e647..f9c12e92fdd6 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -53,8 +53,8 @@
 #include "user.h"
 
 #define DRV_NAME	MLX4_IB_DRV_NAME
-#define DRV_VERSION	"1.0"
-#define DRV_RELDATE	"April 4, 2008"
+#define DRV_VERSION	"2.2-1"
+#define DRV_RELDATE	"Feb 2014"
 
 #define MLX4_IB_FLOW_MAX_PRIO 0xFFF
 #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index aa03e732b6a8..bf900579ac08 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -46,8 +46,8 @@
 #include "mlx5_ib.h"
 
 #define DRIVER_NAME "mlx5_ib"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE	"June 2013"
+#define DRIVER_VERSION "2.2-1"
+#define DRIVER_RELDATE	"Feb 2014"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver");
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/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index bb3b57bea8ba..5ef7fcf0e250 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -76,8 +76,18 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
 	struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
 	unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
 	unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
+	int val;
 
-	return !!(adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank) & bit);
+	mutex_lock(&kpad->gpio_lock);
+
+	if (kpad->dir[bank] & bit)
+		val = kpad->dat_out[bank];
+	else
+		val = adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank);
+
+	mutex_unlock(&kpad->gpio_lock);
+
+	return !!(val & bit);
 }
 
 static void adp5588_gpio_set_value(struct gpio_chip *chip,
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index cbf4f8038cba..97ec33572e56 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -439,7 +439,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no irq defined in platform data\n");
-		return -EINVAL;
+		return irq;
 	}
 
 	input_dev = devm_input_allocate_device(&pdev->dev);
@@ -449,7 +449,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
 	}
 
 	keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad),
-			     GFP_KERNEL);
+			      GFP_KERNEL);
 	if (!keypad) {
 		dev_err(&pdev->dev, "not enough memory for driver data\n");
 		return -ENOMEM;
diff --git a/drivers/input/leds.c b/drivers/input/leds.c
new file mode 100644
index 000000000000..1d8a980719ab
--- /dev/null
+++ b/drivers/input/leds.c
@@ -0,0 +1,249 @@
+/*
+ * LED support for the input layer
+ *
+ * Copyright 2010-2013 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 = kzalloc(sizeof(*leds) * LED_CNT, 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/Kconfig b/drivers/input/misc/Kconfig
index 7904ab05527a..762e6d2de3c9 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -156,7 +156,7 @@ config INPUT_MAX8925_ONKEY
 
 config INPUT_MAX8997_HAPTIC
 	tristate "MAXIM MAX8997 haptic controller support"
-	depends on PWM && HAVE_PWM && MFD_MAX8997
+	depends on PWM && MFD_MAX8997
 	select INPUT_FF_MEMLESS
 	help
 	  This option enables device driver support for the haptic controller
@@ -470,7 +470,7 @@ config INPUT_PCF8574
 
 config INPUT_PWM_BEEPER
 	tristate "PWM beeper support"
-	depends on PWM && HAVE_PWM
+	depends on PWM
 	help
 	  Say Y here to get support for PWM based beeper devices.
 
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index 1f695f229ea8..184c8f21ab59 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -27,29 +27,32 @@ struct da9052_onkey {
 
 static void da9052_onkey_query(struct da9052_onkey *onkey)
 {
-	int key_stat;
+	int ret;
 
-	key_stat = da9052_reg_read(onkey->da9052, DA9052_EVENT_B_REG);
-	if (key_stat < 0) {
+	ret = da9052_reg_read(onkey->da9052, DA9052_STATUS_A_REG);
+	if (ret < 0) {
 		dev_err(onkey->da9052->dev,
-			"Failed to read onkey event %d\n", key_stat);
+			"Failed to read onkey event err=%d\n", ret);
 	} else {
 		/*
 		 * Since interrupt for deassertion of ONKEY pin is not
 		 * generated, onkey event state determines the onkey
 		 * button state.
 		 */
-		key_stat &= DA9052_EVENTB_ENONKEY;
-		input_report_key(onkey->input, KEY_POWER, key_stat);
+		bool pressed = !(ret & DA9052_STATUSA_NONKEY);
+
+		input_report_key(onkey->input, KEY_POWER, pressed);
 		input_sync(onkey->input);
-	}
 
-	/*
-	 * Interrupt is generated only when the ONKEY pin is asserted.
-	 * Hence the deassertion of the pin is simulated through work queue.
-	 */
-	if (key_stat)
-		schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
+		/*
+		 * Interrupt is generated only when the ONKEY pin
+		 * is asserted.  Hence the deassertion of the pin
+		 * is simulated through work queue.
+		 */
+		if (pressed)
+			schedule_delayed_work(&onkey->work,
+						msecs_to_jiffies(50));
+	}
 }
 
 static void da9052_onkey_work(struct work_struct *work)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index e204f26b0011..5a736397d9c8 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -51,6 +51,8 @@ struct ims_pcu_backlight {
 #define IMS_PCU_BL_VERSION_LEN		(9 + 1)
 #define IMS_PCU_BL_RESET_REASON_LEN	(2 + 1)
 
+#define IMS_PCU_PCU_B_DEVICE_ID		5
+
 #define IMS_PCU_BUF_SIZE		128
 
 struct ims_pcu {
@@ -68,6 +70,9 @@ struct ims_pcu {
 	char bl_version[IMS_PCU_BL_VERSION_LEN];
 	char reset_reason[IMS_PCU_BL_RESET_REASON_LEN];
 	int update_firmware_status;
+	u8 device_id;
+
+	u8 ofn_reg_addr;
 
 	struct usb_interface *ctrl_intf;
 
@@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
 #define IMS_PCU_CMD_GET_DEVICE_ID	0xae
 #define IMS_PCU_CMD_SPECIAL_INFO	0xb0
 #define IMS_PCU_CMD_BOOTLOADER		0xb1	/* Pass data to bootloader */
+#define IMS_PCU_CMD_OFN_SET_CONFIG	0xb3
+#define IMS_PCU_CMD_OFN_GET_CONFIG	0xb4
 
 /* PCU responses */
 #define IMS_PCU_RSP_STATUS		0xc0
@@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
 #define IMS_PCU_RSP_GET_DEVICE_ID	0xce
 #define IMS_PCU_RSP_SPECIAL_INFO	0xd0
 #define IMS_PCU_RSP_BOOTLOADER		0xd1	/* Bootloader response */
+#define IMS_PCU_RSP_OFN_SET_CONFIG	0xd2
+#define IMS_PCU_RSP_OFN_GET_CONFIG	0xd3
+
 
 #define IMS_PCU_RSP_EVNT_BUTTONS	0xe0	/* Unsolicited, button state */
 #define IMS_PCU_GAMEPAD_MASK		0x0001ff80UL	/* Bits 7 through 16 */
@@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = {
 	.attrs		= ims_pcu_attrs,
 };
 
+/* Support for a separate OFN attribute group */
+
+#define OFN_REG_RESULT_OFFSET	2
+
+static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data)
+{
+	int error;
+	s16 result;
+
+	error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG,
+					&addr, sizeof(addr));
+	if (error)
+		return error;
+
+	result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
+	if (result < 0)
+		return -EIO;
+
+	/* We only need LSB */
+	*data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET];
+	return 0;
+}
+
+static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data)
+{
+	u8 buffer[] = { addr, data };
+	int error;
+	s16 result;
+
+	error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG,
+					&buffer, sizeof(buffer));
+	if (error)
+		return error;
+
+	result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
+	if (result < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev,
+					 struct device_attribute *dattr,
+					 char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	int error;
+	u8 data;
+
+	mutex_lock(&pcu->cmd_mutex);
+	error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data);
+	mutex_unlock(&pcu->cmd_mutex);
+
+	if (error)
+		return error;
+
+	return scnprintf(buf, PAGE_SIZE, "%x\n", data);
+}
+
+static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev,
+					  struct device_attribute *dattr,
+					  const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	int error;
+	u8 value;
+
+	error = kstrtou8(buf, 0, &value);
+	if (error)
+		return error;
+
+	mutex_lock(&pcu->cmd_mutex);
+	error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value);
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return error ?: count;
+}
+
+static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR,
+		   ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store);
+
+static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev,
+					 struct device_attribute *dattr,
+					 char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	int error;
+
+	mutex_lock(&pcu->cmd_mutex);
+	error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr);
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return error;
+}
+
+static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev,
+					  struct device_attribute *dattr,
+					  const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	int error;
+	u8 value;
+
+	error = kstrtou8(buf, 0, &value);
+	if (error)
+		return error;
+
+	mutex_lock(&pcu->cmd_mutex);
+	pcu->ofn_reg_addr = value;
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return error ?: count;
+}
+
+static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR,
+		   ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store);
+
+struct ims_pcu_ofn_bit_attribute {
+	struct device_attribute dattr;
+	u8 addr;
+	u8 nr;
+};
+
+static ssize_t ims_pcu_ofn_bit_show(struct device *dev,
+				    struct device_attribute *dattr,
+				    char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct ims_pcu_ofn_bit_attribute *attr =
+		container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr);
+	int error;
+	u8 data;
+
+	mutex_lock(&pcu->cmd_mutex);
+	error = ims_pcu_read_ofn_config(pcu, attr->addr, &data);
+	mutex_unlock(&pcu->cmd_mutex);
+
+	if (error)
+		return error;
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr)));
+}
+
+static ssize_t ims_pcu_ofn_bit_store(struct device *dev,
+				     struct device_attribute *dattr,
+				     const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct ims_pcu_ofn_bit_attribute *attr =
+		container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr);
+	int error;
+	int value;
+	u8 data;
+
+	error = kstrtoint(buf, 0, &value);
+	if (error)
+		return error;
+
+	if (value > 1)
+		return -EINVAL;
+
+	mutex_lock(&pcu->cmd_mutex);
+
+	error = ims_pcu_read_ofn_config(pcu, attr->addr, &data);
+	if (!error) {
+		if (value)
+			data |= 1U << attr->nr;
+		else
+			data &= ~(1U << attr->nr);
+
+		error = ims_pcu_write_ofn_config(pcu, attr->addr, data);
+	}
+
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return error ?: count;
+}
+
+#define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr)			\
+struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = {		\
+	.dattr = __ATTR(_field, S_IWUSR | S_IRUGO,			\
+			ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store),	\
+	.addr = _addr,							\
+	.nr = _nr,							\
+}
+
+static IMS_PCU_OFN_BIT_ATTR(engine_enable,   0x60, 7);
+static IMS_PCU_OFN_BIT_ATTR(speed_enable,    0x60, 6);
+static IMS_PCU_OFN_BIT_ATTR(assert_enable,   0x60, 5);
+static IMS_PCU_OFN_BIT_ATTR(xyquant_enable,  0x60, 4);
+static IMS_PCU_OFN_BIT_ATTR(xyscale_enable,  0x60, 1);
+
+static IMS_PCU_OFN_BIT_ATTR(scale_x2,        0x63, 6);
+static IMS_PCU_OFN_BIT_ATTR(scale_y2,        0x63, 7);
+
+static struct attribute *ims_pcu_ofn_attrs[] = {
+	&dev_attr_reg_data.attr,
+	&dev_attr_reg_addr.attr,
+	&ims_pcu_ofn_attr_engine_enable.dattr.attr,
+	&ims_pcu_ofn_attr_speed_enable.dattr.attr,
+	&ims_pcu_ofn_attr_assert_enable.dattr.attr,
+	&ims_pcu_ofn_attr_xyquant_enable.dattr.attr,
+	&ims_pcu_ofn_attr_xyscale_enable.dattr.attr,
+	&ims_pcu_ofn_attr_scale_x2.dattr.attr,
+	&ims_pcu_ofn_attr_scale_y2.dattr.attr,
+	NULL
+};
+
+static struct attribute_group ims_pcu_ofn_attr_group = {
+	.name	= "ofn",
+	.attrs	= ims_pcu_ofn_attrs,
+};
+
 static void ims_pcu_irq(struct urb *urb)
 {
 	struct ims_pcu *pcu = urb->context;
@@ -1624,7 +1853,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 	static atomic_t device_no = ATOMIC_INIT(0);
 
 	const struct ims_pcu_device_info *info;
-	u8 device_id;
 	int error;
 
 	error = ims_pcu_get_device_info(pcu);
@@ -1633,7 +1861,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 		return error;
 	}
 
-	error = ims_pcu_identify_type(pcu, &device_id);
+	error = ims_pcu_identify_type(pcu, &pcu->device_id);
 	if (error) {
 		dev_err(pcu->dev,
 			"Failed to identify device, error: %d\n", error);
@@ -1645,9 +1873,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 		return 0;
 	}
 
-	if (device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
-	    !ims_pcu_device_info[device_id].keymap) {
-		dev_err(pcu->dev, "Device ID %d is not valid\n", device_id);
+	if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
+	    !ims_pcu_device_info[pcu->device_id].keymap) {
+		dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id);
 		/* Same as above, punt to userspace */
 		return 0;
 	}
@@ -1655,11 +1883,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 	/* Device appears to be operable, complete initialization */
 	pcu->device_no = atomic_inc_return(&device_no) - 1;
 
+	/*
+	 * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor
+	 */
+	if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) {
+		error = sysfs_create_group(&pcu->dev->kobj,
+					   &ims_pcu_ofn_attr_group);
+		if (error)
+			return error;
+	}
+
 	error = ims_pcu_setup_backlight(pcu);
 	if (error)
 		return error;
 
-	info = &ims_pcu_device_info[device_id];
+	info = &ims_pcu_device_info[pcu->device_id];
 	error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len);
 	if (error)
 		goto err_destroy_backlight;
@@ -1674,10 +1912,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 
 	return 0;
 
-err_destroy_backlight:
-	ims_pcu_destroy_backlight(pcu);
 err_destroy_buttons:
 	ims_pcu_destroy_buttons(pcu);
+err_destroy_backlight:
+	ims_pcu_destroy_backlight(pcu);
 	return error;
 }
 
@@ -1691,6 +1929,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu)
 			ims_pcu_destroy_gamepad(pcu);
 		ims_pcu_destroy_buttons(pcu);
 		ims_pcu_destroy_backlight(pcu);
+
+		if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID)
+			sysfs_remove_group(&pcu->dev->kobj,
+					   &ims_pcu_ofn_attr_group);
 	}
 }
 
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 17ccba88d636..ed8e5e8449d3 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -67,7 +67,7 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned
 	}
 
 	if (value > 20 && value < 32767)
-		count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1;
+		count = (ixp4xx_timer_freq / (value * 4)) - 1;
 
 	ixp4xx_spkr_control(pin, count);
 
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index e8897c36d21b..4d66c723cf08 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -1,7 +1,8 @@
 /*
  * Power key driver for SiRF PrimaII
  *
- * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company.
+ * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
+ * company.
  *
  * Licensed under GPLv2 or later.
  */
@@ -13,16 +14,41 @@
 #include <linux/input.h>
 #include <linux/rtc/sirfsoc_rtciobrg.h>
 #include <linux/of.h>
+#include <linux/workqueue.h>
 
 struct sirfsoc_pwrc_drvdata {
 	u32			pwrc_base;
 	struct input_dev	*input;
+	struct delayed_work	work;
 };
 
 #define PWRC_ON_KEY_BIT			(1 << 0)
 
 #define PWRC_INT_STATUS			0xc
 #define PWRC_INT_MASK			0x10
+#define PWRC_PIN_STATUS			0x14
+#define PWRC_KEY_DETECT_UP_TIME		20	/* ms*/
+
+static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv)
+{
+	u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base +
+							PWRC_PIN_STATUS);
+	return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */
+}
+
+static void sirfsoc_pwrc_report_event(struct work_struct *work)
+{
+	struct sirfsoc_pwrc_drvdata *pwrcdrv =
+		container_of(work, struct sirfsoc_pwrc_drvdata, work.work);
+
+	if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) {
+		schedule_delayed_work(&pwrcdrv->work,
+			msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
+	} else {
+		input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0);
+		input_sync(pwrcdrv->input);
+	}
+}
 
 static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
 {
@@ -34,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
 	sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT,
 				 pwrcdrv->pwrc_base + PWRC_INT_STATUS);
 
-	/*
-	 * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c
-	 * to queue a SUSPEND APM event
-	 */
-	input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1);
+	input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1);
 	input_sync(pwrcdrv->input);
-
-	/*
-	 * Todo: report KEY_POWER event for Android platforms, Android PowerManager
-	 * will handle the suspend and powerdown/hibernation
-	 */
+	schedule_delayed_work(&pwrcdrv->work,
+			      msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
 
 	return IRQ_HANDLED;
 }
 
+static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv,
+					   bool enable)
+{
+	u32 int_mask;
+
+	int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK);
+	if (enable)
+		int_mask |= PWRC_ON_KEY_BIT;
+	else
+		int_mask &= ~PWRC_ON_KEY_BIT;
+	sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK);
+}
+
+static int sirfsoc_pwrc_open(struct input_dev *input)
+{
+	struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+
+	return 0;
+}
+
+static void sirfsoc_pwrc_close(struct input_dev *input)
+{
+	struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
+	cancel_delayed_work_sync(&pwrcdrv->work);
+}
+
 static const struct of_device_id sirfsoc_pwrc_of_match[] = {
 	{ .compatible = "sirf,prima2-pwrc" },
 	{},
@@ -70,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 	}
 
 	/*
-	 * we can't use of_iomap because pwrc is not mapped in memory,
+	 * We can't use of_iomap because pwrc is not mapped in memory,
 	 * the so-called base address is only offset in rtciobrg
 	 */
 	error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base);
@@ -86,11 +135,21 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 
 	pwrcdrv->input->name = "sirfsoc pwrckey";
 	pwrcdrv->input->phys = "pwrc/input0";
-	pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
+	pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY);
+
+	INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event);
+
+	pwrcdrv->input->open = sirfsoc_pwrc_open;
+	pwrcdrv->input->close = sirfsoc_pwrc_close;
+
+	input_set_drvdata(pwrcdrv->input, pwrcdrv);
+
+	/* Make sure the device is quiesced */
+	sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
 
 	irq = platform_get_irq(pdev, 0);
 	error = devm_request_irq(&pdev->dev, irq,
-				 sirfsoc_pwrc_isr, IRQF_SHARED,
+				 sirfsoc_pwrc_isr, 0,
 				 "sirfsoc_pwrc_int", pwrcdrv);
 	if (error) {
 		dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n",
@@ -98,11 +157,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 		return error;
 	}
 
-	sirfsoc_rtc_iobrg_writel(
-		sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) |
-			PWRC_ON_KEY_BIT,
-		pwrcdrv->pwrc_base + PWRC_INT_MASK);
-
 	error = input_register_device(pwrcdrv->input);
 	if (error) {
 		dev_err(&pdev->dev,
@@ -111,7 +165,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 		return error;
 	}
 
-	platform_set_drvdata(pdev, pwrcdrv);
+	dev_set_drvdata(&pdev->dev, pwrcdrv);
 	device_init_wakeup(&pdev->dev, 1);
 
 	return 0;
@@ -125,25 +179,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int pwrc_resume(struct device *dev)
+static int sirfsoc_pwrc_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);
+	struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev);
+	struct input_dev *input = pwrcdrv->input;
 
 	/*
 	 * Do not mask pwrc interrupt as we want pwrc work as a wakeup source
 	 * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
 	 */
-	sirfsoc_rtc_iobrg_writel(
-		sirfsoc_rtc_iobrg_readl(
-		pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT,
-		pwrcdrv->pwrc_base + PWRC_INT_MASK);
+	mutex_lock(&input->mutex);
+	if (input->users)
+		sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+	mutex_unlock(&input->mutex);
 
 	return 0;
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume);
+static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume);
 
 static struct platform_driver sirfsoc_pwrc_driver = {
 	.probe		= sirfsoc_pwrc_probe,
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 772835938a52..856936247500 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *	0.4	01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *		- add UI_GET_SYSNAME ioctl
  *	0.3	09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>)
  *		- updated ff support for the changes in kernel interface
  *		- added MODULE_VERSION
@@ -670,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer,
 	__ret;						\
 })
 
+static int uinput_str_to_user(void __user *dest, const char *str,
+			      unsigned int maxlen)
+{
+	char __user *p = dest;
+	int len, ret;
+
+	if (!str)
+		return -ENOENT;
+
+	if (maxlen == 0)
+		return -EINVAL;
+
+	len = strlen(str) + 1;
+	if (len > maxlen)
+		len = maxlen;
+
+	ret = copy_to_user(p, str, len);
+	if (ret)
+		return -EFAULT;
+
+	/* force terminating '\0' */
+	ret = put_user(0, p + len - 1);
+	return ret ? -EFAULT : len;
+}
+
 static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 				 unsigned long arg, void __user *p)
 {
@@ -679,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 	struct uinput_ff_erase  ff_erase;
 	struct uinput_request   *req;
 	char			*phys;
+	const char		*name;
+	unsigned int		size;
 
 	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
@@ -693,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 	switch (cmd) {
 		case UI_DEV_CREATE:
 			retval = uinput_create_device(udev);
-			break;
+			goto out;
 
 		case UI_DEV_DESTROY:
 			uinput_destroy_device(udev);
-			break;
+			goto out;
 
 		case UI_SET_EVBIT:
 			retval = uinput_set_bit(arg, evbit, EV_MAX);
-			break;
+			goto out;
 
 		case UI_SET_KEYBIT:
 			retval = uinput_set_bit(arg, keybit, KEY_MAX);
-			break;
+			goto out;
 
 		case UI_SET_RELBIT:
 			retval = uinput_set_bit(arg, relbit, REL_MAX);
-			break;
+			goto out;
 
 		case UI_SET_ABSBIT:
 			retval = uinput_set_bit(arg, absbit, ABS_MAX);
-			break;
+			goto out;
 
 		case UI_SET_MSCBIT:
 			retval = uinput_set_bit(arg, mscbit, MSC_MAX);
-			break;
+			goto out;
 
 		case UI_SET_LEDBIT:
 			retval = uinput_set_bit(arg, ledbit, LED_MAX);
-			break;
+			goto out;
 
 		case UI_SET_SNDBIT:
 			retval = uinput_set_bit(arg, sndbit, SND_MAX);
-			break;
+			goto out;
 
 		case UI_SET_FFBIT:
 			retval = uinput_set_bit(arg, ffbit, FF_MAX);
-			break;
+			goto out;
 
 		case UI_SET_SWBIT:
 			retval = uinput_set_bit(arg, swbit, SW_MAX);
-			break;
+			goto out;
 
 		case UI_SET_PROPBIT:
 			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
-			break;
+			goto out;
 
 		case UI_SET_PHYS:
 			if (udev->state == UIST_CREATED) {
@@ -753,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 
 			kfree(udev->dev->phys);
 			udev->dev->phys = phys;
-			break;
+			goto out;
 
 		case UI_BEGIN_FF_UPLOAD:
 			retval = uinput_ff_upload_from_user(p, &ff_up);
 			if (retval)
-				break;
+				goto out;
 
 			req = uinput_request_find(udev, ff_up.request_id);
 			if (!req || req->code != UI_FF_UPLOAD ||
 			    !req->u.upload.effect) {
 				retval = -EINVAL;
-				break;
+				goto out;
 			}
 
 			ff_up.retval = 0;
@@ -775,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 				memset(&ff_up.old, 0, sizeof(struct ff_effect));
 
 			retval = uinput_ff_upload_to_user(p, &ff_up);
-			break;
+			goto out;
 
 		case UI_BEGIN_FF_ERASE:
 			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
 				retval = -EFAULT;
-				break;
+				goto out;
 			}
 
 			req = uinput_request_find(udev, ff_erase.request_id);
 			if (!req || req->code != UI_FF_ERASE) {
 				retval = -EINVAL;
-				break;
+				goto out;
 			}
 
 			ff_erase.retval = 0;
 			ff_erase.effect_id = req->u.effect_id;
 			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
 				retval = -EFAULT;
-				break;
+				goto out;
 			}
 
-			break;
+			goto out;
 
 		case UI_END_FF_UPLOAD:
 			retval = uinput_ff_upload_from_user(p, &ff_up);
 			if (retval)
-				break;
+				goto out;
 
 			req = uinput_request_find(udev, ff_up.request_id);
 			if (!req || req->code != UI_FF_UPLOAD ||
 			    !req->u.upload.effect) {
 				retval = -EINVAL;
-				break;
+				goto out;
 			}
 
 			req->retval = ff_up.retval;
 			uinput_request_done(udev, req);
-			break;
+			goto out;
 
 		case UI_END_FF_ERASE:
 			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
 				retval = -EFAULT;
-				break;
+				goto out;
 			}
 
 			req = uinput_request_find(udev, ff_erase.request_id);
 			if (!req || req->code != UI_FF_ERASE) {
 				retval = -EINVAL;
-				break;
+				goto out;
 			}
 
 			req->retval = ff_erase.retval;
 			uinput_request_done(udev, req);
-			break;
+			goto out;
+	}
 
-		default:
-			retval = -EINVAL;
+	size = _IOC_SIZE(cmd);
+
+	/* Now check variable-length commands */
+	switch (cmd & ~IOCSIZE_MASK) {
+	case UI_GET_SYSNAME(0):
+		if (udev->state != UIST_CREATED) {
+			retval = -ENOENT;
+			goto out;
+		}
+		name = dev_name(&udev->dev->dev);
+		retval = uinput_str_to_user(p, name, size);
+		goto out;
 	}
 
+	retval = -EINVAL;
  out:
 	mutex_unlock(&udev->mutex);
 	return retval;
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index b6505454bcc4..7b7add5061a5 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
 	{ KE_END,       0 }
 };
 
+static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = {
+	{ KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */
+	{ KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
+	{ KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
+	{ KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
+	{ KE_KEY,       0x36, {KEY_WWW} },           /* www button */
+	{ KE_WIFI,      0x78 },                      /* satelite dish button */
+	{ KE_END,       FE_WIFI_LED }
+};
+
 static struct key_entry keymap_fujitsu_n3510[] __initdata = {
 	{ KE_KEY, 0x11, {KEY_PROG1} },
 	{ KE_KEY, 0x12, {KEY_PROG2} },
@@ -654,6 +664,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = {
 		.driver_data = keymap_fs_amilo_pro_v3505
 	},
 	{
+		/* Fujitsu-Siemens Amilo Pro Edition V8210 */
+		.callback = dmi_matched,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"),
+		},
+		.driver_data = keymap_fs_amilo_pro_v8210
+	},
+	{
 		/* Fujitsu-Siemens Amilo M7400 */
 		.callback = dmi_matched,
 		.matches = {
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index a70aa555bbff..e7409c45bdd0 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -236,7 +236,7 @@ EXPORT_SYMBOL(sparse_keymap_setup);
  * in an input device that was set up by sparse_keymap_setup().
  * NOTE: It is safe to cal this function while input device is
  * still registered (however the drivers should care not to try to
- * use freed keymap and thus have to shut off interrups/polling
+ * use freed keymap and thus have to shut off interrupts/polling
  * before freeing the keymap).
  */
 void sparse_keymap_free(struct input_dev *dev)
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index caecffe8caff..858045694e9d 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -848,7 +848,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
 	gtco->inputdevice = input_dev;
 
 	/* Save interface information */
-	gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
+	gtco->usbdev = interface_to_usbdev(usbinterface);
 	gtco->intf = usbinterface;
 
 	/* Allocate some data for incoming reports */
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 5c342b3139e8..3c0f57efe7b1 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -134,7 +134,8 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
 	} else if (!ts->low_latency_req.dev) {
 		/* First contact, request 100 us latency. */
 		dev_pm_qos_add_ancestor_request(&ts->client->dev,
-						&ts->low_latency_req, 100);
+						&ts->low_latency_req,
+						DEV_PM_QOS_RESUME_LATENCY, 100);
 	}
 
 	/* SYN_REPORT */
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 2175f3419002..01d30cedde46 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -29,10 +29,13 @@
 #include <linux/sysfs.h>
 #include <linux/input/mt.h>
 #include <linux/platform_data/zforce_ts.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #define WAIT_TIMEOUT		msecs_to_jiffies(1000)
 
 #define FRAME_START		0xee
+#define FRAME_MAXSIZE		257
 
 /* Offsets of the different parts of the payload the controller sends */
 #define PAYLOAD_HEADER		0
@@ -64,7 +67,7 @@
 #define RESPONSE_STATUS		0X1e
 
 /*
- * Notifications are send by the touch controller without
+ * Notifications are sent by the touch controller without
  * being requested by the driver and include for example
  * touch indications
  */
@@ -103,8 +106,8 @@ struct zforce_point {
  * @suspended		device suspended
  * @access_mutex	serialize i2c-access, to keep multipart reads together
  * @command_done	completion to wait for the command result
- * @command_mutex	serialize commands send to the ic
- * @command_waiting	the id of the command that that is currently waiting
+ * @command_mutex	serialize commands sent to the ic
+ * @command_waiting	the id of the command that is currently waiting
  *			for a result
  * @command_result	returned result of the command
  */
@@ -235,7 +238,8 @@ static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger,
 			(finger & 0xff), ((finger >> 8) & 0xff),
 			(stylus & 0xff), ((stylus >> 8) & 0xff) };
 
-	dev_dbg(&client->dev, "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
+	dev_dbg(&client->dev,
+		"set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
 		idle, finger, stylus);
 
 	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
@@ -255,7 +259,7 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1)
 static int zforce_start(struct zforce_ts *ts)
 {
 	struct i2c_client *client = ts->client;
-	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+	const struct zforce_ts_platdata *pdata = ts->pdata;
 	int ret;
 
 	dev_dbg(&client->dev, "starting device\n");
@@ -326,13 +330,14 @@ static int zforce_stop(struct zforce_ts *ts)
 static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
 {
 	struct i2c_client *client = ts->client;
-	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+	const struct zforce_ts_platdata *pdata = ts->pdata;
 	struct zforce_point point;
 	int count, i, num = 0;
 
 	count = payload[0];
 	if (count > ZFORCE_REPORT_POINTS) {
-		dev_warn(&client->dev, "to many coordinates %d, expected max %d\n",
+		dev_warn(&client->dev,
+			 "too many coordinates %d, expected max %d\n",
 			 count, ZFORCE_REPORT_POINTS);
 		count = ZFORCE_REPORT_POINTS;
 	}
@@ -421,7 +426,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
 		goto unlock;
 	}
 
-	if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) {
+	if (buf[PAYLOAD_LENGTH] == 0) {
 		dev_err(&client->dev, "invalid payload length: %d\n",
 			buf[PAYLOAD_LENGTH]);
 		ret = -EIO;
@@ -471,9 +476,9 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
 	struct zforce_ts *ts = dev_id;
 	struct i2c_client *client = ts->client;
-	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+	const struct zforce_ts_platdata *pdata = ts->pdata;
 	int ret;
-	u8 payload_buffer[512];
+	u8 payload_buffer[FRAME_MAXSIZE];
 	u8 *payload;
 
 	/*
@@ -494,8 +499,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 	while (!gpio_get_value(pdata->gpio_int)) {
 		ret = zforce_read_packet(ts, payload_buffer);
 		if (ret < 0) {
-			dev_err(&client->dev, "could not read packet, ret: %d\n",
-				ret);
+			dev_err(&client->dev,
+				"could not read packet, ret: %d\n", ret);
 			break;
 		}
 
@@ -539,7 +544,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 						payload[RESPONSE_DATA + 4];
 			ts->version_rev   = (payload[RESPONSE_DATA + 7] << 8) |
 						payload[RESPONSE_DATA + 6];
-			dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n",
+			dev_dbg(&ts->client->dev,
+				"Firmware Version %04x:%04x %04x:%04x\n",
 				ts->version_major, ts->version_minor,
 				ts->version_build, ts->version_rev);
 
@@ -552,7 +558,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 			break;
 
 		default:
-			dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n",
+			dev_err(&ts->client->dev,
+				"unrecognized response id: 0x%x\n",
 				payload[RESPONSE_ID]);
 			break;
 		}
@@ -618,7 +625,8 @@ static int zforce_suspend(struct device *dev)
 
 		enable_irq_wake(client->irq);
 	} else if (input->users) {
-		dev_dbg(&client->dev, "suspend without being a wakeup source\n");
+		dev_dbg(&client->dev,
+			"suspend without being a wakeup source\n");
 
 		ret = zforce_stop(ts);
 		if (ret)
@@ -684,6 +692,45 @@ static void zforce_reset(void *data)
 	gpio_set_value(ts->pdata->gpio_rst, 0);
 }
 
+static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
+{
+	struct zforce_ts_platdata *pdata;
+	struct device_node *np = dev->of_node;
+
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev, "failed to allocate platform data\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pdata->gpio_int = of_get_gpio(np, 0);
+	if (!gpio_is_valid(pdata->gpio_int)) {
+		dev_err(dev, "failed to get interrupt gpio\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdata->gpio_rst = of_get_gpio(np, 1);
+	if (!gpio_is_valid(pdata->gpio_rst)) {
+		dev_err(dev, "failed to get reset gpio\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+		dev_err(dev, "failed to get x-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+		dev_err(dev, "failed to get y-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return pdata;
+}
+
 static int zforce_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -692,8 +739,11 @@ static int zforce_probe(struct i2c_client *client,
 	struct input_dev *input_dev;
 	int ret;
 
-	if (!pdata)
-		return -EINVAL;
+	if (!pdata) {
+		pdata = zforce_parse_dt(&client->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
 
 	ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL);
 	if (!ts)
@@ -798,7 +848,7 @@ static int zforce_probe(struct i2c_client *client,
 		return ret;
 	}
 
-	/* this gets the firmware version among other informations */
+	/* this gets the firmware version among other information */
 	ret = zforce_command_wait(ts, COMMAND_STATUS);
 	if (ret < 0) {
 		dev_err(&client->dev, "couldn't get status, %d\n", ret);
@@ -829,11 +879,20 @@ static struct i2c_device_id zforce_idtable[] = {
 };
 MODULE_DEVICE_TABLE(i2c, zforce_idtable);
 
+#ifdef CONFIG_OF
+static struct of_device_id zforce_dt_idtable[] = {
+	{ .compatible = "neonode,zforce" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, zforce_dt_idtable);
+#endif
+
 static struct i2c_driver zforce_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "zforce-ts",
 		.pm	= &zforce_pm_ops,
+		.of_match_table	= of_match_ptr(zforce_dt_idtable),
 	},
 	.probe		= zforce_probe,
 	.id_table	= zforce_idtable,
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index e400fbe411de..cff039df056e 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/irqreturn.h>
 
 /*
  * Maximum number of IOMMUs supported
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c
index 7a3b928fad1c..464acda0bbc4 100644
--- a/drivers/iommu/shmobile-iommu.c
+++ b/drivers/iommu/shmobile-iommu.c
@@ -343,7 +343,7 @@ static int shmobile_iommu_add_device(struct device *dev)
 	mapping = archdata->iommu_mapping;
 	if (!mapping) {
 		mapping = arm_iommu_create_mapping(&platform_bus_type, 0,
-						   L1_LEN << 20, 0);
+						   L1_LEN << 20);
 		if (IS_ERR(mapping))
 			return PTR_ERR(mapping);
 		archdata->iommu_mapping = mapping;
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 61ffdca96e25..ec42d2decb2f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -39,6 +39,14 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config CLPS711X_IRQCHIP
+	bool
+	depends on ARCH_CLPS711X
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+	default y
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 5194afb39e78..9c843424f123 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_IRQCHIP)			+= irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
+obj-$(CONFIG_ARCH_DOVE)			+= irq-dove.o
 obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
@@ -10,6 +11,7 @@ obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
 obj-$(CONFIG_METAG)			+= irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
 obj-$(CONFIG_ARCH_MOXART)		+= irq-moxart.o
+obj-$(CONFIG_CLPS711X_IRQCHIP)		+= irq-clps711x.o
 obj-$(CONFIG_ORION_IRQCHIP)		+= irq-orion.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index 40e6440348ff..f8636a650cf6 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -17,7 +17,6 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <asm/mach/irq.h>
 
 #include "irqchip.h"
 
@@ -81,7 +80,7 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq);
 
 	if (unlikely(!cascade_irq))
-		do_bad_IRQ(irq, desc);
+		handle_bad_irq(irq, desc);
 	else
 		generic_handle_irq(cascade_irq);
 
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 540956465ed2..cd79503abea9 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -42,6 +43,7 @@
 #define ARMADA_370_XP_INT_SOURCE_CTL(irq)	(0x100 + irq*4)
 
 #define ARMADA_370_XP_CPU_INTACK_OFFS		(0x44)
+#define ARMADA_375_PPI_CAUSE			(0x10)
 
 #define ARMADA_370_XP_SW_TRIG_INT_OFFS           (0x4)
 #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS          (0xc)
@@ -352,6 +354,62 @@ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
+#ifdef CONFIG_PCI_MSI
+static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
+{
+	u32 msimask, msinr;
+
+	msimask = readl_relaxed(per_cpu_int_base +
+				ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+		& PCI_MSI_DOORBELL_MASK;
+
+	writel(~msimask, per_cpu_int_base +
+	       ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+	for (msinr = PCI_MSI_DOORBELL_START;
+	     msinr < PCI_MSI_DOORBELL_END; msinr++) {
+		int irq;
+
+		if (!(msimask & BIT(msinr)))
+			continue;
+
+		irq = irq_find_mapping(armada_370_xp_msi_domain,
+				       msinr - 16);
+
+		if (is_chained)
+			generic_handle_irq(irq);
+		else
+			handle_IRQ(irq, regs);
+	}
+}
+#else
+static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
+#endif
+
+static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
+						  struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	unsigned long irqmap, irqn;
+	unsigned int cascade_irq;
+
+	chained_irq_enter(chip, desc);
+
+	irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
+
+	if (irqmap & BIT(0)) {
+		armada_370_xp_handle_msi_irq(NULL, true);
+		irqmap &= ~BIT(0);
+	}
+
+	for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
+		cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
+		generic_handle_irq(cascade_irq);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
 static asmlinkage void __exception_irq_entry
 armada_370_xp_handle_irq(struct pt_regs *regs)
 {
@@ -372,31 +430,9 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
 			continue;
 		}
 
-#ifdef CONFIG_PCI_MSI
 		/* MSI handling */
-		if (irqnr == 1) {
-			u32 msimask, msinr;
-
-			msimask = readl_relaxed(per_cpu_int_base +
-						ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
-				& PCI_MSI_DOORBELL_MASK;
-
-			writel(~msimask, per_cpu_int_base +
-			       ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
-
-			for (msinr = PCI_MSI_DOORBELL_START;
-			     msinr < PCI_MSI_DOORBELL_END; msinr++) {
-				int irq;
-
-				if (!(msimask & BIT(msinr)))
-					continue;
-
-				irq = irq_find_mapping(armada_370_xp_msi_domain,
-						       msinr - 16);
-				handle_IRQ(irq, regs);
-			}
-		}
-#endif
+		if (irqnr == 1)
+			armada_370_xp_handle_msi_irq(regs, false);
 
 #ifdef CONFIG_SMP
 		/* IPI Handling */
@@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 					     struct device_node *parent)
 {
 	struct resource main_int_res, per_cpu_int_res;
+	int parent_irq;
 	u32 control;
 
 	BUG_ON(of_address_to_resource(node, 0, &main_int_res));
@@ -455,8 +492,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 
 	BUG_ON(!armada_370_xp_mpic_domain);
 
-	irq_set_default_host(armada_370_xp_mpic_domain);
-
 #ifdef CONFIG_SMP
 	armada_xp_mpic_smp_cpu_init();
 
@@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 
 	armada_370_xp_msi_init(node, main_int_res.start);
 
-	set_handle_irq(armada_370_xp_handle_irq);
+	parent_irq = irq_of_parse_and_map(node, 0);
+	if (parent_irq <= 0) {
+		irq_set_default_host(armada_370_xp_mpic_domain);
+		set_handle_irq(armada_370_xp_handle_irq);
+	} else {
+		irq_set_chained_handler(parent_irq,
+					armada_370_xp_mpic_handle_cascade_irq);
+	}
 
 	return 0;
 }
diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c
new file mode 100644
index 000000000000..33340dc97d1d
--- /dev/null
+++ b/drivers/irqchip/irq-clps711x.c
@@ -0,0 +1,243 @@
+/*
+ *  CLPS711X IRQ driver
+ *
+ *  Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute 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/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
+
+#define CLPS711X_INTSR1	(0x0240)
+#define CLPS711X_INTMR1	(0x0280)
+#define CLPS711X_BLEOI	(0x0600)
+#define CLPS711X_MCEOI	(0x0640)
+#define CLPS711X_TEOI	(0x0680)
+#define CLPS711X_TC1EOI	(0x06c0)
+#define CLPS711X_TC2EOI	(0x0700)
+#define CLPS711X_RTCEOI	(0x0740)
+#define CLPS711X_UMSEOI	(0x0780)
+#define CLPS711X_COEOI	(0x07c0)
+#define CLPS711X_INTSR2	(0x1240)
+#define CLPS711X_INTMR2	(0x1280)
+#define CLPS711X_SRXEOF	(0x1600)
+#define CLPS711X_KBDEOI	(0x1700)
+#define CLPS711X_INTSR3	(0x2240)
+#define CLPS711X_INTMR3	(0x2280)
+
+static const struct {
+#define CLPS711X_FLAG_EN	(1 << 0)
+#define CLPS711X_FLAG_FIQ	(1 << 1)
+	unsigned int	flags;
+	phys_addr_t	eoi;
+} clps711x_irqs[] = {
+	[1]	= { CLPS711X_FLAG_FIQ, CLPS711X_BLEOI, },
+	[3]	= { CLPS711X_FLAG_FIQ, CLPS711X_MCEOI, },
+	[4]	= { CLPS711X_FLAG_EN, CLPS711X_COEOI, },
+	[5]	= { CLPS711X_FLAG_EN, },
+	[6]	= { CLPS711X_FLAG_EN, },
+	[7]	= { CLPS711X_FLAG_EN, },
+	[8]	= { CLPS711X_FLAG_EN, CLPS711X_TC1EOI, },
+	[9]	= { CLPS711X_FLAG_EN, CLPS711X_TC2EOI, },
+	[10]	= { CLPS711X_FLAG_EN, CLPS711X_RTCEOI, },
+	[11]	= { CLPS711X_FLAG_EN, CLPS711X_TEOI, },
+	[12]	= { CLPS711X_FLAG_EN, },
+	[13]	= { CLPS711X_FLAG_EN, },
+	[14]	= { CLPS711X_FLAG_EN, CLPS711X_UMSEOI, },
+	[15]	= { CLPS711X_FLAG_EN, CLPS711X_SRXEOF, },
+	[16]	= { CLPS711X_FLAG_EN, CLPS711X_KBDEOI, },
+	[17]	= { CLPS711X_FLAG_EN, },
+	[18]	= { CLPS711X_FLAG_EN, },
+	[28]	= { CLPS711X_FLAG_EN, },
+	[29]	= { CLPS711X_FLAG_EN, },
+	[32]	= { CLPS711X_FLAG_FIQ, },
+};
+
+static struct {
+	void __iomem		*base;
+	void __iomem		*intmr[3];
+	void __iomem		*intsr[3];
+	struct irq_domain	*domain;
+	struct irq_domain_ops	ops;
+} *clps711x_intc;
+
+static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs)
+{
+	u32 irqnr, irqstat;
+
+	do {
+		irqstat = readw_relaxed(clps711x_intc->intmr[0]) &
+			  readw_relaxed(clps711x_intc->intsr[0]);
+		if (irqstat) {
+			irqnr =	irq_find_mapping(clps711x_intc->domain,
+						 fls(irqstat) - 1);
+			handle_IRQ(irqnr, regs);
+		}
+
+		irqstat = readw_relaxed(clps711x_intc->intmr[1]) &
+			  readw_relaxed(clps711x_intc->intsr[1]);
+		if (irqstat) {
+			irqnr =	irq_find_mapping(clps711x_intc->domain,
+						 fls(irqstat) - 1 + 16);
+			handle_IRQ(irqnr, regs);
+		}
+	} while (irqstat);
+}
+
+static void clps711x_intc_eoi(struct irq_data *d)
+{
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+
+	writel_relaxed(0, clps711x_intc->base + clps711x_irqs[hwirq].eoi);
+}
+
+static void clps711x_intc_mask(struct irq_data *d)
+{
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	void __iomem *intmr = clps711x_intc->intmr[hwirq / 16];
+	u32 tmp;
+
+	tmp = readl_relaxed(intmr);
+	tmp &= ~(1 << (hwirq % 16));
+	writel_relaxed(tmp, intmr);
+}
+
+static void clps711x_intc_unmask(struct irq_data *d)
+{
+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	void __iomem *intmr = clps711x_intc->intmr[hwirq / 16];
+	u32 tmp;
+
+	tmp = readl_relaxed(intmr);
+	tmp |= 1 << (hwirq % 16);
+	writel_relaxed(tmp, intmr);
+}
+
+static struct irq_chip clps711x_intc_chip = {
+	.name		= "clps711x-intc",
+	.irq_eoi	= clps711x_intc_eoi,
+	.irq_mask	= clps711x_intc_mask,
+	.irq_unmask	= clps711x_intc_unmask,
+};
+
+static int __init clps711x_intc_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	irq_flow_handler_t handler = handle_level_irq;
+	unsigned int flags = IRQF_VALID | IRQF_PROBE;
+
+	if (!clps711x_irqs[hw].flags)
+		return 0;
+
+	if (clps711x_irqs[hw].flags & CLPS711X_FLAG_FIQ) {
+		handler = handle_bad_irq;
+		flags |= IRQF_NOAUTOEN;
+	} else if (clps711x_irqs[hw].eoi) {
+		handler = handle_fasteoi_irq;
+	}
+
+	/* Clear down pending interrupt */
+	if (clps711x_irqs[hw].eoi)
+		writel_relaxed(0, clps711x_intc->base + clps711x_irqs[hw].eoi);
+
+	irq_set_chip_and_handler(virq, &clps711x_intc_chip, handler);
+	set_irq_flags(virq, flags);
+
+	return 0;
+}
+
+static int __init _clps711x_intc_init(struct device_node *np,
+				      phys_addr_t base, resource_size_t size)
+{
+	int err;
+
+	clps711x_intc = kzalloc(sizeof(*clps711x_intc), GFP_KERNEL);
+	if (!clps711x_intc)
+		return -ENOMEM;
+
+	clps711x_intc->base = ioremap(base, size);
+	if (!clps711x_intc->base) {
+		err = -ENOMEM;
+		goto out_kfree;
+	}
+
+	clps711x_intc->intsr[0] = clps711x_intc->base + CLPS711X_INTSR1;
+	clps711x_intc->intmr[0] = clps711x_intc->base + CLPS711X_INTMR1;
+	clps711x_intc->intsr[1] = clps711x_intc->base + CLPS711X_INTSR2;
+	clps711x_intc->intmr[1] = clps711x_intc->base + CLPS711X_INTMR2;
+	clps711x_intc->intsr[2] = clps711x_intc->base + CLPS711X_INTSR3;
+	clps711x_intc->intmr[2] = clps711x_intc->base + CLPS711X_INTMR3;
+
+	/* Mask all interrupts */
+	writel_relaxed(0, clps711x_intc->intmr[0]);
+	writel_relaxed(0, clps711x_intc->intmr[1]);
+	writel_relaxed(0, clps711x_intc->intmr[2]);
+
+	err = irq_alloc_descs(-1, 0, ARRAY_SIZE(clps711x_irqs), numa_node_id());
+	if (IS_ERR_VALUE(err))
+		goto out_iounmap;
+
+	clps711x_intc->ops.map = clps711x_intc_irq_map;
+	clps711x_intc->ops.xlate = irq_domain_xlate_onecell;
+	clps711x_intc->domain =
+		irq_domain_add_legacy(np, ARRAY_SIZE(clps711x_irqs),
+				      0, 0, &clps711x_intc->ops, NULL);
+	if (!clps711x_intc->domain) {
+		err = -ENOMEM;
+		goto out_irqfree;
+	}
+
+	irq_set_default_host(clps711x_intc->domain);
+	set_handle_irq(clps711x_irqh);
+
+#ifdef CONFIG_FIQ
+	init_FIQ(0);
+#endif
+
+	return 0;
+
+out_irqfree:
+	irq_free_descs(0, ARRAY_SIZE(clps711x_irqs));
+
+out_iounmap:
+	iounmap(clps711x_intc->base);
+
+out_kfree:
+	kfree(clps711x_intc);
+
+	return err;
+}
+
+void __init clps711x_intc_init(phys_addr_t base, resource_size_t size)
+{
+	BUG_ON(_clps711x_intc_init(NULL, base, size));
+}
+
+#ifdef CONFIG_IRQCHIP
+static int __init clps711x_intc_init_dt(struct device_node *np,
+					struct device_node *parent)
+{
+	struct resource res;
+	int err;
+
+	err = of_address_to_resource(np, 0, &res);
+	if (err)
+		return err;
+
+	return _clps711x_intc_init(np, res.start, resource_size(&res));
+}
+IRQCHIP_DECLARE(clps711x, "cirrus,clps711x-intc", clps711x_intc_init_dt);
+#endif
diff --git a/drivers/irqchip/irq-dove.c b/drivers/irqchip/irq-dove.c
new file mode 100644
index 000000000000..788acd89848a
--- /dev/null
+++ b/drivers/irqchip/irq-dove.c
@@ -0,0 +1,126 @@
+/*
+ * Marvell Dove SoCs PMU IRQ chip driver.
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
+
+#define DOVE_PMU_IRQ_CAUSE	0x00
+#define DOVE_PMU_IRQ_MASK	0x04
+
+static void dove_pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_domain *d = irq_get_handler_data(irq);
+	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
+	u32 stat = readl_relaxed(gc->reg_base + DOVE_PMU_IRQ_CAUSE) &
+		   gc->mask_cache;
+
+	while (stat) {
+		u32 hwirq = ffs(stat) - 1;
+
+		generic_handle_irq(irq_find_mapping(d, gc->irq_base + hwirq));
+		stat &= ~(1 << hwirq);
+	}
+}
+
+static void pmu_irq_ack(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	u32 mask = ~d->mask;
+
+	/*
+	 * The PMU mask register is not RW0C: it is RW.	 This means that
+	 * the bits take whatever value is written to them; if you write
+	 * a '1', you will set the interrupt.
+	 *
+	 * Unfortunately this means there is NO race free way to clear
+	 * these interrupts.
+	 *
+	 * So, let's structure the code so that the window is as small as
+	 * possible.
+	 */
+	irq_gc_lock(gc);
+	mask &= irq_reg_readl(gc->reg_base +  ct->regs.ack);
+	irq_reg_writel(mask, gc->reg_base +  ct->regs.ack);
+	irq_gc_unlock(gc);
+}
+
+static int __init dove_pmu_irq_init(struct device_node *np,
+				    struct device_node *parent)
+{
+	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+	struct resource r;
+	struct irq_domain *domain;
+	struct irq_chip_generic *gc;
+	int ret, irq, nrirqs = 7;
+
+	domain = irq_domain_add_linear(np, nrirqs,
+				       &irq_generic_chip_ops, NULL);
+	if (!domain) {
+		pr_err("%s: unable to add irq domain\n", np->name);
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
+			     handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
+	if (ret) {
+		pr_err("%s: unable to alloc irq domain gc\n", np->name);
+		return ret;
+	}
+
+	ret = of_address_to_resource(np, 0, &r);
+	if (ret) {
+		pr_err("%s: unable to get resource\n", np->name);
+		return ret;
+	}
+
+	if (!request_mem_region(r.start, resource_size(&r), np->name)) {
+		pr_err("%s: unable to request mem region\n", np->name);
+		return -ENOMEM;
+	}
+
+	/* Map the parent interrupt for the chained handler */
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		pr_err("%s: unable to parse irq\n", np->name);
+		return -EINVAL;
+	}
+
+	gc = irq_get_domain_generic_chip(domain, 0);
+	gc->reg_base = ioremap(r.start, resource_size(&r));
+	if (!gc->reg_base) {
+		pr_err("%s: unable to map resource\n", np->name);
+		return -ENOMEM;
+	}
+
+	gc->chip_types[0].regs.ack = DOVE_PMU_IRQ_CAUSE;
+	gc->chip_types[0].regs.mask = DOVE_PMU_IRQ_MASK;
+	gc->chip_types[0].chip.irq_ack = pmu_irq_ack;
+	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
+
+	/* mask and clear all interrupts */
+	writel(0, gc->reg_base + DOVE_PMU_IRQ_MASK);
+	writel(0, gc->reg_base + DOVE_PMU_IRQ_CAUSE);
+
+	irq_set_handler_data(irq, domain);
+	irq_set_chained_handler(irq, dove_pmu_irq_handler);
+
+	return 0;
+}
+IRQCHIP_DECLARE(dove_pmu_intc,
+		"marvell,dove-pmu-intc", dove_pmu_irq_init);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 341c6016812d..500e533b9648 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -661,9 +661,9 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
 	/*
 	 * Ensure that stores to Normal memory are visible to the
-	 * other CPUs before issuing the IPI.
+	 * other CPUs before they observe us issuing the IPI.
 	 */
-	dsb();
+	dmb(ishst);
 
 	/* this always happens on GIC0 */
 	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 8e21ae0bab46..fd2c980e4cea 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -57,6 +57,7 @@
 
 /**
  * struct vic_device - VIC PM device
+ * @parent_irq: The parent IRQ number of the VIC if cascaded, or 0.
  * @irq: The IRQ number for the base of the VIC.
  * @base: The register base for the VIC.
  * @valid_sources: A bitmask of valid interrupts
@@ -224,6 +225,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
 	return handled;
 }
 
+static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc)
+{
+	u32 stat, hwirq;
+	struct vic_device *vic = irq_desc_get_handler_data(desc);
+
+	while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
+		hwirq = ffs(stat) - 1;
+		generic_handle_irq(irq_find_mapping(vic->domain, hwirq));
+	}
+}
+
 /*
  * Keep iterating over all registered VIC's until there are no pending
  * interrupts.
@@ -246,6 +258,7 @@ static struct irq_domain_ops vic_irqdomain_ops = {
 /**
  * vic_register() - Register a VIC.
  * @base: The base address of the VIC.
+ * @parent_irq: The parent IRQ if cascaded, else 0.
  * @irq: The base IRQ for the VIC.
  * @valid_sources: bitmask of valid interrupts
  * @resume_sources: bitmask of interrupts allowed for resume sources.
@@ -257,7 +270,8 @@ static struct irq_domain_ops vic_irqdomain_ops = {
  *
  * This also configures the IRQ domain for the VIC.
  */
-static void __init vic_register(void __iomem *base, unsigned int irq,
+static void __init vic_register(void __iomem *base, unsigned int parent_irq,
+				unsigned int irq,
 				u32 valid_sources, u32 resume_sources,
 				struct device_node *node)
 {
@@ -273,15 +287,25 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
 	v->base = base;
 	v->valid_sources = valid_sources;
 	v->resume_sources = resume_sources;
-	v->irq = irq;
 	set_handle_irq(vic_handle_irq);
 	vic_id++;
+
+	if (parent_irq) {
+		irq_set_handler_data(parent_irq, v);
+		irq_set_chained_handler(parent_irq, vic_handle_irq_cascaded);
+	}
+
 	v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
 					  &vic_irqdomain_ops, v);
 	/* create an IRQ mapping for each valid IRQ */
 	for (i = 0; i < fls(valid_sources); i++)
 		if (valid_sources & (1 << i))
 			irq_create_mapping(v->domain, i);
+	/* If no base IRQ was passed, figure out our allocated base */
+	if (irq)
+		v->irq = irq;
+	else
+		v->irq = irq_find_mapping(v->domain, 0);
 }
 
 static void vic_ack_irq(struct irq_data *d)
@@ -409,10 +433,10 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
 		writel(32, base + VIC_PL190_DEF_VECT_ADDR);
 	}
 
-	vic_register(base, irq_start, vic_sources, 0, node);
+	vic_register(base, 0, irq_start, vic_sources, 0, node);
 }
 
-void __init __vic_init(void __iomem *base, int irq_start,
+void __init __vic_init(void __iomem *base, int parent_irq, int irq_start,
 			      u32 vic_sources, u32 resume_sources,
 			      struct device_node *node)
 {
@@ -449,7 +473,7 @@ void __init __vic_init(void __iomem *base, int irq_start,
 
 	vic_init2(base);
 
-	vic_register(base, irq_start, vic_sources, resume_sources, node);
+	vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node);
 }
 
 /**
@@ -462,8 +486,30 @@ void __init __vic_init(void __iomem *base, int irq_start,
 void __init vic_init(void __iomem *base, unsigned int irq_start,
 		     u32 vic_sources, u32 resume_sources)
 {
-	__vic_init(base, irq_start, vic_sources, resume_sources, NULL);
+	__vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL);
+}
+
+/**
+ * vic_init_cascaded() - initialise a cascaded vectored interrupt controller
+ * @base: iomem base address
+ * @parent_irq: the parent IRQ we're cascaded off
+ * @irq_start: starting interrupt number, must be muliple of 32
+ * @vic_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
+ *
+ * This returns the base for the new interrupts or negative on error.
+ */
+int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq,
+			      u32 vic_sources, u32 resume_sources)
+{
+	struct vic_device *v;
+
+	v = &vic_devices[vic_id];
+	__vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL);
+	/* Return out acquired base */
+	return v->irq;
 }
+EXPORT_SYMBOL_GPL(vic_init_cascaded);
 
 #ifdef CONFIG_OF
 int __init vic_of_init(struct device_node *node, struct device_node *parent)
@@ -485,7 +531,7 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
 	/*
 	 * Passing 0 as first IRQ makes the simple domain allocate descriptors
 	 */
-	__vic_init(regs, 0, interrupt_mask, wakeup_mask, node);
+	__vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node);
 
 	return 0;
 }
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index fb4f1bac0133..1c5dc345e7c5 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -86,12 +86,13 @@ isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 	struct divert_info *inf;
 	int len;
 
-	if (!*((struct divert_info **) file->private_data)) {
+	if (!(inf = *((struct divert_info **) file->private_data))) {
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-		interruptible_sleep_on(&(rd_queue));
+		wait_event_interruptible(rd_queue, (inf =
+			*((struct divert_info **) file->private_data)));
 	}
-	if (!(inf = *((struct divert_info **) file->private_data)))
+	if (!inf)
 		return (0);
 
 	inf->usage_cnt--;	/* new usage count */
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 2be1c8a3bb5f..d8ef64da26f1 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -509,7 +509,8 @@ static void
 set_arcofi(struct IsdnCardState *cs, int bc) {
 	cs->dc.isac.arcofi_bc = bc;
 	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
-	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+	wait_event_interruptible(cs->dc.isac.arcofi_wait,
+				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
 }
 
 static int
@@ -528,7 +529,8 @@ check_arcofi(struct IsdnCardState *cs)
 		}
 	cs->dc.isac.arcofi_bc = 0;
 	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
-	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+	wait_event_interruptible(cs->dc.isac.arcofi_wait,
+				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
 	if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
 		debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
 		p = cs->dc.isac.mon_rx;
@@ -595,7 +597,8 @@ check_arcofi(struct IsdnCardState *cs)
 			       Elsa_Types[cs->subtyp],
 			       cs->hw.elsa.base + 8);
 		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
-		interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+		wait_event_interruptible(cs->dc.isac.arcofi_wait,
+				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
 		return (1);
 	}
 	return (0);
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 3f84dd8f1757..a2a358c1dc8e 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -573,7 +573,8 @@ modem_l2l1(struct PStack *st, int pr, void *arg)
 		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
 		bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
 		arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
-		interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
+		wait_event_interruptible(bcs->cs->dc.isac.arcofi_wait,
+				 bcs->cs->dc.isac.arcofi_state == ARCOFI_NOP);
 		bcs->cs->hw.elsa.MFlag = 1;
 	} else {
 		printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index b61e8d5e84ad..7b5fd8fb1761 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -175,14 +175,15 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 	int len;
 	hysdn_card *card = PDE_DATA(file_inode(file));
 
-	if (!*((struct log_data **) file->private_data)) {
+	if (!(inf = *((struct log_data **) file->private_data))) {
 		struct procdata *pd = card->proclog;
 		if (file->f_flags & O_NONBLOCK)
 			return (-EAGAIN);
 
-		interruptible_sleep_on(&(pd->rd_queue));
+		wait_event_interruptible(pd->rd_queue, (inf =
+				*((struct log_data **) file->private_data)));
 	}
-	if (!(inf = *((struct log_data **) file->private_data)))
+	if (!inf)
 		return (0);
 
 	inf->usage_cnt--;	/* new usage count */
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 9bb12ba3191f..130f21643154 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -777,7 +777,8 @@ isdn_readbchan(int di, int channel, u_char *buf, u_char *fp, int len, wait_queue
 		return 0;
 	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
 		if (sleep)
-			interruptible_sleep_on(sleep);
+			wait_event_interruptible(*sleep,
+				!skb_queue_empty(&dev->drv[di]->rpqueue[channel]));
 		else
 			return 0;
 	}
@@ -1072,7 +1073,8 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 				retval = -EAGAIN;
 				goto out;
 			}
-			interruptible_sleep_on(&(dev->info_waitq));
+			wait_event_interruptible(dev->info_waitq,
+						 file->private_data);
 		}
 		p = isdn_statstr();
 		file->private_data = NULL;
@@ -1128,7 +1130,8 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 				retval = -EAGAIN;
 				goto out;
 			}
-			interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
+			wait_event_interruptible(dev->drv[drvidx]->st_waitq,
+						 dev->drv[drvidx]->stavail);
 		}
 		if (dev->drv[drvidx]->interface->readstat) {
 			if (count > dev->drv[drvidx]->stavail)
@@ -1188,8 +1191,8 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
 			goto out;
 		}
 		chidx = isdn_minor2chan(minor);
-		while ((retval = isdn_writebuf_stub(drvidx, chidx, buf, count)) == 0)
-			interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
+		wait_event_interruptible(dev->drv[drvidx]->snd_waitq[chidx],
+			(retval = isdn_writebuf_stub(drvidx, chidx, buf, count)));
 		goto out;
 	}
 	if (minor <= ISDN_MINOR_CTRLMAX) {
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 1eaf62273903..f02cc506fbfa 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -796,6 +796,7 @@ static void set_running_timeout(unsigned long ptr)
 #endif
 	dev = (struct pcbit_dev *) ptr;
 
+	dev->l2_state = L2_DOWN;
 	wake_up_interruptible(&dev->set_running_wq);
 }
 
@@ -818,7 +819,8 @@ static int set_protocol_running(struct pcbit_dev *dev)
 
 	add_timer(&dev->set_running_timer);
 
-	interruptible_sleep_on(&dev->set_running_wq);
+	wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING ||
+					dev->l2_state == L2_DOWN);
 
 	del_timer(&dev->set_running_timer);
 
@@ -842,8 +844,6 @@ static int set_protocol_running(struct pcbit_dev *dev)
 		printk(KERN_DEBUG "pcbit: initialization failed\n");
 		printk(KERN_DEBUG "pcbit: firmware not loaded\n");
 
-		dev->l2_state = L2_DOWN;
-
 #ifdef DEBUG
 		printk(KERN_DEBUG "Bank3 = %02x\n",
 		       readb(dev->sh_mem + BANK3));
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 72156c123033..49d2189644e1 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
@@ -416,12 +413,12 @@ config LEDS_MC13783
 	depends on MFD_MC13XXX
 	help
 	  This option enable support for on-chip LED drivers found
-	  on Freescale Semiconductor MC13783/MC13892 PMIC.
+	  on Freescale Semiconductor MC13783/MC13892/MC34708 PMIC.
 
 config LEDS_NS2
 	tristate "LED support for Network Space v2 GPIO LEDs"
 	depends on LEDS_CLASS
-	depends on ARCH_KIRKWOOD
+	depends on ARCH_KIRKWOOD || MACH_KIRKWOOD
 	default y
 	help
 	  This option enable support for the dual-GPIO LED found on the
@@ -431,7 +428,7 @@ config LEDS_NS2
 config LEDS_NETXBIG
 	tristate "LED support for Big Network series LEDs"
 	depends on LEDS_CLASS
-	depends on ARCH_KIRKWOOD
+	depends on ARCH_KIRKWOOD || MACH_KIRKWOOD
 	default y
 	help
 	  This option enable support for LEDs found on the LaCie 2Big
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index ce8921a753a3..71b40d3bf776 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -39,9 +39,11 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
 	led_cdev->blink_delay_on = delay_on;
 	led_cdev->blink_delay_off = delay_off;
 
-	/* never on - don't blink */
-	if (!delay_on)
+	/* never on - just set to off */
+	if (!delay_on) {
+		__led_set_brightness(led_cdev, LED_OFF);
 		return;
+	}
 
 	/* never off - just set to brightness */
 	if (!delay_off) {
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index e387f41a9cb7..df1a7c15f12d 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 5f588c0a376e..d1e1bca90d11 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -11,7 +11,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index 7e311a120b11..86b5bdb0c773 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index 6de216a89a0c..70c74a7f0dfe 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index 66d0a57db221..d0452b099aee 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -18,7 +18,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
@@ -444,7 +443,7 @@ static void led_work(struct work_struct *work)
 {
 	int ret;
 	struct blinkm_led *led;
-	struct blinkm_data *data ;
+	struct blinkm_data *data;
 	struct blinkm_work *blm_work = work_to_blmwork(work);
 
 	led = blm_work->blinkm_led;
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index d93e2455da5c..19202f5cc299 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -19,7 +19,7 @@ MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
 MODULE_DESCRIPTION("Clevo mail LED driver");
 MODULE_LICENSE("GPL");
 
-static bool __initdata nodetect;
+static bool nodetect;
 module_param_named(nodetect, nodetect, bool, 0);
 MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
 
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 8abcb66db01c..910339d86edf 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -3,7 +3,6 @@
  *
  * Control the Cobalt Qube/RaQ front LED
  */
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/leds.h>
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index 2a4b87f8091a..35dffb100388 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index 865d4faf874a..01486adc7f8b 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index b4d5a44cc41b..2b4dc738dcd6 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -16,7 +16,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/module.h>
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 78b0e273a903..953fb37f0375 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -11,7 +11,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
@@ -204,6 +203,9 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
 		}
 
+		if (of_get_property(child, "retain-state-suspended", NULL))
+			led.retain_state_suspended = 1;
+
 		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
 				      &pdev->dev, NULL);
 		if (ret < 0) {
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index 366b6055e330..d61a98896c71 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <asm/hd64461.h>
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index 027ede73b80d..e2c642c1169b 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/mfd/core.h>
 #include <linux/mutex.h>
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 2ec34cfcedce..8ca197af2864 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 4ade66a2d9d4..cb5ed82994ba 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index bf006f4e44a0..ca85724ab138 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -13,7 +13,6 @@
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -347,9 +346,9 @@ static void lp5562_write_program_memory(struct lp55xx_chip *chip,
 /* check the size of program count */
 static inline bool _is_pc_overflow(struct lp55xx_predef_pattern *ptn)
 {
-	return (ptn->size_r >= LP5562_PROGRAM_LENGTH ||
-		ptn->size_g >= LP5562_PROGRAM_LENGTH ||
-		ptn->size_b >= LP5562_PROGRAM_LENGTH);
+	return ptn->size_r >= LP5562_PROGRAM_LENGTH ||
+	       ptn->size_g >= LP5562_PROGRAM_LENGTH ||
+	       ptn->size_b >= LP5562_PROGRAM_LENGTH;
 }
 
 static int lp5562_run_predef_led_pattern(struct lp55xx_chip *chip, int mode)
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 3417e5be7b57..059f5b1f3553 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index ca87a1b4a0db..f1db88e25138 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -1,5 +1,5 @@
 /*
- * LEDs driver for Freescale MC13783/MC13892
+ * LEDs driver for Freescale MC13783/MC13892/MC34708
  *
  * Copyright (C) 2010 Philippe Rétornaz
  *
@@ -17,57 +17,56 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/mfd/mc13xxx.h>
 
-#define MC13XXX_REG_LED_CONTROL(x)	(51 + (x))
-
 struct mc13xxx_led_devtype {
 	int	led_min;
 	int	led_max;
 	int	num_regs;
+	u32	ledctrl_base;
 };
 
 struct mc13xxx_led {
 	struct led_classdev	cdev;
 	struct work_struct	work;
-	struct mc13xxx		*master;
 	enum led_brightness	new_brightness;
 	int			id;
+	struct mc13xxx_leds	*leds;
 };
 
 struct mc13xxx_leds {
+	struct mc13xxx			*master;
 	struct mc13xxx_led_devtype	*devtype;
 	int				num_leds;
-	struct mc13xxx_led		led[0];
+	struct mc13xxx_led		*led;
 };
 
+static unsigned int mc13xxx_max_brightness(int id)
+{
+	if (id >= MC13783_LED_MD && id <= MC13783_LED_KP)
+		return 0x0f;
+	else if (id >= MC13783_LED_R1 && id <= MC13783_LED_B3)
+		return 0x1f;
+
+	return 0x3f;
+}
+
 static void mc13xxx_led_work(struct work_struct *work)
 {
 	struct mc13xxx_led *led = container_of(work, struct mc13xxx_led, work);
-	int reg, mask, value, bank, off, shift;
+	struct mc13xxx_leds *leds = led->leds;
+	unsigned int reg, bank, off, shift;
 
 	switch (led->id) {
 	case MC13783_LED_MD:
-		reg = MC13XXX_REG_LED_CONTROL(2);
-		shift = 9;
-		mask = 0x0f;
-		value = led->new_brightness >> 4;
-		break;
 	case MC13783_LED_AD:
-		reg = MC13XXX_REG_LED_CONTROL(2);
-		shift = 13;
-		mask = 0x0f;
-		value = led->new_brightness >> 4;
-		break;
 	case MC13783_LED_KP:
-		reg = MC13XXX_REG_LED_CONTROL(2);
-		shift = 17;
-		mask = 0x0f;
-		value = led->new_brightness >> 4;
+		reg = 2;
+		shift = 9 + (led->id - MC13783_LED_MD) * 4;
 		break;
 	case MC13783_LED_R1:
 	case MC13783_LED_G1:
@@ -80,44 +79,35 @@ static void mc13xxx_led_work(struct work_struct *work)
 	case MC13783_LED_B3:
 		off = led->id - MC13783_LED_R1;
 		bank = off / 3;
-		reg = MC13XXX_REG_LED_CONTROL(3) + bank;
+		reg = 3 + bank;
 		shift = (off - bank * 3) * 5 + 6;
-		value = led->new_brightness >> 3;
-		mask = 0x1f;
 		break;
 	case MC13892_LED_MD:
-		reg = MC13XXX_REG_LED_CONTROL(0);
-		shift = 3;
-		mask = 0x3f;
-		value = led->new_brightness >> 2;
-		break;
 	case MC13892_LED_AD:
-		reg = MC13XXX_REG_LED_CONTROL(0);
-		shift = 15;
-		mask = 0x3f;
-		value = led->new_brightness >> 2;
-		break;
 	case MC13892_LED_KP:
-		reg = MC13XXX_REG_LED_CONTROL(1);
-		shift = 3;
-		mask = 0x3f;
-		value = led->new_brightness >> 2;
+		reg = (led->id - MC13892_LED_MD) / 2;
+		shift = 3 + (led->id - MC13892_LED_MD) * 12;
 		break;
 	case MC13892_LED_R:
 	case MC13892_LED_G:
 	case MC13892_LED_B:
 		off = led->id - MC13892_LED_R;
 		bank = off / 2;
-		reg = MC13XXX_REG_LED_CONTROL(2) + bank;
+		reg = 2 + bank;
 		shift = (off - bank * 2) * 12 + 3;
-		value = led->new_brightness >> 2;
-		mask = 0x3f;
+		break;
+	case MC34708_LED_R:
+	case MC34708_LED_G:
+		reg = 0;
+		shift = 3 + (led->id - MC34708_LED_R) * 12;
 		break;
 	default:
 		BUG();
 	}
 
-	mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift);
+	mc13xxx_reg_rmw(leds->master, leds->devtype->ledctrl_base + reg,
+			mc13xxx_max_brightness(led->id) << shift,
+			led->new_brightness << shift);
 }
 
 static void mc13xxx_led_set(struct led_classdev *led_cdev,
@@ -130,47 +120,121 @@ static void mc13xxx_led_set(struct led_classdev *led_cdev,
 	schedule_work(&led->work);
 }
 
-static int __init mc13xxx_led_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
+	struct platform_device *pdev)
 {
-	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct mc13xxx *mcdev = dev_get_drvdata(pdev->dev.parent);
-	struct mc13xxx_led_devtype *devtype =
-		(struct mc13xxx_led_devtype *)pdev->id_entry->driver_data;
-	struct mc13xxx_leds *leds;
-	int i, id, num_leds, ret = -ENODATA;
-	u32 reg, init_led = 0;
+	struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
+	struct mc13xxx_leds_platform_data *pdata;
+	struct device_node *parent, *child;
+	struct device *dev = &pdev->dev;
+	int i = 0, ret = -ENODATA;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	of_node_get(dev->parent->of_node);
+
+	parent = of_find_node_by_name(dev->parent->of_node, "leds");
+	if (!parent)
+		goto out_node_put;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "Missing platform data\n");
-		return -ENODEV;
+	ret = of_property_read_u32_array(parent, "led-control",
+					 pdata->led_control,
+					 leds->devtype->num_regs);
+	if (ret)
+		goto out_node_put;
+
+	pdata->num_leds = of_get_child_count(parent);
+
+	pdata->led = devm_kzalloc(dev, pdata->num_leds * sizeof(*pdata->led),
+				  GFP_KERNEL);
+	if (!pdata->led) {
+		ret = -ENOMEM;
+		goto out_node_put;
 	}
 
-	num_leds = pdata->num_leds;
+	for_each_child_of_node(parent, child) {
+		const char *str;
+		u32 tmp;
 
-	if ((num_leds < 1) ||
-	    (num_leds > (devtype->led_max - devtype->led_min + 1))) {
-		dev_err(&pdev->dev, "Invalid LED count %d\n", num_leds);
-		return -EINVAL;
+		if (of_property_read_u32(child, "reg", &tmp))
+			continue;
+		pdata->led[i].id = leds->devtype->led_min + tmp;
+
+		if (!of_property_read_string(child, "label", &str))
+			pdata->led[i].name = str;
+		if (!of_property_read_string(child, "linux,default-trigger",
+					     &str))
+			pdata->led[i].default_trigger = str;
+
+		i++;
 	}
 
-	leds = devm_kzalloc(&pdev->dev, num_leds * sizeof(struct mc13xxx_led) +
-			    sizeof(struct mc13xxx_leds), GFP_KERNEL);
+	pdata->num_leds = i;
+	ret = i > 0 ? 0 : -ENODATA;
+
+out_node_put:
+	of_node_put(parent);
+
+	return ret ? ERR_PTR(ret) : pdata;
+}
+#else
+static inline struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
+	struct platform_device *pdev)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif
+
+static int __init mc13xxx_led_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(dev);
+	struct mc13xxx *mcdev = dev_get_drvdata(dev->parent);
+	struct mc13xxx_led_devtype *devtype =
+		(struct mc13xxx_led_devtype *)pdev->id_entry->driver_data;
+	struct mc13xxx_leds *leds;
+	int i, id, ret = -ENODATA;
+	u32 init_led = 0;
+
+	leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL);
 	if (!leds)
 		return -ENOMEM;
 
 	leds->devtype = devtype;
-	leds->num_leds = num_leds;
+	leds->master = mcdev;
 	platform_set_drvdata(pdev, leds);
 
+	if (dev->parent->of_node) {
+		pdata = mc13xxx_led_probe_dt(pdev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	} else if (!pdata)
+		return -ENODATA;
+
+	leds->num_leds = pdata->num_leds;
+
+	if ((leds->num_leds < 1) ||
+	    (leds->num_leds > (devtype->led_max - devtype->led_min + 1))) {
+		dev_err(dev, "Invalid LED count %d\n", leds->num_leds);
+		return -EINVAL;
+	}
+
+	leds->led = devm_kzalloc(dev, leds->num_leds * sizeof(*leds->led),
+				 GFP_KERNEL);
+	if (!leds->led)
+		return -ENOMEM;
+
 	for (i = 0; i < devtype->num_regs; i++) {
-		reg = pdata->led_control[i];
-		WARN_ON(reg >= (1 << 24));
-		ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg);
+		ret = mc13xxx_reg_write(mcdev, leds->devtype->ledctrl_base + i,
+					pdata->led_control[i]);
 		if (ret)
 			return ret;
 	}
 
-	for (i = 0; i < num_leds; i++) {
+	for (i = 0; i < leds->num_leds; i++) {
 		const char *name, *trig;
 
 		ret = -EINVAL;
@@ -180,30 +244,29 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
 		trig = pdata->led[i].default_trigger;
 
 		if ((id > devtype->led_max) || (id < devtype->led_min)) {
-			dev_err(&pdev->dev, "Invalid ID %i\n", id);
+			dev_err(dev, "Invalid ID %i\n", id);
 			break;
 		}
 
 		if (init_led & (1 << id)) {
-			dev_warn(&pdev->dev,
-				 "LED %i already initialized\n", id);
+			dev_warn(dev, "LED %i already initialized\n", id);
 			break;
 		}
 
 		init_led |= 1 << id;
 		leds->led[i].id = id;
-		leds->led[i].master = mcdev;
+		leds->led[i].leds = leds;
 		leds->led[i].cdev.name = name;
 		leds->led[i].cdev.default_trigger = trig;
+		leds->led[i].cdev.flags = LED_CORE_SUSPENDRESUME;
 		leds->led[i].cdev.brightness_set = mc13xxx_led_set;
-		leds->led[i].cdev.brightness = LED_OFF;
+		leds->led[i].cdev.max_brightness = mc13xxx_max_brightness(id);
 
 		INIT_WORK(&leds->led[i].work, mc13xxx_led_work);
 
-		ret = led_classdev_register(pdev->dev.parent,
-					    &leds->led[i].cdev);
+		ret = led_classdev_register(dev->parent, &leds->led[i].cdev);
 		if (ret) {
-			dev_err(&pdev->dev, "Failed to register LED %i\n", id);
+			dev_err(dev, "Failed to register LED %i\n", id);
 			break;
 		}
 	}
@@ -219,7 +282,6 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
 
 static int mc13xxx_led_remove(struct platform_device *pdev)
 {
-	struct mc13xxx *mcdev = dev_get_drvdata(pdev->dev.parent);
 	struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
 	int i;
 
@@ -228,9 +290,6 @@ static int mc13xxx_led_remove(struct platform_device *pdev)
 		cancel_work_sync(&leds->led[i].work);
 	}
 
-	for (i = 0; i < leds->devtype->num_regs; i++)
-		mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0);
-
 	return 0;
 }
 
@@ -238,17 +297,27 @@ static const struct mc13xxx_led_devtype mc13783_led_devtype = {
 	.led_min	= MC13783_LED_MD,
 	.led_max	= MC13783_LED_B3,
 	.num_regs	= 6,
+	.ledctrl_base	= 51,
 };
 
 static const struct mc13xxx_led_devtype mc13892_led_devtype = {
 	.led_min	= MC13892_LED_MD,
 	.led_max	= MC13892_LED_B,
 	.num_regs	= 4,
+	.ledctrl_base	= 51,
+};
+
+static const struct mc13xxx_led_devtype mc34708_led_devtype = {
+	.led_min	= MC34708_LED_R,
+	.led_max	= MC34708_LED_G,
+	.num_regs	= 1,
+	.ledctrl_base	= 54,
 };
 
 static const struct platform_device_id mc13xxx_led_id_table[] = {
 	{ "mc13783-led", (kernel_ulong_t)&mc13783_led_devtype, },
 	{ "mc13892-led", (kernel_ulong_t)&mc13892_led_devtype, },
+	{ "mc34708-led", (kernel_ulong_t)&mc34708_led_devtype, },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, mc13xxx_led_id_table);
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index 2f9f141084ba..e97f443a6e07 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index c7a4230233ea..efa625883c83 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -23,7 +23,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
index 98cae529373f..c9d906098466 100644
--- a/drivers/leds/leds-ot200.c
+++ b/drivers/leds/leds-ot200.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/leds.h>
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 605047428b5a..dd1787368fb1 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/fb.h>
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 98174e7240ee..28988b7b4fab 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -12,7 +12,6 @@
 */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 5b8f938a8d73..2eb3ef62962b 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -63,7 +63,7 @@ MODULE_LICENSE("GPL");
 /*
  * PCI ID of the Intel ICH7 LPC Device within which the GPIO block lives.
  */
-static DEFINE_PCI_DEVICE_TABLE(ich7_lpc_pci_id) = {
+static const struct pci_device_id ich7_lpc_pci_id[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30) },
@@ -78,7 +78,7 @@ static int __init ss4200_led_dmi_callback(const struct dmi_system_id *id)
 	return 1;
 }
 
-static bool __initdata nodetect;
+static bool nodetect;
 module_param_named(nodetect, nodetect, bool, 0);
 MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
 
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index 0a1a13f3a6a5..e72c974142d0 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/leds.h>
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 3f75fd22fd49..4133ffe29015 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/err.h>
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
index 118335eccc56..1c3ee9fcaf34 100644
--- a/drivers/leds/trigger/ledtrig-cpu.c
+++ b/drivers/leds/trigger/ledtrig-cpu.c
@@ -26,6 +26,7 @@
 #include <linux/percpu.h>
 #include <linux/syscore_ops.h>
 #include <linux/rwsem.h>
+#include <linux/cpu.h>
 #include "../leds.h"
 
 #define MAX_NAME_LEN	8
@@ -92,6 +93,26 @@ static struct syscore_ops ledtrig_cpu_syscore_ops = {
 	.resume		= ledtrig_cpu_syscore_resume,
 };
 
+static int ledtrig_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		ledtrig_cpu(CPU_LED_START);
+		break;
+	case CPU_DYING:
+		ledtrig_cpu(CPU_LED_STOP);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+
+static struct notifier_block ledtrig_cpu_nb = {
+	.notifier_call = ledtrig_cpu_notify,
+};
+
 static int __init ledtrig_cpu_init(void)
 {
 	int cpu;
@@ -113,6 +134,7 @@ static int __init ledtrig_cpu_init(void)
 	}
 
 	register_syscore_ops(&ledtrig_cpu_syscore_ops);
+	register_cpu_notifier(&ledtrig_cpu_nb);
 
 	pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n");
 
@@ -124,6 +146,8 @@ static void __exit ledtrig_cpu_exit(void)
 {
 	int cpu;
 
+	unregister_cpu_notifier(&ledtrig_cpu_nb);
+
 	for_each_possible_cpu(cpu) {
 		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index bfb39bb56ef1..4becb7782200 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -887,7 +887,7 @@ void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
  * _PAGE_ACCESSED then we can put a read-only PTE entry in immediately, and if
  * they set _PAGE_DIRTY then we can put a writable PTE entry in immediately.
  */
-static void do_set_pte(struct lg_cpu *cpu, int idx,
+static void do_guest_set_pte(struct lg_cpu *cpu, int idx,
 		       unsigned long vaddr, pte_t gpte)
 {
 	/* Look up the matching shadow page directory entry. */
@@ -960,13 +960,13 @@ void guest_set_pte(struct lg_cpu *cpu,
 		unsigned int i;
 		for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++)
 			if (cpu->lg->pgdirs[i].pgdir)
-				do_set_pte(cpu, i, vaddr, gpte);
+				do_guest_set_pte(cpu, i, vaddr, gpte);
 	} else {
 		/* Is this page table one we have a shadow for? */
 		int pgdir = find_pgdir(cpu->lg, gpgdir);
 		if (pgdir != ARRAY_SIZE(cpu->lg->pgdirs))
 			/* If so, do the update. */
-			do_set_pte(cpu, pgdir, vaddr, gpte);
+			do_guest_set_pte(cpu, pgdir, vaddr, gpte);
 	}
 }
 
diff --git a/drivers/mcb/Kconfig b/drivers/mcb/Kconfig
new file mode 100644
index 000000000000..44c82d68c563
--- /dev/null
+++ b/drivers/mcb/Kconfig
@@ -0,0 +1,15 @@
+#
+# MEN Chameleon Bus (MCB) support
+#
+
+menuconfig MCB
+	   tristate "MCB support"
+	   default m
+	   help
+
+	   The MCB (MEN Chameleon Bus) is a Bus specific to MEN Mikroelektronik
+	   FPGA based devices. It is used to identify MCB based IP-Cores within
+	   an FPGA and provide the necessary framework for instantiating drivers
+	   for these devices.
+
+	   If build as a module, the module is called mcb.ko
diff --git a/drivers/mcb/Makefile b/drivers/mcb/Makefile
new file mode 100644
index 000000000000..2d9a751e93bd
--- /dev/null
+++ b/drivers/mcb/Makefile
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_MCB) += mcb.o
+
+mcb-y += mcb-core.o
+mcb-y += mcb-parse.o
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
new file mode 100644
index 000000000000..bbe12932d404
--- /dev/null
+++ b/drivers/mcb/mcb-core.c
@@ -0,0 +1,414 @@
+/*
+ * MEN Chameleon Bus.
+ *
+ * Copyright (C) 2013 MEN Mikroelektronik GmbH (www.men.de)
+ * Author: Johannes Thumshirn <johannes.thumshirn@men.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; version 2 of the License.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/idr.h>
+#include <linux/mcb.h>
+
+static DEFINE_IDA(mcb_ida);
+
+static const struct mcb_device_id *mcb_match_id(const struct mcb_device_id *ids,
+						struct mcb_device *dev)
+{
+	if (ids) {
+		while (ids->device) {
+			if (ids->device == dev->id)
+				return ids;
+			ids++;
+		}
+	}
+
+	return NULL;
+}
+
+static int mcb_match(struct device *dev, struct device_driver *drv)
+{
+	struct mcb_driver *mdrv = to_mcb_driver(drv);
+	struct mcb_device *mdev = to_mcb_device(dev);
+	const struct mcb_device_id *found_id;
+
+	found_id = mcb_match_id(mdrv->id_table, mdev);
+	if (found_id)
+		return 1;
+
+	return 0;
+}
+
+static int mcb_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct mcb_device *mdev = to_mcb_device(dev);
+	int ret;
+
+	ret = add_uevent_var(env, "MODALIAS=mcb:16z%03d", mdev->id);
+	if (ret)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int mcb_probe(struct device *dev)
+{
+	struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
+	struct mcb_device *mdev = to_mcb_device(dev);
+	const struct mcb_device_id *found_id;
+
+	found_id = mcb_match_id(mdrv->id_table, mdev);
+	if (!found_id)
+		return -ENODEV;
+
+	return mdrv->probe(mdev, found_id);
+}
+
+static int mcb_remove(struct device *dev)
+{
+	struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
+	struct mcb_device *mdev = to_mcb_device(dev);
+
+	mdrv->remove(mdev);
+
+	put_device(&mdev->dev);
+
+	return 0;
+}
+
+static void mcb_shutdown(struct device *dev)
+{
+	struct mcb_device *mdev = to_mcb_device(dev);
+	struct mcb_driver *mdrv = mdev->driver;
+
+	if (mdrv && mdrv->shutdown)
+		mdrv->shutdown(mdev);
+}
+
+static struct bus_type mcb_bus_type = {
+	.name = "mcb",
+	.match = mcb_match,
+	.uevent = mcb_uevent,
+	.probe = mcb_probe,
+	.remove = mcb_remove,
+	.shutdown = mcb_shutdown,
+};
+
+/**
+ * __mcb_register_driver() - Register a @mcb_driver at the system
+ * @drv: The @mcb_driver
+ * @owner: The @mcb_driver's module
+ * @mod_name: The name of the @mcb_driver's module
+ *
+ * Register a @mcb_driver at the system. Perform some sanity checks, if
+ * the .probe and .remove methods are provided by the driver.
+ */
+int __mcb_register_driver(struct mcb_driver *drv, struct module *owner,
+			const char *mod_name)
+{
+	if (!drv->probe || !drv->remove)
+		return -EINVAL;
+
+	drv->driver.owner = owner;
+	drv->driver.bus = &mcb_bus_type;
+	drv->driver.mod_name = mod_name;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(__mcb_register_driver);
+
+/**
+ * mcb_unregister_driver() - Unregister a @mcb_driver from the system
+ * @drv: The @mcb_driver
+ *
+ * Unregister a @mcb_driver from the system.
+ */
+void mcb_unregister_driver(struct mcb_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(mcb_unregister_driver);
+
+static void mcb_release_dev(struct device *dev)
+{
+	struct mcb_device *mdev = to_mcb_device(dev);
+
+	mcb_bus_put(mdev->bus);
+	kfree(mdev);
+}
+
+/**
+ * mcb_device_register() - Register a mcb_device
+ * @bus: The @mcb_bus of the device
+ * @dev: The @mcb_device
+ *
+ * Register a specific @mcb_device at a @mcb_bus and the system itself.
+ */
+int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev)
+{
+	int ret;
+	int device_id;
+
+	device_initialize(&dev->dev);
+	dev->dev.bus = &mcb_bus_type;
+	dev->dev.parent = bus->dev.parent;
+	dev->dev.release = mcb_release_dev;
+
+	device_id = dev->id;
+	dev_set_name(&dev->dev, "mcb%d-16z%03d-%d:%d:%d",
+		bus->bus_nr, device_id, dev->inst, dev->group, dev->var);
+
+	ret = device_add(&dev->dev);
+	if (ret < 0) {
+		pr_err("Failed registering device 16z%03d on bus mcb%d (%d)\n",
+			device_id, bus->bus_nr, ret);
+		goto out;
+	}
+
+	return 0;
+
+out:
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mcb_device_register);
+
+/**
+ * mcb_alloc_bus() - Allocate a new @mcb_bus
+ *
+ * Allocate a new @mcb_bus.
+ */
+struct mcb_bus *mcb_alloc_bus(void)
+{
+	struct mcb_bus *bus;
+	int bus_nr;
+
+	bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL);
+	if (!bus)
+		return NULL;
+
+	bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL);
+	if (bus_nr < 0) {
+		kfree(bus);
+		return ERR_PTR(bus_nr);
+	}
+
+	INIT_LIST_HEAD(&bus->children);
+	bus->bus_nr = bus_nr;
+
+	return bus;
+}
+EXPORT_SYMBOL_GPL(mcb_alloc_bus);
+
+static int __mcb_devices_unregister(struct device *dev, void *data)
+{
+	device_unregister(dev);
+	return 0;
+}
+
+static void mcb_devices_unregister(struct mcb_bus *bus)
+{
+	bus_for_each_dev(&mcb_bus_type, NULL, NULL, __mcb_devices_unregister);
+}
+/**
+ * mcb_release_bus() - Free a @mcb_bus
+ * @bus: The @mcb_bus to release
+ *
+ * Release an allocated @mcb_bus from the system.
+ */
+void mcb_release_bus(struct mcb_bus *bus)
+{
+	mcb_devices_unregister(bus);
+
+	ida_simple_remove(&mcb_ida, bus->bus_nr);
+
+	kfree(bus);
+}
+EXPORT_SYMBOL_GPL(mcb_release_bus);
+
+/**
+ * mcb_bus_put() - Increment refcnt
+ * @bus: The @mcb_bus
+ *
+ * Get a @mcb_bus' ref
+ */
+struct mcb_bus *mcb_bus_get(struct mcb_bus *bus)
+{
+	if (bus)
+		get_device(&bus->dev);
+
+	return bus;
+}
+EXPORT_SYMBOL_GPL(mcb_bus_get);
+
+/**
+ * mcb_bus_put() - Decrement refcnt
+ * @bus: The @mcb_bus
+ *
+ * Release a @mcb_bus' ref
+ */
+void mcb_bus_put(struct mcb_bus *bus)
+{
+	if (bus)
+		put_device(&bus->dev);
+}
+EXPORT_SYMBOL_GPL(mcb_bus_put);
+
+/**
+ * mcb_alloc_dev() - Allocate a device
+ * @bus: The @mcb_bus the device is part of
+ *
+ * Allocate a @mcb_device and add bus.
+ */
+struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus)
+{
+	struct mcb_device *dev;
+
+	dev = kzalloc(sizeof(struct mcb_device), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	INIT_LIST_HEAD(&dev->bus_list);
+	dev->bus = bus;
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(mcb_alloc_dev);
+
+/**
+ * mcb_free_dev() - Free @mcb_device
+ * @dev: The device to free
+ *
+ * Free a @mcb_device
+ */
+void mcb_free_dev(struct mcb_device *dev)
+{
+	kfree(dev);
+}
+EXPORT_SYMBOL_GPL(mcb_free_dev);
+
+static int __mcb_bus_add_devices(struct device *dev, void *data)
+{
+	struct mcb_device *mdev = to_mcb_device(dev);
+	int retval;
+
+	if (mdev->is_added)
+		return 0;
+
+	retval = device_attach(dev);
+	if (retval < 0)
+		dev_err(dev, "Error adding device (%d)\n", retval);
+
+	mdev->is_added = true;
+
+	return 0;
+}
+
+static int __mcb_bus_add_child(struct device *dev, void *data)
+{
+	struct mcb_device *mdev = to_mcb_device(dev);
+	struct mcb_bus *child;
+
+	BUG_ON(!mdev->is_added);
+	child = mdev->subordinate;
+
+	if (child)
+		mcb_bus_add_devices(child);
+
+	return 0;
+}
+
+/**
+ * mcb_bus_add_devices() - Add devices in the bus' internal device list
+ * @bus: The @mcb_bus we add the devices
+ *
+ * Add devices in the bus' internal device list to the system.
+ */
+void mcb_bus_add_devices(const struct mcb_bus *bus)
+{
+	bus_for_each_dev(&mcb_bus_type, NULL, NULL, __mcb_bus_add_devices);
+	bus_for_each_dev(&mcb_bus_type, NULL, NULL, __mcb_bus_add_child);
+
+}
+EXPORT_SYMBOL_GPL(mcb_bus_add_devices);
+
+/**
+ * mcb_request_mem() - Request memory
+ * @dev: The @mcb_device the memory is for
+ * @name: The name for the memory reference.
+ *
+ * Request memory for a @mcb_device. If @name is NULL the driver name will
+ * be used.
+ */
+struct resource *mcb_request_mem(struct mcb_device *dev, const char *name)
+{
+	struct resource *mem;
+	u32 size;
+
+	if (!name)
+		name = dev->dev.driver->name;
+
+	size = resource_size(&dev->mem);
+
+	mem = request_mem_region(dev->mem.start, size, name);
+	if (!mem)
+		return ERR_PTR(-EBUSY);
+
+	return mem;
+}
+EXPORT_SYMBOL_GPL(mcb_request_mem);
+
+/**
+ * mcb_release_mem() - Release memory requested by device
+ * @dev: The @mcb_device that requested the memory
+ *
+ * Release memory that was prior requested via @mcb_request_mem().
+ */
+void mcb_release_mem(struct resource *mem)
+{
+	u32 size;
+
+	size = resource_size(mem);
+	release_mem_region(mem->start, size);
+}
+EXPORT_SYMBOL_GPL(mcb_release_mem);
+
+/**
+ * mcb_get_irq() - Get device's IRQ number
+ * @dev: The @mcb_device the IRQ is for
+ *
+ * Get the IRQ number of a given @mcb_device.
+ */
+int mcb_get_irq(struct mcb_device *dev)
+{
+	struct resource *irq = &dev->irq;
+
+	return irq->start;
+}
+EXPORT_SYMBOL_GPL(mcb_get_irq);
+
+static int mcb_init(void)
+{
+	return bus_register(&mcb_bus_type);
+}
+
+static void mcb_exit(void)
+{
+	bus_unregister(&mcb_bus_type);
+}
+
+/* mcb must be initialized after PCI but before the chameleon drivers.
+ * That means we must use some initcall between subsys_initcall and
+ * device_initcall.
+ */
+fs_initcall(mcb_init);
+module_exit(mcb_exit);
+
+MODULE_DESCRIPTION("MEN Chameleon Bus Driver");
+MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h
new file mode 100644
index 000000000000..db22777d0ac8
--- /dev/null
+++ b/drivers/mcb/mcb-internal.h
@@ -0,0 +1,116 @@
+#ifndef __MCB_INTERNAL
+#define __MCB_INTERNAL
+
+#include <linux/types.h>
+
+#define CHAMELEON_FILENAME_LEN		12
+#define CHAMELEONV2_MAGIC		0xabce
+
+enum chameleon_descriptor_type {
+	CHAMELEON_DTYPE_GENERAL = 0x0,
+	CHAMELEON_DTYPE_BRIDGE = 0x1,
+	CHAMELEON_DTYPE_CPU = 0x2,
+	CHAMELEON_DTYPE_BAR = 0x3,
+	CHAMELEON_DTYPE_END = 0xf,
+};
+
+enum chameleon_bus_type {
+	CHAMELEON_BUS_WISHBONE,
+	CHAMELEON_BUS_AVALON,
+	CHAMELEON_BUS_LPC,
+	CHAMELEON_BUS_ISA,
+};
+
+/**
+ * struct chameleon_fpga_header
+ *
+ * @revision:	Revison of Chameleon table in FPGA
+ * @model:	Chameleon table model ASCII char
+ * @minor:	Revision minor
+ * @bus_type:	Bus type (usually %CHAMELEON_BUS_WISHBONE)
+ * @magic:	Chameleon header magic number (0xabce for version 2)
+ * @reserved:	Reserved
+ * @filename:	Filename of FPGA bitstream
+ */
+struct chameleon_fpga_header {
+	u8 revision;
+	char model;
+	u8 minor;
+	u8 bus_type;
+	u16 magic;
+	u16 reserved;
+	/* This one has no '\0' at the end!!! */
+	char filename[CHAMELEON_FILENAME_LEN];
+} __packed;
+#define HEADER_MAGIC_OFFSET 0x4
+
+/**
+ * struct chameleon_gdd - Chameleon General Device Descriptor
+ *
+ * @irq:	the position in the FPGA's IRQ controller vector
+ * @rev:	the revision of the variant's implementation
+ * @var:	the variant of the IP core
+ * @dev:	the device  the IP core is
+ * @dtype:	device descriptor type
+ * @bar:	BAR offset that must be added to module offset
+ * @inst:	the instance number of the device, 0 is first instance
+ * @group:	the group the device belongs to (0 = no group)
+ * @reserved:	reserved
+ * @offset:	beginning of the address window of desired module
+ * @size:	size of the module's address window
+ */
+struct chameleon_gdd {
+	__le32 reg1;
+	__le32 reg2;
+	__le32 offset;
+	__le32 size;
+
+} __packed;
+
+/* GDD Register 1 fields */
+#define GDD_IRQ(x) ((x) & 0x1f)
+#define GDD_REV(x) (((x) >> 5) & 0x3f)
+#define GDD_VAR(x) (((x) >> 11) & 0x3f)
+#define GDD_DEV(x) (((x) >> 18) & 0x3ff)
+#define GDD_DTY(x) (((x) >> 28) & 0xf)
+
+/* GDD Register 2 fields */
+#define GDD_BAR(x) ((x) & 0x7)
+#define GDD_INS(x) (((x) >> 3) & 0x3f)
+#define GDD_GRP(x) (((x) >> 9) & 0x3f)
+
+/**
+ * struct chameleon_bdd - Chameleon Bridge Device Descriptor
+ *
+ * @irq:	the position in the FPGA's IRQ controller vector
+ * @rev:	the revision of the variant's implementation
+ * @var:	the variant of the IP core
+ * @dev:	the device  the IP core is
+ * @dtype:	device descriptor type
+ * @bar:	BAR offset that must be added to module offset
+ * @inst:	the instance number of the device, 0 is first instance
+ * @dbar:	destination bar from the bus _behind_ the bridge
+ * @chamoff:	offset within the BAR of the source bus
+ * @offset:
+ * @size:
+ */
+struct chameleon_bdd {
+	unsigned int irq:6;
+	unsigned int rev:6;
+	unsigned int var:6;
+	unsigned int dev:10;
+	unsigned int dtype:4;
+	unsigned int bar:3;
+	unsigned int inst:6;
+	unsigned int dbar:3;
+	unsigned int group:6;
+	unsigned int reserved:14;
+	u32 chamoff;
+	u32 offset;
+	u32 size;
+} __packed;
+
+int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
+			  void __iomem *base);
+
+#endif
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
new file mode 100644
index 000000000000..d1278b5f3028
--- /dev/null
+++ b/drivers/mcb/mcb-parse.c
@@ -0,0 +1,159 @@
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/mcb.h>
+
+#include "mcb-internal.h"
+
+struct mcb_parse_priv {
+	phys_addr_t mapbase;
+	void __iomem *base;
+};
+
+#define for_each_chameleon_cell(dtype, p)	\
+	for ((dtype) = get_next_dtype((p));	\
+	     (dtype) != CHAMELEON_DTYPE_END;	\
+	     (dtype) = get_next_dtype((p)))
+
+static inline uint32_t get_next_dtype(void __iomem *p)
+{
+	uint32_t dtype;
+
+	dtype = readl(p);
+	return dtype >> 28;
+}
+
+static int chameleon_parse_bdd(struct mcb_bus *bus,
+			phys_addr_t mapbase,
+			void __iomem *base)
+{
+	return 0;
+}
+
+static int chameleon_parse_gdd(struct mcb_bus *bus,
+			phys_addr_t mapbase,
+			void __iomem *base)
+{
+	struct chameleon_gdd __iomem *gdd =
+		(struct chameleon_gdd __iomem *) base;
+	struct mcb_device *mdev;
+	u32 offset;
+	u32 size;
+	int ret;
+	__le32 reg1;
+	__le32 reg2;
+
+	mdev = mcb_alloc_dev(bus);
+	if (!mdev)
+		return -ENOMEM;
+
+	reg1 = readl(&gdd->reg1);
+	reg2 = readl(&gdd->reg2);
+	offset = readl(&gdd->offset);
+	size = readl(&gdd->size);
+
+	mdev->id = GDD_DEV(reg1);
+	mdev->rev = GDD_REV(reg1);
+	mdev->var = GDD_VAR(reg1);
+	mdev->bar = GDD_BAR(reg1);
+	mdev->group = GDD_GRP(reg2);
+	mdev->inst = GDD_INS(reg2);
+
+	pr_debug("Found a 16z%03d\n", mdev->id);
+
+	mdev->irq.start = GDD_IRQ(reg1);
+	mdev->irq.end = GDD_IRQ(reg1);
+	mdev->irq.flags = IORESOURCE_IRQ;
+
+	mdev->mem.start = mapbase + offset;
+	mdev->mem.end = mdev->mem.start + size - 1;
+	mdev->mem.flags = IORESOURCE_MEM;
+
+	mdev->is_added = false;
+
+	ret = mcb_device_register(bus, mdev);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	mcb_free_dev(mdev);
+
+	return ret;
+}
+
+int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
+			void __iomem *base)
+{
+	char __iomem *p = base;
+	struct chameleon_fpga_header *header;
+	uint32_t dtype;
+	int num_cells = 0;
+	int ret = 0;
+	u32 hsize;
+
+	hsize = sizeof(struct chameleon_fpga_header);
+
+	header = kzalloc(hsize, GFP_KERNEL);
+	if (!header)
+		return -ENOMEM;
+
+	/* Extract header information */
+	memcpy_fromio(header, p, hsize);
+	/* We only support chameleon v2 at the moment */
+	header->magic = le16_to_cpu(header->magic);
+	if (header->magic != CHAMELEONV2_MAGIC) {
+		pr_err("Unsupported chameleon version 0x%x\n",
+				header->magic);
+		kfree(header);
+		return -ENODEV;
+	}
+	p += hsize;
+
+	pr_debug("header->revision = %d\n", header->revision);
+	pr_debug("header->model = 0x%x ('%c')\n", header->model,
+		header->model);
+	pr_debug("header->minor = %d\n", header->minor);
+	pr_debug("header->bus_type = 0x%x\n", header->bus_type);
+
+
+	pr_debug("header->magic = 0x%x\n", header->magic);
+	pr_debug("header->filename = \"%.*s\"\n", CHAMELEON_FILENAME_LEN,
+		header->filename);
+
+	for_each_chameleon_cell(dtype, p) {
+		switch (dtype) {
+		case CHAMELEON_DTYPE_GENERAL:
+			ret = chameleon_parse_gdd(bus, mapbase, p);
+			if (ret < 0)
+				goto out;
+			p += sizeof(struct chameleon_gdd);
+			break;
+		case CHAMELEON_DTYPE_BRIDGE:
+			chameleon_parse_bdd(bus, mapbase, p);
+			p += sizeof(struct chameleon_bdd);
+			break;
+		case CHAMELEON_DTYPE_END:
+			break;
+		default:
+			pr_err("Invalid chameleon descriptor type 0x%x\n",
+				dtype);
+			return -EINVAL;
+		}
+		num_cells++;
+	}
+
+	if (num_cells == 0)
+		num_cells = -EINVAL;
+
+	kfree(header);
+	return num_cells;
+
+out:
+	kfree(header);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(chameleon_parse_cells);
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c
index 1e018e986610..0e385e40909e 100644
--- a/drivers/md/dm-cache-policy-mq.c
+++ b/drivers/md/dm-cache-policy-mq.c
@@ -872,7 +872,7 @@ static void mq_destroy(struct dm_cache_policy *p)
 {
 	struct mq_policy *mq = to_mq_policy(p);
 
-	kfree(mq->table);
+	vfree(mq->table);
 	epool_exit(&mq->cache_pool);
 	epool_exit(&mq->pre_cache_pool);
 	kfree(mq);
@@ -1245,7 +1245,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
 
 	mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16);
 	mq->hash_bits = ffs(mq->nr_buckets) - 1;
-	mq->table = kzalloc(sizeof(*mq->table) * mq->nr_buckets, GFP_KERNEL);
+	mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets);
 	if (!mq->table)
 		goto bad_alloc_table;
 
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index 08d9a207259a..b428c0ae63d5 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -66,7 +66,7 @@ static int dm_ulog_sendto_server(struct dm_ulog_request *tfr)
 	msg->seq = tfr->seq;
 	msg->len = sizeof(struct dm_ulog_request) + tfr->data_size;
 
-	r = cn_netlink_send(msg, 0, gfp_any());
+	r = cn_netlink_send(msg, 0, 0, gfp_any());
 
 	return r;
 }
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
index b2c8c3439fea..ea272bcb38df 100644
--- a/drivers/media/pci/cx18/cx18-alsa-main.c
+++ b/drivers/media/pci/cx18/cx18-alsa-main.c
@@ -145,11 +145,12 @@ static int snd_cx18_init(struct v4l2_device *v4l2_dev)
 	/* This is a no-op for us.  We'll use the cx->instance */
 
 	/* (2) Create a card instance */
-	ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
-			      SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
-			      THIS_MODULE, 0, &sc);
+	ret = snd_card_new(&cx->pci_dev->dev,
+			   SNDRV_DEFAULT_IDX1, /* use first available id */
+			   SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+			   THIS_MODULE, 0, &sc);
 	if (ret) {
-		CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+		CX18_ALSA_ERR("%s: snd_card_new() failed with err %d\n",
 			      __func__, ret);
 		goto err_exit;
 	}
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
index c6c9bd58f8be..554798dcedd0 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -489,7 +489,8 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
 		return NULL;
 	}
 
-	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+	err = snd_card_new(&dev->pci->dev,
+			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
 			THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
 	if (err < 0)
 		goto error;
@@ -500,8 +501,6 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
 	chip->card = card;
 	spin_lock_init(&chip->lock);
 
-	snd_card_set_dev(card, &dev->pci->dev);
-
 	err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
 	if (err < 0)
 		goto error;
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index b1e08c3e55cd..2dd5bcaa7e53 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -645,8 +645,9 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
 		return -ENOENT;
 	}
 
-	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
-			sizeof(struct cx25821_audio_dev), &card);
+	err = snd_card_new(&dev->pci->dev, index[devno], id[devno],
+			   THIS_MODULE,
+			   sizeof(struct cx25821_audio_dev), &card);
 	if (err < 0) {
 		pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
 			__func__);
@@ -682,8 +683,6 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
 		goto error;
 	}
 
-	snd_card_set_dev(card, &chip->pci->dev);
-
 	strcpy(card->shortname, "cx25821");
 	sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
 		chip->iobase, chip->irq);
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index d014206e7176..a72579a9f67f 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -852,8 +852,6 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
 	chip->irq = pci->irq;
 	synchronize_irq(chip->irq);
 
-	snd_card_set_dev(card, &pci->dev);
-
 	*rchip = chip;
 	*core_ptr = core;
 
@@ -876,8 +874,8 @@ static int cx88_audio_initdev(struct pci_dev *pci,
 		return (-ENOENT);
 	}
 
-	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
-			      sizeof(snd_cx88_card_t), &card);
+	err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
+			   sizeof(snd_cx88_card_t), &card);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
index e970cface70e..39b52929755a 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -145,11 +145,12 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
 	/* This is a no-op for us.  We'll use the itv->instance */
 
 	/* (2) Create a card instance */
-	ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
-			      SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
-			      THIS_MODULE, 0, &sc);
+	ret = snd_card_new(&itv->pdev->dev,
+			   SNDRV_DEFAULT_IDX1, /* use first available id */
+			   SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+			   THIS_MODULE, 0, &sc);
 	if (ret) {
-		IVTV_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+		IVTV_ALSA_ERR("%s: snd_card_new() failed with err %d\n",
 			      __func__, ret);
 		goto err_exit;
 	}
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index dd67c8a400cc..e04a4d5d6672 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -1072,8 +1072,8 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
 	if (!enable[devnum])
 		return -ENODEV;
 
-	err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
-			      sizeof(snd_card_saa7134_t), &card);
+	err = snd_card_new(&dev->pci->dev, index[devnum], id[devnum],
+			   THIS_MODULE, sizeof(snd_card_saa7134_t), &card);
 	if (err < 0)
 		return err;
 
@@ -1115,8 +1115,6 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
 	if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
 		goto __nodev;
 
-	snd_card_set_dev(card, &chip->pci->dev);
-
 	/* End of "creation" */
 
 	strcpy(card->shortname, "SAA7134");
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index 81a1d971d797..9b925874d392 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -665,8 +665,8 @@ static int cx231xx_audio_init(struct cx231xx *dev)
 	cx231xx_info("cx231xx-audio.c: probing for cx231xx "
 		     "non standard usbaudio\n");
 
-	err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE,
-			      0, &card);
+	err = snd_card_new(&dev->udev->dev, index[devnr], "Cx231xx Audio",
+			   THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
@@ -682,7 +682,6 @@ static int cx231xx_audio_init(struct cx231xx *dev)
 	pcm->info_flags = 0;
 	pcm->private_data = dev;
 	strcpy(pcm->name, "Conexant cx231xx Capture");
-	snd_card_set_dev(card, &dev->udev->dev);
 	strcpy(card->driver, "Cx231xx-Audio");
 	strcpy(card->shortname, "Cx231xx Audio");
 	strcpy(card->longname, "Conexant cx231xx Audio");
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 05e9bd11a3ff..1a28897af183 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -900,8 +900,8 @@ static int em28xx_audio_init(struct em28xx *dev)
 	printk(KERN_INFO
 	       "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n");
 
-	err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
-			      &card);
+	err = snd_card_new(&dev->udev->dev, index[devnr], "Em28xx Audio",
+			   THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
@@ -918,7 +918,6 @@ static int em28xx_audio_init(struct em28xx *dev)
 	pcm->private_data = dev;
 	strcpy(pcm->name, "Empia 28xx Capture");
 
-	snd_card_set_dev(card, &dev->udev->dev);
 	strcpy(card->driver, "Em28xx-Audio");
 	strcpy(card->shortname, "Em28xx Audio");
 	strcpy(card->longname, "Empia Em28xx Audio");
diff --git a/drivers/media/usb/stk1160/stk1160-ac97.c b/drivers/media/usb/stk1160/stk1160-ac97.c
index c8583c262c3d..c46c8be89602 100644
--- a/drivers/media/usb/stk1160/stk1160-ac97.c
+++ b/drivers/media/usb/stk1160/stk1160-ac97.c
@@ -98,13 +98,11 @@ int stk1160_ac97_register(struct stk1160 *dev)
 	 * Just want a card to access ac96 controls,
 	 * the actual capture interface will be handled by snd-usb-audio
 	 */
-	rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			      THIS_MODULE, 0, &card);
+	rc = snd_card_new(dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			  THIS_MODULE, 0, &card);
 	if (rc < 0)
 		return rc;
 
-	snd_card_set_dev(card, dev->dev);
-
 	/* TODO: I'm not sure where should I get these names :-( */
 	snprintf(card->shortname, sizeof(card->shortname),
 		 "stk1160-mixer");
diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c
index 3f3e141f70fb..dd8fe100590f 100644
--- a/drivers/media/usb/tlg2300/pd-alsa.c
+++ b/drivers/media/usb/tlg2300/pd-alsa.c
@@ -300,7 +300,8 @@ int poseidon_audio_init(struct poseidon *p)
 	struct snd_pcm *pcm;
 	int ret;
 
-	ret = snd_card_create(-1, "Telegent", THIS_MODULE, 0, &card);
+	ret = snd_card_new(&p->interface->dev, -1, "Telegent",
+			   THIS_MODULE, 0, &card);
 	if (ret != 0)
 		return ret;
 
diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c
index 813c1ec53608..3239cd62e452 100644
--- a/drivers/media/usb/tm6000/tm6000-alsa.c
+++ b/drivers/media/usb/tm6000/tm6000-alsa.c
@@ -431,7 +431,8 @@ static int tm6000_audio_init(struct tm6000_core *dev)
 	if (!enable[devnr])
 		return -ENOENT;
 
-	rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
+	rc = snd_card_new(&dev->udev->dev, index[devnr], "tm6000",
+			  THIS_MODULE, 0, &card);
 	if (rc < 0) {
 		snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
 		return rc;
@@ -445,7 +446,6 @@ static int tm6000_audio_init(struct tm6000_core *dev)
 		le16_to_cpu(dev->udev->descriptor.idVendor),
 		le16_to_cpu(dev->udev->descriptor.idProduct));
 	snd_component_add(card, component);
-	snd_card_set_dev(card, &dev->udev->dev);
 
 	chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
 	if (!chip) {
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 8f7a6a454a4c..6191968db8fa 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -733,7 +733,7 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
 		copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
 		put_user(kp->pending, &up->pending) ||
 		put_user(kp->sequence, &up->sequence) ||
-		put_compat_timespec(&kp->timestamp, &up->timestamp) ||
+		compat_put_timespec(&kp->timestamp, &up->timestamp) ||
 		put_user(kp->id, &up->id) ||
 		copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
 			return -EFAULT;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 33d3871d1e13..880be0782dd9 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -719,7 +719,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
 
 	/* get the associated scatterlist for this buffer */
 	sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
-	if (IS_ERR_OR_NULL(sgt)) {
+	if (IS_ERR(sgt)) {
 		pr_err("Error getting dmabuf scatterlist\n");
 		return -EINVAL;
 	}
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 29a11db365bc..c59e9c96e86d 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -7,6 +7,17 @@ menuconfig MEMORY
 
 if MEMORY
 
+config TI_AEMIF
+	tristate "Texas Instruments AEMIF driver"
+	depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
+	help
+	  This driver is for the AEMIF module available in Texas Instruments
+	  SoCs. AEMIF stands for Asynchronous External Memory Interface and
+	  is intended to provide a glue-less interface to a variety of
+	  asynchronuous memory devices like ASRAM, NOR and NAND memory. A total
+	  of 256M bytes of any of these memories can be accessed at a given
+	  time via four chip selects with 64M byte access per chip select.
+
 config TI_EMIF
 	tristate "Texas Instruments EMIF driver"
 	depends on ARCH_OMAP2PLUS
@@ -50,4 +61,8 @@ config TEGRA30_MC
 	  analysis, especially for IOMMU/SMMU(System Memory Management
 	  Unit) module.
 
+config FSL_IFC
+	bool
+	depends on FSL_SOC
+
 endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 969d923dad93..71160a2b7313 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -5,7 +5,9 @@
 ifeq ($(CONFIG_DDR),y)
 obj-$(CONFIG_OF)		+= of_memory.o
 endif
+obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
+obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_MVEBU_DEVBUS)	+= mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)	+= tegra30-mc.o
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
new file mode 100644
index 000000000000..3d5d792d5cb2
--- /dev/null
+++ b/drivers/memory/fsl_ifc.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc
+ *
+ * Freescale Integrated Flash Controller
+ *
+ * Author: Dipen Dudhat <Dipen.Dudhat@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.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_ifc.h>
+#include <asm/prom.h>
+
+struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
+EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
+
+/*
+ * convert_ifc_address - convert the base address
+ * @addr_base:	base address of the memory bank
+ */
+unsigned int convert_ifc_address(phys_addr_t addr_base)
+{
+	return addr_base & CSPR_BA;
+}
+EXPORT_SYMBOL(convert_ifc_address);
+
+/*
+ * fsl_ifc_find - find IFC bank
+ * @addr_base:	base address of the memory bank
+ *
+ * This function walks IFC banks comparing "Base address" field of the CSPR
+ * registers with the supplied addr_base argument. When bases match this
+ * function returns bank number (starting with 0), otherwise it returns
+ * appropriate errno value.
+ */
+int fsl_ifc_find(phys_addr_t addr_base)
+{
+	int i = 0;
+
+	if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(fsl_ifc_ctrl_dev->regs->cspr_cs); i++) {
+		u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr);
+		if (cspr & CSPR_V && (cspr & CSPR_BA) ==
+				convert_ifc_address(addr_base))
+			return i;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(fsl_ifc_find);
+
+static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
+{
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+	/*
+	 * Clear all the common status and event registers
+	 */
+	if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER)
+		out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
+
+	/* enable all error and events */
+	out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN);
+
+	/* enable all error and event interrupts */
+	out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN);
+	out_be32(&ifc->cm_erattr0, 0x0);
+	out_be32(&ifc->cm_erattr1, 0x0);
+
+	return 0;
+}
+
+static int fsl_ifc_ctrl_remove(struct platform_device *dev)
+{
+	struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
+
+	free_irq(ctrl->nand_irq, ctrl);
+	free_irq(ctrl->irq, ctrl);
+
+	irq_dispose_mapping(ctrl->nand_irq);
+	irq_dispose_mapping(ctrl->irq);
+
+	iounmap(ctrl->regs);
+
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(ctrl);
+
+	return 0;
+}
+
+/*
+ * NAND events are split between an operational interrupt which only
+ * receives OPC, and an error interrupt that receives everything else,
+ * including non-NAND errors.  Whichever interrupt gets to it first
+ * records the status and wakes the wait queue.
+ */
+static DEFINE_SPINLOCK(nand_irq_lock);
+
+static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
+{
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	unsigned long flags;
+	u32 stat;
+
+	spin_lock_irqsave(&nand_irq_lock, flags);
+
+	stat = in_be32(&ifc->ifc_nand.nand_evter_stat);
+	if (stat) {
+		out_be32(&ifc->ifc_nand.nand_evter_stat, stat);
+		ctrl->nand_stat = stat;
+		wake_up(&ctrl->nand_wait);
+	}
+
+	spin_unlock_irqrestore(&nand_irq_lock, flags);
+
+	return stat;
+}
+
+static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
+{
+	struct fsl_ifc_ctrl *ctrl = data;
+
+	if (check_nand_stat(ctrl))
+		return IRQ_HANDLED;
+
+	return IRQ_NONE;
+}
+
+/*
+ * NOTE: This interrupt is used to report ifc events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
+{
+	struct fsl_ifc_ctrl *ctrl = data;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	u32 err_axiid, err_srcid, status, cs_err, err_addr;
+	irqreturn_t ret = IRQ_NONE;
+
+	/* read for chip select error */
+	cs_err = in_be32(&ifc->cm_evter_stat);
+	if (cs_err) {
+		dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
+				"any memory bank 0x%08X\n", cs_err);
+		/* clear the chip select error */
+		out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
+
+		/* read error attribute registers print the error information */
+		status = in_be32(&ifc->cm_erattr0);
+		err_addr = in_be32(&ifc->cm_erattr1);
+
+		if (status & IFC_CM_ERATTR0_ERTYP_READ)
+			dev_err(ctrl->dev, "Read transaction error"
+				"CM_ERATTR0 0x%08X\n", status);
+		else
+			dev_err(ctrl->dev, "Write transaction error"
+				"CM_ERATTR0 0x%08X\n", status);
+
+		err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
+					IFC_CM_ERATTR0_ERAID_SHIFT;
+		dev_err(ctrl->dev, "AXI ID of the error"
+					"transaction 0x%08X\n", err_axiid);
+
+		err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
+					IFC_CM_ERATTR0_ESRCID_SHIFT;
+		dev_err(ctrl->dev, "SRC ID of the error"
+					"transaction 0x%08X\n", err_srcid);
+
+		dev_err(ctrl->dev, "Transaction Address corresponding to error"
+					"ERADDR 0x%08X\n", err_addr);
+
+		ret = IRQ_HANDLED;
+	}
+
+	if (check_nand_stat(ctrl))
+		ret = IRQ_HANDLED;
+
+	return ret;
+}
+
+/*
+ * fsl_ifc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only.  The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+static int fsl_ifc_ctrl_probe(struct platform_device *dev)
+{
+	int ret = 0;
+
+
+	dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
+
+	fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
+	if (!fsl_ifc_ctrl_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
+
+	/* IOMAP the entire IFC region */
+	fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
+	if (!fsl_ifc_ctrl_dev->regs) {
+		dev_err(&dev->dev, "failed to get memory region\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* get the Controller level irq */
+	fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
+	if (fsl_ifc_ctrl_dev->irq == NO_IRQ) {
+		dev_err(&dev->dev, "failed to get irq resource "
+							"for IFC\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* get the nand machine irq */
+	fsl_ifc_ctrl_dev->nand_irq =
+			irq_of_parse_and_map(dev->dev.of_node, 1);
+
+	fsl_ifc_ctrl_dev->dev = &dev->dev;
+
+	ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
+	if (ret < 0)
+		goto err;
+
+	init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
+
+	ret = request_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_irq, IRQF_SHARED,
+			  "fsl-ifc", fsl_ifc_ctrl_dev);
+	if (ret != 0) {
+		dev_err(&dev->dev, "failed to install irq (%d)\n",
+			fsl_ifc_ctrl_dev->irq);
+		goto err_irq;
+	}
+
+	if (fsl_ifc_ctrl_dev->nand_irq) {
+		ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
+				0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
+		if (ret != 0) {
+			dev_err(&dev->dev, "failed to install irq (%d)\n",
+				fsl_ifc_ctrl_dev->nand_irq);
+			goto err_nandirq;
+		}
+	}
+
+	return 0;
+
+err_nandirq:
+	free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
+	irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
+err_irq:
+	free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
+	irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
+err:
+	return ret;
+}
+
+static const struct of_device_id fsl_ifc_match[] = {
+	{
+		.compatible = "fsl,ifc",
+	},
+	{},
+};
+
+static struct platform_driver fsl_ifc_ctrl_driver = {
+	.driver = {
+		.name	= "fsl-ifc",
+		.of_match_table = fsl_ifc_match,
+	},
+	.probe       = fsl_ifc_ctrl_probe,
+	.remove      = fsl_ifc_ctrl_remove,
+};
+
+static int __init fsl_ifc_init(void)
+{
+	return platform_driver_register(&fsl_ifc_ctrl_driver);
+}
+subsys_initcall(fsl_ifc_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
new file mode 100644
index 000000000000..d3df7602f406
--- /dev/null
+++ b/drivers/memory/ti-aemif.c
@@ -0,0 +1,427 @@
+/*
+ * TI AEMIF driver
+ *
+ * Copyright (C) 2010 - 2013 Texas Instruments Incorporated. http://www.ti.com/
+ *
+ * Authors:
+ * Murali Karicheri <m-karicheri2@ti.com>
+ * Ivan Khoronzhuk <ivan.khoronzhuk@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/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#define TA_SHIFT	2
+#define RHOLD_SHIFT	4
+#define RSTROBE_SHIFT	7
+#define RSETUP_SHIFT	13
+#define WHOLD_SHIFT	17
+#define WSTROBE_SHIFT	20
+#define WSETUP_SHIFT	26
+#define EW_SHIFT	30
+#define SS_SHIFT	31
+
+#define TA(x)		((x) << TA_SHIFT)
+#define RHOLD(x)	((x) << RHOLD_SHIFT)
+#define RSTROBE(x)	((x) << RSTROBE_SHIFT)
+#define RSETUP(x)	((x) << RSETUP_SHIFT)
+#define WHOLD(x)	((x) << WHOLD_SHIFT)
+#define WSTROBE(x)	((x) << WSTROBE_SHIFT)
+#define WSETUP(x)	((x) << WSETUP_SHIFT)
+#define EW(x)		((x) << EW_SHIFT)
+#define SS(x)		((x) << SS_SHIFT)
+
+#define ASIZE_MAX	0x1
+#define TA_MAX		0x3
+#define RHOLD_MAX	0x7
+#define RSTROBE_MAX	0x3f
+#define RSETUP_MAX	0xf
+#define WHOLD_MAX	0x7
+#define WSTROBE_MAX	0x3f
+#define WSETUP_MAX	0xf
+#define EW_MAX		0x1
+#define SS_MAX		0x1
+#define NUM_CS		4
+
+#define TA_VAL(x)	(((x) & TA(TA_MAX)) >> TA_SHIFT)
+#define RHOLD_VAL(x)	(((x) & RHOLD(RHOLD_MAX)) >> RHOLD_SHIFT)
+#define RSTROBE_VAL(x)	(((x) & RSTROBE(RSTROBE_MAX)) >> RSTROBE_SHIFT)
+#define RSETUP_VAL(x)	(((x) & RSETUP(RSETUP_MAX)) >> RSETUP_SHIFT)
+#define WHOLD_VAL(x)	(((x) & WHOLD(WHOLD_MAX)) >> WHOLD_SHIFT)
+#define WSTROBE_VAL(x)	(((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT)
+#define WSETUP_VAL(x)	(((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT)
+#define EW_VAL(x)	(((x) & EW(EW_MAX)) >> EW_SHIFT)
+#define SS_VAL(x)	(((x) & SS(SS_MAX)) >> SS_SHIFT)
+
+#define NRCSR_OFFSET	0x00
+#define AWCCR_OFFSET	0x04
+#define A1CR_OFFSET	0x10
+
+#define ACR_ASIZE_MASK	0x3
+#define ACR_EW_MASK	BIT(30)
+#define ACR_SS_MASK	BIT(31)
+#define ASIZE_16BIT	1
+
+#define CONFIG_MASK	(TA(TA_MAX) | \
+				RHOLD(RHOLD_MAX) | \
+				RSTROBE(RSTROBE_MAX) |	\
+				RSETUP(RSETUP_MAX) | \
+				WHOLD(WHOLD_MAX) | \
+				WSTROBE(WSTROBE_MAX) | \
+				WSETUP(WSETUP_MAX) | \
+				EW(EW_MAX) | SS(SS_MAX) | \
+				ASIZE_MAX)
+
+/**
+ * struct aemif_cs_data: structure to hold cs parameters
+ * @cs: chip-select number
+ * @wstrobe: write strobe width, ns
+ * @rstrobe: read strobe width, ns
+ * @wsetup: write setup width, ns
+ * @whold: write hold width, ns
+ * @rsetup: read setup width, ns
+ * @rhold: read hold width, ns
+ * @ta: minimum turn around time, ns
+ * @enable_ss: enable/disable select strobe mode
+ * @enable_ew: enable/disable extended wait mode
+ * @asize: width of the asynchronous device's data bus
+ */
+struct aemif_cs_data {
+	u8	cs;
+	u16	wstrobe;
+	u16	rstrobe;
+	u8	wsetup;
+	u8	whold;
+	u8	rsetup;
+	u8	rhold;
+	u8	ta;
+	u8	enable_ss;
+	u8	enable_ew;
+	u8	asize;
+};
+
+/**
+ * struct aemif_device: structure to hold device data
+ * @base: base address of AEMIF registers
+ * @clk: source clock
+ * @clk_rate: clock's rate in kHz
+ * @num_cs: number of assigned chip-selects
+ * @cs_offset: start number of cs nodes
+ * @cs_data: array of chip-select settings
+ */
+struct aemif_device {
+	void __iomem *base;
+	struct clk *clk;
+	unsigned long clk_rate;
+	u8 num_cs;
+	int cs_offset;
+	struct aemif_cs_data cs_data[NUM_CS];
+};
+
+/**
+ * aemif_calc_rate - calculate timing data.
+ * @pdev: platform device to calculate for
+ * @wanted: The cycle time needed in nanoseconds.
+ * @clk: The input clock rate in kHz.
+ * @max: The maximum divider value that can be programmed.
+ *
+ * On success, returns the calculated timing value minus 1 for easy
+ * programming into AEMIF timing registers, else negative errno.
+ */
+static int aemif_calc_rate(struct platform_device *pdev, int wanted,
+			   unsigned long clk, int max)
+{
+	int result;
+
+	result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
+
+	dev_dbg(&pdev->dev, "%s: result %d from %ld, %d\n", __func__, result,
+		clk, wanted);
+
+	/* It is generally OK to have a more relaxed timing than requested... */
+	if (result < 0)
+		result = 0;
+
+	/* ... But configuring tighter timings is not an option. */
+	else if (result > max)
+		result = -EINVAL;
+
+	return result;
+}
+
+/**
+ * aemif_config_abus - configure async bus parameters
+ * @pdev: platform device to configure for
+ * @csnum: aemif chip select number
+ *
+ * This function programs the given timing values (in real clock) into the
+ * AEMIF registers taking the AEMIF clock into account.
+ *
+ * This function does not use any locking while programming the AEMIF
+ * because it is expected that there is only one user of a given
+ * chip-select.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+static int aemif_config_abus(struct platform_device *pdev, int csnum)
+{
+	struct aemif_device *aemif = platform_get_drvdata(pdev);
+	struct aemif_cs_data *data = &aemif->cs_data[csnum];
+	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
+	unsigned long clk_rate = aemif->clk_rate;
+	unsigned offset;
+	u32 set, val;
+
+	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
+
+	ta	= aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX);
+	rhold	= aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX);
+	rstrobe	= aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX);
+	rsetup	= aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX);
+	whold	= aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX);
+	wstrobe	= aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX);
+	wsetup	= aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX);
+
+	if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
+	    whold < 0 || wstrobe < 0 || wsetup < 0) {
+		dev_err(&pdev->dev, "%s: cannot get suitable timings\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
+		WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
+
+	set |= (data->asize & ACR_ASIZE_MASK);
+	if (data->enable_ew)
+		set |= ACR_EW_MASK;
+	if (data->enable_ss)
+		set |= ACR_SS_MASK;
+
+	val = readl(aemif->base + offset);
+	val &= ~CONFIG_MASK;
+	val |= set;
+	writel(val, aemif->base + offset);
+
+	return 0;
+}
+
+static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate)
+{
+	return ((val + 1) * NSEC_PER_MSEC) / clk_rate;
+}
+
+/**
+ * aemif_get_hw_params - function to read hw register values
+ * @pdev: platform device to read for
+ * @csnum: aemif chip select number
+ *
+ * This function reads the defaults from the registers and update
+ * the timing values. Required for get/set commands and also for
+ * the case when driver needs to use defaults in hardware.
+ */
+static void aemif_get_hw_params(struct platform_device *pdev, int csnum)
+{
+	struct aemif_device *aemif = platform_get_drvdata(pdev);
+	struct aemif_cs_data *data = &aemif->cs_data[csnum];
+	unsigned long clk_rate = aemif->clk_rate;
+	u32 val, offset;
+
+	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
+	val = readl(aemif->base + offset);
+
+	data->ta = aemif_cycles_to_nsec(TA_VAL(val), clk_rate);
+	data->rhold = aemif_cycles_to_nsec(RHOLD_VAL(val), clk_rate);
+	data->rstrobe = aemif_cycles_to_nsec(RSTROBE_VAL(val), clk_rate);
+	data->rsetup = aemif_cycles_to_nsec(RSETUP_VAL(val), clk_rate);
+	data->whold = aemif_cycles_to_nsec(WHOLD_VAL(val), clk_rate);
+	data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate);
+	data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate);
+	data->enable_ew = EW_VAL(val);
+	data->enable_ss = SS_VAL(val);
+	data->asize = val & ASIZE_MAX;
+}
+
+/**
+ * of_aemif_parse_abus_config - parse CS configuration from DT
+ * @pdev: platform device to parse for
+ * @np: device node ptr
+ *
+ * This function update the emif async bus configuration based on the values
+ * configured in a cs device binding node.
+ */
+static int of_aemif_parse_abus_config(struct platform_device *pdev,
+				      struct device_node *np)
+{
+	struct aemif_device *aemif = platform_get_drvdata(pdev);
+	struct aemif_cs_data *data;
+	u32 cs;
+	u32 val;
+
+	if (of_property_read_u32(np, "ti,cs-chipselect", &cs)) {
+		dev_dbg(&pdev->dev, "cs property is required");
+		return -EINVAL;
+	}
+
+	if (cs - aemif->cs_offset >= NUM_CS || cs < aemif->cs_offset) {
+		dev_dbg(&pdev->dev, "cs number is incorrect %d", cs);
+		return -EINVAL;
+	}
+
+	if (aemif->num_cs >= NUM_CS) {
+		dev_dbg(&pdev->dev, "cs count is more than %d", NUM_CS);
+		return -EINVAL;
+	}
+
+	data = &aemif->cs_data[aemif->num_cs];
+	data->cs = cs;
+
+	/* read the current value in the hw register */
+	aemif_get_hw_params(pdev, aemif->num_cs++);
+
+	/* override the values from device node */
+	if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val))
+		data->ta = val;
+
+	if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val))
+		data->rhold = val;
+
+	if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val))
+		data->rstrobe = val;
+
+	if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val))
+		data->rsetup = val;
+
+	if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val))
+		data->whold = val;
+
+	if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val))
+		data->wstrobe = val;
+
+	if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val))
+		data->wsetup = val;
+
+	if (!of_property_read_u32(np, "ti,cs-bus-width", &val))
+		if (val == 16)
+			data->asize = 1;
+	data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode");
+	data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode");
+	return 0;
+}
+
+static const struct of_device_id aemif_of_match[] = {
+	{ .compatible = "ti,davinci-aemif", },
+	{ .compatible = "ti,da850-aemif", },
+	{},
+};
+
+static int aemif_probe(struct platform_device *pdev)
+{
+	int i;
+	int ret = -ENODEV;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *child_np;
+	struct aemif_device *aemif;
+
+	if (np == NULL)
+		return 0;
+
+	aemif = devm_kzalloc(dev, sizeof(*aemif), GFP_KERNEL);
+	if (!aemif)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, aemif);
+
+	aemif->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(aemif->clk)) {
+		dev_err(dev, "cannot get clock 'aemif'\n");
+		return PTR_ERR(aemif->clk);
+	}
+
+	clk_prepare_enable(aemif->clk);
+	aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC;
+
+	if (of_device_is_compatible(np, "ti,da850-aemif"))
+		aemif->cs_offset = 2;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	aemif->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(aemif->base)) {
+		ret = PTR_ERR(aemif->base);
+		goto error;
+	}
+
+	/*
+	 * For every controller device node, there is a cs device node that
+	 * describe the bus configuration parameters. This functions iterate
+	 * over these nodes and update the cs data array.
+	 */
+	for_each_available_child_of_node(np, child_np) {
+		ret = of_aemif_parse_abus_config(pdev, child_np);
+		if (ret < 0)
+			goto error;
+	}
+
+	for (i = 0; i < aemif->num_cs; i++) {
+		ret = aemif_config_abus(pdev, i);
+		if (ret < 0) {
+			dev_err(dev, "Error configuring chip select %d\n",
+				aemif->cs_data[i].cs);
+			goto error;
+		}
+	}
+
+	/*
+	 * Create a child devices explicitly from here to
+	 * guarantee that the child will be probed after the AEMIF timing
+	 * parameters are set.
+	 */
+	for_each_available_child_of_node(np, child_np) {
+		ret = of_platform_populate(child_np, NULL, NULL, dev);
+		if (ret < 0)
+			goto error;
+	}
+
+	return 0;
+error:
+	clk_disable_unprepare(aemif->clk);
+	return ret;
+}
+
+static int aemif_remove(struct platform_device *pdev)
+{
+	struct aemif_device *aemif = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(aemif->clk);
+	return 0;
+}
+
+static struct platform_driver aemif_driver = {
+	.probe = aemif_probe,
+	.remove = aemif_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(aemif_of_match),
+	},
+};
+
+module_platform_driver(aemif_driver);
+
+MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
+MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments AEMIF driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 49bb445d846a..17004a61fdd5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1193,9 +1193,6 @@ config MFD_STW481X
 	  in various ST Microelectronics and ST-Ericsson embedded
 	  Nomadik series.
 
-endmenu
-endif
-
 menu "Multimedia Capabilities Port drivers"
 	depends on ARCH_SA1100
 
@@ -1226,3 +1223,6 @@ config VEXPRESS_CONFIG
 	help
 	  Platform configuration infrastructure for the ARM Ltd.
 	  Versatile Express.
+
+endmenu
+endif
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index a45aab9f6bb1..1c3ae57082ed 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -251,8 +251,6 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
 	unsigned int fll, sysclk;
 	int ret, err;
 
-	regcache_cache_bypass(arizona->regmap, true);
-
 	/* Cache existing FLL and SYSCLK settings */
 	ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
 	if (ret != 0) {
@@ -322,8 +320,6 @@ err_fll:
 			err);
 	}
 
-	regcache_cache_bypass(arizona->regmap, false);
-
 	if (ret != 0)
 		return ret;
 	else
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 71aa14a6bfbb..c9859d1baf14 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -25,7 +25,10 @@
 #include <linux/mfd/max14577-private.h>
 
 static struct mfd_cell max14577_devs[] = {
-	{ .name = "max14577-muic", },
+	{
+		.name = "max14577-muic",
+		.of_compatible = "maxim,max14577-muic",
+	},
 	{
 		.name = "max14577-regulator",
 		.of_compatible = "maxim,max14577-regulator",
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 1d15735f9ef9..c9de3d598ea5 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -338,58 +338,28 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
 		int num_sg, bool read, int timeout)
 {
 	struct completion trans_done;
-	u8 dir;
-	int err = 0, i, count;
+	int err = 0, count;
 	long timeleft;
 	unsigned long flags;
-	struct scatterlist *sg;
-	enum dma_data_direction dma_dir;
-	u32 val;
-	dma_addr_t addr;
-	unsigned int len;
-
-	dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
-
-	/* don't transfer data during abort processing */
-	if (pcr->remove_pci)
-		return -EINVAL;
-
-	if ((sglist == NULL) || (num_sg <= 0))
-		return -EINVAL;
 
-	if (read) {
-		dir = DEVICE_TO_HOST;
-		dma_dir = DMA_FROM_DEVICE;
-	} else {
-		dir = HOST_TO_DEVICE;
-		dma_dir = DMA_TO_DEVICE;
-	}
-
-	count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+	count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
 	if (count < 1) {
 		dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
 		return -EINVAL;
 	}
 	dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
 
-	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
-	pcr->sgi = 0;
-	for_each_sg(sglist, sg, count, i) {
-		addr = sg_dma_address(sg);
-		len = sg_dma_len(sg);
-		rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
-	}
 
 	spin_lock_irqsave(&pcr->lock, flags);
 
 	pcr->done = &trans_done;
 	pcr->trans_result = TRANS_NOT_READY;
 	init_completion(&trans_done);
-	rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
-	rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
 
 	spin_unlock_irqrestore(&pcr->lock, flags);
 
+	rtsx_pci_dma_transfer(pcr, sglist, count, read);
+
 	timeleft = wait_for_completion_interruptible_timeout(
 			&trans_done, msecs_to_jiffies(timeout));
 	if (timeleft <= 0) {
@@ -413,7 +383,7 @@ out:
 	pcr->done = NULL;
 	spin_unlock_irqrestore(&pcr->lock, flags);
 
-	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+	rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
 
 	if ((err < 0) && (err != -ENODEV))
 		rtsx_pci_stop_cmd(pcr);
@@ -425,6 +395,73 @@ out:
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
 
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read)
+{
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	if (pcr->remove_pci)
+		return -EINVAL;
+
+	if ((sglist == NULL) || num_sg < 1)
+		return -EINVAL;
+
+	return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
+
+int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read)
+{
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	if (pcr->remove_pci)
+		return -EINVAL;
+
+	if (sglist == NULL || num_sg < 1)
+		return -EINVAL;
+
+	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+	return num_sg;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
+
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int sg_count, bool read)
+{
+	struct scatterlist *sg;
+	dma_addr_t addr;
+	unsigned int len;
+	int i;
+	u32 val;
+	u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
+	unsigned long flags;
+
+	if (pcr->remove_pci)
+		return -EINVAL;
+
+	if ((sglist == NULL) || (sg_count < 1))
+		return -EINVAL;
+
+	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
+	pcr->sgi = 0;
+	for_each_sg(sglist, sg, sg_count, i) {
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1);
+	}
+
+	spin_lock_irqsave(&pcr->lock, flags);
+
+	rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
+	rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
+
 int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
 {
 	int err;
@@ -836,6 +873,8 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
 	int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
 	/* Clear interrupt flag */
 	rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
+	dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg);
+
 	if ((int_reg & pcr->bier) == 0) {
 		spin_unlock(&pcr->lock);
 		return IRQ_NONE;
@@ -866,17 +905,28 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
 	}
 
 	if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
-		if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
+		if (int_reg & (TRANS_FAIL_INT | DELINK_INT))
 			pcr->trans_result = TRANS_RESULT_FAIL;
-			if (pcr->done)
-				complete(pcr->done);
-		} else if (int_reg & TRANS_OK_INT) {
+		else if (int_reg & TRANS_OK_INT)
 			pcr->trans_result = TRANS_RESULT_OK;
-			if (pcr->done)
-				complete(pcr->done);
+
+		if (pcr->done)
+			complete(pcr->done);
+
+		if (int_reg & SD_EXIST) {
+			struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
+			if (slot && slot->done_transfer)
+				slot->done_transfer(slot->p_dev);
+		}
+
+		if (int_reg & MS_EXIST) {
+			struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
+			if (slot && slot->done_transfer)
+				slot->done_transfer(slot->p_dev);
 		}
 	}
 
+
 	if (pcr->card_inserted || pcr->card_removed)
 		schedule_delayed_work(&pcr->carddet_work,
 				msecs_to_jiffies(200));
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 1e9a4b2102f9..f4668d39e542 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -73,6 +73,7 @@ static const struct reg_default wm5102_revb_patch[] = {
 	{ 0x171, 0x0000 },
 	{ 0x35E, 0x000C },
 	{ 0x2D4, 0x0000 },
+	{ 0x4DC, 0x0900 },
 	{ 0x80, 0x0000 },
 };
 
@@ -80,8 +81,7 @@ static const struct reg_default wm5102_revb_patch[] = {
 int wm5102_patch(struct arizona *arizona)
 {
 	const struct reg_default *wm5102_patch;
-	int ret = 0;
-	int i, patch_size;
+	int patch_size;
 
 	switch (arizona->rev) {
 	case 0:
@@ -92,21 +92,9 @@ int wm5102_patch(struct arizona *arizona)
 		patch_size = ARRAY_SIZE(wm5102_revb_patch);
 	}
 
-	regcache_cache_bypass(arizona->regmap, true);
-
-	for (i = 0; i < patch_size; i++) {
-		ret = regmap_write(arizona->regmap, wm5102_patch[i].reg,
-				   wm5102_patch[i].def);
-		if (ret != 0) {
-			dev_err(arizona->dev, "Failed to write %x = %x: %d\n",
-				wm5102_patch[i].reg, wm5102_patch[i].def, ret);
-			goto out;
-		}
-	}
-
-out:
-	regcache_cache_bypass(arizona->regmap, false);
-	return ret;
+	return regmap_multi_reg_write_bypassed(arizona->regmap,
+					       wm5102_patch,
+					       patch_size);
 }
 
 static const struct regmap_irq wm5102_aod_irqs[ARIZONA_NUM_IRQ] = {
@@ -1852,6 +1840,23 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP1_STATUS_1:
 	case ARIZONA_DSP1_STATUS_2:
 	case ARIZONA_DSP1_STATUS_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_1:
+	case ARIZONA_DSP1_WDMA_BUFFER_2:
+	case ARIZONA_DSP1_WDMA_BUFFER_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_5:
+	case ARIZONA_DSP1_WDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_BUFFER_7:
+	case ARIZONA_DSP1_WDMA_BUFFER_8:
+	case ARIZONA_DSP1_RDMA_BUFFER_1:
+	case ARIZONA_DSP1_RDMA_BUFFER_2:
+	case ARIZONA_DSP1_RDMA_BUFFER_3:
+	case ARIZONA_DSP1_RDMA_BUFFER_4:
+	case ARIZONA_DSP1_RDMA_BUFFER_5:
+	case ARIZONA_DSP1_RDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_CONFIG_1:
+	case ARIZONA_DSP1_WDMA_CONFIG_2:
+	case ARIZONA_DSP1_RDMA_CONFIG_1:
 	case ARIZONA_DSP1_SCRATCH_0:
 	case ARIZONA_DSP1_SCRATCH_1:
 	case ARIZONA_DSP1_SCRATCH_2:
@@ -1910,6 +1915,23 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP1_STATUS_1:
 	case ARIZONA_DSP1_STATUS_2:
 	case ARIZONA_DSP1_STATUS_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_1:
+	case ARIZONA_DSP1_WDMA_BUFFER_2:
+	case ARIZONA_DSP1_WDMA_BUFFER_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_5:
+	case ARIZONA_DSP1_WDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_BUFFER_7:
+	case ARIZONA_DSP1_WDMA_BUFFER_8:
+	case ARIZONA_DSP1_RDMA_BUFFER_1:
+	case ARIZONA_DSP1_RDMA_BUFFER_2:
+	case ARIZONA_DSP1_RDMA_BUFFER_3:
+	case ARIZONA_DSP1_RDMA_BUFFER_4:
+	case ARIZONA_DSP1_RDMA_BUFFER_5:
+	case ARIZONA_DSP1_RDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_CONFIG_1:
+	case ARIZONA_DSP1_WDMA_CONFIG_2:
+	case ARIZONA_DSP1_RDMA_CONFIG_1:
 	case ARIZONA_DSP1_SCRATCH_0:
 	case ARIZONA_DSP1_SCRATCH_1:
 	case ARIZONA_DSP1_SCRATCH_2:
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 11632f135e8c..ca9968525017 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -2461,6 +2461,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP1_STATUS_1:
 	case ARIZONA_DSP1_STATUS_2:
 	case ARIZONA_DSP1_STATUS_3:
+	case ARIZONA_DSP1_STATUS_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_1:
+	case ARIZONA_DSP1_WDMA_BUFFER_2:
+	case ARIZONA_DSP1_WDMA_BUFFER_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_5:
+	case ARIZONA_DSP1_WDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_BUFFER_7:
+	case ARIZONA_DSP1_WDMA_BUFFER_8:
+	case ARIZONA_DSP1_RDMA_BUFFER_1:
+	case ARIZONA_DSP1_RDMA_BUFFER_2:
+	case ARIZONA_DSP1_RDMA_BUFFER_3:
+	case ARIZONA_DSP1_RDMA_BUFFER_4:
+	case ARIZONA_DSP1_RDMA_BUFFER_5:
+	case ARIZONA_DSP1_RDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_CONFIG_1:
+	case ARIZONA_DSP1_WDMA_CONFIG_2:
+	case ARIZONA_DSP1_WDMA_OFFSET_1:
+	case ARIZONA_DSP1_RDMA_CONFIG_1:
+	case ARIZONA_DSP1_RDMA_OFFSET_1:
+	case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP1_SCRATCH_0:
 	case ARIZONA_DSP1_SCRATCH_1:
 	case ARIZONA_DSP1_SCRATCH_2:
@@ -2470,6 +2491,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP2_STATUS_1:
 	case ARIZONA_DSP2_STATUS_2:
 	case ARIZONA_DSP2_STATUS_3:
+	case ARIZONA_DSP2_STATUS_4:
+	case ARIZONA_DSP2_WDMA_BUFFER_1:
+	case ARIZONA_DSP2_WDMA_BUFFER_2:
+	case ARIZONA_DSP2_WDMA_BUFFER_3:
+	case ARIZONA_DSP2_WDMA_BUFFER_4:
+	case ARIZONA_DSP2_WDMA_BUFFER_5:
+	case ARIZONA_DSP2_WDMA_BUFFER_6:
+	case ARIZONA_DSP2_WDMA_BUFFER_7:
+	case ARIZONA_DSP2_WDMA_BUFFER_8:
+	case ARIZONA_DSP2_RDMA_BUFFER_1:
+	case ARIZONA_DSP2_RDMA_BUFFER_2:
+	case ARIZONA_DSP2_RDMA_BUFFER_3:
+	case ARIZONA_DSP2_RDMA_BUFFER_4:
+	case ARIZONA_DSP2_RDMA_BUFFER_5:
+	case ARIZONA_DSP2_RDMA_BUFFER_6:
+	case ARIZONA_DSP2_WDMA_CONFIG_1:
+	case ARIZONA_DSP2_WDMA_CONFIG_2:
+	case ARIZONA_DSP2_WDMA_OFFSET_1:
+	case ARIZONA_DSP2_RDMA_CONFIG_1:
+	case ARIZONA_DSP2_RDMA_OFFSET_1:
+	case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP2_SCRATCH_0:
 	case ARIZONA_DSP2_SCRATCH_1:
 	case ARIZONA_DSP2_SCRATCH_2:
@@ -2479,6 +2521,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP3_STATUS_1:
 	case ARIZONA_DSP3_STATUS_2:
 	case ARIZONA_DSP3_STATUS_3:
+	case ARIZONA_DSP3_STATUS_4:
+	case ARIZONA_DSP3_WDMA_BUFFER_1:
+	case ARIZONA_DSP3_WDMA_BUFFER_2:
+	case ARIZONA_DSP3_WDMA_BUFFER_3:
+	case ARIZONA_DSP3_WDMA_BUFFER_4:
+	case ARIZONA_DSP3_WDMA_BUFFER_5:
+	case ARIZONA_DSP3_WDMA_BUFFER_6:
+	case ARIZONA_DSP3_WDMA_BUFFER_7:
+	case ARIZONA_DSP3_WDMA_BUFFER_8:
+	case ARIZONA_DSP3_RDMA_BUFFER_1:
+	case ARIZONA_DSP3_RDMA_BUFFER_2:
+	case ARIZONA_DSP3_RDMA_BUFFER_3:
+	case ARIZONA_DSP3_RDMA_BUFFER_4:
+	case ARIZONA_DSP3_RDMA_BUFFER_5:
+	case ARIZONA_DSP3_RDMA_BUFFER_6:
+	case ARIZONA_DSP3_WDMA_CONFIG_1:
+	case ARIZONA_DSP3_WDMA_CONFIG_2:
+	case ARIZONA_DSP3_WDMA_OFFSET_1:
+	case ARIZONA_DSP3_RDMA_CONFIG_1:
+	case ARIZONA_DSP3_RDMA_OFFSET_1:
+	case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP3_SCRATCH_0:
 	case ARIZONA_DSP3_SCRATCH_1:
 	case ARIZONA_DSP3_SCRATCH_2:
@@ -2488,6 +2551,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP4_STATUS_1:
 	case ARIZONA_DSP4_STATUS_2:
 	case ARIZONA_DSP4_STATUS_3:
+	case ARIZONA_DSP4_STATUS_4:
+	case ARIZONA_DSP4_WDMA_BUFFER_1:
+	case ARIZONA_DSP4_WDMA_BUFFER_2:
+	case ARIZONA_DSP4_WDMA_BUFFER_3:
+	case ARIZONA_DSP4_WDMA_BUFFER_4:
+	case ARIZONA_DSP4_WDMA_BUFFER_5:
+	case ARIZONA_DSP4_WDMA_BUFFER_6:
+	case ARIZONA_DSP4_WDMA_BUFFER_7:
+	case ARIZONA_DSP4_WDMA_BUFFER_8:
+	case ARIZONA_DSP4_RDMA_BUFFER_1:
+	case ARIZONA_DSP4_RDMA_BUFFER_2:
+	case ARIZONA_DSP4_RDMA_BUFFER_3:
+	case ARIZONA_DSP4_RDMA_BUFFER_4:
+	case ARIZONA_DSP4_RDMA_BUFFER_5:
+	case ARIZONA_DSP4_RDMA_BUFFER_6:
+	case ARIZONA_DSP4_WDMA_CONFIG_1:
+	case ARIZONA_DSP4_WDMA_CONFIG_2:
+	case ARIZONA_DSP4_WDMA_OFFSET_1:
+	case ARIZONA_DSP4_RDMA_CONFIG_1:
+	case ARIZONA_DSP4_RDMA_OFFSET_1:
+	case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP4_SCRATCH_0:
 	case ARIZONA_DSP4_SCRATCH_1:
 	case ARIZONA_DSP4_SCRATCH_2:
@@ -2543,6 +2627,27 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP1_STATUS_1:
 	case ARIZONA_DSP1_STATUS_2:
 	case ARIZONA_DSP1_STATUS_3:
+	case ARIZONA_DSP1_STATUS_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_1:
+	case ARIZONA_DSP1_WDMA_BUFFER_2:
+	case ARIZONA_DSP1_WDMA_BUFFER_3:
+	case ARIZONA_DSP1_WDMA_BUFFER_4:
+	case ARIZONA_DSP1_WDMA_BUFFER_5:
+	case ARIZONA_DSP1_WDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_BUFFER_7:
+	case ARIZONA_DSP1_WDMA_BUFFER_8:
+	case ARIZONA_DSP1_RDMA_BUFFER_1:
+	case ARIZONA_DSP1_RDMA_BUFFER_2:
+	case ARIZONA_DSP1_RDMA_BUFFER_3:
+	case ARIZONA_DSP1_RDMA_BUFFER_4:
+	case ARIZONA_DSP1_RDMA_BUFFER_5:
+	case ARIZONA_DSP1_RDMA_BUFFER_6:
+	case ARIZONA_DSP1_WDMA_CONFIG_1:
+	case ARIZONA_DSP1_WDMA_CONFIG_2:
+	case ARIZONA_DSP1_WDMA_OFFSET_1:
+	case ARIZONA_DSP1_RDMA_CONFIG_1:
+	case ARIZONA_DSP1_RDMA_OFFSET_1:
+	case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP1_SCRATCH_0:
 	case ARIZONA_DSP1_SCRATCH_1:
 	case ARIZONA_DSP1_SCRATCH_2:
@@ -2550,6 +2655,27 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP2_STATUS_1:
 	case ARIZONA_DSP2_STATUS_2:
 	case ARIZONA_DSP2_STATUS_3:
+	case ARIZONA_DSP2_STATUS_4:
+	case ARIZONA_DSP2_WDMA_BUFFER_1:
+	case ARIZONA_DSP2_WDMA_BUFFER_2:
+	case ARIZONA_DSP2_WDMA_BUFFER_3:
+	case ARIZONA_DSP2_WDMA_BUFFER_4:
+	case ARIZONA_DSP2_WDMA_BUFFER_5:
+	case ARIZONA_DSP2_WDMA_BUFFER_6:
+	case ARIZONA_DSP2_WDMA_BUFFER_7:
+	case ARIZONA_DSP2_WDMA_BUFFER_8:
+	case ARIZONA_DSP2_RDMA_BUFFER_1:
+	case ARIZONA_DSP2_RDMA_BUFFER_2:
+	case ARIZONA_DSP2_RDMA_BUFFER_3:
+	case ARIZONA_DSP2_RDMA_BUFFER_4:
+	case ARIZONA_DSP2_RDMA_BUFFER_5:
+	case ARIZONA_DSP2_RDMA_BUFFER_6:
+	case ARIZONA_DSP2_WDMA_CONFIG_1:
+	case ARIZONA_DSP2_WDMA_CONFIG_2:
+	case ARIZONA_DSP2_WDMA_OFFSET_1:
+	case ARIZONA_DSP2_RDMA_CONFIG_1:
+	case ARIZONA_DSP2_RDMA_OFFSET_1:
+	case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP2_SCRATCH_0:
 	case ARIZONA_DSP2_SCRATCH_1:
 	case ARIZONA_DSP2_SCRATCH_2:
@@ -2557,6 +2683,27 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP3_STATUS_1:
 	case ARIZONA_DSP3_STATUS_2:
 	case ARIZONA_DSP3_STATUS_3:
+	case ARIZONA_DSP3_STATUS_4:
+	case ARIZONA_DSP3_WDMA_BUFFER_1:
+	case ARIZONA_DSP3_WDMA_BUFFER_2:
+	case ARIZONA_DSP3_WDMA_BUFFER_3:
+	case ARIZONA_DSP3_WDMA_BUFFER_4:
+	case ARIZONA_DSP3_WDMA_BUFFER_5:
+	case ARIZONA_DSP3_WDMA_BUFFER_6:
+	case ARIZONA_DSP3_WDMA_BUFFER_7:
+	case ARIZONA_DSP3_WDMA_BUFFER_8:
+	case ARIZONA_DSP3_RDMA_BUFFER_1:
+	case ARIZONA_DSP3_RDMA_BUFFER_2:
+	case ARIZONA_DSP3_RDMA_BUFFER_3:
+	case ARIZONA_DSP3_RDMA_BUFFER_4:
+	case ARIZONA_DSP3_RDMA_BUFFER_5:
+	case ARIZONA_DSP3_RDMA_BUFFER_6:
+	case ARIZONA_DSP3_WDMA_CONFIG_1:
+	case ARIZONA_DSP3_WDMA_CONFIG_2:
+	case ARIZONA_DSP3_WDMA_OFFSET_1:
+	case ARIZONA_DSP3_RDMA_CONFIG_1:
+	case ARIZONA_DSP3_RDMA_OFFSET_1:
+	case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP3_SCRATCH_0:
 	case ARIZONA_DSP3_SCRATCH_1:
 	case ARIZONA_DSP3_SCRATCH_2:
@@ -2564,6 +2711,27 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_DSP4_STATUS_1:
 	case ARIZONA_DSP4_STATUS_2:
 	case ARIZONA_DSP4_STATUS_3:
+	case ARIZONA_DSP4_STATUS_4:
+	case ARIZONA_DSP4_WDMA_BUFFER_1:
+	case ARIZONA_DSP4_WDMA_BUFFER_2:
+	case ARIZONA_DSP4_WDMA_BUFFER_3:
+	case ARIZONA_DSP4_WDMA_BUFFER_4:
+	case ARIZONA_DSP4_WDMA_BUFFER_5:
+	case ARIZONA_DSP4_WDMA_BUFFER_6:
+	case ARIZONA_DSP4_WDMA_BUFFER_7:
+	case ARIZONA_DSP4_WDMA_BUFFER_8:
+	case ARIZONA_DSP4_RDMA_BUFFER_1:
+	case ARIZONA_DSP4_RDMA_BUFFER_2:
+	case ARIZONA_DSP4_RDMA_BUFFER_3:
+	case ARIZONA_DSP4_RDMA_BUFFER_4:
+	case ARIZONA_DSP4_RDMA_BUFFER_5:
+	case ARIZONA_DSP4_RDMA_BUFFER_6:
+	case ARIZONA_DSP4_WDMA_CONFIG_1:
+	case ARIZONA_DSP4_WDMA_CONFIG_2:
+	case ARIZONA_DSP4_WDMA_OFFSET_1:
+	case ARIZONA_DSP4_RDMA_CONFIG_1:
+	case ARIZONA_DSP4_RDMA_OFFSET_1:
+	case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
 	case ARIZONA_DSP4_SCRATCH_0:
 	case ARIZONA_DSP4_SCRATCH_1:
 	case ARIZONA_DSP4_SCRATCH_2:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6cb388e8fb7d..3816b59d3e1e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -526,4 +526,5 @@ source "drivers/misc/mei/Kconfig"
 source "drivers/misc/vmw_vmci/Kconfig"
 source "drivers/misc/mic/Kconfig"
 source "drivers/misc/genwqe/Kconfig"
+source "drivers/misc/echo/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 99b9424ce31d..7eb4b69580c0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
+obj-$(CONFIG_ECHO)		+= echo/
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index d3eee113baeb..a43053daad0e 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -72,7 +72,6 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 0c6e037153d2..c6cc3dc8ae1f 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 5be808406edc..22de13727641 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -150,6 +150,12 @@ static int ssc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
 
+	if (pdev->dev.of_node) {
+		struct device_node *np = pdev->dev.of_node;
+		ssc->clk_from_rk_pin =
+			of_property_read_bool(np, "atmel,clk-from-rk-pin");
+	}
+
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ssc->regs = devm_ioremap_resource(&pdev->dev, regs);
 	if (IS_ERR(ssc->regs))
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 820e53d0048f..9b313f7810f5 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -47,7 +47,6 @@
 
 #include <linux/module.h>
 #include <linux/device.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include "bmp085.h"
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 9e2b985293fc..14d90eae605b 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -101,7 +101,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/poll.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/kref.h>
 #include <linux/io.h>
diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c
index 154b02e5094f..6a672f9ef522 100644
--- a/drivers/misc/ds1682.c
+++ b/drivers/misc/ds1682.c
@@ -32,7 +32,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/string.h>
 #include <linux/list.h>
diff --git a/drivers/misc/echo/Kconfig b/drivers/misc/echo/Kconfig
new file mode 100644
index 000000000000..f1d41ea9cd48
--- /dev/null
+++ b/drivers/misc/echo/Kconfig
@@ -0,0 +1,9 @@
+config ECHO
+	tristate "Line Echo Canceller support"
+	default n
+	---help---
+	  This driver provides line echo cancelling support for mISDN and
+	  Zaptel drivers.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called echo.
diff --git a/drivers/misc/echo/Makefile b/drivers/misc/echo/Makefile
new file mode 100644
index 000000000000..7d4caac12a8d
--- /dev/null
+++ b/drivers/misc/echo/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ECHO) += echo.o
diff --git a/drivers/misc/echo/echo.c b/drivers/misc/echo/echo.c
new file mode 100644
index 000000000000..9597e9523cac
--- /dev/null
+++ b/drivers/misc/echo/echo.c
@@ -0,0 +1,674 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * echo.c - A line echo canceller.  This code is being developed
+ *          against and partially complies with G168.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *         and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
+ *
+ * Based on a bit from here, a bit from there, eye of toad, ear of
+ * bat, 15 years of failed attempts by David and a few fried brain
+ * cells.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*! \file */
+
+/* Implementation Notes
+   David Rowe
+   April 2007
+
+   This code started life as Steve's NLMS algorithm with a tap
+   rotation algorithm to handle divergence during double talk.  I
+   added a Geigel Double Talk Detector (DTD) [2] and performed some
+   G168 tests.  However I had trouble meeting the G168 requirements,
+   especially for double talk - there were always cases where my DTD
+   failed, for example where near end speech was under the 6dB
+   threshold required for declaring double talk.
+
+   So I tried a two path algorithm [1], which has so far given better
+   results.  The original tap rotation/Geigel algorithm is available
+   in SVN http://svn.rowetel.com/software/oslec/tags/before_16bit.
+   It's probably possible to make it work if some one wants to put some
+   serious work into it.
+
+   At present no special treatment is provided for tones, which
+   generally cause NLMS algorithms to diverge.  Initial runs of a
+   subset of the G168 tests for tones (e.g ./echo_test 6) show the
+   current algorithm is passing OK, which is kind of surprising.  The
+   full set of tests needs to be performed to confirm this result.
+
+   One other interesting change is that I have managed to get the NLMS
+   code to work with 16 bit coefficients, rather than the original 32
+   bit coefficents.  This reduces the MIPs and storage required.
+   I evaulated the 16 bit port using g168_tests.sh and listening tests
+   on 4 real-world samples.
+
+   I also attempted the implementation of a block based NLMS update
+   [2] but although this passes g168_tests.sh it didn't converge well
+   on the real-world samples.  I have no idea why, perhaps a scaling
+   problem.  The block based code is also available in SVN
+   http://svn.rowetel.com/software/oslec/tags/before_16bit.  If this
+   code can be debugged, it will lead to further reduction in MIPS, as
+   the block update code maps nicely onto DSP instruction sets (it's a
+   dot product) compared to the current sample-by-sample update.
+
+   Steve also has some nice notes on echo cancellers in echo.h
+
+   References:
+
+   [1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
+       Path Models", IEEE Transactions on communications, COM-25,
+       No. 6, June
+       1977.
+       http://www.rowetel.com/images/echo/dual_path_paper.pdf
+
+   [2] The classic, very useful paper that tells you how to
+       actually build a real world echo canceller:
+	 Messerschmitt, Hedberg, Cole, Haoui, Winship, "Digital Voice
+	 Echo Canceller with a TMS320020,
+	 http://www.rowetel.com/images/echo/spra129.pdf
+
+   [3] I have written a series of blog posts on this work, here is
+       Part 1: http://www.rowetel.com/blog/?p=18
+
+   [4] The source code http://svn.rowetel.com/software/oslec/
+
+   [5] A nice reference on LMS filters:
+	 http://en.wikipedia.org/wiki/Least_mean_squares_filter
+
+   Credits:
+
+   Thanks to Steve Underwood, Jean-Marc Valin, and Ramakrishnan
+   Muthukrishnan for their suggestions and email discussions.  Thanks
+   also to those people who collected echo samples for me such as
+   Mark, Pawel, and Pavel.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "echo.h"
+
+#define MIN_TX_POWER_FOR_ADAPTION	64
+#define MIN_RX_POWER_FOR_ADAPTION	64
+#define DTD_HANGOVER			600	/* 600 samples, or 75ms     */
+#define DC_LOG2BETA			3	/* log2() of DC filter Beta */
+
+/* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
+
+#ifdef __bfin__
+static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
+{
+	int i;
+	int offset1;
+	int offset2;
+	int factor;
+	int exp;
+	int16_t *phist;
+	int n;
+
+	if (shift > 0)
+		factor = clean << shift;
+	else
+		factor = clean >> -shift;
+
+	/* Update the FIR taps */
+
+	offset2 = ec->curr_pos;
+	offset1 = ec->taps - offset2;
+	phist = &ec->fir_state_bg.history[offset2];
+
+	/* st: and en: help us locate the assembler in echo.s */
+
+	/* asm("st:"); */
+	n = ec->taps;
+	for (i = 0; i < n; i++) {
+		exp = *phist++ * factor;
+		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+	}
+	/* asm("en:"); */
+
+	/* Note the asm for the inner loop above generated by Blackfin gcc
+	   4.1.1 is pretty good (note even parallel instructions used):
+
+	   R0 = W [P0++] (X);
+	   R0 *= R2;
+	   R0 = R0 + R3 (NS) ||
+	   R1 = W [P1] (X) ||
+	   nop;
+	   R0 >>>= 15;
+	   R0 = R0 + R1;
+	   W [P1++] = R0;
+
+	   A block based update algorithm would be much faster but the
+	   above can't be improved on much.  Every instruction saved in
+	   the loop above is 2 MIPs/ch!  The for loop above is where the
+	   Blackfin spends most of it's time - about 17 MIPs/ch measured
+	   with speedtest.c with 256 taps (32ms).  Write-back and
+	   Write-through cache gave about the same performance.
+	 */
+}
+
+/*
+   IDEAS for further optimisation of lms_adapt_bg():
+
+   1/ The rounding is quite costly.  Could we keep as 32 bit coeffs
+   then make filter pluck the MS 16-bits of the coeffs when filtering?
+   However this would lower potential optimisation of filter, as I
+   think the dual-MAC architecture requires packed 16 bit coeffs.
+
+   2/ Block based update would be more efficient, as per comments above,
+   could use dual MAC architecture.
+
+   3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC
+   packing.
+
+   4/ Execute the whole e/c in a block of say 20ms rather than sample
+   by sample.  Processing a few samples every ms is inefficient.
+*/
+
+#else
+static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
+{
+	int i;
+
+	int offset1;
+	int offset2;
+	int factor;
+	int exp;
+
+	if (shift > 0)
+		factor = clean << shift;
+	else
+		factor = clean >> -shift;
+
+	/* Update the FIR taps */
+
+	offset2 = ec->curr_pos;
+	offset1 = ec->taps - offset2;
+
+	for (i = ec->taps - 1; i >= offset1; i--) {
+		exp = (ec->fir_state_bg.history[i - offset1] * factor);
+		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+	}
+	for (; i >= 0; i--) {
+		exp = (ec->fir_state_bg.history[i + offset2] * factor);
+		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+	}
+}
+#endif
+
+static inline int top_bit(unsigned int bits)
+{
+	if (bits == 0)
+		return -1;
+	else
+		return (int)fls((int32_t) bits) - 1;
+}
+
+struct oslec_state *oslec_create(int len, int adaption_mode)
+{
+	struct oslec_state *ec;
+	int i;
+	const int16_t *history;
+
+	ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+	if (!ec)
+		return NULL;
+
+	ec->taps = len;
+	ec->log2taps = top_bit(len);
+	ec->curr_pos = ec->taps - 1;
+
+	ec->fir_taps16[0] =
+	    kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
+	if (!ec->fir_taps16[0])
+		goto error_oom_0;
+
+	ec->fir_taps16[1] =
+	    kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
+	if (!ec->fir_taps16[1])
+		goto error_oom_1;
+
+	history = fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
+	if (!history)
+		goto error_state;
+	history = fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
+	if (!history)
+		goto error_state_bg;
+
+	for (i = 0; i < 5; i++)
+		ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
+
+	ec->cng_level = 1000;
+	oslec_adaption_mode(ec, adaption_mode);
+
+	ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
+	if (!ec->snapshot)
+		goto error_snap;
+
+	ec->cond_met = 0;
+	ec->pstates = 0;
+	ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
+	ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
+	ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+	ec->lbgn = ec->lbgn_acc = 0;
+	ec->lbgn_upper = 200;
+	ec->lbgn_upper_acc = ec->lbgn_upper << 13;
+
+	return ec;
+
+error_snap:
+	fir16_free(&ec->fir_state_bg);
+error_state_bg:
+	fir16_free(&ec->fir_state);
+error_state:
+	kfree(ec->fir_taps16[1]);
+error_oom_1:
+	kfree(ec->fir_taps16[0]);
+error_oom_0:
+	kfree(ec);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(oslec_create);
+
+void oslec_free(struct oslec_state *ec)
+{
+	int i;
+
+	fir16_free(&ec->fir_state);
+	fir16_free(&ec->fir_state_bg);
+	for (i = 0; i < 2; i++)
+		kfree(ec->fir_taps16[i]);
+	kfree(ec->snapshot);
+	kfree(ec);
+}
+EXPORT_SYMBOL_GPL(oslec_free);
+
+void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
+{
+	ec->adaption_mode = adaption_mode;
+}
+EXPORT_SYMBOL_GPL(oslec_adaption_mode);
+
+void oslec_flush(struct oslec_state *ec)
+{
+	int i;
+
+	ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
+	ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
+	ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+
+	ec->lbgn = ec->lbgn_acc = 0;
+	ec->lbgn_upper = 200;
+	ec->lbgn_upper_acc = ec->lbgn_upper << 13;
+
+	ec->nonupdate_dwell = 0;
+
+	fir16_flush(&ec->fir_state);
+	fir16_flush(&ec->fir_state_bg);
+	ec->fir_state.curr_pos = ec->taps - 1;
+	ec->fir_state_bg.curr_pos = ec->taps - 1;
+	for (i = 0; i < 2; i++)
+		memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
+
+	ec->curr_pos = ec->taps - 1;
+	ec->pstates = 0;
+}
+EXPORT_SYMBOL_GPL(oslec_flush);
+
+void oslec_snapshot(struct oslec_state *ec)
+{
+	memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
+}
+EXPORT_SYMBOL_GPL(oslec_snapshot);
+
+/* Dual Path Echo Canceller */
+
+int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
+{
+	int32_t echo_value;
+	int clean_bg;
+	int tmp;
+	int tmp1;
+
+	/*
+	 * Input scaling was found be required to prevent problems when tx
+	 * starts clipping.  Another possible way to handle this would be the
+	 * filter coefficent scaling.
+	 */
+
+	ec->tx = tx;
+	ec->rx = rx;
+	tx >>= 1;
+	rx >>= 1;
+
+	/*
+	 * Filter DC, 3dB point is 160Hz (I think), note 32 bit precision
+	 * required otherwise values do not track down to 0. Zero at DC, Pole
+	 * at (1-Beta) on real axis.  Some chip sets (like Si labs) don't
+	 * need this, but something like a $10 X100P card does.  Any DC really
+	 * slows down convergence.
+	 *
+	 * Note: removes some low frequency from the signal, this reduces the
+	 * speech quality when listening to samples through headphones but may
+	 * not be obvious through a telephone handset.
+	 *
+	 * Note that the 3dB frequency in radians is approx Beta, e.g. for Beta
+	 * = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
+	 */
+
+	if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
+		tmp = rx << 15;
+
+		/*
+		 * Make sure the gain of the HPF is 1.0. This can still
+		 * saturate a little under impulse conditions, and it might
+		 * roll to 32768 and need clipping on sustained peak level
+		 * signals. However, the scale of such clipping is small, and
+		 * the error due to any saturation should not markedly affect
+		 * the downstream processing.
+		 */
+		tmp -= (tmp >> 4);
+
+		ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
+
+		/*
+		 * hard limit filter to prevent clipping.  Note that at this
+		 * stage rx should be limited to +/- 16383 due to right shift
+		 * above
+		 */
+		tmp1 = ec->rx_1 >> 15;
+		if (tmp1 > 16383)
+			tmp1 = 16383;
+		if (tmp1 < -16383)
+			tmp1 = -16383;
+		rx = tmp1;
+		ec->rx_2 = tmp;
+	}
+
+	/* Block average of power in the filter states.  Used for
+	   adaption power calculation. */
+
+	{
+		int new, old;
+
+		/* efficient "out with the old and in with the new" algorithm so
+		   we don't have to recalculate over the whole block of
+		   samples. */
+		new = (int)tx * (int)tx;
+		old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
+		    (int)ec->fir_state.history[ec->fir_state.curr_pos];
+		ec->pstates +=
+		    ((new - old) + (1 << (ec->log2taps - 1))) >> ec->log2taps;
+		if (ec->pstates < 0)
+			ec->pstates = 0;
+	}
+
+	/* Calculate short term average levels using simple single pole IIRs */
+
+	ec->ltxacc += abs(tx) - ec->ltx;
+	ec->ltx = (ec->ltxacc + (1 << 4)) >> 5;
+	ec->lrxacc += abs(rx) - ec->lrx;
+	ec->lrx = (ec->lrxacc + (1 << 4)) >> 5;
+
+	/* Foreground filter */
+
+	ec->fir_state.coeffs = ec->fir_taps16[0];
+	echo_value = fir16(&ec->fir_state, tx);
+	ec->clean = rx - echo_value;
+	ec->lcleanacc += abs(ec->clean) - ec->lclean;
+	ec->lclean = (ec->lcleanacc + (1 << 4)) >> 5;
+
+	/* Background filter */
+
+	echo_value = fir16(&ec->fir_state_bg, tx);
+	clean_bg = rx - echo_value;
+	ec->lclean_bgacc += abs(clean_bg) - ec->lclean_bg;
+	ec->lclean_bg = (ec->lclean_bgacc + (1 << 4)) >> 5;
+
+	/* Background Filter adaption */
+
+	/* Almost always adap bg filter, just simple DT and energy
+	   detection to minimise adaption in cases of strong double talk.
+	   However this is not critical for the dual path algorithm.
+	 */
+	ec->factor = 0;
+	ec->shift = 0;
+	if ((ec->nonupdate_dwell == 0)) {
+		int p, logp, shift;
+
+		/* Determine:
+
+		   f = Beta * clean_bg_rx/P ------ (1)
+
+		   where P is the total power in the filter states.
+
+		   The Boffins have shown that if we obey (1) we converge
+		   quickly and avoid instability.
+
+		   The correct factor f must be in Q30, as this is the fixed
+		   point format required by the lms_adapt_bg() function,
+		   therefore the scaled version of (1) is:
+
+		   (2^30) * f  = (2^30) * Beta * clean_bg_rx/P
+		   factor      = (2^30) * Beta * clean_bg_rx/P     ----- (2)
+
+		   We have chosen Beta = 0.25 by experiment, so:
+
+		   factor      = (2^30) * (2^-2) * clean_bg_rx/P
+
+		   (30 - 2 - log2(P))
+		   factor      = clean_bg_rx 2                     ----- (3)
+
+		   To avoid a divide we approximate log2(P) as top_bit(P),
+		   which returns the position of the highest non-zero bit in
+		   P.  This approximation introduces an error as large as a
+		   factor of 2, but the algorithm seems to handle it OK.
+
+		   Come to think of it a divide may not be a big deal on a
+		   modern DSP, so its probably worth checking out the cycles
+		   for a divide versus a top_bit() implementation.
+		 */
+
+		p = MIN_TX_POWER_FOR_ADAPTION + ec->pstates;
+		logp = top_bit(p) + ec->log2taps;
+		shift = 30 - 2 - logp;
+		ec->shift = shift;
+
+		lms_adapt_bg(ec, clean_bg, shift);
+	}
+
+	/* very simple DTD to make sure we dont try and adapt with strong
+	   near end speech */
+
+	ec->adapt = 0;
+	if ((ec->lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->lrx > ec->ltx))
+		ec->nonupdate_dwell = DTD_HANGOVER;
+	if (ec->nonupdate_dwell)
+		ec->nonupdate_dwell--;
+
+	/* Transfer logic */
+
+	/* These conditions are from the dual path paper [1], I messed with
+	   them a bit to improve performance. */
+
+	if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
+	    (ec->nonupdate_dwell == 0) &&
+	    /* (ec->Lclean_bg < 0.875*ec->Lclean) */
+	    (8 * ec->lclean_bg < 7 * ec->lclean) &&
+	    /* (ec->Lclean_bg < 0.125*ec->Ltx) */
+	    (8 * ec->lclean_bg < ec->ltx)) {
+		if (ec->cond_met == 6) {
+			/*
+			 * BG filter has had better results for 6 consecutive
+			 * samples
+			 */
+			ec->adapt = 1;
+			memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
+			       ec->taps * sizeof(int16_t));
+		} else
+			ec->cond_met++;
+	} else
+		ec->cond_met = 0;
+
+	/* Non-Linear Processing */
+
+	ec->clean_nlp = ec->clean;
+	if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
+		/*
+		 * Non-linear processor - a fancy way to say "zap small
+		 * signals, to avoid residual echo due to (uLaw/ALaw)
+		 * non-linearity in the channel.".
+		 */
+
+		if ((16 * ec->lclean < ec->ltx)) {
+			/*
+			 * Our e/c has improved echo by at least 24 dB (each
+			 * factor of 2 is 6dB, so 2*2*2*2=16 is the same as
+			 * 6+6+6+6=24dB)
+			 */
+			if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
+				ec->cng_level = ec->lbgn;
+
+				/*
+				 * Very elementary comfort noise generation.
+				 * Just random numbers rolled off very vaguely
+				 * Hoth-like.  DR: This noise doesn't sound
+				 * quite right to me - I suspect there are some
+				 * overflow issues in the filtering as it's too
+				 * "crackly".
+				 * TODO: debug this, maybe just play noise at
+				 * high level or look at spectrum.
+				 */
+
+				ec->cng_rndnum =
+				    1664525U * ec->cng_rndnum + 1013904223U;
+				ec->cng_filter =
+				    ((ec->cng_rndnum & 0xFFFF) - 32768 +
+				     5 * ec->cng_filter) >> 3;
+				ec->clean_nlp =
+				    (ec->cng_filter * ec->cng_level * 8) >> 14;
+
+			} else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
+				/* This sounds much better than CNG */
+				if (ec->clean_nlp > ec->lbgn)
+					ec->clean_nlp = ec->lbgn;
+				if (ec->clean_nlp < -ec->lbgn)
+					ec->clean_nlp = -ec->lbgn;
+			} else {
+				/*
+				 * just mute the residual, doesn't sound very
+				 * good, used mainly in G168 tests
+				 */
+				ec->clean_nlp = 0;
+			}
+		} else {
+			/*
+			 * Background noise estimator.  I tried a few
+			 * algorithms here without much luck.  This very simple
+			 * one seems to work best, we just average the level
+			 * using a slow (1 sec time const) filter if the
+			 * current level is less than a (experimentally
+			 * derived) constant.  This means we dont include high
+			 * level signals like near end speech.  When combined
+			 * with CNG or especially CLIP seems to work OK.
+			 */
+			if (ec->lclean < 40) {
+				ec->lbgn_acc += abs(ec->clean) - ec->lbgn;
+				ec->lbgn = (ec->lbgn_acc + (1 << 11)) >> 12;
+			}
+		}
+	}
+
+	/* Roll around the taps buffer */
+	if (ec->curr_pos <= 0)
+		ec->curr_pos = ec->taps;
+	ec->curr_pos--;
+
+	if (ec->adaption_mode & ECHO_CAN_DISABLE)
+		ec->clean_nlp = rx;
+
+	/* Output scaled back up again to match input scaling */
+
+	return (int16_t) ec->clean_nlp << 1;
+}
+EXPORT_SYMBOL_GPL(oslec_update);
+
+/* This function is separated from the echo canceller is it is usually called
+   as part of the tx process.  See rx HP (DC blocking) filter above, it's
+   the same design.
+
+   Some soft phones send speech signals with a lot of low frequency
+   energy, e.g. down to 20Hz.  This can make the hybrid non-linear
+   which causes the echo canceller to fall over.  This filter can help
+   by removing any low frequency before it gets to the tx port of the
+   hybrid.
+
+   It can also help by removing and DC in the tx signal.  DC is bad
+   for LMS algorithms.
+
+   This is one of the classic DC removal filters, adjusted to provide
+   sufficient bass rolloff to meet the above requirement to protect hybrids
+   from things that upset them. The difference between successive samples
+   produces a lousy HPF, and then a suitably placed pole flattens things out.
+   The final result is a nicely rolled off bass end. The filtering is
+   implemented with extended fractional precision, which noise shapes things,
+   giving very clean DC removal.
+*/
+
+int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
+{
+	int tmp;
+	int tmp1;
+
+	if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
+		tmp = tx << 15;
+
+		/*
+		 * Make sure the gain of the HPF is 1.0. The first can still
+		 * saturate a little under impulse conditions, and it might
+		 * roll to 32768 and need clipping on sustained peak level
+		 * signals. However, the scale of such clipping is small, and
+		 * the error due to any saturation should not markedly affect
+		 * the downstream processing.
+		 */
+		tmp -= (tmp >> 4);
+
+		ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
+		tmp1 = ec->tx_1 >> 15;
+		if (tmp1 > 32767)
+			tmp1 = 32767;
+		if (tmp1 < -32767)
+			tmp1 = -32767;
+		tx = tmp1;
+		ec->tx_2 = tmp;
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(oslec_hpf_tx);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Rowe");
+MODULE_DESCRIPTION("Open Source Line Echo Canceller");
+MODULE_VERSION("0.3.0");
diff --git a/drivers/misc/echo/echo.h b/drivers/misc/echo/echo.h
new file mode 100644
index 000000000000..9b08c63e6369
--- /dev/null
+++ b/drivers/misc/echo/echo.h
@@ -0,0 +1,187 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * echo.c - A line echo canceller.  This code is being developed
+ *          against and partially complies with G168.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *         and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001 Steve Underwood and 2007 David Rowe
+ *
+ * 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.
+ *
+ * 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 __ECHO_H
+#define __ECHO_H
+
+/*
+Line echo cancellation for voice
+
+What does it do?
+
+This module aims to provide G.168-2002 compliant echo cancellation, to remove
+electrical echoes (e.g. from 2-4 wire hybrids) from voice calls.
+
+How does it work?
+
+The heart of the echo cancellor is FIR filter. This is adapted to match the
+echo impulse response of the telephone line. It must be long enough to
+adequately cover the duration of that impulse response. The signal transmitted
+to the telephone line is passed through the FIR filter. Once the FIR is
+properly adapted, the resulting output is an estimate of the echo signal
+received from the line. This is subtracted from the received signal. The result
+is an estimate of the signal which originated at the far end of the line, free
+from echos of our own transmitted signal.
+
+The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and
+was introduced in 1960. It is the commonest form of filter adaption used in
+things like modem line equalisers and line echo cancellers. There it works very
+well.  However, it only works well for signals of constant amplitude. It works
+very poorly for things like speech echo cancellation, where the signal level
+varies widely.  This is quite easy to fix. If the signal level is normalised -
+similar to applying AGC - LMS can work as well for a signal of varying
+amplitude as it does for a modem signal. This normalised least mean squares
+(NLMS) algorithm is the commonest one used for speech echo cancellation. Many
+other algorithms exist - e.g. RLS (essentially the same as Kalman filtering),
+FAP, etc. Some perform significantly better than NLMS.  However, factors such
+as computational complexity and patents favour the use of NLMS.
+
+A simple refinement to NLMS can improve its performance with speech. NLMS tends
+to adapt best to the strongest parts of a signal. If the signal is white noise,
+the NLMS algorithm works very well. However, speech has more low frequency than
+high frequency content. Pre-whitening (i.e. filtering the signal to flatten its
+spectrum) the echo signal improves the adapt rate for speech, and ensures the
+final residual signal is not heavily biased towards high frequencies. A very
+low complexity filter is adequate for this, so pre-whitening adds little to the
+compute requirements of the echo canceller.
+
+An FIR filter adapted using pre-whitened NLMS performs well, provided certain
+conditions are met:
+
+    - The transmitted signal has poor self-correlation.
+    - There is no signal being generated within the environment being
+      cancelled.
+
+The difficulty is that neither of these can be guaranteed.
+
+If the adaption is performed while transmitting noise (or something fairly
+noise like, such as voice) the adaption works very well. If the adaption is
+performed while transmitting something highly correlative (typically narrow
+band energy such as signalling tones or DTMF), the adaption can go seriously
+wrong. The reason is there is only one solution for the adaption on a near
+random signal - the impulse response of the line. For a repetitive signal,
+there are any number of solutions which converge the adaption, and nothing
+guides the adaption to choose the generalised one. Allowing an untrained
+canceller to converge on this kind of narrowband energy probably a good thing,
+since at least it cancels the tones. Allowing a well converged canceller to
+continue converging on such energy is just a way to ruin its generalised
+adaption. A narrowband detector is needed, so adapation can be suspended at
+appropriate times.
+
+The adaption process is based on trying to eliminate the received signal. When
+there is any signal from within the environment being cancelled it may upset
+the adaption process. Similarly, if the signal we are transmitting is small,
+noise may dominate and disturb the adaption process. If we can ensure that the
+adaption is only performed when we are transmitting a significant signal level,
+and the environment is not, things will be OK. Clearly, it is easy to tell when
+we are sending a significant signal. Telling, if the environment is generating
+a significant signal, and doing it with sufficient speed that the adaption will
+not have diverged too much more we stop it, is a little harder.
+
+The key problem in detecting when the environment is sourcing significant
+energy is that we must do this very quickly. Given a reasonably long sample of
+the received signal, there are a number of strategies which may be used to
+assess whether that signal contains a strong far end component. However, by the
+time that assessment is complete the far end signal will have already caused
+major mis-convergence in the adaption process. An assessment algorithm is
+needed which produces a fairly accurate result from a very short burst of far
+end energy.
+
+How do I use it?
+
+The echo cancellor processes both the transmit and receive streams sample by
+sample. The processing function is not declared inline. Unfortunately,
+cancellation requires many operations per sample, so the call overhead is only
+a minor burden.
+*/
+
+#include "fir.h"
+#include "oslec.h"
+
+/*
+    G.168 echo canceller descriptor. This defines the working state for a line
+    echo canceller.
+*/
+struct oslec_state {
+	int16_t tx;
+	int16_t rx;
+	int16_t clean;
+	int16_t clean_nlp;
+
+	int nonupdate_dwell;
+	int curr_pos;
+	int taps;
+	int log2taps;
+	int adaption_mode;
+
+	int cond_met;
+	int32_t pstates;
+	int16_t adapt;
+	int32_t factor;
+	int16_t shift;
+
+	/* Average levels and averaging filter states */
+	int ltxacc;
+	int lrxacc;
+	int lcleanacc;
+	int lclean_bgacc;
+	int ltx;
+	int lrx;
+	int lclean;
+	int lclean_bg;
+	int lbgn;
+	int lbgn_acc;
+	int lbgn_upper;
+	int lbgn_upper_acc;
+
+	/* foreground and background filter states */
+	struct fir16_state_t fir_state;
+	struct fir16_state_t fir_state_bg;
+	int16_t *fir_taps16[2];
+
+	/* DC blocking filter states */
+	int tx_1;
+	int tx_2;
+	int rx_1;
+	int rx_2;
+
+	/* optional High Pass Filter states */
+	int32_t xvtx[5];
+	int32_t yvtx[5];
+	int32_t xvrx[5];
+	int32_t yvrx[5];
+
+	/* Parameters for the optional Hoth noise generator */
+	int cng_level;
+	int cng_rndnum;
+	int cng_filter;
+
+	/* snapshot sample of coeffs used for development */
+	int16_t *snapshot;
+};
+
+#endif /* __ECHO_H */
diff --git a/drivers/misc/echo/fir.h b/drivers/misc/echo/fir.h
new file mode 100644
index 000000000000..7b9fabf1fea5
--- /dev/null
+++ b/drivers/misc/echo/fir.h
@@ -0,0 +1,216 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * fir.h - General telephony FIR routines
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2002 Steve Underwood
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#if !defined(_FIR_H_)
+#define _FIR_H_
+
+/*
+   Blackfin NOTES & IDEAS:
+
+   A simple dot product function is used to implement the filter.  This performs
+   just one MAC/cycle which is inefficient but was easy to implement as a first
+   pass.  The current Blackfin code also uses an unrolled form of the filter
+   history to avoid 0 length hardware loop issues.  This is wasteful of
+   memory.
+
+   Ideas for improvement:
+
+   1/ Rewrite filter for dual MAC inner loop.  The issue here is handling
+   history sample offsets that are 16 bit aligned - the dual MAC needs
+   32 bit aligmnent.  There are some good examples in libbfdsp.
+
+   2/ Use the hardware circular buffer facility tohalve memory usage.
+
+   3/ Consider using internal memory.
+
+   Using less memory might also improve speed as cache misses will be
+   reduced. A drop in MIPs and memory approaching 50% should be
+   possible.
+
+   The foreground and background filters currenlty use a total of
+   about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
+   can.
+*/
+
+/*
+ * 16 bit integer FIR descriptor. This defines the working state for a single
+ * instance of an FIR filter using 16 bit integer coefficients.
+ */
+struct fir16_state_t {
+	int taps;
+	int curr_pos;
+	const int16_t *coeffs;
+	int16_t *history;
+};
+
+/*
+ * 32 bit integer FIR descriptor. This defines the working state for a single
+ * instance of an FIR filter using 32 bit integer coefficients, and filtering
+ * 16 bit integer data.
+ */
+struct fir32_state_t {
+	int taps;
+	int curr_pos;
+	const int32_t *coeffs;
+	int16_t *history;
+};
+
+/*
+ * Floating point FIR descriptor. This defines the working state for a single
+ * instance of an FIR filter using floating point coefficients and data.
+ */
+struct fir_float_state_t {
+	int taps;
+	int curr_pos;
+	const float *coeffs;
+	float *history;
+};
+
+static inline const int16_t *fir16_create(struct fir16_state_t *fir,
+					      const int16_t *coeffs, int taps)
+{
+	fir->taps = taps;
+	fir->curr_pos = taps - 1;
+	fir->coeffs = coeffs;
+#if defined(__bfin__)
+	fir->history = kcalloc(2 * taps, sizeof(int16_t), GFP_KERNEL);
+#else
+	fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
+#endif
+	return fir->history;
+}
+
+static inline void fir16_flush(struct fir16_state_t *fir)
+{
+#if defined(__bfin__)
+	memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t));
+#else
+	memset(fir->history, 0, fir->taps * sizeof(int16_t));
+#endif
+}
+
+static inline void fir16_free(struct fir16_state_t *fir)
+{
+	kfree(fir->history);
+}
+
+#ifdef __bfin__
+static inline int32_t dot_asm(short *x, short *y, int len)
+{
+	int dot;
+
+	len--;
+
+	__asm__("I0 = %1;\n\t"
+		"I1 = %2;\n\t"
+		"A0 = 0;\n\t"
+		"R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+		"LOOP dot%= LC0 = %3;\n\t"
+		"LOOP_BEGIN dot%=;\n\t"
+		"A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+		"LOOP_END dot%=;\n\t"
+		"A0 += R0.L*R1.L (IS);\n\t"
+		"R0 = A0;\n\t"
+		"%0 = R0;\n\t"
+		: "=&d"(dot)
+		: "a"(x), "a"(y), "a"(len)
+		: "I0", "I1", "A1", "A0", "R0", "R1"
+	);
+
+	return dot;
+}
+#endif
+
+static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample)
+{
+	int32_t y;
+#if defined(__bfin__)
+	fir->history[fir->curr_pos] = sample;
+	fir->history[fir->curr_pos + fir->taps] = sample;
+	y = dot_asm((int16_t *) fir->coeffs, &fir->history[fir->curr_pos],
+		    fir->taps);
+#else
+	int i;
+	int offset1;
+	int offset2;
+
+	fir->history[fir->curr_pos] = sample;
+
+	offset2 = fir->curr_pos;
+	offset1 = fir->taps - offset2;
+	y = 0;
+	for (i = fir->taps - 1; i >= offset1; i--)
+		y += fir->coeffs[i] * fir->history[i - offset1];
+	for (; i >= 0; i--)
+		y += fir->coeffs[i] * fir->history[i + offset2];
+#endif
+	if (fir->curr_pos <= 0)
+		fir->curr_pos = fir->taps;
+	fir->curr_pos--;
+	return (int16_t) (y >> 15);
+}
+
+static inline const int16_t *fir32_create(struct fir32_state_t *fir,
+					      const int32_t *coeffs, int taps)
+{
+	fir->taps = taps;
+	fir->curr_pos = taps - 1;
+	fir->coeffs = coeffs;
+	fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
+	return fir->history;
+}
+
+static inline void fir32_flush(struct fir32_state_t *fir)
+{
+	memset(fir->history, 0, fir->taps * sizeof(int16_t));
+}
+
+static inline void fir32_free(struct fir32_state_t *fir)
+{
+	kfree(fir->history);
+}
+
+static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample)
+{
+	int i;
+	int32_t y;
+	int offset1;
+	int offset2;
+
+	fir->history[fir->curr_pos] = sample;
+	offset2 = fir->curr_pos;
+	offset1 = fir->taps - offset2;
+	y = 0;
+	for (i = fir->taps - 1; i >= offset1; i--)
+		y += fir->coeffs[i] * fir->history[i - offset1];
+	for (; i >= 0; i--)
+		y += fir->coeffs[i] * fir->history[i + offset2];
+	if (fir->curr_pos <= 0)
+		fir->curr_pos = fir->taps;
+	fir->curr_pos--;
+	return (int16_t) (y >> 15);
+}
+
+#endif
diff --git a/drivers/misc/echo/oslec.h b/drivers/misc/echo/oslec.h
new file mode 100644
index 000000000000..f4175360ce27
--- /dev/null
+++ b/drivers/misc/echo/oslec.h
@@ -0,0 +1,94 @@
+/*
+ *  OSLEC - A line echo canceller.  This code is being developed
+ *          against and partially complies with G168. Using code from SpanDSP
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *         and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001 Steve Underwood and 2007-2008 David Rowe
+ *
+ * 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.
+ *
+ * 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 __OSLEC_H
+#define __OSLEC_H
+
+/* Mask bits for the adaption mode */
+#define ECHO_CAN_USE_ADAPTION	0x01
+#define ECHO_CAN_USE_NLP	0x02
+#define ECHO_CAN_USE_CNG	0x04
+#define ECHO_CAN_USE_CLIP	0x08
+#define ECHO_CAN_USE_TX_HPF	0x10
+#define ECHO_CAN_USE_RX_HPF	0x20
+#define ECHO_CAN_DISABLE	0x40
+
+/**
+ * oslec_state: G.168 echo canceller descriptor.
+ *
+ * This defines the working state for a line echo canceller.
+ */
+struct oslec_state;
+
+/**
+ * oslec_create - Create a voice echo canceller context.
+ * @len: The length of the canceller, in samples.
+ * @return: The new canceller context, or NULL if the canceller could not be
+ * created.
+ */
+struct oslec_state *oslec_create(int len, int adaption_mode);
+
+/**
+ * oslec_free - Free a voice echo canceller context.
+ * @ec: The echo canceller context.
+ */
+void oslec_free(struct oslec_state *ec);
+
+/**
+ * oslec_flush - Flush (reinitialise) a voice echo canceller context.
+ * @ec: The echo canceller context.
+ */
+void oslec_flush(struct oslec_state *ec);
+
+/**
+ * oslec_adaption_mode - set the adaption mode of a voice echo canceller context.
+ * @ec The echo canceller context.
+ * @adaption_mode: The mode.
+ */
+void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode);
+
+void oslec_snapshot(struct oslec_state *ec);
+
+/**
+ * oslec_update: Process a sample through a voice echo canceller.
+ * @ec: The echo canceller context.
+ * @tx: The transmitted audio sample.
+ * @rx: The received audio sample.
+ *
+ * The return value is the clean (echo cancelled) received sample.
+ */
+int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx);
+
+/**
+ * oslec_hpf_tx: Process to high pass filter the tx signal.
+ * @ec: The echo canceller context.
+ * @tx: The transmitted auio sample.
+ *
+ * The return value is the HP filtered transmit sample, send this to your D/A.
+ */
+int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx);
+
+#endif /* __OSLEC_H */
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 4f3bca1003a1..634f72929e12 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c
index f0fa4e8ca124..33f8673d23a6 100644
--- a/drivers/misc/eeprom/eeprom.c
+++ b/drivers/misc/eeprom/eeprom.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index 78e55b501c94..9ebeacdb8ec4 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -11,7 +11,6 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index e36157d5d3ab..580ff9df5529 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -27,7 +27,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
index 9c34e5704304..3f2b625b2032 100644
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ b/drivers/misc/eeprom/sunxi_sid.c
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
@@ -96,7 +95,7 @@ static int sunxi_sid_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id sunxi_sid_of_match[] = {
-	{ .compatible = "allwinner,sun4i-sid", .data = (void *)16},
+	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
 	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
 	{/* sentinel */},
 };
diff --git a/drivers/misc/genwqe/card_debugfs.c b/drivers/misc/genwqe/card_debugfs.c
index 3bfdc07a7248..50d2096ea1c7 100644
--- a/drivers/misc/genwqe/card_debugfs.c
+++ b/drivers/misc/genwqe/card_debugfs.c
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
index 170bd3daf336..90520d76633f 100644
--- a/drivers/misc/hmc6352.c
+++ b/drivers/misc/hmc6352.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index e3183f26216b..12c30b486b27 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -26,7 +26,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index b7f84dacf822..4a9c50a43afb 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -23,7 +23,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c
index 61fbe6acabef..0a1565e63c71 100644
--- a/drivers/misc/lattice-ecp3-config.c
+++ b/drivers/misc/lattice-ecp3-config.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index 036effe9a795..3ef4627f9cb1 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -23,7 +23,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/types.h>
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index 7c97550240f1..d324f8a97b88 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index 9aa2bd2a71ae..bd06d0cfac45 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -10,7 +10,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/err.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 49c7a23f02fc..d66a2f24f6b3 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -30,6 +30,7 @@
  *
  * See Documentation/fault-injection/provoke-crashes.txt for instructions
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -45,6 +46,7 @@
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
 #include <linux/mman.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_IDE
 #include <linux/ide.h>
@@ -101,6 +103,7 @@ enum ctype {
 	CT_EXEC_USERSPACE,
 	CT_ACCESS_USERSPACE,
 	CT_WRITE_RO,
+	CT_WRITE_KERN,
 };
 
 static char* cp_name[] = {
@@ -137,6 +140,7 @@ static char* cp_type[] = {
 	"EXEC_USERSPACE",
 	"ACCESS_USERSPACE",
 	"WRITE_RO",
+	"WRITE_KERN",
 };
 
 static struct jprobe lkdtm;
@@ -316,6 +320,13 @@ static void do_nothing(void)
 	return;
 }
 
+/* Must immediately follow do_nothing for size calculuations to work out. */
+static void do_overwritten(void)
+{
+	pr_info("do_overwritten wasn't overwritten!\n");
+	return;
+}
+
 static noinline void corrupt_stack(void)
 {
 	/* Use default char array length that triggers stack protection. */
@@ -328,7 +339,12 @@ static void execute_location(void *dst)
 {
 	void (*func)(void) = dst;
 
+	pr_info("attempting ok execution at %p\n", do_nothing);
+	do_nothing();
+
 	memcpy(dst, do_nothing, EXEC_SIZE);
+	flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
+	pr_info("attempting bad execution at %p\n", func);
 	func();
 }
 
@@ -337,8 +353,13 @@ static void execute_user_location(void *dst)
 	/* Intentionally crossing kernel/user memory boundary. */
 	void (*func)(void) = dst;
 
+	pr_info("attempting ok execution at %p\n", do_nothing);
+	do_nothing();
+
 	if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE))
 		return;
+	flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
+	pr_info("attempting bad execution at %p\n", func);
 	func();
 }
 
@@ -463,8 +484,12 @@ static void lkdtm_do_action(enum ctype which)
 		}
 
 		ptr = (unsigned long *)user_addr;
+
+		pr_info("attempting bad read at %p\n", ptr);
 		tmp = *ptr;
 		tmp += 0xc0dec0de;
+
+		pr_info("attempting bad write at %p\n", ptr);
 		*ptr = tmp;
 
 		vm_munmap(user_addr, PAGE_SIZE);
@@ -475,10 +500,28 @@ static void lkdtm_do_action(enum ctype which)
 		unsigned long *ptr;
 
 		ptr = (unsigned long *)&rodata;
+
+		pr_info("attempting bad write at %p\n", ptr);
 		*ptr ^= 0xabcd1234;
 
 		break;
 	}
+	case CT_WRITE_KERN: {
+		size_t size;
+		unsigned char *ptr;
+
+		size = (unsigned long)do_overwritten -
+		       (unsigned long)do_nothing;
+		ptr = (unsigned char *)do_overwritten;
+
+		pr_info("attempting bad %zu byte write at %p\n", size, ptr);
+		memcpy(ptr, (unsigned char *)do_nothing, size);
+		flush_icache_range((unsigned long)ptr,
+				   (unsigned long)(ptr + size));
+
+		do_overwritten();
+		break;
+	}
 	case CT_NONE:
 	default:
 		break;
@@ -493,8 +536,8 @@ static void lkdtm_handler(void)
 
 	spin_lock_irqsave(&count_lock, flags);
 	count--;
-	printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
-			cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
+	pr_info("Crash point %s of type %s hit, trigger in %d rounds\n",
+		cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
 
 	if (count == 0) {
 		do_it = true;
@@ -551,18 +594,18 @@ static int lkdtm_register_cpoint(enum cname which)
 		lkdtm.kp.symbol_name = "generic_ide_ioctl";
 		lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
 #else
-		printk(KERN_INFO "lkdtm: Crash point not available\n");
+		pr_info("Crash point not available\n");
 		return -EINVAL;
 #endif
 		break;
 	default:
-		printk(KERN_INFO "lkdtm: Invalid Crash Point\n");
+		pr_info("Invalid Crash Point\n");
 		return -EINVAL;
 	}
 
 	cpoint = which;
 	if ((ret = register_jprobe(&lkdtm)) < 0) {
-		printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
+		pr_info("Couldn't register jprobe\n");
 		cpoint = CN_INVALID;
 	}
 
@@ -709,8 +752,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf,
 	if (type == CT_NONE)
 		return -EINVAL;
 
-	printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
-			cp_type_to_str(type));
+	pr_info("Performing direct entry %s\n", cp_type_to_str(type));
 	lkdtm_do_action(type);
 	*off += count;
 
@@ -772,7 +814,7 @@ static int __init lkdtm_module_init(void)
 	/* Register debugfs interface */
 	lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
 	if (!lkdtm_debugfs_root) {
-		printk(KERN_ERR "lkdtm: creating root dir failed\n");
+		pr_err("creating root dir failed\n");
 		return -ENODEV;
 	}
 
@@ -787,28 +829,26 @@ static int __init lkdtm_module_init(void)
 		de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
 				NULL, &cur->fops);
 		if (de == NULL) {
-			printk(KERN_ERR "lkdtm: could not create %s\n",
-					cur->name);
+			pr_err("could not create %s\n", cur->name);
 			goto out_err;
 		}
 	}
 
 	if (lkdtm_parse_commandline() == -EINVAL) {
-		printk(KERN_INFO "lkdtm: Invalid command\n");
+		pr_info("Invalid command\n");
 		goto out_err;
 	}
 
 	if (cpoint != CN_INVALID && cptype != CT_NONE) {
 		ret = lkdtm_register_cpoint(cpoint);
 		if (ret < 0) {
-			printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
-					cpoint);
+			pr_info("Invalid crash point %d\n", cpoint);
 			goto out_err;
 		}
-		printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n",
-				cpoint_name, cpoint_type);
+		pr_info("Crash point %s of type %s registered\n",
+			cpoint_name, cpoint_type);
 	} else {
-		printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n");
+		pr_info("No crash points registered, enable through debugfs\n");
 	}
 
 	return 0;
@@ -823,7 +863,7 @@ static void __exit lkdtm_module_exit(void)
 	debugfs_remove_recursive(lkdtm_debugfs_root);
 
 	unregister_jprobe(&lkdtm);
-	printk(KERN_INFO "lkdtm: Crash point unregistered\n");
+	pr_info("Crash point unregistered\n");
 }
 
 module_init(lkdtm_module_init);
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index c76fa31e9bf6..d23384dde73b 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -34,3 +34,12 @@ config INTEL_MEI_ME
 	  82Q33 Express
 	  82X38/X48 Express
 
+config INTEL_MEI_TXE
+	tristate "Intel Trusted Execution Environment with ME Interface"
+	select INTEL_MEI
+	depends on X86 && PCI && WATCHDOG_CORE
+	help
+	  MEI Support for Trusted Execution Environment device on Intel SoCs
+
+	  Supported SoCs:
+	  Intel Bay Trail
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 08698a466268..8ebc6cda1373 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -1,6 +1,6 @@
 #
 # Makefile - Intel Management Engine Interface (Intel MEI) Linux driver
-# Copyright (c) 2010-2011, Intel Corporation.
+# Copyright (c) 2010-2014, Intel Corporation.
 #
 obj-$(CONFIG_INTEL_MEI) += mei.o
 mei-objs := init.o
@@ -17,3 +17,7 @@ mei-$(CONFIG_DEBUG_FS) += debugfs.o
 obj-$(CONFIG_INTEL_MEI_ME) += mei-me.o
 mei-me-objs := pci-me.o
 mei-me-objs += hw-me.o
+
+obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
+mei-txe-objs := pci-txe.o
+mei-txe-objs += hw-txe.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 2fad84432829..f05d54d15e2f 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -21,7 +21,6 @@
 #include <linux/fcntl.h>
 #include <linux/aio.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/list.h>
@@ -79,10 +78,9 @@ int mei_amthif_host_init(struct mei_device *dev)
 
 	i = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
 	if (i < 0) {
-		ret = i;
 		dev_info(&dev->pdev->dev,
-			"amthif: failed to find the client %d\n", ret);
-		return ret;
+			"amthif: failed to find the client %d\n", i);
+		return -ENOTTY;
 	}
 
 	cl->me_client_id = dev->me_clients[i].client_id;
@@ -116,14 +114,11 @@ int mei_amthif_host_init(struct mei_device *dev)
 
 	cl->state = MEI_FILE_CONNECTING;
 
-	if (mei_hbm_cl_connect_req(dev, cl)) {
-		dev_dbg(&dev->pdev->dev, "amthif: Failed to connect to ME client\n");
-		cl->state = MEI_FILE_DISCONNECTED;
-		cl->host_client_id = 0;
-	} else {
-		cl->timer_count = MEI_CONNECT_TIMEOUT;
-	}
-	return 0;
+	ret = mei_cl_connect(cl, NULL);
+
+	dev->iamthif_state = MEI_IAMTHIF_IDLE;
+
+	return ret;
 }
 
 /**
@@ -137,14 +132,12 @@ int mei_amthif_host_init(struct mei_device *dev)
 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 						struct file *file)
 {
-	struct mei_cl_cb *pos = NULL;
-	struct mei_cl_cb *next = NULL;
+	struct mei_cl_cb *cb;
 
-	list_for_each_entry_safe(pos, next,
-				&dev->amthif_rd_complete_list.list, list) {
-		if (pos->cl && pos->cl == &dev->iamthif_cl &&
-			pos->file_object == file)
-			return pos;
+	list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) {
+		if (cb->cl && cb->cl == &dev->iamthif_cl &&
+			cb->file_object == file)
+			return cb;
 	}
 	return NULL;
 }
@@ -180,14 +173,13 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 	/* Only possible if we are in timeout */
 	if (!cl || cl != &dev->iamthif_cl) {
 		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
-		return -ETIMEDOUT;
+		return -ETIME;
 	}
 
 	i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-
 	if (i < 0) {
 		dev_dbg(&dev->pdev->dev, "amthif client not found.\n");
-		return -ENODEV;
+		return -ENOTTY;
 	}
 	dev_dbg(&dev->pdev->dev, "checking amthif data\n");
 	cb = mei_amthif_find_read_list_entry(dev, file);
@@ -228,7 +220,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 			dev_dbg(&dev->pdev->dev, "amthif Time out\n");
 			/* 15 sec for the message has expired */
 			list_del(&cb->list);
-			rets = -ETIMEDOUT;
+			rets = -ETIME;
 			goto free;
 		}
 	}
@@ -302,9 +294,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret < 0)
 		return ret;
 
-	if (ret && dev->hbuf_is_ready) {
+	if (ret && mei_hbuf_acquire(dev)) {
 		ret = 0;
-		dev->hbuf_is_ready = false;
 		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
 			mei_hdr.length = mei_hbuf_max_len(dev);
 			mei_hdr.msg_complete = 0;
@@ -336,10 +327,6 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 			list_add_tail(&cb->list, &dev->write_list.list);
 		}
 	} else {
-		if (!dev->hbuf_is_ready)
-			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
-		dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
 		list_add_tail(&cb->list, &dev->write_list.list);
 	}
 	return 0;
@@ -365,7 +352,7 @@ int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret)
 		return ret;
 
-	cb->fop_type = MEI_FOP_IOCTL;
+	cb->fop_type = MEI_FOP_WRITE;
 
 	if (!list_empty(&dev->amthif_cmd_list.list) ||
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
@@ -447,23 +434,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 
 
 /**
- * mei_amthif_irq_write_completed - processes completed iamthif operation.
+ * mei_amthif_irq_write - write iamthif command in irq thread context.
  *
  * @dev: the device structure.
- * @slots: free slots.
  * @cb_pos: callback block.
  * @cl: private data of the file object.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				  s32 *slots, struct mei_cl_cb *cmpl_list)
+int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+			 struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
 	struct mei_msg_hdr mei_hdr;
 	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
 	u32 msg_slots = mei_data2slots(len);
+	int slots;
 	int rets;
 
 	rets = mei_cl_flow_ctrl_creds(cl);
@@ -480,13 +467,15 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 	mei_hdr.reserved = 0;
 	mei_hdr.internal = 0;
 
-	if (*slots >= msg_slots) {
+	slots = mei_hbuf_empty_slots(dev);
+
+	if (slots >= msg_slots) {
 		mei_hdr.length = len;
 		mei_hdr.msg_complete = 1;
 	/* Split the message only if we can write the whole host buffer */
-	} else if (*slots == dev->hbuf_depth) {
-		msg_slots = *slots;
-		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+	} else if (slots == dev->hbuf_depth) {
+		msg_slots = slots;
+		len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
 		mei_hdr.length = len;
 		mei_hdr.msg_complete = 0;
 	} else {
@@ -496,7 +485,6 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
 
-	*slots -=  msg_slots;
 	rets = mei_write_message(dev, &mei_hdr,
 			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
 	if (rets) {
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 4bc7d620d695..463ae51fb708 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -145,9 +145,9 @@ static struct device_type mei_cl_device_type = {
 static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
 						uuid_le uuid)
 {
-	struct mei_cl *cl, *next;
+	struct mei_cl *cl;
 
-	list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
+	list_for_each_entry(cl, &dev->device_list, device_link) {
 		if (!uuid_le_cmp(uuid, cl->device_uuid))
 			return cl;
 	}
@@ -524,6 +524,22 @@ void mei_cl_bus_rx_event(struct mei_cl *cl)
 	schedule_work(&device->event_work);
 }
 
+void mei_cl_bus_remove_devices(struct mei_device *dev)
+{
+	struct mei_cl *cl, *next;
+
+	mutex_lock(&dev->device_lock);
+	list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
+		if (cl->device)
+			mei_cl_remove_device(cl->device);
+
+		list_del(&cl->device_link);
+		mei_cl_unlink(cl);
+		kfree(cl);
+	}
+	mutex_unlock(&dev->device_lock);
+}
+
 int __init mei_cl_bus_init(void)
 {
 	return bus_register(&mei_cl_bus_type);
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 89a557972d1b..753608185b77 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -29,20 +29,21 @@
  * mei_me_cl_by_uuid - locate index of me client
  *
  * @dev: mei device
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
  * returns me client index or -ENOENT if not found
  */
 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
 {
-	int i, res = -ENOENT;
+	int i;
 
 	for (i = 0; i < dev->me_clients_num; ++i)
 		if (uuid_le_cmp(*uuid,
-				dev->me_clients[i].props.protocol_name) == 0) {
-			res = i;
-			break;
-		}
+				dev->me_clients[i].props.protocol_name) == 0)
+			return i;
 
-	return res;
+	return -ENOENT;
 }
 
 
@@ -60,16 +61,12 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
 {
 	int i;
+
 	for (i = 0; i < dev->me_clients_num; i++)
 		if (dev->me_clients[i].client_id == client_id)
-			break;
-	if (WARN_ON(dev->me_clients[i].client_id != client_id))
-		return -ENOENT;
-
-	if (i == dev->me_clients_num)
-		return -ENOENT;
+			return i;
 
-	return i;
+	return -ENOENT;
 }
 
 
@@ -254,10 +251,9 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
 {
 	struct mei_device *dev = cl->dev;
-	struct mei_cl_cb *cb = NULL;
-	struct mei_cl_cb *next = NULL;
+	struct mei_cl_cb *cb;
 
-	list_for_each_entry_safe(cb, next, &dev->read_list.list, list)
+	list_for_each_entry(cb, &dev->read_list.list, list)
 		if (mei_cl_cmp_id(cl, cb->cl))
 			return cb;
 	return NULL;
@@ -375,6 +371,23 @@ void mei_host_client_init(struct work_struct *work)
 	mutex_unlock(&dev->device_lock);
 }
 
+/**
+ * mei_hbuf_acquire: try to acquire host buffer
+ *
+ * @dev: the device structure
+ * returns true if host buffer was acquired
+ */
+bool mei_hbuf_acquire(struct mei_device *dev)
+{
+	if (!dev->hbuf_is_ready) {
+		dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
+		return false;
+	}
+
+	dev->hbuf_is_ready = false;
+
+	return true;
+}
 
 /**
  * mei_cl_disconnect - disconnect host client from the me one
@@ -406,8 +419,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
 		return -ENOMEM;
 
 	cb->fop_type = MEI_FOP_CLOSE;
-	if (dev->hbuf_is_ready) {
-		dev->hbuf_is_ready = false;
+	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 			rets = -ENODEV;
 			cl_err(dev, cl, "failed to disconnect.\n");
@@ -461,17 +473,17 @@ free:
 bool mei_cl_is_other_connecting(struct mei_cl *cl)
 {
 	struct mei_device *dev;
-	struct mei_cl *pos;
-	struct mei_cl *next;
+	struct mei_cl *ocl; /* the other client */
 
 	if (WARN_ON(!cl || !cl->dev))
 		return false;
 
 	dev = cl->dev;
 
-	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
-		if ((pos->state == MEI_FILE_CONNECTING) &&
-		    (pos != cl) && cl->me_client_id == pos->me_client_id)
+	list_for_each_entry(ocl, &dev->file_list, link) {
+		if (ocl->state == MEI_FILE_CONNECTING &&
+		    ocl != cl &&
+		    cl->me_client_id == ocl->me_client_id)
 			return true;
 
 	}
@@ -505,11 +517,10 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 		goto out;
 	}
 
-	cb->fop_type = MEI_FOP_IOCTL;
-
-	if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
-		dev->hbuf_is_ready = false;
+	cb->fop_type = MEI_FOP_CONNECT;
 
+	/* run hbuf acquire last so we don't have to undo */
+	if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_connect_req(dev, cl)) {
 			rets = -ENODEV;
 			goto out;
@@ -521,18 +532,19 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 	}
 
 	mutex_unlock(&dev->device_lock);
-	rets = wait_event_timeout(dev->wait_recvd_msg,
-				 (cl->state == MEI_FILE_CONNECTED ||
-				  cl->state == MEI_FILE_DISCONNECTED),
-				 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
+	wait_event_timeout(dev->wait_recvd_msg,
+			(cl->state == MEI_FILE_CONNECTED ||
+			 cl->state == MEI_FILE_DISCONNECTED),
+			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 
 	if (cl->state != MEI_FILE_CONNECTED) {
-		rets = -EFAULT;
+		/* something went really wrong */
+		if (!cl->status)
+			cl->status = -EFAULT;
 
 		mei_io_list_flush(&dev->ctrl_rd_list, cl);
 		mei_io_list_flush(&dev->ctrl_wr_list, cl);
-		goto out;
 	}
 
 	rets = cl->status;
@@ -554,7 +566,8 @@ out:
 int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
 {
 	struct mei_device *dev;
-	int i;
+	struct mei_me_client *me_cl;
+	int id;
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
@@ -567,19 +580,19 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
 	if (cl->mei_flow_ctrl_creds > 0)
 		return 1;
 
-	for (i = 0; i < dev->me_clients_num; i++) {
-		struct mei_me_client  *me_cl = &dev->me_clients[i];
-		if (me_cl->client_id == cl->me_client_id) {
-			if (me_cl->mei_flow_ctrl_creds) {
-				if (WARN_ON(me_cl->props.single_recv_buf == 0))
-					return -EINVAL;
-				return 1;
-			} else {
-				return 0;
-			}
-		}
+	id = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (id < 0) {
+		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
+		return id;
 	}
-	return -ENOENT;
+
+	me_cl = &dev->me_clients[id];
+	if (me_cl->mei_flow_ctrl_creds) {
+		if (WARN_ON(me_cl->props.single_recv_buf == 0))
+			return -EINVAL;
+		return 1;
+	}
+	return 0;
 }
 
 /**
@@ -595,32 +608,31 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
 int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
 {
 	struct mei_device *dev;
-	int i;
+	struct mei_me_client *me_cl;
+	int id;
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
 
 	dev = cl->dev;
 
-	if (!dev->me_clients_num)
-		return -ENOENT;
+	id = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (id < 0) {
+		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
+		return id;
+	}
 
-	for (i = 0; i < dev->me_clients_num; i++) {
-		struct mei_me_client  *me_cl = &dev->me_clients[i];
-		if (me_cl->client_id == cl->me_client_id) {
-			if (me_cl->props.single_recv_buf != 0) {
-				if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
-					return -EINVAL;
-				dev->me_clients[i].mei_flow_ctrl_creds--;
-			} else {
-				if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
-					return -EINVAL;
-				cl->mei_flow_ctrl_creds--;
-			}
-			return 0;
-		}
+	me_cl = &dev->me_clients[id];
+	if (me_cl->props.single_recv_buf != 0) {
+		if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
+			return -EINVAL;
+		me_cl->mei_flow_ctrl_creds--;
+	} else {
+		if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
+			return -EINVAL;
+		cl->mei_flow_ctrl_creds--;
 	}
-	return -ENOENT;
+	return 0;
 }
 
 /**
@@ -652,7 +664,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 	i = mei_me_cl_by_id(dev, cl->me_client_id);
 	if (i < 0) {
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
-		return  -ENODEV;
+		return  -ENOTTY;
 	}
 
 	cb = mei_io_cb_init(cl, NULL);
@@ -666,8 +678,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 		goto err;
 
 	cb->fop_type = MEI_FOP_READ;
-	if (dev->hbuf_is_ready) {
-		dev->hbuf_is_ready = false;
+	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
 			cl_err(dev, cl, "flow control send failed\n");
 			rets = -ENODEV;
@@ -687,27 +698,26 @@ err:
 }
 
 /**
- * mei_cl_irq_write_complete - write a message to device
+ * mei_cl_irq_write - write a message to device
  *	from the interrupt thread context
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise error.
  */
-int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				     s32 *slots, struct mei_cl_cb *cmpl_list)
+int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+		     struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev;
 	struct mei_msg_data *buf;
 	struct mei_msg_hdr mei_hdr;
 	size_t len;
 	u32 msg_slots;
+	int slots;
 	int rets;
 
-
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
 
@@ -724,6 +734,7 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 		return 0;
 	}
 
+	slots = mei_hbuf_empty_slots(dev);
 	len = buf->size - cb->buf_idx;
 	msg_slots = mei_data2slots(len);
 
@@ -732,13 +743,13 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 	mei_hdr.reserved = 0;
 	mei_hdr.internal = cb->internal;
 
-	if (*slots >= msg_slots) {
+	if (slots >= msg_slots) {
 		mei_hdr.length = len;
 		mei_hdr.msg_complete = 1;
 	/* Split the message only if we can write the whole host buffer */
-	} else if (*slots == dev->hbuf_depth) {
-		msg_slots = *slots;
-		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+	} else if (slots == dev->hbuf_depth) {
+		msg_slots = slots;
+		len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
 		mei_hdr.length = len;
 		mei_hdr.msg_complete = 0;
 	} else {
@@ -749,7 +760,6 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 	cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
 			cb->request_buffer.size, cb->buf_idx);
 
-	*slots -=  msg_slots;
 	rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
 	if (rets) {
 		cl->status = rets;
@@ -802,21 +812,29 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
 
 	cb->fop_type = MEI_FOP_WRITE;
+	cb->buf_idx = 0;
+	cl->writing_state = MEI_IDLE;
+
+	mei_hdr.host_addr = cl->host_client_id;
+	mei_hdr.me_addr = cl->me_client_id;
+	mei_hdr.reserved = 0;
+	mei_hdr.msg_complete = 0;
+	mei_hdr.internal = cb->internal;
 
 	rets = mei_cl_flow_ctrl_creds(cl);
 	if (rets < 0)
 		goto err;
 
-	/* Host buffer is not ready, we queue the request */
-	if (rets == 0 || !dev->hbuf_is_ready) {
-		cb->buf_idx = 0;
-		/* unseting complete will enqueue the cb for write */
-		mei_hdr.msg_complete = 0;
+	if (rets == 0) {
+		cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+		rets = buf->size;
+		goto out;
+	}
+	if (!mei_hbuf_acquire(dev)) {
+		cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
 		rets = buf->size;
 		goto out;
 	}
-
-	dev->hbuf_is_ready = false;
 
 	/* Check for a maximum length */
 	if (buf->size > mei_hbuf_max_len(dev)) {
@@ -827,12 +845,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 		mei_hdr.msg_complete = 1;
 	}
 
-	mei_hdr.host_addr = cl->host_client_id;
-	mei_hdr.me_addr = cl->me_client_id;
-	mei_hdr.reserved = 0;
-	mei_hdr.internal = cb->internal;
-
-
 	rets = mei_write_message(dev, &mei_hdr, buf->data);
 	if (rets)
 		goto err;
@@ -840,13 +852,12 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 	cl->writing_state = MEI_WRITING;
 	cb->buf_idx = mei_hdr.length;
 
-	rets = buf->size;
 out:
 	if (mei_hdr.msg_complete) {
-		if (mei_cl_flow_ctrl_reduce(cl)) {
-			rets = -ENODEV;
+		rets = mei_cl_flow_ctrl_reduce(cl);
+		if (rets < 0)
 			goto err;
-		}
+
 		list_add_tail(&cb->list, &dev->write_waiting_list.list);
 	} else {
 		list_add_tail(&cb->list, &dev->write_list.list);
@@ -856,15 +867,18 @@ out:
 	if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
 
 		mutex_unlock(&dev->device_lock);
-		if (wait_event_interruptible(cl->tx_wait,
-			cl->writing_state == MEI_WRITE_COMPLETE)) {
-				if (signal_pending(current))
-					rets = -EINTR;
-				else
-					rets = -ERESTARTSYS;
-		}
+		rets = wait_event_interruptible(cl->tx_wait,
+				cl->writing_state == MEI_WRITE_COMPLETE);
 		mutex_lock(&dev->device_lock);
+		/* wait_event_interruptible returns -ERESTARTSYS */
+		if (rets) {
+			if (signal_pending(current))
+				rets = -EINTR;
+			goto err;
+		}
 	}
+
+	rets = buf->size;
 err:
 	return rets;
 }
@@ -905,9 +919,9 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 
 void mei_cl_all_disconnect(struct mei_device *dev)
 {
-	struct mei_cl *cl, *next;
+	struct mei_cl *cl;
 
-	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+	list_for_each_entry(cl, &dev->file_list, link) {
 		cl->state = MEI_FILE_DISCONNECTED;
 		cl->mei_flow_ctrl_creds = 0;
 		cl->timer_count = 0;
@@ -922,8 +936,8 @@ void mei_cl_all_disconnect(struct mei_device *dev)
  */
 void mei_cl_all_wakeup(struct mei_device *dev)
 {
-	struct mei_cl *cl, *next;
-	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+	struct mei_cl *cl;
+	list_for_each_entry(cl, &dev->file_list, link) {
 		if (waitqueue_active(&cl->rx_wait)) {
 			cl_dbg(dev, cl, "Waking up reading client!\n");
 			wake_up_interruptible(&cl->rx_wait);
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index c8396e582f1c..c11b663358a4 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -102,8 +102,8 @@ int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
 int mei_cl_read_start(struct mei_cl *cl, size_t length);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
-int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				s32 *slots, struct mei_cl_cb *cmpl_list);
+int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+		     struct mei_cl_cb *cmpl_list);
 
 void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
 
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index a3ae154444b2..ced5b777c70f 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -75,6 +75,54 @@ static const struct file_operations mei_dbgfs_fops_meclients = {
 	.llseek = generic_file_llseek,
 };
 
+static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	struct mei_device *dev = fp->private_data;
+	struct mei_cl *cl;
+	const size_t bufsz = 1024;
+	char *buf;
+	int i = 0;
+	int pos = 0;
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if  (!buf)
+		return -ENOMEM;
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"  |me|host|state|rd|wr|\n");
+
+	mutex_lock(&dev->device_lock);
+
+	/*  if the driver is not enabled the list won't b consitent */
+	if (dev->dev_state != MEI_DEV_ENABLED)
+		goto out;
+
+	list_for_each_entry(cl, &dev->file_list, link) {
+
+		pos += scnprintf(buf + pos, bufsz - pos,
+			"%2d|%2d|%4d|%5d|%2d|%2d|\n",
+			i, cl->me_client_id, cl->host_client_id, cl->state,
+			cl->reading_state, cl->writing_state);
+		i++;
+	}
+out:
+	mutex_unlock(&dev->device_lock);
+	ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations mei_dbgfs_fops_active = {
+	.open = simple_open,
+	.read = mei_dbgfs_read_active,
+	.llseek = generic_file_llseek,
+};
+
 static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
 					size_t cnt, loff_t *ppos)
 {
@@ -128,6 +176,12 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name)
 		dev_err(&dev->pdev->dev, "meclients: registration failed\n");
 		goto err;
 	}
+	f = debugfs_create_file("active", S_IRUSR, dir,
+				dev, &mei_dbgfs_fops_active);
+	if (!f) {
+		dev_err(&dev->pdev->dev, "meclients: registration failed\n");
+		goto err;
+	}
 	f = debugfs_create_file("devstate", S_IRUSR, dir,
 				dev, &mei_dbgfs_fops_devstate);
 	if (!f) {
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 28cd74c073b9..9555791c010b 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -22,6 +22,41 @@
 #include "mei_dev.h"
 #include "hbm.h"
 #include "hw-me.h"
+#include "client.h"
+
+static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
+{
+#define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
+	switch (status) {
+	MEI_CL_CS(SUCCESS);
+	MEI_CL_CS(NOT_FOUND);
+	MEI_CL_CS(ALREADY_STARTED);
+	MEI_CL_CS(OUT_OF_RESOURCES);
+	MEI_CL_CS(MESSAGE_SMALL);
+	default: return "unknown";
+	}
+#undef MEI_CL_CCS
+}
+
+/**
+ * mei_cl_conn_status_to_errno - convert client connect response
+ * status to error code
+ *
+ * @status: client connect response status
+ *
+ * returns corresponding error code
+ */
+static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
+{
+	switch (status) {
+	case MEI_CL_CONN_SUCCESS:          return 0;
+	case MEI_CL_CONN_NOT_FOUND:        return -ENOTTY;
+	case MEI_CL_CONN_ALREADY_STARTED:  return -EBUSY;
+	case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY;
+	case MEI_CL_CONN_MESSAGE_SMALL:    return -EINVAL;
+	default:                           return -EINVAL;
+	}
+}
 
 /**
  * mei_hbm_me_cl_allocate - allocates storage for me clients
@@ -100,33 +135,6 @@ bool mei_hbm_cl_addr_equal(struct mei_cl *cl, void *buf)
 
 
 /**
- * is_treat_specially_client - checks if the message belongs
- * to the file private data.
- *
- * @cl: private data of the file object
- * @rs: connect response bus message
- *
- */
-static bool is_treat_specially_client(struct mei_cl *cl,
-		struct hbm_client_connect_response *rs)
-{
-	if (mei_hbm_cl_addr_equal(cl, rs)) {
-		if (!rs->status) {
-			cl->state = MEI_FILE_CONNECTED;
-			cl->status = 0;
-
-		} else {
-			cl->state = MEI_FILE_DISCONNECTED;
-			cl->status = -ENODEV;
-		}
-		cl->timer_count = 0;
-
-		return true;
-	}
-	return false;
-}
-
-/**
  * mei_hbm_idle - set hbm to idle state
  *
  * @dev: the device structure
@@ -147,13 +155,13 @@ int mei_hbm_start_wait(struct mei_device *dev)
 	ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
 			dev->hbm_state == MEI_HBM_IDLE ||
 			dev->hbm_state >= MEI_HBM_STARTED,
-			mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
+			mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 
 	if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
 		dev->hbm_state = MEI_HBM_IDLE;
 		dev_err(&dev->pdev->dev, "waiting for mei start failed\n");
-		return -ETIMEDOUT;
+		return -ETIME;
 	}
 	return 0;
 }
@@ -283,17 +291,18 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 }
 
 /**
- * mei_hbm_stop_req_prepare - prepare stop request message
+ * mei_hbm_stop_req - send stop request message
  *
  * @dev - mei device
- * @mei_hdr - mei message header
- * @data - hbm message body buffer
+ * @cl: client info
+ *
+ * This function returns -EIO on write failure
  */
-static void mei_hbm_stop_req_prepare(struct mei_device *dev,
-		struct mei_msg_hdr *mei_hdr, unsigned char *data)
+static int mei_hbm_stop_req(struct mei_device *dev)
 {
+	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	struct hbm_host_stop_request *req =
-			(struct hbm_host_stop_request *)data;
+			(struct hbm_host_stop_request *)dev->wr_msg.data;
 	const size_t len = sizeof(struct hbm_host_stop_request);
 
 	mei_hbm_hdr(mei_hdr, len);
@@ -301,6 +310,8 @@ static void mei_hbm_stop_req_prepare(struct mei_device *dev,
 	memset(req, 0, len);
 	req->hbm_cmd = HOST_STOP_REQ_CMD;
 	req->reason = DRIVER_STOP_REQUEST;
+
+	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 }
 
 /**
@@ -330,27 +341,34 @@ int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
  *
  * @dev: the device structure
  * @flow: flow control.
+ *
+ * return 0 on success, < 0 otherwise
  */
-static void mei_hbm_add_single_flow_creds(struct mei_device *dev,
+static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
 				  struct hbm_flow_control *flow)
 {
-	struct mei_me_client *client;
-	int i;
-
-	for (i = 0; i < dev->me_clients_num; i++) {
-		client = &dev->me_clients[i];
-		if (client && flow->me_addr == client->client_id) {
-			if (client->props.single_recv_buf) {
-				client->mei_flow_ctrl_creds++;
-				dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
-				    flow->me_addr);
-				dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
-				    client->mei_flow_ctrl_creds);
-			} else {
-				BUG();	/* error in flow control */
-			}
-		}
+	struct mei_me_client *me_cl;
+	int id;
+
+	id = mei_me_cl_by_id(dev, flow->me_addr);
+	if (id < 0) {
+		dev_err(&dev->pdev->dev, "no such me client %d\n",
+			flow->me_addr);
+		return id;
 	}
+
+	me_cl = &dev->me_clients[id];
+	if (me_cl->props.single_recv_buf) {
+		me_cl->mei_flow_ctrl_creds++;
+		dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
+		    flow->me_addr);
+		dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
+		    me_cl->mei_flow_ctrl_creds);
+	} else {
+		BUG();	/* error in flow control */
+	}
+
+	return 0;
 }
 
 /**
@@ -362,8 +380,7 @@ static void mei_hbm_add_single_flow_creds(struct mei_device *dev,
 static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
 		struct hbm_flow_control *flow_control)
 {
-	struct mei_cl *cl = NULL;
-	struct mei_cl *next = NULL;
+	struct mei_cl *cl;
 
 	if (!flow_control->host_addr) {
 		/* single receive buffer */
@@ -372,7 +389,7 @@ static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
 	}
 
 	/* normal connection */
-	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+	list_for_each_entry(cl, &dev->file_list, link) {
 		if (mei_hbm_cl_addr_equal(cl, flow_control)) {
 			cl->mei_flow_ctrl_creds++;
 			dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
@@ -405,6 +422,25 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
 }
 
 /**
+ * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
+ *
+ * @dev: the device structure
+ * @cl: a client to disconnect from
+ *
+ * This function returns -EIO on write failure
+ */
+int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
+{
+	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+	const size_t len = sizeof(struct hbm_client_connect_response);
+
+	mei_hbm_hdr(mei_hdr, len);
+	mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, dev->wr_msg.data, len);
+
+	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+}
+
+/**
  * mei_hbm_cl_disconnect_res - disconnect response from ME
  *
  * @dev: the device structure
@@ -414,29 +450,23 @@ static void mei_hbm_cl_disconnect_res(struct mei_device *dev,
 		struct hbm_client_connect_response *rs)
 {
 	struct mei_cl *cl;
-	struct mei_cl_cb *pos = NULL, *next = NULL;
-
-	dev_dbg(&dev->pdev->dev,
-			"disconnect_response:\n"
-			"ME Client = %d\n"
-			"Host Client = %d\n"
-			"Status = %d\n",
-			rs->me_addr,
-			rs->host_addr,
-			rs->status);
-
-	list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
-		cl = pos->cl;
-
-		if (!cl) {
-			list_del(&pos->list);
+	struct mei_cl_cb *cb, *next;
+
+	dev_dbg(&dev->pdev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
+			rs->me_addr, rs->host_addr, rs->status);
+
+	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
+		cl = cb->cl;
+
+		/* this should not happen */
+		if (WARN_ON(!cl)) {
+			list_del(&cb->list);
 			return;
 		}
 
-		dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
 		if (mei_hbm_cl_addr_equal(cl, rs)) {
-			list_del(&pos->list);
-			if (!rs->status)
+			list_del(&cb->list);
+			if (rs->status == MEI_CL_DISCONN_SUCCESS)
 				cl->state = MEI_FILE_DISCONNECTED;
 
 			cl->status = 0;
@@ -476,46 +506,41 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
 {
 
 	struct mei_cl *cl;
-	struct mei_cl_cb *pos = NULL, *next = NULL;
+	struct mei_cl_cb *cb, *next;
 
-	dev_dbg(&dev->pdev->dev,
-			"connect_response:\n"
-			"ME Client = %d\n"
-			"Host Client = %d\n"
-			"Status = %d\n",
-			rs->me_addr,
-			rs->host_addr,
-			rs->status);
+	dev_dbg(&dev->pdev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
+			rs->me_addr, rs->host_addr,
+			mei_cl_conn_status_str(rs->status));
 
-	/* if WD or iamthif client treat specially */
+	cl = NULL;
 
-	if (is_treat_specially_client(&dev->wd_cl, rs)) {
-		dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
-		mei_watchdog_register(dev);
+	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
 
-		return;
-	}
+		cl = cb->cl;
+		/* this should not happen */
+		if (WARN_ON(!cl)) {
+			list_del_init(&cb->list);
+			continue;
+		}
 
-	if (is_treat_specially_client(&dev->iamthif_cl, rs)) {
-		dev->iamthif_state = MEI_IAMTHIF_IDLE;
-		return;
-	}
-	list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
+		if (cb->fop_type !=  MEI_FOP_CONNECT)
+			continue;
 
-		cl = pos->cl;
-		if (!cl) {
-			list_del(&pos->list);
-			return;
-		}
-		if (pos->fop_type == MEI_FOP_IOCTL) {
-			if (is_treat_specially_client(cl, rs)) {
-				list_del(&pos->list);
-				cl->status = 0;
-				cl->timer_count = 0;
-				break;
-			}
+		if (mei_hbm_cl_addr_equal(cl, rs)) {
+			list_del(&cb->list);
+			break;
 		}
 	}
+
+	if (!cl)
+		return;
+
+	cl->timer_count = 0;
+	if (rs->status == MEI_CL_CONN_SUCCESS)
+		cl->state = MEI_FILE_CONNECTED;
+	else
+		cl->state = MEI_FILE_DISCONNECTED;
+	cl->status = mei_cl_conn_status_to_errno(rs->status);
 }
 
 
@@ -525,32 +550,34 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
  *
  * @dev: the device structure.
  * @disconnect_req: disconnect request bus message from the me
+ *
+ * returns -ENOMEM on allocation failure
  */
-static void mei_hbm_fw_disconnect_req(struct mei_device *dev,
+static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 		struct hbm_client_connect_request *disconnect_req)
 {
-	struct mei_cl *cl, *next;
-	const size_t len = sizeof(struct hbm_client_connect_response);
+	struct mei_cl *cl;
+	struct mei_cl_cb *cb;
 
-	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+	list_for_each_entry(cl, &dev->file_list, link) {
 		if (mei_hbm_cl_addr_equal(cl, disconnect_req)) {
 			dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
 					disconnect_req->host_addr,
 					disconnect_req->me_addr);
 			cl->state = MEI_FILE_DISCONNECTED;
 			cl->timer_count = 0;
-			if (cl == &dev->wd_cl)
-				dev->wd_pending = false;
-			else if (cl == &dev->iamthif_cl)
-				dev->iamthif_timer = 0;
-
-			/* prepare disconnect response */
-			mei_hbm_hdr(&dev->wr_ext_msg.hdr, len);
-			mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD,
-					 dev->wr_ext_msg.data, len);
+
+			cb = mei_io_cb_init(cl, NULL);
+			if (!cb)
+				return -ENOMEM;
+			cb->fop_type = MEI_FOP_DISCONNECT_RSP;
+			cl_dbg(dev, cl, "add disconnect response as first\n");
+			list_add(&cb->list, &dev->ctrl_wr_list.list);
+
 			break;
 		}
 	}
+	return 0;
 }
 
 
@@ -629,10 +656,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 			dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n");
 
 			dev->hbm_state = MEI_HBM_STOPPED;
-			mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
-						dev->wr_msg.data);
-			if (mei_write_message(dev, &dev->wr_msg.hdr,
-					dev->wr_msg.data)) {
+			if (mei_hbm_stop_req(dev)) {
 				dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
 				return -EIO;
 			}
@@ -778,10 +802,11 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 
 	case ME_STOP_REQ_CMD:
 		dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n");
-
 		dev->hbm_state = MEI_HBM_STOPPED;
-		mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
-					dev->wr_ext_msg.data);
+		if (mei_hbm_stop_req(dev)) {
+			dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
+			return -EIO;
+		}
 		break;
 	default:
 		BUG();
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index 5f92188a5cd7..20e8782711c0 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -54,6 +54,7 @@ int mei_hbm_start_req(struct mei_device *dev);
 int mei_hbm_start_wait(struct mei_device *dev);
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
+int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
 bool mei_hbm_version_is_supported(struct mei_device *dev);
 
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 6f656c053b14..7e769c59a420 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -240,11 +240,11 @@ static int mei_me_hw_ready_wait(struct mei_device *dev)
 	mutex_unlock(&dev->device_lock);
 	err = wait_event_interruptible_timeout(dev->wait_hw_ready,
 			dev->recvd_hw_ready,
-			mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
+			mei_secs_to_jiffies(MEI_HW_READY_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 	if (!err && !dev->recvd_hw_ready) {
 		if (!err)
-			err = -ETIMEDOUT;
+			err = -ETIME;
 		dev_err(&dev->pdev->dev,
 			"wait hw ready failed. status = %d\n", err);
 		return err;
@@ -303,7 +303,7 @@ static bool mei_me_hbuf_is_empty(struct mei_device *dev)
  *
  * @dev: the device structure
  *
- * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
+ * returns -EOVERFLOW if overflow, otherwise empty slots count
  */
 static int mei_me_hbuf_empty_slots(struct mei_device *dev)
 {
@@ -326,7 +326,7 @@ static size_t mei_me_hbuf_max_len(const struct mei_device *dev)
 
 
 /**
- * mei_write_message - writes a message to mei device.
+ * mei_me_write_message - writes a message to mei device.
  *
  * @dev: the device structure
  * @header: mei HECI header of message
@@ -354,7 +354,7 @@ static int mei_me_write_message(struct mei_device *dev,
 
 	dw_cnt = mei_data2slots(length);
 	if (empty_slots < 0 || dw_cnt > empty_slots)
-		return -EIO;
+		return -EMSGSIZE;
 
 	mei_me_reg_write(hw, H_CB_WW, *((u32 *) header));
 
@@ -381,7 +381,7 @@ static int mei_me_write_message(struct mei_device *dev,
  *
  * @dev: the device structure
  *
- * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
+ * returns -EOVERFLOW if overflow, otherwise filled slots count
  */
 static int mei_me_count_full_read_slots(struct mei_device *dev)
 {
@@ -505,9 +505,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	/* check slots available for reading */
 	slots = mei_count_full_read_slots(dev);
 	while (slots > 0) {
-		/* we have urgent data to send so break the read */
-		if (dev->wr_ext_msg.hdr.length)
-			break;
 		dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots);
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
@@ -516,6 +513,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 		}
 	}
 
+	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
+
 	rets = mei_irq_write_handler(dev, &complete_list);
 
 	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 80bd829fbd9a..893d5119fa9b 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -20,6 +20,7 @@
 #define _MEI_INTERFACE_H_
 
 #include <linux/mei.h>
+#include <linux/irqreturn.h>
 #include "mei_dev.h"
 #include "client.h"
 
diff --git a/drivers/misc/mei/hw-txe-regs.h b/drivers/misc/mei/hw-txe-regs.h
new file mode 100644
index 000000000000..7283c24c1af1
--- /dev/null
+++ b/drivers/misc/mei/hw-txe-regs.h
@@ -0,0 +1,294 @@
+/******************************************************************************
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Intel MEI Interface Header
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING
+ *
+ * Contact Information:
+ *	Intel Corporation.
+ *	linux-mei@linux.intel.com
+ *	http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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 _MEI_HW_TXE_REGS_H_
+#define _MEI_HW_TXE_REGS_H_
+
+#include "hw.h"
+
+#define SEC_ALIVENESS_TIMER_TIMEOUT        (5 * MSEC_PER_SEC)
+#define SEC_ALIVENESS_WAIT_TIMEOUT         (1 * MSEC_PER_SEC)
+#define SEC_RESET_WAIT_TIMEOUT             (1 * MSEC_PER_SEC)
+#define SEC_READY_WAIT_TIMEOUT             (5 * MSEC_PER_SEC)
+#define START_MESSAGE_RESPONSE_WAIT_TIMEOUT (5 * MSEC_PER_SEC)
+#define RESET_CANCEL_WAIT_TIMEOUT          (1 * MSEC_PER_SEC)
+
+enum {
+	SEC_BAR,
+	BRIDGE_BAR,
+
+	NUM_OF_MEM_BARS
+};
+
+/* SeC FW Status Register
+ *
+ * FW uses this register in order to report its status to host.
+ * This register resides in PCI-E config space.
+ */
+#define PCI_CFG_TXE_FW_STS0   0x40
+#  define PCI_CFG_TXE_FW_STS0_WRK_ST_MSK    0x0000000F
+#  define PCI_CFG_TXE_FW_STS0_OP_ST_MSK     0x000001C0
+#  define PCI_CFG_TXE_FW_STS0_FW_INIT_CMPLT 0x00000200
+#  define PCI_CFG_TXE_FW_STS0_ERR_CODE_MSK  0x0000F000
+#  define PCI_CFG_TXE_FW_STS0_OP_MODE_MSK   0x000F0000
+#  define PCI_CFG_TXE_FW_STS0_RST_CNT_MSK   0x00F00000
+
+
+#define IPC_BASE_ADDR	0x80400 /* SeC IPC Base Address */
+
+/* IPC Input Doorbell Register */
+#define SEC_IPC_INPUT_DOORBELL_REG       (0x0000 + IPC_BASE_ADDR)
+
+/* IPC Input Status Register
+ * This register indicates whether or not processing of
+ * the most recent command has been completed by the SEC
+ * New commands and payloads should not be written by the Host
+ * until this indicates that the previous command has been processed.
+ */
+#define SEC_IPC_INPUT_STATUS_REG         (0x0008 + IPC_BASE_ADDR)
+#  define SEC_IPC_INPUT_STATUS_RDY    BIT(0)
+
+/* IPC Host Interrupt Status Register */
+#define SEC_IPC_HOST_INT_STATUS_REG      (0x0010 + IPC_BASE_ADDR)
+#define   SEC_IPC_HOST_INT_STATUS_OUT_DB             BIT(0)
+#define   SEC_IPC_HOST_INT_STATUS_IN_RDY             BIT(1)
+#define   SEC_IPC_HOST_INT_STATUS_HDCP_M0_RCVD       BIT(5)
+#define   SEC_IPC_HOST_INT_STATUS_ILL_MEM_ACCESS     BIT(17)
+#define   SEC_IPC_HOST_INT_STATUS_AES_HKEY_ERR       BIT(18)
+#define   SEC_IPC_HOST_INT_STATUS_DES_HKEY_ERR       BIT(19)
+#define   SEC_IPC_HOST_INT_STATUS_TMRMTB_OVERFLOW    BIT(21)
+
+/* Convenient mask for pending interrupts */
+#define   SEC_IPC_HOST_INT_STATUS_PENDING \
+		(SEC_IPC_HOST_INT_STATUS_OUT_DB| \
+		SEC_IPC_HOST_INT_STATUS_IN_RDY)
+
+/* IPC Host Interrupt Mask Register */
+#define SEC_IPC_HOST_INT_MASK_REG        (0x0014 + IPC_BASE_ADDR)
+
+#  define SEC_IPC_HOST_INT_MASK_OUT_DB	BIT(0) /* Output Doorbell Int Mask */
+#  define SEC_IPC_HOST_INT_MASK_IN_RDY	BIT(1) /* Input Ready Int Mask */
+
+/* IPC Input Payload RAM */
+#define SEC_IPC_INPUT_PAYLOAD_REG        (0x0100 + IPC_BASE_ADDR)
+/* IPC Shared Payload RAM */
+#define IPC_SHARED_PAYLOAD_REG           (0x0200 + IPC_BASE_ADDR)
+
+/* SeC Address Translation Table Entry 2 - Ctrl
+ *
+ * This register resides also in SeC's PCI-E Memory space.
+ */
+#define SATT2_CTRL_REG                   0x1040
+#  define SATT2_CTRL_VALID_MSK            BIT(0)
+#  define SATT2_CTRL_BR_BASE_ADDR_REG_SHIFT 8
+#  define SATT2_CTRL_BRIDGE_HOST_EN_MSK   BIT(12)
+
+/* SATT Table Entry 2 SAP Base Address Register */
+#define SATT2_SAP_BA_REG                 0x1044
+/* SATT Table Entry 2 SAP Size Register. */
+#define SATT2_SAP_SIZE_REG               0x1048
+ /* SATT Table Entry 2 SAP Bridge Address - LSB Register */
+#define SATT2_BRG_BA_LSB_REG             0x104C
+
+/* Host High-level Interrupt Status Register */
+#define HHISR_REG                        0x2020
+/* Host High-level Interrupt Enable Register
+ *
+ * Resides in PCI memory space. This is the top hierarchy for
+ * interrupts from SeC to host, aggregating both interrupts that
+ * arrive through HICR registers as well as interrupts
+ * that arrive via IPC.
+ */
+#define HHIER_REG                        0x2024
+#define   IPC_HHIER_SEC	BIT(0)
+#define   IPC_HHIER_BRIDGE	BIT(1)
+#define   IPC_HHIER_MSK	(IPC_HHIER_SEC | IPC_HHIER_BRIDGE)
+
+/* Host High-level Interrupt Mask Register.
+ *
+ * Resides in PCI memory space.
+ * This is the top hierarchy for masking interrupts from SeC to host.
+ */
+#define HHIMR_REG                        0x2028
+#define   IPC_HHIMR_SEC       BIT(0)
+#define   IPC_HHIMR_BRIDGE    BIT(1)
+
+/* Host High-level IRQ Status Register */
+#define HHIRQSR_REG                      0x202C
+
+/* Host Interrupt Cause Register 0 - SeC IPC Readiness
+ *
+ * This register is both an ICR to Host from PCI Memory Space
+ * and it is also exposed in the SeC memory space.
+ * This register is used by SeC's IPC driver in order
+ * to synchronize with host about IPC interface state.
+ */
+#define HICR_SEC_IPC_READINESS_REG       0x2040
+#define   HICR_SEC_IPC_READINESS_HOST_RDY  BIT(0)
+#define   HICR_SEC_IPC_READINESS_SEC_RDY   BIT(1)
+#define   HICR_SEC_IPC_READINESS_SYS_RDY     \
+	  (HICR_SEC_IPC_READINESS_HOST_RDY | \
+	   HICR_SEC_IPC_READINESS_SEC_RDY)
+#define   HICR_SEC_IPC_READINESS_RDY_CLR   BIT(2)
+
+/* Host Interrupt Cause Register 1 - Aliveness Response */
+/* This register is both an ICR to Host from PCI Memory Space
+ * and it is also exposed in the SeC memory space.
+ * The register may be used by SeC to ACK a host request for aliveness.
+ */
+#define HICR_HOST_ALIVENESS_RESP_REG     0x2044
+#define   HICR_HOST_ALIVENESS_RESP_ACK    BIT(0)
+
+/* Host Interrupt Cause Register 2 - SeC IPC Output Doorbell */
+#define HICR_SEC_IPC_OUTPUT_DOORBELL_REG 0x2048
+
+/* Host Interrupt Status Register.
+ *
+ * Resides in PCI memory space.
+ * This is the main register involved in generating interrupts
+ * from SeC to host via HICRs.
+ * The interrupt generation rules are as follows:
+ * An interrupt will be generated whenever for any i,
+ * there is a transition from a state where at least one of
+ * the following conditions did not hold, to a state where
+ * ALL the following conditions hold:
+ * A) HISR.INT[i]_STS == 1.
+ * B) HIER.INT[i]_EN == 1.
+ */
+#define HISR_REG                         0x2060
+#define   HISR_INT_0_STS      BIT(0)
+#define   HISR_INT_1_STS      BIT(1)
+#define   HISR_INT_2_STS      BIT(2)
+#define   HISR_INT_3_STS      BIT(3)
+#define   HISR_INT_4_STS      BIT(4)
+#define   HISR_INT_5_STS      BIT(5)
+#define   HISR_INT_6_STS      BIT(6)
+#define   HISR_INT_7_STS      BIT(7)
+#define   HISR_INT_STS_MSK \
+	(HISR_INT_0_STS | HISR_INT_1_STS | HISR_INT_2_STS)
+
+/* Host Interrupt Enable Register. Resides in PCI memory space. */
+#define HIER_REG                         0x2064
+#define   HIER_INT_0_EN      BIT(0)
+#define   HIER_INT_1_EN      BIT(1)
+#define   HIER_INT_2_EN      BIT(2)
+#define   HIER_INT_3_EN      BIT(3)
+#define   HIER_INT_4_EN      BIT(4)
+#define   HIER_INT_5_EN      BIT(5)
+#define   HIER_INT_6_EN      BIT(6)
+#define   HIER_INT_7_EN      BIT(7)
+
+#define   HIER_INT_EN_MSK \
+	 (HIER_INT_0_EN | HIER_INT_1_EN | HIER_INT_2_EN)
+
+
+/* SEC Memory Space IPC output payload.
+ *
+ * This register is part of the output payload which SEC provides to host.
+ */
+#define BRIDGE_IPC_OUTPUT_PAYLOAD_REG    0x20C0
+
+/* SeC Interrupt Cause Register - Host Aliveness Request
+ * This register is both an ICR to SeC and it is also exposed
+ * in the host-visible PCI memory space.
+ * The register is used by host to request SeC aliveness.
+ */
+#define SICR_HOST_ALIVENESS_REQ_REG      0x214C
+#define   SICR_HOST_ALIVENESS_REQ_REQUESTED    BIT(0)
+
+
+/* SeC Interrupt Cause Register - Host IPC Readiness
+ *
+ * This register is both an ICR to SeC and it is also exposed
+ * in the host-visible PCI memory space.
+ * This register is used by the host's SeC driver uses in order
+ * to synchronize with SeC about IPC interface state.
+ */
+#define SICR_HOST_IPC_READINESS_REQ_REG  0x2150
+
+
+#define SICR_HOST_IPC_READINESS_HOST_RDY  BIT(0)
+#define SICR_HOST_IPC_READINESS_SEC_RDY   BIT(1)
+#define SICR_HOST_IPC_READINESS_SYS_RDY     \
+	(SICR_HOST_IPC_READINESS_HOST_RDY | \
+	 SICR_HOST_IPC_READINESS_SEC_RDY)
+#define SICR_HOST_IPC_READINESS_RDY_CLR   BIT(2)
+
+/* SeC Interrupt Cause Register - SeC IPC Output Status
+ *
+ * This register indicates whether or not processing of the most recent
+ * command has been completed by the Host.
+ * New commands and payloads should not be written by SeC until this
+ * register indicates that the previous command has been processed.
+ */
+#define SICR_SEC_IPC_OUTPUT_STATUS_REG   0x2154
+#  define SEC_IPC_OUTPUT_STATUS_RDY BIT(0)
+
+
+
+/*  MEI IPC Message payload size 64 bytes */
+#define PAYLOAD_SIZE        64
+
+/* MAX size for SATT range 32MB */
+#define SATT_RANGE_MAX     (32 << 20)
+
+
+#endif /* _MEI_HW_TXE_REGS_H_ */
+
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
new file mode 100644
index 000000000000..f60182a52f96
--- /dev/null
+++ b/drivers/misc/mei/hw-txe.c
@@ -0,0 +1,1107 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * 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/pci.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/irqreturn.h>
+
+#include <linux/mei.h>
+
+#include "mei_dev.h"
+#include "hw-txe.h"
+#include "client.h"
+#include "hbm.h"
+
+/**
+ * mei_txe_reg_read - Reads 32bit data from the device
+ *
+ * @base_addr: registers base address
+ * @offset: register offset
+ *
+ */
+static inline u32 mei_txe_reg_read(void __iomem *base_addr,
+					unsigned long offset)
+{
+	return ioread32(base_addr + offset);
+}
+
+/**
+ * mei_txe_reg_write - Writes 32bit data to the device
+ *
+ * @base_addr: registers base address
+ * @offset: register offset
+ * @value: the value to write
+ */
+static inline void mei_txe_reg_write(void __iomem *base_addr,
+				unsigned long offset, u32 value)
+{
+	iowrite32(value, base_addr + offset);
+}
+
+/**
+ * mei_txe_sec_reg_read_silent - Reads 32bit data from the SeC BAR
+ *
+ * @dev: the device structure
+ * @offset: register offset
+ *
+ * Doesn't check for aliveness while Reads 32bit data from the SeC BAR
+ */
+static inline u32 mei_txe_sec_reg_read_silent(struct mei_txe_hw *hw,
+				unsigned long offset)
+{
+	return mei_txe_reg_read(hw->mem_addr[SEC_BAR], offset);
+}
+
+/**
+ * mei_txe_sec_reg_read - Reads 32bit data from the SeC BAR
+ *
+ * @dev: the device structure
+ * @offset: register offset
+ *
+ * Reads 32bit data from the SeC BAR and shout loud if aliveness is not set
+ */
+static inline u32 mei_txe_sec_reg_read(struct mei_txe_hw *hw,
+				unsigned long offset)
+{
+	WARN(!hw->aliveness, "sec read: aliveness not asserted\n");
+	return mei_txe_sec_reg_read_silent(hw, offset);
+}
+/**
+ * mei_txe_sec_reg_write_silent - Writes 32bit data to the SeC BAR
+ *   doesn't check for aliveness
+ *
+ * @dev: the device structure
+ * @offset: register offset
+ * @value: value to write
+ *
+ * Doesn't check for aliveness while writes 32bit data from to the SeC BAR
+ */
+static inline void mei_txe_sec_reg_write_silent(struct mei_txe_hw *hw,
+				unsigned long offset, u32 value)
+{
+	mei_txe_reg_write(hw->mem_addr[SEC_BAR], offset, value);
+}
+
+/**
+ * mei_txe_sec_reg_write - Writes 32bit data to the SeC BAR
+ *
+ * @dev: the device structure
+ * @offset: register offset
+ * @value: value to write
+ *
+ * Writes 32bit data from the SeC BAR and shout loud if aliveness is not set
+ */
+static inline void mei_txe_sec_reg_write(struct mei_txe_hw *hw,
+				unsigned long offset, u32 value)
+{
+	WARN(!hw->aliveness, "sec write: aliveness not asserted\n");
+	mei_txe_sec_reg_write_silent(hw, offset, value);
+}
+/**
+ * mei_txe_br_reg_read - Reads 32bit data from the Bridge BAR
+ *
+ * @hw: the device structure
+ * @offset: offset from which to read the data
+ *
+ */
+static inline u32 mei_txe_br_reg_read(struct mei_txe_hw *hw,
+				unsigned long offset)
+{
+	return mei_txe_reg_read(hw->mem_addr[BRIDGE_BAR], offset);
+}
+
+/**
+ * mei_txe_br_reg_write - Writes 32bit data to the Bridge BAR
+ *
+ * @hw: the device structure
+ * @offset: offset from which to write the data
+ * @value: the byte to write
+ */
+static inline void mei_txe_br_reg_write(struct mei_txe_hw *hw,
+				unsigned long offset, u32 value)
+{
+	mei_txe_reg_write(hw->mem_addr[BRIDGE_BAR], offset, value);
+}
+
+/**
+ * mei_txe_aliveness_set - request for aliveness change
+ *
+ * @dev: the device structure
+ * @req: requested aliveness value
+ *
+ * Request for aliveness change and returns true if the change is
+ *   really needed and false if aliveness is already
+ *   in the requested state
+ * Requires device lock to be held
+ */
+static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req)
+{
+
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	bool do_req = hw->aliveness != req;
+
+	dev_dbg(&dev->pdev->dev, "Aliveness current=%d request=%d\n",
+				hw->aliveness, req);
+	if (do_req) {
+		hw->recvd_aliveness = false;
+		mei_txe_br_reg_write(hw, SICR_HOST_ALIVENESS_REQ_REG, req);
+	}
+	return do_req;
+}
+
+
+/**
+ * mei_txe_aliveness_req_get - get aliveness requested register value
+ *
+ * @dev: the device structure
+ *
+ * Extract HICR_HOST_ALIVENESS_RESP_ACK bit from
+ * from HICR_HOST_ALIVENESS_REQ register value
+ */
+static u32 mei_txe_aliveness_req_get(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 reg;
+	reg = mei_txe_br_reg_read(hw, SICR_HOST_ALIVENESS_REQ_REG);
+	return reg & SICR_HOST_ALIVENESS_REQ_REQUESTED;
+}
+
+/**
+ * mei_txe_aliveness_get - get aliveness response register value
+ * @dev: the device structure
+ *
+ * Extract HICR_HOST_ALIVENESS_RESP_ACK bit
+ * from HICR_HOST_ALIVENESS_RESP register value
+ */
+static u32 mei_txe_aliveness_get(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 reg;
+	reg = mei_txe_br_reg_read(hw, HICR_HOST_ALIVENESS_RESP_REG);
+	return reg & HICR_HOST_ALIVENESS_RESP_ACK;
+}
+
+/**
+ * mei_txe_aliveness_poll - waits for aliveness to settle
+ *
+ * @dev: the device structure
+ * @expected: expected aliveness value
+ *
+ * Polls for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
+ * returns > 0 if the expected value was received, -ETIME otherwise
+ */
+static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	int t = 0;
+
+	do {
+		hw->aliveness = mei_txe_aliveness_get(dev);
+		if (hw->aliveness == expected) {
+			dev_dbg(&dev->pdev->dev,
+				"aliveness settled after %d msecs\n", t);
+			return t;
+		}
+		mutex_unlock(&dev->device_lock);
+		msleep(MSEC_PER_SEC / 5);
+		mutex_lock(&dev->device_lock);
+		t += MSEC_PER_SEC / 5;
+	} while (t < SEC_ALIVENESS_WAIT_TIMEOUT);
+
+	dev_err(&dev->pdev->dev, "aliveness timed out\n");
+	return -ETIME;
+}
+
+/**
+ * mei_txe_aliveness_wait - waits for aliveness to settle
+ *
+ * @dev: the device structure
+ * @expected: expected aliveness value
+ *
+ * Waits for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
+ * returns returns 0 on success and < 0 otherwise
+ */
+static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	const unsigned long timeout =
+			msecs_to_jiffies(SEC_ALIVENESS_WAIT_TIMEOUT);
+	long err;
+	int ret;
+
+	hw->aliveness = mei_txe_aliveness_get(dev);
+	if (hw->aliveness == expected)
+		return 0;
+
+	mutex_unlock(&dev->device_lock);
+	err = wait_event_timeout(hw->wait_aliveness,
+			hw->recvd_aliveness, timeout);
+	mutex_lock(&dev->device_lock);
+
+	hw->aliveness = mei_txe_aliveness_get(dev);
+	ret = hw->aliveness == expected ? 0 : -ETIME;
+
+	if (ret)
+		dev_err(&dev->pdev->dev, "aliveness timed out");
+	else
+		dev_dbg(&dev->pdev->dev, "aliveness settled after %d msecs\n",
+				jiffies_to_msecs(timeout - err));
+	hw->recvd_aliveness = false;
+	return ret;
+}
+
+/**
+ * mei_txe_aliveness_set_sync - sets an wait for aliveness to complete
+ *
+ * @dev: the device structure
+ *
+ * returns returns 0 on success and < 0 otherwise
+ */
+int mei_txe_aliveness_set_sync(struct mei_device *dev, u32 req)
+{
+	if (mei_txe_aliveness_set(dev, req))
+		return mei_txe_aliveness_wait(dev, req);
+	return 0;
+}
+
+/**
+ * mei_txe_input_ready_interrupt_enable - sets the Input Ready Interrupt
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_input_ready_interrupt_enable(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 hintmsk;
+	/* Enable the SEC_IPC_HOST_INT_MASK_IN_RDY interrupt */
+	hintmsk = mei_txe_sec_reg_read(hw, SEC_IPC_HOST_INT_MASK_REG);
+	hintmsk |= SEC_IPC_HOST_INT_MASK_IN_RDY;
+	mei_txe_sec_reg_write(hw, SEC_IPC_HOST_INT_MASK_REG, hintmsk);
+}
+
+/**
+ * mei_txe_input_doorbell_set
+ *   - Sets bit 0 in SEC_IPC_INPUT_DOORBELL.IPC_INPUT_DOORBELL.
+ * @dev: the device structure
+ */
+static void mei_txe_input_doorbell_set(struct mei_txe_hw *hw)
+{
+	/* Clear the interrupt cause */
+	clear_bit(TXE_INTR_IN_READY_BIT, &hw->intr_cause);
+	mei_txe_sec_reg_write(hw, SEC_IPC_INPUT_DOORBELL_REG, 1);
+}
+
+/**
+ * mei_txe_output_ready_set - Sets the SICR_SEC_IPC_OUTPUT_STATUS bit to 1
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_output_ready_set(struct mei_txe_hw *hw)
+{
+	mei_txe_br_reg_write(hw,
+			SICR_SEC_IPC_OUTPUT_STATUS_REG,
+			SEC_IPC_OUTPUT_STATUS_RDY);
+}
+
+/**
+ * mei_txe_is_input_ready - check if TXE is ready for receiving data
+ *
+ * @dev: the device structure
+ */
+static bool mei_txe_is_input_ready(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 status;
+	status = mei_txe_sec_reg_read(hw, SEC_IPC_INPUT_STATUS_REG);
+	return !!(SEC_IPC_INPUT_STATUS_RDY & status);
+}
+
+/**
+ * mei_txe_intr_clear - clear all interrupts
+ *
+ * @dev: the device structure
+ */
+static inline void mei_txe_intr_clear(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_sec_reg_write_silent(hw, SEC_IPC_HOST_INT_STATUS_REG,
+		SEC_IPC_HOST_INT_STATUS_PENDING);
+	mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_STS_MSK);
+	mei_txe_br_reg_write(hw, HHISR_REG, IPC_HHIER_MSK);
+}
+
+/**
+ * mei_txe_intr_disable - disable all interrupts
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_intr_disable(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_br_reg_write(hw, HHIER_REG, 0);
+	mei_txe_br_reg_write(hw, HIER_REG, 0);
+}
+/**
+ * mei_txe_intr_disable - enable all interrupts
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_intr_enable(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_br_reg_write(hw, HHIER_REG, IPC_HHIER_MSK);
+	mei_txe_br_reg_write(hw, HIER_REG, HIER_INT_EN_MSK);
+}
+
+/**
+ * mei_txe_pending_interrupts - check if there are pending interrupts
+ *	only Aliveness, Input ready, and output doorbell are of relevance
+ *
+ * @dev: the device structure
+ *
+ * Checks if there are pending interrupts
+ * only Aliveness, Readiness, Input ready, and Output doorbell are relevant
+ */
+static bool mei_txe_pending_interrupts(struct mei_device *dev)
+{
+
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	bool ret = (hw->intr_cause & (TXE_INTR_READINESS |
+				      TXE_INTR_ALIVENESS |
+				      TXE_INTR_IN_READY  |
+				      TXE_INTR_OUT_DB));
+
+	if (ret) {
+		dev_dbg(&dev->pdev->dev,
+			"Pending Interrupts InReady=%01d Readiness=%01d, Aliveness=%01d, OutDoor=%01d\n",
+			!!(hw->intr_cause & TXE_INTR_IN_READY),
+			!!(hw->intr_cause & TXE_INTR_READINESS),
+			!!(hw->intr_cause & TXE_INTR_ALIVENESS),
+			!!(hw->intr_cause & TXE_INTR_OUT_DB));
+	}
+	return ret;
+}
+
+/**
+ * mei_txe_input_payload_write - write a dword to the host buffer
+ *	at offset idx
+ *
+ * @dev: the device structure
+ * @idx: index in the host buffer
+ * @value: value
+ */
+static void mei_txe_input_payload_write(struct mei_device *dev,
+			unsigned long idx, u32 value)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_sec_reg_write(hw, SEC_IPC_INPUT_PAYLOAD_REG +
+			(idx * sizeof(u32)), value);
+}
+
+/**
+ * mei_txe_out_data_read - read dword from the device buffer
+ *	at offset idx
+ *
+ * @dev: the device structure
+ * @idx: index in the device buffer
+ *
+ * returns register value at index
+ */
+static u32 mei_txe_out_data_read(const struct mei_device *dev,
+					unsigned long idx)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	return mei_txe_br_reg_read(hw,
+		BRIDGE_IPC_OUTPUT_PAYLOAD_REG + (idx * sizeof(u32)));
+}
+
+/* Readiness */
+
+/**
+ * mei_txe_readiness_set_host_rdy
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_readiness_set_host_rdy(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_br_reg_write(hw,
+		SICR_HOST_IPC_READINESS_REQ_REG,
+		SICR_HOST_IPC_READINESS_HOST_RDY);
+}
+
+/**
+ * mei_txe_readiness_clear
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_readiness_clear(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	mei_txe_br_reg_write(hw, SICR_HOST_IPC_READINESS_REQ_REG,
+				SICR_HOST_IPC_READINESS_RDY_CLR);
+}
+/**
+ * mei_txe_readiness_get - Reads and returns
+ *	the HICR_SEC_IPC_READINESS register value
+ *
+ * @dev: the device structure
+ */
+static u32 mei_txe_readiness_get(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	return mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
+}
+
+
+/**
+ * mei_txe_readiness_is_sec_rdy - check readiness
+ *  for HICR_SEC_IPC_READINESS_SEC_RDY
+ *
+ * @readiness - cached readiness state
+ */
+static inline bool mei_txe_readiness_is_sec_rdy(u32 readiness)
+{
+	return !!(readiness & HICR_SEC_IPC_READINESS_SEC_RDY);
+}
+
+/**
+ * mei_txe_hw_is_ready - check if the hw is ready
+ *
+ * @dev: the device structure
+ */
+static bool mei_txe_hw_is_ready(struct mei_device *dev)
+{
+	u32 readiness =  mei_txe_readiness_get(dev);
+	return mei_txe_readiness_is_sec_rdy(readiness);
+}
+
+/**
+ * mei_txe_host_is_ready - check if the host is ready
+ *
+ * @dev: the device structure
+ */
+static inline bool mei_txe_host_is_ready(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 reg = mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
+	return !!(reg & HICR_SEC_IPC_READINESS_HOST_RDY);
+}
+
+/**
+ * mei_txe_readiness_wait - wait till readiness settles
+ *
+ * @dev: the device structure
+ *
+ * returns 0 on success and -ETIME on timeout
+ */
+static int mei_txe_readiness_wait(struct mei_device *dev)
+{
+	if (mei_txe_hw_is_ready(dev))
+		return 0;
+
+	mutex_unlock(&dev->device_lock);
+	wait_event_timeout(dev->wait_hw_ready, dev->recvd_hw_ready,
+			msecs_to_jiffies(SEC_RESET_WAIT_TIMEOUT));
+	mutex_lock(&dev->device_lock);
+	if (!dev->recvd_hw_ready) {
+		dev_err(&dev->pdev->dev, "wait for readiness failed\n");
+		return -ETIME;
+	}
+
+	dev->recvd_hw_ready = false;
+	return 0;
+}
+
+/**
+ *  mei_txe_hw_config - configure hardware at the start of the devices
+ *
+ * @dev: the device structure
+ *
+ * Configure hardware at the start of the device should be done only
+ *   once at the device probe time
+ */
+static void mei_txe_hw_config(struct mei_device *dev)
+{
+
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	/* Doesn't change in runtime */
+	dev->hbuf_depth = PAYLOAD_SIZE / 4;
+
+	hw->aliveness = mei_txe_aliveness_get(dev);
+	hw->readiness = mei_txe_readiness_get(dev);
+
+	dev_dbg(&dev->pdev->dev, "aliveness_resp = 0x%08x, readiness = 0x%08x.\n",
+		hw->aliveness, hw->readiness);
+}
+
+
+/**
+ * mei_txe_write - writes a message to device.
+ *
+ * @dev: the device structure
+ * @header: header of message
+ * @buf: message buffer will be written
+ * returns 1 if success, 0 - otherwise.
+ */
+
+static int mei_txe_write(struct mei_device *dev,
+		struct mei_msg_hdr *header, unsigned char *buf)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	unsigned long rem;
+	unsigned long length;
+	int slots = dev->hbuf_depth;
+	u32 *reg_buf = (u32 *)buf;
+	u32 dw_cnt;
+	int i;
+
+	if (WARN_ON(!header || !buf))
+		return -EINVAL;
+
+	length = header->length;
+
+	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
+
+	dw_cnt = mei_data2slots(length);
+	if (dw_cnt > slots)
+		return -EMSGSIZE;
+
+	if (WARN(!hw->aliveness, "txe write: aliveness not asserted\n"))
+		return -EAGAIN;
+
+	/* Enable Input Ready Interrupt. */
+	mei_txe_input_ready_interrupt_enable(dev);
+
+	if (!mei_txe_is_input_ready(dev)) {
+		dev_err(&dev->pdev->dev, "Input is not ready");
+		return -EAGAIN;
+	}
+
+	mei_txe_input_payload_write(dev, 0, *((u32 *)header));
+
+	for (i = 0; i < length / 4; i++)
+		mei_txe_input_payload_write(dev, i + 1, reg_buf[i]);
+
+	rem = length & 0x3;
+	if (rem > 0) {
+		u32 reg = 0;
+		memcpy(&reg, &buf[length - rem], rem);
+		mei_txe_input_payload_write(dev, i + 1, reg);
+	}
+
+	/* after each write the whole buffer is consumed */
+	hw->slots = 0;
+
+	/* Set Input-Doorbell */
+	mei_txe_input_doorbell_set(hw);
+
+	return 0;
+}
+
+/**
+ * mei_txe_hbuf_max_len - mimics the me hbuf circular buffer
+ *
+ * @dev: the device structure
+ *
+ * returns the PAYLOAD_SIZE - 4
+ */
+static size_t mei_txe_hbuf_max_len(const struct mei_device *dev)
+{
+	return PAYLOAD_SIZE - sizeof(struct mei_msg_hdr);
+}
+
+/**
+ * mei_txe_hbuf_empty_slots - mimics the me hbuf circular buffer
+ *
+ * @dev: the device structure
+ *
+ * returns always hbuf_depth
+ */
+static int mei_txe_hbuf_empty_slots(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	return hw->slots;
+}
+
+/**
+ * mei_txe_count_full_read_slots - mimics the me device circular buffer
+ *
+ * @dev: the device structure
+ *
+ * returns always buffer size in dwords count
+ */
+static int mei_txe_count_full_read_slots(struct mei_device *dev)
+{
+	/* read buffers has static size */
+	return  PAYLOAD_SIZE / 4;
+}
+
+/**
+ * mei_txe_read_hdr - read message header which is always in 4 first bytes
+ *
+ * @dev: the device structure
+ *
+ * returns mei message header
+ */
+
+static u32 mei_txe_read_hdr(const struct mei_device *dev)
+{
+	return mei_txe_out_data_read(dev, 0);
+}
+/**
+ * mei_txe_read - reads a message from the txe device.
+ *
+ * @dev: the device structure
+ * @buf: message buffer will be written
+ * @len: message size will be read
+ *
+ * returns -EINVAL on error wrong argument and 0 on success
+ */
+static int mei_txe_read(struct mei_device *dev,
+		unsigned char *buf, unsigned long len)
+{
+
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 i;
+	u32 *reg_buf = (u32 *)buf;
+	u32 rem = len & 0x3;
+
+	if (WARN_ON(!buf || !len))
+		return -EINVAL;
+
+	dev_dbg(&dev->pdev->dev,
+		"buffer-length = %lu buf[0]0x%08X\n",
+		len, mei_txe_out_data_read(dev, 0));
+
+	for (i = 0; i < len / 4; i++) {
+		/* skip header: index starts from 1 */
+		u32 reg = mei_txe_out_data_read(dev, i + 1);
+		dev_dbg(&dev->pdev->dev, "buf[%d] = 0x%08X\n", i, reg);
+		*reg_buf++ = reg;
+	}
+
+	if (rem) {
+		u32 reg = mei_txe_out_data_read(dev, i + 1);
+		memcpy(reg_buf, &reg, rem);
+	}
+
+	mei_txe_output_ready_set(hw);
+	return 0;
+}
+
+/**
+ * mei_txe_hw_reset - resets host and fw.
+ *
+ * @dev: the device structure
+ * @intr_enable: if interrupt should be enabled after reset.
+ *
+ * returns 0 on success and < 0 in case of error
+ */
+static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+
+	u32 aliveness_req;
+	/*
+	 * read input doorbell to ensure consistency between  Bridge and SeC
+	 * return value might be garbage return
+	 */
+	(void)mei_txe_sec_reg_read_silent(hw, SEC_IPC_INPUT_DOORBELL_REG);
+
+	aliveness_req = mei_txe_aliveness_req_get(dev);
+	hw->aliveness = mei_txe_aliveness_get(dev);
+
+	/* Disable interrupts in this stage we will poll */
+	mei_txe_intr_disable(dev);
+
+	/*
+	 * If Aliveness Request and Aliveness Response are not equal then
+	 * wait for them to be equal
+	 * Since we might have interrupts disabled - poll for it
+	 */
+	if (aliveness_req != hw->aliveness)
+		if (mei_txe_aliveness_poll(dev, aliveness_req) < 0) {
+			dev_err(&dev->pdev->dev,
+				"wait for aliveness settle failed ... bailing out\n");
+			return -EIO;
+		}
+
+	/*
+	 * If Aliveness Request and Aliveness Response are set then clear them
+	 */
+	if (aliveness_req) {
+		mei_txe_aliveness_set(dev, 0);
+		if (mei_txe_aliveness_poll(dev, 0) < 0) {
+			dev_err(&dev->pdev->dev,
+				"wait for aliveness failed ... bailing out\n");
+			return -EIO;
+		}
+	}
+
+	/*
+	 * Set rediness RDY_CLR bit
+	 */
+	mei_txe_readiness_clear(dev);
+
+	return 0;
+}
+
+/**
+ * mei_txe_hw_start - start the hardware after reset
+ *
+ * @dev: the device structure
+ *
+ * returns 0 on success and < 0 in case of error
+ */
+static int mei_txe_hw_start(struct mei_device *dev)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	int ret;
+
+	u32 hisr;
+
+	/* bring back interrupts */
+	mei_txe_intr_enable(dev);
+
+	ret = mei_txe_readiness_wait(dev);
+	if (ret < 0) {
+		dev_err(&dev->pdev->dev, "wating for readiness failed\n");
+		return ret;
+	}
+
+	/*
+	 * If HISR.INT2_STS interrupt status bit is set then clear it.
+	 */
+	hisr = mei_txe_br_reg_read(hw, HISR_REG);
+	if (hisr & HISR_INT_2_STS)
+		mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_2_STS);
+
+	/* Clear the interrupt cause of OutputDoorbell */
+	clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause);
+
+	ret = mei_txe_aliveness_set_sync(dev, 1);
+	if (ret < 0) {
+		dev_err(&dev->pdev->dev, "wait for aliveness failed ... bailing out\n");
+		return ret;
+	}
+
+	/* enable input ready interrupts:
+	 * SEC_IPC_HOST_INT_MASK.IPC_INPUT_READY_INT_MASK
+	 */
+	mei_txe_input_ready_interrupt_enable(dev);
+
+
+	/*  Set the SICR_SEC_IPC_OUTPUT_STATUS.IPC_OUTPUT_READY bit */
+	mei_txe_output_ready_set(hw);
+
+	/* Set bit SICR_HOST_IPC_READINESS.HOST_RDY
+	 */
+	mei_txe_readiness_set_host_rdy(dev);
+
+	return 0;
+}
+
+/**
+ * mei_txe_check_and_ack_intrs - translate multi BAR interrupt into
+ *  single bit mask and acknowledge the interrupts
+ *
+ * @dev: the device structure
+ * @do_ack: acknowledge interrupts
+ */
+static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 hisr;
+	u32 hhisr;
+	u32 ipc_isr;
+	u32 aliveness;
+	bool generated;
+
+	/* read interrupt registers */
+	hhisr = mei_txe_br_reg_read(hw, HHISR_REG);
+	generated = (hhisr & IPC_HHIER_MSK);
+	if (!generated)
+		goto out;
+
+	hisr = mei_txe_br_reg_read(hw, HISR_REG);
+
+	aliveness = mei_txe_aliveness_get(dev);
+	if (hhisr & IPC_HHIER_SEC && aliveness)
+		ipc_isr = mei_txe_sec_reg_read_silent(hw,
+				SEC_IPC_HOST_INT_STATUS_REG);
+	else
+		ipc_isr = 0;
+
+	generated = generated ||
+		(hisr & HISR_INT_STS_MSK) ||
+		(ipc_isr & SEC_IPC_HOST_INT_STATUS_PENDING);
+
+	if (generated && do_ack) {
+		/* Save the interrupt causes */
+		hw->intr_cause |= hisr & HISR_INT_STS_MSK;
+		if (ipc_isr & SEC_IPC_HOST_INT_STATUS_IN_RDY)
+			hw->intr_cause |= TXE_INTR_IN_READY;
+
+
+		mei_txe_intr_disable(dev);
+		/* Clear the interrupts in hierarchy:
+		 * IPC and Bridge, than the High Level */
+		mei_txe_sec_reg_write_silent(hw,
+			SEC_IPC_HOST_INT_STATUS_REG, ipc_isr);
+		mei_txe_br_reg_write(hw, HISR_REG, hisr);
+		mei_txe_br_reg_write(hw, HHISR_REG, hhisr);
+	}
+
+out:
+	return generated;
+}
+
+/**
+ * mei_txe_irq_quick_handler - The ISR of the MEI device
+ *
+ * @irq: The irq number
+ * @dev_id: pointer to the device structure
+ *
+ * returns irqreturn_t
+ */
+irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id)
+{
+	struct mei_device *dev = dev_id;
+
+	if (mei_txe_check_and_ack_intrs(dev, true))
+		return IRQ_WAKE_THREAD;
+	return IRQ_NONE;
+}
+
+
+/**
+ * mei_txe_irq_thread_handler - txe interrupt thread
+ *
+ * @irq: The irq number
+ * @dev_id: pointer to the device structure
+ *
+ * returns irqreturn_t
+ *
+ */
+irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
+{
+	struct mei_device *dev = (struct mei_device *) dev_id;
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	struct mei_cl_cb complete_list;
+	s32 slots;
+	int rets = 0;
+
+	dev_dbg(&dev->pdev->dev, "irq thread: Interrupt Registers HHISR|HISR|SEC=%02X|%04X|%02X\n",
+		mei_txe_br_reg_read(hw, HHISR_REG),
+		mei_txe_br_reg_read(hw, HISR_REG),
+		mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG));
+
+
+	/* initialize our complete list */
+	mutex_lock(&dev->device_lock);
+	mei_io_list_init(&complete_list);
+
+	if (pci_dev_msi_enabled(dev->pdev))
+		mei_txe_check_and_ack_intrs(dev, true);
+
+	/* show irq events */
+	mei_txe_pending_interrupts(dev);
+
+	hw->aliveness = mei_txe_aliveness_get(dev);
+	hw->readiness = mei_txe_readiness_get(dev);
+
+	/* Readiness:
+	 * Detection of TXE driver going through reset
+	 * or TXE driver resetting the HECI interface.
+	 */
+	if (test_and_clear_bit(TXE_INTR_READINESS_BIT, &hw->intr_cause)) {
+		dev_dbg(&dev->pdev->dev, "Readiness Interrupt was received...\n");
+
+		/* Check if SeC is going through reset */
+		if (mei_txe_readiness_is_sec_rdy(hw->readiness)) {
+			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
+			dev->recvd_hw_ready = true;
+		} else {
+			dev->recvd_hw_ready = false;
+			if (dev->dev_state != MEI_DEV_RESETTING) {
+
+				dev_warn(&dev->pdev->dev, "FW not ready: resetting.\n");
+				schedule_work(&dev->reset_work);
+				goto end;
+
+			}
+		}
+		wake_up(&dev->wait_hw_ready);
+	}
+
+	/************************************************************/
+	/* Check interrupt cause:
+	 * Aliveness: Detection of SeC acknowledge of host request that
+	 * it remain alive or host cancellation of that request.
+	 */
+
+	if (test_and_clear_bit(TXE_INTR_ALIVENESS_BIT, &hw->intr_cause)) {
+		/* Clear the interrupt cause */
+		dev_dbg(&dev->pdev->dev,
+			"Aliveness Interrupt: Status: %d\n", hw->aliveness);
+		hw->recvd_aliveness = true;
+		if (waitqueue_active(&hw->wait_aliveness))
+			wake_up(&hw->wait_aliveness);
+	}
+
+
+	/* Output Doorbell:
+	 * Detection of SeC having sent output to host
+	 */
+	slots = mei_count_full_read_slots(dev);
+	if (test_and_clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause)) {
+		/* Read from TXE */
+		rets = mei_irq_read_handler(dev, &complete_list, &slots);
+		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
+			dev_err(&dev->pdev->dev,
+				"mei_irq_read_handler ret = %d.\n", rets);
+
+			schedule_work(&dev->reset_work);
+			goto end;
+		}
+	}
+	/* Input Ready: Detection if host can write to SeC */
+	if (test_and_clear_bit(TXE_INTR_IN_READY_BIT, &hw->intr_cause)) {
+		dev->hbuf_is_ready = true;
+		hw->slots = dev->hbuf_depth;
+	}
+
+	if (hw->aliveness && dev->hbuf_is_ready) {
+		/* get the real register value */
+		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
+		rets = mei_irq_write_handler(dev, &complete_list);
+		if (rets && rets != -EMSGSIZE)
+			dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n",
+				rets);
+		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
+	}
+
+	mei_irq_compl_handler(dev, &complete_list);
+
+end:
+	dev_dbg(&dev->pdev->dev, "interrupt thread end ret = %d\n", rets);
+
+	mutex_unlock(&dev->device_lock);
+
+	mei_enable_interrupts(dev);
+	return IRQ_HANDLED;
+}
+
+static const struct mei_hw_ops mei_txe_hw_ops = {
+
+	.host_is_ready = mei_txe_host_is_ready,
+
+	.hw_is_ready = mei_txe_hw_is_ready,
+	.hw_reset = mei_txe_hw_reset,
+	.hw_config = mei_txe_hw_config,
+	.hw_start = mei_txe_hw_start,
+
+	.intr_clear = mei_txe_intr_clear,
+	.intr_enable = mei_txe_intr_enable,
+	.intr_disable = mei_txe_intr_disable,
+
+	.hbuf_free_slots = mei_txe_hbuf_empty_slots,
+	.hbuf_is_ready = mei_txe_is_input_ready,
+	.hbuf_max_len = mei_txe_hbuf_max_len,
+
+	.write = mei_txe_write,
+
+	.rdbuf_full_slots = mei_txe_count_full_read_slots,
+	.read_hdr = mei_txe_read_hdr,
+
+	.read = mei_txe_read,
+
+};
+
+/**
+ * mei_txe_dev_init - allocates and initializes txe hardware specific structure
+ *
+ * @pdev - pci device
+ * returns struct mei_device * on success or NULL;
+ *
+ */
+struct mei_device *mei_txe_dev_init(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+	struct mei_txe_hw *hw;
+
+	dev = kzalloc(sizeof(struct mei_device) +
+			 sizeof(struct mei_txe_hw), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	mei_device_init(dev);
+
+	hw = to_txe_hw(dev);
+
+	init_waitqueue_head(&hw->wait_aliveness);
+
+	dev->ops = &mei_txe_hw_ops;
+
+	dev->pdev = pdev;
+	return dev;
+}
+
+/**
+ * mei_txe_setup_satt2 - SATT2 configuration for DMA support.
+ *
+ * @dev:   the device structure
+ * @addr:  physical address start of the range
+ * @range: physical range size
+ */
+int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range)
+{
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+
+	u32 lo32 = lower_32_bits(addr);
+	u32 hi32 = upper_32_bits(addr);
+	u32 ctrl;
+
+	/* SATT is limited to 36 Bits */
+	if (hi32 & ~0xF)
+		return -EINVAL;
+
+	/* SATT has to be 16Byte aligned */
+	if (lo32 & 0xF)
+		return -EINVAL;
+
+	/* SATT range has to be 4Bytes aligned */
+	if (range & 0x4)
+		return -EINVAL;
+
+	/* SATT is limited to 32 MB range*/
+	if (range > SATT_RANGE_MAX)
+		return -EINVAL;
+
+	ctrl = SATT2_CTRL_VALID_MSK;
+	ctrl |= hi32  << SATT2_CTRL_BR_BASE_ADDR_REG_SHIFT;
+
+	mei_txe_br_reg_write(hw, SATT2_SAP_SIZE_REG, range);
+	mei_txe_br_reg_write(hw, SATT2_BRG_BA_LSB_REG, lo32);
+	mei_txe_br_reg_write(hw, SATT2_CTRL_REG, ctrl);
+	dev_dbg(&dev->pdev->dev, "SATT2: SAP_SIZE_OFFSET=0x%08X, BRG_BA_LSB_OFFSET=0x%08X, CTRL_OFFSET=0x%08X\n",
+		range, lo32, ctrl);
+
+	return 0;
+}
diff --git a/drivers/misc/mei/hw-txe.h b/drivers/misc/mei/hw-txe.h
new file mode 100644
index 000000000000..0812d98633a4
--- /dev/null
+++ b/drivers/misc/mei/hw-txe.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MEI_HW_TXE_H_
+#define _MEI_HW_TXE_H_
+
+#include <linux/irqreturn.h>
+
+#include "hw.h"
+#include "hw-txe-regs.h"
+
+/* Flatten Hierarchy interrupt cause */
+#define TXE_INTR_READINESS_BIT  0 /* HISR_INT_0_STS */
+#define TXE_INTR_READINESS      HISR_INT_0_STS
+#define TXE_INTR_ALIVENESS_BIT  1 /* HISR_INT_1_STS */
+#define TXE_INTR_ALIVENESS      HISR_INT_1_STS
+#define TXE_INTR_OUT_DB_BIT     2 /* HISR_INT_2_STS */
+#define TXE_INTR_OUT_DB         HISR_INT_2_STS
+#define TXE_INTR_IN_READY_BIT   8 /* beyond HISR */
+#define TXE_INTR_IN_READY       BIT(8)
+
+/**
+ * struct mei_txe_hw - txe hardware specifics
+ *
+ * @mem_addr:        SeC and BRIDGE bars
+ * @aliveness:       aliveness (power gating) state of the hardware
+ * @readiness:       readiness state of the hardware
+ * @wait_aliveness:  aliveness wait queue
+ * @recvd_aliveness: aliveness interrupt was recived
+ * @intr_cause:      translated interrupt cause
+ */
+struct mei_txe_hw {
+	void __iomem *mem_addr[NUM_OF_MEM_BARS];
+	u32 aliveness;
+	u32 readiness;
+	u32 slots;
+
+	wait_queue_head_t wait_aliveness;
+	bool recvd_aliveness;
+
+	unsigned long intr_cause;
+};
+
+#define to_txe_hw(dev) (struct mei_txe_hw *)((dev)->hw)
+
+static inline struct mei_device *hw_txe_to_mei(struct mei_txe_hw *hw)
+{
+	return container_of((void *)hw, struct mei_device, hw);
+}
+
+struct mei_device *mei_txe_dev_init(struct pci_dev *pdev);
+
+irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id);
+irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id);
+
+int mei_txe_aliveness_set_sync(struct mei_device *dev, u32 req);
+
+int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range);
+
+
+#endif /* _MEI_HW_TXE_H_ */
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index dd44e33ad2b6..6b476ab49b2e 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -22,7 +22,7 @@
 /*
  * Timeouts in Seconds
  */
-#define MEI_INTEROP_TIMEOUT         7  /* Timeout on ready message */
+#define MEI_HW_READY_TIMEOUT        2  /* Timeout on ready message */
 #define MEI_CONNECT_TIMEOUT         3  /* HPS: at least 2 seconds */
 
 #define MEI_CL_CONNECT_TIMEOUT     15  /* HPS: Client Connect Timeout */
@@ -31,13 +31,13 @@
 #define MEI_IAMTHIF_STALL_TIMER    12  /* HPS */
 #define MEI_IAMTHIF_READ_TIMER     10  /* HPS */
 
+#define MEI_HBM_TIMEOUT            1   /* 1 second */
 
 /*
  * MEI Version
  */
 #define HBM_MINOR_VERSION                   0
 #define HBM_MAJOR_VERSION                   1
-#define HBM_TIMEOUT                         1	/* 1 second */
 
 /* Host bus message command opcode */
 #define MEI_HBM_CMD_OP_MSK                  0x7f
@@ -89,19 +89,19 @@ enum mei_stop_reason_types {
  * Client Connect Status
  * used by hbm_client_connect_response.status
  */
-enum client_connect_status_types {
-	CCS_SUCCESS = 0x00,
-	CCS_NOT_FOUND = 0x01,
-	CCS_ALREADY_STARTED = 0x02,
-	CCS_OUT_OF_RESOURCES = 0x03,
-	CCS_MESSAGE_SMALL = 0x04
+enum mei_cl_connect_status {
+	MEI_CL_CONN_SUCCESS          = 0x00,
+	MEI_CL_CONN_NOT_FOUND        = 0x01,
+	MEI_CL_CONN_ALREADY_STARTED  = 0x02,
+	MEI_CL_CONN_OUT_OF_RESOURCES = 0x03,
+	MEI_CL_CONN_MESSAGE_SMALL    = 0x04
 };
 
 /*
  * Client Disconnect Status
  */
-enum client_disconnect_status_types {
-	CDS_SUCCESS = 0x00
+enum  mei_cl_disconnect_status {
+	MEI_CL_DISCONN_SUCCESS = 0x00
 };
 
 /*
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index cdd31c2a2a2b..4460975c0eef 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -116,7 +116,6 @@ int mei_reset(struct mei_device *dev)
 		mei_cl_unlink(&dev->wd_cl);
 		mei_cl_unlink(&dev->iamthif_cl);
 		mei_amthif_reset_params(dev);
-		memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
 	}
 
 
@@ -126,7 +125,6 @@ int mei_reset(struct mei_device *dev)
 
 	if (ret) {
 		dev_err(&dev->pdev->dev, "hw_reset failed ret = %d\n", ret);
-		dev->dev_state = MEI_DEV_DISABLED;
 		return ret;
 	}
 
@@ -139,7 +137,6 @@ int mei_reset(struct mei_device *dev)
 	ret = mei_hw_start(dev);
 	if (ret) {
 		dev_err(&dev->pdev->dev, "hw_start failed ret = %d\n", ret);
-		dev->dev_state = MEI_DEV_DISABLED;
 		return ret;
 	}
 
@@ -149,7 +146,7 @@ int mei_reset(struct mei_device *dev)
 	ret = mei_hbm_start_req(dev);
 	if (ret) {
 		dev_err(&dev->pdev->dev, "hbm_start failed ret = %d\n", ret);
-		dev->dev_state = MEI_DEV_DISABLED;
+		dev->dev_state = MEI_DEV_RESETTING;
 		return ret;
 	}
 
@@ -166,6 +163,7 @@ EXPORT_SYMBOL_GPL(mei_reset);
  */
 int mei_start(struct mei_device *dev)
 {
+	int ret;
 	mutex_lock(&dev->device_lock);
 
 	/* acknowledge interrupt and stop interrupts */
@@ -175,10 +173,18 @@ int mei_start(struct mei_device *dev)
 
 	dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
 
-	dev->dev_state = MEI_DEV_INITIALIZING;
 	dev->reset_count = 0;
-	mei_reset(dev);
+	do {
+		dev->dev_state = MEI_DEV_INITIALIZING;
+		ret = mei_reset(dev);
+
+		if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
+			dev_err(&dev->pdev->dev, "reset failed ret = %d", ret);
+			goto err;
+		}
+	} while (ret);
 
+	/* we cannot start the device w/o hbm start message completed */
 	if (dev->dev_state == MEI_DEV_DISABLED) {
 		dev_err(&dev->pdev->dev, "reset failed");
 		goto err;
@@ -238,27 +244,40 @@ int mei_restart(struct mei_device *dev)
 
 	mutex_unlock(&dev->device_lock);
 
-	if (err || dev->dev_state == MEI_DEV_DISABLED)
+	if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
+		dev_err(&dev->pdev->dev, "device disabled = %d\n", err);
 		return -ENODEV;
+	}
+
+	/* try to start again */
+	if (err)
+		schedule_work(&dev->reset_work);
+
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mei_restart);
 
-
 static void mei_reset_work(struct work_struct *work)
 {
 	struct mei_device *dev =
 		container_of(work, struct mei_device,  reset_work);
+	int ret;
 
 	mutex_lock(&dev->device_lock);
 
-	mei_reset(dev);
+	ret = mei_reset(dev);
 
 	mutex_unlock(&dev->device_lock);
 
-	if (dev->dev_state == MEI_DEV_DISABLED)
-		dev_err(&dev->pdev->dev, "reset failed");
+	if (dev->dev_state == MEI_DEV_DISABLED) {
+		dev_err(&dev->pdev->dev, "device disabled = %d\n", ret);
+		return;
+	}
+
+	/* retry reset in case of failure */
+	if (ret)
+		schedule_work(&dev->reset_work);
 }
 
 void mei_stop(struct mei_device *dev)
@@ -269,6 +288,8 @@ void mei_stop(struct mei_device *dev)
 
 	mei_nfc_host_exit(dev);
 
+	mei_cl_bus_remove_devices(dev);
+
 	mutex_lock(&dev->device_lock);
 
 	mei_wd_stop(dev);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index f0fbb5179f80..5aab335f585b 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -161,29 +161,62 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
 }
 
 /**
+ * mei_cl_irq_disconnect_rsp - send disconnection response message
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @cmpl_list: complete list.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
+				     struct mei_cl_cb *cmpl_list)
+{
+	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
+	int ret;
+
+	slots = mei_hbuf_empty_slots(dev);
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_response));
+
+	if (slots < msg_slots)
+		return -EMSGSIZE;
+
+	ret = mei_hbm_cl_disconnect_rsp(dev, cl);
+
+	cl->state = MEI_FILE_DISCONNECTED;
+	cl->status = 0;
+	mei_io_cb_free(cb);
+
+	return ret;
+}
+
+
+
+/**
  * mei_cl_irq_close - processes close related operation from
  *	interrupt thread context - send disconnect request
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
-			s32 *slots, struct mei_cl_cb *cmpl_list)
+			    struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
 
-	u32 msg_slots =
-		mei_data2slots(sizeof(struct hbm_client_connect_request));
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+	slots = mei_hbuf_empty_slots(dev);
 
-	if (*slots < msg_slots)
+	if (slots < msg_slots)
 		return -EMSGSIZE;
 
-	*slots -= msg_slots;
-
 	if (mei_hbm_cl_disconnect_req(dev, cl)) {
 		cl->status = 0;
 		cb->buf_idx = 0;
@@ -207,27 +240,23 @@ static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
-			   s32 *slots, struct mei_cl_cb *cmpl_list)
+			   struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
-	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
-
+	u32 msg_slots;
+	int slots;
 	int ret;
 
+	msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
+	slots = mei_hbuf_empty_slots(dev);
 
-	if (*slots < msg_slots) {
-		/* return the cancel routine */
-		list_del(&cb->list);
+	if (slots < msg_slots)
 		return -EMSGSIZE;
-	}
-
-	*slots -= msg_slots;
 
 	ret = mei_hbm_cl_flow_control_req(dev, cl);
 	if (ret) {
@@ -244,32 +273,30 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 
 /**
- * mei_cl_irq_ioctl - processes client ioctl related operation from the
- *	interrupt thread context -   send connection request
+ * mei_cl_irq_connect - send connect request in irq_thread context
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
-			   s32 *slots, struct mei_cl_cb *cmpl_list)
+static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
+			      struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
 	int ret;
 
-	u32 msg_slots =
-		mei_data2slots(sizeof(struct hbm_client_connect_request));
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+	slots = mei_hbuf_empty_slots(dev);
 
-	if (*slots < msg_slots) {
-		/* return the cancel routine */
-		list_del(&cb->list);
-		return -EMSGSIZE;
-	}
+	if (mei_cl_is_other_connecting(cl))
+		return 0;
 
-	*slots -=  msg_slots;
+	if (slots < msg_slots)
+		return -EMSGSIZE;
 
 	cl->state = MEI_FILE_CONNECTING;
 
@@ -323,7 +350,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 		dev_err(&dev->pdev->dev, "less data available than length=%08x.\n",
 				*slots);
 		/* we can't read the message */
-		ret = -ERANGE;
+		ret = -EBADMSG;
 		goto end;
 	}
 
@@ -409,10 +436,10 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 	s32 slots;
 	int ret;
 
-	if (!mei_hbuf_is_ready(dev)) {
-		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
+
+	if (!mei_hbuf_acquire(dev))
 		return 0;
-	}
+
 	slots = mei_hbuf_empty_slots(dev);
 	if (slots <= 0)
 		return -EMSGSIZE;
@@ -447,29 +474,16 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 
 	if (dev->wd_state == MEI_WD_STOPPING) {
 		dev->wd_state = MEI_WD_IDLE;
-		wake_up_interruptible(&dev->wait_stop_wd);
+		wake_up(&dev->wait_stop_wd);
 	}
 
-	if (dev->wr_ext_msg.hdr.length) {
-		mei_write_message(dev, &dev->wr_ext_msg.hdr,
-				dev->wr_ext_msg.data);
-		slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
-		dev->wr_ext_msg.hdr.length = 0;
-	}
-	if (dev->dev_state == MEI_DEV_ENABLED) {
+	if (mei_cl_is_connected(&dev->wd_cl)) {
 		if (dev->wd_pending &&
 		    mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
-			if (mei_wd_send(dev))
-				dev_dbg(&dev->pdev->dev, "wd send failed.\n");
-			else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
-				return -ENODEV;
-
+			ret = mei_wd_send(dev);
+			if (ret)
+				return ret;
 			dev->wd_pending = false;
-
-			if (dev->wd_state == MEI_WD_RUNNING)
-				slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
-			else
-				slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
 		}
 	}
 
@@ -484,28 +498,30 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		switch (cb->fop_type) {
 		case MEI_FOP_CLOSE:
 			/* send disconnect message */
-			ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_close(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
 		case MEI_FOP_READ:
 			/* send flow control message */
-			ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_read(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
-		case MEI_FOP_IOCTL:
+		case MEI_FOP_CONNECT:
 			/* connect message */
-			if (mei_cl_is_other_connecting(cl))
-				continue;
-			ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_connect(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
-
+		case MEI_FOP_DISCONNECT_RSP:
+			/* send disconnect resp */
+			ret = mei_cl_irq_disconnect_rsp(cl, cb, cmpl_list);
+			if (ret)
+				return ret;
 		default:
 			BUG();
 		}
@@ -518,11 +534,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		if (cl == NULL)
 			continue;
 		if (cl == &dev->iamthif_cl)
-			ret = mei_amthif_irq_write_complete(cl, cb,
-						&slots, cmpl_list);
+			ret = mei_amthif_irq_write(cl, cb, cmpl_list);
 		else
-			ret = mei_cl_irq_write_complete(cl, cb,
-						&slots, cmpl_list);
+			ret = mei_cl_irq_write(cl, cb, cmpl_list);
 		if (ret)
 			return ret;
 	}
@@ -541,8 +555,7 @@ EXPORT_SYMBOL_GPL(mei_irq_write_handler);
 void mei_timer(struct work_struct *work)
 {
 	unsigned long timeout;
-	struct mei_cl *cl_pos = NULL;
-	struct mei_cl *cl_next = NULL;
+	struct mei_cl *cl;
 	struct mei_cl_cb  *cb_pos = NULL;
 	struct mei_cl_cb  *cb_next = NULL;
 
@@ -570,9 +583,9 @@ void mei_timer(struct work_struct *work)
 		goto out;
 
 	/*** connect/disconnect timeouts ***/
-	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
-		if (cl_pos->timer_count) {
-			if (--cl_pos->timer_count == 0) {
+	list_for_each_entry(cl, &dev->file_list, link) {
+		if (cl->timer_count) {
+			if (--cl->timer_count == 0) {
 				dev_err(&dev->pdev->dev, "timer: connect/disconnect timeout.\n");
 				mei_reset(dev);
 				goto out;
@@ -580,6 +593,9 @@ void mei_timer(struct work_struct *work)
 		}
 	}
 
+	if (!mei_cl_is_connected(&dev->iamthif_cl))
+		goto out;
+
 	if (dev->iamthif_stall_timer) {
 		if (--dev->iamthif_stall_timer == 0) {
 			dev_err(&dev->pdev->dev, "timer: amthif  hanged.\n");
@@ -619,10 +635,10 @@ void mei_timer(struct work_struct *work)
 			list_for_each_entry_safe(cb_pos, cb_next,
 				&dev->amthif_rd_complete_list.list, list) {
 
-				cl_pos = cb_pos->file_object->private_data;
+				cl = cb_pos->file_object->private_data;
 
 				/* Finding the AMTHI entry. */
-				if (cl_pos == &dev->iamthif_cl)
+				if (cl == &dev->iamthif_cl)
 					list_del(&cb_pos->list);
 			}
 			mei_io_cb_free(dev->iamthif_current_cb);
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 5424f8ff3f7f..49e3bb8a724a 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -340,7 +340,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
 	id = mei_me_cl_by_id(dev, cl->me_client_id);
 	if (id < 0) {
-		rets = -ENODEV;
+		rets = -ENOTTY;
 		goto out;
 	}
 
@@ -471,7 +471,7 @@ static int mei_ioctl_connect_client(struct file *file,
 	if (i < 0 || dev->me_clients[i].props.fixed_address) {
 		dev_dbg(&dev->pdev->dev, "Cannot connect to FW Client UUID = %pUl\n",
 				&data->in_client_uuid);
-		rets = -ENODEV;
+		rets = -ENOTTY;
 		goto end;
 	}
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index f7de95b4cdd9..36640b9d54c5 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -130,16 +130,18 @@ enum mei_wd_states {
 
 /**
  * enum mei_cb_file_ops  - file operation associated with the callback
- * @MEI_FOP_READ   - read
- * @MEI_FOP_WRITE  - write
- * @MEI_FOP_IOCTL  - ioctl
- * @MEI_FOP_OPEN   - open
- * @MEI_FOP_CLOSE  - close
+ * @MEI_FOP_READ      - read
+ * @MEI_FOP_WRITE     - write
+ * @MEI_FOP_CONNECT   - connect
+ * @MEI_FOP_DISCONNECT_RSP - disconnect response
+ * @MEI_FOP_OPEN      - open
+ * @MEI_FOP_CLOSE     - close
  */
 enum mei_cb_file_ops {
 	MEI_FOP_READ = 0,
 	MEI_FOP_WRITE,
-	MEI_FOP_IOCTL,
+	MEI_FOP_CONNECT,
+	MEI_FOP_DISCONNECT_RSP,
 	MEI_FOP_OPEN,
 	MEI_FOP_CLOSE
 };
@@ -294,6 +296,7 @@ int __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length);
 int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length);
 int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
 void mei_cl_bus_rx_event(struct mei_cl *cl);
+void mei_cl_bus_remove_devices(struct mei_device *dev);
 int mei_cl_bus_init(void);
 void mei_cl_bus_exit(void);
 
@@ -339,7 +342,6 @@ struct mei_cl_device {
  * @hbuf_depth - depth of hardware host/write buffer is slots
  * @hbuf_is_ready - query if the host host/write buffer is ready
  * @wr_msg - the buffer for hbm control messages
- * @wr_ext_msg - the buffer for hbm control responses (set in read cycle)
  */
 struct mei_device {
 	struct pci_dev *pdev;	/* pointer to pci device struct */
@@ -394,11 +396,6 @@ struct mei_device {
 		unsigned char data[128];
 	} wr_msg;
 
-	struct {
-		struct mei_msg_hdr hdr;
-		unsigned char data[4];	/* All HBM messages are 4 bytes */
-	} wr_ext_msg;		/* for control responses */
-
 	struct hbm_version version;
 
 	struct mei_me_client *me_clients; /* Note: memory has to be allocated */
@@ -518,8 +515,8 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 
 void mei_amthif_run_next_cmd(struct mei_device *dev);
 
-int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				  s32 *slots, struct mei_cl_cb *cmpl_list);
+int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+			struct mei_cl_cb *cmpl_list);
 
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
 int mei_amthif_irq_read_msg(struct mei_device *dev,
@@ -546,7 +543,7 @@ int mei_wd_host_init(struct mei_device *dev);
  *   once we got connection to the WD Client
  * @dev - mei device
  */
-void mei_watchdog_register(struct mei_device *dev);
+int mei_watchdog_register(struct mei_device *dev);
 /*
  * mei_watchdog_unregister  - Unregistering watchdog interface
  * @dev - mei device
@@ -633,6 +630,8 @@ static inline int mei_count_full_read_slots(struct mei_device *dev)
 	return dev->ops->rdbuf_full_slots(dev);
 }
 
+bool mei_hbuf_acquire(struct mei_device *dev);
+
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 int mei_dbgfs_register(struct mei_device *dev, const char *name);
 void mei_dbgfs_deregister(struct mei_device *dev);
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
index a58320c0c049..3095fc514a65 100644
--- a/drivers/misc/mei/nfc.c
+++ b/drivers/misc/mei/nfc.c
@@ -364,7 +364,7 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
 	if (!wait_event_interruptible_timeout(ndev->send_wq,
 				ndev->recv_req_id == ndev->req_id, HZ)) {
 		dev_err(&dev->pdev->dev, "NFC MEI command timeout\n");
-		err = -ETIMEDOUT;
+		err = -ETIME;
 	} else {
 		ndev->req_id++;
 	}
@@ -502,7 +502,7 @@ int mei_nfc_host_init(struct mei_device *dev)
 	i = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
 	if (i < 0) {
 		dev_info(&dev->pdev->dev, "nfc: failed to find the client\n");
-		ret = -ENOENT;
+		ret = -ENOTTY;
 		goto err;
 	}
 
@@ -520,7 +520,7 @@ int mei_nfc_host_init(struct mei_device *dev)
 	i = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
 	if (i < 0) {
 		dev_info(&dev->pdev->dev, "nfc: failed to find the client\n");
-		ret = -ENOENT;
+		ret = -ENOTTY;
 		goto err;
 	}
 
@@ -552,13 +552,7 @@ err:
 void mei_nfc_host_exit(struct mei_device *dev)
 {
 	struct mei_nfc_dev *ndev = &nfc_dev;
-
 	cancel_work_sync(&ndev->init_work);
+}
 
-	mutex_lock(&dev->device_lock);
-	if (ndev->cl && ndev->cl->device)
-		mei_cl_remove_device(ndev->cl->device);
 
-	mei_nfc_free(ndev);
-	mutex_unlock(&dev->device_lock);
-}
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index ddadd08956f4..50d9cb52a71f 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -27,7 +27,6 @@
 #include <linux/aio.h>
 #include <linux/pci.h>
 #include <linux/poll.h>
-#include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/sched.h>
@@ -270,7 +269,7 @@ static void mei_me_remove(struct pci_dev *pdev)
 
 
 }
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mei_me_pci_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -330,11 +329,12 @@ static int mei_me_pci_resume(struct device *device)
 
 	return 0;
 }
+
 static SIMPLE_DEV_PM_OPS(mei_me_pm_ops, mei_me_pci_suspend, mei_me_pci_resume);
 #define MEI_ME_PM_OPS	(&mei_me_pm_ops)
 #else
 #define MEI_ME_PM_OPS	NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 /*
  *  PCI driver structure
  */
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
new file mode 100644
index 000000000000..a5bf39ad3ff1
--- /dev/null
+++ b/drivers/misc/mei/pci-txe.c
@@ -0,0 +1,293 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/uuid.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+#include <linux/mei.h>
+
+
+#include "mei_dev.h"
+#include "hw-txe.h"
+
+static DEFINE_PCI_DEVICE_TABLE(mei_txe_pci_tbl) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F18)}, /* Baytrail */
+	{0, }
+};
+MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
+
+
+static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
+{
+	int i;
+	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
+		if (hw->mem_addr[i]) {
+			pci_iounmap(pdev, hw->mem_addr[i]);
+			hw->mem_addr[i] = NULL;
+		}
+	}
+}
+/**
+ * mei_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in mei_txe_pci_tbl
+ *
+ * returns 0 on success, <0 on failure.
+ */
+static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct mei_device *dev;
+	struct mei_txe_hw *hw;
+	int err;
+	int i;
+
+	/* enable pci dev */
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable pci device.\n");
+		goto end;
+	}
+	/* set PCI host mastering  */
+	pci_set_master(pdev);
+	/* pci request regions for mei driver */
+	err = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (err) {
+		dev_err(&pdev->dev, "failed to get pci regions.\n");
+		goto disable_device;
+	}
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (err) {
+			dev_err(&pdev->dev, "No suitable DMA available.\n");
+			goto release_regions;
+		}
+	}
+
+	/* allocates and initializes the mei dev structure */
+	dev = mei_txe_dev_init(pdev);
+	if (!dev) {
+		err = -ENOMEM;
+		goto release_regions;
+	}
+	hw = to_txe_hw(dev);
+
+	/* mapping  IO device memory */
+	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
+		hw->mem_addr[i] = pci_iomap(pdev, i, 0);
+		if (!hw->mem_addr[i]) {
+			dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
+			err = -ENOMEM;
+			goto free_device;
+		}
+	}
+
+
+	pci_enable_msi(pdev);
+
+	/* clear spurious interrupts */
+	mei_clear_interrupts(dev);
+
+	/* request and enable interrupt  */
+	if (pci_dev_msi_enabled(pdev))
+		err = request_threaded_irq(pdev->irq,
+			NULL,
+			mei_txe_irq_thread_handler,
+			IRQF_ONESHOT, KBUILD_MODNAME, dev);
+	else
+		err = request_threaded_irq(pdev->irq,
+			mei_txe_irq_quick_handler,
+			mei_txe_irq_thread_handler,
+			IRQF_SHARED, KBUILD_MODNAME, dev);
+	if (err) {
+		dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n",
+			pdev->irq);
+		goto free_device;
+	}
+
+	if (mei_start(dev)) {
+		dev_err(&pdev->dev, "init hw failure.\n");
+		err = -ENODEV;
+		goto release_irq;
+	}
+
+	err = mei_register(dev);
+	if (err)
+		goto release_irq;
+
+	pci_set_drvdata(pdev, dev);
+
+	return 0;
+
+release_irq:
+
+	mei_cancel_work(dev);
+
+	/* disable interrupts */
+	mei_disable_interrupts(dev);
+
+	free_irq(pdev->irq, dev);
+	pci_disable_msi(pdev);
+
+free_device:
+	mei_txe_pci_iounmap(pdev, hw);
+
+	kfree(dev);
+release_regions:
+	pci_release_regions(pdev);
+disable_device:
+	pci_disable_device(pdev);
+end:
+	dev_err(&pdev->dev, "initialization failed.\n");
+	return err;
+}
+
+/**
+ * mei_remove - Device Removal Routine
+ *
+ * @pdev: PCI device structure
+ *
+ * mei_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ */
+static void mei_txe_remove(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+	struct mei_txe_hw *hw;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev) {
+		dev_err(&pdev->dev, "mei: dev =NULL\n");
+		return;
+	}
+
+	hw = to_txe_hw(dev);
+
+	mei_stop(dev);
+
+	/* disable interrupts */
+	mei_disable_interrupts(dev);
+	free_irq(pdev->irq, dev);
+	pci_disable_msi(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+
+	mei_txe_pci_iounmap(pdev, hw);
+
+	mei_deregister(dev);
+
+	kfree(dev);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+
+#ifdef CONFIG_PM_SLEEP
+static int mei_txe_pci_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct mei_device *dev = pci_get_drvdata(pdev);
+
+	if (!dev)
+		return -ENODEV;
+
+	dev_dbg(&pdev->dev, "suspend\n");
+
+	mei_stop(dev);
+
+	mei_disable_interrupts(dev);
+
+	free_irq(pdev->irq, dev);
+	pci_disable_msi(pdev);
+
+	return 0;
+}
+
+static int mei_txe_pci_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct mei_device *dev;
+	int err;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev)
+		return -ENODEV;
+
+	pci_enable_msi(pdev);
+
+	mei_clear_interrupts(dev);
+
+	/* request and enable interrupt */
+	if (pci_dev_msi_enabled(pdev))
+		err = request_threaded_irq(pdev->irq,
+			NULL,
+			mei_txe_irq_thread_handler,
+			IRQF_ONESHOT, KBUILD_MODNAME, dev);
+	else
+		err = request_threaded_irq(pdev->irq,
+			mei_txe_irq_quick_handler,
+			mei_txe_irq_thread_handler,
+			IRQF_SHARED, KBUILD_MODNAME, dev);
+	if (err) {
+		dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
+				pdev->irq);
+		return err;
+	}
+
+	err = mei_restart(dev);
+
+	return err;
+}
+
+static SIMPLE_DEV_PM_OPS(mei_txe_pm_ops,
+			 mei_txe_pci_suspend,
+			 mei_txe_pci_resume);
+
+#define MEI_TXE_PM_OPS	(&mei_txe_pm_ops)
+#else
+#define MEI_TXE_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+/*
+ *  PCI driver structure
+ */
+static struct pci_driver mei_txe_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = mei_txe_pci_tbl,
+	.probe = mei_txe_probe,
+	.remove = mei_txe_remove,
+	.shutdown = mei_txe_remove,
+	.driver.pm = MEI_TXE_PM_OPS,
+};
+
+module_pci_driver(mei_txe_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index f70945ed96f6..e084adf27259 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -53,7 +53,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
  *
  * @dev: the device structure
  *
- * returns -ENENT if wd client cannot be found
+ * returns -ENOTTY if wd client cannot be found
  *         -EIO if write has failed
  *         0 on success
  */
@@ -73,7 +73,7 @@ int mei_wd_host_init(struct mei_device *dev)
 	id = mei_me_cl_by_uuid(dev, &mei_wd_guid);
 	if (id < 0) {
 		dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
-		return id;
+		return -ENOTTY;
 	}
 
 	cl->me_client_id = dev->me_clients[id].client_id;
@@ -87,15 +87,20 @@ int mei_wd_host_init(struct mei_device *dev)
 
 	cl->state = MEI_FILE_CONNECTING;
 
-	if (mei_hbm_cl_connect_req(dev, cl)) {
-		dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
-		cl->state = MEI_FILE_DISCONNECTED;
-		cl->host_client_id = 0;
-		return -EIO;
+	ret = mei_cl_connect(cl, NULL);
+
+	if (ret) {
+		dev_err(&dev->pdev->dev, "wd: failed to connect = %d\n", ret);
+		mei_cl_unlink(cl);
+		return ret;
 	}
-	cl->timer_count = MEI_CONNECT_TIMEOUT;
 
-	return 0;
+	ret = mei_watchdog_register(dev);
+	if (ret) {
+		mei_cl_disconnect(cl);
+		mei_cl_unlink(cl);
+	}
+	return ret;
 }
 
 /**
@@ -106,13 +111,16 @@ int mei_wd_host_init(struct mei_device *dev)
  * returns 0 if success,
  *	-EIO when message send fails
  *	-EINVAL when invalid message is to be sent
+ *	-ENODEV on flow control failure
  */
 int mei_wd_send(struct mei_device *dev)
 {
+	struct mei_cl *cl = &dev->wd_cl;
 	struct mei_msg_hdr hdr;
+	int ret;
 
-	hdr.host_addr = dev->wd_cl.host_client_id;
-	hdr.me_addr = dev->wd_cl.me_client_id;
+	hdr.host_addr = cl->host_client_id;
+	hdr.me_addr = cl->me_client_id;
 	hdr.msg_complete = 1;
 	hdr.reserved = 0;
 	hdr.internal = 0;
@@ -121,10 +129,24 @@ int mei_wd_send(struct mei_device *dev)
 		hdr.length = MEI_WD_START_MSG_SIZE;
 	else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
 		hdr.length = MEI_WD_STOP_MSG_SIZE;
-	else
+	else {
+		dev_err(&dev->pdev->dev, "wd: invalid message is to be sent, aborting\n");
 		return -EINVAL;
+	}
 
-	return mei_write_message(dev, &hdr, dev->wd_data);
+	ret = mei_write_message(dev, &hdr, dev->wd_data);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "wd: write message failed\n");
+		return ret;
+	}
+
+	ret = mei_cl_flow_ctrl_reduce(cl);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "wd: flow_ctrl_reduce failed.\n");
+		return ret;
+	}
+
+	return 0;
 }
 
 /**
@@ -133,9 +155,11 @@ int mei_wd_send(struct mei_device *dev)
  * @dev: the device structure
  * @preserve: indicate if to keep the timeout value
  *
- * returns 0 if success,
- *	-EIO when message send fails
+ * returns 0 if success
+ * on error:
+ *	-EIO    when message send fails
  *	-EINVAL when invalid message is to be sent
+ *	-ETIME  on message timeout
  */
 int mei_wd_stop(struct mei_device *dev)
 {
@@ -151,20 +175,12 @@ int mei_wd_stop(struct mei_device *dev)
 
 	ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
 	if (ret < 0)
-		goto out;
-
-	if (ret && dev->hbuf_is_ready) {
-		ret = 0;
-		dev->hbuf_is_ready = false;
-
-		if (!mei_wd_send(dev)) {
-			ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl);
-			if (ret)
-				goto out;
-		} else {
-			dev_err(&dev->pdev->dev, "wd: send stop failed\n");
-		}
+		goto err;
 
+	if (ret && mei_hbuf_acquire(dev)) {
+		ret = mei_wd_send(dev);
+		if (ret)
+			goto err;
 		dev->wd_pending = false;
 	} else {
 		dev->wd_pending = true;
@@ -172,21 +188,21 @@ int mei_wd_stop(struct mei_device *dev)
 
 	mutex_unlock(&dev->device_lock);
 
-	ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
-					dev->wd_state == MEI_WD_IDLE,
-					msecs_to_jiffies(MEI_WD_STOP_TIMEOUT));
+	ret = wait_event_timeout(dev->wait_stop_wd,
+				dev->wd_state == MEI_WD_IDLE,
+				msecs_to_jiffies(MEI_WD_STOP_TIMEOUT));
 	mutex_lock(&dev->device_lock);
-	if (dev->wd_state == MEI_WD_IDLE) {
-		dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
-		ret = 0;
-	} else {
-		if (!ret)
-			ret = -ETIMEDOUT;
+	if (dev->wd_state != MEI_WD_IDLE) {
+		/* timeout */
+		ret = -ETIME;
 		dev_warn(&dev->pdev->dev,
 			"wd: stop failed to complete ret=%d.\n", ret);
+		goto err;
 	}
-
-out:
+	dev_dbg(&dev->pdev->dev, "wd: stop completed after %u msec\n",
+			MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret));
+	return 0;
+err:
 	return ret;
 }
 
@@ -260,8 +276,8 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
  */
 static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 {
-	int ret = 0;
 	struct mei_device *dev;
+	int ret;
 
 	dev = watchdog_get_drvdata(wd_dev);
 	if (!dev)
@@ -277,25 +293,18 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 
 	dev->wd_state = MEI_WD_RUNNING;
 
+	ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
+	if (ret < 0)
+		goto end;
 	/* Check if we can send the ping to HW*/
-	if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
+	if (ret && mei_hbuf_acquire(dev)) {
 
-		dev->hbuf_is_ready = false;
 		dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
 
-		if (mei_wd_send(dev)) {
-			dev_err(&dev->pdev->dev, "wd: send failed.\n");
-			ret = -EIO;
+		ret = mei_wd_send(dev);
+		if (ret)
 			goto end;
-		}
-
-		if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) {
-			dev_err(&dev->pdev->dev,
-				"wd: mei_cl_flow_ctrl_reduce() failed.\n");
-			ret = -EIO;
-			goto end;
-		}
-
+		dev->wd_pending = false;
 	} else {
 		dev->wd_pending = true;
 	}
@@ -363,17 +372,25 @@ static struct watchdog_device amt_wd_dev = {
 };
 
 
-void mei_watchdog_register(struct mei_device *dev)
+int mei_watchdog_register(struct mei_device *dev)
 {
-	if (watchdog_register_device(&amt_wd_dev)) {
-		dev_err(&dev->pdev->dev,
-			"wd: unable to register watchdog device.\n");
-		return;
+
+	int ret;
+
+	/* unlock to perserve correct locking order */
+	mutex_unlock(&dev->device_lock);
+	ret = watchdog_register_device(&amt_wd_dev);
+	mutex_lock(&dev->device_lock);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "wd: unable to register watchdog device = %d.\n",
+			ret);
+		return ret;
 	}
 
 	dev_dbg(&dev->pdev->dev,
 		"wd: successfully register watchdog interface.\n");
 	watchdog_set_drvdata(&amt_wd_dev, dev);
+	return 0;
 }
 
 void mei_watchdog_unregister(struct mei_device *dev)
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index e42b331edbc6..462a5b1d8651 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -4,7 +4,6 @@ config INTEL_MIC_HOST
 	tristate "Intel MIC Host Driver"
 	depends on 64BIT && PCI && X86
 	select VHOST_RING
-	default N
 	help
 	  This enables Host Driver support for the Intel Many Integrated
 	  Core (MIC) family of PCIe form factor coprocessor devices that
@@ -25,7 +24,6 @@ config INTEL_MIC_CARD
 	tristate "Intel MIC Card Driver"
 	depends on 64BIT && X86
 	select VIRTIO
-	default N
 	help
 	  This enables card driver support for the Intel Many Integrated
 	  Core (MIC) device family. The card driver communicates shutdown/
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
index 347b9b3b7916..306f502be95e 100644
--- a/drivers/misc/mic/card/mic_device.h
+++ b/drivers/misc/mic/card/mic_device.h
@@ -29,6 +29,7 @@
 
 #include <linux/workqueue.h>
 #include <linux/io.h>
+#include <linux/irqreturn.h>
 
 /**
  * struct mic_intr_info - Contains h/w specific interrupt sources info
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 1a6edce2ecde..0398c696d257 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -24,6 +24,7 @@
 #include <linux/cdev.h>
 #include <linux/idr.h>
 #include <linux/notifier.h>
+#include <linux/irqreturn.h>
 
 #include "mic_intr.h"
 
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
index f9c29bc918bc..dbc5afde1392 100644
--- a/drivers/misc/mic/host/mic_intr.c
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -194,7 +194,7 @@ static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
 	for (i = 0; i < MIC_MIN_MSIX; i++)
 		mdev->irq_info.msix_entries[i].entry = i;
 
-	rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
+	rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
 		MIC_MIN_MSIX);
 	if (rc) {
 		dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c
index 2bef3f76032a..a3700a56b8ff 100644
--- a/drivers/misc/sgi-gru/grukdump.c
+++ b/drivers/misc/sgi-gru/grukdump.c
@@ -178,10 +178,10 @@ static int gru_dump_context(struct gru_state *gru, int ctxnum,
 	hdr.cbrcnt = cbrcnt;
 	hdr.dsrcnt = dsrcnt;
 	hdr.cch_locked = cch_locked;
-	if (!ret && copy_to_user((void __user *)uhdr, &hdr, sizeof(hdr)))
-		ret = -EFAULT;
+	if (copy_to_user(uhdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
 
-	return ret ? ret : bytes;
+	return bytes;
 }
 
 int gru_dump_chiplet_request(unsigned long arg)
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index b9e2000969f0..95c894482fdd 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -240,7 +240,7 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
 
 	nid = cpu_to_node(cpu);
 	page = alloc_pages_exact_node(nid,
-				      GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+				      GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
 				      pg_order);
 	if (page == NULL) {
 		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index afe66571ce0b..21181fa243df 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -24,6 +24,9 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -36,14 +39,35 @@ struct sram_dev {
 	struct clk *clk;
 };
 
+struct sram_reserve {
+	struct list_head list;
+	u32 start;
+	u32 size;
+};
+
+static int sram_reserve_cmp(void *priv, struct list_head *a,
+					struct list_head *b)
+{
+	struct sram_reserve *ra = list_entry(a, struct sram_reserve, list);
+	struct sram_reserve *rb = list_entry(b, struct sram_reserve, list);
+
+	return ra->start - rb->start;
+}
+
 static int sram_probe(struct platform_device *pdev)
 {
 	void __iomem *virt_base;
 	struct sram_dev *sram;
 	struct resource *res;
-	unsigned long size;
+	struct device_node *np = pdev->dev.of_node, *child;
+	unsigned long size, cur_start, cur_size;
+	struct sram_reserve *rblocks, *block;
+	struct list_head reserve_list;
+	unsigned int nblocks;
 	int ret;
 
+	INIT_LIST_HEAD(&reserve_list);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	virt_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(virt_base))
@@ -65,19 +89,106 @@ static int sram_probe(struct platform_device *pdev)
 	if (!sram->pool)
 		return -ENOMEM;
 
-	ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base,
-				res->start, size, -1);
-	if (ret < 0) {
-		if (sram->clk)
-			clk_disable_unprepare(sram->clk);
-		return ret;
+	/*
+	 * We need an additional block to mark the end of the memory region
+	 * after the reserved blocks from the dt are processed.
+	 */
+	nblocks = (np) ? of_get_available_child_count(np) + 1 : 1;
+	rblocks = kmalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
+	if (!rblocks) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	block = &rblocks[0];
+	for_each_available_child_of_node(np, child) {
+		struct resource child_res;
+
+		ret = of_address_to_resource(child, 0, &child_res);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"could not get address for node %s\n",
+				child->full_name);
+			goto err_chunks;
+		}
+
+		if (child_res.start < res->start || child_res.end > res->end) {
+			dev_err(&pdev->dev,
+				"reserved block %s outside the sram area\n",
+				child->full_name);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		block->start = child_res.start - res->start;
+		block->size = resource_size(&child_res);
+		list_add_tail(&block->list, &reserve_list);
+
+		dev_dbg(&pdev->dev, "found reserved block 0x%x-0x%x\n",
+			block->start,
+			block->start + block->size);
+
+		block++;
+	}
+
+	/* the last chunk marks the end of the region */
+	rblocks[nblocks - 1].start = size;
+	rblocks[nblocks - 1].size = 0;
+	list_add_tail(&rblocks[nblocks - 1].list, &reserve_list);
+
+	list_sort(NULL, &reserve_list, sram_reserve_cmp);
+
+	cur_start = 0;
+
+	list_for_each_entry(block, &reserve_list, list) {
+		/* can only happen if sections overlap */
+		if (block->start < cur_start) {
+			dev_err(&pdev->dev,
+				"block at 0x%x starts after current offset 0x%lx\n",
+				block->start, cur_start);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		/* current start is in a reserved block, so continue after it */
+		if (block->start == cur_start) {
+			cur_start = block->start + block->size;
+			continue;
+		}
+
+		/*
+		 * allocate the space between the current starting
+		 * address and the following reserved block, or the
+		 * end of the region.
+		 */
+		cur_size = block->start - cur_start;
+
+		dev_dbg(&pdev->dev, "adding chunk 0x%lx-0x%lx\n",
+			cur_start, cur_start + cur_size);
+		ret = gen_pool_add_virt(sram->pool,
+				(unsigned long)virt_base + cur_start,
+				res->start + cur_start, cur_size, -1);
+		if (ret < 0)
+			goto err_chunks;
+
+		/* next allocation after this reserved block */
+		cur_start = block->start + block->size;
 	}
 
+	kfree(rblocks);
+
 	platform_set_drvdata(pdev, sram);
 
 	dev_dbg(&pdev->dev, "SRAM pool: %ld KiB @ 0x%p\n", size / 1024, virt_base);
 
 	return 0;
+
+err_chunks:
+	kfree(rblocks);
+err_alloc:
+	if (sram->clk)
+		clk_disable_unprepare(sram->clk);
+	return ret;
 }
 
 static int sram_remove(struct platform_device *pdev)
@@ -87,8 +198,6 @@ static int sram_remove(struct platform_device *pdev)
 	if (gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
 		dev_dbg(&pdev->dev, "removed while SRAM allocated\n");
 
-	gen_pool_destroy(sram->pool);
-
 	if (sram->clk)
 		clk_disable_unprepare(sram->clk);
 
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 3aed525e55b4..e7fbc08a0627 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -22,7 +22,6 @@
 #define pr_fmt(fmt)	"(stc): " fmt
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/tty.h>
 
 #include <linux/seq_file.h>
@@ -343,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/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index 83da711ce9f1..cb0289b44a17 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/spi/spi.h>
 #include <linux/of.h>
 
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 5bc10fa193de..b00335652e52 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
index d35cda06b5e8..e0d5017785e5 100644
--- a/drivers/misc/vmw_vmci/vmci_guest.c
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -383,11 +383,12 @@ static int vmci_enable_msix(struct pci_dev *pdev,
 		vmci_dev->msix_entries[i].vector = i;
 	}
 
-	result = pci_enable_msix(pdev, vmci_dev->msix_entries, VMCI_MAX_INTRS);
+	result = pci_enable_msix_exact(pdev,
+				       vmci_dev->msix_entries, VMCI_MAX_INTRS);
 	if (result == 0)
 		vmci_dev->exclusive_vectors = true;
-	else if (result > 0)
-		result = pci_enable_msix(pdev, vmci_dev->msix_entries, 1);
+	else if (result == -ENOSPC)
+		result = pci_enable_msix_exact(pdev, vmci_dev->msix_entries, 1);
 
 	return result;
 }
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7b5424f398ac..452782bffebc 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -415,8 +415,7 @@ static int ioctl_do_sanitize(struct mmc_card *card)
 {
 	int err;
 
-	if (!(mmc_can_sanitize(card) &&
-	      (card->host->caps2 & MMC_CAP2_SANITIZE))) {
+	if (!mmc_can_sanitize(card)) {
 			pr_warn("%s: %s - SANITIZE is not supported\n",
 				mmc_hostname(card->host), __func__);
 			err = -EOPNOTSUPP;
@@ -722,19 +721,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 	return result;
 }
 
-static int send_stop(struct mmc_card *card, u32 *status)
-{
-	struct mmc_command cmd = {0};
-	int err;
-
-	cmd.opcode = MMC_STOP_TRANSMISSION;
-	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-	err = mmc_wait_for_cmd(card->host, &cmd, 5);
-	if (err == 0)
-		*status = cmd.resp[0];
-	return err;
-}
-
 static int get_card_status(struct mmc_card *card, u32 *status, int retries)
 {
 	struct mmc_command cmd = {0};
@@ -750,6 +736,99 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
 	return err;
 }
 
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+		bool hw_busy_detect, struct request *req, int *gen_err)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int err = 0;
+	u32 status;
+
+	do {
+		err = get_card_status(card, &status, 5);
+		if (err) {
+			pr_err("%s: error %d requesting status\n",
+			       req->rq_disk->disk_name, err);
+			return err;
+		}
+
+		if (status & R1_ERROR) {
+			pr_err("%s: %s: error sending status cmd, status %#x\n",
+				req->rq_disk->disk_name, __func__, status);
+			*gen_err = 1;
+		}
+
+		/* We may rely on the host hw to handle busy detection.*/
+		if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
+			hw_busy_detect)
+			break;
+
+		/*
+		 * Timeout if the device never becomes ready for data and never
+		 * leaves the program state.
+		 */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s %s\n",
+				mmc_hostname(card->host),
+				req->rq_disk->disk_name, __func__);
+			return -ETIMEDOUT;
+		}
+
+		/*
+		 * Some cards mishandle the status bits,
+		 * so make sure to check both the busy
+		 * indication and the card state.
+		 */
+	} while (!(status & R1_READY_FOR_DATA) ||
+		 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+
+	return err;
+}
+
+static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
+		struct request *req, int *gen_err, u32 *stop_status)
+{
+	struct mmc_host *host = card->host;
+	struct mmc_command cmd = {0};
+	int err;
+	bool use_r1b_resp = rq_data_dir(req) == WRITE;
+
+	/*
+	 * Normally we use R1B responses for WRITE, but in cases where the host
+	 * has specified a max_busy_timeout we need to validate it. A failure
+	 * means we need to prevent the host from doing hw busy detection, which
+	 * is done by converting to a R1 response instead.
+	 */
+	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
+		use_r1b_resp = false;
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	if (use_r1b_resp) {
+		cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+		cmd.busy_timeout = timeout_ms;
+	} else {
+		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, 5);
+	if (err)
+		return err;
+
+	*stop_status = cmd.resp[0];
+
+	/* No need to check card status in case of READ. */
+	if (rq_data_dir(req) == READ)
+		return 0;
+
+	if (!mmc_host_is_spi(host) &&
+		(*stop_status & R1_ERROR)) {
+		pr_err("%s: %s: general error sending stop command, resp %#x\n",
+			req->rq_disk->disk_name, __func__, *stop_status);
+		*gen_err = 1;
+	}
+
+	return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
+}
+
 #define ERR_NOMEDIUM	3
 #define ERR_RETRY	2
 #define ERR_ABORT	1
@@ -866,26 +945,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
 	 */
 	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
 	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
-		err = send_stop(card, &stop_status);
-		if (err)
+		err = send_stop(card,
+			DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
+			req, gen_err, &stop_status);
+		if (err) {
 			pr_err("%s: error %d sending stop command\n",
 			       req->rq_disk->disk_name, err);
-
-		/*
-		 * If the stop cmd also timed out, the card is probably
-		 * not present, so abort.  Other errors are bad news too.
-		 */
-		if (err)
+			/*
+			 * If the stop cmd also timed out, the card is probably
+			 * not present, so abort. Other errors are bad news too.
+			 */
 			return ERR_ABORT;
+		}
+
 		if (stop_status & R1_CARD_ECC_FAILED)
 			*ecc_err = 1;
-		if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
-			if (stop_status & R1_ERROR) {
-				pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
-				       req->rq_disk->disk_name, __func__,
-				       stop_status);
-				*gen_err = 1;
-			}
 	}
 
 	/* Check for set block count errors */
@@ -1157,8 +1231,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
 	 * program mode, which we have to wait for it to complete.
 	 */
 	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
-		u32 status;
-		unsigned long timeout;
+		int err;
 
 		/* Check stop command response */
 		if (brq->stop.resp[0] & R1_ERROR) {
@@ -1168,39 +1241,10 @@ static int mmc_blk_err_check(struct mmc_card *card,
 			gen_err = 1;
 		}
 
-		timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
-		do {
-			int err = get_card_status(card, &status, 5);
-			if (err) {
-				pr_err("%s: error %d requesting status\n",
-				       req->rq_disk->disk_name, err);
-				return MMC_BLK_CMD_ERR;
-			}
-
-			if (status & R1_ERROR) {
-				pr_err("%s: %s: general error sending status command, card status %#x\n",
-				       req->rq_disk->disk_name, __func__,
-				       status);
-				gen_err = 1;
-			}
-
-			/* Timeout if the device never becomes ready for data
-			 * and never leaves the program state.
-			 */
-			if (time_after(jiffies, timeout)) {
-				pr_err("%s: Card stuck in programming state!"\
-					" %s %s\n", mmc_hostname(card->host),
-					req->rq_disk->disk_name, __func__);
-
-				return MMC_BLK_CMD_ERR;
-			}
-			/*
-			 * Some cards mishandle the status bits,
-			 * so make sure to check both the busy
-			 * indication and the card state.
-			 */
-		} while (!(status & R1_READY_FOR_DATA) ||
-			 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
+					&gen_err);
+		if (err)
+			return MMC_BLK_CMD_ERR;
 	}
 
 	/* if general error occurs, retry the write operation. */
@@ -1335,7 +1379,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 	brq->data.blksz = 512;
 	brq->stop.opcode = MMC_STOP_TRANSMISSION;
 	brq->stop.arg = 0;
-	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
 	brq->data.blocks = blk_rq_sectors(req);
 
 	/*
@@ -1378,9 +1421,15 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 	if (rq_data_dir(req) == READ) {
 		brq->cmd.opcode = readcmd;
 		brq->data.flags |= MMC_DATA_READ;
+		if (brq->mrq.stop)
+			brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
+					MMC_CMD_AC;
 	} else {
 		brq->cmd.opcode = writecmd;
 		brq->data.flags |= MMC_DATA_WRITE;
+		if (brq->mrq.stop)
+			brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
+					MMC_CMD_AC;
 	}
 
 	if (do_rel_wr)
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index 269d072ef55e..9ebee72d9c3f 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -2,21 +2,6 @@
 # MMC core configuration
 #
 
-config MMC_UNSAFE_RESUME
-	bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
-	help
-	  If you say Y here, the MMC layer will assume that all cards
-	  stayed in their respective slots during the suspend. The
-	  normal behaviour is to remove them at suspend and
-	  redetecting them at resume. Breaking this assumption will
-	  in most cases result in data corruption.
-
-	  This option is usually just for embedded systems which use
-	  a MMC/SD card for rootfs. Most people should say N here.
-
-	  This option sets a default which can be overridden by the
-	  module parameter "removable=0" or "removable=1".
-
 config MMC_CLKGATE
 	bool "MMC host clock gating"
 	help
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 64145a32b917..824644875d41 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -185,24 +185,16 @@ static int mmc_runtime_suspend(struct device *dev)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
 	struct mmc_host *host = card->host;
-	int ret = 0;
 
-	if (host->bus_ops->runtime_suspend)
-		ret = host->bus_ops->runtime_suspend(host);
-
-	return ret;
+	return host->bus_ops->runtime_suspend(host);
 }
 
 static int mmc_runtime_resume(struct device *dev)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
 	struct mmc_host *host = card->host;
-	int ret = 0;
 
-	if (host->bus_ops->runtime_resume)
-		ret = host->bus_ops->runtime_resume(host);
-
-	return ret;
+	return host->bus_ops->runtime_resume(host);
 }
 
 static int mmc_runtime_idle(struct device *dev)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 098374b1ab2b..dc7a5fb81a5c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -65,23 +65,6 @@ bool use_spi_crc = 1;
 module_param(use_spi_crc, bool, 0);
 
 /*
- * We normally treat cards as removed during suspend if they are not
- * known to be on a non-removable bus, to avoid the risk of writing
- * back data to a different card after resume.  Allow this to be
- * overridden if necessary.
- */
-#ifdef CONFIG_MMC_UNSAFE_RESUME
-bool mmc_assume_removable;
-#else
-bool mmc_assume_removable = 1;
-#endif
-EXPORT_SYMBOL(mmc_assume_removable);
-module_param_named(removable, mmc_assume_removable, bool, 0644);
-MODULE_PARM_DESC(
-	removable,
-	"MMC/SD cards are removable and may be removed during suspend");
-
-/*
  * Internal function. Schedule delayed work in the MMC work queue.
  */
 static int mmc_schedule_delayed_work(struct delayed_work *work,
@@ -302,7 +285,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
 	}
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true);
+			EXT_CSD_BKOPS_START, 1, timeout,
+			use_busy_signal, true, false);
 	if (err) {
 		pr_warn("%s: Error %d starting bkops\n",
 			mmc_hostname(card->host), err);
@@ -1950,7 +1934,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 	cmd.opcode = MMC_ERASE;
 	cmd.arg = arg;
 	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-	cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
+	cmd.busy_timeout = mmc_erase_timeout(card, arg, qty);
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
 		pr_err("mmc_erase: erase error %d, status %#x\n",
@@ -2137,7 +2121,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
 		y = 0;
 		for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
 			timeout = mmc_erase_timeout(card, arg, qty + x);
-			if (timeout > host->max_discard_to)
+			if (timeout > host->max_busy_timeout)
 				break;
 			if (timeout < last_timeout)
 				break;
@@ -2169,7 +2153,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
 	struct mmc_host *host = card->host;
 	unsigned int max_discard, max_trim;
 
-	if (!host->max_discard_to)
+	if (!host->max_busy_timeout)
 		return UINT_MAX;
 
 	/*
@@ -2189,7 +2173,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
 		max_discard = 0;
 	}
 	pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
-		 mmc_hostname(host), max_discard, host->max_discard_to);
+		 mmc_hostname(host), max_discard, host->max_busy_timeout);
 	return max_discard;
 }
 EXPORT_SYMBOL(mmc_calc_max_discard);
@@ -2248,9 +2232,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 {
 	struct mmc_card *card = host->card;
 
-	if (!host->bus_ops->power_restore)
-		return -EOPNOTSUPP;
-
 	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
 		return -EOPNOTSUPP;
 
@@ -2352,7 +2333,7 @@ int _mmc_detect_card_removed(struct mmc_host *host)
 {
 	int ret;
 
-	if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
+	if (host->caps & MMC_CAP_NONREMOVABLE)
 		return 0;
 
 	if (!host->card || mmc_card_removed(host->card))
@@ -2435,7 +2416,7 @@ void mmc_rescan(struct work_struct *work)
 	 * if there is a _removable_ card registered, check whether it is
 	 * still present
 	 */
-	if (host->bus_ops && host->bus_ops->detect && !host->bus_dead
+	if (host->bus_ops && !host->bus_dead
 	    && !(host->caps & MMC_CAP_NONREMOVABLE))
 		host->bus_ops->detect(host);
 
@@ -2537,7 +2518,7 @@ int mmc_power_save_host(struct mmc_host *host)
 
 	mmc_bus_get(host);
 
-	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
+	if (!host->bus_ops || host->bus_dead) {
 		mmc_bus_put(host);
 		return -EINVAL;
 	}
@@ -2563,7 +2544,7 @@ int mmc_power_restore_host(struct mmc_host *host)
 
 	mmc_bus_get(host);
 
-	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
+	if (!host->bus_ops || host->bus_dead) {
 		mmc_bus_put(host);
 		return -EINVAL;
 	}
@@ -2582,12 +2563,8 @@ EXPORT_SYMBOL(mmc_power_restore_host);
  */
 int mmc_flush_cache(struct mmc_card *card)
 {
-	struct mmc_host *host = card->host;
 	int err = 0;
 
-	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
-		return err;
-
 	if (mmc_card_mmc(card) &&
 			(card->ext_csd.cache_size > 0) &&
 			(card->ext_csd.cache_ctrl & 1)) {
@@ -2602,44 +2579,6 @@ int mmc_flush_cache(struct mmc_card *card)
 }
 EXPORT_SYMBOL(mmc_flush_cache);
 
-/*
- * Turn the cache ON/OFF.
- * Turning the cache OFF shall trigger flushing of the data
- * to the non-volatile storage.
- * This function should be called with host claimed
- */
-int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
-{
-	struct mmc_card *card = host->card;
-	unsigned int timeout;
-	int err = 0;
-
-	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
-			mmc_card_is_removable(host))
-		return err;
-
-	if (card && mmc_card_mmc(card) &&
-			(card->ext_csd.cache_size > 0)) {
-		enable = !!enable;
-
-		if (card->ext_csd.cache_ctrl ^ enable) {
-			timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
-			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-					EXT_CSD_CACHE_CTRL, enable, timeout);
-			if (err)
-				pr_err("%s: cache %s error %d\n",
-						mmc_hostname(card->host),
-						enable ? "on" : "off",
-						err);
-			else
-				card->ext_csd.cache_ctrl = enable;
-		}
-	}
-
-	return err;
-}
-EXPORT_SYMBOL(mmc_cache_ctrl);
-
 #ifdef CONFIG_PM
 
 /* Do the card removal on suspend if card is assumed removeable
@@ -2668,7 +2607,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 		/* Validate prerequisites for suspend */
 		if (host->bus_ops->pre_suspend)
 			err = host->bus_ops->pre_suspend(host);
-		if (!err && host->bus_ops->suspend)
+		if (!err)
 			break;
 
 		/* Calling bus_ops->remove() with a claimed host can deadlock */
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 49bc403e31f0..453573d5ab08 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -419,6 +419,16 @@ int mmc_of_parse(struct mmc_host *host)
 		host->caps |= MMC_CAP_SD_HIGHSPEED;
 	if (of_find_property(np, "cap-mmc-highspeed", &len))
 		host->caps |= MMC_CAP_MMC_HIGHSPEED;
+	if (of_find_property(np, "sd-uhs-sdr12", &len))
+		host->caps |= MMC_CAP_UHS_SDR12;
+	if (of_find_property(np, "sd-uhs-sdr25", &len))
+		host->caps |= MMC_CAP_UHS_SDR25;
+	if (of_find_property(np, "sd-uhs-sdr50", &len))
+		host->caps |= MMC_CAP_UHS_SDR50;
+	if (of_find_property(np, "sd-uhs-sdr104", &len))
+		host->caps |= MMC_CAP_UHS_SDR104;
+	if (of_find_property(np, "sd-uhs-ddr50", &len))
+		host->caps |= MMC_CAP_UHS_DDR50;
 	if (of_find_property(np, "cap-power-off-card", &len))
 		host->caps |= MMC_CAP_POWER_OFF_CARD;
 	if (of_find_property(np, "cap-sdio-irq", &len))
@@ -429,6 +439,14 @@ int mmc_of_parse(struct mmc_host *host)
 		host->pm_caps |= MMC_PM_KEEP_POWER;
 	if (of_find_property(np, "enable-sdio-wakeup", &len))
 		host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+	if (of_find_property(np, "mmc-ddr-1_8v", &len))
+		host->caps |= MMC_CAP_1_8V_DDR;
+	if (of_find_property(np, "mmc-ddr-1_2v", &len))
+		host->caps |= MMC_CAP_1_2V_DDR;
+	if (of_find_property(np, "mmc-hs200-1_8v", &len))
+		host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+	if (of_find_property(np, "mmc-hs200-1_2v", &len))
+		host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
 
 	return 0;
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 98e9eb0f6643..1ab5f3a0af5b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -856,8 +856,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	/* switch to HS200 mode if bus width set successfully */
 	if (!err)
-		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				 EXT_CSD_HS_TIMING, 2, 0);
+		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_HS_TIMING, 2,
+				card->ext_csd.generic_cmd6_time,
+				true, true, true);
 err:
 	return err;
 }
@@ -1074,9 +1076,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		    host->caps2 & MMC_CAP2_HS200)
 			err = mmc_select_hs200(card);
 		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
-			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-					 EXT_CSD_HS_TIMING, 1,
-					 card->ext_csd.generic_cmd6_time);
+			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_HS_TIMING, 1,
+					card->ext_csd.generic_cmd6_time,
+					true, true, true);
 
 		if (err && err != -EBADMSG)
 			goto free_card;
@@ -1287,8 +1290,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 * If cache size is higher than 0, this indicates
 	 * the existence of cache and it can be turned on.
 	 */
-	if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
-			card->ext_csd.cache_size > 0) {
+	if (card->ext_csd.cache_size > 0) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				EXT_CSD_CACHE_CTRL, 1,
 				card->ext_csd.generic_cmd6_time);
@@ -1356,11 +1358,9 @@ static int mmc_sleep(struct mmc_host *host)
 {
 	struct mmc_command cmd = {0};
 	struct mmc_card *card = host->card;
+	unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
 	int err;
 
-	if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
-		return 0;
-
 	err = mmc_deselect_cards(host);
 	if (err)
 		return err;
@@ -1369,7 +1369,19 @@ static int mmc_sleep(struct mmc_host *host)
 	cmd.arg = card->rca << 16;
 	cmd.arg |= 1 << 15;
 
-	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+	/*
+	 * If the max_busy_timeout of the host is specified, validate it against
+	 * the sleep cmd timeout. A failure means we need to prevent the host
+	 * from doing hw busy detection, which is done by converting to a R1
+	 * response instead of a R1B.
+	 */
+	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+		cmd.busy_timeout = timeout_ms;
+	}
+
 	err = mmc_wait_for_cmd(host, &cmd, 0);
 	if (err)
 		return err;
@@ -1380,8 +1392,8 @@ static int mmc_sleep(struct mmc_host *host)
 	 * SEND_STATUS command to poll the status because that command (and most
 	 * others) is invalid while the card sleeps.
 	 */
-	if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
-		mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
+	if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+		mmc_delay(timeout_ms);
 
 	return err;
 }
@@ -1404,7 +1416,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			EXT_CSD_POWER_OFF_NOTIFICATION,
-			notify_type, timeout, true, false);
+			notify_type, timeout, true, false, false);
 	if (err)
 		pr_err("%s: Power Off Notification timed out, %u\n",
 		       mmc_hostname(card->host), timeout);
@@ -1484,7 +1496,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 			goto out;
 	}
 
-	err = mmc_cache_ctrl(host, 0);
+	err = mmc_flush_cache(host->card);
 	if (err)
 		goto out;
 
@@ -1636,16 +1648,6 @@ static int mmc_power_restore(struct mmc_host *host)
 static const struct mmc_bus_ops mmc_ops = {
 	.remove = mmc_remove,
 	.detect = mmc_detect,
-	.suspend = NULL,
-	.resume = NULL,
-	.power_restore = mmc_power_restore,
-	.alive = mmc_alive,
-	.shutdown = mmc_shutdown,
-};
-
-static const struct mmc_bus_ops mmc_ops_unsafe = {
-	.remove = mmc_remove,
-	.detect = mmc_detect,
 	.suspend = mmc_suspend,
 	.resume = mmc_resume,
 	.runtime_suspend = mmc_runtime_suspend,
@@ -1655,17 +1657,6 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
 	.shutdown = mmc_shutdown,
 };
 
-static void mmc_attach_bus_ops(struct mmc_host *host)
-{
-	const struct mmc_bus_ops *bus_ops;
-
-	if (!mmc_card_is_removable(host))
-		bus_ops = &mmc_ops_unsafe;
-	else
-		bus_ops = &mmc_ops;
-	mmc_attach_bus(host, bus_ops);
-}
-
 /*
  * Starting point for MMC card init.
  */
@@ -1685,7 +1676,7 @@ int mmc_attach_mmc(struct mmc_host *host)
 	if (err)
 		return err;
 
-	mmc_attach_bus_ops(host);
+	mmc_attach_bus(host, &mmc_ops);
 	if (host->ocr_avail_mmc)
 		host->ocr_avail = host->ocr_avail_mmc;
 
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index e5b5eeb548d1..f51b5ba3bbea 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -405,20 +405,30 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
  *                   timeout of zero implies maximum possible timeout
  *	@use_busy_signal: use the busy signal as response type
  *	@send_status: send status cmd to poll for busy
+ *	@ignore_crc: ignore CRC errors when sending status cmd to poll for busy
  *
  *	Modifies the EXT_CSD register for selected card.
  */
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-		unsigned int timeout_ms, bool use_busy_signal, bool send_status)
+		unsigned int timeout_ms, bool use_busy_signal, bool send_status,
+		bool ignore_crc)
 {
+	struct mmc_host *host = card->host;
 	int err;
 	struct mmc_command cmd = {0};
 	unsigned long timeout;
 	u32 status = 0;
-	bool ignore_crc = false;
+	bool use_r1b_resp = use_busy_signal;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
+	/*
+	 * If the cmd timeout and the max_busy_timeout of the host are both
+	 * specified, let's validate them. A failure means we need to prevent
+	 * the host from doing hw busy detection, which is done by converting
+	 * to a R1 response instead of a R1B.
+	 */
+	if (timeout_ms && host->max_busy_timeout &&
+		(timeout_ms > host->max_busy_timeout))
+		use_r1b_resp = false;
 
 	cmd.opcode = MMC_SWITCH;
 	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
@@ -426,17 +436,21 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		  (value << 8) |
 		  set;
 	cmd.flags = MMC_CMD_AC;
-	if (use_busy_signal)
+	if (use_r1b_resp) {
 		cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
-	else
+		/*
+		 * A busy_timeout of zero means the host can decide to use
+		 * whatever value it finds suitable.
+		 */
+		cmd.busy_timeout = timeout_ms;
+	} else {
 		cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+	}
 
-
-	cmd.cmd_timeout_ms = timeout_ms;
 	if (index == EXT_CSD_SANITIZE_START)
 		cmd.sanitize_busy = true;
 
-	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
 	if (err)
 		return err;
 
@@ -445,24 +459,27 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		return 0;
 
 	/*
-	 * Must check status to be sure of no errors
-	 * If CMD13 is to check the busy completion of the timing change,
-	 * disable the check of CRC error.
+	 * CRC errors shall only be ignored in cases were CMD13 is used to poll
+	 * to detect busy completion.
 	 */
-	if (index == EXT_CSD_HS_TIMING &&
-	    !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
-		ignore_crc = true;
+	if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
+		ignore_crc = false;
+
+	/* We have an unspecified cmd timeout, use the fallback value. */
+	if (!timeout_ms)
+		timeout_ms = MMC_OPS_TIMEOUT_MS;
 
-	timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
+	/* Must check status to be sure of no errors. */
+	timeout = jiffies + msecs_to_jiffies(timeout_ms);
 	do {
 		if (send_status) {
 			err = __mmc_send_status(card, &status, ignore_crc);
 			if (err)
 				return err;
 		}
-		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
 			break;
-		if (mmc_host_is_spi(card->host))
+		if (mmc_host_is_spi(host))
 			break;
 
 		/*
@@ -478,18 +495,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		/* Timeout if the device never leaves the program state. */
 		if (time_after(jiffies, timeout)) {
 			pr_err("%s: Card stuck in programming state! %s\n",
-				mmc_hostname(card->host), __func__);
+				mmc_hostname(host), __func__);
 			return -ETIMEDOUT;
 		}
 	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
-	if (mmc_host_is_spi(card->host)) {
+	if (mmc_host_is_spi(host)) {
 		if (status & R1_SPI_ILLEGAL_COMMAND)
 			return -EBADMSG;
 	} else {
 		if (status & 0xFDFFA000)
-			pr_warning("%s: unexpected status %#x after "
-			       "switch", mmc_hostname(card->host), status);
+			pr_warn("%s: unexpected status %#x after switch\n",
+				mmc_hostname(host), status);
 		if (status & R1_SWITCH_ERROR)
 			return -EBADMSG;
 	}
@@ -501,7 +518,8 @@ EXPORT_SYMBOL_GPL(__mmc_switch);
 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		unsigned int timeout_ms)
 {
-	return __mmc_switch(card, set, index, value, timeout_ms, true, true);
+	return __mmc_switch(card, set, index, value, timeout_ms, true, true,
+				false);
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 692fdb177294..2dd359d2242f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1209,16 +1209,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 static const struct mmc_bus_ops mmc_sd_ops = {
 	.remove = mmc_sd_remove,
 	.detect = mmc_sd_detect,
-	.suspend = NULL,
-	.resume = NULL,
-	.power_restore = mmc_sd_power_restore,
-	.alive = mmc_sd_alive,
-	.shutdown = mmc_sd_suspend,
-};
-
-static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
-	.remove = mmc_sd_remove,
-	.detect = mmc_sd_detect,
 	.runtime_suspend = mmc_sd_runtime_suspend,
 	.runtime_resume = mmc_sd_runtime_resume,
 	.suspend = mmc_sd_suspend,
@@ -1228,17 +1218,6 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
 	.shutdown = mmc_sd_suspend,
 };
 
-static void mmc_sd_attach_bus_ops(struct mmc_host *host)
-{
-	const struct mmc_bus_ops *bus_ops;
-
-	if (!mmc_card_is_removable(host))
-		bus_ops = &mmc_sd_ops_unsafe;
-	else
-		bus_ops = &mmc_sd_ops;
-	mmc_attach_bus(host, bus_ops);
-}
-
 /*
  * Starting point for SD card init.
  */
@@ -1254,7 +1233,7 @@ int mmc_attach_sd(struct mmc_host *host)
 	if (err)
 		return err;
 
-	mmc_sd_attach_bus_ops(host);
+	mmc_attach_bus(host, &mmc_sd_ops);
 	if (host->ocr_avail_sd)
 		host->ocr_avail = host->ocr_avail_sd;
 
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1384f67abe21..82cc34df1af7 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -580,14 +580,6 @@ config MMC_DW_EXYNOS
 	  Synopsys DesignWare Memory Card Interface driver. Select this option
 	  for platforms based on Exynos4 and Exynos5 SoC's.
 
-config MMC_DW_SOCFPGA
-	tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
-	depends on MMC_DW && MFD_SYSCON
-	select MMC_DW_PLTFM
-	help
-	  This selects support for Altera SoCFPGA specific extensions to the
-	  Synopsys DesignWare Memory Card Interface driver.
-
 config MMC_DW_K3
 	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
 	depends on MMC_DW
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3483b6b6b880..f162f87a049c 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,7 +43,6 @@ obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
-obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
 obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index d6153740b77f..5d4c5e0fba2f 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -1192,7 +1192,7 @@ static struct davinci_mmc_config
 	struct device_node *np;
 	struct davinci_mmc_config *pdata = pdev->dev.platform_data;
 	const struct of_device_id *match =
-		of_match_device(of_match_ptr(davinci_mmc_dt_ids), &pdev->dev);
+		of_match_device(davinci_mmc_dt_ids, &pdev->dev);
 	u32 data;
 
 	np = pdev->dev.of_node;
@@ -1468,7 +1468,7 @@ static struct platform_driver davinci_mmcsd_driver = {
 		.name	= "davinci_mmc",
 		.owner	= THIS_MODULE,
 		.pm	= davinci_mmcsd_pm_ops,
-		.of_match_table = of_match_ptr(davinci_mmc_dt_ids),
+		.of_match_table = davinci_mmc_dt_ids,
 	},
 	.remove		= __exit_p(davinci_mmcsd_remove),
 	.id_table	= davinci_mmc_devtype,
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index f567c219cff4..650f9cc3f7a6 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -50,6 +50,7 @@ static int dw_mci_k3_probe(struct platform_device *pdev)
 	return dw_mci_pltfm_register(pdev, drv_data);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int dw_mci_k3_suspend(struct device *dev)
 {
 	struct dw_mci *host = dev_get_drvdata(dev);
@@ -75,6 +76,7 @@ static int dw_mci_k3_resume(struct device *dev)
 
 	return dw_mci_resume(host);
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
 
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 5c4965655297..d4a47a9f5584 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -25,13 +25,17 @@
 #include "dw_mmc.h"
 #include "dw_mmc-pltfm.h"
 
-static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
+static void dw_mci_pltfm_prepare_command(struct dw_mci *host, u32 *cmdr)
 {
 	*cmdr |= SDMMC_CMD_USE_HOLD_REG;
 }
 
 static const struct dw_mci_drv_data rockchip_drv_data = {
-	.prepare_command	= dw_mci_rockchip_prepare_command,
+	.prepare_command	= dw_mci_pltfm_prepare_command,
+};
+
+static const struct dw_mci_drv_data socfpga_drv_data = {
+	.prepare_command	= dw_mci_pltfm_prepare_command,
 };
 
 int dw_mci_pltfm_register(struct platform_device *pdev,
@@ -92,6 +96,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
 	{ .compatible = "rockchip,rk2928-dw-mshc",
 		.data = &rockchip_drv_data },
+	{ .compatible = "altr,socfpga-dw-mshc",
+		.data = &socfpga_drv_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
@@ -123,7 +129,7 @@ static struct platform_driver dw_mci_pltfm_driver = {
 	.remove		= dw_mci_pltfm_remove,
 	.driver		= {
 		.name		= "dw_mmc",
-		.of_match_table	= of_match_ptr(dw_mci_pltfm_match),
+		.of_match_table	= dw_mci_pltfm_match,
 		.pm		= &dw_mci_pltfm_pmops,
 	},
 };
diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c
deleted file mode 100644
index 3e8e53ae3302..000000000000
--- a/drivers/mmc/host/dw_mmc-socfpga.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface
- * driver
- *
- *  Copyright (C) 2012, Samsung Electronics Co., Ltd.
- *  Copyright (C) 2013 Altera 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Taken from dw_mmc-exynos.c
- */
-#include <linux/clk.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/dw_mmc.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include "dw_mmc.h"
-#include "dw_mmc-pltfm.h"
-
-#define SYSMGR_SDMMCGRP_CTRL_OFFSET		0x108
-#define DRV_CLK_PHASE_SHIFT_SEL_MASK	0x7
-#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel)          \
-	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
-
-/* SOCFPGA implementation specific driver private data */
-struct dw_mci_socfpga_priv_data {
-	u8	ciu_div; /* card interface unit divisor */
-	u32	hs_timing; /* bitmask for CIU clock phase shift */
-	struct regmap   *sysreg; /* regmap for system manager register */
-};
-
-static int dw_mci_socfpga_priv_init(struct dw_mci *host)
-{
-	return 0;
-}
-
-static int dw_mci_socfpga_setup_clock(struct dw_mci *host)
-{
-	struct dw_mci_socfpga_priv_data *priv = host->priv;
-
-	clk_disable_unprepare(host->ciu_clk);
-	regmap_write(priv->sysreg, SYSMGR_SDMMCGRP_CTRL_OFFSET,
-		priv->hs_timing);
-	clk_prepare_enable(host->ciu_clk);
-
-	host->bus_hz /= (priv->ciu_div + 1);
-	return 0;
-}
-
-static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr)
-{
-	struct dw_mci_socfpga_priv_data *priv = host->priv;
-
-	if (priv->hs_timing & DRV_CLK_PHASE_SHIFT_SEL_MASK)
-		*cmdr |= SDMMC_CMD_USE_HOLD_REG;
-}
-
-static int dw_mci_socfpga_parse_dt(struct dw_mci *host)
-{
-	struct dw_mci_socfpga_priv_data *priv;
-	struct device_node *np = host->dev->of_node;
-	u32 timing[2];
-	u32 div = 0;
-	int ret;
-
-	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(host->dev, "mem alloc failed for private data\n");
-		return -ENOMEM;
-	}
-
-	priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
-	if (IS_ERR(priv->sysreg)) {
-		dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n");
-		return PTR_ERR(priv->sysreg);
-	}
-
-	ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div);
-	if (ret)
-		dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1");
-	priv->ciu_div = div;
-
-	ret = of_property_read_u32_array(np,
-			"altr,dw-mshc-sdr-timing", timing, 2);
-	if (ret)
-		return ret;
-
-	priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]);
-	host->priv = priv;
-	return 0;
-}
-
-static const struct dw_mci_drv_data socfpga_drv_data = {
-	.init			= dw_mci_socfpga_priv_init,
-	.setup_clock		= dw_mci_socfpga_setup_clock,
-	.prepare_command	= dw_mci_socfpga_prepare_command,
-	.parse_dt		= dw_mci_socfpga_parse_dt,
-};
-
-static const struct of_device_id dw_mci_socfpga_match[] = {
-	{ .compatible = "altr,socfpga-dw-mshc",
-			.data = &socfpga_drv_data, },
-	{},
-};
-MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match);
-
-static int dw_mci_socfpga_probe(struct platform_device *pdev)
-{
-	const struct dw_mci_drv_data *drv_data;
-	const struct of_device_id *match;
-
-	match = of_match_node(dw_mci_socfpga_match, pdev->dev.of_node);
-	drv_data = match->data;
-	return dw_mci_pltfm_register(pdev, drv_data);
-}
-
-static struct platform_driver dw_mci_socfpga_pltfm_driver = {
-	.probe		= dw_mci_socfpga_probe,
-	.remove		= __exit_p(dw_mci_pltfm_remove),
-	.driver		= {
-		.name		= "dwmmc_socfpga",
-		.of_match_table	= dw_mci_socfpga_match,
-		.pm		= &dw_mci_pltfm_pmops,
-	},
-};
-
-module_platform_driver(dw_mci_socfpga_pltfm_driver);
-
-MODULE_DESCRIPTION("Altera SOCFPGA Specific DW-MSHC Driver Extension");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:dwmmc-socfpga");
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 55cd110a49c4..0c56faa6730e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1345,7 +1345,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
 
 			if (!err) {
 				if (!data->stop || mrq->sbc) {
-					if (mrq->sbc)
+					if (mrq->sbc && data->stop)
 						data->stop->error = 0;
 					dw_mci_request_end(host, mrq);
 					goto unlock;
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 6bf24ab917e6..68349779c396 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -185,7 +185,7 @@
 
 extern int dw_mci_probe(struct dw_mci *host);
 extern void dw_mci_remove(struct dw_mci *host);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 extern int dw_mci_suspend(struct dw_mci *host);
 extern int dw_mci_resume(struct dw_mci *host);
 #endif
@@ -244,6 +244,7 @@ struct dw_mci_tuning_data {
  * @prepare_command: handle CMD register extensions.
  * @set_ios: handle bus specific extensions.
  * @parse_dt: parse implementation specific device tree properties.
+ * @execute_tuning: implementation specific tuning procedure.
  *
  * Provide controller implementation specific extensions. The usage of this
  * data structure is fully optional and usage of each member in this structure
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b93122636531..771c60ab4a32 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
 {
 	void __iomem *base = host->base;
 	bool sbc = (cmd == host->mrq->sbc);
+	bool busy_resp = host->variant->busy_detect &&
+			(cmd->flags & MMC_RSP_BUSY);
+
+	/* Check if we need to wait for busy completion. */
+	if (host->busy_status && (status & MCI_ST_CARDBUSY))
+		return;
+
+	/* Enable busy completion if needed and supported. */
+	if (!host->busy_status && busy_resp &&
+		!(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+		(readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
+		writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
+			base + MMCIMASK0);
+		host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
+		return;
+	}
+
+	/* At busy completion, mask the IRQ and complete the request. */
+	if (host->busy_status) {
+		writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
+			base + MMCIMASK0);
+		host->busy_status = 0;
+	}
 
 	host->cmd = NULL;
 
@@ -1139,20 +1162,30 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
 			status &= ~MCI_IRQ1MASK;
 		}
 
+		/*
+		 * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
+		 * enabled) since the HW seems to be triggering the IRQ on both
+		 * edges while monitoring DAT0 for busy completion.
+		 */
 		status &= readl(host->base + MMCIMASK0);
 		writel(status, host->base + MMCICLEAR);
 
 		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
 
+		cmd = host->cmd;
+		if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
+			MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
+			mmci_cmd_irq(host, cmd, status);
+
 		data = host->data;
 		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
 			      MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
 			      MCI_DATABLOCKEND) && data)
 			mmci_data_irq(host, data, status);
 
-		cmd = host->cmd;
-		if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
-			mmci_cmd_irq(host, cmd, status);
+		/* Don't poll for busy completion in irq context. */
+		if (host->busy_status)
+			status &= ~MCI_ST_CARDBUSY;
 
 		ret = 1;
 	} while (status);
@@ -1503,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev,
 		goto clk_disable;
 	}
 
-	if (variant->busy_detect) {
-		mmci_ops.card_busy = mmci_card_busy;
-		mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
-	}
-
-	mmc->ops = &mmci_ops;
 	/*
 	 * The ARM and ST versions of the block have slightly different
 	 * clock divider equations which means that the minimum divider
@@ -1542,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev,
 	mmc->caps = plat->capabilities;
 	mmc->caps2 = plat->capabilities2;
 
+	if (variant->busy_detect) {
+		mmci_ops.card_busy = mmci_card_busy;
+		mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+		mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
+		mmc->max_busy_timeout = 0;
+	}
+
+	mmc->ops = &mmci_ops;
+
 	/* We support these PM capabilities. */
 	mmc->pm_caps = MMC_PM_KEEP_POWER;
 
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 168bc72f7a94..58b1b8896bf2 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -38,10 +38,11 @@
 #define MCI_CPSM_INTERRUPT	(1 << 8)
 #define MCI_CPSM_PENDING	(1 << 9)
 #define MCI_CPSM_ENABLE		(1 << 10)
-#define MCI_SDIO_SUSP		(1 << 11)
-#define MCI_ENCMD_COMPL		(1 << 12)
-#define MCI_NIEN		(1 << 13)
-#define MCI_CE_ATACMD		(1 << 14)
+/* Argument flag extenstions in the ST Micro versions */
+#define MCI_ST_SDIO_SUSP	(1 << 11)
+#define MCI_ST_ENCMD_COMPL	(1 << 12)
+#define MCI_ST_NIEN		(1 << 13)
+#define MCI_ST_CE_ATACMD	(1 << 14)
 
 #define MMCIRESPCMD		0x010
 #define MMCIRESPONSE0		0x014
@@ -139,6 +140,7 @@
 /* Extended status bits for the ST Micro variants */
 #define MCI_ST_SDIOITMASK	(1 << 22)
 #define MCI_ST_CEATAENDMASK	(1 << 23)
+#define MCI_ST_BUSYEND		(1 << 24)
 
 #define MMCIMASK1		0x040
 #define MMCIFIFOCNT		0x048
@@ -186,6 +188,7 @@ struct mmci_host {
 	u32			pwr_reg;
 	u32			clk_reg;
 	u32			datactrl_reg;
+	u32			busy_status;
 	bool			vqmmc_enabled;
 	struct mmci_platform_data *plat;
 	struct variant_data	*variant;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 98b6b6ef7e5c..5c2e58b29305 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -26,6 +26,7 @@
 #include <linux/omap-dma.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -130,7 +131,6 @@ struct mmc_omap_host {
 	u32			dma_rx_burst;
 	struct dma_chan		*dma_tx;
 	u32			dma_tx_burst;
-	struct resource		*mem_res;
 	void __iomem		*virt_base;
 	unsigned int		phys_base;
 	int			irq;
@@ -153,7 +153,6 @@ struct mmc_omap_host {
 	u32			total_bytes_left;
 
 	unsigned		features;
-	unsigned		use_dma:1;
 	unsigned		brs_received:1, dma_done:1;
 	unsigned		dma_in_use:1;
 	spinlock_t		dma_lock;
@@ -338,6 +337,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
 	u32 cmdreg;
 	u32 resptype;
 	u32 cmdtype;
+	u16 irq_mask;
 
 	host->cmd = cmd;
 
@@ -390,12 +390,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
 	OMAP_MMC_WRITE(host, CTO, 200);
 	OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
 	OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
-	OMAP_MMC_WRITE(host, IE,
-		       OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
-		       OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
-		       OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
-		       OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
-		       OMAP_MMC_STAT_END_OF_DATA);
+	irq_mask = OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
+		   OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
+		   OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
+		   OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
+		   OMAP_MMC_STAT_END_OF_DATA;
+	if (cmd->opcode == MMC_ERASE)
+		irq_mask &= ~OMAP_MMC_STAT_DATA_TOUT;
+	OMAP_MMC_WRITE(host, IE, irq_mask);
 	OMAP_MMC_WRITE(host, CMD, cmdreg);
 }
 
@@ -945,7 +947,7 @@ static void
 mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 {
 	struct mmc_data *data = req->data;
-	int i, use_dma, block_size;
+	int i, use_dma = 1, block_size;
 	unsigned sg_len;
 
 	host->data = data;
@@ -970,13 +972,10 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 	sg_len = (data->blocks == 1) ? 1 : data->sg_len;
 
 	/* Only do DMA for entire blocks */
-	use_dma = host->use_dma;
-	if (use_dma) {
-		for (i = 0; i < sg_len; i++) {
-			if ((data->sg[i].length % block_size) != 0) {
-				use_dma = 0;
-				break;
-			}
+	for (i = 0; i < sg_len; i++) {
+		if ((data->sg[i].length % block_size) != 0) {
+			use_dma = 0;
+			break;
 		}
 	}
 
@@ -1239,7 +1238,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 
 	mmc->caps = 0;
 	if (host->pdata->slots[id].wires >= 4)
-		mmc->caps |= MMC_CAP_4_BIT_DATA;
+		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_ERASE;
 
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
@@ -1262,6 +1261,13 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
 	mmc->max_seg_size = mmc->max_req_size;
 
+	if (slot->pdata->get_cover_state != NULL) {
+		setup_timer(&slot->cover_timer, mmc_omap_cover_timer,
+			    (unsigned long)slot);
+		tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
+			     (unsigned long)slot);
+	}
+
 	r = mmc_add_host(mmc);
 	if (r < 0)
 		goto err_remove_host;
@@ -1278,11 +1284,6 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 					&dev_attr_cover_switch);
 		if (r < 0)
 			goto err_remove_slot_name;
-
-		setup_timer(&slot->cover_timer, mmc_omap_cover_timer,
-			    (unsigned long)slot);
-		tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
-			     (unsigned long)slot);
 		tasklet_schedule(&slot->cover_tasklet);
 	}
 
@@ -1333,21 +1334,19 @@ static int mmc_omap_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host = devm_kzalloc(&pdev->dev, sizeof(struct mmc_omap_host),
+			    GFP_KERNEL);
+	if (host == NULL)
+		return -ENOMEM;
+
 	irq = platform_get_irq(pdev, 0);
-	if (res == NULL || irq < 0)
+	if (irq < 0)
 		return -ENXIO;
 
-	res = request_mem_region(res->start, resource_size(res),
-				 pdev->name);
-	if (res == NULL)
-		return -EBUSY;
-
-	host = kzalloc(sizeof(struct mmc_omap_host), GFP_KERNEL);
-	if (host == NULL) {
-		ret = -ENOMEM;
-		goto err_free_mem_region;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->virt_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->virt_base))
+		return PTR_ERR(host->virt_base);
 
 	INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
 	INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
@@ -1369,20 +1368,11 @@ static int mmc_omap_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, host);
 
 	host->id = pdev->id;
-	host->mem_res = res;
-	host->irq = irq;
-	host->use_dma = 1;
 	host->irq = irq;
-	host->phys_base = host->mem_res->start;
-	host->virt_base = ioremap(res->start, resource_size(res));
-	if (!host->virt_base)
-		goto err_ioremap;
-
+	host->phys_base = res->start;
 	host->iclk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(host->iclk)) {
-		ret = PTR_ERR(host->iclk);
-		goto err_free_mmc_host;
-	}
+	if (IS_ERR(host->iclk))
+		return PTR_ERR(host->iclk);
 	clk_enable(host->iclk);
 
 	host->fclk = clk_get(&pdev->dev, "fck");
@@ -1460,12 +1450,6 @@ err_free_dma:
 err_free_iclk:
 	clk_disable(host->iclk);
 	clk_put(host->iclk);
-err_free_mmc_host:
-	iounmap(host->virt_base);
-err_ioremap:
-	kfree(host);
-err_free_mem_region:
-	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
@@ -1493,13 +1477,8 @@ static int mmc_omap_remove(struct platform_device *pdev)
 	if (host->dma_rx)
 		dma_release_channel(host->dma_rx);
 
-	iounmap(host->virt_base);
-	release_mem_region(pdev->resource[0].start,
-			   pdev->resource[0].end - pdev->resource[0].start + 1);
 	destroy_workqueue(host->mmc_omap_wq);
 
-	kfree(host);
-
 	return 0;
 }
 
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index c46feda07d56..5fb994f9a653 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -31,14 +31,9 @@
 #include <linux/mfd/rtsx_pci.h>
 #include <asm/unaligned.h>
 
-/* SD Tuning Data Structure
- * Record continuous timing phase path
- */
-struct timing_phase_path {
-	int start;
-	int end;
-	int mid;
-	int len;
+struct realtek_next {
+	unsigned int	sg_count;
+	s32		cookie;
 };
 
 struct realtek_pci_sdmmc {
@@ -46,9 +41,18 @@ struct realtek_pci_sdmmc {
 	struct rtsx_pcr		*pcr;
 	struct mmc_host		*mmc;
 	struct mmc_request	*mrq;
-
-	struct mutex		host_mutex;
-
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	spinlock_t		lock;
+	struct timer_list	timer;
+	struct tasklet_struct	cmd_tasklet;
+	struct tasklet_struct	data_tasklet;
+	struct tasklet_struct	finish_tasklet;
+
+	u8			rsp_type;
+	u8			rsp_len;
+	int			sg_count;
 	u8			ssc_depth;
 	unsigned int		clock;
 	bool			vpclk;
@@ -58,8 +62,13 @@ struct realtek_pci_sdmmc {
 	int			power_state;
 #define SDMMC_POWER_ON		1
 #define SDMMC_POWER_OFF		0
+
+	struct realtek_next	next_data;
 };
 
+static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
+		struct mmc_request *mrq);
+
 static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
 {
 	return &(host->pdev->dev);
@@ -96,6 +105,95 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
 #define sd_print_debug_regs(host)
 #endif /* DEBUG */
 
+static void sd_isr_done_transfer(struct platform_device *pdev)
+{
+	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+
+	spin_lock(&host->lock);
+	if (host->cmd)
+		tasklet_schedule(&host->cmd_tasklet);
+	if (host->data)
+		tasklet_schedule(&host->data_tasklet);
+	spin_unlock(&host->lock);
+}
+
+static void sd_request_timeout(unsigned long host_addr)
+{
+	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (!host->mrq) {
+		dev_err(sdmmc_dev(host), "error: no request exist\n");
+		goto out;
+	}
+
+	if (host->cmd)
+		host->cmd->error = -ETIMEDOUT;
+	if (host->data)
+		host->data->error = -ETIMEDOUT;
+
+	dev_dbg(sdmmc_dev(host), "timeout for request\n");
+
+out:
+	tasklet_schedule(&host->finish_tasklet);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void sd_finish_request(unsigned long host_addr)
+{
+	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+	unsigned long flags;
+	bool any_error;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	del_timer(&host->timer);
+	mrq = host->mrq;
+	if (!mrq) {
+		dev_err(sdmmc_dev(host), "error: no request need finish\n");
+		goto out;
+	}
+
+	cmd = mrq->cmd;
+	data = mrq->data;
+
+	any_error = (mrq->sbc && mrq->sbc->error) ||
+		(mrq->stop && mrq->stop->error) ||
+		(cmd && cmd->error) || (data && data->error);
+
+	if (any_error) {
+		rtsx_pci_stop_cmd(pcr);
+		sd_clear_error(host);
+	}
+
+	if (data) {
+		if (any_error)
+			data->bytes_xfered = 0;
+		else
+			data->bytes_xfered = data->blocks * data->blksz;
+
+		if (!data->host_cookie)
+			rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len,
+					data->flags & MMC_DATA_READ);
+
+	}
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&pcr->pcr_mutex);
+	mmc_request_done(host->mmc, mrq);
+}
+
 static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
 		u8 *buf, int buf_len, int timeout)
 {
@@ -213,8 +311,7 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
 	return 0;
 }
 
-static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
-		struct mmc_command *cmd)
+static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
 {
 	struct rtsx_pcr *pcr = host->pcr;
 	u8 cmd_idx = (u8)cmd->opcode;
@@ -222,11 +319,14 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
 	int err = 0;
 	int timeout = 100;
 	int i;
-	u8 *ptr;
-	int stat_idx = 0;
 	u8 rsp_type;
 	int rsp_len = 5;
-	bool clock_toggled = false;
+	unsigned long flags;
+
+	if (host->cmd)
+		dev_err(sdmmc_dev(host), "error: cmd already exist\n");
+
+	host->cmd = cmd;
 
 	dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
 			__func__, cmd_idx, arg);
@@ -261,6 +361,8 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
 		err = -EINVAL;
 		goto out;
 	}
+	host->rsp_type = rsp_type;
+	host->rsp_len = rsp_len;
 
 	if (rsp_type == SD_RSP_TYPE_R1b)
 		timeout = 3000;
@@ -270,8 +372,6 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
 				0xFF, SD_CLK_TOGGLE_EN);
 		if (err < 0)
 			goto out;
-
-		clock_toggled = true;
 	}
 
 	rtsx_pci_init_cmd(pcr);
@@ -295,25 +395,60 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
 		/* Read data from ping-pong buffer */
 		for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
 			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
-		stat_idx = 16;
 	} else if (rsp_type != SD_RSP_TYPE_R0) {
 		/* Read data from SD_CMDx registers */
 		for (i = SD_CMD0; i <= SD_CMD4; i++)
 			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
-		stat_idx = 5;
 	}
 
 	rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
 
-	err = rtsx_pci_send_cmd(pcr, timeout);
-	if (err < 0) {
-		sd_print_debug_regs(host);
-		sd_clear_error(host);
-		dev_dbg(sdmmc_dev(host),
-			"rtsx_pci_send_cmd error (err = %d)\n", err);
+	mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout));
+
+	spin_lock_irqsave(&pcr->lock, flags);
+	pcr->trans_result = TRANS_NOT_READY;
+	rtsx_pci_send_cmd_no_wait(pcr);
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	return;
+
+out:
+	cmd->error = err;
+	tasklet_schedule(&host->finish_tasklet);
+}
+
+static void sd_get_rsp(unsigned long host_addr)
+{
+	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_command *cmd;
+	int i, err = 0, stat_idx;
+	u8 *ptr, rsp_type;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	cmd = host->cmd;
+	host->cmd = NULL;
+
+	if (!cmd) {
+		dev_err(sdmmc_dev(host), "error: cmd not exist\n");
 		goto out;
 	}
 
+	spin_lock(&pcr->lock);
+	if (pcr->trans_result == TRANS_NO_DEVICE)
+		err = -ENODEV;
+	else if (pcr->trans_result != TRANS_RESULT_OK)
+		err = -EINVAL;
+	spin_unlock(&pcr->lock);
+
+	if (err < 0)
+		goto out;
+
+	rsp_type = host->rsp_type;
+	stat_idx = host->rsp_len;
+
 	if (rsp_type == SD_RSP_TYPE_R0) {
 		err = 0;
 		goto out;
@@ -350,26 +485,106 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
 				cmd->resp[0]);
 	}
 
+	if (cmd == host->mrq->sbc) {
+		sd_send_cmd(host, host->mrq->cmd);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+	if (cmd == host->mrq->stop)
+		goto out;
+
+	if (cmd->data) {
+		sd_start_multi_rw(host, host->mrq);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
 out:
 	cmd->error = err;
 
-	if (err && clock_toggled)
-		rtsx_pci_write_register(pcr, SD_BUS_STAT,
-				SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+	tasklet_schedule(&host->finish_tasklet);
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
+static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
+			struct mmc_data *data, struct realtek_next *next)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int read = data->flags & MMC_DATA_READ;
+	int sg_count = 0;
+
+	if (!next && data->host_cookie &&
+		data->host_cookie != host->next_data.cookie) {
+		dev_err(sdmmc_dev(host),
+			"error: invalid cookie data[%d] host[%d]\n",
+			data->host_cookie, host->next_data.cookie);
+		data->host_cookie = 0;
+	}
+
+	if (next || (!next && data->host_cookie != host->next_data.cookie))
+		sg_count = rtsx_pci_dma_map_sg(pcr,
+				data->sg, data->sg_len, read);
+	else
+		sg_count = host->next_data.sg_count;
+
+	if (next) {
+		next->sg_count = sg_count;
+		if (++next->cookie < 0)
+			next->cookie = 1;
+		data->host_cookie = next->cookie;
+	}
+
+	return sg_count;
+}
+
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		bool is_first_req)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (data->host_cookie) {
+		dev_err(sdmmc_dev(host),
+			"error: descard already cookie data[%d]\n",
+			data->host_cookie);
+		data->host_cookie = 0;
+	}
+
+	dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n",
+		sd_pre_dma_transfer(host, data, &host->next_data));
+}
+
+static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		int err)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_data *data = mrq->data;
+	int read = data->flags & MMC_DATA_READ;
+
+	rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
+	data->host_cookie = 0;
+}
+
+static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
+		struct mmc_request *mrq)
 {
 	struct rtsx_pcr *pcr = host->pcr;
 	struct mmc_host *mmc = host->mmc;
 	struct mmc_card *card = mmc->card;
 	struct mmc_data *data = mrq->data;
 	int uhs = mmc_card_uhs(card);
-	int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
+	int read = data->flags & MMC_DATA_READ;
 	u8 cfg2, trans_mode;
 	int err;
 	size_t data_len = data->blksz * data->blocks;
 
+	if (host->data)
+		dev_err(sdmmc_dev(host), "error: data already exist\n");
+
+	host->data = data;
+
 	if (read) {
 		cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
 			SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
@@ -420,17 +635,56 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
 	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
 			SD_TRANSFER_END, SD_TRANSFER_END);
 
+	mod_timer(&host->timer, jiffies + 10 * HZ);
 	rtsx_pci_send_cmd_no_wait(pcr);
 
-	err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+	err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read);
 	if (err < 0) {
-		sd_clear_error(host);
-		return err;
+		data->error = err;
+		tasklet_schedule(&host->finish_tasklet);
 	}
-
 	return 0;
 }
 
+static void sd_finish_multi_rw(unsigned long host_addr)
+{
+	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_data *data;
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (!host->data) {
+		dev_err(sdmmc_dev(host), "error: no data exist\n");
+		goto out;
+	}
+
+	data = host->data;
+	host->data = NULL;
+
+	if (pcr->trans_result == TRANS_NO_DEVICE)
+		err = -ENODEV;
+	else if (pcr->trans_result != TRANS_RESULT_OK)
+		err = -EINVAL;
+
+	if (err < 0) {
+		data->error = err;
+		goto out;
+	}
+
+	if (!host->mrq->sbc && data->stop) {
+		sd_send_cmd(host, data->stop);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+out:
+	tasklet_schedule(&host->finish_tasklet);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
 static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
 {
 	rtsx_pci_write_register(host->pcr, SD_CFG1,
@@ -511,85 +765,47 @@ static int sd_change_phase(struct realtek_pci_sdmmc *host,
 	return 0;
 }
 
-static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map)
+static inline u32 test_phase_bit(u32 phase_map, unsigned int bit)
 {
-	struct timing_phase_path path[MAX_PHASE + 1];
-	int i, j, cont_path_cnt;
-	int new_block, max_len, final_path_idx;
-	u8 final_phase = 0xFF;
+	bit %= RTSX_PHASE_MAX;
+	return phase_map & (1 << bit);
+}
 
-	/* Parse phase_map, take it as a bit-ring */
-	cont_path_cnt = 0;
-	new_block = 1;
-	j = 0;
-	for (i = 0; i < MAX_PHASE + 1; i++) {
-		if (phase_map & (1 << i)) {
-			if (new_block) {
-				new_block = 0;
-				j = cont_path_cnt++;
-				path[j].start = i;
-				path[j].end = i;
-			} else {
-				path[j].end = i;
-			}
-		} else {
-			new_block = 1;
-			if (cont_path_cnt) {
-				/* Calculate path length and middle point */
-				int idx = cont_path_cnt - 1;
-				path[idx].len =
-					path[idx].end - path[idx].start + 1;
-				path[idx].mid =
-					path[idx].start + path[idx].len / 2;
-			}
-		}
-	}
+static int sd_get_phase_len(u32 phase_map, unsigned int start_bit)
+{
+	int i;
 
-	if (cont_path_cnt == 0) {
-		dev_dbg(sdmmc_dev(host), "No continuous phase path\n");
-		goto finish;
-	} else {
-		/* Calculate last continuous path length and middle point */
-		int idx = cont_path_cnt - 1;
-		path[idx].len = path[idx].end - path[idx].start + 1;
-		path[idx].mid = path[idx].start + path[idx].len / 2;
+	for (i = 0; i < RTSX_PHASE_MAX; i++) {
+		if (test_phase_bit(phase_map, start_bit + i) == 0)
+			return i;
 	}
+	return RTSX_PHASE_MAX;
+}
+
+static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map)
+{
+	int start = 0, len = 0;
+	int start_final = 0, len_final = 0;
+	u8 final_phase = 0xFF;
 
-	/* Connect the first and last continuous paths if they are adjacent */
-	if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
-		/* Using negative index */
-		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
-		path[0].len += path[cont_path_cnt - 1].len;
-		path[0].mid = path[0].start + path[0].len / 2;
-		/* Convert negative middle point index to positive one */
-		if (path[0].mid < 0)
-			path[0].mid += MAX_PHASE + 1;
-		cont_path_cnt--;
+	if (phase_map == 0) {
+		dev_err(sdmmc_dev(host), "phase error: [map:%x]\n", phase_map);
+		return final_phase;
 	}
 
-	/* Choose the longest continuous phase path */
-	max_len = 0;
-	final_phase = 0;
-	final_path_idx = 0;
-	for (i = 0; i < cont_path_cnt; i++) {
-		if (path[i].len > max_len) {
-			max_len = path[i].len;
-			final_phase = (u8)path[i].mid;
-			final_path_idx = i;
+	while (start < RTSX_PHASE_MAX) {
+		len = sd_get_phase_len(phase_map, start);
+		if (len_final < len) {
+			start_final = start;
+			len_final = len;
 		}
-
-		dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n",
-				i, path[i].start);
-		dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n",
-				i, path[i].end);
-		dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n",
-				i, path[i].len);
-		dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n",
-				i, path[i].mid);
+		start += len ? len : 1;
 	}
 
-finish:
-	dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase);
+	final_phase = (start_final + len_final / 2) % RTSX_PHASE_MAX;
+	dev_dbg(sdmmc_dev(host), "phase: [map:%x] [maxlen:%d] [final:%d]\n",
+		phase_map, len_final, final_phase);
+
 	return final_phase;
 }
 
@@ -635,7 +851,7 @@ static int sd_tuning_phase(struct realtek_pci_sdmmc *host,
 	int err, i;
 	u32 raw_phase_map = 0;
 
-	for (i = MAX_PHASE; i >= 0; i--) {
+	for (i = 0; i < RTSX_PHASE_MAX; i++) {
 		err = sd_tuning_rx_cmd(host, opcode, (u8)i);
 		if (err == 0)
 			raw_phase_map |= 1 << i;
@@ -685,6 +901,13 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
 	return 0;
 }
 
+static inline bool sd_use_muti_rw(struct mmc_command *cmd)
+{
+	return mmc_op_multi(cmd->opcode) ||
+		(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+		(cmd->opcode == MMC_WRITE_BLOCK);
+}
+
 static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
@@ -693,6 +916,14 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	struct mmc_data *data = mrq->data;
 	unsigned int data_size = 0;
 	int err;
+	unsigned long flags;
+
+	mutex_lock(&pcr->pcr_mutex);
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (host->mrq)
+		dev_err(sdmmc_dev(host), "error: request already exist\n");
+	host->mrq = mrq;
 
 	if (host->eject) {
 		cmd->error = -ENOMEDIUM;
@@ -705,8 +936,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		goto finish;
 	}
 
-	mutex_lock(&pcr->pcr_mutex);
-
 	rtsx_pci_start_run(pcr);
 
 	rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
@@ -715,46 +944,28 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
 			CARD_SHARE_MASK, CARD_SHARE_48_SD);
 
-	mutex_lock(&host->host_mutex);
-	host->mrq = mrq;
-	mutex_unlock(&host->host_mutex);
-
 	if (mrq->data)
 		data_size = data->blocks * data->blksz;
 
-	if (!data_size || mmc_op_multi(cmd->opcode) ||
-			(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
-			(cmd->opcode == MMC_WRITE_BLOCK)) {
-		sd_send_cmd_get_rsp(host, cmd);
-
-		if (!cmd->error && data_size) {
-			sd_rw_multi(host, mrq);
+	if (sd_use_muti_rw(cmd))
+		host->sg_count = sd_pre_dma_transfer(host, data, NULL);
 
-			if (mmc_op_multi(cmd->opcode) && mrq->stop)
-				sd_send_cmd_get_rsp(host, mrq->stop);
-		}
+	if (!data_size || sd_use_muti_rw(cmd)) {
+		if (mrq->sbc)
+			sd_send_cmd(host, mrq->sbc);
+		else
+			sd_send_cmd(host, cmd);
+		spin_unlock_irqrestore(&host->lock, flags);
 	} else {
+		spin_unlock_irqrestore(&host->lock, flags);
 		sd_normal_rw(host, mrq);
+		tasklet_schedule(&host->finish_tasklet);
 	}
-
-	if (mrq->data) {
-		if (cmd->error || data->error)
-			data->bytes_xfered = 0;
-		else
-			data->bytes_xfered = data->blocks * data->blksz;
-	}
-
-	mutex_unlock(&pcr->pcr_mutex);
+	return;
 
 finish:
-	if (cmd->error)
-		dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
-
-	mutex_lock(&host->host_mutex);
-	host->mrq = NULL;
-	mutex_unlock(&host->host_mutex);
-
-	mmc_request_done(mmc, mrq);
+	tasklet_schedule(&host->finish_tasklet);
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
@@ -1189,6 +1400,8 @@ out:
 }
 
 static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+	.pre_req = sdmmc_pre_req,
+	.post_req = sdmmc_post_req,
 	.request = sdmmc_request,
 	.set_ios = sdmmc_set_ios,
 	.get_ro = sdmmc_get_ro,
@@ -1252,6 +1465,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
 	struct realtek_pci_sdmmc *host;
 	struct rtsx_pcr *pcr;
 	struct pcr_handle *handle = pdev->dev.platform_data;
+	unsigned long host_addr;
 
 	if (!handle)
 		return -ENXIO;
@@ -1275,8 +1489,15 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
 	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
 	pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
 
-	mutex_init(&host->host_mutex);
+	host_addr = (unsigned long)host;
+	host->next_data.cookie = 1;
+	setup_timer(&host->timer, sd_request_timeout, host_addr);
+	tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr);
+	tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr);
+	tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr);
+	spin_lock_init(&host->lock);
 
+	pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer;
 	realtek_init_host(host);
 
 	mmc_add_host(mmc);
@@ -1289,6 +1510,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
 	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
 	struct rtsx_pcr *pcr;
 	struct mmc_host *mmc;
+	struct mmc_request *mrq;
+	unsigned long flags;
 
 	if (!host)
 		return 0;
@@ -1296,25 +1519,37 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
 	pcr = host->pcr;
 	pcr->slots[RTSX_SD_CARD].p_dev = NULL;
 	pcr->slots[RTSX_SD_CARD].card_event = NULL;
+	pcr->slots[RTSX_SD_CARD].done_transfer = NULL;
 	mmc = host->mmc;
-	host->eject = true;
+	mrq = host->mrq;
 
-	mutex_lock(&host->host_mutex);
+	spin_lock_irqsave(&host->lock, flags);
 	if (host->mrq) {
 		dev_dbg(&(pdev->dev),
 			"%s: Controller removed during transfer\n",
 			mmc_hostname(mmc));
 
-		rtsx_pci_complete_unfinished_transfer(pcr);
+		if (mrq->sbc)
+			mrq->sbc->error = -ENOMEDIUM;
+		if (mrq->cmd)
+			mrq->cmd->error = -ENOMEDIUM;
+		if (mrq->stop)
+			mrq->stop->error = -ENOMEDIUM;
+		if (mrq->data)
+			mrq->data->error = -ENOMEDIUM;
 
-		host->mrq->cmd->error = -ENOMEDIUM;
-		if (host->mrq->stop)
-			host->mrq->stop->error = -ENOMEDIUM;
-		mmc_request_done(mmc, host->mrq);
+		tasklet_schedule(&host->finish_tasklet);
 	}
-	mutex_unlock(&host->host_mutex);
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	del_timer_sync(&host->timer);
+	tasklet_kill(&host->cmd_tasklet);
+	tasklet_kill(&host->data_tasklet);
+	tasklet_kill(&host->finish_tasklet);
 
 	mmc_remove_host(mmc);
+	host->eject = true;
+
 	mmc_free_host(mmc);
 
 	dev_dbg(&(pdev->dev),
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index 7a190fe4dff1..923eefabf801 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -54,6 +54,7 @@
 
 struct sdhci_bcm_kona_dev {
 	struct mutex	write_lock; /* protect back to back writes */
+	struct clk	*external_clk;
 };
 
 
@@ -257,6 +258,24 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)
 		goto err_pltfm_free;
 	}
 
+	/* Get and enable the external clock */
+	kona_dev->external_clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(kona_dev->external_clk)) {
+		dev_err(dev, "Failed to get external clock\n");
+		ret = PTR_ERR(kona_dev->external_clk);
+		goto err_pltfm_free;
+	}
+
+	if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) {
+		dev_err(dev, "Failed to set rate external clock\n");
+		goto err_pltfm_free;
+	}
+
+	if (clk_prepare_enable(kona_dev->external_clk) != 0) {
+		dev_err(dev, "Failed to enable external clock\n");
+		goto err_pltfm_free;
+	}
+
 	dev_dbg(dev, "non-removable=%c\n",
 		(host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N');
 	dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n",
@@ -271,7 +290,7 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)
 
 	ret = sdhci_bcm_kona_sd_reset(host);
 	if (ret)
-		goto err_pltfm_free;
+		goto err_clk_disable;
 
 	sdhci_bcm_kona_sd_init(host);
 
@@ -307,6 +326,9 @@ err_remove_host:
 err_reset:
 	sdhci_bcm_kona_sd_reset(host);
 
+err_clk_disable:
+	clk_disable_unprepare(kona_dev->external_clk);
+
 err_pltfm_free:
 	sdhci_pltfm_free(pdev);
 
@@ -316,7 +338,18 @@ err_pltfm_free:
 
 static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
 {
-	return sdhci_pltfm_unregister(pdev);
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
+	struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
+	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+	sdhci_remove_host(host, dead);
+
+	clk_disable_unprepare(kona_dev->external_clk);
+
+	sdhci_pltfm_free(pdev);
+
+	return 0;
 }
 
 static struct platform_driver sdhci_bcm_kona_driver = {
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 8424839660f8..736d7a2eb7ec 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -208,7 +208,7 @@ static struct platform_driver sdhci_dove_driver = {
 		.name	= "sdhci-dove",
 		.owner	= THIS_MODULE,
 		.pm	= SDHCI_PLTFM_PMOPS,
-		.of_match_table = of_match_ptr(sdhci_dove_of_match_table),
+		.of_match_table = sdhci_dove_of_match_table,
 	},
 	.probe		= sdhci_dove_probe,
 	.remove		= sdhci_dove_remove,
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 0955777b6c7e..fdc612120362 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -610,6 +610,18 @@ static const struct sdhci_pci_fixes sdhci_via = {
 	.probe		= via_probe,
 };
 
+static int rtsx_probe_slot(struct sdhci_pci_slot *slot)
+{
+	slot->host->mmc->caps2 |= MMC_CAP2_HS200;
+	return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_rtsx = {
+	.quirks2	= SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+			SDHCI_QUIRK2_BROKEN_DDR50,
+	.probe_slot	= rtsx_probe_slot,
+};
+
 static const struct pci_device_id pci_ids[] = {
 	{
 		.vendor		= PCI_VENDOR_ID_RICOH,
@@ -732,6 +744,14 @@ static const struct pci_device_id pci_ids[] = {
 	},
 
 	{
+		.vendor		= PCI_VENDOR_ID_REALTEK,
+		.device		= 0x5250,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_rtsx,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_MRST_SD0,
 		.subvendor	= PCI_ANY_ID,
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 6debda952155..d61eb5a70833 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -51,12 +51,13 @@ struct sdhci_s3c {
 	struct platform_device	*pdev;
 	struct resource		*ioarea;
 	struct s3c_sdhci_platdata *pdata;
-	unsigned int		cur_clk;
+	int			cur_clk;
 	int			ext_cd_irq;
 	int			ext_cd_gpio;
 
 	struct clk		*clk_io;
 	struct clk		*clk_bus[MAX_BUS_CLK];
+	unsigned long		clk_rates[MAX_BUS_CLK];
 };
 
 /**
@@ -77,32 +78,6 @@ static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
 }
 
 /**
- * get_curclk - convert ctrl2 register to clock source number
- * @ctrl2: Control2 register value.
- */
-static u32 get_curclk(u32 ctrl2)
-{
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-
-	return ctrl2;
-}
-
-static void sdhci_s3c_check_sclk(struct sdhci_host *host)
-{
-	struct sdhci_s3c *ourhost = to_s3c(host);
-	u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
-
-	if (get_curclk(tmp) != ourhost->cur_clk) {
-		dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
-
-		tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-		tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-		writel(tmp, host->ioaddr + S3C_SDHCI_CONTROL2);
-	}
-}
-
-/**
  * sdhci_s3c_get_max_clk - callback to get maximum clock frequency.
  * @host: The SDHCI host instance.
  *
@@ -111,20 +86,11 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host)
 static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
 {
 	struct sdhci_s3c *ourhost = to_s3c(host);
-	struct clk *busclk;
-	unsigned int rate, max;
-	int clk;
-
-	/* note, a reset will reset the clock source */
-
-	sdhci_s3c_check_sclk(host);
-
-	for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
-		busclk = ourhost->clk_bus[clk];
-		if (!busclk)
-			continue;
+	unsigned long rate, max = 0;
+	int src;
 
-		rate = clk_get_rate(busclk);
+	for (src = 0; src < MAX_BUS_CLK; src++) {
+		rate = ourhost->clk_rates[src];
 		if (rate > max)
 			max = rate;
 	}
@@ -144,9 +110,9 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
 {
 	unsigned long rate;
 	struct clk *clksrc = ourhost->clk_bus[src];
-	int div;
+	int shift;
 
-	if (!clksrc)
+	if (IS_ERR(clksrc))
 		return UINT_MAX;
 
 	/*
@@ -158,17 +124,24 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
 		return wanted - rate;
 	}
 
-	rate = clk_get_rate(clksrc);
+	rate = ourhost->clk_rates[src];
 
-	for (div = 1; div < 256; div *= 2) {
-		if ((rate / div) <= wanted)
+	for (shift = 0; shift <= 8; ++shift) {
+		if ((rate >> shift) <= wanted)
 			break;
 	}
 
+	if (shift > 8) {
+		dev_dbg(&ourhost->pdev->dev,
+			"clk %d: rate %ld, min rate %lu > wanted %u\n",
+			src, rate, rate / 256, wanted);
+		return UINT_MAX;
+	}
+
 	dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
-		src, rate, wanted, rate / div);
+		src, rate, wanted, rate >> shift);
 
-	return wanted - (rate / div);
+	return wanted - (rate >> shift);
 }
 
 /**
@@ -209,20 +182,22 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
 		struct clk *clk = ourhost->clk_bus[best_src];
 
 		clk_prepare_enable(clk);
-		clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
-
-		/* turn clock off to card before changing clock source */
-		writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+		if (ourhost->cur_clk >= 0)
+			clk_disable_unprepare(
+					ourhost->clk_bus[ourhost->cur_clk]);
 
 		ourhost->cur_clk = best_src;
-		host->max_clk = clk_get_rate(clk);
-
-		ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
-		ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-		ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-		writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
+		host->max_clk = ourhost->clk_rates[best_src];
 	}
 
+	/* turn clock off to card before changing clock source */
+	writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+	ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
+	ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+	ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
+	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
+
 	/* reprogram default hardware configuration */
 	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA,
 		host->ioaddr + S3C64XX_SDHCI_CONTROL4);
@@ -254,17 +229,17 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
 static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
 {
 	struct sdhci_s3c *ourhost = to_s3c(host);
-	unsigned int delta, min = UINT_MAX;
+	unsigned long rate, min = ULONG_MAX;
 	int src;
 
 	for (src = 0; src < MAX_BUS_CLK; src++) {
-		delta = sdhci_s3c_consider_clock(ourhost, src, 0);
-		if (delta == UINT_MAX)
+		rate = ourhost->clk_rates[src] / 256;
+		if (!rate)
 			continue;
-		/* delta is a negative value in this case */
-		if (-delta < min)
-			min = -delta;
+		if (rate < min)
+			min = rate;
 	}
+
 	return min;
 }
 
@@ -272,20 +247,44 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
 static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host)
 {
 	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned long rate, max = 0;
+	int src;
 
-	return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX);
+	for (src = 0; src < MAX_BUS_CLK; src++) {
+		struct clk *clk;
+
+		clk = ourhost->clk_bus[src];
+		if (IS_ERR(clk))
+			continue;
+
+		rate = clk_round_rate(clk, ULONG_MAX);
+		if (rate > max)
+			max = rate;
+	}
+
+	return max;
 }
 
 /* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */
 static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
 {
 	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned long rate, min = ULONG_MAX;
+	int src;
 
-	/*
-	 * initial clock can be in the frequency range of
-	 * 100KHz-400KHz, so we set it as max value.
-	 */
-	return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000);
+	for (src = 0; src < MAX_BUS_CLK; src++) {
+		struct clk *clk;
+
+		clk = ourhost->clk_bus[src];
+		if (IS_ERR(clk))
+			continue;
+
+		rate = clk_round_rate(clk, 0);
+		if (rate < min)
+			min = rate;
+	}
+
+	return min;
 }
 
 /* sdhci_cmu_set_clock - callback on clock change.*/
@@ -552,6 +551,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	sc->host = host;
 	sc->pdev = pdev;
 	sc->pdata = pdata;
+	sc->cur_clk = -1;
 
 	platform_set_drvdata(pdev, host);
 
@@ -566,25 +566,18 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	clk_prepare_enable(sc->clk_io);
 
 	for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-		struct clk *clk;
 		char name[14];
 
 		snprintf(name, 14, "mmc_busclk.%d", ptr);
-		clk = devm_clk_get(dev, name);
-		if (IS_ERR(clk))
+		sc->clk_bus[ptr] = devm_clk_get(dev, name);
+		if (IS_ERR(sc->clk_bus[ptr]))
 			continue;
 
 		clks++;
-		sc->clk_bus[ptr] = clk;
-
-		/*
-		 * save current clock index to know which clock bus
-		 * is used later in overriding functions.
-		 */
-		sc->cur_clk = ptr;
+		sc->clk_rates[ptr] = clk_get_rate(sc->clk_bus[ptr]);
 
 		dev_info(dev, "clock source %d: %s (%ld Hz)\n",
-			 ptr, name, clk_get_rate(clk));
+				ptr, name, sc->clk_rates[ptr]);
 	}
 
 	if (clks == 0) {
@@ -593,10 +586,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 		goto err_no_busclks;
 	}
 
-#ifndef CONFIG_PM_RUNTIME
-	clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
-#endif
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	host->ioaddr = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(host->ioaddr)) {
@@ -709,10 +698,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 	return 0;
 
  err_req_regs:
-#ifndef CONFIG_PM_RUNTIME
-	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
-#endif
-
  err_no_busclks:
 	clk_disable_unprepare(sc->clk_io);
 
@@ -743,9 +728,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-#ifndef CONFIG_PM_RUNTIME
-	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
-#endif
 	clk_disable_unprepare(sc->clk_io);
 
 	sdhci_free_host(host);
@@ -779,7 +761,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
 
 	ret = sdhci_runtime_suspend_host(host);
 
-	clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
+	if (ourhost->cur_clk >= 0)
+		clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
 	clk_disable_unprepare(busclk);
 	return ret;
 }
@@ -792,7 +775,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
 	int ret;
 
 	clk_prepare_enable(busclk);
-	clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
+	if (ourhost->cur_clk >= 0)
+		clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
 	ret = sdhci_runtime_resume_host(host);
 	return ret;
 }
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 2dba9f8d1760..76ddd89a688e 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -84,14 +84,12 @@ static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pde
 	/* If pdata is required */
 	if (cd_gpio != -1) {
 		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata) {
+		if (!pdata)
 			dev_err(&pdev->dev, "DT: kzalloc failed\n");
-			return ERR_PTR(-ENOMEM);
-		}
+		else
+			pdata->card_int_gpio = cd_gpio;
 	}
 
-	pdata->card_int_gpio = cd_gpio;
-
 	return pdata;
 }
 #else
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9ddef4763541..7f95211e9449 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -675,12 +675,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 		return 0xE;
 
 	/* Unspecified timeout, assume max */
-	if (!data && !cmd->cmd_timeout_ms)
+	if (!data && !cmd->busy_timeout)
 		return 0xE;
 
 	/* timeout in us */
 	if (!data)
-		target_timeout = cmd->cmd_timeout_ms * 1000;
+		target_timeout = cmd->busy_timeout * 1000;
 	else {
 		target_timeout = data->timeout_ns / 1000;
 		if (host->clock)
@@ -1019,8 +1019,8 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 	}
 
 	timeout = jiffies;
-	if (!cmd->data && cmd->cmd_timeout_ms > 9000)
-		timeout += DIV_ROUND_UP(cmd->cmd_timeout_ms, 1000) * HZ + HZ;
+	if (!cmd->data && cmd->busy_timeout > 9000)
+		timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
 	else
 		timeout += 10 * HZ;
 	mod_timer(&host->timer, timeout);
@@ -2941,7 +2941,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
 		host->timeout_clk = mmc->f_max / 1000;
 
-	mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+	mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
 
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 
@@ -3020,7 +3020,8 @@ int sdhci_add_host(struct sdhci_host *host)
 	} else if (caps[1] & SDHCI_SUPPORT_SDR50)
 		mmc->caps |= MMC_CAP_UHS_SDR50;
 
-	if (caps[1] & SDHCI_SUPPORT_DDR50)
+	if ((caps[1] & SDHCI_SUPPORT_DDR50) &&
+		!(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
 		mmc->caps |= MMC_CAP_UHS_DDR50;
 
 	/* Does the host need tuning for SDR50? */
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 2d6ce257a273..91058dabd11a 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -37,6 +37,8 @@
 
 struct sh_mobile_sdhi_of_data {
 	unsigned long tmio_flags;
+	unsigned long capabilities;
+	unsigned long capabilities2;
 };
 
 static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = {
@@ -45,6 +47,31 @@ static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = {
 	},
 };
 
+static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
+	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+};
+
+static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
+	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+	.capabilities2	= MMC_CAP2_NO_MULTI_READ,
+};
+
+static const struct of_device_id sh_mobile_sdhi_of_match[] = {
+	{ .compatible = "renesas,sdhi-shmobile" },
+	{ .compatible = "renesas,sdhi-sh7372" },
+	{ .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], },
+	{ .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], },
+	{ .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], },
+	{ .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, },
+	{ .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, },
+	{ .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, },
+	{ .compatible = "renesas,sdhi-r8a7791", .data = &of_rcar_gen2_compatible, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
+
 struct sh_mobile_sdhi {
 	struct clk *clk;
 	struct tmio_mmc_data mmc_data;
@@ -114,19 +141,6 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
 	.cd_wakeup = sh_mobile_sdhi_cd_wakeup,
 };
 
-static const struct of_device_id sh_mobile_sdhi_of_match[] = {
-	{ .compatible = "renesas,sdhi-shmobile" },
-	{ .compatible = "renesas,sdhi-sh7372" },
-	{ .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{ .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{ .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{ .compatible = "renesas,sdhi-r8a7778", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{ .compatible = "renesas,sdhi-r8a7779", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{ .compatible = "renesas,sdhi-r8a7790", .data = &sh_mobile_sdhi_of_cfg[0], },
-	{},
-};
-MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
-
 static int sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -212,6 +226,8 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
 	if (of_id && of_id->data) {
 		const struct sh_mobile_sdhi_of_data *of_data = of_id->data;
 		mmc_data->flags |= of_data->tmio_flags;
+		mmc_data->capabilities |= of_data->capabilities;
+		mmc_data->capabilities2 |= of_data->capabilities2;
 	}
 
 	/* SD control register space size is 0x100, 0x200 for bus_shift=1 */
@@ -316,10 +332,10 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
 }
 
 static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
-	.suspend = tmio_mmc_host_suspend,
-	.resume = tmio_mmc_host_resume,
-	.runtime_suspend = tmio_mmc_host_runtime_suspend,
-	.runtime_resume = tmio_mmc_host_runtime_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_host_suspend, tmio_mmc_host_resume)
+	SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend,
+			tmio_mmc_host_runtime_resume,
+			NULL)
 };
 
 static struct platform_driver sh_mobile_sdhi_driver = {
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 1900abb04236..cfad844730d8 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -23,38 +23,37 @@
 
 #include "tmio_mmc.h"
 
-#ifdef CONFIG_PM
-static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int tmio_mmc_suspend(struct device *dev)
 {
-	const struct mfd_cell *cell = mfd_get_cell(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	int ret;
 
-	ret = tmio_mmc_host_suspend(&dev->dev);
+	ret = tmio_mmc_host_suspend(dev);
 
 	/* Tell MFD core it can disable us now.*/
 	if (!ret && cell->disable)
-		cell->disable(dev);
+		cell->disable(pdev);
 
 	return ret;
 }
 
-static int tmio_mmc_resume(struct platform_device *dev)
+static int tmio_mmc_resume(struct device *dev)
 {
-	const struct mfd_cell *cell = mfd_get_cell(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	int ret = 0;
 
 	/* Tell the MFD core we are ready to be enabled */
 	if (cell->resume)
-		ret = cell->resume(dev);
+		ret = cell->resume(pdev);
 
 	if (!ret)
-		ret = tmio_mmc_host_resume(&dev->dev);
+		ret = tmio_mmc_host_resume(dev);
 
 	return ret;
 }
-#else
-#define tmio_mmc_suspend NULL
-#define tmio_mmc_resume NULL
 #endif
 
 static int tmio_mmc_probe(struct platform_device *pdev)
@@ -134,15 +133,18 @@ static int tmio_mmc_remove(struct platform_device *pdev)
 
 /* ------------------- device registration ----------------------- */
 
+static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume)
+};
+
 static struct platform_driver tmio_mmc_driver = {
 	.driver = {
 		.name = "tmio-mmc",
 		.owner = THIS_MODULE,
+		.pm = &tmio_mmc_dev_pm_ops,
 	},
 	.probe = tmio_mmc_probe,
 	.remove = tmio_mmc_remove,
-	.suspend = tmio_mmc_suspend,
-	.resume = tmio_mmc_resume,
 };
 
 module_platform_driver(tmio_mmc_driver);
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index aaa9c7e9e730..100ffe0b2faf 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -162,16 +162,15 @@ static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
 }
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 int tmio_mmc_host_suspend(struct device *dev);
 int tmio_mmc_host_resume(struct device *dev);
-#else
-#define tmio_mmc_host_suspend NULL
-#define tmio_mmc_host_resume NULL
 #endif
 
+#ifdef CONFIG_PM_RUNTIME
 int tmio_mmc_host_runtime_suspend(struct device *dev);
 int tmio_mmc_host_runtime_resume(struct device *dev);
+#endif
 
 static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
 {
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 8d8abf23a611..faf0924e71cb 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -1142,7 +1142,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 }
 EXPORT_SYMBOL(tmio_mmc_host_remove);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 int tmio_mmc_host_suspend(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -1165,9 +1165,9 @@ int tmio_mmc_host_resume(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL(tmio_mmc_host_resume);
+#endif
 
-#endif	/* CONFIG_PM */
-
+#ifdef CONFIG_PM_RUNTIME
 int tmio_mmc_host_runtime_suspend(struct device *dev)
 {
 	return 0;
@@ -1184,5 +1184,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
+#endif
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c
index c0105a2e269a..d2c386f09d69 100644
--- a/drivers/mmc/host/ushc.c
+++ b/drivers/mmc/host/ushc.c
@@ -504,7 +504,7 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
 		ret = -ENOMEM;
 		goto err;
 	}
-	ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
+	ushc->csw = kzalloc(sizeof(struct ushc_csw), GFP_KERNEL);
 	if (ushc->csw == NULL) {
 		ret = -ENOMEM;
 		goto err;
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index e902ed7846b0..498d1f799085 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -757,7 +757,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 		of_match_device(wmt_mci_dt_ids, &pdev->dev);
-	const struct wmt_mci_caps *wmt_caps = of_id->data;
+	const struct wmt_mci_caps *wmt_caps;
 	int ret;
 	int regular_irq, dma_irq;
 
@@ -766,6 +766,8 @@ static int wmt_mci_probe(struct platform_device *pdev)
 		return -EFAULT;
 	}
 
+	wmt_caps = of_id->data;
+
 	if (!np) {
 		dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n");
 		return -EFAULT;
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 77514430f1fe..5e74c860e532 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -435,10 +434,8 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 	int i;
 
 	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-	if (!mtd) {
-		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
+	if (!mtd)
 		return NULL;
-	}
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 
@@ -564,10 +561,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
 	mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
 	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
 			* mtd->numeraseregions, GFP_KERNEL);
-	if (!mtd->eraseregions) {
-		printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
+	if (!mtd->eraseregions)
 		goto setup_err;
-	}
 
 	for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
 		unsigned long ernum, ersize;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 89b9d6891532..e21fde9d4d7e 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -507,10 +506,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 	int i;
 
 	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-	if (!mtd) {
-		printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
+	if (!mtd)
 		return NULL;
-	}
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 
@@ -661,10 +658,8 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 	mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
 	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
 				    * mtd->numeraseregions, GFP_KERNEL);
-	if (!mtd->eraseregions) {
-		printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
+	if (!mtd->eraseregions)
 		goto setup_err;
-	}
 
 	for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
 		unsigned long ernum, ersize;
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index 096993f9711e..6293855fb5ee 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -22,7 +22,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -176,7 +175,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
 	//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
 
 	if (!mtd) {
-		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
 		kfree(cfi->cmdset_priv);
 		return NULL;
 	}
@@ -189,7 +187,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
 	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
 			* mtd->numeraseregions, GFP_KERNEL);
 	if (!mtd->eraseregions) {
-		printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
 		kfree(cfi->cmdset_priv);
 		kfree(mtd);
 		return NULL;
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index d25535279404..e8d0164498b0 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -168,10 +168,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 		return 0;
 
 	cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
-	if (!cfi->cfiq) {
-		printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
+	if (!cfi->cfiq)
 		return 0;
-	}
 
 	memset(cfi->cfiq,0,sizeof(struct cfi_ident));
 
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index f992418f40a8..08049f6eea60 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -116,10 +116,8 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
 	printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);
 
 	extp = kmalloc(size, GFP_KERNEL);
-	if (!extp) {
-		printk(KERN_ERR "Failed to allocate memory\n");
+	if (!extp)
 		goto out;
-	}
 
 #ifdef CONFIG_MTD_XIP
 	local_irq_disable();
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index ffb36ba8a6e0..b57ceea21513 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -114,7 +114,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
 	mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG);
 	chip_map = kzalloc(mapsize, GFP_KERNEL);
 	if (!chip_map) {
-		printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
 		kfree(cfi.cfiq);
 		return NULL;
 	}
@@ -139,7 +138,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
 	retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
 
 	if (!retcfi) {
-		printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
 		kfree(cfi.cfiq);
 		kfree(chip_map);
 		return NULL;
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index d9fd87a4c8dc..3e12234b7565 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -240,13 +240,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 
 	if (IS_ERR(bdev)) {
 		pr_err("error: cannot open device %s\n", devname);
-		goto devinit_err;
+		goto err_free_block2mtd;
 	}
 	dev->blkdev = bdev;
 
 	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 		pr_err("attempting to use an MTD device as a block device\n");
-		goto devinit_err;
+		goto err_free_block2mtd;
 	}
 
 	mutex_init(&dev->write_mutex);
@@ -255,7 +255,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 	/* make the name contain the block device in */
 	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
 	if (!name)
-		goto devinit_err;
+		goto err_destroy_mutex;
 
 	dev->mtd.name = name;
 
@@ -274,7 +274,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 
 	if (mtd_device_register(&dev->mtd, NULL, 0)) {
 		/* Device didn't get added, so free the entry */
-		goto devinit_err;
+		goto err_destroy_mutex;
 	}
 	list_add(&dev->list, &blkmtd_device_list);
 	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
@@ -283,7 +283,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
 
-devinit_err:
+err_destroy_mutex:
+	mutex_destroy(&dev->write_mutex);
+err_free_block2mtd:
 	block2mtd_free_device(dev);
 	return NULL;
 }
@@ -448,6 +450,7 @@ static void block2mtd_exit(void)
 		struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
 		block2mtd_sync(&dev->mtd);
 		mtd_device_unregister(&dev->mtd);
+		mutex_destroy(&dev->write_mutex);
 		pr_info("mtd%d: [%s] removed\n",
 			dev->mtd.index,
 			dev->mtd.name + strlen("block2mtd: "));
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index d1dd6a33a050..f160d2c6cd59 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -354,10 +354,8 @@ static int elm_probe(struct platform_device *pdev)
 	struct elm_info *info;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
 
 	info->dev = &pdev->dev;
 
@@ -380,7 +378,7 @@ static int elm_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(&pdev->dev);
-	if (pm_runtime_get_sync(&pdev->dev)) {
+	if (pm_runtime_get_sync(&pdev->dev) < 0) {
 		ret = -EINVAL;
 		pm_runtime_disable(&pdev->dev);
 		dev_err(&pdev->dev, "can't enable clock\n");
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index ad1913909702..882b72072ae7 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -15,7 +15,6 @@
  *
  */
 
-#include <linux/init.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -41,7 +40,8 @@
 #define	OPCODE_WRSR		0x01	/* Write status register 1 byte */
 #define	OPCODE_NORM_READ	0x03	/* Read data bytes (low frequency) */
 #define	OPCODE_FAST_READ	0x0b	/* Read data bytes (high frequency) */
-#define	OPCODE_QUAD_READ        0x6b    /* Read data bytes */
+#define	OPCODE_DUAL_READ        0x3b    /* Read data bytes (Dual SPI) */
+#define	OPCODE_QUAD_READ        0x6b    /* Read data bytes (Quad SPI) */
 #define	OPCODE_PP		0x02	/* Page program (up to 256 bytes) */
 #define	OPCODE_BE_4K		0x20	/* Erase 4KiB block */
 #define	OPCODE_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips */
@@ -54,7 +54,8 @@
 /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 #define	OPCODE_NORM_READ_4B	0x13	/* Read data bytes (low frequency) */
 #define	OPCODE_FAST_READ_4B	0x0c	/* Read data bytes (high frequency) */
-#define	OPCODE_QUAD_READ_4B	0x6c    /* Read data bytes */
+#define	OPCODE_DUAL_READ_4B	0x3c    /* Read data bytes (Dual SPI) */
+#define	OPCODE_QUAD_READ_4B	0x6c    /* Read data bytes (Quad SPI) */
 #define	OPCODE_PP_4B		0x12	/* Page program (up to 256 bytes) */
 #define	OPCODE_SE_4B		0xdc	/* Sector erase (usually 64KiB) */
 
@@ -95,6 +96,7 @@
 enum read_type {
 	M25P80_NORMAL = 0,
 	M25P80_FAST,
+	M25P80_DUAL,
 	M25P80_QUAD,
 };
 
@@ -479,6 +481,7 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash)
 {
 	switch (flash->flash_read) {
 	case M25P80_FAST:
+	case M25P80_DUAL:
 	case M25P80_QUAD:
 		return 1;
 	case M25P80_NORMAL:
@@ -492,6 +495,8 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash)
 static inline unsigned int m25p80_rx_nbits(const struct m25p *flash)
 {
 	switch (flash->flash_read) {
+	case M25P80_DUAL:
+		return 2;
 	case M25P80_QUAD:
 		return 4;
 	default:
@@ -855,7 +860,8 @@ struct flash_info {
 #define	SST_WRITE	0x04		/* use SST byte programming */
 #define	M25P_NO_FR	0x08		/* Can't do fastread */
 #define	SECT_4K_PMC	0x10		/* OPCODE_BE_4K_PMC works uniformly */
-#define	M25P80_QUAD_READ	0x20    /* Flash supports Quad Read */
+#define	M25P80_DUAL_READ	0x20    /* Flash supports Dual Read */
+#define	M25P80_QUAD_READ	0x40    /* Flash supports Quad Read */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
@@ -953,8 +959,8 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 0) },
 	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 0) },
 	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, M25P80_QUAD_READ) },
-	{ "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_QUAD_READ) },
+	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, M25P80_DUAL_READ | M25P80_QUAD_READ) },
+	{ "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_DUAL_READ | M25P80_QUAD_READ) },
 	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
 	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
 	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
@@ -965,6 +971,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
 	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
 	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
+	{ "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16, SECT_4K) },
 	{ "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32, SECT_4K) },
 	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
 
@@ -1072,9 +1079,8 @@ static const struct spi_device_id *jedec_probe(struct spi_device *spi)
 	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
 		info = (void *)m25p_ids[tmp].driver_data;
 		if (info->jedec_id == jedec) {
-			if (info->ext_id != 0 && info->ext_id != ext_jedec)
-				continue;
-			return &m25p_ids[tmp];
+			if (info->ext_id == 0 || info->ext_id == ext_jedec)
+				return &m25p_ids[tmp];
 		}
 	}
 	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
@@ -1226,7 +1232,7 @@ static int m25p_probe(struct spi_device *spi)
 	if (info->flags & M25P_NO_FR)
 		flash->flash_read = M25P80_NORMAL;
 
-	/* Quad-read mode takes precedence over fast/normal */
+	/* Quad/Dual-read mode takes precedence over fast/normal */
 	if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) {
 		ret = set_quad_mode(flash, info->jedec_id);
 		if (ret) {
@@ -1234,6 +1240,8 @@ static int m25p_probe(struct spi_device *spi)
 			return ret;
 		}
 		flash->flash_read = M25P80_QUAD;
+	} else if (spi->mode & SPI_RX_DUAL && info->flags & M25P80_DUAL_READ) {
+		flash->flash_read = M25P80_DUAL;
 	}
 
 	/* Default commands */
@@ -1241,6 +1249,9 @@ static int m25p_probe(struct spi_device *spi)
 	case M25P80_QUAD:
 		flash->read_opcode = OPCODE_QUAD_READ;
 		break;
+	case M25P80_DUAL:
+		flash->read_opcode = OPCODE_DUAL_READ;
+		break;
 	case M25P80_FAST:
 		flash->read_opcode = OPCODE_FAST_READ;
 		break;
@@ -1265,6 +1276,9 @@ static int m25p_probe(struct spi_device *spi)
 			case M25P80_QUAD:
 				flash->read_opcode = OPCODE_QUAD_READ_4B;
 				break;
+			case M25P80_DUAL:
+				flash->read_opcode = OPCODE_DUAL_READ_4B;
+				break;
 			case M25P80_FAST:
 				flash->read_opcode = OPCODE_FAST_READ_4B;
 				break;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 624069de4f28..8b278d2b15bb 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -10,7 +10,6 @@
  * 2 of the License, or (at your option) any later version.
 */
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index e1f2aebaa489..2cceebfb251e 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -205,6 +205,8 @@ static inline void kill_final_newline(char *str)
 	return 1;		\
 } while (0)
 
+#ifndef MODULE
+static int phram_init_called;
 /*
  * This shall contain the module parameter if any. It is of the form:
  * - phram=<device>,<address>,<size> for module case
@@ -213,9 +215,10 @@ static inline void kill_final_newline(char *str)
  * size.
  * Example: phram.phram=rootfs,0xa0000000,512Mi
  */
-static __initdata char phram_paramline[64 + 20 + 20];
+static char phram_paramline[64 + 20 + 20];
+#endif
 
-static int __init phram_setup(const char *val)
+static int phram_setup(const char *val)
 {
 	char buf[64 + 20 + 20], *str = buf;
 	char *token[3];
@@ -264,17 +267,36 @@ static int __init phram_setup(const char *val)
 	return ret;
 }
 
-static int __init phram_param_call(const char *val, struct kernel_param *kp)
+static int phram_param_call(const char *val, struct kernel_param *kp)
 {
+#ifdef MODULE
+	return phram_setup(val);
+#else
 	/*
-	 * This function is always called before 'init_phram()', whether
-	 * built-in or module.
+	 * If more parameters are later passed in via
+	 * /sys/module/phram/parameters/phram
+	 * and init_phram() has already been called,
+	 * we can parse the argument now.
 	 */
+
+	if (phram_init_called)
+		return phram_setup(val);
+
+	/*
+	 * During early boot stage, we only save the parameters
+	 * here. We must parse them later: if the param passed
+	 * from kernel boot command line, phram_param_call() is
+	 * called so early that it is not possible to resolve
+	 * the device (even kmalloc() fails). Defer that work to
+	 * phram_setup().
+	 */
+
 	if (strlen(val) >= sizeof(phram_paramline))
 		return -ENOSPC;
 	strcpy(phram_paramline, val);
 
 	return 0;
+#endif
 }
 
 module_param_call(phram, phram_param_call, NULL, NULL, 000);
@@ -283,10 +305,15 @@ MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"
 
 static int __init init_phram(void)
 {
+	int ret = 0;
+
+#ifndef MODULE
 	if (phram_paramline[0])
-		return phram_setup(phram_paramline);
+		ret = phram_setup(phram_paramline);
+	phram_init_called = 1;
+#endif
 
-	return 0;
+	return ret;
 }
 
 static void __exit cleanup_phram(void)
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 0c51b988e1f8..f02603e1bfeb 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -725,16 +725,11 @@ static int __init init_pmc551(void)
 		}
 
 		mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
-		if (!mtd) {
-			printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
-				"device.\n");
+		if (!mtd)
 			break;
-		}
 
 		priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
 		if (!priv) {
-			printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
-				"device.\n");
 			kfree(mtd);
 			break;
 		}
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index 423821412062..363da96e6891 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -913,7 +913,6 @@ static int spear_smi_probe(struct platform_device *pdev)
 	if (np) {
 		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 		if (!pdata) {
-			pr_err("%s: ERROR: no memory", __func__);
 			ret = -ENOMEM;
 			goto err;
 		}
@@ -943,7 +942,6 @@ static int spear_smi_probe(struct platform_device *pdev)
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_ATOMIC);
 	if (!dev) {
 		ret = -ENOMEM;
-		dev_err(&pdev->dev, "mem alloc fail\n");
 		goto err;
 	}
 
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 687bf27ec850..c63ecbcad0b7 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -15,7 +15,6 @@
  *
  */
 
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 4adc0374fb6b..487e64f411a5 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -30,7 +30,6 @@
 #include <asm/uaccess.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index d38b6460d505..018c75faadb3 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -55,10 +55,8 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
 	int i, j;
 
 	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-	if (!mtd) {
-		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
+	if (!mtd)
 		return NULL;
-	}
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 
diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c
index 45abed67f1ef..69f2112340b1 100644
--- a/drivers/mtd/lpddr/qinfo_probe.c
+++ b/drivers/mtd/lpddr/qinfo_probe.c
@@ -135,11 +135,8 @@ static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr)
 {
 
 	lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL);
-	if (!lpddr->qinfo) {
-		printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n",
-				map->name);
+	if (!lpddr->qinfo)
 		return 0;
-	}
 
 	/* Get the ManuID */
 	lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID));
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 310dc7c93425..179c6e124701 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -124,7 +124,7 @@ config MTD_NETSC520
 
 config MTD_TS5500
 	tristate "JEDEC Flash device mapped on Technologic Systems TS-5500"
-	depends on X86
+	depends on TS5500 || COMPILE_TEST
 	select MTD_JEDECPROBE
 	select MTD_CFI_AMDSTD
 	help
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 5434d8ded015..6ea51e549045 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -14,7 +14,6 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 1adba86474a5..a4c477b9fdd6 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index 46d195fca942..5ab71f0e1bcd 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index d6b2451eab1d..6a589f1e2880 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -16,7 +16,6 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/slab.h>
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index 93c507a6f862..7aa682cd4d7e 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 98bb5d5375d7..cadfbe051873 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -10,7 +10,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 36da518915b5..eb0242e0b2d9 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index d11109762ac5..217c25d7381b 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 10196f5a897d..d597e89f2692 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -138,7 +137,6 @@ static int platram_probe(struct platform_device *pdev)
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (info == NULL) {
-		dev_err(&pdev->dev, "no memory for flash info\n");
 		err = -ENOMEM;
 		goto exit_error;
 	}
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 9aad854fe912..cb4d92eea9fe 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 93525121d69d..146b6047ed2b 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index 3051c4c36240..b7a22a612a46 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -47,7 +47,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 39cc4181f025..b6f1aac3510c 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 5073cbc796d8..0b2ccb68c0d0 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -30,7 +30,6 @@
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
-#include <linux/init.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 90ff447bf043..f1cf503517fd 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -428,6 +428,7 @@ config MTD_NAND_FSL_IFC
 	tristate "NAND support for Freescale IFC controller"
 	depends on MTD_NAND && FSL_SOC
 	select FSL_IFC
+	select MEMORY
 	help
 	  Various Freescale chips e.g P1010, include a NAND Flash machine
 	  with built-in hardware ECC capabilities.
@@ -459,6 +460,8 @@ config MTD_NAND_MXC
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
 	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on HAS_DMA
 	help
 	  Several Renesas SuperH CPU has FLCTL. This option enables support
 	  for NAND Flash using FLCTL.
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 8611eb4b45fc..4936e9e0002f 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index c36e9b84487c..1f719e03c073 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -430,7 +430,7 @@ err_dma:
 	dma_unmap_single(dma_dev->dev, phys_addr, len, dir);
 err_buf:
 	if (err != 0)
-		dev_warn(host->dev, "Fall back to CPU I/O\n");
+		dev_dbg(host->dev, "Fall back to CPU I/O\n");
 	return err;
 }
 
@@ -1659,8 +1659,8 @@ static void nfc_select_chip(struct mtd_info *mtd, int chip)
 		nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE);
 }
 
-static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr,
-		unsigned int *addr1234, unsigned int *cycle0)
+static int nfc_make_addr(struct mtd_info *mtd, int command, int column,
+		int page_addr, unsigned int *addr1234, unsigned int *cycle0)
 {
 	struct nand_chip *chip = mtd->priv;
 
@@ -1674,7 +1674,8 @@ static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr,
 	*addr1234 = 0;
 
 	if (column != -1) {
-		if (chip->options & NAND_BUSWIDTH_16)
+		if (chip->options & NAND_BUSWIDTH_16 &&
+				!nand_opcode_8bits(command))
 			column >>= 1;
 		addr_bytes[acycle++] = column & 0xff;
 		if (mtd->writesize > 512)
@@ -1787,8 +1788,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
 	}
 
 	if (do_addr)
-		acycle = nfc_make_addr(mtd, column, page_addr, &addr1234,
-				&cycle0);
+		acycle = nfc_make_addr(mtd, command, column, page_addr,
+				&addr1234, &cycle0);
 
 	nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
 	nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 2880d888cfc5..bc5c518828d2 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -11,7 +11,6 @@
 
 #include <linux/slab.h>
 #include <linux/gpio.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
@@ -308,7 +307,8 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
 		/* Serially input address */
 		if (column != -1) {
 			/* Adjust columns for 16 bit buswidth */
-			if (this->options & NAND_BUSWIDTH_16)
+			if (this->options & NAND_BUSWIDTH_16 &&
+					!nand_opcode_8bits(command))
 				column >>= 1;
 			ctx->write_byte(mtd, column);
 		}
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 94f55dbde995..b7a24946ca26 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -37,7 +37,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index f2f64addb5e8..4e66726da9aa 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
+	int old_dma;
+	struct nand_buffers *nbuf;
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		err = -ENOMEM;
 		goto out_free_mtd;
 	}
-	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
-					  &cafe->dmaaddr, GFP_KERNEL);
-	if (!cafe->dmabuf) {
-		err = -ENOMEM;
-		goto out_ior;
-	}
-	cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
 
 	cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
 	if (!cafe->rs) {
@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 			  "CAFE NAND", mtd);
 	if (err) {
 		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
-		goto out_free_dma;
+		goto out_ior;
 	}
 
 	/* Disable master reset, enable NAND clock */
@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
 	cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
 
+	/* Enable NAND IRQ in global IRQ mask register */
+	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
+	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
+		cafe_readl(cafe, GLOBAL_CTRL),
+		cafe_readl(cafe, GLOBAL_IRQ_MASK));
+
+	/* Do not use the DMA for the nand_scan_ident() */
+	old_dma = usedma;
+	usedma = 0;
+
+	/* Scan to find existence of the device */
+	if (nand_scan_ident(mtd, 2, NULL)) {
+		err = -ENXIO;
+		goto out_irq;
+	}
+
+	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev,
+				2112 + sizeof(struct nand_buffers) +
+				mtd->writesize + mtd->oobsize,
+				&cafe->dmaaddr, GFP_KERNEL);
+	if (!cafe->dmabuf) {
+		err = -ENOMEM;
+		goto out_irq;
+	}
+	cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112;
+
 	/* Set up DMA address */
 	cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
 	if (sizeof(cafe->dmaaddr) > 4)
@@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
 		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
 
-	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
-	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
-		cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
+	/* this driver does not need the @ecccalc and @ecccode */
+	nbuf->ecccalc = NULL;
+	nbuf->ecccode = NULL;
+	nbuf->databuf = (uint8_t *)(nbuf + 1);
 
-	/* Scan to find existence of the device */
-	if (nand_scan_ident(mtd, 2, NULL)) {
-		err = -ENXIO;
-		goto out_irq;
-	}
+	/* Restore the DMA flag */
+	usedma = old_dma;
 
 	cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
 	if (mtd->writesize == 2048)
@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	} else {
 		printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
 		       mtd->writesize);
-		goto out_irq;
+		goto out_free_dma;
 	}
 	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 	cafe->nand.ecc.size = mtd->writesize;
@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
 	err = nand_scan_tail(mtd);
 	if (err)
-		goto out_irq;
+		goto out_free_dma;
 
 	pci_set_drvdata(pdev, mtd);
 
@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
 	goto out;
 
+ out_free_dma:
+	dma_free_coherent(&cafe->pdev->dev,
+			2112 + sizeof(struct nand_buffers) +
+			mtd->writesize + mtd->oobsize,
+			cafe->dmabuf, cafe->dmaaddr);
  out_irq:
 	/* Disable NAND IRQ in global IRQ mask register */
 	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
- out_free_dma:
-	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
  out_free_mtd:
@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev)
 	nand_release(mtd);
 	free_rs(cafe->rs);
 	pci_iounmap(pdev, cafe->mmio);
-	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+	dma_free_coherent(&cafe->pdev->dev,
+			2112 + sizeof(struct nand_buffers) +
+			mtd->writesize + mtd->oobsize,
+			cafe->dmabuf, cafe->dmaaddr);
 	kfree(mtd);
 }
 
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index a4989ec6292e..4615d79fc93f 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -24,7 +24,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
@@ -746,28 +745,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
 		goto err_clk_enable;
 	}
 
-	/*
-	 * Setup Async configuration register in case we did not boot from
-	 * NAND and so bootloader did not bother to set it up.
-	 */
-	val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
-
-	/* Extended Wait is not valid and Select Strobe mode is not used */
-	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
-	if (info->chip.options & NAND_BUSWIDTH_16)
-		val |= 0x1;
-
-	davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
-
-	ret = 0;
-	if (info->timing)
-		ret = davinci_aemif_setup_timing(info->timing, info->base,
-							info->core_chipsel);
-	if (ret < 0) {
-		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-		goto err;
-	}
-
 	spin_lock_irq(&davinci_nand_lock);
 
 	/* put CSxNAND into NAND mode */
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index fec31d71b84e..b9b4db607850 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -698,7 +698,8 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
 		/* Serially input address */
 		if (column != -1) {
 			/* Adjust columns for 16 bit buswidth */
-			if (this->options & NAND_BUSWIDTH_16)
+			if (this->options & NAND_BUSWIDTH_16 &&
+					!nand_opcode_8bits(command))
 				column >>= 1;
 			WriteDOC(column, docptr, Mplus_FlashAddress);
 		}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index bcf60800c3ce..ec549cd9849f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -24,7 +24,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 90ca7e75d6f0..cb45d2f8e208 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -22,7 +22,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
@@ -30,7 +29,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand_ecc.h>
-#include <asm/fsl_ifc.h>
+#include <linux/fsl_ifc.h>
 
 #define FSL_IFC_V1_1_0	0x01010000
 #define ERR_BYTE		0xFF /* Value returned for read
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 8e6148aa4539..117ce333fdd4 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -18,7 +18,6 @@
 
 #include <linux/kernel.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 31ee7cfbc12b..e78841a2dcc3 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -30,7 +30,6 @@
 #include <linux/gfp.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index e9a4835c4dd9..dba262bf766f 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -1501,6 +1501,8 @@ static int mxcnd_probe(struct platform_device *pdev)
 	init_completion(&host->op_completion);
 
 	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq < 0)
+		return host->irq;
 
 	/*
 	 * Use host->devtype_data->irq_control() here instead of irq_control()
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9715a7ba164a..62e5d26464f0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -589,7 +589,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
 	/* Serially input address */
 	if (column != -1) {
 		/* Adjust columns for 16 bit buswidth */
-		if (chip->options & NAND_BUSWIDTH_16)
+		if (chip->options & NAND_BUSWIDTH_16 &&
+				!nand_opcode_8bits(command))
 			column >>= 1;
 		chip->cmd_ctrl(mtd, column, ctrl);
 		ctrl &= ~NAND_CTRL_CHANGE;
@@ -680,7 +681,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 		/* Serially input address */
 		if (column != -1) {
 			/* Adjust columns for 16 bit buswidth */
-			if (chip->options & NAND_BUSWIDTH_16)
+			if (chip->options & NAND_BUSWIDTH_16 &&
+					!nand_opcode_8bits(command))
 				column >>= 1;
 			chip->cmd_ctrl(mtd, column, ctrl);
 			ctrl &= ~NAND_CTRL_CHANGE;
@@ -2000,7 +2002,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
 			oob += chip->ecc.prepad;
 		}
 
-		chip->read_buf(mtd, oob, eccbytes);
+		chip->write_buf(mtd, oob, eccbytes);
 		oob += eccbytes;
 
 		if (chip->ecc.postpad) {
@@ -3063,7 +3065,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 					int *busw)
 {
 	struct nand_onfi_params *p = &chip->onfi_params;
-	int i;
+	int i, j;
 	int val;
 
 	/* Try ONFI for unknown chip or LP */
@@ -3072,18 +3074,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
 		return 0;
 
-	/*
-	 * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not
-	 * with NAND_BUSWIDTH_16
-	 */
-	if (chip->options & NAND_BUSWIDTH_16) {
-		pr_err("ONFI cannot be probed in 16-bit mode; aborting\n");
-		return 0;
-	}
-
 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
 	for (i = 0; i < 3; i++) {
-		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
+		for (j = 0; j < sizeof(*p); j++)
+			((uint8_t *)p)[j] = chip->read_byte(mtd);
 		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
 				le16_to_cpu(p->crc)) {
 			break;
@@ -3169,6 +3163,87 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /*
+ * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
+ */
+static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
+					int *busw)
+{
+	struct nand_jedec_params *p = &chip->jedec_params;
+	struct jedec_ecc_info *ecc;
+	int val;
+	int i, j;
+
+	/* Try JEDEC for unknown chip or LP */
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
+	if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' ||
+		chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' ||
+		chip->read_byte(mtd) != 'C')
+		return 0;
+
+	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1);
+	for (i = 0; i < 3; i++) {
+		for (j = 0; j < sizeof(*p); j++)
+			((uint8_t *)p)[j] = chip->read_byte(mtd);
+
+		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) ==
+				le16_to_cpu(p->crc))
+			break;
+	}
+
+	if (i == 3) {
+		pr_err("Could not find valid JEDEC parameter page; aborting\n");
+		return 0;
+	}
+
+	/* Check version */
+	val = le16_to_cpu(p->revision);
+	if (val & (1 << 2))
+		chip->jedec_version = 10;
+	else if (val & (1 << 1))
+		chip->jedec_version = 1; /* vendor specific version */
+
+	if (!chip->jedec_version) {
+		pr_info("unsupported JEDEC version: %d\n", val);
+		return 0;
+	}
+
+	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
+	sanitize_string(p->model, sizeof(p->model));
+	if (!mtd->name)
+		mtd->name = p->model;
+
+	mtd->writesize = le32_to_cpu(p->byte_per_page);
+
+	/* Please reference to the comment for nand_flash_detect_onfi. */
+	mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+	mtd->erasesize *= mtd->writesize;
+
+	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+
+	/* Please reference to the comment for nand_flash_detect_onfi. */
+	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
+	chip->bits_per_cell = p->bits_per_cell;
+
+	if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS)
+		*busw = NAND_BUSWIDTH_16;
+	else
+		*busw = 0;
+
+	/* ECC info */
+	ecc = &p->ecc_info[0];
+
+	if (ecc->codeword_size >= 9) {
+		chip->ecc_strength_ds = ecc->ecc_bits;
+		chip->ecc_step_ds = 1 << ecc->codeword_size;
+	} else {
+		pr_warn("Invalid codeword size\n");
+	}
+
+	return 1;
+}
+
+/*
  * nand_id_has_period - Check if an ID string has a given wraparound period
  * @id_data: the ID string
  * @arrlen: the length of the @id_data array
@@ -3533,6 +3608,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		/* Check is chip is ONFI compliant */
 		if (nand_flash_detect_onfi(mtd, chip, &busw))
 			goto ident_done;
+
+		/* Check if the chip is JEDEC compliant */
+		if (nand_flash_detect_jedec(mtd, chip, &busw))
+			goto ident_done;
 	}
 
 	if (!type->name)
@@ -3612,8 +3691,17 @@ ident_done:
 
 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 		*maf_id, *dev_id);
-	pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
-		chip->onfi_version ? chip->onfi_params.model : type->name);
+
+	if (chip->onfi_version)
+		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+				chip->onfi_params.model);
+	else if (chip->jedec_version)
+		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+				chip->jedec_params.model);
+	else
+		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+				type->name);
+
 	pr_info("%dMiB, %s, page size: %d, OOB size: %d\n",
 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
 		mtd->writesize, mtd->oobsize);
@@ -3696,15 +3784,26 @@ int nand_scan_tail(struct mtd_info *mtd)
 	int i;
 	struct nand_chip *chip = mtd->priv;
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	struct nand_buffers *nbuf;
 
 	/* New bad blocks should be marked in OOB, flash-based BBT, or both */
 	BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
 			!(chip->bbt_options & NAND_BBT_USE_FLASH));
 
-	if (!(chip->options & NAND_OWN_BUFFERS))
-		chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
-	if (!chip->buffers)
-		return -ENOMEM;
+	if (!(chip->options & NAND_OWN_BUFFERS)) {
+		nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
+				+ mtd->oobsize * 3, GFP_KERNEL);
+		if (!nbuf)
+			return -ENOMEM;
+		nbuf->ecccalc = (uint8_t *)(nbuf + 1);
+		nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
+		nbuf->databuf = nbuf->ecccode + mtd->oobsize;
+
+		chip->buffers = nbuf;
+	} else {
+		if (!chip->buffers)
+			return -ENOMEM;
+	}
 
 	/* Set the internal oob buffer location, just after the page data */
 	chip->oob_poi = chip->buffers->databuf + mtd->writesize;
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index daa2faacd7d0..3d7c89fc1031 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -43,6 +43,9 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"TC58NVG6D2 64G 3.3V 8-bit",
 		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },
 		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },
+	{"SDTNRGAMA 64G 3.3V 8-bit",
+		{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} },
+		  SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index 9ee09a8177c6..e8a5fffd6ab2 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -152,7 +151,8 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
 	if (column != -1 || page_addr != -1) {
 
 		if (column != -1) {
-			if (chip->options & NAND_BUSWIDTH_16)
+			if (chip->options & NAND_BUSWIDTH_16 &&
+					!nand_opcode_8bits(command))
 				column >>= 1;
 			write_addr_reg(nand, column);
 			write_addr_reg(nand, column >> 8 | ENDADDR);
@@ -225,7 +225,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand)
 	val = __raw_readl(nand->reg + REG_FMICSR);
 
 	if (!(val & NAND_EN))
-		__raw_writel(val | NAND_EN, REG_FMICSR);
+		__raw_writel(val | NAND_EN, nand->reg + REG_FMICSR);
 
 	val = __raw_readl(nand->reg + REG_SMCSR);
 
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 90f871acb0ef..2c98f9da7471 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -23,7 +23,6 @@
 #undef DEBUG
 
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index f0918e7411d9..79acbb8691b5 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -29,7 +29,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index d72783dd7b96..c0670237e7a2 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -897,7 +897,7 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
 		if (!flctl->qos_request) {
 			ret = dev_pm_qos_add_request(&flctl->pdev->dev,
 							&flctl->pm_qos,
-							DEV_PM_QOS_LATENCY,
+							DEV_PM_QOS_RESUME_LATENCY,
 							100);
 			if (ret < 0)
 				dev_err(&flctl->pdev->dev,
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 8e1919b6f074..093c29ac1a13 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 6547c84afc3a..d945473c3882 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -25,7 +25,6 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 1de33b5d3903..e886d7af868f 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -3995,11 +3994,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	/* Allocate buffers, if necessary */
 	if (!this->page_buf) {
 		this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
-		if (!this->page_buf) {
-			printk(KERN_ERR "%s: Can't allocate page_buf\n",
-				__func__);
+		if (!this->page_buf)
 			return -ENOMEM;
-		}
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
 		this->verify_buf = kzalloc(mtd->writesize, GFP_KERNEL);
 		if (!this->verify_buf) {
@@ -4012,8 +4008,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (!this->oob_buf) {
 		this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
 		if (!this->oob_buf) {
-			printk(KERN_ERR "%s: Can't allocate oob_buf\n",
-				__func__);
 			if (this->options & ONENAND_PAGEBUF_ALLOC) {
 				this->options &= ~ONENAND_PAGEBUF_ALLOC;
 				kfree(this->page_buf);
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index df7400dd4df8..b1a792fd1c23 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -872,10 +872,8 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 
 	size = sizeof(struct mtd_info) + sizeof(struct onenand_chip);
 	mtd = kzalloc(size, GFP_KERNEL);
-	if (!mtd) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!mtd)
 		return -ENOMEM;
-	}
 
 	onenand = kzalloc(sizeof(struct s3c_onenand), GFP_KERNEL);
 	if (!onenand) {
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 233b946e5d66..d1cbf26db2c0 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -602,8 +602,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
 	if (rc) {
 		printk(KERN_ERR PREFIX "error writing '%s' at "
 			"0x%lx\n", part->mbd.mtd->name, addr);
-		if (rc)
-			goto err;
+		goto err;
 	}
 	if (block == part->current_block)
 		part->header_cache[offset + HEADER_MAP_OFFSET] = del;
@@ -675,8 +674,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
 	if (rc) {
 		printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
 				part->mbd.mtd->name, addr);
-		if (rc)
-			goto err;
+		goto err;
 	}
 
 	part->sector_map[sector] = addr;
@@ -695,8 +693,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
 	if (rc) {
 		printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
 				part->mbd.mtd->name, addr);
-		if (rc)
-			goto err;
+		goto err;
 	}
 	block->used_sectors++;
 	block->free_sectors--;
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 4b8e89583f2a..cf49c22673b9 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -59,15 +59,12 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
 	struct attribute_group *attr_group;
 	struct attribute **attributes;
 	struct sm_sysfs_attribute *vendor_attribute;
+	char *vendor;
 
-	int vendor_len = strnlen(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET,
-					SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET);
-
-	char *vendor = kmalloc(vendor_len, GFP_KERNEL);
+	vendor = kstrndup(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET,
+			  SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET, GFP_KERNEL);
 	if (!vendor)
 		goto error1;
-	memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len);
-	vendor[vendor_len] = 0;
 
 	/* Initialize sysfs attributes */
 	vendor_attribute =
@@ -78,7 +75,7 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
 	sysfs_attr_init(&vendor_attribute->dev_attr.attr);
 
 	vendor_attribute->data = vendor;
-	vendor_attribute->len = vendor_len;
+	vendor_attribute->len = strlen(vendor);
 	vendor_attribute->dev_attr.attr.name = "vendor";
 	vendor_attribute->dev_attr.attr.mode = S_IRUGO;
 	vendor_attribute->dev_attr.show = sm_attr_show;
diff --git a/drivers/mtd/tests/mtd_test.c b/drivers/mtd/tests/mtd_test.c
index c818a63532e7..111ee46a7428 100644
--- a/drivers/mtd/tests/mtd_test.c
+++ b/drivers/mtd/tests/mtd_test.c
@@ -1,6 +1,5 @@
 #define pr_fmt(fmt) "mtd_test: " fmt
 
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/printk.h>
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 36663af56d89..783fb186d876 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -87,4 +87,19 @@ config MTD_UBI_GLUEBI
 	   work on top of UBI. Do not enable this unless you use legacy
 	   software.
 
+config MTD_UBI_BLOCK
+	bool "Read-only block devices on top of UBI volumes"
+	default n
+	help
+	   This option enables read-only UBI block devices support. UBI block
+	   devices will be layered on top of UBI volumes, which means that the
+	   UBI driver will transparently handle things like bad eraseblocks and
+	   bit-flips. You can put any block-oriented file system on top of UBI
+	   volumes in read-only mode (e.g., ext4), but it is probably most
+	   practical for read-only file systems, like squashfs.
+
+	   When selected, this feature will be built in the UBI driver.
+
+	   If in doubt, say "N".
+
 endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index b46b0c978581..4e3c3d70d8c3 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o
 ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
 ubi-y += misc.o debug.o
 ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o
+ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o
 
 obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
new file mode 100644
index 000000000000..cea7d1cf9d04
--- /dev/null
+++ b/drivers/mtd/ubi/block.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright (c) 2014 Ezequiel Garcia
+ * Copyright (c) 2011 Free Electrons
+ *
+ * Driver parameter handling strongly based on drivers/mtd/ubi/build.c
+ *   Copyright (c) International Business Machines Corp., 2006
+ *   Copyright (c) Nokia Corporation, 2007
+ *   Authors: Artem Bityutskiy, Frank Haverkamp
+ *
+ * This program is free software; 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 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.
+ */
+
+/*
+ * Read-only block devices on top of UBI volumes
+ *
+ * A simple implementation to allow a block device to be layered on top of a
+ * UBI volume. The implementation is provided by creating a static 1-to-1
+ * mapping between the block device and the UBI volume.
+ *
+ * The addressed byte is obtained from the addressed block sector, which is
+ * mapped linearly into the corresponding LEB:
+ *
+ *   LEB number = addressed byte / LEB size
+ *
+ * This feature is compiled in the UBI core, and adds a new 'block' parameter
+ * to allow early block device attaching. Runtime  block attach/detach for UBI
+ * volumes is provided through two new UBI ioctls: UBI_IOCVOLATTBLK and
+ * UBI_IOCVOLDETBLK.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/ubi.h>
+#include <linux/workqueue.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <asm/div64.h>
+
+#include "ubi-media.h"
+#include "ubi.h"
+
+/* Maximum number of supported devices */
+#define UBIBLOCK_MAX_DEVICES 32
+
+/* Maximum length of the 'block=' parameter */
+#define UBIBLOCK_PARAM_LEN 63
+
+/* Maximum number of comma-separated items in the 'block=' parameter */
+#define UBIBLOCK_PARAM_COUNT 2
+
+struct ubiblock_param {
+	int ubi_num;
+	int vol_id;
+	char name[UBIBLOCK_PARAM_LEN+1];
+};
+
+/* Numbers of elements set in the @ubiblock_param array */
+static int ubiblock_devs __initdata;
+
+/* MTD devices specification parameters */
+static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
+
+struct ubiblock {
+	struct ubi_volume_desc *desc;
+	int ubi_num;
+	int vol_id;
+	int refcnt;
+	int leb_size;
+
+	struct gendisk *gd;
+	struct request_queue *rq;
+
+	struct workqueue_struct *wq;
+	struct work_struct work;
+
+	struct mutex dev_mutex;
+	spinlock_t queue_lock;
+	struct list_head list;
+};
+
+/* Linked list of all ubiblock instances */
+static LIST_HEAD(ubiblock_devices);
+static DEFINE_MUTEX(devices_mutex);
+static int ubiblock_major;
+
+static int __init ubiblock_set_param(const char *val,
+				     const struct kernel_param *kp)
+{
+	int i, ret;
+	size_t len;
+	struct ubiblock_param *param;
+	char buf[UBIBLOCK_PARAM_LEN];
+	char *pbuf = &buf[0];
+	char *tokens[UBIBLOCK_PARAM_COUNT];
+
+	if (!val)
+		return -EINVAL;
+
+	len = strnlen(val, UBIBLOCK_PARAM_LEN);
+	if (len == 0) {
+		ubi_warn("block: empty 'block=' parameter - ignored\n");
+		return 0;
+	}
+
+	if (len == UBIBLOCK_PARAM_LEN) {
+		ubi_err("block: parameter \"%s\" is too long, max. is %d\n",
+			val, UBIBLOCK_PARAM_LEN);
+		return -EINVAL;
+	}
+
+	strcpy(buf, val);
+
+	/* Get rid of the final newline */
+	if (buf[len - 1] == '\n')
+		buf[len - 1] = '\0';
+
+	for (i = 0; i < UBIBLOCK_PARAM_COUNT; i++)
+		tokens[i] = strsep(&pbuf, ",");
+
+	param = &ubiblock_param[ubiblock_devs];
+	if (tokens[1]) {
+		/* Two parameters: can be 'ubi, vol_id' or 'ubi, vol_name' */
+		ret = kstrtoint(tokens[0], 10, &param->ubi_num);
+		if (ret < 0)
+			return -EINVAL;
+
+		/* Second param can be a number or a name */
+		ret = kstrtoint(tokens[1], 10, &param->vol_id);
+		if (ret < 0) {
+			param->vol_id = -1;
+			strcpy(param->name, tokens[1]);
+		}
+
+	} else {
+		/* One parameter: must be device path */
+		strcpy(param->name, tokens[0]);
+		param->ubi_num = -1;
+		param->vol_id = -1;
+	}
+
+	ubiblock_devs++;
+
+	return 0;
+}
+
+static const struct kernel_param_ops ubiblock_param_ops = {
+	.set    = ubiblock_set_param,
+};
+module_param_cb(block, &ubiblock_param_ops, NULL, 0);
+MODULE_PARM_DESC(block, "Attach block devices to UBI volumes. Parameter format: block=<path|dev,num|dev,name>.\n"
+			"Multiple \"block\" parameters may be specified.\n"
+			"UBI volumes may be specified by their number, name, or path to the device node.\n"
+			"Examples\n"
+			"Using the UBI volume path:\n"
+			"ubi.block=/dev/ubi0_0\n"
+			"Using the UBI device, and the volume name:\n"
+			"ubi.block=0,rootfs\n"
+			"Using both UBI device number and UBI volume number:\n"
+			"ubi.block=0,0\n");
+
+static struct ubiblock *find_dev_nolock(int ubi_num, int vol_id)
+{
+	struct ubiblock *dev;
+
+	list_for_each_entry(dev, &ubiblock_devices, list)
+		if (dev->ubi_num == ubi_num && dev->vol_id == vol_id)
+			return dev;
+	return NULL;
+}
+
+static int ubiblock_read_to_buf(struct ubiblock *dev, char *buffer,
+				int leb, int offset, int len)
+{
+	int ret;
+
+	ret = ubi_read(dev->desc, leb, buffer, offset, len);
+	if (ret) {
+		ubi_err("%s ubi_read error %d",
+			dev->gd->disk_name, ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int ubiblock_read(struct ubiblock *dev, char *buffer,
+			 sector_t sec, int len)
+{
+	int ret, leb, offset;
+	int bytes_left = len;
+	int to_read = len;
+	loff_t pos = sec << 9;
+
+	/* Get LEB:offset address to read from */
+	offset = do_div(pos, dev->leb_size);
+	leb = pos;
+
+	while (bytes_left) {
+		/*
+		 * We can only read one LEB at a time. Therefore if the read
+		 * length is larger than one LEB size, we split the operation.
+		 */
+		if (offset + to_read > dev->leb_size)
+			to_read = dev->leb_size - offset;
+
+		ret = ubiblock_read_to_buf(dev, buffer, leb, offset, to_read);
+		if (ret)
+			return ret;
+
+		buffer += to_read;
+		bytes_left -= to_read;
+		to_read = bytes_left;
+		leb += 1;
+		offset = 0;
+	}
+	return 0;
+}
+
+static int do_ubiblock_request(struct ubiblock *dev, struct request *req)
+{
+	int len, ret;
+	sector_t sec;
+
+	if (req->cmd_type != REQ_TYPE_FS)
+		return -EIO;
+
+	if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
+	    get_capacity(req->rq_disk))
+		return -EIO;
+
+	if (rq_data_dir(req) != READ)
+		return -ENOSYS; /* Write not implemented */
+
+	sec = blk_rq_pos(req);
+	len = blk_rq_cur_bytes(req);
+
+	/*
+	 * Let's prevent the device from being removed while we're doing I/O
+	 * work. Notice that this means we serialize all the I/O operations,
+	 * but it's probably of no impact given the NAND core serializes
+	 * flash access anyway.
+	 */
+	mutex_lock(&dev->dev_mutex);
+	ret = ubiblock_read(dev, req->buffer, sec, len);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static void ubiblock_do_work(struct work_struct *work)
+{
+	struct ubiblock *dev =
+		container_of(work, struct ubiblock, work);
+	struct request_queue *rq = dev->rq;
+	struct request *req;
+	int res;
+
+	spin_lock_irq(rq->queue_lock);
+
+	req = blk_fetch_request(rq);
+	while (req) {
+
+		spin_unlock_irq(rq->queue_lock);
+		res = do_ubiblock_request(dev, req);
+		spin_lock_irq(rq->queue_lock);
+
+		/*
+		 * If we're done with this request,
+		 * we need to fetch a new one
+		 */
+		if (!__blk_end_request_cur(req, res))
+			req = blk_fetch_request(rq);
+	}
+
+	spin_unlock_irq(rq->queue_lock);
+}
+
+static void ubiblock_request(struct request_queue *rq)
+{
+	struct ubiblock *dev;
+	struct request *req;
+
+	dev = rq->queuedata;
+
+	if (!dev)
+		while ((req = blk_fetch_request(rq)) != NULL)
+			__blk_end_request_all(req, -ENODEV);
+	else
+		queue_work(dev->wq, &dev->work);
+}
+
+static int ubiblock_open(struct block_device *bdev, fmode_t mode)
+{
+	struct ubiblock *dev = bdev->bd_disk->private_data;
+	int ret;
+
+	mutex_lock(&dev->dev_mutex);
+	if (dev->refcnt > 0) {
+		/*
+		 * The volume is already open, just increase the reference
+		 * counter.
+		 */
+		goto out_done;
+	}
+
+	/*
+	 * We want users to be aware they should only mount us as read-only.
+	 * It's just a paranoid check, as write requests will get rejected
+	 * in any case.
+	 */
+	if (mode & FMODE_WRITE) {
+		ret = -EPERM;
+		goto out_unlock;
+	}
+
+	dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY);
+	if (IS_ERR(dev->desc)) {
+		ubi_err("%s failed to open ubi volume %d_%d",
+			dev->gd->disk_name, dev->ubi_num, dev->vol_id);
+		ret = PTR_ERR(dev->desc);
+		dev->desc = NULL;
+		goto out_unlock;
+	}
+
+out_done:
+	dev->refcnt++;
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+
+out_unlock:
+	mutex_unlock(&dev->dev_mutex);
+	return ret;
+}
+
+static void ubiblock_release(struct gendisk *gd, fmode_t mode)
+{
+	struct ubiblock *dev = gd->private_data;
+
+	mutex_lock(&dev->dev_mutex);
+	dev->refcnt--;
+	if (dev->refcnt == 0) {
+		ubi_close_volume(dev->desc);
+		dev->desc = NULL;
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
+static int ubiblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	/* Some tools might require this information */
+	geo->heads = 1;
+	geo->cylinders = 1;
+	geo->sectors = get_capacity(bdev->bd_disk);
+	geo->start = 0;
+	return 0;
+}
+
+static const struct block_device_operations ubiblock_ops = {
+	.owner = THIS_MODULE,
+	.open = ubiblock_open,
+	.release = ubiblock_release,
+	.getgeo	= ubiblock_getgeo,
+};
+
+int ubiblock_add(struct ubi_volume_info *vi)
+{
+	struct ubiblock *dev;
+	struct gendisk *gd;
+	int disk_capacity;
+	int ret;
+
+	/* Check that the volume isn't already handled */
+	mutex_lock(&devices_mutex);
+	if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
+		mutex_unlock(&devices_mutex);
+		return -EEXIST;
+	}
+	mutex_unlock(&devices_mutex);
+
+	dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	mutex_init(&dev->dev_mutex);
+
+	dev->ubi_num = vi->ubi_num;
+	dev->vol_id = vi->vol_id;
+	dev->leb_size = vi->usable_leb_size;
+
+	/* Initialize the gendisk of this ubiblock device */
+	gd = alloc_disk(1);
+	if (!gd) {
+		ubi_err("block: alloc_disk failed");
+		ret = -ENODEV;
+		goto out_free_dev;
+	}
+
+	gd->fops = &ubiblock_ops;
+	gd->major = ubiblock_major;
+	gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+	gd->private_data = dev;
+	sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
+	disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
+	set_capacity(gd, disk_capacity);
+	dev->gd = gd;
+
+	spin_lock_init(&dev->queue_lock);
+	dev->rq = blk_init_queue(ubiblock_request, &dev->queue_lock);
+	if (!dev->rq) {
+		ubi_err("block: blk_init_queue failed");
+		ret = -ENODEV;
+		goto out_put_disk;
+	}
+
+	dev->rq->queuedata = dev;
+	dev->gd->queue = dev->rq;
+
+	/*
+	 * Create one workqueue per volume (per registered block device).
+	 * Rembember workqueues are cheap, they're not threads.
+	 */
+	dev->wq = alloc_workqueue(gd->disk_name, 0, 0);
+	if (!dev->wq)
+		goto out_free_queue;
+	INIT_WORK(&dev->work, ubiblock_do_work);
+
+	mutex_lock(&devices_mutex);
+	list_add_tail(&dev->list, &ubiblock_devices);
+	mutex_unlock(&devices_mutex);
+
+	/* Must be the last step: anyone can call file ops from now on */
+	add_disk(dev->gd);
+	ubi_msg("%s created from ubi%d:%d(%s)",
+		dev->gd->disk_name, dev->ubi_num, dev->vol_id, vi->name);
+	return 0;
+
+out_free_queue:
+	blk_cleanup_queue(dev->rq);
+out_put_disk:
+	put_disk(dev->gd);
+out_free_dev:
+	kfree(dev);
+
+	return ret;
+}
+
+static void ubiblock_cleanup(struct ubiblock *dev)
+{
+	del_gendisk(dev->gd);
+	blk_cleanup_queue(dev->rq);
+	ubi_msg("%s released", dev->gd->disk_name);
+	put_disk(dev->gd);
+}
+
+int ubiblock_del(struct ubi_volume_info *vi)
+{
+	struct ubiblock *dev;
+
+	mutex_lock(&devices_mutex);
+	dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
+	if (!dev) {
+		mutex_unlock(&devices_mutex);
+		return -ENODEV;
+	}
+
+	/* Found a device, let's lock it so we can check if it's busy */
+	mutex_lock(&dev->dev_mutex);
+	if (dev->refcnt > 0) {
+		mutex_unlock(&dev->dev_mutex);
+		mutex_unlock(&devices_mutex);
+		return -EBUSY;
+	}
+
+	/* Remove from device list */
+	list_del(&dev->list);
+	mutex_unlock(&devices_mutex);
+
+	/* Flush pending work and stop this workqueue */
+	destroy_workqueue(dev->wq);
+
+	ubiblock_cleanup(dev);
+	mutex_unlock(&dev->dev_mutex);
+	kfree(dev);
+	return 0;
+}
+
+static void ubiblock_resize(struct ubi_volume_info *vi)
+{
+	struct ubiblock *dev;
+	int disk_capacity;
+
+	/*
+	 * Need to lock the device list until we stop using the device,
+	 * otherwise the device struct might get released in 'ubiblock_del()'.
+	 */
+	mutex_lock(&devices_mutex);
+	dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
+	if (!dev) {
+		mutex_unlock(&devices_mutex);
+		return;
+	}
+
+	mutex_lock(&dev->dev_mutex);
+	disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
+	set_capacity(dev->gd, disk_capacity);
+	ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
+	mutex_unlock(&dev->dev_mutex);
+	mutex_unlock(&devices_mutex);
+}
+
+static int ubiblock_notify(struct notifier_block *nb,
+			 unsigned long notification_type, void *ns_ptr)
+{
+	struct ubi_notification *nt = ns_ptr;
+
+	switch (notification_type) {
+	case UBI_VOLUME_ADDED:
+		/*
+		 * We want to enforce explicit block device attaching for
+		 * volumes, so when a volume is added we do nothing.
+		 */
+		break;
+	case UBI_VOLUME_REMOVED:
+		ubiblock_del(&nt->vi);
+		break;
+	case UBI_VOLUME_RESIZED:
+		ubiblock_resize(&nt->vi);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block ubiblock_notifier = {
+	.notifier_call = ubiblock_notify,
+};
+
+static struct ubi_volume_desc * __init
+open_volume_desc(const char *name, int ubi_num, int vol_id)
+{
+	if (ubi_num == -1)
+		/* No ubi num, name must be a vol device path */
+		return ubi_open_volume_path(name, UBI_READONLY);
+	else if (vol_id == -1)
+		/* No vol_id, must be vol_name */
+		return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
+	else
+		return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
+}
+
+static int __init ubiblock_attach_from_param(void)
+{
+	int i, ret;
+	struct ubiblock_param *p;
+	struct ubi_volume_desc *desc;
+	struct ubi_volume_info vi;
+
+	for (i = 0; i < ubiblock_devs; i++) {
+		p = &ubiblock_param[i];
+
+		desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
+		if (IS_ERR(desc)) {
+			ubi_err("block: can't open volume, err=%ld\n",
+				PTR_ERR(desc));
+			ret = PTR_ERR(desc);
+			break;
+		}
+
+		ubi_get_volume_info(desc, &vi);
+		ubi_close_volume(desc);
+
+		ret = ubiblock_add(&vi);
+		if (ret) {
+			ubi_err("block: can't add '%s' volume, err=%d\n",
+				vi.name, ret);
+			break;
+		}
+	}
+	return ret;
+}
+
+static void ubiblock_detach_all(void)
+{
+	struct ubiblock *next;
+	struct ubiblock *dev;
+
+	list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
+		/* Flush pending work and stop workqueue */
+		destroy_workqueue(dev->wq);
+		/* The module is being forcefully removed */
+		WARN_ON(dev->desc);
+		/* Remove from device list */
+		list_del(&dev->list);
+		ubiblock_cleanup(dev);
+		kfree(dev);
+	}
+}
+
+int __init ubiblock_init(void)
+{
+	int ret;
+
+	ubiblock_major = register_blkdev(0, "ubiblock");
+	if (ubiblock_major < 0)
+		return ubiblock_major;
+
+	/* Attach block devices from 'block=' module param */
+	ret = ubiblock_attach_from_param();
+	if (ret)
+		goto err_detach;
+
+	/*
+	 * Block devices needs to be attached to volumes explicitly
+	 * upon user request. So we ignore existing volumes.
+	 */
+	ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
+	if (ret)
+		goto err_unreg;
+	return 0;
+
+err_unreg:
+	unregister_blkdev(ubiblock_major, "ubiblock");
+err_detach:
+	ubiblock_detach_all();
+	return ret;
+}
+
+void __exit ubiblock_exit(void)
+{
+	ubi_unregister_volume_notifier(&ubiblock_notifier);
+	ubiblock_detach_all();
+	unregister_blkdev(ubiblock_major, "ubiblock");
+}
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 57deae961429..6e30a3c280d0 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1298,6 +1298,15 @@ static int __init ubi_init(void)
 		}
 	}
 
+	err = ubiblock_init();
+	if (err) {
+		ubi_err("block: cannot initialize, error %d", err);
+
+		/* See comment above re-ubi_is_module(). */
+		if (ubi_is_module())
+			goto out_detach;
+	}
+
 	return 0;
 
 out_detach:
@@ -1326,6 +1335,8 @@ static void __exit ubi_exit(void)
 {
 	int i;
 
+	ubiblock_exit();
+
 	for (i = 0; i < UBI_MAX_DEVICES; i++)
 		if (ubi_devices[i]) {
 			mutex_lock(&ubi_devices_mutex);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 8ca49f2043e4..39d377489c29 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -561,6 +561,26 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
 		break;
 	}
 
+	/* Attach a block device to an UBI volume */
+	case UBI_IOCVOLATTBLK:
+	{
+		struct ubi_volume_info vi;
+
+		ubi_get_volume_info(desc, &vi);
+		err = ubiblock_add(&vi);
+		break;
+	}
+
+	/* Dettach a block device from an UBI volume */
+	case UBI_IOCVOLDETBLK:
+	{
+		struct ubi_volume_info vi;
+
+		ubi_get_volume_info(desc, &vi);
+		err = ubiblock_del(&vi);
+		break;
+	}
+
 	default:
 		err = -ENOTTY;
 		break;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8ea6297a208f..7a8c96fd457f 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -22,7 +22,6 @@
 #ifndef __UBI_UBI_H__
 #define __UBI_UBI_H__
 
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
@@ -864,6 +863,20 @@ int ubi_update_fastmap(struct ubi_device *ubi);
 int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
 		     int fm_anchor);
 
+/* block.c */
+#ifdef CONFIG_MTD_UBI_BLOCK
+int ubiblock_init(void);
+void ubiblock_exit(void);
+int ubiblock_add(struct ubi_volume_info *vi);
+int ubiblock_del(struct ubi_volume_info *vi);
+#else
+static inline int ubiblock_init(void) { return 0; }
+static inline void ubiblock_exit(void) {}
+static inline int ubiblock_add(struct ubi_volume_info *vi) { return -ENOTTY; }
+static inline int ubiblock_del(struct ubi_volume_info *vi) { return -ENOTTY; }
+#endif
+
+
 /*
  * ubi_rb_for_each_entry - walk an RB-tree.
  * @rb: a pointer to type 'struct rb_node' to use as a loop counter
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6d20fbde8d43..a2ef3f72de88 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -181,7 +181,7 @@ static inline int __agg_has_partner(struct aggregator *agg)
  */
 static inline void __disable_port(struct port *port)
 {
-	bond_set_slave_inactive_flags(port->slave);
+	bond_set_slave_inactive_flags(port->slave, BOND_SLAVE_NOTIFY_LATER);
 }
 
 /**
@@ -193,7 +193,7 @@ static inline void __enable_port(struct port *port)
 	struct slave *slave = port->slave;
 
 	if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev))
-		bond_set_slave_active_flags(slave);
+		bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER);
 }
 
 /**
@@ -768,11 +768,11 @@ static int ad_lacpdu_send(struct port *port)
 
 	lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
 
-	memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
+	ether_addr_copy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr);
 	/* Note: source address is set to be the member's PERMANENT address,
 	 * because we use it to identify loopback lacpdus in receive.
 	 */
-	memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
+	ether_addr_copy(lacpdu_header->hdr.h_source, slave->perm_hwaddr);
 	lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
 
 	lacpdu_header->lacpdu = port->lacpdu;
@@ -810,11 +810,11 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
 
 	marker_header = (struct bond_marker_header *)skb_put(skb, length);
 
-	memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
+	ether_addr_copy(marker_header->hdr.h_dest, lacpdu_mcast_addr);
 	/* Note: source address is set to be the member's PERMANENT address,
 	 * because we use it to identify loopback MARKERs in receive.
 	 */
-	memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
+	ether_addr_copy(marker_header->hdr.h_source, slave->perm_hwaddr);
 	marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
 
 	marker_header->marker = *marker;
@@ -1079,7 +1079,8 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 			/* detect loopback situation */
 			if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
 					      &(port->actor_system))) {
-				pr_err("%s: An illegal loopback occurred on adapter (%s).\nCheck the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
+				pr_err("%s: An illegal loopback occurred on adapter (%s)\n"
+				       "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
 				       port->slave->bond->dev->name,
 				       port->slave->dev->name);
 				return;
@@ -1948,7 +1949,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
 			 * new aggregator
 			 */
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n",
+				pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n",
 					 aggregator->aggregator_identifier,
 					 new_aggregator->aggregator_identifier);
 
@@ -2062,6 +2063,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
 	struct list_head *iter;
 	struct slave *slave;
 	struct port *port;
+	bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
 
 	read_lock(&bond->lock);
 	rcu_read_lock();
@@ -2119,8 +2121,19 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
 	}
 
 re_arm:
+	bond_for_each_slave_rcu(bond, slave, iter) {
+		if (slave->should_notify) {
+			should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
+			break;
+		}
+	}
 	rcu_read_unlock();
 	read_unlock(&bond->lock);
+
+	if (should_notify_rtnl && rtnl_trylock()) {
+		bond_slave_state_notify(bond);
+		rtnl_unlock();
+	}
 	queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
 }
 
@@ -2298,9 +2311,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 		port->actor_oper_port_key = (port->actor_admin_port_key &=
 					     ~AD_SPEED_KEY_BITS);
 	}
-	pr_debug("Port %d changed link status to %s",
-		port->actor_port_number,
-		(link == BOND_LINK_UP) ? "UP" : "DOWN");
+	pr_debug("Port %d changed link status to %s\n",
+		 port->actor_port_number,
+		 link == BOND_LINK_UP ? "UP" : "DOWN");
 	/* there is no need to reselect a new aggregator, just signal the
 	 * state machines to reinitialize
 	 */
@@ -2378,17 +2391,16 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
 		}
 	}
 
-	if (aggregator) {
-		ad_info->aggregator_id = aggregator->aggregator_identifier;
-		ad_info->ports = aggregator->num_of_ports;
-		ad_info->actor_key = aggregator->actor_oper_aggregator_key;
-		ad_info->partner_key = aggregator->partner_oper_aggregator_key;
-		memcpy(ad_info->partner_system,
-		       aggregator->partner_system.mac_addr_value, ETH_ALEN);
-		return 0;
-	}
+	if (!aggregator)
+		return -1;
 
-	return -1;
+	ad_info->aggregator_id = aggregator->aggregator_identifier;
+	ad_info->ports = aggregator->num_of_ports;
+	ad_info->actor_key = aggregator->actor_oper_aggregator_key;
+	ad_info->partner_key = aggregator->partner_oper_aggregator_key;
+	ether_addr_copy(ad_info->partner_system,
+			aggregator->partner_system.mac_addr_value);
+	return 0;
 }
 
 /* Wrapper used to hold bond->lock so no slave manipulation can occur */
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index f4dd9592ac62..bb03b1df2f3e 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -28,7 +28,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
 
-// General definitions
+/* General definitions */
 #define PKT_TYPE_LACPDU         cpu_to_be16(ETH_P_SLOW)
 #define AD_TIMER_INTERVAL       100 /*msec*/
 
@@ -47,54 +47,54 @@ enum {
 	BOND_AD_COUNT = 2,
 };
 
-// rx machine states(43.4.11 in the 802.3ad standard)
+/* rx machine states(43.4.11 in the 802.3ad standard) */
 typedef enum {
 	AD_RX_DUMMY,
-	AD_RX_INITIALIZE,     // rx Machine
-	AD_RX_PORT_DISABLED,  // rx Machine
-	AD_RX_LACP_DISABLED,  // rx Machine
-	AD_RX_EXPIRED,	      // rx Machine
-	AD_RX_DEFAULTED,      // rx Machine
-	AD_RX_CURRENT	      // rx Machine
+	AD_RX_INITIALIZE,	/* rx Machine */
+	AD_RX_PORT_DISABLED,	/* rx Machine */
+	AD_RX_LACP_DISABLED,	/* rx Machine */
+	AD_RX_EXPIRED,		/* rx Machine */
+	AD_RX_DEFAULTED,	/* rx Machine */
+	AD_RX_CURRENT		/* rx Machine */
 } rx_states_t;
 
-// periodic machine states(43.4.12 in the 802.3ad standard)
+/* periodic machine states(43.4.12 in the 802.3ad standard) */
 typedef enum {
 	AD_PERIODIC_DUMMY,
-	AD_NO_PERIODIC,	       // periodic machine
-	AD_FAST_PERIODIC,      // periodic machine
-	AD_SLOW_PERIODIC,      // periodic machine
-	AD_PERIODIC_TX	   // periodic machine
+	AD_NO_PERIODIC,		/* periodic machine */
+	AD_FAST_PERIODIC,	/* periodic machine */
+	AD_SLOW_PERIODIC,	/* periodic machine */
+	AD_PERIODIC_TX		/* periodic machine */
 } periodic_states_t;
 
-// mux machine states(43.4.13 in the 802.3ad standard)
+/* mux machine states(43.4.13 in the 802.3ad standard) */
 typedef enum {
 	AD_MUX_DUMMY,
-	AD_MUX_DETACHED,       // mux machine
-	AD_MUX_WAITING,	       // mux machine
-	AD_MUX_ATTACHED,       // mux machine
-	AD_MUX_COLLECTING_DISTRIBUTING // mux machine
+	AD_MUX_DETACHED,	/* mux machine */
+	AD_MUX_WAITING,		/* mux machine */
+	AD_MUX_ATTACHED,	/* mux machine */
+	AD_MUX_COLLECTING_DISTRIBUTING	/* mux machine */
 } mux_states_t;
 
-// tx machine states(43.4.15 in the 802.3ad standard)
+/* tx machine states(43.4.15 in the 802.3ad standard) */
 typedef enum {
 	AD_TX_DUMMY,
-	AD_TRANSMIT	   // tx Machine
+	AD_TRANSMIT		/* tx Machine */
 } tx_states_t;
 
-// rx indication types
+/* rx indication types */
 typedef enum {
-	AD_TYPE_LACPDU = 1,    // type lacpdu
-	AD_TYPE_MARKER	   // type marker
+	AD_TYPE_LACPDU = 1,	/* type lacpdu */
+	AD_TYPE_MARKER		/* type marker */
 } pdu_type_t;
 
-// rx marker indication types
+/* rx marker indication types */
 typedef enum {
-	AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
-	AD_MARKER_RESPONSE_SUBTYPE     // marker response subtype
+	AD_MARKER_INFORMATION_SUBTYPE = 1,	/* marker imformation subtype */
+	AD_MARKER_RESPONSE_SUBTYPE		/* marker response subtype */
 } bond_marker_subtype_t;
 
-// timers types(43.4.9 in the 802.3ad standard)
+/* timers types(43.4.9 in the 802.3ad standard) */
 typedef enum {
 	AD_CURRENT_WHILE_TIMER,
 	AD_ACTOR_CHURN_TIMER,
@@ -105,35 +105,35 @@ typedef enum {
 
 #pragma pack(1)
 
-// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
+/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */
 typedef struct lacpdu {
-	u8 subtype;		     // = LACP(= 0x01)
+	u8 subtype;		/* = LACP(= 0x01) */
 	u8 version_number;
-	u8 tlv_type_actor_info;	      // = actor information(type/length/value)
-	u8 actor_information_length; // = 20
+	u8 tlv_type_actor_info;	/* = actor information(type/length/value) */
+	u8 actor_information_length;	/* = 20 */
 	__be16 actor_system_priority;
 	struct mac_addr actor_system;
 	__be16 actor_key;
 	__be16 actor_port_priority;
 	__be16 actor_port;
 	u8 actor_state;
-	u8 reserved_3_1[3];	     // = 0
-	u8 tlv_type_partner_info;     // = partner information
-	u8 partner_information_length;	 // = 20
+	u8 reserved_3_1[3];		/* = 0 */
+	u8 tlv_type_partner_info;	/* = partner information */
+	u8 partner_information_length;	/* = 20 */
 	__be16 partner_system_priority;
 	struct mac_addr partner_system;
 	__be16 partner_key;
 	__be16 partner_port_priority;
 	__be16 partner_port;
 	u8 partner_state;
-	u8 reserved_3_2[3];	     // = 0
-	u8 tlv_type_collector_info;	  // = collector information
-	u8 collector_information_length; // = 16
+	u8 reserved_3_2[3];		/* = 0 */
+	u8 tlv_type_collector_info;	/* = collector information */
+	u8 collector_information_length;/* = 16 */
 	__be16 collector_max_delay;
 	u8 reserved_12[12];
-	u8 tlv_type_terminator;	     // = terminator
-	u8 terminator_length;	     // = 0
-	u8 reserved_50[50];	     // = 0
+	u8 tlv_type_terminator;		/* = terminator */
+	u8 terminator_length;		/* = 0 */
+	u8 reserved_50[50];		/* = 0 */
 } __packed lacpdu_t;
 
 typedef struct lacpdu_header {
@@ -141,20 +141,20 @@ typedef struct lacpdu_header {
 	struct lacpdu lacpdu;
 } __packed lacpdu_header_t;
 
-// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
+/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */
 typedef struct bond_marker {
-	u8 subtype;		 //  = 0x02  (marker PDU)
-	u8 version_number;	 //  = 0x01
-	u8 tlv_type;		 //  = 0x01  (marker information)
-	//  = 0x02  (marker response information)
-	u8 marker_length;	 //  = 0x16
-	u16 requester_port;	 //   The number assigned to the port by the requester
-	struct mac_addr requester_system;      //   The requester's system id
-	u32 requester_transaction_id;	//   The transaction id allocated by the requester,
-	u16 pad;		 //  = 0
-	u8 tlv_type_terminator;	     //  = 0x00
-	u8 terminator_length;	     //  = 0x00
-	u8 reserved_90[90];	     //  = 0
+	u8 subtype;		/* = 0x02  (marker PDU) */
+	u8 version_number;	/* = 0x01 */
+	u8 tlv_type;		/* = 0x01  (marker information) */
+	/* = 0x02  (marker response information) */
+	u8 marker_length;	/* = 0x16 */
+	u16 requester_port;	/* The number assigned to the port by the requester */
+	struct mac_addr requester_system;	/* The requester's system id */
+	u32 requester_transaction_id;		/* The transaction id allocated by the requester, */
+	u16 pad;		/* = 0 */
+	u8 tlv_type_terminator;	/* = 0x00 */
+	u8 terminator_length;	/* = 0x00 */
+	u8 reserved_90[90];	/* = 0 */
 } __packed bond_marker_t;
 
 typedef struct bond_marker_header {
@@ -173,7 +173,7 @@ struct port;
 #pragma pack(8)
 #endif
 
-// aggregator structure(43.4.5 in the 802.3ad standard)
+/* aggregator structure(43.4.5 in the 802.3ad standard) */
 typedef struct aggregator {
 	struct mac_addr aggregator_mac_address;
 	u16 aggregator_identifier;
@@ -183,12 +183,12 @@ typedef struct aggregator {
 	struct mac_addr partner_system;
 	u16 partner_system_priority;
 	u16 partner_oper_aggregator_key;
-	u16 receive_state;		// BOOLEAN
-	u16 transmit_state;		// BOOLEAN
+	u16 receive_state;	/* BOOLEAN */
+	u16 transmit_state;	/* BOOLEAN */
 	struct port *lag_ports;
-	// ****** PRIVATE PARAMETERS ******
-	struct slave *slave;	    // pointer to the bond slave that this aggregator belongs to
-	u16 is_active;	    // BOOLEAN. Indicates if this aggregator is active
+	/* ****** PRIVATE PARAMETERS ****** */
+	struct slave *slave;	/* pointer to the bond slave that this aggregator belongs to */
+	u16 is_active;		/* BOOLEAN. Indicates if this aggregator is active */
 	u16 num_of_ports;
 } aggregator_t;
 
@@ -201,12 +201,12 @@ struct port_params {
 	u16 port_state;
 };
 
-// port structure(43.4.6 in the 802.3ad standard)
+/* port structure(43.4.6 in the 802.3ad standard) */
 typedef struct port {
 	u16 actor_port_number;
 	u16 actor_port_priority;
-	struct mac_addr actor_system;	       // This parameter is added here although it is not specified in the standard, just for simplification
-	u16 actor_system_priority;	 // This parameter is added here although it is not specified in the standard, just for simplification
+	struct mac_addr actor_system;	/* This parameter is added here although it is not specified in the standard, just for simplification */
+	u16 actor_system_priority;	/* This parameter is added here although it is not specified in the standard, just for simplification */
 	u16 actor_port_aggregator_identifier;
 	bool ntt;
 	u16 actor_admin_port_key;
@@ -219,24 +219,24 @@ typedef struct port {
 
 	bool is_enabled;
 
-	// ****** PRIVATE PARAMETERS ******
-	u16 sm_vars;	      // all state machines variables for this port
-	rx_states_t sm_rx_state;	// state machine rx state
-	u16 sm_rx_timer_counter;    // state machine rx timer counter
-	periodic_states_t sm_periodic_state;// state machine periodic state
-	u16 sm_periodic_timer_counter;	// state machine periodic timer counter
-	mux_states_t sm_mux_state;	// state machine mux state
-	u16 sm_mux_timer_counter;   // state machine mux timer counter
-	tx_states_t sm_tx_state;	// state machine tx state
-	u16 sm_tx_timer_counter;    // state machine tx timer counter(allways on - enter to transmit state 3 time per second)
-	struct slave *slave;	    // pointer to the bond slave that this port belongs to
-	struct aggregator *aggregator;	   // pointer to an aggregator that this port related to
-	struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator
-	u32 transaction_id;	    // continuous number for identification of Marker PDU's;
-	struct lacpdu lacpdu;	       // the lacpdu that will be sent for this port
+	/* ****** PRIVATE PARAMETERS ****** */
+	u16 sm_vars;		/* all state machines variables for this port */
+	rx_states_t sm_rx_state;	/* state machine rx state */
+	u16 sm_rx_timer_counter;	/* state machine rx timer counter */
+	periodic_states_t sm_periodic_state;	/* state machine periodic state */
+	u16 sm_periodic_timer_counter;	/* state machine periodic timer counter */
+	mux_states_t sm_mux_state;	/* state machine mux state */
+	u16 sm_mux_timer_counter;	/* state machine mux timer counter */
+	tx_states_t sm_tx_state;	/* state machine tx state */
+	u16 sm_tx_timer_counter;	/* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */
+	struct slave *slave;		/* pointer to the bond slave that this port belongs to */
+	struct aggregator *aggregator;	/* pointer to an aggregator that this port related to */
+	struct port *next_port_in_aggregator;	/* Next port on the linked list of the parent aggregator */
+	u32 transaction_id;		/* continuous number for identification of Marker PDU's; */
+	struct lacpdu lacpdu;		/* the lacpdu that will be sent for this port */
 } port_t;
 
-// system structure
+/* system structure */
 struct ad_system {
 	u16 sys_priority;
 	struct mac_addr sys_mac_addr;
@@ -246,27 +246,26 @@ struct ad_system {
 #pragma pack()
 #endif
 
-// ================= AD Exported structures to the main bonding code ==================
+/* ========== AD Exported structures to the main bonding code ========== */
 #define BOND_AD_INFO(bond)   ((bond)->ad_info)
 #define SLAVE_AD_INFO(slave) ((slave)->ad_info)
 
 struct ad_bond_info {
-	struct ad_system system;	    /* 802.3ad system structure */
-	u32 agg_select_timer;	    // Timer to select aggregator after all adapter's hand shakes
+	struct ad_system system;	/* 802.3ad system structure */
+	u32 agg_select_timer;		/* Timer to select aggregator after all adapter's hand shakes */
 	u16 aggregator_identifier;
 };
 
 struct ad_slave_info {
-	struct aggregator aggregator;	    // 802.3ad aggregator structure
-	struct port port;		    // 802.3ad port structure
-	spinlock_t state_machine_lock; /* mutex state machines vs.
-					  incoming LACPDU */
+	struct aggregator aggregator;	/* 802.3ad aggregator structure */
+	struct port port;		/* 802.3ad port structure */
+	spinlock_t state_machine_lock;	/* mutex state machines vs. incoming LACPDU */
 	u16 id;
 };
 
-// ================= AD Exported functions to the main bonding code ==================
+/* ========== AD Exported functions to the main bonding code ========== */
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
-void  bond_3ad_bind_slave(struct slave *slave);
+void bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct work_struct *);
 void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
@@ -281,5 +280,5 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
 			 struct slave *slave);
 int bond_3ad_set_carrier(struct bonding *bond);
 void bond_3ad_update_lacp_rate(struct bonding *bond);
-#endif //__BOND_3AD_H__
+#endif /* __BOND_3AD_H__ */
 
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index a2c47476804d..aaeeacf767f2 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -93,9 +93,8 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
 	int i;
 	u8 hash = 0;
 
-	for (i = 0; i < hash_size; i++) {
+	for (i = 0; i < hash_size; i++)
 		hash ^= hash_start[i];
-	}
 
 	return hash;
 }
@@ -190,9 +189,8 @@ static int tlb_initialize(struct bonding *bond)
 
 	bond_info->tx_hashtbl = new_hashtbl;
 
-	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
+	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++)
 		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
-	}
 
 	_unlock_tx_hashtbl_bh(bond);
 
@@ -264,9 +262,8 @@ static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index,
 			hash_table[hash_index].next = next_index;
 			hash_table[hash_index].prev = TLB_NULL_INDEX;
 
-			if (next_index != TLB_NULL_INDEX) {
+			if (next_index != TLB_NULL_INDEX)
 				hash_table[next_index].prev = hash_index;
-			}
 
 			slave_info->head = hash_index;
 			slave_info->load +=
@@ -274,9 +271,8 @@ static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index,
 		}
 	}
 
-	if (assigned_slave) {
+	if (assigned_slave)
 		hash_table[hash_index].tx_bytes += skb_len;
-	}
 
 	return assigned_slave;
 }
@@ -329,7 +325,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
 
 	_lock_rx_hashtbl_bh(bond);
 
-	hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
+	hash_index = _simple_hash((u8 *)&(arp->ip_src), sizeof(arp->ip_src));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 	if ((client_info->assigned) &&
@@ -337,7 +333,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
 	    (client_info->ip_dst == arp->ip_src) &&
 	    (!ether_addr_equal_64bits(client_info->mac_dst, arp->mac_src))) {
 		/* update the clients MAC address */
-		memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
+		ether_addr_copy(client_info->mac_dst, arp->mac_src);
 		client_info->ntt = 1;
 		bond_info->rx_ntt = 1;
 	}
@@ -451,9 +447,8 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond)
  */
 static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
 {
-	if (!bond->curr_active_slave) {
+	if (!bond->curr_active_slave)
 		return;
-	}
 
 	if (!bond->alb_info.primary_is_promisc) {
 		if (!dev_set_promiscuity(bond->curr_active_slave->dev, 1))
@@ -513,9 +508,8 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
 
 	write_lock_bh(&bond->curr_slave_lock);
 
-	if (slave != bond->curr_active_slave) {
+	if (slave != bond->curr_active_slave)
 		rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
-	}
 
 	write_unlock_bh(&bond->curr_slave_lock);
 }
@@ -524,9 +518,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
 {
 	int i;
 
-	if (!client_info->slave) {
+	if (!client_info->slave)
 		return;
-	}
 
 	for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
 		struct sk_buff *skb;
@@ -574,9 +567,8 @@ static void rlb_update_rx_clients(struct bonding *bond)
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 		if (client_info->ntt) {
 			rlb_update_client(client_info);
-			if (bond_info->rlb_update_retry_counter == 0) {
+			if (bond_info->rlb_update_retry_counter == 0)
 				client_info->ntt = 0;
-			}
 		}
 	}
 
@@ -610,10 +602,10 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
 		}
 	}
 
-	// update the team's flag only after the whole iteration
+	/* update the team's flag only after the whole iteration */
 	if (ntt) {
 		bond_info->rx_ntt = 1;
-		//fasten the change
+		/* fasten the change */
 		bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
 	}
 
@@ -677,9 +669,9 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 			/* the entry is already assigned to this client */
 			if (!ether_addr_equal_64bits(arp->mac_dst, mac_bcast)) {
 				/* update mac address from arp */
-				memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+				ether_addr_copy(client_info->mac_dst, arp->mac_dst);
 			}
-			memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
+			ether_addr_copy(client_info->mac_src, arp->mac_src);
 
 			assigned_slave = client_info->slave;
 			if (assigned_slave) {
@@ -719,8 +711,8 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 		 * will be updated with clients actual unicast mac address
 		 * upon receiving an arp reply.
 		 */
-		memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
-		memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
+		ether_addr_copy(client_info->mac_dst, arp->mac_dst);
+		ether_addr_copy(client_info->mac_src, arp->mac_src);
 		client_info->slave = assigned_slave;
 
 		if (!ether_addr_equal_64bits(client_info->mac_dst, mac_bcast)) {
@@ -770,9 +762,8 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 		* rx channel
 		*/
 		tx_slave = rlb_choose_channel(skb, bond);
-		if (tx_slave) {
-			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
-		}
+		if (tx_slave)
+			ether_addr_copy(arp->mac_src, tx_slave->dev->dev_addr);
 		pr_debug("Server sent ARP Reply packet\n");
 	} else if (arp->op_code == htons(ARPOP_REQUEST)) {
 		/* Create an entry in the rx_hashtbl for this client as a
@@ -824,9 +815,8 @@ static void rlb_rebalance(struct bonding *bond)
 	}
 
 	/* update the team's flag only after the whole iteration */
-	if (ntt) {
+	if (ntt)
 		bond_info->rx_ntt = 1;
-	}
 	_unlock_rx_hashtbl_bh(bond);
 }
 
@@ -923,7 +913,7 @@ static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash)
 static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u32 ip_src_hash = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
+	u32 ip_src_hash = _simple_hash((u8 *)&(arp->ip_src), sizeof(arp->ip_src));
 	u32 index;
 
 	_lock_rx_hashtbl_bh(bond);
@@ -957,9 +947,8 @@ static int rlb_initialize(struct bonding *bond)
 
 	bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
 
-	for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
+	for (i = 0; i < RLB_HASH_TABLE_SIZE; i++)
 		rlb_init_table_entry(bond_info->rx_hashtbl + i);
-	}
 
 	_unlock_rx_hashtbl_bh(bond);
 
@@ -1014,8 +1003,8 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
 	char *data;
 
 	memset(&pkt, 0, size);
-	memcpy(pkt.mac_dst, mac_addr, ETH_ALEN);
-	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
+	ether_addr_copy(pkt.mac_dst, mac_addr);
+	ether_addr_copy(pkt.mac_src, mac_addr);
 	pkt.type = cpu_to_be16(ETH_P_LOOP);
 
 	skb = dev_alloc_skb(size);
@@ -1097,7 +1086,7 @@ static void alb_swap_mac_addr(struct slave *slave1, struct slave *slave2)
 {
 	u8 tmp_mac_addr[ETH_ALEN];
 
-	memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
+	ether_addr_copy(tmp_mac_addr, slave1->dev->dev_addr);
 	alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
 	alb_set_slave_mac_addr(slave2, tmp_mac_addr);
 
@@ -1254,9 +1243,9 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 	if (free_mac_slave) {
 		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
 
-		pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
-			   bond->dev->name, slave->dev->name,
-			   free_mac_slave->dev->name);
+		pr_warn("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
+			bond->dev->name, slave->dev->name,
+			free_mac_slave->dev->name);
 
 	} else if (has_bond_addr) {
 		pr_err("%s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
@@ -1294,12 +1283,12 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
 
 	bond_for_each_slave(bond, slave, iter) {
 		/* save net_device's current hw address */
-		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
+		ether_addr_copy(tmp_addr, slave->dev->dev_addr);
 
 		res = dev_set_mac_address(slave->dev, addr);
 
 		/* restore net_device's hw address */
-		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+		ether_addr_copy(slave->dev->dev_addr, tmp_addr);
 
 		if (res)
 			goto unwind;
@@ -1315,9 +1304,9 @@ unwind:
 	bond_for_each_slave(bond, rollback_slave, iter) {
 		if (rollback_slave == slave)
 			break;
-		memcpy(tmp_addr, rollback_slave->dev->dev_addr, ETH_ALEN);
+		ether_addr_copy(tmp_addr, rollback_slave->dev->dev_addr);
 		dev_set_mac_address(rollback_slave->dev, &sa);
-		memcpy(rollback_slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+		ether_addr_copy(rollback_slave->dev->dev_addr, tmp_addr);
 	}
 
 	return res;
@@ -1330,9 +1319,8 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
 	int res;
 
 	res = tlb_initialize(bond);
-	if (res) {
+	if (res)
 		return res;
-	}
 
 	if (rlb_enabled) {
 		bond->alb_info.rlb_enabled = 1;
@@ -1355,9 +1343,8 @@ void bond_alb_deinitialize(struct bonding *bond)
 
 	tlb_deinitialize(bond);
 
-	if (bond_info->rlb_enabled) {
+	if (bond_info->rlb_enabled)
 		rlb_deinitialize(bond);
-	}
 }
 
 int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
@@ -1436,14 +1423,13 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 			break;
 		}
 
-		hash_start = (char*)eth_data->h_dest;
+		hash_start = (char *)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
 	case ETH_P_ARP:
 		do_tx_balance = 0;
-		if (bond_info->rlb_enabled) {
+		if (bond_info->rlb_enabled)
 			tx_slave = rlb_arp_xmit(skb, bond);
-		}
 		break;
 	default:
 		do_tx_balance = 0;
@@ -1463,19 +1449,18 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 
 	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
 		if (tx_slave != rcu_dereference(bond->curr_active_slave)) {
-			memcpy(eth_data->h_source,
-			       tx_slave->dev->dev_addr,
-			       ETH_ALEN);
+			ether_addr_copy(eth_data->h_source,
+					tx_slave->dev->dev_addr);
 		}
 
 		bond_dev_queue_xmit(bond, skb, tx_slave->dev);
 		goto out;
-	} else {
-		if (tx_slave) {
-			_lock_tx_hashtbl(bond);
-			__tlb_clear_slave(bond, tx_slave, 0);
-			_unlock_tx_hashtbl(bond);
-		}
+	}
+
+	if (tx_slave) {
+		_lock_tx_hashtbl(bond);
+		__tlb_clear_slave(bond, tx_slave, 0);
+		_unlock_tx_hashtbl(bond);
 	}
 
 	/* no suitable interface, frame not sent */
@@ -1577,11 +1562,10 @@ void bond_alb_monitor(struct work_struct *work)
 				--bond_info->rlb_update_delay_counter;
 			} else {
 				rlb_update_rx_clients(bond);
-				if (bond_info->rlb_update_retry_counter) {
+				if (bond_info->rlb_update_retry_counter)
 					--bond_info->rlb_update_retry_counter;
-				} else {
+				else
 					bond_info->rx_ntt = 0;
-				}
 			}
 		}
 	}
@@ -1598,23 +1582,20 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
 	int res;
 
 	res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
-	if (res) {
+	if (res)
 		return res;
-	}
 
 	res = alb_handle_addr_collision_on_attach(bond, slave);
-	if (res) {
+	if (res)
 		return res;
-	}
 
 	tlb_init_slave(slave);
 
 	/* order a rebalance ASAP */
 	bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
 
-	if (bond->alb_info.rlb_enabled) {
+	if (bond->alb_info.rlb_enabled)
 		bond->alb_info.rlb_rebalance = 1;
-	}
 
 	return 0;
 }
@@ -1645,9 +1626,8 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
 
 	if (link == BOND_LINK_DOWN) {
 		tlb_clear_slave(bond, slave, 0);
-		if (bond->alb_info.rlb_enabled) {
+		if (bond->alb_info.rlb_enabled)
 			rlb_clear_slave(bond, slave);
-		}
 	} else if (link == BOND_LINK_UP) {
 		/* order a rebalance ASAP */
 		bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
@@ -1723,14 +1703,14 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
 		struct sockaddr sa;
 		u8 tmp_addr[ETH_ALEN];
 
-		memcpy(tmp_addr, new_slave->dev->dev_addr, ETH_ALEN);
+		ether_addr_copy(tmp_addr, new_slave->dev->dev_addr);
 
 		memcpy(sa.sa_data, bond->dev->dev_addr, bond->dev->addr_len);
 		sa.sa_family = bond->dev->type;
 		/* we don't care if it can't change its mac, best effort */
 		dev_set_mac_address(new_slave->dev, &sa);
 
-		memcpy(new_slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+		ether_addr_copy(new_slave->dev->dev_addr, tmp_addr);
 	}
 
 	/* curr_active_slave must be set before calling alb_swap_mac_addr */
@@ -1759,14 +1739,12 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 	struct slave *swap_slave;
 	int res;
 
-	if (!is_valid_ether_addr(sa->sa_data)) {
+	if (!is_valid_ether_addr(sa->sa_data))
 		return -EADDRNOTAVAIL;
-	}
 
 	res = alb_set_mac_address(bond, addr);
-	if (res) {
+	if (res)
 		return res;
-	}
 
 	memcpy(bond_dev->dev_addr, sa->sa_data, bond_dev->addr_len);
 
@@ -1774,9 +1752,8 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 	 * Otherwise we'll need to pass the new address to it and handle
 	 * duplications.
 	 */
-	if (!bond->curr_active_slave) {
+	if (!bond->curr_active_slave)
 		return 0;
-	}
 
 	swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr);
 
@@ -1800,8 +1777,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 
 void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
 {
-	if (bond->alb_info.rlb_enabled) {
+	if (bond->alb_info.rlb_enabled)
 		rlb_clear_vlan(bond, vlan_id);
-	}
 }
 
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 5fc4c2351478..2d3f7fa541ff 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -69,7 +69,7 @@ void bond_debug_register(struct bonding *bond)
 		debugfs_create_dir(bond->dev->name, bonding_debug_root);
 
 	if (!bond->debug_dir) {
-		pr_warning("%s: Warning: failed to register to debugfs\n",
+		pr_warn("%s: Warning: failed to register to debugfs\n",
 			bond->dev->name);
 		return;
 	}
@@ -98,9 +98,8 @@ void bond_debug_reregister(struct bonding *bond)
 	if (d) {
 		bond->debug_dir = d;
 	} else {
-		pr_warning("%s: Warning: failed to reregister, "
-				"so just unregister old one\n",
-				bond->dev->name);
+		pr_warn("%s: Warning: failed to reregister, so just unregister old one\n",
+			bond->dev->name);
 		bond_debug_unregister(bond);
 	}
 }
@@ -110,8 +109,7 @@ void bond_create_debugfs(void)
 	bonding_debug_root = debugfs_create_dir("bonding", NULL);
 
 	if (!bonding_debug_root) {
-		pr_warning("Warning: Cannot create bonding directory"
-				" in debugfs\n");
+		pr_warn("Warning: Cannot create bonding directory in debugfs\n");
 	}
 }
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1c6104d3501d..730d72c706c9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -673,12 +673,12 @@ static void bond_do_fail_over_mac(struct bonding *bond,
 		write_unlock_bh(&bond->curr_slave_lock);
 
 		if (old_active) {
-			memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN);
-			memcpy(saddr.sa_data, old_active->dev->dev_addr,
-			       ETH_ALEN);
+			ether_addr_copy(tmp_mac, new_active->dev->dev_addr);
+			ether_addr_copy(saddr.sa_data,
+					old_active->dev->dev_addr);
 			saddr.sa_family = new_active->dev->type;
 		} else {
-			memcpy(saddr.sa_data, bond->dev->dev_addr, ETH_ALEN);
+			ether_addr_copy(saddr.sa_data, bond->dev->dev_addr);
 			saddr.sa_family = bond->dev->type;
 		}
 
@@ -692,7 +692,7 @@ static void bond_do_fail_over_mac(struct bonding *bond,
 		if (!old_active)
 			goto out;
 
-		memcpy(saddr.sa_data, tmp_mac, ETH_ALEN);
+		ether_addr_copy(saddr.sa_data, tmp_mac);
 		saddr.sa_family = old_active->dev->type;
 
 		rv = dev_set_mac_address(old_active->dev, &saddr);
@@ -798,11 +798,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 		return;
 
 	if (new_active) {
-		new_active->jiffies = jiffies;
+		new_active->last_link_up = jiffies;
 
 		if (new_active->link == BOND_LINK_BACK) {
 			if (USES_PRIMARY(bond->params.mode)) {
-				pr_info("%s: making interface %s the new active one %d ms earlier.\n",
+				pr_info("%s: making interface %s the new active one %d ms earlier\n",
 					bond->dev->name, new_active->dev->name,
 					(bond->params.updelay - new_active->delay) * bond->params.miimon);
 			}
@@ -817,7 +817,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 		} else {
 			if (USES_PRIMARY(bond->params.mode)) {
-				pr_info("%s: making interface %s the new active one.\n",
+				pr_info("%s: making interface %s the new active one\n",
 					bond->dev->name, new_active->dev->name);
 			}
 		}
@@ -829,21 +829,25 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 	if (bond_is_lb(bond)) {
 		bond_alb_handle_active_change(bond, new_active);
 		if (old_active)
-			bond_set_slave_inactive_flags(old_active);
+			bond_set_slave_inactive_flags(old_active,
+						      BOND_SLAVE_NOTIFY_NOW);
 		if (new_active)
-			bond_set_slave_active_flags(new_active);
+			bond_set_slave_active_flags(new_active,
+						    BOND_SLAVE_NOTIFY_NOW);
 	} else {
 		rcu_assign_pointer(bond->curr_active_slave, new_active);
 	}
 
 	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 		if (old_active)
-			bond_set_slave_inactive_flags(old_active);
+			bond_set_slave_inactive_flags(old_active,
+						      BOND_SLAVE_NOTIFY_NOW);
 
 		if (new_active) {
 			bool should_notify_peers = false;
 
-			bond_set_slave_active_flags(new_active);
+			bond_set_slave_active_flags(new_active,
+						    BOND_SLAVE_NOTIFY_NOW);
 
 			if (bond->params.fail_over_mac)
 				bond_do_fail_over_mac(bond, new_active,
@@ -906,7 +910,7 @@ void bond_select_active_slave(struct bonding *bond)
 			pr_info("%s: first active interface up!\n",
 				bond->dev->name);
 		} else {
-			pr_info("%s: now running without any active interface !\n",
+			pr_info("%s: now running without any active interface!\n",
 				bond->dev->name);
 		}
 	}
@@ -942,14 +946,6 @@ static inline void slave_disable_netpoll(struct slave *slave)
 	slave->np = NULL;
 	__netpoll_free_async(np);
 }
-static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)
-{
-	if (slave_dev->priv_flags & IFF_DISABLE_NETPOLL)
-		return false;
-	if (!slave_dev->netdev_ops->ndo_poll_controller)
-		return false;
-	return true;
-}
 
 static void bond_poll_controller(struct net_device *bond_dev)
 {
@@ -1115,9 +1111,6 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
 	slave = bond_slave_get_rcu(skb->dev);
 	bond = slave->bond;
 
-	if (bond->params.arp_interval)
-		slave->dev->last_rx = jiffies;
-
 	recv_probe = ACCESS_ONCE(bond->recv_probe);
 	if (recv_probe) {
 		ret = recv_probe(skb, bond, slave);
@@ -1142,7 +1135,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
 			kfree_skb(skb);
 			return RX_HANDLER_CONSUMED;
 		}
-		memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
+		ether_addr_copy(eth_hdr(skb)->h_dest, bond->dev->dev_addr);
 	}
 
 	return ret;
@@ -1183,16 +1176,21 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	if (!bond->params.use_carrier &&
 	    slave_dev->ethtool_ops->get_link == NULL &&
 	    slave_ops->ndo_do_ioctl == NULL) {
-		pr_warning("%s: Warning: no link monitoring support for %s\n",
-			   bond_dev->name, slave_dev->name);
+		pr_warn("%s: Warning: no link monitoring support for %s\n",
+			bond_dev->name, slave_dev->name);
 	}
 
 	/* already enslaved */
 	if (slave_dev->flags & IFF_SLAVE) {
-		pr_debug("Error, Device was already enslaved\n");
+		pr_debug("Error: Device was already enslaved\n");
 		return -EBUSY;
 	}
 
+	if (bond_dev == slave_dev) {
+		pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name);
+		return -EPERM;
+	}
+
 	/* vlan challenged mutual exclusion */
 	/* no need to lock since we're protected by rtnl_lock */
 	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
@@ -1202,9 +1200,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 			       bond_dev->name, slave_dev->name, bond_dev->name);
 			return -EPERM;
 		} else {
-			pr_warning("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
-				   bond_dev->name, slave_dev->name,
-				   slave_dev->name, bond_dev->name);
+			pr_warn("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
+				bond_dev->name, slave_dev->name,
+				slave_dev->name, bond_dev->name);
 		}
 	} else {
 		pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
@@ -1217,7 +1215,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	 * enslaving it; the old ifenslave will not.
 	 */
 	if ((slave_dev->flags & IFF_UP)) {
-		pr_err("%s is up. This may be due to an out of date ifenslave.\n",
+		pr_err("%s is up - this may be due to an out of date ifenslave\n",
 		       slave_dev->name);
 		res = -EPERM;
 		goto err_undo_flags;
@@ -1261,24 +1259,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 						 bond_dev);
 		}
 	} else if (bond_dev->type != slave_dev->type) {
-		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n",
-		       slave_dev->name,
-		       slave_dev->type, bond_dev->type);
+		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
+		       slave_dev->name, slave_dev->type, bond_dev->type);
 		res = -EINVAL;
 		goto err_undo_flags;
 	}
 
 	if (slave_ops->ndo_set_mac_address == NULL) {
 		if (!bond_has_slaves(bond)) {
-			pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n",
+			pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n",
 				bond_dev->name);
 			if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 				bond->params.fail_over_mac = BOND_FOM_ACTIVE;
-				pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n",
+				pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n",
 					bond_dev->name);
 			}
 		} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
-			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n",
+			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n",
 			       bond_dev->name);
 			res = -EOPNOTSUPP;
 			goto err_undo_flags;
@@ -1317,7 +1314,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	 * that need it, and for restoring it upon release, and then
 	 * set it to the master's address
 	 */
-	memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
+	ether_addr_copy(new_slave->perm_hwaddr, slave_dev->dev_addr);
 
 	if (!bond->params.fail_over_mac ||
 	    bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
@@ -1401,10 +1398,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	bond_update_speed_duplex(new_slave);
 
-	new_slave->last_arp_rx = jiffies -
+	new_slave->last_rx = jiffies -
 		(msecs_to_jiffies(bond->params.arp_interval) + 1);
 	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
-		new_slave->target_last_arp_rx[i] = new_slave->last_arp_rx;
+		new_slave->target_last_arp_rx[i] = new_slave->last_rx;
 
 	if (bond->params.miimon && !bond->params.use_carrier) {
 		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@@ -1419,12 +1416,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 			 * supported); thus, we don't need to change
 			 * the messages for netif_carrier.
 			 */
-			pr_warning("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details.\n",
-			       bond_dev->name, slave_dev->name);
+			pr_warn("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
+				bond_dev->name, slave_dev->name);
 		} else if (link_reporting == -1) {
 			/* unable get link status using mii/ethtool */
-			pr_warning("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface.\n",
-				   bond_dev->name, slave_dev->name);
+			pr_warn("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
+				bond_dev->name, slave_dev->name);
 		}
 	}
 
@@ -1448,10 +1445,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	}
 
 	if (new_slave->link != BOND_LINK_DOWN)
-		new_slave->jiffies = jiffies;
+		new_slave->last_link_up = jiffies;
 	pr_debug("Initial state of slave_dev is BOND_LINK_%s\n",
-		new_slave->link == BOND_LINK_DOWN ? "DOWN" :
-			(new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
+		 new_slave->link == BOND_LINK_DOWN ? "DOWN" :
+		 (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
 
 	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
@@ -1463,14 +1460,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	switch (bond->params.mode) {
 	case BOND_MODE_ACTIVEBACKUP:
-		bond_set_slave_inactive_flags(new_slave);
+		bond_set_slave_inactive_flags(new_slave,
+					      BOND_SLAVE_NOTIFY_NOW);
 		break;
 	case BOND_MODE_8023AD:
 		/* in 802.3ad mode, the internal mechanism
 		 * will activate the slaves in the selected
 		 * aggregator
 		 */
-		bond_set_slave_inactive_flags(new_slave);
+		bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
 		/* if this is the first slave */
 		if (!prev_slave) {
 			SLAVE_AD_INFO(new_slave).id = 1;
@@ -1488,7 +1486,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	case BOND_MODE_TLB:
 	case BOND_MODE_ALB:
 		bond_set_active_slave(new_slave);
-		bond_set_slave_inactive_flags(new_slave);
+		bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
 		break;
 	default:
 		pr_debug("This slave is always active in trunk mode\n");
@@ -1510,9 +1508,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	slave_dev->npinfo = bond->dev->npinfo;
 	if (slave_dev->npinfo) {
 		if (slave_enable_netpoll(new_slave)) {
-			pr_info("Error, %s: master_dev is using netpoll, "
-				 "but new slave device does not support netpoll.\n",
-				 bond_dev->name);
+			pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n",
+				bond_dev->name);
 			res = -EBUSY;
 			goto err_detach;
 		}
@@ -1550,10 +1547,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		unblock_netpoll_tx();
 	}
 
-	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
+	pr_info("%s: Enslaving %s as %s interface with %s link\n",
 		bond_dev->name, slave_dev->name,
-		bond_is_active_slave(new_slave) ? "n active" : " backup",
-		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+		bond_is_active_slave(new_slave) ? "an active" : "a backup",
+		new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
 
 	/* enslave is successful */
 	return 0;
@@ -1593,7 +1590,7 @@ err_restore_mac:
 		 * MAC if this slave's MAC is in use by the bond, or at
 		 * least print a warning.
 		 */
-		memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
+		ether_addr_copy(addr.sa_data, new_slave->perm_hwaddr);
 		addr.sa_family = slave_dev->type;
 		dev_set_mac_address(slave_dev, &addr);
 	}
@@ -1638,7 +1635,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    !netdev_has_upper_dev(slave_dev, bond_dev)) {
-		pr_err("%s: Error: cannot release %s.\n",
+		pr_err("%s: Error: cannot release %s\n",
 		       bond_dev->name, slave_dev->name);
 		return -EINVAL;
 	}
@@ -1654,9 +1651,6 @@ static int __bond_release_one(struct net_device *bond_dev,
 		return -EINVAL;
 	}
 
-	/* release the slave from its bond */
-	bond->slave_cnt--;
-
 	bond_sysfs_slave_del(slave);
 
 	bond_upper_dev_unlink(bond_dev, slave_dev);
@@ -1672,7 +1666,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 
 	write_unlock_bh(&bond->lock);
 
-	pr_info("%s: releasing %s interface %s\n",
+	pr_info("%s: Releasing %s interface %s\n",
 		bond_dev->name,
 		bond_is_active_slave(slave) ? "active" : "backup",
 		slave_dev->name);
@@ -1685,10 +1679,10 @@ static int __bond_release_one(struct net_device *bond_dev,
 		     bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
 		if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
 		    bond_has_slaves(bond))
-			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
-				   bond_dev->name, slave_dev->name,
-				   slave->perm_hwaddr,
-				   bond_dev->name, slave_dev->name);
+			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
+				bond_dev->name, slave_dev->name,
+				slave->perm_hwaddr,
+				bond_dev->name, slave_dev->name);
 	}
 
 	if (bond->primary_slave == slave)
@@ -1729,15 +1723,16 @@ static int __bond_release_one(struct net_device *bond_dev,
 		eth_hw_addr_random(bond_dev);
 
 		if (vlan_uses_dev(bond_dev)) {
-			pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
-				   bond_dev->name, bond_dev->name);
-			pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
-				   bond_dev->name);
+			pr_warn("%s: Warning: clearing HW address of %s while it still has VLANs\n",
+				bond_dev->name, bond_dev->name);
+			pr_warn("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs\n",
+				bond_dev->name);
 		}
 	}
 
 	unblock_netpoll_tx();
 	synchronize_rcu();
+	bond->slave_cnt--;
 
 	if (!bond_has_slaves(bond)) {
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
@@ -1747,7 +1742,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	bond_compute_features(bond);
 	if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
 	    (old_features & NETIF_F_VLAN_CHALLENGED))
-		pr_info("%s: last VLAN challenged slave %s left bond %s. VLAN blocking is removed\n",
+		pr_info("%s: last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
 			bond_dev->name, slave_dev->name, bond_dev->name);
 
 	/* must do this from outside any spinlocks */
@@ -1782,7 +1777,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	if (bond->params.fail_over_mac != BOND_FOM_ACTIVE ||
 	    bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 		/* restore original ("permanent") mac address */
-		memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+		ether_addr_copy(addr.sa_data, slave->perm_hwaddr);
 		addr.sa_family = slave_dev->type;
 		dev_set_mac_address(slave_dev, &addr);
 	}
@@ -1815,7 +1810,7 @@ static int  bond_release_and_destroy(struct net_device *bond_dev,
 	ret = bond_release(bond_dev, slave_dev);
 	if (ret == 0 && !bond_has_slaves(bond)) {
 		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
-		pr_info("%s: destroying bond %s.\n",
+		pr_info("%s: Destroying bond %s\n",
 			bond_dev->name, bond_dev->name);
 		unregister_netdevice(bond_dev);
 	}
@@ -1829,9 +1824,7 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
 	info->bond_mode = bond->params.mode;
 	info->miimon = bond->params.miimon;
 
-	read_lock(&bond->lock);
 	info->num_slaves = bond->slave_cnt;
-	read_unlock(&bond->lock);
 
 	return 0;
 }
@@ -1843,7 +1836,6 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 	int i = 0, res = -ENODEV;
 	struct slave *slave;
 
-	read_lock(&bond->lock);
 	bond_for_each_slave(bond, slave, iter) {
 		if (i++ == (int)info->slave_id) {
 			res = 0;
@@ -1854,7 +1846,6 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 			break;
 		}
 	}
-	read_unlock(&bond->lock);
 
 	return res;
 }
@@ -1884,7 +1875,7 @@ static int bond_miimon_inspect(struct bonding *bond)
 			slave->link = BOND_LINK_FAIL;
 			slave->delay = bond->params.downdelay;
 			if (slave->delay) {
-				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms.\n",
+				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n",
 					bond->dev->name,
 					(bond->params.mode ==
 					 BOND_MODE_ACTIVEBACKUP) ?
@@ -1900,8 +1891,8 @@ static int bond_miimon_inspect(struct bonding *bond)
 				 * recovered before downdelay expired
 				 */
 				slave->link = BOND_LINK_UP;
-				slave->jiffies = jiffies;
-				pr_info("%s: link status up again after %d ms for interface %s.\n",
+				slave->last_link_up = jiffies;
+				pr_info("%s: link status up again after %d ms for interface %s\n",
 					bond->dev->name,
 					(bond->params.downdelay - slave->delay) *
 					bond->params.miimon,
@@ -1926,7 +1917,7 @@ static int bond_miimon_inspect(struct bonding *bond)
 			slave->delay = bond->params.updelay;
 
 			if (slave->delay) {
-				pr_info("%s: link status up for interface %s, enabling it in %d ms.\n",
+				pr_info("%s: link status up for interface %s, enabling it in %d ms\n",
 					bond->dev->name, slave->dev->name,
 					ignore_updelay ? 0 :
 					bond->params.updelay *
@@ -1936,7 +1927,7 @@ static int bond_miimon_inspect(struct bonding *bond)
 		case BOND_LINK_BACK:
 			if (!link_state) {
 				slave->link = BOND_LINK_DOWN;
-				pr_info("%s: link status down again after %d ms for interface %s.\n",
+				pr_info("%s: link status down again after %d ms for interface %s\n",
 					bond->dev->name,
 					(bond->params.updelay - slave->delay) *
 					bond->params.miimon,
@@ -1975,7 +1966,7 @@ static void bond_miimon_commit(struct bonding *bond)
 
 		case BOND_LINK_UP:
 			slave->link = BOND_LINK_UP;
-			slave->jiffies = jiffies;
+			slave->last_link_up = jiffies;
 
 			if (bond->params.mode == BOND_MODE_8023AD) {
 				/* prevent it from being the active one */
@@ -1988,7 +1979,7 @@ static void bond_miimon_commit(struct bonding *bond)
 				bond_set_backup_slave(slave);
 			}
 
-			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
+			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex\n",
 				bond->dev->name, slave->dev->name,
 				slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
 				slave->duplex ? "full" : "half");
@@ -2015,7 +2006,8 @@ static void bond_miimon_commit(struct bonding *bond)
 
 			if (bond->params.mode == BOND_MODE_ACTIVEBACKUP ||
 			    bond->params.mode == BOND_MODE_8023AD)
-				bond_set_slave_inactive_flags(slave);
+				bond_set_slave_inactive_flags(slave,
+							      BOND_SLAVE_NOTIFY_NOW);
 
 			pr_info("%s: link status definitely down for interface %s, disabling it\n",
 				bond->dev->name, slave->dev->name);
@@ -2136,8 +2128,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
 {
 	struct sk_buff *skb;
 
-	pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n", arp_op,
-		 slave_dev->name, &dest_ip, &src_ip, vlan_id);
+	pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n",
+		 arp_op, slave_dev->name, &dest_ip, &src_ip, vlan_id);
 
 	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
 			 NULL, slave_dev->dev_addr, NULL);
@@ -2172,8 +2164,13 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 		rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
 				     RTO_ONLINK, 0);
 		if (IS_ERR(rt)) {
-			pr_debug("%s: no route to arp_ip_target %pI4\n",
-				 bond->dev->name, &targets[i]);
+			/* there's no route to target - try to send arp
+			 * probe to generate any traffic (arp_validate=0)
+			 */
+			if (bond->params.arp_validate && net_ratelimit())
+				pr_warn("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
+					bond->dev->name, &targets[i]);
+			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 0, 0);
 			continue;
 		}
 
@@ -2251,7 +2248,7 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
 		pr_debug("bva: sip %pI4 not found in targets\n", &sip);
 		return;
 	}
-	slave->last_arp_rx = jiffies;
+	slave->last_rx = jiffies;
 	slave->target_last_arp_rx[i] = jiffies;
 }
 
@@ -2259,17 +2256,19 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
 		 struct slave *slave)
 {
 	struct arphdr *arp = (struct arphdr *)skb->data;
+	struct slave *curr_active_slave;
 	unsigned char *arp_ptr;
 	__be32 sip, tip;
-	int alen;
+	int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
 
-	if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
+	if (!slave_do_arp_validate(bond, slave)) {
+		if ((slave_do_arp_validate_only(bond, slave) && is_arp) ||
+		    !slave_do_arp_validate_only(bond, slave))
+			slave->last_rx = jiffies;
 		return RX_HANDLER_ANOTHER;
-
-	read_lock(&bond->lock);
-
-	if (!slave_do_arp_validate(bond, slave))
-		goto out_unlock;
+	} else if (!is_arp) {
+		return RX_HANDLER_ANOTHER;
+	}
 
 	alen = arp_hdr_len(bond->dev);
 
@@ -2303,6 +2302,8 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
 		 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
 		 &sip, &tip);
 
+	curr_active_slave = rcu_dereference(bond->curr_active_slave);
+
 	/*
 	 * Backup slaves won't see the ARP reply, but do come through
 	 * here for each ARP probe (so we swap the sip/tip to validate
@@ -2316,15 +2317,15 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
 	 * is done to avoid endless looping when we can't reach the
 	 * arp_ip_target and fool ourselves with our own arp requests.
 	 */
+
 	if (bond_is_active_slave(slave))
 		bond_validate_arp(bond, slave, sip, tip);
-	else if (bond->curr_active_slave &&
-		 time_after(slave_last_rx(bond, bond->curr_active_slave),
-			    bond->curr_active_slave->jiffies))
+	else if (curr_active_slave &&
+		 time_after(slave_last_rx(bond, curr_active_slave),
+			    curr_active_slave->last_link_up))
 		bond_validate_arp(bond, slave, tip, sip);
 
 out_unlock:
-	read_unlock(&bond->lock);
 	if (arp != (struct arphdr *)skb->data)
 		kfree(arp);
 	return RX_HANDLER_ANOTHER;
@@ -2367,9 +2368,9 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
 	oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
 	/* see if any of the previous devices are up now (i.e. they have
 	 * xmt and rcv traffic). the curr_active_slave does not come into
-	 * the picture unless it is null. also, slave->jiffies is not needed
-	 * here because we send an arp on each slave and give a slave as
-	 * long as it needs to get the tx/rx within the delta.
+	 * the picture unless it is null. also, slave->last_link_up is not
+	 * needed here because we send an arp on each slave and give a slave
+	 * as long as it needs to get the tx/rx within the delta.
 	 * TODO: what about up/down delay in arp mode? it wasn't here before
 	 *       so it can wait
 	 */
@@ -2378,7 +2379,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
 
 		if (slave->link != BOND_LINK_UP) {
 			if (bond_time_in_interval(bond, trans_start, 1) &&
-			    bond_time_in_interval(bond, slave->dev->last_rx, 1)) {
+			    bond_time_in_interval(bond, slave->last_rx, 1)) {
 
 				slave->link  = BOND_LINK_UP;
 				slave_state_changed = 1;
@@ -2389,7 +2390,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
 				 * is closed.
 				 */
 				if (!oldcurrent) {
-					pr_info("%s: link status definitely up for interface %s, ",
+					pr_info("%s: link status definitely up for interface %s\n",
 						bond->dev->name,
 						slave->dev->name);
 					do_failover = 1;
@@ -2407,7 +2408,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
 			 * if we don't know our ip yet
 			 */
 			if (!bond_time_in_interval(bond, trans_start, 2) ||
-			    !bond_time_in_interval(bond, slave->dev->last_rx, 2)) {
+			    !bond_time_in_interval(bond, slave->last_rx, 2)) {
 
 				slave->link  = BOND_LINK_DOWN;
 				slave_state_changed = 1;
@@ -2415,9 +2416,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
 				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
 
-				pr_info("%s: interface %s is now down.\n",
-					bond->dev->name,
-					slave->dev->name);
+				pr_info("%s: interface %s is now down\n",
+					bond->dev->name, slave->dev->name);
 
 				if (slave == oldcurrent)
 					do_failover = 1;
@@ -2496,7 +2496,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
 		 * active.  This avoids bouncing, as the last receive
 		 * times need a full ARP monitor cycle to be updated.
 		 */
-		if (bond_time_in_interval(bond, slave->jiffies, 2))
+		if (bond_time_in_interval(bond, slave->last_link_up, 2))
 			continue;
 
 		/*
@@ -2562,11 +2562,12 @@ static void bond_ab_arp_commit(struct bonding *bond)
 				slave->link = BOND_LINK_UP;
 				if (bond->current_arp_slave) {
 					bond_set_slave_inactive_flags(
-						bond->current_arp_slave);
+						bond->current_arp_slave,
+						BOND_SLAVE_NOTIFY_NOW);
 					bond->current_arp_slave = NULL;
 				}
 
-				pr_info("%s: link status definitely up for interface %s.\n",
+				pr_info("%s: link status definitely up for interface %s\n",
 					bond->dev->name, slave->dev->name);
 
 				if (!bond->curr_active_slave ||
@@ -2582,7 +2583,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
 				slave->link_failure_count++;
 
 			slave->link = BOND_LINK_DOWN;
-			bond_set_slave_inactive_flags(slave);
+			bond_set_slave_inactive_flags(slave,
+						      BOND_SLAVE_NOTIFY_NOW);
 
 			pr_info("%s: link status definitely down for interface %s, disabling it\n",
 				bond->dev->name, slave->dev->name);
@@ -2615,17 +2617,17 @@ do_failover:
 
 /*
  * Send ARP probes for active-backup mode ARP monitor.
+ *
+ * Called with rcu_read_lock hold.
  */
 static bool bond_ab_arp_probe(struct bonding *bond)
 {
 	struct slave *slave, *before = NULL, *new_slave = NULL,
-		     *curr_arp_slave, *curr_active_slave;
+		     *curr_arp_slave = rcu_dereference(bond->current_arp_slave),
+		     *curr_active_slave = rcu_dereference(bond->curr_active_slave);
 	struct list_head *iter;
 	bool found = false;
-
-	rcu_read_lock();
-	curr_arp_slave = rcu_dereference(bond->current_arp_slave);
-	curr_active_slave = rcu_dereference(bond->curr_active_slave);
+	bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
 
 	if (curr_arp_slave && curr_active_slave)
 		pr_info("PROBE: c_arp %s && cas %s BAD\n",
@@ -2634,32 +2636,23 @@ static bool bond_ab_arp_probe(struct bonding *bond)
 
 	if (curr_active_slave) {
 		bond_arp_send_all(bond, curr_active_slave);
-		rcu_read_unlock();
-		return true;
+		return should_notify_rtnl;
 	}
-	rcu_read_unlock();
 
 	/* if we don't have a curr_active_slave, search for the next available
 	 * backup slave from the current_arp_slave and make it the candidate
 	 * for becoming the curr_active_slave
 	 */
 
-	if (!rtnl_trylock())
-		return false;
-	/* curr_arp_slave might have gone away */
-	curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave);
-
 	if (!curr_arp_slave) {
-		curr_arp_slave = bond_first_slave(bond);
-		if (!curr_arp_slave) {
-			rtnl_unlock();
-			return true;
-		}
+		curr_arp_slave = bond_first_slave_rcu(bond);
+		if (!curr_arp_slave)
+			return should_notify_rtnl;
 	}
 
-	bond_set_slave_inactive_flags(curr_arp_slave);
+	bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER);
 
-	bond_for_each_slave(bond, slave, iter) {
+	bond_for_each_slave_rcu(bond, slave, iter) {
 		if (!found && !before && IS_UP(slave->dev))
 			before = slave;
 
@@ -2677,9 +2670,10 @@ static bool bond_ab_arp_probe(struct bonding *bond)
 			if (slave->link_failure_count < UINT_MAX)
 				slave->link_failure_count++;
 
-			bond_set_slave_inactive_flags(slave);
+			bond_set_slave_inactive_flags(slave,
+						      BOND_SLAVE_NOTIFY_LATER);
 
-			pr_info("%s: backup interface %s is now down.\n",
+			pr_info("%s: backup interface %s is now down\n",
 				bond->dev->name, slave->dev->name);
 		}
 		if (slave == curr_arp_slave)
@@ -2689,26 +2683,31 @@ static bool bond_ab_arp_probe(struct bonding *bond)
 	if (!new_slave && before)
 		new_slave = before;
 
-	if (!new_slave) {
-		rtnl_unlock();
-		return true;
-	}
+	if (!new_slave)
+		goto check_state;
 
 	new_slave->link = BOND_LINK_BACK;
-	bond_set_slave_active_flags(new_slave);
+	bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
 	bond_arp_send_all(bond, new_slave);
-	new_slave->jiffies = jiffies;
+	new_slave->last_link_up = jiffies;
 	rcu_assign_pointer(bond->current_arp_slave, new_slave);
-	rtnl_unlock();
 
-	return true;
+check_state:
+	bond_for_each_slave_rcu(bond, slave, iter) {
+		if (slave->should_notify) {
+			should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
+			break;
+		}
+	}
+	return should_notify_rtnl;
 }
 
 static void bond_activebackup_arp_mon(struct work_struct *work)
 {
 	struct bonding *bond = container_of(work, struct bonding,
 					    arp_work.work);
-	bool should_notify_peers = false, should_commit = false;
+	bool should_notify_peers = false;
+	bool should_notify_rtnl = false;
 	int delta_in_ticks;
 
 	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
@@ -2717,11 +2716,12 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
 		goto re_arm;
 
 	rcu_read_lock();
+
 	should_notify_peers = bond_should_notify_peers(bond);
-	should_commit = bond_ab_arp_inspect(bond);
-	rcu_read_unlock();
 
-	if (should_commit) {
+	if (bond_ab_arp_inspect(bond)) {
+		rcu_read_unlock();
+
 		/* Race avoidance with bond_close flush of workqueue */
 		if (!rtnl_trylock()) {
 			delta_in_ticks = 1;
@@ -2730,23 +2730,28 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
 		}
 
 		bond_ab_arp_commit(bond);
+
 		rtnl_unlock();
+		rcu_read_lock();
 	}
 
-	if (!bond_ab_arp_probe(bond)) {
-		/* rtnl locking failed, re-arm */
-		delta_in_ticks = 1;
-		should_notify_peers = false;
-	}
+	should_notify_rtnl = bond_ab_arp_probe(bond);
+	rcu_read_unlock();
 
 re_arm:
 	if (bond->params.arp_interval)
 		queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
 
-	if (should_notify_peers) {
+	if (should_notify_peers || should_notify_rtnl) {
 		if (!rtnl_trylock())
 			return;
-		call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
+
+		if (should_notify_peers)
+			call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
+						 bond->dev);
+		if (should_notify_rtnl)
+			bond_slave_state_notify(bond);
+
 		rtnl_unlock();
 	}
 }
@@ -2865,9 +2870,9 @@ static int bond_slave_netdev_event(unsigned long event,
 			break;
 		}
 
-		pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
-			bond->dev->name, bond->primary_slave ? slave_dev->name :
-							       "none");
+		pr_info("%s: Primary slave changed to %s, reselecting active slave\n",
+			bond->dev->name,
+			bond->primary_slave ? slave_dev->name : "none");
 
 		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
@@ -2903,8 +2908,7 @@ static int bond_netdev_event(struct notifier_block *this,
 	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
 
 	pr_debug("event_dev: %s, event: %lx\n",
-		 event_dev ? event_dev->name : "None",
-		 event);
+		 event_dev ? event_dev->name : "None", event);
 
 	if (!(event_dev->priv_flags & IFF_BONDING))
 		return NOTIFY_DONE;
@@ -3046,9 +3050,11 @@ static int bond_open(struct net_device *bond_dev)
 		bond_for_each_slave(bond, slave, iter) {
 			if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
 				&& (slave != bond->curr_active_slave)) {
-				bond_set_slave_inactive_flags(slave);
+				bond_set_slave_inactive_flags(slave,
+							      BOND_SLAVE_NOTIFY_NOW);
 			} else {
-				bond_set_slave_active_flags(slave);
+				bond_set_slave_active_flags(slave,
+							    BOND_SLAVE_NOTIFY_NOW);
 			}
 		}
 		read_unlock(&bond->curr_slave_lock);
@@ -3071,8 +3077,7 @@ static int bond_open(struct net_device *bond_dev)
 
 	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
 		queue_delayed_work(bond->wq, &bond->arp_work, 0);
-		if (bond->params.arp_validate)
-			bond->recv_probe = bond_arp_rcv;
+		bond->recv_probe = bond_arp_rcv;
 	}
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
@@ -3359,8 +3364,8 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 	struct list_head *iter;
 	int res = 0;
 
-	pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
-		 (bond_dev ? bond_dev->name : "None"), new_mtu);
+	pr_debug("bond=%p, name=%s, new_mtu=%d\n",
+		 bond, bond_dev ? bond_dev->name : "None", new_mtu);
 
 	/* Can't hold bond->lock with bh disabled here since
 	 * some base drivers panic. On the other hand we can't
@@ -3379,8 +3384,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 
 	bond_for_each_slave(bond, slave, iter) {
 		pr_debug("s %p c_m %p\n",
-			 slave,
-			 slave->dev->netdev_ops->ndo_change_mtu);
+			 slave, slave->dev->netdev_ops->ndo_change_mtu);
 
 		res = dev_set_mtu(slave->dev, new_mtu);
 
@@ -3468,15 +3472,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 	 */
 
 	bond_for_each_slave(bond, slave, iter) {
-		const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
 		pr_debug("slave %p %s\n", slave, slave->dev->name);
-
-		if (slave_ops->ndo_set_mac_address == NULL) {
-			res = -EOPNOTSUPP;
-			pr_debug("EOPNOTSUPP %s\n", slave->dev->name);
-			goto unwind;
-		}
-
 		res = dev_set_mac_address(slave->dev, addr);
 		if (res) {
 			/* TODO: consider downing the slave
@@ -3942,7 +3938,7 @@ static void bond_uninit(struct net_device *bond_dev)
 	/* Release the bonded slaves */
 	bond_for_each_slave(bond, slave, iter)
 		__bond_release_one(bond_dev, slave->dev, true);
-	pr_info("%s: released all slaves\n", bond_dev->name);
+	pr_info("%s: Released all slaves\n", bond_dev->name);
 
 	list_del(&bond->bond_list);
 
@@ -4020,7 +4016,7 @@ static int bond_check_params(struct bond_params *params)
 		if ((bond_mode != BOND_MODE_XOR) &&
 		    (bond_mode != BOND_MODE_8023AD)) {
 			pr_info("xmit_hash_policy param is irrelevant in mode %s\n",
-			       bond_mode_name(bond_mode));
+				bond_mode_name(bond_mode));
 		} else {
 			bond_opt_initstr(&newval, xmit_hash_policy);
 			valptr = bond_opt_parse(bond_opt_get(BOND_OPT_XMIT_HASH),
@@ -4061,74 +4057,71 @@ static int bond_check_params(struct bond_params *params)
 		}
 		params->ad_select = valptr->value;
 		if (bond_mode != BOND_MODE_8023AD)
-			pr_warning("ad_select param only affects 802.3ad mode\n");
+			pr_warn("ad_select param only affects 802.3ad mode\n");
 	} else {
 		params->ad_select = BOND_AD_STABLE;
 	}
 
 	if (max_bonds < 0) {
-		pr_warning("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
-			   max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
+		pr_warn("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
+			max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
 		max_bonds = BOND_DEFAULT_MAX_BONDS;
 	}
 
 	if (miimon < 0) {
-		pr_warning("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n",
-			   miimon, INT_MAX);
+		pr_warn("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			miimon, INT_MAX);
 		miimon = 0;
 	}
 
 	if (updelay < 0) {
-		pr_warning("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
-			   updelay, INT_MAX);
+		pr_warn("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			updelay, INT_MAX);
 		updelay = 0;
 	}
 
 	if (downdelay < 0) {
-		pr_warning("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
-			   downdelay, INT_MAX);
+		pr_warn("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			downdelay, INT_MAX);
 		downdelay = 0;
 	}
 
 	if ((use_carrier != 0) && (use_carrier != 1)) {
-		pr_warning("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n",
-			   use_carrier);
+		pr_warn("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n",
+			use_carrier);
 		use_carrier = 1;
 	}
 
 	if (num_peer_notif < 0 || num_peer_notif > 255) {
-		pr_warning("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
-			   num_peer_notif);
+		pr_warn("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
+			num_peer_notif);
 		num_peer_notif = 1;
 	}
 
 	/* reset values for 802.3ad/TLB/ALB */
 	if (BOND_NO_USES_ARP(bond_mode)) {
 		if (!miimon) {
-			pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
-			pr_warning("Forcing miimon to 100msec\n");
+			pr_warn("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
+			pr_warn("Forcing miimon to 100msec\n");
 			miimon = BOND_DEFAULT_MIIMON;
 		}
 	}
 
 	if (tx_queues < 1 || tx_queues > 255) {
-		pr_warning("Warning: tx_queues (%d) should be between "
-			   "1 and 255, resetting to %d\n",
-			   tx_queues, BOND_DEFAULT_TX_QUEUES);
+		pr_warn("Warning: tx_queues (%d) should be between 1 and 255, resetting to %d\n",
+			tx_queues, BOND_DEFAULT_TX_QUEUES);
 		tx_queues = BOND_DEFAULT_TX_QUEUES;
 	}
 
 	if ((all_slaves_active != 0) && (all_slaves_active != 1)) {
-		pr_warning("Warning: all_slaves_active module parameter (%d), "
-			   "not of valid value (0/1), so it was set to "
-			   "0\n", all_slaves_active);
+		pr_warn("Warning: all_slaves_active module parameter (%d), not of valid value (0/1), so it was set to 0\n",
+			all_slaves_active);
 		all_slaves_active = 0;
 	}
 
 	if (resend_igmp < 0 || resend_igmp > 255) {
-		pr_warning("Warning: resend_igmp (%d) should be between "
-			   "0 and 255, resetting to %d\n",
-			   resend_igmp, BOND_DEFAULT_RESEND_IGMP);
+		pr_warn("Warning: resend_igmp (%d) should be between 0 and 255, resetting to %d\n",
+			resend_igmp, BOND_DEFAULT_RESEND_IGMP);
 		resend_igmp = BOND_DEFAULT_RESEND_IGMP;
 	}
 
@@ -4149,37 +4142,36 @@ static int bond_check_params(struct bond_params *params)
 			/* just warn the user the up/down delay will have
 			 * no effect since miimon is zero...
 			 */
-			pr_warning("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n",
-				   updelay, downdelay);
+			pr_warn("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n",
+				updelay, downdelay);
 		}
 	} else {
 		/* don't allow arp monitoring */
 		if (arp_interval) {
-			pr_warning("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n",
-				   miimon, arp_interval);
+			pr_warn("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n",
+				miimon, arp_interval);
 			arp_interval = 0;
 		}
 
 		if ((updelay % miimon) != 0) {
-			pr_warning("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
-				   updelay, miimon,
-				   (updelay / miimon) * miimon);
+			pr_warn("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
+				updelay, miimon, (updelay / miimon) * miimon);
 		}
 
 		updelay /= miimon;
 
 		if ((downdelay % miimon) != 0) {
-			pr_warning("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n",
-				   downdelay, miimon,
-				   (downdelay / miimon) * miimon);
+			pr_warn("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n",
+				downdelay, miimon,
+				(downdelay / miimon) * miimon);
 		}
 
 		downdelay /= miimon;
 	}
 
 	if (arp_interval < 0) {
-		pr_warning("Warning: arp_interval module parameter (%d) , not in range 0-%d, so it was reset to 0\n",
-			   arp_interval, INT_MAX);
+		pr_warn("Warning: arp_interval module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			arp_interval, INT_MAX);
 		arp_interval = 0;
 	}
 
@@ -4190,30 +4182,26 @@ static int bond_check_params(struct bond_params *params)
 		__be32 ip;
 		if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) ||
 		    IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) {
-			pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
-				   arp_ip_target[i]);
+			pr_warn("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
+				arp_ip_target[i]);
 			arp_interval = 0;
 		} else {
 			if (bond_get_targets_ip(arp_target, ip) == -1)
 				arp_target[arp_ip_count++] = ip;
 			else
-				pr_warning("Warning: duplicate address %pI4 in arp_ip_target, skipping\n",
-					   &ip);
+				pr_warn("Warning: duplicate address %pI4 in arp_ip_target, skipping\n",
+					&ip);
 		}
 	}
 
 	if (arp_interval && !arp_ip_count) {
 		/* don't allow arping if no arp_ip_target given... */
-		pr_warning("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n",
-			   arp_interval);
+		pr_warn("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n",
+			arp_interval);
 		arp_interval = 0;
 	}
 
 	if (arp_validate) {
-		if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
-			pr_err("arp_validate only supported in active-backup mode\n");
-			return -EINVAL;
-		}
 		if (!arp_interval) {
 			pr_err("arp_validate requires arp_interval\n");
 			return -EINVAL;
@@ -4255,23 +4243,23 @@ static int bond_check_params(struct bond_params *params)
 			arp_interval, valptr->string, arp_ip_count);
 
 		for (i = 0; i < arp_ip_count; i++)
-			pr_info(" %s", arp_ip_target[i]);
+			pr_cont(" %s", arp_ip_target[i]);
 
-		pr_info("\n");
+		pr_cont("\n");
 
 	} else if (max_bonds) {
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
-		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
+		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details\n");
 	}
 
 	if (primary && !USES_PRIMARY(bond_mode)) {
 		/* currently, using a primary only makes sense
 		 * in active backup, TLB or ALB modes
 		 */
-		pr_warning("Warning: %s primary device specified but has no effect in %s mode\n",
-			   primary, bond_mode_name(bond_mode));
+		pr_warn("Warning: %s primary device specified but has no effect in %s mode\n",
+			primary, bond_mode_name(bond_mode));
 		primary = NULL;
 	}
 
@@ -4300,14 +4288,14 @@ static int bond_check_params(struct bond_params *params)
 		}
 		fail_over_mac_value = valptr->value;
 		if (bond_mode != BOND_MODE_ACTIVEBACKUP)
-			pr_warning("Warning: fail_over_mac only affects active-backup mode.\n");
+			pr_warn("Warning: fail_over_mac only affects active-backup mode\n");
 	} else {
 		fail_over_mac_value = BOND_FOM_NONE;
 	}
 
 	if (lp_interval == 0) {
-		pr_warning("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
-			   INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
+		pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
+			INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
 		lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
 	}
 
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 70651f8e8e3b..20659b114f24 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -181,7 +181,7 @@ static int bond_changelink(struct net_device *bond_dev,
 		int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
 
 		if (arp_interval && miimon) {
-			pr_err("%s: ARP monitoring cannot be used with MII monitoring.\n",
+			pr_err("%s: ARP monitoring cannot be used with MII monitoring\n",
 			       bond->dev->name);
 			return -EINVAL;
 		}
@@ -207,7 +207,7 @@ static int bond_changelink(struct net_device *bond_dev,
 			i++;
 		}
 		if (i == 0 && bond->params.arp_interval)
-			pr_warn("%s: removing last arp target with arp_interval on\n",
+			pr_warn("%s: Removing last arp target with arp_interval on\n",
 				bond->dev->name);
 		if (err)
 			return err;
@@ -216,7 +216,7 @@ static int bond_changelink(struct net_device *bond_dev,
 		int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
 
 		if (arp_validate && miimon) {
-			pr_err("%s: ARP validating cannot be used with MII monitoring.\n",
+			pr_err("%s: ARP validating cannot be used with MII monitoring\n",
 			       bond->dev->name);
 			return -EINVAL;
 		}
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index c37878432717..23f365510b58 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -47,11 +47,14 @@ static struct bond_opt_value bond_xmit_hashtype_tbl[] = {
 };
 
 static struct bond_opt_value bond_arp_validate_tbl[] = {
-	{ "none",   BOND_ARP_VALIDATE_NONE,   BOND_VALFLAG_DEFAULT},
-	{ "active", BOND_ARP_VALIDATE_ACTIVE, 0},
-	{ "backup", BOND_ARP_VALIDATE_BACKUP, 0},
-	{ "all",    BOND_ARP_VALIDATE_ALL,    0},
-	{ NULL,     -1,                       0},
+	{ "none",		BOND_ARP_VALIDATE_NONE,		BOND_VALFLAG_DEFAULT},
+	{ "active",		BOND_ARP_VALIDATE_ACTIVE,	0},
+	{ "backup",		BOND_ARP_VALIDATE_BACKUP,	0},
+	{ "all",		BOND_ARP_VALIDATE_ALL,		0},
+	{ "filter",		BOND_ARP_FILTER,		0},
+	{ "filter_active",	BOND_ARP_FILTER_ACTIVE,		0},
+	{ "filter_backup",	BOND_ARP_FILTER_BACKUP,		0},
+	{ NULL,			-1,				0},
 };
 
 static struct bond_opt_value bond_arp_all_targets_tbl[] = {
@@ -151,7 +154,8 @@ static struct bond_option bond_opts[] = {
 		.id = BOND_OPT_ARP_VALIDATE,
 		.name = "arp_validate",
 		.desc = "validate src/dst of ARP probes",
-		.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP)),
+		.unsuppmodes = BIT(BOND_MODE_8023AD) | BIT(BOND_MODE_TLB) |
+			       BIT(BOND_MODE_ALB),
 		.values = bond_arp_validate_tbl,
 		.set = bond_option_arp_validate_set
 	},
@@ -473,10 +477,10 @@ static void bond_opt_error_interpret(struct bonding *bond,
 				p = strchr(val->string, '\n');
 				if (p)
 					*p = '\0';
-				pr_err("%s: option %s: invalid value (%s).\n",
+				pr_err("%s: option %s: invalid value (%s)\n",
 				       bond->dev->name, opt->name, val->string);
 			} else {
-				pr_err("%s: option %s: invalid value (%llu).\n",
+				pr_err("%s: option %s: invalid value (%llu)\n",
 				       bond->dev->name, opt->name, val->value);
 			}
 		}
@@ -484,7 +488,7 @@ static void bond_opt_error_interpret(struct bonding *bond,
 		maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX);
 		if (!maxval)
 			break;
-		pr_err("%s: option %s: allowed values %llu - %llu.\n",
+		pr_err("%s: option %s: allowed values %llu - %llu\n",
 		       bond->dev->name, opt->name, minval ? minval->value : 0,
 		       maxval->value);
 		break;
@@ -492,11 +496,11 @@ static void bond_opt_error_interpret(struct bonding *bond,
 		bond_opt_dep_print(bond, opt);
 		break;
 	case -ENOTEMPTY:
-		pr_err("%s: option %s: unable to set because the bond device has slaves.\n",
+		pr_err("%s: option %s: unable to set because the bond device has slaves\n",
 		       bond->dev->name, opt->name);
 		break;
 	case -EBUSY:
-		pr_err("%s: option %s: unable to set because the bond device is up.\n",
+		pr_err("%s: option %s: unable to set because the bond device is up\n",
 		       bond->dev->name, opt->name);
 		break;
 	default:
@@ -589,7 +593,7 @@ int bond_option_mode_set(struct bonding *bond, struct bond_opt_value *newval)
 		bond->params.arp_interval = 0;
 		/* set miimon to default value */
 		bond->params.miimon = BOND_DEFAULT_MIIMON;
-		pr_info("%s: Setting MII monitoring interval to %d.\n",
+		pr_info("%s: Setting MII monitoring interval to %d\n",
 			bond->dev->name, bond->params.miimon);
 	}
 
@@ -636,13 +640,13 @@ int bond_option_active_slave_set(struct bonding *bond,
 
 	if (slave_dev) {
 		if (!netif_is_bond_slave(slave_dev)) {
-			pr_err("Device %s is not bonding slave.\n",
+			pr_err("Device %s is not bonding slave\n",
 			       slave_dev->name);
 			return -EINVAL;
 		}
 
 		if (bond->dev != netdev_master_upper_dev_get(slave_dev)) {
-			pr_err("%s: Device %s is not our slave.\n",
+			pr_err("%s: Device %s is not our slave\n",
 			       bond->dev->name, slave_dev->name);
 			return -EINVAL;
 		}
@@ -653,8 +657,7 @@ int bond_option_active_slave_set(struct bonding *bond,
 
 	/* check to see if we are clearing active */
 	if (!slave_dev) {
-		pr_info("%s: Clearing current active slave.\n",
-		bond->dev->name);
+		pr_info("%s: Clearing current active slave\n", bond->dev->name);
 		rcu_assign_pointer(bond->curr_active_slave, NULL);
 		bond_select_active_slave(bond);
 	} else {
@@ -665,16 +668,16 @@ int bond_option_active_slave_set(struct bonding *bond,
 
 		if (new_active == old_active) {
 			/* do nothing */
-			pr_info("%s: %s is already the current active slave.\n",
+			pr_info("%s: %s is already the current active slave\n",
 				bond->dev->name, new_active->dev->name);
 		} else {
 			if (old_active && (new_active->link == BOND_LINK_UP) &&
 			    IS_UP(new_active->dev)) {
-				pr_info("%s: Setting %s as active slave.\n",
+				pr_info("%s: Setting %s as active slave\n",
 					bond->dev->name, new_active->dev->name);
 				bond_change_active_slave(bond, new_active);
 			} else {
-				pr_err("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
+				pr_err("%s: Could not set %s as active slave; either %s is down or the link is down\n",
 				       bond->dev->name, new_active->dev->name,
 				       new_active->dev->name);
 				ret = -EINVAL;
@@ -690,19 +693,19 @@ int bond_option_active_slave_set(struct bonding *bond,
 
 int bond_option_miimon_set(struct bonding *bond, struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting MII monitoring interval to %llu.\n",
+	pr_info("%s: Setting MII monitoring interval to %llu\n",
 		bond->dev->name, newval->value);
 	bond->params.miimon = newval->value;
 	if (bond->params.updelay)
-		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
 			bond->dev->name,
 			bond->params.updelay * bond->params.miimon);
 	if (bond->params.downdelay)
-		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
 			bond->dev->name,
 			bond->params.downdelay * bond->params.miimon);
 	if (newval->value && bond->params.arp_interval) {
-		pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+		pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n",
 			bond->dev->name);
 		bond->params.arp_interval = 0;
 		if (bond->params.arp_validate)
@@ -742,9 +745,8 @@ int bond_option_updelay_set(struct bonding *bond, struct bond_opt_value *newval)
 			bond->params.miimon);
 	}
 	bond->params.updelay = value / bond->params.miimon;
-	pr_info("%s: Setting up delay to %d.\n",
-		bond->dev->name,
-		bond->params.updelay * bond->params.miimon);
+	pr_info("%s: Setting up delay to %d\n",
+		bond->dev->name, bond->params.updelay * bond->params.miimon);
 
 	return 0;
 }
@@ -767,9 +769,8 @@ int bond_option_downdelay_set(struct bonding *bond,
 			bond->params.miimon);
 	}
 	bond->params.downdelay = value / bond->params.miimon;
-	pr_info("%s: Setting down delay to %d.\n",
-		bond->dev->name,
-		bond->params.downdelay * bond->params.miimon);
+	pr_info("%s: Setting down delay to %d\n",
+		bond->dev->name, bond->params.downdelay * bond->params.miimon);
 
 	return 0;
 }
@@ -777,7 +778,7 @@ int bond_option_downdelay_set(struct bonding *bond,
 int bond_option_use_carrier_set(struct bonding *bond,
 				struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting use_carrier to %llu.\n",
+	pr_info("%s: Setting use_carrier to %llu\n",
 		bond->dev->name, newval->value);
 	bond->params.use_carrier = newval->value;
 
@@ -787,17 +788,17 @@ int bond_option_use_carrier_set(struct bonding *bond,
 int bond_option_arp_interval_set(struct bonding *bond,
 				 struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting ARP monitoring interval to %llu.\n",
+	pr_info("%s: Setting ARP monitoring interval to %llu\n",
 		bond->dev->name, newval->value);
 	bond->params.arp_interval = newval->value;
 	if (newval->value) {
 		if (bond->params.miimon) {
-			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n",
 				bond->dev->name, bond->dev->name);
 			bond->params.miimon = 0;
 		}
 		if (!bond->params.arp_targets[0])
-			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n",
 				bond->dev->name);
 	}
 	if (bond->dev->flags & IFF_UP) {
@@ -812,8 +813,7 @@ int bond_option_arp_interval_set(struct bonding *bond,
 			cancel_delayed_work_sync(&bond->arp_work);
 		} else {
 			/* arp_validate can be set only in active-backup mode */
-			if (bond->params.arp_validate)
-				bond->recv_probe = bond_arp_rcv;
+			bond->recv_probe = bond_arp_rcv;
 			cancel_delayed_work_sync(&bond->mii_work);
 			queue_delayed_work(bond->wq, &bond->arp_work, 0);
 		}
@@ -856,12 +856,11 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
 
 	ind = bond_get_targets_ip(targets, 0); /* first free slot */
 	if (ind == -1) {
-		pr_err("%s: ARP target table is full!\n",
-		       bond->dev->name);
+		pr_err("%s: ARP target table is full!\n", bond->dev->name);
 		return -EINVAL;
 	}
 
-	pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &target);
+	pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target);
 
 	_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
 
@@ -896,17 +895,16 @@ int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
 
 	ind = bond_get_targets_ip(targets, target);
 	if (ind == -1) {
-		pr_err("%s: unable to remove nonexistent ARP target %pI4.\n",
+		pr_err("%s: unable to remove nonexistent ARP target %pI4\n",
 		       bond->dev->name, &target);
 		return -EINVAL;
 	}
 
 	if (ind == 0 && !targets[1] && bond->params.arp_interval)
-		pr_warn("%s: removing last arp target with arp_interval on\n",
+		pr_warn("%s: Removing last arp target with arp_interval on\n",
 			bond->dev->name);
 
-	pr_info("%s: removing ARP target %pI4.\n", bond->dev->name,
-		&target);
+	pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);
 
 	/* not to race with bond_arp_rcv */
 	write_lock_bh(&bond->lock);
@@ -954,7 +952,7 @@ int bond_option_arp_ip_targets_set(struct bonding *bond,
 		else if (newval->string[0] == '-')
 			ret = bond_option_arp_ip_target_rem(bond, target);
 		else
-			pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+			pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n",
 			       bond->dev->name);
 	} else {
 		target = newval->value;
@@ -967,7 +965,7 @@ int bond_option_arp_ip_targets_set(struct bonding *bond,
 int bond_option_arp_validate_set(struct bonding *bond,
 				 struct bond_opt_value *newval)
 {
-	pr_info("%s: setting arp_validate to %s (%llu).\n",
+	pr_info("%s: Setting arp_validate to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 
 	if (bond->dev->flags & IFF_UP) {
@@ -984,7 +982,7 @@ int bond_option_arp_validate_set(struct bonding *bond,
 int bond_option_arp_all_targets_set(struct bonding *bond,
 				    struct bond_opt_value *newval)
 {
-	pr_info("%s: setting arp_all_targets to %s (%llu).\n",
+	pr_info("%s: Setting arp_all_targets to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.arp_all_targets = newval->value;
 
@@ -1006,8 +1004,7 @@ int bond_option_primary_set(struct bonding *bond, struct bond_opt_value *newval)
 		*p = '\0';
 	/* check to see if we are clearing primary */
 	if (!strlen(primary)) {
-		pr_info("%s: Setting primary slave to None.\n",
-			bond->dev->name);
+		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
 		bond->primary_slave = NULL;
 		memset(bond->params.primary, 0, sizeof(bond->params.primary));
 		bond_select_active_slave(bond);
@@ -1016,7 +1013,7 @@ int bond_option_primary_set(struct bonding *bond, struct bond_opt_value *newval)
 
 	bond_for_each_slave(bond, slave, iter) {
 		if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) {
-			pr_info("%s: Setting %s as primary slave.\n",
+			pr_info("%s: Setting %s as primary slave\n",
 				bond->dev->name, slave->dev->name);
 			bond->primary_slave = slave;
 			strcpy(bond->params.primary, slave->dev->name);
@@ -1026,15 +1023,14 @@ int bond_option_primary_set(struct bonding *bond, struct bond_opt_value *newval)
 	}
 
 	if (bond->primary_slave) {
-		pr_info("%s: Setting primary slave to None.\n",
-			bond->dev->name);
+		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
 		bond->primary_slave = NULL;
 		bond_select_active_slave(bond);
 	}
 	strncpy(bond->params.primary, primary, IFNAMSIZ);
 	bond->params.primary[IFNAMSIZ - 1] = 0;
 
-	pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet.\n",
+	pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n",
 		bond->dev->name, primary, bond->dev->name);
 
 out:
@@ -1048,7 +1044,7 @@ out:
 int bond_option_primary_reselect_set(struct bonding *bond,
 				     struct bond_opt_value *newval)
 {
-	pr_info("%s: setting primary_reselect to %s (%llu).\n",
+	pr_info("%s: Setting primary_reselect to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.primary_reselect = newval->value;
 
@@ -1064,7 +1060,7 @@ int bond_option_primary_reselect_set(struct bonding *bond,
 int bond_option_fail_over_mac_set(struct bonding *bond,
 				  struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting fail_over_mac to %s (%llu).\n",
+	pr_info("%s: Setting fail_over_mac to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.fail_over_mac = newval->value;
 
@@ -1074,7 +1070,7 @@ int bond_option_fail_over_mac_set(struct bonding *bond,
 int bond_option_xmit_hash_policy_set(struct bonding *bond,
 				     struct bond_opt_value *newval)
 {
-	pr_info("%s: setting xmit hash policy to %s (%llu).\n",
+	pr_info("%s: Setting xmit hash policy to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.xmit_policy = newval->value;
 
@@ -1084,7 +1080,7 @@ int bond_option_xmit_hash_policy_set(struct bonding *bond,
 int bond_option_resend_igmp_set(struct bonding *bond,
 				struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting resend_igmp to %llu.\n",
+	pr_info("%s: Setting resend_igmp to %llu\n",
 		bond->dev->name, newval->value);
 	bond->params.resend_igmp = newval->value;
 
@@ -1158,7 +1154,7 @@ int bond_option_pps_set(struct bonding *bond, struct bond_opt_value *newval)
 int bond_option_lacp_rate_set(struct bonding *bond,
 			      struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting LACP rate to %s (%llu).\n",
+	pr_info("%s: Setting LACP rate to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.lacp_fast = newval->value;
 	bond_3ad_update_lacp_rate(bond);
@@ -1169,7 +1165,7 @@ int bond_option_lacp_rate_set(struct bonding *bond,
 int bond_option_ad_select_set(struct bonding *bond,
 			      struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting ad_select to %s (%llu).\n",
+	pr_info("%s: Setting ad_select to %s (%llu)\n",
 		bond->dev->name, newval->string, newval->value);
 	bond->params.ad_select = newval->value;
 
@@ -1199,8 +1195,7 @@ int bond_option_queue_id_set(struct bonding *bond,
 		goto err_no_cmd;
 
 	/* Check buffer length, valid ifname and queue id */
-	if (strlen(newval->string) > IFNAMSIZ ||
-	    !dev_valid_name(newval->string) ||
+	if (!dev_valid_name(newval->string) ||
 	    qid > bond->dev->real_num_tx_queues)
 		goto err_no_cmd;
 
@@ -1232,8 +1227,7 @@ out:
 	return ret;
 
 err_no_cmd:
-	pr_info("invalid input for queue_id set for %s.\n",
-		bond->dev->name);
+	pr_info("invalid input for queue_id set for %s\n", bond->dev->name);
 	ret = -EPERM;
 	goto out;
 
@@ -1254,7 +1248,7 @@ int bond_option_slaves_set(struct bonding *bond, struct bond_opt_value *newval)
 
 	dev = __dev_get_by_name(dev_net(bond->dev), ifname);
 	if (!dev) {
-		pr_info("%s: Interface %s does not exist!\n",
+		pr_info("%s: interface %s does not exist!\n",
 			bond->dev->name, ifname);
 		ret = -ENODEV;
 		goto out;
@@ -1262,12 +1256,12 @@ int bond_option_slaves_set(struct bonding *bond, struct bond_opt_value *newval)
 
 	switch (command[0]) {
 	case '+':
-		pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name);
+		pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name);
 		ret = bond_enslave(bond->dev, dev);
 		break;
 
 	case '-':
-		pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name);
+		pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name);
 		ret = bond_release(bond->dev, dev);
 		break;
 
@@ -1279,7 +1273,7 @@ out:
 	return ret;
 
 err_no_cmd:
-	pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
+	pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n",
 	       bond->dev->name);
 	ret = -EPERM;
 	goto out;
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 3ac20e78eafc..588cf39d832c 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -69,9 +69,7 @@ static void bond_info_show_master(struct seq_file *seq)
 	struct slave *curr;
 	int i;
 
-	read_lock(&bond->curr_slave_lock);
-	curr = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
+	curr = rcu_dereference(bond->curr_active_slave);
 
 	seq_printf(seq, "Bonding Mode: %s",
 		   bond_mode_name(bond->params.mode));
@@ -254,8 +252,8 @@ void bond_create_proc_entry(struct bonding *bond)
 						    S_IRUGO, bn->proc_dir,
 						    &bond_info_fops, bond);
 		if (bond->proc_entry == NULL)
-			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
-				   DRV_NAME, bond_dev->name);
+			pr_warn("Warning: Cannot create /proc/net/%s/%s\n",
+				DRV_NAME, bond_dev->name);
 		else
 			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
 	}
@@ -281,8 +279,8 @@ void __net_init bond_create_proc_dir(struct bond_net *bn)
 	if (!bn->proc_dir) {
 		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
 		if (!bn->proc_dir)
-			pr_warning("Warning: cannot create /proc/net/%s\n",
-				   DRV_NAME);
+			pr_warn("Warning: Cannot create /proc/net/%s\n",
+				DRV_NAME);
 	}
 }
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 643fcc110299..225ee696db05 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -117,9 +117,9 @@ static ssize_t bonding_store_bonds(struct class *cls,
 		rv = bond_create(bn->net, ifname);
 		if (rv) {
 			if (rv == -EEXIST)
-				pr_info("%s already exists.\n", ifname);
+				pr_info("%s already exists\n", ifname);
 			else
-				pr_info("%s creation failed.\n", ifname);
+				pr_info("%s creation failed\n", ifname);
 			res = rv;
 		}
 	} else if (command[0] == '-') {
@@ -144,7 +144,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
 	return res;
 
 err_no_cmd:
-	pr_err("no command found in bonding_masters. Use +ifname or -ifname.\n");
+	pr_err("no command found in bonding_masters - use +ifname or -ifname\n");
 	return -EPERM;
 }
 
@@ -1135,7 +1135,7 @@ int bond_create_sysfs(struct bond_net *bn)
 		/* Is someone being kinky and naming a device bonding_master? */
 		if (__dev_get_by_name(bn->net,
 				      class_attr_bonding_masters.attr.name))
-			pr_err("network device named %s already exists in sysfs",
+			pr_err("network device named %s already exists in sysfs\n",
 			       class_attr_bonding_masters.attr.name);
 		ret = 0;
 	}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 86ccfb9f71cc..b7127a1ba2c9 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -188,14 +188,16 @@ struct slave {
 	struct net_device *dev; /* first - useful for panic debug */
 	struct bonding *bond; /* our master */
 	int    delay;
-	unsigned long jiffies;
-	unsigned long last_arp_rx;
+	/* all three in jiffies */
+	unsigned long last_link_up;
+	unsigned long last_rx;
 	unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
 	s8     link;    /* one of BOND_LINK_XXXX */
 	s8     new_link;
 	u8     backup:1,   /* indicates backup slave. Value corresponds with
 			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
-	       inactive:1; /* indicates inactive slave */
+	       inactive:1, /* indicates inactive slave */
+	       should_notify:1; /* indicateds whether the state changed */
 	u8     duplex;
 	u32    original_mtu;
 	u32    link_failure_count;
@@ -303,6 +305,24 @@ static inline void bond_set_backup_slave(struct slave *slave)
 	}
 }
 
+static inline void bond_set_slave_state(struct slave *slave,
+					int slave_state, bool notify)
+{
+	if (slave->backup == slave_state)
+		return;
+
+	slave->backup = slave_state;
+	if (notify) {
+		rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_KERNEL);
+		slave->should_notify = 0;
+	} else {
+		if (slave->should_notify)
+			slave->should_notify = 0;
+		else
+			slave->should_notify = 1;
+	}
+}
+
 static inline void bond_slave_state_change(struct bonding *bond)
 {
 	struct list_head *iter;
@@ -316,6 +336,19 @@ static inline void bond_slave_state_change(struct bonding *bond)
 	}
 }
 
+static inline void bond_slave_state_notify(struct bonding *bond)
+{
+	struct list_head *iter;
+	struct slave *tmp;
+
+	bond_for_each_slave(bond, tmp, iter) {
+		if (tmp->should_notify) {
+			rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_KERNEL);
+			tmp->should_notify = 0;
+		}
+	}
+}
+
 static inline int bond_slave_state(struct slave *slave)
 {
 	return slave->backup;
@@ -342,6 +375,14 @@ static inline bool bond_is_active_slave(struct slave *slave)
 #define BOND_ARP_VALIDATE_BACKUP	(1 << BOND_STATE_BACKUP)
 #define BOND_ARP_VALIDATE_ALL		(BOND_ARP_VALIDATE_ACTIVE | \
 					 BOND_ARP_VALIDATE_BACKUP)
+#define BOND_ARP_FILTER			(BOND_ARP_VALIDATE_ALL + 1)
+#define BOND_ARP_FILTER_ACTIVE		(BOND_ARP_VALIDATE_ACTIVE | \
+					 BOND_ARP_FILTER)
+#define BOND_ARP_FILTER_BACKUP		(BOND_ARP_VALIDATE_BACKUP | \
+					 BOND_ARP_FILTER)
+
+#define BOND_SLAVE_NOTIFY_NOW		true
+#define BOND_SLAVE_NOTIFY_LATER		false
 
 static inline int slave_do_arp_validate(struct bonding *bond,
 					struct slave *slave)
@@ -349,6 +390,12 @@ static inline int slave_do_arp_validate(struct bonding *bond,
 	return bond->params.arp_validate & (1 << bond_slave_state(slave));
 }
 
+static inline int slave_do_arp_validate_only(struct bonding *bond,
+					     struct slave *slave)
+{
+	return bond->params.arp_validate & BOND_ARP_FILTER;
+}
+
 /* Get the oldest arp which we've received on this slave for bond's
  * arp_targets.
  */
@@ -368,14 +415,10 @@ static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond,
 static inline unsigned long slave_last_rx(struct bonding *bond,
 					struct slave *slave)
 {
-	if (slave_do_arp_validate(bond, slave)) {
-		if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL)
-			return slave_oldest_target_arp_rx(bond, slave);
-		else
-			return slave->last_arp_rx;
-	}
+	if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL)
+		return slave_oldest_target_arp_rx(bond, slave);
 
-	return slave->dev->last_rx;
+	return slave->last_rx;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -394,17 +437,19 @@ static inline void bond_netpoll_send_skb(const struct slave *slave,
 }
 #endif
 
-static inline void bond_set_slave_inactive_flags(struct slave *slave)
+static inline void bond_set_slave_inactive_flags(struct slave *slave,
+						 bool notify)
 {
 	if (!bond_is_lb(slave->bond))
-		bond_set_backup_slave(slave);
+		bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
 	if (!slave->bond->params.all_slaves_active)
 		slave->inactive = 1;
 }
 
-static inline void bond_set_slave_active_flags(struct slave *slave)
+static inline void bond_set_slave_active_flags(struct slave *slave,
+					       bool notify)
 {
-	bond_set_active_slave(slave);
+	bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);
 	slave->inactive = 0;
 }
 
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 88a6a5810ec6..fc73865bb83a 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -204,7 +204,6 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data,
 
 	skb->protocol = htons(ETH_P_CAIF);
 	skb_reset_mac_header(skb);
-	skb->dev = ser->dev;
 	debugfs_rx(ser, data, count);
 	/* Push received packet up the stack. */
 	ret = netif_rx_ni(skb);
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 155db68e13ba..ff54c0eb2052 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -554,7 +554,6 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len)
 
 		skb->protocol = htons(ETH_P_CAIF);
 		skb_reset_mac_header(skb);
-		skb->dev = cfspi->ndev;
 
 		/*
 		 * Push received packet up the stack.
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 6efe27458116..1d00b95f8983 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -420,7 +420,11 @@ static void at91_chip_start(struct net_device *dev)
 	at91_transceiver_switch(priv, 1);
 
 	/* enable chip */
-	at91_write(priv, AT91_MR, AT91_MR_CANEN);
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		reg_mr = AT91_MR_CANEN | AT91_MR_ABM;
+	else
+		reg_mr = AT91_MR_CANEN;
+	at91_write(priv, AT91_MR, reg_mr);
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -1341,7 +1345,8 @@ static int at91_can_probe(struct platform_device *pdev)
 	priv->can.bittiming_const = &at91_bittiming_const;
 	priv->can.do_set_mode = at91_set_mode;
 	priv->can.do_get_berr_counter = at91_get_berr_counter;
-	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+		CAN_CTRLMODE_LISTENONLY;
 	priv->dev = dev;
 	priv->reg_base = addr;
 	priv->devtype_data = *devtype_data;
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index fc59bc6f040b..c0563f183721 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -512,6 +512,30 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
 }
 EXPORT_SYMBOL_GPL(alloc_can_skb);
 
+struct sk_buff *alloc_canfd_skb(struct net_device *dev,
+				struct canfd_frame **cfd)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+			       sizeof(struct canfd_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CANFD);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = dev->ifindex;
+
+	*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame));
+	memset(*cfd, 0, sizeof(struct canfd_frame));
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_canfd_skb);
+
 struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
 {
 	struct sk_buff *skb;
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 320bef2dba42..61376abdab39 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -144,6 +144,8 @@
 
 #define FLEXCAN_MB_CODE_MASK		(0xf0ffffff)
 
+#define FLEXCAN_TIMEOUT_US             (50)
+
 /*
  * FLEXCAN hardware feature flags
  *
@@ -262,6 +264,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
 }
 #endif
 
+static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
+{
+	if (!priv->reg_xceiver)
+		return 0;
+
+	return regulator_enable(priv->reg_xceiver);
+}
+
+static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
+{
+	if (!priv->reg_xceiver)
+		return 0;
+
+	return regulator_disable(priv->reg_xceiver);
+}
+
 static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
 					      u32 reg_esr)
 {
@@ -269,26 +287,95 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
 		(reg_esr & FLEXCAN_ESR_ERR_BUS);
 }
 
-static inline void flexcan_chip_enable(struct flexcan_priv *priv)
+static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = flexcan_read(&regs->mcr);
 	reg &= ~FLEXCAN_MCR_MDIS;
 	flexcan_write(reg, &regs->mcr);
 
-	udelay(10);
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+		return -ETIMEDOUT;
+
+	return 0;
 }
 
-static inline void flexcan_chip_disable(struct flexcan_priv *priv)
+static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS;
 	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		usleep_range(10, 20);
+
+	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int flexcan_chip_freeze(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
+	u32 reg;
+
+	reg = flexcan_read(&regs->mcr);
+	reg |= FLEXCAN_MCR_HALT;
+	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		usleep_range(100, 200);
+
+	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+	u32 reg;
+
+	reg = flexcan_read(&regs->mcr);
+	reg &= ~FLEXCAN_MCR_HALT;
+	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int flexcan_chip_softreset(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
+		return -ETIMEDOUT;
+
+	return 0;
 }
 
 static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -709,19 +796,14 @@ static int flexcan_chip_start(struct net_device *dev)
 	u32 reg_mcr, reg_ctrl;
 
 	/* enable module */
-	flexcan_chip_enable(priv);
+	err = flexcan_chip_enable(priv);
+	if (err)
+		return err;
 
 	/* soft reset */
-	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
-	udelay(10);
-
-	reg_mcr = flexcan_read(&regs->mcr);
-	if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
-		netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n",
-			   reg_mcr);
-		err = -ENODEV;
-		goto out;
-	}
+	err = flexcan_chip_softreset(priv);
+	if (err)
+		goto out_chip_disable;
 
 	flexcan_set_bittiming(dev);
 
@@ -788,16 +870,14 @@ static int flexcan_chip_start(struct net_device *dev)
 	if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
 		flexcan_write(0x0, &regs->rxfgmask);
 
-	if (priv->reg_xceiver)	{
-		err = regulator_enable(priv->reg_xceiver);
-		if (err)
-			goto out;
-	}
+	err = flexcan_transceiver_enable(priv);
+	if (err)
+		goto out_chip_disable;
 
 	/* synchronize with the can bus */
-	reg_mcr = flexcan_read(&regs->mcr);
-	reg_mcr &= ~FLEXCAN_MCR_HALT;
-	flexcan_write(reg_mcr, &regs->mcr);
+	err = flexcan_chip_unfreeze(priv);
+	if (err)
+		goto out_transceiver_disable;
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -810,7 +890,9 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	return 0;
 
- out:
+ out_transceiver_disable:
+	flexcan_transceiver_disable(priv);
+ out_chip_disable:
 	flexcan_chip_disable(priv);
 	return err;
 }
@@ -825,18 +907,17 @@ static void flexcan_chip_stop(struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->base;
-	u32 reg;
+
+	/* freeze + disable module */
+	flexcan_chip_freeze(priv);
+	flexcan_chip_disable(priv);
 
 	/* Disable all interrupts */
 	flexcan_write(0, &regs->imask1);
+	flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+		      &regs->ctrl);
 
-	/* Disable + halt module */
-	reg = flexcan_read(&regs->mcr);
-	reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
-	flexcan_write(reg, &regs->mcr);
-
-	if (priv->reg_xceiver)
-		regulator_disable(priv->reg_xceiver);
+	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
 
 	return;
@@ -866,7 +947,7 @@ static int flexcan_open(struct net_device *dev)
 	/* start chip and queuing */
 	err = flexcan_chip_start(dev);
 	if (err)
-		goto out_close;
+		goto out_free_irq;
 
 	can_led_event(dev, CAN_LED_EVENT_OPEN);
 
@@ -875,6 +956,8 @@ static int flexcan_open(struct net_device *dev)
 
 	return 0;
 
+ out_free_irq:
+	free_irq(dev->irq, dev);
  out_close:
 	close_candev(dev);
  out_disable_per:
@@ -945,12 +1028,16 @@ static int register_flexcandev(struct net_device *dev)
 		goto out_disable_ipg;
 
 	/* select "bus clock", chip must be disabled */
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_disable(priv);
+	if (err)
+		goto out_disable_per;
 	reg = flexcan_read(&regs->ctrl);
 	reg |= FLEXCAN_CTRL_CLK_SRC;
 	flexcan_write(reg, &regs->ctrl);
 
-	flexcan_chip_enable(priv);
+	err = flexcan_chip_enable(priv);
+	if (err)
+		goto out_chip_disable;
 
 	/* set freeze, halt and activate FIFO, restrict register access */
 	reg = flexcan_read(&regs->mcr);
@@ -967,14 +1054,15 @@ static int register_flexcandev(struct net_device *dev)
 	if (!(reg & FLEXCAN_MCR_FEN)) {
 		netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
 		err = -ENODEV;
-		goto out_disable_per;
+		goto out_chip_disable;
 	}
 
 	err = register_candev(dev);
 
- out_disable_per:
 	/* disable core and turn off clocks */
+ out_chip_disable:
 	flexcan_chip_disable(priv);
+ out_disable_per:
 	clk_disable_unprepare(priv->clk_per);
  out_disable_ipg:
 	clk_disable_unprepare(priv->clk_ipg);
@@ -1104,9 +1192,10 @@ static int flexcan_probe(struct platform_device *pdev)
 static int flexcan_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct flexcan_priv *priv = netdev_priv(dev);
 
 	unregister_flexcandev(dev);
-
+	netif_napi_del(&priv->napi);
 	free_candev(dev);
 
 	return 0;
@@ -1117,8 +1206,11 @@ static int flexcan_suspend(struct device *device)
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
+	int err;
 
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_disable(priv);
+	if (err)
+		return err;
 
 	if (netif_running(dev)) {
 		netif_stop_queue(dev);
@@ -1139,9 +1231,7 @@ static int flexcan_resume(struct device *device)
 		netif_device_attach(dev);
 		netif_start_queue(dev);
 	}
-	flexcan_chip_enable(priv);
-
-	return 0;
+	return flexcan_chip_enable(priv);
 }
 #endif /* CONFIG_PM_SLEEP */
 
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index ff2ba86cd4a4..1e65cb6c2591 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -17,16 +17,9 @@ config CAN_SJA1000_PLATFORM
 	  the "platform bus" (Linux abstraction for directly to the
 	  processor attached devices).  Which can be found on various
 	  boards from Phytec (http://www.phytec.de) like the PCM027,
-	  PCM038.
-
-config CAN_SJA1000_OF_PLATFORM
-	tristate "Generic OF Platform Bus based SJA1000 driver"
-	depends on OF
-	---help---
-	  This driver adds support for the SJA1000 chips connected to
-	  the OpenFirmware "platform bus" found on embedded systems with
-	  OpenFirmware bindings, e.g. if you have a PowerPC based system
-	  you may want to enable this option.
+	  PCM038. It also provides the OpenFirmware "platform bus" found
+	  on embedded systems with OpenFirmware bindings, e.g. if you
+	  have a PowerPC based system you may want to enable this option.
 
 config CAN_EMS_PCMCIA
 	tristate "EMS CPC-CARD Card"
@@ -46,7 +39,7 @@ config CAN_EMS_PCI
 config CAN_PEAK_PCMCIA
 	tristate "PEAK PCAN-PC Card"
 	depends on PCMCIA
-	depends on HAS_IOPORT
+	depends on HAS_IOPORT_MAP
 	---help---
 	  This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
 	  from PEAK-System (http://www.peak-system.com). To compile this
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile
index b3d05cbfec36..531d5fcc97e5 100644
--- a/drivers/net/can/sja1000/Makefile
+++ b/drivers/net/can/sja1000/Makefile
@@ -5,7 +5,6 @@
 obj-$(CONFIG_CAN_SJA1000) += sja1000.o
 obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
 obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
-obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
 obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
 obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
 obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index f17c3018b7c7..55cce4737518 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -106,8 +106,7 @@ static int sja1000_probe_chip(struct net_device *dev)
 	struct sja1000_priv *priv = netdev_priv(dev);
 
 	if (priv->reg_base && sja1000_is_absent(priv)) {
-		printk(KERN_INFO "%s: probing @0x%lX failed\n",
-		       DRV_NAME, dev->base_addr);
+		netdev_err(dev, "probing failed\n");
 		return 0;
 	}
 	return -1;
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
deleted file mode 100644
index 2f6e24534231..000000000000
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus
- *
- * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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, see <http://www.gnu.org/licenses/>.
- */
-
-/* This is a generic driver for SJA1000 chips on the OpenFirmware platform
- * bus found on embedded PowerPC systems. You need a SJA1000 CAN node
- * definition in your flattened device tree source (DTS) file similar to:
- *
- *   can@3,100 {
- *           compatible = "nxp,sja1000";
- *           reg = <3 0x100 0x80>;
- *           interrupts = <2 0>;
- *           interrupt-parent = <&mpic>;
- *           nxp,external-clock-frequency = <16000000>;
- *   };
- *
- * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further
- * information.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/can/dev.h>
-
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-#include "sja1000.h"
-
-#define DRV_NAME "sja1000_of_platform"
-
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
-MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus");
-MODULE_LICENSE("GPL v2");
-
-#define SJA1000_OFP_CAN_CLOCK  (16000000 / 2)
-
-#define SJA1000_OFP_OCR        OCR_TX0_PULLDOWN
-#define SJA1000_OFP_CDR        (CDR_CBP | CDR_CLK_OFF)
-
-static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
-{
-	return ioread8(priv->reg_base + reg);
-}
-
-static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
-				  int reg, u8 val)
-{
-	iowrite8(val, priv->reg_base + reg);
-}
-
-static int sja1000_ofp_remove(struct platform_device *ofdev)
-{
-	struct net_device *dev = platform_get_drvdata(ofdev);
-	struct sja1000_priv *priv = netdev_priv(dev);
-	struct device_node *np = ofdev->dev.of_node;
-	struct resource res;
-
-	unregister_sja1000dev(dev);
-	free_sja1000dev(dev);
-	iounmap(priv->reg_base);
-	irq_dispose_mapping(dev->irq);
-
-	of_address_to_resource(np, 0, &res);
-	release_mem_region(res.start, resource_size(&res));
-
-	return 0;
-}
-
-static int sja1000_ofp_probe(struct platform_device *ofdev)
-{
-	struct device_node *np = ofdev->dev.of_node;
-	struct net_device *dev;
-	struct sja1000_priv *priv;
-	struct resource res;
-	u32 prop;
-	int err, irq, res_size;
-	void __iomem *base;
-
-	err = of_address_to_resource(np, 0, &res);
-	if (err) {
-		dev_err(&ofdev->dev, "invalid address\n");
-		return err;
-	}
-
-	res_size = resource_size(&res);
-
-	if (!request_mem_region(res.start, res_size, DRV_NAME)) {
-		dev_err(&ofdev->dev, "couldn't request %pR\n", &res);
-		return -EBUSY;
-	}
-
-	base = ioremap_nocache(res.start, res_size);
-	if (!base) {
-		dev_err(&ofdev->dev, "couldn't ioremap %pR\n", &res);
-		err = -ENOMEM;
-		goto exit_release_mem;
-	}
-
-	irq = irq_of_parse_and_map(np, 0);
-	if (irq == 0) {
-		dev_err(&ofdev->dev, "no irq found\n");
-		err = -ENODEV;
-		goto exit_unmap_mem;
-	}
-
-	dev = alloc_sja1000dev(0);
-	if (!dev) {
-		err = -ENOMEM;
-		goto exit_dispose_irq;
-	}
-
-	priv = netdev_priv(dev);
-
-	priv->read_reg = sja1000_ofp_read_reg;
-	priv->write_reg = sja1000_ofp_write_reg;
-
-	err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
-	if (!err)
-		priv->can.clock.freq = prop / 2;
-	else
-		priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
-
-	err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
-	if (!err)
-		priv->ocr |= prop & OCR_MODE_MASK;
-	else
-		priv->ocr |= OCR_MODE_NORMAL; /* default */
-
-	err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
-	if (!err)
-		priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
-	else
-		priv->ocr |= OCR_TX0_PULLDOWN; /* default */
-
-	err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
-	if (!err && prop) {
-		u32 divider = priv->can.clock.freq * 2 / prop;
-
-		if (divider > 1)
-			priv->cdr |= divider / 2 - 1;
-		else
-			priv->cdr |= CDR_CLKOUT_MASK;
-	} else {
-		priv->cdr |= CDR_CLK_OFF; /* default */
-	}
-
-	if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
-		priv->cdr |= CDR_CBP; /* default */
-
-	priv->irq_flags = IRQF_SHARED;
-	priv->reg_base = base;
-
-	dev->irq = irq;
-
-	dev_info(&ofdev->dev,
-		 "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n",
-		 priv->reg_base, dev->irq, priv->can.clock.freq,
-		 priv->ocr, priv->cdr);
-
-	platform_set_drvdata(ofdev, dev);
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
-	err = register_sja1000dev(dev);
-	if (err) {
-		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
-			DRV_NAME, err);
-		goto exit_free_sja1000;
-	}
-
-	return 0;
-
-exit_free_sja1000:
-	free_sja1000dev(dev);
-exit_dispose_irq:
-	irq_dispose_mapping(irq);
-exit_unmap_mem:
-	iounmap(base);
-exit_release_mem:
-	release_mem_region(res.start, res_size);
-
-	return err;
-}
-
-static struct of_device_id sja1000_ofp_table[] = {
-	{.compatible = "nxp,sja1000"},
-	{},
-};
-MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
-
-static struct platform_driver sja1000_ofp_driver = {
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = DRV_NAME,
-		.of_match_table = sja1000_ofp_table,
-	},
-	.probe = sja1000_ofp_probe,
-	.remove = sja1000_ofp_remove,
-};
-
-module_platform_driver(sja1000_ofp_driver);
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 943df645b459..95a844a7ee7b 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -26,12 +26,16 @@
 #include <linux/can/dev.h>
 #include <linux/can/platform/sja1000.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include "sja1000.h"
 
 #define DRV_NAME "sja1000_platform"
+#define SP_CAN_CLOCK  (16000000 / 2)
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
 MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_LICENSE("GPL v2");
@@ -66,59 +70,16 @@ static void sp_write_reg32(const struct sja1000_priv *priv, int reg, u8 val)
 	iowrite8(val, priv->reg_base + reg * 4);
 }
 
-static int sp_probe(struct platform_device *pdev)
+static void sp_populate(struct sja1000_priv *priv,
+			struct sja1000_platform_data *pdata,
+			unsigned long resource_mem_flags)
 {
-	int err;
-	void __iomem *addr;
-	struct net_device *dev;
-	struct sja1000_priv *priv;
-	struct resource *res_mem, *res_irq;
-	struct sja1000_platform_data *pdata;
-
-	pdata = dev_get_platdata(&pdev->dev);
-	if (!pdata) {
-		dev_err(&pdev->dev, "No platform data provided!\n");
-		err = -ENODEV;
-		goto exit;
-	}
-
-	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res_mem || !res_irq) {
-		err = -ENODEV;
-		goto exit;
-	}
-
-	if (!request_mem_region(res_mem->start, resource_size(res_mem),
-				DRV_NAME)) {
-		err = -EBUSY;
-		goto exit;
-	}
-
-	addr = ioremap_nocache(res_mem->start, resource_size(res_mem));
-	if (!addr) {
-		err = -ENOMEM;
-		goto exit_release;
-	}
-
-	dev = alloc_sja1000dev(0);
-	if (!dev) {
-		err = -ENOMEM;
-		goto exit_iounmap;
-	}
-	priv = netdev_priv(dev);
-
-	dev->irq = res_irq->start;
-	priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
-	if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
-		priv->irq_flags |= IRQF_SHARED;
-	priv->reg_base = addr;
 	/* The CAN clock frequency is half the oscillator clock frequency */
 	priv->can.clock.freq = pdata->osc_freq / 2;
 	priv->ocr = pdata->ocr;
 	priv->cdr = pdata->cdr;
 
-	switch (res_mem->flags & IORESOURCE_MEM_TYPE_MASK) {
+	switch (resource_mem_flags & IORESOURCE_MEM_TYPE_MASK) {
 	case IORESOURCE_MEM_32BIT:
 		priv->read_reg = sp_read_reg32;
 		priv->write_reg = sp_write_reg32;
@@ -133,6 +94,124 @@ static int sp_probe(struct platform_device *pdev)
 		priv->write_reg = sp_write_reg8;
 		break;
 	}
+}
+
+static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of)
+{
+	int err;
+	u32 prop;
+
+	err = of_property_read_u32(of, "reg-io-width", &prop);
+	if (err)
+		prop = 1; /* 8 bit is default */
+
+	switch (prop) {
+	case 4:
+		priv->read_reg = sp_read_reg32;
+		priv->write_reg = sp_write_reg32;
+		break;
+	case 2:
+		priv->read_reg = sp_read_reg16;
+		priv->write_reg = sp_write_reg16;
+		break;
+	case 1:	/* fallthrough */
+	default:
+		priv->read_reg = sp_read_reg8;
+		priv->write_reg = sp_write_reg8;
+	}
+
+	err = of_property_read_u32(of, "nxp,external-clock-frequency", &prop);
+	if (!err)
+		priv->can.clock.freq = prop / 2;
+	else
+		priv->can.clock.freq = SP_CAN_CLOCK; /* default */
+
+	err = of_property_read_u32(of, "nxp,tx-output-mode", &prop);
+	if (!err)
+		priv->ocr |= prop & OCR_MODE_MASK;
+	else
+		priv->ocr |= OCR_MODE_NORMAL; /* default */
+
+	err = of_property_read_u32(of, "nxp,tx-output-config", &prop);
+	if (!err)
+		priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+	else
+		priv->ocr |= OCR_TX0_PULLDOWN; /* default */
+
+	err = of_property_read_u32(of, "nxp,clock-out-frequency", &prop);
+	if (!err && prop) {
+		u32 divider = priv->can.clock.freq * 2 / prop;
+
+		if (divider > 1)
+			priv->cdr |= divider / 2 - 1;
+		else
+			priv->cdr |= CDR_CLKOUT_MASK;
+	} else {
+		priv->cdr |= CDR_CLK_OFF; /* default */
+	}
+
+	if (!of_property_read_bool(of, "nxp,no-comparator-bypass"))
+		priv->cdr |= CDR_CBP; /* default */
+}
+
+static int sp_probe(struct platform_device *pdev)
+{
+	int err, irq = 0;
+	void __iomem *addr;
+	struct net_device *dev;
+	struct sja1000_priv *priv;
+	struct resource *res_mem, *res_irq = NULL;
+	struct sja1000_platform_data *pdata;
+	struct device_node *of = pdev->dev.of_node;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata && !of) {
+		dev_err(&pdev->dev, "No platform data provided!\n");
+		return -ENODEV;
+	}
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_mem)
+		return -ENODEV;
+
+	if (!devm_request_mem_region(&pdev->dev, res_mem->start,
+				     resource_size(res_mem), DRV_NAME))
+		return -EBUSY;
+
+	addr = devm_ioremap_nocache(&pdev->dev, res_mem->start,
+				    resource_size(res_mem));
+	if (!addr)
+		return -ENOMEM;
+
+	if (of)
+		irq = irq_of_parse_and_map(of, 0);
+	else
+		res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	if (!irq && !res_irq)
+		return -ENODEV;
+
+	dev = alloc_sja1000dev(0);
+	if (!dev)
+		return -ENOMEM;
+	priv = netdev_priv(dev);
+
+	if (res_irq) {
+		irq = res_irq->start;
+		priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+		if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
+			priv->irq_flags |= IRQF_SHARED;
+	} else {
+		priv->irq_flags = IRQF_SHARED;
+	}
+
+	dev->irq = irq;
+	priv->reg_base = addr;
+
+	if (of)
+		sp_populate_of(priv, of);
+	else
+		sp_populate(priv, pdata, res_mem->flags);
 
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -150,39 +229,32 @@ static int sp_probe(struct platform_device *pdev)
 
  exit_free:
 	free_sja1000dev(dev);
- exit_iounmap:
-	iounmap(addr);
- exit_release:
-	release_mem_region(res_mem->start, resource_size(res_mem));
- exit:
 	return err;
 }
 
 static int sp_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
-	struct sja1000_priv *priv = netdev_priv(dev);
-	struct resource *res;
 
 	unregister_sja1000dev(dev);
-
-	if (priv->reg_base)
-		iounmap(priv->reg_base);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	free_sja1000dev(dev);
 
 	return 0;
 }
 
+static struct of_device_id sp_of_table[] = {
+	{.compatible = "nxp,sja1000"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, sp_of_table);
+
 static struct platform_driver sp_driver = {
 	.probe = sp_probe,
 	.remove = sp_remove,
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
+		.of_match_table = sp_of_table,
 	},
 };
 
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index bd8f84b0b894..1656317c96f8 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -88,16 +88,10 @@ static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static int dummy_dev_init(struct net_device *dev)
 {
-	int i;
-	dev->dstats = alloc_percpu(struct pcpu_dstats);
+	dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
 	if (!dev->dstats)
 		return -ENOMEM;
 
-	for_each_possible_cpu(i) {
-		struct pcpu_dstats *dstats;
-		dstats = per_cpu_ptr(dev->dstats, i);
-		u64_stats_init(&dstats->syncp);
-	}
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index 5992860a39c9..063557e037f2 100644
--- a/drivers/net/ethernet/3com/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -1,23 +1,24 @@
-/*======================================================================
-
-    A PCMCIA ethernet driver for the 3com 3c589 card.
-
-    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
-
-    3c589_cs.c 1.162 2001/10/13 00:08:50
-
-    The network driver code is based on Donald Becker's 3c589 code:
-
-    Written 1994 by Donald Becker.
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-    Donald Becker may be reached at becker@scyld.com
-
-    Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-======================================================================*/
+/* ======================================================================
+ *
+ * A PCMCIA ethernet driver for the 3com 3c589 card.
+ *
+ * Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
+ *
+ * 3c589_cs.c 1.162 2001/10/13 00:08:50
+ *
+ * The network driver code is based on Donald Becker's 3c589 code:
+ *
+ * Written 1994 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.  This software may be used and
+ * distributed according to the terms of the GNU General Public License,
+ * incorporated herein by reference.
+ * Donald Becker may be reached at becker@scyld.com
+ *
+ * Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ * ======================================================================
+ */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
@@ -41,18 +42,20 @@
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
 
 /* To minimize the size of the driver source I only define operating
-   constants if they are used several times.  You'll need the manual
-   if you want to understand driver details. */
+ * constants if they are used several times. You'll need the manual
+ * if you want to understand driver details.
+ */
+
 /* Offsets from base I/O address. */
 #define EL3_DATA	0x00
 #define EL3_TIMER	0x0a
@@ -65,7 +68,9 @@
 #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
 
 /* The top five bits written to EL3_CMD are a command, the lower
-   11 bits are the parameter, if applicable. */
+ * 11 bits are the parameter, if applicable.
+ */
+
 enum c509cmd {
 	TotalReset	= 0<<11,
 	SelectWindow	= 1<<11,
@@ -190,138 +195,142 @@ static const struct net_device_ops el3_netdev_ops = {
 
 static int tc589_probe(struct pcmcia_device *link)
 {
-    struct el3_private *lp;
-    struct net_device *dev;
+	struct el3_private *lp;
+	struct net_device *dev;
 
-    dev_dbg(&link->dev, "3c589_attach()\n");
+	dev_dbg(&link->dev, "3c589_attach()\n");
 
-    /* Create new ethernet device */
-    dev = alloc_etherdev(sizeof(struct el3_private));
-    if (!dev)
-	 return -ENOMEM;
-    lp = netdev_priv(dev);
-    link->priv = dev;
-    lp->p_dev = link;
+	/* Create new ethernet device */
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev)
+		return -ENOMEM;
+	lp = netdev_priv(dev);
+	link->priv = dev;
+	lp->p_dev = link;
 
-    spin_lock_init(&lp->lock);
-    link->resource[0]->end = 16;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	spin_lock_init(&lp->lock);
+	link->resource[0]->end = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
-    link->config_flags |= CONF_ENABLE_IRQ;
-    link->config_index = 1;
+	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_index = 1;
 
-    dev->netdev_ops = &el3_netdev_ops;
-    dev->watchdog_timeo = TX_TIMEOUT;
+	dev->netdev_ops = &el3_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
 
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    return tc589_config(link);
+	return tc589_config(link);
 }
 
 static void tc589_detach(struct pcmcia_device *link)
 {
-    struct net_device *dev = link->priv;
+	struct net_device *dev = link->priv;
 
-    dev_dbg(&link->dev, "3c589_detach\n");
+	dev_dbg(&link->dev, "3c589_detach\n");
 
-    unregister_netdev(dev);
+	unregister_netdev(dev);
 
-    tc589_release(link);
+	tc589_release(link);
 
-    free_netdev(dev);
+	free_netdev(dev);
 } /* tc589_detach */
 
 static int tc589_config(struct pcmcia_device *link)
 {
-    struct net_device *dev = link->priv;
-    __be16 *phys_addr;
-    int ret, i, j, multi = 0, fifo;
-    unsigned int ioaddr;
-    static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
-    u8 *buf;
-    size_t len;
-
-    dev_dbg(&link->dev, "3c589_config\n");
-
-    phys_addr = (__be16 *)dev->dev_addr;
-    /* Is this a 3c562? */
-    if (link->manf_id != MANFID_3COM)
-	    dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
-    multi = (link->card_id == PRODID_3COM_3C562);
-
-    link->io_lines = 16;
-
-    /* For the 3c562, the base address must be xx00-xx7f */
-    for (i = j = 0; j < 0x400; j += 0x10) {
-	if (multi && (j & 0x80)) continue;
-	link->resource[0]->start = j ^ 0x300;
-	i = pcmcia_request_io(link);
-	if (i == 0)
-		break;
-    }
-    if (i != 0)
-	goto failed;
-
-    ret = pcmcia_request_irq(link, el3_interrupt);
-    if (ret)
-	    goto failed;
-
-    ret = pcmcia_enable_device(link);
-    if (ret)
-	    goto failed;
-
-    dev->irq = link->irq;
-    dev->base_addr = link->resource[0]->start;
-    ioaddr = dev->base_addr;
-    EL3WINDOW(0);
-
-    /* The 3c589 has an extra EEPROM for configuration info, including
-       the hardware address.  The 3c562 puts the address in the CIS. */
-    len = pcmcia_get_tuple(link, 0x88, &buf);
-    if (buf && len >= 6) {
-	    for (i = 0; i < 3; i++)
-		    phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
-	    kfree(buf);
-    } else {
-	kfree(buf); /* 0 < len < 6 */
-	for (i = 0; i < 3; i++)
-	    phys_addr[i] = htons(read_eeprom(ioaddr, i));
-	if (phys_addr[0] == htons(0x6060)) {
-	    dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
-		    dev->base_addr, dev->base_addr+15);
-	    goto failed;
+	struct net_device *dev = link->priv;
+	__be16 *phys_addr;
+	int ret, i, j, multi = 0, fifo;
+	unsigned int ioaddr;
+	static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+	u8 *buf;
+	size_t len;
+
+	dev_dbg(&link->dev, "3c589_config\n");
+
+	phys_addr = (__be16 *)dev->dev_addr;
+	/* Is this a 3c562? */
+	if (link->manf_id != MANFID_3COM)
+		dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
+	multi = (link->card_id == PRODID_3COM_3C562);
+
+	link->io_lines = 16;
+
+	/* For the 3c562, the base address must be xx00-xx7f */
+	for (i = j = 0; j < 0x400; j += 0x10) {
+		if (multi && (j & 0x80))
+			continue;
+		link->resource[0]->start = j ^ 0x300;
+		i = pcmcia_request_io(link);
+		if (i == 0)
+			break;
 	}
-    }
-
-    /* The address and resource configuration register aren't loaded from
-       the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
-    outw(0x3f00, ioaddr + 8);
-    fifo = inl(ioaddr);
-
-    /* The if_port symbol can be set when the module is loaded */
-    if ((if_port >= 0) && (if_port <= 3))
-	dev->if_port = if_port;
-    else
-	dev_err(&link->dev, "invalid if_port requested\n");
-
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    if (register_netdev(dev) != 0) {
-	    dev_err(&link->dev, "register_netdev() failed\n");
-	goto failed;
-    }
-
-    netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n",
-		(multi ? "562" : "589"), dev->base_addr, dev->irq,
-		dev->dev_addr);
-    netdev_info(dev, "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
-		(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
-		if_names[dev->if_port]);
-    return 0;
+	if (i != 0)
+		goto failed;
+
+	ret = pcmcia_request_irq(link, el3_interrupt);
+	if (ret)
+		goto failed;
+
+	ret = pcmcia_enable_device(link);
+	if (ret)
+		goto failed;
+
+	dev->irq = link->irq;
+	dev->base_addr = link->resource[0]->start;
+	ioaddr = dev->base_addr;
+	EL3WINDOW(0);
+
+	/* The 3c589 has an extra EEPROM for configuration info, including
+	 * the hardware address.  The 3c562 puts the address in the CIS.
+	 */
+	len = pcmcia_get_tuple(link, 0x88, &buf);
+	if (buf && len >= 6) {
+		for (i = 0; i < 3; i++)
+			phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
+		kfree(buf);
+	} else {
+		kfree(buf); /* 0 < len < 6 */
+		for (i = 0; i < 3; i++)
+			phys_addr[i] = htons(read_eeprom(ioaddr, i));
+		if (phys_addr[0] == htons(0x6060)) {
+			dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
+					dev->base_addr, dev->base_addr+15);
+			goto failed;
+		}
+	}
+
+	/* The address and resource configuration register aren't loaded from
+	 * the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version.
+	 */
+
+	outw(0x3f00, ioaddr + 8);
+	fifo = inl(ioaddr);
+
+	/* The if_port symbol can be set when the module is loaded */
+	if ((if_port >= 0) && (if_port <= 3))
+		dev->if_port = if_port;
+	else
+		dev_err(&link->dev, "invalid if_port requested\n");
+
+	SET_NETDEV_DEV(dev, &link->dev);
+
+	if (register_netdev(dev) != 0) {
+		dev_err(&link->dev, "register_netdev() failed\n");
+		goto failed;
+	}
+
+	netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n",
+			(multi ? "562" : "589"), dev->base_addr, dev->irq,
+			dev->dev_addr);
+	netdev_info(dev, "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
+			(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
+			if_names[dev->if_port]);
+	return 0;
 
 failed:
-    tc589_release(link);
-    return -ENODEV;
+	tc589_release(link);
+	return -ENODEV;
 } /* tc589_config */
 
 static void tc589_release(struct pcmcia_device *link)
@@ -353,113 +362,120 @@ static int tc589_resume(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-/*
-  Use this for commands that may take time to finish
-*/
+/* Use this for commands that may take time to finish */
+
 static void tc589_wait_for_completion(struct net_device *dev, int cmd)
 {
-    int i = 100;
-    outw(cmd, dev->base_addr + EL3_CMD);
-    while (--i > 0)
-	if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
-    if (i == 0)
-	netdev_warn(dev, "command 0x%04x did not complete!\n", cmd);
+	int i = 100;
+	outw(cmd, dev->base_addr + EL3_CMD);
+	while (--i > 0)
+		if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000))
+			break;
+	if (i == 0)
+		netdev_warn(dev, "command 0x%04x did not complete!\n", cmd);
 }
 
-/*
-  Read a word from the EEPROM using the regular EEPROM access register.
-  Assume that we are in register window zero.
-*/
+/* Read a word from the EEPROM using the regular EEPROM access register.
+ * Assume that we are in register window zero.
+ */
+
 static u16 read_eeprom(unsigned int ioaddr, int index)
 {
-    int i;
-    outw(EEPROM_READ + index, ioaddr + 10);
-    /* Reading the eeprom takes 162 us */
-    for (i = 1620; i >= 0; i--)
-	if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
-	    break;
-    return inw(ioaddr + 12);
+	int i;
+	outw(EEPROM_READ + index, ioaddr + 10);
+	/* Reading the eeprom takes 162 us */
+	for (i = 1620; i >= 0; i--)
+		if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
+			break;
+	return inw(ioaddr + 12);
 }
 
-/*
-  Set transceiver type, perhaps to something other than what the user
-  specified in dev->if_port.
-*/
+/* Set transceiver type, perhaps to something other than what the user
+ * specified in dev->if_port.
+ */
+
 static void tc589_set_xcvr(struct net_device *dev, int if_port)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    unsigned int ioaddr = dev->base_addr;
-
-    EL3WINDOW(0);
-    switch (if_port) {
-    case 0: case 1: outw(0, ioaddr + 6); break;
-    case 2: outw(3<<14, ioaddr + 6); break;
-    case 3: outw(1<<14, ioaddr + 6); break;
-    }
-    /* On PCMCIA, this just turns on the LED */
-    outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);
-    /* 10baseT interface, enable link beat and jabber check. */
-    EL3WINDOW(4);
-    outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);
-    EL3WINDOW(1);
-    if (if_port == 2)
-	lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);
-    else
-	lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr = dev->base_addr;
+
+	EL3WINDOW(0);
+	switch (if_port) {
+	case 0:
+	case 1:
+		outw(0, ioaddr + 6);
+		break;
+	case 2:
+		outw(3<<14, ioaddr + 6);
+		break;
+	case 3:
+		outw(1<<14, ioaddr + 6);
+		break;
+	}
+	/* On PCMCIA, this just turns on the LED */
+	outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);
+	/* 10baseT interface, enable link beat and jabber check. */
+	EL3WINDOW(4);
+	outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);
+	EL3WINDOW(1);
+	if (if_port == 2)
+		lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);
+	else
+		lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);
 }
 
 static void dump_status(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    EL3WINDOW(1);
-    netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x  tx free %04x\n",
-		inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS),
-		inb(ioaddr+TX_STATUS), inw(ioaddr+TX_FREE));
-    EL3WINDOW(4);
-    netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
-		inw(ioaddr+0x04), inw(ioaddr+0x06), inw(ioaddr+0x08),
-		inw(ioaddr+0x0a));
-    EL3WINDOW(1);
+	unsigned int ioaddr = dev->base_addr;
+	EL3WINDOW(1);
+	netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x  tx free %04x\n",
+			inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS),
+			inb(ioaddr+TX_STATUS), inw(ioaddr+TX_FREE));
+	EL3WINDOW(4);
+	netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+			inw(ioaddr+0x04), inw(ioaddr+0x06), inw(ioaddr+0x08),
+			inw(ioaddr+0x0a));
+	EL3WINDOW(1);
 }
 
 /* Reset and restore all of the 3c589 registers. */
 static void tc589_reset(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    int i;
-
-    EL3WINDOW(0);
-    outw(0x0001, ioaddr + 4);			/* Activate board. */
-    outw(0x3f00, ioaddr + 8);			/* Set the IRQ line. */
-
-    /* Set the station address in window 2. */
-    EL3WINDOW(2);
-    for (i = 0; i < 6; i++)
-	outb(dev->dev_addr[i], ioaddr + i);
-
-    tc589_set_xcvr(dev, dev->if_port);
-
-    /* Switch to the stats window, and clear all stats by reading. */
-    outw(StatsDisable, ioaddr + EL3_CMD);
-    EL3WINDOW(6);
-    for (i = 0; i < 9; i++)
-	inb(ioaddr+i);
-    inw(ioaddr + 10);
-    inw(ioaddr + 12);
-
-    /* Switch to register set 1 for normal use. */
-    EL3WINDOW(1);
-
-    set_rx_mode(dev);
-    outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-    outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
-    outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
-    /* Allow status bits to be seen. */
-    outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
-    /* Ack all pending events, and set active indicator mask. */
-    outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+	unsigned int ioaddr = dev->base_addr;
+	int i;
+
+	EL3WINDOW(0);
+	outw(0x0001, ioaddr + 4);			/* Activate board. */
+	outw(0x3f00, ioaddr + 8);			/* Set the IRQ line. */
+
+	/* Set the station address in window 2. */
+	EL3WINDOW(2);
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+
+	tc589_set_xcvr(dev, dev->if_port);
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	EL3WINDOW(6);
+	for (i = 0; i < 9; i++)
+		inb(ioaddr+i);
+	inw(ioaddr + 10);
+	inw(ioaddr + 12);
+
+	/* Switch to register set 1 for normal use. */
+	EL3WINDOW(1);
+
+	set_rx_mode(dev);
+	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
 	 ioaddr + EL3_CMD);
-    outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
 	 | AdapterFailure, ioaddr + EL3_CMD);
 }
 
@@ -478,381 +494,406 @@ static const struct ethtool_ops netdev_ethtool_ops = {
 
 static int el3_config(struct net_device *dev, struct ifmap *map)
 {
-    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
-	if (map->port <= 3) {
-	    dev->if_port = map->port;
-	    netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
-	    tc589_set_xcvr(dev, dev->if_port);
-	} else
-	    return -EINVAL;
-    }
-    return 0;
+	if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+		if (map->port <= 3) {
+			dev->if_port = map->port;
+			netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
+			tc589_set_xcvr(dev, dev->if_port);
+		} else {
+			return -EINVAL;
+		}
+	}
+	return 0;
 }
 
 static int el3_open(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
+	struct el3_private *lp = netdev_priv(dev);
+	struct pcmcia_device *link = lp->p_dev;
 
-    if (!pcmcia_dev_present(link))
-	return -ENODEV;
+	if (!pcmcia_dev_present(link))
+		return -ENODEV;
 
-    link->open++;
-    netif_start_queue(dev);
+	link->open++;
+	netif_start_queue(dev);
 
-    tc589_reset(dev);
-    init_timer(&lp->media);
-    lp->media.function = media_check;
-    lp->media.data = (unsigned long) dev;
-    lp->media.expires = jiffies + HZ;
-    add_timer(&lp->media);
+	tc589_reset(dev);
+	init_timer(&lp->media);
+	lp->media.function = media_check;
+	lp->media.data = (unsigned long) dev;
+	lp->media.expires = jiffies + HZ;
+	add_timer(&lp->media);
 
-    dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
+	dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
 	  dev->name, inw(dev->base_addr + EL3_STATUS));
 
-    return 0;
+	return 0;
 }
 
 static void el3_tx_timeout(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-
-    netdev_warn(dev, "Transmit timed out!\n");
-    dump_status(dev);
-    dev->stats.tx_errors++;
-    dev->trans_start = jiffies; /* prevent tx timeout */
-    /* Issue TX_RESET and TX_START commands. */
-    tc589_wait_for_completion(dev, TxReset);
-    outw(TxEnable, ioaddr + EL3_CMD);
-    netif_wake_queue(dev);
+	unsigned int ioaddr = dev->base_addr;
+
+	netdev_warn(dev, "Transmit timed out!\n");
+	dump_status(dev);
+	dev->stats.tx_errors++;
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	/* Issue TX_RESET and TX_START commands. */
+	tc589_wait_for_completion(dev, TxReset);
+	outw(TxEnable, ioaddr + EL3_CMD);
+	netif_wake_queue(dev);
 }
 
 static void pop_tx_status(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    int i;
-
-    /* Clear the Tx status stack. */
-    for (i = 32; i > 0; i--) {
-	u_char tx_status = inb(ioaddr + TX_STATUS);
-	if (!(tx_status & 0x84)) break;
-	/* reset transmitter on jabber error or underrun */
-	if (tx_status & 0x30)
-		tc589_wait_for_completion(dev, TxReset);
-	if (tx_status & 0x38) {
-		netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status);
-		outw(TxEnable, ioaddr + EL3_CMD);
-		dev->stats.tx_aborted_errors++;
+	unsigned int ioaddr = dev->base_addr;
+	int i;
+
+	/* Clear the Tx status stack. */
+	for (i = 32; i > 0; i--) {
+		u_char tx_status = inb(ioaddr + TX_STATUS);
+		if (!(tx_status & 0x84))
+			break;
+		/* reset transmitter on jabber error or underrun */
+		if (tx_status & 0x30)
+			tc589_wait_for_completion(dev, TxReset);
+		if (tx_status & 0x38) {
+			netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status);
+			outw(TxEnable, ioaddr + EL3_CMD);
+			dev->stats.tx_aborted_errors++;
+		}
+		outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
 	}
-	outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
-    }
 }
 
 static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
 					struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    struct el3_private *priv = netdev_priv(dev);
-    unsigned long flags;
+	unsigned int ioaddr = dev->base_addr;
+	struct el3_private *priv = netdev_priv(dev);
+	unsigned long flags;
 
-    netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n",
+	netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n",
 	       (long)skb->len, inw(ioaddr + EL3_STATUS));
 
-    spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 
-    dev->stats.tx_bytes += skb->len;
+	dev->stats.tx_bytes += skb->len;
 
-    /* Put out the doubleword header... */
-    outw(skb->len, ioaddr + TX_FIFO);
-    outw(0x00, ioaddr + TX_FIFO);
-    /* ... and the packet rounded to a doubleword. */
-    outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+	/* Put out the doubleword header... */
+	outw(skb->len, ioaddr + TX_FIFO);
+	outw(0x00, ioaddr + TX_FIFO);
+	/* ... and the packet rounded to a doubleword. */
+	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 
-    if (inw(ioaddr + TX_FREE) <= 1536) {
-	netif_stop_queue(dev);
-	/* Interrupt us when the FIFO has room for max-sized packet. */
-	outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-    }
+	if (inw(ioaddr + TX_FREE) <= 1536) {
+		netif_stop_queue(dev);
+		/* Interrupt us when the FIFO has room for max-sized packet. */
+		outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+	}
 
-    pop_tx_status(dev);
-    spin_unlock_irqrestore(&priv->lock, flags);
-    dev_kfree_skb(skb);
+	pop_tx_status(dev);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	dev_kfree_skb(skb);
 
-    return NETDEV_TX_OK;
+	return NETDEV_TX_OK;
 }
 
 /* The EL3 interrupt handler. */
 static irqreturn_t el3_interrupt(int irq, void *dev_id)
 {
-    struct net_device *dev = (struct net_device *) dev_id;
-    struct el3_private *lp = netdev_priv(dev);
-    unsigned int ioaddr;
-    __u16 status;
-    int i = 0, handled = 1;
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr;
+	__u16 status;
+	int i = 0, handled = 1;
 
-    if (!netif_device_present(dev))
-	return IRQ_NONE;
+	if (!netif_device_present(dev))
+		return IRQ_NONE;
 
-    ioaddr = dev->base_addr;
+	ioaddr = dev->base_addr;
 
-    netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS));
+	netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS));
 
-    spin_lock(&lp->lock);
-    while ((status = inw(ioaddr + EL3_STATUS)) &
+	spin_lock(&lp->lock);
+	while ((status = inw(ioaddr + EL3_STATUS)) &
 	(IntLatch | RxComplete | StatsFull)) {
-	if ((status & 0xe000) != 0x2000) {
-		netdev_dbg(dev, "interrupt from dead card\n");
-		handled = 0;
-		break;
-	}
-	if (status & RxComplete)
-		el3_rx(dev);
-	if (status & TxAvailable) {
-		netdev_dbg(dev, "    TX room bit was handled.\n");
-		/* There's room in the FIFO for a full-sized packet. */
-		outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-		netif_wake_queue(dev);
-	}
-	if (status & TxComplete)
-		pop_tx_status(dev);
-	if (status & (AdapterFailure | RxEarly | StatsFull)) {
-	    /* Handle all uncommon interrupts. */
-	    if (status & StatsFull)		/* Empty statistics. */
-		update_stats(dev);
-	    if (status & RxEarly) {		/* Rx early is unused. */
-		el3_rx(dev);
-		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
-	    }
-	    if (status & AdapterFailure) {
-		u16 fifo_diag;
-		EL3WINDOW(4);
-		fifo_diag = inw(ioaddr + 4);
-		EL3WINDOW(1);
-		netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n",
+		if ((status & 0xe000) != 0x2000) {
+			netdev_dbg(dev, "interrupt from dead card\n");
+			handled = 0;
+			break;
+		}
+		if (status & RxComplete)
+			el3_rx(dev);
+		if (status & TxAvailable) {
+			netdev_dbg(dev, "    TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			netif_wake_queue(dev);
+		}
+		if (status & TxComplete)
+			pop_tx_status(dev);
+		if (status & (AdapterFailure | RxEarly | StatsFull)) {
+			/* Handle all uncommon interrupts. */
+			if (status & StatsFull)		/* Empty statistics. */
+				update_stats(dev);
+			if (status & RxEarly) {
+				/* Rx early is unused. */
+				el3_rx(dev);
+				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+			}
+			if (status & AdapterFailure) {
+				u16 fifo_diag;
+				EL3WINDOW(4);
+				fifo_diag = inw(ioaddr + 4);
+				EL3WINDOW(1);
+				netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n",
 			    fifo_diag);
-		if (fifo_diag & 0x0400) {
-		    /* Tx overrun */
-		    tc589_wait_for_completion(dev, TxReset);
-		    outw(TxEnable, ioaddr + EL3_CMD);
+				if (fifo_diag & 0x0400) {
+					/* Tx overrun */
+					tc589_wait_for_completion(dev, TxReset);
+					outw(TxEnable, ioaddr + EL3_CMD);
+				}
+				if (fifo_diag & 0x2000) {
+					/* Rx underrun */
+					tc589_wait_for_completion(dev, RxReset);
+					set_rx_mode(dev);
+					outw(RxEnable, ioaddr + EL3_CMD);
+				}
+				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+			}
 		}
-		if (fifo_diag & 0x2000) {
-		    /* Rx underrun */
-		    tc589_wait_for_completion(dev, RxReset);
-		    set_rx_mode(dev);
-		    outw(RxEnable, ioaddr + EL3_CMD);
+		if (++i > 10) {
+			netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n",
+					status);
+			/* Clear all interrupts */
+			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+			break;
 		}
-		outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
-	    }
+		/* Acknowledge the IRQ. */
+		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
 	}
-	if (++i > 10) {
-		netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n",
-			   status);
-		/* Clear all interrupts */
-		outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
-		break;
-	}
-	/* Acknowledge the IRQ. */
-	outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-    }
-    lp->last_irq = jiffies;
-    spin_unlock(&lp->lock);
-    netdev_dbg(dev, "exiting interrupt, status %4.4x.\n",
-	       inw(ioaddr + EL3_STATUS));
-    return IRQ_RETVAL(handled);
+	lp->last_irq = jiffies;
+	spin_unlock(&lp->lock);
+	netdev_dbg(dev, "exiting interrupt, status %4.4x.\n",
+			inw(ioaddr + EL3_STATUS));
+	return IRQ_RETVAL(handled);
 }
 
 static void media_check(unsigned long arg)
 {
-    struct net_device *dev = (struct net_device *)(arg);
-    struct el3_private *lp = netdev_priv(dev);
-    unsigned int ioaddr = dev->base_addr;
-    u16 media, errs;
-    unsigned long flags;
+	struct net_device *dev = (struct net_device *)(arg);
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr = dev->base_addr;
+	u16 media, errs;
+	unsigned long flags;
 
-    if (!netif_device_present(dev)) goto reschedule;
+	if (!netif_device_present(dev))
+		goto reschedule;
 
-    /* Check for pending interrupt with expired latency timer: with
-       this, we can limp along even if the interrupt is blocked */
-    if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
+	/* Check for pending interrupt with expired latency timer: with
+	 * this, we can limp along even if the interrupt is blocked
+	 */
+	if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
 	(inb(ioaddr + EL3_TIMER) == 0xff)) {
-	if (!lp->fast_poll)
-		netdev_warn(dev, "interrupt(s) dropped!\n");
-
-	local_irq_save(flags);
-	el3_interrupt(dev->irq, dev);
-	local_irq_restore(flags);
-
-	lp->fast_poll = HZ;
-    }
-    if (lp->fast_poll) {
-	lp->fast_poll--;
-	lp->media.expires = jiffies + HZ/100;
-	add_timer(&lp->media);
-	return;
-    }
-
-    /* lp->lock guards the EL3 window. Window should always be 1 except
-       when the lock is held */
-    spin_lock_irqsave(&lp->lock, flags);
-    EL3WINDOW(4);
-    media = inw(ioaddr+WN4_MEDIA) & 0xc810;
-
-    /* Ignore collisions unless we've had no irq's recently */
-    if (time_before(jiffies, lp->last_irq + HZ)) {
-	media &= ~0x0010;
-    } else {
-	/* Try harder to detect carrier errors */
-	EL3WINDOW(6);
-	outw(StatsDisable, ioaddr + EL3_CMD);
-	errs = inb(ioaddr + 0);
-	outw(StatsEnable, ioaddr + EL3_CMD);
-	dev->stats.tx_carrier_errors += errs;
-	if (errs || (lp->media_status & 0x0010)) media |= 0x0010;
-    }
+		if (!lp->fast_poll)
+			netdev_warn(dev, "interrupt(s) dropped!\n");
+
+		local_irq_save(flags);
+		el3_interrupt(dev->irq, dev);
+		local_irq_restore(flags);
+
+		lp->fast_poll = HZ;
+	}
+	if (lp->fast_poll) {
+		lp->fast_poll--;
+		lp->media.expires = jiffies + HZ/100;
+		add_timer(&lp->media);
+		return;
+	}
+
+	/* lp->lock guards the EL3 window. Window should always be 1 except
+	 * when the lock is held
+	 */
+
+	spin_lock_irqsave(&lp->lock, flags);
+	EL3WINDOW(4);
+	media = inw(ioaddr+WN4_MEDIA) & 0xc810;
+
+	/* Ignore collisions unless we've had no irq's recently */
+	if (time_before(jiffies, lp->last_irq + HZ)) {
+		media &= ~0x0010;
+	} else {
+		/* Try harder to detect carrier errors */
+		EL3WINDOW(6);
+		outw(StatsDisable, ioaddr + EL3_CMD);
+		errs = inb(ioaddr + 0);
+		outw(StatsEnable, ioaddr + EL3_CMD);
+		dev->stats.tx_carrier_errors += errs;
+		if (errs || (lp->media_status & 0x0010))
+			media |= 0x0010;
+	}
 
-    if (media != lp->media_status) {
-	if ((media & lp->media_status & 0x8000) &&
-	    ((lp->media_status ^ media) & 0x0800))
+	if (media != lp->media_status) {
+		if ((media & lp->media_status & 0x8000) &&
+				((lp->media_status ^ media) & 0x0800))
 		netdev_info(dev, "%s link beat\n",
-			    (lp->media_status & 0x0800 ? "lost" : "found"));
-	else if ((media & lp->media_status & 0x4000) &&
+				(lp->media_status & 0x0800 ? "lost" : "found"));
+		else if ((media & lp->media_status & 0x4000) &&
 		 ((lp->media_status ^ media) & 0x0010))
 		netdev_info(dev, "coax cable %s\n",
-			    (lp->media_status & 0x0010 ? "ok" : "problem"));
-	if (dev->if_port == 0) {
-	    if (media & 0x8000) {
-		if (media & 0x0800)
-			netdev_info(dev, "flipped to 10baseT\n");
-		else
+				(lp->media_status & 0x0010 ? "ok" : "problem"));
+		if (dev->if_port == 0) {
+			if (media & 0x8000) {
+				if (media & 0x0800)
+					netdev_info(dev, "flipped to 10baseT\n");
+				else
 			tc589_set_xcvr(dev, 2);
-	    } else if (media & 0x4000) {
-		if (media & 0x0010)
-		    tc589_set_xcvr(dev, 1);
-		else
-		    netdev_info(dev, "flipped to 10base2\n");
-	    }
+			} else if (media & 0x4000) {
+				if (media & 0x0010)
+					tc589_set_xcvr(dev, 1);
+				else
+					netdev_info(dev, "flipped to 10base2\n");
+			}
+		}
+		lp->media_status = media;
 	}
-	lp->media_status = media;
-    }
 
-    EL3WINDOW(1);
-    spin_unlock_irqrestore(&lp->lock, flags);
+	EL3WINDOW(1);
+	spin_unlock_irqrestore(&lp->lock, flags);
 
 reschedule:
-    lp->media.expires = jiffies + HZ;
-    add_timer(&lp->media);
+	lp->media.expires = jiffies + HZ;
+	add_timer(&lp->media);
 }
 
 static struct net_device_stats *el3_get_stats(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    unsigned long flags;
-    struct pcmcia_device *link = lp->p_dev;
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	struct pcmcia_device *link = lp->p_dev;
 
-    if (pcmcia_dev_present(link)) {
-	spin_lock_irqsave(&lp->lock, flags);
-	update_stats(dev);
-	spin_unlock_irqrestore(&lp->lock, flags);
-    }
-    return &dev->stats;
+	if (pcmcia_dev_present(link)) {
+		spin_lock_irqsave(&lp->lock, flags);
+		update_stats(dev);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+	return &dev->stats;
 }
 
-/*
-  Update statistics.  We change to register window 6, so this should be run
-  single-threaded if the device is active. This is expected to be a rare
-  operation, and it's simpler for the rest of the driver to assume that
-  window 1 is always valid rather than use a special window-state variable.
-
-  Caller must hold the lock for this
+/* Update statistics.  We change to register window 6, so this should be run
+* single-threaded if the device is active. This is expected to be a rare
+* operation, and it's simpler for the rest of the driver to assume that
+* window 1 is always valid rather than use a special window-state variable.
+*
+* Caller must hold the lock for this
 */
+
 static void update_stats(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-
-    netdev_dbg(dev, "updating the statistics.\n");
-    /* Turn off statistics updates while reading. */
-    outw(StatsDisable, ioaddr + EL3_CMD);
-    /* Switch to the stats window, and read everything. */
-    EL3WINDOW(6);
-    dev->stats.tx_carrier_errors	+= inb(ioaddr + 0);
-    dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
-    /* Multiple collisions. */		inb(ioaddr + 2);
-    dev->stats.collisions		+= inb(ioaddr + 3);
-    dev->stats.tx_window_errors		+= inb(ioaddr + 4);
-    dev->stats.rx_fifo_errors		+= inb(ioaddr + 5);
-    dev->stats.tx_packets		+= inb(ioaddr + 6);
-    /* Rx packets   */			inb(ioaddr + 7);
-    /* Tx deferrals */			inb(ioaddr + 8);
-    /* Rx octets */			inw(ioaddr + 10);
-    /* Tx octets */			inw(ioaddr + 12);
-
-    /* Back to window 1, and turn statistics back on. */
-    EL3WINDOW(1);
-    outw(StatsEnable, ioaddr + EL3_CMD);
+	unsigned int ioaddr = dev->base_addr;
+
+	netdev_dbg(dev, "updating the statistics.\n");
+	/* Turn off statistics updates while reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	/* Switch to the stats window, and read everything. */
+	EL3WINDOW(6);
+	dev->stats.tx_carrier_errors	+= inb(ioaddr + 0);
+	dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
+	/* Multiple collisions. */
+	inb(ioaddr + 2);
+	dev->stats.collisions		+= inb(ioaddr + 3);
+	dev->stats.tx_window_errors		+= inb(ioaddr + 4);
+	dev->stats.rx_fifo_errors		+= inb(ioaddr + 5);
+	dev->stats.tx_packets		+= inb(ioaddr + 6);
+	/* Rx packets   */
+	inb(ioaddr + 7);
+	/* Tx deferrals */
+	inb(ioaddr + 8);
+	/* Rx octets */
+	inw(ioaddr + 10);
+	/* Tx octets */
+	inw(ioaddr + 12);
+
+	/* Back to window 1, and turn statistics back on. */
+	EL3WINDOW(1);
+	outw(StatsEnable, ioaddr + EL3_CMD);
 }
 
 static int el3_rx(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    int worklimit = 32;
-    short rx_status;
+	unsigned int ioaddr = dev->base_addr;
+	int worklimit = 32;
+	short rx_status;
 
-    netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n",
+	netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n",
 	       inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
-    while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
+	while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
 		    worklimit > 0) {
-	worklimit--;
-	if (rx_status & 0x4000) { /* Error, update stats. */
-	    short error = rx_status & 0x3800;
-	    dev->stats.rx_errors++;
-	    switch (error) {
-	    case 0x0000:	dev->stats.rx_over_errors++; break;
-	    case 0x0800:	dev->stats.rx_length_errors++; break;
-	    case 0x1000:	dev->stats.rx_frame_errors++; break;
-	    case 0x1800:	dev->stats.rx_length_errors++; break;
-	    case 0x2000:	dev->stats.rx_frame_errors++; break;
-	    case 0x2800:	dev->stats.rx_crc_errors++; break;
-	    }
-	} else {
-	    short pkt_len = rx_status & 0x7ff;
-	    struct sk_buff *skb;
-
-	    skb = netdev_alloc_skb(dev, pkt_len + 5);
-
-	    netdev_dbg(dev, "    Receiving packet size %d status %4.4x.\n",
+		worklimit--;
+		if (rx_status & 0x4000) { /* Error, update stats. */
+			short error = rx_status & 0x3800;
+			dev->stats.rx_errors++;
+			switch (error) {
+			case 0x0000:
+				dev->stats.rx_over_errors++;
+				break;
+			case 0x0800:
+				dev->stats.rx_length_errors++;
+				break;
+			case 0x1000:
+				dev->stats.rx_frame_errors++;
+				break;
+			case 0x1800:
+				dev->stats.rx_length_errors++;
+				break;
+			case 0x2000:
+				dev->stats.rx_frame_errors++;
+				break;
+			case 0x2800:
+				dev->stats.rx_crc_errors++;
+				break;
+			}
+		} else {
+			short pkt_len = rx_status & 0x7ff;
+			struct sk_buff *skb;
+
+			skb = netdev_alloc_skb(dev, pkt_len + 5);
+
+			netdev_dbg(dev, "    Receiving packet size %d status %4.4x.\n",
 		       pkt_len, rx_status);
-	    if (skb != NULL) {
-		skb_reserve(skb, 2);
-		insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
+			if (skb != NULL) {
+				skb_reserve(skb, 2);
+				insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
 			(pkt_len+3)>>2);
-		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += pkt_len;
-	    } else {
-		netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n",
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+			} else {
+				netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n",
 			   pkt_len);
-		dev->stats.rx_dropped++;
-	    }
+				dev->stats.rx_dropped++;
+			}
+		}
+		/* Pop the top of the Rx FIFO */
+		tc589_wait_for_completion(dev, RxDiscard);
 	}
-	/* Pop the top of the Rx FIFO */
-	tc589_wait_for_completion(dev, RxDiscard);
-    }
-    if (worklimit == 0)
-	netdev_warn(dev, "too much work in el3_rx!\n");
-    return 0;
+	if (worklimit == 0)
+		netdev_warn(dev, "too much work in el3_rx!\n");
+	return 0;
 }
 
 static void set_rx_mode(struct net_device *dev)
 {
-    unsigned int ioaddr = dev->base_addr;
-    u16 opts = SetRxFilter | RxStation | RxBroadcast;
-
-    if (dev->flags & IFF_PROMISC)
-	opts |= RxMulticast | RxProm;
-    else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
-	opts |= RxMulticast;
-    outw(opts, ioaddr + EL3_CMD);
+	unsigned int ioaddr = dev->base_addr;
+	u16 opts = SetRxFilter | RxStation | RxBroadcast;
+
+	if (dev->flags & IFF_PROMISC)
+		opts |= RxMulticast | RxProm;
+	else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
+		opts |= RxMulticast;
+	outw(opts, ioaddr + EL3_CMD);
 }
 
 static void set_multicast_list(struct net_device *dev)
@@ -867,44 +908,44 @@ static void set_multicast_list(struct net_device *dev)
 
 static int el3_close(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
-    unsigned int ioaddr = dev->base_addr;
-
-    dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
+	struct el3_private *lp = netdev_priv(dev);
+	struct pcmcia_device *link = lp->p_dev;
+	unsigned int ioaddr = dev->base_addr;
+
+	dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
+
+	if (pcmcia_dev_present(link)) {
+		/* Turn off statistics ASAP.  We update dev->stats below. */
+		outw(StatsDisable, ioaddr + EL3_CMD);
+
+		/* Disable the receiver and transmitter. */
+		outw(RxDisable, ioaddr + EL3_CMD);
+		outw(TxDisable, ioaddr + EL3_CMD);
+
+		if (dev->if_port == 2)
+			/* Turn off thinnet power.  Green! */
+			outw(StopCoax, ioaddr + EL3_CMD);
+		else if (dev->if_port == 1) {
+			/* Disable link beat and jabber */
+			EL3WINDOW(4);
+			outw(0, ioaddr + WN4_MEDIA);
+		}
 
-    if (pcmcia_dev_present(link)) {
-	/* Turn off statistics ASAP.  We update dev->stats below. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
+		/* Switching back to window 0 disables the IRQ. */
+		EL3WINDOW(0);
+		/* But we explicitly zero the IRQ line select anyway. */
+		outw(0x0f00, ioaddr + WN0_IRQ);
 
-	/* Disable the receiver and transmitter. */
-	outw(RxDisable, ioaddr + EL3_CMD);
-	outw(TxDisable, ioaddr + EL3_CMD);
-
-	if (dev->if_port == 2)
-	    /* Turn off thinnet power.  Green! */
-	    outw(StopCoax, ioaddr + EL3_CMD);
-	else if (dev->if_port == 1) {
-	    /* Disable link beat and jabber */
-	    EL3WINDOW(4);
-	    outw(0, ioaddr + WN4_MEDIA);
+		/* Check if the card still exists */
+		if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
+			update_stats(dev);
 	}
 
-	/* Switching back to window 0 disables the IRQ. */
-	EL3WINDOW(0);
-	/* But we explicitly zero the IRQ line select anyway. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
-
-	/* Check if the card still exists */
-	if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
-	    update_stats(dev);
-    }
-
-    link->open--;
-    netif_stop_queue(dev);
-    del_timer_sync(&lp->media);
+	link->open--;
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->media);
 
-    return 0;
+	return 0;
 }
 
 static const struct pcmcia_device_id tc589_ids[] = {
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
index 65b735d4a6ad..afaab4b2333f 100644
--- a/drivers/net/ethernet/3com/Kconfig
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -66,7 +66,7 @@ config PCMCIA_3C589
 
 config VORTEX
 	tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
-	depends on (PCI || EISA) && HAS_IOPORT
+	depends on (PCI || EISA) && HAS_IOPORT_MAP
 	select MII
 	---help---
 	  This option enables driver support for a large number of 10Mbps and
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 9339cccfe05a..2ae00ed83afa 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -549,35 +549,35 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 	struct pcnet32_rx_head *new_rx_ring;
 	struct sk_buff **new_skb_list;
 	int new, overlap;
+	unsigned int entries = 1 << size;
 
 	new_rx_ring = pci_alloc_consistent(lp->pci_dev,
 					   sizeof(struct pcnet32_rx_head) *
-					   (1 << size),
+					   entries,
 					   &new_ring_dma_addr);
 	if (new_rx_ring == NULL) {
 		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
 		return;
 	}
-	memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
+	memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * entries);
 
-	new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t), GFP_ATOMIC);
+	new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
 	if (!new_dma_addr_list)
 		goto free_new_rx_ring;
 
-	new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *),
-			       GFP_ATOMIC);
+	new_skb_list = kcalloc(entries, sizeof(struct sk_buff *), GFP_ATOMIC);
 	if (!new_skb_list)
 		goto free_new_lists;
 
 	/* first copy the current receive buffers */
-	overlap = min(size, lp->rx_ring_size);
+	overlap = min(entries, lp->rx_ring_size);
 	for (new = 0; new < overlap; new++) {
 		new_rx_ring[new] = lp->rx_ring[new];
 		new_dma_addr_list[new] = lp->rx_dma_addr[new];
 		new_skb_list[new] = lp->rx_skbuff[new];
 	}
 	/* now allocate any new buffers needed */
-	for (; new < size; new++) {
+	for (; new < entries; new++) {
 		struct sk_buff *rx_skbuff;
 		new_skb_list[new] = netdev_alloc_skb(dev, PKT_BUF_SKB);
 		rx_skbuff = new_skb_list[new];
@@ -592,6 +592,13 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 		new_dma_addr_list[new] =
 			    pci_map_single(lp->pci_dev, rx_skbuff->data,
 					   PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(lp->pci_dev,
+					  new_dma_addr_list[new])) {
+			netif_err(lp, drv, dev, "%s dma mapping failed\n",
+				  __func__);
+			dev_kfree_skb(new_skb_list[new]);
+			goto free_all_new;
+		}
 		new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]);
 		new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE);
 		new_rx_ring[new].status = cpu_to_le16(0x8000);
@@ -599,8 +606,12 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 	/* and free any unneeded buffers */
 	for (; new < lp->rx_ring_size; new++) {
 		if (lp->rx_skbuff[new]) {
-			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
-					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			if (!pci_dma_mapping_error(lp->pci_dev,
+						   lp->rx_dma_addr[new]))
+				pci_unmap_single(lp->pci_dev,
+						 lp->rx_dma_addr[new],
+						 PKT_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(lp->rx_skbuff[new]);
 		}
 	}
@@ -612,7 +623,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 			    lp->rx_ring_size, lp->rx_ring,
 			    lp->rx_ring_dma_addr);
 
-	lp->rx_ring_size = (1 << size);
+	lp->rx_ring_size = entries;
 	lp->rx_mod_mask = lp->rx_ring_size - 1;
 	lp->rx_len_bits = (size << 4);
 	lp->rx_ring = new_rx_ring;
@@ -624,8 +635,12 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 free_all_new:
 	while (--new >= lp->rx_ring_size) {
 		if (new_skb_list[new]) {
-			pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
-					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			if (!pci_dma_mapping_error(lp->pci_dev,
+						   new_dma_addr_list[new]))
+				pci_unmap_single(lp->pci_dev,
+						 new_dma_addr_list[new],
+						 PKT_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(new_skb_list[new]);
 		}
 	}
@@ -634,8 +649,7 @@ free_new_lists:
 	kfree(new_dma_addr_list);
 free_new_rx_ring:
 	pci_free_consistent(lp->pci_dev,
-			    sizeof(struct pcnet32_rx_head) *
-			    (1 << size),
+			    sizeof(struct pcnet32_rx_head) * entries,
 			    new_rx_ring,
 			    new_ring_dma_addr);
 }
@@ -650,8 +664,12 @@ static void pcnet32_purge_rx_ring(struct net_device *dev)
 		lp->rx_ring[i].status = 0;	/* CPU owns buffer */
 		wmb();		/* Make sure adapter sees owner change */
 		if (lp->rx_skbuff[i]) {
-			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
-					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			if (!pci_dma_mapping_error(lp->pci_dev,
+						   lp->rx_dma_addr[i]))
+				pci_unmap_single(lp->pci_dev,
+						 lp->rx_dma_addr[i],
+						 PKT_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
 			dev_kfree_skb_any(lp->rx_skbuff[i]);
 		}
 		lp->rx_skbuff[i] = NULL;
@@ -930,6 +948,12 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
 		lp->tx_dma_addr[x] =
 			pci_map_single(lp->pci_dev, skb->data, skb->len,
 				       PCI_DMA_TODEVICE);
+		if (pci_dma_mapping_error(lp->pci_dev, lp->tx_dma_addr[x])) {
+			netif_printk(lp, hw, KERN_DEBUG, dev,
+				     "DMA mapping error at line: %d!\n",
+				     __LINE__);
+			goto clean_up;
+		}
 		lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]);
 		wmb();	/* Make sure owner changes after all others are visible */
 		lp->tx_ring[x].status = cpu_to_le16(status);
@@ -1142,24 +1166,36 @@ static void pcnet32_rx_entry(struct net_device *dev,
 
 	if (pkt_len > rx_copybreak) {
 		struct sk_buff *newskb;
+		dma_addr_t new_dma_addr;
 
 		newskb = netdev_alloc_skb(dev, PKT_BUF_SKB);
+		/*
+		 * map the new buffer, if mapping fails, drop the packet and
+		 * reuse the old buffer
+		 */
 		if (newskb) {
 			skb_reserve(newskb, NET_IP_ALIGN);
-			skb = lp->rx_skbuff[entry];
-			pci_unmap_single(lp->pci_dev,
-					 lp->rx_dma_addr[entry],
-					 PKT_BUF_SIZE,
-					 PCI_DMA_FROMDEVICE);
-			skb_put(skb, pkt_len);
-			lp->rx_skbuff[entry] = newskb;
-			lp->rx_dma_addr[entry] =
-					    pci_map_single(lp->pci_dev,
-							   newskb->data,
-							   PKT_BUF_SIZE,
-							   PCI_DMA_FROMDEVICE);
-			rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]);
-			rx_in_place = 1;
+			new_dma_addr = pci_map_single(lp->pci_dev,
+						      newskb->data,
+						      PKT_BUF_SIZE,
+						      PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(lp->pci_dev, new_dma_addr)) {
+				netif_err(lp, rx_err, dev,
+					  "DMA mapping error.\n");
+				dev_kfree_skb(newskb);
+				skb = NULL;
+			} else {
+				skb = lp->rx_skbuff[entry];
+				pci_unmap_single(lp->pci_dev,
+						 lp->rx_dma_addr[entry],
+						 PKT_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
+				skb_put(skb, pkt_len);
+				lp->rx_skbuff[entry] = newskb;
+				lp->rx_dma_addr[entry] = new_dma_addr;
+				rxp->base = cpu_to_le32(new_dma_addr);
+				rx_in_place = 1;
+			}
 		} else
 			skb = NULL;
 	} else
@@ -2229,9 +2265,12 @@ static void pcnet32_purge_tx_ring(struct net_device *dev)
 		lp->tx_ring[i].status = 0;	/* CPU owns buffer */
 		wmb();		/* Make sure adapter sees owner change */
 		if (lp->tx_skbuff[i]) {
-			pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
-					 lp->tx_skbuff[i]->len,
-					 PCI_DMA_TODEVICE);
+			if (!pci_dma_mapping_error(lp->pci_dev,
+						   lp->tx_dma_addr[i]))
+				pci_unmap_single(lp->pci_dev,
+						 lp->tx_dma_addr[i],
+						 lp->tx_skbuff[i]->len,
+						 PCI_DMA_TODEVICE);
 			dev_kfree_skb_any(lp->tx_skbuff[i]);
 		}
 		lp->tx_skbuff[i] = NULL;
@@ -2264,10 +2303,19 @@ static int pcnet32_init_ring(struct net_device *dev)
 		}
 
 		rmb();
-		if (lp->rx_dma_addr[i] == 0)
+		if (lp->rx_dma_addr[i] == 0) {
 			lp->rx_dma_addr[i] =
 			    pci_map_single(lp->pci_dev, rx_skbuff->data,
 					   PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(lp->pci_dev,
+						  lp->rx_dma_addr[i])) {
+				/* there is not much we can do at this point */
+				netif_err(lp, drv, dev,
+					  "%s pci dma mapping error\n",
+					  __func__);
+				return -1;
+			}
+		}
 		lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]);
 		lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE);
 		wmb();		/* Make sure owner changes after all others are visible */
@@ -2397,9 +2445,14 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
 
 	lp->tx_ring[entry].misc = 0x00000000;
 
-	lp->tx_skbuff[entry] = skb;
 	lp->tx_dma_addr[entry] =
 	    pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(lp->pci_dev, lp->tx_dma_addr[entry])) {
+		dev_kfree_skb(skb);
+		dev->stats.tx_dropped++;
+		goto drop_packet;
+	}
+	lp->tx_skbuff[entry] = skb;
 	lp->tx_ring[entry].base = cpu_to_le32(lp->tx_dma_addr[entry]);
 	wmb();			/* Make sure owner changes after all others are visible */
 	lp->tx_ring[entry].status = cpu_to_le16(status);
@@ -2414,6 +2467,7 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
 		lp->tx_full = 1;
 		netif_stop_queue(dev);
 	}
+drop_packet:
 	spin_unlock_irqrestore(&lp->lock, flags);
 	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 3f97d9fd0a71..85dbddd03722 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -60,6 +60,17 @@ config BCM63XX_ENET
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config BCMGENET
+	tristate "Broadcom GENET internal MAC support"
+	depends on OF
+	select MII
+	select PHYLIB
+	select FIXED_PHY if BCMGENET=y
+	select BCM7XXX_PHY
+	help
+	  This driver supports the built-in Ethernet MACs found in the
+	  Broadcom BCM7xxx Set Top Box family chipset.
+
 config BNX2
 	tristate "Broadcom NetXtremeII support"
 	depends on PCI
diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
index 68efa1a3fb88..fd639a0d4c7d 100644
--- a/drivers/net/ethernet/broadcom/Makefile
+++ b/drivers/net/ethernet/broadcom/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_BCMGENET) += genet/
 obj-$(CONFIG_BNX2) += bnx2.o
 obj-$(CONFIG_CNIC) += cnic.o
 obj-$(CONFIG_BNX2X) += bnx2x/
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 1f7b5aa114fa..8a7bf7dad898 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1484,6 +1484,10 @@ static int b44_open(struct net_device *dev)
 	add_timer(&bp->timer);
 
 	b44_enable_ints(bp);
+
+	if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+		phy_start(bp->phydev);
+
 	netif_start_queue(dev);
 out:
 	return err;
@@ -1646,6 +1650,9 @@ static int b44_close(struct net_device *dev)
 
 	netif_stop_queue(dev);
 
+	if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+		phy_stop(bp->phydev);
+
 	napi_disable(&bp->napi);
 
 	del_timer_sync(&bp->timer);
@@ -2222,7 +2229,12 @@ static void b44_adjust_link(struct net_device *dev)
 	}
 
 	if (status_changed) {
-		b44_check_phy(bp);
+		u32 val = br32(bp, B44_TX_CTRL);
+		if (bp->flags & B44_FLAG_FULL_DUPLEX)
+			val |= TX_CTRL_DUPLEX;
+		else
+			val &= ~TX_CTRL_DUPLEX;
+		bw32(bp, B44_TX_CTRL, val);
 		phy_print_status(phydev);
 	}
 }
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index cda25ac45b47..ca6b36220d94 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -6206,7 +6206,7 @@ bnx2_free_irq(struct bnx2 *bp)
 static void
 bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
 {
-	int i, total_vecs, rc;
+	int i, total_vecs;
 	struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC];
 	struct net_device *dev = bp->dev;
 	const int len = sizeof(bp->irq_tbl[0].name);
@@ -6229,16 +6229,9 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
 #ifdef BCM_CNIC
 	total_vecs++;
 #endif
-	rc = -ENOSPC;
-	while (total_vecs >= BNX2_MIN_MSIX_VEC) {
-		rc = pci_enable_msix(bp->pdev, msix_ent, total_vecs);
-		if (rc <= 0)
-			break;
-		if (rc > 0)
-			total_vecs = rc;
-	}
-
-	if (rc != 0)
+	total_vecs = pci_enable_msix_range(bp->pdev, msix_ent,
+					   BNX2_MIN_MSIX_VEC, total_vecs);
+	if (total_vecs < 0)
 		return;
 
 	msix_vecs = total_vecs;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 391f29ef6d2e..722160940ab9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -26,8 +26,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.78.17-0"
-#define DRV_MODULE_RELDATE      "2013/04/11"
+#define DRV_MODULE_VERSION      "1.78.19-0"
+#define DRV_MODULE_RELDATE      "2014/02/10"
 #define BNX2X_BC_VER            0x040200
 
 #if defined(CONFIG_DCB)
@@ -75,13 +75,22 @@ enum bnx2x_int_mode {
 #define BNX2X_MSG_DCB			0x8000000
 
 /* regular debug print */
+#define DP_INNER(fmt, ...)					\
+	pr_notice("[%s:%d(%s)]" fmt,				\
+		  __func__, __LINE__,				\
+		  bp->dev ? (bp->dev->name) : "?",		\
+		  ##__VA_ARGS__);
+
 #define DP(__mask, fmt, ...)					\
 do {								\
 	if (unlikely(bp->msg_enable & (__mask)))		\
-		pr_notice("[%s:%d(%s)]" fmt,			\
-			  __func__, __LINE__,			\
-			  bp->dev ? (bp->dev->name) : "?",	\
-			  ##__VA_ARGS__);			\
+		DP_INNER(fmt, ##__VA_ARGS__);			\
+} while (0)
+
+#define DP_AND(__mask, fmt, ...)				\
+do {								\
+	if (unlikely((bp->msg_enable & (__mask)) == __mask))	\
+		DP_INNER(fmt, ##__VA_ARGS__);			\
 } while (0)
 
 #define DP_CONT(__mask, fmt, ...)				\
@@ -1261,6 +1270,7 @@ struct bnx2x_slowpath {
 	union {
 		struct client_init_ramrod_data  init_data;
 		struct client_update_ramrod_data update_data;
+		struct tpa_update_ramrod_data tpa_data;
 	} q_rdata;
 
 	union {
@@ -1392,7 +1402,7 @@ struct bnx2x_fw_stats_data {
 };
 
 /* Public slow path states */
-enum {
+enum sp_rtnl_flag {
 	BNX2X_SP_RTNL_SETUP_TC,
 	BNX2X_SP_RTNL_TX_TIMEOUT,
 	BNX2X_SP_RTNL_FAN_FAILURE,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 66c0df78c3ff..117b5c7f8ac9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -61,10 +61,14 @@ static void bnx2x_add_all_napi(struct bnx2x *bp)
 
 static int bnx2x_calc_num_queues(struct bnx2x *bp)
 {
-	return  bnx2x_num_queues ?
-		 min_t(int, bnx2x_num_queues, BNX2X_MAX_QUEUES(bp)) :
-		 min_t(int, netif_get_num_default_rss_queues(),
-		       BNX2X_MAX_QUEUES(bp));
+	int nq = bnx2x_num_queues ? : netif_get_num_default_rss_queues();
+
+	/* Reduce memory usage in kdump environment by using only one queue */
+	if (reset_devices)
+		nq = 1;
+
+	nq = clamp(nq, 1, BNX2X_MAX_QUEUES(bp));
+	return nq;
 }
 
 /**
@@ -1638,36 +1642,16 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 	DP(BNX2X_MSG_SP, "about to request enable msix with %d vectors\n",
 	   msix_vec);
 
-	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], msix_vec);
-
+	rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0],
+				   BNX2X_MIN_MSIX_VEC_CNT(bp), msix_vec);
 	/*
 	 * reconfigure number of tx/rx queues according to available
 	 * MSI-X vectors
 	 */
-	if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
-		/* how less vectors we will have? */
-		int diff = msix_vec - rc;
-
-		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
-
-		rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc);
-
-		if (rc) {
-			BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
-			goto no_msix;
-		}
-		/*
-		 * decrease number of queues by number of unallocated entries
-		 */
-		bp->num_ethernet_queues -= diff;
-		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
-
-		BNX2X_DEV_INFO("New queue configuration set: %d\n",
-			       bp->num_queues);
-	} else if (rc > 0) {
+	if (rc == -ENOSPC) {
 		/* Get by with single vector */
-		rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], 1);
-		if (rc) {
+		rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0], 1, 1);
+		if (rc < 0) {
 			BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n",
 				       rc);
 			goto no_msix;
@@ -1680,8 +1664,22 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 		bp->num_ethernet_queues = 1;
 		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 	} else if (rc < 0) {
-		BNX2X_DEV_INFO("MSI-X is not attainable  rc %d\n", rc);
+		BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
 		goto no_msix;
+	} else if (rc < msix_vec) {
+		/* how less vectors we will have? */
+		int diff = msix_vec - rc;
+
+		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
+
+		/*
+		 * decrease number of queues by number of unallocated entries
+		 */
+		bp->num_ethernet_queues -= diff;
+		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
+
+		BNX2X_DEV_INFO("New queue configuration set: %d\n",
+			       bp->num_queues);
 	}
 
 	bp->flags |= USING_MSIX_FLAG;
@@ -2234,8 +2232,10 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
 		sizeof(struct per_queue_stats) * num_queue_stats +
 		sizeof(struct stats_counter);
 
-	BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping,
-			bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+	bp->fw_stats = BNX2X_PCI_ALLOC(&bp->fw_stats_mapping,
+				       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+	if (!bp->fw_stats)
+		goto alloc_mem_err;
 
 	/* Set shortcuts */
 	bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats;
@@ -3875,7 +3875,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 						     xmit_type);
 		}
 
-		/* Add the macs to the parsing BD this is a vf */
+		/* Add the macs to the parsing BD if this is a vf or if
+		 * Tx Switching is enabled.
+		 */
 		if (IS_VF(bp)) {
 			/* override GRE parameters in BD */
 			bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.src_hi,
@@ -3887,6 +3889,11 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 					      &pbd_e2->data.mac_addr.dst_mid,
 					      &pbd_e2->data.mac_addr.dst_lo,
 					      eth->h_dest);
+		} else if (bp->flags & TX_SWITCHING) {
+			bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.dst_hi,
+					      &pbd_e2->data.mac_addr.dst_mid,
+					      &pbd_e2->data.mac_addr.dst_lo,
+					      eth->h_dest);
 		}
 
 		SET_FLAG(pbd_e2_parsing_data,
@@ -4363,14 +4370,17 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 
 	if (!IS_FCOE_IDX(index)) {
 		/* status blocks */
-		if (!CHIP_IS_E1x(bp))
-			BNX2X_PCI_ALLOC(sb->e2_sb,
-				&bnx2x_fp(bp, index, status_blk_mapping),
-				sizeof(struct host_hc_status_block_e2));
-		else
-			BNX2X_PCI_ALLOC(sb->e1x_sb,
-				&bnx2x_fp(bp, index, status_blk_mapping),
-			    sizeof(struct host_hc_status_block_e1x));
+		if (!CHIP_IS_E1x(bp)) {
+			sb->e2_sb = BNX2X_PCI_ALLOC(&bnx2x_fp(bp, index, status_blk_mapping),
+						    sizeof(struct host_hc_status_block_e2));
+			if (!sb->e2_sb)
+				goto alloc_mem_err;
+		} else {
+			sb->e1x_sb = BNX2X_PCI_ALLOC(&bnx2x_fp(bp, index, status_blk_mapping),
+						     sizeof(struct host_hc_status_block_e1x));
+			if (!sb->e1x_sb)
+				goto alloc_mem_err;
+		}
 	}
 
 	/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
@@ -4389,35 +4399,49 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 			   "allocating tx memory of fp %d cos %d\n",
 			   index, cos);
 
-			BNX2X_ALLOC(txdata->tx_buf_ring,
-				sizeof(struct sw_tx_bd) * NUM_TX_BD);
-			BNX2X_PCI_ALLOC(txdata->tx_desc_ring,
-				&txdata->tx_desc_mapping,
-				sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+			txdata->tx_buf_ring = kcalloc(NUM_TX_BD,
+						      sizeof(struct sw_tx_bd),
+						      GFP_KERNEL);
+			if (!txdata->tx_buf_ring)
+				goto alloc_mem_err;
+			txdata->tx_desc_ring = BNX2X_PCI_ALLOC(&txdata->tx_desc_mapping,
+							       sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+			if (!txdata->tx_desc_ring)
+				goto alloc_mem_err;
 		}
 	}
 
 	/* Rx */
 	if (!skip_rx_queue(bp, index)) {
 		/* fastpath rx rings: rx_buf rx_desc rx_comp */
-		BNX2X_ALLOC(bnx2x_fp(bp, index, rx_buf_ring),
-				sizeof(struct sw_rx_bd) * NUM_RX_BD);
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_desc_ring),
-				&bnx2x_fp(bp, index, rx_desc_mapping),
-				sizeof(struct eth_rx_bd) * NUM_RX_BD);
+		bnx2x_fp(bp, index, rx_buf_ring) =
+			kcalloc(NUM_RX_BD, sizeof(struct sw_rx_bd), GFP_KERNEL);
+		if (!bnx2x_fp(bp, index, rx_buf_ring))
+			goto alloc_mem_err;
+		bnx2x_fp(bp, index, rx_desc_ring) =
+			BNX2X_PCI_ALLOC(&bnx2x_fp(bp, index, rx_desc_mapping),
+					sizeof(struct eth_rx_bd) * NUM_RX_BD);
+		if (!bnx2x_fp(bp, index, rx_desc_ring))
+			goto alloc_mem_err;
 
 		/* Seed all CQEs by 1s */
-		BNX2X_PCI_FALLOC(bnx2x_fp(bp, index, rx_comp_ring),
-				 &bnx2x_fp(bp, index, rx_comp_mapping),
-				 sizeof(struct eth_fast_path_rx_cqe) *
-				 NUM_RCQ_BD);
+		bnx2x_fp(bp, index, rx_comp_ring) =
+			BNX2X_PCI_FALLOC(&bnx2x_fp(bp, index, rx_comp_mapping),
+					 sizeof(struct eth_fast_path_rx_cqe) * NUM_RCQ_BD);
+		if (!bnx2x_fp(bp, index, rx_comp_ring))
+			goto alloc_mem_err;
 
 		/* SGE ring */
-		BNX2X_ALLOC(bnx2x_fp(bp, index, rx_page_ring),
-				sizeof(struct sw_rx_page) * NUM_RX_SGE);
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_sge_ring),
-				&bnx2x_fp(bp, index, rx_sge_mapping),
-				BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
+		bnx2x_fp(bp, index, rx_page_ring) =
+			kcalloc(NUM_RX_SGE, sizeof(struct sw_rx_page),
+				GFP_KERNEL);
+		if (!bnx2x_fp(bp, index, rx_page_ring))
+			goto alloc_mem_err;
+		bnx2x_fp(bp, index, rx_sge_ring) =
+			BNX2X_PCI_ALLOC(&bnx2x_fp(bp, index, rx_sge_mapping),
+					BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
+		if (!bnx2x_fp(bp, index, rx_sge_ring))
+			goto alloc_mem_err;
 		/* RX BD ring */
 		bnx2x_set_next_page_rx_bd(fp);
 
@@ -4773,12 +4797,8 @@ void bnx2x_tx_timeout(struct net_device *dev)
 		bnx2x_panic();
 #endif
 
-	smp_mb__before_clear_bit();
-	set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
-	smp_mb__after_clear_bit();
-
 	/* This allows the netif to be shutdown gracefully before resetting */
-	schedule_delayed_work(&bp->sp_rtnl_task, 0);
+	bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_TX_TIMEOUT, 0);
 }
 
 int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -4906,3 +4926,15 @@ void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
 	disable = disable ? 1 : (usec ? 0 : 1);
 	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
 }
+
+void bnx2x_schedule_sp_rtnl(struct bnx2x *bp, enum sp_rtnl_flag flag,
+			    u32 verbose)
+{
+	smp_mb__before_clear_bit();
+	set_bit(flag, &bp->sp_rtnl_state);
+	smp_mb__after_clear_bit();
+	DP((BNX2X_MSG_SP | verbose), "Scheduling sp_rtnl task [Flag: %d]\n",
+	   flag);
+	schedule_delayed_work(&bp->sp_rtnl_task, 0);
+}
+EXPORT_SYMBOL(bnx2x_schedule_sp_rtnl);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index a89a40f88c25..05f4f5f52635 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -47,31 +47,26 @@ extern int bnx2x_num_queues;
 		} \
 	} while (0)
 
-#define BNX2X_PCI_ALLOC(x, y, size) \
-	do { \
-		x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-		DP(NETIF_MSG_HW, "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n", \
-		   (unsigned long long)(*y), x); \
-	} while (0)
-
-#define BNX2X_PCI_FALLOC(x, y, size) \
-	do { \
-		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-		memset((void *)x, 0xFFFFFFFF, size); \
-		DP(NETIF_MSG_HW, "BNX2X_PCI_FALLOC: Physical %Lx Virtual %p\n",\
-		   (unsigned long long)(*y), x); \
-	} while (0)
-
-#define BNX2X_ALLOC(x, size) \
-	do { \
-		x = kzalloc(size, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-	} while (0)
+#define BNX2X_PCI_ALLOC(y, size)					\
+({									\
+	void *x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
+	if (x)								\
+		DP(NETIF_MSG_HW,					\
+		   "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n",	\
+		   (unsigned long long)(*y), x);			\
+	x;								\
+})
+#define BNX2X_PCI_FALLOC(y, size)					\
+({									\
+	void *x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
+	if (x) {							\
+		memset(x, 0xff, size);					\
+		DP(NETIF_MSG_HW,					\
+		   "BNX2X_PCI_FALLOC: Physical %Lx Virtual %p\n",	\
+		   (unsigned long long)(*y), x);			\
+	}								\
+	x;								\
+})
 
 /*********************** Interfaces ****************************
  *  Functions that need to be implemented by each driver version
@@ -1324,4 +1319,7 @@ void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len);
 int bnx2x_drain_tx_queues(struct bnx2x *bp);
 void bnx2x_squeeze_objects(struct bnx2x *bp);
 
+void bnx2x_schedule_sp_rtnl(struct bnx2x*, enum sp_rtnl_flag,
+			    u32 verbose);
+
 #endif /* BNX2X_CMN_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index fdace204b054..97ea5421dd96 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -710,8 +710,7 @@ static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
 	 * as we are handling an attention on a work queue which must be
 	 * flushed at some rtnl-locked contexts (e.g. if down)
 	 */
-	if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+	bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_SETUP_TC, 0);
 }
 
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
@@ -764,10 +763,7 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
 			if (IS_MF(bp))
 				bnx2x_link_sync_notify(bp);
 
-			set_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state);
-
-			schedule_delayed_work(&bp->sp_rtnl_task, 0);
-
+			bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_TX_STOP, 0);
 			return;
 		}
 	case BNX2X_DCBX_STATE_TX_PAUSED:
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 84aecdf06f7a..95dc36543548 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -87,7 +87,6 @@
 	(IRO[156].base + ((vfId) * IRO[156].m1))
 #define CSTORM_VF_TO_PF_OFFSET(funcId) \
 	(IRO[150].base + ((funcId) * IRO[150].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
 #define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
 	(IRO[203].base + ((pfId) * IRO[203].m1))
 #define TSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[102].base)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index cf1df8b62e2c..46e2f18df2cb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -2848,7 +2848,7 @@ struct afex_stats {
 
 #define BCM_5710_FW_MAJOR_VERSION			7
 #define BCM_5710_FW_MINOR_VERSION			8
-#define BCM_5710_FW_REVISION_VERSION		17
+#define BCM_5710_FW_REVISION_VERSION		19
 #define BCM_5710_FW_ENGINEERING_VERSION		0
 #define BCM_5710_FW_COMPILE_FLAGS			1
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 7d4382286457..5e74599b05c7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -918,7 +918,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 	u16 start = 0, end = 0;
 	u8 cos;
 #endif
-	if (disable_int)
+	if (IS_PF(bp) && disable_int)
 		bnx2x_int_disable(bp);
 
 	bp->stats_state = STATS_STATE_DISABLED;
@@ -929,33 +929,41 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 
 	/* Indices */
 	/* Common */
-	BNX2X_ERR("def_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)  spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
-		  bp->def_idx, bp->def_att_idx, bp->attn_state,
-		  bp->spq_prod_idx, bp->stats_counter);
-	BNX2X_ERR("DSB: attn bits(0x%x)  ack(0x%x)  id(0x%x)  idx(0x%x)\n",
-		  bp->def_status_blk->atten_status_block.attn_bits,
-		  bp->def_status_blk->atten_status_block.attn_bits_ack,
-		  bp->def_status_blk->atten_status_block.status_block_id,
-		  bp->def_status_blk->atten_status_block.attn_bits_index);
-	BNX2X_ERR("     def (");
-	for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
-		pr_cont("0x%x%s",
-			bp->def_status_blk->sp_sb.index_values[i],
-			(i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
-
-	for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
-		*((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
-			i*sizeof(u32));
-
-	pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) pf_id(0x%x)  vnic_id(0x%x)  vf_id(0x%x)  vf_valid (0x%x) state(0x%x)\n",
-	       sp_sb_data.igu_sb_id,
-	       sp_sb_data.igu_seg_id,
-	       sp_sb_data.p_func.pf_id,
-	       sp_sb_data.p_func.vnic_id,
-	       sp_sb_data.p_func.vf_id,
-	       sp_sb_data.p_func.vf_valid,
-	       sp_sb_data.state);
+	if (IS_PF(bp)) {
+		struct host_sp_status_block *def_sb = bp->def_status_blk;
+		int data_size, cstorm_offset;
+
+		BNX2X_ERR("def_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)  spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
+			  bp->def_idx, bp->def_att_idx, bp->attn_state,
+			  bp->spq_prod_idx, bp->stats_counter);
+		BNX2X_ERR("DSB: attn bits(0x%x)  ack(0x%x)  id(0x%x)  idx(0x%x)\n",
+			  def_sb->atten_status_block.attn_bits,
+			  def_sb->atten_status_block.attn_bits_ack,
+			  def_sb->atten_status_block.status_block_id,
+			  def_sb->atten_status_block.attn_bits_index);
+		BNX2X_ERR("     def (");
+		for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
+			pr_cont("0x%x%s",
+				def_sb->sp_sb.index_values[i],
+				(i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
+
+		data_size = sizeof(struct hc_sp_status_block_data) /
+			    sizeof(u32);
+		cstorm_offset = CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func);
+		for (i = 0; i < data_size; i++)
+			*((u32 *)&sp_sb_data + i) =
+				REG_RD(bp, BAR_CSTRORM_INTMEM + cstorm_offset +
+					   i * sizeof(u32));
+
+		pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) pf_id(0x%x)  vnic_id(0x%x)  vf_id(0x%x)  vf_valid (0x%x) state(0x%x)\n",
+			sp_sb_data.igu_sb_id,
+			sp_sb_data.igu_seg_id,
+			sp_sb_data.p_func.pf_id,
+			sp_sb_data.p_func.vnic_id,
+			sp_sb_data.p_func.vf_id,
+			sp_sb_data.p_func.vf_valid,
+			sp_sb_data.state);
+	}
 
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
@@ -1013,6 +1021,11 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 			pr_cont("0x%x%s",
 			       fp->sb_index_values[j],
 			       (j == loop - 1) ? ")" : " ");
+
+		/* VF cannot access FW refelection for status block */
+		if (IS_VF(bp))
+			continue;
+
 		/* fw sb data */
 		data_size = CHIP_IS_E1x(bp) ?
 			sizeof(struct hc_status_block_data_e1x) :
@@ -1064,16 +1077,18 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 	}
 
 #ifdef BNX2X_STOP_ON_ERROR
-
-	/* event queue */
-	BNX2X_ERR("eq cons %x prod %x\n", bp->eq_cons, bp->eq_prod);
-	for (i = 0; i < NUM_EQ_DESC; i++) {
-		u32 *data = (u32 *)&bp->eq_ring[i].message.data;
-
-		BNX2X_ERR("event queue [%d]: header: opcode %d, error %d\n",
-			  i, bp->eq_ring[i].message.opcode,
-			  bp->eq_ring[i].message.error);
-		BNX2X_ERR("data: %x %x %x\n", data[0], data[1], data[2]);
+	if (IS_PF(bp)) {
+		/* event queue */
+		BNX2X_ERR("eq cons %x prod %x\n", bp->eq_cons, bp->eq_prod);
+		for (i = 0; i < NUM_EQ_DESC; i++) {
+			u32 *data = (u32 *)&bp->eq_ring[i].message.data;
+
+			BNX2X_ERR("event queue [%d]: header: opcode %d, error %d\n",
+				  i, bp->eq_ring[i].message.opcode,
+				  bp->eq_ring[i].message.error);
+			BNX2X_ERR("data: %x %x %x\n",
+				  data[0], data[1], data[2]);
+		}
 	}
 
 	/* Rings */
@@ -1140,8 +1155,10 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 		}
 	}
 #endif
-	bnx2x_fw_dump(bp);
-	bnx2x_mc_assert(bp);
+	if (IS_PF(bp)) {
+		bnx2x_fw_dump(bp);
+		bnx2x_mc_assert(bp);
+	}
 	BNX2X_ERR("end crash dump -----------------\n");
 }
 
@@ -1814,6 +1831,11 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
 		drv_cmd = BNX2X_Q_CMD_EMPTY;
 		break;
 
+	case (RAMROD_CMD_ID_ETH_TPA_UPDATE):
+		DP(BNX2X_MSG_SP, "got tpa update ramrod CID=%d\n", cid);
+		drv_cmd = BNX2X_Q_CMD_UPDATE_TPA;
+		break;
+
 	default:
 		BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
 			  command, fp->index);
@@ -3644,10 +3666,18 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 			cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
 				    HW_CID(bp, cid));
 
-	type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
-
-	type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
-		 SPE_HDR_FUNCTION_ID);
+	/* In some cases, type may already contain the func-id
+	 * mainly in SRIOV related use cases, so we add it here only
+	 * if it's not already set.
+	 */
+	if (!(cmd_type & SPE_HDR_FUNCTION_ID)) {
+		type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) &
+			SPE_HDR_CONN_TYPE;
+		type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
+			 SPE_HDR_FUNCTION_ID);
+	} else {
+		type = cmd_type;
+	}
 
 	spe->hdr.type = cpu_to_le16(type);
 
@@ -3878,10 +3908,7 @@ static void bnx2x_fan_failure(struct bnx2x *bp)
 	 * This is due to some boards consuming sufficient power when driver is
 	 * up to overheat if fan fails.
 	 */
-	smp_mb__before_clear_bit();
-	set_bit(BNX2X_SP_RTNL_FAN_FAILURE, &bp->sp_rtnl_state);
-	smp_mb__after_clear_bit();
-	schedule_delayed_work(&bp->sp_rtnl_task, 0);
+	bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_FAN_FAILURE, 0);
 }
 
 static void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
@@ -5221,9 +5248,9 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 			continue;
 
 		case EVENT_RING_OPCODE_STAT_QUERY:
-			DP(BNX2X_MSG_SP | BNX2X_MSG_STATS,
-			   "got statistics comp event %d\n",
-			   bp->stats_comp++);
+			DP_AND((BNX2X_MSG_SP | BNX2X_MSG_STATS),
+			       "got statistics comp event %d\n",
+			       bp->stats_comp++);
 			/* nothing to do with stats comp */
 			goto next_spqe;
 
@@ -5273,6 +5300,8 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 					break;
 
 			} else {
+				int cmd = BNX2X_SP_RTNL_AFEX_F_UPDATE;
+
 				DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
 				   "AFEX: ramrod completed FUNCTION_UPDATE\n");
 				f_obj->complete_cmd(bp, f_obj,
@@ -5282,12 +5311,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 				 * sp_rtnl task as all Queue SP operations
 				 * should run under rtnl_lock.
 				 */
-				smp_mb__before_clear_bit();
-				set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
-					&bp->sp_rtnl_state);
-				smp_mb__after_clear_bit();
-
-				schedule_delayed_work(&bp->sp_rtnl_task, 0);
+				bnx2x_schedule_sp_rtnl(bp, cmd, 0);
 			}
 
 			goto next_spqe;
@@ -6005,18 +6029,6 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
 {
 	int i;
 
-	if (IS_MF_SI(bp))
-		/*
-		 * In switch independent mode, the TSTORM needs to accept
-		 * packets that failed classification, since approximate match
-		 * mac addresses aren't written to NIG LLH
-		 */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
-	else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
-
 	/* Zero this manually as its initialization is
 	   currently missing in the initTool */
 	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
@@ -7989,19 +8001,25 @@ void bnx2x_free_mem(struct bnx2x *bp)
 
 int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
 {
-	if (!CHIP_IS_E1x(bp))
+	if (!CHIP_IS_E1x(bp)) {
 		/* size = the status block + ramrod buffers */
-		BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
-				sizeof(struct host_hc_status_block_e2));
-	else
-		BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb,
-				&bp->cnic_sb_mapping,
-				sizeof(struct
-				       host_hc_status_block_e1x));
+		bp->cnic_sb.e2_sb = BNX2X_PCI_ALLOC(&bp->cnic_sb_mapping,
+						    sizeof(struct host_hc_status_block_e2));
+		if (!bp->cnic_sb.e2_sb)
+			goto alloc_mem_err;
+	} else {
+		bp->cnic_sb.e1x_sb = BNX2X_PCI_ALLOC(&bp->cnic_sb_mapping,
+						     sizeof(struct host_hc_status_block_e1x));
+		if (!bp->cnic_sb.e1x_sb)
+			goto alloc_mem_err;
+	}
 
-	if (CONFIGURE_NIC_MODE(bp) && !bp->t2)
+	if (CONFIGURE_NIC_MODE(bp) && !bp->t2) {
 		/* allocate searcher T2 table, as it wasn't allocated before */
-		BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+		bp->t2 = BNX2X_PCI_ALLOC(&bp->t2_mapping, SRC_T2_SZ);
+		if (!bp->t2)
+			goto alloc_mem_err;
+	}
 
 	/* write address to which L5 should insert its values */
 	bp->cnic_eth_dev.addr_drv_info_to_mcp =
@@ -8022,15 +8040,22 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 {
 	int i, allocated, context_size;
 
-	if (!CONFIGURE_NIC_MODE(bp) && !bp->t2)
+	if (!CONFIGURE_NIC_MODE(bp) && !bp->t2) {
 		/* allocate searcher T2 table */
-		BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+		bp->t2 = BNX2X_PCI_ALLOC(&bp->t2_mapping, SRC_T2_SZ);
+		if (!bp->t2)
+			goto alloc_mem_err;
+	}
 
-	BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
-			sizeof(struct host_sp_status_block));
+	bp->def_status_blk = BNX2X_PCI_ALLOC(&bp->def_status_blk_mapping,
+					     sizeof(struct host_sp_status_block));
+	if (!bp->def_status_blk)
+		goto alloc_mem_err;
 
-	BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
-			sizeof(struct bnx2x_slowpath));
+	bp->slowpath = BNX2X_PCI_ALLOC(&bp->slowpath_mapping,
+				       sizeof(struct bnx2x_slowpath));
+	if (!bp->slowpath)
+		goto alloc_mem_err;
 
 	/* Allocate memory for CDU context:
 	 * This memory is allocated separately and not in the generic ILT
@@ -8050,12 +8075,16 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 	for (i = 0, allocated = 0; allocated < context_size; i++) {
 		bp->context[i].size = min(CDU_ILT_PAGE_SZ,
 					  (context_size - allocated));
-		BNX2X_PCI_ALLOC(bp->context[i].vcxt,
-				&bp->context[i].cxt_mapping,
-				bp->context[i].size);
+		bp->context[i].vcxt = BNX2X_PCI_ALLOC(&bp->context[i].cxt_mapping,
+						      bp->context[i].size);
+		if (!bp->context[i].vcxt)
+			goto alloc_mem_err;
 		allocated += bp->context[i].size;
 	}
-	BNX2X_ALLOC(bp->ilt->lines, sizeof(struct ilt_line) * ILT_MAX_LINES);
+	bp->ilt->lines = kcalloc(ILT_MAX_LINES, sizeof(struct ilt_line),
+				 GFP_KERNEL);
+	if (!bp->ilt->lines)
+		goto alloc_mem_err;
 
 	if (bnx2x_ilt_mem_op(bp, ILT_MEMOP_ALLOC))
 		goto alloc_mem_err;
@@ -8064,11 +8093,15 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 		goto alloc_mem_err;
 
 	/* Slow path ring */
-	BNX2X_PCI_ALLOC(bp->spq, &bp->spq_mapping, BCM_PAGE_SIZE);
+	bp->spq = BNX2X_PCI_ALLOC(&bp->spq_mapping, BCM_PAGE_SIZE);
+	if (!bp->spq)
+		goto alloc_mem_err;
 
 	/* EQ */
-	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
-			BCM_PAGE_SIZE * NUM_EQ_PAGES);
+	bp->eq_ring = BNX2X_PCI_ALLOC(&bp->eq_mapping,
+				      BCM_PAGE_SIZE * NUM_EQ_PAGES);
+	if (!bp->eq_ring)
+		goto alloc_mem_err;
 
 	return 0;
 
@@ -11771,6 +11804,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 
 	bp->disable_tpa = disable_tpa;
 	bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp);
+	/* Reduce memory usage in kdump environment by disabling TPA */
+	bp->disable_tpa |= reset_devices;
 
 	/* Set TPA flags */
 	if (bp->disable_tpa) {
@@ -11942,7 +11977,7 @@ static int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
 {
 	int mc_count = netdev_mc_count(bp->dev);
 	struct bnx2x_mcast_list_elem *mc_mac =
-		kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC);
+		kcalloc(mc_count, sizeof(*mc_mac), GFP_ATOMIC);
 	struct netdev_hw_addr *ha;
 
 	if (!mc_mac)
@@ -12064,11 +12099,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev)
 		return;
 	} else {
 		/* Schedule an SP task to handle rest of change */
-		DP(NETIF_MSG_IFUP, "Scheduling an Rx mode change\n");
-		smp_mb__before_clear_bit();
-		set_bit(BNX2X_SP_RTNL_RX_MODE, &bp->sp_rtnl_state);
-		smp_mb__after_clear_bit();
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+		bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_RX_MODE,
+				       NETIF_MSG_IFUP);
 	}
 }
 
@@ -12101,11 +12133,8 @@ void bnx2x_set_rx_mode_inner(struct bnx2x *bp)
 			/* configuring mcast to a vf involves sleeping (when we
 			 * wait for the pf's response).
 			 */
-			smp_mb__before_clear_bit();
-			set_bit(BNX2X_SP_RTNL_VFPF_MCAST,
-				&bp->sp_rtnl_state);
-			smp_mb__after_clear_bit();
-			schedule_delayed_work(&bp->sp_rtnl_task, 0);
+			bnx2x_schedule_sp_rtnl(bp,
+					       BNX2X_SP_RTNL_VFPF_MCAST, 0);
 		}
 	}
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 0fb6ff2ac8e3..31297266b743 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -2277,11 +2277,11 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
 			 data->header.rule_cnt, p->rx_accept_flags,
 			 p->tx_accept_flags);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 
 	/* Send a ramrod */
@@ -2982,11 +2982,11 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
 		raw->clear_pending(raw);
 		return 0;
 	} else {
-		/* No need for an explicit memory barrier here as long we would
-		 * need to ensure the ordering of writing to the SPQ element
+		/* No need for an explicit memory barrier here as long as we
+		 * ensure the ordering of writing to the SPQ element
 		 * and updating of the SPQ producer which involves a memory
-		 * read and we will have to put a full memory barrier there
-		 * (inside bnx2x_sp_post()).
+		 * read. If the memory read is removed we will have to put a
+		 * full memory barrier there (inside bnx2x_sp_post()).
 		 */
 
 		/* Send a ramrod */
@@ -3466,11 +3466,11 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
 		raw->clear_pending(raw);
 		return 0;
 	} else {
-		/* No need for an explicit memory barrier here as long we would
-		 * need to ensure the ordering of writing to the SPQ element
+		/* No need for an explicit memory barrier here as long as we
+		 * ensure the ordering of writing to the SPQ element
 		 * and updating of the SPQ producer which involves a memory
-		 * read and we will have to put a full memory barrier there
-		 * (inside bnx2x_sp_post()).
+		 * read. If the memory read is removed we will have to put a
+		 * full memory barrier there (inside bnx2x_sp_post()).
 		 */
 
 		/* Send a ramrod */
@@ -4091,11 +4091,11 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
 		data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
 	}
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 
 	/* Send a ramrod */
@@ -4158,16 +4158,6 @@ void bnx2x_init_rss_config_obj(struct bnx2x *bp,
 	rss_obj->config_rss = bnx2x_setup_rss;
 }
 
-int validate_vlan_mac(struct bnx2x *bp,
-		      struct bnx2x_vlan_mac_obj *vlan_mac)
-{
-	if (!vlan_mac->get_n_elements) {
-		BNX2X_ERR("vlan mac object was not intialized\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
 /********************** Queue state object ***********************************/
 
 /**
@@ -4587,13 +4577,12 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
 	/* Fill the ramrod data */
 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4615,13 +4604,12 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
 	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4659,13 +4647,12 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
 			 o->cids[cid_index], rdata->general.client_id,
 			 rdata->general.sp_client_id, rdata->general.cos);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4760,13 +4747,12 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp,
 	/* Fill the ramrod data */
 	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
 			     o->cids[cid_index], U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4813,11 +4799,62 @@ static inline int bnx2x_q_send_activate(struct bnx2x *bp,
 	return bnx2x_q_send_update(bp, params);
 }
 
+static void bnx2x_q_fill_update_tpa_data(struct bnx2x *bp,
+				struct bnx2x_queue_sp_obj *obj,
+				struct bnx2x_queue_update_tpa_params *params,
+				struct tpa_update_ramrod_data *data)
+{
+	data->client_id = obj->cl_id;
+	data->complete_on_both_clients = params->complete_on_both_clients;
+	data->dont_verify_rings_pause_thr_flg =
+		params->dont_verify_thr;
+	data->max_agg_size = cpu_to_le16(params->max_agg_sz);
+	data->max_sges_for_packet = params->max_sges_pkt;
+	data->max_tpa_queues = params->max_tpa_queues;
+	data->sge_buff_size = cpu_to_le16(params->sge_buff_sz);
+	data->sge_page_base_hi = cpu_to_le32(U64_HI(params->sge_map));
+	data->sge_page_base_lo = cpu_to_le32(U64_LO(params->sge_map));
+	data->sge_pause_thr_high = cpu_to_le16(params->sge_pause_thr_high);
+	data->sge_pause_thr_low = cpu_to_le16(params->sge_pause_thr_low);
+	data->tpa_mode = params->tpa_mode;
+	data->update_ipv4 = params->update_ipv4;
+	data->update_ipv6 = params->update_ipv6;
+}
+
 static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
 					struct bnx2x_queue_state_params *params)
 {
-	/* TODO: Not implemented yet. */
-	return -1;
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct tpa_update_ramrod_data *rdata =
+		(struct tpa_update_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_queue_update_tpa_params *update_tpa_params =
+		&params->params.update_tpa;
+	u16 type;
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_update_tpa_data(bp, o, update_tpa_params, rdata);
+
+	/* Add the function id inside the type, so that sp post function
+	 * doesn't automatically add the PF func-id, this is required
+	 * for operations done by PFs on behalf of their VFs
+	 */
+	type = ETH_CONNECTION_TYPE |
+		((o->func_id) << SPE_HDR_FUNCTION_ID_SHIFT);
+
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TPA_UPDATE,
+			     o->cids[BNX2X_PRIMARY_CID_INDEX],
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), type);
 }
 
 static inline int bnx2x_q_send_halt(struct bnx2x *bp,
@@ -5647,6 +5684,12 @@ static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
 	rdata->tx_switch_suspend = switch_update_params->suspend;
 	rdata->echo = SWITCH_UPDATE;
 
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
@@ -5674,11 +5717,11 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
 	rdata->allowed_priorities = afex_update_params->allowed_priorities;
 	rdata->echo = AFEX_UPDATE;
 
-	/*  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 	DP(BNX2X_MSG_SP,
 	   "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
@@ -5763,6 +5806,12 @@ static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
 		rdata->traffic_type_to_priority_cos[i] =
 			tx_start_params->traffic_type_to_priority_cos[i];
 
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 00d7f214a40a..80f6c790ed88 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -893,6 +893,24 @@ struct bnx2x_queue_update_params {
 	u8		cid_index;
 };
 
+struct bnx2x_queue_update_tpa_params {
+	dma_addr_t sge_map;
+	u8 update_ipv4;
+	u8 update_ipv6;
+	u8 max_tpa_queues;
+	u8 max_sges_pkt;
+	u8 complete_on_both_clients;
+	u8 dont_verify_thr;
+	u8 tpa_mode;
+	u8 _pad;
+
+	u16 sge_buff_sz;
+	u16 max_agg_sz;
+
+	u16 sge_pause_thr_low;
+	u16 sge_pause_thr_high;
+};
+
 struct rxq_pause_params {
 	u16		bd_th_lo;
 	u16		bd_th_hi;
@@ -987,6 +1005,7 @@ struct bnx2x_queue_state_params {
 	/* Params according to the current command */
 	union {
 		struct bnx2x_queue_update_params	update;
+		struct bnx2x_queue_update_tpa_params    update_tpa;
 		struct bnx2x_queue_setup_params		setup;
 		struct bnx2x_queue_init_params		init;
 		struct bnx2x_queue_setup_tx_only_params	tx_only;
@@ -1403,6 +1422,4 @@ int bnx2x_config_rss(struct bnx2x *bp,
 void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
 			     u8 *ind_table);
 
-int validate_vlan_mac(struct bnx2x *bp,
-		      struct bnx2x_vlan_mac_obj *vlan_mac);
 #endif /* BNX2X_SP_VERBS */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index e42f48df6e94..61e6f606d8a4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -102,6 +102,21 @@ static void bnx2x_vf_igu_ack_sb(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	mmiowb();
 	barrier();
 }
+
+static bool bnx2x_validate_vf_sp_objs(struct bnx2x *bp,
+				       struct bnx2x_virtf *vf,
+				       bool print_err)
+{
+	if (!bnx2x_leading_vfq(vf, sp_initialized)) {
+		if (print_err)
+			BNX2X_ERR("Slowpath objects not yet initialized!\n");
+		else
+			DP(BNX2X_MSG_IOV, "Slowpath objects not yet initialized!\n");
+		return false;
+	}
+	return true;
+}
+
 /* VFOP - VF slow-path operation support */
 
 #define BNX2X_VFOP_FILTER_ADD_CNT_MAX		0x10000
@@ -176,6 +191,11 @@ enum bnx2x_vfop_rss_state {
 	   BNX2X_VFOP_RSS_DONE
 };
 
+enum bnx2x_vfop_tpa_state {
+	   BNX2X_VFOP_TPA_CONFIG,
+	   BNX2X_VFOP_TPA_DONE
+};
+
 #define bnx2x_vfop_reset_wq(vf)	atomic_set(&vf->op_in_progress, 0)
 
 void bnx2x_vfop_qctor_dump_tx(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -716,7 +736,6 @@ static int bnx2x_vfop_mac_delall_cmd(struct bnx2x *bp,
 				     int qid, bool drv_only)
 {
 	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
-	int rc;
 
 	if (vfop) {
 		struct bnx2x_vfop_args_filters filters = {
@@ -736,9 +755,6 @@ static int bnx2x_vfop_mac_delall_cmd(struct bnx2x *bp,
 		bnx2x_vfop_mac_prep_ramrod(ramrod, &flags);
 
 		/* set object */
-		rc = validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, mac_obj));
-		if (rc)
-			return rc;
 		ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, mac_obj);
 
 		/* set extra args */
@@ -758,9 +774,12 @@ int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp,
 			    struct bnx2x_vfop_filters *macs,
 			    int qid, bool drv_only)
 {
-	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
-	int rc;
+	struct bnx2x_vfop *vfop;
+
+	if (!bnx2x_validate_vf_sp_objs(bp, vf, true))
+			return -EINVAL;
 
+	vfop  = bnx2x_vfop_add(bp, vf);
 	if (vfop) {
 		struct bnx2x_vfop_args_filters filters = {
 			.multi_filter = macs,
@@ -782,9 +801,6 @@ int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp,
 		bnx2x_vfop_mac_prep_ramrod(ramrod, &flags);
 
 		/* set object */
-		rc = validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, mac_obj));
-		if (rc)
-			return rc;
 		ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, mac_obj);
 
 		/* set extra args */
@@ -804,9 +820,12 @@ static int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp,
 				   struct bnx2x_vfop_cmd *cmd,
 				   int qid, u16 vid, bool add)
 {
-	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
-	int rc;
+	struct bnx2x_vfop *vfop;
 
+	if (!bnx2x_validate_vf_sp_objs(bp, vf, true))
+		return -EINVAL;
+
+	vfop  = bnx2x_vfop_add(bp, vf);
 	if (vfop) {
 		struct bnx2x_vfop_args_filters filters = {
 			.multi_filter = NULL, /* single command */
@@ -826,9 +845,6 @@ static int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp,
 		ramrod->user_req.u.vlan.vlan = vid;
 
 		/* set object */
-		rc = validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, vlan_obj));
-		if (rc)
-			return rc;
 		ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj);
 
 		/* set extra args */
@@ -848,7 +864,6 @@ static int bnx2x_vfop_vlan_delall_cmd(struct bnx2x *bp,
 			       int qid, bool drv_only)
 {
 	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
-	int rc;
 
 	if (vfop) {
 		struct bnx2x_vfop_args_filters filters = {
@@ -868,9 +883,6 @@ static int bnx2x_vfop_vlan_delall_cmd(struct bnx2x *bp,
 		bnx2x_vfop_vlan_mac_prep_ramrod(ramrod, &flags);
 
 		/* set object */
-		rc = validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, vlan_obj));
-		if (rc)
-			return rc;
 		ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj);
 
 		/* set extra args */
@@ -890,9 +902,12 @@ int bnx2x_vfop_vlan_list_cmd(struct bnx2x *bp,
 			     struct bnx2x_vfop_filters *vlans,
 			     int qid, bool drv_only)
 {
-	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
-	int rc;
+	struct bnx2x_vfop *vfop;
 
+	if (!bnx2x_validate_vf_sp_objs(bp, vf, true))
+		return -EINVAL;
+
+	vfop = bnx2x_vfop_add(bp, vf);
 	if (vfop) {
 		struct bnx2x_vfop_args_filters filters = {
 			.multi_filter = vlans,
@@ -911,9 +926,6 @@ int bnx2x_vfop_vlan_list_cmd(struct bnx2x *bp,
 		bnx2x_vfop_vlan_mac_prep_ramrod(ramrod, &flags);
 
 		/* set object */
-		rc = validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, vlan_obj));
-		if (rc)
-			return rc;
 		ramrod->vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj);
 
 		/* set extra args */
@@ -971,11 +983,8 @@ op_err:
 op_done:
 	case BNX2X_VFOP_QSETUP_DONE:
 		vf->cfg_flags |= VF_CFG_VLAN;
-		smp_mb__before_clear_bit();
-		set_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
-			&bp->sp_rtnl_state);
-		smp_mb__after_clear_bit();
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+		bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+				       BNX2X_MSG_IOV);
 		bnx2x_vfop_end(bp, vf, vfop);
 		return;
 	default:
@@ -1025,34 +1034,20 @@ static void bnx2x_vfop_qflr(struct bnx2x *bp, struct bnx2x_virtf *vf)
 		/* vlan-clear-all: driver-only, don't consume credit */
 		vfop->state = BNX2X_VFOP_QFLR_CLR_MAC;
 
-		if (!validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, vlan_obj))) {
-			/* the vlan_mac vfop will re-schedule us */
-			vfop->rc = bnx2x_vfop_vlan_delall_cmd(bp, vf, &cmd,
-							      qid, true);
-			if (vfop->rc)
-				goto op_err;
-			return;
-
-		} else {
-			/* need to reschedule ourselves */
-			bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
-		}
+		/* the vlan_mac vfop will re-schedule us */
+		vfop->rc = bnx2x_vfop_vlan_delall_cmd(bp, vf, &cmd, qid, true);
+		if (vfop->rc)
+			goto op_err;
+		return;
 
 	case BNX2X_VFOP_QFLR_CLR_MAC:
 		/* mac-clear-all: driver only consume credit */
 		vfop->state = BNX2X_VFOP_QFLR_TERMINATE;
-		if (!validate_vlan_mac(bp, &bnx2x_vfq(vf, qid, mac_obj))) {
-			/* the vlan_mac vfop will re-schedule us */
-			vfop->rc = bnx2x_vfop_mac_delall_cmd(bp, vf, &cmd,
-							     qid, true);
-			if (vfop->rc)
-				goto op_err;
-			return;
-
-		} else {
-			/* need to reschedule ourselves */
-			bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
-		}
+		/* the vlan_mac vfop will re-schedule us */
+		vfop->rc = bnx2x_vfop_mac_delall_cmd(bp, vf, &cmd, qid, true);
+		if (vfop->rc)
+			goto op_err;
+		return;
 
 	case BNX2X_VFOP_QFLR_TERMINATE:
 		qstate = &vfop->op_p->qctor.qstate;
@@ -1095,8 +1090,13 @@ static int bnx2x_vfop_qflr_cmd(struct bnx2x *bp,
 
 	if (vfop) {
 		vfop->args.qx.qid = qid;
-		bnx2x_vfop_opset(BNX2X_VFOP_QFLR_CLR_VLAN,
-				 bnx2x_vfop_qflr, cmd->done);
+		if ((qid == LEADING_IDX) &&
+		    bnx2x_validate_vf_sp_objs(bp, vf, false))
+			bnx2x_vfop_opset(BNX2X_VFOP_QFLR_CLR_VLAN,
+					 bnx2x_vfop_qflr, cmd->done);
+		else
+			bnx2x_vfop_opset(BNX2X_VFOP_QFLR_TERMINATE,
+					 bnx2x_vfop_qflr, cmd->done);
 		return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_qflr,
 					     cmd->block);
 	}
@@ -1310,7 +1310,10 @@ static void bnx2x_vfop_qdown(struct bnx2x *bp, struct bnx2x_virtf *vf)
 	switch (state) {
 	case BNX2X_VFOP_QTEARDOWN_RXMODE:
 		/* Drop all */
-		vfop->state = BNX2X_VFOP_QTEARDOWN_CLR_VLAN;
+		if (bnx2x_validate_vf_sp_objs(bp, vf, true))
+			vfop->state =  BNX2X_VFOP_QTEARDOWN_CLR_VLAN;
+		else
+			vfop->state = BNX2X_VFOP_QTEARDOWN_QDTOR;
 		vfop->rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd, qid, 0);
 		if (vfop->rc)
 			goto op_err;
@@ -2117,7 +2120,9 @@ int bnx2x_iov_alloc_mem(struct bnx2x *bp)
 		cxt->size = min_t(size_t, tot_size, CDU_ILT_PAGE_SZ);
 
 		if (cxt->size) {
-			BNX2X_PCI_ALLOC(cxt->addr, &cxt->mapping, cxt->size);
+			cxt->addr = BNX2X_PCI_ALLOC(&cxt->mapping, cxt->size);
+			if (!cxt->addr)
+				goto alloc_mem_err;
 		} else {
 			cxt->addr = NULL;
 			cxt->mapping = 0;
@@ -2127,20 +2132,28 @@ int bnx2x_iov_alloc_mem(struct bnx2x *bp)
 
 	/* allocate vfs ramrods dma memory - client_init and set_mac */
 	tot_size = BNX2X_NR_VIRTFN(bp) * sizeof(struct bnx2x_vf_sp);
-	BNX2X_PCI_ALLOC(BP_VFDB(bp)->sp_dma.addr, &BP_VFDB(bp)->sp_dma.mapping,
-			tot_size);
+	BP_VFDB(bp)->sp_dma.addr = BNX2X_PCI_ALLOC(&BP_VFDB(bp)->sp_dma.mapping,
+						   tot_size);
+	if (!BP_VFDB(bp)->sp_dma.addr)
+		goto alloc_mem_err;
 	BP_VFDB(bp)->sp_dma.size = tot_size;
 
 	/* allocate mailboxes */
 	tot_size = BNX2X_NR_VIRTFN(bp) * MBX_MSG_ALIGNED_SIZE;
-	BNX2X_PCI_ALLOC(BP_VF_MBX_DMA(bp)->addr, &BP_VF_MBX_DMA(bp)->mapping,
-			tot_size);
+	BP_VF_MBX_DMA(bp)->addr = BNX2X_PCI_ALLOC(&BP_VF_MBX_DMA(bp)->mapping,
+						  tot_size);
+	if (!BP_VF_MBX_DMA(bp)->addr)
+		goto alloc_mem_err;
+
 	BP_VF_MBX_DMA(bp)->size = tot_size;
 
 	/* allocate local bulletin boards */
 	tot_size = BNX2X_NR_VIRTFN(bp) * BULLETIN_CONTENT_SIZE;
-	BNX2X_PCI_ALLOC(BP_VF_BULLETIN_DMA(bp)->addr,
-			&BP_VF_BULLETIN_DMA(bp)->mapping, tot_size);
+	BP_VF_BULLETIN_DMA(bp)->addr = BNX2X_PCI_ALLOC(&BP_VF_BULLETIN_DMA(bp)->mapping,
+						       tot_size);
+	if (!BP_VF_BULLETIN_DMA(bp)->addr)
+		goto alloc_mem_err;
+
 	BP_VF_BULLETIN_DMA(bp)->size = tot_size;
 
 	return 0;
@@ -2166,6 +2179,9 @@ static void bnx2x_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
 			     bnx2x_vf_sp_map(bp, vf, q_data),
 			     q_type);
 
+	/* sp indication is set only when vlan/mac/etc. are initialized */
+	q->sp_initialized = false;
+
 	DP(BNX2X_MSG_IOV,
 	   "initialized vf %d's queue object. func id set to %d. cid set to 0x%x\n",
 	   vf->abs_vfid, q->sp_obj.func_id, q->cid);
@@ -2527,10 +2543,10 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
 	first_queue_query_index = BNX2X_FIRST_QUEUE_QUERY_IDX -
 		(is_fcoe ? 0 : 1);
 
-	DP(BNX2X_MSG_IOV,
-	   "BNX2X_NUM_ETH_QUEUES %d, is_fcoe %d, first_queue_query_index %d => determined the last non virtual statistics query index is %d. Will add queries on top of that\n",
-	   BNX2X_NUM_ETH_QUEUES(bp), is_fcoe, first_queue_query_index,
-	   first_queue_query_index + num_queues_req);
+	DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+	       "BNX2X_NUM_ETH_QUEUES %d, is_fcoe %d, first_queue_query_index %d => determined the last non virtual statistics query index is %d. Will add queries on top of that\n",
+	       BNX2X_NUM_ETH_QUEUES(bp), is_fcoe, first_queue_query_index,
+	       first_queue_query_index + num_queues_req);
 
 	cur_data_offset = bp->fw_stats_data_mapping +
 		offsetof(struct bnx2x_fw_stats_data, queue_stats) +
@@ -2544,9 +2560,9 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
 		struct bnx2x_virtf *vf = BP_VF(bp, i);
 
 		if (vf->state != VF_ENABLED) {
-			DP(BNX2X_MSG_IOV,
-			   "vf %d not enabled so no stats for it\n",
-			   vf->abs_vfid);
+			DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+			       "vf %d not enabled so no stats for it\n",
+			       vf->abs_vfid);
 			continue;
 		}
 
@@ -2597,7 +2613,8 @@ void bnx2x_iov_sp_task(struct bnx2x *bp)
 	/* Iterate over all VFs and invoke state transition for VFs with
 	 * 'in-progress' slow-path operations
 	 */
-	DP(BNX2X_MSG_IOV, "searching for pending vf operations\n");
+	DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_SP),
+	       "searching for pending vf operations\n");
 	for_each_vf(bp, i) {
 		struct bnx2x_virtf *vf = BP_VF(bp, i);
 
@@ -3046,6 +3063,83 @@ int bnx2x_vfop_rss_cmd(struct bnx2x *bp,
 	return -ENOMEM;
 }
 
+/* VFOP tpa update, send update on all queues */
+static void bnx2x_vfop_tpa(struct bnx2x *bp, struct bnx2x_virtf *vf)
+{
+	struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf);
+	struct bnx2x_vfop_args_tpa *tpa_args = &vfop->args.tpa;
+	enum bnx2x_vfop_tpa_state state = vfop->state;
+
+	bnx2x_vfop_reset_wq(vf);
+
+	if (vfop->rc < 0)
+		goto op_err;
+
+	DP(BNX2X_MSG_IOV, "vf[%d:%d] STATE: %d\n",
+	   vf->abs_vfid, tpa_args->qid,
+	   state);
+
+	switch (state) {
+	case BNX2X_VFOP_TPA_CONFIG:
+
+		if (tpa_args->qid < vf_rxq_count(vf)) {
+			struct bnx2x_queue_state_params *qstate =
+				&vf->op_params.qstate;
+
+			qstate->q_obj = &bnx2x_vfq(vf, tpa_args->qid, sp_obj);
+
+			/* The only thing that changes for the ramrod params
+			 * between calls is the sge_map
+			 */
+			qstate->params.update_tpa.sge_map =
+				tpa_args->sge_map[tpa_args->qid];
+
+			DP(BNX2X_MSG_IOV, "sge_addr[%d] %08x:%08x\n",
+			   tpa_args->qid,
+			   U64_HI(qstate->params.update_tpa.sge_map),
+			   U64_LO(qstate->params.update_tpa.sge_map));
+			qstate->cmd = BNX2X_Q_CMD_UPDATE_TPA;
+			vfop->rc = bnx2x_queue_state_change(bp, qstate);
+
+			tpa_args->qid++;
+			bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
+		}
+		vfop->state = BNX2X_VFOP_TPA_DONE;
+		vfop->rc = 0;
+		bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
+op_err:
+		BNX2X_ERR("TPA update error: rc %d\n", vfop->rc);
+op_done:
+	case BNX2X_VFOP_TPA_DONE:
+		bnx2x_vfop_end(bp, vf, vfop);
+		return;
+	default:
+		bnx2x_vfop_default(state);
+	}
+op_pending:
+	return;
+}
+
+int bnx2x_vfop_tpa_cmd(struct bnx2x *bp,
+			struct bnx2x_virtf *vf,
+			struct bnx2x_vfop_cmd *cmd,
+			struct vfpf_tpa_tlv *tpa_tlv)
+{
+	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
+
+	if (vfop) {
+		vfop->args.qx.qid = 0; /* loop */
+		memcpy(&vfop->args.tpa.sge_map,
+		       tpa_tlv->tpa_client_info.sge_addr,
+		       sizeof(vfop->args.tpa.sge_map));
+		bnx2x_vfop_opset(BNX2X_VFOP_TPA_CONFIG,
+				 bnx2x_vfop_tpa, cmd->done);
+		return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_tpa,
+					     cmd->block);
+	}
+	return -ENOMEM;
+}
+
 /* VF release ~ VF close + VF release-resources
  * Release is the ultimate SW shutdown and is called whenever an
  * irrecoverable error is encountered.
@@ -3074,16 +3168,6 @@ static inline void bnx2x_vf_get_sbdf(struct bnx2x *bp,
 	*sbdf = vf->devfn | (vf->bus << 8);
 }
 
-static inline void bnx2x_vf_get_bars(struct bnx2x *bp, struct bnx2x_virtf *vf,
-		       struct bnx2x_vf_bar_info *bar_info)
-{
-	int n;
-
-	bar_info->nr_bars = bp->vfdb->sriov.nres;
-	for (n = 0; n < bar_info->nr_bars; n++)
-		bar_info->bars[n] = vf->bars[n];
-}
-
 void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
 			      enum channel_tlvs tlv)
 {
@@ -3405,13 +3489,13 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
 	ivi->spoofchk = 1; /*always enabled */
 	if (vf->state == VF_ENABLED) {
 		/* mac and vlan are in vlan_mac objects */
-		if (validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj)))
+		if (bnx2x_validate_vf_sp_objs(bp, vf, false)) {
 			mac_obj->get_n_elements(bp, mac_obj, 1, (u8 *)&ivi->mac,
 						0, ETH_ALEN);
-		if (validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, vlan_obj)))
 			vlan_obj->get_n_elements(bp, vlan_obj, 1,
 						 (u8 *)&ivi->vlan, 0,
 						 VLAN_HLEN);
+		}
 	} else {
 		/* mac */
 		if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
@@ -3485,17 +3569,17 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 	    q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
 		/* configure the mac in device on this vf's queue */
 		unsigned long ramrod_flags = 0;
-		struct bnx2x_vlan_mac_obj *mac_obj =
-			&bnx2x_leading_vfq(vf, mac_obj);
+		struct bnx2x_vlan_mac_obj *mac_obj;
 
-		rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-		if (rc)
-			return rc;
+		/* User should be able to see failure reason in system logs */
+		if (!bnx2x_validate_vf_sp_objs(bp, vf, true))
+			return -EINVAL;
 
 		/* must lock vfpf channel to protect against vf flows */
 		bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
 
 		/* remove existing eth macs */
+		mac_obj = &bnx2x_leading_vfq(vf, mac_obj);
 		rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_ETH_MAC, true);
 		if (rc) {
 			BNX2X_ERR("failed to delete eth macs\n");
@@ -3569,17 +3653,16 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 	    BNX2X_Q_LOGICAL_STATE_ACTIVE)
 		return rc;
 
-	/* configure the vlan in device on this vf's queue */
-	vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
-	rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-	if (rc)
-		return rc;
+	/* User should be able to see error in system logs */
+	if (!bnx2x_validate_vf_sp_objs(bp, vf, true))
+		return -EINVAL;
 
 	/* must lock vfpf channel to protect against vf flows */
 	bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
 	/* remove existing vlans */
 	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+	vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
 	rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
 				  &ramrod_flags);
 	if (rc) {
@@ -3736,13 +3819,9 @@ void bnx2x_timer_sriov(struct bnx2x *bp)
 	bnx2x_sample_bulletin(bp);
 
 	/* if channel is down we need to self destruct */
-	if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN) {
-		smp_mb__before_clear_bit();
-		set_bit(BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
-			&bp->sp_rtnl_state);
-		smp_mb__after_clear_bit();
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
-	}
+	if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN)
+		bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
+				       BNX2X_MSG_IOV);
 }
 
 void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
@@ -3756,12 +3835,16 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 	mutex_init(&bp->vf2pf_mutex);
 
 	/* allocate vf2pf mailbox for vf to pf channel */
-	BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping,
-			sizeof(struct bnx2x_vf_mbx_msg));
+	bp->vf2pf_mbox = BNX2X_PCI_ALLOC(&bp->vf2pf_mbox_mapping,
+					 sizeof(struct bnx2x_vf_mbx_msg));
+	if (!bp->vf2pf_mbox)
+		goto alloc_mem_err;
 
 	/* allocate pf 2 vf bulletin board */
-	BNX2X_PCI_ALLOC(bp->pf2vf_bulletin, &bp->pf2vf_bulletin_mapping,
-			sizeof(union pf_vf_bulletin));
+	bp->pf2vf_bulletin = BNX2X_PCI_ALLOC(&bp->pf2vf_bulletin_mapping,
+					     sizeof(union pf_vf_bulletin));
+	if (!bp->pf2vf_bulletin)
+		goto alloc_mem_err;
 
 	return 0;
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index d9fcca1b5a9d..b1dc751c6175 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -83,6 +83,7 @@ struct bnx2x_vf_queue {
 	u16 index;
 	u16 sb_idx;
 	bool is_leading;
+	bool sp_initialized;
 };
 
 /* struct bnx2x_vfop_qctor_params - prepare queue construction parameters:
@@ -100,6 +101,7 @@ union bnx2x_vfop_params {
 	struct bnx2x_mcast_ramrod_params	mcast;
 	struct bnx2x_config_rss_params		rss;
 	struct bnx2x_vfop_qctor_params		qctor;
+	struct bnx2x_queue_state_params		qstate;
 };
 
 /* forward */
@@ -166,6 +168,11 @@ struct bnx2x_vfop_args_filters {
 	atomic_t *credit;	/* non NULL means 'don't consume credit' */
 };
 
+struct bnx2x_vfop_args_tpa {
+	int	   qid;
+	dma_addr_t sge_map[PFVF_MAX_QUEUES_PER_VF];
+};
+
 union bnx2x_vfop_args {
 	struct bnx2x_vfop_args_mcast	mc_list;
 	struct bnx2x_vfop_args_qctor	qctor;
@@ -173,6 +180,7 @@ union bnx2x_vfop_args {
 	struct bnx2x_vfop_args_defvlan	defvlan;
 	struct bnx2x_vfop_args_qx	qx;
 	struct bnx2x_vfop_args_filters	filters;
+	struct bnx2x_vfop_args_tpa	tpa;
 };
 
 struct bnx2x_vfop {
@@ -704,6 +712,11 @@ int bnx2x_vfop_rss_cmd(struct bnx2x *bp,
 		       struct bnx2x_virtf *vf,
 		       struct bnx2x_vfop_cmd *cmd);
 
+int bnx2x_vfop_tpa_cmd(struct bnx2x *bp,
+		       struct bnx2x_virtf *vf,
+		       struct bnx2x_vfop_cmd *cmd,
+		       struct vfpf_tpa_tlv *tpa_tlv);
+
 /* VF release ~ VF close + VF release-resources
  *
  * Release is the ultimate SW shutdown and is called whenever an
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 3fa6c2a2a5a9..1117ed7776b6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -548,6 +548,7 @@ static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
 
 	vf->leading_rss = cl_id;
 	q->is_leading = true;
+	q->sp_initialized = true;
 }
 
 /* ask the pf to open a queue for the vf */
@@ -1159,7 +1160,8 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	resp->pfdev_info.db_size = bp->db_size;
 	resp->pfdev_info.indices_per_sb = HC_SB_MAX_INDICES_E2;
 	resp->pfdev_info.pf_cap = (PFVF_CAP_RSS |
-				   /* PFVF_CAP_DHC |*/ PFVF_CAP_TPA);
+				   PFVF_CAP_TPA |
+				   PFVF_CAP_TPA_UPDATE);
 	bnx2x_fill_fw_str(bp, resp->pfdev_info.fw_ver,
 			  sizeof(resp->pfdev_info.fw_ver));
 
@@ -1694,16 +1696,12 @@ static int bnx2x_vfop_mbx_qfilters_cmd(struct bnx2x *bp,
 	return -ENOMEM;
 }
 
-static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
-				       struct bnx2x_virtf *vf,
-				       struct bnx2x_vf_mbx *mbx)
+static int bnx2x_filters_validate_mac(struct bnx2x *bp,
+				      struct bnx2x_virtf *vf,
+				      struct vfpf_set_q_filters_tlv *filters)
 {
-	struct vfpf_set_q_filters_tlv *filters = &mbx->msg->req.set_q_filters;
 	struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vf->index);
-	struct bnx2x_vfop_cmd cmd = {
-		.done = bnx2x_vf_mbx_resp,
-		.block = false,
-	};
+	int rc = 0;
 
 	/* if a mac was already set for this VF via the set vf mac ndo, we only
 	 * accept mac configurations of that mac. Why accept them at all?
@@ -1716,6 +1714,7 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
 			BNX2X_ERR("VF[%d] requested the addition of multiple macs after set_vf_mac ndo was called\n",
 				  vf->abs_vfid);
 			vf->op_rc = -EPERM;
+			rc = -EPERM;
 			goto response;
 		}
 
@@ -1726,9 +1725,22 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
 				  vf->abs_vfid);
 
 			vf->op_rc = -EPERM;
+			rc = -EPERM;
 			goto response;
 		}
 	}
+
+response:
+	return rc;
+}
+
+static int bnx2x_filters_validate_vlan(struct bnx2x *bp,
+				       struct bnx2x_virtf *vf,
+				       struct vfpf_set_q_filters_tlv *filters)
+{
+	struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vf->index);
+	int rc = 0;
+
 	/* if vlan was set by hypervisor we don't allow guest to config vlan */
 	if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
 		int i;
@@ -1740,13 +1752,36 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
 				BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
 					  vf->abs_vfid);
 				vf->op_rc = -EPERM;
+				rc = -EPERM;
 				goto response;
 			}
 		}
 	}
 
 	/* verify vf_qid */
-	if (filters->vf_qid > vf_rxq_count(vf))
+	if (filters->vf_qid > vf_rxq_count(vf)) {
+		rc = -EPERM;
+		goto response;
+	}
+
+response:
+	return rc;
+}
+
+static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
+				       struct bnx2x_virtf *vf,
+				       struct bnx2x_vf_mbx *mbx)
+{
+	struct vfpf_set_q_filters_tlv *filters = &mbx->msg->req.set_q_filters;
+	struct bnx2x_vfop_cmd cmd = {
+		.done = bnx2x_vf_mbx_resp,
+		.block = false,
+	};
+
+	if (bnx2x_filters_validate_mac(bp, vf, filters))
+		goto response;
+
+	if (bnx2x_filters_validate_vlan(bp, vf, filters))
 		goto response;
 
 	DP(BNX2X_MSG_IOV, "VF[%d] Q_FILTERS: queue[%d]\n",
@@ -1877,6 +1912,75 @@ mbx_resp:
 		bnx2x_vf_mbx_resp(bp, vf);
 }
 
+static int bnx2x_validate_tpa_params(struct bnx2x *bp,
+				       struct vfpf_tpa_tlv *tpa_tlv)
+{
+	int rc = 0;
+
+	if (tpa_tlv->tpa_client_info.max_sges_for_packet >
+	    U_ETH_MAX_SGES_FOR_PACKET) {
+		rc = -EINVAL;
+		BNX2X_ERR("TPA update: max_sges received %d, max is %d\n",
+			  tpa_tlv->tpa_client_info.max_sges_for_packet,
+			  U_ETH_MAX_SGES_FOR_PACKET);
+	}
+
+	if (tpa_tlv->tpa_client_info.max_tpa_queues > MAX_AGG_QS(bp)) {
+		rc = -EINVAL;
+		BNX2X_ERR("TPA update: max_tpa_queues received %d, max is %d\n",
+			  tpa_tlv->tpa_client_info.max_tpa_queues,
+			  MAX_AGG_QS(bp));
+	}
+
+	return rc;
+}
+
+static void bnx2x_vf_mbx_update_tpa(struct bnx2x *bp, struct bnx2x_virtf *vf,
+				    struct bnx2x_vf_mbx *mbx)
+{
+	struct bnx2x_vfop_cmd cmd = {
+		.done = bnx2x_vf_mbx_resp,
+		.block = false,
+	};
+	struct bnx2x_queue_update_tpa_params *vf_op_params =
+		&vf->op_params.qstate.params.update_tpa;
+	struct vfpf_tpa_tlv *tpa_tlv = &mbx->msg->req.update_tpa;
+
+	memset(vf_op_params, 0, sizeof(*vf_op_params));
+
+	if (bnx2x_validate_tpa_params(bp, tpa_tlv))
+		goto mbx_resp;
+
+	vf_op_params->complete_on_both_clients =
+		tpa_tlv->tpa_client_info.complete_on_both_clients;
+	vf_op_params->dont_verify_thr =
+		tpa_tlv->tpa_client_info.dont_verify_thr;
+	vf_op_params->max_agg_sz =
+		tpa_tlv->tpa_client_info.max_agg_size;
+	vf_op_params->max_sges_pkt =
+		tpa_tlv->tpa_client_info.max_sges_for_packet;
+	vf_op_params->max_tpa_queues =
+		tpa_tlv->tpa_client_info.max_tpa_queues;
+	vf_op_params->sge_buff_sz =
+		tpa_tlv->tpa_client_info.sge_buff_size;
+	vf_op_params->sge_pause_thr_high =
+		tpa_tlv->tpa_client_info.sge_pause_thr_high;
+	vf_op_params->sge_pause_thr_low =
+		tpa_tlv->tpa_client_info.sge_pause_thr_low;
+	vf_op_params->tpa_mode =
+		tpa_tlv->tpa_client_info.tpa_mode;
+	vf_op_params->update_ipv4 =
+		tpa_tlv->tpa_client_info.update_ipv4;
+	vf_op_params->update_ipv6 =
+		tpa_tlv->tpa_client_info.update_ipv6;
+
+	vf->op_rc = bnx2x_vfop_tpa_cmd(bp, vf, &cmd, tpa_tlv);
+
+mbx_resp:
+	if (vf->op_rc)
+		bnx2x_vf_mbx_resp(bp, vf);
+}
+
 /* dispatch request */
 static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
 				  struct bnx2x_vf_mbx *mbx)
@@ -1916,6 +2020,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
 		case CHANNEL_TLV_UPDATE_RSS:
 			bnx2x_vf_mbx_update_rss(bp, vf, mbx);
 			return;
+		case CHANNEL_TLV_UPDATE_TPA:
+			bnx2x_vf_mbx_update_tpa(bp, vf, mbx);
+			return;
 		}
 
 	} else {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index 208568bc7a71..c922b81170e5 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -162,6 +162,7 @@ struct pfvf_acquire_resp_tlv {
 #define PFVF_CAP_RSS		0x00000001
 #define PFVF_CAP_DHC		0x00000002
 #define PFVF_CAP_TPA		0x00000004
+#define PFVF_CAP_TPA_UPDATE	0x00000008
 		char fw_ver[32];
 		u16 db_size;
 		u8  indices_per_sb;
@@ -303,6 +304,25 @@ struct vfpf_set_q_filters_tlv {
 	u32 rx_mask;	/* see mask constants at the top of the file */
 };
 
+struct vfpf_tpa_tlv {
+	struct vfpf_first_tlv	first_tlv;
+
+	struct vf_pf_tpa_client_info {
+		aligned_u64 sge_addr[PFVF_MAX_QUEUES_PER_VF];
+		u8 update_ipv4;
+		u8 update_ipv6;
+		u8 max_tpa_queues;
+		u8 max_sges_for_packet;
+		u8 complete_on_both_clients;
+		u8 dont_verify_thr;
+		u8 tpa_mode;
+		u16 sge_buff_size;
+		u16 max_agg_size;
+		u16 sge_pause_thr_low;
+		u16 sge_pause_thr_high;
+	} tpa_client_info;
+};
+
 /* close VF (disable VF) */
 struct vfpf_close_tlv {
 	struct vfpf_first_tlv   first_tlv;
@@ -331,6 +351,7 @@ union vfpf_tlvs {
 	struct vfpf_set_q_filters_tlv	set_q_filters;
 	struct vfpf_release_tlv		release;
 	struct vfpf_rss_tlv		update_rss;
+	struct vfpf_tpa_tlv		update_tpa;
 	struct channel_list_end_tlv	list_end;
 	struct tlv_buffer_size		tlv_buf_size;
 };
@@ -405,6 +426,7 @@ enum channel_tlvs {
 	CHANNEL_TLV_PF_SET_VLAN,
 	CHANNEL_TLV_UPDATE_RSS,
 	CHANNEL_TLV_PHYS_PORT_ID,
+	CHANNEL_TLV_UPDATE_TPA,
 	CHANNEL_TLV_MAX
 };
 
diff --git a/drivers/net/ethernet/broadcom/genet/Makefile b/drivers/net/ethernet/broadcom/genet/Makefile
new file mode 100644
index 000000000000..31f55a90a197
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/genet/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BCMGENET) += genet.o
+genet-objs := bcmgenet.o bcmmii.o
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
new file mode 100644
index 000000000000..72ce6e8115fa
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -0,0 +1,2578 @@
+/*
+ * Broadcom GENET (Gigabit Ethernet) controller driver
+ *
+ * Copyright (c) 2014 Broadcom 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.
+ *
+ * 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 pr_fmt(fmt)				"bcmgenet: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/if_ether.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <net/arp.h>
+
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/phy.h>
+
+#include <asm/unaligned.h>
+
+#include "bcmgenet.h"
+
+/* Maximum number of hardware queues, downsized if needed */
+#define GENET_MAX_MQ_CNT	4
+
+/* Default highest priority queue for multi queue support */
+#define GENET_Q0_PRIORITY	0
+
+#define GENET_DEFAULT_BD_CNT	\
+	(TOTAL_DESC - priv->hw_params->tx_queues * priv->hw_params->bds_cnt)
+
+#define RX_BUF_LENGTH		2048
+#define SKB_ALIGNMENT		32
+
+/* Tx/Rx DMA register offset, skip 256 descriptors */
+#define WORDS_PER_BD(p)		(p->hw_params->words_per_bd)
+#define DMA_DESC_SIZE		(WORDS_PER_BD(priv) * sizeof(u32))
+
+#define GENET_TDMA_REG_OFF	(priv->hw_params->tdma_offset + \
+				TOTAL_DESC * DMA_DESC_SIZE)
+
+#define GENET_RDMA_REG_OFF	(priv->hw_params->rdma_offset + \
+				TOTAL_DESC * DMA_DESC_SIZE)
+
+static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
+						void __iomem *d, u32 value)
+{
+	__raw_writel(value, d + DMA_DESC_LENGTH_STATUS);
+}
+
+static inline u32 dmadesc_get_length_status(struct bcmgenet_priv *priv,
+						void __iomem *d)
+{
+	return __raw_readl(d + DMA_DESC_LENGTH_STATUS);
+}
+
+static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,
+				    void __iomem *d,
+				    dma_addr_t addr)
+{
+	__raw_writel(lower_32_bits(addr), d + DMA_DESC_ADDRESS_LO);
+
+	/* Register writes to GISB bus can take couple hundred nanoseconds
+	 * and are done for each packet, save these expensive writes unless
+	 * the platform is explicitely configured for 64-bits/LPAE.
+	 */
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	if (priv->hw_params->flags & GENET_HAS_40BITS)
+		__raw_writel(upper_32_bits(addr), d + DMA_DESC_ADDRESS_HI);
+#endif
+}
+
+/* Combined address + length/status setter */
+static inline void dmadesc_set(struct bcmgenet_priv *priv,
+				void __iomem *d, dma_addr_t addr, u32 val)
+{
+	dmadesc_set_length_status(priv, d, val);
+	dmadesc_set_addr(priv, d, addr);
+}
+
+static inline dma_addr_t dmadesc_get_addr(struct bcmgenet_priv *priv,
+					  void __iomem *d)
+{
+	dma_addr_t addr;
+
+	addr = __raw_readl(d + DMA_DESC_ADDRESS_LO);
+
+	/* Register writes to GISB bus can take couple hundred nanoseconds
+	 * and are done for each packet, save these expensive writes unless
+	 * the platform is explicitely configured for 64-bits/LPAE.
+	 */
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	if (priv->hw_params->flags & GENET_HAS_40BITS)
+		addr |= (u64)__raw_readl(d + DMA_DESC_ADDRESS_HI) << 32;
+#endif
+	return addr;
+}
+
+#define GENET_VER_FMT	"%1d.%1d EPHY: 0x%04x"
+
+#define GENET_MSG_DEFAULT	(NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+				NETIF_MSG_LINK)
+
+static inline u32 bcmgenet_rbuf_ctrl_get(struct bcmgenet_priv *priv)
+{
+	if (GENET_IS_V1(priv))
+		return bcmgenet_rbuf_readl(priv, RBUF_FLUSH_CTRL_V1);
+	else
+		return bcmgenet_sys_readl(priv, SYS_RBUF_FLUSH_CTRL);
+}
+
+static inline void bcmgenet_rbuf_ctrl_set(struct bcmgenet_priv *priv, u32 val)
+{
+	if (GENET_IS_V1(priv))
+		bcmgenet_rbuf_writel(priv, val, RBUF_FLUSH_CTRL_V1);
+	else
+		bcmgenet_sys_writel(priv, val, SYS_RBUF_FLUSH_CTRL);
+}
+
+/* These macros are defined to deal with register map change
+ * between GENET1.1 and GENET2. Only those currently being used
+ * by driver are defined.
+ */
+static inline u32 bcmgenet_tbuf_ctrl_get(struct bcmgenet_priv *priv)
+{
+	if (GENET_IS_V1(priv))
+		return bcmgenet_rbuf_readl(priv, TBUF_CTRL_V1);
+	else
+		return __raw_readl(priv->base +
+				priv->hw_params->tbuf_offset + TBUF_CTRL);
+}
+
+static inline void bcmgenet_tbuf_ctrl_set(struct bcmgenet_priv *priv, u32 val)
+{
+	if (GENET_IS_V1(priv))
+		bcmgenet_rbuf_writel(priv, val, TBUF_CTRL_V1);
+	else
+		__raw_writel(val, priv->base +
+				priv->hw_params->tbuf_offset + TBUF_CTRL);
+}
+
+static inline u32 bcmgenet_bp_mc_get(struct bcmgenet_priv *priv)
+{
+	if (GENET_IS_V1(priv))
+		return bcmgenet_rbuf_readl(priv, TBUF_BP_MC_V1);
+	else
+		return __raw_readl(priv->base +
+				priv->hw_params->tbuf_offset + TBUF_BP_MC);
+}
+
+static inline void bcmgenet_bp_mc_set(struct bcmgenet_priv *priv, u32 val)
+{
+	if (GENET_IS_V1(priv))
+		bcmgenet_rbuf_writel(priv, val, TBUF_BP_MC_V1);
+	else
+		__raw_writel(val, priv->base +
+				priv->hw_params->tbuf_offset + TBUF_BP_MC);
+}
+
+/* RX/TX DMA register accessors */
+enum dma_reg {
+	DMA_RING_CFG = 0,
+	DMA_CTRL,
+	DMA_STATUS,
+	DMA_SCB_BURST_SIZE,
+	DMA_ARB_CTRL,
+	DMA_PRIORITY,
+	DMA_RING_PRIORITY,
+};
+
+static const u8 bcmgenet_dma_regs_v3plus[] = {
+	[DMA_RING_CFG]		= 0x00,
+	[DMA_CTRL]		= 0x04,
+	[DMA_STATUS]		= 0x08,
+	[DMA_SCB_BURST_SIZE]	= 0x0C,
+	[DMA_ARB_CTRL]		= 0x2C,
+	[DMA_PRIORITY]		= 0x30,
+	[DMA_RING_PRIORITY]	= 0x38,
+};
+
+static const u8 bcmgenet_dma_regs_v2[] = {
+	[DMA_RING_CFG]		= 0x00,
+	[DMA_CTRL]		= 0x04,
+	[DMA_STATUS]		= 0x08,
+	[DMA_SCB_BURST_SIZE]	= 0x0C,
+	[DMA_ARB_CTRL]		= 0x30,
+	[DMA_PRIORITY]		= 0x34,
+	[DMA_RING_PRIORITY]	= 0x3C,
+};
+
+static const u8 bcmgenet_dma_regs_v1[] = {
+	[DMA_CTRL]		= 0x00,
+	[DMA_STATUS]		= 0x04,
+	[DMA_SCB_BURST_SIZE]	= 0x0C,
+	[DMA_ARB_CTRL]		= 0x30,
+	[DMA_PRIORITY]		= 0x34,
+	[DMA_RING_PRIORITY]	= 0x3C,
+};
+
+/* Set at runtime once bcmgenet version is known */
+static const u8 *bcmgenet_dma_regs;
+
+static inline struct bcmgenet_priv *dev_to_priv(struct device *dev)
+{
+	return netdev_priv(dev_get_drvdata(dev));
+}
+
+static inline u32 bcmgenet_tdma_readl(struct bcmgenet_priv *priv,
+					enum dma_reg r)
+{
+	return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
+			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
+}
+
+static inline void bcmgenet_tdma_writel(struct bcmgenet_priv *priv,
+					u32 val, enum dma_reg r)
+{
+	__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
+			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
+}
+
+static inline u32 bcmgenet_rdma_readl(struct bcmgenet_priv *priv,
+					enum dma_reg r)
+{
+	return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
+			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
+}
+
+static inline void bcmgenet_rdma_writel(struct bcmgenet_priv *priv,
+					u32 val, enum dma_reg r)
+{
+	__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
+			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
+}
+
+/* RDMA/TDMA ring registers and accessors
+ * we merge the common fields and just prefix with T/D the registers
+ * having different meaning depending on the direction
+ */
+enum dma_ring_reg {
+	TDMA_READ_PTR = 0,
+	RDMA_WRITE_PTR = TDMA_READ_PTR,
+	TDMA_READ_PTR_HI,
+	RDMA_WRITE_PTR_HI = TDMA_READ_PTR_HI,
+	TDMA_CONS_INDEX,
+	RDMA_PROD_INDEX = TDMA_CONS_INDEX,
+	TDMA_PROD_INDEX,
+	RDMA_CONS_INDEX = TDMA_PROD_INDEX,
+	DMA_RING_BUF_SIZE,
+	DMA_START_ADDR,
+	DMA_START_ADDR_HI,
+	DMA_END_ADDR,
+	DMA_END_ADDR_HI,
+	DMA_MBUF_DONE_THRESH,
+	TDMA_FLOW_PERIOD,
+	RDMA_XON_XOFF_THRESH = TDMA_FLOW_PERIOD,
+	TDMA_WRITE_PTR,
+	RDMA_READ_PTR = TDMA_WRITE_PTR,
+	TDMA_WRITE_PTR_HI,
+	RDMA_READ_PTR_HI = TDMA_WRITE_PTR_HI
+};
+
+/* GENET v4 supports 40-bits pointer addressing
+ * for obvious reasons the LO and HI word parts
+ * are contiguous, but this offsets the other
+ * registers.
+ */
+static const u8 genet_dma_ring_regs_v4[] = {
+	[TDMA_READ_PTR]			= 0x00,
+	[TDMA_READ_PTR_HI]		= 0x04,
+	[TDMA_CONS_INDEX]		= 0x08,
+	[TDMA_PROD_INDEX]		= 0x0C,
+	[DMA_RING_BUF_SIZE]		= 0x10,
+	[DMA_START_ADDR]		= 0x14,
+	[DMA_START_ADDR_HI]		= 0x18,
+	[DMA_END_ADDR]			= 0x1C,
+	[DMA_END_ADDR_HI]		= 0x20,
+	[DMA_MBUF_DONE_THRESH]		= 0x24,
+	[TDMA_FLOW_PERIOD]		= 0x28,
+	[TDMA_WRITE_PTR]		= 0x2C,
+	[TDMA_WRITE_PTR_HI]		= 0x30,
+};
+
+static const u8 genet_dma_ring_regs_v123[] = {
+	[TDMA_READ_PTR]			= 0x00,
+	[TDMA_CONS_INDEX]		= 0x04,
+	[TDMA_PROD_INDEX]		= 0x08,
+	[DMA_RING_BUF_SIZE]		= 0x0C,
+	[DMA_START_ADDR]		= 0x10,
+	[DMA_END_ADDR]			= 0x14,
+	[DMA_MBUF_DONE_THRESH]		= 0x18,
+	[TDMA_FLOW_PERIOD]		= 0x1C,
+	[TDMA_WRITE_PTR]		= 0x20,
+};
+
+/* Set at runtime once GENET version is known */
+static const u8 *genet_dma_ring_regs;
+
+static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,
+						unsigned int ring,
+						enum dma_ring_reg r)
+{
+	return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
+			(DMA_RING_SIZE * ring) +
+			genet_dma_ring_regs[r]);
+}
+
+static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,
+						unsigned int ring,
+						u32 val,
+						enum dma_ring_reg r)
+{
+	__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
+			(DMA_RING_SIZE * ring) +
+			genet_dma_ring_regs[r]);
+}
+
+static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,
+						unsigned int ring,
+						enum dma_ring_reg r)
+{
+	return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
+			(DMA_RING_SIZE * ring) +
+			genet_dma_ring_regs[r]);
+}
+
+static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
+						unsigned int ring,
+						u32 val,
+						enum dma_ring_reg r)
+{
+	__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
+			(DMA_RING_SIZE * ring) +
+			genet_dma_ring_regs[r]);
+}
+
+static int bcmgenet_get_settings(struct net_device *dev,
+		struct ethtool_cmd *cmd)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (!priv->phydev)
+		return -ENODEV;
+
+	return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int bcmgenet_set_settings(struct net_device *dev,
+		struct ethtool_cmd *cmd)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (!priv->phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static int bcmgenet_set_rx_csum(struct net_device *dev,
+				netdev_features_t wanted)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 rbuf_chk_ctrl;
+	bool rx_csum_en;
+
+	rx_csum_en = !!(wanted & NETIF_F_RXCSUM);
+
+	rbuf_chk_ctrl = bcmgenet_rbuf_readl(priv, RBUF_CHK_CTRL);
+
+	/* enable rx checksumming */
+	if (rx_csum_en)
+		rbuf_chk_ctrl |= RBUF_RXCHK_EN;
+	else
+		rbuf_chk_ctrl &= ~RBUF_RXCHK_EN;
+	priv->desc_rxchk_en = rx_csum_en;
+	bcmgenet_rbuf_writel(priv, rbuf_chk_ctrl, RBUF_CHK_CTRL);
+
+	return 0;
+}
+
+static int bcmgenet_set_tx_csum(struct net_device *dev,
+				netdev_features_t wanted)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	bool desc_64b_en;
+	u32 tbuf_ctrl, rbuf_ctrl;
+
+	tbuf_ctrl = bcmgenet_tbuf_ctrl_get(priv);
+	rbuf_ctrl = bcmgenet_rbuf_readl(priv, RBUF_CTRL);
+
+	desc_64b_en = !!(wanted & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM));
+
+	/* enable 64 bytes descriptor in both directions (RBUF and TBUF) */
+	if (desc_64b_en) {
+		tbuf_ctrl |= RBUF_64B_EN;
+		rbuf_ctrl |= RBUF_64B_EN;
+	} else {
+		tbuf_ctrl &= ~RBUF_64B_EN;
+		rbuf_ctrl &= ~RBUF_64B_EN;
+	}
+	priv->desc_64b_en = desc_64b_en;
+
+	bcmgenet_tbuf_ctrl_set(priv, tbuf_ctrl);
+	bcmgenet_rbuf_writel(priv, rbuf_ctrl, RBUF_CTRL);
+
+	return 0;
+}
+
+static int bcmgenet_set_features(struct net_device *dev,
+		netdev_features_t features)
+{
+	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t wanted = dev->wanted_features;
+	int ret = 0;
+
+	if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
+		ret = bcmgenet_set_tx_csum(dev, wanted);
+	if (changed & (NETIF_F_RXCSUM))
+		ret = bcmgenet_set_rx_csum(dev, wanted);
+
+	return ret;
+}
+
+static u32 bcmgenet_get_msglevel(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	return priv->msg_enable;
+}
+
+static void bcmgenet_set_msglevel(struct net_device *dev, u32 level)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	priv->msg_enable = level;
+}
+
+/* standard ethtool support functions. */
+enum bcmgenet_stat_type {
+	BCMGENET_STAT_NETDEV = -1,
+	BCMGENET_STAT_MIB_RX,
+	BCMGENET_STAT_MIB_TX,
+	BCMGENET_STAT_RUNT,
+	BCMGENET_STAT_MISC,
+};
+
+struct bcmgenet_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int stat_sizeof;
+	int stat_offset;
+	enum bcmgenet_stat_type type;
+	/* reg offset from UMAC base for misc counters */
+	u16 reg_offset;
+};
+
+#define STAT_NETDEV(m) { \
+	.stat_string = __stringify(m), \
+	.stat_sizeof = sizeof(((struct net_device_stats *)0)->m), \
+	.stat_offset = offsetof(struct net_device_stats, m), \
+	.type = BCMGENET_STAT_NETDEV, \
+}
+
+#define STAT_GENET_MIB(str, m, _type) { \
+	.stat_string = str, \
+	.stat_sizeof = sizeof(((struct bcmgenet_priv *)0)->m), \
+	.stat_offset = offsetof(struct bcmgenet_priv, m), \
+	.type = _type, \
+}
+
+#define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX)
+#define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX)
+#define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT)
+
+#define STAT_GENET_MISC(str, m, offset) { \
+	.stat_string = str, \
+	.stat_sizeof = sizeof(((struct bcmgenet_priv *)0)->m), \
+	.stat_offset = offsetof(struct bcmgenet_priv, m), \
+	.type = BCMGENET_STAT_MISC, \
+	.reg_offset = offset, \
+}
+
+
+/* There is a 0xC gap between the end of RX and beginning of TX stats and then
+ * between the end of TX stats and the beginning of the RX RUNT
+ */
+#define BCMGENET_STAT_OFFSET	0xc
+
+/* Hardware counters must be kept in sync because the order/offset
+ * is important here (order in structure declaration = order in hardware)
+ */
+static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
+	/* general stats */
+	STAT_NETDEV(rx_packets),
+	STAT_NETDEV(tx_packets),
+	STAT_NETDEV(rx_bytes),
+	STAT_NETDEV(tx_bytes),
+	STAT_NETDEV(rx_errors),
+	STAT_NETDEV(tx_errors),
+	STAT_NETDEV(rx_dropped),
+	STAT_NETDEV(tx_dropped),
+	STAT_NETDEV(multicast),
+	/* UniMAC RSV counters */
+	STAT_GENET_MIB_RX("rx_64_octets", mib.rx.pkt_cnt.cnt_64),
+	STAT_GENET_MIB_RX("rx_65_127_oct", mib.rx.pkt_cnt.cnt_127),
+	STAT_GENET_MIB_RX("rx_128_255_oct", mib.rx.pkt_cnt.cnt_255),
+	STAT_GENET_MIB_RX("rx_256_511_oct", mib.rx.pkt_cnt.cnt_511),
+	STAT_GENET_MIB_RX("rx_512_1023_oct", mib.rx.pkt_cnt.cnt_1023),
+	STAT_GENET_MIB_RX("rx_1024_1518_oct", mib.rx.pkt_cnt.cnt_1518),
+	STAT_GENET_MIB_RX("rx_vlan_1519_1522_oct", mib.rx.pkt_cnt.cnt_mgv),
+	STAT_GENET_MIB_RX("rx_1522_2047_oct", mib.rx.pkt_cnt.cnt_2047),
+	STAT_GENET_MIB_RX("rx_2048_4095_oct", mib.rx.pkt_cnt.cnt_4095),
+	STAT_GENET_MIB_RX("rx_4096_9216_oct", mib.rx.pkt_cnt.cnt_9216),
+	STAT_GENET_MIB_RX("rx_pkts", mib.rx.pkt),
+	STAT_GENET_MIB_RX("rx_bytes", mib.rx.bytes),
+	STAT_GENET_MIB_RX("rx_multicast", mib.rx.mca),
+	STAT_GENET_MIB_RX("rx_broadcast", mib.rx.bca),
+	STAT_GENET_MIB_RX("rx_fcs", mib.rx.fcs),
+	STAT_GENET_MIB_RX("rx_control", mib.rx.cf),
+	STAT_GENET_MIB_RX("rx_pause", mib.rx.pf),
+	STAT_GENET_MIB_RX("rx_unknown", mib.rx.uo),
+	STAT_GENET_MIB_RX("rx_align", mib.rx.aln),
+	STAT_GENET_MIB_RX("rx_outrange", mib.rx.flr),
+	STAT_GENET_MIB_RX("rx_code", mib.rx.cde),
+	STAT_GENET_MIB_RX("rx_carrier", mib.rx.fcr),
+	STAT_GENET_MIB_RX("rx_oversize", mib.rx.ovr),
+	STAT_GENET_MIB_RX("rx_jabber", mib.rx.jbr),
+	STAT_GENET_MIB_RX("rx_mtu_err", mib.rx.mtue),
+	STAT_GENET_MIB_RX("rx_good_pkts", mib.rx.pok),
+	STAT_GENET_MIB_RX("rx_unicast", mib.rx.uc),
+	STAT_GENET_MIB_RX("rx_ppp", mib.rx.ppp),
+	STAT_GENET_MIB_RX("rx_crc", mib.rx.rcrc),
+	/* UniMAC TSV counters */
+	STAT_GENET_MIB_TX("tx_64_octets", mib.tx.pkt_cnt.cnt_64),
+	STAT_GENET_MIB_TX("tx_65_127_oct", mib.tx.pkt_cnt.cnt_127),
+	STAT_GENET_MIB_TX("tx_128_255_oct", mib.tx.pkt_cnt.cnt_255),
+	STAT_GENET_MIB_TX("tx_256_511_oct", mib.tx.pkt_cnt.cnt_511),
+	STAT_GENET_MIB_TX("tx_512_1023_oct", mib.tx.pkt_cnt.cnt_1023),
+	STAT_GENET_MIB_TX("tx_1024_1518_oct", mib.tx.pkt_cnt.cnt_1518),
+	STAT_GENET_MIB_TX("tx_vlan_1519_1522_oct", mib.tx.pkt_cnt.cnt_mgv),
+	STAT_GENET_MIB_TX("tx_1522_2047_oct", mib.tx.pkt_cnt.cnt_2047),
+	STAT_GENET_MIB_TX("tx_2048_4095_oct", mib.tx.pkt_cnt.cnt_4095),
+	STAT_GENET_MIB_TX("tx_4096_9216_oct", mib.tx.pkt_cnt.cnt_9216),
+	STAT_GENET_MIB_TX("tx_pkts", mib.tx.pkts),
+	STAT_GENET_MIB_TX("tx_multicast", mib.tx.mca),
+	STAT_GENET_MIB_TX("tx_broadcast", mib.tx.bca),
+	STAT_GENET_MIB_TX("tx_pause", mib.tx.pf),
+	STAT_GENET_MIB_TX("tx_control", mib.tx.cf),
+	STAT_GENET_MIB_TX("tx_fcs_err", mib.tx.fcs),
+	STAT_GENET_MIB_TX("tx_oversize", mib.tx.ovr),
+	STAT_GENET_MIB_TX("tx_defer", mib.tx.drf),
+	STAT_GENET_MIB_TX("tx_excess_defer", mib.tx.edf),
+	STAT_GENET_MIB_TX("tx_single_col", mib.tx.scl),
+	STAT_GENET_MIB_TX("tx_multi_col", mib.tx.mcl),
+	STAT_GENET_MIB_TX("tx_late_col", mib.tx.lcl),
+	STAT_GENET_MIB_TX("tx_excess_col", mib.tx.ecl),
+	STAT_GENET_MIB_TX("tx_frags", mib.tx.frg),
+	STAT_GENET_MIB_TX("tx_total_col", mib.tx.ncl),
+	STAT_GENET_MIB_TX("tx_jabber", mib.tx.jbr),
+	STAT_GENET_MIB_TX("tx_bytes", mib.tx.bytes),
+	STAT_GENET_MIB_TX("tx_good_pkts", mib.tx.pok),
+	STAT_GENET_MIB_TX("tx_unicast", mib.tx.uc),
+	/* UniMAC RUNT counters */
+	STAT_GENET_RUNT("rx_runt_pkts", mib.rx_runt_cnt),
+	STAT_GENET_RUNT("rx_runt_valid_fcs", mib.rx_runt_fcs),
+	STAT_GENET_RUNT("rx_runt_inval_fcs_align", mib.rx_runt_fcs_align),
+	STAT_GENET_RUNT("rx_runt_bytes", mib.rx_runt_bytes),
+	/* Misc UniMAC counters */
+	STAT_GENET_MISC("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt,
+			UMAC_RBUF_OVFL_CNT),
+	STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT),
+	STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT),
+};
+
+#define BCMGENET_STATS_LEN	ARRAY_SIZE(bcmgenet_gstrings_stats)
+
+static void bcmgenet_get_drvinfo(struct net_device *dev,
+		struct ethtool_drvinfo *info)
+{
+	strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
+	strlcpy(info->version, "v2.0", sizeof(info->version));
+	info->n_stats = BCMGENET_STATS_LEN;
+
+}
+
+static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
+{
+	switch (string_set) {
+	case ETH_SS_STATS:
+		return BCMGENET_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void bcmgenet_get_strings(struct net_device *dev,
+				u32 stringset, u8 *data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < BCMGENET_STATS_LEN; i++) {
+			memcpy(data + i * ETH_GSTRING_LEN,
+				bcmgenet_gstrings_stats[i].stat_string,
+				ETH_GSTRING_LEN);
+		}
+		break;
+	}
+}
+
+static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
+{
+	int i, j = 0;
+
+	for (i = 0; i < BCMGENET_STATS_LEN; i++) {
+		const struct bcmgenet_stats *s;
+		u8 offset = 0;
+		u32 val = 0;
+		char *p;
+
+		s = &bcmgenet_gstrings_stats[i];
+		switch (s->type) {
+		case BCMGENET_STAT_NETDEV:
+			continue;
+		case BCMGENET_STAT_MIB_RX:
+		case BCMGENET_STAT_MIB_TX:
+		case BCMGENET_STAT_RUNT:
+			if (s->type != BCMGENET_STAT_MIB_RX)
+				offset = BCMGENET_STAT_OFFSET;
+			val = bcmgenet_umac_readl(priv, UMAC_MIB_START +
+								j + offset);
+			break;
+		case BCMGENET_STAT_MISC:
+			val = bcmgenet_umac_readl(priv, s->reg_offset);
+			/* clear if overflowed */
+			if (val == ~0)
+				bcmgenet_umac_writel(priv, 0, s->reg_offset);
+			break;
+		}
+
+		j += s->stat_sizeof;
+		p = (char *)priv + s->stat_offset;
+		*(u32 *)p = val;
+	}
+}
+
+static void bcmgenet_get_ethtool_stats(struct net_device *dev,
+					struct ethtool_stats *stats,
+					u64 *data)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int i;
+
+	if (netif_running(dev))
+		bcmgenet_update_mib_counters(priv);
+
+	for (i = 0; i < BCMGENET_STATS_LEN; i++) {
+		const struct bcmgenet_stats *s;
+		char *p;
+
+		s = &bcmgenet_gstrings_stats[i];
+		if (s->type == BCMGENET_STAT_NETDEV)
+			p = (char *)&dev->stats;
+		else
+			p = (char *)priv;
+		p += s->stat_offset;
+		data[i] = *(u32 *)p;
+	}
+}
+
+/* standard ethtool support functions. */
+static struct ethtool_ops bcmgenet_ethtool_ops = {
+	.get_strings		= bcmgenet_get_strings,
+	.get_sset_count		= bcmgenet_get_sset_count,
+	.get_ethtool_stats	= bcmgenet_get_ethtool_stats,
+	.get_settings		= bcmgenet_get_settings,
+	.set_settings		= bcmgenet_set_settings,
+	.get_drvinfo		= bcmgenet_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_msglevel		= bcmgenet_get_msglevel,
+	.set_msglevel		= bcmgenet_set_msglevel,
+};
+
+/* Power down the unimac, based on mode. */
+static void bcmgenet_power_down(struct bcmgenet_priv *priv,
+				enum bcmgenet_power_mode mode)
+{
+	u32 reg;
+
+	switch (mode) {
+	case GENET_POWER_CABLE_SENSE:
+		phy_detach(priv->phydev);
+		break;
+
+	case GENET_POWER_PASSIVE:
+		/* Power down LED */
+		bcmgenet_mii_reset(priv->dev);
+		if (priv->hw_params->flags & GENET_HAS_EXT) {
+			reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+			reg |= (EXT_PWR_DOWN_PHY |
+				EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS);
+			bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void bcmgenet_power_up(struct bcmgenet_priv *priv,
+				enum bcmgenet_power_mode mode)
+{
+	u32 reg;
+
+	if (!(priv->hw_params->flags & GENET_HAS_EXT))
+		return;
+
+	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+
+	switch (mode) {
+	case GENET_POWER_PASSIVE:
+		reg &= ~(EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_PHY |
+				EXT_PWR_DOWN_BIAS);
+		/* fallthrough */
+	case GENET_POWER_CABLE_SENSE:
+		/* enable APD */
+		reg |= EXT_PWR_DN_EN_LD;
+		break;
+	default:
+		break;
+	}
+
+	bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+	bcmgenet_mii_reset(priv->dev);
+}
+
+/* ioctl handle special commands that are not present in ethtool. */
+static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int val = 0;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		if (!priv->phydev)
+			val = -ENODEV;
+		else
+			val = phy_mii_ioctl(priv->phydev, rq, cmd);
+		break;
+
+	default:
+		val = -EINVAL;
+		break;
+	}
+
+	return val;
+}
+
+static struct enet_cb *bcmgenet_get_txcb(struct bcmgenet_priv *priv,
+					 struct bcmgenet_tx_ring *ring)
+{
+	struct enet_cb *tx_cb_ptr;
+
+	tx_cb_ptr = ring->cbs;
+	tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
+	tx_cb_ptr->bd_addr = priv->tx_bds + ring->write_ptr * DMA_DESC_SIZE;
+	/* Advancing local write pointer */
+	if (ring->write_ptr == ring->end_ptr)
+		ring->write_ptr = ring->cb_ptr;
+	else
+		ring->write_ptr++;
+
+	return tx_cb_ptr;
+}
+
+/* Simple helper to free a control block's resources */
+static void bcmgenet_free_cb(struct enet_cb *cb)
+{
+	dev_kfree_skb_any(cb->skb);
+	cb->skb = NULL;
+	dma_unmap_addr_set(cb, dma_addr, 0);
+}
+
+static inline void bcmgenet_tx_ring16_int_disable(struct bcmgenet_priv *priv,
+						  struct bcmgenet_tx_ring *ring)
+{
+	bcmgenet_intrl2_0_writel(priv,
+			UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+			INTRL2_CPU_MASK_SET);
+}
+
+static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_priv *priv,
+						 struct bcmgenet_tx_ring *ring)
+{
+	bcmgenet_intrl2_0_writel(priv,
+			UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+			INTRL2_CPU_MASK_CLEAR);
+}
+
+static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_priv *priv,
+						struct bcmgenet_tx_ring *ring)
+{
+	bcmgenet_intrl2_1_writel(priv,
+			(1 << ring->index), INTRL2_CPU_MASK_CLEAR);
+	priv->int1_mask &= ~(1 << ring->index);
+}
+
+static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv,
+						struct bcmgenet_tx_ring *ring)
+{
+	bcmgenet_intrl2_1_writel(priv,
+			(1 << ring->index), INTRL2_CPU_MASK_SET);
+	priv->int1_mask |= (1 << ring->index);
+}
+
+/* Unlocked version of the reclaim routine */
+static void __bcmgenet_tx_reclaim(struct net_device *dev,
+				struct bcmgenet_tx_ring *ring)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int last_tx_cn, last_c_index, num_tx_bds;
+	struct enet_cb *tx_cb_ptr;
+	unsigned int c_index;
+
+	/* Compute how many buffers are transmited since last xmit call */
+	c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX);
+
+	last_c_index = ring->c_index;
+	num_tx_bds = ring->size;
+
+	c_index &= (num_tx_bds - 1);
+
+	if (c_index >= last_c_index)
+		last_tx_cn = c_index - last_c_index;
+	else
+		last_tx_cn = num_tx_bds - last_c_index + c_index;
+
+	netif_dbg(priv, tx_done, dev,
+			"%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
+			__func__, ring->index,
+			c_index, last_tx_cn, last_c_index);
+
+	/* Reclaim transmitted buffers */
+	while (last_tx_cn-- > 0) {
+		tx_cb_ptr = ring->cbs + last_c_index;
+		if (tx_cb_ptr->skb) {
+			dev->stats.tx_bytes += tx_cb_ptr->skb->len;
+			dma_unmap_single(&dev->dev,
+					dma_unmap_addr(tx_cb_ptr, dma_addr),
+					tx_cb_ptr->skb->len,
+					DMA_TO_DEVICE);
+			bcmgenet_free_cb(tx_cb_ptr);
+		} else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
+			dev->stats.tx_bytes +=
+				dma_unmap_len(tx_cb_ptr, dma_len);
+			dma_unmap_page(&dev->dev,
+					dma_unmap_addr(tx_cb_ptr, dma_addr),
+					dma_unmap_len(tx_cb_ptr, dma_len),
+					DMA_TO_DEVICE);
+			dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0);
+		}
+		dev->stats.tx_packets++;
+		ring->free_bds += 1;
+
+		last_c_index++;
+		last_c_index &= (num_tx_bds - 1);
+	}
+
+	if (ring->free_bds > (MAX_SKB_FRAGS + 1))
+		ring->int_disable(priv, ring);
+
+	if (__netif_subqueue_stopped(dev, ring->queue))
+		netif_wake_subqueue(dev, ring->queue);
+
+	ring->c_index = c_index;
+}
+
+static void bcmgenet_tx_reclaim(struct net_device *dev,
+		struct bcmgenet_tx_ring *ring)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ring->lock, flags);
+	__bcmgenet_tx_reclaim(dev, ring);
+	spin_unlock_irqrestore(&ring->lock, flags);
+}
+
+static void bcmgenet_tx_reclaim_all(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int i;
+
+	if (netif_is_multiqueue(dev)) {
+		for (i = 0; i < priv->hw_params->tx_queues; i++)
+			bcmgenet_tx_reclaim(dev, &priv->tx_rings[i]);
+	}
+
+	bcmgenet_tx_reclaim(dev, &priv->tx_rings[DESC_INDEX]);
+}
+
+/* Transmits a single SKB (either head of a fragment or a single SKB)
+ * caller must hold priv->lock
+ */
+static int bcmgenet_xmit_single(struct net_device *dev,
+				struct sk_buff *skb,
+				u16 dma_desc_flags,
+				struct bcmgenet_tx_ring *ring)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
+	struct enet_cb *tx_cb_ptr;
+	unsigned int skb_len;
+	dma_addr_t mapping;
+	u32 length_status;
+	int ret;
+
+	tx_cb_ptr = bcmgenet_get_txcb(priv, ring);
+
+	if (unlikely(!tx_cb_ptr))
+		BUG();
+
+	tx_cb_ptr->skb = skb;
+
+	skb_len = skb_headlen(skb) < ETH_ZLEN ? ETH_ZLEN : skb_headlen(skb);
+
+	mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
+	ret = dma_mapping_error(kdev, mapping);
+	if (ret) {
+		netif_err(priv, tx_err, dev, "Tx DMA map failed\n");
+		dev_kfree_skb(skb);
+		return ret;
+	}
+
+	dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping);
+	dma_unmap_len_set(tx_cb_ptr, dma_len, skb->len);
+	length_status = (skb_len << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
+			(priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT) |
+			DMA_TX_APPEND_CRC;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		length_status |= DMA_TX_DO_CSUM;
+
+	dmadesc_set(priv, tx_cb_ptr->bd_addr, mapping, length_status);
+
+	/* Decrement total BD count and advance our write pointer */
+	ring->free_bds -= 1;
+	ring->prod_index += 1;
+	ring->prod_index &= DMA_P_INDEX_MASK;
+
+	return 0;
+}
+
+/* Transmit a SKB fragement */
+static int bcmgenet_xmit_frag(struct net_device *dev,
+				skb_frag_t *frag,
+				u16 dma_desc_flags,
+				struct bcmgenet_tx_ring *ring)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
+	struct enet_cb *tx_cb_ptr;
+	dma_addr_t mapping;
+	int ret;
+
+	tx_cb_ptr = bcmgenet_get_txcb(priv, ring);
+
+	if (unlikely(!tx_cb_ptr))
+		BUG();
+	tx_cb_ptr->skb = NULL;
+
+	mapping = skb_frag_dma_map(kdev, frag, 0,
+		skb_frag_size(frag), DMA_TO_DEVICE);
+	ret = dma_mapping_error(kdev, mapping);
+	if (ret) {
+		netif_err(priv, tx_err, dev, "%s: Tx DMA map failed\n",
+				__func__);
+		return ret;
+	}
+
+	dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping);
+	dma_unmap_len_set(tx_cb_ptr, dma_len, frag->size);
+
+	dmadesc_set(priv, tx_cb_ptr->bd_addr, mapping,
+			(frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
+			(priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT));
+
+
+	ring->free_bds -= 1;
+	ring->prod_index += 1;
+	ring->prod_index &= DMA_P_INDEX_MASK;
+
+	return 0;
+}
+
+/* Reallocate the SKB to put enough headroom in front of it and insert
+ * the transmit checksum offsets in the descriptors
+ */
+static int bcmgenet_put_tx_csum(struct net_device *dev, struct sk_buff *skb)
+{
+	struct status_64 *status = NULL;
+	struct sk_buff *new_skb;
+	u16 offset;
+	u8 ip_proto;
+	u16 ip_ver;
+	u32 tx_csum_info;
+
+	if (unlikely(skb_headroom(skb) < sizeof(*status))) {
+		/* If 64 byte status block enabled, must make sure skb has
+		 * enough headroom for us to insert 64B status block.
+		 */
+		new_skb = skb_realloc_headroom(skb, sizeof(*status));
+		dev_kfree_skb(skb);
+		if (!new_skb) {
+			dev->stats.tx_errors++;
+			dev->stats.tx_dropped++;
+			return -ENOMEM;
+		}
+		skb = new_skb;
+	}
+
+	skb_push(skb, sizeof(*status));
+	status = (struct status_64 *)skb->data;
+
+	if (skb->ip_summed  == CHECKSUM_PARTIAL) {
+		ip_ver = htons(skb->protocol);
+		switch (ip_ver) {
+		case ETH_P_IP:
+			ip_proto = ip_hdr(skb)->protocol;
+			break;
+		case ETH_P_IPV6:
+			ip_proto = ipv6_hdr(skb)->nexthdr;
+			break;
+		default:
+			return 0;
+		}
+
+		offset = skb_checksum_start_offset(skb) - sizeof(*status);
+		tx_csum_info = (offset << STATUS_TX_CSUM_START_SHIFT) |
+				(offset + skb->csum_offset);
+
+		/* Set the length valid bit for TCP and UDP and just set
+		 * the special UDP flag for IPv4, else just set to 0.
+		 */
+		if (ip_proto == IPPROTO_TCP || ip_proto == IPPROTO_UDP) {
+			tx_csum_info |= STATUS_TX_CSUM_LV;
+			if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP)
+				tx_csum_info |= STATUS_TX_CSUM_PROTO_UDP;
+		} else
+			tx_csum_info = 0;
+
+		status->tx_csum_info = tx_csum_info;
+	}
+
+	return 0;
+}
+
+static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct bcmgenet_tx_ring *ring = NULL;
+	unsigned long flags = 0;
+	int nr_frags, index;
+	u16 dma_desc_flags;
+	int ret;
+	int i;
+
+	index = skb_get_queue_mapping(skb);
+	/* Mapping strategy:
+	 * queue_mapping = 0, unclassified, packet xmited through ring16
+	 * queue_mapping = 1, goes to ring 0. (highest priority queue
+	 * queue_mapping = 2, goes to ring 1.
+	 * queue_mapping = 3, goes to ring 2.
+	 * queue_mapping = 4, goes to ring 3.
+	 */
+	if (index == 0)
+		index = DESC_INDEX;
+	else
+		index -= 1;
+
+	if ((index != DESC_INDEX) && (index > priv->hw_params->tx_queues - 1)) {
+		netdev_err(dev, "%s: queue_mapping %d is invalid\n",
+				__func__, skb_get_queue_mapping(skb));
+		dev->stats.tx_errors++;
+		dev->stats.tx_dropped++;
+		ret = NETDEV_TX_OK;
+		goto out;
+	}
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	ring = &priv->tx_rings[index];
+
+	spin_lock_irqsave(&ring->lock, flags);
+	if (ring->free_bds <= nr_frags + 1) {
+		netif_stop_subqueue(dev, ring->queue);
+		netdev_err(dev, "%s: tx ring %d full when queue %d awake\n",
+				__func__, index, ring->queue);
+		ret = NETDEV_TX_BUSY;
+		goto out;
+	}
+
+	/* set the SKB transmit checksum */
+	if (priv->desc_64b_en) {
+		ret = bcmgenet_put_tx_csum(dev, skb);
+		if (ret) {
+			ret = NETDEV_TX_OK;
+			goto out;
+		}
+	}
+
+	dma_desc_flags = DMA_SOP;
+	if (nr_frags == 0)
+		dma_desc_flags |= DMA_EOP;
+
+	/* Transmit single SKB or head of fragment list */
+	ret = bcmgenet_xmit_single(dev, skb, dma_desc_flags, ring);
+	if (ret) {
+		ret = NETDEV_TX_OK;
+		goto out;
+	}
+
+	/* xmit fragment */
+	for (i = 0; i < nr_frags; i++) {
+		ret = bcmgenet_xmit_frag(dev,
+				&skb_shinfo(skb)->frags[i],
+				(i == nr_frags - 1) ? DMA_EOP : 0, ring);
+		if (ret) {
+			ret = NETDEV_TX_OK;
+			goto out;
+		}
+	}
+
+	/* we kept a software copy of how much we should advance the TDMA
+	 * producer index, now write it down to the hardware
+	 */
+	bcmgenet_tdma_ring_writel(priv, ring->index,
+			ring->prod_index, TDMA_PROD_INDEX);
+
+	if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) {
+		netif_stop_subqueue(dev, ring->queue);
+		ring->int_enable(priv, ring);
+	}
+
+out:
+	spin_unlock_irqrestore(&ring->lock, flags);
+
+	return ret;
+}
+
+
+static int bcmgenet_rx_refill(struct bcmgenet_priv *priv,
+				struct enet_cb *cb)
+{
+	struct device *kdev = &priv->pdev->dev;
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+	int ret;
+
+	skb = netdev_alloc_skb(priv->dev,
+				priv->rx_buf_len + SKB_ALIGNMENT);
+	if (!skb)
+		return -ENOMEM;
+
+	/* a caller did not release this control block */
+	WARN_ON(cb->skb != NULL);
+	cb->skb = skb;
+	mapping = dma_map_single(kdev, skb->data,
+			priv->rx_buf_len, DMA_FROM_DEVICE);
+	ret = dma_mapping_error(kdev, mapping);
+	if (ret) {
+		bcmgenet_free_cb(cb);
+		netif_err(priv, rx_err, priv->dev,
+				"%s DMA map failed\n", __func__);
+		return ret;
+	}
+
+	dma_unmap_addr_set(cb, dma_addr, mapping);
+	/* assign packet, prepare descriptor, and advance pointer */
+
+	dmadesc_set_addr(priv, priv->rx_bd_assign_ptr, mapping);
+
+	/* turn on the newly assigned BD for DMA to use */
+	priv->rx_bd_assign_index++;
+	priv->rx_bd_assign_index &= (priv->num_rx_bds - 1);
+
+	priv->rx_bd_assign_ptr = priv->rx_bds +
+		(priv->rx_bd_assign_index * DMA_DESC_SIZE);
+
+	return 0;
+}
+
+/* bcmgenet_desc_rx - descriptor based rx process.
+ * this could be called from bottom half, or from NAPI polling method.
+ */
+static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
+				     unsigned int budget)
+{
+	struct net_device *dev = priv->dev;
+	struct enet_cb *cb;
+	struct sk_buff *skb;
+	u32 dma_length_status;
+	unsigned long dma_flag;
+	int len, err;
+	unsigned int rxpktprocessed = 0, rxpkttoprocess;
+	unsigned int p_index;
+	unsigned int chksum_ok = 0;
+
+	p_index = bcmgenet_rdma_ring_readl(priv,
+			DESC_INDEX, RDMA_PROD_INDEX);
+	p_index &= DMA_P_INDEX_MASK;
+
+	if (p_index < priv->rx_c_index)
+		rxpkttoprocess = (DMA_C_INDEX_MASK + 1) -
+			priv->rx_c_index + p_index;
+	else
+		rxpkttoprocess = p_index - priv->rx_c_index;
+
+	netif_dbg(priv, rx_status, dev,
+		"RDMA: rxpkttoprocess=%d\n", rxpkttoprocess);
+
+	while ((rxpktprocessed < rxpkttoprocess) &&
+			(rxpktprocessed < budget)) {
+
+		/* Unmap the packet contents such that we can use the
+		 * RSV from the 64 bytes descriptor when enabled and save
+		 * a 32-bits register read
+		 */
+		cb = &priv->rx_cbs[priv->rx_read_ptr];
+		skb = cb->skb;
+		dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr),
+				priv->rx_buf_len, DMA_FROM_DEVICE);
+
+		if (!priv->desc_64b_en) {
+			dma_length_status = dmadesc_get_length_status(priv,
+							priv->rx_bds +
+							(priv->rx_read_ptr *
+							 DMA_DESC_SIZE));
+		} else {
+			struct status_64 *status;
+			status = (struct status_64 *)skb->data;
+			dma_length_status = status->length_status;
+		}
+
+		/* DMA flags and length are still valid no matter how
+		 * we got the Receive Status Vector (64B RSB or register)
+		 */
+		dma_flag = dma_length_status & 0xffff;
+		len = dma_length_status >> DMA_BUFLENGTH_SHIFT;
+
+		netif_dbg(priv, rx_status, dev,
+			"%s: p_ind=%d c_ind=%d read_ptr=%d len_stat=0x%08x\n",
+			__func__, p_index, priv->rx_c_index, priv->rx_read_ptr,
+			dma_length_status);
+
+		rxpktprocessed++;
+
+		priv->rx_read_ptr++;
+		priv->rx_read_ptr &= (priv->num_rx_bds - 1);
+
+		/* out of memory, just drop packets at the hardware level */
+		if (unlikely(!skb)) {
+			dev->stats.rx_dropped++;
+			dev->stats.rx_errors++;
+			goto refill;
+		}
+
+		if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
+			netif_err(priv, rx_status, dev,
+					"Droping fragmented packet!\n");
+			dev->stats.rx_dropped++;
+			dev->stats.rx_errors++;
+			dev_kfree_skb_any(cb->skb);
+			cb->skb = NULL;
+			goto refill;
+		}
+		/* report errors */
+		if (unlikely(dma_flag & (DMA_RX_CRC_ERROR |
+						DMA_RX_OV |
+						DMA_RX_NO |
+						DMA_RX_LG |
+						DMA_RX_RXER))) {
+			netif_err(priv, rx_status, dev, "dma_flag=0x%x\n",
+						(unsigned int)dma_flag);
+			if (dma_flag & DMA_RX_CRC_ERROR)
+				dev->stats.rx_crc_errors++;
+			if (dma_flag & DMA_RX_OV)
+				dev->stats.rx_over_errors++;
+			if (dma_flag & DMA_RX_NO)
+				dev->stats.rx_frame_errors++;
+			if (dma_flag & DMA_RX_LG)
+				dev->stats.rx_length_errors++;
+			dev->stats.rx_dropped++;
+			dev->stats.rx_errors++;
+
+			/* discard the packet and advance consumer index.*/
+			dev_kfree_skb_any(cb->skb);
+			cb->skb = NULL;
+			goto refill;
+		} /* error packet */
+
+		chksum_ok = (dma_flag & priv->dma_rx_chk_bit) &&
+				priv->desc_rxchk_en;
+
+		skb_put(skb, len);
+		if (priv->desc_64b_en) {
+			skb_pull(skb, 64);
+			len -= 64;
+		}
+
+		if (likely(chksum_ok))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		/* remove hardware 2bytes added for IP alignment */
+		skb_pull(skb, 2);
+		len -= 2;
+
+		if (priv->crc_fwd_en) {
+			skb_trim(skb, len - ETH_FCS_LEN);
+			len -= ETH_FCS_LEN;
+		}
+
+		/*Finish setting up the received SKB and send it to the kernel*/
+		skb->protocol = eth_type_trans(skb, priv->dev);
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += len;
+		if (dma_flag & DMA_RX_MULT)
+			dev->stats.multicast++;
+
+		/* Notify kernel */
+		napi_gro_receive(&priv->napi, skb);
+		cb->skb = NULL;
+		netif_dbg(priv, rx_status, dev, "pushed up to kernel\n");
+
+		/* refill RX path on the current control block */
+refill:
+		err = bcmgenet_rx_refill(priv, cb);
+		if (err)
+			netif_err(priv, rx_err, dev, "Rx refill failed\n");
+	}
+
+	return rxpktprocessed;
+}
+
+/* Assign skb to RX DMA descriptor. */
+static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv)
+{
+	struct enet_cb *cb;
+	int ret = 0;
+	int i;
+
+	netif_dbg(priv, hw, priv->dev, "%s:\n", __func__);
+
+	/* loop here for each buffer needing assign */
+	for (i = 0; i < priv->num_rx_bds; i++) {
+		cb = &priv->rx_cbs[priv->rx_bd_assign_index];
+		if (cb->skb)
+			continue;
+
+		/* set the DMA descriptor length once and for all
+		 * it will only change if we support dynamically sizing
+		 * priv->rx_buf_len, but we do not
+		 */
+		dmadesc_set_length_status(priv, priv->rx_bd_assign_ptr,
+				priv->rx_buf_len << DMA_BUFLENGTH_SHIFT);
+
+		ret = bcmgenet_rx_refill(priv, cb);
+		if (ret)
+			break;
+
+	}
+
+	return ret;
+}
+
+static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
+{
+	struct enet_cb *cb;
+	int i;
+
+	for (i = 0; i < priv->num_rx_bds; i++) {
+		cb = &priv->rx_cbs[i];
+
+		if (dma_unmap_addr(cb, dma_addr)) {
+			dma_unmap_single(&priv->dev->dev,
+					dma_unmap_addr(cb, dma_addr),
+					priv->rx_buf_len, DMA_FROM_DEVICE);
+			dma_unmap_addr_set(cb, dma_addr, 0);
+		}
+
+		if (cb->skb)
+			bcmgenet_free_cb(cb);
+	}
+}
+
+static int reset_umac(struct bcmgenet_priv *priv)
+{
+	struct device *kdev = &priv->pdev->dev;
+	unsigned int timeout = 0;
+	u32 reg;
+
+	/* 7358a0/7552a0: bad default in RBUF_FLUSH_CTRL.umac_sw_rst */
+	bcmgenet_rbuf_ctrl_set(priv, 0);
+	udelay(10);
+
+	/* disable MAC while updating its registers */
+	bcmgenet_umac_writel(priv, 0, UMAC_CMD);
+
+	/* issue soft reset, wait for it to complete */
+	bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
+	while (timeout++ < 1000) {
+		reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+		if (!(reg & CMD_SW_RESET))
+			return 0;
+
+		udelay(1);
+	}
+
+	if (timeout == 1000) {
+		dev_err(kdev,
+			"timeout waiting for MAC to come out of resetn\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int init_umac(struct bcmgenet_priv *priv)
+{
+	struct device *kdev = &priv->pdev->dev;
+	int ret;
+	u32 reg, cpu_mask_clear;
+
+	dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n");
+
+	ret = reset_umac(priv);
+	if (ret)
+		return ret;
+
+	bcmgenet_umac_writel(priv, 0, UMAC_CMD);
+	/* clear tx/rx counter */
+	bcmgenet_umac_writel(priv,
+		MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT, UMAC_MIB_CTRL);
+	bcmgenet_umac_writel(priv, 0, UMAC_MIB_CTRL);
+
+	bcmgenet_umac_writel(priv, ENET_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
+
+	/* init rx registers, enable ip header optimization */
+	reg = bcmgenet_rbuf_readl(priv, RBUF_CTRL);
+	reg |= RBUF_ALIGN_2B;
+	bcmgenet_rbuf_writel(priv, reg, RBUF_CTRL);
+
+	if (!GENET_IS_V1(priv) && !GENET_IS_V2(priv))
+		bcmgenet_rbuf_writel(priv, 1, RBUF_TBUF_SIZE_CTRL);
+
+	/* Mask all interrupts.*/
+	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
+	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
+	bcmgenet_intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+
+	cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE;
+
+	dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__);
+
+	/* Monitor cable plug/unpluged event for internal PHY */
+	if (phy_is_internal(priv->phydev))
+		cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
+	else if (priv->ext_phy)
+		cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
+	else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+		reg = bcmgenet_bp_mc_get(priv);
+		reg |= BIT(priv->hw_params->bp_in_en_shift);
+
+		/* bp_mask: back pressure mask */
+		if (netif_is_multiqueue(priv->dev))
+			reg |= priv->hw_params->bp_in_mask;
+		else
+			reg &= ~priv->hw_params->bp_in_mask;
+		bcmgenet_bp_mc_set(priv, reg);
+	}
+
+	/* Enable MDIO interrupts on GENET v3+ */
+	if (priv->hw_params->flags & GENET_HAS_MDIO_INTR)
+		cpu_mask_clear |= UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR;
+
+	bcmgenet_intrl2_0_writel(priv, cpu_mask_clear,
+		INTRL2_CPU_MASK_CLEAR);
+
+	/* Enable rx/tx engine.*/
+	dev_dbg(kdev, "done init umac\n");
+
+	return 0;
+}
+
+/* Initialize all house-keeping variables for a TX ring, along
+ * with corresponding hardware registers
+ */
+static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
+				  unsigned int index, unsigned int size,
+				  unsigned int write_ptr, unsigned int end_ptr)
+{
+	struct bcmgenet_tx_ring *ring = &priv->tx_rings[index];
+	u32 words_per_bd = WORDS_PER_BD(priv);
+	u32 flow_period_val = 0;
+	unsigned int first_bd;
+
+	spin_lock_init(&ring->lock);
+	ring->index = index;
+	if (index == DESC_INDEX) {
+		ring->queue = 0;
+		ring->int_enable = bcmgenet_tx_ring16_int_enable;
+		ring->int_disable = bcmgenet_tx_ring16_int_disable;
+	} else {
+		ring->queue = index + 1;
+		ring->int_enable = bcmgenet_tx_ring_int_enable;
+		ring->int_disable = bcmgenet_tx_ring_int_disable;
+	}
+	ring->cbs = priv->tx_cbs + write_ptr;
+	ring->size = size;
+	ring->c_index = 0;
+	ring->free_bds = size;
+	ring->write_ptr = write_ptr;
+	ring->cb_ptr = write_ptr;
+	ring->end_ptr = end_ptr - 1;
+	ring->prod_index = 0;
+
+	/* Set flow period for ring != 16 */
+	if (index != DESC_INDEX)
+		flow_period_val = ENET_MAX_MTU_SIZE << 16;
+
+	bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
+	bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
+	bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
+	/* Disable rate control for now */
+	bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
+			TDMA_FLOW_PERIOD);
+	/* Unclassified traffic goes to ring 16 */
+	bcmgenet_tdma_ring_writel(priv, index,
+			((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
+			DMA_RING_BUF_SIZE);
+
+	first_bd = write_ptr;
+
+	/* Set start and end address, read and write pointers */
+	bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
+			DMA_START_ADDR);
+	bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
+			TDMA_READ_PTR);
+	bcmgenet_tdma_ring_writel(priv, index, first_bd,
+			TDMA_WRITE_PTR);
+	bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
+			DMA_END_ADDR);
+}
+
+/* Initialize a RDMA ring */
+static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
+				  unsigned int index, unsigned int size)
+{
+	u32 words_per_bd = WORDS_PER_BD(priv);
+	int ret;
+
+	priv->num_rx_bds = TOTAL_DESC;
+	priv->rx_bds = priv->base + priv->hw_params->rdma_offset;
+	priv->rx_bd_assign_ptr = priv->rx_bds;
+	priv->rx_bd_assign_index = 0;
+	priv->rx_c_index = 0;
+	priv->rx_read_ptr = 0;
+	priv->rx_cbs = kzalloc(priv->num_rx_bds * sizeof(struct enet_cb),
+				GFP_KERNEL);
+	if (!priv->rx_cbs)
+		return -ENOMEM;
+
+	ret = bcmgenet_alloc_rx_buffers(priv);
+	if (ret) {
+		kfree(priv->rx_cbs);
+		return ret;
+	}
+
+	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_WRITE_PTR);
+	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
+	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
+	bcmgenet_rdma_ring_writel(priv, index,
+		((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
+		DMA_RING_BUF_SIZE);
+	bcmgenet_rdma_ring_writel(priv, index, 0, DMA_START_ADDR);
+	bcmgenet_rdma_ring_writel(priv, index,
+		words_per_bd * size - 1, DMA_END_ADDR);
+	bcmgenet_rdma_ring_writel(priv, index,
+			(DMA_FC_THRESH_LO << DMA_XOFF_THRESHOLD_SHIFT) |
+			DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
+	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_READ_PTR);
+
+	return ret;
+}
+
+/* init multi xmit queues, only available for GENET2+
+ * the queue is partitioned as follows:
+ *
+ * queue 0 - 3 is priority based, each one has 32 descriptors,
+ * with queue 0 being the highest priority queue.
+ *
+ * queue 16 is the default tx queue with GENET_DEFAULT_BD_CNT
+ * descriptors: 256 - (number of tx queues * bds per queues) = 128
+ * descriptors.
+ *
+ * The transmit control block pool is then partitioned as following:
+ * - tx_cbs[0...127] are for queue 16
+ * - tx_ring_cbs[0] points to tx_cbs[128..159]
+ * - tx_ring_cbs[1] points to tx_cbs[160..191]
+ * - tx_ring_cbs[2] points to tx_cbs[192..223]
+ * - tx_ring_cbs[3] points to tx_cbs[224..255]
+ */
+static void bcmgenet_init_multiq(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	unsigned int i, dma_enable;
+	u32 reg, dma_ctrl, ring_cfg = 0, dma_priority = 0;
+
+	if (!netif_is_multiqueue(dev)) {
+		netdev_warn(dev, "called with non multi queue aware HW\n");
+		return;
+	}
+
+	dma_ctrl = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	dma_enable = dma_ctrl & DMA_EN;
+	dma_ctrl &= ~DMA_EN;
+	bcmgenet_tdma_writel(priv, dma_ctrl, DMA_CTRL);
+
+	/* Enable strict priority arbiter mode */
+	bcmgenet_tdma_writel(priv, DMA_ARBITER_SP, DMA_ARB_CTRL);
+
+	for (i = 0; i < priv->hw_params->tx_queues; i++) {
+		/* first 64 tx_cbs are reserved for default tx queue
+		 * (ring 16)
+		 */
+		bcmgenet_init_tx_ring(priv, i, priv->hw_params->bds_cnt,
+					i * priv->hw_params->bds_cnt,
+					(i + 1) * priv->hw_params->bds_cnt);
+
+		/* Configure ring as decriptor ring and setup priority */
+		ring_cfg |= 1 << i;
+		dma_priority |= ((GENET_Q0_PRIORITY + i) <<
+				(GENET_MAX_MQ_CNT + 1) * i);
+		dma_ctrl |= 1 << (i + DMA_RING_BUF_EN_SHIFT);
+	}
+
+	/* Enable rings */
+	reg = bcmgenet_tdma_readl(priv, DMA_RING_CFG);
+	reg |= ring_cfg;
+	bcmgenet_tdma_writel(priv, reg, DMA_RING_CFG);
+
+	/* Use configured rings priority and set ring #16 priority */
+	reg = bcmgenet_tdma_readl(priv, DMA_RING_PRIORITY);
+	reg |= ((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) << 20);
+	reg |= dma_priority;
+	bcmgenet_tdma_writel(priv, reg, DMA_PRIORITY);
+
+	/* Configure ring as descriptor ring and re-enable DMA if enabled */
+	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	reg |= dma_ctrl;
+	if (dma_enable)
+		reg |= DMA_EN;
+	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+}
+
+static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
+{
+	int i;
+
+	/* disable DMA */
+	bcmgenet_rdma_writel(priv, 0, DMA_CTRL);
+	bcmgenet_tdma_writel(priv, 0, DMA_CTRL);
+
+	for (i = 0; i < priv->num_tx_bds; i++) {
+		if (priv->tx_cbs[i].skb != NULL) {
+			dev_kfree_skb(priv->tx_cbs[i].skb);
+			priv->tx_cbs[i].skb = NULL;
+		}
+	}
+
+	bcmgenet_free_rx_buffers(priv);
+	kfree(priv->rx_cbs);
+	kfree(priv->tx_cbs);
+}
+
+/* init_edma: Initialize DMA control register */
+static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
+{
+	int ret;
+
+	netif_dbg(priv, hw, priv->dev, "bcmgenet: init_edma\n");
+
+	/* by default, enable ring 16 (descriptor based) */
+	ret = bcmgenet_init_rx_ring(priv, DESC_INDEX, TOTAL_DESC);
+	if (ret) {
+		netdev_err(priv->dev, "failed to initialize RX ring\n");
+		return ret;
+	}
+
+	/* init rDma */
+	bcmgenet_rdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
+
+	/* Init tDma */
+	bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
+
+	/* Initialize commont TX ring structures */
+	priv->tx_bds = priv->base + priv->hw_params->tdma_offset;
+	priv->num_tx_bds = TOTAL_DESC;
+	priv->tx_cbs = kzalloc(priv->num_tx_bds * sizeof(struct enet_cb),
+				GFP_KERNEL);
+	if (!priv->tx_cbs) {
+		bcmgenet_fini_dma(priv);
+		return -ENOMEM;
+	}
+
+	/* initialize multi xmit queue */
+	bcmgenet_init_multiq(priv->dev);
+
+	/* initialize special ring 16 */
+	bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_DEFAULT_BD_CNT,
+			priv->hw_params->tx_queues * priv->hw_params->bds_cnt,
+			TOTAL_DESC);
+
+	return 0;
+}
+
+/* NAPI polling method*/
+static int bcmgenet_poll(struct napi_struct *napi, int budget)
+{
+	struct bcmgenet_priv *priv = container_of(napi,
+			struct bcmgenet_priv, napi);
+	unsigned int work_done;
+
+	/* tx reclaim */
+	bcmgenet_tx_reclaim(priv->dev, &priv->tx_rings[DESC_INDEX]);
+
+	work_done = bcmgenet_desc_rx(priv, budget);
+
+	/* Advancing our consumer index*/
+	priv->rx_c_index += work_done;
+	priv->rx_c_index &= DMA_C_INDEX_MASK;
+	bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
+				priv->rx_c_index, RDMA_CONS_INDEX);
+	if (work_done < budget) {
+		napi_complete(napi);
+		bcmgenet_intrl2_0_writel(priv,
+			UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_CLEAR);
+	}
+
+	return work_done;
+}
+
+/* Interrupt bottom half */
+static void bcmgenet_irq_task(struct work_struct *work)
+{
+	struct bcmgenet_priv *priv = container_of(
+			work, struct bcmgenet_priv, bcmgenet_irq_work);
+
+	netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
+
+	/* Link UP/DOWN event */
+	if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
+		(priv->irq0_stat & (UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN))) {
+		phy_mac_interrupt(priv->phydev,
+			priv->irq0_stat & UMAC_IRQ_LINK_UP);
+		priv->irq0_stat &= ~(UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN);
+	}
+}
+
+/* bcmgenet_isr1: interrupt handler for ring buffer. */
+static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
+{
+	struct bcmgenet_priv *priv = dev_id;
+	unsigned int index;
+
+	/* Save irq status for bottom-half processing. */
+	priv->irq1_stat =
+		bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
+		~priv->int1_mask;
+	/* clear inerrupts*/
+	bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
+
+	netif_dbg(priv, intr, priv->dev,
+		"%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
+	/* Check the MBDONE interrupts.
+	 * packet is done, reclaim descriptors
+	 */
+	if (priv->irq1_stat & 0x0000ffff) {
+		index = 0;
+		for (index = 0; index < 16; index++) {
+			if (priv->irq1_stat & (1 << index))
+				bcmgenet_tx_reclaim(priv->dev,
+						&priv->tx_rings[index]);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+/* bcmgenet_isr0: Handle various interrupts. */
+static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
+{
+	struct bcmgenet_priv *priv = dev_id;
+
+	/* Save irq status for bottom-half processing. */
+	priv->irq0_stat =
+		bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
+		~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
+	/* clear inerrupts*/
+	bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
+
+	netif_dbg(priv, intr, priv->dev,
+		"IRQ=0x%x\n", priv->irq0_stat);
+
+	if (priv->irq0_stat & (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE)) {
+		/* We use NAPI(software interrupt throttling, if
+		 * Rx Descriptor throttling is not used.
+		 * Disable interrupt, will be enabled in the poll method.
+		 */
+		if (likely(napi_schedule_prep(&priv->napi))) {
+			bcmgenet_intrl2_0_writel(priv,
+				UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_SET);
+			__napi_schedule(&priv->napi);
+		}
+	}
+	if (priv->irq0_stat &
+			(UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE)) {
+		/* Tx reclaim */
+		bcmgenet_tx_reclaim(priv->dev, &priv->tx_rings[DESC_INDEX]);
+	}
+	if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R |
+				UMAC_IRQ_PHY_DET_F |
+				UMAC_IRQ_LINK_UP |
+				UMAC_IRQ_LINK_DOWN |
+				UMAC_IRQ_HFB_SM |
+				UMAC_IRQ_HFB_MM |
+				UMAC_IRQ_MPD_R)) {
+		/* all other interested interrupts handled in bottom half */
+		schedule_work(&priv->bcmgenet_irq_work);
+	}
+
+	if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
+		priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
+		priv->irq0_stat &= ~(UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
+		wake_up(&priv->wq);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
+{
+	u32 reg;
+
+	reg = bcmgenet_rbuf_ctrl_get(priv);
+	reg |= BIT(1);
+	bcmgenet_rbuf_ctrl_set(priv, reg);
+	udelay(10);
+
+	reg &= ~BIT(1);
+	bcmgenet_rbuf_ctrl_set(priv, reg);
+	udelay(10);
+}
+
+static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
+				  unsigned char *addr)
+{
+	bcmgenet_umac_writel(priv, (addr[0] << 24) | (addr[1] << 16) |
+			(addr[2] << 8) | addr[3], UMAC_MAC0);
+	bcmgenet_umac_writel(priv, (addr[4] << 8) | addr[5], UMAC_MAC1);
+}
+
+static int bcmgenet_wol_resume(struct bcmgenet_priv *priv)
+{
+	int ret;
+
+	/* From WOL-enabled suspend, switch to regular clock */
+	clk_disable(priv->clk_wol);
+	/* init umac registers to synchronize s/w with h/w */
+	ret = init_umac(priv);
+	if (ret)
+		return ret;
+
+	phy_init_hw(priv->phydev);
+	/* Speed settings must be restored */
+	bcmgenet_mii_config(priv->dev);
+
+	return 0;
+}
+
+/* Returns a reusable dma control register value */
+static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
+{
+	u32 reg;
+	u32 dma_ctrl;
+
+	/* disable DMA */
+	dma_ctrl = 1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT) | DMA_EN;
+	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	reg &= ~dma_ctrl;
+	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+
+	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+	reg &= ~dma_ctrl;
+	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+	bcmgenet_umac_writel(priv, 1, UMAC_TX_FLUSH);
+	udelay(10);
+	bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
+
+	return dma_ctrl;
+}
+
+static void bcmgenet_enable_dma(struct bcmgenet_priv *priv, u32 dma_ctrl)
+{
+	u32 reg;
+
+	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+	reg |= dma_ctrl;
+	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	reg |= dma_ctrl;
+	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+}
+
+static int bcmgenet_open(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	unsigned long dma_ctrl;
+	u32 reg;
+	int ret;
+
+	netif_dbg(priv, ifup, dev, "bcmgenet_open\n");
+
+	/* Turn on the clock */
+	if (!IS_ERR(priv->clk))
+		clk_prepare_enable(priv->clk);
+
+	/* take MAC out of reset */
+	bcmgenet_umac_reset(priv);
+
+	ret = init_umac(priv);
+	if (ret)
+		goto err_clk_disable;
+
+	/* disable ethernet MAC while updating its registers */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg &= ~(CMD_TX_EN | CMD_RX_EN);
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	bcmgenet_set_hw_addr(priv, dev->dev_addr);
+
+	if (priv->wol_enabled) {
+		ret = bcmgenet_wol_resume(priv);
+		if (ret)
+			return ret;
+	}
+
+	if (phy_is_internal(priv->phydev)) {
+		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+		reg |= EXT_ENERGY_DET_MASK;
+		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+	}
+
+	/* Disable RX/TX DMA and flush TX queues */
+	dma_ctrl = bcmgenet_dma_disable(priv);
+
+	/* Reinitialize TDMA and RDMA and SW housekeeping */
+	ret = bcmgenet_init_dma(priv);
+	if (ret) {
+		netdev_err(dev, "failed to initialize DMA\n");
+		goto err_fini_dma;
+	}
+
+	/* Always enable ring 16 - descriptor ring */
+	bcmgenet_enable_dma(priv, dma_ctrl);
+
+	ret = request_irq(priv->irq0, bcmgenet_isr0, IRQF_SHARED,
+			dev->name, priv);
+	if (ret < 0) {
+		netdev_err(dev, "can't request IRQ %d\n", priv->irq0);
+		goto err_fini_dma;
+	}
+
+	ret = request_irq(priv->irq1, bcmgenet_isr1, IRQF_SHARED,
+				dev->name, priv);
+	if (ret < 0) {
+		netdev_err(dev, "can't request IRQ %d\n", priv->irq1);
+		goto err_irq0;
+	}
+
+	/* Start the network engine */
+	napi_enable(&priv->napi);
+
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg |= (CMD_TX_EN | CMD_RX_EN);
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	/* Make sure we reflect the value of CRC_CMD_FWD */
+	priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
+
+	device_set_wakeup_capable(&dev->dev, 1);
+
+	if (phy_is_internal(priv->phydev))
+		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
+
+	netif_tx_start_all_queues(dev);
+
+	phy_start(priv->phydev);
+
+	return 0;
+
+err_irq0:
+	free_irq(priv->irq0, dev);
+err_fini_dma:
+	bcmgenet_fini_dma(priv);
+err_clk_disable:
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
+{
+	int ret = 0;
+	int timeout = 0;
+	u32 reg;
+
+	/* Disable TDMA to stop add more frames in TX DMA */
+	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	reg &= ~DMA_EN;
+	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+
+	/* Check TDMA status register to confirm TDMA is disabled */
+	while (timeout++ < DMA_TIMEOUT_VAL) {
+		reg = bcmgenet_tdma_readl(priv, DMA_STATUS);
+		if (reg & DMA_DISABLED)
+			break;
+
+		udelay(1);
+	}
+
+	if (timeout == DMA_TIMEOUT_VAL) {
+		netdev_warn(priv->dev,
+			"Timed out while disabling TX DMA\n");
+		ret = -ETIMEDOUT;
+	}
+
+	/* Wait 10ms for packet drain in both tx and rx dma */
+	usleep_range(10000, 20000);
+
+	/* Disable RDMA */
+	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+	reg &= ~DMA_EN;
+	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+	timeout = 0;
+	/* Check RDMA status register to confirm RDMA is disabled */
+	while (timeout++ < DMA_TIMEOUT_VAL) {
+		reg = bcmgenet_rdma_readl(priv, DMA_STATUS);
+		if (reg & DMA_DISABLED)
+			break;
+
+		udelay(1);
+	}
+
+	if (timeout == DMA_TIMEOUT_VAL) {
+		netdev_warn(priv->dev,
+			"Timed out while disabling RX DMA\n");
+			ret = -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int bcmgenet_close(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int ret;
+	u32 reg;
+
+	netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
+
+	phy_stop(priv->phydev);
+
+	/* Disable MAC receive */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg &= ~CMD_RX_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	netif_tx_stop_all_queues(dev);
+
+	ret = bcmgenet_dma_teardown(priv);
+	if (ret)
+		return ret;
+
+	/* Disable MAC transmit. TX DMA disabled have to done before this */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg &= ~CMD_TX_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	napi_disable(&priv->napi);
+
+	/* tx reclaim */
+	bcmgenet_tx_reclaim_all(dev);
+	bcmgenet_fini_dma(priv);
+
+	free_irq(priv->irq0, priv);
+	free_irq(priv->irq1, priv);
+
+	/* Wait for pending work items to complete - we are stopping
+	 * the clock now. Since interrupts are disabled, no new work
+	 * will be scheduled.
+	 */
+	cancel_work_sync(&priv->bcmgenet_irq_work);
+
+	if (phy_is_internal(priv->phydev))
+		bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
+
+	if (priv->wol_enabled)
+		clk_enable(priv->clk_wol);
+
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static void bcmgenet_timeout(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");
+
+	dev->trans_start = jiffies;
+
+	dev->stats.tx_errors++;
+
+	netif_tx_wake_all_queues(dev);
+}
+
+#define MAX_MC_COUNT	16
+
+static inline void bcmgenet_set_mdf_addr(struct bcmgenet_priv *priv,
+					 unsigned char *addr,
+					 int *i,
+					 int *mc)
+{
+	u32 reg;
+
+	bcmgenet_umac_writel(priv,
+			addr[0] << 8 | addr[1], UMAC_MDF_ADDR + (*i * 4));
+	bcmgenet_umac_writel(priv,
+			addr[2] << 24 | addr[3] << 16 |
+			addr[4] << 8 | addr[5],
+			UMAC_MDF_ADDR + ((*i + 1) * 4));
+	reg = bcmgenet_umac_readl(priv, UMAC_MDF_CTRL);
+	reg |= (1 << (MAX_MC_COUNT - *mc));
+	bcmgenet_umac_writel(priv, reg, UMAC_MDF_CTRL);
+	*i += 2;
+	(*mc)++;
+}
+
+static void bcmgenet_set_rx_mode(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct netdev_hw_addr *ha;
+	int i, mc;
+	u32 reg;
+
+	netif_dbg(priv, hw, dev, "%s: %08X\n", __func__, dev->flags);
+
+	/* Promiscous mode */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	if (dev->flags & IFF_PROMISC) {
+		reg |= CMD_PROMISC;
+		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+		bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
+		return;
+	} else {
+		reg &= ~CMD_PROMISC;
+		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	}
+
+	/* UniMac doesn't support ALLMULTI */
+	if (dev->flags & IFF_ALLMULTI) {
+		netdev_warn(dev, "ALLMULTI is not supported\n");
+		return;
+	}
+
+	/* update MDF filter */
+	i = 0;
+	mc = 0;
+	/* Broadcast */
+	bcmgenet_set_mdf_addr(priv, dev->broadcast, &i, &mc);
+	/* my own address.*/
+	bcmgenet_set_mdf_addr(priv, dev->dev_addr, &i, &mc);
+	/* Unicast list*/
+	if (netdev_uc_count(dev) > (MAX_MC_COUNT - mc))
+		return;
+
+	if (!netdev_uc_empty(dev))
+		netdev_for_each_uc_addr(ha, dev)
+			bcmgenet_set_mdf_addr(priv, ha->addr, &i, &mc);
+	/* Multicast */
+	if (netdev_mc_empty(dev) || netdev_mc_count(dev) >= (MAX_MC_COUNT - mc))
+		return;
+
+	netdev_for_each_mc_addr(ha, dev)
+		bcmgenet_set_mdf_addr(priv, ha->addr, &i, &mc);
+}
+
+/* Set the hardware MAC address. */
+static int bcmgenet_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+
+	/* Setting the MAC address at the hardware level is not possible
+	 * without disabling the UniMAC RX/TX enable bits.
+	 */
+	if (netif_running(dev))
+		return -EBUSY;
+
+	ether_addr_copy(dev->dev_addr, addr->sa_data);
+
+	return 0;
+}
+
+static const struct net_device_ops bcmgenet_netdev_ops = {
+	.ndo_open		= bcmgenet_open,
+	.ndo_stop		= bcmgenet_close,
+	.ndo_start_xmit		= bcmgenet_xmit,
+	.ndo_tx_timeout		= bcmgenet_timeout,
+	.ndo_set_rx_mode	= bcmgenet_set_rx_mode,
+	.ndo_set_mac_address	= bcmgenet_set_mac_addr,
+	.ndo_do_ioctl		= bcmgenet_ioctl,
+	.ndo_set_features	= bcmgenet_set_features,
+};
+
+/* Array of GENET hardware parameters/characteristics */
+static struct bcmgenet_hw_params bcmgenet_hw_params[] = {
+	[GENET_V1] = {
+		.tx_queues = 0,
+		.rx_queues = 0,
+		.bds_cnt = 0,
+		.bp_in_en_shift = 16,
+		.bp_in_mask = 0xffff,
+		.hfb_filter_cnt = 16,
+		.qtag_mask = 0x1F,
+		.hfb_offset = 0x1000,
+		.rdma_offset = 0x2000,
+		.tdma_offset = 0x3000,
+		.words_per_bd = 2,
+	},
+	[GENET_V2] = {
+		.tx_queues = 4,
+		.rx_queues = 4,
+		.bds_cnt = 32,
+		.bp_in_en_shift = 16,
+		.bp_in_mask = 0xffff,
+		.hfb_filter_cnt = 16,
+		.qtag_mask = 0x1F,
+		.tbuf_offset = 0x0600,
+		.hfb_offset = 0x1000,
+		.hfb_reg_offset = 0x2000,
+		.rdma_offset = 0x3000,
+		.tdma_offset = 0x4000,
+		.words_per_bd = 2,
+		.flags = GENET_HAS_EXT,
+	},
+	[GENET_V3] = {
+		.tx_queues = 4,
+		.rx_queues = 4,
+		.bds_cnt = 32,
+		.bp_in_en_shift = 17,
+		.bp_in_mask = 0x1ffff,
+		.hfb_filter_cnt = 48,
+		.qtag_mask = 0x3F,
+		.tbuf_offset = 0x0600,
+		.hfb_offset = 0x8000,
+		.hfb_reg_offset = 0xfc00,
+		.rdma_offset = 0x10000,
+		.tdma_offset = 0x11000,
+		.words_per_bd = 2,
+		.flags = GENET_HAS_EXT | GENET_HAS_MDIO_INTR,
+	},
+	[GENET_V4] = {
+		.tx_queues = 4,
+		.rx_queues = 4,
+		.bds_cnt = 32,
+		.bp_in_en_shift = 17,
+		.bp_in_mask = 0x1ffff,
+		.hfb_filter_cnt = 48,
+		.qtag_mask = 0x3F,
+		.tbuf_offset = 0x0600,
+		.hfb_offset = 0x8000,
+		.hfb_reg_offset = 0xfc00,
+		.rdma_offset = 0x2000,
+		.tdma_offset = 0x4000,
+		.words_per_bd = 3,
+		.flags = GENET_HAS_40BITS | GENET_HAS_EXT | GENET_HAS_MDIO_INTR,
+	},
+};
+
+/* Infer hardware parameters from the detected GENET version */
+static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
+{
+	struct bcmgenet_hw_params *params;
+	u32 reg;
+	u8 major;
+
+	if (GENET_IS_V4(priv)) {
+		bcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;
+		genet_dma_ring_regs = genet_dma_ring_regs_v4;
+		priv->dma_rx_chk_bit = DMA_RX_CHK_V3PLUS;
+		priv->version = GENET_V4;
+	} else if (GENET_IS_V3(priv)) {
+		bcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;
+		genet_dma_ring_regs = genet_dma_ring_regs_v123;
+		priv->dma_rx_chk_bit = DMA_RX_CHK_V3PLUS;
+		priv->version = GENET_V3;
+	} else if (GENET_IS_V2(priv)) {
+		bcmgenet_dma_regs = bcmgenet_dma_regs_v2;
+		genet_dma_ring_regs = genet_dma_ring_regs_v123;
+		priv->dma_rx_chk_bit = DMA_RX_CHK_V12;
+		priv->version = GENET_V2;
+	} else if (GENET_IS_V1(priv)) {
+		bcmgenet_dma_regs = bcmgenet_dma_regs_v1;
+		genet_dma_ring_regs = genet_dma_ring_regs_v123;
+		priv->dma_rx_chk_bit = DMA_RX_CHK_V12;
+		priv->version = GENET_V1;
+	}
+
+	/* enum genet_version starts at 1 */
+	priv->hw_params = &bcmgenet_hw_params[priv->version];
+	params = priv->hw_params;
+
+	/* Read GENET HW version */
+	reg = bcmgenet_sys_readl(priv, SYS_REV_CTRL);
+	major = (reg >> 24 & 0x0f);
+	if (major == 5)
+		major = 4;
+	else if (major == 0)
+		major = 1;
+	if (major != priv->version) {
+		dev_err(&priv->pdev->dev,
+			"GENET version mismatch, got: %d, configured for: %d\n",
+			major, priv->version);
+	}
+
+	/* Print the GENET core version */
+	dev_info(&priv->pdev->dev, "GENET " GENET_VER_FMT,
+		major, (reg >> 16) & 0x0f, reg & 0xffff);
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	if (!(params->flags & GENET_HAS_40BITS))
+		pr_warn("GENET does not support 40-bits PA\n");
+#endif
+
+	pr_debug("Configuration for version: %d\n"
+		"TXq: %1d, RXq: %1d, BDs: %1d\n"
+		"BP << en: %2d, BP msk: 0x%05x\n"
+		"HFB count: %2d, QTAQ msk: 0x%05x\n"
+		"TBUF: 0x%04x, HFB: 0x%04x, HFBreg: 0x%04x\n"
+		"RDMA: 0x%05x, TDMA: 0x%05x\n"
+		"Words/BD: %d\n",
+		priv->version,
+		params->tx_queues, params->rx_queues, params->bds_cnt,
+		params->bp_in_en_shift, params->bp_in_mask,
+		params->hfb_filter_cnt, params->qtag_mask,
+		params->tbuf_offset, params->hfb_offset,
+		params->hfb_reg_offset,
+		params->rdma_offset, params->tdma_offset,
+		params->words_per_bd);
+}
+
+static const struct of_device_id bcmgenet_match[] = {
+	{ .compatible = "brcm,genet-v1", .data = (void *)GENET_V1 },
+	{ .compatible = "brcm,genet-v2", .data = (void *)GENET_V2 },
+	{ .compatible = "brcm,genet-v3", .data = (void *)GENET_V3 },
+	{ .compatible = "brcm,genet-v4", .data = (void *)GENET_V4 },
+	{ },
+};
+
+static int bcmgenet_probe(struct platform_device *pdev)
+{
+	struct device_node *dn = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct bcmgenet_priv *priv;
+	struct net_device *dev;
+	const void *macaddr;
+	struct resource *r;
+	int err = -EIO;
+
+	/* Up to GENET_MAX_MQ_CNT + 1 TX queues and a single RX queue */
+	dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1, 1);
+	if (!dev) {
+		dev_err(&pdev->dev, "can't allocate net device\n");
+		return -ENOMEM;
+	}
+
+	of_id = of_match_node(bcmgenet_match, dn);
+	if (!of_id)
+		return -EINVAL;
+
+	priv = netdev_priv(dev);
+	priv->irq0 = platform_get_irq(pdev, 0);
+	priv->irq1 = platform_get_irq(pdev, 1);
+	if (!priv->irq0 || !priv->irq1) {
+		dev_err(&pdev->dev, "can't find IRQs\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	macaddr = of_get_mac_address(dn);
+	if (!macaddr) {
+		dev_err(&pdev->dev, "can't find MAC address\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(priv->base)) {
+		err = PTR_ERR(priv->base);
+		goto err;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	dev_set_drvdata(&pdev->dev, dev);
+	ether_addr_copy(dev->dev_addr, macaddr);
+	dev->watchdog_timeo = 2 * HZ;
+	SET_ETHTOOL_OPS(dev, &bcmgenet_ethtool_ops);
+	dev->netdev_ops = &bcmgenet_netdev_ops;
+	netif_napi_add(dev, &priv->napi, bcmgenet_poll, 64);
+
+	priv->msg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT);
+
+	/* Set hardware features */
+	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
+		NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
+
+	/* Set the needed headroom to account for any possible
+	 * features enabling/disabling at runtime
+	 */
+	dev->needed_headroom += 64;
+
+	netdev_boot_setup_check(dev);
+
+	priv->dev = dev;
+	priv->pdev = pdev;
+	priv->version = (enum bcmgenet_version)of_id->data;
+
+	bcmgenet_set_hw_params(priv);
+
+	spin_lock_init(&priv->lock);
+	/* Mii wait queue */
+	init_waitqueue_head(&priv->wq);
+	/* Always use RX_BUF_LENGTH (2KB) buffer for all chips */
+	priv->rx_buf_len = RX_BUF_LENGTH;
+	INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
+
+	priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
+	if (IS_ERR(priv->clk))
+		dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
+
+	priv->clk_wol = devm_clk_get(&priv->pdev->dev, "enet-wol");
+	if (IS_ERR(priv->clk_wol))
+		dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
+
+	if (!IS_ERR(priv->clk))
+		clk_prepare_enable(priv->clk);
+
+	err = reset_umac(priv);
+	if (err)
+		goto err_clk_disable;
+
+	err = bcmgenet_mii_init(dev);
+	if (err)
+		goto err_clk_disable;
+
+	/* setup number of real queues  + 1 (GENET_V1 has 0 hardware queues
+	 * just the ring 16 descriptor based TX
+	 */
+	netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
+	netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
+
+	err = register_netdev(dev);
+	if (err)
+		goto err_clk_disable;
+
+	/* Turn off the main clock, WOL clock is handled separately */
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
+	return err;
+
+err_clk_disable:
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+err:
+	free_netdev(dev);
+	return err;
+}
+
+static int bcmgenet_remove(struct platform_device *pdev)
+{
+	struct bcmgenet_priv *priv = dev_to_priv(&pdev->dev);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+	unregister_netdev(priv->dev);
+	bcmgenet_mii_exit(priv->dev);
+	free_netdev(priv->dev);
+
+	return 0;
+}
+
+
+static struct platform_driver bcmgenet_driver = {
+	.probe	= bcmgenet_probe,
+	.remove	= bcmgenet_remove,
+	.driver	= {
+		.name	= "bcmgenet",
+		.owner	= THIS_MODULE,
+		.of_match_table = bcmgenet_match,
+	},
+};
+module_platform_driver(bcmgenet_driver);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom GENET Ethernet controller driver");
+MODULE_ALIAS("platform:bcmgenet");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
new file mode 100644
index 000000000000..a6758adefaab
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -0,0 +1,629 @@
+/*
+ * Copyright (c) 2014 Broadcom 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.
+ *
+ * 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 __BCMGENET_H__
+#define __BCMGENET_H__
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+
+/* total number of Buffer Descriptors, same for Rx/Tx */
+#define TOTAL_DESC				256
+
+/* which ring is descriptor based */
+#define DESC_INDEX				16
+
+/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
+ * 1536 is multiple of 256 bytes
+ */
+#define ENET_BRCM_TAG_LEN	6
+#define ENET_PAD		8
+#define ENET_MAX_MTU_SIZE	(ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
+				 ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
+#define DMA_MAX_BURST_LENGTH    0x10
+
+/* misc. configuration */
+#define CLEAR_ALL_HFB			0xFF
+#define DMA_FC_THRESH_HI		(TOTAL_DESC >> 4)
+#define DMA_FC_THRESH_LO		5
+
+/* 64B receive/transmit status block */
+struct status_64 {
+	u32	length_status;		/* length and peripheral status */
+	u32	ext_status;		/* Extended status*/
+	u32	rx_csum;		/* partial rx checksum */
+	u32	unused1[9];		/* unused */
+	u32	tx_csum_info;		/* Tx checksum info. */
+	u32	unused2[3];		/* unused */
+};
+
+/* Rx status bits */
+#define STATUS_RX_EXT_MASK		0x1FFFFF
+#define STATUS_RX_CSUM_MASK		0xFFFF
+#define STATUS_RX_CSUM_OK		0x10000
+#define STATUS_RX_CSUM_FR		0x20000
+#define STATUS_RX_PROTO_TCP		0
+#define STATUS_RX_PROTO_UDP		1
+#define STATUS_RX_PROTO_ICMP		2
+#define STATUS_RX_PROTO_OTHER		3
+#define STATUS_RX_PROTO_MASK		3
+#define STATUS_RX_PROTO_SHIFT		18
+#define STATUS_FILTER_INDEX_MASK	0xFFFF
+/* Tx status bits */
+#define STATUS_TX_CSUM_START_MASK	0X7FFF
+#define STATUS_TX_CSUM_START_SHIFT	16
+#define STATUS_TX_CSUM_PROTO_UDP	0x8000
+#define STATUS_TX_CSUM_OFFSET_MASK	0x7FFF
+#define STATUS_TX_CSUM_LV		0x80000000
+
+/* DMA Descriptor */
+#define DMA_DESC_LENGTH_STATUS	0x00	/* in bytes of data in buffer */
+#define DMA_DESC_ADDRESS_LO	0x04	/* lower bits of PA */
+#define DMA_DESC_ADDRESS_HI	0x08	/* upper 32 bits of PA, GENETv4+ */
+
+/* Rx/Tx common counter group */
+struct bcmgenet_pkt_counters {
+	u32	cnt_64;		/* RO Received/Transmited 64 bytes packet */
+	u32	cnt_127;	/* RO Rx/Tx 127 bytes packet */
+	u32	cnt_255;	/* RO Rx/Tx 65-255 bytes packet */
+	u32	cnt_511;	/* RO Rx/Tx 256-511 bytes packet */
+	u32	cnt_1023;	/* RO Rx/Tx 512-1023 bytes packet */
+	u32	cnt_1518;	/* RO Rx/Tx 1024-1518 bytes packet */
+	u32	cnt_mgv;	/* RO Rx/Tx 1519-1522 good VLAN packet */
+	u32	cnt_2047;	/* RO Rx/Tx 1522-2047 bytes packet*/
+	u32	cnt_4095;	/* RO Rx/Tx 2048-4095 bytes packet*/
+	u32	cnt_9216;	/* RO Rx/Tx 4096-9216 bytes packet*/
+};
+
+/* RSV, Receive Status Vector */
+struct bcmgenet_rx_counters {
+	struct  bcmgenet_pkt_counters pkt_cnt;
+	u32	pkt;		/* RO (0x428) Received pkt count*/
+	u32	bytes;		/* RO Received byte count */
+	u32	mca;		/* RO # of Received multicast pkt */
+	u32	bca;		/* RO # of Receive broadcast pkt */
+	u32	fcs;		/* RO # of Received FCS error  */
+	u32	cf;		/* RO # of Received control frame pkt*/
+	u32	pf;		/* RO # of Received pause frame pkt */
+	u32	uo;		/* RO # of unknown op code pkt */
+	u32	aln;		/* RO # of alignment error count */
+	u32	flr;		/* RO # of frame length out of range count */
+	u32	cde;		/* RO # of code error pkt */
+	u32	fcr;		/* RO # of carrier sense error pkt */
+	u32	ovr;		/* RO # of oversize pkt*/
+	u32	jbr;		/* RO # of jabber count */
+	u32	mtue;		/* RO # of MTU error pkt*/
+	u32	pok;		/* RO # of Received good pkt */
+	u32	uc;		/* RO # of unicast pkt */
+	u32	ppp;		/* RO # of PPP pkt */
+	u32	rcrc;		/* RO (0x470),# of CRC match pkt */
+};
+
+/* TSV, Transmit Status Vector */
+struct bcmgenet_tx_counters {
+	struct bcmgenet_pkt_counters pkt_cnt;
+	u32	pkts;		/* RO (0x4a8) Transmited pkt */
+	u32	mca;		/* RO # of xmited multicast pkt */
+	u32	bca;		/* RO # of xmited broadcast pkt */
+	u32	pf;		/* RO # of xmited pause frame count */
+	u32	cf;		/* RO # of xmited control frame count */
+	u32	fcs;		/* RO # of xmited FCS error count */
+	u32	ovr;		/* RO # of xmited oversize pkt */
+	u32	drf;		/* RO # of xmited deferral pkt */
+	u32	edf;		/* RO # of xmited Excessive deferral pkt*/
+	u32	scl;		/* RO # of xmited single collision pkt */
+	u32	mcl;		/* RO # of xmited multiple collision pkt*/
+	u32	lcl;		/* RO # of xmited late collision pkt */
+	u32	ecl;		/* RO # of xmited excessive collision pkt*/
+	u32	frg;		/* RO # of xmited fragments pkt*/
+	u32	ncl;		/* RO # of xmited total collision count */
+	u32	jbr;		/* RO # of xmited jabber count*/
+	u32	bytes;		/* RO # of xmited byte count */
+	u32	pok;		/* RO # of xmited good pkt */
+	u32	uc;		/* RO (0x0x4f0)# of xmited unitcast pkt */
+};
+
+struct bcmgenet_mib_counters {
+	struct bcmgenet_rx_counters rx;
+	struct bcmgenet_tx_counters tx;
+	u32	rx_runt_cnt;
+	u32	rx_runt_fcs;
+	u32	rx_runt_fcs_align;
+	u32	rx_runt_bytes;
+	u32	rbuf_ovflow_cnt;
+	u32	rbuf_err_cnt;
+	u32	mdf_err_cnt;
+};
+
+#define UMAC_HD_BKP_CTRL		0x004
+#define	 HD_FC_EN			(1 << 0)
+#define  HD_FC_BKOFF_OK			(1 << 1)
+#define  IPG_CONFIG_RX_SHIFT		2
+#define  IPG_CONFIG_RX_MASK		0x1F
+
+#define UMAC_CMD			0x008
+#define  CMD_TX_EN			(1 << 0)
+#define  CMD_RX_EN			(1 << 1)
+#define  UMAC_SPEED_10			0
+#define  UMAC_SPEED_100			1
+#define  UMAC_SPEED_1000		2
+#define  UMAC_SPEED_2500		3
+#define  CMD_SPEED_SHIFT		2
+#define  CMD_SPEED_MASK			3
+#define  CMD_PROMISC			(1 << 4)
+#define  CMD_PAD_EN			(1 << 5)
+#define  CMD_CRC_FWD			(1 << 6)
+#define  CMD_PAUSE_FWD			(1 << 7)
+#define  CMD_RX_PAUSE_IGNORE		(1 << 8)
+#define  CMD_TX_ADDR_INS		(1 << 9)
+#define  CMD_HD_EN			(1 << 10)
+#define  CMD_SW_RESET			(1 << 13)
+#define  CMD_LCL_LOOP_EN		(1 << 15)
+#define  CMD_AUTO_CONFIG		(1 << 22)
+#define  CMD_CNTL_FRM_EN		(1 << 23)
+#define  CMD_NO_LEN_CHK			(1 << 24)
+#define  CMD_RMT_LOOP_EN		(1 << 25)
+#define  CMD_PRBL_EN			(1 << 27)
+#define  CMD_TX_PAUSE_IGNORE		(1 << 28)
+#define  CMD_TX_RX_EN			(1 << 29)
+#define  CMD_RUNT_FILTER_DIS		(1 << 30)
+
+#define UMAC_MAC0			0x00C
+#define UMAC_MAC1			0x010
+#define UMAC_MAX_FRAME_LEN		0x014
+
+#define UMAC_TX_FLUSH			0x334
+
+#define UMAC_MIB_START			0x400
+
+#define UMAC_MDIO_CMD			0x614
+#define  MDIO_START_BUSY		(1 << 29)
+#define  MDIO_READ_FAIL			(1 << 28)
+#define  MDIO_RD			(2 << 26)
+#define  MDIO_WR			(1 << 26)
+#define  MDIO_PMD_SHIFT			21
+#define  MDIO_PMD_MASK			0x1F
+#define  MDIO_REG_SHIFT			16
+#define  MDIO_REG_MASK			0x1F
+
+#define UMAC_RBUF_OVFL_CNT		0x61C
+
+#define UMAC_MPD_CTRL			0x620
+#define  MPD_EN				(1 << 0)
+#define  MPD_PW_EN			(1 << 27)
+#define  MPD_MSEQ_LEN_SHIFT		16
+#define  MPD_MSEQ_LEN_MASK		0xFF
+
+#define UMAC_MPD_PW_MS			0x624
+#define UMAC_MPD_PW_LS			0x628
+#define UMAC_RBUF_ERR_CNT		0x634
+#define UMAC_MDF_ERR_CNT		0x638
+#define UMAC_MDF_CTRL			0x650
+#define UMAC_MDF_ADDR			0x654
+#define UMAC_MIB_CTRL			0x580
+#define  MIB_RESET_RX			(1 << 0)
+#define  MIB_RESET_RUNT			(1 << 1)
+#define  MIB_RESET_TX			(1 << 2)
+
+#define RBUF_CTRL			0x00
+#define  RBUF_64B_EN			(1 << 0)
+#define  RBUF_ALIGN_2B			(1 << 1)
+#define  RBUF_BAD_DIS			(1 << 2)
+
+#define RBUF_STATUS			0x0C
+#define  RBUF_STATUS_WOL		(1 << 0)
+#define  RBUF_STATUS_MPD_INTR_ACTIVE	(1 << 1)
+#define  RBUF_STATUS_ACPI_INTR_ACTIVE	(1 << 2)
+
+#define RBUF_CHK_CTRL			0x14
+#define  RBUF_RXCHK_EN			(1 << 0)
+#define  RBUF_SKIP_FCS			(1 << 4)
+
+#define RBUF_TBUF_SIZE_CTRL		0xb4
+
+#define RBUF_HFB_CTRL_V1		0x38
+#define  RBUF_HFB_FILTER_EN_SHIFT	16
+#define  RBUF_HFB_FILTER_EN_MASK	0xffff0000
+#define  RBUF_HFB_EN			(1 << 0)
+#define  RBUF_HFB_256B			(1 << 1)
+#define  RBUF_ACPI_EN			(1 << 2)
+
+#define RBUF_HFB_LEN_V1			0x3C
+#define  RBUF_FLTR_LEN_MASK		0xFF
+#define  RBUF_FLTR_LEN_SHIFT		8
+
+#define TBUF_CTRL			0x00
+#define TBUF_BP_MC			0x0C
+
+#define TBUF_CTRL_V1			0x80
+#define TBUF_BP_MC_V1			0xA0
+
+#define HFB_CTRL			0x00
+#define HFB_FLT_ENABLE_V3PLUS		0x04
+#define HFB_FLT_LEN_V2			0x04
+#define HFB_FLT_LEN_V3PLUS		0x1C
+
+/* uniMac intrl2 registers */
+#define INTRL2_CPU_STAT			0x00
+#define INTRL2_CPU_SET			0x04
+#define INTRL2_CPU_CLEAR		0x08
+#define INTRL2_CPU_MASK_STATUS		0x0C
+#define INTRL2_CPU_MASK_SET		0x10
+#define INTRL2_CPU_MASK_CLEAR		0x14
+
+/* INTRL2 instance 0 definitions */
+#define UMAC_IRQ_SCB			(1 << 0)
+#define UMAC_IRQ_EPHY			(1 << 1)
+#define UMAC_IRQ_PHY_DET_R		(1 << 2)
+#define UMAC_IRQ_PHY_DET_F		(1 << 3)
+#define UMAC_IRQ_LINK_UP		(1 << 4)
+#define UMAC_IRQ_LINK_DOWN		(1 << 5)
+#define UMAC_IRQ_UMAC			(1 << 6)
+#define UMAC_IRQ_UMAC_TSV		(1 << 7)
+#define UMAC_IRQ_TBUF_UNDERRUN		(1 << 8)
+#define UMAC_IRQ_RBUF_OVERFLOW		(1 << 9)
+#define UMAC_IRQ_HFB_SM			(1 << 10)
+#define UMAC_IRQ_HFB_MM			(1 << 11)
+#define UMAC_IRQ_MPD_R			(1 << 12)
+#define UMAC_IRQ_RXDMA_MBDONE		(1 << 13)
+#define UMAC_IRQ_RXDMA_PDONE		(1 << 14)
+#define UMAC_IRQ_RXDMA_BDONE		(1 << 15)
+#define UMAC_IRQ_TXDMA_MBDONE		(1 << 16)
+#define UMAC_IRQ_TXDMA_PDONE		(1 << 17)
+#define UMAC_IRQ_TXDMA_BDONE		(1 << 18)
+/* Only valid for GENETv3+ */
+#define UMAC_IRQ_MDIO_DONE		(1 << 23)
+#define UMAC_IRQ_MDIO_ERROR		(1 << 24)
+
+/* Register block offsets */
+#define GENET_SYS_OFF			0x0000
+#define GENET_GR_BRIDGE_OFF		0x0040
+#define GENET_EXT_OFF			0x0080
+#define GENET_INTRL2_0_OFF		0x0200
+#define GENET_INTRL2_1_OFF		0x0240
+#define GENET_RBUF_OFF			0x0300
+#define GENET_UMAC_OFF			0x0800
+
+/* SYS block offsets and register definitions */
+#define SYS_REV_CTRL			0x00
+#define SYS_PORT_CTRL			0x04
+#define  PORT_MODE_INT_EPHY		0
+#define  PORT_MODE_INT_GPHY		1
+#define  PORT_MODE_EXT_EPHY		2
+#define  PORT_MODE_EXT_GPHY		3
+#define  PORT_MODE_EXT_RVMII_25		(4 | BIT(4))
+#define  PORT_MODE_EXT_RVMII_50		4
+#define  LED_ACT_SOURCE_MAC		(1 << 9)
+
+#define SYS_RBUF_FLUSH_CTRL		0x08
+#define SYS_TBUF_FLUSH_CTRL		0x0C
+#define RBUF_FLUSH_CTRL_V1		0x04
+
+/* Ext block register offsets and definitions */
+#define EXT_EXT_PWR_MGMT		0x00
+#define  EXT_PWR_DOWN_BIAS		(1 << 0)
+#define  EXT_PWR_DOWN_DLL		(1 << 1)
+#define  EXT_PWR_DOWN_PHY		(1 << 2)
+#define  EXT_PWR_DN_EN_LD		(1 << 3)
+#define  EXT_ENERGY_DET			(1 << 4)
+#define  EXT_IDDQ_FROM_PHY		(1 << 5)
+#define  EXT_PHY_RESET			(1 << 8)
+#define  EXT_ENERGY_DET_MASK		(1 << 12)
+
+#define EXT_RGMII_OOB_CTRL		0x0C
+#define  RGMII_MODE_EN			(1 << 0)
+#define  RGMII_LINK			(1 << 4)
+#define  OOB_DISABLE			(1 << 5)
+#define  ID_MODE_DIS			(1 << 16)
+
+#define EXT_GPHY_CTRL			0x1C
+#define  EXT_CFG_IDDQ_BIAS		(1 << 0)
+#define  EXT_CFG_PWR_DOWN		(1 << 1)
+#define  EXT_GPHY_RESET			(1 << 5)
+
+/* DMA rings size */
+#define DMA_RING_SIZE			(0x40)
+#define DMA_RINGS_SIZE			(DMA_RING_SIZE * (DESC_INDEX + 1))
+
+/* DMA registers common definitions */
+#define DMA_RW_POINTER_MASK		0x1FF
+#define DMA_P_INDEX_DISCARD_CNT_MASK	0xFFFF
+#define DMA_P_INDEX_DISCARD_CNT_SHIFT	16
+#define DMA_BUFFER_DONE_CNT_MASK	0xFFFF
+#define DMA_BUFFER_DONE_CNT_SHIFT	16
+#define DMA_P_INDEX_MASK		0xFFFF
+#define DMA_C_INDEX_MASK		0xFFFF
+
+/* DMA ring size register */
+#define DMA_RING_SIZE_MASK		0xFFFF
+#define DMA_RING_SIZE_SHIFT		16
+#define DMA_RING_BUFFER_SIZE_MASK	0xFFFF
+
+/* DMA interrupt threshold register */
+#define DMA_INTR_THRESHOLD_MASK		0x00FF
+
+/* DMA XON/XOFF register */
+#define DMA_XON_THREHOLD_MASK		0xFFFF
+#define DMA_XOFF_THRESHOLD_MASK		0xFFFF
+#define DMA_XOFF_THRESHOLD_SHIFT	16
+
+/* DMA flow period register */
+#define DMA_FLOW_PERIOD_MASK		0xFFFF
+#define DMA_MAX_PKT_SIZE_MASK		0xFFFF
+#define DMA_MAX_PKT_SIZE_SHIFT		16
+
+
+/* DMA control register */
+#define DMA_EN				(1 << 0)
+#define DMA_RING_BUF_EN_SHIFT		0x01
+#define DMA_RING_BUF_EN_MASK		0xFFFF
+#define DMA_TSB_SWAP_EN			(1 << 20)
+
+/* DMA status register */
+#define DMA_DISABLED			(1 << 0)
+#define DMA_DESC_RAM_INIT_BUSY		(1 << 1)
+
+/* DMA SCB burst size register */
+#define DMA_SCB_BURST_SIZE_MASK		0x1F
+
+/* DMA activity vector register */
+#define DMA_ACTIVITY_VECTOR_MASK	0x1FFFF
+
+/* DMA backpressure mask register */
+#define DMA_BACKPRESSURE_MASK		0x1FFFF
+#define DMA_PFC_ENABLE			(1 << 31)
+
+/* DMA backpressure status register */
+#define DMA_BACKPRESSURE_STATUS_MASK	0x1FFFF
+
+/* DMA override register */
+#define DMA_LITTLE_ENDIAN_MODE		(1 << 0)
+#define DMA_REGISTER_MODE		(1 << 1)
+
+/* DMA timeout register */
+#define DMA_TIMEOUT_MASK		0xFFFF
+#define DMA_TIMEOUT_VAL			5000	/* micro seconds */
+
+/* TDMA rate limiting control register */
+#define DMA_RATE_LIMIT_EN_MASK		0xFFFF
+
+/* TDMA arbitration control register */
+#define DMA_ARBITER_MODE_MASK		0x03
+#define DMA_RING_BUF_PRIORITY_MASK	0x1F
+#define DMA_RING_BUF_PRIORITY_SHIFT	5
+#define DMA_RATE_ADJ_MASK		0xFF
+
+/* Tx/Rx Dma Descriptor common bits*/
+#define DMA_BUFLENGTH_MASK		0x0fff
+#define DMA_BUFLENGTH_SHIFT		16
+#define DMA_OWN				0x8000
+#define DMA_EOP				0x4000
+#define DMA_SOP				0x2000
+#define DMA_WRAP			0x1000
+/* Tx specific Dma descriptor bits */
+#define DMA_TX_UNDERRUN			0x0200
+#define DMA_TX_APPEND_CRC		0x0040
+#define DMA_TX_OW_CRC			0x0020
+#define DMA_TX_DO_CSUM			0x0010
+#define DMA_TX_QTAG_SHIFT		7
+
+/* Rx Specific Dma descriptor bits */
+#define DMA_RX_CHK_V3PLUS		0x8000
+#define DMA_RX_CHK_V12			0x1000
+#define DMA_RX_BRDCAST			0x0040
+#define DMA_RX_MULT			0x0020
+#define DMA_RX_LG			0x0010
+#define DMA_RX_NO			0x0008
+#define DMA_RX_RXER			0x0004
+#define DMA_RX_CRC_ERROR		0x0002
+#define DMA_RX_OV			0x0001
+#define DMA_RX_FI_MASK			0x001F
+#define DMA_RX_FI_SHIFT			0x0007
+#define DMA_DESC_ALLOC_MASK		0x00FF
+
+#define DMA_ARBITER_RR			0x00
+#define DMA_ARBITER_WRR			0x01
+#define DMA_ARBITER_SP			0x02
+
+struct enet_cb {
+	struct sk_buff      *skb;
+	void __iomem *bd_addr;
+	DEFINE_DMA_UNMAP_ADDR(dma_addr);
+	DEFINE_DMA_UNMAP_LEN(dma_len);
+};
+
+/* power management mode */
+enum bcmgenet_power_mode {
+	GENET_POWER_CABLE_SENSE = 0,
+	GENET_POWER_PASSIVE,
+};
+
+struct bcmgenet_priv;
+
+/* We support both runtime GENET detection and compile-time
+ * to optimize code-paths for a given hardware
+ */
+enum bcmgenet_version {
+	GENET_V1 = 1,
+	GENET_V2,
+	GENET_V3,
+	GENET_V4
+};
+
+#define GENET_IS_V1(p)	((p)->version == GENET_V1)
+#define GENET_IS_V2(p)	((p)->version == GENET_V2)
+#define GENET_IS_V3(p)	((p)->version == GENET_V3)
+#define GENET_IS_V4(p)	((p)->version == GENET_V4)
+
+/* Hardware flags */
+#define GENET_HAS_40BITS	(1 << 0)
+#define GENET_HAS_EXT		(1 << 1)
+#define GENET_HAS_MDIO_INTR	(1 << 2)
+
+/* BCMGENET hardware parameters, keep this structure nicely aligned
+ * since it is going to be used in hot paths
+ */
+struct bcmgenet_hw_params {
+	u8		tx_queues;
+	u8		rx_queues;
+	u8		bds_cnt;
+	u8		bp_in_en_shift;
+	u32		bp_in_mask;
+	u8		hfb_filter_cnt;
+	u8		qtag_mask;
+	u16		tbuf_offset;
+	u32		hfb_offset;
+	u32		hfb_reg_offset;
+	u32		rdma_offset;
+	u32		tdma_offset;
+	u32		words_per_bd;
+	u32		flags;
+};
+
+struct bcmgenet_tx_ring {
+	spinlock_t	lock;		/* ring lock */
+	unsigned int	index;		/* ring index */
+	unsigned int	queue;		/* queue index */
+	struct enet_cb	*cbs;		/* tx ring buffer control block*/
+	unsigned int	size;		/* size of each tx ring */
+	unsigned int	c_index;	/* last consumer index of each ring*/
+	unsigned int	free_bds;	/* # of free bds for each ring */
+	unsigned int	write_ptr;	/* Tx ring write pointer SW copy */
+	unsigned int	prod_index;	/* Tx ring producer index SW copy */
+	unsigned int	cb_ptr;		/* Tx ring initial CB ptr */
+	unsigned int	end_ptr;	/* Tx ring end CB ptr */
+	void (*int_enable)(struct bcmgenet_priv *priv,
+				struct bcmgenet_tx_ring *);
+	void (*int_disable)(struct bcmgenet_priv *priv,
+				struct bcmgenet_tx_ring *);
+};
+
+/* device context */
+struct bcmgenet_priv {
+	void __iomem *base;
+	enum bcmgenet_version version;
+	struct net_device *dev;
+	spinlock_t lock;
+	u32 int0_mask;
+	u32 int1_mask;
+
+	/* NAPI for descriptor based rx */
+	struct napi_struct napi ____cacheline_aligned;
+
+	/* transmit variables */
+	void __iomem *tx_bds;
+	struct enet_cb *tx_cbs;
+	unsigned int num_tx_bds;
+
+	struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
+
+	/* receive variables */
+	void __iomem *rx_bds;
+	void __iomem *rx_bd_assign_ptr;
+	int rx_bd_assign_index;
+	struct enet_cb *rx_cbs;
+	unsigned int num_rx_bds;
+	unsigned int rx_buf_len;
+	unsigned int rx_read_ptr;
+	unsigned int rx_c_index;
+
+	/* other misc variables */
+	struct bcmgenet_hw_params *hw_params;
+
+	/* MDIO bus variables */
+	wait_queue_head_t wq;
+	struct phy_device *phydev;
+	struct device_node *phy_dn;
+	struct mii_bus *mii_bus;
+
+	/* PHY device variables */
+	int old_duplex;
+	int old_link;
+	int old_pause;
+	phy_interface_t phy_interface;
+	int phy_addr;
+	int ext_phy;
+
+	/* Interrupt variables */
+	struct work_struct bcmgenet_irq_work;
+	int irq0;
+	int irq1;
+	unsigned int irq0_stat;
+	unsigned int irq1_stat;
+
+	/* HW descriptors/checksum variables */
+	bool desc_64b_en;
+	bool desc_rxchk_en;
+	bool crc_fwd_en;
+
+	unsigned int dma_rx_chk_bit;
+
+	u32 msg_enable;
+
+	struct clk *clk;
+	struct platform_device *pdev;
+
+	/* WOL */
+	unsigned long wol_enabled;
+	struct clk *clk_wol;
+	u32 wolopts;
+
+	struct bcmgenet_mib_counters mib;
+};
+
+#define GENET_IO_MACRO(name, offset)					\
+static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv,	\
+					u32 off)			\
+{									\
+	return __raw_readl(priv->base + offset + off);			\
+}									\
+static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv,	\
+					u32 val, u32 off)		\
+{									\
+	__raw_writel(val, priv->base + offset + off);			\
+}
+
+GENET_IO_MACRO(ext, GENET_EXT_OFF);
+GENET_IO_MACRO(umac, GENET_UMAC_OFF);
+GENET_IO_MACRO(sys, GENET_SYS_OFF);
+
+/* interrupt l2 registers accessors */
+GENET_IO_MACRO(intrl2_0, GENET_INTRL2_0_OFF);
+GENET_IO_MACRO(intrl2_1, GENET_INTRL2_1_OFF);
+
+/* HFB register accessors  */
+GENET_IO_MACRO(hfb, priv->hw_params->hfb_offset);
+
+/* GENET v2+ HFB control and filter len helpers */
+GENET_IO_MACRO(hfb_reg, priv->hw_params->hfb_reg_offset);
+
+/* RBUF register accessors */
+GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
+
+/* MDIO routines */
+int bcmgenet_mii_init(struct net_device *dev);
+int bcmgenet_mii_config(struct net_device *dev);
+void bcmgenet_mii_exit(struct net_device *dev);
+void bcmgenet_mii_reset(struct net_device *dev);
+
+#endif /* __BCMGENET_H__ */
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
new file mode 100644
index 000000000000..4608673beaff
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -0,0 +1,464 @@
+/*
+ * Broadcom GENET MDIO routines
+ *
+ * Copyright (c) 2014 Broadcom 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.
+ *
+ * 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/types.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/brcmphy.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+
+#include "bcmgenet.h"
+
+/* read a value from the MII */
+static int bcmgenet_mii_read(struct mii_bus *bus, int phy_id, int location)
+{
+	int ret;
+	struct net_device *dev = bus->priv;
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 reg;
+
+	bcmgenet_umac_writel(priv, (MDIO_RD | (phy_id << MDIO_PMD_SHIFT) |
+			(location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
+	/* Start MDIO transaction*/
+	reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
+	reg |= MDIO_START_BUSY;
+	bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
+	wait_event_timeout(priv->wq,
+			!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
+				& MDIO_START_BUSY),
+			HZ / 100);
+	ret = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
+
+	if (ret & MDIO_READ_FAIL)
+		return -EIO;
+
+	return ret & 0xffff;
+}
+
+/* write a value to the MII */
+static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
+			int location, u16 val)
+{
+	struct net_device *dev = bus->priv;
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 reg;
+
+	bcmgenet_umac_writel(priv, (MDIO_WR | (phy_id << MDIO_PMD_SHIFT) |
+			(location << MDIO_REG_SHIFT) | (0xffff & val)),
+			UMAC_MDIO_CMD);
+	reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
+	reg |= MDIO_START_BUSY;
+	bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
+	wait_event_timeout(priv->wq,
+			!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
+				MDIO_START_BUSY),
+			HZ / 100);
+
+	return 0;
+}
+
+/* setup netdev link state when PHY link status change and
+ * update UMAC and RGMII block when link up
+ */
+static void bcmgenet_mii_setup(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+	u32 reg, cmd_bits = 0;
+	unsigned int status_changed = 0;
+
+	if (priv->old_link != phydev->link) {
+		status_changed = 1;
+		priv->old_link = phydev->link;
+	}
+
+	if (phydev->link) {
+		/* program UMAC and RGMII block based on established link
+		 * speed, pause, and duplex.
+		 * the speed set in umac->cmd tell RGMII block which clock
+		 * 25MHz(100Mbps)/125MHz(1Gbps) to use for transmit.
+		 * receive clock is provided by PHY.
+		 */
+		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
+		reg &= ~OOB_DISABLE;
+		reg |= RGMII_LINK;
+		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+
+		/* speed */
+		if (phydev->speed == SPEED_1000)
+			cmd_bits = UMAC_SPEED_1000;
+		else if (phydev->speed == SPEED_100)
+			cmd_bits = UMAC_SPEED_100;
+		else
+			cmd_bits = UMAC_SPEED_10;
+		cmd_bits <<= CMD_SPEED_SHIFT;
+
+		if (priv->old_duplex != phydev->duplex) {
+			status_changed = 1;
+			priv->old_duplex = phydev->duplex;
+		}
+
+		/* duplex */
+		if (phydev->duplex != DUPLEX_FULL)
+			cmd_bits |= CMD_HD_EN;
+
+		if (priv->old_pause != phydev->pause) {
+			status_changed = 1;
+			priv->old_pause = phydev->pause;
+		}
+
+		/* pause capability */
+		if (!phydev->pause)
+			cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
+
+		reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+		reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
+			       CMD_HD_EN |
+			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
+		reg |= cmd_bits;
+		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	}
+
+	if (status_changed)
+		phy_print_status(phydev);
+}
+
+void bcmgenet_mii_reset(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	if (priv->phydev) {
+		phy_init_hw(priv->phydev);
+		phy_start_aneg(priv->phydev);
+	}
+}
+
+static void bcmgenet_ephy_power_up(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 reg = 0;
+
+	/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
+	if (!GENET_IS_V4(priv))
+		return;
+
+	reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
+	reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
+	reg |= EXT_GPHY_RESET;
+	bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
+	mdelay(2);
+
+	reg &= ~EXT_GPHY_RESET;
+	bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
+	udelay(20);
+}
+
+static void bcmgenet_internal_phy_setup(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 reg;
+
+	/* Power up EPHY */
+	bcmgenet_ephy_power_up(dev);
+	/* enable APD */
+	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+	reg |= EXT_PWR_DN_EN_LD;
+	bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+	bcmgenet_mii_reset(dev);
+}
+
+static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
+{
+	u32 reg;
+
+	/* Speed settings are set in bcmgenet_mii_setup() */
+	reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
+	reg |= LED_ACT_SOURCE_MAC;
+	bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
+}
+
+int bcmgenet_mii_config(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+	struct device *kdev = &priv->pdev->dev;
+	const char *phy_name = NULL;
+	u32 id_mode_dis = 0;
+	u32 port_ctrl;
+	u32 reg;
+
+	priv->ext_phy = !phy_is_internal(priv->phydev) &&
+			(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
+
+	if (phy_is_internal(priv->phydev))
+		priv->phy_interface = PHY_INTERFACE_MODE_NA;
+
+	switch (priv->phy_interface) {
+	case PHY_INTERFACE_MODE_NA:
+	case PHY_INTERFACE_MODE_MOCA:
+		/* Irrespective of the actually configured PHY speed (100 or
+		 * 1000) GENETv4 only has an internal GPHY so we will just end
+		 * up masking the Gigabit features from what we support, not
+		 * switching to the EPHY
+		 */
+		if (GENET_IS_V4(priv))
+			port_ctrl = PORT_MODE_INT_GPHY;
+		else
+			port_ctrl = PORT_MODE_INT_EPHY;
+
+		bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
+
+		if (phy_is_internal(priv->phydev)) {
+			phy_name = "internal PHY";
+			bcmgenet_internal_phy_setup(dev);
+		} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+			phy_name = "MoCA";
+			bcmgenet_moca_phy_setup(priv);
+		}
+		break;
+
+	case PHY_INTERFACE_MODE_MII:
+		phy_name = "external MII";
+		phydev->supported &= PHY_BASIC_FEATURES;
+		bcmgenet_sys_writel(priv,
+				PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
+		break;
+
+	case PHY_INTERFACE_MODE_REVMII:
+		phy_name = "external RvMII";
+		/* of_mdiobus_register took care of reading the 'max-speed'
+		 * PHY property for us, effectively limiting the PHY supported
+		 * capabilities, use that knowledge to also configure the
+		 * Reverse MII interface correctly.
+		 */
+		if ((priv->phydev->supported & PHY_BASIC_FEATURES) ==
+				PHY_BASIC_FEATURES)
+			port_ctrl = PORT_MODE_EXT_RVMII_25;
+		else
+			port_ctrl = PORT_MODE_EXT_RVMII_50;
+		bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+		/* RGMII_NO_ID: TXC transitions at the same time as TXD
+		 *		(requires PCB or receiver-side delay)
+		 * RGMII:	Add 2ns delay on TXC (90 degree shift)
+		 *
+		 * ID is implicitly disabled for 100Mbps (RG)MII operation.
+		 */
+		id_mode_dis = BIT(16);
+		/* fall through */
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		if (id_mode_dis)
+			phy_name = "external RGMII (no delay)";
+		else
+			phy_name = "external RGMII (TX delay)";
+		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
+		reg |= RGMII_MODE_EN | id_mode_dis;
+		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+		bcmgenet_sys_writel(priv,
+				PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
+		break;
+	default:
+		dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
+		return -EINVAL;
+	}
+
+	dev_info(kdev, "configuring instance for %s\n", phy_name);
+
+	return 0;
+}
+
+static int bcmgenet_mii_probe(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct phy_device *phydev;
+	unsigned int phy_flags;
+	int ret;
+
+	if (priv->phydev) {
+		pr_info("PHY already attached\n");
+		return 0;
+	}
+
+	if (priv->phy_dn)
+		phydev = of_phy_connect(dev, priv->phy_dn,
+					bcmgenet_mii_setup, 0,
+					priv->phy_interface);
+	else
+		phydev = of_phy_connect_fixed_link(dev,
+					bcmgenet_mii_setup,
+					priv->phy_interface);
+
+	if (!phydev) {
+		pr_err("could not attach to PHY\n");
+		return -ENODEV;
+	}
+
+	priv->old_link = -1;
+	priv->old_duplex = -1;
+	priv->old_pause = -1;
+	priv->phydev = phydev;
+
+	/* Configure port multiplexer based on what the probed PHY device since
+	 * reading the 'max-speed' property determines the maximum supported
+	 * PHY speed which is needed for bcmgenet_mii_config() to configure
+	 * things appropriately.
+	 */
+	ret = bcmgenet_mii_config(dev);
+	if (ret) {
+		phy_disconnect(priv->phydev);
+		return ret;
+	}
+
+	phy_flags = PHY_BRCM_100MBPS_WAR;
+
+	/* workarounds are only needed for 100Mpbs PHYs, and
+	 * never on GENET V1 hardware
+	 */
+	if ((phydev->supported & PHY_GBIT_FEATURES) || GENET_IS_V1(priv))
+		phy_flags = 0;
+
+	phydev->dev_flags |= phy_flags;
+	phydev->advertising = phydev->supported;
+
+	/* The internal PHY has its link interrupts routed to the
+	 * Ethernet MAC ISRs
+	 */
+	if (phy_is_internal(priv->phydev))
+		priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
+	else
+		priv->mii_bus->irq[phydev->addr] = PHY_POLL;
+
+	pr_info("attached PHY at address %d [%s]\n",
+			phydev->addr, phydev->drv->name);
+
+	return 0;
+}
+
+static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
+{
+	struct mii_bus *bus;
+
+	if (priv->mii_bus)
+		return 0;
+
+	priv->mii_bus = mdiobus_alloc();
+	if (!priv->mii_bus) {
+		pr_err("failed to allocate\n");
+		return -ENOMEM;
+	}
+
+	bus = priv->mii_bus;
+	bus->priv = priv->dev;
+	bus->name = "bcmgenet MII bus";
+	bus->parent = &priv->pdev->dev;
+	bus->read = bcmgenet_mii_read;
+	bus->write = bcmgenet_mii_write;
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
+			priv->pdev->name, priv->pdev->id);
+
+	bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!bus->irq) {
+		mdiobus_free(priv->mii_bus);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
+{
+	struct device_node *dn = priv->pdev->dev.of_node;
+	struct device *kdev = &priv->pdev->dev;
+	struct device_node *mdio_dn;
+	char *compat;
+	int ret;
+
+	compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
+	if (!compat)
+		return -ENOMEM;
+
+	mdio_dn = of_find_compatible_node(dn, NULL, compat);
+	kfree(compat);
+	if (!mdio_dn) {
+		dev_err(kdev, "unable to find MDIO bus node\n");
+		return -ENODEV;
+	}
+
+	ret = of_mdiobus_register(priv->mii_bus, mdio_dn);
+	if (ret) {
+		dev_err(kdev, "failed to register MDIO bus\n");
+		return ret;
+	}
+
+	/* Fetch the PHY phandle */
+	priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
+
+	/* Get the link mode */
+	priv->phy_interface = of_get_phy_mode(dn);
+
+	return 0;
+}
+
+int bcmgenet_mii_init(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int ret;
+
+	ret = bcmgenet_mii_alloc(priv);
+	if (ret)
+		return ret;
+
+	ret = bcmgenet_mii_of_init(priv);
+	if (ret)
+		goto out_free;
+
+	ret = bcmgenet_mii_probe(dev);
+	if (ret)
+		goto out;
+
+	return 0;
+
+out:
+	mdiobus_unregister(priv->mii_bus);
+out_free:
+	kfree(priv->mii_bus->irq);
+	mdiobus_free(priv->mii_bus);
+	return ret;
+}
+
+void bcmgenet_mii_exit(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	mdiobus_unregister(priv->mii_bus);
+	kfree(priv->mii_bus->irq);
+	mdiobus_free(priv->mii_bus);
+}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 3167ed6593b0..e12735fbdcdb 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6843,8 +6843,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 
 		work_mask |= opaque_key;
 
-		if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
-		    (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+		if (desc->err_vlan & RXD_ERR_MASK) {
 		drop_it:
 			tg3_recycle_rx(tnapi, tpr, opaque_key,
 				       desc_idx, *post_ptr);
@@ -11362,12 +11361,10 @@ static bool tg3_enable_msix(struct tg3 *tp)
 		msix_ent[i].vector = 0;
 	}
 
-	rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt);
+	rc = pci_enable_msix_range(tp->pdev, msix_ent, 1, tp->irq_cnt);
 	if (rc < 0) {
 		return false;
-	} else if (rc != 0) {
-		if (pci_enable_msix(tp->pdev, msix_ent, rc))
-			return false;
+	} else if (rc < tp->irq_cnt) {
 		netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n",
 			      tp->irq_cnt, rc);
 		tp->irq_cnt = rc;
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index ef472385bce4..04321e5a356e 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2608,7 +2608,11 @@ struct tg3_rx_buffer_desc {
 #define RXD_ERR_TOO_SMALL		0x00400000
 #define RXD_ERR_NO_RESOURCES		0x00800000
 #define RXD_ERR_HUGE_FRAME		0x01000000
-#define RXD_ERR_MASK			0xffff0000
+
+#define RXD_ERR_MASK	(RXD_ERR_BAD_CRC | RXD_ERR_COLLISION |		\
+			 RXD_ERR_LINK_LOST | RXD_ERR_PHY_DECODE |	\
+			 RXD_ERR_MAC_ABRT | RXD_ERR_TOO_SMALL |		\
+			 RXD_ERR_NO_RESOURCES | RXD_ERR_HUGE_FRAME)
 
 	u32				reserved;
 	u32				opaque;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index cf64f3d0b60d..aeec9ccc0b39 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -707,7 +707,8 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 		else
 			skb_checksum_none_assert(skb);
 
-		if (flags & BNA_CQ_EF_VLAN)
+		if ((flags & BNA_CQ_EF_VLAN) &&
+		    (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cmpl->vlan_tag));
 
 		if (BNAD_RXBUF_IS_SK_BUFF(unmap_q->type))
@@ -2094,7 +2095,9 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 		rx_config->q1_buf_size = BFI_SMALL_RXBUF_SIZE;
 	}
 
-	rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
+	rx_config->vlan_strip_status =
+		(bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) ?
+		BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED;
 }
 
 static void
@@ -2666,9 +2669,11 @@ bnad_enable_msix(struct bnad *bnad)
 	for (i = 0; i < bnad->msix_num; i++)
 		bnad->msix_table[i].entry = i;
 
-	ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, bnad->msix_num);
-	if (ret > 0) {
-		/* Not enough MSI-X vectors. */
+	ret = pci_enable_msix_range(bnad->pcidev, bnad->msix_table,
+				    1, bnad->msix_num);
+	if (ret < 0) {
+		goto intx_mode;
+	} else if (ret < bnad->msix_num) {
 		pr_warn("BNA: %d MSI-X vectors allocated < %d requested\n",
 			ret, bnad->msix_num);
 
@@ -2681,18 +2686,11 @@ bnad_enable_msix(struct bnad *bnad)
 		bnad->msix_num = BNAD_NUM_TXQ + BNAD_NUM_RXP +
 			 BNAD_MAILBOX_MSIX_VECTORS;
 
-		if (bnad->msix_num > ret)
-			goto intx_mode;
-
-		/* Try once more with adjusted numbers */
-		/* If this fails, fall back to INTx */
-		ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
-				      bnad->msix_num);
-		if (ret)
+		if (bnad->msix_num > ret) {
+			pci_disable_msix(bnad->pcidev);
 			goto intx_mode;
-
-	} else if (ret < 0)
-		goto intx_mode;
+		}
+	}
 
 	pci_intx(bnad->pcidev, 0);
 
@@ -3245,11 +3243,6 @@ bnad_set_rx_mode(struct net_device *netdev)
 			BNA_RXMODE_ALLMULTI;
 	bna_rx_mode_set(bnad->rx_info[0].rx, new_mode, mode_mask, NULL);
 
-	if (bnad->cfg_flags & BNAD_CF_PROMISC)
-		bna_rx_vlan_strip_disable(bnad->rx_info[0].rx);
-	else
-		bna_rx_vlan_strip_enable(bnad->rx_info[0].rx);
-
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -3374,6 +3367,27 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
 	return 0;
 }
 
+static int bnad_set_features(struct net_device *dev, netdev_features_t features)
+{
+	struct bnad *bnad = netdev_priv(dev);
+	netdev_features_t changed = features ^ dev->features;
+
+	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(dev)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+
+		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+			bna_rx_vlan_strip_enable(bnad->rx_info[0].rx);
+		else
+			bna_rx_vlan_strip_disable(bnad->rx_info[0].rx);
+
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void
 bnad_netpoll(struct net_device *netdev)
@@ -3421,6 +3435,7 @@ static const struct net_device_ops bnad_netdev_ops = {
 	.ndo_change_mtu		= bnad_change_mtu,
 	.ndo_vlan_rx_add_vid    = bnad_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid   = bnad_vlan_rx_kill_vid,
+	.ndo_set_features	= bnad_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller    = bnad_netpoll
 #endif
@@ -3433,14 +3448,14 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
 
 	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX;
+		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX |
+		NETIF_F_HW_VLAN_CTAG_RX;
 
 	netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA |
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		NETIF_F_TSO | NETIF_F_TSO6;
 
-	netdev->features |= netdev->hw_features |
-		NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	if (using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 45d77334d7d9..07bbb711b7e5 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3088,30 +3088,22 @@ static int cxgb_enable_msix(struct adapter *adap)
 {
 	struct msix_entry entries[SGE_QSETS + 1];
 	int vectors;
-	int i, err;
+	int i;
 
 	vectors = ARRAY_SIZE(entries);
 	for (i = 0; i < vectors; ++i)
 		entries[i].entry = i;
 
-	while ((err = pci_enable_msix(adap->pdev, entries, vectors)) > 0)
-		vectors = err;
-
-	if (err < 0)
-		pci_disable_msix(adap->pdev);
-
-	if (!err && vectors < (adap->params.nports + 1)) {
-		pci_disable_msix(adap->pdev);
-		err = -1;
-	}
+	vectors = pci_enable_msix_range(adap->pdev, entries,
+					adap->params.nports + 1, vectors);
+	if (vectors < 0)
+		return vectors;
 
-	if (!err) {
-		for (i = 0; i < vectors; ++i)
-			adap->msix_info[i].vec = entries[i].vector;
-		adap->msix_nvectors = vectors;
-	}
+	for (i = 0; i < vectors; ++i)
+		adap->msix_info[i].vec = entries[i].vector;
+	adap->msix_nvectors = vectors;
 
-	return err;
+	return 0;
 }
 
 static void print_port_info(struct adapter *adap, const struct adapter_info *ai)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 1f4b9b30b9ed..944f2cbc1795 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -66,6 +66,7 @@ enum {
 	SERNUM_LEN = 24,    /* Serial # length */
 	EC_LEN     = 16,    /* E/C length */
 	ID_LEN     = 16,    /* ID length */
+	PN_LEN     = 16,    /* Part Number length */
 };
 
 enum {
@@ -254,6 +255,7 @@ struct vpd_params {
 	u8 ec[EC_LEN + 1];
 	u8 sn[SERNUM_LEN + 1];
 	u8 id[ID_LEN + 1];
+	u8 pn[PN_LEN + 1];
 };
 
 struct pci_params {
@@ -306,6 +308,7 @@ struct adapter_params {
 	unsigned char bypass;
 
 	unsigned int ofldq_wr_cred;
+	bool ulptx_memwrite_dsgl;          /* use of T5 DSGL allowed */
 };
 
 #include "t4fw_api.h"
@@ -957,7 +960,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
 	       u64 *parity);
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
 		u64 *parity);
-
+const char *t4_get_port_type_description(enum fw_port_type port_type);
 void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
 void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
 void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 43ab35fea48d..0ac53dd84c61 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -254,6 +254,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
 	CH_DEVICE(0x5011, 4),
 	CH_DEVICE(0x5012, 4),
 	CH_DEVICE(0x5013, 4),
+	CH_DEVICE(0x5014, 4),
+	CH_DEVICE(0x5015, 4),
 	CH_DEVICE(0x5401, 4),
 	CH_DEVICE(0x5402, 4),
 	CH_DEVICE(0x5403, 4),
@@ -273,6 +275,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
 	CH_DEVICE(0x5411, 4),
 	CH_DEVICE(0x5412, 4),
 	CH_DEVICE(0x5413, 4),
+	CH_DEVICE(0x5414, 4),
+	CH_DEVICE(0x5415, 4),
 	{ 0, }
 };
 
@@ -423,15 +427,18 @@ static void link_report(struct net_device *dev)
 		const struct port_info *p = netdev_priv(dev);
 
 		switch (p->link_cfg.speed) {
-		case SPEED_10000:
+		case 10000:
 			s = "10Gbps";
 			break;
-		case SPEED_1000:
+		case 1000:
 			s = "1000Mbps";
 			break;
-		case SPEED_100:
+		case 100:
 			s = "100Mbps";
 			break;
+		case 40000:
+			s = "40Gbps";
+			break;
 		}
 
 		netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
@@ -2061,7 +2068,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		0x40200, 0x40298,
 		0x402ac, 0x4033c,
 		0x403f8, 0x403fc,
-		0x41300, 0x413c4,
+		0x41304, 0x413c4,
 		0x41400, 0x4141c,
 		0x41480, 0x414d0,
 		0x44000, 0x44078,
@@ -2089,7 +2096,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		0x48200, 0x48298,
 		0x482ac, 0x4833c,
 		0x483f8, 0x483fc,
-		0x49300, 0x493c4,
+		0x49304, 0x493c4,
 		0x49400, 0x4941c,
 		0x49480, 0x494d0,
 		0x4c000, 0x4c078,
@@ -2199,6 +2206,8 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
 	else if (type == FW_PORT_TYPE_FIBER_XFI ||
 		 type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
 		v |= SUPPORTED_FIBRE;
+	else if (type == FW_PORT_TYPE_BP40_BA)
+		v |= SUPPORTED_40000baseSR4_Full;
 
 	if (caps & FW_PORT_CAP_ANEG)
 		v |= SUPPORTED_Autoneg;
@@ -2215,6 +2224,8 @@ static unsigned int to_fw_linkcaps(unsigned int caps)
 		v |= FW_PORT_CAP_SPEED_1G;
 	if (caps & ADVERTISED_10000baseT_Full)
 		v |= FW_PORT_CAP_SPEED_10G;
+	if (caps & ADVERTISED_40000baseSR4_Full)
+		v |= FW_PORT_CAP_SPEED_40G;
 	return v;
 }
 
@@ -2263,12 +2274,14 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
 static unsigned int speed_to_caps(int speed)
 {
-	if (speed == SPEED_100)
+	if (speed == 100)
 		return FW_PORT_CAP_SPEED_100M;
-	if (speed == SPEED_1000)
+	if (speed == 1000)
 		return FW_PORT_CAP_SPEED_1G;
-	if (speed == SPEED_10000)
+	if (speed == 10000)
 		return FW_PORT_CAP_SPEED_10G;
+	if (speed == 40000)
+		return FW_PORT_CAP_SPEED_40G;
 	return 0;
 }
 
@@ -2296,8 +2309,10 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	if (cmd->autoneg == AUTONEG_DISABLE) {
 		cap = speed_to_caps(speed);
 
-		if (!(lc->supported & cap) || (speed == SPEED_1000) ||
-		    (speed == SPEED_10000))
+		if (!(lc->supported & cap) ||
+		    (speed == 1000) ||
+		    (speed == 10000) ||
+		    (speed == 40000))
 			return -EINVAL;
 		lc->requested_speed = cap;
 		lc->advertising = 0;
@@ -3765,6 +3780,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
 	lli.dbfifo_int_thresh = dbfifo_int_thresh;
 	lli.sge_pktshift = adap->sge.pktshift;
 	lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
+	lli.ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl;
 
 	handle = ulds[uld].add(&lli);
 	if (IS_ERR(handle)) {
@@ -5370,6 +5386,21 @@ static int adap_init0(struct adapter *adap)
 	(void) t4_set_params(adap, adap->mbox, adap->fn, 0, 1, params, val);
 
 	/*
+	 * Find out whether we're allowed to use the T5+ ULPTX MEMWRITE DSGL
+	 * capability.  Earlier versions of the firmware didn't have the
+	 * ULPTX_MEMWRITE_DSGL so we'll interpret a query failure as no
+	 * permission to use ULPTX MEMWRITE DSGL.
+	 */
+	if (is_t4(adap->params.chip)) {
+		adap->params.ulptx_memwrite_dsgl = false;
+	} else {
+		params[0] = FW_PARAM_DEV(ULPTX_MEMWRITE_DSGL);
+		ret = t4_query_params(adap, adap->mbox, adap->fn, 0,
+				      1, params, val);
+		adap->params.ulptx_memwrite_dsgl = (ret == 0 && val[0] != 0);
+	}
+
+	/*
 	 * Get device capabilities so we can determine what resources we need
 	 * to manage.
 	 */
@@ -5603,9 +5634,10 @@ static const struct pci_error_handlers cxgb4_eeh = {
 	.resume         = eeh_resume,
 };
 
-static inline bool is_10g_port(const struct link_config *lc)
+static inline bool is_x_10g_port(const struct link_config *lc)
 {
-	return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0;
+	return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0 ||
+	       (lc->supported & FW_PORT_CAP_SPEED_40G) != 0;
 }
 
 static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
@@ -5629,7 +5661,7 @@ static void cfg_queues(struct adapter *adap)
 	int i, q10g = 0, n10g = 0, qidx = 0;
 
 	for_each_port(adap, i)
-		n10g += is_10g_port(&adap2pinfo(adap, i)->link_cfg);
+		n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
 
 	/*
 	 * We default to 1 queue per non-10G port and up to # of cores queues
@@ -5644,7 +5676,7 @@ static void cfg_queues(struct adapter *adap)
 		struct port_info *pi = adap2pinfo(adap, i);
 
 		pi->first_qset = qidx;
-		pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
+		pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
 		qidx += pi->nqsets;
 	}
 
@@ -5737,7 +5769,7 @@ static void reduce_ethqs(struct adapter *adap, int n)
 static int enable_msix(struct adapter *adap)
 {
 	int ofld_need = 0;
-	int i, err, want, need;
+	int i, want, need;
 	struct sge *s = &adap->sge;
 	unsigned int nchan = adap->params.nports;
 	struct msix_entry entries[MAX_INGQ + 1];
@@ -5753,32 +5785,30 @@ static int enable_msix(struct adapter *adap)
 	}
 	need = adap->params.nports + EXTRA_VECS + ofld_need;
 
-	while ((err = pci_enable_msix(adap->pdev, entries, want)) >= need)
-		want = err;
+	want = pci_enable_msix_range(adap->pdev, entries, need, want);
+	if (want < 0)
+		return want;
 
-	if (!err) {
-		/*
-		 * Distribute available vectors to the various queue groups.
-		 * Every group gets its minimum requirement and NIC gets top
-		 * priority for leftovers.
-		 */
-		i = want - EXTRA_VECS - ofld_need;
-		if (i < s->max_ethqsets) {
-			s->max_ethqsets = i;
-			if (i < s->ethqsets)
-				reduce_ethqs(adap, i);
-		}
-		if (is_offload(adap)) {
-			i = want - EXTRA_VECS - s->max_ethqsets;
-			i -= ofld_need - nchan;
-			s->ofldqsets = (i / nchan) * nchan;  /* round down */
-		}
-		for (i = 0; i < want; ++i)
-			adap->msix_info[i].vec = entries[i].vector;
-	} else if (err > 0)
-		dev_info(adap->pdev_dev,
-			 "only %d MSI-X vectors left, not using MSI-X\n", err);
-	return err;
+	/*
+	 * Distribute available vectors to the various queue groups.
+	 * Every group gets its minimum requirement and NIC gets top
+	 * priority for leftovers.
+	 */
+	i = want - EXTRA_VECS - ofld_need;
+	if (i < s->max_ethqsets) {
+		s->max_ethqsets = i;
+		if (i < s->ethqsets)
+			reduce_ethqs(adap, i);
+	}
+	if (is_offload(adap)) {
+		i = want - EXTRA_VECS - s->max_ethqsets;
+		i -= ofld_need - nchan;
+		s->ofldqsets = (i / nchan) * nchan;  /* round down */
+	}
+	for (i = 0; i < want; ++i)
+		adap->msix_info[i].vec = entries[i].vector;
+
+	return 0;
 }
 
 #undef EXTRA_VECS
@@ -5801,11 +5831,6 @@ static int init_rss(struct adapter *adap)
 
 static void print_port_info(const struct net_device *dev)
 {
-	static const char *base[] = {
-		"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
-		"KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
-	};
-
 	char buf[80];
 	char *bufp = buf;
 	const char *spd = "";
@@ -5823,9 +5848,11 @@ static void print_port_info(const struct net_device *dev)
 		bufp += sprintf(bufp, "1000/");
 	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
 		bufp += sprintf(bufp, "10G/");
+	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G)
+		bufp += sprintf(bufp, "40G/");
 	if (bufp != buf)
 		--bufp;
-	sprintf(bufp, "BASE-%s", base[pi->port_type]);
+	sprintf(bufp, "BASE-%s", t4_get_port_type_description(pi->port_type));
 
 	netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
 		    adap->params.vpd.id,
@@ -5833,8 +5860,8 @@ static void print_port_info(const struct net_device *dev)
 		    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
 		    (adap->flags & USING_MSIX) ? " MSI-X" :
 		    (adap->flags & USING_MSI) ? " MSI" : "");
-	netdev_info(dev, "S/N: %s, E/C: %s\n",
-		    adap->params.vpd.sn, adap->params.vpd.ec);
+	netdev_info(dev, "S/N: %s, P/N: %s\n",
+		    adap->params.vpd.sn, adap->params.vpd.pn);
 }
 
 static void enable_pcie_relaxed_ordering(struct pci_dev *dev)
@@ -6179,6 +6206,7 @@ static struct pci_driver cxgb4_driver = {
 	.id_table = cxgb4_pci_tbl,
 	.probe    = init_one,
 	.remove   = remove_one,
+	.shutdown = remove_one,
 	.err_handler = &cxgb4_eeh,
 };
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 4dd0a82533e4..e274a047528f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -253,6 +253,7 @@ struct cxgb4_lld_info {
 					     /*	packet data */
 	bool enable_fw_ofld_conn;            /* Enable connection through fw */
 					     /* WR */
+	bool ulptx_memwrite_dsgl;            /* use of T5 DSGL allowed */
 };
 
 struct cxgb4_uld_info {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 47ffa64fcf19..af76b25bb606 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -706,11 +706,17 @@ static inline unsigned int flits_to_desc(unsigned int n)
  *	@skb: the packet
  *
  *	Returns whether an Ethernet packet is small enough to fit as
- *	immediate data.
+ *	immediate data. Return value corresponds to headroom required.
  */
 static inline int is_eth_imm(const struct sk_buff *skb)
 {
-	return skb->len <= MAX_IMM_TX_PKT_LEN - sizeof(struct cpl_tx_pkt);
+	int hdrlen = skb_shinfo(skb)->gso_size ?
+			sizeof(struct cpl_tx_pkt_lso_core) : 0;
+
+	hdrlen += sizeof(struct cpl_tx_pkt);
+	if (skb->len <= MAX_IMM_TX_PKT_LEN - hdrlen)
+		return hdrlen;
+	return 0;
 }
 
 /**
@@ -723,9 +729,10 @@ static inline int is_eth_imm(const struct sk_buff *skb)
 static inline unsigned int calc_tx_flits(const struct sk_buff *skb)
 {
 	unsigned int flits;
+	int hdrlen = is_eth_imm(skb);
 
-	if (is_eth_imm(skb))
-		return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt), 8);
+	if (hdrlen)
+		return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64));
 
 	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4;
 	if (skb_shinfo(skb)->gso_size)
@@ -971,6 +978,7 @@ static inline void txq_advance(struct sge_txq *q, unsigned int n)
  */
 netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	int len;
 	u32 wr_mid;
 	u64 cntrl, *end;
 	int qidx, credits;
@@ -982,6 +990,7 @@ netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct cpl_tx_pkt_core *cpl;
 	const struct skb_shared_info *ssi;
 	dma_addr_t addr[MAX_SKB_FRAGS + 1];
+	bool immediate = false;
 
 	/*
 	 * The chip min packet length is 10 octets but play safe and reject
@@ -1011,7 +1020,10 @@ out_free:	dev_kfree_skb(skb);
 		return NETDEV_TX_BUSY;
 	}
 
-	if (!is_eth_imm(skb) &&
+	if (is_eth_imm(skb))
+		immediate = true;
+
+	if (!immediate &&
 	    unlikely(map_skb(adap->pdev_dev, skb, addr) < 0)) {
 		q->mapping_err++;
 		goto out_free;
@@ -1028,6 +1040,8 @@ out_free:	dev_kfree_skb(skb);
 	wr->r3 = cpu_to_be64(0);
 	end = (u64 *)wr + flits;
 
+	len = immediate ? skb->len : 0;
+	len += sizeof(*cpl);
 	ssi = skb_shinfo(skb);
 	if (ssi->gso_size) {
 		struct cpl_tx_pkt_lso *lso = (void *)wr;
@@ -1035,8 +1049,9 @@ out_free:	dev_kfree_skb(skb);
 		int l3hdr_len = skb_network_header_len(skb);
 		int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
 
+		len += sizeof(*lso);
 		wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
-				       FW_WR_IMMDLEN(sizeof(*lso)));
+				       FW_WR_IMMDLEN(len));
 		lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) |
 					LSO_FIRST_SLICE | LSO_LAST_SLICE |
 					LSO_IPV6(v6) |
@@ -1054,9 +1069,6 @@ out_free:	dev_kfree_skb(skb);
 		q->tso++;
 		q->tx_cso += ssi->gso_segs;
 	} else {
-		int len;
-
-		len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl);
 		wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
 				       FW_WR_IMMDLEN(len));
 		cpl = (void *)(wr + 1);
@@ -1078,7 +1090,7 @@ out_free:	dev_kfree_skb(skb);
 	cpl->len = htons(skb->len);
 	cpl->ctrl1 = cpu_to_be64(cntrl);
 
-	if (is_eth_imm(skb)) {
+	if (immediate) {
 		inline_tx_skb(skb, &q->q, cpl + 1);
 		dev_kfree_skb(skb);
 	} else {
@@ -1467,8 +1479,12 @@ static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
 {
 	unsigned int idx = skb_txq(skb);
 
-	if (unlikely(is_ctrl_pkt(skb)))
+	if (unlikely(is_ctrl_pkt(skb))) {
+		/* Single ctrl queue is a requirement for LE workaround path */
+		if (adap->tids.nsftids)
+			idx = 0;
 		return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
+	}
 	return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
 }
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 2c109343d570..d3c2a516fa88 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -573,7 +573,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 {
 	u32 cclk_param, cclk_val;
 	int i, ret, addr;
-	int ec, sn;
+	int ec, sn, pn;
 	u8 *vpd, csum;
 	unsigned int vpdr_len, kw_offset, id_len;
 
@@ -638,6 +638,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 
 	FIND_VPD_KW(ec, "EC");
 	FIND_VPD_KW(sn, "SN");
+	FIND_VPD_KW(pn, "PN");
 #undef FIND_VPD_KW
 
 	memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len);
@@ -647,6 +648,8 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 	i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
 	memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
 	strim(p->sn);
+	memcpy(p->pn, vpd + pn, min(i, PN_LEN));
+	strim(p->pn);
 
 	/*
 	 * Ask firmware for the Core Clock since it knows how to translate the
@@ -1155,7 +1158,8 @@ out:
 }
 
 #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
-		     FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
+		     FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \
+		     FW_PORT_CAP_ANEG)
 
 /**
  *	t4_link_start - apply link configuration to MAC/PHY
@@ -2247,6 +2251,36 @@ static unsigned int get_mps_bg_map(struct adapter *adap, int idx)
 }
 
 /**
+ *      t4_get_port_type_description - return Port Type string description
+ *      @port_type: firmware Port Type enumeration
+ */
+const char *t4_get_port_type_description(enum fw_port_type port_type)
+{
+	static const char *const port_type_description[] = {
+		"R XFI",
+		"R XAUI",
+		"T SGMII",
+		"T XFI",
+		"T XAUI",
+		"KX4",
+		"CX4",
+		"KX",
+		"KR",
+		"R SFP+",
+		"KR/KX",
+		"KR/KX/KX4",
+		"R QSFP_10G",
+		"",
+		"R QSFP",
+		"R BP40_BA",
+	};
+
+	if (port_type < ARRAY_SIZE(port_type_description))
+		return port_type_description[port_type];
+	return "UNKNOWN";
+}
+
+/**
  *	t4_get_port_stats - collect port statistics
  *	@adap: the adapter
  *	@idx: the port index
@@ -3533,11 +3567,13 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
 		if (stat & FW_PORT_CMD_TXPAUSE)
 			fc |= PAUSE_TX;
 		if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-			speed = SPEED_100;
+			speed = 100;
 		else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-			speed = SPEED_1000;
+			speed = 1000;
 		else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-			speed = SPEED_10000;
+			speed = 10000;
+		else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
+			speed = 40000;
 
 		if (link_ok != lc->link_ok || speed != lc->speed ||
 		    fc != lc->fc) {                    /* something changed */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 74fea74ce0aa..9cc973fbcf26 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -932,6 +932,7 @@ enum fw_params_param_dev {
 	FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
 	FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
 	FW_PARAMS_PARAM_DEV_CF = 0x0D,
+	FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
 };
 
 /*
@@ -1742,6 +1743,9 @@ enum fw_port_type {
 	FW_PORT_TYPE_SFP,
 	FW_PORT_TYPE_BP_AP,
 	FW_PORT_TYPE_BP4_AP,
+	FW_PORT_TYPE_QSFP_10G,
+	FW_PORT_TYPE_QSFP,
+	FW_PORT_TYPE_BP40_BA,
 
 	FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK
 };
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 0899c0983594..1d0fe9b60312 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2444,7 +2444,7 @@ static void reduce_ethqs(struct adapter *adapter, int n)
  */
 static int enable_msix(struct adapter *adapter)
 {
-	int i, err, want, need;
+	int i, want, need, nqsets;
 	struct msix_entry entries[MSIX_ENTRIES];
 	struct sge *s = &adapter->sge;
 
@@ -2460,26 +2460,23 @@ static int enable_msix(struct adapter *adapter)
 	 */
 	want = s->max_ethqsets + MSIX_EXTRAS;
 	need = adapter->params.nports + MSIX_EXTRAS;
-	while ((err = pci_enable_msix(adapter->pdev, entries, want)) >= need)
-		want = err;
 
-	if (err == 0) {
-		int nqsets = want - MSIX_EXTRAS;
-		if (nqsets < s->max_ethqsets) {
-			dev_warn(adapter->pdev_dev, "only enough MSI-X vectors"
-				 " for %d Queue Sets\n", nqsets);
-			s->max_ethqsets = nqsets;
-			if (nqsets < s->ethqsets)
-				reduce_ethqs(adapter, nqsets);
-		}
-		for (i = 0; i < want; ++i)
-			adapter->msix_info[i].vec = entries[i].vector;
-	} else if (err > 0) {
-		pci_disable_msix(adapter->pdev);
-		dev_info(adapter->pdev_dev, "only %d MSI-X vectors left,"
-			 " not using MSI-X\n", err);
+	want = pci_enable_msix_range(adapter->pdev, entries, need, want);
+	if (want < 0)
+		return want;
+
+	nqsets = want - MSIX_EXTRAS;
+	if (nqsets < s->max_ethqsets) {
+		dev_warn(adapter->pdev_dev, "only enough MSI-X vectors"
+			 " for %d Queue Sets\n", nqsets);
+		s->max_ethqsets = nqsets;
+		if (nqsets < s->ethqsets)
+			reduce_ethqs(adapter, nqsets);
 	}
-	return err;
+	for (i = 0; i < want; ++i)
+		adapter->msix_info[i].vec = entries[i].vector;
+
+	return 0;
 }
 
 static const struct net_device_ops cxgb4vf_netdev_ops	= {
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b740bfce72ef..dcd58f23834a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1796,7 +1796,8 @@ static int enic_set_intr_mode(struct enic *enic)
 	    enic->cq_count >= n + m &&
 	    enic->intr_count >= n + m + 2) {
 
-		if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
+		if (pci_enable_msix_range(enic->pdev, enic->msix_entry,
+					  n + m + 2, n + m + 2) > 0) {
 
 			enic->rq_count = n;
 			enic->wq_count = m;
@@ -1815,7 +1816,8 @@ static int enic_set_intr_mode(struct enic *enic)
 	    enic->wq_count >= m &&
 	    enic->cq_count >= 1 + m &&
 	    enic->intr_count >= 1 + m + 2) {
-		if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) {
+		if (pci_enable_msix_range(enic->pdev, enic->msix_entry,
+					  1 + m + 2, 1 + m + 2) > 0) {
 
 			enic->rq_count = 1;
 			enic->wq_count = m;
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8d09615da585..c8502fafff9b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -88,7 +88,6 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE_MIN_MTU		256
 
 #define BE_NUM_VLANS_SUPPORTED	64
-#define BE_UMC_NUM_VLANS_SUPPORTED	15
 #define BE_MAX_EQD		128u
 #define	BE_MAX_TX_FRAG_COUNT	30
 
@@ -293,7 +292,7 @@ struct be_rx_compl_info {
 	u8 ip_csum;
 	u8 l4_csum;
 	u8 ipv6;
-	u8 vtm;
+	u8 qnq;
 	u8 pkt_type;
 	u8 ip_frag;
 };
@@ -350,11 +349,13 @@ struct be_drv_stats {
 	u32 roce_drops_crc;
 };
 
+/* A vlan-id of 0xFFFF must be used to clear transparent vlan-tagging */
+#define BE_RESET_VLAN_TAG_ID	0xFFFF
+
 struct be_vf_cfg {
 	unsigned char mac_addr[ETH_ALEN];
 	int if_handle;
 	int pmac_id;
-	u16 def_vid;
 	u16 vlan_tag;
 	u32 tx_rate;
 };
@@ -465,6 +466,7 @@ struct be_adapter {
 
 	u32 port_num;
 	bool promiscuous;
+	u8 mc_type;
 	u32 function_mode;
 	u32 function_caps;
 	u32 rx_fc;		/* Rx flow control */
@@ -534,6 +536,14 @@ static inline u16 be_max_qs(struct be_adapter *adapter)
 	return min_t(u16, num, num_online_cpus());
 }
 
+/* Is BE in pvid_tagging mode */
+#define be_pvid_tagging_enabled(adapter)	(adapter->pvid)
+
+/* Is BE in QNQ multi-channel mode */
+#define be_is_qnq_mode(adapter)		(adapter->mc_type == FLEX10 ||  \
+					 adapter->mc_type == vNIC1 ||	\
+					 adapter->mc_type == UFP)
+
 #define lancer_chip(adapter)	(adapter->pdev->device == OC_DEVICE_ID3 || \
 				 adapter->pdev->device == OC_DEVICE_ID4)
 
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 48076a6370c3..72bde5d1c358 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -3296,6 +3296,21 @@ static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
 	return NULL;
 }
 
+static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
+{
+	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+	int i;
+
+	for (i = 0; i < desc_count; i++) {
+		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
+			return (struct be_port_res_desc *)hdr;
+
+		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
+		hdr = (void *)hdr + hdr->desc_len;
+	}
+	return NULL;
+}
+
 static void be_copy_nic_desc(struct be_resources *res,
 			     struct be_nic_res_desc *desc)
 {
@@ -3439,6 +3454,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 {
 	struct be_cmd_resp_get_profile_config *resp;
 	struct be_pcie_res_desc *pcie;
+	struct be_port_res_desc *port;
 	struct be_nic_res_desc *nic;
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	struct be_dma_mem cmd;
@@ -3466,6 +3482,10 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 	if (pcie)
 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
 
+	port = be_get_port_desc(resp->func_param, desc_count);
+	if (port)
+		adapter->mc_type = port->mc_type;
+
 	nic = be_get_nic_desc(resp->func_param, desc_count);
 	if (nic)
 		be_copy_nic_desc(res, nic);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index fc4e076dc202..d0ab980f77ea 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -1098,14 +1098,6 @@ struct be_cmd_resp_query_fw_cfg {
 	u32 function_caps;
 };
 
-/* Is BE in a multi-channel mode */
-static inline bool be_is_mc(struct be_adapter *adapter)
-{
-	return adapter->function_mode & FLEX10_MODE ||
-		adapter->function_mode & VNIC_MODE ||
-		adapter->function_mode & UMC_ENABLED;
-}
-
 /******************** RSS Config ****************************************/
 /* RSS type		Input parameters used to compute RX hash
  * RSS_ENABLE_IPV4	SRC IPv4, DST IPv4
@@ -1828,6 +1820,7 @@ struct be_cmd_req_set_ext_fat_caps {
 #define NIC_RESOURCE_DESC_TYPE_V0		0x41
 #define PCIE_RESOURCE_DESC_TYPE_V1		0x50
 #define NIC_RESOURCE_DESC_TYPE_V1		0x51
+#define PORT_RESOURCE_DESC_TYPE_V1		0x55
 #define MAX_RESOURCE_DESC			264
 
 /* QOS unit number */
@@ -1891,6 +1884,33 @@ struct be_nic_res_desc {
 	u32 rsvd8[7];
 } __packed;
 
+/************ Multi-Channel type ***********/
+enum mc_type {
+	MC_NONE = 0x01,
+	UMC = 0x02,
+	FLEX10 = 0x03,
+	vNIC1 = 0x04,
+	nPAR = 0x05,
+	UFP = 0x06,
+	vNIC2 = 0x07
+};
+
+struct be_port_res_desc {
+	struct be_res_desc_hdr hdr;
+	u8 rsvd0;
+	u8 flags;
+	u8 rsvd1;
+	u8 mc_type;
+	u16 rsvd2;
+	u32 rsvd3[20];
+} __packed;
+
+/* Is BE in a multi-channel mode */
+static inline bool be_is_mc(struct be_adapter *adapter)
+{
+	return adapter->mc_type > MC_NONE;
+}
+
 struct be_cmd_req_get_func_config {
 	struct be_cmd_req_hdr hdr;
 };
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 05be0070f55f..cf09d8faca84 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index dc88782185f2..28ac8dd0beaa 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -368,7 +368,7 @@ struct amap_eth_rx_compl_v0 {
 	u8 numfrags[3];		/* dword 1 */
 	u8 rss_flush;		/* dword 2 */
 	u8 cast_enc[2];		/* dword 2 */
-	u8 vtm;			/* dword 2 */
+	u8 qnq;			/* dword 2 */
 	u8 rss_bank;		/* dword 2 */
 	u8 rsvd1[23];		/* dword 2 */
 	u8 lro_pkt;		/* dword 2 */
@@ -401,7 +401,7 @@ struct amap_eth_rx_compl_v1 {
 	u8 numfrags[3];		/* dword 1 */
 	u8 rss_flush;		/* dword 2 */
 	u8 cast_enc[2];		/* dword 2 */
-	u8 vtm;			/* dword 2 */
+	u8 qnq;			/* dword 2 */
 	u8 rss_bank;		/* dword 2 */
 	u8 port[2];		/* dword 2 */
 	u8 vntagp;		/* dword 2 */
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 04ac9c6a0d39..93dc3084851b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -913,24 +913,14 @@ static int be_ipv6_tx_stall_chk(struct be_adapter *adapter,
 	return BE3_chip(adapter) && be_ipv6_exthdr_check(skb);
 }
 
-static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
-					   struct sk_buff *skb,
-					   bool *skip_hw_vlan)
+static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
+						  struct sk_buff *skb,
+						  bool *skip_hw_vlan)
 {
 	struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
 	unsigned int eth_hdr_len;
 	struct iphdr *ip;
 
-	/* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or less
-	 * may cause a transmit stall on that port. So the work-around is to
-	 * pad short packets (<= 32 bytes) to a 36-byte length.
-	 */
-	if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
-		if (skb_padto(skb, 36))
-			goto tx_drop;
-		skb->len = 36;
-	}
-
 	/* For padded packets, BE HW modifies tot_len field in IP header
 	 * incorrecly when VLAN tag is inserted by HW.
 	 * For padded packets, Lancer computes incorrect checksum.
@@ -945,9 +935,9 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
 	}
 
 	/* If vlan tag is already inlined in the packet, skip HW VLAN
-	 * tagging in UMC mode
+	 * tagging in pvid-tagging mode
 	 */
-	if ((adapter->function_mode & UMC_ENABLED) &&
+	if (be_pvid_tagging_enabled(adapter) &&
 	    veh->h_vlan_proto == htons(ETH_P_8021Q))
 			*skip_hw_vlan = true;
 
@@ -959,7 +949,7 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
 	    vlan_tx_tag_present(skb)) {
 		skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
 		if (unlikely(!skb))
-			goto tx_drop;
+			goto err;
 	}
 
 	/* HW may lockup when VLAN HW tagging is requested on
@@ -981,15 +971,39 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
 	    be_vlan_tag_tx_chk(adapter, skb)) {
 		skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
 		if (unlikely(!skb))
-			goto tx_drop;
+			goto err;
 	}
 
 	return skb;
 tx_drop:
 	dev_kfree_skb_any(skb);
+err:
 	return NULL;
 }
 
+static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
+					   struct sk_buff *skb,
+					   bool *skip_hw_vlan)
+{
+	/* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
+	 * less may cause a transmit stall on that port. So the work-around is
+	 * to pad short packets (<= 32 bytes) to a 36-byte length.
+	 */
+	if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+		if (skb_padto(skb, 36))
+			return NULL;
+		skb->len = 36;
+	}
+
+	if (BEx_chip(adapter) || lancer_chip(adapter)) {
+		skb = be_lancer_xmit_workarounds(adapter, skb, skip_hw_vlan);
+		if (!skb)
+			return NULL;
+	}
+
+	return skb;
+}
+
 static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
@@ -1157,6 +1171,14 @@ ret:
 	return status;
 }
 
+static void be_clear_promisc(struct be_adapter *adapter)
+{
+	adapter->promiscuous = false;
+	adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
+
+	be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
+}
+
 static void be_set_rx_mode(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
@@ -1170,9 +1192,7 @@ static void be_set_rx_mode(struct net_device *netdev)
 
 	/* BE was previously in promiscuous mode; disable it */
 	if (adapter->promiscuous) {
-		adapter->promiscuous = false;
-		be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
-
+		be_clear_promisc(adapter);
 		if (adapter->vlans_added)
 			be_vid_config(adapter);
 	}
@@ -1287,24 +1307,20 @@ static int be_set_vf_vlan(struct net_device *netdev,
 
 	if (vlan || qos) {
 		vlan |= qos << VLAN_PRIO_SHIFT;
-		if (vf_cfg->vlan_tag != vlan) {
-			/* If this is new value, program it. Else skip. */
-			vf_cfg->vlan_tag = vlan;
+		if (vf_cfg->vlan_tag != vlan)
 			status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
 						       vf_cfg->if_handle, 0);
-		}
 	} else {
 		/* Reset Transparent Vlan Tagging. */
-		vf_cfg->vlan_tag = 0;
-		vlan = vf_cfg->def_vid;
-		status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
-					       vf_cfg->if_handle, 0);
+		status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID,
+					       vf + 1, vf_cfg->if_handle, 0);
 	}
 
-
-	if (status)
+	if (!status)
+		vf_cfg->vlan_tag = vlan;
+	else
 		dev_info(&adapter->pdev->dev,
-				"VLAN %d config on VF %d failed\n", vlan, vf);
+			 "VLAN %d config on VF %d failed\n", vlan, vf);
 	return status;
 }
 
@@ -1660,7 +1676,7 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
 	rxcp->rss_hash =
 		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl);
 	if (rxcp->vlanf) {
-		rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm,
+		rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq,
 					  compl);
 		rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
 					       compl);
@@ -1690,7 +1706,7 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
 	rxcp->rss_hash =
 		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl);
 	if (rxcp->vlanf) {
-		rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm,
+		rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq,
 					  compl);
 		rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
 					       compl);
@@ -1723,9 +1739,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
 		rxcp->l4_csum = 0;
 
 	if (rxcp->vlanf) {
-		/* vlanf could be wrongly set in some cards.
-		 * ignore if vtm is not set */
-		if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm)
+		/* In QNQ modes, if qnq bit is not set, then the packet was
+		 * tagged only with the transparent outer vlan-tag and must
+		 * not be treated as a vlan packet by host
+		 */
+		if (be_is_qnq_mode(adapter) && !rxcp->qnq)
 			rxcp->vlanf = 0;
 
 		if (!lancer_chip(adapter))
@@ -2423,6 +2441,9 @@ void be_detect_error(struct be_adapter *adapter)
 	u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0;
 	u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
 	u32 i;
+	bool error_detected = false;
+	struct device *dev = &adapter->pdev->dev;
+	struct net_device *netdev = adapter->netdev;
 
 	if (be_hw_error(adapter))
 		return;
@@ -2434,6 +2455,21 @@ void be_detect_error(struct be_adapter *adapter)
 					SLIPORT_ERROR1_OFFSET);
 			sliport_err2 = ioread32(adapter->db +
 					SLIPORT_ERROR2_OFFSET);
+			adapter->hw_error = true;
+			/* Do not log error messages if its a FW reset */
+			if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
+			    sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
+				dev_info(dev, "Firmware update in progress\n");
+			} else {
+				error_detected = true;
+				dev_err(dev, "Error detected in the card\n");
+				dev_err(dev, "ERR: sliport status 0x%x\n",
+					sliport_status);
+				dev_err(dev, "ERR: sliport error1 0x%x\n",
+					sliport_err1);
+				dev_err(dev, "ERR: sliport error2 0x%x\n",
+					sliport_err2);
+			}
 		}
 	} else {
 		pci_read_config_dword(adapter->pdev,
@@ -2447,51 +2483,33 @@ void be_detect_error(struct be_adapter *adapter)
 
 		ue_lo = (ue_lo & ~ue_lo_mask);
 		ue_hi = (ue_hi & ~ue_hi_mask);
-	}
-
-	/* On certain platforms BE hardware can indicate spurious UEs.
-	 * Allow the h/w to stop working completely in case of a real UE.
-	 * Hence not setting the hw_error for UE detection.
-	 */
-	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
-		adapter->hw_error = true;
-		/* Do not log error messages if its a FW reset */
-		if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
-		    sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
-			dev_info(&adapter->pdev->dev,
-				 "Firmware update in progress\n");
-			return;
-		} else {
-			dev_err(&adapter->pdev->dev,
-				"Error detected in the card\n");
-		}
-	}
-
-	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport status 0x%x\n", sliport_status);
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport error1 0x%x\n", sliport_err1);
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport error2 0x%x\n", sliport_err2);
-	}
 
-	if (ue_lo) {
-		for (i = 0; ue_lo; ue_lo >>= 1, i++) {
-			if (ue_lo & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_low_desc[i]);
-		}
-	}
+		/* On certain platforms BE hardware can indicate spurious UEs.
+		 * Allow HW to stop working completely in case of a real UE.
+		 * Hence not setting the hw_error for UE detection.
+		 */
 
-	if (ue_hi) {
-		for (i = 0; ue_hi; ue_hi >>= 1, i++) {
-			if (ue_hi & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_hi_desc[i]);
+		if (ue_lo || ue_hi) {
+			error_detected = true;
+			dev_err(dev,
+				"Unrecoverable Error detected in the adapter");
+			dev_err(dev, "Please reboot server to recover");
+			if (skyhawk_chip(adapter))
+				adapter->hw_error = true;
+			for (i = 0; ue_lo; ue_lo >>= 1, i++) {
+				if (ue_lo & 1)
+					dev_err(dev, "UE: %s bit set\n",
+						ue_status_low_desc[i]);
+			}
+			for (i = 0; ue_hi; ue_hi >>= 1, i++) {
+				if (ue_hi & 1)
+					dev_err(dev, "UE: %s bit set\n",
+						ue_status_hi_desc[i]);
+			}
 		}
 	}
-
+	if (error_detected)
+		netif_carrier_off(netdev);
 }
 
 static void be_msix_disable(struct be_adapter *adapter)
@@ -2505,7 +2523,7 @@ static void be_msix_disable(struct be_adapter *adapter)
 
 static int be_msix_enable(struct be_adapter *adapter)
 {
-	int i, status, num_vec;
+	int i, num_vec;
 	struct device *dev = &adapter->pdev->dev;
 
 	/* If RoCE is supported, program the max number of NIC vectors that
@@ -2521,24 +2539,11 @@ static int be_msix_enable(struct be_adapter *adapter)
 	for (i = 0; i < num_vec; i++)
 		adapter->msix_entries[i].entry = i;
 
-	status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec);
-	if (status == 0) {
-		goto done;
-	} else if (status >= MIN_MSIX_VECTORS) {
-		num_vec = status;
-		status = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-					 num_vec);
-		if (!status)
-			goto done;
-	}
-
-	dev_warn(dev, "MSIx enable failed\n");
+	num_vec = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+					MIN_MSIX_VECTORS, num_vec);
+	if (num_vec < 0)
+		goto fail;
 
-	/* INTx is not supported in VFs, so fail probe if enable_msix fails */
-	if (!be_physfn(adapter))
-		return status;
-	return 0;
-done:
 	if (be_roce_supported(adapter) && num_vec > MIN_MSIX_VECTORS) {
 		adapter->num_msix_roce_vec = num_vec / 2;
 		dev_info(dev, "enabled %d MSI-x vector(s) for RoCE\n",
@@ -2550,6 +2555,14 @@ done:
 	dev_info(dev, "enabled %d MSI-x vector(s) for NIC\n",
 		 adapter->num_msix_vec);
 	return 0;
+
+fail:
+	dev_warn(dev, "MSIx enable failed\n");
+
+	/* INTx is not supported in VFs, so fail probe if enable_msix fails */
+	if (!be_physfn(adapter))
+		return num_vec;
+	return 0;
 }
 
 static inline int be_msix_vec_get(struct be_adapter *adapter,
@@ -3013,11 +3026,11 @@ static int be_vf_setup_init(struct be_adapter *adapter)
 
 static int be_vf_setup(struct be_adapter *adapter)
 {
+	struct device *dev = &adapter->pdev->dev;
 	struct be_vf_cfg *vf_cfg;
-	u16 def_vlan, lnk_speed;
 	int status, old_vfs, vf;
-	struct device *dev = &adapter->pdev->dev;
 	u32 privileges;
+	u16 lnk_speed;
 
 	old_vfs = pci_num_vf(adapter->pdev);
 	if (old_vfs) {
@@ -3084,12 +3097,6 @@ static int be_vf_setup(struct be_adapter *adapter)
 		if (!status)
 			vf_cfg->tx_rate = lnk_speed;
 
-		status = be_cmd_get_hsw_config(adapter, &def_vlan,
-					       vf + 1, vf_cfg->if_handle, NULL);
-		if (status)
-			goto err;
-		vf_cfg->def_vid = def_vlan;
-
 		if (!old_vfs)
 			be_cmd_enable_vf(adapter, vf + 1);
 	}
@@ -3109,6 +3116,22 @@ err:
 	return status;
 }
 
+/* Converting function_mode bits on BE3 to SH mc_type enums */
+
+static u8 be_convert_mc_type(u32 function_mode)
+{
+	if (function_mode & VNIC_MODE && function_mode & FLEX10_MODE)
+		return vNIC1;
+	else if (function_mode & FLEX10_MODE)
+		return FLEX10;
+	else if (function_mode & VNIC_MODE)
+		return vNIC2;
+	else if (function_mode & UMC_ENABLED)
+		return UMC;
+	else
+		return MC_NONE;
+}
+
 /* On BE2/BE3 FW does not suggest the supported limits */
 static void BEx_get_resources(struct be_adapter *adapter,
 			      struct be_resources *res)
@@ -3129,12 +3152,23 @@ static void BEx_get_resources(struct be_adapter *adapter,
 	else
 		res->max_uc_mac = BE_VF_UC_PMAC_COUNT;
 
-	if (adapter->function_mode & FLEX10_MODE)
-		res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-	else if (adapter->function_mode & UMC_ENABLED)
-		res->max_vlans = BE_UMC_NUM_VLANS_SUPPORTED;
-	else
+	adapter->mc_type = be_convert_mc_type(adapter->function_mode);
+
+	if (be_is_mc(adapter)) {
+		/* Assuming that there are 4 channels per port,
+		 * when multi-channel is enabled
+		 */
+		if (be_is_qnq_mode(adapter))
+			res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+		else
+			/* In a non-qnq multichannel mode, the pvid
+			 * takes up one vlan entry
+			 */
+			res->max_vlans = (BE_NUM_VLANS_SUPPORTED / 4) - 1;
+	} else {
 		res->max_vlans = BE_NUM_VLANS_SUPPORTED;
+	}
+
 	res->max_mcast_mac = BE_MAX_MC;
 
 	/* For BE3 1Gb ports, F/W does not properly support multiple TXQs */
@@ -4417,14 +4451,32 @@ static bool be_reset_required(struct be_adapter *adapter)
 
 static char *mc_name(struct be_adapter *adapter)
 {
-	if (adapter->function_mode & FLEX10_MODE)
-		return "FLEX10";
-	else if (adapter->function_mode & VNIC_MODE)
-		return "vNIC";
-	else if (adapter->function_mode & UMC_ENABLED)
-		return "UMC";
-	else
-		return "";
+	char *str = "";	/* default */
+
+	switch (adapter->mc_type) {
+	case UMC:
+		str = "UMC";
+		break;
+	case FLEX10:
+		str = "FLEX10";
+		break;
+	case vNIC1:
+		str = "vNIC-1";
+		break;
+	case nPAR:
+		str = "nPAR";
+		break;
+	case UFP:
+		str = "UFP";
+		break;
+	case vNIC2:
+		str = "vNIC-2";
+		break;
+	default:
+		str = "";
+	}
+
+	return str;
 }
 
 static inline char *func_name(struct be_adapter *adapter)
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index 9cd5415fe017..a5dae4a62bb3 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
index 2cd1129e19af..a3ef8f804b9e 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.h
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 549ce13b92ac..71debd1c18c9 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
 gianfar_driver-objs := gianfar.o \
-		gianfar_ethtool.o \
-		gianfar_sysfs.o
+		gianfar_ethtool.o
 obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
 ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 903362a7b584..479a7cba45c0 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -389,12 +389,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 			netdev_err(ndev, "Tx DMA memory map failed\n");
 		return NETDEV_TX_OK;
 	}
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
-	 * it's the last BD of the frame, and to put the CRC on the end.
-	 */
-	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
-			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
-	bdp->cbd_sc = status;
 
 	if (fep->bufdesc_ex) {
 
@@ -416,6 +410,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		}
 	}
 
+	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	 * it's the last BD of the frame, and to put the CRC on the end.
+	 */
+	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
+			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
+	bdp->cbd_sc = status;
+
 	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
 	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
 	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index ad5a5aadc7e1..c5b9320f7629 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -9,7 +9,7 @@
  * Maintainer: Kumar Gala
  * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
  *
- * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
+ * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
  * Copyright 2007 MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -121,7 +121,6 @@ static irqreturn_t gfar_error(int irq, void *dev_id);
 static irqreturn_t gfar_transmit(int irq, void *dev_id);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id);
 static void adjust_link(struct net_device *dev);
-static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct platform_device *ofdev);
 static int gfar_remove(struct platform_device *ofdev);
@@ -138,9 +137,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
 static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
 static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 			       int amount_pull, struct napi_struct *napi);
-void gfar_halt(struct net_device *dev);
-static void gfar_halt_nodisable(struct net_device *dev);
-void gfar_start(struct net_device *dev);
+static void gfar_halt_nodisable(struct gfar_private *priv);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num,
 				  const u8 *addr);
@@ -332,23 +329,35 @@ static void gfar_init_tx_rx_base(struct gfar_private *priv)
 	}
 }
 
-static void gfar_init_mac(struct net_device *ndev)
+static void gfar_rx_buff_size_config(struct gfar_private *priv)
 {
-	struct gfar_private *priv = netdev_priv(ndev);
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	u32 rctrl = 0;
-	u32 tctrl = 0;
-	u32 attrs = 0;
-
-	/* write the tx/rx base registers */
-	gfar_init_tx_rx_base(priv);
-
-	/* Configure the coalescing support */
-	gfar_configure_coalescing_all(priv);
+	int frame_size = priv->ndev->mtu + ETH_HLEN;
 
 	/* set this when rx hw offload (TOE) functions are being used */
 	priv->uses_rxfcb = 0;
 
+	if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
+		priv->uses_rxfcb = 1;
+
+	if (priv->hwts_rx_en)
+		priv->uses_rxfcb = 1;
+
+	if (priv->uses_rxfcb)
+		frame_size += GMAC_FCB_LEN;
+
+	frame_size += priv->padding;
+
+	frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
+		     INCREMENTAL_BUFFER_SIZE;
+
+	priv->rx_buffer_size = frame_size;
+}
+
+static void gfar_mac_rx_config(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+	u32 rctrl = 0;
+
 	if (priv->rx_filer_enable) {
 		rctrl |= RCTRL_FILREN;
 		/* Program the RIR0 reg with the required distribution */
@@ -356,48 +365,37 @@ static void gfar_init_mac(struct net_device *ndev)
 	}
 
 	/* Restore PROMISC mode */
-	if (ndev->flags & IFF_PROMISC)
+	if (priv->ndev->flags & IFF_PROMISC)
 		rctrl |= RCTRL_PROM;
 
-	if (ndev->features & NETIF_F_RXCSUM) {
+	if (priv->ndev->features & NETIF_F_RXCSUM)
 		rctrl |= RCTRL_CHECKSUMMING;
-		priv->uses_rxfcb = 1;
-	}
-
-	if (priv->extended_hash) {
-		rctrl |= RCTRL_EXTHASH;
 
-		gfar_clear_exact_match(ndev);
-		rctrl |= RCTRL_EMEN;
-	}
+	if (priv->extended_hash)
+		rctrl |= RCTRL_EXTHASH | RCTRL_EMEN;
 
 	if (priv->padding) {
 		rctrl &= ~RCTRL_PAL_MASK;
 		rctrl |= RCTRL_PADDING(priv->padding);
 	}
 
-	/* Insert receive time stamps into padding alignment bytes */
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
-		rctrl &= ~RCTRL_PAL_MASK;
-		rctrl |= RCTRL_PADDING(8);
-		priv->padding = 8;
-	}
-
 	/* Enable HW time stamping if requested from user space */
-	if (priv->hwts_rx_en) {
+	if (priv->hwts_rx_en)
 		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
-		priv->uses_rxfcb = 1;
-	}
 
-	if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
 		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
-		priv->uses_rxfcb = 1;
-	}
 
 	/* Init rctrl based on our settings */
 	gfar_write(&regs->rctrl, rctrl);
+}
+
+static void gfar_mac_tx_config(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+	u32 tctrl = 0;
 
-	if (ndev->features & NETIF_F_IP_CSUM)
+	if (priv->ndev->features & NETIF_F_IP_CSUM)
 		tctrl |= TCTRL_INIT_CSUM;
 
 	if (priv->prio_sched_en)
@@ -408,30 +406,51 @@ static void gfar_init_mac(struct net_device *ndev)
 		gfar_write(&regs->tr47wt, DEFAULT_WRRS_WEIGHT);
 	}
 
-	gfar_write(&regs->tctrl, tctrl);
+	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
+		tctrl |= TCTRL_VLINS;
 
-	/* Set the extraction length and index */
-	attrs = ATTRELI_EL(priv->rx_stash_size) |
-		ATTRELI_EI(priv->rx_stash_index);
+	gfar_write(&regs->tctrl, tctrl);
+}
 
-	gfar_write(&regs->attreli, attrs);
+static void gfar_configure_coalescing(struct gfar_private *priv,
+			       unsigned long tx_mask, unsigned long rx_mask)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+	u32 __iomem *baddr;
 
-	/* Start with defaults, and add stashing or locking
-	 * depending on the approprate variables
-	 */
-	attrs = ATTR_INIT_SETTINGS;
+	if (priv->mode == MQ_MG_MODE) {
+		int i = 0;
 
-	if (priv->bd_stash_en)
-		attrs |= ATTR_BDSTASH;
+		baddr = &regs->txic0;
+		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
+			gfar_write(baddr + i, 0);
+			if (likely(priv->tx_queue[i]->txcoalescing))
+				gfar_write(baddr + i, priv->tx_queue[i]->txic);
+		}
 
-	if (priv->rx_stash_size != 0)
-		attrs |= ATTR_BUFSTASH;
+		baddr = &regs->rxic0;
+		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
+			gfar_write(baddr + i, 0);
+			if (likely(priv->rx_queue[i]->rxcoalescing))
+				gfar_write(baddr + i, priv->rx_queue[i]->rxic);
+		}
+	} else {
+		/* Backward compatible case -- even if we enable
+		 * multiple queues, there's only single reg to program
+		 */
+		gfar_write(&regs->txic, 0);
+		if (likely(priv->tx_queue[0]->txcoalescing))
+			gfar_write(&regs->txic, priv->tx_queue[0]->txic);
 
-	gfar_write(&regs->attr, attrs);
+		gfar_write(&regs->rxic, 0);
+		if (unlikely(priv->rx_queue[0]->rxcoalescing))
+			gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
+	}
+}
 
-	gfar_write(&regs->fifo_tx_thr, priv->fifo_threshold);
-	gfar_write(&regs->fifo_tx_starve, priv->fifo_starve);
-	gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
+void gfar_configure_coalescing_all(struct gfar_private *priv)
+{
+	gfar_configure_coalescing(priv, 0xFF, 0xFF);
 }
 
 static struct net_device_stats *gfar_get_stats(struct net_device *dev)
@@ -479,12 +498,27 @@ static const struct net_device_ops gfar_netdev_ops = {
 #endif
 };
 
-void lock_rx_qs(struct gfar_private *priv)
+static void gfar_ints_disable(struct gfar_private *priv)
 {
 	int i;
+	for (i = 0; i < priv->num_grps; i++) {
+		struct gfar __iomem *regs = priv->gfargrp[i].regs;
+		/* Clear IEVENT */
+		gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
 
-	for (i = 0; i < priv->num_rx_queues; i++)
-		spin_lock(&priv->rx_queue[i]->rxlock);
+		/* Initialize IMASK */
+		gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+	}
+}
+
+static void gfar_ints_enable(struct gfar_private *priv)
+{
+	int i;
+	for (i = 0; i < priv->num_grps; i++) {
+		struct gfar __iomem *regs = priv->gfargrp[i].regs;
+		/* Unmask the interrupts we look for */
+		gfar_write(&regs->imask, IMASK_DEFAULT);
+	}
 }
 
 void lock_tx_qs(struct gfar_private *priv)
@@ -495,23 +529,50 @@ void lock_tx_qs(struct gfar_private *priv)
 		spin_lock(&priv->tx_queue[i]->txlock);
 }
 
-void unlock_rx_qs(struct gfar_private *priv)
+void unlock_tx_qs(struct gfar_private *priv)
 {
 	int i;
 
-	for (i = 0; i < priv->num_rx_queues; i++)
-		spin_unlock(&priv->rx_queue[i]->rxlock);
+	for (i = 0; i < priv->num_tx_queues; i++)
+		spin_unlock(&priv->tx_queue[i]->txlock);
 }
 
-void unlock_tx_qs(struct gfar_private *priv)
+static int gfar_alloc_tx_queues(struct gfar_private *priv)
 {
 	int i;
 
-	for (i = 0; i < priv->num_tx_queues; i++)
-		spin_unlock(&priv->tx_queue[i]->txlock);
+	for (i = 0; i < priv->num_tx_queues; i++) {
+		priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
+					    GFP_KERNEL);
+		if (!priv->tx_queue[i])
+			return -ENOMEM;
+
+		priv->tx_queue[i]->tx_skbuff = NULL;
+		priv->tx_queue[i]->qindex = i;
+		priv->tx_queue[i]->dev = priv->ndev;
+		spin_lock_init(&(priv->tx_queue[i]->txlock));
+	}
+	return 0;
+}
+
+static int gfar_alloc_rx_queues(struct gfar_private *priv)
+{
+	int i;
+
+	for (i = 0; i < priv->num_rx_queues; i++) {
+		priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
+					    GFP_KERNEL);
+		if (!priv->rx_queue[i])
+			return -ENOMEM;
+
+		priv->rx_queue[i]->rx_skbuff = NULL;
+		priv->rx_queue[i]->qindex = i;
+		priv->rx_queue[i]->dev = priv->ndev;
+	}
+	return 0;
 }
 
-static void free_tx_pointers(struct gfar_private *priv)
+static void gfar_free_tx_queues(struct gfar_private *priv)
 {
 	int i;
 
@@ -519,7 +580,7 @@ static void free_tx_pointers(struct gfar_private *priv)
 		kfree(priv->tx_queue[i]);
 }
 
-static void free_rx_pointers(struct gfar_private *priv)
+static void gfar_free_rx_queues(struct gfar_private *priv)
 {
 	int i;
 
@@ -608,6 +669,30 @@ static int gfar_parse_group(struct device_node *np,
 		grp->rx_bit_map = 0xFF;
 		grp->tx_bit_map = 0xFF;
 	}
+
+	/* bit_map's MSB is q0 (from q0 to q7) but, for_each_set_bit parses
+	 * right to left, so we need to revert the 8 bits to get the q index
+	 */
+	grp->rx_bit_map = bitrev8(grp->rx_bit_map);
+	grp->tx_bit_map = bitrev8(grp->tx_bit_map);
+
+	/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
+	 * also assign queues to groups
+	 */
+	for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
+		grp->num_rx_queues++;
+		grp->rstat |= (RSTAT_CLEAR_RHALT >> i);
+		priv->rqueue |= ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
+		priv->rx_queue[i]->grp = grp;
+	}
+
+	for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
+		grp->num_tx_queues++;
+		grp->tstat |= (TSTAT_CLEAR_THALT >> i);
+		priv->tqueue |= (TQUEUE_EN0 >> i);
+		priv->tx_queue[i]->grp = grp;
+	}
+
 	priv->num_grps++;
 
 	return 0;
@@ -664,7 +749,14 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 	priv->num_tx_queues = num_tx_qs;
 	netif_set_real_num_rx_queues(dev, num_rx_qs);
 	priv->num_rx_queues = num_rx_qs;
-	priv->num_grps = 0x0;
+
+	err = gfar_alloc_tx_queues(priv);
+	if (err)
+		goto tx_alloc_failed;
+
+	err = gfar_alloc_rx_queues(priv);
+	if (err)
+		goto rx_alloc_failed;
 
 	/* Init Rx queue filer rule set linked list */
 	INIT_LIST_HEAD(&priv->rx_list.list);
@@ -691,38 +783,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 			goto err_grp_init;
 	}
 
-	for (i = 0; i < priv->num_tx_queues; i++)
-		priv->tx_queue[i] = NULL;
-	for (i = 0; i < priv->num_rx_queues; i++)
-		priv->rx_queue[i] = NULL;
-
-	for (i = 0; i < priv->num_tx_queues; i++) {
-		priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
-					    GFP_KERNEL);
-		if (!priv->tx_queue[i]) {
-			err = -ENOMEM;
-			goto tx_alloc_failed;
-		}
-		priv->tx_queue[i]->tx_skbuff = NULL;
-		priv->tx_queue[i]->qindex = i;
-		priv->tx_queue[i]->dev = dev;
-		spin_lock_init(&(priv->tx_queue[i]->txlock));
-	}
-
-	for (i = 0; i < priv->num_rx_queues; i++) {
-		priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
-					    GFP_KERNEL);
-		if (!priv->rx_queue[i]) {
-			err = -ENOMEM;
-			goto rx_alloc_failed;
-		}
-		priv->rx_queue[i]->rx_skbuff = NULL;
-		priv->rx_queue[i]->qindex = i;
-		priv->rx_queue[i]->dev = dev;
-		spin_lock_init(&(priv->rx_queue[i]->rxlock));
-	}
-
-
 	stash = of_get_property(np, "bd-stash", NULL);
 
 	if (stash) {
@@ -749,17 +809,16 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 		memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
 
 	if (model && !strcasecmp(model, "TSEC"))
-		priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
 				     FSL_GIANFAR_DEV_HAS_COALESCE |
 				     FSL_GIANFAR_DEV_HAS_RMON |
 				     FSL_GIANFAR_DEV_HAS_MULTI_INTR;
 
 	if (model && !strcasecmp(model, "eTSEC"))
-		priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
 				     FSL_GIANFAR_DEV_HAS_COALESCE |
 				     FSL_GIANFAR_DEV_HAS_RMON |
 				     FSL_GIANFAR_DEV_HAS_MULTI_INTR |
-				     FSL_GIANFAR_DEV_HAS_PADDING |
 				     FSL_GIANFAR_DEV_HAS_CSUM |
 				     FSL_GIANFAR_DEV_HAS_VLAN |
 				     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
@@ -784,12 +843,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 
 	return 0;
 
-rx_alloc_failed:
-	free_rx_pointers(priv);
-tx_alloc_failed:
-	free_tx_pointers(priv);
 err_grp_init:
 	unmap_group_regs(priv);
+rx_alloc_failed:
+	gfar_free_rx_queues(priv);
+tx_alloc_failed:
+	gfar_free_tx_queues(priv);
 	free_gfar_dev(priv);
 	return err;
 }
@@ -822,18 +881,16 @@ static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		if (priv->hwts_rx_en) {
-			stop_gfar(netdev);
 			priv->hwts_rx_en = 0;
-			startup_gfar(netdev);
+			reset_gfar(netdev);
 		}
 		break;
 	default:
 		if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
 			return -ERANGE;
 		if (!priv->hwts_rx_en) {
-			stop_gfar(netdev);
 			priv->hwts_rx_en = 1;
-			startup_gfar(netdev);
+			reset_gfar(netdev);
 		}
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
@@ -875,19 +932,6 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return phy_mii_ioctl(priv->phydev, rq, cmd);
 }
 
-static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs)
-{
-	unsigned int new_bit_map = 0x0;
-	int mask = 0x1 << (max_qs - 1), i;
-
-	for (i = 0; i < max_qs; i++) {
-		if (bit_map & mask)
-			new_bit_map = new_bit_map + (1 << i);
-		mask = mask >> 0x1;
-	}
-	return new_bit_map;
-}
-
 static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar,
 				   u32 class)
 {
@@ -1005,99 +1049,140 @@ static void gfar_detect_errata(struct gfar_private *priv)
 			 priv->errata);
 }
 
-/* Set up the ethernet device structure, private data,
- * and anything else we need before we start
- */
-static int gfar_probe(struct platform_device *ofdev)
+void gfar_mac_reset(struct gfar_private *priv)
 {
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 tempval;
-	struct net_device *dev = NULL;
-	struct gfar_private *priv = NULL;
-	struct gfar __iomem *regs = NULL;
-	int err = 0, i, grp_idx = 0;
-	u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0;
-	u32 isrg = 0;
-	u32 __iomem *baddr;
-
-	err = gfar_of_init(ofdev, &dev);
-
-	if (err)
-		return err;
-
-	priv = netdev_priv(dev);
-	priv->ndev = dev;
-	priv->ofdev = ofdev;
-	priv->dev = &ofdev->dev;
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
-	spin_lock_init(&priv->bflock);
-	INIT_WORK(&priv->reset_task, gfar_reset_task);
-
-	platform_set_drvdata(ofdev, priv);
-	regs = priv->gfargrp[0].regs;
-
-	gfar_detect_errata(priv);
-
-	/* Stop the DMA engine now, in case it was running before
-	 * (The firmware could have used it, and left it running).
-	 */
-	gfar_halt(dev);
 
 	/* Reset MAC layer */
 	gfar_write(&regs->maccfg1, MACCFG1_SOFT_RESET);
 
 	/* We need to delay at least 3 TX clocks */
-	udelay(2);
+	udelay(3);
 
-	tempval = 0;
-	if (!priv->pause_aneg_en && priv->tx_pause_en)
-		tempval |= MACCFG1_TX_FLOW;
-	if (!priv->pause_aneg_en && priv->rx_pause_en)
-		tempval |= MACCFG1_RX_FLOW;
 	/* the soft reset bit is not self-resetting, so we need to
 	 * clear it before resuming normal operation
 	 */
-	gfar_write(&regs->maccfg1, tempval);
+	gfar_write(&regs->maccfg1, 0);
+
+	udelay(3);
+
+	/* Compute rx_buff_size based on config flags */
+	gfar_rx_buff_size_config(priv);
+
+	/* Initialize the max receive frame/buffer lengths */
+	gfar_write(&regs->maxfrm, priv->rx_buffer_size);
+	gfar_write(&regs->mrblr, priv->rx_buffer_size);
+
+	/* Initialize the Minimum Frame Length Register */
+	gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
 
 	/* Initialize MACCFG2. */
 	tempval = MACCFG2_INIT_SETTINGS;
-	if (gfar_has_errata(priv, GFAR_ERRATA_74))
+
+	/* If the mtu is larger than the max size for standard
+	 * ethernet frames (ie, a jumbo frame), then set maccfg2
+	 * to allow huge frames, and to check the length
+	 */
+	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
+	    gfar_has_errata(priv, GFAR_ERRATA_74))
 		tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK;
+
 	gfar_write(&regs->maccfg2, tempval);
 
+	/* Clear mac addr hash registers */
+	gfar_write(&regs->igaddr0, 0);
+	gfar_write(&regs->igaddr1, 0);
+	gfar_write(&regs->igaddr2, 0);
+	gfar_write(&regs->igaddr3, 0);
+	gfar_write(&regs->igaddr4, 0);
+	gfar_write(&regs->igaddr5, 0);
+	gfar_write(&regs->igaddr6, 0);
+	gfar_write(&regs->igaddr7, 0);
+
+	gfar_write(&regs->gaddr0, 0);
+	gfar_write(&regs->gaddr1, 0);
+	gfar_write(&regs->gaddr2, 0);
+	gfar_write(&regs->gaddr3, 0);
+	gfar_write(&regs->gaddr4, 0);
+	gfar_write(&regs->gaddr5, 0);
+	gfar_write(&regs->gaddr6, 0);
+	gfar_write(&regs->gaddr7, 0);
+
+	if (priv->extended_hash)
+		gfar_clear_exact_match(priv->ndev);
+
+	gfar_mac_rx_config(priv);
+
+	gfar_mac_tx_config(priv);
+
+	gfar_set_mac_address(priv->ndev);
+
+	gfar_set_multi(priv->ndev);
+
+	/* clear ievent and imask before configuring coalescing */
+	gfar_ints_disable(priv);
+
+	/* Configure the coalescing support */
+	gfar_configure_coalescing_all(priv);
+}
+
+static void gfar_hw_init(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+	u32 attrs;
+
+	/* Stop the DMA engine now, in case it was running before
+	 * (The firmware could have used it, and left it running).
+	 */
+	gfar_halt(priv);
+
+	gfar_mac_reset(priv);
+
+	/* Zero out the rmon mib registers if it has them */
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
+		memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib));
+
+		/* Mask off the CAM interrupts */
+		gfar_write(&regs->rmon.cam1, 0xffffffff);
+		gfar_write(&regs->rmon.cam2, 0xffffffff);
+	}
+
 	/* Initialize ECNTRL */
 	gfar_write(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
 
-	/* Set the dev->base_addr to the gfar reg region */
-	dev->base_addr = (unsigned long) regs;
+	/* Set the extraction length and index */
+	attrs = ATTRELI_EL(priv->rx_stash_size) |
+		ATTRELI_EI(priv->rx_stash_index);
 
-	/* Fill in the dev structure */
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->mtu = 1500;
-	dev->netdev_ops = &gfar_netdev_ops;
-	dev->ethtool_ops = &gfar_ethtool_ops;
+	gfar_write(&regs->attreli, attrs);
 
-	/* Register for napi ...We are registering NAPI for each grp */
-	if (priv->mode == SQ_SG_MODE)
-		netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq,
-			       GFAR_DEV_WEIGHT);
-	else
-		for (i = 0; i < priv->num_grps; i++)
-			netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
-				       GFAR_DEV_WEIGHT);
+	/* Start with defaults, and add stashing
+	 * depending on driver parameters
+	 */
+	attrs = ATTR_INIT_SETTINGS;
 
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
-		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-				   NETIF_F_RXCSUM;
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
-				 NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
-	}
+	if (priv->bd_stash_en)
+		attrs |= ATTR_BDSTASH;
 
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
-		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_HW_VLAN_CTAG_RX;
-		dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
-	}
+	if (priv->rx_stash_size != 0)
+		attrs |= ATTR_BUFSTASH;
+
+	gfar_write(&regs->attr, attrs);
+
+	/* FIFO configs */
+	gfar_write(&regs->fifo_tx_thr, DEFAULT_FIFO_TX_THR);
+	gfar_write(&regs->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE);
+	gfar_write(&regs->fifo_tx_starve_shutoff, DEFAULT_FIFO_TX_STARVE_OFF);
+
+	/* Program the interrupt steering regs, only for MG devices */
+	if (priv->num_grps > 1)
+		gfar_write_isrg(priv);
+}
+
+static void __init gfar_init_addr_hash_table(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
 		priv->extended_hash = 1;
@@ -1133,68 +1218,75 @@ static int gfar_probe(struct platform_device *ofdev)
 		priv->hash_regs[6] = &regs->gaddr6;
 		priv->hash_regs[7] = &regs->gaddr7;
 	}
+}
 
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
-		priv->padding = DEFAULT_PADDING;
-	else
-		priv->padding = 0;
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start
+ */
+static int gfar_probe(struct platform_device *ofdev)
+{
+	struct net_device *dev = NULL;
+	struct gfar_private *priv = NULL;
+	int err = 0, i;
 
-	if (dev->features & NETIF_F_IP_CSUM ||
-	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
-		dev->needed_headroom = GMAC_FCB_LEN;
+	err = gfar_of_init(ofdev, &dev);
 
-	/* Program the isrg regs only if number of grps > 1 */
-	if (priv->num_grps > 1) {
-		baddr = &regs->isrg0;
-		for (i = 0; i < priv->num_grps; i++) {
-			isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX);
-			isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX);
-			gfar_write(baddr, isrg);
-			baddr++;
-			isrg = 0x0;
-		}
-	}
+	if (err)
+		return err;
 
-	/* Need to reverse the bit maps as  bit_map's MSB is q0
-	 * but, for_each_set_bit parses from right to left, which
-	 * basically reverses the queue numbers
-	 */
-	for (i = 0; i< priv->num_grps; i++) {
-		priv->gfargrp[i].tx_bit_map =
-			reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS);
-		priv->gfargrp[i].rx_bit_map =
-			reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS);
+	priv = netdev_priv(dev);
+	priv->ndev = dev;
+	priv->ofdev = ofdev;
+	priv->dev = &ofdev->dev;
+	SET_NETDEV_DEV(dev, &ofdev->dev);
+
+	spin_lock_init(&priv->bflock);
+	INIT_WORK(&priv->reset_task, gfar_reset_task);
+
+	platform_set_drvdata(ofdev, priv);
+
+	gfar_detect_errata(priv);
+
+	/* Set the dev->base_addr to the gfar reg region */
+	dev->base_addr = (unsigned long) priv->gfargrp[0].regs;
+
+	/* Fill in the dev structure */
+	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->mtu = 1500;
+	dev->netdev_ops = &gfar_netdev_ops;
+	dev->ethtool_ops = &gfar_ethtool_ops;
+
+	/* Register for napi ...We are registering NAPI for each grp */
+	if (priv->mode == SQ_SG_MODE)
+		netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq,
+			       GFAR_DEV_WEIGHT);
+	else
+		for (i = 0; i < priv->num_grps; i++)
+			netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
+				       GFAR_DEV_WEIGHT);
+
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
+		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+				   NETIF_F_RXCSUM;
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
+				 NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
 	}
 
-	/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
-	 * also assign queues to groups
-	 */
-	for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
-		priv->gfargrp[grp_idx].num_rx_queues = 0x0;
-
-		for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
-				 priv->num_rx_queues) {
-			priv->gfargrp[grp_idx].num_rx_queues++;
-			priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
-			rstat = rstat | (RSTAT_CLEAR_RHALT >> i);
-			rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
-		}
-		priv->gfargrp[grp_idx].num_tx_queues = 0x0;
-
-		for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
-				 priv->num_tx_queues) {
-			priv->gfargrp[grp_idx].num_tx_queues++;
-			priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
-			tstat = tstat | (TSTAT_CLEAR_THALT >> i);
-			tqueue = tqueue | (TQUEUE_EN0 >> i);
-		}
-		priv->gfargrp[grp_idx].rstat = rstat;
-		priv->gfargrp[grp_idx].tstat = tstat;
-		rstat = tstat =0;
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
+		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
+				    NETIF_F_HW_VLAN_CTAG_RX;
+		dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 	}
 
-	gfar_write(&regs->rqueue, rqueue);
-	gfar_write(&regs->tqueue, tqueue);
+	gfar_init_addr_hash_table(priv);
+
+	/* Insert receive time stamps into padding alignment bytes */
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
+		priv->padding = 8;
+
+	if (dev->features & NETIF_F_IP_CSUM ||
+	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
+		dev->needed_headroom = GMAC_FCB_LEN;
 
 	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
 
@@ -1220,8 +1312,9 @@ static int gfar_probe(struct platform_device *ofdev)
 	if (priv->num_tx_queues == 1)
 		priv->prio_sched_en = 1;
 
-	/* Carrier starts down, phylib will bring it up */
-	netif_carrier_off(dev);
+	set_bit(GFAR_DOWN, &priv->state);
+
+	gfar_hw_init(priv);
 
 	err = register_netdev(dev);
 
@@ -1230,6 +1323,9 @@ static int gfar_probe(struct platform_device *ofdev)
 		goto register_fail;
 	}
 
+	/* Carrier starts down, phylib will bring it up */
+	netif_carrier_off(dev);
+
 	device_init_wakeup(&dev->dev,
 			   priv->device_flags &
 			   FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
@@ -1251,9 +1347,6 @@ static int gfar_probe(struct platform_device *ofdev)
 	/* Initialize the filer table */
 	gfar_init_filer_table(priv);
 
-	/* Create all the sysfs files */
-	gfar_init_sysfs(dev);
-
 	/* Print out the device info */
 	netdev_info(dev, "mac: %pM\n", dev->dev_addr);
 
@@ -1272,8 +1365,8 @@ static int gfar_probe(struct platform_device *ofdev)
 
 register_fail:
 	unmap_group_regs(priv);
-	free_tx_pointers(priv);
-	free_rx_pointers(priv);
+	gfar_free_rx_queues(priv);
+	gfar_free_tx_queues(priv);
 	if (priv->phy_node)
 		of_node_put(priv->phy_node);
 	if (priv->tbi_node)
@@ -1293,6 +1386,8 @@ static int gfar_remove(struct platform_device *ofdev)
 
 	unregister_netdev(priv->ndev);
 	unmap_group_regs(priv);
+	gfar_free_rx_queues(priv);
+	gfar_free_tx_queues(priv);
 	free_gfar_dev(priv);
 
 	return 0;
@@ -1318,9 +1413,8 @@ static int gfar_suspend(struct device *dev)
 
 		local_irq_save(flags);
 		lock_tx_qs(priv);
-		lock_rx_qs(priv);
 
-		gfar_halt_nodisable(ndev);
+		gfar_halt_nodisable(priv);
 
 		/* Disable Tx, and Rx if wake-on-LAN is disabled. */
 		tempval = gfar_read(&regs->maccfg1);
@@ -1332,7 +1426,6 @@ static int gfar_suspend(struct device *dev)
 
 		gfar_write(&regs->maccfg1, tempval);
 
-		unlock_rx_qs(priv);
 		unlock_tx_qs(priv);
 		local_irq_restore(flags);
 
@@ -1378,15 +1471,13 @@ static int gfar_resume(struct device *dev)
 	 */
 	local_irq_save(flags);
 	lock_tx_qs(priv);
-	lock_rx_qs(priv);
 
 	tempval = gfar_read(&regs->maccfg2);
 	tempval &= ~MACCFG2_MPEN;
 	gfar_write(&regs->maccfg2, tempval);
 
-	gfar_start(ndev);
+	gfar_start(priv);
 
-	unlock_rx_qs(priv);
 	unlock_tx_qs(priv);
 	local_irq_restore(flags);
 
@@ -1413,10 +1504,11 @@ static int gfar_restore(struct device *dev)
 		return -ENOMEM;
 	}
 
-	init_registers(ndev);
-	gfar_set_mac_address(ndev);
-	gfar_init_mac(ndev);
-	gfar_start(ndev);
+	gfar_mac_reset(priv);
+
+	gfar_init_tx_rx_base(priv);
+
+	gfar_start(priv);
 
 	priv->oldlink = 0;
 	priv->oldspeed = 0;
@@ -1554,75 +1646,24 @@ static void gfar_configure_serdes(struct net_device *dev)
 		return;
 	}
 
-	/* If the link is already up, we must already be ok, and don't need to
-	 * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
-	 * everything for us?  Resetting it takes the link down and requires
-	 * several seconds for it to come back.
-	 */
-	if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS)
-		return;
-
-	/* Single clk mode, mii mode off(for serdes communication) */
-	phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT);
-
-	phy_write(tbiphy, MII_ADVERTISE,
-		  ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
-		  ADVERTISE_1000XPSE_ASYM);
-
-	phy_write(tbiphy, MII_BMCR,
-		  BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX |
-		  BMCR_SPEED1000);
-}
-
-static void init_registers(struct net_device *dev)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar __iomem *regs = NULL;
-	int i;
-
-	for (i = 0; i < priv->num_grps; i++) {
-		regs = priv->gfargrp[i].regs;
-		/* Clear IEVENT */
-		gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
-
-		/* Initialize IMASK */
-		gfar_write(&regs->imask, IMASK_INIT_CLEAR);
-	}
-
-	regs = priv->gfargrp[0].regs;
-	/* Init hash registers to zero */
-	gfar_write(&regs->igaddr0, 0);
-	gfar_write(&regs->igaddr1, 0);
-	gfar_write(&regs->igaddr2, 0);
-	gfar_write(&regs->igaddr3, 0);
-	gfar_write(&regs->igaddr4, 0);
-	gfar_write(&regs->igaddr5, 0);
-	gfar_write(&regs->igaddr6, 0);
-	gfar_write(&regs->igaddr7, 0);
-
-	gfar_write(&regs->gaddr0, 0);
-	gfar_write(&regs->gaddr1, 0);
-	gfar_write(&regs->gaddr2, 0);
-	gfar_write(&regs->gaddr3, 0);
-	gfar_write(&regs->gaddr4, 0);
-	gfar_write(&regs->gaddr5, 0);
-	gfar_write(&regs->gaddr6, 0);
-	gfar_write(&regs->gaddr7, 0);
-
-	/* Zero out the rmon mib registers if it has them */
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
-		memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib));
+	/* If the link is already up, we must already be ok, and don't need to
+	 * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
+	 * everything for us?  Resetting it takes the link down and requires
+	 * several seconds for it to come back.
+	 */
+	if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS)
+		return;
 
-		/* Mask off the CAM interrupts */
-		gfar_write(&regs->rmon.cam1, 0xffffffff);
-		gfar_write(&regs->rmon.cam2, 0xffffffff);
-	}
+	/* Single clk mode, mii mode off(for serdes communication) */
+	phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT);
 
-	/* Initialize the max receive buffer length */
-	gfar_write(&regs->mrblr, priv->rx_buffer_size);
+	phy_write(tbiphy, MII_ADVERTISE,
+		  ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+		  ADVERTISE_1000XPSE_ASYM);
 
-	/* Initialize the Minimum Frame Length Register */
-	gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
+	phy_write(tbiphy, MII_BMCR,
+		  BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX |
+		  BMCR_SPEED1000);
 }
 
 static int __gfar_is_rx_idle(struct gfar_private *priv)
@@ -1648,23 +1689,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
 }
 
 /* Halt the receive and transmit queues */
-static void gfar_halt_nodisable(struct net_device *dev)
+static void gfar_halt_nodisable(struct gfar_private *priv)
 {
-	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar __iomem *regs = NULL;
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 tempval;
-	int i;
-
-	for (i = 0; i < priv->num_grps; i++) {
-		regs = priv->gfargrp[i].regs;
-		/* Mask all interrupts */
-		gfar_write(&regs->imask, IMASK_INIT_CLEAR);
 
-		/* Clear all interrupts */
-		gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
-	}
+	gfar_ints_disable(priv);
 
-	regs = priv->gfargrp[0].regs;
 	/* Stop the DMA, and wait for it to stop */
 	tempval = gfar_read(&regs->dmactrl);
 	if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
@@ -1685,56 +1716,41 @@ static void gfar_halt_nodisable(struct net_device *dev)
 }
 
 /* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+void gfar_halt(struct gfar_private *priv)
 {
-	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 tempval;
 
-	gfar_halt_nodisable(dev);
+	/* Dissable the Rx/Tx hw queues */
+	gfar_write(&regs->rqueue, 0);
+	gfar_write(&regs->tqueue, 0);
+
+	mdelay(10);
 
-	/* Disable Rx and Tx */
+	gfar_halt_nodisable(priv);
+
+	/* Disable Rx/Tx DMA */
 	tempval = gfar_read(&regs->maccfg1);
 	tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
 	gfar_write(&regs->maccfg1, tempval);
 }
 
-static void free_grp_irqs(struct gfar_priv_grp *grp)
-{
-	free_irq(gfar_irq(grp, TX)->irq, grp);
-	free_irq(gfar_irq(grp, RX)->irq, grp);
-	free_irq(gfar_irq(grp, ER)->irq, grp);
-}
-
 void stop_gfar(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	unsigned long flags;
-	int i;
-
-	phy_stop(priv->phydev);
 
+	netif_tx_stop_all_queues(dev);
 
-	/* Lock it down */
-	local_irq_save(flags);
-	lock_tx_qs(priv);
-	lock_rx_qs(priv);
+	smp_mb__before_clear_bit();
+	set_bit(GFAR_DOWN, &priv->state);
+	smp_mb__after_clear_bit();
 
-	gfar_halt(dev);
+	disable_napi(priv);
 
-	unlock_rx_qs(priv);
-	unlock_tx_qs(priv);
-	local_irq_restore(flags);
+	/* disable ints and gracefully shut down Rx/Tx DMA */
+	gfar_halt(priv);
 
-	/* Free the IRQs */
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
-		for (i = 0; i < priv->num_grps; i++)
-			free_grp_irqs(&priv->gfargrp[i]);
-	} else {
-		for (i = 0; i < priv->num_grps; i++)
-			free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
-				 &priv->gfargrp[i]);
-	}
+	phy_stop(priv->phydev);
 
 	free_skb_resources(priv);
 }
@@ -1825,17 +1841,15 @@ static void free_skb_resources(struct gfar_private *priv)
 			  priv->tx_queue[0]->tx_bd_dma_base);
 }
 
-void gfar_start(struct net_device *dev)
+void gfar_start(struct gfar_private *priv)
 {
-	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 tempval;
 	int i = 0;
 
-	/* Enable Rx and Tx in MACCFG1 */
-	tempval = gfar_read(&regs->maccfg1);
-	tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
-	gfar_write(&regs->maccfg1, tempval);
+	/* Enable Rx/Tx hw queues */
+	gfar_write(&regs->rqueue, priv->rqueue);
+	gfar_write(&regs->tqueue, priv->tqueue);
 
 	/* Initialize DMACTRL to have WWR and WOP */
 	tempval = gfar_read(&regs->dmactrl);
@@ -1852,52 +1866,23 @@ void gfar_start(struct net_device *dev)
 		/* Clear THLT/RHLT, so that the DMA starts polling now */
 		gfar_write(&regs->tstat, priv->gfargrp[i].tstat);
 		gfar_write(&regs->rstat, priv->gfargrp[i].rstat);
-		/* Unmask the interrupts we look for */
-		gfar_write(&regs->imask, IMASK_DEFAULT);
 	}
 
-	dev->trans_start = jiffies; /* prevent tx timeout */
-}
-
-static void gfar_configure_coalescing(struct gfar_private *priv,
-			       unsigned long tx_mask, unsigned long rx_mask)
-{
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	u32 __iomem *baddr;
-
-	if (priv->mode == MQ_MG_MODE) {
-		int i = 0;
-
-		baddr = &regs->txic0;
-		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
-			gfar_write(baddr + i, 0);
-			if (likely(priv->tx_queue[i]->txcoalescing))
-				gfar_write(baddr + i, priv->tx_queue[i]->txic);
-		}
+	/* Enable Rx/Tx DMA */
+	tempval = gfar_read(&regs->maccfg1);
+	tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+	gfar_write(&regs->maccfg1, tempval);
 
-		baddr = &regs->rxic0;
-		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
-			gfar_write(baddr + i, 0);
-			if (likely(priv->rx_queue[i]->rxcoalescing))
-				gfar_write(baddr + i, priv->rx_queue[i]->rxic);
-		}
-	} else {
-		/* Backward compatible case -- even if we enable
-		 * multiple queues, there's only single reg to program
-		 */
-		gfar_write(&regs->txic, 0);
-		if (likely(priv->tx_queue[0]->txcoalescing))
-			gfar_write(&regs->txic, priv->tx_queue[0]->txic);
+	gfar_ints_enable(priv);
 
-		gfar_write(&regs->rxic, 0);
-		if (unlikely(priv->rx_queue[0]->rxcoalescing))
-			gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
-	}
+	priv->ndev->trans_start = jiffies; /* prevent tx timeout */
 }
 
-void gfar_configure_coalescing_all(struct gfar_private *priv)
+static void free_grp_irqs(struct gfar_priv_grp *grp)
 {
-	gfar_configure_coalescing(priv, 0xFF, 0xFF);
+	free_irq(gfar_irq(grp, TX)->irq, grp);
+	free_irq(gfar_irq(grp, RX)->irq, grp);
+	free_irq(gfar_irq(grp, ER)->irq, grp);
 }
 
 static int register_grp_irqs(struct gfar_priv_grp *grp)
@@ -1956,46 +1941,65 @@ err_irq_fail:
 
 }
 
-/* Bring the controller up and running */
-int startup_gfar(struct net_device *ndev)
+static void gfar_free_irq(struct gfar_private *priv)
 {
-	struct gfar_private *priv = netdev_priv(ndev);
-	struct gfar __iomem *regs = NULL;
-	int err, i, j;
+	int i;
 
-	for (i = 0; i < priv->num_grps; i++) {
-		regs= priv->gfargrp[i].regs;
-		gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+	/* Free the IRQs */
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+		for (i = 0; i < priv->num_grps; i++)
+			free_grp_irqs(&priv->gfargrp[i]);
+	} else {
+		for (i = 0; i < priv->num_grps; i++)
+			free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
+				 &priv->gfargrp[i]);
 	}
+}
 
-	regs= priv->gfargrp[0].regs;
-	err = gfar_alloc_skb_resources(ndev);
-	if (err)
-		return err;
-
-	gfar_init_mac(ndev);
+static int gfar_request_irq(struct gfar_private *priv)
+{
+	int err, i, j;
 
 	for (i = 0; i < priv->num_grps; i++) {
 		err = register_grp_irqs(&priv->gfargrp[i]);
 		if (err) {
 			for (j = 0; j < i; j++)
 				free_grp_irqs(&priv->gfargrp[j]);
-			goto irq_fail;
+			return err;
 		}
 	}
 
-	/* Start the controller */
-	gfar_start(ndev);
+	return 0;
+}
+
+/* Bring the controller up and running */
+int startup_gfar(struct net_device *ndev)
+{
+	struct gfar_private *priv = netdev_priv(ndev);
+	int err;
+
+	gfar_mac_reset(priv);
+
+	err = gfar_alloc_skb_resources(ndev);
+	if (err)
+		return err;
+
+	gfar_init_tx_rx_base(priv);
+
+	smp_mb__before_clear_bit();
+	clear_bit(GFAR_DOWN, &priv->state);
+	smp_mb__after_clear_bit();
+
+	/* Start Rx/Tx DMA and enable the interrupts */
+	gfar_start(priv);
 
 	phy_start(priv->phydev);
 
-	gfar_configure_coalescing_all(priv);
+	enable_napi(priv);
 
-	return 0;
+	netif_tx_wake_all_queues(ndev);
 
-irq_fail:
-	free_skb_resources(priv);
-	return err;
+	return 0;
 }
 
 /* Called when something needs to use the ethernet device
@@ -2006,27 +2010,17 @@ static int gfar_enet_open(struct net_device *dev)
 	struct gfar_private *priv = netdev_priv(dev);
 	int err;
 
-	enable_napi(priv);
-
-	/* Initialize a bunch of registers */
-	init_registers(dev);
-
-	gfar_set_mac_address(dev);
-
 	err = init_phy(dev);
+	if (err)
+		return err;
 
-	if (err) {
-		disable_napi(priv);
+	err = gfar_request_irq(priv);
+	if (err)
 		return err;
-	}
 
 	err = startup_gfar(dev);
-	if (err) {
-		disable_napi(priv);
+	if (err)
 		return err;
-	}
-
-	netif_tx_start_all_queues(dev);
 
 	device_set_wakeup_enable(&dev->dev, priv->wol_en);
 
@@ -2351,8 +2345,6 @@ static int gfar_close(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 
-	disable_napi(priv);
-
 	cancel_work_sync(&priv->reset_task);
 	stop_gfar(dev);
 
@@ -2360,7 +2352,7 @@ static int gfar_close(struct net_device *dev)
 	phy_disconnect(priv->phydev);
 	priv->phydev = NULL;
 
-	netif_tx_stop_all_queues(dev);
+	gfar_free_irq(priv);
 
 	return 0;
 }
@@ -2373,77 +2365,9 @@ static int gfar_set_mac_address(struct net_device *dev)
 	return 0;
 }
 
-/* Check if rx parser should be activated */
-void gfar_check_rx_parser_mode(struct gfar_private *priv)
-{
-	struct gfar __iomem *regs;
-	u32 tempval;
-
-	regs = priv->gfargrp[0].regs;
-
-	tempval = gfar_read(&regs->rctrl);
-	/* If parse is no longer required, then disable parser */
-	if (tempval & RCTRL_REQ_PARSER) {
-		tempval |= RCTRL_PRSDEP_INIT;
-		priv->uses_rxfcb = 1;
-	} else {
-		tempval &= ~RCTRL_PRSDEP_INIT;
-		priv->uses_rxfcb = 0;
-	}
-	gfar_write(&regs->rctrl, tempval);
-}
-
-/* Enables and disables VLAN insertion/extraction */
-void gfar_vlan_mode(struct net_device *dev, netdev_features_t features)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar __iomem *regs = NULL;
-	unsigned long flags;
-	u32 tempval;
-
-	regs = priv->gfargrp[0].regs;
-	local_irq_save(flags);
-	lock_rx_qs(priv);
-
-	if (features & NETIF_F_HW_VLAN_CTAG_TX) {
-		/* Enable VLAN tag insertion */
-		tempval = gfar_read(&regs->tctrl);
-		tempval |= TCTRL_VLINS;
-		gfar_write(&regs->tctrl, tempval);
-	} else {
-		/* Disable VLAN tag insertion */
-		tempval = gfar_read(&regs->tctrl);
-		tempval &= ~TCTRL_VLINS;
-		gfar_write(&regs->tctrl, tempval);
-	}
-
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
-		/* Enable VLAN tag extraction */
-		tempval = gfar_read(&regs->rctrl);
-		tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
-		gfar_write(&regs->rctrl, tempval);
-		priv->uses_rxfcb = 1;
-	} else {
-		/* Disable VLAN tag extraction */
-		tempval = gfar_read(&regs->rctrl);
-		tempval &= ~RCTRL_VLEX;
-		gfar_write(&regs->rctrl, tempval);
-
-		gfar_check_rx_parser_mode(priv);
-	}
-
-	gfar_change_mtu(dev, dev->mtu);
-
-	unlock_rx_qs(priv);
-	local_irq_restore(flags);
-}
-
 static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 {
-	int tempsize, tempval;
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	int oldsize = priv->rx_buffer_size;
 	int frame_size = new_mtu + ETH_HLEN;
 
 	if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
@@ -2451,45 +2375,33 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 		return -EINVAL;
 	}
 
-	if (priv->uses_rxfcb)
-		frame_size += GMAC_FCB_LEN;
-
-	frame_size += priv->padding;
-
-	tempsize = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
-		   INCREMENTAL_BUFFER_SIZE;
+	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+		cpu_relax();
 
-	/* Only stop and start the controller if it isn't already
-	 * stopped, and we changed something
-	 */
-	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
+	if (dev->flags & IFF_UP)
 		stop_gfar(dev);
 
-	priv->rx_buffer_size = tempsize;
-
 	dev->mtu = new_mtu;
 
-	gfar_write(&regs->mrblr, priv->rx_buffer_size);
-	gfar_write(&regs->maxfrm, priv->rx_buffer_size);
+	if (dev->flags & IFF_UP)
+		startup_gfar(dev);
 
-	/* If the mtu is larger than the max size for standard
-	 * ethernet frames (ie, a jumbo frame), then set maccfg2
-	 * to allow huge frames, and to check the length
-	 */
-	tempval = gfar_read(&regs->maccfg2);
+	clear_bit_unlock(GFAR_RESETTING, &priv->state);
 
-	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
-	    gfar_has_errata(priv, GFAR_ERRATA_74))
-		tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
-	else
-		tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
+	return 0;
+}
 
-	gfar_write(&regs->maccfg2, tempval);
+void reset_gfar(struct net_device *ndev)
+{
+	struct gfar_private *priv = netdev_priv(ndev);
 
-	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
-		startup_gfar(dev);
+	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+		cpu_relax();
 
-	return 0;
+	stop_gfar(ndev);
+	startup_gfar(ndev);
+
+	clear_bit_unlock(GFAR_RESETTING, &priv->state);
 }
 
 /* gfar_reset_task gets scheduled when a packet has not been
@@ -2501,16 +2413,7 @@ static void gfar_reset_task(struct work_struct *work)
 {
 	struct gfar_private *priv = container_of(work, struct gfar_private,
 						 reset_task);
-	struct net_device *dev = priv->ndev;
-
-	if (dev->flags & IFF_UP) {
-		netif_tx_stop_all_queues(dev);
-		stop_gfar(dev);
-		startup_gfar(dev);
-		netif_tx_start_all_queues(dev);
-	}
-
-	netif_tx_schedule_all(dev);
+	reset_gfar(priv->ndev);
 }
 
 static void gfar_timeout(struct net_device *dev)
@@ -2623,8 +2526,10 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 	}
 
 	/* If we freed a buffer, we can restart transmission, if necessary */
-	if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree)
-		netif_wake_subqueue(dev, tqi);
+	if (tx_queue->num_txbdfree &&
+	    netif_tx_queue_stopped(txq) &&
+	    !(test_bit(GFAR_DOWN, &priv->state)))
+		netif_wake_subqueue(priv->ndev, tqi);
 
 	/* Update dirty indicators */
 	tx_queue->skb_dirtytx = skb_dirtytx;
@@ -2907,17 +2812,6 @@ static int gfar_poll_sq(struct napi_struct *napi, int budget)
 		gfar_write(&regs->rstat, gfargrp->rstat);
 
 		gfar_write(&regs->imask, IMASK_DEFAULT);
-
-		/* If we are coalescing interrupts, update the timer
-		 * Otherwise, clear it
-		 */
-		gfar_write(&regs->txic, 0);
-		if (likely(tx_queue->txcoalescing))
-			gfar_write(&regs->txic, tx_queue->txic);
-
-		gfar_write(&regs->rxic, 0);
-		if (unlikely(rx_queue->rxcoalescing))
-			gfar_write(&regs->rxic, rx_queue->rxic);
 	}
 
 	return work_done;
@@ -2987,12 +2881,6 @@ static int gfar_poll(struct napi_struct *napi, int budget)
 		gfar_write(&regs->rstat, gfargrp->rstat);
 
 		gfar_write(&regs->imask, IMASK_DEFAULT);
-
-		/* If we are coalescing interrupts, update the timer
-		 * Otherwise, clear it
-		 */
-		gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
-					  gfargrp->tx_bit_map);
 	}
 
 	return work_done;
@@ -3101,12 +2989,11 @@ static void adjust_link(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned long flags;
 	struct phy_device *phydev = priv->phydev;
 	int new_state = 0;
 
-	local_irq_save(flags);
-	lock_tx_qs(priv);
+	if (test_bit(GFAR_RESETTING, &priv->state))
+		return;
 
 	if (phydev->link) {
 		u32 tempval1 = gfar_read(&regs->maccfg1);
@@ -3178,8 +3065,6 @@ static void adjust_link(struct net_device *dev)
 
 	if (new_state && netif_msg_link(priv))
 		phy_print_status(phydev);
-	unlock_tx_qs(priv);
-	local_irq_restore(flags);
 }
 
 /* Update the hash table based on the current list of multicast
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 52bb2b0195cc..1e16216d4150 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -9,7 +9,7 @@
  * Maintainer: Kumar Gala
  * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
  *
- * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
+ * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, 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
@@ -880,7 +880,6 @@ struct gfar {
 #define FSL_GIANFAR_DEV_HAS_CSUM		0x00000010
 #define FSL_GIANFAR_DEV_HAS_VLAN		0x00000020
 #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH	0x00000040
-#define FSL_GIANFAR_DEV_HAS_PADDING		0x00000080
 #define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET	0x00000100
 #define FSL_GIANFAR_DEV_HAS_BD_STASHING		0x00000200
 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING	0x00000400
@@ -892,8 +891,8 @@ struct gfar {
 #define DEFAULT_MAPPING 	0xFF
 #endif
 
-#define ISRG_SHIFT_TX	0x10
-#define ISRG_SHIFT_RX	0x18
+#define ISRG_RR0	0x80000000
+#define ISRG_TR0	0x00800000
 
 /* The same driver can operate in two modes */
 /* SQ_SG_MODE: Single Queue Single Group Mode
@@ -966,7 +965,6 @@ struct rx_q_stats {
 
 /**
  *	struct gfar_priv_rx_q - per rx queue structure
- *	@rxlock: per queue rx spin lock
  *	@rx_skbuff: skb pointers
  *	@skb_currx: currently use skb pointer
  *	@rx_bd_base: First rx buffer descriptor
@@ -979,8 +977,7 @@ struct rx_q_stats {
  */
 
 struct gfar_priv_rx_q {
-	spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES)));
-	struct	sk_buff ** rx_skbuff;
+	struct	sk_buff **rx_skbuff __aligned(SMP_CACHE_BYTES);
 	dma_addr_t rx_bd_dma_base;
 	struct	rxbd8 *rx_bd_base;
 	struct	rxbd8 *cur_rx;
@@ -1041,6 +1038,11 @@ enum gfar_errata {
 	GFAR_ERRATA_12		= 0x08, /* a.k.a errata eTSEC49 */
 };
 
+enum gfar_dev_state {
+	GFAR_DOWN = 1,
+	GFAR_RESETTING
+};
+
 /* Struct stolen almost completely (and shamelessly) from the FCC enet source
  * (Ok, that's not so true anymore, but there is a family resemblance)
  * The GFAR buffer descriptors track the ring buffers.  The rx_bd_base
@@ -1069,6 +1071,7 @@ struct gfar_private {
 	struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
 	struct gfar_priv_grp gfargrp[MAXGROUPS];
 
+	unsigned long state;
 	u32 device_flags;
 
 	unsigned int mode;
@@ -1113,6 +1116,9 @@ struct gfar_private {
 	unsigned int total_tx_ring_size;
 	unsigned int total_rx_ring_size;
 
+	u32 rqueue;
+	u32 tqueue;
+
 	/* RX per device parameters */
 	unsigned int rx_stash_size;
 	unsigned int rx_stash_index;
@@ -1127,11 +1133,6 @@ struct gfar_private {
 	u32 __iomem *hash_regs[16];
 	int hash_width;
 
-	/* global parameters */
-	unsigned int fifo_threshold;
-	unsigned int fifo_starve;
-	unsigned int fifo_starve_off;
-
 	/*Filer table*/
 	unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
 	unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
@@ -1176,21 +1177,42 @@ static inline void gfar_read_filer(struct gfar_private *priv,
 	*fpr = gfar_read(&regs->rqfpr);
 }
 
-void lock_rx_qs(struct gfar_private *priv);
-void lock_tx_qs(struct gfar_private *priv);
-void unlock_rx_qs(struct gfar_private *priv);
-void unlock_tx_qs(struct gfar_private *priv);
+static inline void gfar_write_isrg(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+	u32 __iomem *baddr = &regs->isrg0;
+	u32 isrg = 0;
+	int grp_idx, i;
+
+	for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
+		struct gfar_priv_grp *grp = &priv->gfargrp[grp_idx];
+
+		for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
+			isrg |= (ISRG_RR0 >> i);
+		}
+
+		for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
+			isrg |= (ISRG_TR0 >> i);
+		}
+
+		gfar_write(baddr, isrg);
+
+		baddr++;
+		isrg = 0;
+	}
+}
+
 irqreturn_t gfar_receive(int irq, void *dev_id);
 int startup_gfar(struct net_device *dev);
 void stop_gfar(struct net_device *dev);
-void gfar_halt(struct net_device *dev);
+void reset_gfar(struct net_device *dev);
+void gfar_mac_reset(struct gfar_private *priv);
+void gfar_halt(struct gfar_private *priv);
+void gfar_start(struct gfar_private *priv);
 void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable,
 		   u32 regnum, u32 read);
 void gfar_configure_coalescing_all(struct gfar_private *priv);
-void gfar_init_sysfs(struct net_device *dev);
 int gfar_set_features(struct net_device *dev, netdev_features_t features);
-void gfar_check_rx_parser_mode(struct gfar_private *priv);
-void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
 
 extern const struct ethtool_ops gfar_ethtool_ops;
 
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 63d234419cc1..891dbee6e6c1 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -44,10 +44,6 @@
 
 #include "gianfar.h"
 
-extern void gfar_start(struct net_device *dev);
-extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
-			      int rx_work_limit);
-
 #define GFAR_MAX_COAL_USECS 0xffff
 #define GFAR_MAX_COAL_FRAMES 0xff
 static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
@@ -364,25 +360,11 @@ static int gfar_scoalesce(struct net_device *dev,
 			  struct ethtool_coalesce *cvals)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	int i = 0;
+	int i, err = 0;
 
 	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
 		return -EOPNOTSUPP;
 
-	/* Set up rx coalescing */
-	/* As of now, we will enable/disable coalescing for all
-	 * queues together in case of eTSEC2, this will be modified
-	 * along with the ethtool interface
-	 */
-	if ((cvals->rx_coalesce_usecs == 0) ||
-	    (cvals->rx_max_coalesced_frames == 0)) {
-		for (i = 0; i < priv->num_rx_queues; i++)
-			priv->rx_queue[i]->rxcoalescing = 0;
-	} else {
-		for (i = 0; i < priv->num_rx_queues; i++)
-			priv->rx_queue[i]->rxcoalescing = 1;
-	}
-
 	if (NULL == priv->phydev)
 		return -ENODEV;
 
@@ -399,6 +381,32 @@ static int gfar_scoalesce(struct net_device *dev,
 		return -EINVAL;
 	}
 
+	/* Check the bounds of the values */
+	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+		netdev_info(dev, "Coalescing is limited to %d microseconds\n",
+			    GFAR_MAX_COAL_USECS);
+		return -EINVAL;
+	}
+
+	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+		netdev_info(dev, "Coalescing is limited to %d frames\n",
+			    GFAR_MAX_COAL_FRAMES);
+		return -EINVAL;
+	}
+
+	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+		cpu_relax();
+
+	/* Set up rx coalescing */
+	if ((cvals->rx_coalesce_usecs == 0) ||
+	    (cvals->rx_max_coalesced_frames == 0)) {
+		for (i = 0; i < priv->num_rx_queues; i++)
+			priv->rx_queue[i]->rxcoalescing = 0;
+	} else {
+		for (i = 0; i < priv->num_rx_queues; i++)
+			priv->rx_queue[i]->rxcoalescing = 1;
+	}
+
 	for (i = 0; i < priv->num_rx_queues; i++) {
 		priv->rx_queue[i]->rxic = mk_ic_value(
 			cvals->rx_max_coalesced_frames,
@@ -415,28 +423,22 @@ static int gfar_scoalesce(struct net_device *dev,
 			priv->tx_queue[i]->txcoalescing = 1;
 	}
 
-	/* Check the bounds of the values */
-	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
-		netdev_info(dev, "Coalescing is limited to %d microseconds\n",
-			    GFAR_MAX_COAL_USECS);
-		return -EINVAL;
-	}
-
-	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
-		netdev_info(dev, "Coalescing is limited to %d frames\n",
-			    GFAR_MAX_COAL_FRAMES);
-		return -EINVAL;
-	}
-
 	for (i = 0; i < priv->num_tx_queues; i++) {
 		priv->tx_queue[i]->txic = mk_ic_value(
 			cvals->tx_max_coalesced_frames,
 			gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
 	}
 
-	gfar_configure_coalescing_all(priv);
+	if (dev->flags & IFF_UP) {
+		stop_gfar(dev);
+		err = startup_gfar(dev);
+	} else {
+		gfar_mac_reset(priv);
+	}
+
+	clear_bit_unlock(GFAR_RESETTING, &priv->state);
 
-	return 0;
+	return err;
 }
 
 /* Fills in rvals with the current ring parameters.  Currently,
@@ -467,15 +469,13 @@ static void gfar_gringparam(struct net_device *dev,
 }
 
 /* Change the current ring parameters, stopping the controller if
- * necessary so that we don't mess things up while we're in
- * motion.  We wait for the ring to be clean before reallocating
- * the rings.
+ * necessary so that we don't mess things up while we're in motion.
  */
 static int gfar_sringparam(struct net_device *dev,
 			   struct ethtool_ringparam *rvals)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	int err = 0, i = 0;
+	int err = 0, i;
 
 	if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
 		return -EINVAL;
@@ -493,44 +493,25 @@ static int gfar_sringparam(struct net_device *dev,
 		return -EINVAL;
 	}
 
+	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+		cpu_relax();
 
-	if (dev->flags & IFF_UP) {
-		unsigned long flags;
-
-		/* Halt TX and RX, and process the frames which
-		 * have already been received
-		 */
-		local_irq_save(flags);
-		lock_tx_qs(priv);
-		lock_rx_qs(priv);
-
-		gfar_halt(dev);
-
-		unlock_rx_qs(priv);
-		unlock_tx_qs(priv);
-		local_irq_restore(flags);
-
-		for (i = 0; i < priv->num_rx_queues; i++)
-			gfar_clean_rx_ring(priv->rx_queue[i],
-					   priv->rx_queue[i]->rx_ring_size);
-
-		/* Now we take down the rings to rebuild them */
+	if (dev->flags & IFF_UP)
 		stop_gfar(dev);
-	}
 
-	/* Change the size */
-	for (i = 0; i < priv->num_rx_queues; i++) {
+	/* Change the sizes */
+	for (i = 0; i < priv->num_rx_queues; i++)
 		priv->rx_queue[i]->rx_ring_size = rvals->rx_pending;
+
+	for (i = 0; i < priv->num_tx_queues; i++)
 		priv->tx_queue[i]->tx_ring_size = rvals->tx_pending;
-		priv->tx_queue[i]->num_txbdfree =
-			priv->tx_queue[i]->tx_ring_size;
-	}
 
 	/* Rebuild the rings with the new size */
-	if (dev->flags & IFF_UP) {
+	if (dev->flags & IFF_UP)
 		err = startup_gfar(dev);
-		netif_tx_wake_all_queues(dev);
-	}
+
+	clear_bit_unlock(GFAR_RESETTING, &priv->state);
+
 	return err;
 }
 
@@ -608,43 +589,29 @@ static int gfar_spauseparam(struct net_device *dev,
 
 int gfar_set_features(struct net_device *dev, netdev_features_t features)
 {
-	struct gfar_private *priv = netdev_priv(dev);
-	unsigned long flags;
-	int err = 0, i = 0;
 	netdev_features_t changed = dev->features ^ features;
+	struct gfar_private *priv = netdev_priv(dev);
+	int err = 0;
 
-	if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
-		gfar_vlan_mode(dev, features);
-
-	if (!(changed & NETIF_F_RXCSUM))
+	if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
+			 NETIF_F_RXCSUM)))
 		return 0;
 
-	if (dev->flags & IFF_UP) {
-		/* Halt TX and RX, and process the frames which
-		 * have already been received
-		 */
-		local_irq_save(flags);
-		lock_tx_qs(priv);
-		lock_rx_qs(priv);
-
-		gfar_halt(dev);
+	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+		cpu_relax();
 
-		unlock_tx_qs(priv);
-		unlock_rx_qs(priv);
-		local_irq_restore(flags);
-
-		for (i = 0; i < priv->num_rx_queues; i++)
-			gfar_clean_rx_ring(priv->rx_queue[i],
-					   priv->rx_queue[i]->rx_ring_size);
+	dev->features = features;
 
+	if (dev->flags & IFF_UP) {
 		/* Now we take down the rings to rebuild them */
 		stop_gfar(dev);
-
-		dev->features = features;
-
 		err = startup_gfar(dev);
-		netif_tx_wake_all_queues(dev);
+	} else {
+		gfar_mac_reset(priv);
 	}
+
+	clear_bit_unlock(GFAR_RESETTING, &priv->state);
+
 	return err;
 }
 
@@ -1610,9 +1577,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,
 	if (tab->index > MAX_FILER_IDX - 1)
 		return -EBUSY;
 
-	/* Avoid inconsistent filer table to be processed */
-	lock_rx_qs(priv);
-
 	/* Fill regular entries */
 	for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl);
 	     i++)
@@ -1625,8 +1589,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,
 	 */
 	gfar_write_filer(priv, i, 0x20, 0x0);
 
-	unlock_rx_qs(priv);
-
 	return 0;
 }
 
@@ -1831,6 +1793,9 @@ static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 	struct gfar_private *priv = netdev_priv(dev);
 	int ret = 0;
 
+	if (test_bit(GFAR_RESETTING, &priv->state))
+		return -EBUSY;
+
 	mutex_lock(&priv->rx_queue_access);
 
 	switch (cmd->cmd) {
diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c
deleted file mode 100644
index e02dd1378751..000000000000
--- a/drivers/net/ethernet/freescale/gianfar_sysfs.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * drivers/net/ethernet/freescale/gianfar_sysfs.c
- *
- * Gianfar Ethernet Driver
- * This driver is designed for the non-CPM ethernet controllers
- * on the 85xx and 83xx family of integrated processors
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (galak@kernel.crashing.org)
- * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
- *
- * Copyright 2002-2009 Freescale Semiconductor, 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.
- *
- * Sysfs file creation and management
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-
-#include <asm/uaccess.h>
-#include <linux/module.h>
-
-#include "gianfar.h"
-
-static ssize_t gfar_show_bd_stash(struct device *dev,
-				  struct device_attribute *attr, char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
-}
-
-static ssize_t gfar_set_bd_stash(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	int new_setting = 0;
-	u32 temp;
-	unsigned long flags;
-
-	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
-		return count;
-
-
-	/* Find out the new setting */
-	if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
-		new_setting = 1;
-	else if (!strncmp("off", buf, count - 1) ||
-		 !strncmp("0", buf, count - 1))
-		new_setting = 0;
-	else
-		return count;
-
-
-	local_irq_save(flags);
-	lock_rx_qs(priv);
-
-	/* Set the new stashing value */
-	priv->bd_stash_en = new_setting;
-
-	temp = gfar_read(&regs->attr);
-
-	if (new_setting)
-		temp |= ATTR_BDSTASH;
-	else
-		temp &= ~(ATTR_BDSTASH);
-
-	gfar_write(&regs->attr, temp);
-
-	unlock_rx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
-
-static ssize_t gfar_show_rx_stash_size(struct device *dev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%d\n", priv->rx_stash_size);
-}
-
-static ssize_t gfar_set_rx_stash_size(struct device *dev,
-				      struct device_attribute *attr,
-				      const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned int length = simple_strtoul(buf, NULL, 0);
-	u32 temp;
-	unsigned long flags;
-
-	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
-		return count;
-
-	local_irq_save(flags);
-	lock_rx_qs(priv);
-
-	if (length > priv->rx_buffer_size)
-		goto out;
-
-	if (length == priv->rx_stash_size)
-		goto out;
-
-	priv->rx_stash_size = length;
-
-	temp = gfar_read(&regs->attreli);
-	temp &= ~ATTRELI_EL_MASK;
-	temp |= ATTRELI_EL(length);
-	gfar_write(&regs->attreli, temp);
-
-	/* Turn stashing on/off as appropriate */
-	temp = gfar_read(&regs->attr);
-
-	if (length)
-		temp |= ATTR_BUFSTASH;
-	else
-		temp &= ~(ATTR_BUFSTASH);
-
-	gfar_write(&regs->attr, temp);
-
-out:
-	unlock_rx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
-		   gfar_set_rx_stash_size);
-
-/* Stashing will only be enabled when rx_stash_size != 0 */
-static ssize_t gfar_show_rx_stash_index(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%d\n", priv->rx_stash_index);
-}
-
-static ssize_t gfar_set_rx_stash_index(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned short index = simple_strtoul(buf, NULL, 0);
-	u32 temp;
-	unsigned long flags;
-
-	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
-		return count;
-
-	local_irq_save(flags);
-	lock_rx_qs(priv);
-
-	if (index > priv->rx_stash_size)
-		goto out;
-
-	if (index == priv->rx_stash_index)
-		goto out;
-
-	priv->rx_stash_index = index;
-
-	temp = gfar_read(&regs->attreli);
-	temp &= ~ATTRELI_EI_MASK;
-	temp |= ATTRELI_EI(index);
-	gfar_write(&regs->attreli, temp);
-
-out:
-	unlock_rx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
-		   gfar_set_rx_stash_index);
-
-static ssize_t gfar_show_fifo_threshold(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%d\n", priv->fifo_threshold);
-}
-
-static ssize_t gfar_set_fifo_threshold(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned int length = simple_strtoul(buf, NULL, 0);
-	u32 temp;
-	unsigned long flags;
-
-	if (length > GFAR_MAX_FIFO_THRESHOLD)
-		return count;
-
-	local_irq_save(flags);
-	lock_tx_qs(priv);
-
-	priv->fifo_threshold = length;
-
-	temp = gfar_read(&regs->fifo_tx_thr);
-	temp &= ~FIFO_TX_THR_MASK;
-	temp |= length;
-	gfar_write(&regs->fifo_tx_thr, temp);
-
-	unlock_tx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
-		   gfar_set_fifo_threshold);
-
-static ssize_t gfar_show_fifo_starve(struct device *dev,
-				     struct device_attribute *attr, char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%d\n", priv->fifo_starve);
-}
-
-static ssize_t gfar_set_fifo_starve(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned int num = simple_strtoul(buf, NULL, 0);
-	u32 temp;
-	unsigned long flags;
-
-	if (num > GFAR_MAX_FIFO_STARVE)
-		return count;
-
-	local_irq_save(flags);
-	lock_tx_qs(priv);
-
-	priv->fifo_starve = num;
-
-	temp = gfar_read(&regs->fifo_tx_starve);
-	temp &= ~FIFO_TX_STARVE_MASK;
-	temp |= num;
-	gfar_write(&regs->fifo_tx_starve, temp);
-
-	unlock_tx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve,
-		   gfar_set_fifo_starve);
-
-static ssize_t gfar_show_fifo_starve_off(struct device *dev,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
-	return sprintf(buf, "%d\n", priv->fifo_starve_off);
-}
-
-static ssize_t gfar_set_fifo_starve_off(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-	struct gfar __iomem *regs = priv->gfargrp[0].regs;
-	unsigned int num = simple_strtoul(buf, NULL, 0);
-	u32 temp;
-	unsigned long flags;
-
-	if (num > GFAR_MAX_FIFO_STARVE_OFF)
-		return count;
-
-	local_irq_save(flags);
-	lock_tx_qs(priv);
-
-	priv->fifo_starve_off = num;
-
-	temp = gfar_read(&regs->fifo_tx_starve_shutoff);
-	temp &= ~FIFO_TX_STARVE_OFF_MASK;
-	temp |= num;
-	gfar_write(&regs->fifo_tx_starve_shutoff, temp);
-
-	unlock_tx_qs(priv);
-	local_irq_restore(flags);
-
-	return count;
-}
-
-static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
-		   gfar_set_fifo_starve_off);
-
-void gfar_init_sysfs(struct net_device *dev)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	int rc;
-
-	/* Initialize the default values */
-	priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
-	priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
-	priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
-
-	/* Create our sysfs files */
-	rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
-	rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
-	rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
-	rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
-	rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
-	rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
-	if (rc)
-		dev_err(&dev->dev, "Error creating gianfar sysfs files\n");
-}
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 6d91933c4cdd..e6f8961d49eb 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2038,13 +2038,16 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
 							       msix_entry),
 							GFP_KERNEL);
 			if (adapter->msix_entries) {
+				struct e1000_adapter *a = adapter;
+
 				for (i = 0; i < adapter->num_vectors; i++)
 					adapter->msix_entries[i].entry = i;
 
-				err = pci_enable_msix(adapter->pdev,
-						      adapter->msix_entries,
-						      adapter->num_vectors);
-				if (err == 0)
+				err = pci_enable_msix_range(a->pdev,
+							    a->msix_entries,
+							    a->num_vectors,
+							    a->num_vectors);
+				if (err > 0)
 					return;
 			}
 			/* MSI-X failed, so fall through and try MSI */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index a50e6b3479ae..ed3902bf249b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -647,9 +647,8 @@ static u16 i40e_clean_asq(struct i40e_hw *hw)
 			desc_cb = *desc;
 			cb_func(hw, &desc_cb);
 		}
-		memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
-		memset((void *)details, 0,
-		       sizeof(struct i40e_asq_cmd_details));
+		memset(desc, 0, sizeof(*desc));
+		memset(details, 0, sizeof(*details));
 		ntc++;
 		if (ntc == asq->count)
 			ntc = 0;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b901371ca361..53f3ed2df796 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -38,7 +38,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 0
 #define DRV_VERSION_MINOR 3
-#define DRV_VERSION_BUILD 30
+#define DRV_VERSION_BUILD 32
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
 	     __stringify(DRV_VERSION_MINOR) "." \
 	     __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -305,6 +305,7 @@ static void i40e_tx_timeout(struct net_device *netdev)
 		break;
 	default:
 		netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
+		set_bit(__I40E_DOWN, &vsi->state);
 		i40e_down(vsi);
 		break;
 	}
@@ -3107,13 +3108,13 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
 
 	pf_q = vsi->base_queue;
 	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-		j = 1000;
-		do {
-			usleep_range(1000, 2000);
+		for (j = 0; j < 50; j++) {
 			tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
-		} while (j-- && ((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT)
-			       ^ (tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT)) & 1);
-
+			if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) ==
+			    ((tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 1))
+				break;
+			usleep_range(1000, 2000);
+		}
 		/* Skip if the queue is already in the requested state */
 		if (enable && (tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
 			continue;
@@ -3123,8 +3124,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
 		/* turn on/off the queue */
 		if (enable) {
 			wr32(hw, I40E_QTX_HEAD(pf_q), 0);
-			tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK |
-				  I40E_QTX_ENA_QENA_STAT_MASK;
+			tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK;
 		} else {
 			tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
 		}
@@ -3171,12 +3171,13 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
 
 	pf_q = vsi->base_queue;
 	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-		j = 1000;
-		do {
-			usleep_range(1000, 2000);
+		for (j = 0; j < 50; j++) {
 			rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
-		} while (j-- && ((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT)
-			       ^ (rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT)) & 1);
+			if (((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 1) ==
+			    ((rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 1))
+				break;
+			usleep_range(1000, 2000);
+		}
 
 		if (enable) {
 			/* is STAT set ? */
@@ -3190,11 +3191,9 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
 
 		/* turn on/off the queue */
 		if (enable)
-			rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK |
-				  I40E_QRX_ENA_QENA_STAT_MASK;
+			rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK;
 		else
-			rx_reg &= ~(I40E_QRX_ENA_QENA_REQ_MASK |
-				  I40E_QRX_ENA_QENA_STAT_MASK);
+			rx_reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
 		wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
 
 		/* wait for the change to finish */
@@ -5331,6 +5330,11 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
 	/* restart the VSIs that were rebuilt and running before the reset */
 	i40e_pf_unquiesce_all_vsi(pf);
 
+	if (pf->num_alloc_vfs) {
+		for (v = 0; v < pf->num_alloc_vfs; v++)
+			i40e_reset_vf(&pf->vf[v], true);
+	}
+
 	/* tell the firmware that we're starting */
 	dv.major_version = DRV_VERSION_MAJOR;
 	dv.minor_version = DRV_VERSION_MINOR;
@@ -5850,37 +5854,16 @@ err_out:
  **/
 static int i40e_reserve_msix_vectors(struct i40e_pf *pf, int vectors)
 {
-	int err = 0;
-
-	pf->num_msix_entries = 0;
-	while (vectors >= I40E_MIN_MSIX) {
-		err = pci_enable_msix(pf->pdev, pf->msix_entries, vectors);
-		if (err == 0) {
-			/* good to go */
-			pf->num_msix_entries = vectors;
-			break;
-		} else if (err < 0) {
-			/* total failure */
-			dev_info(&pf->pdev->dev,
-				 "MSI-X vector reservation failed: %d\n", err);
-			vectors = 0;
-			break;
-		} else {
-			/* err > 0 is the hint for retry */
-			dev_info(&pf->pdev->dev,
-				 "MSI-X vectors wanted %d, retrying with %d\n",
-				 vectors, err);
-			vectors = err;
-		}
-	}
-
-	if (vectors > 0 && vectors < I40E_MIN_MSIX) {
+	vectors = pci_enable_msix_range(pf->pdev, pf->msix_entries,
+					I40E_MIN_MSIX, vectors);
+	if (vectors < 0) {
 		dev_info(&pf->pdev->dev,
-			 "Couldn't get enough vectors, only %d available\n",
-			 vectors);
+			 "MSI-X vector reservation failed: %d\n", vectors);
 		vectors = 0;
 	}
 
+	pf->num_msix_entries = vectors;
+
 	return vectors;
 }
 
@@ -5942,7 +5925,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
 
 	} else if (vec == I40E_MIN_MSIX) {
 		/* Adjust for minimal MSIX use */
-		dev_info(&pf->pdev->dev, "Features disabled, not enough MSIX vectors\n");
+		dev_info(&pf->pdev->dev, "Features disabled, not enough MSI-X vectors\n");
 		pf->flags &= ~I40E_FLAG_VMDQ_ENABLED;
 		pf->num_vmdq_vsis = 0;
 		pf->num_vmdq_qps = 0;
@@ -6071,7 +6054,7 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf)
 
 	if (!(pf->flags & I40E_FLAG_MSIX_ENABLED) &&
 	    (pf->flags & I40E_FLAG_MSI_ENABLED)) {
-		dev_info(&pf->pdev->dev, "MSIX not available, trying MSI\n");
+		dev_info(&pf->pdev->dev, "MSI-X not available, trying MSI\n");
 		err = pci_enable_msi(pf->pdev);
 		if (err) {
 			dev_info(&pf->pdev->dev, "MSI init failed - %d\n", err);
@@ -6080,7 +6063,7 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf)
 	}
 
 	if (!(pf->flags & (I40E_FLAG_MSIX_ENABLED | I40E_FLAG_MSI_ENABLED)))
-		dev_info(&pf->pdev->dev, "MSIX and MSI not available, falling back to Legacy IRQ\n");
+		dev_info(&pf->pdev->dev, "MSI-X and MSI not available, falling back to Legacy IRQ\n");
 
 	/* track first vector for misc interrupts */
 	err = i40e_get_lump(pf, pf->irq_pile, 1, I40E_PILE_VALID_BIT-1);
@@ -6107,7 +6090,8 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
 				  i40e_intr, 0, pf->misc_int_name, pf);
 		if (err) {
 			dev_info(&pf->pdev->dev,
-				 "request_irq for msix_misc failed: %d\n", err);
+				 "request_irq for %s failed: %d\n",
+				 pf->misc_int_name, err);
 			return -EFAULT;
 		}
 	}
@@ -8070,6 +8054,16 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
 		wr32(hw, I40E_PFGEN_PORTMDIO_NUM, val);
 		i40e_flush(hw);
+
+		if (pci_num_vf(pdev)) {
+			dev_info(&pdev->dev,
+				 "Active VFs found, allocating resources.\n");
+			err = i40e_alloc_vfs(pf, pci_num_vf(pdev));
+			if (err)
+				dev_info(&pdev->dev,
+					 "Error %d allocating resources for existing VFs\n",
+					 err);
+		}
 	}
 
 	pfs_found++;
@@ -8165,16 +8159,16 @@ static void i40e_remove(struct pci_dev *pdev)
 
 	i40e_ptp_stop(pf);
 
-	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
-		i40e_free_vfs(pf);
-		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
-	}
-
 	/* no more scheduling of any task */
 	set_bit(__I40E_DOWN, &pf->state);
 	del_timer_sync(&pf->service_timer);
 	cancel_work_sync(&pf->service_task);
 
+	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
+		i40e_free_vfs(pf);
+		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
+	}
+
 	i40e_fdir_teardown(pf);
 
 	/* If there is a switch structure or any orphans, remove them.
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index d4bb482b1a7f..19af4ce0a4fe 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -892,7 +892,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
 	      rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
 		return;
 
-	/* likely incorrect csum if alternate IP extention headers found */
+	/* likely incorrect csum if alternate IP extension headers found */
 	if (rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
 		return;
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index b9d1c1c8ca5a..189e250198dd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -408,18 +408,10 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
 				 "Could not allocate VF broadcast filter\n");
 	}
 
-	if (!f) {
-		dev_err(&pf->pdev->dev, "Unable to add ucast filter\n");
-		ret = -ENOMEM;
-		goto error_alloc_vsi_res;
-	}
-
 	/* program mac filter */
 	ret = i40e_sync_vsi_filters(vsi);
-	if (ret) {
+	if (ret)
 		dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
-		goto error_alloc_vsi_res;
-	}
 
 error_alloc_vsi_res:
 	return ret;
@@ -679,9 +671,9 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
 complete_reset:
 	/* reallocate vf resources to reset the VSI state */
 	i40e_free_vf_res(vf);
-	mdelay(10);
 	i40e_alloc_vf_res(vf);
 	i40e_enable_vf_mappings(vf);
+	set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
 
 	/* tell the VF the reset is done */
 	wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
@@ -847,7 +839,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
  *
  * allocate vf resources
  **/
-static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
+int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
 {
 	struct i40e_vf *vfs;
 	int i, ret = 0;
@@ -855,14 +847,16 @@ static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
 	/* Disable interrupt 0 so we don't try to handle the VFLR. */
 	i40e_irq_dynamic_disable_icr0(pf);
 
-	ret = pci_enable_sriov(pf->pdev, num_alloc_vfs);
-	if (ret) {
-		dev_err(&pf->pdev->dev,
-			"pci_enable_sriov failed with error %d!\n", ret);
-		pf->num_alloc_vfs = 0;
-		goto err_iov;
+	/* Check to see if we're just allocating resources for extant VFs */
+	if (pci_num_vf(pf->pdev) != num_alloc_vfs) {
+		ret = pci_enable_sriov(pf->pdev, num_alloc_vfs);
+		if (ret) {
+			dev_err(&pf->pdev->dev,
+				"Failed to enable SR-IOV, error %d.\n", ret);
+			pf->num_alloc_vfs = 0;
+			goto err_iov;
+		}
 	}
-
 	/* allocate memory */
 	vfs = kzalloc(num_alloc_vfs * sizeof(struct i40e_vf), GFP_KERNEL);
 	if (!vfs) {
@@ -1873,7 +1867,8 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
 			/* clear the bit in GLGEN_VFLRSTAT */
 			wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), (1 << bit_idx));
 
-			i40e_reset_vf(vf, true);
+			if (!test_bit(__I40E_DOWN, &pf->state))
+				i40e_reset_vf(vf, true);
 		}
 	}
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index cc1feee36e12..bedf0ba21d74 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -102,6 +102,7 @@ struct i40e_vf {
 
 void i40e_free_vfs(struct i40e_pf *pf);
 int i40e_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
+int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
 int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
 			   u32 v_retval, u8 *msg, u16 msglen);
 int i40e_vc_process_vflr_event(struct i40e_pf *pf);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index f7cea1bca38d..97662b6bd98a 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1229,7 +1229,7 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE                 2
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP                  3
 
-	__le32 tenant_id ;
+	__le32 tenant_id;
 	u8     reserved[4];
 	__le16 queue_number;
 #define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT                  0
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index ffdb01d853db..827bb5fa4af9 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -722,7 +722,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
 	      rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
 		return;
 
-	/* likely incorrect csum if alternate IP extention headers found */
+	/* likely incorrect csum if alternate IP extension headers found */
 	if (rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
 		return;
 
@@ -807,8 +807,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 
 	rx_desc = I40E_RX_DESC(rx_ring, i);
 	qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-	rx_status = (qword & I40E_RXD_QW1_STATUS_MASK)
-				>> I40E_RXD_QW1_STATUS_SHIFT;
+	rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
+		    I40E_RXD_QW1_STATUS_SHIFT;
 
 	while (rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) {
 		union i40e_rx_desc *next_rxd;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 3bffac06592f..092aace2a76c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -64,8 +64,6 @@
 struct i40e_hw;
 typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
 
-#define ETH_ALEN	6
-
 /* Data type manipulation macros. */
 
 #define I40E_DESC_UNUSED(R)	\
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index ff6529b288a1..ccb43d343543 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -38,8 +38,6 @@
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
 #include <net/udp.h>
-#include <linux/sctp.h>
-
 
 #include "i40e_type.h"
 #include "i40e_virtchnl.h"
@@ -164,15 +162,14 @@ struct i40evf_vlan_filter {
 /* Driver state. The order of these is important! */
 enum i40evf_state_t {
 	__I40EVF_STARTUP,		/* driver loaded, probe complete */
-	__I40EVF_FAILED,		/* PF communication failed. Fatal. */
 	__I40EVF_REMOVE,		/* driver is being unloaded */
 	__I40EVF_INIT_VERSION_CHECK,	/* aq msg sent, awaiting reply */
 	__I40EVF_INIT_GET_RESOURCES,	/* aq msg sent, awaiting reply */
 	__I40EVF_INIT_SW,		/* got resources, setting up structs */
+	__I40EVF_RESETTING,		/* in reset */
 	/* Below here, watchdog is running */
 	__I40EVF_DOWN,			/* ready, can be opened */
 	__I40EVF_TESTING,		/* in ethtool self-test */
-	__I40EVF_RESETTING,		/* in reset */
 	__I40EVF_RUNNING,		/* opened, working */
 };
 
@@ -185,47 +182,25 @@ enum i40evf_critical_section_t {
 /* board specific private data structure */
 struct i40evf_adapter {
 	struct timer_list watchdog_timer;
-	struct vlan_group *vlgrp;
 	struct work_struct reset_task;
 	struct work_struct adminq_task;
 	struct delayed_work init_task;
 	struct i40e_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
 	struct list_head vlan_filter_list;
-	char name[MAX_MSIX_COUNT][IFNAMSIZ + 9];
-
-	/* Interrupt Throttle Rate */
-	u32 itr_setting;
-	u16 eitr_low;
-	u16 eitr_high;
+	char misc_vector_name[IFNAMSIZ + 9];
 
 	/* TX */
 	struct i40e_ring *tx_rings[I40E_MAX_VSI_QP];
-	u64 restart_queue;
-	u64 hw_csum_tx_good;
-	u64 lsc_int;
-	u64 hw_tso_ctxt;
-	u64 hw_tso6_ctxt;
 	u32 tx_timeout_count;
 	struct list_head mac_filter_list;
-#ifdef DEBUG
-	bool detect_tx_hung;
-#endif /* DEBUG */
 
 	/* RX */
 	struct i40e_ring *rx_rings[I40E_MAX_VSI_QP];
-	int txd_count;
-	int rxd_count;
 	u64 hw_csum_rx_error;
-	u64 hw_rx_no_dma_resources;
-	u64 hw_csum_rx_good;
-	u64 non_eop_descs;
 	int num_msix_vectors;
 	struct msix_entry *msix_entries;
 
-	u64 rx_hdr_split;
-
-	u32 init_state;
-	volatile unsigned long flags;
+	u32 flags;
 #define I40EVF_FLAG_RX_CSUM_ENABLED              (u32)(1)
 #define I40EVF_FLAG_RX_1BUF_CAPABLE              (u32)(1 << 1)
 #define I40EVF_FLAG_RX_PS_CAPABLE                (u32)(1 << 2)
@@ -234,6 +209,8 @@ struct i40evf_adapter {
 #define I40EVF_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
 #define I40EVF_FLAG_MQ_CAPABLE                   (u32)(1 << 6)
 #define I40EVF_FLAG_NEED_LINK_UPDATE             (u32)(1 << 7)
+#define I40EVF_FLAG_PF_COMMS_FAILED              (u32)(1 << 8)
+#define I40EVF_FLAG_RESET_PENDING                (u32)(1 << 9)
 /* duplcates for common code */
 #define I40E_FLAG_FDIR_ATR_ENABLED		 0
 #define I40E_FLAG_DCB_ENABLED			 0
@@ -251,21 +228,19 @@ struct i40evf_adapter {
 #define I40EVF_FLAG_AQ_CONFIGURE_QUEUES		(u32)(1 << 6)
 #define I40EVF_FLAG_AQ_MAP_VECTORS		(u32)(1 << 7)
 #define I40EVF_FLAG_AQ_HANDLE_RESET		(u32)(1 << 8)
+
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 
-	/* structs defined in i40e_vf.h */
-	struct i40e_hw hw;
+	struct i40e_hw hw; /* defined in i40e_type.h */
 
 	enum i40evf_state_t state;
 	volatile unsigned long crit_section;
-	u64 tx_busy;
 
 	struct work_struct watchdog_task;
 	bool netdev_registered;
-	bool dev_closed;
 	bool link_up;
 	enum i40e_virtchnl_ops current_op;
 	struct i40e_virtchnl_vf_resource *vf_res; /* incl. all VSIs */
@@ -276,11 +251,6 @@ struct i40evf_adapter {
 	u32 aq_wait_count;
 };
 
-struct i40evf_info {
-	enum i40e_mac_type	mac;
-	unsigned int		flags;
-};
-
 
 /* needed by i40evf_ethtool.c */
 extern char i40evf_driver_name[];
@@ -315,6 +285,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter);
 void i40evf_del_vlans(struct i40evf_adapter *adapter);
 void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
 void i40evf_request_stats(struct i40evf_adapter *adapter);
+void i40evf_request_reset(struct i40evf_adapter *adapter);
 void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
 				enum i40e_virtchnl_ops v_opcode,
 				i40e_status v_retval, u8 *msg, u16 msglen);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index b0b1f4bf5ac0..8b0db1ce179c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -241,6 +241,7 @@ static int i40evf_set_ringparam(struct net_device *netdev,
 {
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
 	u32 new_rx_count, new_tx_count;
+	int i;
 
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
@@ -256,12 +257,14 @@ static int i40evf_set_ringparam(struct net_device *netdev,
 	new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
 
 	/* if nothing to do return success */
-	if ((new_tx_count == adapter->txd_count) &&
-	    (new_rx_count == adapter->rxd_count))
+	if ((new_tx_count == adapter->tx_rings[0]->count) &&
+	    (new_rx_count == adapter->rx_rings[0]->count))
 		return 0;
 
-	adapter->txd_count = new_tx_count;
-	adapter->rxd_count = new_rx_count;
+	for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+		adapter->tx_rings[0]->count = new_tx_count;
+		adapter->rx_rings[0]->count = new_rx_count;
+	}
 
 	if (netif_running(netdev))
 		i40evf_reinit_locked(adapter);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index f5caf4419243..b2c03bca7929 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -31,10 +31,10 @@ char i40evf_driver_name[] = "i40evf";
 static const char i40evf_driver_string[] =
 	"Intel(R) XL710 X710 Virtual Function Network Driver";
 
-#define DRV_VERSION "0.9.11"
+#define DRV_VERSION "0.9.13"
 const char i40evf_driver_version[] = DRV_VERSION;
 static const char i40evf_copyright[] =
-	"Copyright (c) 2013 Intel Corporation.";
+	"Copyright (c) 2013 - 2014 Intel Corporation.";
 
 /* i40evf_pci_tbl - PCI Device ID Table
  *
@@ -167,9 +167,13 @@ static void i40evf_tx_timeout(struct net_device *netdev)
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
 
 	adapter->tx_timeout_count++;
-
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->reset_task);
+	dev_info(&adapter->pdev->dev, "TX timeout detected.\n");
+	if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
+		dev_info(&adapter->pdev->dev, "Requesting reset from PF\n");
+		i40evf_request_reset(adapter);
+		adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+		schedule_work(&adapter->reset_task);
+	}
 }
 
 /**
@@ -211,6 +215,9 @@ static void i40evf_irq_disable(struct i40evf_adapter *adapter)
 	int i;
 	struct i40e_hw *hw = &adapter->hw;
 
+	if (!adapter->msix_entries)
+		return;
+
 	for (i = 1; i < adapter->num_msix_vectors; i++) {
 		wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), 0);
 		synchronize_irq(adapter->msix_entries[i].vector);
@@ -511,12 +518,14 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	int err;
 
-	sprintf(adapter->name[0], "i40evf:mbx");
+	sprintf(adapter->misc_vector_name, "i40evf:mbx");
 	err = request_irq(adapter->msix_entries[0].vector,
-			  &i40evf_msix_aq, 0, adapter->name[0], netdev);
+			  &i40evf_msix_aq, 0,
+			  adapter->misc_vector_name, netdev);
 	if (err) {
 		dev_err(&adapter->pdev->dev,
-			"request_irq for msix_aq failed: %d\n", err);
+			"request_irq for %s failed: %d\n",
+			adapter->misc_vector_name, err);
 		free_irq(adapter->msix_entries[0].vector, netdev);
 	}
 	return err;
@@ -963,16 +972,23 @@ void i40evf_down(struct i40evf_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	struct i40evf_mac_filter *f;
 
-	/* remove all MAC filters from the VSI */
+	/* remove all MAC filters */
 	list_for_each_entry(f, &adapter->mac_filter_list, list) {
 		f->remove = true;
 	}
-	adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
-	/* disable receives */
-	adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
-	mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
-	msleep(20);
-
+	/* remove all VLAN filters */
+	list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+		f->remove = true;
+	}
+	if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&
+	    adapter->state != __I40EVF_RESETTING) {
+		adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+		adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+		/* disable receives */
+		adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
+		mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+		msleep(20);
+	}
 	netif_tx_disable(netdev);
 
 	netif_tx_stop_all_queues(netdev);
@@ -1291,19 +1307,47 @@ static void i40evf_watchdog_task(struct work_struct *work)
 					  watchdog_task);
 	struct i40e_hw *hw = &adapter->hw;
 
-	if (adapter->state < __I40EVF_DOWN)
+	if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+		goto restart_watchdog;
+
+	if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+		dev_info(&adapter->pdev->dev, "Checking for redemption\n");
+		if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) {
+			/* A chance for redemption! */
+			dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
+			adapter->state = __I40EVF_STARTUP;
+			adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+			schedule_delayed_work(&adapter->init_task, 10);
+			clear_bit(__I40EVF_IN_CRITICAL_TASK,
+				  &adapter->crit_section);
+			/* Don't reschedule the watchdog, since we've restarted
+			 * the init task. When init_task contacts the PF and
+			 * gets everything set up again, it'll restart the
+			 * watchdog for us. Down, boy. Sit. Stay. Woof.
+			 */
+			return;
+		}
+		adapter->aq_pending = 0;
+		adapter->aq_required = 0;
+		adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
 		goto watchdog_done;
+	}
 
-	if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+	if ((adapter->state < __I40EVF_DOWN) ||
+	    (adapter->flags & I40EVF_FLAG_RESET_PENDING))
 		goto watchdog_done;
 
-	/* check for unannounced reset */
-	if ((adapter->state != __I40EVF_RESETTING) &&
+	/* check for reset */
+	if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) &&
 	    (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) {
 		adapter->state = __I40EVF_RESETTING;
+		adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+		dev_err(&adapter->pdev->dev, "Hardware reset detected.\n");
+		dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
 		schedule_work(&adapter->reset_task);
-		dev_info(&adapter->pdev->dev, "%s: hardware reset detected\n",
-			 __func__);
+		adapter->aq_pending = 0;
+		adapter->aq_required = 0;
+		adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
 		goto watchdog_done;
 	}
 
@@ -1358,13 +1402,15 @@ static void i40evf_watchdog_task(struct work_struct *work)
 
 	i40evf_irq_enable(adapter, true);
 	i40evf_fire_sw_int(adapter, 0xFF);
+
 watchdog_done:
+	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+restart_watchdog:
 	if (adapter->aq_required)
 		mod_timer(&adapter->watchdog_timer,
 			  jiffies + msecs_to_jiffies(20));
 	else
 		mod_timer(&adapter->watchdog_timer, jiffies + (HZ * 2));
-	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
 	schedule_work(&adapter->adminq_task);
 }
 
@@ -1411,6 +1457,8 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter)
 	i40e_flush(hw);
 }
 
+#define I40EVF_RESET_WAIT_MS 100
+#define I40EVF_RESET_WAIT_COUNT 200
 /**
  * i40evf_reset_task - Call-back task to handle hardware reset
  * @work: pointer to work_struct
@@ -1421,8 +1469,9 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter)
  **/
 static void i40evf_reset_task(struct work_struct *work)
 {
-	struct i40evf_adapter *adapter =
-			container_of(work, struct i40evf_adapter, reset_task);
+	struct i40evf_adapter *adapter = container_of(work,
+						      struct i40evf_adapter,
+						      reset_task);
 	struct i40e_hw *hw = &adapter->hw;
 	int i = 0, err;
 	uint32_t rstat_val;
@@ -1430,22 +1479,56 @@ static void i40evf_reset_task(struct work_struct *work)
 	while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
 				&adapter->crit_section))
 		udelay(500);
+	/* poll until we see the reset actually happen */
+	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+		rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+		if (rstat_val != I40E_VFR_VFACTIVE) {
+			dev_info(&adapter->pdev->dev, "Reset now occurring\n");
+			break;
+		} else {
+			msleep(I40EVF_RESET_WAIT_MS);
+		}
+	}
+	if (i == I40EVF_RESET_WAIT_COUNT) {
+		dev_err(&adapter->pdev->dev, "Reset was not detected\n");
+		adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+		goto continue_reset; /* act like the reset happened */
+	}
 
-	/* wait until the reset is complete */
-	for (i = 0; i < 20; i++) {
+	/* wait until the reset is complete and the PF is responding to us */
+	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
 		rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
 			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
-		if (rstat_val == I40E_VFR_COMPLETED)
+		if (rstat_val == I40E_VFR_VFACTIVE) {
+			dev_info(&adapter->pdev->dev, "Reset is complete. Reinitializing.\n");
 			break;
-		else
-			mdelay(100);
+		} else {
+			msleep(I40EVF_RESET_WAIT_MS);
+		}
 	}
-	if (i == 20) {
+	if (i == I40EVF_RESET_WAIT_COUNT) {
 		/* reset never finished */
-		dev_info(&adapter->pdev->dev, "%s: reset never finished: %x\n",
-			__func__, rstat_val);
-		/* carry on anyway */
+		dev_err(&adapter->pdev->dev, "Reset never finished (%x). PF driver is dead, and so am I.\n",
+			rstat_val);
+		adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+
+		if (netif_running(adapter->netdev))
+			i40evf_close(adapter->netdev);
+
+		i40evf_free_misc_irq(adapter);
+		i40evf_reset_interrupt_capability(adapter);
+		i40evf_free_queues(adapter);
+		kfree(adapter->vf_res);
+		i40evf_shutdown_adminq(hw);
+		adapter->netdev->flags &= ~IFF_UP;
+		clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+		return; /* Do not attempt to reinit. It's dead, Jim. */
 	}
+
+continue_reset:
+	adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+
 	i40evf_down(adapter);
 	adapter->state = __I40EVF_RESETTING;
 
@@ -1505,6 +1588,9 @@ static void i40evf_adminq_task(struct work_struct *work)
 	i40e_status ret;
 	u16 pending;
 
+	if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
+		return;
+
 	event.msg_size = I40EVF_MAX_AQ_BUF_SIZE;
 	event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL);
 	if (!event.msg_buf) {
@@ -1636,6 +1722,10 @@ static int i40evf_open(struct net_device *netdev)
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
 	int err;
 
+	if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+		dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n");
+		return -EIO;
+	}
 	if (adapter->state != __I40EVF_DOWN)
 		return -EBUSY;
 
@@ -1690,8 +1780,12 @@ static int i40evf_close(struct net_device *netdev)
 {
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
 
+	if (adapter->state <= __I40EVF_DOWN)
+		return 0;
+
 	/* signal that we are down to the interrupt handler */
 	adapter->state = __I40EVF_DOWN;
+
 	set_bit(__I40E_DOWN, &adapter->vsi.state);
 
 	i40evf_down(adapter);
@@ -1842,16 +1936,18 @@ static void i40evf_init_task(struct work_struct *work)
 	switch (adapter->state) {
 	case __I40EVF_STARTUP:
 		/* driver loaded, probe complete */
+		adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+		adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
 		err = i40e_set_mac_type(hw);
 		if (err) {
-			dev_info(&pdev->dev, "%s: set_mac_type failed: %d\n",
-				__func__, err);
+			dev_err(&pdev->dev, "Failed to set MAC type (%d)\n",
+				err);
 		goto err;
 		}
 		err = i40evf_check_reset_complete(hw);
 		if (err) {
-			dev_info(&pdev->dev, "%s: device is still in reset (%d).\n",
-				__func__, err);
+			dev_err(&pdev->dev, "Device is still in reset (%d)\n",
+				err);
 			goto err;
 		}
 		hw->aq.num_arq_entries = I40EVF_AQ_LEN;
@@ -1861,14 +1957,14 @@ static void i40evf_init_task(struct work_struct *work)
 
 		err = i40evf_init_adminq(hw);
 		if (err) {
-			dev_info(&pdev->dev, "%s: init_adminq failed: %d\n",
-				__func__, err);
+			dev_err(&pdev->dev, "Failed to init Admin Queue (%d)\n",
+				err);
 			goto err;
 		}
 		err = i40evf_send_api_ver(adapter);
 		if (err) {
-			dev_info(&pdev->dev, "%s: unable to send to PF (%d)\n",
-				__func__, err);
+			dev_err(&pdev->dev, "Unable to send to PF (%d)\n",
+				err);
 			i40evf_shutdown_adminq(hw);
 			goto err;
 		}
@@ -1882,13 +1978,13 @@ static void i40evf_init_task(struct work_struct *work)
 		/* aq msg sent, awaiting reply */
 		err = i40evf_verify_api_ver(adapter);
 		if (err) {
-			dev_err(&pdev->dev, "Unable to verify API version, error %d\n",
+			dev_err(&pdev->dev, "Unable to verify API version (%d)\n",
 				err);
 			goto err;
 		}
 		err = i40evf_send_vf_config_msg(adapter);
 		if (err) {
-			dev_err(&pdev->dev, "Unable send config request, error %d\n",
+			dev_err(&pdev->dev, "Unable send config request (%d)\n",
 				err);
 			goto err;
 		}
@@ -1902,18 +1998,15 @@ static void i40evf_init_task(struct work_struct *work)
 				(I40E_MAX_VF_VSI *
 				 sizeof(struct i40e_virtchnl_vsi_resource));
 			adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
-			if (!adapter->vf_res) {
-				dev_err(&pdev->dev, "%s: unable to allocate memory\n",
-					__func__);
+			if (!adapter->vf_res)
 				goto err;
-			}
 		}
 		err = i40evf_get_vf_config(adapter);
 		if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
 			goto restart;
 		if (err) {
-			dev_info(&pdev->dev, "%s: unable to get VF config (%d)\n",
-				__func__, err);
+			dev_err(&pdev->dev, "Unable to get VF config (%d)\n",
+				err);
 			goto err_alloc;
 		}
 		adapter->state = __I40EVF_INIT_SW;
@@ -1927,20 +2020,17 @@ static void i40evf_init_task(struct work_struct *work)
 			adapter->vsi_res = &adapter->vf_res->vsi_res[i];
 	}
 	if (!adapter->vsi_res) {
-		dev_info(&pdev->dev, "%s: no LAN VSI found\n", __func__);
+		dev_err(&pdev->dev, "No LAN VSI found\n");
 		goto err_alloc;
 	}
 
 	adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
 
-	adapter->txd_count = I40EVF_DEFAULT_TXD;
-	adapter->rxd_count = I40EVF_DEFAULT_RXD;
-
 	netdev->netdev_ops = &i40evf_netdev_ops;
 	i40evf_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
-
-	netdev->features |= NETIF_F_SG |
+	netdev->features |= NETIF_F_HIGHDMA |
+			    NETIF_F_SG |
 			    NETIF_F_IP_CSUM |
 			    NETIF_F_SCTP_CSUM |
 			    NETIF_F_IPV6_CSUM |
@@ -1956,11 +2046,9 @@ static void i40evf_init_task(struct work_struct *work)
 				    NETIF_F_HW_VLAN_CTAG_FILTER;
 	}
 
-	/* The HW MAC address was set and/or determined in sw_init */
 	if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
-		dev_info(&pdev->dev,
-			"Invalid MAC address %pMAC, using random\n",
-			adapter->hw.mac.addr);
+		dev_info(&pdev->dev, "Invalid MAC address %pMAC, using random\n",
+			 adapter->hw.mac.addr);
 		random_ether_addr(adapter->hw.mac.addr);
 	}
 	memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
@@ -1994,8 +2082,6 @@ static void i40evf_init_task(struct work_struct *work)
 
 	netif_carrier_off(netdev);
 
-	strcpy(netdev->name, "eth%d");
-
 	adapter->vsi.id = adapter->vsi_res->vsi_id;
 	adapter->vsi.seid = adapter->vsi_res->vsi_id; /* dummy */
 	adapter->vsi.back = adapter;
@@ -2005,9 +2091,11 @@ static void i40evf_init_task(struct work_struct *work)
 	adapter->vsi.tx_itr_setting = I40E_ITR_DYNAMIC;
 	adapter->vsi.netdev = adapter->netdev;
 
-	err = register_netdev(netdev);
-	if (err)
-		goto err_register;
+	if (!adapter->netdev_registered) {
+		err = register_netdev(netdev);
+		if (err)
+			goto err_register;
+	}
 
 	adapter->netdev_registered = true;
 
@@ -2031,17 +2119,16 @@ err_register:
 	i40evf_free_misc_irq(adapter);
 err_sw_init:
 	i40evf_reset_interrupt_capability(adapter);
-	adapter->state = __I40EVF_FAILED;
 err_alloc:
 	kfree(adapter->vf_res);
 	adapter->vf_res = NULL;
 err:
+	if (hw->aq.asq.count)
+		i40evf_shutdown_adminq(hw); /* ignore error */
 	/* Things went into the weeds, so try again later */
 	if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
 		dev_err(&pdev->dev, "Failed to communicate with PF; giving up.\n");
-		if (hw->aq.asq.count)
-			i40evf_shutdown_adminq(hw); /* ignore error */
-		adapter->state = __I40EVF_FAILED;
+		adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
 		return; /* do not reschedule */
 	}
 	schedule_delayed_work(&adapter->init_task, HZ * 3);
@@ -2084,20 +2171,18 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct net_device *netdev;
 	struct i40evf_adapter *adapter = NULL;
 	struct i40e_hw *hw = NULL;
-	int err, pci_using_dac;
+	int err;
 
 	err = pci_enable_device(pdev);
 	if (err)
 		return err;
 
 	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-		pci_using_dac = true;
 		/* coherent mask for the same size will always succeed if
 		 * dma_set_mask does
 		 */
 		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
 	} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
-		pci_using_dac = false;
 		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	} else {
 		dev_err(&pdev->dev, "%s: DMA configuration failed: %d\n",
@@ -2128,8 +2213,6 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_drvdata(pdev, netdev);
 	adapter = netdev_priv(netdev);
-	if (pci_using_dac)
-		netdev->features |= NETIF_F_HIGHDMA;
 
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
@@ -2271,6 +2354,7 @@ static void i40evf_remove(struct pci_dev *pdev)
 	struct i40e_hw *hw = &adapter->hw;
 
 	cancel_delayed_work_sync(&adapter->init_task);
+	cancel_work_sync(&adapter->reset_task);
 
 	if (adapter->netdev_registered) {
 		unregister_netdev(netdev);
@@ -2278,17 +2362,15 @@ static void i40evf_remove(struct pci_dev *pdev)
 	}
 	adapter->state = __I40EVF_REMOVE;
 
-	if (adapter->num_msix_vectors) {
+	if (adapter->msix_entries) {
 		i40evf_misc_irq_disable(adapter);
-		del_timer_sync(&adapter->watchdog_timer);
-
-		flush_scheduled_work();
-
 		i40evf_free_misc_irq(adapter);
-
 		i40evf_reset_interrupt_capability(adapter);
 	}
 
+	del_timer_sync(&adapter->watchdog_timer);
+	flush_scheduled_work();
+
 	if (hw->aq.asq.count)
 		i40evf_shutdown_adminq(hw);
 
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index e6978d79e62b..e294f012647d 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -43,6 +43,9 @@ static int i40evf_send_pf_msg(struct i40evf_adapter *adapter,
 	struct i40e_hw *hw = &adapter->hw;
 	i40e_status err;
 
+	if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
+		return 0; /* nothing to see here, move along */
+
 	err = i40e_aq_send_msg_to_pf(hw, op, 0, msg, len, NULL);
 	if (err)
 		dev_err(&adapter->pdev->dev, "Unable to send opcode %d to PF, error %d, aq status %d\n",
@@ -651,6 +654,18 @@ void i40evf_request_stats(struct i40evf_adapter *adapter)
 		/* if the request failed, don't lock out others */
 		adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
 }
+/**
+ * i40evf_request_reset
+ * @adapter: adapter structure
+ *
+ * Request that the PF reset this VF. No response is expected.
+ **/
+void i40evf_request_reset(struct i40evf_adapter *adapter)
+{
+	/* Don't check CURRENT_OP - this is always higher priority */
+	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_RESET_VF, NULL, 0);
+	adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
+}
 
 /**
  * i40evf_virtchnl_completion
@@ -689,10 +704,12 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
 			}
 			break;
 		case I40E_VIRTCHNL_EVENT_RESET_IMPENDING:
-			adapter->state = __I40EVF_RESETTING;
-			schedule_work(&adapter->reset_task);
-			dev_info(&adapter->pdev->dev,
-				 "%s: hardware reset pending\n", __func__);
+			dev_info(&adapter->pdev->dev, "PF reset warning received\n");
+			if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
+				adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+				dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
+				schedule_work(&adapter->reset_task);
+			}
 			break;
 		default:
 			dev_err(&adapter->pdev->dev,
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index f19700e285bb..5bcb2de75933 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2013 Intel Corporation.
+# Copyright(c) 1999 - 2014 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
 # 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.
+# this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # The full GNU General Public License is included in this distribution in
 # the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 06df6928f44c..45947b3f7d92 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -2720,7 +2719,7 @@ static const u8 e1000_emc_therm_limit[4] = {
  *
  *  Updates the temperatures in mac.thermal_sensor_data
  **/
-s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw)
+static s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw)
 {
 	s32 status = E1000_SUCCESS;
 	u16 ets_offset;
@@ -2774,7 +2773,7 @@ s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw)
  *  Sets the thermal sensor thresholds according to the NVM map
  *  and save off the threshold and location values into mac.thermal_sensor_data
  **/
-s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw)
+static s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw)
 {
 	s32 status = E1000_SUCCESS;
 	u16 ets_offset;
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 8c2437722aad..f12b086e578d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -266,8 +265,6 @@ u16 igb_rxpbs_adjust_82580(u32 data);
 s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
 s32 igb_set_eee_i350(struct e1000_hw *);
 s32 igb_set_eee_i354(struct e1000_hw *);
-s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *);
-s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw);
 
 #define E1000_I2C_THERMAL_SENSOR_ADDR	0xF8
 #define E1000_EMC_INTERNAL_DATA		0x00
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 0571b973be80..393c896ac7e7 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index ab99e2b582a8..10741d170f2d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index 0c0393316a3a..db963397cc27 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -35,6 +34,8 @@
 #include "e1000_hw.h"
 #include "e1000_i210.h"
 
+static s32 igb_update_flash_i210(struct e1000_hw *hw);
+
 /**
  * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
  *  @hw: pointer to the HW structure
@@ -111,7 +112,7 @@ static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
  *  Return successful if access grant bit set, else clear the request for
  *  EEPROM access and return -E1000_ERR_NVM (-1).
  **/
-s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
+static s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
 {
 	return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
 }
@@ -123,7 +124,7 @@ s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
  *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
  *  then release the semaphores acquired.
  **/
-void igb_release_nvm_i210(struct e1000_hw *hw)
+static void igb_release_nvm_i210(struct e1000_hw *hw)
 {
 	igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
 }
@@ -206,8 +207,8 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
  *  Reads a 16 bit word from the Shadow Ram using the EERD register.
  *  Uses necessary synchronization semaphores.
  **/
-s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
-			     u16 *data)
+static s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
 {
 	s32 status = E1000_SUCCESS;
 	u16 i, count;
@@ -306,8 +307,8 @@ out:
  *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
  *  partially written.
  **/
-s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
-			      u16 *data)
+static s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+				   u16 *data)
 {
 	s32 status = E1000_SUCCESS;
 	u16 i, count;
@@ -555,7 +556,7 @@ s32 igb_read_invm_version(struct e1000_hw *hw,
  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
  *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
  **/
-s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
+static s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
 {
 	s32 status = E1000_SUCCESS;
 	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
@@ -590,7 +591,7 @@ s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
  *  up to the checksum.  Then calculates the EEPROM checksum and writes the
  *  value to the EEPROM. Next commit EEPROM data onto the Flash.
  **/
-s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
+static s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
 {
 	s32 ret_val = E1000_SUCCESS;
 	u16 checksum = 0;
@@ -684,7 +685,7 @@ bool igb_get_flash_presence_i210(struct e1000_hw *hw)
  *  @hw: pointer to the HW structure
  *
  **/
-s32 igb_update_flash_i210(struct e1000_hw *hw)
+static s32 igb_update_flash_i210(struct e1000_hw *hw)
 {
 	s32 ret_val = E1000_SUCCESS;
 	u32 flup;
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index 2d913716573a..907fe99a9813 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -28,17 +27,8 @@
 #ifndef _E1000_I210_H_
 #define _E1000_I210_H_
 
-s32 igb_update_flash_i210(struct e1000_hw *hw);
-s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw);
-s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw);
-s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
-			    u16 *data);
-s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
-			   u16 *data);
 s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
 void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
-s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
-void igb_release_nvm_i210(struct e1000_hw *hw);
 s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
 s32 igb_read_invm_version(struct e1000_hw *hw,
 			  struct e1000_fw_version *invm_ver);
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 298f0ed50670..5910a932ea7c 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index e4cbe8ef67b3..99299ba8ee3a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c
index dac1447fabf7..d5b121771c31 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h
index de9bba41acf3..f52f5515e5a8 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index a7db7f3db914..9abf82919c65 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index 433b7419cb98..5b101170b17e 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index ad2b74d95138..4009bbab7407 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -394,77 +393,6 @@ s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
 }
 
 /**
- *  e1000_write_sfp_data_byte - Writes SFP module data.
- *  @hw: pointer to the HW structure
- *  @offset: byte location offset to write to
- *  @data: data to write
- *
- *  Writes one byte to SFP module data stored
- *  in SFP resided EEPROM memory or SFP diagnostic area.
- *  Function should be called with
- *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
- *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
- *  access
- **/
-s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
-{
-	u32 i = 0;
-	u32 i2ccmd = 0;
-	u32 data_local = 0;
-
-	if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
-		hw_dbg("I2CCMD command address exceeds upper limit\n");
-		return -E1000_ERR_PHY;
-	}
-	/* The programming interface is 16 bits wide
-	 * so we need to read the whole word first
-	 * then update appropriate byte lane and write
-	 * the updated word back.
-	 */
-	/* Set up Op-code, EEPROM Address,in the I2CCMD
-	 * register. The MAC will take care of interfacing
-	 * with an EEPROM to write the data given.
-	 */
-	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
-		  E1000_I2CCMD_OPCODE_READ);
-	/* Set a command to read single word */
-	wr32(E1000_I2CCMD, i2ccmd);
-	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
-		udelay(50);
-		/* Poll the ready bit to see if lastly
-		 * launched I2C operation completed
-		 */
-		i2ccmd = rd32(E1000_I2CCMD);
-		if (i2ccmd & E1000_I2CCMD_READY) {
-			/* Check if this is READ or WRITE phase */
-			if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
-			    E1000_I2CCMD_OPCODE_READ) {
-				/* Write the selected byte
-				 * lane and update whole word
-				 */
-				data_local = i2ccmd & 0xFF00;
-				data_local |= data;
-				i2ccmd = ((offset <<
-					E1000_I2CCMD_REG_ADDR_SHIFT) |
-					E1000_I2CCMD_OPCODE_WRITE | data_local);
-				wr32(E1000_I2CCMD, i2ccmd);
-			} else {
-				break;
-			}
-		}
-	}
-	if (!(i2ccmd & E1000_I2CCMD_READY)) {
-		hw_dbg("I2CCMD Write did not complete\n");
-		return -E1000_ERR_PHY;
-	}
-	if (i2ccmd & E1000_I2CCMD_ERROR) {
-		hw_dbg("I2CCMD Error bit set\n");
-		return -E1000_ERR_PHY;
-	}
-	return 0;
-}
-
-/**
  *  igb_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 6a0873f2095a..4c2c36c46a73 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -70,7 +69,6 @@ s32  igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 s32  igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
 s32  igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
-s32  e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data);
 s32  igb_copper_link_setup_82580(struct e1000_hw *hw);
 s32  igb_get_phy_info_82580(struct e1000_hw *hw);
 s32  igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 82632c6c53af..abdd935a9dad 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index ccf472f073dd..fc3fc2c6fe40 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -525,9 +524,7 @@ void igb_set_fw_version(struct igb_adapter *);
 void igb_ptp_init(struct igb_adapter *adapter);
 void igb_ptp_stop(struct igb_adapter *adapter);
 void igb_ptp_reset(struct igb_adapter *adapter);
-void igb_ptp_tx_work(struct work_struct *work);
 void igb_ptp_rx_hang(struct igb_adapter *adapter);
-void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
 void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
 void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va,
 			 struct sk_buff *skb);
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 1df02378de69..c7f574165298 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c
index e0af5bc61613..8333f67acf96 100644
--- a/drivers/net/ethernet/intel/igb/igb_hwmon.c
+++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 46d31a49f5ea..3384156cf1b5 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2013 Intel Corporation.
+  Copyright(c) 2007-2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -13,8 +13,7 @@
   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.
+  this program; if not, see <http://www.gnu.org/licenses/>.
 
   The full GNU General Public License is included in this distribution in
   the file called "COPYING".
@@ -70,7 +69,7 @@ char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
 				"Intel(R) Gigabit Ethernet Network Driver";
 static const char igb_copyright[] =
-				"Copyright (c) 2007-2013 Intel Corporation.";
+				"Copyright (c) 2007-2014 Intel Corporation.";
 
 static const struct e1000_info *igb_info_tbl[] = {
 	[board_82575] = &e1000_82575_info,
@@ -1111,10 +1110,11 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix)
 	for (i = 0; i < numvecs; i++)
 		adapter->msix_entries[i].entry = i;
 
-	err = pci_enable_msix(adapter->pdev,
-			      adapter->msix_entries,
-			      numvecs);
-	if (err == 0)
+	err = pci_enable_msix_range(adapter->pdev,
+				    adapter->msix_entries,
+				    numvecs,
+				    numvecs);
+	if (err > 0)
 		return;
 
 	igb_reset_interrupt_capability(adapter);
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 5a54e3dc535d..9c9c141f089a 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -12,9 +12,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU 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.
+ * 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/device.h>
@@ -75,6 +74,8 @@
 #define INCVALUE_82576			(16 << IGB_82576_TSYNC_SHIFT)
 #define IGB_NBITS_82580			40
 
+static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
+
 /* SYSTIM read access for the 82576 */
 static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc)
 {
@@ -372,7 +373,7 @@ static int igb_ptp_enable(struct ptp_clock_info *ptp,
  * This work function polls the TSYNCTXCTL valid bit to determine when a
  * timestamp has been taken for the current stored skb.
  **/
-void igb_ptp_tx_work(struct work_struct *work)
+static void igb_ptp_tx_work(struct work_struct *work)
 {
 	struct igb_adapter *adapter = container_of(work, struct igb_adapter,
 						   ptp_tx_work);
@@ -466,7 +467,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter)
  * available, then it must have been for this skb here because we only
  * allow only one such packet into the queue.
  **/
-void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
+static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct skb_shared_hwtstamps shhwtstamps;
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 675435fc2e53..e2c6d8059b74 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1043,11 +1043,11 @@ static void igbvf_set_interrupt_capability(struct igbvf_adapter *adapter)
 		for (i = 0; i < 3; i++)
 			adapter->msix_entries[i].entry = i;
 
-		err = pci_enable_msix(adapter->pdev,
-		                      adapter->msix_entries, 3);
+		err = pci_enable_msix_range(adapter->pdev,
+		                            adapter->msix_entries, 3, 3);
 	}
 
-	if (err) {
+	if (err < 0) {
 		/* MSI-X failed */
 		dev_err(&adapter->pdev->dev,
 		        "Failed to initialize MSI-X interrupts.\n");
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 0186ea2969fe..4371ef0ed4a0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -765,6 +765,7 @@ struct ixgbe_adapter {
 	struct ptp_clock_info ptp_caps;
 	struct work_struct ptp_tx_work;
 	struct sk_buff *ptp_tx_skb;
+	struct hwtstamp_config tstamp_config;
 	unsigned long ptp_tx_start;
 	unsigned long last_overflow_check;
 	unsigned long last_rx_ptp_check;
@@ -884,7 +885,6 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
 					  u16 soft_id);
 void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
 					  union ixgbe_atr_input *mask);
-bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 void ixgbe_set_rx_mode(struct net_device *netdev);
 #ifdef CONFIG_IXGBE_DCB
 void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
@@ -958,8 +958,8 @@ static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring,
 	rx_ring->last_rx_timestamp = jiffies;
 }
 
-int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr,
-			     int cmd);
+int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr);
+int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr);
 void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
 void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
 void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index a26f3fee4f35..15506f0780b2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -61,6 +61,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
 	u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
 	u16 pcie_devctl2;
 
+	if (ixgbe_removed(hw->hw_addr))
+		return;
+
 	/* only take action if timeout value is defaulted to 0 */
 	if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
 		goto out;
@@ -79,8 +82,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
 	 * directly in order to set the completion timeout value for
 	 * 16ms to 55ms
 	 */
-	pci_read_config_word(adapter->pdev,
-	                     IXGBE_PCI_DEVICE_CONTROL2, &pcie_devctl2);
+	pcie_devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2);
+	if (ixgbe_removed(hw->hw_addr))
+		return;
 	pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
 	pci_write_config_word(adapter->pdev,
 	                      IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
@@ -1316,6 +1320,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
 	.get_thermal_sensor_data = NULL,
 	.init_thermal_sensor_thresh = NULL,
 	.mng_fw_enabled		= NULL,
+	.prot_autoc_read	= &prot_autoc_read_generic,
+	.prot_autoc_write	= &prot_autoc_write_generic,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index edda6814108c..b96cefd5a2eb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -63,6 +63,8 @@ static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
 				     u8 dev_addr, u8 *data);
 static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
 				      u8 dev_addr, u8 data);
+static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
+static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 
 static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
 {
@@ -122,7 +124,6 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val = 0;
 	u16 list_offset, data_offset, data_value;
-	bool got_lock = false;
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
 		ixgbe_init_mac_link_ops_82599(hw);
@@ -160,30 +161,10 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 		usleep_range(hw->eeprom.semaphore_delay * 1000,
 			     hw->eeprom.semaphore_delay * 2000);
 
-		/* Need SW/FW semaphore around AUTOC writes if LESM on,
-		 * likewise reset_pipeline requires lock as it also writes
-		 * AUTOC.
-		 */
-		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
-			if (ret_val)
-				goto setup_sfp_out;
-
-			got_lock = true;
-		}
-
 		/* Restart DSP and set SFI mode */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((hw->mac.orig_autoc) |
-				IXGBE_AUTOC_LMS_10G_SERIAL));
-		hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-		ret_val = ixgbe_reset_pipeline_82599(hw);
-
-		if (got_lock) {
-			hw->mac.ops.release_swfw_sync(hw,
-						      IXGBE_GSSR_MAC_CSR_SM);
-			got_lock = false;
-		}
+		ret_val = hw->mac.ops.prot_autoc_write(hw,
+			hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
+			false);
 
 		if (ret_val) {
 			hw_dbg(hw, " sfp module setup not complete\n");
@@ -207,6 +188,79 @@ setup_sfp_err:
 	return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
 }
 
+/**
+ *  prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
+ *  @hw: pointer to hardware structure
+ *  @locked: Return the if we locked for this read.
+ *  @reg_val: Value we read from AUTOC
+ *
+ *  For this part (82599) we need to wrap read-modify-writes with a possible
+ *  FW/SW lock.  It is assumed this lock will be freed with the next
+ *  prot_autoc_write_82599().  Note, that locked can only be true in cases
+ *  where this function doesn't return an error.
+ **/
+static s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked,
+				 u32 *reg_val)
+{
+	s32 ret_val;
+
+	*locked = false;
+	/* If LESM is on then we need to hold the SW/FW semaphore. */
+	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+					IXGBE_GSSR_MAC_CSR_SM);
+		if (!ret_val)
+			return IXGBE_ERR_SWFW_SYNC;
+
+		*locked = true;
+	}
+
+	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	return 0;
+}
+
+/**
+ * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
+ * @hw: pointer to hardware structure
+ * @reg_val: value to write to AUTOC
+ * @locked: bool to indicate whether the SW/FW lock was already taken by
+ *	     previous proc_autoc_read_82599.
+ *
+ * This part (82599) may need to hold a the SW/FW lock around all writes to
+ * AUTOC. Likewise after a write we need to do a pipeline reset.
+ **/
+static s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
+{
+	s32 ret_val = 0;
+
+	/* Blocked by MNG FW so bail */
+	if (ixgbe_check_reset_blocked(hw))
+		goto out;
+
+	/* We only need to get the lock if:
+	 *  - We didn't do it already (in the read part of a read-modify-write)
+	 *  - LESM is enabled.
+	 */
+	if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+					IXGBE_GSSR_MAC_CSR_SM);
+		if (!ret_val)
+			return IXGBE_ERR_SWFW_SYNC;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+	ret_val = ixgbe_reset_pipeline_82599(hw);
+
+out:
+	/* Free the SW/FW semaphore as we either grabbed it here or
+	 * already had it when this function was called.
+	 */
+	if (locked)
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
+	return ret_val;
+}
+
 static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
@@ -542,6 +596,10 @@ static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
+	/* Blocked by MNG FW so bail */
+	if (ixgbe_check_reset_blocked(hw))
+		return;
+
 	/* Disable tx laser; allow 100us to go dark per spec */
 	esdp_reg |= IXGBE_ESDP_SDP3;
 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
@@ -582,6 +640,10 @@ static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
  **/
 static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
+	/* Blocked by MNG FW so bail */
+	if (ixgbe_check_reset_blocked(hw))
+		return;
+
 	if (hw->mac.autotry_restart) {
 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
@@ -966,7 +1028,6 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	u32 links_reg;
 	u32 i;
 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
-	bool got_lock = false;
 	bool autoneg = false;
 
 	/* Check to see if speed passed in is supported. */
@@ -989,7 +1050,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 
 	orig_autoc = autoc;
-	start_autoc = hw->mac.cached_autoc;
+	start_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
 	pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
 
@@ -1030,27 +1091,10 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	}
 
 	if (autoc != start_autoc) {
-		/* Need SW/FW semaphore around AUTOC writes if LESM is on,
-		 * likewise reset_pipeline requires us to hold this lock as
-		 * it also writes to AUTOC.
-		 */
-		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-			status = hw->mac.ops.acquire_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
-			if (status != 0)
-				goto out;
-
-			got_lock = true;
-		}
-
 		/* Restart link */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
-		hw->mac.cached_autoc = autoc;
-		ixgbe_reset_pipeline_82599(hw);
-
-		if (got_lock)
-			hw->mac.ops.release_swfw_sync(hw,
-						      IXGBE_GSSR_MAC_CSR_SM);
+		status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
+		if (!status)
+			goto out;
 
 		/* Only poll for autoneg to complete if specified to do so */
 		if (autoneg_wait_to_complete) {
@@ -1117,7 +1161,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 {
 	ixgbe_link_speed link_speed;
 	s32 status;
-	u32 ctrl, i, autoc2;
+	u32 ctrl, i, autoc, autoc2;
 	u32 curr_lms;
 	bool link_up = false;
 
@@ -1151,11 +1195,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 		hw->phy.ops.reset(hw);
 
 	/* remember AUTOC from before we reset */
-	if (hw->mac.cached_autoc)
-		curr_lms = hw->mac.cached_autoc & IXGBE_AUTOC_LMS_MASK;
-	else
-		curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) &
-			   IXGBE_AUTOC_LMS_MASK;
+	curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
 
 mac_reset_top:
 	/*
@@ -1205,7 +1245,7 @@ mac_reset_top:
 	 * stored off yet.  Otherwise restore the stored original
 	 * values since the reset operation sets back to defaults.
 	 */
-	hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
 
 	/* Enable link if disabled in NVM */
@@ -1216,7 +1256,7 @@ mac_reset_top:
 	}
 
 	if (hw->mac.orig_link_settings_stored == false) {
-		hw->mac.orig_autoc = hw->mac.cached_autoc;
+		hw->mac.orig_autoc = autoc;
 		hw->mac.orig_autoc2 = autoc2;
 		hw->mac.orig_link_settings_stored = true;
 	} else {
@@ -1233,28 +1273,12 @@ mac_reset_top:
 				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
 				curr_lms;
 
-		if (hw->mac.cached_autoc != hw->mac.orig_autoc) {
-			/* Need SW/FW semaphore around AUTOC writes if LESM is
-			 * on, likewise reset_pipeline requires us to hold
-			 * this lock as it also writes to AUTOC.
-			 */
-			bool got_lock = false;
-			if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-				status = hw->mac.ops.acquire_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
-				if (status)
-					goto reset_hw_out;
-
-				got_lock = true;
-			}
-
-			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
-			hw->mac.cached_autoc = hw->mac.orig_autoc;
-			ixgbe_reset_pipeline_82599(hw);
-
-			if (got_lock)
-				hw->mac.ops.release_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
+		if (autoc != hw->mac.orig_autoc) {
+			status = hw->mac.ops.prot_autoc_write(hw,
+							hw->mac.orig_autoc,
+							false);
+			if (!status)
+				goto reset_hw_out;
 		}
 
 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
@@ -2260,7 +2284,7 @@ fw_version_err:
  *  Returns true if the LESM FW module is present and enabled. Otherwise
  *  returns false. Smart Speed must be disabled if LESM FW module is enabled.
  **/
-bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
 {
 	bool lesm_enabled = false;
 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
@@ -2366,7 +2390,7 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
  * full pipeline reset.  Note - We must hold the SW/FW semaphore before writing
  * to AUTOC, so this function assumes the semaphore is held.
  **/
-s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val;
 	u32 anlp1_reg = 0;
@@ -2380,11 +2404,12 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
 		IXGBE_WRITE_FLUSH(hw);
 	}
 
-	autoc_reg = hw->mac.cached_autoc;
+	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 
 	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
+			autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
 
 	/* Wait for AN to leave state 0 */
 	for (i = 0; i < 10; i++) {
@@ -2566,6 +2591,8 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
 	.get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
 	.init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
 	.mng_fw_enabled		= &ixgbe_mng_enabled,
+	.prot_autoc_read	= &prot_autoc_read_82599,
+	.prot_autoc_write	= &prot_autoc_write_82599,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index b5c434b617b1..4456c235a44a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -114,7 +114,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	s32 ret_val = 0;
 	u32 reg = 0, reg_bp = 0;
 	u16 reg_cu = 0;
-	bool got_lock = false;
+	bool locked = false;
 
 	/*
 	 * Validate the requested mode.  Strict IEEE mode does not allow
@@ -139,11 +139,17 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
 	 */
 	switch (hw->phy.media_type) {
+	case ixgbe_media_type_backplane:
+		/* some MAC's need RMW protection on AUTOC */
+		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
+		if (!ret_val)
+			goto out;
+
+		/* only backplane uses autoc so fall though */
 	case ixgbe_media_type_fiber_fixed:
 	case ixgbe_media_type_fiber:
-	case ixgbe_media_type_backplane:
 		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-		reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
 		break;
 	case ixgbe_media_type_copper:
 		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
@@ -240,27 +246,12 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 		 * LESM is on, likewise reset_pipeline requries the lock as
 		 * it also writes AUTOC.
 		 */
-		if ((hw->mac.type == ixgbe_mac_82599EB) &&
-		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
-			if (ret_val)
-				goto out;
-
-			got_lock = true;
-		}
-
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
-
-		if (hw->mac.type == ixgbe_mac_82599EB)
-			ixgbe_reset_pipeline_82599(hw);
-
-		if (got_lock)
-			hw->mac.ops.release_swfw_sync(hw,
-						      IXGBE_GSSR_MAC_CSR_SM);
+		ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
+		if (ret_val)
+			goto out;
 
 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
-		    ixgbe_device_supports_autoneg_fc(hw)) {
+		   ixgbe_device_supports_autoneg_fc(hw)) {
 		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
 				      MDIO_MMD_AN, reg_cu);
 	}
@@ -2437,6 +2428,55 @@ out:
 }
 
 /**
+ * ixgbe_pcie_timeout_poll - Return number of times to poll for completion
+ * @hw: pointer to hardware structure
+ *
+ * System-wide timeout range is encoded in PCIe Device Control2 register.
+ *
+ *  Add 10% to specified maximum and return the number of times to poll for
+ *  completion timeout, in units of 100 microsec.  Never return less than
+ *  800 = 80 millisec.
+ **/
+static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+	s16 devctl2;
+	u32 pollcnt;
+
+	pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_CONTROL2,
+			     &devctl2);
+	devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK;
+
+	switch (devctl2) {
+	case IXGBE_PCIDEVCTRL2_65_130ms:
+		 pollcnt = 1300;         /* 130 millisec */
+		break;
+	case IXGBE_PCIDEVCTRL2_260_520ms:
+		pollcnt = 5200;         /* 520 millisec */
+		break;
+	case IXGBE_PCIDEVCTRL2_1_2s:
+		pollcnt = 20000;        /* 2 sec */
+		break;
+	case IXGBE_PCIDEVCTRL2_4_8s:
+		pollcnt = 80000;        /* 8 sec */
+		break;
+	case IXGBE_PCIDEVCTRL2_17_34s:
+		pollcnt = 34000;        /* 34 sec */
+		break;
+	case IXGBE_PCIDEVCTRL2_50_100us:        /* 100 microsecs */
+	case IXGBE_PCIDEVCTRL2_1_2ms:           /* 2 millisecs */
+	case IXGBE_PCIDEVCTRL2_16_32ms:         /* 32 millisec */
+	case IXGBE_PCIDEVCTRL2_16_32ms_def:     /* 32 millisec default */
+	default:
+		pollcnt = 800;          /* 80 millisec minimum */
+		break;
+	}
+
+	/* add 10% to spec maximum */
+	return (pollcnt * 11) / 10;
+}
+
+/**
  *  ixgbe_disable_pcie_master - Disable PCI-express master access
  *  @hw: pointer to hardware structure
  *
@@ -2447,16 +2487,16 @@ out:
  **/
 static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
-	struct ixgbe_adapter *adapter = hw->back;
 	s32 status = 0;
-	u32 i;
+	u32 i, poll;
 	u16 value;
 
 	/* Always set this bit to ensure any future transactions are blocked */
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
 
 	/* Exit if master requests are blocked */
-	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
+	    ixgbe_removed(hw->hw_addr))
 		goto out;
 
 	/* Poll for master request bit to clear */
@@ -2481,10 +2521,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 	 * Before proceeding, make sure that the PCIe block does not have
 	 * transactions pending.
 	 */
-	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+	poll = ixgbe_pcie_timeout_poll(hw);
+	for (i = 0; i < poll; i++) {
 		udelay(100);
-		pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS,
-							 &value);
+		value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
+		if (ixgbe_removed(hw->hw_addr))
+			goto out;
 		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
 			goto out;
 	}
@@ -2564,6 +2606,35 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 }
 
 /**
+ * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
+ * @hw: pointer to hardware structure
+ * @reg_val: Value we read from AUTOC
+ * @locked: bool to indicate whether the SW/FW lock should be taken.  Never
+ *	    true in this the generic case.
+ *
+ * The default case requires no protection so just to the register read.
+ **/
+s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
+{
+	*locked = false;
+	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	return 0;
+}
+
+/**
+ * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write
+ * @hw: pointer to hardware structure
+ * @reg_val: value to write to AUTOC
+ * @locked: bool to indicate whether the SW/FW lock was already taken by
+ *	    previous read.
+ **/
+s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
+{
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
+	return 0;
+}
+
+/**
  *  ixgbe_disable_rx_buff_generic - Stops the receive data path
  *  @hw: pointer to hardware structure
  *
@@ -2641,6 +2712,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
 	s32 ret_val = 0;
+	bool locked = false;
 
 	/*
 	 * Link must be up to auto-blink the LEDs;
@@ -2649,28 +2721,19 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
 	if (!link_up) {
-		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
-		 * LESM is on.
-		 */
-		bool got_lock = false;
-
-		if ((hw->mac.type == ixgbe_mac_82599EB) &&
-		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-							IXGBE_GSSR_MAC_CSR_SM);
-			if (ret_val)
-				goto out;
+		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+		if (!ret_val)
+			goto out;
 
-			got_lock = true;
-		}
 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 		autoc_reg |= IXGBE_AUTOC_FLU;
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+
+		ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+		if (!ret_val)
+			goto out;
+
 		IXGBE_WRITE_FLUSH(hw);
 
-		if (got_lock)
-			hw->mac.ops.release_swfw_sync(hw,
-						      IXGBE_GSSR_MAC_CSR_SM);
 		usleep_range(10000, 20000);
 	}
 
@@ -2690,33 +2753,21 @@ out:
  **/
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
-	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	u32 autoc_reg = 0;
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
 	s32 ret_val = 0;
-	bool got_lock = false;
+	bool locked = false;
 
-	/* Need the SW/FW semaphore around AUTOC writes if 82599 and
-	 * LESM is on.
-	 */
-	if ((hw->mac.type == ixgbe_mac_82599EB) &&
-	    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-						IXGBE_GSSR_MAC_CSR_SM);
-		if (ret_val)
-			goto out;
-
-		got_lock = true;
-	}
+	ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+	if (!ret_val)
+		goto out;
 
 	autoc_reg &= ~IXGBE_AUTOC_FLU;
 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
-
-	if (hw->mac.type == ixgbe_mac_82599EB)
-		ixgbe_reset_pipeline_82599(hw);
 
-	if (got_lock)
-		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+	ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+	if (!ret_val)
+		goto out;
 
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
 	led_reg &= ~IXGBE_LED_BLINK(index);
@@ -2817,7 +2868,6 @@ san_mac_addr_clr:
  **/
 u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 {
-	struct ixgbe_adapter *adapter = hw->back;
 	u16 msix_count = 1;
 	u16 max_msix_count;
 	u16 pcie_offset;
@@ -2836,7 +2886,9 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 		return msix_count;
 	}
 
-	pci_read_config_word(adapter->pdev, pcie_offset, &msix_count);
+	msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset);
+	if (ixgbe_removed(hw->hw_addr))
+		msix_count = 0;
 	msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
 
 	/* MSI-X count is zero-based in HW */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index f2e3919750ec..ef0fd4cef5df 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -98,6 +98,10 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
                                  bool *link_up, bool link_up_wait_to_complete);
 s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
                                  u16 *wwpn_prefix);
+
+s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *, u32 *reg_val);
+s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked);
+
 s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
 void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
@@ -109,7 +113,6 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
 
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
 			     u32 headroom, int strategy);
-s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR	0xF8
 #define IXGBE_EMC_INTERNAL_DATA		0x00
@@ -125,6 +128,10 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
 s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
 
 #define IXGBE_FAILED_READ_REG 0xffffffffU
+#define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU
+#define IXGBE_FAILED_READ_CFG_WORD 0xffffU
+
+u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg);
 
 static inline bool ixgbe_removed(void __iomem *addr)
 {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 043307024c4a..f2d35c04159c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -1247,6 +1247,11 @@ static int ixgbe_link_test(struct ixgbe_adapter *adapter, u64 *data)
 	struct ixgbe_hw *hw = &adapter->hw;
 	bool link_up;
 	u32 link_speed = 0;
+
+	if (ixgbe_removed(hw->hw_addr)) {
+		*data = 1;
+		return 1;
+	}
 	*data = 0;
 
 	hw->mac.ops.check_link(hw, &link_speed, &link_up, true);
@@ -1969,6 +1974,7 @@ static void ixgbe_diag_test(struct net_device *netdev,
 		data[1] = 1;
 		data[2] = 1;
 		data[3] = 1;
+		data[4] = 1;
 		eth_test->flags |= ETH_TEST_FL_FAILED;
 		return;
 	}
@@ -1988,6 +1994,7 @@ static void ixgbe_diag_test(struct net_device *netdev,
 					data[1] = 1;
 					data[2] = 1;
 					data[3] = 1;
+					data[4] = 1;
 					eth_test->flags |= ETH_TEST_FL_FAILED;
 					clear_bit(__IXGBE_TESTING,
 						  &adapter->state);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index f58db453a97e..08726177a3eb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -585,7 +585,7 @@ static int ixgbe_fcoe_dma_pool_alloc(struct ixgbe_fcoe *fcoe,
 	struct dma_pool *pool;
 	char pool_name[32];
 
-	snprintf(pool_name, 32, "ixgbe_fcoe_ddp_%d", cpu);
+	snprintf(pool_name, 32, "ixgbe_fcoe_ddp_%u", cpu);
 
 	pool = dma_pool_create(pool_name, dev, IXGBE_FCPTR_MAX,
 			       IXGBE_FCPTR_ALIGN, PAGE_SIZE);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 32e3eaaa160a..0834e1ea44bc 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -698,7 +698,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
 				       int vectors)
 {
-	int err, vector_threshold;
+	int vector_threshold;
 
 	/* We'll want at least 2 (vector_threshold):
 	 * 1) TxQ[0] + RxQ[0] handler
@@ -712,18 +712,10 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
 	 * Right now, we simply care about how many we'll get; we'll
 	 * set them up later while requesting irq's.
 	 */
-	while (vectors >= vector_threshold) {
-		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-				      vectors);
-		if (!err) /* Success in acquiring all requested vectors. */
-			break;
-		else if (err < 0)
-			vectors = 0; /* Nasty failure, quit now */
-		else /* err == number of vectors we should try again with */
-			vectors = err;
-	}
+	vectors = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+					vector_threshold, vectors);
 
-	if (vectors < vector_threshold) {
+	if (vectors < 0) {
 		/* Can't allocate enough MSI-X interrupts?  Oh well.
 		 * This just means we'll go with either a single MSI
 		 * vector or fall back to legacy interrupts.
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 18076c4178b4..10b35d82e309 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -67,7 +67,7 @@ static char ixgbe_default_device_descr[] =
 #define DRV_VERSION "3.19.1-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
-				"Copyright (c) 1999-2013 Intel Corporation.";
+				"Copyright (c) 1999-2014 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
 	[board_82598] = &ixgbe_82598_info,
@@ -151,6 +151,8 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
+
 static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
 					  u32 reg, u16 *value)
 {
@@ -169,6 +171,9 @@ static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
 		return -1;
 
 	pcie_capability_read_word(parent_dev, reg, value);
+	if (*value == IXGBE_FAILED_READ_CFG_WORD &&
+	    ixgbe_check_cfg_remove(&adapter->hw, parent_dev))
+		return -1;
 	return 0;
 }
 
@@ -313,6 +318,48 @@ void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
 		ixgbe_remove_adapter(hw);
 }
 
+static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev)
+{
+	u16 value;
+
+	pci_read_config_word(pdev, PCI_VENDOR_ID, &value);
+	if (value == IXGBE_FAILED_READ_CFG_WORD) {
+		ixgbe_remove_adapter(hw);
+		return true;
+	}
+	return false;
+}
+
+u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+	u16 value;
+
+	if (ixgbe_removed(hw->hw_addr))
+		return IXGBE_FAILED_READ_CFG_WORD;
+	pci_read_config_word(adapter->pdev, reg, &value);
+	if (value == IXGBE_FAILED_READ_CFG_WORD &&
+	    ixgbe_check_cfg_remove(hw, adapter->pdev))
+		return IXGBE_FAILED_READ_CFG_WORD;
+	return value;
+}
+
+#ifdef CONFIG_PCI_IOV
+static u32 ixgbe_read_pci_cfg_dword(struct ixgbe_hw *hw, u32 reg)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+	u32 value;
+
+	if (ixgbe_removed(hw->hw_addr))
+		return IXGBE_FAILED_READ_CFG_DWORD;
+	pci_read_config_dword(adapter->pdev, reg, &value);
+	if (value == IXGBE_FAILED_READ_CFG_DWORD &&
+	    ixgbe_check_cfg_remove(hw, adapter->pdev))
+		return IXGBE_FAILED_READ_CFG_DWORD;
+	return value;
+}
+#endif /* CONFIG_PCI_IOV */
+
 static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter)
 {
 	BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state));
@@ -2630,9 +2677,12 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
 	switch (hw->mac.type) {
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		if (eicr & IXGBE_EICR_ECC)
-			e_info(link, "Received unrecoverable ECC Err, please "
-			       "reboot\n");
+		if (eicr & IXGBE_EICR_ECC) {
+			e_info(link, "Received ECC Err, initiating reset\n");
+			adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
+			ixgbe_service_event_schedule(adapter);
+			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+		}
 		/* Handle Flow Director Full threshold interrupt */
 		if (eicr & IXGBE_EICR_FLOW_DIR) {
 			int reinit_count = 0;
@@ -2846,9 +2896,12 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 		ixgbe_check_sfp_event(adapter, eicr);
 		/* Fall through */
 	case ixgbe_mac_X540:
-		if (eicr & IXGBE_EICR_ECC)
-			e_info(link, "Received unrecoverable ECC err, please "
-				     "reboot\n");
+		if (eicr & IXGBE_EICR_ECC) {
+			e_info(link, "Received ECC Err, initiating reset\n");
+			adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
+			ixgbe_service_event_schedule(adapter);
+			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+		}
 		ixgbe_check_overtemp_event(adapter, eicr);
 		break;
 	default:
@@ -5502,6 +5555,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
 	struct net_device *netdev = adapter->netdev;
 	u32 err;
 
+	adapter->hw.hw_addr = adapter->io_addr;
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	/*
@@ -7143,7 +7197,9 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
 
 	switch (cmd) {
 	case SIOCSHWTSTAMP:
-		return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd);
+		return ixgbe_ptp_set_ts_config(adapter, req);
+	case SIOCGHWTSTAMP:
+		return ixgbe_ptp_get_ts_config(adapter, req);
 	default:
 		return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
 	}
@@ -7792,6 +7848,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
 	case IXGBE_DEV_ID_82599_SFP:
 		/* Only these subdevices could supports WOL */
 		switch (subdevice_id) {
+		case IXGBE_SUBDEV_ID_82599_SFP_WOL0:
 		case IXGBE_SUBDEV_ID_82599_560FLR:
 			/* only support first port */
 			if (hw->bus.func != 0)
@@ -8331,6 +8388,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 	struct net_device *netdev = adapter->netdev;
 
 #ifdef CONFIG_PCI_IOV
+	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *bdev, *vfdev;
 	u32 dw0, dw1, dw2, dw3;
 	int vf, pos;
@@ -8351,10 +8409,12 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 	if (!pos)
 		goto skip_bad_vf_detection;
 
-	pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG, &dw0);
-	pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 4, &dw1);
-	pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 8, &dw2);
-	pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 12, &dw3);
+	dw0 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG);
+	dw1 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 4);
+	dw2 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 8);
+	dw3 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 12);
+	if (ixgbe_removed(hw->hw_addr))
+		goto skip_bad_vf_detection;
 
 	req_id = dw1 >> 16;
 	/* On the 82599 if bit 7 of the requestor ID is set then it's a VF */
@@ -8446,6 +8506,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
 		e_err(probe, "Cannot re-enable PCI device after reset.\n");
 		result = PCI_ERS_RESULT_DISCONNECT;
 	} else {
+		adapter->hw.hw_addr = adapter->io_addr;
 		pci_set_master(pdev);
 		pci_restore_state(pdev);
 		pci_save_state(pdev);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 132557c318f8..d2caae4750e0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -98,6 +98,32 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 }
 
 /**
+ * ixgbe_check_reset_blocked - check status of MNG FW veto bit
+ * @hw: pointer to the hardware structure
+ *
+ * This function checks the MMNGC.MNG_VETO bit to see if there are
+ * any constraints on link from manageability.  For MAC's that don't
+ * have this bit just return false since the link can not be blocked
+ * via this method.
+ **/
+s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw)
+{
+	u32 mmngc;
+
+	/* If we don't have this bit, it can't be blocking */
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return false;
+
+	mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC);
+	if (mmngc & IXGBE_MMNGC_MNG_VETO) {
+		hw_dbg(hw, "MNG_VETO bit detected.\n");
+		return true;
+	}
+
+	return false;
+}
+
+/**
  *  ixgbe_get_phy_id - Get the phy type
  *  @hw: pointer to hardware structure
  *
@@ -172,6 +198,10 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
 	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
 		goto out;
 
+	/* Blocked by MNG FW so bail */
+	if (ixgbe_check_reset_blocked(hw))
+		goto out;
+
 	/*
 	 * Perform soft PHY reset to the PHY_XS.
 	 * This will cause a soft reset to the PHY
@@ -476,6 +506,10 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 				      autoneg_reg);
 	}
 
+	/* Blocked by MNG FW so don't reset PHY */
+	if (ixgbe_check_reset_blocked(hw))
+		return status;
+
 	/* Restart PHY autonegotiation and wait for completion */
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
 			     MDIO_MMD_AN, &autoneg_reg);
@@ -682,6 +716,10 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 				      autoneg_reg);
 	}
 
+	/* Blocked by MNG FW so don't reset PHY */
+	if (ixgbe_check_reset_blocked(hw))
+		return status;
+
 	/* Restart PHY autonegotiation and wait for completion */
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
 			     MDIO_MMD_AN, &autoneg_reg);
@@ -759,6 +797,10 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
 	s32 ret_val = 0;
 	u32 i;
 
+	/* Blocked by MNG FW so bail */
+	if (ixgbe_check_reset_blocked(hw))
+		goto out;
+
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data);
 
 	/* reset the PHY and poll for completion */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index fffcbdd2bf0e..b4d4323666b8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -131,6 +131,7 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
 s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
                                                ixgbe_link_speed *speed,
                                                bool *autoneg);
+s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw);
 
 /* PHY specific */
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 5184e2a1a7d8..9ef730f2916a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -576,14 +576,21 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
 	shhwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
+int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr)
+{
+	struct hwtstamp_config *config = &adapter->tstamp_config;
+
+	return copy_to_user(ifr->ifr_data, config,
+			    sizeof(*config)) ? -EFAULT : 0;
+}
+
 /**
- * ixgbe_ptp_hwtstamp_ioctl - control hardware time stamping
+ * ixgbe_ptp_set_ts_config - control hardware time stamping
  * @adapter: pointer to adapter struct
  * @ifreq: ioctl data
- * @cmd: particular ioctl requested
  *
  * Outgoing time stamping can be enabled and disabled. Play nice and
- * disable it when requested, although it shouldn't case any overhead
+ * disable it when requested, although it shouldn't cause any overhead
  * when no packet needs it. At most one packet in the queue may be
  * marked for time stamping, otherwise it would be impossible to tell
  * for sure to which packet the hardware time stamp belongs.
@@ -599,8 +606,7 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
  * Event mode. This more accurately tells the user what the hardware is going
  * to do anyways.
  */
-int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
-			     struct ifreq *ifr, int cmd)
+int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct hwtstamp_config config;
@@ -702,6 +708,10 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 	regval = IXGBE_READ_REG(hw, IXGBE_TXSTMPH);
 	regval = IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
 
+	/* save these settings for future reference */
+	memcpy(&adapter->tstamp_config, &config,
+	       sizeof(adapter->tstamp_config));
+
 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 		-EFAULT : 0;
 }
@@ -809,6 +819,9 @@ void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
 	IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
 	IXGBE_WRITE_FLUSH(hw);
 
+	/* Reset the saved tstamp_config */
+	memset(&adapter->tstamp_config, 0, sizeof(adapter->tstamp_config));
+
 	ixgbe_ptp_start_cyclecounter(adapter);
 
 	spin_lock_irqsave(&adapter->tmreg_lock, flags);
@@ -840,7 +853,9 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
 	switch (adapter->hw.mac.type) {
 	case ixgbe_mac_X540:
-		snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
+		snprintf(adapter->ptp_caps.name,
+			 sizeof(adapter->ptp_caps.name),
+			 "%s", netdev->name);
 		adapter->ptp_caps.owner = THIS_MODULE;
 		adapter->ptp_caps.max_adj = 250000000;
 		adapter->ptp_caps.n_alarm = 0;
@@ -854,7 +869,9 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 		adapter->ptp_caps.enable = ixgbe_ptp_enable;
 		break;
 	case ixgbe_mac_82599EB:
-		snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
+		snprintf(adapter->ptp_caps.name,
+			 sizeof(adapter->ptp_caps.name),
+			 "%s", netdev->name);
 		adapter->ptp_caps.owner = THIS_MODULE;
 		adapter->ptp_caps.max_adj = 250000000;
 		adapter->ptp_caps.n_alarm = 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 0d39cfc4a3bf..c10382e5aabc 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -54,6 +54,7 @@
 #define IXGBE_DEV_ID_82599_BACKPLANE_FCOE       0x152a
 #define IXGBE_DEV_ID_82599_SFP_FCOE      0x1529
 #define IXGBE_SUBDEV_ID_82599_SFP        0x11A9
+#define IXGBE_SUBDEV_ID_82599_SFP_WOL0   0x1071
 #define IXGBE_SUBDEV_ID_82599_RNDC       0x1F72
 #define IXGBE_SUBDEV_ID_82599_560FLR     0x17D0
 #define IXGBE_SUBDEV_ID_82599_SP_560FLR  0x211B
@@ -1609,6 +1610,9 @@ enum {
 #define IXGBE_MACC_FS        0x00040000
 #define IXGBE_MAC_RX2TX_LPBK 0x00000002
 
+/* Veto Bit definiton */
+#define IXGBE_MMNGC_MNG_VETO  0x00000001
+
 /* LINKS Bit Masks */
 #define IXGBE_LINKS_KX_AN_COMP  0x80000000
 #define IXGBE_LINKS_UP          0x40000000
@@ -1853,8 +1857,19 @@ enum {
 #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
 #define IXGBE_PCI_DEVICE_CONTROL2_16ms  0x0005
 
+#define IXGBE_PCIDEVCTRL2_TIMEO_MASK	0xf
+#define IXGBE_PCIDEVCTRL2_16_32ms_def	0x0
+#define IXGBE_PCIDEVCTRL2_50_100us	0x1
+#define IXGBE_PCIDEVCTRL2_1_2ms		0x2
+#define IXGBE_PCIDEVCTRL2_16_32ms	0x5
+#define IXGBE_PCIDEVCTRL2_65_130ms	0x6
+#define IXGBE_PCIDEVCTRL2_260_520ms	0x9
+#define IXGBE_PCIDEVCTRL2_1_2s		0xa
+#define IXGBE_PCIDEVCTRL2_4_8s		0xd
+#define IXGBE_PCIDEVCTRL2_17_34s	0xe
+
 /* Number of 100 microseconds we wait for PCI Express master disable */
-#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
+#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT	800
 
 /* RAH */
 #define IXGBE_RAH_VIND_MASK     0x003C0000
@@ -2858,6 +2873,8 @@ struct ixgbe_mac_operations {
 	s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
 	s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u16);
 	void (*release_swfw_sync)(struct ixgbe_hw *, u16);
+	s32 (*prot_autoc_read)(struct ixgbe_hw *, bool *, u32 *);
+	s32 (*prot_autoc_write)(struct ixgbe_hw *, u32, bool);
 
 	/* Link */
 	void (*disable_tx_laser)(struct ixgbe_hw *);
@@ -2957,7 +2974,6 @@ struct ixgbe_mac_info {
 	u32                             max_tx_queues;
 	u32                             max_rx_queues;
 	u32                             orig_autoc;
-	u32                             cached_autoc;
 	u32                             orig_autoc2;
 	bool                            orig_link_settings_stored;
 	bool                            autotry_restart;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 24b80a6cfca4..c870f37f15d3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -855,6 +855,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
 	.get_thermal_sensor_data = NULL,
 	.init_thermal_sensor_thresh = NULL,
 	.mng_fw_enabled		= NULL,
+	.prot_autoc_read	= &prot_autoc_read_generic,
+	.prot_autoc_write	= &prot_autoc_write_generic,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 9df28985eba7..57e0cd89b3dc 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1817,7 +1817,6 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
 static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
 					int vectors)
 {
-	int err = 0;
 	int vector_threshold;
 
 	/* We'll want at least 2 (vector_threshold):
@@ -1831,33 +1830,24 @@ static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
 	 * Right now, we simply care about how many we'll get; we'll
 	 * set them up later while requesting irq's.
 	 */
-	while (vectors >= vector_threshold) {
-		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-				      vectors);
-		if (!err || err < 0) /* Success or a nasty failure. */
-			break;
-		else /* err == number of vectors we should try again with */
-			vectors = err;
-	}
-
-	if (vectors < vector_threshold)
-		err = -ENOMEM;
+	vectors = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+					vector_threshold, vectors);
 
-	if (err) {
+	if (vectors < 0) {
 		dev_err(&adapter->pdev->dev,
 			"Unable to allocate MSI-X interrupts\n");
 		kfree(adapter->msix_entries);
 		adapter->msix_entries = NULL;
-	} else {
-		/*
-		 * Adjust for only the vectors we'll use, which is minimum
-		 * of max_msix_q_vectors + NON_Q_VECTORS, or the number of
-		 * vectors we were allocated.
-		 */
-		adapter->num_msix_vectors = vectors;
+		return vectors;
 	}
 
-	return err;
+	/* Adjust for only the vectors we'll use, which is minimum
+	 * of max_msix_q_vectors + NON_Q_VECTORS, or the number of
+	 * vectors we were allocated.
+	 */
+	adapter->num_msix_vectors = vectors;
+
+	return 0;
 }
 
 /**
@@ -2787,6 +2777,9 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
 	u32 vlan_macip_lens, type_tucmd;
 	u32 mss_l4len_idx, l4len;
 
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
 	if (!skb_is_gso(skb))
 		return 0;
 
@@ -3165,7 +3158,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	tso = ixgbevf_tso(tx_ring, first, &hdr_len);
 	if (tso < 0)
 		goto out_drop;
-	else
+	else if (!tso)
 		ixgbevf_tx_csum(tx_ring, first);
 
 	ixgbevf_tx_map(tx_ring, first, hdr_len);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index f418f4f20f94..12c6a66e54d1 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2784,7 +2784,6 @@ static int mvneta_probe(struct platform_device *pdev)
 	const char *mac_from;
 	int phy_mode;
 	int err;
-	int cpu;
 
 	/* Our multiqueue support is not complete, so for now, only
 	 * allow the usage of the first RX queue
@@ -2845,18 +2844,12 @@ static int mvneta_probe(struct platform_device *pdev)
 	}
 
 	/* Alloc per-cpu stats */
-	pp->stats = alloc_percpu(struct mvneta_pcpu_stats);
+	pp->stats = netdev_alloc_pcpu_stats(struct mvneta_pcpu_stats);
 	if (!pp->stats) {
 		err = -ENOMEM;
 		goto err_unmap;
 	}
 
-	for_each_possible_cpu(cpu) {
-		struct mvneta_pcpu_stats *stats;
-		stats = per_cpu_ptr(pp->stats, cpu);
-		u64_stats_init(&stats->syncp);
-	}
-
 	dt_mac_addr = of_get_mac_address(dn);
 	if (dt_mac_addr) {
 		mac_from = "device tree";
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 563495d8975a..1a6e1887a171 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -3,7 +3,7 @@
 #
 
 config MLX4_EN
-	tristate "Mellanox Technologies 10Gbit Ethernet support"
+	tristate "Mellanox Technologies 1/10/40Gbit Ethernet support"
 	depends on PCI
 	select MLX4_CORE
 	select PTP_1588_CLOCK
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
index b4881b686159..c95ca252187c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
@@ -62,7 +62,7 @@ static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets)
 	int has_ets_tc = 0;
 
 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-		if (ets->prio_tc[i] > MLX4_EN_NUM_UP) {
+		if (ets->prio_tc[i] >= MLX4_EN_NUM_UP) {
 			en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n",
 					i, ets->prio_tc[i]);
 			return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index d357bf5a4686..3454437fcd95 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -72,6 +72,12 @@ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
 MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
 			   " Per priority bit mask");
 
+MLX4_EN_PARM_INT(inline_thold, MAX_INLINE,
+		 "Threshold for using inline data (range: 17-104, default: 104)");
+
+#define MAX_PFC_TX     0xff
+#define MAX_PFC_RX     0xff
+
 int en_print(const char *level, const struct mlx4_en_priv *priv,
 	     const char *format, ...)
 {
@@ -140,6 +146,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
 		params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
 			MLX4_EN_NUM_UP;
 		params->prof[i].rss_rings = 0;
+		params->prof[i].inline_thold = inline_thold;
 	}
 
 	return 0;
@@ -274,19 +281,8 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
 	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
 		mlx4_en_init_timestamp(mdev);
 
-	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
-		if (!dev->caps.comp_pool) {
-			mdev->profile.prof[i].rx_ring_num =
-				rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
-							   min_t(int,
-								 dev->caps.num_comp_vectors,
-								 DEF_RX_RINGS)));
-		} else {
-			mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
-				min_t(int, dev->caps.comp_pool/
-				      dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1));
-		}
-	}
+	/* Set default number of RX rings*/
+	mlx4_en_set_num_rx_rings(mdev);
 
 	/* Create our own workqueue for reset/multicast tasks
 	 * Note: we cannot use the shared workqueue because of deadlocks caused
@@ -336,8 +332,31 @@ static struct mlx4_interface mlx4_en_interface = {
 	.protocol	= MLX4_PROT_ETH,
 };
 
+void mlx4_en_verify_params(void)
+{
+	if (pfctx > MAX_PFC_TX) {
+		pr_warn("mlx4_en: WARNING: illegal module parameter pfctx 0x%x - should be in range 0-0x%x, will be changed to default (0)\n",
+			pfctx, MAX_PFC_TX);
+		pfctx = 0;
+	}
+
+	if (pfcrx > MAX_PFC_RX) {
+		pr_warn("mlx4_en: WARNING: illegal module parameter pfcrx 0x%x - should be in range 0-0x%x, will be changed to default (0)\n",
+			pfcrx, MAX_PFC_RX);
+		pfcrx = 0;
+	}
+
+	if (inline_thold < MIN_PKT_LEN || inline_thold > MAX_INLINE) {
+		pr_warn("mlx4_en: WARNING: illegal module parameter inline_thold %d - should be in range %d-%d, will be changed to default (%d)\n",
+			inline_thold, MIN_PKT_LEN, MAX_INLINE, MAX_INLINE);
+		inline_thold = MAX_INLINE;
+	}
+}
+
 static int __init mlx4_en_init(void)
 {
+	mlx4_en_verify_params();
+
 	return mlx4_register_interface(&mlx4_en_interface);
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index fad45316200a..3db594614fd3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -603,7 +603,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
 	int err = 0;
 	u64 reg_id;
 	int *qpn = &priv->base_qpn;
-	u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
+	u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr);
 
 	en_dbg(DRV, priv, "Registering MAC: %pM for adding\n",
 	       priv->dev->dev_addr);
@@ -672,7 +672,7 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
 	u64 mac;
 
 	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
-		mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
+		mac = mlx4_mac_to_u64(priv->dev->dev_addr);
 		en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
 		       priv->dev->dev_addr);
 		mlx4_unregister_mac(dev, priv->port, mac);
@@ -685,7 +685,7 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
 		for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
 			bucket = &priv->mac_hash[i];
 			hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
-				mac = mlx4_en_mac_to_u64(entry->mac);
+				mac = mlx4_mac_to_u64(entry->mac);
 				en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
 				       entry->mac);
 				mlx4_en_uc_steer_release(priv, entry->mac,
@@ -715,14 +715,14 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_dev *dev = mdev->dev;
 	int err = 0;
-	u64 new_mac_u64 = mlx4_en_mac_to_u64(new_mac);
+	u64 new_mac_u64 = mlx4_mac_to_u64(new_mac);
 
 	if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
 		struct hlist_head *bucket;
 		unsigned int mac_hash;
 		struct mlx4_mac_entry *entry;
 		struct hlist_node *tmp;
-		u64 prev_mac_u64 = mlx4_en_mac_to_u64(prev_mac);
+		u64 prev_mac_u64 = mlx4_mac_to_u64(prev_mac);
 
 		bucket = &priv->mac_hash[prev_mac[MLX4_EN_MAC_HASH_IDX]];
 		hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
@@ -751,18 +751,6 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
 	return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64);
 }
 
-u64 mlx4_en_mac_to_u64(u8 *addr)
-{
-	u64 mac = 0;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		mac <<= 8;
-		mac |= addr[i];
-	}
-	return mac;
-}
-
 static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
 {
 	int err = 0;
@@ -1081,7 +1069,7 @@ static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
 		mlx4_en_cache_mclist(dev);
 		netif_addr_unlock_bh(dev);
 		list_for_each_entry(mclist, &priv->mc_list, list) {
-			mcast_addr = mlx4_en_mac_to_u64(mclist->addr);
+			mcast_addr = mlx4_mac_to_u64(mclist->addr);
 			mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
 					    mcast_addr, 0, MLX4_MCAST_CONFIG);
 		}
@@ -1173,7 +1161,7 @@ static void mlx4_en_do_uc_filter(struct mlx4_en_priv *priv,
 				found = true;
 
 			if (!found) {
-				mac = mlx4_en_mac_to_u64(entry->mac);
+				mac = mlx4_mac_to_u64(entry->mac);
 				mlx4_en_uc_steer_release(priv, entry->mac,
 							 priv->base_qpn,
 							 entry->reg_id);
@@ -1216,7 +1204,7 @@ static void mlx4_en_do_uc_filter(struct mlx4_en_priv *priv,
 				priv->flags |= MLX4_EN_FLAG_FORCE_PROMISC;
 				break;
 			}
-			mac = mlx4_en_mac_to_u64(ha->addr);
+			mac = mlx4_mac_to_u64(ha->addr);
 			memcpy(entry->mac, ha->addr, ETH_ALEN);
 			err = mlx4_register_mac(mdev->dev, priv->port, mac);
 			if (err < 0) {
@@ -2206,7 +2194,7 @@ static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
 {
 	struct mlx4_en_priv *en_priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = en_priv->mdev;
-	u64 mac_u64 = mlx4_en_mac_to_u64(mac);
+	u64 mac_u64 = mlx4_mac_to_u64(mac);
 
 	if (!is_valid_ether_addr(mac))
 		return -EINVAL;
@@ -2341,7 +2329,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
 
 	SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
-	dev->dev_id =  port - 1;
+	dev->dev_port = port - 1;
 
 	/*
 	 * Initialize driver private data
@@ -2407,7 +2395,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		if (mlx4_is_slave(priv->mdev->dev)) {
 			eth_hw_addr_random(dev);
 			en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
-			mac_u64 = mlx4_en_mac_to_u64(dev->dev_addr);
+			mac_u64 = mlx4_mac_to_u64(dev->dev_addr);
 			mdev->dev->caps.def_mac[priv->port] = mac_u64;
 		} else {
 			en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c
index dae1a1f4ae55..c2cfb05e7290 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c
@@ -148,10 +148,16 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 	stats->tx_packets = 0;
 	stats->tx_bytes = 0;
 	priv->port_stats.tx_chksum_offload = 0;
+	priv->port_stats.queue_stopped = 0;
+	priv->port_stats.wake_queue = 0;
+
 	for (i = 0; i < priv->tx_ring_num; i++) {
 		stats->tx_packets += priv->tx_ring[i]->packets;
 		stats->tx_bytes += priv->tx_ring[i]->bytes;
 		priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum;
+		priv->port_stats.queue_stopped +=
+			priv->tx_ring[i]->queue_stopped;
+		priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue;
 	}
 
 	stats->rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 890922c1c8ee..8afb72ec957d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -318,6 +318,31 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
 	}
 }
 
+void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev)
+{
+	int i;
+	int num_of_eqs;
+	int num_rx_rings;
+	struct mlx4_dev *dev = mdev->dev;
+
+	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+		if (!dev->caps.comp_pool)
+			num_of_eqs = max_t(int, MIN_RX_RINGS,
+					   min_t(int,
+						 dev->caps.num_comp_vectors,
+						 DEF_RX_RINGS));
+		else
+			num_of_eqs = min_t(int, MAX_MSIX_P_PORT,
+					   dev->caps.comp_pool/
+					   dev->caps.num_ports) - 1;
+
+		num_rx_rings = min_t(int, num_of_eqs,
+				     netif_get_num_default_rss_queues());
+		mdev->profile.prof[i].rx_ring_num =
+			rounddown_pow_of_two(num_rx_rings);
+	}
+}
+
 int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
 			   struct mlx4_en_rx_ring **pring,
 			   u32 size, u16 stride, int node)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index c11d063473e5..03e5f6ac67e7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
@@ -129,8 +129,10 @@ static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
 	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
 		return -ENOMEM;
 
-	/* The device currently only supports 10G speed */
-	if (priv->port_state.link_speed != SPEED_10000)
+	/* The device supports 1G, 10G and 40G speeds */
+	if (priv->port_state.link_speed != 1000 &&
+	    priv->port_state.link_speed != 10000 &&
+	    priv->port_state.link_speed != 40000)
 		return priv->port_state.link_speed;
 	return 0;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 13457032d15f..69c2fcef9d4c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -44,16 +44,6 @@
 
 #include "mlx4_en.h"
 
-enum {
-	MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
-	MAX_BF = 256,
-};
-
-static int inline_thold __read_mostly = MAX_INLINE;
-
-module_param_named(inline_thold, inline_thold, int, 0444);
-MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
-
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
 			   struct mlx4_en_tx_ring **pring, int qpn, u32 size,
 			   u16 stride, int node, int queue_index)
@@ -75,8 +65,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
 	ring->size = size;
 	ring->size_mask = size - 1;
 	ring->stride = stride;
-
-	inline_thold = min(inline_thold, MAX_INLINE);
+	ring->inline_thold = priv->prof->inline_thold;
 
 	tmp = size * sizeof(struct mlx4_en_tx_info);
 	ring->tx_info = vmalloc_node(tmp, node);
@@ -456,7 +445,7 @@ static int mlx4_en_process_tx_cq(struct net_device *dev,
 	 */
 	if (netif_tx_queue_stopped(ring->tx_queue) && txbbs_skipped > 0) {
 		netif_tx_wake_queue(ring->tx_queue);
-		priv->port_stats.wake_queue++;
+		ring->wake_queue++;
 	}
 	return done;
 }
@@ -520,7 +509,7 @@ static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
 	return ring->buf + index * TXBB_SIZE;
 }
 
-static int is_inline(struct sk_buff *skb, void **pfrag)
+static int is_inline(int inline_thold, struct sk_buff *skb, void **pfrag)
 {
 	void *ptr;
 
@@ -580,7 +569,7 @@ static int get_real_size(struct sk_buff *skb, struct net_device *dev,
 		}
 	} else {
 		*lso_header_size = 0;
-		if (!is_inline(skb, NULL))
+		if (!is_inline(priv->prof->inline_thold, skb, NULL))
 			real_size = CTRL_SIZE + (skb_shinfo(skb)->nr_frags + 1) * DS_SIZE;
 		else
 			real_size = inline_size(skb);
@@ -596,7 +585,13 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
 	int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof *inl;
 
 	if (skb->len <= spc) {
-		inl->byte_count = cpu_to_be32(1 << 31 | skb->len);
+		if (likely(skb->len >= MIN_PKT_LEN)) {
+			inl->byte_count = cpu_to_be32(1 << 31 | skb->len);
+		} else {
+			inl->byte_count = cpu_to_be32(1 << 31 | MIN_PKT_LEN);
+			memset(((void *)(inl + 1)) + skb->len, 0,
+			       MIN_PKT_LEN - skb->len);
+		}
 		skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
 		if (skb_shinfo(skb)->nr_frags)
 			memcpy(((void *)(inl + 1)) + skb_headlen(skb), fragptr,
@@ -696,7 +691,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 		     ring->size - HEADROOM - MAX_DESC_TXBBS)) {
 		/* every full Tx ring stops queue */
 		netif_tx_stop_queue(ring->tx_queue);
-		priv->port_stats.queue_stopped++;
+		ring->queue_stopped++;
 
 		/* If queue was emptied after the if, and before the
 		 * stop_queue - need to wake the queue, or else it will remain
@@ -709,7 +704,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (unlikely(((int)(ring->prod - ring->cons)) <=
 			     ring->size - HEADROOM - MAX_DESC_TXBBS)) {
 			netif_tx_wake_queue(ring->tx_queue);
-			priv->port_stats.wake_queue++;
+			ring->wake_queue++;
 		} else {
 			return NETDEV_TX_BUSY;
 		}
@@ -747,11 +742,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx_info->data_offset = (void *)data - (void *)tx_desc;
 
 	tx_info->linear = (lso_header_size < skb_headlen(skb) &&
-			   !is_inline(skb, NULL)) ? 1 : 0;
+			   !is_inline(ring->inline_thold, skb, NULL)) ? 1 : 0;
 
 	data += skb_shinfo(skb)->nr_frags + tx_info->linear - 1;
 
-	if (is_inline(skb, &fragptr)) {
+	if (is_inline(ring->inline_thold, skb, &fragptr)) {
 		tx_info->inl = 1;
 	} else {
 		/* Map fragments */
@@ -881,7 +876,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 	skb_tx_timestamp(skb);
 
 	if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {
-		*(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
+		tx_desc->ctrl.bf_qpn |= cpu_to_be32(ring->doorbell_qpn);
+
 		op_own |= htonl((bf_index & 0xffff) << 8);
 		/* Ensure new descirptor hits memory
 		* before setting ownership of this descriptor to HW */
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 91b69ff4b4a2..9cdf452140da 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1890,7 +1890,8 @@ void mlx4_opreq_action(struct work_struct *work)
 			err = EINVAL;
 			break;
 		}
-		err = mlx4_cmd(dev, 0, ((u32) err | cpu_to_be32(token) << 16),
+		err = mlx4_cmd(dev, 0, ((u32) err |
+					(__force u32)cpu_to_be32(token) << 16),
 			       1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
 			       MLX4_CMD_NATIVE);
 		if (err) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index d711158b0d4b..979ea4364efb 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -41,7 +41,6 @@
 #include <linux/slab.h>
 #include <linux/io-mapping.h>
 #include <linux/delay.h>
-#include <linux/netdevice.h>
 #include <linux/kmod.h>
 
 #include <linux/mlx4/device.h>
@@ -1974,9 +1973,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct msix_entry *entries;
 	int nreq = min_t(int, dev->caps.num_ports *
-			 min_t(int, netif_get_num_default_rss_queues() + 1,
+			 min_t(int, num_online_cpus() + 1,
 			       MAX_MSIX_P_PORT) + MSIX_LEGACY_SZ, MAX_MSIX);
-	int err;
 	int i;
 
 	if (msi_x) {
@@ -1990,23 +1988,13 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 		for (i = 0; i < nreq; ++i)
 			entries[i].entry = i;
 
-	retry:
-		err = pci_enable_msix(dev->pdev, entries, nreq);
-		if (err) {
-			/* Try again if at least 2 vectors are available */
-			if (err > 1) {
-				mlx4_info(dev, "Requested %d vectors, "
-					  "but only %d MSI-X vectors available, "
-					  "trying again\n", nreq, err);
-				nreq = err;
-				goto retry;
-			}
+		nreq = pci_enable_msix_range(dev->pdev, entries, 2, nreq);
+
+		if (nreq < 0) {
 			kfree(entries);
 			goto no_msi;
-		}
-
-		if (nreq <
-		    MSIX_LEGACY_SZ + dev->caps.num_ports * MIN_MSIX_P_PORT) {
+		} else if (nreq < MSIX_LEGACY_SZ +
+				  dev->caps.num_ports * MIN_MSIX_P_PORT) {
 			/*Working in legacy mode , all EQ's shared*/
 			dev->caps.comp_pool           = 0;
 			dev->caps.num_comp_vectors = nreq - 1;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 6b65f7795215..7aec6c833973 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -51,8 +51,8 @@
 
 #define DRV_NAME	"mlx4_core"
 #define PFX		DRV_NAME ": "
-#define DRV_VERSION	"1.1"
-#define DRV_RELDATE	"Dec, 2011"
+#define DRV_VERSION	"2.2-1"
+#define DRV_RELDATE	"Feb, 2014"
 
 #define MLX4_FS_UDP_UC_EN		(1 << 1)
 #define MLX4_FS_TCP_UC_EN		(1 << 2)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 9ca223bc90fc..69e1f36858e0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -57,8 +57,8 @@
 #include "en_port.h"
 
 #define DRV_NAME	"mlx4_en"
-#define DRV_VERSION	"2.0"
-#define DRV_RELDATE	"Dec 2011"
+#define DRV_VERSION	"2.2-1"
+#define DRV_RELDATE	"Feb 2014"
 
 #define MLX4_EN_MSG_LEVEL	(NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
 
@@ -187,6 +187,13 @@ enum {
 #define GET_AVG_PERF_COUNTER(cnt)	(0)
 #endif /* MLX4_EN_PERF_STAT */
 
+/* Constants for TX flow */
+enum {
+	MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
+	MAX_BF = 256,
+	MIN_PKT_LEN = 17,
+};
+
 /*
  * Configurables
  */
@@ -267,10 +274,13 @@ struct mlx4_en_tx_ring {
 	unsigned long bytes;
 	unsigned long packets;
 	unsigned long tx_csum;
+	unsigned long queue_stopped;
+	unsigned long wake_queue;
 	struct mlx4_bf bf;
 	bool bf_enabled;
 	struct netdev_queue *tx_queue;
 	int hwtstamp_tx_type;
+	int inline_thold;
 };
 
 struct mlx4_en_rx_desc {
@@ -346,6 +356,7 @@ struct mlx4_en_port_profile {
 	u8 tx_pause;
 	u8 tx_ppp;
 	int rss_rings;
+	int inline_thold;
 };
 
 struct mlx4_en_profile {
@@ -737,7 +748,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
 			     int cq, int user_prio);
 void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
 				struct mlx4_en_tx_ring *ring);
-
+void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev);
 int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
 			   struct mlx4_en_rx_ring **pring,
 			   u32 size, u16 stride, int node);
@@ -786,7 +797,6 @@ void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv);
 
 #define MLX4_EN_NUM_SELF_TEST	5
 void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
-u64 mlx4_en_mac_to_u64(u8 *addr);
 void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
 
 /*
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index a064f06e0cb8..6f7c866d0bfa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -46,8 +46,8 @@
 #include "mlx5_core.h"
 
 #define DRIVER_NAME "mlx5_core"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE	"June 2013"
+#define DRIVER_VERSION "2.2-1"
+#define DRIVER_RELDATE	"Feb 2014"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox ConnectX-IB HCA core library");
@@ -116,7 +116,6 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
 	struct mlx5_eq_table *table = &dev->priv.eq_table;
 	int num_eqs = 1 << dev->caps.log_max_eq;
 	int nvec;
-	int err;
 	int i;
 
 	nvec = dev->caps.num_ports * num_online_cpus() + MLX5_EQ_VEC_COMP_BASE;
@@ -131,17 +130,12 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
 	for (i = 0; i < nvec; i++)
 		table->msix_arr[i].entry = i;
 
-retry:
-	table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
-	err = pci_enable_msix(dev->pdev, table->msix_arr, nvec);
-	if (err <= 0) {
-		return err;
-	} else if (err > 2) {
-		nvec = err;
-		goto retry;
-	}
+	nvec = pci_enable_msix_range(dev->pdev, table->msix_arr,
+				     MLX5_EQ_VEC_COMP_BASE, nvec);
+	if (nvec < 0)
+		return nvec;
 
-	mlx5_core_dbg(dev, "received %d MSI vectors out of %d requested\n", err, nvec);
+	table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 68026f7e8ba3..130f6b204efa 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2329,16 +2329,14 @@ static int myri10ge_request_irq(struct myri10ge_priv *mgp)
 	status = 0;
 	if (myri10ge_msi) {
 		if (mgp->num_slices > 1) {
-			status =
-			    pci_enable_msix(pdev, mgp->msix_vectors,
-					    mgp->num_slices);
-			if (status == 0) {
-				mgp->msix_enabled = 1;
-			} else {
+			status = pci_enable_msix_range(pdev, mgp->msix_vectors,
+					mgp->num_slices, mgp->num_slices);
+			if (status < 0) {
 				dev_err(&pdev->dev,
 					"Error %d setting up MSI-X\n", status);
 				return status;
 			}
+			mgp->msix_enabled = 1;
 		}
 		if (mgp->msix_enabled == 0) {
 			status = pci_enable_msi(pdev);
@@ -3895,32 +3893,34 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
 	mgp->msix_vectors = kcalloc(mgp->num_slices, sizeof(*mgp->msix_vectors),
 				    GFP_KERNEL);
 	if (mgp->msix_vectors == NULL)
-		goto disable_msix;
+		goto no_msix;
 	for (i = 0; i < mgp->num_slices; i++) {
 		mgp->msix_vectors[i].entry = i;
 	}
 
 	while (mgp->num_slices > 1) {
-		/* make sure it is a power of two */
-		while (!is_power_of_2(mgp->num_slices))
-			mgp->num_slices--;
+		mgp->num_slices = rounddown_pow_of_two(mgp->num_slices);
 		if (mgp->num_slices == 1)
-			goto disable_msix;
-		status = pci_enable_msix(pdev, mgp->msix_vectors,
-					 mgp->num_slices);
-		if (status == 0) {
-			pci_disable_msix(pdev);
+			goto no_msix;
+		status = pci_enable_msix_range(pdev,
+					       mgp->msix_vectors,
+					       mgp->num_slices,
+					       mgp->num_slices);
+		if (status < 0)
+			goto no_msix;
+
+		pci_disable_msix(pdev);
+
+		if (status == mgp->num_slices) {
 			if (old_allocated)
 				kfree(old_fw);
 			return;
-		}
-		if (status > 0)
+		} else {
 			mgp->num_slices = status;
-		else
-			goto disable_msix;
+		}
 	}
 
-disable_msix:
+no_msix:
 	if (mgp->msix_vectors != NULL) {
 		kfree(mgp->msix_vectors);
 		mgp->msix_vectors = NULL;
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 9eeddbd0b2c7..56e3a9d42bb2 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -3792,9 +3792,10 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
 	writeq(rx_mat, &bar0->rx_mat);
 	readq(&bar0->rx_mat);
 
-	ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries);
+	ret = pci_enable_msix_range(nic->pdev, nic->entries,
+				    nic->num_entries, nic->num_entries);
 	/* We fail init if error or we get less vectors than min required */
-	if (ret) {
+	if (ret < 0) {
 		DBG_PRINT(ERR_DBG, "Enabling MSI-X failed\n");
 		kfree(nic->entries);
 		swstats->mem_freed += nic->num_entries *
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index e46e8698e630..c83cedd26dec 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -2349,12 +2349,18 @@ start:
 	vdev->vxge_entries[j].entry = VXGE_ALARM_MSIX_ID;
 	vdev->vxge_entries[j].in_use = 0;
 
-	ret = pci_enable_msix(vdev->pdev, vdev->entries, vdev->intr_cnt);
-	if (ret > 0) {
+	ret = pci_enable_msix_range(vdev->pdev,
+				    vdev->entries, 3, vdev->intr_cnt);
+	if (ret < 0) {
+		ret = -ENODEV;
+		goto enable_msix_failed;
+	} else if (ret < vdev->intr_cnt) {
+		pci_disable_msix(vdev->pdev);
+
 		vxge_debug_init(VXGE_ERR,
 			"%s: MSI-X enable failed for %d vectors, ret: %d",
 			VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
-		if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+		if (max_config_vpath != VXGE_USE_DEFAULT) {
 			ret = -ENODEV;
 			goto enable_msix_failed;
 		}
@@ -2368,9 +2374,6 @@ start:
 		vxge_close_vpaths(vdev, temp);
 		vdev->no_of_vpath = temp;
 		goto start;
-	} else if (ret < 0) {
-		ret = -ENODEV;
-		goto enable_msix_failed;
 	}
 	return 0;
 
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 70cf97fe67f2..bad3c057ee8a 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -3930,7 +3930,7 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 {
 	struct fe_priv *np = get_nvpriv(dev);
 	u8 __iomem *base = get_hwbase(dev);
-	int ret = 1;
+	int ret;
 	int i;
 	irqreturn_t (*handler)(int foo, void *data);
 
@@ -3946,14 +3946,18 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 	if (np->msi_flags & NV_MSI_X_CAPABLE) {
 		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++)
 			np->msi_x_entry[i].entry = i;
-		ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK));
-		if (ret == 0) {
+		ret = pci_enable_msix_range(np->pci_dev,
+					    np->msi_x_entry,
+					    np->msi_flags & NV_MSI_X_VECTORS_MASK,
+					    np->msi_flags & NV_MSI_X_VECTORS_MASK);
+		if (ret > 0) {
 			np->msi_flags |= NV_MSI_X_ENABLED;
 			if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) {
 				/* Request irq for rx handling */
 				sprintf(np->name_rx, "%s-rx", dev->name);
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector,
-						nv_nic_irq_rx, IRQF_SHARED, np->name_rx, dev) != 0) {
+				ret = request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector,
+						  nv_nic_irq_rx, IRQF_SHARED, np->name_rx, dev);
+				if (ret) {
 					netdev_info(dev,
 						    "request_irq failed for rx %d\n",
 						    ret);
@@ -3963,8 +3967,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 				}
 				/* Request irq for tx handling */
 				sprintf(np->name_tx, "%s-tx", dev->name);
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector,
-						nv_nic_irq_tx, IRQF_SHARED, np->name_tx, dev) != 0) {
+				ret = request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector,
+						  nv_nic_irq_tx, IRQF_SHARED, np->name_tx, dev);
+				if (ret) {
 					netdev_info(dev,
 						    "request_irq failed for tx %d\n",
 						    ret);
@@ -3974,8 +3979,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 				}
 				/* Request irq for link and timer handling */
 				sprintf(np->name_other, "%s-other", dev->name);
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector,
-						nv_nic_irq_other, IRQF_SHARED, np->name_other, dev) != 0) {
+				ret = request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector,
+						  nv_nic_irq_other, IRQF_SHARED, np->name_other, dev);
+				if (ret) {
 					netdev_info(dev,
 						    "request_irq failed for link %d\n",
 						    ret);
@@ -3991,7 +3997,9 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 				set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
 			} else {
 				/* Request irq for all interrupts */
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, handler, IRQF_SHARED, dev->name, dev) != 0) {
+				ret = request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector,
+						  handler, IRQF_SHARED, dev->name, dev);
+				if (ret) {
 					netdev_info(dev,
 						    "request_irq failed %d\n",
 						    ret);
@@ -4005,13 +4013,15 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 				writel(0, base + NvRegMSIXMap1);
 			}
 			netdev_info(dev, "MSI-X enabled\n");
+			return 0;
 		}
 	}
-	if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+	if (np->msi_flags & NV_MSI_CAPABLE) {
 		ret = pci_enable_msi(np->pci_dev);
 		if (ret == 0) {
 			np->msi_flags |= NV_MSI_ENABLED;
-			if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
+			ret = request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev);
+			if (ret) {
 				netdev_info(dev, "request_irq failed %d\n",
 					    ret);
 				pci_disable_msi(np->pci_dev);
@@ -4025,13 +4035,12 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
 			/* enable msi vector 0 */
 			writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
 			netdev_info(dev, "MSI enabled\n");
+			return 0;
 		}
 	}
-	if (ret != 0) {
-		if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0)
-			goto out_err;
 
-	}
+	if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0)
+		goto out_err;
 
 	return 0;
 out_free_tx:
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 70849dea32b1..f09c35d669b3 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -643,8 +643,9 @@ static int netxen_setup_msi_interrupts(struct netxen_adapter *adapter,
 
 	if (adapter->msix_supported) {
 		netxen_init_msix_entries(adapter, num_msix);
-		err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
-		if (err == 0) {
+		err = pci_enable_msix_range(pdev, adapter->msix_entries,
+					    num_msix, num_msix);
+		if (err > 0) {
 			adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
 			netxen_set_msix_bit(pdev, 1);
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index f19f81cde134..df9daa335292 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -38,8 +38,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 55
-#define QLCNIC_LINUX_VERSIONID  "5.3.55"
+#define _QLCNIC_LINUX_SUBVERSION 56
+#define QLCNIC_LINUX_VERSIONID  "5.3.56"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -394,7 +394,7 @@ struct qlcnic_nic_intr_coalesce {
 	u32	timer_out;
 };
 
-struct qlcnic_dump_template_hdr {
+struct qlcnic_83xx_dump_template_hdr {
 	u32	type;
 	u32	offset;
 	u32	size;
@@ -411,15 +411,42 @@ struct qlcnic_dump_template_hdr {
 	u32	rsvd[0];
 };
 
+struct qlcnic_82xx_dump_template_hdr {
+	u32	type;
+	u32	offset;
+	u32	size;
+	u32	cap_mask;
+	u32	num_entries;
+	u32	version;
+	u32	timestamp;
+	u32	checksum;
+	u32	drv_cap_mask;
+	u32	sys_info[3];
+	u32	saved_state[16];
+	u32	cap_sizes[8];
+	u32	rsvd[7];
+	u32	capabilities;
+	u32	rsvd1[0];
+};
+
 struct qlcnic_fw_dump {
 	u8	clr;	/* flag to indicate if dump is cleared */
 	bool	enable; /* enable/disable dump */
 	u32	size;	/* total size of the dump */
+	u32	cap_mask; /* Current capture mask */
 	void	*data;	/* dump data area */
-	struct	qlcnic_dump_template_hdr *tmpl_hdr;
+	void	*tmpl_hdr;
 	dma_addr_t phys_addr;
 	void	*dma_buffer;
 	bool	use_pex_dma;
+	/* Read only elements which are common between 82xx and 83xx
+	 * template header. Update these values immediately after we read
+	 * template header from Firmware
+	 */
+	u32	tmpl_hdr_size;
+	u32	version;
+	u32	num_entries;
+	u32	offset;
 };
 
 /*
@@ -1769,6 +1796,12 @@ struct qlcnic_hardware_ops {
 				struct qlcnic_host_tx_ring *);
 	void (*disable_tx_intr) (struct qlcnic_adapter *,
 				 struct qlcnic_host_tx_ring *);
+	u32 (*get_saved_state)(void *, u32);
+	void (*set_saved_state)(void *, u32, u32);
+	void (*cache_tmpl_hdr_values)(struct qlcnic_fw_dump *);
+	u32 (*get_cap_size)(void *, int);
+	void (*set_sys_info)(void *, int, u32);
+	void (*store_cap_mask)(void *, u32);
 };
 
 extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -2007,6 +2040,42 @@ static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter)
 		adapter->ahw->hw_ops->read_phys_port_id(adapter);
 }
 
+static inline u32 qlcnic_get_saved_state(struct qlcnic_adapter *adapter,
+					 void *t_hdr, u32 index)
+{
+	return adapter->ahw->hw_ops->get_saved_state(t_hdr, index);
+}
+
+static inline void qlcnic_set_saved_state(struct qlcnic_adapter *adapter,
+					  void *t_hdr, u32 index, u32 value)
+{
+	adapter->ahw->hw_ops->set_saved_state(t_hdr, index, value);
+}
+
+static inline void qlcnic_cache_tmpl_hdr_values(struct qlcnic_adapter *adapter,
+						struct qlcnic_fw_dump *fw_dump)
+{
+	adapter->ahw->hw_ops->cache_tmpl_hdr_values(fw_dump);
+}
+
+static inline u32 qlcnic_get_cap_size(struct qlcnic_adapter *adapter,
+				      void *tmpl_hdr, int index)
+{
+	return adapter->ahw->hw_ops->get_cap_size(tmpl_hdr, index);
+}
+
+static inline void qlcnic_set_sys_info(struct qlcnic_adapter *adapter,
+				       void *tmpl_hdr, int idx, u32 value)
+{
+	adapter->ahw->hw_ops->set_sys_info(tmpl_hdr, idx, value);
+}
+
+static inline void qlcnic_store_cap_mask(struct qlcnic_adapter *adapter,
+					 void *tmpl_hdr, u32 mask)
+{
+	adapter->ahw->hw_ops->store_cap_mask(tmpl_hdr, mask);
+}
+
 static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
 					    u32 key)
 {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 4146664d4d6a..3b83fbde4975 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -203,7 +203,12 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
 	.disable_sds_intr		= qlcnic_83xx_disable_sds_intr,
 	.enable_tx_intr			= qlcnic_83xx_enable_tx_intr,
 	.disable_tx_intr		= qlcnic_83xx_disable_tx_intr,
-
+	.get_saved_state		= qlcnic_83xx_get_saved_state,
+	.set_saved_state		= qlcnic_83xx_set_saved_state,
+	.cache_tmpl_hdr_values		= qlcnic_83xx_cache_tmpl_hdr_values,
+	.get_cap_size			= qlcnic_83xx_get_cap_size,
+	.set_sys_info			= qlcnic_83xx_set_sys_info,
+	.store_cap_mask			= qlcnic_83xx_store_cap_mask,
 };
 
 static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -340,6 +345,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
 			if (qlcnic_sriov_vf_check(adapter))
 				return -EINVAL;
 			num_msix = 1;
+			adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
 			adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
 		}
 	}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index f92485ca21d1..81c1889f6f3e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -308,6 +308,8 @@ struct qlc_83xx_reset {
 #define QLC_83XX_IDC_FLASH_PARAM_ADDR			0x3e8020
 
 struct qlcnic_adapter;
+struct qlcnic_fw_dump;
+
 struct qlc_83xx_idc {
 	int (*state_entry) (struct qlcnic_adapter *);
 	u64		sec_counter;
@@ -650,4 +652,10 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *);
 void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *);
 int qlcnic_83xx_aer_reset(struct qlcnic_adapter *);
 void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *);
+u32 qlcnic_83xx_get_saved_state(void *, u32);
+void qlcnic_83xx_set_saved_state(void *, u32, u32);
+void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *);
+u32 qlcnic_83xx_get_cap_size(void *, int);
+void qlcnic_83xx_set_sys_info(void *, int, u32);
+void qlcnic_83xx_store_cap_mask(void *, u32);
 #endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
index 77f1bce432d2..7d4f54912bad 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
@@ -807,7 +807,7 @@ qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
 	    !type->tc_param_valid)
 		return;
 
-	if (tc < 0 || (tc > QLC_DCB_MAX_TC))
+	if (tc < 0 || (tc >= QLC_DCB_MAX_TC))
 		return;
 
 	tc_cfg = &type->tc_cfg[tc];
@@ -843,7 +843,7 @@ static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
 	    !type->tc_param_valid)
 		return;
 
-	if (pgid < 0 || pgid > QLC_DCB_MAX_PG)
+	if (pgid < 0 || pgid >= QLC_DCB_MAX_PG)
 		return;
 
 	pgcfg = &type->pg_cfg[pgid];
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index acee1a5d80c6..1960609481ce 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1639,14 +1639,14 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
 	}
 
 	if (fw_dump->clr)
-		dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
+		dump->len = fw_dump->tmpl_hdr_size + fw_dump->size;
 	else
 		dump->len = 0;
 
 	if (!qlcnic_check_fw_dump_state(adapter))
 		dump->flag = ETH_FW_DUMP_DISABLE;
 	else
-		dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
+		dump->flag = fw_dump->cap_mask;
 
 	dump->version = adapter->fw_version;
 	return 0;
@@ -1671,9 +1671,10 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 		netdev_info(netdev, "Dump not available\n");
 		return -EINVAL;
 	}
+
 	/* Copy template header first */
-	copy_sz = fw_dump->tmpl_hdr->size;
-	hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
+	copy_sz = fw_dump->tmpl_hdr_size;
+	hdr_ptr = (u32 *)fw_dump->tmpl_hdr;
 	data = buffer;
 	for (i = 0; i < copy_sz/sizeof(u32); i++)
 		*data++ = cpu_to_le32(*hdr_ptr++);
@@ -1681,7 +1682,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 	/* Copy captured dump data */
 	memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
 	dump->len = copy_sz + fw_dump->size;
-	dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
+	dump->flag = fw_dump->cap_mask;
 
 	/* Free dump area once data has been captured */
 	vfree(fw_dump->data);
@@ -1703,7 +1704,11 @@ static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
 		return -EOPNOTSUPP;
 	}
 
-	fw_dump->tmpl_hdr->drv_cap_mask = mask;
+	fw_dump->cap_mask = mask;
+
+	/* Store new capture mask in template header as well*/
+	qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask);
+
 	netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
 	return 0;
 }
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 03d18a0be6ce..9f3adf4e70b5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -317,9 +317,7 @@ static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data)
 int
 qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
 {
-	int timeout = 0;
-	int err = 0;
-	u32 done = 0;
+	int timeout = 0, err = 0, done = 0;
 
 	while (!done) {
 		done = QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)),
@@ -327,10 +325,20 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
 		if (done == 1)
 			break;
 		if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
-			dev_err(&adapter->pdev->dev,
-				"Failed to acquire sem=%d lock; holdby=%d\n",
-				sem,
-				id_reg ? QLCRD32(adapter, id_reg, &err) : -1);
+			if (id_reg) {
+				done = QLCRD32(adapter, id_reg, &err);
+				if (done != -1)
+					dev_err(&adapter->pdev->dev,
+						"Failed to acquire sem=%d lock held by=%d\n",
+						sem, done);
+				else
+					dev_err(&adapter->pdev->dev,
+						"Failed to acquire sem=%d lock",
+						sem);
+			} else {
+				dev_err(&adapter->pdev->dev,
+					"Failed to acquire sem=%d lock", sem);
+			}
 			return -EIO;
 		}
 		msleep(1);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 63d75617d445..576b301b11ef 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -161,6 +161,7 @@ struct qlcnic_host_sds_ring;
 struct qlcnic_host_tx_ring;
 struct qlcnic_hardware_context;
 struct qlcnic_adapter;
+struct qlcnic_fw_dump;
 
 int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong, int *);
 int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32);
@@ -213,4 +214,11 @@ int qlcnic_82xx_shutdown(struct pci_dev *);
 int qlcnic_82xx_resume(struct qlcnic_adapter *);
 void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed);
 void qlcnic_fw_poll_work(struct work_struct *work);
+
+u32 qlcnic_82xx_get_saved_state(void *, u32);
+void qlcnic_82xx_set_saved_state(void *, u32, u32);
+void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *);
+u32 qlcnic_82xx_get_cap_size(void *, int);
+void qlcnic_82xx_set_sys_info(void *, int, u32);
+void qlcnic_82xx_store_cap_mask(void *, u32);
 #endif				/* __QLCNIC_HW_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index ba78c7481fa3..4b92d9d90267 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -90,7 +90,6 @@ static void qlcnic_82xx_io_resume(struct pci_dev *);
 static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
 static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *,
 						      pci_channel_state_t);
-
 static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -561,6 +560,12 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
 	.disable_sds_intr		= qlcnic_82xx_disable_sds_intr,
 	.enable_tx_intr			= qlcnic_82xx_enable_tx_intr,
 	.disable_tx_intr		= qlcnic_82xx_disable_tx_intr,
+	.get_saved_state		= qlcnic_82xx_get_saved_state,
+	.set_saved_state		= qlcnic_82xx_set_saved_state,
+	.cache_tmpl_hdr_values		= qlcnic_82xx_cache_tmpl_hdr_values,
+	.get_cap_size			= qlcnic_82xx_get_cap_size,
+	.set_sys_info			= qlcnic_82xx_set_sys_info,
+	.store_cap_mask			= qlcnic_82xx_store_cap_mask,
 };
 
 static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
@@ -684,7 +689,7 @@ restore:
 int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
 {
 	struct pci_dev *pdev = adapter->pdev;
-	int err = -1, vector;
+	int err, vector;
 
 	if (!adapter->msix_entries) {
 		adapter->msix_entries = kcalloc(num_msix,
@@ -701,13 +706,17 @@ enable_msix:
 		for (vector = 0; vector < num_msix; vector++)
 			adapter->msix_entries[vector].entry = vector;
 
-		err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
-		if (err == 0) {
+		err = pci_enable_msix_range(pdev,
+					    adapter->msix_entries, 1, num_msix);
+
+		if (err == num_msix) {
 			adapter->flags |= QLCNIC_MSIX_ENABLED;
 			adapter->ahw->num_msix = num_msix;
 			dev_info(&pdev->dev, "using msi-x interrupts\n");
-			return err;
+			return 0;
 		} else if (err > 0) {
+			pci_disable_msix(pdev);
+
 			dev_info(&pdev->dev,
 				 "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
 				 num_msix, err);
@@ -715,12 +724,12 @@ enable_msix:
 			if (qlcnic_82xx_check(adapter)) {
 				num_msix = rounddown_pow_of_two(err);
 				if (err < QLCNIC_82XX_MINIMUM_VECTOR)
-					return -EIO;
+					return -ENOSPC;
 			} else {
 				num_msix = rounddown_pow_of_two(err - 1);
 				num_msix += 1;
 				if (err < QLCNIC_83XX_MINIMUM_VECTOR)
-					return -EIO;
+					return -ENOSPC;
 			}
 
 			if (qlcnic_82xx_check(adapter) &&
@@ -747,7 +756,7 @@ enable_msix:
 		}
 	}
 
-	return err;
+	return -EIO;
 }
 
 static int qlcnic_82xx_calculate_msix_vector(struct qlcnic_adapter *adapter)
@@ -816,9 +825,10 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
 
 		if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
 			qlcnic_disable_multi_tx(adapter);
+			adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
 
 			err = qlcnic_enable_msi_legacy(adapter);
-			if (!err)
+			if (err)
 				return err;
 		}
 	}
@@ -2441,8 +2451,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if (err) {
 			switch (err) {
 			case -ENOTRECOVERABLE:
-				dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware. Please reboot\n");
-				dev_err(&pdev->dev, "If reboot doesn't help, please replace the adapter with new one and return the faulty adapter for repair\n");
+				dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware\n");
+				dev_err(&pdev->dev, "Please replace the adapter with new one and return the faulty adapter for repair\n");
 				goto err_out_free_hw;
 			case -ENOMEM:
 				dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n");
@@ -3863,7 +3873,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
 		strcpy(buf, "Tx");
 	}
 
-	if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
+	if (!QLCNIC_IS_MSI_FAMILY(adapter)) {
 		netdev_err(netdev, "No RSS/TSS support in INT-x mode\n");
 		return -EINVAL;
 	}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index 7763962e2ec4..37b979b1266b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -211,6 +211,107 @@ enum qlcnic_minidump_opcode {
 	QLCNIC_DUMP_RDEND	= 255
 };
 
+inline u32 qlcnic_82xx_get_saved_state(void *t_hdr, u32 index)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
+
+	return hdr->saved_state[index];
+}
+
+inline void qlcnic_82xx_set_saved_state(void *t_hdr, u32 index,
+					u32 value)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
+
+	hdr->saved_state[index] = value;
+}
+
+void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr;
+
+	hdr = fw_dump->tmpl_hdr;
+	fw_dump->tmpl_hdr_size = hdr->size;
+	fw_dump->version = hdr->version;
+	fw_dump->num_entries = hdr->num_entries;
+	fw_dump->offset = hdr->offset;
+
+	hdr->drv_cap_mask = hdr->cap_mask;
+	fw_dump->cap_mask = hdr->cap_mask;
+}
+
+inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
+
+	return hdr->cap_sizes[index];
+}
+
+void qlcnic_82xx_set_sys_info(void *t_hdr, int idx, u32 value)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
+
+	hdr->sys_info[idx] = value;
+}
+
+void qlcnic_82xx_store_cap_mask(void *tmpl_hdr, u32 mask)
+{
+	struct qlcnic_82xx_dump_template_hdr *hdr = tmpl_hdr;
+
+	hdr->drv_cap_mask = mask;
+}
+
+inline u32 qlcnic_83xx_get_saved_state(void *t_hdr, u32 index)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
+
+	return hdr->saved_state[index];
+}
+
+inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index,
+					u32 value)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
+
+	hdr->saved_state[index] = value;
+}
+
+void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr;
+
+	hdr = fw_dump->tmpl_hdr;
+	fw_dump->tmpl_hdr_size = hdr->size;
+	fw_dump->version = hdr->version;
+	fw_dump->num_entries = hdr->num_entries;
+	fw_dump->offset = hdr->offset;
+
+	hdr->drv_cap_mask = hdr->cap_mask;
+	fw_dump->cap_mask = hdr->cap_mask;
+}
+
+inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
+
+	return hdr->cap_sizes[index];
+}
+
+void qlcnic_83xx_set_sys_info(void *t_hdr, int idx, u32 value)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
+
+	hdr->sys_info[idx] = value;
+}
+
+void qlcnic_83xx_store_cap_mask(void *tmpl_hdr, u32 mask)
+{
+	struct qlcnic_83xx_dump_template_hdr *hdr;
+
+	hdr = tmpl_hdr;
+	hdr->drv_cap_mask = mask;
+}
+
 struct qlcnic_dump_operations {
 	enum qlcnic_minidump_opcode opcode;
 	u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,
@@ -238,11 +339,11 @@ static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,
 static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
 			    struct qlcnic_dump_entry *entry, __le32 *buffer)
 {
+	void *hdr = adapter->ahw->fw_dump.tmpl_hdr;
+	struct __ctrl *ctr = &entry->region.ctrl;
 	int i, k, timeout = 0;
-	u32 addr, data;
+	u32 addr, data, temp;
 	u8 no_ops;
-	struct __ctrl *ctr = &entry->region.ctrl;
-	struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
 
 	addr = ctr->addr;
 	no_ops = ctr->no_ops;
@@ -285,29 +386,42 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
 				}
 				break;
 			case QLCNIC_DUMP_RD_SAVE:
-				if (ctr->index_a)
-					addr = t_hdr->saved_state[ctr->index_a];
+				temp = ctr->index_a;
+				if (temp)
+					addr = qlcnic_get_saved_state(adapter,
+								      hdr,
+								      temp);
 				data = qlcnic_ind_rd(adapter, addr);
-				t_hdr->saved_state[ctr->index_v] = data;
+				qlcnic_set_saved_state(adapter, hdr,
+						       ctr->index_v, data);
 				break;
 			case QLCNIC_DUMP_WRT_SAVED:
-				if (ctr->index_v)
-					data = t_hdr->saved_state[ctr->index_v];
+				temp = ctr->index_v;
+				if (temp)
+					data = qlcnic_get_saved_state(adapter,
+								      hdr,
+								      temp);
 				else
 					data = ctr->val1;
-				if (ctr->index_a)
-					addr = t_hdr->saved_state[ctr->index_a];
+
+				temp = ctr->index_a;
+				if (temp)
+					addr = qlcnic_get_saved_state(adapter,
+								      hdr,
+								      temp);
 				qlcnic_ind_wr(adapter, addr, data);
 				break;
 			case QLCNIC_DUMP_MOD_SAVE_ST:
-				data = t_hdr->saved_state[ctr->index_v];
+				data = qlcnic_get_saved_state(adapter, hdr,
+							      ctr->index_v);
 				data <<= ctr->shl_val;
 				data >>= ctr->shr_val;
 				if (ctr->val2)
 					data &= ctr->val2;
 				data |= ctr->val3;
 				data += ctr->val1;
-				t_hdr->saved_state[ctr->index_v] = data;
+				qlcnic_set_saved_state(adapter, hdr,
+						       ctr->index_v, data);
 				break;
 			default:
 				dev_info(&adapter->pdev->dev,
@@ -544,7 +658,7 @@ out:
 static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter,
 				struct __mem *mem)
 {
-	struct qlcnic_dump_template_hdr *tmpl_hdr;
+	struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
 	struct device *dev = &adapter->pdev->dev;
 	u32 dma_no, dma_base_addr, temp_addr;
 	int i, ret, dma_sts;
@@ -596,7 +710,7 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 	u32 temp, dma_base_addr, size = 0, read_size = 0;
 	struct qlcnic_pex_dma_descriptor *dma_descr;
-	struct qlcnic_dump_template_hdr *tmpl_hdr;
+	struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
 	struct device *dev = &adapter->pdev->dev;
 	dma_addr_t dma_phys_addr;
 	void *dma_buffer;
@@ -938,8 +1052,8 @@ static int
 qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter,
 				       struct qlcnic_cmd_args *cmd)
 {
-	struct qlcnic_dump_template_hdr tmp_hdr;
-	u32 size = sizeof(struct qlcnic_dump_template_hdr) / sizeof(u32);
+	struct qlcnic_83xx_dump_template_hdr tmp_hdr;
+	u32 size = sizeof(tmp_hdr) / sizeof(u32);
 	int ret = 0;
 
 	if (qlcnic_82xx_check(adapter))
@@ -1027,17 +1141,19 @@ free_mem:
 	return err;
 }
 
+#define QLCNIC_TEMPLATE_VERSION (0x20001)
+
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 {
-	int err;
-	u32 temp_size = 0;
-	u32 version, csum, *tmp_buf;
 	struct qlcnic_hardware_context *ahw;
-	struct qlcnic_dump_template_hdr *tmpl_hdr;
+	struct qlcnic_fw_dump *fw_dump;
+	u32 version, csum, *tmp_buf;
 	u8 use_flash_temp = 0;
+	u32 temp_size = 0;
+	int err;
 
 	ahw = adapter->ahw;
-
+	fw_dump = &ahw->fw_dump;
 	err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size,
 					       &use_flash_temp);
 	if (err) {
@@ -1046,11 +1162,11 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 		return -EIO;
 	}
 
-	ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
-	if (!ahw->fw_dump.tmpl_hdr)
+	fw_dump->tmpl_hdr = vzalloc(temp_size);
+	if (!fw_dump->tmpl_hdr)
 		return -ENOMEM;
 
-	tmp_buf = (u32 *)ahw->fw_dump.tmpl_hdr;
+	tmp_buf = (u32 *)fw_dump->tmpl_hdr;
 	if (use_flash_temp)
 		goto flash_temp;
 
@@ -1065,8 +1181,8 @@ flash_temp:
 			dev_err(&adapter->pdev->dev,
 				"Failed to get minidump template header %d\n",
 				err);
-			vfree(ahw->fw_dump.tmpl_hdr);
-			ahw->fw_dump.tmpl_hdr = NULL;
+			vfree(fw_dump->tmpl_hdr);
+			fw_dump->tmpl_hdr = NULL;
 			return -EIO;
 		}
 	}
@@ -1076,21 +1192,22 @@ flash_temp:
 	if (csum) {
 		dev_err(&adapter->pdev->dev,
 			"Template header checksum validation failed\n");
-		vfree(ahw->fw_dump.tmpl_hdr);
-		ahw->fw_dump.tmpl_hdr = NULL;
+		vfree(fw_dump->tmpl_hdr);
+		fw_dump->tmpl_hdr = NULL;
 		return -EIO;
 	}
 
-	tmpl_hdr = ahw->fw_dump.tmpl_hdr;
-	tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask;
+	qlcnic_cache_tmpl_hdr_values(adapter, fw_dump);
+
 	dev_info(&adapter->pdev->dev,
 		 "Default minidump capture mask 0x%x\n",
-		 tmpl_hdr->cap_mask);
+		 fw_dump->cap_mask);
 
-	if ((tmpl_hdr->version & 0xfffff) >= 0x20001)
-		ahw->fw_dump.use_pex_dma = true;
+	if (qlcnic_83xx_check(adapter) &&
+	    (fw_dump->version & 0xfffff) >= QLCNIC_TEMPLATE_VERSION)
+		fw_dump->use_pex_dma = true;
 	else
-		ahw->fw_dump.use_pex_dma = false;
+		fw_dump->use_pex_dma = false;
 
 	qlcnic_enable_fw_dump_state(adapter);
 
@@ -1099,21 +1216,22 @@ flash_temp:
 
 int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 {
-	__le32 *buffer;
-	u32 ocm_window;
-	char mesg[64];
-	char *msg[] = {mesg, NULL};
-	int i, k, ops_cnt, ops_index, dump_size = 0;
-	u32 entry_offset, dump, no_entries, buf_offset = 0;
-	struct qlcnic_dump_entry *entry;
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
-	struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
 	static const struct qlcnic_dump_operations *fw_dump_ops;
+	struct qlcnic_83xx_dump_template_hdr *hdr_83xx;
+	u32 entry_offset, dump, no_entries, buf_offset = 0;
+	int i, k, ops_cnt, ops_index, dump_size = 0;
 	struct device *dev = &adapter->pdev->dev;
 	struct qlcnic_hardware_context *ahw;
-	void *temp_buffer;
+	struct qlcnic_dump_entry *entry;
+	void *temp_buffer, *tmpl_hdr;
+	u32 ocm_window;
+	__le32 *buffer;
+	char mesg[64];
+	char *msg[] = {mesg, NULL};
 
 	ahw = adapter->ahw;
+	tmpl_hdr = fw_dump->tmpl_hdr;
 
 	/* Return if we don't have firmware dump template header */
 	if (!tmpl_hdr)
@@ -1133,8 +1251,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 	netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n");
 	/* Calculate the size for dump data area only */
 	for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
-		if (i & tmpl_hdr->drv_cap_mask)
-			dump_size += tmpl_hdr->cap_sizes[k];
+		if (i & fw_dump->cap_mask)
+			dump_size += qlcnic_get_cap_size(adapter, tmpl_hdr, k);
+
 	if (!dump_size)
 		return -EIO;
 
@@ -1144,10 +1263,10 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 
 	buffer = fw_dump->data;
 	fw_dump->size = dump_size;
-	no_entries = tmpl_hdr->num_entries;
-	entry_offset = tmpl_hdr->offset;
-	tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
-	tmpl_hdr->sys_info[1] = adapter->fw_version;
+	no_entries = fw_dump->num_entries;
+	entry_offset = fw_dump->offset;
+	qlcnic_set_sys_info(adapter, tmpl_hdr, 0, QLCNIC_DRIVER_VERSION);
+	qlcnic_set_sys_info(adapter, tmpl_hdr, 1, adapter->fw_version);
 
 	if (fw_dump->use_pex_dma) {
 		temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE,
@@ -1163,16 +1282,17 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 		ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops);
 		fw_dump_ops = qlcnic_fw_dump_ops;
 	} else {
+		hdr_83xx = tmpl_hdr;
 		ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops);
 		fw_dump_ops = qlcnic_83xx_fw_dump_ops;
-		ocm_window = tmpl_hdr->ocm_wnd_reg[adapter->ahw->pci_func];
-		tmpl_hdr->saved_state[QLC_83XX_OCM_INDEX] = ocm_window;
-		tmpl_hdr->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func;
+		ocm_window = hdr_83xx->ocm_wnd_reg[ahw->pci_func];
+		hdr_83xx->saved_state[QLC_83XX_OCM_INDEX] = ocm_window;
+		hdr_83xx->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func;
 	}
 
 	for (i = 0; i < no_entries; i++) {
-		entry = (void *)tmpl_hdr + entry_offset;
-		if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
+		entry = tmpl_hdr + entry_offset;
+		if (!(entry->hdr.mask & fw_dump->cap_mask)) {
 			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
 			entry_offset += entry->hdr.offset;
 			continue;
@@ -1209,8 +1329,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 
 	fw_dump->clr = 1;
 	snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name);
-	dev_info(dev, "%s: Dump data %d bytes captured, template header size %d bytes\n",
-		 adapter->netdev->name, fw_dump->size, tmpl_hdr->size);
+	netdev_info(adapter->netdev,
+		    "Dump data %d bytes captured, template header size %d bytes\n",
+		    fw_dump->size, fw_dump->tmpl_hdr_size);
 	/* Send a udev event to notify availability of FW dump */
 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg);
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
index 09acf15c3a56..14f748cbf0de 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -13,10 +13,9 @@
 #define QLC_VF_MIN_TX_RATE	100
 #define QLC_VF_MAX_TX_RATE	9999
 #define QLC_MAC_OPCODE_MASK	0x7
-#define QLC_MAC_STAR_ADD	6
-#define QLC_MAC_STAR_DEL	7
 #define QLC_VF_FLOOD_BIT	BIT_16
 #define QLC_FLOOD_MODE		0x5
+#define QLC_SRIOV_ALLOW_VLAN0	BIT_19
 
 static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
 
@@ -337,8 +336,11 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
 		return err;
 
 	cmd.req.arg[1] = 0x4;
-	if (enable)
+	if (enable) {
 		cmd.req.arg[1] |= BIT_16;
+		if (qlcnic_84xx_check(adapter))
+			cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0;
+	}
 
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err)
@@ -1206,13 +1208,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
 	struct qlcnic_vport *vp = vf->vp;
 	u8 op, new_op;
 
-	if (((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_ADD) ||
-	    ((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_DEL)) {
-		netdev_err(adapter->netdev, "MAC + any VLAN filter not allowed from VF %d\n",
-			   vf->pci_func);
-		return -EINVAL;
-	}
-
 	if (!(cmd->req.arg[1] & BIT_8))
 		return -EINVAL;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 3d64113a35af..448d156c3d08 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -350,33 +350,15 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
 	return size;
 }
 
-static u32 qlcnic_get_pci_func_count(struct qlcnic_adapter *adapter)
-{
-	struct qlcnic_hardware_context *ahw = adapter->ahw;
-	u32 count = 0;
-
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
-		return ahw->total_nic_func;
-
-	if (ahw->total_pci_func <= QLC_DEFAULT_VNIC_COUNT)
-		count = QLC_DEFAULT_VNIC_COUNT;
-	else
-		count = ahw->max_vnic_func;
-
-	return count;
-}
-
 int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
 {
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	int i;
 
-	for (i = 0; i < pci_func_count; i++) {
+	for (i = 0; i < adapter->ahw->max_vnic_func; i++) {
 		if (adapter->npars[i].pci_func == pci_func)
 			return i;
 	}
-
-	return -1;
+	return -EINVAL;
 }
 
 static int validate_pm_config(struct qlcnic_adapter *adapter,
@@ -464,23 +446,21 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_pm_func_cfg *pm_cfg;
-	int i, pm_cfg_size;
 	u8 pci_func;
+	u32 count;
+	int i;
 
-	pm_cfg_size = pci_func_count * sizeof(*pm_cfg);
-	if (size != pm_cfg_size)
-		return QL_STATUS_INVALID_PARAM;
-
-	memset(buf, 0, pm_cfg_size);
+	memset(buf, 0, size);
 	pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
-
-	for (i = 0; i < pci_func_count; i++) {
+	count = size / sizeof(struct qlcnic_pm_func_cfg);
+	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
 		pci_func = adapter->npars[i].pci_func;
-		if (!adapter->npars[i].active)
+		if (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;
-
+		}
 		if (!adapter->npars[i].eswitch_status)
 			continue;
 
@@ -494,7 +474,6 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
 static int validate_esw_config(struct qlcnic_adapter *adapter,
 			       struct qlcnic_esw_func_cfg *esw_cfg, int count)
 {
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
 	int i, ret;
 	u32 op_mode;
@@ -507,7 +486,7 @@ static int validate_esw_config(struct qlcnic_adapter *adapter,
 
 	for (i = 0; i < count; i++) {
 		pci_func = esw_cfg[i].pci_func;
-		if (pci_func >= pci_func_count)
+		if (pci_func >= ahw->max_vnic_func)
 			return QL_STATUS_INVALID_PARAM;
 
 		if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
@@ -642,23 +621,21 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_esw_func_cfg *esw_cfg;
-	size_t esw_cfg_size;
-	u8 i, pci_func;
-
-	esw_cfg_size = pci_func_count * sizeof(*esw_cfg);
-	if (size != esw_cfg_size)
-		return QL_STATUS_INVALID_PARAM;
+	u8 pci_func;
+	u32 count;
+	int i;
 
-	memset(buf, 0, esw_cfg_size);
+	memset(buf, 0, size);
 	esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
-
-	for (i = 0; i < pci_func_count; i++) {
+	count = size / sizeof(struct qlcnic_esw_func_cfg);
+	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
 		pci_func = adapter->npars[i].pci_func;
-		if (!adapter->npars[i].active)
+		if (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;
-
+		}
 		if (!adapter->npars[i].eswitch_status)
 			continue;
 
@@ -741,23 +718,24 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_npar_func_cfg *np_cfg;
 	struct qlcnic_info nic_info;
-	size_t np_cfg_size;
 	int i, ret;
-
-	np_cfg_size = pci_func_count * sizeof(*np_cfg);
-	if (size != np_cfg_size)
-		return QL_STATUS_INVALID_PARAM;
+	u32 count;
 
 	memset(&nic_info, 0, sizeof(struct qlcnic_info));
-	memset(buf, 0, np_cfg_size);
+	memset(buf, 0, size);
 	np_cfg = (struct qlcnic_npar_func_cfg *)buf;
 
-	for (i = 0; i < pci_func_count; i++) {
+	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;
@@ -783,7 +761,6 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_esw_statistics port_stats;
 	int ret;
 
@@ -793,7 +770,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
 	if (size != sizeof(struct qlcnic_esw_statistics))
 		return QL_STATUS_INVALID_PARAM;
 
-	if (offset >= pci_func_count)
+	if (offset >= adapter->ahw->max_vnic_func)
 		return QL_STATUS_INVALID_PARAM;
 
 	memset(&port_stats, 0, size);
@@ -884,13 +861,12 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
 
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	int ret;
 
 	if (qlcnic_83xx_check(adapter))
 		return QLC_STATUS_UNSUPPORTED_CMD;
 
-	if (offset >= pci_func_count)
+	if (offset >= adapter->ahw->max_vnic_func)
 		return QL_STATUS_INVALID_PARAM;
 
 	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
@@ -914,17 +890,12 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
 	struct qlcnic_pci_func_cfg *pci_cfg;
 	struct qlcnic_pci_info *pci_info;
-	size_t pci_cfg_sz;
 	int i, ret;
+	u32 count;
 
-	pci_cfg_sz = pci_func_count * sizeof(*pci_cfg);
-	if (size != pci_cfg_sz)
-		return QL_STATUS_INVALID_PARAM;
-
-	pci_info = kcalloc(pci_func_count, sizeof(*pci_info), GFP_KERNEL);
+	pci_info = kcalloc(size, sizeof(*pci_info), GFP_KERNEL);
 	if (!pci_info)
 		return -ENOMEM;
 
@@ -935,7 +906,8 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
 	}
 
 	pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
-	for (i = 0; i < pci_func_count; i++) {
+	count = size / sizeof(struct qlcnic_pci_func_cfg);
+	for (i = 0; i < count; i++) {
 		pci_cfg[i].pci_func = pci_info[i].id;
 		pci_cfg[i].func_type = pci_info[i].type;
 		pci_cfg[i].func_state = 0;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index ce2cfddbed50..adf87d26e68f 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -3331,24 +3331,16 @@ static void ql_enable_msix(struct ql_adapter *qdev)
 		for (i = 0; i < qdev->intr_count; i++)
 			qdev->msi_x_entry[i].entry = i;
 
-		/* Loop to get our vectors.  We start with
-		 * what we want and settle for what we get.
-		 */
-		do {
-			err = pci_enable_msix(qdev->pdev,
-				qdev->msi_x_entry, qdev->intr_count);
-			if (err > 0)
-				qdev->intr_count = err;
-		} while (err > 0);
-
+		err = pci_enable_msix_range(qdev->pdev, qdev->msi_x_entry,
+					    1, qdev->intr_count);
 		if (err < 0) {
 			kfree(qdev->msi_x_entry);
 			qdev->msi_x_entry = NULL;
 			netif_warn(qdev, ifup, qdev->ndev,
 				   "MSI-X Enable failed, trying MSI.\n");
-			qdev->intr_count = 1;
 			qlge_irq_type = MSI_IRQ;
-		} else if (err == 0) {
+		} else {
+			qdev->intr_count = err;
 			set_bit(QL_MSIX_ENABLED, &qdev->flags);
 			netif_info(qdev, ifup, qdev->ndev,
 				   "MSI-X Enabled, got %d vectors.\n",
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 91a67ae8f17b..e9779653cd4c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7118,6 +7118,8 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	mutex_init(&tp->wk.mutex);
+	u64_stats_init(&tp->rx_stats.syncp);
+	u64_stats_init(&tp->tx_stats.syncp);
 
 	/* Get MAC address */
 	for (i = 0; i < ETH_ALEN; i++)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 040cb94e8219..b1e6554f44bc 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1,8 +1,8 @@
 /*  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2013 Renesas Solutions Corp.
- *  Copyright (C) 2013 Cogent Embedded, Inc.
+ *  Copyright (C) 2008-2014 Renesas Solutions Corp.
+ *  Copyright (C) 2013-2014 Cogent Embedded, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -27,6 +27,10 @@
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
 #include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/cache.h>
 #include <linux/io.h>
@@ -2098,8 +2102,8 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 				 skb->len + 2);
 	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
 				      DMA_TO_DEVICE);
-	if (skb->len < ETHERSMALL)
-		txdesc->buffer_length = ETHERSMALL;
+	if (skb->len < ETH_ZLEN)
+		txdesc->buffer_length = ETH_ZLEN;
 	else
 		txdesc->buffer_length = skb->len;
 
@@ -2710,6 +2714,54 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
 	.ndo_change_mtu		= eth_change_mtu,
 };
 
+#ifdef CONFIG_OF
+static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct sh_eth_plat_data *pdata;
+	struct device_node *phy;
+	const char *mac_addr;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	pdata->phy_interface = of_get_phy_mode(np);
+
+	phy = of_parse_phandle(np, "phy-handle", 0);
+	if (of_property_read_u32(phy, "reg", &pdata->phy))
+		return NULL;
+	pdata->phy_irq = irq_of_parse_and_map(phy, 0);
+
+	mac_addr = of_get_mac_address(np);
+	if (mac_addr)
+		memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
+
+	pdata->no_ether_link =
+		of_property_read_bool(np, "renesas,no-ether-link");
+	pdata->ether_link_active_low =
+		of_property_read_bool(np, "renesas,ether-link-active-low");
+
+	return pdata;
+}
+
+static const struct of_device_id sh_eth_match_table[] = {
+	{ .compatible = "renesas,gether-r8a7740", .data = &r8a7740_data },
+	{ .compatible = "renesas,ether-r8a7778", .data = &r8a777x_data },
+	{ .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
+	{ .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
+	{ .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
+	{ .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh_eth_match_table);
+#else
+static inline struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static int sh_eth_drv_probe(struct platform_device *pdev)
 {
 	int ret, devno = 0;
@@ -2763,6 +2815,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
+	if (pdev->dev.of_node)
+		pd = sh_eth_parse_dt(&pdev->dev);
 	if (!pd) {
 		dev_err(&pdev->dev, "no platform data\n");
 		ret = -EINVAL;
@@ -2778,7 +2832,15 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	mdp->ether_link_active_low = pd->ether_link_active_low;
 
 	/* set cpu data */
-	mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
+	if (id) {
+		mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
+	} else	{
+		const struct of_device_id *match;
+
+		match = of_match_device(of_match_ptr(sh_eth_match_table),
+					&pdev->dev);
+		mdp->cd = (struct sh_eth_cpu_data *)match->data;
+	}
 	mdp->reg_offset = sh_eth_get_register_offset(mdp->cd->register_type);
 	sh_eth_set_default_cpu_data(mdp->cd);
 
@@ -2920,6 +2982,7 @@ static struct platform_driver sh_eth_driver = {
 	.driver = {
 		   .name = CARDNAME,
 		   .pm = SH_ETH_PM_OPS,
+		   .of_match_table = of_match_ptr(sh_eth_match_table),
 	},
 };
 
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 6075915b88ec..d55e37cd5fec 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -27,8 +27,7 @@
 #define RX_RING_MIN	64
 #define TX_RING_MAX	1024
 #define RX_RING_MAX	1024
-#define ETHERSMALL		60
-#define PKT_BUF_SZ		1538
+#define PKT_BUF_SZ	1538
 #define SH_ETH_TSU_TIMEOUT_MS	500
 #define SH_ETH_TSU_CAM_ENTRIES	32
 
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 174a92f5fe51..3b397987119d 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -172,8 +172,8 @@ static int efx_ef10_probe(struct efx_nic *efx)
 	struct efx_ef10_nic_data *nic_data;
 	int i, rc;
 
-	/* We can have one VI for each 8K region.  However we need
-	 * multiple TX queues per channel.
+	/* We can have one VI for each 8K region.  However, until we
+	 * use TX option descriptors we need two TX queues per channel.
 	 */
 	efx->max_channels =
 		min_t(unsigned int,
diff --git a/drivers/net/ethernet/sfc/ef10_regs.h b/drivers/net/ethernet/sfc/ef10_regs.h
index 207ac9a1e3de..62a55dde61d5 100644
--- a/drivers/net/ethernet/sfc/ef10_regs.h
+++ b/drivers/net/ethernet/sfc/ef10_regs.h
@@ -227,36 +227,6 @@
 #define	ESF_DZ_RX_KER_BUF_ADDR_LBN 0
 #define	ESF_DZ_RX_KER_BUF_ADDR_WIDTH 48
 
-/* RX_USER_DESC */
-#define	ESF_DZ_RX_USR_RESERVED_LBN 62
-#define	ESF_DZ_RX_USR_RESERVED_WIDTH 2
-#define	ESF_DZ_RX_USR_BYTE_CNT_LBN 48
-#define	ESF_DZ_RX_USR_BYTE_CNT_WIDTH 14
-#define	ESF_DZ_RX_USR_BUF_PAGE_SIZE_LBN 44
-#define	ESF_DZ_RX_USR_BUF_PAGE_SIZE_WIDTH 4
-#define	ESE_DZ_USR_BUF_PAGE_SZ_4MB 10
-#define	ESE_DZ_USR_BUF_PAGE_SZ_1MB 8
-#define	ESE_DZ_USR_BUF_PAGE_SZ_64KB 4
-#define	ESE_DZ_USR_BUF_PAGE_SZ_4KB 0
-#define	ESF_DZ_RX_USR_BUF_ID_OFFSET_LBN 0
-#define	ESF_DZ_RX_USR_BUF_ID_OFFSET_WIDTH 44
-#define	ESF_DZ_RX_USR_4KBPS_BUF_ID_LBN 12
-#define	ESF_DZ_RX_USR_4KBPS_BUF_ID_WIDTH 32
-#define	ESF_DZ_RX_USR_64KBPS_BUF_ID_LBN 16
-#define	ESF_DZ_RX_USR_64KBPS_BUF_ID_WIDTH 28
-#define	ESF_DZ_RX_USR_1MBPS_BUF_ID_LBN 20
-#define	ESF_DZ_RX_USR_1MBPS_BUF_ID_WIDTH 24
-#define	ESF_DZ_RX_USR_4MBPS_BUF_ID_LBN 22
-#define	ESF_DZ_RX_USR_4MBPS_BUF_ID_WIDTH 22
-#define	ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_WIDTH 22
-#define	ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_WIDTH 20
-#define	ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_WIDTH 16
-#define	ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_WIDTH 12
-
 /* TX_CSUM_TSTAMP_DESC */
 #define	ESF_DZ_TX_DESC_IS_OPT_LBN 63
 #define	ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
@@ -338,37 +308,6 @@
 #define	ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
 #define	ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
 
-/* TX_USER_DESC */
-#define	ESF_DZ_TX_USR_TYPE_LBN 63
-#define	ESF_DZ_TX_USR_TYPE_WIDTH 1
-#define	ESF_DZ_TX_USR_CONT_LBN 62
-#define	ESF_DZ_TX_USR_CONT_WIDTH 1
-#define	ESF_DZ_TX_USR_BYTE_CNT_LBN 48
-#define	ESF_DZ_TX_USR_BYTE_CNT_WIDTH 14
-#define	ESF_DZ_TX_USR_BUF_PAGE_SIZE_LBN 44
-#define	ESF_DZ_TX_USR_BUF_PAGE_SIZE_WIDTH 4
-#define	ESE_DZ_USR_BUF_PAGE_SZ_4MB 10
-#define	ESE_DZ_USR_BUF_PAGE_SZ_1MB 8
-#define	ESE_DZ_USR_BUF_PAGE_SZ_64KB 4
-#define	ESE_DZ_USR_BUF_PAGE_SZ_4KB 0
-#define	ESF_DZ_TX_USR_BUF_ID_OFFSET_LBN 0
-#define	ESF_DZ_TX_USR_BUF_ID_OFFSET_WIDTH 44
-#define	ESF_DZ_TX_USR_4KBPS_BUF_ID_LBN 12
-#define	ESF_DZ_TX_USR_4KBPS_BUF_ID_WIDTH 32
-#define	ESF_DZ_TX_USR_64KBPS_BUF_ID_LBN 16
-#define	ESF_DZ_TX_USR_64KBPS_BUF_ID_WIDTH 28
-#define	ESF_DZ_TX_USR_1MBPS_BUF_ID_LBN 20
-#define	ESF_DZ_TX_USR_1MBPS_BUF_ID_WIDTH 24
-#define	ESF_DZ_TX_USR_4MBPS_BUF_ID_LBN 22
-#define	ESF_DZ_TX_USR_4MBPS_BUF_ID_WIDTH 22
-#define	ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_WIDTH 22
-#define	ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_WIDTH 20
-#define	ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_WIDTH 16
-#define	ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_LBN 0
-#define	ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_WIDTH 12
 /*************************************************************************/
 
 /* TX_DESC_UPD_REG: Transmit descriptor update register.
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 83d464347021..d72e0038a740 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -503,8 +503,6 @@ static int efx_probe_channel(struct efx_channel *channel)
 			goto fail;
 	}
 
-	channel->n_rx_frm_trunc = 0;
-
 	return 0;
 
 fail:
@@ -1346,20 +1344,23 @@ static int efx_probe_interrupts(struct efx_nic *efx)
 
 		for (i = 0; i < n_channels; i++)
 			xentries[i].entry = i;
-		rc = pci_enable_msix(efx->pci_dev, xentries, n_channels);
-		if (rc > 0) {
+		rc = pci_enable_msix_range(efx->pci_dev,
+					   xentries, 1, n_channels);
+		if (rc < 0) {
+			/* Fall back to single channel MSI */
+			efx->interrupt_mode = EFX_INT_MODE_MSI;
+			netif_err(efx, drv, efx->net_dev,
+				  "could not enable MSI-X\n");
+		} else if (rc < n_channels) {
 			netif_err(efx, drv, efx->net_dev,
 				  "WARNING: Insufficient MSI-X vectors"
 				  " available (%d < %u).\n", rc, n_channels);
 			netif_err(efx, drv, efx->net_dev,
 				  "WARNING: Performance may be reduced.\n");
-			EFX_BUG_ON_PARANOID(rc >= n_channels);
 			n_channels = rc;
-			rc = pci_enable_msix(efx->pci_dev, xentries,
-					     n_channels);
 		}
 
-		if (rc == 0) {
+		if (rc > 0) {
 			efx->n_channels = n_channels;
 			if (n_channels > extra_channels)
 				n_channels -= extra_channels;
@@ -1375,11 +1376,6 @@ static int efx_probe_interrupts(struct efx_nic *efx)
 			for (i = 0; i < efx->n_channels; i++)
 				efx_get_channel(efx, i)->irq =
 					xentries[i].vector;
-		} else {
-			/* Fall back to single channel MSI */
-			efx->interrupt_mode = EFX_INT_MODE_MSI;
-			netif_err(efx, drv, efx->net_dev,
-				  "could not enable MSI-X\n");
 		}
 	}
 
@@ -2115,7 +2111,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct sockaddr *addr = data;
-	char *new_addr = addr->sa_data;
+	u8 *new_addr = addr->sa_data;
 
 	if (!is_valid_ether_addr(new_addr)) {
 		netif_err(efx, drv, efx->net_dev,
@@ -3273,6 +3269,6 @@ module_exit(efx_exit_module);
 
 MODULE_AUTHOR("Solarflare Communications and "
 	      "Michael Brown <mbrown@fensystems.co.uk>");
-MODULE_DESCRIPTION("Solarflare Communications network driver");
+MODULE_DESCRIPTION("Solarflare network driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, efx_pci_table);
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index dbd7b78fe01c..99032581336f 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -14,7 +14,7 @@
 #include "net_driver.h"
 #include "filter.h"
 
-/* Solarstorm controllers use BAR 0 for I/O space and BAR 2(&3) for memory */
+/* All controllers use BAR 0 for I/O space and BAR 2(&3) for memory */
 #define EFX_MEM_BAR 2
 
 /* TX */
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 229428915aa8..89fcaffd7de2 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -251,6 +251,9 @@ static void efx_fill_test(unsigned int test_index, u8 *strings, u64 *data,
  * @test_index:		Starting index of the test
  * @strings:		Ethtool strings, or %NULL
  * @data:		Ethtool test results, or %NULL
+ *
+ * Fill in a block of loopback self-test entries.  Return new test
+ * index.
  */
 static int efx_fill_loopback_test(struct efx_nic *efx,
 				  struct efx_loopback_self_tests *lb_tests,
@@ -290,6 +293,12 @@ static int efx_fill_loopback_test(struct efx_nic *efx,
  * @tests:		Efx self-test results structure, or %NULL
  * @strings:		Ethtool strings, or %NULL
  * @data:		Ethtool test results, or %NULL
+ *
+ * Get self-test number of strings, strings, and/or test results.
+ * Return number of strings (== number of test results).
+ *
+ * The reason for merging these three functions is to make sure that
+ * they can never be inconsistent.
  */
 static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
 				       struct efx_self_tests *tests,
@@ -444,7 +453,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_self_tests *efx_tests;
-	int already_up;
+	bool already_up;
 	int rc = -ENOMEM;
 
 	efx_tests = kzalloc(sizeof(*efx_tests), GFP_KERNEL);
@@ -452,8 +461,8 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
 		goto fail;
 
 	if (efx->state != STATE_READY) {
-		rc = -EIO;
-		goto fail1;
+		rc = -EBUSY;
+		goto out;
 	}
 
 	netif_info(efx, drv, efx->net_dev, "starting %sline testing\n",
@@ -466,7 +475,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
 		if (rc) {
 			netif_err(efx, drv, efx->net_dev,
 				  "failed opening device.\n");
-			goto fail1;
+			goto out;
 		}
 	}
 
@@ -479,8 +488,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
 		   rc == 0 ? "passed" : "failed",
 		   (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
 
-fail1:
-	/* Fill ethtool results structures */
+out:
 	efx_ethtool_fill_self_tests(efx, efx_tests, NULL, data);
 	kfree(efx_tests);
 fail:
@@ -691,7 +699,6 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
 	pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO);
 }
 
-
 static void efx_ethtool_get_wol(struct net_device *net_dev,
 				struct ethtool_wolinfo *wol)
 {
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 18d6f761f4d0..72652f380243 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -422,7 +422,6 @@ static inline void falcon_irq_ack_a1(struct efx_nic *efx)
 	efx_readd(efx, &reg, FR_AA_WORK_AROUND_BROKEN_PCI_READS);
 }
 
-
 static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
 {
 	struct efx_nic *efx = dev_id;
@@ -467,6 +466,7 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
 		efx_schedule_channel_irq(efx_get_channel(efx, 1));
 	return IRQ_HANDLED;
 }
+
 /**************************************************************************
  *
  * RSS
@@ -1358,6 +1358,7 @@ static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	case 100:   link_speed = 1; break;
 	default:    link_speed = 0; break;
 	}
+
 	/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
 	 * as advertised.  Disable to ensure packets are not
 	 * indefinitely held and TX queue can be flushed at any point
@@ -2868,4 +2869,3 @@ const struct efx_nic_type falcon_b0_nic_type = {
 	.mcdi_max_ver = -1,
 	.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
 };
-
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index f72489a105ca..aa1b169f45ec 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -311,7 +311,6 @@ static inline void efx_farch_push_tx_desc(struct efx_tx_queue *tx_queue,
  */
 void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
 {
-
 	struct efx_tx_buffer *buffer;
 	efx_qword_t *txd;
 	unsigned write_ptr;
@@ -1609,7 +1608,6 @@ irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-
 /* Setup RSS indirection table.
  * This maps from the hash value of the packet to RXQ
  */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index af2b8c59a903..8a400a0595eb 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1323,7 +1323,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
 	return &rx_queue->buffer[index];
 }
 
-
 /**
  * EFX_MAX_FRAME_LEN - calculate maximum frame length
  *
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 79226b19e3c4..32d969e857f7 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -530,4 +530,3 @@ void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *rx_nodesc_drops)
 	efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP);
 	*rx_nodesc_drops -= efx->rx_nodesc_drops_while_down;
 }
-
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index eb75fbd11a01..722344fcd155 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -223,7 +223,6 @@ struct efx_ptp_timeset {
  * @evt_list: List of MC receive events awaiting packets
  * @evt_free_list: List of free events
  * @evt_lock: Lock for manipulating evt_list and evt_free_list
- * @evt_overflow: Boolean indicating that event list has overflowed
  * @rx_evts: Instantiated events (on evt_list and evt_free_list)
  * @workwq: Work queue for processing pending PTP operations
  * @work: Work task
@@ -275,7 +274,6 @@ struct efx_ptp_data {
 	struct list_head evt_list;
 	struct list_head evt_free_list;
 	spinlock_t evt_lock;
-	bool evt_overflow;
 	struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS];
 	struct workqueue_struct *workwq;
 	struct work_struct work;
@@ -768,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
 		return -EAGAIN;
 	}
 
-	/* Convert the NIC time into kernel time. No correction is required-
-	 * this time is the output of a firmware process.
-	 */
-	mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major,
-					  ptp->timeset[last_good].minor, 0);
-
-	/* Calculate delay from actual PPS to last_time */
-	delta = ktime_to_timespec(mc_time);
-	delta.tv_nsec +=
-		last_time->ts_real.tv_nsec -
-		(ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK);
-
-	/* It is possible that the seconds rolled over between taking
+	/* Calculate delay from last good sync (host time) to last_time.
+	 * It is possible that the seconds rolled over between taking
 	 * the start reading and the last value written by the host.  The
 	 * timescales are such that a gap of more than one second is never
-	 * expected.
+	 * expected.  delta is *not* normalised.
 	 */
 	start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS;
 	last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK;
-	if (start_sec != last_sec) {
-		if (((start_sec + 1) & MC_SECOND_MASK) != last_sec) {
-			netif_warn(efx, hw, efx->net_dev,
-				   "PTP bad synchronisation seconds\n");
-			return -EAGAIN;
-		} else {
-			delta.tv_sec = 1;
-		}
-	} else {
-		delta.tv_sec = 0;
+	if (start_sec != last_sec &&
+	    ((start_sec + 1) & MC_SECOND_MASK) != last_sec) {
+		netif_warn(efx, hw, efx->net_dev,
+			   "PTP bad synchronisation seconds\n");
+		return -EAGAIN;
 	}
+	delta.tv_sec = (last_sec - start_sec) & 1;
+	delta.tv_nsec =
+		last_time->ts_real.tv_nsec -
+		(ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK);
+
+	/* Convert the NIC time at last good sync into kernel time.
+	 * No correction is required - this time is the output of a
+	 * firmware process.
+	 */
+	mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major,
+					  ptp->timeset[last_good].minor, 0);
+
+	/* Calculate delay from NIC top of second to last_time */
+	delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec;
 
+	/* Set PPS timestamp to match NIC top of second */
 	ptp->host_time_pps = *last_time;
 	pps_sub_ts(&ptp->host_time_pps, delta);
 
@@ -941,11 +938,6 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
 			}
 		}
 	}
-	/* If the event overflow flag is set and the event list is now empty
-	 * clear the flag to re-enable the overflow warning message.
-	 */
-	if (ptp->evt_overflow && list_empty(&ptp->evt_list))
-		ptp->evt_overflow = false;
 	spin_unlock_bh(&ptp->evt_lock);
 }
 
@@ -989,11 +981,6 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
 			break;
 		}
 	}
-	/* If the event overflow flag is set and the event list is now empty
-	 * clear the flag to re-enable the overflow warning message.
-	 */
-	if (ptp->evt_overflow && list_empty(&ptp->evt_list))
-		ptp->evt_overflow = false;
 	spin_unlock_bh(&ptp->evt_lock);
 
 	return rc;
@@ -1147,7 +1134,6 @@ static int efx_ptp_stop(struct efx_nic *efx)
 	list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) {
 		list_move(cursor, &efx->ptp_data->evt_free_list);
 	}
-	ptp->evt_overflow = false;
 	spin_unlock_bh(&efx->ptp_data->evt_lock);
 
 	return rc;
@@ -1253,7 +1239,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
 	spin_lock_init(&ptp->evt_lock);
 	for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++)
 		list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list);
-	ptp->evt_overflow = false;
 
 	/* Get the NIC PTP attributes and set up time conversions */
 	rc = efx_ptp_get_attributes(efx);
@@ -1380,6 +1365,7 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 	struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb;
 	u8 *match_data_012, *match_data_345;
 	unsigned int version;
+	u8 *data;
 
 	match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS);
 
@@ -1388,7 +1374,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 		if (!pskb_may_pull(skb, PTP_V1_MIN_LENGTH)) {
 			return false;
 		}
-		version = ntohs(*(__be16 *)&skb->data[PTP_V1_VERSION_OFFSET]);
+		data = skb->data;
+		version = ntohs(*(__be16 *)&data[PTP_V1_VERSION_OFFSET]);
 		if (version != PTP_VERSION_V1) {
 			return false;
 		}
@@ -1396,13 +1383,14 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 		/* PTP V1 uses all six bytes of the UUID to match the packet
 		 * to the timestamp
 		 */
-		match_data_012 = skb->data + PTP_V1_UUID_OFFSET;
-		match_data_345 = skb->data + PTP_V1_UUID_OFFSET + 3;
+		match_data_012 = data + PTP_V1_UUID_OFFSET;
+		match_data_345 = data + PTP_V1_UUID_OFFSET + 3;
 	} else {
 		if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) {
 			return false;
 		}
-		version = skb->data[PTP_V2_VERSION_OFFSET];
+		data = skb->data;
+		version = data[PTP_V2_VERSION_OFFSET];
 		if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) {
 			return false;
 		}
@@ -1414,17 +1402,17 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 		 * enhanced mode fixes this issue and uses bytes 0-2
 		 * and byte 5-7 of the UUID.
 		 */
-		match_data_345 = skb->data + PTP_V2_UUID_OFFSET + 5;
+		match_data_345 = data + PTP_V2_UUID_OFFSET + 5;
 		if (ptp->mode == MC_CMD_PTP_MODE_V2) {
-			match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 2;
+			match_data_012 = data + PTP_V2_UUID_OFFSET + 2;
 		} else {
-			match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 0;
+			match_data_012 = data + PTP_V2_UUID_OFFSET + 0;
 			BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED);
 		}
 	}
 
 	/* Does this packet require timestamping? */
-	if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) {
+	if (ntohs(*(__be16 *)&data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) {
 		match->state = PTP_PACKET_STATE_UNMATCHED;
 
 		/* We expect the sequence number to be in the same position in
@@ -1440,8 +1428,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 				   (match_data_345[0] << 24));
 		match->words[1] = (match_data_345[1]         |
 				   (match_data_345[2] << 8)  |
-				   (skb->data[PTP_V1_SEQUENCE_OFFSET +
-					      PTP_V1_SEQUENCE_LENGTH - 1] <<
+				   (data[PTP_V1_SEQUENCE_OFFSET +
+					 PTP_V1_SEQUENCE_LENGTH - 1] <<
 				    16));
 	} else {
 		match->state = PTP_PACKET_STATE_MATCH_UNWANTED;
@@ -1635,13 +1623,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
 		list_add_tail(&evt->link, &ptp->evt_list);
 
 		queue_work(ptp->workwq, &ptp->work);
-	} else if (!ptp->evt_overflow) {
-		/* Log a warning message and set the event overflow flag.
-		 * The message won't be logged again until the event queue
-		 * becomes empty.
-		 */
+	} else if (net_ratelimit()) {
+		/* Log a rate-limited warning message. */
 		netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n");
-		ptp->evt_overflow = true;
 	}
 	spin_unlock_bh(&ptp->evt_lock);
 }
@@ -1668,6 +1652,13 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev)
 	struct efx_ptp_data *ptp = efx->ptp_data;
 	int code = EFX_QWORD_FIELD(*ev, MCDI_EVENT_CODE);
 
+	if (!ptp) {
+		if (net_ratelimit())
+			netif_warn(efx, drv, efx->net_dev,
+				   "Received PTP event but PTP not set up\n");
+		return;
+	}
+
 	if (!ptp->enabled)
 		return;
 
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 75d11fa4eb0a..fa9475300411 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -787,15 +787,6 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
  * Requires TX checksum offload support.
  */
 
-/* Number of bytes inserted at the start of a TSO header buffer,
- * similar to NET_IP_ALIGN.
- */
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-#define TSOH_OFFSET	0
-#else
-#define TSOH_OFFSET	NET_IP_ALIGN
-#endif
-
 #define PTR_DIFF(p1, p2)  ((u8 *)(p1) - (u8 *)(p2))
 
 /**
@@ -882,13 +873,13 @@ static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue,
 	EFX_BUG_ON_PARANOID(buffer->flags);
 	EFX_BUG_ON_PARANOID(buffer->unmap_len);
 
-	if (likely(len <= TSOH_STD_SIZE - TSOH_OFFSET)) {
+	if (likely(len <= TSOH_STD_SIZE - NET_IP_ALIGN)) {
 		unsigned index =
 			(tx_queue->insert_count & tx_queue->ptr_mask) / 2;
 		struct efx_buffer *page_buf =
 			&tx_queue->tsoh_page[index / TSOH_PER_PAGE];
 		unsigned offset =
-			TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + TSOH_OFFSET;
+			TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + NET_IP_ALIGN;
 
 		if (unlikely(!page_buf->addr) &&
 		    efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE,
@@ -901,10 +892,10 @@ static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue,
 	} else {
 		tx_queue->tso_long_headers++;
 
-		buffer->heap_buf = kmalloc(TSOH_OFFSET + len, GFP_ATOMIC);
+		buffer->heap_buf = kmalloc(NET_IP_ALIGN + len, GFP_ATOMIC);
 		if (unlikely(!buffer->heap_buf))
 			return NULL;
-		result = (u8 *)buffer->heap_buf + TSOH_OFFSET;
+		result = (u8 *)buffer->heap_buf + NET_IP_ALIGN;
 		buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_HEAP;
 	}
 
@@ -1011,7 +1002,7 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
 static int tso_start(struct tso_state *st, struct efx_nic *efx,
 		     const struct sk_buff *skb)
 {
-	bool use_options = efx_nic_rev(efx) >= EFX_REV_HUNT_A0;
+	bool use_opt_desc = efx_nic_rev(efx) >= EFX_REV_HUNT_A0;
 	struct device *dma_dev = &efx->pci_dev->dev;
 	unsigned int header_len, in_len;
 	dma_addr_t dma_addr;
@@ -1037,7 +1028,7 @@ static int tso_start(struct tso_state *st, struct efx_nic *efx,
 
 	st->out_len = skb->len - header_len;
 
-	if (!use_options) {
+	if (!use_opt_desc) {
 		st->header_unmap_len = 0;
 
 		if (likely(in_len == 0)) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a2e7d2c96e36..078ad0ec8593 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1705,7 +1705,7 @@ static int stmmac_open(struct net_device *dev)
 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
 
-	alloc_dma_desc_resources(priv);
+	ret = alloc_dma_desc_resources(priv);
 	if (ret < 0) {
 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
 		goto dma_desc_error;
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 8e2266e1f260..79606f47a08e 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9041,7 +9041,7 @@ static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
 	struct msix_entry msi_vec[NIU_NUM_LDG];
 	struct niu_parent *parent = np->parent;
 	struct pci_dev *pdev = np->pdev;
-	int i, num_irqs, err;
+	int i, num_irqs;
 	u8 first_ldg;
 
 	first_ldg = (NIU_NUM_LDG / parent->num_ports) * np->port;
@@ -9053,21 +9053,16 @@ static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
 		    (np->port == 0 ? 3 : 1));
 	BUG_ON(num_irqs > (NIU_NUM_LDG / parent->num_ports));
 
-retry:
 	for (i = 0; i < num_irqs; i++) {
 		msi_vec[i].vector = 0;
 		msi_vec[i].entry = i;
 	}
 
-	err = pci_enable_msix(pdev, msi_vec, num_irqs);
-	if (err < 0) {
+	num_irqs = pci_enable_msix_range(pdev, msi_vec, 1, num_irqs);
+	if (num_irqs < 0) {
 		np->flags &= ~NIU_FLAGS_MSIX;
 		return;
 	}
-	if (err > 0) {
-		num_irqs = err;
-		goto retry;
-	}
 
 	np->flags |= NIU_FLAGS_MSIX;
 	for (i = 0; i < num_irqs; i++)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 651087b5c8da..53f85dd3bbad 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1164,11 +1164,17 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 
 static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
+	u32 slave_port;
+
+	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+
 	if (!slave->phy)
 		return;
 	phy_stop(slave->phy);
 	phy_disconnect(slave->phy);
 	slave->phy = NULL;
+	cpsw_ale_control_set(priv->ale, slave_port,
+			     ALE_PORT_STATE, ALE_PORT_STATE_DISABLE);
 }
 
 static int cpsw_ndo_open(struct net_device *ndev)
@@ -1471,7 +1477,6 @@ static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
 static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
 	struct cpsw_priv *priv = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(req);
 	int slave_no = cpsw_slave_index(priv);
 
 	if (!netif_running(dev))
@@ -1484,14 +1489,11 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 	case SIOCGHWTSTAMP:
 		return cpsw_hwtstamp_get(dev, req);
 #endif
-	case SIOCGMIIPHY:
-		data->phy_id = priv->slaves[slave_no].phy->addr;
-		break;
-	default:
-		return -ENOTSUPP;
 	}
 
-	return 0;
+	if (!priv->slaves[slave_no].phy)
+		return -EOPNOTSUPP;
+	return phy_mii_ioctl(priv->slaves[slave_no].phy, req, cmd);
 }
 
 static void cpsw_ndo_tx_timeout(struct net_device *ndev)
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 0df36c6ec7f4..104d46f37969 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -641,11 +641,10 @@ static int w5100_hw_probe(struct platform_device *pdev)
 	if (!mem)
 		return -ENXIO;
 	mem_size = resource_size(mem);
-	if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size, name))
-		return -EBUSY;
-	priv->base = devm_ioremap(&pdev->dev, mem->start, mem_size);
-	if (!priv->base)
-		return -EBUSY;
+
+	priv->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
 
 	spin_lock_init(&priv->reg_lock);
 	priv->indirect = mem_size < W5100_BUS_DIRECT_SIZE;
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 71c27b3292f1..1f33c4c86c20 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -561,11 +561,10 @@ static int w5300_hw_probe(struct platform_device *pdev)
 	if (!mem)
 		return -ENXIO;
 	mem_size = resource_size(mem);
-	if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size, name))
-		return -EBUSY;
-	priv->base = devm_ioremap(&pdev->dev, mem->start, mem_size);
-	if (!priv->base)
-		return -EBUSY;
+
+	priv->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
 
 	spin_lock_init(&priv->reg_lock);
 	priv->indirect = mem_size < W5300_BUS_DIRECT_SIZE;
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 7b594ce3f21d..39fc230f5c20 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -139,6 +139,8 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
 
 #define NVSP_PROTOCOL_VERSION_1		2
 #define NVSP_PROTOCOL_VERSION_2		0x30002
+#define NVSP_PROTOCOL_VERSION_4		0x40000
+#define NVSP_PROTOCOL_VERSION_5		0x50000
 
 enum {
 	NVSP_MSG_TYPE_NONE = 0,
@@ -193,6 +195,23 @@ enum {
 
 	NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE,
 	NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+	NVSP_MSG2_MAX = NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+	/* Version 4 messages */
+	NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION,
+	NVSP_MSG4_TYPE_SWITCH_DATA_PATH,
+	NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+	NVSP_MSG4_MAX = NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+	/* Version 5 messages */
+	NVSP_MSG5_TYPE_OID_QUERY_EX,
+	NVSP_MSG5_TYPE_OID_QUERY_EX_COMP,
+	NVSP_MSG5_TYPE_SUBCHANNEL,
+	NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
+
+	NVSP_MSG5_MAX = NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
 };
 
 enum {
@@ -447,10 +466,44 @@ union nvsp_2_message_uber {
 	struct nvsp_2_free_rxbuf free_rxbuf;
 } __packed;
 
+enum nvsp_subchannel_operation {
+	NVSP_SUBCHANNEL_NONE = 0,
+	NVSP_SUBCHANNEL_ALLOCATE,
+	NVSP_SUBCHANNEL_MAX
+};
+
+struct nvsp_5_subchannel_request {
+	u32 op;
+	u32 num_subchannels;
+} __packed;
+
+struct nvsp_5_subchannel_complete {
+	u32 status;
+	u32 num_subchannels; /* Actual number of subchannels allocated */
+} __packed;
+
+struct nvsp_5_send_indirect_table {
+	/* The number of entries in the send indirection table */
+	u32 count;
+
+	/* The offset of the send indireciton table from top of this struct.
+	 * The send indirection table tells which channel to put the send
+	 * traffic on. Each entry is a channel number.
+	 */
+	u32 offset;
+} __packed;
+
+union nvsp_5_message_uber {
+	struct nvsp_5_subchannel_request subchn_req;
+	struct nvsp_5_subchannel_complete subchn_comp;
+	struct nvsp_5_send_indirect_table send_table;
+} __packed;
+
 union nvsp_all_messages {
 	union nvsp_message_init_uber init_msg;
 	union nvsp_1_message_uber v1_msg;
 	union nvsp_2_message_uber v2_msg;
+	union nvsp_5_message_uber v5_msg;
 } __packed;
 
 /* ALL Messages */
@@ -506,6 +559,8 @@ struct netvsc_device {
 
 	/* Holds rndis device info */
 	void *extension;
+	/* The recive buffer for this device */
+	unsigned char cb_buffer[NETVSC_PACKET_SIZE];
 };
 
 /* NdisInitialize message */
@@ -846,12 +901,6 @@ struct rndis_message {
 };
 
 
-struct rndis_filter_packet {
-	void *completion_ctx;
-	void (*completion)(void *context);
-	struct rndis_message msg;
-};
-
 /* Handy macros */
 
 /* get the size of an RNDIS message. Pass in the message type, */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 03a2c6e17158..1a0280dcba7e 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -290,7 +290,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
 	    NVSP_STAT_SUCCESS)
 		return -EINVAL;
 
-	if (nvsp_ver != NVSP_PROTOCOL_VERSION_2)
+	if (nvsp_ver == NVSP_PROTOCOL_VERSION_1)
 		return 0;
 
 	/* NVSPv2 only: Send NDIS config */
@@ -314,6 +314,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
 	struct nvsp_message *init_packet;
 	int ndis_version;
 	struct net_device *ndev;
+	u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
+		NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
+	int i, num_ver = 4; /* number of different NVSP versions */
 
 	net_device = get_outbound_net_device(device);
 	if (!net_device)
@@ -323,13 +326,14 @@ static int netvsc_connect_vsp(struct hv_device *device)
 	init_packet = &net_device->channel_init_pkt;
 
 	/* Negotiate the latest NVSP protocol supported */
-	if (negotiate_nvsp_ver(device, net_device, init_packet,
-			       NVSP_PROTOCOL_VERSION_2) == 0) {
-		net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2;
-	} else if (negotiate_nvsp_ver(device, net_device, init_packet,
-				    NVSP_PROTOCOL_VERSION_1) == 0) {
-		net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1;
-	} else {
+	for (i = num_ver - 1; i >= 0; i--)
+		if (negotiate_nvsp_ver(device, net_device, init_packet,
+				       ver_list[i])  == 0) {
+			net_device->nvsp_version = ver_list[i];
+			break;
+		}
+
+	if (i < 0) {
 		ret = -EPROTO;
 		goto cleanup;
 	}
@@ -339,7 +343,10 @@ static int netvsc_connect_vsp(struct hv_device *device)
 	/* Send the ndis version */
 	memset(init_packet, 0, sizeof(struct nvsp_message));
 
-	ndis_version = 0x00050001;
+	if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
+		ndis_version = 0x00050001;
+	else
+		ndis_version = 0x0006001e;
 
 	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
 	init_packet->msg.v1_msg.
@@ -432,17 +439,14 @@ static inline u32 hv_ringbuf_avail_percent(
 	return avail_write * 100 / ring_info->ring_datasize;
 }
 
-static void netvsc_send_completion(struct hv_device *device,
+static void netvsc_send_completion(struct netvsc_device *net_device,
+				   struct hv_device *device,
 				   struct vmpacket_descriptor *packet)
 {
-	struct netvsc_device *net_device;
 	struct nvsp_message *nvsp_packet;
 	struct hv_netvsc_packet *nvsc_packet;
 	struct net_device *ndev;
 
-	net_device = get_inbound_net_device(device);
-	if (!net_device)
-		return;
 	ndev = net_device->ndev;
 
 	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
@@ -561,13 +565,13 @@ int netvsc_send(struct hv_device *device,
 }
 
 static void netvsc_send_recv_completion(struct hv_device *device,
+					struct netvsc_device *net_device,
 					u64 transaction_id, u32 status)
 {
 	struct nvsp_message recvcompMessage;
 	int retries = 0;
 	int ret;
 	struct net_device *ndev;
-	struct netvsc_device *net_device = hv_get_drvdata(device);
 
 	ndev = net_device->ndev;
 
@@ -653,14 +657,15 @@ static void netvsc_receive_completion(void *context)
 
 	/* Send a receive completion for the xfer page packet */
 	if (fsend_receive_comp)
-		netvsc_send_recv_completion(device, transaction_id, status);
+		netvsc_send_recv_completion(device, net_device, transaction_id,
+					status);
 
 }
 
-static void netvsc_receive(struct hv_device *device,
-			    struct vmpacket_descriptor *packet)
+static void netvsc_receive(struct netvsc_device *net_device,
+			struct hv_device *device,
+			struct vmpacket_descriptor *packet)
 {
-	struct netvsc_device *net_device;
 	struct vmtransfer_page_packet_header *vmxferpage_packet;
 	struct nvsp_message *nvsp_packet;
 	struct hv_netvsc_packet *netvsc_packet = NULL;
@@ -673,9 +678,6 @@ static void netvsc_receive(struct hv_device *device,
 
 	LIST_HEAD(listHead);
 
-	net_device = get_inbound_net_device(device);
-	if (!net_device)
-		return;
 	ndev = net_device->ndev;
 
 	/*
@@ -741,7 +743,7 @@ static void netvsc_receive(struct hv_device *device,
 		spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
 				       flags);
 
-		netvsc_send_recv_completion(device,
+		netvsc_send_recv_completion(device, net_device,
 					    vmxferpage_packet->d.trans_id,
 					    NVSP_STAT_FAIL);
 
@@ -800,22 +802,16 @@ static void netvsc_channel_cb(void *context)
 	struct netvsc_device *net_device;
 	u32 bytes_recvd;
 	u64 request_id;
-	unsigned char *packet;
 	struct vmpacket_descriptor *desc;
 	unsigned char *buffer;
 	int bufferlen = NETVSC_PACKET_SIZE;
 	struct net_device *ndev;
 
-	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
-			 GFP_ATOMIC);
-	if (!packet)
-		return;
-	buffer = packet;
-
 	net_device = get_inbound_net_device(device);
 	if (!net_device)
-		goto out;
+		return;
 	ndev = net_device->ndev;
+	buffer = net_device->cb_buffer;
 
 	do {
 		ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
@@ -825,11 +821,13 @@ static void netvsc_channel_cb(void *context)
 				desc = (struct vmpacket_descriptor *)buffer;
 				switch (desc->type) {
 				case VM_PKT_COMP:
-					netvsc_send_completion(device, desc);
+					netvsc_send_completion(net_device,
+								device, desc);
 					break;
 
 				case VM_PKT_DATA_USING_XFER_PAGES:
-					netvsc_receive(device, desc);
+					netvsc_receive(net_device,
+							device, desc);
 					break;
 
 				default:
@@ -841,23 +839,16 @@ static void netvsc_channel_cb(void *context)
 					break;
 				}
 
-				/* reset */
-				if (bufferlen > NETVSC_PACKET_SIZE) {
-					kfree(buffer);
-					buffer = packet;
-					bufferlen = NETVSC_PACKET_SIZE;
-				}
 			} else {
-				/* reset */
-				if (bufferlen > NETVSC_PACKET_SIZE) {
-					kfree(buffer);
-					buffer = packet;
-					bufferlen = NETVSC_PACKET_SIZE;
-				}
-
+				/*
+				 * We are done for this pass.
+				 */
 				break;
 			}
+
 		} else if (ret == -ENOBUFS) {
+			if (bufferlen > NETVSC_PACKET_SIZE)
+				kfree(buffer);
 			/* Handle large packet */
 			buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
 			if (buffer == NULL) {
@@ -872,8 +863,8 @@ static void netvsc_channel_cb(void *context)
 		}
 	} while (1);
 
-out:
-	kfree(buffer);
+	if (bufferlen > NETVSC_PACKET_SIZE)
+		kfree(buffer);
 	return;
 }
 
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 7141a1937360..9ef6be90a81c 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -155,7 +155,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 	/* Allocate a netvsc packet based on # of frags. */
 	packet = kzalloc(sizeof(struct hv_netvsc_packet) +
 			 (num_pages * sizeof(struct hv_page_buffer)) +
-			 sizeof(struct rndis_filter_packet) +
+			 sizeof(struct rndis_message) +
 			 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
 	if (!packet) {
 		/* out of memory, drop packet */
@@ -327,7 +327,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
 	if (nvdev == NULL || nvdev->destroy)
 		return -ENODEV;
 
-	if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
+	if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
 		limit = NETVSC_MTU;
 
 	if (mtu < 68 || mtu > limit)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 1084e5de3ceb..f0cc8ef21e1c 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -58,9 +58,6 @@ struct rndis_request {
 	u8 request_ext[RNDIS_EXT_LEN];
 };
 
-static void rndis_filter_send_completion(void *ctx);
-
-
 static struct rndis_device *get_rndis_device(void)
 {
 	struct rndis_device *device;
@@ -277,7 +274,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
 				"rndis response buffer overflow "
 				"detected (size %u max %zu)\n",
 				resp->msg_len,
-				sizeof(struct rndis_filter_packet));
+				sizeof(struct rndis_message));
 
 			if (resp->ndis_msg_type ==
 			    RNDIS_MSG_RESET_C) {
@@ -898,17 +895,14 @@ int rndis_filter_close(struct hv_device *dev)
 int rndis_filter_send(struct hv_device *dev,
 			     struct hv_netvsc_packet *pkt)
 {
-	int ret;
-	struct rndis_filter_packet *filter_pkt;
 	struct rndis_message *rndis_msg;
 	struct rndis_packet *rndis_pkt;
 	u32 rndis_msg_size;
 	bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT;
 
 	/* Add the rndis header */
-	filter_pkt = (struct rndis_filter_packet *)pkt->extension;
+	rndis_msg = (struct rndis_message *)pkt->extension;
 
-	rndis_msg = &filter_pkt->msg;
 	rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
 	if (isvlan)
 		rndis_msg_size += NDIS_VLAN_PPI_SIZE;
@@ -961,34 +955,5 @@ int rndis_filter_send(struct hv_device *dev,
 		pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len;
 	}
 
-	/* Save the packet send completion and context */
-	filter_pkt->completion = pkt->completion.send.send_completion;
-	filter_pkt->completion_ctx =
-				pkt->completion.send.send_completion_ctx;
-
-	/* Use ours */
-	pkt->completion.send.send_completion = rndis_filter_send_completion;
-	pkt->completion.send.send_completion_ctx = filter_pkt;
-
-	ret = netvsc_send(dev, pkt);
-	if (ret != 0) {
-		/*
-		 * Reset the completion to originals to allow retries from
-		 * above
-		 */
-		pkt->completion.send.send_completion =
-				filter_pkt->completion;
-		pkt->completion.send.send_completion_ctx =
-				filter_pkt->completion_ctx;
-	}
-
-	return ret;
-}
-
-static void rndis_filter_send_completion(void *ctx)
-{
-	struct rndis_filter_packet *filter_pkt = ctx;
-
-	/* Pass it back to the original handler */
-	filter_pkt->completion(filter_pkt->completion_ctx);
+	return netvsc_send(dev, pkt);
 }
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index ab31544bc254..03e24c560b2e 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -37,7 +37,6 @@
 
 struct at86rf230_local {
 	struct spi_device *spi;
-	int rstn, slp_tr, dig2;
 
 	u8 part;
 	u8 vers;
@@ -53,8 +52,16 @@ struct at86rf230_local {
 	spinlock_t lock;
 	bool irq_busy;
 	bool is_tx;
+	bool tx_aret;
+
+	int rssi_base_val;
 };
 
+static bool is_rf212(struct at86rf230_local *local)
+{
+	return local->part == 7;
+}
+
 #define	RG_TRX_STATUS	(0x01)
 #define	SR_TRX_STATUS		0x01, 0x1f, 0
 #define	SR_RESERVED_01_3	0x01, 0x20, 5
@@ -100,7 +107,10 @@ struct at86rf230_local {
 #define	SR_SFD_VALUE		0x0b, 0xff, 0
 #define	RG_TRX_CTRL_2	(0x0c)
 #define	SR_OQPSK_DATA_RATE	0x0c, 0x03, 0
-#define	SR_RESERVED_0c_2	0x0c, 0x7c, 2
+#define	SR_SUB_MODE		0x0c, 0x04, 2
+#define	SR_BPSK_QPSK		0x0c, 0x08, 3
+#define	SR_OQPSK_SUB1_RC_EN	0x0c, 0x10, 4
+#define	SR_RESERVED_0c_5	0x0c, 0x60, 5
 #define	SR_RX_SAFE_MODE		0x0c, 0x80, 7
 #define	RG_ANT_DIV	(0x0d)
 #define	SR_ANT_CTRL		0x0d, 0x03, 0
@@ -145,7 +155,7 @@ struct at86rf230_local {
 #define	SR_RESERVED_17_5	0x17, 0x08, 3
 #define	SR_AACK_UPLD_RES_FT	0x17, 0x10, 4
 #define	SR_AACK_FLTR_RES_FT	0x17, 0x20, 5
-#define	SR_RESERVED_17_2	0x17, 0x40, 6
+#define	SR_CSMA_LBT_MODE	0x17, 0x40, 6
 #define	SR_RESERVED_17_1	0x17, 0x80, 7
 #define	RG_FTN_CTRL	(0x18)
 #define	SR_RESERVED_18_2	0x18, 0x7f, 0
@@ -244,6 +254,57 @@ struct at86rf230_local {
 #define STATE_TRANSITION_IN_PROGRESS 0x1F
 
 static int
+__at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
+		u8 *version)
+{
+	u8 data[4];
+	u8 *buf = kmalloc(2, GFP_KERNEL);
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer = {
+		.len	= 2,
+		.tx_buf	= buf,
+		.rx_buf	= buf,
+	};
+	u8 reg;
+
+	if (!buf)
+		return -ENOMEM;
+
+	for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) {
+		buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
+		buf[1] = 0xff;
+		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
+		spi_message_init(&msg);
+		spi_message_add_tail(&xfer, &msg);
+
+		status = spi_sync(spi, &msg);
+		dev_vdbg(&spi->dev, "status = %d\n", status);
+		if (msg.status)
+			status = msg.status;
+
+		dev_vdbg(&spi->dev, "status = %d\n", status);
+		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
+		dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]);
+
+		if (status == 0)
+			data[reg - RG_PART_NUM] = buf[1];
+		else
+			break;
+	}
+
+	if (status == 0) {
+		*part = data[0];
+		*version = data[1];
+		*man_id = (data[3] << 8) | data[2];
+	}
+
+	kfree(buf);
+
+	return status;
+}
+
+static int
 __at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
 {
 	u8 *buf = lp->buf;
@@ -489,7 +550,9 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
 	} while (val == STATE_TRANSITION_IN_PROGRESS);
 
 
-	if (val == desired_status)
+	if (val == desired_status ||
+	    (desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
+	    (desired_status == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK))
 		return 0;
 
 	pr_err("unexpected state change: %d, asked for %d\n", val, state);
@@ -510,7 +573,11 @@ at86rf230_start(struct ieee802154_dev *dev)
 	if (rc)
 		return rc;
 
-	return at86rf230_state(dev, STATE_RX_ON);
+	rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
+	if (rc)
+		return rc;
+
+	return at86rf230_state(dev, STATE_RX_AACK_ON);
 }
 
 static void
@@ -520,6 +587,39 @@ at86rf230_stop(struct ieee802154_dev *dev)
 }
 
 static int
+at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
+{
+	lp->rssi_base_val = -91;
+
+	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+}
+
+static int
+at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
+{
+	int rc;
+
+	if (channel == 0)
+		rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 0);
+	else
+		rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 1);
+	if (rc < 0)
+		return rc;
+
+	if (page == 0) {
+		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
+		lp->rssi_base_val = -100;
+	} else {
+		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
+		lp->rssi_base_val = -98;
+	}
+	if (rc < 0)
+		return rc;
+
+	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+}
+
+static int
 at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 {
 	struct at86rf230_local *lp = dev->priv;
@@ -527,14 +627,22 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 
 	might_sleep();
 
-	if (page != 0 || channel < 11 || channel > 26) {
+	if (page < 0 || page > 31 ||
+	    !(lp->dev->phy->channels_supported[page] & BIT(channel))) {
 		WARN_ON(1);
 		return -EINVAL;
 	}
 
-	rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+	if (is_rf212(lp))
+		rc = at86rf212_set_channel(lp, page, channel);
+	else
+		rc = at86rf230_set_channel(lp, page, channel);
+	if (rc < 0)
+		return rc;
+
 	msleep(1); /* Wait for PLL */
 	dev->phy->current_channel = channel;
+	dev->phy->current_page = page;
 
 	return 0;
 }
@@ -568,6 +676,12 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
 	if (rc)
 		goto err_rx;
 
+	if (lp->tx_aret) {
+		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
+		if (rc)
+			goto err_rx;
+	}
+
 	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
 	if (rc)
 		goto err_rx;
@@ -668,6 +782,93 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
 	return 0;
 }
 
+static int
+at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	/* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five
+	 * bits decrease power in 1dB steps. 0x60 represents extra PA gain of
+	 * 0dB.
+	 * thus, supported values for db range from -26 to 5, for 31dB of
+	 * reduction to 0dB of reduction.
+	 */
+	if (db > 5 || db < -26)
+		return -EINVAL;
+
+	db = -(db - 5);
+
+	return __at86rf230_write(lp, RG_PHY_TX_PWR, 0x60 | db);
+}
+
+static int
+at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
+}
+
+static int
+at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
+}
+
+static int
+at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int desens_steps;
+
+	if (level < lp->rssi_base_val || level > 30)
+		return -EINVAL;
+
+	desens_steps = (level - lp->rssi_base_val) * 100 / 207;
+
+	return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
+}
+
+static int
+at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
+			  u8 retries)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int rc;
+
+	if (min_be > max_be || max_be > 8 || retries > 5)
+		return -EINVAL;
+
+	rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be);
+	if (rc)
+		return rc;
+
+	rc = at86rf230_write_subreg(lp, SR_MAX_BE, max_be);
+	if (rc)
+		return rc;
+
+	return at86rf230_write_subreg(lp, SR_MAX_CSMA_RETRIES, max_be);
+}
+
+static int
+at86rf212_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int rc = 0;
+
+	if (retries < -1 || retries > 15)
+		return -EINVAL;
+
+	lp->tx_aret = retries >= 0;
+
+	if (retries >= 0)
+		rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries);
+
+	return rc;
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -678,6 +879,22 @@ static struct ieee802154_ops at86rf230_ops = {
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
 };
 
+static struct ieee802154_ops at86rf212_ops = {
+	.owner = THIS_MODULE,
+	.xmit = at86rf230_xmit,
+	.ed = at86rf230_ed,
+	.set_channel = at86rf230_channel,
+	.start = at86rf230_start,
+	.stop = at86rf230_stop,
+	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+	.set_txpower = at86rf212_set_txpower,
+	.set_lbt = at86rf212_set_lbt,
+	.set_cca_mode = at86rf212_set_cca_mode,
+	.set_cca_ed_level = at86rf212_set_cca_ed_level,
+	.set_csma_params = at86rf212_set_csma_params,
+	.set_frame_retries = at86rf212_set_frame_retries,
+};
+
 static void at86rf230_irqwork(struct work_struct *work)
 {
 	struct at86rf230_local *lp =
@@ -752,22 +969,15 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data;
 	int rc, irq_pol;
 	u8 status;
+	u8 csma_seed[2];
 
 	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
 	if (rc)
 		return rc;
 
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	if (status == STATE_P_ON) {
-		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF);
-		if (rc)
-			return rc;
-		msleep(1);
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-		if (rc)
-			return rc;
-		dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	}
+	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
+	if (rc)
+		return rc;
 
 	/* configure irq polarity, defaults to high active */
 	if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
@@ -783,6 +993,14 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	if (rc)
 		return rc;
 
+	get_random_bytes(csma_seed, ARRAY_SIZE(csma_seed));
+	rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_0, csma_seed[0]);
+	if (rc)
+		return rc;
+	rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_1, csma_seed[1]);
+	if (rc)
+		return rc;
+
 	/* CLKM changes are applied immediately */
 	rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
 	if (rc)
@@ -795,16 +1013,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	/* Wait the next SLEEP cycle */
 	msleep(100);
 
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
-	if (rc)
-		return rc;
-	msleep(1);
-
-	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-	if (rc)
-		return rc;
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-
 	rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
 	if (rc)
 		return rc;
@@ -824,26 +1032,18 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	return 0;
 }
 
-static void at86rf230_fill_data(struct spi_device *spi)
-{
-	struct at86rf230_local *lp = spi_get_drvdata(spi);
-	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
-
-	lp->rstn = pdata->rstn;
-	lp->slp_tr = pdata->slp_tr;
-	lp->dig2 = pdata->dig2;
-}
-
 static int at86rf230_probe(struct spi_device *spi)
 {
 	struct at86rf230_platform_data *pdata;
 	struct ieee802154_dev *dev;
 	struct at86rf230_local *lp;
-	u8 man_id_0, man_id_1, status;
+	u16 man_id = 0;
+	u8 part = 0, version = 0, status;
 	irq_handler_t irq_handler;
 	work_func_t irq_worker;
-	int rc, supported = 0;
+	int rc;
 	const char *chip;
+	struct ieee802154_ops *ops = NULL;
 
 	if (!spi->irq) {
 		dev_err(&spi->dev, "no IRQ specified\n");
@@ -856,116 +1056,117 @@ static int at86rf230_probe(struct spi_device *spi)
 		return -EINVAL;
 	}
 
-	dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
-	if (!dev)
-		return -ENOMEM;
-
-	lp = dev->priv;
-	lp->dev = dev;
-
-	lp->spi = spi;
-
-	dev->parent = &spi->dev;
-	dev->extra_tx_headroom = 0;
-	/* We do support only 2.4 Ghz */
-	dev->phy->channels_supported[0] = 0x7FFF800;
-	dev->flags = IEEE802154_HW_OMIT_CKSUM;
-
-	if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		irq_worker = at86rf230_irqwork;
-		irq_handler = at86rf230_isr;
-	} else {
-		irq_worker = at86rf230_irqwork_level;
-		irq_handler = at86rf230_isr_level;
-	}
-
-	mutex_init(&lp->bmux);
-	INIT_WORK(&lp->irqwork, irq_worker);
-	spin_lock_init(&lp->lock);
-	init_completion(&lp->tx_complete);
-
-	spi_set_drvdata(spi, lp);
-
-	at86rf230_fill_data(spi);
-
-	rc = gpio_request(lp->rstn, "rstn");
+	rc = gpio_request(pdata->rstn, "rstn");
 	if (rc)
-		goto err_rstn;
+		return rc;
 
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_request(lp->slp_tr, "slp_tr");
+	if (gpio_is_valid(pdata->slp_tr)) {
+		rc = gpio_request(pdata->slp_tr, "slp_tr");
 		if (rc)
 			goto err_slp_tr;
 	}
 
-	rc = gpio_direction_output(lp->rstn, 1);
+	rc = gpio_direction_output(pdata->rstn, 1);
 	if (rc)
 		goto err_gpio_dir;
 
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_direction_output(lp->slp_tr, 0);
+	if (gpio_is_valid(pdata->slp_tr)) {
+		rc = gpio_direction_output(pdata->slp_tr, 0);
 		if (rc)
 			goto err_gpio_dir;
 	}
 
 	/* Reset */
 	msleep(1);
-	gpio_set_value(lp->rstn, 0);
+	gpio_set_value(pdata->rstn, 0);
 	msleep(1);
-	gpio_set_value(lp->rstn, 1);
+	gpio_set_value(pdata->rstn, 1);
 	msleep(1);
 
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
-	if (rc)
-		goto err_gpio_dir;
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
-	if (rc)
+	rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
+	if (rc < 0)
 		goto err_gpio_dir;
 
-	if (man_id_1 != 0x00 || man_id_0 != 0x1f) {
+	if (man_id != 0x001f) {
 		dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
-			man_id_1, man_id_0);
+			man_id >> 8, man_id & 0xFF);
 		rc = -EINVAL;
 		goto err_gpio_dir;
 	}
 
-	rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part);
-	if (rc)
-		goto err_gpio_dir;
-
-	rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
-	if (rc)
-		goto err_gpio_dir;
-
-	switch (lp->part) {
+	switch (part) {
 	case 2:
 		chip = "at86rf230";
-		/* supported = 1;  FIXME: should be easy to support; */
+		/* FIXME: should be easy to support; */
 		break;
 	case 3:
 		chip = "at86rf231";
-		supported = 1;
+		ops = &at86rf230_ops;
+		break;
+	case 7:
+		chip = "at86rf212";
+		if (version == 1)
+			ops = &at86rf212_ops;
 		break;
 	default:
 		chip = "UNKNOWN";
 		break;
 	}
 
-	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers);
-	if (!supported) {
+	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
+	if (!ops) {
 		rc = -ENOTSUPP;
 		goto err_gpio_dir;
 	}
 
+	dev = ieee802154_alloc_device(sizeof(*lp), ops);
+	if (!dev) {
+		rc = -ENOMEM;
+		goto err_gpio_dir;
+	}
+
+	lp = dev->priv;
+	lp->dev = dev;
+	lp->part = part;
+	lp->vers = version;
+
+	lp->spi = spi;
+
+	dev->parent = &spi->dev;
+	dev->extra_tx_headroom = 0;
+	dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
+
+	if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		irq_worker = at86rf230_irqwork;
+		irq_handler = at86rf230_isr;
+	} else {
+		irq_worker = at86rf230_irqwork_level;
+		irq_handler = at86rf230_isr_level;
+	}
+
+	mutex_init(&lp->bmux);
+	INIT_WORK(&lp->irqwork, irq_worker);
+	spin_lock_init(&lp->lock);
+	init_completion(&lp->tx_complete);
+
+	spi_set_drvdata(spi, lp);
+
+	if (is_rf212(lp)) {
+		dev->phy->channels_supported[0] = 0x00007FF;
+		dev->phy->channels_supported[2] = 0x00007FF;
+	} else {
+		dev->phy->channels_supported[0] = 0x7FFF800;
+	}
+
 	rc = at86rf230_hw_init(lp);
 	if (rc)
-		goto err_gpio_dir;
+		goto err_hw_init;
 
 	rc = request_irq(spi->irq, irq_handler,
 			 IRQF_SHARED | pdata->irq_type,
 			 dev_name(&spi->dev), lp);
 	if (rc)
-		goto err_gpio_dir;
+		goto err_hw_init;
 
 	/* Read irq status register to reset irq line */
 	rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
@@ -980,30 +1181,33 @@ static int at86rf230_probe(struct spi_device *spi)
 
 err_irq:
 	free_irq(spi->irq, lp);
+err_hw_init:
 	flush_work(&lp->irqwork);
-err_gpio_dir:
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-err_slp_tr:
-	gpio_free(lp->rstn);
-err_rstn:
+	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_device(lp->dev);
+
+err_gpio_dir:
+	if (gpio_is_valid(pdata->slp_tr))
+		gpio_free(pdata->slp_tr);
+err_slp_tr:
+	gpio_free(pdata->rstn);
 	return rc;
 }
 
 static int at86rf230_remove(struct spi_device *spi)
 {
 	struct at86rf230_local *lp = spi_get_drvdata(spi);
+	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
 
 	ieee802154_unregister_device(lp->dev);
 
 	free_irq(spi->irq, lp);
 	flush_work(&lp->irqwork);
 
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-	gpio_free(lp->rstn);
+	if (gpio_is_valid(pdata->slp_tr))
+		gpio_free(pdata->slp_tr);
+	gpio_free(pdata->rstn);
 
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_device(lp->dev);
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/loopback.c b/drivers/net/loopback.c
index c5011e078e1b..282effee7e1c 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -136,16 +136,9 @@ static const struct ethtool_ops loopback_ethtool_ops = {
 
 static int loopback_dev_init(struct net_device *dev)
 {
-	int i;
-	dev->lstats = alloc_percpu(struct pcpu_lstats);
+	dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
 	if (!dev->lstats)
 		return -ENOMEM;
-
-	for_each_possible_cpu(i) {
-		struct pcpu_lstats *lb_stats;
-		lb_stats = per_cpu_ptr(dev->lstats, i);
-		u64_stats_init(&lb_stats->syncp);
-	}
 	return 0;
 }
 
@@ -160,6 +153,7 @@ static const struct net_device_ops loopback_ops = {
 	.ndo_init      = loopback_dev_init,
 	.ndo_start_xmit= loopback_xmit,
 	.ndo_get_stats64 = loopback_get_stats64,
+	.ndo_set_mac_address = eth_mac_addr,
 };
 
 /*
@@ -174,6 +168,7 @@ static void loopback_setup(struct net_device *dev)
 	dev->tx_queue_len	= 0;
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
 	dev->flags		= IFF_LOOPBACK;
+	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
 	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
 	dev->hw_features	= NETIF_F_ALL_TSO | NETIF_F_UFO;
 	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
@@ -181,6 +176,7 @@ static void loopback_setup(struct net_device *dev)
 		| NETIF_F_UFO
 		| NETIF_F_HW_CSUM
 		| NETIF_F_RXCSUM
+		| NETIF_F_SCTP_CSUM
 		| NETIF_F_HIGHDMA
 		| NETIF_F_LLTX
 		| NETIF_F_NETNS_LOCAL
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index a5d21893670d..c683ac2c8c94 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -506,6 +506,9 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
 static struct lock_class_key macvlan_netdev_xmit_lock_key;
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
+#define ALWAYS_ON_FEATURES \
+	(NETIF_F_SG | NETIF_F_GEN_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX)
+
 #define MACVLAN_FEATURES \
 	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
 	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
@@ -534,28 +537,21 @@ static int macvlan_init(struct net_device *dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	const struct net_device *lowerdev = vlan->lowerdev;
-	int i;
 
 	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
-	dev->features		|= NETIF_F_LLTX;
+	dev->features		|= ALWAYS_ON_FEATURES;
 	dev->gso_max_size	= lowerdev->gso_max_size;
 	dev->iflink		= lowerdev->ifindex;
 	dev->hard_header_len	= lowerdev->hard_header_len;
 
 	macvlan_set_lockdep_class(dev);
 
-	vlan->pcpu_stats = alloc_percpu(struct vlan_pcpu_stats);
+	vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
 	if (!vlan->pcpu_stats)
 		return -ENOMEM;
 
-	for_each_possible_cpu(i) {
-		struct vlan_pcpu_stats *mvlstats;
-		mvlstats = per_cpu_ptr(vlan->pcpu_stats, i);
-		u64_stats_init(&mvlstats->syncp);
-	}
-
 	return 0;
 }
 
@@ -699,7 +695,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	features = netdev_increment_features(vlan->lowerdev->features,
 					     features,
 					     mask);
-	features |= NETIF_F_LLTX;
+	features |= ALWAYS_ON_FEATURES;
 
 	return features;
 }
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index d2bb12bfabd5..14ce7de6a933 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -47,16 +47,7 @@ static int nlmon_change_mtu(struct net_device *dev, int new_mtu)
 
 static int nlmon_dev_init(struct net_device *dev)
 {
-	int i;
-
-	dev->lstats = alloc_percpu(struct pcpu_lstats);
-
-	for_each_possible_cpu(i) {
-		struct pcpu_lstats *nlmstats;
-		nlmstats = per_cpu_ptr(dev->lstats, i);
-		u64_stats_init(&nlmstats->syncp);
-	}
-
+	dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
 	return dev->lstats == NULL ? -ENOMEM : 0;
 }
 
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 9b5d46c03eed..6a17f92153b3 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -71,6 +71,12 @@ config BCM63XX_PHY
 	---help---
 	  Currently supports the 6348 and 6358 PHYs.
 
+config BCM7XXX_PHY
+	tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
+	---help---
+	  Currently supports the BCM7366, BCM7439, BCM7445, and
+	  40nm and 65nm generation of BCM7xxx Set Top Box SoCs.
+
 config BCM87XX_PHY
 	tristate "Driver for Broadcom BCM8706 and BCM8727 PHYs"
 	help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 9013dfa12aa3..07d24024863e 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
+obj-$(CONFIG_BCM7XXX_PHY)	+= bcm7xxx.o
 obj-$(CONFIG_BCM87XX_PHY)	+= bcm87xx.o
 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
new file mode 100644
index 000000000000..697337220016
--- /dev/null
+++ b/drivers/net/phy/bcm7xxx.c
@@ -0,0 +1,343 @@
+/*
+ * Broadcom BCM7xxx internal transceivers support.
+ *
+ * Copyright (C) 2014, 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/brcmphy.h>
+
+/* Broadcom BCM7xxx internal PHY registers */
+#define MII_BCM7XXX_CHANNEL_WIDTH	0x2000
+
+/* 40nm only register definitions */
+#define MII_BCM7XXX_100TX_AUX_CTL	0x10
+#define MII_BCM7XXX_100TX_FALSE_CAR	0x13
+#define MII_BCM7XXX_100TX_DISC		0x14
+#define MII_BCM7XXX_AUX_MODE		0x1d
+#define  MII_BCM7XX_64CLK_MDIO		BIT(12)
+#define MII_BCM7XXX_CORE_BASE1E		0x1e
+#define MII_BCM7XXX_TEST		0x1f
+#define  MII_BCM7XXX_SHD_MODE_2		BIT(2)
+
+static int bcm7445_config_init(struct phy_device *phydev)
+{
+	int ret;
+	const struct bcm7445_regs {
+		int reg;
+		u16 value;
+	} bcm7445_regs_cfg[] = {
+		/* increases ADC latency by 24ns */
+		{ MII_BCM54XX_EXP_SEL, 0x0038 },
+		{ MII_BCM54XX_EXP_DATA, 0xAB95 },
+		/* increases internal 1V LDO voltage by 5% */
+		{ MII_BCM54XX_EXP_SEL, 0x2038 },
+		{ MII_BCM54XX_EXP_DATA, 0xBB22 },
+		/* reduce RX low pass filter corner frequency */
+		{ MII_BCM54XX_EXP_SEL, 0x6038 },
+		{ MII_BCM54XX_EXP_DATA, 0xFFC5 },
+		/* reduce RX high pass filter corner frequency */
+		{ MII_BCM54XX_EXP_SEL, 0x003a },
+		{ MII_BCM54XX_EXP_DATA, 0x2002 },
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(bcm7445_regs_cfg); i++) {
+		ret = phy_write(phydev,
+				bcm7445_regs_cfg[i].reg,
+				bcm7445_regs_cfg[i].value);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void phy_write_exp(struct phy_device *phydev,
+					u16 reg, u16 value)
+{
+	phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg);
+	phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
+}
+
+static void phy_write_misc(struct phy_device *phydev,
+					u16 reg, u16 chl, u16 value)
+{
+	int tmp;
+
+	phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+
+	tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+	tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
+	phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
+
+	tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg;
+	phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp);
+
+	phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
+}
+
+static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev)
+{
+	/* write AFE_RXCONFIG_0 */
+	phy_write_misc(phydev, 0x38, 0x0000, 0xeb19);
+
+	/* write AFE_RXCONFIG_1 */
+	phy_write_misc(phydev, 0x38, 0x0001, 0x9a3f);
+
+	/* write AFE_RX_LP_COUNTER */
+	phy_write_misc(phydev, 0x38, 0x0003, 0x7fc7);
+
+	/* write AFE_HPF_TRIM_OTHERS */
+	phy_write_misc(phydev, 0x3A, 0x0000, 0x000b);
+
+	/* write AFTE_TX_CONFIG */
+	phy_write_misc(phydev, 0x39, 0x0000, 0x0800);
+
+	/* Increase VCO range to prevent unlocking problem of PLL at low
+	 * temp
+	 */
+	phy_write_misc(phydev, 0x0032, 0x0001, 0x0048);
+
+	/* Change Ki to 011 */
+	phy_write_misc(phydev, 0x0032, 0x0002, 0x021b);
+
+	/* Disable loading of TVCO buffer to bandgap, set bandgap trim
+	 * to 111
+	 */
+	phy_write_misc(phydev, 0x0033, 0x0000, 0x0e20);
+
+	/* Adjust bias current trim by -3 */
+	phy_write_misc(phydev, 0x000a, 0x0000, 0x690b);
+
+	/* Switch to CORE_BASE1E */
+	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd);
+
+	/* Reset R_CAL/RC_CAL Engine */
+	phy_write_exp(phydev, 0x00b0, 0x0010);
+
+	/* Disable Reset R_CAL/RC_CAL Engine */
+	phy_write_exp(phydev, 0x00b0, 0x0000);
+
+	return 0;
+}
+
+static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = bcm7445_config_init(phydev);
+	if (ret)
+		return ret;
+
+	return bcm7xxx_28nm_afe_config_init(phydev);
+}
+
+static int phy_set_clr_bits(struct phy_device *dev, int location,
+					int set_mask, int clr_mask)
+{
+	int v, ret;
+
+	v = phy_read(dev, location);
+	if (v < 0)
+		return v;
+
+	v &= ~clr_mask;
+	v |= set_mask;
+
+	ret = phy_write(dev, location, v);
+	if (ret < 0)
+		return ret;
+
+	return v;
+}
+
+static int bcm7xxx_config_init(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Enable 64 clock MDIO */
+	phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XX_64CLK_MDIO);
+	phy_read(phydev, MII_BCM7XXX_AUX_MODE);
+
+	/* Workaround only required for 100Mbits/sec */
+	if (!(phydev->dev_flags & PHY_BRCM_100MBPS_WAR))
+		return 0;
+
+	/* set shadow mode 2 */
+	ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
+			MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
+	if (ret < 0)
+		return ret;
+
+	/* set iddq_clkbias */
+	phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
+	udelay(10);
+
+	/* reset iddq_clkbias */
+	phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
+
+	phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
+
+	/* reset shadow mode 2 */
+	ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, MII_BCM7XXX_SHD_MODE_2, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Workaround for putting the PHY in IDDQ mode, required
+ * for all BCM7XXX PHYs
+ */
+static int bcm7xxx_suspend(struct phy_device *phydev)
+{
+	int ret;
+	const struct bcm7xxx_regs {
+		int reg;
+		u16 value;
+	} bcm7xxx_suspend_cfg[] = {
+		{ MII_BCM7XXX_TEST, 0x008b },
+		{ MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
+		{ MII_BCM7XXX_100TX_DISC, 0x7000 },
+		{ MII_BCM7XXX_TEST, 0x000f },
+		{ MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
+		{ MII_BCM7XXX_TEST, 0x000b },
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
+		ret = phy_write(phydev,
+				bcm7xxx_suspend_cfg[i].reg,
+				bcm7xxx_suspend_cfg[i].value);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int bcm7xxx_dummy_config_init(struct phy_device *phydev)
+{
+	return 0;
+}
+
+static struct phy_driver bcm7xxx_driver[] = {
+{
+	.phy_id		= PHY_ID_BCM7366,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Broadcom BCM7366",
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_28nm_afe_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_28nm_afe_config_init,
+	.driver		= { .owner = THIS_MODULE },
+}, {
+	.phy_id		= PHY_ID_BCM7439,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Broadcom BCM7439",
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_28nm_afe_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_28nm_afe_config_init,
+	.driver		= { .owner = THIS_MODULE },
+}, {
+	.phy_id		= PHY_ID_BCM7445,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Broadcom BCM7445",
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_28nm_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_28nm_config_init,
+	.driver		= { .owner = THIS_MODULE },
+}, {
+	.name		= "Broadcom BCM7XXX 28nm",
+	.phy_id		= PHY_ID_BCM7XXX_28,
+	.phy_id_mask	= PHY_BCM_OUI_MASK,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_28nm_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_28nm_config_init,
+	.driver		= { .owner = THIS_MODULE },
+}, {
+	.phy_id		= PHY_BCM_OUI_4,
+	.phy_id_mask	= 0xffff0000,
+	.name		= "Broadcom BCM7XXX 40nm",
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_config_init,
+	.driver		= { .owner = THIS_MODULE },
+}, {
+	.phy_id		= PHY_BCM_OUI_5,
+	.phy_id_mask	= 0xffffff00,
+	.name		= "Broadcom BCM7XXX 65nm",
+	.features	= PHY_BASIC_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_IS_INTERNAL,
+	.config_init	= bcm7xxx_dummy_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.suspend	= bcm7xxx_suspend,
+	.resume		= bcm7xxx_config_init,
+	.driver		= { .owner = THIS_MODULE },
+} };
+
+static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
+	{ PHY_ID_BCM7366, 0xfffffff0, },
+	{ PHY_ID_BCM7439, 0xfffffff0, },
+	{ PHY_ID_BCM7445, 0xfffffff0, },
+	{ PHY_ID_BCM7XXX_28, 0xfffffc00 },
+	{ PHY_BCM_OUI_4, 0xffff0000 },
+	{ PHY_BCM_OUI_5, 0xffffff00 },
+	{ }
+};
+
+static int __init bcm7xxx_phy_init(void)
+{
+	return phy_drivers_register(bcm7xxx_driver,
+			ARRAY_SIZE(bcm7xxx_driver));
+}
+
+static void __exit bcm7xxx_phy_exit(void)
+{
+	phy_drivers_unregister(bcm7xxx_driver,
+			ARRAY_SIZE(bcm7xxx_driver));
+}
+
+module_init(bcm7xxx_phy_init);
+module_exit(bcm7xxx_phy_exit);
+
+MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
+
+MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index f8c90ea75108..34088d60da74 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -25,58 +25,6 @@
 #define BRCM_PHY_REV(phydev) \
 	((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
 
-
-#define MII_BCM54XX_ECR		0x10	/* BCM54xx extended control register */
-#define MII_BCM54XX_ECR_IM	0x1000	/* Interrupt mask */
-#define MII_BCM54XX_ECR_IF	0x0800	/* Interrupt force */
-
-#define MII_BCM54XX_ESR		0x11	/* BCM54xx extended status register */
-#define MII_BCM54XX_ESR_IS	0x1000	/* Interrupt status */
-
-#define MII_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
-#define MII_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
-#define MII_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
-#define MII_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
-
-#define MII_BCM54XX_AUX_CTL	0x18	/* Auxiliary control register */
-#define MII_BCM54XX_ISR		0x1a	/* BCM54xx interrupt status register */
-#define MII_BCM54XX_IMR		0x1b	/* BCM54xx interrupt mask register */
-#define MII_BCM54XX_INT_CRCERR	0x0001	/* CRC error */
-#define MII_BCM54XX_INT_LINK	0x0002	/* Link status changed */
-#define MII_BCM54XX_INT_SPEED	0x0004	/* Link speed change */
-#define MII_BCM54XX_INT_DUPLEX	0x0008	/* Duplex mode changed */
-#define MII_BCM54XX_INT_LRS	0x0010	/* Local receiver status changed */
-#define MII_BCM54XX_INT_RRS	0x0020	/* Remote receiver status changed */
-#define MII_BCM54XX_INT_SSERR	0x0040	/* Scrambler synchronization error */
-#define MII_BCM54XX_INT_UHCD	0x0080	/* Unsupported HCD negotiated */
-#define MII_BCM54XX_INT_NHCD	0x0100	/* No HCD */
-#define MII_BCM54XX_INT_NHCDL	0x0200	/* No HCD link */
-#define MII_BCM54XX_INT_ANPR	0x0400	/* Auto-negotiation page received */
-#define MII_BCM54XX_INT_LC	0x0800	/* All counters below 128 */
-#define MII_BCM54XX_INT_HC	0x1000	/* Counter above 32768 */
-#define MII_BCM54XX_INT_MDIX	0x2000	/* MDIX status change */
-#define MII_BCM54XX_INT_PSERR	0x4000	/* Pair swap error */
-
-#define MII_BCM54XX_SHD		0x1c	/* 0x1c shadow registers */
-#define MII_BCM54XX_SHD_WRITE	0x8000
-#define MII_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
-#define MII_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
-
-/*
- * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
- */
-#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
-#define MII_BCM54XX_AUXCTL_ACTL_TX_6DB		0x0400
-#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA	0x0800
-
-#define MII_BCM54XX_AUXCTL_MISC_WREN	0x8000
-#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
-#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
-#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
-
-#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
-
-
 /*
  * Broadcom LED source encodings.  These are used in BCM5461, BCM5481,
  * BCM5482, and possibly some others.
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 71e49000fbf3..76f54b32a120 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -432,8 +432,28 @@ phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR_RO(phy_id);
 
+static ssize_t
+phy_interface_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct phy_device *phydev = to_phy_device(dev);
+
+	return sprintf(buf, "%s\n", phy_modes(phydev->interface));
+}
+static DEVICE_ATTR_RO(phy_interface);
+
+static ssize_t
+phy_has_fixups_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct phy_device *phydev = to_phy_device(dev);
+
+	return sprintf(buf, "%d\n", phydev->has_fixups);
+}
+static DEVICE_ATTR_RO(phy_has_fixups);
+
 static struct attribute *mdio_dev_attrs[] = {
 	&dev_attr_phy_id.attr,
+	&dev_attr_phy_interface.attr,
+	&dev_attr_phy_has_fixups.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(mdio_dev);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 5a8993b0cafc..0c9e4342f11d 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -148,15 +148,52 @@ static int ks8737_config_intr(struct phy_device *phydev)
 	return rc < 0 ? rc : 0;
 }
 
+static int kszphy_setup_led(struct phy_device *phydev,
+			    unsigned int reg, unsigned int shift)
+{
+
+	struct device *dev = &phydev->dev;
+	struct device_node *of_node = dev->of_node;
+	int rc, temp;
+	u32 val;
+
+	if (!of_node && dev->parent->of_node)
+		of_node = dev->parent->of_node;
+
+	if (of_property_read_u32(of_node, "micrel,led-mode", &val))
+		return 0;
+
+	temp = phy_read(phydev, reg);
+	if (temp < 0)
+		return temp;
+
+	temp &= 3 << shift;
+	temp |= val << shift;
+	rc = phy_write(phydev, reg, temp);
+
+	return rc < 0 ? rc : 0;
+}
+
 static int kszphy_config_init(struct phy_device *phydev)
 {
 	return 0;
 }
 
+static int kszphy_config_init_led8041(struct phy_device *phydev)
+{
+	/* single led control, register 0x1e bits 15..14 */
+	return kszphy_setup_led(phydev, 0x1e, 14);
+}
+
 static int ksz8021_config_init(struct phy_device *phydev)
 {
-	int rc;
 	const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
+	int rc;
+
+	rc = kszphy_setup_led(phydev, 0x1f, 4);
+	if (rc)
+		dev_err(&phydev->dev, "failed to set led mode\n");
+
 	phy_write(phydev, MII_KSZPHY_OMSO, val);
 	rc = ksz_config_flags(phydev);
 	return rc < 0 ? rc : 0;
@@ -166,6 +203,10 @@ static int ks8051_config_init(struct phy_device *phydev)
 {
 	int rc;
 
+	rc = kszphy_setup_led(phydev, 0x1f, 4);
+	if (rc)
+		dev_err(&phydev->dev, "failed to set led mode\n");
+
 	rc = ksz_config_flags(phydev);
 	return rc < 0 ? rc : 0;
 }
@@ -327,7 +368,7 @@ static struct phy_driver ksphy_driver[] = {
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
 				| SUPPORTED_Asym_Pause),
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-	.config_init	= kszphy_config_init,
+	.config_init	= kszphy_config_init_led8041,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
@@ -342,7 +383,7 @@ static struct phy_driver ksphy_driver[] = {
 	.features	= PHY_BASIC_FEATURES |
 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-	.config_init	= kszphy_config_init,
+	.config_init	= kszphy_config_init_led8041,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
@@ -371,7 +412,7 @@ static struct phy_driver ksphy_driver[] = {
 	.phy_id_mask	= 0x00ffffff,
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-	.config_init	= kszphy_config_init,
+	.config_init	= kszphy_config_init_led8041,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 19c9eca0ef26..643b5d665f41 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -38,6 +38,26 @@
 
 #include <asm/irq.h>
 
+static const char *phy_speed_to_str(int speed)
+{
+	switch (speed) {
+	case SPEED_10:
+		return "10Mbps";
+	case SPEED_100:
+		return "100Mbps";
+	case SPEED_1000:
+		return "1Gbps";
+	case SPEED_2500:
+		return "2.5Gbps";
+	case SPEED_10000:
+		return "10Gbps";
+	case SPEED_UNKNOWN:
+		return "Unknown";
+	default:
+		return "Unsupported (update phy.c)";
+	}
+}
+
 /**
  * phy_print_status - Convenience function to print out the current phy status
  * @phydev: the phy_device struct
@@ -45,12 +65,13 @@
 void phy_print_status(struct phy_device *phydev)
 {
 	if (phydev->link) {
-		pr_info("%s - Link is Up - %d/%s\n",
-			dev_name(&phydev->dev),
-			phydev->speed,
-			DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+		netdev_info(phydev->attached_dev,
+			"Link is Up - %s/%s - flow control %s\n",
+			phy_speed_to_str(phydev->speed),
+			DUPLEX_FULL == phydev->duplex ? "Full" : "Half",
+			phydev->pause ? "rx/tx" : "off");
 	} else	{
-		pr_info("%s - Link is Down\n", dev_name(&phydev->dev));
+		netdev_info(phydev->attached_dev, "Link is Down\n");
 	}
 }
 EXPORT_SYMBOL(phy_print_status);
@@ -62,7 +83,7 @@ EXPORT_SYMBOL(phy_print_status);
  * If the @phydev driver has an ack_interrupt function, call it to
  * ack and clear the phy device's interrupt.
  *
- * Returns 0 on success on < 0 on error.
+ * Returns 0 on success or < 0 on error.
  */
 static int phy_clear_interrupt(struct phy_device *phydev)
 {
@@ -77,7 +98,7 @@ static int phy_clear_interrupt(struct phy_device *phydev)
  * @phydev: the phy_device struct
  * @interrupts: interrupt flags to configure for this @phydev
  *
- * Returns 0 on success on < 0 on error.
+ * Returns 0 on success or < 0 on error.
  */
 static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
 {
@@ -93,15 +114,16 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
  * phy_aneg_done - return auto-negotiation status
  * @phydev: target phy_device struct
  *
- * Description: Reads the status register and returns 0 either if
- *   auto-negotiation is incomplete, or if there was an error.
- *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ * Description: Return the auto-negotiation status from this @phydev
+ * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation
+ * is still pending.
  */
 static inline int phy_aneg_done(struct phy_device *phydev)
 {
-	int retval = phy_read(phydev, MII_BMSR);
+	if (phydev->drv->aneg_done)
+		return phydev->drv->aneg_done(phydev);
 
-	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+	return genphy_aneg_done(phydev);
 }
 
 /* A structure for mapping a particular speed and duplex
@@ -283,7 +305,10 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
 
 	ethtool_cmd_speed_set(cmd, phydev->speed);
 	cmd->duplex = phydev->duplex;
-	cmd->port = PORT_MII;
+	if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
+		cmd->port = PORT_BNC;
+	else
+		cmd->port = PORT_MII;
 	cmd->phy_address = phydev->addr;
 	cmd->transceiver = phy_is_internal(phydev) ?
 		XCVR_INTERNAL : XCVR_EXTERNAL;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 82514e72b3d8..a2fbb3e1db9a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -139,6 +139,7 @@ static int phy_scan_fixups(struct phy_device *phydev)
 				mutex_unlock(&phy_fixup_lock);
 				return err;
 			}
+			phydev->has_fixups = true;
 		}
 	}
 	mutex_unlock(&phy_fixup_lock);
@@ -534,16 +535,16 @@ static int phy_poll_reset(struct phy_device *phydev)
 
 int phy_init_hw(struct phy_device *phydev)
 {
-	int ret;
+	int ret = 0;
 
 	if (!phydev->drv || !phydev->drv->config_init)
 		return 0;
 
-	ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
-	if (ret < 0)
-		return ret;
+	if (phydev->drv->soft_reset)
+		ret = phydev->drv->soft_reset(phydev);
+	else
+		ret = genphy_soft_reset(phydev);
 
-	ret = phy_poll_reset(phydev);
 	if (ret < 0)
 		return ret;
 
@@ -865,6 +866,22 @@ int genphy_config_aneg(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_config_aneg);
 
+/**
+ * genphy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the status register and returns 0 either if
+ *   auto-negotiation is incomplete, or if there was an error.
+ *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ */
+int genphy_aneg_done(struct phy_device *phydev)
+{
+	int retval = phy_read(phydev, MII_BMSR);
+
+	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+EXPORT_SYMBOL(genphy_aneg_done);
+
 static int gen10g_config_aneg(struct phy_device *phydev)
 {
 	return 0;
@@ -916,6 +933,8 @@ int genphy_read_status(struct phy_device *phydev)
 	int err;
 	int lpa;
 	int lpagb = 0;
+	int common_adv;
+	int common_adv_gb = 0;
 
 	/* Update the link, but return if there was an error */
 	err = genphy_update_link(phydev);
@@ -937,7 +956,7 @@ int genphy_read_status(struct phy_device *phydev)
 
 			phydev->lp_advertising =
 				mii_stat1000_to_ethtool_lpa_t(lpagb);
-			lpagb &= adv << 2;
+			common_adv_gb = lpagb & adv << 2;
 		}
 
 		lpa = phy_read(phydev, MII_LPA);
@@ -950,25 +969,25 @@ int genphy_read_status(struct phy_device *phydev)
 		if (adv < 0)
 			return adv;
 
-		lpa &= adv;
+		common_adv = lpa & adv;
 
 		phydev->speed = SPEED_10;
 		phydev->duplex = DUPLEX_HALF;
 		phydev->pause = 0;
 		phydev->asym_pause = 0;
 
-		if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+		if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
 			phydev->speed = SPEED_1000;
 
-			if (lpagb & LPA_1000FULL)
+			if (common_adv_gb & LPA_1000FULL)
 				phydev->duplex = DUPLEX_FULL;
-		} else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+		} else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
 			phydev->speed = SPEED_100;
 
-			if (lpa & LPA_100FULL)
+			if (common_adv & LPA_100FULL)
 				phydev->duplex = DUPLEX_FULL;
 		} else
-			if (lpa & LPA_10FULL)
+			if (common_adv & LPA_10FULL)
 				phydev->duplex = DUPLEX_FULL;
 
 		if (phydev->duplex == DUPLEX_FULL) {
@@ -1028,6 +1047,27 @@ static int gen10g_read_status(struct phy_device *phydev)
 	return 0;
 }
 
+/**
+ * genphy_soft_reset - software reset the PHY via BMCR_RESET bit
+ * @phydev: target phy_device struct
+ *
+ * Description: Perform a software PHY reset using the standard
+ * BMCR_RESET bit and poll for the reset bit to be cleared.
+ *
+ * Returns: 0 on success, < 0 on failure
+ */
+int genphy_soft_reset(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
+	if (ret < 0)
+		return ret;
+
+	return phy_poll_reset(phydev);
+}
+EXPORT_SYMBOL(genphy_soft_reset);
+
 static int genphy_config_init(struct phy_device *phydev)
 {
 	int val;
@@ -1074,6 +1114,12 @@ static int genphy_config_init(struct phy_device *phydev)
 	return 0;
 }
 
+static int gen10g_soft_reset(struct phy_device *phydev)
+{
+	/* Do nothing for now */
+	return 0;
+}
+
 static int gen10g_config_init(struct phy_device *phydev)
 {
 	/* Temporarily just say we support everything */
@@ -1248,9 +1294,11 @@ static struct phy_driver genphy_driver[] = {
 	.phy_id		= 0xffffffff,
 	.phy_id_mask	= 0xffffffff,
 	.name		= "Generic PHY",
+	.soft_reset	= genphy_soft_reset,
 	.config_init	= genphy_config_init,
 	.features	= 0,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -1259,6 +1307,7 @@ static struct phy_driver genphy_driver[] = {
 	.phy_id         = 0xffffffff,
 	.phy_id_mask    = 0xffffffff,
 	.name           = "Generic 10G PHY",
+	.soft_reset	= gen10g_soft_reset,
 	.config_init    = gen10g_config_init,
 	.features       = 0,
 	.config_aneg    = gen10g_config_aneg,
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 6d1f6ed3113f..a8497183ff8b 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -493,6 +493,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 	ndev->netdev_ops = &rionet_netdev_ops;
 	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
 	ndev->features = NETIF_F_LLTX;
+	SET_NETDEV_DEV(ndev, &mport->dev);
 	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
 
 	spin_lock_init(&rnet->lock);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index c8624a8235ab..aea92f02401b 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1540,16 +1540,10 @@ static int team_init(struct net_device *dev)
 	mutex_init(&team->lock);
 	team_set_no_mode(team);
 
-	team->pcpu_stats = alloc_percpu(struct team_pcpu_stats);
+	team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
 	if (!team->pcpu_stats)
 		return -ENOMEM;
 
-	for_each_possible_cpu(i) {
-		struct team_pcpu_stats *team_stats;
-		team_stats = per_cpu_ptr(team->pcpu_stats, i);
-		u64_stats_init(&team_stats->syncp);
-	}
-
 	for (i = 0; i < TEAM_PORT_HASHENTRIES; i++)
 		INIT_HLIST_HEAD(&team->en_port_hlist[i]);
 	INIT_LIST_HEAD(&team->port_list);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8fe9cb7d0f72..26f8635b027d 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1686,7 +1686,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 				   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
 				   NETIF_F_HW_VLAN_STAG_TX;
 		dev->features = dev->hw_features;
-		dev->vlan_features = dev->features;
+		dev->vlan_features = dev->features &
+				     ~(NETIF_F_HW_VLAN_CTAG_TX |
+				       NETIF_F_HW_VLAN_STAG_TX);
 
 		INIT_LIST_HEAD(&tun->disabled);
 		err = tun_attach(tun, file, false);
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 955df81a4358..d2e6fdb25e28 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1395,6 +1395,19 @@ static const struct driver_info ax88178a_info = {
 	.tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info dlink_dub1312_info = {
+	.description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter",
+	.bind = ax88179_bind,
+	.unbind = ax88179_unbind,
+	.status = ax88179_status,
+	.link_reset = ax88179_link_reset,
+	.reset = ax88179_reset,
+	.stop = ax88179_stop,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = ax88179_rx_fixup,
+	.tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct driver_info sitecom_info = {
 	.description = "Sitecom USB 3.0 to Gigabit Adapter",
 	.bind = ax88179_bind,
@@ -1421,6 +1434,19 @@ static const struct driver_info samsung_info = {
 	.tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info lenovo_info = {
+	.description = "Lenovo OneLinkDock Gigabit LAN",
+	.bind = ax88179_bind,
+	.unbind = ax88179_unbind,
+	.status = ax88179_status,
+	.link_reset = ax88179_link_reset,
+	.reset = ax88179_reset,
+	.stop = ax88179_stop,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = ax88179_rx_fixup,
+	.tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct usb_device_id products[] = {
 {
 	/* ASIX AX88179 10/100/1000 */
@@ -1431,6 +1457,10 @@ static const struct usb_device_id products[] = {
 	USB_DEVICE(0x0b95, 0x178a),
 	.driver_info = (unsigned long)&ax88178a_info,
 }, {
+	/* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */
+	USB_DEVICE(0x2001, 0x4a00),
+	.driver_info = (unsigned long)&dlink_dub1312_info,
+}, {
 	/* Sitecom USB 3.0 to Gigabit Adapter */
 	USB_DEVICE(0x0df6, 0x0072),
 	.driver_info = (unsigned long)&sitecom_info,
@@ -1438,6 +1468,10 @@ static const struct usb_device_id products[] = {
 	/* Samsung USB Ethernet Adapter */
 	USB_DEVICE(0x04e8, 0xa100),
 	.driver_info = (unsigned long)&samsung_info,
+}, {
+	/* Lenovo OneLinkDock Gigabit LAN */
+	USB_DEVICE(0x17ef, 0x304b),
+	.driver_info = (unsigned long)&lenovo_info,
 },
 	{ },
 };
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index d89dbe395ad2..0654bd3c4591 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -23,7 +23,7 @@
 #include <linux/ipv6.h>
 
 /* Version Information */
-#define DRIVER_VERSION "v1.04.0 (2014/01/15)"
+#define DRIVER_VERSION "v1.05.0 (2014/02/18)"
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
 #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
 #define MODULENAME "r8152"
@@ -62,6 +62,8 @@
 #define PLA_RSTTELLY		0xe800
 #define PLA_CR			0xe813
 #define PLA_CRWECR		0xe81c
+#define PLA_CONFIG12		0xe81e	/* CONFIG1, CONFIG2 */
+#define PLA_CONFIG34		0xe820	/* CONFIG3, CONFIG4 */
 #define PLA_CONFIG5		0xe822
 #define PLA_PHY_PWR		0xe84c
 #define PLA_OOB_CTRL		0xe84f
@@ -216,7 +218,14 @@
 /* PAL_BDC_CR */
 #define ALDPS_PROXY_MODE	0x0001
 
+/* PLA_CONFIG34 */
+#define LINK_ON_WAKE_EN		0x0010
+#define LINK_OFF_WAKE_EN	0x0008
+
 /* PLA_CONFIG5 */
+#define BWF_EN			0x0040
+#define MWF_EN			0x0020
+#define UWF_EN			0x0010
 #define LAN_WAKE_EN		0x0002
 
 /* PLA_LED_FEATURE */
@@ -436,6 +445,8 @@ enum rtl8152_flags {
 	RTL8152_SET_RX_MODE,
 	WORK_ENABLE,
 	RTL8152_LINK_CHG,
+	SELECTIVE_SUSPEND,
+	PHY_RESET,
 };
 
 /* Define these values to match your device */
@@ -514,11 +525,13 @@ struct r8152 {
 		void (*init)(struct r8152 *);
 		int (*enable)(struct r8152 *);
 		void (*disable)(struct r8152 *);
+		void (*up)(struct r8152 *);
 		void (*down)(struct r8152 *);
 		void (*unload)(struct r8152 *);
 	} rtl_ops;
 
 	int intr_interval;
+	u32 saved_wolopts;
 	u32 msg_enable;
 	u32 tx_qlen;
 	u16 ocp_base;
@@ -865,11 +878,21 @@ static u16 sram_read(struct r8152 *tp, u16 addr)
 static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
 {
 	struct r8152 *tp = netdev_priv(netdev);
+	int ret;
 
 	if (phy_id != R8152_PHY_ID)
 		return -EINVAL;
 
-	return r8152_mdio_read(tp, reg);
+	ret = usb_autopm_get_interface(tp->intf);
+	if (ret < 0)
+		goto out;
+
+	ret = r8152_mdio_read(tp, reg);
+
+	usb_autopm_put_interface(tp->intf);
+
+out:
+	return ret;
 }
 
 static
@@ -880,7 +903,12 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
 	if (phy_id != R8152_PHY_ID)
 		return;
 
+	if (usb_autopm_get_interface(tp->intf) < 0)
+		return;
+
 	r8152_mdio_write(tp, reg, val);
+
+	usb_autopm_put_interface(tp->intf);
 }
 
 static
@@ -889,11 +917,26 @@ int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
 static inline void set_ethernet_addr(struct r8152 *tp)
 {
 	struct net_device *dev = tp->netdev;
+	int ret;
 	u8 node_id[8] = {0};
 
-	if (pla_ocp_read(tp, PLA_IDR, sizeof(node_id), node_id) < 0)
+	if (tp->version == RTL_VER_01)
+		ret = pla_ocp_read(tp, PLA_IDR, sizeof(node_id), node_id);
+	else
+		ret = pla_ocp_read(tp, PLA_BACKUP, sizeof(node_id), node_id);
+
+	if (ret < 0) {
 		netif_notice(tp, probe, dev, "inet addr fail\n");
-	else {
+	} else {
+		if (tp->version != RTL_VER_01) {
+			ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR,
+				       CRWECR_CONFIG);
+			pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES,
+				      sizeof(node_id), node_id);
+			ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR,
+				       CRWECR_NORAML);
+		}
+
 		memcpy(dev->dev_addr, node_id, dev->addr_len);
 		memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 	}
@@ -951,6 +994,8 @@ static void read_bulk_callback(struct urb *urb)
 	if (!netif_carrier_ok(netdev))
 		return;
 
+	usb_mark_last_busy(tp->udev);
+
 	switch (status) {
 	case 0:
 		if (urb->actual_length < ETH_ZLEN)
@@ -1018,6 +1063,8 @@ static void write_bulk_callback(struct urb *urb)
 	list_add_tail(&agg->list, &tp->tx_free);
 	spin_unlock_irqrestore(&tp->tx_lock, flags);
 
+	usb_autopm_put_interface_async(tp->intf);
+
 	if (!netif_carrier_ok(tp->netdev))
 		return;
 
@@ -1028,7 +1075,7 @@ static void write_bulk_callback(struct urb *urb)
 		return;
 
 	if (!skb_queue_empty(&tp->tx_queue))
-		tasklet_schedule(&tp->tl);
+		schedule_delayed_work(&tp->schedule, 0);
 }
 
 static void intr_callback(struct urb *urb)
@@ -1284,9 +1331,16 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
 
 static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 {
-	int remain;
+	struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
+	unsigned long flags;
+	int remain, ret;
 	u8 *tx_data;
 
+	__skb_queue_head_init(&skb_head);
+	spin_lock_irqsave(&tx_queue->lock, flags);
+	skb_queue_splice_init(tx_queue, &skb_head);
+	spin_unlock_irqrestore(&tx_queue->lock, flags);
+
 	tx_data = agg->head;
 	agg->skb_num = agg->skb_len = 0;
 	remain = rx_buf_sz;
@@ -1296,14 +1350,14 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 		struct sk_buff *skb;
 		unsigned int len;
 
-		skb = skb_dequeue(&tp->tx_queue);
+		skb = __skb_dequeue(&skb_head);
 		if (!skb)
 			break;
 
 		remain -= sizeof(*tx_desc);
 		len = skb->len;
 		if (remain < len) {
-			skb_queue_head(&tp->tx_queue, skb);
+			__skb_queue_head(&skb_head, skb);
 			break;
 		}
 
@@ -1321,28 +1375,50 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 		remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
 	}
 
-	netif_tx_lock(tp->netdev);
+	if (!skb_queue_empty(&skb_head)) {
+		spin_lock_irqsave(&tx_queue->lock, flags);
+		skb_queue_splice(&skb_head, tx_queue);
+		spin_unlock_irqrestore(&tx_queue->lock, flags);
+	}
+
+	netif_tx_lock_bh(tp->netdev);
 
 	if (netif_queue_stopped(tp->netdev) &&
 	    skb_queue_len(&tp->tx_queue) < tp->tx_qlen)
 		netif_wake_queue(tp->netdev);
 
-	netif_tx_unlock(tp->netdev);
+	netif_tx_unlock_bh(tp->netdev);
+
+	ret = usb_autopm_get_interface(tp->intf);
+	if (ret < 0)
+		goto out_tx_fill;
 
 	usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
 			  agg->head, (int)(tx_data - (u8 *)agg->head),
 			  (usb_complete_t)write_bulk_callback, agg);
 
-	return usb_submit_urb(agg->urb, GFP_ATOMIC);
+	ret = usb_submit_urb(agg->urb, GFP_KERNEL);
+	if (ret < 0)
+		usb_autopm_put_interface(tp->intf);
+
+out_tx_fill:
+	return ret;
 }
 
 static void rx_bottom(struct r8152 *tp)
 {
 	unsigned long flags;
-	struct list_head *cursor, *next;
+	struct list_head *cursor, *next, rx_queue;
 
+	if (list_empty(&tp->rx_done))
+		return;
+
+	INIT_LIST_HEAD(&rx_queue);
 	spin_lock_irqsave(&tp->rx_lock, flags);
-	list_for_each_safe(cursor, next, &tp->rx_done) {
+	list_splice_init(&tp->rx_done, &rx_queue);
+	spin_unlock_irqrestore(&tp->rx_lock, flags);
+
+	list_for_each_safe(cursor, next, &rx_queue) {
 		struct rx_desc *rx_desc;
 		struct rx_agg *agg;
 		int len_used = 0;
@@ -1351,7 +1427,6 @@ static void rx_bottom(struct r8152 *tp)
 		int ret;
 
 		list_del_init(cursor);
-		spin_unlock_irqrestore(&tp->rx_lock, flags);
 
 		agg = list_entry(cursor, struct rx_agg, list);
 		urb = agg->urb;
@@ -1389,7 +1464,7 @@ static void rx_bottom(struct r8152 *tp)
 			memcpy(skb->data, rx_data, pkt_len);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, netdev);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			stats->rx_packets++;
 			stats->rx_bytes += pkt_len;
 
@@ -1401,13 +1476,13 @@ static void rx_bottom(struct r8152 *tp)
 
 submit:
 		ret = r8152_submit_rx(tp, agg, GFP_ATOMIC);
-		spin_lock_irqsave(&tp->rx_lock, flags);
 		if (ret && ret != -ENODEV) {
-			list_add_tail(&agg->list, next);
+			spin_lock_irqsave(&tp->rx_lock, flags);
+			list_add_tail(&agg->list, &tp->rx_done);
+			spin_unlock_irqrestore(&tp->rx_lock, flags);
 			tasklet_schedule(&tp->tl);
 		}
 	}
-	spin_unlock_irqrestore(&tp->rx_lock, flags);
 }
 
 static void tx_bottom(struct r8152 *tp)
@@ -1465,7 +1540,6 @@ static void bottom_half(unsigned long data)
 		return;
 
 	rx_bottom(tp);
-	tx_bottom(tp);
 }
 
 static
@@ -1478,6 +1552,27 @@ int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags)
 	return usb_submit_urb(agg->urb, mem_flags);
 }
 
+static void rtl_drop_queued_tx(struct r8152 *tp)
+{
+	struct net_device_stats *stats = &tp->netdev->stats;
+	struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
+	unsigned long flags;
+	struct sk_buff *skb;
+
+	if (skb_queue_empty(tx_queue))
+		return;
+
+	__skb_queue_head_init(&skb_head);
+	spin_lock_irqsave(&tx_queue->lock, flags);
+	skb_queue_splice_init(tx_queue, &skb_head);
+	spin_unlock_irqrestore(&tx_queue->lock, flags);
+
+	while ((skb = __skb_dequeue(&skb_head))) {
+		dev_kfree_skb(skb);
+		stats->tx_dropped++;
+	}
+}
+
 static void rtl8152_tx_timeout(struct net_device *netdev)
 {
 	struct r8152 *tp = netdev_priv(netdev);
@@ -1554,7 +1649,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
 		netif_stop_queue(netdev);
 
 	if (!list_empty(&tp->tx_free))
-		tasklet_schedule(&tp->tl);
+		schedule_delayed_work(&tp->schedule, 0);
 
 	return NETDEV_TX_OK;
 }
@@ -1613,6 +1708,18 @@ static void rtl_set_eee_plus(struct r8152 *tp)
 	}
 }
 
+static void rxdy_gated_en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
+	if (enable)
+		ocp_data |= RXDY_GATED_EN;
+	else
+		ocp_data &= ~RXDY_GATED_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+}
+
 static int rtl_enable(struct r8152 *tp)
 {
 	u32 ocp_data;
@@ -1624,9 +1731,7 @@ static int rtl_enable(struct r8152 *tp)
 	ocp_data |= CR_RE | CR_TE;
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data &= ~RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+	rxdy_gated_en(tp, false);
 
 	INIT_LIST_HEAD(&tp->rx_done);
 	ret = 0;
@@ -1681,8 +1786,6 @@ static int rtl8153_enable(struct r8152 *tp)
 
 static void rtl8152_disable(struct r8152 *tp)
 {
-	struct net_device_stats *stats = rtl8152_get_stats(tp->netdev);
-	struct sk_buff *skb;
 	u32 ocp_data;
 	int i;
 
@@ -1690,17 +1793,12 @@ static void rtl8152_disable(struct r8152 *tp)
 	ocp_data &= ~RCR_ACPT_ALL;
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
 
-	while ((skb = skb_dequeue(&tp->tx_queue))) {
-		dev_kfree_skb(skb);
-		stats->tx_dropped++;
-	}
+	rtl_drop_queued_tx(tp);
 
 	for (i = 0; i < RTL8152_MAX_TX; i++)
 		usb_kill_urb(tp->tx_info[i].urb);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data |= RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+	rxdy_gated_en(tp, true);
 
 	for (i = 0; i < 1000; i++) {
 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -1721,6 +1819,198 @@ static void rtl8152_disable(struct r8152 *tp)
 	rtl8152_nic_reset(tp);
 }
 
+static void r8152_power_cut_en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
+	if (enable)
+		ocp_data |= POWER_CUT;
+	else
+		ocp_data &= ~POWER_CUT;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
+	ocp_data &= ~RESUME_INDICATE;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
+
+}
+
+#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
+
+static u32 __rtl_get_wol(struct r8152 *tp)
+{
+	u32 ocp_data;
+	u32 wolopts = 0;
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5);
+	if (!(ocp_data & LAN_WAKE_EN))
+		return 0;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
+	if (ocp_data & LINK_ON_WAKE_EN)
+		wolopts |= WAKE_PHY;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
+	if (ocp_data & UWF_EN)
+		wolopts |= WAKE_UCAST;
+	if (ocp_data & BWF_EN)
+		wolopts |= WAKE_BCAST;
+	if (ocp_data & MWF_EN)
+		wolopts |= WAKE_MCAST;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
+	if (ocp_data & MAGIC_EN)
+		wolopts |= WAKE_MAGIC;
+
+	return wolopts;
+}
+
+static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
+{
+	u32 ocp_data;
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
+	ocp_data &= ~LINK_ON_WAKE_EN;
+	if (wolopts & WAKE_PHY)
+		ocp_data |= LINK_ON_WAKE_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
+	ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN | LAN_WAKE_EN);
+	if (wolopts & WAKE_UCAST)
+		ocp_data |= UWF_EN;
+	if (wolopts & WAKE_BCAST)
+		ocp_data |= BWF_EN;
+	if (wolopts & WAKE_MCAST)
+		ocp_data |= MWF_EN;
+	if (wolopts & WAKE_ANY)
+		ocp_data |= LAN_WAKE_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
+	ocp_data &= ~MAGIC_EN;
+	if (wolopts & WAKE_MAGIC)
+		ocp_data |= MAGIC_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
+
+	if (wolopts & WAKE_ANY)
+		device_set_wakeup_enable(&tp->udev->dev, true);
+	else
+		device_set_wakeup_enable(&tp->udev->dev, false);
+}
+
+static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable)
+{
+	if (enable) {
+		u32 ocp_data;
+
+		__rtl_set_wol(tp, WAKE_ANY);
+
+		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
+
+		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
+		ocp_data |= LINK_OFF_WAKE_EN;
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
+
+		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+	} else {
+		__rtl_set_wol(tp, tp->saved_wolopts);
+	}
+}
+
+static void rtl_phy_reset(struct r8152 *tp)
+{
+	u16 data;
+	int i;
+
+	clear_bit(PHY_RESET, &tp->flags);
+
+	data = r8152_mdio_read(tp, MII_BMCR);
+
+	/* don't reset again before the previous one complete */
+	if (data & BMCR_RESET)
+		return;
+
+	data |= BMCR_RESET;
+	r8152_mdio_write(tp, MII_BMCR, data);
+
+	for (i = 0; i < 50; i++) {
+		msleep(20);
+		if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
+			break;
+	}
+}
+
+static void rtl_clear_bp(struct r8152 *tp)
+{
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0);
+	mdelay(3);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0);
+	ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
+}
+
+static void r8153_clear_bp(struct r8152 *tp)
+{
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
+	ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
+	rtl_clear_bp(tp);
+}
+
+static void r8153_teredo_off(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
+	ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
+}
+
+static void r8152b_disable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
+	msleep(20);
+}
+
+static inline void r8152b_enable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
+					    LINKENA | DIS_SDSAVE);
+}
+
+static void r8152b_hw_phy_cfg(struct r8152 *tp)
+{
+	u16 data;
+
+	data = r8152_mdio_read(tp, MII_BMCR);
+	if (data & BMCR_PDOWN) {
+		data &= ~BMCR_PDOWN;
+		r8152_mdio_write(tp, MII_BMCR, data);
+	}
+
+	r8152b_disable_aldps(tp);
+
+	rtl_clear_bp(tp);
+
+	r8152b_enable_aldps(tp);
+	set_bit(PHY_RESET, &tp->flags);
+}
+
 static void r8152b_exit_oob(struct r8152 *tp)
 {
 	u32	ocp_data;
@@ -1730,9 +2020,9 @@ static void r8152b_exit_oob(struct r8152 *tp)
 	ocp_data &= ~RCR_ACPT_ALL;
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data |= RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+	rxdy_gated_en(tp, true);
+	r8153_teredo_off(tp);
+	r8152b_hw_phy_cfg(tp);
 
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00);
@@ -1838,10 +2128,6 @@ static void r8152b_enter_oob(struct r8152 *tp)
 
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
-	ocp_data |= MAGIC_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
-
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
 	ocp_data |= CPCR_RX_VLAN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
@@ -1854,36 +2140,26 @@ static void r8152b_enter_oob(struct r8152 *tp)
 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
 
-	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data &= ~RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+	rxdy_gated_en(tp, false);
 
 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
 }
 
-static void r8152b_disable_aldps(struct r8152 *tp)
-{
-	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
-	msleep(20);
-}
-
-static inline void r8152b_enable_aldps(struct r8152 *tp)
-{
-	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
-					    LINKENA | DIS_SDSAVE);
-}
-
 static void r8153_hw_phy_cfg(struct r8152 *tp)
 {
 	u32 ocp_data;
 	u16 data;
 
 	ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
-	r8152_mdio_write(tp, MII_BMCR, BMCR_ANENABLE);
+	data = r8152_mdio_read(tp, MII_BMCR);
+	if (data & BMCR_PDOWN) {
+		data &= ~BMCR_PDOWN;
+		r8152_mdio_write(tp, MII_BMCR, data);
+	}
+
+	r8153_clear_bp(tp);
 
 	if (tp->version == RTL_VER_03) {
 		data = ocp_reg_read(tp, OCP_EEE_CFG);
@@ -1919,9 +2195,11 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)
 	data = sram_read(tp, SRAM_10M_AMP2);
 	data |= AMP_DN;
 	sram_write(tp, SRAM_10M_AMP2, data);
+
+	set_bit(PHY_RESET, &tp->flags);
 }
 
-static void r8153_u1u2en(struct r8152 *tp, int enable)
+static void r8153_u1u2en(struct r8152 *tp, bool enable)
 {
 	u8 u1u2[8];
 
@@ -1933,7 +2211,7 @@ static void r8153_u1u2en(struct r8152 *tp, int enable)
 	usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
 }
 
-static void r8153_u2p3en(struct r8152 *tp, int enable)
+static void r8153_u2p3en(struct r8152 *tp, bool enable)
 {
 	u32 ocp_data;
 
@@ -1945,7 +2223,7 @@ static void r8153_u2p3en(struct r8152 *tp, int enable)
 	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
 }
 
-static void r8153_power_cut_en(struct r8152 *tp, int enable)
+static void r8153_power_cut_en(struct r8152 *tp, bool enable)
 {
 	u32 ocp_data;
 
@@ -1961,28 +2239,12 @@ static void r8153_power_cut_en(struct r8152 *tp, int enable)
 	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
 }
 
-static void r8153_teredo_off(struct r8152 *tp)
-{
-	u32 ocp_data;
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
-	ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
-
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
-}
-
 static void r8153_first_init(struct r8152 *tp)
 {
 	u32 ocp_data;
 	int i;
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data |= RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-
+	rxdy_gated_en(tp, true);
 	r8153_teredo_off(tp);
 
 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
@@ -2075,10 +2337,6 @@ static void r8153_enter_oob(struct r8152 *tp)
 
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
-	ocp_data |= MAGIC_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
-
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
 	ocp_data &= ~TEREDO_WAKE_MASK;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
@@ -2095,11 +2353,7 @@ static void r8153_enter_oob(struct r8152 *tp)
 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
 
-	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-	ocp_data &= ~RXDY_GATED_EN;
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+	rxdy_gated_en(tp, false);
 
 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
@@ -2190,12 +2444,26 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
 		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
 	}
 
+	if (test_bit(PHY_RESET, &tp->flags))
+		bmcr |= BMCR_RESET;
+
 	if (tp->mii.supports_gmii)
 		r8152_mdio_write(tp, MII_CTRL1000, gbcr);
 
 	r8152_mdio_write(tp, MII_ADVERTISE, anar);
 	r8152_mdio_write(tp, MII_BMCR, bmcr);
 
+	if (test_bit(PHY_RESET, &tp->flags)) {
+		int i;
+
+		clear_bit(PHY_RESET, &tp->flags);
+		for (i = 0; i < 50; i++) {
+			msleep(20);
+			if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
+				break;
+		}
+	}
+
 out:
 
 	return ret;
@@ -2203,12 +2471,7 @@ out:
 
 static void rtl8152_down(struct r8152 *tp)
 {
-	u32	ocp_data;
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-	ocp_data &= ~POWER_CUT;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-
+	r8152_power_cut_en(tp, false);
 	r8152b_disable_aldps(tp);
 	r8152b_enter_oob(tp);
 	r8152b_enable_aldps(tp);
@@ -2216,8 +2479,8 @@ static void rtl8152_down(struct r8152 *tp)
 
 static void rtl8153_down(struct r8152 *tp)
 {
-	r8153_u1u2en(tp, 0);
-	r8153_power_cut_en(tp, 0);
+	r8153_u1u2en(tp, false);
+	r8153_power_cut_en(tp, false);
 	r8153_disable_aldps(tp);
 	r8153_enter_oob(tp);
 	r8153_enable_aldps(tp);
@@ -2252,6 +2515,9 @@ static void rtl_work_func_t(struct work_struct *work)
 {
 	struct r8152 *tp = container_of(work, struct r8152, schedule.work);
 
+	if (usb_autopm_get_interface(tp->intf) < 0)
+		return;
+
 	if (!test_bit(WORK_ENABLE, &tp->flags))
 		goto out1;
 
@@ -2264,8 +2530,14 @@ static void rtl_work_func_t(struct work_struct *work)
 	if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
 		_rtl8152_set_rx_mode(tp->netdev);
 
+	if (tp->speed & LINK_STATUS)
+		tx_bottom(tp);
+
+	if (test_bit(PHY_RESET, &tp->flags))
+		rtl_phy_reset(tp);
+
 out1:
-	return;
+	usb_autopm_put_interface(tp->intf);
 }
 
 static int rtl8152_open(struct net_device *netdev)
@@ -2273,6 +2545,27 @@ static int rtl8152_open(struct net_device *netdev)
 	struct r8152 *tp = netdev_priv(netdev);
 	int res = 0;
 
+	res = alloc_all_mem(tp);
+	if (res)
+		goto out;
+
+	res = usb_autopm_get_interface(tp->intf);
+	if (res < 0) {
+		free_all_mem(tp);
+		goto out;
+	}
+
+	/* The WORK_ENABLE may be set when autoresume occurs */
+	if (test_bit(WORK_ENABLE, &tp->flags)) {
+		clear_bit(WORK_ENABLE, &tp->flags);
+		usb_kill_urb(tp->intr_urb);
+		cancel_delayed_work_sync(&tp->schedule);
+		if (tp->speed & LINK_STATUS)
+			tp->rtl_ops.disable(tp);
+	}
+
+	tp->rtl_ops.up(tp);
+
 	rtl8152_set_speed(tp, AUTONEG_ENABLE,
 			  tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
 			  DUPLEX_FULL);
@@ -2286,9 +2579,12 @@ static int rtl8152_open(struct net_device *netdev)
 			netif_device_detach(tp->netdev);
 		netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
 			   res);
+		free_all_mem(tp);
 	}
 
+	usb_autopm_put_interface(tp->intf);
 
+out:
 	return res;
 }
 
@@ -2301,33 +2597,30 @@ static int rtl8152_close(struct net_device *netdev)
 	usb_kill_urb(tp->intr_urb);
 	cancel_delayed_work_sync(&tp->schedule);
 	netif_stop_queue(netdev);
-	tasklet_disable(&tp->tl);
-	tp->rtl_ops.disable(tp);
-	tasklet_enable(&tp->tl);
 
-	return res;
-}
+	res = usb_autopm_get_interface(tp->intf);
+	if (res < 0) {
+		rtl_drop_queued_tx(tp);
+	} else {
+		/*
+		 * The autosuspend may have been enabled and wouldn't
+		 * be disable when autoresume occurs, because the
+		 * netif_running() would be false.
+		 */
+		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+			rtl_runtime_suspend_enable(tp, false);
+			clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+		}
 
-static void rtl_clear_bp(struct r8152 *tp)
-{
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0);
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0);
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0);
-	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0);
-	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0);
-	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0);
-	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0);
-	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0);
-	mdelay(3);
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0);
-	ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
-}
+		tasklet_disable(&tp->tl);
+		tp->rtl_ops.down(tp);
+		tasklet_enable(&tp->tl);
+		usb_autopm_put_interface(tp->intf);
+	}
 
-static void r8153_clear_bp(struct r8152 *tp)
-{
-	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
-	ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
-	rtl_clear_bp(tp);
+	free_all_mem(tp);
+
+	return res;
 }
 
 static void r8152b_enable_eee(struct r8152 *tp)
@@ -2378,18 +2671,9 @@ static void r8152b_enable_fc(struct r8152 *tp)
 	r8152_mdio_write(tp, MII_ADVERTISE, anar);
 }
 
-static void r8152b_hw_phy_cfg(struct r8152 *tp)
-{
-	r8152_mdio_write(tp, MII_BMCR, BMCR_ANENABLE);
-	r8152b_disable_aldps(tp);
-}
-
 static void r8152b_init(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
-
-	rtl_clear_bp(tp);
 
 	if (tp->version == RTL_VER_01) {
 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
@@ -2397,17 +2681,7 @@ static void r8152b_init(struct r8152 *tp)
 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
 	}
 
-	r8152b_hw_phy_cfg(tp);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-	ocp_data &= ~POWER_CUT;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-	ocp_data &= ~RESUME_INDICATE;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
-
-	r8152b_exit_oob(tp);
+	r8152_power_cut_en(tp, false);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
 	ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
@@ -2424,14 +2698,6 @@ static void r8152b_init(struct r8152 *tp)
 	r8152b_enable_aldps(tp);
 	r8152b_enable_fc(tp);
 
-	r8152_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE |
-				       BMCR_ANRESTART);
-	for (i = 0; i < 100; i++) {
-		udelay(100);
-		if (!(r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET))
-			break;
-	}
-
 	/* enable rx aggregation */
 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
 	ocp_data &= ~RX_AGG_DISABLE;
@@ -2443,7 +2709,7 @@ static void r8153_init(struct r8152 *tp)
 	u32 ocp_data;
 	int i;
 
-	r8153_u1u2en(tp, 0);
+	r8153_u1u2en(tp, false);
 
 	for (i = 0; i < 500; i++) {
 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
@@ -2459,14 +2725,12 @@ static void r8153_init(struct r8152 *tp)
 		msleep(20);
 	}
 
-	r8153_u2p3en(tp, 0);
+	r8153_u2p3en(tp, false);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
 	ocp_data &= ~TIMER11_EN;
 	ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
 
-	r8153_clear_bp(tp);
-
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
 	ocp_data &= ~LED_MODE_MASK;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
@@ -2484,10 +2748,8 @@ static void r8153_init(struct r8152 *tp)
 	ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
 	ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
 
-	r8153_power_cut_en(tp, 0);
-	r8153_u1u2en(tp, 1);
-
-	r8153_first_init(tp);
+	r8153_power_cut_en(tp, false);
+	r8153_u1u2en(tp, true);
 
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ALDPS_SPDWN_RATIO);
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, EEE_SPDWN_RATIO);
@@ -2502,26 +2764,30 @@ static void r8153_init(struct r8152 *tp)
 	r8153_enable_eee(tp);
 	r8153_enable_aldps(tp);
 	r8152b_enable_fc(tp);
-
-	r8152_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE |
-				       BMCR_ANRESTART);
 }
 
 static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct r8152 *tp = usb_get_intfdata(intf);
 
-	netif_device_detach(tp->netdev);
+	if (PMSG_IS_AUTO(message))
+		set_bit(SELECTIVE_SUSPEND, &tp->flags);
+	else
+		netif_device_detach(tp->netdev);
 
 	if (netif_running(tp->netdev)) {
 		clear_bit(WORK_ENABLE, &tp->flags);
 		usb_kill_urb(tp->intr_urb);
 		cancel_delayed_work_sync(&tp->schedule);
-		tasklet_disable(&tp->tl);
+		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+			rtl_runtime_suspend_enable(tp, true);
+		} else {
+			tasklet_disable(&tp->tl);
+			tp->rtl_ops.down(tp);
+			tasklet_enable(&tp->tl);
+		}
 	}
 
-	tp->rtl_ops.down(tp);
-
 	return 0;
 }
 
@@ -2529,22 +2795,77 @@ static int rtl8152_resume(struct usb_interface *intf)
 {
 	struct r8152 *tp = usb_get_intfdata(intf);
 
-	tp->rtl_ops.init(tp);
-	netif_device_attach(tp->netdev);
+	if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+		tp->rtl_ops.init(tp);
+		netif_device_attach(tp->netdev);
+	}
+
 	if (netif_running(tp->netdev)) {
-		rtl8152_set_speed(tp, AUTONEG_ENABLE,
+		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+			rtl_runtime_suspend_enable(tp, false);
+			clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+			if (tp->speed & LINK_STATUS)
+				tp->rtl_ops.disable(tp);
+		} else {
+			tp->rtl_ops.up(tp);
+			rtl8152_set_speed(tp, AUTONEG_ENABLE,
 				tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
 				DUPLEX_FULL);
+		}
 		tp->speed = 0;
 		netif_carrier_off(tp->netdev);
 		set_bit(WORK_ENABLE, &tp->flags);
 		usb_submit_urb(tp->intr_urb, GFP_KERNEL);
-		tasklet_enable(&tp->tl);
 	}
 
 	return 0;
 }
 
+static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct r8152 *tp = netdev_priv(dev);
+
+	if (usb_autopm_get_interface(tp->intf) < 0)
+		return;
+
+	wol->supported = WAKE_ANY;
+	wol->wolopts = __rtl_get_wol(tp);
+
+	usb_autopm_put_interface(tp->intf);
+}
+
+static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct r8152 *tp = netdev_priv(dev);
+	int ret;
+
+	ret = usb_autopm_get_interface(tp->intf);
+	if (ret < 0)
+		goto out_set_wol;
+
+	__rtl_set_wol(tp, wol->wolopts);
+	tp->saved_wolopts = wol->wolopts & WAKE_ANY;
+
+	usb_autopm_put_interface(tp->intf);
+
+out_set_wol:
+	return ret;
+}
+
+static u32 rtl8152_get_msglevel(struct net_device *dev)
+{
+	struct r8152 *tp = netdev_priv(dev);
+
+	return tp->msg_enable;
+}
+
+static void rtl8152_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct r8152 *tp = netdev_priv(dev);
+
+	tp->msg_enable = value;
+}
+
 static void rtl8152_get_drvinfo(struct net_device *netdev,
 				struct ethtool_drvinfo *info)
 {
@@ -2569,8 +2890,18 @@ int rtl8152_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
 static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct r8152 *tp = netdev_priv(dev);
+	int ret;
+
+	ret = usb_autopm_get_interface(tp->intf);
+	if (ret < 0)
+		goto out;
+
+	ret = rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex);
 
-	return rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex);
+	usb_autopm_put_interface(tp->intf);
+
+out:
+	return ret;
 }
 
 static struct ethtool_ops ops = {
@@ -2578,13 +2909,21 @@ static struct ethtool_ops ops = {
 	.get_settings = rtl8152_get_settings,
 	.set_settings = rtl8152_set_settings,
 	.get_link = ethtool_op_get_link,
+	.get_msglevel = rtl8152_get_msglevel,
+	.set_msglevel = rtl8152_set_msglevel,
+	.get_wol = rtl8152_get_wol,
+	.set_wol = rtl8152_set_wol,
 };
 
 static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
 	struct r8152 *tp = netdev_priv(netdev);
 	struct mii_ioctl_data *data = if_mii(rq);
-	int res = 0;
+	int res;
+
+	res = usb_autopm_get_interface(tp->intf);
+	if (res < 0)
+		goto out;
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
@@ -2607,6 +2946,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 		res = -EOPNOTSUPP;
 	}
 
+	usb_autopm_put_interface(tp->intf);
+
+out:
 	return res;
 }
 
@@ -2659,22 +3001,13 @@ static void r8152b_get_version(struct r8152 *tp)
 
 static void rtl8152_unload(struct r8152 *tp)
 {
-	u32	ocp_data;
-
-	if (tp->version != RTL_VER_01) {
-		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-		ocp_data |= POWER_CUT;
-		ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-	}
-
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-	ocp_data &= ~RESUME_INDICATE;
-	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
+	if (tp->version != RTL_VER_01)
+		r8152_power_cut_en(tp, true);
 }
 
 static void rtl8153_unload(struct r8152 *tp)
 {
-	r8153_power_cut_en(tp, 1);
+	r8153_power_cut_en(tp, true);
 }
 
 static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
@@ -2689,6 +3022,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
 			ops->init		= r8152b_init;
 			ops->enable		= rtl8152_enable;
 			ops->disable		= rtl8152_disable;
+			ops->up			= r8152b_exit_oob;
 			ops->down		= rtl8152_down;
 			ops->unload		= rtl8152_unload;
 			ret = 0;
@@ -2697,6 +3031,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
 			ops->init		= r8153_init;
 			ops->enable		= rtl8153_enable;
 			ops->disable		= rtl8152_disable;
+			ops->up			= r8153_first_init;
 			ops->down		= rtl8153_down;
 			ops->unload		= rtl8153_unload;
 			ret = 0;
@@ -2712,6 +3047,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
 			ops->init		= r8153_init;
 			ops->enable		= rtl8153_enable;
 			ops->disable		= rtl8152_disable;
+			ops->up			= r8153_first_init;
 			ops->down		= rtl8153_down;
 			ops->unload		= rtl8153_unload;
 			ret = 0;
@@ -2775,14 +3111,12 @@ static int rtl8152_probe(struct usb_interface *intf,
 	tp->mii.phy_id = R8152_PHY_ID;
 	tp->mii.supports_gmii = 0;
 
+	intf->needs_remote_wakeup = 1;
+
 	r8152b_get_version(tp);
 	tp->rtl_ops.init(tp);
 	set_ethernet_addr(tp);
 
-	ret = alloc_all_mem(tp);
-	if (ret)
-		goto out;
-
 	usb_set_intfdata(intf, tp);
 
 	ret = register_netdev(netdev);
@@ -2791,6 +3125,12 @@ static int rtl8152_probe(struct usb_interface *intf,
 		goto out1;
 	}
 
+	tp->saved_wolopts = __rtl_get_wol(tp);
+	if (tp->saved_wolopts)
+		device_set_wakeup_enable(&udev->dev, true);
+	else
+		device_set_wakeup_enable(&udev->dev, false);
+
 	netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
 
 	return 0;
@@ -2812,7 +3152,6 @@ static void rtl8152_disconnect(struct usb_interface *intf)
 		tasklet_kill(&tp->tl);
 		unregister_netdev(tp->netdev);
 		tp->rtl_ops.unload(tp);
-		free_all_mem(tp);
 		free_netdev(tp->netdev);
 	}
 }
@@ -2835,6 +3174,8 @@ static struct usb_driver rtl8152_driver = {
 	.suspend =	rtl8152_suspend,
 	.resume =	rtl8152_resume,
 	.reset_resume =	rtl8152_resume,
+	.supports_autosuspend = 1,
+	.disable_hub_initiated_lpm = 1,
 };
 
 module_usb_driver(rtl8152_driver);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 2ec2041b62d4..3aca92e80e1e 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -14,6 +14,7 @@
 #include <linux/etherdevice.h>
 #include <linux/u64_stats_sync.h>
 
+#include <net/rtnetlink.h>
 #include <net/dst.h>
 #include <net/xfrm.h>
 #include <linux/veth.h>
@@ -235,18 +236,9 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)
 
 static int veth_dev_init(struct net_device *dev)
 {
-	int i;
-
-	dev->vstats = alloc_percpu(struct pcpu_vstats);
+	dev->vstats = netdev_alloc_pcpu_stats(struct pcpu_vstats);
 	if (!dev->vstats)
 		return -ENOMEM;
-
-	for_each_possible_cpu(i) {
-		struct pcpu_vstats *veth_stats;
-		veth_stats = per_cpu_ptr(dev->vstats, i);
-		u64_stats_init(&veth_stats->syncp);
-	}
-
 	return 0;
 }
 
@@ -285,7 +277,8 @@ static void veth_setup(struct net_device *dev)
 	dev->ethtool_ops = &veth_ethtool_ops;
 	dev->features |= NETIF_F_LLTX;
 	dev->features |= VETH_FEATURES;
-	dev->vlan_features = dev->features;
+	dev->vlan_features = dev->features &
+			     ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX);
 	dev->destructor = veth_dev_free;
 
 	dev->hw_features = VETH_FEATURES;
@@ -332,10 +325,9 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 
 		nla_peer = data[VETH_INFO_PEER];
 		ifmp = nla_data(nla_peer);
-		err = nla_parse(peer_tb, IFLA_MAX,
-				nla_data(nla_peer) + sizeof(struct ifinfomsg),
-				nla_len(nla_peer) - sizeof(struct ifinfomsg),
-				ifla_policy);
+		err = rtnl_nla_parse_ifla(peer_tb,
+					  nla_data(nla_peer) + sizeof(struct ifinfomsg),
+					  nla_len(nla_peer) - sizeof(struct ifinfomsg));
 		if (err < 0)
 			return err;
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d75f8edf4fb3..5632a99cbbd2 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1711,7 +1711,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* If we can receive ANY GSO packets, we must allocate large ones. */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
 	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
-	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
+	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
 		vi->big_packets = true;
 
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 3be786faaaec..9275c8c423b1 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2729,47 +2729,35 @@ vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
 /*
  * Enable MSIx vectors.
  * Returns :
- *	0 on successful enabling of required vectors,
  *	VMXNET3_LINUX_MIN_MSIX_VECT when only minimum number of vectors required
- *	 could be enabled.
- *	number of vectors which can be enabled otherwise (this number is smaller
+ *	 were enabled.
+ *	number of vectors which were enabled otherwise (this number is greater
  *	 than VMXNET3_LINUX_MIN_MSIX_VECT)
  */
 
 static int
-vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter,
-			     int vectors)
-{
-	int err = 0, vector_threshold;
-	vector_threshold = VMXNET3_LINUX_MIN_MSIX_VECT;
-
-	while (vectors >= vector_threshold) {
-		err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
-				      vectors);
-		if (!err) {
-			adapter->intr.num_intrs = vectors;
-			return 0;
-		} else if (err < 0) {
-			dev_err(&adapter->netdev->dev,
-				   "Failed to enable MSI-X, error: %d\n", err);
-			vectors = 0;
-		} else if (err < vector_threshold) {
-			break;
-		} else {
-			/* If fails to enable required number of MSI-x vectors
-			 * try enabling minimum number of vectors required.
-			 */
-			dev_err(&adapter->netdev->dev,
-				"Failed to enable %d MSI-X, trying %d instead\n",
-				    vectors, vector_threshold);
-			vectors = vector_threshold;
-		}
+vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter, int nvec)
+{
+	int ret = pci_enable_msix_range(adapter->pdev,
+					adapter->intr.msix_entries, nvec, nvec);
+
+	if (ret == -ENOSPC && nvec > VMXNET3_LINUX_MIN_MSIX_VECT) {
+		dev_err(&adapter->netdev->dev,
+			"Failed to enable %d MSI-X, trying %d\n",
+			nvec, VMXNET3_LINUX_MIN_MSIX_VECT);
+
+		ret = pci_enable_msix_range(adapter->pdev,
+					    adapter->intr.msix_entries,
+					    VMXNET3_LINUX_MIN_MSIX_VECT,
+					    VMXNET3_LINUX_MIN_MSIX_VECT);
 	}
 
-	dev_info(&adapter->pdev->dev,
-		 "Number of MSI-X interrupts which can be allocated "
-		 "is lower than min threshold required.\n");
-	return err;
+	if (ret < 0) {
+		dev_err(&adapter->netdev->dev,
+			"Failed to enable MSI-X, error: %d\n", ret);
+	}
+
+	return ret;
 }
 
 
@@ -2796,56 +2784,50 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 
 #ifdef CONFIG_PCI_MSI
 	if (adapter->intr.type == VMXNET3_IT_MSIX) {
-		int vector, err = 0;
-
-		adapter->intr.num_intrs = (adapter->share_intr ==
-					   VMXNET3_INTR_TXSHARE) ? 1 :
-					   adapter->num_tx_queues;
-		adapter->intr.num_intrs += (adapter->share_intr ==
-					   VMXNET3_INTR_BUDDYSHARE) ? 0 :
-					   adapter->num_rx_queues;
-		adapter->intr.num_intrs += 1;		/* for link event */
-
-		adapter->intr.num_intrs = (adapter->intr.num_intrs >
-					   VMXNET3_LINUX_MIN_MSIX_VECT
-					   ? adapter->intr.num_intrs :
-					   VMXNET3_LINUX_MIN_MSIX_VECT);
-
-		for (vector = 0; vector < adapter->intr.num_intrs; vector++)
-			adapter->intr.msix_entries[vector].entry = vector;
-
-		err = vmxnet3_acquire_msix_vectors(adapter,
-						   adapter->intr.num_intrs);
+		int i, nvec;
+
+		nvec  = adapter->share_intr == VMXNET3_INTR_TXSHARE ?
+			1 : adapter->num_tx_queues;
+		nvec += adapter->share_intr == VMXNET3_INTR_BUDDYSHARE ?
+			0 : adapter->num_rx_queues;
+		nvec += 1;	/* for link event */
+		nvec = nvec > VMXNET3_LINUX_MIN_MSIX_VECT ?
+		       nvec : VMXNET3_LINUX_MIN_MSIX_VECT;
+
+		for (i = 0; i < nvec; i++)
+			adapter->intr.msix_entries[i].entry = i;
+
+		nvec = vmxnet3_acquire_msix_vectors(adapter, nvec);
+		if (nvec < 0)
+			goto msix_err;
+
 		/* If we cannot allocate one MSIx vector per queue
 		 * then limit the number of rx queues to 1
 		 */
-		if (err == VMXNET3_LINUX_MIN_MSIX_VECT) {
+		if (nvec == VMXNET3_LINUX_MIN_MSIX_VECT) {
 			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE
 			    || adapter->num_rx_queues != 1) {
 				adapter->share_intr = VMXNET3_INTR_TXSHARE;
 				netdev_err(adapter->netdev,
 					   "Number of rx queues : 1\n");
 				adapter->num_rx_queues = 1;
-				adapter->intr.num_intrs =
-						VMXNET3_LINUX_MIN_MSIX_VECT;
 			}
-			return;
 		}
-		if (!err)
-			return;
 
+		adapter->intr.num_intrs = nvec;
+		return;
+
+msix_err:
 		/* If we cannot allocate MSIx vectors use only one rx queue */
 		dev_info(&adapter->pdev->dev,
 			 "Failed to enable MSI-X, error %d. "
-			 "Limiting #rx queues to 1, try MSI.\n", err);
+			 "Limiting #rx queues to 1, try MSI.\n", nvec);
 
 		adapter->intr.type = VMXNET3_IT_MSI;
 	}
 
 	if (adapter->intr.type == VMXNET3_IT_MSI) {
-		int err;
-		err = pci_enable_msi(adapter->pdev);
-		if (!err) {
+		if (!pci_enable_msi(adapter->pdev)) {
 			adapter->num_rx_queues = 1;
 			adapter->intr.num_intrs = 1;
 			return;
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index b0f705c2378f..eb59b14d5ee0 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1132,7 +1132,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
 	struct vxlan_sock *vs;
 	struct vxlanhdr *vxh;
-	__be16 port;
 
 	/* Need Vxlan and inner Ethernet header to be present */
 	if (!pskb_may_pull(skb, VXLAN_HLEN))
@@ -1150,8 +1149,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB)))
 		goto drop;
 
-	port = inet_sk(sk)->inet_sport;
-
 	vs = rcu_dereference_sk_user_data(sk);
 	if (!vs)
 		goto drop;
@@ -1978,19 +1975,11 @@ static int vxlan_init(struct net_device *dev)
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
 	struct vxlan_sock *vs;
-	int i;
 
-	dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
+	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
 	if (!dev->tstats)
 		return -ENOMEM;
 
-	for_each_possible_cpu(i) {
-		struct pcpu_sw_netstats *vxlan_stats;
-		vxlan_stats = per_cpu_ptr(dev->tstats, i);
-		u64_stats_init(&vxlan_stats->syncp);
-	}
-
-
 	spin_lock(&vn->sock_lock);
 	vs = vxlan_find_sock(dev_net(dev), vxlan->dst_port);
 	if (vs) {
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index b59cfbe0276b..6260b834a86f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -161,6 +161,8 @@ struct ath_common {
 	bool btcoex_enabled;
 	bool disable_ani;
 	bool bt_ant_diversity;
+
+	int last_rssi;
 };
 
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 74f45fa6f428..27f20e0510f7 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -204,7 +204,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
 			break;
 		/* 80MHZ */
 		case 2:
-			status->flag |= RX_FLAG_80MHZ;
+			status->vht_flag |= RX_VHT_FLAG_80MHZ;
 		}
 
 		status->flag |= RX_FLAG_VHT;
@@ -266,7 +266,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
 		   status->flag & RX_FLAG_HT ? "ht" : "",
 		   status->flag & RX_FLAG_VHT ? "vht" : "",
 		   status->flag & RX_FLAG_40MHZ ? "40" : "",
-		   status->flag & RX_FLAG_80MHZ ? "80" : "",
+		   status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
 		   status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
 		   status->rate_idx,
 		   status->vht_nss,
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index fd4c89df67e1..c2c6f4604958 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
 	if (nw_type & ADHOC_NETWORK) {
 		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
 			   nw_type & ADHOC_CREATOR ? "creator" : "joiner");
-		cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
+		cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
 		cfg80211_put_bss(ar->wiphy, bss);
 		return;
 	}
@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
 	}
 
 	if (vif->nw_type & ADHOC_NETWORK) {
-		if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
+		if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
 			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 				   "%s: ath6k not in ibss mode\n", __func__);
-			return;
-		}
-		memset(bssid, 0, ETH_ALEN);
-		cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
 		return;
 	}
 
@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 	struct ath6kl_vif *vif = netdev_priv(dev);
 	u16 interval;
 	int ret, rssi_thold;
+	int n_match_sets = request->n_match_sets;
+
+	/*
+	 * If there's a matchset w/o an SSID, then assume it's just for
+	 * the RSSI (nothing else is currently supported) and ignore it.
+	 * The device only supports a global RSSI filter that we set below.
+	 */
+	if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
+		n_match_sets = 0;
 
 	if (ar->state != ATH6KL_STATE_ON)
 		return -EIO;
@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
 				      request->n_ssids,
 				      request->match_sets,
-				      request->n_match_sets);
+				      n_match_sets);
 	if (ret < 0)
 		return ret;
 
-	if (!request->n_match_sets) {
+	if (!n_match_sets) {
 		ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
 					       ALL_BSS_FILTER, 0);
 		if (ret < 0)
@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 
 	if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
 		     ar->fw_capabilities)) {
-		if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
+		if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
 			rssi_thold = 0;
-		else if (request->rssi_thold < -127)
+		else if (request->min_rssi_thold < -127)
 			rssi_thold = -127;
 		else
-			rssi_thold = request->rssi_thold;
+			rssi_thold = request->min_rssi_thold;
 
 		ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
 						     rssi_thold);
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 7b96b3e5712d..8fcc029a76a6 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -120,18 +120,6 @@ config ATH9K_WOW
 	  This option enables Wake on Wireless LAN support for certain cards.
 	  Currently, AR9462 is supported.
 
-config ATH9K_LEGACY_RATE_CONTROL
-	bool "Atheros ath9k rate control"
-	depends on ATH9K
-	default n
-	---help---
-	  Say Y, if you want to use the ath9k specific rate control
-	  module instead of minstrel_ht. Be warned that there are various
-	  issues with the ath9k RC and minstrel is a more robust algorithm.
-	  Note that even if this option is selected, "ath9k_rate_control"
-	  has to be passed to mac80211 using the module parameter,
-	  ieee80211_default_rc_algo.
-
 config ATH9K_RFKILL
 	bool "Atheros ath9k rfkill support" if EXPERT
 	depends on ATH9K
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index a40e5c5d7418..747975e1860a 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -8,7 +8,6 @@ ath9k-y +=	beacon.o \
 		antenna.o
 
 ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
-ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index a352128c40ad..ac8301ef5242 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -23,10 +23,11 @@
 #define MAX_MEASUREMENT	MAX_IQCAL_MEASUREMENT
 #define MAX_MAG_DELTA	11
 #define MAX_PHS_DELTA	10
+#define MAXIQCAL        3
 
 struct coeff {
-	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
-	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
+	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
 	int iqc_coeff[2];
 };
 
@@ -655,9 +656,6 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 	if (i2_m_q2_a0_d1 > 0x800)
 		i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
 
-	if (i2_p_q2_a0_d1 > 0x1000)
-		i2_p_q2_a0_d1 = -((0x1fff - i2_p_q2_a0_d1) + 1);
-
 	if (iq_corr_a0_d1 > 0x800)
 		iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
 
@@ -800,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 	if (q_q_coff > 63)
 		q_q_coff = 63;
 
-	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
+	iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
 
 	ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
 		chain_idx, iqc_coeff[0]);
@@ -831,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 	if (q_q_coff > 63)
 		q_q_coff = 63;
 
-	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
+	iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
 
 	ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
 		chain_idx, iqc_coeff[1]);
@@ -839,7 +837,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 	return true;
 }
 
-static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
+				     int nmeasurement,
 				     int max_delta)
 {
 	int mp_max = -64, max_idx = 0;
@@ -848,20 +847,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 
 	/* find min/max mismatch across all calibrated gains */
 	for (i = 0; i < nmeasurement; i++) {
-		if (mp_coeff[i] > mp_max) {
-			mp_max = mp_coeff[i];
+		if (mp_coeff[i][0] > mp_max) {
+			mp_max = mp_coeff[i][0];
 			max_idx = i;
-		} else if (mp_coeff[i] < mp_min) {
-			mp_min = mp_coeff[i];
+		} else if (mp_coeff[i][0] < mp_min) {
+			mp_min = mp_coeff[i][0];
 			min_idx = i;
 		}
 	}
 
 	/* find average (exclude max abs value) */
 	for (i = 0; i < nmeasurement; i++) {
-		if ((abs(mp_coeff[i]) < abs(mp_max)) ||
-		    (abs(mp_coeff[i]) < abs(mp_min))) {
-			mp_avg += mp_coeff[i];
+		if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
+		    (abs(mp_coeff[i][0]) < abs(mp_min))) {
+			mp_avg += mp_coeff[i][0];
 			mp_count++;
 		}
 	}
@@ -873,7 +872,7 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 	if (mp_count)
 		mp_avg /= mp_count;
 	else
-		mp_avg = mp_coeff[nmeasurement - 1];
+		mp_avg = mp_coeff[nmeasurement - 1][0];
 
 	/* detect outlier */
 	if (abs(mp_max - mp_min) > max_delta) {
@@ -882,15 +881,16 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 		else
 			outlier_idx = min_idx;
 
-		mp_coeff[outlier_idx] = mp_avg;
+		mp_coeff[outlier_idx][0] = mp_avg;
 	}
 }
 
-static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
-						 struct coeff *coeff,
-						 bool is_reusable)
+static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
+						  struct coeff *coeff,
+						  bool is_reusable)
 {
 	int i, im, nmeasurement;
+	int magnitude, phase;
 	u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 
@@ -920,21 +920,30 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
 		if (nmeasurement > MAX_MEASUREMENT)
 			nmeasurement = MAX_MEASUREMENT;
 
-		/* detect outlier only if nmeasurement > 1 */
-		if (nmeasurement > 1) {
-			/* Detect magnitude outlier */
-			ar9003_hw_detect_outlier(coeff->mag_coeff[i],
-					nmeasurement, MAX_MAG_DELTA);
-
-			/* Detect phase outlier */
-			ar9003_hw_detect_outlier(coeff->phs_coeff[i],
-					nmeasurement, MAX_PHS_DELTA);
+		/*
+		 * Skip normal outlier detection for AR9550.
+		 */
+		if (!AR_SREV_9550(ah)) {
+			/* detect outlier only if nmeasurement > 1 */
+			if (nmeasurement > 1) {
+				/* Detect magnitude outlier */
+				ar9003_hw_detect_outlier(coeff->mag_coeff[i],
+							 nmeasurement,
+							 MAX_MAG_DELTA);
+
+				/* Detect phase outlier */
+				ar9003_hw_detect_outlier(coeff->phs_coeff[i],
+							 nmeasurement,
+							 MAX_PHS_DELTA);
+			}
 		}
 
 		for (im = 0; im < nmeasurement; im++) {
+			magnitude = coeff->mag_coeff[i][im][0];
+			phase = coeff->phs_coeff[i][im][0];
 
-			coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
-				((coeff->phs_coeff[i][im] & 0x7f) << 7);
+			coeff->iqc_coeff[0] =
+				(phase & 0x7f) | ((magnitude & 0x7f) << 7);
 
 			if ((im % 2) == 0)
 				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
@@ -991,7 +1000,63 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
 	return true;
 }
 
-static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
+				    struct coeff *coeff,
+				    int i, int nmeasurement)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	int im, ix, iy, temp;
+
+	for (im = 0; im < nmeasurement; im++) {
+		for (ix = 0; ix < MAXIQCAL - 1; ix++) {
+			for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
+				if (coeff->mag_coeff[i][im][iy] <
+				    coeff->mag_coeff[i][im][ix]) {
+					temp = coeff->mag_coeff[i][im][ix];
+					coeff->mag_coeff[i][im][ix] =
+						coeff->mag_coeff[i][im][iy];
+					coeff->mag_coeff[i][im][iy] = temp;
+				}
+				if (coeff->phs_coeff[i][im][iy] <
+				    coeff->phs_coeff[i][im][ix]) {
+					temp = coeff->phs_coeff[i][im][ix];
+					coeff->phs_coeff[i][im][ix] =
+						coeff->phs_coeff[i][im][iy];
+					coeff->phs_coeff[i][im][iy] = temp;
+				}
+			}
+		}
+		coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
+		coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
+
+		ath_dbg(common, CALIBRATE,
+			"IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
+			i, im,
+			coeff->mag_coeff[i][im][0],
+			coeff->phs_coeff[i][im][0]);
+	}
+}
+
+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
+				    struct coeff *coeff,
+				    int iqcal_idx,
+				    int nmeasurement)
+{
+	int i;
+
+	if ((iqcal_idx + 1) != MAXIQCAL)
+		return false;
+
+	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+		__ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
+	}
+
+	return true;
+}
+
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
+					  int iqcal_idx,
+					  bool is_reusable)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
@@ -1004,10 +1069,11 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 		AR_PHY_CHAN_INFO_TAB_1,
 		AR_PHY_CHAN_INFO_TAB_2,
 	};
-	struct coeff coeff;
+	static struct coeff coeff;
 	s32 iq_res[6];
 	int i, im, j;
-	int nmeasurement;
+	int nmeasurement = 0;
+	bool outlier_detect = true;
 
 	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 		if (!(ah->txchainmask & (1 << i)))
@@ -1065,17 +1131,23 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 				goto tx_iqcal_fail;
 			}
 
-			coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
-			coeff.phs_coeff[i][im] =
+			coeff.phs_coeff[i][im][iqcal_idx] =
+				coeff.iqc_coeff[0] & 0x7f;
+			coeff.mag_coeff[i][im][iqcal_idx] =
 				(coeff.iqc_coeff[0] >> 7) & 0x7f;
 
-			if (coeff.mag_coeff[i][im] > 63)
-				coeff.mag_coeff[i][im] -= 128;
-			if (coeff.phs_coeff[i][im] > 63)
-				coeff.phs_coeff[i][im] -= 128;
+			if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
+				coeff.mag_coeff[i][im][iqcal_idx] -= 128;
+			if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
+				coeff.phs_coeff[i][im][iqcal_idx] -= 128;
 		}
 	}
-	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
+
+	if (AR_SREV_9550(ah))
+		outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
+							 iqcal_idx, nmeasurement);
+	if (outlier_detect)
+		ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
 
 	return;
 
@@ -1409,7 +1481,7 @@ skip_tx_iqcal:
 	}
 
 	if (txiqcal_done)
-		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+		ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
 	else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
 		ar9003_hw_tx_iq_cal_reload(ah);
 
@@ -1455,14 +1527,38 @@ skip_tx_iqcal:
 	return true;
 }
 
+static bool do_ar9003_agc_cal(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	bool status;
+
+	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
+		  AR_PHY_AGC_CONTROL_CAL);
+
+	status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+			       AR_PHY_AGC_CONTROL_CAL,
+			       0, AH_WAIT_TIMEOUT);
+	if (!status) {
+		ath_dbg(common, CALIBRATE,
+			"offset calibration failed to complete in %d ms,"
+			"noisy environment?\n",
+			AH_WAIT_TIMEOUT / 1000);
+		return false;
+	}
+
+	return true;
+}
+
 static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 				   struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 	bool txiqcal_done = false;
-	bool is_reusable = true, status = true;
+	bool status = true;
 	bool run_agc_cal = false, sep_iq_cal = false;
+	int i = 0;
 
 	/* Use chip chainmask only for calibration */
 	ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
@@ -1485,7 +1581,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 	 * AGC calibration. Specifically, AR9550 in SoC chips.
 	 */
 	if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
-		txiqcal_done = true;
+		if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+				   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
+				txiqcal_done = true;
+		} else {
+			txiqcal_done = false;
+		}
 		run_agc_cal = true;
 	} else {
 		sep_iq_cal = true;
@@ -1512,27 +1613,37 @@ skip_tx_iqcal:
 		if (AR_SREV_9330_11(ah))
 			ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
 
-		/* Calibrate the AGC */
-		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
-			  AR_PHY_AGC_CONTROL_CAL);
-
-		/* Poll for offset calibration complete */
-		status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-				       AR_PHY_AGC_CONTROL_CAL,
-				       0, AH_WAIT_TIMEOUT);
-	}
+		/*
+		 * For non-AR9550 chips, we just trigger AGC calibration
+		 * in the HW, poll for completion and then process
+		 * the results.
+		 *
+		 * For AR955x, we run it multiple times and use
+		 * median IQ correction.
+		 */
+		if (!AR_SREV_9550(ah)) {
+			status = do_ar9003_agc_cal(ah);
+			if (!status)
+				return false;
 
-	if (!status) {
-		ath_dbg(common, CALIBRATE,
-			"offset calibration failed to complete in %d ms; noisy environment?\n",
-			AH_WAIT_TIMEOUT / 1000);
-		return false;
+			if (txiqcal_done)
+				ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
+		} else {
+			if (!txiqcal_done) {
+				status = do_ar9003_agc_cal(ah);
+				if (!status)
+					return false;
+			} else {
+				for (i = 0; i < MAXIQCAL; i++) {
+					status = do_ar9003_agc_cal(ah);
+					if (!status)
+						return false;
+					ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
+				}
+			}
+		}
 	}
 
-	if (txiqcal_done)
-		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
-
 	/* Revert chainmask to runtime parameters */
 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index 1cc13569b17b..1b6b4d0cfa97 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -57,7 +57,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
 	{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
 	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
-	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
 	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
 	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
 	{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
@@ -96,7 +96,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
 	{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
 	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-	{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+	{0x0000ae20, 0x000001a6, 0x000001a6, 0x000001aa, 0x000001aa},
 	{0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index b5ac32cfbeb8..21d13bc99c5a 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -30,7 +30,6 @@
 #include "spectral.h"
 
 struct ath_node;
-struct ath_rate_table;
 
 extern struct ieee80211_ops ath9k_ops;
 extern int ath9k_modparam_nohwcrypt;
@@ -150,6 +149,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 #define IS_CCK_RATE(rate)  ((rate >= 0x18) && (rate <= 0x1e))
 #define IS_OFDM_RATE(rate) ((rate >= 0x8) && (rate <= 0xf))
 
+enum {
+       WLAN_RC_PHY_OFDM,
+       WLAN_RC_PHY_CCK,
+};
+
 struct ath_txq {
 	int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
 	u32 axq_qnum; /* ath9k hardware queue number */
@@ -442,7 +446,8 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
 void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_set_beacon(struct ath_softc *sc);
-bool ath9k_csa_is_finished(struct ath_softc *sc);
+bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_csa_update(struct ath_softc *sc);
 
 /*******************/
 /* Link Monitoring */
@@ -757,7 +762,6 @@ struct ath_softc {
 #endif
 
 	struct ath9k_hw_cal_data caldata;
-	int last_rssi;
 
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
@@ -774,7 +778,6 @@ struct ath_softc {
 #endif
 
 	struct ath_descdma txsdma;
-	struct ieee80211_vif *csa_vif;
 
 	struct ath_ant_comb ant_comb;
 	u8 ant_tx, ant_rx;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 2e8bba0eb361..32d00e8cfd0c 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -292,11 +292,8 @@ static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
 		(unsigned long long)tsfadjust, avp->av_bslot);
 }
 
-bool ath9k_csa_is_finished(struct ath_softc *sc)
+bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
-	struct ieee80211_vif *vif;
-
-	vif = sc->csa_vif;
 	if (!vif || !vif->csa_active)
 		return false;
 
@@ -304,11 +301,23 @@ bool ath9k_csa_is_finished(struct ath_softc *sc)
 		return false;
 
 	ieee80211_csa_finish(vif);
-
-	sc->csa_vif = NULL;
 	return true;
 }
 
+static void ath9k_csa_update_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = data;
+	ath9k_csa_is_finished(sc, vif);
+}
+
+void ath9k_csa_update(struct ath_softc *sc)
+{
+	ieee80211_iterate_active_interfaces(sc->hw,
+					    IEEE80211_IFACE_ITER_NORMAL,
+					    ath9k_csa_update_vif,
+					    sc);
+}
+
 void ath9k_beacon_tasklet(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
@@ -362,13 +371,13 @@ void ath9k_beacon_tasklet(unsigned long data)
 		return;
 	}
 
-	/* EDMA devices check that in the tx completion function. */
-	if (!edma && ath9k_csa_is_finished(sc))
-		return;
-
 	slot = ath9k_beacon_choose_slot(sc);
 	vif = sc->beacon.bslot[slot];
 
+	/* EDMA devices check that in the tx completion function. */
+	if (!edma && ath9k_csa_is_finished(sc, vif))
+		return;
+
 	if (!vif || !vif->bss_conf.enable_beacon)
 		return;
 
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 768c733cad31..c6dd7f1fed65 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,6 +27,250 @@ MODULE_AUTHOR("Atheros Communications");
 MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
 MODULE_LICENSE("Dual BSD/GPL");
 
+/* Assumes you've already done the endian to CPU conversion */
+bool ath9k_cmn_rx_accept(struct ath_common *common,
+			 struct ieee80211_hdr *hdr,
+			 struct ieee80211_rx_status *rxs,
+			 struct ath_rx_status *rx_stats,
+			 bool *decrypt_error,
+			 unsigned int rxfilter)
+{
+	struct ath_hw *ah = common->ah;
+	bool is_mc, is_valid_tkip, strip_mic, mic_error;
+	__le16 fc;
+
+	fc = hdr->frame_control;
+
+	is_mc = !!is_multicast_ether_addr(hdr->addr1);
+	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+	strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+		ieee80211_has_protected(fc) &&
+		!(rx_stats->rs_status &
+		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
+		 ATH9K_RXERR_KEYMISS));
+
+	/*
+	 * Key miss events are only relevant for pairwise keys where the
+	 * descriptor does contain a valid key index. This has been observed
+	 * mostly with CCMP encryption.
+	 */
+	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
+	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
+		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
+	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+		!ieee80211_has_morefrags(fc) &&
+		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+		(rx_stats->rs_status & ATH9K_RXERR_MIC);
+
+	/*
+	 * The rx_stats->rs_status will not be set until the end of the
+	 * chained descriptors so it can be ignored if rs_more is set. The
+	 * rs_more will be false at the last element of the chained
+	 * descriptors.
+	 */
+	if (rx_stats->rs_status != 0) {
+		u8 status_mask;
+
+		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
+			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+			mic_error = false;
+		}
+
+		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
+		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
+			*decrypt_error = true;
+			mic_error = false;
+		}
+
+
+		/*
+		 * Reject error frames with the exception of
+		 * decryption and MIC failures. For monitor mode,
+		 * we also ignore the CRC error.
+		 */
+		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+			      ATH9K_RXERR_KEYMISS;
+
+		if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
+			status_mask |= ATH9K_RXERR_CRC;
+
+		if (rx_stats->rs_status & ~status_mask)
+			return false;
+	}
+
+	/*
+	 * For unicast frames the MIC error bit can have false positives,
+	 * so all MIC error reports need to be validated in software.
+	 * False negatives are not common, so skip software verification
+	 * if the hardware considers the MIC valid.
+	 */
+	if (strip_mic)
+		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+	else if (is_mc && mic_error)
+		rxs->flag |= RX_FLAG_MMIC_ERROR;
+
+	return true;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_accept);
+
+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+				  struct sk_buff *skb,
+				  struct ath_rx_status *rx_stats,
+				  struct ieee80211_rx_status *rxs,
+				  bool decrypt_error)
+{
+	struct ath_hw *ah = common->ah;
+	struct ieee80211_hdr *hdr;
+	int hdrlen, padpos, padsize;
+	u8 keyix;
+	__le16 fc;
+
+	/* see if any padding is done by the hw and remove it */
+	hdr = (struct ieee80211_hdr *) skb->data;
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	fc = hdr->frame_control;
+	padpos = ieee80211_hdrlen(fc);
+
+	/* The MAC header is padded to have 32-bit boundary if the
+	 * packet payload is non-zero. The general calculation for
+	 * padsize would take into account odd header lengths:
+	 * padsize = (4 - padpos % 4) % 4; However, since only
+	 * even-length headers are used, padding can only be 0 or 2
+	 * bytes and we can optimize this a bit. In addition, we must
+	 * not try to remove padding from short control frames that do
+	 * not have payload. */
+	padsize = padpos & 3;
+	if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
+		memmove(skb->data + padsize, skb->data, padpos);
+		skb_pull(skb, padsize);
+	}
+
+	keyix = rx_stats->rs_keyix;
+
+	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
+	    ieee80211_has_protected(fc)) {
+		rxs->flag |= RX_FLAG_DECRYPTED;
+	} else if (ieee80211_has_protected(fc)
+		   && !decrypt_error && skb->len >= hdrlen + 4) {
+		keyix = skb->data[hdrlen + 3] >> 6;
+
+		if (test_bit(keyix, common->keymap))
+			rxs->flag |= RX_FLAG_DECRYPTED;
+	}
+	if (ah->sw_mgmt_crypto &&
+	    (rxs->flag & RX_FLAG_DECRYPTED) &&
+	    ieee80211_is_mgmt(fc))
+		/* Use software decrypt for management frames. */
+		rxs->flag &= ~RX_FLAG_DECRYPTED;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
+
+int ath9k_cmn_process_rate(struct ath_common *common,
+			   struct ieee80211_hw *hw,
+			   struct ath_rx_status *rx_stats,
+			   struct ieee80211_rx_status *rxs)
+{
+	struct ieee80211_supported_band *sband;
+	enum ieee80211_band band;
+	unsigned int i = 0;
+	struct ath_hw *ah = common->ah;
+
+	band = ah->curchan->chan->band;
+	sband = hw->wiphy->bands[band];
+
+	if (IS_CHAN_QUARTER_RATE(ah->curchan))
+		rxs->flag |= RX_FLAG_5MHZ;
+	else if (IS_CHAN_HALF_RATE(ah->curchan))
+		rxs->flag |= RX_FLAG_10MHZ;
+
+	if (rx_stats->rs_rate & 0x80) {
+		/* HT rate */
+		rxs->flag |= RX_FLAG_HT;
+		rxs->flag |= rx_stats->flag;
+		rxs->rate_idx = rx_stats->rs_rate & 0x7f;
+		return 0;
+	}
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
+			rxs->rate_idx = i;
+			return 0;
+		}
+		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
+			rxs->flag |= RX_FLAG_SHORTPRE;
+			rxs->rate_idx = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(ath9k_cmn_process_rate);
+
+void ath9k_cmn_process_rssi(struct ath_common *common,
+			    struct ieee80211_hw *hw,
+			    struct ath_rx_status *rx_stats,
+			    struct ieee80211_rx_status *rxs)
+{
+	struct ath_hw *ah = common->ah;
+	int last_rssi;
+	int rssi = rx_stats->rs_rssi;
+	int i, j;
+
+	/*
+	 * RSSI is not available for subframes in an A-MPDU.
+	 */
+	if (rx_stats->rs_moreaggr) {
+		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
+		return;
+	}
+
+	/*
+	 * Check if the RSSI for the last subframe in an A-MPDU
+	 * or an unaggregated frame is valid.
+	 */
+	if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
+		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
+		return;
+	}
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
+		s8 rssi;
+
+		if (!(ah->rxchainmask & BIT(i)))
+			continue;
+
+		rssi = rx_stats->rs_rssi_ctl[i];
+		if (rssi != ATH9K_RSSI_BAD) {
+		    rxs->chains |= BIT(j);
+		    rxs->chain_signal[j] = ah->noise + rssi;
+		}
+		j++;
+	}
+
+	/*
+	 * Update Beacon RSSI, this is used by ANI.
+	 */
+	if (rx_stats->is_mybeacon &&
+	    ((ah->opmode == NL80211_IFTYPE_STATION) ||
+	     (ah->opmode == NL80211_IFTYPE_ADHOC))) {
+		ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
+		last_rssi = common->last_rssi;
+
+		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+		if (rssi < 0)
+			rssi = 0;
+
+		ah->stats.avgbrssi = rssi;
+	}
+
+	rxs->signal = ah->noise + rx_stats->rs_rssi;
+}
+EXPORT_SYMBOL(ath9k_cmn_process_rssi);
+
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index eb85e1bdca88..38b5609a4018 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,6 +42,25 @@
 #define ATH_EP_RND(x, mul) 						\
 	(((x) + ((mul)/2)) / (mul))
 
+bool ath9k_cmn_rx_accept(struct ath_common *common,
+			 struct ieee80211_hdr *hdr,
+			 struct ieee80211_rx_status *rxs,
+			 struct ath_rx_status *rx_stats,
+			 bool *decrypt_error,
+			 unsigned int rxfilter);
+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+				  struct sk_buff *skb,
+				  struct ath_rx_status *rx_stats,
+				  struct ieee80211_rx_status *rxs,
+				  bool decrypt_error);
+int ath9k_cmn_process_rate(struct ath_common *common,
+			   struct ieee80211_hw *hw,
+			   struct ath_rx_status *rx_stats,
+			   struct ieee80211_rx_status *rxs);
+void ath9k_cmn_process_rssi(struct ath_common *common,
+			    struct ieee80211_hw *hw,
+			    struct ath_rx_status *rx_stats,
+			    struct ieee80211_rx_status *rxs);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
 struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
 					    struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cc7a025d833e..559a68c2709c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -18,7 +18,6 @@
 #define DEBUG_H
 
 #include "hw.h"
-#include "rc.h"
 #include "dfs_debug.h"
 
 struct ath_txq;
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h
index 0a7ddf4c88c9..7936c9126a20 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h
@@ -21,6 +21,8 @@
 
 #include "hw.h"
 
+struct ath_softc;
+
 /**
  * struct ath_dfs_stats - DFS Statistics per wiphy
  * @pulses_total:     pulses reported by HW
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 6d5d716adc1b..8e7153b186ed 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -54,6 +54,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
 	  .driver_info = AR9280_USB },  /* SMC Networks */
 	{ USB_DEVICE(0x0411, 0x017f),
 	  .driver_info = AR9280_USB },  /* Sony UWA-BR100 */
+	{ USB_DEVICE(0x0411, 0x0197),
+	  .driver_info = AR9280_USB },  /* Buffalo WLI-UV-AG300P */
 	{ USB_DEVICE(0x04da, 0x3904),
 	  .driver_info = AR9280_USB },
 
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 99a203174f45..ba83f582bf4a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -277,7 +277,6 @@ struct ath9k_htc_rxbuf {
 };
 
 struct ath9k_htc_rx {
-	int last_rssi; /* FIXME: per-STA */
 	struct list_head rxbuf;
 	spinlock_t rxbuflock;
 };
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index c57d6b859c04..8d0b9bcb47b4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -611,6 +611,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
 
 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 
+	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	priv->ah->opmode = NL80211_IFTYPE_STATION;
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index c9254a61ca52..90dad4172b0a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1474,6 +1474,7 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 
 	if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
 		common->curaid = bss_conf->aid;
+		common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
 	}
 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 12e0f32a4905..47b2bfcd8223 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -927,43 +927,39 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
 	ath9k_hw_rxena(priv->ah);
 	ath9k_htc_opmode_init(priv);
 	ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
-	priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
 }
 
-static void ath9k_process_rate(struct ieee80211_hw *hw,
-			       struct ieee80211_rx_status *rxs,
-			       u8 rx_rate, u8 rs_flags)
+static inline void convert_htc_flag(struct ath_rx_status *rx_stats,
+				   struct ath_htc_rx_status *rxstatus)
 {
-	struct ieee80211_supported_band *sband;
-	enum ieee80211_band band;
-	unsigned int i = 0;
-
-	if (rx_rate & 0x80) {
-		/* HT rate */
-		rxs->flag |= RX_FLAG_HT;
-		if (rs_flags & ATH9K_RX_2040)
-			rxs->flag |= RX_FLAG_40MHZ;
-		if (rs_flags & ATH9K_RX_GI)
-			rxs->flag |= RX_FLAG_SHORT_GI;
-		rxs->rate_idx = rx_rate & 0x7f;
-		return;
-	}
-
-	band = hw->conf.chandef.chan->band;
-	sband = hw->wiphy->bands[band];
-
-	for (i = 0; i < sband->n_bitrates; i++) {
-		if (sband->bitrates[i].hw_value == rx_rate) {
-			rxs->rate_idx = i;
-			return;
-		}
-		if (sband->bitrates[i].hw_value_short == rx_rate) {
-			rxs->rate_idx = i;
-			rxs->flag |= RX_FLAG_SHORTPRE;
-			return;
-		}
-	}
+	rx_stats->flag = 0;
+	if (rxstatus->rs_flags & ATH9K_RX_2040)
+		rx_stats->flag |= RX_FLAG_40MHZ;
+	if (rxstatus->rs_flags & ATH9K_RX_GI)
+		rx_stats->flag |= RX_FLAG_SHORT_GI;
+}
 
+static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
+				 struct ath_htc_rx_status *rxstatus)
+{
+	rx_stats->rs_datalen	= rxstatus->rs_datalen;
+	rx_stats->rs_status	= rxstatus->rs_status;
+	rx_stats->rs_phyerr	= rxstatus->rs_phyerr;
+	rx_stats->rs_rssi	= rxstatus->rs_rssi;
+	rx_stats->rs_keyix	= rxstatus->rs_keyix;
+	rx_stats->rs_rate	= rxstatus->rs_rate;
+	rx_stats->rs_antenna	= rxstatus->rs_antenna;
+	rx_stats->rs_more	= rxstatus->rs_more;
+
+	memcpy(rx_stats->rs_rssi_ctl, rxstatus->rs_rssi_ctl,
+		sizeof(rx_stats->rs_rssi_ctl));
+	memcpy(rx_stats->rs_rssi_ext, rxstatus->rs_rssi_ext,
+		sizeof(rx_stats->rs_rssi_ext));
+
+	rx_stats->rs_isaggr	= rxstatus->rs_isaggr;
+	rx_stats->rs_moreaggr	= rxstatus->rs_moreaggr;
+	rx_stats->rs_num_delims	= rxstatus->rs_num_delims;
+	convert_htc_flag(rx_stats, rxstatus);
 }
 
 static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
@@ -975,10 +971,10 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 	struct ieee80211_hw *hw = priv->hw;
 	struct sk_buff *skb = rxbuf->skb;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath_hw *ah = common->ah;
 	struct ath_htc_rx_status *rxstatus;
-	int hdrlen, padsize;
-	int last_rssi = ATH_RSSI_DUMMY_MARKER;
-	__le16 fc;
+	struct ath_rx_status rx_stats;
+	bool decrypt_error;
 
 	if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
 		ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
@@ -999,103 +995,39 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 	ath9k_htc_err_stat_rx(priv, rxstatus);
 
 	/* Get the RX status information */
-	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
-	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-
-	padsize = hdrlen & 3;
-	if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
-		memmove(skb->data + padsize, skb->data, hdrlen);
-		skb_pull(skb, padsize);
-	}
 
 	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
 
-	if (rxbuf->rxstatus.rs_status != 0) {
-		if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC)
-			rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY)
-			goto rx_next;
-
-		if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) {
-			/* FIXME */
-		} else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) {
-			if (ieee80211_is_ctl(fc))
-				/*
-				 * Sometimes, we get invalid
-				 * MIC failures on valid control frames.
-				 * Remove these mic errors.
-				 */
-				rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC;
-			else
-				rx_status->flag |= RX_FLAG_MMIC_ERROR;
-		}
-
-		/*
-		 * Reject error frames with the exception of
-		 * decryption and MIC failures. For monitor mode,
-		 * we also ignore the CRC error.
-		 */
-		if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) {
-			if (rxbuf->rxstatus.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-			      ATH9K_RXERR_CRC))
-				goto rx_next;
-		} else {
-			if (rxbuf->rxstatus.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
-				goto rx_next;
-			}
-		}
-	}
-
-	if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) {
-		u8 keyix;
-		keyix = rxbuf->rxstatus.rs_keyix;
-		if (keyix != ATH9K_RXKEYIX_INVALID) {
-			rx_status->flag |= RX_FLAG_DECRYPTED;
-		} else if (ieee80211_has_protected(fc) &&
-			   skb->len >= hdrlen + 4) {
-			keyix = skb->data[hdrlen + 3] >> 6;
-			if (test_bit(keyix, common->keymap))
-				rx_status->flag |= RX_FLAG_DECRYPTED;
-		}
-	}
-
-	ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
-			   rxbuf->rxstatus.rs_flags);
-
-	if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
-	    !rxbuf->rxstatus.rs_moreaggr)
-		ATH_RSSI_LPF(priv->rx.last_rssi,
-			     rxbuf->rxstatus.rs_rssi);
-
-	last_rssi = priv->rx.last_rssi;
+	/* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
+	 * After this, we can drop this part of skb. */
+	rx_status_htc_to_ath(&rx_stats, rxstatus);
+	rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
+	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
 
-	if (ath_is_mybeacon(common, hdr)) {
-		s8 rssi = rxbuf->rxstatus.rs_rssi;
+	/*
+	 * everything but the rate is checked here, the rate check is done
+	 * separately to avoid doing two lookups for a rate for each frame.
+	 */
+	hdr = (struct ieee80211_hdr *)skb->data;
+	if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats,
+			&decrypt_error, priv->rxfilter))
+		goto rx_next;
 
-		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+	ath9k_cmn_rx_skb_postprocess(common, skb, &rx_stats,
+				     rx_status, decrypt_error);
 
-		if (rssi < 0)
-			rssi = 0;
+	if (ath9k_cmn_process_rate(common, hw, &rx_stats, rx_status))
+		goto rx_next;
 
-		priv->ah->stats.avgbrssi = rssi;
-	}
+	rx_stats.is_mybeacon = ath_is_mybeacon(common, hdr);
+	ath9k_cmn_process_rssi(common, hw, &rx_stats, rx_status);
 
-	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
-	rx_status->band = hw->conf.chandef.chan->band;
-	rx_status->freq = hw->conf.chandef.chan->center_freq;
-	rx_status->signal =  rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
-	rx_status->antenna = rxbuf->rxstatus.rs_antenna;
+	rx_status->band = ah->curchan->chan->band;
+	rx_status->freq = ah->curchan->chan->center_freq;
+	rx_status->antenna = rx_stats.rs_antenna;
 	rx_status->flag |= RX_FLAG_MACTIME_END;
 
 	return true;
-
 rx_next:
 	return false;
 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index aac4a406a513..a0ff5b637054 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -358,6 +358,36 @@ ret:
 		kfree_skb(skb);
 }
 
+static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
+				      struct sk_buff *skb)
+{
+	uint32_t *pattern = (uint32_t *)skb->data;
+
+	switch (*pattern) {
+	case 0x33221199:
+		{
+		struct htc_panic_bad_vaddr *htc_panic;
+		htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
+		dev_err(htc_handle->dev, "ath: firmware panic! "
+			"exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
+			htc_panic->exccause, htc_panic->pc,
+			htc_panic->badvaddr);
+		break;
+		}
+	case 0x33221299:
+		{
+		struct htc_panic_bad_epid *htc_panic;
+		htc_panic = (struct htc_panic_bad_epid *) skb->data;
+		dev_err(htc_handle->dev, "ath: firmware panic! "
+			"bad epid: 0x%08x\n", htc_panic->epid);
+		break;
+		}
+	default:
+		dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
+		break;
+	}
+}
+
 /*
  * HTC Messages are handled directly here and the obtained SKB
  * is freed.
@@ -379,6 +409,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
 	htc_hdr = (struct htc_frame_hdr *) skb->data;
 	epid = htc_hdr->endpoint_id;
 
+	if (epid == 0x99) {
+		ath9k_htc_fw_panic_report(htc_handle, skb);
+		kfree_skb(skb);
+		return;
+	}
+
 	if (epid >= ENDPOINT_MAX) {
 		if (pipe_id != USB_REG_IN_PIPE)
 			dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index e1ffbb6bd636..06474ccc7696 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -77,6 +77,18 @@ struct htc_config_pipe_msg {
 	u8 credits;
 } __packed;
 
+struct htc_panic_bad_vaddr {
+	__be32 pattern;
+	__be32 exccause;
+	__be32 pc;
+	__be32 badvaddr;
+} __packed;
+
+struct htc_panic_bad_epid {
+	__be32 pattern;
+	__be32 epid;
+} __packed;
+
 struct htc_ep_callbacks {
 	void *priv;
 	void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 11eab9f01fd8..2509c2ff0828 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -23,7 +23,6 @@
 
 #include "hw.h"
 #include "hw-ops.h"
-#include "rc.h"
 #include "ar9003_mac.h"
 #include "ar9003_mci.h"
 #include "ar9003_phy.h"
@@ -1534,7 +1533,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
 bool ath9k_hw_check_alive(struct ath_hw *ah)
 {
 	int count = 50;
-	u32 reg;
+	u32 reg, last_val;
 
 	if (AR_SREV_9300(ah))
 		return !ath9k_hw_detect_mac_hang(ah);
@@ -1542,9 +1541,13 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
 	if (AR_SREV_9285_12_OR_LATER(ah))
 		return true;
 
+	last_val = REG_READ(ah, AR_OBS_BUS_1);
 	do {
 		reg = REG_READ(ah, AR_OBS_BUS_1);
+		if (reg != last_val)
+			return true;
 
+		last_val = reg;
 		if ((reg & 0x7E7FFFEF) == 0x00702400)
 			continue;
 
@@ -1556,6 +1559,8 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
 		default:
 			return true;
 		}
+
+		udelay(1);
 	} while (count-- > 0);
 
 	return false;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 1fc2e5a26b52..07a0315dd2f6 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -538,7 +538,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
 
 	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
-	sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	sc->config.txpowlimit = ATH_TXPOWER_MAX;
 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
@@ -1106,19 +1106,11 @@ static int __init ath9k_init(void)
 {
 	int error;
 
-	/* Register rate control algorithm */
-	error = ath_rate_control_register();
-	if (error != 0) {
-		pr_err("Unable to register rate control algorithm: %d\n",
-		       error);
-		goto err_out;
-	}
-
 	error = ath_pci_init();
 	if (error < 0) {
 		pr_err("No PCI devices found, driver not installed\n");
 		error = -ENODEV;
-		goto err_rate_unregister;
+		goto err_out;
 	}
 
 	error = ath_ahb_init();
@@ -1131,9 +1123,6 @@ static int __init ath9k_init(void)
 
  err_pci_exit:
 	ath_pci_exit();
-
- err_rate_unregister:
-	ath_rate_control_unregister();
  err_out:
 	return error;
 }
@@ -1144,7 +1133,6 @@ static void __exit ath9k_exit(void)
 	is_ath9k_unloaded = true;
 	ath_ahb_exit();
 	ath_pci_exit();
-	ath_rate_control_unregister();
 	pr_info("%s: Driver unloaded\n", dev_info);
 }
 module_exit(ath9k_exit);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 10271373a0cd..89df634e81f9 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -155,12 +155,8 @@ struct ath_htc_rx_status {
 	u8 rs_status;
 	u8 rs_phyerr;
 	int8_t rs_rssi;
-	int8_t rs_rssi_ctl0;
-	int8_t rs_rssi_ctl1;
-	int8_t rs_rssi_ctl2;
-	int8_t rs_rssi_ext0;
-	int8_t rs_rssi_ext1;
-	int8_t rs_rssi_ext2;
+	int8_t rs_rssi_ctl[3];
+	int8_t rs_rssi_ext[3];
 	u8 rs_keyix;
 	u8 rs_rate;
 	u8 rs_antenna;
@@ -170,6 +166,7 @@ struct ath_htc_rx_status {
 	u8 rs_num_delims;
 	u8 rs_flags;
 	u8 rs_dummy;
+	/* FIXME: evm* never used? */
 	__be32 evm0;
 	__be32 evm1;
 	__be32 evm2;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5924f72dd493..afce549a097b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1178,9 +1178,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 	if (ath9k_uses_beacons(vif->type))
 		ath9k_beacon_remove_slot(sc, vif);
 
-	if (sc->csa_vif == vif)
-		sc->csa_vif = NULL;
-
 	ath9k_ps_wakeup(sc);
 	ath9k_calculate_summary_state(hw, NULL);
 	ath9k_ps_restore(sc);
@@ -1609,7 +1606,7 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
 	common->curaid = bss_conf->aid;
 	ath9k_hw_write_associd(sc->sc_ah);
 
-	sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 	spin_lock_irqsave(&sc->sc_pm_lock, flags);
@@ -1866,7 +1863,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
-	int i, npend;
+	int i, npend = 0;
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 		if (!ATH_TXQ_SETUP(sc, i))
@@ -2086,13 +2083,8 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif,
 					struct cfg80211_chan_def *chandef)
 {
-	struct ath_softc *sc = hw->priv;
-
-	/* mac80211 does not support CSA in multi-if cases (yet) */
-	if (WARN_ON(sc->csa_vif))
-		return;
-
-	sc->csa_vif = vif;
+	/* depend on vif->csa_active only */
+	return;
 }
 
 struct ieee80211_ops ath9k_ops = {
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
deleted file mode 100644
index d829bb62a3fc..000000000000
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ /dev/null
@@ -1,1495 +0,0 @@
-/*
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2004-2011 Atheros Communications, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include "ath9k.h"
-
-static const struct ath_rate_table ar5416_11na_ratetable = {
-	68,
-	8, /* MCS start */
-	{
-		[0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000,
-			5400, 0, 12 }, /* 6 Mb */
-		[1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000,
-			7800,  1, 18 }, /* 9 Mb */
-		[2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
-			10000, 2, 24 }, /* 12 Mb */
-		[3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
-			13900, 3, 36 }, /* 18 Mb */
-		[4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
-			17300, 4, 48 }, /* 24 Mb */
-		[5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
-			23000, 5, 72 }, /* 36 Mb */
-		[6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
-			27400, 6, 96 }, /* 48 Mb */
-		[7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
-			29300, 7, 108 }, /* 54 Mb */
-		[8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500,
-			6400, 0, 0 }, /* 6.5 Mb */
-		[9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
-			12700, 1, 1 }, /* 13 Mb */
-		[10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
-			18800, 2, 2 }, /* 19.5 Mb */
-		[11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
-			25000, 3, 3 }, /* 26 Mb */
-		[12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
-			36700, 4, 4 }, /* 39 Mb */
-		[13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
-			48100, 5, 5 }, /* 52 Mb */
-		[14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
-			53500, 6, 6 }, /* 58.5 Mb */
-		[15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
-			59000, 7, 7 }, /* 65 Mb */
-		[16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
-			65400, 7, 7 }, /* 75 Mb */
-		[17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
-			12700, 8, 8 }, /* 13 Mb */
-		[18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
-			24800, 9, 9 }, /* 26 Mb */
-		[19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
-			36600, 10, 10 }, /* 39 Mb */
-		[20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
-			48100, 11, 11 }, /* 52 Mb */
-		[21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
-			69500, 12, 12 }, /* 78 Mb */
-		[22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
-			89500, 13, 13 }, /* 104 Mb */
-		[23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
-			98900, 14, 14 }, /* 117 Mb */
-		[24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
-			108300, 15, 15 }, /* 130 Mb */
-		[25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
-			120000, 15, 15 }, /* 144.4 Mb */
-		[26] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
-			17400, 16, 16 }, /* 19.5 Mb */
-		[27] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
-			35100, 17, 17 }, /* 39 Mb */
-		[28] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
-			52600, 18, 18 }, /* 58.5 Mb */
-		[29] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
-			70400, 19, 19 }, /* 78 Mb */
-		[30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
-			104900, 20, 20 }, /* 117 Mb */
-		[31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
-			115800, 20, 20 }, /* 130 Mb*/
-		[32] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
-			137200, 21, 21 }, /* 156 Mb */
-		[33] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
-			151100, 21, 21 }, /* 173.3 Mb */
-		[34] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
-			152800, 22, 22 }, /* 175.5 Mb */
-		[35] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
-			168400, 22, 22 }, /* 195 Mb*/
-		[36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
-			168400, 23, 23 }, /* 195 Mb */
-		[37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
-			185000, 23, 23 }, /* 216.7 Mb */
-		[38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
-			13200, 0, 0 }, /* 13.5 Mb*/
-		[39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
-			25900, 1, 1 }, /* 27.0 Mb*/
-		[40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
-			38600, 2, 2 }, /* 40.5 Mb*/
-		[41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
-			49800, 3, 3 }, /* 54 Mb */
-		[42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
-			72200, 4, 4 }, /* 81 Mb */
-		[43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000,
-			92900, 5, 5 }, /* 108 Mb */
-		[44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
-			102700, 6, 6 }, /* 121.5 Mb*/
-		[45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
-			112000, 7, 7 }, /* 135 Mb */
-		[46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
-			122000, 7, 7 }, /* 150 Mb */
-		[47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
-			25800, 8, 8 }, /* 27 Mb */
-		[48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
-			49800, 9, 9 }, /* 54 Mb */
-		[49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
-			71900, 10, 10 }, /* 81 Mb */
-		[50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
-			92500, 11, 11 }, /* 108 Mb */
-		[51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
-			130300, 12, 12 }, /* 162 Mb */
-		[52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
-			162800, 13, 13 }, /* 216 Mb */
-		[53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
-			178200, 14, 14 }, /* 243 Mb */
-		[54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
-			192100, 15, 15 }, /* 270 Mb */
-		[55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
-			207000, 15, 15 }, /* 300 Mb */
-		[56] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
-			36100, 16, 16 }, /* 40.5 Mb */
-		[57] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
-			72900, 17, 17 }, /* 81 Mb */
-		[58] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
-			108300, 18, 18 }, /* 121.5 Mb */
-		[59] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
-			142000, 19, 19 }, /*  162 Mb */
-		[60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
-			205100, 20, 20 }, /*  243 Mb */
-		[61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
-			224700, 20, 20 }, /*  270 Mb */
-		[62] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
-			263100, 21, 21 }, /*  324 Mb */
-		[63] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
-			288000, 21, 21 }, /*  360 Mb */
-		[64] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
-			290700, 22, 22 }, /* 364.5 Mb */
-		[65] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
-			317200, 22, 22 }, /* 405 Mb */
-		[66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
-			317200, 23, 23 }, /* 405 Mb */
-		[67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
-			346400, 23, 23 }, /* 450 Mb */
-	},
-	50,  /* probe interval */
-	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
-};
-
-/* 4ms frame limit not used for NG mode.  The values filled
- * for HT are the 64K max aggregate limit */
-
-static const struct ath_rate_table ar5416_11ng_ratetable = {
-	72,
-	12, /* MCS start */
-	{
-		[0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000,
-			900, 0, 2 }, /* 1 Mb */
-		[1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000,
-			1900, 1, 4 }, /* 2 Mb */
-		[2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500,
-			4900, 2, 11 }, /* 5.5 Mb */
-		[3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000,
-			8100, 3, 22 }, /* 11 Mb */
-		[4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000,
-			5400, 4, 12 }, /* 6 Mb */
-		[5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000,
-			7800, 5, 18 }, /* 9 Mb */
-		[6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
-			10100, 6, 24 }, /* 12 Mb */
-		[7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
-			14100, 7, 36 }, /* 18 Mb */
-		[8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
-			17700, 8, 48 }, /* 24 Mb */
-		[9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
-			23700, 9, 72 }, /* 36 Mb */
-		[10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
-			27400, 10, 96 }, /* 48 Mb */
-		[11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
-			30900, 11, 108 }, /* 54 Mb */
-		[12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500,
-			6400, 0, 0 }, /* 6.5 Mb */
-		[13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
-			12700, 1, 1 }, /* 13 Mb */
-		[14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
-			18800, 2, 2 }, /* 19.5 Mb*/
-		[15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
-			25000, 3, 3 }, /* 26 Mb */
-		[16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
-			36700, 4, 4 }, /* 39 Mb */
-		[17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
-			48100, 5, 5 }, /* 52 Mb */
-		[18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
-			53500, 6, 6 }, /* 58.5 Mb */
-		[19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
-			59000, 7, 7 }, /* 65 Mb */
-		[20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
-			65400, 7, 7 }, /* 65 Mb*/
-		[21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
-			12700, 8, 8 }, /* 13 Mb */
-		[22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
-			24800, 9, 9 }, /* 26 Mb */
-		[23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
-			36600, 10, 10 }, /* 39 Mb */
-		[24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
-			48100, 11, 11 }, /* 52 Mb */
-		[25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
-			69500, 12, 12 }, /* 78 Mb */
-		[26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
-			89500, 13, 13 }, /* 104 Mb */
-		[27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
-			98900, 14, 14 }, /* 117 Mb */
-		[28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
-			108300, 15, 15 }, /* 130 Mb */
-		[29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
-			120000, 15, 15 }, /* 144.4 Mb */
-		[30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
-			17400, 16, 16 }, /* 19.5 Mb */
-		[31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
-			35100, 17, 17 }, /* 39 Mb */
-		[32] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
-			52600, 18, 18 }, /* 58.5 Mb */
-		[33] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
-			70400, 19, 19 }, /* 78 Mb */
-		[34] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
-			104900, 20, 20 }, /* 117 Mb */
-		[35] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
-			115800, 20, 20 }, /* 130 Mb */
-		[36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
-			137200, 21, 21 }, /* 156 Mb */
-		[37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
-			151100, 21, 21 }, /* 173.3 Mb */
-		[38] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
-			152800, 22, 22 }, /* 175.5 Mb */
-		[39] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
-			168400, 22, 22 }, /* 195 Mb */
-		[40] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
-			168400, 23, 23 }, /* 195 Mb */
-		[41] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
-			185000, 23, 23 }, /* 216.7 Mb */
-		[42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
-			13200, 0, 0 }, /* 13.5 Mb */
-		[43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
-			25900, 1, 1 }, /* 27.0 Mb */
-		[44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
-			38600, 2, 2 }, /* 40.5 Mb */
-		[45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
-			49800, 3, 3 }, /* 54 Mb */
-		[46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
-			72200, 4, 4 }, /* 81 Mb */
-		[47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000,
-			92900, 5, 5 }, /* 108 Mb */
-		[48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
-			102700, 6, 6 }, /* 121.5 Mb */
-		[49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
-			112000, 7, 7 }, /* 135 Mb */
-		[50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
-			122000, 7, 7 }, /* 150 Mb */
-		[51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
-			25800, 8, 8 }, /* 27 Mb */
-		[52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
-			49800, 9, 9 }, /* 54 Mb */
-		[53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
-			71900, 10, 10 }, /* 81 Mb */
-		[54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
-			92500, 11, 11 }, /* 108 Mb */
-		[55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
-			130300, 12, 12 }, /* 162 Mb */
-		[56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
-			162800, 13, 13 }, /* 216 Mb */
-		[57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
-			178200, 14, 14 }, /* 243 Mb */
-		[58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
-			192100, 15, 15 }, /* 270 Mb */
-		[59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
-			207000, 15, 15 }, /* 300 Mb */
-		[60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
-			36100, 16, 16 }, /* 40.5 Mb */
-		[61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
-			72900, 17, 17 }, /* 81 Mb */
-		[62] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
-			108300, 18, 18 }, /* 121.5 Mb */
-		[63] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
-			142000, 19, 19 }, /* 162 Mb */
-		[64] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
-			205100, 20, 20 }, /* 243 Mb */
-		[65] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
-			224700, 20, 20 }, /* 270 Mb */
-		[66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
-			263100, 21, 21 }, /* 324 Mb */
-		[67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
-			288000, 21, 21 }, /* 360 Mb */
-		[68] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
-			290700, 22, 22 }, /* 364.5 Mb */
-		[69] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
-			317200, 22, 22 }, /* 405 Mb */
-		[70] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
-			317200, 23, 23 }, /* 405 Mb */
-		[71] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
-			346400, 23, 23 }, /* 450 Mb */
-	},
-	50,  /* probe interval */
-	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
-};
-
-static const struct ath_rate_table ar5416_11a_ratetable = {
-	8,
-	0,
-	{
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0, 12},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800,  1, 18},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 2, 24},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 3, 36},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 4, 48},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 5, 72},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 6, 96},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 7, 108},
-	},
-	50,  /* probe interval */
-	0,   /* Phy rates allowed initially */
-};
-
-static const struct ath_rate_table ar5416_11g_ratetable = {
-	12,
-	0,
-	{
-		{ RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0, 2},
-		{ RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1900, 1, 4},
-		{ RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4900, 2, 11},
-		{ RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			8100, 3, 22},
-		{ RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 4, 12},
-		{ RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 5, 18},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 6, 24},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 7, 36},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 8, 48},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 9, 72},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 10, 96},
-		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 11, 108},
-	},
-	50,  /* probe interval */
-	0,   /* Phy rates allowed initially */
-};
-
-static int ath_rc_get_rateindex(struct ath_rate_priv *ath_rc_priv,
-				struct ieee80211_tx_rate *rate)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	int rix, i, idx = 0;
-
-	if (!(rate->flags & IEEE80211_TX_RC_MCS))
-		return rate->idx;
-
-	for (i = 0; i < ath_rc_priv->max_valid_rate; i++) {
-		idx = ath_rc_priv->valid_rate_index[i];
-
-		if (WLAN_RC_PHY_HT(rate_table->info[idx].phy) &&
-		    rate_table->info[idx].ratecode == rate->idx)
-			break;
-	}
-
-	rix = idx;
-
-	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-		rix++;
-
-	return rix;
-}
-
-static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	u8 i, j, idx, idx_next;
-
-	for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
-		for (j = 0; j <= i-1; j++) {
-			idx = ath_rc_priv->valid_rate_index[j];
-			idx_next = ath_rc_priv->valid_rate_index[j+1];
-
-			if (rate_table->info[idx].ratekbps >
-				rate_table->info[idx_next].ratekbps) {
-				ath_rc_priv->valid_rate_index[j] = idx_next;
-				ath_rc_priv->valid_rate_index[j+1] = idx;
-			}
-		}
-	}
-}
-
-static inline
-int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
-				struct ath_rate_priv *ath_rc_priv,
-				u8 cur_valid_txrate,
-				u8 *next_idx)
-{
-	u8 i;
-
-	for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
-		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
-			*next_idx = ath_rc_priv->valid_rate_index[i+1];
-			return 1;
-		}
-	}
-
-	/* No more valid rates */
-	*next_idx = 0;
-
-	return 0;
-}
-
-/* Return true only for single stream */
-
-static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
-{
-	if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
-		return 0;
-	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
-		return 0;
-	if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG))
-		return 0;
-	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
-		return 0;
-	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
-		if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
-			return 0;
-	return 1;
-}
-
-static inline int
-ath_rc_get_lower_rix(struct ath_rate_priv *ath_rc_priv,
-		     u8 cur_valid_txrate, u8 *next_idx)
-{
-	int8_t i;
-
-	for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
-		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
-			*next_idx = ath_rc_priv->valid_rate_index[i-1];
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	u8 i, hi = 0;
-
-	for (i = 0; i < rate_table->rate_cnt; i++) {
-		if (rate_table->info[i].rate_flags & RC_LEGACY) {
-			u32 phy = rate_table->info[i].phy;
-			u8 valid_rate_count = 0;
-
-			if (!ath_rc_valid_phyrate(phy, ath_rc_priv->ht_cap, 0))
-				continue;
-
-			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
-
-			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
-			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_priv->valid_rate_index[i] = true;
-			hi = i;
-		}
-	}
-
-	return hi;
-}
-
-static inline bool ath_rc_check_legacy(u8 rate, u8 dot11rate, u16 rate_flags,
-				       u32 phy, u32 capflag)
-{
-	if (rate != dot11rate || WLAN_RC_PHY_HT(phy))
-		return false;
-
-	if ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != WLAN_RC_CAP_MODE(capflag))
-		return false;
-
-	if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag)))
-		return false;
-
-	return true;
-}
-
-static inline bool ath_rc_check_ht(u8 rate, u8 dot11rate, u16 rate_flags,
-				   u32 phy, u32 capflag)
-{
-	if (rate != dot11rate || !WLAN_RC_PHY_HT(phy))
-		return false;
-
-	if (!WLAN_RC_PHY_HT_VALID(rate_flags, capflag))
-		return false;
-
-	if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag)))
-		return false;
-
-	return true;
-}
-
-static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, bool legacy)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	struct ath_rateset *rateset;
-	u32 phy, capflag = ath_rc_priv->ht_cap;
-	u16 rate_flags;
-	u8 i, j, hi = 0, rate, dot11rate, valid_rate_count;
-
-	if (legacy)
-		rateset = &ath_rc_priv->neg_rates;
-	else
-		rateset = &ath_rc_priv->neg_ht_rates;
-
-	for (i = 0; i < rateset->rs_nrates; i++) {
-		for (j = 0; j < rate_table->rate_cnt; j++) {
-			phy = rate_table->info[j].phy;
-			rate_flags = rate_table->info[j].rate_flags;
-			rate = rateset->rs_rates[i];
-			dot11rate = rate_table->info[j].dot11rate;
-
-			if (legacy &&
-			    !ath_rc_check_legacy(rate, dot11rate,
-						 rate_flags, phy, capflag))
-				continue;
-
-			if (!legacy &&
-			    !ath_rc_check_ht(rate, dot11rate,
-					     rate_flags, phy, capflag))
-				continue;
-
-			if (!ath_rc_valid_phyrate(phy, capflag, 0))
-				continue;
-
-			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
-			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j;
-			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_priv->valid_rate_index[j] = true;
-			hi = max(hi, j);
-		}
-	}
-
-	return hi;
-}
-
-static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv,
-				 int *is_probing)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	u32 best_thruput, this_thruput, now_msec;
-	u8 rate, next_rate, best_rate, maxindex, minindex;
-	int8_t index = 0;
-
-	now_msec = jiffies_to_msecs(jiffies);
-	*is_probing = 0;
-	best_thruput = 0;
-	maxindex = ath_rc_priv->max_valid_rate-1;
-	minindex = 0;
-	best_rate = minindex;
-
-	/*
-	 * Try the higher rate first. It will reduce memory moving time
-	 * if we have very good channel characteristics.
-	 */
-	for (index = maxindex; index >= minindex ; index--) {
-		u8 per_thres;
-
-		rate = ath_rc_priv->valid_rate_index[index];
-		if (rate > ath_rc_priv->rate_max_phy)
-			continue;
-
-		/*
-		 * For TCP the average collision rate is around 11%,
-		 * so we ignore PERs less than this.  This is to
-		 * prevent the rate we are currently using (whose
-		 * PER might be in the 10-15 range because of TCP
-		 * collisions) looking worse than the next lower
-		 * rate whose PER has decayed close to 0.  If we
-		 * used to next lower rate, its PER would grow to
-		 * 10-15 and we would be worse off then staying
-		 * at the current rate.
-		 */
-		per_thres = ath_rc_priv->per[rate];
-		if (per_thres < 12)
-			per_thres = 12;
-
-		this_thruput = rate_table->info[rate].user_ratekbps *
-			(100 - per_thres);
-
-		if (best_thruput <= this_thruput) {
-			best_thruput = this_thruput;
-			best_rate    = rate;
-		}
-	}
-
-	rate = best_rate;
-
-	/*
-	 * Must check the actual rate (ratekbps) to account for
-	 * non-monoticity of 11g's rate table
-	 */
-
-	if (rate >= ath_rc_priv->rate_max_phy) {
-		rate = ath_rc_priv->rate_max_phy;
-
-		/* Probe the next allowed phy state */
-		if (ath_rc_get_nextvalid_txrate(rate_table,
-					ath_rc_priv, rate, &next_rate) &&
-		    (now_msec - ath_rc_priv->probe_time >
-		     rate_table->probe_interval) &&
-		    (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
-			rate = next_rate;
-			ath_rc_priv->probe_rate = rate;
-			ath_rc_priv->probe_time = now_msec;
-			ath_rc_priv->hw_maxretry_pktcnt = 0;
-			*is_probing = 1;
-		}
-	}
-
-	if (rate > (ath_rc_priv->rate_table_size - 1))
-		rate = ath_rc_priv->rate_table_size - 1;
-
-	if (RC_TS_ONLY(rate_table->info[rate].rate_flags) &&
-	    (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG))
-		return rate;
-
-	if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) &&
-	    (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG)))
-		return rate;
-
-	if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags))
-		return rate;
-
-	/* This should not happen */
-	WARN_ON_ONCE(1);
-
-	rate = ath_rc_priv->valid_rate_index[0];
-
-	return rate;
-}
-
-static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
-				   struct ieee80211_tx_rate *rate,
-				   struct ieee80211_tx_rate_control *txrc,
-				   u8 tries, u8 rix, int rtsctsenable)
-{
-	rate->count = tries;
-	rate->idx = rate_table->info[rix].ratecode;
-
-	if (txrc->rts || rtsctsenable)
-		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
-
-	if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {
-		rate->flags |= IEEE80211_TX_RC_MCS;
-		if (WLAN_RC_PHY_40(rate_table->info[rix].phy) &&
-		    conf_is_ht40(&txrc->hw->conf))
-			rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-		if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
-			rate->flags |= IEEE80211_TX_RC_SHORT_GI;
-	}
-}
-
-static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
-				   const struct ath_rate_table *rate_table,
-				   struct ieee80211_tx_info *tx_info)
-{
-	struct ieee80211_bss_conf *bss_conf;
-
-	if (!tx_info->control.vif)
-		return;
-	/*
-	 * For legacy frames, mac80211 takes care of CTS protection.
-	 */
-	if (!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS))
-		return;
-
-	bss_conf = &tx_info->control.vif->bss_conf;
-
-	if (!bss_conf->basic_rates)
-		return;
-
-	/*
-	 * For now, use the lowest allowed basic rate for HT frames.
-	 */
-	tx_info->control.rts_cts_rate_idx = __ffs(bss_conf->basic_rates);
-}
-
-static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
-			 struct ieee80211_tx_rate_control *txrc)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	const struct ath_rate_table *rate_table;
-	struct sk_buff *skb = txrc->skb;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_rate *rates = tx_info->control.rates;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	__le16 fc = hdr->frame_control;
-	u8 try_per_rate, i = 0, rix;
-	int is_probe = 0;
-
-	if (rate_control_send_low(sta, priv_sta, txrc))
-		return;
-
-	/*
-	 * For Multi Rate Retry we use a different number of
-	 * retry attempt counts. This ends up looking like this:
-	 *
-	 * MRR[0] = 4
-	 * MRR[1] = 4
-	 * MRR[2] = 4
-	 * MRR[3] = 8
-	 *
-	 */
-	try_per_rate = 4;
-
-	rate_table = ath_rc_priv->rate_table;
-	rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe);
-
-	if (conf_is_ht(&sc->hw->conf) &&
-	    (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
-		tx_info->flags |= IEEE80211_TX_CTL_LDPC;
-
-	if (conf_is_ht(&sc->hw->conf) &&
-	    (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
-		tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT);
-
-	if (is_probe) {
-		/*
-		 * Set one try for probe rates. For the
-		 * probes don't enable RTS.
-		 */
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       1, rix, 0);
-		/*
-		 * Get the next tried/allowed rate.
-		 * No RTS for the next series after the probe rate.
-		 */
-		ath_rc_get_lower_rix(ath_rc_priv, rix, &rix);
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, rix, 0);
-
-		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-	} else {
-		/*
-		 * Set the chosen rate. No RTS for first series entry.
-		 */
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, rix, 0);
-	}
-
-	for ( ; i < 4; i++) {
-		/*
-		 * Use twice the number of tries for the last MRR segment.
-		 */
-		if (i + 1 == 4)
-			try_per_rate = 8;
-
-		ath_rc_get_lower_rix(ath_rc_priv, rix, &rix);
-
-		/*
-		 * All other rates in the series have RTS enabled.
-		 */
-		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
-				       try_per_rate, rix, 1);
-	}
-
-	/*
-	 * NB:Change rate series to enable aggregation when operating
-	 * at lower MCS rates. When first rate in series is MCS2
-	 * in HT40 @ 2.4GHz, series should look like:
-	 *
-	 * {MCS2, MCS1, MCS0, MCS0}.
-	 *
-	 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
-	 * look like:
-	 *
-	 * {MCS3, MCS2, MCS1, MCS1}
-	 *
-	 * So, set fourth rate in series to be same as third one for
-	 * above conditions.
-	 */
-	if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) &&
-	    (conf_is_ht(&sc->hw->conf))) {
-		u8 dot11rate = rate_table->info[rix].dot11rate;
-		u8 phy = rate_table->info[rix].phy;
-		if (i == 4 &&
-		    ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
-		     (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
-			rates[3].idx = rates[2].idx;
-			rates[3].flags = rates[2].flags;
-		}
-	}
-
-	/*
-	 * Force hardware to use computed duration for next
-	 * fragment by disabling multi-rate retry, which
-	 * updates duration based on the multi-rate duration table.
-	 *
-	 * FIXME: Fix duration
-	 */
-	if (ieee80211_has_morefrags(fc) ||
-	    (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
-		rates[1].count = rates[2].count = rates[3].count = 0;
-		rates[1].idx = rates[2].idx = rates[3].idx = 0;
-		rates[0].count = ATH_TXMAXTRY;
-	}
-
-	ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
-}
-
-static void ath_rc_update_per(struct ath_softc *sc,
-			      const struct ath_rate_table *rate_table,
-			      struct ath_rate_priv *ath_rc_priv,
-				  struct ieee80211_tx_info *tx_info,
-			      int tx_rate, int xretries, int retries,
-			      u32 now_msec)
-{
-	int count, n_bad_frames;
-	u8 last_per;
-	static const u32 nretry_to_per_lookup[10] = {
-		100 * 0 / 1,
-		100 * 1 / 4,
-		100 * 1 / 2,
-		100 * 3 / 4,
-		100 * 4 / 5,
-		100 * 5 / 6,
-		100 * 6 / 7,
-		100 * 7 / 8,
-		100 * 8 / 9,
-		100 * 9 / 10
-	};
-
-	last_per = ath_rc_priv->per[tx_rate];
-	n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len;
-
-	if (xretries) {
-		if (xretries == 1) {
-			ath_rc_priv->per[tx_rate] += 30;
-			if (ath_rc_priv->per[tx_rate] > 100)
-				ath_rc_priv->per[tx_rate] = 100;
-		} else {
-			/* xretries == 2 */
-			count = ARRAY_SIZE(nretry_to_per_lookup);
-			if (retries >= count)
-				retries = count - 1;
-
-			/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
-			ath_rc_priv->per[tx_rate] =
-				(u8)(last_per - (last_per >> 3) + (100 >> 3));
-		}
-
-		/* xretries == 1 or 2 */
-
-		if (ath_rc_priv->probe_rate == tx_rate)
-			ath_rc_priv->probe_rate = 0;
-
-	} else { /* xretries == 0 */
-		count = ARRAY_SIZE(nretry_to_per_lookup);
-		if (retries >= count)
-			retries = count - 1;
-
-		if (n_bad_frames) {
-			/* new_PER = 7/8*old_PER + 1/8*(currentPER)
-			 * Assuming that n_frames is not 0.  The current PER
-			 * from the retries is 100 * retries / (retries+1),
-			 * since the first retries attempts failed, and the
-			 * next one worked.  For the one that worked,
-			 * n_bad_frames subframes out of n_frames wored,
-			 * so the PER for that part is
-			 * 100 * n_bad_frames / n_frames, and it contributes
-			 * 100 * n_bad_frames / (n_frames * (retries+1)) to
-			 * the above PER.  The expression below is a
-			 * simplified version of the sum of these two terms.
-			 */
-			if (tx_info->status.ampdu_len > 0) {
-				int n_frames, n_bad_tries;
-				u8 cur_per, new_per;
-
-				n_bad_tries = retries * tx_info->status.ampdu_len +
-					n_bad_frames;
-				n_frames = tx_info->status.ampdu_len * (retries + 1);
-				cur_per = (100 * n_bad_tries / n_frames) >> 3;
-				new_per = (u8)(last_per - (last_per >> 3) + cur_per);
-				ath_rc_priv->per[tx_rate] = new_per;
-			}
-		} else {
-			ath_rc_priv->per[tx_rate] =
-				(u8)(last_per - (last_per >> 3) +
-				     (nretry_to_per_lookup[retries] >> 3));
-		}
-
-
-		/*
-		 * If we got at most one retry then increase the max rate if
-		 * this was a probe.  Otherwise, ignore the probe.
-		 */
-		if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
-			if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) {
-				/*
-				 * Since we probed with just a single attempt,
-				 * any retries means the probe failed.  Also,
-				 * if the attempt worked, but more than half
-				 * the subframes were bad then also consider
-				 * the probe a failure.
-				 */
-				ath_rc_priv->probe_rate = 0;
-			} else {
-				u8 probe_rate = 0;
-
-				ath_rc_priv->rate_max_phy =
-					ath_rc_priv->probe_rate;
-				probe_rate = ath_rc_priv->probe_rate;
-
-				if (ath_rc_priv->per[probe_rate] > 30)
-					ath_rc_priv->per[probe_rate] = 20;
-
-				ath_rc_priv->probe_rate = 0;
-
-				/*
-				 * Since this probe succeeded, we allow the next
-				 * probe twice as soon.  This allows the maxRate
-				 * to move up faster if the probes are
-				 * successful.
-				 */
-				ath_rc_priv->probe_time =
-					now_msec - rate_table->probe_interval / 2;
-			}
-		}
-
-		if (retries > 0) {
-			/*
-			 * Don't update anything.  We don't know if
-			 * this was because of collisions or poor signal.
-			 */
-			ath_rc_priv->hw_maxretry_pktcnt = 0;
-		} else {
-			/*
-			 * It worked with no retries. First ignore bogus (small)
-			 * rssi_ack values.
-			 */
-			if (tx_rate == ath_rc_priv->rate_max_phy &&
-			    ath_rc_priv->hw_maxretry_pktcnt < 255) {
-				ath_rc_priv->hw_maxretry_pktcnt++;
-			}
-
-		}
-	}
-}
-
-static void ath_rc_update_ht(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct ieee80211_tx_info *tx_info,
-			     int tx_rate, int xretries, int retries)
-{
-	u32 now_msec = jiffies_to_msecs(jiffies);
-	int rate;
-	u8 last_per;
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	int size = ath_rc_priv->rate_table_size;
-
-	if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
-		return;
-
-	last_per = ath_rc_priv->per[tx_rate];
-
-	/* Update PER first */
-	ath_rc_update_per(sc, rate_table, ath_rc_priv,
-			  tx_info, tx_rate, xretries,
-			  retries, now_msec);
-
-	/*
-	 * If this rate looks bad (high PER) then stop using it for
-	 * a while (except if we are probing).
-	 */
-	if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 &&
-	    rate_table->info[tx_rate].ratekbps <=
-	    rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
-		ath_rc_get_lower_rix(ath_rc_priv, (u8)tx_rate,
-				     &ath_rc_priv->rate_max_phy);
-
-		/* Don't probe for a little while. */
-		ath_rc_priv->probe_time = now_msec;
-	}
-
-	/* Make sure the rates below this have lower PER */
-	/* Monotonicity is kept only for rates below the current rate. */
-	if (ath_rc_priv->per[tx_rate] < last_per) {
-		for (rate = tx_rate - 1; rate >= 0; rate--) {
-
-			if (ath_rc_priv->per[rate] >
-			    ath_rc_priv->per[rate+1]) {
-				ath_rc_priv->per[rate] =
-					ath_rc_priv->per[rate+1];
-			}
-		}
-	}
-
-	/* Maintain monotonicity for rates above the current rate */
-	for (rate = tx_rate; rate < size - 1; rate++) {
-		if (ath_rc_priv->per[rate+1] <
-		    ath_rc_priv->per[rate])
-			ath_rc_priv->per[rate+1] =
-				ath_rc_priv->per[rate];
-	}
-
-	/* Every so often, we reduce the thresholds
-	 * and PER (different for CCK and OFDM). */
-	if (now_msec - ath_rc_priv->per_down_time >=
-	    rate_table->probe_interval) {
-		for (rate = 0; rate < size; rate++) {
-			ath_rc_priv->per[rate] =
-				7 * ath_rc_priv->per[rate] / 8;
-		}
-
-		ath_rc_priv->per_down_time = now_msec;
-	}
-
-	ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
-			       ath_rc_priv->per[tx_rate]);
-
-}
-
-static void ath_rc_tx_status(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct sk_buff *skb)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_rate *rates = tx_info->status.rates;
-	struct ieee80211_tx_rate *rate;
-	int final_ts_idx = 0, xretries = 0, long_retry = 0;
-	u8 flags;
-	u32 i = 0, rix;
-
-	for (i = 0; i < sc->hw->max_rates; i++) {
-		rate = &tx_info->status.rates[i];
-		if (rate->idx < 0 || !rate->count)
-			break;
-
-		final_ts_idx = i;
-		long_retry = rate->count - 1;
-	}
-
-	if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
-		xretries = 1;
-
-	/*
-	 * If the first rate is not the final index, there
-	 * are intermediate rate failures to be processed.
-	 */
-	if (final_ts_idx != 0) {
-		for (i = 0; i < final_ts_idx ; i++) {
-			if (rates[i].count != 0 && (rates[i].idx >= 0)) {
-				flags = rates[i].flags;
-
-				/* If HT40 and we have switched mode from
-				 * 40 to 20 => don't update */
-
-				if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-				    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
-					return;
-
-				rix = ath_rc_get_rateindex(ath_rc_priv, &rates[i]);
-				ath_rc_update_ht(sc, ath_rc_priv, tx_info,
-						 rix, xretries ? 1 : 2,
-						 rates[i].count);
-			}
-		}
-	}
-
-	flags = rates[final_ts_idx].flags;
-
-	/* If HT40 and we have switched mode from 40 to 20 => don't update */
-	if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-	    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
-		return;
-
-	rix = ath_rc_get_rateindex(ath_rc_priv, &rates[final_ts_idx]);
-	ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry);
-	ath_debug_stat_rc(ath_rc_priv, rix);
-}
-
-static const
-struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
-					     enum ieee80211_band band,
-					     bool is_ht)
-{
-	switch(band) {
-	case IEEE80211_BAND_2GHZ:
-		if (is_ht)
-			return &ar5416_11ng_ratetable;
-		return &ar5416_11g_ratetable;
-	case IEEE80211_BAND_5GHZ:
-		if (is_ht)
-			return &ar5416_11na_ratetable;
-		return &ar5416_11a_ratetable;
-	default:
-		return NULL;
-	}
-}
-
-static void ath_rc_init(struct ath_softc *sc,
-			struct ath_rate_priv *ath_rc_priv)
-{
-	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
-	struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	u8 i, j, k, hi = 0, hthi = 0;
-
-	ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
-
-	for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
-		ath_rc_priv->per[i] = 0;
-		ath_rc_priv->valid_rate_index[i] = 0;
-	}
-
-	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
-		for (j = 0; j < RATE_TABLE_SIZE; j++)
-			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
-		ath_rc_priv->valid_phy_ratecnt[i] = 0;
-	}
-
-	if (!rateset->rs_nrates) {
-		hi = ath_rc_init_validrates(ath_rc_priv);
-	} else {
-		hi = ath_rc_setvalid_rates(ath_rc_priv, true);
-
-		if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG)
-			hthi = ath_rc_setvalid_rates(ath_rc_priv, false);
-
-		hi = max(hi, hthi);
-	}
-
-	ath_rc_priv->rate_table_size = hi + 1;
-	ath_rc_priv->rate_max_phy = 0;
-	WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
-
-	for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
-		for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
-			ath_rc_priv->valid_rate_index[k++] =
-				ath_rc_priv->valid_phy_rateidx[i][j];
-		}
-
-		if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) ||
-		    !ath_rc_priv->valid_phy_ratecnt[i])
-			continue;
-
-		ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
-	}
-	WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
-	WARN_ON(k > RATE_TABLE_SIZE);
-
-	ath_rc_priv->max_valid_rate = k;
-	ath_rc_sort_validrates(ath_rc_priv);
-	ath_rc_priv->rate_max_phy = (k > 4) ?
-		ath_rc_priv->valid_rate_index[k-4] :
-		ath_rc_priv->valid_rate_index[k-1];
-
-	ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n",
-		ath_rc_priv->ht_cap);
-}
-
-static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
-	u8 caps = 0;
-
-	if (sta->ht_cap.ht_supported) {
-		caps = WLAN_RC_HT_FLAG;
-		if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2])
-			caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
-		else if (sta->ht_cap.mcs.rx_mask[1])
-			caps |= WLAN_RC_DS_FLAG;
-		if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
-			caps |= WLAN_RC_40_FLAG;
-			if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
-				caps |= WLAN_RC_SGI_FLAG;
-		} else {
-			if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
-				caps |= WLAN_RC_SGI_FLAG;
-		}
-	}
-
-	return caps;
-}
-
-static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
-			      u8 tidno)
-{
-	struct ath_node *an = (struct ath_node *)sta->drv_priv;
-	struct ath_atx_tid *txtid;
-
-	if (!sta->ht_cap.ht_supported)
-		return false;
-
-	txtid = ATH_AN_2_TID(an, tidno);
-	return !txtid->active;
-}
-
-
-/***********************************/
-/* mac80211 Rate Control callbacks */
-/***********************************/
-
-static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
-			  struct ieee80211_sta *sta, void *priv_sta,
-			  struct sk_buff *skb)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	__le16 fc = hdr->frame_control;
-
-	if (!priv_sta || !ieee80211_is_data(fc))
-		return;
-
-	/* This packet was aggregated but doesn't carry status info */
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-	    !(tx_info->flags & IEEE80211_TX_STAT_AMPDU))
-		return;
-
-	if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
-		return;
-
-	ath_rc_tx_status(sc, ath_rc_priv, skb);
-
-	/* Check if aggregation has to be enabled for this tid */
-	if (conf_is_ht(&sc->hw->conf) &&
-	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-		if (ieee80211_is_data_qos(fc) &&
-		    skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
-			u8 *qc, tid;
-
-			qc = ieee80211_get_qos_ctl(hdr);
-			tid = qc[0] & 0xf;
-
-			if(ath_tx_aggr_check(sc, sta, tid))
-				ieee80211_start_tx_ba_session(sta, tid, 0);
-		}
-	}
-}
-
-static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
-			  struct cfg80211_chan_def *chandef,
-                          struct ieee80211_sta *sta, void *priv_sta)
-{
-	struct ath_softc *sc = priv;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	int i, j = 0;
-	u32 rate_flags = ieee80211_chandef_rate_flags(&sc->hw->conf.chandef);
-
-	for (i = 0; i < sband->n_bitrates; i++) {
-		if (sta->supp_rates[sband->band] & BIT(i)) {
-			if ((rate_flags & sband->bitrates[i].flags)
-			    != rate_flags)
-				continue;
-
-			ath_rc_priv->neg_rates.rs_rates[j]
-				= (sband->bitrates[i].bitrate * 2) / 10;
-			j++;
-		}
-	}
-	ath_rc_priv->neg_rates.rs_nrates = j;
-
-	if (sta->ht_cap.ht_supported) {
-		for (i = 0, j = 0; i < 77; i++) {
-			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
-				ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
-			if (j == ATH_RATE_MAX)
-				break;
-		}
-		ath_rc_priv->neg_ht_rates.rs_nrates = j;
-	}
-
-	ath_rc_priv->rate_table = ath_choose_rate_table(sc, sband->band,
-							sta->ht_cap.ht_supported);
-	if (!ath_rc_priv->rate_table) {
-		ath_err(common, "No rate table chosen\n");
-		return;
-	}
-
-	ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta);
-	ath_rc_init(sc, priv_sta);
-}
-
-static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
-			    struct cfg80211_chan_def *chandef,
-			    struct ieee80211_sta *sta, void *priv_sta,
-			    u32 changed)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-
-	if (changed & IEEE80211_RC_BW_CHANGED) {
-		ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta);
-		ath_rc_init(sc, priv_sta);
-
-		ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
-			"Operating Bandwidth changed to: %d\n",
-			sc->hw->conf.chandef.width);
-	}
-}
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-
-void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
-	struct ath_rc_stats *stats;
-
-	stats = &rc->rcstats[final_rate];
-	stats->success++;
-}
-
-void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
-			    int xretries, int retries, u8 per)
-{
-	struct ath_rc_stats *stats = &rc->rcstats[rix];
-
-	stats->xretries += xretries;
-	stats->retries += retries;
-	stats->per = per;
-}
-
-static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
-				size_t count, loff_t *ppos)
-{
-	struct ath_rate_priv *rc = file->private_data;
-	char *buf;
-	unsigned int len = 0, max;
-	int rix;
-	ssize_t retval;
-
-	if (rc->rate_table == NULL)
-		return 0;
-
-	max = 80 + rc->rate_table_size * 1024 + 1;
-	buf = kmalloc(max, GFP_KERNEL);
-	if (buf == NULL)
-		return -ENOMEM;
-
-	len += sprintf(buf, "%6s %6s %6s "
-		       "%10s %10s %10s %10s\n",
-		       "HT", "MCS", "Rate",
-		       "Success", "Retries", "XRetries", "PER");
-
-	for (rix = 0; rix < rc->max_valid_rate; rix++) {
-		u8 i = rc->valid_rate_index[rix];
-		u32 ratekbps = rc->rate_table->info[i].ratekbps;
-		struct ath_rc_stats *stats = &rc->rcstats[i];
-		char mcs[5];
-		char htmode[5];
-		int used_mcs = 0, used_htmode = 0;
-
-		if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
-			used_mcs = scnprintf(mcs, 5, "%d",
-					     rc->rate_table->info[i].ratecode);
-
-			if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
-				used_htmode = scnprintf(htmode, 5, "HT40");
-			else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
-				used_htmode = scnprintf(htmode, 5, "HT20");
-			else
-				used_htmode = scnprintf(htmode, 5, "????");
-		}
-
-		mcs[used_mcs] = '\0';
-		htmode[used_htmode] = '\0';
-
-		len += scnprintf(buf + len, max - len,
-				 "%6s %6s %3u.%d: "
-				 "%10u %10u %10u %10u\n",
-				 htmode,
-				 mcs,
-				 ratekbps / 1000,
-				 (ratekbps % 1000) / 100,
-				 stats->success,
-				 stats->retries,
-				 stats->xretries,
-				 stats->per);
-	}
-
-	if (len > max)
-		len = max;
-
-	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-	return retval;
-}
-
-static const struct file_operations fops_rcstat = {
-	.read = read_file_rcstat,
-	.open = simple_open,
-	.owner = THIS_MODULE
-};
-
-static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
-				     struct dentry *dir)
-{
-	struct ath_rate_priv *rc = priv_sta;
-	rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO,
-						  dir, rc, &fops_rcstat);
-}
-
-static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta)
-{
-	struct ath_rate_priv *rc = priv_sta;
-	debugfs_remove(rc->debugfs_rcstats);
-}
-
-#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */
-
-static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-	return hw->priv;
-}
-
-static void ath_rate_free(void *priv)
-{
-	return;
-}
-
-static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
-	return kzalloc(sizeof(struct ath_rate_priv), gfp);
-}
-
-static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
-			      void *priv_sta)
-{
-	struct ath_rate_priv *rate_priv = priv_sta;
-	kfree(rate_priv);
-}
-
-static struct rate_control_ops ath_rate_ops = {
-	.module = NULL,
-	.name = "ath9k_rate_control",
-	.tx_status = ath_tx_status,
-	.get_rate = ath_get_rate,
-	.rate_init = ath_rate_init,
-	.rate_update = ath_rate_update,
-	.alloc = ath_rate_alloc,
-	.free = ath_rate_free,
-	.alloc_sta = ath_rate_alloc_sta,
-	.free_sta = ath_rate_free_sta,
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-	.add_sta_debugfs = ath_rate_add_sta_debugfs,
-	.remove_sta_debugfs = ath_rate_remove_sta_debugfs,
-#endif
-};
-
-int ath_rate_control_register(void)
-{
-	return ieee80211_rate_control_register(&ath_rate_ops);
-}
-
-void ath_rate_control_unregister(void)
-{
-	ieee80211_rate_control_unregister(&ath_rate_ops);
-}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
deleted file mode 100644
index b9a87383cb43..000000000000
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2004 Sam Leffler, Errno Consulting
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2008-2011 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef RC_H
-#define RC_H
-
-#include "hw.h"
-
-struct ath_softc;
-
-#define ATH_RATE_MAX     30
-#define RATE_TABLE_SIZE  72
-
-#define RC_INVALID	0x0000
-#define RC_LEGACY	0x0001
-#define RC_SS		0x0002
-#define RC_DS		0x0004
-#define RC_TS		0x0008
-#define RC_HT_20	0x0010
-#define RC_HT_40	0x0020
-
-#define RC_STREAM_MASK	0xe
-#define RC_DS_OR_LATER(f)	((((f) & RC_STREAM_MASK) == RC_DS) || \
-				(((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
-#define RC_TS_ONLY(f)		(((f) & RC_STREAM_MASK) == RC_TS)
-#define RC_SS_OR_LEGACY(f)	((f) & (RC_SS | RC_LEGACY))
-
-#define RC_HT_2040		(RC_HT_20 | RC_HT_40)
-#define RC_ALL_STREAM		(RC_SS | RC_DS | RC_TS)
-#define RC_L_SD			(RC_LEGACY | RC_SS | RC_DS)
-#define RC_L_SDT		(RC_LEGACY | RC_SS | RC_DS | RC_TS)
-#define RC_HT_S_20		(RC_HT_20 | RC_SS)
-#define RC_HT_D_20		(RC_HT_20 | RC_DS)
-#define RC_HT_T_20		(RC_HT_20 | RC_TS)
-#define RC_HT_S_40		(RC_HT_40 | RC_SS)
-#define RC_HT_D_40		(RC_HT_40 | RC_DS)
-#define RC_HT_T_40		(RC_HT_40 | RC_TS)
-
-#define RC_HT_SD_20		(RC_HT_20 | RC_SS | RC_DS)
-#define RC_HT_DT_20		(RC_HT_20 | RC_DS | RC_TS)
-#define RC_HT_SD_40		(RC_HT_40 | RC_SS | RC_DS)
-#define RC_HT_DT_40		(RC_HT_40 | RC_DS | RC_TS)
-
-#define RC_HT_SD_2040		(RC_HT_2040 | RC_SS | RC_DS)
-#define RC_HT_SDT_2040		(RC_HT_2040 | RC_SS | RC_DS | RC_TS)
-
-#define RC_HT_SDT_20		(RC_HT_20 | RC_SS | RC_DS | RC_TS)
-#define RC_HT_SDT_40		(RC_HT_40 | RC_SS | RC_DS | RC_TS)
-
-#define RC_ALL			(RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
-
-enum {
-	WLAN_RC_PHY_OFDM,
-	WLAN_RC_PHY_CCK,
-	WLAN_RC_PHY_HT_20_SS,
-	WLAN_RC_PHY_HT_20_DS,
-	WLAN_RC_PHY_HT_20_TS,
-	WLAN_RC_PHY_HT_40_SS,
-	WLAN_RC_PHY_HT_40_DS,
-	WLAN_RC_PHY_HT_40_TS,
-	WLAN_RC_PHY_HT_20_SS_HGI,
-	WLAN_RC_PHY_HT_20_DS_HGI,
-	WLAN_RC_PHY_HT_20_TS_HGI,
-	WLAN_RC_PHY_HT_40_SS_HGI,
-	WLAN_RC_PHY_HT_40_DS_HGI,
-	WLAN_RC_PHY_HT_40_TS_HGI,
-	WLAN_RC_PHY_MAX
-};
-
-#define WLAN_RC_PHY_DS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_DS)		\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_TS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_TS)		\
-				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-#define WLAN_RC_PHY_20(_phy)   ((_phy == WLAN_RC_PHY_HT_20_SS)		\
-				|| (_phy == WLAN_RC_PHY_HT_20_DS)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_TS)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_SS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
-#define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)		\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-#define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
-
-#define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)
-
-#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?	\
-	((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
-
-#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ?	\
-	(RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
-
-/* Return TRUE if flag supports HT20 && client supports HT20 or
- * return TRUE if flag supports HT40 && client supports HT40.
- * This is used becos some rates overlap between HT20/HT40.
- */
-#define WLAN_RC_PHY_HT_VALID(flag, capflag)			\
-	(((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
-	 ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
-
-#define WLAN_RC_DS_FLAG         (0x01)
-#define WLAN_RC_TS_FLAG         (0x02)
-#define WLAN_RC_40_FLAG         (0x04)
-#define WLAN_RC_SGI_FLAG        (0x08)
-#define WLAN_RC_HT_FLAG         (0x10)
-
-/**
- * struct ath_rate_table - Rate Control table
- * @rate_cnt: total number of rates for the given wireless mode
- * @mcs_start: MCS rate index offset
- * @rate_flags: Rate Control flags
- * @phy: CCK/OFDM/HT20/HT40
- * @ratekbps: rate in Kbits per second
- * @user_ratekbps: user rate in Kbits per second
- * @ratecode: rate that goes into HW descriptors
- * @dot11rate: value that goes into supported
- * 	rates info element of MLME
- * @ctrl_rate: Index of next lower basic rate, used for duration computation
- * @cw40index: Index of rates having 40MHz channel width
- * @sgi_index: Index of rates having Short Guard Interval
- * @ht_index: high throughput rates having 40MHz channel width and
- * 	Short Guard Interval
- * @probe_interval: interval for rate control to probe for other rates
- * @initial_ratemax: initial ratemax value
- */
-struct ath_rate_table {
-	int rate_cnt;
-	int mcs_start;
-	struct {
-		u16 rate_flags;
-		u8 phy;
-		u32 ratekbps;
-		u32 user_ratekbps;
-		u8 ratecode;
-		u8 dot11rate;
-	} info[RATE_TABLE_SIZE];
-	u32 probe_interval;
-	u8 initial_ratemax;
-};
-
-struct ath_rateset {
-	u8 rs_nrates;
-	u8 rs_rates[ATH_RATE_MAX];
-};
-
-struct ath_rc_stats {
-	u32 success;
-	u32 retries;
-	u32 xretries;
-	u8 per;
-};
-
-/**
- * struct ath_rate_priv - Rate Control priv data
- * @state: RC state
- * @probe_rate: rate we are probing at
- * @probe_time: msec timestamp for last probe
- * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
- * @max_valid_rate: maximum number of valid rate
- * @per_down_time: msec timestamp for last PER down step
- * @valid_phy_ratecnt: valid rate count
- * @rate_max_phy: phy index for the max rate
- * @per: PER for every valid rate in %
- * @probe_interval: interval for ratectrl to probe for other rates
- * @ht_cap: HT capabilities
- * @neg_rates: Negotatied rates
- * @neg_ht_rates: Negotiated HT rates
- */
-struct ath_rate_priv {
-	u8 rate_table_size;
-	u8 probe_rate;
-	u8 hw_maxretry_pktcnt;
-	u8 max_valid_rate;
-	u8 valid_rate_index[RATE_TABLE_SIZE];
-	u8 ht_cap;
-	u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
-	u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
-	u8 rate_max_phy;
-	u8 per[RATE_TABLE_SIZE];
-	u32 probe_time;
-	u32 per_down_time;
-	u32 probe_interval;
-	struct ath_rateset neg_rates;
-	struct ath_rateset neg_ht_rates;
-	const struct ath_rate_table *rate_table;
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-	struct dentry *debugfs_rcstats;
-	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
-#endif
-};
-
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
-void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
-void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
-			    int xretries, int retries, u8 per);
-#else
-static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
-}
-static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
-					  int xretries, int retries, u8 per)
-{
-}
-#endif
-
-#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL
-int ath_rate_control_register(void);
-void ath_rate_control_unregister(void);
-#else
-static inline int ath_rate_control_register(void)
-{
-	return 0;
-}
-
-static inline void ath_rate_control_unregister(void)
-{
-}
-#endif
-
-#endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a0ebdd000fc2..6c9accdb52e4 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
 			return NULL;
 
 		/*
-		 * mark descriptor as zero-length and set the 'more'
-		 * flag to ensure that both buffers get discarded
+		 * Re-check previous descriptor, in case it has been filled
+		 * in the mean time.
 		 */
-		rs->rs_datalen = 0;
-		rs->rs_more = true;
+		ret = ath9k_hw_rxprocdesc(ah, ds, rs);
+		if (ret == -EINPROGRESS) {
+			/*
+			 * mark descriptor as zero-length and set the 'more'
+			 * flag to ensure that both buffers get discarded
+			 */
+			rs->rs_datalen = 0;
+			rs->rs_more = true;
+		}
 	}
 
 	list_del(&bf->list);
@@ -755,204 +762,6 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
 	return bf;
 }
 
-/* Assumes you've already done the endian to CPU conversion */
-static bool ath9k_rx_accept(struct ath_common *common,
-			    struct ieee80211_hdr *hdr,
-			    struct ieee80211_rx_status *rxs,
-			    struct ath_rx_status *rx_stats,
-			    bool *decrypt_error)
-{
-	struct ath_softc *sc = (struct ath_softc *) common->priv;
-	bool is_mc, is_valid_tkip, strip_mic, mic_error;
-	struct ath_hw *ah = common->ah;
-	__le16 fc;
-
-	fc = hdr->frame_control;
-
-	is_mc = !!is_multicast_ether_addr(hdr->addr1);
-	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
-		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
-	strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
-		ieee80211_has_protected(fc) &&
-		!(rx_stats->rs_status &
-		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
-		 ATH9K_RXERR_KEYMISS));
-
-	/*
-	 * Key miss events are only relevant for pairwise keys where the
-	 * descriptor does contain a valid key index. This has been observed
-	 * mostly with CCMP encryption.
-	 */
-	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
-	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
-		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
-
-	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
-		!ieee80211_has_morefrags(fc) &&
-		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-		(rx_stats->rs_status & ATH9K_RXERR_MIC);
-
-	/*
-	 * The rx_stats->rs_status will not be set until the end of the
-	 * chained descriptors so it can be ignored if rs_more is set. The
-	 * rs_more will be false at the last element of the chained
-	 * descriptors.
-	 */
-	if (rx_stats->rs_status != 0) {
-		u8 status_mask;
-
-		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
-			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
-			mic_error = false;
-		}
-
-		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
-		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
-			*decrypt_error = true;
-			mic_error = false;
-		}
-
-		/*
-		 * Reject error frames with the exception of
-		 * decryption and MIC failures. For monitor mode,
-		 * we also ignore the CRC error.
-		 */
-		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-			      ATH9K_RXERR_KEYMISS;
-
-		if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
-			status_mask |= ATH9K_RXERR_CRC;
-
-		if (rx_stats->rs_status & ~status_mask)
-			return false;
-	}
-
-	/*
-	 * For unicast frames the MIC error bit can have false positives,
-	 * so all MIC error reports need to be validated in software.
-	 * False negatives are not common, so skip software verification
-	 * if the hardware considers the MIC valid.
-	 */
-	if (strip_mic)
-		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
-	else if (is_mc && mic_error)
-		rxs->flag |= RX_FLAG_MMIC_ERROR;
-
-	return true;
-}
-
-static int ath9k_process_rate(struct ath_common *common,
-			      struct ieee80211_hw *hw,
-			      struct ath_rx_status *rx_stats,
-			      struct ieee80211_rx_status *rxs)
-{
-	struct ieee80211_supported_band *sband;
-	enum ieee80211_band band;
-	unsigned int i = 0;
-	struct ath_softc __maybe_unused *sc = common->priv;
-	struct ath_hw *ah = sc->sc_ah;
-
-	band = ah->curchan->chan->band;
-	sband = hw->wiphy->bands[band];
-
-	if (IS_CHAN_QUARTER_RATE(ah->curchan))
-		rxs->flag |= RX_FLAG_5MHZ;
-	else if (IS_CHAN_HALF_RATE(ah->curchan))
-		rxs->flag |= RX_FLAG_10MHZ;
-
-	if (rx_stats->rs_rate & 0x80) {
-		/* HT rate */
-		rxs->flag |= RX_FLAG_HT;
-		rxs->flag |= rx_stats->flag;
-		rxs->rate_idx = rx_stats->rs_rate & 0x7f;
-		return 0;
-	}
-
-	for (i = 0; i < sband->n_bitrates; i++) {
-		if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
-			rxs->rate_idx = i;
-			return 0;
-		}
-		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
-			rxs->flag |= RX_FLAG_SHORTPRE;
-			rxs->rate_idx = i;
-			return 0;
-		}
-	}
-
-	/*
-	 * No valid hardware bitrate found -- we should not get here
-	 * because hardware has already validated this frame as OK.
-	 */
-	ath_dbg(common, ANY,
-		"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
-		rx_stats->rs_rate);
-	RX_STAT_INC(rx_rate_err);
-	return -EINVAL;
-}
-
-static void ath9k_process_rssi(struct ath_common *common,
-			       struct ieee80211_hw *hw,
-			       struct ath_rx_status *rx_stats,
-			       struct ieee80211_rx_status *rxs)
-{
-	struct ath_softc *sc = hw->priv;
-	struct ath_hw *ah = common->ah;
-	int last_rssi;
-	int rssi = rx_stats->rs_rssi;
-	int i, j;
-
-	/*
-	 * RSSI is not available for subframes in an A-MPDU.
-	 */
-	if (rx_stats->rs_moreaggr) {
-		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
-		return;
-	}
-
-	/*
-	 * Check if the RSSI for the last subframe in an A-MPDU
-	 * or an unaggregated frame is valid.
-	 */
-	if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
-		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
-		return;
-	}
-
-	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
-		s8 rssi;
-
-		if (!(ah->rxchainmask & BIT(i)))
-			continue;
-
-		rssi = rx_stats->rs_rssi_ctl[i];
-		if (rssi != ATH9K_RSSI_BAD) {
-		    rxs->chains |= BIT(j);
-		    rxs->chain_signal[j] = ah->noise + rssi;
-		}
-		j++;
-	}
-
-	/*
-	 * Update Beacon RSSI, this is used by ANI.
-	 */
-	if (rx_stats->is_mybeacon &&
-	    ((ah->opmode == NL80211_IFTYPE_STATION) ||
-	     (ah->opmode == NL80211_IFTYPE_ADHOC))) {
-		ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
-		last_rssi = sc->last_rssi;
-
-		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
-		if (rssi < 0)
-			rssi = 0;
-
-		ah->stats.avgbrssi = rssi;
-	}
-
-	rxs->signal = ah->noise + rx_stats->rs_rssi;
-}
-
 static void ath9k_process_tsf(struct ath_rx_status *rs,
 			      struct ieee80211_rx_status *rxs,
 			      u64 tsf)
@@ -985,32 +794,32 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_hdr *hdr;
 	bool discard_current = sc->rx.discard_next;
-	int ret = 0;
 
 	/*
 	 * Discard corrupt descriptors which are marked in
 	 * ath_get_next_rx_buf().
 	 */
-	sc->rx.discard_next = rx_stats->rs_more;
 	if (discard_current)
-		return -EINVAL;
+		goto corrupt;
+
+	sc->rx.discard_next = false;
 
 	/*
 	 * Discard zero-length packets.
 	 */
 	if (!rx_stats->rs_datalen) {
 		RX_STAT_INC(rx_len_err);
-		return -EINVAL;
+		goto corrupt;
 	}
 
-        /*
-         * rs_status follows rs_datalen so if rs_datalen is too large
-         * we can take a hint that hardware corrupted it, so ignore
-         * those frames.
-         */
+	/*
+	 * rs_status follows rs_datalen so if rs_datalen is too large
+	 * we can take a hint that hardware corrupted it, so ignore
+	 * those frames.
+	 */
 	if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
 		RX_STAT_INC(rx_len_err);
-		return -EINVAL;
+		goto corrupt;
 	}
 
 	/* Only use status info from the last fragment */
@@ -1024,10 +833,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 	 * This is different from the other corrupt descriptor
 	 * condition handled above.
 	 */
-	if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
-		ret = -EINVAL;
-		goto exit;
-	}
+	if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
+		goto corrupt;
 
 	hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
 
@@ -1043,18 +850,15 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 		if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
 			RX_STAT_INC(rx_spectral);
 
-		ret = -EINVAL;
-		goto exit;
+		return -EINVAL;
 	}
 
 	/*
 	 * everything but the rate is checked here, the rate check is done
 	 * separately to avoid doing two lookups for a rate for each frame.
 	 */
-	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
-		ret = -EINVAL;
-		goto exit;
-	}
+	if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error, sc->rx.rxfilter))
+		return -EINVAL;
 
 	if (ath_is_mybeacon(common, hdr)) {
 		RX_STAT_INC(rx_beacons);
@@ -1064,17 +868,21 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 	/*
 	 * This shouldn't happen, but have a safety check anyway.
 	 */
-	if (WARN_ON(!ah->curchan)) {
-		ret = -EINVAL;
-		goto exit;
-	}
+	if (WARN_ON(!ah->curchan))
+		return -EINVAL;
 
-	if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
-		ret =-EINVAL;
-		goto exit;
+	if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status)) {
+		/*
+		 * No valid hardware bitrate found -- we should not get here
+		 * because hardware has already validated this frame as OK.
+		 */
+		ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
+			rx_stats->rs_rate);
+		RX_STAT_INC(rx_rate_err);
+		return -EINVAL;
 	}
 
-	ath9k_process_rssi(common, hw, rx_stats, rx_status);
+	ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
 
 	rx_status->band = ah->curchan->chan->band;
 	rx_status->freq = ah->curchan->chan->center_freq;
@@ -1087,60 +895,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 		sc->rx.num_pkts++;
 #endif
 
-exit:
-	sc->rx.discard_next = false;
-	return ret;
-}
-
-static void ath9k_rx_skb_postprocess(struct ath_common *common,
-				     struct sk_buff *skb,
-				     struct ath_rx_status *rx_stats,
-				     struct ieee80211_rx_status *rxs,
-				     bool decrypt_error)
-{
-	struct ath_hw *ah = common->ah;
-	struct ieee80211_hdr *hdr;
-	int hdrlen, padpos, padsize;
-	u8 keyix;
-	__le16 fc;
-
-	/* see if any padding is done by the hw and remove it */
-	hdr = (struct ieee80211_hdr *) skb->data;
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	fc = hdr->frame_control;
-	padpos = ieee80211_hdrlen(fc);
-
-	/* The MAC header is padded to have 32-bit boundary if the
-	 * packet payload is non-zero. The general calculation for
-	 * padsize would take into account odd header lengths:
-	 * padsize = (4 - padpos % 4) % 4; However, since only
-	 * even-length headers are used, padding can only be 0 or 2
-	 * bytes and we can optimize this a bit. In addition, we must
-	 * not try to remove padding from short control frames that do
-	 * not have payload. */
-	padsize = padpos & 3;
-	if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
-		memmove(skb->data + padsize, skb->data, padpos);
-		skb_pull(skb, padsize);
-	}
-
-	keyix = rx_stats->rs_keyix;
-
-	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
-	    ieee80211_has_protected(fc)) {
-		rxs->flag |= RX_FLAG_DECRYPTED;
-	} else if (ieee80211_has_protected(fc)
-		   && !decrypt_error && skb->len >= hdrlen + 4) {
-		keyix = skb->data[hdrlen + 3] >> 6;
+	return 0;
 
-		if (test_bit(keyix, common->keymap))
-			rxs->flag |= RX_FLAG_DECRYPTED;
-	}
-	if (ah->sw_mgmt_crypto &&
-	    (rxs->flag & RX_FLAG_DECRYPTED) &&
-	    ieee80211_is_mgmt(fc))
-		/* Use software decrypt for management frames. */
-		rxs->flag &= ~RX_FLAG_DECRYPTED;
+corrupt:
+	sc->rx.discard_next = rx_stats->rs_more;
+	return -EINVAL;
 }
 
 /*
@@ -1292,8 +1051,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 			skb_pull(skb, ah->caps.rx_status_len);
 
 		if (!rs.rs_more)
-			ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
-						 rxs, decrypt_error);
+			ath9k_cmn_rx_skb_postprocess(common, hdr_skb, &rs,
+						     rxs, decrypt_error);
 
 		if (rs.rs_more) {
 			RX_STAT_INC(rx_frags);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 0a75e2f68c9d..312314ce7642 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
 	for (tidno = 0, tid = &an->tid[tidno];
 	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
 
-		if (!tid->sched)
-			continue;
-
 		ac = tid->ac;
 		txq = ac->txq;
 
 		ath_txq_lock(sc, txq);
 
+		if (!tid->sched) {
+			ath_txq_unlock(sc, txq);
+			continue;
+		}
+
 		buffered = ath_tid_has_buffered(tid);
 
 		tid->sched = false;
@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		txq->stopped = true;
 	}
 
+	if (txctl->an)
+		tid = ath_get_skb_tid(sc, txctl->an, skb);
+
 	if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
 		ath_txq_unlock(sc, txq);
 		txq = sc->tx.uapsdq;
 		ath_txq_lock(sc, txq);
 	} else if (txctl->an &&
 		   ieee80211_is_data_present(hdr->frame_control)) {
-		tid = ath_get_skb_tid(sc, txctl->an, skb);
-
 		WARN_ON(tid->ac->txq != txctl->txq);
 
 		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
@@ -2566,7 +2569,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 			sc->beacon.tx_processed = true;
 			sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
 
-			ath9k_csa_is_finished(sc);
+			ath9k_csa_update(sc);
 			continue;
 		}
 
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index ee25786b4447..73f12f196f14 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -44,6 +44,14 @@ static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
 	writel(data, wcn->mmio + addr);
 }
 
+#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data)		 \
+do {									 \
+	if (wcn->chip_version == WCN36XX_CHIP_3680)			 \
+		wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
+	else								 \
+		wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
+} while (0)								 \
+
 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
 {
 	*data = readl(wcn->mmio + addr);
@@ -680,7 +688,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
 
 	/* Setting interrupt path */
 	reg_data = WCN36XX_DXE_CCU_INT;
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
+	wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
 
 	/***************************************/
 	/* Init descriptors for TX LOW channel */
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h
index c88562f85de1..35ee7e966bd2 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -28,11 +28,11 @@ H2H_TEST_RX_TX = DMA2
 */
 
 /* DXE registers */
-#define WCN36XX_DXE_MEM_BASE			0x03000000
 #define WCN36XX_DXE_MEM_REG			0x202000
 
 #define WCN36XX_DXE_CCU_INT			0xA0011
-#define WCN36XX_DXE_REG_CCU_INT			0x200b10
+#define WCN36XX_DXE_REG_CCU_INT_3660		0x200b10
+#define WCN36XX_DXE_REG_CCU_INT_3680		0x2050dc
 
 /* TODO This must calculated properly but not hardcoded */
 #define WCN36XX_DXE_CTRL_TX_L			0x328a44
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h
index 3c2ef0c32f72..a1f1127d7808 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -4384,11 +4384,13 @@ enum place_holder_in_cap_bitmap {
 	MAX_FEATURE_SUPPORTED = 128,
 };
 
+#define WCN36XX_HAL_CAPS_SIZE 4
+
 struct wcn36xx_hal_feat_caps_msg {
 
 	struct wcn36xx_hal_msg_header header;
 
-	u32 feat_caps[4];
+	u32 feat_caps[WCN36XX_HAL_CAPS_SIZE];
 } __packed;
 
 /* status codes to help debug rekey failures */
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index e64a6784079e..4ab5370ab7a6 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -17,6 +17,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
+#include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include "wcn36xx.h"
 
@@ -177,6 +178,60 @@ static inline u8 get_sta_index(struct ieee80211_vif *vif,
 	       sta_priv->sta_index;
 }
 
+static const char * const wcn36xx_caps_names[] = {
+	"MCC",				/* 0 */
+	"P2P",				/* 1 */
+	"DOT11AC",			/* 2 */
+	"SLM_SESSIONIZATION",		/* 3 */
+	"DOT11AC_OPMODE",		/* 4 */
+	"SAP32STA",			/* 5 */
+	"TDLS",				/* 6 */
+	"P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
+	"WLANACTIVE_OFFLOAD",		/* 8 */
+	"BEACON_OFFLOAD",		/* 9 */
+	"SCAN_OFFLOAD",			/* 10 */
+	"ROAM_OFFLOAD",			/* 11 */
+	"BCN_MISS_OFFLOAD",		/* 12 */
+	"STA_POWERSAVE",		/* 13 */
+	"STA_ADVANCED_PWRSAVE",		/* 14 */
+	"AP_UAPSD",			/* 15 */
+	"AP_DFS",			/* 16 */
+	"BLOCKACK",			/* 17 */
+	"PHY_ERR",			/* 18 */
+	"BCN_FILTER",			/* 19 */
+	"RTT",				/* 20 */
+	"RATECTRL",			/* 21 */
+	"WOW"				/* 22 */
+};
+
+static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
+{
+	if (x >= ARRAY_SIZE(wcn36xx_caps_names))
+		return "UNKNOWN";
+	return wcn36xx_caps_names[x];
+}
+
+static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
+{
+	int i;
+
+	for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
+		if (get_feat_caps(wcn->fw_feat_caps, i))
+			wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i));
+	}
+}
+
+static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
+{
+	if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
+		wcn36xx_info("Chip is 3680\n");
+		wcn->chip_version = WCN36XX_CHIP_3680;
+	} else {
+		wcn36xx_info("Chip is 3660\n");
+		wcn->chip_version = WCN36XX_CHIP_3660;
+	}
+}
+
 static int wcn36xx_start(struct ieee80211_hw *hw)
 {
 	struct wcn36xx *wcn = hw->priv;
@@ -223,6 +278,16 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
 		goto out_free_smd_buf;
 	}
 
+	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
+		ret = wcn36xx_smd_feature_caps_exchange(wcn);
+		if (ret)
+			wcn36xx_warn("Exchange feature caps failed\n");
+		else
+			wcn36xx_feat_caps_info(wcn);
+	}
+
+	wcn36xx_detect_chip_version(wcn);
+
 	/* DMA channel initialization */
 	ret = wcn36xx_dxe_init(wcn);
 	if (ret) {
@@ -232,11 +297,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
 
 	wcn36xx_debugfs_init(wcn);
 
-	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
-		ret = wcn36xx_smd_feature_caps_exchange(wcn);
-		if (ret)
-			wcn36xx_warn("Exchange feature caps failed\n");
-	}
 	INIT_LIST_HEAD(&wcn->vif_list);
 	return 0;
 
@@ -648,6 +708,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
 			    bss_conf->enable_beacon);
 
 		if (bss_conf->enable_beacon) {
+			vif_priv->dtim_period = bss_conf->dtim_period;
 			vif_priv->bss_index = 0xff;
 			wcn36xx_smd_config_bss(wcn, vif, NULL,
 					       vif->addr, false);
@@ -992,6 +1053,7 @@ static int wcn36xx_remove(struct platform_device *pdev)
 	struct wcn36xx *wcn = hw->priv;
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
 
+	release_firmware(wcn->nv);
 	mutex_destroy(&wcn->hal_mutex);
 
 	ieee80211_unregister_hw(hw);
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 750626b0e22d..7bf0ef8a1f56 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -195,9 +195,11 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 {
 	int ret = 0;
+	unsigned long start;
 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
 
 	init_completion(&wcn->hal_rsp_compl);
+	start = jiffies;
 	ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
 	if (ret) {
 		wcn36xx_err("HAL TX failed\n");
@@ -205,10 +207,13 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 	}
 	if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
 		msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
-		wcn36xx_err("Timeout while waiting SMD response\n");
+		wcn36xx_err("Timeout! No SMD response in %dms\n",
+			    HAL_MSG_TIMEOUT);
 		ret = -ETIME;
 		goto out;
 	}
+	wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms",
+		    jiffies_to_msecs(jiffies - start));
 out:
 	return ret;
 }
@@ -246,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
 
 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 {
-	const struct firmware *nv;
 	struct nv_data *nv_d;
 	struct wcn36xx_hal_nv_img_download_req_msg msg_body;
 	int fw_bytes_left;
 	int ret;
 	u16 fm_offset = 0;
 
-	ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev);
-	if (ret) {
-		wcn36xx_err("Failed to load nv file %s: %d\n",
-			      WLAN_NV_FILE, ret);
-		goto out_free_nv;
+	if (!wcn->nv) {
+		ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
+		if (ret) {
+			wcn36xx_err("Failed to load nv file %s: %d\n",
+				      WLAN_NV_FILE, ret);
+			goto out;
+		}
 	}
 
-	nv_d = (struct nv_data *)nv->data;
+	nv_d = (struct nv_data *)wcn->nv->data;
 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
 
 	msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
@@ -270,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 	mutex_lock(&wcn->hal_mutex);
 
 	do {
-		fw_bytes_left = nv->size - fm_offset - 4;
+		fw_bytes_left = wcn->nv->size - fm_offset - 4;
 		if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
 			msg_body.last_fragment = 0;
 			msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
@@ -308,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 
 out_unlock:
 	mutex_unlock(&wcn->hal_mutex);
-out_free_nv:
-	release_firmware(nv);
-
-	return ret;
+out:	return ret;
 }
 
 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
@@ -899,11 +902,12 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
 
 	sta_priv->sta_index = params->sta_index;
 	sta_priv->dpu_desc_index = params->dpu_index;
+	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
 
 	wcn36xx_dbg(WCN36XX_DBG_HAL,
-		    "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n",
+		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
 		    params->status, params->sta_index, params->bssid_index,
-		    params->p2p);
+		    params->uc_ucast_sig, params->p2p);
 
 	return 0;
 }
@@ -1118,7 +1122,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
 		priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
 	}
 
-	priv_vif->ucast_dpu_signature = params->ucast_dpu_signature;
+	priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
 
 	return 0;
 }
@@ -1637,12 +1641,12 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
 
 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
 	if (ret) {
-		wcn36xx_err("Sending hal_exit_bmps failed\n");
+		wcn36xx_err("Sending hal_keep_alive failed\n");
 		goto out;
 	}
 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
 	if (ret) {
-		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
+		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
 		goto out;
 	}
 out:
@@ -1682,8 +1686,7 @@ out:
 	return ret;
 }
 
-static inline void set_feat_caps(u32 *bitmap,
-				 enum place_holder_in_cap_bitmap cap)
+void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
 {
 	int arr_idx, bit_idx;
 
@@ -1697,8 +1700,7 @@ static inline void set_feat_caps(u32 *bitmap,
 	bitmap[arr_idx] |= (1 << bit_idx);
 }
 
-static inline int get_feat_caps(u32 *bitmap,
-				enum place_holder_in_cap_bitmap cap)
+int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
 {
 	int arr_idx, bit_idx;
 	int ret = 0;
@@ -1714,8 +1716,7 @@ static inline int get_feat_caps(u32 *bitmap,
 	return ret;
 }
 
-static inline void clear_feat_caps(u32 *bitmap,
-				enum place_holder_in_cap_bitmap cap)
+void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
 {
 	int arr_idx, bit_idx;
 
@@ -1731,8 +1732,8 @@ static inline void clear_feat_caps(u32 *bitmap,
 
 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
 {
-	struct wcn36xx_hal_feat_caps_msg msg_body;
-	int ret = 0;
+	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
+	int ret = 0, i;
 
 	mutex_lock(&wcn->hal_mutex);
 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
@@ -1746,12 +1747,15 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
 		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
 		goto out;
 	}
-	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
-	if (ret) {
-		wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n",
-			    ret);
+	if (wcn->hal_rsp_len != sizeof(*rsp)) {
+		wcn36xx_err("Invalid hal_feature_caps_exchange response");
 		goto out;
 	}
+
+	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
+
+	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
+		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
 out:
 	mutex_unlock(&wcn->hal_mutex);
 	return ret;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index e7c39019c6f1..008d03423dbf 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -24,7 +24,7 @@
 
 #define WCN36XX_HAL_BUF_SIZE				4096
 
-#define HAL_MSG_TIMEOUT 200
+#define HAL_MSG_TIMEOUT 500
 #define WCN36XX_SMSM_WLAN_TX_ENABLE			0x00000400
 #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY		0x00000200
 /* The PNO version info be contained in the rsp msg */
@@ -112,6 +112,9 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
 			     u32 arg3, u32 arg4, u32 arg5);
 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn);
+void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
+int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
+void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap);
 
 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
 		struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index b2b60e30caaf..32bb26a0db2a 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -57,8 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
 		       RX_FLAG_MMIC_STRIPPED |
 		       RX_FLAG_DECRYPTED;
 
-	wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n",
-		    status.flag,  status.vendor_radiotap_len);
+	wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
 
 	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 
@@ -132,6 +131,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
 				   struct ieee80211_vif,
 				   drv_priv);
 
+		bd->dpu_sign = sta_priv->ucast_dpu_sign;
 		if (vif->type == NL80211_IFTYPE_STATION) {
 			bd->sta_index = sta_priv->bss_sta_index;
 			bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
@@ -145,10 +145,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
 		__vif_priv = get_vif_by_addr(wcn, hdr->addr2);
 		bd->sta_index = __vif_priv->self_sta_index;
 		bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
+		bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
 	}
 
-	bd->dpu_sign = __vif_priv->ucast_dpu_signature;
-
 	if (ieee80211_is_nullfunc(hdr->frame_control) ||
 	   (sta_priv && !sta_priv->is_data_encrypted))
 		bd->dpu_ne = 1;
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 8fa5cbace5ab..f0fb81dfd17b 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -125,10 +125,10 @@ struct wcn36xx_vif {
 	enum wcn36xx_power_state pw_state;
 
 	u8 bss_index;
-	u8 ucast_dpu_signature;
 	/* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */
 	u8 self_sta_index;
 	u8 self_dpu_desc_index;
+	u8 self_ucast_dpu_sign;
 };
 
 /**
@@ -159,6 +159,7 @@ struct wcn36xx_sta {
 	u16 tid;
 	u8 sta_index;
 	u8 dpu_desc_index;
+	u8 ucast_dpu_sign;
 	u8 bss_sta_index;
 	u8 bss_dpu_desc_index;
 	bool is_data_encrypted;
@@ -171,10 +172,14 @@ struct wcn36xx {
 	struct device		*dev;
 	struct list_head	vif_list;
 
+	const struct firmware	*nv;
+
 	u8			fw_revision;
 	u8			fw_version;
 	u8			fw_minor;
 	u8			fw_major;
+	u32			fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
+	u32			chip_version;
 
 	/* extra byte for the NULL termination */
 	u8			crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
@@ -222,6 +227,9 @@ struct wcn36xx {
 
 };
 
+#define WCN36XX_CHIP_3660	0
+#define WCN36XX_CHIP_3680	1
+
 static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
 					 u8 major,
 					 u8 minor,
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index eeceab39cda2..e1c8cc4a4b92 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -41,30 +41,28 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
 	switch (use_msi) {
 	case 3:
 	case 1:
+		wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
+		break;
 	case 0:
+		wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
 		break;
 	default:
-		wil_err(wil, "Invalid use_msi=%d, default to 1\n",
-			use_msi);
+		wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi);
 		use_msi = 1;
 	}
-	wil->n_msi = use_msi;
-	if (wil->n_msi) {
-		wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
-		rc = pci_enable_msi_block(pdev, wil->n_msi);
-		if (rc && (wil->n_msi == 3)) {
-			wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
-			wil->n_msi = 1;
-			rc = pci_enable_msi_block(pdev, wil->n_msi);
-		}
-		if (rc) {
-			wil_err(wil, "pci_enable_msi failed, use INTx\n");
-			wil->n_msi = 0;
-		}
-	} else {
-		wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
+
+	if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) {
+		wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
+		use_msi = 1;
+	}
+
+	if (use_msi == 1 && pci_enable_msi(pdev)) {
+		wil_err(wil, "pci_enable_msi failed, use INTx\n");
+		use_msi = 0;
 	}
 
+	wil->n_msi = use_msi;
+
 	rc = wil6210_init_irq(wil, pdev->irq);
 	if (rc)
 		goto stop_master;
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index abac25ee958d..f476fc337d64 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -58,41 +58,6 @@ enum b43_verbosity {
 #endif
 };
 
-
-/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
-static inline u8 b43_freq_to_channel_5ghz(int freq)
-{
-	return ((freq - 5000) / 5);
-}
-static inline u8 b43_freq_to_channel_2ghz(int freq)
-{
-	u8 channel;
-
-	if (freq == 2484)
-		channel = 14;
-	else
-		channel = (freq - 2407) / 5;
-
-	return channel;
-}
-
-/* Lightweight function to convert a channel number to a frequency (in Mhz). */
-static inline int b43_channel_to_freq_5ghz(u8 channel)
-{
-	return (5000 + (5 * channel));
-}
-static inline int b43_channel_to_freq_2ghz(u8 channel)
-{
-	int freq;
-
-	if (channel == 14)
-		freq = 2484;
-	else
-		freq = 2407 + (5 * channel);
-
-	return freq;
-}
-
 static inline int b43_is_cck_rate(int rate)
 {
 	return (rate == B43_CCK_RATE_1MB ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 50e5ddb12fb3..218a0f37af46 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -806,7 +806,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 		B43_WARN_ON(1);
 		/* FIXME: We don't really know which value the "chanid" contains.
 		 *        So the following assignment might be wrong. */
-		status.freq = b43_channel_to_freq_5ghz(chanid);
+		status.freq =
+			ieee80211_channel_to_frequency(chanid, status.band);
 		break;
 	case B43_PHYTYPE_G:
 		status.band = IEEE80211_BAND_2GHZ;
@@ -819,13 +820,12 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 	case B43_PHYTYPE_HT:
 		/* chanid is the SHM channel cookie. Which is the plain
 		 * channel number in b43. */
-		if (chanstat & B43_RX_CHAN_5GHZ) {
+		if (chanstat & B43_RX_CHAN_5GHZ)
 			status.band = IEEE80211_BAND_5GHZ;
-			status.freq = b43_channel_to_freq_5ghz(chanid);
-		} else {
+		else
 			status.band = IEEE80211_BAND_2GHZ;
-			status.freq = b43_channel_to_freq_2ghz(chanid);
-		}
+		status.freq =
+			ieee80211_channel_to_frequency(chanid, status.band);
 		break;
 	default:
 		B43_WARN_ON(1);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 57cddee03252..1d2ceac3a221 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__
 obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
 brcmfmac-objs += \
 		wl_cfg80211.o \
+		chip.o \
 		fwil.o \
 		fweh.o \
 		fwsignal.o \
@@ -36,8 +37,7 @@ brcmfmac-objs += \
 		btcoex.o
 brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
 		dhd_sdio.o \
-		bcmsdh.o \
-		sdio_chip.o
+		bcmsdh.o
 brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
 		usb.o
 brcmfmac-$(CONFIG_BRCMDBG) += \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index fa35b23bbaa7..07e7d2520257 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -43,7 +43,6 @@
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
 #include "sdio_host.h"
-#include "sdio_chip.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
 
@@ -827,7 +826,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
 		}
 		if (!write)
 			memcpy(data, pkt->data, dsize);
-		skb_trim(pkt, dsize);
+		skb_trim(pkt, 0);
 
 		/* Adjust for next transfer (if any) */
 		size -= dsize;
@@ -1115,11 +1114,12 @@ static struct sdio_driver brcmf_sdmmc_driver = {
 	.remove = brcmf_ops_sdio_remove,
 	.name = BRCMFMAC_SDIO_PDATA_NAME,
 	.id_table = brcmf_sdmmc_ids,
-#ifdef CONFIG_PM_SLEEP
 	.drv = {
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
 		.pm = &brcmf_sdio_pm_ops,
-	},
 #endif	/* CONFIG_PM_SLEEP */
+	},
 };
 
 static int brcmf_sdio_pd_probe(struct platform_device *pdev)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
new file mode 100644
index 000000000000..a07b95ef9e70
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/ssb/ssb_regs.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
+
+#include <defs.h>
+#include <soc.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <chipcommon.h>
+#include "dhd_dbg.h"
+#include "chip.h"
+
+/* SOC Interconnect types (aka chip types) */
+#define SOCI_SB		0
+#define SOCI_AI		1
+
+/* PL-368 DMP definitions */
+#define DMP_DESC_TYPE_MSK	0x0000000F
+#define  DMP_DESC_EMPTY		0x00000000
+#define  DMP_DESC_VALID		0x00000001
+#define  DMP_DESC_COMPONENT	0x00000001
+#define  DMP_DESC_MASTER_PORT	0x00000003
+#define  DMP_DESC_ADDRESS	0x00000005
+#define  DMP_DESC_ADDRSIZE_GT32	0x00000008
+#define  DMP_DESC_EOT		0x0000000F
+
+#define DMP_COMP_DESIGNER	0xFFF00000
+#define DMP_COMP_DESIGNER_S	20
+#define DMP_COMP_PARTNUM	0x000FFF00
+#define DMP_COMP_PARTNUM_S	8
+#define DMP_COMP_CLASS		0x000000F0
+#define DMP_COMP_CLASS_S	4
+#define DMP_COMP_REVISION	0xFF000000
+#define DMP_COMP_REVISION_S	24
+#define DMP_COMP_NUM_SWRAP	0x00F80000
+#define DMP_COMP_NUM_SWRAP_S	19
+#define DMP_COMP_NUM_MWRAP	0x0007C000
+#define DMP_COMP_NUM_MWRAP_S	14
+#define DMP_COMP_NUM_SPORT	0x00003E00
+#define DMP_COMP_NUM_SPORT_S	9
+#define DMP_COMP_NUM_MPORT	0x000001F0
+#define DMP_COMP_NUM_MPORT_S	4
+
+#define DMP_MASTER_PORT_UID	0x0000FF00
+#define DMP_MASTER_PORT_UID_S	8
+#define DMP_MASTER_PORT_NUM	0x000000F0
+#define DMP_MASTER_PORT_NUM_S	4
+
+#define DMP_SLAVE_ADDR_BASE	0xFFFFF000
+#define DMP_SLAVE_ADDR_BASE_S	12
+#define DMP_SLAVE_PORT_NUM	0x00000F00
+#define DMP_SLAVE_PORT_NUM_S	8
+#define DMP_SLAVE_TYPE		0x000000C0
+#define DMP_SLAVE_TYPE_S	6
+#define  DMP_SLAVE_TYPE_SLAVE	0
+#define  DMP_SLAVE_TYPE_BRIDGE	1
+#define  DMP_SLAVE_TYPE_SWRAP	2
+#define  DMP_SLAVE_TYPE_MWRAP	3
+#define DMP_SLAVE_SIZE_TYPE	0x00000030
+#define DMP_SLAVE_SIZE_TYPE_S	4
+#define  DMP_SLAVE_SIZE_4K	0
+#define  DMP_SLAVE_SIZE_8K	1
+#define  DMP_SLAVE_SIZE_16K	2
+#define  DMP_SLAVE_SIZE_DESC	3
+
+/* EROM CompIdentB */
+#define CIB_REV_MASK		0xff000000
+#define CIB_REV_SHIFT		24
+
+/* ARM CR4 core specific control flag bits */
+#define ARMCR4_BCMA_IOCTL_CPUHALT	0x0020
+
+/* D11 core specific control flag bits */
+#define D11_BCMA_IOCTL_PHYCLOCKEN	0x0004
+#define D11_BCMA_IOCTL_PHYRESET		0x0008
+
+/* chip core base & ramsize */
+/* bcm4329 */
+/* SDIO device core, ID 0x829 */
+#define BCM4329_CORE_BUS_BASE		0x18011000
+/* internal memory core, ID 0x80e */
+#define BCM4329_CORE_SOCRAM_BASE	0x18003000
+/* ARM Cortex M3 core, ID 0x82a */
+#define BCM4329_CORE_ARM_BASE		0x18002000
+#define BCM4329_RAMSIZE			0x48000
+
+/* bcm43143 */
+/* SDIO device core */
+#define BCM43143_CORE_BUS_BASE		0x18002000
+/* internal memory core */
+#define BCM43143_CORE_SOCRAM_BASE	0x18004000
+/* ARM Cortex M3 core, ID 0x82a */
+#define BCM43143_CORE_ARM_BASE		0x18003000
+#define BCM43143_RAMSIZE		0x70000
+
+#define CORE_SB(base, field) \
+		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+#define	SBCOREREV(sbidh) \
+	((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
+	  ((sbidh) & SSB_IDHIGH_RCLO))
+
+struct sbconfig {
+	u32 PAD[2];
+	u32 sbipsflag;	/* initiator port ocp slave flag */
+	u32 PAD[3];
+	u32 sbtpsflag;	/* target port ocp slave flag */
+	u32 PAD[11];
+	u32 sbtmerrloga;	/* (sonics >= 2.3) */
+	u32 PAD;
+	u32 sbtmerrlog;	/* (sonics >= 2.3) */
+	u32 PAD[3];
+	u32 sbadmatch3;	/* address match3 */
+	u32 PAD;
+	u32 sbadmatch2;	/* address match2 */
+	u32 PAD;
+	u32 sbadmatch1;	/* address match1 */
+	u32 PAD[7];
+	u32 sbimstate;	/* initiator agent state */
+	u32 sbintvec;	/* interrupt mask */
+	u32 sbtmstatelow;	/* target state */
+	u32 sbtmstatehigh;	/* target state */
+	u32 sbbwa0;		/* bandwidth allocation table0 */
+	u32 PAD;
+	u32 sbimconfiglow;	/* initiator configuration */
+	u32 sbimconfighigh;	/* initiator configuration */
+	u32 sbadmatch0;	/* address match0 */
+	u32 PAD;
+	u32 sbtmconfiglow;	/* target configuration */
+	u32 sbtmconfighigh;	/* target configuration */
+	u32 sbbconfig;	/* broadcast configuration */
+	u32 PAD;
+	u32 sbbstate;	/* broadcast state */
+	u32 PAD[3];
+	u32 sbactcnfg;	/* activate configuration */
+	u32 PAD[3];
+	u32 sbflagst;	/* current sbflags */
+	u32 PAD[3];
+	u32 sbidlow;		/* identification */
+	u32 sbidhigh;	/* identification */
+};
+
+struct brcmf_core_priv {
+	struct brcmf_core pub;
+	u32 wrapbase;
+	struct list_head list;
+	struct brcmf_chip_priv *chip;
+};
+
+/* ARM CR4 core specific control flag bits */
+#define ARMCR4_BCMA_IOCTL_CPUHALT	0x0020
+
+/* D11 core specific control flag bits */
+#define D11_BCMA_IOCTL_PHYCLOCKEN	0x0004
+#define D11_BCMA_IOCTL_PHYRESET		0x0008
+
+struct brcmf_chip_priv {
+	struct brcmf_chip pub;
+	const struct brcmf_buscore_ops *ops;
+	void *ctx;
+	/* assured first core is chipcommon, second core is buscore */
+	struct list_head cores;
+	u16 num_cores;
+
+	bool (*iscoreup)(struct brcmf_core_priv *core);
+	void (*coredisable)(struct brcmf_core_priv *core, u32 prereset,
+			    u32 reset);
+	void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset,
+			  u32 postreset);
+};
+
+static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci,
+				  struct brcmf_core *core)
+{
+	u32 regdata;
+
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh));
+	core->rev = SBCOREREV(regdata);
+}
+
+static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	u32 address;
+
+	ci = core->chip;
+	address = CORE_SB(core->pub.base, sbtmstatelow);
+	regdata = ci->ops->read32(ci->ctx, address);
+	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
+		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
+	return SSB_TMSLOW_CLOCK == regdata;
+}
+
+static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	bool ret;
+
+	ci = core->chip;
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+	ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
+
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
+	ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
+
+	return ret;
+}
+
+static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core,
+				      u32 prereset, u32 reset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 val, base;
+
+	ci = core->chip;
+	base = core->pub.base;
+	val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	if (val & SSB_TMSLOW_RESET)
+		return;
+
+	val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	if ((val & SSB_TMSLOW_CLOCK) != 0) {
+		/*
+		 * set target reject and spin until busy is clear
+		 * (preserve core-specific bits)
+		 */
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+					 val | SSB_TMSLOW_REJECT);
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		udelay(1);
+		SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh))
+			  & SSB_TMSHIGH_BUSY), 100000);
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
+		if (val & SSB_TMSHIGH_BUSY)
+			brcmf_err("core state still busy\n");
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
+		if (val & SSB_IDLOW_INITIATOR) {
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			val |= SSB_IMSTATE_REJECT;
+			ci->ops->write32(ci->ctx,
+					 CORE_SB(base, sbimstate), val);
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			udelay(1);
+			SPINWAIT((ci->ops->read32(ci->ctx,
+						  CORE_SB(base, sbimstate)) &
+				  SSB_IMSTATE_BUSY), 100000);
+		}
+
+		/* set reset and reject while enabling the clocks */
+		val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+		      SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		udelay(10);
+
+		/* clear the initiator reject bit */
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
+		if (val & SSB_IDLOW_INITIATOR) {
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			val &= ~SSB_IMSTATE_REJECT;
+			ci->ops->write32(ci->ctx,
+					 CORE_SB(base, sbimstate), val);
+		}
+	}
+
+	/* leave reset and reject asserted */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
+	udelay(1);
+}
+
+static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
+				      u32 prereset, u32 reset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+
+	ci = core->chip;
+
+	/* if core is already in reset, just return */
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
+	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
+		return;
+
+	/* configure reset */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+
+	/* put in reset */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL,
+			 BCMA_RESET_CTL_RESET);
+	usleep_range(10, 20);
+
+	/* wait till reset is 1 */
+	SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
+		 BCMA_RESET_CTL_RESET, 300);
+
+	/* in-reset configure */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+}
+
+static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset,
+				    u32 reset, u32 postreset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	u32 base;
+
+	ci = core->chip;
+	base = core->pub.base;
+	/*
+	 * Must do the disable sequence first to work for
+	 * arbitrary current core state.
+	 */
+	brcmf_chip_sb_coredisable(core, 0, 0);
+
+	/*
+	 * Now do the initialization sequence.
+	 * set reset while enabling the clock and
+	 * forcing them on throughout the core
+	 */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+			 SSB_TMSLOW_RESET);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+
+	/* clear any serror */
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
+	if (regdata & SSB_TMSHIGH_SERR)
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);
+
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate));
+	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
+		regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata);
+	}
+
+	/* clear reset and allow it to propagate throughout the core */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+
+	/* leave clock enabled */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_CLOCK);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+}
+
+static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset,
+				    u32 reset, u32 postreset)
+{
+	struct brcmf_chip_priv *ci;
+	int count;
+
+	ci = core->chip;
+
+	/* must disable first to work for arbitrary current core state */
+	brcmf_chip_ai_coredisable(core, prereset, reset);
+
+	count = 0;
+	while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) &
+	       BCMA_RESET_CTL_RESET) {
+		ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0);
+		count++;
+		if (count > 50)
+			break;
+		usleep_range(40, 60);
+	}
+
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 postreset | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+}
+
+static char *brcmf_chip_name(uint chipid, char *buf, uint len)
+{
+	const char *fmt;
+
+	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+	snprintf(buf, len, fmt, chipid);
+	return buf;
+}
+
+static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
+					      u16 coreid, u32 base,
+					      u32 wrapbase)
+{
+	struct brcmf_core_priv *core;
+
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (!core)
+		return ERR_PTR(-ENOMEM);
+
+	core->pub.id = coreid;
+	core->pub.base = base;
+	core->chip = ci;
+	core->wrapbase = wrapbase;
+
+	list_add_tail(&core->list, &ci->cores);
+	return &core->pub;
+}
+
+#ifdef DEBUG
+/* safety check for chipinfo */
+static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core_priv *core;
+	bool need_socram = false;
+	bool has_socram = false;
+	int idx = 1;
+
+	list_for_each_entry(core, &ci->cores, list) {
+		brcmf_dbg(INFO, " [%-2d] core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
+			  idx++, core->pub.id, core->pub.rev, core->pub.base,
+			  core->wrapbase);
+
+		switch (core->pub.id) {
+		case BCMA_CORE_ARM_CM3:
+			need_socram = true;
+			break;
+		case BCMA_CORE_INTERNAL_MEM:
+			has_socram = true;
+			break;
+		case BCMA_CORE_ARM_CR4:
+			if (ci->pub.rambase == 0) {
+				brcmf_err("RAM base not provided with ARM CR4 core\n");
+				return -ENOMEM;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* check RAM core presence for ARM CM3 core */
+	if (need_socram && !has_socram) {
+		brcmf_err("RAM core not provided with ARM CM3 core\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+#else	/* DEBUG */
+static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
+{
+	return 0;
+}
+#endif
+
+static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+{
+	switch (ci->pub.chip) {
+	case BCM4329_CHIP_ID:
+		ci->pub.ramsize = BCM4329_RAMSIZE;
+		break;
+	case BCM43143_CHIP_ID:
+		ci->pub.ramsize = BCM43143_RAMSIZE;
+		break;
+	case BCM43241_CHIP_ID:
+		ci->pub.ramsize = 0x90000;
+		break;
+	case BCM4330_CHIP_ID:
+		ci->pub.ramsize = 0x48000;
+		break;
+	case BCM4334_CHIP_ID:
+		ci->pub.ramsize = 0x80000;
+		break;
+	case BCM4335_CHIP_ID:
+		ci->pub.ramsize = 0xc0000;
+		ci->pub.rambase = 0x180000;
+		break;
+	case BCM43362_CHIP_ID:
+		ci->pub.ramsize = 0x3c000;
+		break;
+	case BCM4339_CHIP_ID:
+		ci->pub.ramsize = 0xc0000;
+		ci->pub.rambase = 0x180000;
+		break;
+	default:
+		brcmf_err("unknown chip: %s\n", ci->pub.name);
+		break;
+	}
+}
+
+static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
+				   u8 *type)
+{
+	u32 val;
+
+	/* read next descriptor */
+	val = ci->ops->read32(ci->ctx, *eromaddr);
+	*eromaddr += 4;
+
+	if (!type)
+		return val;
+
+	/* determine descriptor type */
+	*type = (val & DMP_DESC_TYPE_MSK);
+	if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)
+		*type = DMP_DESC_ADDRESS;
+
+	return val;
+}
+
+static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,
+				      u32 *regbase, u32 *wrapbase)
+{
+	u8 desc;
+	u32 val;
+	u8 mpnum = 0;
+	u8 stype, sztype, wraptype;
+
+	*regbase = 0;
+	*wrapbase = 0;
+
+	val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
+	if (desc == DMP_DESC_MASTER_PORT) {
+		mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S;
+		wraptype = DMP_SLAVE_TYPE_MWRAP;
+	} else if (desc == DMP_DESC_ADDRESS) {
+		/* revert erom address */
+		*eromaddr -= 4;
+		wraptype = DMP_SLAVE_TYPE_SWRAP;
+	} else {
+		*eromaddr -= 4;
+		return -EILSEQ;
+	}
+
+	do {
+		/* locate address descriptor */
+		do {
+			val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
+			/* unexpected table end */
+			if (desc == DMP_DESC_EOT) {
+				*eromaddr -= 4;
+				return -EFAULT;
+			}
+		} while (desc != DMP_DESC_ADDRESS);
+
+		/* skip upper 32-bit address descriptor */
+		if (val & DMP_DESC_ADDRSIZE_GT32)
+			brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+
+		sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;
+
+		/* next size descriptor can be skipped */
+		if (sztype == DMP_SLAVE_SIZE_DESC) {
+			val = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+			/* skip upper size descriptor if present */
+			if (val & DMP_DESC_ADDRSIZE_GT32)
+				brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+		}
+
+		/* only look for 4K register regions */
+		if (sztype != DMP_SLAVE_SIZE_4K)
+			continue;
+
+		stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;
+
+		/* only regular slave and wrapper */
+		if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)
+			*regbase = val & DMP_SLAVE_ADDR_BASE;
+		if (*wrapbase == 0 && stype == wraptype)
+			*wrapbase = val & DMP_SLAVE_ADDR_BASE;
+	} while (*regbase == 0 || *wrapbase == 0);
+
+	return 0;
+}
+
+static
+int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core *core;
+	u32 eromaddr;
+	u8 desc_type = 0;
+	u32 val;
+	u16 id;
+	u8 nmp, nsp, nmw, nsw, rev;
+	u32 base, wrap;
+	int err;
+
+	eromaddr = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, eromptr));
+
+	while (desc_type != DMP_DESC_EOT) {
+		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
+		if (!(val & DMP_DESC_VALID))
+			continue;
+
+		if (desc_type == DMP_DESC_EMPTY)
+			continue;
+
+		/* need a component descriptor */
+		if (desc_type != DMP_DESC_COMPONENT)
+			continue;
+
+		id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;
+
+		/* next descriptor must be component as well */
+		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
+		if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))
+			return -EFAULT;
+
+		/* only look at cores with master port(s) */
+		nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S;
+		nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S;
+		nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
+		nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
+		rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
+
+		/* need core with ports */
+		if (nmw + nsw == 0)
+			continue;
+
+		/* try to obtain register address info */
+		err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);
+		if (err)
+			continue;
+
+		/* finally a core to be added */
+		core = brcmf_chip_add_core(ci, id, base, wrap);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
+		core->rev = rev;
+	}
+
+	return 0;
+}
+
+static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core *core;
+	u32 regdata;
+	u32 socitype;
+
+	/* Get CC core rev
+	 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
+	 * For different chiptypes or old sdio hosts w/o chipcommon,
+	 * other ways of recognition should be added here.
+	 */
+	regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, chipid));
+	ci->pub.chip = regdata & CID_ID_MASK;
+	ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+	socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
+
+	brcmf_chip_name(ci->pub.chip, ci->pub.name, sizeof(ci->pub.name));
+	brcmf_dbg(INFO, "found %s chip: BCM%s, rev=%d\n",
+		  socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name,
+		  ci->pub.chiprev);
+
+	if (socitype == SOCI_SB) {
+		if (ci->pub.chip != BCM4329_CHIP_ID) {
+			brcmf_err("SB chip is not supported\n");
+			return -ENODEV;
+		}
+		ci->iscoreup = brcmf_chip_sb_iscoreup;
+		ci->coredisable = brcmf_chip_sb_coredisable;
+		ci->resetcore = brcmf_chip_sb_resetcore;
+
+		core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
+					   SI_ENUM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
+					   BCM4329_CORE_BUS_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
+					   BCM4329_CORE_SOCRAM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
+					   BCM4329_CORE_ARM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+
+		core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
+		brcmf_chip_sb_corerev(ci, core);
+	} else if (socitype == SOCI_AI) {
+		ci->iscoreup = brcmf_chip_ai_iscoreup;
+		ci->coredisable = brcmf_chip_ai_coredisable;
+		ci->resetcore = brcmf_chip_ai_resetcore;
+
+		brcmf_chip_dmp_erom_scan(ci);
+	} else {
+		brcmf_err("chip backplane type %u is not supported\n",
+			  socitype);
+		return -ENODEV;
+	}
+
+	brcmf_chip_get_raminfo(ci);
+
+	return brcmf_chip_cores_check(ci);
+}
+
+static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
+{
+	struct brcmf_core *core;
+	struct brcmf_core_priv *cr4;
+	u32 val;
+
+
+	core = brcmf_chip_get_core(&chip->pub, id);
+	if (!core)
+		return;
+
+	switch (id) {
+	case BCMA_CORE_ARM_CM3:
+		brcmf_chip_coredisable(core, 0, 0);
+		break;
+	case BCMA_CORE_ARM_CR4:
+		cr4 = container_of(core, struct brcmf_core_priv, pub);
+
+		/* clear all IOCTL bits except HALT bit */
+		val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL);
+		val &= ARMCR4_BCMA_IOCTL_CPUHALT;
+		brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
+				     ARMCR4_BCMA_IOCTL_CPUHALT);
+		break;
+	default:
+		brcmf_err("unknown id: %u\n", id);
+		break;
+	}
+}
+
+static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_chip *pub;
+	struct brcmf_core_priv *cc;
+	u32 base;
+	u32 val;
+	int ret = 0;
+
+	pub = &chip->pub;
+	cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
+	base = cc->pub.base;
+
+	/* get chipcommon capabilites */
+	pub->cc_caps = chip->ops->read32(chip->ctx,
+					 CORE_CC_REG(base, capabilities));
+
+	/* get pmu caps & rev */
+	if (pub->cc_caps & CC_CAP_PMU) {
+		val = chip->ops->read32(chip->ctx,
+					CORE_CC_REG(base, pmucapabilities));
+		pub->pmurev = val & PCAP_REV_MASK;
+		pub->pmucaps = val;
+	}
+
+	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",
+		  cc->pub.rev, pub->pmurev, pub->pmucaps);
+
+	/* execute bus core specific setup */
+	if (chip->ops->setup)
+		ret = chip->ops->setup(chip->ctx, pub);
+
+	/*
+	 * Make sure any on-chip ARM is off (in case strapping is wrong),
+	 * or downloaded code was already running.
+	 */
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
+	return ret;
+}
+
+struct brcmf_chip *brcmf_chip_attach(void *ctx,
+				     const struct brcmf_buscore_ops *ops)
+{
+	struct brcmf_chip_priv *chip;
+	int err = 0;
+
+	if (WARN_ON(!ops->read32))
+		err = -EINVAL;
+	if (WARN_ON(!ops->write32))
+		err = -EINVAL;
+	if (WARN_ON(!ops->prepare))
+		err = -EINVAL;
+	if (WARN_ON(!ops->exit_dl))
+		err = -EINVAL;
+	if (err < 0)
+		return ERR_PTR(-EINVAL);
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&chip->cores);
+	chip->num_cores = 0;
+	chip->ops = ops;
+	chip->ctx = ctx;
+
+	err = ops->prepare(ctx);
+	if (err < 0)
+		goto fail;
+
+	err = brcmf_chip_recognition(chip);
+	if (err < 0)
+		goto fail;
+
+	err = brcmf_chip_setup(chip);
+	if (err < 0)
+		goto fail;
+
+	return &chip->pub;
+
+fail:
+	brcmf_chip_detach(&chip->pub);
+	return ERR_PTR(err);
+}
+
+void brcmf_chip_detach(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *core;
+	struct brcmf_core_priv *tmp;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	list_for_each_entry_safe(core, tmp, &chip->cores, list) {
+		list_del(&core->list);
+		kfree(core);
+	}
+	kfree(chip);
+}
+
+struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *core;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	list_for_each_entry(core, &chip->cores, list)
+		if (core->pub.id == coreid)
+			return &core->pub;
+
+	return NULL;
+}
+
+struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *cc;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
+	if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON))
+		return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON);
+	return &cc->pub;
+}
+
+bool brcmf_chip_iscoreup(struct brcmf_core *pub)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	return core->chip->iscoreup(core);
+}
+
+void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	core->chip->coredisable(core, prereset, reset);
+}
+
+void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset,
+			  u32 postreset)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	core->chip->resetcore(core, prereset, reset, postreset);
+}
+
+static void
+brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+	brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+				   D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN);
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
+	brcmf_chip_resetcore(core, 0, 0, 0);
+}
+
+static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
+	if (!brcmf_chip_iscoreup(core)) {
+		brcmf_err("SOCRAM core is down after reset?\n");
+		return false;
+	}
+
+	chip->ops->exit_dl(chip->ctx, &chip->pub, 0);
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);
+	brcmf_chip_resetcore(core, 0, 0, 0);
+
+	return true;
+}
+
+static inline void
+brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+	brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+				   D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN);
+}
+
+static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec)
+{
+	struct brcmf_core *core;
+
+	chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec);
+
+	/* restore ARM */
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);
+	brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
+
+	return true;
+}
+
+void brcmf_chip_enter_download(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core *arm;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+	if (arm) {
+		brcmf_chip_cr4_enterdl(chip);
+		return;
+	}
+
+	brcmf_chip_cm3_enterdl(chip);
+}
+
+bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core *arm;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+	if (arm)
+		return brcmf_chip_cr4_exitdl(chip, rstvec);
+
+	return brcmf_chip_cm3_exitdl(chip);
+}
+
+bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
+{
+	u32 base, addr, reg, pmu_cc3_mask = ~0;
+	struct brcmf_chip_priv *chip;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/* old chips with PMU version less than 17 don't support save restore */
+	if (pub->pmurev < 17)
+		return false;
+
+	base = brcmf_chip_get_chipcommon(pub)->base;
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+
+	switch (pub->chip) {
+	case BCM43241_CHIP_ID:
+	case BCM4335_CHIP_ID:
+	case BCM4339_CHIP_ID:
+		/* read PMU chipcontrol register 3 */
+		addr = CORE_CC_REG(base, chipcontrol_addr);
+		chip->ops->write32(chip->ctx, addr, 3);
+		addr = CORE_CC_REG(base, chipcontrol_data);
+		reg = chip->ops->read32(chip->ctx, addr);
+		return (reg & pmu_cc3_mask) != 0;
+	default:
+		addr = CORE_CC_REG(base, pmucapabilities_ext);
+		reg = chip->ops->read32(chip->ctx, addr);
+		if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
+			return false;
+
+		addr = CORE_CC_REG(base, retention_ctl);
+		reg = chip->ops->read32(chip->ctx, addr);
+		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
+			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
+	}
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
new file mode 100644
index 000000000000..c32908da90c8
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMF_CHIP_H
+#define BRCMF_CHIP_H
+
+#include <linux/types.h>
+
+#define CORE_CC_REG(base, field) \
+		(base + offsetof(struct chipcregs, field))
+
+/**
+ * struct brcmf_chip - chip level information.
+ *
+ * @chip: chip identifier.
+ * @chiprev: chip revision.
+ * @cc_caps: chipcommon core capabilities.
+ * @pmucaps: PMU capabilities.
+ * @pmurev: PMU revision.
+ * @rambase: RAM base address (only applicable for ARM CR4 chips).
+ * @ramsize: amount of RAM on chip.
+ * @name: string representation of the chip identifier.
+ */
+struct brcmf_chip {
+	u32 chip;
+	u32 chiprev;
+	u32 cc_caps;
+	u32 pmucaps;
+	u32 pmurev;
+	u32 rambase;
+	u32 ramsize;
+	char name[8];
+};
+
+/**
+ * struct brcmf_core - core related information.
+ *
+ * @id: core identifier.
+ * @rev: core revision.
+ * @base: base address of core register space.
+ */
+struct brcmf_core {
+	u16 id;
+	u16 rev;
+	u32 base;
+};
+
+/**
+ * struct brcmf_buscore_ops - buscore specific callbacks.
+ *
+ * @read32: read 32-bit value over bus.
+ * @write32: write 32-bit value over bus.
+ * @prepare: prepare bus for core configuration.
+ * @setup: bus-specific core setup.
+ * @exit_dl: exit download state.
+ *	The callback should use the provided @rstvec when non-zero.
+ */
+struct brcmf_buscore_ops {
+	u32 (*read32)(void *ctx, u32 addr);
+	void (*write32)(void *ctx, u32 addr, u32 value);
+	int (*prepare)(void *ctx);
+	int (*setup)(void *ctx, struct brcmf_chip *chip);
+	void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+};
+
+struct brcmf_chip *brcmf_chip_attach(void *ctx,
+				     const struct brcmf_buscore_ops *ops);
+void brcmf_chip_detach(struct brcmf_chip *chip);
+struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
+struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
+bool brcmf_chip_iscoreup(struct brcmf_core *core);
+void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
+void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
+			  u32 postreset);
+void brcmf_chip_enter_download(struct brcmf_chip *ci);
+bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec);
+bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
+
+#endif /* BRCMF_AXIDMP_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 3e991897d7ca..49d4196ef9d2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/card.h>
 #include <linux/semaphore.h>
@@ -40,7 +41,7 @@
 #include <brcm_hw_ids.h>
 #include <soc.h>
 #include "sdio_host.h"
-#include "sdio_chip.h"
+#include "chip.h"
 #include "nvram.h"
 
 #define DCMD_RESP_TIMEOUT  2000	/* In milli second */
@@ -156,6 +157,33 @@ struct rte_console {
 /* manfid tuple length, include tuple, link bytes */
 #define SBSDIO_CIS_MANFID_TUPLE_LEN	6
 
+#define CORE_BUS_REG(base, field) \
+		(base + offsetof(struct sdpcmd_regs, field))
+
+/* SDIO function 1 register CHIPCLKCSR */
+/* Force ALP request to backplane */
+#define SBSDIO_FORCE_ALP		0x01
+/* Force HT request to backplane */
+#define SBSDIO_FORCE_HT			0x02
+/* Force ILP request to backplane */
+#define SBSDIO_FORCE_ILP		0x04
+/* Make ALP ready (power up xtal) */
+#define SBSDIO_ALP_AVAIL_REQ		0x08
+/* Make HT ready (power up PLL) */
+#define SBSDIO_HT_AVAIL_REQ		0x10
+/* Squelch clock requests from HW */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20
+/* Status: ALP is ready */
+#define SBSDIO_ALP_AVAIL		0x40
+/* Status: HT is ready */
+#define SBSDIO_HT_AVAIL			0x80
+#define SBSDIO_AVBITS		(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval)	((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval)	(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval)	(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+#define SBSDIO_CLKAV(regval, alponly) \
+	(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
+
 /* intstatus */
 #define I_SMB_SW0	(1 << 0)	/* To SB Mail S/W interrupt 0 */
 #define I_SMB_SW1	(1 << 1)	/* To SB Mail S/W interrupt 1 */
@@ -457,7 +485,6 @@ struct brcmf_sdio {
 
 	u8 tx_hdrlen;		/* sdio bus header length for tx packet */
 	bool txglom;		/* host tx glomming enable flag */
-	struct sk_buff *txglom_sgpad;	/* scatter-gather padding buffer */
 	u16 head_align;		/* buffer pointer alignment */
 	u16 sgentry_align;	/* scatter-gather buffer alignment */
 };
@@ -494,6 +521,52 @@ enum brcmf_sdio_frmtype {
 	BRCMF_SDIO_FT_SUB,
 };
 
+#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
+
+/* SDIO Pad drive strength to select value mappings */
+struct sdiod_drive_str {
+	u8 strength;	/* Pad Drive Strength in mA */
+	u8 sel;		/* Chip-specific select value */
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
+	{32, 0x6},
+	{26, 0x7},
+	{22, 0x4},
+	{16, 0x5},
+	{12, 0x2},
+	{8, 0x3},
+	{4, 0x0},
+	{0, 0x1}
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
+static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
+	{6, 0x7},
+	{5, 0x6},
+	{4, 0x5},
+	{3, 0x4},
+	{2, 0x2},
+	{1, 0x1},
+	{0, 0x0}
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
+static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
+	{3, 0x3},
+	{2, 0x2},
+	{1, 0x1},
+	{0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
+	{16, 0x7},
+	{12, 0x5},
+	{8,  0x3},
+	{4,  0x1}
+};
+
 #define BCM43143_FIRMWARE_NAME		"brcm/brcmfmac43143-sdio.bin"
 #define BCM43143_NVRAM_NAME		"brcm/brcmfmac43143-sdio.txt"
 #define BCM43241B0_FIRMWARE_NAME	"brcm/brcmfmac43241b0-sdio.bin"
@@ -619,27 +692,24 @@ static bool data_ok(struct brcmf_sdio *bus)
  * Reads a register in the SDIO hardware block. This block occupies a series of
  * adresses on the 32 bit backplane bus.
  */
-static int
-r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
+static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
 {
-	u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+	struct brcmf_core *core;
 	int ret;
 
-	*regvar = brcmf_sdiod_regrl(bus->sdiodev,
-				    bus->ci->c_inf[idx].base + offset, &ret);
+	core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
+	*regvar = brcmf_sdiod_regrl(bus->sdiodev, core->base + offset, &ret);
 
 	return ret;
 }
 
-static int
-w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
+static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
 {
-	u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+	struct brcmf_core *core;
 	int ret;
 
-	brcmf_sdiod_regwl(bus->sdiodev,
-			  bus->ci->c_inf[idx].base + reg_offset,
-			  regval, &ret);
+	core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
+	brcmf_sdiod_regwl(bus->sdiodev, core->base + reg_offset, regval, &ret);
 
 	return ret;
 }
@@ -900,8 +970,8 @@ static int
 brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 {
 	int err = 0;
-	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_dbg(SDIO, "request %s currently %s\n",
+
+	brcmf_dbg(SDIO, "Enter: request %s currently %s\n",
 		  (sleep ? "SLEEP" : "WAKE"),
 		  (bus->sleeping ? "SLEEP" : "WAKE"));
 
@@ -953,6 +1023,86 @@ end:
 
 }
 
+#ifdef DEBUG
+static inline bool brcmf_sdio_valid_shared_address(u32 addr)
+{
+	return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
+}
+
+static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
+				 struct sdpcm_shared *sh)
+{
+	u32 addr;
+	int rv;
+	u32 shaddr = 0;
+	struct sdpcm_shared_le sh_le;
+	__le32 addr_le;
+
+	shaddr = bus->ci->rambase + bus->ramsize - 4;
+
+	/*
+	 * Read last word in socram to determine
+	 * address of sdpcm_shared structure
+	 */
+	sdio_claim_host(bus->sdiodev->func[1]);
+	brcmf_sdio_bus_sleep(bus, false, false);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
+	sdio_release_host(bus->sdiodev->func[1]);
+	if (rv < 0)
+		return rv;
+
+	addr = le32_to_cpu(addr_le);
+
+	brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
+
+	/*
+	 * Check if addr is valid.
+	 * NVRAM length at the end of memory should have been overwritten.
+	 */
+	if (!brcmf_sdio_valid_shared_address(addr)) {
+			brcmf_err("invalid sdpcm_shared address 0x%08X\n",
+				  addr);
+			return -EINVAL;
+	}
+
+	/* Read hndrte_shared structure */
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+			       sizeof(struct sdpcm_shared_le));
+	if (rv < 0)
+		return rv;
+
+	/* Endianness */
+	sh->flags = le32_to_cpu(sh_le.flags);
+	sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
+	sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
+	sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
+	sh->assert_line = le32_to_cpu(sh_le.assert_line);
+	sh->console_addr = le32_to_cpu(sh_le.console_addr);
+	sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
+
+	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
+		brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
+			  SDPCM_SHARED_VERSION,
+			  sh->flags & SDPCM_SHARED_VERSION_MASK);
+		return -EPROTO;
+	}
+
+	return 0;
+}
+
+static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
+{
+	struct sdpcm_shared sh;
+
+	if (brcmf_sdio_readshared(bus, &sh) == 0)
+		bus->console_addr = sh.console_addr;
+}
+#else
+static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
+{
+}
+#endif /* DEBUG */
+
 static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
 {
 	u32 intstatus = 0;
@@ -996,6 +1146,12 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
 		else
 			brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
 				  bus->sdpcm_ver);
+
+		/*
+		 * Retrieve console state address now that firmware should have
+		 * updated it.
+		 */
+		brcmf_sdio_get_console_addr(bus);
 	}
 
 	/*
@@ -1944,9 +2100,8 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
 	if (lastfrm && chain_pad)
 		tail_pad += blksize - chain_pad;
 	if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
-		pkt_pad = bus->txglom_sgpad;
-		if (pkt_pad == NULL)
-			  brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+		pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop +
+						bus->head_align);
 		if (pkt_pad == NULL)
 			return -ENOMEM;
 		ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
@@ -1957,6 +2112,7 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
 		       tail_chop);
 		*(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
 		skb_trim(pkt, pkt->len - tail_chop);
+		skb_trim(pkt_pad, tail_pad + tail_chop);
 		__skb_queue_after(pktq, pkt, pkt_pad);
 	} else {
 		ntail = pkt->data_len + tail_pad -
@@ -2011,7 +2167,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
 			return ret;
 		head_pad = (u16)ret;
 		if (head_pad)
-			memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen);
+			memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad);
 
 		total_len += pkt_next->len;
 
@@ -2293,14 +2449,13 @@ static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
 
 static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
 {
-	u8 idx;
+	struct brcmf_core *buscore;
 	u32 addr;
 	unsigned long val;
 	int n, ret;
 
-	idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
-	addr = bus->ci->c_inf[idx].base +
-	       offsetof(struct sdpcmd_regs, intstatus);
+	buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
+	addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
 
 	val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
 	bus->sdcnt.f1regdata++;
@@ -2810,72 +2965,6 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 }
 
 #ifdef DEBUG
-static inline bool brcmf_sdio_valid_shared_address(u32 addr)
-{
-	return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
-}
-
-static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
-				 struct sdpcm_shared *sh)
-{
-	u32 addr;
-	int rv;
-	u32 shaddr = 0;
-	struct sdpcm_shared_le sh_le;
-	__le32 addr_le;
-
-	shaddr = bus->ci->rambase + bus->ramsize - 4;
-
-	/*
-	 * Read last word in socram to determine
-	 * address of sdpcm_shared structure
-	 */
-	sdio_claim_host(bus->sdiodev->func[1]);
-	brcmf_sdio_bus_sleep(bus, false, false);
-	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
-	sdio_release_host(bus->sdiodev->func[1]);
-	if (rv < 0)
-		return rv;
-
-	addr = le32_to_cpu(addr_le);
-
-	brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
-
-	/*
-	 * Check if addr is valid.
-	 * NVRAM length at the end of memory should have been overwritten.
-	 */
-	if (!brcmf_sdio_valid_shared_address(addr)) {
-			brcmf_err("invalid sdpcm_shared address 0x%08X\n",
-				  addr);
-			return -EINVAL;
-	}
-
-	/* Read hndrte_shared structure */
-	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
-			       sizeof(struct sdpcm_shared_le));
-	if (rv < 0)
-		return rv;
-
-	/* Endianness */
-	sh->flags = le32_to_cpu(sh_le.flags);
-	sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
-	sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
-	sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
-	sh->assert_line = le32_to_cpu(sh_le.assert_line);
-	sh->console_addr = le32_to_cpu(sh_le.console_addr);
-	sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
-
-	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
-		brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
-			  SDPCM_SHARED_VERSION,
-			  sh->flags & SDPCM_SHARED_VERSION_MASK);
-		return -EPROTO;
-	}
-
-	return 0;
-}
-
 static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
 				   struct sdpcm_shared *sh, char __user *data,
 				   size_t count)
@@ -3105,6 +3194,8 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
 	debugfs_create_file("forensics", S_IRUGO, dentry, bus,
 			    &brcmf_sdio_forensic_ops);
 	brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
+	debugfs_create_u32("console_interval", 0644, dentry,
+			   &bus->console_interval);
 }
 #else
 static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
@@ -3223,32 +3314,17 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
 					 const struct firmware *fw)
 {
 	int err;
-	int offset;
-	int address;
-	int len;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	err = 0;
-	offset = 0;
-	address = bus->ci->rambase;
-	while (offset < fw->size) {
-		len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK :
-		      fw->size - offset;
-		err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
-					(u8 *)&fw->data[offset], len);
-		if (err) {
-			brcmf_err("error %d on writing %d membytes at 0x%08x\n",
-				  err, len, address);
-			return err;
-		}
-		offset += len;
-		address += len;
-	}
-	if (!err)
-		if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
-					     (u8 *)fw->data, fw->size))
-			err = -EIO;
+	err = brcmf_sdiod_ramrw(bus->sdiodev, true, bus->ci->rambase,
+				(u8 *)fw->data, fw->size);
+	if (err)
+		brcmf_err("error %d on writing %d membytes at 0x%08x\n",
+			  err, (int)fw->size, bus->ci->rambase);
+	else if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
+					  (u8 *)fw->data, fw->size))
+		err = -EIO;
 
 	return err;
 }
@@ -3291,7 +3367,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
 	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
 
 	/* Keep arm in reset */
-	brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
+	brcmf_chip_enter_download(bus->ci);
 
 	fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
 	if (fw == NULL) {
@@ -3323,7 +3399,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
 	}
 
 	/* Take arm out of reset */
-	if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) {
+	if (!brcmf_chip_exit_download(bus->ci, rstvec)) {
 		brcmf_err("error getting out of ARM core reset\n");
 		goto err;
 	}
@@ -3338,40 +3414,6 @@ err:
 	return bcmerror;
 }
 
-static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus)
-{
-	u32 addr, reg, pmu_cc3_mask = ~0;
-	int err;
-
-	brcmf_dbg(TRACE, "Enter\n");
-
-	/* old chips with PMU version less than 17 don't support save restore */
-	if (bus->ci->pmurev < 17)
-		return false;
-
-	switch (bus->ci->chip) {
-	case BCM43241_CHIP_ID:
-	case BCM4335_CHIP_ID:
-	case BCM4339_CHIP_ID:
-		/* read PMU chipcontrol register 3 */
-		addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
-		brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL);
-		addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
-		reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
-		return (reg & pmu_cc3_mask) != 0;
-	default:
-		addr = CORE_CC_REG(bus->ci->c_inf[0].base, pmucapabilities_ext);
-		reg = brcmf_sdiod_regrl(bus->sdiodev, addr, &err);
-		if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
-			return false;
-
-		addr = CORE_CC_REG(bus->ci->c_inf[0].base, retention_ctl);
-		reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
-		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
-			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
-	}
-}
-
 static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
 {
 	int err = 0;
@@ -3423,7 +3465,7 @@ static int brcmf_sdio_kso_init(struct brcmf_sdio *bus)
 	brcmf_dbg(TRACE, "Enter\n");
 
 	/* KSO bit added in SDIO core rev 12 */
-	if (bus->ci->c_inf[1].rev < 12)
+	if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
 		return 0;
 
 	val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
@@ -3454,15 +3496,13 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
 	struct brcmf_sdio *bus = sdiodev->bus;
 	uint pad_size;
 	u32 value;
-	u8 idx;
 	int err;
 
 	/* the commands below use the terms tx and rx from
 	 * a device perspective, ie. bus:txglom affects the
 	 * bus transfers from device to host.
 	 */
-	idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
-	if (bus->ci->c_inf[idx].rev < 12) {
+	if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) {
 		/* for sdio core rev < 12, disable txgloming */
 		value = 0;
 		err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
@@ -3486,10 +3526,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
 		bus->txglom = false;
 		value = 1;
 		pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
-		bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size);
-		if (!bus->txglom_sgpad)
-			brcmf_err("allocating txglom padding skb failed, reduced performance\n");
-
 		err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
 					   &value, sizeof(u32));
 		if (err < 0) {
@@ -3573,7 +3609,7 @@ static int brcmf_sdio_bus_init(struct device *dev)
 		ret = -ENODEV;
 	}
 
-	if (brcmf_sdio_sr_capable(bus)) {
+	if (brcmf_chip_sr_capable(bus->ci)) {
 		brcmf_sdio_sr_init(bus);
 	} else {
 		/* Restore previous clock setting */
@@ -3722,6 +3758,170 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
 	}
 }
 
+static void
+brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
+			     struct brcmf_chip *ci, u32 drivestrength)
+{
+	const struct sdiod_drive_str *str_tab = NULL;
+	u32 str_mask;
+	u32 str_shift;
+	u32 base;
+	u32 i;
+	u32 drivestrength_sel = 0;
+	u32 cc_data_temp;
+	u32 addr;
+
+	if (!(ci->cc_caps & CC_CAP_PMU))
+		return;
+
+	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
+	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
+		str_tab = sdiod_drvstr_tab1_1v8;
+		str_mask = 0x00003800;
+		str_shift = 11;
+		break;
+	case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
+		str_tab = sdiod_drvstr_tab6_1v8;
+		str_mask = 0x00001800;
+		str_shift = 11;
+		break;
+	case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+		/* note: 43143 does not support tristate */
+		i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
+		if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
+			str_tab = sdiod_drvstr_tab2_3v3;
+			str_mask = 0x00000007;
+			str_shift = 0;
+		} else
+			brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
+				  ci->name, drivestrength);
+		break;
+	case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
+		str_tab = sdiod_drive_strength_tab5_1v8;
+		str_mask = 0x00003800;
+		str_shift = 11;
+		break;
+	default:
+		brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
+			  ci->name, ci->chiprev, ci->pmurev);
+		break;
+	}
+
+	if (str_tab != NULL) {
+		for (i = 0; str_tab[i].strength != 0; i++) {
+			if (drivestrength >= str_tab[i].strength) {
+				drivestrength_sel = str_tab[i].sel;
+				break;
+			}
+		}
+		base = brcmf_chip_get_chipcommon(ci)->base;
+		addr = CORE_CC_REG(base, chipcontrol_addr);
+		brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
+		cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+		cc_data_temp &= ~str_mask;
+		drivestrength_sel <<= str_shift;
+		cc_data_temp |= drivestrength_sel;
+		brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
+
+		brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
+			  str_tab[i].strength, drivestrength, cc_data_temp);
+	}
+}
+
+static int brcmf_sdio_buscoreprep(void *ctx)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	int err = 0;
+	u8 clkval, clkset;
+
+	/* Try forcing SDIO core to do ALPAvail request only */
+	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+	if (err) {
+		brcmf_err("error writing for HT off\n");
+		return err;
+	}
+
+	/* If register supported, wait for ALPAvail and then force ALP */
+	/* This may take up to 15 milliseconds */
+	clkval = brcmf_sdiod_regrb(sdiodev,
+				   SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+
+	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
+		brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+			  clkset, clkval);
+		return -EACCES;
+	}
+
+	SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
+					      SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
+			!SBSDIO_ALPAV(clkval)),
+			PMU_MAX_TRANSITION_DLY);
+	if (!SBSDIO_ALPAV(clkval)) {
+		brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
+			  clkval);
+		return -EBUSY;
+	}
+
+	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
+	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+	udelay(65);
+
+	/* Also, disable the extra SDIO pull-ups */
+	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+
+	return 0;
+}
+
+static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
+				      u32 rstvec)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	struct brcmf_core *core;
+	u32 reg_addr;
+
+	/* clear all interrupts */
+	core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
+	reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
+	brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+	if (rstvec)
+		/* Write reset vector to address 0 */
+		brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
+				  sizeof(rstvec));
+}
+
+static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	u32 val, rev;
+
+	val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+	if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
+	    addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
+		rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
+		if (rev >= 2) {
+			val &= ~CID_ID_MASK;
+			val |= BCM4339_CHIP_ID;
+		}
+	}
+	return val;
+}
+
+static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+
+	brcmf_sdiod_regwl(sdiodev, addr, val, NULL);
+}
+
+static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
+	.prepare = brcmf_sdio_buscoreprep,
+	.exit_dl = brcmf_sdio_buscore_exitdl,
+	.read32 = brcmf_sdio_buscore_read32,
+	.write32 = brcmf_sdio_buscore_write32,
+};
+
 static bool
 brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 {
@@ -3737,7 +3937,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 		 brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
 
 	/*
-	 * Force PLL off until brcmf_sdio_chip_attach()
+	 * Force PLL off until brcmf_chip_attach()
 	 * programs PLL control regs
 	 */
 
@@ -3758,8 +3958,10 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 	 */
 	brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
 
-	if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) {
-		brcmf_err("brcmf_sdio_chip_attach failed!\n");
+	bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
+	if (IS_ERR(bus->ci)) {
+		brcmf_err("brcmf_chip_attach failed!\n");
+		bus->ci = NULL;
 		goto fail;
 	}
 
@@ -3772,7 +3974,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 		drivestrength = bus->sdiodev->pdata->drive_strength;
 	else
 		drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
-	brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
+	brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
 
 	/* Get info on the SOCRAM cores... */
 	bus->ramsize = bus->ci->ramsize;
@@ -3795,24 +3997,18 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 		goto fail;
 
 	/* set PMUControl so a backplane reset does PMU state reload */
-	reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
+	reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base,
 			       pmucontrol);
-	reg_val = brcmf_sdiod_regrl(bus->sdiodev,
-				    reg_addr,
-				    &err);
+	reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
 	if (err)
 		goto fail;
 
 	reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
 
-	brcmf_sdiod_regwl(bus->sdiodev,
-			  reg_addr,
-			  reg_val,
-			  &err);
+	brcmf_sdiod_regwl(bus->sdiodev, reg_addr, reg_val, &err);
 	if (err)
 		goto fail;
 
-
 	sdio_release_host(bus->sdiodev->func[1]);
 
 	brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
@@ -4027,14 +4223,14 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
 		/* De-register interrupt handler */
 		brcmf_sdiod_intr_unregister(bus->sdiodev);
 
-		cancel_work_sync(&bus->datawork);
-		if (bus->brcmf_wq)
-			destroy_workqueue(bus->brcmf_wq);
-
 		if (bus->sdiodev->bus_if->drvr) {
 			brcmf_detach(bus->sdiodev->dev);
 		}
 
+		cancel_work_sync(&bus->datawork);
+		if (bus->brcmf_wq)
+			destroy_workqueue(bus->brcmf_wq);
+
 		if (bus->ci) {
 			if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
 				sdio_claim_host(bus->sdiodev->func[1]);
@@ -4045,15 +4241,13 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
 				 * all necessary cores.
 				 */
 				msleep(20);
-				brcmf_sdio_chip_enter_download(bus->sdiodev,
-							       bus->ci);
+				brcmf_chip_enter_download(bus->ci);
 				brcmf_sdio_clkctl(bus, CLK_NONE, false);
 				sdio_release_host(bus->sdiodev->func[1]);
 			}
-			brcmf_sdio_chip_detach(&bus->ci);
+			brcmf_chip_detach(bus->ci);
 		}
 
-		brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
 		kfree(bus->rxbuf);
 		kfree(bus->hdrbuf);
 		kfree(bus);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
index 22adbe311d20..59a5af5bf994 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -124,7 +124,8 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
 }
 
 static u32
-brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
+brcmf_create_iovar(char *name, const char *data, u32 datalen,
+		   char *buf, u32 buflen)
 {
 	u32 len;
 
@@ -144,7 +145,7 @@ brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
 
 
 s32
-brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
 			 u32 len)
 {
 	struct brcmf_pub *drvr = ifp->drvr;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
index 77eae86e55c2..a30be683f4a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
@@ -83,7 +83,7 @@ s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
 s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
 s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
 
-s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
 			     u32 len);
 s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
 			     u32 len);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
deleted file mode 100644
index 82bf3c5d3cdc..000000000000
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ /dev/null
@@ -1,972 +0,0 @@
-/*
- * Copyright (c) 2011 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/* ***** SDIO interface chip backplane handle functions ***** */
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/ssb/ssb_regs.h>
-#include <linux/bcma/bcma.h>
-
-#include <chipcommon.h>
-#include <brcm_hw_ids.h>
-#include <brcmu_wifi.h>
-#include <brcmu_utils.h>
-#include <soc.h>
-#include "dhd_dbg.h"
-#include "sdio_host.h"
-#include "sdio_chip.h"
-
-/* chip core base & ramsize */
-/* bcm4329 */
-/* SDIO device core, ID 0x829 */
-#define BCM4329_CORE_BUS_BASE		0x18011000
-/* internal memory core, ID 0x80e */
-#define BCM4329_CORE_SOCRAM_BASE	0x18003000
-/* ARM Cortex M3 core, ID 0x82a */
-#define BCM4329_CORE_ARM_BASE		0x18002000
-#define BCM4329_RAMSIZE			0x48000
-
-/* bcm43143 */
-/* SDIO device core */
-#define BCM43143_CORE_BUS_BASE		0x18002000
-/* internal memory core */
-#define BCM43143_CORE_SOCRAM_BASE	0x18004000
-/* ARM Cortex M3 core, ID 0x82a */
-#define BCM43143_CORE_ARM_BASE		0x18003000
-#define BCM43143_RAMSIZE		0x70000
-
-/* All D11 cores, ID 0x812 */
-#define BCM43xx_CORE_D11_BASE		0x18001000
-
-#define	SBCOREREV(sbidh) \
-	((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
-	  ((sbidh) & SSB_IDHIGH_RCLO))
-
-/* SOC Interconnect types (aka chip types) */
-#define SOCI_SB		0
-#define SOCI_AI		1
-
-/* EROM CompIdentB */
-#define CIB_REV_MASK		0xff000000
-#define CIB_REV_SHIFT		24
-
-/* ARM CR4 core specific control flag bits */
-#define ARMCR4_BCMA_IOCTL_CPUHALT	0x0020
-
-/* D11 core specific control flag bits */
-#define D11_BCMA_IOCTL_PHYCLOCKEN	0x0004
-#define D11_BCMA_IOCTL_PHYRESET		0x0008
-
-#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
-/* SDIO Pad drive strength to select value mappings */
-struct sdiod_drive_str {
-	u8 strength;	/* Pad Drive Strength in mA */
-	u8 sel;		/* Chip-specific select value */
-};
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
-static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
-	{32, 0x6},
-	{26, 0x7},
-	{22, 0x4},
-	{16, 0x5},
-	{12, 0x2},
-	{8, 0x3},
-	{4, 0x0},
-	{0, 0x1}
-};
-
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
-static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
-        {6, 0x7},
-        {5, 0x6},
-        {4, 0x5},
-        {3, 0x4},
-        {2, 0x2},
-        {1, 0x1},
-        {0, 0x0}
-};
-
-/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
-static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
-	{3, 0x3},
-	{2, 0x2},
-	{1, 0x1},
-	{0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
-static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
-	{16, 0x7},
-	{12, 0x5},
-	{8,  0x3},
-	{4,  0x1}
-};
-
-u8
-brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid)
-{
-	u8 idx;
-
-	for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
-		if (coreid == ci->c_inf[idx].id)
-			return idx;
-
-	return BRCMF_MAX_CORENUM;
-}
-
-static u32
-brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
-		      struct brcmf_chip *ci, u16 coreid)
-{
-	u32 regdata;
-	u8 idx;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbidhigh),
-				    NULL);
-	return SBCOREREV(regdata);
-}
-
-static u32
-brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
-		      struct brcmf_chip *ci, u16 coreid)
-{
-	u8 idx;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-
-	return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
-}
-
-static bool
-brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
-		       struct brcmf_chip *ci, u16 coreid)
-{
-	u32 regdata;
-	u8 idx;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	if (idx == BRCMF_MAX_CORENUM)
-		return false;
-
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-				    NULL);
-	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
-		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
-	return (SSB_TMSLOW_CLOCK == regdata);
-}
-
-static bool
-brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
-		       struct brcmf_chip *ci, u16 coreid)
-{
-	u32 regdata;
-	u8 idx;
-	bool ret;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	if (idx == BRCMF_MAX_CORENUM)
-		return false;
-
-	regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-				    NULL);
-	ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
-
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-				    NULL);
-	ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
-
-	return ret;
-}
-
-static void
-brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
-			  struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
-			  u32 in_resetbits)
-{
-	u32 regdata, base;
-	u8 idx;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	base = ci->c_inf[idx].base;
-
-	regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
-	if (regdata & SSB_TMSLOW_RESET)
-		return;
-
-	regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
-	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
-		/*
-		 * set target reject and spin until busy is clear
-		 * (preserve core-specific bits)
-		 */
-		regdata = brcmf_sdiod_regrl(sdiodev,
-					    CORE_SB(base, sbtmstatelow), NULL);
-		brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-				  regdata | SSB_TMSLOW_REJECT, NULL);
-
-		regdata = brcmf_sdiod_regrl(sdiodev,
-					    CORE_SB(base, sbtmstatelow), NULL);
-		udelay(1);
-		SPINWAIT((brcmf_sdiod_regrl(sdiodev,
-					    CORE_SB(base, sbtmstatehigh),
-					    NULL) &
-			  SSB_TMSHIGH_BUSY), 100000);
-
-		regdata = brcmf_sdiod_regrl(sdiodev,
-					    CORE_SB(base, sbtmstatehigh),
-					    NULL);
-		if (regdata & SSB_TMSHIGH_BUSY)
-			brcmf_err("core state still busy\n");
-
-		regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
-					    NULL);
-		if (regdata & SSB_IDLOW_INITIATOR) {
-			regdata = brcmf_sdiod_regrl(sdiodev,
-						    CORE_SB(base, sbimstate),
-						    NULL);
-			regdata |= SSB_IMSTATE_REJECT;
-			brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
-					  regdata, NULL);
-			regdata = brcmf_sdiod_regrl(sdiodev,
-						    CORE_SB(base, sbimstate),
-						    NULL);
-			udelay(1);
-			SPINWAIT((brcmf_sdiod_regrl(sdiodev,
-						    CORE_SB(base, sbimstate),
-						    NULL) &
-				  SSB_IMSTATE_BUSY), 100000);
-		}
-
-		/* set reset and reject while enabling the clocks */
-		regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
-			  SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
-		brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-				  regdata, NULL);
-		regdata = brcmf_sdiod_regrl(sdiodev,
-					    CORE_SB(base, sbtmstatelow), NULL);
-		udelay(10);
-
-		/* clear the initiator reject bit */
-		regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
-					    NULL);
-		if (regdata & SSB_IDLOW_INITIATOR) {
-			regdata = brcmf_sdiod_regrl(sdiodev,
-						    CORE_SB(base, sbimstate),
-						    NULL);
-			regdata &= ~SSB_IMSTATE_REJECT;
-			brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
-					  regdata, NULL);
-		}
-	}
-
-	/* leave reset and reject asserted */
-	brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-			  (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
-	udelay(1);
-}
-
-static void
-brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
-			  struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
-			  u32 in_resetbits)
-{
-	u8 idx;
-	u32 regdata;
-	u32 wrapbase;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	if (idx == BRCMF_MAX_CORENUM)
-		return;
-
-	wrapbase = ci->c_inf[idx].wrapbase;
-
-	/* if core is already in reset, just return */
-	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
-	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
-		return;
-
-	/* configure reset */
-	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
-			  BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
-
-	/* put in reset */
-	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
-			  BCMA_RESET_CTL_RESET, NULL);
-	usleep_range(10, 20);
-
-	/* wait till reset is 1 */
-	SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
-		 BCMA_RESET_CTL_RESET, 300);
-
-	/* post reset configure */
-	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
-			  BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
-}
-
-static void
-brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
-			struct brcmf_chip *ci, u16 coreid,  u32 pre_resetbits,
-			u32 in_resetbits, u32 post_resetbits)
-{
-	u32 regdata;
-	u8 idx;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	if (idx == BRCMF_MAX_CORENUM)
-		return;
-
-	/*
-	 * Must do the disable sequence first to work for
-	 * arbitrary current core state.
-	 */
-	brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits,
-				  in_resetbits);
-
-	/*
-	 * Now do the initialization sequence.
-	 * set reset while enabling the clock and
-	 * forcing them on throughout the core
-	 */
-	brcmf_sdiod_regwl(sdiodev,
-			  CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-			  SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
-			  NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-				    NULL);
-	udelay(1);
-
-	/* clear any serror */
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
-				    NULL);
-	if (regdata & SSB_TMSHIGH_SERR)
-		brcmf_sdiod_regwl(sdiodev,
-				  CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
-				  0, NULL);
-
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbimstate),
-				    NULL);
-	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
-		brcmf_sdiod_regwl(sdiodev,
-				  CORE_SB(ci->c_inf[idx].base, sbimstate),
-				  regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
-				  NULL);
-
-	/* clear reset and allow it to propagate throughout the core */
-	brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-			  SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-				    NULL);
-	udelay(1);
-
-	/* leave clock enabled */
-	brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-			  SSB_TMSLOW_CLOCK, NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-				    NULL);
-	udelay(1);
-}
-
-static void
-brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
-			struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
-			u32 in_resetbits, u32 post_resetbits)
-{
-	u8 idx;
-	u32 regdata;
-	u32 wrapbase;
-
-	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
-	if (idx == BRCMF_MAX_CORENUM)
-		return;
-
-	wrapbase = ci->c_inf[idx].wrapbase;
-
-	/* must disable first to work for arbitrary current core state */
-	brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits,
-				  in_resetbits);
-
-	while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) &
-	       BCMA_RESET_CTL_RESET) {
-		brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL);
-		usleep_range(40, 60);
-	}
-
-	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits |
-			  BCMA_IOCTL_CLK, NULL);
-	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
-}
-
-#ifdef DEBUG
-/* safety check for chipinfo */
-static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
-{
-	u8 core_idx;
-
-	/* check RAM core presence for ARM CM3 core */
-	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
-	if (BRCMF_MAX_CORENUM != core_idx) {
-		core_idx = brcmf_sdio_chip_getinfidx(ci,
-						     BCMA_CORE_INTERNAL_MEM);
-		if (BRCMF_MAX_CORENUM == core_idx) {
-			brcmf_err("RAM core not provided with ARM CM3 core\n");
-			return -ENODEV;
-		}
-	}
-
-	/* check RAM base for ARM CR4 core */
-	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
-	if (BRCMF_MAX_CORENUM != core_idx) {
-		if (ci->rambase == 0) {
-			brcmf_err("RAM base not provided with ARM CR4 core\n");
-			return -ENOMEM;
-		}
-	}
-
-	return 0;
-}
-#else	/* DEBUG */
-static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
-{
-	return 0;
-}
-#endif
-
-static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
-				       struct brcmf_chip *ci)
-{
-	u32 regdata;
-	u32 socitype;
-
-	/* Get CC core rev
-	 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
-	 * For different chiptypes or old sdio hosts w/o chipcommon,
-	 * other ways of recognition should be added here.
-	 */
-	regdata = brcmf_sdiod_regrl(sdiodev,
-				    CORE_CC_REG(SI_ENUM_BASE, chipid),
-				    NULL);
-	ci->chip = regdata & CID_ID_MASK;
-	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
-	if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
-	    ci->chiprev >= 2)
-		ci->chip = BCM4339_CHIP_ID;
-	socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
-
-	brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n",
-		  socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev);
-
-	if (socitype == SOCI_SB) {
-		if (ci->chip != BCM4329_CHIP_ID) {
-			brcmf_err("SB chip is not supported\n");
-			return -ENODEV;
-		}
-		ci->iscoreup = brcmf_sdio_sb_iscoreup;
-		ci->corerev = brcmf_sdio_sb_corerev;
-		ci->coredisable = brcmf_sdio_sb_coredisable;
-		ci->resetcore = brcmf_sdio_sb_resetcore;
-
-		ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
-		ci->c_inf[0].base = SI_ENUM_BASE;
-		ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-		ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
-		ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-		ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
-		ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-		ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
-		ci->c_inf[4].id = BCMA_CORE_80211;
-		ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-		ci->ramsize = BCM4329_RAMSIZE;
-	} else if (socitype == SOCI_AI) {
-		ci->iscoreup = brcmf_sdio_ai_iscoreup;
-		ci->corerev = brcmf_sdio_ai_corerev;
-		ci->coredisable = brcmf_sdio_ai_coredisable;
-		ci->resetcore = brcmf_sdio_ai_resetcore;
-
-		ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
-		ci->c_inf[0].base = SI_ENUM_BASE;
-
-		/* Address of cores for new chips should be added here */
-		switch (ci->chip) {
-		case BCM43143_CHIP_ID:
-			ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
-			ci->c_inf[0].cib = 0x2b000000;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
-			ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
-			ci->c_inf[1].cib = 0x18000000;
-			ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-			ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
-			ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
-			ci->c_inf[2].cib = 0x14000000;
-			ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-			ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
-			ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
-			ci->c_inf[3].cib = 0x07000000;
-			ci->c_inf[4].id = BCMA_CORE_80211;
-			ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
-			ci->ramsize = BCM43143_RAMSIZE;
-			break;
-		case BCM43241_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x2a084411;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18002000;
-			ci->c_inf[1].wrapbase = 0x18102000;
-			ci->c_inf[1].cib = 0x0e004211;
-			ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-			ci->c_inf[2].base = 0x18004000;
-			ci->c_inf[2].wrapbase = 0x18104000;
-			ci->c_inf[2].cib = 0x14080401;
-			ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-			ci->c_inf[3].base = 0x18003000;
-			ci->c_inf[3].wrapbase = 0x18103000;
-			ci->c_inf[3].cib = 0x07004211;
-			ci->c_inf[4].id = BCMA_CORE_80211;
-			ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
-			ci->ramsize = 0x90000;
-			break;
-		case BCM4330_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x27004211;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18002000;
-			ci->c_inf[1].wrapbase = 0x18102000;
-			ci->c_inf[1].cib = 0x07004211;
-			ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-			ci->c_inf[2].base = 0x18004000;
-			ci->c_inf[2].wrapbase = 0x18104000;
-			ci->c_inf[2].cib = 0x0d080401;
-			ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-			ci->c_inf[3].base = 0x18003000;
-			ci->c_inf[3].wrapbase = 0x18103000;
-			ci->c_inf[3].cib = 0x03004211;
-			ci->c_inf[4].id = BCMA_CORE_80211;
-			ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
-			ci->ramsize = 0x48000;
-			break;
-		case BCM4334_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x29004211;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18002000;
-			ci->c_inf[1].wrapbase = 0x18102000;
-			ci->c_inf[1].cib = 0x0d004211;
-			ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-			ci->c_inf[2].base = 0x18004000;
-			ci->c_inf[2].wrapbase = 0x18104000;
-			ci->c_inf[2].cib = 0x13080401;
-			ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-			ci->c_inf[3].base = 0x18003000;
-			ci->c_inf[3].wrapbase = 0x18103000;
-			ci->c_inf[3].cib = 0x07004211;
-			ci->c_inf[4].id = BCMA_CORE_80211;
-			ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
-			ci->ramsize = 0x80000;
-			break;
-		case BCM4335_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x2b084411;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18005000;
-			ci->c_inf[1].wrapbase = 0x18105000;
-			ci->c_inf[1].cib = 0x0f004211;
-			ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
-			ci->c_inf[2].base = 0x18002000;
-			ci->c_inf[2].wrapbase = 0x18102000;
-			ci->c_inf[2].cib = 0x01084411;
-			ci->c_inf[3].id = BCMA_CORE_80211;
-			ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
-			ci->ramsize = 0xc0000;
-			ci->rambase = 0x180000;
-			break;
-		case BCM43362_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x27004211;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18002000;
-			ci->c_inf[1].wrapbase = 0x18102000;
-			ci->c_inf[1].cib = 0x0a004211;
-			ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
-			ci->c_inf[2].base = 0x18004000;
-			ci->c_inf[2].wrapbase = 0x18104000;
-			ci->c_inf[2].cib = 0x08080401;
-			ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
-			ci->c_inf[3].base = 0x18003000;
-			ci->c_inf[3].wrapbase = 0x18103000;
-			ci->c_inf[3].cib = 0x03004211;
-			ci->c_inf[4].id = BCMA_CORE_80211;
-			ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
-			ci->ramsize = 0x3C000;
-			break;
-		case BCM4339_CHIP_ID:
-			ci->c_inf[0].wrapbase = 0x18100000;
-			ci->c_inf[0].cib = 0x2e084411;
-			ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
-			ci->c_inf[1].base = 0x18005000;
-			ci->c_inf[1].wrapbase = 0x18105000;
-			ci->c_inf[1].cib = 0x15004211;
-			ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
-			ci->c_inf[2].base = 0x18002000;
-			ci->c_inf[2].wrapbase = 0x18102000;
-			ci->c_inf[2].cib = 0x04084411;
-			ci->c_inf[3].id = BCMA_CORE_80211;
-			ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
-			ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
-			ci->ramsize = 0xc0000;
-			ci->rambase = 0x180000;
-			break;
-		default:
-			brcmf_err("AXI chip is not supported\n");
-			return -ENODEV;
-		}
-	} else {
-		brcmf_err("chip backplane type %u is not supported\n",
-			  socitype);
-		return -ENODEV;
-	}
-
-	return brcmf_sdio_chip_cichk(ci);
-}
-
-static int
-brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
-{
-	int err = 0;
-	u8 clkval, clkset;
-
-	/* Try forcing SDIO core to do ALPAvail request only */
-	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
-	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
-	if (err) {
-		brcmf_err("error writing for HT off\n");
-		return err;
-	}
-
-	/* If register supported, wait for ALPAvail and then force ALP */
-	/* This may take up to 15 milliseconds */
-	clkval = brcmf_sdiod_regrb(sdiodev,
-				   SBSDIO_FUNC1_CHIPCLKCSR, NULL);
-
-	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
-		brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
-			  clkset, clkval);
-		return -EACCES;
-	}
-
-	SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
-					      SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
-			!SBSDIO_ALPAV(clkval)),
-			PMU_MAX_TRANSITION_DLY);
-	if (!SBSDIO_ALPAV(clkval)) {
-		brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
-			  clkval);
-		return -EBUSY;
-	}
-
-	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
-	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
-	udelay(65);
-
-	/* Also, disable the extra SDIO pull-ups */
-	brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
-
-	return 0;
-}
-
-static void
-brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
-			     struct brcmf_chip *ci)
-{
-	u32 base = ci->c_inf[0].base;
-
-	/* get chipcommon rev */
-	ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
-
-	/* get chipcommon capabilites */
-	ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev,
-					      CORE_CC_REG(base, capabilities),
-					      NULL);
-
-	/* get pmu caps & rev */
-	if (ci->c_inf[0].caps & CC_CAP_PMU) {
-		ci->pmucaps =
-			brcmf_sdiod_regrl(sdiodev,
-					  CORE_CC_REG(base, pmucapabilities),
-					  NULL);
-		ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
-	}
-
-	ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
-
-	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
-		  ci->c_inf[0].rev, ci->pmurev,
-		  ci->c_inf[1].rev, ci->c_inf[1].id);
-
-	/*
-	 * Make sure any on-chip ARM is off (in case strapping is wrong),
-	 * or downloaded code was already running.
-	 */
-	ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
-}
-
-int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
-			   struct brcmf_chip **ci_ptr)
-{
-	int ret;
-	struct brcmf_chip *ci;
-
-	brcmf_dbg(TRACE, "Enter\n");
-
-	ci = kzalloc(sizeof(*ci), GFP_ATOMIC);
-	if (!ci)
-		return -ENOMEM;
-
-	ret = brcmf_sdio_chip_buscoreprep(sdiodev);
-	if (ret != 0)
-		goto err;
-
-	ret = brcmf_sdio_chip_recognition(sdiodev, ci);
-	if (ret != 0)
-		goto err;
-
-	brcmf_sdio_chip_buscoresetup(sdiodev, ci);
-
-	brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
-			  0, NULL);
-	brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
-			  0, NULL);
-
-	*ci_ptr = ci;
-	return 0;
-
-err:
-	kfree(ci);
-	return ret;
-}
-
-void
-brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr)
-{
-	brcmf_dbg(TRACE, "Enter\n");
-
-	kfree(*ci_ptr);
-	*ci_ptr = NULL;
-}
-
-static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
-{
-	const char *fmt;
-
-	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
-	snprintf(buf, len, fmt, chipid);
-	return buf;
-}
-
-void
-brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
-				  struct brcmf_chip *ci, u32 drivestrength)
-{
-	const struct sdiod_drive_str *str_tab = NULL;
-	u32 str_mask;
-	u32 str_shift;
-	char chn[8];
-	u32 base = ci->c_inf[0].base;
-	u32 i;
-	u32 drivestrength_sel = 0;
-	u32 cc_data_temp;
-	u32 addr;
-
-	if (!(ci->c_inf[0].caps & CC_CAP_PMU))
-		return;
-
-	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
-	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
-		str_tab = sdiod_drvstr_tab1_1v8;
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
-		str_tab = sdiod_drvstr_tab6_1v8;
-		str_mask = 0x00001800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
-		/* note: 43143 does not support tristate */
-		i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
-		if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
-			str_tab = sdiod_drvstr_tab2_3v3;
-			str_mask = 0x00000007;
-			str_shift = 0;
-		} else
-			brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
-				  brcmf_sdio_chip_name(ci->chip, chn, 8),
-				  drivestrength);
-		break;
-	case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
-		str_tab = sdiod_drive_strength_tab5_1v8;
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	default:
-		brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
-			  brcmf_sdio_chip_name(ci->chip, chn, 8),
-			  ci->chiprev, ci->pmurev);
-		break;
-	}
-
-	if (str_tab != NULL) {
-		for (i = 0; str_tab[i].strength != 0; i++) {
-			if (drivestrength >= str_tab[i].strength) {
-				drivestrength_sel = str_tab[i].sel;
-				break;
-			}
-		}
-		addr = CORE_CC_REG(base, chipcontrol_addr);
-		brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
-		cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
-		cc_data_temp &= ~str_mask;
-		drivestrength_sel <<= str_shift;
-		cc_data_temp |= drivestrength_sel;
-		brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
-
-		brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
-			  str_tab[i].strength, drivestrength, cc_data_temp);
-	}
-}
-
-static void
-brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
-			    struct brcmf_chip *ci)
-{
-	ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
-	ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
-		      D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
-		      D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
-	ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0);
-}
-
-static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev,
-				       struct brcmf_chip *ci)
-{
-	u8 core_idx;
-	u32 reg_addr;
-
-	if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
-		brcmf_err("SOCRAM core is down after reset?\n");
-		return false;
-	}
-
-	/* clear all interrupts */
-	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
-	reg_addr = ci->c_inf[core_idx].base;
-	reg_addr += offsetof(struct sdpcmd_regs, intstatus);
-	brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-
-	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0);
-
-	return true;
-}
-
-static inline void
-brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
-			    struct brcmf_chip *ci)
-{
-	u8 idx;
-	u32 regdata;
-	u32 wrapbase;
-	idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
-
-	if (idx == BRCMF_MAX_CORENUM)
-		return;
-
-	wrapbase = ci->c_inf[idx].wrapbase;
-	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
-	regdata &= ARMCR4_BCMA_IOCTL_CPUHALT;
-	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata,
-		      ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT);
-	ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
-		      D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
-		      D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
-}
-
-static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev,
-				       struct brcmf_chip *ci, u32 rstvec)
-{
-	u8 core_idx;
-	u32 reg_addr;
-
-	/* clear all interrupts */
-	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
-	reg_addr = ci->c_inf[core_idx].base;
-	reg_addr += offsetof(struct sdpcmd_regs, intstatus);
-	brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-
-	/* Write reset vector to address 0 */
-	brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
-			  sizeof(rstvec));
-
-	/* restore ARM */
-	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
-		      0, 0);
-
-	return true;
-}
-
-void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
-				    struct brcmf_chip *ci)
-{
-	u8 arm_core_idx;
-
-	arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
-	if (BRCMF_MAX_CORENUM != arm_core_idx) {
-		brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
-		return;
-	}
-
-	brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
-}
-
-bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
-				   struct brcmf_chip *ci, u32 rstvec)
-{
-	u8 arm_core_idx;
-
-	arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
-	if (BRCMF_MAX_CORENUM != arm_core_idx)
-		return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
-
-	return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
-}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
deleted file mode 100644
index fb0614329ede..000000000000
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2011 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCMFMAC_SDIO_CHIP_H_
-#define _BRCMFMAC_SDIO_CHIP_H_
-
-/*
- * Core reg address translation.
- * Both macro's returns a 32 bits byte address on the backplane bus.
- */
-#define CORE_CC_REG(base, field) \
-		(base + offsetof(struct chipcregs, field))
-#define CORE_BUS_REG(base, field) \
-		(base + offsetof(struct sdpcmd_regs, field))
-#define CORE_SB(base, field) \
-		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
-
-/* SDIO function 1 register CHIPCLKCSR */
-/* Force ALP request to backplane */
-#define SBSDIO_FORCE_ALP		0x01
-/* Force HT request to backplane */
-#define SBSDIO_FORCE_HT			0x02
-/* Force ILP request to backplane */
-#define SBSDIO_FORCE_ILP		0x04
-/* Make ALP ready (power up xtal) */
-#define SBSDIO_ALP_AVAIL_REQ		0x08
-/* Make HT ready (power up PLL) */
-#define SBSDIO_HT_AVAIL_REQ		0x10
-/* Squelch clock requests from HW */
-#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20
-/* Status: ALP is ready */
-#define SBSDIO_ALP_AVAIL		0x40
-/* Status: HT is ready */
-#define SBSDIO_HT_AVAIL			0x80
-#define SBSDIO_AVBITS		(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
-#define SBSDIO_ALPAV(regval)	((regval) & SBSDIO_AVBITS)
-#define SBSDIO_HTAV(regval)	(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
-#define SBSDIO_ALPONLY(regval)	(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
-#define SBSDIO_CLKAV(regval, alponly) \
-	(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
-
-#define BRCMF_MAX_CORENUM	6
-
-struct brcmf_core {
-	u16 id;
-	u16 rev;
-	u32 base;
-	u32 wrapbase;
-	u32 caps;
-	u32 cib;
-};
-
-struct brcmf_chip {
-	u32 chip;
-	u32 chiprev;
-	/* core info */
-	/* always put chipcommon core at 0, bus core at 1 */
-	struct brcmf_core c_inf[BRCMF_MAX_CORENUM];
-	u32 pmurev;
-	u32 pmucaps;
-	u32 ramsize;
-	u32 rambase;
-	u32 rst_vec;	/* reset vertor for ARM CR4 core */
-
-	bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
-			 u16 coreid);
-	u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
-			 u16 coreid);
-	void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
-			struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
-			u32 in_resetbits);
-	void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
-			struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
-			u32 in_resetbits, u32 post_resetbits);
-};
-
-struct sbconfig {
-	u32 PAD[2];
-	u32 sbipsflag;	/* initiator port ocp slave flag */
-	u32 PAD[3];
-	u32 sbtpsflag;	/* target port ocp slave flag */
-	u32 PAD[11];
-	u32 sbtmerrloga;	/* (sonics >= 2.3) */
-	u32 PAD;
-	u32 sbtmerrlog;	/* (sonics >= 2.3) */
-	u32 PAD[3];
-	u32 sbadmatch3;	/* address match3 */
-	u32 PAD;
-	u32 sbadmatch2;	/* address match2 */
-	u32 PAD;
-	u32 sbadmatch1;	/* address match1 */
-	u32 PAD[7];
-	u32 sbimstate;	/* initiator agent state */
-	u32 sbintvec;	/* interrupt mask */
-	u32 sbtmstatelow;	/* target state */
-	u32 sbtmstatehigh;	/* target state */
-	u32 sbbwa0;		/* bandwidth allocation table0 */
-	u32 PAD;
-	u32 sbimconfiglow;	/* initiator configuration */
-	u32 sbimconfighigh;	/* initiator configuration */
-	u32 sbadmatch0;	/* address match0 */
-	u32 PAD;
-	u32 sbtmconfiglow;	/* target configuration */
-	u32 sbtmconfighigh;	/* target configuration */
-	u32 sbbconfig;	/* broadcast configuration */
-	u32 PAD;
-	u32 sbbstate;	/* broadcast state */
-	u32 PAD[3];
-	u32 sbactcnfg;	/* activate configuration */
-	u32 PAD[3];
-	u32 sbflagst;	/* current sbflags */
-	u32 PAD[3];
-	u32 sbidlow;		/* identification */
-	u32 sbidhigh;	/* identification */
-};
-
-/* sdio core registers */
-struct sdpcmd_regs {
-	u32 corecontrol;		/* 0x00, rev8 */
-	u32 corestatus;			/* rev8 */
-	u32 PAD[1];
-	u32 biststatus;			/* rev8 */
-
-	/* PCMCIA access */
-	u16 pcmciamesportaladdr;	/* 0x010, rev8 */
-	u16 PAD[1];
-	u16 pcmciamesportalmask;	/* rev8 */
-	u16 PAD[1];
-	u16 pcmciawrframebc;		/* rev8 */
-	u16 PAD[1];
-	u16 pcmciaunderflowtimer;	/* rev8 */
-	u16 PAD[1];
-
-	/* interrupt */
-	u32 intstatus;			/* 0x020, rev8 */
-	u32 hostintmask;		/* rev8 */
-	u32 intmask;			/* rev8 */
-	u32 sbintstatus;		/* rev8 */
-	u32 sbintmask;			/* rev8 */
-	u32 funcintmask;		/* rev4 */
-	u32 PAD[2];
-	u32 tosbmailbox;		/* 0x040, rev8 */
-	u32 tohostmailbox;		/* rev8 */
-	u32 tosbmailboxdata;		/* rev8 */
-	u32 tohostmailboxdata;		/* rev8 */
-
-	/* synchronized access to registers in SDIO clock domain */
-	u32 sdioaccess;			/* 0x050, rev8 */
-	u32 PAD[3];
-
-	/* PCMCIA frame control */
-	u8 pcmciaframectrl;		/* 0x060, rev8 */
-	u8 PAD[3];
-	u8 pcmciawatermark;		/* rev8 */
-	u8 PAD[155];
-
-	/* interrupt batching control */
-	u32 intrcvlazy;			/* 0x100, rev8 */
-	u32 PAD[3];
-
-	/* counters */
-	u32 cmd52rd;			/* 0x110, rev8 */
-	u32 cmd52wr;			/* rev8 */
-	u32 cmd53rd;			/* rev8 */
-	u32 cmd53wr;			/* rev8 */
-	u32 abort;			/* rev8 */
-	u32 datacrcerror;		/* rev8 */
-	u32 rdoutofsync;		/* rev8 */
-	u32 wroutofsync;		/* rev8 */
-	u32 writebusy;			/* rev8 */
-	u32 readwait;			/* rev8 */
-	u32 readterm;			/* rev8 */
-	u32 writeterm;			/* rev8 */
-	u32 PAD[40];
-	u32 clockctlstatus;		/* rev8 */
-	u32 PAD[7];
-
-	u32 PAD[128];			/* DMA engines */
-
-	/* SDIO/PCMCIA CIS region */
-	char cis[512];			/* 0x400-0x5ff, rev6 */
-
-	/* PCMCIA function control registers */
-	char pcmciafcr[256];		/* 0x600-6ff, rev6 */
-	u16 PAD[55];
-
-	/* PCMCIA backplane access */
-	u16 backplanecsr;		/* 0x76E, rev6 */
-	u16 backplaneaddr0;		/* rev6 */
-	u16 backplaneaddr1;		/* rev6 */
-	u16 backplaneaddr2;		/* rev6 */
-	u16 backplaneaddr3;		/* rev6 */
-	u16 backplanedata0;		/* rev6 */
-	u16 backplanedata1;		/* rev6 */
-	u16 backplanedata2;		/* rev6 */
-	u16 backplanedata3;		/* rev6 */
-	u16 PAD[31];
-
-	/* sprom "size" & "blank" info */
-	u16 spromstatus;		/* 0x7BE, rev2 */
-	u32 PAD[464];
-
-	u16 PAD[0x80];
-};
-
-int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
-			   struct brcmf_chip **ci_ptr);
-void brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr);
-void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
-				       struct brcmf_chip *ci,
-				       u32 drivestrength);
-u8 brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid);
-void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
-				    struct brcmf_chip *ci);
-bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
-				   struct brcmf_chip *ci, u32 rstvec);
-
-#endif		/* _BRCMFMAC_SDIO_CHIP_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 092e9c824992..5e53eb1b2ffa 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -182,6 +182,95 @@ struct brcmf_sdio_dev {
 	uint max_segment_size;
 };
 
+/* sdio core registers */
+struct sdpcmd_regs {
+	u32 corecontrol;		/* 0x00, rev8 */
+	u32 corestatus;			/* rev8 */
+	u32 PAD[1];
+	u32 biststatus;			/* rev8 */
+
+	/* PCMCIA access */
+	u16 pcmciamesportaladdr;	/* 0x010, rev8 */
+	u16 PAD[1];
+	u16 pcmciamesportalmask;	/* rev8 */
+	u16 PAD[1];
+	u16 pcmciawrframebc;		/* rev8 */
+	u16 PAD[1];
+	u16 pcmciaunderflowtimer;	/* rev8 */
+	u16 PAD[1];
+
+	/* interrupt */
+	u32 intstatus;			/* 0x020, rev8 */
+	u32 hostintmask;		/* rev8 */
+	u32 intmask;			/* rev8 */
+	u32 sbintstatus;		/* rev8 */
+	u32 sbintmask;			/* rev8 */
+	u32 funcintmask;		/* rev4 */
+	u32 PAD[2];
+	u32 tosbmailbox;		/* 0x040, rev8 */
+	u32 tohostmailbox;		/* rev8 */
+	u32 tosbmailboxdata;		/* rev8 */
+	u32 tohostmailboxdata;		/* rev8 */
+
+	/* synchronized access to registers in SDIO clock domain */
+	u32 sdioaccess;			/* 0x050, rev8 */
+	u32 PAD[3];
+
+	/* PCMCIA frame control */
+	u8 pcmciaframectrl;		/* 0x060, rev8 */
+	u8 PAD[3];
+	u8 pcmciawatermark;		/* rev8 */
+	u8 PAD[155];
+
+	/* interrupt batching control */
+	u32 intrcvlazy;			/* 0x100, rev8 */
+	u32 PAD[3];
+
+	/* counters */
+	u32 cmd52rd;			/* 0x110, rev8 */
+	u32 cmd52wr;			/* rev8 */
+	u32 cmd53rd;			/* rev8 */
+	u32 cmd53wr;			/* rev8 */
+	u32 abort;			/* rev8 */
+	u32 datacrcerror;		/* rev8 */
+	u32 rdoutofsync;		/* rev8 */
+	u32 wroutofsync;		/* rev8 */
+	u32 writebusy;			/* rev8 */
+	u32 readwait;			/* rev8 */
+	u32 readterm;			/* rev8 */
+	u32 writeterm;			/* rev8 */
+	u32 PAD[40];
+	u32 clockctlstatus;		/* rev8 */
+	u32 PAD[7];
+
+	u32 PAD[128];			/* DMA engines */
+
+	/* SDIO/PCMCIA CIS region */
+	char cis[512];			/* 0x400-0x5ff, rev6 */
+
+	/* PCMCIA function control registers */
+	char pcmciafcr[256];		/* 0x600-6ff, rev6 */
+	u16 PAD[55];
+
+	/* PCMCIA backplane access */
+	u16 backplanecsr;		/* 0x76E, rev6 */
+	u16 backplaneaddr0;		/* rev6 */
+	u16 backplaneaddr1;		/* rev6 */
+	u16 backplaneaddr2;		/* rev6 */
+	u16 backplaneaddr3;		/* rev6 */
+	u16 backplanedata0;		/* rev6 */
+	u16 backplanedata1;		/* rev6 */
+	u16 backplanedata2;		/* rev6 */
+	u16 backplanedata3;		/* rev6 */
+	u16 PAD[31];
+
+	/* sprom "size" & "blank" info */
+	u16 spromstatus;		/* 0x7BE, rev2 */
+	u32 PAD[464];
+
+	u16 PAD[0x80];
+};
+
 /* Register/deregister interrupt handler. */
 int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
 int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index d7718a5fa2f0..a54db9185747 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -351,13 +351,11 @@ u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
  * triples, returning a pointer to the substring whose first element
  * matches tag
  */
-struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
+const struct brcmf_tlv *
+brcmf_parse_tlvs(const void *buf, int buflen, uint key)
 {
-	struct brcmf_tlv *elt;
-	int totlen;
-
-	elt = (struct brcmf_tlv *)buf;
-	totlen = buflen;
+	const struct brcmf_tlv *elt = buf;
+	int totlen = buflen;
 
 	/* find tagged parameter */
 	while (totlen >= TLV_HDR_LEN) {
@@ -378,8 +376,8 @@ struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
  * not update the tlvs buffer pointer/length.
  */
 static bool
-brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
-		 u8 *oui, u32 oui_len, u8 type)
+brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
+		 const u8 *oui, u32 oui_len, u8 type)
 {
 	/* If the contents match the OUI and the type */
 	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
@@ -401,12 +399,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
 }
 
 static struct brcmf_vs_tlv *
-brcmf_find_wpaie(u8 *parse, u32 len)
+brcmf_find_wpaie(const u8 *parse, u32 len)
 {
-	struct brcmf_tlv *ie;
+	const struct brcmf_tlv *ie;
 
 	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
-		if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
+		if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
 				     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
 			return (struct brcmf_vs_tlv *)ie;
 	}
@@ -414,9 +412,9 @@ brcmf_find_wpaie(u8 *parse, u32 len)
 }
 
 static struct brcmf_vs_tlv *
-brcmf_find_wpsie(u8 *parse, u32 len)
+brcmf_find_wpsie(const u8 *parse, u32 len)
 {
-	struct brcmf_tlv *ie;
+	const struct brcmf_tlv *ie;
 
 	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
 		if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
@@ -1562,9 +1560,9 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 	struct ieee80211_channel *chan = sme->channel;
 	struct brcmf_join_params join_params;
 	size_t join_params_size;
-	struct brcmf_tlv *rsn_ie;
-	struct brcmf_vs_tlv *wpa_ie;
-	void *ie;
+	const struct brcmf_tlv *rsn_ie;
+	const struct brcmf_vs_tlv *wpa_ie;
+	const void *ie;
 	u32 ie_len;
 	struct brcmf_ext_join_params_le *ext_join_params;
 	u16 chanspec;
@@ -1591,7 +1589,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 			ie_len = wpa_ie->len + TLV_HDR_LEN;
 		} else {
 			/* find the RSN_IE */
-			rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len,
+			rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie,
+						  sme->ie_len,
 						  WLAN_EID_RSN);
 			if (rsn_ie) {
 				ie = rsn_ie;
@@ -1981,7 +1980,9 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	if (mac_addr) {
+	if (mac_addr &&
+		(params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+		(params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
 		brcmf_dbg(TRACE, "Exit");
 		return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
 	}
@@ -2164,6 +2165,8 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
 	s32 err = 0;
 	u8 *bssid = profile->bssid;
 	struct brcmf_sta_info_le sta_info_le;
+	u32 beacon_period;
+	u32 dtim_period;
 
 	brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
 	if (!check_vif_up(ifp->vif))
@@ -2218,6 +2221,30 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
 				sinfo->signal = rssi;
 				brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
 			}
+			err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
+						    &beacon_period);
+			if (err) {
+				brcmf_err("Could not get beacon period (%d)\n",
+					  err);
+				goto done;
+			} else {
+				sinfo->bss_param.beacon_interval =
+					beacon_period;
+				brcmf_dbg(CONN, "Beacon peroid %d\n",
+					  beacon_period);
+			}
+			err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
+						    &dtim_period);
+			if (err) {
+				brcmf_err("Could not get DTIM period (%d)\n",
+					  err);
+				goto done;
+			} else {
+				sinfo->bss_param.dtim_period = dtim_period;
+				brcmf_dbg(CONN, "DTIM peroid %d\n",
+					  dtim_period);
+			}
+			sinfo->filled |= STATION_INFO_BSS_PARAM;
 		}
 	} else
 		err = -EPERM;
@@ -2455,7 +2482,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
 	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
 	struct brcmf_bss_info_le *bi;
 	struct brcmf_ssid *ssid;
-	struct brcmf_tlv *tim;
+	const struct brcmf_tlv *tim;
 	u16 beacon_interval;
 	u8 dtim_period;
 	size_t ie_len;
@@ -3220,8 +3247,9 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
 }
 
 static s32
-brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
-		     bool is_rsn_ie)
+brcmf_configure_wpaie(struct net_device *ndev,
+		      const struct brcmf_vs_tlv *wpa_ie,
+		      bool is_rsn_ie)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	u32 auth = 0; /* d11 open authentication */
@@ -3707,11 +3735,11 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 	s32 ie_offset;
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct brcmf_if *ifp = netdev_priv(ndev);
-	struct brcmf_tlv *ssid_ie;
+	const struct brcmf_tlv *ssid_ie;
 	struct brcmf_ssid_le ssid_le;
 	s32 err = -EPERM;
-	struct brcmf_tlv *rsn_ie;
-	struct brcmf_vs_tlv *wpa_ie;
+	const struct brcmf_tlv *rsn_ie;
+	const struct brcmf_vs_tlv *wpa_ie;
 	struct brcmf_join_params join_params;
 	enum nl80211_iftype dev_role;
 	struct brcmf_fil_bss_enable_le bss_enable;
@@ -4658,6 +4686,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
 	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	struct net_device *ndev = ifp->ndev;
 	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct ieee80211_channel *chan;
 	s32 err = 0;
 
 	if (ifp->vif->mode == WL_MODE_AP) {
@@ -4665,9 +4694,10 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
 	} else if (brcmf_is_linkup(e)) {
 		brcmf_dbg(CONN, "Linkup\n");
 		if (brcmf_is_ibssmode(ifp->vif)) {
+			chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
 			memcpy(profile->bssid, e->addr, ETH_ALEN);
 			wl_inform_ibss(cfg, ndev, e->addr);
-			cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
+			cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
 			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
 				  &ifp->vif->sme_state);
 			set_bit(BRCMF_VIF_STATUS_CONNECTED,
@@ -5164,9 +5194,6 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
 				ieee80211_channel_to_frequency(ch.chnum, band);
 			band_chan_arr[index].hw_value = ch.chnum;
 
-			brcmf_err("channel %d: f=%d bw=%d sb=%d\n",
-				  ch.chnum, band_chan_arr[index].center_freq,
-				  ch.bw, ch.sb);
 			if (ch.bw == BRCMU_CHAN_BW_40) {
 				/* assuming the order is HT20, HT40 Upper,
 				 * HT40 lower from chanspecs
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 2dc6a074e8ed..254feed2860e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -491,7 +491,8 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
 s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
 			  const u8 *vndr_ie_buf, u32 vndr_ie_len);
 s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
-struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
+const struct brcmf_tlv *
+brcmf_parse_tlvs(const void *buf, int buflen, uint key);
 u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
 			struct ieee80211_channel *ch);
 u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index d36e252d2ccb..596525528f50 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -147,7 +147,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
 
 	if (!sta->ap && sta->u.sta.challenge)
 		kfree(sta->u.sta.challenge);
-	del_timer(&sta->timer);
+	del_timer_sync(&sta->timer);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
 	kfree(sta);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index 9a45f6f626f6..76b0729ade17 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -891,8 +891,7 @@ il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
 {
 }
 
-static struct rate_control_ops rs_ops = {
-	.module = NULL,
+static const struct rate_control_ops rs_ops = {
 	.name = RS_NAME,
 	.tx_status = il3945_rs_tx_status,
 	.get_rate = il3945_rs_get_rate,
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index 4d5e33259ca8..eaaeea19d8c5 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2807,8 +2807,7 @@ il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
 {
 }
 
-static struct rate_control_ops rs_4965_ops = {
-	.module = NULL,
+static const struct rate_control_ops rs_4965_ops = {
 	.name = IL4965_RS_NAME,
 	.tx_status = il4965_rs_tx_status,
 	.get_rate = il4965_rs_get_rate,
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 3eb2102ce236..74b3b4de7bb7 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -68,6 +68,19 @@ config IWLWIFI_OPMODE_MODULAR
 comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
 	depends on IWLWIFI && IWLDVM=n && IWLMVM=n
 
+config IWLWIFI_BCAST_FILTERING
+	bool "Enable broadcast filtering"
+	depends on IWLMVM
+	help
+	  Say Y here to enable default bcast filtering configuration.
+
+	  Enabling broadcast filtering will drop any incoming wireless
+	  broadcast frames, except some very specific predefined
+	  patterns (e.g. incoming arp requests).
+
+	  If unsure, don't enable this option, as some programs might
+	  expect incoming broadcasts for their normal operations.
+
 menu "Debugging Options"
 	depends on IWLWIFI
 
@@ -111,6 +124,7 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
 	  Enable use of experimental ucode for testing and debugging.
 
 config IWLWIFI_DEVICE_TRACING
+
 	bool "iwlwifi device access tracing"
 	depends on IWLWIFI
 	depends on EVENT_TRACING
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 1fa64429bcc2..3d32f4120174 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -8,7 +8,7 @@ iwlwifi-objs		+= iwl-eeprom-read.o iwl-eeprom-parse.o
 iwlwifi-objs		+= iwl-phy-db.o iwl-nvm-parse.o
 iwlwifi-objs		+= pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
 iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
-iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o
+iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o
 
 iwlwifi-objs += $(iwlwifi-m)
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index 0977d93b529d..aa773a2da4ab 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -176,46 +176,46 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
  * (2.4 GHz) band.
  */
 
-static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
+static const u16 expected_tpt_legacy[IWL_RATE_COUNT] = {
 	7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
 };
 
-static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 42, 0,  76, 102, 124, 159, 183, 193, 202}, /* Norm */
 	{0, 0, 0, 0, 46, 0,  82, 110, 132, 168, 192, 202, 210}, /* SGI */
 	{0, 0, 0, 0, 47, 0,  91, 133, 171, 242, 305, 334, 362}, /* AGG */
 	{0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */
 };
 
-static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
 	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
 	{0, 0, 0, 0,  94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */
 	{0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */
 };
 
-static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */
 	{0, 0, 0, 0,  81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */
 	{0, 0, 0, 0,  89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */
 	{0, 0, 0, 0,  97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/
 };
 
-static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
 	{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
 	{0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */
 	{0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */
 };
 
-static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */
 	{0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */
 	{0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */
 	{0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */
 };
 
-static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 152, 0, 211, 239, 255, 279,  290,  294,  297}, /* Norm */
 	{0, 0, 0, 0, 160, 0, 219, 245, 261, 284,  294,  297,  300}, /* SGI */
 	{0, 0, 0, 0, 254, 0, 443, 584, 695, 868,  984, 1030, 1070}, /* AGG */
@@ -1111,7 +1111,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 				      struct iwl_scale_tbl_info *tbl)
 {
 	/* Used to choose among HT tables */
-	s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
+	const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT];
 
 	/* Check for invalid LQ type */
 	if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
@@ -1173,9 +1173,8 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
 	    &(lq_sta->lq_info[lq_sta->active_tbl]);
 	s32 active_sr = active_tbl->win[index].success_ratio;
 	s32 active_tpt = active_tbl->expected_tpt[index];
-
 	/* expected "search" throughput */
-	s32 *tpt_tbl = tbl->expected_tpt;
+	const u16 *tpt_tbl = tbl->expected_tpt;
 
 	s32 new_rate, high, low, start_hi;
 	u16 high_low;
@@ -3319,8 +3318,8 @@ static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sba
 			      struct ieee80211_sta *sta, void *priv_sta)
 {
 }
-static struct rate_control_ops rs_ops = {
-	.module = NULL,
+
+static const struct rate_control_ops rs_ops = {
 	.name = RS_NAME,
 	.tx_status = rs_tx_status,
 	.get_rate = rs_get_rate,
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h
index bdd5644a400b..f6bd25cad203 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.h
@@ -315,7 +315,7 @@ struct iwl_scale_tbl_info {
 	u8 is_dup;	/* 1 = duplicated data streams */
 	u8 action;	/* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
 	u8 max_search;	/* maximun number of tables we can search */
-	s32 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
+	const u16 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
 	u32 current_rate;  /* rate_n_flags, uCode API format */
 	struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
 };
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c
index c0d070c5df5e..9cdd91cdf661 100644
--- a/drivers/net/wireless/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c
@@ -590,6 +590,7 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
 			sizeof(priv->tid_data[sta_id][tid]));
 
 	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
 
 	priv->num_stations--;
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index a6839dfcb82d..398dd096674c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -1291,8 +1291,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
 	struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
 	struct iwl_ht_agg *agg;
 	struct sk_buff_head reclaimed_skbs;
-	struct ieee80211_tx_info *info;
-	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb;
 	int sta_id;
 	int tid;
@@ -1379,22 +1377,28 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
 	freed = 0;
 
 	skb_queue_walk(&reclaimed_skbs, skb) {
-		hdr = (struct ieee80211_hdr *)skb->data;
+		struct ieee80211_hdr *hdr = (void *)skb->data;
+		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 		if (ieee80211_is_data_qos(hdr->frame_control))
 			freed++;
 		else
 			WARN_ON_ONCE(1);
 
-		info = IEEE80211_SKB_CB(skb);
 		iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
 
+		memset(&info->status, 0, sizeof(info->status));
+		/* Packet was transmitted successfully, failures come as single
+		 * frames because before failing a frame the firmware transmits
+		 * it without aggregation at least once.
+		 */
+		info->flags |= IEEE80211_TX_STAT_ACK;
+
 		if (freed == 1) {
 			/* this is the first skb we deliver in this batch */
 			/* put the rate scaling data there */
 			info = IEEE80211_SKB_CB(skb);
 			memset(&info->status, 0, sizeof(info->status));
-			info->flags |= IEEE80211_TX_STAT_ACK;
 			info->flags |= IEEE80211_TX_STAT_AMPDU;
 			info->status.ampdu_ack_len = ba_resp->txed_2_done;
 			info->status.ampdu_len = ba_resp->txed;
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 2a59da2ff87a..fbd262ffa497 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -71,8 +71,8 @@
 #define IWL3160_UCODE_API_MAX	8
 
 /* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK	7
-#define IWL3160_UCODE_API_OK	7
+#define IWL7260_UCODE_API_OK	8
+#define IWL3160_UCODE_API_OK	8
 
 /* Lowest firmware API version supported */
 #define IWL7260_UCODE_API_MIN	7
@@ -95,6 +95,8 @@
 #define IWL7265_FW_PRE "iwlwifi-7265-"
 #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
 
+#define NVM_HW_SECTION_NUM_FAMILY_7000		0
+
 static const struct iwl_base_params iwl7000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
@@ -120,7 +122,8 @@ static const struct iwl_ht_params iwl7000_ht_params = {
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.base_params = &iwl7000_base_params,			\
-	.led_mode = IWL_LED_RF_STATE
+	.led_mode = IWL_LED_RF_STATE,				\
+	.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000
 
 
 const struct iwl_cfg iwl7260_2ac_cfg = {
@@ -194,6 +197,17 @@ const struct iwl_cfg iwl3160_n_cfg = {
 	.host_interrupt_operation_mode = true,
 };
 
+static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
+	{.pwr = 1600, .backoff = 0},
+	{.pwr = 1300, .backoff = 467},
+	{.pwr = 900,  .backoff = 1900},
+	{.pwr = 800, .backoff = 2630},
+	{.pwr = 700, .backoff = 3720},
+	{.pwr = 600, .backoff = 5550},
+	{.pwr = 500, .backoff = 9350},
+	{0},
+};
+
 const struct iwl_cfg iwl7265_2ac_cfg = {
 	.name = "Intel(R) Dual Band Wireless AC 7265",
 	.fw_name_pre = IWL7265_FW_PRE,
@@ -201,6 +215,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
 	.ht_params = &iwl7000_ht_params,
 	.nvm_ver = IWL7265_NVM_VERSION,
 	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
 };
 
 const struct iwl_cfg iwl7265_2n_cfg = {
@@ -210,6 +225,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
 	.ht_params = &iwl7000_ht_params,
 	.nvm_ver = IWL7265_NVM_VERSION,
 	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
 };
 
 const struct iwl_cfg iwl7265_n_cfg = {
@@ -219,6 +235,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
 	.ht_params = &iwl7000_ht_params,
 	.nvm_ver = IWL7265_NVM_VERSION,
 	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
 };
 
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
new file mode 100644
index 000000000000..f5bd82b88592
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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/stringify.h>
+#include "iwl-config.h"
+#include "iwl-agn-hw.h"
+
+/* Highest firmware API version supported */
+#define IWL8000_UCODE_API_MAX	8
+
+/* Oldest version we won't warn about */
+#define IWL8000_UCODE_API_OK	8
+
+/* Lowest firmware API version supported */
+#define IWL8000_UCODE_API_MIN	8
+
+/* NVM versions */
+#define IWL8000_NVM_VERSION		0x0a1d
+#define IWL8000_TX_POWER_VERSION	0xffff /* meaningless */
+
+#define IWL8000_FW_PRE "iwlwifi-8000-"
+#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
+
+#define NVM_HW_SECTION_NUM_FAMILY_8000		10
+
+static const struct iwl_base_params iwl8000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = true,
+	.pcie_l1_allowed = true,
+};
+
+static const struct iwl_ht_params iwl8000_ht_params = {
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
+};
+
+#define IWL_DEVICE_8000						\
+	.ucode_api_max = IWL8000_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL8000_UCODE_API_OK,			\
+	.ucode_api_min = IWL8000_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_8000,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.base_params = &iwl8000_base_params,			\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000
+
+const struct iwl_cfg iwl8260_2ac_cfg = {
+	.name = "Intel(R) Dual Band Wireless AC 8260",
+	.fw_name_pre = IWL8000_FW_PRE,
+	IWL_DEVICE_8000,
+	.ht_params = &iwl8000_ht_params,
+	.nvm_ver = IWL8000_NVM_VERSION,
+	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
+};
+
+const struct iwl_cfg iwl8260_n_cfg = {
+	.name = "Intel(R) Dual Band Wireless-AC 8260",
+	.fw_name_pre = IWL8000_FW_PRE,
+	IWL_DEVICE_8000,
+	.ht_params = &iwl8000_ht_params,
+	.nvm_ver = IWL8000_NVM_VERSION,
+	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
+};
+
+MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 1ced525157dc..13ec56607d10 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -84,6 +84,7 @@ enum iwl_device_family {
 	IWL_DEVICE_FAMILY_6050,
 	IWL_DEVICE_FAMILY_6150,
 	IWL_DEVICE_FAMILY_7000,
+	IWL_DEVICE_FAMILY_8000,
 };
 
 /*
@@ -192,6 +193,15 @@ struct iwl_eeprom_params {
 	bool enhanced_txpower;
 };
 
+/* Tx-backoff power threshold
+ * @pwr: The power limit in mw
+ * @backoff: The tx-backoff in uSec
+ */
+struct iwl_pwr_tx_backoff {
+	u32 pwr;
+	u32 backoff;
+};
+
 /**
  * struct iwl_cfg
  * @name: Offical name of the device
@@ -217,6 +227,9 @@ struct iwl_eeprom_params {
  * @high_temp: Is this NIC is designated to be in high temperature.
  * @host_interrupt_operation_mode: device needs host interrupt operation
  *	mode set
+ * @d0i3: device uses d0i3 instead of d3
+ * @nvm_hw_section_num: the ID of the HW NVM section
+ * @pwr_tx_backoffs: translation table between power limits and backoffs
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -247,6 +260,9 @@ struct iwl_cfg {
 	const bool internal_wimax_coex;
 	const bool host_interrupt_operation_mode;
 	bool high_temp;
+	bool d0i3;
+	u8   nvm_hw_section_num;
+	const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
 };
 
 /*
@@ -307,6 +323,8 @@ extern const struct iwl_cfg iwl3160_n_cfg;
 extern const struct iwl_cfg iwl7265_2ac_cfg;
 extern const struct iwl_cfg iwl7265_2n_cfg;
 extern const struct iwl_cfg iwl7265_n_cfg;
+extern const struct iwl_cfg iwl8260_2ac_cfg;
+extern const struct iwl_cfg iwl8260_n_cfg;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 9d325516c42d..f13dec9ad9c9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -395,38 +395,6 @@
 #define CSR_DRAM_INT_TBL_ENABLE		(1 << 31)
 #define CSR_DRAM_INIT_TBL_WRAP_CHECK	(1 << 27)
 
-/* SECURE boot registers */
-#define CSR_SECURE_BOOT_CONFIG_ADDR	(0x100)
-enum secure_boot_config_reg {
-	CSR_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP	= 0x00000001,
-	CSR_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ	= 0x00000002,
-};
-
-#define CSR_SECURE_BOOT_CPU1_STATUS_ADDR	(0x100)
-#define CSR_SECURE_BOOT_CPU2_STATUS_ADDR	(0x100)
-enum secure_boot_status_reg {
-	CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS		= 0x00000003,
-	CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED	= 0x00000002,
-	CSR_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS		= 0x00000004,
-	CSR_SECURE_BOOT_CPU_STATUS_VERF_FAIL		= 0x00000008,
-	CSR_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL	= 0x00000010,
-};
-
-#define CSR_UCODE_LOAD_STATUS_ADDR	(0x100)
-enum secure_load_status_reg {
-	CSR_CPU_STATUS_LOADING_STARTED			= 0x00000001,
-	CSR_CPU_STATUS_LOADING_COMPLETED		= 0x00000002,
-	CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED		= 0x000000F8,
-	CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK		= 0x0000FF00,
-};
-
-#define CSR_SECURE_INSPECTOR_CODE_ADDR	(0x100)
-#define CSR_SECURE_INSPECTOR_DATA_ADDR	(0x100)
-
-#define CSR_SECURE_TIME_OUT	(100)
-
-#define FH_TCSR_0_REG0 (0x1D00)
-
 /*
  * HBUS (Host-side Bus)
  *
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index a75aac986a23..c8cbdbe15924 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -126,6 +126,7 @@ do {                                            			\
 /* 0x00000F00 - 0x00000100 */
 #define IWL_DL_POWER		0x00000100
 #define IWL_DL_TEMP		0x00000200
+#define IWL_DL_RPM		0x00000400
 #define IWL_DL_SCAN		0x00000800
 /* 0x0000F000 - 0x00001000 */
 #define IWL_DL_ASSOC		0x00001000
@@ -189,5 +190,6 @@ do {                                            			\
 #define IWL_DEBUG_RADIO(p, f, a...)	IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
 #define IWL_DEBUG_POWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
 #define IWL_DEBUG_11H(p, f, a...)	IWL_DEBUG(p, IWL_DL_11H, f, ## a)
+#define IWL_DEBUG_RPM(p, f, a...)	IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
 
 #endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 75103554cd63..bcfdcfb4485e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -128,7 +128,7 @@ struct iwl_drv {
 	const struct iwl_cfg *cfg;
 
 	int fw_index;                   /* firmware we're trying to load */
-	char firmware_name[25];         /* name of firmware file to load */
+	char firmware_name[32];         /* name of firmware file to load */
 
 	struct completion request_firmware_complete;
 
@@ -237,7 +237,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
 		return -ENOENT;
 	}
 
-	sprintf(drv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+	snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode",
+		 name_pre, tag);
 
 	IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
 		       (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 5f1493c44097..f80ba586c253 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -95,6 +95,8 @@
  * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a
  *	single bound interface).
  * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
+ * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
+ * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
  */
 enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_PAN			= BIT(0),
@@ -119,6 +121,8 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_P2P_PS		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT	= BIT(24),
 	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
+	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
+	IWL_UCODE_TLV_FLAGS_GO_UAPSD		= BIT(30),
 };
 
 /* The default calibrate table size if not specified by firmware file */
@@ -160,8 +164,7 @@ enum iwl_ucode_sec {
  * For 16.0 uCode and above, there is no differentiation between sections,
  * just an offset to the HW address.
  */
-#define IWL_UCODE_SECTION_MAX 6
-#define IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU	(IWL_UCODE_SECTION_MAX/2)
+#define IWL_UCODE_SECTION_MAX 12
 
 struct iwl_ucode_capabilities {
 	u32 max_probe_length;
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index f98175a0d35b..07372f2b0250 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -130,6 +130,21 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
 }
 IWL_EXPORT_SYMBOL(iwl_write_prph);
 
+int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
+		      u32 bits, u32 mask, int timeout)
+{
+	int t = 0;
+
+	do {
+		if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
+}
+
 void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 {
 	unsigned long flags;
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index c339c1bed080..9e81b23d738b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -72,6 +72,8 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
 
 u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
 void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
+int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
+		      u32 bits, u32 mask, int timeout);
 void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
 void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
 			    u32 bits, u32 mask);
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 725e954d8475..53b9cad50477 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -402,11 +402,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
 	iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE,
 			tx_chains, rx_chains);
 
-	data->calib_version = 255;   /* TODO:
-					this value will prevent some checks from
-					failing, we need to check if this
-					field is still needed, and if it does,
-					where is it in the NVM*/
+	data->calib_version = 255;
 
 	return data;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index b5be51f3cd3d..5d78207040b0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -131,6 +131,8 @@ struct iwl_cfg;
  * @nic_config: configure NIC, called before firmware is started.
  *	May sleep
  * @wimax_active: invoked when WiMax becomes active. May sleep
+ * @enter_d0i3: configure the fw to enter d0i3. May sleep.
+ * @exit_d0i3: configure the fw to exit d0i3. May sleep.
  */
 struct iwl_op_mode_ops {
 	struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@@ -148,6 +150,8 @@ struct iwl_op_mode_ops {
 	void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
 	void (*nic_config)(struct iwl_op_mode *op_mode);
 	void (*wimax_active)(struct iwl_op_mode *op_mode);
+	int (*enter_d0i3)(struct iwl_op_mode *op_mode);
+	int (*exit_d0i3)(struct iwl_op_mode *op_mode);
 };
 
 int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
@@ -155,7 +159,7 @@ void iwl_opmode_deregister(const char *name);
 
 /**
  * struct iwl_op_mode - operational mode
- * @ops - pointer to its own ops
+ * @ops: pointer to its own ops
  *
  * This holds an implementation of the mac80211 / fw API.
  */
@@ -226,4 +230,22 @@ static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
 	op_mode->ops->wimax_active(op_mode);
 }
 
+static inline int iwl_op_mode_enter_d0i3(struct iwl_op_mode *op_mode)
+{
+	might_sleep();
+
+	if (!op_mode->ops->enter_d0i3)
+		return 0;
+	return op_mode->ops->enter_d0i3(op_mode);
+}
+
+static inline int iwl_op_mode_exit_d0i3(struct iwl_op_mode *op_mode)
+{
+	might_sleep();
+
+	if (!op_mode->ops->exit_d0i3)
+		return 0;
+	return op_mode->ops->exit_d0i3(op_mode);
+}
+
 #endif /* __iwl_op_mode_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
index fa77d63a277a..b761ac4822a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c
+++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
@@ -72,7 +72,7 @@
 #include "iwl-trans.h"
 
 #define CHANNEL_NUM_SIZE	4	/* num of channels in calib_ch size */
-#define IWL_NUM_PAPD_CH_GROUPS	4
+#define IWL_NUM_PAPD_CH_GROUPS	7
 #define IWL_NUM_TXP_CH_GROUPS	9
 
 struct iwl_phy_db_entry {
@@ -383,7 +383,7 @@ static int iwl_phy_db_send_all_channel_groups(
 		if (!entry)
 			return -EINVAL;
 
-		if (WARN_ON_ONCE(!entry->size))
+		if (!entry->size)
 			continue;
 
 		/* Send the requested PHY DB section */
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 100bd0d79681..9c90186d1744 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -105,6 +105,13 @@
 /* Device NMI register */
 #define DEVICE_SET_NMI_REG 0x00a01c30
 
+/*
+ * Device reset for family 8000
+ * write to bit 24 in order to reset the CPU
+*/
+#define RELEASE_CPU_RESET		(0x300C)
+#define RELEASE_CPU_RESET_BIT		BIT(24)
+
 /*****************************************************************************
  *                        7000/3000 series SHR DTS addresses                 *
  *****************************************************************************/
@@ -281,4 +288,43 @@ static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
 #define OSC_CLK				(0xa04068)
 #define OSC_CLK_FORCE_CONTROL		(0x8)
 
+/* SECURE boot registers */
+#define LMPM_SECURE_BOOT_CONFIG_ADDR	(0x100)
+enum secure_boot_config_reg {
+	LMPM_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP	= 0x00000001,
+	LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ	= 0x00000002,
+};
+
+#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR	(0x1E30)
+#define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR	(0x1E34)
+enum secure_boot_status_reg {
+	LMPM_SECURE_BOOT_CPU_STATUS_VERF_STATUS		= 0x00000001,
+	LMPM_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED	= 0x00000002,
+	LMPM_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS	= 0x00000004,
+	LMPM_SECURE_BOOT_CPU_STATUS_VERF_FAIL		= 0x00000008,
+	LMPM_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL	= 0x00000010,
+	LMPM_SECURE_BOOT_STATUS_SUCCESS			= 0x00000003,
+};
+
+#define CSR_UCODE_LOAD_STATUS_ADDR	(0x1E70)
+enum secure_load_status_reg {
+	LMPM_CPU_UCODE_LOADING_STARTED			= 0x00000001,
+	LMPM_CPU_HDRS_LOADING_COMPLETED			= 0x00000003,
+	LMPM_CPU_UCODE_LOADING_COMPLETED		= 0x00000007,
+	LMPM_CPU_STATUS_NUM_OF_LAST_COMPLETED		= 0x000000F8,
+	LMPM_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK	= 0x0000FF00,
+};
+
+#define LMPM_SECURE_INSPECTOR_CODE_ADDR	(0x1E38)
+#define LMPM_SECURE_INSPECTOR_DATA_ADDR	(0x1E3C)
+#define LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR	(0x1E78)
+#define LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR	(0x1E7C)
+
+#define LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE	(0x400000)
+#define LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE	(0x402000)
+#define LMPM_SECURE_CPU1_HDR_MEM_SPACE		(0x420000)
+#define LMPM_SECURE_CPU2_HDR_MEM_SPACE		(0x420400)
+
+#define LMPM_SECURE_TIME_OUT	(100)
+
 #endif				/* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 1f065cf4a4ba..7b19274b550f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -193,12 +193,23 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
  * @CMD_ASYNC: Return right away and don't wait for the response
  * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
  *	response. The caller needs to call iwl_free_resp when done.
+ * @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the
+ *	command queue, but after other high priority commands. valid only
+ *	with CMD_ASYNC.
+ * @CMD_SEND_IN_IDLE: The command should be sent even when the trans is idle.
+ * @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
+ * @CMD_WAKE_UP_TRANS: The command response should wake up the trans
+ *	(i.e. mark it as non-idle).
  */
 enum CMD_MODE {
 	CMD_SYNC		= 0,
 	CMD_ASYNC		= BIT(0),
 	CMD_WANT_SKB		= BIT(1),
 	CMD_SEND_IN_RFKILL	= BIT(2),
+	CMD_HIGH_PRIO		= BIT(3),
+	CMD_SEND_IN_IDLE	= BIT(4),
+	CMD_MAKE_TRANS_IDLE	= BIT(5),
+	CMD_WAKE_UP_TRANS	= BIT(6),
 };
 
 #define DEF_CMD_PAYLOAD_SIZE 320
@@ -335,6 +346,9 @@ enum iwl_d3_status {
  * @STATUS_INT_ENABLED: interrupts are enabled
  * @STATUS_RFKILL: the HW RFkill switch is in KILL position
  * @STATUS_FW_ERROR: the fw is in error state
+ * @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands
+ *	are sent
+ * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
  */
 enum iwl_trans_status {
 	STATUS_SYNC_HCMD_ACTIVE,
@@ -343,6 +357,8 @@ enum iwl_trans_status {
 	STATUS_INT_ENABLED,
 	STATUS_RFKILL,
 	STATUS_FW_ERROR,
+	STATUS_TRANS_GOING_IDLE,
+	STATUS_TRANS_IDLE,
 };
 
 /**
@@ -443,6 +459,11 @@ struct iwl_trans;
  * @release_nic_access: let the NIC go to sleep. The "flags" parameter
  *	must be the same one that was sent before to the grab_nic_access.
  * @set_bits_mask - set SRAM register according to value and mask.
+ * @ref: grab a reference to the transport/FW layers, disallowing
+ *	certain low power states
+ * @unref: release a reference previously taken with @ref. Note that
+ *	initially the reference count is 1, making an initial @unref
+ *	necessary to allow low power states.
  */
 struct iwl_trans_ops {
 
@@ -489,6 +510,8 @@ struct iwl_trans_ops {
 				   unsigned long *flags);
 	void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
 			      u32 value);
+	void (*ref)(struct iwl_trans *trans);
+	void (*unref)(struct iwl_trans *trans);
 };
 
 /**
@@ -523,6 +546,7 @@ enum iwl_trans_state {
  *	starting the firmware, used for tracing
  * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
  *	start of the 802.11 header in the @rx_mpdu_cmd
+ * @dflt_pwr_limit: default power limit fetched from the platform (ACPI)
  */
 struct iwl_trans {
 	const struct iwl_trans_ops *ops;
@@ -551,6 +575,8 @@ struct iwl_trans {
 	struct lockdep_map sync_cmd_lockdep_map;
 #endif
 
+	u64 dflt_pwr_limit;
+
 	/* pointer to trans specific struct */
 	/*Ensure that this pointer will always be aligned to sizeof pointer */
 	char trans_specific[0] __aligned(sizeof(void *));
@@ -627,6 +653,18 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
 	return trans->ops->d3_resume(trans, status, test);
 }
 
+static inline void iwl_trans_ref(struct iwl_trans *trans)
+{
+	if (trans->ops->ref)
+		trans->ops->ref(trans);
+}
+
+static inline void iwl_trans_unref(struct iwl_trans *trans)
+{
+	if (trans->ops->unref)
+		trans->ops->unref(trans);
+}
+
 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 				     struct iwl_host_cmd *cmd)
 {
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index f98ec2b23898..41d390fd2ac8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM)   += iwlmvm.o
 iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
 iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
 iwlmvm-y += scan.o time-event.o rs.o
-iwlmvm-y += power.o power_legacy.o bt-coex.o
+iwlmvm-y += power.o bt-coex.o
 iwlmvm-y += led.o tt.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index 76cde6ce6551..38a54a3fde34 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -378,7 +378,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 
 	flags = iwlwifi_mod_params.bt_coex_active ?
 			BT_COEX_NW : BT_COEX_DISABLE;
-	flags |= BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN | BT_SYNC_2_BT_DISABLE;
 	bt_cmd->flags = cpu_to_le32(flags);
 
 	bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
@@ -399,6 +398,9 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 					    BT_VALID_TXRX_MAX_FREQ_0 |
 					    BT_VALID_SYNC_TO_SCO);
 
+	if (IWL_MVM_BT_COEX_SYNC2SCO)
+		bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
+
 	if (mvm->cfg->bt_shared_single_ant)
 		memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
 		       sizeof(iwl_single_shared_ant));
@@ -489,8 +491,7 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
 	return ret;
 }
 
-static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
-				       bool enable)
+int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)
 {
 	struct iwl_bt_coex_cmd *bt_cmd;
 	/* Send ASYNC since this can be sent from an atomic context */
@@ -500,25 +501,16 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
 		.dataflags = { IWL_HCMD_DFL_DUP, },
 		.flags = CMD_ASYNC,
 	};
-
-	struct ieee80211_sta *sta;
 	struct iwl_mvm_sta *mvmsta;
 	int ret;
 
-	if (sta_id == IWL_MVM_STATION_COUNT)
-		return 0;
-
-	sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
-					lockdep_is_held(&mvm->mutex));
-
-	/* This can happen if the station has been removed right now */
-	if (IS_ERR_OR_NULL(sta))
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
+	if (!mvmsta)
 		return 0;
 
-	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
 	/* nothing to do */
-	if (mvmsta->bt_reduced_txpower == enable)
+	if (mvmsta->bt_reduced_txpower_dbg ||
+	    mvmsta->bt_reduced_txpower == enable)
 		return 0;
 
 	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
@@ -552,6 +544,7 @@ struct iwl_bt_iterator_data {
 	bool reduced_tx_power;
 	struct ieee80211_chanctx_conf *primary;
 	struct ieee80211_chanctx_conf *secondary;
+	bool primary_ll;
 };
 
 static inline
@@ -577,72 +570,113 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
 	struct iwl_mvm *mvm = data->mvm;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	enum ieee80211_smps_mode smps_mode;
+	u32 bt_activity_grading;
 	int ave_rssi;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (vif->type != NL80211_IFTYPE_STATION &&
-	    vif->type != NL80211_IFTYPE_AP)
-		return;
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		/* default smps_mode for BSS / P2P client is AUTOMATIC */
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+		data->num_bss_ifaces++;
 
-	smps_mode = IEEE80211_SMPS_AUTOMATIC;
+		/*
+		 * Count unassoc BSSes, relax SMSP constraints
+		 * and disable reduced Tx Power
+		 */
+		if (!vif->bss_conf.assoc) {
+			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+					    smps_mode);
+			if (iwl_mvm_bt_coex_reduced_txp(mvm,
+							mvmvif->ap_sta_id,
+							false))
+				IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+			return;
+		}
+		break;
+	case NL80211_IFTYPE_AP:
+		/* default smps_mode for AP / GO is OFF */
+		smps_mode = IEEE80211_SMPS_OFF;
+		if (!mvmvif->ap_ibss_active) {
+			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+					    smps_mode);
+			return;
+		}
+
+		/* the Ack / Cts kill mask must be default if AP / GO */
+		data->reduced_tx_power = false;
+		break;
+	default:
+		return;
+	}
 
 	chanctx_conf = rcu_dereference(vif->chanctx_conf);
 
 	/* If channel context is invalid or not on 2.4GHz .. */
 	if ((!chanctx_conf ||
 	     chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
-		/* ... and it is an associated STATION, relax constraints */
-		if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc)
-			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
-					    smps_mode);
-		iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+		/* ... relax constraints and disable rssi events */
+		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+				    smps_mode);
+		if (vif->type == NL80211_IFTYPE_STATION)
+			iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
 		return;
 	}
 
-	/* SoftAP / GO will always be primary */
-	if (vif->type == NL80211_IFTYPE_AP) {
-		if (!mvmvif->ap_ibss_active)
-			return;
+	bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
+	if (bt_activity_grading >= BT_HIGH_TRAFFIC)
+		smps_mode = IEEE80211_SMPS_STATIC;
+	else if (bt_activity_grading >= BT_LOW_TRAFFIC)
+		smps_mode = vif->type == NL80211_IFTYPE_AP ?
+				IEEE80211_SMPS_OFF :
+				IEEE80211_SMPS_DYNAMIC;
+	IWL_DEBUG_COEX(data->mvm,
+		       "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
+		       mvmvif->id, data->notif->bt_status, bt_activity_grading,
+		       smps_mode);
 
-		/* the Ack / Cts kill mask must be default if AP / GO */
-		data->reduced_tx_power = false;
+	iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
 
-		if (chanctx_conf == data->primary)
-			return;
+	/* low latency is always primary */
+	if (iwl_mvm_vif_low_latency(mvmvif)) {
+		data->primary_ll = true;
 
-		/* downgrade the current primary no matter what its type is */
 		data->secondary = data->primary;
 		data->primary = chanctx_conf;
-		return;
 	}
 
-	data->num_bss_ifaces++;
+	if (vif->type == NL80211_IFTYPE_AP) {
+		if (!mvmvif->ap_ibss_active)
+			return;
 
-	/* we are now a STA / P2P Client, and take associated ones only */
-	if (!vif->bss_conf.assoc)
+		if (chanctx_conf == data->primary)
+			return;
+
+		if (!data->primary_ll) {
+			/*
+			 * downgrade the current primary no matter what its
+			 * type is.
+			 */
+			data->secondary = data->primary;
+			data->primary = chanctx_conf;
+		} else {
+			/* there is low latency vif - we will be secondary */
+			data->secondary = chanctx_conf;
+		}
 		return;
+	}
 
-	/* STA / P2P Client, try to be primary if first vif */
+	/*
+	 * STA / P2P Client, try to be primary if first vif. If we are in low
+	 * latency mode, we are already in primary and just don't do much
+	 */
 	if (!data->primary || data->primary == chanctx_conf)
 		data->primary = chanctx_conf;
 	else if (!data->secondary)
 		/* if secondary is not NULL, it might be a GO */
 		data->secondary = chanctx_conf;
 
-	if (le32_to_cpu(data->notif->bt_activity_grading) >= BT_HIGH_TRAFFIC)
-		smps_mode = IEEE80211_SMPS_STATIC;
-	else if (le32_to_cpu(data->notif->bt_activity_grading) >=
-		 BT_LOW_TRAFFIC)
-		smps_mode = IEEE80211_SMPS_DYNAMIC;
-
-	IWL_DEBUG_COEX(data->mvm,
-		       "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
-		       mvmvif->id,  data->notif->bt_status,
-		       data->notif->bt_activity_grading, smps_mode);
-
-	iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
-
 	/* don't reduce the Tx power if in loose scheme */
 	if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
 	    mvm->cfg->bt_shared_single_ant) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index 036857698565..2d133b1b2dde 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -78,5 +78,9 @@
 #define IWL_MVM_PS_SNOOZE_INTERVAL		25
 #define IWL_MVM_PS_SNOOZE_WINDOW		50
 #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW		25
+#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT	64
+#define IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR	24 /* TU */
+#define IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR	24 /* TU */
+#define IWL_MVM_BT_COEX_SYNC2SCO		1
 
 #endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index f36a7ee0267f..b956e2f0b631 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -963,7 +963,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 	};
 	int ret, i;
 	int len __maybe_unused;
-	u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT;
 
 	if (!wowlan) {
 		/*
@@ -980,8 +979,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 
 	mutex_lock(&mvm->mutex);
 
-	old_aux_sta_id = mvm->aux_sta.sta_id;
-
 	/* see if there's only a single BSS vif and it's associated */
 	ieee80211_iterate_active_interfaces_atomic(
 		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
@@ -1067,16 +1064,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 	iwl_trans_stop_device(mvm->trans);
 
 	/*
-	 * The D3 firmware still hardcodes the AP station ID for the
-	 * BSS we're associated with as 0. Store the real STA ID here
-	 * and assign 0. When we leave this function, we'll restore
-	 * the original value for the resume code.
-	 */
-	old_ap_sta_id = mvm_ap_sta->sta_id;
-	mvm_ap_sta->sta_id = 0;
-	mvmvif->ap_sta_id = 0;
-
-	/*
 	 * Set the HW restart bit -- this is mostly true as we're
 	 * going to load new firmware and reprogram that, though
 	 * the reprogramming is going to be manual to avoid adding
@@ -1096,16 +1083,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 	mvm->ptk_ivlen = 0;
 	mvm->ptk_icvlen = 0;
 
-	/*
-	 * The D3 firmware still hardcodes the AP station ID for the
-	 * BSS we're associated with as 0. As a result, we have to move
-	 * the auxiliary station to ID 1 so the ID 0 remains free for
-	 * the AP station for later.
-	 * We set the sta_id to 1 here, and reset it to its previous
-	 * value (that we stored above) later.
-	 */
-	mvm->aux_sta.sta_id = 1;
-
 	ret = iwl_mvm_load_d3_fw(mvm);
 	if (ret)
 		goto out;
@@ -1191,11 +1168,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 	if (ret)
 		goto out;
 
-	ret = iwl_mvm_power_update_device_mode(mvm);
+	ret = iwl_mvm_power_update_device(mvm);
 	if (ret)
 		goto out;
 
-	ret = iwl_mvm_power_update_mode(mvm, vif);
+	ret = iwl_mvm_power_update_mac(mvm, vif);
 	if (ret)
 		goto out;
 
@@ -1222,10 +1199,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 
 	iwl_trans_d3_suspend(mvm->trans, test);
  out:
-	mvm->aux_sta.sta_id = old_aux_sta_id;
-	mvm_ap_sta->sta_id = old_ap_sta_id;
-	mvmvif->ap_sta_id = old_ap_sta_id;
-
 	if (ret < 0)
 		ieee80211_restart_hw(mvm->hw);
  out_noreset:
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 0e29cd83a06a..29b4396018b1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -185,7 +185,7 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
 
 	mutex_lock(&mvm->mutex);
 	iwl_dbgfs_update_pm(mvm, vif, param, val);
-	ret = iwl_mvm_power_update_mode(mvm, vif);
+	ret = iwl_mvm_power_update_mac(mvm, vif);
 	mutex_unlock(&mvm->mutex);
 
 	return ret ?: count;
@@ -202,7 +202,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
 	int bufsz = sizeof(buf);
 	int pos;
 
-	pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
+	pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -225,6 +225,29 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
 
 	ap_sta_id = mvmvif->ap_sta_id;
 
+	switch (ieee80211_vif_type_p2p(vif)) {
+	case NL80211_IFTYPE_ADHOC:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
+		break;
+	case NL80211_IFTYPE_STATION:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
+		break;
+	case NL80211_IFTYPE_AP:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
+		break;
+	case NL80211_IFTYPE_P2P_DEVICE:
+		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
+		break;
+	default:
+		break;
+	}
+
 	pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
 			 mvmvif->id, mvmvif->color);
 	pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
@@ -249,9 +272,10 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
 			struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 
 			pos += scnprintf(buf+pos, bufsz-pos,
-					 "ap_sta_id %d - reduced Tx power %d\n",
+					 "ap_sta_id %d - reduced Tx power %d force %d\n",
 					 ap_sta_id,
-					 mvm_sta->bt_reduced_txpower);
+					 mvm_sta->bt_reduced_txpower,
+					 mvm_sta->bt_reduced_txpower_dbg);
 		}
 	}
 
@@ -269,6 +293,36 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+static ssize_t iwl_dbgfs_reduced_txp_write(struct ieee80211_vif *vif,
+					   char *buf, size_t count,
+					   loff_t *ppos)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mvm *mvm = mvmvif->mvm;
+	struct iwl_mvm_sta *mvmsta;
+	bool reduced_tx_power;
+	int ret;
+
+	if (mvmvif->ap_sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
+		return -ENOTCONN;
+
+	if (strtobool(buf, &reduced_tx_power) != 0)
+		return -EINVAL;
+
+	mutex_lock(&mvm->mutex);
+
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
+	mvmsta->bt_reduced_txpower_dbg = false;
+	ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+					  reduced_tx_power);
+	if (!ret)
+		mvmsta->bt_reduced_txpower_dbg = true;
+
+	mutex_unlock(&mvm->mutex);
+
+	return ret ? : count;
+}
+
 static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
 				enum iwl_dbgfs_bf_mask param, int value)
 {
@@ -403,9 +457,9 @@ static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
 	mutex_lock(&mvm->mutex);
 	iwl_dbgfs_update_bf(vif, param, value);
 	if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
-		ret = iwl_mvm_disable_beacon_filter(mvm, vif);
+		ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
 	else
-		ret = iwl_mvm_enable_beacon_filter(mvm, vif);
+		ret = iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC);
 	mutex_unlock(&mvm->mutex);
 
 	return ret ?: count;
@@ -460,6 +514,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
+					   size_t count, loff_t *ppos)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mvm *mvm = mvmvif->mvm;
+	u8 value;
+	int ret;
+
+	ret = kstrtou8(buf, 0, &value);
+	if (ret)
+		return ret;
+	if (value > 1)
+		return -EINVAL;
+
+	mutex_lock(&mvm->mutex);
+	iwl_mvm_update_low_latency(mvm, vif, value);
+	mutex_unlock(&mvm->mutex);
+
+	return count;
+}
+
+static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
+					  char __user *user_buf,
+					  size_t count, loff_t *ppos)
+{
+	struct ieee80211_vif *vif = file->private_data;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	char buf[3];
+
+	buf[0] = mvmvif->low_latency ? '1' : '0';
+	buf[1] = '\n';
+	buf[2] = '\0';
+	return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
+}
+
 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
 	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
@@ -473,6 +562,8 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
 MVM_DEBUGFS_READ_FILE_OPS(mac_params);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
+MVM_DEBUGFS_WRITE_FILE_OPS(reduced_txp, 10);
 
 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
@@ -496,15 +587,18 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 		return;
 	}
 
-	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
+	if ((mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) &&
+	    iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
 	    ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
 	     (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
 	      mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)))
 		MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
 					 S_IRUSR);
 
-	MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
-				 S_IRUSR);
+	MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
+	MVM_DEBUGFS_ADD_FILE_VIF(reduced_txp, mvmvif->dbgfs_dir, S_IWUSR);
+	MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
+				 S_IRUSR | S_IWUSR);
 
 	if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
 	    mvmvif == mvm->bf_allowed_vif)
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 369d4c90e669..6853e5efe522 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -90,7 +90,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
 					 size_t count, loff_t *ppos)
 {
-	struct ieee80211_sta *sta;
+	struct iwl_mvm_sta *mvmsta;
 	int sta_id, drain, ret;
 
 	if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
@@ -105,13 +105,12 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
 
 	mutex_lock(&mvm->mutex);
 
-	sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
-					lockdep_is_held(&mvm->mutex));
-	if (IS_ERR_OR_NULL(sta))
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
+
+	if (!mvmsta)
 		ret = -ENOENT;
 	else
-		ret = iwl_mvm_drain_sta(mvm, (void *)sta->drv_priv, drain) ? :
-			count;
+		ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
 
 	mutex_unlock(&mvm->mutex);
 
@@ -251,7 +250,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
 	}
 
 	mutex_lock(&mvm->mutex);
-	ret = iwl_mvm_power_update_device_mode(mvm);
+	ret = iwl_mvm_power_update_device(mvm);
 	mutex_unlock(&mvm->mutex);
 
 	return ret ?: count;
@@ -600,6 +599,187 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
 	return count;
 }
 
+#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
+					    char __user *user_buf,
+					    size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	struct iwl_bcast_filter_cmd cmd;
+	const struct iwl_fw_bcast_filter *filter;
+	char *buf;
+	int bufsz = 1024;
+	int i, j, pos = 0;
+	ssize_t ret;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	mutex_lock(&mvm->mutex);
+	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
+		ADD_TEXT("None\n");
+		mutex_unlock(&mvm->mutex);
+		goto out;
+	}
+	mutex_unlock(&mvm->mutex);
+
+	for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
+		filter = &cmd.filters[i];
+
+		ADD_TEXT("Filter [%d]:\n", i);
+		ADD_TEXT("\tDiscard=%d\n", filter->discard);
+		ADD_TEXT("\tFrame Type: %s\n",
+			 filter->frame_type ? "IPv4" : "Generic");
+
+		for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
+			const struct iwl_fw_bcast_filter_attr *attr;
+
+			attr = &filter->attrs[j];
+			if (!attr->mask)
+				break;
+
+			ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
+				 j, attr->offset,
+				 attr->offset_type ? "IP End" :
+						     "Payload Start",
+				 be32_to_cpu(attr->mask),
+				 be32_to_cpu(attr->val),
+				 le16_to_cpu(attr->reserved1));
+		}
+	}
+out:
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
+					     size_t count, loff_t *ppos)
+{
+	int pos, next_pos;
+	struct iwl_fw_bcast_filter filter = {};
+	struct iwl_bcast_filter_cmd cmd;
+	u32 filter_id, attr_id, mask, value;
+	int err = 0;
+
+	if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
+		   &filter.frame_type, &pos) != 3)
+		return -EINVAL;
+
+	if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
+	    filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
+		return -EINVAL;
+
+	for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
+	     attr_id++) {
+		struct iwl_fw_bcast_filter_attr *attr =
+				&filter.attrs[attr_id];
+
+		if (pos >= count)
+			break;
+
+		if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
+			   &attr->offset, &attr->offset_type,
+			   &mask, &value, &next_pos) != 4)
+			return -EINVAL;
+
+		attr->mask = cpu_to_be32(mask);
+		attr->val = cpu_to_be32(value);
+		if (mask)
+			filter.num_attrs++;
+
+		pos += next_pos;
+	}
+
+	mutex_lock(&mvm->mutex);
+	memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
+	       &filter, sizeof(filter));
+
+	/* send updated bcast filtering configuration */
+	if (mvm->dbgfs_bcast_filtering.override &&
+	    iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
+		err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+					   sizeof(cmd), &cmd);
+	mutex_unlock(&mvm->mutex);
+
+	return err ?: count;
+}
+
+static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
+						 char __user *user_buf,
+						 size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	struct iwl_bcast_filter_cmd cmd;
+	char *buf;
+	int bufsz = 1024;
+	int i, pos = 0;
+	ssize_t ret;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	mutex_lock(&mvm->mutex);
+	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
+		ADD_TEXT("None\n");
+		mutex_unlock(&mvm->mutex);
+		goto out;
+	}
+	mutex_unlock(&mvm->mutex);
+
+	for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
+		const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
+
+		ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
+			 i, mac->default_discard, mac->attached_filters);
+	}
+out:
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
+						  char *buf, size_t count,
+						  loff_t *ppos)
+{
+	struct iwl_bcast_filter_cmd cmd;
+	struct iwl_fw_bcast_mac mac = {};
+	u32 mac_id, attached_filters;
+	int err = 0;
+
+	if (!mvm->bcast_filters)
+		return -ENOENT;
+
+	if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
+		   &attached_filters) != 3)
+		return -EINVAL;
+
+	if (mac_id >= ARRAY_SIZE(cmd.macs) ||
+	    mac.default_discard > 1 ||
+	    attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
+		return -EINVAL;
+
+	mac.attached_filters = cpu_to_le16(attached_filters);
+
+	mutex_lock(&mvm->mutex);
+	memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
+	       &mac, sizeof(mac));
+
+	/* send updated bcast filtering configuration */
+	if (mvm->dbgfs_bcast_filtering.override &&
+	    iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
+		err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+					   sizeof(cmd), &cmd);
+	mutex_unlock(&mvm->mutex);
+
+	return err ?: count;
+}
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
 				       size_t count, loff_t *ppos)
@@ -658,15 +838,74 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
 }
 #endif
 
+#define PRINT_MVM_REF(ref) do {					\
+	if (test_bit(ref, mvm->ref_bitmap))			\
+		pos += scnprintf(buf + pos, bufsz - pos,	\
+				 "\t(0x%lx) %s\n",		\
+				 BIT(ref), #ref);		\
+} while (0)
+
+static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	int pos = 0;
+	char buf[256];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
+			 mvm->ref_bitmap[0]);
+
+	PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
+	PRINT_MVM_REF(IWL_MVM_REF_SCAN);
+	PRINT_MVM_REF(IWL_MVM_REF_ROC);
+	PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
+	PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
+	PRINT_MVM_REF(IWL_MVM_REF_USER);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
+					 size_t count, loff_t *ppos)
+{
+	unsigned long value;
+	int ret;
+	bool taken;
+
+	ret = kstrtoul(buf, 10, &value);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&mvm->mutex);
+
+	taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
+	if (value == 1 && !taken)
+		iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
+	else if (value == 0 && taken)
+		iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
+	else
+		ret = -EINVAL;
+
+	mutex_unlock(&mvm->mutex);
+
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
 	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
 	_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
-#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do {			\
-		if (!debugfs_create_file(#name, mode, parent, mvm,	\
+#define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {	\
+		if (!debugfs_create_file(alias, mode, parent, mvm,	\
 					 &iwl_dbgfs_##name##_ops))	\
 			goto err;					\
 	} while (0)
+#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
+	MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
 
 /* Device wide debugfs entries */
 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
@@ -680,6 +919,12 @@ MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
+
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
+#endif
 
 #ifdef CONFIG_PM_SLEEP
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
@@ -687,6 +932,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
 
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 {
+	struct dentry *bcast_dir __maybe_unused;
 	char buf[100];
 
 	mvm->debugfs_dir = dbgfs_dir;
@@ -705,6 +951,27 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 	MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
 			     S_IWUSR | S_IRUSR);
+	MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
+
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
+		bcast_dir = debugfs_create_dir("bcast_filtering",
+					       mvm->debugfs_dir);
+		if (!bcast_dir)
+			goto err;
+
+		if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR,
+				bcast_dir,
+				&mvm->dbgfs_bcast_filtering.override))
+			goto err;
+
+		MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
+					   bcast_dir, S_IWUSR | S_IRUSR);
+		MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
+					   bcast_dir, S_IWUSR | S_IRUSR);
+	}
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 	MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
index 1b4e54d416b0..20b723d6270f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
@@ -70,37 +70,24 @@
 
 /**
  * enum iwl_bt_coex_flags - flags for BT_COEX command
- * @BT_CH_PRIMARY_EN:
- * @BT_CH_SECONDARY_EN:
- * @BT_NOTIF_COEX_OFF:
  * @BT_COEX_MODE_POS:
  * @BT_COEX_MODE_MSK:
  * @BT_COEX_DISABLE:
  * @BT_COEX_2W:
  * @BT_COEX_3W:
  * @BT_COEX_NW:
- * @BT_USE_DEFAULTS:
- * @BT_SYNC_2_BT_DISABLE:
- * @BT_COEX_CORUNNING_TBL_EN:
+ * @BT_COEX_SYNC2SCO:
  *
  * The COEX_MODE must be set for each command. Even if it is not changed.
  */
 enum iwl_bt_coex_flags {
-	BT_CH_PRIMARY_EN		= BIT(0),
-	BT_CH_SECONDARY_EN		= BIT(1),
-	BT_NOTIF_COEX_OFF		= BIT(2),
 	BT_COEX_MODE_POS		= 3,
 	BT_COEX_MODE_MSK		= BITS(3) << BT_COEX_MODE_POS,
 	BT_COEX_DISABLE			= 0x0 << BT_COEX_MODE_POS,
 	BT_COEX_2W			= 0x1 << BT_COEX_MODE_POS,
 	BT_COEX_3W			= 0x2 << BT_COEX_MODE_POS,
 	BT_COEX_NW			= 0x3 << BT_COEX_MODE_POS,
-	BT_USE_DEFAULTS			= BIT(6),
-	BT_SYNC_2_BT_DISABLE		= BIT(7),
-	BT_COEX_CORUNNING_TBL_EN	= BIT(8),
-	BT_COEX_MPLUT_TBL_EN		= BIT(9),
-	/* Bit 10 is reserved */
-	BT_COEX_WF_PRIO_BOOST_CHECK_EN	= BIT(11),
+	BT_COEX_SYNC2SCO		= BIT(7),
 };
 
 /*
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 8415ff312d0e..521997669c99 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -231,8 +231,12 @@ enum iwl_wowlan_wakeup_filters {
 	IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT		= BIT(8),
 	IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS		= BIT(9),
 	IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE	= BIT(10),
-	/* BIT(11) reserved */
+	IWL_WOWLAN_WAKEUP_REMOTE_TCP_EXTERNAL		= BIT(11),
 	IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET		= BIT(12),
+	IWL_WOWLAN_WAKEUP_IOAC_MAGIC_PACKET		= BIT(13),
+	IWL_WOWLAN_WAKEUP_HOST_TIMER			= BIT(14),
+	IWL_WOWLAN_WAKEUP_RX_FRAME			= BIT(15),
+	IWL_WOWLAN_WAKEUP_BCN_FILTERING			= BIT(16),
 }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
 
 struct iwl_wowlan_config_cmd {
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 884c08725308..cbbcd8e284e4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -301,54 +301,65 @@ struct iwl_beacon_filter_cmd {
 
 /* Beacon filtering and beacon abort */
 #define IWL_BF_ENERGY_DELTA_DEFAULT 5
+#define IWL_BF_ENERGY_DELTA_D0I3 20
 #define IWL_BF_ENERGY_DELTA_MAX 255
 #define IWL_BF_ENERGY_DELTA_MIN 0
 
 #define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1
+#define IWL_BF_ROAMING_ENERGY_DELTA_D0I3 20
 #define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255
 #define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0
 
 #define IWL_BF_ROAMING_STATE_DEFAULT 72
+#define IWL_BF_ROAMING_STATE_D0I3 72
 #define IWL_BF_ROAMING_STATE_MAX 255
 #define IWL_BF_ROAMING_STATE_MIN 0
 
 #define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
+#define IWL_BF_TEMP_THRESHOLD_D0I3 112
 #define IWL_BF_TEMP_THRESHOLD_MAX 255
 #define IWL_BF_TEMP_THRESHOLD_MIN 0
 
 #define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
+#define IWL_BF_TEMP_FAST_FILTER_D0I3 1
 #define IWL_BF_TEMP_FAST_FILTER_MAX 255
 #define IWL_BF_TEMP_FAST_FILTER_MIN 0
 
 #define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
+#define IWL_BF_TEMP_SLOW_FILTER_D0I3 5
 #define IWL_BF_TEMP_SLOW_FILTER_MAX 255
 #define IWL_BF_TEMP_SLOW_FILTER_MIN 0
 
 #define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
 
 #define IWL_BF_DEBUG_FLAG_DEFAULT 0
+#define IWL_BF_DEBUG_FLAG_D0I3 0
 
 #define IWL_BF_ESCAPE_TIMER_DEFAULT 50
+#define IWL_BF_ESCAPE_TIMER_D0I3 1024
 #define IWL_BF_ESCAPE_TIMER_MAX 1024
 #define IWL_BF_ESCAPE_TIMER_MIN 0
 
 #define IWL_BA_ESCAPE_TIMER_DEFAULT 6
+#define IWL_BA_ESCAPE_TIMER_D0I3 6
 #define IWL_BA_ESCAPE_TIMER_D3 9
 #define IWL_BA_ESCAPE_TIMER_MAX 1024
 #define IWL_BA_ESCAPE_TIMER_MIN 0
 
 #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
 
-#define IWL_BF_CMD_CONFIG_DEFAULTS					     \
-	.bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT),	     \
-	.bf_roaming_energy_delta =					     \
-		cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT),	     \
-	.bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT),	     \
-	.bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT),     \
-	.bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \
-	.bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \
-	.bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT),	     \
-	.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),	     \
-	.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
+#define IWL_BF_CMD_CONFIG(mode)					     \
+	.bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA ## mode),	      \
+	.bf_roaming_energy_delta =					      \
+		cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA ## mode),	      \
+	.bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE ## mode),	      \
+	.bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD ## mode),      \
+	.bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER ## mode),  \
+	.bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER ## mode),  \
+	.bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG ## mode),	      \
+	.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER ## mode),	      \
+	.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER ## mode)
 
+#define IWL_BF_CMD_CONFIG_DEFAULTS IWL_BF_CMD_CONFIG(_DEFAULT)
+#define IWL_BF_CMD_CONFIG_D0I3 IWL_BF_CMD_CONFIG(_D0I3)
 #endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
index 1b60fdff6a56..d63647867262 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
@@ -199,11 +199,14 @@ enum iwl_sta_modify_flag {
  * @STA_SLEEP_STATE_AWAKE:
  * @STA_SLEEP_STATE_PS_POLL:
  * @STA_SLEEP_STATE_UAPSD:
+ * @STA_SLEEP_STATE_MOREDATA: set more-data bit on
+ *	(last) released frame
  */
 enum iwl_sta_sleep_flag {
-	STA_SLEEP_STATE_AWAKE	= 0,
-	STA_SLEEP_STATE_PS_POLL	= BIT(0),
-	STA_SLEEP_STATE_UAPSD	= BIT(1),
+	STA_SLEEP_STATE_AWAKE		= 0,
+	STA_SLEEP_STATE_PS_POLL		= BIT(0),
+	STA_SLEEP_STATE_UAPSD		= BIT(1),
+	STA_SLEEP_STATE_MOREDATA	= BIT(2),
 };
 
 /* STA ID and color bits definitions */
@@ -318,13 +321,15 @@ struct iwl_mvm_add_sta_cmd_v5 {
 } __packed; /* ADD_STA_CMD_API_S_VER_5 */
 
 /**
- * struct iwl_mvm_add_sta_cmd_v6 - Add / modify a station
- * VER_6 of this command is quite similar to VER_5 except
+ * struct iwl_mvm_add_sta_cmd_v7 - Add / modify a station
+ * VER_7 of this command is quite similar to VER_5 except
  * exclusion of all fields related to the security key installation.
+ * It only differs from VER_6 by the "awake_acs" field that is
+ * reserved and ignored in VER_6.
  */
-struct iwl_mvm_add_sta_cmd_v6 {
+struct iwl_mvm_add_sta_cmd_v7 {
 	u8 add_modify;
-	u8 reserved1;
+	u8 awake_acs;
 	__le16 tid_disable_tx;
 	__le32 mac_id_n_color;
 	u8 addr[ETH_ALEN];	/* _STA_ID_MODIFY_INFO_API_S_VER_1 */
@@ -342,7 +347,7 @@ struct iwl_mvm_add_sta_cmd_v6 {
 	__le16 assoc_id;
 	__le16 beamform_flags;
 	__le32 tfd_queue_msk;
-} __packed; /* ADD_STA_CMD_API_S_VER_6 */
+} __packed; /* ADD_STA_CMD_API_S_VER_7 */
 
 /**
  * struct iwl_mvm_add_sta_key_cmd - add/modify sta key
@@ -432,5 +437,15 @@ struct iwl_mvm_wep_key_cmd {
 	struct iwl_mvm_wep_key wep_key[0];
 } __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */
 
+/**
+ * struct iwl_mvm_eosp_notification - EOSP notification from firmware
+ * @remain_frame_count: # of frames remaining, non-zero if SP was cut
+ *	short by GO absence
+ * @sta_id: station ID
+ */
+struct iwl_mvm_eosp_notification {
+	__le32 remain_frame_count;
+	__le32 sta_id;
+} __packed; /* UAPSD_EOSP_NTFY_API_S_VER_1 */
 
 #endif /* __fw_api_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 989d7dbdca6c..a7c88f1402e9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -163,6 +163,7 @@ enum {
 	TX_ANT_CONFIGURATION_CMD = 0x98,
 	BT_CONFIG = 0x9b,
 	STATISTICS_NOTIFICATION = 0x9d,
+	EOSP_NOTIFICATION = 0x9e,
 	REDUCE_TX_POWER_CMD = 0x9f,
 
 	/* RF-KILL commands and notifications */
@@ -190,6 +191,7 @@ enum {
 	REPLY_DEBUG_CMD = 0xf0,
 	DEBUG_LOG_MSG = 0xf7,
 
+	BCAST_FILTER_CMD = 0xcf,
 	MCAST_FILTER_CMD = 0xd0,
 
 	/* D3 commands/notifications */
@@ -197,6 +199,7 @@ enum {
 	PROT_OFFLOAD_CONFIG_CMD = 0xd4,
 	OFFLOADS_QUERY_CMD = 0xd5,
 	REMOTE_WAKE_CONFIG_CMD = 0xd6,
+	D0I3_END_CMD = 0xed,
 
 	/* for WoWLAN in particular */
 	WOWLAN_PATTERNS = 0xe0,
@@ -303,6 +306,7 @@ struct iwl_phy_cfg_cmd {
 #define PHY_CFG_RX_CHAIN_B	BIT(13)
 #define PHY_CFG_RX_CHAIN_C	BIT(14)
 
+#define NVM_MAX_NUM_SECTIONS	11
 
 /* Target of the NVM_ACCESS_CMD */
 enum {
@@ -313,14 +317,9 @@ enum {
 
 /* Section types for NVM_ACCESS_CMD */
 enum {
-	NVM_SECTION_TYPE_HW = 0,
-	NVM_SECTION_TYPE_SW,
-	NVM_SECTION_TYPE_PAPD,
-	NVM_SECTION_TYPE_BT,
-	NVM_SECTION_TYPE_CALIBRATION,
-	NVM_SECTION_TYPE_PRODUCTION,
-	NVM_SECTION_TYPE_POST_FCS_CALIB,
-	NVM_NUM_OF_SECTIONS,
+	NVM_SECTION_TYPE_SW = 1,
+	NVM_SECTION_TYPE_CALIBRATION = 4,
+	NVM_SECTION_TYPE_PRODUCTION = 5,
 };
 
 /**
@@ -412,6 +411,35 @@ struct mvm_alive_resp {
 	__le32 scd_base_ptr;		/* SRAM address for SCD */
 } __packed; /* ALIVE_RES_API_S_VER_1 */
 
+struct mvm_alive_resp_ver2 {
+	__le16 status;
+	__le16 flags;
+	u8 ucode_minor;
+	u8 ucode_major;
+	__le16 id;
+	u8 api_minor;
+	u8 api_major;
+	u8 ver_subtype;
+	u8 ver_type;
+	u8 mac;
+	u8 opt;
+	__le16 reserved2;
+	__le32 timestamp;
+	__le32 error_event_table_ptr;	/* SRAM address for error log */
+	__le32 log_event_table_ptr;	/* SRAM address for LMAC event log */
+	__le32 cpu_register_ptr;
+	__le32 dbgm_config_ptr;
+	__le32 alive_counter_ptr;
+	__le32 scd_base_ptr;		/* SRAM address for SCD */
+	__le32 st_fwrd_addr;		/* pointer to Store and forward */
+	__le32 st_fwrd_size;
+	u8 umac_minor;			/* UMAC version: minor */
+	u8 umac_major;			/* UMAC version: major */
+	__le16 umac_id;			/* UMAC version: id */
+	__le32 error_info_addr;		/* SRAM address for UMAC error log */
+	__le32 dbg_print_buff_addr;
+} __packed; /* ALIVE_RES_API_S_VER_2 */
+
 /* Error response/notification */
 enum {
 	FW_ERR_UNKNOWN_CMD = 0x0,
@@ -1159,6 +1187,90 @@ struct iwl_mcast_filter_cmd {
 	u8 addr_list[0];
 } __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */
 
+#define MAX_BCAST_FILTERS 8
+#define MAX_BCAST_FILTER_ATTRS 2
+
+/**
+ * enum iwl_mvm_bcast_filter_attr_offset - written by fw for each Rx packet
+ * @BCAST_FILTER_OFFSET_PAYLOAD_START: offset is from payload start.
+ * @BCAST_FILTER_OFFSET_IP_END: offset is from ip header end (i.e.
+ *	start of ip payload).
+ */
+enum iwl_mvm_bcast_filter_attr_offset {
+	BCAST_FILTER_OFFSET_PAYLOAD_START = 0,
+	BCAST_FILTER_OFFSET_IP_END = 1,
+};
+
+/**
+ * struct iwl_fw_bcast_filter_attr - broadcast filter attribute
+ * @offset_type:	&enum iwl_mvm_bcast_filter_attr_offset.
+ * @offset:	starting offset of this pattern.
+ * @val:		value to match - big endian (MSB is the first
+ *		byte to match from offset pos).
+ * @mask:	mask to match (big endian).
+ */
+struct iwl_fw_bcast_filter_attr {
+	u8 offset_type;
+	u8 offset;
+	__le16 reserved1;
+	__be32 val;
+	__be32 mask;
+} __packed; /* BCAST_FILTER_ATT_S_VER_1 */
+
+/**
+ * enum iwl_mvm_bcast_filter_frame_type - filter frame type
+ * @BCAST_FILTER_FRAME_TYPE_ALL: consider all frames.
+ * @BCAST_FILTER_FRAME_TYPE_IPV4: consider only ipv4 frames
+ */
+enum iwl_mvm_bcast_filter_frame_type {
+	BCAST_FILTER_FRAME_TYPE_ALL = 0,
+	BCAST_FILTER_FRAME_TYPE_IPV4 = 1,
+};
+
+/**
+ * struct iwl_fw_bcast_filter - broadcast filter
+ * @discard: discard frame (1) or let it pass (0).
+ * @frame_type: &enum iwl_mvm_bcast_filter_frame_type.
+ * @num_attrs: number of valid attributes in this filter.
+ * @attrs: attributes of this filter. a filter is considered matched
+ *	only when all its attributes are matched (i.e. AND relationship)
+ */
+struct iwl_fw_bcast_filter {
+	u8 discard;
+	u8 frame_type;
+	u8 num_attrs;
+	u8 reserved1;
+	struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS];
+} __packed; /* BCAST_FILTER_S_VER_1 */
+
+/**
+ * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration.
+ * @default_discard: default action for this mac (discard (1) / pass (0)).
+ * @attached_filters: bitmap of relevant filters for this mac.
+ */
+struct iwl_fw_bcast_mac {
+	u8 default_discard;
+	u8 reserved1;
+	__le16 attached_filters;
+} __packed; /* BCAST_MAC_CONTEXT_S_VER_1 */
+
+/**
+ * struct iwl_bcast_filter_cmd - broadcast filtering configuration
+ * @disable: enable (0) / disable (1)
+ * @max_bcast_filters: max number of filters (MAX_BCAST_FILTERS)
+ * @max_macs: max number of macs (NUM_MAC_INDEX_DRIVER)
+ * @filters: broadcast filters
+ * @macs: broadcast filtering configuration per-mac
+ */
+struct iwl_bcast_filter_cmd {
+	u8 disable;
+	u8 max_bcast_filters;
+	u8 max_macs;
+	u8 reserved1;
+	struct iwl_fw_bcast_filter filters[MAX_BCAST_FILTERS];
+	struct iwl_fw_bcast_mac macs[NUM_MAC_INDEX_DRIVER];
+} __packed; /* BCAST_FILTERING_HCMD_API_S_VER_1 */
+
 struct mvm_statistics_dbg {
 	__le32 burst_check;
 	__le32 burst_count;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index c03d39541f9e..bae75b308fc0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -110,18 +110,46 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
 		container_of(notif_wait, struct iwl_mvm, notif_wait);
 	struct iwl_mvm_alive_data *alive_data = data;
 	struct mvm_alive_resp *palive;
-
-	palive = (void *)pkt->data;
-
-	mvm->error_event_table = le32_to_cpu(palive->error_event_table_ptr);
-	mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
-	alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
-
-	alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
-	IWL_DEBUG_FW(mvm,
-		     "Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
-		     le16_to_cpu(palive->status), palive->ver_type,
-		     palive->ver_subtype, palive->flags);
+	struct mvm_alive_resp_ver2 *palive2;
+
+	if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
+		palive = (void *)pkt->data;
+
+		mvm->support_umac_log = false;
+		mvm->error_event_table =
+			le32_to_cpu(palive->error_event_table_ptr);
+		mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
+		alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
+
+		alive_data->valid = le16_to_cpu(palive->status) ==
+				    IWL_ALIVE_STATUS_OK;
+		IWL_DEBUG_FW(mvm,
+			     "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
+			     le16_to_cpu(palive->status), palive->ver_type,
+			     palive->ver_subtype, palive->flags);
+	} else {
+		palive2 = (void *)pkt->data;
+
+		mvm->support_umac_log = true;
+		mvm->error_event_table =
+			le32_to_cpu(palive2->error_event_table_ptr);
+		mvm->log_event_table =
+			le32_to_cpu(palive2->log_event_table_ptr);
+		alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr);
+		mvm->umac_error_event_table =
+			le32_to_cpu(palive2->error_info_addr);
+
+		alive_data->valid = le16_to_cpu(palive2->status) ==
+				    IWL_ALIVE_STATUS_OK;
+		IWL_DEBUG_FW(mvm,
+			     "Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
+			     le16_to_cpu(palive2->status), palive2->ver_type,
+			     palive2->ver_subtype, palive2->flags);
+
+		IWL_DEBUG_FW(mvm,
+			     "UMAC version: Major - 0x%x, Minor - 0x%x\n",
+			     palive2->umac_major, palive2->umac_minor);
+	}
 
 	return true;
 }
@@ -439,10 +467,23 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
 			goto error;
 	}
 
-	ret = iwl_mvm_power_update_device_mode(mvm);
+	/* Initialize tx backoffs to the minimal possible */
+	iwl_mvm_tt_tx_backoff(mvm, 0);
+
+	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
+		ret = iwl_power_legacy_set_cam_mode(mvm);
+		if (ret)
+			goto error;
+	}
+
+	ret = iwl_mvm_power_update_device(mvm);
 	if (ret)
 		goto error;
 
+	/* allow FW/transport low power modes if not during restart */
+	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+		iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
+
 	IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
 	return 0;
  error:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index ba723d50939a..5c21aabb40cb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -90,6 +90,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
 {
 	struct iwl_mvm_mac_iface_iterator_data *data = _data;
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	u16 min_bi;
 
 	/* Skip the interface for which we are trying to assign a tsf_id  */
 	if (vif == data->vif)
@@ -114,42 +115,57 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
 	switch (data->vif->type) {
 	case NL80211_IFTYPE_STATION:
 		/*
-		 * The new interface is client, so if the existing one
-		 * we're iterating is an AP, and both interfaces have the
-		 * same beacon interval, the same TSF should be used to
-		 * avoid drift between the new client and existing AP,
-		 * the existing AP will get drift updates from the new
-		 * client context in this case
+		 * The new interface is a client, so if the one we're iterating
+		 * is an AP, and the beacon interval of the AP is a multiple or
+		 * divisor of the beacon interval of the client, the same TSF
+		 * should be used to avoid drift between the new client and
+		 * existing AP. The existing AP will get drift updates from the
+		 * new client context in this case.
 		 */
-		if (vif->type == NL80211_IFTYPE_AP) {
-			if (data->preferred_tsf == NUM_TSF_IDS &&
-			    test_bit(mvmvif->tsf_id, data->available_tsf_ids) &&
-			    (vif->bss_conf.beacon_int ==
-			     data->vif->bss_conf.beacon_int)) {
-				data->preferred_tsf = mvmvif->tsf_id;
-				return;
-			}
+		if (vif->type != NL80211_IFTYPE_AP ||
+		    data->preferred_tsf != NUM_TSF_IDS ||
+		    !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
+			break;
+
+		min_bi = min(data->vif->bss_conf.beacon_int,
+			     vif->bss_conf.beacon_int);
+
+		if (!min_bi)
+			break;
+
+		if ((data->vif->bss_conf.beacon_int -
+		     vif->bss_conf.beacon_int) % min_bi == 0) {
+			data->preferred_tsf = mvmvif->tsf_id;
+			return;
 		}
 		break;
+
 	case NL80211_IFTYPE_AP:
 		/*
-		 * The new interface is AP/GO, so in case both interfaces
-		 * have the same beacon interval, it should get drift
-		 * updates from an existing client or use the same
-		 * TSF as an existing GO. There's no drift between
-		 * TSFs internally but if they used different TSFs
-		 * then a new client MAC could update one of them
-		 * and cause drift that way.
+		 * The new interface is AP/GO, so if its beacon interval is a
+		 * multiple or a divisor of the beacon interval of an existing
+		 * interface, it should get drift updates from an existing
+		 * client or use the same TSF as an existing GO. There's no
+		 * drift between TSFs internally but if they used different
+		 * TSFs then a new client MAC could update one of them and
+		 * cause drift that way.
 		 */
-		if (vif->type == NL80211_IFTYPE_STATION ||
-		    vif->type == NL80211_IFTYPE_AP) {
-			if (data->preferred_tsf == NUM_TSF_IDS &&
-			    test_bit(mvmvif->tsf_id, data->available_tsf_ids) &&
-			    (vif->bss_conf.beacon_int ==
-			     data->vif->bss_conf.beacon_int)) {
-				data->preferred_tsf = mvmvif->tsf_id;
-				return;
-			}
+		if ((vif->type != NL80211_IFTYPE_AP &&
+		     vif->type != NL80211_IFTYPE_STATION) ||
+		    data->preferred_tsf != NUM_TSF_IDS ||
+		    !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
+			break;
+
+		min_bi = min(data->vif->bss_conf.beacon_int,
+			     vif->bss_conf.beacon_int);
+
+		if (!min_bi)
+			break;
+
+		if ((data->vif->bss_conf.beacon_int -
+		     vif->bss_conf.beacon_int) % min_bi == 0) {
+			data->preferred_tsf = mvmvif->tsf_id;
+			return;
 		}
 		break;
 	default:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index c35b8661b395..a49d1ef13f42 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -66,6 +66,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
+#include <linux/if_arp.h>
 #include <net/mac80211.h>
 #include <net/tcp.h>
 
@@ -128,6 +129,117 @@ static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = {
 };
 #endif
 
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+/*
+ * Use the reserved field to indicate magic values.
+ * these values will only be used internally by the driver,
+ * and won't make it to the fw (reserved will be 0).
+ * BC_FILTER_MAGIC_IP - configure the val of this attribute to
+ *	be the vif's ip address. in case there is not a single
+ *	ip address (0, or more than 1), this attribute will
+ *	be skipped.
+ * BC_FILTER_MAGIC_MAC - set the val of this attribute to
+ *	the LSB bytes of the vif's mac address
+ */
+enum {
+	BC_FILTER_MAGIC_NONE = 0,
+	BC_FILTER_MAGIC_IP,
+	BC_FILTER_MAGIC_MAC,
+};
+
+static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = {
+	{
+		/* arp */
+		.discard = 0,
+		.frame_type = BCAST_FILTER_FRAME_TYPE_ALL,
+		.attrs = {
+			{
+				/* frame type - arp, hw type - ethernet */
+				.offset_type =
+					BCAST_FILTER_OFFSET_PAYLOAD_START,
+				.offset = sizeof(rfc1042_header),
+				.val = cpu_to_be32(0x08060001),
+				.mask = cpu_to_be32(0xffffffff),
+			},
+			{
+				/* arp dest ip */
+				.offset_type =
+					BCAST_FILTER_OFFSET_PAYLOAD_START,
+				.offset = sizeof(rfc1042_header) + 2 +
+					  sizeof(struct arphdr) +
+					  ETH_ALEN + sizeof(__be32) +
+					  ETH_ALEN,
+				.mask = cpu_to_be32(0xffffffff),
+				/* mark it as special field */
+				.reserved1 = cpu_to_le16(BC_FILTER_MAGIC_IP),
+			},
+		},
+	},
+	{
+		/* dhcp offer bcast */
+		.discard = 0,
+		.frame_type = BCAST_FILTER_FRAME_TYPE_IPV4,
+		.attrs = {
+			{
+				/* udp dest port - 68 (bootp client)*/
+				.offset_type = BCAST_FILTER_OFFSET_IP_END,
+				.offset = offsetof(struct udphdr, dest),
+				.val = cpu_to_be32(0x00440000),
+				.mask = cpu_to_be32(0xffff0000),
+			},
+			{
+				/* dhcp - lsb bytes of client hw address */
+				.offset_type = BCAST_FILTER_OFFSET_IP_END,
+				.offset = 38,
+				.mask = cpu_to_be32(0xffffffff),
+				/* mark it as special field */
+				.reserved1 = cpu_to_le16(BC_FILTER_MAGIC_MAC),
+			},
+		},
+	},
+	/* last filter must be empty */
+	{},
+};
+#endif
+
+void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
+{
+	if (!mvm->trans->cfg->d0i3)
+		return;
+
+	IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
+	WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap));
+	iwl_trans_ref(mvm->trans);
+}
+
+void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
+{
+	if (!mvm->trans->cfg->d0i3)
+		return;
+
+	IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
+	WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap));
+	iwl_trans_unref(mvm->trans);
+}
+
+static void
+iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref)
+{
+	int i;
+
+	if (!mvm->trans->cfg->d0i3)
+		return;
+
+	for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) {
+		if (ref == i)
+			continue;
+
+		IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i);
+		clear_bit(i, mvm->ref_bitmap);
+		iwl_trans_unref(mvm->trans);
+	}
+}
+
 static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
 {
 	int i;
@@ -203,6 +315,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
 				       REGULATORY_DISABLE_BEACON_HINTS;
 
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
+		hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+
 	hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
 	hw->wiphy->n_iface_combinations =
 		ARRAY_SIZE(iwl_mvm_iface_combinations);
@@ -289,6 +404,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	}
 #endif
 
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+	/* assign default bcast filtering configuration */
+	mvm->bcast_filters = iwl_mvm_default_bcast_filters;
+#endif
+
 	ret = iwl_mvm_leds_init(mvm);
 	if (ret)
 		return ret;
@@ -305,6 +425,9 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
 			   struct sk_buff *skb)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct ieee80211_sta *sta = control->sta;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (void *)skb->data;
 
 	if (iwl_mvm_is_radio_killed(mvm)) {
 		IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
@@ -315,8 +438,16 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
 	    !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
 		goto drop;
 
-	if (control->sta) {
-		if (iwl_mvm_tx_skb(mvm, skb, control->sta))
+	/* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
+	if (unlikely(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER &&
+		     ieee80211_is_mgmt(hdr->frame_control) &&
+		     !ieee80211_is_deauth(hdr->frame_control) &&
+		     !ieee80211_is_disassoc(hdr->frame_control) &&
+		     !ieee80211_is_action(hdr->frame_control)))
+		sta = NULL;
+
+	if (sta) {
+		if (iwl_mvm_tx_skb(mvm, skb, sta))
 			goto drop;
 		return;
 	}
@@ -434,6 +565,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 		iwl_mvm_cleanup_iterator, mvm);
 
 	mvm->p2p_device_vif = NULL;
+	mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
 
 	iwl_mvm_reset_phy_ctxts(mvm);
 	memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
@@ -441,6 +573,10 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 
 	ieee80211_wake_queues(mvm->hw);
 
+	/* cleanup all stale references (scan, roc), but keep the
+	 * ucode_down ref until reconfig is complete */
+	iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
+
 	mvm->vif_count = 0;
 	mvm->rx_ba_sessions = 0;
 }
@@ -475,6 +611,9 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
 		IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
 			ret);
 
+	/* allow transport/FW low power modes */
+	iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
+
 	mutex_unlock(&mvm->mutex);
 }
 
@@ -482,9 +621,14 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
+	flush_work(&mvm->d0i3_exit_work);
 	flush_work(&mvm->async_handlers_wk);
 
 	mutex_lock(&mvm->mutex);
+
+	/* disallow low power states when the FW is down */
+	iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
+
 	/* async_handlers_wk is now blocked */
 
 	/*
@@ -510,14 +654,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
 	cancel_work_sync(&mvm->async_handlers_wk);
 }
 
-static void iwl_mvm_power_update_iterator(void *data, u8 *mac,
-					  struct ieee80211_vif *vif)
-{
-	struct iwl_mvm *mvm = data;
-
-	iwl_mvm_power_update_mode(mvm, vif);
-}
-
 static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
 {
 	u16 i;
@@ -585,7 +721,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 	    vif->type == NL80211_IFTYPE_ADHOC) {
 		u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
 		ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta,
-					       qmask);
+					       qmask,
+					       ieee80211_vif_type_p2p(vif));
 		if (ret) {
 			IWL_ERR(mvm, "Failed to allocate bcast sta\n");
 			goto out_release;
@@ -599,10 +736,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 	if (ret)
 		goto out_release;
 
-	iwl_mvm_power_disable(mvm, vif);
+	ret = iwl_mvm_power_update_mac(mvm, vif);
+	if (ret)
+		goto out_release;
 
 	/* beacon filtering */
-	ret = iwl_mvm_disable_beacon_filter(mvm, vif);
+	ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
 	if (ret)
 		goto out_remove_mac;
 
@@ -661,11 +800,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 	if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
 		mvm->vif_count--;
 
-	/* TODO: remove this when legacy PM will be discarded */
-	ieee80211_iterate_active_interfaces(
-		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-		iwl_mvm_power_update_iterator, mvm);
-
 	iwl_mvm_mac_ctxt_release(mvm, vif);
  out_unlock:
 	mutex_unlock(&mvm->mutex);
@@ -754,11 +888,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
 	if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
 		mvm->vif_count--;
 
-	/* TODO: remove this when legacy PM will be discarded */
-	ieee80211_iterate_active_interfaces(
-		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-		iwl_mvm_power_update_iterator, mvm);
-
+	iwl_mvm_power_update_mac(mvm, vif);
 	iwl_mvm_mac_ctxt_remove(mvm, vif);
 
 out_release:
@@ -876,6 +1006,156 @@ out:
 	*total_flags = 0;
 }
 
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+struct iwl_bcast_iter_data {
+	struct iwl_mvm *mvm;
+	struct iwl_bcast_filter_cmd *cmd;
+	u8 current_filter;
+};
+
+static void
+iwl_mvm_set_bcast_filter(struct ieee80211_vif *vif,
+			 const struct iwl_fw_bcast_filter *in_filter,
+			 struct iwl_fw_bcast_filter *out_filter)
+{
+	struct iwl_fw_bcast_filter_attr *attr;
+	int i;
+
+	memcpy(out_filter, in_filter, sizeof(*out_filter));
+
+	for (i = 0; i < ARRAY_SIZE(out_filter->attrs); i++) {
+		attr = &out_filter->attrs[i];
+
+		if (!attr->mask)
+			break;
+
+		switch (attr->reserved1) {
+		case cpu_to_le16(BC_FILTER_MAGIC_IP):
+			if (vif->bss_conf.arp_addr_cnt != 1) {
+				attr->mask = 0;
+				continue;
+			}
+
+			attr->val = vif->bss_conf.arp_addr_list[0];
+			break;
+		case cpu_to_le16(BC_FILTER_MAGIC_MAC):
+			attr->val = *(__be32 *)&vif->addr[2];
+			break;
+		default:
+			break;
+		}
+		attr->reserved1 = 0;
+		out_filter->num_attrs++;
+	}
+}
+
+static void iwl_mvm_bcast_filter_iterator(void *_data, u8 *mac,
+					  struct ieee80211_vif *vif)
+{
+	struct iwl_bcast_iter_data *data = _data;
+	struct iwl_mvm *mvm = data->mvm;
+	struct iwl_bcast_filter_cmd *cmd = data->cmd;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_fw_bcast_mac *bcast_mac;
+	int i;
+
+	if (WARN_ON(mvmvif->id >= ARRAY_SIZE(cmd->macs)))
+		return;
+
+	bcast_mac = &cmd->macs[mvmvif->id];
+
+	/* enable filtering only for associated stations */
+	if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc)
+		return;
+
+	bcast_mac->default_discard = 1;
+
+	/* copy all configured filters */
+	for (i = 0; mvm->bcast_filters[i].attrs[0].mask; i++) {
+		/*
+		 * Make sure we don't exceed our filters limit.
+		 * if there is still a valid filter to be configured,
+		 * be on the safe side and just allow bcast for this mac.
+		 */
+		if (WARN_ON_ONCE(data->current_filter >=
+				 ARRAY_SIZE(cmd->filters))) {
+			bcast_mac->default_discard = 0;
+			bcast_mac->attached_filters = 0;
+			break;
+		}
+
+		iwl_mvm_set_bcast_filter(vif,
+					 &mvm->bcast_filters[i],
+					 &cmd->filters[data->current_filter]);
+
+		/* skip current filter if it contains no attributes */
+		if (!cmd->filters[data->current_filter].num_attrs)
+			continue;
+
+		/* attach the filter to current mac */
+		bcast_mac->attached_filters |=
+				cpu_to_le16(BIT(data->current_filter));
+
+		data->current_filter++;
+	}
+}
+
+bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
+				    struct iwl_bcast_filter_cmd *cmd)
+{
+	struct iwl_bcast_iter_data iter_data = {
+		.mvm = mvm,
+		.cmd = cmd,
+	};
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters);
+	cmd->max_macs = ARRAY_SIZE(cmd->macs);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	/* use debugfs filters/macs if override is configured */
+	if (mvm->dbgfs_bcast_filtering.override) {
+		memcpy(cmd->filters, &mvm->dbgfs_bcast_filtering.cmd.filters,
+		       sizeof(cmd->filters));
+		memcpy(cmd->macs, &mvm->dbgfs_bcast_filtering.cmd.macs,
+		       sizeof(cmd->macs));
+		return true;
+	}
+#endif
+
+	/* if no filters are configured, do nothing */
+	if (!mvm->bcast_filters)
+		return false;
+
+	/* configure and attach these filters for each associated sta vif */
+	ieee80211_iterate_active_interfaces(
+		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+		iwl_mvm_bcast_filter_iterator, &iter_data);
+
+	return true;
+}
+static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
+					  struct ieee80211_vif *vif)
+{
+	struct iwl_bcast_filter_cmd cmd;
+
+	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING))
+		return 0;
+
+	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
+		return 0;
+
+	return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+				    sizeof(cmd), &cmd);
+}
+#else
+static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
+						 struct ieee80211_vif *vif)
+{
+	return 0;
+}
+#endif
+
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 					     struct ieee80211_vif *vif,
 					     struct ieee80211_bss_conf *bss_conf,
@@ -928,6 +1208,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 
 			iwl_mvm_sf_update(mvm, vif, false);
 			iwl_mvm_power_vif_assoc(mvm, vif);
+			if (vif->p2p)
+				iwl_mvm_ref(mvm, IWL_MVM_REF_P2P_CLIENT);
 		} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
 			/*
 			 * If update fails - SF might be running in associated
@@ -940,27 +1222,25 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 			ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
 			if (ret)
 				IWL_ERR(mvm, "failed to remove AP station\n");
+
+			if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
+				mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
 			mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
 			/* remove quota for this interface */
 			ret = iwl_mvm_update_quotas(mvm, NULL);
 			if (ret)
 				IWL_ERR(mvm, "failed to update quotas\n");
+
+			if (vif->p2p)
+				iwl_mvm_unref(mvm, IWL_MVM_REF_P2P_CLIENT);
 		}
 
 		iwl_mvm_recalc_multicast(mvm);
+		iwl_mvm_configure_bcast_filter(mvm, vif);
 
 		/* reset rssi values */
 		mvmvif->bf_data.ave_beacon_signal = 0;
 
-		if (!(mvm->fw->ucode_capa.flags &
-					IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
-			/* Workaround for FW bug, otherwise FW disables device
-			 * power save upon disassociation
-			 */
-			ret = iwl_mvm_power_update_mode(mvm, vif);
-			if (ret)
-				IWL_ERR(mvm, "failed to update power mode\n");
-		}
 		iwl_mvm_bt_coex_vif_change(mvm);
 		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
 				    IEEE80211_SMPS_AUTOMATIC);
@@ -973,7 +1253,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 					  &mvmvif->time_event_data);
 	} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
 			      BSS_CHANGED_QOS)) {
-		ret = iwl_mvm_power_update_mode(mvm, vif);
+		ret = iwl_mvm_power_update_mac(mvm, vif);
 		if (ret)
 			IWL_ERR(mvm, "failed to update power mode\n");
 	}
@@ -987,10 +1267,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 		IWL_DEBUG_MAC80211(mvm, "cqm info_changed");
 		/* reset cqm events tracking */
 		mvmvif->bf_data.last_cqm_event = 0;
-		ret = iwl_mvm_update_beacon_filter(mvm, vif);
+		ret = iwl_mvm_update_beacon_filter(mvm, vif, false, CMD_SYNC);
 		if (ret)
 			IWL_ERR(mvm, "failed to update CQM thresholds\n");
 	}
+
+	if (changes & BSS_CHANGED_ARP_FILTER) {
+		IWL_DEBUG_MAC80211(mvm, "arp filter changed");
+		iwl_mvm_configure_bcast_filter(mvm, vif);
+	}
 }
 
 static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
@@ -1024,8 +1309,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 	if (ret)
 		goto out_remove;
 
-	mvmvif->ap_ibss_active = true;
-
 	/* Send the bcast station. At this stage the TBTT and DTIM time events
 	 * are added and applied to the scheduler */
 	ret = iwl_mvm_send_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
@@ -1037,7 +1320,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 
 	/* power updated needs to be done before quotas */
 	mvm->bound_vif_cnt++;
-	iwl_mvm_power_update_binding(mvm, vif, true);
+	iwl_mvm_power_update_mac(mvm, vif);
 
 	ret = iwl_mvm_update_quotas(mvm, vif);
 	if (ret)
@@ -1047,6 +1330,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 	if (vif->p2p && mvm->p2p_device_vif)
 		iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
 
+	iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
+
 	iwl_mvm_bt_coex_vif_change(mvm);
 
 	mutex_unlock(&mvm->mutex);
@@ -1054,7 +1339,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 
 out_quota_failed:
 	mvm->bound_vif_cnt--;
-	iwl_mvm_power_update_binding(mvm, vif, false);
+	iwl_mvm_power_update_mac(mvm, vif);
 	mvmvif->ap_ibss_active = false;
 	iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
 out_unbind:
@@ -1080,6 +1365,8 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
 
 	iwl_mvm_bt_coex_vif_change(mvm);
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_AP_IBSS);
+
 	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
 	if (vif->p2p && mvm->p2p_device_vif)
 		iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
@@ -1089,7 +1376,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
 	iwl_mvm_binding_remove_vif(mvm, vif);
 
 	mvm->bound_vif_cnt--;
-	iwl_mvm_power_update_binding(mvm, vif, false);
+	iwl_mvm_power_update_mac(mvm, vif);
 
 	iwl_mvm_mac_ctxt_remove(mvm, vif);
 
@@ -1103,26 +1390,20 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
 				 u32 changes)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT |
-					      BSS_CHANGED_HT |
-					      BSS_CHANGED_BANDWIDTH;
-	int ret;
 
 	/* Changes will be applied when the AP/IBSS is started */
 	if (!mvmvif->ap_ibss_active)
 		return;
 
-	if (changes & ht_change) {
-		ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
-		if (ret)
-			IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
-	}
+	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
+		       BSS_CHANGED_BANDWIDTH) &&
+	    iwl_mvm_mac_ctxt_changed(mvm, vif))
+		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 
 	/* Need to send a new beacon template to the FW */
-	if (changes & BSS_CHANGED_BEACON) {
-		if (iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
-			IWL_WARN(mvm, "Failed updating beacon data\n");
-	}
+	if (changes & BSS_CHANGED_BEACON &&
+	    iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
+		IWL_WARN(mvm, "Failed updating beacon data\n");
 }
 
 static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
@@ -1155,6 +1436,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
 			       struct cfg80211_scan_request *req)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct iwl_notification_wait wait_scan_done;
+	static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
 	int ret;
 
 	if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
@@ -1162,11 +1445,38 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
 
 	mutex_lock(&mvm->mutex);
 
-	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
-		ret = iwl_mvm_scan_request(mvm, vif, req);
-	else
+	switch (mvm->scan_status) {
+	case IWL_MVM_SCAN_SCHED:
+		iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
+					   scan_done_notif,
+					   ARRAY_SIZE(scan_done_notif),
+					   NULL, NULL);
+		iwl_mvm_sched_scan_stop(mvm);
+		ret = iwl_wait_notification(&mvm->notif_wait,
+					    &wait_scan_done, HZ);
+		if (ret) {
+			ret = -EBUSY;
+			goto out;
+		}
+		/* iwl_mvm_rx_scan_offload_complete_notif() will be called
+		 * soon but will not reset the scan status as it won't be
+		 * IWL_MVM_SCAN_SCHED any more since we queue the next scan
+		 * immediately (below)
+		 */
+		break;
+	case IWL_MVM_SCAN_NONE:
+		break;
+	default:
 		ret = -EBUSY;
+		goto out;
+	}
+
+	iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
 
+	ret = iwl_mvm_scan_request(mvm, vif, req);
+	if (ret)
+		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+out:
 	mutex_unlock(&mvm->mutex);
 
 	return ret;
@@ -1186,20 +1496,32 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
 
 static void
 iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
-				  struct ieee80211_sta *sta, u16 tid,
+				  struct ieee80211_sta *sta, u16 tids,
 				  int num_frames,
 				  enum ieee80211_frame_release_type reason,
 				  bool more_data)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
-	/* TODO: how do we tell the fw to send frames for a specific TID */
+	/* Called when we need to transmit (a) frame(s) from mac80211 */
 
-	/*
-	 * The fw will send EOSP notification when the last frame will be
-	 * transmitted.
-	 */
-	iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames);
+	iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
+					  tids, more_data, false);
+}
+
+static void
+iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
+				    struct ieee80211_sta *sta, u16 tids,
+				    int num_frames,
+				    enum ieee80211_frame_release_type reason,
+				    bool more_data)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+	/* Called when we need to transmit (a) frame(s) from agg queue */
+
+	iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
+					  tids, more_data, true);
 }
 
 static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
@@ -1209,11 +1531,25 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+	int tid;
 
 	switch (cmd) {
 	case STA_NOTIFY_SLEEP:
 		if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0)
 			ieee80211_sta_block_awake(hw, sta, true);
+		spin_lock_bh(&mvmsta->lock);
+		for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
+			struct iwl_mvm_tid_data *tid_data;
+
+			tid_data = &mvmsta->tid_data[tid];
+			if (tid_data->state != IWL_AGG_ON &&
+			    tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
+				continue;
+			if (iwl_mvm_tid_queued(tid_data) == 0)
+				continue;
+			ieee80211_sta_set_buffered(sta, tid, true);
+		}
+		spin_unlock_bh(&mvmsta->lock);
 		/*
 		 * The fw updates the STA to be asleep. Tx packets on the Tx
 		 * queues to this station will not be transmitted. The fw will
@@ -1304,12 +1640,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
 	} else if (old_state == IEEE80211_STA_ASSOC &&
 		   new_state == IEEE80211_STA_AUTHORIZED) {
 		/* enable beacon filtering */
-		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif));
+		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));
 		ret = 0;
 	} else if (old_state == IEEE80211_STA_AUTHORIZED &&
 		   new_state == IEEE80211_STA_ASSOC) {
 		/* disable beacon filtering */
-		WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif));
+		WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC));
 		ret = 0;
 	} else if (old_state == IEEE80211_STA_ASSOC &&
 		   new_state == IEEE80211_STA_AUTH) {
@@ -1774,7 +2110,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
 	 * otherwise fw will complain.
 	 */
 	mvm->bound_vif_cnt++;
-	iwl_mvm_power_update_binding(mvm, vif, true);
+	iwl_mvm_power_update_mac(mvm, vif);
 
 	/* Setting the quota at this stage is only required for monitor
 	 * interfaces. For the other types, the bss_info changed flow
@@ -1792,7 +2128,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
  out_remove_binding:
 	iwl_mvm_binding_remove_vif(mvm, vif);
 	mvm->bound_vif_cnt--;
-	iwl_mvm_power_update_binding(mvm, vif, false);
+	iwl_mvm_power_update_mac(mvm, vif);
  out_unlock:
 	mutex_unlock(&mvm->mutex);
 	if (ret)
@@ -1825,7 +2161,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
 
 	iwl_mvm_binding_remove_vif(mvm, vif);
 	mvm->bound_vif_cnt--;
-	iwl_mvm_power_update_binding(mvm, vif, false);
+	iwl_mvm_power_update_mac(mvm, vif);
 
 out_unlock:
 	mvmvif->phy_ctxt = NULL;
@@ -1892,8 +2228,9 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
 			return -EINVAL;
 
 		if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]))
-			return iwl_mvm_enable_beacon_filter(mvm, vif);
-		return iwl_mvm_disable_beacon_filter(mvm, vif);
+			return iwl_mvm_enable_beacon_filter(mvm, vif,
+							    CMD_SYNC);
+		return iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
 	}
 
 	return -EOPNOTSUPP;
@@ -1932,6 +2269,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
 	.sta_state = iwl_mvm_mac_sta_state,
 	.sta_notify = iwl_mvm_mac_sta_notify,
 	.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
+	.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
 	.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
 	.sta_rc_update = iwl_mvm_sta_rc_update,
 	.conf_tx = iwl_mvm_mac_conf_tx,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index e4ead86f06d6..ad0315abf765 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -92,7 +92,6 @@ enum iwl_mvm_tx_fifo {
 };
 
 extern struct ieee80211_ops iwl_mvm_hw_ops;
-extern const struct iwl_mvm_power_ops pm_legacy_ops;
 extern const struct iwl_mvm_power_ops pm_mac_ops;
 
 /**
@@ -152,27 +151,13 @@ enum iwl_power_scheme {
 	IWL_POWER_SCHEME_LP
 };
 
-#define IWL_CONN_MAX_LISTEN_INTERVAL	70
+#define IWL_CONN_MAX_LISTEN_INTERVAL	10
 #define IWL_UAPSD_AC_INFO		(IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
 					 IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
 					 IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
 					 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
 #define IWL_UAPSD_MAX_SP		IEEE80211_WMM_IE_STA_QOSINFO_SP_2
 
-struct iwl_mvm_power_ops {
-	int (*power_update_mode)(struct iwl_mvm *mvm,
-				 struct ieee80211_vif *vif);
-	int (*power_update_device_mode)(struct iwl_mvm *mvm);
-	int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-	void (*power_update_binding)(struct iwl_mvm *mvm,
-				     struct ieee80211_vif *vif, bool assign);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-				char *buf, int bufsz);
-#endif
-};
-
-
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 enum iwl_dbgfs_pm_mask {
 	MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
@@ -239,6 +224,17 @@ enum iwl_mvm_smps_type_request {
 	NUM_IWL_MVM_SMPS_REQ,
 };
 
+enum iwl_mvm_ref_type {
+	IWL_MVM_REF_UCODE_DOWN,
+	IWL_MVM_REF_SCAN,
+	IWL_MVM_REF_ROC,
+	IWL_MVM_REF_P2P_CLIENT,
+	IWL_MVM_REF_AP_IBSS,
+	IWL_MVM_REF_USER,
+
+	IWL_MVM_REF_COUNT,
+};
+
 /**
 * struct iwl_mvm_vif_bf_data - beacon filtering related data
 * @bf_enabled: indicates if beacon filtering is enabled
@@ -269,7 +265,9 @@ struct iwl_mvm_vif_bf_data {
  * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
  *	should get quota etc.
  * @monitor_active: indicates that monitor context is configured, and that the
- * interface should get quota etc.
+ *	interface should get quota etc.
+ * @low_latency: indicates that this interface is in low-latency mode
+ *	(VMACLowLatencyMode)
  * @queue_params: QoS params for this MAC
  * @bcast_sta: station used for broadcast packets. Used by the following
  *  vifs: P2P_DEVICE, GO and AP.
@@ -285,6 +283,7 @@ struct iwl_mvm_vif {
 	bool uploaded;
 	bool ap_ibss_active;
 	bool monitor_active;
+	bool low_latency;
 	struct iwl_mvm_vif_bf_data bf_data;
 
 	u32 ap_beacon_time;
@@ -333,14 +332,13 @@ struct iwl_mvm_vif {
 	struct dentry *dbgfs_slink;
 	struct iwl_dbgfs_pm dbgfs_pm;
 	struct iwl_dbgfs_bf dbgfs_bf;
+	struct iwl_mac_power_cmd mac_pwr_cmd;
 #endif
 
 	enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
 
 	/* FW identified misbehaving AP */
 	u8 uapsd_misbehaving_bssid[ETH_ALEN];
-
-	bool pm_prevented;
 };
 
 static inline struct iwl_mvm_vif *
@@ -415,6 +413,7 @@ struct iwl_tt_params {
  * @ct_kill_exit: worker to exit thermal kill
  * @dynamic_smps: Is thermal throttling enabled dynamic_smps?
  * @tx_backoff: The current thremal throttling tx backoff in uSec.
+ * @min_backoff: The minimal tx backoff due to power restrictions
  * @params: Parameters to configure the thermal throttling algorithm.
  * @throttle: Is thermal throttling is active?
  */
@@ -422,6 +421,7 @@ struct iwl_mvm_tt_mgmt {
 	struct delayed_work ct_kill_exit;
 	bool dynamic_smps;
 	u32 tx_backoff;
+	u32 min_backoff;
 	const struct iwl_tt_params *params;
 	bool throttle;
 };
@@ -457,6 +457,8 @@ struct iwl_mvm {
 	bool init_ucode_complete;
 	u32 error_event_table;
 	u32 log_event_table;
+	u32 umac_error_event_table;
+	bool support_umac_log;
 
 	u32 ampdu_ref;
 
@@ -470,7 +472,7 @@ struct iwl_mvm {
 
 	struct iwl_nvm_data *nvm_data;
 	/* NVM sections */
-	struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
+	struct iwl_nvm_section nvm_sections[NVM_MAX_NUM_SECTIONS];
 
 	/* EEPROM MAC addresses */
 	struct mac_address addresses[IWL_MVM_MAX_ADDRESSES];
@@ -494,6 +496,17 @@ struct iwl_mvm {
 	/* rx chain antennas set through debugfs for the scan command */
 	u8 scan_rx_ant;
 
+#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
+	/* broadcast filters to configure for each associated station */
+	const struct iwl_fw_bcast_filter *bcast_filters;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	struct {
+		u32 override; /* u32 for debugfs_create_bool */
+		struct iwl_bcast_filter_cmd cmd;
+	} dbgfs_bcast_filtering;
+#endif
+#endif
+
 	/* Internal station */
 	struct iwl_mvm_int_sta aux_sta;
 
@@ -526,6 +539,9 @@ struct iwl_mvm {
 	 */
 	unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
 
+	/* A bitmap of reference types taken by the driver. */
+	unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)];
+
 	u8 vif_count;
 
 	/* -1 for always, 0 for never, >0 for that many times */
@@ -548,6 +564,10 @@ struct iwl_mvm {
 #endif
 #endif
 
+	/* d0i3 */
+	u8 d0i3_ap_sta_id;
+	struct work_struct d0i3_exit_work;
+
 	/* BT-Coex */
 	u8 bt_kill_msk;
 	struct iwl_bt_coex_profile_notif last_bt_notif;
@@ -557,8 +577,6 @@ struct iwl_mvm {
 	struct iwl_mvm_tt_mgmt thermal_throttle;
 	s32 temperature;	/* Celsius */
 
-	const struct iwl_mvm_power_ops *pm_ops;
-
 #ifdef CONFIG_NL80211_TESTMODE
 	u32 noa_duration;
 	struct ieee80211_vif *noa_vif;
@@ -572,7 +590,9 @@ struct iwl_mvm {
 	u8 bound_vif_cnt;
 
 	/* Indicate if device power save is allowed */
-	bool ps_prevented;
+	bool ps_disabled;
+	/* Indicate if device power management is allowed */
+	bool pm_disabled;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -595,6 +615,24 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
 	       test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
 }
 
+static inline struct iwl_mvm_sta *
+iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
+{
+	struct ieee80211_sta *sta;
+
+	if (sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
+		return NULL;
+
+	sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
+					lockdep_is_held(&mvm->mutex));
+
+	/* This can happen if the station has been removed right now */
+	if (IS_ERR_OR_NULL(sta))
+		return NULL;
+
+	return iwl_mvm_sta_from_mac80211(sta);
+}
+
 extern const u8 iwl_mvm_ac_to_tx_fifo[];
 
 struct iwl_rate_info {
@@ -661,6 +699,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm);
 int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm);
 
 int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm);
+bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
+				    struct iwl_bcast_filter_cmd *cmd);
 
 /*
  * FW notifications / CMD responses handlers
@@ -773,48 +813,19 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 /* rate scaling */
 int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init);
 
-/* power managment */
-static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
-					    struct ieee80211_vif *vif)
-{
-	return mvm->pm_ops->power_update_mode(mvm, vif);
-}
-
-static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
-					struct ieee80211_vif *vif)
-{
-	return mvm->pm_ops->power_disable(mvm, vif);
-}
-
-static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm)
-{
-	if (mvm->pm_ops->power_update_device_mode)
-		return mvm->pm_ops->power_update_device_mode(mvm);
-	return 0;
-}
+/* power management */
+int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm);
 
-static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
-						struct ieee80211_vif *vif,
-						bool assign)
-{
-	if (mvm->pm_ops->power_update_binding)
-		mvm->pm_ops->power_update_binding(mvm, vif, assign);
-}
+int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+				 char *buf, int bufsz);
 
 void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
 					     struct iwl_rx_cmd_buffer *rxb,
 					     struct iwl_device_cmd *cmd);
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
-					    struct ieee80211_vif *vif,
-					    char *buf, int bufsz)
-{
-	return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
-}
-#endif
-
 int iwl_mvm_leds_init(struct iwl_mvm *mvm);
 void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
 
@@ -841,6 +852,10 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 }
 #endif
 
+/* D0i3 */
+void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
+void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
+
 /* BT Coex */
 int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
@@ -854,6 +869,7 @@ u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm,
 				   struct ieee80211_sta *sta);
 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
 				     struct ieee80211_sta *sta);
+int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable);
 
 enum iwl_bt_kill_msk {
 	BT_KILL_MSK_DEFAULT,
@@ -875,25 +891,51 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
 					 struct iwl_beacon_filter_cmd *cmd)
 {}
 #endif
+int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
+				   struct ieee80211_vif *vif,
+				   bool enable, u32 flags);
 int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
-				 struct ieee80211_vif *vif);
+				 struct ieee80211_vif *vif,
+				 u32 flags);
 int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
-				  struct ieee80211_vif *vif);
-int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
-				   struct iwl_beacon_filter_cmd *cmd);
+				  struct ieee80211_vif *vif,
+				  u32 flags);
 int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
 				struct ieee80211_vif *vif, bool enable);
 int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
-				  struct ieee80211_vif *vif);
+				 struct ieee80211_vif *vif,
+				 bool force,
+				 u32 flags);
 
 /* SMPS */
 void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 				enum iwl_mvm_smps_type_request req_type,
 				enum ieee80211_smps_mode smps_request);
 
+/* Low latency */
+int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			       bool value);
+/* get VMACLowLatencyMode */
+static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
+{
+	/*
+	 * should this consider associated/active/... state?
+	 *
+	 * Normally low-latency should only be active on interfaces
+	 * that are active, but at least with debugfs it can also be
+	 * enabled on interfaces that aren't active. However, when
+	 * interface aren't active then they aren't added into the
+	 * binding, so this has no real impact. For now, just return
+	 * the current desired low-latency state.
+	 */
+
+	return mvmvif->low_latency;
+}
+
 /* Thermal management and CT-kill */
+void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
 void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
-void iwl_mvm_tt_initialize(struct iwl_mvm *mvm);
+void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
 void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
 void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 35b71af78d02..2d5251b3600c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -67,14 +67,6 @@
 #include "iwl-eeprom-read.h"
 #include "iwl-nvm-parse.h"
 
-/* list of NVM sections we are allowed/need to read */
-static const int nvm_to_read[] = {
-	NVM_SECTION_TYPE_HW,
-	NVM_SECTION_TYPE_SW,
-	NVM_SECTION_TYPE_CALIBRATION,
-	NVM_SECTION_TYPE_PRODUCTION,
-};
-
 /* Default NVM size to read */
 #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
 #define IWL_MAX_NVM_SECTION_SIZE 7000
@@ -240,7 +232,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
 
 	/* Checking for required sections */
 	if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
-	    !mvm->nvm_sections[NVM_SECTION_TYPE_HW].data) {
+	    !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
 		IWL_ERR(mvm, "Can't parse empty NVM sections\n");
 		return NULL;
 	}
@@ -248,7 +240,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
 	if (WARN_ON(!mvm->cfg))
 		return NULL;
 
-	hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data;
+	hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data;
 	sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
 	calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
 	return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
@@ -367,7 +359,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
 			break;
 		}
 
-		if (WARN(section_id >= NVM_NUM_OF_SECTIONS,
+		if (WARN(section_id >= NVM_MAX_NUM_SECTIONS,
 			 "Invalid NVM section ID %d\n", section_id)) {
 			ret = -EINVAL;
 			break;
@@ -415,6 +407,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 	int ret, i, section;
 	u8 *nvm_buffer, *temp;
 
+	if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
+		return -EINVAL;
+
 	/* load external NVM if configured */
 	if (iwlwifi_mod_params.nvm_file) {
 		/* move to External NVM flow */
@@ -422,6 +417,14 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 		if (ret)
 			return ret;
 	} else {
+		/* list of NVM sections we are allowed/need to read */
+		int nvm_to_read[] = {
+			mvm->cfg->nvm_hw_section_num,
+			NVM_SECTION_TYPE_SW,
+			NVM_SECTION_TYPE_CALIBRATION,
+			NVM_SECTION_TYPE_PRODUCTION,
+		};
+
 		/* Read From FW NVM */
 		IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
 
@@ -446,10 +449,6 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 			switch (section) {
-			case NVM_SECTION_TYPE_HW:
-				mvm->nvm_hw_blob.data = temp;
-				mvm->nvm_hw_blob.size = ret;
-				break;
 			case NVM_SECTION_TYPE_SW:
 				mvm->nvm_sw_blob.data = temp;
 				mvm->nvm_sw_blob.size  = ret;
@@ -463,6 +462,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 				mvm->nvm_prod_blob.size  = ret;
 				break;
 			default:
+				if (section == mvm->cfg->nvm_hw_section_num) {
+					mvm->nvm_hw_blob.data = temp;
+					mvm->nvm_hw_blob.size = ret;
+					break;
+				}
 				WARN(1, "section: %d", section);
 			}
 #endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index a3d43de342d7..a46f0b8b0870 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -185,9 +185,10 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
 	 * (PCIe power is lost before PERST# is asserted), causing ME FW
 	 * to lose ownership and not being able to obtain it back.
 	 */
-	iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
-			       APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
-			       ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
+	if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
+				       APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
+				       ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
 }
 
 struct iwl_rx_handlers {
@@ -222,10 +223,12 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
 
 	RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false),
 
+	RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false),
+
 	RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
 	RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
 	RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
-		   iwl_mvm_rx_scan_offload_complete_notif, false),
+		   iwl_mvm_rx_scan_offload_complete_notif, true),
 	RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
 		   false),
 
@@ -284,9 +287,11 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(BEACON_NOTIFICATION),
 	CMD(BEACON_TEMPLATE_CMD),
 	CMD(STATISTICS_NOTIFICATION),
+	CMD(EOSP_NOTIFICATION),
 	CMD(REDUCE_TX_POWER_CMD),
 	CMD(TX_ANT_CONFIGURATION_CMD),
 	CMD(D3_CONFIG_CMD),
+	CMD(D0I3_END_CMD),
 	CMD(PROT_OFFLOAD_CONFIG_CMD),
 	CMD(OFFLOADS_QUERY_CMD),
 	CMD(REMOTE_WAKE_CONFIG_CMD),
@@ -309,6 +314,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(BT_PROFILE_NOTIFICATION),
 	CMD(BT_CONFIG),
 	CMD(MCAST_FILTER_CMD),
+	CMD(BCAST_FILTER_CMD),
 	CMD(REPLY_SF_CFG_CMD),
 	CMD(REPLY_BEACON_FILTERING_CMD),
 	CMD(REPLY_THERMAL_MNG_BACKOFF),
@@ -320,6 +326,24 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 
 /* this forward declaration can avoid to export the function */
 static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
+static void iwl_mvm_d0i3_exit_work(struct work_struct *wk);
+
+static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
+{
+	const struct iwl_pwr_tx_backoff *pwr_tx_backoff = cfg->pwr_tx_backoffs;
+
+	if (!pwr_tx_backoff)
+		return 0;
+
+	while (pwr_tx_backoff->pwr) {
+		if (trans->dflt_pwr_limit >= pwr_tx_backoff->pwr)
+			return pwr_tx_backoff->backoff;
+
+		pwr_tx_backoff++;
+	}
+
+	return 0;
+}
 
 static struct iwl_op_mode *
 iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
@@ -333,6 +357,14 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 		TX_CMD,
 	};
 	int err, scan_size;
+	u32 min_backoff;
+
+	/*
+	 * We use IWL_MVM_STATION_COUNT to check the validity of the station
+	 * index all over the driver - check that its value corresponds to the
+	 * array size.
+	 */
+	BUILD_BUG_ON(ARRAY_SIZE(mvm->fw_id_to_mac_id) != IWL_MVM_STATION_COUNT);
 
 	/********************************
 	 * 1. Allocating and configuring HW data
@@ -373,6 +405,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
 	INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
 	INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
+	INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
 
 	SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
 
@@ -421,7 +454,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	IWL_INFO(mvm, "Detected %s, REV=0x%X\n",
 		 mvm->cfg->name, mvm->trans->hw_rev);
 
-	iwl_mvm_tt_initialize(mvm);
+	min_backoff = calc_min_backoff(trans, cfg);
+	iwl_mvm_tt_initialize(mvm, min_backoff);
 
 	/*
 	 * If the NVM exists in an external file,
@@ -462,13 +496,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	if (err)
 		goto out_unregister;
 
-	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)
-		mvm->pm_ops = &pm_mac_ops;
-	else
-		mvm->pm_ops = &pm_legacy_ops;
-
 	memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
 
+	/* rpm starts with a taken ref. only set the appropriate bit here. */
+	set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap);
+
 	return op_mode;
 
  out_unregister:
@@ -508,7 +540,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
 	mvm->phy_db = NULL;
 
 	iwl_free_nvm_data(mvm->nvm_data);
-	for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
+	for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
 		kfree(mvm->nvm_sections[i].data);
 
 	ieee80211_free_hw(mvm->hw);
@@ -703,6 +735,29 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 	iwl_abort_notification_waits(&mvm->notif_wait);
 
 	/*
+	 * This is a bit racy, but worst case we tell mac80211 about
+	 * a stopped/aborted scan when that was already done which
+	 * is not a problem. It is necessary to abort any os scan
+	 * here because mac80211 requires having the scan cleared
+	 * before restarting.
+	 * We'll reset the scan_status to NONE in restart cleanup in
+	 * the next start() call from mac80211. If restart isn't called
+	 * (no fw restart) scan status will stay busy.
+	 */
+	switch (mvm->scan_status) {
+	case IWL_MVM_SCAN_NONE:
+		break;
+	case IWL_MVM_SCAN_OS:
+		ieee80211_scan_completed(mvm->hw, true);
+		break;
+	case IWL_MVM_SCAN_SCHED:
+		/* Sched scan will be restarted by mac80211 in restart_hw. */
+		if (!mvm->restart_fw)
+			ieee80211_sched_scan_stopped(mvm->hw);
+		break;
+	}
+
+	/*
 	 * If we're restarting already, don't cycle restarts.
 	 * If INIT fw asserted, it will likely fail again.
 	 * If WoWLAN fw asserted, don't restart either, mac80211
@@ -733,25 +788,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 		INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
 		schedule_work(&reprobe->work);
 	} else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
-		/*
-		 * This is a bit racy, but worst case we tell mac80211 about
-		 * a stopped/aborted (sched) scan when that was already done
-		 * which is not a problem. It is necessary to abort any scan
-		 * here because mac80211 requires having the scan cleared
-		 * before restarting.
-		 * We'll reset the scan_status to NONE in restart cleanup in
-		 * the next start() call from mac80211.
-		 */
-		switch (mvm->scan_status) {
-		case IWL_MVM_SCAN_NONE:
-			break;
-		case IWL_MVM_SCAN_OS:
-			ieee80211_scan_completed(mvm->hw, true);
-			break;
-		case IWL_MVM_SCAN_SCHED:
-			ieee80211_sched_scan_stopped(mvm->hw);
-			break;
-		}
+		/* don't let the transport/FW power down */
+		iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
 
 		if (mvm->restart_fw > 0)
 			mvm->restart_fw--;
@@ -778,6 +816,163 @@ static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
 	iwl_mvm_nic_restart(mvm);
 }
 
+struct iwl_d0i3_iter_data {
+	struct iwl_mvm *mvm;
+	u8 ap_sta_id;
+	u8 vif_count;
+};
+
+static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac,
+					struct ieee80211_vif *vif)
+{
+	struct iwl_d0i3_iter_data *data = _data;
+	struct iwl_mvm *mvm = data->mvm;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
+
+	IWL_DEBUG_RPM(mvm, "entering D0i3 - vif %pM\n", vif->addr);
+	if (vif->type != NL80211_IFTYPE_STATION ||
+	    !vif->bss_conf.assoc)
+		return;
+
+	iwl_mvm_update_d0i3_power_mode(mvm, vif, true, flags);
+
+	/*
+	 * on init/association, mvm already configures POWER_TABLE_CMD
+	 * and REPLY_MCAST_FILTER_CMD, so currently don't
+	 * reconfigure them (we might want to use different
+	 * params later on, though).
+	 */
+	data->ap_sta_id = mvmvif->ap_sta_id;
+	data->vif_count++;
+}
+
+static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
+{
+	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
+	int ret;
+	struct iwl_d0i3_iter_data d0i3_iter_data = {
+		.mvm = mvm,
+	};
+	struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+		.wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
+					     IWL_WOWLAN_WAKEUP_BEACON_MISS |
+					     IWL_WOWLAN_WAKEUP_LINK_CHANGE |
+					     IWL_WOWLAN_WAKEUP_BCN_FILTERING),
+	};
+	struct iwl_d3_manager_config d3_cfg_cmd = {
+		.min_sleep_time = cpu_to_le32(1000),
+	};
+
+	IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
+
+	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+						   IEEE80211_IFACE_ITER_NORMAL,
+						   iwl_mvm_enter_d0i3_iterator,
+						   &d0i3_iter_data);
+	if (d0i3_iter_data.vif_count == 1) {
+		mvm->d0i3_ap_sta_id = d0i3_iter_data.ap_sta_id;
+	} else {
+		WARN_ON_ONCE(d0i3_iter_data.vif_count > 1);
+		mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
+	}
+
+	ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
+				   sizeof(wowlan_config_cmd),
+				   &wowlan_config_cmd);
+	if (ret)
+		return ret;
+
+	return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD,
+				    flags | CMD_MAKE_TRANS_IDLE,
+				    sizeof(d3_cfg_cmd), &d3_cfg_cmd);
+}
+
+static void iwl_mvm_exit_d0i3_iterator(void *_data, u8 *mac,
+				       struct ieee80211_vif *vif)
+{
+	struct iwl_mvm *mvm = _data;
+	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO;
+
+	IWL_DEBUG_RPM(mvm, "exiting D0i3 - vif %pM\n", vif->addr);
+	if (vif->type != NL80211_IFTYPE_STATION ||
+	    !vif->bss_conf.assoc)
+		return;
+
+	iwl_mvm_update_d0i3_power_mode(mvm, vif, false, flags);
+}
+
+static void iwl_mvm_d0i3_disconnect_iter(void *data, u8 *mac,
+					 struct ieee80211_vif *vif)
+{
+	struct iwl_mvm *mvm = data;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc &&
+	    mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
+		ieee80211_connection_loss(vif);
+}
+
+static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
+{
+	struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work);
+	struct iwl_host_cmd get_status_cmd = {
+		.id = WOWLAN_GET_STATUSES,
+		.flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB,
+	};
+	struct iwl_wowlan_status_v6 *status;
+	int ret;
+	u32 disconnection_reasons, wakeup_reasons;
+
+	mutex_lock(&mvm->mutex);
+	ret = iwl_mvm_send_cmd(mvm, &get_status_cmd);
+	if (ret)
+		goto out;
+
+	if (!get_status_cmd.resp_pkt)
+		goto out;
+
+	status = (void *)get_status_cmd.resp_pkt->data;
+	wakeup_reasons = le32_to_cpu(status->wakeup_reasons);
+
+	IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons);
+
+	disconnection_reasons =
+		IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
+		IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH;
+	if (wakeup_reasons & disconnection_reasons)
+		ieee80211_iterate_active_interfaces(
+			mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+			iwl_mvm_d0i3_disconnect_iter, mvm);
+
+	iwl_free_resp(&get_status_cmd);
+out:
+	mutex_unlock(&mvm->mutex);
+}
+
+static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
+{
+	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
+		    CMD_WAKE_UP_TRANS;
+	int ret;
+
+	IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n");
+
+	ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
+	if (ret)
+		goto out;
+
+	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+						   IEEE80211_IFACE_ITER_NORMAL,
+						   iwl_mvm_exit_d0i3_iterator,
+						   mvm);
+out:
+	schedule_work(&mvm->d0i3_exit_work);
+	return ret;
+}
+
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
 	.start = iwl_op_mode_mvm_start,
 	.stop = iwl_op_mode_mvm_stop,
@@ -789,4 +984,6 @@ static const struct iwl_op_mode_ops iwl_mvm_ops = {
 	.nic_error = iwl_mvm_nic_error,
 	.cmd_queue_full = iwl_mvm_cmd_queue_full,
 	.nic_config = iwl_mvm_nic_config,
+	.enter_d0i3 = iwl_mvm_enter_d0i3,
+	.exit_d0i3 = iwl_mvm_exit_d0i3,
 };
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index d9eab3b7bb9f..4da1ea44f39a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -74,39 +74,36 @@
 
 #define POWER_KEEP_ALIVE_PERIOD_SEC    25
 
+static
 int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
-				   struct iwl_beacon_filter_cmd *cmd)
+				   struct iwl_beacon_filter_cmd *cmd,
+				   u32 flags)
 {
-	int ret;
-
-	ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC,
-				   sizeof(struct iwl_beacon_filter_cmd), cmd);
-
-	if (!ret) {
-		IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
-				le32_to_cpu(cmd->ba_enable_beacon_abort));
-		IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
-				le32_to_cpu(cmd->ba_escape_timer));
-		IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
-				le32_to_cpu(cmd->bf_debug_flag));
-		IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
-				le32_to_cpu(cmd->bf_enable_beacon_filter));
-		IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
-				le32_to_cpu(cmd->bf_energy_delta));
-		IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
-				le32_to_cpu(cmd->bf_escape_timer));
-		IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
-				le32_to_cpu(cmd->bf_roaming_energy_delta));
-		IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
-				le32_to_cpu(cmd->bf_roaming_state));
-		IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
-				le32_to_cpu(cmd->bf_temp_threshold));
-		IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
-				le32_to_cpu(cmd->bf_temp_fast_filter));
-		IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
-				le32_to_cpu(cmd->bf_temp_slow_filter));
-	}
-	return ret;
+	IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
+			le32_to_cpu(cmd->ba_enable_beacon_abort));
+	IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
+			le32_to_cpu(cmd->ba_escape_timer));
+	IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
+			le32_to_cpu(cmd->bf_debug_flag));
+	IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
+			le32_to_cpu(cmd->bf_enable_beacon_filter));
+	IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
+			le32_to_cpu(cmd->bf_energy_delta));
+	IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
+			le32_to_cpu(cmd->bf_escape_timer));
+	IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
+			le32_to_cpu(cmd->bf_roaming_energy_delta));
+	IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
+			le32_to_cpu(cmd->bf_roaming_state));
+	IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
+			le32_to_cpu(cmd->bf_temp_threshold));
+	IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
+			le32_to_cpu(cmd->bf_temp_fast_filter));
+	IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
+			le32_to_cpu(cmd->bf_temp_slow_filter));
+
+	return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
+				    sizeof(struct iwl_beacon_filter_cmd), cmd);
 }
 
 static
@@ -145,7 +142,7 @@ int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
 	mvmvif->bf_data.ba_enabled = enable;
 	iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
 	iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
-	return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+	return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, CMD_SYNC);
 }
 
 static void iwl_mvm_power_log(struct iwl_mvm *mvm,
@@ -301,8 +298,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
 	cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
 
-	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
-	    mvm->ps_prevented)
+	if (mvm->ps_disabled)
 		return;
 
 	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
@@ -312,7 +308,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 	    mvmvif->dbgfs_pm.disable_power_off)
 		cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
 #endif
-	if (!vif->bss_conf.ps || mvmvif->pm_prevented)
+	if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
+	    mvm->pm_disabled)
 		return;
 
 	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -419,11 +416,9 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 }
 
-static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
+static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
 					 struct ieee80211_vif *vif)
 {
-	int ret;
-	bool ba_enable;
 	struct iwl_mac_power_cmd cmd = {};
 
 	if (vif->type != NL80211_IFTYPE_STATION)
@@ -435,56 +430,30 @@ static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
 
 	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
 	iwl_mvm_power_log(mvm, &cmd);
-
-	ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
-				   sizeof(cmd), &cmd);
-	if (ret)
-		return ret;
-
-	ba_enable = !!(cmd.flags &
-		       cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
-
-	return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
-}
-
-static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
-				     struct ieee80211_vif *vif)
-{
-	struct iwl_mac_power_cmd cmd = {};
-	struct iwl_mvm_vif *mvmvif __maybe_unused =
-		iwl_mvm_vif_from_mac80211(vif);
-
-	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
-		return 0;
-
-	cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
-							   mvmvif->color));
-
-	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
-		cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
-
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
-	    mvmvif->dbgfs_pm.disable_power_off)
-		cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
+	memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
 #endif
-	iwl_mvm_power_log(mvm, &cmd);
 
-	return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC,
+	return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
 				    sizeof(cmd), &cmd);
 }
 
-static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
+int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
 {
 	struct iwl_device_power_cmd cmd = {
 		.flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
 	};
 
+	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
+		return 0;
+
 	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
 		return 0;
 
-	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
-	    force_disable)
+	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
+		mvm->ps_disabled = true;
+
+	if (mvm->ps_disabled)
 		cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -501,11 +470,6 @@ static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
 				    &cmd);
 }
 
-static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
-{
-	return _iwl_mvm_power_update_device(mvm, false);
-}
-
 void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -544,44 +508,137 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
 	return 0;
 }
 
-static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac,
-					   struct ieee80211_vif *vif)
+struct iwl_power_constraint {
+	struct ieee80211_vif *bf_vif;
+	struct ieee80211_vif *bss_vif;
+	bool pm_disabled;
+	bool ps_disabled;
+};
+
+static void iwl_mvm_power_iterator(void *_data, u8 *mac,
+				   struct ieee80211_vif *vif)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct iwl_mvm *mvm = _data;
-	int ret;
+	struct iwl_power_constraint *power_iterator = _data;
+
+	switch (ieee80211_vif_type_p2p(vif)) {
+	case NL80211_IFTYPE_P2P_DEVICE:
+		break;
+
+	case NL80211_IFTYPE_P2P_GO:
+	case NL80211_IFTYPE_AP:
+		/* no BSS power mgmt if we have an active AP */
+		if (mvmvif->ap_ibss_active)
+			power_iterator->pm_disabled = true;
+		break;
+
+	case NL80211_IFTYPE_MONITOR:
+		/* no BSS power mgmt and no device power save */
+		power_iterator->pm_disabled = true;
+		power_iterator->ps_disabled = true;
+		break;
+
+	case NL80211_IFTYPE_P2P_CLIENT:
+		/* no BSS power mgmt if we have a P2P client*/
+		power_iterator->pm_disabled = true;
+		break;
+
+	case NL80211_IFTYPE_STATION:
+		/* we should have only one BSS vif */
+		WARN_ON(power_iterator->bss_vif);
+		power_iterator->bss_vif = vif;
+
+		if (mvmvif->bf_data.bf_enabled &&
+		    !WARN_ON(power_iterator->bf_vif))
+			power_iterator->bf_vif = vif;
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void
+iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm,
+				    struct iwl_power_constraint *constraint)
+{
+	lockdep_assert_held(&mvm->mutex);
+
+	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
+		constraint->pm_disabled = true;
+		constraint->ps_disabled = true;
+	}
 
-	mvmvif->pm_prevented = (mvm->bound_vif_cnt <= 1) ? false : true;
+	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+					    IEEE80211_IFACE_ITER_NORMAL,
+					    iwl_mvm_power_iterator, constraint);
 
-	ret = iwl_mvm_power_mac_update_mode(mvm, vif);
-	WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n");
+	/* TODO: remove this and determine this variable in the iterator */
+	if (mvm->bound_vif_cnt > 1)
+		constraint->pm_disabled = true;
 }
 
-static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
-					  struct ieee80211_vif *vif,
-					  bool assign)
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_power_constraint constraint = {};
+	bool ba_enable;
+	int ret;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
+		return 0;
+
+	iwl_mvm_power_get_global_constraint(mvm, &constraint);
+	mvm->ps_disabled = constraint.ps_disabled;
+	mvm->pm_disabled = constraint.pm_disabled;
+
+	/* don't update device power state unless we add / remove monitor */
 	if (vif->type == NL80211_IFTYPE_MONITOR) {
-		int ret = _iwl_mvm_power_update_device(mvm, assign);
-		mvm->ps_prevented = assign;
-		WARN_ONCE(ret, "Failed to update power device state\n");
+		ret = iwl_mvm_power_update_device(mvm);
+		if (ret)
+			return ret;
 	}
 
-	ieee80211_iterate_active_interfaces(mvm->hw,
-					    IEEE80211_IFACE_ITER_NORMAL,
-					    iwl_mvm_power_binding_iterator,
-					    mvm);
+	ret = iwl_mvm_power_send_cmd(mvm, vif);
+	if (ret)
+		return ret;
+
+	if (constraint.bss_vif && vif != constraint.bss_vif) {
+		ret = iwl_mvm_power_send_cmd(mvm, constraint.bss_vif);
+		if (ret)
+			return ret;
+	}
+
+	if (!constraint.bf_vif)
+		return 0;
+
+	vif = constraint.bf_vif;
+	mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	ba_enable = !(constraint.pm_disabled || constraint.ps_disabled ||
+		      !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));
+
+	return iwl_mvm_update_beacon_abort(mvm, constraint.bf_vif, ba_enable);
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
-					struct ieee80211_vif *vif, char *buf,
-					int bufsz)
+int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
+				 struct ieee80211_vif *vif, char *buf,
+				 int bufsz)
 {
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mac_power_cmd cmd = {};
 	int pos = 0;
 
-	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+	if (WARN_ON(!(mvm->fw->ucode_capa.flags &
+		      IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)))
+		return 0;
+
+	mutex_lock(&mvm->mutex);
+	memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
+	mutex_unlock(&mvm->mutex);
 
 	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
 		pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
@@ -685,32 +742,46 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
 }
 #endif
 
-int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
-				 struct ieee80211_vif *vif)
+static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
+					 struct ieee80211_vif *vif,
+					 struct iwl_beacon_filter_cmd *cmd,
+					 u32 cmd_flags,
+					 bool d0i3)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct iwl_beacon_filter_cmd cmd = {
-		IWL_BF_CMD_CONFIG_DEFAULTS,
-		.bf_enable_beacon_filter = cpu_to_le32(1),
-	};
 	int ret;
 
 	if (mvmvif != mvm->bf_allowed_vif ||
 	    vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
-	iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
-	iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
-	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+	iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
+	if (!d0i3)
+		iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
+	ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
 
-	if (!ret)
+	/* don't change bf_enabled in case of temporary d0i3 configuration */
+	if (!ret && !d0i3)
 		mvmvif->bf_data.bf_enabled = true;
 
 	return ret;
 }
 
+int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
+				 struct ieee80211_vif *vif,
+				 u32 flags)
+{
+	struct iwl_beacon_filter_cmd cmd = {
+		IWL_BF_CMD_CONFIG_DEFAULTS,
+		.bf_enable_beacon_filter = cpu_to_le32(1),
+	};
+
+	return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
+}
+
 int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
-				  struct ieee80211_vif *vif)
+				  struct ieee80211_vif *vif,
+				  u32 flags)
 {
 	struct iwl_beacon_filter_cmd cmd = {};
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -720,7 +791,7 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 	    vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
-	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
 
 	if (!ret)
 		mvmvif->bf_data.bf_enabled = false;
@@ -728,23 +799,89 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 	return ret;
 }
 
-int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
-				 struct ieee80211_vif *vif)
+int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
+				   struct ieee80211_vif *vif,
+				   bool enable, u32 flags)
 {
+	int ret;
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mac_power_cmd cmd = {};
 
-	if (!mvmvif->bf_data.bf_enabled)
+	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
-	return iwl_mvm_enable_beacon_filter(mvm, vif);
-}
+	if (!vif->bss_conf.assoc)
+		return 0;
 
-const struct iwl_mvm_power_ops pm_mac_ops = {
-	.power_update_mode = iwl_mvm_power_mac_update_mode,
-	.power_update_device_mode = iwl_mvm_power_update_device,
-	.power_disable = iwl_mvm_power_mac_disable,
-	.power_update_binding = _iwl_mvm_power_update_binding,
+	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+	if (enable) {
+		/* configure skip over dtim up to 300 msec */
+		int dtimper = mvm->hw->conf.ps_dtim_period ?: 1;
+		int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+
+		if (WARN_ON(!dtimper_msec))
+			return 0;
+
+		cmd.flags |=
+			cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+		cmd.skip_dtim_periods = 300 / dtimper_msec;
+	}
+	iwl_mvm_power_log(mvm, &cmd);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	.power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
+	memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
 #endif
-};
+	ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
+				   sizeof(cmd), &cmd);
+	if (ret)
+		return ret;
+
+	/* configure beacon filtering */
+	if (mvmvif != mvm->bf_allowed_vif)
+		return 0;
+
+	if (enable) {
+		struct iwl_beacon_filter_cmd cmd_bf = {
+			IWL_BF_CMD_CONFIG_D0I3,
+			.bf_enable_beacon_filter = cpu_to_le32(1),
+		};
+		ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
+						    flags, true);
+	} else {
+		if (mvmvif->bf_data.bf_enabled)
+			ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
+		else
+			ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
+	}
+
+	return ret;
+}
+
+int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
+				 struct ieee80211_vif *vif,
+				 bool force,
+				 u32 flags)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	if (mvmvif != mvm->bf_allowed_vif)
+		return 0;
+
+	if (!mvmvif->bf_data.bf_enabled) {
+		/* disable beacon filtering explicitly if force is true */
+		if (force)
+			return iwl_mvm_disable_beacon_filter(mvm, vif, flags);
+		return 0;
+	}
+
+	return iwl_mvm_enable_beacon_filter(mvm, vif, flags);
+}
+
+int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm)
+{
+	struct iwl_powertable_cmd cmd = {
+		.keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC,
+	};
+
+	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
+				    sizeof(cmd), &cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
deleted file mode 100644
index ef712ae5bc62..000000000000
--- a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2012 - 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * 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 Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "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 COPYRIGHT
- * OWNER OR CONTRIBUTORS 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/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-debug.h"
-#include "mvm.h"
-#include "iwl-modparams.h"
-#include "fw-api-power.h"
-
-#define POWER_KEEP_ALIVE_PERIOD_SEC    25
-
-static void iwl_mvm_power_log(struct iwl_mvm *mvm,
-			      struct iwl_powertable_cmd *cmd)
-{
-	IWL_DEBUG_POWER(mvm,
-			"Sending power table command for power level %d, flags = 0x%X\n",
-			iwlmvm_mod_params.power_scheme,
-			le16_to_cpu(cmd->flags));
-	IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
-
-	if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
-		IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
-				le32_to_cpu(cmd->rx_data_timeout));
-		IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
-				le32_to_cpu(cmd->tx_data_timeout));
-		if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
-			IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
-					le32_to_cpu(cmd->skip_dtim_periods));
-		if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
-			IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
-					le32_to_cpu(cmd->lprx_rssi_threshold));
-	}
-}
-
-static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
-				    struct ieee80211_vif *vif,
-				    struct iwl_powertable_cmd *cmd)
-{
-	struct ieee80211_hw *hw = mvm->hw;
-	struct ieee80211_chanctx_conf *chanctx_conf;
-	struct ieee80211_channel *chan;
-	int dtimper, dtimper_msec;
-	int keep_alive;
-	bool radar_detect = false;
-	struct iwl_mvm_vif *mvmvif __maybe_unused =
-		iwl_mvm_vif_from_mac80211(vif);
-
-	/*
-	 * Regardless of power management state the driver must set
-	 * keep alive period. FW will use it for sending keep alive NDPs
-	 * immediately after association.
-	 */
-	cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
-
-	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
-		return;
-
-	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
-	if (!vif->bss_conf.assoc)
-		cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
-	    mvmvif->dbgfs_pm.disable_power_off)
-		cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
-#endif
-	if (!vif->bss_conf.ps)
-		return;
-
-	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
-
-	if (vif->bss_conf.beacon_rate &&
-	    (vif->bss_conf.beacon_rate->bitrate == 10 ||
-	     vif->bss_conf.beacon_rate->bitrate == 60)) {
-		cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
-		cmd->lprx_rssi_threshold =
-			cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
-	}
-
-	dtimper = hw->conf.ps_dtim_period ?: 1;
-
-	/* Check if radar detection is required on current channel */
-	rcu_read_lock();
-	chanctx_conf = rcu_dereference(vif->chanctx_conf);
-	WARN_ON(!chanctx_conf);
-	if (chanctx_conf) {
-		chan = chanctx_conf->def.chan;
-		radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
-	}
-	rcu_read_unlock();
-
-	/* Check skip over DTIM conditions */
-	if (!radar_detect && (dtimper <= 10) &&
-	    (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
-	     mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
-		cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-		cmd->skip_dtim_periods = cpu_to_le32(3);
-	}
-
-	/* Check that keep alive period is at least 3 * DTIM */
-	dtimper_msec = dtimper * vif->bss_conf.beacon_int;
-	keep_alive = max_t(int, 3 * dtimper_msec,
-			   MSEC_PER_SEC * cmd->keep_alive_seconds);
-	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
-	cmd->keep_alive_seconds = keep_alive;
-
-	if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
-		cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
-		cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
-	} else {
-		cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
-		cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
-		cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
-		if (mvmvif->dbgfs_pm.skip_over_dtim)
-			cmd->flags |=
-				cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-		else
-			cmd->flags &=
-				cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-	}
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
-		cmd->rx_data_timeout =
-			cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
-		cmd->tx_data_timeout =
-			cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
-		cmd->skip_dtim_periods =
-			cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
-		if (mvmvif->dbgfs_pm.lprx_ena)
-			cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
-		else
-			cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
-	}
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
-		cmd->lprx_rssi_threshold =
-			cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
-#endif /* CONFIG_IWLWIFI_DEBUGFS */
-}
-
-static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
-					    struct ieee80211_vif *vif)
-{
-	int ret;
-	bool ba_enable;
-	struct iwl_powertable_cmd cmd = {};
-
-	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
-		return 0;
-
-	/*
-	 * TODO: The following vif_count verification is temporary condition.
-	 * Avoid power mode update if more than one interface is currently
-	 * active. Remove this condition when FW will support power management
-	 * on multiple MACs.
-	 */
-	IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
-			mvm->vif_count);
-	if (mvm->vif_count > 1)
-		return 0;
-
-	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
-	iwl_mvm_power_log(mvm, &cmd);
-
-	ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
-				   sizeof(cmd), &cmd);
-	if (ret)
-		return ret;
-
-	ba_enable = !!(cmd.flags &
-		       cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
-
-	return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
-}
-
-static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
-					struct ieee80211_vif *vif)
-{
-	struct iwl_powertable_cmd cmd = {};
-	struct iwl_mvm_vif *mvmvif __maybe_unused =
-		iwl_mvm_vif_from_mac80211(vif);
-
-	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
-		return 0;
-
-	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
-		cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
-	    mvmvif->dbgfs_pm.disable_power_off)
-		cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
-#endif
-	iwl_mvm_power_log(mvm, &cmd);
-
-	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
-				    sizeof(cmd), &cmd);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
-					   struct ieee80211_vif *vif, char *buf,
-					   int bufsz)
-{
-	struct iwl_powertable_cmd cmd = {};
-	int pos = 0;
-
-	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
-
-	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
-			 (cmd.flags &
-			 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
-			 0 : 1);
-	pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
-			 le32_to_cpu(cmd.skip_dtim_periods));
-	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
-			 iwlmvm_mod_params.power_scheme);
-	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
-			 le16_to_cpu(cmd.flags));
-	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
-			 cmd.keep_alive_seconds);
-
-	if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
-		pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
-				 (cmd.flags &
-				 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
-				 1 : 0);
-		pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
-				 le32_to_cpu(cmd.rx_data_timeout));
-		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
-				 le32_to_cpu(cmd.tx_data_timeout));
-		if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
-			pos += scnprintf(buf+pos, bufsz-pos,
-					 "lprx_rssi_threshold = %d\n",
-					 le32_to_cpu(cmd.lprx_rssi_threshold));
-	}
-	return pos;
-}
-#endif
-
-const struct iwl_mvm_power_ops pm_legacy_ops = {
-	.power_update_mode = iwl_mvm_power_legacy_update_mode,
-	.power_disable = iwl_mvm_power_legacy_disable,
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	.power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
-#endif
-};
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index ce5db6c4ef7e..06d8429be1fb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -65,9 +65,14 @@
 #include "fw-api.h"
 #include "mvm.h"
 
+#define QUOTA_100	IWL_MVM_MAX_QUOTA
+#define QUOTA_LOWLAT_MIN ((QUOTA_100 * IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT) / 100)
+
 struct iwl_mvm_quota_iterator_data {
 	int n_interfaces[MAX_BINDINGS];
 	int colors[MAX_BINDINGS];
+	int low_latency[MAX_BINDINGS];
+	int n_low_latency_bindings;
 	struct ieee80211_vif *new_vif;
 };
 
@@ -107,22 +112,29 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
 		if (vif->bss_conf.assoc)
-			data->n_interfaces[id]++;
-		break;
+			break;
+		return;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_ADHOC:
 		if (mvmvif->ap_ibss_active)
-			data->n_interfaces[id]++;
-		break;
+			break;
+		return;
 	case NL80211_IFTYPE_MONITOR:
 		if (mvmvif->monitor_active)
-			data->n_interfaces[id]++;
-		break;
+			break;
+		return;
 	case NL80211_IFTYPE_P2P_DEVICE:
-		break;
+		return;
 	default:
 		WARN_ON_ONCE(1);
-		break;
+		return;
+	}
+
+	data->n_interfaces[id]++;
+
+	if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
+		data->n_low_latency_bindings++;
+		data->low_latency[id] = true;
 	}
 }
 
@@ -162,12 +174,13 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
 int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 {
 	struct iwl_time_quota_cmd cmd = {};
-	int i, idx, ret, num_active_macs, quota, quota_rem;
+	int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
 	struct iwl_mvm_quota_iterator_data data = {
 		.n_interfaces = {},
 		.colors = { -1, -1, -1, -1 },
 		.new_vif = newvif,
 	};
+	u32 ll_max_duration;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -186,6 +199,21 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 		iwl_mvm_quota_iterator(&data, newvif->addr, newvif);
 	}
 
+	switch (data.n_low_latency_bindings) {
+	case 0: /* no low latency - use default */
+		ll_max_duration = 0;
+		break;
+	case 1: /* SingleBindingLowLatencyMode */
+		ll_max_duration = IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR;
+		break;
+	case 2: /* DualBindingLowLatencyMode */
+		ll_max_duration = IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR;
+		break;
+	default: /* MultiBindingLowLatencyMode */
+		ll_max_duration = 0;
+		break;
+	}
+
 	/*
 	 * The FW's scheduling session consists of
 	 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
@@ -197,11 +225,39 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 		num_active_macs += data.n_interfaces[i];
 	}
 
-	quota = 0;
-	quota_rem = 0;
-	if (num_active_macs) {
-		quota = IWL_MVM_MAX_QUOTA / num_active_macs;
-		quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
+	n_non_lowlat = num_active_macs;
+
+	if (data.n_low_latency_bindings == 1) {
+		for (i = 0; i < MAX_BINDINGS; i++) {
+			if (data.low_latency[i]) {
+				n_non_lowlat -= data.n_interfaces[i];
+				break;
+			}
+		}
+	}
+
+	if (data.n_low_latency_bindings == 1 && n_non_lowlat) {
+		/*
+		 * Reserve quota for the low latency binding in case that
+		 * there are several data bindings but only a single
+		 * low latency one. Split the rest of the quota equally
+		 * between the other data interfaces.
+		 */
+		quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
+		quota_rem = QUOTA_100 - n_non_lowlat * quota -
+			    QUOTA_LOWLAT_MIN;
+	} else if (num_active_macs) {
+		/*
+		 * There are 0 or more than 1 low latency bindings, or all the
+		 * data interfaces belong to the single low latency binding.
+		 * Split the quota equally between the data interfaces.
+		 */
+		quota = QUOTA_100 / num_active_macs;
+		quota_rem = QUOTA_100 % num_active_macs;
+	} else {
+		/* values don't really matter - won't be used */
+		quota = 0;
+		quota_rem = 0;
 	}
 
 	for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@@ -211,19 +267,42 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 		cmd.quotas[idx].id_and_color =
 			cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i]));
 
-		if (data.n_interfaces[i] <= 0) {
+		if (data.n_interfaces[i] <= 0)
 			cmd.quotas[idx].quota = cpu_to_le32(0);
-			cmd.quotas[idx].max_duration = cpu_to_le32(0);
-		} else {
+		else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
+			 data.low_latency[i])
+			/*
+			 * There is more than one binding, but only one of the
+			 * bindings is in low latency. For this case, allocate
+			 * the minimal required quota for the low latency
+			 * binding.
+			 */
+			cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
+
+		else
 			cmd.quotas[idx].quota =
 				cpu_to_le32(quota * data.n_interfaces[i]);
+
+		WARN_ONCE(le32_to_cpu(cmd.quotas[idx].quota) > QUOTA_100,
+			  "Binding=%d, quota=%u > max=%u\n",
+			  idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100);
+
+		if (data.n_interfaces[i] && !data.low_latency[i])
+			cmd.quotas[idx].max_duration =
+				cpu_to_le32(ll_max_duration);
+		else
 			cmd.quotas[idx].max_duration = cpu_to_le32(0);
-		}
+
 		idx++;
 	}
 
-	/* Give the remainder of the session to the first binding */
-	le32_add_cpu(&cmd.quotas[0].quota, quota_rem);
+	/* Give the remainder of the session to the first data binding */
+	for (i = 0; i < MAX_BINDINGS; i++) {
+		if (le32_to_cpu(cmd.quotas[i].quota) != 0) {
+			le32_add_cpu(&cmd.quotas[i].quota, quota_rem);
+			break;
+		}
+	}
 
 	iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 6abf74e1351f..32bb8075121c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -380,49 +380,49 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
  * (2.4 GHz) band.
  */
 
-static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
+static const u16 expected_tpt_legacy[IWL_RATE_COUNT] = {
 	7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0
 };
 
 /* Expected TpT tables. 4 indexes:
  * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI
  */
-static s32 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 42, 0,  76, 102, 124, 159, 183, 193, 202, 216, 0},
 	{0, 0, 0, 0, 46, 0,  82, 110, 132, 168, 192, 202, 210, 225, 0},
 	{0, 0, 0, 0, 49, 0,  97, 145, 192, 285, 375, 420, 464, 551, 0},
 	{0, 0, 0, 0, 54, 0, 108, 160, 213, 315, 415, 465, 513, 608, 0},
 };
 
-static s32 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250,  257,  269,  275},
 	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257,  264,  275,  280},
 	{0, 0, 0, 0, 101, 0, 199, 295, 389, 570, 744, 828,  911, 1070, 1173},
 	{0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284},
 };
 
-static s32 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 130, 0, 191, 223, 244,  273,  288,  294,  298,  305,  308},
 	{0, 0, 0, 0, 138, 0, 200, 231, 251,  279,  293,  298,  302,  308,  312},
 	{0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466},
 	{0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691},
 };
 
-static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250,  261, 0},
 	{0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256,  267, 0},
 	{0, 0, 0, 0,  98, 0, 193, 286, 375, 550, 718, 799, 878, 1032, 0},
 	{0, 0, 0, 0, 109, 0, 214, 316, 414, 607, 790, 879, 965, 1132, 0},
 };
 
-static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 123, 0, 182, 214, 235,  264,  279,  285,  289,  296,  300},
 	{0, 0, 0, 0, 131, 0, 191, 222, 242,  270,  284,  289,  293,  300,  303},
 	{0, 0, 0, 0, 200, 0, 390, 571, 741, 1067, 1365, 1505, 1640, 1894, 2053},
 	{0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221},
 };
 
-static s32 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = {
+static const u16 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 182, 0, 240,  264,  278,  299,  308,  311,  313,  317,  319},
 	{0, 0, 0, 0, 190, 0, 247,  269,  282,  302,  310,  313,  315,  319,  320},
 	{0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219},
@@ -905,7 +905,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
 
 		rate->bw = RATE_MCS_CHAN_WIDTH_20;
 
-		WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX &&
+		WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX ||
 			     rate->index > IWL_RATE_MCS_9_INDEX);
 
 		rate->index = rs_ht_to_legacy[rate->index];
@@ -1169,12 +1169,12 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
 	lq_sta->visited_columns = 0;
 }
 
-static s32 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
+static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 				      const struct rs_tx_column *column,
 				      u32 bw)
 {
 	/* Used to choose among HT tables */
-	s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
+	const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT];
 
 	if (WARN_ON_ONCE(column->mode != RS_LEGACY &&
 			 column->mode != RS_SISO &&
@@ -1262,9 +1262,8 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
 	    &(lq_sta->lq_info[lq_sta->active_tbl]);
 	s32 active_sr = active_tbl->win[index].success_ratio;
 	s32 active_tpt = active_tbl->expected_tpt[index];
-
 	/* expected "search" throughput */
-	s32 *tpt_tbl = tbl->expected_tpt;
+	const u16 *tpt_tbl = tbl->expected_tpt;
 
 	s32 new_rate, high, low, start_hi;
 	u16 high_low;
@@ -1479,7 +1478,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 	const struct rs_tx_column *next_col;
 	allow_column_func_t allow_func;
 	u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw);
-	s32 *expected_tpt_tbl;
+	const u16 *expected_tpt_tbl;
 	s32 tpt, max_expected_tpt;
 
 	for (i = 0; i < MAX_NEXT_COLUMNS; i++) {
@@ -2815,8 +2814,8 @@ static void rs_rate_init_stub(void *mvm_r,
 			      struct ieee80211_sta *sta, void *mvm_sta)
 {
 }
-static struct rate_control_ops rs_mvm_ops = {
-	.module = NULL,
+
+static const struct rate_control_ops rs_mvm_ops = {
 	.name = RS_NAME,
 	.tx_status = rs_tx_status,
 	.get_rate = rs_get_rate,
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 7bc6404f6986..3332b396011e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -277,7 +277,7 @@ enum rs_column {
 struct iwl_scale_tbl_info {
 	struct rs_rate rate;
 	enum rs_column column;
-	s32 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
+	const u16 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
 	struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
 };
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index a85b60f7e67e..fa3c1393e103 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -129,22 +129,16 @@ static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
 			      struct ieee80211_rx_status *rx_status)
 {
 	int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
-	int rssi_all_band_a, rssi_all_band_b;
-	u32 agc_a, agc_b, max_agc;
+	u32 agc_a, agc_b;
 	u32 val;
 
 	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
 	agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
 	agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
-	max_agc = max_t(u32, agc_a, agc_b);
 
 	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
 	rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
 	rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
-	rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
-				IWL_OFDM_RSSI_ALLBAND_A_POS;
-	rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
-				IWL_OFDM_RSSI_ALLBAND_B_POS;
 
 	/*
 	 * dBm = rssi dB - agc dB - constant.
@@ -364,10 +358,10 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 		rx_status.flag |= RX_FLAG_40MHZ;
 		break;
 	case RATE_MCS_CHAN_WIDTH_80:
-		rx_status.flag |= RX_FLAG_80MHZ;
+		rx_status.vht_flag |= RX_VHT_FLAG_80MHZ;
 		break;
 	case RATE_MCS_CHAN_WIDTH_160:
-		rx_status.flag |= RX_FLAG_160MHZ;
+		rx_status.vht_flag |= RX_VHT_FLAG_160MHZ;
 		break;
 	}
 	if (rate_n_flags & RATE_MCS_SGI_MSK)
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 742afc429c94..eba55cc3352d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -408,6 +408,8 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 	mvm->scan_status = IWL_MVM_SCAN_NONE;
 	ieee80211_scan_completed(mvm->hw, notif->status != SCAN_COMP_STATUS_OK);
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+
 	return 0;
 }
 
@@ -476,6 +478,7 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
 
 	if (iwl_mvm_is_radio_killed(mvm)) {
 		ieee80211_scan_completed(mvm->hw, true);
+		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
 		mvm->scan_status = IWL_MVM_SCAN_NONE;
 		return;
 	}
@@ -488,7 +491,7 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
 	ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
 	if (ret) {
 		IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
-		/* mac80211's state will be cleaned in the fw_restart flow */
+		/* mac80211's state will be cleaned in the nic_restart flow */
 		goto out_remove_notif;
 	}
 
@@ -509,11 +512,16 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_scan_offload_complete *scan_notif = (void *)pkt->data;
 
+	/* scan status must be locked for proper checking */
+	lockdep_assert_held(&mvm->mutex);
+
 	IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n",
 		       scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
 		       "completed" : "aborted");
 
-	mvm->scan_status = IWL_MVM_SCAN_NONE;
+	/* might already be something else again, don't reset if so */
+	if (mvm->scan_status == IWL_MVM_SCAN_SCHED)
+		mvm->scan_status = IWL_MVM_SCAN_NONE;
 	ieee80211_sched_scan_stopped(mvm->hw);
 
 	return 0;
@@ -596,6 +604,9 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
 	 * config match list.
 	 */
 	for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
+		/* skip empty SSID matchsets */
+		if (!req->match_sets[i].ssid.ssid_len)
+			continue;
 		scan->direct_scan[i].id = WLAN_EID_SSID;
 		scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
 		memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 3397f59cd4e4..2677d1c0e1a1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -66,27 +66,27 @@
 #include "sta.h"
 #include "rs.h"
 
-static void iwl_mvm_add_sta_cmd_v6_to_v5(struct iwl_mvm_add_sta_cmd_v6 *cmd_v6,
+static void iwl_mvm_add_sta_cmd_v7_to_v5(struct iwl_mvm_add_sta_cmd_v7 *cmd_v7,
 					 struct iwl_mvm_add_sta_cmd_v5 *cmd_v5)
 {
 	memset(cmd_v5, 0, sizeof(*cmd_v5));
 
-	cmd_v5->add_modify = cmd_v6->add_modify;
-	cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx;
-	cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color;
-	memcpy(cmd_v5->addr, cmd_v6->addr, ETH_ALEN);
-	cmd_v5->sta_id = cmd_v6->sta_id;
-	cmd_v5->modify_mask = cmd_v6->modify_mask;
-	cmd_v5->station_flags = cmd_v6->station_flags;
-	cmd_v5->station_flags_msk = cmd_v6->station_flags_msk;
-	cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid;
-	cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid;
-	cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn;
-	cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count;
-	cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags;
-	cmd_v5->assoc_id = cmd_v6->assoc_id;
-	cmd_v5->beamform_flags = cmd_v6->beamform_flags;
-	cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk;
+	cmd_v5->add_modify = cmd_v7->add_modify;
+	cmd_v5->tid_disable_tx = cmd_v7->tid_disable_tx;
+	cmd_v5->mac_id_n_color = cmd_v7->mac_id_n_color;
+	memcpy(cmd_v5->addr, cmd_v7->addr, ETH_ALEN);
+	cmd_v5->sta_id = cmd_v7->sta_id;
+	cmd_v5->modify_mask = cmd_v7->modify_mask;
+	cmd_v5->station_flags = cmd_v7->station_flags;
+	cmd_v5->station_flags_msk = cmd_v7->station_flags_msk;
+	cmd_v5->add_immediate_ba_tid = cmd_v7->add_immediate_ba_tid;
+	cmd_v5->remove_immediate_ba_tid = cmd_v7->remove_immediate_ba_tid;
+	cmd_v5->add_immediate_ba_ssn = cmd_v7->add_immediate_ba_ssn;
+	cmd_v5->sleep_tx_count = cmd_v7->sleep_tx_count;
+	cmd_v5->sleep_state_flags = cmd_v7->sleep_state_flags;
+	cmd_v5->assoc_id = cmd_v7->assoc_id;
+	cmd_v5->beamform_flags = cmd_v7->beamform_flags;
+	cmd_v5->tfd_queue_msk = cmd_v7->tfd_queue_msk;
 }
 
 static void
@@ -110,7 +110,7 @@ iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd,
 }
 
 static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm,
-					   struct iwl_mvm_add_sta_cmd_v6 *cmd,
+					   struct iwl_mvm_add_sta_cmd_v7 *cmd,
 					   int *status)
 {
 	struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
@@ -119,14 +119,14 @@ static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm,
 		return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd),
 						   cmd, status);
 
-	iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5);
+	iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5);
 
 	return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5),
 					   &cmd_v5, status);
 }
 
 static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags,
-				    struct iwl_mvm_add_sta_cmd_v6 *cmd)
+				    struct iwl_mvm_add_sta_cmd_v7 *cmd)
 {
 	struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
 
@@ -134,7 +134,7 @@ static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags,
 		return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags,
 					    sizeof(*cmd), cmd);
 
-	iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5);
+	iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5);
 
 	return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5),
 				    &cmd_v5);
@@ -175,19 +175,30 @@ static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm,
 				    &sta_cmd);
 }
 
-static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
+static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
+				    enum nl80211_iftype iftype)
 {
 	int sta_id;
+	u32 reserved_ids = 0;
 
+	BUILD_BUG_ON(IWL_MVM_STATION_COUNT > 32);
 	WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
 
 	lockdep_assert_held(&mvm->mutex);
 
+	/* d0i3/d3 assumes the AP's sta_id (of sta vif) is 0. reserve it. */
+	if (iftype != NL80211_IFTYPE_STATION)
+		reserved_ids = BIT(0);
+
 	/* Don't take rcu_read_lock() since we are protected by mvm->mutex */
-	for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++)
+	for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) {
+		if (BIT(sta_id) & reserved_ids)
+			continue;
+
 		if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
 					       lockdep_is_held(&mvm->mutex)))
 			return sta_id;
+	}
 	return IWL_MVM_STATION_COUNT;
 }
 
@@ -196,7 +207,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 			   bool update)
 {
 	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
-	struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd;
+	struct iwl_mvm_add_sta_cmd_v7 add_sta_cmd;
 	int ret;
 	u32 status;
 	u32 agg_size = 0, mpdu_dens = 0;
@@ -312,7 +323,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
 	lockdep_assert_held(&mvm->mutex);
 
 	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
-		sta_id = iwl_mvm_find_free_sta_id(mvm);
+		sta_id = iwl_mvm_find_free_sta_id(mvm,
+						  ieee80211_vif_type_p2p(vif));
 	else
 		sta_id = mvm_sta->sta_id;
 
@@ -368,7 +380,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm,
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 		      bool drain)
 {
-	struct iwl_mvm_add_sta_cmd_v6 cmd = {};
+	struct iwl_mvm_add_sta_cmd_v7 cmd = {};
 	int ret;
 	u32 status;
 
@@ -522,6 +534,10 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 
 		/* unassoc - go ahead - remove the AP STA now */
 		mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
+
+		/* clear d0i3_ap_sta_id if no longer relevant */
+		if (mvm->d0i3_ap_sta_id == mvm_sta->sta_id)
+			mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
 	}
 
 	/*
@@ -560,10 +576,10 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
 }
 
 int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
-			     u32 qmask)
+			     u32 qmask, enum nl80211_iftype iftype)
 {
 	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
-		sta->sta_id = iwl_mvm_find_free_sta_id(mvm);
+		sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
 		if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT))
 			return -ENOSPC;
 	}
@@ -587,13 +603,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
 				      const u8 *addr,
 				      u16 mac_id, u16 color)
 {
-	struct iwl_mvm_add_sta_cmd_v6 cmd;
+	struct iwl_mvm_add_sta_cmd_v7 cmd;
 	int ret;
 	u32 status;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6));
+	memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v7));
 	cmd.sta_id = sta->sta_id;
 	cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
 							     color));
@@ -627,7 +643,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
 	lockdep_assert_held(&mvm->mutex);
 
 	/* Add the aux station, but without any queues */
-	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0);
+	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0,
+				       NL80211_IFTYPE_UNSPECIFIED);
 	if (ret)
 		return ret;
 
@@ -699,7 +716,8 @@ int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	lockdep_assert_held(&mvm->mutex);
 
 	qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
-	ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask);
+	ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask,
+				       ieee80211_vif_type_p2p(vif));
 	if (ret)
 		return ret;
 
@@ -735,7 +753,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 		       int tid, u16 ssn, bool start)
 {
 	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
-	struct iwl_mvm_add_sta_cmd_v6 cmd = {};
+	struct iwl_mvm_add_sta_cmd_v7 cmd = {};
 	int ret;
 	u32 status;
 
@@ -794,7 +812,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 			      int tid, u8 queue, bool start)
 {
 	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
-	struct iwl_mvm_add_sta_cmd_v6 cmd = {};
+	struct iwl_mvm_add_sta_cmd_v7 cmd = {};
 	int ret;
 	u32 status;
 
@@ -833,7 +851,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 	return ret;
 }
 
-static const u8 tid_to_ac[] = {
+static const u8 tid_to_mac80211_ac[] = {
 	IEEE80211_AC_BE,
 	IEEE80211_AC_BK,
 	IEEE80211_AC_BK,
@@ -844,6 +862,17 @@ static const u8 tid_to_ac[] = {
 	IEEE80211_AC_VO,
 };
 
+static const u8 tid_to_ucode_ac[] = {
+	AC_BE,
+	AC_BK,
+	AC_BK,
+	AC_BE,
+	AC_VI,
+	AC_VI,
+	AC_VO,
+	AC_VO,
+};
+
 int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
@@ -874,7 +903,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	}
 
 	/* the new tx queue is still connected to the same mac80211 queue */
-	mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_ac[tid]];
+	mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]];
 
 	spin_lock_bh(&mvmsta->lock);
 	tid_data = &mvmsta->tid_data[tid];
@@ -916,7 +945,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	tid_data->ssn = 0xffff;
 	spin_unlock_bh(&mvmsta->lock);
 
-	fifo = iwl_mvm_ac_to_tx_fifo[tid_to_ac[tid]];
+	fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
 
 	ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
 	if (ret)
@@ -1411,7 +1440,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
 				struct ieee80211_sta *sta)
 {
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	struct iwl_mvm_add_sta_cmd_v6 cmd = {
+	struct iwl_mvm_add_sta_cmd_v7 cmd = {
 		.add_modify = STA_MODE_MODIFY,
 		.sta_id = mvmsta->sta_id,
 		.station_flags_msk = cpu_to_le32(STA_FLG_PS),
@@ -1427,28 +1456,102 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
 void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
 				       struct ieee80211_sta *sta,
 				       enum ieee80211_frame_release_type reason,
-				       u16 cnt)
+				       u16 cnt, u16 tids, bool more_data,
+				       bool agg)
 {
-	u16 sleep_state_flags =
-		(reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
-			STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	struct iwl_mvm_add_sta_cmd_v6 cmd = {
+	struct iwl_mvm_add_sta_cmd_v7 cmd = {
 		.add_modify = STA_MODE_MODIFY,
 		.sta_id = mvmsta->sta_id,
 		.modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
 		.sleep_tx_count = cpu_to_le16(cnt),
 		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
-		/*
-		 * Same modify mask for sleep_tx_count and sleep_state_flags so
-		 * we must set the sleep_state_flags too.
-		 */
-		.sleep_state_flags = cpu_to_le16(sleep_state_flags),
 	};
-	int ret;
+	int tid, ret;
+	unsigned long _tids = tids;
+
+	/* convert TIDs to ACs - we don't support TSPEC so that's OK
+	 * Note that this field is reserved and unused by firmware not
+	 * supporting GO uAPSD, so it's safe to always do this.
+	 */
+	for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
+		cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
+
+	/* If we're releasing frames from aggregation queues then check if the
+	 * all queues combined that we're releasing frames from have
+	 *  - more frames than the service period, in which case more_data
+	 *    needs to be set
+	 *  - fewer than 'cnt' frames, in which case we need to adjust the
+	 *    firmware command (but do that unconditionally)
+	 */
+	if (agg) {
+		int remaining = cnt;
+
+		spin_lock_bh(&mvmsta->lock);
+		for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT) {
+			struct iwl_mvm_tid_data *tid_data;
+			u16 n_queued;
+
+			tid_data = &mvmsta->tid_data[tid];
+			if (WARN(tid_data->state != IWL_AGG_ON &&
+				 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
+				 "TID %d state is %d\n",
+				 tid, tid_data->state)) {
+				spin_unlock_bh(&mvmsta->lock);
+				ieee80211_sta_eosp(sta);
+				return;
+			}
+
+			n_queued = iwl_mvm_tid_queued(tid_data);
+			if (n_queued > remaining) {
+				more_data = true;
+				remaining = 0;
+				break;
+			}
+			remaining -= n_queued;
+		}
+		spin_unlock_bh(&mvmsta->lock);
+
+		cmd.sleep_tx_count = cpu_to_le16(cnt - remaining);
+		if (WARN_ON(cnt - remaining == 0)) {
+			ieee80211_sta_eosp(sta);
+			return;
+		}
+	}
+
+	/* Note: this is ignored by firmware not supporting GO uAPSD */
+	if (more_data)
+		cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_MOREDATA);
+
+	if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) {
+		mvmsta->next_status_eosp = true;
+		cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_PS_POLL);
+	} else {
+		cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD);
+	}
 
-	/* TODO: somehow the fw doesn't seem to take PS_POLL into account */
 	ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd);
 	if (ret)
 		IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
 }
+
+int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
+			  struct iwl_rx_cmd_buffer *rxb,
+			  struct iwl_device_cmd *cmd)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_mvm_eosp_notification *notif = (void *)pkt->data;
+	struct ieee80211_sta *sta;
+	u32 sta_id = le32_to_cpu(notif->sta_id);
+
+	if (WARN_ON_ONCE(sta_id >= IWL_MVM_STATION_COUNT))
+		return 0;
+
+	rcu_read_lock();
+	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+	if (!IS_ERR_OR_NULL(sta))
+		ieee80211_sta_eosp(sta);
+	rcu_read_unlock();
+
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index 4968d0237dc5..2ed84c421481 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -195,24 +195,33 @@ struct iwl_mvm;
 /**
  * DOC: AP mode - PS
  *
- * When a station is asleep, the fw will set it as "asleep". All the
- * non-aggregation frames to that station will be dropped by the fw
- * (%TX_STATUS_FAIL_DEST_PS failure code).
+ * When a station is asleep, the fw will set it as "asleep". All frames on
+ * shared queues (i.e. non-aggregation queues) to that station will be dropped
+ * by the fw (%TX_STATUS_FAIL_DEST_PS failure code).
+ *
  * AMPDUs are in a separate queue that is stopped by the fw. We just need to
- * let mac80211 know how many frames we have in these queues so that it can
+ * let mac80211 know when there are frames in these queues so that it can
  * properly handle trigger frames.
- * When the a trigger frame is received, mac80211 tells the driver to send
- * frames from the AMPDU queues or AC queue depending on which queue are
- * delivery-enabled and what TID has frames to transmit (Note that mac80211 has
- * all the knowledege since all the non-agg frames are buffered / filtered, and
- * the driver tells mac80211 about agg frames). The driver needs to tell the fw
- * to let frames out even if the station is asleep. This is done by
- * %iwl_mvm_sta_modify_sleep_tx_count.
- * When we receive a frame from that station with PM bit unset, the
- * driver needs to let the fw know that this station isn't alseep any more.
- * This is done by %iwl_mvm_sta_modify_ps_wake.
- *
- * TODO - EOSP handling
+ *
+ * When a trigger frame is received, mac80211 tells the driver to send frames
+ * from the AMPDU queues or sends frames to non-aggregation queues itself,
+ * depending on which ACs are delivery-enabled and what TID has frames to
+ * transmit. Note that mac80211 has all the knowledege since all the non-agg
+ * frames are buffered / filtered, and the driver tells mac80211 about agg
+ * frames). The driver needs to tell the fw to let frames out even if the
+ * station is asleep. This is done by %iwl_mvm_sta_modify_sleep_tx_count.
+ *
+ * When we receive a frame from that station with PM bit unset, the driver
+ * needs to let the fw know that this station isn't asleep any more. This is
+ * done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signalling the
+ * station's wakeup.
+ *
+ * For a GO, the Service Period might be cut short due to an absence period
+ * of the GO. In this (and all other cases) the firmware notifies us with the
+ * EOSP_NOTIFICATION, and we notify mac80211 of that. Further frames that we
+ * already sent to the device will be rejected again.
+ *
+ * See also "AP support for powersaving clients" in mac80211.h.
  */
 
 /**
@@ -261,6 +270,12 @@ struct iwl_mvm_tid_data {
 	u16 ssn;
 };
 
+static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
+{
+	return ieee80211_sn_sub(IEEE80211_SEQ_TO_SN(tid_data->seq_number),
+				tid_data->next_reclaimed);
+}
+
 /**
  * struct iwl_mvm_sta - representation of a station in the driver
  * @sta_id: the index of the station in the fw (will be replaced by id_n_color)
@@ -269,7 +284,11 @@ struct iwl_mvm_tid_data {
  * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
  *	tid.
  * @max_agg_bufsize: the maximal size of the AGG buffer for this station
+ * @bt_reduced_txpower_dbg: debug mode in which %bt_reduced_txpower is forced
+ *	by debugfs.
  * @bt_reduced_txpower: is reduced tx power enabled for this station
+ * @next_status_eosp: the next reclaimed packet is a PS-Poll response and
+ *	we need to signal the EOSP
  * @lock: lock to protect the whole struct. Since %tid_data is access from Tx
  * and from Tx response flow, it needs a spinlock.
  * @tid_data: per tid data. Look at %iwl_mvm_tid_data.
@@ -287,7 +306,9 @@ struct iwl_mvm_sta {
 	u32 mac_id_n_color;
 	u16 tid_disable_agg;
 	u8 max_agg_bufsize;
+	bool bt_reduced_txpower_dbg;
 	bool bt_reduced_txpower;
+	bool next_status_eosp;
 	spinlock_t lock;
 	struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
 	struct iwl_lq_sta lq_sta;
@@ -345,6 +366,10 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
 			     struct ieee80211_sta *sta, u32 iv32,
 			     u16 *phase1key);
 
+int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
+			  struct iwl_rx_cmd_buffer *rxb,
+			  struct iwl_device_cmd *cmd);
+
 /* AMPDU */
 int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 		       int tid, u16 ssn, bool start);
@@ -359,7 +384,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
 int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
-			     u32 qmask);
+			     u32 qmask, enum nl80211_iftype iftype);
 void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm,
 			     struct iwl_mvm_int_sta *sta);
 int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -375,7 +400,8 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
 void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
 				       struct ieee80211_sta *sta,
 				       enum ieee80211_frame_release_type reason,
-				       u16 cnt);
+				       u16 cnt, u16 tids, bool more_data,
+				       bool agg);
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 		      bool drain);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index b4c2abaa297b..e145dd41e85e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -126,6 +126,7 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
 	 * in iwl_mvm_te_handle_notif).
 	 */
 	clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
+	iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
 
 	/*
 	 * Of course, our status bit is just as racy as mac80211, so in
@@ -210,6 +211,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
 
 		if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 			set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
+			iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
 			ieee80211_ready_on_channel(mvm->hw);
 		}
 	} else {
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 3afa6b6bf835..7a99fa361954 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -403,7 +403,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
 	}
 }
 
-static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
+void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
 {
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_THERMAL_MNG_BACKOFF,
@@ -412,6 +412,8 @@ static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
 		.flags = CMD_SYNC,
 	};
 
+	backoff = max(backoff, mvm->thermal_throttle.min_backoff);
+
 	if (iwl_mvm_send_cmd(mvm, &cmd) == 0) {
 		IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n",
 			       backoff);
@@ -534,7 +536,7 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
 	.support_tx_backoff = true,
 };
 
-void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
+void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff)
 {
 	struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
 
@@ -546,6 +548,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
 		tt->params = &iwl7000_tt_params;
 
 	tt->throttle = false;
+	tt->min_backoff = min_backoff;
 	INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
 }
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 4df12fa9d336..98096fa364cd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -377,6 +377,13 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
 	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
 	/* From now on, we cannot access info->control */
 
+	/*
+	 * we handle that entirely ourselves -- for uAPSD the firmware
+	 * will always send a notification, and for PS-Poll responses
+	 * we'll notify mac80211 when getting frame status
+	 */
+	info->flags &= ~IEEE80211_TX_STATUS_EOSP;
+
 	spin_lock(&mvmsta->lock);
 
 	if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
@@ -437,6 +444,17 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
 
 	lockdep_assert_held(&mvmsta->lock);
 
+	if ((tid_data->state == IWL_AGG_ON ||
+	     tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
+	    iwl_mvm_tid_queued(tid_data) == 0) {
+		/*
+		 * Now that this aggregation queue is empty tell mac80211 so it
+		 * knows we no longer have frames buffered for the station on
+		 * this TID (for the TIM bitmap calculation.)
+		 */
+		ieee80211_sta_set_buffered(sta, tid, false);
+	}
+
 	if (tid_data->ssn != tid_data->next_reclaimed)
 		return;
 
@@ -680,6 +698,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 			iwl_mvm_check_ratid_empty(mvm, sta, tid);
 			spin_unlock_bh(&mvmsta->lock);
 		}
+
+		if (mvmsta->next_status_eosp) {
+			mvmsta->next_status_eosp = false;
+			ieee80211_sta_eosp(sta);
+		}
 	} else {
 		mvmsta = NULL;
 	}
@@ -822,16 +845,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 	struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data;
 	struct sk_buff_head reclaimed_skbs;
 	struct iwl_mvm_tid_data *tid_data;
-	struct ieee80211_tx_info *info;
 	struct ieee80211_sta *sta;
 	struct iwl_mvm_sta *mvmsta;
-	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb;
 	int sta_id, tid, freed;
-
 	/* "flow" corresponds to Tx queue */
 	u16 scd_flow = le16_to_cpu(ba_notif->scd_flow);
-
 	/* "ssn" is start of block-ack Tx window, corresponds to index
 	 * (in Tx queue's circular buffer) of first TFD/frame in window */
 	u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn);
@@ -888,22 +907,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 	freed = 0;
 
 	skb_queue_walk(&reclaimed_skbs, skb) {
-		hdr = (struct ieee80211_hdr *)skb->data;
+		struct ieee80211_hdr *hdr = (void *)skb->data;
+		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 		if (ieee80211_is_data_qos(hdr->frame_control))
 			freed++;
 		else
 			WARN_ON_ONCE(1);
 
-		info = IEEE80211_SKB_CB(skb);
 		iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
 
+		memset(&info->status, 0, sizeof(info->status));
+		/* Packet was transmitted successfully, failures come as single
+		 * frames because before failing a frame the firmware transmits
+		 * it without aggregation at least once.
+		 */
+		info->flags |= IEEE80211_TX_STAT_ACK;
+
 		if (freed == 1) {
 			/* this is the first skb we deliver in this batch */
 			/* put the rate scaling data there */
-			info = IEEE80211_SKB_CB(skb);
-			memset(&info->status, 0, sizeof(info->status));
-			info->flags |= IEEE80211_TX_STAT_ACK;
 			info->flags |= IEEE80211_TX_STAT_AMPDU;
 			info->status.ampdu_ack_len = ba_notif->txed_2_done;
 			info->status.ampdu_len = ba_notif->txed;
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 86989df69356..1493f79e67e0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -376,9 +376,67 @@ struct iwl_error_event_table {
 	u32 flow_handler;	/* FH read/write pointers, RX credit */
 } __packed;
 
+/*
+ * UMAC error struct - relevant starting from family 8000 chip.
+ * Note: This structure is read from the device with IO accesses,
+ * and the reading already does the endian conversion. As it is
+ * read with u32-sized accesses, any members with a different size
+ * need to be ordered correctly though!
+ */
+struct iwl_umac_error_event_table {
+	u32 valid;		/* (nonzero) valid, (0) log is empty */
+	u32 error_id;		/* type of error */
+	u32 pc;			/* program counter */
+	u32 blink1;		/* branch link */
+	u32 blink2;		/* branch link */
+	u32 ilink1;		/* interrupt link */
+	u32 ilink2;		/* interrupt link */
+	u32 data1;		/* error-specific data */
+	u32 data2;		/* error-specific data */
+	u32 line;		/* source code line of error */
+	u32 umac_ver;		/* umac version */
+} __packed;
+
 #define ERROR_START_OFFSET  (1 * sizeof(u32))
 #define ERROR_ELEM_SIZE     (7 * sizeof(u32))
 
+static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
+{
+	struct iwl_trans *trans = mvm->trans;
+	struct iwl_umac_error_event_table table;
+	u32 base;
+
+	base = mvm->umac_error_event_table;
+
+	if (base < 0x800000 || base >= 0x80C000) {
+		IWL_ERR(mvm,
+			"Not valid error log pointer 0x%08X for %s uCode\n",
+			base,
+			(mvm->cur_ucode == IWL_UCODE_INIT)
+					? "Init" : "RT");
+		return;
+	}
+
+	iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
+
+	if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
+		IWL_ERR(trans, "Start IWL Error Log Dump:\n");
+		IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
+			mvm->status, table.valid);
+	}
+
+	IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id,
+		desc_lookup(table.error_id));
+	IWL_ERR(mvm, "0x%08X | umac uPc\n", table.pc);
+	IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1);
+	IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2);
+	IWL_ERR(mvm, "0x%08X | umac interruptlink1\n", table.ilink1);
+	IWL_ERR(mvm, "0x%08X | umac interruptlink2\n", table.ilink2);
+	IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1);
+	IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2);
+	IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_ver);
+}
+
 void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 {
 	struct iwl_trans *trans = mvm->trans;
@@ -394,7 +452,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 			base = mvm->fw->inst_errlog_ptr;
 	}
 
-	if (base < 0x800000 || base >= 0x80C000) {
+	if (base < 0x800000) {
 		IWL_ERR(mvm,
 			"Not valid error log pointer 0x%08X for %s uCode\n",
 			base,
@@ -453,13 +511,17 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 	IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
 	IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp);
 	IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
+
+	if (mvm->support_umac_log)
+		iwl_mvm_dump_umac_error_log(mvm);
 }
 
 void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
 {
 	const struct fw_img *img;
 	int ofs, len = 0;
-	u8 *buf;
+	int i;
+	__le32 *buf;
 
 	if (!mvm->ucode_loaded)
 		return;
@@ -473,7 +535,12 @@ void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
 		return;
 
 	iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len);
-	iwl_print_hex_error(mvm->trans, buf, len);
+	len = len >> 2;
+	for (i = 0; i < len; i++) {
+		IWL_ERR(mvm, "0x%08X\n", le32_to_cpu(buf[i]));
+		/* Add a small delay to let syslog catch up */
+		udelay(10);
+	}
 
 	kfree(buf);
 }
@@ -516,7 +583,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			 enum ieee80211_smps_mode smps_request)
 {
 	struct iwl_mvm_vif *mvmvif;
-	enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
+	enum ieee80211_smps_mode smps_mode;
 	int i;
 
 	lockdep_assert_held(&mvm->mutex);
@@ -525,6 +592,11 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1)
 		return;
 
+	if (vif->type == NL80211_IFTYPE_AP)
+		smps_mode = IEEE80211_SMPS_OFF;
+	else
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
 	mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	mvmvif->smps_requests[req_type] = smps_request;
 	for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
@@ -538,3 +610,22 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 	ieee80211_request_smps(vif, smps_mode);
 }
+
+int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			       bool value)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	int res;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	mvmvif->low_latency = value;
+
+	res = iwl_mvm_update_quotas(mvm, NULL);
+	if (res)
+		return res;
+
+	iwl_mvm_bt_coex_vif_change(mvm);
+
+	return iwl_mvm_power_update_mac(mvm, vif);
+}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index f47bcbe2945a..0f52e961a5a5 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -66,6 +66,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/pci-aspm.h>
+#include <linux/acpi.h>
 
 #include "iwl-trans.h"
 #include "iwl-drv.h"
@@ -390,12 +391,91 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
+
+/* 8000 Series */
+	{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
 	{0}
 };
 MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 
+#ifdef CONFIG_ACPI
+#define SPL_METHOD		"SPLC"
+#define SPL_DOMAINTYPE_MODULE	BIT(0)
+#define SPL_DOMAINTYPE_WIFI	BIT(1)
+#define SPL_DOMAINTYPE_WIGIG	BIT(2)
+#define SPL_DOMAINTYPE_RFEM	BIT(3)
+
+static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
+{
+	union acpi_object *limits, *domain_type, *power_limit;
+
+	if (splx->type != ACPI_TYPE_PACKAGE ||
+	    splx->package.count != 2 ||
+	    splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    splx->package.elements[0].integer.value != 0) {
+		IWL_ERR(trans, "Unsupported splx structure");
+		return 0;
+	}
+
+	limits = &splx->package.elements[1];
+	if (limits->type != ACPI_TYPE_PACKAGE ||
+	    limits->package.count < 2 ||
+	    limits->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    limits->package.elements[1].type != ACPI_TYPE_INTEGER) {
+		IWL_ERR(trans, "Invalid limits element");
+		return 0;
+	}
+
+	domain_type = &limits->package.elements[0];
+	power_limit = &limits->package.elements[1];
+	if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {
+		IWL_DEBUG_INFO(trans, "WiFi power is not limited");
+		return 0;
+	}
+
+	return power_limit->integer.value;
+}
+
+static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
+{
+	acpi_handle pxsx_handle;
+	acpi_handle handle;
+	struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_status status;
+
+	pxsx_handle = ACPI_HANDLE(&pdev->dev);
+	if (!pxsx_handle) {
+		IWL_ERR(trans, "Could not retrieve root port ACPI handle");
+		return;
+	}
+
+	/* Get the method's handle */
+	status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);
+	if (ACPI_FAILURE(status)) {
+		IWL_DEBUG_INFO(trans, "SPL method not found");
+		return;
+	}
+
+	/* Call SPLC with no arguments */
+	status = acpi_evaluate_object(handle, NULL, NULL, &splx);
+	if (ACPI_FAILURE(status)) {
+		IWL_ERR(trans, "SPLC invocation failed (0x%x)", status);
+		return;
+	}
+
+	trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);
+	IWL_DEBUG_INFO(trans, "Default power limit set to %lld",
+		       trans->dflt_pwr_limit);
+	kfree(splx.pointer);
+}
+
+#else /* CONFIG_ACPI */
+static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) {}
+#endif
+
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT	0x041
 
@@ -420,6 +500,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto out_free_trans;
 	}
 
+	set_dflt_pwr_limit(iwl_trans, pdev);
+
 	/* register transport layer debugfs here */
 	ret = iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir);
 	if (ret)
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 08c23d497a02..41f684deff97 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -802,10 +802,9 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 
 static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
 
-	lockdep_assert_held(&trans_pcie->irq_lock);
+	lockdep_assert_held(&IWL_TRANS_GET_PCIE_TRANS(trans)->irq_lock);
 
 	trace_iwlwifi_dev_irq(trans->dev);
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index f9507807b486..84d471299e5a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -89,6 +89,7 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
 
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT	0x041
+#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
 
 static void iwl_pcie_apm_config(struct iwl_trans *trans)
 {
@@ -132,8 +133,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
 	 */
 
 	/* Disable L0S exit timer (platform NMI Work/Around) */
-	iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
-		    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+	if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
+			    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
 
 	/*
 	 * Disable L0s without affecting L1;
@@ -203,19 +205,23 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
 	/*
 	 * Enable DMA clock and wait for it to stabilize.
 	 *
-	 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
-	 * do not disable clocks.  This preserves any hardware bits already
-	 * set by default in "CLK_CTRL_REG" after reset.
+	 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0"
+	 * bits do not disable clocks.  This preserves any hardware
+	 * bits already set by default in "CLK_CTRL_REG" after reset.
 	 */
-	iwl_write_prph(trans, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-	udelay(20);
+	if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+		iwl_write_prph(trans, APMG_CLK_EN_REG,
+			       APMG_CLK_VAL_DMA_CLK_RQT);
+		udelay(20);
 
-	/* Disable L1-Active */
-	iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
-			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+		/* Disable L1-Active */
+		iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
+				  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	/* Clear the interrupt in APMG if the NIC is in RFKILL */
-	iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL);
+		/* Clear the interrupt in APMG if the NIC is in RFKILL */
+		iwl_write_prph(trans, APMG_RTC_INT_STT_REG,
+			       APMG_RTC_INT_STT_RFKILL);
+	}
 
 	set_bit(STATUS_DEVICE_ENABLED, &trans->status);
 
@@ -273,7 +279,8 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
 
 	spin_unlock(&trans_pcie->irq_lock);
 
-	iwl_pcie_set_pwr(trans, false);
+	if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		iwl_pcie_set_pwr(trans, false);
 
 	iwl_op_mode_nic_config(trans->op_mode);
 
@@ -435,78 +442,106 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
 	return ret;
 }
 
-static int iwl_pcie_secure_set(struct iwl_trans *trans, int cpu)
+static int iwl_pcie_load_cpu_secured_sections(struct iwl_trans *trans,
+					      const struct fw_img *image,
+					      int cpu,
+					      int *first_ucode_section)
 {
 	int shift_param;
-	u32 address;
-	int ret = 0;
+	int i, ret = 0;
+	u32 last_read_idx = 0;
 
 	if (cpu == 1) {
 		shift_param = 0;
-		address = CSR_SECURE_BOOT_CPU1_STATUS_ADDR;
+		*first_ucode_section = 0;
 	} else {
 		shift_param = 16;
-		address = CSR_SECURE_BOOT_CPU2_STATUS_ADDR;
+		(*first_ucode_section)++;
 	}
 
-	/* set CPU to started */
-	iwl_trans_set_bits_mask(trans,
-				CSR_UCODE_LOAD_STATUS_ADDR,
-				CSR_CPU_STATUS_LOADING_STARTED << shift_param,
-				1);
-
-	/* set last complete descriptor number */
-	iwl_trans_set_bits_mask(trans,
-				CSR_UCODE_LOAD_STATUS_ADDR,
-				CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED
-				<< shift_param,
-				1);
-
-	/* set last loaded block */
-	iwl_trans_set_bits_mask(trans,
-				CSR_UCODE_LOAD_STATUS_ADDR,
-				CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK
-				<< shift_param,
-				1);
+	for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) {
+		last_read_idx = i;
+
+		if (!image->sec[i].data ||
+		    image->sec[i].offset == CPU1_CPU2_SEPARATOR_SECTION) {
+			IWL_DEBUG_FW(trans,
+				     "Break since Data not valid or Empty section, sec = %d\n",
+				     i);
+			break;
+		}
+
+		if (i == (*first_ucode_section) + 1)
+			/* set CPU to started */
+			iwl_set_bits_prph(trans,
+					  CSR_UCODE_LOAD_STATUS_ADDR,
+					  LMPM_CPU_HDRS_LOADING_COMPLETED
+					  << shift_param);
 
+		ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
+		if (ret)
+			return ret;
+	}
 	/* image loading complete */
-	iwl_trans_set_bits_mask(trans,
-				CSR_UCODE_LOAD_STATUS_ADDR,
-				CSR_CPU_STATUS_LOADING_COMPLETED
-				<< shift_param,
-				1);
-
-	/* set FH_TCSR_0_REG  */
-	iwl_trans_set_bits_mask(trans, FH_TCSR_0_REG0, 0x00400000, 1);
-
-	/* verify image verification started  */
-	ret = iwl_poll_bit(trans, address,
-			   CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS,
-			   CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS,
-			   CSR_SECURE_TIME_OUT);
-	if (ret < 0) {
-		IWL_ERR(trans, "secure boot process didn't start\n");
-		return ret;
+	iwl_set_bits_prph(trans,
+			  CSR_UCODE_LOAD_STATUS_ADDR,
+			  LMPM_CPU_UCODE_LOADING_COMPLETED << shift_param);
+
+	*first_ucode_section = last_read_idx;
+
+	return 0;
+}
+
+static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
+				      const struct fw_img *image,
+				      int cpu,
+				      int *first_ucode_section)
+{
+	int shift_param;
+	int i, ret = 0;
+	u32 last_read_idx = 0;
+
+	if (cpu == 1) {
+		shift_param = 0;
+		*first_ucode_section = 0;
+	} else {
+		shift_param = 16;
+		(*first_ucode_section)++;
 	}
 
-	/* wait for image verification to complete  */
-	ret = iwl_poll_bit(trans, address,
-			   CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED,
-			   CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED,
-			   CSR_SECURE_TIME_OUT);
+	for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) {
+		last_read_idx = i;
 
-	if (ret < 0) {
-		IWL_ERR(trans, "Time out on secure boot process\n");
-		return ret;
+		if (!image->sec[i].data ||
+		    image->sec[i].offset == CPU1_CPU2_SEPARATOR_SECTION) {
+			IWL_DEBUG_FW(trans,
+				     "Break since Data not valid or Empty section, sec = %d\n",
+				     i);
+			break;
+		}
+
+		ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
+		if (ret)
+			return ret;
 	}
 
+	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+		iwl_set_bits_prph(trans,
+				  CSR_UCODE_LOAD_STATUS_ADDR,
+				  (LMPM_CPU_UCODE_LOADING_COMPLETED |
+				   LMPM_CPU_HDRS_LOADING_COMPLETED |
+				   LMPM_CPU_UCODE_LOADING_STARTED) <<
+					shift_param);
+
+	*first_ucode_section = last_read_idx;
+
 	return 0;
 }
 
 static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 				const struct fw_img *image)
 {
-	int i, ret = 0;
+	int ret = 0;
+	int first_ucode_section;
 
 	IWL_DEBUG_FW(trans,
 		     "working with %s image\n",
@@ -518,53 +553,68 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 	/* configure the ucode to be ready to get the secured image */
 	if (image->is_secure) {
 		/* set secure boot inspector addresses */
-		iwl_write32(trans, CSR_SECURE_INSPECTOR_CODE_ADDR, 0);
-		iwl_write32(trans, CSR_SECURE_INSPECTOR_DATA_ADDR, 0);
-
-		/* release CPU1 reset if secure inspector image burned in OTP */
-		iwl_write32(trans, CSR_RESET, 0);
-	}
-
-	/* load to FW the binary sections of CPU1 */
-	IWL_DEBUG_INFO(trans, "Loading CPU1\n");
-	for (i = 0;
-	     i < IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU;
-	     i++) {
-		if (!image->sec[i].data)
-			break;
-		ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
+		iwl_write_prph(trans,
+			       LMPM_SECURE_INSPECTOR_CODE_ADDR,
+			       LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE);
+
+		iwl_write_prph(trans,
+			       LMPM_SECURE_INSPECTOR_DATA_ADDR,
+			       LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE);
+
+		/* set CPU1 header address */
+		iwl_write_prph(trans,
+			       LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR,
+			       LMPM_SECURE_CPU1_HDR_MEM_SPACE);
+
+		/* load to FW the binary Secured sections of CPU1 */
+		ret = iwl_pcie_load_cpu_secured_sections(trans, image, 1,
+							 &first_ucode_section);
 		if (ret)
 			return ret;
-	}
 
-	/* configure the ucode to start secure process on CPU1 */
-	if (image->is_secure) {
-		/* config CPU1 to start secure protocol */
-		ret = iwl_pcie_secure_set(trans, 1);
+	} else {
+		/* load to FW the binary Non secured sections of CPU1 */
+		ret = iwl_pcie_load_cpu_sections(trans, image, 1,
+						 &first_ucode_section);
 		if (ret)
 			return ret;
-	} else {
-		/* Remove all resets to allow NIC to operate */
-		iwl_write32(trans, CSR_RESET, 0);
 	}
 
 	if (image->is_dual_cpus) {
+		/* set CPU2 header address */
+		iwl_write_prph(trans,
+			       LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR,
+			       LMPM_SECURE_CPU2_HDR_MEM_SPACE);
+
 		/* load to FW the binary sections of CPU2 */
-		IWL_DEBUG_INFO(trans, "working w/ DUAL CPUs - Loading CPU2\n");
-		for (i = IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU;
-			i < IWL_UCODE_SECTION_MAX; i++) {
-			if (!image->sec[i].data)
-				break;
-			ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
-			if (ret)
-				return ret;
-		}
+		if (image->is_secure)
+			ret = iwl_pcie_load_cpu_secured_sections(
+							trans, image, 2,
+							&first_ucode_section);
+		else
+			ret = iwl_pcie_load_cpu_sections(trans, image, 2,
+							 &first_ucode_section);
+		if (ret)
+			return ret;
+	}
 
-		if (image->is_secure) {
-			/* set CPU2 for secure protocol */
-			ret = iwl_pcie_secure_set(trans, 2);
-			if (ret)
-				return ret;
+	/* release CPU reset */
+	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+		iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
+	else
+		iwl_write32(trans, CSR_RESET, 0);
+
+	if (image->is_secure) {
+		/* wait for image verification to complete  */
+		ret = iwl_poll_prph_bit(trans,
+					LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
+					LMPM_SECURE_BOOT_STATUS_SUCCESS,
+					LMPM_SECURE_BOOT_STATUS_SUCCESS,
+					LMPM_SECURE_TIME_OUT);
+
+		if (ret < 0) {
+			IWL_ERR(trans, "Time out on secure boot process\n");
+			return ret;
 		}
 	}
 
@@ -1407,16 +1457,15 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
 {
 	struct iwl_trans *trans = file->private_data;
 	char *buf = NULL;
-	int pos = 0;
-	ssize_t ret = -EFAULT;
-
-	ret = pos = iwl_dump_fh(trans, &buf);
-	if (buf) {
-		ret = simple_read_from_buffer(user_buf,
-					      count, ppos, buf, pos);
-		kfree(buf);
-	}
+	ssize_t ret;
 
+	ret = iwl_dump_fh(trans, &buf);
+	if (ret < 0)
+		return ret;
+	if (!buf)
+		return -EINVAL;
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+	kfree(buf);
 	return ret;
 }
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 3d549008b3e2..254126447c68 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -705,8 +705,9 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
 			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
 
 	/* Enable L1-Active */
-	iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
-			    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+	if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
+				    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 }
 
 void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 32f75007a825..54e344aed6e0 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -621,7 +621,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
 			id = *pos++;
 			elen = *pos++;
 			left -= 2;
-			if (elen > left || elen == 0) {
+			if (elen > left) {
 				lbs_deb_scan("scan response: invalid IE fmt\n");
 				goto done;
 			}
@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_private *priv,
 	memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
 	priv->wdev->ssid_len = params->ssid_len;
 
-	cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
+	cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
+			     GFP_KERNEL);
 
 	/* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
 	priv->connect_status = LBS_CONNECTED;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 69d4c3179d04..f7e3562542fe 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -57,6 +57,10 @@ static bool rctbl = false;
 module_param(rctbl, bool, 0444);
 MODULE_PARM_DESC(rctbl, "Handle rate control table");
 
+static bool support_p2p_device = true;
+module_param(support_p2p_device, bool, 0444);
+MODULE_PARM_DESC(support_p2p_device, "Support P2P-Device interface type");
+
 /**
  * enum hwsim_regtest - the type of regulatory tests we offer
  *
@@ -335,7 +339,8 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
 #endif
 				 BIT(NL80211_IFTYPE_AP) |
 				 BIT(NL80211_IFTYPE_P2P_GO) },
-	{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
+	/* must be last, see hwsim_if_comb */
+	{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }
 };
 
 static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
@@ -345,6 +350,27 @@ static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
 static const struct ieee80211_iface_combination hwsim_if_comb[] = {
 	{
 		.limits = hwsim_if_limits,
+		/* remove the last entry which is P2P_DEVICE */
+		.n_limits = ARRAY_SIZE(hwsim_if_limits) - 1,
+		.max_interfaces = 2048,
+		.num_different_channels = 1,
+	},
+	{
+		.limits = hwsim_if_dfs_limits,
+		.n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
+		.max_interfaces = 8,
+		.num_different_channels = 1,
+		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+				       BIT(NL80211_CHAN_WIDTH_20) |
+				       BIT(NL80211_CHAN_WIDTH_40) |
+				       BIT(NL80211_CHAN_WIDTH_80) |
+				       BIT(NL80211_CHAN_WIDTH_160),
+	}
+};
+
+static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
+	{
+		.limits = hwsim_if_limits,
 		.n_limits = ARRAY_SIZE(hwsim_if_limits),
 		.max_interfaces = 2048,
 		.num_different_channels = 1,
@@ -451,7 +477,7 @@ static struct genl_family hwsim_genl_family = {
 
 /* MAC80211_HWSIM netlink policy */
 
-static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
+static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
 	[HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
 	[HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
 	[HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
@@ -468,6 +494,7 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
 	[HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 },
 	[HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 },
 	[HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG },
+	[HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG },
 };
 
 static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
@@ -1035,32 +1062,6 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 			ack = true;
 
 		rx_status.mactime = now + data2->tsf_offset;
-#if 0
-		/*
-		 * Don't enable this code by default as the OUI 00:00:00
-		 * is registered to Xerox so we shouldn't use it here, it
-		 * might find its way into pcap files.
-		 * Note that this code requires the headroom in the SKB
-		 * that was allocated earlier.
-		 */
-		rx_status.vendor_radiotap_oui[0] = 0x00;
-		rx_status.vendor_radiotap_oui[1] = 0x00;
-		rx_status.vendor_radiotap_oui[2] = 0x00;
-		rx_status.vendor_radiotap_subns = 127;
-		/*
-		 * Radiotap vendor namespaces can (and should) also be
-		 * split into fields by using the standard radiotap
-		 * presence bitmap mechanism. Use just BIT(0) here for
-		 * the presence bitmap.
-		 */
-		rx_status.vendor_radiotap_bitmap = BIT(0);
-		/* We have 8 bytes of (dummy) data */
-		rx_status.vendor_radiotap_len = 8;
-		/* For testing, also require it to be aligned */
-		rx_status.vendor_radiotap_align = 8;
-		/* push the data */
-		memcpy(skb_push(nskb, 8), "ABCDEFGH", 8);
-#endif
 
 		memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
 		ieee80211_rx_irqsafe(data2->hw, nskb);
@@ -1275,6 +1276,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
 
 	mac80211_hwsim_tx_frame(hw, skb,
 				rcu_dereference(vif->chanctx_conf)->def.chan);
+
+	if (vif->csa_active && ieee80211_csa_is_complete(vif))
+		ieee80211_csa_finish(vif);
 }
 
 static enum hrtimer_restart
@@ -1936,7 +1940,7 @@ static struct ieee80211_ops mac80211_hwsim_mchan_ops;
 
 static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
 				       const struct ieee80211_regdomain *regd,
-				       bool reg_strict)
+				       bool reg_strict, bool p2p_device)
 {
 	int err;
 	u8 addr[ETH_ALEN];
@@ -2000,8 +2004,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
 		/* For channels > 1 DFS is not allowed */
 		hw->wiphy->n_iface_combinations = 1;
 		hw->wiphy->iface_combinations = &data->if_combination;
-		data->if_combination = hwsim_if_comb[0];
 		data->if_combination.num_different_channels = data->channels;
+		if (p2p_device)
+			data->if_combination = hwsim_if_comb_p2p_dev[0];
+		else
+			data->if_combination = hwsim_if_comb[0];
+	} else if (p2p_device) {
+		hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
+		hw->wiphy->n_iface_combinations =
+			ARRAY_SIZE(hwsim_if_comb_p2p_dev);
 	} else {
 		hw->wiphy->iface_combinations = hwsim_if_comb;
 		hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
@@ -2017,8 +2028,10 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
 				     BIT(NL80211_IFTYPE_P2P_CLIENT) |
 				     BIT(NL80211_IFTYPE_P2P_GO) |
 				     BIT(NL80211_IFTYPE_ADHOC) |
-				     BIT(NL80211_IFTYPE_MESH_POINT) |
-				     BIT(NL80211_IFTYPE_P2P_DEVICE);
+				     BIT(NL80211_IFTYPE_MESH_POINT);
+
+	if (p2p_device)
+		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
 
 	hw->flags = IEEE80211_HW_MFP_CAPABLE |
 		    IEEE80211_HW_SIGNAL_DBM |
@@ -2027,13 +2040,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_WANT_MONITOR_VIF |
 		    IEEE80211_HW_QUEUE_CONTROL |
-		    IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
+		    IEEE80211_HW_SUPPORTS_HT_CCK_RATES |
+		    IEEE80211_HW_CHANCTX_STA_CSA;
 	if (rctbl)
 		hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
 
 	hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
 			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
-			    WIPHY_FLAG_AP_UAPSD;
+			    WIPHY_FLAG_AP_UAPSD |
+			    WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 	hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
 
 	/* ask mac80211 to reserve space for magic */
@@ -2407,6 +2422,7 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
 	const char *alpha2 = NULL;
 	const struct ieee80211_regdomain *regd = NULL;
 	bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
+	bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
 
 	if (info->attrs[HWSIM_ATTR_CHANNELS])
 		chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
@@ -2422,7 +2438,8 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
 		regd = hwsim_world_regdom_custom[idx];
 	}
 
-	return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict);
+	return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict,
+					   p2p_device);
 }
 
 static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info)
@@ -2640,7 +2657,8 @@ static int __init init_mac80211_hwsim(void)
 		}
 
 		err = mac80211_hwsim_create_radio(channels, reg_alpha2,
-						  regd, reg_strict);
+						  regd, reg_strict,
+						  support_p2p_device);
 		if (err < 0)
 			goto out_free_radios;
 	}
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index 2747cce5a269..6e72996ec8c1 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -107,6 +107,7 @@ enum {
  *	(nla string, length 2)
  * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute)
  * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute)
+ * @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag)
  * @__HWSIM_ATTR_MAX: enum limit
  */
 
@@ -126,6 +127,7 @@ enum {
 	HWSIM_ATTR_REG_HINT_ALPHA2,
 	HWSIM_ATTR_REG_CUSTOM_REG,
 	HWSIM_ATTR_REG_STRICT_REG,
+	HWSIM_ATTR_SUPPORT_P2P_DEVICE,
 	__HWSIM_ATTR_MAX,
 };
 #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
index 5e0eec4d71c7..bb43251c18f2 100644
--- a/drivers/net/wireless/mwifiex/11ac.c
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -23,6 +23,31 @@
 #include "main.h"
 #include "11ac.h"
 
+/* Tables of the MCS map to the highest data rate (in Mbps) supported
+ * for long GI.
+ */
+static const u16 max_rate_lgi_80MHZ[8][3] = {
+	{0x124, 0x15F, 0x186},	/* NSS = 1 */
+	{0x249, 0x2BE, 0x30C},  /* NSS = 2 */
+	{0x36D, 0x41D, 0x492},  /* NSS = 3 */
+	{0x492, 0x57C, 0x618},  /* NSS = 4 */
+	{0x5B6, 0x6DB, 0x79E},  /* NSS = 5 */
+	{0x6DB, 0x83A, 0x0},    /* NSS = 6 */
+	{0x7FF, 0x999, 0xAAA},  /* NSS = 7 */
+	{0x924, 0xAF8, 0xC30}   /* NSS = 8 */
+};
+
+static const u16 max_rate_lgi_160MHZ[8][3] = {
+	{0x249, 0x2BE, 0x30C},   /* NSS = 1 */
+	{0x492, 0x57C, 0x618},   /* NSS = 2 */
+	{0x6DB, 0x83A, 0x0},     /* NSS = 3 */
+	{0x924, 0xAF8, 0xC30},   /* NSS = 4 */
+	{0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
+	{0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
+	{0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
+	{0x1248, 0x15F0, 0x1860} /* NSS = 8 */
+};
+
 /* This function converts the 2-bit MCS map to the highest long GI
  * VHT data rate.
  */
@@ -30,33 +55,10 @@ static u16
 mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
 				  u8 bands, u16 mcs_map)
 {
-	u8 i, nss, max_mcs;
+	u8 i, nss, mcs;
 	u16 max_rate = 0;
 	u32 usr_vht_cap_info = 0;
 	struct mwifiex_adapter *adapter = priv->adapter;
-	/* tables of the MCS map to the highest data rate (in Mbps)
-	 * supported for long GI
-	 */
-	u16 max_rate_lgi_80MHZ[8][3] = {
-		{0x124, 0x15F, 0x186},	/* NSS = 1 */
-		{0x249, 0x2BE, 0x30C},  /* NSS = 2 */
-		{0x36D, 0x41D, 0x492},  /* NSS = 3 */
-		{0x492, 0x57C, 0x618},  /* NSS = 4 */
-		{0x5B6, 0x6DB, 0x79E},  /* NSS = 5 */
-		{0x6DB, 0x83A, 0x0},    /* NSS = 6 */
-		{0x7FF, 0x999, 0xAAA},  /* NSS = 7 */
-		{0x924, 0xAF8, 0xC30}   /* NSS = 8 */
-	};
-	u16 max_rate_lgi_160MHZ[8][3] = {
-		{0x249, 0x2BE, 0x30C},   /* NSS = 1 */
-		{0x492, 0x57C, 0x618},   /* NSS = 2 */
-		{0x6DB, 0x83A, 0x0},     /* NSS = 3 */
-		{0x924, 0xAF8, 0xC30},   /* NSS = 4 */
-		{0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
-		{0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
-		{0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
-		{0x1248, 0x15F0, 0x1860} /* NSS = 8 */
-	};
 
 	if (bands & BAND_AAC)
 		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
@@ -64,29 +66,29 @@ mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
 		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
 
 	/* find the max NSS supported */
-	nss = 0;
-	for (i = 0; i < 8; i++) {
-		max_mcs = (mcs_map >> (2 * i)) & 0x3;
-		if (max_mcs < 3)
+	nss = 1;
+	for (i = 1; i <= 8; i++) {
+		mcs = GET_VHTNSSMCS(mcs_map, i);
+		if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED)
 			nss = i;
 	}
-	max_mcs = (mcs_map >> (2 * nss)) & 0x3;
+	mcs = GET_VHTNSSMCS(mcs_map, nss);
 
-	/* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */
-	if (max_mcs >= 3)
-		max_mcs = 2;
+	/* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */
+	if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+		mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
 
 	if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
 		/* support 160 MHz */
-		max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
+		max_rate = max_rate_lgi_160MHZ[nss - 1][mcs];
 		if (!max_rate)
 			/* MCS9 is not supported in NSS6 */
-			max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1];
+			max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1];
 	} else {
-		max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
+		max_rate = max_rate_lgi_80MHZ[nss - 1][mcs];
 		if (!max_rate)
 			/* MCS9 is not supported in NSS3 */
-			max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1];
+			max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1];
 	}
 
 	return max_rate;
@@ -94,21 +96,20 @@ mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
 
 static void
 mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
-			  struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
+			  struct ieee80211_vht_cap *vht_cap, u8 bands)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 
 	if (bands & BAND_A)
-		vht_cap->vht_cap.vht_cap_info =
+		vht_cap->vht_cap_info =
 				cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
 	else
-		vht_cap->vht_cap.vht_cap_info =
+		vht_cap->vht_cap_info =
 				cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
 }
 
-static void
-mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
-			 struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
+void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
+			      struct ieee80211_vht_cap *vht_cap, u8 bands)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	u16 mcs_map_user, mcs_map_resp, mcs_map_result;
@@ -119,46 +120,48 @@ mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
 
 	/* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
 	mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
-	mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.rx_mcs_map);
+	mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
 	mcs_map_result = 0;
 
 	for (nss = 1; nss <= 8; nss++) {
 		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
 		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
 
-		if ((mcs_user == NO_NSS_SUPPORT) ||
-		    (mcs_resp == NO_NSS_SUPPORT))
-			SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+		if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+		    (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      IEEE80211_VHT_MCS_NOT_SUPPORTED);
 		else
 			SET_VHTNSSMCS(mcs_map_result, nss,
 				      min(mcs_user, mcs_resp));
 	}
 
-	vht_cap->vht_cap.supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
+	vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
 
 	tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
-	vht_cap->vht_cap.supp_mcs.rx_highest = cpu_to_le16(tmp);
+	vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp);
 
 	/* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
 	mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
-	mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.tx_mcs_map);
+	mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
 	mcs_map_result = 0;
 
 	for (nss = 1; nss <= 8; nss++) {
 		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
 		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
-		if ((mcs_user == NO_NSS_SUPPORT) ||
-		    (mcs_resp == NO_NSS_SUPPORT))
-			SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+		if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+		    (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      IEEE80211_VHT_MCS_NOT_SUPPORTED);
 		else
 			SET_VHTNSSMCS(mcs_map_result, nss,
 				      min(mcs_user, mcs_resp));
 	}
 
-	vht_cap->vht_cap.supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
+	vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
 
 	tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
-	vht_cap->vht_cap.supp_mcs.tx_highest = cpu_to_le16(tmp);
+	vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp);
 
 	return;
 }
@@ -193,7 +196,8 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
 		       sizeof(struct ieee_types_header),
 		       le16_to_cpu(vht_cap->header.len));
 
-		mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band);
+		mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap,
+					 bss_desc->bss_band);
 		*buffer += sizeof(*vht_cap);
 		ret_len += sizeof(*vht_cap);
 	}
@@ -300,3 +304,81 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
 
 	return;
 }
+
+bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv)
+{
+	struct mwifiex_bssdescriptor *bss_desc;
+	struct ieee80211_vht_operation *vht_oper;
+
+	bss_desc = &priv->curr_bss_params.bss_descriptor;
+	vht_oper = bss_desc->bcn_vht_oper;
+
+	if (!bss_desc->bcn_vht_cap || !vht_oper)
+		return false;
+
+	if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT)
+		return false;
+
+	return true;
+}
+
+u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
+				 u32 pri_chan, u8 chan_bw)
+{
+	u8 center_freq_idx = 0;
+
+	if (band & BAND_AAC) {
+		switch (pri_chan) {
+		case 36:
+		case 40:
+		case 44:
+		case 48:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 42;
+			break;
+		case 52:
+		case 56:
+		case 60:
+		case 64:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 58;
+			else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
+				center_freq_idx = 50;
+			break;
+		case 100:
+		case 104:
+		case 108:
+		case 112:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 106;
+			break;
+		case 116:
+		case 120:
+		case 124:
+		case 128:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 122;
+			else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
+				center_freq_idx = 114;
+			break;
+		case 132:
+		case 136:
+		case 140:
+		case 144:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 138;
+			break;
+		case 149:
+		case 153:
+		case 157:
+		case 161:
+			if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
+				center_freq_idx = 155;
+			break;
+		default:
+			center_freq_idx = 42;
+		}
+	}
+
+	return center_freq_idx;
+}
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h
index 7c2c69b5b3eb..0b02cb6cfcb4 100644
--- a/drivers/net/wireless/mwifiex/11ac.h
+++ b/drivers/net/wireless/mwifiex/11ac.h
@@ -40,4 +40,6 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
 int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
 			 struct host_cmd_ds_command *cmd, u16 cmd_action,
 			 struct mwifiex_11ac_vht_cfg *cfg);
+void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
+			      struct ieee80211_vht_cap *vht_cap, u8 bands);
 #endif /* _MWIFIEX_11AC_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 6261f8c53d44..37677af8d2fc 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -34,22 +34,26 @@
  *
  * RD responder bit to set to clear in the extended capability header.
  */
-void
-mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
-		      struct mwifiex_ie_types_htcap *ht_cap)
+int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
+			  struct ieee80211_ht_cap *ht_cap)
 {
-	uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info);
+	uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info);
 	struct ieee80211_supported_band *sband =
 					priv->wdev->wiphy->bands[radio_type];
 
-	ht_cap->ht_cap.ampdu_params_info =
+	if (WARN_ON_ONCE(!sband)) {
+		dev_err(priv->adapter->dev, "Invalid radio type!\n");
+		return -EINVAL;
+	}
+
+	ht_cap->ampdu_params_info =
 		(sband->ht_cap.ampdu_factor &
 		 IEEE80211_HT_AMPDU_PARM_FACTOR) |
 		((sband->ht_cap.ampdu_density <<
 		 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) &
 		 IEEE80211_HT_AMPDU_PARM_DENSITY);
 
-	memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs,
+	memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs,
 	       sizeof(sband->ht_cap.mcs));
 
 	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
@@ -57,13 +61,18 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
 	     (priv->adapter->sec_chan_offset !=
 					IEEE80211_HT_PARAM_CHA_SEC_NONE)))
 		/* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
-		SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);
+		SETHT_MCS32(ht_cap->mcs.rx_mask);
 
 	/* Clear RD responder bit */
 	ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;
 
-	ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap);
-	ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
+	ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
+	ht_cap->extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
+
+	if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap))
+		ht_cap->tx_BF_cap_info = cpu_to_le32(MWIFIEX_DEF_11N_TX_BF_CAP);
+
+	return 0;
 }
 
 /*
@@ -312,7 +321,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 		       sizeof(struct ieee_types_header),
 		       le16_to_cpu(ht_cap->header.len));
 
-		mwifiex_fill_cap_info(priv, radio_type, ht_cap);
+		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
 
 		*buffer += sizeof(struct mwifiex_ie_types_htcap);
 		ret_len += sizeof(struct mwifiex_ie_types_htcap);
@@ -528,16 +537,32 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
 int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
 {
 	struct host_cmd_ds_11n_addba_req add_ba_req;
+	struct mwifiex_sta_node *sta_ptr;
+	u32 tx_win_size = priv->add_ba_param.tx_win_size;
 	static u8 dialog_tok;
 	int ret;
 
 	dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
 
+	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+	    priv->adapter->is_hw_11ac_capable &&
+	    memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
+		sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
+		if (!sta_ptr) {
+			dev_warn(priv->adapter->dev,
+				 "BA setup with unknown TDLS peer %pM!\n",
+				peer_mac);
+			return -1;
+		}
+		if (sta_ptr->is_11ac_enabled)
+			tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
+	}
+
 	add_ba_req.block_ack_param_set = cpu_to_le16(
 		(u16) ((tid << BLOCKACKPARAM_TID_POS) |
-			 (priv->add_ba_param.
-			  tx_win_size << BLOCKACKPARAM_WINSIZE_POS) |
-			 IMMEDIATE_BLOCK_ACK));
+		       tx_win_size << BLOCKACKPARAM_WINSIZE_POS |
+		       IMMEDIATE_BLOCK_ACK));
 	add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout);
 
 	++dialog_tok;
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 375db01442bf..12bb6acbdd58 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -34,8 +34,8 @@ int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
 int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 			       struct mwifiex_bssdescriptor *bss_desc,
 			       u8 **buffer);
-void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
-			   struct mwifiex_ie_types_htcap *);
+int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
+			  struct ieee80211_ht_cap *);
 int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv,
 				  u16 action, int *htcap_cfg);
 void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
@@ -64,14 +64,32 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
 				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
 void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
 
-/*
- * This function checks whether AMPDU is allowed or not for a particular TID.
- */
 static inline u8
-mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid)
+mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv,
+				 struct mwifiex_ra_list_tbl *ptr, int tid)
 {
-	return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
-		? true : false);
+	struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra);
+
+	if (unlikely(!node))
+		return false;
+
+	return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false;
+}
+
+/* This function checks whether AMPDU is allowed or not for a particular TID. */
+static inline u8
+mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
+			 struct mwifiex_ra_list_tbl *ptr, int tid)
+{
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+		return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
+	} else {
+		if (ptr->tdls_link)
+			return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
+
+		return (priv->aggr_prio_tbl[tid].ampdu_ap !=
+			BA_STREAM_NOT_ALLOWED) ? true : false;
+	}
 }
 
 /*
@@ -165,4 +183,14 @@ static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
 
 	return node->is_11n_enabled;
 }
+
+static inline u8
+mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra)
+{
+	struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
+	if (node)
+		return node->is_11n_enabled;
+
+	return false;
+}
 #endif /* !_MWIFIEX_11N_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index ada809f576fe..b361257fb65e 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -290,7 +290,11 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 				last_seq = node->rx_seq[tid];
 		}
 	} else {
-		last_seq = priv->rx_seq[tid];
+		node = mwifiex_get_sta_entry(priv, ta);
+		if (node)
+			last_seq = node->rx_seq[tid];
+		else
+			last_seq = priv->rx_seq[tid];
 	}
 
 	if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
@@ -358,10 +362,28 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
 				  *cmd_addba_req)
 {
 	struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp;
+	struct mwifiex_sta_node *sta_ptr;
+	u32 rx_win_size = priv->add_ba_param.rx_win_size;
 	u8 tid;
 	int win_size;
 	uint16_t block_ack_param_set;
 
+	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+	    priv->adapter->is_hw_11ac_capable &&
+	    memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
+		sta_ptr = mwifiex_get_sta_entry(priv,
+						cmd_addba_req->peer_mac_addr);
+		if (!sta_ptr) {
+			dev_warn(priv->adapter->dev,
+				 "BA setup with unknown TDLS peer %pM!\n",
+				 cmd_addba_req->peer_mac_addr);
+			return -1;
+		}
+		if (sta_ptr->is_11ac_enabled)
+			rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
+	}
+
 	cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
 	cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN);
 
@@ -378,8 +400,7 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
 	block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
 	/* We donot support AMSDU inside AMPDU, hence reset the bit */
 	block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
-	block_ack_param_set |= (priv->add_ba_param.rx_win_size <<
-					     BLOCKACKPARAM_WINSIZE_POS);
+	block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
 	add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
 	win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
 					& IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index a42a506fd32b..2aa208ffbe23 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -41,6 +41,7 @@ mwifiex-y += uap_txrx.o
 mwifiex-y += cfg80211.o
 mwifiex-y += ethtool.o
 mwifiex-y += 11h.o
+mwifiex-y += tdls.o
 mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
 obj-$(CONFIG_MWIFIEX) += mwifiex.o
 
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 8bfc07cd330e..436ba437a4ba 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1416,9 +1416,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
 		if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
 			config_bands |= BAND_GN;
-
-		if (params->chandef.width > NL80211_CHAN_WIDTH_40)
-			config_bands |= BAND_GAC;
 	} else {
 		bss_cfg->band_cfg = BAND_CONFIG_A;
 		config_bands = BAND_A;
@@ -1583,8 +1580,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
  * the function notifies the CFG802.11 subsystem of the new BSS connection.
  */
 static int
-mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
-		       u8 *bssid, int mode, struct ieee80211_channel *channel,
+mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
+		       const u8 *ssid, const u8 *bssid, int mode,
+		       struct ieee80211_channel *channel,
 		       struct cfg80211_connect_params *sme, bool privacy)
 {
 	struct cfg80211_ssid req_ssid;
@@ -1881,7 +1879,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 				     params->privacy);
 done:
 	if (!ret) {
-		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
+				     params->chandef.chan, GFP_KERNEL);
 		dev_dbg(priv->adapter->dev,
 			"info: joined/created adhoc network with bssid"
 			" %pM successfully\n", priv->cfg_bssid);
@@ -2595,6 +2594,170 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
 				     HostCmd_ACT_GEN_SET, 0, &coalesce_cfg);
 }
 
+/* cfg80211 ops handler for tdls_mgmt.
+ * Function prepares TDLS action frame packets and forwards them to FW
+ */
+static int
+mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+			   u8 *peer, u8 action_code, u8 dialog_token,
+			   u16 status_code, const u8 *extra_ies,
+			   size_t extra_ies_len)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	int ret;
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+		return -ENOTSUPP;
+
+	/* make sure we are in station mode and connected */
+	if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+		return -ENOTSUPP;
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+		dev_dbg(priv->adapter->dev,
+			"Send TDLS Setup Request to %pM status_code=%d\n", peer,
+			 status_code);
+		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		dev_dbg(priv->adapter->dev,
+			"Send TDLS Setup Response to %pM status_code=%d\n",
+			peer, status_code);
+		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	case WLAN_TDLS_SETUP_CONFIRM:
+		dev_dbg(priv->adapter->dev,
+			"Send TDLS Confirm to %pM status_code=%d\n", peer,
+			status_code);
+		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		dev_dbg(priv->adapter->dev, "Send TDLS Tear down to %pM\n",
+			peer);
+		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		dev_dbg(priv->adapter->dev,
+			"Send TDLS Discovery Request to %pM\n", peer);
+		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		dev_dbg(priv->adapter->dev,
+			"Send TDLS Discovery Response to %pM\n", peer);
+		ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
+						   dialog_token, status_code,
+						   extra_ies, extra_ies_len);
+		break;
+	default:
+		dev_warn(priv->adapter->dev,
+			 "Unknown TDLS mgmt/action frame %pM\n", peer);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+			   u8 *peer, enum nl80211_tdls_operation action)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
+	    !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
+		return -ENOTSUPP;
+
+	/* make sure we are in station mode and connected */
+	if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+		return -ENOTSUPP;
+
+	dev_dbg(priv->adapter->dev,
+		"TDLS peer=%pM, oper=%d\n", peer, action);
+
+	switch (action) {
+	case NL80211_TDLS_ENABLE_LINK:
+		action = MWIFIEX_TDLS_ENABLE_LINK;
+		break;
+	case NL80211_TDLS_DISABLE_LINK:
+		action = MWIFIEX_TDLS_DISABLE_LINK;
+		break;
+	case NL80211_TDLS_TEARDOWN:
+		/* shouldn't happen!*/
+		dev_warn(priv->adapter->dev,
+			 "tdls_oper: teardown from driver not supported\n");
+		return -EINVAL;
+	case NL80211_TDLS_SETUP:
+		/* shouldn't happen!*/
+		dev_warn(priv->adapter->dev,
+			 "tdls_oper: setup from driver not supported\n");
+		return -EINVAL;
+	case NL80211_TDLS_DISCOVERY_REQ:
+		/* shouldn't happen!*/
+		dev_warn(priv->adapter->dev,
+			 "tdls_oper: discovery from driver not supported\n");
+		return -EINVAL;
+	default:
+		dev_err(priv->adapter->dev,
+			"tdls_oper: operation not supported\n");
+		return -ENOTSUPP;
+	}
+
+	return mwifiex_tdls_oper(priv, peer, action);
+}
+
+static int
+mwifiex_cfg80211_add_station(struct wiphy *wiphy,
+			     struct net_device *dev,
+			     u8 *mac, struct station_parameters *params)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+		return -ENOTSUPP;
+
+	/* make sure we are in station mode and connected */
+	if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
+		return -ENOTSUPP;
+
+	return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
+}
+
+static int
+mwifiex_cfg80211_change_station(struct wiphy *wiphy,
+				struct net_device *dev,
+				u8 *mac, struct station_parameters *params)
+{
+	int ret;
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+	/* we support change_station handler only for TDLS peers*/
+	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+		return -ENOTSUPP;
+
+	/* make sure we are in station mode and connected */
+	if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
+		return -ENOTSUPP;
+
+	priv->sta_params = params;
+
+	ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
+	priv->sta_params = NULL;
+
+	return ret;
+}
+
 /* station cfg80211 operations */
 static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.add_virtual_intf = mwifiex_add_virtual_intf,
@@ -2630,6 +2793,10 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.set_wakeup = mwifiex_cfg80211_set_wakeup,
 #endif
 	.set_coalesce = mwifiex_cfg80211_set_coalesce,
+	.tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
+	.tdls_oper = mwifiex_cfg80211_tdls_oper,
+	.add_station = mwifiex_cfg80211_add_station,
+	.change_station = mwifiex_cfg80211_change_station,
 };
 
 #ifdef CONFIG_PM
@@ -2715,6 +2882,11 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 			WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
 			WIPHY_FLAG_AP_UAPSD |
 			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+
+	if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
+		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
+				WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+
 	wiphy->regulatory_flags |=
 			REGULATORY_CUSTOM_REG |
 			REGULATORY_STRICT_REG;
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index 9eefacbc844b..2c3226bf86f8 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -71,6 +71,95 @@ u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
 
 static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
 
+/* For every mcs_rate line, the first 8 bytes are for stream 1x1,
+ * and all 16 bytes are for stream 2x2.
+ */
+static const u16 mcs_rate[4][16] = {
+	/* LGI 40M */
+	{ 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
+	  0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
+
+	/* SGI 40M */
+	{ 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
+	  0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
+
+	/* LGI 20M */
+	{ 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
+	  0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
+
+	/* SGI 20M */
+	{ 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
+	  0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
+};
+
+/* AC rates */
+static const u16 ac_mcs_rate_nss1[8][10] = {
+	/* LG 160M */
+	{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
+	  0x492, 0x57C, 0x618 },
+
+	/* SG 160M */
+	{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
+	  0x514, 0x618, 0x6C6 },
+
+	/* LG 80M */
+	{ 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
+	  0x249, 0x2BE, 0x30C },
+
+	/* SG 80M */
+	{ 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
+	  0x28A, 0x30C, 0x363 },
+
+	/* LG 40M */
+	{ 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
+	  0x10E, 0x144, 0x168 },
+
+	/* SG 40M */
+	{ 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
+	  0x12C, 0x168, 0x190 },
+
+	/* LG 20M */
+	{ 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
+
+	/* SG 20M */
+	{ 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
+};
+
+/* NSS2 note: the value in the table is 2 multiplier of the actual rate */
+static const u16 ac_mcs_rate_nss2[8][10] = {
+	/* LG 160M */
+	{ 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
+	  0x924, 0xAF8, 0xC30 },
+
+	/* SG 160M */
+	{ 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
+	  0xA28, 0xC30, 0xD8B },
+
+	/* LG 80M */
+	{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
+	  0x492, 0x57C, 0x618 },
+
+	/* SG 80M */
+	{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
+	  0x514, 0x618, 0x6C6 },
+
+	/* LG 40M */
+	{ 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
+	  0x21C, 0x288, 0x2D0 },
+
+	/* SG 40M */
+	{ 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
+	  0x258, 0x2D0, 0x320 },
+
+	/* LG 20M */
+	{ 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
+	  0x138, 0x00 },
+
+	/* SG 20M */
+	{ 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
+	  0x15B, 0x00 },
+};
+
 struct region_code_mapping {
 	u8 code;
 	u8 region[IEEE80211_COUNTRY_STRING_LEN];
@@ -109,95 +198,6 @@ u8 *mwifiex_11d_code_2_region(u8 code)
 u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
 				   u8 index, u8 ht_info)
 {
-	/*
-	 * For every mcs_rate line, the first 8 bytes are for stream 1x1,
-	 * and all 16 bytes are for stream 2x2.
-	 */
-	u16  mcs_rate[4][16] = {
-		/* LGI 40M */
-		{ 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
-		  0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
-
-		/* SGI 40M */
-		{ 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
-		  0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
-
-		/* LGI 20M */
-		{ 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
-		  0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
-
-		/* SGI 20M */
-		{ 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
-		  0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
-	};
-	/* AC rates */
-	u16 ac_mcs_rate_nss1[8][10] = {
-		/* LG 160M */
-		{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
-		  0x492, 0x57C, 0x618 },
-
-		/* SG 160M */
-		{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
-		  0x514, 0x618, 0x6C6 },
-
-		/* LG 80M */
-		{ 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
-		  0x249, 0x2BE, 0x30C },
-
-		/* SG 80M */
-		{ 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
-		  0x28A, 0x30C, 0x363 },
-
-		/* LG 40M */
-		{ 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
-		  0x10E, 0x144, 0x168 },
-
-		/* SG 40M */
-		{ 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
-		  0x12C, 0x168, 0x190 },
-
-		/* LG 20M */
-		{ 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
-
-		/* SG 20M */
-		{ 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
-	};
-	/* NSS2 note: the value in the table is 2 multiplier of the actual
-	 * rate
-	 */
-	u16 ac_mcs_rate_nss2[8][10] = {
-		/* LG 160M */
-		{ 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
-		  0x924, 0xAF8, 0xC30 },
-
-		/* SG 160M */
-		{ 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
-		  0xA28, 0xC30, 0xD8B },
-
-		/* LG 80M */
-		{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
-		  0x492, 0x57C, 0x618 },
-
-		/* SG 80M */
-		{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
-		  0x514, 0x618, 0x6C6 },
-
-		/* LG 40M */
-		{ 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
-		  0x21C, 0x288, 0x2D0 },
-
-		/* SG 40M */
-		{ 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
-		  0x258, 0x2D0, 0x320 },
-
-		/* LG 20M */
-		{ 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
-		  0x138, 0x00 },
-
-		/* SG 20M */
-		{ 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
-		  0x15B, 0x00 },
-	};
 	u32 rate = 0;
 	u8 mcs_index = 0;
 	u8 bw = 0;
@@ -252,26 +252,6 @@ u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
 u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
 			       u8 index, u8 ht_info)
 {
-	/* For every mcs_rate line, the first 8 bytes are for stream 1x1,
-	 * and all 16 bytes are for stream 2x2.
-	 */
-	u16  mcs_rate[4][16] = {
-		/* LGI 40M */
-		{ 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
-		  0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
-
-		/* SGI 40M */
-		{ 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
-		  0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
-
-		/* LGI 20M */
-		{ 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
-		  0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
-
-		/* SGI 20M */
-		{ 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
-		  0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
-	};
 	u32 mcs_num_supp =
 		(priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
 	u32 rate;
@@ -458,7 +438,6 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
 			break;
 		case BAND_G:
 		case BAND_G | BAND_GN:
-		case BAND_G | BAND_GN | BAND_GAC:
 			dev_dbg(adapter->dev, "info: infra band=%d "
 				"supported_rates_g\n", adapter->config_bands);
 			k = mwifiex_copy_rates(rates, k, supported_rates_g,
@@ -469,10 +448,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
 		case BAND_A | BAND_B:
 		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
 		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
-		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN |
-		     BAND_AAC | BAND_GAC:
 		case BAND_B | BAND_G | BAND_GN:
-		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
 			dev_dbg(adapter->dev, "info: infra band=%d "
 				"supported_rates_bg\n", adapter->config_bands);
 			k = mwifiex_copy_rates(rates, k, supported_rates_bg,
@@ -496,7 +472,6 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
 					       sizeof(supported_rates_a));
 			break;
 		case BAND_GN:
-		case BAND_GN | BAND_GAC:
 			dev_dbg(adapter->dev, "info: infra band=%d "
 				"supported_rates_n\n", adapter->config_bands);
 			k = mwifiex_copy_rates(rates, k, supported_rates_n,
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 1ddc8b2e3722..21544602043c 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -595,7 +595,8 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
 	}
 
 	/* Send command */
-	if (cmd_no == HostCmd_CMD_802_11_SCAN) {
+	if (cmd_no == HostCmd_CMD_802_11_SCAN ||
+	    cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
 		mwifiex_queue_scan_cmd(priv, cmd_node);
 	} else {
 		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
@@ -1454,7 +1455,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
 {
 	struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
 	struct mwifiex_adapter *adapter = priv->adapter;
-	int i;
+	struct mwifiex_ie_types_header *tlv;
+	struct hw_spec_fw_api_rev *api_rev;
+	u16 resp_size, api_id;
+	int i, left_len, parsed_len = 0;
 
 	adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
 
@@ -1498,8 +1502,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
 		/* Copy 11AC cap */
 		adapter->hw_dot_11ac_dev_cap =
 					le32_to_cpu(hw_spec->dot_11ac_dev_cap);
-		adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap;
-		adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap;
+		adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
+					& ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
+		adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
+					& ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
 
 		/* Copy 11AC mcs */
 		adapter->hw_dot_11ac_mcs_support =
@@ -1510,6 +1516,46 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
 		adapter->is_hw_11ac_capable = false;
 	}
 
+	resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
+	if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
+		/* we have variable HW SPEC information */
+		left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
+		while (left_len > sizeof(struct mwifiex_ie_types_header)) {
+			tlv = (void *)&hw_spec->tlvs + parsed_len;
+			switch (le16_to_cpu(tlv->type)) {
+			case TLV_TYPE_FW_API_REV:
+				api_rev = (struct hw_spec_fw_api_rev *)tlv;
+				api_id = le16_to_cpu(api_rev->api_id);
+				switch (api_id) {
+				case KEY_API_VER_ID:
+					adapter->fw_key_api_major_ver =
+							api_rev->major_ver;
+					adapter->fw_key_api_minor_ver =
+							api_rev->minor_ver;
+					dev_dbg(adapter->dev,
+						"fw_key_api v%d.%d\n",
+						adapter->fw_key_api_major_ver,
+						adapter->fw_key_api_minor_ver);
+					break;
+				default:
+					dev_warn(adapter->dev,
+						 "Unknown FW api_id: %d\n",
+						 api_id);
+					break;
+				}
+				break;
+			default:
+				dev_warn(adapter->dev,
+					 "Unknown GET_HW_SPEC TLV type: %#x\n",
+					 le16_to_cpu(tlv->type));
+				break;
+			}
+			parsed_len += le16_to_cpu(tlv->len) +
+				      sizeof(struct mwifiex_ie_types_header);
+			left_len -= parsed_len;
+		}
+	}
+
 	dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n",
 		adapter->fw_release_number);
 	dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n",
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 3a21bd03d6db..e7b3e16e5d34 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -75,10 +75,16 @@
 
 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
 #define MWIFIEX_BUF_FLAG_BRIDGED_PKT	   BIT(1)
+#define MWIFIEX_BUF_FLAG_TDLS_PKT	   BIT(2)
 
 #define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
 #define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
 
+#define MWIFIEX_TDLS_DISABLE_LINK             0x00
+#define MWIFIEX_TDLS_ENABLE_LINK              0x01
+#define MWIFIEX_TDLS_CREATE_LINK              0x02
+#define MWIFIEX_TDLS_CONFIG_LINK              0x03
+
 enum mwifiex_bss_type {
 	MWIFIEX_BSS_TYPE_STA = 0,
 	MWIFIEX_BSS_TYPE_UAP = 1,
@@ -92,6 +98,23 @@ enum mwifiex_bss_role {
 	MWIFIEX_BSS_ROLE_ANY = 0xff,
 };
 
+enum mwifiex_tdls_status {
+	TDLS_NOT_SETUP = 0,
+	TDLS_SETUP_INPROGRESS,
+	TDLS_SETUP_COMPLETE,
+	TDLS_SETUP_FAILURE,
+	TDLS_LINK_TEARDOWN,
+};
+
+enum mwifiex_tdls_error_code {
+	TDLS_ERR_NO_ERROR = 0,
+	TDLS_ERR_INTERNAL_ERROR,
+	TDLS_ERR_MAX_LINKS_EST,
+	TDLS_ERR_LINK_EXISTS,
+	TDLS_ERR_LINK_NONEXISTENT,
+	TDLS_ERR_PEER_STA_UNREACHABLE = 25,
+};
+
 #define BSS_ROLE_BIT_MASK    BIT(0)
 
 #define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_MASK)
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 5fa932d5f905..aa8abef58349 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -50,21 +50,23 @@ struct tx_packet_hdr {
 #define HOSTCMD_SUPPORTED_RATES         14
 #define N_SUPPORTED_RATES               3
 #define ALL_802_11_BANDS           (BAND_A | BAND_B | BAND_G | BAND_GN | \
-				    BAND_AN | BAND_GAC | BAND_AAC)
+				    BAND_AN | BAND_AAC)
 
 #define FW_MULTI_BANDS_SUPPORT  (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \
-				 BIT(12) | BIT(13))
+				 BIT(13))
 #define IS_SUPPORT_MULTI_BANDS(adapter)        \
 	(adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
 
-/* shift bit 12 and bit 13 in fw_cap_info from the firmware to bit 13 and 14
- * for 11ac so that bit 11 is for GN, bit 12 for AN, bit 13 for GAC, and bit
- * bit 14 for AAC, in order to be compatible with the band capability
- * defined in the driver after right shift of 8 bits.
+/* bit 13: 11ac BAND_AAC
+ * bit 12: reserved for lab testing, will be reused for BAND_AN
+ * bit 11: 11n  BAND_GN
+ * bit 10: 11a  BAND_A
+ * bit 9: 11g   BAND_G
+ * bit 8: 11b   BAND_B
+ * Map these bits to band capability by right shifting 8 bits.
  */
 #define GET_FW_DEFAULT_BANDS(adapter)  \
-	    (((((adapter->fw_cap_info & 0x3000) << 1) | \
-	       (adapter->fw_cap_info & ~0xF000)) >> 8) & \
+	    (((adapter->fw_cap_info & 0x2f00) >> 8) & \
 	     ALL_802_11_BANDS)
 
 #define HostCmd_WEP_KEY_INDEX_MASK              0x3fff
@@ -77,12 +79,21 @@ enum KEY_TYPE_ID {
 	KEY_TYPE_ID_WAPI,
 	KEY_TYPE_ID_AES_CMAC,
 };
+
+#define WPA_PN_SIZE		8
+#define KEY_PARAMS_FIXED_LEN	10
+#define KEY_INDEX_MASK		0xf
+#define FW_KEY_API_VER_MAJOR_V2	2
+
 #define KEY_MCAST	BIT(0)
 #define KEY_UNICAST	BIT(1)
 #define KEY_ENABLED	BIT(2)
+#define KEY_DEFAULT	BIT(3)
+#define KEY_TX_KEY	BIT(4)
+#define KEY_RX_KEY	BIT(5)
 #define KEY_IGTK	BIT(10)
 
-#define WAPI_KEY_LEN			50
+#define WAPI_KEY_LEN			(WLAN_KEY_LEN_SMS4 + PN_LEN + 2)
 
 #define MAX_POLL_TRIES			100
 #define MAX_FIRMWARE_POLL_TRIES			100
@@ -130,6 +141,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
 #define TLV_TYPE_AUTH_TYPE          (PROPRIETARY_TLV_BASE_ID + 31)
 #define TLV_TYPE_STA_MAC_ADDR       (PROPRIETARY_TLV_BASE_ID + 32)
+#define TLV_TYPE_BSSID              (PROPRIETARY_TLV_BASE_ID + 35)
 #define TLV_TYPE_CHANNELBANDLIST    (PROPRIETARY_TLV_BASE_ID + 42)
 #define TLV_TYPE_UAP_BEACON_PERIOD  (PROPRIETARY_TLV_BASE_ID + 44)
 #define TLV_TYPE_UAP_DTIM_PERIOD    (PROPRIETARY_TLV_BASE_ID + 45)
@@ -144,6 +156,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 82)
 #define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 83)
 #define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 84)
+#define TLV_TYPE_BSS_SCAN_RSP       (PROPRIETARY_TLV_BASE_ID + 86)
+#define TLV_TYPE_BSS_SCAN_INFO      (PROPRIETARY_TLV_BASE_ID + 87)
 #define TLV_TYPE_UAP_RETRY_LIMIT    (PROPRIETARY_TLV_BASE_ID + 93)
 #define TLV_TYPE_WAPI_IE            (PROPRIETARY_TLV_BASE_ID + 94)
 #define TLV_TYPE_UAP_MGMT_FRAME     (PROPRIETARY_TLV_BASE_ID + 104)
@@ -154,6 +168,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_PWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 145)
 #define TLV_TYPE_GWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 146)
 #define TLV_TYPE_COALESCE_RULE      (PROPRIETARY_TLV_BASE_ID + 154)
+#define TLV_TYPE_KEY_PARAM_V2       (PROPRIETARY_TLV_BASE_ID + 156)
+#define TLV_TYPE_FW_API_REV         (PROPRIETARY_TLV_BASE_ID + 199)
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
 
@@ -176,11 +192,14 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define MWIFIEX_TX_DATA_BUF_SIZE_8K        8192
 
 #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
+#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
 
 #define MWIFIEX_DEF_HT_CAP	(IEEE80211_HT_CAP_DSSSCCK40 | \
 				 (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
 				 IEEE80211_HT_CAP_SM_PS)
 
+#define MWIFIEX_DEF_11N_TX_BF_CAP	0x09E1E008
+
 #define MWIFIEX_DEF_AMPDU	IEEE80211_HT_AMPDU_PARM_FACTOR
 
 /* dev_cap bitmap
@@ -204,6 +223,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
 #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8))
 #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22))
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30))
 
 /* httxcfg bitmap
  * 0		reserved
@@ -226,17 +246,24 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 
 /* HW_SPEC fw_cap_info */
 
-#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(12)|BIT(13)))
+#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & BIT(13))
 
 #define GET_VHTCAP_CHWDSET(vht_cap_info)    ((vht_cap_info >> 2) & 0x3)
 #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3)
 #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \
 					      (2 * (nss - 1)))
-#define NO_NSS_SUPPORT		0x3
-
 #define GET_DEVTXMCSMAP(dev_mcs_map)      (dev_mcs_map >> 16)
 #define GET_DEVRXMCSMAP(dev_mcs_map)      (dev_mcs_map & 0xFFFF)
 
+/* Clear SU Beanformer, MU beanformer, MU beanformee and
+ * sounding dimensions bits
+ */
+#define MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK \
+			(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \
+			 IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \
+			 IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \
+			 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
+
 #define MOD_CLASS_HR_DSSS       0x03
 #define MOD_CLASS_OFDM          0x07
 #define MOD_CLASS_HT            0x08
@@ -295,10 +322,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_CAU_REG_ACCESS                    0x00ed
 #define HostCmd_CMD_SET_BSS_MODE                      0x00f7
 #define HostCmd_CMD_PCIE_DESC_DETAILS                 0x00fa
+#define HostCmd_CMD_802_11_SCAN_EXT                   0x0107
 #define HostCmd_CMD_COALESCE_CFG                      0x010a
 #define HostCmd_CMD_MGMT_FRAME_REG                    0x010c
 #define HostCmd_CMD_REMAIN_ON_CHAN                    0x010d
 #define HostCmd_CMD_11AC_CFG			      0x0112
+#define HostCmd_CMD_TDLS_OPER                         0x0122
 
 #define PROTOCOL_NO_SECURITY        0x01
 #define PROTOCOL_STATIC_WEP         0x02
@@ -440,6 +469,7 @@ enum P2P_MODES {
 #define EVENT_UAP_MIC_COUNTERMEASURES   0x0000004c
 #define EVENT_HOSTWAKE_STAIE		0x0000004d
 #define EVENT_CHANNEL_SWITCH_ANN        0x00000050
+#define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
 
 #define EVENT_ID_MASK                   0xffff
@@ -468,6 +498,10 @@ enum P2P_MODES {
 #define MWIFIEX_CRITERIA_UNICAST	BIT(1)
 #define MWIFIEX_CRITERIA_MULTICAST	BIT(3)
 
+#define ACT_TDLS_DELETE            0x00
+#define ACT_TDLS_CREATE            0x01
+#define ACT_TDLS_CONFIG            0x02
+
 struct mwifiex_ie_types_header {
 	__le16 type;
 	__le16 len;
@@ -480,6 +514,7 @@ struct mwifiex_ie_types_data {
 
 #define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01
 #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08
+#define MWIFIEX_TXPD_FLAGS_TDLS_PACKET      0x10
 
 struct txpd {
 	u8 bss_type;
@@ -676,6 +711,56 @@ struct mwifiex_cmac_param {
 	u8 key[WLAN_KEY_LEN_AES_CMAC];
 } __packed;
 
+struct mwifiex_wep_param {
+	__le16 key_len;
+	u8 key[WLAN_KEY_LEN_WEP104];
+} __packed;
+
+struct mwifiex_tkip_param {
+	u8 pn[WPA_PN_SIZE];
+	__le16 key_len;
+	u8 key[WLAN_KEY_LEN_TKIP];
+} __packed;
+
+struct mwifiex_aes_param {
+	u8 pn[WPA_PN_SIZE];
+	__le16 key_len;
+	u8 key[WLAN_KEY_LEN_CCMP];
+} __packed;
+
+struct mwifiex_wapi_param {
+	u8 pn[PN_LEN];
+	__le16 key_len;
+	u8 key[WLAN_KEY_LEN_SMS4];
+} __packed;
+
+struct mwifiex_cmac_aes_param {
+	u8 ipn[IGTK_PN_LEN];
+	__le16 key_len;
+	u8 key[WLAN_KEY_LEN_AES_CMAC];
+} __packed;
+
+struct mwifiex_ie_type_key_param_set_v2 {
+	__le16 type;
+	__le16 len;
+	u8 mac_addr[ETH_ALEN];
+	u8 key_idx;
+	u8 key_type;
+	__le16 key_info;
+	union {
+		struct mwifiex_wep_param wep;
+		struct mwifiex_tkip_param tkip;
+		struct mwifiex_aes_param aes;
+		struct mwifiex_wapi_param wapi;
+		struct mwifiex_cmac_aes_param cmac_aes;
+	} key_params;
+} __packed;
+
+struct host_cmd_ds_802_11_key_material_v2 {
+	__le16 action;
+	struct mwifiex_ie_type_key_param_set_v2 key_param_set;
+} __packed;
+
 struct host_cmd_ds_802_11_key_material {
 	__le16 action;
 	struct mwifiex_ie_type_key_param_set key_param_set;
@@ -727,6 +812,17 @@ struct host_cmd_ds_802_11_ps_mode_enh {
 	} params;
 } __packed;
 
+enum FW_API_VER_ID {
+	KEY_API_VER_ID = 1,
+};
+
+struct hw_spec_fw_api_rev {
+	struct mwifiex_ie_types_header header;
+	__le16 api_id;
+	u8 major_ver;
+	u8 minor_ver;
+} __packed;
+
 struct host_cmd_ds_get_hw_spec {
 	__le16 hw_if_version;
 	__le16 version;
@@ -748,6 +844,7 @@ struct host_cmd_ds_get_hw_spec {
 	__le32 reserved_6;
 	__le32 dot_11ac_dev_cap;
 	__le32 dot_11ac_mcs_support;
+	u8 tlvs[0];
 } __packed;
 
 struct host_cmd_ds_802_11_rssi_info {
@@ -1047,14 +1144,28 @@ struct host_cmd_ds_rf_ant_siso {
 	__le16 ant_mode;
 };
 
-struct mwifiex_bcn_param {
-	u8 bssid[ETH_ALEN];
-	u8 rssi;
+struct host_cmd_ds_tdls_oper {
+	__le16 tdls_action;
+	__le16 reason;
+	u8 peer_mac[ETH_ALEN];
+} __packed;
+
+struct mwifiex_fixed_bcn_param {
 	__le64 timestamp;
 	__le16 beacon_period;
 	__le16 cap_info_bitmap;
 } __packed;
 
+struct mwifiex_event_scan_result {
+	__le16 event_id;
+	u8 bss_index;
+	u8 bss_type;
+	u8 more_event;
+	u8 reserved[3];
+	__le16 buf_size;
+	u8 num_of_set;
+} __packed;
+
 #define MWIFIEX_USER_SCAN_CHAN_MAX             50
 
 #define MWIFIEX_MAX_SSID_LIST_LENGTH         10
@@ -1124,6 +1235,28 @@ struct host_cmd_ds_802_11_scan_rsp {
 	u8 bss_desc_and_tlv_buffer[1];
 } __packed;
 
+struct host_cmd_ds_802_11_scan_ext {
+	u32   reserved;
+	u8    tlv_buffer[1];
+} __packed;
+
+struct mwifiex_ie_types_bss_scan_rsp {
+	struct mwifiex_ie_types_header header;
+	u8 bssid[ETH_ALEN];
+	u8 frame_body[1];
+} __packed;
+
+struct mwifiex_ie_types_bss_scan_info {
+	struct mwifiex_ie_types_header header;
+	__le16 rssi;
+	__le16 anpi;
+	u8 cca_busy_fraction;
+	u8 radio_type;
+	u8 channel;
+	u8 reserved;
+	__le64 tsf;
+} __packed;
+
 struct host_cmd_ds_802_11_bg_scan_query {
 	u8 flush;
 } __packed;
@@ -1296,6 +1429,11 @@ struct mwifiex_ie_types_vhtcap {
 	struct ieee80211_vht_cap vht_cap;
 } __packed;
 
+struct mwifiex_ie_types_aid {
+	struct mwifiex_ie_types_header header;
+	__le16 aid;
+} __packed;
+
 struct mwifiex_ie_types_oper_mode_ntf {
 	struct mwifiex_ie_types_header header;
 	u8 oper_mode;
@@ -1331,6 +1469,11 @@ struct mwifiex_ie_types_extcap {
 	u8 ext_capab[0];
 } __packed;
 
+struct mwifiex_ie_types_qos_info {
+	struct mwifiex_ie_types_header header;
+	u8 qos_info;
+} __packed;
+
 struct host_cmd_ds_mac_reg_access {
 	__le16 action;
 	__le16 offset;
@@ -1441,6 +1584,11 @@ struct host_cmd_tlv_rates {
 	u8 rates[0];
 } __packed;
 
+struct mwifiex_ie_types_bssid_list {
+	struct mwifiex_ie_types_header header;
+	u8 bssid[ETH_ALEN];
+} __packed;
+
 struct host_cmd_tlv_bcast_ssid {
 	struct mwifiex_ie_types_header header;
 	u8 bcast_ctl;
@@ -1634,6 +1782,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
 		struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
 		struct host_cmd_ds_802_11_scan scan;
+		struct host_cmd_ds_802_11_scan_ext ext_scan;
 		struct host_cmd_ds_802_11_scan_rsp scan_resp;
 		struct host_cmd_ds_802_11_bg_scan_query bg_scan_query;
 		struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp;
@@ -1653,6 +1802,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_11n_cfg htcfg;
 		struct host_cmd_ds_wmm_get_status get_wmm_status;
 		struct host_cmd_ds_802_11_key_material key_material;
+		struct host_cmd_ds_802_11_key_material_v2 key_material_v2;
 		struct host_cmd_ds_version_ext verext;
 		struct host_cmd_ds_mgmt_frame_reg reg_mask;
 		struct host_cmd_ds_remain_on_chan roc_cfg;
@@ -1671,6 +1821,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_sta_deauth sta_deauth;
 		struct host_cmd_11ac_vht_cfg vht_cfg;
 		struct host_cmd_ds_coalesce_cfg coalesce_cfg;
+		struct host_cmd_ds_tdls_oper tdls_oper;
 	} params;
 } __packed;
 
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 1d0a817f2bf0..a4cd2cb066ed 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -137,6 +137,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
 	priv->csa_expire_time = 0;
 	priv->del_list_idx = 0;
 	priv->hs2_enabled = false;
+	memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
 
 	return mwifiex_add_bss_prio_tbl(priv);
 }
@@ -281,6 +282,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 	adapter->arp_filter_size = 0;
 	adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
 	adapter->empty_tx_q_cnt = 0;
+	adapter->ext_scan = true;
+	adapter->fw_key_api_major_ver = 0;
+	adapter->fw_key_api_minor_ver = 0;
 }
 
 /*
@@ -450,6 +454,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
 		INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
 		INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
 		INIT_LIST_HEAD(&priv->sta_list);
+		skb_queue_head_init(&priv->tdls_txq);
 
 		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
 		spin_lock_init(&priv->rx_reorder_tbl_lock);
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 00a95f4c6a6c..5974642f38b1 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -60,8 +60,7 @@ enum {
 	BAND_A = 4,
 	BAND_GN = 8,
 	BAND_AN = 16,
-	BAND_GAC = 32,
-	BAND_AAC = 64,
+	BAND_AAC = 32,
 };
 
 #define MWIFIEX_WPA_PASSHPHRASE_LEN 64
@@ -86,6 +85,10 @@ struct wep_key {
 #define BAND_CONFIG_A           0x01
 #define MWIFIEX_SUPPORTED_RATES                 14
 #define MWIFIEX_SUPPORTED_RATES_EXT             32
+#define MWIFIEX_TDLS_SUPPORTED_RATES		8
+#define MWIFIEX_TDLS_DEF_QOS_CAPAB		0xf
+#define MWIFIEX_PRIO_BK				2
+#define MWIFIEX_PRIO_VI				5
 
 struct mwifiex_uap_bss_param {
 	u8 channel;
@@ -233,7 +236,10 @@ struct mwifiex_ds_encrypt_key {
 	u8 mac_addr[ETH_ALEN];
 	u32 is_wapi_key;
 	u8 pn[PN_LEN];		/* packet number */
+	u8 pn_len;
 	u8 is_igtk_key;
+	u8 is_current_wep_key;
+	u8 is_rx_seq_valid;
 };
 
 struct mwifiex_power_cfg {
@@ -432,4 +438,16 @@ struct mwifiex_ds_coalesce_cfg {
 	struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES];
 };
 
+struct mwifiex_ds_tdls_oper {
+	u16 tdls_action;
+	u8 peer_mac[ETH_ALEN];
+	u16 capability;
+	u8 qos_info;
+	u8 *ext_capab;
+	u8 ext_capab_len;
+	u8 *supp_rates;
+	u8 supp_rates_len;
+	u8 *ht_capab;
+};
+
 #endif /* !_MWIFIEX_IOCTL_H_ */
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 4e4686e6ac09..34472ea53841 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -515,8 +515,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
 
 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
 	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-	    (priv->adapter->config_bands & BAND_GAC ||
-	     priv->adapter->config_bands & BAND_AAC))
+	    priv->adapter->config_bands & BAND_AAC)
 		mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos);
 
 	/* Append vendor specific IE TLV */
@@ -983,7 +982,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 		       cpu_to_le16(sizeof(struct ieee80211_ht_cap));
 		radio_type = mwifiex_band_to_radio_type(
 					priv->adapter->config_bands);
-		mwifiex_fill_cap_info(priv, radio_type, ht_cap);
+		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
 
 		if (adapter->sec_chan_offset ==
 					IEEE80211_HT_PARAM_CHA_SEC_NONE) {
@@ -1300,8 +1299,7 @@ int mwifiex_associate(struct mwifiex_private *priv,
 
 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
 	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-	    (priv->adapter->config_bands & BAND_GAC ||
-	     priv->adapter->config_bands & BAND_AAC))
+	    priv->adapter->config_bands & BAND_AAC)
 		mwifiex_set_11ac_ba_params(priv);
 	else
 		mwifiex_set_ba_params(priv);
@@ -1335,8 +1333,7 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
 		priv->curr_bss_params.band);
 
 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
-	    (priv->adapter->config_bands & BAND_GAC ||
-	     priv->adapter->config_bands & BAND_AAC))
+	    priv->adapter->config_bands & BAND_AAC)
 		mwifiex_set_11ac_ba_params(priv);
 	else
 		mwifiex_set_ba_params(priv);
@@ -1376,8 +1373,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
 
 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
 	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
-	    (priv->adapter->config_bands & BAND_GAC ||
-	     priv->adapter->config_bands & BAND_AAC))
+	    priv->adapter->config_bands & BAND_AAC)
 		mwifiex_set_11ac_ba_params(priv);
 	else
 		mwifiex_set_ba_params(priv);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index d8ad554ce39f..407f8eada720 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -59,7 +59,7 @@ enum {
 
 #define MWIFIEX_UPLD_SIZE               (2312)
 
-#define MAX_EVENT_SIZE                  1024
+#define MAX_EVENT_SIZE                  2048
 
 #define ARP_FILTER_MAX_BUF_SIZE         68
 
@@ -210,6 +210,7 @@ struct mwifiex_ra_list_tbl {
 	u16 ba_pkt_count;
 	u8 ba_packet_thr;
 	u16 total_pkt_count;
+	bool tdls_link;
 };
 
 struct mwifiex_tid_tbl {
@@ -262,6 +263,31 @@ struct ieee_types_generic {
 	u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)];
 } __packed;
 
+struct ieee_types_bss_co_2040 {
+	struct ieee_types_header ieee_hdr;
+	u8 bss_2040co;
+} __packed;
+
+struct ieee_types_extcap {
+	struct ieee_types_header ieee_hdr;
+	u8 ext_capab[8];
+} __packed;
+
+struct ieee_types_vht_cap {
+	struct ieee_types_header ieee_hdr;
+	struct ieee80211_vht_cap vhtcap;
+} __packed;
+
+struct ieee_types_vht_oper {
+	struct ieee_types_header ieee_hdr;
+	struct ieee80211_vht_operation vhtoper;
+} __packed;
+
+struct ieee_types_aid {
+	struct ieee_types_header ieee_hdr;
+	u16 aid;
+} __packed;
+
 struct mwifiex_bssdescriptor {
 	u8 mac_address[ETH_ALEN];
 	struct cfg80211_ssid ssid;
@@ -443,6 +469,7 @@ struct mwifiex_private {
 	u8 wpa_ie_len;
 	u8 wpa_is_gtk_set;
 	struct host_cmd_ds_802_11_key_material aes_key;
+	struct host_cmd_ds_802_11_key_material_v2 aes_key_v2;
 	u8 wapi_ie[256];
 	u8 wapi_ie_len;
 	u8 *wps_ie;
@@ -461,6 +488,7 @@ struct mwifiex_private {
 	struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID];
 	struct mwifiex_add_ba_param add_ba_param;
 	u16 rx_seq[MAX_NUM_TID];
+	u8 tos_to_tid_inv[MAX_NUM_TID];
 	struct list_head rx_reorder_tbl_ptr;
 	/* spin lock for rx_reorder_tbl_ptr queue */
 	spinlock_t rx_reorder_tbl_lock;
@@ -518,6 +546,8 @@ struct mwifiex_private {
 	unsigned long csa_expire_time;
 	u8 del_list_idx;
 	bool hs2_enabled;
+	struct station_parameters *sta_params;
+	struct sk_buff_head tdls_txq;
 };
 
 enum mwifiex_ba_status {
@@ -583,17 +613,35 @@ struct mwifiex_bss_priv {
 	u64 fw_tsf;
 };
 
-/* This is AP specific structure which stores information
- * about associated STA
+struct mwifiex_tdls_capab {
+	__le16 capab;
+	u8 rates[32];
+	u8 rates_len;
+	u8 qos_info;
+	u8 coex_2040;
+	u16 aid;
+	struct ieee80211_ht_cap ht_capb;
+	struct ieee80211_ht_operation ht_oper;
+	struct ieee_types_extcap extcap;
+	struct ieee_types_generic rsn_ie;
+	struct ieee80211_vht_cap vhtcap;
+	struct ieee80211_vht_operation vhtoper;
+};
+
+/* This is AP/TDLS specific structure which stores information
+ * about associated/peer STA
  */
 struct mwifiex_sta_node {
 	struct list_head list;
 	u8 mac_addr[ETH_ALEN];
 	u8 is_wmm_enabled;
 	u8 is_11n_enabled;
+	u8 is_11ac_enabled;
 	u8 ampdu_sta[MAX_NUM_TID];
 	u16 rx_seq[MAX_NUM_TID];
 	u16 max_amsdu;
+	u8 tdls_status;
+	struct mwifiex_tdls_capab tdls_cap;
 };
 
 struct mwifiex_if_ops {
@@ -753,6 +801,8 @@ struct mwifiex_adapter {
 	atomic_t is_tx_received;
 	atomic_t pending_bridged_pkts;
 	struct semaphore *card_sem;
+	bool ext_scan;
+	u8 fw_key_api_major_ver, fw_key_api_minor_ver;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -938,6 +988,12 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
 		       struct cfg80211_ap_settings *params);
 void mwifiex_set_ba_params(struct mwifiex_private *priv);
 void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
+int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
+				struct host_cmd_ds_command *cmd,
+				void *data_buf);
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv);
+int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
+					 void *buf);
 
 /*
  * This function checks if the queuing is RA based or not.
@@ -1078,7 +1134,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
 		       const u8 *key, int key_len, u8 key_index,
 		       const u8 *mac_addr, int disable);
 
-int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
+int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len);
 
 int mwifiex_get_ver_ext(struct mwifiex_private *priv);
 
@@ -1159,6 +1215,32 @@ void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv);
 
 extern const struct ethtool_ops mwifiex_ethtool_ops;
 
+void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
+void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac);
+void
+mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
+		       int ies_len, struct mwifiex_sta_node *node);
+struct mwifiex_sta_node *
+mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac);
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer,
+				 u8 action_code, u8 dialog_token,
+				 u16 status_code, const u8 *extra_ies,
+				 size_t extra_ies_len);
+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
+				 u8 *peer, u8 action_code, u8 dialog_token,
+				 u16 status_code, const u8 *extra_ies,
+				 size_t extra_ies_len);
+void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
+				       u8 *buf, int len);
+int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action);
+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac);
+void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
+bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
+u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
+				 u32 pri_chan, u8 chan_bw);
+
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
 void mwifiex_debugfs_remove(void);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 03688aa14e8a..31d8a9df1331 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -39,20 +39,31 @@ static struct semaphore add_remove_card_sem;
 
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
-		       int size, int flags)
+		       size_t size, int flags)
 {
 	struct pcie_service_card *card = adapter->card;
-	dma_addr_t buf_pa;
+	struct mwifiex_dma_mapping mapping;
 
-	buf_pa = pci_map_single(card->dev, skb->data, size, flags);
-	if (pci_dma_mapping_error(card->dev, buf_pa)) {
+	mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
+	if (pci_dma_mapping_error(card->dev, mapping.addr)) {
 		dev_err(adapter->dev, "failed to map pci memory!\n");
 		return -1;
 	}
-	memcpy(skb->cb, &buf_pa, sizeof(dma_addr_t));
+	mapping.len = size;
+	memcpy(skb->cb, &mapping, sizeof(mapping));
 	return 0;
 }
 
+static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
+				     struct sk_buff *skb, int flags)
+{
+	struct pcie_service_card *card = adapter->card;
+	struct mwifiex_dma_mapping mapping;
+
+	MWIFIEX_SKB_PACB(skb, &mapping);
+	pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
+}
+
 /*
  * This function reads sleep cookie and checks if FW is ready
  */
@@ -456,7 +467,7 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
 					   PCI_DMA_FROMDEVICE))
 			return -1;
 
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
+		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
 		dev_dbg(adapter->dev,
 			"info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
@@ -513,7 +524,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
 					   PCI_DMA_FROMDEVICE))
 			return -1;
 
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
+		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
 		dev_dbg(adapter->dev,
 			"info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
@@ -549,8 +560,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
 			desc2 = card->txbd_ring[i];
 			if (card->tx_buf_list[i]) {
 				skb = card->tx_buf_list[i];
-				pci_unmap_single(card->dev, desc2->paddr,
-						 skb->len, PCI_DMA_TODEVICE);
+				mwifiex_unmap_pci_memory(adapter, skb,
+							 PCI_DMA_TODEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc2, 0, sizeof(*desc2));
@@ -558,8 +569,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
 			desc = card->txbd_ring[i];
 			if (card->tx_buf_list[i]) {
 				skb = card->tx_buf_list[i];
-				pci_unmap_single(card->dev, desc->paddr,
-						 skb->len, PCI_DMA_TODEVICE);
+				mwifiex_unmap_pci_memory(adapter, skb,
+							 PCI_DMA_TODEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc, 0, sizeof(*desc));
@@ -587,8 +598,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
 			desc2 = card->rxbd_ring[i];
 			if (card->rx_buf_list[i]) {
 				skb = card->rx_buf_list[i];
-				pci_unmap_single(card->dev, desc2->paddr,
-						 skb->len, PCI_DMA_FROMDEVICE);
+				mwifiex_unmap_pci_memory(adapter, skb,
+							 PCI_DMA_FROMDEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc2, 0, sizeof(*desc2));
@@ -596,8 +607,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
 			desc = card->rxbd_ring[i];
 			if (card->rx_buf_list[i]) {
 				skb = card->rx_buf_list[i];
-				pci_unmap_single(card->dev, desc->paddr,
-						 skb->len, PCI_DMA_FROMDEVICE);
+				mwifiex_unmap_pci_memory(adapter, skb,
+							 PCI_DMA_FROMDEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc, 0, sizeof(*desc));
@@ -622,8 +633,8 @@ static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
 		desc = card->evtbd_ring[i];
 		if (card->evt_buf_list[i]) {
 			skb = card->evt_buf_list[i];
-			pci_unmap_single(card->dev, desc->paddr, MAX_EVENT_SIZE,
-					 PCI_DMA_FROMDEVICE);
+			mwifiex_unmap_pci_memory(adapter, skb,
+						 PCI_DMA_FROMDEVICE);
 			dev_kfree_skb_any(skb);
 		}
 		card->evt_buf_list[i] = NULL;
@@ -861,7 +872,6 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
 static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
 {
 	struct pcie_service_card *card;
-	dma_addr_t buf_pa;
 
 	if (!adapter)
 		return 0;
@@ -869,16 +879,14 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
 	card = adapter->card;
 
 	if (card && card->cmdrsp_buf) {
-		MWIFIEX_SKB_PACB(card->cmdrsp_buf, &buf_pa);
-		pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
-				 PCI_DMA_FROMDEVICE);
+		mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
+					 PCI_DMA_FROMDEVICE);
 		dev_kfree_skb_any(card->cmdrsp_buf);
 	}
 
 	if (card && card->cmd_buf) {
-		MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa);
-		pci_unmap_single(card->dev, buf_pa, card->cmd_buf->len,
-				 PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
+					 PCI_DMA_TODEVICE);
 	}
 	return 0;
 }
@@ -956,7 +964,6 @@ static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
 static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
 {
 	struct sk_buff *skb;
-	dma_addr_t buf_pa;
 	u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
 	struct mwifiex_pcie_buf_desc *desc;
 	struct mwifiex_pfu_buf_desc *desc2;
@@ -986,13 +993,13 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
 			    reg->tx_start_ptr;
 
 		skb = card->tx_buf_list[wrdoneidx];
+
 		if (skb) {
 			dev_dbg(adapter->dev,
 				"SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
 				skb, wrdoneidx);
-			MWIFIEX_SKB_PACB(skb, &buf_pa);
-			pci_unmap_single(card->dev, buf_pa, skb->len,
-					 PCI_DMA_TODEVICE);
+			mwifiex_unmap_pci_memory(adapter, skb,
+						 PCI_DMA_TODEVICE);
 
 			unmap_count++;
 
@@ -1082,12 +1089,12 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 		tmp = (__le16 *)&payload[2];
 		*tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
 
-		if (mwifiex_map_pci_memory(adapter, skb, skb->len ,
+		if (mwifiex_map_pci_memory(adapter, skb, skb->len,
 					   PCI_DMA_TODEVICE))
 			return -1;
 
 		wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
+		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 		card->tx_buf_list[wrindx] = skb;
 
 		if (reg->pfu_enabled) {
@@ -1162,8 +1169,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 
 	return -EINPROGRESS;
 done_unmap:
-	MWIFIEX_SKB_PACB(skb, &buf_pa);
-	pci_unmap_single(card->dev, buf_pa, skb->len, PCI_DMA_TODEVICE);
+	mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 	card->tx_buf_list[wrindx] = NULL;
 	if (reg->pfu_enabled)
 		memset(desc2, 0, sizeof(*desc2));
@@ -1211,9 +1217,13 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 		rd_index = card->rxbd_rdptr & reg->rx_mask;
 		skb_data = card->rx_buf_list[rd_index];
 
-		MWIFIEX_SKB_PACB(skb_data, &buf_pa);
-		pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE,
-				 PCI_DMA_FROMDEVICE);
+		/* If skb allocation was failed earlier for Rx packet,
+		 * rx_buf_list[rd_index] would have been left with a NULL.
+		 */
+		if (!skb_data)
+			return -ENOMEM;
+
+		mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
 		card->rx_buf_list[rd_index] = NULL;
 
 		/* Get data length from interface header -
@@ -1240,7 +1250,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 					   PCI_DMA_FROMDEVICE))
 			return -1;
 
-		MWIFIEX_SKB_PACB(skb_tmp, &buf_pa);
+		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
 
 		dev_dbg(adapter->dev,
 			"RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
@@ -1316,7 +1326,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 	if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
 		return -1;
 
-	MWIFIEX_SKB_PACB(skb, &buf_pa);
+	buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
 	/* Write the lower 32bits of the physical address to low command
 	 * address scratch register
@@ -1325,8 +1335,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 		dev_err(adapter->dev,
 			"%s: failed to write download command to boot code.\n",
 			__func__);
-		pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
-				 PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 		return -1;
 	}
 
@@ -1338,8 +1347,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 		dev_err(adapter->dev,
 			"%s: failed to write download command to boot code.\n",
 			__func__);
-		pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
-				 PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 		return -1;
 	}
 
@@ -1348,8 +1356,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 		dev_err(adapter->dev,
 			"%s: failed to write command len to cmd_size scratch reg\n",
 			__func__);
-		pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
-				 PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 		return -1;
 	}
 
@@ -1358,8 +1365,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 			      CPU_INTR_DOOR_BELL)) {
 		dev_err(adapter->dev,
 			"%s: failed to assert door-bell intr\n", __func__);
-		pci_unmap_single(card->dev, buf_pa,
-				 MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 		return -1;
 	}
 
@@ -1433,7 +1439,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 	*/
 
 	if (card->cmdrsp_buf) {
-		MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa);
+		cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
 		/* Write the lower 32bits of the cmdrsp buffer physical
 		   address */
 		if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
@@ -1454,7 +1460,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 		}
 	}
 
-	MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa);
+	cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
 	/* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
 	if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
 			      (u32)cmd_buf_pa)) {
@@ -1508,13 +1514,17 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 	int count = 0;
 	u16 rx_len;
 	__le16 pkt_len;
-	dma_addr_t buf_pa;
 
 	dev_dbg(adapter->dev, "info: Rx CMD Response\n");
 
-	MWIFIEX_SKB_PACB(skb, &buf_pa);
-	pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
-			 PCI_DMA_FROMDEVICE);
+	mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
+
+	/* Unmap the command as a response has been received. */
+	if (card->cmd_buf) {
+		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
+					 PCI_DMA_TODEVICE);
+		card->cmd_buf = NULL;
+	}
 
 	pkt_len = *((__le16 *)skb->data);
 	rx_len = le16_to_cpu(pkt_len);
@@ -1525,6 +1535,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 		if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
 			mwifiex_process_sleep_confirm_resp(adapter, skb->data,
 							   skb->len);
+			mwifiex_pcie_enable_host_int(adapter);
+			if (mwifiex_write_reg(adapter,
+					      PCIE_CPU_INT_EVENT,
+					      CPU_INTR_SLEEP_CFM_DONE)) {
+				dev_warn(adapter->dev,
+					 "Write register failed\n");
+				return -1;
+			}
 			while (reg->sleep_cookie && (count++ < 10) &&
 			       mwifiex_pcie_ok_to_access_hw(adapter))
 				usleep_range(50, 60);
@@ -1538,8 +1556,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
 					   PCI_DMA_FROMDEVICE))
 			return -1;
-
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
 	} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
 		adapter->curr_cmd->resp_skb = skb;
 		adapter->cmd_resp_received = true;
@@ -1574,8 +1590,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
 					struct sk_buff *skb)
 {
 	struct pcie_service_card *card = adapter->card;
-	dma_addr_t buf_pa;
-	struct sk_buff *skb_tmp;
 
 	if (skb) {
 		card->cmdrsp_buf = skb;
@@ -1585,14 +1599,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
 			return -1;
 	}
 
-	skb_tmp = card->cmd_buf;
-	if (skb_tmp) {
-		MWIFIEX_SKB_PACB(skb_tmp, &buf_pa);
-		pci_unmap_single(card->dev, buf_pa, skb_tmp->len,
-				 PCI_DMA_FROMDEVICE);
-		card->cmd_buf = NULL;
-	}
-
 	return 0;
 }
 
@@ -1605,7 +1611,6 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
 	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 	u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
 	u32 wrptr, event;
-	dma_addr_t buf_pa;
 	struct mwifiex_evt_buf_desc *desc;
 
 	if (!mwifiex_pcie_ok_to_access_hw(adapter))
@@ -1641,9 +1646,7 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
 
 		dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr);
 		skb_cmd = card->evt_buf_list[rdptr];
-		MWIFIEX_SKB_PACB(skb_cmd, &buf_pa);
-		pci_unmap_single(card->dev, buf_pa, MAX_EVENT_SIZE,
-				 PCI_DMA_FROMDEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
 
 		/* Take the pointer and set it to event pointer in adapter
 		   and will return back after event handling callback */
@@ -1689,7 +1692,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
 	int ret = 0;
 	u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
 	u32 wrptr;
-	dma_addr_t buf_pa;
 	struct mwifiex_evt_buf_desc *desc;
 
 	if (!skb)
@@ -1714,11 +1716,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
 					   MAX_EVENT_SIZE,
 					   PCI_DMA_FROMDEVICE))
 			return -1;
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
 		card->evt_buf_list[rdptr] = skb;
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
 		desc = card->evtbd_ring[rdptr];
-		desc->paddr = buf_pa;
+		desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
 		desc->len = (u16)skb->len;
 		desc->flags = 0;
 		skb = NULL;
@@ -1768,7 +1768,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 	struct sk_buff *skb;
 	u32 txlen, tx_blocks = 0, tries, len;
 	u32 block_retry_cnt = 0;
-	dma_addr_t buf_pa;
 	struct pcie_service_card *card = adapter->card;
 	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -1866,8 +1865,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 			goto done;
 		}
 
-		MWIFIEX_SKB_PACB(skb, &buf_pa);
-
 		/* Wait for the command done interrupt */
 		do {
 			if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
@@ -1875,16 +1872,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 				dev_err(adapter->dev, "%s: Failed to read "
 					"interrupt status during fw dnld.\n",
 					__func__);
-				pci_unmap_single(card->dev, buf_pa, skb->len,
-						 PCI_DMA_TODEVICE);
+				mwifiex_unmap_pci_memory(adapter, skb,
+							 PCI_DMA_TODEVICE);
 				ret = -1;
 				goto done;
 			}
 		} while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
 			 CPU_INTR_DOOR_BELL);
 
-		pci_unmap_single(card->dev, buf_pa, skb->len,
-				 PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 
 		offset += txlen;
 	} while (true);
@@ -1993,23 +1989,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
 		adapter->int_status |= pcie_ireg;
 		spin_unlock_irqrestore(&adapter->int_lock, flags);
 
-		if (pcie_ireg & HOST_INTR_CMD_DONE) {
-			if ((adapter->ps_state == PS_STATE_SLEEP_CFM) ||
-			    (adapter->ps_state == PS_STATE_SLEEP)) {
-				mwifiex_pcie_enable_host_int(adapter);
-				if (mwifiex_write_reg(adapter,
-						      PCIE_CPU_INT_EVENT,
-						      CPU_INTR_SLEEP_CFM_DONE)
-						      ) {
-					dev_warn(adapter->dev,
-						 "Write register failed\n");
-					return;
-
-				}
-			}
-		} else if (!adapter->pps_uapsd_mode &&
-			   adapter->ps_state == PS_STATE_SLEEP &&
-			   mwifiex_pcie_ok_to_access_hw(adapter)) {
+		if (!adapter->pps_uapsd_mode &&
+		    adapter->ps_state == PS_STATE_SLEEP &&
+		    mwifiex_pcie_ok_to_access_hw(adapter)) {
 				/* Potentially for PCIe we could get other
 				 * interrupts like shared. Don't change power
 				 * state until cookie is set */
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 0a8a26e10f01..92adbb1ebabc 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -595,7 +595,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 	struct mwifiex_chan_scan_param_set *tmp_chan_list;
 	struct mwifiex_chan_scan_param_set *start_chan;
 
-	u32 tlv_idx, rates_size;
+	u32 tlv_idx, rates_size, cmd_no;
 	u32 total_scan_time;
 	u32 done_early;
 	u8 radio_type;
@@ -733,9 +733,13 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 
 		/* Send the scan command to the firmware with the specified
 		   cfg */
-		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN,
-					     HostCmd_ACT_GEN_SET, 0,
-					     scan_cfg_out);
+		if (priv->adapter->ext_scan)
+			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+		else
+			cmd_no = HostCmd_CMD_802_11_SCAN;
+
+		ret = mwifiex_send_cmd_async(priv, cmd_no, HostCmd_ACT_GEN_SET,
+					     0, scan_cfg_out);
 
 		/* rate IE is updated per scan command but same starting
 		 * pointer is used each time so that rate IE from earlier
@@ -786,6 +790,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct mwifiex_ie_types_num_probes *num_probes_tlv;
 	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
+	struct mwifiex_ie_types_bssid_list *bssid_tlv;
 	u8 *tlv_pos;
 	u32 num_probes;
 	u32 ssid_len;
@@ -848,6 +853,17 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 		       user_scan_in->specific_bssid,
 		       sizeof(scan_cfg_out->specific_bssid));
 
+		if (adapter->ext_scan &&
+		    !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
+			bssid_tlv =
+				(struct mwifiex_ie_types_bssid_list *)tlv_pos;
+			bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
+			bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
+			memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
+			       ETH_ALEN);
+			tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
+		}
+
 		for (i = 0; i < user_scan_in->num_ssids; i++) {
 			ssid_len = user_scan_in->ssid_list[i].ssid_len;
 
@@ -941,7 +957,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 				cpu_to_le16(sizeof(struct ieee80211_ht_cap));
 		radio_type =
 			mwifiex_band_to_radio_type(priv->adapter->config_bands);
-		mwifiex_fill_cap_info(priv, radio_type, ht_cap);
+		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
 		tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
 	}
 
@@ -1576,6 +1592,228 @@ done:
 	return 0;
 }
 
+static int
+mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
+				  u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
+				  bool ext_scan, s32 rssi_val)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct mwifiex_chan_freq_power *cfp;
+	struct cfg80211_bss *bss;
+	u8 bssid[ETH_ALEN];
+	s32 rssi;
+	const u8 *ie_buf;
+	size_t ie_len;
+	u16 channel = 0;
+	u16 beacon_size = 0;
+	u32 curr_bcn_bytes;
+	u32 freq;
+	u16 beacon_period;
+	u16 cap_info_bitmap;
+	u8 *current_ptr;
+	u64 timestamp;
+	struct mwifiex_fixed_bcn_param *bcn_param;
+	struct mwifiex_bss_priv *bss_priv;
+
+	if (*bytes_left >= sizeof(beacon_size)) {
+		/* Extract & convert beacon size from command buffer */
+		memcpy(&beacon_size, *bss_info, sizeof(beacon_size));
+		*bytes_left -= sizeof(beacon_size);
+		*bss_info += sizeof(beacon_size);
+	}
+
+	if (!beacon_size || beacon_size > *bytes_left) {
+		*bss_info += *bytes_left;
+		*bytes_left = 0;
+		return -EFAULT;
+	}
+
+	/* Initialize the current working beacon pointer for this BSS
+	 * iteration
+	 */
+	current_ptr = *bss_info;
+
+	/* Advance the return beacon pointer past the current beacon */
+	*bss_info += beacon_size;
+	*bytes_left -= beacon_size;
+
+	curr_bcn_bytes = beacon_size;
+
+	/* First 5 fields are bssid, RSSI(for legacy scan only),
+	 * time stamp, beacon interval, and capability information
+	 */
+	if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
+	    sizeof(struct mwifiex_fixed_bcn_param)) {
+		dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
+		return -EFAULT;
+	}
+
+	memcpy(bssid, current_ptr, ETH_ALEN);
+	current_ptr += ETH_ALEN;
+	curr_bcn_bytes -= ETH_ALEN;
+
+	if (!ext_scan) {
+		rssi = (s32) *(u8 *)current_ptr;
+		rssi = (-rssi) * 100;		/* Convert dBm to mBm */
+		current_ptr += sizeof(u8);
+		curr_bcn_bytes -= sizeof(u8);
+		dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
+	} else {
+		rssi = rssi_val;
+	}
+
+	bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
+	current_ptr += sizeof(*bcn_param);
+	curr_bcn_bytes -= sizeof(*bcn_param);
+
+	timestamp = le64_to_cpu(bcn_param->timestamp);
+	beacon_period = le16_to_cpu(bcn_param->beacon_period);
+
+	cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
+	dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
+		cap_info_bitmap);
+
+	/* Rest of the current buffer are IE's */
+	ie_buf = current_ptr;
+	ie_len = curr_bcn_bytes;
+	dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
+		curr_bcn_bytes);
+
+	while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
+		u8 element_id, element_len;
+
+		element_id = *current_ptr;
+		element_len = *(current_ptr + 1);
+		if (curr_bcn_bytes < element_len +
+				sizeof(struct ieee_types_header)) {
+			dev_err(adapter->dev,
+				"%s: bytes left < IE length\n", __func__);
+			return -EFAULT;
+		}
+		if (element_id == WLAN_EID_DS_PARAMS) {
+			channel = *(current_ptr +
+				    sizeof(struct ieee_types_header));
+			break;
+		}
+
+		current_ptr += element_len + sizeof(struct ieee_types_header);
+		curr_bcn_bytes -= element_len +
+					sizeof(struct ieee_types_header);
+	}
+
+	if (channel) {
+		struct ieee80211_channel *chan;
+		u8 band;
+
+		/* Skip entry if on csa closed channel */
+		if (channel == priv->csa_chan) {
+			dev_dbg(adapter->dev,
+				"Dropping entry on csa closed channel\n");
+			return 0;
+		}
+
+		band = BAND_G;
+		if (radio_type)
+			band = mwifiex_radio_type_to_band(*radio_type &
+							  (BIT(0) | BIT(1)));
+
+		cfp = mwifiex_get_cfp(priv, band, channel, 0);
+
+		freq = cfp ? cfp->freq : 0;
+
+		chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
+
+		if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
+			bss = cfg80211_inform_bss(priv->wdev->wiphy,
+					    chan, bssid, timestamp,
+					    cap_info_bitmap, beacon_period,
+					    ie_buf, ie_len, rssi, GFP_KERNEL);
+			bss_priv = (struct mwifiex_bss_priv *)bss->priv;
+			bss_priv->band = band;
+			bss_priv->fw_tsf = fw_tsf;
+			if (priv->media_connected &&
+			    !memcmp(bssid, priv->curr_bss_params.bss_descriptor
+				    .mac_address, ETH_ALEN))
+				mwifiex_update_curr_bss_params(priv, bss);
+			cfg80211_put_bss(priv->wdev->wiphy, bss);
+		}
+	} else {
+		dev_dbg(adapter->dev, "missing BSS channel IE\n");
+	}
+
+	return 0;
+}
+
+static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct cmd_ctrl_node *cmd_node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+	if (list_empty(&adapter->scan_pending_q)) {
+		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+		adapter->scan_processing = false;
+		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+		/* Need to indicate IOCTL complete */
+		if (adapter->curr_cmd->wait_q_enabled) {
+			adapter->cmd_wait_q.status = 0;
+			if (!priv->scan_request) {
+				dev_dbg(adapter->dev,
+					"complete internal scan\n");
+				mwifiex_complete_cmd(adapter,
+						     adapter->curr_cmd);
+			}
+		}
+		if (priv->report_scan_result)
+			priv->report_scan_result = false;
+
+		if (priv->scan_request) {
+			dev_dbg(adapter->dev, "info: notifying scan done\n");
+			cfg80211_scan_done(priv->scan_request, 0);
+			priv->scan_request = NULL;
+		} else {
+			priv->scan_aborting = false;
+			dev_dbg(adapter->dev, "info: scan already aborted\n");
+		}
+	} else {
+		if ((priv->scan_aborting && !priv->scan_request) ||
+		    priv->scan_block) {
+			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+					       flags);
+			adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
+			mod_timer(&priv->scan_delay_timer, jiffies);
+			dev_dbg(priv->adapter->dev,
+				"info: %s: triggerring scan abort\n", __func__);
+		} else if (!mwifiex_wmm_lists_empty(adapter) &&
+			   (priv->scan_request && (priv->scan_request->flags &
+					    NL80211_SCAN_FLAG_LOW_PRIORITY))) {
+			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+					       flags);
+			adapter->scan_delay_cnt = 1;
+			mod_timer(&priv->scan_delay_timer, jiffies +
+				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
+			dev_dbg(priv->adapter->dev,
+				"info: %s: deferring scan\n", __func__);
+		} else {
+			/* Get scan command from scan_pending_q and put to
+			 * cmd_pending_q
+			 */
+			cmd_node = list_first_entry(&adapter->scan_pending_q,
+						    struct cmd_ctrl_node, list);
+			list_del(&cmd_node->list);
+			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+					       flags);
+			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
+							true);
+		}
+	}
+
+	return;
+}
+
 /*
  * This function handles the command response of scan.
  *
@@ -1600,7 +1838,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 {
 	int ret = 0;
 	struct mwifiex_adapter *adapter = priv->adapter;
-	struct cmd_ctrl_node *cmd_node;
 	struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
 	struct mwifiex_ie_types_data *tlv_data;
 	struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
@@ -1609,12 +1846,11 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 	u32 bytes_left;
 	u32 idx;
 	u32 tlv_buf_size;
-	struct mwifiex_chan_freq_power *cfp;
 	struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
 	struct chan_band_param_set *chan_band;
 	u8 is_bgscan_resp;
-	unsigned long flags;
-	struct cfg80211_bss *bss;
+	__le64 fw_tsf = 0;
+	u8 *radio_type;
 
 	is_bgscan_resp = (le16_to_cpu(resp->command)
 			  == HostCmd_CMD_802_11_BG_SCAN_QUERY);
@@ -1676,220 +1912,194 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 					     &chan_band_tlv);
 
 	for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
-		u8 bssid[ETH_ALEN];
-		s32 rssi;
-		const u8 *ie_buf;
-		size_t ie_len;
-		u16 channel = 0;
-		__le64 fw_tsf = 0;
-		u16 beacon_size = 0;
-		u32 curr_bcn_bytes;
-		u32 freq;
-		u16 beacon_period;
-		u16 cap_info_bitmap;
-		u8 *current_ptr;
-		u64 timestamp;
-		struct mwifiex_bcn_param *bcn_param;
-		struct mwifiex_bss_priv *bss_priv;
-
-		if (bytes_left >= sizeof(beacon_size)) {
-			/* Extract & convert beacon size from command buffer */
-			memcpy(&beacon_size, bss_info, sizeof(beacon_size));
-			bytes_left -= sizeof(beacon_size);
-			bss_info += sizeof(beacon_size);
-		}
+		/*
+		 * If the TSF TLV was appended to the scan results, save this
+		 * entry's TSF value in the fw_tsf field. It is the firmware's
+		 * TSF value at the time the beacon or probe response was
+		 * received.
+		 */
+		if (tsf_tlv)
+			memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+			       sizeof(fw_tsf));
 
-		if (!beacon_size || beacon_size > bytes_left) {
-			bss_info += bytes_left;
-			bytes_left = 0;
-			ret = -1;
-			goto check_next_scan;
+		if (chan_band_tlv) {
+			chan_band = &chan_band_tlv->chan_band_param[idx];
+			radio_type = &chan_band->radio_type;
+		} else {
+			radio_type = NULL;
 		}
 
-		/* Initialize the current working beacon pointer for this BSS
-		 * iteration */
-		current_ptr = bss_info;
+		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
+							&bytes_left,
+							le64_to_cpu(fw_tsf),
+							radio_type, false, 0);
+		if (ret)
+			goto check_next_scan;
+	}
 
-		/* Advance the return beacon pointer past the current beacon */
-		bss_info += beacon_size;
-		bytes_left -= beacon_size;
+check_next_scan:
+	mwifiex_check_next_scan_command(priv);
+	return ret;
+}
 
-		curr_bcn_bytes = beacon_size;
+/*
+ * This function prepares an extended scan command to be sent to the firmware
+ *
+ * This uses the scan command configuration sent to the command processing
+ * module in command preparation stage to configure a extended scan command
+ * structure to send to firmware.
+ */
+int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
+				struct host_cmd_ds_command *cmd,
+				void *data_buf)
+{
+	struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
+	struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
 
-		/*
-		 * First 5 fields are bssid, RSSI, time stamp, beacon interval,
-		 *   and capability information
-		 */
-		if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
-			dev_err(adapter->dev,
-				"InterpretIE: not enough bytes left\n");
-			continue;
-		}
-		bcn_param = (struct mwifiex_bcn_param *)current_ptr;
-		current_ptr += sizeof(*bcn_param);
-		curr_bcn_bytes -= sizeof(*bcn_param);
+	memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
 
-		memcpy(bssid, bcn_param->bssid, ETH_ALEN);
+	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
 
-		rssi = (s32) bcn_param->rssi;
-		rssi = (-rssi) * 100;		/* Convert dBm to mBm */
-		dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
+				      + scan_cfg->tlv_buf_len + S_DS_GEN));
 
-		timestamp = le64_to_cpu(bcn_param->timestamp);
-		beacon_period = le16_to_cpu(bcn_param->beacon_period);
+	return 0;
+}
 
-		cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
-		dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
-			cap_info_bitmap);
+/* This function handles the command response of extended scan */
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
+{
+	dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
+	return 0;
+}
 
-		/* Rest of the current buffer are IE's */
-		ie_buf = current_ptr;
-		ie_len = curr_bcn_bytes;
-		dev_dbg(adapter->dev,
-			"info: InterpretIE: IELength for this AP = %d\n",
-			curr_bcn_bytes);
+/* This function This function handles the event extended scan report. It
+ * parses extended scan results and informs to cfg80211 stack.
+ */
+int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
+					 void *buf)
+{
+	int ret = 0;
+	struct mwifiex_adapter *adapter = priv->adapter;
+	u8 *bss_info;
+	u32 bytes_left, bytes_left_for_tlv, idx;
+	u16 type, len;
+	struct mwifiex_ie_types_data *tlv;
+	struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
+	struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
+	u8 *radio_type;
+	u64 fw_tsf = 0;
+	s32 rssi = 0;
+	struct mwifiex_event_scan_result *event_scan = buf;
+	u8 num_of_set = event_scan->num_of_set;
+	u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
+	u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
+
+	if (num_of_set > MWIFIEX_MAX_AP) {
+		dev_err(adapter->dev,
+			"EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+			num_of_set);
+		ret = -1;
+		goto check_next_scan;
+	}
 
-		while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
-			u8 element_id, element_len;
+	bytes_left = scan_resp_size;
+	dev_dbg(adapter->dev,
+		"EXT_SCAN: size %d, returned %d APs...",
+		scan_resp_size, num_of_set);
 
-			element_id = *current_ptr;
-			element_len = *(current_ptr + 1);
-			if (curr_bcn_bytes < element_len +
-					sizeof(struct ieee_types_header)) {
-				dev_err(priv->adapter->dev,
-					"%s: bytes left < IE length\n",
-					__func__);
-				goto check_next_scan;
-			}
-			if (element_id == WLAN_EID_DS_PARAMS) {
-				channel = *(current_ptr + sizeof(struct ieee_types_header));
-				break;
-			}
+	tlv = (struct mwifiex_ie_types_data *)scan_resp;
 
-			current_ptr += element_len +
-					sizeof(struct ieee_types_header);
-			curr_bcn_bytes -= element_len +
-					sizeof(struct ieee_types_header);
+	for (idx = 0; idx < num_of_set && bytes_left; idx++) {
+		type = le16_to_cpu(tlv->header.type);
+		len = le16_to_cpu(tlv->header.len);
+		if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
+			dev_err(adapter->dev, "EXT_SCAN: Error bytes left < TLV length\n");
+			break;
 		}
+		scan_rsp_tlv = NULL;
+		scan_info_tlv = NULL;
+		bytes_left_for_tlv = bytes_left;
 
-		/*
-		 * If the TSF TLV was appended to the scan results, save this
-		 * entry's TSF value in the fw_tsf field. It is the firmware's
-		 * TSF value at the time the beacon or probe response was
-		 * received.
+		/* BSS response TLV with beacon or probe response buffer
+		 * at the initial position of each descriptor
 		 */
-		if (tsf_tlv)
-			memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
-			       sizeof(fw_tsf));
-
-		if (channel) {
-			struct ieee80211_channel *chan;
-			u8 band;
+		if (type != TLV_TYPE_BSS_SCAN_RSP)
+			break;
 
-			/* Skip entry if on csa closed channel */
-			if (channel == priv->csa_chan) {
-				dev_dbg(adapter->dev,
-					"Dropping entry on csa closed channel\n");
+		bss_info = (u8 *)tlv;
+		scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
+		tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
+		bytes_left_for_tlv -=
+				(len + sizeof(struct mwifiex_ie_types_header));
+
+		while (bytes_left_for_tlv >=
+		       sizeof(struct mwifiex_ie_types_header) &&
+		       le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
+			type = le16_to_cpu(tlv->header.type);
+			len = le16_to_cpu(tlv->header.len);
+			if (bytes_left_for_tlv <
+			    sizeof(struct mwifiex_ie_types_header) + len) {
+				dev_err(adapter->dev,
+					"EXT_SCAN: Error in processing TLV, bytes left < TLV length\n");
+				scan_rsp_tlv = NULL;
+				bytes_left_for_tlv = 0;
 				continue;
 			}
-
-			band = BAND_G;
-			if (chan_band_tlv) {
-				chan_band =
-					&chan_band_tlv->chan_band_param[idx];
-				band = mwifiex_radio_type_to_band(
-						chan_band->radio_type
-						& (BIT(0) | BIT(1)));
-			}
-
-			cfp = mwifiex_get_cfp(priv, band, channel, 0);
-
-			freq = cfp ? cfp->freq : 0;
-
-			chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
-
-			if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
-				bss = cfg80211_inform_bss(priv->wdev->wiphy,
-					      chan, bssid, timestamp,
-					      cap_info_bitmap, beacon_period,
-					      ie_buf, ie_len, rssi, GFP_KERNEL);
-				bss_priv = (struct mwifiex_bss_priv *)bss->priv;
-				bss_priv->band = band;
-				bss_priv->fw_tsf = le64_to_cpu(fw_tsf);
-				if (priv->media_connected &&
-				    !memcmp(bssid,
-					    priv->curr_bss_params.bss_descriptor
-					    .mac_address, ETH_ALEN))
-					mwifiex_update_curr_bss_params(priv,
-								       bss);
-				cfg80211_put_bss(priv->wdev->wiphy, bss);
+			switch (type) {
+			case TLV_TYPE_BSS_SCAN_INFO:
+				scan_info_tlv =
+				  (struct mwifiex_ie_types_bss_scan_info *)tlv;
+				if (len !=
+				 sizeof(struct mwifiex_ie_types_bss_scan_info) -
+				 sizeof(struct mwifiex_ie_types_header)) {
+					bytes_left_for_tlv = 0;
+					continue;
+				}
+				break;
+			default:
+				break;
 			}
-		} else {
-			dev_dbg(adapter->dev, "missing BSS channel IE\n");
+			tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
+			bytes_left -=
+				(len + sizeof(struct mwifiex_ie_types_header));
+			bytes_left_for_tlv -=
+				(len + sizeof(struct mwifiex_ie_types_header));
 		}
-	}
 
-check_next_scan:
-	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-	if (list_empty(&adapter->scan_pending_q)) {
-		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-		adapter->scan_processing = false;
-		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+		if (!scan_rsp_tlv)
+			break;
 
-		/* Need to indicate IOCTL complete */
-		if (adapter->curr_cmd->wait_q_enabled) {
-			adapter->cmd_wait_q.status = 0;
-			if (!priv->scan_request) {
-				dev_dbg(adapter->dev,
-					"complete internal scan\n");
-				mwifiex_complete_cmd(adapter,
-						     adapter->curr_cmd);
-			}
-		}
-		if (priv->report_scan_result)
-			priv->report_scan_result = false;
+		/* Advance pointer to the beacon buffer length and
+		 * update the bytes count so that the function
+		 * wlan_interpret_bss_desc_with_ie() can handle the
+		 * scan buffer withut any change
+		 */
+		bss_info += sizeof(u16);
+		bytes_left -= sizeof(u16);
 
-		if (priv->scan_request) {
-			dev_dbg(adapter->dev, "info: notifying scan done\n");
-			cfg80211_scan_done(priv->scan_request, 0);
-			priv->scan_request = NULL;
-		} else {
-			priv->scan_aborting = false;
-			dev_dbg(adapter->dev, "info: scan already aborted\n");
-		}
-	} else {
-		if ((priv->scan_aborting && !priv->scan_request) ||
-		    priv->scan_block) {
-			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-					       flags);
-			adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
-			mod_timer(&priv->scan_delay_timer, jiffies);
-			dev_dbg(priv->adapter->dev,
-				"info: %s: triggerring scan abort\n", __func__);
-		} else if (!mwifiex_wmm_lists_empty(adapter) &&
-			   (priv->scan_request && (priv->scan_request->flags &
-					    NL80211_SCAN_FLAG_LOW_PRIORITY))) {
-			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-					       flags);
-			adapter->scan_delay_cnt = 1;
-			mod_timer(&priv->scan_delay_timer, jiffies +
-				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
-			dev_dbg(priv->adapter->dev,
-				"info: %s: deferring scan\n", __func__);
+		if (scan_info_tlv) {
+			rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
+			rssi *= 100;           /* Convert dBm to mBm */
+			dev_dbg(adapter->dev,
+				"info: InterpretIE: RSSI=%d\n", rssi);
+			fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
+			radio_type = &scan_info_tlv->radio_type;
 		} else {
-			/* Get scan command from scan_pending_q and put to
-			   cmd_pending_q */
-			cmd_node = list_first_entry(&adapter->scan_pending_q,
-						    struct cmd_ctrl_node, list);
-			list_del(&cmd_node->list);
-			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-					       flags);
-			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
-							true);
+			radio_type = NULL;
 		}
+		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
+							&bytes_left, fw_tsf,
+							radio_type, true, rssi);
+		if (ret)
+			goto check_next_scan;
 	}
 
+check_next_scan:
+	if (!event_scan->more_event)
+		mwifiex_check_next_scan_command(priv);
+
 	return ret;
 }
 
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 9208a8816b80..5aa3d39e48bc 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -532,8 +532,228 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
 	return 0;
 }
 
+/* This function populates key material v2 command
+ * to set network key for AES & CMAC AES.
+ */
+static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv,
+				  struct host_cmd_ds_command *cmd,
+				  struct mwifiex_ds_encrypt_key *enc_key,
+				  struct host_cmd_ds_802_11_key_material_v2 *km)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	u16 size, len = KEY_PARAMS_FIXED_LEN;
+
+	if (enc_key->is_igtk_key) {
+		dev_dbg(adapter->dev, "%s: Set CMAC AES Key\n", __func__);
+		if (enc_key->is_rx_seq_valid)
+			memcpy(km->key_param_set.key_params.cmac_aes.ipn,
+			       enc_key->pn, enc_key->pn_len);
+		km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST);
+		km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK);
+		km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		km->key_param_set.key_params.cmac_aes.key_len =
+					  cpu_to_le16(enc_key->key_len);
+		memcpy(km->key_param_set.key_params.cmac_aes.key,
+		       enc_key->key_material, enc_key->key_len);
+		len += sizeof(struct mwifiex_cmac_aes_param);
+	} else {
+		dev_dbg(adapter->dev, "%s: Set AES Key\n", __func__);
+		if (enc_key->is_rx_seq_valid)
+			memcpy(km->key_param_set.key_params.aes.pn,
+			       enc_key->pn, enc_key->pn_len);
+		km->key_param_set.key_type = KEY_TYPE_ID_AES;
+		km->key_param_set.key_params.aes.key_len =
+					  cpu_to_le16(enc_key->key_len);
+		memcpy(km->key_param_set.key_params.aes.key,
+		       enc_key->key_material, enc_key->key_len);
+		len += sizeof(struct mwifiex_aes_param);
+	}
+
+	km->key_param_set.len = cpu_to_le16(len);
+	size = len + sizeof(struct mwifiex_ie_types_header) +
+	       sizeof(km->action) + S_DS_GEN;
+	cmd->size = cpu_to_le16(size);
+
+	return 0;
+}
+
+/* This function prepares command to set/get/reset network key(s).
+ * This function prepares key material command for V2 format.
+ * Preparation includes -
+ *      - Setting command ID, action and proper size
+ *      - Setting WEP keys, WAPI keys or WPA keys along with required
+ *        encryption (TKIP, AES) (as required)
+ *      - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
+				   struct host_cmd_ds_command *cmd,
+				   u16 cmd_action, u32 cmd_oid,
+				   struct mwifiex_ds_encrypt_key *enc_key)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	u8 *mac = enc_key->mac_addr;
+	u16 key_info, len = KEY_PARAMS_FIXED_LEN;
+	struct host_cmd_ds_802_11_key_material_v2 *km =
+						&cmd->params.key_material_v2;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+	km->action = cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		dev_dbg(adapter->dev, "%s: Get key\n", __func__);
+		km->key_param_set.key_idx =
+					enc_key->key_index & KEY_INDEX_MASK;
+		km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+		km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+		memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+
+		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
+			key_info = KEY_UNICAST;
+		else
+			key_info = KEY_MCAST;
+
+		if (enc_key->is_igtk_key)
+			key_info |= KEY_IGTK;
+
+		km->key_param_set.key_info = cpu_to_le16(key_info);
+
+		cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+					S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					sizeof(km->action));
+		return 0;
+	}
+
+	memset(&km->key_param_set, 0,
+	       sizeof(struct mwifiex_ie_type_key_param_set_v2));
+
+	if (enc_key->key_disable) {
+		dev_dbg(adapter->dev, "%s: Remove key\n", __func__);
+		km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+		km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+		km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+		km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
+		key_info = KEY_MCAST | KEY_UNICAST;
+		km->key_param_set.key_info = cpu_to_le16(key_info);
+		memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+		cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+					S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					sizeof(km->action));
+		return 0;
+	}
+
+	km->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
+	km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+	key_info = KEY_ENABLED;
+	memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
+
+	if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
+		dev_dbg(adapter->dev, "%s: Set WEP Key\n", __func__);
+		len += sizeof(struct mwifiex_wep_param);
+		km->key_param_set.len = cpu_to_le16(len);
+		km->key_param_set.key_type = KEY_TYPE_ID_WEP;
+
+		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+				key_info |= KEY_MCAST | KEY_UNICAST;
+		} else {
+			if (enc_key->is_current_wep_key) {
+				key_info |= KEY_MCAST | KEY_UNICAST;
+				if (km->key_param_set.key_idx ==
+				    (priv->wep_key_curr_index & KEY_INDEX_MASK))
+					key_info |= KEY_DEFAULT;
+			} else {
+				if (mac) {
+					if (is_broadcast_ether_addr(mac))
+						key_info |= KEY_MCAST;
+					else
+						key_info |= KEY_UNICAST |
+							    KEY_DEFAULT;
+				} else {
+					key_info |= KEY_MCAST;
+				}
+			}
+		}
+		km->key_param_set.key_info = cpu_to_le16(key_info);
+
+		km->key_param_set.key_params.wep.key_len =
+						  cpu_to_le16(enc_key->key_len);
+		memcpy(km->key_param_set.key_params.wep.key,
+		       enc_key->key_material, enc_key->key_len);
+
+		cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+					len + sizeof(km->action) + S_DS_GEN);
+		return 0;
+	}
+
+	if (is_broadcast_ether_addr(mac))
+		key_info |= KEY_MCAST | KEY_RX_KEY;
+	else
+		key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
+
+	if (enc_key->is_wapi_key) {
+		dev_dbg(adapter->dev, "%s: Set WAPI Key\n", __func__);
+		km->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+		memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn,
+		       PN_LEN);
+		km->key_param_set.key_params.wapi.key_len =
+						cpu_to_le16(enc_key->key_len);
+		memcpy(km->key_param_set.key_params.wapi.key,
+		       enc_key->key_material, enc_key->key_len);
+		if (is_broadcast_ether_addr(mac))
+			priv->sec_info.wapi_key_on = true;
+
+		if (!priv->sec_info.wapi_key_on)
+			key_info |= KEY_DEFAULT;
+		km->key_param_set.key_info = cpu_to_le16(key_info);
+
+		len += sizeof(struct mwifiex_wapi_param);
+		km->key_param_set.len = cpu_to_le16(len);
+		cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+					len + sizeof(km->action) + S_DS_GEN);
+		return 0;
+	}
+
+	if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+		key_info |= KEY_DEFAULT;
+		/* Enable unicast bit for WPA-NONE/ADHOC_AES */
+		if (!priv->sec_info.wpa2_enabled &&
+		    !is_broadcast_ether_addr(mac))
+			key_info |= KEY_UNICAST;
+	} else {
+		/* Enable default key for WPA/WPA2 */
+		if (!priv->wpa_is_gtk_set)
+			key_info |= KEY_DEFAULT;
+	}
+
+	km->key_param_set.key_info = cpu_to_le16(key_info);
+
+	if (enc_key->key_len == WLAN_KEY_LEN_CCMP)
+		return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km);
+
+	if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
+		dev_dbg(adapter->dev, "%s: Set TKIP Key\n", __func__);
+		if (enc_key->is_rx_seq_valid)
+			memcpy(km->key_param_set.key_params.tkip.pn,
+			       enc_key->pn, enc_key->pn_len);
+		km->key_param_set.key_type = KEY_TYPE_ID_TKIP;
+		km->key_param_set.key_params.tkip.key_len =
+						cpu_to_le16(enc_key->key_len);
+		memcpy(km->key_param_set.key_params.tkip.key,
+		       enc_key->key_material, enc_key->key_len);
+
+		len += sizeof(struct mwifiex_tkip_param);
+		km->key_param_set.len = cpu_to_le16(len);
+		cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) +
+					len + sizeof(km->action) + S_DS_GEN);
+	}
+
+	return 0;
+}
+
 /*
  * This function prepares command to set/get/reset network key(s).
+ * This function prepares key material command for V1 format.
  *
  * Preparation includes -
  *      - Setting command ID, action and proper size
@@ -542,10 +762,10 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int
-mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
-				struct host_cmd_ds_command *cmd,
-				u16 cmd_action, u32 cmd_oid,
-				struct mwifiex_ds_encrypt_key *enc_key)
+mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
+				   struct host_cmd_ds_command *cmd,
+				   u16 cmd_action, u32 cmd_oid,
+				   struct mwifiex_ds_encrypt_key *enc_key)
 {
 	struct host_cmd_ds_802_11_key_material *key_material =
 		&cmd->params.key_material;
@@ -724,6 +944,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
 	return ret;
 }
 
+/* Wrapper function for setting network key depending upon FW KEY API version */
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+				struct host_cmd_ds_command *cmd,
+				u16 cmd_action, u32 cmd_oid,
+				struct mwifiex_ds_encrypt_key *enc_key)
+{
+	if (priv->adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2)
+		return mwifiex_cmd_802_11_key_material_v2(priv, cmd,
+							  cmd_action, cmd_oid,
+							  enc_key);
+
+	else
+		return mwifiex_cmd_802_11_key_material_v1(priv, cmd,
+							  cmd_action, cmd_oid,
+							  enc_key);
+}
+
 /*
  * This function prepares command to set/get 11d domain information.
  *
@@ -1280,6 +1518,127 @@ mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
 	return 0;
 }
 
+static int
+mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
+		      struct host_cmd_ds_command *cmd,
+		      void *data_buf)
+{
+	struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper;
+	struct mwifiex_ds_tdls_oper *oper = data_buf;
+	struct mwifiex_sta_node *sta_ptr;
+	struct host_cmd_tlv_rates *tlv_rates;
+	struct mwifiex_ie_types_htcap *ht_capab;
+	struct mwifiex_ie_types_qos_info *wmm_qos_info;
+	struct mwifiex_ie_types_extcap *extcap;
+	struct mwifiex_ie_types_vhtcap *vht_capab;
+	struct mwifiex_ie_types_aid *aid;
+	u8 *pos, qos_info;
+	u16 config_len = 0;
+	struct station_parameters *params = priv->sta_params;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER);
+	cmd->size = cpu_to_le16(S_DS_GEN);
+	le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper));
+
+	tdls_oper->reason = 0;
+	memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN);
+	sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac);
+
+	pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper);
+
+	switch (oper->tdls_action) {
+	case MWIFIEX_TDLS_DISABLE_LINK:
+		tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
+		break;
+	case MWIFIEX_TDLS_CREATE_LINK:
+		tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
+		break;
+	case MWIFIEX_TDLS_CONFIG_LINK:
+		tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG);
+
+		if (!params) {
+			dev_err(priv->adapter->dev,
+				"TDLS config params not available for %pM\n",
+				oper->peer_mac);
+			return -ENODATA;
+		}
+
+		*(__le16 *)pos = cpu_to_le16(params->capability);
+		config_len += sizeof(params->capability);
+
+		qos_info = params->uapsd_queues | (params->max_sp << 5);
+		wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos +
+								    config_len);
+		wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA);
+		wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info));
+		wmm_qos_info->qos_info = qos_info;
+		config_len += sizeof(struct mwifiex_ie_types_qos_info);
+
+		if (params->ht_capa) {
+			ht_capab = (struct mwifiex_ie_types_htcap *)(pos +
+								    config_len);
+			ht_capab->header.type =
+					    cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+			ht_capab->header.len =
+				   cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+			memcpy(&ht_capab->ht_cap, params->ht_capa,
+			       sizeof(struct ieee80211_ht_cap));
+			config_len += sizeof(struct mwifiex_ie_types_htcap);
+		}
+
+		if (params->supported_rates && params->supported_rates_len) {
+			tlv_rates = (struct host_cmd_tlv_rates *)(pos +
+								  config_len);
+			tlv_rates->header.type =
+					       cpu_to_le16(WLAN_EID_SUPP_RATES);
+			tlv_rates->header.len =
+				       cpu_to_le16(params->supported_rates_len);
+			memcpy(tlv_rates->rates, params->supported_rates,
+			       params->supported_rates_len);
+			config_len += sizeof(struct host_cmd_tlv_rates) +
+				      params->supported_rates_len;
+		}
+
+		if (params->ext_capab && params->ext_capab_len) {
+			extcap = (struct mwifiex_ie_types_extcap *)(pos +
+								    config_len);
+			extcap->header.type =
+					   cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
+			extcap->header.len = cpu_to_le16(params->ext_capab_len);
+			memcpy(extcap->ext_capab, params->ext_capab,
+			       params->ext_capab_len);
+			config_len += sizeof(struct mwifiex_ie_types_extcap) +
+				      params->ext_capab_len;
+		}
+		if (params->vht_capa) {
+			vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos +
+								    config_len);
+			vht_capab->header.type =
+					   cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
+			vht_capab->header.len =
+				  cpu_to_le16(sizeof(struct ieee80211_vht_cap));
+			memcpy(&vht_capab->vht_cap, params->vht_capa,
+			       sizeof(struct ieee80211_vht_cap));
+			config_len += sizeof(struct mwifiex_ie_types_vhtcap);
+		}
+		if (params->aid) {
+			aid = (struct mwifiex_ie_types_aid *)(pos + config_len);
+			aid->header.type = cpu_to_le16(WLAN_EID_AID);
+			aid->header.len = cpu_to_le16(sizeof(params->aid));
+			aid->aid = cpu_to_le16(params->aid);
+			config_len += sizeof(struct mwifiex_ie_types_aid);
+		}
+
+		break;
+	default:
+		dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
+		return -ENOTSUPP;
+	}
+
+	le16_add_cpu(&cmd->size, config_len);
+
+	return 0;
+}
 /*
  * This function prepares the commands before sending them to the firmware.
  *
@@ -1472,6 +1831,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 		ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action,
 							 data_buf);
 		break;
+	case HostCmd_CMD_802_11_SCAN_EXT:
+		ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf);
+		break;
 	case HostCmd_CMD_MAC_REG_ACCESS:
 	case HostCmd_CMD_BBP_REG_ACCESS:
 	case HostCmd_CMD_RF_REG_ACCESS:
@@ -1507,6 +1869,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 		ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action,
 					       data_buf);
 		break;
+	case HostCmd_CMD_TDLS_OPER:
+		ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
+		break;
 	default:
 		dev_err(priv->adapter->dev,
 			"PREP_CMD: unknown cmd- %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 24523e4015cb..1c5e18804074 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -69,6 +69,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
 
 		break;
 	case HostCmd_CMD_802_11_SCAN:
+	case HostCmd_CMD_802_11_SCAN_EXT:
 		/* Cancel all pending scan command */
 		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
 		list_for_each_entry_safe(cmd_node, tmp_node,
@@ -561,13 +562,13 @@ static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
 }
 
 /*
- * This function handles the command response of set/get key material.
+ * This function handles the command response of set/get v1 key material.
  *
  * Handling includes updating the driver parameters to reflect the
  * changes.
  */
-static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
-					   struct host_cmd_ds_command *resp)
+static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
+					      struct host_cmd_ds_command *resp)
 {
 	struct host_cmd_ds_802_11_key_material *key =
 						&resp->params.key_material;
@@ -590,6 +591,51 @@ static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
 }
 
 /*
+ * This function handles the command response of set/get v2 key material.
+ *
+ * Handling includes updating the driver parameters to reflect the
+ * changes.
+ */
+static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
+					      struct host_cmd_ds_command *resp)
+{
+	struct host_cmd_ds_802_11_key_material_v2 *key_v2;
+	__le16 len;
+
+	key_v2 = &resp->params.key_material_v2;
+	if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
+		if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
+			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
+			priv->wpa_is_gtk_set = true;
+			priv->scan_block = false;
+		}
+	}
+
+	if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
+		return 0;
+
+	memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
+	       WLAN_KEY_LEN_CCMP);
+	priv->aes_key_v2.key_param_set.key_params.aes.key_len =
+				key_v2->key_param_set.key_params.aes.key_len;
+	len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
+	memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
+	       key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
+
+	return 0;
+}
+
+/* Wrapper function for processing response of key material command */
+static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
+					   struct host_cmd_ds_command *resp)
+{
+	if (priv->adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2)
+		return mwifiex_ret_802_11_key_material_v2(priv, resp);
+	else
+		return mwifiex_ret_802_11_key_material_v1(priv, resp);
+}
+
+/*
  * This function handles the command response of get 11d domain information.
  */
 static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
@@ -800,7 +846,60 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
 
 	return 0;
 }
+static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
+				 struct host_cmd_ds_command *resp)
+{
+	struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
+	u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
+	u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
+	struct mwifiex_sta_node *node =
+			   mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
 
+	switch (action) {
+	case ACT_TDLS_DELETE:
+		if (reason)
+			dev_err(priv->adapter->dev,
+				"TDLS link delete for %pM failed: reason %d\n",
+				cmd_tdls_oper->peer_mac, reason);
+		else
+			dev_dbg(priv->adapter->dev,
+				"TDLS link config for %pM successful\n",
+				cmd_tdls_oper->peer_mac);
+		break;
+	case ACT_TDLS_CREATE:
+		if (reason) {
+			dev_err(priv->adapter->dev,
+				"TDLS link creation for %pM failed: reason %d",
+				cmd_tdls_oper->peer_mac, reason);
+			if (node && reason != TDLS_ERR_LINK_EXISTS)
+				node->tdls_status = TDLS_SETUP_FAILURE;
+		} else {
+			dev_dbg(priv->adapter->dev,
+				"TDLS link creation for %pM successful",
+				cmd_tdls_oper->peer_mac);
+		}
+		break;
+	case ACT_TDLS_CONFIG:
+		if (reason) {
+			dev_err(priv->adapter->dev,
+				"TDLS link config for %pM failed, reason %d\n",
+				cmd_tdls_oper->peer_mac, reason);
+			if (node)
+				node->tdls_status = TDLS_SETUP_FAILURE;
+		} else {
+			dev_dbg(priv->adapter->dev,
+				"TDLS link config for %pM successful\n",
+				cmd_tdls_oper->peer_mac);
+		}
+		break;
+	default:
+		dev_err(priv->adapter->dev,
+			"Unknown TDLS command action respnse %d", action);
+		return -1;
+	}
+
+	return 0;
+}
 /*
  * This function handles the command response for subscribe event command.
  */
@@ -871,6 +970,10 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 		ret = mwifiex_ret_802_11_scan(priv, resp);
 		adapter->curr_cmd->wait_q_enabled = false;
 		break;
+	case HostCmd_CMD_802_11_SCAN_EXT:
+		ret = mwifiex_ret_802_11_scan_ext(priv);
+		adapter->curr_cmd->wait_q_enabled = false;
+		break;
 	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
 		ret = mwifiex_ret_802_11_scan(priv, resp);
 		dev_dbg(adapter->dev,
@@ -999,6 +1102,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 		break;
 	case HostCmd_CMD_COALESCE_CFG:
 		break;
+	case HostCmd_CMD_TDLS_OPER:
+		ret = mwifiex_ret_tdls_oper(priv, resp);
+		break;
 	default:
 		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
 			resp->command);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8c351f71f72f..92ff7b324b00 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -54,6 +54,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
 
 	priv->scan_block = false;
 
+	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+		mwifiex_disable_all_tdls_links(priv);
+
 	/* Free Tx and Rx packets, report disconnect to upper layer */
 	mwifiex_clean_txrx(priv);
 
@@ -331,6 +335,14 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		dev_dbg(adapter->dev, "event: PORT RELEASE\n");
 		break;
 
+	case EVENT_EXT_SCAN_REPORT:
+		dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
+		if (adapter->ext_scan)
+			ret = mwifiex_handle_event_ext_scan_report(priv,
+						adapter->event_skb->data);
+
+		break;
+
 	case EVENT_WMM_STATUS_CHANGE:
 		dev_dbg(adapter->dev, "event: WMM status changed\n");
 		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS,
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index c5cb2ed19ec2..b393d55b3aa0 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -290,7 +290,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 
 		if (mwifiex_band_to_radio_type(bss_desc->bss_band) ==
 						HostCmd_SCAN_RADIO_TYPE_BG)
-			config_bands = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+			config_bands = BAND_B | BAND_G | BAND_GN;
 		else
 			config_bands = BAND_A | BAND_AN | BAND_AAC;
 
@@ -865,6 +865,7 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv,
 static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
 			      struct mwifiex_ds_encrypt_key *encrypt_key)
 {
+	struct mwifiex_adapter *adapter = priv->adapter;
 	int ret;
 	struct mwifiex_wep_key *wep_key;
 	int index;
@@ -879,10 +880,17 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
 		/* Copy the required key as the current key */
 		wep_key = &priv->wep_key[index];
 		if (!wep_key->key_length) {
-			dev_err(priv->adapter->dev,
+			dev_err(adapter->dev,
 				"key not set, so cannot enable it\n");
 			return -1;
 		}
+
+		if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) {
+			memcpy(encrypt_key->key_material,
+			       wep_key->key_material, wep_key->key_length);
+			encrypt_key->key_len = wep_key->key_length;
+		}
+
 		priv->wep_key_curr_index = (u16) index;
 		priv->sec_info.wep_enabled = 1;
 	} else {
@@ -897,13 +905,25 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
 		priv->sec_info.wep_enabled = 1;
 	}
 	if (wep_key->key_length) {
+		void *enc_key;
+
+		if (encrypt_key->key_disable)
+			memset(&priv->wep_key[index], 0,
+			       sizeof(struct mwifiex_wep_key));
+
+		if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2)
+			enc_key = encrypt_key;
+		else
+			enc_key = NULL;
+
 		/* Send request to firmware */
 		ret = mwifiex_send_cmd_async(priv,
 					     HostCmd_CMD_802_11_KEY_MATERIAL,
-					     HostCmd_ACT_GEN_SET, 0, NULL);
+					     HostCmd_ACT_GEN_SET, 0, enc_key);
 		if (ret)
 			return ret;
 	}
+
 	if (priv->sec_info.wep_enabled)
 		priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
 	else
@@ -1044,19 +1064,27 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
 
 	memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
 	encrypt_key.key_len = key_len;
+	encrypt_key.key_index = key_index;
 
 	if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
 		encrypt_key.is_igtk_key = true;
 
 	if (!disable) {
-		encrypt_key.key_index = key_index;
 		if (key_len)
 			memcpy(encrypt_key.key_material, key, key_len);
+		else
+			encrypt_key.is_current_wep_key = true;
+
 		if (mac_addr)
 			memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
-		if (kp && kp->seq && kp->seq_len)
+		if (kp && kp->seq && kp->seq_len) {
 			memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
+			encrypt_key.pn_len = kp->seq_len;
+			encrypt_key.is_rx_seq_valid = true;
+		}
 	} else {
+		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
+			return 0;
 		encrypt_key.key_disable = true;
 		if (mac_addr)
 			memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
@@ -1391,7 +1419,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
  * with requisite parameters and calls the IOCTL handler.
  */
 int
-mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
+mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
 {
 	struct mwifiex_ds_misc_gen_ie gen_ie;
 
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 4651d676df38..b6aa958bd6e4 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -88,11 +88,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 	struct rxpd *local_rx_pd;
 	int hdr_chop;
 	struct ethhdr *eth;
+	u16 rx_pkt_off, rx_pkt_len;
+	u8 *offset;
 
 	local_rx_pd = (struct rxpd *) (skb->data);
 
-	rx_pkt_hdr = (void *)local_rx_pd +
-		     le16_to_cpu(local_rx_pd->rx_pkt_offset);
+	rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
+	rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
+	rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
 
 	if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
 		     sizeof(bridge_tunnel_header))) ||
@@ -142,6 +145,12 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 		return 0;
 	}
 
+	if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+	    ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
+		offset = (u8 *)local_rx_pd + rx_pkt_off;
+		mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
+	}
+
 	priv->rxpd_rate = local_rx_pd->rx_rate;
 
 	priv->rxpd_htinfo = local_rx_pd->ht_info;
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 354d64c9606f..1236a5de7bca 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -95,6 +95,9 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 		}
 	}
 
+	if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
+		local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
+
 	/* Offset of actual data */
 	pkt_offset = sizeof(struct txpd) + pad;
 	if (pkt_type == PKT_TYPE_MGMT) {
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
new file mode 100644
index 000000000000..5efd456af571
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -0,0 +1,1044 @@
+/* Marvell Wireless LAN device driver: TDLS handling
+ *
+ * Copyright (C) 2014, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "11n_rxreorder.h"
+#include "11ac.h"
+
+#define TDLS_REQ_FIX_LEN      6
+#define TDLS_RESP_FIX_LEN     8
+#define TDLS_CONFIRM_FIX_LEN  6
+
+static void
+mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
+{
+	struct mwifiex_ra_list_tbl *ra_list;
+	struct list_head *tid_list;
+	struct sk_buff *skb, *tmp;
+	struct mwifiex_txinfo *tx_info;
+	unsigned long flags;
+	u32 tid;
+	u8 tid_down;
+
+	dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
+	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
+		if (!ether_addr_equal(mac, skb->data))
+			continue;
+
+		__skb_unlink(skb, &priv->tdls_txq);
+		tx_info = MWIFIEX_SKB_TXCB(skb);
+		tid = skb->priority;
+		tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+
+		if (status == TDLS_SETUP_COMPLETE) {
+			ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
+			ra_list->tdls_link = true;
+			tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+		} else {
+			tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
+			if (!list_empty(tid_list))
+				ra_list = list_first_entry(tid_list,
+					      struct mwifiex_ra_list_tbl, list);
+			else
+				ra_list = NULL;
+			tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
+		}
+
+		if (!ra_list) {
+			mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+			continue;
+		}
+
+		skb_queue_tail(&ra_list->skb_head, skb);
+
+		ra_list->ba_pkt_count++;
+		ra_list->total_pkt_count++;
+
+		if (atomic_read(&priv->wmm.highest_queued_prio) <
+						       tos_to_tid_inv[tid_down])
+			atomic_set(&priv->wmm.highest_queued_prio,
+				   tos_to_tid_inv[tid_down]);
+
+		atomic_inc(&priv->wmm.tx_pkts_queued);
+	}
+
+	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+	return;
+}
+
+static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_ra_list_tbl *ra_list;
+	struct list_head *ra_list_head;
+	struct sk_buff *skb, *tmp;
+	unsigned long flags;
+	int i;
+
+	dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
+	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
+			ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+			list_for_each_entry(ra_list, ra_list_head, list) {
+				skb_queue_walk_safe(&ra_list->skb_head, skb,
+						    tmp) {
+					if (!ether_addr_equal(mac, skb->data))
+						continue;
+					__skb_unlink(skb, &ra_list->skb_head);
+					atomic_dec(&priv->wmm.tx_pkts_queued);
+					ra_list->total_pkt_count--;
+					skb_queue_tail(&priv->tdls_txq, skb);
+				}
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+	return;
+}
+
+/* This function appends rate TLV to scan config command. */
+static int
+mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
+			     struct sk_buff *skb)
+{
+	u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
+	u16 rates_size, supp_rates_size, ext_rates_size;
+
+	memset(rates, 0, sizeof(rates));
+	rates_size = mwifiex_get_supported_rates(priv, rates);
+
+	supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
+
+	if (skb_tailroom(skb) < rates_size + 4) {
+		dev_err(priv->adapter->dev,
+			"Insuffient space while adding rates\n");
+		return -ENOMEM;
+	}
+
+	pos = skb_put(skb, supp_rates_size + 2);
+	*pos++ = WLAN_EID_SUPP_RATES;
+	*pos++ = supp_rates_size;
+	memcpy(pos, rates, supp_rates_size);
+
+	if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
+		ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
+		pos = skb_put(skb, ext_rates_size + 2);
+		*pos++ = WLAN_EID_EXT_SUPP_RATES;
+		*pos++ = ext_rates_size;
+		memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
+		       ext_rates_size);
+	}
+
+	return 0;
+}
+
+static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
+				struct sk_buff *skb)
+{
+	struct ieee_types_assoc_rsp *assoc_rsp;
+	u8 *pos;
+
+	assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
+	pos = (void *)skb_put(skb, 4);
+	*pos++ = WLAN_EID_AID;
+	*pos++ = 2;
+	*pos++ = le16_to_cpu(assoc_rsp->a_id);
+
+	return;
+}
+
+static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
+				      struct sk_buff *skb)
+{
+	struct ieee80211_vht_cap vht_cap;
+	u8 *pos;
+
+	pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+	*pos++ = WLAN_EID_VHT_CAPABILITY;
+	*pos++ = sizeof(struct ieee80211_vht_cap);
+
+	memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
+
+	mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
+	memcpy(pos, &vht_cap, sizeof(struct ieee80211_ht_cap));
+
+	return 0;
+}
+
+static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
+				     u8 *mac, struct sk_buff *skb)
+{
+	struct mwifiex_bssdescriptor *bss_desc;
+	struct ieee80211_vht_operation *vht_oper;
+	struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
+	struct mwifiex_sta_node *sta_ptr;
+	struct mwifiex_adapter *adapter = priv->adapter;
+	u8 supp_chwd_set, peer_supp_chwd_set;
+	u8 *pos, ap_supp_chwd_set, chan_bw;
+	u16 mcs_map_user, mcs_map_resp, mcs_map_result;
+	u16 mcs_user, mcs_resp, nss;
+	u32 usr_vht_cap_info;
+
+	bss_desc = &priv->curr_bss_params.bss_descriptor;
+
+	sta_ptr = mwifiex_get_sta_entry(priv, mac);
+	if (unlikely(!sta_ptr)) {
+		dev_warn(adapter->dev, "TDLS peer station not found in list\n");
+		return -1;
+	}
+
+	if (!mwifiex_is_bss_in_11ac_mode(priv)) {
+		if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
+		   WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
+			dev_dbg(adapter->dev,
+				"TDLS peer doesn't support wider bandwitdh\n");
+			return 0;
+		}
+	} else {
+		ap_vht_cap = bss_desc->bcn_vht_cap;
+	}
+
+	pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
+	*pos++ = WLAN_EID_VHT_OPERATION;
+	*pos++ = sizeof(struct ieee80211_vht_operation);
+	vht_oper = (struct ieee80211_vht_operation *)pos;
+
+	if (bss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
+
+	/* find the minmum bandwith between AP/TDLS peers */
+	vht_cap = &sta_ptr->tdls_cap.vhtcap;
+	supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+	peer_supp_chwd_set =
+			 GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
+	supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
+
+	/* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
+
+	if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
+	    WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
+		ap_supp_chwd_set =
+		      GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
+		supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
+	}
+
+	switch (supp_chwd_set) {
+	case IEEE80211_VHT_CHANWIDTH_80MHZ:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
+		break;
+	case IEEE80211_VHT_CHANWIDTH_160MHZ:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
+		break;
+	case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
+		break;
+	default:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+
+	mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
+	mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
+	mcs_map_result = 0;
+
+	for (nss = 1; nss <= 8; nss++) {
+		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+
+		if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
+		    (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      IEEE80211_VHT_MCS_NOT_SUPPORTED);
+		else
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      min_t(u16, mcs_user, mcs_resp));
+	}
+
+	vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
+
+	switch (vht_oper->chan_width) {
+	case IEEE80211_VHT_CHANWIDTH_80MHZ:
+		chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
+		break;
+	case IEEE80211_VHT_CHANWIDTH_160MHZ:
+		chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
+		break;
+	case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+		chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
+		break;
+	default:
+		chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+	vht_oper->center_freq_seg1_idx =
+			mwifiex_get_center_freq_index(priv, BAND_AAC,
+						      bss_desc->channel,
+						      chan_bw);
+
+	return 0;
+}
+
+static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
+				       struct sk_buff *skb)
+{
+	struct ieee_types_extcap *extcap;
+
+	extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
+	extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
+	extcap->ieee_hdr.len = 8;
+	memset(extcap->ext_capab, 0, 8);
+	extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
+
+	if (priv->adapter->is_hw_11ac_capable)
+		extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
+}
+
+static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
+{
+	u8 *pos = (void *)skb_put(skb, 3);
+
+	*pos++ = WLAN_EID_QOS_CAPA;
+	*pos++ = 1;
+	*pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
+}
+
+static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
+			     u8 *peer, u8 action_code, u8 dialog_token,
+			     u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_tdls_data *tf;
+	int ret;
+	u16 capab;
+	struct ieee80211_ht_cap *ht_cap;
+	u8 radio, *pos;
+
+	capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+
+	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+	memcpy(tf->da, peer, ETH_ALEN);
+	memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
+	tf->ether_type = cpu_to_be16(ETH_P_TDLS);
+	tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+		skb_put(skb, sizeof(tf->u.setup_req));
+		tf->u.setup_req.dialog_token = dialog_token;
+		tf->u.setup_req.capability = cpu_to_le16(capab);
+		ret = mwifiex_tdls_append_rates_ie(priv, skb);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+		*pos++ = WLAN_EID_HT_CAPABILITY;
+		*pos++ = sizeof(struct ieee80211_ht_cap);
+		ht_cap = (void *)pos;
+		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		if (priv->adapter->is_hw_11ac_capable) {
+			ret = mwifiex_tdls_add_vht_capab(priv, skb);
+			if (ret) {
+				dev_kfree_skb_any(skb);
+				return ret;
+			}
+			mwifiex_tdls_add_aid(priv, skb);
+		}
+
+		mwifiex_tdls_add_ext_capab(priv, skb);
+		mwifiex_tdls_add_qos_capab(skb);
+		break;
+
+	case WLAN_TDLS_SETUP_RESPONSE:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+		skb_put(skb, sizeof(tf->u.setup_resp));
+		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tf->u.setup_resp.dialog_token = dialog_token;
+		tf->u.setup_resp.capability = cpu_to_le16(capab);
+		ret = mwifiex_tdls_append_rates_ie(priv, skb);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+		*pos++ = WLAN_EID_HT_CAPABILITY;
+		*pos++ = sizeof(struct ieee80211_ht_cap);
+		ht_cap = (void *)pos;
+		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		if (priv->adapter->is_hw_11ac_capable) {
+			ret = mwifiex_tdls_add_vht_capab(priv, skb);
+			if (ret) {
+				dev_kfree_skb_any(skb);
+				return ret;
+			}
+			mwifiex_tdls_add_aid(priv, skb);
+		}
+
+		mwifiex_tdls_add_ext_capab(priv, skb);
+		mwifiex_tdls_add_qos_capab(skb);
+		break;
+
+	case WLAN_TDLS_SETUP_CONFIRM:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+		skb_put(skb, sizeof(tf->u.setup_cfm));
+		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tf->u.setup_cfm.dialog_token = dialog_token;
+		if (priv->adapter->is_hw_11ac_capable) {
+			ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
+			if (ret) {
+				dev_kfree_skb_any(skb);
+				return ret;
+			}
+		}
+		break;
+
+	case WLAN_TDLS_TEARDOWN:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_TEARDOWN;
+		skb_put(skb, sizeof(tf->u.teardown));
+		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+		skb_put(skb, sizeof(tf->u.discover_req));
+		tf->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
+{
+	struct ieee80211_tdls_lnkie *lnkid;
+
+	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+	lnkid->ie_type = WLAN_EID_LINK_ID;
+	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
+			sizeof(struct ieee_types_header);
+
+	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
+				 u8 *peer, u8 action_code, u8 dialog_token,
+				 u16 status_code, const u8 *extra_ies,
+				 size_t extra_ies_len)
+{
+	struct sk_buff *skb;
+	struct mwifiex_txinfo *tx_info;
+	struct timeval tv;
+	int ret;
+	u16 skb_len;
+
+	skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
+		  max(sizeof(struct ieee80211_mgmt),
+		      sizeof(struct ieee80211_tdls_data)) +
+		  MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+		  MWIFIEX_SUPPORTED_RATES +
+		  3 + /* Qos Info */
+		  sizeof(struct ieee_types_extcap) +
+		  sizeof(struct ieee80211_ht_cap) +
+		  sizeof(struct ieee_types_bss_co_2040) +
+		  sizeof(struct ieee80211_ht_operation) +
+		  sizeof(struct ieee80211_tdls_lnkie) +
+		  extra_ies_len;
+
+	if (priv->adapter->is_hw_11ac_capable)
+		skb_len += sizeof(struct ieee_types_vht_cap) +
+			   sizeof(struct ieee_types_vht_oper) +
+			   sizeof(struct ieee_types_aid);
+
+	skb = dev_alloc_skb(skb_len);
+	if (!skb) {
+		dev_err(priv->adapter->dev,
+			"allocate skb failed for management frame\n");
+		return -ENOMEM;
+	}
+	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_CONFIRM:
+	case WLAN_TDLS_TEARDOWN:
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
+						   dialog_token, status_code,
+						   skb);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+		if (extra_ies_len)
+			memcpy(skb_put(skb, extra_ies_len), extra_ies,
+			       extra_ies_len);
+		mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
+					 priv->cfg_bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
+						   dialog_token, status_code,
+						   skb);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+		if (extra_ies_len)
+			memcpy(skb_put(skb, extra_ies_len), extra_ies,
+			       extra_ies_len);
+		mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
+					 priv->cfg_bssid);
+		break;
+	}
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_RESPONSE:
+		skb->priority = MWIFIEX_PRIO_BK;
+		break;
+	default:
+		skb->priority = MWIFIEX_PRIO_VI;
+		break;
+	}
+
+	tx_info = MWIFIEX_SKB_TXCB(skb);
+	tx_info->bss_num = priv->bss_num;
+	tx_info->bss_type = priv->bss_type;
+
+	do_gettimeofday(&tv);
+	skb->tstamp = timeval_to_ktime(tv);
+	mwifiex_queue_tx_pkt(priv, skb);
+
+	return 0;
+}
+
+static int
+mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
+				    u8 action_code, u8 dialog_token,
+				    u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_mgmt *mgmt;
+	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	int ret;
+	u16 capab;
+	struct ieee80211_ht_cap *ht_cap;
+	u8 radio, *pos;
+
+	capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+
+	mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
+
+	memset(mgmt, 0, 24);
+	memcpy(mgmt->da, peer, ETH_ALEN);
+	memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+
+	/* add address 4 */
+	pos = skb_put(skb, ETH_ALEN);
+
+	switch (action_code) {
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
+		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+		mgmt->u.action.u.tdls_discover_resp.action_code =
+					      WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+		mgmt->u.action.u.tdls_discover_resp.dialog_token =
+								   dialog_token;
+		mgmt->u.action.u.tdls_discover_resp.capability =
+							     cpu_to_le16(capab);
+		/* move back for addr4 */
+		memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+			sizeof(mgmt->u.action.u.tdls_discover_resp));
+		/* init address 4 */
+		memcpy(pos, bc_addr, ETH_ALEN);
+
+		ret = mwifiex_tdls_append_rates_ie(priv, skb);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+		*pos++ = WLAN_EID_HT_CAPABILITY;
+		*pos++ = sizeof(struct ieee80211_ht_cap);
+		ht_cap = (void *)pos;
+		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return ret;
+		}
+
+		if (priv->adapter->is_hw_11ac_capable) {
+			ret = mwifiex_tdls_add_vht_capab(priv, skb);
+			if (ret) {
+				dev_kfree_skb_any(skb);
+				return ret;
+			}
+			mwifiex_tdls_add_aid(priv, skb);
+		}
+
+		mwifiex_tdls_add_ext_capab(priv, skb);
+		mwifiex_tdls_add_qos_capab(skb);
+		break;
+	default:
+		dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
+				 u8 *peer, u8 action_code, u8 dialog_token,
+				 u16 status_code, const u8 *extra_ies,
+				 size_t extra_ies_len)
+{
+	struct sk_buff *skb;
+	struct mwifiex_txinfo *tx_info;
+	struct timeval tv;
+	u8 *pos;
+	u32 pkt_type, tx_control;
+	u16 pkt_len, skb_len;
+
+	skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
+		  max(sizeof(struct ieee80211_mgmt),
+		      sizeof(struct ieee80211_tdls_data)) +
+		  MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+		  MWIFIEX_SUPPORTED_RATES +
+		  sizeof(struct ieee_types_extcap) +
+		  sizeof(struct ieee80211_ht_cap) +
+		  sizeof(struct ieee_types_bss_co_2040) +
+		  sizeof(struct ieee80211_ht_operation) +
+		  sizeof(struct ieee80211_tdls_lnkie) +
+		  extra_ies_len +
+		  3 + /* Qos Info */
+		  ETH_ALEN; /* Address4 */
+
+	if (priv->adapter->is_hw_11ac_capable)
+		skb_len += sizeof(struct ieee_types_vht_cap) +
+			   sizeof(struct ieee_types_vht_oper) +
+			   sizeof(struct ieee_types_aid);
+
+	skb = dev_alloc_skb(skb_len);
+	if (!skb) {
+		dev_err(priv->adapter->dev,
+			"allocate skb failed for management frame\n");
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+	pkt_type = PKT_TYPE_MGMT;
+	tx_control = 0;
+	pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+	memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+	memcpy(pos, &pkt_type, sizeof(pkt_type));
+	memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
+
+	if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
+						dialog_token, status_code,
+						skb)) {
+		dev_kfree_skb_any(skb);
+		return -EINVAL;
+	}
+
+	if (extra_ies_len)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+	/* the TDLS link IE is always added last we are the responder */
+
+	mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
+				 priv->cfg_bssid);
+
+	skb->priority = MWIFIEX_PRIO_VI;
+
+	tx_info = MWIFIEX_SKB_TXCB(skb);
+	tx_info->bss_num = priv->bss_num;
+	tx_info->bss_type = priv->bss_type;
+	tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+
+	pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
+	memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
+	       sizeof(pkt_len));
+	do_gettimeofday(&tv);
+	skb->tstamp = timeval_to_ktime(tv);
+	mwifiex_queue_tx_pkt(priv, skb);
+
+	return 0;
+}
+
+/* This function process tdls action frame from peer.
+ * Peer capabilities are stored into station node structure.
+ */
+void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
+				       u8 *buf, int len)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	u8 *peer, *pos, *end;
+	u8 i, action, basic;
+	int ie_len = 0;
+
+	if (len < (sizeof(struct ethhdr) + 3))
+		return;
+	if (*(u8 *)(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
+		return;
+	if (*(u8 *)(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
+		return;
+
+	peer = buf + ETH_ALEN;
+	action = *(u8 *)(buf + sizeof(struct ethhdr) + 2);
+
+	/* just handle TDLS setup request/response/confirm */
+	if (action > WLAN_TDLS_SETUP_CONFIRM)
+		return;
+
+	dev_dbg(priv->adapter->dev,
+		"rx:tdls action: peer=%pM, action=%d\n", peer, action);
+
+	sta_ptr = mwifiex_add_sta_entry(priv, peer);
+	if (!sta_ptr)
+		return;
+
+	switch (action) {
+	case WLAN_TDLS_SETUP_REQUEST:
+		if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
+			return;
+
+		pos = buf + sizeof(struct ethhdr) + 4;
+		/* payload 1+ category 1 + action 1 + dialog 1 */
+		sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+		ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
+		pos += 2;
+		break;
+
+	case WLAN_TDLS_SETUP_RESPONSE:
+		if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
+			return;
+		/* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
+		pos = buf + sizeof(struct ethhdr) + 6;
+		sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+		ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
+		pos += 2;
+		break;
+
+	case WLAN_TDLS_SETUP_CONFIRM:
+		if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
+			return;
+		pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
+		ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
+		break;
+	default:
+		dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
+		return;
+	}
+
+	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
+		if (pos + 2 + pos[1] > end)
+			break;
+
+		switch (*pos) {
+		case WLAN_EID_SUPP_RATES:
+			sta_ptr->tdls_cap.rates_len = pos[1];
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->tdls_cap.rates[i] = pos[i + 2];
+			break;
+
+		case WLAN_EID_EXT_SUPP_RATES:
+			basic = sta_ptr->tdls_cap.rates_len;
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
+			sta_ptr->tdls_cap.rates_len += pos[1];
+			break;
+		case WLAN_EID_HT_CAPABILITY:
+			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+			       sizeof(struct ieee80211_ht_cap));
+			sta_ptr->is_11n_enabled = 1;
+			break;
+		case WLAN_EID_HT_OPERATION:
+			memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+			       sizeof(struct ieee80211_ht_operation));
+			break;
+		case WLAN_EID_BSS_COEX_2040:
+			sta_ptr->tdls_cap.coex_2040 = pos[2];
+			break;
+		case WLAN_EID_EXT_CAPABILITY:
+			memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
+			       sizeof(struct ieee_types_header) +
+			       min_t(u8, pos[1], 8));
+			break;
+		case WLAN_EID_RSN:
+			memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
+			       sizeof(struct ieee_types_header) + pos[1]);
+			break;
+		case WLAN_EID_QOS_CAPA:
+			sta_ptr->tdls_cap.qos_info = pos[2];
+			break;
+		case WLAN_EID_VHT_OPERATION:
+			if (priv->adapter->is_hw_11ac_capable)
+				memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+				       sizeof(struct ieee80211_vht_operation));
+			break;
+		case WLAN_EID_VHT_CAPABILITY:
+			if (priv->adapter->is_hw_11ac_capable) {
+				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+				       sizeof(struct ieee80211_vht_cap));
+				sta_ptr->is_11ac_enabled = 1;
+			}
+			break;
+		case WLAN_EID_AID:
+			if (priv->adapter->is_hw_11ac_capable)
+				sta_ptr->tdls_cap.aid =
+					      le16_to_cpu(*(__le16 *)(pos + 2));
+		default:
+			break;
+		}
+	}
+
+	return;
+}
+
+static int
+mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	struct mwifiex_ds_tdls_oper tdls_oper;
+
+	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+	sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+	if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
+		dev_err(priv->adapter->dev,
+			"link absent for peer %pM; cannot config\n", peer);
+		return -EINVAL;
+	}
+
+	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+	tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
+	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
+				     HostCmd_ACT_GEN_SET, 0, &tdls_oper);
+}
+
+static int
+mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	struct mwifiex_ds_tdls_oper tdls_oper;
+
+	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+	sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+	if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
+		dev_dbg(priv->adapter->dev,
+			"Setup already in progress for peer %pM\n", peer);
+		return 0;
+	}
+
+	sta_ptr = mwifiex_add_sta_entry(priv, peer);
+	if (!sta_ptr)
+		return -ENOMEM;
+
+	sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
+	mwifiex_hold_tdls_packets(priv, peer);
+	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+	tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
+	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
+				     HostCmd_ACT_GEN_SET, 0, &tdls_oper);
+}
+
+static int
+mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	struct mwifiex_ds_tdls_oper tdls_oper;
+	unsigned long flags;
+
+	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+	sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+	if (sta_ptr) {
+		if (sta_ptr->is_11n_enabled) {
+			mwifiex_11n_cleanup_reorder_tbl(priv);
+			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+					  flags);
+			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+					       flags);
+		}
+		mwifiex_del_sta_entry(priv, peer);
+	}
+
+	mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
+	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
+	tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
+	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
+				     HostCmd_ACT_GEN_SET, 0, &tdls_oper);
+}
+
+static int
+mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	struct ieee80211_mcs_info mcs;
+	unsigned long flags;
+	int i;
+
+	sta_ptr = mwifiex_get_sta_entry(priv, peer);
+
+	if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
+		dev_dbg(priv->adapter->dev,
+			"tdls: enable link %pM success\n", peer);
+
+		sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
+
+		mcs = sta_ptr->tdls_cap.ht_capb.mcs;
+		if (mcs.rx_mask[0] != 0xff)
+			sta_ptr->is_11n_enabled = true;
+		if (sta_ptr->is_11n_enabled) {
+			if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
+			    IEEE80211_HT_CAP_MAX_AMSDU)
+				sta_ptr->max_amsdu =
+					MWIFIEX_TX_DATA_BUF_SIZE_8K;
+			else
+				sta_ptr->max_amsdu =
+					MWIFIEX_TX_DATA_BUF_SIZE_4K;
+
+			for (i = 0; i < MAX_NUM_TID; i++)
+				sta_ptr->ampdu_sta[i] =
+					      priv->aggr_prio_tbl[i].ampdu_user;
+		} else {
+			for (i = 0; i < MAX_NUM_TID; i++)
+				sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+		}
+
+		memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
+		mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
+	} else {
+		dev_dbg(priv->adapter->dev,
+			"tdls: enable link %pM failed\n", peer);
+		if (sta_ptr) {
+			mwifiex_11n_cleanup_reorder_tbl(priv);
+			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+					  flags);
+			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+					       flags);
+			mwifiex_del_sta_entry(priv, peer);
+		}
+		mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
+
+		return -1;
+	}
+
+	return 0;
+}
+
+int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
+{
+	switch (action) {
+	case MWIFIEX_TDLS_ENABLE_LINK:
+		return mwifiex_tdls_process_enable_link(priv, peer);
+	case MWIFIEX_TDLS_DISABLE_LINK:
+		return mwifiex_tdls_process_disable_link(priv, peer);
+	case MWIFIEX_TDLS_CREATE_LINK:
+		return mwifiex_tdls_process_create_link(priv, peer);
+	case MWIFIEX_TDLS_CONFIG_LINK:
+		return mwifiex_tdls_process_config_link(priv, peer);
+	}
+	return 0;
+}
+
+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *sta_ptr;
+
+	sta_ptr = mwifiex_get_sta_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->tdls_status;
+
+	return TDLS_NOT_SETUP;
+}
+
+void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
+{
+	struct mwifiex_sta_node *sta_ptr;
+	struct mwifiex_ds_tdls_oper tdls_oper;
+	unsigned long flags;
+
+	if (list_empty(&priv->sta_list))
+		return;
+
+	list_for_each_entry(sta_ptr, &priv->sta_list, list) {
+		memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
+
+		if (sta_ptr->is_11n_enabled) {
+			mwifiex_11n_cleanup_reorder_tbl(priv);
+			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
+					  flags);
+			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
+			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+					       flags);
+		}
+
+		mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
+					     TDLS_LINK_TEARDOWN);
+		memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
+		tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
+		if (mwifiex_send_cmd_async(priv, HostCmd_CMD_TDLS_OPER,
+					   HostCmd_ACT_GEN_SET, 0, &tdls_oper))
+			dev_warn(priv->adapter->dev,
+				 "Disable link failed for TDLS peer %pM",
+				 sta_ptr->mac_addr);
+	}
+
+	mwifiex_del_all_sta_list(priv);
+}
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 718066577c6c..2d47ba70225c 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -21,126 +21,8 @@
 #include "main.h"
 #include "11n.h"
 
-/*
- * This function will return the pointer to station entry in station list
- * table which matches specified mac address.
- * This function should be called after acquiring RA list spinlock.
- * NULL is returned if station entry is not found in associated STA list.
- */
-struct mwifiex_sta_node *
-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
-{
-	struct mwifiex_sta_node *node;
-
-	if (!mac)
-		return NULL;
-
-	list_for_each_entry(node, &priv->sta_list, list) {
-		if (!memcmp(node->mac_addr, mac, ETH_ALEN))
-			return node;
-	}
 
-	return NULL;
-}
-
-/*
- * This function will add a sta_node entry to associated station list
- * table with the given mac address.
- * If entry exist already, existing entry is returned.
- * If received mac address is NULL, NULL is returned.
- */
-static struct mwifiex_sta_node *
-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
-{
-	struct mwifiex_sta_node *node;
-	unsigned long flags;
 
-	if (!mac)
-		return NULL;
-
-	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-	node = mwifiex_get_sta_entry(priv, mac);
-	if (node)
-		goto done;
-
-	node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_ATOMIC);
-	if (!node)
-		goto done;
-
-	memcpy(node->mac_addr, mac, ETH_ALEN);
-	list_add_tail(&node->list, &priv->sta_list);
-
-done:
-	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-	return node;
-}
-
-/*
- * This function will search for HT IE in association request IEs
- * and set station HT parameters accordingly.
- */
-static void
-mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
-		       int ies_len, struct mwifiex_sta_node *node)
-{
-	const struct ieee80211_ht_cap *ht_cap;
-
-	if (!ies)
-		return;
-
-	ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
-	if (ht_cap) {
-		node->is_11n_enabled = 1;
-		node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
-				  IEEE80211_HT_CAP_MAX_AMSDU ?
-				  MWIFIEX_TX_DATA_BUF_SIZE_8K :
-				  MWIFIEX_TX_DATA_BUF_SIZE_4K;
-	} else {
-		node->is_11n_enabled = 0;
-	}
-
-	return;
-}
-
-/*
- * This function will delete a station entry from station list
- */
-static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
-{
-	struct mwifiex_sta_node *node;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-
-	node = mwifiex_get_sta_entry(priv, mac);
-	if (node) {
-		list_del(&node->list);
-		kfree(node);
-	}
-
-	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-	return;
-}
-
-/*
- * This function will delete all stations from associated station list.
- */
-static void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
-{
-	struct mwifiex_sta_node *node, *tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-
-	list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
-		list_del(&node->list);
-		kfree(node);
-	}
-
-	INIT_LIST_HEAD(&priv->sta_list);
-	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-	return;
-}
 
 /*
  * This function handles AP interface specific events generated by firmware.
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index e8ebbd4bc3cd..208748804a55 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -22,8 +22,6 @@
 
 #define USB_VERSION	"1.0"
 
-static const char usbdriver_name[] = "usb8xxx";
-
 static struct mwifiex_if_ops usb_ops;
 static struct semaphore add_remove_card_sem;
 static struct usb_card_rec *usb_card;
@@ -527,13 +525,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
 						   MWIFIEX_BSS_ROLE_ANY),
 				  MWIFIEX_ASYNC_CMD);
 
-#ifdef CONFIG_PM
-	/* Resume handler may be called due to remote wakeup,
-	 * force to exit suspend anyway
-	 */
-	usb_disable_autosuspend(card->udev);
-#endif /* CONFIG_PM */
-
 	return 0;
 }
 
@@ -567,13 +558,12 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver mwifiex_usb_driver = {
-	.name = usbdriver_name,
+	.name = "mwifiex_usb",
 	.probe = mwifiex_usb_probe,
 	.disconnect = mwifiex_usb_disconnect,
 	.id_table = mwifiex_usb_table,
 	.suspend = mwifiex_usb_suspend,
 	.resume = mwifiex_usb_resume,
-	.supports_autosuspend = 1,
 };
 
 static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 9b82e225880c..8d37bfc578bd 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -252,3 +252,117 @@ int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
 
 	return 0;
 }
+
+/* This function will return the pointer to station entry in station list
+ * table which matches specified mac address.
+ * This function should be called after acquiring RA list spinlock.
+ * NULL is returned if station entry is not found in associated STA list.
+ */
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node;
+
+	if (!mac)
+		return NULL;
+
+	list_for_each_entry(node, &priv->sta_list, list) {
+		if (!memcmp(node->mac_addr, mac, ETH_ALEN))
+			return node;
+	}
+
+	return NULL;
+}
+
+/* This function will add a sta_node entry to associated station list
+ * table with the given mac address.
+ * If entry exist already, existing entry is returned.
+ * If received mac address is NULL, NULL is returned.
+ */
+struct mwifiex_sta_node *
+mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node;
+	unsigned long flags;
+
+	if (!mac)
+		return NULL;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+	node = mwifiex_get_sta_entry(priv, mac);
+	if (node)
+		goto done;
+
+	node = kzalloc(sizeof(*node), GFP_ATOMIC);
+	if (!node)
+		goto done;
+
+	memcpy(node->mac_addr, mac, ETH_ALEN);
+	list_add_tail(&node->list, &priv->sta_list);
+
+done:
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return node;
+}
+
+/* This function will search for HT IE in association request IEs
+ * and set station HT parameters accordingly.
+ */
+void
+mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
+		       int ies_len, struct mwifiex_sta_node *node)
+{
+	const struct ieee80211_ht_cap *ht_cap;
+
+	if (!ies)
+		return;
+
+	ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
+	if (ht_cap) {
+		node->is_11n_enabled = 1;
+		node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
+				  IEEE80211_HT_CAP_MAX_AMSDU ?
+				  MWIFIEX_TX_DATA_BUF_SIZE_8K :
+				  MWIFIEX_TX_DATA_BUF_SIZE_4K;
+	} else {
+		node->is_11n_enabled = 0;
+	}
+
+	return;
+}
+
+/* This function will delete a station entry from station list */
+void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+	node = mwifiex_get_sta_entry(priv, mac);
+	if (node) {
+		list_del(&node->list);
+		kfree(node);
+	}
+
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return;
+}
+
+/* This function will delete all stations from associated station list. */
+void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
+{
+	struct mwifiex_sta_node *node, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+	list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
+		list_del(&node->list);
+		kfree(node);
+	}
+
+	INIT_LIST_HEAD(&priv->sta_list);
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return;
+}
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
index cb2d0582bd36..ddae57021397 100644
--- a/drivers/net/wireless/mwifiex/util.h
+++ b/drivers/net/wireless/mwifiex/util.h
@@ -30,8 +30,24 @@ static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
 	return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t));
 }
 
-static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, dma_addr_t *buf_pa)
+struct mwifiex_dma_mapping {
+	dma_addr_t addr;
+	size_t len;
+};
+
+static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb,
+					struct mwifiex_dma_mapping *mapping)
 {
-	memcpy(buf_pa, skb->cb, sizeof(dma_addr_t));
+	memcpy(mapping, skb->cb, sizeof(*mapping));
 }
+
+static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb)
+{
+	struct mwifiex_dma_mapping mapping;
+
+	MWIFIEX_SKB_PACB(skb, &mapping);
+
+	return mapping.addr;
+}
+
 #endif /* !_MWIFIEX_UTIL_H_ */
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 13eaeed03898..1c5f2b66f057 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -64,21 +64,6 @@ static u8 tos_to_tid[] = {
 	0x07			/* 1 1 1 AC_VO */
 };
 
-/*
- * This table inverses the tos_to_tid operation to get a priority
- * which is in sequential order, and can be compared.
- * Use this to compare the priority of two different TIDs.
- */
-static u8 tos_to_tid_inv[] = {
-	0x02,  /* from tos_to_tid[2] = 0 */
-	0x00,  /* from tos_to_tid[0] = 1 */
-	0x01,  /* from tos_to_tid[1] = 2 */
-	0x03,
-	0x04,
-	0x05,
-	0x06,
-	0x07};
-
 static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
 
 /*
@@ -175,8 +160,15 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
 			break;
 
 		ra_list->is_11n_enabled = 0;
+		ra_list->tdls_link = false;
 		if (!mwifiex_queuing_ra_based(priv)) {
-			ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+			if (mwifiex_get_tdls_link_status(priv, ra) ==
+			    TDLS_SETUP_COMPLETE) {
+				ra_list->is_11n_enabled =
+					mwifiex_tdls_peer_11n_enabled(priv, ra);
+			} else {
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+			}
 		} else {
 			ra_list->is_11n_enabled =
 				      mwifiex_is_sta_11n_enabled(priv, node);
@@ -213,8 +205,9 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)
  * This function map ACs to TIDs.
  */
 static void
-mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm)
+mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv)
 {
+	struct mwifiex_wmm_desc *wmm = &priv->wmm;
 	u8 *queue_priority = wmm->queue_priority;
 	int i;
 
@@ -224,7 +217,7 @@ mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm)
 	}
 
 	for (i = 0; i < MAX_NUM_TID; ++i)
-		tos_to_tid_inv[tos_to_tid[i]] = (u8)i;
+		priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i;
 
 	atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID);
 }
@@ -285,7 +278,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
 		}
 	}
 
-	mwifiex_wmm_queue_priorities_tid(&priv->wmm);
+	mwifiex_wmm_queue_priorities_tid(priv);
 }
 
 /*
@@ -388,8 +381,7 @@ mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos)
  * AP is disabled (due to call admission control (ACM bit). Mapping
  * of TID to AC is taken care of internally.
  */
-static u8
-mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
+u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
 {
 	enum mwifiex_wmm_ac_e ac, ac_down;
 	u8 new_tid;
@@ -421,9 +413,11 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
 			continue;
 
 		for (i = 0; i < MAX_NUM_TID; ++i) {
-			priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
-			priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i];
-			priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+			priv->aggr_prio_tbl[i].amsdu = priv->tos_to_tid_inv[i];
+			priv->aggr_prio_tbl[i].ampdu_ap =
+							priv->tos_to_tid_inv[i];
+			priv->aggr_prio_tbl[i].ampdu_user =
+							priv->tos_to_tid_inv[i];
 		}
 
 		priv->aggr_prio_tbl[6].amsdu
@@ -546,6 +540,7 @@ void
 mwifiex_clean_txrx(struct mwifiex_private *priv)
 {
 	unsigned long flags;
+	struct sk_buff *skb, *tmp;
 
 	mwifiex_11n_cleanup_reorder_tbl(priv);
 	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
@@ -559,9 +554,13 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
 	mwifiex_wmm_delete_all_ralist(priv);
 	memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
 
-	if (priv->adapter->if_ops.clean_pcie_ring)
+	if (priv->adapter->if_ops.clean_pcie_ring &&
+	    !priv->adapter->surprise_removed)
 		priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
 	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+
+	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
+		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
 }
 
 /*
@@ -590,7 +589,7 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
  * If no such node is found, a new node is added first and then
  * retrieved.
  */
-static struct mwifiex_ra_list_tbl *
+struct mwifiex_ra_list_tbl *
 mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
 {
 	struct mwifiex_ra_list_tbl *ra_list;
@@ -640,6 +639,21 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 	struct mwifiex_ra_list_tbl *ra_list;
 	u8 ra[ETH_ALEN], tid_down;
 	unsigned long flags;
+	struct list_head list_head;
+	int tdls_status = TDLS_NOT_SETUP;
+	struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+
+	memcpy(ra, eth_hdr->h_dest, ETH_ALEN);
+
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+	    ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) {
+		if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)
+			dev_dbg(adapter->dev,
+				"TDLS setup packet for %pM. Don't block\n", ra);
+		else
+			tdls_status = mwifiex_get_tdls_link_status(priv, ra);
+	}
 
 	if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
 		dev_dbg(adapter->dev, "data: drop packet in disconnect\n");
@@ -658,12 +672,27 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 	   have only 1 raptr for a tid in case of infra */
 	if (!mwifiex_queuing_ra_based(priv) &&
 	    !mwifiex_is_skb_mgmt_frame(skb)) {
-		if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list))
-			ra_list = list_first_entry(
-				&priv->wmm.tid_tbl_ptr[tid_down].ra_list,
-				struct mwifiex_ra_list_tbl, list);
-		else
-			ra_list = NULL;
+		switch (tdls_status) {
+		case TDLS_SETUP_COMPLETE:
+			ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down,
+							      ra);
+			tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+			break;
+		case TDLS_SETUP_INPROGRESS:
+			skb_queue_tail(&priv->tdls_txq, skb);
+			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+					       flags);
+			return;
+		default:
+			list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
+			if (!list_empty(&list_head))
+				ra_list = list_first_entry(
+					&list_head, struct mwifiex_ra_list_tbl,
+					list);
+			else
+				ra_list = NULL;
+			break;
+		}
 	} else {
 		memcpy(ra, skb->data, ETH_ALEN);
 		if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb))
@@ -683,9 +712,9 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 	ra_list->total_pkt_count++;
 
 	if (atomic_read(&priv->wmm.highest_queued_prio) <
-						tos_to_tid_inv[tid_down])
+						priv->tos_to_tid_inv[tid_down])
 		atomic_set(&priv->wmm.highest_queued_prio,
-			   tos_to_tid_inv[tid_down]);
+			   priv->tos_to_tid_inv[tid_down]);
 
 	atomic_inc(&priv->wmm.tx_pkts_queued);
 
@@ -1226,7 +1255,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
 		/* ra_list_spinlock has been freed in
 		   mwifiex_send_single_packet() */
 	} else {
-		if (mwifiex_is_ampdu_allowed(priv, tid) &&
+		if (mwifiex_is_ampdu_allowed(priv, ptr, tid) &&
 		    ptr->ba_pkt_count > ptr->ba_packet_thr) {
 			if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
 				mwifiex_create_ba_tbl(priv, ptr->ra, tid,
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index 0f129d498fb1..83e42083ebff 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -34,6 +34,21 @@ enum ieee_types_wmm_ecw_bitmasks {
 static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
 
 /*
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+static const u8 tos_to_tid_inv[] = {
+	0x02,  /* from tos_to_tid[2] = 0 */
+	0x00,  /* from tos_to_tid[0] = 1 */
+	0x01,  /* from tos_to_tid[1] = 2 */
+	0x03,
+	0x04,
+	0x05,
+	0x06,
+	0x07};
+
+/*
  * This function retrieves the TID of the given RA list.
  */
 static inline int
@@ -107,5 +122,8 @@ void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
 void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
 int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
 			       const struct host_cmd_ds_command *resp);
+struct mwifiex_ra_list_tbl *
+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr);
+u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
 
 #endif /* !_MWIFIEX_WMM_H_ */
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 5028557aa18a..2e89a865a67d 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
 					bssid, req_ie, req_ie_len,
 					resp_ie, resp_ie_len, GFP_KERNEL);
 	} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
-		cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
+		cfg80211_ibss_joined(usbdev->net, bssid,
+				     get_current_channel(usbdev, NULL),
+				     GFP_KERNEL);
 
 	kfree(info);
 
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index caddc1b427a9..14a90ddf585c 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -125,9 +125,9 @@ static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
 
 	tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 	if (unlikely(tout))
-		rt2x00_warn(entry->queue->rt2x00dev,
-			    "TX status timeout for entry %d in queue %d\n",
-			    entry->entry_idx, entry->queue->qid);
+		rt2x00_dbg(entry->queue->rt2x00dev,
+			   "TX status timeout for entry %d in queue %d\n",
+			   entry->entry_idx, entry->queue->qid);
 	return tout;
 
 }
@@ -566,8 +566,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
 		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
 
 		if (unlikely(rt2x00queue_empty(queue))) {
-			rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
-				    qid);
+			rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+				   qid);
 			break;
 		}
 
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 3867d1470b36..7980ab1f9eca 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -619,13 +619,13 @@ static int rtl8180_start(struct ieee80211_hw *dev)
 
 	if (priv->r8185) {
 		reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
-		reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
-		reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+		reg &= ~RTL818X_CW_CONF_PERPACKET_CW;
+		reg |= RTL818X_CW_CONF_PERPACKET_RETRY;
 		rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
 
 		reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
-		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
-		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN;
+		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL;
 		reg |=  RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
 		rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index fd78df813a85..c981bcfb6cef 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -785,7 +785,7 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
 	rtl818x_iowrite16(priv, (__le16 *)0xFF34, 0x0FFF);
 
 	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
-	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+	reg |= RTL818X_CW_CONF_PERPACKET_RETRY;
 	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
 
 	/* Auto Rate Fallback Register (ARFR): 1M-54M setting */
@@ -943,8 +943,8 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 		rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
 
 		reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
-		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
-		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN;
+		reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL;
 		reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
 		rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
@@ -986,13 +986,13 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 	rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
 
 	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
-	reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
-	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+	reg &= ~RTL818X_CW_CONF_PERPACKET_CW;
+	reg |= RTL818X_CW_CONF_PERPACKET_RETRY;
 	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
 
 	reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
-	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
-	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN;
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL;
 	reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
 	rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index ce23dfd42381..fa7f7f61ea26 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -144,9 +144,9 @@ struct rtl818x_csr {
 	__le32	HSSI_PARA;
 	u8	reserved_13[4];
 	u8	TX_AGC_CTL;
-#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT		(1 << 0)
-#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT	(1 << 1)
-#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT			(1 << 2)
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN	(1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL	(1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT		(1 << 2)
 	u8	TX_GAIN_CCK;
 	u8	TX_GAIN_OFDM;
 	u8	TX_ANTENNA;
@@ -158,8 +158,8 @@ struct rtl818x_csr {
 	u8	SLOT;
 	u8	reserved_16[5];
 	u8	CW_CONF;
-#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT	(1 << 0)
-#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT	(1 << 1)
+#define RTL818X_CW_CONF_PERPACKET_CW	(1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY	(1 << 1)
 	u8	CW_VAL;
 	u8	RATE_FALLBACK;
 #define RTL818X_RATE_FALLBACK_ENABLE	(1 << 7)
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index a98acefb8c06..ee28a1a3d010 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -260,8 +260,7 @@ static void rtl_rate_free_sta(void *rtlpriv,
 	kfree(rate_priv);
 }
 
-static struct rate_control_ops rtl_rate_ops = {
-	.module = NULL,
+static const struct rate_control_ops rtl_rate_ops = {
 	.name = "rtl_rc",
 	.alloc = rtl_rate_alloc,
 	.free = rtl_rate_free,
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
index aece6c9cccf1..27ace3054d56 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
 			/* During testing, hdr was NULL */
 			return false;
 		}
-		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
 		    (ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
 		else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 52abf0a862fa..114858d46158 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 			/* In testing, hdr was NULL here */
 			return false;
 		}
-		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
 		    (ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
 		else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 27efbcdac6a9..163a681962c6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 			/* during testing, hdr was NULL here */
 			return false;
 		}
-		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
 			(ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
 		else
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
index 50b7be3f3a60..721162cacc3a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
 			/* during testing, hdr could be NULL here */
 			return false;
 		}
-		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
 			(ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
 		else
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index be7129ba16ad..d50dfac91631 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
 
 static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
 {
-	if (wl->fw_status_1->tx_results_counter ==
+	if (wl->fw_status->tx_results_counter ==
 	    (wl->tx_results_count & 0xff))
 		return 0;
 
@@ -1438,6 +1438,37 @@ out:
 	return ret;
 }
 
+static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
+				     struct wl_fw_status *fw_status)
+{
+	struct wl12xx_fw_status *int_fw_status = raw_fw_status;
+
+	fw_status->intr = le32_to_cpu(int_fw_status->intr);
+	fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
+	fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
+	fw_status->tx_results_counter = int_fw_status->tx_results_counter;
+	fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
+
+	fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
+	fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
+	fw_status->link_fast_bitmap =
+			le32_to_cpu(int_fw_status->link_fast_bitmap);
+	fw_status->total_released_blks =
+			le32_to_cpu(int_fw_status->total_released_blks);
+	fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
+
+	fw_status->counters.tx_released_pkts =
+			int_fw_status->counters.tx_released_pkts;
+	fw_status->counters.tx_lnk_free_pkts =
+			int_fw_status->counters.tx_lnk_free_pkts;
+	fw_status->counters.tx_voice_released_blks =
+			int_fw_status->counters.tx_voice_released_blks;
+	fw_status->counters.tx_last_rate =
+			int_fw_status->counters.tx_last_rate;
+
+	fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
+}
+
 static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
 				       struct wl12xx_vif *wlvif)
 {
@@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = {
 	.tx_delayed_compl	= wl12xx_tx_delayed_compl,
 	.hw_init		= wl12xx_hw_init,
 	.init_vif		= NULL,
+	.convert_fw_status	= wl12xx_convert_fw_status,
 	.sta_get_ap_rate_mask	= wl12xx_sta_get_ap_rate_mask,
 	.get_pg_ver		= wl12xx_get_pg_ver,
 	.get_mac		= wl12xx_get_mac,
@@ -1711,22 +1743,53 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
 		},
 };
 
+static const struct ieee80211_iface_limit wl12xx_iface_limits[] = {
+	{
+		.max = 3,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP) |
+			 BIT(NL80211_IFTYPE_P2P_GO) |
+			 BIT(NL80211_IFTYPE_P2P_CLIENT),
+	},
+};
+
+static const struct ieee80211_iface_combination
+wl12xx_iface_combinations[] = {
+	{
+		.max_interfaces = 3,
+		.limits = wl12xx_iface_limits,
+		.n_limits = ARRAY_SIZE(wl12xx_iface_limits),
+		.num_different_channels = 1,
+	},
+};
+
 static int wl12xx_setup(struct wl1271 *wl)
 {
 	struct wl12xx_priv *priv = wl->priv;
 	struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev);
 	struct wl12xx_platform_data *pdata = pdev_data->pdata;
 
+	BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS);
+	BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS);
+
 	wl->rtable = wl12xx_rtable;
 	wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
 	wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS;
-	wl->num_channels = 1;
+	wl->num_links = WL12XX_MAX_LINKS;
+	wl->max_ap_stations = WL12XX_MAX_AP_STATIONS;
+	wl->iface_combinations = wl12xx_iface_combinations;
+	wl->n_iface_combinations = ARRAY_SIZE(wl12xx_iface_combinations);
 	wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES;
 	wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
 	wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
 	wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
+	wl->fw_status_len = sizeof(struct wl12xx_fw_status);
 	wl->fw_status_priv_len = 0;
 	wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
+	wl->ofdm_only_ap = true;
 	wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
 	wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
 	wl12xx_conf_init(wl);
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 9e5484a73667..75c92658bfea 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -65,6 +65,9 @@
 
 #define WL12XX_RX_BA_MAX_SESSIONS 3
 
+#define WL12XX_MAX_AP_STATIONS 8
+#define WL12XX_MAX_LINKS 12
+
 struct wl127x_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
@@ -79,4 +82,54 @@ struct wl12xx_priv {
 	struct wl127x_rx_mem_pool_addr *rx_mem_addr;
 };
 
+struct wl12xx_fw_packet_counters {
+	/* Cumulative counter of released packets per AC */
+	u8 tx_released_pkts[NUM_TX_QUEUES];
+
+	/* Cumulative counter of freed packets per HLID */
+	u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
+
+	/* Cumulative counter of released Voice memory blocks */
+	u8 tx_voice_released_blks;
+
+	/* Tx rate of the last transmitted packet */
+	u8 tx_last_rate;
+
+	u8 padding[2];
+} __packed;
+
+/* FW status registers */
+struct wl12xx_fw_status {
+	__le32 intr;
+	u8  fw_rx_counter;
+	u8  drv_rx_counter;
+	u8  reserved;
+	u8  tx_results_counter;
+	__le32 rx_pkt_descs[WL12XX_NUM_RX_DESCRIPTORS];
+
+	__le32 fw_localtime;
+
+	/*
+	 * A bitmap (where each bit represents a single HLID)
+	 * to indicate if the station is in PS mode.
+	 */
+	__le32 link_ps_bitmap;
+
+	/*
+	 * A bitmap (where each bit represents a single HLID) to indicate
+	 * if the station is in Fast mode
+	 */
+	__le32 link_fast_bitmap;
+
+	/* Cumulative counter of total released mem blocks since FW-reset */
+	__le32 total_released_blks;
+
+	/* Size (in Memory Blocks) of TX pool */
+	__le32 tx_total;
+
+	struct wl12xx_fw_packet_counters counters;
+
+	__le32 log_start_addr;
+} __packed;
+
 #endif /* __WL12XX_PRIV_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ec37b16585df..de5b4fa5d166 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -648,7 +648,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
 };
 
 /* TODO: maybe move to a new header file? */
-#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-2.bin"
+#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-3.bin"
 
 static int wl18xx_identify_chip(struct wl1271 *wl)
 {
@@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271 *wl)
 	return ret;
 }
 
+static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
+				     struct wl_fw_status *fw_status)
+{
+	struct wl18xx_fw_status *int_fw_status = raw_fw_status;
+
+	fw_status->intr = le32_to_cpu(int_fw_status->intr);
+	fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
+	fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
+	fw_status->tx_results_counter = int_fw_status->tx_results_counter;
+	fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
+
+	fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
+	fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
+	fw_status->link_fast_bitmap =
+			le32_to_cpu(int_fw_status->link_fast_bitmap);
+	fw_status->total_released_blks =
+			le32_to_cpu(int_fw_status->total_released_blks);
+	fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
+
+	fw_status->counters.tx_released_pkts =
+			int_fw_status->counters.tx_released_pkts;
+	fw_status->counters.tx_lnk_free_pkts =
+			int_fw_status->counters.tx_lnk_free_pkts;
+	fw_status->counters.tx_voice_released_blks =
+			int_fw_status->counters.tx_voice_released_blks;
+	fw_status->counters.tx_last_rate =
+			int_fw_status->counters.tx_last_rate;
+
+	fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
+
+	fw_status->priv = &int_fw_status->priv;
+}
+
 static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
 				    struct wl1271_tx_hw_descr *desc,
 				    struct sk_buff *skb)
@@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
 {
 	u8 thold;
 	struct wl18xx_fw_status_priv *status_priv =
-		(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
+		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
 	u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
 
 	/* suspended links are never high priority */
@@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
 {
 	u8 thold;
 	struct wl18xx_fw_status_priv *status_priv =
-		(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
+		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
 	u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
 
 	if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
@@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = {
 	.tx_immediate_compl = wl18xx_tx_immediate_completion,
 	.tx_delayed_compl = NULL,
 	.hw_init	= wl18xx_hw_init,
+	.convert_fw_status = wl18xx_convert_fw_status,
 	.set_tx_desc_csum = wl18xx_set_tx_desc_csum,
 	.get_pg_ver	= wl18xx_get_pg_ver,
 	.set_rx_csum = wl18xx_set_rx_csum,
@@ -1713,19 +1747,62 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
 		},
 };
 
+static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
+	{
+		.max = 3,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP) |
+			 BIT(NL80211_IFTYPE_P2P_GO) |
+			 BIT(NL80211_IFTYPE_P2P_CLIENT),
+	},
+};
+
+static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_AP),
+	},
+};
+
+static const struct ieee80211_iface_combination
+wl18xx_iface_combinations[] = {
+	{
+		.max_interfaces = 3,
+		.limits = wl18xx_iface_limits,
+		.n_limits = ARRAY_SIZE(wl18xx_iface_limits),
+		.num_different_channels = 2,
+	},
+	{
+		.max_interfaces = 2,
+		.limits = wl18xx_iface_ap_limits,
+		.n_limits = ARRAY_SIZE(wl18xx_iface_ap_limits),
+		.num_different_channels = 1,
+	}
+};
+
 static int wl18xx_setup(struct wl1271 *wl)
 {
 	struct wl18xx_priv *priv = wl->priv;
 	int ret;
 
+	BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS);
+	BUILD_BUG_ON(WL18XX_MAX_AP_STATIONS > WL18XX_MAX_LINKS);
+
 	wl->rtable = wl18xx_rtable;
 	wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
 	wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS;
-	wl->num_channels = 2;
+	wl->num_links = WL18XX_MAX_LINKS;
+	wl->max_ap_stations = WL18XX_MAX_AP_STATIONS;
+	wl->iface_combinations = wl18xx_iface_combinations;
+	wl->n_iface_combinations = ARRAY_SIZE(wl18xx_iface_combinations);
 	wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES;
 	wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
 	wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
 	wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
+	wl->fw_status_len = sizeof(struct wl18xx_fw_status);
 	wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
 	wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
 	wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
index 57c694396647..be1ebd55ac88 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -32,7 +32,7 @@ static
 void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
 			     struct ieee80211_tx_rate *rate)
 {
-	u8 fw_rate = wl->fw_status_2->counters.tx_last_rate;
+	u8 fw_rate = wl->fw_status->counters.tx_last_rate;
 
 	if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
 		wl1271_error("last Tx rate invalid: %d", fw_rate);
@@ -139,7 +139,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
 void wl18xx_tx_immediate_complete(struct wl1271 *wl)
 {
 	struct wl18xx_fw_status_priv *status_priv =
-		(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
+		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
 	struct wl18xx_priv *priv = wl->priv;
 	u8 i;
 
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 9204e07ee432..eb7cfe817010 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -26,10 +26,10 @@
 
 /* minimum FW required for driver */
 #define WL18XX_CHIP_VER		8
-#define WL18XX_IFTYPE_VER	5
+#define WL18XX_IFTYPE_VER	8
 #define WL18XX_MAJOR_VER	WLCORE_FW_VER_IGNORE
 #define WL18XX_SUBTYPE_VER	WLCORE_FW_VER_IGNORE
-#define WL18XX_MINOR_VER	39
+#define WL18XX_MINOR_VER	13
 
 #define WL18XX_CMD_MAX_SIZE          740
 
@@ -40,7 +40,10 @@
 
 #define WL18XX_NUM_MAC_ADDRESSES 3
 
-#define WL18XX_RX_BA_MAX_SESSIONS 5
+#define WL18XX_RX_BA_MAX_SESSIONS 13
+
+#define WL18XX_MAX_AP_STATIONS 10
+#define WL18XX_MAX_LINKS 16
 
 struct wl18xx_priv {
 	/* buffer for sending commands to FW */
@@ -109,6 +112,59 @@ struct wl18xx_fw_status_priv {
 	u8 padding[3];
 };
 
+struct wl18xx_fw_packet_counters {
+	/* Cumulative counter of released packets per AC */
+	u8 tx_released_pkts[NUM_TX_QUEUES];
+
+	/* Cumulative counter of freed packets per HLID */
+	u8 tx_lnk_free_pkts[WL18XX_MAX_LINKS];
+
+	/* Cumulative counter of released Voice memory blocks */
+	u8 tx_voice_released_blks;
+
+	/* Tx rate of the last transmitted packet */
+	u8 tx_last_rate;
+
+	u8 padding[2];
+} __packed;
+
+/* FW status registers */
+struct wl18xx_fw_status {
+	__le32 intr;
+	u8  fw_rx_counter;
+	u8  drv_rx_counter;
+	u8  reserved;
+	u8  tx_results_counter;
+	__le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS];
+
+	__le32 fw_localtime;
+
+	/*
+	 * A bitmap (where each bit represents a single HLID)
+	 * to indicate if the station is in PS mode.
+	 */
+	__le32 link_ps_bitmap;
+
+	/*
+	 * A bitmap (where each bit represents a single HLID) to indicate
+	 * if the station is in Fast mode
+	 */
+	__le32 link_fast_bitmap;
+
+	/* Cumulative counter of total released mem blocks since FW-reset */
+	__le32 total_released_blks;
+
+	/* Size (in Memory Blocks) of TX pool */
+	__le32 tx_total;
+
+	struct wl18xx_fw_packet_counters counters;
+
+	__le32 log_start_addr;
+
+	/* Private status to be used by the lower drivers */
+	struct wl18xx_fw_status_priv priv;
+} __packed;
+
 #define WL18XX_PHY_VERSION_MAX_LEN 20
 
 struct wl18xx_static_data_priv {
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index ec83675a2446..b924ceadc02c 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -358,7 +358,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	struct acx_beacon_filter_option *beacon_filter = NULL;
 	int ret = 0;
 
-	wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
+	wl1271_debug(DEBUG_ACX, "acx beacon filter opt enable=%d",
+		     enable_filter);
 
 	if (enable_filter &&
 	    wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED)
@@ -1591,7 +1592,8 @@ out:
 	return ret;
 }
 
-int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl,
+				    struct wl12xx_vif *wlvif, u8 *addr)
 {
 	struct wl1271_acx_inconnection_sta *acx = NULL;
 	int ret;
@@ -1603,6 +1605,7 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
 		return -ENOMEM;
 
 	memcpy(acx->addr, addr, ETH_ALEN);
+	acx->role_id = wlvif->role_id;
 
 	ret = wl1271_cmd_configure(wl, ACX_UPDATE_INCONNECTION_STA_LIST,
 				   acx, sizeof(*acx));
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 6dcfad9b0472..954d57ec98f4 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -824,7 +824,8 @@ struct wl1271_acx_inconnection_sta {
 	struct acx_header header;
 
 	u8 addr[ETH_ALEN];
-	u8 padding1[2];
+	u8 role_id;
+	u8 padding;
 } __packed;
 
 /*
@@ -1118,7 +1119,8 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			       bool enable);
 int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif);
-int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl,
+				    struct wl12xx_vif *wlvif, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
 int wl12xx_acx_config_hangover(struct wl1271 *wl);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 9b2ecf52449f..40dc30f4faaa 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -60,8 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf,
 	u16 status;
 	u16 poll_count = 0;
 
-	if (WARN_ON(wl->state == WLCORE_STATE_RESTARTING &&
-		    id != CMD_STOP_FWLOGGER))
+	if (unlikely(wl->state == WLCORE_STATE_RESTARTING &&
+		     id != CMD_STOP_FWLOGGER))
 		return -EIO;
 
 	cmd = buf;
@@ -312,8 +312,8 @@ static int wlcore_get_new_session_id(struct wl1271 *wl, u8 hlid)
 int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 {
 	unsigned long flags;
-	u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
-	if (link >= WL12XX_MAX_LINKS)
+	u8 link = find_first_zero_bit(wl->links_map, wl->num_links);
+	if (link >= wl->num_links)
 		return -EBUSY;
 
 	wl->session_ids[link] = wlcore_get_new_session_id(wl, link);
@@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 	__set_bit(link, wlvif->links_map);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	/* take the last "freed packets" value from the current FW status */
-	wl->links[link].prev_freed_pkts =
-			wl->fw_status_2->counters.tx_lnk_free_pkts[link];
+	/*
+	 * take the last "freed packets" value from the current FW status.
+	 * on recovery, we might not have fw_status yet, and
+	 * tx_lnk_free_pkts will be NULL. check for it.
+	 */
+	if (wl->fw_status->counters.tx_lnk_free_pkts)
+		wl->links[link].prev_freed_pkts =
+			wl->fw_status->counters.tx_lnk_free_pkts[link];
 	wl->links[link].wlvif = wlvif;
 
 	/*
@@ -1527,6 +1532,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	cmd->sp_len = sta->max_sp;
 	cmd->wmm = sta->wme ? 1 : 0;
 	cmd->session_id = wl->session_ids[hlid];
+	cmd->role_id = wlvif->role_id;
 
 	for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)
 		if (sta->wme && (sta->uapsd_queues & BIT(i)))
@@ -1563,7 +1569,8 @@ out:
 	return ret;
 }
 
-int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+			   u8 hlid)
 {
 	struct wl12xx_cmd_remove_peer *cmd;
 	int ret;
@@ -1581,6 +1588,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
 	/* We never send a deauth, mac80211 is in charge of this */
 	cmd->reason_opcode = 0;
 	cmd->send_deauth_flag = 0;
+	cmd->role_id = wlvif->role_id;
 
 	ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 323d4a856e4b..b084830a61cf 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -88,7 +88,8 @@ int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id,
 int wl12xx_croc(struct wl1271 *wl, u8 role_id);
 int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			struct ieee80211_sta *sta, u8 hlid);
-int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+			   u8 hlid);
 void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel,
 				     enum ieee80211_band band);
 int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl);
@@ -206,7 +207,7 @@ enum cmd_templ {
 #define WL1271_COMMAND_TIMEOUT     2000
 #define WL1271_CMD_TEMPL_DFLT_SIZE 252
 #define WL1271_CMD_TEMPL_MAX_SIZE  512
-#define WL1271_EVENT_TIMEOUT       1500
+#define WL1271_EVENT_TIMEOUT       5000
 
 struct wl1271_cmd_header {
 	__le16 id;
@@ -594,6 +595,8 @@ struct wl12xx_cmd_add_peer {
 	u8 sp_len;
 	u8 wmm;
 	u8 session_id;
+	u8 role_id;
+	u8 padding[3];
 } __packed;
 
 struct wl12xx_cmd_remove_peer {
@@ -602,7 +605,7 @@ struct wl12xx_cmd_remove_peer {
 	u8 hlid;
 	u8 reason_opcode;
 	u8 send_deauth_flag;
-	u8 padding1;
+	u8 role_id;
 } __packed;
 
 /*
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 8d3b34965db3..1f9a36031b06 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -67,7 +67,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 		u8 hlid;
 		struct wl1271_link *lnk;
 		for_each_set_bit(hlid, wlvif->ap.sta_hlid_map,
-				 WL12XX_MAX_LINKS) {
+				 wl->num_links) {
 			lnk = &wl->links[hlid];
 			if (!lnk->ba_bitmap)
 				continue;
@@ -172,7 +172,7 @@ static void wlcore_disconnect_sta(struct wl1271 *wl, unsigned long sta_bitmap)
 	const u8 *addr;
 	int h;
 
-	for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
+	for_each_set_bit(h, &sta_bitmap, wl->num_links) {
 		bool found = false;
 		/* find the ap vif connected to this sta */
 		wl12xx_for_each_wlvif_ap(wl, wlvif) {
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 51f8d634d32f..1555ff970050 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 	return 0;
 }
 
+static inline void
+wlcore_hw_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
+			    struct wl_fw_status *fw_status)
+{
+	BUG_ON(!wl->ops->convert_fw_status);
+
+	wl->ops->convert_fw_status(wl, raw_fw_status, fw_status);
+}
+
 static inline u32
 wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 {
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index 7699f9d07e26..199e94120864 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -287,8 +287,8 @@ static int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
 	if (ret < 0)
 		return ret;
 
-	/* enable beacon filtering */
-	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
+	/* disable beacon filtering until we get the first beacon */
+	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
 	if (ret < 0)
 		return ret;
 
@@ -462,7 +462,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 	 * If the basic rates contain OFDM rates, use OFDM only
 	 * rates for unicast TX as well. Else use all supported rates.
 	 */
-	if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES))
+	if (wl->ofdm_only_ap && (wlvif->basic_rate_set & CONF_TX_OFDM_RATES))
 		supported_rates = CONF_TX_OFDM_RATES;
 	else
 		supported_rates = CONF_TX_ENABLED_RATES;
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h
index 07e3d6a049ad..0305729d0986 100644
--- a/drivers/net/wireless/ti/wlcore/io.h
+++ b/drivers/net/wireless/ti/wlcore/io.h
@@ -60,7 +60,9 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
 {
 	int ret;
 
-	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
+	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags) ||
+	    WARN_ON((test_bit(WL1271_FLAG_IN_ELP, &wl->flags) &&
+		     addr != HW_ACCESS_ELP_CTRL_REG)))
 		return -EIO;
 
 	ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
@@ -76,7 +78,9 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
 {
 	int ret;
 
-	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
+	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags) ||
+	    WARN_ON((test_bit(WL1271_FLAG_IN_ELP, &wl->flags) &&
+		     addr != HW_ACCESS_ELP_CTRL_REG)))
 		return -EIO;
 
 	ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index b46b3116cc55..7aae5b3a0c2c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -345,24 +345,24 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
 	 * Start high-level PS if the STA is asleep with enough blocks in FW.
 	 * Make an exception if this is the only connected link. In this
 	 * case FW-memory congestion is less of a problem.
-	 * Note that a single connected STA means 3 active links, since we must
-	 * account for the global and broadcast AP links. The "fw_ps" check
-	 * assures us the third link is a STA connected to the AP. Otherwise
-	 * the FW would not set the PSM bit.
+	 * Note that a single connected STA means 2*ap_count + 1 active links,
+	 * since we must account for the global and broadcast AP links
+	 * for each AP. The "fw_ps" check assures us the other link is a STA
+	 * connected to the AP. Otherwise the FW would not set the PSM bit.
 	 */
-	else if (wl->active_link_count > 3 && fw_ps &&
+	else if (wl->active_link_count > (wl->ap_count*2 + 1) && fw_ps &&
 		 tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl12xx_ps_link_start(wl, wlvif, hlid, true);
 }
 
 static void wl12xx_irq_update_links_status(struct wl1271 *wl,
 					   struct wl12xx_vif *wlvif,
-					   struct wl_fw_status_2 *status)
+					   struct wl_fw_status *status)
 {
 	u32 cur_fw_ps_map;
 	u8 hlid;
 
-	cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
+	cur_fw_ps_map = status->link_ps_bitmap;
 	if (wl->ap_fw_ps_map != cur_fw_ps_map) {
 		wl1271_debug(DEBUG_PSM,
 			     "link ps prev 0x%x cur 0x%x changed 0x%x",
@@ -372,77 +372,73 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
 		wl->ap_fw_ps_map = cur_fw_ps_map;
 	}
 
-	for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS)
+	for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, wl->num_links)
 		wl12xx_irq_ps_regulate_link(wl, wlvif, hlid,
 					    wl->links[hlid].allocated_pkts);
 }
 
-static int wlcore_fw_status(struct wl1271 *wl,
-			    struct wl_fw_status_1 *status_1,
-			    struct wl_fw_status_2 *status_2)
+static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status)
 {
 	struct wl12xx_vif *wlvif;
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
 	int avail, freed_blocks;
 	int i;
-	size_t status_len;
 	int ret;
 	struct wl1271_link *lnk;
 
-	status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
-		sizeof(*status_2) + wl->fw_status_priv_len;
-
-	ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
-				   status_len, false);
+	ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR,
+				   wl->raw_fw_status,
+				   wl->fw_status_len, false);
 	if (ret < 0)
 		return ret;
 
+	wlcore_hw_convert_fw_status(wl, wl->raw_fw_status, wl->fw_status);
+
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
-		     status_1->intr,
-		     status_1->fw_rx_counter,
-		     status_1->drv_rx_counter,
-		     status_1->tx_results_counter);
+		     status->intr,
+		     status->fw_rx_counter,
+		     status->drv_rx_counter,
+		     status->tx_results_counter);
 
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
 		/* prevent wrap-around in freed-packets counter */
 		wl->tx_allocated_pkts[i] -=
-				(status_2->counters.tx_released_pkts[i] -
+				(status->counters.tx_released_pkts[i] -
 				wl->tx_pkts_freed[i]) & 0xff;
 
-		wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i];
+		wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
 	}
 
 
-	for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) {
+	for_each_set_bit(i, wl->links_map, wl->num_links) {
 		u8 diff;
 		lnk = &wl->links[i];
 
 		/* prevent wrap-around in freed-packets counter */
-		diff = (status_2->counters.tx_lnk_free_pkts[i] -
+		diff = (status->counters.tx_lnk_free_pkts[i] -
 		       lnk->prev_freed_pkts) & 0xff;
 
 		if (diff == 0)
 			continue;
 
 		lnk->allocated_pkts -= diff;
-		lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
+		lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[i];
 
 		/* accumulate the prev_freed_pkts counter */
 		lnk->total_freed_pkts += diff;
 	}
 
 	/* prevent wrap-around in total blocks counter */
-	if (likely(wl->tx_blocks_freed <=
-		   le32_to_cpu(status_2->total_released_blks)))
-		freed_blocks = le32_to_cpu(status_2->total_released_blks) -
+	if (likely(wl->tx_blocks_freed <= status->total_released_blks))
+		freed_blocks = status->total_released_blks -
 			       wl->tx_blocks_freed;
 	else
 		freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
-			       le32_to_cpu(status_2->total_released_blks);
+			       status->total_released_blks;
 
-	wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks);
+	wl->tx_blocks_freed = status->total_released_blks;
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
@@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl1271 *wl,
 			cancel_delayed_work(&wl->tx_watchdog_work);
 	}
 
-	avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks;
+	avail = status->tx_total - wl->tx_allocated_blocks;
 
 	/*
 	 * The FW might change the total number of TX memblocks before
@@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl1271 *wl,
 
 	/* for AP update num of allocated TX blocks per link and ps status */
 	wl12xx_for_each_wlvif_ap(wl, wlvif) {
-		wl12xx_irq_update_links_status(wl, wlvif, status_2);
+		wl12xx_irq_update_links_status(wl, wlvif, status);
 	}
 
 	/* update the host-chipset time offset */
 	getnstimeofday(&ts);
 	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
-		(s64)le32_to_cpu(status_2->fw_localtime);
+		(s64)(status->fw_localtime);
 
-	wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap);
+	wl->fw_fast_lnk_map = status->link_fast_bitmap;
 
 	return 0;
 }
@@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl1271 *wl)
 		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
 		smp_mb__after_clear_bit();
 
-		ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
+		ret = wlcore_fw_status(wl, wl->fw_status);
 		if (ret < 0)
 			goto out;
 
 		wlcore_hw_tx_immediate_compl(wl);
 
-		intr = le32_to_cpu(wl->fw_status_1->intr);
+		intr = wl->fw_status->intr;
 		intr &= WLCORE_ALL_INTR_MASK;
 		if (!intr) {
 			done = true;
@@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
 		if (likely(intr & WL1271_ACX_INTR_DATA)) {
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
-			ret = wlcore_rx(wl, wl->fw_status_1);
+			ret = wlcore_rx(wl, wl->fw_status);
 			if (ret < 0)
 				goto out;
 
@@ -786,10 +782,11 @@ out:
 
 void wl12xx_queue_recovery_work(struct wl1271 *wl)
 {
-	WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
-
 	/* Avoid a recursive recovery */
 	if (wl->state == WLCORE_STATE_ON) {
+		WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY,
+				  &wl->flags));
+
 		wl->state = WLCORE_STATE_RESTARTING;
 		set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
 		wl1271_ps_elp_wakeup(wl);
@@ -843,11 +840,11 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
 		wl12xx_cmd_stop_fwlog(wl);
 
 	/* Read the first memory block address */
-	ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
+	ret = wlcore_fw_status(wl, wl->fw_status);
 	if (ret < 0)
 		goto out;
 
-	addr = le32_to_cpu(wl->fw_status_2->log_start_addr);
+	addr = wl->fw_status->log_start_addr;
 	if (!addr)
 		goto out;
 
@@ -990,23 +987,23 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)
 
 static int wl1271_setup(struct wl1271 *wl)
 {
-	wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
-				  sizeof(*wl->fw_status_2) +
-				  wl->fw_status_priv_len, GFP_KERNEL);
-	if (!wl->fw_status_1)
-		return -ENOMEM;
+	wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL);
+	if (!wl->raw_fw_status)
+		goto err;
 
-	wl->fw_status_2 = (struct wl_fw_status_2 *)
-				(((u8 *) wl->fw_status_1) +
-				WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc));
+	wl->fw_status = kzalloc(sizeof(*wl->fw_status), GFP_KERNEL);
+	if (!wl->fw_status)
+		goto err;
 
 	wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
-	if (!wl->tx_res_if) {
-		kfree(wl->fw_status_1);
-		return -ENOMEM;
-	}
+	if (!wl->tx_res_if)
+		goto err;
 
 	return 0;
+err:
+	kfree(wl->fw_status);
+	kfree(wl->raw_fw_status);
+	return -ENOMEM;
 }
 
 static int wl12xx_set_power_on(struct wl1271 *wl)
@@ -1767,6 +1764,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
 	flush_work(&wl->tx_work);
 	flush_delayed_work(&wl->elp_work);
 
+	/*
+	 * Cancel the watchdog even if above tx_flush failed. We will detect
+	 * it on resume anyway.
+	 */
+	cancel_delayed_work(&wl->tx_watchdog_work);
+
 	return 0;
 }
 
@@ -1824,6 +1827,13 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
 
 out:
 	wl->wow_enabled = false;
+
+	/*
+	 * Set a flag to re-init the watchdog on the first Tx after resume.
+	 * That way we avoid possible conditions where Tx-complete interrupts
+	 * fail to arrive and we perform a spurious recovery.
+	 */
+	set_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags);
 	mutex_unlock(&wl->mutex);
 
 	return 0;
@@ -1914,6 +1924,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
 	memset(wl->links_map, 0, sizeof(wl->links_map));
 	memset(wl->roc_map, 0, sizeof(wl->roc_map));
 	memset(wl->session_ids, 0, sizeof(wl->session_ids));
+	memset(wl->rx_filter_enabled, 0, sizeof(wl->rx_filter_enabled));
 	wl->active_sta_count = 0;
 	wl->active_link_count = 0;
 
@@ -1938,9 +1949,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
 
 	wl1271_debugfs_reset(wl);
 
-	kfree(wl->fw_status_1);
-	wl->fw_status_1 = NULL;
-	wl->fw_status_2 = NULL;
+	kfree(wl->raw_fw_status);
+	wl->raw_fw_status = NULL;
+	kfree(wl->fw_status);
+	wl->fw_status = NULL;
 	kfree(wl->tx_res_if);
 	wl->tx_res_if = NULL;
 	kfree(wl->target_mem_map);
@@ -2571,10 +2583,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 		ieee80211_scan_completed(wl->hw, true);
 	}
 
-	if (wl->sched_vif == wlvif) {
-		ieee80211_sched_scan_stopped(wl->hw);
+	if (wl->sched_vif == wlvif)
 		wl->sched_vif = NULL;
-	}
 
 	if (wl->roc_vif == vif) {
 		wl->roc_vif = NULL;
@@ -2931,6 +2941,11 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 		ret = wl1271_acx_keep_alive_mode(wl, wlvif, false);
 		if (ret < 0)
 			return ret;
+
+		/* disable beacon filtering */
+		ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
+		if (ret < 0)
+			return ret;
 	}
 
 	if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) {
@@ -3463,6 +3478,10 @@ static void wl1271_op_set_default_key_idx(struct ieee80211_hw *hw,
 	wl1271_debug(DEBUG_MAC80211, "mac80211 set default key idx %d",
 		     key_idx);
 
+	/* we don't handle unsetting of default key */
+	if (key_idx == -1)
+		return;
+
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state != WLCORE_STATE_ON)) {
@@ -4298,6 +4317,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 		}
 	}
 
+	if ((changed & BSS_CHANGED_BEACON_INFO) && bss_conf->dtim_period) {
+		/* enable beacon filtering */
+		ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
+		if (ret < 0)
+			goto out;
+	}
+
 	ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed);
 	if (ret < 0)
 		goto out;
@@ -4651,7 +4677,7 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
 	int ret;
 
 
-	if (wl->active_sta_count >= AP_MAX_STATIONS) {
+	if (wl->active_sta_count >= wl->max_ap_stations) {
 		wl1271_warning("could not allocate HLID - too much stations");
 		return -EBUSY;
 	}
@@ -4754,7 +4780,7 @@ static int wl12xx_sta_remove(struct wl1271 *wl,
 	if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
 		return -EINVAL;
 
-	ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
+	ret = wl12xx_cmd_remove_peer(wl, wlvif, wl_sta->hlid);
 	if (ret < 0)
 		return ret;
 
@@ -5679,28 +5705,6 @@ static void wl1271_unregister_hw(struct wl1271 *wl)
 
 }
 
-static const struct ieee80211_iface_limit wlcore_iface_limits[] = {
-	{
-		.max = 3,
-		.types = BIT(NL80211_IFTYPE_STATION),
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_AP) |
-			 BIT(NL80211_IFTYPE_P2P_GO) |
-			 BIT(NL80211_IFTYPE_P2P_CLIENT),
-	},
-};
-
-static struct ieee80211_iface_combination
-wlcore_iface_combinations[] = {
-	{
-	  .max_interfaces = 3,
-	  .limits = wlcore_iface_limits,
-	  .n_limits = ARRAY_SIZE(wlcore_iface_limits),
-	},
-};
-
 static int wl1271_init_ieee80211(struct wl1271 *wl)
 {
 	int i;
@@ -5733,7 +5737,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
 		IEEE80211_HW_AP_LINK_PS |
 		IEEE80211_HW_AMPDU_AGGREGATION |
 		IEEE80211_HW_TX_AMPDU_SETUP_IN_HW |
-		IEEE80211_HW_QUEUE_CONTROL;
+		IEEE80211_HW_QUEUE_CONTROL |
+		IEEE80211_HW_CHANCTX_STA_CSA;
 
 	wl->hw->wiphy->cipher_suites = cipher_suites;
 	wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
@@ -5821,10 +5826,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
 		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
 
 	/* allowed interface combinations */
-	wlcore_iface_combinations[0].num_different_channels = wl->num_channels;
-	wl->hw->wiphy->iface_combinations = wlcore_iface_combinations;
-	wl->hw->wiphy->n_iface_combinations =
-		ARRAY_SIZE(wlcore_iface_combinations);
+	wl->hw->wiphy->iface_combinations = wl->iface_combinations;
+	wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations;
 
 	SET_IEEE80211_DEV(wl->hw, wl->dev);
 
@@ -5844,8 +5847,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
 	int i, j, ret;
 	unsigned int order;
 
-	BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS);
-
 	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
 	if (!hw) {
 		wl1271_error("could not alloc ieee80211_hw");
@@ -5867,8 +5868,12 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
 
 	wl->hw = hw;
 
+	/*
+	 * wl->num_links is not configured yet, so just use WLCORE_MAX_LINKS.
+	 * we don't allocate any additional resource here, so that's fine.
+	 */
 	for (i = 0; i < NUM_TX_QUEUES; i++)
-		for (j = 0; j < WL12XX_MAX_LINKS; j++)
+		for (j = 0; j < WLCORE_MAX_LINKS; j++)
 			skb_queue_head_init(&wl->links[j].tx_queue[i]);
 
 	skb_queue_head_init(&wl->deferred_rx_queue);
@@ -6011,7 +6016,8 @@ int wlcore_free_hw(struct wl1271 *wl)
 	kfree(wl->nvs);
 	wl->nvs = NULL;
 
-	kfree(wl->fw_status_1);
+	kfree(wl->raw_fw_status);
+	kfree(wl->fw_status);
 	kfree(wl->tx_res_if);
 	destroy_workqueue(wl->freezable_wq);
 
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 26bfc365ba70..b52516eed7b2 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -280,7 +280,11 @@ void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	struct ieee80211_sta *sta;
 	struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
 
-	if (test_bit(hlid, &wl->ap_ps_map))
+	if (WARN_ON_ONCE(wlvif->bss_type != BSS_TYPE_AP_BSS))
+		return;
+
+	if (!test_bit(hlid, wlvif->ap.sta_hlid_map) ||
+	    test_bit(hlid, &wl->ap_ps_map))
 		return;
 
 	wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 6791a1a6afba..e125974285cc 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -203,9 +203,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
 	return is_data;
 }
 
-int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
 {
-	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
+	unsigned long active_hlids[BITS_TO_LONGS(WLCORE_MAX_LINKS)] = {0};
 	u32 buf_size;
 	u32 fw_rx_counter = status->fw_rx_counter % wl->num_rx_desc;
 	u32 drv_rx_counter = wl->rx_counter % wl->num_rx_desc;
@@ -263,12 +263,12 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
 						  wl->aggr_buf + pkt_offset,
 						  pkt_len, rx_align,
 						  &hlid) == 1) {
-				if (hlid < WL12XX_MAX_LINKS)
+				if (hlid < wl->num_links)
 					__set_bit(hlid, active_hlids);
 				else
 					WARN(1,
-					     "hlid exceeded WL12XX_MAX_LINKS "
-					     "(%d)\n", hlid);
+					     "hlid (%d) exceeded MAX_LINKS\n",
+					     hlid);
 			}
 
 			wl->rx_counter++;
@@ -302,7 +302,7 @@ int wl1271_rx_filter_enable(struct wl1271 *wl,
 {
 	int ret;
 
-	if (wl->rx_filter_enabled[index] == enable) {
+	if (!!test_bit(index, wl->rx_filter_enabled) == enable) {
 		wl1271_warning("Request to enable an already "
 			     "enabled rx filter %d", index);
 		return 0;
@@ -316,7 +316,10 @@ int wl1271_rx_filter_enable(struct wl1271 *wl,
 		return ret;
 	}
 
-	wl->rx_filter_enabled[index] = enable;
+	if (enable)
+		__set_bit(index, wl->rx_filter_enabled);
+	else
+		__clear_bit(index, wl->rx_filter_enabled);
 
 	return 0;
 }
@@ -326,7 +329,7 @@ int wl1271_rx_filter_clear_all(struct wl1271 *wl)
 	int i, ret = 0;
 
 	for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) {
-		if (!wl->rx_filter_enabled[i])
+		if (!test_bit(i, wl->rx_filter_enabled))
 			continue;
 		ret = wl1271_rx_filter_enable(wl, i, 0, NULL);
 		if (ret)
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index 3363f60fb7da..a3b1618db27c 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -142,7 +142,7 @@ struct wl1271_rx_descriptor {
 	u8  reserved;
 } __packed;
 
-int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 int wl1271_rx_filter_enable(struct wl1271 *wl,
 			    int index, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 87cd707affa2..40b43115f835 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -101,7 +101,7 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 	 * authentication response. this way it won't get de-authed by FW
 	 * when transmitting too soon.
 	 */
-	wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
+	wl1271_acx_set_inconnection_sta(wl, wlvif, hdr->addr1);
 
 	/*
 	 * ROC for 1 second on the AP channel for completing the connection.
@@ -134,12 +134,12 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
 	 * into high-level PS and clean out its TX queues.
 	 * Make an exception if this is the only connected link. In this
 	 * case FW-memory congestion is less of a problem.
-	 * Note that a single connected STA means 3 active links, since we must
-	 * account for the global and broadcast AP links. The "fw_ps" check
-	 * assures us the third link is a STA connected to the AP. Otherwise
-	 * the FW would not set the PSM bit.
+	 * Note that a single connected STA means 2*ap_count + 1 active links,
+	 * since we must account for the global and broadcast AP links
+	 * for each AP. The "fw_ps" check assures us the other link is a STA
+	 * connected to the AP. Otherwise the FW would not set the PSM bit.
 	 */
-	if (wl->active_link_count > 3 && fw_ps &&
+	if (wl->active_link_count > (wl->ap_count*2 + 1) && fw_ps &&
 	    tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl12xx_ps_link_start(wl, wlvif, hlid, true);
 }
@@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 		wl->tx_blocks_available -= total_blocks;
 		wl->tx_allocated_blocks += total_blocks;
 
-		/* If the FW was empty before, arm the Tx watchdog */
-		if (wl->tx_allocated_blocks == total_blocks)
+		/*
+		 * If the FW was empty before, arm the Tx watchdog. Also do
+		 * this on the first Tx after resume, as we always cancel the
+		 * watchdog on suspend.
+		 */
+		if (wl->tx_allocated_blocks == total_blocks ||
+		    test_and_clear_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags))
 			wl12xx_rearm_tx_watchdog_locked(wl);
 
 		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
@@ -357,6 +362,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 	    ieee80211_has_protected(frame_control))
 		tx_attr |= TX_HW_ATTR_HOST_ENCRYPT;
 
+	/* send EAPOL frames as voice */
+	if (control->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
+		tx_attr |= TX_HW_ATTR_EAPOL_FRAME;
+
 	desc->tx_attr = cpu_to_le16(tx_attr);
 
 	wlcore_hw_set_tx_desc_csum(wl, desc, skb);
@@ -560,11 +569,11 @@ static struct sk_buff *wlcore_vif_dequeue_high_prio(struct wl1271 *wl,
 	int i, h, start_hlid;
 
 	/* start from the link after the last one */
-	start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
+	start_hlid = (wlvif->last_tx_hlid + 1) % wl->num_links;
 
 	/* dequeue according to AC, round robin on each link */
-	for (i = 0; i < WL12XX_MAX_LINKS; i++) {
-		h = (start_hlid + i) % WL12XX_MAX_LINKS;
+	for (i = 0; i < wl->num_links; i++) {
+		h = (start_hlid + i) % wl->num_links;
 
 		/* only consider connected stations */
 		if (!test_bit(h, wlvif->links_map))
@@ -688,8 +697,8 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 		skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
 
 		/* make sure we dequeue the same packet next time */
-		wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
-				      WL12XX_MAX_LINKS;
+		wlvif->last_tx_hlid = (hlid + wl->num_links - 1) %
+				      wl->num_links;
 	}
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
@@ -722,7 +731,7 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
 	timeout = wl->conf.rx_streaming.duration;
 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
 		bool found = false;
-		for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) {
+		for_each_set_bit(hlid, active_hlids, wl->num_links) {
 			if (test_bit(hlid, wlvif->links_map)) {
 				found  = true;
 				break;
@@ -759,7 +768,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
 	struct wl1271_tx_hw_descr *desc;
 	u32 buf_offset = 0, last_len = 0;
 	bool sent_packets = false;
-	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
+	unsigned long active_hlids[BITS_TO_LONGS(WLCORE_MAX_LINKS)] = {0};
 	int ret = 0;
 	int bus_ret = 0;
 	u8 hlid;
@@ -1061,7 +1070,7 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 	int i;
 
 	/* TX failure */
-	for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
+	for_each_set_bit(i, wlvif->links_map, wl->num_links) {
 		if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
 		    i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) {
 			/* this calls wl12xx_free_link */
@@ -1085,7 +1094,7 @@ void wl12xx_tx_reset(struct wl1271 *wl)
 
 	/* only reset the queues if something bad happened */
 	if (wl1271_tx_total_queue_count(wl) != 0) {
-		for (i = 0; i < WL12XX_MAX_LINKS; i++)
+		for (i = 0; i < wl->num_links; i++)
 			wl1271_tx_reset_link_queues(wl, i);
 
 		for (i = 0; i < NUM_TX_QUEUES; i++)
@@ -1178,7 +1187,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
 		       WL1271_TX_FLUSH_TIMEOUT / 1000);
 
 	/* forcibly flush all Tx buffers on our queues */
-	for (i = 0; i < WL12XX_MAX_LINKS; i++)
+	for (i = 0; i < wl->num_links; i++)
 		wl1271_tx_reset_link_queues(wl, i);
 
 out_wake:
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index 35489c300da1..79cb3ff8b71f 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -37,6 +37,7 @@
 #define TX_HW_ATTR_TX_CMPLT_REQ          BIT(12)
 #define TX_HW_ATTR_TX_DUMMY_REQ          BIT(13)
 #define TX_HW_ATTR_HOST_ENCRYPT          BIT(14)
+#define TX_HW_ATTR_EAPOL_FRAME           BIT(15)
 
 #define TX_HW_ATTR_OFST_SAVE_RETRIES     0
 #define TX_HW_ATTR_OFST_HEADER_PAD       1
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 06efc12a39e5..95a54504f0cc 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -73,6 +73,8 @@ struct wlcore_ops {
 	void (*tx_immediate_compl)(struct wl1271 *wl);
 	int (*hw_init)(struct wl1271 *wl);
 	int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
+	void (*convert_fw_status)(struct wl1271 *wl, void *raw_fw_status,
+				  struct wl_fw_status *fw_status);
 	u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
 				    struct wl12xx_vif *wlvif);
 	int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
@@ -220,7 +222,7 @@ struct wl1271 {
 	int channel;
 	u8 system_hlid;
 
-	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+	unsigned long links_map[BITS_TO_LONGS(WLCORE_MAX_LINKS)];
 	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 	unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 	unsigned long rate_policies_map[
@@ -228,7 +230,7 @@ struct wl1271 {
 	unsigned long klv_templates_map[
 			BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)];
 
-	u8 session_ids[WL12XX_MAX_LINKS];
+	u8 session_ids[WLCORE_MAX_LINKS];
 
 	struct list_head wlvif_list;
 
@@ -346,8 +348,8 @@ struct wl1271 {
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-	struct wl_fw_status_1 *fw_status_1;
-	struct wl_fw_status_2 *fw_status_2;
+	void *raw_fw_status;
+	struct wl_fw_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	/* Current chipset configuration */
@@ -376,7 +378,7 @@ struct wl1271 {
 	 * AP-mode - links indexed by HLID. The global and broadcast links
 	 * are always active.
 	 */
-	struct wl1271_link links[WL12XX_MAX_LINKS];
+	struct wl1271_link links[WLCORE_MAX_LINKS];
 
 	/* number of currently active links */
 	int active_link_count;
@@ -405,6 +407,9 @@ struct wl1271 {
 	/* AP-mode - number of currently connected stations */
 	int active_sta_count;
 
+	/* Flag determining whether AP should broadcast OFDM-only rates */
+	bool ofdm_only_ap;
+
 	/* last wlvif we transmitted from */
 	struct wl12xx_vif *last_wlvif;
 
@@ -434,6 +439,10 @@ struct wl1271 {
 	u32 num_tx_desc;
 	/* number of RX descriptors the HW supports. */
 	u32 num_rx_desc;
+	/* number of links the HW supports */
+	u8 num_links;
+	/* max stations a single AP can support */
+	u8 max_ap_stations;
 
 	/* translate HW Tx rates to standard rate-indices */
 	const u8 **band_rate_to_idx;
@@ -448,10 +457,11 @@ struct wl1271 {
 	struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
 
 	/* size of the private FW status data */
+	size_t fw_status_len;
 	size_t fw_status_priv_len;
 
 	/* RX Data filter rule state - enabled/disabled */
-	bool rx_filter_enabled[WL1271_MAX_RX_FILTERS];
+	unsigned long rx_filter_enabled[BITS_TO_LONGS(WL1271_MAX_RX_FILTERS)];
 
 	/* size of the private static data */
 	size_t static_data_priv_len;
@@ -476,8 +486,9 @@ struct wl1271 {
 
 	struct completion nvs_loading_complete;
 
-	/* number of concurrent channels the HW supports */
-	u32 num_channels;
+	/* interface combinations supported by the hw */
+	const struct ieee80211_iface_combination *iface_combinations;
+	u8 n_iface_combinations;
 };
 
 int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index ce7261ce8b59..756e890bc5ee 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -58,10 +58,15 @@
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
 #define WL12XX_MAX_ROLES           4
-#define WL12XX_MAX_LINKS           12
 #define WL12XX_INVALID_ROLE_ID     0xff
 #define WL12XX_INVALID_LINK_ID     0xff
 
+/*
+ * max number of links allowed by all HWs.
+ * this is NOT the actual max links supported by the current hw.
+ */
+#define WLCORE_MAX_LINKS 16
+
 /* the driver supports the 2.4Ghz and 5Ghz bands */
 #define WLCORE_NUM_BANDS           2
 
@@ -118,72 +123,58 @@ struct wl1271_chip {
 
 #define NUM_TX_QUEUES              4
 
-#define AP_MAX_STATIONS            8
-
-struct wl_fw_packet_counters {
-	/* Cumulative counter of released packets per AC */
-	u8 tx_released_pkts[NUM_TX_QUEUES];
-
-	/* Cumulative counter of freed packets per HLID */
-	u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
-
-	/* Cumulative counter of released Voice memory blocks */
-	u8 tx_voice_released_blks;
-
-	/* Tx rate of the last transmitted packet */
-	u8 tx_last_rate;
-
-	u8 padding[2];
-} __packed;
-
-/* FW status registers */
-struct wl_fw_status_1 {
-	__le32 intr;
+struct wl_fw_status {
+	u32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
-	u8  reserved;
 	u8  tx_results_counter;
-	__le32 rx_pkt_descs[0];
-} __packed;
-
-/*
- * Each HW arch has a different number of Rx descriptors.
- * The length of the status depends on it, since it holds an array
- * of descriptors.
- */
-#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \
-		(sizeof(struct wl_fw_status_1) + \
-		(sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \
-		num_rx_desc)
+	__le32 *rx_pkt_descs;
 
-struct wl_fw_status_2 {
-	__le32 fw_localtime;
+	u32 fw_localtime;
 
 	/*
 	 * A bitmap (where each bit represents a single HLID)
 	 * to indicate if the station is in PS mode.
 	 */
-	__le32 link_ps_bitmap;
+	u32 link_ps_bitmap;
 
 	/*
 	 * A bitmap (where each bit represents a single HLID) to indicate
 	 * if the station is in Fast mode
 	 */
-	__le32 link_fast_bitmap;
+	u32 link_fast_bitmap;
 
 	/* Cumulative counter of total released mem blocks since FW-reset */
-	__le32 total_released_blks;
+	u32 total_released_blks;
 
 	/* Size (in Memory Blocks) of TX pool */
-	__le32 tx_total;
+	u32 tx_total;
+
+	struct {
+		/*
+		 * Cumulative counter of released packets per AC
+		 * (length of the array is NUM_TX_QUEUES)
+		 */
+		u8 *tx_released_pkts;
 
-	struct wl_fw_packet_counters counters;
+		/*
+		 * Cumulative counter of freed packets per HLID
+		 * (length of the array is wl->num_links)
+		 */
+		u8 *tx_lnk_free_pkts;
+
+		/* Cumulative counter of released Voice memory blocks */
+		u8 tx_voice_released_blks;
 
-	__le32 log_start_addr;
+		/* Tx rate of the last transmitted packet */
+		u8 tx_last_rate;
+	} counters;
+
+	u32 log_start_addr;
 
 	/* Private status to be used by the lower drivers */
-	u8 priv[0];
-} __packed;
+	void *priv;
+};
 
 #define WL1271_MAX_CHANNELS 64
 struct wl1271_scan {
@@ -240,6 +231,7 @@ enum wl12xx_flags {
 	WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
 	WL1271_FLAG_INTENDED_FW_RECOVERY,
 	WL1271_FLAG_IO_FAILED,
+	WL1271_FLAG_REINIT_TX_WDOG,
 };
 
 enum wl12xx_vif_flags {
@@ -368,7 +360,7 @@ struct wl12xx_vif {
 
 			/* HLIDs bitmap of associated stations */
 			unsigned long sta_hlid_map[BITS_TO_LONGS(
-							WL12XX_MAX_LINKS)];
+							WLCORE_MAX_LINKS)];
 
 			/* recoreded keys - set here before AP startup */
 			struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS];
@@ -385,7 +377,7 @@ struct wl12xx_vif {
 	/* counters of packets per AC, across all links in the vif */
 	int tx_queue_count[NUM_TX_QUEUES];
 
-	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+	unsigned long links_map[BITS_TO_LONGS(WLCORE_MAX_LINKS)];
 
 	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 ssid_len;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index f9daa9e183f2..a38f03ded5a4 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -907,6 +907,7 @@ static int handle_incoming_queue(struct net_device *dev,
 
 		/* Ethernet work: Delayed to here as it peeks the header. */
 		skb->protocol = eth_type_trans(skb, dev);
+		skb_reset_network_header(skb);
 
 		if (checksum_setup(dev, skb)) {
 			kfree_skb(skb);
@@ -1281,16 +1282,10 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 	np->rx_refill_timer.function = rx_refill_timeout;
 
 	err = -ENOMEM;
-	np->stats = alloc_percpu(struct netfront_stats);
+	np->stats = netdev_alloc_pcpu_stats(struct netfront_stats);
 	if (np->stats == NULL)
 		goto exit;
 
-	for_each_possible_cpu(i) {
-		struct netfront_stats *xen_nf_stats;
-		xen_nf_stats = per_cpu_ptr(np->stats, i);
-		u64_stats_init(&xen_nf_stats->syncp);
-	}
-
 	/* Initialise tx_skbs as a free chain containing every entry. */
 	np->tx_skb_freelist = 0;
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index c6973f101a3e..ffdcb11f75fb 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -44,6 +44,10 @@ config OF_DYNAMIC
 config OF_ADDRESS
 	def_bool y
 	depends on !SPARC
+	select OF_ADDRESS_PCI if PCI
+
+config OF_ADDRESS_PCI
+	bool
 
 config OF_IRQ
 	def_bool y
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 1a54f1ffaadb..cb4242a69cd5 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -91,7 +91,7 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
 	return IORESOURCE_MEM;
 }
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_OF_ADDRESS_PCI
 /*
  * PCI bus specific translator
  */
@@ -166,7 +166,9 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
 {
 	return of_bus_default_translate(addr + 1, offset, na - 1);
 }
+#endif /* CONFIG_OF_ADDRESS_PCI */
 
+#ifdef CONFIG_PCI
 const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
 			unsigned int *flags)
 {
@@ -356,7 +358,7 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr)
  */
 
 static struct of_bus of_busses[] = {
-#ifdef CONFIG_PCI
+#ifdef CONFIG_OF_ADDRESS_PCI
 	/* PCI */
 	{
 		.name = "pci",
@@ -367,7 +369,7 @@ static struct of_bus of_busses[] = {
 		.translate = of_bus_pci_translate,
 		.get_flags = of_bus_pci_get_flags,
 	},
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_OF_ADDRESS_PCI */
 	/* ISA */
 	{
 		.name = "isa",
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 89e888a78899..3d1c864a5b6c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -904,6 +904,38 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
+ * of_property_count_elems_of_size - Count the number of elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @elem_size:	size of the individual element
+ *
+ * Search for a property in a device node and count the number of elements of
+ * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
+ * property does not exist or its length does not match a multiple of elem_size
+ * and -ENODATA if the property does not have a value.
+ */
+int of_property_count_elems_of_size(const struct device_node *np,
+				const char *propname, int elem_size)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+
+	if (prop->length % elem_size != 0) {
+		pr_err("size of %s in node %s is not a multiple of %d\n",
+		       propname, np->full_name, elem_size);
+		return -EINVAL;
+	}
+
+	return prop->length / elem_size;
+}
+EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
+
+/**
  * of_find_property_value_of_size
  *
  * @np:		device node from which the property value is to be read.
@@ -1511,11 +1543,31 @@ static int of_property_notify(int action, struct device_node *np,
 #endif
 
 /**
+ * __of_add_property - Add a property to a node without lock operations
+ */
+static int __of_add_property(struct device_node *np, struct property *prop)
+{
+	struct property **next;
+
+	prop->next = NULL;
+	next = &np->properties;
+	while (*next) {
+		if (strcmp(prop->name, (*next)->name) == 0)
+			/* duplicate ! don't insert it */
+			return -EEXIST;
+
+		next = &(*next)->next;
+	}
+	*next = prop;
+
+	return 0;
+}
+
+/**
  * of_add_property - Add a property to a node
  */
 int of_add_property(struct device_node *np, struct property *prop)
 {
-	struct property **next;
 	unsigned long flags;
 	int rc;
 
@@ -1523,27 +1575,17 @@ int of_add_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	prop->next = NULL;
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (strcmp(prop->name, (*next)->name) == 0) {
-			/* duplicate ! don't insert it */
-			raw_spin_unlock_irqrestore(&devtree_lock, flags);
-			return -1;
-		}
-		next = &(*next)->next;
-	}
-	*next = prop;
+	rc = __of_add_property(np, prop);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 #ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
-	if (np->pde)
+	if (!rc && np->pde)
 		proc_device_tree_add_prop(np->pde, prop);
 #endif /* CONFIG_PROC_DEVICETREE */
 
-	return 0;
+	return rc;
 }
 
 /**
@@ -1605,7 +1647,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 {
 	struct property **next, *oldprop;
 	unsigned long flags;
-	int rc, found = 0;
+	int rc = 0;
 
 	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
 	if (rc)
@@ -1614,36 +1656,28 @@ int of_update_property(struct device_node *np, struct property *newprop)
 	if (!newprop->name)
 		return -EINVAL;
 
-	oldprop = of_find_property(np, newprop->name, NULL);
-	if (!oldprop)
-		return of_add_property(np, newprop);
-
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (*next == oldprop) {
-			/* found the node */
-			newprop->next = oldprop->next;
-			*next = newprop;
-			oldprop->next = np->deadprops;
-			np->deadprops = oldprop;
-			found = 1;
-			break;
-		}
-		next = &(*next)->next;
+	oldprop = __of_find_property(np, newprop->name, NULL);
+	if (!oldprop) {
+		/* add the node */
+		rc = __of_add_property(np, newprop);
+	} else {
+		/* replace the node */
+		next = &oldprop;
+		newprop->next = oldprop->next;
+		*next = newprop;
+		oldprop->next = np->deadprops;
+		np->deadprops = oldprop;
 	}
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	if (!found)
-		return -ENODEV;
-
 #ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
-	if (np->pde)
+	if (!rc && np->pde)
 		proc_device_tree_update_prop(np->pde, newprop, oldprop);
 #endif /* CONFIG_PROC_DEVICETREE */
 
-	return 0;
+	return rc;
 }
 
 #if defined(CONFIG_OF_DYNAMIC)
@@ -1710,6 +1744,7 @@ int of_attach_node(struct device_node *np)
 	np->allnext = of_allnodes;
 	np->parent->child = np;
 	of_allnodes = np;
+	of_node_clear_flag(np, OF_DETACHED);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_add_proc_dt_entry(np);
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
index a208a457558c..73e14184aafe 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -12,33 +12,12 @@
 #include <linux/export.h>
 
 /**
- * It maps 'enum phy_interface_t' found in include/linux/phy.h
- * into the device tree binding of 'phy-mode', so that Ethernet
- * device driver can get phy interface from device tree.
- */
-static const char *phy_modes[] = {
-	[PHY_INTERFACE_MODE_NA]		= "",
-	[PHY_INTERFACE_MODE_MII]	= "mii",
-	[PHY_INTERFACE_MODE_GMII]	= "gmii",
-	[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
-	[PHY_INTERFACE_MODE_TBI]	= "tbi",
-	[PHY_INTERFACE_MODE_REVMII]	= "rev-mii",
-	[PHY_INTERFACE_MODE_RMII]	= "rmii",
-	[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
-	[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
-	[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
-	[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
-	[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
-	[PHY_INTERFACE_MODE_SMII]	= "smii",
-	[PHY_INTERFACE_MODE_XGMII]	= "xgmii",
-};
-
-/**
  * of_get_phy_mode - Get phy mode for given device_node
  * @np:	Pointer to the given device_node
  *
- * The function gets phy interface string from property 'phy-mode',
- * and return its index in phy_modes table, or errno in error case.
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
  */
 int of_get_phy_mode(struct device_node *np)
 {
@@ -47,10 +26,12 @@ int of_get_phy_mode(struct device_node *np)
 
 	err = of_property_read_string(np, "phy-mode", &pm);
 	if (err < 0)
+		err = of_property_read_string(np, "phy-connection-type", &pm);
+	if (err < 0)
 		return err;
 
-	for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
-		if (!strcasecmp(pm, phy_modes[i]))
+	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
+		if (!strcasecmp(pm, phy_modes(i)))
 			return i;
 
 	return -ENODEV;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 6a83ee1e9178..3fa66244ce32 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -905,7 +905,8 @@ int parport_claim_or_block(struct pardevice *dev)
 		/* If dev->waiting is clear now, an interrupt
 		   gave us the port and we would deadlock if we slept.  */
 		if (dev->waiting) {
-			interruptible_sleep_on (&dev->wait_q);
+			wait_event_interruptible(dev->wait_q,
+						 !dev->waiting);
 			if (signal_pending (current)) {
 				return -EINTR;
 			}
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 17d2b07ee67c..e04fe2d9df3b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -33,21 +33,14 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 #
 # Some architectures use the generic PCI setup functions
 #
-obj-$(CONFIG_X86) += setup-bus.o
-obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
-obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
-obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
-obj-$(CONFIG_PARISC) += setup-bus.o
-obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
-obj-$(CONFIG_PPC) += setup-bus.o
-obj-$(CONFIG_FRV) += setup-bus.o
-obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
-obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_MN10300) += setup-bus.o
-obj-$(CONFIG_MICROBLAZE) += setup-bus.o
-obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
-obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
-obj-$(CONFIG_M68K) += setup-bus.o setup-irq.o
+obj-$(CONFIG_ALPHA) += setup-irq.o
+obj-$(CONFIG_ARM) += setup-irq.o
+obj-$(CONFIG_UNICORE32) += setup-irq.o
+obj-$(CONFIG_SUPERH) += setup-irq.o
+obj-$(CONFIG_MIPS) += setup-irq.o
+obj-$(CONFIG_TILE) += setup-irq.o
+obj-$(CONFIG_SPARC_LEON) += setup-irq.o
+obj-$(CONFIG_M68K) += setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 47d46c6d8468..a6f67ec8882f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -27,7 +27,7 @@ config PCI_TEGRA
 
 config PCI_RCAR_GEN2
 	bool "Renesas R-Car Gen2 Internal PCI controller"
-	depends on ARM && (ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST)
+	depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
 	help
 	  Say Y here if you want internal PCI support on R-Car Gen2 SoC.
 	  There are 3 internal PCI controllers available with a single
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index e8663a8c3406..ee082509b0ba 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -424,20 +424,40 @@ static void imx6_pcie_reset_phy(struct pcie_port *pp)
 
 static int imx6_pcie_link_up(struct pcie_port *pp)
 {
-	u32 rc, ltssm, rx_valid;
+	u32 rc, debug_r0, rx_valid;
+	int count = 5;
 
 	/*
-	 * Test if the PHY reports that the link is up and also that
-	 * the link training finished.  It might happen that the PHY
-	 * reports the link is already up, but the link training bit
-	 * is still set, so make sure to check the training is done
-	 * as well here.
+	 * Test if the PHY reports that the link is up and also that the LTSSM
+	 * training finished. There are three possible states of the link when
+	 * this code is called:
+	 * 1) The link is DOWN (unlikely)
+	 *     The link didn't come up yet for some reason. This usually means
+	 *     we have a real problem somewhere. Reset the PHY and exit. This
+	 *     state calls for inspection of the DEBUG registers.
+	 * 2) The link is UP, but still in LTSSM training
+	 *     Wait for the training to finish, which should take a very short
+	 *     time. If the training does not finish, we have a problem and we
+	 *     need to inspect the DEBUG registers. If the training does finish,
+	 *     the link is up and operating correctly.
+	 * 3) The link is UP and no longer in LTSSM training
+	 *     The link is up and operating correctly.
 	 */
-	rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
-	if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
-	    !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
-		return 1;
-
+	while (1) {
+		rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+		if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
+			break;
+		if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
+			return 1;
+		if (!count--)
+			break;
+		dev_dbg(pp->dev, "Link is up, but still in training\n");
+		/*
+		 * Wait a little bit, then re-check if the link finished
+		 * the training.
+		 */
+		usleep_range(1000, 2000);
+	}
 	/*
 	 * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
 	 * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
@@ -446,15 +466,16 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
 	 * to gen2 is stuck
 	 */
 	pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
-	ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
+	debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
 
 	if (rx_valid & 0x01)
 		return 0;
 
-	if (ltssm != 0x0d)
+	if ((debug_r0 & 0x3f) != 0x0d)
 		return 0;
 
 	dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
+	dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
 
 	imx6_pcie_reset_phy(pp);
 
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 0e79665afd44..d3d1cfd51e09 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -101,7 +101,9 @@ struct mvebu_pcie {
 	struct mvebu_pcie_port *ports;
 	struct msi_chip *msi;
 	struct resource io;
+	char io_name[30];
 	struct resource realio;
+	char mem_name[30];
 	struct resource mem;
 	struct resource busn;
 	int nports;
@@ -672,10 +674,30 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct mvebu_pcie *pcie = sys_to_pcie(sys);
 	int i;
+	int domain = 0;
 
-	if (resource_size(&pcie->realio) != 0)
+#ifdef CONFIG_PCI_DOMAINS
+	domain = sys->domain;
+#endif
+
+	snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x",
+		 domain);
+	pcie->mem.name = pcie->mem_name;
+
+	snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
+	pcie->realio.name = pcie->io_name;
+
+	if (request_resource(&iomem_resource, &pcie->mem))
+		return 0;
+
+	if (resource_size(&pcie->realio) != 0) {
+		if (request_resource(&ioport_resource, &pcie->realio)) {
+			release_resource(&pcie->mem);
+			return 0;
+		}
 		pci_add_resource_offset(&sys->resources, &pcie->realio,
 					sys->io_offset);
+	}
 	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
 	pci_add_resource(&sys->resources, &pcie->busn);
 
@@ -797,7 +819,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 
 	for (i = 0; i < nranges; i++) {
 		u32 flags = of_read_number(range, 1);
-		u32 slot = of_read_number(range, 2);
+		u32 slot = of_read_number(range + 1, 1);
 		u64 cpuaddr = of_read_number(range + na, pna);
 		unsigned long rtype;
 
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index ceec147baec3..fd3e3ab56509 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -18,6 +18,7 @@
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 
 /* AHB-PCI Bridge PCI communication registers */
@@ -39,9 +40,26 @@
 
 #define RCAR_PCI_INT_ENABLE_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
 #define RCAR_PCI_INT_STATUS_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
+#define RCAR_PCI_INT_SIGTABORT		(1 << 0)
+#define RCAR_PCI_INT_SIGRETABORT	(1 << 1)
+#define RCAR_PCI_INT_REMABORT		(1 << 2)
+#define RCAR_PCI_INT_PERR		(1 << 3)
+#define RCAR_PCI_INT_SIGSERR		(1 << 4)
+#define RCAR_PCI_INT_RESERR		(1 << 5)
+#define RCAR_PCI_INT_WIN1ERR		(1 << 12)
+#define RCAR_PCI_INT_WIN2ERR		(1 << 13)
 #define RCAR_PCI_INT_A			(1 << 16)
 #define RCAR_PCI_INT_B			(1 << 17)
 #define RCAR_PCI_INT_PME		(1 << 19)
+#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT		| \
+				RCAR_PCI_INT_SIGRETABORT	| \
+				RCAR_PCI_INT_SIGRETABORT	| \
+				RCAR_PCI_INT_REMABORT		| \
+				RCAR_PCI_INT_PERR		| \
+				RCAR_PCI_INT_SIGSERR		| \
+				RCAR_PCI_INT_RESERR		| \
+				RCAR_PCI_INT_WIN1ERR		| \
+				RCAR_PCI_INT_WIN2ERR)
 
 #define RCAR_AHB_BUS_CTR_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
 #define RCAR_AHB_BUS_MMODE_HTRANS	(1 << 0)
@@ -74,9 +92,6 @@
 
 #define RCAR_PCI_UNIT_REV_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
 
-/* Number of internal PCI controllers */
-#define RCAR_PCI_NR_CONTROLLERS		3
-
 struct rcar_pci_priv {
 	struct device *dev;
 	void __iomem *reg;
@@ -84,6 +99,7 @@ struct rcar_pci_priv {
 	struct resource mem_res;
 	struct resource *cfg_res;
 	int irq;
+	unsigned long window_size;
 };
 
 /* PCI configuration space operations */
@@ -102,6 +118,10 @@ static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
 	if (slot > 2)
 		return NULL;
 
+	/* bridge logic only has registers to 0x40 */
+	if (slot == 0x0 && where >= 0x40)
+		return NULL;
+
 	val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG :
 		     RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG;
 
@@ -156,7 +176,7 @@ static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 }
 
 /* PCI interrupt mapping */
-static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+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;
@@ -164,8 +184,48 @@ static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return priv->irq;
 }
 
+#ifdef CONFIG_PCI_DEBUG
+/* if debug enabled, then attach an error handler irq to the bridge */
+
+static irqreturn_t rcar_pci_err_irq(int irq, void *pw)
+{
+	struct rcar_pci_priv *priv = pw;
+	u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG);
+
+	if (status & RCAR_PCI_INT_ALLERRORS) {
+		dev_err(priv->dev, "error irq: status %08x\n", status);
+
+		/* clear the error(s) */
+		iowrite32(status & RCAR_PCI_INT_ALLERRORS,
+			  priv->reg + RCAR_PCI_INT_STATUS_REG);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv)
+{
+	int ret;
+	u32 val;
+
+	ret = devm_request_irq(priv->dev, priv->irq, rcar_pci_err_irq,
+			       IRQF_SHARED, "error irq", priv);
+	if (ret) {
+		dev_err(priv->dev, "cannot claim IRQ for error handling\n");
+		return;
+	}
+
+	val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG);
+	val |= RCAR_PCI_INT_ALLERRORS;
+	iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG);
+}
+#else
+static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { }
+#endif
+
 /* PCI host controller setup */
-static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
+static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
 {
 	struct rcar_pci_priv *priv = sys->private_data;
 	void __iomem *reg = priv->reg;
@@ -183,10 +243,31 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
 	iowrite32(val, reg + RCAR_USBCTR_REG);
 	udelay(4);
 
-	/* De-assert reset and set PCIAHB window1 size to 1GB */
+	/* De-assert reset and reset PCIAHB window1 size */
 	val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK |
 		 RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST);
-	iowrite32(val | RCAR_USBCTR_PCIAHB_WIN1_1G, reg + RCAR_USBCTR_REG);
+
+	/* Setup PCIAHB window1 size */
+	switch (priv->window_size) {
+	case SZ_2G:
+		val |= RCAR_USBCTR_PCIAHB_WIN1_2G;
+		break;
+	case SZ_1G:
+		val |= RCAR_USBCTR_PCIAHB_WIN1_1G;
+		break;
+	case SZ_512M:
+		val |= RCAR_USBCTR_PCIAHB_WIN1_512M;
+		break;
+	default:
+		pr_warn("unknown window size %ld - defaulting to 256M\n",
+			priv->window_size);
+		priv->window_size = SZ_256M;
+		/* fall-through */
+	case SZ_256M:
+		val |= RCAR_USBCTR_PCIAHB_WIN1_256M;
+		break;
+	}
+	iowrite32(val, reg + RCAR_USBCTR_REG);
 
 	/* Configure AHB master and slave modes */
 	iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG);
@@ -197,7 +278,7 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
 	       RCAR_PCI_ARBITER_PCIBP_MODE;
 	iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
 
-	/* PCI-AHB mapping: 0x40000000-0x80000000 */
+	/* PCI-AHB mapping: 0x40000000 base */
 	iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16,
 		  reg + RCAR_PCIAHB_WIN1_CTR_REG);
 
@@ -224,10 +305,15 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
 	iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME,
 		  reg + RCAR_PCI_INT_ENABLE_REG);
 
+	if (priv->irq > 0)
+		rcar_pci_setup_errirq(priv);
+
 	/* Add PCI resources */
 	pci_add_resource(&sys->resources, &priv->io_res);
 	pci_add_resource(&sys->resources, &priv->mem_res);
 
+	/* Setup bus number based on platform device id */
+	sys->busnr = to_platform_device(priv->dev)->id;
 	return 1;
 }
 
@@ -236,48 +322,13 @@ static struct pci_ops rcar_pci_ops = {
 	.write	= rcar_pci_write_config,
 };
 
-static struct hw_pci rcar_hw_pci __initdata = {
-	.map_irq	= rcar_pci_map_irq,
-	.ops		= &rcar_pci_ops,
-	.setup		= rcar_pci_setup,
-};
-
-static int rcar_pci_count __initdata;
-
-static int __init rcar_pci_add_controller(struct rcar_pci_priv *priv)
-{
-	void **private_data;
-	int count;
-
-	if (rcar_hw_pci.nr_controllers < rcar_pci_count)
-		goto add_priv;
-
-	/* (Re)allocate private data pointer array if needed */
-	count = rcar_pci_count + RCAR_PCI_NR_CONTROLLERS;
-	private_data = kzalloc(count * sizeof(void *), GFP_KERNEL);
-	if (!private_data)
-		return -ENOMEM;
-
-	rcar_pci_count = count;
-	if (rcar_hw_pci.private_data) {
-		memcpy(private_data, rcar_hw_pci.private_data,
-		       rcar_hw_pci.nr_controllers * sizeof(void *));
-		kfree(rcar_hw_pci.private_data);
-	}
-
-	rcar_hw_pci.private_data = private_data;
-
-add_priv:
-	/* Add private data pointer to the array */
-	rcar_hw_pci.private_data[rcar_hw_pci.nr_controllers++] = priv;
-	return 0;
-}
-
-static int __init rcar_pci_probe(struct platform_device *pdev)
+static int rcar_pci_probe(struct platform_device *pdev)
 {
 	struct resource *cfg_res, *mem_res;
 	struct rcar_pci_priv *priv;
 	void __iomem *reg;
+	struct hw_pci hw;
+	void *hw_private[1];
 
 	cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	reg = devm_ioremap_resource(&pdev->dev, cfg_res);
@@ -308,31 +359,34 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
 	priv->reg = reg;
 	priv->dev = &pdev->dev;
 
-	return rcar_pci_add_controller(priv);
+	if (priv->irq < 0) {
+		dev_err(&pdev->dev, "no valid irq found\n");
+		return priv->irq;
+	}
+
+	priv->window_size = SZ_1G;
+
+	hw_private[0] = priv;
+	memset(&hw, 0, sizeof(hw));
+	hw.nr_controllers = ARRAY_SIZE(hw_private);
+	hw.private_data = hw_private;
+	hw.map_irq = rcar_pci_map_irq;
+	hw.ops = &rcar_pci_ops;
+	hw.setup = rcar_pci_setup;
+	pci_common_init_dev(&pdev->dev, &hw);
+	return 0;
 }
 
 static struct platform_driver rcar_pci_driver = {
 	.driver = {
 		.name = "pci-rcar-gen2",
+		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
 	},
+	.probe = rcar_pci_probe,
 };
 
-static int __init rcar_pci_init(void)
-{
-	int retval;
-
-	retval = platform_driver_probe(&rcar_pci_driver, rcar_pci_probe);
-	if (!retval)
-		pci_common_init(&rcar_hw_pci);
-
-	/* Private data pointer array is not needed any more */
-	kfree(rcar_hw_pci.private_data);
-	rcar_hw_pci.private_data = NULL;
-
-	return retval;
-}
-
-subsys_initcall(rcar_pci_init);
+module_platform_driver(rcar_pci_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI");
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 17ce88f79d2b..6d23d8c893cd 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -800,7 +800,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 
 	/* setup RC BARs */
 	dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0);
-	dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_1);
+	dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);
 
 	/* setup interrupt pins */
 	dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val);
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index b6162be4df40..2b859249303b 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -93,7 +93,6 @@ struct acpiphp_slot {
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 	struct slot *slot;
-	struct mutex crit_sect;
 
 	u8		device;		/* pci device# */
 	u32		flags;		/* see below */
@@ -117,20 +116,30 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
-	acpi_handle handle;
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
 }
 
+static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
+{
+	return func_to_context(func)->hp.self;
+}
+
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
 {
-	return func_to_context(func)->handle;
+	return func_to_acpi_device(func)->handle;
 }
 
 /*
@@ -158,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7c7a388c85ab..0d46d2fef96b 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,71 +58,59 @@
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
-static DEFINE_MUTEX(acpiphp_context_lock);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type);
+static void acpiphp_post_dock_fixup(struct acpi_device *adev);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event(acpi_handle handle, u32 type, void *data);
+static void hotplug_event(u32 type, struct acpiphp_context *context);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
- * @handle: ACPI object handle to create the context for.
+ * @adev: ACPI device object to create the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->handle = handle;
 	context->refcount = 1;
-	status = acpi_attach_data(handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL,
+			    acpiphp_post_dock_fixup);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context;
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	if (!adev->hp)
+		return NULL;
+
+	context = to_acpiphp_context(adev->hp);
+	context->refcount++;
 	return context;
 }
 
 /**
  * acpiphp_put_context - Drop a reference to ACPI hotplug context.
- * @handle: ACPI object handle to put the context for.
+ * @context: ACPI hotplug context to drop a reference to.
  *
  * The context object is removed if there are no more references to it.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static void acpiphp_put_context(struct acpiphp_context *context)
 {
@@ -130,7 +118,7 @@ static void acpiphp_put_context(struct acpiphp_context *context)
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -144,6 +132,27 @@ static inline void put_bridge(struct acpiphp_bridge *bridge)
 	kref_put(&bridge->ref, free_bridge);
 }
 
+static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev)
+{
+	struct acpiphp_context *context;
+
+	acpi_lock_hp_context();
+	context = acpiphp_get_context(adev);
+	if (!context || context->func.parent->is_going_away) {
+		acpi_unlock_hp_context();
+		return NULL;
+	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	acpi_unlock_hp_context();
+	return context;
+}
+
+static void acpiphp_let_context_go(struct acpiphp_context *context)
+{
+	put_bridge(context->func.parent);
+}
+
 static void free_bridge(struct kref *kref)
 {
 	struct acpiphp_context *context;
@@ -151,7 +160,7 @@ static void free_bridge(struct kref *kref)
 	struct acpiphp_slot *slot, *next;
 	struct acpiphp_func *func, *tmp;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 
 	bridge = container_of(kref, struct acpiphp_bridge, ref);
 
@@ -175,31 +184,32 @@ static void free_bridge(struct kref *kref)
 	pci_dev_put(bridge->pci_dev);
 	kfree(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
-/*
- * the _DCK method can do funny things... and sometimes not
- * hah-hah funny.
+/**
+ * acpiphp_post_dock_fixup - Post-dock fixups for PCI devices.
+ * @adev: ACPI device object corresponding to a PCI device.
  *
- * TBD - figure out a way to only call fixups for
- * systems that require them.
+ * TBD - figure out a way to only call fixups for systems that require them.
  */
-static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
+static void acpiphp_post_dock_fixup(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = data;
-	struct pci_bus *bus = context->func.slot->bus;
+	struct acpiphp_context *context = acpiphp_grab_context(adev);
+	struct pci_bus *bus;
 	u32 buses;
 
-	if (!bus->self)
+	if (!context)
 		return;
 
+	bus = context->func.slot->bus;
+	if (!bus->self)
+		goto out;
+
 	/* fixup bad _DCK function that rewrites
 	 * secondary bridge on slot
 	 */
-	pci_read_config_dword(bus->self,
-			PCI_PRIMARY_BUS,
-			&buses);
+	pci_read_config_dword(bus->self, PCI_PRIMARY_BUS, &buses);
 
 	if (((buses >> 8) & 0xff) != bus->busn_res.start) {
 		buses = (buses & 0xff000000)
@@ -208,33 +218,11 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
 			| ((unsigned int)(bus->busn_res.end) << 16);
 		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
 	}
-}
-
-static void dock_event(acpi_handle handle, u32 type, void *data)
-{
-	struct acpiphp_context *context;
-
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->handle != handle)
-	    || context->func.parent->is_going_away) {
-		mutex_unlock(&acpiphp_context_lock);
-		return;
-	}
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
-
-	hotplug_event(handle, type, data);
 
-	put_bridge(context->func.parent);
+ out:
+	acpiphp_let_context_go(context);
 }
 
-static const struct acpi_dock_ops acpiphp_dock_ops = {
-	.fixup = post_dock_fixups,
-	.handler = dock_event,
-};
-
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
 static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
 {
@@ -264,26 +252,19 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
 	return true;
 }
 
-static void acpiphp_dock_init(void *data)
-{
-	struct acpiphp_context *context = data;
-
-	get_bridge(context->func.parent);
-}
-
-static void acpiphp_dock_release(void *data)
-{
-	struct acpiphp_context *context = data;
-
-	put_bridge(context->func.parent);
-}
-
-/* callback routine to register each ACPI PCI slot object */
-static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
-				 void **rv)
+/**
+ * acpiphp_add_context - Add ACPIPHP context to an ACPI device object.
+ * @handle: ACPI handle of the object to add a context to.
+ * @lvl: Not used.
+ * @data: The object's parent ACPIPHP bridge.
+ * @rv: Not used.
+ */
+static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data,
+				       void **rv)
 {
 	struct acpiphp_bridge *bridge = data;
 	struct acpiphp_context *context;
+	struct acpi_device *adev;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
 	acpi_status status = AE_OK;
@@ -293,9 +274,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 	struct pci_dev *pdev = bridge->pci_dev;
 	u32 val;
 
-	if (pdev && device_is_managed_by_native_pciehp(pdev))
-		return AE_OK;
-
 	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
 	if (ACPI_FAILURE(status)) {
 		if (status != AE_NOT_FOUND)
@@ -303,31 +281,34 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 				"can't evaluate _ADR (%#x)\n", status);
 		return AE_OK;
 	}
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
 
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_init_context(handle);
+	acpi_lock_hp_context();
+	context = acpiphp_init_context(adev);
 	if (!context) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		acpi_handle_err(handle, "No hotplug context\n");
 		return AE_NOT_EXIST;
 	}
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
-	if (acpi_has_method(handle, "_EJ0"))
+	/*
+	 * If this is a dock device, its _EJ0 should be executed by the dock
+	 * notify handler after calling _DCK.
+	 */
+	if (!is_dock_device(adev) && acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
 
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
-	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
-
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
 		if (slot->device == device)
@@ -335,19 +316,26 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		status = AE_NO_MEMORY;
-		goto err;
+		acpi_lock_hp_context();
+		acpiphp_put_context(context);
+		acpi_unlock_hp_context();
+		return AE_NO_MEMORY;
 	}
 
 	slot->bus = bridge->pci_bus;
 	slot->device = device;
 	INIT_LIST_HEAD(&slot->funcs);
-	mutex_init(&slot->crit_sect);
 
 	list_add_tail(&slot->node, &bridge->slots);
 
-	/* Register slots for ejectable functions only. */
-	if (acpi_pci_check_ejectable(pbus, handle)  || is_dock_device(handle)) {
+	/*
+	 * Expose slots to user space for functions that have _EJ0 or _RMV or
+	 * are located in dock stations.  Do not expose them for devices handled
+	 * by the native PCIe hotplug (PCIeHP), becuase that code is supposed to
+	 * expose slots to user space in those cases.
+	 */
+	if ((acpi_pci_check_ejectable(pbus, handle) || is_dock_device(adev))
+	    && !(pdev && device_is_managed_by_native_pciehp(pdev))) {
 		unsigned long long sun;
 		int retval;
 
@@ -381,44 +369,16 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 				       &val, 60*1000))
 		slot->flags |= SLOT_ENABLED;
 
-	if (is_dock_device(handle)) {
-		/* we don't want to call this device's _EJ0
-		 * because we want the dock notify handler
-		 * to call it after it calls _DCK
-		 */
-		newfunc->flags &= ~FUNC_HAS_EJ0;
-		if (register_hotplug_dock_device(handle,
-			&acpiphp_dock_ops, context,
-			acpiphp_dock_init, acpiphp_dock_release))
-			pr_debug("failed to register dock device\n");
-	}
-
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
-
 	return AE_OK;
-
- err:
-	mutex_lock(&acpiphp_context_lock);
-	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
-	return status;
 }
 
-static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
+static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
+	acpi_lock_hp_context();
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -426,7 +386,7 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 
 		acpiphp_put_context(context);
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	return bridge;
 }
 
@@ -434,22 +394,15 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
-			acpi_handle handle = func_to_handle(func);
-
-			if (is_dock_device(handle))
-				unregister_hotplug_dock_device(handle);
+			struct acpi_device *adev = func_to_acpi_device(func);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			acpi_lock_hp_context();
+			adev->hp->notify = NULL;
+			adev->hp->fixup = NULL;
+			acpi_unlock_hp_context();
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -460,9 +413,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 	list_del(&bridge->list);
 	mutex_unlock(&bridge_mutex);
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge->is_going_away = true;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
 /**
@@ -471,7 +424,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
  */
 static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 {
-	struct list_head *tmp;
+	struct pci_bus *tmp;
 	unsigned char max, n;
 
 	/*
@@ -484,41 +437,14 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 	 */
 	max = bus->busn_res.start;
 
-	list_for_each(tmp, &bus->children) {
-		n = pci_bus_max_busnr(pci_bus_b(tmp));
+	list_for_each_entry(tmp, &bus->children, node) {
+		n = pci_bus_max_busnr(tmp);
 		if (n > max)
 			max = n;
 	}
 	return max;
 }
 
-/**
- * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
- * @handle: ACPI device object handle to start from.
- */
-static void acpiphp_bus_trim(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
-	if (adev)
-		acpi_bus_trim(adev);
-}
-
-/**
- * acpiphp_bus_add - Scan ACPI namespace subtree.
- * @handle: ACPI object handle to start the scan from.
- */
-static void acpiphp_bus_add(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_scan(handle);
-	acpi_bus_get_device(handle, &adev);
-	if (acpi_device_enumerated(adev))
-		acpi_device_set_power(adev, ACPI_STATE_D0);
-}
-
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
@@ -558,9 +484,13 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_add(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = func_to_acpi_device(func);
 
+		acpi_bus_scan(adev->handle);
+		if (acpi_device_enumerated(adev))
+			acpi_device_set_power(adev, ACPI_STATE_D0);
+	}
 	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
 }
 
@@ -625,32 +555,15 @@ static void __ref enable_slot(struct acpiphp_slot *slot)
 	}
 }
 
-/* return first device in slot, acquiring a reference on it */
-static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *dev;
-	struct pci_dev *ret = NULL;
-
-	down_read(&pci_bus_sem);
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if (PCI_SLOT(dev->devfn) == slot->device) {
-			ret = pci_dev_get(dev);
-			break;
-		}
-	up_read(&pci_bus_sem);
-
-	return ret;
-}
-
 /**
  * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
 static void disable_slot(struct acpiphp_slot *slot)
 {
+	struct pci_bus *bus = slot->bus;
+	struct pci_dev *dev, *prev;
 	struct acpiphp_func *func;
-	struct pci_dev *pdev;
 
 	/*
 	 * enable_slot() enumerates all functions in this device via
@@ -658,22 +571,18 @@ static void disable_slot(struct acpiphp_slot *slot)
 	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
 	 * here.
 	 */
-	while ((pdev = dev_in_slot(slot))) {
-		pci_stop_and_remove_bus_device(pdev);
-		pci_dev_put(pdev);
-	}
+	list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list)
+		if (PCI_SLOT(dev->devfn) == slot->device)
+			pci_stop_and_remove_bus_device(dev);
 
 	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_trim(func_to_handle(func));
+		acpi_bus_trim(func_to_acpi_device(func));
 
 	slot->flags &= (~SLOT_ENABLED);
 }
 
-static bool acpiphp_no_hotplug(acpi_handle handle)
+static bool acpiphp_no_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
 	return adev && adev->flags.no_hotplug;
 }
 
@@ -682,7 +591,7 @@ static bool slot_no_hotplug(struct acpiphp_slot *slot)
 	struct acpiphp_func *func;
 
 	list_for_each_entry(func, &slot->funcs, sibling)
-		if (acpiphp_no_hotplug(func_to_handle(func)))
+		if (acpiphp_no_hotplug(func_to_acpi_device(func)))
 			return true;
 
 	return false;
@@ -747,17 +656,17 @@ static inline bool device_status_valid(unsigned int sta)
  */
 static void trim_stale_devices(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
 	struct pci_bus *bus = dev->subordinate;
 	bool alive = false;
 
-	if (handle) {
+	if (adev) {
 		acpi_status status;
 		unsigned long long sta;
 
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
 		alive = (ACPI_SUCCESS(status) && device_status_valid(sta))
-			|| acpiphp_no_hotplug(handle);
+			|| acpiphp_no_hotplug(adev);
 	}
 	if (!alive) {
 		u32 v;
@@ -767,8 +676,8 @@ static void trim_stale_devices(struct pci_dev *dev)
 	}
 	if (!alive) {
 		pci_stop_and_remove_bus_device(dev);
-		if (handle)
-			acpiphp_bus_trim(handle);
+		if (adev)
+			acpi_bus_trim(adev);
 	} else if (bus) {
 		struct pci_dev *child, *tmp;
 
@@ -800,7 +709,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 		struct pci_bus *bus = slot->bus;
 		struct pci_dev *dev, *tmp;
 
-		mutex_lock(&slot->crit_sect);
 		if (slot_no_hotplug(slot)) {
 			; /* do nothing */
 		} else if (device_status_valid(get_slot_status(slot))) {
@@ -815,7 +723,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 		} else {
 			disable_slot(slot);
 		}
-		mutex_unlock(&slot->crit_sect);
 	}
 }
 
@@ -855,11 +762,11 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
  * ACPI event handlers
  */
 
-void acpiphp_check_host_bridge(acpi_handle handle)
+void acpiphp_check_host_bridge(struct acpi_device *adev)
 {
 	struct acpiphp_bridge *bridge;
 
-	bridge = acpiphp_handle_to_bridge(handle);
+	bridge = acpiphp_dev_to_bridge(adev);
 	if (bridge) {
 		pci_lock_rescan_remove();
 
@@ -872,73 +779,52 @@ void acpiphp_check_host_bridge(acpi_handle handle)
 
 static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 
-static void hotplug_event(acpi_handle handle, u32 type, void *data)
+static void hotplug_event(u32 type, struct acpiphp_context *context)
 {
-	struct acpiphp_context *context = data;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_func *func = &context->func;
+	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge = context->bridge;
 	if (bridge)
 		get_bridge(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	pci_lock_rescan_remove();
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
-		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
-		pr_debug("%s: re-enumerating slots under %s\n",
-			 __func__, objname);
-		if (bridge) {
+		acpi_handle_debug(handle, "Bus check in %s()\n", __func__);
+		if (bridge)
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
-
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
-			mutex_lock(&slot->crit_sect);
+		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
 			enable_slot(slot);
-			mutex_unlock(&slot->crit_sect);
-		}
+
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		/* device check */
-		pr_debug("%s: Device check notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Device check in %s()\n", __func__);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
-			int ret;
-
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
+		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
 			/*
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
 			 */
-			mutex_lock(&slot->crit_sect);
-			ret = acpiphp_rescan_slot(slot);
-			mutex_unlock(&slot->crit_sect);
-			if (ret)
+			if (acpiphp_rescan_slot(slot))
 				acpiphp_check_bridge(func->parent);
 		}
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
-		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
-		acpiphp_disable_and_eject_slot(func->slot);
+		acpi_handle_debug(handle, "Eject request in %s()\n", __func__);
+		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}
 
@@ -947,106 +833,41 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
+static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type)
 {
-	struct acpiphp_context *context = data;
-	acpi_handle handle = context->handle;
-
-	acpi_scan_lock_acquire();
+	struct acpiphp_context *context;
 
-	hotplug_event(handle, type, context);
+	context = acpiphp_grab_context(adev);
+	if (!context)
+		return -ENODATA;
 
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
+	hotplug_event(type, context);
+	acpiphp_let_context_go(context);
+	return 0;
 }
 
 /**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
+ * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus.
+ * @bus: PCI bus to enumerate the slots for.
  *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
-{
-	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->handle != handle)
-	    || context->func.parent->is_going_away)
-		goto err_out;
-
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	status = acpi_hotplug_execute(hotplug_event_work, context, type);
-	if (ACPI_SUCCESS(status)) {
-		mutex_unlock(&acpiphp_context_lock);
-		return;
-	}
-	put_bridge(context->func.parent);
-
- err_out:
-	mutex_unlock(&acpiphp_context_lock);
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-}
-
-/*
- * Create hotplug slots for the PCI bus.
- * It should always return 0 to avoid skipping following notifiers.
+ * A "slot" is an object associated with a PCI device number.  All functions
+ * (PCI devices) with the same bus and device number belong to the same slot.
  */
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;
+	struct acpi_device *adev;
 	acpi_handle handle;
 	acpi_status status;
 
 	if (acpiphp_disabled)
 		return;
 
-	handle = ACPI_HANDLE(bus->bridge);
-	if (!handle)
+	adev = ACPI_COMPANION(bus->bridge);
+	if (!adev)
 		return;
 
+	handle = adev->handle;
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (!bridge) {
 		acpi_handle_err(handle, "No memory for bridge object\n");
@@ -1074,10 +895,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
 		 * parent is going to be handled by pciehp, in which case this
 		 * bridge is not interesting to us either.
 		 */
-		mutex_lock(&acpiphp_context_lock);
-		context = acpiphp_get_context(handle);
+		acpi_lock_hp_context();
+		context = acpiphp_get_context(adev);
 		if (!context) {
-			mutex_unlock(&acpiphp_context_lock);
+			acpi_unlock_hp_context();
 			put_device(&bus->dev);
 			pci_dev_put(bridge->pci_dev);
 			kfree(bridge);
@@ -1087,17 +908,17 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
 		context->bridge = bridge;
 		/* Get a reference to the parent bridge. */
 		get_bridge(context->func.parent);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 	}
 
-	/* must be added to the list prior to calling register_slot */
+	/* Must be added to the list prior to calling acpiphp_add_context(). */
 	mutex_lock(&bridge_mutex);
 	list_add(&bridge->list, &bridge_list);
 	mutex_unlock(&bridge_mutex);
 
 	/* register all slot objects under this bridge */
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-				     register_slot, NULL, bridge, NULL);
+				     acpiphp_add_context, NULL, bridge, NULL);
 	if (ACPI_FAILURE(status)) {
 		acpi_handle_err(handle, "failed to register slots\n");
 		cleanup_bridge(bridge);
@@ -1105,7 +926,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
 	}
 }
 
-/* Destroy hotplug slots associated with the PCI bus */
+/**
+ * acpiphp_remove_slots - Remove slot objects associated with a given bus.
+ * @bus: PCI bus to remove the slot objects for.
+ */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;
@@ -1136,13 +960,10 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
 	/* configure all functions */
 	if (!(slot->flags & SLOT_ENABLED))
 		enable_slot(slot);
 
-	mutex_unlock(&slot->crit_sect);
-
 	pci_unlock_rescan_remove();
 	return 0;
 }
@@ -1158,8 +979,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
-
 	/* unconfigure all functions */
 	disable_slot(slot);
 
@@ -1173,7 +992,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
 			break;
 		}
 
-	mutex_unlock(&slot->crit_sect);
 	return 0;
 }
 
@@ -1181,9 +999,15 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
 {
 	int ret;
 
+	/*
+	 * Acquire acpi_scan_lock to ensure that the execution of _EJ0 in
+	 * acpiphp_disable_and_eject_slot() will be synchronized properly.
+	 */
+	acpi_scan_lock_acquire();
 	pci_lock_rescan_remove();
 	ret = acpiphp_disable_and_eject_slot(slot);
 	pci_unlock_rescan_remove();
+	acpi_scan_lock_release();
 	return ret;
 }
 
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 31273e155e6c..037e2612c5bd 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -920,12 +920,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;
 				break;
 			}
-			if (bus_cap & 20) {
+			if (bus_cap & 0x20) {
 				dbg("bus max supports 66MHz PCI-X\n");
 				bus->max_bus_speed = PCI_SPEED_66MHz_PCIX;
 				break;
 			}
-			if (bus_cap & 10) {
+			if (bus_cap & 0x10) {
 				dbg("bus max supports 66MHz PCI\n");
 				bus->max_bus_speed = PCI_SPEED_66MHz;
 				break;
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 88b37cad4b35..8a66866b8cf1 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -76,6 +76,7 @@ struct slot {
 	struct hotplug_slot *hotplug_slot;
 	struct delayed_work work;	/* work for button event */
 	struct mutex lock;
+	struct mutex hotplug_lock;
 	struct workqueue_struct *wq;
 };
 
@@ -109,6 +110,8 @@ struct controller {
 #define INT_BUTTON_PRESS		7
 #define INT_BUTTON_RELEASE		8
 #define INT_BUTTON_CANCEL		9
+#define INT_LINK_UP			10
+#define INT_LINK_DOWN			11
 
 #define STATIC_STATE			0
 #define BLINKINGON_STATE		1
@@ -132,6 +135,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot);
 u8 pciehp_handle_switch_change(struct slot *p_slot);
 u8 pciehp_handle_presence_change(struct slot *p_slot);
 u8 pciehp_handle_power_fault(struct slot *p_slot);
+void pciehp_handle_linkstate_change(struct slot *p_slot);
 int pciehp_configure_device(struct slot *p_slot);
 int pciehp_unconfigure_device(struct slot *p_slot);
 void pciehp_queue_pushbutton_work(struct work_struct *work);
@@ -153,6 +157,7 @@ void pciehp_green_led_on(struct slot *slot);
 void pciehp_green_led_off(struct slot *slot);
 void pciehp_green_led_blink(struct slot *slot);
 int pciehp_check_link_status(struct controller *ctrl);
+bool pciehp_check_link_active(struct controller *ctrl);
 void pciehp_release_ctrl(struct controller *ctrl);
 int pciehp_reset_slot(struct slot *slot, int probe);
 
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index eddddd447d0d..20fea57d2149 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -112,6 +112,7 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
 static int __init select_detection_mode(void)
 {
 	struct dummy_slot *slot, *tmp;
+
 	if (pcie_port_service_register(&dummy_driver))
 		return PCIEHP_DETECT_ACPI;
 	pcie_port_service_unregister(&dummy_driver);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 53b58debc288..0e0a2fff20a3 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -108,6 +108,7 @@ static int init_slot(struct controller *ctrl)
 	ops = kzalloc(sizeof(*ops), GFP_KERNEL);
 	if (!ops)
 		goto out;
+
 	ops->enable_slot = enable_slot;
 	ops->disable_slot = disable_slot;
 	ops->get_power_status = get_power_status;
@@ -283,8 +284,11 @@ static int pciehp_probe(struct pcie_device *dev)
 	slot = ctrl->slot;
 	pciehp_get_adapter_status(slot, &occupied);
 	pciehp_get_power_status(slot, &poweron);
-	if (occupied && pciehp_force)
+	if (occupied && pciehp_force) {
+		mutex_lock(&slot->hotplug_lock);
 		pciehp_enable_slot(slot);
+		mutex_unlock(&slot->hotplug_lock);
+	}
 	/* If empty slot's power status is on, turn power off */
 	if (!occupied && poweron && POWER_CTRL(ctrl))
 		pciehp_power_off_slot(slot);
@@ -328,10 +332,12 @@ static int pciehp_resume (struct pcie_device *dev)
 
 	/* Check if slot is occupied */
 	pciehp_get_adapter_status(slot, &status);
+	mutex_lock(&slot->hotplug_lock);
 	if (status)
 		pciehp_enable_slot(slot);
 	else
 		pciehp_disable_slot(slot);
+	mutex_unlock(&slot->hotplug_lock);
 	return 0;
 }
 #endif /* PM */
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 50628487597d..c75e6a678dcc 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -150,6 +150,27 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
 	return 1;
 }
 
+void pciehp_handle_linkstate_change(struct slot *p_slot)
+{
+	u32 event_type;
+	struct controller *ctrl = p_slot->ctrl;
+
+	/* Link Status Change */
+	ctrl_dbg(ctrl, "Data Link Layer State change\n");
+
+	if (pciehp_check_link_active(ctrl)) {
+		ctrl_info(ctrl, "slot(%s): Link Up event\n",
+			  slot_name(p_slot));
+		event_type = INT_LINK_UP;
+	} else {
+		ctrl_info(ctrl, "slot(%s): Link Down event\n",
+			  slot_name(p_slot));
+		event_type = INT_LINK_DOWN;
+	}
+
+	queue_interrupt_event(p_slot, event_type);
+}
+
 /* The following routines constitute the bulk of the
    hotplug controller logic
  */
@@ -212,7 +233,8 @@ static int board_added(struct slot *p_slot)
 	if (retval) {
 		ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
 			 pci_domain_nr(parent), parent->number);
-		goto err_exit;
+		if (retval != -EEXIST)
+			goto err_exit;
 	}
 
 	pciehp_green_led_on(p_slot);
@@ -255,6 +277,9 @@ static int remove_board(struct slot *p_slot)
 struct power_work_info {
 	struct slot *p_slot;
 	struct work_struct work;
+	unsigned int req;
+#define DISABLE_REQ 0
+#define ENABLE_REQ  1
 };
 
 /**
@@ -269,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work)
 	struct power_work_info *info =
 		container_of(work, struct power_work_info, work);
 	struct slot *p_slot = info->p_slot;
+	int ret;
 
-	mutex_lock(&p_slot->lock);
-	switch (p_slot->state) {
-	case POWEROFF_STATE:
-		mutex_unlock(&p_slot->lock);
+	switch (info->req) {
+	case DISABLE_REQ:
 		ctrl_dbg(p_slot->ctrl,
 			 "Disabling domain:bus:device=%04x:%02x:00\n",
 			 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
 			 p_slot->ctrl->pcie->port->subordinate->number);
+		mutex_lock(&p_slot->hotplug_lock);
 		pciehp_disable_slot(p_slot);
+		mutex_unlock(&p_slot->hotplug_lock);
 		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
-		break;
-	case POWERON_STATE:
 		mutex_unlock(&p_slot->lock);
-		if (pciehp_enable_slot(p_slot))
+		break;
+	case ENABLE_REQ:
+		ctrl_dbg(p_slot->ctrl,
+			 "Enabling domain:bus:device=%04x:%02x:00\n",
+			 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
+			 p_slot->ctrl->pcie->port->subordinate->number);
+		mutex_lock(&p_slot->hotplug_lock);
+		ret = pciehp_enable_slot(p_slot);
+		mutex_unlock(&p_slot->hotplug_lock);
+		if (ret)
 			pciehp_green_led_off(p_slot);
 		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
+		mutex_unlock(&p_slot->lock);
 		break;
 	default:
 		break;
 	}
-	mutex_unlock(&p_slot->lock);
 
 	kfree(info);
 }
@@ -315,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
 	switch (p_slot->state) {
 	case BLINKINGOFF_STATE:
 		p_slot->state = POWEROFF_STATE;
+		info->req = DISABLE_REQ;
 		break;
 	case BLINKINGON_STATE:
 		p_slot->state = POWERON_STATE;
+		info->req = ENABLE_REQ;
 		break;
 	default:
 		kfree(info);
@@ -364,11 +399,10 @@ static void handle_button_press_event(struct slot *p_slot)
 		 */
 		ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
 		cancel_delayed_work(&p_slot->work);
-		if (p_slot->state == BLINKINGOFF_STATE) {
+		if (p_slot->state == BLINKINGOFF_STATE)
 			pciehp_green_led_on(p_slot);
-		} else {
+		else
 			pciehp_green_led_off(p_slot);
-		}
 		pciehp_set_attention_status(p_slot, 0);
 		ctrl_info(ctrl, "PCI slot #%s - action canceled "
 			  "due to button press\n", slot_name(p_slot));
@@ -407,14 +441,81 @@ static void handle_surprise_event(struct slot *p_slot)
 	INIT_WORK(&info->work, pciehp_power_thread);
 
 	pciehp_get_adapter_status(p_slot, &getstatus);
-	if (!getstatus)
+	if (!getstatus) {
 		p_slot->state = POWEROFF_STATE;
-	else
+		info->req = DISABLE_REQ;
+	} else {
 		p_slot->state = POWERON_STATE;
+		info->req = ENABLE_REQ;
+	}
 
 	queue_work(p_slot->wq, &info->work);
 }
 
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_link_event(struct slot *p_slot, u32 event)
+{
+	struct controller *ctrl = p_slot->ctrl;
+	struct power_work_info *info;
+
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
+			 __func__);
+		return;
+	}
+	info->p_slot = p_slot;
+	info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
+	INIT_WORK(&info->work, pciehp_power_thread);
+
+	switch (p_slot->state) {
+	case BLINKINGON_STATE:
+	case BLINKINGOFF_STATE:
+		cancel_delayed_work(&p_slot->work);
+		/* Fall through */
+	case STATIC_STATE:
+		p_slot->state = event == INT_LINK_UP ?
+		    POWERON_STATE : POWEROFF_STATE;
+		queue_work(p_slot->wq, &info->work);
+		break;
+	case POWERON_STATE:
+		if (event == INT_LINK_UP) {
+			ctrl_info(ctrl,
+				  "Link Up event ignored on slot(%s): already powering on\n",
+				  slot_name(p_slot));
+			kfree(info);
+		} else {
+			ctrl_info(ctrl,
+				  "Link Down event queued on slot(%s): currently getting powered on\n",
+				  slot_name(p_slot));
+			p_slot->state = POWEROFF_STATE;
+			queue_work(p_slot->wq, &info->work);
+		}
+		break;
+	case POWEROFF_STATE:
+		if (event == INT_LINK_UP) {
+			ctrl_info(ctrl,
+				  "Link Up event queued on slot(%s): currently getting powered off\n",
+				  slot_name(p_slot));
+			p_slot->state = POWERON_STATE;
+			queue_work(p_slot->wq, &info->work);
+		} else {
+			ctrl_info(ctrl,
+				  "Link Down event ignored on slot(%s): already powering off\n",
+				  slot_name(p_slot));
+			kfree(info);
+		}
+		break;
+	default:
+		ctrl_err(ctrl, "Not a valid state on slot(%s)\n",
+			 slot_name(p_slot));
+		kfree(info);
+		break;
+	}
+}
+
 static void interrupt_event_handler(struct work_struct *work)
 {
 	struct event_info *info = container_of(work, struct event_info, work);
@@ -433,12 +534,23 @@ static void interrupt_event_handler(struct work_struct *work)
 		pciehp_green_led_off(p_slot);
 		break;
 	case INT_PRESENCE_ON:
-	case INT_PRESENCE_OFF:
 		if (!HP_SUPR_RM(ctrl))
 			break;
+		ctrl_dbg(ctrl, "Surprise Insertion\n");
+		handle_surprise_event(p_slot);
+		break;
+	case INT_PRESENCE_OFF:
+		/*
+		 * Regardless of surprise capability, we need to
+		 * definitely remove a card that has been pulled out!
+		 */
 		ctrl_dbg(ctrl, "Surprise Removal\n");
 		handle_surprise_event(p_slot);
 		break;
+	case INT_LINK_UP:
+	case INT_LINK_DOWN:
+		handle_link_event(p_slot, info->event_type);
+		break;
 	default:
 		break;
 	}
@@ -447,6 +559,9 @@ static void interrupt_event_handler(struct work_struct *work)
 	kfree(info);
 }
 
+/*
+ * Note: This function must be called with slot->hotplug_lock held
+ */
 int pciehp_enable_slot(struct slot *p_slot)
 {
 	u8 getstatus = 0;
@@ -479,13 +594,15 @@ int pciehp_enable_slot(struct slot *p_slot)
 	pciehp_get_latch_status(p_slot, &getstatus);
 
 	rc = board_added(p_slot);
-	if (rc) {
+	if (rc)
 		pciehp_get_latch_status(p_slot, &getstatus);
-	}
+
 	return rc;
 }
 
-
+/*
+ * Note: This function must be called with slot->hotplug_lock held
+ */
 int pciehp_disable_slot(struct slot *p_slot)
 {
 	u8 getstatus = 0;
@@ -494,24 +611,6 @@ int pciehp_disable_slot(struct slot *p_slot)
 	if (!p_slot->ctrl)
 		return 1;
 
-	if (!HP_SUPR_RM(p_slot->ctrl)) {
-		pciehp_get_adapter_status(p_slot, &getstatus);
-		if (!getstatus) {
-			ctrl_info(ctrl, "No adapter on slot(%s)\n",
-				  slot_name(p_slot));
-			return -ENODEV;
-		}
-	}
-
-	if (MRL_SENS(p_slot->ctrl)) {
-		pciehp_get_latch_status(p_slot, &getstatus);
-		if (getstatus) {
-			ctrl_info(ctrl, "Latch open on slot(%s)\n",
-				  slot_name(p_slot));
-			return -ENODEV;
-		}
-	}
-
 	if (POWER_CTRL(p_slot->ctrl)) {
 		pciehp_get_power_status(p_slot, &getstatus);
 		if (!getstatus) {
@@ -536,7 +635,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
 	case STATIC_STATE:
 		p_slot->state = POWERON_STATE;
 		mutex_unlock(&p_slot->lock);
+		mutex_lock(&p_slot->hotplug_lock);
 		retval = pciehp_enable_slot(p_slot);
+		mutex_unlock(&p_slot->hotplug_lock);
 		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
 		break;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 14acfccb7670..d7d058fa19a4 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -206,7 +206,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
 	mutex_unlock(&ctrl->ctrl_lock);
 }
 
-static bool check_link_active(struct controller *ctrl)
+bool pciehp_check_link_active(struct controller *ctrl)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
 	u16 lnk_status;
@@ -225,12 +225,12 @@ static void __pcie_wait_link_active(struct controller *ctrl, bool active)
 {
 	int timeout = 1000;
 
-	if (check_link_active(ctrl) == active)
+	if (pciehp_check_link_active(ctrl) == active)
 		return;
 	while (timeout > 0) {
 		msleep(10);
 		timeout -= 10;
-		if (check_link_active(ctrl) == active)
+		if (pciehp_check_link_active(ctrl) == active)
 			return;
 	}
 	ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n",
@@ -242,11 +242,6 @@ static void pcie_wait_link_active(struct controller *ctrl)
 	__pcie_wait_link_active(ctrl, true);
 }
 
-static void pcie_wait_link_not_active(struct controller *ctrl)
-{
-	__pcie_wait_link_active(ctrl, false);
-}
-
 static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
 {
 	u32 l;
@@ -332,11 +327,6 @@ static int pciehp_link_enable(struct controller *ctrl)
 	return __pciehp_link_set(ctrl, true);
 }
 
-static int pciehp_link_disable(struct controller *ctrl)
-{
-	return __pciehp_link_set(ctrl, false);
-}
-
 void pciehp_get_attention_status(struct slot *slot, u8 *status)
 {
 	struct controller *ctrl = slot->ctrl;
@@ -508,14 +498,6 @@ void pciehp_power_off_slot(struct slot * slot)
 {
 	struct controller *ctrl = slot->ctrl;
 
-	/* Disable the link at first */
-	pciehp_link_disable(ctrl);
-	/* wait the link is down */
-	if (ctrl->link_active_reporting)
-		pcie_wait_link_not_active(ctrl);
-	else
-		msleep(1000);
-
 	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);
 	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
 		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
@@ -540,7 +522,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 
 		detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
 			     PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
-			     PCI_EXP_SLTSTA_CC);
+			     PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
 		detected &= ~intr_loc;
 		intr_loc |= detected;
 		if (!intr_loc)
@@ -579,6 +561,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 		ctrl->power_fault_detected = 1;
 		pciehp_handle_power_fault(slot);
 	}
+
+	if (intr_loc & PCI_EXP_SLTSTA_DLLSC)
+		pciehp_handle_linkstate_change(slot);
+
 	return IRQ_HANDLED;
 }
 
@@ -596,9 +582,17 @@ void pcie_enable_notification(struct controller *ctrl)
 	 * when it is cleared in the interrupt service routine, and
 	 * next power fault detected interrupt was notified again.
 	 */
-	cmd = PCI_EXP_SLTCTL_PDCE;
+
+	/*
+	 * Always enable link events: thus link-up and link-down shall
+	 * always be treated as hotplug and unplug respectively. Enable
+	 * presence detect only if Attention Button is not present.
+	 */
+	cmd = PCI_EXP_SLTCTL_DLLSCE;
 	if (ATTN_BUTTN(ctrl))
 		cmd |= PCI_EXP_SLTCTL_ABPE;
+	else
+		cmd |= PCI_EXP_SLTCTL_PDCE;
 	if (MRL_SENS(ctrl))
 		cmd |= PCI_EXP_SLTCTL_MRLSCE;
 	if (!pciehp_poll_mode)
@@ -606,7 +600,8 @@ void pcie_enable_notification(struct controller *ctrl)
 
 	mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
 		PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
-		PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
+		PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
+		PCI_EXP_SLTCTL_DLLSCE);
 
 	pcie_write_cmd(ctrl, cmd, mask);
 }
@@ -624,33 +619,38 @@ static void pcie_disable_notification(struct controller *ctrl)
 
 /*
  * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
- * bus reset of the bridge, but if the slot supports surprise removal we need
- * to disable presence detection around the bus reset and clear any spurious
+ * bus reset of the bridge, but at the same time we want to ensure that it is
+ * not seen as a hot-unplug, followed by the hot-plug of the device. Thus,
+ * disable link state notification and presence detection change notification
+ * momentarily, if we see that they could interfere. Also, clear any spurious
  * events after.
  */
 int pciehp_reset_slot(struct slot *slot, int probe)
 {
 	struct controller *ctrl = slot->ctrl;
 	struct pci_dev *pdev = ctrl_dev(ctrl);
+	u16 stat_mask = 0, ctrl_mask = 0;
 
 	if (probe)
 		return 0;
 
-	if (HP_SUPR_RM(ctrl)) {
-		pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE);
-		if (pciehp_poll_mode)
-			del_timer_sync(&ctrl->poll_timer);
+	if (!ATTN_BUTTN(ctrl)) {
+		ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
+		stat_mask |= PCI_EXP_SLTSTA_PDC;
 	}
+	ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE;
+	stat_mask |= PCI_EXP_SLTSTA_DLLSC;
+
+	pcie_write_cmd(ctrl, 0, ctrl_mask);
+	if (pciehp_poll_mode)
+		del_timer_sync(&ctrl->poll_timer);
 
 	pci_reset_bridge_secondary_bus(ctrl->pcie->port);
 
-	if (HP_SUPR_RM(ctrl)) {
-		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
-					   PCI_EXP_SLTSTA_PDC);
-		pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
-		if (pciehp_poll_mode)
-			int_poll_timeout(ctrl->poll_timer.data);
-	}
+	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
+	pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
+	if (pciehp_poll_mode)
+		int_poll_timeout(ctrl->poll_timer.data);
 
 	return 0;
 }
@@ -687,6 +687,7 @@ static int pcie_init_slot(struct controller *ctrl)
 
 	slot->ctrl = ctrl;
 	mutex_init(&slot->lock);
+	mutex_init(&slot->hotplug_lock);
 	INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
 	ctrl->slot = slot;
 	return 0;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index b07d7cc2d697..1b533060ce65 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -50,7 +50,7 @@ int pciehp_configure_device(struct slot *p_slot)
 			 "at %04x:%02x:00, cannot hot-add\n", pci_name(dev),
 			 pci_domain_nr(parent), parent->number);
 		pci_dev_put(dev);
-		ret = -EINVAL;
+		ret = -EEXIST;
 		goto out;
 	}
 
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 9dce7c5e2a77..de7a74782f92 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -170,97 +170,6 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
 	pci_dev_put(dev);
 }
 
-static int sriov_migration(struct pci_dev *dev)
-{
-	u16 status;
-	struct pci_sriov *iov = dev->sriov;
-
-	if (!iov->num_VFs)
-		return 0;
-
-	if (!(iov->cap & PCI_SRIOV_CAP_VFM))
-		return 0;
-
-	pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status);
-	if (!(status & PCI_SRIOV_STATUS_VFM))
-		return 0;
-
-	schedule_work(&iov->mtask);
-
-	return 1;
-}
-
-static void sriov_migration_task(struct work_struct *work)
-{
-	int i;
-	u8 state;
-	u16 status;
-	struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
-
-	for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
-		state = readb(iov->mstate + i);
-		if (state == PCI_SRIOV_VFM_MI) {
-			writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
-			state = readb(iov->mstate + i);
-			if (state == PCI_SRIOV_VFM_AV)
-				virtfn_add(iov->self, i, 1);
-		} else if (state == PCI_SRIOV_VFM_MO) {
-			virtfn_remove(iov->self, i, 1);
-			writeb(PCI_SRIOV_VFM_UA, iov->mstate + i);
-			state = readb(iov->mstate + i);
-			if (state == PCI_SRIOV_VFM_AV)
-				virtfn_add(iov->self, i, 0);
-		}
-	}
-
-	pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status);
-	status &= ~PCI_SRIOV_STATUS_VFM;
-	pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status);
-}
-
-static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
-{
-	int bir;
-	u32 table;
-	resource_size_t pa;
-	struct pci_sriov *iov = dev->sriov;
-
-	if (nr_virtfn <= iov->initial_VFs)
-		return 0;
-
-	pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
-	bir = PCI_SRIOV_VFM_BIR(table);
-	if (bir > PCI_STD_RESOURCE_END)
-		return -EIO;
-
-	table = PCI_SRIOV_VFM_OFFSET(table);
-	if (table + nr_virtfn > pci_resource_len(dev, bir))
-		return -EIO;
-
-	pa = pci_resource_start(dev, bir) + table;
-	iov->mstate = ioremap(pa, nr_virtfn);
-	if (!iov->mstate)
-		return -ENOMEM;
-
-	INIT_WORK(&iov->mtask, sriov_migration_task);
-
-	iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR;
-	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-
-	return 0;
-}
-
-static void sriov_disable_migration(struct pci_dev *dev)
-{
-	struct pci_sriov *iov = dev->sriov;
-
-	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR);
-	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-
-	cancel_work_sync(&iov->mtask);
-	iounmap(iov->mstate);
-}
-
 static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 {
 	int rc;
@@ -351,12 +260,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 			goto failed;
 	}
 
-	if (iov->cap & PCI_SRIOV_CAP_VFM) {
-		rc = sriov_enable_migration(dev, nr_virtfn);
-		if (rc)
-			goto failed;
-	}
-
 	kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
 	iov->num_VFs = nr_virtfn;
 
@@ -387,9 +290,6 @@ static void sriov_disable(struct pci_dev *dev)
 	if (!iov->num_VFs)
 		return;
 
-	if (iov->cap & PCI_SRIOV_CAP_VFM)
-		sriov_disable_migration(dev);
-
 	for (i = 0; i < iov->num_VFs; i++)
 		virtfn_remove(dev, i, 0);
 
@@ -688,25 +588,6 @@ void pci_disable_sriov(struct pci_dev *dev)
 EXPORT_SYMBOL_GPL(pci_disable_sriov);
 
 /**
- * pci_sriov_migration - notify SR-IOV core of Virtual Function Migration
- * @dev: the PCI device
- *
- * Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not.
- *
- * Physical Function driver is responsible to register IRQ handler using
- * VF Migration Interrupt Message Number, and call this function when the
- * interrupt is generated by the hardware.
- */
-irqreturn_t pci_sriov_migration(struct pci_dev *dev)
-{
-	if (!dev->is_physfn)
-		return IRQ_NONE;
-
-	return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE;
-}
-EXPORT_SYMBOL_GPL(pci_sriov_migration);
-
-/**
  * pci_num_vf - return number of VFs associated with a PF device_release_driver
  * @dev: the PCI device
  *
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 276ef9c18802..4e0acefb7565 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -351,28 +351,17 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan,
 							(S_IWUSR|S_IWGRP),
 							NULL, dev_rescan_store);
 
-static void remove_callback(struct device *dev)
-{
-	pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
-}
-
 static ssize_t
-remove_store(struct device *dev, struct device_attribute *dummy,
+remove_store(struct device *dev, struct device_attribute *attr,
 	     const char *buf, size_t count)
 {
-	int ret = 0;
 	unsigned long val;
 
 	if (kstrtoul(buf, 0, &val) < 0)
 		return -EINVAL;
 
-	/* An attribute cannot be unregistered by one of its own methods,
-	 * so we have to use this roundabout approach.
-	 */
-	if (val)
-		ret = device_schedule_callback(dev, remove_callback);
-	if (ret)
-		count = ret;
+	if (val && device_remove_file_self(dev, attr))
+		pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
 	return count;
 }
 static struct device_attribute dev_remove_attr = __ATTR(remove,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6b05f6134b68..b6ddde1d04ca 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -108,12 +108,12 @@ static bool pcie_ari_disabled;
  */
 unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 {
-	struct list_head *tmp;
+	struct pci_bus *tmp;
 	unsigned char max, n;
 
 	max = bus->busn_res.end;
-	list_for_each(tmp, &bus->children) {
-		n = pci_bus_max_busnr(pci_bus_b(tmp));
+	list_for_each_entry(tmp, &bus->children, node) {
+		n = pci_bus_max_busnr(tmp);
 		if(n > max)
 			max = n;
 	}
@@ -1621,29 +1621,27 @@ static void pci_pme_list_scan(struct work_struct *work)
 	struct pci_pme_device *pme_dev, *n;
 
 	mutex_lock(&pci_pme_list_mutex);
-	if (!list_empty(&pci_pme_list)) {
-		list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
-			if (pme_dev->dev->pme_poll) {
-				struct pci_dev *bridge;
-
-				bridge = pme_dev->dev->bus->self;
-				/*
-				 * If bridge is in low power state, the
-				 * configuration space of subordinate devices
-				 * may be not accessible
-				 */
-				if (bridge && bridge->current_state != PCI_D0)
-					continue;
-				pci_pme_wakeup(pme_dev->dev, NULL);
-			} else {
-				list_del(&pme_dev->list);
-				kfree(pme_dev);
-			}
+	list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
+		if (pme_dev->dev->pme_poll) {
+			struct pci_dev *bridge;
+
+			bridge = pme_dev->dev->bus->self;
+			/*
+			 * If bridge is in low power state, the
+			 * configuration space of subordinate devices
+			 * may be not accessible
+			 */
+			if (bridge && bridge->current_state != PCI_D0)
+				continue;
+			pci_pme_wakeup(pme_dev->dev, NULL);
+		} else {
+			list_del(&pme_dev->list);
+			kfree(pme_dev);
 		}
-		if (!list_empty(&pci_pme_list))
-			schedule_delayed_work(&pci_pme_work,
-					      msecs_to_jiffies(PME_TIMEOUT));
 	}
+	if (!list_empty(&pci_pme_list))
+		schedule_delayed_work(&pci_pme_work,
+				      msecs_to_jiffies(PME_TIMEOUT));
 	mutex_unlock(&pci_pme_list_mutex);
 }
 
@@ -2190,21 +2188,18 @@ void pci_request_acs(void)
 }
 
 /**
- * pci_enable_acs - enable ACS if hardware support it
+ * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
  * @dev: the PCI device
  */
-void pci_enable_acs(struct pci_dev *dev)
+static int pci_std_enable_acs(struct pci_dev *dev)
 {
 	int pos;
 	u16 cap;
 	u16 ctrl;
 
-	if (!pci_acs_enable)
-		return;
-
 	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
 	if (!pos)
-		return;
+		return -ENODEV;
 
 	pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
 	pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
@@ -2222,6 +2217,23 @@ void pci_enable_acs(struct pci_dev *dev)
 	ctrl |= (cap & PCI_ACS_UF);
 
 	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+
+	return 0;
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_acs(struct pci_dev *dev)
+{
+	if (!pci_acs_enable)
+		return;
+
+	if (!pci_std_enable_acs(dev))
+		return;
+
+	pci_dev_specific_enable_acs(dev);
 }
 
 static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4df38df224f4..6bd082299e31 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,8 +1,6 @@
 #ifndef DRIVERS_PCI_H
 #define DRIVERS_PCI_H
 
-#include <linux/workqueue.h>
-
 #define PCI_CFG_SPACE_SIZE	256
 #define PCI_CFG_SPACE_EXP_SIZE	4096
 
@@ -240,8 +238,6 @@ struct pci_sriov {
 	struct pci_dev *dev;	/* lowest numbered PF */
 	struct pci_dev *self;	/* this PF */
 	struct mutex lock;	/* lock for VF bus */
-	struct work_struct mtask; /* VF Migration task */
-	u8 __iomem *mstate;	/* VF Migration State Array */
 };
 
 #ifdef CONFIG_PCI_ATS
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6e34498ec9f0..509494381a7a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -731,22 +731,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
 	return child;
 }
 
-static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
-{
-	struct pci_bus *parent = child->parent;
-
-	/* Attempts to fix that up are really dangerous unless
-	   we're going to re-assign all bus numbers. */
-	if (!pcibios_assign_all_busses())
-		return;
-
-	while (parent->parent && parent->busn_res.end < max) {
-		parent->busn_res.end = max;
-		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
-		parent = parent->parent;
-	}
-}
-
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -782,7 +766,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 	/* Check if setup is sensible at all */
 	if (!pass &&
 	    (primary != bus->number || secondary <= bus->number ||
-	     secondary > subordinate)) {
+	     secondary > subordinate || subordinate > bus->busn_res.end)) {
 		dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
 			 secondary, subordinate);
 		broken = 1;
@@ -805,11 +789,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 			goto out;
 
 		/*
-		 * If we already got to this bus through a different bridge,
-		 * don't re-add it. This can happen with the i450NX chipset.
-		 *
-		 * However, we continue to descend down the hierarchy and
-		 * scan remaining child buses.
+		 * The bus might already exist for two reasons: Either we are
+		 * rescanning the bus or the bus is reachable through more than
+		 * one bridge. The second case can happen with the i450NX
+		 * chipset.
 		 */
 		child = pci_find_bus(pci_domain_nr(bus), secondary);
 		if (!child) {
@@ -822,17 +805,19 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 		}
 
 		cmax = pci_scan_child_bus(child);
-		if (cmax > max)
-			max = cmax;
-		if (child->busn_res.end > max)
-			max = child->busn_res.end;
+		if (cmax > subordinate)
+			dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
+				 subordinate, cmax);
+		/* subordinate should equal child->busn_res.end */
+		if (subordinate > max)
+			max = subordinate;
 	} else {
 		/*
 		 * We need to assign a number to this bus which we always
 		 * do in the second pass.
 		 */
 		if (!pass) {
-			if (pcibios_assign_all_busses() || broken)
+			if (pcibios_assign_all_busses() || broken || is_cardbus)
 				/* Temporarily disable forwarding of the
 				   configuration cycles on all bridges in
 				   this bus segment to avoid possible
@@ -844,19 +829,25 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 			goto out;
 		}
 
+		if (max >= bus->busn_res.end) {
+			dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
+				 max, &bus->busn_res);
+			goto out;
+		}
+
 		/* Clear errors */
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-		/* Prevent assigning a bus number that already exists.
-		 * This can happen when a bridge is hot-plugged, so in
-		 * this case we only re-scan this bus. */
+		/* The bus will already exist if we are rescanning */
 		child = pci_find_bus(pci_domain_nr(bus), max+1);
 		if (!child) {
-			child = pci_add_new_bus(bus, dev, ++max);
+			child = pci_add_new_bus(bus, dev, max+1);
 			if (!child)
 				goto out;
-			pci_bus_insert_busn_res(child, max, 0xff);
+			pci_bus_insert_busn_res(child, max+1,
+						bus->busn_res.end);
 		}
+		max++;
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->busn_res.start)   <<  8)
@@ -878,20 +869,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
 		if (!is_cardbus) {
 			child->bridge_ctl = bctl;
-			/*
-			 * Adjust subordinate busnr in parent buses.
-			 * We do this before scanning for children because
-			 * some devices may not be detected if the bios
-			 * was lazy.
-			 */
-			pci_fixup_parent_subordinate_busnr(child, max);
-			/* Now we can scan all subordinate buses... */
 			max = pci_scan_child_bus(child);
-			/*
-			 * now fix it up again since we have found
-			 * the real value of max.
-			 */
-			pci_fixup_parent_subordinate_busnr(child, max);
 		} else {
 			/*
 			 * For CardBus bridges, we leave 4 bus numbers
@@ -922,11 +900,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 				}
 			}
 			max += i;
-			pci_fixup_parent_subordinate_busnr(child, max);
 		}
 		/*
 		 * Set the subordinate bus number to its real value.
 		 */
+		if (max > bus->busn_res.end) {
+			dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
+				 max, &bus->busn_res);
+			max = bus->busn_res.end;
+		}
 		pci_bus_update_busn_res_end(child, max);
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 	}
@@ -1835,7 +1817,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 		res->flags |= IORESOURCE_PCI_FIXED;
 	}
 
-	conflict = insert_resource_conflict(parent_res, res);
+	conflict = request_resource_conflict(parent_res, res);
 
 	if (conflict)
 		dev_printk(KERN_DEBUG, &b->dev,
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 5cb726c193de..ed2ed867c34c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3423,6 +3423,61 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
 #endif
 }
 
+/*
+ * Many Intel PCH root ports do provide ACS-like features to disable peer
+ * transactions and validate bus numbers in requests, but do not provide an
+ * actual PCIe ACS capability.  This is the list of device IDs known to fall
+ * into that category as provided by Intel in Red Hat bugzilla 1037684.
+ */
+static const u16 pci_quirk_intel_pch_acs_ids[] = {
+	/* Ibexpeak PCH */
+	0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49,
+	0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51,
+	/* Cougarpoint PCH */
+	0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17,
+	0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f,
+	/* Pantherpoint PCH */
+	0x1e10, 0x1e11, 0x1e12, 0x1e13, 0x1e14, 0x1e15, 0x1e16, 0x1e17,
+	0x1e18, 0x1e19, 0x1e1a, 0x1e1b, 0x1e1c, 0x1e1d, 0x1e1e, 0x1e1f,
+	/* Lynxpoint-H PCH */
+	0x8c10, 0x8c11, 0x8c12, 0x8c13, 0x8c14, 0x8c15, 0x8c16, 0x8c17,
+	0x8c18, 0x8c19, 0x8c1a, 0x8c1b, 0x8c1c, 0x8c1d, 0x8c1e, 0x8c1f,
+	/* Lynxpoint-LP PCH */
+	0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17,
+	0x9c18, 0x9c19, 0x9c1a, 0x9c1b,
+	/* Wildcat PCH */
+	0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97,
+	0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
+};
+
+static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
+{
+	int i;
+
+	/* Filter out a few obvious non-matches first */
+	if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+		return false;
+
+	for (i = 0; i < ARRAY_SIZE(pci_quirk_intel_pch_acs_ids); i++)
+		if (pci_quirk_intel_pch_acs_ids[i] == dev->device)
+			return true;
+
+	return false;
+}
+
+#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
+
+static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
+{
+	u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
+		    INTEL_PCH_ACS_FLAGS : 0;
+
+	if (!pci_quirk_intel_pch_acs_match(dev))
+		return -ENOTTY;
+
+	return acs_flags & ~flags ? 0 : 1;
+}
+
 static const struct pci_dev_acs_enabled {
 	u16 vendor;
 	u16 device;
@@ -3434,6 +3489,7 @@ static const struct pci_dev_acs_enabled {
 	{ PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
 	{ PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
 	{ PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
 	{ 0 }
 };
 
@@ -3461,3 +3517,132 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
 
 	return -ENOTTY;
 }
+
+/* Config space offset of Root Complex Base Address register */
+#define INTEL_LPC_RCBA_REG 0xf0
+/* 31:14 RCBA address */
+#define INTEL_LPC_RCBA_MASK 0xffffc000
+/* RCBA Enable */
+#define INTEL_LPC_RCBA_ENABLE (1 << 0)
+
+/* Backbone Scratch Pad Register */
+#define INTEL_BSPR_REG 0x1104
+/* Backbone Peer Non-Posted Disable */
+#define INTEL_BSPR_REG_BPNPD (1 << 8)
+/* Backbone Peer Posted Disable */
+#define INTEL_BSPR_REG_BPPD  (1 << 9)
+
+/* Upstream Peer Decode Configuration Register */
+#define INTEL_UPDCR_REG 0x1114
+/* 5:0 Peer Decode Enable bits */
+#define INTEL_UPDCR_REG_MASK 0x3f
+
+static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev)
+{
+	u32 rcba, bspr, updcr;
+	void __iomem *rcba_mem;
+
+	/*
+	 * Read the RCBA register from the LPC (D31:F0).  PCH root ports
+	 * are D28:F* and therefore get probed before LPC, thus we can't
+	 * use pci_get_slot/pci_read_config_dword here.
+	 */
+	pci_bus_read_config_dword(dev->bus, PCI_DEVFN(31, 0),
+				  INTEL_LPC_RCBA_REG, &rcba);
+	if (!(rcba & INTEL_LPC_RCBA_ENABLE))
+		return -EINVAL;
+
+	rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK,
+				   PAGE_ALIGN(INTEL_UPDCR_REG));
+	if (!rcba_mem)
+		return -ENOMEM;
+
+	/*
+	 * The BSPR can disallow peer cycles, but it's set by soft strap and
+	 * therefore read-only.  If both posted and non-posted peer cycles are
+	 * disallowed, we're ok.  If either are allowed, then we need to use
+	 * the UPDCR to disable peer decodes for each port.  This provides the
+	 * PCIe ACS equivalent of PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF
+	 */
+	bspr = readl(rcba_mem + INTEL_BSPR_REG);
+	bspr &= INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD;
+	if (bspr != (INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD)) {
+		updcr = readl(rcba_mem + INTEL_UPDCR_REG);
+		if (updcr & INTEL_UPDCR_REG_MASK) {
+			dev_info(&dev->dev, "Disabling UPDCR peer decodes\n");
+			updcr &= ~INTEL_UPDCR_REG_MASK;
+			writel(updcr, rcba_mem + INTEL_UPDCR_REG);
+		}
+	}
+
+	iounmap(rcba_mem);
+	return 0;
+}
+
+/* Miscellaneous Port Configuration register */
+#define INTEL_MPC_REG 0xd8
+/* MPC: Invalid Receive Bus Number Check Enable */
+#define INTEL_MPC_REG_IRBNCE (1 << 26)
+
+static void pci_quirk_enable_intel_rp_mpc_acs(struct pci_dev *dev)
+{
+	u32 mpc;
+
+	/*
+	 * When enabled, the IRBNCE bit of the MPC register enables the
+	 * equivalent of PCI ACS Source Validation (PCI_ACS_SV), which
+	 * ensures that requester IDs fall within the bus number range
+	 * of the bridge.  Enable if not already.
+	 */
+	pci_read_config_dword(dev, INTEL_MPC_REG, &mpc);
+	if (!(mpc & INTEL_MPC_REG_IRBNCE)) {
+		dev_info(&dev->dev, "Enabling MPC IRBNCE\n");
+		mpc |= INTEL_MPC_REG_IRBNCE;
+		pci_write_config_word(dev, INTEL_MPC_REG, mpc);
+	}
+}
+
+static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
+{
+	if (!pci_quirk_intel_pch_acs_match(dev))
+		return -ENOTTY;
+
+	if (pci_quirk_enable_intel_lpc_acs(dev)) {
+		dev_warn(&dev->dev, "Failed to enable Intel PCH ACS quirk\n");
+		return 0;
+	}
+
+	pci_quirk_enable_intel_rp_mpc_acs(dev);
+
+	dev->dev_flags |= PCI_DEV_FLAGS_ACS_ENABLED_QUIRK;
+
+	dev_info(&dev->dev, "Intel PCH root port ACS workaround enabled\n");
+
+	return 0;
+}
+
+static const struct pci_dev_enable_acs {
+	u16 vendor;
+	u16 device;
+	int (*enable_acs)(struct pci_dev *dev);
+} pci_dev_enable_acs[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
+	{ 0 }
+};
+
+void pci_dev_specific_enable_acs(struct pci_dev *dev)
+{
+	const struct pci_dev_enable_acs *i;
+	int ret;
+
+	for (i = pci_dev_enable_acs; i->enable_acs; i++) {
+		if ((i->vendor == dev->vendor ||
+		     i->vendor == (u16)PCI_ANY_ID) &&
+		    (i->device == dev->device ||
+		     i->device == (u16)PCI_ANY_ID)) {
+			ret = i->enable_acs(dev);
+			if (ret >= 0)
+				return;
+		}
+	}
+}
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 3ff2ac7c14e2..4a1b972efe7f 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -54,14 +54,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
 
 static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
 {
-	struct pci_bus* child;
-	struct list_head *tmp;
+	struct pci_bus *child;
+	struct pci_bus *tmp;
 
 	if(bus->number == busnr)
 		return bus;
 
-	list_for_each(tmp, &bus->children) {
-		child = pci_do_find_bus(pci_bus_b(tmp), busnr);
+	list_for_each_entry(tmp, &bus->children, node) {
+		child = pci_do_find_bus(tmp, busnr);
 		if(child)
 			return child;
 	}
@@ -111,7 +111,7 @@ pci_find_next_bus(const struct pci_bus *from)
 	down_read(&pci_bus_sem);
 	n = from ? from->node.next : pci_root_buses.next;
 	if (n != &pci_root_buses)
-		b = pci_bus_b(n);
+		b = list_entry(n, struct pci_bus, node);
 	up_read(&pci_bus_sem);
 	return b;
 }
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 8485761e76af..946f90ef6020 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1076,7 +1076,7 @@ static void yenta_config_init(struct yenta_socket *socket)
  */
 static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 {
-	struct list_head *tmp;
+	struct pci_bus *sibling;
 	unsigned char upper_limit;
 	/*
 	 * We only check and fix the parent bridge: All systems which need
@@ -1095,18 +1095,18 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 	/* stay within the limits of the bus range of the parent: */
 	upper_limit = bridge_to_fix->parent->busn_res.end;
 
-	/* check the bus ranges of all silbling bridges to prevent overlap */
-	list_for_each(tmp, &bridge_to_fix->parent->children) {
-		struct pci_bus *silbling = pci_bus_b(tmp);
+	/* check the bus ranges of all sibling bridges to prevent overlap */
+	list_for_each_entry(sibling, &bridge_to_fix->parent->children,
+			node) {
 		/*
-		 * If the silbling has a higher secondary bus number
+		 * If the sibling has a higher secondary bus number
 		 * and it's secondary is equal or smaller than our
 		 * current upper limit, set the new upper limit to
-		 * the bus number below the silbling's range:
+		 * the bus number below the sibling's range:
 		 */
-		if (silbling->busn_res.start > bridge_to_fix->busn_res.end
-		    && silbling->busn_res.start <= upper_limit)
-			upper_limit = silbling->busn_res.start - 1;
+		if (sibling->busn_res.start > bridge_to_fix->busn_res.end
+		    && sibling->busn_res.start <= upper_limit)
+			upper_limit = sibling->busn_res.start - 1;
 	}
 
 	/* Show that the wanted subordinate number is not possible: */
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index c7a551c2d5f1..05711ea4fd15 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -24,7 +24,7 @@ config PHY_EXYNOS_MIPI_VIDEO
 
 config PHY_MVEBU_SATA
 	def_bool y
-	depends on ARCH_KIRKWOOD || ARCH_DOVE
+	depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_KIRKWOOD
 	depends on OF
 	select GENERIC_PHY
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index be361b7cd30f..1e4e69384baa 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -217,7 +217,7 @@ config PINCTRL_IMX28
 	select PINCTRL_MXS
 
 config PINCTRL_MSM
-	tristate
+	bool
 	select PINMUX
 	select PINCONF
 	select GENERIC_PINCONF
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 340fb4e6c600..eda13de2e7c0 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -186,7 +186,9 @@ int pinctrl_dt_to_map(struct pinctrl *p)
 
 	/* CONFIG_OF enabled, p->dev not instantiated from DT */
 	if (!np) {
-		dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
+		if (of_have_populated_dt())
+			dev_dbg(p->dev,
+				"no of_node; not parsing pinctrl DT\n");
 		return 0;
 	}
 
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
index 366fa541ee91..cc298fade93a 100644
--- a/drivers/pinctrl/mvebu/Kconfig
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -8,6 +8,7 @@ config PINCTRL_MVEBU
 config PINCTRL_DOVE
 	bool
 	select PINCTRL_MVEBU
+	select MFD_SYSCON
 
 config PINCTRL_KIRKWOOD
 	bool
@@ -17,6 +18,14 @@ config PINCTRL_ARMADA_370
 	bool
 	select PINCTRL_MVEBU
 
+config PINCTRL_ARMADA_375
+	bool
+	select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_38X
+	bool
+	select PINCTRL_MVEBU
+
 config PINCTRL_ARMADA_XP
 	bool
 	select PINCTRL_MVEBU
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
index 37c253297af0..bc1b9f14f539 100644
--- a/drivers/pinctrl/mvebu/Makefile
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -2,4 +2,6 @@ obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
 obj-$(CONFIG_PINCTRL_DOVE)	+= pinctrl-dove.o
 obj-$(CONFIG_PINCTRL_KIRKWOOD)	+= pinctrl-kirkwood.o
 obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_375) += pinctrl-armada-375.o
+obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o
 obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index ae1f760cbdd2..670e5b01c678 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -23,6 +23,18 @@
 
 #include "pinctrl-mvebu.h"
 
+static void __iomem *mpp_base;
+
+static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
 static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
 	MPP_MODE(0,
 	   MPP_FUNCTION(0x0, "gpio", NULL),
@@ -373,7 +385,7 @@ static struct of_device_id armada_370_pinctrl_of_match[] = {
 };
 
 static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
-	MPP_REG_CTRL(0, 65),
+	MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
@@ -385,6 +397,12 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
 static int armada_370_pinctrl_probe(struct platform_device *pdev)
 {
 	struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
 
 	soc->variant = 0; /* no variants for Armada 370 */
 	soc->controls = mv88f6710_mpp_controls;
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-375.c b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
new file mode 100644
index 000000000000..db078fe7ace6
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
@@ -0,0 +1,459 @@
+/*
+ * Marvell Armada 375 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static void __iomem *mpp_base;
+
+static int armada_375_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_375_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+static struct mvebu_mpp_mode mv88f6720_mpp_modes[] = {
+	MPP_MODE(0,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad2"),
+		 MPP_FUNCTION(0x2, "spi0", "cs1"),
+		 MPP_FUNCTION(0x3, "spi1", "cs1"),
+		 MPP_FUNCTION(0x5, "nand", "io2")),
+	MPP_MODE(1,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad3"),
+		 MPP_FUNCTION(0x2, "spi0", "mosi"),
+		 MPP_FUNCTION(0x3, "spi1", "mosi"),
+		 MPP_FUNCTION(0x5, "nand", "io3")),
+	MPP_MODE(2,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad4"),
+		 MPP_FUNCTION(0x2, "ptp", "eventreq"),
+		 MPP_FUNCTION(0x3, "led", "c0"),
+		 MPP_FUNCTION(0x4, "audio", "sdi"),
+		 MPP_FUNCTION(0x5, "nand", "io4"),
+		 MPP_FUNCTION(0x6, "spi1", "mosi")),
+	MPP_MODE(3,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad5"),
+		 MPP_FUNCTION(0x2, "ptp", "triggen"),
+		 MPP_FUNCTION(0x3, "led", "p3"),
+		 MPP_FUNCTION(0x4, "audio", "mclk"),
+		 MPP_FUNCTION(0x5, "nand", "io5"),
+		 MPP_FUNCTION(0x6, "spi1", "miso")),
+	MPP_MODE(4,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad6"),
+		 MPP_FUNCTION(0x2, "spi0", "miso"),
+		 MPP_FUNCTION(0x3, "spi1", "miso"),
+		 MPP_FUNCTION(0x5, "nand", "io6")),
+	MPP_MODE(5,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad7"),
+		 MPP_FUNCTION(0x2, "spi0", "cs2"),
+		 MPP_FUNCTION(0x3, "spi1", "cs2"),
+		 MPP_FUNCTION(0x5, "nand", "io7"),
+		 MPP_FUNCTION(0x6, "spi1", "miso")),
+	MPP_MODE(6,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad0"),
+		 MPP_FUNCTION(0x3, "led", "p1"),
+		 MPP_FUNCTION(0x4, "audio", "rclk"),
+		 MPP_FUNCTION(0x5, "nand", "io0")),
+	MPP_MODE(7,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "ad1"),
+		 MPP_FUNCTION(0x2, "ptp", "clk"),
+		 MPP_FUNCTION(0x3, "led", "p2"),
+		 MPP_FUNCTION(0x4, "audio", "extclk"),
+		 MPP_FUNCTION(0x5, "nand", "io1")),
+	MPP_MODE(8,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev ", "bootcs"),
+		 MPP_FUNCTION(0x2, "spi0", "cs0"),
+		 MPP_FUNCTION(0x3, "spi1", "cs0"),
+		 MPP_FUNCTION(0x5, "nand", "ce")),
+	MPP_MODE(9,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "nf", "wen"),
+		 MPP_FUNCTION(0x2, "spi0", "sck"),
+		 MPP_FUNCTION(0x3, "spi1", "sck"),
+		 MPP_FUNCTION(0x5, "nand", "we")),
+	MPP_MODE(10,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "nf", "ren"),
+		 MPP_FUNCTION(0x2, "dram", "vttctrl"),
+		 MPP_FUNCTION(0x3, "led", "c1"),
+		 MPP_FUNCTION(0x5, "nand", "re"),
+		 MPP_FUNCTION(0x6, "spi1", "sck")),
+	MPP_MODE(11,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "a0"),
+		 MPP_FUNCTION(0x3, "led", "c2"),
+		 MPP_FUNCTION(0x4, "audio", "sdo"),
+		 MPP_FUNCTION(0x5, "nand", "cle")),
+	MPP_MODE(12,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "a1"),
+		 MPP_FUNCTION(0x4, "audio", "bclk"),
+		 MPP_FUNCTION(0x5, "nand", "ale")),
+	MPP_MODE(13,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "dev", "readyn"),
+		 MPP_FUNCTION(0x2, "pcie0", "rstoutn"),
+		 MPP_FUNCTION(0x3, "pcie1", "rstoutn"),
+		 MPP_FUNCTION(0x5, "nand", "rb"),
+		 MPP_FUNCTION(0x6, "spi1", "mosi")),
+	MPP_MODE(14,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "i2c0", "sda"),
+		 MPP_FUNCTION(0x3, "uart1", "txd")),
+	MPP_MODE(15,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "i2c0", "sck"),
+		 MPP_FUNCTION(0x3, "uart1", "rxd")),
+	MPP_MODE(16,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "uart0", "txd")),
+	MPP_MODE(17,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "uart0", "rxd")),
+	MPP_MODE(18,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "intn")),
+	MPP_MODE(19,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "rstn")),
+	MPP_MODE(20,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "pclk")),
+	MPP_MODE(21,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "fsync")),
+	MPP_MODE(22,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "drx")),
+	MPP_MODE(23,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "tdm", "dtx")),
+	MPP_MODE(24,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p0"),
+		 MPP_FUNCTION(0x2, "ge1", "rxd0"),
+		 MPP_FUNCTION(0x3, "sd", "cmd"),
+		 MPP_FUNCTION(0x4, "uart0", "rts"),
+		 MPP_FUNCTION(0x5, "spi0", "cs0"),
+		 MPP_FUNCTION(0x6, "dev", "cs1")),
+	MPP_MODE(25,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p2"),
+		 MPP_FUNCTION(0x2, "ge1", "rxd1"),
+		 MPP_FUNCTION(0x3, "sd", "d0"),
+		 MPP_FUNCTION(0x4, "uart0", "cts"),
+		 MPP_FUNCTION(0x5, "spi0", "mosi"),
+		 MPP_FUNCTION(0x6, "dev", "cs2")),
+	MPP_MODE(26,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie0", "clkreq"),
+		 MPP_FUNCTION(0x2, "ge1", "rxd2"),
+		 MPP_FUNCTION(0x3, "sd", "d2"),
+		 MPP_FUNCTION(0x4, "uart1", "rts"),
+		 MPP_FUNCTION(0x5, "spi0", "cs1"),
+		 MPP_FUNCTION(0x6, "led", "c1")),
+	MPP_MODE(27,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie1", "clkreq"),
+		 MPP_FUNCTION(0x2, "ge1", "rxd3"),
+		 MPP_FUNCTION(0x3, "sd", "d1"),
+		 MPP_FUNCTION(0x4, "uart1", "cts"),
+		 MPP_FUNCTION(0x5, "spi0", "miso"),
+		 MPP_FUNCTION(0x6, "led", "c2")),
+	MPP_MODE(28,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p3"),
+		 MPP_FUNCTION(0x2, "ge1", "txctl"),
+		 MPP_FUNCTION(0x3, "sd", "clk"),
+		 MPP_FUNCTION(0x5, "dram", "vttctrl")),
+	MPP_MODE(29,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie1", "clkreq"),
+		 MPP_FUNCTION(0x2, "ge1", "rxclk"),
+		 MPP_FUNCTION(0x3, "sd", "d3"),
+		 MPP_FUNCTION(0x5, "spi0", "sck"),
+		 MPP_FUNCTION(0x6, "pcie0", "rstoutn")),
+	MPP_MODE(30,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "txd0"),
+		 MPP_FUNCTION(0x3, "spi1", "cs0"),
+		 MPP_FUNCTION(0x5, "led", "p3"),
+		 MPP_FUNCTION(0x6, "ptp", "eventreq")),
+	MPP_MODE(31,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "txd1"),
+		 MPP_FUNCTION(0x3, "spi1", "mosi"),
+		 MPP_FUNCTION(0x5, "led", "p0")),
+	MPP_MODE(32,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "txd2"),
+		 MPP_FUNCTION(0x3, "spi1", "sck"),
+		 MPP_FUNCTION(0x4, "ptp", "triggen"),
+		 MPP_FUNCTION(0x5, "led", "c0")),
+	MPP_MODE(33,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "txd3"),
+		 MPP_FUNCTION(0x3, "spi1", "miso"),
+		 MPP_FUNCTION(0x5, "led", "p2")),
+	MPP_MODE(34,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "txclkout"),
+		 MPP_FUNCTION(0x3, "spi1", "sck"),
+		 MPP_FUNCTION(0x5, "led", "c1")),
+	MPP_MODE(35,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge1", "rxctl"),
+		 MPP_FUNCTION(0x3, "spi1", "cs1"),
+		 MPP_FUNCTION(0x4, "spi0", "cs2"),
+		 MPP_FUNCTION(0x5, "led", "p1")),
+	MPP_MODE(36,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie0", "clkreq"),
+		 MPP_FUNCTION(0x5, "led", "c2")),
+	MPP_MODE(37,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie0", "clkreq"),
+		 MPP_FUNCTION(0x2, "tdm", "intn"),
+		 MPP_FUNCTION(0x4, "ge", "mdc")),
+	MPP_MODE(38,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie1", "clkreq"),
+		 MPP_FUNCTION(0x4, "ge", "mdio")),
+	MPP_MODE(39,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "ref", "clkout"),
+		 MPP_FUNCTION(0x5, "led", "p3")),
+	MPP_MODE(40,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "uart1", "txd"),
+		 MPP_FUNCTION(0x5, "led", "p0")),
+	MPP_MODE(41,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "uart1", "rxd"),
+		 MPP_FUNCTION(0x5, "led", "p1")),
+	MPP_MODE(42,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x3, "spi1", "cs2"),
+		 MPP_FUNCTION(0x4, "led", "c0"),
+		 MPP_FUNCTION(0x6, "ptp", "clk")),
+	MPP_MODE(43,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "sata0", "prsnt"),
+		 MPP_FUNCTION(0x4, "dram", "vttctrl"),
+		 MPP_FUNCTION(0x5, "led", "c1")),
+	MPP_MODE(44,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "sata0", "prsnt")),
+	MPP_MODE(45,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "spi0", "cs2"),
+		 MPP_FUNCTION(0x4, "pcie0", "rstoutn"),
+		 MPP_FUNCTION(0x5, "led", "c2"),
+		 MPP_FUNCTION(0x6, "spi1", "cs2")),
+	MPP_MODE(46,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p0"),
+		 MPP_FUNCTION(0x2, "ge0", "txd0"),
+		 MPP_FUNCTION(0x3, "ge1", "txd0"),
+		 MPP_FUNCTION(0x6, "dev", "wen1")),
+	MPP_MODE(47,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p1"),
+		 MPP_FUNCTION(0x2, "ge0", "txd1"),
+		 MPP_FUNCTION(0x3, "ge1", "txd1"),
+		 MPP_FUNCTION(0x5, "ptp", "triggen"),
+		 MPP_FUNCTION(0x6, "dev", "ale0")),
+	MPP_MODE(48,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p2"),
+		 MPP_FUNCTION(0x2, "ge0", "txd2"),
+		 MPP_FUNCTION(0x3, "ge1", "txd2"),
+		 MPP_FUNCTION(0x6, "dev", "ale1")),
+	MPP_MODE(49,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "p3"),
+		 MPP_FUNCTION(0x2, "ge0", "txd3"),
+		 MPP_FUNCTION(0x3, "ge1", "txd3"),
+		 MPP_FUNCTION(0x6, "dev", "a2")),
+	MPP_MODE(50,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "c0"),
+		 MPP_FUNCTION(0x2, "ge0", "rxd0"),
+		 MPP_FUNCTION(0x3, "ge1", "rxd0"),
+		 MPP_FUNCTION(0x5, "ptp", "eventreq"),
+		 MPP_FUNCTION(0x6, "dev", "ad12")),
+	MPP_MODE(51,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "c1"),
+		 MPP_FUNCTION(0x2, "ge0", "rxd1"),
+		 MPP_FUNCTION(0x3, "ge1", "rxd1"),
+		 MPP_FUNCTION(0x6, "dev", "ad8")),
+	MPP_MODE(52,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "led", "c2"),
+		 MPP_FUNCTION(0x2, "ge0", "rxd2"),
+		 MPP_FUNCTION(0x3, "ge1", "rxd2"),
+		 MPP_FUNCTION(0x5, "i2c0", "sda"),
+		 MPP_FUNCTION(0x6, "dev", "ad9")),
+	MPP_MODE(53,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie1", "rstoutn"),
+		 MPP_FUNCTION(0x2, "ge0", "rxd3"),
+		 MPP_FUNCTION(0x3, "ge1", "rxd3"),
+		 MPP_FUNCTION(0x5, "i2c0", "sck"),
+		 MPP_FUNCTION(0x6, "dev", "ad10")),
+	MPP_MODE(54,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "pcie0", "rstoutn"),
+		 MPP_FUNCTION(0x2, "ge0", "rxctl"),
+		 MPP_FUNCTION(0x3, "ge1", "rxctl"),
+		 MPP_FUNCTION(0x6, "dev", "ad11")),
+	MPP_MODE(55,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge0", "rxclk"),
+		 MPP_FUNCTION(0x3, "ge1", "rxclk"),
+		 MPP_FUNCTION(0x6, "dev", "cs0")),
+	MPP_MODE(56,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge0", "txclkout"),
+		 MPP_FUNCTION(0x3, "ge1", "txclkout"),
+		 MPP_FUNCTION(0x6, "dev", "oe")),
+	MPP_MODE(57,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ge0", "txctl"),
+		 MPP_FUNCTION(0x3, "ge1", "txctl"),
+		 MPP_FUNCTION(0x6, "dev", "wen0")),
+	MPP_MODE(58,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "led", "c0")),
+	MPP_MODE(59,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x4, "led", "c1")),
+	MPP_MODE(60,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "uart1", "txd"),
+		 MPP_FUNCTION(0x4, "led", "c2"),
+		 MPP_FUNCTION(0x6, "dev", "ad13")),
+	MPP_MODE(61,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "i2c1", "sda"),
+		 MPP_FUNCTION(0x2, "uart1", "rxd"),
+		 MPP_FUNCTION(0x3, "spi1", "cs2"),
+		 MPP_FUNCTION(0x4, "led", "p0"),
+		 MPP_FUNCTION(0x6, "dev", "ad14")),
+	MPP_MODE(62,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "i2c1", "sck"),
+		 MPP_FUNCTION(0x4, "led", "p1"),
+		 MPP_FUNCTION(0x6, "dev", "ad15")),
+	MPP_MODE(63,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ptp", "triggen"),
+		 MPP_FUNCTION(0x4, "led", "p2"),
+		 MPP_FUNCTION(0x6, "dev", "burst")),
+	MPP_MODE(64,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "dram", "vttctrl"),
+		 MPP_FUNCTION(0x4, "led", "p3")),
+	MPP_MODE(65,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x1, "sata1", "prsnt")),
+	MPP_MODE(66,
+		 MPP_FUNCTION(0x0, "gpio", NULL),
+		 MPP_FUNCTION(0x2, "ptp", "eventreq"),
+		 MPP_FUNCTION(0x4, "spi1", "cs3"),
+		 MPP_FUNCTION(0x5, "pcie0", "rstoutn"),
+		 MPP_FUNCTION(0x6, "dev", "cs3")),
+};
+
+static struct mvebu_pinctrl_soc_info armada_375_pinctrl_info;
+
+static struct of_device_id armada_375_pinctrl_of_match[] = {
+	{ .compatible = "marvell,mv88f6720-pinctrl" },
+	{ },
+};
+
+static struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
+	MPP_FUNC_CTRL(0, 69, NULL, armada_375_mpp_ctrl),
+};
+
+static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 32),
+	MPP_GPIO_RANGE(2,  64, 64,  3),
+};
+
+static int armada_375_pinctrl_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = &armada_375_pinctrl_info;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
+
+	soc->variant = 0; /* no variants for Armada 375 */
+	soc->controls = mv88f6720_mpp_controls;
+	soc->ncontrols = ARRAY_SIZE(mv88f6720_mpp_controls);
+	soc->modes = mv88f6720_mpp_modes;
+	soc->nmodes = ARRAY_SIZE(mv88f6720_mpp_modes);
+	soc->gpioranges = mv88f6720_mpp_gpio_ranges;
+	soc->ngpioranges = ARRAY_SIZE(mv88f6720_mpp_gpio_ranges);
+
+	pdev->dev.platform_data = soc;
+
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int armada_375_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_375_pinctrl_driver = {
+	.driver = {
+		.name = "armada-375-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(armada_375_pinctrl_of_match),
+	},
+	.probe = armada_375_pinctrl_probe,
+	.remove = armada_375_pinctrl_remove,
+};
+
+module_platform_driver(armada_375_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 375 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
new file mode 100644
index 000000000000..1049f82fb62f
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
@@ -0,0 +1,462 @@
+/*
+ * Marvell Armada 380/385 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2013 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static void __iomem *mpp_base;
+
+static int armada_38x_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_38x_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+enum {
+	V_88F6810 = BIT(0),
+	V_88F6820 = BIT(1),
+	V_88F6828 = BIT(2),
+	V_88F6810_PLUS = (V_88F6810 | V_88F6820 | V_88F6828),
+	V_88F6820_PLUS = (V_88F6820 | V_88F6828),
+};
+
+static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
+	MPP_MODE(0,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua0",   "rxd",        V_88F6810_PLUS)),
+	MPP_MODE(1,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua0",   "txd",        V_88F6810_PLUS)),
+	MPP_MODE(2,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "i2c0",  "sck",        V_88F6810_PLUS)),
+	MPP_MODE(3,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "i2c0",  "sda",        V_88F6810_PLUS)),
+	MPP_MODE(4,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge",    "mdc",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ua1",   "txd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS)),
+	MPP_MODE(5,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge",    "mdio",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ua1",   "rxd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS)),
+	MPP_MODE(6,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txclkout",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge0",   "crs",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "cs3",        V_88F6810_PLUS)),
+	MPP_MODE(7,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txd0",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad9",        V_88F6810_PLUS)),
+	MPP_MODE(8,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txd1",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad10",       V_88F6810_PLUS)),
+	MPP_MODE(9,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txd2",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad11",       V_88F6810_PLUS)),
+	MPP_MODE(10,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txd3",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad12",       V_88F6810_PLUS)),
+	MPP_MODE(11,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txctl",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad13",       V_88F6810_PLUS)),
+	MPP_MODE(12,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxd0",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "cs1",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad14",       V_88F6810_PLUS)),
+	MPP_MODE(13,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxd1",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie0", "clkreq",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "clkreq",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "cs2",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad15",       V_88F6810_PLUS)),
+	MPP_MODE(14,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxd2",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "m",     "vtt_ctrl",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "cs3",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "wen1",       V_88F6810_PLUS)),
+	MPP_MODE(15,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxd3",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge",    "mdc slave",  V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "mosi",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "pcie1", "rstout",     V_88F6820_PLUS)),
+	MPP_MODE(16,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxctl",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge",    "mdio slave", V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "m",     "decc_err",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "miso",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "pcie0", "clkreq",     V_88F6810_PLUS)),
+	MPP_MODE(17,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxclk",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua1",   "rxd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sata1", "prsnt",      V_88F6810_PLUS)),
+	MPP_MODE(18,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "rxerr",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ptp",   "trig_gen",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua1",   "txd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi0",  "cs0",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "pcie1", "rstout",     V_88F6820_PLUS)),
+	MPP_MODE(19,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "col",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ptp",   "event_req",  V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie0", "clkreq",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sata1", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "ua0",   "cts",        V_88F6810_PLUS)),
+	MPP_MODE(20,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ge0",   "txclk",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "ua0",   "rts",        V_88F6810_PLUS)),
+	MPP_MODE(21,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "cs1",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxd0",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "cmd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "bootcs",     V_88F6810_PLUS)),
+	MPP_MODE(22,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "mosi",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad0",        V_88F6810_PLUS)),
+	MPP_MODE(23,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad2",        V_88F6810_PLUS)),
+	MPP_MODE(24,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "miso",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ua0",   "cts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua1",   "rxd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d4",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ready",      V_88F6810_PLUS)),
+	MPP_MODE(25,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "cs0",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ua0",   "rts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua1",   "txd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d5",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "cs0",        V_88F6810_PLUS)),
+	MPP_MODE(26,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "cs2",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "i2c1",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d6",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "cs1",        V_88F6810_PLUS)),
+	MPP_MODE(27,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "spi0",  "cs3",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txclkout",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "i2c1",  "sda",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d7",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "cs2",        V_88F6810_PLUS)),
+	MPP_MODE(28,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txd0",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "clk",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad5",        V_88F6810_PLUS)),
+	MPP_MODE(29,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txd1",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ale0",       V_88F6810_PLUS)),
+	MPP_MODE(30,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txd2",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "oen",        V_88F6810_PLUS)),
+	MPP_MODE(31,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txd3",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ale1",       V_88F6810_PLUS)),
+	MPP_MODE(32,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "txctl",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "wen0",       V_88F6810_PLUS)),
+	MPP_MODE(33,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "m",     "decc_err",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad3",        V_88F6810_PLUS)),
+	MPP_MODE(34,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad1",        V_88F6810_PLUS)),
+	MPP_MODE(35,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ref",   "clk_out1",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "a1",         V_88F6810_PLUS)),
+	MPP_MODE(36,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ptp",   "trig_gen",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "a0",         V_88F6810_PLUS)),
+	MPP_MODE(37,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ptp",   "clk",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxclk",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d3",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad8",        V_88F6810_PLUS)),
+	MPP_MODE(38,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ptp",   "event_req",  V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxd1",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ref",   "clk_out0",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d0",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad4",        V_88F6810_PLUS)),
+	MPP_MODE(39,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "i2c1",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxd2",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d1",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "a2",         V_88F6810_PLUS)),
+	MPP_MODE(40,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "i2c1",  "sda",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxd3",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "sd0",   "d2",         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad6",        V_88F6810_PLUS)),
+	MPP_MODE(41,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua1",   "rxd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge1",   "rxctl",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "cs3",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "burst/last", V_88F6810_PLUS)),
+	MPP_MODE(42,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua1",   "txd",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "ad7",        V_88F6810_PLUS)),
+	MPP_MODE(43,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "pcie0", "clkreq",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "m",     "vtt_ctrl",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "m",     "decc_err",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "dev",   "clkout",     V_88F6810_PLUS)),
+	MPP_MODE(44,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "sata2", "prsnt",      V_88F6828),
+		 MPP_VAR_FUNCTION(4, "sata3", "prsnt",      V_88F6828),
+		 MPP_VAR_FUNCTION(5, "pcie0", "rstout",     V_88F6810_PLUS)),
+	MPP_MODE(45,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ref",   "clk_out0",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "pcie2", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "pcie3", "rstout",     V_88F6810_PLUS)),
+	MPP_MODE(46,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ref",   "clk_out1",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "pcie2", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "pcie3", "rstout",     V_88F6810_PLUS)),
+	MPP_MODE(47,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "sata2", "prsnt",      V_88F6828),
+		 MPP_VAR_FUNCTION(4, "spi1",  "cs2",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sata3", "prsnt",      V_88F6828)),
+	MPP_MODE(48,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "m",     "vtt_ctrl",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "pclk",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "mclk",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d4",         V_88F6810_PLUS)),
+	MPP_MODE(49,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata2", "prsnt",      V_88F6828),
+		 MPP_VAR_FUNCTION(2, "sata3", "prsnt",      V_88F6828),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "fsync",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "lrclk",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d5",         V_88F6810_PLUS)),
+	MPP_MODE(50,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "drx",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "extclk",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "cmd",        V_88F6810_PLUS)),
+	MPP_MODE(51,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "dtx",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "sdo",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "m",     "decc_err",   V_88F6810_PLUS)),
+	MPP_MODE(52,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "intn",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "sdi",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d6",         V_88F6810_PLUS)),
+	MPP_MODE(53,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata1", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "tdm2c", "rstn",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "audio", "bclk",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d7",         V_88F6810_PLUS)),
+	MPP_MODE(54,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d3",         V_88F6810_PLUS)),
+	MPP_MODE(55,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua1",   "cts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge",    "mdio",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "clkreq",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "cs1",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d0",         V_88F6810_PLUS)),
+	MPP_MODE(56,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "ua1",   "rts",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "ge",    "mdc",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "m",     "decc_err",   V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "mosi",       V_88F6810_PLUS)),
+	MPP_MODE(57,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "clk",        V_88F6810_PLUS)),
+	MPP_MODE(58,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "pcie1", "clkreq",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(2, "i2c1",  "sck",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie2", "clkreq",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "miso",       V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d1",         V_88F6810_PLUS)),
+	MPP_MODE(59,
+		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(2, "i2c1",  "sda",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(3, "pcie1", "rstout",     V_88F6820_PLUS),
+		 MPP_VAR_FUNCTION(4, "spi1",  "cs0",        V_88F6810_PLUS),
+		 MPP_VAR_FUNCTION(5, "sd0",   "d2",         V_88F6810_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_38x_pinctrl_info;
+
+static struct of_device_id armada_38x_pinctrl_of_match[] = {
+	{
+		.compatible = "marvell,mv88f6810-pinctrl",
+		.data       = (void *) V_88F6810,
+	},
+	{
+		.compatible = "marvell,mv88f6820-pinctrl",
+		.data       = (void *) V_88F6820,
+	},
+	{
+		.compatible = "marvell,mv88f6828-pinctrl",
+		.data       = (void *) V_88F6828,
+	},
+	{ },
+};
+
+static struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
+	MPP_FUNC_CTRL(0, 59, NULL, armada_38x_mpp_ctrl),
+};
+
+static struct pinctrl_gpio_range armada_38x_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 27),
+};
+
+static int armada_38x_pinctrl_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = &armada_38x_pinctrl_info;
+	const struct of_device_id *match =
+		of_match_device(armada_38x_pinctrl_of_match, &pdev->dev);
+	struct resource *res;
+
+	if (!match)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
+
+	soc->variant = (unsigned) match->data & 0xff;
+	soc->controls = armada_38x_mpp_controls;
+	soc->ncontrols = ARRAY_SIZE(armada_38x_mpp_controls);
+	soc->gpioranges = armada_38x_mpp_gpio_ranges;
+	soc->ngpioranges = ARRAY_SIZE(armada_38x_mpp_gpio_ranges);
+	soc->modes = armada_38x_mpp_modes;
+	soc->nmodes = armada_38x_mpp_controls[0].npins;
+
+	pdev->dev.platform_data = soc;
+
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int armada_38x_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_38x_pinctrl_driver = {
+	.driver = {
+		.name = "armada-38x-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(armada_38x_pinctrl_of_match),
+	},
+	.probe = armada_38x_pinctrl_probe,
+	.remove = armada_38x_pinctrl_remove,
+};
+
+module_platform_driver(armada_38x_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 38x pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index 843a51f9d129..de311129f7a0 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -33,6 +33,18 @@
 
 #include "pinctrl-mvebu.h"
 
+static void __iomem *mpp_base;
+
+static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
 enum armada_xp_variant {
 	V_MV78230	= BIT(0),
 	V_MV78260	= BIT(1),
@@ -366,7 +378,7 @@ static struct of_device_id armada_xp_pinctrl_of_match[] = {
 };
 
 static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
-	MPP_REG_CTRL(0, 48),
+	MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
@@ -375,7 +387,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
 };
 
 static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
-	MPP_REG_CTRL(0, 66),
+	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
@@ -385,7 +397,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
 };
 
 static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
-	MPP_REG_CTRL(0, 66),
+	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
@@ -399,10 +411,16 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 	struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
 	const struct of_device_id *match =
 		of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
+	struct resource *res;
 
 	if (!match)
 		return -ENODEV;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
+
 	soc->variant = (unsigned) match->data & 0xff;
 
 	switch (soc->variant) {
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index 47268393af34..9e7ff651c018 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -18,107 +18,122 @@
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
 #include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
 
 #include "pinctrl-mvebu.h"
 
-#define DOVE_SB_REGS_VIRT_BASE		IOMEM(0xfde00000)
-#define DOVE_MPP_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE + 0xd0200)
-#define DOVE_PMU_MPP_GENERAL_CTRL	(DOVE_MPP_VIRT_BASE + 0x10)
-#define  DOVE_AU0_AC97_SEL		BIT(16)
-#define DOVE_PMU_SIGNAL_SELECT_0	(DOVE_SB_REGS_VIRT_BASE + 0xd802C)
-#define DOVE_PMU_SIGNAL_SELECT_1	(DOVE_SB_REGS_VIRT_BASE + 0xd8030)
-#define DOVE_GLOBAL_CONFIG_1		(DOVE_SB_REGS_VIRT_BASE + 0xe802C)
-#define DOVE_GLOBAL_CONFIG_1		(DOVE_SB_REGS_VIRT_BASE + 0xe802C)
-#define  DOVE_TWSI_ENABLE_OPTION1	BIT(7)
-#define DOVE_GLOBAL_CONFIG_2		(DOVE_SB_REGS_VIRT_BASE + 0xe8030)
-#define  DOVE_TWSI_ENABLE_OPTION2	BIT(20)
-#define  DOVE_TWSI_ENABLE_OPTION3	BIT(21)
-#define  DOVE_TWSI_OPTION3_GPIO		BIT(22)
-#define DOVE_SSP_CTRL_STATUS_1		(DOVE_SB_REGS_VIRT_BASE + 0xe8034)
-#define  DOVE_SSP_ON_AU1		BIT(0)
-#define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xe803c)
-#define  DOVE_AU1_SPDIFO_GPIO_EN	BIT(1)
-#define  DOVE_NAND_GPIO_EN		BIT(0)
-#define DOVE_GPIO_LO_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE + 0xd0400)
-#define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_LO_VIRT_BASE + 0x40)
-#define  DOVE_SPI_GPIO_SEL		BIT(5)
-#define  DOVE_UART1_GPIO_SEL		BIT(4)
-#define  DOVE_AU1_GPIO_SEL		BIT(3)
-#define  DOVE_CAM_GPIO_SEL		BIT(2)
-#define  DOVE_SD1_GPIO_SEL		BIT(1)
-#define  DOVE_SD0_GPIO_SEL		BIT(0)
-
-#define MPPS_PER_REG	8
-#define MPP_BITS	4
-#define MPP_MASK	0xf
+/* Internal registers can be configured at any 1 MiB aligned address */
+#define INT_REGS_MASK		~(SZ_1M - 1)
+#define MPP4_REGS_OFFS		0xd0440
+#define PMU_REGS_OFFS		0xd802c
+#define GC_REGS_OFFS		0xe802c
+
+/* MPP Base registers */
+#define PMU_MPP_GENERAL_CTRL	0x10
+#define  AU0_AC97_SEL		BIT(16)
+
+/* MPP Control 4 register */
+#define SPI_GPIO_SEL		BIT(5)
+#define UART1_GPIO_SEL		BIT(4)
+#define AU1_GPIO_SEL		BIT(3)
+#define CAM_GPIO_SEL		BIT(2)
+#define SD1_GPIO_SEL		BIT(1)
+#define SD0_GPIO_SEL		BIT(0)
+
+/* PMU Signal Select registers */
+#define PMU_SIGNAL_SELECT_0	0x00
+#define PMU_SIGNAL_SELECT_1	0x04
+
+/* Global Config regmap registers */
+#define GLOBAL_CONFIG_1		0x00
+#define  TWSI_ENABLE_OPTION1	BIT(7)
+#define GLOBAL_CONFIG_2		0x04
+#define  TWSI_ENABLE_OPTION2	BIT(20)
+#define  TWSI_ENABLE_OPTION3	BIT(21)
+#define  TWSI_OPTION3_GPIO	BIT(22)
+#define SSP_CTRL_STATUS_1	0x08
+#define  SSP_ON_AU1		BIT(0)
+#define MPP_GENERAL_CONFIG	0x10
+#define  AU1_SPDIFO_GPIO_EN	BIT(1)
+#define  NAND_GPIO_EN		BIT(0)
 
 #define CONFIG_PMU	BIT(4)
 
-static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				 unsigned long *config)
+static void __iomem *mpp_base;
+static void __iomem *mpp4_base;
+static void __iomem *pmu_base;
+static struct regmap *gconfmap;
+
+static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int dove_mpp_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 	unsigned long func;
 
-	if (pmu & (1 << ctrl->pid)) {
-		func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
-		*config = (func >> shift) & MPP_MASK;
-		*config |= CONFIG_PMU;
-	} else {
-		func = readl(DOVE_MPP_VIRT_BASE + off);
-		*config = (func >> shift) & MPP_MASK;
-	}
+	if ((pmu & BIT(pid)) == 0)
+		return default_mpp_ctrl_get(mpp_base, pid, config);
+
+	func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
+	*config = (func >> shift) & MVEBU_MPP_MASK;
+	*config |= CONFIG_PMU;
+
 	return 0;
 }
 
-static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				 unsigned long config)
+static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 	unsigned long func;
 
-	if (config & CONFIG_PMU) {
-		writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
-		func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
-		func &= ~(MPP_MASK << shift);
-		func |= (config & MPP_MASK) << shift;
-		writel(func, DOVE_PMU_SIGNAL_SELECT_0 + off);
-	} else {
-		writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
-		func = readl(DOVE_MPP_VIRT_BASE + off);
-		func &= ~(MPP_MASK << shift);
-		func |= (config & MPP_MASK) << shift;
-		writel(func, DOVE_MPP_VIRT_BASE + off);
+	if ((config & CONFIG_PMU) == 0) {
+		writel(pmu & ~BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
+		return default_mpp_ctrl_set(mpp_base, pid, config);
 	}
+
+	writel(pmu | BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
+	func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
+	func &= ~(MVEBU_MPP_MASK << shift);
+	func |= (config & MVEBU_MPP_MASK) << shift;
+	writel(func, pmu_base + PMU_SIGNAL_SELECT_0 + off);
+
 	return 0;
 }
 
-static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
+static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
 {
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long mpp4 = readl(mpp4_base);
 	unsigned long mask;
 
-	switch (ctrl->pid) {
+	switch (pid) {
 	case 24: /* mpp_camera */
-		mask = DOVE_CAM_GPIO_SEL;
+		mask = CAM_GPIO_SEL;
 		break;
 	case 40: /* mpp_sdio0 */
-		mask = DOVE_SD0_GPIO_SEL;
+		mask = SD0_GPIO_SEL;
 		break;
 	case 46: /* mpp_sdio1 */
-		mask = DOVE_SD1_GPIO_SEL;
+		mask = SD1_GPIO_SEL;
 		break;
 	case 58: /* mpp_spi0 */
-		mask = DOVE_SPI_GPIO_SEL;
+		mask = SPI_GPIO_SEL;
 		break;
 	case 62: /* mpp_uart1 */
-		mask = DOVE_UART1_GPIO_SEL;
+		mask = UART1_GPIO_SEL;
 		break;
 	default:
 		return -EINVAL;
@@ -129,27 +144,26 @@ static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
 	return 0;
 }
 
-static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long config)
+static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long mpp4 = readl(mpp4_base);
 	unsigned long mask;
 
-	switch (ctrl->pid) {
+	switch (pid) {
 	case 24: /* mpp_camera */
-		mask = DOVE_CAM_GPIO_SEL;
+		mask = CAM_GPIO_SEL;
 		break;
 	case 40: /* mpp_sdio0 */
-		mask = DOVE_SD0_GPIO_SEL;
+		mask = SD0_GPIO_SEL;
 		break;
 	case 46: /* mpp_sdio1 */
-		mask = DOVE_SD1_GPIO_SEL;
+		mask = SD1_GPIO_SEL;
 		break;
 	case 58: /* mpp_spi0 */
-		mask = DOVE_SPI_GPIO_SEL;
+		mask = SPI_GPIO_SEL;
 		break;
 	case 62: /* mpp_uart1 */
-		mask = DOVE_UART1_GPIO_SEL;
+		mask = UART1_GPIO_SEL;
 		break;
 	default:
 		return -EINVAL;
@@ -159,74 +173,69 @@ static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
 	if (config)
 		mpp4 |= mask;
 
-	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+	writel(mpp4, mpp4_base);
 
 	return 0;
 }
 
-static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
+static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
 {
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+	unsigned int gmpp;
 
-	*config = ((gmpp & DOVE_NAND_GPIO_EN) != 0);
+	regmap_read(gconfmap, MPP_GENERAL_CONFIG, &gmpp);
+	*config = ((gmpp & NAND_GPIO_EN) != 0);
 
 	return 0;
 }
 
-static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long config)
+static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-
-	gmpp &= ~DOVE_NAND_GPIO_EN;
-	if (config)
-		gmpp |= DOVE_NAND_GPIO_EN;
-
-	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
-
+	regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
+			   NAND_GPIO_EN,
+			   (config) ? NAND_GPIO_EN : 0);
 	return 0;
 }
 
-static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long *config)
+static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
 {
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 
-	*config = ((pmu & DOVE_AU0_AC97_SEL) != 0);
+	*config = ((pmu & AU0_AC97_SEL) != 0);
 
 	return 0;
 }
 
-static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
+static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 
-	pmu &= ~DOVE_AU0_AC97_SEL;
+	pmu &= ~AU0_AC97_SEL;
 	if (config)
-		pmu |= DOVE_AU0_AC97_SEL;
-	writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL);
+		pmu |= AU0_AC97_SEL;
+	writel(pmu, mpp_base + PMU_MPP_GENERAL_CTRL);
 
 	return 0;
 }
 
-static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long *config)
+static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
 {
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+	unsigned int mpp4 = readl(mpp4_base);
+	unsigned int sspc1;
+	unsigned int gmpp;
+	unsigned int gcfg2;
+
+	regmap_read(gconfmap, SSP_CTRL_STATUS_1, &sspc1);
+	regmap_read(gconfmap, MPP_GENERAL_CONFIG, &gmpp);
+	regmap_read(gconfmap, GLOBAL_CONFIG_2, &gcfg2);
 
 	*config = 0;
-	if (mpp4 & DOVE_AU1_GPIO_SEL)
+	if (mpp4 & AU1_GPIO_SEL)
 		*config |= BIT(3);
-	if (sspc1 & DOVE_SSP_ON_AU1)
+	if (sspc1 & SSP_ON_AU1)
 		*config |= BIT(2);
-	if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN)
+	if (gmpp & AU1_SPDIFO_GPIO_EN)
 		*config |= BIT(1);
-	if (gcfg2 & DOVE_TWSI_OPTION3_GPIO)
+	if (gcfg2 & TWSI_OPTION3_GPIO)
 		*config |= BIT(0);
 
 	/* SSP/TWSI only if I2S1 not set*/
@@ -238,35 +247,24 @@ static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
 	return 0;
 }
 
-static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
+static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+	unsigned int mpp4 = readl(mpp4_base);
 
-	/*
-	 * clear all audio1 related bits before configure
-	 */
-	gcfg2 &= ~DOVE_TWSI_OPTION3_GPIO;
-	gmpp &= ~DOVE_AU1_SPDIFO_GPIO_EN;
-	sspc1 &= ~DOVE_SSP_ON_AU1;
-	mpp4 &= ~DOVE_AU1_GPIO_SEL;
-
-	if (config & BIT(0))
-		gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
-	if (config & BIT(1))
-		gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
-	if (config & BIT(2))
-		sspc1 |= DOVE_SSP_ON_AU1;
+	mpp4 &= ~AU1_GPIO_SEL;
 	if (config & BIT(3))
-		mpp4 |= DOVE_AU1_GPIO_SEL;
-
-	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
-	writel(sspc1, DOVE_SSP_CTRL_STATUS_1);
-	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
-	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+		mpp4 |= AU1_GPIO_SEL;
+	writel(mpp4, mpp4_base);
+
+	regmap_update_bits(gconfmap, SSP_CTRL_STATUS_1,
+			   SSP_ON_AU1,
+			   (config & BIT(2)) ? SSP_ON_AU1 : 0);
+	regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
+			   AU1_SPDIFO_GPIO_EN,
+			   (config & BIT(1)) ? AU1_SPDIFO_GPIO_EN : 0);
+	regmap_update_bits(gconfmap, GLOBAL_CONFIG_2,
+			   TWSI_OPTION3_GPIO,
+			   (config & BIT(0)) ? TWSI_OPTION3_GPIO : 0);
 
 	return 0;
 }
@@ -276,11 +274,11 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
  * break other functions. If you require all mpps as gpio
  * enforce gpio setting by pinctrl mapping.
  */
-static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
+static int dove_audio1_ctrl_gpio_req(unsigned pid)
 {
 	unsigned long config;
 
-	dove_audio1_ctrl_get(ctrl, &config);
+	dove_audio1_ctrl_get(pid, &config);
 
 	switch (config) {
 	case 0x02: /* i2s1 : gpio[56:57] */
@@ -303,76 +301,62 @@ static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
 }
 
 /* mpp[52:57] has gpio pins capable of in and out */
-static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
-				bool input)
+static int dove_audio1_ctrl_gpio_dir(unsigned pid, bool input)
 {
 	if (pid < 52 || pid > 57)
 		return -ENOTSUPP;
 	return 0;
 }
 
-static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
+static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
 {
-	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+	unsigned int gcfg1;
+	unsigned int gcfg2;
+
+	regmap_read(gconfmap, GLOBAL_CONFIG_1, &gcfg1);
+	regmap_read(gconfmap, GLOBAL_CONFIG_2, &gcfg2);
 
 	*config = 0;
-	if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1)
+	if (gcfg1 & TWSI_ENABLE_OPTION1)
 		*config = 1;
-	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2)
+	else if (gcfg2 & TWSI_ENABLE_OPTION2)
 		*config = 2;
-	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3)
+	else if (gcfg2 & TWSI_ENABLE_OPTION3)
 		*config = 3;
 
 	return 0;
 }
 
-static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
+static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
 {
-	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
-
-	gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
-	gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION3);
+	unsigned int gcfg1 = 0;
+	unsigned int gcfg2 = 0;
 
 	switch (config) {
 	case 1:
-		gcfg1 |= DOVE_TWSI_ENABLE_OPTION1;
+		gcfg1 = TWSI_ENABLE_OPTION1;
 		break;
 	case 2:
-		gcfg2 |= DOVE_TWSI_ENABLE_OPTION2;
+		gcfg2 = TWSI_ENABLE_OPTION2;
 		break;
 	case 3:
-		gcfg2 |= DOVE_TWSI_ENABLE_OPTION3;
+		gcfg2 = TWSI_ENABLE_OPTION3;
 		break;
 	}
 
-	writel(gcfg1, DOVE_GLOBAL_CONFIG_1);
-	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+	regmap_update_bits(gconfmap, GLOBAL_CONFIG_1,
+			   TWSI_ENABLE_OPTION1,
+			   gcfg1);
+	regmap_update_bits(gconfmap, GLOBAL_CONFIG_2,
+			   TWSI_ENABLE_OPTION2 | TWSI_ENABLE_OPTION3,
+			   gcfg2);
 
 	return 0;
 }
 
 static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
-	MPP_REG_CTRL(16, 23),
+	MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
 	MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
 	MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
 	MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
@@ -772,8 +756,17 @@ static struct of_device_id dove_pinctrl_of_match[] = {
 	{ }
 };
 
+static struct regmap_config gc_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 5,
+};
+
 static int dove_pinctrl_probe(struct platform_device *pdev)
 {
+	struct resource *res, *mpp_res;
+	struct resource fb_res;
 	const struct of_device_id *match =
 		of_match_device(dove_pinctrl_of_match, &pdev->dev);
 	pdev->dev.platform_data = (void *)match->data;
@@ -789,6 +782,58 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(clk);
 
+	mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, mpp_res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
+
+	/* prepare fallback resource */
+	memcpy(&fb_res, mpp_res, sizeof(struct resource));
+	fb_res.start = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_warn(&pdev->dev, "falling back to hardcoded MPP4 resource\n");
+		adjust_resource(&fb_res,
+			(mpp_res->start & INT_REGS_MASK) + MPP4_REGS_OFFS, 0x4);
+		res = &fb_res;
+	}
+
+	mpp4_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp4_base))
+		return PTR_ERR(mpp4_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_warn(&pdev->dev, "falling back to hardcoded PMU resource\n");
+		adjust_resource(&fb_res,
+			(mpp_res->start & INT_REGS_MASK) + PMU_REGS_OFFS, 0x8);
+		res = &fb_res;
+	}
+
+	pmu_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pmu_base))
+		return PTR_ERR(pmu_base);
+
+	gconfmap = syscon_regmap_lookup_by_compatible("marvell,dove-global-config");
+	if (IS_ERR(gconfmap)) {
+		void __iomem *gc_base;
+
+		dev_warn(&pdev->dev, "falling back to hardcoded global registers\n");
+		adjust_resource(&fb_res,
+			(mpp_res->start & INT_REGS_MASK) + GC_REGS_OFFS, 0x14);
+		gc_base = devm_ioremap_resource(&pdev->dev, &fb_res);
+		if (IS_ERR(gc_base))
+			return PTR_ERR(gc_base);
+		gconfmap = devm_regmap_init_mmio(&pdev->dev,
+						 gc_base, &gc_regmap_config);
+		if (IS_ERR(gconfmap))
+			return PTR_ERR(gconfmap);
+	}
+
+	/* Warn on any missing DT resource */
+	WARN(fb_res.start, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n");
+
 	return mvebu_pinctrl_probe(pdev);
 }
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 6b504b5935a5..0d0211a1a0b0 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -21,6 +21,18 @@
 
 #include "pinctrl-mvebu.h"
 
+static void __iomem *mpp_base;
+
+static int kirkwood_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+	return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int kirkwood_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+	return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
 #define V(f6180, f6190, f6192, f6281, f6282, dx4122)	\
 	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
 	 (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
@@ -359,7 +371,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
 };
 
 static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
-	MPP_REG_CTRL(0, 29),
+	MPP_FUNC_CTRL(0, 29, NULL, kirkwood_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
@@ -367,7 +379,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
 };
 
 static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
-	MPP_REG_CTRL(0, 35),
+	MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
@@ -376,7 +388,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
 };
 
 static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
-	MPP_REG_CTRL(0, 49),
+	MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
@@ -456,9 +468,16 @@ static struct of_device_id kirkwood_pinctrl_of_match[] = {
 
 static int kirkwood_pinctrl_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	const struct of_device_id *match =
 		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
 	pdev->dev.platform_data = (void *)match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mpp_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mpp_base))
+		return PTR_ERR(mpp_base);
+
 	return mvebu_pinctrl_probe(pdev);
 }
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 0fd1ad31fbf9..9908374f8f92 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -50,7 +50,6 @@ struct mvebu_pinctrl {
 	struct device *dev;
 	struct pinctrl_dev *pctldev;
 	struct pinctrl_desc desc;
-	void __iomem *base;
 	struct mvebu_pinctrl_group *groups;
 	unsigned num_groups;
 	struct mvebu_pinctrl_function *functions;
@@ -138,43 +137,6 @@ static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
 	return NULL;
 }
 
-/*
- * Common mpp pin configuration registers on MVEBU are
- * registers of eight 4-bit values for each mpp setting.
- * Register offset and bit mask are calculated accordingly below.
- */
-static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
-				struct mvebu_pinctrl_group *grp,
-				unsigned long *config)
-{
-	unsigned pin = grp->gid;
-	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
-
-	*config = readl(pctl->base + off);
-	*config >>= shift;
-	*config &= MPP_MASK;
-
-	return 0;
-}
-
-static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
-				struct mvebu_pinctrl_group *grp,
-				unsigned long config)
-{
-	unsigned pin = grp->gid;
-	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
-	unsigned long reg;
-
-	reg = readl(pctl->base + off);
-	reg &= ~(MPP_MASK << shift);
-	reg |= (config << shift);
-	writel(reg, pctl->base + off);
-
-	return 0;
-}
-
 static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
 				unsigned gid, unsigned long *config)
 {
@@ -184,10 +146,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
 	if (!grp->ctrl)
 		return -EINVAL;
 
-	if (grp->ctrl->mpp_get)
-		return grp->ctrl->mpp_get(grp->ctrl, config);
-
-	return mvebu_common_mpp_get(pctl, grp, config);
+	return grp->ctrl->mpp_get(grp->pins[0], config);
 }
 
 static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
@@ -202,11 +161,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	for (i = 0; i < num_configs; i++) {
-		if (grp->ctrl->mpp_set)
-			ret = grp->ctrl->mpp_set(grp->ctrl, configs[i]);
-		else
-			ret = mvebu_common_mpp_set(pctl, grp, configs[i]);
-
+		ret = grp->ctrl->mpp_set(grp->pins[0], configs[i]);
 		if (ret)
 			return ret;
 	} /* for each config */
@@ -347,7 +302,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	if (grp->ctrl->mpp_gpio_req)
-		return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
+		return grp->ctrl->mpp_gpio_req(offset);
 
 	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
 	if (!setting)
@@ -370,7 +325,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	if (grp->ctrl->mpp_gpio_dir)
-		return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
+		return grp->ctrl->mpp_gpio_dir(offset, input);
 
 	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
 	if (!setting)
@@ -593,11 +548,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
 int mvebu_pinctrl_probe(struct platform_device *pdev)
 {
 	struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
-	struct resource *res;
 	struct mvebu_pinctrl *pctl;
-	void __iomem *base;
 	struct pinctrl_pin_desc *pdesc;
 	unsigned gid, n, k;
+	unsigned size, noname = 0;
+	char *noname_buf;
+	void *p;
 	int ret;
 
 	if (!soc || !soc->controls || !soc->modes) {
@@ -605,11 +561,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
 	pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
 			GFP_KERNEL);
 	if (!pctl) {
@@ -623,7 +574,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	pctl->desc.pmxops = &mvebu_pinmux_ops;
 	pctl->desc.confops = &mvebu_pinconf_ops;
 	pctl->variant = soc->variant;
-	pctl->base = base;
 	pctl->dev = &pdev->dev;
 	platform_set_drvdata(pdev, pctl);
 
@@ -633,33 +583,23 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	pctl->desc.npins = 0;
 	for (n = 0; n < soc->ncontrols; n++) {
 		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
-		char *names;
 
 		pctl->desc.npins += ctrl->npins;
-		/* initial control pins */
+		/* initialize control's pins[] array */
 		for (k = 0; k < ctrl->npins; k++)
 			ctrl->pins[k] = ctrl->pid + k;
 
-		/* special soc specific control */
-		if (ctrl->mpp_get || ctrl->mpp_set) {
-			if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) {
-				dev_err(&pdev->dev, "wrong soc control info\n");
-				return -EINVAL;
-			}
+		/*
+		 * We allow to pass controls with NULL name that we treat
+		 * as a range of one-pin groups with generic mvebu register
+		 * controls.
+		 */
+		if (!ctrl->name) {
+			pctl->num_groups += ctrl->npins;
+			noname += ctrl->npins;
+		} else {
 			pctl->num_groups += 1;
-			continue;
 		}
-
-		/* generic mvebu register control */
-		names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
-		if (!names) {
-			dev_err(&pdev->dev, "failed to alloc mpp names\n");
-			return -ENOMEM;
-		}
-		for (k = 0; k < ctrl->npins; k++)
-			sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
-		ctrl->name = names;
-		pctl->num_groups += ctrl->npins;
 	}
 
 	pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
@@ -673,12 +613,17 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 		pdesc[n].number = n;
 	pctl->desc.pins = pdesc;
 
-	pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
-			     sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
-	if (!pctl->groups) {
-		dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
+	/*
+	 * allocate groups and name buffers for unnamed groups.
+	 */
+	size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8;
+	p = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to alloc group data\n");
 		return -ENOMEM;
 	}
+	pctl->groups = p;
+	noname_buf = p + pctl->num_groups * sizeof(*pctl->groups);
 
 	/* assign mpp controls to groups */
 	gid = 0;
@@ -690,17 +635,26 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 		pctl->groups[gid].pins = ctrl->pins;
 		pctl->groups[gid].npins = ctrl->npins;
 
-		/* generic mvebu register control maps to a number of groups */
-		if (!ctrl->mpp_get && !ctrl->mpp_set) {
+		/*
+		 * We treat unnamed controls as a range of one-pin groups
+		 * with generic mvebu register controls. Use one group for
+		 * each in this range and assign a default group name.
+		 */
+		if (!ctrl->name) {
+			pctl->groups[gid].name = noname_buf;
 			pctl->groups[gid].npins = 1;
+			sprintf(noname_buf, "mpp%d", ctrl->pid+0);
+			noname_buf += 8;
 
 			for (k = 1; k < ctrl->npins; k++) {
 				gid++;
 				pctl->groups[gid].gid = gid;
 				pctl->groups[gid].ctrl = ctrl;
-				pctl->groups[gid].name = &ctrl->name[8*k];
+				pctl->groups[gid].name = noname_buf;
 				pctl->groups[gid].pins = &ctrl->pins[k];
 				pctl->groups[gid].npins = 1;
+				sprintf(noname_buf, "mpp%d", ctrl->pid+k);
+				noname_buf += 8;
 			}
 		}
 		gid++;
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index 90bd3beee860..65a98e6f7265 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -28,20 +28,19 @@
  * between two or more different settings, e.g. assign mpp pin 13 to
  * uart1 or sata.
  *
- * If optional mpp_get/_set functions are set these are used to get/set
- * a specific mode. Otherwise it is assumed that the mpp control is based
- * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
- * functions can be used to allow pin settings with varying gpio pins.
+ * The mpp_get/_set functions are mandatory and are used to get/set a
+ * specific mode. The optional mpp_gpio_req/_dir functions can be used
+ * to allow pin settings with varying gpio pins.
  */
 struct mvebu_mpp_ctrl {
 	const char *name;
 	u8 pid;
 	u8 npins;
 	unsigned *pins;
-	int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
-	int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
-	int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
-	int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
+	int (*mpp_get)(unsigned pid, unsigned long *config);
+	int (*mpp_set)(unsigned pid, unsigned long config);
+	int (*mpp_gpio_req)(unsigned pid);
+	int (*mpp_gpio_dir)(unsigned pid, bool input);
 };
 
 /**
@@ -114,18 +113,6 @@ struct mvebu_pinctrl_soc_info {
 	int ngpioranges;
 };
 
-#define MPP_REG_CTRL(_idl, _idh)				\
-	{							\
-		.name = NULL,					\
-		.pid = _idl,					\
-		.npins = _idh - _idl + 1,			\
-		.pins = (unsigned[_idh - _idl + 1]) { },	\
-		.mpp_get = NULL,				\
-		.mpp_set = NULL,				\
-		.mpp_gpio_req = NULL,				\
-		.mpp_gpio_dir = NULL,				\
-	}
-
 #define MPP_FUNC_CTRL(_idl, _idh, _name, _func)			\
 	{							\
 		.name = _name,					\
@@ -186,6 +173,34 @@ struct mvebu_pinctrl_soc_info {
 		.npins = _npins,				\
 	}
 
+#define MVEBU_MPPS_PER_REG	8
+#define MVEBU_MPP_BITS		4
+#define MVEBU_MPP_MASK		0xf
+
+static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
+				       unsigned long *config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+
+	*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;
+
+	return 0;
+}
+
+static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
+				       unsigned long config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned long reg;
+
+	reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
+	writel(reg | (config << shift), base + off);
+
+	return 0;
+}
+
 int mvebu_pinctrl_probe(struct platform_device *pdev);
 int mvebu_pinctrl_remove(struct platform_device *pdev);
 
diff --git a/drivers/pinctrl/pinctrl-adi2-bf54x.c b/drivers/pinctrl/pinctrl-adi2-bf54x.c
index ea9d9ab9cda1..008a29e92e56 100644
--- a/drivers/pinctrl/pinctrl-adi2-bf54x.c
+++ b/drivers/pinctrl/pinctrl-adi2-bf54x.c
@@ -309,39 +309,6 @@ static const unsigned keys_8x8_pins[] = {
 	GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7,
 };
 
-static const struct adi_pin_group adi_pin_groups[] = {
-	ADI_PIN_GROUP("uart0grp", uart0_pins),
-	ADI_PIN_GROUP("uart1grp", uart1_pins),
-	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
-	ADI_PIN_GROUP("uart2grp", uart2_pins),
-	ADI_PIN_GROUP("uart3grp", uart3_pins),
-	ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins),
-	ADI_PIN_GROUP("rsi0grp", rsi0_pins),
-	ADI_PIN_GROUP("spi0grp", spi0_pins),
-	ADI_PIN_GROUP("spi1grp", spi1_pins),
-	ADI_PIN_GROUP("twi0grp", twi0_pins),
-	ADI_PIN_GROUP("twi1grp", twi1_pins),
-	ADI_PIN_GROUP("rotarygrp", rotary_pins),
-	ADI_PIN_GROUP("can0grp", can0_pins),
-	ADI_PIN_GROUP("can1grp", can1_pins),
-	ADI_PIN_GROUP("smc0grp", smc0_pins),
-	ADI_PIN_GROUP("sport0grp", sport0_pins),
-	ADI_PIN_GROUP("sport1grp", sport1_pins),
-	ADI_PIN_GROUP("sport2grp", sport2_pins),
-	ADI_PIN_GROUP("sport3grp", sport3_pins),
-	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
-	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
-	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
-	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
-	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
-	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
-	ADI_PIN_GROUP("atapigrp", atapi_pins),
-	ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins),
-	ADI_PIN_GROUP("nfc0grp", nfc0_pins),
-	ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins),
-	ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins),
-};
-
 static const unsigned short uart0_mux[] = {
 	P_UART0_TX, P_UART0_RX,
 	0
@@ -513,6 +480,39 @@ static const unsigned short keys_8x8_mux[] = {
 	0
 };
 
+static const struct adi_pin_group adi_pin_groups[] = {
+	ADI_PIN_GROUP("uart0grp", uart0_pins, uart0_mux),
+	ADI_PIN_GROUP("uart1grp", uart1_pins, uart1_mux),
+	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins, uart1_ctsrts_mux),
+	ADI_PIN_GROUP("uart2grp", uart2_pins, uart2_mux),
+	ADI_PIN_GROUP("uart3grp", uart3_pins, uart3_mux),
+	ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins, uart3_ctsrts_mux),
+	ADI_PIN_GROUP("rsi0grp", rsi0_pins, rsi0_mux),
+	ADI_PIN_GROUP("spi0grp", spi0_pins, spi0_mux),
+	ADI_PIN_GROUP("spi1grp", spi1_pins, spi1_mux),
+	ADI_PIN_GROUP("twi0grp", twi0_pins, twi0_mux),
+	ADI_PIN_GROUP("twi1grp", twi1_pins, twi1_mux),
+	ADI_PIN_GROUP("rotarygrp", rotary_pins, rotary_mux),
+	ADI_PIN_GROUP("can0grp", can0_pins, can0_mux),
+	ADI_PIN_GROUP("can1grp", can1_pins, can1_mux),
+	ADI_PIN_GROUP("smc0grp", smc0_pins, smc0_mux),
+	ADI_PIN_GROUP("sport0grp", sport0_pins, sport0_mux),
+	ADI_PIN_GROUP("sport1grp", sport1_pins, sport1_mux),
+	ADI_PIN_GROUP("sport2grp", sport2_pins, sport2_mux),
+	ADI_PIN_GROUP("sport3grp", sport3_pins, sport3_mux),
+	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins, ppi0_8b_mux),
+	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins, ppi0_16b_mux),
+	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins, ppi0_24b_mux),
+	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins, ppi1_8b_mux),
+	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins, ppi1_16b_mux),
+	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins, ppi2_8b_mux),
+	ADI_PIN_GROUP("atapigrp", atapi_pins, atapi_mux),
+	ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins, atapi_alter_mux),
+	ADI_PIN_GROUP("nfc0grp", nfc0_pins, nfc0_mux),
+	ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins, keys_4x4_mux),
+	ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins, keys_8x8_mux),
+};
+
 static const char * const uart0grp[] = { "uart0grp" };
 static const char * const uart1grp[] = { "uart1grp" };
 static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" };
@@ -532,49 +532,45 @@ static const char * const sport0grp[] = { "sport0grp" };
 static const char * const sport1grp[] = { "sport1grp" };
 static const char * const sport2grp[] = { "sport2grp" };
 static const char * const sport3grp[] = { "sport3grp" };
-static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
-static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
-static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
-static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
-static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
-static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
+static const char * const ppi0grp[] = { "ppi0_8bgrp",
+					"ppi0_16bgrp",
+					"ppi0_24bgrp" };
+static const char * const ppi1grp[] = { "ppi1_8bgrp",
+					"ppi1_16bgrp" };
+static const char * const ppi2grp[] = { "ppi2_8bgrp" };
 static const char * const atapigrp[] = { "atapigrp" };
 static const char * const atapialtergrp[] = { "atapialtergrp" };
 static const char * const nfc0grp[] = { "nfc0grp" };
-static const char * const keys_4x4grp[] = { "keys_4x4grp" };
-static const char * const keys_8x8grp[] = { "keys_8x8grp" };
+static const char * const keysgrp[] = { "keys_4x4grp",
+					"keys_8x8grp" };
 
 static const struct adi_pmx_func adi_pmx_functions[] = {
-	ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
-	ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
-	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
-	ADI_PMX_FUNCTION("uart2", uart2grp, uart2_mux),
-	ADI_PMX_FUNCTION("uart3", uart3grp, uart3_mux),
-	ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp, uart3_ctsrts_mux),
-	ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
-	ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
-	ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
-	ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
-	ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
-	ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
-	ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
-	ADI_PMX_FUNCTION("can1", can1grp, can1_mux),
-	ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
-	ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
-	ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
-	ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
-	ADI_PMX_FUNCTION("sport3", sport3grp, sport3_mux),
-	ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
-	ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
-	ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
-	ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
-	ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
-	ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
-	ADI_PMX_FUNCTION("atapi", atapigrp, atapi_mux),
-	ADI_PMX_FUNCTION("atapi_alter", atapialtergrp, atapi_alter_mux),
-	ADI_PMX_FUNCTION("nfc0", nfc0grp, nfc0_mux),
-	ADI_PMX_FUNCTION("keys_4x4", keys_4x4grp, keys_4x4_mux),
-	ADI_PMX_FUNCTION("keys_8x8", keys_8x8grp, keys_8x8_mux),
+	ADI_PMX_FUNCTION("uart0", uart0grp),
+	ADI_PMX_FUNCTION("uart1", uart1grp),
+	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp),
+	ADI_PMX_FUNCTION("uart2", uart2grp),
+	ADI_PMX_FUNCTION("uart3", uart3grp),
+	ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp),
+	ADI_PMX_FUNCTION("rsi0", rsi0grp),
+	ADI_PMX_FUNCTION("spi0", spi0grp),
+	ADI_PMX_FUNCTION("spi1", spi1grp),
+	ADI_PMX_FUNCTION("twi0", twi0grp),
+	ADI_PMX_FUNCTION("twi1", twi1grp),
+	ADI_PMX_FUNCTION("rotary", rotarygrp),
+	ADI_PMX_FUNCTION("can0", can0grp),
+	ADI_PMX_FUNCTION("can1", can1grp),
+	ADI_PMX_FUNCTION("smc0", smc0grp),
+	ADI_PMX_FUNCTION("sport0", sport0grp),
+	ADI_PMX_FUNCTION("sport1", sport1grp),
+	ADI_PMX_FUNCTION("sport2", sport2grp),
+	ADI_PMX_FUNCTION("sport3", sport3grp),
+	ADI_PMX_FUNCTION("ppi0", ppi0grp),
+	ADI_PMX_FUNCTION("ppi1", ppi1grp),
+	ADI_PMX_FUNCTION("ppi2", ppi2grp),
+	ADI_PMX_FUNCTION("atapi", atapigrp),
+	ADI_PMX_FUNCTION("atapi_alter", atapialtergrp),
+	ADI_PMX_FUNCTION("nfc0", nfc0grp),
+	ADI_PMX_FUNCTION("keys", keysgrp),
 };
 
 static const struct adi_pinctrl_soc_data adi_bf54x_soc = {
diff --git a/drivers/pinctrl/pinctrl-adi2-bf60x.c b/drivers/pinctrl/pinctrl-adi2-bf60x.c
index bf57aea2826c..4cb59fe9be70 100644
--- a/drivers/pinctrl/pinctrl-adi2-bf60x.c
+++ b/drivers/pinctrl/pinctrl-adi2-bf60x.c
@@ -259,37 +259,6 @@ static const unsigned lp3_pins[] = {
 	GPIO_PF12, GPIO_PF13, GPIO_PF14, GPIO_PF15,
 };
 
-static const struct adi_pin_group adi_pin_groups[] = {
-	ADI_PIN_GROUP("uart0grp", uart0_pins),
-	ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins),
-	ADI_PIN_GROUP("uart1grp", uart1_pins),
-	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
-	ADI_PIN_GROUP("rsi0grp", rsi0_pins),
-	ADI_PIN_GROUP("eth0grp", eth0_pins),
-	ADI_PIN_GROUP("eth1grp", eth1_pins),
-	ADI_PIN_GROUP("spi0grp", spi0_pins),
-	ADI_PIN_GROUP("spi1grp", spi1_pins),
-	ADI_PIN_GROUP("twi0grp", twi0_pins),
-	ADI_PIN_GROUP("twi1grp", twi1_pins),
-	ADI_PIN_GROUP("rotarygrp", rotary_pins),
-	ADI_PIN_GROUP("can0grp", can0_pins),
-	ADI_PIN_GROUP("smc0grp", smc0_pins),
-	ADI_PIN_GROUP("sport0grp", sport0_pins),
-	ADI_PIN_GROUP("sport1grp", sport1_pins),
-	ADI_PIN_GROUP("sport2grp", sport2_pins),
-	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
-	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
-	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
-	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
-	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
-	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
-	ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins),
-	ADI_PIN_GROUP("lp0grp", lp0_pins),
-	ADI_PIN_GROUP("lp1grp", lp1_pins),
-	ADI_PIN_GROUP("lp2grp", lp2_pins),
-	ADI_PIN_GROUP("lp3grp", lp3_pins),
-};
-
 static const unsigned short uart0_mux[] = {
 	P_UART0_TX, P_UART0_RX,
 	0
@@ -446,6 +415,37 @@ static const unsigned short lp3_mux[] = {
         0
 };
 
+static const struct adi_pin_group adi_pin_groups[] = {
+	ADI_PIN_GROUP("uart0grp", uart0_pins, uart0_mux),
+	ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins, uart0_ctsrts_mux),
+	ADI_PIN_GROUP("uart1grp", uart1_pins, uart1_mux),
+	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins, uart1_ctsrts_mux),
+	ADI_PIN_GROUP("rsi0grp", rsi0_pins, rsi0_mux),
+	ADI_PIN_GROUP("eth0grp", eth0_pins, eth0_mux),
+	ADI_PIN_GROUP("eth1grp", eth1_pins, eth1_mux),
+	ADI_PIN_GROUP("spi0grp", spi0_pins, spi0_mux),
+	ADI_PIN_GROUP("spi1grp", spi1_pins, spi1_mux),
+	ADI_PIN_GROUP("twi0grp", twi0_pins, twi0_mux),
+	ADI_PIN_GROUP("twi1grp", twi1_pins, twi1_mux),
+	ADI_PIN_GROUP("rotarygrp", rotary_pins, rotary_mux),
+	ADI_PIN_GROUP("can0grp", can0_pins, can0_mux),
+	ADI_PIN_GROUP("smc0grp", smc0_pins, smc0_mux),
+	ADI_PIN_GROUP("sport0grp", sport0_pins, sport0_mux),
+	ADI_PIN_GROUP("sport1grp", sport1_pins, sport1_mux),
+	ADI_PIN_GROUP("sport2grp", sport2_pins, sport2_mux),
+	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins, ppi0_8b_mux),
+	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins, ppi0_16b_mux),
+	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins, ppi0_24b_mux),
+	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins, ppi1_8b_mux),
+	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins, ppi1_16b_mux),
+	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins, ppi2_8b_mux),
+	ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins, ppi2_16b_mux),
+	ADI_PIN_GROUP("lp0grp", lp0_pins, lp0_mux),
+	ADI_PIN_GROUP("lp1grp", lp1_pins, lp1_mux),
+	ADI_PIN_GROUP("lp2grp", lp2_pins, lp2_mux),
+	ADI_PIN_GROUP("lp3grp", lp3_pins, lp3_mux),
+};
+
 static const char * const uart0grp[] = { "uart0grp" };
 static const char * const uart0ctsrtsgrp[] = { "uart0ctsrtsgrp" };
 static const char * const uart1grp[] = { "uart1grp" };
@@ -463,47 +463,43 @@ static const char * const smc0grp[] = { "smc0grp" };
 static const char * const sport0grp[] = { "sport0grp" };
 static const char * const sport1grp[] = { "sport1grp" };
 static const char * const sport2grp[] = { "sport2grp" };
-static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
-static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
-static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
-static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
-static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
-static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
-static const char * const ppi2_16bgrp[] = { "ppi2_16bgrp" };
+static const char * const ppi0grp[] = { "ppi0_8bgrp",
+					"ppi0_16bgrp",
+					"ppi0_24bgrp" };
+static const char * const ppi1grp[] = { "ppi1_8bgrp",
+					"ppi1_16bgrp" };
+static const char * const ppi2grp[] = { "ppi2_8bgrp",
+					"ppi2_16bgrp" };
 static const char * const lp0grp[] = { "lp0grp" };
 static const char * const lp1grp[] = { "lp1grp" };
 static const char * const lp2grp[] = { "lp2grp" };
 static const char * const lp3grp[] = { "lp3grp" };
 
 static const struct adi_pmx_func adi_pmx_functions[] = {
-	ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
-	ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp, uart0_ctsrts_mux),
-	ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
-	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
-	ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
-	ADI_PMX_FUNCTION("eth0", eth0grp, eth0_mux),
-	ADI_PMX_FUNCTION("eth1", eth1grp, eth1_mux),
-	ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
-	ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
-	ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
-	ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
-	ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
-	ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
-	ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
-	ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
-	ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
-	ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
-	ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
-	ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
-	ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
-	ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
-	ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
-	ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
-	ADI_PMX_FUNCTION("ppi2_16b", ppi2_16bgrp, ppi2_16b_mux),
-	ADI_PMX_FUNCTION("lp0", lp0grp, lp0_mux),
-	ADI_PMX_FUNCTION("lp1", lp1grp, lp1_mux),
-	ADI_PMX_FUNCTION("lp2", lp2grp, lp2_mux),
-	ADI_PMX_FUNCTION("lp3", lp3grp, lp3_mux),
+	ADI_PMX_FUNCTION("uart0", uart0grp),
+	ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp),
+	ADI_PMX_FUNCTION("uart1", uart1grp),
+	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp),
+	ADI_PMX_FUNCTION("rsi0", rsi0grp),
+	ADI_PMX_FUNCTION("eth0", eth0grp),
+	ADI_PMX_FUNCTION("eth1", eth1grp),
+	ADI_PMX_FUNCTION("spi0", spi0grp),
+	ADI_PMX_FUNCTION("spi1", spi1grp),
+	ADI_PMX_FUNCTION("twi0", twi0grp),
+	ADI_PMX_FUNCTION("twi1", twi1grp),
+	ADI_PMX_FUNCTION("rotary", rotarygrp),
+	ADI_PMX_FUNCTION("can0", can0grp),
+	ADI_PMX_FUNCTION("smc0", smc0grp),
+	ADI_PMX_FUNCTION("sport0", sport0grp),
+	ADI_PMX_FUNCTION("sport1", sport1grp),
+	ADI_PMX_FUNCTION("sport2", sport2grp),
+	ADI_PMX_FUNCTION("ppi0", ppi0grp),
+	ADI_PMX_FUNCTION("ppi1", ppi1grp),
+	ADI_PMX_FUNCTION("ppi2", ppi2grp),
+	ADI_PMX_FUNCTION("lp0", lp0grp),
+	ADI_PMX_FUNCTION("lp1", lp1grp),
+	ADI_PMX_FUNCTION("lp2", lp2grp),
+	ADI_PMX_FUNCTION("lp3", lp3grp),
 };
 
 static const struct adi_pinctrl_soc_data adi_bf60x_soc = {
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 7a39562c3e42..200ea1e72d40 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -89,6 +89,19 @@ struct gpio_port_saved {
 	u32 mux;
 };
 
+/*
+ * struct gpio_pint_saved - PINT registers saved in PM operations
+ *
+ * @assign: ASSIGN register
+ * @edge_set: EDGE_SET register
+ * @invert_set: INVERT_SET register
+ */
+struct gpio_pint_saved {
+	u32 assign;
+	u32 edge_set;
+	u32 invert_set;
+};
+
 /**
  * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO
  * banks can be mapped into one Pin interrupt controller.
@@ -114,7 +127,7 @@ struct gpio_pint {
 	int irq;
 	struct irq_domain *domain[2];
 	struct gpio_pint_regs *regs;
-	struct adi_pm_pint_save saved_data;
+	struct gpio_pint_saved saved_data;
 	int map_count;
 	spinlock_t lock;
 
@@ -160,7 +173,7 @@ struct adi_pinctrl {
 struct gpio_port {
 	struct list_head node;
 	void __iomem *base;
-	unsigned int irq_base;
+	int irq_base;
 	unsigned int width;
 	struct gpio_port_t *regs;
 	struct gpio_port_saved saved_data;
@@ -605,8 +618,8 @@ static struct pinctrl_ops adi_pctrl_ops = {
 	.get_group_pins = adi_get_group_pins,
 };
 
-static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
-	unsigned group)
+static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned func_id,
+	unsigned group_id)
 {
 	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
 	struct gpio_port *port;
@@ -614,7 +627,7 @@ static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	unsigned long flags;
 	unsigned short *mux, pin;
 
-	mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+	mux = (unsigned short *)pinctrl->soc->groups[group_id].mux;
 
 	while (*mux) {
 		pin = P_IDENT(*mux);
@@ -628,7 +641,7 @@ static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
 		spin_lock_irqsave(&port->lock, flags);
 
 		portmux_setup(port, pin_to_offset(range, pin),
-				 P_FUNCT2MUX(*mux));
+				P_FUNCT2MUX(*mux));
 		port_setup(port, pin_to_offset(range, pin), false);
 		mux++;
 
@@ -638,8 +651,8 @@ static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	return 0;
 }
 
-static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned selector,
-	unsigned group)
+static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned func_id,
+	unsigned group_id)
 {
 	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
 	struct gpio_port *port;
@@ -647,7 +660,7 @@ static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned selector,
 	unsigned long flags;
 	unsigned short *mux, pin;
 
-	mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+	mux = (unsigned short *)pinctrl->soc->groups[group_id].mux;
 
 	while (*mux) {
 		pin = P_IDENT(*mux);
diff --git a/drivers/pinctrl/pinctrl-adi2.h b/drivers/pinctrl/pinctrl-adi2.h
index 1f06f8df1fa3..3ca29738213f 100644
--- a/drivers/pinctrl/pinctrl-adi2.h
+++ b/drivers/pinctrl/pinctrl-adi2.h
@@ -21,13 +21,15 @@ struct adi_pin_group {
 	const char *name;
 	const unsigned *pins;
 	const unsigned num;
+	const unsigned short *mux;
 };
 
-#define ADI_PIN_GROUP(n, p)  \
+#define ADI_PIN_GROUP(n, p, m)  \
 	{			\
 		.name = n,	\
 		.pins = p,	\
 		.num = ARRAY_SIZE(p),	\
+		.mux = m,			\
 	}
 
  /**
@@ -41,15 +43,13 @@ struct adi_pmx_func {
 	const char *name;
 	const char * const *groups;
 	const unsigned num_groups;
-	const unsigned short *mux;
 };
 
-#define ADI_PMX_FUNCTION(n, g, m)		\
+#define ADI_PMX_FUNCTION(n, g)		\
 	{					\
 		.name = n,			\
 		.groups = g,			\
 		.num_groups = ARRAY_SIZE(g),	\
-		.mux = m,			\
 	}
 
 /**
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index d990e33d8aa7..5d24aaec5dbc 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1137,6 +1137,17 @@ static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
 	pinctrl_free_gpio(gpio);
 }
 
+static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 osr;
+
+	osr = readl_relaxed(pio + PIO_OSR);
+	return !(osr & mask);
+}
+
 static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
@@ -1325,6 +1336,31 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
 	return 0;
 }
 
+static unsigned int gpio_irq_startup(struct irq_data *d)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	unsigned	pin = d->hwirq;
+	int ret;
+
+	ret = gpio_lock_as_irq(&at91_gpio->chip, pin);
+	if (ret) {
+		dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
+			d->hwirq);
+		return ret;
+	}
+	gpio_irq_unmask(d);
+	return 0;
+}
+
+static void gpio_irq_shutdown(struct irq_data *d)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	unsigned	pin = d->hwirq;
+
+	gpio_irq_mask(d);
+	gpio_unlock_as_irq(&at91_gpio->chip, pin);
+}
+
 #ifdef CONFIG_PM
 
 static u32 wakeups[MAX_GPIO_BANKS];
@@ -1399,6 +1435,8 @@ void at91_pinctrl_gpio_resume(void)
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "GPIO",
+	.irq_startup	= gpio_irq_startup,
+	.irq_shutdown	= gpio_irq_shutdown,
 	.irq_disable	= gpio_irq_mask,
 	.irq_mask	= gpio_irq_mask,
 	.irq_unmask	= gpio_irq_unmask,
@@ -1543,6 +1581,7 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
 static struct gpio_chip at91_gpio_template = {
 	.request		= at91_gpio_request,
 	.free			= at91_gpio_free,
+	.get_direction		= at91_gpio_get_direction,
 	.direction_input	= at91_gpio_direction_input,
 	.get			= at91_gpio_get,
 	.direction_output	= at91_gpio_direction_output,
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 155b1b3a0e7a..07c81306f2f3 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -1042,6 +1042,88 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
 	},
 };
 
+/* pin banks of exynos5260 pin-controller 0 */
+static struct samsung_pin_bank exynos5260_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpb1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(5, 0x0a0, "gpb2", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpb3", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpb4", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpb5", 0x20),
+	EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpd1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(5, 0x160, "gpd2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpe0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(5, 0x1a0, "gpe1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(4, 0x1c0, "gpf0", 0x38),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1e0, "gpf1", 0x3c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x200, "gpk0", 0x40),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5260 pin-controller 1 */
+static struct samsung_pin_bank exynos5260_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpc0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpc1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpc4", 0x10),
+};
+
+/* pin banks of exynos5260 pin-controller 2 */
+static struct samsung_pin_bank exynos5260_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5260 SoC. Exynos5260 SoC includes
+ * three gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5260_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos5260_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks0),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
+		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
+		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.label		= "exynos5260-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos5260_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks1),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5260-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos5260_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks2),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5260-gpio-ctrl2",
+	},
+};
+
 /* pin banks of exynos5420 pin-controller 0 */
 static struct samsung_pin_bank exynos5420_pin_banks0[] = {
 	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00),
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 4779b8e0eee8..e118fb121e02 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -491,7 +491,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
 			pin->mux_mode |= IOMUXC_CONFIG_SION;
 		pin->config = config & ~IMX_PAD_SION;
 
-		dev_dbg(info->dev, "%s: %d 0x%08lx", info->pins[i].name,
+		dev_dbg(info->dev, "%s: %d 0x%08lx", info->pins[pin_id].name,
 				pin->mux_mode, pin->config);
 	}
 
diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c
index ef2bf3126da6..2cfb1d4e4395 100644
--- a/drivers/pinctrl/pinctrl-msm.c
+++ b/drivers/pinctrl/pinctrl-msm.c
@@ -228,6 +228,11 @@ static int msm_config_reg(struct msm_pinctrl *pctrl,
 		*bit = g->drv_bit;
 		*mask = 7;
 		break;
+	case PIN_CONFIG_OUTPUT:
+		*reg = g->ctl_reg;
+		*bit = g->oe_bit;
+		*mask = 1;
+		break;
 	default:
 		dev_err(pctrl->dev, "Invalid config param %04x\n", param);
 		return -ENOTSUPP;
@@ -301,6 +306,14 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
 	case PIN_CONFIG_DRIVE_STRENGTH:
 		arg = msm_regval_to_drive[arg];
 		break;
+	case PIN_CONFIG_OUTPUT:
+		/* Pin is not output */
+		if (!arg)
+			return -EINVAL;
+
+		val = readl(pctrl->regs + g->io_reg);
+		arg = !!(val & BIT(g->in_bit));
+		break;
 	default:
 		dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
 			param);
@@ -357,6 +370,20 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
 			else
 				arg = msm_drive_to_regval[arg];
 			break;
+		case PIN_CONFIG_OUTPUT:
+			/* set output value */
+			spin_lock_irqsave(&pctrl->lock, flags);
+			val = readl(pctrl->regs + g->io_reg);
+			if (arg)
+				val |= BIT(g->out_bit);
+			else
+				val &= ~BIT(g->out_bit);
+			writel(val, pctrl->regs + g->io_reg);
+			spin_unlock_irqrestore(&pctrl->lock, flags);
+
+			/* enable output */
+			arg = 1;
+			break;
 		default:
 			dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
 				param);
diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c
index f944bf2172ef..9aeeb384ddf7 100644
--- a/drivers/pinctrl/pinctrl-msm8x74.c
+++ b/drivers/pinctrl/pinctrl-msm8x74.c
@@ -406,6 +406,7 @@ enum msm8x74_functions {
 	MSM_MUX_blsp_i2c6,
 	MSM_MUX_blsp_i2c11,
 	MSM_MUX_blsp_spi1,
+	MSM_MUX_blsp_spi8,
 	MSM_MUX_blsp_uart2,
 	MSM_MUX_blsp_uart8,
 	MSM_MUX_slimbus,
@@ -416,6 +417,9 @@ static const char * const blsp_i2c2_groups[] = { "gpio6", "gpio7" };
 static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" };
 static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" };
 static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3" };
+static const char * const blsp_spi8_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48"
+};
 static const char * const blsp_uart2_groups[] = { "gpio4", "gpio5" };
 static const char * const blsp_uart8_groups[] = { "gpio45", "gpio46" };
 static const char * const slimbus_groups[] = { "gpio70", "gpio71" };
@@ -425,6 +429,7 @@ static const struct msm_function msm8x74_functions[] = {
 	FUNCTION(blsp_i2c6),
 	FUNCTION(blsp_i2c11),
 	FUNCTION(blsp_spi1),
+	FUNCTION(blsp_spi8),
 	FUNCTION(blsp_uart2),
 	FUNCTION(blsp_uart8),
 	FUNCTION(slimbus),
@@ -476,10 +481,10 @@ static const struct msm_pingroup msm8x74_groups[] = {
 	PINGROUP(42,  NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(43,  NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(44,  NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(45,  NA, blsp_uart8, NA, NA, NA, NA, NA),
-	PINGROUP(46,  NA, blsp_uart8, NA, NA, NA, NA, NA),
-	PINGROUP(47,  NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(48,  NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(45,  blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA),
+	PINGROUP(46,  blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA),
+	PINGROUP(47,  blsp_spi8, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48,  blsp_spi8, NA, NA, NA, NA, NA, NA),
 	PINGROUP(49,  NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(50,  NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(51,  NA, NA, NA, NA, NA, NA, NA),
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 53a11114927f..cec7762cf335 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -2035,27 +2035,29 @@ static const struct of_device_id nmk_pinctrl_match[] = {
 	{},
 };
 
-static int nmk_pinctrl_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int nmk_pinctrl_suspend(struct device *dev)
 {
 	struct nmk_pinctrl *npct;
 
-	npct = platform_get_drvdata(pdev);
+	npct = dev_get_drvdata(dev);
 	if (!npct)
 		return -EINVAL;
 
 	return pinctrl_force_sleep(npct->pctl);
 }
 
-static int nmk_pinctrl_resume(struct platform_device *pdev)
+static int nmk_pinctrl_resume(struct device *dev)
 {
 	struct nmk_pinctrl *npct;
 
-	npct = platform_get_drvdata(pdev);
+	npct = dev_get_drvdata(dev);
 	if (!npct)
 		return -EINVAL;
 
 	return pinctrl_force_default(npct->pctl);
 }
+#endif
 
 static int nmk_pinctrl_probe(struct platform_device *pdev)
 {
@@ -2144,17 +2146,18 @@ static struct platform_driver nmk_gpio_driver = {
 	.probe = nmk_gpio_probe,
 };
 
+static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops,
+			nmk_pinctrl_suspend,
+			nmk_pinctrl_resume);
+
 static struct platform_driver nmk_pinctrl_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "pinctrl-nomadik",
 		.of_match_table = nmk_pinctrl_match,
+		.pm = &nmk_pinctrl_pm_ops,
 	},
 	.probe = nmk_pinctrl_probe,
-#ifdef CONFIG_PM
-	.suspend = nmk_pinctrl_suspend,
-	.resume = nmk_pinctrl_resume,
-#endif
 };
 
 static int __init nmk_gpio_init(void)
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 47ec2e8741e4..0324d4cb19b2 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -1120,6 +1120,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
 		.data = (void *)exynos4x12_pin_ctrl },
 	{ .compatible = "samsung,exynos5250-pinctrl",
 		.data = (void *)exynos5250_pin_ctrl },
+	{ .compatible = "samsung,exynos5260-pinctrl",
+		.data = (void *)exynos5260_pin_ctrl },
 	{ .compatible = "samsung,exynos5420-pinctrl",
 		.data = (void *)exynos5420_pin_ctrl },
 	{ .compatible = "samsung,s5pv210-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index 30622d9afa2e..bab9c2122556 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -254,6 +254,7 @@ struct samsung_pmx_func {
 extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
 extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
 extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5260_pin_ctrl[];
 extern struct samsung_pin_ctrl exynos5420_pin_ctrl[];
 extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
 extern struct samsung_pin_ctrl s3c2412_pin_ctrl[];
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index de6459628b4f..81075f2a1d3f 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -662,6 +662,7 @@ static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
 			break;
 		case PIN_CONFIG_DRIVE_STRENGTH:
 		case PIN_CONFIG_SLEW_RATE:
+		case PIN_CONFIG_LOW_POWER_MODE:
 		default:
 			*config = data;
 			break;
@@ -699,6 +700,7 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
 			case PIN_CONFIG_INPUT_SCHMITT:
 			case PIN_CONFIG_DRIVE_STRENGTH:
 			case PIN_CONFIG_SLEW_RATE:
+			case PIN_CONFIG_LOW_POWER_MODE:
 				shift = ffs(func->conf[i].mask) - 1;
 				data &= ~func->conf[i].mask;
 				data |= (arg << shift) & func->conf[i].mask;
@@ -1101,6 +1103,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
 		{ "pinctrl-single,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, },
 		{ "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
 		{ "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
+		{ "pinctrl-single,low-power-mode", PIN_CONFIG_LOW_POWER_MODE, },
 	};
 	struct pcs_conf_type prop4[] = {
 		{ "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 320c27363cc8..9fb66aa796aa 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -13,7 +13,12 @@
 #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>
 #include <linux/of_address.h>
 #include <linux/regmap.h>
@@ -266,11 +271,59 @@ struct st_pctl_group {
 	struct st_pinconf	*pin_conf;
 };
 
+/*
+ * Edge triggers are not supported at hardware level, it is supported by
+ * software by exploiting the level trigger support in hardware.
+ * Software uses a virtual register (EDGE_CONF) for edge trigger configuration
+ * of each gpio pin in a GPIO bank.
+ *
+ * Each bank has a 32 bit EDGE_CONF register which is divided in to 8 parts of
+ * 4-bits. Each 4-bit space is allocated for each pin in a gpio bank.
+ *
+ * bit allocation per pin is:
+ * Bits:  [0 - 3] | [4 - 7]  [8 - 11] ... ... ... ...  [ 28 - 31]
+ *       --------------------------------------------------------
+ *       |  pin-0  |  pin-2 | pin-3  | ... ... ... ... | pin -7 |
+ *       --------------------------------------------------------
+ *
+ *  A pin can have one of following the values in its edge configuration field.
+ *
+ *	-------   ----------------------------
+ *	[0-3]	- Description
+ *	-------   ----------------------------
+ *	0000	- No edge IRQ.
+ *	0001	- Falling edge IRQ.
+ *	0010	- Rising edge IRQ.
+ *	0011	- Rising and Falling edge IRQ.
+ *	-------   ----------------------------
+ */
+
+#define ST_IRQ_EDGE_CONF_BITS_PER_PIN	4
+#define ST_IRQ_EDGE_MASK		0xf
+#define ST_IRQ_EDGE_FALLING		BIT(0)
+#define ST_IRQ_EDGE_RISING		BIT(1)
+#define ST_IRQ_EDGE_BOTH		(BIT(0) | BIT(1))
+
+#define ST_IRQ_RISING_EDGE_CONF(pin) \
+	(ST_IRQ_EDGE_RISING << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN))
+
+#define ST_IRQ_FALLING_EDGE_CONF(pin) \
+	(ST_IRQ_EDGE_FALLING << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN))
+
+#define ST_IRQ_BOTH_EDGE_CONF(pin) \
+	(ST_IRQ_EDGE_BOTH << (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN))
+
+#define ST_IRQ_EDGE_CONF(conf, pin) \
+	(conf >> (pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN) & ST_IRQ_EDGE_MASK)
+
 struct st_gpio_bank {
 	struct gpio_chip		gpio_chip;
 	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;
 };
 
 struct st_pinctrl {
@@ -284,6 +337,7 @@ struct st_pinctrl {
 	int				ngroups;
 	struct regmap			*regmap;
 	const struct st_pctl_data	*data;
+	void __iomem			*irqmux_base;
 };
 
 /* SOC specific data */
@@ -1200,6 +1254,194 @@ 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);
+
+	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);
+
+	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);
+	unsigned long flags;
+	int comp, pin = d->hwirq;
+	u32 val;
+	u32 pin_edge_conf = 0;
+
+	switch (type) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		comp = 0;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		comp = 0;
+		pin_edge_conf = ST_IRQ_FALLING_EDGE_CONF(pin);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		comp = 1;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		comp = 1;
+		pin_edge_conf = ST_IRQ_RISING_EDGE_CONF(pin);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		comp = st_gpio_get(&bank->gpio_chip, pin);
+		pin_edge_conf = ST_IRQ_BOTH_EDGE_CONF(pin);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&bank->lock, flags);
+	bank->irq_edge_conf &=  ~(ST_IRQ_EDGE_MASK << (
+				pin * ST_IRQ_EDGE_CONF_BITS_PER_PIN));
+	bank->irq_edge_conf |= pin_edge_conf;
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	val = readl(bank->base + REG_PIO_PCOMP);
+	val &= ~BIT(pin);
+	val |= (comp << pin);
+	writel(val, bank->base + REG_PIO_PCOMP);
+
+	return 0;
+}
+
+/*
+ * As edge triggers are not supported at hardware level, it is supported by
+ * software by exploiting the level trigger support in hardware.
+ *
+ * Steps for detection raising edge interrupt in software.
+ *
+ * Step 1: CONFIGURE pin to detect level LOW interrupts.
+ *
+ * Step 2: DETECT level LOW interrupt and in irqmux/gpio bank interrupt handler,
+ * if the value of pin is low, then CONFIGURE pin for level HIGH interrupt.
+ * IGNORE calling the actual interrupt handler for the pin at this stage.
+ *
+ * Step 3: DETECT level HIGH interrupt and in irqmux/gpio-bank interrupt handler
+ * if the value of pin is HIGH, CONFIGURE pin for level LOW interrupt and then
+ * DISPATCH the interrupt to the interrupt handler of the pin.
+ *
+ *		 step-1  ________     __________
+ *				|     | step - 3
+ *			        |     |
+ *			step -2 |_____|
+ *
+ * falling edge is also detected int the same way.
+ *
+ */
+static void __gpio_irq_handler(struct st_gpio_bank *bank)
+{
+	unsigned long port_in, port_mask, port_comp, active_irqs;
+	unsigned long bank_edge_mask, flags;
+	int n, val, ecfg;
+
+	spin_lock_irqsave(&bank->lock, flags);
+	bank_edge_mask = bank->irq_edge_conf;
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	for (;;) {
+		port_in = readl(bank->base + REG_PIO_PIN);
+		port_comp = readl(bank->base + REG_PIO_PCOMP);
+		port_mask = readl(bank->base + REG_PIO_PMASK);
+
+		active_irqs = (port_in ^ port_comp) & port_mask;
+
+		if (active_irqs == 0)
+			break;
+
+		for_each_set_bit(n, &active_irqs, BITS_PER_LONG) {
+			/* check if we are detecting fake edges ... */
+			ecfg = ST_IRQ_EDGE_CONF(bank_edge_mask, n);
+
+			if (ecfg) {
+				/* edge detection. */
+				val = st_gpio_get(&bank->gpio_chip, n);
+
+				writel(BIT(n),
+					val ? bank->base + REG_PIO_SET_PCOMP :
+					bank->base + REG_PIO_CLR_PCOMP);
+
+				if (ecfg != ST_IRQ_EDGE_BOTH &&
+					!((ecfg & ST_IRQ_EDGE_FALLING) ^ val))
+					continue;
+			}
+
+			generic_handle_irq(irq_find_mapping(bank->domain, n));
+		}
+	}
+}
+
+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);
+
+	chained_irq_enter(chip, desc);
+	__gpio_irq_handler(bank);
+	chained_irq_exit(chip, desc);
+}
+
+static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct st_pinctrl *info = irq_get_handler_data(irq);
+	unsigned long status;
+	int n;
+
+	chained_irq_enter(chip, desc);
+
+	status = readl(info->irqmux_base);
+
+	for_each_set_bit(n, &status, ST_GPIO_PINS_PER_BANK)
+		__gpio_irq_handler(&info->banks[n]);
+
+	chained_irq_exit(chip, desc);
+}
+
 static struct gpio_chip st_gpio_template = {
 	.request		= st_gpio_request,
 	.free			= st_gpio_free,
@@ -1210,6 +1452,34 @@ 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 = {
+	.name		= "GPIO",
+	.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,
@@ -1219,8 +1489,8 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 	struct pinctrl_gpio_range *range = &bank->range;
 	struct device *dev = info->dev;
 	int bank_num = of_alias_get_id(np, "gpio");
-	struct resource res;
-	int err;
+	struct resource res, irq_res;
+	int gpio_irq = 0, err, i;
 
 	if (of_address_to_resource(np, 0, &res))
 		return -ENODEV;
@@ -1233,6 +1503,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;
+	spin_lock_init(&bank->lock);
 
 	of_property_read_string(np, "st,bank-name", &range->name);
 	bank->gpio_chip.label = range->name;
@@ -1248,6 +1519,51 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 	}
 	dev_info(dev, "%s bank added.\n", range->name);
 
+	/**
+	 * GPIO bank can have one of the two possible types of
+	 * interrupt-wirings.
+	 *
+	 * First type is via irqmux, single interrupt is used by multiple
+	 * gpio banks. This reduces number of overall interrupts numbers
+	 * required. All these banks belong to a single pincontroller.
+	 *		  _________
+	 *		 |	   |----> [gpio-bank (n)    ]
+	 *		 |	   |----> [gpio-bank (n + 1)]
+	 *	[irqN]-- | irq-mux |----> [gpio-bank (n + 2)]
+	 *		 |	   |----> [gpio-bank (...  )]
+	 *		 |_________|----> [gpio-bank (n + 7)]
+	 *
+	 * Second type has a dedicated interrupt per each gpio bank.
+	 *
+	 *	[irqN]----> [gpio-bank (n)]
+	 */
+
+	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);
+	}
+
+	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);
+			}
+		}
+
+	} else {
+		dev_info(dev, "No IRQ support for %s bank\n", np->full_name);
+	}
+
 	return 0;
 }
 
@@ -1276,6 +1592,8 @@ static int st_pctl_probe_dt(struct platform_device *pdev,
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *child;
 	int grp_index = 0;
+	int irq = 0;
+	struct resource *res;
 
 	st_pctl_dt_child_count(info, np);
 	if (!info->nbanks) {
@@ -1306,6 +1624,21 @@ static int st_pctl_probe_dt(struct platform_device *pdev,
 	}
 	info->data = of_match_node(st_pctl_of_match, np)->data;
 
+	irq = platform_get_irq(pdev, 0);
+
+	if (irq > 0) {
+		res = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "irqmux");
+		info->irqmux_base = devm_ioremap_resource(&pdev->dev, res);
+
+		if (IS_ERR(info->irqmux_base))
+			return PTR_ERR(info->irqmux_base);
+
+		irq_set_chained_handler(irq, st_gpio_irqmux_handler);
+		irq_set_handler_data(irq, info);
+
+	}
+
 	pctl_desc->npins = info->nbanks * ST_GPIO_PINS_PER_BANK;
 	pdesc =	devm_kzalloc(&pdev->dev,
 			sizeof(*pdesc) * pctl_desc->npins, GFP_KERNEL);
diff --git a/drivers/pinctrl/pinctrl-sunxi-pins.h b/drivers/pinctrl/pinctrl-sunxi-pins.h
index 6fd8d4d95140..3d6066988a72 100644
--- a/drivers/pinctrl/pinctrl-sunxi-pins.h
+++ b/drivers/pinctrl/pinctrl-sunxi-pins.h
@@ -1932,27 +1932,27 @@ static const struct sunxi_desc_pin sun5i_a13_pins[] = {
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* D1 */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* D0 */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* CLK */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* CMD */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* D3 */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x4, "mmc0")),		/* D2 */
+		  SUNXI_FUNCTION(0x2, "mmc0")),		/* D2 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 9ccf681dad2f..f9fabe9bf47d 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -584,7 +585,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
 	spin_lock_irqsave(&pctl->lock, flags);
 
 	regval = readl(pctl->membase + reg);
-	regval &= ~IRQ_CFG_IRQ_MASK;
+	regval &= ~(IRQ_CFG_IRQ_MASK << index);
 	writel(regval | (mode << index), pctl->membase + reg);
 
 	spin_unlock_irqrestore(&pctl->lock, flags);
@@ -665,6 +666,7 @@ static struct irq_chip sunxi_pinctrl_irq_chip = {
 
 static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_get_chip(irq);
 	struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
 	const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
 
@@ -674,10 +676,12 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 	if (reg) {
 		int irqoffset;
 
+		chained_irq_enter(chip, desc);
 		for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
 			int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
 			generic_handle_irq(pin_irq);
 		}
+		chained_irq_exit(chip, desc);
 	}
 }
 
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index 01c494f8a14f..552b0e97077a 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin)
 
 static inline u32 sunxi_irq_cfg_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
+	u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
 	return reg + IRQ_CFG_REG;
 }
 
@@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
 
 static inline u32 sunxi_irq_ctrl_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
+	u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
 	return reg + IRQ_CTRL_REG;
 }
 
@@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
 
 static inline u32 sunxi_irq_status_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
+	u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
 	return reg + IRQ_STATUS_REG;
 }
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index c381ae63c508..2814440843df 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -2389,6 +2389,29 @@ static const unsigned int msiof3_tx_pins[] = {
 static const unsigned int msiof3_tx_mux[] = {
 	MSIOF3_TXD_MARK,
 };
+/* - QSPI ------------------------------------------------------------------- */
+static const unsigned int qspi_ctrl_pins[] = {
+	/* SPCLK, SSL */
+	RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 9),
+};
+static const unsigned int qspi_ctrl_mux[] = {
+	SPCLK_MARK, SSL_MARK,
+};
+static const unsigned int qspi_data2_pins[] = {
+	/* MOSI_IO0, MISO_IO1 */
+	RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int qspi_data2_mux[] = {
+	MOSI_IO0_MARK, MISO_IO1_MARK,
+};
+static const unsigned int qspi_data4_pins[] = {
+	/* MOSI_IO0, MISO_IO1, IO2, IO3 */
+	RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7),
+	RCAR_GP_PIN(1, 8),
+};
+static const unsigned int qspi_data4_mux[] = {
+	MOSI_IO0_MARK, MISO_IO1_MARK, IO2_MARK, IO3_MARK,
+};
 /* - SCIF0 ------------------------------------------------------------------ */
 static const unsigned int scif0_data_pins[] = {
 	/* RX, TX */
@@ -3231,6 +3254,13 @@ static const unsigned int usb0_pins[] = {
 static const unsigned int usb0_mux[] = {
 	USB0_PWEN_MARK, USB0_OVC_VBUS_MARK,
 };
+static const unsigned int usb0_ovc_vbus_pins[] = {
+	/* OVC/VBUS */
+	RCAR_GP_PIN(5, 19),
+};
+static const unsigned int usb0_ovc_vbus_mux[] = {
+	USB0_OVC_VBUS_MARK,
+};
 /* - USB1 ------------------------------------------------------------------- */
 static const unsigned int usb1_pins[] = {
 	/* PWEN, OVC */
@@ -3671,6 +3701,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(msiof3_ss2),
 	SH_PFC_PIN_GROUP(msiof3_rx),
 	SH_PFC_PIN_GROUP(msiof3_tx),
+	SH_PFC_PIN_GROUP(qspi_ctrl),
+	SH_PFC_PIN_GROUP(qspi_data2),
+	SH_PFC_PIN_GROUP(qspi_data4),
 	SH_PFC_PIN_GROUP(scif0_data),
 	SH_PFC_PIN_GROUP(scif0_clk),
 	SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -3789,6 +3822,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(tpu0_to2),
 	SH_PFC_PIN_GROUP(tpu0_to3),
 	SH_PFC_PIN_GROUP(usb0),
+	SH_PFC_PIN_GROUP(usb0_ovc_vbus),
 	SH_PFC_PIN_GROUP(usb1),
 	SH_PFC_PIN_GROUP(usb2),
 	VIN_DATA_PIN_GROUP(vin0_data, 24),
@@ -3970,6 +4004,12 @@ static const char * const msiof3_groups[] = {
 	"msiof3_tx",
 };
 
+static const char * const qspi_groups[] = {
+	"qspi_ctrl",
+	"qspi_data2",
+	"qspi_data4",
+};
+
 static const char * const scif0_groups[] = {
 	"scif0_data",
 	"scif0_clk",
@@ -4134,6 +4174,7 @@ static const char * const tpu0_groups[] = {
 
 static const char * const usb0_groups[] = {
 	"usb0",
+	"usb0_ovc_vbus",
 };
 
 static const char * const usb1_groups[] = {
@@ -4213,6 +4254,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(msiof1),
 	SH_PFC_FUNCTION(msiof2),
 	SH_PFC_FUNCTION(msiof3),
+	SH_PFC_FUNCTION(qspi),
 	SH_PFC_FUNCTION(scif0),
 	SH_PFC_FUNCTION(scif1),
 	SH_PFC_FUNCTION(scif2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 77d103fe39d9..7ac8d7fca91b 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -1943,6 +1943,50 @@ static const unsigned int i2c4_c_pins[] = {
 static const unsigned int i2c4_c_mux[] = {
 	SCL4_C_MARK, SDA4_C_MARK,
 };
+/* - I2C7 ------------------------------------------------------------------- */
+static const unsigned int i2c7_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 16),
+};
+static const unsigned int i2c7_mux[] = {
+	SCL7_MARK, SDA7_MARK,
+};
+static const unsigned int i2c7_b_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int i2c7_b_mux[] = {
+	SCL7_B_MARK, SDA7_B_MARK,
+};
+static const unsigned int i2c7_c_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(6, 28), RCAR_GP_PIN(6, 29),
+};
+static const unsigned int i2c7_c_mux[] = {
+	SCL7_C_MARK, SDA7_C_MARK,
+};
+/* - I2C8 ------------------------------------------------------------------- */
+static const unsigned int i2c8_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(4, 13), RCAR_GP_PIN(4, 14),
+};
+static const unsigned int i2c8_mux[] = {
+	SCL8_MARK, SDA8_MARK,
+};
+static const unsigned int i2c8_b_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
+};
+static const unsigned int i2c8_b_mux[] = {
+	SCL8_B_MARK, SDA8_B_MARK,
+};
+static const unsigned int i2c8_c_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(6, 22), RCAR_GP_PIN(6, 23),
+};
+static const unsigned int i2c8_c_mux[] = {
+	SCL8_C_MARK, SDA8_C_MARK,
+};
 /* - INTC ------------------------------------------------------------------- */
 static const unsigned int intc_irq0_pins[] = {
 	/* IRQ */
@@ -2135,6 +2179,53 @@ static const unsigned int msiof2_tx_pins[] = {
 static const unsigned int msiof2_tx_mux[] = {
 	MSIOF2_TXD_MARK,
 };
+/* - QSPI ------------------------------------------------------------------- */
+static const unsigned int qspi_ctrl_pins[] = {
+	/* SPCLK, SSL */
+	RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 9),
+};
+static const unsigned int qspi_ctrl_mux[] = {
+	SPCLK_MARK, SSL_MARK,
+};
+static const unsigned int qspi_data2_pins[] = {
+	/* MOSI_IO0, MISO_IO1 */
+	RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int qspi_data2_mux[] = {
+	MOSI_IO0_MARK, MISO_IO1_MARK,
+};
+static const unsigned int qspi_data4_pins[] = {
+	/* MOSI_IO0, MISO_IO1, IO2, IO3 */
+	RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7),
+	RCAR_GP_PIN(1, 8),
+};
+static const unsigned int qspi_data4_mux[] = {
+	MOSI_IO0_MARK, MISO_IO1_MARK, IO2_MARK, IO3_MARK,
+};
+
+static const unsigned int qspi_ctrl_b_pins[] = {
+	/* SPCLK, SSL */
+	RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 5),
+};
+static const unsigned int qspi_ctrl_b_mux[] = {
+	SPCLK_B_MARK, SSL_B_MARK,
+};
+static const unsigned int qspi_data2_b_pins[] = {
+	/* MOSI_IO0, MISO_IO1 */
+	RCAR_GP_PIN(6, 1), RCAR_GP_PIN(6, 2),
+};
+static const unsigned int qspi_data2_b_mux[] = {
+	MOSI_IO0_B_MARK, MISO_IO1_B_MARK,
+};
+static const unsigned int qspi_data4_b_pins[] = {
+	/* MOSI_IO0, MISO_IO1, IO2, IO3 */
+	RCAR_GP_PIN(6, 1), RCAR_GP_PIN(6, 2), RCAR_GP_PIN(6, 3),
+	RCAR_GP_PIN(6, 4),
+};
+static const unsigned int qspi_data4_b_mux[] = {
+	SPCLK_B_MARK, MOSI_IO0_B_MARK, MISO_IO1_B_MARK,
+	IO2_B_MARK, IO3_B_MARK, SSL_B_MARK,
+};
 /* - SCIF0 ------------------------------------------------------------------ */
 static const unsigned int scif0_data_pins[] = {
 	/* RX, TX */
@@ -3123,6 +3214,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(i2c4),
 	SH_PFC_PIN_GROUP(i2c4_b),
 	SH_PFC_PIN_GROUP(i2c4_c),
+	SH_PFC_PIN_GROUP(i2c7),
+	SH_PFC_PIN_GROUP(i2c7_b),
+	SH_PFC_PIN_GROUP(i2c7_c),
+	SH_PFC_PIN_GROUP(i2c8),
+	SH_PFC_PIN_GROUP(i2c8_b),
+	SH_PFC_PIN_GROUP(i2c8_c),
 	SH_PFC_PIN_GROUP(intc_irq0),
 	SH_PFC_PIN_GROUP(intc_irq1),
 	SH_PFC_PIN_GROUP(intc_irq2),
@@ -3149,6 +3246,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(msiof2_ss2),
 	SH_PFC_PIN_GROUP(msiof2_rx),
 	SH_PFC_PIN_GROUP(msiof2_tx),
+	SH_PFC_PIN_GROUP(qspi_ctrl),
+	SH_PFC_PIN_GROUP(qspi_data2),
+	SH_PFC_PIN_GROUP(qspi_data4),
+	SH_PFC_PIN_GROUP(qspi_ctrl_b),
+	SH_PFC_PIN_GROUP(qspi_data2_b),
+	SH_PFC_PIN_GROUP(qspi_data4_b),
 	SH_PFC_PIN_GROUP(scif0_data),
 	SH_PFC_PIN_GROUP(scif0_data_b),
 	SH_PFC_PIN_GROUP(scif0_data_c),
@@ -3335,6 +3438,18 @@ static const char * const i2c4_groups[] = {
 	"i2c4_c",
 };
 
+static const char * const i2c7_groups[] = {
+	"i2c7",
+	"i2c7_b",
+	"i2c7_c",
+};
+
+static const char * const i2c8_groups[] = {
+	"i2c8",
+	"i2c8_b",
+	"i2c8_c",
+};
+
 static const char * const intc_groups[] = {
 	"intc_irq0",
 	"intc_irq1",
@@ -3376,6 +3491,15 @@ static const char * const msiof2_groups[] = {
 	"msiof2_tx",
 };
 
+static const char * const qspi_groups[] = {
+	"qspi_ctrl",
+	"qspi_data2",
+	"qspi_data4",
+	"qspi_ctrl_b",
+	"qspi_data2_b",
+	"qspi_data4_b",
+};
+
 static const char * const scif0_groups[] = {
 	"scif0_data",
 	"scif0_data_b",
@@ -3566,11 +3690,14 @@ static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(i2c2),
 	SH_PFC_FUNCTION(i2c3),
 	SH_PFC_FUNCTION(i2c4),
+	SH_PFC_FUNCTION(i2c7),
+	SH_PFC_FUNCTION(i2c8),
 	SH_PFC_FUNCTION(intc),
 	SH_PFC_FUNCTION(mmc),
 	SH_PFC_FUNCTION(msiof0),
 	SH_PFC_FUNCTION(msiof1),
 	SH_PFC_FUNCTION(msiof2),
+	SH_PFC_FUNCTION(qspi),
 	SH_PFC_FUNCTION(scif0),
 	SH_PFC_FUNCTION(scif1),
 	SH_PFC_FUNCTION(scif2),
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas6.c b/drivers/pinctrl/sirf/pinctrl-atlas6.c
index 2b9f32065920..c4dd3d5cf9c3 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas6.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas6.c
@@ -1,7 +1,8 @@
 /*
  * pinctrl pads, groups, functions for CSR SiRFatlasVI
  *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
+ * company.
  *
  * Licensed under GPLv2 or later.
  */
@@ -529,6 +530,40 @@ static const struct sirfsoc_padmux usp0_padmux = {
 
 static const unsigned usp0_pins[] = { 51, 52, 53, 54, 55 };
 
+static const struct sirfsoc_muxmask usp0_only_utfs_muxmask[] = {
+	{
+		.group = 1,
+		.mask = BIT(19) | BIT(20) | BIT(21) | BIT(22),
+	},
+};
+
+static const struct sirfsoc_padmux usp0_only_utfs_padmux = {
+	.muxmask_counts = ARRAY_SIZE(usp0_only_utfs_muxmask),
+	.muxmask = usp0_only_utfs_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
+	.funcmask = BIT(1) | BIT(2) | BIT(6),
+	.funcval = 0,
+};
+
+static const unsigned usp0_only_utfs_pins[] = { 51, 52, 53, 54 };
+
+static const struct sirfsoc_muxmask usp0_only_urfs_muxmask[] = {
+	{
+		.group = 1,
+		.mask = BIT(19) | BIT(20) | BIT(21) | BIT(23),
+	},
+};
+
+static const struct sirfsoc_padmux usp0_only_urfs_padmux = {
+	.muxmask_counts = ARRAY_SIZE(usp0_only_urfs_muxmask),
+	.muxmask = usp0_only_urfs_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
+	.funcmask = BIT(1) | BIT(2) | BIT(9),
+	.funcval = 0,
+};
+
+static const unsigned usp0_only_urfs_pins[] = { 51, 52, 53, 55 };
+
 static const struct sirfsoc_muxmask usp0_uart_nostreamctrl_muxmask[] = {
 	{
 		.group = 1,
@@ -905,6 +940,8 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
 	SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
 	SIRFSOC_PIN_GROUP("usp0_uart_nostreamctrl_grp",
 					usp0_uart_nostreamctrl_pins),
+	SIRFSOC_PIN_GROUP("usp0_only_utfs_grp", usp0_only_utfs_pins),
+	SIRFSOC_PIN_GROUP("usp0_only_urfs_grp", usp0_only_urfs_pins),
 	SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
 	SIRFSOC_PIN_GROUP("usp1_uart_nostreamctrl_grp",
 					usp1_uart_nostreamctrl_pins),
@@ -953,6 +990,9 @@ static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
 static const char * const usp0_uart_nostreamctrl_grp[] = {
 					"usp0_uart_nostreamctrl_grp" };
 static const char * const usp0grp[] = { "usp0grp" };
+static const char * const usp0_only_utfs_grp[] = { "usp0_only_utfs_grp" };
+static const char * const usp0_only_urfs_grp[] = { "usp0_only_urfs_grp" };
+
 static const char * const usp1grp[] = { "usp1grp" };
 static const char * const usp1_uart_nostreamctrl_grp[] = {
 					"usp1_uart_nostreamctrl_grp" };
@@ -1003,6 +1043,10 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = {
 	SIRFSOC_PMX_FUNCTION("usp0_uart_nostreamctrl",
 						usp0_uart_nostreamctrl_grp,
 						usp0_uart_nostreamctrl_padmux),
+	SIRFSOC_PMX_FUNCTION("usp0_only_utfs", usp0_only_utfs_grp,
+						usp0_only_utfs_padmux),
+	SIRFSOC_PMX_FUNCTION("usp0_only_urfs", usp0_only_urfs_grp,
+						usp0_only_urfs_padmux),
 	SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
 	SIRFSOC_PMX_FUNCTION("usp1_uart_nostreamctrl",
 						usp1_uart_nostreamctrl_grp,
diff --git a/drivers/pinctrl/sirf/pinctrl-prima2.c b/drivers/pinctrl/sirf/pinctrl-prima2.c
index dde0285544d6..8aa76f0776d7 100644
--- a/drivers/pinctrl/sirf/pinctrl-prima2.c
+++ b/drivers/pinctrl/sirf/pinctrl-prima2.c
@@ -1,7 +1,8 @@
 /*
  * pinctrl pads, groups, functions for CSR SiRFprimaII
  *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
+ * company.
  *
  * Licensed under GPLv2 or later.
  */
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index a0d6152701cd..72291cd5400b 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -1,7 +1,8 @@
 /*
  * pinmux driver for CSR SiRFprimaII
  *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
+ * company.
  *
  * Licensed under GPLv2 or later.
  */
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index defb6afc1409..f21e1095b1dd 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -2321,53 +2321,55 @@ static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
 	}
 }
 
-static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
-					   struct tp_nvram_state *newn,
-					   const u32 event_mask)
-{
-
 #define TPACPI_COMPARE_KEY(__scancode, __member) \
-	do { \
-		if ((event_mask & (1 << __scancode)) && \
-		    oldn->__member != newn->__member) \
-			tpacpi_hotkey_send_key(__scancode); \
-	} while (0)
+do { \
+	if ((event_mask & (1 << __scancode)) && \
+	    oldn->__member != newn->__member) \
+		tpacpi_hotkey_send_key(__scancode); \
+} while (0)
 
 #define TPACPI_MAY_SEND_KEY(__scancode) \
-	do { \
-		if (event_mask & (1 << __scancode)) \
-			tpacpi_hotkey_send_key(__scancode); \
-	} while (0)
+do { \
+	if (event_mask & (1 << __scancode)) \
+		tpacpi_hotkey_send_key(__scancode); \
+} while (0)
 
-	void issue_volchange(const unsigned int oldvol,
-			     const unsigned int newvol)
-	{
-		unsigned int i = oldvol;
+static void issue_volchange(const unsigned int oldvol,
+			    const unsigned int newvol,
+			    const u32 event_mask)
+{
+	unsigned int i = oldvol;
 
-		while (i > newvol) {
-			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
-			i--;
-		}
-		while (i < newvol) {
-			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
-			i++;
-		}
+	while (i > newvol) {
+		TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
+		i--;
+	}
+	while (i < newvol) {
+		TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
+		i++;
 	}
+}
 
-	void issue_brightnesschange(const unsigned int oldbrt,
-				    const unsigned int newbrt)
-	{
-		unsigned int i = oldbrt;
+static void issue_brightnesschange(const unsigned int oldbrt,
+				   const unsigned int newbrt,
+				   const u32 event_mask)
+{
+	unsigned int i = oldbrt;
 
-		while (i > newbrt) {
-			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
-			i--;
-		}
-		while (i < newbrt) {
-			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
-			i++;
-		}
+	while (i > newbrt) {
+		TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND);
+		i--;
 	}
+	while (i < newbrt) {
+		TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME);
+		i++;
+	}
+}
+
+static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
+					   struct tp_nvram_state *newn,
+					   const u32 event_mask)
+{
 
 	TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle);
 	TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle);
@@ -2402,7 +2404,8 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
 		    oldn->volume_level != newn->volume_level) {
 			/* recently muted, or repeated mute keypress, or
 			 * multiple presses ending in mute */
-			issue_volchange(oldn->volume_level, newn->volume_level);
+			issue_volchange(oldn->volume_level, newn->volume_level,
+				event_mask);
 			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE);
 		}
 	} else {
@@ -2412,7 +2415,8 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
 			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
 		}
 		if (oldn->volume_level != newn->volume_level) {
-			issue_volchange(oldn->volume_level, newn->volume_level);
+			issue_volchange(oldn->volume_level, newn->volume_level,
+				event_mask);
 		} else if (oldn->volume_toggle != newn->volume_toggle) {
 			/* repeated vol up/down keypress at end of scale ? */
 			if (newn->volume_level == 0)
@@ -2425,7 +2429,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
 	/* handle brightness */
 	if (oldn->brightness_level != newn->brightness_level) {
 		issue_brightnesschange(oldn->brightness_level,
-				       newn->brightness_level);
+				       newn->brightness_level, event_mask);
 	} else if (oldn->brightness_toggle != newn->brightness_toggle) {
 		/* repeated key presses that didn't change state */
 		if (newn->brightness_level == 0)
@@ -6776,8 +6780,9 @@ static int __init volume_create_alsa_mixer(void)
 	struct snd_kcontrol *ctl_mute;
 	int rc;
 
-	rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
-			    sizeof(struct tpacpi_alsa_data), &card);
+	rc = snd_card_new(&tpacpi_pdev->dev,
+			  alsa_index, alsa_id, THIS_MODULE,
+			  sizeof(struct tpacpi_alsa_data), &card);
 	if (rc < 0 || !card) {
 		pr_err("Failed to create ALSA card structures: %d\n", rc);
 		return 1;
@@ -6828,7 +6833,6 @@ static int __init volume_create_alsa_mixer(void)
 	}
 	data->ctl_mute_id = &ctl_mute->id;
 
-	snd_card_set_dev(card, &tpacpi_pdev->dev);
 	rc = snd_card_register(card);
 	if (rc < 0) {
 		pr_err("Failed to register ALSA card: %d\n", rc);
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 769d265b221b..deb7f4bcdb7b 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -21,7 +21,7 @@
 
 #include "pnpbios.h"
 
-static struct {
+__visible struct {
 	u16 offset;
 	u16 segment;
 } pnp_bios_callpoint;
@@ -41,6 +41,7 @@ asmlinkage void pnp_bios_callfunc(void);
 
 __asm__(".text			\n"
 	__ALIGN_STR "\n"
+	".globl pnp_bios_callfunc\n"
 	"pnp_bios_callfunc:\n"
 	"	pushl %edx	\n"
 	"	pushl %ecx	\n"
@@ -66,9 +67,9 @@ static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
  * after PnP BIOS oopses.
  */
 
-u32 pnp_bios_fault_esp;
-u32 pnp_bios_fault_eip;
-u32 pnp_bios_is_utter_crap = 0;
+__visible u32 pnp_bios_fault_esp;
+__visible u32 pnp_bios_fault_eip;
+__visible u32 pnp_bios_is_utter_crap = 0;
 
 static spinlock_t pnp_bios_lock;
 
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 6d452a78b19c..fa0e4e057b99 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -22,7 +22,7 @@ config POWER_RESET_GPIO
 
 config POWER_RESET_MSM
 	bool "Qualcomm MSM power-off driver"
-	depends on POWER_RESET && ARCH_MSM
+	depends on POWER_RESET && ARCH_QCOM
 	help
 	  Power off and restart support for Qualcomm boards.
 
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 3c6768378a94..61b51e17d932 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -834,7 +834,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
 }
 
 static const struct x86_cpu_id energy_unit_quirk_ids[] = {
-	{ X86_VENDOR_INTEL, 6, 0x37},/* VLV */
+	{ X86_VENDOR_INTEL, 6, 0x37},/* Valleyview */
 	{}
 };
 
@@ -947,11 +947,11 @@ static void package_power_limit_irq_restore(int package_id)
 }
 
 static const struct x86_cpu_id rapl_ids[] = {
-	{ X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
-	{ X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
-	{ X86_VENDOR_INTEL, 6, 0x37},/* VLV */
-	{ X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
-	{ X86_VENDOR_INTEL, 6, 0x45},/* HSW */
+	{ X86_VENDOR_INTEL, 6, 0x2a},/* Sandy Bridge */
+	{ X86_VENDOR_INTEL, 6, 0x2d},/* Sandy Bridge EP */
+	{ X86_VENDOR_INTEL, 6, 0x37},/* Valleyview */
+	{ X86_VENDOR_INTEL, 6, 0x3a},/* Ivy Bridge */
+	{ X86_VENDOR_INTEL, 6, 0x45},/* Haswell */
 	/* TODO: Add more CPU IDs after testing */
 	{}
 };
@@ -1147,6 +1147,11 @@ static int rapl_check_domain(int cpu, int domain)
 	if (rdmsrl_safe_on_cpu(cpu, msr, &val1))
 		return -ENODEV;
 
+	/* PP1/uncore/graphics domain may not be active at the time of
+	 * driver loading. So skip further checks.
+	 */
+	if (domain == RAPL_DOMAIN_PP1)
+		return 0;
 	/* energy counters roll slowly on some domains */
 	while (++retry < 10) {
 		usleep_range(10000, 15000);
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/pwm/Kconfig b/drivers/pwm/Kconfig
index 22f2f2857b82..0b7a3c96f639 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -160,6 +160,7 @@ config PWM_PXA
 config PWM_RENESAS_TPU
 	tristate "Renesas TPU PWM support"
 	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on HAS_IOMEM
 	help
 	  This driver exposes the Timer Pulse Unit (TPU) PWM controller found
 	  in Renesas chips through the PWM API.
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 8d995731cef8..7eb2c181c25a 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -140,8 +140,6 @@ static struct of_device_id pwm_of_match[] = {
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pwm_of_match);
-#else
-#define pwm_of_match NULL
 #endif
 
 static const struct platform_device_id *pxa_pwm_get_id_dt(struct device *dev)
@@ -228,7 +226,7 @@ static struct platform_driver pwm_driver = {
 	.driver		= {
 		.name	= "pxa25x-pwm",
 		.owner	= THIS_MODULE,
-		.of_match_table = pwm_of_match,
+		.of_match_table = of_match_ptr(pwm_of_match),
 	},
 	.probe		= pwm_probe,
 	.remove		= pwm_remove,
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index b59639e0c029..d66529a995a1 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -598,9 +598,8 @@ static int pwm_samsung_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops pwm_samsung_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(pwm_samsung_suspend, pwm_samsung_resume)
-};
+static SIMPLE_DEV_PM_OPS(pwm_samsung_pm_ops, pwm_samsung_suspend,
+			 pwm_samsung_resume);
 
 static struct platform_driver pwm_samsung_driver = {
 	.driver		= {
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index ff7cbf2d28e3..1753dc693c15 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2256,6 +2256,7 @@ static int tsi721_setup_mport(struct tsi721_device *priv)
 	mport->phy_type = RIO_PHY_SERIAL;
 	mport->priv = (void *)priv;
 	mport->phys_efptr = 0x100;
+	mport->dev.parent = &pdev->dev;
 	priv->mport = mport;
 
 	INIT_LIST_HEAD(&mport->dbells);
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index b4b0d83f9ef6..0305675270ee 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -644,6 +644,9 @@ enum tsi721_smsg_int_flag {
 
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 
+#define TSI721_BDMA_BD_RING_SZ	128
+#define TSI721_BDMA_MAX_BCOUNT	(TSI721_DMAD_BCOUNT1 + 1)
+
 struct tsi721_tx_desc {
 	struct dma_async_tx_descriptor	txd;
 	struct tsi721_dma_desc		*hw_desc;
@@ -652,6 +655,7 @@ struct tsi721_tx_desc {
 	u64				rio_addr;
 	/* upper 2-bits of 66-bit RIO address */
 	u8				rio_addr_u;
+	u32				bcount;
 	bool				interrupt;
 	struct list_head		desc_node;
 	struct list_head		tx_list;
@@ -678,6 +682,7 @@ struct tsi721_bdma_chan {
 	struct list_head	free_list;
 	dma_cookie_t		completed_cookie;
 	struct tasklet_struct	tasklet;
+	bool			active;
 };
 
 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index 502663f5f7c6..9b60b1f3261c 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -206,8 +206,8 @@ void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan)
 {
 	/* Disable BDMA channel interrupts */
 	iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE);
-
-	tasklet_schedule(&bdma_chan->tasklet);
+	if (bdma_chan->active)
+		tasklet_schedule(&bdma_chan->tasklet);
 }
 
 #ifdef CONFIG_PCI_MSI
@@ -304,35 +304,17 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan)
 }
 
 static int
-tsi721_fill_desc(struct tsi721_bdma_chan *bdma_chan,
-	struct tsi721_tx_desc *desc, struct scatterlist *sg,
+tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg,
 	enum dma_rtype rtype, u32 sys_size)
 {
 	struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
 	u64 rio_addr;
 
-	if (sg_dma_len(sg) > TSI721_DMAD_BCOUNT1 + 1) {
-		dev_err(bdma_chan->dchan.device->dev,
-			"SG element is too large\n");
-		return -EINVAL;
-	}
-
-	dev_dbg(bdma_chan->dchan.device->dev,
-		"desc: 0x%llx, addr: 0x%llx len: 0x%x\n",
-		(u64)desc->txd.phys, (unsigned long long)sg_dma_address(sg),
-		sg_dma_len(sg));
-
-	dev_dbg(bdma_chan->dchan.device->dev,
-		"bd_ptr = %p did=%d raddr=0x%llx\n",
-		bd_ptr, desc->destid, desc->rio_addr);
-
 	/* Initialize DMA descriptor */
 	bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) |
 					(rtype << 19) | desc->destid);
-	if (desc->interrupt)
-		bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF);
 	bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) |
-					(sys_size << 26) | sg_dma_len(sg));
+				     (sys_size << 26));
 	rio_addr = (desc->rio_addr >> 2) |
 				((u64)(desc->rio_addr_u & 0x3) << 62);
 	bd_ptr->raddr_lo = cpu_to_le32(rio_addr & 0xffffffff);
@@ -346,6 +328,20 @@ tsi721_fill_desc(struct tsi721_bdma_chan *bdma_chan,
 	return 0;
 }
 
+static int
+tsi721_desc_fill_end(struct tsi721_tx_desc *desc)
+{
+	struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
+
+	/* Update DMA descriptor */
+	if (desc->interrupt)
+		bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF);
+	bd_ptr->bcount |= cpu_to_le32(desc->bcount & TSI721_DMAD_BCOUNT1);
+
+	return 0;
+}
+
+
 static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan,
 				      struct tsi721_tx_desc *desc)
 {
@@ -562,7 +558,7 @@ static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
 	}
 #endif /* CONFIG_PCI_MSI */
 
-	tasklet_enable(&bdma_chan->tasklet);
+	bdma_chan->active = true;
 	tsi721_bdma_interrupt_enable(bdma_chan, 1);
 
 	return bdma_chan->bd_num - 1;
@@ -576,9 +572,7 @@ err_out:
 static void tsi721_free_chan_resources(struct dma_chan *dchan)
 {
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-#ifdef CONFIG_PCI_MSI
 	struct tsi721_device *priv = to_tsi721(dchan->device);
-#endif
 	LIST_HEAD(list);
 
 	dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
@@ -589,14 +583,25 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan)
 	BUG_ON(!list_empty(&bdma_chan->active_list));
 	BUG_ON(!list_empty(&bdma_chan->queue));
 
-	tasklet_disable(&bdma_chan->tasklet);
+	tsi721_bdma_interrupt_enable(bdma_chan, 0);
+	bdma_chan->active = false;
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		synchronize_irq(priv->msix[TSI721_VECT_DMA0_DONE +
+					   bdma_chan->id].vector);
+		synchronize_irq(priv->msix[TSI721_VECT_DMA0_INT +
+					   bdma_chan->id].vector);
+	} else
+#endif
+	synchronize_irq(priv->pdev->irq);
+
+	tasklet_kill(&bdma_chan->tasklet);
 
 	spin_lock_bh(&bdma_chan->lock);
 	list_splice_init(&bdma_chan->free_list, &list);
 	spin_unlock_bh(&bdma_chan->lock);
 
-	tsi721_bdma_interrupt_enable(bdma_chan, 0);
-
 #ifdef CONFIG_PCI_MSI
 	if (priv->flags & TSI721_USING_MSIX) {
 		free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
@@ -665,6 +670,7 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan,
 	unsigned int i;
 	u32 sys_size = dma_to_mport(dchan->device)->sys_size;
 	enum dma_rtype rtype;
+	dma_addr_t next_addr = -1;
 
 	if (!sgl || !sg_len) {
 		dev_err(dchan->device->dev, "%s: No SG list\n", __func__);
@@ -695,36 +701,84 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan,
 	for_each_sg(sgl, sg, sg_len, i) {
 		int err;
 
-		dev_dbg(dchan->device->dev, "%s: sg #%d\n", __func__, i);
+		if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) {
+			dev_err(dchan->device->dev,
+				"%s: SG entry %d is too large\n", __func__, i);
+			goto err_desc_put;
+		}
+
+		/*
+		 * If this sg entry forms contiguous block with previous one,
+		 * try to merge it into existing DMA descriptor
+		 */
+		if (desc) {
+			if (next_addr == sg_dma_address(sg) &&
+			    desc->bcount + sg_dma_len(sg) <=
+						TSI721_BDMA_MAX_BCOUNT) {
+				/* Adjust byte count of the descriptor */
+				desc->bcount += sg_dma_len(sg);
+				goto entry_done;
+			}
+
+			/*
+			 * Finalize this descriptor using total
+			 * byte count value.
+			 */
+			tsi721_desc_fill_end(desc);
+			dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
+				__func__, desc->bcount);
+		}
+
+		/*
+		 * Obtain and initialize a new descriptor
+		 */
 		desc = tsi721_desc_get(bdma_chan);
 		if (!desc) {
 			dev_err(dchan->device->dev,
-				"Not enough descriptors available\n");
-			goto err_desc_get;
+				"%s: Failed to get new descriptor for SG %d\n",
+				__func__, i);
+			goto err_desc_put;
 		}
 
-		if (sg_is_last(sg))
-			desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0;
-		else
-			desc->interrupt = false;
-
 		desc->destid = rext->destid;
 		desc->rio_addr = rio_addr;
 		desc->rio_addr_u = 0;
+		desc->bcount = sg_dma_len(sg);
+
+		dev_dbg(dchan->device->dev,
+			"sg%d desc: 0x%llx, addr: 0x%llx len: %d\n",
+			i, (u64)desc->txd.phys,
+			(unsigned long long)sg_dma_address(sg),
+			sg_dma_len(sg));
 
-		err = tsi721_fill_desc(bdma_chan, desc, sg, rtype, sys_size);
+		dev_dbg(dchan->device->dev,
+			"bd_ptr = %p did=%d raddr=0x%llx\n",
+			desc->hw_desc, desc->destid, desc->rio_addr);
+
+		err = tsi721_desc_fill_init(desc, sg, rtype, sys_size);
 		if (err) {
 			dev_err(dchan->device->dev,
 				"Failed to build desc: %d\n", err);
-			goto err_desc_get;
+			goto err_desc_put;
 		}
 
-		rio_addr += sg_dma_len(sg);
+		next_addr = sg_dma_address(sg);
 
 		if (!first)
 			first = desc;
 		else
 			list_add_tail(&desc->desc_node, &first->tx_list);
+
+entry_done:
+		if (sg_is_last(sg)) {
+			desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0;
+			tsi721_desc_fill_end(desc);
+			dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
+				__func__, desc->bcount);
+		} else {
+			rio_addr += sg_dma_len(sg);
+			next_addr += sg_dma_len(sg);
+		}
 	}
 
 	first->txd.cookie = -EBUSY;
@@ -732,7 +786,7 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan,
 
 	return &first->txd;
 
-err_desc_get:
+err_desc_put:
 	tsi721_desc_put(bdma_chan, first);
 	return NULL;
 }
@@ -783,13 +837,14 @@ int tsi721_register_dma(struct tsi721_device *priv)
 		if (i == TSI721_DMACH_MAINT)
 			continue;
 
-		bdma_chan->bd_num = 64;
+		bdma_chan->bd_num = TSI721_BDMA_BD_RING_SZ;
 		bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i);
 
 		bdma_chan->dchan.device = &mport->dma;
 		bdma_chan->dchan.cookie = 1;
 		bdma_chan->dchan.chan_id = i;
 		bdma_chan->id = i;
+		bdma_chan->active = false;
 
 		spin_lock_init(&bdma_chan->lock);
 
@@ -799,7 +854,6 @@ int tsi721_register_dma(struct tsi721_device *priv)
 
 		tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet,
 			     (unsigned long)bdma_chan);
-		tasklet_disable(&bdma_chan->tasklet);
 		list_add_tail(&bdma_chan->dchan.device_node,
 			      &mport->dma.channels);
 	}
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index c9ae692d3451..f301f059bb85 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -167,7 +167,6 @@ void rio_unregister_driver(struct rio_driver *rdrv)
 void rio_attach_device(struct rio_dev *rdev)
 {
 	rdev->dev.bus = &rio_bus_type;
-	rdev->dev.parent = &rio_bus;
 }
 EXPORT_SYMBOL_GPL(rio_attach_device);
 
@@ -216,9 +215,12 @@ static int rio_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-struct device rio_bus = {
-	.init_name = "rapidio",
+struct class rio_mport_class = {
+	.name		= "rapidio_port",
+	.owner		= THIS_MODULE,
+	.dev_groups	= rio_mport_groups,
 };
+EXPORT_SYMBOL_GPL(rio_mport_class);
 
 struct bus_type rio_bus_type = {
 	.name = "rapidio",
@@ -233,14 +235,20 @@ struct bus_type rio_bus_type = {
 /**
  *  rio_bus_init - Register the RapidIO bus with the device model
  *
- *  Registers the RIO bus device and RIO bus type with the Linux
+ *  Registers the RIO mport device class and RIO bus type with the Linux
  *  device model.
  */
 static int __init rio_bus_init(void)
 {
-	if (device_register(&rio_bus) < 0)
-		printk("RIO: failed to register RIO bus device\n");
-	return bus_register(&rio_bus_type);
+	int ret;
+
+	ret = class_register(&rio_mport_class);
+	if (!ret) {
+		ret = bus_register(&rio_bus_type);
+		if (ret)
+			class_unregister(&rio_mport_class);
+	}
+	return ret;
 }
 
 postcore_initcall(rio_bus_init);
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index d3a6539a77cc..47a1b2ea76c4 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -461,6 +461,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
 			     rdev->comp_tag & RIO_CTAG_UDEVID);
 	}
 
+	rdev->dev.parent = &port->dev;
 	rio_attach_device(rdev);
 
 	device_initialize(&rdev->dev);
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index e0221c6d0cc2..cdb005c0094d 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -341,3 +341,43 @@ const struct attribute_group *rio_bus_groups[] = {
 	&rio_bus_group,
 	NULL,
 };
+
+static ssize_t
+port_destid_show(struct device *dev, struct device_attribute *attr,
+		 char *buf)
+{
+	struct rio_mport *mport = to_rio_mport(dev);
+
+	if (mport)
+		return sprintf(buf, "0x%04x\n", mport->host_deviceid);
+	else
+		return -ENODEV;
+}
+static DEVICE_ATTR_RO(port_destid);
+
+static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct rio_mport *mport = to_rio_mport(dev);
+
+	if (mport)
+		return sprintf(buf, "%u\n", mport->sys_size);
+	else
+		return -ENODEV;
+}
+static DEVICE_ATTR_RO(sys_size);
+
+static struct attribute *rio_mport_attrs[] = {
+	&dev_attr_port_destid.attr,
+	&dev_attr_sys_size.attr,
+	NULL,
+};
+
+static const struct attribute_group rio_mport_group = {
+	.attrs = rio_mport_attrs,
+};
+
+const struct attribute_group *rio_mport_groups[] = {
+	&rio_mport_group,
+	NULL,
+};
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 2e8a20cac588..a54ba0494dd3 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1884,6 +1884,7 @@ static int rio_get_hdid(int index)
 int rio_register_mport(struct rio_mport *port)
 {
 	struct rio_scan_node *scan = NULL;
+	int res = 0;
 
 	if (next_portid >= RIO_MAX_MPORTS) {
 		pr_err("RIO: reached specified max number of mports\n");
@@ -1894,6 +1895,16 @@ int rio_register_mport(struct rio_mport *port)
 	port->host_deviceid = rio_get_hdid(port->id);
 	port->nscan = NULL;
 
+	dev_set_name(&port->dev, "rapidio%d", port->id);
+	port->dev.class = &rio_mport_class;
+
+	res = device_register(&port->dev);
+	if (res)
+		dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n",
+			port->id, res);
+	else
+		dev_dbg(&port->dev, "RIO: mport%d registered\n", port->id);
+
 	mutex_lock(&rio_mport_list_lock);
 	list_add_tail(&port->node, &rio_mports);
 
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 5f99d22ad0b0..2d0550e08ea2 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -50,6 +50,7 @@ extern int rio_mport_scan(int mport_id);
 /* Structures internal to the RIO core code */
 extern const struct attribute_group *rio_dev_groups[];
 extern const struct attribute_group *rio_bus_groups[];
+extern const struct attribute_group *rio_mport_groups[];
 
 #define RIO_GET_DID(size, x)	(size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
 #define RIO_SET_DID(size, x)	(size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
index d333f7eac106..7a721d67e6ac 100644
--- a/drivers/regulator/88pm800.c
+++ b/drivers/regulator/88pm800.c
@@ -310,10 +310,8 @@ static int pm800_regulator_probe(struct platform_device *pdev)
 
 	pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data),
 					GFP_KERNEL);
-	if (!pm800_data) {
-		dev_err(&pdev->dev, "Failed to allocate pm800_regualtors");
+	if (!pm800_data)
 		return -ENOMEM;
-	}
 
 	pm800_data->map = chip->subchip->regmap_power;
 	pm800_data->chip = chip;
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index f704d83c93c4..337634ad0562 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -2,7 +2,7 @@
  * Regulators driver for Marvell 88PM8607
  *
  * Copyright (C) 2009 Marvell International Ltd.
- * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *	Haojian Zhuang <haojian.zhuang@marvell.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
@@ -78,7 +78,7 @@ static const unsigned int BUCK2_suspend_table[] = {
 };
 
 static const unsigned int BUCK3_table[] = {
-              0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
+	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
@@ -89,7 +89,7 @@ static const unsigned int BUCK3_table[] = {
 };
 
 static const unsigned int BUCK3_suspend_table[] = {
-              0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
+	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
@@ -322,7 +322,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
 	nproot = of_node_get(pdev->dev.parent->of_node);
 	if (!nproot)
 		return -ENODEV;
-	nproot = of_find_node_by_name(nproot, "regulators");
+	nproot = of_get_child_by_name(nproot, "regulators");
 	if (!nproot) {
 		dev_err(&pdev->dev, "failed to find regulators node\n");
 		return -ENODEV;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a7932822e37..b7c95e8d8a0e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -513,6 +513,15 @@ config REGULATOR_TPS65217
 	  voltage regulators. It supports software based voltage control
 	  for different voltage domains
 
+config REGULATOR_TPS65218
+	tristate "TI TPS65218 Power regulators"
+	depends on MFD_TPS65218 && OF
+	help
+	  This driver supports TPS65218 voltage regulator chips. TPS65218
+	  provides six step-down converters and one general-purpose LDO
+	  voltage regulators. It supports software based voltage control
+	  for different voltage domains
+
 config REGULATOR_TPS6524X
 	tristate "TI TPS6524X Power regulators"
 	depends on SPI
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9ddcf259..ba801a5081b6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
+obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 084cc0819a52..a5ff30c8a1e3 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -213,7 +213,7 @@ static int act8865_pdata_from_dt(struct device *dev,
 	struct device_node *np;
 	struct act8865_regulator_data *regulator;
 
-	np = of_find_node_by_name(dev->of_node, "regulators");
+	np = of_get_child_by_name(dev->of_node, "regulators");
 	if (!np) {
 		dev_err(dev, "missing 'regulators' subnode in DT\n");
 		return -EINVAL;
@@ -221,17 +221,15 @@ static int act8865_pdata_from_dt(struct device *dev,
 
 	matched = of_regulator_match(dev, np,
 				act8865_matches, ARRAY_SIZE(act8865_matches));
+	of_node_put(np);
 	if (matched <= 0)
 		return matched;
 
 	pdata->regulators = devm_kzalloc(dev,
 				sizeof(struct act8865_regulator_data) *
 				ARRAY_SIZE(act8865_matches), GFP_KERNEL);
-	if (!pdata->regulators) {
-		dev_err(dev, "%s: failed to allocate act8865 registor\n",
-						__func__);
+	if (!pdata->regulators)
 		return -ENOMEM;
-	}
 
 	pdata->num_regulators = matched;
 	regulator = pdata->regulators;
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 862e63e451d0..38e8122c4b09 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -34,6 +34,9 @@
 #define LDO_RAMP_UP_UNIT_IN_CYCLES      64 /* 64 cycles per step */
 #define LDO_RAMP_UP_FREQ_IN_MHZ         24 /* cycle based on 24M OSC */
 
+#define LDO_POWER_GATE			0x00
+#define LDO_FET_FULL_ON			0x1f
+
 struct anatop_regulator {
 	const char *name;
 	u32 control_reg;
@@ -48,6 +51,8 @@ struct anatop_regulator {
 	int max_voltage;
 	struct regulator_desc rdesc;
 	struct regulator_init_data *initdata;
+	bool bypass;
+	int sel;
 };
 
 static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
@@ -97,14 +102,101 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
 	return regulator_get_voltage_sel_regmap(reg);
 }
 
+static int anatop_regmap_enable(struct regulator_dev *reg)
+{
+	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+	int sel;
+
+	sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel;
+	return regulator_set_voltage_sel_regmap(reg, sel);
+}
+
+static int anatop_regmap_disable(struct regulator_dev *reg)
+{
+	return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE);
+}
+
+static int anatop_regmap_is_enabled(struct regulator_dev *reg)
+{
+	return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE;
+}
+
+static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg,
+					      unsigned selector)
+{
+	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+	int ret;
+
+	if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) {
+		anatop_reg->sel = selector;
+		return 0;
+	}
+
+	ret = regulator_set_voltage_sel_regmap(reg, selector);
+	if (!ret)
+		anatop_reg->sel = selector;
+	return ret;
+}
+
+static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg)
+{
+	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+	if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg))
+		return anatop_reg->sel;
+
+	return regulator_get_voltage_sel_regmap(reg);
+}
+
+static int anatop_regmap_get_bypass(struct regulator_dev *reg, bool *enable)
+{
+	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+	int sel;
+
+	sel = regulator_get_voltage_sel_regmap(reg);
+	if (sel == LDO_FET_FULL_ON)
+		WARN_ON(!anatop_reg->bypass);
+	else if (sel != LDO_POWER_GATE)
+		WARN_ON(anatop_reg->bypass);
+
+	*enable = anatop_reg->bypass;
+	return 0;
+}
+
+static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable)
+{
+	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+	int sel;
+
+	if (enable == anatop_reg->bypass)
+		return 0;
+
+	sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel;
+	anatop_reg->bypass = enable;
+
+	return regulator_set_voltage_sel_regmap(reg, sel);
+}
+
 static struct regulator_ops anatop_rops = {
 	.set_voltage_sel = anatop_regmap_set_voltage_sel,
-	.set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
 	.get_voltage_sel = anatop_regmap_get_voltage_sel,
 	.list_voltage = regulator_list_voltage_linear,
 	.map_voltage = regulator_map_voltage_linear,
 };
 
+static struct regulator_ops anatop_core_rops = {
+	.enable = anatop_regmap_enable,
+	.disable = anatop_regmap_disable,
+	.is_enabled = anatop_regmap_is_enabled,
+	.set_voltage_sel = anatop_regmap_core_set_voltage_sel,
+	.set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
+	.get_voltage_sel = anatop_regmap_core_get_voltage_sel,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.get_bypass = anatop_regmap_get_bypass,
+	.set_bypass = anatop_regmap_set_bypass,
+};
+
 static int anatop_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -116,6 +208,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
 	struct regulator_init_data *initdata;
 	struct regulator_config config = { };
 	int ret = 0;
+	u32 val;
 
 	initdata = of_get_regulator_init_data(dev, np);
 	sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
@@ -125,7 +218,6 @@ static int anatop_regulator_probe(struct platform_device *pdev)
 	sreg->name = of_get_property(np, "regulator-name", NULL);
 	rdesc = &sreg->rdesc;
 	rdesc->name = sreg->name;
-	rdesc->ops = &anatop_rops;
 	rdesc->type = REGULATOR_VOLTAGE;
 	rdesc->owner = THIS_MODULE;
 
@@ -197,6 +289,25 @@ static int anatop_regulator_probe(struct platform_device *pdev)
 	config.of_node = pdev->dev.of_node;
 	config.regmap = sreg->anatop;
 
+	/* Only core regulators have the ramp up delay configuration. */
+	if (sreg->control_reg && sreg->delay_bit_width) {
+		rdesc->ops = &anatop_core_rops;
+
+		ret = regmap_read(config.regmap, rdesc->vsel_reg, &val);
+		if (ret) {
+			dev_err(dev, "failed to read initial state\n");
+			return ret;
+		}
+
+		sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift;
+		if (sreg->sel == LDO_FET_FULL_ON) {
+			sreg->sel = 0;
+			sreg->bypass = true;
+		}
+	} else {
+		rdesc->ops = &anatop_rops;
+	}
+
 	/* register regulator */
 	rdev = devm_regulator_register(dev, rdesc, &config);
 	if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 4f6c2055f6b2..d8e7db696d5a 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -189,10 +189,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
 	int ret;
 
 	ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
-	if (ldo1 == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!ldo1)
 		return -ENOMEM;
-	}
 
 	ldo1->arizona = arizona;
 
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index 034ece707083..6fdd9bf6927f 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -204,10 +204,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
 	int ret;
 
 	micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
-	if (micsupp == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!micsupp)
 		return -ENOMEM;
-	}
 
 	micsupp->arizona = arizona;
 	INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index c77a58478cca..b47283f91e2d 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -191,7 +191,7 @@ static int as3711_regulator_parse_dt(struct device *dev,
 {
 	struct as3711_regulator_pdata *pdata = dev_get_platdata(dev);
 	struct device_node *regulators =
-		of_find_node_by_name(dev->parent->of_node, "regulators");
+		of_get_child_by_name(dev->parent->of_node, "regulators");
 	struct of_regulator_match *match;
 	int ret, i;
 
@@ -221,7 +221,6 @@ static int as3711_regulator_probe(struct platform_device *pdev)
 {
 	struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
-	struct regulator_init_data *reg_data;
 	struct regulator_config config = {.dev = &pdev->dev,};
 	struct as3711_regulator *reg = NULL;
 	struct as3711_regulator *regs;
@@ -246,22 +245,14 @@ static int as3711_regulator_probe(struct platform_device *pdev)
 
 	regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
 			sizeof(struct as3711_regulator), GFP_KERNEL);
-	if (!regs) {
-		dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+	if (!regs)
 		return -ENOMEM;
-	}
 
 	for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
-		reg_data = pdata->init_data[id];
-
-		/* No need to register if there is no regulator data */
-		if (!reg_data)
-			continue;
-
 		reg = &regs[id];
 		reg->reg_info = ri;
 
-		config.init_data = reg_data;
+		config.init_data = pdata->init_data[id];
 		config.driver_data = reg;
 		config.regmap = as3711->regmap;
 		config.of_node = of_node[id];
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index 8b17d786cb71..85585219ce82 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -719,6 +719,7 @@ static int as3722_get_regulator_dt_data(struct platform_device *pdev,
 
 	ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
 			ARRAY_SIZE(as3722_regulator_matches));
+	of_node_put(np);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
 			ret);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d1ac4caaf1b0..9a09f3cdbabb 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -953,6 +953,8 @@ static int machine_constraints_current(struct regulator_dev *rdev,
 	return 0;
 }
 
+static int _regulator_do_enable(struct regulator_dev *rdev);
+
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
@@ -1013,10 +1015,9 @@ static int set_machine_constraints(struct regulator_dev *rdev,
 	/* If the constraints say the regulator should be on at this point
 	 * and we have control then make sure it is enabled.
 	 */
-	if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
-	    ops->enable) {
-		ret = ops->enable(rdev);
-		if (ret < 0) {
+	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
+		ret = _regulator_do_enable(rdev);
+		if (ret < 0 && ret != -EINVAL) {
 			rdev_err(rdev, "failed to enable\n");
 			goto out;
 		}
@@ -1907,8 +1908,6 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
 
 	trace_regulator_disable_complete(rdev_get_name(rdev));
 
-	_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
-			     NULL);
 	return 0;
 }
 
@@ -1932,6 +1931,8 @@ static int _regulator_disable(struct regulator_dev *rdev)
 				rdev_err(rdev, "failed to disable\n");
 				return ret;
 			}
+			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
+					NULL);
 		}
 
 		rdev->use_count = 0;
@@ -1984,20 +1985,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
 {
 	int ret = 0;
 
-	/* force disable */
-	if (rdev->desc->ops->disable) {
-		/* ah well, who wants to live forever... */
-		ret = rdev->desc->ops->disable(rdev);
-		if (ret < 0) {
-			rdev_err(rdev, "failed to force disable\n");
-			return ret;
-		}
-		/* notify other consumers that power has been forced off */
-		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
-			REGULATOR_EVENT_DISABLE, NULL);
+	ret = _regulator_do_disable(rdev);
+	if (ret < 0) {
+		rdev_err(rdev, "failed to force disable\n");
+		return ret;
 	}
 
-	return ret;
+	_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+			REGULATOR_EVENT_DISABLE, NULL);
+
+	return 0;
 }
 
 /**
@@ -2141,7 +2138,7 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled);
  * @regulator: regulator source
  *
  * Returns positive if the regulator driver backing the source/client
- * can change its voltage, false otherwise. Usefull for detecting fixed
+ * can change its voltage, false otherwise. Useful for detecting fixed
  * or dummy regulators and disabling voltage change logic in the client
  * driver.
  */
@@ -2402,6 +2399,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
 	int old_min_uV, old_max_uV;
+	int current_uV;
 
 	mutex_lock(&rdev->mutex);
 
@@ -2412,6 +2410,19 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 	if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
 		goto out;
 
+	/* If we're trying to set a range that overlaps the current voltage,
+	 * return succesfully even though the regulator does not support
+	 * changing the voltage.
+	 */
+	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+		current_uV = _regulator_get_voltage(rdev);
+		if (min_uV <= current_uV && current_uV <= max_uV) {
+			regulator->min_uV = min_uV;
+			regulator->max_uV = max_uV;
+			goto out;
+		}
+	}
+
 	/* sanity check */
 	if (!rdev->desc->ops->set_voltage &&
 	    !rdev->desc->ops->set_voltage_sel) {
@@ -3630,23 +3641,18 @@ int regulator_suspend_finish(void)
 
 	mutex_lock(&regulator_list_mutex);
 	list_for_each_entry(rdev, &regulator_list, list) {
-		struct regulator_ops *ops = rdev->desc->ops;
-
 		mutex_lock(&rdev->mutex);
-		if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
-				ops->enable) {
-			error = ops->enable(rdev);
+		if (rdev->use_count > 0  || rdev->constraints->always_on) {
+			error = _regulator_do_enable(rdev);
 			if (error)
 				ret = error;
 		} else {
 			if (!have_full_constraints())
 				goto unlock;
-			if (!ops->disable)
-				goto unlock;
 			if (!_regulator_is_enabled(rdev))
 				goto unlock;
 
-			error = ops->disable(rdev);
+			error = _regulator_do_disable(rdev);
 			if (error)
 				ret = error;
 		}
@@ -3820,7 +3826,7 @@ static int __init regulator_init_complete(void)
 		ops = rdev->desc->ops;
 		c = rdev->constraints;
 
-		if (!ops->disable || (c && c->always_on))
+		if (c && c->always_on)
 			continue;
 
 		mutex_lock(&rdev->mutex);
@@ -3841,7 +3847,7 @@ static int __init regulator_init_complete(void)
 			/* We log since this may kill the system if it
 			 * goes wrong. */
 			rdev_info(rdev, "disabling\n");
-			ret = ops->disable(rdev);
+			ret = _regulator_do_disable(rdev);
 			if (ret != 0)
 				rdev_err(rdev, "couldn't disable: %d\n", ret);
 		} else {
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 3adeaeffc485..fdb6ea8ae7e6 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -240,6 +240,31 @@ static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
 	return ret;
 }
 
+static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+						 unsigned int old_sel,
+						 unsigned int new_sel)
+{
+	struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9052_regulator_info *info = regulator->info;
+	int id = rdev_get_id(rdev);
+	int ret = 0;
+
+	/* The DVC controlled LDOs and DCDCs ramp with 6.25mV/µs after enabling
+	 * the activate bit.
+	 */
+	switch (id) {
+	case DA9052_ID_BUCK1:
+	case DA9052_ID_BUCK2:
+	case DA9052_ID_BUCK3:
+	case DA9052_ID_LDO2:
+	case DA9052_ID_LDO3:
+		ret = (new_sel - old_sel) * info->step_uV / 6250;
+		break;
+	}
+
+	return ret;
+}
+
 static struct regulator_ops da9052_dcdc_ops = {
 	.get_current_limit = da9052_dcdc_get_current_limit,
 	.set_current_limit = da9052_dcdc_set_current_limit,
@@ -248,6 +273,7 @@ static struct regulator_ops da9052_dcdc_ops = {
 	.map_voltage = da9052_map_voltage,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = da9052_regulator_set_voltage_sel,
+	.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
 	.is_enabled = regulator_is_enabled_regmap,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -258,6 +284,7 @@ static struct regulator_ops da9052_ldo_ops = {
 	.map_voltage = da9052_map_voltage,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = da9052_regulator_set_voltage_sel,
+	.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
 	.is_enabled = regulator_is_enabled_regmap,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -401,7 +428,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
 		if (!nproot)
 			return -ENODEV;
 
-		nproot = of_find_node_by_name(nproot, "regulators");
+		nproot = of_get_child_by_name(nproot, "regulators");
 		if (!nproot)
 			return -ENODEV;
 
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index b14ebdad5dd2..9516317e1a9f 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -19,6 +19,8 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 
 #include <linux/mfd/da9055/core.h>
 #include <linux/mfd/da9055/reg.h>
@@ -446,6 +448,9 @@ static int da9055_gpio_init(struct da9055_regulator *regulator,
 	struct da9055_regulator_info *info = regulator->info;
 	int ret = 0;
 
+	if (!pdata)
+		return 0;
+
 	if (pdata->gpio_ren && pdata->gpio_ren[id]) {
 		char name[18];
 		int gpio_mux = pdata->gpio_ren[id];
@@ -530,6 +535,59 @@ static inline struct da9055_regulator_info *find_regulator_info(int id)
 	return NULL;
 }
 
+#ifdef CONFIG_OF
+static struct of_regulator_match da9055_reg_matches[] = {
+	{ .name = "BUCK1", },
+	{ .name = "BUCK2", },
+	{ .name = "LDO1", },
+	{ .name = "LDO2", },
+	{ .name = "LDO3", },
+	{ .name = "LDO4", },
+	{ .name = "LDO5", },
+	{ .name = "LDO6", },
+};
+
+static int da9055_regulator_dt_init(struct platform_device *pdev,
+				    struct da9055_regulator *regulator,
+				    struct regulator_config *config,
+				    int regid)
+{
+	struct device_node *nproot, *np;
+	int ret;
+
+	nproot = of_node_get(pdev->dev.parent->of_node);
+	if (!nproot)
+		return -ENODEV;
+
+	np = of_get_child_by_name(nproot, "regulators");
+	if (!np)
+		return -ENODEV;
+
+	ret = of_regulator_match(&pdev->dev, np, &da9055_reg_matches[regid], 1);
+	of_node_put(nproot);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Error matching regulator: %d\n", ret);
+		return ret;
+	}
+
+	config->init_data = da9055_reg_matches[regid].init_data;
+	config->of_node = da9055_reg_matches[regid].of_node;
+
+	if (!config->of_node)
+		return -ENODEV;
+
+	return 0;
+}
+#else
+static inline int da9055_regulator_dt_init(struct platform_device *pdev,
+				       struct da9055_regulator *regulator,
+				       struct regulator_config *config,
+				       int regid)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_OF */
+
 static int da9055_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_config config = { };
@@ -538,9 +596,6 @@ static int da9055_regulator_probe(struct platform_device *pdev)
 	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
 	int ret, irq;
 
-	if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
-		return -ENODEV;
-
 	regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
 				 GFP_KERNEL);
 	if (!regulator)
@@ -557,8 +612,14 @@ static int da9055_regulator_probe(struct platform_device *pdev)
 	config.driver_data = regulator;
 	config.regmap = da9055->regmap;
 
-	if (pdata && pdata->regulators)
+	if (pdata && pdata->regulators) {
 		config.init_data = pdata->regulators[pdev->id];
+	} else {
+		ret = da9055_regulator_dt_init(pdev, regulator, &config,
+					       pdev->id);
+		if (ret < 0)
+			return ret;
+	}
 
 	ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
 	if (ret < 0)
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 91e99a2c8dc1..38ad5e950907 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -365,7 +365,7 @@ static int da9063_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 
 	sel = regulator_map_voltage_linear(rdev, uV, uV);
 	if (sel < 0)
-		return -EINVAL;
+		return sel;
 
 	sel <<= ffs(rdev->desc->vsel_mask) - 1;
 
@@ -666,7 +666,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
 	struct device_node *node;
 	int i, n, num;
 
-	node = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
+	node = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
 	if (!node) {
 		dev_err(&pdev->dev, "Regulators device node not found\n");
 		return ERR_PTR(-ENODEV);
@@ -674,6 +674,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
 
 	num = of_regulator_match(&pdev->dev, node, da9063_matches,
 				 ARRAY_SIZE(da9063_matches));
+	of_node_put(node);
 	if (num < 0) {
 		dev_err(&pdev->dev, "Failed to match regulators\n");
 		return ERR_PTR(-EINVAL);
@@ -756,7 +757,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev,
 			"Error while reading BUCKs configuration\n");
-		return -EIO;
+		return ret;
 	}
 	bcores_merged = val & DA9063_BCORE_MERGE;
 	bmem_bio_merged = val & DA9063_BUCK_MERGE;
@@ -775,10 +776,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
 	size = sizeof(struct da9063_regulators) +
 		n_regulators * sizeof(struct da9063_regulator);
 	regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
-	if (!regulators) {
-		dev_err(&pdev->dev, "No memory for regulators\n");
+	if (!regulators)
 		return -ENOMEM;
-	}
 
 	regulators->n_regulators = n_regulators;
 	platform_set_drvdata(pdev, regulators);
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 6f5ecbe1132e..7a320dd11c46 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -134,11 +134,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
 	int error;
 
 	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL);
-	if (NULL == chip) {
-		dev_err(&i2c->dev,
-			"Cannot kzalloc memory for regulator structure\n");
+	if (!chip)
 		return -ENOMEM;
-	}
 
 	chip->regmap = devm_regmap_init_i2c(i2c, &da9210_regmap_config);
 	if (IS_ERR(chip->regmap)) {
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index ce89f7848a57..f111dfb8d2d7 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -202,18 +202,12 @@ ux500_regulator_debug_init(struct platform_device *pdev,
 	rdebug.num_regulators = num_regulators;
 
 	rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
-	if (!rdebug.state_before_suspend) {
-		dev_err(&pdev->dev,
-			"could not allocate memory for saving state\n");
+	if (!rdebug.state_before_suspend)
 		goto exit_destroy_power_state;
-	}
 
 	rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
-	if (!rdebug.state_after_suspend) {
-		dev_err(&pdev->dev,
-			"could not allocate memory for saving state\n");
+	if (!rdebug.state_after_suspend)
 		goto exit_free;
-	}
 
 	dbx500_regulator_testcase(regulator_info, num_regulators);
 	return 0;
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index df9f42524abb..2436db9e2ca3 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -25,7 +25,11 @@
 
 struct regulator_dev *dummy_regulator_rdev;
 
-static struct regulator_init_data dummy_initdata;
+static struct regulator_init_data dummy_initdata = {
+	.constraints = {
+		.always_on = 1,
+	},
+};
 
 static struct regulator_ops dummy_ops;
 
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 7ca3d9e3b0fe..714fd9a89aa1 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -90,11 +90,11 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 		return 0;
 	ret = regulator_map_voltage_linear(rdev, uV, uV);
 	if (ret < 0)
-		return -EINVAL;
+		return ret;
 	ret = regmap_update_bits(di->regmap, di->sleep_reg,
 					VSEL_NSEL_MASK, ret);
 	if (ret < 0)
-		return -EINVAL;
+		return ret;
 	/* Cache the sleep voltage setting.
 	 * Might not be the real voltage which is rounded */
 	di->sleep_vol_cache = uV;
@@ -244,10 +244,9 @@ static int fan53555_regulator_probe(struct i2c_client *client,
 
 	di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
 					GFP_KERNEL);
-	if (!di) {
-		dev_err(&client->dev, "Failed to allocate device info data!\n");
+	if (!di)
 		return -ENOMEM;
-	}
+
 	di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
 	if (IS_ERR(di->regmap)) {
 		dev_err(&client->dev, "Failed to allocate regmap!\n");
@@ -260,14 +259,14 @@ static int fan53555_regulator_probe(struct i2c_client *client,
 	ret = regmap_read(di->regmap, FAN53555_ID1, &val);
 	if (ret < 0) {
 		dev_err(&client->dev, "Failed to get chip ID!\n");
-		return -ENODEV;
+		return ret;
 	}
 	di->chip_id = val & DIE_ID;
 	/* Get chip revision */
 	ret = regmap_read(di->regmap, FAN53555_ID2, &val);
 	if (ret < 0) {
 		dev_err(&client->dev, "Failed to get chip Rev!\n");
-		return -ENODEV;
+		return ret;
 	}
 	di->chip_rev = val & DIE_REV;
 	dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 5ea64b94341c..c61f7e97e4f8 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -130,17 +130,15 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
 			       GFP_KERNEL);
-	if (drvdata == NULL) {
-		dev_err(&pdev->dev, "Failed to allocate device data\n");
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!drvdata)
+		return -ENOMEM;
 
-	drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+	drvdata->desc.name = devm_kstrdup(&pdev->dev,
+					  config->supply_name,
+					  GFP_KERNEL);
 	if (drvdata->desc.name == NULL) {
 		dev_err(&pdev->dev, "Failed to allocate supply name\n");
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 	drvdata->desc.type = REGULATOR_VOLTAGE;
 	drvdata->desc.owner = THIS_MODULE;
@@ -149,13 +147,13 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 	drvdata->desc.enable_time = config->startup_delay;
 
 	if (config->input_supply) {
-		drvdata->desc.supply_name = kstrdup(config->input_supply,
-							GFP_KERNEL);
+		drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
+					    config->input_supply,
+					    GFP_KERNEL);
 		if (!drvdata->desc.supply_name) {
 			dev_err(&pdev->dev,
 				"Failed to allocate input supply\n");
-			ret = -ENOMEM;
-			goto err_name;
+			return -ENOMEM;
 		}
 	}
 
@@ -186,11 +184,12 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 	cfg.driver_data = drvdata;
 	cfg.of_node = pdev->dev.of_node;
 
-	drvdata->dev = regulator_register(&drvdata->desc, &cfg);
+	drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
+					       &cfg);
 	if (IS_ERR(drvdata->dev)) {
 		ret = PTR_ERR(drvdata->dev);
 		dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
-		goto err_input;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, drvdata);
@@ -199,24 +198,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 		drvdata->desc.fixed_uV);
 
 	return 0;
-
-err_input:
-	kfree(drvdata->desc.supply_name);
-err_name:
-	kfree(drvdata->desc.name);
-err:
-	return ret;
-}
-
-static int reg_fixed_voltage_remove(struct platform_device *pdev)
-{
-	struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
-
-	regulator_unregister(drvdata->dev);
-	kfree(drvdata->desc.supply_name);
-	kfree(drvdata->desc.name);
-
-	return 0;
 }
 
 #if defined(CONFIG_OF)
@@ -229,7 +210,6 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
 
 static struct platform_driver regulator_fixed_voltage_driver = {
 	.probe		= reg_fixed_voltage_probe,
-	.remove		= reg_fixed_voltage_remove,
 	.driver		= {
 		.name		= "reg-fixed-voltage",
 		.owner		= THIS_MODULE,
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index c0a1d00b78c9..989b23b377c0 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -136,7 +136,6 @@ static struct gpio_regulator_config *
 of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
 {
 	struct gpio_regulator_config *config;
-	struct property *prop;
 	const char *regtype;
 	int proplen, gpio, i;
 	int ret;
@@ -172,22 +171,35 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
 	if (!config->gpios)
 		return ERR_PTR(-ENOMEM);
 
+	proplen = of_property_count_u32_elems(np, "gpios-states");
+	/* optional property */
+	if (proplen < 0)
+		proplen = 0;
+
+	if (proplen > 0 && proplen != config->nr_gpios) {
+		dev_warn(dev, "gpios <-> gpios-states mismatch\n");
+		proplen = 0;
+	}
+
 	for (i = 0; i < config->nr_gpios; i++) {
 		gpio = of_get_named_gpio(np, "gpios", i);
 		if (gpio < 0)
 			break;
 		config->gpios[i].gpio = gpio;
+		if (proplen > 0) {
+			of_property_read_u32_index(np, "gpios-states", i, &ret);
+			if (ret)
+				config->gpios[i].flags = GPIOF_OUT_INIT_HIGH;
+		}
 	}
 
 	/* Fetch states. */
-	prop = of_find_property(np, "states", NULL);
-	if (!prop) {
+	proplen = of_property_count_u32_elems(np, "states");
+	if (proplen < 0) {
 		dev_err(dev, "No 'states' property found\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	proplen = prop->length / sizeof(int);
-
 	config->states = devm_kzalloc(dev,
 				sizeof(struct gpio_regulator_state)
 				* (proplen / 2),
@@ -196,10 +208,10 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
 		return ERR_PTR(-ENOMEM);
 
 	for (i = 0; i < proplen / 2; i++) {
-		config->states[i].value =
-			be32_to_cpup((int *)prop->value + (i * 2));
-		config->states[i].gpios =
-			be32_to_cpup((int *)prop->value + (i * 2 + 1));
+		of_property_read_u32_index(np, "states", i * 2,
+					   &config->states[i].value);
+		of_property_read_u32_index(np, "states", i * 2 + 1,
+					   &config->states[i].gpios);
 	}
 	config->nr_states = i;
 
@@ -239,10 +251,8 @@ static int gpio_regulator_probe(struct platform_device *pdev)
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
 			       GFP_KERNEL);
-	if (drvdata == NULL) {
-		dev_err(&pdev->dev, "Failed to allocate device data\n");
+	if (drvdata == NULL)
 		return -ENOMEM;
-	}
 
 	drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
 	if (drvdata->desc.name == NULL) {
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 3b1102b75071..66fd2330dca0 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -327,7 +327,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
 		return -EIO;
 	ret = i2c_smbus_read_byte_data(i2c, reg);
 	if (ret < 0)
-		return -EIO;
+		return ret;
 
 	*dest = ret;
 	return 0;
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 2e4734ff79fc..2e022aabd951 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -211,7 +211,7 @@ static int lp872x_get_timestep_usec(struct lp872x *lp)
 
 	ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
 	if (ret)
-		return -EINVAL;
+		return ret;
 
 	val = (val & mask) >> shift;
 	if (val >= size)
@@ -229,7 +229,7 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
 	u8 addr, val;
 
 	if (time_step_us < 0)
-		return -EINVAL;
+		return time_step_us;
 
 	switch (rid) {
 	case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c
index e0619526708c..ed60baaeceec 100644
--- a/drivers/regulator/max14577.c
+++ b/drivers/regulator/max14577.c
@@ -1,7 +1,7 @@
 /*
  * max14577.c - Regulator driver for the Maxim 14577
  *
- * Copyright (C) 2013 Samsung Electronics
+ * Copyright (C) 2013,2014 Samsung Electronics
  * Krzysztof Kozlowski <k.kozlowski@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,12 +22,6 @@
 #include <linux/mfd/max14577-private.h>
 #include <linux/regulator/of_regulator.h>
 
-struct max14577_regulator {
-	struct device *dev;
-	struct max14577 *max14577;
-	struct regulator_dev **regulators;
-};
-
 static int max14577_reg_is_enabled(struct regulator_dev *rdev)
 {
 	int rid = rdev_get_id(rdev);
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index ae001ccf26f4..de020adf0568 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -400,7 +400,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
 	unsigned int i;
 
 	pmic_np = iodev->dev->of_node;
-	regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
+	regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
 	if (!regulators_np) {
 		dev_err(&pdev->dev, "could not find regulators sub-node\n");
 		return -EINVAL;
@@ -410,8 +410,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
 	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
 			     pdata->num_regulators, GFP_KERNEL);
 	if (!rdata) {
-		dev_err(&pdev->dev,
-			"could not allocate memory for regulator data\n");
+		of_node_put(regulators_np);
 		return -ENOMEM;
 	}
 
@@ -425,6 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
 	}
 
 	pdata->regulators = rdata;
+	of_node_put(regulators_np);
 
 	return 0;
 }
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
index 5fb899f461d0..d6807fd7eadc 100644
--- a/drivers/regulator/max77693.c
+++ b/drivers/regulator/max77693.c
@@ -170,19 +170,22 @@ static int max77693_pmic_dt_parse_rdata(struct device *dev,
 	struct max77693_regulator_data *tmp;
 	int i, matched = 0;
 
-	np = of_find_node_by_name(dev->parent->of_node, "regulators");
+	np = of_get_child_by_name(dev->parent->of_node, "regulators");
 	if (!np)
 		return -EINVAL;
 
 	rmatch = devm_kzalloc(dev,
 		 sizeof(*rmatch) * ARRAY_SIZE(regulators), GFP_KERNEL);
-	if (!rmatch)
+	if (!rmatch) {
+		of_node_put(np);
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(regulators); i++)
 		rmatch[i].name = regulators[i].name;
 
 	matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(regulators));
+	of_node_put(np);
 	if (matched <= 0)
 		return matched;
 	*rdata = devm_kzalloc(dev, sizeof(**rdata) * matched, GFP_KERNEL);
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 8d94d3d7f97f..61ecd0892637 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -330,7 +330,7 @@ static int max8660_pdata_from_dt(struct device *dev,
 	struct max8660_subdev_data *sub;
 	struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
 
-	np = of_find_node_by_name(dev->of_node, "regulators");
+	np = of_get_child_by_name(dev->of_node, "regulators");
 	if (!np) {
 		dev_err(dev, "missing 'regulators' subnode in DT\n");
 		return -EINVAL;
@@ -340,6 +340,7 @@ static int max8660_pdata_from_dt(struct device *dev,
 		rmatch[i].name = max8660_reg[i].name;
 
 	matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch));
+	of_node_put(np);
 	if (matched <= 0)
 		return matched;
 
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index 0c5fe6c6ac26..ed90c759c231 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -231,7 +231,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev)
 	if (!np)
 		return 0;
 
-	regulators = of_find_node_by_name(np, "regulators");
+	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
 		dev_err(&pdev->dev, "regulators node not found\n");
 		return -EINVAL;
@@ -292,10 +292,9 @@ static int max8907_regulator_probe(struct platform_device *pdev)
 		return ret;
 
 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
-	if (!pmic) {
-		dev_err(&pdev->dev, "Failed to alloc pmic\n");
+	if (!pmic)
 		return -ENOMEM;
-	}
+
 	platform_set_drvdata(pdev, pmic);
 
 	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index 759510789e71..9c859ed4131b 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -254,7 +254,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
 	nproot = of_node_get(pdev->dev.parent->of_node);
 	if (!nproot)
 		return -ENODEV;
-	np = of_find_node_by_name(nproot, "regulators");
+	np = of_get_child_by_name(nproot, "regulators");
 	if (!np) {
 		dev_err(&pdev->dev, "failed to find regulators node\n");
 		return -ENODEV;
@@ -264,7 +264,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
 				&max8925_regulator_matches[ridx], 1);
 	of_node_put(np);
 	if (rcount < 0)
-		return -ENODEV;
+		return rcount;
 	config->init_data =	max8925_regulator_matches[ridx].init_data;
 	config->of_node = max8925_regulator_matches[ridx].of_node;
 
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 788e5ae2af1b..66e777967c69 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -144,10 +144,8 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
 	int i;
 
 	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		dev_err(dev, "Failed to allocate platform data\n");
+	if (!pd)
 		return NULL;
-	}
 
 	pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0);
 	pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1);
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 892aa1e5b96c..79f57fef0038 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -379,10 +379,8 @@ static int max8973_probe(struct i2c_client *client,
 	}
 
 	max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
-	if (!max) {
-		dev_err(&client->dev, "Memory allocation for max failed\n");
+	if (!max)
 		return -ENOMEM;
-	}
 
 	max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
 	if (IS_ERR(max->regmap)) {
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index 2d618fc9c1af..f657d8db9c0c 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -924,7 +924,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
 		return -ENODEV;
 	}
 
-	regulators_np = of_find_node_by_name(pmic_np, "regulators");
+	regulators_np = of_get_child_by_name(pmic_np, "regulators");
 	if (!regulators_np) {
 		dev_err(&pdev->dev, "could not find regulators sub-node\n");
 		return -EINVAL;
@@ -937,7 +937,6 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
 				pdata->num_regulators, GFP_KERNEL);
 	if (!rdata) {
 		of_node_put(regulators_np);
-		dev_err(&pdev->dev, "could not allocate memory for regulator data\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index ae3f0656feb0..ce22d4f3f3eb 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -674,8 +674,10 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
 
 	rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
 				pdata->num_regulators, GFP_KERNEL);
-	if (!rdata)
+	if (!rdata) {
+		of_node_put(regulators_np);
 		return -ENOMEM;
+	}
 
 	pdata->regulators = rdata;
 	for (i = 0; i < ARRAY_SIZE(regulators); ++i) {
@@ -692,6 +694,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
 	}
 	pdata->num_regulators = rdata - pdata->regulators;
 
+	of_node_put(reg_np);
+	of_node_put(regulators_np);
+
 	ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
 	if (ret)
 		return -EINVAL;
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index da4859282302..05b971726ffa 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -167,8 +167,10 @@ int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 	struct device_node *parent;
 	int num;
 
-	of_node_get(pdev->dev.parent->of_node);
-	parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
+	if (!pdev->dev.parent->of_node)
+		return -ENODEV;
+
+	parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
 	if (!parent)
 		return -ENODEV;
 
@@ -187,8 +189,10 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
 	struct device_node *parent, *child;
 	int i, parsed = 0;
 
-	of_node_get(pdev->dev.parent->of_node);
-	parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
+	if (!pdev->dev.parent->of_node)
+		return NULL;
+
+	parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
 	if (!parent)
 		return NULL;
 
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index ab174f20ca11..129622131147 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -92,7 +92,7 @@ MODULE_DEVICE_TABLE(of, pfuze_dt_ids);
 static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
 	struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
-	int id = rdev->desc->id;
+	int id = rdev_get_id(rdev);
 	unsigned int ramp_bits;
 	int ret;
 
@@ -250,11 +250,11 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
 	struct device_node *np, *parent;
 	int ret;
 
-	np = of_node_get(dev->parent->of_node);
+	np = of_node_get(dev->of_node);
 	if (!np)
-		return 0;
+		return -EINVAL;
 
-	parent = of_find_node_by_name(np, "regulators");
+	parent = of_get_child_by_name(np, "regulators");
 	if (!parent) {
 		dev_err(dev, "regulators node not found\n");
 		return -EINVAL;
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
index b58affb33143..4c414ae109ae 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -119,7 +119,6 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
 {
 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
-	struct regulator_init_data *reg_data;
 	struct regulator_config config = { };
 	struct rc5t583_regulator *reg = NULL;
 	struct rc5t583_regulator *regs;
@@ -135,19 +134,11 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
 
 	regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
 			sizeof(struct rc5t583_regulator), GFP_KERNEL);
-	if (!regs) {
-		dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+	if (!regs)
 		return -ENOMEM;
-	}
 
 
 	for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
-		reg_data = pdata->reg_init_data[id];
-
-		/* No need to register if there is no regulator data */
-		if (!reg_data)
-			continue;
-
 		reg = &regs[id];
 		ri = &rc5t583_reg_info[id];
 		reg->reg_info = ri;
@@ -169,7 +160,7 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
 
 skip_ext_pwr_config:
 		config.dev = &pdev->dev;
-		config.init_data = reg_data;
+		config.init_data = pdata->reg_init_data[id];
 		config.driver_data = reg;
 		config.regmap = rc5t583->regmap;
 
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index cd0b9e35a56d..694d2a9b20f0 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -25,11 +25,8 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
 
-#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
-
 struct s2mps11_info {
-	struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
-
+	unsigned int rdev_num;
 	int ramp_delay2;
 	int ramp_delay34;
 	int ramp_delay5;
@@ -65,7 +62,7 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 	unsigned int ramp_delay = 0;
 	int old_volt, new_volt;
 
-	switch (rdev->desc->id) {
+	switch (rdev_get_id(rdev)) {
 	case S2MPS11_BUCK2:
 		ramp_delay = s2mps11->ramp_delay2;
 		break;
@@ -105,7 +102,7 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 	unsigned int ramp_enable = 1, enable_shift = 0;
 	int ret;
 
-	switch (rdev->desc->id) {
+	switch (rdev_get_id(rdev)) {
 	case S2MPS11_BUCK1:
 		if (ramp_delay > s2mps11->ramp_delay16)
 			s2mps11->ramp_delay16 = ramp_delay;
@@ -345,7 +342,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 	.enable_mask	= S2MPS11_ENABLE_MASK			\
 }
 
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc s2mps11_regulators[] __initconst = {
 	regulator_desc_ldo2(1),
 	regulator_desc_ldo1(2),
 	regulator_desc_ldo1(3),
@@ -396,21 +393,62 @@ static struct regulator_desc regulators[] = {
 	regulator_desc_buck10,
 };
 
+/*
+ * Allocates memory under 'regulators' pointer and copies there array
+ * of regulator_desc for given device.
+ *
+ * Returns number of regulators or negative ERRNO on error.
+ */
+static int __init
+s2mps11_pmic_init_regulators_desc(struct platform_device *pdev,
+		struct regulator_desc **regulators)
+{
+	const struct regulator_desc *regulators_init;
+	enum sec_device_type dev_type;
+	int rdev_num;
+
+	dev_type = platform_get_device_id(pdev)->driver_data;
+	switch (dev_type) {
+	case S2MPS11X:
+		rdev_num = ARRAY_SIZE(s2mps11_regulators);
+		regulators_init = s2mps11_regulators;
+		break;
+	default:
+		dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
+		return -EINVAL;
+	};
+
+	*regulators = devm_kzalloc(&pdev->dev,
+			sizeof(**regulators) * rdev_num, GFP_KERNEL);
+	if (!*regulators)
+		return -ENOMEM;
+
+	memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num);
+
+	return rdev_num;
+}
+
 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 = dev_get_platdata(iodev->dev);
-	struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
+	struct sec_platform_data *pdata = iodev->pdata;
+	struct of_regulator_match *rdata = NULL;
 	struct device_node *reg_np = NULL;
 	struct regulator_config config = { };
 	struct s2mps11_info *s2mps11;
-	int i, ret;
+	int i, ret = 0;
+	struct regulator_desc *regulators = NULL;
+	int rdev_num;
 
 	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
 				GFP_KERNEL);
 	if (!s2mps11)
 		return -ENOMEM;
 
+	rdev_num = s2mps11_pmic_init_regulators_desc(pdev, &regulators);
+	if (rdev_num < 0)
+		return rdev_num;
+
 	if (!iodev->dev->of_node) {
 		if (pdata) {
 			goto common_reg;
@@ -421,24 +459,32 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 		}
 	}
 
-	for (i = 0; i < S2MPS11_REGULATOR_CNT; i++)
+	rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
+	if (!rdata)
+		return -ENOMEM;
+
+	for (i = 0; i < rdev_num; i++)
 		rdata[i].name = regulators[i].name;
 
 	reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
 	if (!reg_np) {
 		dev_err(&pdev->dev, "could not find regulators sub-node\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
+	of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);
 
 common_reg:
 	platform_set_drvdata(pdev, s2mps11);
+	s2mps11->rdev_num = rdev_num;
 
 	config.dev = &pdev->dev;
 	config.regmap = iodev->regmap_pmic;
 	config.driver_data = s2mps11;
-	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+	for (i = 0; i < rdev_num; i++) {
+		struct regulator_dev *regulator;
+
 		if (!reg_np) {
 			config.init_data = pdata->regulators[i].initdata;
 			config.of_node = pdata->regulators[i].reg_node;
@@ -447,21 +493,24 @@ common_reg:
 			config.of_node = rdata[i].of_node;
 		}
 
-		s2mps11->rdev[i] = devm_regulator_register(&pdev->dev,
+		regulator = devm_regulator_register(&pdev->dev,
 						&regulators[i], &config);
-		if (IS_ERR(s2mps11->rdev[i])) {
-			ret = PTR_ERR(s2mps11->rdev[i]);
+		if (IS_ERR(regulator)) {
+			ret = PTR_ERR(regulator);
 			dev_err(&pdev->dev, "regulator init failed for %d\n",
 				i);
-			return ret;
+			goto out;
 		}
 	}
 
-	return 0;
+out:
+	kfree(rdata);
+
+	return ret;
 }
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
-	{ "s2mps11-pmic", 0},
+	{ "s2mps11-pmic", S2MPS11X},
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index d958dfa05125..342a66ab654a 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -11,11 +11,8 @@
  *
  */
 
-#include <linux/bug.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
 #include <linux/of_gpio.h>
-#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
@@ -483,6 +480,65 @@ static struct regulator_desc regulators[] = {
 	s5m8767_regulator_desc(BUCK9),
 };
 
+/*
+ * Enable GPIO control over BUCK9 in regulator_config for that regulator.
+ */
+static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
+		struct sec_regulator_data *rdata,
+		struct regulator_config *config)
+{
+	int i, mode = 0;
+
+	if (rdata->id != S5M8767_BUCK9)
+		return;
+
+	/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
+	for (i = 0; i < s5m8767->num_regulators; i++) {
+		const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
+		if (opmode->id == rdata->id) {
+			mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
+			break;
+		}
+	}
+	if (mode != S5M8767_ENCTRL_USE_GPIO) {
+		dev_warn(s5m8767->dev,
+				"ext-control for %s: mismatched op_mode (%x), ignoring\n",
+				rdata->reg_node->name, mode);
+		return;
+	}
+
+	if (!gpio_is_valid(rdata->ext_control_gpio)) {
+		dev_warn(s5m8767->dev,
+				"ext-control for %s: GPIO not valid, ignoring\n",
+				rdata->reg_node->name);
+		return;
+	}
+
+	config->ena_gpio = rdata->ext_control_gpio;
+	config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+}
+
+/*
+ * Turn on GPIO control over BUCK9.
+ */
+static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
+		struct regulator_dev *rdev)
+{
+	int ret, reg, enable_ctrl;
+
+	if (rdev_get_id(rdev) != S5M8767_BUCK9)
+		return -EINVAL;
+
+	ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(s5m8767->iodev->regmap_pmic,
+			reg, S5M8767_ENCTRL_MASK,
+			S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
+}
+
+
 #ifdef CONFIG_OF
 static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
 			struct sec_platform_data *pdata,
@@ -520,6 +576,16 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
 	return 0;
 }
 
+static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev,
+		struct sec_regulator_data *rdata,
+		struct device_node *reg_np)
+{
+	rdata->ext_control_gpio = of_get_named_gpio(reg_np,
+			"s5m8767,pmic-ext-control-gpios", 0);
+	if (!gpio_is_valid(rdata->ext_control_gpio))
+		rdata->ext_control_gpio = 0;
+}
+
 static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
 					struct sec_platform_data *pdata)
 {
@@ -546,19 +612,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
 
 	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
 				pdata->num_regulators, GFP_KERNEL);
-	if (!rdata) {
-		dev_err(iodev->dev,
-			"could not allocate memory for regulator data\n");
+	if (!rdata)
 		return -ENOMEM;
-	}
 
 	rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
 				pdata->num_regulators, GFP_KERNEL);
-	if (!rmode) {
-		dev_err(iodev->dev,
-			"could not allocate memory for regulator mode\n");
+	if (!rmode)
 		return -ENOMEM;
-	}
 
 	pdata->regulators = rdata;
 	pdata->opmode = rmode;
@@ -574,6 +634,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
 			continue;
 		}
 
+		s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np);
+
 		rdata->id = i;
 		rdata->initdata = of_get_regulator_init_data(
 						&pdev->dev, reg_np);
@@ -942,6 +1004,9 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 		config.driver_data = s5m8767;
 		config.regmap = iodev->regmap_pmic;
 		config.of_node = pdata->regulators[i].reg_node;
+		if (pdata->regulators[i].ext_control_gpio)
+			s5m8767_regulator_config_ext_control(s5m8767,
+					&pdata->regulators[i], &config);
 
 		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
 						  &config);
@@ -951,6 +1016,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 					id);
 			return ret;
 		}
+
+		if (pdata->regulators[i].ext_control_gpio) {
+			ret = s5m8767_enable_ext_control(s5m8767, rdev[i]);
+			if (ret < 0) {
+				dev_err(s5m8767->dev,
+						"failed to enable gpio control over %s: %d\n",
+						rdev[i]->desc->name, ret);
+				return ret;
+			}
+		}
 	}
 
 	return 0;
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index b187b6bba7ad..a2dabb575b97 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -54,8 +54,8 @@ struct ti_abb_info {
 
 /**
  * struct ti_abb_reg - Register description for ABB block
- * @setup_reg:			setup register offset from base
- * @control_reg:		control register offset from base
+ * @setup_off:			setup register offset from base
+ * @control_off:		control register offset from base
  * @sr2_wtcnt_value_mask:	setup register- sr2_wtcnt_value mask
  * @fbb_sel_mask:		setup register- FBB sel mask
  * @rbb_sel_mask:		setup register- RBB sel mask
@@ -64,8 +64,8 @@ struct ti_abb_info {
  * @opp_sel_mask:		control register - mask for mode to operate
  */
 struct ti_abb_reg {
-	u32 setup_reg;
-	u32 control_reg;
+	u32 setup_off;
+	u32 control_off;
 
 	/* Setup register fields */
 	u32 sr2_wtcnt_value_mask;
@@ -83,6 +83,8 @@ struct ti_abb_reg {
  * @rdesc:			regulator descriptor
  * @clk:			clock(usually sysclk) supplying ABB block
  * @base:			base address of ABB block
+ * @setup_reg:			setup register of ABB block
+ * @control_reg:		control register of ABB block
  * @int_base:			interrupt register base address
  * @efuse_base:			(optional) efuse base address for ABB modes
  * @ldo_base:			(optional) LDOVBB vset override base address
@@ -99,6 +101,8 @@ struct ti_abb {
 	struct regulator_desc rdesc;
 	struct clk *clk;
 	void __iomem *base;
+	void __iomem *setup_reg;
+	void __iomem *control_reg;
 	void __iomem *int_base;
 	void __iomem *efuse_base;
 	void __iomem *ldo_base;
@@ -118,20 +122,18 @@ struct ti_abb {
  * ti_abb_rmw() - handy wrapper to set specific register bits
  * @mask:	mask for register field
  * @value:	value shifted to mask location and written
- * @offset:	offset of register
- * @base:	base address
+ * @reg:	register address
  *
  * Return: final register value (may be unused)
  */
-static inline u32 ti_abb_rmw(u32 mask, u32 value, u32 offset,
-			     void __iomem *base)
+static inline u32 ti_abb_rmw(u32 mask, u32 value, void __iomem *reg)
 {
 	u32 val;
 
-	val = readl(base + offset);
+	val = readl(reg);
 	val &= ~mask;
 	val |= (value << __ffs(mask)) & mask;
-	writel(val, base + offset);
+	writel(val, reg);
 
 	return val;
 }
@@ -263,21 +265,19 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
 	if (ret)
 		goto out;
 
-	ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, regs->setup_reg,
-		   abb->base);
+	ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, abb->setup_reg);
 
 	switch (info->opp_sel) {
 	case TI_ABB_SLOW_OPP:
-		ti_abb_rmw(regs->rbb_sel_mask, 1, regs->setup_reg, abb->base);
+		ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg);
 		break;
 	case TI_ABB_FAST_OPP:
-		ti_abb_rmw(regs->fbb_sel_mask, 1, regs->setup_reg, abb->base);
+		ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg);
 		break;
 	}
 
 	/* program next state of ABB ldo */
-	ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg,
-		   abb->base);
+	ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg);
 
 	/*
 	 * program LDO VBB vset override if needed for !bypass mode
@@ -288,7 +288,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
 		ti_abb_program_ldovbb(dev, abb, info);
 
 	/* Initiate ABB ldo change */
-	ti_abb_rmw(regs->opp_change_mask, 1, regs->control_reg, abb->base);
+	ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg);
 
 	/* Wait for ABB LDO to complete transition to new Bias setting */
 	ret = ti_abb_wait_txdone(dev, abb);
@@ -490,8 +490,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb)
 	dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__,
 		clk_get_rate(abb->clk), sr2_wt_cnt_val);
 
-	ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, regs->setup_reg,
-		   abb->base);
+	ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg);
 
 	return 0;
 }
@@ -508,32 +507,24 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
 			     struct regulator_init_data *rinit_data)
 {
 	struct ti_abb_info *info;
-	const struct property *prop;
-	const __be32 *abb_info;
 	const u32 num_values = 6;
 	char *pname = "ti,abb_info";
-	u32 num_entries, i;
+	u32 i;
 	unsigned int *volt_table;
-	int min_uV = INT_MAX, max_uV = 0;
+	int num_entries, min_uV = INT_MAX, max_uV = 0;
 	struct regulation_constraints *c = &rinit_data->constraints;
 
-	prop = of_find_property(dev->of_node, pname, NULL);
-	if (!prop) {
-		dev_err(dev, "No '%s' property?\n", pname);
-		return -ENODEV;
-	}
-
-	if (!prop->value) {
-		dev_err(dev, "Empty '%s' property?\n", pname);
-		return -ENODATA;
-	}
-
 	/*
 	 * Each abb_info is a set of n-tuple, where n is num_values, consisting
 	 * of voltage and a set of detection logic for ABB information for that
 	 * voltage to apply.
 	 */
-	num_entries = prop->length / sizeof(u32);
+	num_entries = of_property_count_u32_elems(dev->of_node, pname);
+	if (num_entries < 0) {
+		dev_err(dev, "No '%s' property?\n", pname);
+		return num_entries;
+	}
+
 	if (!num_entries || (num_entries % num_values)) {
 		dev_err(dev, "All '%s' list entries need %d vals\n", pname,
 			num_values);
@@ -542,38 +533,38 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
 	num_entries /= num_values;
 
 	info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL);
-	if (!info) {
-		dev_err(dev, "Can't allocate info table for '%s' property\n",
-			pname);
+	if (!info)
 		return -ENOMEM;
-	}
+
 	abb->info = info;
 
 	volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries,
 				  GFP_KERNEL);
-	if (!volt_table) {
-		dev_err(dev, "Can't allocate voltage table for '%s' property\n",
-			pname);
+	if (!volt_table)
 		return -ENOMEM;
-	}
 
 	abb->rdesc.n_voltages = num_entries;
 	abb->rdesc.volt_table = volt_table;
 	/* We do not know where the OPP voltage is at the moment */
 	abb->current_info_idx = -EINVAL;
 
-	abb_info = prop->value;
 	for (i = 0; i < num_entries; i++, info++, volt_table++) {
 		u32 efuse_offset, rbb_mask, fbb_mask, vset_mask;
 		u32 efuse_val;
 
 		/* NOTE: num_values should equal to entries picked up here */
-		*volt_table = be32_to_cpup(abb_info++);
-		info->opp_sel = be32_to_cpup(abb_info++);
-		efuse_offset = be32_to_cpup(abb_info++);
-		rbb_mask = be32_to_cpup(abb_info++);
-		fbb_mask = be32_to_cpup(abb_info++);
-		vset_mask = be32_to_cpup(abb_info++);
+		of_property_read_u32_index(dev->of_node, pname, i * num_values,
+					   volt_table);
+		of_property_read_u32_index(dev->of_node, pname,
+					   i * num_values + 1, &info->opp_sel);
+		of_property_read_u32_index(dev->of_node, pname,
+					   i * num_values + 2, &efuse_offset);
+		of_property_read_u32_index(dev->of_node, pname,
+					   i * num_values + 3, &rbb_mask);
+		of_property_read_u32_index(dev->of_node, pname,
+					   i * num_values + 4, &fbb_mask);
+		of_property_read_u32_index(dev->of_node, pname,
+					   i * num_values + 5, &vset_mask);
 
 		dev_dbg(dev,
 			"[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n",
@@ -648,8 +639,8 @@ static struct regulator_ops ti_abb_reg_ops = {
 /* Default ABB block offsets, IF this changes in future, create new one */
 static const struct ti_abb_reg abb_regs_v1 = {
 	/* WARNING: registers are wrongly documented in TRM */
-	.setup_reg		= 0x04,
-	.control_reg		= 0x00,
+	.setup_off		= 0x04,
+	.control_off		= 0x00,
 
 	.sr2_wtcnt_value_mask	= (0xff << 8),
 	.fbb_sel_mask		= (0x01 << 2),
@@ -661,8 +652,8 @@ static const struct ti_abb_reg abb_regs_v1 = {
 };
 
 static const struct ti_abb_reg abb_regs_v2 = {
-	.setup_reg		= 0x00,
-	.control_reg		= 0x04,
+	.setup_off		= 0x00,
+	.control_off		= 0x04,
 
 	.sr2_wtcnt_value_mask	= (0xff << 8),
 	.fbb_sel_mask		= (0x01 << 2),
@@ -673,9 +664,20 @@ static const struct ti_abb_reg abb_regs_v2 = {
 	.opp_sel_mask		= (0x03 << 0),
 };
 
+static const struct ti_abb_reg abb_regs_generic = {
+	.sr2_wtcnt_value_mask	= (0xff << 8),
+	.fbb_sel_mask		= (0x01 << 2),
+	.rbb_sel_mask		= (0x01 << 1),
+	.sr2_en_mask		= (0x01 << 0),
+
+	.opp_change_mask	= (0x01 << 2),
+	.opp_sel_mask		= (0x03 << 0),
+};
+
 static const struct of_device_id ti_abb_of_match[] = {
 	{.compatible = "ti,abb-v1", .data = &abb_regs_v1},
 	{.compatible = "ti,abb-v2", .data = &abb_regs_v2},
+	{.compatible = "ti,abb-v3", .data = &abb_regs_generic},
 	{ },
 };
 
@@ -722,11 +724,29 @@ static int ti_abb_probe(struct platform_device *pdev)
 	abb->regs = match->data;
 
 	/* Map ABB resources */
-	pname = "base-address";
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
-	abb->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(abb->base))
-		return PTR_ERR(abb->base);
+	if (abb->regs->setup_off || abb->regs->control_off) {
+		pname = "base-address";
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
+		abb->base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(abb->base))
+			return PTR_ERR(abb->base);
+
+		abb->setup_reg = abb->base + abb->regs->setup_off;
+		abb->control_reg = abb->base + abb->regs->control_off;
+
+	} else {
+		pname = "control-address";
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
+		abb->control_reg = devm_ioremap_resource(dev, res);
+		if (IS_ERR(abb->control_reg))
+			return PTR_ERR(abb->control_reg);
+
+		pname = "setup-address";
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
+		abb->setup_reg = devm_ioremap_resource(dev, res);
+		if (IS_ERR(abb->setup_reg))
+			return PTR_ERR(abb->setup_reg);
+	}
 
 	pname = "int-address";
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
@@ -860,7 +880,7 @@ skip_opt:
 	platform_set_drvdata(pdev, rdev);
 
 	/* Enable the ldo if not already done by bootloader */
-	ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
+	ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg);
 
 	return 0;
 }
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index b3764f594ee9..f31f22e3e1bd 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -227,10 +227,8 @@ static struct tps51632_regulator_platform_data *
 	struct device_node *np = dev->of_node;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
-		dev_err(dev, "Memory alloc failed for platform data\n");
+	if (!pdata)
 		return NULL;
-	}
 
 	pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
 	if (!pdata->reg_init_data) {
@@ -299,10 +297,8 @@ static int tps51632_probe(struct i2c_client *client,
 	}
 
 	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
-	if (!tps) {
-		dev_err(&client->dev, "Memory allocation failed\n");
+	if (!tps)
 		return -ENOMEM;
-	}
 
 	tps->dev = &client->dev;
 	tps->desc.name = client->name;
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index c3fa15a299b1..a1672044e519 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -299,10 +299,8 @@ static struct tps62360_regulator_platform_data *
 	struct device_node *np = dev->of_node;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
-		dev_err(dev, "Memory alloc failed for platform data\n");
+	if (!pdata)
 		return NULL;
-	}
 
 	pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
 	if (!pdata->reg_init_data) {
@@ -377,11 +375,8 @@ static int tps62360_probe(struct i2c_client *client,
 	}
 
 	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
-	if (!tps) {
-		dev_err(&client->dev, "%s(): Memory allocation failed\n",
-						__func__);
+	if (!tps)
 		return -ENOMEM;
-	}
 
 	tps->en_discharge = pdata->en_discharge;
 	tps->en_internal_pulldn = pdata->en_internal_pulldn;
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 162a0fae20b3..98e66ce26723 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -359,7 +359,6 @@ static struct regulator_ops tps6507x_pmic_ops = {
 	.map_voltage = regulator_map_voltage_ascend,
 };
 
-#ifdef CONFIG_OF
 static struct of_regulator_match tps6507x_matches[] = {
 	{ .name = "VDCDC1"},
 	{ .name = "VDCDC2"},
@@ -381,12 +380,10 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data(
 
 	tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board),
 					GFP_KERNEL);
-	if (!tps_board) {
-		dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n");
+	if (!tps_board)
 		return NULL;
-	}
 
-	regulators = of_find_node_by_name(np, "regulators");
+	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
 		dev_err(&pdev->dev, "regulator node not found\n");
 		return NULL;
@@ -396,6 +393,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data(
 	matches = tps6507x_matches;
 
 	ret = of_regulator_match(&pdev->dev, regulators, matches, count);
+	of_node_put(regulators);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
 			ret);
@@ -406,10 +404,8 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data(
 
 	reg_data = devm_kzalloc(&pdev->dev, (sizeof(struct regulator_init_data)
 					* TPS6507X_NUM_REGULATOR), GFP_KERNEL);
-	if (!reg_data) {
-		dev_err(&pdev->dev, "Failure to alloc init data for regulators.\n");
+	if (!reg_data)
 		return NULL;
-	}
 
 	tps_board->tps6507x_pmic_init_data = reg_data;
 
@@ -424,15 +420,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data(
 
 	return tps_board;
 }
-#else
-static inline struct tps6507x_board *tps6507x_parse_dt_reg_data(
-			struct platform_device *pdev,
-			struct of_regulator_match **tps6507x_reg_matches)
-{
-	*tps6507x_reg_matches = NULL;
-	return NULL;
-}
-#endif
+
 static int tps6507x_pmic_probe(struct platform_device *pdev)
 {
 	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
@@ -453,9 +441,10 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
 	 */
 
 	tps_board = dev_get_platdata(tps6507x_dev->dev);
-	if (!tps_board && tps6507x_dev->dev->of_node)
+	if (IS_ENABLED(CONFIG_OF) && !tps_board &&
+		tps6507x_dev->dev->of_node)
 		tps_board = tps6507x_parse_dt_reg_data(pdev,
-						&tps6507x_reg_matches);
+				&tps6507x_reg_matches);
 	if (!tps_board)
 		return -EINVAL;
 
@@ -481,7 +470,7 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
 		tps->info[i] = info;
 		if (init_data->driver_data) {
 			struct tps6507x_reg_platform_data *data =
-							init_data->driver_data;
+					init_data->driver_data;
 			tps->info[i]->defdcdc_default = data->defdcdc_default;
 		}
 
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 676f75548f00..2e92ef68574d 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -168,17 +168,13 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
 
 	tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata),
 				GFP_KERNEL);
-	if (!tps65090_pdata) {
-		dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n");
+	if (!tps65090_pdata)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX *
 				sizeof(*reg_pdata), GFP_KERNEL);
-	if (!reg_pdata) {
-		dev_err(&pdev->dev, "Memory alloc for reg_pdata failed\n");
+	if (!reg_pdata)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
@@ -188,6 +184,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
 
 	ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches,
 			ARRAY_SIZE(tps65090_matches));
+	of_node_put(regulators);
 	if (ret < 0) {
 		dev_err(&pdev->dev,
 			"Error parsing regulator init data: %d\n", ret);
@@ -252,10 +249,8 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
 
 	pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
 			GFP_KERNEL);
-	if (!pmic) {
-		dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+	if (!pmic)
 		return -ENOMEM;
-	}
 
 	for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
 		tps_pdata = tps65090_pdata->reg_pdata[num];
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 9ea1bf26bd13..10b78d2b766a 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -187,7 +187,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 	struct device_node *regs;
 	int i, count;
 
-	regs = of_find_node_by_name(node, "regulators");
+	regs = of_get_child_by_name(node, "regulators");
 	if (!regs)
 		return NULL;
 
@@ -202,7 +202,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 		return NULL;
 
 	for (i = 0; i < count; i++) {
-		if (!reg_matches[i].init_data || !reg_matches[i].of_node)
+		if (!reg_matches[i].of_node)
 			continue;
 
 		pdata->tps65217_init_data[i] = reg_matches[i].init_data;
@@ -222,7 +222,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
 {
 	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
 	struct tps65217_board *pdata = dev_get_platdata(tps->dev);
-	struct regulator_init_data *reg_data;
 	struct regulator_dev *rdev;
 	struct regulator_config config = { };
 	int i;
@@ -243,19 +242,9 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, tps);
 
 	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
-
-		reg_data = pdata->tps65217_init_data[i];
-
-		/*
-		 * Regulator API handles empty constraints but not NULL
-		 * constraints
-		 */
-		if (!reg_data)
-			continue;
-
 		/* Register the regulators */
 		config.dev = tps->dev;
-		config.init_data = reg_data;
+		config.init_data = pdata->tps65217_init_data[i];
 		config.driver_data = tps;
 		config.regmap = tps->regmap;
 		if (tps->dev->of_node)
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
new file mode 100644
index 000000000000..cec72fa71d1d
--- /dev/null
+++ b/drivers/regulator/tps65218-regulator.c
@@ -0,0 +1,285 @@
+/*
+ * tps65218-regulator.c
+ *
+ * Regulator driver for TPS65218 PMIC
+ *
+ * Copyright (C) 2014 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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/tps65218.h>
+
+static unsigned int tps65218_ramp_delay = 4000;
+
+enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
+
+#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \
+			    _lr, _nlr)				\
+	{							\
+		.name			= _name,		\
+		.id			= _id,			\
+		.ops			= &_ops,		\
+		.n_voltages		= _n,			\
+		.type			= REGULATOR_VOLTAGE,	\
+		.owner			= THIS_MODULE,		\
+		.vsel_reg		= _vr,			\
+		.vsel_mask		= _vm,			\
+		.enable_reg		= _er,			\
+		.enable_mask		= _em,			\
+		.volt_table		= _t,			\
+		.linear_ranges		= _lr,			\
+		.n_linear_ranges	= _nlr,			\
+	}							\
+
+#define TPS65218_INFO(_id, _nm, _min, _max)	\
+	{						\
+		.id		= _id,			\
+		.name		= _nm,			\
+		.min_uV		= _min,			\
+		.max_uV		= _max,			\
+	}
+
+static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000),
+	REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000),
+};
+
+static const struct regulator_linear_range ldo1_dcdc3_ranges[] = {
+	REGULATOR_LINEAR_RANGE(900000, 0x0, 0x1a, 25000),
+	REGULATOR_LINEAR_RANGE(1600000, 0x1b, 0x3f, 50000),
+};
+
+static const struct regulator_linear_range dcdc4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
+	REGULATOR_LINEAR_RANGE(1550000, 0x10, 0x34, 50000),
+};
+
+static struct tps_info tps65218_pmic_regs[] = {
+	TPS65218_INFO(0, "DCDC1", 850000, 167500),
+	TPS65218_INFO(1, "DCDC2", 850000, 1675000),
+	TPS65218_INFO(2, "DCDC3", 900000, 3400000),
+	TPS65218_INFO(3, "DCDC4", 1175000, 3400000),
+	TPS65218_INFO(4, "DCDC5", 1000000, 1000000),
+	TPS65218_INFO(5, "DCDC6", 1800000, 1800000),
+	TPS65218_INFO(6, "LDO1", 900000, 3400000),
+};
+
+#define TPS65218_OF_MATCH(comp, label) \
+	{ \
+		.compatible = comp, \
+		.data = &label, \
+	}
+
+static const struct of_device_id tps65218_of_match[] = {
+	TPS65218_OF_MATCH("ti,tps65218-dcdc1", tps65218_pmic_regs[DCDC1]),
+	TPS65218_OF_MATCH("ti,tps65218-dcdc2", tps65218_pmic_regs[DCDC2]),
+	TPS65218_OF_MATCH("ti,tps65218-dcdc3", tps65218_pmic_regs[DCDC3]),
+	TPS65218_OF_MATCH("ti,tps65218-dcdc4", tps65218_pmic_regs[DCDC4]),
+	TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[DCDC5]),
+	TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[DCDC6]),
+	TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[LDO1]),
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tps65218_of_match);
+
+static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev,
+					 unsigned selector)
+{
+	int ret;
+	struct tps65218 *tps = rdev_get_drvdata(dev);
+	unsigned int rid = rdev_get_id(dev);
+
+	/* Set the voltage based on vsel value and write protect level is 2 */
+	ret = tps65218_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
+				selector, TPS65218_PROTECT_L1);
+
+	/* Set GO bit for DCDC1/2 to initiate voltage transistion */
+	switch (rid) {
+	case TPS65218_DCDC_1:
+	case TPS65218_DCDC_2:
+		ret = tps65218_set_bits(tps, TPS65218_REG_CONTRL_SLEW_RATE,
+					TPS65218_SLEW_RATE_GO,
+					TPS65218_SLEW_RATE_GO,
+					TPS65218_PROTECT_L1);
+		break;
+	}
+
+	return ret;
+}
+
+static int tps65218_pmic_enable(struct regulator_dev *dev)
+{
+	struct tps65218 *tps = rdev_get_drvdata(dev);
+	unsigned int rid = rdev_get_id(dev);
+
+	if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+		return -EINVAL;
+
+	/* Enable the regulator and password protection is level 1 */
+	return tps65218_set_bits(tps, dev->desc->enable_reg,
+				 dev->desc->enable_mask, dev->desc->enable_mask,
+				 TPS65218_PROTECT_L1);
+}
+
+static int tps65218_pmic_disable(struct regulator_dev *dev)
+{
+	struct tps65218 *tps = rdev_get_drvdata(dev);
+	unsigned int rid = rdev_get_id(dev);
+
+	if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+		return -EINVAL;
+
+	/* Disable the regulator and password protection is level 1 */
+	return tps65218_clear_bits(tps, dev->desc->enable_reg,
+				   dev->desc->enable_mask, TPS65218_PROTECT_L1);
+}
+
+static int tps65218_set_voltage_time_sel(struct regulator_dev *rdev,
+	unsigned int old_selector, unsigned int new_selector)
+{
+	int old_uv, new_uv;
+
+	old_uv = regulator_list_voltage_linear_range(rdev, old_selector);
+	if (old_uv < 0)
+		return old_uv;
+
+	new_uv = regulator_list_voltage_linear_range(rdev, new_selector);
+	if (new_uv < 0)
+		return new_uv;
+
+	return DIV_ROUND_UP(abs(old_uv - new_uv), tps65218_ramp_delay);
+}
+
+/* Operations permitted on DCDC1, DCDC2 */
+static struct regulator_ops tps65218_dcdc12_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= tps65218_pmic_enable,
+	.disable		= tps65218_pmic_disable,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= tps65218_pmic_set_voltage_sel,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+	.set_voltage_time_sel	= tps65218_set_voltage_time_sel,
+};
+
+/* Operations permitted on DCDC3, DCDC4 and LDO1 */
+static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= tps65218_pmic_enable,
+	.disable		= tps65218_pmic_disable,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= tps65218_pmic_set_voltage_sel,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+};
+
+/* Operations permitted on DCDC5, DCDC6 */
+static struct regulator_ops tps65218_dcdc56_pmic_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= tps65218_pmic_enable,
+	.disable		= tps65218_pmic_disable,
+};
+
+static const struct regulator_desc regulators[] = {
+	TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64,
+			   TPS65218_REG_CONTROL_DCDC1,
+			   TPS65218_CONTROL_DCDC1_MASK,
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL,
+			   dcdc1_dcdc2_ranges, 2),
+	TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
+			   TPS65218_REG_CONTROL_DCDC2,
+			   TPS65218_CONTROL_DCDC2_MASK,
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL,
+			   dcdc1_dcdc2_ranges, 2),
+	TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
+			   64, TPS65218_REG_CONTROL_DCDC3,
+			   TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
+			   TPS65218_ENABLE1_DC3_EN, NULL,
+			   ldo1_dcdc3_ranges, 2),
+	TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
+			   53, TPS65218_REG_CONTROL_DCDC4,
+			   TPS65218_CONTROL_DCDC4_MASK,
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL,
+			   dcdc4_ranges, 2),
+	TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
+			   1, -1, -1, TPS65218_REG_ENABLE1,
+			   TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0),
+	TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
+			   1, -1, -1, TPS65218_REG_ENABLE1,
+			   TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0),
+	TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
+			   TPS65218_REG_CONTROL_DCDC4,
+			   TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
+			   TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges,
+			   2),
+};
+
+static int tps65218_regulator_probe(struct platform_device *pdev)
+{
+	struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct regulator_init_data *init_data;
+	const struct tps_info	*template;
+	struct regulator_dev *rdev;
+	const struct of_device_id	*match;
+	struct regulator_config config = { };
+	int id;
+
+	match = of_match_device(tps65218_of_match, &pdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	template = match->data;
+	id = template->id;
+	init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+
+	platform_set_drvdata(pdev, tps);
+
+	tps->info[id] = &tps65218_pmic_regs[id];
+	config.dev = &pdev->dev;
+	config.init_data = init_data;
+	config.driver_data = tps;
+	config.regmap = tps->regmap;
+
+	rdev = devm_regulator_register(&pdev->dev, &regulators[id], &config);
+	if (IS_ERR(rdev)) {
+		dev_err(tps->dev, "failed to register %s regulator\n",
+			pdev->name);
+		return PTR_ERR(rdev);
+	}
+
+	return 0;
+}
+
+static struct platform_driver tps65218_regulator_driver = {
+	.driver = {
+		.name = "tps65218-pmic",
+		.owner = THIS_MODULE,
+		.of_match_table = tps65218_of_match,
+	},
+	.probe = tps65218_regulator_probe,
+};
+
+module_platform_driver(tps65218_regulator_driver);
+
+MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
+MODULE_DESCRIPTION("TPS65218 voltage regulator driver");
+MODULE_ALIAS("platform:tps65218-pmic");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 9f6bfda711b7..5b494db9f95c 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -593,10 +593,9 @@ static int pmic_probe(struct spi_device *spi)
 	}
 
 	hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);
-	if (!hw) {
-		dev_err(dev, "cannot allocate regulator private data\n");
+	if (!hw)
 		return -ENOMEM;
-	}
+
 	spi_set_drvdata(spi, hw);
 
 	memset(hw, 0, sizeof(struct tps6524x));
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 0485d47f0d8a..e36f3569767f 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -363,10 +363,8 @@ static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
 	}
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
-		dev_err(&pdev->dev, "Memory alloction failed\n");
+	if (!pdata)
 		return NULL;
-	}
 
 	for (i = 0; i < num; i++) {
 		int id;
@@ -420,10 +418,8 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
 
 	rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
 				sizeof(*rdev), GFP_KERNEL);
-	if (!rdev) {
-		dev_err(&pdev->dev, "Mmemory alloc failed\n");
+	if (!rdev)
 		return -ENOMEM;
-	}
 
 	version = tps6586x_get_version(pdev->dev.parent);
 
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index f50dd847eebc..fa7db8847578 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1011,11 +1011,8 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
 
 	pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data),
 					GFP_KERNEL);
-
-	if (!pmic_plat_data) {
-		dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n");
+	if (!pmic_plat_data)
 		return NULL;
-	}
 
 	np = of_node_get(pdev->dev.parent->of_node);
 	regulators = of_get_child_by_name(np, "regulators");
@@ -1098,10 +1095,8 @@ static int tps65910_probe(struct platform_device *pdev)
 	}
 
 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
-	if (!pmic) {
-		dev_err(&pdev->dev, "Memory allocation failed for pmic\n");
+	if (!pmic)
 		return -ENOMEM;
-	}
 
 	pmic->mfd = tps65910;
 	platform_set_drvdata(pdev, pmic);
@@ -1130,24 +1125,18 @@ static int tps65910_probe(struct platform_device *pdev)
 
 	pmic->desc = devm_kzalloc(&pdev->dev, pmic->num_regulators *
 			sizeof(struct regulator_desc), GFP_KERNEL);
-	if (!pmic->desc) {
-		dev_err(&pdev->dev, "Memory alloc fails for desc\n");
+	if (!pmic->desc)
 		return -ENOMEM;
-	}
 
 	pmic->info = devm_kzalloc(&pdev->dev, pmic->num_regulators *
 			sizeof(struct tps_info *), GFP_KERNEL);
-	if (!pmic->info) {
-		dev_err(&pdev->dev, "Memory alloc fails for info\n");
+	if (!pmic->info)
 		return -ENOMEM;
-	}
 
 	pmic->rdev = devm_kzalloc(&pdev->dev, pmic->num_regulators *
 			sizeof(struct regulator_dev *), GFP_KERNEL);
-	if (!pmic->rdev) {
-		dev_err(&pdev->dev, "Memory alloc fails for rdev\n");
+	if (!pmic->rdev)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS;
 			i++, info++) {
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index 71f457a42623..ac88c988bb2e 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -693,10 +693,8 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
 
 	pmic = devm_kzalloc(&pdev->dev,
 			TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
-	if (!pmic) {
-		dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+	if (!pmic)
 		return -ENOMEM;
-	}
 
 	for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
 		tps_pdata = pdata->regulator_pdata[num];
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 04cf9c16ef23..0d88a82ab2a2 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -469,10 +469,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
 
 	dcdc = devm_kzalloc(&pdev->dev,  sizeof(struct wm831x_dcdc),
 			    GFP_KERNEL);
-	if (dcdc == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!dcdc)
 		return -ENOMEM;
-	}
 
 	dcdc->wm831x = wm831x;
 
@@ -622,10 +620,8 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
 
 	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
 			    GFP_KERNEL);
-	if (dcdc == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!dcdc)
 		return -ENOMEM;
-	}
 
 	dcdc->wm831x = wm831x;
 
@@ -752,10 +748,8 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
 		return -ENODEV;
 
 	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
-	if (dcdc == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!dcdc)
 		return -ENOMEM;
-	}
 
 	dcdc->wm831x = wm831x;
 
@@ -842,10 +836,8 @@ static int wm831x_epe_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1);
 
 	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
-	if (dcdc == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!dcdc)
 		return -ENOMEM;
-	}
 
 	dcdc->wm831x = wm831x;
 
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 0339b886df5d..72e385e76a9d 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -165,10 +165,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
 
 	isink = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_isink),
 			     GFP_KERNEL);
-	if (isink == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!isink)
 		return -ENOMEM;
-	}
 
 	isink->wm831x = wm831x;
 
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 46d6700467b5..eca0eeb78acd 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -235,10 +235,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
-	if (ldo == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!ldo)
 		return -ENOMEM;
-	}
 
 	ldo->wm831x = wm831x;
 
@@ -447,10 +445,8 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
-	if (ldo == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!ldo)
 		return -ENOMEM;
-	}
 
 	ldo->wm831x = wm831x;
 
@@ -594,10 +590,8 @@ static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
-	if (ldo == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!ldo)
 		return -ENOMEM;
-	}
 
 	ldo->wm831x = wm831x;
 
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index de7b9c73e3fa..7ec7c390eeda 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -361,7 +361,7 @@ static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 
 	sel = regulator_map_voltage_linear(rdev, uV, uV);
 	if (sel < 0)
-		return -EINVAL;
+		return sel;
 
 	/* all DCDCs have same mV bits */
 	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
@@ -574,7 +574,7 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 
 	sel = regulator_map_voltage_linear_range(rdev, uV, uV);
 	if (sel < 0)
-		return -EINVAL;
+		return sel;
 
 	/* all LDOs have same mV bits */
 	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 71c5911f2e71..c24346db8a71 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -134,10 +134,8 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_ldo), GFP_KERNEL);
-	if (ldo == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate private data\n");
+	if (!ldo)
 		return -ENOMEM;
-	}
 
 	ldo->wm8994 = wm8994;
 	ldo->supply = wm8994_ldo_consumer[id];
diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index 129f7b997866..3841b9813109 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -201,23 +201,11 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
 	}
 
 	bootreg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!bootreg_res) {
-		dev_err(dev,
-			"platform_get_resource(IORESOURCE_MEM, 0): NULL\n");
-		return -EADDRNOTAVAIL;
-	}
-
-	chipsig_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!chipsig_res) {
-		dev_err(dev,
-			"platform_get_resource(IORESOURCE_MEM, 1): NULL\n");
-		return -EADDRNOTAVAIL;
-	}
-
 	bootreg = devm_ioremap_resource(dev, bootreg_res);
 	if (IS_ERR(bootreg))
 		return PTR_ERR(bootreg);
 
+	chipsig_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	chipsig = devm_ioremap_resource(dev, chipsig_res);
 	if (IS_ERR(chipsig))
 		return PTR_ERR(chipsig);
@@ -301,8 +289,6 @@ static int da8xx_rproc_remove(struct platform_device *pdev)
 	 */
 	disable_irq(drproc->irq);
 
-	devm_clk_put(dev, drproc->dsp_clk);
-
 	rproc_del(rproc);
 	rproc_put(rproc);
 
diff --git a/drivers/remoteproc/ste_modem_rproc.c b/drivers/remoteproc/ste_modem_rproc.c
index 1ec39a4c0b3e..c4ac9104dd8e 100644
--- a/drivers/remoteproc/ste_modem_rproc.c
+++ b/drivers/remoteproc/ste_modem_rproc.c
@@ -164,7 +164,7 @@ sproc_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw)
 }
 
 /* STE modem firmware handler operations */
-const struct rproc_fw_ops sproc_fw_ops = {
+static const struct rproc_fw_ops sproc_fw_ops = {
 	.load = sproc_load_segments,
 	.find_rsc_table = sproc_find_rsc_table,
 	.find_loaded_rsc_table = sproc_find_loaded_rsc_table,
@@ -193,7 +193,7 @@ static void sproc_kick_callback(struct ste_modem_device *mdev, int vqid)
 		sproc_dbg(sproc, "no message was found in vqid %d\n", vqid);
 }
 
-struct ste_modem_dev_cb sproc_dev_cb = {
+static struct ste_modem_dev_cb sproc_dev_cb = {
 	.kick = sproc_kick_callback,
 };
 
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 544be722937c..c2eff6082363 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -584,6 +584,9 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
 void rtc_update_irq(struct rtc_device *rtc,
 		unsigned long num, unsigned long events)
 {
+	if (unlikely(IS_ERR_OR_NULL(rtc)))
+		return;
+
 	pm_stay_awake(rtc->dev.parent);
 	schedule_work(&rtc->irqwork);
 }
diff --git a/drivers/rtc/rtc-as3722.c b/drivers/rtc/rtc-as3722.c
index 4af016985890..9f38eda69154 100644
--- a/drivers/rtc/rtc-as3722.c
+++ b/drivers/rtc/rtc-as3722.c
@@ -242,9 +242,8 @@ static int as3722_rtc_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops as3722_rtc_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(as3722_rtc_suspend, as3722_rtc_resume)
-};
+static SIMPLE_DEV_PM_OPS(as3722_rtc_pm_ops, as3722_rtc_suspend,
+			 as3722_rtc_resume);
 
 static struct platform_driver as3722_rtc_driver = {
 	.probe = as3722_rtc_probe,
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index 3161ab5263ed..aee3387fb099 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -204,10 +204,8 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(struct rtc_at32ap700x),
 			   GFP_KERNEL);
-	if (!rtc) {
-		dev_dbg(&pdev->dev, "out of memory\n");
+	if (!rtc)
 		return -ENOMEM;
-	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 309b8b342d9c..596374304532 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -24,7 +24,7 @@
 
 #include <mach/at91_rtt.h>
 #include <mach/cpu.h>
-
+#include <mach/hardware.h>
 
 /*
  * This driver uses two configurable hardware resources that live in the
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index cae212f30d65..0963c9309c74 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -837,7 +837,7 @@ static void __exit cmos_do_remove(struct device *dev)
 	cmos->dev = NULL;
 }
 
-#ifdef	CONFIG_PM
+#ifdef	CONFIG_PM_SLEEP
 
 static int cmos_suspend(struct device *dev)
 {
@@ -935,8 +935,6 @@ static int cmos_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
-
 #else
 
 static inline int cmos_poweroff(struct device *dev)
@@ -946,6 +944,8 @@ static inline int cmos_poweroff(struct device *dev)
 
 #endif
 
+static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
+
 /*----------------------------------------------------------------*/
 
 /* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus.
@@ -1088,11 +1088,9 @@ static struct pnp_driver cmos_pnp_driver = {
 
 	/* flag ensures resume() gets called, and stops syslog spam */
 	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
-#ifdef CONFIG_PM_SLEEP
 	.driver		= {
 			.pm = &cmos_pm_ops,
 	},
-#endif
 };
 
 #endif	/* CONFIG_PNP */
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index 73f157519dff..869cae273799 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -43,8 +43,6 @@
 struct coh901331_port {
 	struct rtc_device *rtc;
 	struct clk *clk;
-	u32 phybase;
-	u32 physize;
 	void __iomem *virtbase;
 	int irq;
 #ifdef CONFIG_PM_SLEEP
@@ -173,19 +171,9 @@ static int __init coh901331_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-
-	rtap->phybase = res->start;
-	rtap->physize = resource_size(res);
-
-	if (devm_request_mem_region(&pdev->dev, rtap->phybase, rtap->physize,
-				    "rtc-coh901331") == NULL)
-		return -EBUSY;
-
-	rtap->virtbase = devm_ioremap(&pdev->dev, rtap->phybase, rtap->physize);
-	if (!rtap->virtbase)
-		return -ENOMEM;
+	rtap->virtbase  = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rtap->virtbase))
+		return PTR_ERR(rtap->virtbase);
 
 	rtap->irq = platform_get_irq(pdev, 0);
 	if (devm_request_irq(&pdev->dev, rtap->irq, coh901331_interrupt, 0,
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c
index 4385ca4503da..a1cbf64242a5 100644
--- a/drivers/rtc/rtc-da9052.c
+++ b/drivers/rtc/rtc-da9052.c
@@ -26,7 +26,6 @@
 struct da9052_rtc {
 	struct rtc_device *rtc;
 	struct da9052 *da9052;
-	int irq;
 };
 
 static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
@@ -240,8 +239,7 @@ static int da9052_rtc_probe(struct platform_device *pdev)
 
 	rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
 	platform_set_drvdata(pdev, rtc);
-	rtc->irq =  DA9052_IRQ_ALARM;
-	ret = da9052_request_irq(rtc->da9052, rtc->irq, "ALM",
+	ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
 				da9052_rtc_irq, rtc);
 	if (ret != 0) {
 		rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 24677ef8c39a..c0a3b59f65a2 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -119,8 +119,6 @@ static DEFINE_SPINLOCK(davinci_rtc_lock);
 struct davinci_rtc {
 	struct rtc_device		*rtc;
 	void __iomem			*base;
-	resource_size_t			pbase;
-	size_t				base_size;
 	int				irq;
 };
 
@@ -482,14 +480,12 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct davinci_rtc *davinci_rtc;
-	struct resource *res, *mem;
+	struct resource *res;
 	int ret = 0;
 
 	davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL);
-	if (!davinci_rtc) {
-		dev_dbg(dev, "could not allocate memory for private data\n");
+	if (!davinci_rtc)
 		return -ENOMEM;
-	}
 
 	davinci_rtc->irq = platform_get_irq(pdev, 0);
 	if (davinci_rtc->irq < 0) {
@@ -498,28 +494,9 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "no mem resource\n");
-		return -EINVAL;
-	}
-
-	davinci_rtc->pbase = res->start;
-	davinci_rtc->base_size = resource_size(res);
-
-	mem = devm_request_mem_region(dev, davinci_rtc->pbase,
-				davinci_rtc->base_size, pdev->name);
-	if (!mem) {
-		dev_err(dev, "RTC registers at %08x are not free\n",
-			davinci_rtc->pbase);
-		return -EBUSY;
-	}
-
-	davinci_rtc->base = devm_ioremap(dev, davinci_rtc->pbase,
-					davinci_rtc->base_size);
-	if (!davinci_rtc->base) {
-		dev_err(dev, "unable to ioremap MEM resource\n");
-		return -ENOMEM;
-	}
+	davinci_rtc->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(davinci_rtc->base))
+		return PTR_ERR(davinci_rtc->base);
 
 	platform_set_drvdata(pdev, davinci_rtc);
 
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 4e75345a559a..580379a97f0c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -154,6 +154,7 @@ static const struct chip_desc chips[last_ds_type] = {
 		.alarm		= 1,
 	},
 	[mcp7941x] = {
+		.alarm		= 1,
 		/* this is battery backed SRAM */
 		.nvram_offset	= 0x20,
 		.nvram_size	= 0x40,
@@ -606,6 +607,178 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
 
 /*----------------------------------------------------------------------*/
 
+/*
+ * Alarm support for mcp7941x devices.
+ */
+
+#define MCP7941X_REG_CONTROL		0x07
+#	define MCP7941X_BIT_ALM0_EN	0x10
+#	define MCP7941X_BIT_ALM1_EN	0x20
+#define MCP7941X_REG_ALARM0_BASE	0x0a
+#define MCP7941X_REG_ALARM0_CTRL	0x0d
+#define MCP7941X_REG_ALARM1_BASE	0x11
+#define MCP7941X_REG_ALARM1_CTRL	0x14
+#	define MCP7941X_BIT_ALMX_IF	(1 << 3)
+#	define MCP7941X_BIT_ALMX_C0	(1 << 4)
+#	define MCP7941X_BIT_ALMX_C1	(1 << 5)
+#	define MCP7941X_BIT_ALMX_C2	(1 << 6)
+#	define MCP7941X_BIT_ALMX_POL	(1 << 7)
+#	define MCP7941X_MSK_ALMX_MATCH	(MCP7941X_BIT_ALMX_C0 | \
+					 MCP7941X_BIT_ALMX_C1 | \
+					 MCP7941X_BIT_ALMX_C2)
+
+static void mcp7941x_work(struct work_struct *work)
+{
+	struct ds1307 *ds1307 = container_of(work, struct ds1307, work);
+	struct i2c_client *client = ds1307->client;
+	int reg, ret;
+
+	mutex_lock(&ds1307->rtc->ops_lock);
+
+	/* Check and clear alarm 0 interrupt flag. */
+	reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_ALARM0_CTRL);
+	if (reg < 0)
+		goto out;
+	if (!(reg & MCP7941X_BIT_ALMX_IF))
+		goto out;
+	reg &= ~MCP7941X_BIT_ALMX_IF;
+	ret = i2c_smbus_write_byte_data(client, MCP7941X_REG_ALARM0_CTRL, reg);
+	if (ret < 0)
+		goto out;
+
+	/* Disable alarm 0. */
+	reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_CONTROL);
+	if (reg < 0)
+		goto out;
+	reg &= ~MCP7941X_BIT_ALM0_EN;
+	ret = i2c_smbus_write_byte_data(client, MCP7941X_REG_CONTROL, reg);
+	if (ret < 0)
+		goto out;
+
+	rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+
+out:
+	if (test_bit(HAS_ALARM, &ds1307->flags))
+		enable_irq(client->irq);
+	mutex_unlock(&ds1307->rtc->ops_lock);
+}
+
+static int mcp7941x_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds1307 *ds1307 = i2c_get_clientdata(client);
+	u8 *regs = ds1307->regs;
+	int ret;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	/* Read control and alarm 0 registers. */
+	ret = ds1307->read_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
+	if (ret < 0)
+		return ret;
+
+	t->enabled = !!(regs[0] & MCP7941X_BIT_ALM0_EN);
+
+	/* Report alarm 0 time assuming 24-hour and day-of-month modes. */
+	t->time.tm_sec = bcd2bin(ds1307->regs[3] & 0x7f);
+	t->time.tm_min = bcd2bin(ds1307->regs[4] & 0x7f);
+	t->time.tm_hour = bcd2bin(ds1307->regs[5] & 0x3f);
+	t->time.tm_wday = bcd2bin(ds1307->regs[6] & 0x7) - 1;
+	t->time.tm_mday = bcd2bin(ds1307->regs[7] & 0x3f);
+	t->time.tm_mon = bcd2bin(ds1307->regs[8] & 0x1f) - 1;
+	t->time.tm_year = -1;
+	t->time.tm_yday = -1;
+	t->time.tm_isdst = -1;
+
+	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
+		"enabled=%d polarity=%d irq=%d match=%d\n", __func__,
+		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled,
+		!!(ds1307->regs[6] & MCP7941X_BIT_ALMX_POL),
+		!!(ds1307->regs[6] & MCP7941X_BIT_ALMX_IF),
+		(ds1307->regs[6] & MCP7941X_MSK_ALMX_MATCH) >> 4);
+
+	return 0;
+}
+
+static int mcp7941x_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds1307 *ds1307 = i2c_get_clientdata(client);
+	unsigned char *regs = ds1307->regs;
+	int ret;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
+		"enabled=%d pending=%d\n", __func__,
+		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
+		t->enabled, t->pending);
+
+	/* Read control and alarm 0 registers. */
+	ret = ds1307->read_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
+	if (ret < 0)
+		return ret;
+
+	/* Set alarm 0, using 24-hour and day-of-month modes. */
+	regs[3] = bin2bcd(t->time.tm_sec);
+	regs[4] = bin2bcd(t->time.tm_min);
+	regs[5] = bin2bcd(t->time.tm_hour);
+	regs[6] = bin2bcd(t->time.tm_wday) + 1;
+	regs[7] = bin2bcd(t->time.tm_mday);
+	regs[8] = bin2bcd(t->time.tm_mon) + 1;
+
+	/* Clear the alarm 0 interrupt flag. */
+	regs[6] &= ~MCP7941X_BIT_ALMX_IF;
+	/* Set alarm match: second, minute, hour, day, date, month. */
+	regs[6] |= MCP7941X_MSK_ALMX_MATCH;
+
+	if (t->enabled)
+		regs[0] |= MCP7941X_BIT_ALM0_EN;
+	else
+		regs[0] &= ~MCP7941X_BIT_ALM0_EN;
+
+	ret = ds1307->write_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mcp7941x_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds1307 *ds1307 = i2c_get_clientdata(client);
+	int reg;
+
+	if (!test_bit(HAS_ALARM, &ds1307->flags))
+		return -EINVAL;
+
+	reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_CONTROL);
+	if (reg < 0)
+		return reg;
+
+	if (enabled)
+		reg |= MCP7941X_BIT_ALM0_EN;
+	else
+		reg &= ~MCP7941X_BIT_ALM0_EN;
+
+	return i2c_smbus_write_byte_data(client, MCP7941X_REG_CONTROL, reg);
+}
+
+static const struct rtc_class_ops mcp7941x_rtc_ops = {
+	.read_time	= ds1307_get_time,
+	.set_time	= ds1307_set_time,
+	.read_alarm	= mcp7941x_read_alarm,
+	.set_alarm	= mcp7941x_set_alarm,
+	.alarm_irq_enable = mcp7941x_alarm_irq_enable,
+};
+
+/*----------------------------------------------------------------------*/
+
 static ssize_t
 ds1307_nvram_read(struct file *filp, struct kobject *kobj,
 		struct bin_attribute *attr,
@@ -678,6 +851,7 @@ static int ds1307_probe(struct i2c_client *client,
 		[ds_1339] = DS1339_BIT_BBSQI,
 		[ds_3231] = DS3231_BIT_BBSQW,
 	};
+	const struct rtc_class_ops *rtc_ops = &ds13xx_rtc_ops;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)
 	    && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
@@ -816,6 +990,13 @@ static int ds1307_probe(struct i2c_client *client,
 	case ds_1388:
 		ds1307->offset = 1; /* Seconds starts at 1 */
 		break;
+	case mcp7941x:
+		rtc_ops = &mcp7941x_rtc_ops;
+		if (ds1307->client->irq > 0 && chip->alarm) {
+			INIT_WORK(&ds1307->work, mcp7941x_work);
+			want_irq = true;
+		}
+		break;
 	default:
 		break;
 	}
@@ -927,8 +1108,9 @@ read_rtc:
 				bin2bcd(tmp));
 	}
 
+	device_set_wakeup_capable(&client->dev, want_irq);
 	ds1307->rtc = devm_rtc_device_register(&client->dev, client->name,
-				&ds13xx_rtc_ops, THIS_MODULE);
+				rtc_ops, THIS_MODULE);
 	if (IS_ERR(ds1307->rtc)) {
 		err = PTR_ERR(ds1307->rtc);
 		dev_err(&client->dev,
@@ -945,7 +1127,6 @@ read_rtc:
 			goto exit;
 		}
 
-		device_set_wakeup_capable(&client->dev, 1);
 		set_bit(HAS_ALARM, &ds1307->flags);
 		dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
 	}
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index be9d8c0a7e3a..e67bfcb3a1aa 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -132,10 +132,9 @@ static int ds1390_probe(struct spi_device *spi)
 	spi_setup(spi);
 
 	chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
-	if (!chip) {
-		dev_err(&spi->dev, "unable to allocate device memory\n");
+	if (!chip)
 		return -ENOMEM;
-	}
+
 	spi_set_drvdata(spi, chip);
 
 	res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp);
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index b83bb5a527f8..9b9fe5f9fe41 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -57,6 +57,7 @@ struct ds3232 {
 	 * in the remove function.
 	 */
 	struct mutex mutex;
+	bool suspended;
 	int exiting;
 };
 
@@ -345,7 +346,15 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id)
 	struct ds3232 *ds3232 = i2c_get_clientdata(client);
 
 	disable_irq_nosync(irq);
-	schedule_work(&ds3232->work);
+
+	/*
+	 * If rtc as a wakeup source, can't schedule the work
+	 * at system resume flow, because at this time the i2c bus
+	 * has not been resumed.
+	 */
+	if (!ds3232->suspended)
+		schedule_work(&ds3232->work);
+
 	return IRQ_HANDLED;
 }
 
@@ -363,22 +372,26 @@ static void ds3232_work(struct work_struct *work)
 
 	if (stat & DS3232_REG_SR_A1F) {
 		control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-		if (control < 0)
-			goto out;
-		/* disable alarm1 interrupt */
-		control &= ~(DS3232_REG_CR_A1IE);
-		i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
-
-		/* clear the alarm pend flag */
-		stat &= ~DS3232_REG_SR_A1F;
-		i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
-
-		rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
+		if (control < 0) {
+			pr_warn("Read DS3232 Control Register error."
+				"Disable IRQ%d.\n", client->irq);
+		} else {
+			/* disable alarm1 interrupt */
+			control &= ~(DS3232_REG_CR_A1IE);
+			i2c_smbus_write_byte_data(client, DS3232_REG_CR,
+						control);
+
+			/* clear the alarm pend flag */
+			stat &= ~DS3232_REG_SR_A1F;
+			i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
+
+			rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
+
+			if (!ds3232->exiting)
+				enable_irq(client->irq);
+		}
 	}
 
-out:
-	if (!ds3232->exiting)
-		enable_irq(client->irq);
 unlock:
 	mutex_unlock(&ds3232->mutex);
 }
@@ -411,23 +424,18 @@ static int ds3232_probe(struct i2c_client *client,
 	if (ret)
 		return ret;
 
-	ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
-					  &ds3232_rtc_ops, THIS_MODULE);
-	if (IS_ERR(ds3232->rtc)) {
-		dev_err(&client->dev, "unable to register the class device\n");
-		return PTR_ERR(ds3232->rtc);
-	}
-
-	if (client->irq >= 0) {
-		ret = devm_request_irq(&client->dev, client->irq, ds3232_irq, 0,
-				 "ds3232", client);
+	if (client->irq > 0) {
+		ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
+				       IRQF_SHARED, "ds3232", client);
 		if (ret) {
 			dev_err(&client->dev, "unable to request IRQ\n");
 			return ret;
 		}
+		device_init_wakeup(&client->dev, 1);
 	}
-
-	return 0;
+	ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
+					  &ds3232_rtc_ops, THIS_MODULE);
+	return PTR_ERR_OR_ZERO(ds3232->rtc);
 }
 
 static int ds3232_remove(struct i2c_client *client)
@@ -446,6 +454,42 @@ static int ds3232_remove(struct i2c_client *client)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int ds3232_suspend(struct device *dev)
+{
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_can_wakeup(dev)) {
+		ds3232->suspended = true;
+		irq_set_irq_wake(client->irq, 1);
+	}
+
+	return 0;
+}
+
+static int ds3232_resume(struct device *dev)
+{
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (ds3232->suspended) {
+		ds3232->suspended = false;
+
+		/* Clear the hardware alarm pend flag */
+		schedule_work(&ds3232->work);
+
+		irq_set_irq_wake(client->irq, 0);
+	}
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops ds3232_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
+};
+
 static const struct i2c_device_id ds3232_id[] = {
 	{ "ds3232", 0 },
 	{ }
@@ -456,6 +500,7 @@ static struct i2c_driver ds3232_driver = {
 	.driver = {
 		.name = "rtc-ds3232",
 		.owner = THIS_MODULE,
+		.pm	= &ds3232_pm_ops,
 	},
 	.probe = ds3232_probe,
 	.remove = ds3232_remove,
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index abd7f9091f34..cd741c77e085 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -401,7 +401,9 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
 	imxdi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(imxdi->clk))
 		return PTR_ERR(imxdi->clk);
-	clk_prepare_enable(imxdi->clk);
+	rc = clk_prepare_enable(imxdi->clk);
+	if (rc)
+		return rc;
 
 	/*
 	 * Initialize dryice hardware
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c
index 7854a656628f..41bd76aaff76 100644
--- a/drivers/rtc/rtc-isl12057.c
+++ b/drivers/rtc/rtc-isl12057.c
@@ -26,7 +26,6 @@
 #include <linux/rtc.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
-#include <linux/rtc.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/regmap.h>
@@ -275,10 +274,7 @@ static int isl12057_probe(struct i2c_client *client,
 	dev_set_drvdata(dev, data);
 
 	rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(rtc);
 }
 
 #ifdef CONFIG_OF
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
index 1b126d2513de..08f5160fb6d4 100644
--- a/drivers/rtc/rtc-jz4740.c
+++ b/drivers/rtc/rtc-jz4740.c
@@ -38,7 +38,6 @@
 #define JZ_RTC_CTRL_ENABLE	BIT(0)
 
 struct jz4740_rtc {
-	struct resource *mem;
 	void __iomem *base;
 
 	struct rtc_device *rtc;
@@ -216,6 +215,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
 	int ret;
 	struct jz4740_rtc *rtc;
 	uint32_t scratchpad;
+	struct resource *mem;
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
 	if (!rtc)
@@ -227,25 +227,10 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!rtc->mem) {
-		dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
-		return -ENOENT;
-	}
-
-	rtc->mem = devm_request_mem_region(&pdev->dev, rtc->mem->start,
-					resource_size(rtc->mem), pdev->name);
-	if (!rtc->mem) {
-		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-		return -EBUSY;
-	}
-
-	rtc->base = devm_ioremap_nocache(&pdev->dev, rtc->mem->start,
-					resource_size(rtc->mem));
-	if (!rtc->base) {
-		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-		return -EBUSY;
-	}
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rtc->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(rtc->base))
+		return PTR_ERR(rtc->base);
 
 	spin_lock_init(&rtc->lock);
 
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index bfdbcb82d069..f130c08c98f8 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -211,10 +211,9 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
 	}
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
-	if (unlikely(!rtc)) {
-		dev_err(&pdev->dev, "Can't allocate memory\n");
+	if (unlikely(!rtc))
 		return -ENOMEM;
-	}
+
 	rtc->irq = rtcirq;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 77ea9896b5ba..9b1a77eb91a9 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -23,6 +23,8 @@
 #define MC13XXX_RTCDAY	22
 #define MC13XXX_RTCDAYA	23
 
+#define SEC_PER_DAY	(24 * 60 * 60)
+
 struct mc13xxx_rtc {
 	struct rtc_device *rtc;
 	struct mc13xxx *mc13xxx;
@@ -42,15 +44,15 @@ static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev,
 	return func(priv->mc13xxx, irq);
 }
 
-static int mc13xxx_rtc_irq_enable(struct device *dev,
-		unsigned int enabled, int irq)
+static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
+					unsigned int enabled)
 {
 	struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 	int ret;
 
 	mc13xxx_lock(priv->mc13xxx);
 
-	ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq);
+	ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, MC13XXX_IRQ_TODA);
 
 	mc13xxx_unlock(priv->mc13xxx);
 
@@ -61,44 +63,27 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 	unsigned int seconds, days1, days2;
-	unsigned long s1970;
-	int ret;
-
-	mc13xxx_lock(priv->mc13xxx);
-
-	if (!priv->valid) {
-		ret = -ENODATA;
-		goto out;
-	}
-
-	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
-	if (unlikely(ret))
-		goto out;
-
-	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
-	if (unlikely(ret))
-		goto out;
 
-	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
-out:
-	mc13xxx_unlock(priv->mc13xxx);
+	if (!priv->valid)
+		return -ENODATA;
 
-	if (ret)
-		return ret;
+	do {
+		int ret;
 
-	if (days2 == days1 + 1) {
-		if (seconds >= 86400 / 2)
-			days2 = days1;
-		else
-			days1 = days2;
-	}
+		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
+		if (ret)
+			return ret;
 
-	if (days1 != days2)
-		return -EIO;
+		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
+		if (ret)
+			return ret;
 
-	s1970 = days1 * 86400 + seconds;
+		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
+		if (ret)
+			return ret;
+	} while (days1 != days2);
 
-	rtc_time_to_tm(s1970, tm);
+	rtc_time_to_tm(days1 * SEC_PER_DAY + seconds, tm);
 
 	return rtc_valid_tm(tm);
 }
@@ -110,8 +95,8 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
 	unsigned int alarmseconds;
 	int ret;
 
-	seconds = secs % 86400;
-	days = secs / 86400;
+	seconds = secs % SEC_PER_DAY;
+	days = secs / SEC_PER_DAY;
 
 	mc13xxx_lock(priv->mc13xxx);
 
@@ -123,7 +108,7 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
 	if (unlikely(ret))
 		goto out;
 
-	if (alarmseconds < 86400) {
+	if (alarmseconds < SEC_PER_DAY) {
 		ret = mc13xxx_reg_write(priv->mc13xxx,
 				MC13XXX_RTCTODA, 0x1ffff);
 		if (unlikely(ret))
@@ -147,18 +132,21 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
 		goto out;
 
 	/* restore alarm */
-	if (alarmseconds < 86400) {
+	if (alarmseconds < SEC_PER_DAY) {
 		ret = mc13xxx_reg_write(priv->mc13xxx,
 				MC13XXX_RTCTODA, alarmseconds);
 		if (unlikely(ret))
 			goto out;
 	}
 
-	ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
-	if (unlikely(ret))
-		goto out;
+	if (!priv->valid) {
+		ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
+		if (unlikely(ret))
+			goto out;
+
+		ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
+	}
 
-	ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
 out:
 	priv->valid = !ret;
 
@@ -180,7 +168,7 @@ static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);
 	if (unlikely(ret))
 		goto out;
-	if (seconds >= 86400) {
+	if (seconds >= SEC_PER_DAY) {
 		ret = -ENODATA;
 		goto out;
 	}
@@ -201,7 +189,7 @@ out:
 	alarm->enabled = enabled;
 	alarm->pending = pending;
 
-	s1970 = days * 86400 + seconds;
+	s1970 = days * SEC_PER_DAY + seconds;
 
 	rtc_time_to_tm(s1970, &alarm->time);
 	dev_dbg(dev, "%s: %lu\n", __func__, s1970);
@@ -239,8 +227,8 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 	if (unlikely(ret))
 		goto out;
 
-	seconds = s1970 % 86400;
-	days = s1970 / 86400;
+	seconds = s1970 % SEC_PER_DAY;
+	days = s1970 / SEC_PER_DAY;
 
 	ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);
 	if (unlikely(ret))
@@ -282,12 +270,6 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
-		unsigned int enabled)
-{
-	return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA);
-}
-
 static const struct rtc_class_ops mc13xxx_rtc_ops = {
 	.read_time = mc13xxx_rtc_read_time,
 	.set_mmss = mc13xxx_rtc_set_mmss,
@@ -301,7 +283,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
 	struct mc13xxx_rtc *priv = dev;
 	struct mc13xxx *mc13xxx = priv->mc13xxx;
 
-	dev_dbg(&priv->rtc->dev, "RTCRST\n");
+	dev_warn(&priv->rtc->dev, "Contents of the RTC are no longer valid\n");
 	priv->valid = 0;
 
 	mc13xxx_irq_mask(mc13xxx, irq);
@@ -314,7 +296,6 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
 	int ret;
 	struct mc13xxx_rtc *priv;
 	struct mc13xxx *mc13xxx;
-	int rtcrst_pending;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -322,60 +303,46 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
 
 	mc13xxx = dev_get_drvdata(pdev->dev.parent);
 	priv->mc13xxx = mc13xxx;
+	priv->valid = 1;
 
 	platform_set_drvdata(pdev, priv);
 
+	priv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+					     &mc13xxx_rtc_ops, THIS_MODULE);
+	if (IS_ERR(priv->rtc))
+		return PTR_ERR(priv->rtc);
+
 	mc13xxx_lock(mc13xxx);
 
+	mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST);
+
 	ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST,
 			mc13xxx_rtc_reset_handler, DRIVER_NAME, priv);
 	if (ret)
 		goto err_reset_irq_request;
 
-	ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST,
-			NULL, &rtcrst_pending);
-	if (ret)
-		goto err_reset_irq_status;
-
-	priv->valid = !rtcrst_pending;
-
-	ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ,
+	ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ,
 			mc13xxx_rtc_update_handler, DRIVER_NAME, priv);
 	if (ret)
-		goto err_update_irq_request;
+		goto err_reset_irq_status;
 
 	ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA,
 			mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv);
-	if (ret)
-		goto err_alarm_irq_request;
-
-	mc13xxx_unlock(mc13xxx);
-
-	priv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
-					&mc13xxx_rtc_ops, THIS_MODULE);
-	if (IS_ERR(priv->rtc)) {
-		ret = PTR_ERR(priv->rtc);
-
-		mc13xxx_lock(mc13xxx);
-
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
-err_alarm_irq_request:
+	if (!ret)
+		goto err_reset_irq_request;
 
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
-err_update_irq_request:
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
 
 err_reset_irq_status:
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 
-		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 err_reset_irq_request:
-
-		mc13xxx_unlock(mc13xxx);
-	}
+	mc13xxx_unlock(mc13xxx);
 
 	return ret;
 }
 
-static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
+static int mc13xxx_rtc_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
 
@@ -404,7 +371,7 @@ MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);
 
 static struct platform_driver mc13xxx_rtc_driver = {
 	.id_table = mc13xxx_rtc_idtable,
-	.remove = __exit_p(mc13xxx_rtc_remove),
+	.remove = mc13xxx_rtc_remove,
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/rtc/rtc-moxart.c b/drivers/rtc/rtc-moxart.c
index c29dee0946e6..c31846238871 100644
--- a/drivers/rtc/rtc-moxart.c
+++ b/drivers/rtc/rtc-moxart.c
@@ -247,10 +247,8 @@ static int moxart_rtc_probe(struct platform_device *pdev)
 	int ret = 0;
 
 	moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL);
-	if (!moxart_rtc) {
-		dev_err(&pdev->dev, "devm_kzalloc failed\n");
+	if (!moxart_rtc)
 		return -ENOMEM;
-	}
 
 	moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node,
 						  "gpio-rtc-data", 0);
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index d536c5962c99..d15a999363fc 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -222,6 +222,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct rtc_plat_data *pdata;
 	u32 rtc_time;
+	u32 rtc_date;
 	int ret = 0;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -257,6 +258,17 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
+	/*
+	 * A date after January 19th, 2038 does not fit on 32 bits and
+	 * will confuse the kernel and userspace. Reset to a sane date
+	 * (January 1st, 2013) if we're after 2038.
+	 */
+	rtc_date = readl(pdata->ioaddr + RTC_DATE_REG_OFFS);
+	if (bcd2bin((rtc_date >> RTC_YEAR_OFFS) & 0xff) >= 38) {
+		dev_info(&pdev->dev, "invalid RTC date, resetting to January 1st, 2013\n");
+		writel(0x130101, pdata->ioaddr + RTC_DATE_REG_OFFS);
+	}
+
 	pdata->irq = platform_get_irq(pdev, 0);
 
 	platform_set_drvdata(pdev, pdata);
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
index 248653c74b80..a53da0958e95 100644
--- a/drivers/rtc/rtc-nuc900.c
+++ b/drivers/rtc/rtc-nuc900.c
@@ -229,10 +229,9 @@ static int __init nuc900_rtc_probe(struct platform_device *pdev)
 
 	nuc900_rtc = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_rtc),
 				GFP_KERNEL);
-	if (!nuc900_rtc) {
-		dev_err(&pdev->dev, "kzalloc nuc900_rtc failed\n");
+	if (!nuc900_rtc)
 		return -ENOMEM;
-	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	nuc900_rtc->rtc_reg = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(nuc900_rtc->rtc_reg))
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index fffb7d3449d7..c360d62fb3f6 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -348,9 +348,8 @@ static int palmas_rtc_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops palmas_rtc_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(palmas_rtc_suspend, palmas_rtc_resume)
-};
+static SIMPLE_DEV_PM_OPS(palmas_rtc_pm_ops, palmas_rtc_suspend,
+			 palmas_rtc_resume);
 
 #ifdef CONFIG_OF
 static struct of_device_id of_palmas_rtc_match[] = {
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index 03f8f75d5af2..bd76ffe92784 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -396,10 +396,8 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
 		rtc_write_enable = pdata->rtc_write_enable;
 
 	rtc_dd = devm_kzalloc(&pdev->dev, sizeof(*rtc_dd), GFP_KERNEL);
-	if (rtc_dd == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate memory!\n");
+	if (rtc_dd == NULL)
 		return -ENOMEM;
-	}
 
 	/* Initialise spinlock to protect RTC control register */
 	spin_lock_init(&rtc_dd->ctrl_reg_lock);
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index a355f2b82bb8..cccbf9d89729 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -32,7 +32,6 @@
 
 #include <mach/hardware.h>
 
-#define TIMER_FREQ		CLOCK_TICK_RATE
 #define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM		0
 #define MAXFREQ_PERIODIC	1000
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 8fa23eabcb68..e6298e02b400 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -551,7 +551,6 @@ static int rx8025_probe(struct i2c_client *client,
 
 	rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
 	if (!rx8025) {
-		dev_err(&adapter->dev, "failed to alloc memory\n");
 		err = -ENOMEM;
 		goto errout;
 	}
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 7afd373b9595..c4cde9c08f1f 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -580,10 +580,12 @@ static int s3c_rtc_suspend(struct device *dev)
 
 	clk_enable(rtc_clk);
 	/* save TICNT for anyone using periodic interrupts */
-	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
 		ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
 		ticnt_en_save &= S3C64XX_RTCCON_TICEN;
+		ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT);
+	} else {
+		ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
 	}
 	s3c_rtc_enable(pdev, 0);
 
@@ -605,10 +607,15 @@ static int s3c_rtc_resume(struct device *dev)
 
 	clk_enable(rtc_clk);
 	s3c_rtc_enable(pdev, 1);
-	writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
-	if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
-		tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-		writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
+	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
+		writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
+		if (ticnt_en_save) {
+			tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
+			writew(tmp | ticnt_en_save,
+					s3c_rtc_base + S3C2410_RTCCON);
+		}
+	} else {
+		writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
 	}
 
 	if (device_may_wakeup(dev) && wake_en) {
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c
index 3eb3642ae299..76e38007ba90 100644
--- a/drivers/rtc/rtc-sirfsoc.c
+++ b/drivers/rtc/rtc-sirfsoc.c
@@ -264,12 +264,8 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
 
 	rtcdrv = devm_kzalloc(&pdev->dev,
 		sizeof(struct sirfsoc_rtc_drv), GFP_KERNEL);
-	if (rtcdrv == NULL) {
-		dev_err(&pdev->dev,
-			"%s: can't alloc mem for drv struct\n",
-			pdev->name);
+	if (rtcdrv == NULL)
 		return -ENOMEM;
-	}
 
 	err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base);
 	if (err) {
@@ -335,39 +331,29 @@ static int sirfsoc_rtc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
 static int sirfsoc_rtc_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
+	struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
 	rtcdrv->overflow_rtc =
 		sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
 
 	rtcdrv->saved_counter =
 		sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
 	rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
-	if (device_may_wakeup(&pdev->dev) && !enable_irq_wake(rtcdrv->irq))
+	if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq))
 		rtcdrv->irq_wake = 1;
 
 	return 0;
 }
 
-static int sirfsoc_rtc_freeze(struct device *dev)
-{
-	sirfsoc_rtc_suspend(dev);
-
-	return 0;
-}
-
-static int sirfsoc_rtc_thaw(struct device *dev)
+static int sirfsoc_rtc_resume(struct device *dev)
 {
 	u32 tmp;
-	struct sirfsoc_rtc_drv *rtcdrv;
-	rtcdrv = dev_get_drvdata(dev);
+	struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
 
 	/*
-	 * if resume from snapshot and the rtc power is losed,
+	 * if resume from snapshot and the rtc power is lost,
 	 * restroe the rtc settings
 	 */
 	if (SIRFSOC_RTC_CLK != sirfsoc_rtc_iobrg_readl(
@@ -407,57 +393,23 @@ static int sirfsoc_rtc_thaw(struct device *dev)
 	sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
 			rtcdrv->rtc_base + RTC_SW_VALUE);
 
-	return 0;
-}
-
-static int sirfsoc_rtc_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
-	sirfsoc_rtc_thaw(dev);
-	if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
+	if (device_may_wakeup(dev) && rtcdrv->irq_wake) {
 		disable_irq_wake(rtcdrv->irq);
 		rtcdrv->irq_wake = 0;
 	}
 
 	return 0;
 }
-
-static int sirfsoc_rtc_restore(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
-
-	if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
-		disable_irq_wake(rtcdrv->irq);
-		rtcdrv->irq_wake = 0;
-	}
-	return 0;
-}
-
-#else
-#define sirfsoc_rtc_suspend	NULL
-#define sirfsoc_rtc_resume	NULL
-#define sirfsoc_rtc_freeze	NULL
-#define sirfsoc_rtc_thaw	NULL
-#define sirfsoc_rtc_restore	NULL
 #endif
 
-static const struct dev_pm_ops sirfsoc_rtc_pm_ops = {
-	.suspend = sirfsoc_rtc_suspend,
-	.resume = sirfsoc_rtc_resume,
-	.freeze = sirfsoc_rtc_freeze,
-	.thaw = sirfsoc_rtc_thaw,
-	.restore = sirfsoc_rtc_restore,
-};
+static SIMPLE_DEV_PM_OPS(sirfsoc_rtc_pm_ops,
+		sirfsoc_rtc_suspend, sirfsoc_rtc_resume);
 
 static struct platform_driver sirfsoc_rtc_driver = {
 	.driver = {
 		.name = "sirfsoc-rtc",
 		.owner = THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm = &sirfsoc_rtc_pm_ops,
-#endif
 		.of_match_table = sirfsoc_rtc_of_match,
 	},
 	.probe = sirfsoc_rtc_probe,
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index c492cf0ab8cd..d2cdb9823a15 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -365,10 +365,8 @@ static int spear_rtc_probe(struct platform_device *pdev)
 	}
 
 	config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
-	if (!config) {
-		dev_err(&pdev->dev, "out of memory\n");
+	if (!config)
 		return -ENOMEM;
-	}
 
 	/* alarm irqs */
 	irq = platform_get_irq(pdev, 0);
diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c
index 68a35284e5ad..b6f21f73d508 100644
--- a/drivers/rtc/rtc-sunxi.c
+++ b/drivers/rtc/rtc-sunxi.c
@@ -428,7 +428,7 @@ static const struct rtc_class_ops sunxi_rtc_ops = {
 };
 
 static const struct of_device_id sunxi_rtc_dt_ids[] = {
-	{ .compatible = "allwinner,sun4i-rtc", .data = &data_year_param[0] },
+	{ .compatible = "allwinner,sun4i-a10-rtc", .data = &data_year_param[0] },
 	{ .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] },
 	{ /* sentinel */ },
 };
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index df2ef3eba7cd..051da968da6d 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -79,7 +79,6 @@
 
 struct vt8500_rtc {
 	void __iomem		*regbase;
-	struct resource		*res;
 	int			irq_alarm;
 	struct rtc_device	*rtc;
 	spinlock_t		lock;		/* Protects this structure */
@@ -209,6 +208,7 @@ static const struct rtc_class_ops vt8500_rtc_ops = {
 static int vt8500_rtc_probe(struct platform_device *pdev)
 {
 	struct vt8500_rtc *vt8500_rtc;
+	struct resource	*res;
 	int ret;
 
 	vt8500_rtc = devm_kzalloc(&pdev->dev,
@@ -219,34 +219,16 @@ static int vt8500_rtc_probe(struct platform_device *pdev)
 	spin_lock_init(&vt8500_rtc->lock);
 	platform_set_drvdata(pdev, vt8500_rtc);
 
-	vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!vt8500_rtc->res) {
-		dev_err(&pdev->dev, "No I/O memory resource defined\n");
-		return -ENXIO;
-	}
-
 	vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);
 	if (vt8500_rtc->irq_alarm < 0) {
 		dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
 		return vt8500_rtc->irq_alarm;
 	}
 
-	vt8500_rtc->res = devm_request_mem_region(&pdev->dev,
-					vt8500_rtc->res->start,
-					resource_size(vt8500_rtc->res),
-					"vt8500-rtc");
-	if (vt8500_rtc->res == NULL) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		return -EBUSY;
-	}
-
-	vt8500_rtc->regbase = devm_ioremap(&pdev->dev, vt8500_rtc->res->start,
-				      resource_size(vt8500_rtc->res));
-	if (!vt8500_rtc->regbase) {
-		dev_err(&pdev->dev, "Unable to map RTC I/O memory\n");
-		ret = -EBUSY;
-		goto err_return;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	vt8500_rtc->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(vt8500_rtc->regbase))
+		return PTR_ERR(vt8500_rtc->regbase);
 
 	/* Enable RTC and set it to 24-hour mode */
 	writel(VT8500_RTC_CR_ENABLE,
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index ebf41e228e55..ee0e85abe1fd 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -304,12 +304,6 @@ dcssblk_load_segment(char *name, struct segment_info **seg_info)
 	return rc;
 }
 
-static void dcssblk_unregister_callback(struct device *dev)
-{
-	device_unregister(dev);
-	put_device(dev);
-}
-
 /*
  * device attribute for switching shared/nonshared (exclusive)
  * operation (show + store)
@@ -397,7 +391,13 @@ removeseg:
 	blk_cleanup_queue(dev_info->dcssblk_queue);
 	dev_info->gd->queue = NULL;
 	put_disk(dev_info->gd);
-	rc = device_schedule_callback(dev, dcssblk_unregister_callback);
+	up_write(&dcssblk_devices_sem);
+
+	if (device_remove_file_self(dev, attr)) {
+		device_unregister(dev);
+		put_device(dev);
+	}
+	return rc;
 out:
 	up_write(&dcssblk_devices_sem);
 	return rc;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index eb5d22795c47..5af7f0bd6125 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -922,7 +922,7 @@ static int __init con3215_init(void)
 		raw3215_freelist = req;
 	}
 
-	cdev = ccw_device_probe_console();
+	cdev = ccw_device_create_console(&raw3215_ccw_driver);
 	if (IS_ERR(cdev))
 		return -ENODEV;
 
@@ -932,6 +932,12 @@ static int __init con3215_init(void)
 	cdev->handler = raw3215_irq;
 
 	raw->flags |= RAW3215_FIXED;
+	if (ccw_device_enable_console(cdev)) {
+		ccw_device_destroy_console(cdev);
+		raw3215_free_info(raw);
+		raw3215[0] = NULL;
+		return -ENODEV;
+	}
 
 	/* Request the console irq */
 	if (raw3215_startup(raw) != 0) {
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 699fd3e363df..bb6b0df50b33 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -576,7 +576,6 @@ static struct console con3270 = {
 static int __init
 con3270_init(void)
 {
-	struct ccw_device *cdev;
 	struct raw3270 *rp;
 	void *cbuf;
 	int i;
@@ -591,10 +590,7 @@ con3270_init(void)
 		cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
 	}
 
-	cdev = ccw_device_probe_console();
-	if (IS_ERR(cdev))
-		return -ENODEV;
-	rp = raw3270_setup_console(cdev);
+	rp = raw3270_setup_console();
 	if (IS_ERR(rp))
 		return PTR_ERR(rp);
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 2cdec21e8924..041c65bc7bb1 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -776,22 +776,37 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
 }
 
 #ifdef CONFIG_TN3270_CONSOLE
+/* Tentative definition - see below for actual definition. */
+static struct ccw_driver raw3270_ccw_driver;
+
 /*
  * Setup 3270 device configured as console.
  */
-struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
+struct raw3270 __init *raw3270_setup_console(void)
 {
+	struct ccw_device *cdev;
 	unsigned long flags;
 	struct raw3270 *rp;
 	char *ascebc;
 	int rc;
 
+	cdev = ccw_device_create_console(&raw3270_ccw_driver);
+	if (IS_ERR(cdev))
+		return ERR_CAST(cdev);
+
 	rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
 	ascebc = kzalloc(256, GFP_KERNEL);
 	rc = raw3270_setup_device(cdev, rp, ascebc);
 	if (rc)
 		return ERR_PTR(rc);
 	set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
+
+	rc = ccw_device_enable_console(cdev);
+	if (rc) {
+		ccw_device_destroy_console(cdev);
+		return ERR_PTR(rc);
+	}
+
 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
 	do {
 		__raw3270_reset_device(rp);
diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h
index 7b73ff8c1bd7..359276a88396 100644
--- a/drivers/s390/char/raw3270.h
+++ b/drivers/s390/char/raw3270.h
@@ -190,7 +190,7 @@ raw3270_put_view(struct raw3270_view *view)
 		wake_up(&raw3270_wait_queue);
 }
 
-struct raw3270 *raw3270_setup_console(struct ccw_device *cdev);
+struct raw3270 *raw3270_setup_console(void);
 void raw3270_wait_cons_dev(struct raw3270 *);
 
 /* Notifier for device addition/removal */
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index 82f2c389b4d1..2c6aac66e2b0 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -184,9 +184,9 @@ static long __init sclp_hsa_size_init(struct sdias_sccb *sccb)
 	sccb_init_eq_size(sccb);
 	if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
 		return -EIO;
-	if (sccb->evbuf.blk_cnt != 0)
-		return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
-	return 0;
+	if (sccb->evbuf.blk_cnt == 0)
+		return 0;
+	return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
 }
 
 static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
@@ -195,6 +195,8 @@ static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
 	sccb->length = PAGE_SIZE;
 	if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
 		return -EIO;
+	if (((struct sdias_sccb *) sccb)->evbuf.blk_cnt == 0)
+		return 0;
 	return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
 }
 
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index f055df0b167f..445564c790f6 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv)
 EXPORT_SYMBOL(airq_iv_release);
 
 /**
- * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector
+ * airq_iv_alloc - allocate irq bits from an interrupt vector
  * @iv: pointer to an interrupt vector structure
+ * @num: number of consecutive irq bits to allocate
  *
- * Returns the bit number of the allocated irq, or -1UL if no bit
- * is available or the AIRQ_IV_ALLOC flag has not been specified
+ * Returns the bit number of the first irq in the allocated block of irqs,
+ * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been
+ * specified
  */
-unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
+unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
 {
-	unsigned long bit;
+	unsigned long bit, i;
 
-	if (!iv->avail)
+	if (!iv->avail || num == 0)
 		return -1UL;
 	spin_lock(&iv->lock);
 	bit = find_first_bit_inv(iv->avail, iv->bits);
-	if (bit < iv->bits) {
-		clear_bit_inv(bit, iv->avail);
-		if (bit >= iv->end)
-			iv->end = bit + 1;
-	} else
+	while (bit + num <= iv->bits) {
+		for (i = 1; i < num; i++)
+			if (!test_bit_inv(bit + i, iv->avail))
+				break;
+		if (i >= num) {
+			/* Found a suitable block of irqs */
+			for (i = 0; i < num; i++)
+				clear_bit_inv(bit + i, iv->avail);
+			if (bit + num >= iv->end)
+				iv->end = bit + num + 1;
+			break;
+		}
+		bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1);
+	}
+	if (bit + num > iv->bits)
 		bit = -1UL;
 	spin_unlock(&iv->lock);
 	return bit;
 
 }
-EXPORT_SYMBOL(airq_iv_alloc_bit);
+EXPORT_SYMBOL(airq_iv_alloc);
 
 /**
- * airq_iv_free_bit - free an irq bit of an interrupt vector
+ * airq_iv_free - free irq bits of an interrupt vector
  * @iv: pointer to interrupt vector structure
- * @bit: number of the irq bit to free
+ * @bit: number of the first irq bit to free
+ * @num: number of consecutive irq bits to free
  */
-void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
+void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)
 {
-	if (!iv->avail)
+	unsigned long i;
+
+	if (!iv->avail || num == 0)
 		return;
 	spin_lock(&iv->lock);
-	/* Clear (possibly left over) interrupt bit */
-	clear_bit_inv(bit, iv->vector);
-	/* Make the bit position available again */
-	set_bit_inv(bit, iv->avail);
-	if (bit == iv->end - 1) {
+	for (i = 0; i < num; i++) {
+		/* Clear (possibly left over) interrupt bit */
+		clear_bit_inv(bit + i, iv->vector);
+		/* Make the bit positions available again */
+		set_bit_inv(bit + i, iv->avail);
+	}
+	if (bit + num >= iv->end) {
 		/* Find new end of bit-field */
-		while (--iv->end > 0)
-			if (!test_bit_inv(iv->end - 1, iv->avail))
-				break;
+		while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail))
+			iv->end--;
 	}
 	spin_unlock(&iv->lock);
 }
-EXPORT_SYMBOL(airq_iv_free_bit);
+EXPORT_SYMBOL(airq_iv_free);
 
 /**
  * airq_iv_scan - scan interrupt vector for non-zero bits
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index fd3367a1dc7a..dfd7bc681c25 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -168,14 +168,12 @@ static ssize_t ccwgroup_online_show(struct device *dev,
  * Provide an 'ungroup' attribute so the user can remove group devices no
  * longer needed or accidentially created. Saves memory :)
  */
-static void ccwgroup_ungroup_callback(struct device *dev)
+static void ccwgroup_ungroup(struct ccwgroup_device *gdev)
 {
-	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
-
 	mutex_lock(&gdev->reg_mutex);
 	if (device_is_registered(&gdev->dev)) {
 		__ccwgroup_remove_symlinks(gdev);
-		device_unregister(dev);
+		device_unregister(&gdev->dev);
 		__ccwgroup_remove_cdev_refs(gdev);
 	}
 	mutex_unlock(&gdev->reg_mutex);
@@ -195,10 +193,9 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev,
 		rc = -EINVAL;
 		goto out;
 	}
-	/* Note that we cannot unregister the device from one of its
-	 * attribute methods, so we have to use this roundabout approach.
-	 */
-	rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
+
+	if (device_remove_file_self(dev, attr))
+		ccwgroup_ungroup(gdev);
 out:
 	if (rc) {
 		if (rc != -EAGAIN)
@@ -224,6 +221,14 @@ static const struct attribute_group *ccwgroup_attr_groups[] = {
 	NULL,
 };
 
+static void ccwgroup_ungroup_workfn(struct work_struct *work)
+{
+	struct ccwgroup_device *gdev =
+		container_of(work, struct ccwgroup_device, ungroup_work);
+
+	ccwgroup_ungroup(gdev);
+}
+
 static void ccwgroup_release(struct device *dev)
 {
 	kfree(to_ccwgroupdev(dev));
@@ -323,6 +328,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
 	atomic_set(&gdev->onoff, 0);
 	mutex_init(&gdev->reg_mutex);
 	mutex_lock(&gdev->reg_mutex);
+	INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn);
 	gdev->count = num_devices;
 	gdev->dev.bus = &ccwgroup_bus_type;
 	gdev->dev.parent = parent;
@@ -404,10 +410,10 @@ EXPORT_SYMBOL(ccwgroup_create_dev);
 static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
 			     void *data)
 {
-	struct device *dev = data;
+	struct ccwgroup_device *gdev = to_ccwgroupdev(data);
 
 	if (action == BUS_NOTIFY_UNBIND_DRIVER)
-		device_schedule_callback(dev, ccwgroup_ungroup_callback);
+		schedule_work(&gdev->ungroup_work);
 
 	return NOTIFY_OK;
 }
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 7b29d0be0ca3..1d3661af7bd8 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -173,8 +173,7 @@ static struct css_driver chsc_subchannel_driver = {
 
 static int __init chsc_init_dbfs(void)
 {
-	chsc_debug_msg_id = debug_register("chsc_msg", 16, 1,
-					   16 * sizeof(long));
+	chsc_debug_msg_id = debug_register("chsc_msg", 8, 1, 4 * sizeof(long));
 	if (!chsc_debug_msg_id)
 		goto out;
 	debug_register_view(chsc_debug_msg_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 8ee88c4ebd83..97c48b38d67d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -54,7 +54,7 @@ debug_info_t *cio_debug_crw_id;
  */
 static int __init cio_debug_init(void)
 {
-	cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long));
+	cio_debug_msg_id = debug_register("cio_msg", 16, 1, 11 * sizeof(long));
 	if (!cio_debug_msg_id)
 		goto out_unregister;
 	debug_register_view(cio_debug_msg_id, &debug_sprintf_view);
@@ -64,7 +64,7 @@ static int __init cio_debug_init(void)
 		goto out_unregister;
 	debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view);
 	debug_set_level(cio_debug_trace_id, 2);
-	cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long));
+	cio_debug_crw_id = debug_register("cio_crw", 8, 1, 8 * sizeof(long));
 	if (!cio_debug_crw_id)
 		goto out_unregister;
 	debug_register_view(cio_debug_crw_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e9d783563cbb..d8d9b5b5cc56 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1571,12 +1571,27 @@ out:
 	return rc;
 }
 
+static void ccw_device_set_int_class(struct ccw_device *cdev)
+{
+	struct ccw_driver *cdrv = cdev->drv;
+
+	/* Note: we interpret class 0 in this context as an uninitialized
+	 * field since it translates to a non-I/O interrupt class. */
+	if (cdrv->int_class != 0)
+		cdev->private->int_class = cdrv->int_class;
+	else
+		cdev->private->int_class = IRQIO_CIO;
+}
+
 #ifdef CONFIG_CCW_CONSOLE
-static int ccw_device_console_enable(struct ccw_device *cdev,
-				     struct subchannel *sch)
+int __init ccw_device_enable_console(struct ccw_device *cdev)
 {
+	struct subchannel *sch = to_subchannel(cdev->dev.parent);
 	int rc;
 
+	if (!cdev->drv || !cdev->handler)
+		return -EINVAL;
+
 	io_subchannel_init_fields(sch);
 	rc = cio_commit_config(sch);
 	if (rc)
@@ -1609,12 +1624,11 @@ out_unlock:
 	return rc;
 }
 
-struct ccw_device *ccw_device_probe_console(void)
+struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv)
 {
 	struct io_subchannel_private *io_priv;
 	struct ccw_device *cdev;
 	struct subchannel *sch;
-	int ret;
 
 	sch = cio_probe_console();
 	if (IS_ERR(sch))
@@ -1631,18 +1645,23 @@ struct ccw_device *ccw_device_probe_console(void)
 		kfree(io_priv);
 		return cdev;
 	}
+	cdev->drv = drv;
 	set_io_private(sch, io_priv);
-	ret = ccw_device_console_enable(cdev, sch);
-	if (ret) {
-		set_io_private(sch, NULL);
-		put_device(&sch->dev);
-		put_device(&cdev->dev);
-		kfree(io_priv);
-		return ERR_PTR(ret);
-	}
+	ccw_device_set_int_class(cdev);
 	return cdev;
 }
 
+void __init ccw_device_destroy_console(struct ccw_device *cdev)
+{
+	struct subchannel *sch = to_subchannel(cdev->dev.parent);
+	struct io_subchannel_private *io_priv = to_io_private(sch);
+
+	set_io_private(sch, NULL);
+	put_device(&sch->dev);
+	put_device(&cdev->dev);
+	kfree(io_priv);
+}
+
 /**
  * ccw_device_wait_idle() - busy wait for device to become idle
  * @cdev: ccw device
@@ -1726,15 +1745,8 @@ ccw_device_probe (struct device *dev)
 	int ret;
 
 	cdev->drv = cdrv; /* to let the driver call _set_online */
-	/* Note: we interpret class 0 in this context as an uninitialized
-	 * field since it translates to a non-I/O interrupt class. */
-	if (cdrv->int_class != 0)
-		cdev->private->int_class = cdrv->int_class;
-	else
-		cdev->private->int_class = IRQIO_CIO;
-
+	ccw_device_set_int_class(cdev);
 	ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
-
 	if (ret) {
 		cdev->drv = NULL;
 		cdev->private->int_class = IRQIO_CIO;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index c3a83df07894..a0aff2eb247c 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -33,8 +33,8 @@ struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
 	/*                   N  P  A    M  L  V                      H  */
 	[QETH_DBF_SETUP] = {"qeth_setup",
 				8, 1,   8, 5, &debug_hex_ascii_view, NULL},
-	[QETH_DBF_MSG]   = {"qeth_msg",
-				8, 1, 128, 3, &debug_sprintf_view,   NULL},
+	[QETH_DBF_MSG]	 = {"qeth_msg", 8, 1, 11 * sizeof(long), 3,
+			    &debug_sprintf_view, NULL},
 	[QETH_DBF_CTRL]  = {"qeth_control",
 		8, 1, QETH_DBF_CTRL_LEN, 5, &debug_hex_ascii_view, NULL},
 };
@@ -1660,7 +1660,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
 				QDIO_FLAG_CLEANUP_USING_CLEAR);
 		if (rc)
 			QETH_CARD_TEXT_(card, 3, "1err%d", rc);
-		qdio_free(CARD_DDEV(card));
 		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
 		break;
 	case QETH_QDIO_CLEANING:
@@ -2605,6 +2604,7 @@ static int qeth_mpc_initialize(struct qeth_card *card)
 	return 0;
 out_qdio:
 	qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
+	qdio_free(CARD_DDEV(card));
 	return rc;
 }
 
@@ -4906,9 +4906,11 @@ retry:
 	if (retries < 3)
 		QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n",
 			dev_name(&card->gdev->dev));
+	rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
 	ccw_device_set_offline(CARD_RDEV(card));
+	qdio_free(CARD_DDEV(card));
 	rc = ccw_device_set_online(CARD_RDEV(card));
 	if (rc)
 		goto retriable;
@@ -4918,7 +4920,6 @@ retry:
 	rc = ccw_device_set_online(CARD_DDEV(card));
 	if (rc)
 		goto retriable;
-	rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
 retriable:
 	if (rc == -ERESTARTSYS) {
 		QETH_DBF_TEXT(SETUP, 2, "break1");
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 0710550093ce..908d82529ee9 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1091,6 +1091,7 @@ out_remove:
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
 	ccw_device_set_offline(CARD_RDEV(card));
+	qdio_free(CARD_DDEV(card));
 	if (recover_flag == CARD_STATE_RECOVER)
 		card->state = CARD_STATE_RECOVER;
 	else
@@ -1132,6 +1133,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
 		rc = (rc2) ? rc2 : rc3;
 	if (rc)
 		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+	qdio_free(CARD_DDEV(card));
 	if (recover_flag == CARD_STATE_UP)
 		card->state = CARD_STATE_RECOVER;
 	/* let user_space know that device is offline */
@@ -1194,6 +1196,7 @@ static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
 		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
 	qeth_qdio_clear_card(card, 0);
 	qeth_clear_qdio_buffers(card);
+	qdio_free(CARD_DDEV(card));
 }
 
 static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 0f430424c3b8..3524d34ff694 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3447,6 +3447,7 @@ out_remove:
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
 	ccw_device_set_offline(CARD_RDEV(card));
+	qdio_free(CARD_DDEV(card));
 	if (recover_flag == CARD_STATE_RECOVER)
 		card->state = CARD_STATE_RECOVER;
 	else
@@ -3493,6 +3494,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
 		rc = (rc2) ? rc2 : rc3;
 	if (rc)
 		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+	qdio_free(CARD_DDEV(card));
 	if (recover_flag == CARD_STATE_UP)
 		card->state = CARD_STATE_RECOVER;
 	/* let user_space know that device is offline */
@@ -3545,6 +3547,7 @@ static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
 		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
 	qeth_qdio_clear_card(card, 0);
 	qeth_clear_qdio_buffers(card);
+	qdio_free(CARD_DDEV(card));
 }
 
 static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index dfffd0f37916..a70692779a16 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -486,6 +486,8 @@ mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc)
 
 	pthru32->dataxferaddr	= kioc->buf_paddr;
 	if (kioc->data_dir & UIOC_WR) {
+		if (pthru32->dataxferlen > kioc->xferlen)
+			return -EINVAL;
 		if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
 						pthru32->dataxferlen)) {
 			return (-EFAULT);
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 97dabd39b092..158020522dfb 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -379,14 +379,7 @@
 #define  DEBUG_PRINT_NVRAM	0
 #define  DEBUG_QLA1280		0
 
-/*
- * The SGI VISWS is broken and doesn't support MMIO ;-(
- */
-#ifdef CONFIG_X86_VISWS
-#define	MEMORY_MAPPED_IO	0
-#else
 #define	MEMORY_MAPPED_IO	1
-#endif
 
 #include "qla1280.h"
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 9117d0bf408e..8ead24c3453a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -649,23 +649,12 @@ store_rescan_field (struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
 
-static void sdev_store_delete_callback(struct device *dev)
-{
-	scsi_remove_device(to_scsi_device(dev));
-}
-
 static ssize_t
 sdev_store_delete(struct device *dev, struct device_attribute *attr,
 		  const char *buf, size_t count)
 {
-	int rc;
-
-	/* An attribute cannot be unregistered by one of its own methods,
-	 * so we have to use this roundabout approach.
-	 */
-	rc = device_schedule_callback(dev, sdev_store_delete_callback);
-	if (rc)
-		count = rc;
+	if (device_remove_file_self(dev, attr))
+		scsi_remove_device(to_scsi_device(dev));
 	return count;
 };
 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index fd8ffe6bcfdd..0102a2d70dd8 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1225,7 +1225,7 @@ struct bus_type iscsi_flashnode_bus = {
  * Adds a sysfs entry for the flashnode session attributes
  *
  * Returns:
- *  pointer to allocated flashnode sess on sucess
+ *  pointer to allocated flashnode sess on success
  *  %NULL on failure
  */
 struct iscsi_bus_flash_session *
@@ -1423,7 +1423,7 @@ static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
 }
 
 /**
- * iscsi_destroy_flashnode_sess - destory flashnode session entry
+ * iscsi_destroy_flashnode_sess - destroy flashnode session entry
  * @fnode_sess: pointer to flashnode session entry to be destroyed
  *
  * Deletes the flashnode session entry and all children flashnode connection
@@ -1453,7 +1453,7 @@ static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
 }
 
 /**
- * iscsi_destroy_all_flashnode - destory all flashnode session entries
+ * iscsi_destroy_all_flashnode - destroy all flashnode session entries
  * @shost: pointer to host data
  *
  * Destroys all the flashnode session entries and all corresponding children
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 1ebe67cd1833..7442bc130055 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -36,9 +36,47 @@ static void sh_clk_write(int value, struct clk *clk)
 		iowrite32(value, clk->mapped_reg);
 }
 
+static unsigned int r8(const void __iomem *addr)
+{
+	return ioread8(addr);
+}
+
+static unsigned int r16(const void __iomem *addr)
+{
+	return ioread16(addr);
+}
+
+static unsigned int r32(const void __iomem *addr)
+{
+	return ioread32(addr);
+}
+
 static int sh_clk_mstp_enable(struct clk *clk)
 {
 	sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
+	if (clk->status_reg) {
+		unsigned int (*read)(const void __iomem *addr);
+		int i;
+		void __iomem *mapped_status = (phys_addr_t)clk->status_reg -
+			(phys_addr_t)clk->enable_reg + clk->mapped_reg;
+
+		if (clk->flags & CLK_ENABLE_REG_8BIT)
+			read = r8;
+		else if (clk->flags & CLK_ENABLE_REG_16BIT)
+			read = r16;
+		else
+			read = r32;
+
+		for (i = 1000;
+		     (read(mapped_status) & (1 << clk->enable_bit)) && i;
+		     i--)
+			cpu_relax();
+		if (!i) {
+			pr_err("cpg: failed to enable %p[%d]\n",
+			       clk->enable_reg, clk->enable_bit);
+			return -ETIMEDOUT;
+		}
+	}
 	return 0;
 }
 
diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
index a305731742a9..f7d90617c9d9 100644
--- a/drivers/sh/intc/Kconfig
+++ b/drivers/sh/intc/Kconfig
@@ -6,7 +6,7 @@ comment "Interrupt controller options"
 
 config INTC_USERIMASK
 	bool "Userspace interrupt masking support"
-	depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A)
+	depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) || COMPILE_TEST
 	help
 	  This enables support for hardware-assisted userspace hardirq
 	  masking.
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 581ee2a8856b..17df2069fca2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -212,7 +212,6 @@ config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
 	depends on ARCH_MXC || COMPILE_TEST
 	select SPI_BITBANG
-	default m if IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  This enables using the Freescale i.MX SPI controllers in master
 	  mode.
@@ -270,6 +269,7 @@ config SPI_FSL_SPI
 config SPI_FSL_DSPI
 	tristate "Freescale DSPI controller"
 	select SPI_BITBANG
+	select REGMAP_MMIO
 	depends on SOC_VF610 || COMPILE_TEST
 	help
 	  This enables support for the Freescale DSPI controller in master
@@ -307,7 +307,7 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
 	tristate "McSPI driver for OMAP"
-	depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
+	depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	help
 	  SPI master controller for OMAP24XX and later Multichannel SPI
@@ -381,6 +381,19 @@ config SPI_RSPI
 	help
 	  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_QUP
+	tristate "Qualcomm SPI controller with QUP interface"
+	depends on ARCH_MSM_DT || (ARM && COMPILE_TEST)
+	help
+	  Qualcomm Universal Peripheral (QUP) core is an AHB slave that
+	  provides a common data path (an output FIFO and an input FIFO)
+	  for serial peripheral interface (SPI) mini-core. SPI in master
+	  mode supports up to 50MHz, up to four chip selects, programmable
+	  data path from 4 bits to 32 bits and numerous protocol variants.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called spi_qup.
+
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
 	depends on ARCH_S3C24XX
@@ -416,7 +429,6 @@ config SPI_SH_MSIOF
 	tristate "SuperH MSIOF SPI controller"
 	depends on HAVE_CLK
 	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
-	select SPI_BITBANG
 	help
 	  SPI driver for SuperH and SH Mobile MSIOF blocks.
 
@@ -446,6 +458,19 @@ config SPI_SIRF
 	help
 	  SPI driver for CSR SiRFprimaII SoCs
 
+config SPI_SUN4I
+	tristate "Allwinner A10 SoCs SPI controller"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	help
+	  SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+
+config SPI_SUN6I
+	tristate "Allwinner A31 SPI controller"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	depends on RESET_CONTROLLER
+	help
+	  This enables using the SPI controller on the Allwinner A31 SoCs.
+
 config SPI_MXS
 	tristate "Freescale MXS SPI controller"
 	depends on ARCH_MXS
@@ -546,7 +571,7 @@ config SPI_DW_MID_DMA
 
 config SPI_DW_MMIO
 	tristate "Memory-mapped io interface driver for DW SPI core"
-	depends on SPI_DESIGNWARE && HAVE_CLK
+	depends on SPI_DESIGNWARE
 
 #
 # There are lots of SPI device types, with sensors and memory
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 95af48d2d360..fcf96e85c03e 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -59,6 +59,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA)	+= spi-pxa2xx-pxadma.o
 spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA)	+= spi-pxa2xx-dma.o
 obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx-platform.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
+obj-$(CONFIG_SPI_QUP)			+= spi-qup.o
 obj-$(CONFIG_SPI_RSPI)			+= spi-rspi.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y			:= spi-s3c24xx.o
@@ -70,6 +71,8 @@ obj-$(CONFIG_SPI_SH_HSPI)		+= spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)		+= spi-sirf.o
+obj-$(CONFIG_SPI_SUN4I)			+= spi-sun4i.o
+obj-$(CONFIG_SPI_SUN6I)			+= spi-sun6i.o
 obj-$(CONFIG_SPI_TEGRA114)		+= spi-tegra114.o
 obj-$(CONFIG_SPI_TEGRA20_SFLASH)	+= spi-tegra20-sflash.o
 obj-$(CONFIG_SPI_TEGRA20_SLINK)		+= spi-tegra20-slink.o
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index 5d7deaf62867..1928b835e870 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -13,7 +13,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/module.h>
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 31534b51715a..a1cf9af9c0ad 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index b0842f751016..8bd637d0c826 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -993,13 +992,6 @@ static int atmel_spi_setup(struct spi_device *spi)
 
 	as = spi_master_get_devdata(spi->master);
 
-	if (spi->chip_select > spi->master->num_chipselect) {
-		dev_dbg(&spi->dev,
-				"setup: invalid chipselect %u (%u defined)\n",
-				spi->chip_select, spi->master->num_chipselect);
-		return -EINVAL;
-	}
-
 	/* see notes above re chipselect */
 	if (!atmel_spi_is_v2(as)
 			&& spi->chip_select == 0
@@ -1087,14 +1079,6 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 		}
 	}
 
-	if (xfer->bits_per_word > 8) {
-		if (xfer->len % 2) {
-			dev_dbg(&spi->dev,
-			"buffer len should be 16 bits aligned\n");
-			return -EINVAL;
-		}
-	}
-
 	/*
 	 * DMA map early, for performance (empties dcache ASAP) and
 	 * better fault reporting.
@@ -1221,9 +1205,6 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
 	dev_dbg(&spi->dev, "new message %p submitted for %s\n",
 					msg, dev_name(&spi->dev));
 
-	if (unlikely(list_empty(&msg->transfers)))
-		return -EINVAL;
-
 	atmel_spi_lock(as);
 	cs_activate(as, spi);
 
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index c4141c92bcff..67375a11d4bd 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -55,8 +55,6 @@ struct au1550_spi {
 
 	volatile psc_spi_t __iomem *regs;
 	int irq;
-	unsigned freq_max;
-	unsigned freq_min;
 
 	unsigned len;
 	unsigned tx_count;
@@ -248,11 +246,8 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
 			hz = t->speed_hz;
 	}
 
-	if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
-		dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n",
-			hz);
+	if (!hz)
 		return -EINVAL;
-	}
 
 	au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
@@ -287,23 +282,6 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
 	return 0;
 }
 
-static int au1550_spi_setup(struct spi_device *spi)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-
-	if (spi->max_speed_hz == 0)
-		spi->max_speed_hz = hw->freq_max;
-	if (spi->max_speed_hz > hw->freq_max
-			|| spi->max_speed_hz < hw->freq_min)
-		return -EINVAL;
-	/*
-	 * NOTE: cannot change speed and other hw settings immediately,
-	 *       otherwise sharing of spi bus is not possible,
-	 *       so do not call setupxfer(spi, NULL) here
-	 */
-	return 0;
-}
-
 /*
  * for dma spi transfers, we have to setup rx channel, otherwise there is
  * no reliable way how to recognize that spi transfer is done
@@ -838,7 +816,6 @@ static int au1550_spi_probe(struct platform_device *pdev)
 	hw->bitbang.master = hw->master;
 	hw->bitbang.setup_transfer = au1550_spi_setupxfer;
 	hw->bitbang.chipselect = au1550_spi_chipsel;
-	hw->bitbang.master->setup = au1550_spi_setup;
 	hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
 
 	if (hw->usedma) {
@@ -909,8 +886,9 @@ static int au1550_spi_probe(struct platform_device *pdev)
 	{
 		int min_div = (2 << 0) * (2 * (4 + 1));
 		int max_div = (2 << 3) * (2 * (63 + 1));
-		hw->freq_max = hw->pdata->mainclk_hz / min_div;
-		hw->freq_min = hw->pdata->mainclk_hz / (max_div + 1) + 1;
+		master->max_speed_hz = hw->pdata->mainclk_hz / min_div;
+		master->min_speed_hz =
+				hw->pdata->mainclk_hz / (max_div + 1) + 1;
 	}
 
 	au1550_spi_setup_psc_as_spi(hw);
@@ -999,6 +977,15 @@ static int __init au1550_spi_init(void)
 	 * create memory device with 8 bits dev_devwidth
 	 * needed for proper byte ordering to spi fifo
 	 */
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1550:
+	case ALCHEMY_CPU_AU1200:
+	case ALCHEMY_CPU_AU1300:
+		break;
+	default:
+		return -ENODEV;
+	}
+
 	if (usedma) {
 		ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
 		if (!ddma_memid)
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 8a89dd1f2654..69167456ec1e 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -315,7 +315,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 
 	master->mode_bits = BCM2835_SPI_MODE_BITS;
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
-	master->bus_num = -1;
 	master->num_chipselect = 3;
 	master->transfer_one_message = bcm2835_spi_transfer_one;
 	master->dev.of_node = pdev->dev.of_node;
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index b528f9fc8bc0..3ad3e0c59992 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -180,7 +180,7 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
 	while (pending > 0) {
 		int curr_step = min_t(int, step_size, pending);
 
-		init_completion(&bs->done);
+		reinit_completion(&bs->done);
 		if (tx) {
 			memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
 			tx += curr_step;
@@ -369,6 +369,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
 	bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
 
 	mutex_init(&bs->bus_mutex);
+	init_completion(&bs->done);
 
 	master->bus_num = HSSPI_BUS_NUM;
 	master->num_chipselect = 8;
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 77286aef2adf..b45ec59a483b 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -169,7 +168,7 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
 			       transfer_list);
 	}
 
-	init_completion(&bs->done);
+	reinit_completion(&bs->done);
 
 	/* Fill in the Message control register */
 	msg_ctl = (len << SPI_BYTE_CNT_SHIFT);
@@ -353,6 +352,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 	}
 
 	bs = spi_master_get_devdata(master);
+	init_completion(&bs->done);
 
 	platform_set_drvdata(pdev, master);
 	bs->pdev = pdev;
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index 38941e5920b5..f515c5e9db57 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -8,7 +8,6 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
index 8f8598834b30..4089d0e0d84e 100644
--- a/drivers/spi/spi-bfin-v3.c
+++ b/drivers/spi/spi-bfin-v3.c
@@ -822,7 +822,8 @@ static int bfin_spi_probe(struct platform_device *pdev)
 	master->cleanup = bfin_spi_cleanup;
 	master->setup = bfin_spi_setup;
 	master->transfer_one_message = bfin_spi_transfer_one_message;
-	master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+	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;
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index f0f195af75d4..55e57c3eb9bd 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -350,7 +350,6 @@ static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
 static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
 {
 	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
-	struct spi_transfer *last_transfer;
 	unsigned long flags;
 	struct spi_message *msg;
 
@@ -362,9 +361,6 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
 	queue_work(drv_data->workqueue, &drv_data->pump_messages);
 	spin_unlock_irqrestore(&drv_data->lock, flags);
 
-	last_transfer = list_entry(msg->transfers.prev,
-				   struct spi_transfer, transfer_list);
-
 	msg->state = NULL;
 
 	if (!drv_data->cs_change)
@@ -1030,10 +1026,6 @@ static int bfin_spi_setup(struct spi_device *spi)
 	}
 
 	/* translate common spi framework into our register */
-	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
-		dev_err(&spi->dev, "unsupported spi modes detected\n");
-		goto error;
-	}
 	if (spi->mode & SPI_CPOL)
 		chip->ctl_reg |= BIT_CTL_CPOL;
 	if (spi->mode & SPI_CPHA)
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index bd222f6b677d..3bfdb851960b 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -16,7 +16,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 374ba4a48a9e..3900c314311a 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -11,7 +11,6 @@
 
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/module.h>
@@ -25,51 +24,29 @@
 #define DRIVER_NAME	"spi-clps711x"
 
 struct spi_clps711x_data {
-	struct completion	done;
-
 	struct clk		*spi_clk;
 	u32			max_speed_hz;
 
 	u8			*tx_buf;
 	u8			*rx_buf;
-	int			count;
+	unsigned int		bpw;
 	int			len;
-
-	int			chipselect[0];
 };
 
 static int spi_clps711x_setup(struct spi_device *spi)
 {
-	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
-
 	/* We are expect that SPI-device is not selected */
-	gpio_direction_output(hw->chipselect[spi->chip_select],
-			      !(spi->mode & SPI_CS_HIGH));
+	gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 
 	return 0;
 }
 
-static void spi_clps711x_setup_mode(struct spi_device *spi)
-{
-	/* Setup edge for transfer */
-	if (spi->mode & SPI_CPHA)
-		clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
-	else
-		clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
-}
-
-static int spi_clps711x_setup_xfer(struct spi_device *spi,
-				   struct spi_transfer *xfer)
+static void spi_clps711x_setup_xfer(struct spi_device *spi,
+				    struct spi_transfer *xfer)
 {
 	u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
-	u8 bpw = xfer->bits_per_word;
 	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
 
-	if (bpw != 8) {
-		dev_err(&spi->dev, "Unsupported master bus width %i\n", bpw);
-		return -EINVAL;
-	}
-
 	/* Setup SPI frequency divider */
 	if (!speed || (speed >= hw->max_speed_hz))
 		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
@@ -83,76 +60,60 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi,
 	else
 		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
 			    SYSCON1_ADCKSEL(0), SYSCON1);
-
-	return 0;
 }
 
-static int spi_clps711x_transfer_one_message(struct spi_master *master,
-					     struct spi_message *msg)
+static int spi_clps711x_prepare_message(struct spi_master *master,
+					struct spi_message *msg)
 {
-	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
-	struct spi_transfer *xfer;
-	int status = 0, cs = hw->chipselect[msg->spi->chip_select];
-	u32 data;
-
-	spi_clps711x_setup_mode(msg->spi);
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		if (spi_clps711x_setup_xfer(msg->spi, xfer)) {
-			status = -EINVAL;
-			goto out_xfr;
-		}
-
-		gpio_set_value(cs, !!(msg->spi->mode & SPI_CS_HIGH));
-
-		reinit_completion(&hw->done);
-
-		hw->count = 0;
-		hw->len = xfer->len;
-		hw->tx_buf = (u8 *)xfer->tx_buf;
-		hw->rx_buf = (u8 *)xfer->rx_buf;
-
-		/* Initiate transfer */
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+	struct spi_device *spi = msg->spi;
 
-		wait_for_completion(&hw->done);
+	/* Setup edge for transfer */
+	if (spi->mode & SPI_CPHA)
+		clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
+	else
+		clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
 
-		if (xfer->delay_usecs)
-			udelay(xfer->delay_usecs);
+	return 0;
+}
 
-		if (xfer->cs_change ||
-		    list_is_last(&xfer->transfer_list, &msg->transfers))
-			gpio_set_value(cs, !(msg->spi->mode & SPI_CS_HIGH));
+static int spi_clps711x_transfer_one(struct spi_master *master,
+				     struct spi_device *spi,
+				     struct spi_transfer *xfer)
+{
+	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+	u8 data;
 
-		msg->actual_length += xfer->len;
-	}
+	spi_clps711x_setup_xfer(spi, xfer);
 
-out_xfr:
-	msg->status = status;
-	spi_finalize_current_message(master);
+	hw->len = xfer->len;
+	hw->bpw = xfer->bits_per_word ? : spi->bits_per_word;
+	hw->tx_buf = (u8 *)xfer->tx_buf;
+	hw->rx_buf = (u8 *)xfer->rx_buf;
 
-	return 0;
+	/* Initiate transfer */
+	data = hw->tx_buf ? *hw->tx_buf++ : 0;
+	clps_writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN, SYNCIO);
+	return 1;
 }
 
 static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 {
-	struct spi_clps711x_data *hw = (struct spi_clps711x_data *)dev_id;
-	u32 data;
+	struct spi_master *master = dev_id;
+	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+	u8 data;
 
 	/* Handle RX */
 	data = clps_readb(SYNCIO);
 	if (hw->rx_buf)
-		hw->rx_buf[hw->count] = (u8)data;
-
-	hw->count++;
+		*hw->rx_buf++ = data;
 
 	/* Handle TX */
-	if (hw->count < hw->len) {
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+	if (--hw->len > 0) {
+		data = hw->tx_buf ? *hw->tx_buf++ : 0;
+		clps_writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
+			    SYNCIO);
 	} else
-		complete(&hw->done);
+		spi_finalize_current_transfer(master);
 
 	return IRQ_HANDLED;
 }
@@ -174,31 +135,35 @@ static int spi_clps711x_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	master = spi_alloc_master(&pdev->dev,
-				  sizeof(struct spi_clps711x_data) +
-				  sizeof(int) * pdata->num_chipselect);
-	if (!master) {
-		dev_err(&pdev->dev, "SPI allocating memory error\n");
+	master = spi_alloc_master(&pdev->dev, sizeof(*hw));
+	if (!master)
 		return -ENOMEM;
+
+	master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) *
+					pdata->num_chipselect, GFP_KERNEL);
+	if (!master->cs_gpios) {
+		ret = -ENOMEM;
+		goto err_out;
 	}
 
 	master->bus_num = pdev->id;
 	master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
-	master->bits_per_word_mask = SPI_BPW_MASK(8);
+	master->bits_per_word_mask =  SPI_BPW_RANGE_MASK(1, 8);
 	master->num_chipselect = pdata->num_chipselect;
 	master->setup = spi_clps711x_setup;
-	master->transfer_one_message = spi_clps711x_transfer_one_message;
+	master->prepare_message = spi_clps711x_prepare_message;
+	master->transfer_one = spi_clps711x_transfer_one;
 
 	hw = spi_master_get_devdata(master);
 
 	for (i = 0; i < master->num_chipselect; i++) {
-		hw->chipselect[i] = pdata->chipselect[i];
-		if (!gpio_is_valid(hw->chipselect[i])) {
+		master->cs_gpios[i] = pdata->chipselect[i];
+		if (!gpio_is_valid(master->cs_gpios[i])) {
 			dev_err(&pdev->dev, "Invalid CS GPIO %i\n", i);
 			ret = -EINVAL;
 			goto err_out;
 		}
-		if (devm_gpio_request(&pdev->dev, hw->chipselect[i], NULL)) {
+		if (devm_gpio_request(&pdev->dev, master->cs_gpios[i], NULL)) {
 			dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
 			ret = -EINVAL;
 			goto err_out;
@@ -213,7 +178,6 @@ static int spi_clps711x_probe(struct platform_device *pdev)
 	}
 	hw->max_speed_hz = clk_get_rate(hw->spi_clk);
 
-	init_completion(&hw->done);
 	platform_set_drvdata(pdev, master);
 
 	/* Disable extended mode due hardware problems */
@@ -223,7 +187,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
 	clps_readl(SYNCIO);
 
 	ret = devm_request_irq(&pdev->dev, IRQ_SSEOTI, spi_clps711x_isr, 0,
-			       dev_name(&pdev->dev), hw);
+			       dev_name(&pdev->dev), master);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't request IRQ\n");
 		goto err_out;
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index cabed8f9119e..c29bbb0aeb27 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -77,8 +77,6 @@ struct mcfqspi {
 	struct mcfqspi_cs_control *cs_control;
 
 	wait_queue_head_t waitq;
-
-	struct device *dev;
 };
 
 static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
@@ -300,68 +298,48 @@ static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
 	}
 }
 
-static int mcfqspi_transfer_one_message(struct spi_master *master,
-					 struct spi_message *msg)
+static void mcfqspi_set_cs(struct spi_device *spi, bool enable)
 {
-	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-	struct spi_device *spi = msg->spi;
-	struct spi_transfer *t;
-	int status = 0;
-
-	list_for_each_entry(t, &msg->transfers, transfer_list) {
-		bool cs_high = spi->mode & SPI_CS_HIGH;
-		u16 qmr = MCFQSPI_QMR_MSTR;
-
-		qmr |= t->bits_per_word << 10;
-		if (spi->mode & SPI_CPHA)
-			qmr |= MCFQSPI_QMR_CPHA;
-		if (spi->mode & SPI_CPOL)
-			qmr |= MCFQSPI_QMR_CPOL;
-		if (t->speed_hz)
-			qmr |= mcfqspi_qmr_baud(t->speed_hz);
-		else
-			qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
-		mcfqspi_wr_qmr(mcfqspi, qmr);
+	struct mcfqspi *mcfqspi = spi_master_get_devdata(spi->master);
+	bool cs_high = spi->mode & SPI_CS_HIGH;
 
+	if (enable)
 		mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
+	else
+		mcfqspi_cs_deselect(mcfqspi, spi->chip_select, cs_high);
+}
 
-		mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
-		if (t->bits_per_word == 8)
-			mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf,
-					t->rx_buf);
-		else
-			mcfqspi_transfer_msg16(mcfqspi, t->len / 2, t->tx_buf,
-					t->rx_buf);
-		mcfqspi_wr_qir(mcfqspi, 0);
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-		if (t->cs_change) {
-			if (!list_is_last(&t->transfer_list, &msg->transfers))
-				mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
-						cs_high);
-		} else {
-			if (list_is_last(&t->transfer_list, &msg->transfers))
-				mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
-						cs_high);
-		}
-		msg->actual_length += t->len;
-	}
-	msg->status = status;
-	spi_finalize_current_message(master);
+static int mcfqspi_transfer_one(struct spi_master *master,
+				struct spi_device *spi,
+				struct spi_transfer *t)
+{
+	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
+	u16 qmr = MCFQSPI_QMR_MSTR;
+
+	qmr |= t->bits_per_word << 10;
+	if (spi->mode & SPI_CPHA)
+		qmr |= MCFQSPI_QMR_CPHA;
+	if (spi->mode & SPI_CPOL)
+		qmr |= MCFQSPI_QMR_CPOL;
+	if (t->speed_hz)
+		qmr |= mcfqspi_qmr_baud(t->speed_hz);
+	else
+		qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
+	mcfqspi_wr_qmr(mcfqspi, qmr);
 
-	return status;
+	mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
+	if (t->bits_per_word == 8)
+		mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf, t->rx_buf);
+	else
+		mcfqspi_transfer_msg16(mcfqspi, t->len / 2, t->tx_buf,
+				       t->rx_buf);
+	mcfqspi_wr_qir(mcfqspi, 0);
 
+	return 0;
 }
 
 static int mcfqspi_setup(struct spi_device *spi)
 {
-	if (spi->chip_select >= spi->master->num_chipselect) {
-		dev_dbg(&spi->dev, "%d chip select is out of range\n",
-			spi->chip_select);
-		return -EINVAL;
-	}
-
 	mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
 			    spi->chip_select, spi->mode & SPI_CS_HIGH);
 
@@ -436,12 +414,12 @@ static int mcfqspi_probe(struct platform_device *pdev)
 	}
 
 	init_waitqueue_head(&mcfqspi->waitq);
-	mcfqspi->dev = &pdev->dev;
 
 	master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
 	master->setup = mcfqspi_setup;
-	master->transfer_one_message = mcfqspi_transfer_one_message;
+	master->set_cs = mcfqspi_set_cs;
+	master->transfer_one = mcfqspi_transfer_one;
 	master->auto_runtime_pm = true;
 
 	platform_set_drvdata(pdev, master);
@@ -451,7 +429,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
 		dev_dbg(&pdev->dev, "spi_register_master failed\n");
 		goto fail2;
 	}
-	pm_runtime_enable(mcfqspi->dev);
+	pm_runtime_enable(&pdev->dev);
 
 	dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
 
@@ -473,9 +451,8 @@ static int mcfqspi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	pm_runtime_disable(mcfqspi->dev);
+	pm_runtime_disable(&pdev->dev);
 	/* disable the hardware (set the baud rate to 0) */
 	mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
 
@@ -514,7 +491,8 @@ static int mcfqspi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int mcfqspi_runtime_suspend(struct device *dev)
 {
-	struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
 
 	clk_disable(mcfqspi->clk);
 
@@ -523,7 +501,8 @@ static int mcfqspi_runtime_suspend(struct device *dev)
 
 static int mcfqspi_runtime_resume(struct device *dev)
 {
-	struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
 
 	clk_enable(mcfqspi->clk);
 
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 5e7389faa2a0..50f750989258 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -802,8 +802,7 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
 	pdata = &dspi->pdata;
 
 	pdata->version = SPI_VERSION_1;
-	match = of_match_device(of_match_ptr(davinci_spi_of_match),
-				&pdev->dev);
+	match = of_match_device(davinci_spi_of_match, &pdev->dev);
 	if (!match)
 		return -ENODEV;
 
@@ -824,7 +823,6 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
 	return 0;
 }
 #else
-#define davinci_spi_of_match NULL
 static struct davinci_spi_platform_data
 	*spi_davinci_get_pdata(struct platform_device *pdev,
 		struct davinci_spi *dspi)
@@ -864,10 +862,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	dspi = spi_master_get_devdata(master);
-	if (dspi == NULL) {
-		ret = -ENOENT;
-		goto free_master;
-	}
 
 	if (dev_get_platdata(&pdev->dev)) {
 		pdata = dev_get_platdata(&pdev->dev);
@@ -908,10 +902,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
 		goto free_master;
 
 	dspi->bitbang.master = master;
-	if (dspi->bitbang.master == NULL) {
-		ret = -ENODEV;
-		goto free_master;
-	}
 
 	dspi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dspi->clk)) {
@@ -1040,7 +1030,7 @@ static struct platform_driver davinci_spi_driver = {
 	.driver = {
 		.name = "spi_davinci",
 		.owner = THIS_MODULE,
-		.of_match_table = davinci_spi_of_match,
+		.of_match_table = of_match_ptr(davinci_spi_of_match),
 	},
 	.probe = davinci_spi_probe,
 	.remove = davinci_spi_remove,
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 9af56cdf1540..1492f5ee9aaa 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -66,7 +66,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	dws->bus_num = 0;
+	dws->bus_num = pdev->id;
 	dws->num_cs = 4;
 	dws->max_freq = clk_get_rate(dwsmmio->clk);
 
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index bf98d63d92b3..390da9bf2d84 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -276,8 +276,7 @@ static void giveback(struct dw_spi *dws)
 	queue_work(dws->workqueue, &dws->pump_messages);
 	spin_unlock_irqrestore(&dws->lock, flags);
 
-	last_transfer = list_entry(msg->transfers.prev,
-					struct spi_transfer,
+	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
 					transfer_list);
 
 	if (!last_transfer->cs_change && dws->cs_control)
diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c
index d4d3cc534792..f53bbea385c0 100644
--- a/drivers/spi/spi-efm32.c
+++ b/drivers/spi/spi-efm32.c
@@ -198,7 +198,7 @@ static int efm32_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
 
 	efm32_spi_filltx(ddata);
 
-	init_completion(&ddata->done);
+	reinit_completion(&ddata->done);
 
 	efm32_spi_write32(ddata, REG_IF_TXBL | REG_IF_RXDATAV, REG_IEN);
 
@@ -308,10 +308,6 @@ static int efm32_spi_probe_dt(struct platform_device *pdev,
 	}
 
 	ddata->pdata.location = location;
-
-	/* spi core takes care about the bus number using an alias */
-	master->bus_num = -1;
-
 	return 0;
 }
 
@@ -349,6 +345,7 @@ static int efm32_spi_probe(struct platform_device *pdev)
 	ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
 
 	spin_lock_init(&ddata->lock);
+	init_completion(&ddata->done);
 
 	ddata->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(ddata->clk)) {
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 1bfaed6e4073..2f675d32df0e 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -73,8 +73,6 @@
  * @clk: clock for the controller
  * @regs_base: pointer to ioremap()'d registers
  * @sspdr_phys: physical address of the SSPDR register
- * @min_rate: minimum clock rate (in Hz) supported by the controller
- * @max_rate: maximum clock rate (in Hz) supported by the controller
  * @wait: wait here until given transfer is completed
  * @current_msg: message that is currently processed (or %NULL if none)
  * @tx: current byte in transfer to transmit
@@ -95,8 +93,6 @@ struct ep93xx_spi {
 	struct clk			*clk;
 	void __iomem			*regs_base;
 	unsigned long			sspdr_phys;
-	unsigned long			min_rate;
-	unsigned long			max_rate;
 	struct completion		wait;
 	struct spi_message		*current_msg;
 	size_t				tx;
@@ -199,9 +195,9 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
  * @div_scr: pointer to return the scr divider
  */
 static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
-				    unsigned long rate,
-				    u8 *div_cpsr, u8 *div_scr)
+				    u32 rate, u8 *div_cpsr, u8 *div_scr)
 {
+	struct spi_master *master = platform_get_drvdata(espi->pdev);
 	unsigned long spi_clk_rate = clk_get_rate(espi->clk);
 	int cpsr, scr;
 
@@ -210,7 +206,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
 	 * controller. Note that minimum value is already checked in
 	 * ep93xx_spi_transfer_one_message().
 	 */
-	rate = clamp(rate, espi->min_rate, espi->max_rate);
+	rate = clamp(rate, master->min_speed_hz, master->max_speed_hz);
 
 	/*
 	 * Calculate divisors so that we can get speed according the
@@ -735,13 +731,6 @@ static int ep93xx_spi_transfer_one_message(struct spi_master *master,
 					   struct spi_message *msg)
 {
 	struct ep93xx_spi *espi = spi_master_get_devdata(master);
-	struct spi_transfer *t;
-
-	/* first validate each transfer */
-	list_for_each_entry(t, &msg->transfers, transfer_list) {
-		if (t->speed_hz < espi->min_rate)
-			return -EINVAL;
-	}
 
 	msg->state = NULL;
 	msg->status = 0;
@@ -917,8 +906,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 	 * Calculate maximum and minimum supported clock rates
 	 * for the controller.
 	 */
-	espi->max_rate = clk_get_rate(espi->clk) / 2;
-	espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
+	master->max_speed_hz = clk_get_rate(espi->clk) / 2;
+	master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
 	espi->pdev = pdev;
 
 	espi->sspdr_phys = res->start + SSPDR;
diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c
index dd5bd468e962..09965f069a1c 100644
--- a/drivers/spi/spi-falcon.c
+++ b/drivers/spi/spi-falcon.c
@@ -312,9 +312,6 @@ static int falcon_sflash_setup(struct spi_device *spi)
 	unsigned int i;
 	unsigned long flags;
 
-	if (spi->chip_select > 0)
-		return -ENODEV;
-
 	spin_lock_irqsave(&ebu_lock, flags);
 
 	if (spi->max_speed_hz >= CLOCK_100M) {
@@ -422,9 +419,7 @@ static int falcon_sflash_probe(struct platform_device *pdev)
 	priv->master = master;
 
 	master->mode_bits = SPI_MODE_3;
-	master->num_chipselect = 1;
 	master->flags = SPI_MASTER_HALF_DUPLEX;
-	master->bus_num = -1;
 	master->setup = falcon_sflash_setup;
 	master->prepare_transfer_hardware = falcon_sflash_prepare_xfer;
 	master->transfer_one_message = falcon_sflash_xfer_one;
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index ec79f726672a..42ede0d796a7 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -108,11 +109,11 @@ struct fsl_dspi {
 	struct spi_bitbang	bitbang;
 	struct platform_device	*pdev;
 
-	void __iomem		*base;
+	struct regmap		*regmap;
 	int			irq;
-	struct clk 		*clk;
+	struct clk		*clk;
 
-	struct spi_transfer 	*cur_transfer;
+	struct spi_transfer	*cur_transfer;
 	struct chip_data	*cur_chip;
 	size_t			len;
 	void			*tx;
@@ -123,24 +124,17 @@ struct fsl_dspi {
 	u8			cs;
 	u16			void_write_data;
 
-	wait_queue_head_t 	waitq;
-	u32 			waitflags;
+	wait_queue_head_t	waitq;
+	u32			waitflags;
 };
 
 static inline int is_double_byte_mode(struct fsl_dspi *dspi)
 {
-	return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK)
-			== SPI_FRAME_BITS(8)) ? 0 : 1;
-}
+	unsigned int val;
 
-static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits)
-{
-	u32 temp;
+	regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val);
 
-	temp = readl(dspi->base + SPI_CTAR(dspi->cs));
-	temp &= ~SPI_FRAME_BITS_MASK;
-	temp |= SPI_FRAME_BITS(bits);
-	writel(temp, dspi->base + SPI_CTAR(dspi->cs));
+	return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
 }
 
 static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
@@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
 	 */
 	if (tx_word && (dspi->len == 1)) {
 		dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-		set_bit_mode(dspi, 8);
+		regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
 		tx_word = 0;
 	}
 
@@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
 			dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */
 		}
 
-		writel(dspi_pushr, dspi->base + SPI_PUSHR);
+		regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
+
 		tx_count++;
 	}
 
@@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)
 	while ((dspi->rx < dspi->rx_end)
 			&& (rx_count < DSPI_FIFO_SIZE)) {
 		if (rx_word) {
+			unsigned int val;
+
 			if ((dspi->rx_end - dspi->rx) == 1)
 				break;
 
-			d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
+			regmap_read(dspi->regmap, SPI_POPR, &val);
+			d = SPI_POPR_RXDATA(val);
 
 			if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
 				*(u16 *)dspi->rx = d;
 			dspi->rx += 2;
 
 		} else {
-			d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
+			unsigned int val;
+
+			regmap_read(dspi->regmap, SPI_POPR, &val);
+			d = SPI_POPR_RXDATA(val);
 			if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
 				*(u8 *)dspi->rx = d;
 			dspi->rx++;
@@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
 	if (!dspi->tx)
 		dspi->dataflags |= TRAN_STATE_TX_VOID;
 
-	writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR);
-	writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs));
-	writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER);
+	regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
+	regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val);
+	regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
 
 	if (t->speed_hz)
-		writel(dspi->cur_chip->ctar_val,
-				dspi->base + SPI_CTAR(dspi->cs));
+		regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+				dspi->cur_chip->ctar_val);
 
 	dspi_transfer_write(dspi);
 
@@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
 static void dspi_chipselect(struct spi_device *spi, int value)
 {
 	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
-	u32 pushr = readl(dspi->base + SPI_PUSHR);
+	unsigned int pushr;
+
+	regmap_read(dspi->regmap, SPI_PUSHR, &pushr);
 
 	switch (value) {
 	case BITBANG_CS_ACTIVE:
@@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value)
 		break;
 	}
 
-	writel(pushr, dspi->base + SPI_PUSHR);
+	regmap_write(dspi->regmap, SPI_PUSHR, pushr);
 }
 
 static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
@@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
 {
 	struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
 
-	writel(SPI_SR_EOQF, dspi->base + SPI_SR);
+	regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
 
 	dspi_transfer_read(dspi);
 
 	if (!dspi->len) {
 		if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
-			set_bit_mode(dspi, 16);
+			regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
+
 		dspi->waitflags = 1;
 		wake_up_interruptible(&dspi->waitq);
 	} else {
@@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = {
 	SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
 };
 
+static struct regmap_config dspi_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x88,
+};
+
 static int dspi_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct spi_master *master;
 	struct fsl_dspi *dspi;
 	struct resource *res;
+	void __iomem *base;
 	int ret = 0, cs_num, bus_num;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
@@ -475,12 +489,24 @@ static int dspi_probe(struct platform_device *pdev)
 	master->bus_num = bus_num;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dspi->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dspi->base)) {
-		ret = PTR_ERR(dspi->base);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
 		goto out_master_put;
 	}
 
+	dspi_regmap_config.lock_arg = dspi;
+	dspi_regmap_config.val_format_endian =
+		of_property_read_bool(np, "big-endian")
+			? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT;
+	dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base,
+						&dspi_regmap_config);
+	if (IS_ERR(dspi->regmap)) {
+		dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+				PTR_ERR(dspi->regmap));
+		return PTR_ERR(dspi->regmap);
+	}
+
 	dspi->irq = platform_get_irq(pdev, 0);
 	if (dspi->irq < 0) {
 		dev_err(&pdev->dev, "can't get platform irq\n");
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 119f7af94537..f35488ed62a9 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -239,12 +239,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
 	if (!bits_per_word)
 		bits_per_word = spi->bits_per_word;
 
-	/* Make sure its a bit width we support [4..16, 32] */
-	if ((bits_per_word < 4)
-	    || ((bits_per_word > 16) && (bits_per_word != 32))
-	    || (bits_per_word > mpc8xxx_spi->max_bits_per_word))
-		return -EINVAL;
-
 	if (!hz)
 		hz = spi->max_speed_hz;
 
@@ -362,18 +356,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
 static void fsl_spi_do_one_msg(struct spi_message *m)
 {
 	struct spi_device *spi = m->spi;
-	struct spi_transfer *t;
+	struct spi_transfer *t, *first;
 	unsigned int cs_change;
 	const int nsecs = 50;
 	int status;
 
-	cs_change = 1;
-	status = 0;
+	/* Don't allow changes if CS is active */
+	first = list_first_entry(&m->transfers, struct spi_transfer,
+			transfer_list);
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word || t->speed_hz) {
-			/* Don't allow changes if CS is active */
+		if ((first->bits_per_word != t->bits_per_word) ||
+			(first->speed_hz != t->speed_hz)) {
 			status = -EINVAL;
+			dev_err(&spi->dev,
+				"bits_per_word/speed_hz should be same for the same SPI transfer\n");
+			return;
+		}
+	}
 
+	cs_change = 1;
+	status = -EINVAL;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
 			if (cs_change)
 				status = fsl_spi_setup_transfer(spi, t);
 			if (status < 0)
@@ -641,6 +645,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
 	if (mpc8xxx_spi->type == TYPE_GRLIB)
 		fsl_spi_grlib_probe(dev);
 
+	master->bits_per_word_mask =
+		(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
+		SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
+
 	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
 		mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
 
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 7beeb29472ac..406bbd7dcfa4 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -19,7 +19,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
@@ -250,7 +249,7 @@ static int spi_gpio_setup(struct spi_device *spi)
 		/*
 		 * ... otherwise, take it from spi->controller_data
 		 */
-		cs = (unsigned int) spi->controller_data;
+		cs = (unsigned int)(uintptr_t) spi->controller_data;
 	}
 
 	if (!spi->controller_state) {
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a5474ef9d2a0..5daff2054ae4 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -741,7 +740,7 @@ static int spi_imx_transfer(struct spi_device *spi,
 	spi_imx->count = transfer->len;
 	spi_imx->txfifo = 0;
 
-	init_completion(&spi_imx->xfer_done);
+	reinit_completion(&spi_imx->xfer_done);
 
 	spi_imx_push(spi_imx);
 
@@ -880,12 +879,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 
 	spi_imx->irq = platform_get_irq(pdev, 0);
 	if (spi_imx->irq < 0) {
-		ret = -EINVAL;
+		ret = spi_imx->irq;
 		goto out_master_put;
 	}
 
 	ret = devm_request_irq(&pdev->dev, spi_imx->irq, spi_imx_isr, 0,
-			       DRIVER_NAME, spi_imx);
+			       dev_name(&pdev->dev), spi_imx);
 	if (ret) {
 		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
 		goto out_master_put;
@@ -948,8 +947,8 @@ static int spi_imx_remove(struct platform_device *pdev)
 	spi_bitbang_stop(&spi_imx->bitbang);
 
 	writel(0, spi_imx->base + MXC_CSPICTRL);
-	clk_disable_unprepare(spi_imx->clk_ipg);
-	clk_disable_unprepare(spi_imx->clk_per);
+	clk_unprepare(spi_imx->clk_ipg);
+	clk_unprepare(spi_imx->clk_per);
 	spi_master_put(master);
 
 	return 0;
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 5032141eeeec..3822eef2ef9d 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -16,7 +16,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
@@ -466,10 +465,8 @@ static void mpc512x_spi_cs_control(struct spi_device *spi, bool onoff)
 	gpio_set_value(spi->cs_gpio, onoff);
 }
 
-/* bus_num is used only for the case dev->platform_data == NULL */
 static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
-					      u32 size, unsigned int irq,
-					      s16 bus_num)
+					      u32 size, unsigned int irq)
 {
 	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
 	struct mpc512x_psc_spi *mps;
@@ -488,7 +485,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 
 	if (pdata == NULL) {
 		mps->cs_control = mpc512x_spi_cs_control;
-		master->bus_num = bus_num;
 	} else {
 		mps->cs_control = pdata->cs_control;
 		master->bus_num = pdata->bus_num;
@@ -574,7 +570,6 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op)
 {
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
-	s16 id = -1;
 
 	regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
 	if (!regaddr_p) {
@@ -583,16 +578,8 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op)
 	}
 	regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
 
-	/* get PSC id (0..11, used by port_config) */
-	id = of_alias_get_id(op->dev.of_node, "spi");
-	if (id < 0) {
-		dev_err(&op->dev, "no alias id for %s\n",
-			op->dev.of_node->full_name);
-		return id;
-	}
-
 	return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
-				irq_of_parse_and_map(op->dev.of_node, 0), id);
+				irq_of_parse_and_map(op->dev.of_node, 0));
 }
 
 static int mpc512x_psc_spi_of_remove(struct platform_device *op)
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
index 00ba910ab302..3d18d9351185 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
index 7c675fe83101..bd404c2c26f0 100644
--- a/drivers/spi/spi-mpc52xx.c
+++ b/drivers/spi/spi-mpc52xx.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
@@ -365,9 +364,6 @@ static int mpc52xx_spi_setup(struct spi_device *spi)
 	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST))
 		return -EINVAL;
 
-	if (spi->chip_select >= spi->master->num_chipselect)
-		return -EINVAL;
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 79e5aa2250c8..2884f0c2f5f0 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -29,7 +29,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -371,7 +370,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
 {
 	struct mxs_spi *spi = spi_master_get_devdata(master);
 	struct mxs_ssp *ssp = &spi->ssp;
-	struct spi_transfer *t, *tmp_t;
+	struct spi_transfer *t;
 	unsigned int flag;
 	int status = 0;
 
@@ -381,7 +380,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
 	writel(mxs_spi_cs_to_reg(m->spi->chip_select),
 	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
-	list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
+	list_for_each_entry(t, &m->transfers, transfer_list) {
 
 		status = mxs_spi_setup_transfer(m->spi, t);
 		if (status)
@@ -473,7 +472,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq_err = platform_get_irq(pdev, 0);
 	if (irq_err < 0)
-		return -EINVAL;
+		return irq_err;
 
 	base = devm_ioremap_resource(&pdev->dev, iores);
 	if (IS_ERR(base))
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index bae97ffec4b9..675c210342c0 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
@@ -58,11 +57,8 @@ struct nuc900_spi {
 	unsigned char		*rx;
 	struct clk		*clk;
 	struct spi_master	*master;
-	struct spi_device	*curdev;
-	struct device		*dev;
 	struct nuc900_spi_info *pdata;
 	spinlock_t		lock;
-	struct resource		*res;
 };
 
 static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
@@ -338,6 +334,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 {
 	struct nuc900_spi *hw;
 	struct spi_master *master;
+	struct resource *res;
 	int err = 0;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
@@ -349,7 +346,6 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 	hw = spi_master_get_devdata(master);
 	hw->master = master;
 	hw->pdata  = dev_get_platdata(&pdev->dev);
-	hw->dev = &pdev->dev;
 
 	if (hw->pdata == NULL) {
 		dev_err(&pdev->dev, "No platform data supplied\n");
@@ -369,8 +365,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 	hw->bitbang.chipselect     = nuc900_spi_chipsel;
 	hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
 
-	hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hw->regs = devm_ioremap_resource(&pdev->dev, hw->res);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hw->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(hw->regs)) {
 		err = PTR_ERR(hw->regs);
 		goto err_pdata;
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index f7c896e2981e..022774e158f1 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -15,7 +15,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/module.h>
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
index 67249a48b391..c5e2f718eebd 100644
--- a/drivers/spi/spi-octeon.c
+++ b/drivers/spi/spi-octeon.c
@@ -11,7 +11,6 @@
 #include <linux/spi/spi.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of.h>
 
@@ -33,13 +32,6 @@ struct octeon_spi {
 	u64 cs_enax;
 };
 
-struct octeon_spi_setup {
-	u32 max_speed_hz;
-	u8 chip_select;
-	u8 mode;
-	u8 bits_per_word;
-};
-
 static void octeon_spi_wait_ready(struct octeon_spi *p)
 {
 	union cvmx_mpi_sts mpi_sts;
@@ -57,6 +49,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 				  struct spi_transfer *xfer,
 				  bool last_xfer)
 {
+	struct spi_device *spi = msg->spi;
 	union cvmx_mpi_cfg mpi_cfg;
 	union cvmx_mpi_tx mpi_tx;
 	unsigned int clkdiv;
@@ -68,18 +61,11 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 	int len;
 	int i;
 
-	struct octeon_spi_setup *msg_setup = spi_get_ctldata(msg->spi);
-
-	speed_hz = msg_setup->max_speed_hz;
-	mode = msg_setup->mode;
+	mode = spi->mode;
 	cpha = mode & SPI_CPHA;
 	cpol = mode & SPI_CPOL;
 
-	if (xfer->speed_hz)
-		speed_hz = xfer->speed_hz;
-
-	if (speed_hz > OCTEON_SPI_MAX_CLOCK_HZ)
-		speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
+	speed_hz = xfer->speed_hz ? : spi->max_speed_hz;
 
 	clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);
 
@@ -93,8 +79,8 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 	mpi_cfg.s.cslate = cpha ? 1 : 0;
 	mpi_cfg.s.enable = 1;
 
-	if (msg_setup->chip_select < 4)
-		p->cs_enax |= 1ull << (12 + msg_setup->chip_select);
+	if (spi->chip_select < 4)
+		p->cs_enax |= 1ull << (12 + spi->chip_select);
 	mpi_cfg.u64 |= p->cs_enax;
 
 	if (mpi_cfg.u64 != p->last_cfg) {
@@ -114,7 +100,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 			cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);
 		}
 		mpi_tx.u64 = 0;
-		mpi_tx.s.csid = msg_setup->chip_select;
+		mpi_tx.s.csid = spi->chip_select;
 		mpi_tx.s.leavecs = 1;
 		mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;
 		mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;
@@ -139,7 +125,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 	}
 
 	mpi_tx.u64 = 0;
-	mpi_tx.s.csid = msg_setup->chip_select;
+	mpi_tx.s.csid = spi->chip_select;
 	if (last_xfer)
 		mpi_tx.s.leavecs = xfer->cs_change;
 	else
@@ -169,17 +155,9 @@ static int octeon_spi_transfer_one_message(struct spi_master *master,
 	int status = 0;
 	struct spi_transfer *xfer;
 
-	/*
-	 * We better have set the configuration via a call to .setup
-	 * before we get here.
-	 */
-	if (spi_get_ctldata(msg->spi) == NULL) {
-		status = -EINVAL;
-		goto err;
-	}
-
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		bool last_xfer = &xfer->transfer_list == msg->transfers.prev;
+		bool last_xfer = list_is_last(&xfer->transfer_list,
+					      &msg->transfers);
 		int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
 		if (r < 0) {
 			status = r;
@@ -194,41 +172,6 @@ err:
 	return status;
 }
 
-static struct octeon_spi_setup *octeon_spi_new_setup(struct spi_device *spi)
-{
-	struct octeon_spi_setup *setup = kzalloc(sizeof(*setup), GFP_KERNEL);
-	if (!setup)
-		return NULL;
-
-	setup->max_speed_hz = spi->max_speed_hz;
-	setup->chip_select = spi->chip_select;
-	setup->mode = spi->mode;
-	setup->bits_per_word = spi->bits_per_word;
-	return setup;
-}
-
-static int octeon_spi_setup(struct spi_device *spi)
-{
-	struct octeon_spi_setup *new_setup;
-	struct octeon_spi_setup *old_setup = spi_get_ctldata(spi);
-
-	new_setup = octeon_spi_new_setup(spi);
-	if (!new_setup)
-		return -ENOMEM;
-
-	spi_set_ctldata(spi, new_setup);
-	kfree(old_setup);
-
-	return 0;
-}
-
-static void octeon_spi_cleanup(struct spi_device *spi)
-{
-	struct octeon_spi_setup *old_setup = spi_get_ctldata(spi);
-	spi_set_ctldata(spi, NULL);
-	kfree(old_setup);
-}
-
 static int octeon_spi_probe(struct platform_device *pdev)
 {
 	struct resource *res_mem;
@@ -257,8 +200,6 @@ static int octeon_spi_probe(struct platform_device *pdev)
 	p->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start,
 					     resource_size(res_mem));
 
-	/* Dynamic bus numbering */
-	master->bus_num = -1;
 	master->num_chipselect = 4;
 	master->mode_bits = SPI_CPHA |
 			    SPI_CPOL |
@@ -266,10 +207,9 @@ static int octeon_spi_probe(struct platform_device *pdev)
 			    SPI_LSB_FIRST |
 			    SPI_3WIRE;
 
-	master->setup = octeon_spi_setup;
-	master->cleanup = octeon_spi_cleanup;
 	master->transfer_one_message = octeon_spi_transfer_one_message;
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
+	master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
 
 	master->dev.of_node = pdev->dev.of_node;
 	err = devm_spi_register_master(&pdev->dev, master);
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
index 0d32054bfc0d..3b8b36a144b4 100644
--- a/drivers/spi/spi-omap-100k.c
+++ b/drivers/spi/spi-omap-100k.c
@@ -83,15 +83,11 @@
 #define SPI_SHUTDOWN	1
 
 struct omap1_spi100k {
-	struct spi_master       *master;
 	struct clk              *ick;
 	struct clk              *fck;
 
 	/* Virtual base address of the controller */
 	void __iomem            *base;
-
-	/* State of the SPI */
-	unsigned int		state;
 };
 
 struct omap1_spi100k_cs {
@@ -99,13 +95,6 @@ struct omap1_spi100k_cs {
 	int                     word_len;
 };
 
-#define MOD_REG_BIT(val, mask, set) do { \
-	if (set) \
-		val |= mask; \
-	else \
-		val &= ~mask; \
-} while (0)
-
 static void spi100k_enable_clock(struct spi_master *master)
 {
 	unsigned int val;
@@ -204,12 +193,10 @@ static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
 static unsigned
 omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 {
-	struct omap1_spi100k    *spi100k;
 	struct omap1_spi100k_cs *cs = spi->controller_state;
 	unsigned int            count, c;
 	int                     word_len;
 
-	spi100k = spi_master_get_devdata(spi->master);
 	count = xfer->len;
 	c = count;
 	word_len = cs->word_len;
@@ -434,7 +421,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	spi100k = spi_master_get_devdata(master);
-	spi100k->master = master;
 
 	/*
 	 * The memory region base address is taken as the platform_data.
@@ -461,8 +447,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
 	if (status < 0)
 		goto err;
 
-	spi100k->state = SPI_RUNNING;
-
 	return status;
 
 err:
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index 9313fd3b413d..95cc6948a2ba 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -99,7 +99,6 @@ struct uwire_spi {
 };
 
 struct uwire_state {
-	unsigned	bits_per_word;
 	unsigned	div1_idx;
 };
 
@@ -210,9 +209,8 @@ static void uwire_chipselect(struct spi_device *spi, int value)
 
 static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
 {
-	struct uwire_state *ust = spi->controller_state;
 	unsigned	len = t->len;
-	unsigned	bits = ust->bits_per_word;
+	unsigned	bits = t->bits_per_word ? : spi->bits_per_word;
 	unsigned	bytes;
 	u16		val, w;
 	int		status = 0;
@@ -322,7 +320,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	struct uwire_state	*ust = spi->controller_state;
 	struct uwire_spi	*uwire;
 	unsigned		flags = 0;
-	unsigned		bits;
 	unsigned		hz;
 	unsigned long		rate;
 	int			div1_idx;
@@ -332,23 +329,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
 	uwire = spi_master_get_devdata(spi->master);
 
-	if (spi->chip_select > 3) {
-		pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
-		status = -ENODEV;
-		goto done;
-	}
-
-	bits = spi->bits_per_word;
-	if (t != NULL && t->bits_per_word)
-		bits = t->bits_per_word;
-
-	if (bits > 16) {
-		pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
-		status = -ENODEV;
-		goto done;
-	}
-	ust->bits_per_word = bits;
-
 	/* mode 0..3, clock inverted separately;
 	 * standard nCS signaling;
 	 * don't treat DI=high as "not ready"
@@ -515,7 +495,7 @@ static int uwire_probe(struct platform_device *pdev)
 
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
+	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
 	master->flags = SPI_MASTER_HALF_DUPLEX;
 
 	master->bus_num = 2;	/* "official" */
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index a72127f08e39..2941c5b96ebc 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -45,6 +44,7 @@
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #define OMAP2_MCSPI_MAX_FREQ		48000000
+#define OMAP2_MCSPI_MAX_DIVIDER		4096
 #define OMAP2_MCSPI_MAX_FIFODEPTH	64
 #define OMAP2_MCSPI_MAX_FIFOWCNT	0xFFFF
 #define SPI_AUTOSUSPEND_TIMEOUT		2000
@@ -89,6 +89,7 @@
 #define OMAP2_MCSPI_CHCONF_FORCE	BIT(20)
 #define OMAP2_MCSPI_CHCONF_FFET		BIT(27)
 #define OMAP2_MCSPI_CHCONF_FFER		BIT(28)
+#define OMAP2_MCSPI_CHCONF_CLKG		BIT(29)
 
 #define OMAP2_MCSPI_CHSTAT_RXS		BIT(0)
 #define OMAP2_MCSPI_CHSTAT_TXS		BIT(1)
@@ -96,6 +97,7 @@
 #define OMAP2_MCSPI_CHSTAT_TXFFE	BIT(3)
 
 #define OMAP2_MCSPI_CHCTRL_EN		BIT(0)
+#define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK	(0xff << 8)
 
 #define OMAP2_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
 
@@ -149,7 +151,7 @@ struct omap2_mcspi_cs {
 	int			word_len;
 	struct list_head	node;
 	/* Context save and restore shadow register */
-	u32			chconf0;
+	u32			chconf0, chctrl0;
 };
 
 static inline void mcspi_write_reg(struct spi_master *master,
@@ -230,10 +232,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
 
 static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
 {
+	struct omap2_mcspi_cs *cs = spi->controller_state;
 	u32 l;
 
-	l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+	l = cs->chctrl0;
+	if (enable)
+		l |= OMAP2_MCSPI_CHCTRL_EN;
+	else
+		l &= ~OMAP2_MCSPI_CHCTRL_EN;
+	cs->chctrl0 = l;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
 	/* Flash post-writes */
 	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
 }
@@ -840,7 +848,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	struct omap2_mcspi_cs *cs = spi->controller_state;
 	struct omap2_mcspi *mcspi;
 	struct spi_master *spi_cntrl;
-	u32 l = 0, div = 0;
+	u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
 	u8 word_len = spi->bits_per_word;
 	u32 speed_hz = spi->max_speed_hz;
 
@@ -856,7 +864,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 		speed_hz = t->speed_hz;
 
 	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
-	div = omap2_mcspi_calc_divisor(speed_hz);
+	if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
+		clkd = omap2_mcspi_calc_divisor(speed_hz);
+		speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
+		clkg = 0;
+	} else {
+		div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
+		speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
+		clkd = (div - 1) & 0xf;
+		extclk = (div - 1) >> 4;
+		clkg = OMAP2_MCSPI_CHCONF_CLKG;
+	}
 
 	l = mcspi_cached_chconf0(spi);
 
@@ -885,7 +903,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 
 	/* set clock divisor */
 	l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
-	l |= div << 2;
+	l |= clkd << 2;
+
+	/* set clock granularity */
+	l &= ~OMAP2_MCSPI_CHCONF_CLKG;
+	l |= clkg;
+	if (clkg) {
+		cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK;
+		cs->chctrl0 |= extclk << 8;
+		mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
+	}
 
 	/* set SPI mode 0..3 */
 	if (spi->mode & SPI_CPOL)
@@ -900,7 +927,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	mcspi_write_chconf0(spi, l);
 
 	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
-			OMAP2_MCSPI_MAX_FREQ >> div,
+			speed_hz,
 			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
 			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
 
@@ -972,6 +999,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 		cs->base = mcspi->base + spi->chip_select * 0x14;
 		cs->phys = mcspi->phys + spi->chip_select * 0x14;
 		cs->chconf0 = 0;
+		cs->chctrl0 = 0;
 		spi->controller_state = cs;
 		/* Link this to context save list */
 		list_add_tail(&cs->node, &ctx->cs);
@@ -1057,12 +1085,15 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 			status = -EINVAL;
 			break;
 		}
-		if (par_override || t->speed_hz || t->bits_per_word) {
+		if (par_override ||
+		    (t->speed_hz != spi->max_speed_hz) ||
+		    (t->bits_per_word != spi->bits_per_word)) {
 			par_override = 1;
 			status = omap2_mcspi_setup_transfer(spi, t);
 			if (status < 0)
 				break;
-			if (!t->speed_hz && !t->bits_per_word)
+			if (t->speed_hz == spi->max_speed_hz &&
+			    t->bits_per_word == spi->bits_per_word)
 				par_override = 0;
 		}
 		if (cd && cd->cs_per_word) {
@@ -1176,16 +1207,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
 	m->actual_length = 0;
 	m->status = 0;
 
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers))
-		return -EINVAL;
 	list_for_each_entry(t, &m->transfers, transfer_list) {
 		const void	*tx_buf = t->tx_buf;
 		void		*rx_buf = t->rx_buf;
 		unsigned	len = t->len;
 
-		if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
-				|| (len && !(rx_buf || tx_buf))) {
+		if ((len && !(rx_buf || tx_buf))) {
 			dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
 					t->speed_hz,
 					len,
@@ -1194,12 +1221,6 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
 					t->bits_per_word);
 			return -EINVAL;
 		}
-		if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
-			dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
-					t->speed_hz,
-					OMAP2_MCSPI_MAX_FREQ >> 15);
-			return -EINVAL;
-		}
 
 		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
 			continue;
@@ -1311,6 +1332,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
 	master->transfer_one_message = omap2_mcspi_transfer_one_message;
 	master->cleanup = omap2_mcspi_cleanup;
 	master->dev.of_node = node;
+	master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
+	master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
 
 	platform_set_drvdata(pdev, master);
 
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 7f2121fe2622..d018a4aac3a1 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -9,7 +9,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
@@ -43,8 +42,6 @@
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
-	unsigned int		max_speed;
-	unsigned int		min_speed;
 	struct clk              *clk;
 };
 
@@ -75,23 +72,6 @@ orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
 	writel(val, reg_addr);
 }
 
-static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
-{
-	if (size == 16) {
-		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-				  ORION_SPI_IF_8_16_BIT_MODE);
-	} else if (size == 8) {
-		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-				  ORION_SPI_IF_8_16_BIT_MODE);
-	} else {
-		pr_debug("Bad bits per word value %d (only 8 or 16 are allowed).\n",
-			size);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
 {
 	u32 tclk_hz;
@@ -170,7 +150,14 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	if (rc)
 		return rc;
 
-	return orion_spi_set_transfer_size(orion_spi, bits_per_word);
+	if (bits_per_word == 16)
+		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+				  ORION_SPI_IF_8_16_BIT_MODE);
+	else
+		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+				  ORION_SPI_IF_8_16_BIT_MODE);
+
+	return 0;
 }
 
 static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
@@ -260,11 +247,9 @@ orion_spi_write_read_16bit(struct spi_device *spi,
 static unsigned int
 orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
-	struct orion_spi *orion_spi;
 	unsigned int count;
 	int word_len;
 
-	orion_spi = spi_master_get_devdata(spi->master);
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
@@ -310,27 +295,6 @@ static int orion_spi_transfer_one_message(struct spi_master *master,
 		goto msg_done;
 
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		/* make sure buffer length is even when working in 16
-		 * bit mode*/
-		if ((t->bits_per_word == 16) && (t->len & 1)) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"odd data length %d while in 16 bit mode\n",
-				t->len);
-			status = -EIO;
-			goto msg_done;
-		}
-
-		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"device min speed (%d Hz) exceeds "
-				"required transfer speed (%d Hz)\n",
-				orion_spi->min_speed, t->speed_hz);
-			status = -EIO;
-			goto msg_done;
-		}
-
 		if (par_override || t->speed_hz || t->bits_per_word) {
 			par_override = 1;
 			status = orion_spi_setup_transfer(spi, t);
@@ -375,28 +339,6 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 	return 0;
 }
 
-static int orion_spi_setup(struct spi_device *spi)
-{
-	struct orion_spi *orion_spi;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	if ((spi->max_speed_hz == 0)
-			|| (spi->max_speed_hz > orion_spi->max_speed))
-		spi->max_speed_hz = orion_spi->max_speed;
-
-	if (spi->max_speed_hz < orion_spi->min_speed) {
-		dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
-			spi->max_speed_hz);
-		return -EINVAL;
-	}
-
-	/*
-	 * baudrate & width will be set orion_spi_setup_transfer
-	 */
-	return 0;
-}
-
 static int orion_spi_probe(struct platform_device *pdev)
 {
 	struct spi_master *master;
@@ -425,9 +367,9 @@ static int orion_spi_probe(struct platform_device *pdev)
 	/* we support only mode 0, and no options */
 	master->mode_bits = SPI_CPHA | SPI_CPOL;
 
-	master->setup = orion_spi_setup;
 	master->transfer_one_message = orion_spi_transfer_one_message;
 	master->num_chipselect = ORION_NUM_CHIPSELECTS;
+	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
 
 	platform_set_drvdata(pdev, master);
 
@@ -443,8 +385,8 @@ static int orion_spi_probe(struct platform_device *pdev)
 	clk_prepare(spi->clk);
 	clk_enable(spi->clk);
 	tclk_hz = clk_get_rate(spi->clk);
-	spi->max_speed = DIV_ROUND_UP(tclk_hz, 4);
-	spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
+	master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
+	master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	spi->base = devm_ioremap_resource(&pdev->dev, r);
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 2789b452e711..3e7c37716375 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -459,9 +459,8 @@ static void giveback(struct pl022 *pl022)
 	struct spi_transfer *last_transfer;
 	pl022->next_msg_cs_active = false;
 
-	last_transfer = list_entry(pl022->cur_msg->transfers.prev,
-					struct spi_transfer,
-					transfer_list);
+	last_transfer = list_last_entry(&pl022->cur_msg->transfers,
+					struct spi_transfer, transfer_list);
 
 	/* Delay if requested before any change in chip select */
 	if (last_transfer->delay_usecs)
@@ -2109,8 +2108,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
 					  GFP_KERNEL);
 
-	pinctrl_pm_select_default_state(dev);
-
 	/*
 	 * Bus Number Which has been Assigned to this SSP controller
 	 * on this board
@@ -2183,13 +2180,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_no_clk;
 	}
 
-	status = clk_prepare(pl022->clk);
-	if (status) {
-		dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
-		goto  err_clk_prep;
-	}
-
-	status = clk_enable(pl022->clk);
+	status = clk_prepare_enable(pl022->clk);
 	if (status) {
 		dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
 		goto err_no_clk_en;
@@ -2250,10 +2241,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	if (platform_info->enable_dma)
 		pl022_dma_remove(pl022);
  err_no_irq:
-	clk_disable(pl022->clk);
+	clk_disable_unprepare(pl022->clk);
  err_no_clk_en:
-	clk_unprepare(pl022->clk);
- err_clk_prep:
  err_no_clk:
  err_no_ioremap:
 	amba_release_regions(adev);
@@ -2281,8 +2270,7 @@ pl022_remove(struct amba_device *adev)
 	if (pl022->master_info->enable_dma)
 		pl022_dma_remove(pl022);
 
-	clk_disable(pl022->clk);
-	clk_unprepare(pl022->clk);
+	clk_disable_unprepare(pl022->clk);
 	amba_release_regions(adev);
 	tasklet_disable(&pl022->pump_transfers);
 	return 0;
@@ -2296,7 +2284,7 @@ pl022_remove(struct amba_device *adev)
  */
 static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
 {
-	clk_disable(pl022->clk);
+	clk_disable_unprepare(pl022->clk);
 
 	if (runtime)
 		pinctrl_pm_select_idle_state(&pl022->adev->dev);
@@ -2312,7 +2300,7 @@ static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
 		/* Then let's idle the pins until the next transfer happens */
 		pinctrl_pm_select_idle_state(&pl022->adev->dev);
 
-	clk_enable(pl022->clk);
+	clk_prepare_enable(pl022->clk);
 }
 #endif
 
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 5ee56726f8d0..80b8408ac3e3 100644
--- a/drivers/spi/spi-ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -24,7 +24,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index 3c0b55125f1e..713af4806f26 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -9,7 +9,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-pxadma.c
index 2916efc7cfe5..e8a26f25d5c0 100644
--- a/drivers/spi/spi-pxa2xx-pxadma.c
+++ b/drivers/spi/spi-pxa2xx-pxadma.c
@@ -18,7 +18,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index c702fc536a77..41185d0557fa 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -362,8 +362,7 @@ static void giveback(struct driver_data *drv_data)
 	drv_data->cur_msg = NULL;
 	drv_data->cur_transfer = NULL;
 
-	last_transfer = list_entry(msg->transfers.prev,
-					struct spi_transfer,
+	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
 					transfer_list);
 
 	/* Delay if requested before any change in chip select */
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
new file mode 100644
index 000000000000..b032e8885e24
--- /dev/null
+++ b/drivers/spi/spi-qup.c
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2008-2014, The Linux foundation. 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 rev 2 and
+ * only rev 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/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/spi/spi.h>
+
+#define QUP_CONFIG			0x0000
+#define QUP_STATE			0x0004
+#define QUP_IO_M_MODES			0x0008
+#define QUP_SW_RESET			0x000c
+#define QUP_OPERATIONAL			0x0018
+#define QUP_ERROR_FLAGS			0x001c
+#define QUP_ERROR_FLAGS_EN		0x0020
+#define QUP_OPERATIONAL_MASK		0x0028
+#define QUP_HW_VERSION			0x0030
+#define QUP_MX_OUTPUT_CNT		0x0100
+#define QUP_OUTPUT_FIFO			0x0110
+#define QUP_MX_WRITE_CNT		0x0150
+#define QUP_MX_INPUT_CNT		0x0200
+#define QUP_MX_READ_CNT			0x0208
+#define QUP_INPUT_FIFO			0x0218
+
+#define SPI_CONFIG			0x0300
+#define SPI_IO_CONTROL			0x0304
+#define SPI_ERROR_FLAGS			0x0308
+#define SPI_ERROR_FLAGS_EN		0x030c
+
+/* QUP_CONFIG fields */
+#define QUP_CONFIG_SPI_MODE		(1 << 8)
+#define QUP_CONFIG_CLOCK_AUTO_GATE	BIT(13)
+#define QUP_CONFIG_NO_INPUT		BIT(7)
+#define QUP_CONFIG_NO_OUTPUT		BIT(6)
+#define QUP_CONFIG_N			0x001f
+
+/* QUP_STATE fields */
+#define QUP_STATE_VALID			BIT(2)
+#define QUP_STATE_RESET			0
+#define QUP_STATE_RUN			1
+#define QUP_STATE_PAUSE			3
+#define QUP_STATE_MASK			3
+#define QUP_STATE_CLEAR			2
+
+#define QUP_HW_VERSION_2_1_1		0x20010001
+
+/* QUP_IO_M_MODES fields */
+#define QUP_IO_M_PACK_EN		BIT(15)
+#define QUP_IO_M_UNPACK_EN		BIT(14)
+#define QUP_IO_M_INPUT_MODE_MASK_SHIFT	12
+#define QUP_IO_M_OUTPUT_MODE_MASK_SHIFT	10
+#define QUP_IO_M_INPUT_MODE_MASK	(3 << QUP_IO_M_INPUT_MODE_MASK_SHIFT)
+#define QUP_IO_M_OUTPUT_MODE_MASK	(3 << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT)
+
+#define QUP_IO_M_OUTPUT_BLOCK_SIZE(x)	(((x) & (0x03 << 0)) >> 0)
+#define QUP_IO_M_OUTPUT_FIFO_SIZE(x)	(((x) & (0x07 << 2)) >> 2)
+#define QUP_IO_M_INPUT_BLOCK_SIZE(x)	(((x) & (0x03 << 5)) >> 5)
+#define QUP_IO_M_INPUT_FIFO_SIZE(x)	(((x) & (0x07 << 7)) >> 7)
+
+#define QUP_IO_M_MODE_FIFO		0
+#define QUP_IO_M_MODE_BLOCK		1
+#define QUP_IO_M_MODE_DMOV		2
+#define QUP_IO_M_MODE_BAM		3
+
+/* QUP_OPERATIONAL fields */
+#define QUP_OP_MAX_INPUT_DONE_FLAG	BIT(11)
+#define QUP_OP_MAX_OUTPUT_DONE_FLAG	BIT(10)
+#define QUP_OP_IN_SERVICE_FLAG		BIT(9)
+#define QUP_OP_OUT_SERVICE_FLAG		BIT(8)
+#define QUP_OP_IN_FIFO_FULL		BIT(7)
+#define QUP_OP_OUT_FIFO_FULL		BIT(6)
+#define QUP_OP_IN_FIFO_NOT_EMPTY	BIT(5)
+#define QUP_OP_OUT_FIFO_NOT_EMPTY	BIT(4)
+
+/* QUP_ERROR_FLAGS and QUP_ERROR_FLAGS_EN fields */
+#define QUP_ERROR_OUTPUT_OVER_RUN	BIT(5)
+#define QUP_ERROR_INPUT_UNDER_RUN	BIT(4)
+#define QUP_ERROR_OUTPUT_UNDER_RUN	BIT(3)
+#define QUP_ERROR_INPUT_OVER_RUN	BIT(2)
+
+/* SPI_CONFIG fields */
+#define SPI_CONFIG_HS_MODE		BIT(10)
+#define SPI_CONFIG_INPUT_FIRST		BIT(9)
+#define SPI_CONFIG_LOOPBACK		BIT(8)
+
+/* SPI_IO_CONTROL fields */
+#define SPI_IO_C_FORCE_CS		BIT(11)
+#define SPI_IO_C_CLK_IDLE_HIGH		BIT(10)
+#define SPI_IO_C_MX_CS_MODE		BIT(8)
+#define SPI_IO_C_CS_N_POLARITY_0	BIT(4)
+#define SPI_IO_C_CS_SELECT(x)		(((x) & 3) << 2)
+#define SPI_IO_C_CS_SELECT_MASK		0x000c
+#define SPI_IO_C_TRISTATE_CS		BIT(1)
+#define SPI_IO_C_NO_TRI_STATE		BIT(0)
+
+/* SPI_ERROR_FLAGS and SPI_ERROR_FLAGS_EN fields */
+#define SPI_ERROR_CLK_OVER_RUN		BIT(1)
+#define SPI_ERROR_CLK_UNDER_RUN		BIT(0)
+
+#define SPI_NUM_CHIPSELECTS		4
+
+/* high speed mode is when bus rate is greater then 26MHz */
+#define SPI_HS_MIN_RATE			26000000
+#define SPI_MAX_RATE			50000000
+
+#define SPI_DELAY_THRESHOLD		1
+#define SPI_DELAY_RETRY			10
+
+struct spi_qup {
+	void __iomem		*base;
+	struct device		*dev;
+	struct clk		*cclk;	/* core clock */
+	struct clk		*iclk;	/* interface clock */
+	int			irq;
+	spinlock_t		lock;
+
+	int			in_fifo_sz;
+	int			out_fifo_sz;
+	int			in_blk_sz;
+	int			out_blk_sz;
+
+	struct spi_transfer	*xfer;
+	struct completion	done;
+	int			error;
+	int			w_size;	/* bytes per SPI word */
+	int			tx_bytes;
+	int			rx_bytes;
+};
+
+
+static inline bool spi_qup_is_valid_state(struct spi_qup *controller)
+{
+	u32 opstate = readl_relaxed(controller->base + QUP_STATE);
+
+	return opstate & QUP_STATE_VALID;
+}
+
+static int spi_qup_set_state(struct spi_qup *controller, u32 state)
+{
+	unsigned long loop;
+	u32 cur_state;
+
+	loop = 0;
+	while (!spi_qup_is_valid_state(controller)) {
+
+		usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);
+
+		if (++loop > SPI_DELAY_RETRY)
+			return -EIO;
+	}
+
+	if (loop)
+		dev_dbg(controller->dev, "invalid state for %ld,us %d\n",
+			loop, state);
+
+	cur_state = readl_relaxed(controller->base + QUP_STATE);
+	/*
+	 * Per spec: for PAUSE_STATE to RESET_STATE, two writes
+	 * of (b10) are required
+	 */
+	if (((cur_state & QUP_STATE_MASK) == QUP_STATE_PAUSE) &&
+	    (state == QUP_STATE_RESET)) {
+		writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
+		writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
+	} else {
+		cur_state &= ~QUP_STATE_MASK;
+		cur_state |= state;
+		writel_relaxed(cur_state, controller->base + QUP_STATE);
+	}
+
+	loop = 0;
+	while (!spi_qup_is_valid_state(controller)) {
+
+		usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);
+
+		if (++loop > SPI_DELAY_RETRY)
+			return -EIO;
+	}
+
+	return 0;
+}
+
+
+static void spi_qup_fifo_read(struct spi_qup *controller,
+			    struct spi_transfer *xfer)
+{
+	u8 *rx_buf = xfer->rx_buf;
+	u32 word, state;
+	int idx, shift, w_size;
+
+	w_size = controller->w_size;
+
+	while (controller->rx_bytes < xfer->len) {
+
+		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
+		if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY))
+			break;
+
+		word = readl_relaxed(controller->base + QUP_INPUT_FIFO);
+
+		if (!rx_buf) {
+			controller->rx_bytes += w_size;
+			continue;
+		}
+
+		for (idx = 0; idx < w_size; idx++, controller->rx_bytes++) {
+			/*
+			 * The data format depends on bytes per SPI word:
+			 *  4 bytes: 0x12345678
+			 *  2 bytes: 0x00001234
+			 *  1 byte : 0x00000012
+			 */
+			shift = BITS_PER_BYTE;
+			shift *= (w_size - idx - 1);
+			rx_buf[controller->rx_bytes] = word >> shift;
+		}
+	}
+}
+
+static void spi_qup_fifo_write(struct spi_qup *controller,
+			    struct spi_transfer *xfer)
+{
+	const u8 *tx_buf = xfer->tx_buf;
+	u32 word, state, data;
+	int idx, w_size;
+
+	w_size = controller->w_size;
+
+	while (controller->tx_bytes < xfer->len) {
+
+		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
+		if (state & QUP_OP_OUT_FIFO_FULL)
+			break;
+
+		word = 0;
+		for (idx = 0; idx < w_size; idx++, controller->tx_bytes++) {
+
+			if (!tx_buf) {
+				controller->tx_bytes += w_size;
+				break;
+			}
+
+			data = tx_buf[controller->tx_bytes];
+			word |= data << (BITS_PER_BYTE * (3 - idx));
+		}
+
+		writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO);
+	}
+}
+
+static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
+{
+	struct spi_qup *controller = dev_id;
+	struct spi_transfer *xfer;
+	u32 opflags, qup_err, spi_err;
+	unsigned long flags;
+	int error = 0;
+
+	spin_lock_irqsave(&controller->lock, flags);
+	xfer = controller->xfer;
+	controller->xfer = NULL;
+	spin_unlock_irqrestore(&controller->lock, flags);
+
+	qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
+	spi_err = readl_relaxed(controller->base + SPI_ERROR_FLAGS);
+	opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
+
+	writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS);
+	writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS);
+	writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
+
+	if (!xfer) {
+		dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n",
+				    qup_err, spi_err, opflags);
+		return IRQ_HANDLED;
+	}
+
+	if (qup_err) {
+		if (qup_err & QUP_ERROR_OUTPUT_OVER_RUN)
+			dev_warn(controller->dev, "OUTPUT_OVER_RUN\n");
+		if (qup_err & QUP_ERROR_INPUT_UNDER_RUN)
+			dev_warn(controller->dev, "INPUT_UNDER_RUN\n");
+		if (qup_err & QUP_ERROR_OUTPUT_UNDER_RUN)
+			dev_warn(controller->dev, "OUTPUT_UNDER_RUN\n");
+		if (qup_err & QUP_ERROR_INPUT_OVER_RUN)
+			dev_warn(controller->dev, "INPUT_OVER_RUN\n");
+
+		error = -EIO;
+	}
+
+	if (spi_err) {
+		if (spi_err & SPI_ERROR_CLK_OVER_RUN)
+			dev_warn(controller->dev, "CLK_OVER_RUN\n");
+		if (spi_err & SPI_ERROR_CLK_UNDER_RUN)
+			dev_warn(controller->dev, "CLK_UNDER_RUN\n");
+
+		error = -EIO;
+	}
+
+	if (opflags & QUP_OP_IN_SERVICE_FLAG)
+		spi_qup_fifo_read(controller, xfer);
+
+	if (opflags & QUP_OP_OUT_SERVICE_FLAG)
+		spi_qup_fifo_write(controller, xfer);
+
+	spin_lock_irqsave(&controller->lock, flags);
+	controller->error = error;
+	controller->xfer = xfer;
+	spin_unlock_irqrestore(&controller->lock, flags);
+
+	if (controller->rx_bytes == xfer->len || error)
+		complete(&controller->done);
+
+	return IRQ_HANDLED;
+}
+
+
+/* set clock freq ... bits per word */
+static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct spi_qup *controller = spi_master_get_devdata(spi->master);
+	u32 config, iomode, mode;
+	int ret, n_words, w_size;
+
+	if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
+		dev_err(controller->dev, "too big size for loopback %d > %d\n",
+			xfer->len, controller->in_fifo_sz);
+		return -EIO;
+	}
+
+	ret = clk_set_rate(controller->cclk, xfer->speed_hz);
+	if (ret) {
+		dev_err(controller->dev, "fail to set frequency %d",
+			xfer->speed_hz);
+		return -EIO;
+	}
+
+	if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
+		dev_err(controller->dev, "cannot set RESET state\n");
+		return -EIO;
+	}
+
+	w_size = 4;
+	if (xfer->bits_per_word <= 8)
+		w_size = 1;
+	else if (xfer->bits_per_word <= 16)
+		w_size = 2;
+
+	n_words = xfer->len / w_size;
+	controller->w_size = w_size;
+
+	if (n_words <= controller->in_fifo_sz) {
+		mode = QUP_IO_M_MODE_FIFO;
+		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
+		writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
+		/* must be zero for FIFO */
+		writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
+		writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
+	} else {
+		mode = QUP_IO_M_MODE_BLOCK;
+		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
+		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
+		/* must be zero for BLOCK and BAM */
+		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
+		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+	}
+
+	iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
+	/* Set input and output transfer mode */
+	iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
+	iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
+	iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
+	iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
+
+	writel_relaxed(iomode, controller->base + QUP_IO_M_MODES);
+
+	config = readl_relaxed(controller->base + SPI_CONFIG);
+
+	if (spi->mode & SPI_LOOP)
+		config |= SPI_CONFIG_LOOPBACK;
+	else
+		config &= ~SPI_CONFIG_LOOPBACK;
+
+	if (spi->mode & SPI_CPHA)
+		config &= ~SPI_CONFIG_INPUT_FIRST;
+	else
+		config |= SPI_CONFIG_INPUT_FIRST;
+
+	/*
+	 * HS_MODE improves signal stability for spi-clk high rates,
+	 * but is invalid in loop back mode.
+	 */
+	if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(spi->mode & SPI_LOOP))
+		config |= SPI_CONFIG_HS_MODE;
+	else
+		config &= ~SPI_CONFIG_HS_MODE;
+
+	writel_relaxed(config, controller->base + SPI_CONFIG);
+
+	config = readl_relaxed(controller->base + QUP_CONFIG);
+	config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
+	config |= xfer->bits_per_word - 1;
+	config |= QUP_CONFIG_SPI_MODE;
+	writel_relaxed(config, controller->base + QUP_CONFIG);
+
+	writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
+	return 0;
+}
+
+static void spi_qup_set_cs(struct spi_device *spi, bool enable)
+{
+	struct spi_qup *controller = spi_master_get_devdata(spi->master);
+
+	u32 iocontol, mask;
+
+	iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
+
+	/* Disable auto CS toggle and use manual */
+	iocontol &= ~SPI_IO_C_MX_CS_MODE;
+	iocontol |= SPI_IO_C_FORCE_CS;
+
+	iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
+	iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select);
+
+	mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select;
+
+	if (enable)
+		iocontol |= mask;
+	else
+		iocontol &= ~mask;
+
+	writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
+}
+
+static int spi_qup_transfer_one(struct spi_master *master,
+			      struct spi_device *spi,
+			      struct spi_transfer *xfer)
+{
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	unsigned long timeout, flags;
+	int ret = -EIO;
+
+	ret = spi_qup_io_config(spi, xfer);
+	if (ret)
+		return ret;
+
+	timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC);
+	timeout = DIV_ROUND_UP(xfer->len * 8, timeout);
+	timeout = 100 * msecs_to_jiffies(timeout);
+
+	reinit_completion(&controller->done);
+
+	spin_lock_irqsave(&controller->lock, flags);
+	controller->xfer     = xfer;
+	controller->error    = 0;
+	controller->rx_bytes = 0;
+	controller->tx_bytes = 0;
+	spin_unlock_irqrestore(&controller->lock, flags);
+
+	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
+		dev_warn(controller->dev, "cannot set RUN state\n");
+		goto exit;
+	}
+
+	if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
+		dev_warn(controller->dev, "cannot set PAUSE state\n");
+		goto exit;
+	}
+
+	spi_qup_fifo_write(controller, xfer);
+
+	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
+		dev_warn(controller->dev, "cannot set EXECUTE state\n");
+		goto exit;
+	}
+
+	if (!wait_for_completion_timeout(&controller->done, timeout))
+		ret = -ETIMEDOUT;
+exit:
+	spi_qup_set_state(controller, QUP_STATE_RESET);
+	spin_lock_irqsave(&controller->lock, flags);
+	controller->xfer = NULL;
+	if (!ret)
+		ret = controller->error;
+	spin_unlock_irqrestore(&controller->lock, flags);
+	return ret;
+}
+
+static int spi_qup_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct clk *iclk, *cclk;
+	struct spi_qup *controller;
+	struct resource *res;
+	struct device *dev;
+	void __iomem *base;
+	u32 data, max_freq, iomode;
+	int ret, irq, size;
+
+	dev = &pdev->dev;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	cclk = devm_clk_get(dev, "core");
+	if (IS_ERR(cclk))
+		return PTR_ERR(cclk);
+
+	iclk = devm_clk_get(dev, "iface");
+	if (IS_ERR(iclk))
+		return PTR_ERR(iclk);
+
+	/* This is optional parameter */
+	if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq))
+		max_freq = SPI_MAX_RATE;
+
+	if (!max_freq || max_freq > SPI_MAX_RATE) {
+		dev_err(dev, "invalid clock frequency %d\n", max_freq);
+		return -ENXIO;
+	}
+
+	ret = clk_prepare_enable(cclk);
+	if (ret) {
+		dev_err(dev, "cannot enable core clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(iclk);
+	if (ret) {
+		clk_disable_unprepare(cclk);
+		dev_err(dev, "cannot enable iface clock\n");
+		return ret;
+	}
+
+	data = readl_relaxed(base + QUP_HW_VERSION);
+
+	if (data < QUP_HW_VERSION_2_1_1) {
+		clk_disable_unprepare(cclk);
+		clk_disable_unprepare(iclk);
+		dev_err(dev, "v.%08x is not supported\n", data);
+		return -ENXIO;
+	}
+
+	master = spi_alloc_master(dev, sizeof(struct spi_qup));
+	if (!master) {
+		clk_disable_unprepare(cclk);
+		clk_disable_unprepare(iclk);
+		dev_err(dev, "cannot allocate master\n");
+		return -ENOMEM;
+	}
+
+	master->bus_num = pdev->id;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+	master->num_chipselect = SPI_NUM_CHIPSELECTS;
+	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+	master->max_speed_hz = max_freq;
+	master->set_cs = spi_qup_set_cs;
+	master->transfer_one = spi_qup_transfer_one;
+	master->dev.of_node = pdev->dev.of_node;
+	master->auto_runtime_pm = true;
+
+	platform_set_drvdata(pdev, master);
+
+	controller = spi_master_get_devdata(master);
+
+	controller->dev = dev;
+	controller->base = base;
+	controller->iclk = iclk;
+	controller->cclk = cclk;
+	controller->irq = irq;
+
+	spin_lock_init(&controller->lock);
+	init_completion(&controller->done);
+
+	iomode = readl_relaxed(base + QUP_IO_M_MODES);
+
+	size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode);
+	if (size)
+		controller->out_blk_sz = size * 16;
+	else
+		controller->out_blk_sz = 4;
+
+	size = QUP_IO_M_INPUT_BLOCK_SIZE(iomode);
+	if (size)
+		controller->in_blk_sz = size * 16;
+	else
+		controller->in_blk_sz = 4;
+
+	size = QUP_IO_M_OUTPUT_FIFO_SIZE(iomode);
+	controller->out_fifo_sz = controller->out_blk_sz * (2 << size);
+
+	size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
+	controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
+
+	dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
+		 data, controller->in_blk_sz, controller->in_fifo_sz,
+		 controller->out_blk_sz, controller->out_fifo_sz);
+
+	writel_relaxed(1, base + QUP_SW_RESET);
+
+	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
+	if (ret) {
+		dev_err(dev, "cannot set RESET state\n");
+		goto error;
+	}
+
+	writel_relaxed(0, base + QUP_OPERATIONAL);
+	writel_relaxed(0, base + QUP_IO_M_MODES);
+	writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
+	writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
+		       base + SPI_ERROR_FLAGS_EN);
+
+	writel_relaxed(0, base + SPI_CONFIG);
+	writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
+
+	ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
+			       IRQF_TRIGGER_HIGH, pdev->name, controller);
+	if (ret)
+		goto error;
+
+	ret = devm_spi_register_master(dev, master);
+	if (ret)
+		goto error;
+
+	pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	return 0;
+
+error:
+	clk_disable_unprepare(cclk);
+	clk_disable_unprepare(iclk);
+	spi_master_put(master);
+	return ret;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int spi_qup_pm_suspend_runtime(struct device *device)
+{
+	struct spi_master *master = dev_get_drvdata(device);
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	u32 config;
+
+	/* Enable clocks auto gaiting */
+	config = readl(controller->base + QUP_CONFIG);
+	config |= QUP_CONFIG_CLOCK_AUTO_GATE;
+	writel_relaxed(config, controller->base + QUP_CONFIG);
+	return 0;
+}
+
+static int spi_qup_pm_resume_runtime(struct device *device)
+{
+	struct spi_master *master = dev_get_drvdata(device);
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	u32 config;
+
+	/* Disable clocks auto gaiting */
+	config = readl_relaxed(controller->base + QUP_CONFIG);
+	config &= ~QUP_CONFIG_CLOCK_AUTO_GATE;
+	writel_relaxed(config, controller->base + QUP_CONFIG);
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+static int spi_qup_suspend(struct device *device)
+{
+	struct spi_master *master = dev_get_drvdata(device);
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	int ret;
+
+	ret = spi_master_suspend(master);
+	if (ret)
+		return ret;
+
+	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
+	if (ret)
+		return ret;
+
+	clk_disable_unprepare(controller->cclk);
+	clk_disable_unprepare(controller->iclk);
+	return 0;
+}
+
+static int spi_qup_resume(struct device *device)
+{
+	struct spi_master *master = dev_get_drvdata(device);
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(controller->iclk);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(controller->cclk);
+	if (ret)
+		return ret;
+
+	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
+	if (ret)
+		return ret;
+
+	return spi_master_resume(master);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int spi_qup_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = dev_get_drvdata(&pdev->dev);
+	struct spi_qup *controller = spi_master_get_devdata(master);
+	int ret;
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret)
+		return ret;
+
+	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
+	if (ret)
+		return ret;
+
+	clk_disable_unprepare(controller->cclk);
+	clk_disable_unprepare(controller->iclk);
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+
+static struct of_device_id spi_qup_dt_match[] = {
+	{ .compatible = "qcom,spi-qup-v2.1.1", },
+	{ .compatible = "qcom,spi-qup-v2.2.1", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, spi_qup_dt_match);
+
+static const struct dev_pm_ops spi_qup_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(spi_qup_suspend, spi_qup_resume)
+	SET_RUNTIME_PM_OPS(spi_qup_pm_suspend_runtime,
+			   spi_qup_pm_resume_runtime,
+			   NULL)
+};
+
+static struct platform_driver spi_qup_driver = {
+	.driver = {
+		.name		= "spi_qup",
+		.owner		= THIS_MODULE,
+		.pm		= &spi_qup_dev_pm_ops,
+		.of_match_table = spi_qup_dt_match,
+	},
+	.probe = spi_qup_probe,
+	.remove = spi_qup_remove,
+};
+module_platform_driver(spi_qup_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:spi_qup");
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 28987d9fcfe5..92bec7e91046 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -1,7 +1,8 @@
 /*
  * SH RSPI driver
  *
- * Copyright (C) 2012  Renesas Solutions Corp.
+ * Copyright (C) 2012, 2013  Renesas Solutions Corp.
+ * Copyright (C) 2014 Glider bvba
  *
  * Based on spi-sh.c:
  * Copyright (C) 2011 Renesas Solutions Corp.
@@ -25,14 +26,13 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_device.h>
 #include <linux/sh_dma.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/rspi.h>
@@ -49,7 +49,7 @@
 #define RSPI_SPCKD		0x0c	/* Clock Delay Register */
 #define RSPI_SSLND		0x0d	/* Slave Select Negation Delay Register */
 #define RSPI_SPND		0x0e	/* Next-Access Delay Register */
-#define RSPI_SPCR2		0x0f	/* Control Register 2 */
+#define RSPI_SPCR2		0x0f	/* Control Register 2 (SH only) */
 #define RSPI_SPCMD0		0x10	/* Command Register 0 */
 #define RSPI_SPCMD1		0x12	/* Command Register 1 */
 #define RSPI_SPCMD2		0x14	/* Command Register 2 */
@@ -58,16 +58,23 @@
 #define RSPI_SPCMD5		0x1a	/* Command Register 5 */
 #define RSPI_SPCMD6		0x1c	/* Command Register 6 */
 #define RSPI_SPCMD7		0x1e	/* Command Register 7 */
+#define RSPI_SPCMD(i)		(RSPI_SPCMD0 + (i) * 2)
+#define RSPI_NUM_SPCMD		8
+#define RSPI_RZ_NUM_SPCMD	4
+#define QSPI_NUM_SPCMD		4
+
+/* RSPI on RZ only */
 #define RSPI_SPBFCR		0x20	/* Buffer Control Register */
 #define RSPI_SPBFDR		0x22	/* Buffer Data Count Setting Register */
 
-/*qspi only */
+/* QSPI only */
 #define QSPI_SPBFCR		0x18	/* Buffer Control Register */
 #define QSPI_SPBDCR		0x1a	/* Buffer Data Count Register */
 #define QSPI_SPBMUL0		0x1c	/* Transfer Data Length Multiplier Setting Register 0 */
 #define QSPI_SPBMUL1		0x20	/* Transfer Data Length Multiplier Setting Register 1 */
 #define QSPI_SPBMUL2		0x24	/* Transfer Data Length Multiplier Setting Register 2 */
 #define QSPI_SPBMUL3		0x28	/* Transfer Data Length Multiplier Setting Register 3 */
+#define QSPI_SPBMUL(i)		(QSPI_SPBMUL0 + (i) * 4)
 
 /* SPCR - Control Register */
 #define SPCR_SPRIE		0x80	/* Receive Interrupt Enable */
@@ -104,7 +111,7 @@
 #define SPSR_PERF		0x08	/* Parity Error Flag */
 #define SPSR_MODF		0x04	/* Mode Fault Error Flag */
 #define SPSR_IDLNF		0x02	/* RSPI Idle Flag */
-#define SPSR_OVRF		0x01	/* Overrun Error Flag */
+#define SPSR_OVRF		0x01	/* Overrun Error Flag (RSPI only) */
 
 /* SPSCR - Sequence Control Register */
 #define SPSCR_SPSLN_MASK	0x07	/* Sequence Length Specification */
@@ -121,13 +128,13 @@
 #define SPDCR_SPLWORD		SPDCR_SPLW1
 #define SPDCR_SPLBYTE		SPDCR_SPLW0
 #define SPDCR_SPLW		0x20	/* Access Width Specification (SH) */
-#define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select */
+#define SPDCR_SPRDTD		0x10	/* Receive Transmit Data Select (SH) */
 #define SPDCR_SLSEL1		0x08
 #define SPDCR_SLSEL0		0x04
-#define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select */
+#define SPDCR_SLSEL_MASK	0x0c	/* SSL1 Output Select (SH) */
 #define SPDCR_SPFC1		0x02
 #define SPDCR_SPFC0		0x01
-#define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) */
+#define SPDCR_SPFC_MASK		0x03	/* Frame Count Setting (1-4) (SH) */
 
 /* SPCKD - Clock Delay Register */
 #define SPCKD_SCKDL_MASK	0x07	/* Clock Delay Setting (1-8) */
@@ -151,7 +158,7 @@
 #define SPCMD_LSBF		0x1000	/* LSB First */
 #define SPCMD_SPB_MASK		0x0f00	/* Data Length Setting */
 #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
-#define SPCMD_SPB_8BIT		0x0000	/* qspi only */
+#define SPCMD_SPB_8BIT		0x0000	/* QSPI only */
 #define SPCMD_SPB_16BIT		0x0100
 #define SPCMD_SPB_20BIT		0x0000
 #define SPCMD_SPB_24BIT		0x0100
@@ -170,8 +177,8 @@
 #define SPCMD_CPHA		0x0001	/* Clock Phase Setting */
 
 /* SPBFCR - Buffer Control Register */
-#define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset (qspi only) */
-#define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset (qspi only) */
+#define SPBFCR_TXRST		0x80	/* Transmit Buffer Data Reset */
+#define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset */
 #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
 #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
 
@@ -181,22 +188,21 @@ struct rspi_data {
 	void __iomem *addr;
 	u32 max_speed_hz;
 	struct spi_master *master;
-	struct list_head queue;
-	struct work_struct ws;
 	wait_queue_head_t wait;
-	spinlock_t lock;
 	struct clk *clk;
-	u8 spsr;
 	u16 spcmd;
+	u8 spsr;
+	u8 sppcr;
+	int rx_irq, tx_irq;
 	const struct spi_ops *ops;
 
 	/* for dmaengine */
 	struct dma_chan *chan_tx;
 	struct dma_chan *chan_rx;
-	int irq;
 
 	unsigned dma_width_16bit:1;
 	unsigned dma_callbacked:1;
+	unsigned byte_access:1;
 };
 
 static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
@@ -224,34 +230,47 @@ static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
 	return ioread16(rspi->addr + offset);
 }
 
+static void rspi_write_data(const struct rspi_data *rspi, u16 data)
+{
+	if (rspi->byte_access)
+		rspi_write8(rspi, data, RSPI_SPDR);
+	else /* 16 bit */
+		rspi_write16(rspi, data, RSPI_SPDR);
+}
+
+static u16 rspi_read_data(const struct rspi_data *rspi)
+{
+	if (rspi->byte_access)
+		return rspi_read8(rspi, RSPI_SPDR);
+	else /* 16 bit */
+		return rspi_read16(rspi, RSPI_SPDR);
+}
+
 /* optional functions */
 struct spi_ops {
-	int (*set_config_register)(const struct rspi_data *rspi,
-				   int access_size);
-	int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
-			struct spi_transfer *t);
-	int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
-			   struct spi_transfer *t);
-
+	int (*set_config_register)(struct rspi_data *rspi, int access_size);
+	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
+			    struct spi_transfer *xfer);
+	u16 mode_bits;
 };
 
 /*
- * functions for RSPI
+ * functions for RSPI on legacy SH
  */
-static int rspi_set_config_register(const struct rspi_data *rspi,
-				    int access_size)
+static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 {
 	int spbr;
 
-	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
-	rspi_write8(rspi, 0x00, RSPI_SPPCR);
+	/* Sets output mode, MOSI signal, and (optionally) loopback */
+	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
 	/* Sets transfer bit rate */
 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
-	/* Sets number of frames to be used: 1 frame */
-	rspi_write8(rspi, 0x00, RSPI_SPDCR);
+	/* Disable dummy transmission, set 16-bit word access, 1 frame */
+	rspi_write8(rspi, 0, RSPI_SPDCR);
+	rspi->byte_access = 0;
 
 	/* Sets RSPCK, SSL, next-access delay value */
 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
@@ -262,8 +281,41 @@ static int rspi_set_config_register(const struct rspi_data *rspi,
 	rspi_write8(rspi, 0x00, RSPI_SPCR2);
 
 	/* Sets SPCMD */
-	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
-		     RSPI_SPCMD0);
+	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
+	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
+
+	/* Sets RSPI mode */
+	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
+
+	return 0;
+}
+
+/*
+ * functions for RSPI on RZ
+ */
+static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
+{
+	int spbr;
+
+	/* Sets output mode, MOSI signal, and (optionally) loopback */
+	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
+
+	/* Sets transfer bit rate */
+	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
+	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+
+	/* Disable dummy transmission, set byte access */
+	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
+	rspi->byte_access = 1;
+
+	/* Sets RSPCK, SSL, next-access delay value */
+	rspi_write8(rspi, 0x00, RSPI_SPCKD);
+	rspi_write8(rspi, 0x00, RSPI_SSLND);
+	rspi_write8(rspi, 0x00, RSPI_SPND);
+
+	/* Sets SPCMD */
+	rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
+	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
 
 	/* Sets RSPI mode */
 	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
@@ -274,21 +326,20 @@ static int rspi_set_config_register(const struct rspi_data *rspi,
 /*
  * functions for QSPI
  */
-static int qspi_set_config_register(const struct rspi_data *rspi,
-				    int access_size)
+static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
 {
-	u16 spcmd;
 	int spbr;
 
-	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
-	rspi_write8(rspi, 0x00, RSPI_SPPCR);
+	/* Sets output mode, MOSI signal, and (optionally) loopback */
+	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
 	/* Sets transfer bit rate */
 	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
-	/* Sets number of frames to be used: 1 frame */
-	rspi_write8(rspi, 0x00, RSPI_SPDCR);
+	/* Disable dummy transmission, set byte access */
+	rspi_write8(rspi, 0, RSPI_SPDCR);
+	rspi->byte_access = 1;
 
 	/* Sets RSPCK, SSL, next-access delay value */
 	rspi_write8(rspi, 0x00, RSPI_SPCKD);
@@ -297,13 +348,13 @@ static int qspi_set_config_register(const struct rspi_data *rspi,
 
 	/* Data Length Setting */
 	if (access_size == 8)
-		spcmd = SPCMD_SPB_8BIT;
+		rspi->spcmd |= SPCMD_SPB_8BIT;
 	else if (access_size == 16)
-		spcmd = SPCMD_SPB_16BIT;
+		rspi->spcmd |= SPCMD_SPB_16BIT;
 	else
-		spcmd = SPCMD_SPB_32BIT;
+		rspi->spcmd |= SPCMD_SPB_32BIT;
 
-	spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
+	rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN;
 
 	/* Resets transfer data length */
 	rspi_write32(rspi, 0, QSPI_SPBMUL0);
@@ -314,9 +365,9 @@ static int qspi_set_config_register(const struct rspi_data *rspi,
 	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
 
 	/* Sets SPCMD */
-	rspi_write16(rspi, spcmd, RSPI_SPCMD0);
+	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
 
-	/* Enables SPI function in a master mode */
+	/* Enables SPI function in master mode */
 	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
 
 	return 0;
@@ -340,6 +391,9 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
 	int ret;
 
 	rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
+	if (rspi->spsr & wait_mask)
+		return 0;
+
 	rspi_enable_irq(rspi, enable_bit);
 	ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
 	if (ret == 0 && !(rspi->spsr & wait_mask))
@@ -348,78 +402,39 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
 	return 0;
 }
 
-static void rspi_assert_ssl(const struct rspi_data *rspi)
+static int rspi_data_out(struct rspi_data *rspi, u8 data)
 {
-	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
-}
-
-static void rspi_negate_ssl(const struct rspi_data *rspi)
-{
-	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
+	if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
+		dev_err(&rspi->master->dev, "transmit timeout\n");
+		return -ETIMEDOUT;
+	}
+	rspi_write_data(rspi, data);
+	return 0;
 }
 
-static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
-			 struct spi_transfer *t)
+static int rspi_data_in(struct rspi_data *rspi)
 {
-	int remain = t->len;
-	const u8 *data = t->tx_buf;
-	while (remain > 0) {
-		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
-			    RSPI_SPCR);
+	u8 data;
 
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: tx empty timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-
-		rspi_write16(rspi, *data, RSPI_SPDR);
-		data++;
-		remain--;
+	if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
+		dev_err(&rspi->master->dev, "receive timeout\n");
+		return -ETIMEDOUT;
 	}
-
-	/* Waiting for the last transmission */
-	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
-
-	return 0;
+	data = rspi_read_data(rspi);
+	return data;
 }
 
-static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
-			 struct spi_transfer *t)
+static int rspi_data_out_in(struct rspi_data *rspi, u8 data)
 {
-	int remain = t->len;
-	const u8 *data = t->tx_buf;
-
-	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
-	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
-
-	while (remain > 0) {
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: tx empty timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		rspi_write8(rspi, *data++, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		rspi_read8(rspi, RSPI_SPDR);
-
-		remain--;
-	}
+	int ret;
 
-	/* Waiting for the last transmission */
-	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+	ret = rspi_data_out(rspi, data);
+	if (ret < 0)
+		return ret;
 
-	return 0;
+	return rspi_data_in(rspi);
 }
 
-#define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t)
-
 static void rspi_dma_complete(void *arg)
 {
 	struct rspi_data *rspi = arg;
@@ -471,7 +486,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
 	struct scatterlist sg;
 	const void *buf = NULL;
 	struct dma_async_tx_descriptor *desc;
-	unsigned len;
+	unsigned int len;
 	int ret = 0;
 
 	if (rspi->dma_width_16bit) {
@@ -509,7 +524,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
 	 * called. So, this driver disables the IRQ while DMA transfer.
 	 */
-	disable_irq(rspi->irq);
+	disable_irq(rspi->tx_irq);
 
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
 	rspi_enable_irq(rspi, SPCR_SPTIE);
@@ -528,7 +543,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
 		ret = -ETIMEDOUT;
 	rspi_disable_irq(rspi, SPCR_SPTIE);
 
-	enable_irq(rspi->irq);
+	enable_irq(rspi->tx_irq);
 
 end:
 	rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
@@ -545,46 +560,17 @@ static void rspi_receive_init(const struct rspi_data *rspi)
 
 	spsr = rspi_read8(rspi, RSPI_SPSR);
 	if (spsr & SPSR_SPRF)
-		rspi_read16(rspi, RSPI_SPDR);	/* dummy read */
+		rspi_read_data(rspi);	/* dummy read */
 	if (spsr & SPSR_OVRF)
 		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
 			    RSPI_SPSR);
 }
 
-static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
-			    struct spi_transfer *t)
+static void rspi_rz_receive_init(const struct rspi_data *rspi)
 {
-	int remain = t->len;
-	u8 *data;
-
 	rspi_receive_init(rspi);
-
-	data = t->rx_buf;
-	while (remain > 0) {
-		rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
-			    RSPI_SPCR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: tx empty timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		/* dummy write for generate clock */
-		rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		/* SPDR allows 16 or 32-bit access only */
-		*data = (u8)rspi_read16(rspi, RSPI_SPDR);
-
-		data++;
-		remain--;
-	}
-
-	return 0;
+	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR);
+	rspi_write8(rspi, 0, RSPI_SPBFCR);
 }
 
 static void qspi_receive_init(const struct rspi_data *rspi)
@@ -593,51 +579,17 @@ static void qspi_receive_init(const struct rspi_data *rspi)
 
 	spsr = rspi_read8(rspi, RSPI_SPSR);
 	if (spsr & SPSR_SPRF)
-		rspi_read8(rspi, RSPI_SPDR);   /* dummy read */
+		rspi_read_data(rspi);   /* dummy read */
 	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
-	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+	rspi_write8(rspi, 0, QSPI_SPBFCR);
 }
 
-static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
-			    struct spi_transfer *t)
-{
-	int remain = t->len;
-	u8 *data;
-
-	qspi_receive_init(rspi);
-
-	data = t->rx_buf;
-	while (remain > 0) {
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: tx empty timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		/* dummy write for generate clock */
-		rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-		/* SPDR allows 8, 16 or 32-bit access */
-		*data++ = rspi_read8(rspi, RSPI_SPDR);
-		remain--;
-	}
-
-	return 0;
-}
-
-#define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t)
-
 static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
 {
 	struct scatterlist sg, sg_dummy;
 	void *dummy = NULL, *rx_buf = NULL;
 	struct dma_async_tx_descriptor *desc, *desc_dummy;
-	unsigned len;
+	unsigned int len;
 	int ret = 0;
 
 	if (rspi->dma_width_16bit) {
@@ -695,7 +647,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
 	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
 	 * called. So, this driver disables the IRQ while DMA transfer.
 	 */
-	disable_irq(rspi->irq);
+	disable_irq(rspi->tx_irq);
+	if (rspi->rx_irq != rspi->tx_irq)
+		disable_irq(rspi->rx_irq);
 
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
 	rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
@@ -718,7 +672,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
 		ret = -ETIMEDOUT;
 	rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
 
-	enable_irq(rspi->irq);
+	enable_irq(rspi->tx_irq);
+	if (rspi->rx_irq != rspi->tx_irq)
+		enable_irq(rspi->rx_irq);
 
 end:
 	rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
@@ -746,56 +702,175 @@ static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
 	return 0;
 }
 
-static void rspi_work(struct work_struct *work)
+static int rspi_transfer_out_in(struct rspi_data *rspi,
+				struct spi_transfer *xfer)
 {
-	struct rspi_data *rspi = container_of(work, struct rspi_data, ws);
-	struct spi_message *mesg;
-	struct spi_transfer *t;
-	unsigned long flags;
-	int ret;
+	int remain = xfer->len, ret;
+	const u8 *tx_buf = xfer->tx_buf;
+	u8 *rx_buf = xfer->rx_buf;
+	u8 spcr, data;
 
-	while (1) {
-		spin_lock_irqsave(&rspi->lock, flags);
-		if (list_empty(&rspi->queue)) {
-			spin_unlock_irqrestore(&rspi->lock, flags);
-			break;
-		}
-		mesg = list_entry(rspi->queue.next, struct spi_message, queue);
-		list_del_init(&mesg->queue);
-		spin_unlock_irqrestore(&rspi->lock, flags);
-
-		rspi_assert_ssl(rspi);
-
-		list_for_each_entry(t, &mesg->transfers, transfer_list) {
-			if (t->tx_buf) {
-				if (rspi_is_dma(rspi, t))
-					ret = rspi_send_dma(rspi, t);
-				else
-					ret = send_pio(rspi, mesg, t);
-				if (ret < 0)
-					goto error;
-			}
-			if (t->rx_buf) {
-				if (rspi_is_dma(rspi, t))
-					ret = rspi_receive_dma(rspi, t);
-				else
-					ret = receive_pio(rspi, mesg, t);
-				if (ret < 0)
-					goto error;
-			}
-			mesg->actual_length += t->len;
+	rspi_receive_init(rspi);
+
+	spcr = rspi_read8(rspi, RSPI_SPCR);
+	if (rx_buf)
+		spcr &= ~SPCR_TXMD;
+	else
+		spcr |= SPCR_TXMD;
+	rspi_write8(rspi, spcr, RSPI_SPCR);
+
+	while (remain > 0) {
+		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
+		ret = rspi_data_out(rspi, data);
+		if (ret < 0)
+			return ret;
+		if (rx_buf) {
+			ret = rspi_data_in(rspi);
+			if (ret < 0)
+				return ret;
+			*rx_buf++ = ret;
 		}
-		rspi_negate_ssl(rspi);
+		remain--;
+	}
+
+	/* Wait for the last transmission */
+	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+
+	return 0;
+}
+
+static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
+			     struct spi_transfer *xfer)
+{
+	struct rspi_data *rspi = spi_master_get_devdata(master);
+	int ret;
+
+	if (!rspi_is_dma(rspi, xfer))
+		return rspi_transfer_out_in(rspi, xfer);
+
+	if (xfer->tx_buf) {
+		ret = rspi_send_dma(rspi, xfer);
+		if (ret < 0)
+			return ret;
+	}
+	if (xfer->rx_buf)
+		return rspi_receive_dma(rspi, xfer);
+
+	return 0;
+}
+
+static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
+				   struct spi_transfer *xfer)
+{
+	int remain = xfer->len, ret;
+	const u8 *tx_buf = xfer->tx_buf;
+	u8 *rx_buf = xfer->rx_buf;
+	u8 data;
+
+	rspi_rz_receive_init(rspi);
+
+	while (remain > 0) {
+		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
+		ret = rspi_data_out_in(rspi, data);
+		if (ret < 0)
+			return ret;
+		if (rx_buf)
+			*rx_buf++ = ret;
+		remain--;
+	}
+
+	/* Wait for the last transmission */
+	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+
+	return 0;
+}
+
+static int rspi_rz_transfer_one(struct spi_master *master,
+				struct spi_device *spi,
+				struct spi_transfer *xfer)
+{
+	struct rspi_data *rspi = spi_master_get_devdata(master);
+
+	return rspi_rz_transfer_out_in(rspi, xfer);
+}
+
+static int qspi_transfer_out_in(struct rspi_data *rspi,
+				struct spi_transfer *xfer)
+{
+	int remain = xfer->len, ret;
+	const u8 *tx_buf = xfer->tx_buf;
+	u8 *rx_buf = xfer->rx_buf;
+	u8 data;
+
+	qspi_receive_init(rspi);
 
-		mesg->status = 0;
-		mesg->complete(mesg->context);
+	while (remain > 0) {
+		data = tx_buf ? *tx_buf++ : DUMMY_DATA;
+		ret = rspi_data_out_in(rspi, data);
+		if (ret < 0)
+			return ret;
+		if (rx_buf)
+			*rx_buf++ = ret;
+		remain--;
+	}
+
+	/* Wait for the last transmission */
+	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+
+	return 0;
+}
+
+static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
+{
+	const u8 *buf = xfer->tx_buf;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < xfer->len; i++) {
+		ret = rspi_data_out(rspi, *buf++);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Wait for the last transmission */
+	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+
+	return 0;
+}
+
+static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
+{
+	u8 *buf = xfer->rx_buf;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < xfer->len; i++) {
+		ret = rspi_data_in(rspi);
+		if (ret < 0)
+			return ret;
+		*buf++ = ret;
 	}
 
-	return;
+	return 0;
+}
 
-error:
-	mesg->status = ret;
-	mesg->complete(mesg->context);
+static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
+			     struct spi_transfer *xfer)
+{
+	struct rspi_data *rspi = spi_master_get_devdata(master);
+
+	if (spi->mode & SPI_LOOP) {
+		return qspi_transfer_out_in(rspi, xfer);
+	} else if (xfer->tx_buf && xfer->tx_nbits > SPI_NBITS_SINGLE) {
+		/* Quad or Dual SPI Write */
+		return qspi_transfer_out(rspi, xfer);
+	} else if (xfer->rx_buf && xfer->rx_nbits > SPI_NBITS_SINGLE) {
+		/* Quad or Dual SPI Read */
+		return qspi_transfer_in(rspi, xfer);
+	} else {
+		/* Single SPI Transfer */
+		return qspi_transfer_out_in(rspi, xfer);
+	}
 }
 
 static int rspi_setup(struct spi_device *spi)
@@ -810,32 +885,115 @@ static int rspi_setup(struct spi_device *spi)
 	if (spi->mode & SPI_CPHA)
 		rspi->spcmd |= SPCMD_CPHA;
 
+	/* CMOS output mode and MOSI signal from previous transfer */
+	rspi->sppcr = 0;
+	if (spi->mode & SPI_LOOP)
+		rspi->sppcr |= SPPCR_SPLP;
+
 	set_config_register(rspi, 8);
 
 	return 0;
 }
 
-static int rspi_transfer(struct spi_device *spi, struct spi_message *mesg)
+static u16 qspi_transfer_mode(const struct spi_transfer *xfer)
 {
-	struct rspi_data *rspi = spi_master_get_devdata(spi->master);
-	unsigned long flags;
+	if (xfer->tx_buf)
+		switch (xfer->tx_nbits) {
+		case SPI_NBITS_QUAD:
+			return SPCMD_SPIMOD_QUAD;
+		case SPI_NBITS_DUAL:
+			return SPCMD_SPIMOD_DUAL;
+		default:
+			return 0;
+		}
+	if (xfer->rx_buf)
+		switch (xfer->rx_nbits) {
+		case SPI_NBITS_QUAD:
+			return SPCMD_SPIMOD_QUAD | SPCMD_SPRW;
+		case SPI_NBITS_DUAL:
+			return SPCMD_SPIMOD_DUAL | SPCMD_SPRW;
+		default:
+			return 0;
+		}
 
-	mesg->actual_length = 0;
-	mesg->status = -EINPROGRESS;
+	return 0;
+}
 
-	spin_lock_irqsave(&rspi->lock, flags);
-	list_add_tail(&mesg->queue, &rspi->queue);
-	schedule_work(&rspi->ws);
-	spin_unlock_irqrestore(&rspi->lock, flags);
+static int qspi_setup_sequencer(struct rspi_data *rspi,
+				const struct spi_message *msg)
+{
+	const struct spi_transfer *xfer;
+	unsigned int i = 0, len = 0;
+	u16 current_mode = 0xffff, mode;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		mode = qspi_transfer_mode(xfer);
+		if (mode == current_mode) {
+			len += xfer->len;
+			continue;
+		}
+
+		/* Transfer mode change */
+		if (i) {
+			/* Set transfer data length of previous transfer */
+			rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
+		}
+
+		if (i >= QSPI_NUM_SPCMD) {
+			dev_err(&msg->spi->dev,
+				"Too many different transfer modes");
+			return -EINVAL;
+		}
+
+		/* Program transfer mode for this transfer */
+		rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i));
+		current_mode = mode;
+		len = xfer->len;
+		i++;
+	}
+	if (i) {
+		/* Set final transfer data length and sequence length */
+		rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
+		rspi_write8(rspi, i - 1, RSPI_SPSCR);
+	}
 
 	return 0;
 }
 
-static void rspi_cleanup(struct spi_device *spi)
+static int rspi_prepare_message(struct spi_master *master,
+				struct spi_message *msg)
 {
+	struct rspi_data *rspi = spi_master_get_devdata(master);
+	int ret;
+
+	if (msg->spi->mode &
+	    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
+		/* Setup sequencer for messages with multiple transfer modes */
+		ret = qspi_setup_sequencer(rspi, msg);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Enable SPI function in master mode */
+	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
+	return 0;
 }
 
-static irqreturn_t rspi_irq(int irq, void *_sr)
+static int rspi_unprepare_message(struct spi_master *master,
+				  struct spi_message *msg)
+{
+	struct rspi_data *rspi = spi_master_get_devdata(master);
+
+	/* Disable SPI function */
+	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
+
+	/* Reset sequencer for Single SPI Transfers */
+	rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
+	rspi_write8(rspi, 0, RSPI_SPSCR);
+	return 0;
+}
+
+static irqreturn_t rspi_irq_mux(int irq, void *_sr)
 {
 	struct rspi_data *rspi = _sr;
 	u8 spsr;
@@ -857,6 +1015,36 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 	return ret;
 }
 
+static irqreturn_t rspi_irq_rx(int irq, void *_sr)
+{
+	struct rspi_data *rspi = _sr;
+	u8 spsr;
+
+	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
+	if (spsr & SPSR_SPRF) {
+		rspi_disable_irq(rspi, SPCR_SPRIE);
+		wake_up(&rspi->wait);
+		return IRQ_HANDLED;
+	}
+
+	return 0;
+}
+
+static irqreturn_t rspi_irq_tx(int irq, void *_sr)
+{
+	struct rspi_data *rspi = _sr;
+	u8 spsr;
+
+	rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
+	if (spsr & SPSR_SPTEF) {
+		rspi_disable_irq(rspi, SPCR_SPTIE);
+		wake_up(&rspi->wait);
+		return IRQ_HANDLED;
+	}
+
+	return 0;
+}
+
 static int rspi_request_dma(struct rspi_data *rspi,
 				      struct platform_device *pdev)
 {
@@ -923,34 +1111,89 @@ static int rspi_remove(struct platform_device *pdev)
 	struct rspi_data *rspi = platform_get_drvdata(pdev);
 
 	rspi_release_dma(rspi);
-	clk_disable(rspi->clk);
+	clk_disable_unprepare(rspi->clk);
 
 	return 0;
 }
 
+static const struct spi_ops rspi_ops = {
+	.set_config_register =		rspi_set_config_register,
+	.transfer_one =			rspi_transfer_one,
+	.mode_bits =			SPI_CPHA | SPI_CPOL | SPI_LOOP,
+};
+
+static const struct spi_ops rspi_rz_ops = {
+	.set_config_register =		rspi_rz_set_config_register,
+	.transfer_one =			rspi_rz_transfer_one,
+	.mode_bits =			SPI_CPHA | SPI_CPOL | SPI_LOOP,
+};
+
+static const struct spi_ops qspi_ops = {
+	.set_config_register =		qspi_set_config_register,
+	.transfer_one =			qspi_transfer_one,
+	.mode_bits =			SPI_CPHA | SPI_CPOL | SPI_LOOP |
+					SPI_TX_DUAL | SPI_TX_QUAD |
+					SPI_RX_DUAL | SPI_RX_QUAD,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id rspi_of_match[] = {
+	/* RSPI on legacy SH */
+	{ .compatible = "renesas,rspi", .data = &rspi_ops },
+	/* RSPI on RZ/A1H */
+	{ .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops },
+	/* QSPI on R-Car Gen2 */
+	{ .compatible = "renesas,qspi", .data = &qspi_ops },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, rspi_of_match);
+
+static int rspi_parse_dt(struct device *dev, struct spi_master *master)
+{
+	u32 num_cs;
+	int error;
+
+	/* Parse DT properties */
+	error = of_property_read_u32(dev->of_node, "num-cs", &num_cs);
+	if (error) {
+		dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error);
+		return error;
+	}
+
+	master->num_chipselect = num_cs;
+	return 0;
+}
+#else
+#define rspi_of_match	NULL
+static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_OF */
+
+static int rspi_request_irq(struct device *dev, unsigned int irq,
+			    irq_handler_t handler, const char *suffix,
+			    void *dev_id)
+{
+	const char *base = dev_name(dev);
+	size_t len = strlen(base) + strlen(suffix) + 2;
+	char *name = devm_kzalloc(dev, len, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+	snprintf(name, len, "%s:%s", base, suffix);
+	return devm_request_irq(dev, irq, handler, 0, name, dev_id);
+}
+
 static int rspi_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct spi_master *master;
 	struct rspi_data *rspi;
-	int ret, irq;
-	char clk_name[16];
-	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+	int ret;
+	const struct of_device_id *of_id;
+	const struct rspi_plat_data *rspi_pd;
 	const struct spi_ops *ops;
-	const struct platform_device_id *id_entry = pdev->id_entry;
-
-	ops = (struct spi_ops *)id_entry->driver_data;
-	/* ops parameter check */
-	if (!ops->set_config_register) {
-		dev_err(&pdev->dev, "there is no set_config_register\n");
-		return -ENODEV;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "platform_get_irq error\n");
-		return -ENODEV;
-	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
 	if (master == NULL) {
@@ -958,6 +1201,28 @@ static int rspi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	of_id = of_match_device(rspi_of_match, &pdev->dev);
+	if (of_id) {
+		ops = of_id->data;
+		ret = rspi_parse_dt(&pdev->dev, master);
+		if (ret)
+			goto error1;
+	} else {
+		ops = (struct spi_ops *)pdev->id_entry->driver_data;
+		rspi_pd = dev_get_platdata(&pdev->dev);
+		if (rspi_pd && rspi_pd->num_chipselect)
+			master->num_chipselect = rspi_pd->num_chipselect;
+		else
+			master->num_chipselect = 2; /* default */
+	};
+
+	/* ops parameter check */
+	if (!ops->set_config_register) {
+		dev_err(&pdev->dev, "there is no set_config_register\n");
+		ret = -ENODEV;
+		goto error1;
+	}
+
 	rspi = spi_master_get_devdata(master);
 	platform_set_drvdata(pdev, rspi);
 	rspi->ops = ops;
@@ -970,39 +1235,64 @@ static int rspi_probe(struct platform_device *pdev)
 		goto error1;
 	}
 
-	snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
-	rspi->clk = devm_clk_get(&pdev->dev, clk_name);
+	rspi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(rspi->clk)) {
 		dev_err(&pdev->dev, "cannot get clock\n");
 		ret = PTR_ERR(rspi->clk);
 		goto error1;
 	}
-	clk_enable(rspi->clk);
 
-	INIT_LIST_HEAD(&rspi->queue);
-	spin_lock_init(&rspi->lock);
-	INIT_WORK(&rspi->ws, rspi_work);
-	init_waitqueue_head(&rspi->wait);
+	ret = clk_prepare_enable(rspi->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to prepare/enable clock\n");
+		goto error1;
+	}
 
-	if (rspi_pd && rspi_pd->num_chipselect)
-		master->num_chipselect = rspi_pd->num_chipselect;
-	else
-		master->num_chipselect = 2; /* default */
+	init_waitqueue_head(&rspi->wait);
 
 	master->bus_num = pdev->id;
 	master->setup = rspi_setup;
-	master->transfer = rspi_transfer;
-	master->cleanup = rspi_cleanup;
-	master->mode_bits = SPI_CPHA | SPI_CPOL;
+	master->transfer_one = ops->transfer_one;
+	master->prepare_message = rspi_prepare_message;
+	master->unprepare_message = rspi_unprepare_message;
+	master->mode_bits = ops->mode_bits;
+	master->dev.of_node = pdev->dev.of_node;
 
-	ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
-			       dev_name(&pdev->dev), rspi);
+	ret = platform_get_irq_byname(pdev, "rx");
+	if (ret < 0) {
+		ret = platform_get_irq_byname(pdev, "mux");
+		if (ret < 0)
+			ret = platform_get_irq(pdev, 0);
+		if (ret >= 0)
+			rspi->rx_irq = rspi->tx_irq = ret;
+	} else {
+		rspi->rx_irq = ret;
+		ret = platform_get_irq_byname(pdev, "tx");
+		if (ret >= 0)
+			rspi->tx_irq = ret;
+	}
+	if (ret < 0) {
+		dev_err(&pdev->dev, "platform_get_irq error\n");
+		goto error2;
+	}
+
+	if (rspi->rx_irq == rspi->tx_irq) {
+		/* Single multiplexed interrupt */
+		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
+				       "mux", rspi);
+	} else {
+		/* Multi-interrupt mode, only SPRI and SPTI are used */
+		ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
+				       "rx", rspi);
+		if (!ret)
+			ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
+					       rspi_irq_tx, "tx", rspi);
+	}
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request_irq error\n");
 		goto error2;
 	}
 
-	rspi->irq = irq;
 	ret = rspi_request_dma(rspi, pdev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "rspi_request_dma failed.\n");
@@ -1022,27 +1312,16 @@ static int rspi_probe(struct platform_device *pdev)
 error3:
 	rspi_release_dma(rspi);
 error2:
-	clk_disable(rspi->clk);
+	clk_disable_unprepare(rspi->clk);
 error1:
 	spi_master_put(master);
 
 	return ret;
 }
 
-static struct spi_ops rspi_ops = {
-	.set_config_register =		rspi_set_config_register,
-	.send_pio =			rspi_send_pio,
-	.receive_pio =			rspi_receive_pio,
-};
-
-static struct spi_ops qspi_ops = {
-	.set_config_register =		qspi_set_config_register,
-	.send_pio =			qspi_send_pio,
-	.receive_pio =			qspi_receive_pio,
-};
-
 static struct platform_device_id spi_driver_ids[] = {
 	{ "rspi",	(kernel_ulong_t)&rspi_ops },
+	{ "rspi-rz",	(kernel_ulong_t)&rspi_rz_ops },
 	{ "qspi",	(kernel_ulong_t)&qspi_ops },
 	{},
 };
@@ -1056,6 +1335,7 @@ static struct platform_driver rspi_driver = {
 	.driver		= {
 		.name = "renesas_spi",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(rspi_of_match),
 	},
 };
 module_platform_driver(rspi_driver);
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 746424aa5353..a275445790a6 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -9,7 +9,6 @@
  *
 */
 
-#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
@@ -123,25 +122,15 @@ static int s3c24xx_spi_update_state(struct spi_device *spi,
 {
 	struct s3c24xx_spi *hw = to_hw(spi);
 	struct s3c24xx_spi_devstate *cs = spi->controller_state;
-	unsigned int bpw;
 	unsigned int hz;
 	unsigned int div;
 	unsigned long clk;
 
-	bpw = t ? t->bits_per_word : spi->bits_per_word;
 	hz  = t ? t->speed_hz : spi->max_speed_hz;
 
-	if (!bpw)
-		bpw = 8;
-
 	if (!hz)
 		hz = spi->max_speed_hz;
 
-	if (bpw != 8) {
-		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
-		return -EINVAL;
-	}
-
 	if (spi->mode != cs->mode) {
 		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
 
@@ -544,6 +533,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
 
 	master->num_chipselect = hw->pdata->num_cs;
 	master->bus_num = pdata->bus_num;
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
 
 	/* setup the state for the bitbang driver */
 
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index ae907dde1371..f19cd97855e8 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -34,10 +34,6 @@
 
 #include <linux/platform_data/spi-s3c64xx.h>
 
-#ifdef CONFIG_S3C_DMA
-#include <mach/dma.h>
-#endif
-
 #define MAX_SPI_PORTS		3
 #define S3C64XX_SPI_QUIRK_POLL		(1 << 0)
 
@@ -200,9 +196,6 @@ struct s3c64xx_spi_driver_data {
 	unsigned                        cur_speed;
 	struct s3c64xx_spi_dma_data	rx_dma;
 	struct s3c64xx_spi_dma_data	tx_dma;
-#ifdef CONFIG_S3C_DMA
-	struct samsung_dma_ops		*ops;
-#endif
 	struct s3c64xx_spi_port_config	*port_conf;
 	unsigned int			port_id;
 	bool				cs_gpio;
@@ -284,104 +277,8 @@ static void s3c64xx_spi_dmacb(void *data)
 	spin_unlock_irqrestore(&sdd->lock, flags);
 }
 
-#ifdef CONFIG_S3C_DMA
-/* FIXME: remove this section once arch/arm/mach-s3c64xx uses dmaengine */
-
-static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
-	.name = "samsung-spi-dma",
-};
-
-static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
-					unsigned len, dma_addr_t buf)
-{
-	struct s3c64xx_spi_driver_data *sdd;
-	struct samsung_dma_prep info;
-	struct samsung_dma_config config;
-
-	if (dma->direction == DMA_DEV_TO_MEM) {
-		sdd = container_of((void *)dma,
-			struct s3c64xx_spi_driver_data, rx_dma);
-		config.direction = sdd->rx_dma.direction;
-		config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
-		config.width = sdd->cur_bpw / 8;
-		sdd->ops->config((enum dma_ch)sdd->rx_dma.ch, &config);
-	} else {
-		sdd = container_of((void *)dma,
-			struct s3c64xx_spi_driver_data, tx_dma);
-		config.direction =  sdd->tx_dma.direction;
-		config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-		config.width = sdd->cur_bpw / 8;
-		sdd->ops->config((enum dma_ch)sdd->tx_dma.ch, &config);
-	}
-
-	info.cap = DMA_SLAVE;
-	info.len = len;
-	info.fp = s3c64xx_spi_dmacb;
-	info.fp_param = dma;
-	info.direction = dma->direction;
-	info.buf = buf;
-
-	sdd->ops->prepare((enum dma_ch)dma->ch, &info);
-	sdd->ops->trigger((enum dma_ch)dma->ch);
-}
-
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-	struct samsung_dma_req req;
-	struct device *dev = &sdd->pdev->dev;
-
-	sdd->ops = samsung_dma_get_ops();
-
-	req.cap = DMA_SLAVE;
-	req.client = &s3c64xx_spi_dma_client;
-
-	sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
-					sdd->rx_dma.dmach, &req, dev, "rx");
-	sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
-					sdd->tx_dma.dmach, &req, dev, "tx");
-
-	return 1;
-}
-
-static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
-{
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
-	/*
-	 * If DMA resource was not available during
-	 * probe, no need to continue with dma requests
-	 * else Acquire DMA channels
-	 */
-	while (!is_polling(sdd) && !acquire_dma(sdd))
-		usleep_range(10000, 11000);
-
-	return 0;
-}
-
-static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
-{
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
-	/* Free DMA channels */
-	if (!is_polling(sdd)) {
-		sdd->ops->release((enum dma_ch)sdd->rx_dma.ch,
-					&s3c64xx_spi_dma_client);
-		sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
-					&s3c64xx_spi_dma_client);
-	}
-
-	return 0;
-}
-
-static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd,
-				 struct s3c64xx_spi_dma_data *dma)
-{
-	sdd->ops->stop((enum dma_ch)dma->ch);
-}
-#else
-
 static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
-					unsigned len, dma_addr_t buf)
+			struct sg_table *sgt)
 {
 	struct s3c64xx_spi_driver_data *sdd;
 	struct dma_slave_config config;
@@ -407,8 +304,8 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
 		dmaengine_slave_config(dma->ch, &config);
 	}
 
-	desc = dmaengine_prep_slave_single(dma->ch, buf, len,
-					dma->direction, DMA_PREP_INTERRUPT);
+	desc = dmaengine_prep_slave_sg(dma->ch, sgt->sgl, sgt->nents,
+				       dma->direction, DMA_PREP_INTERRUPT);
 
 	desc->callback = s3c64xx_spi_dmacb;
 	desc->callback_param = dma;
@@ -437,6 +334,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 			ret = -EBUSY;
 			goto out;
 		}
+		spi->dma_rx = sdd->rx_dma.ch;
 
 		sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
 				   (void *)sdd->tx_dma.dmach, dev, "tx");
@@ -445,6 +343,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 			ret = -EBUSY;
 			goto out_rx;
 		}
+		spi->dma_tx = sdd->tx_dma.ch;
 	}
 
 	ret = pm_runtime_get_sync(&sdd->pdev->dev);
@@ -477,12 +376,14 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
 	return 0;
 }
 
-static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd,
-				 struct s3c64xx_spi_dma_data *dma)
+static bool s3c64xx_spi_can_dma(struct spi_master *master,
+				struct spi_device *spi,
+				struct spi_transfer *xfer)
 {
-	dmaengine_terminate_all(dma->ch);
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+
+	return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1;
 }
-#endif
 
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 				struct spi_device *spi,
@@ -515,7 +416,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
 		if (dma_mode) {
 			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-			prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
+			prepare_dma(&sdd->tx_dma, &xfer->tx_sg);
 		} else {
 			switch (sdd->cur_bpw) {
 			case 32:
@@ -547,7 +448,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
 					| S3C64XX_SPI_PACKET_CNT_EN,
 					regs + S3C64XX_SPI_PACKET_CNT);
-			prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
+			prepare_dma(&sdd->rx_dma, &xfer->rx_sg);
 		}
 	}
 
@@ -555,23 +456,6 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 	writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
 }
 
-static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_device *spi)
-{
-	if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
-		if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
-			/* Deselect the last toggled device */
-			if (spi->cs_gpio >= 0)
-				gpio_set_value(spi->cs_gpio,
-					spi->mode & SPI_CS_HIGH ? 0 : 1);
-		}
-		sdd->tgl_spi = NULL;
-	}
-
-	if (spi->cs_gpio >= 0)
-		gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0);
-}
-
 static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd,
 					int timeout_ms)
 {
@@ -593,112 +477,111 @@ static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd,
 	return RX_FIFO_LVL(status, sdd);
 }
 
-static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
-				struct spi_transfer *xfer, int dma_mode)
+static int wait_for_dma(struct s3c64xx_spi_driver_data *sdd,
+			struct spi_transfer *xfer)
 {
 	void __iomem *regs = sdd->regs;
 	unsigned long val;
+	u32 status;
 	int ms;
 
 	/* millisecs to xfer 'len' bytes @ 'cur_speed' */
 	ms = xfer->len * 8 * 1000 / sdd->cur_speed;
 	ms += 10; /* some tolerance */
 
-	if (dma_mode) {
-		val = msecs_to_jiffies(ms) + 10;
-		val = wait_for_completion_timeout(&sdd->xfer_completion, val);
-	} else {
-		u32 status;
-		val = msecs_to_loops(ms);
-		do {
+	val = msecs_to_jiffies(ms) + 10;
+	val = wait_for_completion_timeout(&sdd->xfer_completion, val);
+
+	/*
+	 * If the previous xfer was completed within timeout, then
+	 * proceed further else return -EIO.
+	 * DmaTx returns after simply writing data in the FIFO,
+	 * w/o waiting for real transmission on the bus to finish.
+	 * DmaRx returns only after Dma read data from FIFO which
+	 * needs bus transmission to finish, so we don't worry if
+	 * Xfer involved Rx(with or without Tx).
+	 */
+	if (val && !xfer->rx_buf) {
+		val = msecs_to_loops(10);
+		status = readl(regs + S3C64XX_SPI_STATUS);
+		while ((TX_FIFO_LVL(status, sdd)
+			|| !S3C64XX_SPI_ST_TX_DONE(status, sdd))
+		       && --val) {
+			cpu_relax();
 			status = readl(regs + S3C64XX_SPI_STATUS);
-		} while (RX_FIFO_LVL(status, sdd) < xfer->len && --val);
+		}
+
 	}
 
-	if (dma_mode) {
-		u32 status;
-
-		/*
-		 * If the previous xfer was completed within timeout, then
-		 * proceed further else return -EIO.
-		 * DmaTx returns after simply writing data in the FIFO,
-		 * w/o waiting for real transmission on the bus to finish.
-		 * DmaRx returns only after Dma read data from FIFO which
-		 * needs bus transmission to finish, so we don't worry if
-		 * Xfer involved Rx(with or without Tx).
-		 */
-		if (val && !xfer->rx_buf) {
-			val = msecs_to_loops(10);
-			status = readl(regs + S3C64XX_SPI_STATUS);
-			while ((TX_FIFO_LVL(status, sdd)
-				|| !S3C64XX_SPI_ST_TX_DONE(status, sdd))
-					&& --val) {
-				cpu_relax();
-				status = readl(regs + S3C64XX_SPI_STATUS);
-			}
+	/* If timed out while checking rx/tx status return error */
+	if (!val)
+		return -EIO;
 
-		}
+	return 0;
+}
 
-		/* If timed out while checking rx/tx status return error */
-		if (!val)
-			return -EIO;
-	} else {
-		int loops;
-		u32 cpy_len;
-		u8 *buf;
-
-		/* If it was only Tx */
-		if (!xfer->rx_buf) {
-			sdd->state &= ~TXBUSY;
-			return 0;
-		}
+static int wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
+			struct spi_transfer *xfer)
+{
+	void __iomem *regs = sdd->regs;
+	unsigned long val;
+	u32 status;
+	int loops;
+	u32 cpy_len;
+	u8 *buf;
+	int ms;
 
-		/*
-		 * If the receive length is bigger than the controller fifo
-		 * size, calculate the loops and read the fifo as many times.
-		 * loops = length / max fifo size (calculated by using the
-		 * fifo mask).
-		 * For any size less than the fifo size the below code is
-		 * executed atleast once.
-		 */
-		loops = xfer->len / ((FIFO_LVL_MASK(sdd) >> 1) + 1);
-		buf = xfer->rx_buf;
-		do {
-			/* wait for data to be received in the fifo */
-			cpy_len = s3c64xx_spi_wait_for_timeout(sdd,
-						(loops ? ms : 0));
+	/* millisecs to xfer 'len' bytes @ 'cur_speed' */
+	ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+	ms += 10; /* some tolerance */
 
-			switch (sdd->cur_bpw) {
-			case 32:
-				ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
-					buf, cpy_len / 4);
-				break;
-			case 16:
-				ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
-					buf, cpy_len / 2);
-				break;
-			default:
-				ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
-					buf, cpy_len);
-				break;
-			}
+	val = msecs_to_loops(ms);
+	do {
+		status = readl(regs + S3C64XX_SPI_STATUS);
+	} while (RX_FIFO_LVL(status, sdd) < xfer->len && --val);
 
-			buf = buf + cpy_len;
-		} while (loops--);
-		sdd->state &= ~RXBUSY;
+
+	/* If it was only Tx */
+	if (!xfer->rx_buf) {
+		sdd->state &= ~TXBUSY;
+		return 0;
 	}
 
-	return 0;
-}
+	/*
+	 * If the receive length is bigger than the controller fifo
+	 * size, calculate the loops and read the fifo as many times.
+	 * loops = length / max fifo size (calculated by using the
+	 * fifo mask).
+	 * For any size less than the fifo size the below code is
+	 * executed atleast once.
+	 */
+	loops = xfer->len / ((FIFO_LVL_MASK(sdd) >> 1) + 1);
+	buf = xfer->rx_buf;
+	do {
+		/* wait for data to be received in the fifo */
+		cpy_len = s3c64xx_spi_wait_for_timeout(sdd,
+						       (loops ? ms : 0));
+
+		switch (sdd->cur_bpw) {
+		case 32:
+			ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
+				     buf, cpy_len / 4);
+			break;
+		case 16:
+			ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
+				     buf, cpy_len / 2);
+			break;
+		default:
+			ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
+				    buf, cpy_len);
+			break;
+		}
 
-static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_device *spi)
-{
-	if (sdd->tgl_spi == spi)
-		sdd->tgl_spi = NULL;
+		buf = buf + cpy_len;
+	} while (loops--);
+	sdd->state &= ~RXBUSY;
 
-	if (spi->cs_gpio >= 0)
-		gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+	return 0;
 }
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
@@ -774,81 +657,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
-static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_message *msg)
-{
-	struct device *dev = &sdd->pdev->dev;
-	struct spi_transfer *xfer;
-
-	if (is_polling(sdd) || msg->is_dma_mapped)
-		return 0;
-
-	/* First mark all xfer unmapped */
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		xfer->rx_dma = XFER_DMAADDR_INVALID;
-		xfer->tx_dma = XFER_DMAADDR_INVALID;
-	}
-
-	/* Map until end or first fail */
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-		if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
-			continue;
-
-		if (xfer->tx_buf != NULL) {
-			xfer->tx_dma = dma_map_single(dev,
-					(void *)xfer->tx_buf, xfer->len,
-					DMA_TO_DEVICE);
-			if (dma_mapping_error(dev, xfer->tx_dma)) {
-				dev_err(dev, "dma_map_single Tx failed\n");
-				xfer->tx_dma = XFER_DMAADDR_INVALID;
-				return -ENOMEM;
-			}
-		}
-
-		if (xfer->rx_buf != NULL) {
-			xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
-						xfer->len, DMA_FROM_DEVICE);
-			if (dma_mapping_error(dev, xfer->rx_dma)) {
-				dev_err(dev, "dma_map_single Rx failed\n");
-				dma_unmap_single(dev, xfer->tx_dma,
-						xfer->len, DMA_TO_DEVICE);
-				xfer->tx_dma = XFER_DMAADDR_INVALID;
-				xfer->rx_dma = XFER_DMAADDR_INVALID;
-				return -ENOMEM;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_message *msg)
-{
-	struct device *dev = &sdd->pdev->dev;
-	struct spi_transfer *xfer;
-
-	if (is_polling(sdd) || msg->is_dma_mapped)
-		return;
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-		if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
-			continue;
-
-		if (xfer->rx_buf != NULL
-				&& xfer->rx_dma != XFER_DMAADDR_INVALID)
-			dma_unmap_single(dev, xfer->rx_dma,
-						xfer->len, DMA_FROM_DEVICE);
-
-		if (xfer->tx_buf != NULL
-				&& xfer->tx_dma != XFER_DMAADDR_INVALID)
-			dma_unmap_single(dev, xfer->tx_dma,
-						xfer->len, DMA_TO_DEVICE);
-	}
-}
-
 static int s3c64xx_spi_prepare_message(struct spi_master *master,
 				       struct spi_message *msg)
 {
@@ -866,13 +674,6 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
 		s3c64xx_spi_config(sdd);
 	}
 
-	/* Map all the transfers if needed */
-	if (s3c64xx_spi_map_mssg(sdd, msg)) {
-		dev_err(&spi->dev,
-			"Xfer: Unable to map message buffers!\n");
-		return -ENOMEM;
-	}
-
 	/* Configure feedback delay */
 	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
 
@@ -896,13 +697,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
 	bpw = xfer->bits_per_word;
 	speed = xfer->speed_hz ? : spi->max_speed_hz;
 
-	if (xfer->len % (bpw / 8)) {
-		dev_err(&spi->dev,
-			"Xfer length(%u) not a multiple of word size(%u)\n",
-			xfer->len, bpw / 8);
-		return -EIO;
-	}
-
 	if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
 		sdd->cur_bpw = bpw;
 		sdd->cur_speed = speed;
@@ -929,7 +723,10 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
 
 	spin_unlock_irqrestore(&sdd->lock, flags);
 
-	status = wait_for_xfer(sdd, xfer, use_dma);
+	if (use_dma)
+		status = wait_for_dma(sdd, xfer);
+	else
+		status = wait_for_pio(sdd, xfer);
 
 	if (status) {
 		dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
@@ -941,10 +738,10 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
 		if (use_dma) {
 			if (xfer->tx_buf != NULL
 			    && (sdd->state & TXBUSY))
-				s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
+				dmaengine_terminate_all(sdd->tx_dma.ch);
 			if (xfer->rx_buf != NULL
 			    && (sdd->state & RXBUSY))
-				s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
+				dmaengine_terminate_all(sdd->rx_dma.ch);
 		}
 	} else {
 		flush_fifo(sdd);
@@ -953,16 +750,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
 	return status;
 }
 
-static int s3c64xx_spi_unprepare_message(struct spi_master *master,
-					    struct spi_message *msg)
-{
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-
-	s3c64xx_spi_unmap_mssg(sdd, msg);
-
-	return 0;
-}
-
 static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
 				struct spi_device *spi)
 {
@@ -1092,14 +879,12 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 
 	pm_runtime_put(&sdd->pdev->dev);
 	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
-	disable_cs(sdd, spi);
 	return 0;
 
 setup_exit:
 	pm_runtime_put(&sdd->pdev->dev);
 	/* setup() returns with device de-selected */
 	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
-	disable_cs(sdd, spi);
 
 	gpio_free(cs->line);
 	spi_set_ctldata(spi, NULL);
@@ -1338,7 +1123,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 	master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
 	master->prepare_message = s3c64xx_spi_prepare_message;
 	master->transfer_one = s3c64xx_spi_transfer_one;
-	master->unprepare_message = s3c64xx_spi_unprepare_message;
 	master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
 	master->num_chipselect = sci->num_cs;
 	master->dma_alignment = 8;
@@ -1347,6 +1131,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->auto_runtime_pm = true;
+	if (!is_polling(sdd))
+		master->can_dma = s3c64xx_spi_can_dma;
 
 	sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
 	if (IS_ERR(sdd->regs)) {
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
index 121c2e1dea36..7fba10bba3b0 100644
--- a/drivers/spi/spi-sc18is602.c
+++ b/drivers/spi/spi-sc18is602.c
@@ -205,12 +205,6 @@ static int sc18is602_transfer_one(struct spi_master *master,
 	struct spi_transfer *t;
 	int status = 0;
 
-	/* SC18IS602 does not support CS2 */
-	if (hw->id == sc18is602 && spi->chip_select == 2) {
-		status = -ENXIO;
-		goto error;
-	}
-
 	hw->tlen = 0;
 	list_for_each_entry(t, &m->transfers, transfer_list) {
 		u32 hz = t->speed_hz ? : spi->max_speed_hz;
@@ -238,7 +232,6 @@ static int sc18is602_transfer_one(struct spi_master *master,
 		if (t->delay_usecs)
 			udelay(t->delay_usecs);
 	}
-error:
 	m->status = status;
 	spi_finalize_current_message(master);
 
@@ -247,10 +240,13 @@ error:
 
 static int sc18is602_setup(struct spi_device *spi)
 {
-	if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
-		return -EINVAL;
+	struct sc18is602 *hw = spi_master_get_devdata(spi->master);
 
-	return sc18is602_check_transfer(spi, NULL, 0);
+	/* SC18IS602 does not support CS2 */
+	if (hw->id == sc18is602 && spi->chip_select == 2)
+		return -ENXIO;
+
+	return 0;
 }
 
 static int sc18is602_probe(struct i2c_client *client,
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 82d2f922ffa0..3b170b9f3471 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -46,8 +46,6 @@
 /* SPSR */
 #define RXFL	(1 << 2)
 
-#define hspi2info(h)	(h->dev->platform_data)
-
 struct hspi_priv {
 	void __iomem *addr;
 	struct spi_master *master;
@@ -113,14 +111,9 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
 {
 	struct spi_device *spi = msg->spi;
 	struct device *dev = hspi->dev;
-	u32 target_rate;
 	u32 spcr, idiv_clk;
 	u32 rate, best_rate, min, tmp;
 
-	target_rate = t ? t->speed_hz : 0;
-	if (!target_rate)
-		target_rate = spi->max_speed_hz;
-
 	/*
 	 * find best IDIV/CLKCx settings
 	 */
@@ -140,7 +133,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
 		rate /= (((idiv_clk & 0x1F) + 1) * 2);
 
 		/* save best settings */
-		tmp = abs(target_rate - rate);
+		tmp = abs(t->speed_hz - rate);
 		if (tmp < min) {
 			min = tmp;
 			spcr = idiv_clk;
@@ -153,7 +146,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
 	if (spi->mode & SPI_CPOL)
 		spcr |= 1 << 6;
 
-	dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate);
+	dev_dbg(dev, "speed %d/%d\n", t->speed_hz, best_rate);
 
 	hspi_write(hspi, SPCR, spcr);
 	hspi_write(hspi, SPSR, 0x0);
@@ -230,29 +223,6 @@ static int hspi_transfer_one_message(struct spi_master *master,
 	return ret;
 }
 
-static int hspi_setup(struct spi_device *spi)
-{
-	struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
-	struct device *dev = hspi->dev;
-
-	if (8 != spi->bits_per_word) {
-		dev_err(dev, "bits_per_word should be 8\n");
-		return -EIO;
-	}
-
-	dev_dbg(dev, "%s setup\n", spi->modalias);
-
-	return 0;
-}
-
-static void hspi_cleanup(struct spi_device *spi)
-{
-	struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
-	struct device *dev = hspi->dev;
-
-	dev_dbg(dev, "%s cleanup\n", spi->modalias);
-}
-
 static int hspi_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -298,14 +268,13 @@ static int hspi_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(&pdev->dev);
 
-	master->num_chipselect	= 1;
 	master->bus_num		= pdev->id;
-	master->setup		= hspi_setup;
-	master->cleanup		= hspi_cleanup;
 	master->mode_bits	= SPI_CPOL | SPI_CPHA;
 	master->dev.of_node	= pdev->dev.of_node;
 	master->auto_runtime_pm = true;
 	master->transfer_one_message		= hspi_transfer_one_message;
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
+
 	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "spi_register_master error.\n");
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 81cc02f5f9b0..739eb2f12ecc 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -15,59 +15,108 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/spi/sh_msiof.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 
 #include <asm/unaligned.h>
 
+
+struct sh_msiof_chipdata {
+	u16 tx_fifo_size;
+	u16 rx_fifo_size;
+	u16 master_flags;
+};
+
 struct sh_msiof_spi_priv {
-	struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
 	void __iomem *mapbase;
 	struct clk *clk;
 	struct platform_device *pdev;
+	const struct sh_msiof_chipdata *chipdata;
 	struct sh_msiof_spi_info *info;
 	struct completion done;
-	unsigned long flags;
 	int tx_fifo_size;
 	int rx_fifo_size;
 };
 
-#define TMDR1	0x00
-#define TMDR2	0x04
-#define TMDR3	0x08
-#define RMDR1	0x10
-#define RMDR2	0x14
-#define RMDR3	0x18
-#define TSCR	0x20
-#define RSCR	0x22
-#define CTR	0x28
-#define FCTR	0x30
-#define STR	0x40
-#define IER	0x44
-#define TDR1	0x48
-#define TDR2	0x4c
-#define TFDR	0x50
-#define RDR1	0x58
-#define RDR2	0x5c
-#define RFDR	0x60
-
-#define CTR_TSCKE (1 << 15)
-#define CTR_TFSE  (1 << 14)
-#define CTR_TXE   (1 << 9)
-#define CTR_RXE   (1 << 8)
-
-#define STR_TEOF  (1 << 23)
-#define STR_REOF  (1 << 7)
+#define TMDR1	0x00	/* Transmit Mode Register 1 */
+#define TMDR2	0x04	/* Transmit Mode Register 2 */
+#define TMDR3	0x08	/* Transmit Mode Register 3 */
+#define RMDR1	0x10	/* Receive Mode Register 1 */
+#define RMDR2	0x14	/* Receive Mode Register 2 */
+#define RMDR3	0x18	/* Receive Mode Register 3 */
+#define TSCR	0x20	/* Transmit Clock Select Register */
+#define RSCR	0x22	/* Receive Clock Select Register (SH, A1, APE6) */
+#define CTR	0x28	/* Control Register */
+#define FCTR	0x30	/* FIFO Control Register */
+#define STR	0x40	/* Status Register */
+#define IER	0x44	/* Interrupt Enable Register */
+#define TDR1	0x48	/* Transmit Control Data Register 1 (SH, A1) */
+#define TDR2	0x4c	/* Transmit Control Data Register 2 (SH, A1) */
+#define TFDR	0x50	/* Transmit FIFO Data Register */
+#define RDR1	0x58	/* Receive Control Data Register 1 (SH, A1) */
+#define RDR2	0x5c	/* Receive Control Data Register 2 (SH, A1) */
+#define RFDR	0x60	/* Receive FIFO Data Register */
+
+/* TMDR1 and RMDR1 */
+#define MDR1_TRMD	 0x80000000 /* Transfer Mode (1 = Master mode) */
+#define MDR1_SYNCMD_MASK 0x30000000 /* SYNC Mode */
+#define MDR1_SYNCMD_SPI	 0x20000000 /*   Level mode/SPI */
+#define MDR1_SYNCMD_LR	 0x30000000 /*   L/R mode */
+#define MDR1_SYNCAC_SHIFT	 25 /* Sync Polarity (1 = Active-low) */
+#define MDR1_BITLSB_SHIFT	 24 /* MSB/LSB First (1 = LSB first) */
+#define MDR1_FLD_MASK	 0x000000c0 /* Frame Sync Signal Interval (0-3) */
+#define MDR1_FLD_SHIFT		  2
+#define MDR1_XXSTP	 0x00000001 /* Transmission/Reception Stop on FIFO */
+/* TMDR1 */
+#define TMDR1_PCON	 0x40000000 /* Transfer Signal Connection */
+
+/* TMDR2 and RMDR2 */
+#define MDR2_BITLEN1(i)	(((i) - 1) << 24) /* Data Size (8-32 bits) */
+#define MDR2_WDLEN1(i)	(((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
+#define MDR2_GRPMASK1	0x00000001 /* Group Output Mask 1 (SH, A1) */
+
+/* TSCR and RSCR */
+#define SCR_BRPS_MASK	    0x1f00 /* Prescaler Setting (1-32) */
+#define SCR_BRPS(i)	(((i) - 1) << 8)
+#define SCR_BRDV_MASK	    0x0007 /* Baud Rate Generator's Division Ratio */
+#define SCR_BRDV_DIV_2	    0x0000
+#define SCR_BRDV_DIV_4	    0x0001
+#define SCR_BRDV_DIV_8	    0x0002
+#define SCR_BRDV_DIV_16	    0x0003
+#define SCR_BRDV_DIV_32	    0x0004
+#define SCR_BRDV_DIV_1	    0x0007
+
+/* CTR */
+#define CTR_TSCKIZ_MASK	0xc0000000 /* Transmit Clock I/O Polarity Select */
+#define CTR_TSCKIZ_SCK	0x80000000 /*   Disable SCK when TX disabled */
+#define CTR_TSCKIZ_POL_SHIFT	30 /*   Transmit Clock Polarity */
+#define CTR_RSCKIZ_MASK	0x30000000 /* Receive Clock Polarity Select */
+#define CTR_RSCKIZ_SCK	0x20000000 /*   Must match CTR_TSCKIZ_SCK */
+#define CTR_RSCKIZ_POL_SHIFT	28 /*   Receive Clock Polarity */
+#define CTR_TEDG_SHIFT		27 /* Transmit Timing (1 = falling edge) */
+#define CTR_REDG_SHIFT		26 /* Receive Timing (1 = falling edge) */
+#define CTR_TXDIZ_MASK	0x00c00000 /* Pin Output When TX is Disabled */
+#define CTR_TXDIZ_LOW	0x00000000 /*   0 */
+#define CTR_TXDIZ_HIGH	0x00400000 /*   1 */
+#define CTR_TXDIZ_HIZ	0x00800000 /*   High-impedance */
+#define CTR_TSCKE	0x00008000 /* Transmit Serial Clock Output Enable */
+#define CTR_TFSE	0x00004000 /* Transmit Frame Sync Signal Output Enable */
+#define CTR_TXE		0x00000200 /* Transmit Enable */
+#define CTR_RXE		0x00000100 /* Receive Enable */
+
+/* STR and IER */
+#define STR_TEOF	0x00800000 /* Frame Transmission End */
+#define STR_REOF	0x00000080 /* Frame Reception End */
+
 
 static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
 {
@@ -131,22 +180,21 @@ static struct {
 	unsigned short div;
 	unsigned short scr;
 } const sh_msiof_spi_clk_table[] = {
-	{ 1, 0x0007 },
-	{ 2, 0x0000 },
-	{ 4, 0x0001 },
-	{ 8, 0x0002 },
-	{ 16, 0x0003 },
-	{ 32, 0x0004 },
-	{ 64, 0x1f00 },
-	{ 128, 0x1f01 },
-	{ 256, 0x1f02 },
-	{ 512, 0x1f03 },
-	{ 1024, 0x1f04 },
+	{ 1,	SCR_BRPS( 1) | SCR_BRDV_DIV_1 },
+	{ 2,	SCR_BRPS( 1) | SCR_BRDV_DIV_2 },
+	{ 4,	SCR_BRPS( 1) | SCR_BRDV_DIV_4 },
+	{ 8,	SCR_BRPS( 1) | SCR_BRDV_DIV_8 },
+	{ 16,	SCR_BRPS( 1) | SCR_BRDV_DIV_16 },
+	{ 32,	SCR_BRPS( 1) | SCR_BRDV_DIV_32 },
+	{ 64,	SCR_BRPS(32) | SCR_BRDV_DIV_2 },
+	{ 128,	SCR_BRPS(32) | SCR_BRDV_DIV_4 },
+	{ 256,	SCR_BRPS(32) | SCR_BRDV_DIV_8 },
+	{ 512,	SCR_BRPS(32) | SCR_BRDV_DIV_16 },
+	{ 1024,	SCR_BRPS(32) | SCR_BRDV_DIV_32 },
 };
 
 static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
-				      unsigned long parent_rate,
-				      unsigned long spi_hz)
+				      unsigned long parent_rate, u32 spi_hz)
 {
 	unsigned long div = 1024;
 	size_t k;
@@ -164,7 +212,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
 	k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1);
 
 	sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr);
-	sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
+	if (!(p->chipdata->master_flags & SPI_MASTER_MUST_TX))
+		sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
 }
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
@@ -183,21 +232,25 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
 	 */
 	sh_msiof_write(p, FCTR, 0);
 
-	tmp = 0;
-	tmp |= !cs_high << 25;
-	tmp |= lsb_first << 24;
-	sh_msiof_write(p, TMDR1, 0xe0000005 | tmp);
-	sh_msiof_write(p, RMDR1, 0x20000005 | tmp);
+	tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP;
+	tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
+	tmp |= lsb_first << MDR1_BITLSB_SHIFT;
+	sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON);
+	if (p->chipdata->master_flags & SPI_MASTER_MUST_TX) {
+		/* These bits are reserved if RX needs TX */
+		tmp &= ~0x0000ffff;
+	}
+	sh_msiof_write(p, RMDR1, tmp);
 
-	tmp = 0xa0000000;
-	tmp |= cpol << 30; /* TSCKIZ */
-	tmp |= cpol << 28; /* RSCKIZ */
+	tmp = 0;
+	tmp |= CTR_TSCKIZ_SCK | cpol << CTR_TSCKIZ_POL_SHIFT;
+	tmp |= CTR_RSCKIZ_SCK | cpol << CTR_RSCKIZ_POL_SHIFT;
 
 	edge = cpol ^ !cpha;
 
-	tmp |= edge << 27; /* TEDG */
-	tmp |= edge << 26; /* REDG */
-	tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */
+	tmp |= edge << CTR_TEDG_SHIFT;
+	tmp |= edge << CTR_REDG_SHIFT;
+	tmp |= tx_hi_z ? CTR_TXDIZ_HIZ : CTR_TXDIZ_LOW;
 	sh_msiof_write(p, CTR, tmp);
 }
 
@@ -205,12 +258,12 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, void *rx_buf,
 				       u32 bits, u32 words)
 {
-	u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
+	u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words);
 
-	if (tx_buf)
+	if (tx_buf || (p->chipdata->master_flags & SPI_MASTER_MUST_TX))
 		sh_msiof_write(p, TMDR2, dr2);
 	else
-		sh_msiof_write(p, TMDR2, dr2 | 1);
+		sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1);
 
 	if (rx_buf)
 		sh_msiof_write(p, RMDR2, dr2);
@@ -363,77 +416,58 @@ static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
 		put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
 }
 
-static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
+static int sh_msiof_spi_setup(struct spi_device *spi)
 {
-	int bits;
+	struct device_node	*np = spi->master->dev.of_node;
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
 
-	bits = t ? t->bits_per_word : 0;
-	if (!bits)
-		bits = spi->bits_per_word;
-	return bits;
-}
+	if (!np) {
+		/*
+		 * Use spi->controller_data for CS (same strategy as spi_gpio),
+		 * if any. otherwise let HW control CS
+		 */
+		spi->cs_gpio = (uintptr_t)spi->controller_data;
+	}
 
-static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
-				     struct spi_transfer *t)
-{
-	unsigned long hz;
+	/* Configure pins before deasserting CS */
+	sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
+				  !!(spi->mode & SPI_CPHA),
+				  !!(spi->mode & SPI_3WIRE),
+				  !!(spi->mode & SPI_LSB_FIRST),
+				  !!(spi->mode & SPI_CS_HIGH));
+
+	if (spi->cs_gpio >= 0)
+		gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 
-	hz = t ? t->speed_hz : 0;
-	if (!hz)
-		hz = spi->max_speed_hz;
-	return hz;
+	return 0;
 }
 
-static int sh_msiof_spi_setup_transfer(struct spi_device *spi,
-				       struct spi_transfer *t)
+static int sh_msiof_prepare_message(struct spi_master *master,
+				    struct spi_message *msg)
 {
-	int bits;
-
-	/* noting to check hz values against since parent clock is disabled */
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+	const struct spi_device *spi = msg->spi;
 
-	bits = sh_msiof_spi_bits(spi, t);
-	if (bits < 8)
-		return -EINVAL;
-	if (bits > 32)
-		return -EINVAL;
+	pm_runtime_get_sync(&p->pdev->dev);
+	clk_enable(p->clk);
 
-	return spi_bitbang_setup_transfer(spi, t);
+	/* Configure pins before asserting CS */
+	sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
+				  !!(spi->mode & SPI_CPHA),
+				  !!(spi->mode & SPI_3WIRE),
+				  !!(spi->mode & SPI_LSB_FIRST),
+				  !!(spi->mode & SPI_CS_HIGH));
+	return 0;
 }
 
-static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
+static int sh_msiof_unprepare_message(struct spi_master *master,
+				      struct spi_message *msg)
 {
-	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
-	int value;
-
-	/* chip select is active low unless SPI_CS_HIGH is set */
-	if (spi->mode & SPI_CS_HIGH)
-		value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0;
-	else
-		value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1;
-
-	if (is_on == BITBANG_CS_ACTIVE) {
-		if (!test_and_set_bit(0, &p->flags)) {
-			pm_runtime_get_sync(&p->pdev->dev);
-			clk_enable(p->clk);
-		}
-
-		/* Configure pins before asserting CS */
-		sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
-					  !!(spi->mode & SPI_CPHA),
-					  !!(spi->mode & SPI_3WIRE),
-					  !!(spi->mode & SPI_LSB_FIRST),
-					  !!(spi->mode & SPI_CS_HIGH));
-	}
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
 
-	/* use spi->controller data for CS (same strategy as spi_gpio) */
-	gpio_set_value((uintptr_t)spi->controller_data, value);
-
-	if (is_on == BITBANG_CS_INACTIVE) {
-		if (test_and_clear_bit(0, &p->flags)) {
-			clk_disable(p->clk);
-			pm_runtime_put(&p->pdev->dev);
-		}
-	}
+	clk_disable(p->clk);
+	pm_runtime_put(&p->pdev->dev);
+	return 0;
 }
 
 static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
@@ -487,7 +521,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
 	/* clear status bits */
 	sh_msiof_reset_str(p);
 
-	/* shut down frame, tx/tx and clock signals */
+	/* shut down frame, rx/tx and clock signals */
 	ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
 	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
 	if (rx_buf)
@@ -505,9 +539,11 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
 	return ret;
 }
 
-static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+static int sh_msiof_transfer_one(struct spi_master *master,
+				 struct spi_device *spi,
+				 struct spi_transfer *t)
 {
-	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
 	void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
 	void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
 	int bits;
@@ -517,7 +553,7 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 	int n;
 	bool swab;
 
-	bits = sh_msiof_spi_bits(spi, t);
+	bits = t->bits_per_word;
 
 	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
 		bits = 32;
@@ -567,8 +603,7 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 	}
 
 	/* setup clocks (clock already enabled in chipselect()) */
-	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
-				  sh_msiof_spi_hz(spi, t));
+	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
 
 	/* transfer in fifo sized chunks */
 	words = t->len / bytes_per_word;
@@ -588,22 +623,36 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 		words -= n;
 	}
 
-	return bytes_done;
-}
-
-static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
-				  u32 word, u8 bits)
-{
-	BUG(); /* unused but needed by bitbang code */
 	return 0;
 }
 
+static const struct sh_msiof_chipdata sh_data = {
+	.tx_fifo_size = 64,
+	.rx_fifo_size = 64,
+	.master_flags = 0,
+};
+
+static const struct sh_msiof_chipdata r8a779x_data = {
+	.tx_fifo_size = 64,
+	.rx_fifo_size = 256,
+	.master_flags = SPI_MASTER_MUST_TX,
+};
+
+static const struct of_device_id sh_msiof_match[] = {
+	{ .compatible = "renesas,sh-msiof",        .data = &sh_data },
+	{ .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
+	{ .compatible = "renesas,msiof-r8a7790",   .data = &r8a779x_data },
+	{ .compatible = "renesas,msiof-r8a7791",   .data = &r8a779x_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sh_msiof_match);
+
 #ifdef CONFIG_OF
 static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
 {
 	struct sh_msiof_spi_info *info;
 	struct device_node *np = dev->of_node;
-	u32 num_cs = 0;
+	u32 num_cs = 1;
 
 	info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL);
 	if (!info) {
@@ -633,6 +682,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 {
 	struct resource	*r;
 	struct spi_master *master;
+	const struct of_device_id *of_id;
 	struct sh_msiof_spi_priv *p;
 	int i;
 	int ret;
@@ -646,10 +696,15 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 	p = spi_master_get_devdata(master);
 
 	platform_set_drvdata(pdev, p);
-	if (pdev->dev.of_node)
+
+	of_id = of_match_device(sh_msiof_match, &pdev->dev);
+	if (of_id) {
+		p->chipdata = of_id->data;
 		p->info = sh_msiof_spi_parse_dt(&pdev->dev);
-	else
+	} else {
+		p->chipdata = (const void *)pdev->id_entry->driver_data;
 		p->info = dev_get_platdata(&pdev->dev);
+	}
 
 	if (!p->info) {
 		dev_err(&pdev->dev, "failed to obtain device info\n");
@@ -696,38 +751,36 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 	p->pdev = pdev;
 	pm_runtime_enable(&pdev->dev);
 
-	/* The standard version of MSIOF use 64 word FIFOs */
-	p->tx_fifo_size = 64;
-	p->rx_fifo_size = 64;
-
 	/* Platform data may override FIFO sizes */
+	p->tx_fifo_size = p->chipdata->tx_fifo_size;
+	p->rx_fifo_size = p->chipdata->rx_fifo_size;
 	if (p->info->tx_fifo_override)
 		p->tx_fifo_size = p->info->tx_fifo_override;
 	if (p->info->rx_fifo_override)
 		p->rx_fifo_size = p->info->rx_fifo_override;
 
-	/* init master and bitbang code */
+	/* init master code */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
-	master->flags = 0;
+	master->flags = p->chipdata->master_flags;
 	master->bus_num = pdev->id;
+	master->dev.of_node = pdev->dev.of_node;
 	master->num_chipselect = p->info->num_chipselect;
-	master->setup = spi_bitbang_setup;
-	master->cleanup = spi_bitbang_cleanup;
-
-	p->bitbang.master = master;
-	p->bitbang.chipselect = sh_msiof_spi_chipselect;
-	p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
-	p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
-	p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word;
-
-	ret = spi_bitbang_start(&p->bitbang);
-	if (ret == 0)
-		return 0;
+	master->setup = sh_msiof_spi_setup;
+	master->prepare_message = sh_msiof_prepare_message;
+	master->unprepare_message = sh_msiof_unprepare_message;
+	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
+	master->transfer_one = sh_msiof_transfer_one;
 
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "spi_register_master error.\n");
+		goto err2;
+	}
+
+	return 0;
+
+ err2:
 	pm_runtime_disable(&pdev->dev);
 	clk_unprepare(p->clk);
  err1:
@@ -738,29 +791,24 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 static int sh_msiof_spi_remove(struct platform_device *pdev)
 {
 	struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = spi_bitbang_stop(&p->bitbang);
-	if (!ret) {
-		pm_runtime_disable(&pdev->dev);
-		clk_unprepare(p->clk);
-		spi_master_put(p->bitbang.master);
-	}
-	return ret;
+	pm_runtime_disable(&pdev->dev);
+	clk_unprepare(p->clk);
+	return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id sh_msiof_match[] = {
-	{ .compatible = "renesas,sh-msiof", },
-	{ .compatible = "renesas,sh-mobile-msiof", },
+static struct platform_device_id spi_driver_ids[] = {
+	{ "spi_sh_msiof",	(kernel_ulong_t)&sh_data },
+	{ "spi_r8a7790_msiof",	(kernel_ulong_t)&r8a779x_data },
+	{ "spi_r8a7791_msiof",	(kernel_ulong_t)&r8a779x_data },
 	{},
 };
-MODULE_DEVICE_TABLE(of, sh_msiof_match);
-#endif
+MODULE_DEVICE_TABLE(platform, spi_driver_ids);
 
 static struct platform_driver sh_msiof_spi_drv = {
 	.probe		= sh_msiof_spi_probe,
 	.remove		= sh_msiof_spi_remove,
+	.id_table	= spi_driver_ids,
 	.driver		= {
 		.name		= "spi_sh_msiof",
 		.owner		= THIS_MODULE,
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
index 38eb24df796c..85c2efd57c80 100644
--- a/drivers/spi/spi-sh-sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index e430689c3837..a72b8f87a156 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -22,7 +22,6 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-direction.h>
 #include <linux/dma-mapping.h>
-#include <linux/sirfsoc_dma.h>
 
 #define DRIVER_NAME "sirfsoc_spi"
 
@@ -132,6 +131,8 @@
 #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
 	ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
 
+#define SIRFSOC_MAX_CMD_BYTES	4
+
 struct sirfsoc_spi {
 	struct spi_bitbang bitbang;
 	struct completion rx_done;
@@ -162,6 +163,12 @@ struct sirfsoc_spi {
 	void *dummypage;
 	int word_width; /* in bytes */
 
+	/*
+	 * if tx size is not more than 4 and rx size is NULL, use
+	 * command model
+	 */
+	bool	tx_by_cmd;
+
 	int chipselect[0];
 };
 
@@ -260,6 +267,12 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
 
 	writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
+	if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {
+		complete(&sspi->tx_done);
+		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
+		return IRQ_HANDLED;
+	}
+
 	/* Error Conditions */
 	if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
 			spi_stat & SIRFSOC_SPI_TX_UFLOW) {
@@ -310,6 +323,34 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 
 	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
+	/*
+	 * 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);
+
+		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+			dev_err(&spi->dev, "transfer timeout\n");
+			return 0;
+		}
+
+		return t->len;
+	}
+
 	if (sspi->left_tx_word == 1) {
 		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
 			SIRFSOC_SPI_ENA_AUTO_CLR,
@@ -459,11 +500,6 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 		regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8;
 		sspi->rx_word = spi_sirfsoc_rx_word_u8;
 		sspi->tx_word = spi_sirfsoc_tx_word_u8;
-		txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_BYTE;
-		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_BYTE;
-		sspi->word_width = 1;
 		break;
 	case 12:
 	case 16:
@@ -471,26 +507,22 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 			SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
 		sspi->rx_word = spi_sirfsoc_rx_word_u16;
 		sspi->tx_word = spi_sirfsoc_tx_word_u16;
-		txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_WORD;
-		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_WORD;
-		sspi->word_width = 2;
 		break;
 	case 32:
 		regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
 		sspi->rx_word = spi_sirfsoc_rx_word_u32;
 		sspi->tx_word = spi_sirfsoc_tx_word_u32;
-		txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_DWORD;
-		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-					SIRFSOC_SPI_FIFO_WIDTH_DWORD;
-		sspi->word_width = 4;
 		break;
 	default:
 		BUG();
 	}
 
+	sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
+	txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
+					   sspi->word_width;
+	rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
+					   sspi->word_width;
+
 	if (!(spi->mode & SPI_CS_HIGH))
 		regval |= SIRFSOC_SPI_CS_IDLE_STAT;
 	if (!(spi->mode & SPI_LSB_FIRST))
@@ -519,6 +551,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL);
 	writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
 
+	if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) {
+		regval |= (SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) |
+				SIRFSOC_SPI_CMD_MODE);
+		sspi->tx_by_cmd = true;
+	} else {
+		regval &= ~SIRFSOC_SPI_CMD_MODE;
+		sspi->tx_by_cmd = false;
+	}
 	writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
 
 	if (IS_DMA_VALID(t)) {
@@ -548,8 +588,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct resource *mem_res;
 	int num_cs, cs_gpio, irq;
-	u32 rx_dma_ch, tx_dma_ch;
-	dma_cap_mask_t dma_cap_mask;
 	int i;
 	int ret;
 
@@ -560,20 +598,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 		goto err_cs;
 	}
 
-	ret = of_property_read_u32(pdev->dev.of_node,
-			"sirf,spi-dma-rx-channel", &rx_dma_ch);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to get rx dma channel\n");
-		goto err_cs;
-	}
-
-	ret = of_property_read_u32(pdev->dev.of_node,
-			"sirf,spi-dma-tx-channel", &tx_dma_ch);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to get tx dma channel\n");
-		goto err_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");
@@ -637,18 +661,13 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 	sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
 
 	/* request DMA channels */
-	dma_cap_zero(dma_cap_mask);
-	dma_cap_set(DMA_INTERLEAVE, dma_cap_mask);
-
-	sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
-		(void *)rx_dma_ch);
+	sspi->rx_chan = dma_request_slave_channel(&pdev->dev, "rx");
 	if (!sspi->rx_chan) {
 		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
 		ret = -ENODEV;
 		goto free_master;
 	}
-	sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
-		(void *)tx_dma_ch);
+	sspi->tx_chan = dma_request_slave_channel(&pdev->dev, "tx");
 	if (!sspi->tx_chan) {
 		dev_err(&pdev->dev, "can not allocate tx dma channel\n");
 		ret = -ENODEV;
@@ -724,7 +743,7 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int spi_sirfsoc_suspend(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
@@ -747,13 +766,11 @@ static int spi_sirfsoc_resume(struct device *dev)
 
 	return 0;
 }
-
-static const struct dev_pm_ops spi_sirfsoc_pm_ops = {
-	.suspend = spi_sirfsoc_suspend,
-	.resume = spi_sirfsoc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend,
+			 spi_sirfsoc_resume);
+
 static const struct of_device_id spi_sirfsoc_of_match[] = {
 	{ .compatible = "sirf,prima2-spi", },
 	{ .compatible = "sirf,marco-spi", },
@@ -765,9 +782,7 @@ static struct platform_driver spi_sirfsoc_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm     = &spi_sirfsoc_pm_ops,
-#endif
 		.of_match_table = spi_sirfsoc_of_match,
 	},
 	.probe = spi_sirfsoc_probe,
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
new file mode 100644
index 000000000000..3f82705d0a27
--- /dev/null
+++ b/drivers/spi/spi-sun4i.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.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/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN4I_FIFO_DEPTH		64
+
+#define SUN4I_RXDATA_REG		0x00
+
+#define SUN4I_TXDATA_REG		0x04
+
+#define SUN4I_CTL_REG			0x08
+#define SUN4I_CTL_ENABLE			BIT(0)
+#define SUN4I_CTL_MASTER			BIT(1)
+#define SUN4I_CTL_CPHA				BIT(2)
+#define SUN4I_CTL_CPOL				BIT(3)
+#define SUN4I_CTL_CS_ACTIVE_LOW			BIT(4)
+#define SUN4I_CTL_LMTF				BIT(6)
+#define SUN4I_CTL_TF_RST			BIT(8)
+#define SUN4I_CTL_RF_RST			BIT(9)
+#define SUN4I_CTL_XCH				BIT(10)
+#define SUN4I_CTL_CS_MASK			0x3000
+#define SUN4I_CTL_CS(cs)			(((cs) << 12) & SUN4I_CTL_CS_MASK)
+#define SUN4I_CTL_DHB				BIT(15)
+#define SUN4I_CTL_CS_MANUAL			BIT(16)
+#define SUN4I_CTL_CS_LEVEL			BIT(17)
+#define SUN4I_CTL_TP				BIT(18)
+
+#define SUN4I_INT_CTL_REG		0x0c
+#define SUN4I_INT_CTL_TC			BIT(16)
+
+#define SUN4I_INT_STA_REG		0x10
+
+#define SUN4I_DMA_CTL_REG		0x14
+
+#define SUN4I_WAIT_REG			0x18
+
+#define SUN4I_CLK_CTL_REG		0x1c
+#define SUN4I_CLK_CTL_CDR2_MASK			0xff
+#define SUN4I_CLK_CTL_CDR2(div)			((div) & SUN4I_CLK_CTL_CDR2_MASK)
+#define SUN4I_CLK_CTL_CDR1_MASK			0xf
+#define SUN4I_CLK_CTL_CDR1(div)			(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN4I_CLK_CTL_DRS			BIT(12)
+
+#define SUN4I_BURST_CNT_REG		0x20
+#define SUN4I_BURST_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN4I_XMIT_CNT_REG		0x24
+#define SUN4I_XMIT_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN4I_FIFO_STA_REG		0x28
+#define SUN4I_FIFO_STA_RF_CNT_MASK		0x7f
+#define SUN4I_FIFO_STA_RF_CNT_BITS		0
+#define SUN4I_FIFO_STA_TF_CNT_MASK		0x7f
+#define SUN4I_FIFO_STA_TF_CNT_BITS		16
+
+struct sun4i_spi {
+	struct spi_master	*master;
+	void __iomem		*base_addr;
+	struct clk		*hclk;
+	struct clk		*mclk;
+
+	struct completion	done;
+
+	const u8		*tx_buf;
+	u8			*rx_buf;
+	int			len;
+};
+
+static inline u32 sun4i_spi_read(struct sun4i_spi *sspi, u32 reg)
+{
+	return readl(sspi->base_addr + reg);
+}
+
+static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value)
+{
+	writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
+{
+	u32 reg, cnt;
+	u8 byte;
+
+	/* See how much data is available */
+	reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
+	reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
+	cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
+
+	if (len > cnt)
+		len = cnt;
+
+	while (len--) {
+		byte = readb(sspi->base_addr + SUN4I_RXDATA_REG);
+		if (sspi->rx_buf)
+			*sspi->rx_buf++ = byte;
+	}
+}
+
+static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len)
+{
+	u8 byte;
+
+	if (len > sspi->len)
+		len = sspi->len;
+
+	while (len--) {
+		byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+		writeb(byte, sspi->base_addr + SUN4I_TXDATA_REG);
+		sspi->len--;
+	}
+}
+
+static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
+	u32 reg;
+
+	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+
+	reg &= ~SUN4I_CTL_CS_MASK;
+	reg |= SUN4I_CTL_CS(spi->chip_select);
+
+	if (enable)
+		reg |= SUN4I_CTL_CS_LEVEL;
+	else
+		reg &= ~SUN4I_CTL_CS_LEVEL;
+
+	/*
+	 * Even though this looks irrelevant since we are supposed to
+	 * be controlling the chip select manually, this bit also
+	 * controls the levels of the chip select for inactive
+	 * devices.
+	 *
+	 * If we don't set it, the chip select level will go low by
+	 * default when the device is idle, which is not really
+	 * expected in the common case where the chip select is active
+	 * low.
+	 */
+	if (spi->mode & SPI_CS_HIGH)
+		reg &= ~SUN4I_CTL_CS_ACTIVE_LOW;
+	else
+		reg |= SUN4I_CTL_CS_ACTIVE_LOW;
+
+	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
+}
+
+static int sun4i_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *tfr)
+{
+	struct sun4i_spi *sspi = spi_master_get_devdata(master);
+	unsigned int mclk_rate, div, timeout;
+	unsigned int tx_len = 0;
+	int ret = 0;
+	u32 reg;
+
+	/* We don't support transfer larger than the FIFO */
+	if (tfr->len > SUN4I_FIFO_DEPTH)
+		return -EINVAL;
+
+	reinit_completion(&sspi->done);
+	sspi->tx_buf = tfr->tx_buf;
+	sspi->rx_buf = tfr->rx_buf;
+	sspi->len = tfr->len;
+
+	/* Clear pending interrupts */
+	sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0);
+
+
+	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+
+	/* Reset FIFOs */
+	sun4i_spi_write(sspi, SUN4I_CTL_REG,
+			reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
+
+	/*
+	 * Setup the transfer control register: Chip Select,
+	 * polarities, etc.
+	 */
+	if (spi->mode & SPI_CPOL)
+		reg |= SUN4I_CTL_CPOL;
+	else
+		reg &= ~SUN4I_CTL_CPOL;
+
+	if (spi->mode & SPI_CPHA)
+		reg |= SUN4I_CTL_CPHA;
+	else
+		reg &= ~SUN4I_CTL_CPHA;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		reg |= SUN4I_CTL_LMTF;
+	else
+		reg &= ~SUN4I_CTL_LMTF;
+
+
+	/*
+	 * If it's a TX only transfer, we don't want to fill the RX
+	 * FIFO with bogus data
+	 */
+	if (sspi->rx_buf)
+		reg &= ~SUN4I_CTL_DHB;
+	else
+		reg |= SUN4I_CTL_DHB;
+
+	/* We want to control the chip select manually */
+	reg |= SUN4I_CTL_CS_MANUAL;
+
+	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
+
+	/* Ensure that we have a parent clock fast enough */
+	mclk_rate = clk_get_rate(sspi->mclk);
+	if (mclk_rate < (2 * spi->max_speed_hz)) {
+		clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+		mclk_rate = clk_get_rate(sspi->mclk);
+	}
+
+	/*
+	 * Setup clock divider.
+	 *
+	 * We have two choices there. Either we can use the clock
+	 * divide rate 1, which is calculated thanks to this formula:
+	 * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
+	 * Or we can use CDR2, which is calculated with the formula:
+	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+	 * Wether we use the former or the latter is set through the
+	 * DRS bit.
+	 *
+	 * First try CDR2, and if we can't reach the expected
+	 * frequency, fall back to CDR1.
+	 */
+	div = mclk_rate / (2 * spi->max_speed_hz);
+	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
+		if (div > 0)
+			div--;
+
+		reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
+	} else {
+		div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+		reg = SUN4I_CLK_CTL_CDR1(div);
+	}
+
+	sun4i_spi_write(sspi, SUN4I_CLK_CTL_REG, reg);
+
+	/* Setup the transfer now... */
+	if (sspi->tx_buf)
+		tx_len = tfr->len;
+
+	/* Setup the counters */
+	sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
+	sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
+
+	/* Fill the TX FIFO */
+	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
+
+	/* Enable the interrupts */
+	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
+
+	/* Start the transfer */
+	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
+
+	timeout = wait_for_completion_timeout(&sspi->done,
+					      msecs_to_jiffies(1000));
+	if (!timeout) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
+
+out:
+	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
+
+	return ret;
+}
+
+static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
+{
+	struct sun4i_spi *sspi = dev_id;
+	u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
+
+	/* Transfer complete */
+	if (status & SUN4I_INT_CTL_TC) {
+		sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
+		complete(&sspi->done);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int sun4i_spi_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun4i_spi *sspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(sspi->hclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable AHB clock\n");
+		goto out;
+	}
+
+	ret = clk_prepare_enable(sspi->mclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable module clock\n");
+		goto err;
+	}
+
+	sun4i_spi_write(sspi, SUN4I_CTL_REG,
+			SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP);
+
+	return 0;
+
+err:
+	clk_disable_unprepare(sspi->hclk);
+out:
+	return ret;
+}
+
+static int sun4i_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun4i_spi *sspi = spi_master_get_devdata(master);
+
+	clk_disable_unprepare(sspi->mclk);
+	clk_disable_unprepare(sspi->hclk);
+
+	return 0;
+}
+
+static int sun4i_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct sun4i_spi *sspi;
+	struct resource	*res;
+	int ret = 0, irq;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
+	if (!master) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+	sspi = spi_master_get_devdata(master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sspi->base_addr)) {
+		ret = PTR_ERR(sspi->base_addr);
+		goto err_free_master;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No spi IRQ specified\n");
+		ret = -ENXIO;
+		goto err_free_master;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler,
+			       0, "sun4i-spi", sspi);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot request IRQ\n");
+		goto err_free_master;
+	}
+
+	sspi->master = master;
+	master->set_cs = sun4i_spi_set_cs;
+	master->transfer_one = sun4i_spi_transfer_one;
+	master->num_chipselect = 4;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+	master->dev.of_node = pdev->dev.of_node;
+	master->auto_runtime_pm = true;
+
+	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sspi->hclk)) {
+		dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+		ret = PTR_ERR(sspi->hclk);
+		goto err_free_master;
+	}
+
+	sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+	if (IS_ERR(sspi->mclk)) {
+		dev_err(&pdev->dev, "Unable to acquire module clock\n");
+		ret = PTR_ERR(sspi->mclk);
+		goto err_free_master;
+	}
+
+	init_completion(&sspi->done);
+
+	/*
+	 * This wake-up/shutdown pattern is to be able to have the
+	 * device woken up, even if runtime_pm is disabled
+	 */
+	ret = sun4i_spi_runtime_resume(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't resume the device\n");
+		goto err_free_master;
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_idle(&pdev->dev);
+
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		goto err_pm_disable;
+	}
+
+	return 0;
+
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
+	sun4i_spi_runtime_suspend(&pdev->dev);
+err_free_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int sun4i_spi_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id sun4i_spi_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun4i_spi_match);
+
+static const struct dev_pm_ops sun4i_spi_pm_ops = {
+	.runtime_resume		= sun4i_spi_runtime_resume,
+	.runtime_suspend	= sun4i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun4i_spi_driver = {
+	.probe	= sun4i_spi_probe,
+	.remove	= sun4i_spi_remove,
+	.driver	= {
+		.name		= "sun4i-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun4i_spi_match,
+		.pm		= &sun4i_spi_pm_ops,
+	},
+};
+module_platform_driver(sun4i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A1X/A20 SPI controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
new file mode 100644
index 000000000000..4b9ec08022fe
--- /dev/null
+++ b/drivers/spi/spi-sun6i.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.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/reset.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN6I_FIFO_DEPTH		128
+
+#define SUN6I_GBL_CTL_REG		0x04
+#define SUN6I_GBL_CTL_BUS_ENABLE		BIT(0)
+#define SUN6I_GBL_CTL_MASTER			BIT(1)
+#define SUN6I_GBL_CTL_TP			BIT(7)
+#define SUN6I_GBL_CTL_RST			BIT(31)
+
+#define SUN6I_TFR_CTL_REG		0x08
+#define SUN6I_TFR_CTL_CPHA			BIT(0)
+#define SUN6I_TFR_CTL_CPOL			BIT(1)
+#define SUN6I_TFR_CTL_SPOL			BIT(2)
+#define SUN6I_TFR_CTL_CS_MASK			0x30
+#define SUN6I_TFR_CTL_CS(cs)			(((cs) << 4) & SUN6I_TFR_CTL_CS_MASK)
+#define SUN6I_TFR_CTL_CS_MANUAL			BIT(6)
+#define SUN6I_TFR_CTL_CS_LEVEL			BIT(7)
+#define SUN6I_TFR_CTL_DHB			BIT(8)
+#define SUN6I_TFR_CTL_FBS			BIT(12)
+#define SUN6I_TFR_CTL_XCH			BIT(31)
+
+#define SUN6I_INT_CTL_REG		0x10
+#define SUN6I_INT_CTL_RF_OVF			BIT(8)
+#define SUN6I_INT_CTL_TC			BIT(12)
+
+#define SUN6I_INT_STA_REG		0x14
+
+#define SUN6I_FIFO_CTL_REG		0x18
+#define SUN6I_FIFO_CTL_RF_RST			BIT(15)
+#define SUN6I_FIFO_CTL_TF_RST			BIT(31)
+
+#define SUN6I_FIFO_STA_REG		0x1c
+#define SUN6I_FIFO_STA_RF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_RF_CNT_BITS		0
+#define SUN6I_FIFO_STA_TF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_TF_CNT_BITS		16
+
+#define SUN6I_CLK_CTL_REG		0x24
+#define SUN6I_CLK_CTL_CDR2_MASK			0xff
+#define SUN6I_CLK_CTL_CDR2(div)			(((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
+#define SUN6I_CLK_CTL_CDR1_MASK			0xf
+#define SUN6I_CLK_CTL_CDR1(div)			(((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN6I_CLK_CTL_DRS			BIT(12)
+
+#define SUN6I_BURST_CNT_REG		0x30
+#define SUN6I_BURST_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_XMIT_CNT_REG		0x34
+#define SUN6I_XMIT_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_BURST_CTL_CNT_REG		0x38
+#define SUN6I_BURST_CTL_CNT_STC(cnt)		((cnt) & 0xffffff)
+
+#define SUN6I_TXDATA_REG		0x200
+#define SUN6I_RXDATA_REG		0x300
+
+struct sun6i_spi {
+	struct spi_master	*master;
+	void __iomem		*base_addr;
+	struct clk		*hclk;
+	struct clk		*mclk;
+	struct reset_control	*rstc;
+
+	struct completion	done;
+
+	const u8		*tx_buf;
+	u8			*rx_buf;
+	int			len;
+};
+
+static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
+{
+	return readl(sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
+{
+	writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
+{
+	u32 reg, cnt;
+	u8 byte;
+
+	/* See how much data is available */
+	reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
+	reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
+	cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+
+	if (len > cnt)
+		len = cnt;
+
+	while (len--) {
+		byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
+		if (sspi->rx_buf)
+			*sspi->rx_buf++ = byte;
+	}
+}
+
+static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
+{
+	u8 byte;
+
+	if (len > sspi->len)
+		len = sspi->len;
+
+	while (len--) {
+		byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+		writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
+		sspi->len--;
+	}
+}
+
+static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+	u32 reg;
+
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	reg &= ~SUN6I_TFR_CTL_CS_MASK;
+	reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
+
+	if (enable)
+		reg |= SUN6I_TFR_CTL_CS_LEVEL;
+	else
+		reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
+
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+}
+
+
+static int sun6i_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *tfr)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	unsigned int mclk_rate, div, timeout;
+	unsigned int tx_len = 0;
+	int ret = 0;
+	u32 reg;
+
+	/* We don't support transfer larger than the FIFO */
+	if (tfr->len > SUN6I_FIFO_DEPTH)
+		return -EINVAL;
+
+	reinit_completion(&sspi->done);
+	sspi->tx_buf = tfr->tx_buf;
+	sspi->rx_buf = tfr->rx_buf;
+	sspi->len = tfr->len;
+
+	/* Clear pending interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
+
+	/* Reset FIFO */
+	sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
+			SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
+
+	/*
+	 * Setup the transfer control register: Chip Select,
+	 * polarities, etc.
+	 */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+	if (spi->mode & SPI_CPOL)
+		reg |= SUN6I_TFR_CTL_CPOL;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPOL;
+
+	if (spi->mode & SPI_CPHA)
+		reg |= SUN6I_TFR_CTL_CPHA;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPHA;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		reg |= SUN6I_TFR_CTL_FBS;
+	else
+		reg &= ~SUN6I_TFR_CTL_FBS;
+
+	/*
+	 * If it's a TX only transfer, we don't want to fill the RX
+	 * FIFO with bogus data
+	 */
+	if (sspi->rx_buf)
+		reg &= ~SUN6I_TFR_CTL_DHB;
+	else
+		reg |= SUN6I_TFR_CTL_DHB;
+
+	/* We want to control the chip select manually */
+	reg |= SUN6I_TFR_CTL_CS_MANUAL;
+
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+	/* Ensure that we have a parent clock fast enough */
+	mclk_rate = clk_get_rate(sspi->mclk);
+	if (mclk_rate < (2 * spi->max_speed_hz)) {
+		clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+		mclk_rate = clk_get_rate(sspi->mclk);
+	}
+
+	/*
+	 * Setup clock divider.
+	 *
+	 * We have two choices there. Either we can use the clock
+	 * divide rate 1, which is calculated thanks to this formula:
+	 * SPI_CLK = MOD_CLK / (2 ^ cdr)
+	 * Or we can use CDR2, which is calculated with the formula:
+	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+	 * Wether we use the former or the latter is set through the
+	 * DRS bit.
+	 *
+	 * First try CDR2, and if we can't reach the expected
+	 * frequency, fall back to CDR1.
+	 */
+	div = mclk_rate / (2 * spi->max_speed_hz);
+	if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+		if (div > 0)
+			div--;
+
+		reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+	} else {
+		div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+		reg = SUN6I_CLK_CTL_CDR1(div);
+	}
+
+	sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
+
+	/* Setup the transfer now... */
+	if (sspi->tx_buf)
+		tx_len = tfr->len;
+
+	/* Setup the counters */
+	sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len));
+	sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len));
+	sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG,
+			SUN6I_BURST_CTL_CNT_STC(tx_len));
+
+	/* Fill the TX FIFO */
+	sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+	/* Enable the interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
+
+	/* Start the transfer */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+
+	timeout = wait_for_completion_timeout(&sspi->done,
+					      msecs_to_jiffies(1000));
+	if (!timeout) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+out:
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+
+	return ret;
+}
+
+static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
+{
+	struct sun6i_spi *sspi = dev_id;
+	u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+
+	/* Transfer complete */
+	if (status & SUN6I_INT_CTL_TC) {
+		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
+		complete(&sspi->done);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int sun6i_spi_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(sspi->hclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable AHB clock\n");
+		goto out;
+	}
+
+	ret = clk_prepare_enable(sspi->mclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable module clock\n");
+		goto err;
+	}
+
+	ret = reset_control_deassert(sspi->rstc);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert the device from reset\n");
+		goto err2;
+	}
+
+	sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
+			SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
+
+	return 0;
+
+err2:
+	clk_disable_unprepare(sspi->mclk);
+err:
+	clk_disable_unprepare(sspi->hclk);
+out:
+	return ret;
+}
+
+static int sun6i_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+	reset_control_assert(sspi->rstc);
+	clk_disable_unprepare(sspi->mclk);
+	clk_disable_unprepare(sspi->hclk);
+
+	return 0;
+}
+
+static int sun6i_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct sun6i_spi *sspi;
+	struct resource	*res;
+	int ret = 0, irq;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
+	if (!master) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+	sspi = spi_master_get_devdata(master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sspi->base_addr)) {
+		ret = PTR_ERR(sspi->base_addr);
+		goto err_free_master;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No spi IRQ specified\n");
+		ret = -ENXIO;
+		goto err_free_master;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
+			       0, "sun6i-spi", sspi);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot request IRQ\n");
+		goto err_free_master;
+	}
+
+	sspi->master = master;
+	master->set_cs = sun6i_spi_set_cs;
+	master->transfer_one = sun6i_spi_transfer_one;
+	master->num_chipselect = 4;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+	master->dev.of_node = pdev->dev.of_node;
+	master->auto_runtime_pm = true;
+
+	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sspi->hclk)) {
+		dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+		ret = PTR_ERR(sspi->hclk);
+		goto err_free_master;
+	}
+
+	sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+	if (IS_ERR(sspi->mclk)) {
+		dev_err(&pdev->dev, "Unable to acquire module clock\n");
+		ret = PTR_ERR(sspi->mclk);
+		goto err_free_master;
+	}
+
+	init_completion(&sspi->done);
+
+	sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(sspi->rstc)) {
+		dev_err(&pdev->dev, "Couldn't get reset controller\n");
+		ret = PTR_ERR(sspi->rstc);
+		goto err_free_master;
+	}
+
+	/*
+	 * This wake-up/shutdown pattern is to be able to have the
+	 * device woken up, even if runtime_pm is disabled
+	 */
+	ret = sun6i_spi_runtime_resume(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't resume the device\n");
+		goto err_free_master;
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_idle(&pdev->dev);
+
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		goto err_pm_disable;
+	}
+
+	return 0;
+
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
+	sun6i_spi_runtime_suspend(&pdev->dev);
+err_free_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int sun6i_spi_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id sun6i_spi_match[] = {
+	{ .compatible = "allwinner,sun6i-a31-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun6i_spi_match);
+
+static const struct dev_pm_ops sun6i_spi_pm_ops = {
+	.runtime_resume		= sun6i_spi_runtime_resume,
+	.runtime_suspend	= sun6i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun6i_spi_driver = {
+	.probe	= sun6i_spi_probe,
+	.remove	= sun6i_spi_remove,
+	.driver	= {
+		.name		= "sun6i-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun6i_spi_match,
+		.pm		= &sun6i_spi_pm_ops,
+	},
+};
+module_platform_driver(sun6i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 413c71843492..400649595505 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -23,7 +23,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -172,7 +171,6 @@ struct tegra_spi_data {
 	void __iomem				*base;
 	phys_addr_t				phys;
 	unsigned				irq;
-	u32					spi_max_frequency;
 	u32					cur_speed;
 
 	struct spi_device			*cur_spi;
@@ -761,11 +759,6 @@ static int tegra_spi_setup(struct spi_device *spi)
 		spi->mode & SPI_CPHA ? "" : "~",
 		spi->max_speed_hz);
 
-	BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
-
-	/* Set speed to the spi max fequency if spi device has not set */
-	spi->max_speed_hz = spi->max_speed_hz ? : tspi->spi_max_frequency;
-
 	ret = pm_runtime_get_sync(tspi->dev);
 	if (ret < 0) {
 		dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
@@ -853,8 +846,8 @@ complete_xfer:
 					SPI_COMMAND1);
 			tegra_spi_transfer_delay(xfer->delay_usecs);
 			goto exit;
-		} else if (msg->transfers.prev == &xfer->transfer_list) {
-			/* This is the last transfer in message */
+		} else if (list_is_last(&xfer->transfer_list,
+					&msg->transfers)) {
 			if (xfer->cs_change)
 				tspi->cs_control = spi;
 			else {
@@ -1019,16 +1012,6 @@ static irqreturn_t tegra_spi_isr(int irq, void *context_data)
 	return IRQ_WAKE_THREAD;
 }
 
-static void tegra_spi_parse_dt(struct platform_device *pdev,
-	struct tegra_spi_data *tspi)
-{
-	struct device_node *np = pdev->dev.of_node;
-
-	if (of_property_read_u32(np, "spi-max-frequency",
-				&tspi->spi_max_frequency))
-		tspi->spi_max_frequency = 25000000; /* 25MHz */
-}
-
 static struct of_device_id tegra_spi_of_match[] = {
 	{ .compatible = "nvidia,tegra114-spi", },
 	{}
@@ -1050,15 +1033,15 @@ static int tegra_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 	tspi = spi_master_get_devdata(master);
 
-	/* Parse DT */
-	tegra_spi_parse_dt(pdev, tspi);
+	if (of_property_read_u32(pdev->dev.of_node, "spi-max-frequency",
+				 &master->max_speed_hz))
+		master->max_speed_hz = 25000000; /* 25MHz */
 
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->setup = tegra_spi_setup;
 	master->transfer_one_message = tegra_spi_transfer_one_message;
 	master->num_chipselect = MAX_CHIP_SELECT;
-	master->bus_num = -1;
 	master->auto_runtime_pm = true;
 
 	tspi->master = master;
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index 08794977f21a..47869ea636e1 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -22,7 +22,6 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -121,7 +120,6 @@ struct tegra_sflash_data {
 	struct reset_control			*rst;
 	void __iomem				*base;
 	unsigned				irq;
-	u32					spi_max_frequency;
 	u32					cur_speed;
 
 	struct spi_device			*cur_spi;
@@ -315,15 +313,6 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
 	return tegra_sflash_start_cpu_based_transfer(tsd, t);
 }
 
-static int tegra_sflash_setup(struct spi_device *spi)
-{
-	struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
-
-	/* Set speed to the spi max fequency if spi device has not set */
-	spi->max_speed_hz = spi->max_speed_hz ? : tsd->spi_max_frequency;
-	return 0;
-}
-
 static int tegra_sflash_transfer_one_message(struct spi_master *master,
 			struct spi_message *msg)
 {
@@ -430,15 +419,6 @@ static irqreturn_t tegra_sflash_isr(int irq, void *context_data)
 	return handle_cpu_based_xfer(tsd);
 }
 
-static void tegra_sflash_parse_dt(struct tegra_sflash_data *tsd)
-{
-	struct device_node *np = tsd->dev->of_node;
-
-	if (of_property_read_u32(np, "spi-max-frequency",
-					&tsd->spi_max_frequency))
-		tsd->spi_max_frequency = 25000000; /* 25MHz */
-}
-
 static struct of_device_id tegra_sflash_of_match[] = {
 	{ .compatible = "nvidia,tegra20-sflash", },
 	{}
@@ -467,11 +447,9 @@ static int tegra_sflash_probe(struct platform_device *pdev)
 
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA;
-	master->setup = tegra_sflash_setup;
 	master->transfer_one_message = tegra_sflash_transfer_one_message;
 	master->auto_runtime_pm = true;
 	master->num_chipselect = MAX_CHIP_SELECT;
-	master->bus_num = -1;
 
 	platform_set_drvdata(pdev, master);
 	tsd = spi_master_get_devdata(master);
@@ -479,7 +457,9 @@ static int tegra_sflash_probe(struct platform_device *pdev)
 	tsd->dev = &pdev->dev;
 	spin_lock_init(&tsd->lock);
 
-	tegra_sflash_parse_dt(tsd);
+	if (of_property_read_u32(tsd->dev->of_node, "spi-max-frequency",
+				 &master->max_speed_hz))
+		master->max_speed_hz = 25000000; /* 25MHz */
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	tsd->base = devm_ioremap_resource(&pdev->dev, r);
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index be3a069879c3..e3c1b93e45d1 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -23,7 +23,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -171,7 +170,6 @@ struct tegra_slink_data {
 	void __iomem				*base;
 	phys_addr_t				phys;
 	unsigned				irq;
-	u32					spi_max_frequency;
 	u32					cur_speed;
 
 	struct spi_device			*cur_spi;
@@ -761,10 +759,6 @@ static int tegra_slink_setup(struct spi_device *spi)
 		spi->mode & SPI_CPHA ? "" : "~",
 		spi->max_speed_hz);
 
-	BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
-
-	/* Set speed to the spi max fequency if spi device has not set */
-	spi->max_speed_hz = spi->max_speed_hz ? : tspi->spi_max_frequency;
 	ret = pm_runtime_get_sync(tspi->dev);
 	if (ret < 0) {
 		dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
@@ -999,15 +993,6 @@ static irqreturn_t tegra_slink_isr(int irq, void *context_data)
 	return IRQ_WAKE_THREAD;
 }
 
-static void tegra_slink_parse_dt(struct tegra_slink_data *tspi)
-{
-	struct device_node *np = tspi->dev->of_node;
-
-	if (of_property_read_u32(np, "spi-max-frequency",
-					&tspi->spi_max_frequency))
-		tspi->spi_max_frequency = 25000000; /* 25MHz */
-}
-
 static const struct tegra_slink_chip_data tegra30_spi_cdata = {
 	.cs_hold_time = true,
 };
@@ -1053,7 +1038,6 @@ static int tegra_slink_probe(struct platform_device *pdev)
 	master->unprepare_message = tegra_slink_unprepare_message;
 	master->auto_runtime_pm = true;
 	master->num_chipselect = MAX_CHIP_SELECT;
-	master->bus_num = -1;
 
 	platform_set_drvdata(pdev, master);
 	tspi = spi_master_get_devdata(master);
@@ -1062,7 +1046,9 @@ static int tegra_slink_probe(struct platform_device *pdev)
 	tspi->chip_data = cdata;
 	spin_lock_init(&tspi->lock);
 
-	tegra_slink_parse_dt(tspi);
+	if (of_property_read_u32(tspi->dev->of_node, "spi-max-frequency",
+				 &master->max_speed_hz))
+		master->max_speed_hz = 25000000; /* 25MHz */
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 3d09265b5133..49ddfc7f12b1 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -429,13 +429,13 @@ static int ti_qspi_probe(struct platform_device *pdev)
 
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD;
 
-	master->bus_num = -1;
 	master->flags = SPI_MASTER_HALF_DUPLEX;
 	master->setup = ti_qspi_setup;
 	master->auto_runtime_pm = true;
 	master->transfer_one_message = ti_qspi_start_transfer_one;
 	master->dev.of_node = pdev->dev.of_node;
-	master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
+				     SPI_BPW_MASK(8);
 
 	if (!of_property_read_u32(np, "num-cs", &num_cs))
 		master->num_chipselect = num_cs;
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 2e7f38c7a961..3540d5215217 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -464,20 +464,6 @@ static void pch_spi_reset(struct spi_master *master)
 	pch_spi_writereg(master, PCH_SRST, 0x0);
 }
 
-static int pch_spi_setup(struct spi_device *pspi)
-{
-	/* Check baud rate setting */
-	/* if baud rate of chip is greater than
-	   max we can support,return error */
-	if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
-		pspi->max_speed_hz = PCH_MAX_BAUDRATE;
-
-	dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
-		(pspi->mode) & (SPI_CPOL | SPI_CPHA));
-
-	return 0;
-}
-
 static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 {
 
@@ -486,23 +472,6 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 	int retval;
 	unsigned long flags;
 
-	/* validate spi message and baud rate */
-	if (unlikely(list_empty(&pmsg->transfers) == 1)) {
-		dev_err(&pspi->dev, "%s list empty\n", __func__);
-		retval = -EINVAL;
-		goto err_out;
-	}
-
-	if (unlikely(pspi->max_speed_hz == 0)) {
-		dev_err(&pspi->dev, "%s pch_spi_transfer maxspeed=%d\n",
-			__func__, pspi->max_speed_hz);
-		retval = -EINVAL;
-		goto err_out;
-	}
-
-	dev_dbg(&pspi->dev,
-		"%s Transfer List not empty. Transfer Speed is set.\n", __func__);
-
 	spin_lock_irqsave(&data->lock, flags);
 	/* validate Tx/Rx buffers and Transfer length */
 	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
@@ -523,10 +492,6 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 		dev_dbg(&pspi->dev,
 			"%s Tx/Rx buffer valid. Transfer length valid\n",
 			__func__);
-
-		/* if baud rate has been specified validate the same */
-		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
-			transfer->speed_hz = PCH_MAX_BAUDRATE;
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 
@@ -915,7 +880,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
 	/* Set Tx DMA */
 	param = &dma->param_tx;
 	param->dma_dev = &dma_dev->dev;
-	param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
+	param->chan_id = data->ch * 2; /* Tx = 0, 2 */;
 	param->tx_reg = data->io_base_addr + PCH_SPDWR;
 	param->width = width;
 	chan = dma_request_channel(mask, pch_spi_filter, param);
@@ -930,7 +895,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
 	/* Set Rx DMA */
 	param = &dma->param_rx;
 	param->dma_dev = &dma_dev->dev;
-	param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
+	param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */;
 	param->rx_reg = data->io_base_addr + PCH_SPDRR;
 	param->width = width;
 	chan = dma_request_channel(mask, pch_spi_filter, param);
@@ -1151,8 +1116,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
 	dma->nent = num;
 	dma->desc_tx = desc_tx;
 
-	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
-		"0x2 to SSNXCR\n", __func__);
+	dev_dbg(&data->master->dev, "%s:Pulling down SSN low - writing 0x2 to SSNXCR\n", __func__);
 
 	spin_lock_irqsave(&data->lock, flags);
 	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
@@ -1418,10 +1382,10 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
 
 	/* initialize members of SPI master */
 	master->num_chipselect = PCH_MAX_CS;
-	master->setup = pch_spi_setup;
 	master->transfer = pch_spi_transfer;
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
 	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
+	master->max_speed_hz = PCH_MAX_BAUDRATE;
 
 	data->board_dat = board_dat;
 	data->plat_dev = plat_dev;
@@ -1452,6 +1416,11 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
 
 	pch_spi_set_master_mode(master);
 
+	if (use_dma) {
+		dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+		pch_alloc_dma_buf(board_dat, data);
+	}
+
 	ret = spi_register_master(master);
 	if (ret != 0) {
 		dev_err(&plat_dev->dev,
@@ -1459,14 +1428,10 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
 		goto err_spi_register_master;
 	}
 
-	if (use_dma) {
-		dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
-		pch_alloc_dma_buf(board_dat, data);
-	}
-
 	return 0;
 
 err_spi_register_master:
+	pch_free_dma_buf(board_dat, data);
 	free_irq(board_dat->pdev->irq, data);
 err_request_irq:
 	pch_spi_free_resources(board_dat, data);
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
index 6191ced514b2..820b499816f8 100644
--- a/drivers/spi/spi-txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -80,7 +80,6 @@ struct txx9spi {
 	void __iomem *membase;
 	int baseclk;
 	struct clk *clk;
-	u32 max_speed_hz, min_speed_hz;
 	int last_chipselect;
 	int last_chipselect_val;
 };
@@ -117,9 +116,7 @@ static int txx9spi_setup(struct spi_device *spi)
 {
 	struct txx9spi *c = spi_master_get_devdata(spi->master);
 
-	if (!spi->max_speed_hz
-			|| spi->max_speed_hz > c->max_speed_hz
-			|| spi->max_speed_hz < c->min_speed_hz)
+	if (!spi->max_speed_hz)
 		return -EINVAL;
 
 	if (gpio_direction_output(spi->chip_select,
@@ -309,15 +306,8 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
 
 	/* check each transfer's parameters */
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
-		u8 bits_per_word = t->bits_per_word;
-
 		if (!t->tx_buf && !t->rx_buf && t->len)
 			return -EINVAL;
-		if (t->len & ((bits_per_word >> 3) - 1))
-			return -EINVAL;
-		if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
-			return -EINVAL;
 	}
 
 	spin_lock_irqsave(&c->lock, flags);
@@ -360,17 +350,12 @@ static int txx9spi_probe(struct platform_device *dev)
 		goto exit;
 	}
 	c->baseclk = clk_get_rate(c->clk);
-	c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
-	c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
+	master->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
+	master->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res)
-		goto exit_busy;
-	if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
-				     "spi_txx9"))
-		goto exit_busy;
-	c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
-	if (!c->membase)
+	c->membase = devm_ioremap_resource(&dev->dev, res);
+	if (IS_ERR(c->membase))
 		goto exit_busy;
 
 	/* enter config mode */
diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c
index 24c40b13dab1..350a76b7e8d4 100644
--- a/drivers/spi/spi-xcomm.c
+++ b/drivers/spi/spi-xcomm.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 6d4ce4615163..a3b0b9944bf0 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -88,10 +87,10 @@ struct xilinx_spi {
 	const u8 *tx_ptr;	/* pointer in the Rx buffer */
 	int remaining_bytes;	/* the number of bytes left to transfer */
 	u8 bits_per_word;
-	unsigned int (*read_fn) (void __iomem *);
-	void (*write_fn) (u32, void __iomem *);
-	void (*tx_fn) (struct xilinx_spi *);
-	void (*rx_fn) (struct xilinx_spi *);
+	unsigned int (*read_fn)(void __iomem *);
+	void (*write_fn)(u32, void __iomem *);
+	void (*tx_fn)(struct xilinx_spi *);
+	void (*rx_fn)(struct xilinx_spi *);
 };
 
 static void xspi_write32(u32 val, void __iomem *addr)
@@ -209,26 +208,11 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
 }
 
 /* spi_bitbang requires custom setup_transfer() to be defined if there is a
- * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
- * supports 8 or 16 bits per word which cannot be changed in software.
- * SPI clock can't be changed in software either.
- * Check for correct bits per word. Chip select delay calculations could be
- * added here as soon as bitbang_work() can be made aware of the delay value.
+ * custom txrx_bufs().
  */
 static int xilinx_spi_setup_transfer(struct spi_device *spi,
 		struct spi_transfer *t)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	u8 bits_per_word;
-
-	bits_per_word = (t && t->bits_per_word)
-			 ? t->bits_per_word : spi->bits_per_word;
-	if (bits_per_word != xspi->bits_per_word) {
-		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-			__func__, bits_per_word);
-		return -EINVAL;
-	}
-
 	return 0;
 }
 
@@ -407,6 +391,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 		xspi->write_fn = xspi_write32_be;
 	}
 
+	master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
 	xspi->bits_per_word = bits_per_word;
 	if (xspi->bits_per_word == 8) {
 		xspi->tx_fn = xspi_tx8;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index d0b28bba38be..454a523cda60 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -24,6 +24,8 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/cache.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
@@ -255,13 +257,12 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
 static int spi_drv_probe(struct device *dev)
 {
 	const struct spi_driver		*sdrv = to_spi_driver(dev->driver);
-	struct spi_device		*spi = to_spi_device(dev);
 	int ret;
 
-	acpi_dev_pm_attach(&spi->dev, true);
-	ret = sdrv->probe(spi);
+	acpi_dev_pm_attach(dev, true);
+	ret = sdrv->probe(to_spi_device(dev));
 	if (ret)
-		acpi_dev_pm_detach(&spi->dev, true);
+		acpi_dev_pm_detach(dev, true);
 
 	return ret;
 }
@@ -269,11 +270,10 @@ static int spi_drv_probe(struct device *dev)
 static int spi_drv_remove(struct device *dev)
 {
 	const struct spi_driver		*sdrv = to_spi_driver(dev->driver);
-	struct spi_device		*spi = to_spi_device(dev);
 	int ret;
 
-	ret = sdrv->remove(spi);
-	acpi_dev_pm_detach(&spi->dev, true);
+	ret = sdrv->remove(to_spi_device(dev));
+	acpi_dev_pm_detach(dev, true);
 
 	return ret;
 }
@@ -580,6 +580,169 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
 		spi->master->set_cs(spi, !enable);
 }
 
+static int spi_map_buf(struct spi_master *master, struct device *dev,
+		       struct sg_table *sgt, void *buf, size_t len,
+		       enum dma_data_direction dir)
+{
+	const bool vmalloced_buf = is_vmalloc_addr(buf);
+	const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len;
+	const int sgs = DIV_ROUND_UP(len, desc_len);
+	struct page *vm_page;
+	void *sg_buf;
+	size_t min;
+	int i, ret;
+
+	ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
+	if (ret != 0)
+		return ret;
+
+	for (i = 0; i < sgs; i++) {
+		min = min_t(size_t, len, desc_len);
+
+		if (vmalloced_buf) {
+			vm_page = vmalloc_to_page(buf);
+			if (!vm_page) {
+				sg_free_table(sgt);
+				return -ENOMEM;
+			}
+			sg_buf = page_address(vm_page) +
+				((size_t)buf & ~PAGE_MASK);
+		} else {
+			sg_buf = buf;
+		}
+
+		sg_set_buf(&sgt->sgl[i], sg_buf, min);
+
+		buf += min;
+		len -= min;
+	}
+
+	ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
+	if (ret < 0) {
+		sg_free_table(sgt);
+		return ret;
+	}
+
+	sgt->nents = ret;
+
+	return 0;
+}
+
+static void spi_unmap_buf(struct spi_master *master, struct device *dev,
+			  struct sg_table *sgt, enum dma_data_direction dir)
+{
+	if (sgt->orig_nents) {
+		dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
+		sg_free_table(sgt);
+	}
+}
+
+static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
+{
+	struct device *tx_dev, *rx_dev;
+	struct spi_transfer *xfer;
+	void *tmp;
+	unsigned int max_tx, max_rx;
+	int ret;
+
+	if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) {
+		max_tx = 0;
+		max_rx = 0;
+
+		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+			if ((master->flags & SPI_MASTER_MUST_TX) &&
+			    !xfer->tx_buf)
+				max_tx = max(xfer->len, max_tx);
+			if ((master->flags & SPI_MASTER_MUST_RX) &&
+			    !xfer->rx_buf)
+				max_rx = max(xfer->len, max_rx);
+		}
+
+		if (max_tx) {
+			tmp = krealloc(master->dummy_tx, max_tx,
+				       GFP_KERNEL | GFP_DMA);
+			if (!tmp)
+				return -ENOMEM;
+			master->dummy_tx = tmp;
+			memset(tmp, 0, max_tx);
+		}
+
+		if (max_rx) {
+			tmp = krealloc(master->dummy_rx, max_rx,
+				       GFP_KERNEL | GFP_DMA);
+			if (!tmp)
+				return -ENOMEM;
+			master->dummy_rx = tmp;
+		}
+
+		if (max_tx || max_rx) {
+			list_for_each_entry(xfer, &msg->transfers,
+					    transfer_list) {
+				if (!xfer->tx_buf)
+					xfer->tx_buf = master->dummy_tx;
+				if (!xfer->rx_buf)
+					xfer->rx_buf = master->dummy_rx;
+			}
+		}
+	}
+
+	if (!master->can_dma)
+		return 0;
+
+	tx_dev = &master->dma_tx->dev->device;
+	rx_dev = &master->dma_rx->dev->device;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (!master->can_dma(master, msg->spi, xfer))
+			continue;
+
+		if (xfer->tx_buf != NULL) {
+			ret = spi_map_buf(master, tx_dev, &xfer->tx_sg,
+					  (void *)xfer->tx_buf, xfer->len,
+					  DMA_TO_DEVICE);
+			if (ret != 0)
+				return ret;
+		}
+
+		if (xfer->rx_buf != NULL) {
+			ret = spi_map_buf(master, rx_dev, &xfer->rx_sg,
+					  xfer->rx_buf, xfer->len,
+					  DMA_FROM_DEVICE);
+			if (ret != 0) {
+				spi_unmap_buf(master, tx_dev, &xfer->tx_sg,
+					      DMA_TO_DEVICE);
+				return ret;
+			}
+		}
+	}
+
+	master->cur_msg_mapped = true;
+
+	return 0;
+}
+
+static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
+{
+	struct spi_transfer *xfer;
+	struct device *tx_dev, *rx_dev;
+
+	if (!master->cur_msg_mapped || !master->can_dma)
+		return 0;
+
+	tx_dev = &master->dma_tx->dev->device;
+	rx_dev = &master->dma_rx->dev->device;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (!master->can_dma(master, msg->spi, xfer))
+			continue;
+
+		spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
+		spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
+	}
+
+	return 0;
+}
+
 /*
  * spi_transfer_one_message - Default implementation of transfer_one_message()
  *
@@ -594,6 +757,7 @@ static int spi_transfer_one_message(struct spi_master *master,
 	bool cur_cs = true;
 	bool keep_cs = false;
 	int ret = 0;
+	int ms = 1;
 
 	spi_set_cs(msg->spi, true);
 
@@ -611,7 +775,16 @@ static int spi_transfer_one_message(struct spi_master *master,
 
 		if (ret > 0) {
 			ret = 0;
-			wait_for_completion(&master->xfer_completion);
+			ms = xfer->len * 8 * 1000 / xfer->speed_hz;
+			ms += 10; /* some tolerance */
+
+			ms = wait_for_completion_timeout(&master->xfer_completion,
+							 msecs_to_jiffies(ms));
+		}
+
+		if (ms == 0) {
+			dev_err(&msg->spi->dev, "SPI transfer timed out\n");
+			msg->status = -ETIMEDOUT;
 		}
 
 		trace_spi_transfer_stop(msg, xfer);
@@ -686,6 +859,10 @@ static void spi_pump_messages(struct kthread_work *work)
 		}
 		master->busy = false;
 		spin_unlock_irqrestore(&master->queue_lock, flags);
+		kfree(master->dummy_rx);
+		master->dummy_rx = NULL;
+		kfree(master->dummy_tx);
+		master->dummy_tx = NULL;
 		if (master->unprepare_transfer_hardware &&
 		    master->unprepare_transfer_hardware(master))
 			dev_err(&master->dev,
@@ -752,6 +929,13 @@ static void spi_pump_messages(struct kthread_work *work)
 		master->cur_msg_prepared = true;
 	}
 
+	ret = spi_map_msg(master, master->cur_msg);
+	if (ret) {
+		master->cur_msg->status = ret;
+		spi_finalize_current_message(master);
+		return;
+	}
+
 	ret = master->transfer_one_message(master, master->cur_msg);
 	if (ret) {
 		dev_err(&master->dev,
@@ -839,6 +1023,8 @@ void spi_finalize_current_message(struct spi_master *master)
 	queue_kthread_work(&master->kworker, &master->pump_messages);
 	spin_unlock_irqrestore(&master->queue_lock, flags);
 
+	spi_unmap_msg(master, mesg);
+
 	if (master->cur_msg_prepared && master->unprepare_message) {
 		ret = master->unprepare_message(master, mesg);
 		if (ret) {
@@ -892,7 +1078,7 @@ static int spi_stop_queue(struct spi_master *master)
 	 */
 	while ((!list_empty(&master->queue) || master->busy) && limit--) {
 		spin_unlock_irqrestore(&master->queue_lock, flags);
-		msleep(10);
+		usleep_range(10000, 11000);
 		spin_lock_irqsave(&master->queue_lock, flags);
 	}
 
@@ -1372,6 +1558,8 @@ int spi_register_master(struct spi_master *master)
 	mutex_init(&master->bus_lock_mutex);
 	master->bus_lock_flag = 0;
 	init_completion(&master->xfer_completion);
+	if (!master->max_dma_len)
+		master->max_dma_len = INT_MAX;
 
 	/* register the device, then userspace will see it.
 	 * registration fails if the bus ID is in use.
@@ -1597,6 +1785,9 @@ int spi_setup(struct spi_device *spi)
 	if (!spi->bits_per_word)
 		spi->bits_per_word = 8;
 
+	if (!spi->max_speed_hz)
+		spi->max_speed_hz = spi->master->max_speed_hz;
+
 	if (spi->master->setup)
 		status = spi->master->setup(spi);
 
@@ -1617,6 +1808,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 {
 	struct spi_master *master = spi->master;
 	struct spi_transfer *xfer;
+	int w_size;
 
 	if (list_empty(&message->transfers))
 		return -EINVAL;
@@ -1668,6 +1860,21 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 				return -EINVAL;
 		}
 
+		/*
+		 * SPI transfer length should be multiple of SPI word size
+		 * where SPI word size should be power-of-two multiple
+		 */
+		if (xfer->bits_per_word <= 8)
+			w_size = 1;
+		else if (xfer->bits_per_word <= 16)
+			w_size = 2;
+		else
+			w_size = 4;
+
+		/* No partial transfers accepted */
+		if (xfer->len % w_size)
+			return -EINVAL;
+
 		if (xfer->speed_hz && master->min_speed_hz &&
 		    xfer->speed_hz < master->min_speed_hz)
 			return -EINVAL;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d7c6e36021e8..e3bc23bb5883 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
  */
 #define SPI_MODE_MASK		(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
 				| SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
-				| SPI_NO_CS | SPI_READY)
+				| SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
+				| SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
 
 struct spidev_data {
 	dev_t			devt;
@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev,
 		buf += k_tmp->len;
 
 		k_tmp->cs_change = !!u_tmp->cs_change;
+		k_tmp->tx_nbits = u_tmp->tx_nbits;
+		k_tmp->rx_nbits = u_tmp->rx_nbits;
 		k_tmp->bits_per_word = u_tmp->bits_per_word;
 		k_tmp->delay_usecs = u_tmp->delay_usecs;
 		k_tmp->speed_hz = u_tmp->speed_hz;
@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		retval = __put_user(spi->mode & SPI_MODE_MASK,
 					(__u8 __user *)arg);
 		break;
+	case SPI_IOC_RD_MODE32:
+		retval = __put_user(spi->mode & SPI_MODE_MASK,
+					(__u32 __user *)arg);
+		break;
 	case SPI_IOC_RD_LSB_FIRST:
 		retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
 					(__u8 __user *)arg);
@@ -372,9 +379,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 	/* write requests */
 	case SPI_IOC_WR_MODE:
-		retval = __get_user(tmp, (u8 __user *)arg);
+	case SPI_IOC_WR_MODE32:
+		if (cmd == SPI_IOC_WR_MODE)
+			retval = __get_user(tmp, (u8 __user *)arg);
+		else
+			retval = __get_user(tmp, (u32 __user *)arg);
 		if (retval == 0) {
-			u8	save = spi->mode;
+			u32	save = spi->mode;
 
 			if (tmp & ~SPI_MODE_MASK) {
 				retval = -EINVAL;
@@ -382,18 +393,18 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 
 			tmp |= spi->mode & ~SPI_MODE_MASK;
-			spi->mode = (u8)tmp;
+			spi->mode = (u16)tmp;
 			retval = spi_setup(spi);
 			if (retval < 0)
 				spi->mode = save;
 			else
-				dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
+				dev_dbg(&spi->dev, "spi mode %x\n", tmp);
 		}
 		break;
 	case SPI_IOC_WR_LSB_FIRST:
 		retval = __get_user(tmp, (__u8 __user *)arg);
 		if (retval == 0) {
-			u8	save = spi->mode;
+			u32	save = spi->mode;
 
 			if (tmp)
 				spi->mode |= SPI_LSB_FIRST;
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 000000000000..075bd79e1ac4
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,27 @@
+#
+# SPMI driver configuration
+#
+menuconfig SPMI
+	tristate "SPMI support"
+	help
+	  SPMI (System Power Management Interface) is a two-wire
+	  serial interface between baseband and application processors
+	  and Power Management Integrated Circuits (PMIC).
+
+if SPMI
+
+config SPMI_MSM_PMIC_ARB
+	tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
+	depends on ARM
+	depends on IRQ_DOMAIN
+	depends on ARCH_MSM || COMPILE_TEST
+	default ARCH_MSM
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in SPMI PMIC Arbiter interface on Qualcomm MSM family
+	  processors.
+
+	  This is required for communicating with Qualcomm PMICs and
+	  other devices that have the SPMI interface.
+
+endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 000000000000..fc75104a5aab
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for kernel SPMI framework.
+#
+obj-$(CONFIG_SPMI)	+= spmi.o
+
+obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
new file mode 100644
index 000000000000..246e03a18c94
--- /dev/null
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -0,0 +1,778 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 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/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+/* PMIC Arbiter configuration registers */
+#define PMIC_ARB_VERSION		0x0000
+#define PMIC_ARB_INT_EN			0x0004
+
+/* PMIC Arbiter channel registers */
+#define PMIC_ARB_CMD(N)			(0x0800 + (0x80 * (N)))
+#define PMIC_ARB_CONFIG(N)		(0x0804 + (0x80 * (N)))
+#define PMIC_ARB_STATUS(N)		(0x0808 + (0x80 * (N)))
+#define PMIC_ARB_WDATA0(N)		(0x0810 + (0x80 * (N)))
+#define PMIC_ARB_WDATA1(N)		(0x0814 + (0x80 * (N)))
+#define PMIC_ARB_RDATA0(N)		(0x0818 + (0x80 * (N)))
+#define PMIC_ARB_RDATA1(N)		(0x081C + (0x80 * (N)))
+
+/* Interrupt Controller */
+#define SPMI_PIC_OWNER_ACC_STATUS(M, N)	(0x0000 + ((32 * (M)) + (4 * (N))))
+#define SPMI_PIC_ACC_ENABLE(N)		(0x0200 + (4 * (N)))
+#define SPMI_PIC_IRQ_STATUS(N)		(0x0600 + (4 * (N)))
+#define SPMI_PIC_IRQ_CLEAR(N)		(0x0A00 + (4 * (N)))
+
+/* Mapping Table */
+#define SPMI_MAPPING_TABLE_REG(N)	(0x0B00 + (4 * (N)))
+#define SPMI_MAPPING_BIT_INDEX(X)	(((X) >> 18) & 0xF)
+#define SPMI_MAPPING_BIT_IS_0_FLAG(X)	(((X) >> 17) & 0x1)
+#define SPMI_MAPPING_BIT_IS_0_RESULT(X)	(((X) >> 9) & 0xFF)
+#define SPMI_MAPPING_BIT_IS_1_FLAG(X)	(((X) >> 8) & 0x1)
+#define SPMI_MAPPING_BIT_IS_1_RESULT(X)	(((X) >> 0) & 0xFF)
+
+#define SPMI_MAPPING_TABLE_LEN		255
+#define SPMI_MAPPING_TABLE_TREE_DEPTH	16	/* Maximum of 16-bits */
+
+/* Ownership Table */
+#define SPMI_OWNERSHIP_TABLE_REG(N)	(0x0700 + (4 * (N)))
+#define SPMI_OWNERSHIP_PERIPH2OWNER(X)	((X) & 0x7)
+
+/* Channel Status fields */
+enum pmic_arb_chnl_status {
+	PMIC_ARB_STATUS_DONE	= (1 << 0),
+	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
+	PMIC_ARB_STATUS_DENIED	= (1 << 2),
+	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
+};
+
+/* Command register fields */
+#define PMIC_ARB_CMD_MAX_BYTE_COUNT	8
+
+/* Command Opcodes */
+enum pmic_arb_cmd_op_code {
+	PMIC_ARB_OP_EXT_WRITEL = 0,
+	PMIC_ARB_OP_EXT_READL = 1,
+	PMIC_ARB_OP_EXT_WRITE = 2,
+	PMIC_ARB_OP_RESET = 3,
+	PMIC_ARB_OP_SLEEP = 4,
+	PMIC_ARB_OP_SHUTDOWN = 5,
+	PMIC_ARB_OP_WAKEUP = 6,
+	PMIC_ARB_OP_AUTHENTICATE = 7,
+	PMIC_ARB_OP_MSTR_READ = 8,
+	PMIC_ARB_OP_MSTR_WRITE = 9,
+	PMIC_ARB_OP_EXT_READ = 13,
+	PMIC_ARB_OP_WRITE = 14,
+	PMIC_ARB_OP_READ = 15,
+	PMIC_ARB_OP_ZERO_WRITE = 16,
+};
+
+/* Maximum number of support PMIC peripherals */
+#define PMIC_ARB_MAX_PERIPHS		256
+#define PMIC_ARB_PERIPH_ID_VALID	(1 << 15)
+#define PMIC_ARB_TIMEOUT_US		100
+#define PMIC_ARB_MAX_TRANS_BYTES	(8)
+
+#define PMIC_ARB_APID_MASK		0xFF
+#define PMIC_ARB_PPID_MASK		0xFFF
+
+/* interrupt enable bit */
+#define SPMI_PIC_ACC_ENABLE_BIT		BIT(0)
+
+/**
+ * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
+ *
+ * @base:		address of the PMIC Arbiter core registers.
+ * @intr:		address of the SPMI interrupt control registers.
+ * @cnfg:		address of the PMIC Arbiter configuration registers.
+ * @lock:		lock to synchronize accesses.
+ * @channel:		which channel to use for accesses.
+ * @irq:		PMIC ARB interrupt.
+ * @ee:			the current Execution Environment
+ * @min_apid:		minimum APID (used for bounding IRQ search)
+ * @max_apid:		maximum APID
+ * @mapping_table:	in-memory copy of PPID -> APID mapping table.
+ * @domain:		irq domain object for PMIC IRQ domain
+ * @spmic:		SPMI controller object
+ * @apid_to_ppid:	cached mapping from APID to PPID
+ */
+struct spmi_pmic_arb_dev {
+	void __iomem		*base;
+	void __iomem		*intr;
+	void __iomem		*cnfg;
+	raw_spinlock_t		lock;
+	u8			channel;
+	int			irq;
+	u8			ee;
+	u8			min_apid;
+	u8			max_apid;
+	u32			mapping_table[SPMI_MAPPING_TABLE_LEN];
+	struct irq_domain	*domain;
+	struct spmi_controller	*spmic;
+	u16			apid_to_ppid[256];
+};
+
+static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset)
+{
+	return readl_relaxed(dev->base + offset);
+}
+
+static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
+				       u32 offset, u32 val)
+{
+	writel_relaxed(val, dev->base + offset);
+}
+
+/**
+ * pa_read_data: reads pmic-arb's register and copy 1..4 bytes to buf
+ * @bc:		byte count -1. range: 0..3
+ * @reg:	register's address
+ * @buf:	output parameter, length must be bc + 1
+ */
+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = pmic_arb_base_read(dev, reg);
+	memcpy(buf, &data, (bc & 3) + 1);
+}
+
+/**
+ * pa_write_data: write 1..4 bytes from buf to pmic-arb's register
+ * @bc:		byte-count -1. range: 0..3.
+ * @reg:	register's address.
+ * @buf:	buffer to write. length must be bc + 1.
+ */
+static void
+pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = 0;
+	memcpy(&data, buf, (bc & 3) + 1);
+	pmic_arb_base_write(dev, reg, data);
+}
+
+static int pmic_arb_wait_for_done(struct spmi_controller *ctrl)
+{
+	struct spmi_pmic_arb_dev *dev = spmi_controller_get_drvdata(ctrl);
+	u32 status = 0;
+	u32 timeout = PMIC_ARB_TIMEOUT_US;
+	u32 offset = PMIC_ARB_STATUS(dev->channel);
+
+	while (timeout--) {
+		status = pmic_arb_base_read(dev, offset);
+
+		if (status & PMIC_ARB_STATUS_DONE) {
+			if (status & PMIC_ARB_STATUS_DENIED) {
+				dev_err(&ctrl->dev,
+					"%s: transaction denied (0x%x)\n",
+					__func__, status);
+				return -EPERM;
+			}
+
+			if (status & PMIC_ARB_STATUS_FAILURE) {
+				dev_err(&ctrl->dev,
+					"%s: transaction failed (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			if (status & PMIC_ARB_STATUS_DROPPED) {
+				dev_err(&ctrl->dev,
+					"%s: transaction dropped (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			return 0;
+		}
+		udelay(1);
+	}
+
+	dev_err(&ctrl->dev,
+		"%s: timeout, status 0x%x\n",
+		__func__, status);
+	return -ETIMEDOUT;
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	/* Check for valid non-data command */
+	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+		return -EINVAL;
+
+	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			     u16 addr, u8 *buf, size_t len)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u8 bc = len - 1;
+	u32 cmd;
+	int rc;
+
+	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
+		dev_err(&ctrl->dev,
+			"pmic-arb supports 1..%d bytes per trans, but %d requested",
+			PMIC_ARB_MAX_TRANS_BYTES, len);
+		return  -EINVAL;
+	}
+
+	/* Check the opcode */
+	if (opc >= 0x60 && opc <= 0x7F)
+		opc = PMIC_ARB_OP_READ;
+	else if (opc >= 0x20 && opc <= 0x2F)
+		opc = PMIC_ARB_OP_EXT_READ;
+	else if (opc >= 0x38 && opc <= 0x3F)
+		opc = PMIC_ARB_OP_EXT_READL;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	if (rc)
+		goto done;
+
+	pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel),
+		     min_t(u8, bc, 3));
+
+	if (bc > 3)
+		pa_read_data(pmic_arb, buf + 4,
+				PMIC_ARB_RDATA1(pmic_arb->channel), bc - 4);
+
+done:
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return rc;
+}
+
+static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			      u16 addr, const u8 *buf, size_t len)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u8 bc = len - 1;
+	u32 cmd;
+	int rc;
+
+	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
+		dev_err(&ctrl->dev,
+			"pmic-arb supports 1..%d bytes per trans, but:%d requested",
+			PMIC_ARB_MAX_TRANS_BYTES, len);
+		return  -EINVAL;
+	}
+
+	/* Check the opcode */
+	if (opc >= 0x40 && opc <= 0x5F)
+		opc = PMIC_ARB_OP_WRITE;
+	else if (opc >= 0x00 && opc <= 0x0F)
+		opc = PMIC_ARB_OP_EXT_WRITE;
+	else if (opc >= 0x30 && opc <= 0x37)
+		opc = PMIC_ARB_OP_EXT_WRITEL;
+	else if (opc >= 0x80 && opc <= 0xFF)
+		opc = PMIC_ARB_OP_ZERO_WRITE;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	/* Write data to FIFOs */
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel)
+							, min_t(u8, bc, 3));
+	if (bc > 3)
+		pa_write_data(pmic_arb, buf + 4,
+				PMIC_ARB_WDATA1(pmic_arb->channel), bc - 4);
+
+	/* Start the transaction */
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+enum qpnpint_regs {
+	QPNPINT_REG_RT_STS		= 0x10,
+	QPNPINT_REG_SET_TYPE		= 0x11,
+	QPNPINT_REG_POLARITY_HIGH	= 0x12,
+	QPNPINT_REG_POLARITY_LOW	= 0x13,
+	QPNPINT_REG_LATCHED_CLR		= 0x14,
+	QPNPINT_REG_EN_SET		= 0x15,
+	QPNPINT_REG_EN_CLR		= 0x16,
+	QPNPINT_REG_LATCHED_STS		= 0x18,
+};
+
+struct spmi_pmic_arb_qpnpint_type {
+	u8 type; /* 1 -> edge */
+	u8 polarity_high;
+	u8 polarity_low;
+} __packed;
+
+/* Simplified accessor functions for irqchip callbacks */
+static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
+			       size_t len)
+{
+	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	u8 sid = d->hwirq >> 24;
+	u8 per = d->hwirq >> 16;
+
+	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
+			       (per << 8) + reg, buf, len))
+		dev_err_ratelimited(&pa->spmic->dev,
+				"failed irqchip transaction on %x\n",
+				    d->irq);
+}
+
+static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
+{
+	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	u8 sid = d->hwirq >> 24;
+	u8 per = d->hwirq >> 16;
+
+	if (pmic_arb_read_cmd(pa->spmic, SPMI_CMD_EXT_READL, sid,
+			      (per << 8) + reg, buf, len))
+		dev_err_ratelimited(&pa->spmic->dev,
+				"failed irqchip transaction on %x\n",
+				    d->irq);
+}
+
+static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
+{
+	unsigned int irq;
+	u32 status;
+	int id;
+
+	status = readl_relaxed(pa->intr + SPMI_PIC_IRQ_STATUS(apid));
+	while (status) {
+		id = ffs(status) - 1;
+		status &= ~(1 << id);
+		irq = irq_find_mapping(pa->domain,
+				       pa->apid_to_ppid[apid] << 16
+				     | id << 8
+				     | apid);
+		generic_handle_irq(irq);
+	}
+}
+
+static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct spmi_pmic_arb_dev *pa = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+	void __iomem *intr = pa->intr;
+	int first = pa->min_apid >> 5;
+	int last = pa->max_apid >> 5;
+	u32 status;
+	int i, id;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = first; i <= last; ++i) {
+		status = readl_relaxed(intr +
+				       SPMI_PIC_OWNER_ACC_STATUS(pa->ee, i));
+		while (status) {
+			id = ffs(status) - 1;
+			status &= ~(1 << id);
+			periph_interrupt(pa, id + i * 32);
+		}
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static void qpnpint_irq_ack(struct irq_data *d)
+{
+	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	u8 irq  = d->hwirq >> 8;
+	u8 apid = d->hwirq;
+	unsigned long flags;
+	u8 data;
+
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	writel_relaxed(1 << irq, pa->intr + SPMI_PIC_IRQ_CLEAR(apid));
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
+
+	data = 1 << irq;
+	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
+}
+
+static void qpnpint_irq_mask(struct irq_data *d)
+{
+	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	u8 irq  = d->hwirq >> 8;
+	u8 apid = d->hwirq;
+	unsigned long flags;
+	u32 status;
+	u8 data;
+
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (status & SPMI_PIC_ACC_ENABLE_BIT) {
+		status = status & ~SPMI_PIC_ACC_ENABLE_BIT;
+		writel_relaxed(status, pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+	}
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
+
+	data = 1 << irq;
+	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
+}
+
+static void qpnpint_irq_unmask(struct irq_data *d)
+{
+	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	u8 irq  = d->hwirq >> 8;
+	u8 apid = d->hwirq;
+	unsigned long flags;
+	u32 status;
+	u8 data;
+
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (!(status & SPMI_PIC_ACC_ENABLE_BIT)) {
+		writel_relaxed(status | SPMI_PIC_ACC_ENABLE_BIT,
+				pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+	}
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
+
+	data = 1 << irq;
+	qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
+}
+
+static void qpnpint_irq_enable(struct irq_data *d)
+{
+	u8 irq  = d->hwirq >> 8;
+	u8 data;
+
+	qpnpint_irq_unmask(d);
+
+	data = 1 << irq;
+	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
+}
+
+static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct spmi_pmic_arb_qpnpint_type type;
+	u8 irq = d->hwirq >> 8;
+
+	qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
+
+	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		type.type |= 1 << irq;
+		if (flow_type & IRQF_TRIGGER_RISING)
+			type.polarity_high |= 1 << irq;
+		if (flow_type & IRQF_TRIGGER_FALLING)
+			type.polarity_low  |= 1 << irq;
+	} else {
+		if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
+		    (flow_type & (IRQF_TRIGGER_LOW)))
+			return -EINVAL;
+
+		type.type &= ~(1 << irq); /* level trig */
+		if (flow_type & IRQF_TRIGGER_HIGH)
+			type.polarity_high |= 1 << irq;
+		else
+			type.polarity_low  |= 1 << irq;
+	}
+
+	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
+	return 0;
+}
+
+static struct irq_chip pmic_arb_irqchip = {
+	.name		= "pmic_arb",
+	.irq_enable	= qpnpint_irq_enable,
+	.irq_ack	= qpnpint_irq_ack,
+	.irq_mask	= qpnpint_irq_mask,
+	.irq_unmask	= qpnpint_irq_unmask,
+	.irq_set_type	= qpnpint_irq_set_type,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND
+			| IRQCHIP_SKIP_SET_WAKE,
+};
+
+struct spmi_pmic_arb_irq_spec {
+	unsigned slave:4;
+	unsigned per:8;
+	unsigned irq:3;
+};
+
+static int search_mapping_table(struct spmi_pmic_arb_dev *pa,
+				struct spmi_pmic_arb_irq_spec *spec,
+				u8 *apid)
+{
+	u16 ppid = spec->slave << 8 | spec->per;
+	u32 *mapping_table = pa->mapping_table;
+	int index = 0, i;
+	u32 data;
+
+	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
+		data = mapping_table[index];
+
+		if (ppid & (1 << SPMI_MAPPING_BIT_INDEX(data))) {
+			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+			} else {
+				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+				return 0;
+			}
+		} else {
+			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+			} else {
+				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+				return 0;
+			}
+		}
+	}
+
+	return -ENODEV;
+}
+
+static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
+					   struct device_node *controller,
+					   const u32 *intspec,
+					   unsigned int intsize,
+					   unsigned long *out_hwirq,
+					   unsigned int *out_type)
+{
+	struct spmi_pmic_arb_dev *pa = d->host_data;
+	struct spmi_pmic_arb_irq_spec spec;
+	int err;
+	u8 apid;
+
+	dev_dbg(&pa->spmic->dev,
+		"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
+		intspec[0], intspec[1], intspec[2]);
+
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize != 4)
+		return -EINVAL;
+	if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7)
+		return -EINVAL;
+
+	spec.slave = intspec[0];
+	spec.per   = intspec[1];
+	spec.irq   = intspec[2];
+
+	err = search_mapping_table(pa, &spec, &apid);
+	if (err)
+		return err;
+
+	pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per;
+
+	/* Keep track of {max,min}_apid for bounding search during interrupt */
+	if (apid > pa->max_apid)
+		pa->max_apid = apid;
+	if (apid < pa->min_apid)
+		pa->min_apid = apid;
+
+	*out_hwirq = spec.slave << 24
+		   | spec.per   << 16
+		   | spec.irq   << 8
+		   | apid;
+	*out_type  = intspec[3] & IRQ_TYPE_SENSE_MASK;
+
+	dev_dbg(&pa->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
+
+	return 0;
+}
+
+static int qpnpint_irq_domain_map(struct irq_domain *d,
+				  unsigned int virq,
+				  irq_hw_number_t hwirq)
+{
+	struct spmi_pmic_arb_dev *pa = d->host_data;
+
+	dev_dbg(&pa->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
+
+	irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq);
+	irq_set_chip_data(virq, d->host_data);
+	irq_set_noprobe(virq);
+	return 0;
+}
+
+static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
+	.map	= qpnpint_irq_domain_map,
+	.xlate	= qpnpint_irq_domain_dt_translate,
+};
+
+static int spmi_pmic_arb_probe(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pa;
+	struct spmi_controller *ctrl;
+	struct resource *res;
+	u32 channel, ee;
+	int err, i;
+
+	ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa));
+	if (!ctrl)
+		return -ENOMEM;
+
+	pa = spmi_controller_get_drvdata(ctrl);
+	pa->spmic = ctrl;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
+	pa->base = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->base)) {
+		err = PTR_ERR(pa->base);
+		goto err_put_ctrl;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
+	pa->intr = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->intr)) {
+		err = PTR_ERR(pa->intr);
+		goto err_put_ctrl;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
+	pa->cnfg = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->cnfg)) {
+		err = PTR_ERR(pa->cnfg);
+		goto err_put_ctrl;
+	}
+
+	pa->irq = platform_get_irq_byname(pdev, "periph_irq");
+	if (pa->irq < 0) {
+		err = pa->irq;
+		goto err_put_ctrl;
+	}
+
+	err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
+	if (err) {
+		dev_err(&pdev->dev, "channel unspecified.\n");
+		goto err_put_ctrl;
+	}
+
+	if (channel > 5) {
+		dev_err(&pdev->dev, "invalid channel (%u) specified.\n",
+			channel);
+		goto err_put_ctrl;
+	}
+
+	pa->channel = channel;
+
+	err = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &ee);
+	if (err) {
+		dev_err(&pdev->dev, "EE unspecified.\n");
+		goto err_put_ctrl;
+	}
+
+	if (ee > 5) {
+		dev_err(&pdev->dev, "invalid EE (%u) specified\n", ee);
+		err = -EINVAL;
+		goto err_put_ctrl;
+	}
+
+	pa->ee = ee;
+
+	for (i = 0; i < ARRAY_SIZE(pa->mapping_table); ++i)
+		pa->mapping_table[i] = readl_relaxed(
+				pa->cnfg + SPMI_MAPPING_TABLE_REG(i));
+
+	/* Initialize max_apid/min_apid to the opposite bounds, during
+	 * the irq domain translation, we are sure to update these */
+	pa->max_apid = 0;
+	pa->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
+	platform_set_drvdata(pdev, ctrl);
+	raw_spin_lock_init(&pa->lock);
+
+	ctrl->cmd = pmic_arb_cmd;
+	ctrl->read_cmd = pmic_arb_read_cmd;
+	ctrl->write_cmd = pmic_arb_write_cmd;
+
+	dev_dbg(&pdev->dev, "adding irq domain\n");
+	pa->domain = irq_domain_add_tree(pdev->dev.of_node,
+					 &pmic_arb_irq_domain_ops, pa);
+	if (!pa->domain) {
+		dev_err(&pdev->dev, "unable to create irq_domain\n");
+		err = -ENOMEM;
+		goto err_put_ctrl;
+	}
+
+	irq_set_handler_data(pa->irq, pa);
+	irq_set_chained_handler(pa->irq, pmic_arb_chained_irq);
+
+	err = spmi_controller_add(ctrl);
+	if (err)
+		goto err_domain_remove;
+
+	dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n",
+		pmic_arb_base_read(pa, PMIC_ARB_VERSION));
+
+	return 0;
+
+err_domain_remove:
+	irq_set_chained_handler(pa->irq, NULL);
+	irq_set_handler_data(pa->irq, NULL);
+	irq_domain_remove(pa->domain);
+err_put_ctrl:
+	spmi_controller_put(ctrl);
+	return err;
+}
+
+static int spmi_pmic_arb_remove(struct platform_device *pdev)
+{
+	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
+	struct spmi_pmic_arb_dev *pa = spmi_controller_get_drvdata(ctrl);
+	spmi_controller_remove(ctrl);
+	irq_set_chained_handler(pa->irq, NULL);
+	irq_set_handler_data(pa->irq, NULL);
+	irq_domain_remove(pa->domain);
+	spmi_controller_put(ctrl);
+	return 0;
+}
+
+static const struct of_device_id spmi_pmic_arb_match_table[] = {
+	{ .compatible = "qcom,spmi-pmic-arb", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
+
+static struct platform_driver spmi_pmic_arb_driver = {
+	.probe		= spmi_pmic_arb_probe,
+	.remove		= spmi_pmic_arb_remove,
+	.driver		= {
+		.name	= "spmi_pmic_arb",
+		.owner	= THIS_MODULE,
+		.of_match_table = spmi_pmic_arb_match_table,
+	},
+};
+module_platform_driver(spmi_pmic_arb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:spmi_pmic_arb");
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
new file mode 100644
index 000000000000..6122c8f2f4e3
--- /dev/null
+++ b/drivers/spmi/spmi.c
@@ -0,0 +1,609 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <dt-bindings/spmi/spmi.h>
+
+static DEFINE_IDA(ctrl_ida);
+
+static void spmi_dev_release(struct device *dev)
+{
+	struct spmi_device *sdev = to_spmi_device(dev);
+	kfree(sdev);
+}
+
+static const struct device_type spmi_dev_type = {
+	.release	= spmi_dev_release,
+};
+
+static void spmi_ctrl_release(struct device *dev)
+{
+	struct spmi_controller *ctrl = to_spmi_controller(dev);
+	ida_simple_remove(&ctrl_ida, ctrl->nr);
+	kfree(ctrl);
+}
+
+static const struct device_type spmi_ctrl_type = {
+	.release	= spmi_ctrl_release,
+};
+
+#ifdef CONFIG_PM_RUNTIME
+static int spmi_runtime_suspend(struct device *dev)
+{
+	struct spmi_device *sdev = to_spmi_device(dev);
+	int err;
+
+	err = pm_generic_runtime_suspend(dev);
+	if (err)
+		return err;
+
+	return spmi_command_sleep(sdev);
+}
+
+static int spmi_runtime_resume(struct device *dev)
+{
+	struct spmi_device *sdev = to_spmi_device(dev);
+	int err;
+
+	err = spmi_command_wakeup(sdev);
+	if (err)
+		return err;
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
+static const struct dev_pm_ops spmi_pm_ops = {
+	SET_RUNTIME_PM_OPS(
+		spmi_runtime_suspend,
+		spmi_runtime_resume,
+		NULL
+	)
+};
+
+static int spmi_device_match(struct device *dev, struct device_driver *drv)
+{
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (drv->name)
+		return strncmp(dev_name(dev), drv->name,
+			       SPMI_NAME_SIZE) == 0;
+
+	return 0;
+}
+
+/**
+ * spmi_device_add() - add a device previously constructed via spmi_device_alloc()
+ * @sdev:	spmi_device to be added
+ */
+int spmi_device_add(struct spmi_device *sdev)
+{
+	struct spmi_controller *ctrl = sdev->ctrl;
+	int err;
+
+	dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid);
+
+	err = device_add(&sdev->dev);
+	if (err < 0) {
+		dev_err(&sdev->dev, "Can't add %s, status %d\n",
+			dev_name(&sdev->dev), err);
+		goto err_device_add;
+	}
+
+	dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev));
+
+err_device_add:
+	return err;
+}
+EXPORT_SYMBOL_GPL(spmi_device_add);
+
+/**
+ * spmi_device_remove(): remove an SPMI device
+ * @sdev:	spmi_device to be removed
+ */
+void spmi_device_remove(struct spmi_device *sdev)
+{
+	device_unregister(&sdev->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_device_remove);
+
+static inline int
+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
+{
+	if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->cmd(ctrl, opcode, sid);
+}
+
+static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode,
+				u8 sid, u16 addr, u8 *buf, size_t len)
+{
+	if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+}
+
+static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode,
+				 u8 sid, u16 addr, const u8 *buf, size_t len)
+{
+	if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+}
+
+/**
+ * spmi_register_read() - register read
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (5-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf)
+{
+	/* 5-bit register address */
+	if (addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_READ, sdev->usid, addr,
+			     buf, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_read);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (8-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ * @len:	the request number of bytes to read (up to 16 bytes).
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
+			   size_t len)
+{
+	/* 8-bit register address, up to 16 bytes */
+	if (len == 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READ, sdev->usid, addr,
+			     buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_read);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (16-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ * @len:	the request number of bytes to read (up to 8 bytes).
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf,
+			    size_t len)
+{
+	/* 16-bit register address, up to 8 bytes */
+	if (len == 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READL, sdev->usid, addr,
+			     buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_readl);
+
+/**
+ * spmi_register_write() - register write
+ * @sdev:	SPMI device
+ * @addr:	slave register address (5-bit address).
+ * @data:	buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data)
+{
+	/* 5-bit register address */
+	if (addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_WRITE, sdev->usid, addr,
+			      &data, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_write);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @sdev:	SPMI device.
+ * @data:	the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+int spmi_register_zero_write(struct spmi_device *sdev, u8 data)
+{
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_ZERO_WRITE, sdev->usid, 0,
+			      &data, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_zero_write);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (8-bit address).
+ * @buf:	buffer containing the data to be transferred to the Slave.
+ * @len:	the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, const u8 *buf,
+			    size_t len)
+{
+	/* 8-bit register address, up to 16 bytes */
+	if (len == 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITE, sdev->usid, addr,
+			      buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_write);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (16-bit address).
+ * @buf:	buffer containing the data to be transferred to the Slave.
+ * @len:	the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, const u8 *buf,
+			     size_t len)
+{
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (len == 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITEL, sdev->usid,
+			      addr, buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_writel);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @sdev:	SPMI device.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ */
+int spmi_command_reset(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_RESET, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_reset);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ */
+int spmi_command_sleep(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_SLEEP, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_sleep);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ */
+int spmi_command_wakeup(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_WAKEUP, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_wakeup);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ */
+int spmi_command_shutdown(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_SHUTDOWN, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_shutdown);
+
+static int spmi_drv_probe(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+	struct spmi_device *sdev = to_spmi_device(dev);
+	int err;
+
+	/* Ensure the slave is in ACTIVE state */
+	err = spmi_command_wakeup(sdev);
+	if (err)
+		goto fail_wakeup;
+
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	err = sdrv->probe(sdev);
+	if (err)
+		goto fail_probe;
+
+	return 0;
+
+fail_probe:
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+fail_wakeup:
+	return err;
+}
+
+static int spmi_drv_remove(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	pm_runtime_get_sync(dev);
+	sdrv->remove(to_spmi_device(dev));
+	pm_runtime_put_noidle(dev);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+	return 0;
+}
+
+static struct bus_type spmi_bus_type = {
+	.name		= "spmi",
+	.match		= spmi_device_match,
+	.pm		= &spmi_pm_ops,
+	.probe		= spmi_drv_probe,
+	.remove		= spmi_drv_remove,
+};
+
+/**
+ * spmi_controller_alloc() - Allocate a new SPMI device
+ * @ctrl:	associated controller
+ *
+ * Caller is responsible for either calling spmi_device_add() to add the
+ * newly allocated controller, or calling spmi_device_put() to discard it.
+ */
+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl)
+{
+	struct spmi_device *sdev;
+
+	sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+	if (!sdev)
+		return NULL;
+
+	sdev->ctrl = ctrl;
+	device_initialize(&sdev->dev);
+	sdev->dev.parent = &ctrl->dev;
+	sdev->dev.bus = &spmi_bus_type;
+	sdev->dev.type = &spmi_dev_type;
+	return sdev;
+}
+EXPORT_SYMBOL_GPL(spmi_device_alloc);
+
+/**
+ * spmi_controller_alloc() - Allocate a new SPMI controller
+ * @parent:	parent device
+ * @size:	size of private data
+ *
+ * Caller is responsible for either calling spmi_controller_add() to add the
+ * newly allocated controller, or calling spmi_controller_put() to discard it.
+ * The allocated private data region may be accessed via
+ * spmi_controller_get_drvdata()
+ */
+struct spmi_controller *spmi_controller_alloc(struct device *parent,
+					      size_t size)
+{
+	struct spmi_controller *ctrl;
+	int id;
+
+	if (WARN_ON(!parent))
+		return NULL;
+
+	ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL);
+	if (!ctrl)
+		return NULL;
+
+	device_initialize(&ctrl->dev);
+	ctrl->dev.type = &spmi_ctrl_type;
+	ctrl->dev.bus = &spmi_bus_type;
+	ctrl->dev.parent = parent;
+	ctrl->dev.of_node = parent->of_node;
+	spmi_controller_set_drvdata(ctrl, &ctrl[1]);
+
+	id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		dev_err(parent,
+			"unable to allocate SPMI controller identifier.\n");
+		spmi_controller_put(ctrl);
+		return NULL;
+	}
+
+	ctrl->nr = id;
+	dev_set_name(&ctrl->dev, "spmi-%d", id);
+
+	dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id);
+	return ctrl;
+}
+EXPORT_SYMBOL_GPL(spmi_controller_alloc);
+
+static void of_spmi_register_devices(struct spmi_controller *ctrl)
+{
+	struct device_node *node;
+	int err;
+
+	if (!ctrl->dev.of_node)
+		return;
+
+	for_each_available_child_of_node(ctrl->dev.of_node, node) {
+		struct spmi_device *sdev;
+		u32 reg[2];
+
+		dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name);
+
+		err = of_property_read_u32_array(node, "reg", reg, 2);
+		if (err) {
+			dev_err(&ctrl->dev,
+				"node %s err (%d) does not have 'reg' property\n",
+				node->full_name, err);
+			continue;
+		}
+
+		if (reg[1] != SPMI_USID) {
+			dev_err(&ctrl->dev,
+				"node %s contains unsupported 'reg' entry\n",
+				node->full_name);
+			continue;
+		}
+
+		if (reg[0] >= SPMI_MAX_SLAVE_ID) {
+			dev_err(&ctrl->dev,
+				"invalid usid on node %s\n",
+				node->full_name);
+			continue;
+		}
+
+		dev_dbg(&ctrl->dev, "read usid %02x\n", reg[0]);
+
+		sdev = spmi_device_alloc(ctrl);
+		if (!sdev)
+			continue;
+
+		sdev->dev.of_node = node;
+		sdev->usid = (u8) reg[0];
+
+		err = spmi_device_add(sdev);
+		if (err) {
+			dev_err(&sdev->dev,
+				"failure adding device. status %d\n", err);
+			spmi_device_put(sdev);
+		}
+	}
+}
+
+/**
+ * spmi_controller_add() - Add an SPMI controller
+ * @ctrl:	controller to be registered.
+ *
+ * Register a controller previously allocated via spmi_controller_alloc() with
+ * the SPMI core.
+ */
+int spmi_controller_add(struct spmi_controller *ctrl)
+{
+	int ret;
+
+	/* Can't register until after driver model init */
+	if (WARN_ON(!spmi_bus_type.p))
+		return -EAGAIN;
+
+	ret = device_add(&ctrl->dev);
+	if (ret)
+		return ret;
+
+	if (IS_ENABLED(CONFIG_OF))
+		of_spmi_register_devices(ctrl);
+
+	dev_dbg(&ctrl->dev, "spmi-%d registered: dev:%p\n",
+		ctrl->nr, &ctrl->dev);
+
+	return 0;
+};
+EXPORT_SYMBOL_GPL(spmi_controller_add);
+
+/* Remove a device associated with a controller */
+static int spmi_ctrl_remove_device(struct device *dev, void *data)
+{
+	struct spmi_device *spmidev = to_spmi_device(dev);
+	if (dev->type == &spmi_dev_type)
+		spmi_device_remove(spmidev);
+	return 0;
+}
+
+/**
+ * spmi_controller_remove(): remove an SPMI controller
+ * @ctrl:	controller to remove
+ *
+ * Remove a SPMI controller.  Caller is responsible for calling
+ * spmi_controller_put() to discard the allocated controller.
+ */
+void spmi_controller_remove(struct spmi_controller *ctrl)
+{
+	int dummy;
+
+	if (!ctrl)
+		return;
+
+	dummy = device_for_each_child(&ctrl->dev, NULL,
+				      spmi_ctrl_remove_device);
+	device_del(&ctrl->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_controller_remove);
+
+/**
+ * spmi_driver_register() - Register client driver with SPMI core
+ * @sdrv:	client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is typically called from the driver's module-init function.
+ */
+int spmi_driver_register(struct spmi_driver *sdrv)
+{
+	sdrv->driver.bus = &spmi_bus_type;
+	return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(spmi_driver_register);
+
+static void __exit spmi_exit(void)
+{
+	bus_unregister(&spmi_bus_type);
+}
+module_exit(spmi_exit);
+
+static int __init spmi_init(void)
+{
+	return bus_register(&spmi_bus_type);
+}
+postcore_initcall(spmi_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPMI module");
+MODULE_ALIAS("platform:spmi");
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 99375f0a9440..d729978cc6e4 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -34,8 +34,6 @@ source "drivers/staging/winbond/Kconfig"
 
 source "drivers/staging/wlan-ng/Kconfig"
 
-source "drivers/staging/echo/Kconfig"
-
 source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/olpc_dcon/Kconfig"
@@ -82,8 +80,6 @@ source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
 
-source "drivers/staging/sm7xxfb/Kconfig"
-
 source "drivers/staging/crystalhd/Kconfig"
 
 source "drivers/staging/cxt1e1/Kconfig"
@@ -128,8 +124,6 @@ source "drivers/staging/imx-drm/Kconfig"
 
 source "drivers/staging/dgrp/Kconfig"
 
-source "drivers/staging/sb105x/Kconfig"
-
 source "drivers/staging/fwserial/Kconfig"
 
 source "drivers/staging/goldfish/Kconfig"
@@ -146,4 +140,8 @@ source "drivers/staging/dgnc/Kconfig"
 
 source "drivers/staging/dgap/Kconfig"
 
+source "drivers/staging/gs_fpgaboot/Kconfig"
+
+source "drivers/staging/nokia_h4p/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ddc3c4a5d39d..9eb4e8a7d133 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_SLICOSS)		+= slicoss/
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
 obj-$(CONFIG_W35UND)		+= winbond/
 obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
-obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon/
 obj-$(CONFIG_PANEL)		+= panel/
@@ -35,7 +34,6 @@ obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
-obj-$(CONFIG_FB_SM7XX)		+= sm7xxfb/
 obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
 obj-$(CONFIG_CXT1E1)		+= cxt1e1/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
@@ -57,7 +55,6 @@ obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
 obj-$(CONFIG_DGRP)		+= dgrp/
-obj-$(CONFIG_SB105X)		+= sb105x/
 obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_LUSTRE_FS)		+= lustre/
@@ -65,3 +62,5 @@ obj-$(CONFIG_XILLYBUS)		+= xillybus/
 obj-$(CONFIG_DGNC)			+= dgnc/
 obj-$(CONFIG_DGAP)			+= dgap/
 obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
+obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
+obj-$(CONFIG_BT_NOKIA_H4P)	+= nokia_h4p/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index b91c758883bf..99e484f845f2 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -2,7 +2,6 @@ menu "Android"
 
 config ANDROID
 	bool "Android Drivers"
-	default N
 	---help---
 	  Enable support for various drivers needed on the Android platform
 
@@ -20,6 +19,19 @@ config ANDROID_BINDER_IPC
 	  Android process, using Binder to identify, invoke and pass arguments
 	  between said processes.
 
+config ANDROID_BINDER_IPC_32BIT
+	bool
+	depends on !64BIT && ANDROID_BINDER_IPC
+	default y
+	---help---
+	  The Binder API has been changed to support both 32 and 64bit
+	  applications in a mixed environment.
+
+	  Enable this to support an old 32-bit Android user-space (v4.4 and
+	  earlier).
+
+	  Note that enabling this will break newer Android user-space.
+
 config ASHMEM
 	bool "Enable the Anonymous Shared Memory Subsystem"
 	default n
@@ -60,7 +72,6 @@ config ANDROID_TIMED_GPIO
 
 config ANDROID_LOW_MEMORY_KILLER
 	bool "Android Low Memory Killer"
-	default N
 	---help---
 	  Registers processes to be killed when memory is low
 
diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h
index 4fd32f337f9c..495b20cf3bf6 100644
--- a/drivers/staging/android/android_alarm.h
+++ b/drivers/staging/android/android_alarm.h
@@ -16,50 +16,10 @@
 #ifndef _LINUX_ANDROID_ALARM_H
 #define _LINUX_ANDROID_ALARM_H
 
-#include <linux/ioctl.h>
-#include <linux/time.h>
 #include <linux/compat.h>
+#include <linux/ioctl.h>
 
-enum android_alarm_type {
-	/* return code bit numbers or set alarm arg */
-	ANDROID_ALARM_RTC_WAKEUP,
-	ANDROID_ALARM_RTC,
-	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
-	ANDROID_ALARM_ELAPSED_REALTIME,
-	ANDROID_ALARM_SYSTEMTIME,
-
-	ANDROID_ALARM_TYPE_COUNT,
-
-	/* return code bit numbers */
-	/* ANDROID_ALARM_TIME_CHANGE = 16 */
-};
-
-enum android_alarm_return_flags {
-	ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
-	ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
-	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK =
-				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
-	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
-				1U << ANDROID_ALARM_ELAPSED_REALTIME,
-	ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
-	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
-};
-
-/* Disable alarm */
-#define ANDROID_ALARM_CLEAR(type)           _IO('a', 0 | ((type) << 4))
-
-/* Ack last alarm and wait for next */
-#define ANDROID_ALARM_WAIT                  _IO('a', 1)
-
-#define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
-/* Set alarm */
-#define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
-#define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
-#define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
-#define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
-#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
-
+#include "uapi/android_alarm.h"
 
 #ifdef CONFIG_COMPAT
 #define ANDROID_ALARM_SET_COMPAT(type)		ALARM_IOW(2, type, \
diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h
index 8dc0f0d3adf3..5abcfd7aa706 100644
--- a/drivers/staging/android/ashmem.h
+++ b/drivers/staging/android/ashmem.h
@@ -16,35 +16,7 @@
 #include <linux/ioctl.h>
 #include <linux/compat.h>
 
-#define ASHMEM_NAME_LEN		256
-
-#define ASHMEM_NAME_DEF		"dev/ashmem"
-
-/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
-#define ASHMEM_NOT_PURGED	0
-#define ASHMEM_WAS_PURGED	1
-
-/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
-#define ASHMEM_IS_UNPINNED	0
-#define ASHMEM_IS_PINNED	1
-
-struct ashmem_pin {
-	__u32 offset;	/* offset into region, in bytes, page-aligned */
-	__u32 len;	/* length forward from offset, in bytes, page-aligned */
-};
-
-#define __ASHMEMIOC		0x77
-
-#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
-#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
-#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
-#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
-#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
-#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
-#define ASHMEM_PIN		_IOW(__ASHMEMIOC, 7, struct ashmem_pin)
-#define ASHMEM_UNPIN		_IOW(__ASHMEMIOC, 8, struct ashmem_pin)
-#define ASHMEM_GET_PIN_STATUS	_IO(__ASHMEMIOC, 9)
-#define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)
+#include "uapi/ashmem.h"
 
 /* support of 32bit userspace on 64bit platforms */
 #ifdef CONFIG_COMPAT
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 1432d956769c..cfe4bc8f05cb 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -228,8 +228,8 @@ struct binder_node {
 	int internal_strong_refs;
 	int local_weak_refs;
 	int local_strong_refs;
-	void __user *ptr;
-	void __user *cookie;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
 	unsigned has_strong_ref:1;
 	unsigned pending_strong_ref:1;
 	unsigned has_weak_ref:1;
@@ -242,7 +242,7 @@ struct binder_node {
 
 struct binder_ref_death {
 	struct binder_work work;
-	void __user *cookie;
+	binder_uintptr_t cookie;
 };
 
 struct binder_ref {
@@ -515,14 +515,14 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc,
 }
 
 static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-						  void __user *user_ptr)
+						  uintptr_t user_ptr)
 {
 	struct rb_node *n = proc->allocated_buffers.rb_node;
 	struct binder_buffer *buffer;
 	struct binder_buffer *kern_ptr;
 
-	kern_ptr = user_ptr - proc->user_buffer_offset
-		- offsetof(struct binder_buffer, data);
+	kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset
+		- offsetof(struct binder_buffer, data));
 
 	while (n) {
 		buffer = rb_entry(n, struct binder_buffer, rb_node);
@@ -856,7 +856,7 @@ static void binder_free_buf(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_get_node(struct binder_proc *proc,
-					   void __user *ptr)
+					   binder_uintptr_t ptr)
 {
 	struct rb_node *n = proc->nodes.rb_node;
 	struct binder_node *node;
@@ -875,8 +875,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_new_node(struct binder_proc *proc,
-					   void __user *ptr,
-					   void __user *cookie)
+					   binder_uintptr_t ptr,
+					   binder_uintptr_t cookie)
 {
 	struct rb_node **p = &proc->nodes.rb_node;
 	struct rb_node *parent = NULL;
@@ -908,9 +908,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "%d:%d node %d u%p c%p created\n",
+		     "%d:%d node %d u%016llx c%016llx created\n",
 		     proc->pid, current->pid, node->debug_id,
-		     node->ptr, node->cookie);
+		     (u64)node->ptr, (u64)node->cookie);
 	return node;
 }
 
@@ -1226,9 +1226,9 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
 					      struct binder_buffer *buffer,
-					      size_t *failed_at)
+					      binder_size_t *failed_at)
 {
-	size_t *offp, *off_end;
+	binder_size_t *offp, *off_end;
 	int debug_id = buffer->debug_id;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1239,7 +1239,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 	if (buffer->target_node)
 		binder_dec_node(buffer->target_node, 1, 0);
 
-	offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+	offp = (binder_size_t *)(buffer->data +
+				 ALIGN(buffer->data_size, sizeof(void *)));
 	if (failed_at)
 		off_end = failed_at;
 	else
@@ -1249,8 +1250,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		if (*offp > buffer->data_size - sizeof(*fp) ||
 		    buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			pr_err("transaction release %d bad offset %zd, size %zd\n",
-			 debug_id, *offp, buffer->data_size);
+			pr_err("transaction release %d bad offset %lld, size %zd\n",
+			       debug_id, (u64)*offp, buffer->data_size);
 			continue;
 		}
 		fp = (struct flat_binder_object *)(buffer->data + *offp);
@@ -1259,13 +1260,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_BINDER: {
 			struct binder_node *node = binder_get_node(proc, fp->binder);
 			if (node == NULL) {
-				pr_err("transaction release %d bad node %p\n",
-					debug_id, fp->binder);
+				pr_err("transaction release %d bad node %016llx\n",
+				       debug_id, (u64)fp->binder);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p\n",
-				     node->debug_id, node->ptr);
+				     "        node %d u%016llx\n",
+				     node->debug_id, (u64)node->ptr);
 			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
 		} break;
 		case BINDER_TYPE_HANDLE:
@@ -1303,7 +1304,7 @@ static void binder_transaction(struct binder_proc *proc,
 {
 	struct binder_transaction *t;
 	struct binder_work *tcomplete;
-	size_t *offp, *off_end;
+	binder_size_t *offp, *off_end;
 	struct binder_proc *target_proc;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
@@ -1432,18 +1433,20 @@ static void binder_transaction(struct binder_proc *proc,
 
 	if (reply)
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_thread->pid,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
+			     (u64)tr->data.ptr.buffer,
+			     (u64)tr->data.ptr.offsets,
+			     (u64)tr->data_size, (u64)tr->offsets_size);
 	else
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_node->debug_id,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
+			     (u64)tr->data.ptr.buffer,
+			     (u64)tr->data.ptr.offsets,
+			     (u64)tr->data_size, (u64)tr->offsets_size);
 
 	if (!reply && !(tr->flags & TF_ONE_WAY))
 		t->from = thread;
@@ -1472,23 +1475,26 @@ static void binder_transaction(struct binder_proc *proc,
 	if (target_node)
 		binder_inc_node(target_node, 1, 0, NULL);
 
-	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+	offp = (binder_size_t *)(t->buffer->data +
+				 ALIGN(tr->data_size, sizeof(void *)));
 
-	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+	if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
+			   tr->data.ptr.buffer, tr->data_size)) {
 		binder_user_error("%d:%d got transaction with invalid data ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
-	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+	if (copy_from_user(offp, (const void __user *)(uintptr_t)
+			   tr->data.ptr.offsets, tr->offsets_size)) {
 		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
-	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-		binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n",
-				proc->pid, thread->pid, tr->offsets_size);
+	if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
+		binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
+				proc->pid, thread->pid, (u64)tr->offsets_size);
 		return_error = BR_FAILED_REPLY;
 		goto err_bad_offset;
 	}
@@ -1498,8 +1504,8 @@ static void binder_transaction(struct binder_proc *proc,
 		if (*offp > t->buffer->data_size - sizeof(*fp) ||
 		    t->buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
-					proc->pid, thread->pid, *offp);
+			binder_user_error("%d:%d got transaction with invalid offset, %lld\n",
+					  proc->pid, thread->pid, (u64)*offp);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_offset;
 		}
@@ -1519,10 +1525,10 @@ static void binder_transaction(struct binder_proc *proc,
 				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
 			}
 			if (fp->cookie != node->cookie) {
-				binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
 					proc->pid, thread->pid,
-					fp->binder, node->debug_id,
-					fp->cookie, node->cookie);
+					(u64)fp->binder, node->debug_id,
+					(u64)fp->cookie, (u64)node->cookie);
 				goto err_binder_get_ref_for_node_failed;
 			}
 			ref = binder_get_ref_for_node(target_proc, node);
@@ -1540,9 +1546,9 @@ static void binder_transaction(struct binder_proc *proc,
 
 			trace_binder_transaction_node_to_ref(t, node, ref);
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p -> ref %d desc %d\n",
-				     node->debug_id, node->ptr, ref->debug_id,
-				     ref->desc);
+				     "        node %d u%016llx -> ref %d desc %d\n",
+				     node->debug_id, (u64)node->ptr,
+				     ref->debug_id, ref->desc);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
@@ -1564,9 +1570,9 @@ static void binder_transaction(struct binder_proc *proc,
 				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
 				trace_binder_transaction_ref_to_node(t, ref);
 				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> node %d u%p\n",
+					     "        ref %d desc %d -> node %d u%016llx\n",
 					     ref->debug_id, ref->desc, ref->node->debug_id,
-					     ref->node->ptr);
+					     (u64)ref->node->ptr);
 			} else {
 				struct binder_ref *new_ref;
 				new_ref = binder_get_ref_for_node(target_proc, ref->node);
@@ -1682,9 +1688,9 @@ err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
 	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-		     "%d:%d transaction failed %d, size %zd-%zd\n",
+		     "%d:%d transaction failed %d, size %lld-%lld\n",
 		     proc->pid, thread->pid, return_error,
-		     tr->data_size, tr->offsets_size);
+		     (u64)tr->data_size, (u64)tr->offsets_size);
 
 	{
 		struct binder_transaction_log_entry *fe;
@@ -1702,9 +1708,11 @@ err_no_context_mgr_node:
 
 static int binder_thread_write(struct binder_proc *proc,
 			struct binder_thread *thread,
-			void __user *buffer, size_t size, size_t *consumed)
+			binder_uintptr_t binder_buffer, size_t size,
+			binder_size_t *consumed)
 {
 	uint32_t cmd;
+	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
 
@@ -1773,33 +1781,33 @@ static int binder_thread_write(struct binder_proc *proc,
 		}
 		case BC_INCREFS_DONE:
 		case BC_ACQUIRE_DONE: {
-			void __user *node_ptr;
-			void __user *cookie;
+			binder_uintptr_t node_ptr;
+			binder_uintptr_t cookie;
 			struct binder_node *node;
 
-			if (get_user(node_ptr, (void * __user *)ptr))
+			if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
-			if (get_user(cookie, (void * __user *)ptr))
+			ptr += sizeof(binder_uintptr_t);
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			node = binder_get_node(proc, node_ptr);
 			if (node == NULL) {
-				binder_user_error("%d:%d %s u%p no match\n",
+				binder_user_error("%d:%d %s u%016llx no match\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" :
 					"BC_ACQUIRE_DONE",
-					node_ptr);
+					(u64)node_ptr);
 				break;
 			}
 			if (cookie != node->cookie) {
-				binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-					node_ptr, node->debug_id,
-					cookie, node->cookie);
+					(u64)node_ptr, node->debug_id,
+					(u64)cookie, (u64)node->cookie);
 				break;
 			}
 			if (cmd == BC_ACQUIRE_DONE) {
@@ -1835,27 +1843,28 @@ static int binder_thread_write(struct binder_proc *proc,
 			return -EINVAL;
 
 		case BC_FREE_BUFFER: {
-			void __user *data_ptr;
+			binder_uintptr_t data_ptr;
 			struct binder_buffer *buffer;
 
-			if (get_user(data_ptr, (void * __user *)ptr))
+			if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 
 			buffer = binder_buffer_lookup(proc, data_ptr);
 			if (buffer == NULL) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
-					proc->pid, thread->pid, data_ptr);
+				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
+					proc->pid, thread->pid, (u64)data_ptr);
 				break;
 			}
 			if (!buffer->allow_user_free) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
-					proc->pid, thread->pid, data_ptr);
+				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
+					proc->pid, thread->pid, (u64)data_ptr);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_FREE_BUFFER,
-				     "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
-				     proc->pid, thread->pid, data_ptr, buffer->debug_id,
+				     "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
+				     proc->pid, thread->pid, (u64)data_ptr,
+				     buffer->debug_id,
 				     buffer->transaction ? "active" : "finished");
 
 			if (buffer->transaction) {
@@ -1925,16 +1934,16 @@ static int binder_thread_write(struct binder_proc *proc,
 		case BC_REQUEST_DEATH_NOTIFICATION:
 		case BC_CLEAR_DEATH_NOTIFICATION: {
 			uint32_t target;
-			void __user *cookie;
+			binder_uintptr_t cookie;
 			struct binder_ref *ref;
 			struct binder_ref_death *death;
 
 			if (get_user(target, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
-			if (get_user(cookie, (void __user * __user *)ptr))
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			ref = binder_get_ref(proc, target);
 			if (ref == NULL) {
 				binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1947,12 +1956,12 @@ static int binder_thread_write(struct binder_proc *proc,
 			}
 
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+				     "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
 				     proc->pid, thread->pid,
 				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 				     "BC_REQUEST_DEATH_NOTIFICATION" :
 				     "BC_CLEAR_DEATH_NOTIFICATION",
-				     cookie, ref->debug_id, ref->desc,
+				     (u64)cookie, ref->debug_id, ref->desc,
 				     ref->strong, ref->weak, ref->node->debug_id);
 
 			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
@@ -1990,9 +1999,10 @@ static int binder_thread_write(struct binder_proc *proc,
 				}
 				death = ref->death;
 				if (death->cookie != cookie) {
-					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
+					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",
 						proc->pid, thread->pid,
-						death->cookie, cookie);
+						(u64)death->cookie,
+						(u64)cookie);
 					break;
 				}
 				ref->death = NULL;
@@ -2012,9 +2022,9 @@ static int binder_thread_write(struct binder_proc *proc,
 		} break;
 		case BC_DEAD_BINDER_DONE: {
 			struct binder_work *w;
-			void __user *cookie;
+			binder_uintptr_t cookie;
 			struct binder_ref_death *death = NULL;
-			if (get_user(cookie, (void __user * __user *)ptr))
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 
 			ptr += sizeof(void *);
@@ -2026,11 +2036,12 @@ static int binder_thread_write(struct binder_proc *proc,
 				}
 			}
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
-				     proc->pid, thread->pid, cookie, death);
+				     "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
+				     proc->pid, thread->pid, (u64)cookie,
+				     death);
 			if (death == NULL) {
-				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
-					proc->pid, thread->pid, cookie);
+				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
+					proc->pid, thread->pid, (u64)cookie);
 				break;
 			}
 
@@ -2082,9 +2093,10 @@ static int binder_has_thread_work(struct binder_thread *thread)
 
 static int binder_thread_read(struct binder_proc *proc,
 			      struct binder_thread *thread,
-			      void  __user *buffer, size_t size,
-			      size_t *consumed, int non_block)
+			      binder_uintptr_t binder_buffer, size_t size,
+			      binder_size_t *consumed, int non_block)
 {
+	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
 
@@ -2229,32 +2241,40 @@ retry:
 				if (put_user(cmd, (uint32_t __user *)ptr))
 					return -EFAULT;
 				ptr += sizeof(uint32_t);
-				if (put_user(node->ptr, (void * __user *)ptr))
+				if (put_user(node->ptr,
+					     (binder_uintptr_t __user *)ptr))
 					return -EFAULT;
-				ptr += sizeof(void *);
-				if (put_user(node->cookie, (void * __user *)ptr))
+				ptr += sizeof(binder_uintptr_t);
+				if (put_user(node->cookie,
+					     (binder_uintptr_t __user *)ptr))
 					return -EFAULT;
-				ptr += sizeof(void *);
+				ptr += sizeof(binder_uintptr_t);
 
 				binder_stat_br(proc, thread, cmd);
 				binder_debug(BINDER_DEBUG_USER_REFS,
-					     "%d:%d %s %d u%p c%p\n",
-					     proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
+					     "%d:%d %s %d u%016llx c%016llx\n",
+					     proc->pid, thread->pid, cmd_name,
+					     node->debug_id,
+					     (u64)node->ptr, (u64)node->cookie);
 			} else {
 				list_del_init(&w->entry);
 				if (!weak && !strong) {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%p c%p deleted\n",
-						     proc->pid, thread->pid, node->debug_id,
-						     node->ptr, node->cookie);
+						     "%d:%d node %d u%016llx c%016llx deleted\n",
+						     proc->pid, thread->pid,
+						     node->debug_id,
+						     (u64)node->ptr,
+						     (u64)node->cookie);
 					rb_erase(&node->rb_node, &proc->nodes);
 					kfree(node);
 					binder_stats_deleted(BINDER_STAT_NODE);
 				} else {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%p c%p state unchanged\n",
-						     proc->pid, thread->pid, node->debug_id, node->ptr,
-						     node->cookie);
+						     "%d:%d node %d u%016llx c%016llx state unchanged\n",
+						     proc->pid, thread->pid,
+						     node->debug_id,
+						     (u64)node->ptr,
+						     (u64)node->cookie);
 				}
 			}
 		} break;
@@ -2272,17 +2292,18 @@ retry:
 			if (put_user(cmd, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
-			if (put_user(death->cookie, (void * __user *)ptr))
+			if (put_user(death->cookie,
+				     (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			binder_stat_br(proc, thread, cmd);
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "%d:%d %s %p\n",
+				     "%d:%d %s %016llx\n",
 				      proc->pid, thread->pid,
 				      cmd == BR_DEAD_BINDER ?
 				      "BR_DEAD_BINDER" :
 				      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-				      death->cookie);
+				      (u64)death->cookie);
 
 			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
 				list_del(&w->entry);
@@ -2312,8 +2333,8 @@ retry:
 				binder_set_nice(target_node->min_priority);
 			cmd = BR_TRANSACTION;
 		} else {
-			tr.target.ptr = NULL;
-			tr.cookie = NULL;
+			tr.target.ptr = 0;
+			tr.cookie = 0;
 			cmd = BR_REPLY;
 		}
 		tr.code = t->code;
@@ -2330,8 +2351,9 @@ retry:
 
 		tr.data_size = t->buffer->data_size;
 		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (void *)t->buffer->data +
-					proc->user_buffer_offset;
+		tr.data.ptr.buffer = (binder_uintptr_t)(
+					(uintptr_t)t->buffer->data +
+					proc->user_buffer_offset);
 		tr.data.ptr.offsets = tr.data.ptr.buffer +
 					ALIGN(t->buffer->data_size,
 					    sizeof(void *));
@@ -2346,14 +2368,14 @@ retry:
 		trace_binder_transaction_received(t);
 		binder_stat_br(proc, thread, cmd);
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n",
+			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
 			     "BR_REPLY",
 			     t->debug_id, t->from ? t->from->proc->pid : 0,
 			     t->from ? t->from->pid : 0, cmd,
 			     t->buffer->data_size, t->buffer->offsets_size,
-			     tr.data.ptr.buffer, tr.data.ptr.offsets);
+			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
 
 		list_del(&t->work.entry);
 		t->buffer->allow_user_free = 1;
@@ -2423,8 +2445,8 @@ static void binder_release_work(struct list_head *list)
 
 			death = container_of(w, struct binder_ref_death, work);
 			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-				"undelivered death notification, %p\n",
-				death->cookie);
+				"undelivered death notification, %016llx\n",
+				(u64)death->cookie);
 			kfree(death);
 			binder_stats_deleted(BINDER_STAT_DEATH);
 		} break;
@@ -2580,12 +2602,16 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			goto err;
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d write %zd at %016lx, read %zd at %016lx\n",
-			     proc->pid, thread->pid, bwr.write_size,
-			     bwr.write_buffer, bwr.read_size, bwr.read_buffer);
+			     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
+			     proc->pid, thread->pid,
+			     (u64)bwr.write_size, (u64)bwr.write_buffer,
+			     (u64)bwr.read_size, (u64)bwr.read_buffer);
 
 		if (bwr.write_size > 0) {
-			ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+			ret = binder_thread_write(proc, thread,
+						  bwr.write_buffer,
+						  bwr.write_size,
+						  &bwr.write_consumed);
 			trace_binder_write_done(ret);
 			if (ret < 0) {
 				bwr.read_consumed = 0;
@@ -2595,7 +2621,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 		}
 		if (bwr.read_size > 0) {
-			ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+			ret = binder_thread_read(proc, thread, bwr.read_buffer,
+						 bwr.read_size,
+						 &bwr.read_consumed,
+						 filp->f_flags & O_NONBLOCK);
 			trace_binder_read_done(ret);
 			if (!list_empty(&proc->todo))
 				wake_up_interruptible(&proc->wait);
@@ -2606,9 +2635,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d wrote %zd of %zd, read return %zd of %zd\n",
-			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
-			     bwr.read_consumed, bwr.read_size);
+			     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
+			     proc->pid, thread->pid,
+			     (u64)bwr.write_consumed, (u64)bwr.write_size,
+			     (u64)bwr.read_consumed, (u64)bwr.read_size);
 		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
 			ret = -EFAULT;
 			goto err;
@@ -2637,7 +2667,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 		} else
 			binder_context_mgr_uid = current->cred->euid;
-		binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+		binder_context_mgr_node = binder_new_node(proc, 0, 0);
 		if (binder_context_mgr_node == NULL) {
 			ret = -ENOMEM;
 			goto err;
@@ -3132,8 +3162,9 @@ static void print_binder_work(struct seq_file *m, const char *prefix,
 		break;
 	case BINDER_WORK_NODE:
 		node = container_of(w, struct binder_node, work);
-		seq_printf(m, "%snode work %d: u%p c%p\n",
-			   prefix, node->debug_id, node->ptr, node->cookie);
+		seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
+			   prefix, node->debug_id,
+			   (u64)node->ptr, (u64)node->cookie);
 		break;
 	case BINDER_WORK_DEAD_BINDER:
 		seq_printf(m, "%shas dead binder\n", prefix);
@@ -3193,8 +3224,8 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
 	hlist_for_each_entry(ref, &node->refs, node_entry)
 		count++;
 
-	seq_printf(m, "  node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
-		   node->debug_id, node->ptr, node->cookie,
+	seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d",
+		   node->debug_id, (u64)node->ptr, (u64)node->cookie,
 		   node->has_strong_ref, node->has_weak_ref,
 		   node->local_strong_refs, node->local_weak_refs,
 		   node->internal_strong_refs, count);
@@ -3496,6 +3527,7 @@ static const struct file_operations binder_fops = {
 	.owner = THIS_MODULE,
 	.poll = binder_poll,
 	.unlocked_ioctl = binder_ioctl,
+	.compat_ioctl = binder_ioctl,
 	.mmap = binder_mmap,
 	.open = binder_open,
 	.flush = binder_flush,
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
index cbe345168067..eb0834656dfe 100644
--- a/drivers/staging/android/binder.h
+++ b/drivers/staging/android/binder.h
@@ -20,311 +20,11 @@
 #ifndef _LINUX_BINDER_H
 #define _LINUX_BINDER_H
 
-#include <linux/ioctl.h>
+#ifdef CONFIG_ANDROID_BINDER_IPC_32BIT
+#define BINDER_IPC_32BIT 1
+#endif
 
-#define B_PACK_CHARS(c1, c2, c3, c4) \
-	((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
-#define B_TYPE_LARGE 0x85
-
-enum {
-	BINDER_TYPE_BINDER	= B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
-	BINDER_TYPE_WEAK_BINDER	= B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
-	BINDER_TYPE_HANDLE	= B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
-	BINDER_TYPE_WEAK_HANDLE	= B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
-	BINDER_TYPE_FD		= B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
-};
-
-enum {
-	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
-	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
-};
-
-/*
- * This is the flattened representation of a Binder object for transfer
- * between processes.  The 'offsets' supplied as part of a binder transaction
- * contains offsets into the data where these structures occur.  The Binder
- * driver takes care of re-writing the structure type and data as it moves
- * between processes.
- */
-struct flat_binder_object {
-	/* 8 bytes for large_flat_header. */
-	__u32		type;
-	__u32		flags;
-
-	/* 8 bytes of data. */
-	union {
-		void __user	*binder;	/* local object */
-		__u32	    handle;		/* remote object */
-	};
-
-	/* extra data associated with local object */
-	void __user		*cookie;
-};
-
-/*
- * On 64-bit platforms where user code may run in 32-bits the driver must
- * translate the buffer (and local binder) addresses appropriately.
- */
-
-struct binder_write_read {
-	size_t write_size;	/* bytes to write */
-	size_t write_consumed;	/* bytes consumed by driver */
-	unsigned long	write_buffer;
-	size_t read_size;	/* bytes to read */
-	size_t read_consumed;	/* bytes consumed by driver */
-	unsigned long	read_buffer;
-};
-
-/* Use with BINDER_VERSION, driver fills in fields. */
-struct binder_version {
-	/* driver protocol version -- increment with incompatible change */
-	__s32       protocol_version;
-};
-
-/* This is the current protocol version. */
-#define BINDER_CURRENT_PROTOCOL_VERSION 7
-
-#define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
-#define	BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
-#define	BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
-#define	BINDER_SET_IDLE_PRIORITY	_IOW('b', 6, __s32)
-#define	BINDER_SET_CONTEXT_MGR		_IOW('b', 7, __s32)
-#define	BINDER_THREAD_EXIT		_IOW('b', 8, __s32)
-#define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
-
-/*
- * NOTE: Two special error codes you should check for when calling
- * in to the driver are:
- *
- * EINTR -- The operation has been interupted.  This should be
- * handled by retrying the ioctl() until a different error code
- * is returned.
- *
- * ECONNREFUSED -- The driver is no longer accepting operations
- * from your process.  That is, the process is being destroyed.
- * You should handle this by exiting from your process.  Note
- * that once this error code is returned, all further calls to
- * the driver from any thread will return this same code.
- */
-
-enum transaction_flags {
-	TF_ONE_WAY	= 0x01,	/* this is a one-way call: async, no return */
-	TF_ROOT_OBJECT	= 0x04,	/* contents are the component's root object */
-	TF_STATUS_CODE	= 0x08,	/* contents are a 32-bit status code */
-	TF_ACCEPT_FDS	= 0x10,	/* allow replies with file descriptors */
-};
-
-struct binder_transaction_data {
-	/* The first two are only used for bcTRANSACTION and brTRANSACTION,
-	 * identifying the target and contents of the transaction.
-	 */
-	union {
-		__u32	handle;	/* target descriptor of command transaction */
-		void	*ptr;	/* target descriptor of return transaction */
-	} target;
-	void		*cookie;	/* target object cookie */
-	__u32		code;		/* transaction command */
-
-	/* General information about the transaction. */
-	__u32	        flags;
-	pid_t		sender_pid;
-	uid_t		sender_euid;
-	size_t		data_size;	/* number of bytes of data */
-	size_t		offsets_size;	/* number of bytes of offsets */
-
-	/* If this transaction is inline, the data immediately
-	 * follows here; otherwise, it ends with a pointer to
-	 * the data buffer.
-	 */
-	union {
-		struct {
-			/* transaction data */
-			const void __user	*buffer;
-			/* offsets from buffer to flat_binder_object structs */
-			const void __user	*offsets;
-		} ptr;
-		__u8	buf[8];
-	} data;
-};
-
-struct binder_ptr_cookie {
-	void *ptr;
-	void *cookie;
-};
-
-struct binder_pri_desc {
-	__s32 priority;
-	__u32 desc;
-};
-
-struct binder_pri_ptr_cookie {
-	__s32 priority;
-	void *ptr;
-	void *cookie;
-};
-
-enum binder_driver_return_protocol {
-	BR_ERROR = _IOR('r', 0, __s32),
-	/*
-	 * int: error code
-	 */
-
-	BR_OK = _IO('r', 1),
-	/* No parameters! */
-
-	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
-	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
-	/*
-	 * binder_transaction_data: the received command.
-	 */
-
-	BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
-	/*
-	 * not currently supported
-	 * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
-	 * Else the remote object has acquired a primary reference.
-	 */
-
-	BR_DEAD_REPLY = _IO('r', 5),
-	/*
-	 * The target of the last transaction (either a bcTRANSACTION or
-	 * a bcATTEMPT_ACQUIRE) is no longer with us.  No parameters.
-	 */
-
-	BR_TRANSACTION_COMPLETE = _IO('r', 6),
-	/*
-	 * No parameters... always refers to the last transaction requested
-	 * (including replies).  Note that this will be sent even for
-	 * asynchronous transactions.
-	 */
-
-	BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
-	BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
-	BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
-	BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
-	/*
-	 * void *:	ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
-	/*
-	 * not currently supported
-	 * int:	priority
-	 * void *: ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BR_NOOP = _IO('r', 12),
-	/*
-	 * No parameters.  Do nothing and examine the next command.  It exists
-	 * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
-	 */
-
-	BR_SPAWN_LOOPER = _IO('r', 13),
-	/*
-	 * No parameters.  The driver has determined that a process has no
-	 * threads waiting to service incoming transactions.  When a process
-	 * receives this command, it must spawn a new service thread and
-	 * register it via bcENTER_LOOPER.
-	 */
-
-	BR_FINISHED = _IO('r', 14),
-	/*
-	 * not currently supported
-	 * stop threadpool thread
-	 */
-
-	BR_DEAD_BINDER = _IOR('r', 15, void *),
-	/*
-	 * void *: cookie
-	 */
-	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
-	/*
-	 * void *: cookie
-	 */
-
-	BR_FAILED_REPLY = _IO('r', 17),
-	/*
-	 * The the last transaction (either a bcTRANSACTION or
-	 * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory).  No parameters.
-	 */
-};
-
-enum binder_driver_command_protocol {
-	BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
-	BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
-	/*
-	 * binder_transaction_data: the sent command.
-	 */
-
-	BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
-	/*
-	 * not currently supported
-	 * int:  0 if the last BR_ATTEMPT_ACQUIRE was not successful.
-	 * Else you have acquired a primary reference on the object.
-	 */
-
-	BC_FREE_BUFFER = _IOW('c', 3, void *),
-	/*
-	 * void *: ptr to transaction data received on a read
-	 */
-
-	BC_INCREFS = _IOW('c', 4, __u32),
-	BC_ACQUIRE = _IOW('c', 5, __u32),
-	BC_RELEASE = _IOW('c', 6, __u32),
-	BC_DECREFS = _IOW('c', 7, __u32),
-	/*
-	 * int:	descriptor
-	 */
-
-	BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
-	BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
-	/*
-	 * not currently supported
-	 * int: priority
-	 * int: descriptor
-	 */
-
-	BC_REGISTER_LOOPER = _IO('c', 11),
-	/*
-	 * No parameters.
-	 * Register a spawned looper thread with the device.
-	 */
-
-	BC_ENTER_LOOPER = _IO('c', 12),
-	BC_EXIT_LOOPER = _IO('c', 13),
-	/*
-	 * No parameters.
-	 * These two commands are sent as an application-level thread
-	 * enters and exits the binder loop, respectively.  They are
-	 * used so the binder can have an accurate count of the number
-	 * of looping threads it has available.
-	 */
-
-	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie
-	 */
-
-	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie
-	 */
-
-	BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
-	/*
-	 * void *: cookie
-	 */
-};
+#include "uapi/binder.h"
 
 #endif /* _LINUX_BINDER_H */
 
diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h
index 82a567c2af67..7f20f3dc8369 100644
--- a/drivers/staging/android/binder_trace.h
+++ b/drivers/staging/android/binder_trace.h
@@ -152,7 +152,7 @@ TRACE_EVENT(binder_transaction_node_to_ref,
 	TP_STRUCT__entry(
 		__field(int, debug_id)
 		__field(int, node_debug_id)
-		__field(void __user *, node_ptr)
+		__field(binder_uintptr_t, node_ptr)
 		__field(int, ref_debug_id)
 		__field(uint32_t, ref_desc)
 	),
@@ -163,8 +163,9 @@ TRACE_EVENT(binder_transaction_node_to_ref,
 		__entry->ref_debug_id = ref->debug_id;
 		__entry->ref_desc = ref->desc;
 	),
-	TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d",
-		  __entry->debug_id, __entry->node_debug_id, __entry->node_ptr,
+	TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d",
+		  __entry->debug_id, __entry->node_debug_id,
+		  (u64)__entry->node_ptr,
 		  __entry->ref_debug_id, __entry->ref_desc)
 );
 
@@ -177,7 +178,7 @@ TRACE_EVENT(binder_transaction_ref_to_node,
 		__field(int, ref_debug_id)
 		__field(uint32_t, ref_desc)
 		__field(int, node_debug_id)
-		__field(void __user *, node_ptr)
+		__field(binder_uintptr_t, node_ptr)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -186,9 +187,10 @@ TRACE_EVENT(binder_transaction_ref_to_node,
 		__entry->node_debug_id = ref->node->debug_id;
 		__entry->node_ptr = ref->node->ptr;
 	),
-	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p",
+	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx",
 		  __entry->debug_id, __entry->node_debug_id,
-		  __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr)
+		  __entry->ref_debug_id, __entry->ref_desc,
+		  (u64)__entry->node_ptr)
 );
 
 TRACE_EVENT(binder_transaction_ref_to_ref,
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 574066ff73f8..08367179a48c 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/file.h>
 #include <linux/freezer.h>
 #include <linux/fs.h>
@@ -55,10 +56,12 @@ struct ion_device {
 	struct mutex buffer_lock;
 	struct rw_semaphore lock;
 	struct plist_head heaps;
-	long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
-			      unsigned long arg);
+	long (*custom_ioctl)(struct ion_client *client, unsigned int cmd,
+			     unsigned long arg);
 	struct rb_root clients;
 	struct dentry *debug_root;
+	struct dentry *heaps_debug_root;
+	struct dentry *clients_debug_root;
 };
 
 /**
@@ -69,6 +72,8 @@ struct ion_device {
  * @idr:		an idr space for allocating handle ids
  * @lock:		lock protecting the tree of handles
  * @name:		used for debugging
+ * @display_name:	used for debugging (unique version of @name)
+ * @display_serial:	used for debugging (to make display_name unique)
  * @task:		used for debugging
  *
  * A client represents a list of buffers this client may access.
@@ -82,6 +87,8 @@ struct ion_client {
 	struct idr idr;
 	struct mutex lock;
 	const char *name;
+	char *display_name;
+	int display_serial;
 	struct task_struct *task;
 	pid_t pid;
 	struct dentry *debug_root;
@@ -429,7 +436,7 @@ static bool ion_handle_validate(struct ion_client *client,
 				struct ion_handle *handle)
 {
 	WARN_ON(!mutex_is_locked(&client->lock));
-	return (idr_find(&client->idr, handle->id) == handle);
+	return idr_find(&client->idr, handle->id) == handle;
 }
 
 static int ion_handle_add(struct ion_client *client, struct ion_handle *handle)
@@ -708,6 +715,21 @@ static const struct file_operations debug_client_fops = {
 	.release = single_release,
 };
 
+static int ion_get_client_serial(const struct rb_root *root,
+					const unsigned char *name)
+{
+	int serial = -1;
+	struct rb_node *node;
+	for (node = rb_first(root); node; node = rb_next(node)) {
+		struct ion_client *client = rb_entry(node, struct ion_client,
+						node);
+		if (strcmp(client->name, name))
+			continue;
+		serial = max(serial, client->display_serial);
+	}
+	return serial + 1;
+}
+
 struct ion_client *ion_client_create(struct ion_device *dev,
 				     const char *name)
 {
@@ -716,9 +738,13 @@ struct ion_client *ion_client_create(struct ion_device *dev,
 	struct rb_node **p;
 	struct rb_node *parent = NULL;
 	struct ion_client *entry;
-	char debug_name[64];
 	pid_t pid;
 
+	if (!name) {
+		pr_err("%s: Name cannot be null\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
 	get_task_struct(current->group_leader);
 	task_lock(current->group_leader);
 	pid = task_pid_nr(current->group_leader);
@@ -733,21 +759,27 @@ struct ion_client *ion_client_create(struct ion_device *dev,
 	task_unlock(current->group_leader);
 
 	client = kzalloc(sizeof(struct ion_client), GFP_KERNEL);
-	if (!client) {
-		if (task)
-			put_task_struct(current->group_leader);
-		return ERR_PTR(-ENOMEM);
-	}
+	if (!client)
+		goto err_put_task_struct;
 
 	client->dev = dev;
 	client->handles = RB_ROOT;
 	idr_init(&client->idr);
 	mutex_init(&client->lock);
-	client->name = name;
 	client->task = task;
 	client->pid = pid;
+	client->name = kstrdup(name, GFP_KERNEL);
+	if (!client->name)
+		goto err_free_client;
 
 	down_write(&dev->lock);
+	client->display_serial = ion_get_client_serial(&dev->clients, name);
+	client->display_name = kasprintf(
+		GFP_KERNEL, "%s-%d", name, client->display_serial);
+	if (!client->display_name) {
+		up_write(&dev->lock);
+		goto err_free_client_name;
+	}
 	p = &dev->clients.rb_node;
 	while (*p) {
 		parent = *p;
@@ -761,13 +793,28 @@ struct ion_client *ion_client_create(struct ion_device *dev,
 	rb_link_node(&client->node, parent, p);
 	rb_insert_color(&client->node, &dev->clients);
 
-	snprintf(debug_name, 64, "%u", client->pid);
-	client->debug_root = debugfs_create_file(debug_name, 0664,
-						 dev->debug_root, client,
-						 &debug_client_fops);
+	client->debug_root = debugfs_create_file(client->display_name, 0664,
+						dev->clients_debug_root,
+						client, &debug_client_fops);
+	if (!client->debug_root) {
+		char buf[256], *path;
+		path = dentry_path(dev->clients_debug_root, buf, 256);
+		pr_err("Failed to create client debugfs at %s/%s\n",
+			path, client->display_name);
+	}
+
 	up_write(&dev->lock);
 
 	return client;
+
+err_free_client_name:
+	kfree(client->name);
+err_free_client:
+	kfree(client);
+err_put_task_struct:
+	if (task)
+		put_task_struct(current->group_leader);
+	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(ion_client_create);
 
@@ -792,6 +839,8 @@ void ion_client_destroy(struct ion_client *client)
 	debugfs_remove_recursive(client->debug_root);
 	up_write(&dev->lock);
 
+	kfree(client->display_name);
+	kfree(client->name);
 	kfree(client);
 }
 EXPORT_SYMBOL(ion_client_destroy);
@@ -1017,9 +1066,7 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start,
 	mutex_lock(&buffer->lock);
 	vaddr = ion_buffer_kmap_get(buffer);
 	mutex_unlock(&buffer->lock);
-	if (IS_ERR(vaddr))
-		return PTR_ERR(vaddr);
-	return 0;
+	return PTR_ERR_OR_ZERO(vaddr);
 }
 
 static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start,
@@ -1293,9 +1340,11 @@ static int ion_open(struct inode *inode, struct file *file)
 	struct miscdevice *miscdev = file->private_data;
 	struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
 	struct ion_client *client;
+	char debug_name[64];
 
 	pr_debug("%s: %d\n", __func__, __LINE__);
-	client = ion_client_create(dev, "user");
+	snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
+	client = ion_client_create(dev, debug_name);
 	if (IS_ERR(client))
 		return PTR_ERR(client);
 	file->private_data = client;
@@ -1443,6 +1492,8 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get,
 
 void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
 {
+	struct dentry *debug_file;
+
 	if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma ||
 	    !heap->ops->unmap_dma)
 		pr_err("%s: can not add heap with invalid ops struct.\n",
@@ -1451,21 +1502,40 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
 	if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
 		ion_heap_init_deferred_free(heap);
 
+	if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink)
+		ion_heap_init_shrinker(heap);
+
 	heap->dev = dev;
 	down_write(&dev->lock);
 	/* use negative heap->id to reverse the priority -- when traversing
 	   the list later attempt higher id numbers first */
 	plist_node_init(&heap->node, -heap->id);
 	plist_add(&heap->node, &dev->heaps);
-	debugfs_create_file(heap->name, 0664, dev->debug_root, heap,
-			    &debug_heap_fops);
+	debug_file = debugfs_create_file(heap->name, 0664,
+					dev->heaps_debug_root, heap,
+					&debug_heap_fops);
+
+	if (!debug_file) {
+		char buf[256], *path;
+		path = dentry_path(dev->heaps_debug_root, buf, 256);
+		pr_err("Failed to create heap debugfs at %s/%s\n",
+			path, heap->name);
+	}
+
 #ifdef DEBUG_HEAP_SHRINKER
 	if (heap->shrinker.shrink) {
 		char debug_name[64];
 
 		snprintf(debug_name, 64, "%s_shrink", heap->name);
-		debugfs_create_file(debug_name, 0644, dev->debug_root, heap,
-				    &debug_shrink_fops);
+		debug_file = debugfs_create_file(
+			debug_name, 0644, dev->heaps_debug_root, heap,
+			&debug_shrink_fops);
+		if (!debug_file) {
+			char buf[256], *path;
+			path = dentry_path(dev->heaps_debug_root, buf, 256);
+			pr_err("Failed to create heap shrinker debugfs at %s/%s\n",
+				path, debug_name);
+		}
 	}
 #endif
 	up_write(&dev->lock);
@@ -1494,8 +1564,21 @@ struct ion_device *ion_device_create(long (*custom_ioctl)
 	}
 
 	idev->debug_root = debugfs_create_dir("ion", NULL);
-	if (!idev->debug_root)
-		pr_err("ion: failed to create debug files.\n");
+	if (!idev->debug_root) {
+		pr_err("ion: failed to create debugfs root directory.\n");
+		goto debugfs_done;
+	}
+	idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root);
+	if (!idev->heaps_debug_root) {
+		pr_err("ion: failed to create debugfs heaps directory.\n");
+		goto debugfs_done;
+	}
+	idev->clients_debug_root = debugfs_create_dir("clients",
+						idev->debug_root);
+	if (!idev->clients_debug_root)
+		pr_err("ion: failed to create debugfs clients directory.\n");
+
+debugfs_done:
 
 	idev->custom_ioctl = custom_ioctl;
 	idev->buffers = RB_ROOT;
@@ -1509,6 +1592,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl)
 void ion_device_destroy(struct ion_device *dev)
 {
 	misc_deregister(&dev->dev);
+	debugfs_remove_recursive(dev->debug_root);
 	/* XXX need to free the heaps and clients ? */
 	kfree(dev);
 }
@@ -1527,8 +1611,7 @@ void __init ion_reserve(struct ion_platform_data *data)
 						    data->heaps[i].align,
 						    MEMBLOCK_ALLOC_ANYWHERE);
 			if (!paddr) {
-				pr_err("%s: error allocating memblock for "
-				       "heap %d\n",
+				pr_err("%s: error allocating memblock for heap %d\n",
 					__func__, i);
 				continue;
 			}
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index f0f98897e4b9..ce68ecfed31f 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -135,7 +135,7 @@ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer,
 	struct device *dev = cma_heap->dev;
 	struct ion_cma_buffer_info *info = buffer->priv_virt;
 
-	dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer,
+	dev_dbg(dev, "Return buffer %p physical address %pa\n", buffer,
 		&info->handle);
 
 	*addr = info->handle;
diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c
index 01cdc8aee898..3a45e79fe444 100644
--- a/drivers/staging/android/ion/ion_dummy_driver.c
+++ b/drivers/staging/android/ion/ion_dummy_driver.c
@@ -25,13 +25,13 @@
 #include "ion.h"
 #include "ion_priv.h"
 
-struct ion_device *idev;
-struct ion_heap **heaps;
+static struct ion_device *idev;
+static struct ion_heap **heaps;
 
-void *carveout_ptr;
-void *chunk_ptr;
+static void *carveout_ptr;
+static void *chunk_ptr;
 
-struct ion_platform_heap dummy_heaps[] = {
+static struct ion_platform_heap dummy_heaps[] = {
 		{
 			.id	= ION_HEAP_TYPE_SYSTEM,
 			.type	= ION_HEAP_TYPE_SYSTEM,
@@ -58,7 +58,7 @@ struct ion_platform_heap dummy_heaps[] = {
 		},
 };
 
-struct ion_platform_data dummy_ion_pdata = {
+static struct ion_platform_data dummy_ion_pdata = {
 	.nr = ARRAY_SIZE(dummy_heaps),
 	.heaps = dummy_heaps,
 };
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index 37e64d51394c..bdc6a28ba8c9 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -178,7 +178,8 @@ size_t ion_heap_freelist_size(struct ion_heap *heap)
 	return size;
 }
 
-size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
+static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size,
+				bool skip_pools)
 {
 	struct ion_buffer *buffer;
 	size_t total_drained = 0;
@@ -197,6 +198,8 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
 					  list);
 		list_del(&buffer->list);
 		heap->free_list_size -= buffer->size;
+		if (skip_pools)
+			buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE;
 		total_drained += buffer->size;
 		spin_unlock(&heap->free_lock);
 		ion_buffer_destroy(buffer);
@@ -207,6 +210,16 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
 	return total_drained;
 }
 
+size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
+{
+	return _ion_heap_freelist_drain(heap, size, false);
+}
+
+size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size)
+{
+	return _ion_heap_freelist_drain(heap, size, true);
+}
+
 static int ion_heap_deferred_free(void *data)
 {
 	struct ion_heap *heap = data;
@@ -246,12 +259,62 @@ int ion_heap_init_deferred_free(struct ion_heap *heap)
 	if (IS_ERR(heap->task)) {
 		pr_err("%s: creating thread for deferred free failed\n",
 		       __func__);
-		return PTR_RET(heap->task);
+		return PTR_ERR_OR_ZERO(heap->task);
 	}
 	sched_setscheduler(heap->task, SCHED_IDLE, &param);
 	return 0;
 }
 
+static unsigned long ion_heap_shrink_count(struct shrinker *shrinker,
+						struct shrink_control *sc)
+{
+	struct ion_heap *heap = container_of(shrinker, struct ion_heap,
+					     shrinker);
+	int total = 0;
+
+	total = ion_heap_freelist_size(heap) / PAGE_SIZE;
+	if (heap->ops->shrink)
+		total += heap->ops->shrink(heap, sc->gfp_mask, 0);
+	return total;
+}
+
+static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
+						struct shrink_control *sc)
+{
+	struct ion_heap *heap = container_of(shrinker, struct ion_heap,
+					     shrinker);
+	int freed = 0;
+	int to_scan = sc->nr_to_scan;
+
+	if (to_scan == 0)
+		return 0;
+
+	/*
+	 * shrink the free list first, no point in zeroing the memory if we're
+	 * just going to reclaim it. Also, skip any possible page pooling.
+	 */
+	if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
+		freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) /
+				PAGE_SIZE;
+
+	to_scan -= freed;
+	if (to_scan <= 0)
+		return freed;
+
+	if (heap->ops->shrink)
+		freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan);
+	return freed;
+}
+
+void ion_heap_init_shrinker(struct ion_heap *heap)
+{
+	heap->shrinker.count_objects = ion_heap_shrink_count;
+	heap->shrinker.scan_objects = ion_heap_shrink_scan;
+	heap->shrinker.seeks = DEFAULT_SEEKS;
+	heap->shrinker.batch = 0;
+	register_shrinker(&heap->shrinker);
+}
+
 struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
 {
 	struct ion_heap *heap = NULL;
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index fa693c23681a..ecb5fc34ec5c 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -130,8 +130,7 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high)
 int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
 				int nr_to_scan)
 {
-	int nr_freed = 0;
-	int i;
+	int freed;
 	bool high;
 
 	high = !!(gfp_mask & __GFP_HIGHMEM);
@@ -139,7 +138,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
 	if (nr_to_scan == 0)
 		return ion_page_pool_total(pool, high);
 
-	for (i = 0; i < nr_to_scan; i++) {
+	for (freed = 0; freed < nr_to_scan; freed++) {
 		struct page *page;
 
 		mutex_lock(&pool->mutex);
@@ -153,10 +152,9 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
 		}
 		mutex_unlock(&pool->mutex);
 		ion_page_pool_free_pages(pool, page);
-		nr_freed += (1 << pool->order);
 	}
 
-	return nr_freed;
+	return freed;
 }
 
 struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order)
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index fc2e4fccf69d..1eba3f2076a9 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -38,6 +38,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
  * @dev:		back pointer to the ion_device
  * @heap:		back pointer to the heap the buffer came from
  * @flags:		buffer specific flags
+ * @private_flags:	internal buffer specific flags
  * @size:		size of the buffer
  * @priv_virt:		private data to the buffer representable as
  *			a void *
@@ -66,6 +67,7 @@ struct ion_buffer {
 	struct ion_device *dev;
 	struct ion_heap *heap;
 	unsigned long flags;
+	unsigned long private_flags;
 	size_t size;
 	union {
 		void *priv_virt;
@@ -98,22 +100,27 @@ void ion_buffer_destroy(struct ion_buffer *buffer);
  * @map_user		map memory to userspace
  *
  * allocate, phys, and map_user return 0 on success, -errno on error.
- * map_dma and map_kernel return pointer on success, ERR_PTR on error.
+ * map_dma and map_kernel return pointer on success, ERR_PTR on
+ * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in
+ * the buffer's private_flags when called from a shrinker. In that
+ * case, the pages being free'd must be truly free'd back to the
+ * system, not put in a page pool or otherwise cached.
  */
 struct ion_heap_ops {
-	int (*allocate) (struct ion_heap *heap,
-			 struct ion_buffer *buffer, unsigned long len,
-			 unsigned long align, unsigned long flags);
-	void (*free) (struct ion_buffer *buffer);
-	int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer,
-		     ion_phys_addr_t *addr, size_t *len);
-	struct sg_table *(*map_dma) (struct ion_heap *heap,
-					struct ion_buffer *buffer);
-	void (*unmap_dma) (struct ion_heap *heap, struct ion_buffer *buffer);
-	void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
-	void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
-	int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
-			 struct vm_area_struct *vma);
+	int (*allocate)(struct ion_heap *heap,
+			struct ion_buffer *buffer, unsigned long len,
+			unsigned long align, unsigned long flags);
+	void (*free)(struct ion_buffer *buffer);
+	int (*phys)(struct ion_heap *heap, struct ion_buffer *buffer,
+		    ion_phys_addr_t *addr, size_t *len);
+	struct sg_table * (*map_dma)(struct ion_heap *heap,
+				     struct ion_buffer *buffer);
+	void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer);
+	void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
+	void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
+	int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer,
+			struct vm_area_struct *vma);
+	int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan);
 };
 
 /**
@@ -122,6 +129,17 @@ struct ion_heap_ops {
 #define ION_HEAP_FLAG_DEFER_FREE (1 << 0)
 
 /**
+ * private flags - flags internal to ion
+ */
+/*
+ * Buffer is being freed from a shrinker function. Skip any possible
+ * heap-specific caching mechanism (e.g. page pools). Guarantees that
+ * any buffer storage that came from the system allocator will be
+ * returned to the system allocator.
+ */
+#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0)
+
+/**
  * struct ion_heap - represents a heap in the system
  * @node:		rb node to put the heap on the device's tree of heaps
  * @dev:		back pointer to the ion_device
@@ -132,10 +150,7 @@ struct ion_heap_ops {
  *			allocating.  These are specified by platform data and
  *			MUST be unique
  * @name:		used for debugging
- * @shrinker:		a shrinker for the heap, if the heap caches system
- *			memory, it must define a shrinker to return it on low
- *			memory conditions, this includes system memory cached
- *			in the deferred free lists for heaps that support it
+ * @shrinker:		a shrinker for the heap
  * @free_list:		free list head if deferred free is used
  * @free_list_size	size of the deferred free list in bytes
  * @lock:		protects the free list
@@ -219,6 +234,16 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer);
 int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
 
 /**
+ * ion_heap_init_shrinker
+ * @heap:		the heap
+ *
+ * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op
+ * this function will be called to setup a shrinker to shrink the freelists
+ * and call the heap's shrink op.
+ */
+void ion_heap_init_shrinker(struct ion_heap *heap);
+
+/**
  * ion_heap_init_deferred_free -- initialize deferred free functionality
  * @heap:		the heap
  *
@@ -250,6 +275,29 @@ void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer);
 size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size);
 
 /**
+ * ion_heap_freelist_shrink - drain the deferred free
+ *				list, skipping any heap-specific
+ *				pooling or caching mechanisms
+ *
+ * @heap:		the heap
+ * @size:		amount of memory to drain in bytes
+ *
+ * Drains the indicated amount of memory from the deferred freelist immediately.
+ * Returns the total amount freed.  The total freed may be higher depending
+ * on the size of the items in the list, or lower if there is insufficient
+ * total memory on the freelist.
+ *
+ * Unlike with @ion_heap_freelist_drain, don't put any pages back into
+ * page pools or otherwise cache the pages. Everything must be
+ * genuinely free'd back to the system. If you're free'ing from a
+ * shrinker you probably want to use this. Note that this relies on
+ * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE
+ * flag.
+ */
+size_t ion_heap_freelist_shrink(struct ion_heap *heap,
+					size_t size);
+
+/**
  * ion_heap_freelist_size - returns the size of the freelist in bytes
  * @heap:		the heap
  */
@@ -305,13 +353,8 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
  * @low_count:		number of lowmem items in the pool
  * @high_items:		list of highmem items
  * @low_items:		list of lowmem items
- * @shrinker:		a shrinker for the items
  * @mutex:		lock protecting this struct and especially the count
  *			item list
- * @alloc:		function to be used to allocate pageory when the pool
- *			is empty
- * @free:		function to be used to free pageory back to the system
- *			when the shrinker fires
  * @gfp_mask:		gfp_mask to use from alloc
  * @order:		order of pages in the pool
  * @list:		plist node for list of pools
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 9849f3963e75..c92363356ae1 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -90,7 +90,7 @@ static void free_buffer_page(struct ion_system_heap *heap,
 {
 	bool cached = ion_buffer_cached(buffer);
 
-	if (!cached) {
+	if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) {
 		struct ion_page_pool *pool = heap->pools[order_to_index(order)];
 		ion_page_pool_free(pool, page);
 	} else {
@@ -209,7 +209,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer)
 
 	/* uncached pages come from the page pools, zero them before returning
 	   for security purposes (other allocations are zerod at alloc time */
-	if (!cached)
+	if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE))
 		ion_heap_buffer_zero(buffer);
 
 	for_each_sg(table->sgl, sg, table->nents, i)
@@ -231,75 +231,34 @@ static void ion_system_heap_unmap_dma(struct ion_heap *heap,
 	return;
 }
 
-static struct ion_heap_ops system_heap_ops = {
-	.allocate = ion_system_heap_allocate,
-	.free = ion_system_heap_free,
-	.map_dma = ion_system_heap_map_dma,
-	.unmap_dma = ion_system_heap_unmap_dma,
-	.map_kernel = ion_heap_map_kernel,
-	.unmap_kernel = ion_heap_unmap_kernel,
-	.map_user = ion_heap_map_user,
-};
-
-static unsigned long ion_system_heap_shrink_count(struct shrinker *shrinker,
-				  struct shrink_control *sc)
+static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask,
+					int nr_to_scan)
 {
-	struct ion_heap *heap = container_of(shrinker, struct ion_heap,
-					     shrinker);
-	struct ion_system_heap *sys_heap = container_of(heap,
-							struct ion_system_heap,
-							heap);
+	struct ion_system_heap *sys_heap;
 	int nr_total = 0;
 	int i;
 
-	/* total number of items is whatever the page pools are holding
-	   plus whatever's in the freelist */
-	for (i = 0; i < num_orders; i++) {
-		struct ion_page_pool *pool = sys_heap->pools[i];
-		nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0);
-	}
-	nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE;
-	return nr_total;
-
-}
-
-static unsigned long ion_system_heap_shrink_scan(struct shrinker *shrinker,
-				  struct shrink_control *sc)
-{
-
-	struct ion_heap *heap = container_of(shrinker, struct ion_heap,
-					     shrinker);
-	struct ion_system_heap *sys_heap = container_of(heap,
-							struct ion_system_heap,
-							heap);
-	int nr_freed = 0;
-	int i;
-
-	if (sc->nr_to_scan == 0)
-		goto end;
-
-	/* shrink the free list first, no point in zeroing the memory if
-	   we're just going to reclaim it */
-	nr_freed += ion_heap_freelist_drain(heap, sc->nr_to_scan * PAGE_SIZE) /
-		PAGE_SIZE;
-
-	if (nr_freed >= sc->nr_to_scan)
-		goto end;
+	sys_heap = container_of(heap, struct ion_system_heap, heap);
 
 	for (i = 0; i < num_orders; i++) {
 		struct ion_page_pool *pool = sys_heap->pools[i];
-
-		nr_freed += ion_page_pool_shrink(pool, sc->gfp_mask,
-						 sc->nr_to_scan);
-		if (nr_freed >= sc->nr_to_scan)
-			break;
+		nr_total += ion_page_pool_shrink(pool, gfp_mask, nr_to_scan);
 	}
 
-end:
-	return nr_freed;
-
+	return nr_total;
 }
 
+static struct ion_heap_ops system_heap_ops = {
+	.allocate = ion_system_heap_allocate,
+	.free = ion_system_heap_free,
+	.map_dma = ion_system_heap_map_dma,
+	.unmap_dma = ion_system_heap_unmap_dma,
+	.map_kernel = ion_heap_map_kernel,
+	.unmap_kernel = ion_heap_unmap_kernel,
+	.map_user = ion_heap_map_user,
+	.shrink = ion_system_heap_shrink,
+};
+
 static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s,
 				      void *unused)
 {
@@ -347,11 +306,6 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
 		heap->pools[i] = pool;
 	}
 
-	heap->heap.shrinker.scan_objects = ion_system_heap_shrink_scan;
-	heap->heap.shrinker.count_objects = ion_system_heap_shrink_count;
-	heap->heap.shrinker.seeks = DEFAULT_SEEKS;
-	heap->heap.shrinker.batch = 0;
-	register_shrinker(&heap->heap.shrinker);
 	heap->heap.debug_show = ion_system_heap_debug_show;
 	return &heap->heap;
 err_create_pool:
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 6f094b37f1f1..b545d3d1da3e 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -88,7 +88,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
 	int array_size = ARRAY_SIZE(lowmem_adj);
 	int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
 	int other_file = global_page_state(NR_FILE_PAGES) -
-						global_page_state(NR_SHMEM);
+						global_page_state(NR_SHMEM) -
+						total_swapcache_pages();
 
 	if (lowmem_adj_size < array_size)
 		array_size = lowmem_adj_size;
@@ -159,8 +160,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
 			     selected->pid, selected->comm,
 			     selected_oom_score_adj, selected_tasksize);
 		lowmem_deathpending_timeout = jiffies + HZ;
-		send_sig(SIGKILL, selected, 0);
 		set_tsk_thread_flag(selected, TIF_MEMDIE);
+		send_sig(SIGKILL, selected, 0);
 		rem += selected_tasksize;
 	}
 
diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h
index 5aaf71d6974b..1a50669ec8a9 100644
--- a/drivers/staging/android/sw_sync.h
+++ b/drivers/staging/android/sw_sync.h
@@ -18,10 +18,9 @@
 #define _LINUX_SW_SYNC_H
 
 #include <linux/types.h>
-
-#ifdef __KERNEL__
-
+#include <linux/kconfig.h>
 #include "sync.h"
+#include "uapi/sw_sync.h"
 
 struct sw_sync_timeline {
 	struct	sync_timeline	obj;
@@ -57,19 +56,4 @@ static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj,
 }
 #endif /* IS_ENABLED(CONFIG_SW_SYNC) */
 
-#endif /* __KERNEL __ */
-
-struct sw_sync_create_fence_data {
-	__u32	value;
-	char	name[32];
-	__s32	fence; /* fd of new fence */
-};
-
-#define SW_SYNC_IOC_MAGIC	'W'
-
-#define SW_SYNC_IOC_CREATE_FENCE	_IOWR(SW_SYNC_IOC_MAGIC, 0,\
-		struct sw_sync_create_fence_data)
-#define SW_SYNC_IOC_INC			_IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
-
-
 #endif /* _LINUX_SW_SYNC_H */
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
index 62e2255b1c1e..eaf57cccf626 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -14,14 +14,14 @@
 #define _LINUX_SYNC_H
 
 #include <linux/types.h>
-#ifdef __KERNEL__
-
 #include <linux/kref.h>
 #include <linux/ktime.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 
+#include "uapi/sync.h"
+
 struct sync_timeline;
 struct sync_pt;
 struct sync_fence;
@@ -53,7 +53,7 @@ struct sync_timeline_ops {
 	const char *driver_name;
 
 	/* required */
-	struct sync_pt *(*dup)(struct sync_pt *pt);
+	struct sync_pt * (*dup)(struct sync_pt *pt);
 
 	/* required */
 	int (*has_signaled)(struct sync_pt *pt);
@@ -341,86 +341,4 @@ int sync_fence_cancel_async(struct sync_fence *fence,
  */
 int sync_fence_wait(struct sync_fence *fence, long timeout);
 
-#endif /* __KERNEL__ */
-
-/**
- * struct sync_merge_data - data passed to merge ioctl
- * @fd2:	file descriptor of second fence
- * @name:	name of new fence
- * @fence:	returns the fd of the new fence to userspace
- */
-struct sync_merge_data {
-	__s32	fd2; /* fd of second fence */
-	char	name[32]; /* name of new fence */
-	__s32	fence; /* fd on newly created fence */
-};
-
-/**
- * struct sync_pt_info - detailed sync_pt information
- * @len:		length of sync_pt_info including any driver_data
- * @obj_name:		name of parent sync_timeline
- * @driver_name:	name of driver implementing the parent
- * @status:		status of the sync_pt 0:active 1:signaled <0:error
- * @timestamp_ns:	timestamp of status change in nanoseconds
- * @driver_data:	any driver dependent data
- */
-struct sync_pt_info {
-	__u32	len;
-	char	obj_name[32];
-	char	driver_name[32];
-	__s32	status;
-	__u64	timestamp_ns;
-
-	__u8	driver_data[0];
-};
-
-/**
- * struct sync_fence_info_data - data returned from fence info ioctl
- * @len:	ioctl caller writes the size of the buffer its passing in.
- *		ioctl returns length of sync_fence_data returned to userspace
- *		including pt_info.
- * @name:	name of fence
- * @status:	status of fence. 1: signaled 0:active <0:error
- * @pt_info:	a sync_pt_info struct for every sync_pt in the fence
- */
-struct sync_fence_info_data {
-	__u32	len;
-	char	name[32];
-	__s32	status;
-
-	__u8	pt_info[0];
-};
-
-#define SYNC_IOC_MAGIC		'>'
-
-/**
- * DOC: SYNC_IOC_WAIT - wait for a fence to signal
- *
- * pass timeout in milliseconds.  Waits indefinitely timeout < 0.
- */
-#define SYNC_IOC_WAIT		_IOW(SYNC_IOC_MAGIC, 0, __s32)
-
-/**
- * DOC: SYNC_IOC_MERGE - merge two fences
- *
- * Takes a struct sync_merge_data.  Creates a new fence containing copies of
- * the sync_pts in both the calling fd and sync_merge_data.fd2.  Returns the
- * new fence's fd in sync_merge_data.fence
- */
-#define SYNC_IOC_MERGE		_IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
-
-/**
- * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
- *
- * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
- * Caller should write the size of the buffer into len.  On return, len is
- * updated to reflect the total size of the sync_fence_info_data including
- * pt_info.
- *
- * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
- * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
- */
-#define SYNC_IOC_FENCE_INFO	_IOWR(SYNC_IOC_MAGIC, 2,\
-	struct sync_fence_info_data)
-
 #endif /* _LINUX_SYNC_H */
diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h
index 905c7cc9588e..13d2ca51cbe8 100644
--- a/drivers/staging/android/timed_output.h
+++ b/drivers/staging/android/timed_output.h
@@ -20,10 +20,10 @@ struct timed_output_dev {
 	const char	*name;
 
 	/* enable the output and set the timer */
-	void	(*enable)(struct timed_output_dev *sdev, int timeout);
+	void (*enable)(struct timed_output_dev *sdev, int timeout);
 
 	/* returns the current number of milliseconds remaining on the timer */
-	int		(*get_time)(struct timed_output_dev *sdev);
+	int (*get_time)(struct timed_output_dev *sdev);
 
 	/* private data */
 	struct device	*dev;
diff --git a/drivers/staging/android/uapi/android_alarm.h b/drivers/staging/android/uapi/android_alarm.h
new file mode 100644
index 000000000000..aa013f6f5f3a
--- /dev/null
+++ b/drivers/staging/android/uapi/android_alarm.h
@@ -0,0 +1,62 @@
+/* drivers/staging/android/uapi/android_alarm.h
+ *
+ * Copyright (C) 2006-2007 Google, 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.
+ *
+ */
+
+#ifndef _UAPI_LINUX_ANDROID_ALARM_H
+#define _UAPI_LINUX_ANDROID_ALARM_H
+
+#include <linux/ioctl.h>
+#include <linux/time.h>
+
+enum android_alarm_type {
+	/* return code bit numbers or set alarm arg */
+	ANDROID_ALARM_RTC_WAKEUP,
+	ANDROID_ALARM_RTC,
+	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
+	ANDROID_ALARM_ELAPSED_REALTIME,
+	ANDROID_ALARM_SYSTEMTIME,
+
+	ANDROID_ALARM_TYPE_COUNT,
+
+	/* return code bit numbers */
+	/* ANDROID_ALARM_TIME_CHANGE = 16 */
+};
+
+enum android_alarm_return_flags {
+	ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
+	ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
+	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK =
+				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
+	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
+				1U << ANDROID_ALARM_ELAPSED_REALTIME,
+	ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
+	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
+};
+
+/* Disable alarm */
+#define ANDROID_ALARM_CLEAR(type)           _IO('a', 0 | ((type) << 4))
+
+/* Ack last alarm and wait for next */
+#define ANDROID_ALARM_WAIT                  _IO('a', 1)
+
+#define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
+/* Set alarm */
+#define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
+#define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
+#define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
+#define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
+#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
+
+#endif
diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h
new file mode 100644
index 000000000000..ba4743c71d6b
--- /dev/null
+++ b/drivers/staging/android/uapi/ashmem.h
@@ -0,0 +1,47 @@
+/*
+ * drivers/staging/android/uapi/ashmem.h
+ *
+ * Copyright 2008 Google Inc.
+ * Author: Robert Love
+ *
+ * This file is dual licensed.  It may be redistributed and/or modified
+ * under the terms of the Apache 2.0 License OR version 2 of the GNU
+ * General Public License.
+ */
+
+#ifndef _UAPI_LINUX_ASHMEM_H
+#define _UAPI_LINUX_ASHMEM_H
+
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN		256
+
+#define ASHMEM_NAME_DEF		"dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_PURGED	0
+#define ASHMEM_WAS_PURGED	1
+
+/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
+#define ASHMEM_IS_UNPINNED	0
+#define ASHMEM_IS_PINNED	1
+
+struct ashmem_pin {
+	__u32 offset;	/* offset into region, in bytes, page-aligned */
+	__u32 len;	/* length forward from offset, in bytes, page-aligned */
+};
+
+#define __ASHMEMIOC		0x77
+
+#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN		_IOW(__ASHMEMIOC, 7, struct ashmem_pin)
+#define ASHMEM_UNPIN		_IOW(__ASHMEMIOC, 8, struct ashmem_pin)
+#define ASHMEM_GET_PIN_STATUS	_IO(__ASHMEMIOC, 9)
+#define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)
+
+#endif	/* _UAPI_LINUX_ASHMEM_H */
diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h
new file mode 100644
index 000000000000..904adb7600cf
--- /dev/null
+++ b/drivers/staging/android/uapi/binder.h
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * Based on, but no longer compatible with, the original
+ * OpenBinder.org binder driver interface, which is:
+ *
+ * Copyright (c) 2005 Palmsource, 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.
+ *
+ */
+
+#ifndef _UAPI_LINUX_BINDER_H
+#define _UAPI_LINUX_BINDER_H
+
+#include <linux/ioctl.h>
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+	((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+#define B_TYPE_LARGE 0x85
+
+enum {
+	BINDER_TYPE_BINDER	= B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
+	BINDER_TYPE_WEAK_BINDER	= B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
+	BINDER_TYPE_HANDLE	= B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
+	BINDER_TYPE_WEAK_HANDLE	= B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
+	BINDER_TYPE_FD		= B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+};
+
+enum {
+	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+};
+
+#ifdef BINDER_IPC_32BIT
+typedef __u32 binder_size_t;
+typedef __u32 binder_uintptr_t;
+#else
+typedef __u64 binder_size_t;
+typedef __u64 binder_uintptr_t;
+#endif
+
+/*
+ * This is the flattened representation of a Binder object for transfer
+ * between processes.  The 'offsets' supplied as part of a binder transaction
+ * contains offsets into the data where these structures occur.  The Binder
+ * driver takes care of re-writing the structure type and data as it moves
+ * between processes.
+ */
+struct flat_binder_object {
+	/* 8 bytes for large_flat_header. */
+	__u32		type;
+	__u32		flags;
+
+	/* 8 bytes of data. */
+	union {
+		binder_uintptr_t	binder;	/* local object */
+		__u32			handle;	/* remote object */
+	};
+
+	/* extra data associated with local object */
+	binder_uintptr_t	cookie;
+};
+
+/*
+ * On 64-bit platforms where user code may run in 32-bits the driver must
+ * translate the buffer (and local binder) addresses appropriately.
+ */
+
+struct binder_write_read {
+	binder_size_t		write_size;	/* bytes to write */
+	binder_size_t		write_consumed;	/* bytes consumed by driver */
+	binder_uintptr_t	write_buffer;
+	binder_size_t		read_size;	/* bytes to read */
+	binder_size_t		read_consumed;	/* bytes consumed by driver */
+	binder_uintptr_t	read_buffer;
+};
+
+/* Use with BINDER_VERSION, driver fills in fields. */
+struct binder_version {
+	/* driver protocol version -- increment with incompatible change */
+	__s32       protocol_version;
+};
+
+/* This is the current protocol version. */
+#ifdef BINDER_IPC_32BIT
+#define BINDER_CURRENT_PROTOCOL_VERSION 7
+#else
+#define BINDER_CURRENT_PROTOCOL_VERSION 8
+#endif
+
+#define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
+#define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
+#define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
+#define BINDER_SET_IDLE_PRIORITY	_IOW('b', 6, __s32)
+#define BINDER_SET_CONTEXT_MGR		_IOW('b', 7, __s32)
+#define BINDER_THREAD_EXIT		_IOW('b', 8, __s32)
+#define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
+
+/*
+ * NOTE: Two special error codes you should check for when calling
+ * in to the driver are:
+ *
+ * EINTR -- The operation has been interupted.  This should be
+ * handled by retrying the ioctl() until a different error code
+ * is returned.
+ *
+ * ECONNREFUSED -- The driver is no longer accepting operations
+ * from your process.  That is, the process is being destroyed.
+ * You should handle this by exiting from your process.  Note
+ * that once this error code is returned, all further calls to
+ * the driver from any thread will return this same code.
+ */
+
+enum transaction_flags {
+	TF_ONE_WAY	= 0x01,	/* this is a one-way call: async, no return */
+	TF_ROOT_OBJECT	= 0x04,	/* contents are the component's root object */
+	TF_STATUS_CODE	= 0x08,	/* contents are a 32-bit status code */
+	TF_ACCEPT_FDS	= 0x10,	/* allow replies with file descriptors */
+};
+
+struct binder_transaction_data {
+	/* The first two are only used for bcTRANSACTION and brTRANSACTION,
+	 * identifying the target and contents of the transaction.
+	 */
+	union {
+		/* target descriptor of command transaction */
+		__u32	handle;
+		/* target descriptor of return transaction */
+		binder_uintptr_t ptr;
+	} target;
+	binder_uintptr_t	cookie;	/* target object cookie */
+	__u32		code;		/* transaction command */
+
+	/* General information about the transaction. */
+	__u32	        flags;
+	pid_t		sender_pid;
+	uid_t		sender_euid;
+	binder_size_t	data_size;	/* number of bytes of data */
+	binder_size_t	offsets_size;	/* number of bytes of offsets */
+
+	/* If this transaction is inline, the data immediately
+	 * follows here; otherwise, it ends with a pointer to
+	 * the data buffer.
+	 */
+	union {
+		struct {
+			/* transaction data */
+			binder_uintptr_t	buffer;
+			/* offsets from buffer to flat_binder_object structs */
+			binder_uintptr_t	offsets;
+		} ptr;
+		__u8	buf[8];
+	} data;
+};
+
+struct binder_ptr_cookie {
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+};
+
+struct binder_handle_cookie {
+	__u32 handle;
+	binder_uintptr_t cookie;
+} __attribute__((packed));
+
+struct binder_pri_desc {
+	__s32 priority;
+	__u32 desc;
+};
+
+struct binder_pri_ptr_cookie {
+	__s32 priority;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+};
+
+enum binder_driver_return_protocol {
+	BR_ERROR = _IOR('r', 0, __s32),
+	/*
+	 * int: error code
+	 */
+
+	BR_OK = _IO('r', 1),
+	/* No parameters! */
+
+	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
+	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
+	/*
+	 * binder_transaction_data: the received command.
+	 */
+
+	BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
+	/*
+	 * not currently supported
+	 * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
+	 * Else the remote object has acquired a primary reference.
+	 */
+
+	BR_DEAD_REPLY = _IO('r', 5),
+	/*
+	 * The target of the last transaction (either a bcTRANSACTION or
+	 * a bcATTEMPT_ACQUIRE) is no longer with us.  No parameters.
+	 */
+
+	BR_TRANSACTION_COMPLETE = _IO('r', 6),
+	/*
+	 * No parameters... always refers to the last transaction requested
+	 * (including replies).  Note that this will be sent even for
+	 * asynchronous transactions.
+	 */
+
+	BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
+	BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
+	BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
+	BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
+	/*
+	 * void *:	ptr to binder
+	 * void *: cookie for binder
+	 */
+
+	BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
+	/*
+	 * not currently supported
+	 * int:	priority
+	 * void *: ptr to binder
+	 * void *: cookie for binder
+	 */
+
+	BR_NOOP = _IO('r', 12),
+	/*
+	 * No parameters.  Do nothing and examine the next command.  It exists
+	 * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
+	 */
+
+	BR_SPAWN_LOOPER = _IO('r', 13),
+	/*
+	 * No parameters.  The driver has determined that a process has no
+	 * threads waiting to service incoming transactions.  When a process
+	 * receives this command, it must spawn a new service thread and
+	 * register it via bcENTER_LOOPER.
+	 */
+
+	BR_FINISHED = _IO('r', 14),
+	/*
+	 * not currently supported
+	 * stop threadpool thread
+	 */
+
+	BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
+	/*
+	 * void *: cookie
+	 */
+	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
+	/*
+	 * void *: cookie
+	 */
+
+	BR_FAILED_REPLY = _IO('r', 17),
+	/*
+	 * The the last transaction (either a bcTRANSACTION or
+	 * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory).  No parameters.
+	 */
+};
+
+enum binder_driver_command_protocol {
+	BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
+	BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
+	/*
+	 * binder_transaction_data: the sent command.
+	 */
+
+	BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
+	/*
+	 * not currently supported
+	 * int:  0 if the last BR_ATTEMPT_ACQUIRE was not successful.
+	 * Else you have acquired a primary reference on the object.
+	 */
+
+	BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
+	/*
+	 * void *: ptr to transaction data received on a read
+	 */
+
+	BC_INCREFS = _IOW('c', 4, __u32),
+	BC_ACQUIRE = _IOW('c', 5, __u32),
+	BC_RELEASE = _IOW('c', 6, __u32),
+	BC_DECREFS = _IOW('c', 7, __u32),
+	/*
+	 * int:	descriptor
+	 */
+
+	BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
+	BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
+	/*
+	 * void *: ptr to binder
+	 * void *: cookie for binder
+	 */
+
+	BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
+	/*
+	 * not currently supported
+	 * int: priority
+	 * int: descriptor
+	 */
+
+	BC_REGISTER_LOOPER = _IO('c', 11),
+	/*
+	 * No parameters.
+	 * Register a spawned looper thread with the device.
+	 */
+
+	BC_ENTER_LOOPER = _IO('c', 12),
+	BC_EXIT_LOOPER = _IO('c', 13),
+	/*
+	 * No parameters.
+	 * These two commands are sent as an application-level thread
+	 * enters and exits the binder loop, respectively.  They are
+	 * used so the binder can have an accurate count of the number
+	 * of looping threads it has available.
+	 */
+
+	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14,
+						struct binder_handle_cookie),
+	/*
+	 * int: handle
+	 * void *: cookie
+	 */
+
+	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
+						struct binder_handle_cookie),
+	/*
+	 * int: handle
+	 * void *: cookie
+	 */
+
+	BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
+	/*
+	 * void *: cookie
+	 */
+};
+
+#endif /* _UAPI_LINUX_BINDER_H */
+
diff --git a/drivers/staging/android/uapi/sw_sync.h b/drivers/staging/android/uapi/sw_sync.h
new file mode 100644
index 000000000000..9b5d4869505c
--- /dev/null
+++ b/drivers/staging/android/uapi/sw_sync.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Google, 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.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SW_SYNC_H
+#define _UAPI_LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+
+struct sw_sync_create_fence_data {
+	__u32	value;
+	char	name[32];
+	__s32	fence; /* fd of new fence */
+};
+
+#define SW_SYNC_IOC_MAGIC	'W'
+
+#define SW_SYNC_IOC_CREATE_FENCE	_IOWR(SW_SYNC_IOC_MAGIC, 0,\
+		struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC			_IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+#endif /* _UAPI_LINUX_SW_SYNC_H */
diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h
new file mode 100644
index 000000000000..e964c751f6b8
--- /dev/null
+++ b/drivers/staging/android/uapi/sync.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * 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 _UAPI_LINUX_SYNC_H
+#define _UAPI_LINUX_SYNC_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2:	file descriptor of second fence
+ * @name:	name of new fence
+ * @fence:	returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+	__s32	fd2; /* fd of second fence */
+	char	name[32]; /* name of new fence */
+	__s32	fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len:		length of sync_pt_info including any driver_data
+ * @obj_name:		name of parent sync_timeline
+ * @driver_name:	name of driver implementing the parent
+ * @status:		status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns:	timestamp of status change in nanoseconds
+ * @driver_data:	any driver dependent data
+ */
+struct sync_pt_info {
+	__u32	len;
+	char	obj_name[32];
+	char	driver_name[32];
+	__s32	status;
+	__u64	timestamp_ns;
+
+	__u8	driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len:	ioctl caller writes the size of the buffer its passing in.
+ *		ioctl returns length of sync_fence_data returned to userspace
+ *		including pt_info.
+ * @name:	name of fence
+ * @status:	status of fence. 1: signaled 0:active <0:error
+ * @pt_info:	a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+	__u32	len;
+	char	name[32];
+	__s32	status;
+
+	__u8	pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC		'>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds.  Waits indefinitely timeout < 0.
+ */
+#define SYNC_IOC_WAIT		_IOW(SYNC_IOC_MAGIC, 0, __s32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data.  Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2.  Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE		_IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len.  On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO	_IOWR(SYNC_IOC_MAGIC, 2,\
+	struct sync_fence_info_data)
+
+#endif /* _UAPI_LINUX_SYNC_H */
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index f1b6de0293c8..5e4dfe031040 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -150,1354 +150,1224 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
 	return PktLen;
 }
 
-static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
+static int bcm_char_ioctl_reg_read_private(void __user *argp, struct bcm_mini_adapter *Adapter)
 {
-	struct bcm_tarang_data *pTarang = filp->private_data;
-	void __user *argp = (void __user *)arg;
-	struct bcm_mini_adapter *Adapter = pTarang->Adapter;
-	INT Status = STATUS_FAILURE;
-	int timeout = 0;
+	struct bcm_rdm_buffer sRdmBuffer = {0};
 	struct bcm_ioctl_buffer IoBuffer;
+	PCHAR temp_buff;
+	INT Status = STATUS_FAILURE;
+	UINT Bufflen;
+	u16 temp_value;
 	int bytes;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-			"Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX",
-			cmd, arg);
-
-	if (_IOC_TYPE(cmd) != BCM_IOCTL)
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 		return -EFAULT;
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
-	else if (_IOC_DIR(cmd) & _IOC_WRITE)
-		Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
-	else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
-		Status = STATUS_SUCCESS;
 
-	if (Status)
-		return -EFAULT;
+	if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+		return -EINVAL;
 
-	if (Adapter->device_removed)
+	if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
 		return -EFAULT;
 
-	if (false == Adapter->fw_download_done) {
-		switch (cmd) {
-		case IOCTL_MAC_ADDR_REQ:
-		case IOCTL_LINK_REQ:
-		case IOCTL_CM_REQUEST:
-		case IOCTL_SS_INFO_REQ:
-		case IOCTL_SEND_CONTROL_MESSAGE:
-		case IOCTL_IDLE_REQ:
-		case IOCTL_BCM_GPIO_SET_REQUEST:
-		case IOCTL_BCM_GPIO_STATUS_REQUEST:
-			return -EACCES;
-		default:
-			break;
-		}
+	if (IoBuffer.OutputLength > USHRT_MAX ||
+		IoBuffer.OutputLength == 0) {
+		return -EINVAL;
 	}
 
-	Status = vendorextnIoctl(Adapter, cmd, arg);
-	if (Status != CONTINUE_COMMON_PATH)
-		return Status;
-
-	switch (cmd) {
-	/* Rdms for Swin Idle... */
-	case IOCTL_BCM_REGISTER_READ_PRIVATE: {
-		struct bcm_rdm_buffer sRdmBuffer = {0};
-		PCHAR temp_buff;
-		UINT Bufflen;
-		u16 temp_value;
-
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	Bufflen = IoBuffer.OutputLength;
+	temp_value = 4 - (Bufflen % 4);
+	Bufflen += temp_value % 4;
 
-		if (IoBuffer.InputLength > sizeof(sRdmBuffer))
-			return -EINVAL;
+	temp_buff = kmalloc(Bufflen, GFP_KERNEL);
+	if (!temp_buff)
+		return -ENOMEM;
 
-		if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+	bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+			(PUINT)temp_buff, Bufflen);
+	if (bytes > 0) {
+		Status = STATUS_SUCCESS;
+		if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
+			kfree(temp_buff);
 			return -EFAULT;
-
-		if (IoBuffer.OutputLength > USHRT_MAX ||
-			IoBuffer.OutputLength == 0) {
-			return -EINVAL;
 		}
+	} else {
+		Status = bytes;
+	}
 
-		Bufflen = IoBuffer.OutputLength;
-		temp_value = 4 - (Bufflen % 4);
-		Bufflen += temp_value % 4;
+	kfree(temp_buff);
+	return Status;
+}
 
-		temp_buff = kmalloc(Bufflen, GFP_KERNEL);
-		if (!temp_buff)
-			return -ENOMEM;
+static int bcm_char_ioctl_reg_write_private(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_wrm_buffer sWrmBuffer = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	UINT uiTempVar = 0;
+	INT Status;
 
-		bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
-				(PUINT)temp_buff, Bufflen);
-		if (bytes > 0) {
-			Status = STATUS_SUCCESS;
-			if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
-				kfree(temp_buff);
-				return -EFAULT;
-			}
-		} else {
-			Status = bytes;
-		}
+	/* Copy Ioctl Buffer structure */
 
-		kfree(temp_buff);
-		break;
-	}
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-	case IOCTL_BCM_REGISTER_WRITE_PRIVATE: {
-		struct bcm_wrm_buffer sWrmBuffer = {0};
-		UINT uiTempVar = 0;
-		/* Copy Ioctl Buffer structure */
+	if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+		return -EINVAL;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* Get WrmBuffer structure */
+	if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (IoBuffer.InputLength > sizeof(sWrmBuffer))
-			return -EINVAL;
+	uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+	if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+		((uiTempVar == EEPROM_REJECT_REG_1) ||
+			(uiTempVar == EEPROM_REJECT_REG_2) ||
+			(uiTempVar == EEPROM_REJECT_REG_3) ||
+			(uiTempVar == EEPROM_REJECT_REG_4))) {
 
-		/* Get WrmBuffer structure */
-		if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"EEPROM Access Denied, not in VSG Mode\n");
+		return -EFAULT;
+	}
 
-		uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
-		if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
-			((uiTempVar == EEPROM_REJECT_REG_1) ||
-				(uiTempVar == EEPROM_REJECT_REG_2) ||
-				(uiTempVar == EEPROM_REJECT_REG_3) ||
-				(uiTempVar == EEPROM_REJECT_REG_4))) {
+	Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
+			(PUINT)sWrmBuffer.Data, sizeof(ULONG));
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"EEPROM Access Denied, not in VSG Mode\n");
-			return -EFAULT;
-		}
+	if (Status == STATUS_SUCCESS) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL, "WRM Done\n");
+	} else {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL, "WRM Failed\n");
+		Status = -EFAULT;
+	}
+	return Status;
+}
 
-		Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
-				(PUINT)sWrmBuffer.Data, sizeof(ULONG));
+static int bcm_char_ioctl_eeprom_reg_read(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_rdm_buffer sRdmBuffer = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	PCHAR temp_buff = NULL;
+	UINT uiTempVar = 0;
+	INT Status;
+	int bytes;
 
-		if (Status == STATUS_SUCCESS) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL, "WRM Done\n");
-		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL, "WRM Failed\n");
-			Status = -EFAULT;
-		}
-		break;
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Device in Idle Mode, Blocking Rdms\n");
+		return -EACCES;
 	}
 
-	case IOCTL_BCM_REGISTER_READ:
-	case IOCTL_BCM_EEPROM_REGISTER_READ: {
-		struct bcm_rdm_buffer sRdmBuffer = {0};
-		PCHAR temp_buff = NULL;
-		UINT uiTempVar = 0;
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Device in Idle Mode, Blocking Rdms\n");
-			return -EACCES;
-		}
+	if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+		return -EINVAL;
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (IoBuffer.InputLength > sizeof(sRdmBuffer))
-			return -EINVAL;
+	if (IoBuffer.OutputLength > USHRT_MAX ||
+		IoBuffer.OutputLength == 0) {
+		return -EINVAL;
+	}
 
-		if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+	temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+	if (!temp_buff)
+		return STATUS_FAILURE;
 
-		if (IoBuffer.OutputLength > USHRT_MAX ||
-			IoBuffer.OutputLength == 0) {
-			return -EINVAL;
-		}
+	if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+		((ULONG)sRdmBuffer.Register & 0x3)) {
 
-		temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
-		if (!temp_buff)
-			return STATUS_FAILURE;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"RDM Done On invalid Address : %x Access Denied.\n",
+				(int)sRdmBuffer.Register);
 
-		if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
-			((ULONG)sRdmBuffer.Register & 0x3)) {
+		kfree(temp_buff);
+		return -EINVAL;
+	}
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"RDM Done On invalid Address : %x Access Denied.\n",
-					(int)sRdmBuffer.Register);
+	uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
+	bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
+			       (PUINT)temp_buff, IoBuffer.OutputLength);
 
+	if (bytes > 0) {
+		Status = STATUS_SUCCESS;
+		if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
 			kfree(temp_buff);
-			return -EINVAL;
+			return -EFAULT;
 		}
+	} else {
+		Status = bytes;
+	}
 
-		uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
-		bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
-				       (PUINT)temp_buff, IoBuffer.OutputLength);
+	kfree(temp_buff);
+	return Status;
+}
 
-		if (bytes > 0) {
-			Status = STATUS_SUCCESS;
-			if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
-				kfree(temp_buff);
-				return -EFAULT;
-			}
-		} else {
-			Status = bytes;
-		}
+static int bcm_char_ioctl_eeprom_reg_write(void __user *argp, struct bcm_mini_adapter *Adapter, UINT cmd)
+{
+	struct bcm_wrm_buffer sWrmBuffer = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	UINT uiTempVar = 0;
+	INT Status;
 
-		kfree(temp_buff);
-		break;
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Device in Idle Mode, Blocking Wrms\n");
+		return -EACCES;
 	}
-	case IOCTL_BCM_REGISTER_WRITE:
-	case IOCTL_BCM_EEPROM_REGISTER_WRITE: {
-		struct bcm_wrm_buffer sWrmBuffer = {0};
-		UINT uiTempVar = 0;
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Device in Idle Mode, Blocking Wrms\n");
-			return -EACCES;
-		}
+	if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+		return -EINVAL;
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* Get WrmBuffer structure */
+	if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (IoBuffer.InputLength > sizeof(sWrmBuffer))
-			return -EINVAL;
+	if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+		((ULONG)sWrmBuffer.Register & 0x3)) {
 
-		/* Get WrmBuffer structure */
-		if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"WRM Done On invalid Address : %x Access Denied.\n",
+				(int)sWrmBuffer.Register);
+		return -EINVAL;
+	}
 
-		if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
-			((ULONG)sWrmBuffer.Register & 0x3)) {
+	uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+	if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+			((uiTempVar == EEPROM_REJECT_REG_1) ||
+			(uiTempVar == EEPROM_REJECT_REG_2) ||
+			(uiTempVar == EEPROM_REJECT_REG_3) ||
+			(uiTempVar == EEPROM_REJECT_REG_4)) &&
+			(cmd == IOCTL_BCM_REGISTER_WRITE)) {
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"WRM Done On invalid Address : %x Access Denied.\n",
-					(int)sWrmBuffer.Register);
-			return -EINVAL;
-		}
-
-		uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
-		if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
-				((uiTempVar == EEPROM_REJECT_REG_1) ||
-				(uiTempVar == EEPROM_REJECT_REG_2) ||
-				(uiTempVar == EEPROM_REJECT_REG_3) ||
-				(uiTempVar == EEPROM_REJECT_REG_4)) &&
-				(cmd == IOCTL_BCM_REGISTER_WRITE)) {
-
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-						"EEPROM Access Denied, not in VSG Mode\n");
-				return -EFAULT;
-		}
+					"EEPROM Access Denied, not in VSG Mode\n");
+			return -EFAULT;
+	}
 
-		Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
-					(PUINT)sWrmBuffer.Data,
-					sWrmBuffer.Length);
+	Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
+				(PUINT)sWrmBuffer.Data,
+				sWrmBuffer.Length);
 
-		if (Status == STATUS_SUCCESS) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG,
-					DBG_LVL_ALL, "WRM Done\n");
-		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL, "WRM Failed\n");
-			Status = -EFAULT;
-		}
-		break;
+	if (Status == STATUS_SUCCESS) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG,
+				DBG_LVL_ALL, "WRM Done\n");
+	} else {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL, "WRM Failed\n");
+		Status = -EFAULT;
 	}
-	case IOCTL_BCM_GPIO_SET_REQUEST: {
-		UCHAR ucResetValue[4];
-		UINT value = 0;
-		UINT uiBit = 0;
-		UINT uiOperation = 0;
-		struct bcm_gpio_info gpio_info = {0};
+	return Status;
+}
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+static int bcm_char_ioctl_gpio_set_request(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_gpio_info gpio_info = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	UCHAR ucResetValue[4];
+	UINT value = 0;
+	UINT uiBit = 0;
+	UINT uiOperation = 0;
+	INT Status;
+	int bytes;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"GPIO Can't be set/clear in Low power Mode");
-			return -EACCES;
-		}
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"GPIO Can't be set/clear in Low power Mode");
+		return -EACCES;
+	}
 
-		if (IoBuffer.InputLength > sizeof(gpio_info))
-			return -EINVAL;
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+	if (IoBuffer.InputLength > sizeof(gpio_info))
+		return -EINVAL;
 
-		uiBit  = gpio_info.uiGpioNumber;
-		uiOperation = gpio_info.uiGpioValue;
-		value = (1<<uiBit);
+	if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (IsReqGpioIsLedInNVM(Adapter, value) == false) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",
-					value);
-			Status = -EINVAL;
-			break;
-		}
+	uiBit  = gpio_info.uiGpioNumber;
+	uiOperation = gpio_info.uiGpioValue;
+	value = (1<<uiBit);
 
-		/* Set - setting 1 */
-		if (uiOperation) {
-			/* Set the gpio output register */
-			Status = wrmaltWithLock(Adapter,
-						BCM_GPIO_OUTPUT_SET_REG,
-						(PUINT)(&value), sizeof(UINT));
-
-			if (Status == STATUS_SUCCESS) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"Set the GPIO bit\n");
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"Failed to set the %dth GPIO\n",
-						uiBit);
-				break;
-			}
-		} else {
-			/* Set the gpio output register */
-			Status = wrmaltWithLock(Adapter,
-						BCM_GPIO_OUTPUT_CLR_REG,
-						(PUINT)(&value), sizeof(UINT));
-
-			if (Status == STATUS_SUCCESS) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"Set the GPIO bit\n");
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"Failed to clear the %dth GPIO\n",
-						uiBit);
-				break;
-			}
-		}
+	if (IsReqGpioIsLedInNVM(Adapter, value) == false) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",
+				value);
+		return -EINVAL;
+	}
 
-		bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
-				       (PUINT)ucResetValue, sizeof(UINT));
-		if (bytes < 0) {
-			Status = bytes;
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-					"GPIO_MODE_REGISTER read failed");
-			break;
+	/* Set - setting 1 */
+	if (uiOperation) {
+		/* Set the gpio output register */
+		Status = wrmaltWithLock(Adapter,
+					BCM_GPIO_OUTPUT_SET_REG,
+					(PUINT)(&value), sizeof(UINT));
+
+		if (Status == STATUS_SUCCESS) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"Set the GPIO bit\n");
 		} else {
-			Status = STATUS_SUCCESS;
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"Failed to set the %dth GPIO\n",
+					uiBit);
+			return Status;
 		}
-
-		/* Set the gpio mode register to output */
-		*(UINT *)ucResetValue |= (1<<uiBit);
-		Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
-					(PUINT)ucResetValue, sizeof(UINT));
+	} else {
+		/* Set the gpio output register */
+		Status = wrmaltWithLock(Adapter,
+					BCM_GPIO_OUTPUT_CLR_REG,
+					(PUINT)(&value), sizeof(UINT));
 
 		if (Status == STATUS_SUCCESS) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"Set the GPIO to output Mode\n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"Set the GPIO bit\n");
 		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"Failed to put GPIO in Output Mode\n");
-			break;
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"Failed to clear the %dth GPIO\n",
+					uiBit);
+			return Status;
 		}
 	}
-	break;
 
-	case BCM_LED_THREAD_STATE_CHANGE_REQ: {
-		struct bcm_user_thread_req threadReq = {0};
+	bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
+			       (PUINT)ucResetValue, sizeof(UINT));
+	if (bytes < 0) {
+		Status = bytes;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-				"User made LED thread InActive");
+				"GPIO_MODE_REGISTER read failed");
+		return Status;
+	} else {
+		Status = STATUS_SUCCESS;
+	}
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	/* Set the gpio mode register to output */
+	*(UINT *)ucResetValue |= (1<<uiBit);
+	Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
+				(PUINT)ucResetValue, sizeof(UINT));
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"GPIO Can't be set/clear in Low power Mode");
-			Status = -EACCES;
-			break;
-		}
+	if (Status == STATUS_SUCCESS) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"Set the GPIO to output Mode\n");
+	} else {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"Failed to put GPIO in Output Mode\n");
+	}
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	return Status;
+}
 
-		if (IoBuffer.InputLength > sizeof(threadReq))
-			return -EINVAL;
+static int bcm_char_ioctl_led_thread_state_change_req(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_user_thread_req threadReq = {0};
+	struct bcm_ioctl_buffer IoBuffer;
 
-		if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+			"User made LED thread InActive");
 
-		/* if LED thread is running(Actively or Inactively) set it state to make inactive */
-		if (Adapter->LEDInfo.led_thread_running) {
-			if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"Activating thread req");
-				Adapter->DriverState = LED_THREAD_ACTIVE;
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-						OSAL_DBG, DBG_LVL_ALL,
-						"DeActivating Thread req.....");
-				Adapter->DriverState = LED_THREAD_INACTIVE;
-			}
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-			/* signal thread. */
-			wake_up(&Adapter->LEDInfo.notify_led_event);
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"GPIO Can't be set/clear in Low power Mode");
+		return -EACCES;
 	}
-	break;
-
-	case IOCTL_BCM_GPIO_STATUS_REQUEST: {
-		ULONG uiBit = 0;
-		UCHAR ucRead[4];
-		struct bcm_gpio_info gpio_info = {0};
-
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE))
-			return -EACCES;
-
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
-
-		if (IoBuffer.InputLength > sizeof(gpio_info))
-			return -EINVAL;
 
-		if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		uiBit = gpio_info.uiGpioNumber;
+	if (IoBuffer.InputLength > sizeof(threadReq))
+		return -EINVAL;
 
-		/* Set the gpio output register */
-		bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
-					(PUINT)ucRead, sizeof(UINT));
+	if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (bytes < 0) {
-			Status = bytes;
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"RDM Failed\n");
-			return Status;
+	/* if LED thread is running(Actively or Inactively) set it state to make inactive */
+	if (Adapter->LEDInfo.led_thread_running) {
+		if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"Activating thread req");
+			Adapter->DriverState = LED_THREAD_ACTIVE;
 		} else {
-			Status = STATUS_SUCCESS;
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+					OSAL_DBG, DBG_LVL_ALL,
+					"DeActivating Thread req.....");
+			Adapter->DriverState = LED_THREAD_INACTIVE;
 		}
-	}
-	break;
 
-	case IOCTL_BCM_GPIO_MULTI_REQUEST: {
-		UCHAR ucResetValue[4];
-		struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
-		struct bcm_gpio_multi_info *pgpio_multi_info = (struct bcm_gpio_multi_info *)gpio_multi_info;
+		/* signal thread. */
+		wake_up(&Adapter->LEDInfo.notify_led_event);
+	}
+	return STATUS_SUCCESS;
+}
 
-		memset(pgpio_multi_info, 0, MAX_IDX * sizeof(struct bcm_gpio_multi_info));
-
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE))
-			return -EINVAL;
+static int bcm_char_ioctl_gpio_status_request(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_gpio_info gpio_info = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	ULONG uiBit = 0;
+	UCHAR ucRead[4];
+	INT Status;
+	int bytes;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE))
+		return -EACCES;
 
-		if (IoBuffer.InputLength > sizeof(gpio_multi_info))
-			return -EINVAL;
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+	if (IoBuffer.InputLength > sizeof(gpio_info))
+		return -EINVAL;
 
-		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == false) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL,
-					"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
-					pgpio_multi_info[WIMAX_IDX].uiGPIOMask,
-					Adapter->gpioBitMap);
-			Status = -EINVAL;
-			break;
-		}
+	if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		/* Set the gpio output register */
-		if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
-			(pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
-			/* Set 1's in GPIO OUTPUT REGISTER */
-			*(UINT *)ucResetValue =  pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
-				pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
-				pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
+	uiBit = gpio_info.uiGpioNumber;
 
-			if (*(UINT *) ucResetValue)
-				Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG,
-							(PUINT)ucResetValue, sizeof(ULONG));
+	/* Set the gpio output register */
+	bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+				(PUINT)ucRead, sizeof(UINT));
 
-			if (Status != STATUS_SUCCESS) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-						"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
-				return Status;
-			}
+	if (bytes < 0) {
+		Status = bytes;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"RDM Failed\n");
+		return Status;
+	} else {
+		Status = STATUS_SUCCESS;
+	}
+	return Status;
+}
 
-			/* Clear to 0's in GPIO OUTPUT REGISTER */
-			*(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
-						pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
-						(~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
+static int bcm_char_ioctl_gpio_multi_request(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
+	struct bcm_gpio_multi_info *pgpio_multi_info = (struct bcm_gpio_multi_info *)gpio_multi_info;
+	struct bcm_ioctl_buffer IoBuffer;
+	UCHAR ucResetValue[4];
+	INT Status = STATUS_FAILURE;
+	int bytes;
 
-			if (*(UINT *) ucResetValue)
-				Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG));
+	memset(pgpio_multi_info, 0, MAX_IDX * sizeof(struct bcm_gpio_multi_info));
 
-			if (Status != STATUS_SUCCESS) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-						"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
-				return Status;
-			}
-		}
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE))
+		return -EINVAL;
 
-		if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
-			bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-			if (bytes < 0) {
-				Status = bytes;
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-						"RDM to GPIO_PIN_STATE_REGISTER Failed.");
-				return Status;
-			} else {
-				Status = STATUS_SUCCESS;
-			}
+	if (IoBuffer.InputLength > sizeof(gpio_multi_info))
+		return -EINVAL;
+	if (IoBuffer.OutputLength > sizeof(gpio_multi_info))
+		IoBuffer.OutputLength = sizeof(gpio_multi_info);
 
-			pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
-								pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
-		}
+	if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Failed while copying Content to IOBufer for user space err:%d", Status);
-			return -EFAULT;
-		}
+	if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == false) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL,
+				"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+				pgpio_multi_info[WIMAX_IDX].uiGPIOMask,
+				Adapter->gpioBitMap);
+		return -EINVAL;
 	}
-	break;
 
-	case IOCTL_BCM_GPIO_MODE_REQUEST: {
-		UCHAR ucResetValue[4];
-		struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
-		struct bcm_gpio_multi_mode *pgpio_multi_mode = (struct bcm_gpio_multi_mode *)gpio_multi_mode;
+	/* Set the gpio output register */
+	if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
+		(pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
+		/* Set 1's in GPIO OUTPUT REGISTER */
+		*(UINT *)ucResetValue =  pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+			pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+			pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE))
-			return -EINVAL;
+		if (*(UINT *) ucResetValue)
+			Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG,
+						(PUINT)ucResetValue, sizeof(ULONG));
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+		if (Status != STATUS_SUCCESS) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
+			return Status;
+		}
 
-		if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
-			return -EINVAL;
+		/* Clear to 0's in GPIO OUTPUT REGISTER */
+		*(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+					pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+					(~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
 
-		if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
-			return -EFAULT;
+		if (*(UINT *) ucResetValue)
+			Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG));
+
+		if (Status != STATUS_SUCCESS) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
+			return Status;
+		}
+	}
 
-		bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+	if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
+		bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
 
 		if (bytes < 0) {
 			Status = bytes;
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"RDM to GPIO_PIN_STATE_REGISTER Failed.");
 			return Status;
 		} else {
 			Status = STATUS_SUCCESS;
 		}
 
-		/* Validating the request */
-		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == false) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-					"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
-					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
-			Status = -EINVAL;
-			break;
-		}
-
-		if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
-			/* write all OUT's (1's) */
-			*(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
-						pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
-
-			/* write all IN's (0's) */
-			*(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
-						pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
-
-			/* Currently implemented return the modes of all GPIO's
-			 * else needs to bit AND with  mask
-			 */
-			pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
-
-			Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG));
-			if (Status == STATUS_SUCCESS) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-						"WRM to GPIO_MODE_REGISTER Done");
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-						"WRM to GPIO_MODE_REGISTER Failed");
-				Status = -EFAULT;
-				break;
-			}
-		} else {
-/* if uiGPIOMask is 0 then return mode register configuration */
-			pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
-		}
-
-		Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Failed while copying Content to IOBufer for user space err:%d", Status);
-			return -EFAULT;
-		}
+		pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
+							pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
 	}
-	break;
 
-	case IOCTL_MAC_ADDR_REQ:
-	case IOCTL_LINK_REQ:
-	case IOCTL_CM_REQUEST:
-	case IOCTL_SS_INFO_REQ:
-	case IOCTL_SEND_CONTROL_MESSAGE:
-	case IOCTL_IDLE_REQ: {
-		PVOID pvBuffer = NULL;
+	Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Failed while copying Content to IOBufer for user space err:%d", Status);
+		return -EFAULT;
+	}
+	return Status;
+}
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+static int bcm_char_ioctl_gpio_mode_request(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
+	struct bcm_gpio_multi_mode *pgpio_multi_mode = (struct bcm_gpio_multi_mode *)gpio_multi_mode;
+	struct bcm_ioctl_buffer IoBuffer;
+	UCHAR ucResetValue[4];
+	INT Status;
+	int bytes;
 
-		if (IoBuffer.InputLength < sizeof(struct bcm_link_request))
-			return -EINVAL;
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE))
+		return -EINVAL;
 
-		if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
-			return -EINVAL;
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		pvBuffer = memdup_user(IoBuffer.InputBuffer,
-				       IoBuffer.InputLength);
-		if (IS_ERR(pvBuffer))
-			return PTR_ERR(pvBuffer);
+	if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
+		return -EINVAL;
+	if (IoBuffer.OutputLength > sizeof(gpio_multi_mode))
+		IoBuffer.OutputLength = sizeof(gpio_multi_mode);
 
-		down(&Adapter->LowPowerModeSync);
-		Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
-							!Adapter->bPreparingForLowPowerMode,
-							(1 * HZ));
-		if (Status == -ERESTARTSYS)
-			goto cntrlEnd;
+	if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		return -EFAULT;
 
-		if (Adapter->bPreparingForLowPowerMode) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-					"Preparing Idle Mode is still True - Hence Rejecting control message\n");
-			Status = STATUS_FAILURE;
-			goto cntrlEnd;
-		}
-		Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
+	bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
 
-cntrlEnd:
-		up(&Adapter->LowPowerModeSync);
-		kfree(pvBuffer);
-		break;
+	if (bytes < 0) {
+		Status = bytes;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
+		return Status;
+	} else {
+		Status = STATUS_SUCCESS;
 	}
 
-	case IOCTL_BCM_BUFFER_DOWNLOAD_START: {
-		if (down_trylock(&Adapter->NVMRdmWrmLock)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
-					"IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
-			return -EACCES;
-		}
+	/* Validating the request */
+	if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == false) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+				pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
+		return -EINVAL;
+	}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-				"Starting the firmware download PID =0x%x!!!!\n", current->pid);
-
-		if (down_trylock(&Adapter->fw_download_sema))
-			return -EBUSY;
-
-		Adapter->bBinDownloaded = false;
-		Adapter->fw_download_process_pid = current->pid;
-		Adapter->bCfgDownloaded = false;
-		Adapter->fw_download_done = false;
-		netif_carrier_off(Adapter->dev);
-		netif_stop_queue(Adapter->dev);
-		Status = reset_card_proc(Adapter);
-		if (Status) {
-			pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
-			up(&Adapter->fw_download_sema);
-			up(&Adapter->NVMRdmWrmLock);
-			return Status;
-		}
-		mdelay(10);
+	if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
+		/* write all OUT's (1's) */
+		*(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
+					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
 
-		up(&Adapter->NVMRdmWrmLock);
-		return Status;
-	}
+		/* write all IN's (0's) */
+		*(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
+					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
 
-	case IOCTL_BCM_BUFFER_DOWNLOAD: {
-		struct bcm_firmware_info *psFwInfo = NULL;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+		/* Currently implemented return the modes of all GPIO's
+		 * else needs to bit AND with  mask
+		 */
+		pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
 
-		if (!down_trylock(&Adapter->fw_download_sema)) {
+		Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG));
+		if (Status == STATUS_SUCCESS) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+					"WRM to GPIO_MODE_REGISTER Done");
+		} else {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Invalid way to download buffer. Use Start and then call this!!!\n");
-			up(&Adapter->fw_download_sema);
-			Status = -EINVAL;
-			return Status;
-		}
-
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
-			up(&Adapter->fw_download_sema);
+					"WRM to GPIO_MODE_REGISTER Failed");
 			return -EFAULT;
 		}
+	} else {
+		/* if uiGPIOMask is 0 then return mode register configuration */
+		pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+	}
 
+	Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
+	if (Status) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-				"Length for FW DLD is : %lx\n", IoBuffer.InputLength);
+				"Failed while copying Content to IOBufer for user space err:%d", Status);
+		return -EFAULT;
+	}
+	return Status;
+}
 
-		if (IoBuffer.InputLength > sizeof(struct bcm_firmware_info)) {
-			up(&Adapter->fw_download_sema);
-			return -EINVAL;
-		}
+static int bcm_char_ioctl_misc_request(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	PVOID pvBuffer = NULL;
+	INT Status;
 
-		psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
-		if (!psFwInfo) {
-			up(&Adapter->fw_download_sema);
-			return -ENOMEM;
-		}
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
-			up(&Adapter->fw_download_sema);
-			kfree(psFwInfo);
-			return -EFAULT;
-		}
+	if (IoBuffer.InputLength < sizeof(struct bcm_link_request))
+		return -EINVAL;
 
-		if (!psFwInfo->pvMappedFirmwareAddress ||
-			(psFwInfo->u32FirmwareLength == 0)) {
+	if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
+		return -EINVAL;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
-					psFwInfo->u32FirmwareLength);
-			up(&Adapter->fw_download_sema);
-			kfree(psFwInfo);
-			Status = -EINVAL;
-			return Status;
-		}
+	pvBuffer = memdup_user(IoBuffer.InputBuffer,
+			       IoBuffer.InputLength);
+	if (IS_ERR(pvBuffer))
+		return PTR_ERR(pvBuffer);
 
-		Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+	down(&Adapter->LowPowerModeSync);
+	Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
+						!Adapter->bPreparingForLowPowerMode,
+						(1 * HZ));
+	if (Status == -ERESTARTSYS)
+		goto cntrlEnd;
 
-		if (Status != STATUS_SUCCESS) {
-			if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
-			else
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,	"IOCTL: Firmware File Upload Failed\n");
+	if (Adapter->bPreparingForLowPowerMode) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Preparing Idle Mode is still True - Hence Rejecting control message\n");
+		Status = STATUS_FAILURE;
+		goto cntrlEnd;
+	}
+	Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
 
-			/* up(&Adapter->fw_download_sema); */
+cntrlEnd:
+	up(&Adapter->LowPowerModeSync);
+	kfree(pvBuffer);
+	return Status;
+}
 
-			if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-				Adapter->DriverState = DRIVER_INIT;
-				Adapter->LEDInfo.bLedInitDone = false;
-				wake_up(&Adapter->LEDInfo.notify_led_event);
-			}
-		}
+static int bcm_char_ioctl_buffer_download_start(struct bcm_mini_adapter *Adapter)
+{
+	INT Status;
 
-		if (Status != STATUS_SUCCESS)
-			up(&Adapter->fw_download_sema);
+	if (down_trylock(&Adapter->NVMRdmWrmLock)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+		return -EACCES;
+	}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
-		kfree(psFwInfo);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+			"Starting the firmware download PID =0x%x!!!!\n", current->pid);
+
+	if (down_trylock(&Adapter->fw_download_sema))
+		return -EBUSY;
+
+	Adapter->bBinDownloaded = false;
+	Adapter->fw_download_process_pid = current->pid;
+	Adapter->bCfgDownloaded = false;
+	Adapter->fw_download_done = false;
+	netif_carrier_off(Adapter->dev);
+	netif_stop_queue(Adapter->dev);
+	Status = reset_card_proc(Adapter);
+	if (Status) {
+		pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
+		up(&Adapter->fw_download_sema);
+		up(&Adapter->NVMRdmWrmLock);
 		return Status;
 	}
+	mdelay(10);
 
-	case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: {
-		if (!down_trylock(&Adapter->fw_download_sema)) {
-			up(&Adapter->fw_download_sema);
-			return -EINVAL;
-		}
+	up(&Adapter->NVMRdmWrmLock);
+	return Status;
+}
 
-		if (down_trylock(&Adapter->NVMRdmWrmLock)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"FW download blocked as EEPROM Read/Write is in progress\n");
-			up(&Adapter->fw_download_sema);
-			return -EACCES;
-		}
+static int bcm_char_ioctl_buffer_download(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_firmware_info *psFwInfo = NULL;
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status;
 
-		Adapter->bBinDownloaded = TRUE;
-		Adapter->bCfgDownloaded = TRUE;
-		atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
-		Adapter->CurrNumRecvDescs = 0;
-		Adapter->downloadDDR = 0;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
 
-		/* setting the Mips to Run */
-		Status = run_card_proc(Adapter);
+	if (!down_trylock(&Adapter->fw_download_sema)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Invalid way to download buffer. Use Start and then call this!!!\n");
+		up(&Adapter->fw_download_sema);
+		return -EINVAL;
+	}
 
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
-			up(&Adapter->fw_download_sema);
-			up(&Adapter->NVMRdmWrmLock);
-			return Status;
-		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
-					DBG_LVL_ALL, "Firm Download Over...\n");
-		}
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+		up(&Adapter->fw_download_sema);
+		return -EFAULT;
+	}
 
-		mdelay(10);
-
-		/* Wait for MailBox Interrupt */
-		if (StartInterruptUrb((struct bcm_interface_adapter *)Adapter->pvInterfaceAdapter))
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
-
-		timeout = 5*HZ;
-		Adapter->waiting_to_fw_download_done = false;
-		wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
-				Adapter->waiting_to_fw_download_done, timeout);
-		Adapter->fw_download_process_pid = INVALID_PID;
-		Adapter->fw_download_done = TRUE;
-		atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
-		Adapter->CurrNumRecvDescs = 0;
-		Adapter->PrevNumRecvDescs = 0;
-		atomic_set(&Adapter->cntrlpktCnt, 0);
-		Adapter->LinkUpStatus = 0;
-		Adapter->LinkStatus = 0;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+			"Length for FW DLD is : %lx\n", IoBuffer.InputLength);
 
-		if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-			Adapter->DriverState = FW_DOWNLOAD_DONE;
-			wake_up(&Adapter->LEDInfo.notify_led_event);
-		}
+	if (IoBuffer.InputLength > sizeof(struct bcm_firmware_info)) {
+		up(&Adapter->fw_download_sema);
+		return -EINVAL;
+	}
 
-		if (!timeout)
-			Status = -ENODEV;
+	psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+	if (!psFwInfo) {
+		up(&Adapter->fw_download_sema);
+		return -ENOMEM;
+	}
 
+	if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
 		up(&Adapter->fw_download_sema);
-		up(&Adapter->NVMRdmWrmLock);
-		return Status;
+		kfree(psFwInfo);
+		return -EFAULT;
 	}
 
-	case IOCTL_BE_BUCKET_SIZE:
-		Status = 0;
-		if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
-			Status = -EFAULT;
-		break;
+	if (!psFwInfo->pvMappedFirmwareAddress ||
+		(psFwInfo->u32FirmwareLength == 0)) {
 
-	case IOCTL_RTPS_BUCKET_SIZE:
-		Status = 0;
-		if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
-			Status = -EFAULT;
-		break;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
+				psFwInfo->u32FirmwareLength);
+		up(&Adapter->fw_download_sema);
+		kfree(psFwInfo);
+		Status = -EINVAL;
+		return Status;
+	}
 
-	case IOCTL_CHIP_RESET: {
-		INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
-		if (NVMAccess) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
-			return -EACCES;
-		}
+	Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
 
-		down(&Adapter->RxAppControlQueuelock);
-		Status = reset_card_proc(Adapter);
-		flushAllAppQ();
-		up(&Adapter->RxAppControlQueuelock);
-		up(&Adapter->NVMRdmWrmLock);
-		ResetCounters(Adapter);
-		break;
-	}
+	if (Status != STATUS_SUCCESS) {
+		if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
+		else
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,	"IOCTL: Firmware File Upload Failed\n");
 
-	case IOCTL_QOS_THRESHOLD: {
-		USHORT uiLoopIndex;
+		/* up(&Adapter->fw_download_sema); */
 
-		Status = 0;
-		for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
-			if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
-					(unsigned long __user *)arg)) {
-				Status = -EFAULT;
-				break;
-			}
+		if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+			Adapter->DriverState = DRIVER_INIT;
+			Adapter->LEDInfo.bLedInitDone = false;
+			wake_up(&Adapter->LEDInfo.notify_led_event);
 		}
-		break;
 	}
 
-	case IOCTL_DUMP_PACKET_INFO:
-		DumpPackInfo(Adapter);
-		DumpPhsRules(&Adapter->stBCMPhsContext);
-		Status = STATUS_SUCCESS;
-		break;
+	if (Status != STATUS_SUCCESS)
+		up(&Adapter->fw_download_sema);
 
-	case IOCTL_GET_PACK_INFO:
-		if (copy_to_user(argp, &Adapter->PackInfo, sizeof(struct bcm_packet_info)*NO_OF_QUEUES))
-			return -EFAULT;
-		Status = STATUS_SUCCESS;
-		break;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
+	kfree(psFwInfo);
+	return Status;
+}
 
-	case IOCTL_BCM_SWITCH_TRANSFER_MODE: {
-		UINT uiData = 0;
-		if (copy_from_user(&uiData, argp, sizeof(UINT)))
-			return -EFAULT;
+static int bcm_char_ioctl_buffer_download_stop(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	INT Status;
+	int timeout = 0;
 
-		if (uiData) {
-			/* Allow All Packets */
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
-				Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
-		} else {
-			/* Allow IP only Packets */
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
-			Adapter->TransferMode = IP_PACKET_ONLY_MODE;
-		}
-		Status = STATUS_SUCCESS;
-		break;
+	if (!down_trylock(&Adapter->fw_download_sema)) {
+		up(&Adapter->fw_download_sema);
+		return -EINVAL;
 	}
 
-	case IOCTL_BCM_GET_DRIVER_VERSION: {
-		ulong len;
+	if (down_trylock(&Adapter->NVMRdmWrmLock)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"FW download blocked as EEPROM Read/Write is in progress\n");
+		up(&Adapter->fw_download_sema);
+		return -EACCES;
+	}
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	Adapter->bBinDownloaded = TRUE;
+	Adapter->bCfgDownloaded = TRUE;
+	atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+	Adapter->CurrNumRecvDescs = 0;
+	Adapter->downloadDDR = 0;
 
-		len = min_t(ulong, IoBuffer.OutputLength, strlen(DRV_VERSION) + 1);
+	/* setting the Mips to Run */
+	Status = run_card_proc(Adapter);
 
-		if (copy_to_user(IoBuffer.OutputBuffer, DRV_VERSION, len))
-			return -EFAULT;
-		Status = STATUS_SUCCESS;
-		break;
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
+		up(&Adapter->fw_download_sema);
+		up(&Adapter->NVMRdmWrmLock);
+		return Status;
+	} else {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+				DBG_LVL_ALL, "Firm Download Over...\n");
 	}
 
-	case IOCTL_BCM_GET_CURRENT_STATUS: {
-		struct bcm_link_state link_state;
+	mdelay(10);
+
+	/* Wait for MailBox Interrupt */
+	if (StartInterruptUrb((struct bcm_interface_adapter *)Adapter->pvInterfaceAdapter))
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
+
+	timeout = 5*HZ;
+	Adapter->waiting_to_fw_download_done = false;
+	wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+			Adapter->waiting_to_fw_download_done, timeout);
+	Adapter->fw_download_process_pid = INVALID_PID;
+	Adapter->fw_download_done = TRUE;
+	atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+	Adapter->CurrNumRecvDescs = 0;
+	Adapter->PrevNumRecvDescs = 0;
+	atomic_set(&Adapter->cntrlpktCnt, 0);
+	Adapter->LinkUpStatus = 0;
+	Adapter->LinkStatus = 0;
+
+	if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+		Adapter->DriverState = FW_DOWNLOAD_DONE;
+		wake_up(&Adapter->LEDInfo.notify_led_event);
+	}
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
-			return -EFAULT;
-		}
+	if (!timeout)
+		Status = -ENODEV;
 
-		if (IoBuffer.OutputLength != sizeof(link_state)) {
-			Status = -EINVAL;
-			break;
-		}
+	up(&Adapter->fw_download_sema);
+	up(&Adapter->NVMRdmWrmLock);
+	return Status;
+}
 
-		memset(&link_state, 0, sizeof(link_state));
-		link_state.bIdleMode = Adapter->IdleMode;
-		link_state.bShutdownMode = Adapter->bShutStatus;
-		link_state.ucLinkStatus = Adapter->LinkStatus;
+static int bcm_char_ioctl_chip_reset(struct bcm_mini_adapter *Adapter)
+{
+	INT Status;
+	INT NVMAccess;
 
-		if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
-			return -EFAULT;
-		}
-		Status = STATUS_SUCCESS;
-		break;
+	NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+	if (NVMAccess) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+		return -EACCES;
 	}
 
-	case IOCTL_BCM_SET_MAC_TRACING: {
-		UINT  tracing_flag;
+	down(&Adapter->RxAppControlQueuelock);
+	Status = reset_card_proc(Adapter);
+	flushAllAppQ();
+	up(&Adapter->RxAppControlQueuelock);
+	up(&Adapter->NVMRdmWrmLock);
+	ResetCounters(Adapter);
+	return Status;
+}
 
-		/* copy ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+static int bcm_char_ioctl_qos_threshold(ULONG arg, struct bcm_mini_adapter *Adapter)
+{
+	USHORT uiLoopIndex;
 
-		if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
+	for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+		if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
+				(unsigned long __user *)arg)) {
 			return -EFAULT;
-
-		if (tracing_flag)
-			Adapter->pTarangs->MacTracingEnabled = TRUE;
-		else
-			Adapter->pTarangs->MacTracingEnabled = false;
-		break;
+		}
 	}
+	return 0;
+}
 
-	case IOCTL_BCM_GET_DSX_INDICATION: {
-		ULONG ulSFId = 0;
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
-
-		if (IoBuffer.OutputLength < sizeof(struct bcm_add_indication_alt)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Mismatch req: %lx needed is =0x%zx!!!",
-					IoBuffer.OutputLength, sizeof(struct bcm_add_indication_alt));
-			return -EINVAL;
-		}
+static int bcm_char_ioctl_switch_transfer_mode(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	UINT uiData = 0;
 
-		if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
-			return -EFAULT;
+	if (copy_from_user(&uiData, argp, sizeof(UINT)))
+		return -EFAULT;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId);
-		get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
-		Status = STATUS_SUCCESS;
+	if (uiData) {
+		/* Allow All Packets */
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
+			Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
+	} else {
+		/* Allow IP only Packets */
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
+		Adapter->TransferMode = IP_PACKET_ONLY_MODE;
 	}
-	break;
+	return STATUS_SUCCESS;
+}
 
-	case IOCTL_BCM_GET_HOST_MIBS: {
-		PVOID temp_buff;
+static int bcm_char_ioctl_get_driver_version(void __user *argp)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	ulong len;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if (IoBuffer.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-					"Length Check failed %lu %zd\n",
-					IoBuffer.OutputLength, sizeof(struct bcm_host_stats_mibs));
-			return -EINVAL;
-		}
+	len = min_t(ulong, IoBuffer.OutputLength, strlen(DRV_VERSION) + 1);
 
-		/* FIXME: HOST_STATS are too big for kmalloc (122048)! */
-		temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
-		if (!temp_buff)
-			return STATUS_FAILURE;
+	if (copy_to_user(IoBuffer.OutputBuffer, DRV_VERSION, len))
+		return -EFAULT;
 
-		Status = ProcessGetHostMibs(Adapter, temp_buff);
-		GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
+	return STATUS_SUCCESS;
+}
 
-		if (Status != STATUS_FAILURE)
-			if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(struct bcm_host_stats_mibs))) {
-				kfree(temp_buff);
-				return -EFAULT;
-			}
+static int bcm_char_ioctl_get_current_status(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_link_state link_state;
+	struct bcm_ioctl_buffer IoBuffer;
 
-		kfree(temp_buff);
-		break;
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
+		return -EFAULT;
 	}
 
-	case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
-		if ((false == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
-			Adapter->usIdleModePattern = ABORT_IDLE_MODE;
-			Adapter->bWakeUpDevice = TRUE;
-			wake_up(&Adapter->process_rx_cntrlpkt);
-		}
+	if (IoBuffer.OutputLength != sizeof(link_state))
+		return -EINVAL;
 
-		Status = STATUS_SUCCESS;
-		break;
+	memset(&link_state, 0, sizeof(link_state));
+	link_state.bIdleMode = Adapter->IdleMode;
+	link_state.bShutdownMode = Adapter->bShutStatus;
+	link_state.ucLinkStatus = Adapter->LinkStatus;
+
+	if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
+		return -EFAULT;
+	}
+	return STATUS_SUCCESS;
+}
 
-	case IOCTL_BCM_BULK_WRM: {
-		struct bcm_bulk_wrm_buffer *pBulkBuffer;
-		UINT uiTempVar = 0;
-		PCHAR pvBuffer = NULL;
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+static int bcm_char_ioctl_set_mac_tracing(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	UINT tracing_flag;
 
-			BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
-			Status = -EACCES;
-			break;
-		}
+	/* copy ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
+		return -EFAULT;
 
-		if (IoBuffer.InputLength < sizeof(ULONG) * 2)
-			return -EINVAL;
+	if (tracing_flag)
+		Adapter->pTarangs->MacTracingEnabled = TRUE;
+	else
+		Adapter->pTarangs->MacTracingEnabled = false;
 
-		pvBuffer = memdup_user(IoBuffer.InputBuffer,
-				       IoBuffer.InputLength);
-		if (IS_ERR(pvBuffer))
-			return PTR_ERR(pvBuffer);
+	return STATUS_SUCCESS;
+}
 
-		pBulkBuffer = (struct bcm_bulk_wrm_buffer *)pvBuffer;
+static int bcm_char_ioctl_get_dsx_indication(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	ULONG ulSFId = 0;
 
-		if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
-			((ULONG)pBulkBuffer->Register & 0x3)) {
-			BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
-			kfree(pvBuffer);
-			Status = -EINVAL;
-			break;
-		}
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
-		if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
-			((uiTempVar == EEPROM_REJECT_REG_1) ||
-				(uiTempVar == EEPROM_REJECT_REG_2) ||
-				(uiTempVar == EEPROM_REJECT_REG_3) ||
-				(uiTempVar == EEPROM_REJECT_REG_4)) &&
-			(cmd == IOCTL_BCM_REGISTER_WRITE)) {
+	if (IoBuffer.OutputLength < sizeof(struct bcm_add_indication_alt)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Mismatch req: %lx needed is =0x%zx!!!",
+				IoBuffer.OutputLength, sizeof(struct bcm_add_indication_alt));
+		return -EINVAL;
+	}
 
-			kfree(pvBuffer);
-			BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
-			Status = -EFAULT;
-			break;
-		}
+	if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
+		return -EFAULT;
 
-		if (pBulkBuffer->SwapEndian == false)
-			Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
-		else
-			Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId);
+	get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
+	return STATUS_SUCCESS;
+}
 
-		if (Status != STATUS_SUCCESS)
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
+static int bcm_char_ioctl_get_host_mibs(void __user *argp, struct bcm_mini_adapter *Adapter, struct bcm_tarang_data *pTarang)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_FAILURE;
+	PVOID temp_buff;
 
-		kfree(pvBuffer);
-		break;
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
+
+	if (IoBuffer.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"Length Check failed %lu %zd\n",
+				IoBuffer.OutputLength, sizeof(struct bcm_host_stats_mibs));
+		return -EINVAL;
 	}
 
-	case IOCTL_BCM_GET_NVM_SIZE:
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* FIXME: HOST_STATS are too big for kmalloc (122048)! */
+	temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
+	if (!temp_buff)
+		return STATUS_FAILURE;
 
-		if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
-			if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
-				return -EFAULT;
+	Status = ProcessGetHostMibs(Adapter, temp_buff);
+	GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
+
+	if (Status != STATUS_FAILURE) {
+		if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(struct bcm_host_stats_mibs))) {
+			kfree(temp_buff);
+			return -EFAULT;
 		}
+	}
 
-		Status = STATUS_SUCCESS;
-		break;
+	kfree(temp_buff);
+	return Status;
+}
 
-	case IOCTL_BCM_CAL_INIT: {
-		UINT uiSectorSize = 0;
-		if (Adapter->eNVMType == NVM_FLASH) {
-			if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-				return -EFAULT;
+static int bcm_char_ioctl_bulk_wrm(void __user *argp, struct bcm_mini_adapter *Adapter, UINT cmd)
+{
+	struct bcm_bulk_wrm_buffer *pBulkBuffer;
+	struct bcm_ioctl_buffer IoBuffer;
+	UINT uiTempVar = 0;
+	INT Status = STATUS_FAILURE;
+	PCHAR pvBuffer = NULL;
 
-			if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
-				return -EFAULT;
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-			if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) {
-				if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
-							sizeof(UINT)))
-					return -EFAULT;
-			} else {
-				if (IsFlash2x(Adapter)) {
-					if (copy_to_user(IoBuffer.OutputBuffer,	&Adapter->uiSectorSize, sizeof(UINT)))
-						return -EFAULT;
-				} else {
-					if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) {
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n");
-						return -EACCES;
-					}
-
-					Adapter->uiSectorSize = uiSectorSize;
-					BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize);
-				}
-			}
-			Status = STATUS_SUCCESS;
-		} else {
-			Status = STATUS_FAILURE;
-		}
+		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
+		return -EACCES;
 	}
-	break;
 
-	case IOCTL_BCM_SET_DEBUG:
-#ifdef DEBUG
-	{
-		struct bcm_user_debug_state sUserDebugState;
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	if (IoBuffer.InputLength < sizeof(ULONG) * 2)
+		return -EINVAL;
 
-		if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(struct bcm_user_debug_state)))
-			return -EFAULT;
+	pvBuffer = memdup_user(IoBuffer.InputBuffer,
+			       IoBuffer.InputLength);
+	if (IS_ERR(pvBuffer))
+		return PTR_ERR(pvBuffer);
 
-		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
-				sUserDebugState.OnOff, sUserDebugState.Type);
-		/* sUserDebugState.Subtype <<= 1; */
-		sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
-		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
-
-		/* Update new 'DebugState' in the Adapter */
-		Adapter->stDebugState.type |= sUserDebugState.Type;
-		/* Subtype: A bitmap of 32 bits for Subtype per Type.
-		 * Valid indexes in 'subtype' array: 1,2,4,8
-		 * corresponding to valid Type values. Hence we can use the 'Type' field
-		 * as the index value, ignoring the array entries 0,3,5,6,7 !
-		 */
-		if (sUserDebugState.OnOff)
-			Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
-		else
-			Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
+	pBulkBuffer = (struct bcm_bulk_wrm_buffer *)pvBuffer;
 
-		BCM_SHOW_DEBUG_BITMAP(Adapter);
+	if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
+		((ULONG)pBulkBuffer->Register & 0x3)) {
+		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
+		kfree(pvBuffer);
+		return -EINVAL;
 	}
-#endif
-	break;
-
-	case IOCTL_BCM_NVM_READ:
-	case IOCTL_BCM_NVM_WRITE: {
-		struct bcm_nvm_readwrite stNVMReadWrite;
-		PUCHAR pReadData = NULL;
-		ULONG ulDSDMagicNumInUsrBuff = 0;
-		struct timeval tv0, tv1;
-		memset(&tv0, 0, sizeof(struct timeval));
-		memset(&tv1, 0, sizeof(struct timeval));
-		if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
-			return -EFAULT;
-		}
 
-		if (IsFlash2x(Adapter)) {
-			if ((Adapter->eActiveDSD != DSD0) &&
-				(Adapter->eActiveDSD != DSD1) &&
-				(Adapter->eActiveDSD != DSD2)) {
+	uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
+	if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
+		((uiTempVar == EEPROM_REJECT_REG_1) ||
+			(uiTempVar == EEPROM_REJECT_REG_2) ||
+			(uiTempVar == EEPROM_REJECT_REG_3) ||
+			(uiTempVar == EEPROM_REJECT_REG_4)) &&
+		(cmd == IOCTL_BCM_REGISTER_WRITE)) {
 
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
-				return STATUS_FAILURE;
-			}
-		}
+		kfree(pvBuffer);
+		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+		return -EFAULT;
+	}
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	if (pBulkBuffer->SwapEndian == false)
+		Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+	else
+		Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
 
-		if (copy_from_user(&stNVMReadWrite,
-					(IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
-					sizeof(struct bcm_nvm_readwrite)))
-			return -EFAULT;
+	if (Status != STATUS_SUCCESS)
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
 
-		/*
-		 * Deny the access if the offset crosses the cal area limit.
-		 */
-		if (stNVMReadWrite.uiNumBytes > Adapter->uiNVMDSDSize)
-			return STATUS_FAILURE;
+	kfree(pvBuffer);
+	return Status;
+}
 
-		if (stNVMReadWrite.uiOffset > Adapter->uiNVMDSDSize - stNVMReadWrite.uiNumBytes) {
-			/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
-			return STATUS_FAILURE;
-		}
+static int bcm_char_ioctl_get_nvm_size(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
 
-		pReadData = memdup_user(stNVMReadWrite.pBuffer,
-					stNVMReadWrite.uiNumBytes);
-		if (IS_ERR(pReadData))
-			return PTR_ERR(pReadData);
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		do_gettimeofday(&tv0);
-		if (IOCTL_BCM_NVM_READ == cmd) {
-			down(&Adapter->NVMRdmWrmLock);
+	if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
+		if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
+			return -EFAULT;
+	}
 
-			if ((Adapter->IdleMode == TRUE) ||
-				(Adapter->bShutStatus == TRUE) ||
-				(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	return STATUS_SUCCESS;
+}
 
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-				up(&Adapter->NVMRdmWrmLock);
-				kfree(pReadData);
-				return -EACCES;
-			}
+static int bcm_char_ioctl_cal_init(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	UINT uiSectorSize = 0;
+	INT Status = STATUS_FAILURE;
 
-			Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
-			up(&Adapter->NVMRdmWrmLock);
+	if (Adapter->eNVMType == NVM_FLASH) {
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+			return -EFAULT;
 
-			if (Status != STATUS_SUCCESS) {
-				kfree(pReadData);
-				return Status;
-			}
+		if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
+			return -EFAULT;
 
-			if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
-				kfree(pReadData);
+		if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) {
+			if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
+						sizeof(UINT)))
 				return -EFAULT;
-			}
 		} else {
-			down(&Adapter->NVMRdmWrmLock);
-
-			if ((Adapter->IdleMode == TRUE) ||
-				(Adapter->bShutStatus == TRUE) ||
-				(Adapter->bPreparingForLowPowerMode == TRUE)) {
-
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-				up(&Adapter->NVMRdmWrmLock);
-				kfree(pReadData);
-				return -EACCES;
-			}
-
-			Adapter->bHeaderChangeAllowed = TRUE;
 			if (IsFlash2x(Adapter)) {
-				/*
-				 *			New Requirement:-
-				 *			DSD section updation will be allowed in two case:-
-				 *			1.  if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
-				 *			2.  if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
-				 *			      corrupted then user space program first modify the DSD header with valid DSD sig so
-				 *			      that this as well as further write may be worthwhile.
-				 *
-				 *			 This restriction has been put assuming that if DSD sig is corrupted, DSD
-				 *			 data won't be considered valid.
-				 */
-
-				Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
-				if (Status != STATUS_SUCCESS) {
-					if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) ||
-						(stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) {
-
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
-						up(&Adapter->NVMRdmWrmLock);
-						kfree(pReadData);
-						return Status;
-					}
-
-					ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
-					if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
-						up(&Adapter->NVMRdmWrmLock);
-						kfree(pReadData);
-						return Status;
-					}
+				if (copy_to_user(IoBuffer.OutputBuffer,	&Adapter->uiSectorSize, sizeof(UINT)))
+					return -EFAULT;
+			} else {
+				if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) {
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n");
+					return -EACCES;
 				}
+
+				Adapter->uiSectorSize = uiSectorSize;
+				BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize);
 			}
+		}
+		Status = STATUS_SUCCESS;
+	} else {
+		Status = STATUS_FAILURE;
+	}
+	return Status;
+}
 
-			Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
-			if (IsFlash2x(Adapter))
-				BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
+static int bcm_char_ioctl_set_debug(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+#ifdef DEBUG
+	struct bcm_ioctl_buffer IoBuffer;
+	struct bcm_user_debug_state sUserDebugState;
 
-			Adapter->bHeaderChangeAllowed = false;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-			up(&Adapter->NVMRdmWrmLock);
+	if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(struct bcm_user_debug_state)))
+		return -EFAULT;
 
-			if (Status != STATUS_SUCCESS) {
-				kfree(pReadData);
-				return Status;
-			}
-		}
+	BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
+			sUserDebugState.OnOff, sUserDebugState.Type);
+	/* sUserDebugState.Subtype <<= 1; */
+	sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
+	BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
+
+	/* Update new 'DebugState' in the Adapter */
+	Adapter->stDebugState.type |= sUserDebugState.Type;
+	/* Subtype: A bitmap of 32 bits for Subtype per Type.
+	 * Valid indexes in 'subtype' array: 1,2,4,8
+	 * corresponding to valid Type values. Hence we can use the 'Type' field
+	 * as the index value, ignoring the array entries 0,3,5,6,7 !
+	 */
+	if (sUserDebugState.OnOff)
+		Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
+	else
+		Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
+
+	BCM_SHOW_DEBUG_BITMAP(Adapter);
+#endif
+	return STATUS_SUCCESS;
+}
 
-		do_gettimeofday(&tv1);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
+static int bcm_char_ioctl_nvm_rw(void __user *argp, struct bcm_mini_adapter *Adapter, UINT cmd)
+{
+	struct bcm_nvm_readwrite stNVMReadWrite;
+	struct timeval tv0, tv1;
+	struct bcm_ioctl_buffer IoBuffer;
+	PUCHAR pReadData = NULL;
+	ULONG ulDSDMagicNumInUsrBuff = 0;
+	INT Status = STATUS_FAILURE;
 
-		kfree(pReadData);
-		return STATUS_SUCCESS;
+	memset(&tv0, 0, sizeof(struct timeval));
+	memset(&tv1, 0, sizeof(struct timeval));
+	if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
+		return -EFAULT;
 	}
 
-	case IOCTL_BCM_FLASH2X_SECTION_READ: {
-		struct bcm_flash2x_readwrite sFlash2xRead = {0};
-		PUCHAR pReadBuff = NULL;
-		UINT NOB = 0;
-		UINT BuffSize = 0;
-		UINT ReadBytes = 0;
-		UINT ReadOffset = 0;
-		void __user *OutPutBuff;
+	if (IsFlash2x(Adapter)) {
+		if ((Adapter->eActiveDSD != DSD0) &&
+			(Adapter->eActiveDSD != DSD1) &&
+			(Adapter->eActiveDSD != DSD2)) {
 
-		if (IsFlash2x(Adapter) != TRUE)	{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
-			return -EINVAL;
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
+			return STATUS_FAILURE;
 		}
+	}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		/* Reading FLASH 2.x READ structure */
-		if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
-			return -EFAULT;
+	if (copy_from_user(&stNVMReadWrite,
+				(IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
+				sizeof(struct bcm_nvm_readwrite)))
+		return -EFAULT;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
+	/*
+	 * Deny the access if the offset crosses the cal area limit.
+	 */
+	if (stNVMReadWrite.uiNumBytes > Adapter->uiNVMDSDSize)
+		return STATUS_FAILURE;
 
-		/* This was internal to driver for raw read. now it has ben exposed to user space app. */
-		if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == false)
-			return STATUS_FAILURE;
+	if (stNVMReadWrite.uiOffset > Adapter->uiNVMDSDSize - stNVMReadWrite.uiNumBytes) {
+		/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
+		return STATUS_FAILURE;
+	}
 
-		NOB = sFlash2xRead.numOfBytes;
-		if (NOB > Adapter->uiSectorSize)
-			BuffSize = Adapter->uiSectorSize;
-		else
-			BuffSize = NOB;
+	pReadData = memdup_user(stNVMReadWrite.pBuffer,
+				stNVMReadWrite.uiNumBytes);
+	if (IS_ERR(pReadData))
+		return PTR_ERR(pReadData);
+
+	do_gettimeofday(&tv0);
+	if (IOCTL_BCM_NVM_READ == cmd) {
+		down(&Adapter->NVMRdmWrmLock);
+
+		if ((Adapter->IdleMode == TRUE) ||
+			(Adapter->bShutStatus == TRUE) ||
+			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+			up(&Adapter->NVMRdmWrmLock);
+			kfree(pReadData);
+			return -EACCES;
+		}
 
-		ReadOffset = sFlash2xRead.offset;
-		OutPutBuff = IoBuffer.OutputBuffer;
-		pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
+		Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
+		up(&Adapter->NVMRdmWrmLock);
+
+		if (Status != STATUS_SUCCESS) {
+			kfree(pReadData);
+			return Status;
+		}
 
-		if (pReadBuff == NULL) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
-			return -ENOMEM;
+		if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
+			kfree(pReadData);
+			return -EFAULT;
 		}
+	} else {
 		down(&Adapter->NVMRdmWrmLock);
 
 		if ((Adapter->IdleMode == TRUE) ||
@@ -1506,544 +1376,930 @@ cntrlEnd:
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
 			up(&Adapter->NVMRdmWrmLock);
-			kfree(pReadBuff);
+			kfree(pReadData);
 			return -EACCES;
 		}
 
-		while (NOB) {
-			if (NOB > Adapter->uiSectorSize)
-				ReadBytes = Adapter->uiSectorSize;
-			else
-				ReadBytes = NOB;
+		Adapter->bHeaderChangeAllowed = TRUE;
+		if (IsFlash2x(Adapter)) {
+			/*
+			 *			New Requirement:-
+			 *			DSD section updation will be allowed in two case:-
+			 *			1.  if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
+			 *			2.  if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
+			 *			      corrupted then user space program first modify the DSD header with valid DSD sig so
+			 *			      that this as well as further write may be worthwhile.
+			 *
+			 *			 This restriction has been put assuming that if DSD sig is corrupted, DSD
+			 *			 data won't be considered valid.
+			 */
 
-			/* Reading the data from Flash 2.x */
-			Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes);
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status);
-				break;
-			}
+			Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
+			if (Status != STATUS_SUCCESS) {
+				if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) ||
+					(stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) {
 
-			BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+					up(&Adapter->NVMRdmWrmLock);
+					kfree(pReadData);
+					return Status;
+				}
 
-			Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
-				up(&Adapter->NVMRdmWrmLock);
-				kfree(pReadBuff);
-				return -EFAULT;
-			}
-			NOB = NOB - ReadBytes;
-			if (NOB) {
-				ReadOffset = ReadOffset + ReadBytes;
-				OutPutBuff = OutPutBuff + ReadBytes;
+				ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
+				if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+					up(&Adapter->NVMRdmWrmLock);
+					kfree(pReadData);
+					return Status;
+				}
 			}
 		}
 
-		up(&Adapter->NVMRdmWrmLock);
-		kfree(pReadBuff);
-	}
-	break;
+		Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
+		if (IsFlash2x(Adapter))
+			BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
 
-	case IOCTL_BCM_FLASH2X_SECTION_WRITE: {
-		struct bcm_flash2x_readwrite sFlash2xWrite = {0};
-		PUCHAR pWriteBuff;
-		void __user *InputAddr;
-		UINT NOB = 0;
-		UINT BuffSize = 0;
-		UINT WriteOffset = 0;
-		UINT WriteBytes = 0;
+		Adapter->bHeaderChangeAllowed = false;
 
-		if (IsFlash2x(Adapter) != TRUE) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
-			return -EINVAL;
+		up(&Adapter->NVMRdmWrmLock);
+
+		if (Status != STATUS_SUCCESS) {
+			kfree(pReadData);
+			return Status;
 		}
+	}
 
-		/* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
-		Adapter->bAllDSDWriteAllow = false;
+	do_gettimeofday(&tv1);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
+	kfree(pReadData);
+	return STATUS_SUCCESS;
+}
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+static int bcm_char_ioctl_flash2x_section_read(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_flash2x_readwrite sFlash2xRead = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	PUCHAR pReadBuff = NULL;
+	UINT NOB = 0;
+	UINT BuffSize = 0;
+	UINT ReadBytes = 0;
+	UINT ReadOffset = 0;
+	INT Status = STATUS_FAILURE;
+	void __user *OutPutBuff;
 
-		/* Reading FLASH 2.x READ structure */
-		if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
-			return -EFAULT;
+	if (IsFlash2x(Adapter) != TRUE)	{
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+		return -EINVAL;
+	}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed");
-			return -EINVAL;
-		}
+	/* Reading FLASH 2.x READ structure */
+	if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
+		return -EFAULT;
 
-		if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == false)
-			return STATUS_FAILURE;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
 
-		InputAddr = sFlash2xWrite.pDataBuff;
-		WriteOffset = sFlash2xWrite.offset;
-		NOB = sFlash2xWrite.numOfBytes;
+	/* This was internal to driver for raw read. now it has ben exposed to user space app. */
+	if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == false)
+		return STATUS_FAILURE;
 
-		if (NOB > Adapter->uiSectorSize)
-			BuffSize = Adapter->uiSectorSize;
-		else
-			BuffSize = NOB;
+	NOB = sFlash2xRead.numOfBytes;
+	if (NOB > Adapter->uiSectorSize)
+		BuffSize = Adapter->uiSectorSize;
+	else
+		BuffSize = NOB;
 
-		pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
+	ReadOffset = sFlash2xRead.offset;
+	OutPutBuff = IoBuffer.OutputBuffer;
+	pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
 
-		if (pWriteBuff == NULL)
-			return -ENOMEM;
+	if (pReadBuff == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+		return -ENOMEM;
+	}
+	down(&Adapter->NVMRdmWrmLock);
 
-		/* extracting the remainder of the given offset. */
-		WriteBytes = Adapter->uiSectorSize;
-		if (WriteOffset % Adapter->uiSectorSize)
-			WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-		if (NOB < WriteBytes)
-			WriteBytes = NOB;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+		up(&Adapter->NVMRdmWrmLock);
+		kfree(pReadBuff);
+		return -EACCES;
+	}
 
-		down(&Adapter->NVMRdmWrmLock);
+	while (NOB) {
+		if (NOB > Adapter->uiSectorSize)
+			ReadBytes = Adapter->uiSectorSize;
+		else
+			ReadBytes = NOB;
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+		/* Reading the data from Flash 2.x */
+		Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes);
+		if (Status) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status);
+			break;
+		}
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+		BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+		Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+		if (Status) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
 			up(&Adapter->NVMRdmWrmLock);
-			kfree(pWriteBuff);
-			return -EACCES;
+			kfree(pReadBuff);
+			return -EFAULT;
 		}
+		NOB = NOB - ReadBytes;
+		if (NOB) {
+			ReadOffset = ReadOffset + ReadBytes;
+			OutPutBuff = OutPutBuff + ReadBytes;
+		}
+	}
 
-		BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
-		do {
-			Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
-				up(&Adapter->NVMRdmWrmLock);
-				kfree(pWriteBuff);
-				return -EFAULT;
-			}
-			BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
+	up(&Adapter->NVMRdmWrmLock);
+	kfree(pReadBuff);
+	return Status;
+}
 
-			/* Writing the data from Flash 2.x */
-			Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify);
+static int bcm_char_ioctl_flash2x_section_write(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_flash2x_readwrite sFlash2xWrite = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	PUCHAR pWriteBuff;
+	void __user *InputAddr;
+	UINT NOB = 0;
+	UINT BuffSize = 0;
+	UINT WriteOffset = 0;
+	UINT WriteBytes = 0;
+	INT Status = STATUS_FAILURE;
 
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
-				break;
-			}
+	if (IsFlash2x(Adapter) != TRUE) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+		return -EINVAL;
+	}
 
-			NOB = NOB - WriteBytes;
-			if (NOB) {
-				WriteOffset = WriteOffset + WriteBytes;
-				InputAddr = InputAddr + WriteBytes;
-				if (NOB > Adapter->uiSectorSize)
-					WriteBytes = Adapter->uiSectorSize;
-				else
-					WriteBytes = NOB;
-			}
-		} while (NOB > 0);
+	/* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
+	Adapter->bAllDSDWriteAllow = false;
 
-		BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
-		up(&Adapter->NVMRdmWrmLock);
-		kfree(pWriteBuff);
-	}
-	break;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
 
-	case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: {
-		struct bcm_flash2x_bitmap *psFlash2xBitMap;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	/* Reading FLASH 2.x READ structure */
+	if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
+		return -EFAULT;
 
-		if (IoBuffer.OutputLength != sizeof(struct bcm_flash2x_bitmap))
-			return -EINVAL;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
 
-		psFlash2xBitMap = kzalloc(sizeof(struct bcm_flash2x_bitmap), GFP_KERNEL);
-		if (psFlash2xBitMap == NULL) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
-			return -ENOMEM;
-		}
+	if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed");
+		return -EINVAL;
+	}
 
-		/* Reading the Flash Sectio Bit map */
-		down(&Adapter->NVMRdmWrmLock);
+	if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == false)
+		return STATUS_FAILURE;
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	InputAddr = sFlash2xWrite.pDataBuff;
+	WriteOffset = sFlash2xWrite.offset;
+	NOB = sFlash2xWrite.numOfBytes;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-			up(&Adapter->NVMRdmWrmLock);
-			kfree(psFlash2xBitMap);
-			return -EACCES;
-		}
+	if (NOB > Adapter->uiSectorSize)
+		BuffSize = Adapter->uiSectorSize;
+	else
+		BuffSize = NOB;
 
-		BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
-		up(&Adapter->NVMRdmWrmLock);
-		if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(struct bcm_flash2x_bitmap))) {
-			kfree(psFlash2xBitMap);
-			return -EFAULT;
-		}
+	pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
 
-		kfree(psFlash2xBitMap);
-	}
-	break;
+	if (pWriteBuff == NULL)
+		return -ENOMEM;
 
-	case IOCTL_BCM_SET_ACTIVE_SECTION: {
-		enum bcm_flash2x_section_val eFlash2xSectionVal = 0;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
+	/* extracting the remainder of the given offset. */
+	WriteBytes = Adapter->uiSectorSize;
+	if (WriteOffset % Adapter->uiSectorSize)
+		WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
 
-		if (IsFlash2x(Adapter) != TRUE) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
-			return -EINVAL;
-		}
+	if (NOB < WriteBytes)
+		WriteBytes = NOB;
+
+	down(&Adapter->NVMRdmWrmLock);
+
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+		up(&Adapter->NVMRdmWrmLock);
+		kfree(pWriteBuff);
+		return -EACCES;
+	}
+
+	BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
+	do {
+		Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
 		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
+			up(&Adapter->NVMRdmWrmLock);
+			kfree(pWriteBuff);
 			return -EFAULT;
 		}
+		BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
+
+		/* Writing the data from Flash 2.x */
+		Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify);
 
-		Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
 		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
-			return -EFAULT;
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
+			break;
 		}
 
-		down(&Adapter->NVMRdmWrmLock);
+		NOB = NOB - WriteBytes;
+		if (NOB) {
+			WriteOffset = WriteOffset + WriteBytes;
+			InputAddr = InputAddr + WriteBytes;
+			if (NOB > Adapter->uiSectorSize)
+				WriteBytes = Adapter->uiSectorSize;
+			else
+				WriteBytes = NOB;
+		}
+	} while (NOB > 0);
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
+	up(&Adapter->NVMRdmWrmLock);
+	kfree(pWriteBuff);
+	return Status;
+}
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-			up(&Adapter->NVMRdmWrmLock);
-			return -EACCES;
-		}
+static int bcm_char_ioctl_flash2x_section_bitmap(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_flash2x_bitmap *psFlash2xBitMap;
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_FAILURE;
+
+BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
+
+	if (IoBuffer.OutputLength != sizeof(struct bcm_flash2x_bitmap))
+		return -EINVAL;
 
-		Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
-		if (Status)
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status);
+	psFlash2xBitMap = kzalloc(sizeof(struct bcm_flash2x_bitmap), GFP_KERNEL);
+	if (psFlash2xBitMap == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
+		return -ENOMEM;
+	}
+
+	/* Reading the Flash Sectio Bit map */
+	down(&Adapter->NVMRdmWrmLock);
+
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
 		up(&Adapter->NVMRdmWrmLock);
+		kfree(psFlash2xBitMap);
+		return -EACCES;
 	}
-	break;
 
-	case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: {
-		/* Right Now we are taking care of only DSD */
-		Adapter->bAllDSDWriteAllow = false;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
-		Status = STATUS_SUCCESS;
+	BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
+	up(&Adapter->NVMRdmWrmLock);
+	if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(struct bcm_flash2x_bitmap))) {
+		kfree(psFlash2xBitMap);
+		return -EFAULT;
 	}
-	break;
 
-	case IOCTL_BCM_COPY_SECTION: {
-		struct bcm_flash2x_copy_section sCopySectStrut = {0};
-		Status = STATUS_SUCCESS;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION  Called");
+	kfree(psFlash2xBitMap);
+	return Status;
+}
 
-		Adapter->bAllDSDWriteAllow = false;
-		if (IsFlash2x(Adapter) != TRUE) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
-			return -EINVAL;
-		}
+static int bcm_char_ioctl_set_active_section(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	enum bcm_flash2x_section_val eFlash2xSectionVal = 0;
+	INT Status = STATUS_FAILURE;
+	struct bcm_ioctl_buffer IoBuffer;
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
-			return -EFAULT;
-		}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
 
-		Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_copy_section));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
-			return -EFAULT;
-		}
+	if (IsFlash2x(Adapter) != TRUE) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+		return -EINVAL;
+	}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
+	Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+		return -EFAULT;
+	}
 
-		if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == false) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exist in Flash ", sCopySectStrut.SrcSection);
-			return -EINVAL;
-		}
+	Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+		return -EFAULT;
+	}
 
-		if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == false) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exist in Flash ", sCopySectStrut.DstSection);
-			return -EINVAL;
-		}
+	down(&Adapter->NVMRdmWrmLock);
 
-		if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different");
-			return -EINVAL;
-		}
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-		down(&Adapter->NVMRdmWrmLock);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+		up(&Adapter->NVMRdmWrmLock);
+		return -EACCES;
+	}
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
+	if (Status)
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status);
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-			up(&Adapter->NVMRdmWrmLock);
-			return -EACCES;
-		}
+	up(&Adapter->NVMRdmWrmLock);
 
-		if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) {
-			if (IsNonCDLessDevice(Adapter)) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!");
-				Status = -EINVAL;
-			} else if (sCopySectStrut.numOfBytes == 0) {
-				Status = BcmCopyISO(Adapter, sCopySectStrut);
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed..");
-				Status = STATUS_FAILURE;
-			}
-			up(&Adapter->NVMRdmWrmLock);
-			return Status;
-		}
+	return Status;
+}
 
-		Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
-					sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes);
-		up(&Adapter->NVMRdmWrmLock);
+static int bcm_char_ioctl_copy_section(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_flash2x_copy_section sCopySectStrut = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_SUCCESS;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION  Called");
+
+	Adapter->bAllDSDWriteAllow = false;
+	if (IsFlash2x(Adapter) != TRUE) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+		return -EINVAL;
 	}
-	break;
 
-	case IOCTL_BCM_GET_FLASH_CS_INFO: {
-		Status = STATUS_SUCCESS;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
+	Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
+		return -EFAULT;
+	}
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
-			return -EFAULT;
-		}
+	Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_copy_section));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
+		return -EFAULT;
+	}
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
+
+	if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == false) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exist in Flash ", sCopySectStrut.SrcSection);
+		return -EINVAL;
+	}
+
+	if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == false) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exist in Flash ", sCopySectStrut.DstSection);
+		return -EINVAL;
+	}
+
+	if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different");
+		return -EINVAL;
+	}
+
+	down(&Adapter->NVMRdmWrmLock);
+
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+		up(&Adapter->NVMRdmWrmLock);
+		return -EACCES;
+	}
 
-		if (Adapter->eNVMType != NVM_FLASH) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash");
+	if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) {
+		if (IsNonCDLessDevice(Adapter)) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!");
 			Status = -EINVAL;
-			break;
+		} else if (sCopySectStrut.numOfBytes == 0) {
+			Status = BcmCopyISO(Adapter, sCopySectStrut);
+		} else {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed..");
+			Status = STATUS_FAILURE;
 		}
+		up(&Adapter->NVMRdmWrmLock);
+		return Status;
+	}
 
-		if (IsFlash2x(Adapter) == TRUE) {
-			if (IoBuffer.OutputLength < sizeof(struct bcm_flash2x_cs_info))
-				return -EINVAL;
+	Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
+				sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes);
+	up(&Adapter->NVMRdmWrmLock);
+	return Status;
+}
 
-			if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(struct bcm_flash2x_cs_info)))
-				return -EFAULT;
-		} else {
-			if (IoBuffer.OutputLength < sizeof(struct bcm_flash_cs_info))
-				return -EINVAL;
+static int bcm_char_ioctl_get_flash_cs_info(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_SUCCESS;
 
-			if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(struct bcm_flash_cs_info)))
-				return -EFAULT;
-		}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
+
+	Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+		return -EFAULT;
 	}
-	break;
 
-	case IOCTL_BCM_SELECT_DSD: {
-		UINT SectOfset = 0;
-		enum bcm_flash2x_section_val eFlash2xSectionVal;
-		eFlash2xSectionVal = NO_SECTION_VAL;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
+	if (Adapter->eNVMType != NVM_FLASH) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash");
+		return -EINVAL;
+	}
 
-		if (IsFlash2x(Adapter) != TRUE) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+	if (IsFlash2x(Adapter) == TRUE) {
+		if (IoBuffer.OutputLength < sizeof(struct bcm_flash2x_cs_info))
 			return -EINVAL;
-		}
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+		if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(struct bcm_flash2x_cs_info)))
 			return -EFAULT;
-		}
-		Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+	} else {
+		if (IoBuffer.OutputLength < sizeof(struct bcm_flash_cs_info))
+			return -EINVAL;
+
+		if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(struct bcm_flash_cs_info)))
 			return -EFAULT;
-		}
+	}
+	return Status;
+}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
-		if ((eFlash2xSectionVal != DSD0) &&
-			(eFlash2xSectionVal != DSD1) &&
-			(eFlash2xSectionVal != DSD2)) {
+static int bcm_char_ioctl_select_dsd(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_FAILURE;
+	UINT SectOfset = 0;
+	enum bcm_flash2x_section_val eFlash2xSectionVal;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal);
-			return STATUS_FAILURE;
-		}
+	eFlash2xSectionVal = NO_SECTION_VAL;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
 
-		SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
-		if (SectOfset == INVALID_OFFSET) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exist in Flash 2.x", eFlash2xSectionVal);
-			return -EINVAL;
-		}
+	if (IsFlash2x(Adapter) != TRUE) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+		return -EINVAL;
+	}
 
-		Adapter->bAllDSDWriteAllow = TRUE;
-		Adapter->ulFlashCalStart = SectOfset;
-		Adapter->eActiveDSD = eFlash2xSectionVal;
+	Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+		return -EFAULT;
+	}
+	Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+		return -EFAULT;
 	}
-	Status = STATUS_SUCCESS;
-	break;
 
-	case IOCTL_BCM_NVM_RAW_READ: {
-		struct bcm_nvm_readwrite stNVMRead;
-		INT NOB;
-		INT BuffSize;
-		INT ReadOffset = 0;
-		UINT ReadBytes = 0;
-		PUCHAR pReadBuff;
-		void __user *OutPutBuff;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
+	if ((eFlash2xSectionVal != DSD0) &&
+		(eFlash2xSectionVal != DSD1) &&
+		(eFlash2xSectionVal != DSD2)) {
 
-		if (Adapter->eNVMType != NVM_FLASH) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash");
-			return -EINVAL;
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal);
+		return STATUS_FAILURE;
+	}
 
-		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
-			return -EFAULT;
-		}
+	SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+	if (SectOfset == INVALID_OFFSET) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exist in Flash 2.x", eFlash2xSectionVal);
+		return -EINVAL;
+	}
 
-		if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(struct bcm_nvm_readwrite)))
-			return -EFAULT;
+	Adapter->bAllDSDWriteAllow = TRUE;
+	Adapter->ulFlashCalStart = SectOfset;
+	Adapter->eActiveDSD = eFlash2xSectionVal;
 
-		NOB = stNVMRead.uiNumBytes;
-		/* In Raw-Read max Buff size : 64MB */
+	return STATUS_SUCCESS;
+}
 
-		if (NOB > DEFAULT_BUFF_SIZE)
-			BuffSize = DEFAULT_BUFF_SIZE;
-		else
-			BuffSize = NOB;
+static int bcm_char_ioctl_nvm_raw_read(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_nvm_readwrite stNVMRead;
+	struct bcm_ioctl_buffer IoBuffer;
+	unsigned int NOB;
+	INT BuffSize;
+	INT ReadOffset = 0;
+	UINT ReadBytes = 0;
+	PUCHAR pReadBuff;
+	void __user *OutPutBuff;
+	INT Status = STATUS_FAILURE;
 
-		ReadOffset = stNVMRead.uiOffset;
-		OutPutBuff = stNVMRead.pBuffer;
+	if (Adapter->eNVMType != NVM_FLASH) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash");
+		return -EINVAL;
+	}
 
-		pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
-		if (pReadBuff == NULL) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
-			Status = -ENOMEM;
-			break;
-		}
-		down(&Adapter->NVMRdmWrmLock);
+	/* Copy Ioctl Buffer structure */
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
+		return -EFAULT;
+	}
 
-		if ((Adapter->IdleMode == TRUE) ||
-			(Adapter->bShutStatus == TRUE) ||
-			(Adapter->bPreparingForLowPowerMode == TRUE)) {
+	if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(struct bcm_nvm_readwrite)))
+		return -EFAULT;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
-			kfree(pReadBuff);
-			up(&Adapter->NVMRdmWrmLock);
-			return -EACCES;
-		}
+	NOB = stNVMRead.uiNumBytes;
+	/* In Raw-Read max Buff size : 64MB */
 
-		Adapter->bFlashRawRead = TRUE;
+	if (NOB > DEFAULT_BUFF_SIZE)
+		BuffSize = DEFAULT_BUFF_SIZE;
+	else
+		BuffSize = NOB;
 
-		while (NOB) {
-			if (NOB > DEFAULT_BUFF_SIZE)
-				ReadBytes = DEFAULT_BUFF_SIZE;
-			else
-				ReadBytes = NOB;
+	ReadOffset = stNVMRead.uiOffset;
+	OutPutBuff = stNVMRead.pBuffer;
 
-			/* Reading the data from Flash 2.x */
-			Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes);
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
-				break;
-			}
+	pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
+	if (pReadBuff == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+		return -ENOMEM;
+	}
+	down(&Adapter->NVMRdmWrmLock);
 
-			BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+	if ((Adapter->IdleMode == TRUE) ||
+		(Adapter->bShutStatus == TRUE) ||
+		(Adapter->bPreparingForLowPowerMode == TRUE)) {
 
-			Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
-			if (Status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
-				up(&Adapter->NVMRdmWrmLock);
-				kfree(pReadBuff);
-				return -EFAULT;
-			}
-			NOB = NOB - ReadBytes;
-			if (NOB) {
-				ReadOffset = ReadOffset + ReadBytes;
-				OutPutBuff = OutPutBuff + ReadBytes;
-			}
-		}
-		Adapter->bFlashRawRead = false;
-		up(&Adapter->NVMRdmWrmLock);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
 		kfree(pReadBuff);
-		break;
+		up(&Adapter->NVMRdmWrmLock);
+		return -EACCES;
 	}
 
-	case IOCTL_BCM_CNTRLMSG_MASK: {
-		ULONG RxCntrlMsgBitMask = 0;
+	Adapter->bFlashRawRead = TRUE;
 
-		/* Copy Ioctl Buffer structure */
-		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
-		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
-			return -EFAULT;
-		}
+	while (NOB) {
+		if (NOB > DEFAULT_BUFF_SIZE)
+			ReadBytes = DEFAULT_BUFF_SIZE;
+		else
+			ReadBytes = NOB;
 
-		if (IoBuffer.InputLength != sizeof(unsigned long)) {
-			Status = -EINVAL;
+		/* Reading the data from Flash 2.x */
+		Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes);
+		if (Status) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
 			break;
 		}
 
-		Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
+		BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+		Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
 		if (Status) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
+			up(&Adapter->NVMRdmWrmLock);
+			kfree(pReadBuff);
 			return -EFAULT;
 		}
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
-		pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
+		NOB = NOB - ReadBytes;
+		if (NOB) {
+			ReadOffset = ReadOffset + ReadBytes;
+			OutPutBuff = OutPutBuff + ReadBytes;
+		}
 	}
-	break;
+	Adapter->bFlashRawRead = false;
+	up(&Adapter->NVMRdmWrmLock);
+	kfree(pReadBuff);
+	return Status;
+}
 
-	case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: {
-		struct bcm_driver_info DevInfo;
+static int bcm_char_ioctl_cntrlmsg_mask(void __user *argp, struct bcm_mini_adapter *Adapter, struct bcm_tarang_data *pTarang)
+{
+	struct bcm_ioctl_buffer IoBuffer;
+	INT Status = STATUS_FAILURE;
+	ULONG RxCntrlMsgBitMask = 0;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+	/* Copy Ioctl Buffer structure */
+	Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
+		return -EFAULT;
+	}
 
-		memset(&DevInfo, 0, sizeof(DevInfo));
-		DevInfo.MaxRDMBufferSize = BUFFER_4K;
-		DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
-		DevInfo.u32RxAlignmentCorrection = 0;
-		DevInfo.u32NVMType = Adapter->eNVMType;
-		DevInfo.u32InterfaceType = BCM_USB;
+	if (IoBuffer.InputLength != sizeof(unsigned long))
+		return -EINVAL;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
+	if (Status) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
+		return -EFAULT;
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
+	pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
 
-		if (IoBuffer.OutputLength < sizeof(DevInfo))
-			return -EINVAL;
+	return Status;
+}
 
-		if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
-			return -EFAULT;
+static int bcm_char_ioctl_get_device_driver_info(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_driver_info DevInfo;
+	struct bcm_ioctl_buffer IoBuffer;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
+	memset(&DevInfo, 0, sizeof(DevInfo));
+	DevInfo.MaxRDMBufferSize = BUFFER_4K;
+	DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+	DevInfo.u32RxAlignmentCorrection = 0;
+	DevInfo.u32NVMType = Adapter->eNVMType;
+	DevInfo.u32InterfaceType = BCM_USB;
+
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
+
+	if (IoBuffer.OutputLength < sizeof(DevInfo))
+		return -EINVAL;
+
+	if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
+		return -EFAULT;
+
+	return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_time_since_net_entry(void __user *argp, struct bcm_mini_adapter *Adapter)
+{
+	struct bcm_time_elapsed stTimeElapsedSinceNetEntry = {0};
+	struct bcm_ioctl_buffer IoBuffer;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+
+	if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+		return -EFAULT;
+
+	if (IoBuffer.OutputLength < sizeof(struct bcm_time_elapsed))
+		return -EINVAL;
+
+	stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+
+	if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(struct bcm_time_elapsed)))
+		return -EFAULT;
+
+	return STATUS_SUCCESS;
+}
+
+
+static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
+{
+	struct bcm_tarang_data *pTarang = filp->private_data;
+	void __user *argp = (void __user *)arg;
+	struct bcm_mini_adapter *Adapter = pTarang->Adapter;
+	INT Status = STATUS_FAILURE;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+			"Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX",
+			cmd, arg);
+
+	if (_IOC_TYPE(cmd) != BCM_IOCTL)
+		return -EFAULT;
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+	else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
+		Status = STATUS_SUCCESS;
+
+	if (Status)
+		return -EFAULT;
+
+	if (Adapter->device_removed)
+		return -EFAULT;
+
+	if (false == Adapter->fw_download_done) {
+		switch (cmd) {
+		case IOCTL_MAC_ADDR_REQ:
+		case IOCTL_LINK_REQ:
+		case IOCTL_CM_REQUEST:
+		case IOCTL_SS_INFO_REQ:
+		case IOCTL_SEND_CONTROL_MESSAGE:
+		case IOCTL_IDLE_REQ:
+		case IOCTL_BCM_GPIO_SET_REQUEST:
+		case IOCTL_BCM_GPIO_STATUS_REQUEST:
+			return -EACCES;
+		default:
+			break;
+		}
 	}
-	break;
 
-	case IOCTL_BCM_TIME_SINCE_NET_ENTRY: {
-		struct bcm_time_elapsed stTimeElapsedSinceNetEntry = {0};
+	Status = vendorextnIoctl(Adapter, cmd, arg);
+	if (Status != CONTINUE_COMMON_PATH)
+		return Status;
+
+	switch (cmd) {
+	/* Rdms for Swin Idle... */
+	case IOCTL_BCM_REGISTER_READ_PRIVATE:
+		Status = bcm_char_ioctl_reg_read_private(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
+		Status = bcm_char_ioctl_reg_write_private(argp, Adapter);
+		return Status;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+	case IOCTL_BCM_REGISTER_READ:
+	case IOCTL_BCM_EEPROM_REGISTER_READ:
+		Status = bcm_char_ioctl_eeprom_reg_read(argp, Adapter);
+		return Status;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
-			return -EFAULT;
+	case IOCTL_BCM_REGISTER_WRITE:
+	case IOCTL_BCM_EEPROM_REGISTER_WRITE:
+		Status = bcm_char_ioctl_eeprom_reg_write(argp, Adapter, cmd);
+		return Status;
 
-		if (IoBuffer.OutputLength < sizeof(struct bcm_time_elapsed))
-			return -EINVAL;
+	case IOCTL_BCM_GPIO_SET_REQUEST:
+		Status = bcm_char_ioctl_gpio_set_request(argp, Adapter);
+		return Status;
+
+	case BCM_LED_THREAD_STATE_CHANGE_REQ:
+		Status = bcm_char_ioctl_led_thread_state_change_req(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GPIO_STATUS_REQUEST:
+		Status = bcm_char_ioctl_gpio_status_request(argp, Adapter);
+		return Status;
 
-		stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+	case IOCTL_BCM_GPIO_MULTI_REQUEST:
+		Status = bcm_char_ioctl_gpio_multi_request(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GPIO_MODE_REQUEST:
+		Status = bcm_char_ioctl_gpio_mode_request(argp, Adapter);
+		return Status;
+
+	case IOCTL_MAC_ADDR_REQ:
+	case IOCTL_LINK_REQ:
+	case IOCTL_CM_REQUEST:
+	case IOCTL_SS_INFO_REQ:
+	case IOCTL_SEND_CONTROL_MESSAGE:
+	case IOCTL_IDLE_REQ:
+		Status = bcm_char_ioctl_misc_request(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_BUFFER_DOWNLOAD_START:
+		Status = bcm_char_ioctl_buffer_download_start(Adapter);
+		return Status;
+
+	case IOCTL_BCM_BUFFER_DOWNLOAD:
+		Status = bcm_char_ioctl_buffer_download(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
+		Status = bcm_char_ioctl_buffer_download_stop(argp, Adapter);
+		return Status;
 
-		if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(struct bcm_time_elapsed)))
+
+	case IOCTL_BE_BUCKET_SIZE:
+		Status = 0;
+		if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
+			Status = -EFAULT;
+		break;
+
+	case IOCTL_RTPS_BUCKET_SIZE:
+		Status = 0;
+		if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
+			Status = -EFAULT;
+		break;
+
+	case IOCTL_CHIP_RESET:
+		Status = bcm_char_ioctl_chip_reset(Adapter);
+		return Status;
+
+	case IOCTL_QOS_THRESHOLD:
+		Status = bcm_char_ioctl_qos_threshold(arg, Adapter);
+		return Status;
+
+	case IOCTL_DUMP_PACKET_INFO:
+		DumpPackInfo(Adapter);
+		DumpPhsRules(&Adapter->stBCMPhsContext);
+		Status = STATUS_SUCCESS;
+		break;
+
+	case IOCTL_GET_PACK_INFO:
+		if (copy_to_user(argp, &Adapter->PackInfo, sizeof(struct bcm_packet_info)*NO_OF_QUEUES))
 			return -EFAULT;
-	}
-	break;
+		Status = STATUS_SUCCESS;
+		break;
+
+	case IOCTL_BCM_SWITCH_TRANSFER_MODE:
+		Status = bcm_char_ioctl_switch_transfer_mode(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GET_DRIVER_VERSION:
+		Status = bcm_char_ioctl_get_driver_version(argp);
+		return Status;
+
+	case IOCTL_BCM_GET_CURRENT_STATUS:
+		Status = bcm_char_ioctl_get_current_status(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_SET_MAC_TRACING:
+		Status = bcm_char_ioctl_set_mac_tracing(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GET_DSX_INDICATION:
+		Status = bcm_char_ioctl_get_dsx_indication(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GET_HOST_MIBS:
+		Status = bcm_char_ioctl_get_host_mibs(argp, Adapter, pTarang);
+		return Status;
+
+	case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
+		if ((false == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
+			Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+			Adapter->bWakeUpDevice = TRUE;
+			wake_up(&Adapter->process_rx_cntrlpkt);
+		}
+
+		Status = STATUS_SUCCESS;
+		break;
+
+	case IOCTL_BCM_BULK_WRM:
+		Status = bcm_char_ioctl_bulk_wrm(argp, Adapter, cmd);
+		return Status;
+
+	case IOCTL_BCM_GET_NVM_SIZE:
+		Status = bcm_char_ioctl_get_nvm_size(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_CAL_INIT:
+		Status = bcm_char_ioctl_cal_init(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_SET_DEBUG:
+		Status = bcm_char_ioctl_set_debug(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_NVM_READ:
+	case IOCTL_BCM_NVM_WRITE:
+		Status = bcm_char_ioctl_nvm_rw(argp, Adapter, cmd);
+		return Status;
+
+	case IOCTL_BCM_FLASH2X_SECTION_READ:
+		Status = bcm_char_ioctl_flash2x_section_read(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_FLASH2X_SECTION_WRITE:
+		Status = bcm_char_ioctl_flash2x_section_write(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP:
+		Status = bcm_char_ioctl_flash2x_section_bitmap(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_SET_ACTIVE_SECTION:
+		Status = bcm_char_ioctl_set_active_section(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION:
+		/* Right Now we are taking care of only DSD */
+		Adapter->bAllDSDWriteAllow = false;
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
+		Status = STATUS_SUCCESS;
+		break;
+
+	case IOCTL_BCM_COPY_SECTION:
+		Status = bcm_char_ioctl_copy_section(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_GET_FLASH_CS_INFO:
+		Status = bcm_char_ioctl_get_flash_cs_info(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_SELECT_DSD:
+		Status = bcm_char_ioctl_select_dsd(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_NVM_RAW_READ:
+		Status = bcm_char_ioctl_nvm_raw_read(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_CNTRLMSG_MASK:
+		Status = bcm_char_ioctl_cntrlmsg_mask(argp, Adapter, pTarang);
+		return Status;
+
+	case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
+		Status = bcm_char_ioctl_get_device_driver_info(argp, Adapter);
+		return Status;
+
+	case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
+		Status = bcm_char_ioctl_time_since_net_entry(argp, Adapter);
+		return Status;
 
 	case IOCTL_CLOSE_NOTIFICATION:
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION");
diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c
index ed285b2d892d..f1d7cb82fd7e 100644
--- a/drivers/staging/bcm/DDRInit.c
+++ b/drivers/staging/bcm/DDRInit.c
@@ -3,7 +3,7 @@
 
 
 #define DDR_DUMP_INTERNAL_DEVICE_MEMORY 0xBFC02B00
-#define MIPS_CLOCK_REG 	0x0f000820
+#define MIPS_CLOCK_REG 0x0f000820
 
 /* DDR INIT-133Mhz */
 #define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12  /* index for 0x0F007000 */
@@ -818,13 +818,13 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 	if ((Adapter->chip_id !=  BCS220_2) &&
 		(Adapter->chip_id !=  BCS220_2BC) &&
 		(Adapter->chip_id != BCS220_3)) {
-		retval = rdmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+		retval = rdmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
 		if (retval < 0) {
 			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 			return retval;
 		}
 		uiResetValue |= 0x44;
-		retval = wrmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+		retval = wrmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
 		if (retval < 0) {
 			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 			return retval;
@@ -871,7 +871,7 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 	case 0xbece0121:
 	case 0xbece0130:
 	case 0xbece0300:
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting);
 		switch (Adapter->DDRSetting) {
 		case DDR_80_MHZ:
 			psDDRSetting = asT3_DDRSetting80MHz;
@@ -933,7 +933,7 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 	}
 
 	value = 0;
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount);
 	while (RegCount && !retval) {
 		if (uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG)
 			value = uiClockSetting;
@@ -990,12 +990,12 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 		 * we will change this when we will have internal PMU.
 		 */
 		if (Adapter->PmuMode == HYBRID_MODE_7C) {
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
@@ -1006,12 +1006,12 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
@@ -1024,12 +1024,12 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 			}
 		} else if (Adapter->PmuMode == HYBRID_MODE_6) {
 
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
@@ -1040,12 +1040,12 @@ int ddr_init(struct bcm_mini_adapter *Adapter)
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
 				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
 				return retval;
@@ -1094,8 +1094,8 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter)
 			RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
 			psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
 			break;
-			default:
-			    return -EINVAL;
+		default:
+			return -EINVAL;
 		}
 		break;
 
@@ -1215,7 +1215,7 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter)
 		ul_ddr_setting_load_addr += sizeof(ULONG);
 		if (!retval) {
 			if (bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) {
-				value = (psDDRSetting->ulRegValue |(1<<8));
+				value = (psDDRSetting->ulRegValue | (1<<8));
 			if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr,
 				&value, sizeof(value))) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index 94f32728f7c8..5b03a19778d6 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -1,5 +1,5 @@
 #include "headers.h"
-
+#include <linux/usb/ch9.h>
 static struct usb_device_id InterfaceUsbtable[] = {
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
@@ -347,81 +347,6 @@ static int device_run(struct bcm_interface_adapter *psIntfAdapter)
 	return 0;
 }
 
-
-static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_BULK);
-}
-
-static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_CONTROL);
-}
-
-static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_INT);
-}
-
-static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_ISOC);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
 static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 {
 	struct usb_host_interface *iface_desc;
@@ -481,8 +406,8 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 				 * If Modem is high speed device EP2 should be INT OUT End point
 				 * If Mode is FS then EP2 should be bulk end point
 				 */
-				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (bcm_usb_endpoint_is_int_out(endpoint) == false))
-					|| ((psIntfAdapter->bHighSpeedDevice == false) && (bcm_usb_endpoint_is_bulk_out(endpoint) == false))) {
+				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (usb_endpoint_is_int_out(endpoint) == false))
+					|| ((psIntfAdapter->bHighSpeedDevice == false) && (usb_endpoint_is_bulk_out(endpoint) == false))) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Configuring the EEPROM\n");
 					/* change the EP2, EP4 to INT OUT end point */
@@ -501,7 +426,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 					}
 
 				}
-				if ((psIntfAdapter->bHighSpeedDevice == false) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+				if ((psIntfAdapter->bHighSpeedDevice == false) && usb_endpoint_is_bulk_out(endpoint)) {
 					/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
 					UINT _uiData = ntohl(EP2_CFG_INT);
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
@@ -513,7 +438,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 				endpoint = &iface_desc->endpoint[EP4].desc;
 				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 					"Choosing AltSetting as a default setting.\n");
-				if (bcm_usb_endpoint_is_int_out(endpoint) == false) {
+				if (usb_endpoint_is_int_out(endpoint) == false) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Dongle does not have BCM16 Fix.\n");
 					/* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
@@ -541,7 +466,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 	for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) {
 		endpoint = &iface_desc->endpoint[value].desc;
 
-		if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint)) {
+		if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
 			psIntfAdapter->sBulkIn.bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -550,14 +475,14 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 								psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
 		}
 
-		if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+		if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) {
 			psIntfAdapter->sBulkOut.bulk_out_endpointAddr = endpoint->bEndpointAddress;
 			psIntfAdapter->sBulkOut.bulk_out_pipe =
 				usb_sndbulkpipe(psIntfAdapter->udev,
 					psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
 		}
 
-		if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint)) {
+		if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			psIntfAdapter->sIntrIn.int_in_size = buffer_size;
 			psIntfAdapter->sIntrIn.int_in_endpointAddr = endpoint->bEndpointAddress;
@@ -568,7 +493,7 @@ static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 				return -EINVAL;
 		}
 
-		if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint)) {
+		if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && usb_endpoint_is_int_out(endpoint)) {
 			if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
 				(psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer)) {
 				/* use first intout end point as a bulk out end point */
diff --git a/drivers/staging/bcm/Kconfig b/drivers/staging/bcm/Kconfig
index 83c9752504d4..8acf4b24a7c9 100644
--- a/drivers/staging/bcm/Kconfig
+++ b/drivers/staging/bcm/Kconfig
@@ -1,7 +1,6 @@
 config BCM_WIMAX
        tristate "Beceem BCS200/BCS220-3 and BCSM250 wimax support"
        depends on USB && NET
-       default N
        help
          This is an experimental driver for the Beceem WIMAX chipset used
 	 by Sprint 4G.
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
index 0727599bf5fa..4f315835ddfc 100644
--- a/drivers/staging/bcm/Qos.c
+++ b/drivers/staging/bcm/Qos.c
@@ -222,10 +222,7 @@ static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter,
 
 		//Checking classifier validity
 		if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
-		{
-			bClassificationSucceed = false;
 			break;
-		}
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
 		if (pstClassifierRule->bIpv6Protocol)
@@ -233,51 +230,47 @@ static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter,
 
 		//**************Checking IP header parameter**************************//
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-		if (false == (bClassificationSucceed =
-			MatchSrcIpAddress(pstClassifierRule, iphd->saddr)))
+		if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
+		if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchTos(pstClassifierRule, iphd->tos)))
-		{
+		if (!MatchTos(pstClassifierRule, iphd->tos)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
 			break;
 		}
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchProtocol(pstClassifierRule, iphd->protocol)))
+		if (!MatchProtocol(pstClassifierRule, iphd->protocol))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
 
 		//if protocol is not TCP or UDP then no need of comparing source port and destination port
-		if (iphd->protocol != TCP && iphd->protocol != UDP)
+		if (iphd->protocol != TCP && iphd->protocol != UDP) {
+			bClassificationSucceed = TRUE;
 			break;
+		}
 		//******************Checking Transport Layer Header field if present *****************//
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-		if (false == (bClassificationSucceed =
-			MatchSrcPort(pstClassifierRule,
-				ntohs((iphd->protocol == UDP) ?
-				xprt_hdr->uhdr.source : xprt_hdr->thdr.source))))
+		if (!MatchSrcPort(pstClassifierRule,
+				  ntohs((iphd->protocol == UDP) ?
+				  xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
 			xprt_hdr->thdr.dest);
-		if (false == (bClassificationSucceed =
-			MatchDestPort(pstClassifierRule,
-			ntohs((iphd->protocol == UDP) ?
-			xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))))
+		if (!MatchDestPort(pstClassifierRule,
+				   ntohs((iphd->protocol == UDP) ?
+				   xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
 			break;
+		bClassificationSucceed = TRUE;
 	} while (0);
 
 	if (TRUE == bClassificationSucceed)
diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c
index bf532b1bd345..573a283fb12c 100644
--- a/drivers/staging/ced1401/ced_ioc.c
+++ b/drivers/staging/ced1401/ced_ioc.c
@@ -38,8 +38,8 @@
 ****************************************************************************/
 static void FlushOutBuff(DEVICE_EXTENSION *pdx)
 {
-	dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__,
-		pdx->sCurrentState);
+	dev_dbg(&pdx->interface->dev, "%s: currentState=%d\n",
+		__func__, pdx->sCurrentState);
 	if (pdx->sCurrentState == U14ERR_TIME)	/* Do nothing if hardware in trouble */
 		return;
 	/* Kill off any pending I/O */
@@ -59,8 +59,8 @@ static void FlushOutBuff(DEVICE_EXTENSION *pdx)
 ****************************************************************************/
 static void FlushInBuff(DEVICE_EXTENSION *pdx)
 {
-	dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__,
-		pdx->sCurrentState);
+	dev_dbg(&pdx->interface->dev, "%s: currentState=%d\n",
+		__func__, pdx->sCurrentState);
 	if (pdx->sCurrentState == U14ERR_TIME)	/* Do nothing if hardware in trouble */
 		return;
 	/* Kill off any pending I/O */
@@ -118,8 +118,8 @@ int SendString(DEVICE_EXTENSION *pdx, const char __user *pData,
 
 	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 	if (n > 0) {		/*  do nothing if nowt to do! */
-		dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, n,
-			buffer);
+		dev_dbg(&pdx->interface->dev, "%s: n=%d>%s<\n",
+			__func__, n, buffer);
 		iReturn = PutChars(pdx, buffer, n);
 	}
 
@@ -139,7 +139,7 @@ int SendChar(DEVICE_EXTENSION *pdx, char c)
 	int iReturn;
 	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 	iReturn = PutChars(pdx, &c, 1);
-	dev_dbg(&pdx->interface->dev, "SendChar >%c< (0x%02x)", c, c);
+	dev_dbg(&pdx->interface->dev, "SendChar >%c< (0x%02x)\n", c, c);
 	Allowi(pdx);	/*  Make sure char reads are running */
 	mutex_unlock(&pdx->io_mutex);
 	return iReturn;
@@ -174,7 +174,7 @@ int SendChar(DEVICE_EXTENSION *pdx, char c)
 int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error)
 {
 	int nGot;
-	dev_dbg(&pdx->interface->dev, "Get1401State() entry");
+	dev_dbg(&pdx->interface->dev, "%s: entry\n", __func__);
 
 	*state = 0xFFFFFFFF;	/*  Start off with invalid state */
 	nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
@@ -182,15 +182,15 @@ int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error)
 			       pdx->statBuf, sizeof(pdx->statBuf), HZ);
 	if (nGot != sizeof(pdx->statBuf)) {
 		dev_err(&pdx->interface->dev,
-			"Get1401State() FAILED, return code %d", nGot);
+			"%s: FAILED, return code %d\n", __func__, nGot);
 		pdx->sCurrentState = U14ERR_TIME;	/*  Indicate that things are very wrong indeed */
 		*state = 0;	/*  Force status values to a known state */
 		*error = 0;
 	} else {
 		int nDevice;
 		dev_dbg(&pdx->interface->dev,
-			"Get1401State() Success, state: 0x%x, 0x%x",
-			pdx->statBuf[0], pdx->statBuf[1]);
+			"%s: Success, state: 0x%x, 0x%x\n",
+			__func__, pdx->statBuf[0], pdx->statBuf[1]);
 
 		*state = pdx->statBuf[0];	/*  Return the state values to the calling code */
 		*error = pdx->statBuf[1];
@@ -220,8 +220,8 @@ int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error)
 ****************************************************************************/
 int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
 {
-	dev_dbg(&pdx->interface->dev, "ReadWrite_Cancel entry %d",
-		pdx->bStagedUrbPending);
+	dev_dbg(&pdx->interface->dev, "%s: entry %d\n",
+		__func__, pdx->bStagedUrbPending);
 #ifdef NOT_WRITTEN_YET
 	int ntStatus = STATUS_SUCCESS;
 	bool bResult = false;
@@ -231,7 +231,7 @@ int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
 
 	if (pdx->bStagedUrbPending) {	/*  anything to be cancelled? May need more... */
 		dev_info(&pdx->interface - dev,
-			 "ReadWrite_Cancel about to cancel Urb");
+			 "ReadWrite_Cancel about to cancel Urb\n");
 		/* Clear the staging done flag */
 		/* KeClearEvent(&pdx->StagingDoneEvent); */
 		USB_ASSERT(pdx->pStagedIrp != NULL);
@@ -244,14 +244,14 @@ int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
 			LARGE_INTEGER timeout;
 			timeout.QuadPart = -10000000;	/*  Use a timeout of 1 second */
 			dev_info(&pdx->interface - dev,
-				 "ReadWrite_Cancel about to wait till done");
+				 "%s: about to wait till done\n", __func__);
 			ntStatus =
 			    KeWaitForSingleObject(&pdx->StagingDoneEvent,
 						  Executive, KernelMode, FALSE,
 						  &timeout);
 		} else {
 			dev_info(&pdx->interface - dev,
-				 "ReadWrite_Cancel, cancellation failed");
+				 "%s: cancellation failed\n", __func__);
 			ntStatus = U14ERR_FAIL;
 		}
 		USB_KdPrint(DBGLVL_DEFAULT,
@@ -260,7 +260,7 @@ int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
 	} else
 		spin_unlock_irq(&pdx->stagedLock);
 
-	dev_info(&pdx->interface - dev, "ReadWrite_Cancel  done");
+	dev_info(&pdx->interface - dev, "%s: done\n", __func__);
 	return ntStatus;
 #else
 	return U14ERR_NOERROR;
@@ -304,7 +304,7 @@ static int InSelfTest(DEVICE_EXTENSION *pdx, unsigned int *pState)
 bool Is1401(DEVICE_EXTENSION *pdx)
 {
 	int iReturn;
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	ced_draw_down(pdx);	/*  wait for, then kill outstanding Urbs */
 	FlushInBuff(pdx);	/*  Clear out input buffer & pipe */
@@ -368,7 +368,7 @@ bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset)
 		      (pdx->sCurrentState >= U14ERR_STD));	/*  No 1401 errors stored */
 
 	dev_dbg(&pdx->interface->dev,
-		"%s DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d",
+		"%s: DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d\n",
 		__func__, pdx->dwDMAFlag, pdx->sCurrentState, pdx->bForceReset,
 		bTestBuff, bShortTest);
 
@@ -376,13 +376,13 @@ bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset)
 	    (pdx->dwNumInput || pdx->dwNumOutput)) {	/*  ...characters were in the buffer? */
 		bShortTest = false;	/*  Then do the full test */
 		dev_dbg(&pdx->interface->dev,
-			"%s will reset as buffers not empty", __func__);
+			"%s: will reset as buffers not empty\n", __func__);
 	}
 
 	if (bShortTest || !bCanReset) {	/*  Still OK to try the short test? */
 				/*  Always test if no reset - we want state update */
 		unsigned int state, error;
-		dev_dbg(&pdx->interface->dev, "%s->Get1401State", __func__);
+		dev_dbg(&pdx->interface->dev, "%s: Get1401State\n", __func__);
 		if (Get1401State(pdx, &state, &error) == U14ERR_NOERROR) {	/*  Check on the 1401 state */
 			if ((state & 0xFF) == 0)	/*  If call worked, check the status value */
 				bRet = true;	/*  If that was zero, all is OK, no reset needed */
@@ -390,7 +390,7 @@ bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset)
 	}
 
 	if (!bRet && bCanReset)	{ /*  If all not OK, then */
-		dev_info(&pdx->interface->dev, "%s->Is1401 %d %d %d %d",
+		dev_info(&pdx->interface->dev, "%s: Is1401 %d %d %d %d\n",
 			 __func__, bShortTest, pdx->sCurrentState, bTestBuff,
 			 pdx->bForceReset);
 		bRet = Is1401(pdx);	/*   do full test */
@@ -407,7 +407,8 @@ bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset)
 int Reset1401(DEVICE_EXTENSION *pdx)
 {
 	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	dev_dbg(&pdx->interface->dev, "ABout to call QuickCheck");
+	dev_dbg(&pdx->interface->dev, "%s: About to call QuickCheck\n",
+		__func__);
 	QuickCheck(pdx, true, true);	/*  Check 1401, reset if not OK */
 	mutex_unlock(&pdx->io_mutex);
 	return U14ERR_NOERROR;
@@ -423,7 +424,7 @@ int GetChar(DEVICE_EXTENSION *pdx)
 	int iReturn = U14ERR_NOIN;	/*  assume we will get  nothing */
 	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 
-	dev_dbg(&pdx->interface->dev, "GetChar");
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	Allowi(pdx);	/*  Make sure char reads are running */
 	SendChars(pdx);	/*  and send any buffered chars */
@@ -497,8 +498,8 @@ int GetString(DEVICE_EXTENSION *pdx, char __user *pUser, int n)
 		pdx->dwNumInput -= nGot;
 		spin_unlock_irq(&pdx->charInLock);
 
-		dev_dbg(&pdx->interface->dev,
-			"GetString read %d characters >%s<", nGot, buffer);
+		dev_dbg(&pdx->interface->dev, "%s: read %d characters >%s<\n",
+			__func__, nGot, buffer);
 		if (copy_to_user(pUser, buffer, nCopyToUser))
 			iReturn = -EFAULT;
 		else
@@ -555,7 +556,7 @@ int LineCount(DEVICE_EXTENSION *pdx)
 	}
 
 	spin_unlock_irq(&pdx->charInLock);
-	dev_dbg(&pdx->interface->dev, "LineCount returned %d", iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: returned %d\n", __func__, iReturn);
 	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 	return iReturn;
 }
@@ -571,7 +572,7 @@ int GetOutBufSpace(DEVICE_EXTENSION *pdx)
 	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 	SendChars(pdx);		/*  send any buffered chars */
 	iReturn = (int)(OUTBUF_SZ - pdx->dwNumOutput);	/*  no lock needed for single read */
-	dev_dbg(&pdx->interface->dev, "OutBufSpace %d", iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
 	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
 	return iReturn;
 }
@@ -589,7 +590,7 @@ int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
 
 	if ((nArea < 0) || (nArea >= MAX_TRANSAREAS)) {
 		iReturn = U14ERR_BADAREA;
-		dev_err(&pdx->interface->dev, "%s Attempt to clear area %d",
+		dev_err(&pdx->interface->dev, "%s: Attempt to clear area %d\n",
 			__func__, nArea);
 	} else {
 		TRANSAREA *pTA = &pdx->rTransDef[nArea];	/*  to save typing */
@@ -602,14 +603,14 @@ int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
 			int nPages = 0;	/*  and number of pages */
 			int np;
 
-			dev_dbg(&pdx->interface->dev, "%s area %d", __func__,
-				nArea);
+			dev_dbg(&pdx->interface->dev, "%s: area %d\n",
+				__func__, nArea);
 			spin_lock_irq(&pdx->stagedLock);
 			if ((pdx->StagedId == nArea)
 			    && (pdx->dwDMAFlag > MODE_CHAR)) {
 				iReturn = U14ERR_UNLOCKFAIL;	/*  cannot delete as in use */
 				dev_err(&pdx->interface->dev,
-					"%s call on area %d while active",
+					"%s: call on area %d while active\n",
 					__func__, nArea);
 			} else {
 				pPages = pTA->pPages;	/*  save page address list */
@@ -633,7 +634,7 @@ int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
 				/*  Now we must undo the pinning down of the pages. We will assume the worst and mark */
 				/*  all the pages as dirty. Don't be tempted to move this up above as you must not be */
 				/*  holding a spin lock to do this stuff as it is not atomic. */
-				dev_dbg(&pdx->interface->dev, "%s nPages=%d",
+				dev_dbg(&pdx->interface->dev, "%s: nPages=%d\n",
 					__func__, nPages);
 
 				for (np = 0; np < nPages; ++np) {
@@ -645,7 +646,7 @@ int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
 
 				kfree(pPages);
 				dev_dbg(&pdx->interface->dev,
-					"%s kfree(pPages) done", __func__);
+					"%s: kfree(pPages) done\n", __func__);
 			}
 		}
 	}
@@ -687,12 +688,12 @@ static int SetArea(DEVICE_EXTENSION *pdx, int nArea, char __user *puBuf,
 		iReturn = U14ERR_NOMEMORY;
 		goto error;
 	}
-	dev_dbg(&pdx->interface->dev, "%s %p, length=%06x, circular %d",
+	dev_dbg(&pdx->interface->dev, "%s: %p, length=%06x, circular %d\n",
 		__func__, puBuf, dwLength, bCircular);
 
 	/*  To pin down user pages we must first acquire the mapping semaphore. */
 	nPages = get_user_pages_fast(ulStart, len, 1, pPages);
-	dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages);
+	dev_dbg(&pdx->interface->dev, "%s: nPages = %d\n", __func__, nPages);
 
 	if (nPages > 0) {		/*  if we succeeded */
 		/*  If you are tempted to use page_address (form LDD3), forget it. You MUST use */
@@ -744,8 +745,8 @@ int SetTransfer(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__,
-		td.wAreaNum, td.dwLength);
+	dev_dbg(&pdx->interface->dev, "%s: area:%d, size:%08x\n",
+		__func__, td.wAreaNum, td.dwLength);
 	/*  The strange cast is done so that we don't get warnings in 32-bit linux about the size of the */
 	/*  pointer. The pointer is always passed as a 64-bit object so that we don't have problems using */
 	/*  a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system. */
@@ -922,7 +923,7 @@ int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pTX)
 ****************************************************************************/
 int KillIO1401(DEVICE_EXTENSION *pdx)
 {
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 	mutex_lock(&pdx->io_mutex);
 	FlushOutBuff(pdx);
 	FlushInBuff(pdx);
@@ -938,7 +939,7 @@ int KillIO1401(DEVICE_EXTENSION *pdx)
 int BlkTransState(DEVICE_EXTENSION *pdx)
 {
 	int iReturn = pdx->dwDMAFlag != MODE_CHAR;
-	dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
 	return iReturn;
 }
 
@@ -956,7 +957,7 @@ int StateOf1401(DEVICE_EXTENSION *pdx)
 	iReturn = pdx->sCurrentState;
 
 	mutex_unlock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
 
 	return iReturn;
 }
@@ -971,7 +972,7 @@ int StartSelfTest(DEVICE_EXTENSION *pdx)
 {
 	int nGot;
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	ced_draw_down(pdx);	/*  wait for, then kill outstanding Urbs */
 	FlushInBuff(pdx);	/*  Clear out input buffer & pipe */
@@ -987,7 +988,7 @@ int StartSelfTest(DEVICE_EXTENSION *pdx)
 
 	mutex_unlock(&pdx->io_mutex);
 	if (nGot < 0)
-		dev_err(&pdx->interface->dev, "%s err=%d", __func__, nGot);
+		dev_err(&pdx->interface->dev, "%s: err=%d\n", __func__, nGot);
 	return nGot < 0 ? U14ERR_FAIL : U14ERR_NOERROR;
 }
 
@@ -1005,7 +1006,7 @@ int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
 
 	mutex_lock(&pdx->io_mutex);
 
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 	iReturn = Get1401State(pdx, &state, &error);
 	if (iReturn == U14ERR_NOERROR)	/*  Only accept zero if it happens twice */
 		iReturn = Get1401State(pdx, &state, &error);
@@ -1013,8 +1014,8 @@ int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
 	if (iReturn != U14ERR_NOERROR) {	/*  Self-test can cause comms errors */
 				/*  so we assume still testing */
 		dev_err(&pdx->interface->dev,
-			"%s Get1401State=%d, assuming still testing", __func__,
-			iReturn);
+			"%s: Get1401State=%d, assuming still testing\n",
+			__func__, iReturn);
 		state = 0x80;	/*  Force still-testing, no error */
 		error = 0;
 		iReturn = U14ERR_NOERROR;
@@ -1022,7 +1023,7 @@ int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
 
 	if ((state == -1) && (error == -1)) {	/*  If Get1401State had problems */
 		dev_err(&pdx->interface->dev,
-			"%s Get1401State failed, assuming still testing",
+			"%s: Get1401State failed, assuming still testing\n",
 			__func__);
 		state = 0x80;	/*  Force still-testing, no error */
 		error = 0;
@@ -1033,21 +1034,21 @@ int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
 			gst.code = (state & 0x00FF0000) >> 16;	/*  read the error code */
 			gst.x = error & 0x0000FFFF;	/*  Error data X */
 			gst.y = (error & 0xFFFF0000) >> 16;	/*  and data Y */
-			dev_dbg(&pdx->interface->dev, "Self-test error code %d",
-				gst.code);
+			dev_dbg(&pdx->interface->dev,
+				"Self-test error code %d\n", gst.code);
 		} else {		/*  No error, check for timeout */
 			unsigned long ulNow = jiffies;	/*  get current time */
 			if (time_after(ulNow, pdx->ulSelfTestTime)) {
 				gst.code = -2;	/*  Flag the timeout */
 				dev_dbg(&pdx->interface->dev,
-					"Self-test timed-out");
+					"Self-test timed-out\n");
 			} else
 				dev_dbg(&pdx->interface->dev,
-					"Self-test on-going");
+					"Self-test on-going\n");
 		}
 	} else {
 		gst.code = -1;	/*  Flag the test is done */
-		dev_dbg(&pdx->interface->dev, "Self-test done");
+		dev_dbg(&pdx->interface->dev, "Self-test done\n");
 	}
 
 	if (gst.code < 0) {	/*  If we have a problem or finished */
@@ -1074,7 +1075,7 @@ int TypeOf1401(DEVICE_EXTENSION *pdx)
 {
 	int iReturn = TYPEUNKNOWN;
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	switch (pdx->s1401Type) {
 	case TYPE1401:
@@ -1092,7 +1093,7 @@ int TypeOf1401(DEVICE_EXTENSION *pdx)
 		else		/*   for up-coming 1401 designs */
 			iReturn = TYPEUNKNOWN;	/*  Don't know or not there */
 	}
-	dev_dbg(&pdx->interface->dev, "%s %d", __func__, iReturn);
+	dev_dbg(&pdx->interface->dev, "%s %d\n", __func__, iReturn);
 	mutex_unlock(&pdx->io_mutex);
 
 	return iReturn;
@@ -1107,7 +1108,7 @@ int TransferFlags(DEVICE_EXTENSION *pdx)
 {
 	int iReturn = U14TF_MULTIA | U14TF_DIAG |	/*  we always have multiple DMA area */
 	    U14TF_NOTIFY | U14TF_CIRCTH;	/*  diagnostics, notify and circular */
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 	mutex_lock(&pdx->io_mutex);
 	if (pdx->bIsUSB2)	/*  Set flag for USB2 if appropriate */
 		iReturn |= U14TF_USB2;
@@ -1125,15 +1126,15 @@ static int DbgCmd1401(DEVICE_EXTENSION *pdx, unsigned char cmd,
 		      unsigned int data)
 {
 	int iReturn;
-	dev_dbg(&pdx->interface->dev, "%s entry", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: entry\n", __func__);
 	iReturn = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0), cmd,
 				  (H_TO_D | VENDOR | DEVREQ),
 				  (unsigned short)data,
 				  (unsigned short)(data >> 16), NULL, 0, HZ);
 						/* allow 1 second timeout */
 	if (iReturn < 0)
-		dev_err(&pdx->interface->dev, "%s fail code=%d", __func__,
-			iReturn);
+		dev_err(&pdx->interface->dev, "%s: fail code=%d\n",
+			__func__, iReturn);
 
 	return iReturn;
 }
@@ -1152,7 +1153,7 @@ int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
 
 	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
 	if (iReturn == U14ERR_NOERROR)
@@ -1181,7 +1182,7 @@ int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
 
 	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
 	if (iReturn == U14ERR_NOERROR)
@@ -1210,7 +1211,7 @@ int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
 
 	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
 	if (iReturn == U14ERR_NOERROR)
@@ -1242,7 +1243,7 @@ int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
 	if (iReturn == U14ERR_NOERROR)
@@ -1270,7 +1271,7 @@ int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 	memset(&db, 0, sizeof(db));	/*  fill returned block with 0s */
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	/*  Read back the last peeked value from the 1401. */
 	iReturn = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
@@ -1282,8 +1283,8 @@ int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
 		else
 			iReturn = U14ERR_NOERROR;
 	} else
-		dev_err(&pdx->interface->dev, "%s failed, code %d", __func__,
-			iReturn);
+		dev_err(&pdx->interface->dev, "%s: failed, code %d\n",
+			__func__, iReturn);
 
 	mutex_unlock(&pdx->io_mutex);
 
@@ -1302,7 +1303,7 @@ int DbgStopLoop(DEVICE_EXTENSION *pdx)
 	unsigned int uState, uErr;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 	iReturn = Get1401State(pdx, &uState, &uErr);
 	mutex_unlock(&pdx->io_mutex);
 
@@ -1327,8 +1328,8 @@ int SetCircular(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD)
 		return -EFAULT;
 
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__,
-		td.wAreaNum, td.dwLength);
+	dev_dbg(&pdx->interface->dev, "%s: area:%d, size:%08x\n",
+		__func__, td.wAreaNum, td.dwLength);
 	bToHost = td.eSize != 0;	/*  this is used as the tohost flag */
 
 	/*  The strange cast is done so that we don't get warnings in 32-bit linux about the size of the */
@@ -1353,7 +1354,7 @@ int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 	unsigned int nArea;
 	TCIRCBLOCK cb;
 
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	if (copy_from_user(&cb, pCB, sizeof(cb)))
 		return -EFAULT;
@@ -1374,7 +1375,7 @@ int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 				cb.dwOffset = pArea->aBlocks[0].dwOffset;
 				cb.dwSize = pArea->aBlocks[0].dwSize;
 				dev_dbg(&pdx->interface->dev,
-					"%s return block 0: %d bytes at %d",
+					"%s: return block 0: %d bytes at %d\n",
 					__func__, cb.dwSize, cb.dwOffset);
 			}
 		} else
@@ -1402,7 +1403,7 @@ int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 	unsigned int nArea, uStart, uSize;
 	TCIRCBLOCK cb;
 
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	if (copy_from_user(&cb, pCB, sizeof(cb)))
 		return -EFAULT;
@@ -1437,7 +1438,7 @@ int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 				}
 
 				dev_dbg(&pdx->interface->dev,
-					"%s free %d bytes at %d, return %d bytes at %d, wait=%d",
+					"%s: free %d bytes at %d, return %d bytes at %d, wait=%d\n",
 					__func__, uSize, uStart,
 					pArea->aBlocks[0].dwSize,
 					pArea->aBlocks[0].dwOffset,
@@ -1453,13 +1454,13 @@ int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 				bWaiting = pdx->bXFerWaiting;
 				if (bWaiting && pdx->bStagedUrbPending) {
 					dev_err(&pdx->interface->dev,
-						"%s ERROR: waiting xfer and staged Urb pending!",
+						"%s: ERROR: waiting xfer and staged Urb pending!\n",
 						__func__);
 					bWaiting = false;
 				}
 			} else {
 				dev_err(&pdx->interface->dev,
-					"%s ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d",
+					"%s: ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d\n",
 					__func__, uSize, uStart,
 					pArea->aBlocks[0].dwSize,
 					pArea->aBlocks[0].dwOffset);
@@ -1475,7 +1476,7 @@ int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
 						 pdx->rDMAInfo.dwSize);
 				if (RWMStat != U14ERR_NOERROR)
 					dev_err(&pdx->interface->dev,
-						"%s rw setup failed %d",
+						"%s: rw setup failed %d\n",
 						__func__, RWMStat);
 			}
 		} else
diff --git a/drivers/staging/ced1401/usb1401.c b/drivers/staging/ced1401/usb1401.c
index efc310ca789e..c281fdabb4ed 100644
--- a/drivers/staging/ced1401/usb1401.c
+++ b/drivers/staging/ced1401/usb1401.c
@@ -166,7 +166,7 @@ static int ced_open(struct inode *inode, struct file *file)
 		goto exit;
 	}
 
-	dev_dbg(&interface->dev, "%s got pdx", __func__);
+	dev_dbg(&interface->dev, "%s: got pdx\n", __func__);
 
 	/* increment our usage count for the device */
 	kref_get(&pdx->kref);
@@ -184,7 +184,7 @@ static int ced_open(struct inode *inode, struct file *file)
 			goto exit;
 		}
 	} else {		/* uncomment this block if you want exclusive open */
-		dev_err(&interface->dev, "%s fail: already open", __func__);
+		dev_err(&interface->dev, "%s: fail: already open\n", __func__);
 		retval = -EBUSY;
 		pdx->open_count--;
 		mutex_unlock(&pdx->io_mutex);
@@ -207,7 +207,7 @@ static int ced_release(struct inode *inode, struct file *file)
 	if (pdx == NULL)
 		return -ENODEV;
 
-	dev_dbg(&pdx->interface->dev, "%s called", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
 	mutex_lock(&pdx->io_mutex);
 	if (!--pdx->open_count && pdx->interface)	/*  Allow autosuspend */
 		usb_autopm_put_interface(pdx->interface);
@@ -224,12 +224,12 @@ static int ced_flush(struct file *file, fl_owner_t id)
 	if (pdx == NULL)
 		return -ENODEV;
 
-	dev_dbg(&pdx->interface->dev, "%s char in pend=%d", __func__,
-		pdx->bReadCharsPending);
+	dev_dbg(&pdx->interface->dev, "%s: char in pend=%d\n",
+		__func__, pdx->bReadCharsPending);
 
 	/* wait for io to stop */
 	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s got io_mutex", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: got io_mutex\n", __func__);
 	ced_draw_down(pdx);
 
 	/* read out errors, leave subsequent opens a clean slate */
@@ -239,7 +239,7 @@ static int ced_flush(struct file *file, fl_owner_t id)
 	spin_unlock_irq(&pdx->err_lock);
 
 	mutex_unlock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s exit reached", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: exit reached\n", __func__);
 
 	return res;
 }
@@ -270,7 +270,7 @@ static void ced_writechar_callback(struct urb *pUrb)
 		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
 		     || pUrb->status == -ESHUTDOWN)) {
 			dev_err(&pdx->interface->dev,
-				"%s - nonzero write bulk status received: %d",
+				"%s: nonzero write bulk status received: %d\n",
 				__func__, pUrb->status);
 		}
 
@@ -287,10 +287,10 @@ static void ced_writechar_callback(struct urb *pUrb)
 		pdx->bSendCharsPending = false;	/*  Allow other threads again */
 		spin_unlock(&pdx->charOutLock);	/*  already at irq level */
 		dev_dbg(&pdx->interface->dev,
-			"%s - char out done, 0 chars sent", __func__);
+			"%s: char out done, 0 chars sent\n", __func__);
 	} else {
 		dev_dbg(&pdx->interface->dev,
-			"%s - char out done, %d chars sent", __func__, nGot);
+			"%s: char out done, %d chars sent\n", __func__, nGot);
 		spin_lock(&pdx->charOutLock);	/*  already at irq level */
 		pdx->dwNumOutput -= nGot;	/*  Now adjust the char send buffer */
 		pdx->dwOutBuffGet += nGot;	/*  to match what we did */
@@ -315,15 +315,15 @@ static void ced_writechar_callback(struct urb *pUrb)
 			    URB_NO_TRANSFER_DMA_MAP;
 			usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted);	/*  in case we need to kill it */
 			iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC);
-			dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__,
-				dwCount, pDat);
+			dev_dbg(&pdx->interface->dev, "%s: n=%d>%s<\n",
+				__func__, dwCount, pDat);
 			spin_lock(&pdx->charOutLock);	/*  grab lock for errors */
 			if (iReturn) {
 				pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
 				pdx->bSendCharsPending = false;	/*  Allow other threads again */
 				usb_unanchor_urb(pdx->pUrbCharOut);
 				dev_err(&pdx->interface->dev,
-					"%s usb_submit_urb() returned %d",
+					"%s: usb_submit_urb() returned %d\n",
 					__func__, iReturn);
 			}
 		} else
@@ -350,8 +350,8 @@ int SendChars(DEVICE_EXTENSION *pdx)
 		pdx->bSendCharsPending = true;	/*  Set flag to lock out other threads */
 
 		dev_dbg(&pdx->interface->dev,
-			"Send %d chars to 1401, EP0 flag %d\n", dwCount,
-			pdx->nPipes == 3);
+			"Send %d chars to 1401, EP0 flag %d\n",
+			dwCount, pdx->nPipes == 3);
 		/*  If we have only 3 end points we must send the characters to the 1401 using EP0. */
 		if (pdx->nPipes == 3) {
 			/*  For EP0 character transmissions to the 1401, we have to hang about until they */
@@ -375,11 +375,11 @@ int SendChars(DEVICE_EXTENSION *pdx)
 				if (nSent <= 0) {
 					iReturn = nSent ? nSent : -ETIMEDOUT;	/*  if 0 chars says we timed out */
 					dev_err(&pdx->interface->dev,
-						"Send %d chars by EP0 failed: %d",
+						"Send %d chars by EP0 failed: %d\n",
 						n, iReturn);
 				} else {
 					dev_dbg(&pdx->interface->dev,
-						"Sent %d chars by EP0", n);
+						"Sent %d chars by EP0\n", n);
 					count -= nSent;
 					index += nSent;
 				}
@@ -416,9 +416,9 @@ int SendChars(DEVICE_EXTENSION *pdx)
 		}
 	} else if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0))
 		dev_dbg(&pdx->interface->dev,
-			"SendChars bSendCharsPending:true");
+			"%s: bSendCharsPending:true\n", __func__);
 
-	dev_dbg(&pdx->interface->dev, "SendChars exit code: %d", iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: exit code: %d\n", __func__, iReturn);
 	spin_unlock_irq(&pdx->charOutLock);	/*  Now let go of the spinlock */
 	return iReturn;
 }
@@ -446,7 +446,7 @@ static void CopyUserSpace(DEVICE_EXTENSION *pdx, int n)
 		    pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset;
 		char *pCoherBuf = pdx->pCoherStagedIO;	/*  coherent buffer */
 		if (!pArea->bUsed) {
-			dev_err(&pdx->interface->dev, "%s area %d unused",
+			dev_err(&pdx->interface->dev, "%s: area %d unused\n",
 				__func__, nArea);
 			return;
 		}
@@ -474,21 +474,21 @@ static void CopyUserSpace(DEVICE_EXTENSION *pdx, int n)
 					n -= uiXfer;
 				} else {
 					dev_err(&pdx->interface->dev,
-						"%s did not map page %d",
+						"%s: did not map page %d\n",
 						__func__, nPage);
 					return;
 				}
 
 			} else {
 				dev_err(&pdx->interface->dev,
-					"%s exceeded pages %d", __func__,
-					nPage);
+					"%s: exceeded pages %d\n",
+					__func__, nPage);
 				return;
 			}
 		}
 	} else
-		dev_err(&pdx->interface->dev, "%s bad area %d", __func__,
-			nArea);
+		dev_err(&pdx->interface->dev, "%s: bad area %d\n",
+			__func__, nArea);
 }
 
 /*  Forward declarations for stuff used circularly */
@@ -513,11 +513,11 @@ static void staged_callback(struct urb *pUrb)
 		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
 		     || pUrb->status == -ESHUTDOWN)) {
 			dev_err(&pdx->interface->dev,
-				"%s - nonzero write bulk status received: %d",
+				"%s: nonzero write bulk status received: %d\n",
 				__func__, pUrb->status);
 		} else
 			dev_info(&pdx->interface->dev,
-				 "%s - staged xfer cancelled", __func__);
+				 "%s: staged xfer cancelled\n", __func__);
 
 		spin_lock(&pdx->err_lock);
 		pdx->errors = pUrb->status;
@@ -525,26 +525,26 @@ static void staged_callback(struct urb *pUrb)
 		nGot = 0;	/*   and tidy up again if so */
 		bCancel = true;
 	} else {
-		dev_dbg(&pdx->interface->dev, "%s %d chars xferred", __func__,
-			nGot);
+		dev_dbg(&pdx->interface->dev, "%s: %d chars xferred\n",
+			__func__, nGot);
 		if (pdx->StagedRead)	/*  if reading, save to user space */
 			CopyUserSpace(pdx, nGot);	/*  copy from buffer to user */
 		if (nGot == 0)
-			dev_dbg(&pdx->interface->dev, "%s ZLP", __func__);
+			dev_dbg(&pdx->interface->dev, "%s: ZLP\n", __func__);
 	}
 
 	/*  Update the transfer length based on the TransferBufferLength value in the URB */
 	pdx->StagedDone += nGot;
 
-	dev_dbg(&pdx->interface->dev, "%s, done %d bytes of %d", __func__,
-		pdx->StagedDone, pdx->StagedLength);
+	dev_dbg(&pdx->interface->dev, "%s: done %d bytes of %d\n",
+		__func__, pdx->StagedDone, pdx->StagedLength);
 
 	if ((pdx->StagedDone == pdx->StagedLength) ||	/*  If no more to do */
 	    (bCancel)) {		/*  or this IRP was cancelled */
 		TRANSAREA *pArea = &pdx->rTransDef[pdx->StagedId];	/*  Transfer area info */
 		dev_dbg(&pdx->interface->dev,
-			"%s transfer done, bytes %d, cancel %d", __func__,
-			pdx->StagedDone, bCancel);
+			"%s: transfer done, bytes %d, cancel %d\n",
+			__func__, pdx->StagedDone, bCancel);
 
 		/*  Here is where we sort out what to do with this transfer if using a circular buffer. We have */
 		/*   a completed transfer that can be assumed to fit into the transfer area. We should be able to */
@@ -559,7 +559,7 @@ static void staged_callback(struct urb *pUrb)
 					pArea->aBlocks[1].dwSize +=
 					    pdx->StagedLength;
 					dev_dbg(&pdx->interface->dev,
-						"RWM_Complete, circ block 1 now %d bytes at %d",
+						"RWM_Complete, circ block 1 now %d bytes at %d\n",
 						pArea->aBlocks[1].dwSize,
 						pArea->aBlocks[1].dwOffset);
 				} else {
@@ -569,7 +569,7 @@ static void staged_callback(struct urb *pUrb)
 					pArea->aBlocks[1].dwSize =
 					    pdx->StagedLength;
 					dev_err(&pdx->interface->dev,
-						"%s ERROR, circ block 1 re-started %d bytes at %d",
+						"%s: ERROR, circ block 1 re-started %d bytes at %d\n",
 						__func__,
 						pArea->aBlocks[1].dwSize,
 						pArea->aBlocks[1].dwOffset);
@@ -582,7 +582,7 @@ static void staged_callback(struct urb *pUrb)
 					     pArea->aBlocks[0].dwSize)) {
 						pArea->aBlocks[0].dwSize += pdx->StagedLength;	/*  Just add this transfer in */
 						dev_dbg(&pdx->interface->dev,
-							"RWM_Complete, circ block 0 now %d bytes at %d",
+							"RWM_Complete, circ block 0 now %d bytes at %d\n",
 							pArea->aBlocks[0].
 							dwSize,
 							pArea->aBlocks[0].
@@ -593,7 +593,7 @@ static void staged_callback(struct urb *pUrb)
 						pArea->aBlocks[1].dwSize =
 						    pdx->StagedLength;
 						dev_dbg(&pdx->interface->dev,
-							"RWM_Complete, circ block 1 started %d bytes at %d",
+							"RWM_Complete, circ block 1 started %d bytes at %d\n",
 							pArea->aBlocks[1].
 							dwSize,
 							pArea->aBlocks[1].
@@ -605,7 +605,7 @@ static void staged_callback(struct urb *pUrb)
 					pArea->aBlocks[0].dwSize =
 					    pdx->StagedLength;
 					dev_dbg(&pdx->interface->dev,
-						"RWM_Complete, circ block 0 started %d bytes at %d",
+						"RWM_Complete, circ block 0 started %d bytes at %d\n",
 						pArea->aBlocks[0].dwSize,
 						pArea->aBlocks[0].dwOffset);
 				}
@@ -614,7 +614,7 @@ static void staged_callback(struct urb *pUrb)
 
 		if (!bCancel) { /*  Don't generate an event if cancelled */
 			dev_dbg(&pdx->interface->dev,
-				"RWM_Complete,  bCircular %d, bToHost %d, eStart %d, eSize %d",
+				"RWM_Complete,  bCircular %d, bToHost %d, eStart %d, eSize %d\n",
 				pArea->bCircular, pArea->bEventToHost,
 				pArea->dwEventSt, pArea->dwEventSz);
 			if ((pArea->dwEventSz) &&	/*  Set a user-mode event... */
@@ -641,7 +641,7 @@ static void staged_callback(struct urb *pUrb)
 
 				if (iWakeUp) {
 					dev_dbg(&pdx->interface->dev,
-						"About to set event to notify app");
+						"About to set event to notify app\n");
 					wake_up_interruptible(&pArea->wqEvent);	/*  wake up waiting processes */
 					++pArea->iWakeUp;	/*  increment wakeup count */
 				}
@@ -655,7 +655,7 @@ static void staged_callback(struct urb *pUrb)
 			if (pdx->bXFerWaiting) {	/*  Got a block xfer waiting? */
 				int iReturn;
 				dev_info(&pdx->interface->dev,
-					 "*** RWM_Complete *** pending transfer will now be set up!!!");
+					 "*** RWM_Complete *** pending transfer will now be set up!!!\n");
 				iReturn =
 				    ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
 						 pdx->rDMAInfo.wIdent,
@@ -664,7 +664,7 @@ static void staged_callback(struct urb *pUrb)
 
 				if (iReturn)
 					dev_err(&pdx->interface->dev,
-						"RWM_Complete rw setup failed %d",
+						"RWM_Complete rw setup failed %d\n",
 						iReturn);
 			}
 		}
@@ -685,7 +685,7 @@ static void staged_callback(struct urb *pUrb)
 	/*  not be upset by char input during DMA... sigh. Needs sorting out. */
 	if (bRestartCharInput)	/*  may be out of date, but... */
 		Allowi(pdx);	/*  ...Allowi tests a lock too. */
-	dev_dbg(&pdx->interface->dev, "%s done", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: done\n", __func__);
 }
 
 /****************************************************************************
@@ -707,7 +707,7 @@ static int StageChunk(DEVICE_EXTENSION *pdx)
 		return U14ERR_FAIL;
 
 	if (!CanAcceptIoRequests(pdx)) {	/*  got sudden remove? */
-		dev_info(&pdx->interface->dev, "%s sudden remove, giving up",
+		dev_info(&pdx->interface->dev, "%s: sudden remove, giving up\n",
 			 __func__);
 		return U14ERR_FAIL;	/*  could do with a better error */
 	}
@@ -731,11 +731,11 @@ static int StageChunk(DEVICE_EXTENSION *pdx)
 	if (iReturn) {
 		usb_unanchor_urb(pdx->pStagedUrb);	/*  kill it */
 		pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
-		dev_err(&pdx->interface->dev, "%s submit urb failed, code %d",
+		dev_err(&pdx->interface->dev, "%s: submit urb failed, code %d\n",
 			__func__, iReturn);
 	} else
 		pdx->bStagedUrbPending = true;	/*  Set the flag for staged URB pending */
-	dev_dbg(&pdx->interface->dev, "%s done so far:%d, this size:%d",
+	dev_dbg(&pdx->interface->dev, "%s: done so far:%d, this size:%d\n",
 		__func__, pdx->StagedDone, ChunkSize);
 
 	return iReturn;
@@ -764,28 +764,28 @@ int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
 	TRANSAREA *pArea = &pdx->rTransDef[wIdent];	/*  Transfer area info */
 
 	if (!CanAcceptIoRequests(pdx)) {	/*  Are we in a state to accept new requests? */
-		dev_err(&pdx->interface->dev, "%s can't accept requests",
+		dev_err(&pdx->interface->dev, "%s: can't accept requests\n",
 			__func__);
 		return U14ERR_FAIL;
 	}
 
 	dev_dbg(&pdx->interface->dev,
-		"%s xfer %d bytes to %s, offset %d, area %d", __func__, dwLen,
-		Read ? "host" : "1401", dwOffs, wIdent);
+		"%s: xfer %d bytes to %s, offset %d, area %d\n",
+		__func__, dwLen, Read ? "host" : "1401", dwOffs, wIdent);
 
 	/*  Amazingly, we can get an escape sequence back before the current staged Urb is done, so we */
 	/*   have to check for this situation and, if so, wait until all is OK. */
 	if (pdx->bStagedUrbPending) {
 		pdx->bXFerWaiting = true;	/*  Flag we are waiting */
 		dev_info(&pdx->interface->dev,
-			 "%s xfer is waiting, as previous staged pending",
+			 "%s: xfer is waiting, as previous staged pending\n",
 			 __func__);
 		return U14ERR_NOERROR;
 	}
 
 	if (dwLen == 0) {		/*  allow 0-len read or write; just return success */
 		dev_dbg(&pdx->interface->dev,
-			"%s OK; zero-len read/write request", __func__);
+			"%s: OK; zero-len read/write request\n", __func__);
 		return U14ERR_NOERROR;
 	}
 
@@ -795,7 +795,7 @@ int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
 		bool bWait = false;	/*  Flag for transfer having to wait */
 
 		dev_dbg(&pdx->interface->dev,
-			"Circular buffers are %d at %d and %d at %d",
+			"Circular buffers are %d at %d and %d at %d\n",
 			pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset,
 			pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
 		if (pArea->aBlocks[1].dwSize > 0) {	/*  Using the second block already? */
@@ -819,14 +819,14 @@ int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
 		if (bWait) {	/*  This transfer will have to wait? */
 			pdx->bXFerWaiting = true;	/*  Flag we are waiting */
 			dev_dbg(&pdx->interface->dev,
-				"%s xfer waiting for circular buffer space",
+				"%s: xfer waiting for circular buffer space\n",
 				__func__);
 			return U14ERR_NOERROR;
 		}
 
 		dev_dbg(&pdx->interface->dev,
-			"%s circular xfer, %d bytes starting at %d", __func__,
-			dwLen, dwOffs);
+			"%s: circular xfer, %d bytes starting at %d\n",
+			__func__, dwLen, dwOffs);
 	}
 	/*  Save the parameters for the read\write transfer */
 	pdx->StagedRead = Read;	/*  Save the parameters for this read */
@@ -948,7 +948,7 @@ static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
 	unsigned char ucData;
 	unsigned int dDone = 0;	/*  We haven't parsed anything so far */
 
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	if (ReadChar(&ucData, pBuf, &dDone, dwCount)) {
 		unsigned char ucTransCode = (ucData & 0x0F);	/*  get code for transfer type */
@@ -960,8 +960,8 @@ static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
 		pDmaDesc->dwSize = 0;	/*  initialise other bits */
 		pDmaDesc->dwOffset = 0;
 
-		dev_dbg(&pdx->interface->dev, "%s type: %d ident: %d", __func__,
-			pDmaDesc->wTransType, pDmaDesc->wIdent);
+		dev_dbg(&pdx->interface->dev, "%s: type: %d ident: %d\n",
+			__func__, pDmaDesc->wTransType, pDmaDesc->wIdent);
 
 		pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST);	/*  set transfer direction */
 
@@ -976,7 +976,7 @@ static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
 						&dDone, dwCount);
 				if (bResult) {
 					dev_dbg(&pdx->interface->dev,
-						"%s xfer offset & size %d %d",
+						"%s: xfer offset & size %d %d\n",
 						__func__, pDmaDesc->dwOffset,
 						pDmaDesc->dwSize);
 
@@ -989,7 +989,7 @@ static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
 					      dwLength))) {
 						bResult = false;	/*  bad parameter(s) */
 						dev_dbg(&pdx->interface->dev,
-							"%s bad param - id %d, bUsed %d, offset %d, size %d, area length %d",
+							"%s: bad param - id %d, bUsed %d, offset %d, size %d, area length %d\n",
 							__func__, wIdent,
 							pdx->rTransDef[wIdent].
 							bUsed,
@@ -1008,7 +1008,7 @@ static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
 		bResult = false;
 
 	if (!bResult)		/*  now check parameters for validity */
-		dev_err(&pdx->interface->dev, "%s error reading Esc sequence",
+		dev_err(&pdx->interface->dev, "%s: error reading Esc sequence\n",
 			__func__);
 
 	return bResult;
@@ -1045,15 +1045,15 @@ static int Handle1401Esc(DEVICE_EXTENSION *pdx, char *pCh,
 			unsigned short wTransType = pdx->rDMAInfo.wTransType;	/*  check transfer type */
 
 			dev_dbg(&pdx->interface->dev,
-				"%s xfer to %s, offset %d, length %d", __func__,
+				"%s: xfer to %s, offset %d, length %d\n",
+				__func__,
 				pdx->rDMAInfo.bOutWard ? "1401" : "host",
 				pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
 
 			if (pdx->bXFerWaiting) { /*  Check here for badly out of kilter... */
 				/*  This can never happen, really */
 				dev_err(&pdx->interface->dev,
-					"ERROR: DMA setup while transfer still waiting");
-				spin_unlock(&pdx->stagedLock);
+					"ERROR: DMA setup while transfer still waiting\n");
 			} else {
 				if ((wTransType == TM_EXTTOHOST)
 				    || (wTransType == TM_EXTTO1401)) {
@@ -1066,21 +1066,21 @@ static int Handle1401Esc(DEVICE_EXTENSION *pdx, char *pCh,
 							 pdx->rDMAInfo.dwSize);
 					if (iReturn != U14ERR_NOERROR)
 						dev_err(&pdx->interface->dev,
-							"%s ReadWriteMem() failed %d",
+							"%s: ReadWriteMem() failed %d\n",
 							__func__, iReturn);
 				} else	/*  This covers non-linear transfer setup */
 					dev_err(&pdx->interface->dev,
-						"%s Unknown block xfer type %d",
+						"%s: Unknown block xfer type %d\n",
 						__func__, wTransType);
 			}
 		} else		/*  Failed to read parameters */
-			dev_err(&pdx->interface->dev, "%s ReadDMAInfo() fail",
+			dev_err(&pdx->interface->dev, "%s: ReadDMAInfo() fail\n",
 				__func__);
 
 		spin_unlock(&pdx->stagedLock);	/*  OK here */
 	}
 
-	dev_dbg(&pdx->interface->dev, "%s returns %d", __func__, iReturn);
+	dev_dbg(&pdx->interface->dev, "%s: returns %d\n", __func__, iReturn);
 
 	return iReturn;
 }
@@ -1100,11 +1100,11 @@ static void ced_readchar_callback(struct urb *pUrb)
 		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
 		     || pUrb->status == -ESHUTDOWN)) {
 			dev_err(&pdx->interface->dev,
-				"%s - nonzero write bulk status received: %d",
+				"%s: nonzero write bulk status received: %d\n",
 				__func__, pUrb->status);
 		} else
 			dev_dbg(&pdx->interface->dev,
-				"%s - 0 chars pUrb->status=%d (shutdown?)",
+				"%s: 0 chars pUrb->status=%d (shutdown?)\n",
 				__func__, pUrb->status);
 
 		spin_lock(&pdx->err_lock);
@@ -1125,7 +1125,7 @@ static void ced_readchar_callback(struct urb *pUrb)
 				if (nGot < INBUF_SZ) {
 					pdx->pCoherCharIn[nGot] = 0;	/*  tidy the string */
 					dev_dbg(&pdx->interface->dev,
-						"%s got %d chars >%s<",
+						"%s: got %d chars >%s<\n",
 						__func__, nGot,
 						pdx->pCoherCharIn);
 				}
@@ -1140,7 +1140,7 @@ static void ced_readchar_callback(struct urb *pUrb)
 				if ((pdx->dwNumInput + nGot) <= INBUF_SZ)
 					pdx->dwNumInput += nGot;	/*  Adjust the buffer count accordingly */
 			} else
-				dev_dbg(&pdx->interface->dev, "%s read ZLP",
+				dev_dbg(&pdx->interface->dev, "%s: read ZLP\n",
 					__func__);
 		}
 	}
@@ -1178,7 +1178,7 @@ int Allowi(DEVICE_EXTENSION *pdx)
 		unsigned int nMax = INBUF_SZ - pdx->dwNumInput;	/*  max we could read */
 		int nPipe = pdx->nPipes == 4 ? 1 : 0;	/*  The pipe number to use */
 
-		dev_dbg(&pdx->interface->dev, "%s %d chars in input buffer",
+		dev_dbg(&pdx->interface->dev, "%s: %d chars in input buffer\n",
 			__func__, pdx->dwNumInput);
 
 		usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev,
@@ -1192,7 +1192,8 @@ int Allowi(DEVICE_EXTENSION *pdx)
 			usb_unanchor_urb(pdx->pUrbCharIn);	/*  remove from list of active Urbs */
 			pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
 			dev_err(&pdx->interface->dev,
-				"%s submit urb failed: %d", __func__, iReturn);
+				"%s: submit urb failed: %d\n",
+				__func__, iReturn);
 		} else
 			pdx->bReadCharsPending = true;	/*  Flag that we are active here */
 	}
@@ -1397,7 +1398,7 @@ static int ced_probe(struct usb_interface *interface,
 	else if ((i >= 1) && (i <= 23))
 		pdx->s1401Type = i + 2;
 	else {
-		dev_err(&interface->dev, "%s Unknown device. bcdDevice = %d",
+		dev_err(&interface->dev, "%s: Unknown device. bcdDevice = %d\n",
 			__func__, bcdDevice);
 		goto error;
 	}
@@ -1405,7 +1406,7 @@ static int ced_probe(struct usb_interface *interface,
 	/*  we know that we are dealing with a 1401 device. */
 	iface_desc = interface->cur_altsetting;
 	pdx->nPipes = iface_desc->desc.bNumEndpoints;
-	dev_info(&interface->dev, "1401Type=%d with %d End Points",
+	dev_info(&interface->dev, "1401Type=%d with %d End Points\n",
 		 pdx->s1401Type, pdx->nPipes);
 	if ((pdx->nPipes < 3) || (pdx->nPipes > 4))
 		goto error;
@@ -1415,7 +1416,7 @@ static int ced_probe(struct usb_interface *interface,
 	pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL);	/*  character input URB */
 	pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL);	/*  block transfer URB */
 	if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb) {
-		dev_err(&interface->dev, "%s URB alloc failed", __func__);
+		dev_err(&interface->dev, "%s: URB alloc failed\n", __func__);
 		goto error;
 	}
 
@@ -1429,7 +1430,7 @@ static int ced_probe(struct usb_interface *interface,
 	    usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL,
 			       &pdx->pUrbCharIn->transfer_dma);
 	if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO) {
-		dev_err(&interface->dev, "%s Coherent buffer alloc failed",
+		dev_err(&interface->dev, "%s: Coherent buffer alloc failed\n",
 			__func__);
 		goto error;
 	}
@@ -1437,19 +1438,19 @@ static int ced_probe(struct usb_interface *interface,
 	for (i = 0; i < pdx->nPipes; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 		pdx->epAddr[i] = endpoint->bEndpointAddress;
-		dev_info(&interface->dev, "Pipe %d, ep address %02x", i,
-			 pdx->epAddr[i]);
+		dev_info(&interface->dev, "Pipe %d, ep address %02x\n",
+			 i, pdx->epAddr[i]);
 		if (((pdx->nPipes == 3) && (i == 0)) ||	/*  if char input end point */
 		    ((pdx->nPipes == 4) && (i == 1))) {
 			pdx->bInterval = endpoint->bInterval;	/*  save the endpoint interrupt interval */
-			dev_info(&interface->dev, "Pipe %d, bInterval = %d", i,
-				 pdx->bInterval);
+			dev_info(&interface->dev, "Pipe %d, bInterval = %d\n",
+				 i, pdx->bInterval);
 		}
 		/*  Detect USB2 by checking last ep size (64 if USB1) */
 		if (i == pdx->nPipes - 1) {	/*  if this is the last ep (bulk) */
 			pdx->bIsUSB2 =
 			    le16_to_cpu(endpoint->wMaxPacketSize) > 64;
-			dev_info(&pdx->interface->dev, "USB%d",
+			dev_info(&pdx->interface->dev, "USB%d\n",
 				 pdx->bIsUSB2 + 1);
 		}
 	}
@@ -1462,14 +1463,14 @@ static int ced_probe(struct usb_interface *interface,
 	if (retval) {
 		/* something prevented us from registering this driver */
 		dev_err(&interface->dev,
-			"Not able to get a minor for this device.\n");
+			"Not able to get a minor for this device\n");
 		usb_set_intfdata(interface, NULL);
 		goto error;
 	}
 
 	/* let the user know what node this device is now attached to */
 	dev_info(&interface->dev,
-		 "USB CEDUSB device now attached to cedusb #%d",
+		 "USB CEDUSB device now attached to cedusb #%d\n",
 		 interface->minor);
 	return 0;
 
@@ -1493,7 +1494,7 @@ static void ced_disconnect(struct usb_interface *interface)
 	for (i = 0; i < MAX_TRANSAREAS; ++i) {
 		int iErr = ClearArea(pdx, i);	/*  ...release any used memory */
 		if (iErr == U14ERR_UNLOCKFAIL)
-			dev_err(&pdx->interface->dev, "%s Area %d was in used",
+			dev_err(&pdx->interface->dev, "%s: Area %d was in used\n",
 				__func__, i);
 	}
 	pdx->interface = NULL;	/*  ...we kill off link to interface */
@@ -1503,7 +1504,7 @@ static void ced_disconnect(struct usb_interface *interface)
 
 	kref_put(&pdx->kref, ced_delete);	/*  decrement our usage count */
 
-	dev_info(&interface->dev, "USB cedusb #%d now disconnected", minor);
+	dev_info(&interface->dev, "USB cedusb #%d now disconnected\n", minor);
 }
 
 /*  Wait for all the urbs we know of to be done with, then kill off any that */
@@ -1513,13 +1514,13 @@ static void ced_disconnect(struct usb_interface *interface)
 void ced_draw_down(DEVICE_EXTENSION *pdx)
 {
 	int time;
-	dev_dbg(&pdx->interface->dev, "%s called", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
 
 	pdx->bInDrawDown = true;
 	time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
 	if (!time) {		/*  if we timed out we kill the urbs */
 		usb_kill_anchored_urbs(&pdx->submitted);
-		dev_err(&pdx->interface->dev, "%s timed out", __func__);
+		dev_err(&pdx->interface->dev, "%s: timed out\n", __func__);
 	}
 	pdx->bInDrawDown = false;
 }
@@ -1531,7 +1532,7 @@ static int ced_suspend(struct usb_interface *intf, pm_message_t message)
 		return 0;
 	ced_draw_down(pdx);
 
-	dev_dbg(&pdx->interface->dev, "%s called", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
 	return 0;
 }
 
@@ -1540,14 +1541,14 @@ static int ced_resume(struct usb_interface *intf)
 	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
 	if (!pdx)
 		return 0;
-	dev_dbg(&pdx->interface->dev, "%s called", __func__);
+	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
 	return 0;
 }
 
 static int ced_pre_reset(struct usb_interface *intf)
 {
 	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 	mutex_lock(&pdx->io_mutex);
 	ced_draw_down(pdx);
 	return 0;
@@ -1556,7 +1557,7 @@ static int ced_pre_reset(struct usb_interface *intf)
 static int ced_post_reset(struct usb_interface *intf)
 {
 	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	dev_dbg(&pdx->interface->dev, "%s", __func__);
+	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
 
 	/* we are sure no URBs are active - no locking needed */
 	pdx->errors = -EPIPE;
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index c22c617b0da1..a819e543ed30 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -297,7 +297,7 @@ static ssize_t max_read_buffer_kb_show(struct device *csdev,
 	mutex_unlock(&dev->mutex);
 
 	comedi_dev_put(dev);
-	return snprintf(buf, PAGE_SIZE, "%i\n", size);
+	return snprintf(buf, PAGE_SIZE, "%u\n", size);
 }
 
 static ssize_t max_read_buffer_kb_store(struct device *csdev,
@@ -353,7 +353,7 @@ static ssize_t read_buffer_kb_show(struct device *csdev,
 	mutex_unlock(&dev->mutex);
 
 	comedi_dev_put(dev);
-	return snprintf(buf, PAGE_SIZE, "%i\n", size);
+	return snprintf(buf, PAGE_SIZE, "%u\n", size);
 }
 
 static ssize_t read_buffer_kb_store(struct device *csdev,
@@ -410,7 +410,7 @@ static ssize_t max_write_buffer_kb_show(struct device *csdev,
 	mutex_unlock(&dev->mutex);
 
 	comedi_dev_put(dev);
-	return snprintf(buf, PAGE_SIZE, "%i\n", size);
+	return snprintf(buf, PAGE_SIZE, "%u\n", size);
 }
 
 static ssize_t max_write_buffer_kb_store(struct device *csdev,
@@ -466,7 +466,7 @@ static ssize_t write_buffer_kb_show(struct device *csdev,
 	mutex_unlock(&dev->mutex);
 
 	comedi_dev_put(dev);
-	return snprintf(buf, PAGE_SIZE, "%i\n", size);
+	return snprintf(buf, PAGE_SIZE, "%u\n", size);
 }
 
 static ssize_t write_buffer_kb_store(struct device *csdev,
@@ -1194,6 +1194,11 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
 		switch (insn->insn) {
 		case INSN_READ:
 			ret = s->insn_read(dev, s, insn, data);
+			if (ret == -ETIMEDOUT) {
+				dev_dbg(dev->class_dev,
+					"subdevice %d read instruction timed out\n",
+					s->index);
+			}
 			break;
 		case INSN_WRITE:
 			maxdata = s->maxdata_list
@@ -1207,8 +1212,14 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
 					break;
 				}
 			}
-			if (ret == 0)
+			if (ret == 0) {
 				ret = s->insn_write(dev, s, insn, data);
+				if (ret == -ETIMEDOUT) {
+					dev_dbg(dev->class_dev,
+						"subdevice %d write instruction timed out\n",
+						s->index);
+				}
+			}
 			break;
 		case INSN_BITS:
 			if (insn->n != 2) {
@@ -1470,7 +1481,8 @@ static int do_cmd_ioctl(struct comedi_device *dev,
 	async->cmd.data = NULL;
 	/* load channel/gain list */
 	async->cmd.chanlist = memdup_user(user_chanlist,
-					  async->cmd.chanlist_len * sizeof(int));
+					  async->cmd.chanlist_len *
+					  sizeof(int));
 	if (IS_ERR(async->cmd.chanlist)) {
 		ret = PTR_ERR(async->cmd.chanlist);
 		async->cmd.chanlist = NULL;
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index f82bd4256d51..d46123a97582 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -61,31 +61,31 @@ struct comedi_subdevice {
 
 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
 
-	int (*insn_read) (struct comedi_device *, struct comedi_subdevice *,
+	int (*insn_read)(struct comedi_device *, struct comedi_subdevice *,
+			 struct comedi_insn *, unsigned int *);
+	int (*insn_write)(struct comedi_device *, struct comedi_subdevice *,
 			  struct comedi_insn *, unsigned int *);
-	int (*insn_write) (struct comedi_device *, struct comedi_subdevice *,
+	int (*insn_bits)(struct comedi_device *, struct comedi_subdevice *,
+			 struct comedi_insn *, unsigned int *);
+	int (*insn_config)(struct comedi_device *, struct comedi_subdevice *,
 			   struct comedi_insn *, unsigned int *);
-	int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *,
-			  struct comedi_insn *, unsigned int *);
-	int (*insn_config) (struct comedi_device *, struct comedi_subdevice *,
-			    struct comedi_insn *, unsigned int *);
-
-	int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
-	int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *,
-			   struct comedi_cmd *);
-	int (*poll) (struct comedi_device *, struct comedi_subdevice *);
-	int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
+
+	int (*do_cmd)(struct comedi_device *, struct comedi_subdevice *);
+	int (*do_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
+			  struct comedi_cmd *);
+	int (*poll)(struct comedi_device *, struct comedi_subdevice *);
+	int (*cancel)(struct comedi_device *, struct comedi_subdevice *);
 	/* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */
 	/* int (*do_unlock)(struct comedi_device *, \
 			struct comedi_subdevice *); */
 
 	/* called when the buffer changes */
-	int (*buf_change) (struct comedi_device *dev,
-			   struct comedi_subdevice *s, unsigned long new_size);
+	int (*buf_change)(struct comedi_device *dev,
+			  struct comedi_subdevice *s, unsigned long new_size);
 
-	void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s,
-		       void *data, unsigned int num_bytes,
-		       unsigned int start_chan_index);
+	void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
+		      void *data, unsigned int num_bytes,
+		      unsigned int start_chan_index);
 	enum dma_data_direction async_dma_dir;
 
 	unsigned int state;
@@ -146,8 +146,8 @@ struct comedi_async {
 
 	unsigned int cb_mask;
 
-	int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned int x);
+	int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
+		       unsigned int x);
 };
 
 struct comedi_driver {
@@ -155,9 +155,9 @@ struct comedi_driver {
 
 	const char *driver_name;
 	struct module *module;
-	int (*attach) (struct comedi_device *, struct comedi_devconfig *);
-	void (*detach) (struct comedi_device *);
-	int (*auto_attach) (struct comedi_device *, unsigned long);
+	int (*attach)(struct comedi_device *, struct comedi_devconfig *);
+	void (*detach)(struct comedi_device *);
+	int (*auto_attach)(struct comedi_device *, unsigned long);
 
 	/* number of elements in board_name and board_id arrays */
 	unsigned int num_names;
@@ -202,8 +202,8 @@ struct comedi_device {
 
 	struct fasync_struct *async_queue;
 
-	int (*open) (struct comedi_device *dev);
-	void (*close) (struct comedi_device *dev);
+	int (*open)(struct comedi_device *dev);
+	void (*close)(struct comedi_device *dev);
 };
 
 static inline const void *comedi_board(const struct comedi_device *dev)
@@ -353,6 +353,14 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
 
 /* drivers.c - general comedi driver functions */
 
+#define COMEDI_TIMEOUT_MS	1000
+
+int comedi_timeout(struct comedi_device *, struct comedi_subdevice *,
+		   struct comedi_insn *,
+		   int (*cb)(struct comedi_device *, struct comedi_subdevice *,
+			     struct comedi_insn *, unsigned long context),
+		   unsigned long context);
+
 int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *,
 			   struct comedi_insn *, unsigned int *data,
 			   unsigned int mask);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 5b15033a94bf..ab0e8ed47291 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -155,6 +155,36 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
 }
 
 /**
+ * comedi_timeout() - busy-wait for a driver condition to occur.
+ * @dev: comedi_device struct
+ * @s: comedi_subdevice struct
+ * @insn: comedi_insn struct
+ * @cb: callback to check for the condition
+ * @context: private context from the driver
+ */
+int comedi_timeout(struct comedi_device *dev,
+		   struct comedi_subdevice *s,
+		   struct comedi_insn *insn,
+		   int (*cb)(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned long context),
+		   unsigned long context)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(COMEDI_TIMEOUT_MS);
+	int ret;
+
+	while (time_before(jiffies, timeout)) {
+		ret = cb(dev, s, insn, context);
+		if (ret != -EBUSY)
+			return ret;	/* success (0) or non EBUSY errno */
+		cpu_relax();
+	}
+	return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(comedi_timeout);
+
+/**
  * comedi_dio_insn_config() - boilerplate (*insn_config) for DIO subdevices.
  * @dev: comedi_device struct
  * @s: comedi_subdevice struct
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index 8a57c3c1ade0..47321de629a7 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -235,9 +235,6 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
 			return ret;
 	}
 
-	dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n",
-		dev->board_name, board->n_8255 * 24);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 1128c22e7517..80cca95c830a 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -106,8 +106,8 @@ static struct comedi_lrange range_apci035_ai = {
 	}
 };
 
-static int i_WatchdogNbr = 0;
-static int i_Temp = 0;
+static int i_WatchdogNbr;
+static int i_Temp;
 static int i_Flag = 1;
 /*
 +----------------------------------------------------------------------------+
@@ -169,36 +169,31 @@ static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
 					 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Status = 0;
-	unsigned int ui_Command = 0;
-	unsigned int ui_Mode = 0;
+	unsigned int ui_Status;
+	unsigned int ui_Command;
+	unsigned int ui_Mode;
 
 	i_Temp = 0;
 	devpriv->tsk_Current = current;
 	devpriv->b_TimerSelectMode = data[0];
 	i_WatchdogNbr = data[1];
-	if (data[0] == 0) {
+	if (data[0] == 0)
 		ui_Mode = 2;
-	} else {
+	else
 		ui_Mode = 0;
-	}
-/* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */
+
 	ui_Command = 0;
-/* ui_Command = ui_Command & 0xFFFFF9FEUL; */
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-/************************/
-/* Set the reload value */
-/************************/
+
+	/* Set the reload value */
 	outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
-/*********************/
-/* Set the time unit */
-/*********************/
+
+	/* Set the time unit */
 	outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
 	if (data[0] == ADDIDATA_TIMER) {
 
-		 /******************************/
 		/* Set the mode :             */
 		/* - Disable the hardware     */
 		/* - Disable the counter mode */
@@ -206,101 +201,82 @@ static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
 		/* - Disable the reset        */
 		/* - Enable the timer mode    */
 		/* - Set the timer mode       */
-		 /******************************/
 
 		ui_Command =
 			(ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
 
-	}			/* if (data[0] == ADDIDATA_TIMER) */
-	else {
-		if (data[0] == ADDIDATA_WATCHDOG) {
+	} else if (data[0] == ADDIDATA_WATCHDOG) {
 
-		 /******************************/
-			/* Set the mode :             */
-			/* - Disable the hardware     */
-			/* - Disable the counter mode */
-			/* - Disable the warning      */
-			/* - Disable the reset        */
-			/* - Disable the timer mode   */
-		 /******************************/
+		/* Set the mode :             */
+		/* - Disable the hardware     */
+		/* - Disable the counter mode */
+		/* - Disable the warning      */
+		/* - Disable the reset        */
+		/* - Disable the timer mode   */
 
-			ui_Command = ui_Command & 0xFFF819E2UL;
+		ui_Command = ui_Command & 0xFFF819E2UL;
 
-		} else {
-			printk("\n The parameter for Timer/watchdog selection is in error\n");
-			return -EINVAL;
-		}
+	} else {
+		dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
+		return -EINVAL;
 	}
+
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-/********************************/
-/* Disable the hardware trigger */
-/********************************/
+
+	/* Disable the hardware trigger */
 	ui_Command = ui_Command & 0xFFFFF89FUL;
 	if (data[4] == ADDIDATA_ENABLE) {
-    /**********************************/
+
 		/* Set the hardware trigger level */
-    /**********************************/
 		ui_Command = ui_Command | (data[5] << 5);
 	}
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-/*****************************/
-/* Disable the hardware gate */
-/*****************************/
+
+	/* Disable the hardware gate */
 	ui_Command = ui_Command & 0xFFFFF87FUL;
 	if (data[6] == ADDIDATA_ENABLE) {
-/*******************************/
-/* Set the hardware gate level */
-/*******************************/
+
+		/* Set the hardware gate level */
 		ui_Command = ui_Command | (data[7] << 7);
 	}
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-/*******************************/
-/* Disable the hardware output */
-/*******************************/
+
+	/* Disable the hardware output */
 	ui_Command = ui_Command & 0xFFFFF9FBUL;
-/*********************************/
-/* Set the hardware output level */
-/*********************************/
+
+	/* Set the hardware output level */
 	ui_Command = ui_Command | (data[8] << 2);
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
 	if (data[9] == ADDIDATA_ENABLE) {
-   /************************/
+
 		/* Set the reload value */
-   /************************/
 		outl(data[11],
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
-   /**********************/
+
 		/* Set the time unite */
-   /**********************/
 		outl(data[10],
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
 	}
 
-	ui_Command = 0;
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- /*******************************/
+
 	/* Disable the hardware output */
- /*******************************/
 	ui_Command = ui_Command & 0xFFFFF9F7UL;
-   /*********************************/
+
 	/* Set the hardware output level */
-   /*********************************/
 	ui_Command = ui_Command | (data[12] << 3);
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- /*************************************/
- /**  Enable the watchdog interrupt  **/
- /*************************************/
-	ui_Command = 0;
+
+	/* Enable the watchdog interrupt */
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-/*******************************/
-/* Set the interrupt selection */
-/*******************************/
+
+	/* Set the interrupt selection */
 	ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
 	ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
@@ -342,50 +318,47 @@ static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
 						 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Command = 0;
-	int i_Count = 0;
+	unsigned int ui_Command;
+	int i_Count;
 
 	if (data[0] == 1) {
 		ui_Command =
 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	 /**********************/
+
 		/* Start the hardware */
-	 /**********************/
 		ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	}			/*  if  (data[0]==1) */
+	}
 	if (data[0] == 2) {
 		ui_Command =
 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	 /***************************/
+
 		/* Set the trigger command */
-	 /***************************/
 		ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
 	}
 
-	if (data[0] == 0)	/* Stop The Watchdog */
-	{
+	if (data[0] == 0) {
 		/* Stop The Watchdog */
 		ui_Command = 0;
-/*
-* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
-* ui_Command = ui_Command & 0xFFFFF9FEUL;
-*/
+		/*
+		* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+		* ui_Command = ui_Command & 0xFFFFF9FEUL;
+		*/
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	}			/*   if (data[1]==0) */
-	if (data[0] == 3)	/* stop all Watchdogs */
-	{
+	}
+	if (data[0] == 3) {
+		/* stop all Watchdogs */
 		ui_Command = 0;
 		for (i_Count = 1; i_Count <= 4; i_Count++) {
-			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
 				ui_Command = 0x2UL;
-			} else {
+			else
 				ui_Command = 0x10UL;
-			}
+
 			i_WatchdogNbr = i_Count;
 			outl(ui_Command,
 				devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
@@ -393,30 +366,29 @@ static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
 		}
 
 	}
-	if (data[0] == 4)	/* start all Watchdogs */
-	{
+	if (data[0] == 4) {
+		/* start all Watchdogs */
 		ui_Command = 0;
 		for (i_Count = 1; i_Count <= 4; i_Count++) {
-			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
 				ui_Command = 0x1UL;
-			} else {
+			else
 				ui_Command = 0x8UL;
-			}
+
 			i_WatchdogNbr = i_Count;
 			outl(ui_Command,
 				devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
 				0);
 		}
 	}
-	if (data[0] == 5)	/* trigger all Watchdogs */
-	{
+	if (data[0] == 5) {
+		/* trigger all Watchdogs */
 		ui_Command = 0;
 		for (i_Count = 1; i_Count <= 4; i_Count++) {
-			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+			if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
 				ui_Command = 0x4UL;
-			} else {
+			else
 				ui_Command = 0x20UL;
-			}
 
 			i_WatchdogNbr = i_Count;
 			outl(ui_Command,
@@ -461,38 +433,27 @@ static int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev,
 				       unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Status = 0;	/*  Status register */
+	unsigned int ui_Status;	/*  Status register */
 
 	i_WatchdogNbr = insn->unused[0];
 
-	/******************/
 	/* Get the status */
-	/******************/
-
 	ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
-	/***********************************/
 	/* Get the software trigger status */
-	/***********************************/
-
 	data[0] = ((ui_Status >> 1) & 1);
-	/***********************************/
+
 	/* Get the hardware trigger status */
-	/***********************************/
 	data[1] = ((ui_Status >> 2) & 1);
-	/*********************************/
+
 	/* Get the software clear status */
-	/*********************************/
 	data[2] = ((ui_Status >> 3) & 1);
-	/***************************/
+
 	/* Get the overflow status */
-	/***************************/
 	data[3] = ((ui_Status >> 0) & 1);
-	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER)
 		data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
 
-	}			/*   if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
-
 	return insn->n;
 }
 
@@ -529,9 +490,8 @@ static int i_APCI035_ConfigAnalogInput(struct comedi_device *dev,
 	devpriv->tsk_Current = current;
 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
 	outl(0, devpriv->iobase + 128 + 0);
-/********************************/
-/* Initialise the warning value */
-/********************************/
+
+	/* Initialise the warning value */
 	outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
 	outl((data[0] << 8), devpriv->iobase + 128 + 0);
 	outl(0x200000UL, devpriv->iobase + 128 + 12);
@@ -566,20 +526,15 @@ static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
 				     unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_CommandRegister = 0;
+	unsigned int ui_CommandRegister;
 
-/******************/
-/*  Set the start */
-/******************/
+	/*  Set the start */
 	ui_CommandRegister = 0x80000;
- /******************************/
+
 	/* Write the command register */
- /******************************/
 	outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
 
-/***************************************/
-/* Read the digital value of the input */
-/***************************************/
+	/* Read the digital value of the input */
 	data[0] = inl(devpriv->iobase + 128 + 28);
 	return insn->n;
 }
@@ -602,11 +557,13 @@ static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
 static int i_APCI035_Reset(struct comedi_device *dev)
 {
 	struct addi_private *devpriv = dev->private;
-	int i_Count = 0;
+	int i_Count;
 
 	for (i_Count = 1; i_Count <= 4; i_Count++) {
 		i_WatchdogNbr = i_Count;
-		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	/* stop all timers */
+
+		/* stop all timers */
+		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
 	}
 	outl(0x0, devpriv->iobase + 128 + 12);	/* Disable the warning delay */
 
@@ -634,51 +591,45 @@ static void v_APCI035_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_StatusRegister1 = 0;
-	unsigned int ui_StatusRegister2 = 0;
-	unsigned int ui_ReadCommand = 0;
-	unsigned int ui_ChannelNumber = 0;
-	unsigned int ui_DigitalTemperature = 0;
+	unsigned int ui_StatusRegister1;
+	unsigned int ui_StatusRegister2;
+	unsigned int ui_ReadCommand;
+	unsigned int ui_ChannelNumber;
+	unsigned int ui_DigitalTemperature;
 
 	if (i_Temp == 1) {
 		i_WatchdogNbr = i_Flag;
 		i_Flag = i_Flag + 1;
 	}
-  /**************************************/
+
 	/* Read the interrupt status register of temperature Warning */
-  /**************************************/
 	ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
-  /**************************************/
-	/* Read the interrupt status register for Watchdog/timer */
-   /**************************************/
 
+	/* Read the interrupt status register for Watchdog/timer */
 	ui_StatusRegister2 =
 		inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
 
-	if ((((ui_StatusRegister1) & 0x8) == 0x8))	/* Test if warning relay interrupt */
-	{
-	/**********************************/
+	/* Test if warning relay interrupt */
+	if ((((ui_StatusRegister1) & 0x8) == 0x8)) {
+
 		/* Disable the temperature warning */
-	/**********************************/
 		ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
 		ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
 		outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
-      /***************************/
+
 		/* Read the channel number */
-      /***************************/
 		ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
-	/**************************************/
+
 		/* Read the digital temperature value */
-	/**************************************/
 		ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
-		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
-	}			/* if (((ui_StatusRegister1 & 0x8) == 0x8)) */
 
-	else {
-		if ((ui_StatusRegister2 & 0x1) == 0x1) {
-			send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
-		}
-	}			/* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */
+		/*  send signal to the sample */
+		send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+	} else if ((ui_StatusRegister2 & 0x1) == 0x1) {
+		/*  send signal to the sample */
+		send_sig(SIGIO, devpriv->tsk_Current, 0);
+	}
 
 	return;
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 84668544f52d..2b47fa17d601 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -100,7 +100,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
 #define APCI1564_TCW_WARN_TIMEBASE			28
 
 /* Global variables */
-static unsigned int ui_InterruptStatus_1564 = 0;
+static unsigned int ui_InterruptStatus_1564;
 static unsigned int ui_InterruptData, ui_Type;
 
 /*
@@ -138,9 +138,8 @@ static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
 	struct addi_private *devpriv = dev->private;
 
 	devpriv->tsk_Current = current;
-   /*******************************/
+
 	/* Set the digital input logic */
-   /*******************************/
 	if (data[0] == ADDIDATA_ENABLE) {
 		data[2] = data[2] << 4;
 		data[3] = data[3] << 4;
@@ -154,14 +153,12 @@ static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
 			outl(0x4,
 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
 				APCI1564_DIGITAL_IP_IRQ);
-		}		/*  if  (data[1] == ADDIDATA_OR) */
-		else {
+		} else {
 			outl(0x6,
 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
 				APCI1564_DIGITAL_IP_IRQ);
-		}		/*  else if  (data[1] == ADDIDATA_OR) */
-	}			/*  if  (data[0] == ADDIDATA_ENABLE) */
-	else {
+		}
+	} else {
 		outl(0x0,
 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
 			APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
@@ -171,7 +168,7 @@ static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
 		outl(0x0,
 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
 			APCI1564_DIGITAL_IP_IRQ);
-	}			/*  else if  (data[0] == ADDIDATA_ENABLE) */
+	}
 
 	return insn->n;
 }
@@ -225,25 +222,23 @@ static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev,
 		comedi_error(dev,
 			"Not a valid Data !!! ,Data should be 1 or 0\n");
 		return -EINVAL;
-	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
-	if (data[0]) {
+	}
+
+	if (data[0])
 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
-	}			/*  if  (data[0]) */
-	else {
+	else
 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
-	}			/*  else if  (data[0]) */
-	if (data[1] == ADDIDATA_ENABLE) {
+
+	if (data[1] == ADDIDATA_ENABLE)
 		ul_Command = ul_Command | 0x1;
-	}			/*  if  (data[1] == ADDIDATA_ENABLE) */
-	else {
+	else
 		ul_Command = ul_Command & 0xFFFFFFFE;
-	}			/*  else if  (data[1] == ADDIDATA_ENABLE) */
-	if (data[2] == ADDIDATA_ENABLE) {
+
+	if (data[2] == ADDIDATA_ENABLE)
 		ul_Command = ul_Command | 0x2;
-	}			/*  if  (data[2] == ADDIDATA_ENABLE) */
-	else {
+	else
 		ul_Command = ul_Command & 0xFFFFFFFD;
-	}			/*  else if  (data[2] == ADDIDATA_ENABLE) */
+
 	outl(ul_Command,
 		devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
 		APCI1564_DIGITAL_OP_INTERRUPT);
@@ -323,8 +318,7 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 		outl(data[3],
 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
 			APCI1564_TCW_RELOAD_VALUE);
-	}			/*  if  (data[0]==ADDIDATA_WATCHDOG) */
-	else if (data[0] == ADDIDATA_TIMER) {
+	} else if (data[0] == ADDIDATA_TIMER) {
 		/* First Stop The Timer */
 		ul_Command1 =
 			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
@@ -357,13 +351,11 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 			outl(0x0,
 				devpriv->iobase + APCI1564_COUNTER4 +
 				APCI1564_TCW_IRQ);
-		}		/*  if  (data[1]==1) */
-		else {
+		} else {
 			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* disable Timer interrupt */
-		}		/*  else if  (data[1]==1) */
+		}
 
 		/*  Loading Timebase */
-
 		outl(data[2],
 			devpriv->i_IobaseAmcc + APCI1564_TIMER +
 			APCI1564_TCW_TIMEBASE);
@@ -379,8 +371,7 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 		ul_Command1 =
 			(ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
 		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* mode 2 */
-	}			/*  else if  (data[0]==ADDIDATA_TIMER) */
-	else if (data[0] == ADDIDATA_COUNTER) {
+	} else if (data[0] == ADDIDATA_COUNTER) {
 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
 		devpriv->b_ModeSelectRegister = data[5];
 
@@ -391,14 +382,11 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
 		outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG);	/* Stop The Timer */
 
-      /************************/
 		/* Set the reload value */
-      /************************/
 		outl(data[3],
 			devpriv->iobase + ((data[5] - 1) * 0x20) +
 			APCI1564_TCW_RELOAD_VALUE);
 
-      /******************************/
 		/* Set the mode :             */
 		/* - Disable the hardware     */
 		/* - Disable the counter mode */
@@ -406,7 +394,7 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 		/* - Disable the reset        */
 		/* - Disable the timer mode   */
 		/* - Enable the counter mode  */
-      /******************************/
+
 		ul_Command1 =
 			(ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
 			(unsigned int) ((unsigned int) data[4] << 16UL);
@@ -420,17 +408,14 @@ static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 			devpriv->iobase + ((data[5] - 1) * 0x20) +
 			APCI1564_TCW_PROG);
 
-      /*****************************/
 		/* Set the Up/Down selection */
-      /*****************************/
 		ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
 		outl(ul_Command1,
 			devpriv->iobase + ((data[5] - 1) * 0x20) +
 			APCI1564_TCW_PROG);
-	}			/*  else if  (data[0]==ADDIDATA_COUNTER) */
-	else {
-		printk(" Invalid subdevice.");
-	}			/*  else if  (data[0]==ADDIDATA_WATCHDOG) */
+	} else {
+		dev_err(dev->class_dev, "Invalid subdevice.\n");
+	}
 
 	return insn->n;
 }
@@ -487,10 +472,10 @@ static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *d
 				APCI1564_TCW_PROG);
 			break;
 		default:
-			printk("\nSpecified functionality does not exist\n");
+			dev_err(dev->class_dev, "Specified functionality does not exist.\n");
 			return -EINVAL;
-		}		/*  switch (data[1]) */
-	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+		}
+	}
 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
 		if (data[1] == 1) {
 			ul_Command1 =
@@ -502,8 +487,7 @@ static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *d
 			outl(ul_Command1,
 				devpriv->i_IobaseAmcc + APCI1564_TIMER +
 				APCI1564_TCW_PROG);
-		}		/*  if  (data[1]==1) */
-		else if (data[1] == 0) {
+		} else if (data[1] == 0) {
 			/* Stop The Timer */
 
 			ul_Command1 =
@@ -513,8 +497,8 @@ static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *d
 			outl(ul_Command1,
 				devpriv->i_IobaseAmcc + APCI1564_TIMER +
 				APCI1564_TCW_PROG);
-		}		/*  else if(data[1]==0) */
-	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+		}
+	}
 	if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
 		ul_Command1 =
 			inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
@@ -522,16 +506,14 @@ static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *d
 		if (data[1] == 1) {
 			/* Start the Counter subdevice */
 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
-		}		/*  if  (data[1] == 1) */
-		else if (data[1] == 0) {
+		} else if (data[1] == 0) {
 			/*  Stops the Counter subdevice */
 			ul_Command1 = 0;
 
-		}		/*  else if  (data[1] == 0) */
-		else if (data[1] == 2) {
+		} else if (data[1] == 2) {
 			/*  Clears the Counter subdevice */
 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
-		}		/*  else if  (data[1] == 3) */
+		}
 		outl(ul_Command1,
 			devpriv->iobase + ((devpriv->b_ModeSelectRegister -
 					1) * 0x20) + APCI1564_TCW_PROG);
@@ -577,8 +559,7 @@ static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
 		data[1] =
 			inl(devpriv->i_IobaseAmcc +
 			APCI1564_DIGITAL_OP_WATCHDOG);
-	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
-	else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+	} else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
 		/*  Stores the status of the Timer */
 		data[0] =
 			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
@@ -586,8 +567,7 @@ static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
 
 		/*  Stores the Actual value of the Timer */
 		data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
-	}			/*  else if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
-	else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+	} else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
 		/*  Read the Counter Actual Value. */
 		data[0] =
 			inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
@@ -597,31 +577,22 @@ static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
 			inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
 					1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
 
-      /***********************************/
 		/* Get the software trigger status */
-      /***********************************/
 		data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
 
-      /***********************************/
 		/* Get the hardware trigger status */
-      /***********************************/
 		data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
 
-      /*********************************/
 		/* Get the software clear status */
-      /*********************************/
 		data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
 
-      /***************************/
 		/* Get the overflow status */
-      /***************************/
 		data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
-	}			/*  else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
-	else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+	} else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
 		&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
 		&& (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
-		printk("\n Invalid Subdevice !!!\n");
-	}			/*  else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
+		dev_err(dev->class_dev, "Invalid Subdevice!\n");
+	}
 	return insn->n;
 }
 
@@ -694,8 +665,8 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 		APCI1564_TCW_IRQ) & 0x1;
 	if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
 		&& ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
-		printk("\nInterrupt from unknown source\n");
-	}			/*  if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
+		dev_err(dev->class_dev, "Interrupt from unknown source.\n");
+	}
 
 	if (ui_DI == 1) {
 		ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
@@ -724,8 +695,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 
 		/* Sends signal to user space */
 		send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-	}			/*  if  (ui_DO) */
+	}
 
 	if (ui_Timer == 1) {
 		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
@@ -748,8 +718,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 			     devpriv->i_IobaseAmcc + APCI1564_TIMER +
 			     APCI1564_TCW_PROG);
 		}
-	}/* if  (ui_Timer == 1) */
-
+	}
 
 	if (ui_C1 == 1) {
 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
@@ -771,7 +740,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 			     devpriv->iobase + APCI1564_COUNTER1 +
 			     APCI1564_TCW_PROG);
 		}
-	} /* if  (ui_C1 == 1) */
+	}
 
 	if (ui_C2 == 1) {
 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
@@ -793,7 +762,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 			     devpriv->iobase + APCI1564_COUNTER2 +
 			     APCI1564_TCW_PROG);
 		}
-	} /*  if  ((ui_C2 == 1) */
+	}
 
 	if (ui_C3 == 1) {
 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
@@ -815,7 +784,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 			     devpriv->iobase + APCI1564_COUNTER3 +
 			     APCI1564_TCW_PROG);
 		}
-	}	/*  if ((ui_C3 == 1) */
+	}
 
 	if (ui_C4 == 1) {
 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
@@ -837,7 +806,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 			     devpriv->iobase + APCI1564_COUNTER4 +
 			     APCI1564_TCW_PROG);
 		}
-	}	/*  if (ui_C4 == 1) */
+	}
 	return;
 }
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index ceadf8eff47f..6dc11c407f57 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -434,13 +434,26 @@ static int apci3xxx_ai_setup(struct comedi_device *dev, unsigned int chanspec)
 	return 0;
 }
 
+static int apci3xxx_ai_eoc(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
+			   unsigned long context)
+{
+	struct apci3xxx_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readl(devpriv->mmio + 20);
+	if (status & 0x1)
+		return 0;
+	return -EBUSY;
+}
+
 static int apci3xxx_ai_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
 	struct apci3xxx_private *devpriv = dev->private;
-	unsigned int val;
 	int ret;
 	int i;
 
@@ -453,10 +466,9 @@ static int apci3xxx_ai_insn_read(struct comedi_device *dev,
 		writel(0x80000, devpriv->mmio + 8);
 
 		/* Wait the EOS */
-		do {
-			val = readl(devpriv->mmio + 20);
-			val &= 0x1;
-		} while (!val);
+		ret = comedi_timeout(dev, s, insn, apci3xxx_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* Read the analog value */
 		data[i] = readl(devpriv->mmio + 28);
@@ -622,6 +634,20 @@ static int apci3xxx_ai_cancel(struct comedi_device *dev,
 	return 0;
 }
 
+static int apci3xxx_ao_eoc(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
+			   unsigned long context)
+{
+	struct apci3xxx_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readl(devpriv->mmio + 96);
+	if (status & 0x100)
+		return 0;
+	return -EBUSY;
+}
+
 static int apci3xxx_ao_insn_write(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn,
@@ -630,7 +656,7 @@ static int apci3xxx_ao_insn_write(struct comedi_device *dev,
 	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int range = CR_RANGE(insn->chanspec);
-	unsigned int status;
+	int ret;
 	int i;
 
 	for (i = 0; i < insn->n; i++) {
@@ -641,9 +667,9 @@ static int apci3xxx_ao_insn_write(struct comedi_device *dev,
 		writel((data[i] << 8) | chan, devpriv->mmio + 100);
 
 		/* Wait the end of transfer */
-		do {
-			status = readl(devpriv->mmio + 96);
-		} while ((status & 0x100) != 0x100);
+		ret = comedi_timeout(dev, s, insn, apci3xxx_ao_eoc, 0);
+		if (ret)
+			return ret;
 	}
 
 	return insn->n;
@@ -680,7 +706,7 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev,
 				    unsigned int *data)
 {
 	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned int mask;
+	unsigned int mask = 0;
 	int ret;
 
 	/*
@@ -688,12 +714,13 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev,
 	 * Port 1 (channels 8-15) are always outputs
 	 * Port 2 (channels 16-23) are programmable i/o
 	 */
-	if (chan < 16) {
-		if (data[0] != INSN_CONFIG_DIO_QUERY)
+	if (data[0] != INSN_CONFIG_DIO_QUERY) {
+		/* ignore all other instructions for ports 0 and 1 */
+		if (chan < 16)
 			return -EINVAL;
-	} else {
-		/* changing any channel in port 2 changes the entire port */
-		mask = 0xff0000;
+		else
+			/* changing any channel in port 2 changes the entire port */
+			mask = 0xff0000;
 	}
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 5c1413abc52d..921f6942dfce 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -73,19 +73,17 @@ struct pci6208_private {
 	unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS];
 };
 
-static int pci6208_ao_wait_for_data_send(struct comedi_device *dev,
-					 unsigned int timeout)
+static int pci6208_ao_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
 {
 	unsigned int status;
 
-	while (timeout--) {
-		status = inw(dev->iobase + PCI6208_AO_STATUS);
-		if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0)
-			return 0;
-		udelay(1);
-	}
-
-	return -ETIME;
+	status = inw(dev->iobase + PCI6208_AO_STATUS);
+	if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static int pci6208_ao_insn_write(struct comedi_device *dev,
@@ -102,8 +100,8 @@ static int pci6208_ao_insn_write(struct comedi_device *dev,
 	for (i = 0; i < insn->n; i++) {
 		val = data[i];
 
-		/* D/A transfer rate is 2.2us, wait up to 10us */
-		ret = pci6208_ao_wait_for_data_send(dev, 10);
+		/* D/A transfer rate is 2.2us */
+		ret = comedi_timeout(dev, s, insn, pci6208_ao_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 6f622b4de698..5e3cc77a8a0c 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -239,9 +239,6 @@ static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
 		}
 	}
 
-	dev_info(dev->class_dev, "%s attached (%d inputs/%d outputs)\n",
-		dev->board_name, board->di_nchan, board->do_nchan);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 363f2e42a27f..80a0560fa6a8 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -84,7 +84,6 @@ TODO:
 
 #define PCI9111_RANGE_SETTING_DELAY		10
 #define PCI9111_AI_INSTANT_READ_UDELAY_US	2
-#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
 
 /*
  * IO address map and bit defines
@@ -490,29 +489,18 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 		dev->iobase + PCI9111_AI_RANGE_STAT_REG);
 
 	/* Set counter */
-
-	switch (async_cmd->stop_src) {
-	case TRIG_COUNT:
+	if (async_cmd->stop_src == TRIG_COUNT) {
 		dev_private->stop_counter =
 		    async_cmd->stop_arg * async_cmd->chanlist_len;
 		dev_private->stop_is_none = 0;
-		break;
-
-	case TRIG_NONE:
+	} else {	/* TRIG_NONE */
 		dev_private->stop_counter = 0;
 		dev_private->stop_is_none = 1;
-		break;
-
-	default:
-		comedi_error(dev, "Invalid stop trigger");
-		return -1;
 	}
 
 	/*  Set timer pacer */
-
 	dev_private->scan_delay = 0;
-	switch (async_cmd->convert_src) {
-	case TRIG_TIMER:
+	if (async_cmd->convert_src == TRIG_TIMER) {
 		pci9111_trigger_source_set(dev, software);
 		pci9111_timer_set(dev);
 		pci9111_fifo_reset(dev);
@@ -528,11 +516,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 				 (async_cmd->convert_arg *
 				  async_cmd->chanlist_len)) - 1;
 		}
-
-		break;
-
-	case TRIG_EXT:
-
+	} else {	/* TRIG_EXT */
 		pci9111_trigger_source_set(dev, external);
 		pci9111_fifo_reset(dev);
 		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
@@ -540,11 +524,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
 		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
 					  false, true, true);
 
-		break;
-
-	default:
-		comedi_error(dev, "Invalid convert trigger");
-		return -1;
 	}
 
 	dev_private->stop_counter *= (1 + dev_private->scan_delay);
@@ -707,6 +686,19 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
 	return IRQ_HANDLED;
 }
 
+static int pci9111_ai_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+	if (status & PCI9111_AI_STAT_FF_EF)
+		return 0;
+	return -EBUSY;
+}
+
 static int pci9111_ai_insn_read(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
@@ -717,7 +709,7 @@ static int pci9111_ai_insn_read(struct comedi_device *dev,
 	unsigned int invert = (maxdata + 1) >> 1;
 	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
 	unsigned int status;
-	int timeout;
+	int ret;
 	int i;
 
 	outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
@@ -734,22 +726,12 @@ static int pci9111_ai_insn_read(struct comedi_device *dev,
 		/* Generate a software trigger */
 		outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG);
 
-		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
-
-		while (timeout--) {
-			status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
-			/* '1' means FIFO is not empty */
-			if (status & PCI9111_AI_STAT_FF_EF)
-				goto conversion_done;
+		ret = comedi_timeout(dev, s, insn, pci9111_ai_eoc, 0);
+		if (ret) {
+			pci9111_fifo_reset(dev);
+			return ret;
 		}
 
-		comedi_error(dev, "A/D read timeout");
-		data[i] = 0;
-		pci9111_fifo_reset(dev);
-		return -ETIME;
-
-conversion_done:
-
 		data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG);
 		data[i] = ((data[i] >> shift) & maxdata) ^ invert;
 	}
@@ -906,8 +888,6 @@ static int pci9111_auto_attach(struct comedi_device *dev,
 	s->range_table	= &range_digital;
 	s->insn_bits	= pci9111_do_insn_bits;
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 4bdd9720e9eb..6ca6c429c722 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -571,12 +571,26 @@ static int setup_channel_list(struct comedi_device *dev,
 	return 1;		/* we can serve this with scan logic */
 }
 
+static int pci9118_ai_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
+{
+	unsigned int status;
+
+	status = inl(dev->iobase + PCI9118_ADSTAT);
+	if (status & AdStatus_ADrdy)
+		return 0;
+	return -EBUSY;
+}
+
 static int pci9118_insn_read_ai(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
 	struct pci9118_private *devpriv = dev->private;
-	int n, timeout;
+	int ret;
+	int n;
 
 	devpriv->AdControlReg = AdControl_Int & 0xff;
 	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
@@ -597,19 +611,13 @@ static int pci9118_insn_read_ai(struct comedi_device *dev,
 	for (n = 0; n < insn->n; n++) {
 		outw(0, dev->iobase + PCI9118_SOFTTRG);	/* start conversion */
 		udelay(2);
-		timeout = 100;
-		while (timeout--) {
-			if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
-				goto conv_finish;
-			udelay(1);
-		}
 
-		comedi_error(dev, "A/D insn timeout");
-		data[n] = 0;
-		outl(0, dev->iobase + PCI9118_DELFIFO);	/* flush FIFO */
-		return -ETIME;
+		ret = comedi_timeout(dev, s, insn, pci9118_ai_eoc, 0);
+		if (ret) {
+			outl(0, dev->iobase + PCI9118_DELFIFO);	/* flush FIFO */
+			return ret;
+		}
 
-conv_finish:
 		if (devpriv->ai16bits) {
 			data[n] =
 			    (inl(dev->iobase +
@@ -1936,28 +1944,6 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
 	return NULL;
 }
 
-static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	struct pci9118_private *devpriv = dev->private;
-	char irqbuf[30];
-	char muxbuf[30];
-
-	if (irq)
-		snprintf(irqbuf, sizeof(irqbuf), "irq %u%s", irq,
-			 (dev->irq ? "" : " UNAVAILABLE"));
-	else
-		snprintf(irqbuf, sizeof(irqbuf), "irq DISABLED");
-	if (devpriv->usemux)
-		snprintf(muxbuf, sizeof(muxbuf), "ext mux %u chans",
-			 devpriv->usemux);
-	else
-		snprintf(muxbuf, sizeof(muxbuf), "no ext mux");
-	dev_info(dev->class_dev, "%s (pci %s, %s, %sbus master, %s) attached\n",
-		 dev->board_name, pci_name(pcidev), irqbuf,
-		 (devpriv->master ? "" : "no "), muxbuf);
-}
-
 static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
 				 int master, int ext_mux, int softsshdelay,
 				 int hw_err_mask)
@@ -2113,7 +2099,6 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
 		break;
 	}
 
-	pci9118_report_attach(dev, dev->irq);
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index 3190ef7d285e..b4ea37704eaf 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -94,8 +94,6 @@ If you do not specify any options, they will default to
 /* mask of the bit at STINR to check end of conversion */
 #define ADQ12B_EOC     0x20
 
-#define TIMEOUT        20
-
 /* available ranges through the PGA gains */
 static const struct comedi_lrange range_adq12b_ai_bipolar = {
 	4, {
@@ -122,19 +120,28 @@ struct adq12b_private {
 	int last_range;
 };
 
-/*
- * "instructions" read/write data in "one-shot" or "software-triggered"
- * mode.
- */
+static int adq12b_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned char status;
+
+	status = inb(dev->iobase + ADQ12B_STINR);
+	if (status & ADQ12B_EOC)
+		return 0;
+	return -EBUSY;
+}
 
 static int adq12b_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
 	struct adq12b_private *devpriv = dev->private;
-	int n, i;
+	int n;
 	int range, channel;
 	unsigned char hi, lo, status;
+	int ret;
 
 	/* change channel and range only if it is different from the previous */
 	range = CR_RANGE(insn->chanspec);
@@ -151,13 +158,9 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,
 	for (n = 0; n < insn->n; n++) {
 
 		/* wait for end of conversion */
-		i = 0;
-		do {
-			/* udelay(1); */
-			status = inb(dev->iobase + ADQ12B_STINR);
-			status = status & ADQ12B_EOC;
-		} while (status == 0 && ++i < TIMEOUT);
-		/* } while (++i < 10); */
+		ret = comedi_timeout(dev, s, insn, adq12b_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		hi = inb(dev->iobase + ADQ12B_ADHIG);
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index d9ad2c0fdda2..5978ae63d804 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -429,15 +429,26 @@ static void setup_channel_list(struct comedi_device *dev,
 	outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
 }
 
-/*
-==============================================================================
-*/
+static int pci171x_ai_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + PCI171x_STATUS);
+	if ((status & Status_FE) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int pci171x_insn_read_ai(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
 	struct pci1710_private *devpriv = dev->private;
-	int n, timeout;
+	int ret;
+	int n;
 #ifdef PCI171x_PARANOIDCHECK
 	const struct boardtype *this_board = comedi_board(dev);
 	unsigned int idata;
@@ -453,19 +464,14 @@ static int pci171x_insn_read_ai(struct comedi_device *dev,
 
 	for (n = 0; n < insn->n; n++) {
 		outw(0, dev->iobase + PCI171x_SOFTTRG);	/* start conversion */
-		/* udelay(1); */
-		timeout = 100;
-		while (timeout--) {
-			if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE))
-				goto conv_finish;
+
+		ret = comedi_timeout(dev, s, insn, pci171x_ai_eoc, 0);
+		if (ret) {
+			outb(0, dev->iobase + PCI171x_CLRFIFO);
+			outb(0, dev->iobase + PCI171x_CLRINT);
+			return ret;
 		}
-		comedi_error(dev, "A/D insn timeout");
-		outb(0, dev->iobase + PCI171x_CLRFIFO);
-		outb(0, dev->iobase + PCI171x_CLRINT);
-		data[n] = 0;
-		return -ETIME;
 
-conv_finish:
 #ifdef PCI171x_PARANOIDCHECK
 		idata = inw(dev->iobase + PCI171x_AD_DATA);
 		if (this_board->cardtype != TYPE_PCI1713)
@@ -1354,9 +1360,6 @@ static int pci1710_auto_attach(struct comedi_device *dev,
 		subdev++;
 	}
 
-	dev_info(dev->class_dev, "%s attached, irq %sabled\n",
-		dev->board_name, dev->irq ? "en" : "dis");
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 72394267ddfe..07b107d1ab33 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -280,8 +280,6 @@ static int pci1723_auto_attach(struct comedi_device *dev,
 
 	pci1723_reset(dev);
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index d4bd61d84daf..2d966a87f2e8 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -1130,10 +1130,12 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
 	for (i = 0; i < MAX_DIO_SUBDEVG; i++)
 		for (j = 0; j < this_board->sdio[i].regs; j++) {
 			s = &dev->subdevices[subdev];
-			subdev_8255_init(dev, s, NULL,
-					 dev->iobase +
-					 this_board->sdio[i].addr +
-					 SIZE_8255 * j);
+			ret = subdev_8255_init(dev, s, NULL,
+					       dev->iobase +
+					       this_board->sdio[i].addr +
+					       SIZE_8255 * j);
+			if (ret)
+				return ret;
 			subdev++;
 		}
 
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index 68c3fb3226ca..324746b14931 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -101,14 +101,27 @@ struct aio12_8_private {
 	unsigned int ao_readback[4];
 };
 
+static int aio_aio12_8_ai_eoc(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + AIO12_8_STATUS_REG);
+	if (status & AIO12_8_STATUS_ADC_EOC)
+		return 0;
+	return -EBUSY;
+}
+
 static int aio_aio12_8_ai_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int range = CR_RANGE(insn->chanspec);
-	unsigned int val;
 	unsigned char control;
+	int ret;
 	int n;
 
 	/*
@@ -122,20 +135,13 @@ static int aio_aio12_8_ai_read(struct comedi_device *dev,
 	inb(dev->iobase + AIO12_8_STATUS_REG);
 
 	for (n = 0; n < insn->n; n++) {
-		int timeout = 5;
-
 		/*  Setup and start conversion */
 		outb(control, dev->iobase + AIO12_8_ADC_REG);
 
 		/*  Wait for conversion to complete */
-		do {
-			val = inb(dev->iobase + AIO12_8_STATUS_REG);
-			timeout--;
-			if (timeout == 0) {
-				dev_err(dev->class_dev, "ADC timeout\n");
-				return -ETIMEDOUT;
-			}
-		} while (!(val & AIO12_8_STATUS_ADC_EOC));
+		ret = comedi_timeout(dev, s, insn, aio_aio12_8_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		data[n] = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata;
 	}
@@ -247,9 +253,6 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
 	/* 8254 counter/timer subdevice */
 	s->type		= COMEDI_SUBD_UNUSED;
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 22b3dda135ff..781104aa533e 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -98,7 +98,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
 	s->range_table = &range_digital;
 	s->insn_bits = aio_iiro_16_dio_insn_bits_read;
 
-	return 1;
+	return 0;
 }
 
 static struct comedi_driver aio_iiro_16_driver = {
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index 9c9559ffc643..818a0d7e3d58 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -1208,7 +1208,7 @@ int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
 				 "warning! irq %u unavailable!\n", irq);
 		}
 	}
-	dev_info(dev->class_dev, "attached\n");
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(amplc_dio200_common_attach);
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 31734e1142fd..b21d7b48f1da 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -368,32 +368,6 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
 	return IRQ_RETVAL(handled);
 }
 
-static void pc236_report_attach(struct comedi_device *dev, unsigned int irq)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	char tmpbuf[60];
-	int tmplen;
-
-	if (is_isa_board(thisboard))
-		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-				   "(base %#lx) ", dev->iobase);
-	else if (is_pci_board(thisboard))
-		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-				   "(pci %s) ", pci_name(pcidev));
-	else
-		tmplen = 0;
-	if (irq)
-		tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
-				    "(irq %u%s) ", irq,
-				    (dev->irq ? "" : " UNAVAILABLE"));
-	else
-		tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
-				    "(no irq) ");
-	dev_info(dev->class_dev, "%s %sattached\n",
-		 dev->board_name, tmpbuf);
-}
-
 static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
 			       unsigned int irq, unsigned long req_irq_flags)
 {
@@ -411,10 +385,9 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
 	s = &dev->subdevices[0];
 	/* digital i/o subdevice (8255) */
 	ret = subdev_8255_init(dev, s, NULL, iobase);
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
+	if (ret)
 		return ret;
-	}
+
 	s = &dev->subdevices[1];
 	dev->read_subdev = s;
 	s->type = COMEDI_SUBD_UNUSED;
@@ -434,8 +407,8 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
 			s->cancel = pc236_intr_cancel;
 		}
 	}
-	pc236_report_attach(dev, irq);
-	return 1;
+
+	return 0;
 }
 
 static int pc236_pci_common_attach(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 5b4b5ab34e2e..7c10d28d2784 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -94,8 +94,6 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* read initial relay state */
 	s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8);
 
-	dev_info(dev->class_dev, "%s (base %#lx) attached\n", dev->board_name,
-		 dev->iobase);
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index ae4048a624fa..8be36b8afbdf 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -1237,20 +1237,6 @@ static struct pci_dev *pci224_find_pci_dev(struct comedi_device *dev,
 	return NULL;
 }
 
-static void pci224_report_attach(struct comedi_device *dev, unsigned int irq)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	char tmpbuf[30];
-
-	if (irq)
-		snprintf(tmpbuf, sizeof(tmpbuf), "irq %u%s", irq,
-			 (dev->irq ? "" : " UNAVAILABLE"));
-	else
-		snprintf(tmpbuf, sizeof(tmpbuf), "no irq");
-	dev_info(dev->class_dev, "%s (pci %s) (%s) attached\n",
-		 dev->board_name, pci_name(pcidev), tmpbuf);
-}
-
 /*
  * Common part of attach and auto_attach.
  */
@@ -1399,8 +1385,7 @@ static int pci224_attach_common(struct comedi_device *dev,
 		}
 	}
 
-	pci224_report_attach(dev, irq);
-	return 1;
+	return 0;
 }
 
 static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index c08dfbbe4062..99e60835dc4a 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -799,19 +799,29 @@ static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
 	/* Counter ct, 8254 mode 1, initial count not written. */
 }
 
-/*
- *  COMEDI_SUBD_AI instruction;
- */
+static int pci230_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + PCI230_ADCCON);
+	if ((status & PCI230_ADC_FIFO_EMPTY) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int pci230_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
 	struct pci230_private *devpriv = dev->private;
-	unsigned int n, i;
+	unsigned int n;
 	unsigned int chan, range, aref;
 	unsigned int gainshift;
-	unsigned int status;
 	unsigned short adccon, adcen;
+	int ret;
 
 	/* Unpack channel and range. */
 	chan = CR_CHAN(insn->chanspec);
@@ -883,18 +893,10 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
 			       I8254_MODE1);
 
-#define TIMEOUT 100
 		/* wait for conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			status = inw(dev->iobase + PCI230_ADCCON);
-			if (!(status & PCI230_ADC_FIFO_EMPTY))
-				break;
-			udelay(1);
-		}
-		if (i == TIMEOUT) {
-			dev_err(dev->class_dev, "timeout\n");
-			return -ETIMEDOUT;
-		}
+		ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		data[n] = pci230_ai_read(dev);
@@ -2762,14 +2764,14 @@ static int pci230_attach_common(struct comedi_device *dev,
 	/* digital i/o subdevice */
 	if (thisboard->have_dio) {
 		rc = subdev_8255_init(dev, s, NULL,
-				      (devpriv->iobase1 + PCI230_PPI_X_BASE));
-		if (rc < 0)
+				      devpriv->iobase1 + PCI230_PPI_X_BASE);
+		if (rc)
 			return rc;
 	} else {
 		s->type = COMEDI_SUBD_UNUSED;
 	}
-	dev_info(dev->class_dev, "attached\n");
-	return 1;
+
+	return 0;
 }
 
 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index be28e6cbea20..93ed03ee416a 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -84,8 +84,6 @@ static int pci263_auto_attach(struct comedi_device *dev,
 	/* read initial relay state */
 	s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8);
 
-	dev_info(dev->class_dev, "%s (pci %s) attached\n", dev->board_name,
-		 pci_name(pci_dev));
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 64d5f291553f..645fcb0cf17d 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -95,10 +95,17 @@ static const struct comedi_lrange das16cs_ai_range = {
 	}
 };
 
-static irqreturn_t das16cs_interrupt(int irq, void *d)
+static int das16cs_ai_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
 {
-	/* struct comedi_device *dev = d; */
-	return IRQ_HANDLED;
+	unsigned int status;
+
+	status = inw(dev->iobase + DAS16CS_MISC1);
+	if (status & 0x0080)
+		return 0;
+	return -EBUSY;
 }
 
 static int das16cs_ai_rinsn(struct comedi_device *dev,
@@ -109,8 +116,8 @@ static int das16cs_ai_rinsn(struct comedi_device *dev,
 	int chan = CR_CHAN(insn->chanspec);
 	int range = CR_RANGE(insn->chanspec);
 	int aref = CR_AREF(insn->chanspec);
+	int ret;
 	int i;
-	int to;
 
 	outw(chan, dev->iobase + DAS16CS_DIO_MUX);
 
@@ -138,132 +145,16 @@ static int das16cs_ai_rinsn(struct comedi_device *dev,
 	for (i = 0; i < insn->n; i++) {
 		outw(0, dev->iobase + DAS16CS_ADC_DATA);
 
-#define TIMEOUT 1000
-		for (to = 0; to < TIMEOUT; to++) {
-			if (inw(dev->iobase + DAS16CS_MISC1) & 0x0080)
-				break;
-		}
-		if (to == TIMEOUT) {
-			dev_dbg(dev->class_dev, "cb_das16_cs: ai timeout\n");
-			return -ETIME;
-		}
+		ret = comedi_timeout(dev, s, insn, das16cs_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		data[i] = inw(dev->iobase + DAS16CS_ADC_DATA);
 	}
 
 	return i;
 }
 
-static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	return -EINVAL;
-}
-
-static int das16cs_ai_cmdtest(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_cmd *cmd)
-{
-	int err = 0;
-	int tmp;
-
-	/* Step 1 : check if triggers are trivially valid */
-
-	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-					TRIG_TIMER | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->convert_src,
-					TRIG_TIMER | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
-
-	if (err)
-		return 1;
-
-	/* Step 2a : make sure trigger sources are unique */
-
-	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-	err |= cfc_check_trigger_is_unique(cmd->convert_src);
-	err |= cfc_check_trigger_is_unique(cmd->stop_src);
-
-	/* Step 2b : and mutually compatible */
-
-	if (err)
-		return 2;
-
-	/* Step 3: check if arguments are trivially valid */
-
-	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-
-#define MAX_SPEED	10000	/* in nanoseconds */
-#define MIN_SPEED	1000000000	/* in nanoseconds */
-
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-						 MAX_SPEED);
-		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-						 MIN_SPEED);
-	} else {
-		/* external trigger */
-		/* should be level/edge, hi/lo specification here */
-		/* should specify multiple external triggers */
-		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-						 MAX_SPEED);
-		err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
-						 MIN_SPEED);
-	} else {
-		/* external trigger */
-		/* see above */
-		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
-	}
-
-	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-
-	if (cmd->stop_src == TRIG_COUNT)
-		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
-	else	/* TRIG_NONE */
-		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
-
-	if (err)
-		return 3;
-
-	/* step 4: fix up any arguments */
-
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		unsigned int div1 = 0, div2 = 0;
-
-		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-					  &div1, &div2,
-					  &cmd->scan_begin_arg, cmd->flags);
-		if (tmp != cmd->scan_begin_arg)
-			err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		unsigned int div1 = 0, div2 = 0;
-
-		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-					  &div1, &div2,
-					  &cmd->scan_begin_arg, cmd->flags);
-		if (tmp != cmd->convert_arg)
-			err++;
-		if (cmd->scan_begin_src == TRIG_TIMER &&
-		    cmd->scan_begin_arg <
-		    cmd->convert_arg * cmd->scan_end_arg) {
-			cmd->scan_begin_arg =
-			    cmd->convert_arg * cmd->scan_end_arg;
-			err++;
-		}
-	}
-
-	if (err)
-		return 4;
-
-	return 0;
-}
-
 static int das16cs_ao_winsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
@@ -401,10 +292,6 @@ static int das16cs_auto_attach(struct comedi_device *dev,
 	dev->iobase = link->resource[0]->start;
 
 	link->priv = dev;
-	ret = pcmcia_request_irq(link, das16cs_interrupt);
-	if (ret)
-		return ret;
-	dev->irq = link->irq;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
@@ -415,7 +302,6 @@ static int das16cs_auto_attach(struct comedi_device *dev,
 		return ret;
 
 	s = &dev->subdevices[0];
-	dev->read_subdev = s;
 	/* analog input subdevice */
 	s->type		= COMEDI_SUBD_AI;
 	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
@@ -424,8 +310,6 @@ static int das16cs_auto_attach(struct comedi_device *dev,
 	s->range_table	= &das16cs_ai_range;
 	s->len_chanlist	= 16;
 	s->insn_read	= das16cs_ai_rinsn;
-	s->do_cmd	= das16cs_ai_cmd;
-	s->do_cmdtest	= das16cs_ai_cmdtest;
 
 	s = &dev->subdevices[1];
 	/* analog output subdevice */
@@ -451,10 +335,6 @@ static int das16cs_auto_attach(struct comedi_device *dev,
 	s->insn_bits	= das16cs_dio_insn_bits;
 	s->insn_config	= das16cs_dio_insn_config;
 
-	dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx, irq=%u\n",
-		dev->driver->driver_name, dev->board_name,
-		dev->iobase, dev->irq);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 9819be092f8d..5452b718f93f 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -376,6 +376,20 @@ static inline unsigned int cal_enable_bits(struct comedi_device *dev)
 	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
 }
 
+static int cb_pcidas_ai_eoc(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn,
+			    unsigned long context)
+{
+	struct cb_pcidas_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = inw(devpriv->control_status + ADCMUX_CONT);
+	if (status & EOC)
+		return 0;
+	return -EBUSY;
+}
+
 static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
@@ -385,7 +399,8 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
 	unsigned int range = CR_RANGE(insn->chanspec);
 	unsigned int aref = CR_AREF(insn->chanspec);
 	unsigned int bits;
-	int n, i;
+	int ret;
+	int n;
 
 	/* enable calibration input if appropriate */
 	if (insn->chanspec & CR_ALT_SOURCE) {
@@ -415,13 +430,9 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
 		outw(0, devpriv->adc_fifo + ADCDATA);
 
 		/* wait for conversion to end */
-		/* return -ETIMEDOUT if there is a timeout */
-		for (i = 0; i < 10000; i++) {
-			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
-				break;
-		}
-		if (i == 10000)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		data[n] = inw(devpriv->adc_fifo + ADCDATA);
@@ -1006,9 +1017,9 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 
 	/*  set start trigger and burst mode */
 	bits = 0;
-	if (cmd->start_src == TRIG_NOW)
+	if (cmd->start_src == TRIG_NOW) {
 		bits |= SW_TRIGGER;
-	else if (cmd->start_src == TRIG_EXT) {
+	} else {	/* TRIG_EXT */
 		bits |= EXT_TRIGGER | TGEN | XTRCL;
 		if (thisboard->is_1602) {
 			if (cmd->start_arg & CR_INVERT)
@@ -1016,9 +1027,6 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 			if (cmd->start_arg & CR_EDGE)
 				bits |= TGSEL;
 		}
-	} else {
-		comedi_error(dev, "bug!");
-		return -1;
 	}
 	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
 		bits |= BURSTE;
@@ -1576,9 +1584,6 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
 	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
 	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 4fff1738e3f8..f9afcbe1da54 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1664,15 +1664,36 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
 	i2c_stop(dev);
 }
 
+static int cb_pcidas64_ai_eoc(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned long context)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readw(devpriv->main_iobase + HW_STATUS_REG);
+	if (thisboard->layout == LAYOUT_4020) {
+		status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG);
+		if (status)
+			return 0;
+	} else {
+		if (pipe_full_bits(status))
+			return 0;
+	}
+	return -EBUSY;
+}
+
 static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
 	const struct pcidas64_board *thisboard = comedi_board(dev);
 	struct pcidas64_private *devpriv = dev->private;
-	unsigned int bits = 0, n, i;
+	unsigned int bits = 0, n;
 	unsigned int channel, range, aref;
 	unsigned long flags;
-	static const int timeout = 100;
+	int ret;
 
 	channel = CR_CHAN(insn->chanspec);
 	range = CR_RANGE(insn->chanspec);
@@ -1770,23 +1791,10 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		       devpriv->main_iobase + ADC_CONVERT_REG);
 
 		/*  wait for data */
-		for (i = 0; i < timeout; i++) {
-			bits = readw(devpriv->main_iobase + HW_STATUS_REG);
-			if (thisboard->layout == LAYOUT_4020) {
-				if (readw(devpriv->main_iobase +
-					  ADC_WRITE_PNTR_REG))
-					break;
-			} else {
-				if (pipe_full_bits(bits))
-					break;
-			}
-			udelay(1);
-		}
-		if (i == timeout) {
-			comedi_error(dev, " analog input read insn timed out");
-			dev_info(dev->class_dev, "status 0x%x\n", bits);
-			return -ETIME;
-		}
+		ret = comedi_timeout(dev, s, insn, cb_pcidas64_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		if (thisboard->layout == LAYOUT_4020)
 			data[n] = readl(devpriv->dio_counter_iobase +
 					ADC_FIFO_REG) & 0xffff;
@@ -3816,16 +3824,19 @@ static int setup_subdevices(struct comedi_device *dev)
 	if (thisboard->has_8255) {
 		if (thisboard->layout == LAYOUT_4020) {
 			dio_8255_iobase = devpriv->main_iobase + I8255_4020_REG;
-			subdev_8255_init(dev, s, dio_callback_4020,
-					 (unsigned long)dio_8255_iobase);
+			ret = subdev_8255_init(dev, s, dio_callback_4020,
+					       (unsigned long)dio_8255_iobase);
 		} else {
 			dio_8255_iobase =
 				devpriv->dio_counter_iobase + DIO_8255_OFFSET;
-			subdev_8255_init(dev, s, dio_callback,
-					 (unsigned long)dio_8255_iobase);
+			ret = subdev_8255_init(dev, s, dio_callback,
+					       (unsigned long)dio_8255_iobase);
 		}
-	} else
+		if (ret)
+			return ret;
+	} else {
 		s->type = COMEDI_SUBD_UNUSED;
+	}
 
 	/*  8 channel dio for 60xx */
 	s = &dev->subdevices[5];
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 8cca0518cfda..901dc5d1bb72 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -388,8 +388,6 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
 	for (i = 0; i < thisboard->ao_chans; i++)
 		cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]);
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 57295d189ff6..d3141c865fe7 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -85,21 +85,31 @@ struct cb_pcimdas_private {
 	unsigned int ao_readback[2];
 };
 
-/*
- * "instructions" read/write data in "one-shot" or "software-triggered"
- * mode.
- */
+static int cb_pcimdas_ai_eoc(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned long context)
+{
+	struct cb_pcimdas_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = inb(devpriv->BADR3 + 2);
+	if ((status & 0x80) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
 	struct cb_pcimdas_private *devpriv = dev->private;
-	int n, i;
+	int n;
 	unsigned int d;
-	unsigned int busy;
 	int chan = CR_CHAN(insn->chanspec);
 	unsigned short chanlims;
 	int maxchans;
+	int ret;
 
 	/*  only support sw initiated reads from a single channel */
 
@@ -133,17 +143,10 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 		/* trigger conversion */
 		outw(0, dev->iobase + 0);
 
-#define TIMEOUT 1000		/* typically takes 5 loops on a lightly loaded Pentium 100MHz, */
-		/* this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit. */
-
 		/* wait for conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			busy = inb(devpriv->BADR3 + 2) & 0x80;
-			if (!busy)
-				break;
-		}
-		if (i == TIMEOUT)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, cb_pcimdas_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		data[n] = inw(dev->iobase + 0);
@@ -247,9 +250,9 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
 
 	s = &dev->subdevices[2];
 	/* digital i/o subdevice */
-	subdev_8255_init(dev, s, NULL, iobase_8255);
-
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+	ret = subdev_8255_init(dev, s, NULL, iobase_8255);
+	if (ret)
+		return ret;
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 43a86630a66e..4a2b200de01b 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -187,9 +187,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
-	return 1;
+	return 0;
 }
 
 static struct comedi_driver cb_pcimdda_driver = {
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 51a59e5b8ec5..8450c99af8b0 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -211,7 +211,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
 			return -EINVAL;
 		}
 
-		snprintf(file, sizeof(file), "/dev/comedi%u", minor);
+		snprintf(file, sizeof(file), "/dev/comedi%d", minor);
 		file[sizeof(file) - 1] = 0;
 
 		d = comedi_open(file);
@@ -254,6 +254,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
 			if (!devs) {
 				dev_err(dev->class_dev,
 					"Could not allocate memory. Out of memory?\n");
+				kfree(bdev);
 				return -ENOMEM;
 			}
 			devpriv->devs = devs;
@@ -263,7 +264,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
 				char buf[20];
 				int left =
 				    MAX_BOARD_NAME - strlen(devpriv->name) - 1;
-				snprintf(buf, sizeof(buf), "%d:%d ",
+				snprintf(buf, sizeof(buf), "%u:%u ",
 					 bdev->minor, bdev->subdev);
 				buf[sizeof(buf) - 1] = 0;
 				strncat(devpriv->name, buf, left);
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index d539eaf53b63..3f596669d07a 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -318,12 +318,8 @@ static int waveform_ai_cmd(struct comedi_device *dev,
 
 	if (cmd->convert_src == TRIG_NOW)
 		devpriv->convert_period = 0;
-	else if (cmd->convert_src == TRIG_TIMER)
+	else	/* TRIG_TIMER */
 		devpriv->convert_period = cmd->convert_arg / nano_per_micro;
-	else {
-		comedi_error(dev, "bug setting conversion period");
-		return -1;
-	}
 
 	do_gettimeofday(&devpriv->last);
 	devpriv->usec_current = devpriv->last.tv_usec % devpriv->usec_period;
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 323a7f39cd97..0a9c32e9db4a 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -92,8 +92,6 @@ static int contec_auto_attach(struct comedi_device *dev,
 	s->range_table	= &range_digital;
 	s->insn_bits	= contec_do_insn_bits;
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index ce153fcb8b2a..a8f6036ad82b 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -333,14 +333,28 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain)
 	writeAcqScanListEntry(dev, word3);
 }
 
+static int daqboard2000_ai_status(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned long context)
+{
+	struct daqboard2000_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readw(devpriv->daq + acqControl);
+	if (status & context)
+		return 0;
+	return -EBUSY;
+}
+
 static int daqboard2000_ai_insn_read(struct comedi_device *dev,
 				     struct comedi_subdevice *s,
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
 	struct daqboard2000_private *devpriv = dev->private;
-	unsigned int val;
-	int gain, chan, timeout;
+	int gain, chan;
+	int ret;
 	int i;
 
 	writew(DAQBOARD2000_AcqResetScanListFifo |
@@ -367,25 +381,24 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev,
 		/* Enable reading from the scanlist FIFO */
 		writew(DAQBOARD2000_SeqStartScanList,
 		       devpriv->daq + acqControl);
-		for (timeout = 0; timeout < 20; timeout++) {
-			val = readw(devpriv->daq + acqControl);
-			if (val & DAQBOARD2000_AcqConfigPipeFull)
-				break;
-			/* udelay(2); */
-		}
+
+		ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status,
+				     DAQBOARD2000_AcqConfigPipeFull);
+		if (ret)
+			return ret;
+
 		writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl);
-		for (timeout = 0; timeout < 20; timeout++) {
-			val = readw(devpriv->daq + acqControl);
-			if (val & DAQBOARD2000_AcqLogicScanning)
-				break;
-			/* udelay(2); */
-		}
-		for (timeout = 0; timeout < 20; timeout++) {
-			val = readw(devpriv->daq + acqControl);
-			if (val & DAQBOARD2000_AcqResultsFIFOHasValidData)
-				break;
-			/* udelay(2); */
-		}
+
+		ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status,
+				     DAQBOARD2000_AcqLogicScanning);
+		if (ret)
+			return ret;
+
+		ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status,
+				     DAQBOARD2000_AcqResultsFIFOHasValidData);
+		if (ret)
+			return ret;
+
 		data[i] = readw(devpriv->daq + acqResultsFIFO);
 		writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl);
 		writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl);
@@ -409,6 +422,21 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev,
 	return i;
 }
 
+static int daqboard2000_ao_eoc(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned long context)
+{
+	struct daqboard2000_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int status;
+
+	status = readw(devpriv->daq + dacControl);
+	if ((status & ((chan + 1) * 0x0010)) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int daqboard2000_ao_insn_write(struct comedi_device *dev,
 				      struct comedi_subdevice *s,
 				      struct comedi_insn *insn,
@@ -416,8 +444,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
 {
 	struct daqboard2000_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
-	unsigned int val;
-	int timeout;
+	int ret;
 	int i;
 
 	for (i = 0; i < insn->n; i++) {
@@ -431,12 +458,11 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
 		udelay(1000);
 #endif
 		writew(data[i], devpriv->daq + dacSetting(chan));
-		for (timeout = 0; timeout < 20; timeout++) {
-			val = readw(devpriv->daq + dacControl);
-			if ((val & ((chan + 1) * 0x0010)) == 0)
-				break;
-			/* udelay(2); */
-		}
+
+		ret = comedi_timeout(dev, s, insn, daqboard2000_ao_eoc, 0);
+		if (ret)
+			return ret;
+
 		devpriv->ao_readback[chan] = data[i];
 #if 0
 		/*
@@ -737,9 +763,6 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
 	if (result)
 		return result;
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index e5c0ee9a09c2..c5e352fb5555 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -201,17 +201,29 @@ static const int *const das08_gainlists[] = {
 	das08_pgm_gainlist,
 };
 
-#define TIMEOUT 100000
+static int das08_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + DAS08_STATUS);
+	if ((status & DAS08_EOC) == 0)
+		return 0;
+	return -EBUSY;
+}
 
 static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
 	const struct das08_board_struct *thisboard = comedi_board(dev);
 	struct das08_private_struct *devpriv = dev->private;
-	int i, n;
+	int n;
 	int chan;
 	int range;
 	int lsb, msb;
+	int ret;
 
 	chan = CR_CHAN(insn->chanspec);
 	range = CR_RANGE(insn->chanspec);
@@ -244,14 +256,10 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		/* trigger conversion */
 		outb_p(0, dev->iobase + DAS08_TRIG_12BIT);
 
-		for (i = 0; i < TIMEOUT; i++) {
-			if (!(inb(dev->iobase + DAS08_STATUS) & DAS08_EOC))
-				break;
-		}
-		if (i == TIMEOUT) {
-			dev_err(dev->class_dev, "timeout\n");
-			return -ETIME;
-		}
+		ret = comedi_timeout(dev, s, insn, das08_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		msb = inb(dev->iobase + DAS08_MSB);
 		lsb = inb(dev->iobase + DAS08_LSB);
 		if (thisboard->ai_encoding == das08_encode12) {
@@ -529,9 +537,10 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
 	s = &dev->subdevices[4];
 	/* 8255 */
 	if (thisboard->i8255_offset != 0) {
-		subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase +
-							       thisboard->
-							       i8255_offset));
+		ret = subdev_8255_init(dev, s, NULL,
+				       dev->iobase + thisboard->i8255_offset);
+		if (ret)
+			return ret;
 	} else {
 		s->type = COMEDI_SUBD_UNUSED;
 	}
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index a8446ca04110..6a7d652ff564 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -856,18 +856,17 @@ static void das16_ai_munge(struct comedi_device *dev,
 	}
 }
 
-static int das16_ai_wait_for_conv(struct comedi_device *dev,
-				  unsigned int timeout)
+static int das16_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
 {
 	unsigned int status;
-	int i;
 
-	for (i = 0; i < timeout; i++) {
-		status = inb(dev->iobase + DAS16_STATUS_REG);
-		if (!(status & DAS16_STATUS_BUSY))
-			return 0;
-	}
-	return -ETIME;
+	status = inb(dev->iobase + DAS16_STATUS_REG);
+	if ((status & DAS16_STATUS_BUSY) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static int das16_ai_insn_read(struct comedi_device *dev,
@@ -897,7 +896,7 @@ static int das16_ai_insn_read(struct comedi_device *dev,
 		/* trigger conversion */
 		outb_p(0, dev->iobase + DAS16_TRIG_REG);
 
-		ret = das16_ai_wait_for_conv(dev, 1000);
+		ret = comedi_timeout(dev, s, insn, das16_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index fee5facff8dd..0a90ab341758 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -331,14 +331,27 @@ static int das16m1_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
+static int das16m1_ai_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + DAS16M1_CS);
+	if (status & IRQDATA)
+		return 0;
+	return -EBUSY;
+}
+
 static int das16m1_ai_rinsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
 	struct das16m1_private_struct *devpriv = dev->private;
-	int i, n;
+	int ret;
+	int n;
 	int byte;
-	const int timeout = 1000;
 
 	/* disable interrupts and internal pacer */
 	devpriv->control_state &= ~INTE & ~PACER_MASK;
@@ -356,14 +369,10 @@ static int das16m1_ai_rinsn(struct comedi_device *dev,
 		/* trigger conversion */
 		outb(0, dev->iobase);
 
-		for (i = 0; i < timeout; i++) {
-			if (inb(dev->iobase + DAS16M1_CS) & IRQDATA)
-				break;
-		}
-		if (i == timeout) {
-			comedi_error(dev, "timeout");
-			return -ETIME;
-		}
+		ret = comedi_timeout(dev, s, insn, das16m1_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		data[n] = munge_sample(inw(dev->iobase));
 	}
 
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 5af0a5764a8c..8c15929811b6 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -420,17 +420,12 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
 	gain &= 0xf;
 	outb(gain, dev->iobase + DAS800_GAIN);
 
-	switch (async->cmd.stop_src) {
-	case TRIG_COUNT:
+	if (async->cmd.stop_src == TRIG_COUNT) {
 		devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len;
 		devpriv->forever = false;
-		break;
-	case TRIG_NONE:
+	} else {	/* TRIG_NONE */
 		devpriv->forever = true;
 		devpriv->count = 0;
-		break;
-	default:
-		break;
 	}
 
 	/* enable auto channel scan, send interrupts on end of conversion
@@ -440,19 +435,13 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
 	conv_bits |= EACS | IEOC;
 	if (async->cmd.start_src == TRIG_EXT)
 		conv_bits |= DTEN;
-	switch (async->cmd.convert_src) {
-	case TRIG_TIMER:
+	if (async->cmd.convert_src == TRIG_TIMER) {
 		conv_bits |= CASC | ITE;
 		/* set conversion frequency */
 		if (das800_set_frequency(dev) < 0) {
 			comedi_error(dev, "Error setting up counters");
 			return -1;
 		}
-		break;
-	case TRIG_EXT:
-		break;
-	default:
-		break;
 	}
 
 	spin_lock_irqsave(&dev->spinlock, irq_flags);
@@ -556,15 +545,17 @@ static irqreturn_t das800_interrupt(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-static int das800_wait_for_conv(struct comedi_device *dev, int timeout)
+static int das800_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
 {
-	int i;
+	unsigned int status;
 
-	for (i = 0; i < timeout; i++) {
-		if (!(inb(dev->iobase + DAS800_STATUS) & BUSY))
-			return 0;
-	}
-	return -ETIME;
+	status = inb(dev->iobase + DAS800_STATUS);
+	if ((status & BUSY) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static int das800_ai_insn_read(struct comedi_device *dev,
@@ -599,7 +590,7 @@ static int das800_ai_insn_read(struct comedi_device *dev,
 		/* trigger conversion */
 		outb_p(0, dev->iobase + DAS800_MSB);
 
-		ret = das800_wait_for_conv(dev, 1000);
+		ret = comedi_timeout(dev, s, insn, das800_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 78a19629ff56..c8a36eb5f015 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -164,16 +164,29 @@ struct dmm32at_private {
 
 };
 
+static int dmm32at_ai_status(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned long context)
+{
+	unsigned char status;
+
+	status = inb(dev->iobase + context);
+	if ((status & DMM32AT_STATUS) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int dmm32at_ai_rinsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
-	int n, i;
+	int n;
 	unsigned int d;
-	unsigned char status;
 	unsigned short msb, lsb;
 	unsigned char chan;
 	int range;
+	int ret;
 
 	/* get the channel and range number */
 
@@ -190,26 +203,20 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev,
 	outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF);
 
 	/* wait for circuit to settle */
-	for (i = 0; i < 40000; i++) {
-		status = inb(dev->iobase + DMM32AT_AIRBACK);
-		if ((status & DMM32AT_STATUS) == 0)
-			break;
-	}
-	if (i == 40000)
-		return -ETIMEDOUT;
+	ret = comedi_timeout(dev, s, insn, dmm32at_ai_status, DMM32AT_AIRBACK);
+	if (ret)
+		return ret;
 
 	/* convert n samples */
 	for (n = 0; n < insn->n; n++) {
 		/* trigger conversion */
 		outb(0xff, dev->iobase + DMM32AT_CONV);
+
 		/* wait for conversion to end */
-		for (i = 0; i < 40000; i++) {
-			status = inb(dev->iobase + DMM32AT_AISTAT);
-			if ((status & DMM32AT_STATUS) == 0)
-				break;
-		}
-		if (i == 40000)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, dmm32at_ai_status,
+				     DMM32AT_AISTAT);
+		if (ret)
+			return ret;
 
 		/* read data */
 		lsb = inb(dev->iobase + DMM32AT_AILSB);
@@ -403,8 +410,9 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct dmm32at_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
-	int i, range;
-	unsigned char chanlo, chanhi, status;
+	int range;
+	unsigned char chanlo, chanhi;
+	int ret;
 
 	if (!cmd->chanlist)
 		return -EINVAL;
@@ -439,14 +447,13 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 						      * isr */
 	}
 
-	/* wait for circuit to settle */
-	for (i = 0; i < 40000; i++) {
-		status = inb(dev->iobase + DMM32AT_AIRBACK);
-		if ((status & DMM32AT_STATUS) == 0)
-			break;
-	}
-	if (i == 40000)
-		return -ETIMEDOUT;
+	/*
+	 * wait for circuit to settle
+	 * we don't have the 'insn' here but it's not needed
+	 */
+	ret = comedi_timeout(dev, s, NULL, dmm32at_ai_status, DMM32AT_AIRBACK);
+	if (ret)
+		return ret;
 
 	if (devpriv->ai_scans_left > 1) {
 		/* start the clock and enable the interrupts */
@@ -525,6 +532,19 @@ static irqreturn_t dmm32at_isr(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
+static int dmm32at_ao_eoc(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned long context)
+{
+	unsigned char status;
+
+	status = inb(dev->iobase + DMM32AT_DACSTAT);
+	if ((status & DMM32AT_DACBUSY) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int dmm32at_ao_winsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
@@ -533,6 +553,7 @@ static int dmm32at_ao_winsn(struct comedi_device *dev,
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 	unsigned char hi, lo, status;
+	int ret;
 
 	/* Writing a list of values to an AO channel is probably not
 	 * very useful, but that's how the interface is defined. */
@@ -549,13 +570,9 @@ static int dmm32at_ao_winsn(struct comedi_device *dev,
 		outb(hi, dev->iobase + DMM32AT_DACMSB);
 
 		/* wait for circuit to settle */
-		for (i = 0; i < 40000; i++) {
-			status = inb(dev->iobase + DMM32AT_DACSTAT);
-			if ((status & DMM32AT_DACBUSY) == 0)
-				break;
-		}
-		if (i == 40000)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, dmm32at_ao_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* dummy read to update trigger the output */
 		status = inb(dev->iobase + DMM32AT_DACMSB);
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 4271903facd7..ba7c2ba618e6 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -224,23 +224,32 @@ static const struct comedi_lrange *dac_range_types[] = {
 	&range_unipolar5
 };
 
-#define DT2811_TIMEOUT 5
+static int dt2811_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + DT2811_ADCSR);
+	if ((status & DT2811_ADBUSY) == 0)
+		return 0;
+	return -EBUSY;
+}
 
 static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
 	int chan = CR_CHAN(insn->chanspec);
-	int timeout = DT2811_TIMEOUT;
+	int ret;
 	int i;
 
 	for (i = 0; i < insn->n; i++) {
 		outb(chan, dev->iobase + DT2811_ADGCR);
 
-		while (timeout
-		       && inb(dev->iobase + DT2811_ADCSR) & DT2811_ADBUSY)
-			timeout--;
-		if (!timeout)
-			return -ETIME;
+		ret = comedi_timeout(dev, s, insn, dt2811_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		data[i] = inb(dev->iobase + DT2811_ADDATLO);
 		data[i] |= inb(dev->iobase + DT2811_ADDATHI) << 8;
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index abad6e49c1c1..3794b7e52091 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -66,26 +66,35 @@ struct dt2814_private {
 #define DT2814_TIMEOUT 10
 #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
 
+static int dt2814_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + DT2814_CSR);
+	if (status & DT2814_FINISH)
+		return 0;
+	return -EBUSY;
+}
+
 static int dt2814_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
-	int n, i, hi, lo;
+	int n, hi, lo;
 	int chan;
-	int status = 0;
+	int ret;
 
 	for (n = 0; n < insn->n; n++) {
 		chan = CR_CHAN(insn->chanspec);
 
 		outb(chan, dev->iobase + DT2814_CSR);
-		for (i = 0; i < DT2814_TIMEOUT; i++) {
-			status = inb(dev->iobase + DT2814_CSR);
-			udelay(10);
-			if (status & DT2814_FINISH)
-				break;
-		}
-		if (i >= DT2814_TIMEOUT)
-			return -ETIMEDOUT;
+
+		ret = comedi_timeout(dev, s, insn, dt2814_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		hi = inb(dev->iobase + DT2814_DATA);
 		lo = inb(dev->iobase + DT2814_DATA);
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index ee24717821e1..b9ac4ed8babb 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -67,15 +67,17 @@ struct dt2815_private {
 	unsigned int ao_readback[8];
 };
 
-static int dt2815_wait_for_status(struct comedi_device *dev, int status)
+static int dt2815_ao_status(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn,
+			    unsigned long context)
 {
-	int i;
+	unsigned int status;
 
-	for (i = 0; i < 100; i++) {
-		if (inb(dev->iobase + DT2815_STATUS) == status)
-			break;
-	}
-	return status;
+	status = inb(dev->iobase + DT2815_STATUS);
+	if (status == context)
+		return 0;
+	return -EBUSY;
 }
 
 static int dt2815_ao_insn_read(struct comedi_device *dev,
@@ -98,30 +100,23 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 	struct dt2815_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
-	unsigned int status;
 	unsigned int lo, hi;
+	int ret;
 
 	for (i = 0; i < insn->n; i++) {
 		lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01;
 		hi = (data[i] & 0xff0) >> 4;
 
-		status = dt2815_wait_for_status(dev, 0x00);
-		if (status != 0) {
-			dev_dbg(dev->class_dev,
-				"failed to write low byte on %d reason %x\n",
-				chan, status);
-			return -EBUSY;
-		}
+		ret = comedi_timeout(dev, s, insn, dt2815_ao_status, 0x00);
+		if (ret)
+			return ret;
 
 		outb(lo, dev->iobase + DT2815_DATA);
 
-		status = dt2815_wait_for_status(dev, 0x10);
-		if (status != 0x10) {
-			dev_dbg(dev->class_dev,
-				"failed to write high byte on %d reason %x\n",
-				chan, status);
-			return -EBUSY;
-		}
+		ret = comedi_timeout(dev, s, insn, dt2815_ao_status, 0x10);
+		if (ret)
+			return ret;
+
 		devpriv->ao_readback[chan] = data[i];
 	}
 	return i;
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 895f73a19023..6cc8f1d5b831 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -63,7 +63,6 @@ Notes:
 
 #include "comedi_fc.h"
 
-#define DT2821_TIMEOUT		100	/* 500 us */
 #define DT2821_SIZE 0x10
 
 /*
@@ -248,27 +247,6 @@ struct dt282x_private {
  *    Some useless abstractions
  */
 #define chan_to_DAC(a)	((a)&1)
-#define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY)
-#define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE)
-
-/*
- *    danger! macro abuse... a is the expression to wait on, and b is
- *      the statement(s) to execute if it doesn't happen.
- */
-#define wait_for(a, b)						\
-	do {							\
-		int _i;						\
-		for (_i = 0; _i < DT2821_TIMEOUT; _i++) {	\
-			if (a) {				\
-				_i = 0;				\
-				break;				\
-			}					\
-			udelay(5);				\
-		}						\
-		if (_i) {					\
-			b					\
-		}						\
-	} while (0)
 
 static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
 static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
@@ -530,6 +508,29 @@ static void dt282x_load_changain(struct comedi_device *dev, int n,
 	outw(n - 1, dev->iobase + DT2821_CHANCSR);
 }
 
+static int dt282x_ai_timeout(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + DT2821_ADCSR);
+	switch (context) {
+	case DT2821_MUXBUSY:
+		if ((status & DT2821_MUXBUSY) == 0)
+			return 0;
+		break;
+	case DT2821_ADDONE:
+		if (status & DT2821_ADDONE)
+			return 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return -EBUSY;
+}
+
 /*
  *    Performs a single A/D conversion.
  *      - Put channel/gain into channel-gain list
@@ -542,6 +543,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
 {
 	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
+	int ret;
 	int i;
 
 	/* XXX should we really be enabling the ad clock here? */
@@ -551,13 +553,18 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
 	dt282x_load_changain(dev, 1, &insn->chanspec);
 
 	outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
-	wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;);
+	ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, DT2821_MUXBUSY);
+	if (ret)
+		return ret;
 
 	for (i = 0; i < insn->n; i++) {
 		outw(devpriv->supcsr | DT2821_STRIG,
 			dev->iobase + DT2821_SUPCSR);
-		wait_for(ad_done(), comedi_error(dev, "timeout\n");
-			 return -ETIME;);
+
+		ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout,
+				     DT2821_ADDONE);
+		if (ret)
+			return ret;
 
 		data[i] =
 		    inw(dev->iobase +
@@ -646,6 +653,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	struct dt282x_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
+	int ret;
 
 	if (devpriv->usedma == 0) {
 		comedi_error(dev,
@@ -691,7 +699,9 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
 
 	outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
-	wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;);
+	ret = comedi_timeout(dev, s, NULL, dt282x_ai_timeout, DT2821_MUXBUSY);
+	if (ret)
+		return ret;
 
 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
 		outw(devpriv->supcsr | DT2821_STRIG,
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index f52a4476cb73..f54685ed463c 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -767,8 +767,6 @@ static int dt3000_auto_attach(struct comedi_device *dev,
 	s->type = COMEDI_SUBD_PROC;
 #endif
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index f224825830ba..e5593f8c7406 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -57,18 +57,27 @@ struct dyna_pci10xx_private {
 	unsigned long BADR3;
 };
 
-/******************************************************************************/
-/************************** READ WRITE FUNCTIONS ******************************/
-/******************************************************************************/
+static int dyna_pci10xx_ai_eoc(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned long context)
+{
+	unsigned int status;
+
+	status = inw_p(dev->iobase);
+	if (status & (1 << 15))
+		return 0;
+	return -EBUSY;
+}
 
-/* analog input callback */
 static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
 			struct comedi_subdevice *s,
 			struct comedi_insn *insn, unsigned int *data)
 {
 	struct dyna_pci10xx_private *devpriv = dev->private;
-	int n, counter;
+	int n;
 	u16 d = 0;
+	int ret = 0;
 	unsigned int chan, range;
 
 	/* get the channel number and range */
@@ -82,18 +91,13 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
 		smp_mb();
 		outw_p(0x0000 + range + chan, dev->iobase + 2);
 		udelay(10);
+
+		ret = comedi_timeout(dev, s, insn, dyna_pci10xx_ai_eoc, 0);
+		if (ret)
+			break;
+
 		/* read data */
-		for (counter = 0; counter < READ_TIMEOUT; counter++) {
-			d = inw_p(dev->iobase);
-
-			/* check if read is successful if the EOC bit is set */
-			if (d & (1 << 15))
-				goto conv_finish;
-		}
-		data[n] = 0;
-		dev_dbg(dev->class_dev, "timeout reading analog input\n");
-		continue;
-conv_finish:
+		d = inw_p(dev->iobase);
 		/* mask the first 4 bits - EOC bits */
 		d &= 0x0FFF;
 		data[n] = d;
@@ -101,7 +105,7 @@ conv_finish:
 	mutex_unlock(&devpriv->mutex);
 
 	/* return the number of samples read/written */
-	return n;
+	return ret ? ret : n;
 }
 
 /* analog output callback */
@@ -232,8 +236,6 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
 	s->state = 0;
 	s->insn_bits = dyna_pci10xx_do_insn_bits;
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index a99ddf00ddc4..a5562ea2806f 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -159,7 +159,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* function to call when reading DA */
 	s->insn_read = fl512_ao_insn_readback;
 
-	return 1;
+	return 0;
 }
 
 static struct comedi_driver fl512_driver = {
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 80539b2bea1a..0b8b2162b76b 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -171,12 +171,27 @@ static void setup_channel_list(struct comedi_device *dev,
 	}
 }
 
+static int icp_multi_ai_eoc(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn,
+			    unsigned long context)
+{
+	struct icp_multi_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readw(devpriv->io_addr + ICP_MULTI_ADC_CSR);
+	if ((status & ADC_BSY) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int icp_multi_insn_read_ai(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
 	struct icp_multi_private *devpriv = dev->private;
-	int n, timeout;
+	int ret = 0;
+	int n;
 
 	/*  Disable A/D conversion ready interrupt */
 	devpriv->IntEnable &= ~ADC_READY;
@@ -199,33 +214,10 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 		udelay(1);
 
 		/*  Wait for conversion to complete, or get fed up waiting */
-		timeout = 100;
-		while (timeout--) {
-			if (!(readw(devpriv->io_addr +
-				    ICP_MULTI_ADC_CSR) & ADC_BSY))
-				goto conv_finish;
-
-			udelay(1);
-		}
-
-		/*  If we reach here, a timeout has occurred */
-		comedi_error(dev, "A/D insn timeout");
-
-		/*  Disable interrupt */
-		devpriv->IntEnable &= ~ADC_READY;
-		writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
-
-		/*  Clear interrupt status */
-		devpriv->IntStatus |= ADC_READY;
-		writew(devpriv->IntStatus,
-		       devpriv->io_addr + ICP_MULTI_INT_STAT);
+		ret = comedi_timeout(dev, s, insn, icp_multi_ai_eoc, 0);
+		if (ret)
+			break;
 
-		/*  Clear data received */
-		data[n] = 0;
-
-		return -ETIME;
-
-conv_finish:
 		data[n] =
 		    (readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff;
 	}
@@ -238,7 +230,21 @@ conv_finish:
 	devpriv->IntStatus |= ADC_READY;
 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
 
-	return n;
+	return ret ? ret : n;
+}
+
+static int icp_multi_ao_eoc(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn,
+			    unsigned long context)
+{
+	struct icp_multi_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readw(devpriv->io_addr + ICP_MULTI_DAC_CSR);
+	if ((status & DAC_BSY) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static int icp_multi_insn_write_ao(struct comedi_device *dev,
@@ -246,7 +252,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 				   struct comedi_insn *insn, unsigned int *data)
 {
 	struct icp_multi_private *devpriv = dev->private;
-	int n, chan, range, timeout;
+	int n, chan, range;
+	int ret;
 
 	/*  Disable D/A conversion ready interrupt */
 	devpriv->IntEnable &= ~DAC_READY;
@@ -274,33 +281,24 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 	for (n = 0; n < insn->n; n++) {
 		/*  Wait for analogue output data register to be
 		 *  ready for new data, or get fed up waiting */
-		timeout = 100;
-		while (timeout--) {
-			if (!(readw(devpriv->io_addr +
-				    ICP_MULTI_DAC_CSR) & DAC_BSY))
-				goto dac_ready;
-
-			udelay(1);
+		ret = comedi_timeout(dev, s, insn, icp_multi_ao_eoc, 0);
+		if (ret) {
+			/*  Disable interrupt */
+			devpriv->IntEnable &= ~DAC_READY;
+			writew(devpriv->IntEnable,
+			       devpriv->io_addr + ICP_MULTI_INT_EN);
+
+			/*  Clear interrupt status */
+			devpriv->IntStatus |= DAC_READY;
+			writew(devpriv->IntStatus,
+			       devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+			/*  Clear data received */
+			devpriv->ao_data[chan] = 0;
+
+			return ret;
 		}
 
-		/*  If we reach here, a timeout has occurred */
-		comedi_error(dev, "D/A insn timeout");
-
-		/*  Disable interrupt */
-		devpriv->IntEnable &= ~DAC_READY;
-		writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
-
-		/*  Clear interrupt status */
-		devpriv->IntStatus |= DAC_READY;
-		writew(devpriv->IntStatus,
-		       devpriv->io_addr + ICP_MULTI_INT_STAT);
-
-		/*  Clear data received */
-		devpriv->ao_data[chan] = 0;
-
-		return -ETIME;
-
-dac_ready:
 		/*  Write data to analogue output data register */
 		writew(data[n], devpriv->io_addr + ICP_MULTI_AO);
 
@@ -565,9 +563,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
 
 	devpriv->valid = 1;
 
-	dev_info(dev->class_dev, "%s attached, irq %sabled\n",
-		dev->board_name, dev->irq ? "en" : "dis");
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 8577778441fa..3558ab3b6e1f 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -190,20 +190,18 @@ static int ii20k_ao_insn_write(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int ii20k_ai_wait_eoc(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     int timeout)
+static int ii20k_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
 {
 	void __iomem *iobase = ii20k_module_iobase(dev, s);
 	unsigned char status;
 
-	do {
-		status = readb(iobase + II20K_AI_STATUS_REG);
-		if ((status & II20K_AI_STATUS_INT) == 0)
-			return 0;
-	} while (timeout--);
-
-	return -ETIME;
+	status = readb(iobase + II20K_AI_STATUS_REG);
+	if ((status & II20K_AI_STATUS_INT) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static void ii20k_ai_setup(struct comedi_device *dev,
@@ -263,7 +261,7 @@ static int ii20k_ai_insn_read(struct comedi_device *dev,
 		/* generate a software start convert signal */
 		readb(iobase + II20K_AI_PACER_RESET_REG);
 
-		ret = ii20k_ai_wait_eoc(dev, s, 100);
+		ret = comedi_timeout(dev, s, insn, ii20k_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 6100c12c164f..73ef31ebc05d 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -773,7 +773,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
 	devpriv->timer.expires = jiffies + msecs_to_jiffies(1000);
 	add_timer(&devpriv->timer);
 
-	return result;
+	return 0;
 }
 
 static void jr3_pci_detach(struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 6b9846fd8c48..1c32816e9130 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -119,9 +119,6 @@ static int cnt_auto_attach(struct comedi_device *dev,
 	outb(0, dev->iobase + 0x20);
 	outb(0, dev->iobase + 0x40);
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 7f6687896401..0ff126b1fdfd 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -248,6 +248,20 @@ static int me_dio_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
+static int me_ai_eoc(struct comedi_device *dev,
+		     struct comedi_subdevice *s,
+		     struct comedi_insn *insn,
+		     unsigned long context)
+{
+	struct me_private_data *dev_private = dev->private;
+	unsigned int status;
+
+	status = readw(dev_private->me_regbase + ME_STATUS);
+	if ((status & 0x0004) == 0)
+		return 0;
+	return -EBUSY;
+}
+
 static int me_ai_insn_read(struct comedi_device *dev,
 			   struct comedi_subdevice *s,
 			   struct comedi_insn *insn,
@@ -258,7 +272,7 @@ static int me_ai_insn_read(struct comedi_device *dev,
 	unsigned int rang = CR_RANGE(insn->chanspec);
 	unsigned int aref = CR_AREF(insn->chanspec);
 	unsigned short val;
-	int i;
+	int ret;
 
 	/* stop any running conversion */
 	dev_private->control_1 &= 0xFFFC;
@@ -290,19 +304,14 @@ static int me_ai_insn_read(struct comedi_device *dev,
 	readw(dev_private->me_regbase + ME_ADC_START);
 
 	/* wait for ADC fifo not empty flag */
-	for (i = 100000; i > 0; i--)
-		if (!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004))
-			break;
+	ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0);
+	if (ret)
+		return ret;
 
 	/* get value from ADC fifo */
-	if (i) {
-		val = readw(dev_private->me_regbase + ME_READ_AD_FIFO);
-		val = (val ^ 0x800) & 0x0fff;
-		data[0] = val;
-	} else {
-		dev_err(dev->class_dev, "Cannot get single value\n");
-		return -EIO;
-	}
+	val = readw(dev_private->me_regbase + ME_READ_AD_FIFO);
+	val = (val ^ 0x800) & 0x0fff;
+	data[0] = val;
 
 	/* stop any running conversion */
 	dev_private->control_1 &= 0xFFFC;
@@ -542,9 +551,6 @@ static int me_auto_attach(struct comedi_device *dev,
 	s->insn_bits	= me_dio_insn_bits;
 	s->insn_config	= me_dio_insn_config;
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c
index 81b78e053f4e..a4f7d6f138df 100644
--- a/drivers/staging/comedi/drivers/mf6x4.c
+++ b/drivers/staging/comedi/drivers/mf6x4.c
@@ -133,21 +133,18 @@ static int mf6x4_do_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int mf6x4_ai_wait_for_eoc(struct comedi_device *dev,
-				 unsigned int timeout)
+static int mf6x4_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
 {
 	struct mf6x4_private *devpriv = dev->private;
-	unsigned int eolc;
+	unsigned int status;
 
-	while (timeout--) {
-		eolc = ioread32(devpriv->gpioc_R) & MF6X4_GPIOC_EOLC;
-		if (eolc)
-			return 0;
-
-		udelay(1);
-	}
-
-	return -ETIME;
+	status = ioread32(devpriv->gpioc_R);
+	if (status & MF6X4_GPIOC_EOLC)
+		return 0;
+	return -EBUSY;
 }
 
 static int mf6x4_ai_insn_read(struct comedi_device *dev,
@@ -168,7 +165,7 @@ static int mf6x4_ai_insn_read(struct comedi_device *dev,
 		/* Trigger ADC conversion by reading ADSTART */
 		ioread16(devpriv->bar1_mem + MF6X4_ADSTART_R);
 
-		ret = mf6x4_ai_wait_for_eoc(dev, 100);
+		ret = comedi_timeout(dev, s, insn, mf6x4_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index fe4621ea65c3..f770400a0e81 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -142,8 +142,18 @@ static const struct comedi_lrange range_mpc624_bipolar10 = {
 	 }
 };
 
-/* Timeout 200ms */
-#define TIMEOUT 200
+static int mpc624_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned char status;
+
+	status = inb(dev->iobase + MPC624_ADC);
+	if ((status & MPC624_ADBUSY) == 0)
+		return 0;
+	return -EBUSY;
+}
 
 static int mpc624_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
@@ -152,7 +162,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
 	struct mpc624_private *devpriv = dev->private;
 	int n, i;
 	unsigned long int data_in, data_out;
-	unsigned char ucPort;
+	int ret;
 
 	/*
 	 *  WARNING:
@@ -170,15 +180,9 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
 		udelay(1);
 
 		/*  Wait for the conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			ucPort = inb(dev->iobase + MPC624_ADC);
-			if (ucPort & MPC624_ADBUSY)
-				udelay(1000);
-			else
-				break;
-		}
-		if (i == TIMEOUT)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, mpc624_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/*  Start reading data */
 		data_in = 0;
@@ -341,7 +345,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->len_chanlist = 1;
 	s->insn_read = mpc624_ai_rinsn;
 
-	return 1;
+	return 0;
 }
 
 static struct comedi_driver mpc624_driver = {
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 3ca755eca285..b74b9e9bfd4a 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -81,34 +81,44 @@ struct multiq3_private {
 	unsigned int ao_readback[2];
 };
 
+static int multiq3_ai_status(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + MULTIQ3_STATUS);
+	if (status & context)
+		return 0;
+	return -EBUSY;
+}
+
 static int multiq3_ai_insn_read(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
-	int i, n;
+	int n;
 	int chan;
 	unsigned int hi, lo;
+	int ret;
 
 	chan = CR_CHAN(insn->chanspec);
 	outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3),
 	     dev->iobase + MULTIQ3_CONTROL);
 
-	for (i = 0; i < MULTIQ3_TIMEOUT; i++) {
-		if (inw(dev->iobase + MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC)
-			break;
-	}
-	if (i == MULTIQ3_TIMEOUT)
-		return -ETIMEDOUT;
+	ret = comedi_timeout(dev, s, insn, multiq3_ai_status,
+			     MULTIQ3_STATUS_EOC);
+	if (ret)
+		return ret;
 
 	for (n = 0; n < insn->n; n++) {
 		outw(0, dev->iobase + MULTIQ3_AD_CS);
-		for (i = 0; i < MULTIQ3_TIMEOUT; i++) {
-			if (inw(dev->iobase +
-				MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC_I)
-				break;
-		}
-		if (i == MULTIQ3_TIMEOUT)
-			return -ETIMEDOUT;
+
+		ret = comedi_timeout(dev, s, insn, multiq3_ai_status,
+				     MULTIQ3_STATUS_EOC_I);
+		if (ret)
+			return ret;
 
 		hi = inb(dev->iobase + MULTIQ3_AD_CS);
 		lo = inb(dev->iobase + MULTIQ3_AD_CS);
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index df42e3906171..b8c3fbe25b21 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -1187,7 +1187,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
 		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
 	ni_660x_write_register(dev, 0, global_interrupt_config_bits,
 			       NI660X_GLOBAL_INT_CFG);
-	dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
+
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 8550fdc4ccd3..1002ceacfdcc 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -246,9 +246,6 @@ static int ni_670x_auto_attach(struct comedi_device *dev,
 	/* Config of ao registers */
 	writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET);
 
-	dev_info(dev->class_dev, "%s: %s attached\n",
-		dev->driver->driver_name, dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index f83eb9ebe278..740f14994f97 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -488,13 +488,25 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
+static int a2150_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + STATUS_REG);
+	if (status & FNE_BIT)
+		return 0;
+	return -EBUSY;
+}
+
 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
 	struct a2150_private *devpriv = dev->private;
-	unsigned int i, n;
-	static const int timeout = 100000;
-	static const int filter_delay = 36;
+	unsigned int n;
+	int ret;
 
 	/*  clear fifo and reset triggering circuitry */
 	outw(0, dev->iobase + FIFO_RESET_REG);
@@ -524,30 +536,20 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 	 * there is a 35.6 sample delay for data to get through the
 	 * antialias filter
 	 */
-	for (n = 0; n < filter_delay; n++) {
-		for (i = 0; i < timeout; i++) {
-			if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
-				break;
-			udelay(1);
-		}
-		if (i == timeout) {
-			comedi_error(dev, "timeout");
-			return -ETIME;
-		}
+	for (n = 0; n < 36; n++) {
+		ret = comedi_timeout(dev, s, insn, a2150_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		inw(dev->iobase + FIFO_DATA_REG);
 	}
 
 	/*  read data */
 	for (n = 0; n < insn->n; n++) {
-		for (i = 0; i < timeout; i++) {
-			if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
-				break;
-			udelay(1);
-		}
-		if (i == timeout) {
-			comedi_error(dev, "timeout");
-			return -ETIME;
-		}
+		ret = comedi_timeout(dev, s, insn, a2150_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		data[n] = inw(dev->iobase + FIFO_DATA_REG);
 		data[n] ^= 0x8000;
 	}
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index e8cd5ddb85c5..4262385e4f46 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -96,7 +96,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
 #define CLOCK_100_HZ	0x8F25
 /* Other miscellaneous defines */
 #define ATMIO16D_SIZE	32	/* bus address range */
-#define ATMIO16D_TIMEOUT 10
 
 struct atmio16_board_t {
 
@@ -448,16 +447,32 @@ static int atmio16d_ai_cancel(struct comedi_device *dev,
 	return 0;
 }
 
-/* Mode 0 is used to get a single conversion on demand */
+static int atmio16d_ai_eoc(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
+			   unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + STAT_REG);
+	if (status & STAT_AD_CONVAVAIL)
+		return 0;
+	if (status & STAT_AD_OVERFLOW) {
+		outw(0, dev->iobase + AD_CLEAR_REG);
+		return -EOVERFLOW;
+	}
+	return -EBUSY;
+}
+
 static int atmio16d_ai_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
 	struct atmio16d_private *devpriv = dev->private;
-	int i, t;
+	int i;
 	int chan;
 	int gain;
-	int status;
+	int ret;
 
 	chan = CR_CHAN(insn->chanspec);
 	gain = CR_RANGE(insn->chanspec);
@@ -473,26 +488,17 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev,
 	for (i = 0; i < insn->n; i++) {
 		/* start the conversion */
 		outw(0, dev->iobase + START_CONVERT_REG);
+
 		/* wait for it to finish */
-		for (t = 0; t < ATMIO16D_TIMEOUT; t++) {
-			/* check conversion status */
-			status = inw(dev->iobase + STAT_REG);
-			if (status & STAT_AD_CONVAVAIL) {
-				/* read the data now */
-				data[i] = inw(dev->iobase + AD_FIFO_REG);
-				/* change to two's complement if need be */
-				if (devpriv->adc_coding == adc_2comp)
-					data[i] ^= 0x800;
-				break;
-			}
-			if (status & STAT_AD_OVERFLOW) {
-				outw(0, dev->iobase + AD_CLEAR_REG);
-				return -ETIME;
-			}
-		}
-		/* end waiting, now check if it timed out */
-		if (t == ATMIO16D_TIMEOUT)
-			return -ETIME;
+		ret = comedi_timeout(dev, s, insn, atmio16d_ai_eoc, 0);
+		if (ret)
+			return ret;
+
+		/* read the data now */
+		data[i] = inw(dev->iobase + AD_FIFO_REG);
+		/* change to two's complement if need be */
+		if (devpriv->adc_coding == adc_2comp)
+			data[i] ^= 0x800;
 	}
 
 	return i;
@@ -723,10 +729,13 @@ static int atmio16d_attach(struct comedi_device *dev,
 
 	/* 8255 subdevice */
 	s = &dev->subdevices[3];
-	if (board->has_8255)
-		subdev_8255_init(dev, s, NULL, dev->iobase);
-	else
+	if (board->has_8255) {
+		ret = subdev_8255_init(dev, s, NULL, dev->iobase);
+		if (ret)
+			return ret;
+	} else {
 		s->type = COMEDI_SUBD_UNUSED;
+	}
 
 /* don't yet know how to deal with counter/timers */
 #if 0
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index e4cdca349157..171a71d20c88 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -109,14 +109,31 @@ static int daq700_dio_insn_config(struct comedi_device *dev,
 	return insn->n;
 }
 
+static int daq700_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + STA_R2);
+	if ((status & 0x03))
+		return -EOVERFLOW;
+	status = inb(dev->iobase + STA_R1);
+	if ((status & 0x02))
+		return -ENODATA;
+	if ((status & 0x11) == 0x01)
+		return 0;
+	return -EBUSY;
+}
+
 static int daq700_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s,
 			   struct comedi_insn *insn, unsigned int *data)
 {
-	int n, i, chan;
+	int n, chan;
 	int d;
-	unsigned int status;
-	enum { TIMEOUT = 100 };
+	int ret;
 
 	chan = CR_CHAN(insn->chanspec);
 	/* write channel to multiplexer */
@@ -130,30 +147,12 @@ static int daq700_ai_rinsn(struct comedi_device *dev,
 		outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */
 		/* mode 1 out0 H, L to H, start conversion */
 		outb(0x32, dev->iobase + CMO_R);
+
 		/* wait for conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			status = inb(dev->iobase + STA_R2);
-			if ((status & 0x03) != 0) {
-				dev_info(dev->class_dev,
-					 "Overflow/run Error\n");
-				return -EOVERFLOW;
-			}
-			status = inb(dev->iobase + STA_R1);
-			if ((status & 0x02) != 0) {
-				dev_info(dev->class_dev, "Data Error\n");
-				return -ENODATA;
-			}
-			if ((status & 0x11) == 0x01) {
-				/* ADC conversion complete */
-				break;
-			}
-			udelay(1);
-		}
-		if (i == TIMEOUT) {
-			dev_info(dev->class_dev,
-				 "timeout during ADC conversion\n");
-			return -ETIMEDOUT;
-		}
+		ret = comedi_timeout(dev, s, insn, daq700_ai_eoc, 0);
+		if (ret)
+			return ret;
+
 		/* read data */
 		d = inw(dev->iobase + ADFIFO_R);
 		/* mangle the data as necessary */
@@ -229,11 +228,6 @@ static int daq700_auto_attach(struct comedi_device *dev,
 	s->insn_read = daq700_ai_rinsn;
 	daq700_ai_config(dev, s);
 
-	dev_info(dev->class_dev, "%s: %s, io 0x%lx\n",
-		dev->driver->driver_name,
-		dev->board_name,
-		dev->iobase);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 0512445df08e..037b46eb949f 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -73,7 +73,6 @@
 #include "ni_labpc_isadma.h"
 
 #define LABPC_SIZE		0x20	/* size of ISA io region */
-#define LABPC_ADC_TIMEOUT	1000
 
 enum scan_mode {
 	MODE_SINGLE_CHAN,
@@ -308,19 +307,17 @@ static void labpc_clear_adc_fifo(struct comedi_device *dev)
 	labpc_read_adc_fifo(dev);
 }
 
-static int labpc_ai_wait_for_data(struct comedi_device *dev,
-				  int timeout)
+static int labpc_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
 {
 	struct labpc_private *devpriv = dev->private;
-	int i;
 
-	for (i = 0; i < timeout; i++) {
-		devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
-		if (devpriv->stat1 & STAT1_DAVAIL)
-			return 0;
-		udelay(1);
-	}
-	return -ETIME;
+	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	if (devpriv->stat1 & STAT1_DAVAIL)
+		return 0;
+	return -EBUSY;
 }
 
 static int labpc_ai_insn_read(struct comedi_device *dev,
@@ -363,7 +360,7 @@ static int labpc_ai_insn_read(struct comedi_device *dev,
 		/* trigger conversion */
 		devpriv->write_byte(0x1, dev->iobase + ADC_START_CONVERT_REG);
 
-		ret = labpc_ai_wait_for_data(dev, LABPC_ADC_TIMEOUT);
+		ret = comedi_timeout(dev, s, insn, labpc_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 457b88481db0..3a86d482babd 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -687,12 +687,22 @@ static void ni_clear_ai_fifo(struct comedi_device *dev)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
+	static const int timeout = 10000;
+	int i;
 
 	if (board->reg_type == ni_reg_6143) {
 		/*  Flush the 6143 data FIFO */
 		ni_writel(0x10, AIFIFO_Control_6143);	/*  Flush fifo */
 		ni_writel(0x00, AIFIFO_Control_6143);	/*  Flush fifo */
-		while (ni_readl(AIFIFO_Status_6143) & 0x10) ;	/*  Wait for complete */
+		/*  Wait for complete */
+		for (i = 0; i < timeout; i++) {
+			if (!(ni_readl(AIFIFO_Status_6143) & 0x10))
+				break;
+			udelay(1);
+		}
+		if (i == timeout) {
+			comedi_error(dev, "FIFO flush timeout.");
+		}
 	} else {
 		devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
 		if (board->reg_type == ni_reg_625x) {
@@ -4282,10 +4292,14 @@ static int ni_E_init(struct comedi_device *dev)
 
 	/* 8255 device */
 	s = &dev->subdevices[NI_8255_DIO_SUBDEV];
-	if (board->has_8255)
-		subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev);
-	else
+	if (board->has_8255) {
+		ret = subdev_8255_init(dev, s, ni_8255_callback,
+				       (unsigned long)dev);
+		if (ret)
+			return ret;
+	} else {
 		s->type = COMEDI_SUBD_UNUSED;
+	}
 
 	/* formerly general purpose counter/timer device, but no longer used */
 	s = &dev->subdevices[NI_UNUSED_SUBDEV];
@@ -4393,6 +4407,9 @@ static int ni_E_init(struct comedi_device *dev)
 							&ni_gpct_read_register,
 							counter_variant,
 							NUM_GPCT);
+	if (!devpriv->counter_dev)
+		return -ENOMEM;
+
 	/* General purpose counters */
 	for (j = 0; j < NUM_GPCT; ++j) {
 		s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
@@ -4483,7 +4500,6 @@ static int ni_E_init(struct comedi_device *dev)
 		ni_writeb(0x0, M_Offset_AO_Calibration);
 	}
 
-	printk("\n");
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 0ed980455875..d40df072583c 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -1551,7 +1551,7 @@ static int pcimio_auto_attach(struct comedi_device *dev,
 	dev->subdevices[NI_GPCT_SUBDEV(1)].buf_change = &pcimio_gpct1_change;
 	dev->subdevices[NI_DIO_SUBDEV].buf_change = &pcimio_dio_change;
 
-	return ret;
+	return 0;
 }
 
 static int pcimio_ai_change(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index f0fc123ef566..7c03a5d17b1b 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -253,18 +253,17 @@ static void pcl711_set_changain(struct comedi_device *dev,
 	outb(mux | PCL711_MUX_CHAN(chan), dev->iobase + PCL711_MUX_REG);
 }
 
-static int pcl711_ai_wait_for_eoc(struct comedi_device *dev,
-				  unsigned int timeout)
+static int pcl711_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
 {
-	unsigned int msb;
+	unsigned int status;
 
-	while (timeout--) {
-		msb = inb(dev->iobase + PCL711_AI_MSB_REG);
-		if ((msb & PCL711_AI_MSB_DRDY) == 0)
-			return 0;
-		udelay(1);
-	}
-	return -ETIME;
+	status = inb(dev->iobase + PCL711_AI_MSB_REG);
+	if ((status & PCL711_AI_MSB_DRDY) == 0)
+		return 0;
+	return -EBUSY;
 }
 
 static int pcl711_ai_insn_read(struct comedi_device *dev,
@@ -282,7 +281,7 @@ static int pcl711_ai_insn_read(struct comedi_device *dev,
 	for (i = 0; i < insn->n; i++) {
 		outb(PCL711_SOFTTRIG, dev->iobase + PCL711_SOFTTRIG_REG);
 
-		ret = pcl711_ai_wait_for_eoc(dev, 100);
+		ret = comedi_timeout(dev, s, insn, pcl711_ai_eoc, 0);
 		if (ret)
 			return ret;
 
@@ -336,11 +335,8 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (cmd->stop_src == TRIG_NONE) {
+	if (cmd->stop_src == TRIG_NONE)
 		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
-	} else {
-		/* ignore */
-	}
 
 	if (err)
 		return 3;
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 53613b385f35..3a0dad82d510 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -131,12 +131,7 @@
 #define boardACL8216	      8	/* and ICP DAS A-826PG */
 #define boardA821	      9	/* PGH, PGL, PGL/NDA versions */
 
-#define PCLx1x_IORANGE	     16
-
-#define PCL812_CTR0	      0
-#define PCL812_CTR1	      1
-#define PCL812_CTR2	      2
-#define PCL812_CTRCTL	      3
+#define PCL812_TIMER_BASE			0x00
 #define PCL812_AD_LO	      4
 #define PCL812_DA1_LO	      4
 #define PCL812_AD_HI	      5
@@ -331,79 +326,268 @@ static const struct comedi_lrange range_a821pgh_ai = {
 };
 
 struct pcl812_board {
+	const char *name;
+	int board_type;
+	int n_aichan;
+	int n_aochan;
+	unsigned int ai_ns_min;
+	const struct comedi_lrange *rangelist_ai;
+	unsigned int IRQbits;
+	unsigned int has_dma:1;
+	unsigned int has_16bit_ai:1;
+	unsigned int has_mpc508_mux:1;
+	unsigned int has_dio:1;
+};
 
-	const char *name;	/*  board name */
-	int board_type;		/*  type of this board */
-	int n_aichan;		/*  num of AI chans in S.E. */
-	int n_aichan_diff;	/*  DIFF num of chans */
-	int n_aochan;		/*  num of DA chans */
-	int n_dichan;		/*  DI and DO chans */
-	int n_dochan;
-	int ai_maxdata;		/*  AI resolution */
-	unsigned int ai_ns_min;	/*  max sample speed of card v ns */
-	unsigned int i8254_osc_base;	/*  clock base */
-	const struct comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
-	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
-	unsigned int IRQbits;	/*  allowed IRQ */
-	unsigned char DMAbits;	/*  allowed DMA chans */
-	unsigned char io_range;	/*  iorange for this board */
-	unsigned char haveMPC508;	/*  1=board use MPC508A multiplexor */
+static const struct pcl812_board boardtypes[] = {
+	{
+		.name		= "pcl812",
+		.board_type	= boardPCL812,
+		.n_aichan	= 16,
+		.n_aochan	= 2,
+		.ai_ns_min	= 33000,
+		.rangelist_ai	= &range_bipolar10,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "pcl812pg",
+		.board_type	= boardPCL812PG,
+		.n_aichan	= 16,
+		.n_aochan	= 2,
+		.ai_ns_min	= 33000,
+		.rangelist_ai	= &range_pcl812pg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "acl8112pg",
+		.board_type	= boardPCL812PG,
+		.n_aichan	= 16,
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_pcl812pg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "acl8112dg",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_acl8112dg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_mpc508_mux	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "acl8112hg",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_acl8112hg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_mpc508_mux	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "a821pgl",
+		.board_type	= boardA821,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 1,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_pcl813b_ai,
+		.IRQbits	= 0x000c,
+		.has_dio	= 1,
+	}, {
+		.name		= "a821pglnda",
+		.board_type	= boardA821,
+		.n_aichan	= 16,	/* 8 differential */
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_pcl813b_ai,
+		.IRQbits	= 0x000c,
+	}, {
+		.name		= "a821pgh",
+		.board_type	= boardA821,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 1,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_a821pgh_ai,
+		.IRQbits	= 0x000c,
+		.has_dio	= 1,
+	}, {
+		.name		= "a822pgl",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_acl8112dg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "a822pgh",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_acl8112hg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "a823pgl",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 8000,
+		.rangelist_ai	= &range_acl8112dg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "a823pgh",
+		.board_type	= boardACL8112,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 8000,
+		.rangelist_ai	= &range_acl8112hg_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "pcl813",
+		.board_type	= boardPCL813,
+		.n_aichan	= 32,
+		.rangelist_ai	= &range_pcl813b_ai,
+	}, {
+		.name		= "pcl813b",
+		.board_type	= boardPCL813B,
+		.n_aichan	= 32,
+		.rangelist_ai	= &range_pcl813b_ai,
+	}, {
+		.name		= "acl8113",
+		.board_type	= boardACL8113,
+		.n_aichan	= 32,
+		.rangelist_ai	= &range_acl8113_1_ai,
+	}, {
+		.name		= "iso813",
+		.board_type	= boardISO813,
+		.n_aichan	= 32,
+		.rangelist_ai	= &range_iso813_1_ai,
+	}, {
+		.name		= "acl8216",
+		.board_type	= boardACL8216,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_pcl813b2_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_16bit_ai	= 1,
+		.has_mpc508_mux	= 1,
+		.has_dio	= 1,
+	}, {
+		.name		= "a826pg",
+		.board_type	= boardACL8216,
+		.n_aichan	= 16,	/* 8 differential */
+		.n_aochan	= 2,
+		.ai_ns_min	= 10000,
+		.rangelist_ai	= &range_pcl813b2_ai,
+		.IRQbits	= 0xdcfc,
+		.has_dma	= 1,
+		.has_16bit_ai	= 1,
+		.has_dio	= 1,
+	},
 };
 
 struct pcl812_private {
-
-	unsigned char valid;	/*  =1 device is OK */
 	unsigned char dma;	/*  >0 use dma ( usedDMA channel) */
-	unsigned char use_diff;	/*  =1 diff inputs */
-	unsigned char use_MPC;	/*  1=board uses MPC508A multiplexor */
-	unsigned char use_ext_trg;	/*  1=board uses external trigger */
 	unsigned char range_correction;	/*  =1 we must add 1 to range number */
 	unsigned char old_chan_reg;	/*  lastly used chan/gain pair */
 	unsigned char old_gain_reg;
 	unsigned char mode_reg_int;	/*  there is stored INT number for some card */
-	unsigned char ai_neverending;	/*  =1 we do unlimited AI */
-	unsigned char ai_eos;	/*  1=EOS wake up */
-	unsigned char ai_dma;	/*  =1 we use DMA */
 	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
-	unsigned int ai_scans;	/*  len of scanlist */
 	unsigned int ai_act_scan;	/*  how many scans we finished */
-	unsigned int ai_chanlist[MAX_CHANLIST_LEN];	/*  our copy of channel/range list */
-	unsigned int ai_n_chan;	/*  how many channels is measured */
-	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
-	unsigned int ai_is16b;	/*  =1 we have 16 bit card */
+	unsigned int dmapages;
+	unsigned int hwdmasize;
 	unsigned long dmabuf[2];	/*  PTR to DMA buf */
-	unsigned int dmapages[2];	/*  how many pages we have allocated */
 	unsigned int hwdmaptr[2];	/*  HW PTR to DMA buf */
-	unsigned int hwdmasize[2];	/*  DMA buf size in bytes */
 	unsigned int dmabytestomove[2];	/*  how many bytes DMA transfer */
 	int next_dma_buf;	/*  which buffer is next to use */
 	unsigned int dma_runs_to_end;	/*  how many times we must switch DMA buffers */
 	unsigned int last_dma_run;	/*  how many bytes to transfer on last DMA buffer */
 	unsigned int max_812_ai_mode0_rangewait;	/*  setling time for gain */
 	unsigned int ao_readback[2];	/*  data for AO readback */
+	unsigned int divisor1;
+	unsigned int divisor2;
+	unsigned int use_diff:1;
+	unsigned int use_mpc508:1;
+	unsigned int use_ext_trg:1;
+	unsigned int ai_dma:1;
+	unsigned int ai_eos:1;
+	unsigned int ai_neverending:1;
 };
 
-/*
-==============================================================================
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
-			unsigned int divisor1, unsigned int divisor2);
 static void setup_range_channel(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				unsigned int rangechan, char wait);
-static int pcl812_ai_cancel(struct comedi_device *dev,
-			    struct comedi_subdevice *s);
-/*
-==============================================================================
-*/
+
+static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers)
+{
+	struct pcl812_private *devpriv = dev->private;
+	unsigned long timer_base = dev->iobase + PCL812_TIMER_BASE;
+
+	i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
+	udelay(1);
+
+	if (load_timers) {
+		i8254_write(timer_base, 0, 2, devpriv->divisor2);
+		i8254_write(timer_base, 0, 1, devpriv->divisor1);
+	}
+}
+
+static unsigned int pcl812_ai_get_sample(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
+{
+	unsigned int val;
+
+	val = inb(dev->iobase + PCL812_AD_HI) << 8;
+	val |= inb(dev->iobase + PCL812_AD_LO);
+
+	return val & s->maxdata;
+}
+
+static int pcl812_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	if (s->maxdata > 0x0fff) {
+		status = inb(dev->iobase + ACL8216_STATUS);
+		if ((status & ACL8216_DRDY) == 0)
+			return 0;
+	} else {
+		status = inb(dev->iobase + PCL812_AD_HI);
+		if ((status & PCL812_DRDY) == 0)
+			return 0;
+	}
+	return -EBUSY;
+}
+
 static int pcl812_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
 	struct pcl812_private *devpriv = dev->private;
+	int ret = 0;
 	int n;
-	int timeout, hi;
 
 	/* select software trigger */
 	outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);
@@ -413,64 +597,18 @@ static int pcl812_ai_insn_read(struct comedi_device *dev,
 		/* start conversion */
 		outb(255, dev->iobase + PCL812_SOFTTRIG);
 		udelay(5);
-		timeout = 50;	/* wait max 50us, it must finish under 33us */
-		while (timeout--) {
-			hi = inb(dev->iobase + PCL812_AD_HI);
-			if (!(hi & PCL812_DRDY))
-				goto conv_finish;
-			udelay(1);
-		}
-		dev_dbg(dev->class_dev, "A/D insn read timeout\n");
-		outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
-		return -ETIME;
 
-conv_finish:
-		data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO);
+		ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0);
+		if (ret)
+			break;
+
+		data[n] = pcl812_ai_get_sample(dev, s);
 	}
 	outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
-	return n;
-}
-
-/*
-==============================================================================
-*/
-static int acl8216_ai_insn_read(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
-{
-	int n;
-	int timeout;
 
-	/* select software trigger */
-	outb(1, dev->iobase + PCL812_MODE);
-	/*  select channel and renge */
-	setup_range_channel(dev, s, insn->chanspec, 1);
-	for (n = 0; n < insn->n; n++) {
-		/* start conversion */
-		outb(255, dev->iobase + PCL812_SOFTTRIG);
-		udelay(5);
-		timeout = 50;	/* wait max 50us, it must finish under 33us */
-		while (timeout--) {
-			if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY))
-				goto conv_finish;
-			udelay(1);
-		}
-		dev_dbg(dev->class_dev, "A/D insn read timeout\n");
-		outb(0, dev->iobase + PCL812_MODE);
-		return -ETIME;
-
-conv_finish:
-		data[n] =
-		    (inb(dev->iobase +
-			 PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO);
-	}
-	outb(0, dev->iobase + PCL812_MODE);
-	return n;
+	return ret ? ret : n;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
@@ -490,9 +628,6 @@ static int pcl812_ao_insn_write(struct comedi_device *dev,
 	return i;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
@@ -507,9 +642,6 @@ static int pcl812_ao_insn_read(struct comedi_device *dev,
 	return i;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_di_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
@@ -535,9 +667,6 @@ static int pcl812_do_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
@@ -545,7 +674,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 	struct pcl812_private *devpriv = dev->private;
 	int err = 0;
 	unsigned int flags;
-	int tmp, divisor1, divisor2;
+	int tmp;
 
 	/* Step 1 : check if triggers are trivially valid */
 
@@ -600,8 +729,9 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(board->i8254_osc_base,
-					  &divisor1, &divisor2,
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
 					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < board->ai_ns_min)
 			cmd->convert_arg = board->ai_ns_min;
@@ -615,54 +745,21 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 	return 0;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct pcl812_board *board = comedi_board(dev);
 	struct pcl812_private *devpriv = dev->private;
-	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
 	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int i, dma_flags, bytes;
 
-	if (cmd->start_src != TRIG_NOW)
-		return -EINVAL;
-	if (cmd->scan_begin_src != TRIG_FOLLOW)
-		return -EINVAL;
-	if (devpriv->use_ext_trg) {
-		if (cmd->convert_src != TRIG_EXT)
-			return -EINVAL;
-	} else {
-		if (cmd->convert_src != TRIG_TIMER)
-			return -EINVAL;
-	}
-	if (cmd->scan_end_src != TRIG_COUNT)
-		return -EINVAL;
-	if (cmd->scan_end_arg != cmd->chanlist_len)
-		return -EINVAL;
-	if (cmd->chanlist_len > MAX_CHANLIST_LEN)
-		return -EINVAL;
-
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_ns_min)
-			cmd->convert_arg = board->ai_ns_min;
-		i8253_cascade_ns_to_timer(board->i8254_osc_base,
-					  &divisor1, &divisor2,
-					  &cmd->convert_arg, cmd->flags);
-	}
-
-	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+	pcl812_start_pacer(dev, false);
 
-	devpriv->ai_n_chan = cmd->chanlist_len;
-	memcpy(devpriv->ai_chanlist, cmd->chanlist,
-	       sizeof(unsigned int) * cmd->scan_end_arg);
 	/*  select first channel and range */
-	setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);
+	setup_range_channel(dev, s, cmd->chanlist[0], 1);
 
 	if (devpriv->dma) {	/*  check if we can use DMA transfer */
 		devpriv->ai_dma = 1;
-		for (i = 1; i < devpriv->ai_n_chan; i++)
-			if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) {
+		for (i = 1; i < cmd->chanlist_len; i++)
+			if (cmd->chanlist[0] != cmd->chanlist[i]) {
 				/*  we cann't use DMA :-( */
 				devpriv->ai_dma = 0;
 				break;
@@ -670,26 +767,22 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	} else
 		devpriv->ai_dma = 0;
 
-	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
-	if (cmd->stop_src == TRIG_COUNT) {
-		devpriv->ai_scans = cmd->stop_arg;
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->ai_neverending = 0;
-	} else {
-		devpriv->ai_scans = 0;
+	else
 		devpriv->ai_neverending = 1;
-	}
 
 	devpriv->ai_act_scan = 0;
 	devpriv->ai_poll_ptr = 0;
 	s->async->cur_chan = 0;
 
 	/*  don't we want wake up every scan? */
-	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
+	if (cmd->flags & TRIG_WAKE_EOS) {
 		devpriv->ai_eos = 1;
 
 		/*  DMA is useless for this situation */
-		if (devpriv->ai_n_chan == 1)
+		if (cmd->chanlist_len == 1)
 			devpriv->ai_dma = 0;
 	}
 
@@ -697,25 +790,25 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/*  we use EOS, so adapt DMA buffer to one scan */
 		if (devpriv->ai_eos) {
 			devpriv->dmabytestomove[0] =
-			    devpriv->ai_n_chan * sizeof(short);
+			    cmd->chanlist_len * sizeof(short);
 			devpriv->dmabytestomove[1] =
-			    devpriv->ai_n_chan * sizeof(short);
+			    cmd->chanlist_len * sizeof(short);
 			devpriv->dma_runs_to_end = 1;
 		} else {
-			devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
-			devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
-			if (devpriv->ai_data_len < devpriv->hwdmasize[0])
+			devpriv->dmabytestomove[0] = devpriv->hwdmasize;
+			devpriv->dmabytestomove[1] = devpriv->hwdmasize;
+			if (devpriv->ai_data_len < devpriv->hwdmasize) {
 				devpriv->dmabytestomove[0] =
 				    devpriv->ai_data_len;
-			if (devpriv->ai_data_len < devpriv->hwdmasize[1])
 				devpriv->dmabytestomove[1] =
 				    devpriv->ai_data_len;
+			}
 			if (devpriv->ai_neverending) {
 				devpriv->dma_runs_to_end = 1;
 			} else {
 				/*  how many samples we must transfer? */
-				bytes = devpriv->ai_n_chan *
-					devpriv->ai_scans * sizeof(short);
+				bytes = cmd->chanlist_len *
+					cmd->stop_arg * sizeof(short);
 
 				/*  how many DMA pages we must fill */
 				devpriv->dma_runs_to_end =
@@ -730,12 +823,12 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 				devpriv->dma_runs_to_end--;
 			}
 		}
-		if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) {
-			devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
+		if (devpriv->dmabytestomove[0] > devpriv->hwdmasize) {
+			devpriv->dmabytestomove[0] = devpriv->hwdmasize;
 			devpriv->ai_eos = 0;
 		}
-		if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) {
-			devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
+		if (devpriv->dmabytestomove[1] > devpriv->hwdmasize) {
+			devpriv->dmabytestomove[1] = devpriv->hwdmasize;
 			devpriv->ai_eos = 0;
 		}
 		devpriv->next_dma_buf = 0;
@@ -750,7 +843,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	switch (cmd->convert_src) {
 	case TRIG_TIMER:
-		start_pacer(dev, 1, divisor1, divisor2);
+		pcl812_start_pacer(dev, true);
 		break;
 	}
 
@@ -762,23 +855,20 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
-/*
-==============================================================================
-*/
 static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 {
 	char err = 1;
-	unsigned int mask, timeout;
+	unsigned int timeout;
 	struct comedi_device *dev = d;
 	struct pcl812_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int next_chan;
 
 	s->async->events = 0;
 
 	timeout = 50;		/* wait max 50us, it must finish under 33us */
-	if (devpriv->ai_is16b) {
-		mask = 0xffff;
+	if (s->maxdata > 0x0fff) {
 		while (timeout--) {
 			if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) {
 				err = 0;
@@ -787,7 +877,6 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 			udelay(1);
 		}
 	} else {
-		mask = 0x0fff;
 		while (timeout--) {
 			if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) {
 				err = 0;
@@ -799,23 +888,20 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 
 	if (err) {
 		dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n");
-		pcl812_ai_cancel(dev, s);
+		s->cancel(dev, s);
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
 	}
 
-	comedi_buf_put(s->async,
-		       ((inb(dev->iobase + PCL812_AD_HI) << 8) |
-			inb(dev->iobase + PCL812_AD_LO)) & mask);
+	comedi_buf_put(s->async, pcl812_ai_get_sample(dev, s));
 
 	/* Set up next channel. Added by abbotti 2010-01-20, but untested. */
 	next_chan = s->async->cur_chan + 1;
-	if (next_chan >= devpriv->ai_n_chan)
+	if (next_chan >= cmd->chanlist_len)
 		next_chan = 0;
-	if (devpriv->ai_chanlist[s->async->cur_chan] !=
-			devpriv->ai_chanlist[next_chan])
-		setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0);
+	if (cmd->chanlist[s->async->cur_chan] != cmd->chanlist[next_chan])
+		setup_range_channel(dev, s, cmd->chanlist[next_chan], 0);
 
 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
 
@@ -824,8 +910,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 		devpriv->ai_act_scan++;
 		if (!(devpriv->ai_neverending))
 							/* all data sampled */
-			if (devpriv->ai_act_scan >= devpriv->ai_scans) {
-				pcl812_ai_cancel(dev, s);
+			if (devpriv->ai_act_scan >= cmd->stop_arg) {
+				s->cancel(dev, s);
 				s->async->events |= COMEDI_CB_EOA;
 			}
 	}
@@ -834,15 +920,13 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-*/
 static void transfer_from_dma_buf(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  unsigned short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
 	struct pcl812_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int i;
 
 	s->async->events = 0;
@@ -851,13 +935,13 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 		comedi_buf_put(s->async, ptr[bufptr++]);
 
 		s->async->cur_chan++;
-		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+		if (s->async->cur_chan >= cmd->chanlist_len) {
 			s->async->cur_chan = 0;
 			devpriv->ai_act_scan++;
 			if (!devpriv->ai_neverending)
 							/* all data sampled */
-				if (devpriv->ai_act_scan >= devpriv->ai_scans) {
-					pcl812_ai_cancel(dev, s);
+				if (devpriv->ai_act_scan >= cmd->stop_arg) {
+					s->cancel(dev, s);
 					s->async->events |= COMEDI_CB_EOA;
 					break;
 				}
@@ -867,9 +951,6 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 	comedi_event(dev, s);
 }
 
-/*
-==============================================================================
-*/
 static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 {
 	struct comedi_device *dev = d;
@@ -914,9 +995,6 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-*/
 static irqreturn_t interrupt_pcl812(int irq, void *d)
 {
 	struct comedi_device *dev = d;
@@ -932,9 +1010,6 @@ static irqreturn_t interrupt_pcl812(int irq, void *d)
 		return interrupt_pcl812_ai_int(irq, d);
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pcl812_private *devpriv = dev->private;
@@ -979,9 +1054,6 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 	return s->async->buf_write_count - s->async->buf_read_count;
 }
 
-/*
-==============================================================================
-*/
 static void setup_range_channel(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				unsigned int rangechan, char wait)
@@ -999,7 +1071,7 @@ static void setup_range_channel(struct comedi_device *dev,
 	devpriv->old_chan_reg = chan_reg;
 	devpriv->old_gain_reg = gain_reg;
 
-	if (devpriv->use_MPC) {
+	if (devpriv->use_mpc508) {
 		if (devpriv->use_diff) {
 			chan_reg = chan_reg | 0x30;	/*  DIFF inputs */
 		} else {
@@ -1024,27 +1096,6 @@ static void setup_range_channel(struct comedi_device *dev,
 		udelay(devpriv->max_812_ai_mode0_rangewait);
 }
 
-/*
-==============================================================================
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
-			unsigned int divisor1, unsigned int divisor2)
-{
-	outb(0xb4, dev->iobase + PCL812_CTRCTL);
-	outb(0x74, dev->iobase + PCL812_CTRCTL);
-	udelay(1);
-
-	if (mode == 1) {
-		outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2);
-		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2);
-		outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1);
-		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1);
-	}
-}
-
-/*
-==============================================================================
-*/
 static int pcl812_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
@@ -1055,14 +1106,11 @@ static int pcl812_ai_cancel(struct comedi_device *dev,
 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
 							/* Stop A/D */
 	outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
-	start_pacer(dev, -1, 0, 0);	/*  stop 8254 */
+	pcl812_start_pacer(dev, false);
 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
 	return 0;
 }
 
-/*
-==============================================================================
-*/
 static void pcl812_reset(struct comedi_device *dev)
 {
 	const struct pcl812_board *board = comedi_board(dev);
@@ -1083,7 +1131,7 @@ static void pcl812_reset(struct comedi_device *dev)
 	case boardA821:
 		outb(0, dev->iobase + PCL812_DA1_LO);
 		outb(0, dev->iobase + PCL812_DA1_HI);
-		start_pacer(dev, -1, 0, 0);	/*  stop 8254 */
+		pcl812_start_pacer(dev, false);
 		outb(0, dev->iobase + PCL812_DO_HI);
 		outb(0, dev->iobase + PCL812_DO_LO);
 		outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
@@ -1099,24 +1147,114 @@ static void pcl812_reset(struct comedi_device *dev)
 	udelay(5);
 }
 
+static void pcl812_set_ai_range_table(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_devconfig *it)
+{
+	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv = dev->private;
+
+	/* default to the range table from the boardinfo */
+	s->range_table = board->rangelist_ai;
+
+	/* now check the user config option based on the boardtype */
+	switch (board->board_type) {
+	case boardPCL812PG:
+		if (it->options[4] == 1)
+			s->range_table = &range_pcl812pg2_ai;
+		break;
+	case boardPCL812:
+		switch (it->options[4]) {
+		case 0:
+			s->range_table = &range_bipolar10;
+			break;
+		case 1:
+			s->range_table = &range_bipolar5;
+			break;
+		case 2:
+			s->range_table = &range_bipolar2_5;
+			break;
+		case 3:
+			s->range_table = &range812_bipolar1_25;
+			break;
+		case 4:
+			s->range_table = &range812_bipolar0_625;
+			break;
+		case 5:
+			s->range_table = &range812_bipolar0_3125;
+			break;
+		default:
+			s->range_table = &range_bipolar10;
+			break;
+		}
+		break;
+	case boardPCL813B:
+		if (it->options[1] == 1)
+			s->range_table = &range_pcl813b2_ai;
+		break;
+	case boardISO813:
+		switch (it->options[1]) {
+		case 0:
+			s->range_table = &range_iso813_1_ai;
+			break;
+		case 1:
+			s->range_table = &range_iso813_1_2_ai;
+			break;
+		case 2:
+			s->range_table = &range_iso813_2_ai;
+			devpriv->range_correction = 1;
+			break;
+		case 3:
+			s->range_table = &range_iso813_2_2_ai;
+			devpriv->range_correction = 1;
+			break;
+		default:
+			s->range_table = &range_iso813_1_ai;
+			break;
+		}
+		break;
+	case boardACL8113:
+		switch (it->options[1]) {
+		case 0:
+			s->range_table = &range_acl8113_1_ai;
+			break;
+		case 1:
+			s->range_table = &range_acl8113_1_2_ai;
+			break;
+		case 2:
+			s->range_table = &range_acl8113_2_ai;
+			devpriv->range_correction = 1;
+			break;
+		case 3:
+			s->range_table = &range_acl8113_2_2_ai;
+			devpriv->range_correction = 1;
+			break;
+		default:
+			s->range_table = &range_acl8113_1_ai;
+			break;
+		}
+		break;
+	}
+}
+
 static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl812_board *board = comedi_board(dev);
 	struct pcl812_private *devpriv;
-	int ret, subdev;
-	unsigned int dma;
-	unsigned long pages;
 	struct comedi_subdevice *s;
 	int n_subdevices;
-
-	ret = comedi_request_region(dev, it->options[0], board->io_range);
-	if (ret)
-		return ret;
+	int subdev;
+	int ret;
+	int i;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
+	ret = comedi_request_region(dev, it->options[0], 0x10);
+	if (ret)
+		return ret;
+
 	if ((1 << it->options[1]) & board->IRQbits) {
 		ret = request_irq(it->options[1], interrupt_pcl812, 0,
 				  dev->board_name, dev);
@@ -1124,59 +1262,51 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 			dev->irq = it->options[1];
 	}
 
-	dma = 0;
-	devpriv->dma = dma;
-	if (!dev->irq)
-		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
-	if (board->DMAbits != 0) {	/* board support DMA */
-		dma = it->options[2];
-		if (((1 << dma) & board->DMAbits) == 0) {
-			dev_err(dev->class_dev,
-				"DMA is out of allowed range, FAIL!\n");
-			return -EINVAL;	/* Bad DMA */
-		}
-		ret = request_dma(dma, dev->board_name);
+	/* we need an IRQ to do DMA on channel 3 or 1 */
+	if (dev->irq && board->has_dma &&
+	    (it->options[2] == 3 || it->options[2] == 1)) {
+		ret = request_dma(it->options[2], dev->board_name);
 		if (ret) {
 			dev_err(dev->class_dev,
-				"unable to allocate DMA %u, FAIL!\n", dma);
-			return -EBUSY;	/* DMA isn't free */
-		}
-		devpriv->dma = dma;
-		pages = 1;	/* we want 8KB */
-		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
-		if (!devpriv->dmabuf[0]) {
-			dev_err(dev->class_dev,
-				"unable to allocate DMA buffer, FAIL!\n");
-			/*
-			 * maybe experiment with try_to_free_pages()
-			 * will help ....
-			 */
-			return -EBUSY;	/* no buffer :-( */
-		}
-		devpriv->dmapages[0] = pages;
-		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
-		devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages);
-		devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
-		if (!devpriv->dmabuf[1]) {
-			dev_err(dev->class_dev,
-				"unable to allocate DMA buffer, FAIL!\n");
+				"unable to request DMA channel %d\n",
+				it->options[2]);
 			return -EBUSY;
 		}
-		devpriv->dmapages[1] = pages;
-		devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
-		devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages);
+		devpriv->dma = it->options[2];
+
+		devpriv->dmapages = 1;	/* we want 8KB */
+		devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE;
+
+		for (i = 0; i < 2; i++) {
+			unsigned long dmabuf;
+
+			dmabuf =  __get_dma_pages(GFP_KERNEL, devpriv->dmapages);
+			if (!dmabuf)
+				return -ENOMEM;
+
+			devpriv->dmabuf[i] = dmabuf;
+			devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf);
+		}
 	}
-no_dma:
 
-	n_subdevices = 0;
-	if (board->n_aichan > 0)
-		n_subdevices++;
+	/* differential analog inputs? */
+	switch (board->board_type) {
+	case boardA821:
+		if (it->options[2] == 1)
+			devpriv->use_diff = 1;
+		break;
+	case boardACL8112:
+	case boardACL8216:
+		if (it->options[4] == 1)
+			devpriv->use_diff = 1;
+		break;
+	}
+
+	n_subdevices = 1;		/* all boardtypes have analog inputs */
 	if (board->n_aochan > 0)
 		n_subdevices++;
-	if (board->n_dichan > 0)
-		n_subdevices++;
-	if (board->n_dochan > 0)
-		n_subdevices++;
+	if (board->has_dio)
+		n_subdevices += 2;
 
 	ret = comedi_alloc_subdevices(dev, n_subdevices);
 	if (ret)
@@ -1184,135 +1314,36 @@ no_dma:
 
 	subdev = 0;
 
-	/* analog input */
-	if (board->n_aichan > 0) {
-		s = &dev->subdevices[subdev];
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags = SDF_READABLE;
-		switch (board->board_type) {
-		case boardA821:
-			if (it->options[2] == 1) {
-				s->n_chan = board->n_aichan_diff;
-				s->subdev_flags |= SDF_DIFF;
-				devpriv->use_diff = 1;
-			} else {
-				s->n_chan = board->n_aichan;
-				s->subdev_flags |= SDF_GROUND;
-			}
-			break;
-		case boardACL8112:
-		case boardACL8216:
-			if (it->options[4] == 1) {
-				s->n_chan = board->n_aichan_diff;
-				s->subdev_flags |= SDF_DIFF;
-				devpriv->use_diff = 1;
-			} else {
-				s->n_chan = board->n_aichan;
-				s->subdev_flags |= SDF_GROUND;
-			}
-			break;
-		default:
-			s->n_chan = board->n_aichan;
-			s->subdev_flags |= SDF_GROUND;
-			break;
-		}
-		s->maxdata = board->ai_maxdata;
-		s->range_table = board->rangelist_ai;
-		if (board->board_type == boardACL8216)
-			s->insn_read = acl8216_ai_insn_read;
-		else
-			s->insn_read = pcl812_ai_insn_read;
-
-		devpriv->use_MPC = board->haveMPC508;
-		if (dev->irq) {
-			dev->read_subdev = s;
-			s->subdev_flags |= SDF_CMD_READ;
-			s->len_chanlist = MAX_CHANLIST_LEN;
-			s->do_cmdtest = pcl812_ai_cmdtest;
-			s->do_cmd = pcl812_ai_cmd;
-			s->poll = pcl812_ai_poll;
-			s->cancel = pcl812_ai_cancel;
-		}
-		switch (board->board_type) {
-		case boardPCL812PG:
-			if (it->options[4] == 1)
-				s->range_table = &range_pcl812pg2_ai;
-			break;
-		case boardPCL812:
-			switch (it->options[4]) {
-			case 0:
-				s->range_table = &range_bipolar10;
-				break;
-			case 1:
-				s->range_table = &range_bipolar5;
-				break;
-			case 2:
-				s->range_table = &range_bipolar2_5;
-				break;
-			case 3:
-				s->range_table = &range812_bipolar1_25;
-				break;
-			case 4:
-				s->range_table = &range812_bipolar0_625;
-				break;
-			case 5:
-				s->range_table = &range812_bipolar0_3125;
-				break;
-			default:
-				s->range_table = &range_bipolar10;
-				break;
-			}
-			break;
-			break;
-		case boardPCL813B:
-			if (it->options[1] == 1)
-				s->range_table = &range_pcl813b2_ai;
-			break;
-		case boardISO813:
-			switch (it->options[1]) {
-			case 0:
-				s->range_table = &range_iso813_1_ai;
-				break;
-			case 1:
-				s->range_table = &range_iso813_1_2_ai;
-				break;
-			case 2:
-				s->range_table = &range_iso813_2_ai;
-				devpriv->range_correction = 1;
-				break;
-			case 3:
-				s->range_table = &range_iso813_2_2_ai;
-				devpriv->range_correction = 1;
-				break;
-			default:
-				s->range_table = &range_iso813_1_ai;
-				break;
-			}
-			break;
-		case boardACL8113:
-			switch (it->options[1]) {
-			case 0:
-				s->range_table = &range_acl8113_1_ai;
-				break;
-			case 1:
-				s->range_table = &range_acl8113_1_2_ai;
-				break;
-			case 2:
-				s->range_table = &range_acl8113_2_ai;
-				devpriv->range_correction = 1;
-				break;
-			case 3:
-				s->range_table = &range_acl8113_2_2_ai;
-				devpriv->range_correction = 1;
-				break;
-			default:
-				s->range_table = &range_acl8113_1_ai;
-				break;
-			}
-			break;
-		}
-		subdev++;
+	/* Analog Input subdevice */
+	s = &dev->subdevices[subdev];
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE;
+	if (devpriv->use_diff) {
+		s->subdev_flags	|= SDF_DIFF;
+		s->n_chan	= board->n_aichan / 2;
+	} else {
+		s->subdev_flags	|= SDF_GROUND;
+		s->n_chan	= board->n_aichan;
 	}
+	s->maxdata	= board->has_16bit_ai ? 0xffff : 0x0fff;
+
+	pcl812_set_ai_range_table(dev, s, it);
+
+	s->insn_read	= pcl812_ai_insn_read;
+
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= MAX_CHANLIST_LEN;
+		s->do_cmdtest	= pcl812_ai_cmdtest;
+		s->do_cmd	= pcl812_ai_cmd;
+		s->poll		= pcl812_ai_poll;
+		s->cancel	= pcl812_ai_cancel;
+	}
+
+	devpriv->use_mpc508 = board->has_mpc508_mux;
+
+	subdev++;
 
 	/* analog output */
 	if (board->n_aochan > 0) {
@@ -1321,7 +1352,7 @@ no_dma:
 		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
 		s->n_chan = board->n_aochan;
 		s->maxdata = 0xfff;
-		s->range_table = board->rangelist_ao;
+		s->range_table = &range_unipolar5;
 		s->insn_read = pcl812_ao_insn_read;
 		s->insn_write = pcl812_ao_insn_write;
 		switch (board->board_type) {
@@ -1342,24 +1373,22 @@ no_dma:
 		subdev++;
 	}
 
-	/* digital input */
-	if (board->n_dichan > 0) {
+	if (board->has_dio) {
+		/* Digital Input subdevice */
 		s = &dev->subdevices[subdev];
 		s->type = COMEDI_SUBD_DI;
 		s->subdev_flags = SDF_READABLE;
-		s->n_chan = board->n_dichan;
+		s->n_chan = 16;
 		s->maxdata = 1;
 		s->range_table = &range_digital;
 		s->insn_bits = pcl812_di_insn_bits;
 		subdev++;
-	}
 
-	/* digital output */
-	if (board->n_dochan > 0) {
+		/* Digital Output subdevice */
 		s = &dev->subdevices[subdev];
 		s->type = COMEDI_SUBD_DO;
 		s->subdev_flags = SDF_WRITABLE;
-		s->n_chan = board->n_dochan;
+		s->n_chan = 16;
 		s->maxdata = 1;
 		s->range_table = &range_digital;
 		s->insn_bits = pcl812_do_insn_bits;
@@ -1368,7 +1397,6 @@ no_dma:
 
 	switch (board->board_type) {
 	case boardACL8216:
-		devpriv->ai_is16b = 1;
 	case boardPCL812PG:
 	case boardPCL812:
 	case boardACL8112:
@@ -1390,8 +1418,6 @@ no_dma:
 		break;
 	}
 
-	devpriv->valid = 1;
-
 	pcl812_reset(dev);
 
 	return 0;
@@ -1403,72 +1429,15 @@ static void pcl812_detach(struct comedi_device *dev)
 
 	if (devpriv) {
 		if (devpriv->dmabuf[0])
-			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
+			free_pages(devpriv->dmabuf[0], devpriv->dmapages);
 		if (devpriv->dmabuf[1])
-			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
+			free_pages(devpriv->dmabuf[1], devpriv->dmapages);
 		if (devpriv->dma)
 			free_dma(devpriv->dma);
 	}
 	comedi_legacy_detach(dev);
 }
 
-static const struct pcl812_board boardtypes[] = {
-	{"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
-	 33000, I8254_OSC_BASE_2MHZ, &range_bipolar10, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
-	 33000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
-	{"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
-	{"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, &range_unipolar5,
-	 0x000c, 0x00, PCLx1x_IORANGE, 0},
-	{"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, NULL,
-	 0x000c, 0x00, PCLx1x_IORANGE, 0},
-	{"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_a821pgh_ai, &range_unipolar5,
-	 0x000c, 0x00, PCLx1x_IORANGE, 0},
-	{"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 8000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 8000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-	{"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
-	 0, 0, &range_pcl813b_ai, NULL,
-	 0x0000, 0x00, PCLx1x_IORANGE, 0},
-	{"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
-	 0, 0, &range_pcl813b_ai, NULL,
-	 0x0000, 0x00, PCLx1x_IORANGE, 0},
-	{"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
-	 0, 0, &range_acl8113_1_ai, NULL,
-	 0x0000, 0x00, PCLx1x_IORANGE, 0},
-	{"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
-	 0, 0, &range_iso813_1_ai, NULL,
-	 0x0000, 0x00, PCLx1x_IORANGE, 0},
-	{"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
-	{"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
-	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
-	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-};
-
 static struct comedi_driver pcl812_driver = {
 	.driver_name	= "pcl812",
 	.module		= THIS_MODULE,
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index e9d470459933..2e383ebde119 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -44,16 +44,7 @@ Configuration Options:
 #include "comedi_fc.h"
 #include "8253.h"
 
-/* boards constants */
-/* IO space len */
-#define PCLx1x_RANGE 16
-
-/* INTEL 8254 counters */
-#define PCL816_CTR0 4
-#define PCL816_CTR1 5
-#define PCL816_CTR2 6
-/* R: counter read-back register W: counter control */
-#define PCL816_CTRCTL 7
+#define PCL816_TIMER_BASE			0x04
 
 /* R: A/D high byte W: A/D range control */
 #define PCL816_RANGE 9
@@ -95,81 +86,103 @@ static const struct comedi_lrange range_pcl816 = {
 };
 
 struct pcl816_board {
+	const char *name;
+	int ai_maxdata;
+	int ao_maxdata;
+	int ai_chanlist;
+};
 
-	const char *name;	/*  board name */
-	int n_ranges;		/*  len of range list */
-	int n_aichan;		/*  num of A/D chans in diferencial mode */
-	unsigned int ai_ns_min;	/*  minimal allowed delay between samples (in ns) */
-	int n_aochan;		/*  num of D/A chans */
-	int n_dichan;		/*  num of DI chans */
-	int n_dochan;		/*  num of DO chans */
-	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
-	const struct comedi_lrange *ao_range_type;	/*  default D/A rangelist */
-	unsigned int io_range;	/*  len of IO space */
-	unsigned int IRQbits;	/*  allowed interrupts */
-	unsigned int DMAbits;	/*  allowed DMA chans */
-	int ai_maxdata;		/*  maxdata for A/D */
-	int ao_maxdata;		/*  maxdata for D/A */
-	int ai_chanlist;	/*  allowed len of channel list A/D */
-	int ao_chanlist;	/*  allowed len of channel list D/A */
-	int i8254_osc_base;	/*  1/frequency of on board oscilator in ns */
+static const struct pcl816_board boardtypes[] = {
+	{
+		.name		= "pcl816",
+		.ai_maxdata	= 0xffff,
+		.ao_maxdata	= 0xffff,
+		.ai_chanlist	= 1024,
+	}, {
+		.name		= "pcl814b",
+		.ai_maxdata	= 0x3fff,
+		.ao_maxdata	= 0x3fff,
+		.ai_chanlist	= 1024,
+	},
 };
 
 struct pcl816_private {
-
 	unsigned int dma;	/*  used DMA, 0=don't use DMA */
+	unsigned int dmapages;
+	unsigned int hwdmasize;
 	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
-	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
 	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
-	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
 	unsigned int dmasamplsize;	/*  size in samples hwdmasize[0]/2 */
 	int next_dma_buf;	/*  which DMA buffer will be used next round */
 	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
 	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
-
-	unsigned int ai_scans;	/*  len of scanlist */
-	unsigned char ai_neverending;	/*  if=1, then we do neverending record (you must use cancel()) */
-	int irq_blocked;	/*  1=IRQ now uses any subdev */
-	int irq_was_now_closed;	/*  when IRQ finish, there's stored int816_mode for last interrupt */
 	int int816_mode;	/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
-	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
 	int ai_act_scan;	/*  how many scans we finished */
 	unsigned int ai_act_chanlist[16];	/*  MUX setting for actual AI operations */
-	unsigned int ai_act_chanlist_len;	/*  how long is actual MUX list */
-	unsigned int ai_act_chanlist_pos;	/*  actual position in MUX list */
-	unsigned int ai_n_chan;		/*  how many channels per scan */
 	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
+	unsigned int divisor1;
+	unsigned int divisor2;
+	unsigned int ai_cmd_running:1;
+	unsigned int irq_was_now_closed:1;
+	unsigned int ai_neverending:1;
 };
 
-/*
-==============================================================================
-*/
 static int check_channel_list(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      unsigned int *chanlist, unsigned int chanlen);
 static void setup_channel_list(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       unsigned int *chanlist, unsigned int seglen);
-static int pcl816_ai_cancel(struct comedi_device *dev,
-			    struct comedi_subdevice *s);
-static void start_pacer(struct comedi_device *dev, int mode,
-			unsigned int divisor1, unsigned int divisor2);
 
-static int pcl816_ai_cmdtest(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_cmd *cmd);
-static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters)
+{
+	struct pcl816_private *devpriv = dev->private;
+	unsigned long timer_base = dev->iobase + PCL816_TIMER_BASE;
+
+	i8254_set_mode(timer_base, 0, 0, I8254_MODE1 | I8254_BINARY);
+	i8254_write(timer_base, 0, 0, 0x00ff);
+	udelay(1);
+
+	i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
+	udelay(1);
+
+	if (load_counters) {
+		i8254_write(timer_base, 0, 2, devpriv->divisor2);
+		i8254_write(timer_base, 0, 1, devpriv->divisor1);
+	}
+}
+
+static unsigned int pcl816_ai_get_sample(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
+{
+	unsigned int val;
+
+	val = inb(dev->iobase + PCL816_AD_HI) << 8;
+	val |= inb(dev->iobase + PCL816_AD_LO);
+
+	return val & s->maxdata;
+}
+
+static int pcl816_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + PCL816_STATUS);
+	if ((status & PCL816_STATUS_DRDY_MASK) == 0)
+		return 0;
+	return -EBUSY;
+}
 
-/*
-==============================================================================
-   ANALOG INPUT MODE0, 816 cards, slow version
-*/
 static int pcl816_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	int ret;
 	int n;
-	int timeout;
 
 	/*  software trigger, DMA and INT off */
 	outb(0, dev->iobase + PCL816_CONTROL);
@@ -185,45 +198,27 @@ static int pcl816_ai_insn_read(struct comedi_device *dev,
 
 		outb(0, dev->iobase + PCL816_AD_LO);	/* start conversion */
 
-		timeout = 100;
-		while (timeout--) {
-			if (!(inb(dev->iobase + PCL816_STATUS) &
-			      PCL816_STATUS_DRDY_MASK)) {
-				/*  return read value */
-				data[n] =
-				    ((inb(dev->iobase +
-					  PCL816_AD_HI) << 8) |
-				     (inb(dev->iobase + PCL816_AD_LO)));
-				/* clear INT (conversion end) flag */
-				outb(0, dev->iobase + PCL816_CLRINT);
-				break;
-			}
-			udelay(1);
-		}
-		/*  Return timeout error */
-		if (!timeout) {
-			comedi_error(dev, "A/D insn timeout\n");
-			data[0] = 0;
+		ret = comedi_timeout(dev, s, insn, pcl816_ai_eoc, 0);
+		if (ret) {
 			/* clear INT (conversion end) flag */
 			outb(0, dev->iobase + PCL816_CLRINT);
-			return -EIO;
+			return ret;
 		}
 
+		data[n] = pcl816_ai_get_sample(dev, s);
+
+		/* clear INT (conversion end) flag */
+		outb(0, dev->iobase + PCL816_CLRINT);
 	}
 	return n;
 }
 
-/*
-==============================================================================
-   analog input interrupt mode 1 & 3, 818 cards
-   one sample per interrupt version
-*/
 static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct pcl816_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
-	unsigned char low, hi;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	int timeout = 50;	/* wait max 50us */
 
 	while (timeout--) {
@@ -235,51 +230,41 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 	if (!timeout) {		/*  timeout, bail error */
 		outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
 		comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
-		pcl816_ai_cancel(dev, s);
+		s->cancel(dev, s);
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
 
 	}
 
-	/*  get the sample */
-	low = inb(dev->iobase + PCL816_AD_LO);
-	hi = inb(dev->iobase + PCL816_AD_HI);
-
-	comedi_buf_put(s->async, (hi << 8) | low);
+	comedi_buf_put(s->async, pcl816_ai_get_sample(dev, s));
 
 	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
 
-	if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len)
-		devpriv->ai_act_chanlist_pos = 0;
-
 	s->async->cur_chan++;
-	if (s->async->cur_chan >= devpriv->ai_n_chan) {
+	if (s->async->cur_chan >= cmd->chanlist_len) {
 		s->async->cur_chan = 0;
 		devpriv->ai_act_scan++;
 	}
 
 	if (!devpriv->ai_neverending)
 					/* all data sampled */
-		if (devpriv->ai_act_scan >= devpriv->ai_scans) {
+		if (devpriv->ai_act_scan >= cmd->stop_arg) {
 			/* all data sampled */
-			pcl816_ai_cancel(dev, s);
+			s->cancel(dev, s);
 			s->async->events |= COMEDI_CB_EOA;
 		}
 	comedi_event(dev, s);
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-   analog input dma mode 1 & 3, 816 cards
-*/
 static void transfer_from_dma_buf(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  unsigned short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
 	struct pcl816_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	int i;
 
 	s->async->events = 0;
@@ -288,21 +273,16 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 
 		comedi_buf_put(s->async, ptr[bufptr++]);
 
-		if (++devpriv->ai_act_chanlist_pos >=
-		    devpriv->ai_act_chanlist_len) {
-			devpriv->ai_act_chanlist_pos = 0;
-		}
-
 		s->async->cur_chan++;
-		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+		if (s->async->cur_chan >= cmd->chanlist_len) {
 			s->async->cur_chan = 0;
 			devpriv->ai_act_scan++;
 		}
 
 		if (!devpriv->ai_neverending)
 						/*  all data sampled */
-			if (devpriv->ai_act_scan >= devpriv->ai_scans) {
-				pcl816_ai_cancel(dev, s);
+			if (devpriv->ai_act_scan >= cmd->stop_arg) {
+				s->cancel(dev, s);
 				s->async->events |= COMEDI_CB_EOA;
 				s->async->events |= COMEDI_CB_BLOCK;
 				break;
@@ -333,13 +313,10 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 /* clear_dma_ff (devpriv->dma); */
 		set_dma_addr(devpriv->dma,
 			     devpriv->hwdmaptr[devpriv->next_dma_buf]);
-		if (devpriv->dma_runs_to_end) {
-			set_dma_count(devpriv->dma,
-				      devpriv->hwdmasize[devpriv->
-							 next_dma_buf]);
-		} else {
+		if (devpriv->dma_runs_to_end)
+			set_dma_count(devpriv->dma, devpriv->hwdmasize);
+		else
 			set_dma_count(devpriv->dma, devpriv->last_dma_run);
-		}
 		release_dma_lock(dma_flags);
 		enable_dma(devpriv->dma);
 	}
@@ -349,7 +326,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 
 	ptr = (unsigned short *)devpriv->dmabuf[this_dma_buf];
 
-	len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr;
+	len = (devpriv->hwdmasize >> 1) - devpriv->ai_poll_ptr;
 	bufptr = devpriv->ai_poll_ptr;
 	devpriv->ai_poll_ptr = 0;
 
@@ -357,10 +334,6 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-    INT procedure
-*/
 static irqreturn_t interrupt_pcl816(int irq, void *d)
 {
 	struct comedi_device *dev = d;
@@ -381,7 +354,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d)
 	}
 
 	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
-	if (!dev->irq || !devpriv->irq_blocked || !devpriv->int816_mode) {
+	if (!devpriv->ai_cmd_running || !devpriv->int816_mode) {
 		if (devpriv->irq_was_now_closed) {
 			devpriv->irq_was_now_closed = 0;
 			/*  comedi_error(dev,"last IRQ.."); */
@@ -394,15 +367,12 @@ static irqreturn_t interrupt_pcl816(int irq, void *d)
 	return IRQ_NONE;
 }
 
-/*
-==============================================================================
-*/
 static int pcl816_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-	const struct pcl816_board *board = comedi_board(dev);
+	struct pcl816_private *devpriv = dev->private;
 	int err = 0;
-	int tmp, divisor1 = 0, divisor2 = 0;
+	int tmp;
 
 	/* Step 1 : check if triggers are trivially valid */
 
@@ -432,8 +402,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
 	if (cmd->convert_src == TRIG_TIMER)
-		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-						 board->ai_ns_min);
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
 	else	/* TRIG_EXT */
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
@@ -451,11 +420,12 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 	/* step 4: fix up any arguments */
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(board->i8254_osc_base,
-					  &divisor1, &divisor2,
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
 					  &cmd->convert_arg, cmd->flags);
-		if (cmd->convert_arg < board->ai_ns_min)
-			cmd->convert_arg = board->ai_ns_min;
+		if (cmd->convert_arg < 10000)
+			cmd->convert_arg = 10000;
 		if (tmp != cmd->convert_arg)
 			err++;
 	}
@@ -477,44 +447,15 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 
 static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct pcl816_board *board = comedi_board(dev);
 	struct pcl816_private *devpriv = dev->private;
-	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
 	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int dma_flags, bytes, dmairq;
 	unsigned int seglen;
 
-	if (cmd->start_src != TRIG_NOW)
-		return -EINVAL;
-	if (cmd->scan_begin_src != TRIG_FOLLOW)
-		return -EINVAL;
-	if (cmd->scan_end_src != TRIG_COUNT)
-		return -EINVAL;
-	if (cmd->scan_end_arg != cmd->chanlist_len)
-		return -EINVAL;
-/* if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL; */
-	if (devpriv->irq_blocked)
+	if (devpriv->ai_cmd_running)
 		return -EBUSY;
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_ns_min)
-			cmd->convert_arg = board->ai_ns_min;
-
-		i8253_cascade_ns_to_timer(board->i8254_osc_base,
-					  &divisor1, &divisor2,
-					  &cmd->convert_arg, cmd->flags);
-
-		/*  PCL816 crash if any divisor is set to 1 */
-		if (divisor1 == 1) {
-			divisor1 = 2;
-			divisor2 /= 2;
-		}
-		if (divisor2 == 1) {
-			divisor2 = 2;
-			divisor1 /= 2;
-		}
-	}
-
-	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+	pcl816_start_pacer(dev, false);
 
 	seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
 	if (seglen < 1)
@@ -522,23 +463,19 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	setup_channel_list(dev, s, cmd->chanlist, seglen);
 	udelay(1);
 
-	devpriv->ai_n_chan = cmd->chanlist_len;
 	devpriv->ai_act_scan = 0;
 	s->async->cur_chan = 0;
-	devpriv->irq_blocked = 1;
+	devpriv->ai_cmd_running = 1;
 	devpriv->ai_poll_ptr = 0;
 	devpriv->irq_was_now_closed = 0;
 
-	if (cmd->stop_src == TRIG_COUNT) {
-		devpriv->ai_scans = cmd->stop_arg;
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->ai_neverending = 0;
-	} else {
-		devpriv->ai_scans = 0;
+	else
 		devpriv->ai_neverending = 1;
-	}
 
 	if (devpriv->dma) {
-		bytes = devpriv->hwdmasize[0];
+		bytes = devpriv->hwdmasize;
 		if (!devpriv->ai_neverending) {
 			/*  how many */
 			bytes = s->async->cmd.chanlist_len *
@@ -546,14 +483,13 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 			sizeof(short);
 
 			/*  how many DMA pages we must fill */
-			devpriv->dma_runs_to_end = bytes /
-			devpriv->hwdmasize[0];
+			devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize;
 
 			/* on last dma transfer must be moved */
-			devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];
+			devpriv->last_dma_run = bytes % devpriv->hwdmasize;
 			devpriv->dma_runs_to_end--;
 			if (devpriv->dma_runs_to_end >= 0)
-				bytes = devpriv->hwdmasize[0];
+				bytes = devpriv->hwdmasize;
 		} else
 			devpriv->dma_runs_to_end = -1;
 
@@ -567,7 +503,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		enable_dma(devpriv->dma);
 	}
 
-	start_pacer(dev, 1, divisor1, divisor2);
+	pcl816_start_pacer(dev, true);
 	dmairq = ((devpriv->dma & 0x3) << 4) | (dev->irq & 0x7);
 
 	switch (cmd->convert_src) {
@@ -618,7 +554,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 	}
 
 	/*  where is now DMA in buffer */
-	top1 = devpriv->hwdmasize[0] - top1;
+	top1 = devpriv->hwdmasize - top1;
 	top1 >>= 1;		/*  sample position */
 	top2 = top1 - devpriv->ai_poll_ptr;
 	if (top2 < 1) {		/*  no new samples */
@@ -637,16 +573,12 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 	return s->async->buf_write_count - s->async->buf_read_count;
 }
 
-/*
-==============================================================================
- cancel any mode 1-4 AI
-*/
 static int pcl816_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
 	struct pcl816_private *devpriv = dev->private;
 
-	if (devpriv->irq_blocked > 0) {
+	if (devpriv->ai_cmd_running) {
 		switch (devpriv->int816_mode) {
 		case INT_TYPE_AI1_DMA:
 		case INT_TYPE_AI3_DMA:
@@ -659,21 +591,22 @@ static int pcl816_ai_cancel(struct comedi_device *dev,
 			outb(0, dev->iobase + PCL816_CONTROL);	/* Stop A/D */
 
 			/* Stop pacer */
-			outb(0xb0, dev->iobase + PCL816_CTRCTL);
-			outb(0x70, dev->iobase + PCL816_CTRCTL);
+			i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0,
+				       2, I8254_MODE0 | I8254_BINARY);
+			i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0,
+				       1, I8254_MODE0 | I8254_BINARY);
+
 			outb(0, dev->iobase + PCL816_AD_LO);
-			inb(dev->iobase + PCL816_AD_LO);
-			inb(dev->iobase + PCL816_AD_HI);
+			pcl816_ai_get_sample(dev, s);
 
 			/* clear INT request */
 			outb(0, dev->iobase + PCL816_CLRINT);
 
 			/* Stop A/D */
 			outb(0, dev->iobase + PCL816_CONTROL);
-			devpriv->irq_blocked = 0;
-			devpriv->irq_was_now_closed = devpriv->int816_mode;
+			devpriv->ai_cmd_running = 0;
+			devpriv->irq_was_now_closed = 1;
 			devpriv->int816_mode = 0;
-			devpriv->last_int_sub = s;
 /* s->busy = 0; */
 			break;
 		}
@@ -681,35 +614,10 @@ static int pcl816_ai_cancel(struct comedi_device *dev,
 	return 0;
 }
 
-/*
-==============================================================================
- chech for PCL816
-*/
-static int pcl816_check(unsigned long iobase)
-{
-	outb(0x00, iobase + PCL816_MUX);
-	udelay(1);
-	if (inb(iobase + PCL816_MUX) != 0x00)
-		return 1;	/* there isn't card */
-	outb(0x55, iobase + PCL816_MUX);
-	udelay(1);
-	if (inb(iobase + PCL816_MUX) != 0x55)
-		return 1;	/* there isn't card */
-	outb(0x00, iobase + PCL816_MUX);
-	udelay(1);
-	outb(0x18, iobase + PCL816_CONTROL);
-	udelay(1);
-	if (inb(iobase + PCL816_CONTROL) != 0x18)
-		return 1;	/* there isn't card */
-	return 0;		/*  ok, card exist */
-}
-
-/*
-==============================================================================
- reset whole PCL-816 cards
-*/
 static void pcl816_reset(struct comedi_device *dev)
 {
+	unsigned long timer_base = dev->iobase + PCL816_TIMER_BASE;
+
 /* outb (0, dev->iobase + PCL818_DA_LO);         DAC=0V */
 /* outb (0, dev->iobase + PCL818_DA_HI); */
 /* udelay (1); */
@@ -719,49 +627,15 @@ static void pcl816_reset(struct comedi_device *dev)
 	outb(0, dev->iobase + PCL816_CONTROL);
 	outb(0, dev->iobase + PCL816_MUX);
 	outb(0, dev->iobase + PCL816_CLRINT);
-	outb(0xb0, dev->iobase + PCL816_CTRCTL);	/* Stop pacer */
-	outb(0x70, dev->iobase + PCL816_CTRCTL);
-	outb(0x30, dev->iobase + PCL816_CTRCTL);
-	outb(0, dev->iobase + PCL816_RANGE);
-}
-
-/*
-==============================================================================
- Start/stop pacer onboard pacer
-*/
-static void
-start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
-	    unsigned int divisor2)
-{
-	outb(0x32, dev->iobase + PCL816_CTRCTL);
-	outb(0xff, dev->iobase + PCL816_CTR0);
-	outb(0x00, dev->iobase + PCL816_CTR0);
-	udelay(1);
 
-	/*  set counter 2 as mode 3 */
-	outb(0xb4, dev->iobase + PCL816_CTRCTL);
-	/*  set counter 1 as mode 3 */
-	outb(0x74, dev->iobase + PCL816_CTRCTL);
-	udelay(1);
+	/* Stop pacer */
+	i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 1, I8254_MODE0 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY);
 
-	if (mode == 1) {
-		dev_dbg(dev->class_dev, "mode %d, divisor1 %d, divisor2 %d\n",
-			mode, divisor1, divisor2);
-		outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2);
-		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2);
-		outb(divisor1 & 0xff, dev->iobase + PCL816_CTR1);
-		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL816_CTR1);
-	}
-
-	/* clear pending interrupts (just in case) */
-/* outb(0, dev->iobase + PCL816_CLRINT); */
+	outb(0, dev->iobase + PCL816_RANGE);
 }
 
-/*
-==============================================================================
- Check if channel list from user is built correctly
- If it's ok, then return non-zero length of repeated segment of channel list
-*/
 static int
 check_channel_list(struct comedi_device *dev,
 		   struct comedi_subdevice *s, unsigned int *chanlist,
@@ -818,10 +692,6 @@ check_channel_list(struct comedi_device *dev,
 	return seglen;	/*  we can serve this with MUX logic */
 }
 
-/*
-==============================================================================
- Program scan/gain logic with channel list.
-*/
 static void
 setup_channel_list(struct comedi_device *dev,
 		   struct comedi_subdevice *s, unsigned int *chanlist,
@@ -830,9 +700,6 @@ setup_channel_list(struct comedi_device *dev,
 	struct pcl816_private *devpriv = dev->private;
 	unsigned int i;
 
-	devpriv->ai_act_chanlist_len = seglen;
-	devpriv->ai_act_chanlist_pos = 0;
-
 	for (i = 0; i < seglen; i++) {	/*  store range list to card */
 		devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]);
 		outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX);
@@ -847,147 +714,124 @@ setup_channel_list(struct comedi_device *dev,
 	     dev->iobase + PCL816_MUX);
 }
 
+static int pcl816_check(struct comedi_device *dev)
+{
+	/* the MUX register should return the same value written */
+	outb(0x00, dev->iobase + PCL816_MUX);
+	if (inb(dev->iobase + PCL816_MUX) != 0x00)
+		return -ENODEV;
+	outb(0x55, dev->iobase + PCL816_MUX);
+	if (inb(dev->iobase + PCL816_MUX) != 0x55)
+		return -ENODEV;
+
+	/* reset the MUX register to a known state */
+	outb(0x00, dev->iobase + PCL816_MUX);
+
+	/* the CONTROL register should return the same value written */
+	outb(0x18, dev->iobase + PCL816_CONTROL);
+	if (inb(dev->iobase + PCL816_CONTROL) != 0x18)
+		return -ENODEV;
+
+	/* reset the CONTROL register to a known state */
+	outb(0x00, dev->iobase + PCL816_CONTROL);
+
+	return 0;
+}
+
 static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl816_board *board = comedi_board(dev);
 	struct pcl816_private *devpriv;
-	int ret;
-	unsigned int dma;
-	unsigned long pages;
-	/* int i; */
 	struct comedi_subdevice *s;
-
-	ret = comedi_request_region(dev, it->options[0], board->io_range);
-	if (ret)
-		return ret;
-
-	if (pcl816_check(dev->iobase)) {
-		dev_err(dev->class_dev, "I can't detect board. FAIL!\n");
-		return -EIO;
-	}
+	int ret;
+	int i;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
-	if ((1 << it->options[1]) & board->IRQbits) {
+	ret = comedi_request_region(dev, it->options[0], 0x10);
+	if (ret)
+		return ret;
+
+	ret = pcl816_check(dev);
+	if (ret)
+		return ret;
+
+	/* we can use IRQ 2-7 for async command support */
+	if (it->options[1] >= 2 && it->options[1] <= 7) {
 		ret = request_irq(it->options[1], interrupt_pcl816, 0,
 				  dev->board_name, dev);
 		if (ret == 0)
 			dev->irq = it->options[1];
 	}
 
-	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
-	devpriv->int816_mode = 0;	/* mode of irq */
-
-	/* grab our DMA */
-	dma = 0;
-	devpriv->dma = dma;
-	if (!dev->irq)
-		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
-
-	if (board->DMAbits != 0) {	/* board support DMA */
-		dma = it->options[2];
-		if (dma < 1)
-			goto no_dma;	/* DMA disabled */
-
-		if (((1 << dma) & board->DMAbits) == 0) {
-			dev_err(dev->class_dev,
-				"DMA is out of allowed range, FAIL!\n");
-			return -EINVAL;	/* Bad DMA */
-		}
-		ret = request_dma(dma, dev->board_name);
+	/* we need an IRQ to do DMA on channel 3 or 1 */
+	if (dev->irq && (it->options[2] == 3 || it->options[2] == 1)) {
+		ret = request_dma(it->options[2], dev->board_name);
 		if (ret) {
 			dev_err(dev->class_dev,
-				"unable to allocate DMA %u, FAIL!\n", dma);
-			return -EBUSY;	/* DMA isn't free */
+				"unable to request DMA channel %d\n",
+				it->options[2]);
+			return -EBUSY;
 		}
+		devpriv->dma = it->options[2];
 
-		devpriv->dma = dma;
-		pages = 2;	/* we need 16KB */
-		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
+		devpriv->dmapages = 2;	/* we need 16KB */
+		devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE;
 
-		if (!devpriv->dmabuf[0]) {
-			dev_err(dev->class_dev,
-				"unable to allocate DMA buffer, FAIL!\n");
-			/*
-			 * maybe experiment with try_to_free_pages()
-			 * will help ....
-			 */
-			return -EBUSY;	/* no buffer :-( */
-		}
-		devpriv->dmapages[0] = pages;
-		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
-		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
+		for (i = 0; i < 2; i++) {
+			unsigned long dmabuf;
 
-		devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
-		if (!devpriv->dmabuf[1]) {
-			dev_err(dev->class_dev,
-				"unable to allocate DMA buffer, FAIL!\n");
-			return -EBUSY;
+			dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages);
+			if (!dmabuf)
+				return -ENOMEM;
+
+			devpriv->dmabuf[i] = dmabuf;
+			devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf);
 		}
-		devpriv->dmapages[1] = pages;
-		devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
-		devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
 	}
 
-no_dma:
-
-/*  if (board->n_aochan > 0)
-    subdevs[1] = COMEDI_SUBD_AO;
-  if (board->n_dichan > 0)
-    subdevs[2] = COMEDI_SUBD_DI;
-  if (board->n_dochan > 0)
-    subdevs[3] = COMEDI_SUBD_DO;
-*/
-
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
 		return ret;
 
 	s = &dev->subdevices[0];
-	if (board->n_aichan > 0) {
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags = SDF_CMD_READ | SDF_DIFF;
-		s->n_chan = board->n_aichan;
-		s->maxdata = board->ai_maxdata;
-		s->range_table = board->ai_range_type;
-		s->insn_read = pcl816_ai_insn_read;
-		if (dev->irq) {
-			dev->read_subdev = s;
-			s->subdev_flags |= SDF_CMD_READ;
-			s->len_chanlist = board->ai_chanlist;
-			s->do_cmdtest = pcl816_ai_cmdtest;
-			s->do_cmd = pcl816_ai_cmd;
-			s->poll = pcl816_ai_poll;
-			s->cancel = pcl816_ai_cancel;
-		}
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_CMD_READ | SDF_DIFF;
+	s->n_chan	= 16;
+	s->maxdata	= board->ai_maxdata;
+	s->range_table	= &range_pcl816;
+	s->insn_read	= pcl816_ai_insn_read;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= board->ai_chanlist;
+		s->do_cmdtest	= pcl816_ai_cmdtest;
+		s->do_cmd	= pcl816_ai_cmd;
+		s->poll		= pcl816_ai_poll;
+		s->cancel	= pcl816_ai_cancel;
 	}
 
 #if 0
-case COMEDI_SUBD_AO:
+	subdevs[1] = COMEDI_SUBD_AO;
 	s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
-	s->n_chan = board->n_aochan;
+	s->n_chan = 1;
 	s->maxdata = board->ao_maxdata;
-	s->len_chanlist = board->ao_chanlist;
-	s->range_table = board->ao_range_type;
+	s->range_table = &range_pcl816;
 	break;
 
-case COMEDI_SUBD_DI:
+	subdevs[2] = COMEDI_SUBD_DI;
 	s->subdev_flags = SDF_READABLE;
-	s->n_chan = board->n_dichan;
+	s->n_chan = 16;
 	s->maxdata = 1;
-	s->len_chanlist = board->n_dichan;
 	s->range_table = &range_digital;
 	break;
 
-case COMEDI_SUBD_DO:
+	subdevs[3] = COMEDI_SUBD_DO;
 	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = board->n_dochan;
+	s->n_chan = 16;
 	s->maxdata = 1;
-	s->len_chanlist = board->n_dochan;
 	s->range_table = &range_digital;
 	break;
 #endif
@@ -1007,34 +851,13 @@ static void pcl816_detach(struct comedi_device *dev)
 		if (devpriv->dma)
 			free_dma(devpriv->dma);
 		if (devpriv->dmabuf[0])
-			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
+			free_pages(devpriv->dmabuf[0], devpriv->dmapages);
 		if (devpriv->dmabuf[1])
-			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
+			free_pages(devpriv->dmabuf[1], devpriv->dmapages);
 	}
 	comedi_legacy_detach(dev);
 }
 
-static const struct pcl816_board boardtypes[] = {
-	{"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
-	 &range_pcl816, PCLx1x_RANGE,
-	 0x00fc,		/*  IRQ mask */
-	 0x0a,			/*  DMA mask */
-	 0xffff,		/*  16-bit card */
-	 0xffff,		/*  D/A maxdata */
-	 1024,
-	 1,			/*  ao chan list */
-	 I8254_OSC_BASE_10MHZ},
-	{"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
-	 &range_pcl816, PCLx1x_RANGE,
-	 0x00fc,
-	 0x0a,
-	 0x3fff,		/* 14 bit card */
-	 0x3fff,
-	 1024,
-	 1,
-	 I8254_OSC_BASE_10MHZ},
-};
-
 static struct comedi_driver pcl816_driver = {
 	.driver_name	= "pcl816",
 	.module		= THIS_MODULE,
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index fa1758ad49d5..861f51976fd7 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -110,8 +110,6 @@ A word or two about DMA. Driver support DMA operations at two ways:
 #include "comedi_fc.h"
 #include "8253.h"
 
-/* #define PCL818_MODE13_AO 1 */
-
 /* boards constants */
 
 #define boardPCL818L 0
@@ -121,11 +119,6 @@ A word or two about DMA. Driver support DMA operations at two ways:
 #define boardPCL818 4
 #define boardPCL718 5
 
-/* IO space len */
-#define PCLx1x_RANGE 16
-/* IO space len if we use FIFO */
-#define PCLx1xFIFO_RANGE 32
-
 /* W: clear INT request */
 #define PCL818_CLRINT 8
 /* R: return status byte */
@@ -155,12 +148,8 @@ A word or two about DMA. Driver support DMA operations at two ways:
 /* W: PCL718 second D/A */
 #define PCL718_DA2_LO 6
 #define PCL718_DA2_HI 7
-/* counters */
-#define PCL818_CTR0 12
-#define PCL818_CTR1 13
-#define PCL818_CTR2 14
-/* W: counter control */
-#define PCL818_CTRCTL 15
+
+#define PCL818_TIMER_BASE			0x0c
 
 /* W: fifo enable/disable */
 #define PCL818_FI_ENABLE 6
@@ -181,10 +170,6 @@ A word or two about DMA. Driver support DMA operations at two ways:
 #define INT_TYPE_AI3_INT 4
 #define INT_TYPE_AI3_DMA 5
 #define INT_TYPE_AI3_FIFO 6
-#ifdef PCL818_MODE13_AO
-#define INT_TYPE_AO1_INT 7
-#define INT_TYPE_AO3_INT 8
-#endif
 
 #define MAGIC_DMA_WORD 0x5a5a
 
@@ -262,67 +247,99 @@ static const struct comedi_lrange range718_unipolar1 = {
 };
 
 struct pcl818_board {
+	const char *name;
+	unsigned int ns_min;
+	int n_aochan;
+	const struct comedi_lrange *ai_range_type;
+	unsigned int has_dma:1;
+	unsigned int has_fifo:1;
+	unsigned int is_818:1;
+};
 
-	const char *name;	/*  driver name */
-	int n_ranges;		/*  len of range list */
-	int n_aichan_se;	/*  num of A/D chans in single ended  mode */
-	int n_aichan_diff;	/*  num of A/D chans in diferencial mode */
-	unsigned int ns_min;	/*  minimal allowed delay between samples (in ns) */
-	int n_aochan;		/*  num of D/A chans */
-	int n_dichan;		/*  num of DI chans */
-	int n_dochan;		/*  num of DO chans */
-	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
-	const struct comedi_lrange *ao_range_type;	/*  default D/A rangelist */
-	unsigned int io_range;	/*  len of IO space */
-	unsigned int IRQbits;	/*  allowed interrupts */
-	unsigned int DMAbits;	/*  allowed DMA chans */
-	int ai_maxdata;		/*  maxdata for A/D */
-	int ao_maxdata;		/*  maxdata for D/A */
-	unsigned char fifo;	/*  1=board has FIFO */
-	int is_818;
+static const struct pcl818_board boardtypes[] = {
+	{
+		.name		= "pcl818l",
+		.ns_min		= 25000,
+		.n_aochan	= 1,
+		.ai_range_type	= &range_pcl818l_l_ai,
+		.has_dma	= 1,
+		.is_818		= 1,
+	}, {
+		.name		= "pcl818h",
+		.ns_min		= 10000,
+		.n_aochan	= 1,
+		.ai_range_type	= &range_pcl818h_ai,
+		.has_dma	= 1,
+		.is_818		= 1,
+	}, {
+		.name		= "pcl818hd",
+		.ns_min		= 10000,
+		.n_aochan	= 1,
+		.ai_range_type	= &range_pcl818h_ai,
+		.has_dma	= 1,
+		.has_fifo	= 1,
+		.is_818		= 1,
+	}, {
+		.name		= "pcl818hg",
+		.ns_min		= 10000,
+		.n_aochan	= 1,
+		.ai_range_type	= &range_pcl818hg_ai,
+		.has_dma	= 1,
+		.has_fifo	= 1,
+		.is_818		= 1,
+	}, {
+		.name		= "pcl818",
+		.ns_min		= 10000,
+		.n_aochan	= 2,
+		.ai_range_type	= &range_pcl818h_ai,
+		.has_dma	= 1,
+		.is_818		= 1,
+	}, {
+		.name		= "pcl718",
+		.ns_min		= 16000,
+		.n_aochan	= 2,
+		.ai_range_type	= &range_unipolar5,
+		.has_dma	= 1,
+	}, {
+		.name		= "pcm3718",
+		.ns_min		= 10000,
+		.ai_range_type	= &range_pcl818h_ai,
+		.has_dma	= 1,
+		.is_818		= 1,
+	},
 };
 
 struct pcl818_private {
-
 	unsigned int dma;	/*  used DMA, 0=don't use DMA */
-	unsigned int io_range;
+	unsigned int dmapages;
+	unsigned int hwdmasize;
 	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
-	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
 	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
-	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
 	int next_dma_buf;	/*  which DMA buffer will be used next round */
 	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
 	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
-	unsigned char neverending_ai;	/*  if=1, then we do neverending record (you must use cancel()) */
 	unsigned int ns_min;	/*  manimal allowed delay between samples (in us) for actual card */
 	int i8253_osc_base;	/*  1/frequency of on board oscilator in ns */
-	int irq_blocked;	/*  1=IRQ now uses any subdev */
-	int irq_was_now_closed;	/*  when IRQ finish, there's stored int818_mode for last interrupt */
 	int ai_mode;		/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
-	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
 	int ai_act_scan;	/*  how many scans we finished */
 	int ai_act_chan;	/*  actual position in actual scan */
 	unsigned int act_chanlist[16];	/*  MUX setting for actual AI operations */
 	unsigned int act_chanlist_len;	/*  how long is actual MUX list */
 	unsigned int act_chanlist_pos;	/*  actual position in MUX list */
-	unsigned int ai_scans;	/*  len of scanlist */
-	unsigned int ai_n_chan;	/*  how many channels is measured */
-	unsigned int *ai_chanlist;	/*  actaul chanlist */
-	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
-	unsigned int ai_timer1;	/*  timers */
-	unsigned int ai_timer2;
-	unsigned char usefifo;	/*  1=use fifo */
 	unsigned int ao_readback[2];
+	unsigned int divisor1;
+	unsigned int divisor2;
+	unsigned int usefifo:1;
+	unsigned int ai_cmd_running:1;
+	unsigned int irq_was_now_closed:1;
+	unsigned int neverending_ai:1;
 };
 
 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	/*  used for gain list programming */
 	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
 };
 
-/*
-==============================================================================
-*/
 static void setup_channel_list(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       unsigned int *chanlist, unsigned int n_chan,
@@ -331,21 +348,55 @@ static int check_channel_list(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      unsigned int *chanlist, unsigned int n_chan);
 
-static int pcl818_ai_cancel(struct comedi_device *dev,
-			    struct comedi_subdevice *s);
-static void start_pacer(struct comedi_device *dev, int mode,
-			unsigned int divisor1, unsigned int divisor2);
+static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters)
+{
+	struct pcl818_private *devpriv = dev->private;
+	unsigned long timer_base = dev->iobase + PCL818_TIMER_BASE;
+
+	i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
+	udelay(1);
+
+	if (load_counters) {
+		i8254_write(timer_base, 0, 2, devpriv->divisor2);
+		i8254_write(timer_base, 0, 1, devpriv->divisor1);
+	}
+}
+
+static unsigned int pcl818_ai_get_sample(struct comedi_device *dev,
+					 struct comedi_subdevice *s,
+					 unsigned int *chan)
+{
+	unsigned int val;
+
+	val = inb(dev->iobase + PCL818_AD_HI) << 8;
+	val |= inb(dev->iobase + PCL818_AD_LO);
+
+	if (chan)
+		*chan = val & 0xf;
+
+	return (val >> 4) & s->maxdata;
+}
+
+static int pcl818_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
+{
+	unsigned int status;
+
+	status = inb(dev->iobase + PCL818_STATUS);
+	if (status & 0x10)
+		return 0;
+	return -EBUSY;
+}
 
-/*
-==============================================================================
-   ANALOG INPUT MODE0, 818 cards, slow version
-*/
 static int pcl818_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	int ret;
 	int n;
-	int timeout;
 
 	/* software trigger, DMA and INT off */
 	outb(0, dev->iobase + PCL818_CONTROL);
@@ -364,30 +415,19 @@ static int pcl818_ai_insn_read(struct comedi_device *dev,
 		/* start conversion */
 		outb(0, dev->iobase + PCL818_AD_LO);
 
-		timeout = 100;
-		while (timeout--) {
-			if (inb(dev->iobase + PCL818_STATUS) & 0x10)
-				goto conv_finish;
-			udelay(1);
+		ret = comedi_timeout(dev, s, insn, pcl818_ai_eoc, 0);
+		if (ret) {
+			/* clear INT (conversion end) flag */
+			outb(0, dev->iobase + PCL818_CLRINT);
+			return ret;
 		}
-		comedi_error(dev, "A/D insn timeout");
-		/* clear INT (conversion end) flag */
-		outb(0, dev->iobase + PCL818_CLRINT);
-		return -EIO;
 
-conv_finish:
-		data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
-			   (inb(dev->iobase + PCL818_AD_LO) >> 4));
+		data[n] = pcl818_ai_get_sample(dev, s, NULL);
 	}
 
 	return n;
 }
 
-/*
-==============================================================================
-   ANALOG OUTPUT MODE0, 818 cards
-   only one sample per call is supported
-*/
 static int pcl818_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
@@ -421,12 +461,6 @@ static int pcl818_ao_insn_write(struct comedi_device *dev,
 	return n;
 }
 
-/*
-==============================================================================
-   DIGITAL INPUT MODE0, 818 cards
-
-   only one sample per call is supported
-*/
 static int pcl818_di_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
@@ -452,17 +486,13 @@ static int pcl818_do_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-/*
-==============================================================================
-   analog input interrupt mode 1 & 3, 818 cards
-   one sample per interrupt version
-*/
 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
-	unsigned char low;
+	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int chan;
 	int timeout = 50;	/* wait max 50us */
 
 	while (timeout--) {
@@ -472,22 +502,21 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
 	}
 	outb(0, dev->iobase + PCL818_STATUS);	/* clear INT request */
 	comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
-	pcl818_ai_cancel(dev, s);
+	s->cancel(dev, s);
 	s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 	comedi_event(dev, s);
 	return IRQ_HANDLED;
 
 conv_finish:
-	low = inb(dev->iobase + PCL818_AD_LO);
-	comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));	/*  get one sample */
+	comedi_buf_put(s->async, pcl818_ai_get_sample(dev, s, &chan));
 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
 
-	if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
+	if (chan != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {
 		dev_dbg(dev->class_dev,
 			"A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
-			(low & 0xf),
+			chan,
 			devpriv->act_chanlist[devpriv->act_chanlist_pos]);
-		pcl818_ai_cancel(dev, s);
+		s->cancel(dev, s);
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
@@ -497,14 +526,14 @@ conv_finish:
 		devpriv->act_chanlist_pos = 0;
 
 	s->async->cur_chan++;
-	if (s->async->cur_chan >= devpriv->ai_n_chan) {
+	if (s->async->cur_chan >= cmd->chanlist_len) {
 		s->async->cur_chan = 0;
 		devpriv->ai_act_scan--;
 	}
 
 	if (!devpriv->neverending_ai) {
 		if (devpriv->ai_act_scan == 0) {	/* all data sampled */
-			pcl818_ai_cancel(dev, s);
+			s->cancel(dev, s);
 			s->async->events |= COMEDI_CB_EOA;
 		}
 	}
@@ -512,15 +541,12 @@ conv_finish:
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-   analog input dma mode 1 & 3, 818 cards
-*/
 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	int i, len, bufptr;
 	unsigned long flags;
 	unsigned short *ptr;
@@ -532,13 +558,10 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 		flags = claim_dma_lock();
 		set_dma_addr(devpriv->dma,
 			     devpriv->hwdmaptr[devpriv->next_dma_buf]);
-		if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
-			set_dma_count(devpriv->dma,
-				      devpriv->hwdmasize[devpriv->
-							 next_dma_buf]);
-		} else {
+		if (devpriv->dma_runs_to_end || devpriv->neverending_ai)
+			set_dma_count(devpriv->dma, devpriv->hwdmasize);
+		else
 			set_dma_count(devpriv->dma, devpriv->last_dma_run);
-		}
 		release_dma_lock(flags);
 		enable_dma(devpriv->dma);
 	}
@@ -547,7 +570,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
 	ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
 
-	len = devpriv->hwdmasize[0] >> 1;
+	len = devpriv->hwdmasize >> 1;
 	bufptr = 0;
 
 	for (i = 0; i < len; i++) {
@@ -557,7 +580,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 				(ptr[bufptr] & 0xf),
 				devpriv->act_chanlist[devpriv->act_chanlist_pos],
 				devpriv->act_chanlist_pos);
-			pcl818_ai_cancel(dev, s);
+			s->cancel(dev, s);
 			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 			comedi_event(dev, s);
 			return IRQ_HANDLED;
@@ -570,14 +593,14 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 			devpriv->act_chanlist_pos = 0;
 
 		s->async->cur_chan++;
-		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+		if (s->async->cur_chan >= cmd->chanlist_len) {
 			s->async->cur_chan = 0;
 			devpriv->ai_act_scan--;
 		}
 
 		if (!devpriv->neverending_ai)
 			if (devpriv->ai_act_scan == 0) {	/* all data sampled */
-				pcl818_ai_cancel(dev, s);
+				s->cancel(dev, s);
 				s->async->events |= COMEDI_CB_EOA;
 				comedi_event(dev, s);
 				return IRQ_HANDLED;
@@ -589,15 +612,12 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-   analog input interrupt mode 1 & 3, 818HD/HG cards
-*/
 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	int i, len;
 	unsigned char lo;
 
@@ -607,7 +627,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 
 	if (lo & 4) {
 		comedi_error(dev, "A/D mode1/3 FIFO overflow!");
-		pcl818_ai_cancel(dev, s);
+		s->cancel(dev, s);
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
@@ -615,7 +635,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 
 	if (lo & 1) {
 		comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
-		pcl818_ai_cancel(dev, s);
+		s->cancel(dev, s);
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
@@ -633,7 +653,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 				"A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
 				(lo & 0xf),
 				devpriv->act_chanlist[devpriv->act_chanlist_pos]);
-			pcl818_ai_cancel(dev, s);
+			s->cancel(dev, s);
 			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 			comedi_event(dev, s);
 			return IRQ_HANDLED;
@@ -646,14 +666,14 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 			devpriv->act_chanlist_pos = 0;
 
 		s->async->cur_chan++;
-		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+		if (s->async->cur_chan >= cmd->chanlist_len) {
 			s->async->cur_chan = 0;
 			devpriv->ai_act_scan--;
 		}
 
 		if (!devpriv->neverending_ai)
 			if (devpriv->ai_act_scan == 0) {	/* all data sampled */
-				pcl818_ai_cancel(dev, s);
+				s->cancel(dev, s);
 				s->async->events |= COMEDI_CB_EOA;
 				comedi_event(dev, s);
 				return IRQ_HANDLED;
@@ -665,21 +685,18 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-/*
-==============================================================================
-    INT procedure
-*/
 static irqreturn_t interrupt_pcl818(int irq, void *d)
 {
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
 
 	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
 		return IRQ_HANDLED;
 	}
 
-	if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
+	if (devpriv->ai_cmd_running && devpriv->irq_was_now_closed) {
 		if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
 						 devpriv->ai_act_scan > 0)) &&
 		    (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
@@ -691,7 +708,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 			 */
 			devpriv->ai_act_scan = 0;
 			devpriv->neverending_ai = 0;
-			pcl818_ai_cancel(dev, dev->read_subdev);
+			s->cancel(dev, s);
 		}
 
 		outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
@@ -709,18 +726,13 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 	case INT_TYPE_AI1_FIFO:
 	case INT_TYPE_AI3_FIFO:
 		return interrupt_pcl818_ai_mode13_fifo(irq, d);
-#ifdef PCL818_MODE13_AO
-	case INT_TYPE_AO1_INT:
-	case INT_TYPE_AO3_INT:
-		return interrupt_pcl818_ao_mode13_int(irq, d);
-#endif
 	default:
 		break;
 	}
 
 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
 
-	if (!devpriv->irq_blocked || !devpriv->ai_mode) {
+	if (!devpriv->ai_cmd_running || !devpriv->ai_mode) {
 		comedi_error(dev, "bad IRQ!");
 		return IRQ_NONE;
 	}
@@ -729,26 +741,23 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 	return IRQ_NONE;
 }
 
-/*
-==============================================================================
-   ANALOG INPUT MODE 1 or 3 DMA , 818 cards
-*/
 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 				    struct comedi_subdevice *s)
 {
 	struct pcl818_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int flags;
 	unsigned int bytes;
 
 	disable_dma(devpriv->dma);	/*  disable dma */
-	bytes = devpriv->hwdmasize[0];
+	bytes = devpriv->hwdmasize;
 	if (!devpriv->neverending_ai) {
-		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	/*  how many */
-		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	/*  how many DMA pages we must fiil */
-		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	/* on last dma transfer must be moved */
+		bytes = cmd->chanlist_len * cmd->stop_arg * sizeof(short);
+		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize;
+		devpriv->last_dma_run = bytes % devpriv->hwdmasize;
 		devpriv->dma_runs_to_end--;
 		if (devpriv->dma_runs_to_end >= 0)
-			bytes = devpriv->hwdmasize[0];
+			bytes = devpriv->hwdmasize;
 	}
 
 	devpriv->next_dma_buf = 0;
@@ -769,58 +778,32 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 	}
 }
 
-/*
-==============================================================================
-   ANALOG INPUT MODE 1 or 3, 818 cards
-*/
 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
-	int divisor1 = 0, divisor2 = 0;
 	unsigned int seglen;
 
-	if (devpriv->irq_blocked)
+	if (devpriv->ai_cmd_running)
 		return -EBUSY;
 
-	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+	pcl818_start_pacer(dev, false);
 
-	seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
-				    devpriv->ai_n_chan);
+	seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
 	if (seglen < 1)
 		return -EINVAL;
-	setup_channel_list(dev, s, devpriv->ai_chanlist,
-			   devpriv->ai_n_chan, seglen);
+	setup_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len, seglen);
 
 	udelay(1);
 
-	devpriv->ai_act_scan = devpriv->ai_scans;
+	devpriv->ai_act_scan = cmd->stop_arg;
 	devpriv->ai_act_chan = 0;
-	devpriv->irq_blocked = 1;
+	devpriv->ai_cmd_running = 1;
 	devpriv->irq_was_now_closed = 0;
-	devpriv->neverending_ai = 0;
 	devpriv->act_chanlist_pos = 0;
 	devpriv->dma_runs_to_end = 0;
 
-	if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
-		devpriv->neverending_ai = 1;	/* well, user want neverending */
-
-	if (mode == 1) {
-		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
-					  &divisor1, &divisor2,
-					  &cmd->convert_arg,
-					  TRIG_ROUND_NEAREST);
-		if (divisor1 == 1) {	/* PCL718/818 crash if any divisor is set to 1 */
-			divisor1 = 2;
-			divisor2 /= 2;
-		}
-		if (divisor2 == 1) {
-			divisor2 = 2;
-			divisor1 /= 2;
-		}
-	}
-
 	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
 
 	switch (devpriv->dma) {
@@ -857,35 +840,11 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 		}
 	}
 
-	start_pacer(dev, mode, divisor1, divisor2);
+	pcl818_start_pacer(dev, mode == 1);
 
 	return 0;
 }
 
-/*
-==============================================================================
- Start/stop pacer onboard pacer
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
-			unsigned int divisor1, unsigned int divisor2)
-{
-	outb(0xb4, dev->iobase + PCL818_CTRCTL);
-	outb(0x74, dev->iobase + PCL818_CTRCTL);
-	udelay(1);
-
-	if (mode == 1) {
-		outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
-		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
-		outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
-		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
-	}
-}
-
-/*
-==============================================================================
- Check if channel list from user is builded correctly
- If it's ok, then program scan/gain logic
-*/
 static int check_channel_list(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      unsigned int *chanlist, unsigned int n_chan)
@@ -966,10 +925,6 @@ static void setup_channel_list(struct comedi_device *dev,
 	     dev->iobase + PCL818_MUX);
 }
 
-/*
-==============================================================================
- Check if board is switched to SE (1) or DIFF(0) mode
-*/
 static int check_single_ended(unsigned int port)
 {
 	if (inb(port + PCL818_STATUS) & 0x20)
@@ -977,16 +932,13 @@ static int check_single_ended(unsigned int port)
 	return 0;
 }
 
-/*
-==============================================================================
-*/
 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		      struct comedi_cmd *cmd)
 {
 	const struct pcl818_board *board = comedi_board(dev);
 	struct pcl818_private *devpriv = dev->private;
 	int err = 0;
-	int tmp, divisor1 = 0, divisor2 = 0;
+	int tmp;
 
 	/* Step 1 : check if triggers are trivially valid */
 
@@ -1035,7 +987,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
 		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
-					  &divisor1, &divisor2,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
 					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < board->ns_min)
 			cmd->convert_arg = board->ns_min;
@@ -1057,30 +1010,21 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	return 0;
 }
 
-/*
-==============================================================================
-*/
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int retval;
 
-	devpriv->ai_n_chan = cmd->chanlist_len;
-	devpriv->ai_chanlist = cmd->chanlist;
-	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
-	devpriv->ai_timer1 = 0;
-	devpriv->ai_timer2 = 0;
 
 	if (cmd->stop_src == TRIG_COUNT)
-		devpriv->ai_scans = cmd->stop_arg;
+		devpriv->neverending_ai = 0;
 	else
-		devpriv->ai_scans = 0;
+		devpriv->neverending_ai = 1;
 
 	if (cmd->scan_begin_src == TRIG_FOLLOW) {	/*  mode 1, 3 */
 		if (cmd->convert_src == TRIG_TIMER) {	/*  mode 1 */
-			devpriv->ai_timer1 = cmd->convert_arg;
 			retval = pcl818_ai_cmd_mode(1, dev, s);
 			return retval;
 		}
@@ -1092,16 +1036,12 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	return -1;
 }
 
-/*
-==============================================================================
- cancel any mode 1-4 AI
-*/
 static int pcl818_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
 	struct pcl818_private *devpriv = dev->private;
 
-	if (devpriv->irq_blocked > 0) {
+	if (devpriv->ai_cmd_running) {
 		devpriv->irq_was_now_closed = 1;
 
 		switch (devpriv->ai_mode) {
@@ -1118,16 +1058,11 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
 		case INT_TYPE_AI3_INT:
 		case INT_TYPE_AI1_FIFO:
 		case INT_TYPE_AI3_FIFO:
-#ifdef PCL818_MODE13_AO
-		case INT_TYPE_AO1_INT:
-		case INT_TYPE_AO3_INT:
-#endif
 			outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
 			udelay(1);
-			start_pacer(dev, -1, 0, 0);
+			pcl818_start_pacer(dev, false);
 			outb(0, dev->iobase + PCL818_AD_LO);
-			inb(dev->iobase + PCL818_AD_LO);
-			inb(dev->iobase + PCL818_AD_HI);
+			pcl818_ai_get_sample(dev, s, NULL);
 			outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
 			outb(0, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
 			if (devpriv->usefifo) {	/*  FIFO shutdown */
@@ -1135,8 +1070,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
 				outb(0, dev->iobase + PCL818_FI_FLUSH);
 				outb(0, dev->iobase + PCL818_FI_ENABLE);
 			}
-			devpriv->irq_blocked = 0;
-			devpriv->last_int_sub = s;
+			devpriv->ai_cmd_running = 0;
 			devpriv->neverending_ai = 0;
 			devpriv->ai_mode = 0;
 			devpriv->irq_was_now_closed = 0;
@@ -1148,37 +1082,11 @@ end:
 	return 0;
 }
 
-/*
-==============================================================================
- chech for PCL818
-*/
-static int pcl818_check(unsigned long iobase)
-{
-	outb(0x00, iobase + PCL818_MUX);
-	udelay(1);
-	if (inb(iobase + PCL818_MUX) != 0x00)
-		return 1;	/* there isn't card */
-	outb(0x55, iobase + PCL818_MUX);
-	udelay(1);
-	if (inb(iobase + PCL818_MUX) != 0x55)
-		return 1;	/* there isn't card */
-	outb(0x00, iobase + PCL818_MUX);
-	udelay(1);
-	outb(0x18, iobase + PCL818_CONTROL);
-	udelay(1);
-	if (inb(iobase + PCL818_CONTROL) != 0x18)
-		return 1;	/* there isn't card */
-	return 0;		/*  ok, card exist */
-}
-
-/*
-==============================================================================
- reset whole PCL-818 cards
-*/
 static void pcl818_reset(struct comedi_device *dev)
 {
 	const struct pcl818_board *board = comedi_board(dev);
 	struct pcl818_private *devpriv = dev->private;
+	unsigned long timer_base = dev->iobase + PCL818_TIMER_BASE;
 
 	if (devpriv->usefifo) {	/*  FIFO shutdown */
 		outb(0, dev->iobase + PCL818_FI_INTCLR);
@@ -1195,9 +1103,12 @@ static void pcl818_reset(struct comedi_device *dev)
 	outb(0, dev->iobase + PCL818_CNTENABLE);
 	outb(0, dev->iobase + PCL818_MUX);
 	outb(0, dev->iobase + PCL818_CLRINT);
-	outb(0xb0, dev->iobase + PCL818_CTRCTL);	/* Stop pacer */
-	outb(0x70, dev->iobase + PCL818_CTRCTL);
-	outb(0x30, dev->iobase + PCL818_CTRCTL);
+
+	/* Stop pacer */
+	i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 1, I8254_MODE0 | I8254_BINARY);
+	i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY);
+
 	if (board->is_818) {
 		outb(0, dev->iobase + PCL818_RANGE);
 	} else {
@@ -1206,145 +1117,167 @@ static void pcl818_reset(struct comedi_device *dev)
 	}
 }
 
+static void pcl818_set_ai_range_table(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_devconfig *it)
+{
+	const struct pcl818_board *board = comedi_board(dev);
+
+	/* default to the range table from the boardinfo */
+	s->range_table = board->ai_range_type;
+
+	/* now check the user config option based on the boardtype */
+	if (board->is_818) {
+		if (it->options[4] == 1 || it->options[4] == 10) {
+			/* secondary range list jumper selectable */
+			s->range_table = &range_pcl818l_h_ai;
+		}
+	} else {
+		switch (it->options[4]) {
+		case 0:
+			s->range_table = &range_bipolar10;
+			break;
+		case 1:
+			s->range_table = &range_bipolar5;
+			break;
+		case 2:
+			s->range_table = &range_bipolar2_5;
+			break;
+		case 3:
+			s->range_table = &range718_bipolar1;
+			break;
+		case 4:
+			s->range_table = &range718_bipolar0_5;
+			break;
+		case 6:
+			s->range_table = &range_unipolar10;
+			break;
+		case 7:
+			s->range_table = &range_unipolar5;
+			break;
+		case 8:
+			s->range_table = &range718_unipolar2;
+			break;
+		case 9:
+			s->range_table = &range718_unipolar1;
+			break;
+		default:
+			s->range_table = &range_unknown;
+			break;
+		}
+	}
+}
+
+static int pcl818_check(struct comedi_device *dev)
+{
+	/* the MUX register should return the same value written */
+	outb(0x00, dev->iobase + PCL818_MUX);
+	if (inb(dev->iobase + PCL818_MUX) != 0x00)
+		return -ENODEV;
+	outb(0x55, dev->iobase + PCL818_MUX);
+	if (inb(dev->iobase + PCL818_MUX) != 0x55)
+		return -ENODEV;
+
+	/* reset the MUX register to a known state */
+	outb(0x00, dev->iobase + PCL818_MUX);
+
+	/* the CONTROL register should return the same value written */
+	outb(0x18, dev->iobase + PCL818_CONTROL);
+	if (inb(dev->iobase + PCL818_CONTROL) != 0x18)
+		return -ENODEV;
+
+	/* reset the CONTROL register to a known state */
+	outb(0x00, dev->iobase + PCL818_CONTROL);
+
+	return 0;
+}
+
 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl818_board *board = comedi_board(dev);
 	struct pcl818_private *devpriv;
-	int ret;
-	int dma;
-	unsigned long pages;
 	struct comedi_subdevice *s;
+	int ret;
+	int i;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
-	devpriv->io_range = board->io_range;
-	if ((board->fifo) && (it->options[2] == -1)) {
-		/*  we've board with FIFO and we want to use FIFO */
-		devpriv->io_range = PCLx1xFIFO_RANGE;
+	/* should we use the FIFO? */
+	if (board->has_fifo && it->options[2] == -1)
 		devpriv->usefifo = 1;
-	}
-	ret = comedi_request_region(dev, it->options[0], devpriv->io_range);
+
+	ret = comedi_request_region(dev, it->options[0],
+				    devpriv->usefifo ? 0x20 : 0x10);
 	if (ret)
 		return ret;
 
-	if (pcl818_check(dev->iobase)) {
-		comedi_error(dev, "I can't detect board. FAIL!\n");
-		return -EIO;
-	}
+	ret = pcl818_check(dev);
+	if (ret)
+		return ret;
 
-	if ((1 << it->options[1]) & board->IRQbits) {
+	/* we can use IRQ 2-7 for async command support */
+	if (it->options[1] >= 2 && it->options[1] <= 7) {
 		ret = request_irq(it->options[1], interrupt_pcl818, 0,
 				  dev->board_name, dev);
 		if (ret == 0)
 			dev->irq = it->options[1];
 	}
 
-	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
-	devpriv->ai_mode = 0;	/* mode of irq */
-
-	/* grab our DMA */
-	dma = 0;
-	devpriv->dma = dma;
-	if (!dev->irq)
-		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
-	if (board->DMAbits != 0) {	/* board support DMA */
-		dma = it->options[2];
-		if (dma < 1)
-			goto no_dma;	/* DMA disabled */
-		if (((1 << dma) & board->DMAbits) == 0) {
+	/* we need an IRQ to do DMA on channel 3 or 1 */
+	if (dev->irq && board->has_dma &&
+	    (it->options[2] == 3 || it->options[2] == 1)) {
+		ret = request_dma(it->options[2], dev->board_name);
+		if (ret) {
 			dev_err(dev->class_dev,
-				"DMA is out of allowed range, FAIL!\n");
-			return -EINVAL;	/* Bad DMA */
-		}
-		ret = request_dma(dma, dev->board_name);
-		if (ret)
-			return -EBUSY;	/* DMA isn't free */
-		devpriv->dma = dma;
-		pages = 2;	/* we need 16KB */
-		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
-		if (!devpriv->dmabuf[0])
-			/* maybe experiment with try_to_free_pages() will help .... */
-			return -EBUSY;	/* no buffer :-( */
-		devpriv->dmapages[0] = pages;
-		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
-		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
-		devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
-		if (!devpriv->dmabuf[1])
+				"unable to request DMA channel %d\n",
+				it->options[2]);
 			return -EBUSY;
-		devpriv->dmapages[1] = pages;
-		devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
-		devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
-	}
+		}
+		devpriv->dma = it->options[2];
 
-no_dma:
+		devpriv->dmapages = 2;	/* we need 16KB */
+		devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE;
+
+		for (i = 0; i < 2; i++) {
+			unsigned long dmabuf;
+
+			dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages);
+			if (!dmabuf)
+				return -ENOMEM;
+
+			devpriv->dmabuf[i] = dmabuf;
+			devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf);
+		}
+	}
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
 		return ret;
 
 	s = &dev->subdevices[0];
-	if (!board->n_aichan_se) {
-		s->type = COMEDI_SUBD_UNUSED;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE;
+	if (check_single_ended(dev->iobase)) {
+		s->n_chan	= 16;
+		s->subdev_flags	|= SDF_COMMON | SDF_GROUND;
 	} else {
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags = SDF_READABLE;
-		if (check_single_ended(dev->iobase)) {
-			s->n_chan = board->n_aichan_se;
-			s->subdev_flags |= SDF_COMMON | SDF_GROUND;
-		} else {
-			s->n_chan = board->n_aichan_diff;
-			s->subdev_flags |= SDF_DIFF;
-		}
-		s->maxdata = board->ai_maxdata;
-		s->range_table = board->ai_range_type;
-		s->insn_read = pcl818_ai_insn_read;
-		if (dev->irq) {
-			dev->read_subdev = s;
-			s->subdev_flags |= SDF_CMD_READ;
-			s->len_chanlist = s->n_chan;
-			s->do_cmdtest = ai_cmdtest;
-			s->do_cmd = ai_cmd;
-			s->cancel = pcl818_ai_cancel;
-		}
-		if (board->is_818) {
-			if ((it->options[4] == 1) || (it->options[4] == 10))
-				s->range_table = &range_pcl818l_h_ai;	/*  secondary range list jumper selectable */
-		} else {
-			switch (it->options[4]) {
-			case 0:
-				s->range_table = &range_bipolar10;
-				break;
-			case 1:
-				s->range_table = &range_bipolar5;
-				break;
-			case 2:
-				s->range_table = &range_bipolar2_5;
-				break;
-			case 3:
-				s->range_table = &range718_bipolar1;
-				break;
-			case 4:
-				s->range_table = &range718_bipolar0_5;
-				break;
-			case 6:
-				s->range_table = &range_unipolar10;
-				break;
-			case 7:
-				s->range_table = &range_unipolar5;
-				break;
-			case 8:
-				s->range_table = &range718_unipolar2;
-				break;
-			case 9:
-				s->range_table = &range718_unipolar1;
-				break;
-			default:
-				s->range_table = &range_unknown;
-				break;
-			}
-		}
+		s->n_chan	= 8;
+		s->subdev_flags	|= SDF_DIFF;
+	}
+	s->maxdata	= 0x0fff;
+
+	pcl818_set_ai_range_table(dev, s, it);
+
+	s->insn_read	= pcl818_ai_insn_read;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= s->n_chan;
+		s->do_cmdtest	= ai_cmdtest;
+		s->do_cmd	= ai_cmd;
+		s->cancel	= pcl818_ai_cancel;
 	}
 
 	s = &dev->subdevices[1];
@@ -1354,8 +1287,8 @@ no_dma:
 		s->type = COMEDI_SUBD_AO;
 		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
 		s->n_chan = board->n_aochan;
-		s->maxdata = board->ao_maxdata;
-		s->range_table = board->ao_range_type;
+		s->maxdata = 0x0fff;
+		s->range_table = &range_unipolar5;
 		s->insn_read = pcl818_ao_insn_read;
 		s->insn_write = pcl818_ao_insn_write;
 		if (board->is_818) {
@@ -1371,29 +1304,23 @@ no_dma:
 		}
 	}
 
+	/* Digital Input subdevice */
 	s = &dev->subdevices[2];
-	if (!board->n_dichan) {
-		s->type = COMEDI_SUBD_UNUSED;
-	} else {
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE;
-		s->n_chan = board->n_dichan;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = pcl818_di_insn_bits;
-	}
-
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= pcl818_di_insn_bits;
+
+	/* Digital Output subdevice */
 	s = &dev->subdevices[3];
-	if (!board->n_dochan) {
-		s->type = COMEDI_SUBD_UNUSED;
-	} else {
-		s->type = COMEDI_SUBD_DO;
-		s->subdev_flags = SDF_WRITABLE;
-		s->n_chan = board->n_dochan;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = pcl818_do_insn_bits;
-	}
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= pcl818_do_insn_bits;
 
 	/* select 1/10MHz oscilator */
 	if ((it->options[3] == 0) || (it->options[3] == 10))
@@ -1424,38 +1351,13 @@ static void pcl818_detach(struct comedi_device *dev)
 		if (devpriv->dma)
 			free_dma(devpriv->dma);
 		if (devpriv->dmabuf[0])
-			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
+			free_pages(devpriv->dmabuf[0], devpriv->dmapages);
 		if (devpriv->dmabuf[1])
-			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
+			free_pages(devpriv->dmabuf[1], devpriv->dmapages);
 	}
 	comedi_legacy_detach(dev);
 }
 
-static const struct pcl818_board boardtypes[] = {
-	{"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 0, 1},
-	{"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 0, 1},
-	{"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 1, 1},
-	{"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 1, 1},
-	{"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 0, 1},
-	{"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 0, 0},
-	/* pcm3718 */
-	{"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
-	 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
-	 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
-};
-
 static struct comedi_driver pcl818_driver = {
 	.driver_name	= "pcl818",
 	.module		= THIS_MODULE,
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index f4a49bd649f0..53e73737a906 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -225,8 +225,10 @@ static int pcm3724_attach(struct comedi_device *dev,
 
 	for (i = 0; i < dev->n_subdevices; i++) {
 		s = &dev->subdevices[i];
-		subdev_8255_init(dev, s, subdev_8255_cb,
-				 (unsigned long)(dev->iobase + SIZE_8255 * i));
+		ret = subdev_8255_init(dev, s, subdev_8255_cb,
+				       dev->iobase + SIZE_8255 * i);
+		if (ret)
+			return ret;
 		s->insn_config = subdev_3724_insn_config;
 	}
 	return 0;
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index fe482fdd512e..87c61d9b11da 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -61,18 +61,17 @@ static const struct pcmad_board_struct pcmad_boards[] = {
 	},
 };
 
-#define TIMEOUT	100
-
-static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
-				 int timeout)
+static int pcmad_ai_eoc(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn,
+			unsigned long context)
 {
-	int i;
+	unsigned int status;
 
-	for (i = 0; i < timeout; i++) {
-		if ((inb(dev->iobase + PCMAD_STATUS) & 0x3) == 0x3)
-			return 0;
-	}
-	return -ETIME;
+	status = inb(dev->iobase + PCMAD_STATUS);
+	if ((status & 0x3) == 0x3)
+		return 0;
+	return -EBUSY;
 }
 
 static int pcmad_ai_insn_read(struct comedi_device *dev,
@@ -89,7 +88,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 	for (i = 0; i < insn->n; i++) {
 		outb(chan, dev->iobase + PCMAD_CONVERT);
 
-		ret = pcmad_ai_wait_for_eoc(dev, TIMEOUT);
+		ret = comedi_timeout(dev, s, insn, pcmad_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index c388f7f32227..e89bca845349 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -589,16 +589,17 @@ static int pcmmio_cmdtest(struct comedi_device *dev,
 	return 0;
 }
 
-static int pcmmio_ai_wait_for_eoc(unsigned long iobase, unsigned int timeout)
+static int pcmmio_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
 {
 	unsigned char status;
 
-	while (timeout--) {
-		status = inb(iobase + PCMMIO_AI_STATUS_REG);
-		if (status & PCMMIO_AI_STATUS_DATA_READY)
-			return 0;
-	}
-	return -ETIME;
+	status = inb(dev->iobase + PCMMIO_AI_STATUS_REG);
+	if (status & PCMMIO_AI_STATUS_DATA_READY)
+		return 0;
+	return -EBUSY;
 }
 
 static int pcmmio_ai_insn_read(struct comedi_device *dev,
@@ -643,7 +644,8 @@ static int pcmmio_ai_insn_read(struct comedi_device *dev,
 	cmd |= PCMMIO_AI_CMD_RANGE(range);
 
 	outb(cmd, iobase + PCMMIO_AI_CMD_REG);
-	ret = pcmmio_ai_wait_for_eoc(iobase, 100000);
+
+	ret = comedi_timeout(dev, s, insn, pcmmio_ai_eoc, 0);
 	if (ret)
 		return ret;
 
@@ -652,7 +654,8 @@ static int pcmmio_ai_insn_read(struct comedi_device *dev,
 
 	for (i = 0; i < insn->n; i++) {
 		outb(cmd, iobase + PCMMIO_AI_CMD_REG);
-		ret = pcmmio_ai_wait_for_eoc(iobase, 100000);
+
+		ret = comedi_timeout(dev, s, insn, pcmmio_ai_eoc, 0);
 		if (ret)
 			return ret;
 
@@ -684,16 +687,17 @@ static int pcmmio_ao_insn_read(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int pcmmio_ao_wait_for_eoc(unsigned long iobase, unsigned int timeout)
+static int pcmmio_ao_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
 {
 	unsigned char status;
 
-	while (timeout--) {
-		status = inb(iobase + PCMMIO_AO_STATUS_REG);
-		if (status & PCMMIO_AO_STATUS_DATA_READY)
-			return 0;
-	}
-	return -ETIME;
+	status = inb(dev->iobase + PCMMIO_AO_STATUS_REG);
+	if (status & PCMMIO_AO_STATUS_DATA_READY)
+		return 0;
+	return -EBUSY;
 }
 
 static int pcmmio_ao_insn_write(struct comedi_device *dev,
@@ -726,7 +730,8 @@ static int pcmmio_ao_insn_write(struct comedi_device *dev,
 	outb(PCMMIO_AO_LSB_SPAN(range), iobase + PCMMIO_AO_LSB_REG);
 	outb(0, iobase + PCMMIO_AO_MSB_REG);
 	outb(cmd | PCMMIO_AO_CMD_WR_SPAN_UPDATE, iobase + PCMMIO_AO_CMD_REG);
-	ret = pcmmio_ao_wait_for_eoc(iobase, 100000);
+
+	ret = comedi_timeout(dev, s, insn, pcmmio_ao_eoc, 0);
 	if (ret)
 		return ret;
 
@@ -738,7 +743,8 @@ static int pcmmio_ao_insn_write(struct comedi_device *dev,
 		outb((val >> 8) & 0xff, iobase + PCMMIO_AO_MSB_REG);
 		outb(cmd | PCMMIO_AO_CMD_WR_CODE_UPDATE,
 		     iobase + PCMMIO_AO_CMD_REG);
-		ret = pcmmio_ao_wait_for_eoc(iobase, 100000);
+
+		ret = comedi_timeout(dev, s, insn, pcmmio_ao_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 0f026afde9be..cd3fdf973bdd 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -237,20 +237,6 @@
 /* The board support a channel list up to the FIFO length (1K or 8K) */
 #define RTD_MAX_CHANLIST	128	/* max channel list that we allow */
 
-/* tuning for ai/ao instruction done polling */
-#ifdef FAST_SPIN
-#define WAIT_QUIETLY		/* as nothing, spin on done bit */
-#define RTD_ADC_TIMEOUT	66000	/* 2 msec at 33mhz bus rate */
-#define RTD_DAC_TIMEOUT	66000
-#define RTD_DMA_TIMEOUT	33000	/* 1 msec */
-#else
-/* by delaying, power and electrical noise are reduced somewhat */
-#define WAIT_QUIETLY	udelay(1)
-#define RTD_ADC_TIMEOUT	2000	/* in usec */
-#define RTD_DAC_TIMEOUT	2000	/* in usec */
-#define RTD_DMA_TIMEOUT	1000	/* in usec */
-#endif
-
 /*======================================================================
   Board specific stuff
 ======================================================================*/
@@ -562,21 +548,27 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
 	return fifo_size;
 }
 
-/*
-  "instructions" read/write data in "one-shot" or "software-triggered"
-  mode (simplest case).
-  This doesn't use interrupts.
+static int rtd_ai_eoc(struct comedi_device *dev,
+		      struct comedi_subdevice *s,
+		      struct comedi_insn *insn,
+		      unsigned long context)
+{
+	struct rtd_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readl(devpriv->las0 + LAS0_ADC);
+	if (status & FS_ADC_NOT_EMPTY)
+		return 0;
+	return -EBUSY;
+}
 
-  Note, we don't do any settling delays.  Use a instruction list to
-  select, delay, then read.
- */
 static int rtd_ai_rinsn(struct comedi_device *dev,
 			struct comedi_subdevice *s, struct comedi_insn *insn,
 			unsigned int *data)
 {
 	struct rtd_private *devpriv = dev->private;
-	int n, ii;
-	int stat;
+	int ret;
+	int n;
 
 	/* clear any old fifo data */
 	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
@@ -593,14 +585,9 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 		/* trigger conversion */
 		writew(0, devpriv->las0 + LAS0_ADC);
 
-		for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
-			stat = readl(devpriv->las0 + LAS0_ADC);
-			if (stat & FS_ADC_NOT_EMPTY)	/* 1 -> not empty */
-				break;
-			WAIT_QUIETLY;
-		}
-		if (ii >= RTD_ADC_TIMEOUT)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, rtd_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
@@ -1116,9 +1103,22 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
-/*
-  Output one (or more) analog values to a single port as fast as possible.
-*/
+static int rtd_ao_eoc(struct comedi_device *dev,
+		      struct comedi_subdevice *s,
+		      struct comedi_insn *insn,
+		      unsigned long context)
+{
+	struct rtd_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int bit = (chan == 0) ? FS_DAC1_NOT_EMPTY : FS_DAC2_NOT_EMPTY;
+	unsigned int status;
+
+	status = readl(devpriv->las0 + LAS0_ADC);
+	if (status & bit)
+		return 0;
+	return -EBUSY;
+}
+
 static int rtd_ao_winsn(struct comedi_device *dev,
 			struct comedi_subdevice *s, struct comedi_insn *insn,
 			unsigned int *data)
@@ -1127,6 +1127,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 	int range = CR_RANGE(insn->chanspec);
+	int ret;
 
 	/* Configure the output range (table index matches the range values) */
 	writew(range & 7, devpriv->las0 +
@@ -1136,8 +1137,6 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 	 * very useful, but that's how the interface is defined. */
 	for (i = 0; i < insn->n; ++i) {
 		int val = data[i] << 3;
-		int stat = 0;	/* initialize to avoid bogus warning */
-		int ii;
 
 		/* VERIFY: comedi range and offset conversions */
 
@@ -1157,16 +1156,9 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 
 		devpriv->ao_readback[chan] = data[i];
 
-		for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
-			stat = readl(devpriv->las0 + LAS0_ADC);
-			/* 1 -> not empty */
-			if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
-				    FS_DAC2_NOT_EMPTY))
-				break;
-			WAIT_QUIETLY;
-		}
-		if (ii >= RTD_DAC_TIMEOUT)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, rtd_ao_eoc, 0);
+		if (ret)
+			return ret;
 	}
 
 	/* return the number of samples read/written */
@@ -1382,8 +1374,6 @@ static int rtd_auto_attach(struct comedi_device *dev,
 	if (dev->irq)
 		writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + PLX_INTRCS_REG);
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index e1f3671ac056..bd447b2add7b 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -83,8 +83,6 @@
 
 #define RTI800_IOSIZE		0x10
 
-#define RTI800_AI_TIMEOUT	100
-
 static const struct comedi_lrange range_rti800_ai_10_bipolar = {
 	4, {
 		BIP_RANGE(10),
@@ -145,23 +143,21 @@ struct rti800_private {
 	unsigned char muxgain_bits;
 };
 
-static int rti800_ai_wait_for_conversion(struct comedi_device *dev,
-					 int timeout)
+static int rti800_ai_eoc(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned long context)
 {
 	unsigned char status;
-	int i;
 
-	for (i = 0; i < timeout; i++) {
-		status = inb(dev->iobase + RTI800_CSR);
-		if (status & RTI800_CSR_OVERRUN) {
-			outb(0, dev->iobase + RTI800_CLRFLAGS);
-			return -EIO;
-		}
-		if (status & RTI800_CSR_DONE)
-			return 0;
-		udelay(1);
+	status = inb(dev->iobase + RTI800_CSR);
+	if (status & RTI800_CSR_OVERRUN) {
+		outb(0, dev->iobase + RTI800_CLRFLAGS);
+		return -EOVERFLOW;
 	}
-	return -ETIME;
+	if (status & RTI800_CSR_DONE)
+		return 0;
+	return -EBUSY;
 }
 
 static int rti800_ai_insn_read(struct comedi_device *dev,
@@ -198,7 +194,8 @@ static int rti800_ai_insn_read(struct comedi_device *dev,
 
 	for (i = 0; i < insn->n; i++) {
 		outb(0, dev->iobase + RTI800_CONVERT);
-		ret = rti800_ai_wait_for_conversion(dev, RTI800_AI_TIMEOUT);
+
+		ret = comedi_timeout(dev, s, insn, rti800_ai_eoc, 0);
 		if (ret)
 			return ret;
 
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index 9950f59b1192..85d2b7a3c125 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -420,15 +420,28 @@ static int s526_ai_insn_config(struct comedi_device *dev,
 	return result;
 }
 
+static int s526_ai_eoc(struct comedi_device *dev,
+		       struct comedi_subdevice *s,
+		       struct comedi_insn *insn,
+		       unsigned long context)
+{
+	unsigned int status;
+
+	status = inw(dev->iobase + REG_ISR);
+	if (status & ISR_ADC_DONE)
+		return 0;
+	return -EBUSY;
+}
+
 static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
 	struct s526_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
-	int n, i;
+	int n;
 	unsigned short value;
 	unsigned int d;
-	unsigned int status;
+	int ret;
 
 	/* Set configured delay, enable channel for this channel only,
 	 * select "ADC read" channel, set "ADC start" bit. */
@@ -440,17 +453,12 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		/* trigger conversion */
 		outw(value, dev->iobase + REG_ADC);
 
-#define TIMEOUT 100
 		/* wait for conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			status = inw(dev->iobase + REG_ISR);
-			if (status & ISR_ADC_DONE) {
-				outw(ISR_ADC_DONE, dev->iobase + REG_ISR);
-				break;
-			}
-		}
-		if (i == TIMEOUT)
-			return -ETIMEDOUT;
+		ret = comedi_timeout(dev, s, insn, s526_ai_eoc, 0);
+		if (ret)
+			return ret;
+
+		outw(ISR_ADC_DONE, dev->iobase + REG_ISR);
 
 		/* read data */
 		d = inw(dev->iobase + REG_ADD);
@@ -604,7 +612,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->insn_bits = s526_dio_insn_bits;
 	s->insn_config = s526_dio_insn_config;
 
-	return 1;
+	return 0;
 }
 
 static struct comedi_driver s526_driver = {
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 19da1dbea494..5ba4b4ae6507 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1846,6 +1846,20 @@ static int s626_ai_rinsn(struct comedi_device *dev,
 }
 #endif
 
+static int s626_ai_eoc(struct comedi_device *dev,
+		       struct comedi_subdevice *s,
+		       struct comedi_insn *insn,
+		       unsigned long context)
+{
+	struct s626_private *devpriv = dev->private;
+	unsigned int status;
+
+	status = readl(devpriv->mmio + S626_P_PSR);
+	if (status & S626_PSR_GPIO2)
+		return 0;
+	return -EBUSY;
+}
+
 static int s626_ai_insn_read(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
@@ -1856,6 +1870,7 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 	uint16_t adc_spec = 0;
 	uint32_t gpio_image;
 	uint32_t tmp;
+	int ret;
 	int n;
 
 	/*
@@ -1897,8 +1912,9 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 		 */
 
 		/* 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 */
 		if (n != 0) {
@@ -2902,8 +2918,6 @@ static int s626_auto_attach(struct comedi_device *dev,
 
 	s626_initialize(dev);
 
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index 77e2059ff62e..39008cf30ecb 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -142,6 +142,29 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
 }
 
 /*
+ * This function doesn't require a particular form, this is just
+ * what happens to be used in some of the drivers. The comedi_timeout()
+ * helper uses this callback to check for the end-of-conversion while
+ * waiting for up to 1 second. This function should return 0 when the
+ * conversion is finished and -EBUSY to keep waiting. Any other errno
+ * will terminate comedi_timeout() and return that errno to the caller.
+ * If the timeout occurs, comedi_timeout() will return -ETIMEDOUT.
+ */
+static int skel_ai_eoc(struct comedi_device *dev,
+		       struct comedi_subdevice *s,
+		       struct comedi_insn *insn,
+		       unsigned long context)
+{
+	unsigned int status;
+
+	/* status = inb(dev->iobase + SKEL_STATUS); */
+	status = 1;
+	if (status)
+		return 0;
+	return -EBUSY;
+}
+
+/*
  * "instructions" read/write data in "one-shot" or "software-triggered"
  * mode.
  */
@@ -149,9 +172,9 @@ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
 	const struct skel_board *thisboard = comedi_board(dev);
-	int n, i;
+	int n;
 	unsigned int d;
-	unsigned int status;
+	int ret;
 
 	/* a typical programming sequence */
 
@@ -165,18 +188,10 @@ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		/* trigger conversion */
 		/* outw(0,dev->iobase + SKEL_CONVERT); */
 
-#define TIMEOUT 100
 		/* wait for conversion to end */
-		for (i = 0; i < TIMEOUT; i++) {
-			status = 1;
-			/* status = inb(dev->iobase + SKEL_STATUS); */
-			if (status)
-				break;
-		}
-		if (i == TIMEOUT) {
-			dev_warn(dev->class_dev, "ai timeout\n");
-			return -ETIMEDOUT;
-		}
+		ret = comedi_timeout(dev, s, insn, skel_ai_eoc, 0);
+		if (ret)
+			return ret;
 
 		/* read data */
 		/* d = inw(dev->iobase + SKEL_AI_DATA); */
@@ -456,8 +471,6 @@ static int skel_common_attach(struct comedi_device *dev)
 		s->type = COMEDI_SUBD_UNUSED;
 	}
 
-	dev_info(dev->class_dev, "skel: attached\n");
-
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index df22a78d2b7e..848c30801580 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -161,8 +161,7 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	outb(PCMR, CSCIR);
 	outb((inb(CSCDR) & 0xAA), CSCDR);
 
-	dev_info(dev->class_dev, "%s: attached\n", dev->board_name);
-	return 1;
+	return 0;
 }
 
 static void dnp_detach(struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 5f85c55c1109..d6fae11ee4e0 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -372,7 +372,7 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 	err |= cfc_check_trigger_src(&cmd->start_src,
 					TRIG_NOW | TRIG_EXT | TRIG_INT);
 	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-					TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+					TRIG_FOLLOW | TRIG_EXT);
 	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
 	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
@@ -424,9 +424,6 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp);
 	}
 
-	if (cmd->scan_begin_src == TRIG_TIMER)
-		err |= -EINVAL;
-
 	/* stop source */
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
@@ -514,36 +511,28 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 	 */
 	devpriv->ignore = PACKETS_TO_IGNORE;
 
-	if (cmd->chanlist_len > 0) {
-		gain = CR_RANGE(cmd->chanlist[0]);
-		for (i = 0; i < cmd->chanlist_len; ++i) {
-			chan = CR_CHAN(cmd->chanlist[i]);
-			if (chan != i) {
-				dev_err(dev->class_dev,
-					"channels are not consecutive\n");
-				up(&devpriv->sem);
-				return -EINVAL;
-			}
-			if ((gain != CR_RANGE(cmd->chanlist[i]))
-			    && (cmd->chanlist_len > 3)) {
-				dev_err(dev->class_dev,
-					"gain must be the same for all channels\n");
-				up(&devpriv->sem);
-				return -EINVAL;
-			}
-			if (i >= NUMCHANNELS) {
-				dev_err(dev->class_dev, "chanlist too long\n");
-				break;
-			}
+	gain = CR_RANGE(cmd->chanlist[0]);
+	for (i = 0; i < cmd->chanlist_len; ++i) {
+		chan = CR_CHAN(cmd->chanlist[i]);
+		if (chan != i) {
+			dev_err(dev->class_dev,
+				"channels are not consecutive\n");
+			up(&devpriv->sem);
+			return -EINVAL;
+		}
+		if ((gain != CR_RANGE(cmd->chanlist[i]))
+			&& (cmd->chanlist_len > 3)) {
+			dev_err(dev->class_dev,
+				"gain must be the same for all channels\n");
+			up(&devpriv->sem);
+			return -EINVAL;
+		}
+		if (i >= NUMCHANNELS) {
+			dev_err(dev->class_dev, "chanlist too long\n");
+			break;
 		}
 	}
 	steps = 0;
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		dev_err(dev->class_dev,
-			"scan_begin_src==TRIG_TIMER not valid\n");
-		up(&devpriv->sem);
-		return -EINVAL;
-	}
 	if (cmd->convert_src == TRIG_TIMER)
 		steps = (cmd->convert_arg * 30) / 1000;
 
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index 7dc5a18e69d4..8777f958c041 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -41,7 +41,8 @@ struct comedi_device *comedi_open(const char *filename)
 	if (strncmp(filename, "/dev/comedi", 11) != 0)
 		return NULL;
 
-	minor = simple_strtoul(filename + 11, NULL, 0);
+	if (kstrtouint(filename + 11, 0, &minor))
+		return NULL;
 
 	if (minor >= COMEDI_NUM_BOARD_MINORS)
 		return NULL;
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
index 8d0680d93684..4765d528279b 100644
--- a/drivers/staging/crystalhd/crystalhd_hw.c
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -433,10 +433,12 @@ static void crystalhd_rx_pkt_rel_call_back(void *context, void *data)
 }
 
 #define crystalhd_hw_delete_ioq(adp, q)		\
+do {						\
 	if (q) {				\
 		crystalhd_delete_dioq(adp, q);	\
 		q = NULL;			\
-	}
+	}					\
+} while (0)
 
 static void crystalhd_hw_delete_ioqs(struct crystalhd_hw *hw)
 {
@@ -1437,7 +1439,7 @@ static bool crystalhd_rx_list0_handler(struct crystalhd_hw *hw,
 		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
 	}
 
-	return (tmp_lsts != hw->rx_list_sts[0]);
+	return tmp_lsts != hw->rx_list_sts[0];
 }
 
 static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw,
@@ -1507,7 +1509,7 @@ static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw,
 		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
 	}
 
-	return (tmp_lsts != hw->rx_list_sts[1]);
+	return tmp_lsts != hw->rx_list_sts[1];
 }
 
 
diff --git a/drivers/staging/cxt1e1/functions.c b/drivers/staging/cxt1e1/functions.c
index 95218e283966..40dbe2c623c4 100644
--- a/drivers/staging/cxt1e1/functions.c
+++ b/drivers/staging/cxt1e1/functions.c
@@ -25,7 +25,8 @@
 #include "pmcc4.h"
 
 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
-    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+defined(CONFIG_SBE_HDLC_V7_MODULE) || \
+defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
 #define _v7_hdlc_  1
 #else
 #define _v7_hdlc_  0
@@ -33,9 +34,9 @@
 
 #if _v7_hdlc_
 #define V7(x) (x ## _v7)
-extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
-extern int  register_hdlc_device_v7 (hdlc_device *);
-extern int  unregister_hdlc_device_v7 (hdlc_device *);
+extern int  hdlc_netif_rx_v7(hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7(hdlc_device *);
+extern int  unregister_hdlc_device_v7(hdlc_device *);
 
 #else
 #define V7(x) x
@@ -53,49 +54,49 @@ extern int  drvr_state;
 
 #if 1
 u_int32_t
-pci_read_32 (u_int32_t *p)
+pci_read_32(u_int32_t *p)
 {
 #ifdef FLOW_DEBUG
-    u_int32_t   v;
+	u_int32_t   v;
 
-    FLUSH_PCI_READ ();
-    v = le32_to_cpu (*p);
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
-    return v;
+	FLUSH_PCI_READ();
+	v = le32_to_cpu(*p);
+	if (cxt1e1_log_level >= LOG_DEBUG)
+		pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
+	return v;
 #else
-    FLUSH_PCI_READ ();              /* */
-    return le32_to_cpu (*p);
+	FLUSH_PCI_READ();              /* */
+	return le32_to_cpu(*p);
 #endif
 }
 
 void
-pci_write_32 (u_int32_t *p, u_int32_t v)
+pci_write_32(u_int32_t *p, u_int32_t v)
 {
 #ifdef FLOW_DEBUG
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
+	if (cxt1e1_log_level >= LOG_DEBUG)
+		pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
 #endif
-    *p = cpu_to_le32 (v);
-    FLUSH_PCI_WRITE ();             /* This routine is called from routines
-                                     * which do multiple register writes
-                                     * which themselves need flushing between
-                                     * writes in order to guarantee write
-                                     * ordering.  It is less code-cumbersome
-                                     * to flush here-in then to investigate
-                                     * and code the many other register
-                                     * writing routines. */
+	*p = cpu_to_le32 (v);
+	FLUSH_PCI_WRITE();             /* This routine is called from routines
+					* which do multiple register writes
+					* which themselves need flushing between
+					* writes in order to guarantee write
+					* ordering.  It is less code-cumbersome
+					* to flush here-in then to investigate
+					* and code the many other register
+					* writing routines. */
 }
 #endif
 
 
 void
-pci_flush_write (ci_t *ci)
+pci_flush_write(ci_t *ci)
 {
-    volatile u_int32_t v;
+	volatile u_int32_t v;
 
     /* issue a PCI read to flush PCI write thru bridge */
-    v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
+	v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
 
     /*
      * return nothing, this just reads PCI bridge interface to flush
@@ -105,55 +106,53 @@ pci_flush_write (ci_t *ci)
 
 
 static void
-watchdog_func (unsigned long arg)
+watchdog_func(unsigned long arg)
 {
-    struct watchdog *wd = (void *) arg;
-
-    if (drvr_state != SBE_DRVR_AVAILABLE)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state);
-        return;
-    }
-    schedule_work (&wd->work);
-    mod_timer (&wd->h, jiffies + wd->ticks);
+	struct watchdog *wd = (void *) arg;
+
+	if (drvr_state != SBE_DRVR_AVAILABLE) {
+		if (cxt1e1_log_level >= LOG_MONITOR)
+			pr_warning("%s: drvr not available (%x)\n",
+				   __func__, drvr_state);
+		return;
+	}
+	schedule_work(&wd->work);
+	mod_timer(&wd->h, jiffies + wd->ticks);
 }
 
-int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec)
+int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *),
+		     void *c, int usec)
 {
-    wdp->func = f;
-    wdp->softc = c;
-    wdp->ticks = (HZ) * (usec / 1000) / 1000;
-    INIT_WORK(&wdp->work, (void *)f);
-    init_timer (&wdp->h);
-    {
-        ci_t       *ci = (ci_t *) c;
-
-        wdp->h.data = (unsigned long) &ci->wd;
-    }
-    wdp->h.function = watchdog_func;
-    return 0;
+	wdp->func = f;
+	wdp->softc = c;
+	wdp->ticks = (HZ) * (usec / 1000) / 1000;
+	INIT_WORK(&wdp->work, (void *)f);
+	init_timer(&wdp->h);
+	{
+		ci_t       *ci = (ci_t *) c;
+
+		wdp->h.data = (unsigned long) &ci->wd;
+	}
+	wdp->h.function = watchdog_func;
+	return 0;
 }
 
 void
-OS_uwait (int usec, char *description)
+OS_uwait(int usec, char *description)
 {
-    int         tmp;
-
-    if (usec >= 1000)
-    {
-        mdelay (usec / 1000);
-        /* now delay residual */
-        tmp = (usec / 1000) * 1000; /* round */
-        tmp = usec - tmp;           /* residual */
-        if (tmp)
-        {                           /* wait on residual */
-            udelay (tmp);
-        }
-    } else
-    {
-        udelay (usec);
-    }
+	int         tmp;
+
+	if (usec >= 1000) {
+		mdelay(usec / 1000);
+		/* now delay residual */
+		tmp = (usec / 1000) * 1000; /* round */
+		tmp = usec - tmp;           /* residual */
+		if (tmp) {                           /* wait on residual */
+			udelay(tmp);
+		}
+	} else {
+		udelay(usec);
+	}
 }
 
 /* dummy short delay routine called as a subroutine so that compiler
@@ -161,96 +160,95 @@ OS_uwait (int usec, char *description)
  */
 
 void
-OS_uwait_dummy (void)
+OS_uwait_dummy(void)
 {
 #ifndef USE_MAX_INT_DELAY
-    dummy++;
+	dummy++;
 #else
-    udelay (1);
+	udelay(1);
 #endif
 }
 
 
 void
-OS_sem_init (void *sem, int state)
+OS_sem_init(void *sem, int state)
 {
-    switch (state)
-    {
-        case SEM_TAKEN:
-		sema_init((struct semaphore *) sem, 0);
-        break;
-    case SEM_AVAILABLE:
+	switch (state) {
+	case SEM_TAKEN:
+	    sema_init((struct semaphore *) sem, 0);
+	    break;
+	case SEM_AVAILABLE:
 	    sema_init((struct semaphore *) sem, 1);
-        break;
-    default:                        /* otherwise, set sem.count to state's
-                                     * value */
-        sema_init (sem, state);
-        break;
-    }
+	    break;
+	default:                        /* otherwise, set sem.count to state's
+					* value */
+	    sema_init(sem, state);
+	    break;
+	}
 }
 
 
 int
-sd_line_is_ok (void *user)
+sd_line_is_ok(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    return netif_carrier_ok (ndev);
+	return netif_carrier_ok(ndev);
 }
 
 void
-sd_line_is_up (void *user)
+sd_line_is_up(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_on (ndev);
-    return;
+	netif_carrier_on(ndev);
+	return;
 }
 
 void
-sd_line_is_down (void *user)
+sd_line_is_down(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_off (ndev);
-    return;
+	netif_carrier_off(ndev);
+	return;
 }
 
 void
-sd_disable_xmit (void *user)
+sd_disable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+	struct net_device *dev = (struct net_device *) user;
 
-    netif_stop_queue (dev);
-    return;
+	netif_stop_queue(dev);
+	return;
 }
 
 void
-sd_enable_xmit (void *user)
+sd_enable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+	struct net_device *dev = (struct net_device *) user;
 
-    netif_wake_queue (dev);
-    return;
+	netif_wake_queue(dev);
+	return;
 }
 
 int
-sd_queue_stopped (void *user)
+sd_queue_stopped(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    return netif_queue_stopped (ndev);
+	return netif_queue_stopped(ndev);
 }
 
 void sd_recv_consume(void *token, size_t len, void *user)
 {
-    struct net_device *ndev = user;
-    struct sk_buff *skb = token;
+	struct net_device *ndev = user;
+	struct sk_buff *skb = token;
 
-    skb->dev = ndev;
-    skb_put (skb, len);
-    skb->protocol = hdlc_type_trans(skb, ndev);
-    netif_rx(skb);
+	skb->dev = ndev;
+	skb_put(skb, len);
+	skb->protocol = hdlc_type_trans(skb, ndev);
+	netif_rx(skb);
 }
 
 
@@ -263,86 +261,76 @@ void sd_recv_consume(void *token, size_t len, void *user)
 
 extern ci_t *CI;                /* dummy pointer to board ZERO's data */
 void
-VMETRO_TRACE (void *x)
+VMETRO_TRIGGER(ci_t *ci, int x)
 {
-    u_int32_t   y = (u_int32_t) x;
-
-    pci_write_32 ((u_int32_t *) &CI->cpldbase->leds, y);
-}
-
-
-void
-VMETRO_TRIGGER (ci_t *ci, int x)
-{
-    struct s_comet_reg    *comet;
-    volatile u_int32_t data;
-
-    comet = ci->port[0].cometbase;  /* default to COMET # 0 */
-
-    switch (x)
-    {
-    default:
-    case 0:
-        data = pci_read_32 ((u_int32_t *) &comet->__res24);     /* 0x90 */
-        break;
-    case 1:
-        data = pci_read_32 ((u_int32_t *) &comet->__res25);     /* 0x94 */
-        break;
-    case 2:
-        data = pci_read_32 ((u_int32_t *) &comet->__res26);     /* 0x98 */
-        break;
-    case 3:
-        data = pci_read_32 ((u_int32_t *) &comet->__res27);     /* 0x9C */
-        break;
-    case 4:
-        data = pci_read_32 ((u_int32_t *) &comet->__res88);     /* 0x220 */
-        break;
-    case 5:
-        data = pci_read_32 ((u_int32_t *) &comet->__res89);     /* 0x224 */
-        break;
-    case 6:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8A);     /* 0x228 */
-        break;
-    case 7:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8B);     /* 0x22C */
-        break;
-    case 8:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA0);     /* 0x280 */
-        break;
-    case 9:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA1);     /* 0x284 */
-        break;
-    case 10:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA2);     /* 0x288 */
-        break;
-    case 11:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA3);     /* 0x28C */
-        break;
-    case 12:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA4);     /* 0x290 */
-        break;
-    case 13:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA5);     /* 0x294 */
-        break;
-    case 14:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA6);     /* 0x298 */
-        break;
-    case 15:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA7);     /* 0x29C */
-        break;
-    case 16:
-        data = pci_read_32 ((u_int32_t *) &comet->__res74);     /* 0x1D0 */
-        break;
-    case 17:
-        data = pci_read_32 ((u_int32_t *) &comet->__res75);     /* 0x1D4 */
-        break;
-    case 18:
-        data = pci_read_32 ((u_int32_t *) &comet->__res76);     /* 0x1D8 */
-        break;
-    case 19:
-        data = pci_read_32 ((u_int32_t *) &comet->__res77);     /* 0x1DC */
-        break;
-    }
+	struct s_comet_reg    *comet;
+	volatile u_int32_t data;
+
+	comet = ci->port[0].cometbase;  /* default to COMET # 0 */
+
+	switch (x) {
+	default:
+	case 0:
+	    data = pci_read_32((u_int32_t *) &comet->__res24);     /* 0x90 */
+	    break;
+	case 1:
+	    data = pci_read_32((u_int32_t *) &comet->__res25);     /* 0x94 */
+	    break;
+	case 2:
+	    data = pci_read_32((u_int32_t *) &comet->__res26);     /* 0x98 */
+	    break;
+	case 3:
+	    data = pci_read_32((u_int32_t *) &comet->__res27);     /* 0x9C */
+	    break;
+	case 4:
+	    data = pci_read_32((u_int32_t *) &comet->__res88);     /* 0x220 */
+	    break;
+	case 5:
+	    data = pci_read_32((u_int32_t *) &comet->__res89);     /* 0x224 */
+	    break;
+	case 6:
+	    data = pci_read_32((u_int32_t *) &comet->__res8A);     /* 0x228 */
+	    break;
+	case 7:
+	    data = pci_read_32((u_int32_t *) &comet->__res8B);     /* 0x22C */
+	    break;
+	case 8:
+	    data = pci_read_32((u_int32_t *) &comet->__resA0);     /* 0x280 */
+	    break;
+	case 9:
+	    data = pci_read_32((u_int32_t *) &comet->__resA1);     /* 0x284 */
+	    break;
+	case 10:
+	    data = pci_read_32((u_int32_t *) &comet->__resA2);     /* 0x288 */
+	    break;
+	case 11:
+	    data = pci_read_32((u_int32_t *) &comet->__resA3);     /* 0x28C */
+	    break;
+	case 12:
+	    data = pci_read_32((u_int32_t *) &comet->__resA4);     /* 0x290 */
+	    break;
+	case 13:
+	    data = pci_read_32((u_int32_t *) &comet->__resA5);     /* 0x294 */
+	    break;
+	case 14:
+	    data = pci_read_32((u_int32_t *) &comet->__resA6);     /* 0x298 */
+	    break;
+	case 15:
+	    data = pci_read_32((u_int32_t *) &comet->__resA7);     /* 0x29C */
+	    break;
+	case 16:
+	    data = pci_read_32((u_int32_t *) &comet->__res74);     /* 0x1D0 */
+	    break;
+	case 17:
+	    data = pci_read_32((u_int32_t *) &comet->__res75);     /* 0x1D4 */
+	    break;
+	case 18:
+	    data = pci_read_32((u_int32_t *) &comet->__res76);     /* 0x1D8 */
+	    break;
+	case 19:
+	    data = pci_read_32((u_int32_t *) &comet->__res77);     /* 0x1DC */
+	    break;
+	}
 }
 
 
diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c
index 02b4f8f1aca5..85040bb617c4 100644
--- a/drivers/staging/cxt1e1/hwprobe.c
+++ b/drivers/staging/cxt1e1/hwprobe.c
@@ -36,355 +36,355 @@ extern int  error_flag;
 extern int  drvr_state;
 
 /* forward references */
-void        c4_stopwd (ci_t *);
-struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
+void        c4_stopwd(ci_t *);
+struct net_device * __init c4_add_dev(hdw_info_t *, int, unsigned long, unsigned long, int, int);
 
 
 struct s_hdw_info hdw_info[MAX_BOARDS];
 
 
-void        __init
-show_two (hdw_info_t *hi, int brdno)
+void __init
+show_two(hdw_info_t *hi, int brdno)
 {
-    ci_t       *ci;
-    struct pci_dev *pdev;
-    char       *bid;
-    char       *bp, banner[80];
-    char        sn[6];
-
-    bp = banner;
-    memset (banner, 0, 80);         /* clear print buffer */
-
-    ci = (ci_t *)(netdev_priv(hi->ndev));
-    bid = sbeid_get_bdname (ci);
-    switch (hi->promfmt)
-    {
-    case PROM_FORMAT_TYPE1:
-        memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-        break;
-    case PROM_FORMAT_TYPE2:
-        memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-        break;
-    default:
-        memset (sn, 0, 6);
-        break;
-    }
-
-    sprintf (banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
-             hi->devname, bid,
-             ((sn[3] << 16) & 0xff0000) |
-              ((sn[4] << 8) & 0x00ff00) |
-              (sn[5] & 0x0000ff),
-             (u_int8_t) hi->revid[0]);
-
-    pr_info("%s\n", banner);
-
-    pdev = hi->pdev[0];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "MUSYCC",
-            (unsigned long) hi->addr_mapped[0], hi->addr[0],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
-
-    pdev = hi->pdev[1];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "EBUS  ",
-            (unsigned long) hi->addr_mapped[1], hi->addr[1],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+	ci_t       *ci;
+	struct pci_dev *pdev;
+	char       *bid;
+	char       banner[80];
+	char	sn[6];
+
+	/* clear print buffer */
+	memset(banner, 0, 80);
+
+	ci = (ci_t *)(netdev_priv(hi->ndev));
+	bid = sbeid_get_bdname(ci);
+	switch (hi->promfmt)
+	{
+	case PROM_FORMAT_TYPE1:
+		memcpy(sn, (FLD_TYPE1 *)(hi->mfg_info.pft1.Serial), 6);
+		break;
+	case PROM_FORMAT_TYPE2:
+		memcpy(sn, (FLD_TYPE2 *)(hi->mfg_info.pft2.Serial), 6);
+		break;
+	default:
+		memset(sn, 0, 6);
+		break;
+	}
+
+	sprintf(banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
+		hi->devname, bid,
+		((sn[3] << 16) & 0xff0000) |
+		((sn[4] << 8) & 0x00ff00) |
+		(sn[5] & 0x0000ff),
+		(u_int8_t) hi->revid[0]);
+
+	pr_info("%s\n", banner);
+
+	pdev = hi->pdev[0];
+	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+		hi->devname, "MUSYCC",
+		(unsigned long) hi->addr_mapped[0], hi->addr[0],
+		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
+
+	pdev = hi->pdev[1];
+	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+		hi->devname, "EBUS  ",
+		(unsigned long) hi->addr_mapped[1], hi->addr[1],
+		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
 }
 
 
-void        __init
-hdw_sn_get (hdw_info_t *hi, int brdno)
+void __init
+hdw_sn_get(hdw_info_t *hi, int brdno)
 {
-    /* obtain hardware EEPROM information */
-    long        addr;
+	/* obtain hardware EEPROM information */
+	long        addr;
 
-    addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
+	addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
 
-    /* read EEPROM with largest known format size... */
-    pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
+	/* read EEPROM with largest known format size... */
+	pmc_eeprom_read_buffer(addr, 0, (char *)hi->mfg_info.data, sizeof(FLD_TYPE2));
 
 #if 0
-    {
-        unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
-
-        pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
-        pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
-        pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
-        pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
-        pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
-        pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
-    }
+	{
+		unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
+
+		pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
+		pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
+		pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
+		pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
+		pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
+		pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+				*(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
+	}
 #endif
 #if 0
-    pr_info("sn: %x %x %x %x %x %x\n",
-            hi->mfg_info.Serial[0],
-            hi->mfg_info.Serial[1],
-            hi->mfg_info.Serial[2],
-            hi->mfg_info.Serial[3],
-            hi->mfg_info.Serial[4],
-            hi->mfg_info.Serial[5]);
+	pr_info("sn: %x %x %x %x %x %x\n",
+			hi->mfg_info.Serial[0],
+			hi->mfg_info.Serial[1],
+			hi->mfg_info.Serial[2],
+			hi->mfg_info.Serial[3],
+			hi->mfg_info.Serial[4],
+			hi->mfg_info.Serial[5]);
 #endif
 
-    if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
-    {
-        /* bad crc, data is suspect */
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: EEPROM cksum error\n", hi->devname);
-        hi->mfg_info_sts = EEPROM_CRCERR;
-    } else
-        hi->mfg_info_sts = EEPROM_OK;
+	if ((hi->promfmt = pmc_verify_cksum(&hi->mfg_info.data)) == PROM_FORMAT_Unk)
+	{
+		/* bad crc, data is suspect */
+		if (cxt1e1_log_level >= LOG_WARN)
+			pr_info("%s: EEPROM cksum error\n", hi->devname);
+		hi->mfg_info_sts = EEPROM_CRCERR;
+	} else
+		hi->mfg_info_sts = EEPROM_OK;
 }
 
 
-void        __init
-prep_hdw_info (void)
+	void __init
+prep_hdw_info(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        hi->pci_busno = 0xff;
-        hi->pci_slot = 0xff;
-        hi->pci_pin[0] = 0;
-        hi->pci_pin[1] = 0;
-        hi->ndev = NULL;
-        hi->addr[0] = 0L;
-        hi->addr[1] = 0L;
-        hi->addr_mapped[0] = 0L;
-        hi->addr_mapped[1] = 0L;
-    }
+	hdw_info_t *hi;
+	int         i;
+
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		hi->pci_busno = 0xff;
+		hi->pci_slot = 0xff;
+		hi->pci_pin[0] = 0;
+		hi->pci_pin[1] = 0;
+		hi->ndev = NULL;
+		hi->addr[0] = 0L;
+		hi->addr[1] = 0L;
+		hi->addr_mapped[0] = 0L;
+		hi->addr_mapped[1] = 0L;
+	}
 }
 
 void
-cleanup_ioremap (void)
+cleanup_ioremap(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (hi->addr_mapped[0])
-        {
-            iounmap ((void *) (hi->addr_mapped[0]));
-            release_mem_region ((long) hi->addr[0], hi->len[0]);
-            hi->addr_mapped[0] = 0;
-        }
-        if (hi->addr_mapped[1])
-        {
-            iounmap ((void *) (hi->addr_mapped[1]));
-            release_mem_region ((long) hi->addr[1], hi->len[1]);
-            hi->addr_mapped[1] = 0;
-        }
-    }
+	hdw_info_t *hi;
+	int         i;
+
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->pci_slot == 0xff)
+			break;
+		if (hi->addr_mapped[0])
+		{
+			iounmap((void *)(hi->addr_mapped[0]));
+			release_mem_region((long) hi->addr[0], hi->len[0]);
+			hi->addr_mapped[0] = 0;
+		}
+		if (hi->addr_mapped[1])
+		{
+			iounmap((void *)(hi->addr_mapped[1]));
+			release_mem_region((long) hi->addr[1], hi->len[1]);
+			hi->addr_mapped[1] = 0;
+		}
+	}
 }
 
 
 void
-cleanup_devs (void)
+cleanup_devs(void)
 {
-    hdw_info_t *hi;
-    int         i;
-
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff || !hi->ndev)
-            break;
-        c4_stopwd(netdev_priv(hi->ndev));
+	hdw_info_t *hi;
+	int         i;
+
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->pci_slot == 0xff || !hi->ndev)
+			break;
+		c4_stopwd(netdev_priv(hi->ndev));
 #ifdef CONFIG_PROC_FS
-        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
+		sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
 #endif
-        unregister_netdev (hi->ndev);
-        free_irq (hi->pdev[0]->irq, hi->ndev);
+		unregister_netdev(hi->ndev);
+		free_irq(hi->pdev[0]->irq, hi->ndev);
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-        free_irq (hi->pdev[1]->irq, hi->ndev);
+		free_irq(hi->pdev[1]->irq, hi->ndev);
 #endif
-        OS_kfree (hi->ndev);
-    }
+		OS_kfree(hi->ndev);
+	}
 }
 
 
 static int  __init
-c4_hdw_init (struct pci_dev *pdev, int found)
+c4_hdw_init(struct pci_dev *pdev, int found)
 {
-    hdw_info_t *hi;
-    int         i;
-    int         fun, slot;
-    unsigned char busno = 0xff;
-
-    /* our MUSYCC chip supports two functions, 0 & 1 */
-    if ((fun = PCI_FUNC (pdev->devfn)) > 1)
-    {
-        pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
-        return 0;
-    }
-    if (pdev->bus)                  /* obtain bus number */
-        busno = pdev->bus->number;
-    else
-        busno = 0;                  /* default for system PCI inconsistency */
-    slot = pdev->devfn & ~0x07;
-
-    /*
-     * Functions 0 & 1 for a given board (identified by same bus(busno) and
-     * slot(slot)) are placed into the same 'hardware' structure.  The first
-     * part of the board's functionality will be placed into an unpopulated
-     * element, identified by "slot==(0xff)".  The second part of a board's
-     * functionality will match the previously loaded slot/busno.
-     */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        /*
-         * match with board's first found interface, otherwise this is first
-         * found
-         */
-        if ((hi->pci_slot == 0xff) ||   /* new board */
-            ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
-            break;                  /* found for-loop exit */
-    }
-    if (i == MAX_BOARDS)            /* no match in above loop means MAX
-                                     * exceeded */
-    {
-        pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
-        return 0;
-    }
-    if (pdev->bus)
-        hi->pci_busno = pdev->bus->number;
-    else
-        hi->pci_busno = 0;          /* default for system PCI inconsistency */
-    hi->pci_slot = slot;
-    pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
-    pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
-    hi->bus = pdev->bus;
-    hi->addr[fun] = pci_resource_start (pdev, 0);
-    hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
-    hi->pdev[fun] = pdev;
-
-    {
-        /*
-         * create device name from module name, plus add the appropriate
-         * board number
-         */
-        char       *cp = hi->devname;
-
-        strcpy (cp, KBUILD_MODNAME);
-        cp += strlen (cp);          /* reposition */
-        *cp++ = '-';
-        *cp++ = '0' + (found / 2);  /* there are two found interfaces per
-                                     * board */
-        *cp = 0;                    /* termination */
-    }
-
-    return 1;
+	hdw_info_t *hi;
+	int         i;
+	int         fun, slot;
+	unsigned char busno = 0xff;
+
+	/* our MUSYCC chip supports two functions, 0 & 1 */
+	if ((fun = PCI_FUNC(pdev->devfn)) > 1)
+	{
+		pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
+		return 0;
+	}
+
+	if (pdev->bus)                  /* obtain bus number */
+		busno = pdev->bus->number;
+	else
+		busno = 0;                  /* default for system PCI inconsistency */
+	slot = pdev->devfn & ~0x07;
+
+	/*
+	 * Functions 0 & 1 for a given board (identified by same bus(busno) and
+	 * slot(slot)) are placed into the same 'hardware' structure.  The first
+	 * part of the board's functionality will be placed into an unpopulated
+	 * element, identified by "slot==(0xff)".  The second part of a board's
+	 * functionality will match the previously loaded slot/busno.
+	 */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		/*
+		 * match with board's first found interface, otherwise this is first
+		 * found
+		 */
+		if ((hi->pci_slot == 0xff) ||   /* new board */
+		    ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
+			break;                  /* found for-loop exit */
+	}
+	if (i == MAX_BOARDS)            /* no match in above loop means MAX
+					 * exceeded */
+	{
+		pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
+		return 0;
+	}
+	if (pdev->bus)
+		hi->pci_busno = pdev->bus->number;
+	else
+		hi->pci_busno = 0;          /* default for system PCI inconsistency */
+	hi->pci_slot = slot;
+	pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &hi->revid[fun]);
+	hi->bus = pdev->bus;
+	hi->addr[fun] = pci_resource_start(pdev, 0);
+	hi->len[fun] = pci_resource_end(pdev, 0) - hi->addr[fun] + 1;
+	hi->pdev[fun] = pdev;
+
+	{
+		/*
+		 * create device name from module name, plus add the appropriate
+		 * board number
+		 */
+		char       *cp = hi->devname;
+
+		strcpy(cp, KBUILD_MODNAME);
+		cp += strlen(cp);          /* reposition */
+		*cp++ = '-';
+		*cp++ = '0' + (found / 2);  /* there are two found interfaces per
+		* board */
+		*cp = 0;                    /* termination */
+	}
+
+	return 1;
 }
 
-
-status_t    __init
-c4hw_attach_all (void)
+status_t __init
+c4hw_attach_all(void)
 {
-    hdw_info_t *hi;
-    struct pci_dev *pdev = NULL;
-    int         found = 0, i, j;
-
-    error_flag = 0;
-    prep_hdw_info ();
-    /*** scan PCI bus for all possible boards */
-    while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
-                                    PCI_DEVICE_ID_CN8474,
-                                    pdev)))
-    {
-        if (c4_hdw_init (pdev, found))
-            found++;
-    }
-    if (!found)
-    {
-        pr_warning("No boards found\n");
-        return -ENODEV;
-    }
-    /* sanity check for consistent hardware found */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
-        {
-            pr_warning("%s: something very wrong with pci_get_device\n",
-                       hi->devname);
-            return -EIO;
-        }
-    }
-    /* bring board's memory regions on/line */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        for (j = 0; j < 2; j++)
-        {
-	    if (!request_mem_region (hi->addr[j], hi->len[j], hi->devname))
-            {
-                pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
-            hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
-            if (!hi->addr_mapped[j])
-            {
-                pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
+	hdw_info_t *hi;
+	struct pci_dev *pdev = NULL;
+	int         found = 0, i, j;
+
+	error_flag = 0;
+	prep_hdw_info();
+	/*** scan PCI bus for all possible boards */
+	while ((pdev = pci_get_device(PCI_VENDOR_ID_CONEXANT,
+				      PCI_DEVICE_ID_CN8474,
+				      pdev)))
+	{
+		if (c4_hdw_init(pdev, found))
+			found++;
+	}
+	if (!found)
+	{
+		pr_warning("No boards found\n");
+		return -ENODEV;
+	}
+	/* sanity check for consistent hardware found */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
+		{
+			pr_warning("%s: something very wrong with pci_get_device\n",
+				   hi->devname);
+			return -EIO;
+		}
+	}
+	/* bring board's memory regions on/line */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->pci_slot == 0xff)
+			break;
+		for (j = 0; j < 2; j++)
+		{
+			if (!request_mem_region(hi->addr[j], hi->len[j], hi->devname))
+			{
+				pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
+					   hi->devname, hi->addr[j], hi->len[j]);
+				cleanup_ioremap();
+				return -ENOMEM;
+			}
+			hi->addr_mapped[j] = (unsigned long)ioremap(hi->addr[j], hi->len[j]);
+			if (!hi->addr_mapped[j])
+			{
+				pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
+					   hi->devname, hi->addr[j], hi->len[j]);
+				cleanup_ioremap();
+				return -ENOMEM;
+			}
 #ifdef SBE_MAP_DEBUG
-            pr_warning("%s: io remapped from phys %x to virt %x\n",
-                       hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
+			pr_warning("%s: io remapped from phys %x to virt %x\n",
+				   hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
 #endif
-        }
-    }
-
-    drvr_state = SBE_DRVR_AVAILABLE;
-
-    /* Have now memory mapped all boards.  Now allow board's access to system */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (pci_enable_device (hi->pdev[0]) ||
-            pci_enable_device (hi->pdev[1]))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            pr_warning("%s: failed to enable card %d slot %d\n",
-                       hi->devname, i, hi->pci_slot);
-            cleanup_devs ();
-            cleanup_ioremap ();
-            return -EIO;
-        }
-        pci_set_master (hi->pdev[0]);
-        pci_set_master (hi->pdev[1]);
-        if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
-                                     (long) hi->addr_mapped[1],
-                                     hi->pdev[0]->irq,
-                                     hi->pdev[1]->irq)))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            cleanup_ioremap ();
-            /* NOTE: c4_add_dev() does its own device cleanup */
+		}
+	}
+
+	drvr_state = SBE_DRVR_AVAILABLE;
+
+	/* Have now memory mapped all boards.  Now allow board's access to system */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->pci_slot == 0xff)
+			break;
+		if (pci_enable_device(hi->pdev[0]) ||
+		    pci_enable_device(hi->pdev[1]))
+		{
+			drvr_state = SBE_DRVR_DOWN;
+			pr_warning("%s: failed to enable card %d slot %d\n",
+				   hi->devname, i, hi->pci_slot);
+			cleanup_devs();
+			cleanup_ioremap();
+			return -EIO;
+		}
+		pci_set_master(hi->pdev[0]);
+		pci_set_master(hi->pdev[1]);
+		if (!(hi->ndev = c4_add_dev(hi, i, (long) hi->addr_mapped[0],
+					    (long) hi->addr_mapped[1],
+					    hi->pdev[0]->irq,
+					    hi->pdev[1]->irq)))
+		{
+			drvr_state = SBE_DRVR_DOWN;
+			cleanup_ioremap();
+			/* NOTE: c4_add_dev() does its own device cleanup */
 #if 0
-            cleanup_devs ();
+			cleanup_devs();
 #endif
-            return error_flag;      /* error_flag set w/in add_dev() */
-        }
-        show_two (hi, i);           /* displays found information */
-    }
-    return 0;
+			return error_flag;      /* error_flag set w/in add_dev() */
+		}
+		show_two(hi, i);           /* displays found information */
+	}
+	return 0;
 }
 
 /***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/pmc93x6_eeprom.c b/drivers/staging/cxt1e1/pmc93x6_eeprom.c
index 137b63cb5537..78cc1709ebdb 100644
--- a/drivers/staging/cxt1e1/pmc93x6_eeprom.c
+++ b/drivers/staging/cxt1e1/pmc93x6_eeprom.c
@@ -90,7 +90,7 @@ static int  ByteReverseBuilt = FALSE;
  *------------------------------------------------------------------------
  */
 
-short       mfg_template[sizeof (FLD_TYPE2)] =
+static u8 mfg_template[sizeof(FLD_TYPE2)] =
 {
     PROM_FORMAT_TYPE2,          /* type; */
     0x00, 0x1A,                 /* length[2]; */
@@ -491,13 +491,11 @@ pmc_init_seeprom (u_int32_t addr, u_int32_t serialNum)
     PROMFORMAT  buffer;         /* Memory image of structure */
     u_int32_t   crc;            /* CRC of structure */
     time_t      createTime;
-    int         i;
 
     createTime = get_seconds ();
 
     /* use template data */
-    for (i = 0; i < sizeof (FLD_TYPE2); ++i)
-        buffer.bytes[i] = mfg_template[i];
+    memcpy(&buffer.fldType2, mfg_template, sizeof(buffer.fldType2));
 
     /* Update serial number field in buffer */
     pmcSetBuffValue (&buffer.fldType2.Serial[3], serialNum, 3);
diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h
index 003eb8690190..b4b5e5ad791b 100644
--- a/drivers/staging/cxt1e1/pmcc4.h
+++ b/drivers/staging/cxt1e1/pmcc4.h
@@ -96,7 +96,6 @@ void        sbeid_set_bdtype (ci_t *ci);
 void        sbeid_set_hdwbid (ci_t *ci);
 u_int32_t   sbeCrc (u_int8_t *, u_int32_t, u_int32_t, u_int32_t *);
 
-void        VMETRO_TRACE (void *);       /* put data into 8 LEDs */
 void        VMETRO_TRIGGER (ci_t *, int);       /* Note: int = 0(default)
                                                  * thru 15 */
 
diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile
index 3abe8d2bb748..0063d044ca71 100644
--- a/drivers/staging/dgap/Makefile
+++ b/drivers/staging/dgap/Makefile
@@ -1,7 +1 @@
 obj-$(CONFIG_DGAP) += dgap.o
-
-
-dgap-objs :=	dgap_driver.o   dgap_fep5.o \
-		dgap_parse.o	dgap_trace.o \
-		dgap_tty.o	dgap_sysfs.o
-
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
new file mode 100644
index 000000000000..cbce45776230
--- /dev/null
+++ b/drivers/staging/dgap/dgap.c
@@ -0,0 +1,7857 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, 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.
+ *
+ * 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.
+ *
+ */
+
+/*
+ *      In the original out of kernel Digi dgap driver, firmware
+ *      loading was done via user land to driver handshaking.
+ *
+ *      For cards that support a concentrator (port expander),
+ *      I believe the concentrator its self told the card which
+ *      concentrator is actually attached and then that info
+ *      was used to tell user land which concentrator firmware
+ *      image was to be downloaded. I think even the BIOS or
+ *      FEP images required could change with the connection
+ *      of a particular concentrator.
+ *
+ *      Since I have no access to any of these cards or
+ *      concentrators, I cannot put the correct concentrator
+ *      firmware file names into the firmware_info structure
+ *      as is now done for the BIOS and FEP images.
+ *
+ *      I think, but am not certain, that the cards supporting
+ *      concentrators will function without them. So support
+ *      of these cards has been left in this driver.
+ *
+ *      In order to fully support those cards, they would
+ *      either have to be acquired for dissection or maybe
+ *      Digi International could provide some assistance.
+ */
+#undef DIGI_CONCENTRATORS_SUPPORTED
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>	/* For udelay */
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/ctype.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>		/* For read[bwl]/write[bwl] */
+
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/firmware.h>
+
+#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");
+
+/*
+ * insmod command line overrideable parameters
+ *
+ * NOTE: we use a set of macros to create the variables, which allows
+ * us to specify the variable type, name, initial value, and description.
+ */
+PARM_INT(rawreadok,	1,		0644,	"Bypass flip buffers on input");
+
+
+/**************************************************************************
+ *
+ * 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);
+static void dgap_cleanup_board(struct board_t *brd);
+static void dgap_poll_handler(ulong dummy);
+static int dgap_init_pci(void);
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void dgap_remove_one(struct pci_dev *dev);
+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, struct channel_t *ch);
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_write_room(struct tty_struct *tty);
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty);
+static void dgap_tty_start(struct tty_struct *tty);
+static void dgap_tty_stop(struct tty_struct *tty);
+static void dgap_tty_throttle(struct tty_struct *tty);
+static void dgap_tty_unthrottle(struct tty_struct *tty);
+static void dgap_tty_flush_chars(struct tty_struct *tty);
+static void dgap_tty_flush_buffer(struct tty_struct *tty);
+static void dgap_tty_hangup(struct tty_struct *tty);
+static int dgap_wait_for_drain(struct tty_struct *tty);
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_tiocmget(struct tty_struct *tty);
+static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
+static int dgap_tty_send_break(struct tty_struct *tty, int msec);
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
+static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
+
+static int dgap_tty_register(struct board_t *brd);
+static int dgap_tty_preinit(void);
+static int dgap_tty_init(struct board_t *);
+static void dgap_tty_post_uninit(void);
+static void dgap_tty_uninit(struct board_t *);
+static void dgap_carrier(struct channel_t *ch);
+static void dgap_input(struct channel_t *ch);
+
+/*
+ * Our function prototypes from dgap_fep5
+ */
+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_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, unsigned char *fbuf, int *len);
+static uint dgap_get_custom_baud(struct channel_t *ch);
+static void dgap_firmware_reset_port(struct channel_t *ch);
+
+/*
+ * Function prototypes from dgap_parse.c.
+ */
+static int dgap_gettok(char **in, struct cnode *p);
+static char *dgap_getword(char **in);
+static char *dgap_savestring(char *s);
+static struct cnode *dgap_newnode(int t);
+static int dgap_checknode(struct cnode *p);
+static void dgap_err(char *s);
+
+/*
+ * Function prototypes from dgap_sysfs.h
+ */
+struct board_t;
+struct channel_t;
+struct un_t;
+struct pci_driver;
+struct class_device;
+
+static void dgap_create_ports_sysfiles(struct board_t *bd);
+static void dgap_remove_ports_sysfiles(struct board_t *bd);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *);
+static void dgap_remove_driver_sysfiles(struct pci_driver *);
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
+static void dgap_remove_tty_sysfs(struct device *c);
+
+/*
+ * Function prototypes from dgap_parse.h
+ */
+static int dgap_parsefile(char **in, int Remove);
+static struct cnode *dgap_find_config(int type, int bus, int slot);
+static uint dgap_config_get_number_of_ports(struct board_t *bd);
+static char *dgap_create_config_string(struct board_t *bd, char *string);
+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, uchar __user *ubios, int len);
+static void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+static void dgap_do_conc_load(struct board_t *brd, uchar *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 void dgap_do_wait_for_bios(struct board_t *brd);
+static void dgap_do_wait_for_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 load/unload functions */
+int			dgap_init_module(void);
+void			dgap_cleanup_module(void);
+
+module_init(dgap_init_module);
+module_exit(dgap_cleanup_module);
+
+/*
+ * File operations permitted on Control/Management major.
+ */
+static const struct file_operations DgapBoardFops = {
+	.owner	= THIS_MODULE,
+};
+
+/*
+ * Globals
+ */
+static uint dgap_NumBoards;
+static struct board_t *dgap_Board[MAXBOARDS];
+DEFINE_SPINLOCK(dgap_global_lock);
+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 int dgap_Major_Control_Registered = FALSE;
+static uint dgap_driver_start = FALSE;
+
+static struct class *dgap_class;
+
+static struct board_t *dgap_BoardsByMajor[256];
+static uchar *dgap_TmpWriteBuf = NULL;
+DECLARE_MUTEX(dgap_TmpWriteSem);
+static uint dgap_count = 500;
+
+/*
+ * Poller stuff
+ */
+DEFINE_SPINLOCK(dgap_poll_lock);	/* Poll scheduling lock */
+static ulong dgap_poll_time;		/* Time of next poll */
+static uint dgap_poll_stop;		/* Used to tell poller to stop */
+static struct timer_list dgap_poll_timer;
+
+/*
+     SUPPORTED PRODUCTS
+
+     Card Model               Number of Ports      Interface
+     ----------------------------------------------------------------
+     Acceleport Xem           4 - 64              (EIA232 & EIA422)
+     Acceleport Xr            4 & 8               (EIA232)
+     Acceleport Xr 920        4 & 8               (EIA232)
+     Acceleport C/X           8 - 128             (EIA232)
+     Acceleport EPC/X         8 - 224             (EIA232)
+     Acceleport Xr/422        4 & 8               (EIA422)
+     Acceleport 2r/920        2                   (EIA232)
+     Acceleport 4r/920        4                   (EIA232)
+     Acceleport 8r/920        8                   (EIA232)
+
+     IBM 8-Port Asynchronous PCI Adapter          (EIA232)
+     IBM 128-Port Asynchronous PCI Adapter        (EIA232 & EIA422)
+*/
+
+static struct pci_device_id dgap_pci_tbl[] = {
+	{       DIGI_VID, PCI_DEVICE_XEM_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	0 },
+	{       DIGI_VID, PCI_DEVICE_CX_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
+	{       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	2 },
+	{       DIGI_VID, PCI_DEVICE_EPCJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	3 },
+	{       DIGI_VID, PCI_DEVICE_920_2_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	4 },
+	{       DIGI_VID, PCI_DEVICE_920_4_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	5 },
+	{       DIGI_VID, PCI_DEVICE_920_8_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	6 },
+	{       DIGI_VID, PCI_DEVICE_XR_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	7 },
+	{       DIGI_VID, PCI_DEVICE_XRJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	8 },
+	{       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	9 },
+	{       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	10 },
+	{       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	11 },
+	{       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	12 },
+	{       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
+	{       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	14 },
+	{0,}					/* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
+
+/*
+ * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
+ */
+struct board_id {
+	uint config_type;
+	uchar *name;
+	uint maxports;
+	uint dpatype;
+};
+
+static struct board_id dgap_Ids[] = {
+	{	PPCM,		PCI_DEVICE_XEM_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
+	{	PCX,		PCI_DEVICE_CX_NAME,	128,	(T_CX | T_PCIBUS)		},
+	{	PCX,		PCI_DEVICE_CX_IBM_NAME,	128,	(T_CX | T_PCIBUS)		},
+	{	PEPC,		PCI_DEVICE_EPCJ_NAME,	224,	(T_EPC  | T_PCIBUS)		},
+	{	APORT2_920P,	PCI_DEVICE_920_2_NAME,	2,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT4_920P,	PCI_DEVICE_920_4_NAME,	4,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT8_920P,	PCI_DEVICE_920_8_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XRJ_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_422_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_IBM_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_SAIP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_BULL_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT8_920P,	PCI_DEVICE_920_8_HP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PPCM,		PCI_DEVICE_XEM_HP_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
+	{0,}						/* 0 terminated list. */
+};
+
+static struct pci_driver dgap_driver = {
+	.name		= "dgap",
+	.probe		= dgap_init_one,
+	.id_table	= dgap_pci_tbl,
+	.remove		= dgap_remove_one,
+};
+
+struct firmware_info {
+	uchar *conf_name;       /* dgap.conf */
+	uchar *bios_name;	/* BIOS filename */
+	uchar *fep_name;	/* FEP  filename */
+	uchar *con_name;	/* Concentrator filename  FIXME*/
+	int num;                /* sequence number */
+};
+
+/*
+ * Firmware - BIOS, FEP, and CONC filenames
+ */
+static struct firmware_info fw_info[] = {
+	{ "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 0 },
+	{ "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 1 },
+	{ "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 2 },
+	{ "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", 0, 3 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 4 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 5 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 6 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 7 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 8 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 9 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 10 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 11 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 12 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 13 },
+	{ "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 14 },
+	{0,}
+};
+
+static char *dgap_driver_state_text[] = {
+	"Driver Initialized",
+	"Driver needs configuration load.",
+	"Driver requested configuration from download daemon.",
+	"Driver Ready."
+};
+
+/*
+ * Default transparent print information.
+ */
+static struct digi_t dgap_digi_init = {
+	.digi_flags =	DIGI_COOK,	/* Flags			*/
+	.digi_maxcps =	100,		/* Max CPS			*/
+	.digi_maxchar =	50,		/* Max chars in print queue	*/
+	.digi_bufsize =	100,		/* Printer buffer size		*/
+	.digi_onlen =	4,		/* size of printer on string	*/
+	.digi_offlen =	4,		/* size of printer off string	*/
+	.digi_onstr =	"\033[5i",	/* ANSI printer on string ]	*/
+	.digi_offstr =	"\033[4i",	/* ANSI printer off string ]	*/
+	.digi_term =	"ansi"		/* default terminal type	*/
+};
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.
+ *
+ * This defines a raw port at 9600 baud, 8 data bits, no parity,
+ * 1 stop bit.
+ */
+
+static struct ktermios DgapDefaultTermios = {
+	.c_iflag =	(DEFAULT_IFLAGS),	/* iflags */
+	.c_oflag =	(DEFAULT_OFLAGS),	/* oflags */
+	.c_cflag =	(DEFAULT_CFLAGS),	/* cflags */
+	.c_lflag =	(DEFAULT_LFLAGS),	/* lflags */
+	.c_cc =		INIT_C_CC,
+	.c_line =	0,
+};
+
+static const struct tty_operations dgap_tty_ops = {
+	.open = dgap_tty_open,
+	.close = dgap_tty_close,
+	.write = dgap_tty_write,
+	.write_room = dgap_tty_write_room,
+	.flush_buffer = dgap_tty_flush_buffer,
+	.chars_in_buffer = dgap_tty_chars_in_buffer,
+	.flush_chars = dgap_tty_flush_chars,
+	.ioctl = dgap_tty_ioctl,
+	.set_termios = dgap_tty_set_termios,
+	.stop = dgap_tty_stop,
+	.start = dgap_tty_start,
+	.throttle = dgap_tty_throttle,
+	.unthrottle = dgap_tty_unthrottle,
+	.hangup = dgap_tty_hangup,
+	.put_char = dgap_tty_put_char,
+	.tiocmget = dgap_tty_tiocmget,
+	.tiocmset = dgap_tty_tiocmset,
+	.break_ctl = dgap_tty_send_break,
+	.wait_until_sent = dgap_tty_wait_until_sent,
+	.send_xchar = dgap_tty_send_xchar
+};
+
+/*
+ * Our needed internal static variables from dgap_parse.c
+ */
+static struct cnode dgap_head;
+#define MAXCWORD 200
+static char dgap_cword[MAXCWORD];
+
+struct toklist {
+	int	token;
+	char	*string;
+};
+
+static struct toklist dgap_tlist[] = {
+	{	BEGIN,		"config_begin"			},
+	{	END,		"config_end"			},
+	{	BOARD,		"board"				},
+	{	PCX,		"Digi_AccelePort_C/X_PCI"	},	/* C/X_PCI */
+	{	PEPC,		"Digi_AccelePort_EPC/X_PCI"	},	/* EPC/X_PCI */
+	{	PPCM,		"Digi_AccelePort_Xem_PCI"	},	/* PCI/Xem */
+	{	APORT2_920P,	"Digi_AccelePort_2r_920_PCI"	},
+	{	APORT4_920P,	"Digi_AccelePort_4r_920_PCI"	},
+	{	APORT8_920P,	"Digi_AccelePort_8r_920_PCI"	},
+	{	PAPORT4,	"Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
+	{	PAPORT8,	"Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
+	{	IO,		"io"				},
+	{	PCIINFO,	"pciinfo"			},
+	{	LINE,		"line"				},
+	{	CONC,		"conc"				},
+	{	CONC,		"concentrator"			},
+	{	CX,		"cx"				},
+	{	CX,		"ccon"				},
+	{	EPC,		"epccon"			},
+	{	EPC,		"epc"				},
+	{	MOD,		"module"			},
+	{	ID,		"id"				},
+	{	STARTO,		"start"				},
+	{	SPEED,		"speed"				},
+	{	CABLE,		"cable"				},
+	{	CONNECT,	"connect"			},
+	{	METHOD,		"method"			},
+	{	STATUS,		"status"			},
+	{	CUSTOM,		"Custom"			},
+	{	BASIC,		"Basic"				},
+	{	MEM,		"mem"				},
+	{	MEM,		"memory"			},
+	{	PORTS,		"ports"				},
+	{	MODEM,		"modem"				},
+	{	NPORTS,		"nports"			},
+	{	TTYN,		"ttyname"			},
+	{	CU,		"cuname"			},
+	{	PRINT,		"prname"			},
+	{	CMAJOR,		"major"				},
+	{	ALTPIN,		"altpin"			},
+	{	USEINTR,	"useintr"			},
+	{	TTSIZ,		"ttysize"			},
+	{	CHSIZ,		"chsize"			},
+	{	BSSIZ,		"boardsize"			},
+	{	UNTSIZ,		"schedsize"			},
+	{	F2SIZ,		"f2200size"			},
+	{	VPSIZ,		"vpixsize"			},
+	{	0,		NULL				}
+};
+
+/************************************************************************
+ *
+ * Driver load/unload functions
+ *
+ ************************************************************************/
+
+/*
+ * init_module()
+ *
+ * Module load.  This is where it all starts.
+ */
+int dgap_init_module(void)
+{
+	int rc = 0;
+
+	pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART);
+
+	dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+
+	/*
+	 * Initialize global stuff
+	 */
+	rc = dgap_start();
+
+	if (rc < 0)
+		return rc;
+
+	/*
+	 * Find and configure all the cards
+	 */
+	rc = dgap_init_pci();
+
+	/*
+	 * If something went wrong in the scan, bail out of driver.
+	 */
+	if (rc < 0) {
+		/* Only unregister the pci driver if it was actually registered. */
+		if (dgap_NumBoards)
+			pci_unregister_driver(&dgap_driver);
+		else
+			printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
+
+		dgap_cleanup_module();
+	} else {
+		dgap_create_driver_sysfiles(&dgap_driver);
+		dgap_driver_state = DRIVER_READY;
+	}
+
+	return rc;
+}
+
+/*
+ * Start of driver.
+ */
+static int dgap_start(void)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (dgap_driver_start == FALSE) {
+
+		dgap_driver_start = TRUE;
+
+		/*
+		 * make sure that the globals are
+		 * init'd before we do anything else
+		 */
+		dgap_init_globals();
+
+		dgap_NumBoards = 0;
+
+		pr_info("For the tools package please visit http://www.digi.com\n");
+
+		/*
+		 * Register our base character device into the kernel.
+		 * This allows the download daemon to connect to the downld device
+		 * before any of the boards are init'ed.
+		 */
+		if (!dgap_Major_Control_Registered) {
+			/*
+			 * Register management/dpa devices
+			 */
+			rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
+			if (rc < 0)
+				return rc;
+
+			dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
+			device_create(dgap_class, NULL,
+				MKDEV(DIGI_DGAP_MAJOR, 0),
+				NULL, "dgap_mgmt");
+			dgap_Major_Control_Registered = TRUE;
+		}
+
+		/*
+		 * Init any global tty stuff.
+		 */
+		rc = dgap_tty_preinit();
+
+		if (rc < 0)
+			return rc;
+
+		/* Start the poller */
+		DGAP_LOCK(dgap_poll_lock, flags);
+		init_timer(&dgap_poll_timer);
+		dgap_poll_timer.function = dgap_poll_handler;
+		dgap_poll_timer.data = 0;
+		dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
+		dgap_poll_timer.expires = dgap_poll_time;
+		DGAP_UNLOCK(dgap_poll_lock, flags);
+
+		add_timer(&dgap_poll_timer);
+
+		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+	}
+
+	return rc;
+}
+
+/*
+ * Register pci driver, and return how many boards we have.
+ */
+static int dgap_init_pci(void)
+{
+	return pci_register_driver(&dgap_driver);
+}
+
+/* returns count (>= 0), or negative on error */
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+
+	/* wake up and enable device */
+	rc = pci_enable_device(pdev);
+
+	if (rc < 0) {
+		rc = -EIO;
+	} else {
+		rc = dgap_probe1(pdev, ent->driver_data);
+		if (rc == 0) {
+			dgap_NumBoards++;
+			rc = dgap_firmware_load(pdev, ent->driver_data);
+		}
+	}
+	return rc;
+}
+
+static int dgap_probe1(struct pci_dev *pdev, int card_type)
+{
+	return dgap_found_board(pdev, card_type);
+}
+
+static void dgap_remove_one(struct pci_dev *dev)
+{
+	/* Do Nothing */
+}
+
+/*
+ * dgap_cleanup_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+void dgap_cleanup_module(void)
+{
+	int i;
+	ulong lock_flags;
+
+	DGAP_LOCK(dgap_poll_lock, lock_flags);
+	dgap_poll_stop = 1;
+	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+	/* Turn off poller right away. */
+	del_timer_sync(&dgap_poll_timer);
+
+	dgap_remove_driver_sysfiles(&dgap_driver);
+
+
+	if (dgap_Major_Control_Registered) {
+		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
+		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
+		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]);
+		dgap_cleanup_board(dgap_Board[i]);
+	}
+
+	dgap_tty_post_uninit();
+
+#if defined(DGAP_TRACER)
+	/* last thing, make sure we release the tracebuffer */
+	dgap_tracer_free();
+#endif
+	if (dgap_NumBoards)
+		pci_unregister_driver(&dgap_driver);
+}
+
+/*
+ * dgap_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void dgap_cleanup_board(struct board_t *brd)
+{
+	int i = 0;
+
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	if (brd->intr_used && brd->irq)
+		free_irq(brd->irq, brd);
+
+	tasklet_kill(&brd->helper_tasklet);
+
+	if (brd->re_map_port) {
+		release_mem_region(brd->membase + 0x200000, 0x200000);
+		iounmap(brd->re_map_port);
+		brd->re_map_port = NULL;
+	}
+
+	if (brd->re_map_membase) {
+		release_mem_region(brd->membase, 0x200000);
+		iounmap(brd->re_map_membase);
+		brd->re_map_membase = NULL;
+	}
+
+	if (brd->msgbuf_head) {
+		unsigned long flags;
+
+		DGAP_LOCK(dgap_global_lock, flags);
+		brd->msgbuf = NULL;
+		printk("%s", brd->msgbuf_head);
+		kfree(brd->msgbuf_head);
+		brd->msgbuf_head = NULL;
+		DGAP_UNLOCK(dgap_global_lock, flags);
+	}
+
+	/* Free all allocated channels structs */
+	for (i = 0; i < MAXPORTS ; i++) {
+		if (brd->channels[i]) {
+			kfree(brd->channels[i]);
+			brd->channels[i] = NULL;
+		}
+	}
+
+	kfree(brd->flipbuf);
+	kfree(brd->flipflagbuf);
+
+	dgap_Board[brd->boardnum] = NULL;
+
+	kfree(brd);
+}
+
+/*
+ * dgap_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int dgap_found_board(struct pci_dev *pdev, int id)
+{
+	struct board_t *brd;
+	unsigned int pci_irq;
+	int i = 0;
+	unsigned long flags;
+
+	/* get the board structure and prep it */
+	brd = dgap_Board[dgap_NumBoards] =
+	(struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
+	if (!brd)
+		return -ENOMEM;
+
+	/* make a temporary message buffer for the boot messages */
+	brd->msgbuf = brd->msgbuf_head =
+		(char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+	if (!brd->msgbuf) {
+		kfree(brd);
+		return -ENOMEM;
+	}
+
+	/* store the info for the board we've found */
+	brd->magic = DGAP_BOARD_MAGIC;
+	brd->boardnum = dgap_NumBoards;
+	brd->firstminor = 0;
+	brd->vendor = dgap_pci_tbl[id].vendor;
+	brd->device = dgap_pci_tbl[id].device;
+	brd->pdev = pdev;
+	brd->pci_bus = pdev->bus->number;
+	brd->pci_slot = PCI_SLOT(pdev->devfn);
+	brd->name = dgap_Ids[id].name;
+	brd->maxports = dgap_Ids[id].maxports;
+	brd->type = dgap_Ids[id].config_type;
+	brd->dpatype = dgap_Ids[id].dpatype;
+	brd->dpastatus = BD_NOFEP;
+	init_waitqueue_head(&brd->state_wait);
+
+	DGAP_SPINLOCK_INIT(brd->bd_lock);
+
+	brd->state		= BOARD_FOUND;
+	brd->runwait		= 0;
+	brd->inhibit_poller	= FALSE;
+	brd->wait_for_bios	= 0;
+	brd->wait_for_fep	= 0;
+
+	for (i = 0; i < MAXPORTS; i++)
+		brd->channels[i] = NULL;
+
+	/* store which card & revision we have */
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+	pci_irq = pdev->irq;
+	brd->irq = pci_irq;
+
+	/* get the PCI Base Address Registers */
+
+	/* Xr Jupiter and EPC use BAR 2 */
+	if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
+		brd->membase     = pci_resource_start(pdev, 2);
+		brd->membase_end = pci_resource_end(pdev, 2);
+	}
+	/* Everyone else uses BAR 0 */
+	else {
+		brd->membase     = pci_resource_start(pdev, 0);
+		brd->membase_end = pci_resource_end(pdev, 0);
+	}
+
+	if (!brd->membase)
+		return -ENODEV;
+
+	if (brd->membase & 1)
+		brd->membase &= ~3;
+	else
+		brd->membase &= ~15;
+
+	/*
+	 * On the PCI boards, there is no IO space allocated
+	 * The I/O registers will be in the first 3 bytes of the
+	 * upper 2MB of the 4MB memory space.  The board memory
+	 * will be mapped into the low 2MB of the 4MB memory space
+	 */
+	brd->port = brd->membase + PCI_IO_OFFSET;
+	brd->port_end = brd->port + PCI_IO_SIZE;
+
+	/*
+	 * Special initialization for non-PLX boards
+	 */
+	if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
+		unsigned short cmd;
+
+		pci_write_config_byte(pdev, 0x40, 0);
+		pci_write_config_byte(pdev, 0x46, 0);
+
+		/* Limit burst length to 2 doubleword transactions */
+		pci_write_config_byte(pdev, 0x42, 1);
+
+		/*
+		 * Enable IO and mem if not already done.
+		 * This was needed for support on Itanium.
+		 */
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		pci_write_config_word(pdev, PCI_COMMAND, cmd);
+	}
+
+	/* init our poll helper tasklet */
+	tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
+
+	DGAP_LOCK(dgap_global_lock, flags);
+	brd->msgbuf = NULL;
+	printk("%s", brd->msgbuf_head);
+	kfree(brd->msgbuf_head);
+	brd->msgbuf_head = NULL;
+	DGAP_UNLOCK(dgap_global_lock, flags);
+
+	i = dgap_do_remap(brd);
+	if (i)
+		brd->state = BOARD_FAILED;
+	else
+		brd->state = NEED_RESET;
+
+	return 0;
+}
+
+
+static int dgap_finalize_board_init(struct board_t *brd)
+{
+	int rc;
+
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return -ENODEV;
+
+	brd->use_interrupts = dgap_config_get_useintr(brd);
+
+	/*
+	 * Set up our interrupt handler if we are set to do interrupts.
+	 */
+	if (brd->use_interrupts && brd->irq) {
+
+		rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
+
+		if (rc)
+			brd->intr_used = 0;
+		else
+			brd->intr_used = 1;
+	} else {
+		brd->intr_used = 0;
+	}
+
+	return 0;
+}
+
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
+{
+	struct board_t *brd = dgap_Board[dgap_NumBoards - 1];
+	const struct firmware *fw;
+	int ret;
+
+	dgap_get_vpd(brd);
+	dgap_do_reset_board(brd);
+
+	if ((fw_info[card_type].conf_name) &&
+	    (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD)) {
+		ret = request_firmware(&fw, fw_info[card_type].conf_name,
+					 &pdev->dev);
+		if (ret) {
+			pr_err("dgap: config file %s not found\n",
+				fw_info[card_type].conf_name);
+			return ret;
+		}
+		if (!dgap_config_buf) {
+			dgap_config_buf = kmalloc(fw->size + 1, GFP_ATOMIC);
+			if (!dgap_config_buf) {
+				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)
+			return -EINVAL;
+
+		dgap_driver_state = -1;
+	}
+
+	ret = dgap_after_config_loaded(brd->boardnum);
+	if (ret)
+		return ret;
+	/*
+	 * Match this board to a config the user created for us.
+	 */
+	brd->bd_config =
+		dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot);
+
+	/*
+	 * Because the 4 port Xr products share the same PCI ID
+	 * as the 8 port Xr products, if we receive a NULL config
+	 * back, and this is a PAPORT8 board, retry with a
+	 * PAPORT4 attempt as well.
+	 */
+	if (brd->type == PAPORT8 && !brd->bd_config)
+		brd->bd_config =
+			dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot);
+
+	if (!brd->bd_config) {
+		pr_err("dgap: No valid configuration found\n");
+		return -EINVAL;
+	}
+
+	dgap_tty_register(brd);
+	dgap_finalize_board_init(brd);
+
+	if (fw_info[card_type].bios_name) {
+		ret = request_firmware(&fw, fw_info[card_type].bios_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: bios file %s not found\n",
+				fw_info[card_type].bios_name);
+			return ret;
+		}
+		dgap_do_bios_load(brd, (char *)fw->data, fw->size);
+		release_firmware(fw);
+
+		/* Wait for BIOS to test board... */
+		dgap_do_wait_for_bios(brd);
+
+		if (brd->state != FINISHED_BIOS_LOAD)
+			return -ENXIO;
+	}
+
+	if (fw_info[card_type].fep_name) {
+		ret = request_firmware(&fw, fw_info[card_type].fep_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: fep file %s not found\n",
+				fw_info[card_type].fep_name);
+			return ret;
+		}
+		dgap_do_fep_load(brd, (char *)fw->data, fw->size);
+		release_firmware(fw);
+
+		/* Wait for FEP to load on board... */
+		dgap_do_wait_for_fep(brd);
+
+		if (brd->state != FINISHED_FEP_LOAD)
+			return -ENXIO;
+	}
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+	/*
+	 * If this is a CX or EPCX, we need to see if the firmware
+	 * is requesting a concentrator image from us.
+	 */
+	if ((bd->type == PCX) || (bd->type == PEPC)) {
+		chk_addr = (u16 *) (vaddr + DOWNREQ);
+		/* Nonzero if FEP is requesting concentrator image. */
+		check = readw(chk_addr);
+		vaddr = brd->re_map_membase;
+	}
+
+	if (fw_info[card_type].con_name && check && vaddr) {
+		ret = request_firmware(&fw, fw_info[card_type].con_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: conc file %s not found\n",
+				fw_info[card_type].con_name);
+			return ret;
+		}
+		/* Put concentrator firmware loading code here */
+		offset = readw((u16 *) (vaddr + DOWNREQ));
+		memcpy_toio(offset, fw->data, fw->size);
+
+		dgap_do_conc_load(brd, (char *)fw->data, fw->size)
+		release_firmware(fw);
+	}
+#endif
+	/*
+	 * Do tty device initialization.
+	 */
+	ret = dgap_tty_init(brd);
+	if (ret < 0) {
+		dgap_tty_uninit(brd);
+		return ret;
+	}
+
+	ret = dgap_tty_register_ports(brd);
+	if (ret)
+		return ret;
+
+	brd->state = BOARD_READY;
+	brd->dpastatus = BD_RUNNING;
+
+	return 0;
+}
+
+/*
+ * Remap PCI memory.
+ */
+static int dgap_do_remap(struct board_t *brd)
+{
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	if (!request_mem_region(brd->membase, 0x200000, "dgap"))
+		return -ENOMEM;
+
+	if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
+		release_mem_region(brd->membase, 0x200000);
+		return -ENOMEM;
+	}
+
+	brd->re_map_membase = ioremap(brd->membase, 0x200000);
+	if (!brd->re_map_membase) {
+		release_mem_region(brd->membase, 0x200000);
+		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+		return -ENOMEM;
+	}
+
+	brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
+	if (!brd->re_map_port) {
+		release_mem_region(brd->membase, 0x200000);
+		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+		iounmap(brd->re_map_membase);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+*
+* Function:
+*
+*    dgap_poll_handler
+*
+* Author:
+*
+*    Scott H Kilau
+*
+* Parameters:
+*
+*    dummy -- ignored
+*
+* Return Values:
+*
+*    none
+*
+* Description:
+*
+*    As each timer expires, it determines (a) whether the "transmit"
+*    waiter needs to be woken up, and (b) whether the poller needs to
+*    be rescheduled.
+*
+******************************************************************************/
+
+static void dgap_poll_handler(ulong dummy)
+{
+	int i;
+	struct board_t *brd;
+	unsigned long lock_flags;
+	ulong new_time;
+
+	dgap_poll_counter++;
+
+	/*
+	 * Do not start the board state machine until
+	 * driver tells us its up and running, and has
+	 * everything it needs.
+	 */
+	if (dgap_driver_state != DRIVER_READY)
+		goto schedule_poller;
+
+	/*
+	 * If we have just 1 board, or the system is not SMP,
+	 * then use the typical old style poller.
+	 * Otherwise, use our new tasklet based poller, which should
+	 * speed things up for multiple boards.
+	 */
+	if ((dgap_NumBoards == 1) || (num_online_cpus() <= 1)) {
+		for (i = 0; i < dgap_NumBoards; i++) {
+
+			brd = dgap_Board[i];
+
+			if (brd->state == BOARD_FAILED)
+				continue;
+			if (!brd->intr_running)
+				/* Call the real board poller directly */
+				dgap_poll_tasklet((unsigned long) brd);
+		}
+	} else {
+		/* Go thru each board, kicking off a tasklet for each if needed */
+		for (i = 0; i < dgap_NumBoards; i++) {
+			brd = dgap_Board[i];
+
+			/*
+			 * Attempt to grab the board lock.
+			 *
+			 * If we can't get it, no big deal, the next poll will get it.
+			 * Basically, I just really don't want to spin in here, because I want
+			 * to kick off my tasklets as fast as I can, and then get out the poller.
+			 */
+			if (!spin_trylock(&brd->bd_lock))
+				continue;
+
+			/* If board is in a failed state, don't bother scheduling a tasklet */
+			if (brd->state == BOARD_FAILED) {
+				spin_unlock(&brd->bd_lock);
+				continue;
+			}
+
+			/* Schedule a poll helper task */
+			if (!brd->intr_running)
+				tasklet_schedule(&brd->helper_tasklet);
+
+			/*
+			 * Can't do DGAP_UNLOCK here, as we don't have
+			 * lock_flags because we did a trylock above.
+			 */
+			spin_unlock(&brd->bd_lock);
+		}
+	}
+
+schedule_poller:
+
+	/*
+	 * Schedule ourself back at the nominal wakeup interval.
+	 */
+	DGAP_LOCK(dgap_poll_lock, lock_flags);
+	dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
+
+	new_time = dgap_poll_time - jiffies;
+
+	if ((ulong) new_time >= 2 * dgap_poll_tick)
+		dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
+
+	dgap_poll_timer.function = dgap_poll_handler;
+	dgap_poll_timer.data = 0;
+	dgap_poll_timer.expires = dgap_poll_time;
+	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+	if (!dgap_poll_stop)
+		add_timer(&dgap_poll_timer);
+}
+
+/*
+ * dgap_intr()
+ *
+ * Driver interrupt handler.
+ */
+static irqreturn_t dgap_intr(int irq, void *voidbrd)
+{
+	struct board_t *brd = (struct board_t *) voidbrd;
+
+	if (!brd)
+		return IRQ_NONE;
+
+	/*
+	 * Check to make sure its for us.
+	 */
+	if (brd->magic != DGAP_BOARD_MAGIC)
+		return IRQ_NONE;
+
+	brd->intr_count++;
+
+	/*
+	 * Schedule tasklet to run at a better time.
+	 */
+	tasklet_schedule(&brd->helper_tasklet);
+	return IRQ_HANDLED;
+}
+
+/*
+ * dgap_init_globals()
+ *
+ * This is where we initialize the globals from the static insmod
+ * configuration variables.  These are declared near the head of
+ * this file.
+ */
+static void dgap_init_globals(void)
+{
+	int i = 0;
+
+	dgap_rawreadok		= rawreadok;
+
+	for (i = 0; i < MAXBOARDS; i++)
+		dgap_Board[i] = NULL;
+
+	init_timer(&dgap_poll_timer);
+
+	init_waitqueue_head(&dgap_dl_wait);
+	dgap_dl_action = 0;
+}
+
+/************************************************************************
+ *
+ * Utility functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_ms_sleep()
+ *
+ * Put the driver to sleep for x ms's
+ *
+ * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
+ */
+static int dgap_ms_sleep(ulong ms)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((ms * HZ) / 1000);
+	return signal_pending(current);
+}
+
+/************************************************************************
+ *
+ * TTY Initialization/Cleanup Functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_preinit()
+ *
+ * Initialize any global tty related data before we download any boards.
+ */
+static int dgap_tty_preinit(void)
+{
+	unsigned long flags;
+
+	DGAP_LOCK(dgap_global_lock, flags);
+
+	/*
+	 * Allocate a buffer for doing the copy from user space to
+	 * kernel space in dgap_input().  We only use one buffer and
+	 * control access to it with a semaphore.  If we are paging, we
+	 * are already in trouble so one buffer won't hurt much anyway.
+	 */
+	dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
+
+	if (!dgap_TmpWriteBuf) {
+		DGAP_UNLOCK(dgap_global_lock, flags);
+		return -ENOMEM;
+	}
+
+	DGAP_UNLOCK(dgap_global_lock, flags);
+	return 0;
+}
+
+/*
+ * dgap_tty_register()
+ *
+ * Init the tty subsystem for this board.
+ */
+static int dgap_tty_register(struct board_t *brd)
+{
+	int rc = 0;
+
+	brd->SerialDriver = alloc_tty_driver(MAXPORTS);
+
+	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
+	brd->SerialDriver->name = brd->SerialName;
+	brd->SerialDriver->name_base = 0;
+	brd->SerialDriver->major = 0;
+	brd->SerialDriver->minor_start = 0;
+	brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
+	brd->SerialDriver->init_termios = DgapDefaultTermios;
+	brd->SerialDriver->driver_name = DRVSTR;
+	brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/* The kernel wants space to store pointers to tty_structs */
+	brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->SerialDriver->ttys)
+		return -ENOMEM;
+
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
+
+	/*
+	 * If we're doing transparent print, we have to do all of the above
+	 * again, separately so we don't get the LD confused about what major
+	 * we are when we get into the dgap_tty_open() routine.
+	 */
+	brd->PrintDriver = alloc_tty_driver(MAXPORTS);
+
+	snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
+	brd->PrintDriver->name = brd->PrintName;
+	brd->PrintDriver->name_base = 0;
+	brd->PrintDriver->major = 0;
+	brd->PrintDriver->minor_start = 0;
+	brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
+	brd->PrintDriver->init_termios = DgapDefaultTermios;
+	brd->PrintDriver->driver_name = DRVSTR;
+	brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/* The kernel wants space to store pointers to tty_structs */
+	brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->PrintDriver->ttys)
+		return -ENOMEM;
+
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
+
+	if (!brd->dgap_Major_Serial_Registered) {
+		/* Register tty devices */
+		rc = tty_register_driver(brd->SerialDriver);
+		if (rc < 0)
+			return rc;
+		brd->dgap_Major_Serial_Registered = TRUE;
+		dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
+		brd->dgap_Serial_Major = brd->SerialDriver->major;
+	}
+
+	if (!brd->dgap_Major_TransparentPrint_Registered) {
+		/* Register Transparent Print devices */
+		rc = tty_register_driver(brd->PrintDriver);
+		if (rc < 0)
+			return rc;
+		brd->dgap_Major_TransparentPrint_Registered = TRUE;
+		dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
+		brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
+	}
+
+	return rc;
+}
+
+/*
+ * dgap_tty_init()
+ *
+ * Init the tty subsystem.  Called once per board after board has been
+ * downloaded and init'ed.
+ */
+static int dgap_tty_init(struct board_t *brd)
+{
+	int i;
+	int tlw;
+	uint true_count = 0;
+	uchar *vaddr;
+	uchar modem = 0;
+	struct channel_t *ch;
+	struct bs_t *bs;
+	struct cm_t *cm;
+
+	if (!brd)
+		return -ENXIO;
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	vaddr = brd->re_map_membase;
+	true_count = readw((vaddr + NCHAN));
+
+	brd->nasync = dgap_config_get_number_of_ports(brd);
+
+	if (!brd->nasync)
+		brd->nasync = brd->maxports;
+
+	if (brd->nasync > brd->maxports)
+		brd->nasync = brd->maxports;
+
+	if (true_count != brd->nasync) {
+		if ((brd->type == PPCM) && (true_count == 64))
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+				brd->name, brd->nasync, true_count);
+		else if ((brd->type == PPCM) && (true_count == 0))
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+				brd->name, brd->nasync, true_count);
+		else
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\n",
+				brd->name, brd->nasync, true_count);
+
+		brd->nasync = true_count;
+
+		/* If no ports, don't bother going any further */
+		if (!brd->nasync) {
+			brd->state = BOARD_FAILED;
+			brd->dpastatus = BD_NOFEP;
+			return -ENXIO;
+		}
+	}
+
+	/*
+	 * Allocate channel memory that might not have been allocated
+	 * when the driver was first loaded.
+	 */
+	for (i = 0; i < brd->nasync; i++) {
+		if (!brd->channels[i]) {
+			brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
+			if (!brd->channels[i])
+				return -ENOMEM;
+		}
+	}
+
+	ch = brd->channels[0];
+	vaddr = brd->re_map_membase;
+
+	bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
+	cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
+
+	brd->bd_bs = bs;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
+
+		if (!brd->channels[i])
+			continue;
+
+		DGAP_SPINLOCK_INIT(ch->ch_lock);
+
+		/* Store all our magic numbers */
+		ch->magic = DGAP_CHANNEL_MAGIC;
+		ch->ch_tun.magic = DGAP_UNIT_MAGIC;
+		ch->ch_tun.un_type = DGAP_SERIAL;
+		ch->ch_tun.un_ch = ch;
+		ch->ch_tun.un_dev = i;
+
+		ch->ch_pun.magic = DGAP_UNIT_MAGIC;
+		ch->ch_pun.un_type = DGAP_PRINT;
+		ch->ch_pun.un_ch = ch;
+		ch->ch_pun.un_dev = i;
+
+		ch->ch_vaddr = vaddr;
+		ch->ch_bs = bs;
+		ch->ch_cm = cm;
+		ch->ch_bd = brd;
+		ch->ch_portnum = i;
+		ch->ch_digi = dgap_digi_init;
+
+		/*
+		 * Set up digi dsr and dcd bits based on altpin flag.
+		 */
+		if (dgap_config_get_altpin(brd)) {
+			ch->ch_dsr	= DM_CD;
+			ch->ch_cd	= DM_DSR;
+			ch->ch_digi.digi_flags |= DIGI_ALTPIN;
+		} else {
+			ch->ch_cd	= DM_CD;
+			ch->ch_dsr	= DM_DSR;
+		}
+
+		ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
+		ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
+		ch->ch_tx_win = 0;
+		ch->ch_rx_win = 0;
+		ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
+		ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
+		ch->ch_tstart = 0;
+		ch->ch_rstart = 0;
+
+		/* .25 second delay */
+		ch->ch_close_delay = 250;
+
+		/*
+		 * Set queue water marks, interrupt mask,
+		 * and general tty parameters.
+		 */
+		ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
+
+		dgap_cmdw(ch, STLOW, tlw, 0);
+
+		dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
+
+		dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
+
+		ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
+
+		init_waitqueue_head(&ch->ch_flags_wait);
+		init_waitqueue_head(&ch->ch_tun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_pun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_sniff_wait);
+
+		/* Turn on all modem interrupts for now */
+		modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
+		writeb(modem, &(ch->ch_bs->m_int));
+
+		/*
+		 * Set edelay to 0 if interrupts are turned on,
+		 * otherwise set edelay to the usual 100.
+		 */
+		if (brd->intr_used)
+			writew(0, &(ch->ch_bs->edelay));
+		else
+			writew(100, &(ch->ch_bs->edelay));
+
+		writeb(1, &(ch->ch_bs->idata));
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_tty_post_uninit()
+ *
+ * UnInitialize any global tty related data.
+ */
+static void dgap_tty_post_uninit(void)
+{
+	kfree(dgap_TmpWriteBuf);
+	dgap_TmpWriteBuf = NULL;
+}
+
+/*
+ * dgap_tty_uninit()
+ *
+ * Uninitialize the TTY portion of this driver.  Free all memory and
+ * resources.
+ */
+static void dgap_tty_uninit(struct board_t *brd)
+{
+	int i = 0;
+
+	if (brd->dgap_Major_Serial_Registered) {
+		dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
+		brd->dgap_Serial_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			tty_port_destroy(&brd->SerialPorts[i]);
+			dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
+			tty_unregister_device(brd->SerialDriver, i);
+		}
+		tty_unregister_driver(brd->SerialDriver);
+		kfree(brd->SerialDriver->ttys);
+		brd->SerialDriver->ttys = NULL;
+		put_tty_driver(brd->SerialDriver);
+		kfree(brd->SerialPorts);
+		brd->dgap_Major_Serial_Registered = FALSE;
+	}
+
+	if (brd->dgap_Major_TransparentPrint_Registered) {
+		dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
+		brd->dgap_TransparentPrint_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			tty_port_destroy(&brd->PrinterPorts[i]);
+			dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
+			tty_unregister_device(brd->PrintDriver, i);
+		}
+		tty_unregister_driver(brd->PrintDriver);
+		kfree(brd->PrintDriver->ttys);
+		brd->PrintDriver->ttys = NULL;
+		put_tty_driver(brd->PrintDriver);
+		kfree(brd->PrinterPorts);
+		brd->dgap_Major_TransparentPrint_Registered = FALSE;
+	}
+}
+
+#define TMPBUFLEN (1024)
+/*
+ * 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)
+{
+	struct timeval tv;
+	int n;
+	int r;
+	int nbuf;
+	int i;
+	int tmpbuflen;
+	char tmpbuf[TMPBUFLEN];
+	char *p = tmpbuf;
+	int too_much_data;
+
+	/* Leave if sniff not open */
+	if (!(ch->ch_sniff_flags & SNIFF_OPEN))
+		return;
+
+	do_gettimeofday(&tv);
+
+	/* Create our header for data dump */
+	p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
+	tmpbuflen = p - tmpbuf;
+
+	do {
+		too_much_data = 0;
+
+		for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
+			p += sprintf(p, "%02x ", *buf);
+			buf++;
+			tmpbuflen = p - tmpbuf;
+		}
+
+		if (tmpbuflen < (TMPBUFLEN - 4)) {
+			if (i > 0)
+				p += sprintf(p - 1, "%s\n", ">");
+			else
+				p += sprintf(p, "%s\n", ">");
+		} else {
+			too_much_data = 1;
+			len -= i;
+		}
+
+		nbuf = strlen(tmpbuf);
+		p = tmpbuf;
+
+		/*
+		 *  Loop while data remains.
+		 */
+		while (nbuf > 0 && ch->ch_sniff_buf) {
+			/*
+			 *  Determine the amount of available space left in the
+			 *  buffer.  If there's none, wait until some appears.
+			 */
+			n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
+
+			/*
+			 * If there is no space left to write to in our sniff buffer,
+			 * we have no choice but to drop the data.
+			 * We *cannot* sleep here waiting for space, because this
+			 * function was probably called by the interrupt/timer routines!
+			 */
+			if (n == 0)
+				return;
+
+			/*
+			 * Copy as much data as will fit.
+			 */
+
+			if (n > nbuf)
+				n = nbuf;
+
+			r = SNIFF_MAX - ch->ch_sniff_in;
+
+			if (r <= n) {
+				memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
+
+				n -= r;
+				ch->ch_sniff_in = 0;
+				p += r;
+				nbuf -= r;
+			}
+
+			memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
+
+			ch->ch_sniff_in += n;
+			p += n;
+			nbuf -= n;
+
+			/*
+			 *  Wakeup any thread waiting for data
+			 */
+			if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
+				ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
+				wake_up_interruptible(&ch->ch_sniff_wait);
+			}
+		}
+
+		/*
+		 * If the user sent us too much data to push into our tmpbuf,
+		 * we need to keep looping around on all the data.
+		 */
+		if (too_much_data) {
+			p = tmpbuf;
+			tmpbuflen = 0;
+		}
+
+	} while (too_much_data);
+}
+
+/*=======================================================================
+ *
+ *      dgap_input - Process received data.
+ *
+ *              ch      - Pointer to channel structure.
+ *
+ *=======================================================================*/
+
+static void dgap_input(struct channel_t *ch)
+{
+	struct board_t *bd;
+	struct bs_t	*bs;
+	struct tty_struct *tp;
+	struct tty_ldisc *ld;
+	uint	rmask;
+	uint	head;
+	uint	tail;
+	int	data_len;
+	ulong	lock_flags;
+	ulong   lock_flags2;
+	int flip_len;
+	int len = 0;
+	int n = 0;
+	uchar *buf;
+	uchar tmpchar;
+	int s = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	tp = ch->ch_tun.un_tty;
+
+	bs  = ch->ch_bs;
+	if (!bs)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/*
+	 *      Figure the number of characters in the buffer.
+	 *      Exit immediately if none.
+	 */
+
+	rmask = ch->ch_rsize - 1;
+
+	head = readw(&(bs->rx_head));
+	head &= rmask;
+	tail = readw(&(bs->rx_tail));
+	tail &= rmask;
+
+	data_len = (head - tail) & rmask;
+
+	if (data_len == 0) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If the device is not open, or CREAD is off, flush
+	 * input data and return immediately.
+	 */
+	if ((bd->state != BOARD_READY) || !tp  ||
+	    (tp->magic != TTY_MAGIC) ||
+	    !(ch->ch_tun.un_flags & UN_ISOPEN) ||
+	    !(tp->termios.c_cflag & CREAD) ||
+	    (ch->ch_tun.un_flags & UN_CLOSING)) {
+
+		writew(head, &(bs->rx_tail));
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If we are throttled, simply don't read any data.
+	 */
+	if (ch->ch_flags & CH_RXBLOCK) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 *      Ignore oruns.
+	 */
+	tmpchar = readb(&(bs->orun));
+	if (tmpchar) {
+		ch->ch_err_overrun++;
+		writeb(0, &(bs->orun));
+	}
+
+	/* Decide how much data we can send into the tty layer */
+	flip_len = TTY_FLIPBUF_SIZE;
+
+	/* Chop down the length, if needed */
+	len = min(data_len, flip_len);
+	len = min(len, (N_TTY_BUF_SIZE - 1));
+
+	ld = tty_ldisc_ref(tp);
+
+#ifdef TTY_DONT_FLIP
+	/*
+	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
+	 * like the ld doesn't have any space to put the data right now.
+	 */
+	if (test_bit(TTY_DONT_FLIP, &tp->flags))
+		len = 0;
+#endif
+
+	/*
+	 * If we were unable to get a reference to the ld,
+	 * don't flush our buffer, and act like the ld doesn't
+	 * have any space to put the data right now.
+	 */
+	if (!ld) {
+		len = 0;
+	} else {
+		/*
+		 * If ld doesn't have a pointer to a receive_buf function,
+		 * flush the data, then act like the ld doesn't have any
+		 * space to put the data right now.
+		 */
+		if (!ld->ops->receive_buf) {
+			writew(head, &(bs->rx_tail));
+			len = 0;
+		}
+	}
+
+	if (len <= 0) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (ld)
+			tty_ldisc_deref(ld);
+		return;
+	}
+
+	buf = ch->ch_bd->flipbuf;
+	n = len;
+
+	/*
+	 * n now contains the most amount of data we can copy,
+	 * bounded either by our buffer size or the amount
+	 * of data the card actually has pending...
+	 */
+	while (n) {
+
+		s = ((head >= tail) ? head : ch->ch_rsize) - tail;
+		s = min(s, n);
+
+		if (s <= 0)
+			break;
+
+		memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
+		dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
+
+		tail += s;
+		buf += s;
+
+		n -= s;
+		/* Flip queue if needed */
+		tail &= rmask;
+	}
+
+	writew(tail, &(bs->rx_tail));
+	writeb(1, &(bs->idata));
+	ch->ch_rxcount += len;
+
+	/*
+	 * If we are completely raw, we don't need to go through a lot
+	 * of the tty layers that exist.
+	 * In this case, we take the shortest and fastest route we
+	 * can to relay the data to the user.
+	 *
+	 * On the other hand, if we are not raw, we need to go through
+	 * the tty layer, which has its API more well defined.
+	 */
+	if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+		dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
+
+		len = tty_buffer_request_room(tp->port, len);
+		tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
+			ch->ch_bd->flipflagbuf, len);
+	} else {
+		len = tty_buffer_request_room(tp->port, len);
+		tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
+	}
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	/* Tell the tty layer its okay to "eat" the data now */
+	tty_flip_buffer_push(tp->port);
+
+	if (ld)
+		tty_ldisc_deref(ld);
+
+}
+
+/************************************************************************
+ * Determines when CARRIER changes state and takes appropriate
+ * action.
+ ************************************************************************/
+static void dgap_carrier(struct channel_t *ch)
+{
+	struct board_t *bd;
+
+	int virt_carrier = 0;
+	int phys_carrier = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	/* Make sure altpin is always set correctly */
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
+		ch->ch_dsr      = DM_CD;
+		ch->ch_cd       = DM_DSR;
+	} else {
+		ch->ch_dsr      = DM_DSR;
+		ch->ch_cd       = DM_CD;
+	}
+
+	if (ch->ch_mistat & D_CD(ch))
+		phys_carrier = 1;
+
+	if (ch->ch_digi.digi_flags & DIGI_FORCEDCD)
+		virt_carrier = 1;
+
+	if (ch->ch_c_cflag & CLOCAL)
+		virt_carrier = 1;
+
+	/*
+	 * Test for a VIRTUAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 * Test for a PHYSICAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 *  Test for a PHYSICAL transition to low, so long as we aren't
+	 *  currently ignoring physical transitions (which is what "virtual
+	 *  carrier" indicates).
+	 *
+	 *  The transition of the virtual carrier to low really doesn't
+	 *  matter... it really only means "ignore carrier state", not
+	 *  "make pretend that carrier is there".
+	 */
+	if ((virt_carrier == 0) &&
+	    ((ch->ch_flags & CH_CD) != 0) &&
+	    (phys_carrier == 0)) {
+
+		/*
+		 *   When carrier drops:
+		 *
+		 *   Drop carrier on all open units.
+		 *
+		 *   Flush queues, waking up any task waiting in the
+		 *   line discipline.
+		 *
+		 *   Send a hangup to the control terminal.
+		 *
+		 *   Enable all select calls.
+		 */
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+
+		if (ch->ch_tun.un_open_count > 0)
+			tty_hangup(ch->ch_tun.un_tty);
+
+		if (ch->ch_pun.un_open_count > 0)
+			tty_hangup(ch->ch_pun.un_tty);
+	}
+
+	/*
+	 *  Make sure that our cached values reflect the current reality.
+	 */
+	if (virt_carrier == 1)
+		ch->ch_flags |= CH_FCAR;
+	else
+		ch->ch_flags &= ~CH_FCAR;
+
+	if (phys_carrier == 1)
+		ch->ch_flags |= CH_CD;
+	else
+		ch->ch_flags &= ~CH_CD;
+}
+
+/************************************************************************
+ *
+ * TTY Entry points and helper functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_open()
+ *
+ */
+static int dgap_tty_open(struct tty_struct *tty, struct file *file)
+{
+	struct board_t	*brd;
+	struct channel_t *ch;
+	struct un_t	*un;
+	struct bs_t	*bs;
+	uint		major = 0;
+	uint		minor = 0;
+	int		rc = 0;
+	ulong		lock_flags;
+	ulong		lock_flags2;
+	u16		head;
+
+	rc = 0;
+
+	major = MAJOR(tty_devnum(tty));
+	minor = MINOR(tty_devnum(tty));
+
+	if (major > 255)
+		return -ENXIO;
+
+	/* Get board pointer from our array of majors we have allocated */
+	brd = dgap_BoardsByMajor[major];
+	if (!brd)
+		return -ENXIO;
+
+	/*
+	 * If board is not yet up to a state of READY, go to
+	 * sleep waiting for it to happen or they cancel the open.
+	 */
+	rc = wait_event_interruptible(brd->state_wait,
+		(brd->state & BOARD_READY));
+
+	if (rc)
+		return rc;
+
+	DGAP_LOCK(brd->bd_lock, lock_flags);
+
+	/* The wait above should guarantee this cannot happen */
+	if (brd->state != BOARD_READY) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* If opened device is greater than our number of ports, bail. */
+	if (MINOR(tty_devnum(tty)) > brd->nasync) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	ch = brd->channels[minor];
+	if (!ch) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* Grab channel lock */
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/* Figure out our type */
+	if (major == brd->dgap_Serial_Major) {
+		un = &brd->channels[minor]->ch_tun;
+		un->un_type = DGAP_SERIAL;
+	} else if (major == brd->dgap_TransparentPrint_Major) {
+		un = &brd->channels[minor]->ch_pun;
+		un->un_type = DGAP_PRINT;
+	} else {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* Store our unit into driver_data, so we always have it available. */
+	tty->driver_data = un;
+
+	/*
+	 * Error if channel info pointer is NULL.
+	 */
+	bs = ch->ch_bs;
+	if (!bs) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/*
+	 * Initialize tty's
+	 */
+	if (!(un->un_flags & UN_ISOPEN)) {
+		/* Store important variables. */
+		un->un_tty     = tty;
+
+		/* Maybe do something here to the TTY struct as well? */
+	}
+
+	/*
+	 * Initialize if neither terminal or printer is open.
+	 */
+	if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
+
+		ch->ch_mforce = 0;
+		ch->ch_mval = 0;
+
+		/*
+		 * Flush input queue.
+		 */
+		head = readw(&(bs->rx_head));
+		writew(head, &(bs->rx_tail));
+
+		ch->ch_flags = 0;
+		ch->pscan_state = 0;
+		ch->pscan_savechar = 0;
+
+		ch->ch_c_cflag   = tty->termios.c_cflag;
+		ch->ch_c_iflag   = tty->termios.c_iflag;
+		ch->ch_c_oflag   = tty->termios.c_oflag;
+		ch->ch_c_lflag   = tty->termios.c_lflag;
+		ch->ch_startc = tty->termios.c_cc[VSTART];
+		ch->ch_stopc  = tty->termios.c_cc[VSTOP];
+
+		/* TODO: flush our TTY struct here? */
+	}
+
+	dgap_carrier(ch);
+	/*
+	 * Run param in case we changed anything
+	 */
+	dgap_param(tty);
+
+	/*
+	 * follow protocol for opening port
+	 */
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(brd->bd_lock, lock_flags);
+
+	rc = dgap_block_til_ready(tty, file, ch);
+
+	if (!un->un_tty)
+		return -ENODEV;
+
+	/* No going back now, increment our unit and channel counters */
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	ch->ch_open_count++;
+	un->un_open_count++;
+	un->un_flags |= (UN_ISOPEN);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return rc;
+}
+
+/*
+ * dgap_block_til_ready()
+ *
+ * Wait for DCD, if needed.
+ */
+static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
+{
+	int retval = 0;
+	struct un_t *un = NULL;
+	ulong   lock_flags;
+	uint	old_flags = 0;
+	int sleep_on_un_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC || !file || !ch ||
+		ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_wopen++;
+
+	/* Loop forever */
+	while (1) {
+
+		sleep_on_un_flags = 0;
+
+		/*
+		 * If board has failed somehow during our sleep, bail with error.
+		 */
+		if (ch->ch_bd->state == BOARD_FAILED) {
+			retval = -ENXIO;
+			break;
+		}
+
+		/* If tty was hung up, break out of loop and set error. */
+		if (tty_hung_up_p(file)) {
+			retval = -EAGAIN;
+			break;
+		}
+
+		/*
+		 * If either unit is in the middle of the fragile part of close,
+		 * we just cannot touch the channel safely.
+		 * Go back to sleep, knowing that when the channel can be
+		 * touched safely, the close routine will signal the
+		 * ch_wait_flags to wake us back up.
+		 */
+		if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
+
+			/*
+			 * Our conditions to leave cleanly and happily:
+			 * 1) NONBLOCKING on the tty is set.
+			 * 2) CLOCAL is set.
+			 * 3) DCD (fake or real) is active.
+			 */
+
+			if (file->f_flags & O_NONBLOCK)
+				break;
+
+			if (tty->flags & (1 << TTY_IO_ERROR))
+				break;
+
+			if (ch->ch_flags & CH_CD)
+				break;
+
+			if (ch->ch_flags & CH_FCAR)
+				break;
+		} else {
+			sleep_on_un_flags = 1;
+		}
+
+		/*
+		 * If there is a signal pending, the user probably
+		 * interrupted (ctrl-c) us.
+		 * Leave loop with error set.
+		 */
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+		/*
+		 * Store the flags before we let go of channel lock
+		 */
+		if (sleep_on_un_flags)
+			old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
+		else
+			old_flags = ch->ch_flags;
+
+		/*
+		 * Let go of channel lock before calling schedule.
+		 * Our poller will get any FEP events and wake us up when DCD
+		 * eventually goes active.
+		 */
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * Wait for something in the flags to change from the current value.
+		 */
+		if (sleep_on_un_flags) {
+			retval = wait_event_interruptible(un->un_flags_wait,
+				(old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
+		} else {
+			retval = wait_event_interruptible(ch->ch_flags_wait,
+				(old_flags != ch->ch_flags));
+		}
+
+		/*
+		 * We got woken up for some reason.
+		 * Before looping around, grab our channel lock.
+		 */
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+	}
+
+	ch->ch_wopen--;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_hangup()
+ *
+ * Hangup the port.  Like a close, but don't wait for output to drain.
+ */
+static void dgap_tty_hangup(struct tty_struct *tty)
+{
+	struct board_t	*bd;
+	struct channel_t *ch;
+	struct un_t	*un;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	/* flush the transmit queues */
+	dgap_tty_flush_buffer(tty);
+
+}
+
+/*
+ * dgap_tty_close()
+ *
+ */
+static void dgap_tty_close(struct tty_struct *tty, struct file *file)
+{
+	struct ktermios *ts;
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+	int rc = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	ts = &tty->termios;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * Determine if this is the last close or not - and if we agree about
+	 * which type of close it is with the Line Discipline
+	 */
+	if ((tty->count == 1) && (un->un_open_count != 1))
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  un_open_count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		un->un_open_count = 1;
+
+	if (--un->un_open_count < 0)
+		un->un_open_count = 0;
+
+	ch->ch_open_count--;
+
+	if (ch->ch_open_count && un->un_open_count) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* OK, its the last close on the unit */
+
+	un->un_flags |= UN_CLOSING;
+
+	tty->closing = 1;
+
+	/*
+	 * Only officially close channel if count is 0 and
+	 * DIGI_PRINTER bit is not set.
+	 */
+	if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
+
+		ch->ch_flags &= ~(CH_RXBLOCK);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* wait for output to drain */
+		/* This will also return if we take an interrupt */
+
+		rc = dgap_wait_for_drain(tty);
+
+		dgap_tty_flush_buffer(tty);
+		tty_ldisc_flush(tty);
+
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+
+		tty->closing = 0;
+
+		/*
+		 * If we have HUPCL set, lower DTR and RTS
+		 */
+		if (ch->ch_c_cflag & HUPCL) {
+			ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
+			dgap_cmdb(ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0);
+
+			/*
+			 * Go to sleep to ensure RTS/DTR
+			 * have been dropped for modems to see it.
+			 */
+			if (ch->ch_close_delay) {
+				DGAP_UNLOCK(ch->ch_lock, lock_flags);
+				dgap_ms_sleep(ch->ch_close_delay);
+				DGAP_LOCK(ch->ch_lock, lock_flags);
+			}
+		}
+
+		ch->pscan_state = 0;
+		ch->pscan_savechar = 0;
+		ch->ch_baud_info = 0;
+
+	}
+
+	/*
+	 * turn off print device when closing print device.
+	 */
+	if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_offstr,
+			(int) ch->ch_digi.digi_offlen);
+		ch->ch_flags &= ~CH_PRON;
+	}
+
+	un->un_tty = NULL;
+	un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
+	tty->driver_data = NULL;
+
+	wake_up_interruptible(&ch->ch_flags_wait);
+	wake_up_interruptible(&un->un_flags_wait);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_chars_in_buffer()
+ *
+ * Return number of characters that have not been transmitted yet.
+ *
+ * This routine is used by the line discipline to determine if there
+ * is data waiting to be transmitted/drained/flushed or not.
+ */
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct board_t *bd = NULL;
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	uchar tbusy;
+	uint chars = 0;
+	u16 thead, ttail, tmask, chead, ctail;
+	ulong   lock_flags = 0;
+	ulong   lock_flags2 = 0;
+
+	if (tty == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	tmask = (ch->ch_tsize - 1);
+
+	/* Get Transmit queue pointers */
+	thead = readw(&(bs->tx_head)) & tmask;
+	ttail = readw(&(bs->tx_tail)) & tmask;
+
+	/* Get tbusy flag */
+	tbusy = readb(&(bs->tbusy));
+
+	/* Get Command queue pointers */
+	chead = readw(&(ch->ch_cm->cm_head));
+	ctail = readw(&(ch->ch_cm->cm_tail));
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	/*
+	 * The only way we know for sure if there is no pending
+	 * data left to be transferred, is if:
+	 * 1) Transmit head and tail are equal (empty).
+	 * 2) Command queue head and tail are equal (empty).
+	 * 3) The "TBUSY" flag is 0. (Transmitter not busy).
+	 */
+
+	if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
+		chars = 0;
+	} else {
+		if (thead >= ttail)
+			chars = thead - ttail;
+		else
+			chars = thead - ttail + ch->ch_tsize;
+		/*
+		 * Fudge factor here.
+		 * If chars is zero, we know that the command queue had
+		 * something in it or tbusy was set.  Because we cannot
+		 * be sure if there is still some data to be transmitted,
+		 * lets lie, and tell ld we have 1 byte left.
+		 */
+		if (chars == 0) {
+			/*
+			 * If TBUSY is still set, and our tx buffers are empty,
+			 * force the firmware to send me another wakeup after
+			 * TBUSY has been cleared.
+			 */
+			if (tbusy != 0) {
+				DGAP_LOCK(ch->ch_lock, lock_flags);
+				un->un_flags |= UN_EMPTY;
+				writeb(1, &(bs->iempty));
+				DGAP_UNLOCK(ch->ch_lock, lock_flags);
+			}
+			chars = 1;
+		}
+	}
+
+	return chars;
+}
+
+static int dgap_wait_for_drain(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	struct bs_t *bs;
+	int ret = -EIO;
+	uint count = 1;
+	ulong   lock_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return ret;
+
+	ret = 0;
+
+	/* Loop until data is drained */
+	while (count != 0) {
+
+		count = dgap_tty_chars_in_buffer(tty);
+
+		if (count == 0)
+			break;
+
+		/* Set flag waiting for drain */
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+		un->un_flags |= UN_EMPTY;
+		writeb(1, &(bs->iempty));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* Go to sleep till we get woken up */
+		ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
+		/* If ret is non-zero, user ctrl-c'ed us */
+		if (ret)
+			break;
+	}
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	un->un_flags &= ~(UN_EMPTY);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return ret;
+}
+
+/*
+ * dgap_maxcps_room
+ *
+ * Reduces bytes_available to the max number of characters
+ * that can be sent currently given the maxcps value, and
+ * returns the new bytes_available.  This only affects printer
+ * output.
+ */
+static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+
+	if (tty == NULL)
+		return bytes_available;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return bytes_available;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return bytes_available;
+
+	/*
+	 * If its not the Transparent print device, return
+	 * the full data amount.
+	 */
+	if (un->un_type != DGAP_PRINT)
+		return bytes_available;
+
+	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) {
+		int cps_limit = 0;
+		unsigned long current_time = jiffies;
+		unsigned long buffer_time = current_time +
+			(HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
+
+		if (ch->ch_cpstime < current_time) {
+			/* buffer is empty */
+			ch->ch_cpstime = current_time;            /* reset ch_cpstime */
+			cps_limit = ch->ch_digi.digi_bufsize;
+		} else if (ch->ch_cpstime < buffer_time) {
+			/* still room in the buffer */
+			cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
+		} else {
+			/* no room in the buffer */
+			cps_limit = 0;
+		}
+
+		bytes_available = min(cps_limit, bytes_available);
+	}
+
+	return bytes_available;
+}
+
+static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
+{
+	struct channel_t *ch = NULL;
+	struct bs_t *bs = NULL;
+
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+	bs = ch->ch_bs;
+	if (!bs)
+		return;
+
+	if ((event & UN_LOW) != 0) {
+		if ((un->un_flags & UN_LOW) == 0) {
+			un->un_flags |= UN_LOW;
+			writeb(1, &(bs->ilow));
+		}
+	}
+	if ((event & UN_LOW) != 0) {
+		if ((un->un_flags & UN_EMPTY) == 0) {
+			un->un_flags |= UN_EMPTY;
+			writeb(1, &(bs->iempty));
+		}
+	}
+}
+
+/*
+ * dgap_tty_write_room()
+ *
+ * Return space available in Tx buffer
+ */
+static int dgap_tty_write_room(struct tty_struct *tty)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	u16 head, tail, tmask;
+	int ret = 0;
+	ulong   lock_flags = 0;
+
+	if (tty == NULL || dgap_TmpWriteBuf == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	tmask = ch->ch_tsize - 1;
+	head = readw(&(bs->tx_head)) & tmask;
+	tail = readw(&(bs->tx_tail)) & tmask;
+
+	ret = tail - head - 1;
+	if (ret < 0)
+		ret += ch->ch_tsize;
+
+	/* Limit printer to maxcps */
+	ret = dgap_maxcps_room(tty, ret);
+
+	/*
+	 * If we are printer device, leave space for
+	 * possibly both the on and off strings.
+	 */
+	if (un->un_type == DGAP_PRINT) {
+		if (!(ch->ch_flags & CH_PRON))
+			ret -= ch->ch_digi.digi_onlen;
+		ret -= ch->ch_digi.digi_offlen;
+	} else {
+		if (ch->ch_flags & CH_PRON)
+			ret -= ch->ch_digi.digi_offlen;
+	}
+
+	if (ret < 0)
+		ret = 0;
+
+	/*
+	 * Schedule FEP to wake us up if needed.
+	 *
+	 * TODO:  This might be overkill...
+	 * Do we really need to schedule callbacks from the FEP
+	 * in every case?  Can we get smarter based on ret?
+	 */
+	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return ret;
+}
+
+/*
+ * dgap_tty_put_char()
+ *
+ * Put a character into ch->ch_buf
+ *
+ *      - used by the line discipline for OPOST processing
+ */
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
+{
+	/*
+	 * Simply call tty_write.
+	 */
+	dgap_tty_write(tty, &c, 1);
+	return 1;
+}
+
+/*
+ * dgap_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	char *vaddr = NULL;
+	u16 head, tail, tmask, remain;
+	int bufcount = 0, n = 0;
+	int orig_count = 0;
+	ulong lock_flags;
+	int from_user = 0;
+
+	if (tty == NULL || dgap_TmpWriteBuf == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	if (!count)
+		return 0;
+
+	/*
+	 * Store original amount of characters passed in.
+	 * This helps to figure out if we should ask the FEP
+	 * to send us an event when it has more space available.
+	 */
+	orig_count = count;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	/* Get our space available for the channel from the board */
+	tmask = ch->ch_tsize - 1;
+	head = readw(&(bs->tx_head)) & tmask;
+	tail = readw(&(bs->tx_tail)) & tmask;
+
+	bufcount = tail - head - 1;
+	if (bufcount < 0)
+		bufcount += ch->ch_tsize;
+
+	/*
+	 * Limit printer output to maxcps overall, with bursts allowed
+	 * up to bufsize characters.
+	 */
+	bufcount = dgap_maxcps_room(tty, bufcount);
+
+	/*
+	 * Take minimum of what the user wants to send, and the
+	 * space available in the FEP buffer.
+	 */
+	count = min(count, bufcount);
+
+	/*
+	 * Bail if no space left.
+	 */
+	if (count <= 0) {
+		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return 0;
+	}
+
+	/*
+	 * Output the printer ON string, if we are in terminal mode, but
+	 * need to be in printer mode.
+	 */
+	if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_onstr,
+		    (int) ch->ch_digi.digi_onlen);
+		head = readw(&(bs->tx_head)) & tmask;
+		ch->ch_flags |= CH_PRON;
+	}
+
+	/*
+	 * On the other hand, output the printer OFF string, if we are
+	 * currently in printer mode, but need to output to the terminal.
+	 */
+	if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_offstr,
+			(int) ch->ch_digi.digi_offlen);
+		head = readw(&(bs->tx_head)) & tmask;
+		ch->ch_flags &= ~CH_PRON;
+	}
+
+	/*
+	 * If there is nothing left to copy, or I can't handle any more data, leave.
+	 */
+	if (count <= 0) {
+		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return 0;
+	}
+
+	if (from_user) {
+
+		count = min(count, WRITEBUFLEN);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * If data is coming from user space, copy it into a temporary
+		 * buffer so we don't get swapped out while doing the copy to
+		 * the board.
+		 */
+		/* we're allowed to block if it's from_user */
+		if (down_interruptible(&dgap_TmpWriteSem))
+			return -EINTR;
+
+		if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
+			up(&dgap_TmpWriteSem);
+			printk("Write: Copy from user failed!\n");
+			return -EFAULT;
+		}
+
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+
+		buf = dgap_TmpWriteBuf;
+	}
+
+	n = count;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	remain = ch->ch_tstart + ch->ch_tsize - head;
+
+	if (n >= remain) {
+		n -= remain;
+		vaddr = ch->ch_taddr + head;
+
+		memcpy_toio(vaddr, (uchar *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+		head = ch->ch_tstart;
+		buf += remain;
+	}
+
+	if (n > 0) {
+
+		/*
+		 * Move rest of data.
+		 */
+		vaddr = ch->ch_taddr + head;
+		remain = n;
+
+		memcpy_toio(vaddr, (uchar *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+		head += remain;
+
+	}
+
+	if (count) {
+		ch->ch_txcount += count;
+		head &= tmask;
+		writew(head, &(bs->tx_head));
+	}
+
+	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+
+	/*
+	 * If this is the print device, and the
+	 * printer is still on, we need to turn it
+	 * off before going idle.  If the buffer is
+	 * non-empty, wait until it goes empty.
+	 * Otherwise turn it off right now.
+	 */
+	if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+		tail = readw(&(bs->tx_tail)) & tmask;
+
+		if (tail != head) {
+			un->un_flags |= UN_EMPTY;
+			writeb(1, &(bs->iempty));
+		} else {
+			dgap_wmove(ch, ch->ch_digi.digi_offstr,
+				(int) ch->ch_digi.digi_offlen);
+			head = readw(&(bs->tx_head)) & tmask;
+			ch->ch_flags &= ~CH_PRON;
+		}
+	}
+
+	/* Update printer buffer empty time. */
+	if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
+	    && (ch->ch_digi.digi_bufsize > 0)) {
+		ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
+	}
+
+	if (from_user) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		up(&dgap_TmpWriteSem);
+	} else
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return count;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_tty_tiocmget(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int result = -EIO;
+	uchar mstat = 0;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return result;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return result;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return result;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = readb(&(ch->ch_bs->m_stat));
+	/* Append any outbound signals that might be pending... */
+	mstat |= ch->ch_mostat;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & D_DTR(ch))
+		result |= TIOCM_DTR;
+	if (mstat & D_RTS(ch))
+		result |= TIOCM_RTS;
+	if (mstat & D_CTS(ch))
+		result |= TIOCM_CTS;
+	if (mstat & D_DSR(ch))
+		result |= TIOCM_DSR;
+	if (mstat & D_RI(ch))
+		result |= TIOCM_RI;
+	if (mstat & D_CD(ch))
+		result |= TIOCM_CD;
+
+	return result;
+}
+
+/*
+ * dgap_tty_tiocmset()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_tty_tiocmset(struct tty_struct *tty,
+		unsigned int set, unsigned int clear)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	if (set & TIOCM_RTS) {
+		ch->ch_mforce |= D_RTS(ch);
+		ch->ch_mval   |= D_RTS(ch);
+	}
+
+	if (set & TIOCM_DTR) {
+		ch->ch_mforce |= D_DTR(ch);
+		ch->ch_mval   |= D_DTR(ch);
+	}
+
+	if (clear & TIOCM_RTS) {
+		ch->ch_mforce |= D_RTS(ch);
+		ch->ch_mval   &= ~(D_RTS(ch));
+	}
+
+	if (clear & TIOCM_DTR) {
+		ch->ch_mforce |= D_DTR(ch);
+		ch->ch_mval   &= ~(D_DTR(ch));
+	}
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_send_break()
+ *
+ * Send a Break, called by ld.
+ */
+static int dgap_tty_send_break(struct tty_struct *tty, int msec)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	switch (msec) {
+	case -1:
+		msec = 0xFFFF;
+		break;
+	case 0:
+		msec = 1;
+		break;
+	default:
+		msec /= 10;
+		break;
+	}
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+#if 0
+	dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+#endif
+	dgap_cmdw(ch, SBREAK, (u16) msec, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_wait_until_sent()
+ *
+ * wait until data has been transmitted, called by ld.
+ */
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	dgap_wait_for_drain(tty);
+}
+
+/*
+ * dgap_send_xchar()
+ *
+ * send a high priority character, called by ld.
+ */
+static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/*
+	 * This is technically what we should do.
+	 * However, the NIST tests specifically want
+	 * to see each XON or XOFF character that it
+	 * sends, so lets just send each character
+	 * by hand...
+	 */
+#if 0
+	if (c == STOP_CHAR(tty))
+		dgap_cmdw(ch, RPAUSE, 0, 0);
+	else if (c == START_CHAR(tty))
+		dgap_cmdw(ch, RRESUME, 0, 0);
+	else
+		dgap_wmove(ch, &c, 1);
+#else
+	dgap_wmove(ch, &c, 1);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
+{
+	int result = 0;
+	uchar mstat = 0;
+	ulong lock_flags;
+	int rc = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = readb(&(ch->ch_bs->m_stat));
+	/* Append any outbound signals that might be pending... */
+	mstat |= ch->ch_mostat;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & D_DTR(ch))
+		result |= TIOCM_DTR;
+	if (mstat & D_RTS(ch))
+		result |= TIOCM_RTS;
+	if (mstat & D_CTS(ch))
+		result |= TIOCM_CTS;
+	if (mstat & D_DSR(ch))
+		result |= TIOCM_DSR;
+	if (mstat & D_RI(ch))
+		result |= TIOCM_RI;
+	if (mstat & D_CD(ch))
+		result |= TIOCM_CD;
+
+	rc = put_user(result, value);
+
+	return rc;
+}
+
+/*
+ * dgap_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -ENXIO;
+	unsigned int arg = 0;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	ret = get_user(arg, value);
+	if (ret)
+		return ret;
+
+	switch (command) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mforce |= D_RTS(ch);
+			ch->ch_mval   |= D_RTS(ch);
+		}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mforce |= D_DTR(ch);
+			ch->ch_mval   |= D_DTR(ch);
+		}
+
+		break;
+
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mforce |= D_RTS(ch);
+			ch->ch_mval   &= ~(D_RTS(ch));
+		}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mforce |= D_DTR(ch);
+			ch->ch_mval   &= ~(D_DTR(ch));
+		}
+
+		break;
+
+	case TIOCMSET:
+		ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
+
+		if (arg & TIOCM_RTS)
+			ch->ch_mval |= D_RTS(ch);
+		else
+			ch->ch_mval &= ~(D_RTS(ch));
+
+		if (arg & TIOCM_DTR)
+			ch->ch_mval |= (D_DTR(ch));
+		else
+			ch->ch_mval &= ~(D_DTR(ch));
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigeta()
+ *
+ * Ioctl to get the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digiseta()
+ *
+ * Ioctl to set the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t new_digi;
+	ulong   lock_flags = 0;
+	unsigned long lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+	if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t)))
+		return -EFAULT;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+
+	if (ch->ch_digi.digi_maxcps < 1)
+		ch->ch_digi.digi_maxcps = 1;
+
+	if (ch->ch_digi.digi_maxcps > 10000)
+		ch->ch_digi.digi_maxcps = 10000;
+
+	if (ch->ch_digi.digi_bufsize < 10)
+		ch->ch_digi.digi_bufsize = 10;
+
+	if (ch->ch_digi.digi_maxchar < 1)
+		ch->ch_digi.digi_maxchar = 1;
+
+	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
+		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
+
+	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
+		ch->ch_digi.digi_onlen = DIGI_PLEN;
+
+	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
+		ch->ch_digi.digi_offlen = DIGI_PLEN;
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigetedelay()
+ *
+ * Ioctl to get the current edelay setting.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	tmp = readw(&(ch->ch_bs->edelay));
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digisetedelay()
+ *
+ * Ioctl to set the EDELAY setting
+ *
+ */
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int new_digi;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+	if (copy_from_user(&new_digi, new_info, sizeof(int)))
+		return -EFAULT;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	writew((u16) new_digi, &(ch->ch_bs->edelay));
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigetcustombaud()
+ *
+ * Ioctl to get the current custom baud rate setting.
+ */
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	tmp = dgap_get_custom_baud(ch);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digisetcustombaud()
+ *
+ * Ioctl to set the custom baud rate setting
+ */
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	uint new_rate;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+
+	if (copy_from_user(&new_rate, new_info, sizeof(unsigned int)))
+		return -EFAULT;
+
+	if (bd->bd_flags & BD_FEP5PLUS) {
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		ch->ch_custom_speed = new_rate;
+
+		dgap_param(tty);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_set_termios()
+ */
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	unsigned long lock_flags;
+	unsigned long lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_c_cflag   = tty->termios.c_cflag;
+	ch->ch_c_iflag   = tty->termios.c_iflag;
+	ch->ch_c_oflag   = tty->termios.c_oflag;
+	ch->ch_c_lflag   = tty->termios.c_lflag;
+	ch->ch_startc    = tty->termios.c_cc[VSTART];
+	ch->ch_stopc     = tty->termios.c_cc[VSTOP];
+
+	dgap_carrier(ch);
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_throttle(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags |= (CH_RXBLOCK);
+#if 1
+	dgap_cmdw(ch, RPAUSE, 0, 0);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_unthrottle(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags &= ~(CH_RXBLOCK);
+
+#if 1
+	dgap_cmdw(ch, RRESUME, 0, 0);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_start(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_cmdw(ch, RESUMETX, 0, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_stop(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_cmdw(ch, PAUSETX, 0, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+/*
+ * dgap_tty_flush_chars()
+ *
+ * Flush the cook buffer
+ *
+ * Note to self, and any other poor souls who venture here:
+ *
+ * flush in this case DOES NOT mean dispose of the data.
+ * instead, it means "stop buffering and send it if you
+ * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
+ *
+ * It is also always called in interrupt context - JAR 8-Sept-99
+ */
+static void dgap_tty_flush_chars(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/* TODO: Do something here */
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_flush_buffer()
+ *
+ * Flush Tx buffer (make in == out)
+ */
+static void dgap_tty_flush_buffer(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+	u16	head = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags &= ~CH_STOP;
+	head = readw(&(ch->ch_bs->tx_head));
+	dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+	dgap_cmdw(ch, RESUMETX, 0, 0);
+	if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+	}
+	if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+	}
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+	if (waitqueue_active(&tty->write_wait))
+		wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
+}
+
+/*****************************************************************************
+ *
+ * The IOCTL function and all of its helpers
+ *
+ *****************************************************************************/
+
+/*
+ * dgap_tty_ioctl()
+ *
+ * The usual assortment of ioctl's
+ */
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+		unsigned long arg)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int rc;
+	u16	head = 0;
+	ulong   lock_flags = 0;
+	ulong   lock_flags2 = 0;
+	void __user *uarg = (void __user *) arg;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -ENODEV;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENODEV;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENODEV;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENODEV;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	if (un->un_open_count <= 0) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -EIO;
+	}
+
+	switch (cmd) {
+
+	/* Here are all the standard ioctl's that we MUST implement */
+
+	case TCSBRK:
+		/*
+		 * TCSBRK is SVID version: non-zero arg --> no break
+		 * this behaviour is exploited by tcdrain().
+		 *
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP))
+			dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TCSBRKP:
+		/* support for POSIX tcsendbreak()
+
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCSBRK:
+		/*
+		 * FEP5 doesn't support turning on a break unconditionally.
+		 * The FEP5 device will stop sending a break automatically
+		 * after the specified time value that was sent when turning on
+		 * the break.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCCBRK:
+		/*
+		 * FEP5 doesn't support turning off a break unconditionally.
+		 * The FEP5 device will stop sending a break automatically
+		 * after the specified time value that was sent when turning on
+		 * the break.
+		 */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return 0;
+
+	case TIOCGSOFTCAR:
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
+		return rc;
+
+	case TIOCSSOFTCAR:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		rc = get_user(arg, (unsigned long __user *) arg);
+		if (rc)
+			return rc;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+		dgap_param(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCMGET:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_get_modem_info(ch, uarg);
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_set_modem_info(tty, cmd, uarg);
+
+		/*
+		 * Here are any additional ioctl's that we want to implement
+		 */
+
+	case TCFLSH:
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */
+		rc = tty_check_change(tty);
+		if (rc) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return rc;
+		}
+
+		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
+			if (!(un->un_type == DGAP_PRINT)) {
+				head = readw(&(ch->ch_bs->rx_head));
+				writew(head, &(ch->ch_bs->rx_tail));
+				writeb(0, &(ch->ch_bs->orun));
+			}
+		}
+
+		if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
+			ch->ch_flags &= ~CH_STOP;
+			head = readw(&(ch->ch_bs->tx_head));
+			dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+			dgap_cmdw(ch, RESUMETX, 0, 0);
+			if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+				ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+			}
+			if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+				ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+				wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+			}
+			if (waitqueue_active(&tty->write_wait))
+				wake_up_interruptible(&tty->write_wait);
+
+			/* Can't hold any locks when calling tty_wakeup! */
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			tty_wakeup(tty);
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+		}
+
+		/* pretend we didn't recognize this IOCTL */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return -ENOIOCTLCMD;
+
+	case TCSETSF:
+	case TCSETSW:
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */
+		if (cmd == TCSETSF) {
+			/* flush rx */
+			ch->ch_flags &= ~CH_STOP;
+			head = readw(&(ch->ch_bs->rx_head));
+			writew(head, &(ch->ch_bs->rx_tail));
+		}
+
+		/* now wait for all the output to drain */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		/* pretend we didn't recognize this */
+		return -ENOIOCTLCMD;
+
+	case TCSETAW:
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		/* pretend we didn't recognize this */
+		return -ENOIOCTLCMD;
+
+	case TCXONC:
+		/*
+		 * The Linux Line Discipline (LD) would do this for us if we
+		 * let it, but we have the special firmware options to do this
+		 * the "right way" regardless of hardware or software flow
+		 * control so we'll do it outselves instead of letting the LD
+		 * do it.
+		 */
+		rc = tty_check_change(tty);
+		if (rc) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return rc;
+		}
+
+		switch (arg) {
+
+		case TCOON:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_tty_start(tty);
+			return 0;
+		case TCOOFF:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_tty_stop(tty);
+			return 0;
+		case TCION:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			/* Make the ld do it */
+			return -ENOIOCTLCMD;
+		case TCIOFF:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			/* Make the ld do it */
+			return -ENOIOCTLCMD;
+		default:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return -EINVAL;
+		}
+
+	case DIGI_GETA:
+		/* get information for ditty */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigeta(tty, uarg);
+
+	case DIGI_SETAW:
+	case DIGI_SETAF:
+
+		/* set information for ditty */
+		if (cmd == (DIGI_SETAW)) {
+
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			rc = dgap_wait_for_drain(tty);
+			if (rc)
+				return -EINTR;
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+		} else
+			tty_ldisc_flush(tty);
+		/* fall thru */
+
+	case DIGI_SETA:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digiseta(tty, uarg);
+
+	case DIGI_GEDELAY:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigetedelay(tty, uarg);
+
+	case DIGI_SEDELAY:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digisetedelay(tty, uarg);
+
+	case DIGI_GETCUSTOMBAUD:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigetcustombaud(tty, uarg);
+
+	case DIGI_SETCUSTOMBAUD:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digisetcustombaud(tty, uarg);
+
+	case DIGI_RESET_PORT:
+		dgap_firmware_reset_port(ch);
+		dgap_param(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return 0;
+
+	default:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int dgap_after_config_loaded(int board)
+{
+	/*
+	 * Initialize KME waitqueues...
+	 */
+	init_waitqueue_head(&(dgap_Board[board]->kme_wait));
+
+	/*
+	 * allocate flip buffer for board.
+	 */
+	dgap_Board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+	if (!dgap_Board[board]->flipbuf)
+		return -ENOMEM;
+
+	dgap_Board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+	if (!dgap_Board[board]->flipflagbuf) {
+		kfree(dgap_Board[board]->flipbuf);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Create pr and tty device entries
+ */
+static int dgap_tty_register_ports(struct board_t *brd)
+{
+	struct channel_t *ch;
+	int i;
+
+	brd->SerialPorts = kcalloc(brd->nasync, sizeof(*brd->SerialPorts),
+					GFP_KERNEL);
+	if (brd->SerialPorts == NULL)
+		return -ENOMEM;
+	for (i = 0; i < brd->nasync; i++)
+		tty_port_init(&brd->SerialPorts[i]);
+
+	brd->PrinterPorts = kcalloc(brd->nasync, sizeof(*brd->PrinterPorts),
+					GFP_KERNEL);
+	if (brd->PrinterPorts == NULL) {
+		kfree(brd->SerialPorts);
+		return -ENOMEM;
+	}
+	for (i = 0; i < brd->nasync; i++)
+		tty_port_init(&brd->PrinterPorts[i]);
+
+	ch = brd->channels[0];
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+		struct device *classp;
+
+		classp = tty_port_register_device(&brd->SerialPorts[i],
+					brd->SerialDriver,
+					brd->firstminor + i, NULL);
+
+		dgap_create_tty_sysfs(&ch->ch_tun, classp);
+		ch->ch_tun.un_sysfs = classp;
+
+		classp = tty_port_register_device(&brd->PrinterPorts[i],
+					brd->PrintDriver,
+					brd->firstminor + i, NULL);
+
+		dgap_create_tty_sysfs(&ch->ch_pun, classp);
+		ch->ch_pun.un_sysfs = classp;
+	}
+	dgap_create_ports_sysfiles(brd);
+
+	return 0;
+}
+
+/*
+ * 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, uchar __user *ubios, int len)
+{
+	uchar *addr;
+	uint offset;
+	int i;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+
+	/*
+	 * clear POST area
+	 */
+	for (i = 0; i < 16; i++)
+		writeb(0, addr + POSTAREA + i);
+
+	/*
+	 * Download bios
+	 */
+	offset = 0x1000;
+	memcpy_toio(addr + offset, ubios, len);
+
+	writel(0x0bf00401, addr);
+	writel(0, (addr + 4));
+
+	/* Clear the reset, and change states. */
+	writeb(FEPCLR, brd->re_map_port);
+}
+
+/*
+ * Checks to see if the BIOS completed running on the card.
+ */
+static void dgap_do_wait_for_bios(struct board_t *brd)
+{
+	uchar *addr;
+	u16 word;
+	u16 err1;
+	u16 err2;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+	word = readw(addr + POSTAREA);
+
+	/*
+	 * It can take 5-6 seconds for a board to
+	 * pass the bios self test and post results.
+	 * Give it 10 seconds.
+	 */
+	brd->wait_for_bios = 0;
+	while (brd->wait_for_bios < 1000) {
+		/* Check to see if BIOS thinks board is good. (GD). */
+		if (word == *(u16 *) "GD") {
+			brd->state = FINISHED_BIOS_LOAD;
+			return;
+		}
+		msleep_interruptible(10);
+		brd->wait_for_bios++;
+		word = readw(addr + POSTAREA);
+	}
+
+	/* Gave up on board after too long of time taken */
+	err1 = readw(addr + SEQUENCE);
+	err2 = readw(addr + ERROR);
+	pr_warn("dgap: %s failed diagnostics.  Error #(%x,%x).\n",
+		brd->name, err1, err2);
+	brd->state = BOARD_FAILED;
+	brd->dpastatus = BD_NOBIOS;
+}
+
+/*
+ * 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, uchar *ufep, int len)
+{
+	uchar *addr;
+	uint offset;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+
+	/*
+	 * Download FEP
+	 */
+	offset = 0x1000;
+	memcpy_toio(addr + offset, ufep, len);
+
+	/*
+	 * If board is a concentrator product, we need to give
+	 * it its config string describing how the concentrators look.
+	 */
+	if ((brd->type == PCX) || (brd->type == PEPC)) {
+		uchar string[100];
+		uchar *config, *xconfig;
+		int i = 0;
+
+		xconfig = dgap_create_config_string(brd, string);
+
+		/* Write string to board memory */
+		config = addr + CONFIG;
+		for (; i < CONFIGSIZE; i++, config++, xconfig++) {
+			writeb(*xconfig, config);
+			if ((*xconfig & 0xff) == 0xff)
+				break;
+		}
+	}
+
+	writel(0xbfc01004, (addr + 0xc34));
+	writel(0x3, (addr + 0xc30));
+
+}
+
+/*
+ * Waits for the FEP to report thats its ready for us to use.
+ */
+static void dgap_do_wait_for_fep(struct board_t *brd)
+{
+	uchar *addr;
+	u16 word;
+	u16 err1;
+	u16 err2;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+	word = readw(addr + FEPSTAT);
+
+	/*
+	 * It can take 2-3 seconds for the FEP to
+	 * be up and running. Give it 5 secs.
+	 */
+	brd->wait_for_fep = 0;
+	while (brd->wait_for_fep < 500) {
+		/* Check to see if FEP is up and running now. */
+		if (word == *(u16 *) "OS") {
+			brd->state = FINISHED_FEP_LOAD;
+			/*
+			 * Check to see if the board can support FEP5+ commands.
+			*/
+			word = readw(addr + FEP5_PLUS);
+			if (word == *(u16 *) "5A")
+				brd->bd_flags |= BD_FEP5PLUS;
+
+			return;
+		}
+		msleep_interruptible(10);
+		brd->wait_for_fep++;
+		word = readw(addr + FEPSTAT);
+	}
+
+	/* Gave up on board after too long of time taken */
+	err1 = readw(addr + SEQUENCE);
+	err2 = readw(addr + ERROR);
+	pr_warn("dgap: FEPOS for %s not functioning.  Error #(%x,%x).\n",
+		brd->name, err1, err2);
+	brd->state = BOARD_FAILED;
+	brd->dpastatus = BD_NOFEP;
+}
+
+/*
+ * Physically forces the FEP5 card to reset itself.
+ */
+static void dgap_do_reset_board(struct board_t *brd)
+{
+	uchar check;
+	u32 check1;
+	u32 check2;
+	int i = 0;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) ||
+	    !brd->re_map_membase || !brd->re_map_port)
+		return;
+
+	/* FEPRST does not vary among supported boards */
+	writeb(FEPRST, brd->re_map_port);
+
+	for (i = 0; i <= 1000; i++) {
+		check = readb(brd->re_map_port) & 0xe;
+		if (check == FEPRST)
+			break;
+		udelay(10);
+
+	}
+	if (i > 1000) {
+		pr_warn("dgap: Board not resetting...  Failing board.\n");
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+		return;
+	}
+
+	/*
+	 * Make sure there really is memory out there.
+	 */
+	writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
+	writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
+	check1 = readl(brd->re_map_membase + LOWMEM);
+	check2 = readl(brd->re_map_membase + HIGHMEM);
+
+	if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
+		pr_warn("dgap: No memory at %p for board.\n",
+			brd->re_map_membase);
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+		return;
+	}
+
+	if (brd->state != BOARD_FAILED)
+		brd->state = FINISHED_RESET;
+}
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+/*
+ * Sends a concentrator image into the FEP5 board.
+ */
+static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
+{
+	char *vaddr;
+	u16 offset = 0;
+	struct downld_t *to_dp;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	vaddr = brd->re_map_membase;
+
+	offset = readw((u16 *) (vaddr + DOWNREQ));
+	to_dp = (struct downld_t *) (vaddr + (int) offset);
+	memcpy_toio(to_dp, uaddr, len);
+
+	/* Tell card we have data for it */
+	writew(0, vaddr + (DOWNREQ));
+
+	brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
+}
+#endif
+
+#define EXPANSION_ROM_SIZE	(64 * 1024)
+#define FEP5_ROM_MAGIC		(0xFEFFFFFF)
+
+static void dgap_get_vpd(struct board_t *brd)
+{
+	u32 magic;
+	u32 base_offset;
+	u16 rom_offset;
+	u16 vpd_offset;
+	u16 image_length;
+	u16 i;
+	uchar byte1;
+	uchar byte2;
+
+	/*
+	 * Poke the magic number at the PCI Rom Address location.
+	 * If VPD is supported, the value read from that address
+	 * will be non-zero.
+	 */
+	magic = FEP5_ROM_MAGIC;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+	/* VPD not supported, bail */
+	if (!magic)
+		return;
+
+	/*
+	 * To get to the OTPROM memory, we have to send the boards base
+	 * address or'ed with 1 into the PCI Rom Address location.
+	 */
+	magic = brd->membase | 0x01;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+	byte1 = readb(brd->re_map_membase);
+	byte2 = readb(brd->re_map_membase + 1);
+
+	/*
+	 * If the board correctly swapped to the OTPROM memory,
+	 * the first 2 bytes (header) should be 0x55, 0xAA
+	 */
+	if (byte1 == 0x55 && byte2 == 0xAA) {
+
+		base_offset = 0;
+
+		/*
+		 * We have to run through all the OTPROM memory looking
+		 * for the VPD offset.
+		 */
+		while (base_offset <= EXPANSION_ROM_SIZE) {
+
+			/*
+			 * Lots of magic numbers here.
+			 *
+			 * The VPD offset is located inside the ROM Data Structure.
+			 * We also have to remember the length of each
+			 * ROM Data Structure, so we can "hop" to the next
+			 * entry if the VPD isn't in the current
+			 * ROM Data Structure.
+			 */
+			rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
+			image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
+			vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
+
+			/* Found the VPD entry */
+			if (vpd_offset)
+				break;
+
+			/* We didn't find a VPD entry, go to next ROM entry. */
+			base_offset += image_length;
+
+			byte1 = readb(brd->re_map_membase + base_offset);
+			byte2 = readb(brd->re_map_membase + base_offset + 1);
+
+			/*
+			 * If the new ROM offset doesn't have 0x55, 0xAA
+			 * as its header, we have run out of ROM.
+			 */
+			if (byte1 != 0x55 || byte2 != 0xAA)
+				break;
+		}
+
+		/*
+		 * If we have a VPD offset, then mark the board
+		 * as having a valid VPD, and copy VPDSIZE (512) bytes of
+		 * that VPD to the buffer we have in our board structure.
+		 */
+		if (vpd_offset) {
+			brd->bd_flags |= BD_HAS_VPD;
+			for (i = 0; i < VPDSIZE; i++)
+				brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
+		}
+	}
+
+	/*
+	 * We MUST poke the magic number at the PCI Rom Address location again.
+	 * This makes the card report the regular board memory back to us,
+	 * rather than the OTPROM memory.
+	 */
+	magic = FEP5_ROM_MAGIC;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+}
+
+/*
+ * Our board poller function.
+ */
+static void dgap_poll_tasklet(unsigned long data)
+{
+	struct board_t *bd = (struct board_t *) data;
+	ulong  lock_flags;
+	ulong  lock_flags2;
+	char *vaddr;
+	u16 head, tail;
+
+	if (!bd || (bd->magic != DGAP_BOARD_MAGIC))
+		return;
+
+	if (bd->inhibit_poller)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+
+	vaddr = bd->re_map_membase;
+
+	/*
+	 * If board is ready, parse deeper to see if there is anything to do.
+	 */
+	if (bd->state == BOARD_READY) {
+
+		struct ev_t *eaddr = NULL;
+
+		if (!bd->re_map_membase) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return;
+		}
+		if (!bd->re_map_port) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return;
+		}
+
+		if (!bd->nasync)
+			goto out;
+
+		eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+		/* Get our head and tail */
+		head = readw(&(eaddr->ev_head));
+		tail = readw(&(eaddr->ev_tail));
+
+		/*
+		 * If there is an event pending. Go service it.
+		 */
+		if (head != tail) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_event(bd);
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+		}
+
+out:
+		/*
+		 * If board is doing interrupts, ACK the interrupt.
+		 */
+		if (bd && bd->intr_running)
+			readb(bd->re_map_port + 2);
+
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/* Our state machine to get the board up and running */
+
+	/* Reset board */
+	if (bd->state == NEED_RESET) {
+
+		/* Get VPD info */
+		dgap_get_vpd(bd);
+
+		dgap_do_reset_board(bd);
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_RESET)
+		bd->state = NEED_CONFIG;
+
+	if (bd->state == NEED_CONFIG) {
+		/*
+		 * Match this board to a config the user created for us.
+		 */
+		bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
+
+		/*
+		 * Because the 4 port Xr products share the same PCI ID
+		 * as the 8 port Xr products, if we receive a NULL config
+		 * back, and this is a PAPORT8 board, retry with a
+		 * PAPORT4 attempt as well.
+		 */
+		if (bd->type == PAPORT8 && !bd->bd_config)
+			bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
+
+		/*
+		 * Register the ttys (if any) into the kernel.
+		 */
+		if (bd->bd_config)
+			bd->state = FINISHED_CONFIG;
+		else
+			bd->state = CONFIG_NOT_FOUND;
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_CONFIG)
+		bd->state = NEED_DEVICE_CREATION;
+
+	/* Move to next state */
+	if (bd->state == NEED_DEVICE_CREATION) {
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_DEVICE_CREATION)
+		bd->state = NEED_BIOS_LOAD;
+
+	/* Move to next state */
+	if (bd->state == NEED_BIOS_LOAD) {
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Wait for BIOS to test board... */
+	if (bd->state == WAIT_BIOS_LOAD)
+		dgap_do_wait_for_bios(bd);
+
+	/* Move to next state */
+	if (bd->state == FINISHED_BIOS_LOAD) {
+		bd->state = NEED_FEP_LOAD;
+
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Wait for FEP to load on board... */
+	if (bd->state == WAIT_FEP_LOAD)
+		dgap_do_wait_for_fep(bd);
+
+	/* Move to next state */
+	if (bd->state == FINISHED_FEP_LOAD) {
+
+		/*
+		 * Do tty device initialization.
+		 */
+		int rc = dgap_tty_init(bd);
+
+		if (rc < 0) {
+			dgap_tty_uninit(bd);
+			bd->state = BOARD_FAILED;
+			bd->dpastatus = BD_NOFEP;
+		} else {
+			bd->state = NEED_PROC_CREATION;
+
+			/*
+			 * Signal downloader, its got some work to do.
+			 */
+			DGAP_LOCK(dgap_dl_lock, lock_flags2);
+			if (dgap_dl_action != 1) {
+				dgap_dl_action = 1;
+				wake_up_interruptible(&dgap_dl_wait);
+			}
+			DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+		}
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_PROC_CREATION) {
+
+		bd->state = BOARD_READY;
+		bd->dpastatus = BD_RUNNING;
+
+		/*
+		 * If user requested the board to run in interrupt mode,
+		 * go and set it up on the board.
+		 */
+		if (bd->intr_used) {
+			writew(1, (bd->re_map_membase + ENABLE_INTR));
+			/*
+			 * Tell the board to poll the UARTS as fast as possible.
+			 */
+			writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
+			bd->intr_running = 1;
+		}
+
+		/* Wake up anyone waiting for board state to change to ready */
+		wake_up_interruptible(&bd->state_wait);
+	}
+
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdb - Sends a 2 byte command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              byte1   - Integer containing first byte to be sent.
+ *              byte2   - Integer containing second byte to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * 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(byte1, (char *) (vaddr + head + CMDSTART + 2));
+	writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
+
+	head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw - Sends a 1 word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * 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));
+	writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
+
+	head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw_ext - Sends a extended word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * Put the data in the circular command buffer.
+	 */
+
+	/* Write an FF to tell the FEP that we want an extended command */
+	writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
+
+	writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
+	writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
+
+	/*
+	 * If the second part of the command won't fit,
+	 * put it at the beginning of the circular buffer.
+	 */
+	if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03)))
+		writew((u16) word, (char *) (vaddr + CMDSTART));
+	else
+		writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
+
+	head = (head + 8) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_wmove - Write data to FEP buffer.
+ *
+ *              ch      - Pointer to channel structure.
+ *              buf     - Poiter to characters to be moved.
+ *              cnt     - Number of characters to move.
+ *
+ *=======================================================================*/
+static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
+{
+	int    n;
+	char   *taddr;
+	struct bs_t    *bs;
+	u16    head;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check parameters.
+	 */
+	bs   = ch->ch_bs;
+	head = readw(&(bs->tx_head));
+
+	/*
+	 * If pointers are out of range, just return.
+	 */
+	if ((cnt > ch->ch_tsize) ||
+	    (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize)
+		return;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	n = ch->ch_tstart + ch->ch_tsize - head;
+
+	if (cnt >= n) {
+		cnt -= n;
+		taddr = ch->ch_taddr + head;
+		memcpy_toio(taddr, buf, n);
+		head = ch->ch_tstart;
+		buf += n;
+	}
+
+	/*
+	 * Move rest of data.
+	 */
+	taddr = ch->ch_taddr + head;
+	n = cnt;
+	memcpy_toio(taddr, buf, n);
+	head += cnt;
+
+	writew(head, &(bs->tx_head));
+}
+
+/*
+ * Retrives the current custom baud rate from FEP memory,
+ * and returns it back to the user.
+ * Returns 0 on error.
+ */
+static uint dgap_get_custom_baud(struct channel_t *ch)
+{
+	uchar *vaddr;
+	ulong offset = 0;
+	uint value = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+
+	if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
+		return 0;
+
+	vaddr = ch->ch_bd->re_map_membase;
+
+	if (!vaddr)
+		return 0;
+
+	/*
+	 * Go get from fep mem, what the fep
+	 * believes the custom baud rate is.
+	 */
+	offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
+		(ch->ch_portnum * 0x28) + LINE_SPEED));
+
+	value = readw(vaddr + offset);
+	return value;
+}
+
+/*
+ * Calls the firmware to reset this channel.
+ */
+static void dgap_firmware_reset_port(struct channel_t *ch)
+{
+	dgap_cmdb(ch, CHRESET, 0, 0, 0);
+
+	/*
+	 * Now that the channel is reset, we need to make sure
+	 * all the current settings get reapplied to the port
+	 * in the firmware.
+	 *
+	 * So we will set the driver's cache of firmware
+	 * settings all to 0, and then call param.
+	 */
+	ch->ch_fepiflag = 0;
+	ch->ch_fepcflag = 0;
+	ch->ch_fepoflag = 0;
+	ch->ch_fepstartc = 0;
+	ch->ch_fepstopc = 0;
+	ch->ch_fepastartc = 0;
+	ch->ch_fepastopc = 0;
+	ch->ch_mostat = 0;
+	ch->ch_hflow = 0;
+}
+
+/*=======================================================================
+ *
+ *      dgap_param - Set Digi parameters.
+ *
+ *              struct tty_struct *     - TTY for port.
+ *
+ *=======================================================================*/
+static int dgap_param(struct tty_struct *tty)
+{
+	struct ktermios *ts;
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct bs_t   *bs;
+	struct un_t   *un;
+	u16	head;
+	u16	cflag;
+	u16	iflag;
+	uchar	mval;
+	uchar	hflow;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -ENXIO;
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENXIO;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return -ENXIO;
+
+	ts = &tty->termios;
+
+	/*
+	 * If baud rate is zero, flush queues, and set mval to drop DTR.
+	 */
+	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+
+		/* flush rx */
+		head = readw(&(ch->ch_bs->rx_head));
+		writew(head, &(ch->ch_bs->rx_tail));
+
+		/* flush tx */
+		head = readw(&(ch->ch_bs->tx_head));
+		writew(head, &(ch->ch_bs->tx_tail));
+
+		ch->ch_flags |= (CH_BAUD0);
+
+		/* Drop RTS and DTR */
+		ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
+		mval = D_DTR(ch) | D_RTS(ch);
+		ch->ch_baud_info = 0;
+
+	} else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
+		/*
+		 * Tell the fep to do the command
+		 */
+
+		dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
+
+		/*
+		 * Now go get from fep mem, what the fep
+		 * believes the custom baud rate is.
+		 */
+		ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+		}
+		mval = D_DTR(ch) | D_RTS(ch);
+
+	} else {
+		/*
+		 * Set baud rate, character size, and parity.
+		 */
+
+
+		int iindex = 0;
+		int jindex = 0;
+		int baud = 0;
+
+		ulong bauds[4][16] = {
+			{ /* slowbaud */
+				0,	50,	75,	110,
+				134,	150,	200,	300,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 },
+			{ /* slowbaud & CBAUDEX */
+				0,	57600,	115200,	230400,
+				460800,	150,	200,	921600,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 },
+			{ /* fastbaud */
+				0,	57600,	76800,	115200,
+				14400,	57600,	230400,	76800,
+				115200,	230400,	28800,	460800,
+				921600,	9600,	19200,	38400 },
+			{ /* fastbaud & CBAUDEX */
+				0,	57600,	115200,	230400,
+				460800,	150,	200,	921600,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 }
+		};
+
+		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
+		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
+			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
+		else
+			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
+
+		if (ch->ch_c_cflag & CBAUDEX)
+			iindex = 1;
+
+		if (ch->ch_digi.digi_flags & DIGI_FAST)
+			iindex += 2;
+
+		jindex = baud;
+
+		if ((iindex >= 0) && (iindex < 4) &&
+		    (jindex >= 0) && (jindex < 16))
+			baud = bauds[iindex][jindex];
+		else
+			baud = 0;
+
+		if (baud == 0)
+			baud = 9600;
+
+		ch->ch_baud_info = baud;
+
+		/*
+		 * CBAUD has bit position 0x1000 set these days to indicate Linux
+		 * baud rate remap.
+		 * We use a different bit assignment for high speed.  Clear this
+		 * bit out while grabbing the parts of "cflag" we want.
+		 */
+		cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
+
+		/*
+		 * HUPCL bit is used by FEP to indicate fast baud
+		 * table is to be used.
+		 */
+		if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
+			cflag |= HUPCL;
+
+		if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
+		/*
+		 * The below code is trying to guarantee that only baud rates
+		 * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
+		 * because the various baud rates share common bit positions
+		 * and therefore can't be tested for easily.
+		 */
+			tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
+			int baudpart = 0;
+
+			/* Map high speed requests to index into FEP's baud table */
+			switch (tcflag) {
+			case B57600:
+				baudpart = 1;
+				break;
+#ifdef B76800
+			case B76800:
+				baudpart = 2;
+				break;
+#endif
+			case B115200:
+				baudpart = 3;
+				break;
+			case B230400:
+				baudpart = 9;
+				break;
+			case B460800:
+				baudpart = 11;
+				break;
+#ifdef B921600
+			case B921600:
+				baudpart = 12;
+				break;
+#endif
+			default:
+				baudpart = 0;
+			}
+
+			if (baudpart)
+				cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
+		}
+
+		cflag &= 0xffff;
+
+		if (cflag != ch->ch_fepcflag) {
+			ch->ch_fepcflag = (u16) (cflag & 0xffff);
+
+			/* Okay to have channel and board locks held calling this */
+			dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
+		}
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+		}
+		mval = D_DTR(ch) | D_RTS(ch);
+	}
+
+	/*
+	 * Get input flags.
+	 */
+	iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
+
+	if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
+		iflag &= ~(IXON | IXOFF);
+		ch->ch_c_iflag &= ~(IXON | IXOFF);
+	}
+
+	/*
+	 * Only the IBM Xr card can switch between
+	 * 232 and 422 modes on the fly
+	 */
+	if (bd->device == PCI_DEVICE_XR_IBM_DID) {
+		if (ch->ch_digi.digi_flags & DIGI_422)
+			dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
+		else
+			dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
+	}
+
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
+		iflag |= IALTPIN;
+
+	if (iflag != ch->ch_fepiflag) {
+		ch->ch_fepiflag = iflag;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
+	}
+
+	/*
+	 * Select hardware handshaking.
+	 */
+	hflow = 0;
+
+	if (ch->ch_c_cflag & CRTSCTS)
+		hflow |= (D_RTS(ch) | D_CTS(ch));
+	if (ch->ch_digi.digi_flags & RTSPACE)
+		hflow |= D_RTS(ch);
+	if (ch->ch_digi.digi_flags & DTRPACE)
+		hflow |= D_DTR(ch);
+	if (ch->ch_digi.digi_flags & CTSPACE)
+		hflow |= D_CTS(ch);
+	if (ch->ch_digi.digi_flags & DSRPACE)
+		hflow |= D_DSR(ch);
+	if (ch->ch_digi.digi_flags & DCDPACE)
+		hflow |= D_CD(ch);
+
+	if (hflow != ch->ch_hflow) {
+		ch->ch_hflow = hflow;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
+	}
+
+
+	/*
+	 * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
+	 */
+	if (bd->bd_flags & BD_FEP5PLUS) {
+		u16 hflow2 = 0;
+		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
+			hflow2 |= (D_RTS(ch));
+		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)
+			hflow2 |= (D_DTR(ch));
+
+		dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
+	}
+
+	/*
+	 * Set modem control lines.
+	 */
+
+	mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
+
+	if (ch->ch_mostat ^ mval) {
+		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);
+	}
+
+	/*
+	 * Read modem signals, and then call carrier function.
+	 */
+	ch->ch_mistat = readb(&(bs->m_stat));
+	dgap_carrier(ch);
+
+	/*
+	 * Set the start and stop characters.
+	 */
+	if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
+		ch->ch_fepstartc = ch->ch_startc;
+		ch->ch_fepstopc =  ch->ch_stopc;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
+	}
+
+	/*
+	 * Set the Auxiliary start and stop characters.
+	 */
+	if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
+		ch->ch_fepastartc = ch->ch_astartc;
+		ch->ch_fepastopc = ch->ch_astopc;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_parity_scan()
+ *
+ * Convert the FEP5 way of reporting parity errors and breaks into
+ * the Linux line discipline way.
+ */
+static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
+{
+	int l = *len;
+	int count = 0;
+	unsigned char *in, *cout, *fout;
+	unsigned char c;
+
+	in = cbuf;
+	cout = cbuf;
+	fout = fbuf;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	while (l--) {
+		c = *in++;
+		switch (ch->pscan_state) {
+		default:
+			/* reset to sanity and fall through */
+			ch->pscan_state = 0;
+
+		case 0:
+			/* No FF seen yet */
+			if (c == (unsigned char) '\377')
+				/* delete this character from stream */
+				ch->pscan_state = 1;
+			else {
+				*cout++ = c;
+				*fout++ = TTY_NORMAL;
+				count += 1;
+			}
+			break;
+
+		case 1:
+			/* first FF seen */
+			if (c == (unsigned char) '\377') {
+				/* doubled ff, transform to single ff */
+				*cout++ = c;
+				*fout++ = TTY_NORMAL;
+				count += 1;
+				ch->pscan_state = 0;
+			} else {
+				/* save value examination in next state */
+				ch->pscan_savechar = c;
+				ch->pscan_state = 2;
+			}
+			break;
+
+		case 2:
+			/* third character of ff sequence */
+
+			*cout++ = c;
+
+			if (ch->pscan_savechar == 0x0) {
+
+				if (c == 0x0) {
+					ch->ch_err_break++;
+					*fout++ = TTY_BREAK;
+				} else {
+					ch->ch_err_parity++;
+					*fout++ = TTY_PARITY;
+				}
+			}
+
+			count += 1;
+			ch->pscan_state = 0;
+		}
+	}
+	*len = count;
+}
+
+/*=======================================================================
+ *
+ *      dgap_event - FEP to host event processing routine.
+ *
+ *              bd     - Board of current event.
+ *
+ *=======================================================================*/
+static int dgap_event(struct board_t *bd)
+{
+	struct channel_t *ch;
+	ulong		lock_flags;
+	ulong		lock_flags2;
+	struct bs_t	*bs;
+	uchar		*event;
+	uchar		*vaddr = NULL;
+	struct ev_t	*eaddr = NULL;
+	uint		head;
+	uint		tail;
+	int		port;
+	int		reason;
+	int		modem;
+	int		b1;
+
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+
+	vaddr = bd->re_map_membase;
+
+	if (!vaddr) {
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+	/* Get our head and tail */
+	head = readw(&(eaddr->ev_head));
+	tail = readw(&(eaddr->ev_tail));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+
+	if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
+	    (head | tail) & 03) {
+		/* Let go of board lock */
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/*
+	 * Loop to process all the events in the buffer.
+	 */
+	while (tail != head) {
+
+		/*
+		 * Get interrupt information.
+		 */
+
+		event = bd->re_map_membase + tail + EVSTART;
+
+		port   = event[0];
+		reason = event[1];
+		modem  = event[2];
+		b1     = event[3];
+
+		/*
+		 * Make sure the interrupt is valid.
+		 */
+		if (port >= bd->nasync)
+			goto next;
+
+		if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA)))
+			goto next;
+
+		ch = bd->channels[port];
+
+		if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+			goto next;
+
+		/*
+		 * If we have made it here, the event was valid.
+		 * Lock down the channel.
+		 */
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		bs = ch->ch_bs;
+
+		if (!bs) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			goto next;
+		}
+
+		/*
+		 * Process received data.
+		 */
+		if (reason & IFDATA) {
+
+			/*
+			 * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
+			 * input could send some data to ld, which in turn
+			 * could do a callback to one of our other functions.
+			 */
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+			dgap_input(ch);
+
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+			if (ch->ch_flags & CH_RACTIVE)
+				ch->ch_flags |= CH_RENABLE;
+			else
+				writeb(1, &(bs->idata));
+
+			if (ch->ch_flags & CH_RWAIT) {
+				ch->ch_flags &= ~CH_RWAIT;
+
+				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+			}
+		}
+
+		/*
+		 * Process Modem change signals.
+		 */
+		if (reason & IFMODEM) {
+			ch->ch_mistat = modem;
+			dgap_carrier(ch);
+		}
+
+		/*
+		 * Process break.
+		 */
+		if (reason & IFBREAK) {
+
+			if (ch->ch_tun.un_tty) {
+				/* A break has been indicated */
+				ch->ch_err_break++;
+				tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
+				tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
+				tty_flip_buffer_push(ch->ch_tun.un_tty->port);
+			}
+		}
+
+		/*
+		 * Process Transmit low.
+		 */
+		if (reason & IFTLW) {
+
+			if (ch->ch_tun.un_flags & UN_LOW) {
+				ch->ch_tun.un_flags &= ~UN_LOW;
+
+				if (ch->ch_tun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_tun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_pun.un_flags & UN_LOW) {
+				ch->ch_pun.un_flags &= ~UN_LOW;
+				if (ch->ch_pun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_pun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_flags & CH_WLOW) {
+				ch->ch_flags &= ~CH_WLOW;
+				wake_up_interruptible(&ch->ch_flags_wait);
+			}
+		}
+
+		/*
+		 * Process Transmit empty.
+		 */
+		if (reason & IFTEM) {
+			if (ch->ch_tun.un_flags & UN_EMPTY) {
+				ch->ch_tun.un_flags &= ~UN_EMPTY;
+				if (ch->ch_tun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_tun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_pun.un_flags & UN_EMPTY) {
+				ch->ch_pun.un_flags &= ~UN_EMPTY;
+				if (ch->ch_pun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_pun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+				}
+			}
+
+
+			if (ch->ch_flags & CH_WEMPTY) {
+				ch->ch_flags &= ~CH_WEMPTY;
+				wake_up_interruptible(&ch->ch_flags_wait);
+			}
+		}
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+
+next:
+		tail = (tail + 4) & (EVMAX - EVSTART - 4);
+	}
+
+	writew(tail, &(eaddr->ev_tail));
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
+}
+static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
+
+
+static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
+}
+static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
+
+
+static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
+}
+static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
+
+
+static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
+}
+static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
+
+
+static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
+
+static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
+}
+
+static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "0x%x\n", &dgap_rawreadok);
+	return count;
+}
+static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
+
+
+static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
+}
+
+static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "%d\n", &dgap_poll_tick);
+	return count;
+}
+static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+	int rc = 0;
+	struct device_driver *driverfs = &dgap_driver->driver;
+
+	rc |= driver_create_file(driverfs, &driver_attr_version);
+	rc |= driver_create_file(driverfs, &driver_attr_boards);
+	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
+	rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
+	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
+	rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
+	rc |= driver_create_file(driverfs, &driver_attr_state);
+	if (rc)
+		printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
+}
+
+static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+	struct device_driver *driverfs = &dgap_driver->driver;
+	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(driverfs, &driver_attr_boards);
+	driver_remove_file(driverfs, &driver_attr_maxboards);
+	driver_remove_file(driverfs, &driver_attr_rawreadok);
+	driver_remove_file(driverfs, &driver_attr_pollrate);
+	driver_remove_file(driverfs, &driver_attr_pollcounter);
+	driver_remove_file(driverfs, &driver_attr_state);
+}
+
+#define DGAP_VERIFY_BOARD(p, bd)			\
+	if (!p)						\
+		return 0;				\
+							\
+	bd = dev_get_drvdata(p);			\
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)	\
+		return 0;				\
+	if (bd->state != BOARD_READY)			\
+		return 0;				\
+
+static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count,
+			"%d %s\n", bd->channels[i]->ch_portnum,
+			bd->channels[i]->ch_open_count ? "Open" : "Closed");
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
+
+static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count +=  snprintf(buf + count, PAGE_SIZE - count,
+			"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
+
+static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		if (bd->channels[i]->ch_open_count)
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
+				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+		else
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d\n", bd->channels[i]->ch_portnum);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
+
+static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
+	return count;
+}
+static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
+
+static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
+	return count;
+}
+static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
+
+static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
+	return count;
+}
+static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
+
+static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
+	return count;
+}
+static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
+
+static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
+	return count;
+}
+static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
+
+static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
+	return count;
+}
+static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
+
+static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
+	return count;
+}
+static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
+
+/* this function creates the sys files that will export each signal status
+ * to sysfs each value will be put in a separate filename
+ */
+static void dgap_create_ports_sysfiles(struct board_t *bd)
+{
+	int rc = 0;
+
+	dev_set_drvdata(&bd->pdev->dev, bd);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+	if (rc)
+		printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
+}
+
+/* removes all the sys files created for that port */
+static void dgap_remove_ports_sysfiles(struct board_t *bd)
+{
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+}
+
+static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
+}
+static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
+
+static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
+}
+static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
+
+static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	if (ch->ch_open_count) {
+		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
+			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+	}
+	return 0;
+}
+static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
+
+static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
+}
+static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
+
+static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
+}
+static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
+
+static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
+}
+static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
+
+static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
+}
+static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
+
+static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
+}
+static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
+
+static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
+}
+static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
+
+static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
+}
+static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
+
+static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int	cn;
+	int	bn;
+	struct cnode *cptr = NULL;
+	int found = FALSE;
+	int ncount = 0;
+	int starto = 0;
+	int i = 0;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	bn = bd->boardnum;
+	cn = ch->ch_portnum;
+
+	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
+
+		if ((cptr->type == BNODE) &&
+		    ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
+		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
+		     (cptr->u.board.type == PAPORT8))) {
+
+				found = TRUE;
+				if (cptr->u.board.v_start)
+					starto = cptr->u.board.start;
+				else
+					starto = 1;
+		}
+
+		if (cptr->type == TNODE && found == TRUE) {
+			char *ptr1;
+			if (strstr(cptr->u.ttyname, "tty")) {
+				ptr1 = cptr->u.ttyname;
+				ptr1 += 3;
+			} else
+				ptr1 = cptr->u.ttyname;
+
+			for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
+				if (cn == i)
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						ptr1, i + starto);
+			}
+		}
+
+		if (cptr->type == CNODE) {
+
+			for (i = 0; i < cptr->u.conc.nport; i++) {
+				if (cn == (i + ncount))
+
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						cptr->u.conc.id,
+						i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
+			}
+
+			ncount += cptr->u.conc.nport;
+		}
+
+		if (cptr->type == MNODE) {
+
+			for (i = 0; i < cptr->u.module.nport; i++) {
+				if (cn == (i + ncount))
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						cptr->u.module.id,
+						i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
+			}
+
+			ncount += cptr->u.module.nport;
+
+		}
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
+		(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
+
+}
+static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
+
+static struct attribute *dgap_sysfs_tty_entries[] = {
+	&dev_attr_state.attr,
+	&dev_attr_baud.attr,
+	&dev_attr_msignals.attr,
+	&dev_attr_iflag.attr,
+	&dev_attr_cflag.attr,
+	&dev_attr_oflag.attr,
+	&dev_attr_lflag.attr,
+	&dev_attr_digi_flag.attr,
+	&dev_attr_rxcount.attr,
+	&dev_attr_txcount.attr,
+	&dev_attr_custom_name.attr,
+	NULL
+};
+
+static struct attribute_group dgap_tty_attribute_group = {
+	.name = NULL,
+	.attrs = dgap_sysfs_tty_entries,
+};
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
+{
+	int ret;
+
+	ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
+	if (ret) {
+		printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
+		sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+		return;
+	}
+
+	dev_set_drvdata(c, un);
+
+}
+
+static void dgap_remove_tty_sysfs(struct device *c)
+{
+	sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+}
+
+/*
+ * Parse a configuration file read into memory as a string.
+ */
+static int	dgap_parsefile(char **in, int Remove)
+{
+	struct cnode *p, *brd, *line, *conc;
+	int	rc;
+	char	*s = NULL, *s2 = NULL;
+	int	linecnt = 0;
+
+	p = &dgap_head;
+	brd = line = conc = NULL;
+
+	/* perhaps we are adding to an existing list? */
+	while (p->next != NULL)
+		p = p->next;
+
+	/* file must start with a BEGIN */
+	while ((rc = dgap_gettok(in, p)) != BEGIN) {
+		if (rc == 0) {
+			dgap_err("unexpected EOF");
+			return -1;
+		}
+	}
+
+	for (; ;) {
+		rc = dgap_gettok(in, p);
+		if (rc == 0) {
+			dgap_err("unexpected EOF");
+			return -1;
+		}
+
+		switch (rc) {
+		case 0:
+			dgap_err("unexpected end of file");
+			return -1;
+
+		case BEGIN:	/* should only be 1 begin */
+			dgap_err("unexpected config_begin\n");
+			return -1;
+
+		case END:
+			return 0;
+
+		case BOARD:	/* board info */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(BNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+
+			p->u.board.status = dgap_savestring("No");
+			line = conc = NULL;
+			brd = p;
+			linecnt = -1;
+			break;
+
+		case APORT2_920P:	/* AccelePort_4 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_2r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT2_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case APORT4_920P:	/* AccelePort_4 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_4r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT4_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case APORT8_920P:	/* AccelePort_8 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_8r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT8_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case PAPORT4:	/* AccelePort_4 PCI */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_4r(PCI) string");
+				return -1;
+			}
+			p->u.board.type = PAPORT4;
+			p->u.board.v_type = 1;
+			break;
+
+		case PAPORT8:	/* AccelePort_8 PCI */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_8r string");
+				return -1;
+			}
+			p->u.board.type = PAPORT8;
+			p->u.board.v_type = 1;
+			break;
+
+		case PCX:	/* PCI C/X */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_C/X_(PCI) string");
+				return -1;
+			}
+			p->u.board.type = PCX;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			p->u.board.module1 = 0;
+			p->u.board.module2 = 0;
+			break;
+
+		case PEPC:	/* PCI EPC/X */
+			if (p->type != BNODE) {
+				dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
+				return -1;
+			}
+			p->u.board.type = PEPC;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			p->u.board.module1 = 0;
+			p->u.board.module2 = 0;
+			break;
+
+		case PPCM:	/* PCI/Xem */
+			if (p->type != BNODE) {
+				dgap_err("unexpected PCI/Xem string");
+				return -1;
+			}
+			p->u.board.type = PPCM;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			break;
+
+		case IO:	/* i/o port */
+			if (p->type != BNODE) {
+				dgap_err("IO port only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.portstr = dgap_savestring(s);
+			p->u.board.port = (short)simple_strtol(s, &s2, 0);
+			if ((short)strlen(s) > (short)(s2 - s)) {
+				dgap_err("bad number for IO port");
+				return -1;
+			}
+			p->u.board.v_port = 1;
+			break;
+
+		case MEM:	/* memory address */
+			if (p->type != BNODE) {
+				dgap_err("memory address only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.addrstr = dgap_savestring(s);
+			p->u.board.addr = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for memory address");
+				return -1;
+			}
+			p->u.board.v_addr = 1;
+			break;
+
+		case PCIINFO:	/* pci information */
+			if (p->type != BNODE) {
+				dgap_err("memory address only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.pcibusstr = dgap_savestring(s);
+			p->u.board.pcibus = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for pci bus");
+				return -1;
+			}
+			p->u.board.v_pcibus = 1;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.pcislotstr = dgap_savestring(s);
+			p->u.board.pcislot = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for pci slot");
+				return -1;
+			}
+			p->u.board.v_pcislot = 1;
+			break;
+
+		case METHOD:
+			if (p->type != BNODE) {
+				dgap_err("install method only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.method = dgap_savestring(s);
+			p->u.board.v_method = 1;
+			break;
+
+		case STATUS:
+			if (p->type != BNODE) {
+				dgap_err("config status only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.status = dgap_savestring(s);
+			break;
+
+		case NPORTS:	/* number of ports */
+			if (p->type == BNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.board.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.board.v_nport = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.conc.v_nport = 1;
+			} else if (p->type == MNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.module.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.module.v_nport = 1;
+			} else {
+				dgap_err("nports only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case ID:	/* letter ID used in tty name */
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+
+			p->u.board.status = dgap_savestring(s);
+
+			if (p->type == CNODE) {
+				p->u.conc.id = dgap_savestring(s);
+				p->u.conc.v_id = 1;
+			} else if (p->type == MNODE) {
+				p->u.module.id = dgap_savestring(s);
+				p->u.module.v_id = 1;
+			} else {
+				dgap_err("id only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case STARTO:	/* start offset of ID */
+			if (p->type == BNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.board.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.board.v_start = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.conc.v_start = 1;
+			} else if (p->type == MNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.module.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.module.v_start = 1;
+			} else {
+				dgap_err("start only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case TTYN:	/* tty name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(TNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.ttyname = dgap_savestring(s);
+			if (!p->u.ttyname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case CU:	/* cu name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(CUNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.cuname = dgap_savestring(s);
+			if (!p->u.cuname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case LINE:	/* line information */
+			if (dgap_checknode(p))
+				return -1;
+			if (brd == NULL) {
+				dgap_err("must specify board before line info");
+				return -1;
+			}
+			switch (brd->u.board.type) {
+			case PPCM:
+				dgap_err("line not vaild for PC/em");
+				return -1;
+			}
+			p->next = dgap_newnode(LNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			conc = NULL;
+			line = p;
+			linecnt++;
+			break;
+
+		case CONC:	/* concentrator information */
+			if (dgap_checknode(p))
+				return -1;
+			if (line == NULL) {
+				dgap_err("must specify line info before concentrator");
+				return -1;
+			}
+			p->next = dgap_newnode(CNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			conc = p;
+			if (linecnt)
+				brd->u.board.conc2++;
+			else
+				brd->u.board.conc1++;
+
+			break;
+
+		case CX:	/* c/x type concentrator */
+			if (p->type != CNODE) {
+				dgap_err("cx only valid for concentrators");
+				return -1;
+			}
+			p->u.conc.type = CX;
+			p->u.conc.v_type = 1;
+			break;
+
+		case EPC:	/* epc type concentrator */
+			if (p->type != CNODE) {
+				dgap_err("cx only valid for concentrators");
+				return -1;
+			}
+			p->u.conc.type = EPC;
+			p->u.conc.v_type = 1;
+			break;
+
+		case MOD:	/* EBI module */
+			if (dgap_checknode(p))
+				return -1;
+			if (brd == NULL) {
+				dgap_err("must specify board info before EBI modules");
+				return -1;
+			}
+			switch (brd->u.board.type) {
+			case PPCM:
+				linecnt = 0;
+				break;
+			default:
+				if (conc == NULL) {
+					dgap_err("must specify concentrator info before EBI module");
+					return -1;
+				}
+			}
+			p->next = dgap_newnode(MNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			if (linecnt)
+				brd->u.board.module2++;
+			else
+				brd->u.board.module1++;
+
+			break;
+
+		case PORTS:	/* ports type EBI module */
+			if (p->type != MNODE) {
+				dgap_err("ports only valid for EBI modules");
+				return -1;
+			}
+			p->u.module.type = PORTS;
+			p->u.module.v_type = 1;
+			break;
+
+		case MODEM:	/* ports type EBI module */
+			if (p->type != MNODE) {
+				dgap_err("modem only valid for modem modules");
+				return -1;
+			}
+			p->u.module.type = MODEM;
+			p->u.module.v_type = 1;
+			break;
+
+		case CABLE:
+			if (p->type == LNODE) {
+				s = dgap_getword(in);
+				if (!s) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.line.cable = dgap_savestring(s);
+				p->u.line.v_cable = 1;
+			}
+			break;
+
+		case SPEED:	/* sync line speed indication */
+			if (p->type == LNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.line.speed = (char)simple_strtol(s, &s2, 0);
+				if ((short)strlen(s) > (short)(s2 - s)) {
+					dgap_err("bad number for line speed");
+					return -1;
+				}
+				p->u.line.v_speed = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
+				if ((short)strlen(s) > (short)(s2 - s)) {
+					dgap_err("bad number for line speed");
+					return -1;
+				}
+				p->u.conc.v_speed = 1;
+			} else {
+				dgap_err("speed valid only for lines or concentrators.");
+				return -1;
+			}
+			break;
+
+		case CONNECT:
+			if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (!s) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.connect = dgap_savestring(s);
+				p->u.conc.v_connect = 1;
+			}
+			break;
+		case PRINT:	/* transparent print name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(PNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.printname = dgap_savestring(s);
+			if (!p->u.printname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case CMAJOR:	/* major number */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(JNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.majornumber = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for major number");
+				return -1;
+			}
+			break;
+
+		case ALTPIN:	/* altpin setting */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(ANODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.altpin = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for altpin");
+				return -1;
+			}
+			break;
+
+		case USEINTR:		/* enable interrupt setting */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(INTRNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.useintr = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for useintr");
+				return -1;
+			}
+			break;
+
+		case TTSIZ:	/* size of tty structure */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(TSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.ttysize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for ttysize");
+				return -1;
+			}
+			break;
+
+		case CHSIZ:	/* channel structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(CSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.chsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for chsize");
+				return -1;
+			}
+			break;
+
+		case BSSIZ:	/* board structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(BSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.bssize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for bssize");
+				return -1;
+			}
+			break;
+
+		case UNTSIZ:	/* sched structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(USNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.unsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for schedsize");
+				return -1;
+			}
+			break;
+
+		case F2SIZ:	/* f2200 structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(FSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.f2size = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for f2200size");
+				return -1;
+			}
+			break;
+
+		case VPSIZ:	/* vpix structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(VSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.vpixsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for vpixsize");
+				return -1;
+			}
+			break;
+		}
+	}
+}
+
+/*
+ * dgap_sindex: much like index(), but it looks for a match of any character in
+ * the group, and returns that position.  If the first character is a ^, then
+ * this will match the first occurrence not in that group.
+ */
+static char *dgap_sindex (char *string, char *group)
+{
+	char    *ptr;
+
+	if (!string || !group)
+		return (char *) NULL;
+
+	if (*group == '^') {
+		group++;
+		for (; *string; string++) {
+			for (ptr = group; *ptr; ptr++) {
+				if (*ptr == *string)
+					break;
+			}
+			if (*ptr == '\0')
+				return string;
+		}
+	} else {
+		for (; *string; string++) {
+			for (ptr = group; *ptr; ptr++) {
+				if (*ptr == *string)
+					return string;
+			}
+		}
+	}
+
+	return (char *) NULL;
+}
+
+/*
+ * Get a token from the input file; return 0 if end of file is reached
+ */
+static int dgap_gettok(char **in, struct cnode *p)
+{
+	char	*w;
+	struct toklist *t;
+
+	if (strstr(dgap_cword, "boar")) {
+		w = dgap_getword(in);
+		snprintf(dgap_cword, MAXCWORD, "%s", w);
+		for (t = dgap_tlist; t->token != 0; t++) {
+			if (!strcmp(w, t->string))
+				return t->token;
+		}
+		dgap_err("board !!type not specified");
+		return 1;
+	} else {
+		while ( (w = dgap_getword(in)) != NULL ) {
+			snprintf(dgap_cword, MAXCWORD, "%s", w);
+			for (t = dgap_tlist; t->token != 0; t++) {
+				if (!strcmp(w, t->string))
+					return t->token;
+			}
+		}
+		return 0;
+	}
+}
+
+/*
+ * get a word from the input stream, also keep track of current line number.
+ * words are separated by whitespace.
+ */
+static char *dgap_getword(char **in)
+{
+	char *ret_ptr = *in;
+
+	char *ptr = dgap_sindex(*in, " \t\n");
+
+	/* If no word found, return null */
+	if (!ptr)
+		return NULL;
+
+	/* Mark new location for our buffer */
+	*ptr = '\0';
+	*in = ptr + 1;
+
+	/* Eat any extra spaces/tabs/newlines that might be present */
+	while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
+		**in = '\0';
+		*in = *in + 1;
+	}
+
+	return ret_ptr;
+}
+
+/*
+ * print an error message, giving the line number in the file where
+ * the error occurred.
+ */
+static void dgap_err(char *s)
+{
+	printk("DGAP: parse: %s\n", s);
+}
+
+/*
+ * allocate a new configuration node of type t
+ */
+static struct cnode *dgap_newnode(int t)
+{
+	struct cnode *n;
+
+	n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
+	if (n != NULL) {
+		memset((char *)n, 0, sizeof(struct cnode));
+		n->type = t;
+	}
+	return n;
+}
+
+/*
+ * dgap_checknode: see if all the necessary info has been supplied for a node
+ * before creating the next node.
+ */
+static int dgap_checknode(struct cnode *p)
+{
+	switch (p->type) {
+	case BNODE:
+		if (p->u.board.v_type == 0) {
+			dgap_err("board type !not specified");
+			return 1;
+		}
+
+		return 0;
+
+	case LNODE:
+		if (p->u.line.v_speed == 0) {
+			dgap_err("line speed not specified");
+			return 1;
+		}
+		return 0;
+
+	case CNODE:
+		if (p->u.conc.v_type == 0) {
+			dgap_err("concentrator type not specified");
+			return 1;
+		}
+		if (p->u.conc.v_speed == 0) {
+			dgap_err("concentrator line speed not specified");
+			return 1;
+		}
+		if (p->u.conc.v_nport == 0) {
+			dgap_err("number of ports on concentrator not specified");
+			return 1;
+		}
+		if (p->u.conc.v_id == 0) {
+			dgap_err("concentrator id letter not specified");
+			return 1;
+		}
+		return 0;
+
+	case MNODE:
+		if (p->u.module.v_type == 0) {
+			dgap_err("EBI module type not specified");
+			return 1;
+		}
+		if (p->u.module.v_nport == 0) {
+			dgap_err("number of ports on EBI module not specified");
+			return 1;
+		}
+		if (p->u.module.v_id == 0) {
+			dgap_err("EBI module id letter not specified");
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ * save a string somewhere
+ */
+static char	*dgap_savestring(char *s)
+{
+	char	*p;
+
+	p = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+	if (p)
+		strcpy(p, s);
+	return p;
+}
+
+/*
+ * Given a board pointer, returns whether we should use interrupts or not.
+ */
+static uint dgap_config_get_useintr(struct board_t *bd)
+{
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+		switch (p->type) {
+		case INTRNODE:
+			/*
+			 * check for pcxr types.
+			 */
+			return p->u.useintr;
+		default:
+			break;
+		}
+	}
+
+	/* If not found, then don't turn on interrupts. */
+	return 0;
+}
+
+/*
+ * Given a board pointer, returns whether we turn on altpin or not.
+ */
+static uint dgap_config_get_altpin(struct board_t *bd)
+{
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+		switch (p->type) {
+		case ANODE:
+			/*
+			 * check for pcxr types.
+			 */
+			return p->u.altpin;
+		default:
+			break;
+		}
+	}
+
+	/* If not found, then don't turn on interrupts. */
+	return 0;
+}
+
+/*
+ * Given a specific type of board, if found, detached link and
+ * returns the first occurrence in the list.
+ */
+static struct cnode *dgap_find_config(int type, int bus, int slot)
+{
+	struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
+
+	p = &dgap_head;
+
+	while (p->next != NULL) {
+		prev = p;
+		p = p->next;
+
+		if (p->type == BNODE) {
+
+			if (p->u.board.type == type) {
+
+				if (p->u.board.v_pcibus &&
+				    p->u.board.pcibus != bus)
+					continue;
+				if (p->u.board.v_pcislot &&
+				    p->u.board.pcislot != slot)
+					continue;
+
+				found = p;
+				/*
+				 * Keep walking thru the list till we find the next board.
+				 */
+				while (p->next != NULL) {
+					prev2 = p;
+					p = p->next;
+					if (p->type == BNODE) {
+
+						/*
+						 * Mark the end of our 1 board chain of configs.
+						 */
+						prev2->next = NULL;
+
+						/*
+						 * Link the "next" board to the previous board,
+						 * effectively "unlinking" our board from the main config.
+						 */
+						prev->next = p;
+
+						return found;
+					}
+				}
+				/*
+				 * It must be the last board in the list.
+				 */
+				prev->next = NULL;
+				return found;
+			}
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Given a board pointer, walks the config link, counting up
+ * all ports user specified should be on the board.
+ * (This does NOT mean they are all actually present right now tho)
+ */
+static uint dgap_config_get_number_of_ports(struct board_t *bd)
+{
+	int count = 0;
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+
+		switch (p->type) {
+		case BNODE:
+			/*
+			 * check for pcxr types.
+			 */
+			if (p->u.board.type > EPCFE)
+				count += p->u.board.nport;
+			break;
+		case CNODE:
+			count += p->u.conc.nport;
+			break;
+		case MNODE:
+			count += p->u.module.nport;
+			break;
+		}
+	}
+	return count;
+}
+
+static char *dgap_create_config_string(struct board_t *bd, char *string)
+{
+	char *ptr = string;
+	struct cnode *p = NULL;
+	struct cnode *q = NULL;
+	int speed;
+
+	if (!bd) {
+		*ptr = 0xff;
+		return string;
+	}
+
+	for (p = bd->bd_config; p; p = p->next) {
+
+		switch (p->type) {
+		case LNODE:
+			*ptr = '\0';
+			ptr++;
+			*ptr = p->u.line.speed;
+			ptr++;
+			break;
+		case CNODE:
+			/*
+			 * Because the EPC/con concentrators can have EM modules
+			 * hanging off of them, we have to walk ahead in the list
+			 * and keep adding the number of ports on each EM to the config.
+			 * UGH!
+			 */
+			speed = p->u.conc.speed;
+			q = p->next;
+			if ((q != NULL) && (q->type == MNODE)) {
+				*ptr = (p->u.conc.nport + 0x80);
+				ptr++;
+				p = q;
+				while ((q->next != NULL) && (q->next->type) == MNODE) {
+					*ptr = (q->u.module.nport + 0x80);
+					ptr++;
+					p = q;
+					q = q->next;
+				}
+				*ptr = q->u.module.nport;
+				ptr++;
+			} else {
+				*ptr = p->u.conc.nport;
+				ptr++;
+			}
+
+			*ptr = speed;
+			ptr++;
+			break;
+		}
+	}
+
+	*ptr = 0xff;
+	return string;
+}
diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h
new file mode 100644
index 000000000000..e33e59198ff7
--- /dev/null
+++ b/drivers/staging/dgap/dgap.h
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, 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.
+ *
+ * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *************************************************************************
+ *
+ * Driver includes
+ *
+ *************************************************************************/
+
+#ifndef __DGAP_DRIVER_H
+#define __DGAP_DRIVER_H
+
+#include <linux/types.h>        /* To pick up the varions Linux types */
+#include <linux/tty.h>          /* To pick up the various tty structs/defines */
+#include <linux/interrupt.h>    /* For irqreturn_t type */
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* Required for our shared headers! */
+typedef unsigned char		uchar;
+
+#if !defined(TTY_FLIPBUF_SIZE)
+# define TTY_FLIPBUF_SIZE 512
+#endif
+
+/* Sparse stuff */
+# ifndef __user
+#  define __user
+#  define __kernel
+#  define __safe
+#  define __force
+#  define __chk_user_ptr(x) (void)0
+# endif
+
+
+#  define PARM_STR(VAR, INIT, PERM, DESC) \
+		static char *VAR = INIT; \
+		char *dgap_##VAR; \
+		module_param(VAR, charp, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_INT(VAR, INIT, PERM, DESC) \
+		static int VAR = INIT; \
+		int dgap_##VAR; \
+		module_param(VAR, int, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
+		static ulong VAR = INIT; \
+		ulong dgap_##VAR; \
+		module_param(VAR, long, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+/*************************************************************************
+ *
+ * Driver defines
+ *
+ *************************************************************************/
+
+/*
+ * Driver identification, error and debugging statments
+ *
+ * In theory, you can change all occurrences of "digi" in the next
+ * three lines, and the driver printk's will all automagically change.
+ *
+ * APR((fmt, args, ...));	Always prints message
+ * DPR((fmt, args, ...));	Only prints if DGAP_TRACER is defined at
+ *				  compile time and dgap_debug!=0
+ */
+#define	DG_NAME		"dgap-1.3-16"
+#define	DG_PART		"40002347_C"
+
+#define	PROCSTR		"dgap"			/* /proc entries	 */
+#define	DEVSTR		"/dev/dg/dgap"		/* /dev entries		 */
+#define	DRVSTR		"dgap"			/* Driver name string
+						 * displayed by APR	 */
+#define	APR(args)	do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
+			   } while (0)
+#define	RAPR(args)	do { PRINTF_TO_KMEM(args); printk args; } while (0)
+
+#define TRC_TO_CONSOLE 1
+
+/*
+ * defines from dgap_pci.h
+ */ 
+#define PCIMAX 32			/* maximum number of PCI boards */
+
+#define DIGI_VID		0x114F
+
+#define PCI_DEVICE_EPC_DID	0x0002
+#define PCI_DEVICE_XEM_DID	0x0004
+#define PCI_DEVICE_XR_DID	0x0005
+#define PCI_DEVICE_CX_DID	0x0006
+#define PCI_DEVICE_XRJ_DID	0x0009	/* PLX-based Xr adapter */
+#define PCI_DEVICE_XR_IBM_DID	0x0011	/* IBM 8-port Async Adapter */
+#define PCI_DEVICE_XR_BULL_DID	0x0013	/* BULL 8-port Async Adapter */
+#define PCI_DEVICE_XR_SAIP_DID	0x001c	/* SAIP card - Xr adapter */
+#define PCI_DEVICE_XR_422_DID	0x0012	/* Xr-422 */
+#define PCI_DEVICE_920_2_DID	0x0034	/* XR-Plus 920 K, 2 port */
+#define PCI_DEVICE_920_4_DID	0x0026	/* XR-Plus 920 K, 4 port */
+#define PCI_DEVICE_920_8_DID	0x0027	/* XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_EPCJ_DID	0x000a	/* PLX 9060 chip for PCI  */
+#define PCI_DEVICE_CX_IBM_DID	0x001b	/* IBM 128-port Async Adapter */
+#define PCI_DEVICE_920_8_HP_DID	0x0058	/* HP XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_XEM_HP_DID	0x0059  /* HP Xem PCI */
+
+#define PCI_DEVICE_XEM_NAME	"AccelePort XEM"
+#define PCI_DEVICE_CX_NAME	"AccelePort CX"
+#define PCI_DEVICE_XR_NAME	"AccelePort Xr"
+#define PCI_DEVICE_XRJ_NAME	"AccelePort Xr (PLX)"
+#define PCI_DEVICE_XR_SAIP_NAME	"AccelePort Xr (SAIP)"
+#define PCI_DEVICE_920_2_NAME	"AccelePort Xr920 2 port"
+#define PCI_DEVICE_920_4_NAME	"AccelePort Xr920 4 port"
+#define PCI_DEVICE_920_8_NAME	"AccelePort Xr920 8 port"
+#define PCI_DEVICE_XR_422_NAME	"AccelePort Xr 422"
+#define PCI_DEVICE_EPCJ_NAME	"AccelePort EPC (PLX)"
+#define PCI_DEVICE_XR_BULL_NAME	"AccelePort Xr (BULL)"
+#define PCI_DEVICE_XR_IBM_NAME	"AccelePort Xr (IBM)"
+#define PCI_DEVICE_CX_IBM_NAME	"AccelePort CX (IBM)"
+#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
+#define PCI_DEVICE_XEM_HP_NAME	"AccelePort XEM (HP)"
+
+/*
+ * On the PCI boards, there is no IO space allocated
+ * The I/O registers will be in the first 3 bytes of the
+ * upper 2MB of the 4MB memory space.  The board memory
+ * will be mapped into the low 2MB of the 4MB memory space
+ */
+
+/* Potential location of PCI Bios from E0000 to FFFFF*/
+#define PCI_BIOS_SIZE		0x00020000
+
+/* Size of Memory and I/O for PCI (4MB) */
+#define PCI_RAM_SIZE		0x00400000
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE		0x00200000
+
+/* Max PCI Window Size (2MB) */
+#define PCI_WIN_SIZE		0x00200000
+
+#define PCI_WIN_SHIFT		21 /* 21 bits max */
+
+/* Offset of I/0 in Memory (2MB) */
+#define PCI_IO_OFFSET		0x00200000
+
+/* Size of IO (2MB) */
+#define PCI_IO_SIZE		0x00200000
+
+/* Number of boards we support at once. */
+#define	MAXBOARDS	32
+#define	MAXPORTS	224
+#define MAXTTYNAMELEN	200
+
+/* Our 3 magic numbers for our board, channel and unit structs */
+#define DGAP_BOARD_MAGIC	0x5c6df104
+#define DGAP_CHANNEL_MAGIC	0x6c6df104
+#define DGAP_UNIT_MAGIC		0x7c6df104
+
+/* Serial port types */
+#define DGAP_SERIAL		0
+#define DGAP_PRINT		1
+
+#define	SERIAL_TYPE_NORMAL	1
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN		((4096) + 4)
+#define MYFLIPLEN		N_TTY_BUF_SIZE
+
+#define SBREAK_TIME 0x25
+#define U2BSIZE 0x400
+
+#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
+
+/*
+ * Our major for the mgmt devices.
+ *
+ * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
+ * 22 has now become obsolete now that the "cu" devices have
+ * been removed from 2.6.
+ * Also, this *IS* the epca driver, just PCI only now.
+ */
+#ifndef DIGI_DGAP_MAJOR
+# define DIGI_DGAP_MAJOR         22
+#endif
+
+/*
+ * The parameters we use to define the periods of the moving averages.
+ */
+#define		MA_PERIOD	(HZ / 10)
+#define		SMA_DUR		(1 * HZ)
+#define		EMA_DUR		(1 * HZ)
+#define		SMA_NPERIODS	(SMA_DUR / MA_PERIOD)
+#define		EMA_NPERIODS	(EMA_DUR / MA_PERIOD)
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.  This is the same structure that is defined
+ * as the default in tty_io.c with the same settings overriden as in serial.c
+ *
+ * In short, this should match the internal serial ports' defaults.
+ */
+#define	DEFAULT_IFLAGS	(ICRNL | IXON)
+#define	DEFAULT_OFLAGS	(OPOST | ONLCR)
+#define	DEFAULT_CFLAGS	(B9600 | CS8 | CREAD | HUPCL | CLOCAL)
+#define	DEFAULT_LFLAGS	(ISIG | ICANON | ECHO | ECHOE | ECHOK | \
+			ECHOCTL | ECHOKE | IEXTEN)
+
+#ifndef _POSIX_VDISABLE
+#define   _POSIX_VDISABLE '\0'
+#endif
+
+#define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
+#define SNIFF_MASK	(SNIFF_MAX - 1)	/* Sniff wrap mask */
+
+#define VPDSIZE (512)
+
+/*
+ * Lock function/defines.
+ * Makes spotting lock/unlock locations easier.
+ */
+# define DGAP_SPINLOCK_INIT(x)		spin_lock_init(&(x))
+# define DGAP_LOCK(x,y)			spin_lock_irqsave(&(x), y)
+# define DGAP_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
+# define DGAP_TRYLOCK(x,y)		spin_trylock(&(x))
+
+/************************************************************************
+ *      FEP memory offsets
+ ************************************************************************/
+#define START           0x0004L         /* Execution start address      */
+
+#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
+#define CMDSTART        0x0400L         /* Start of command buffer      */
+#define CMDMAX          0x0800L         /* End of command buffer        */
+
+#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
+#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 */
+
+/* BIOS MAGIC SPOTS */
+#define ERROR           0x0C14L		/* BIOS error code              */
+#define SEQUENCE	0x0C12L		/* BIOS sequence indicator      */
+#define POSTAREA	0x0C00L		/* POST complete message area   */
+
+/* FEP MAGIC SPOTS */
+#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
+#define NCHAN           0x0C02L         /* number of ports FEP sees     */
+#define PANIC           0x0C10L         /* PANIC area for FEP           */
+#define KMEMEM          0x0C30L         /* Memory for KME use           */
+#define CONFIG          0x0CD0L         /* Concentrator configuration info */
+#define CONFIGSIZE      0x0030          /* configuration info size      */
+#define DOWNREQ         0x0D00          /* Download request buffer pointer */
+
+#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
+#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
+
+#define XEMPORTS    0xC02	/*
+				 * Offset in board memory where FEP5 stores
+				 * how many ports it has detected.
+				 * NOTE: FEP5 reports 64 ports when the user
+				 * has the cable in EBI OUT instead of EBI IN.
+				 */
+
+#define FEPCLR      0x00
+#define FEPMEM      0x02
+#define FEPRST      0x04
+#define FEPINT      0x08
+#define FEPMASK     0x0e
+#define FEPWIN      0x80
+
+#define LOWMEM      0x0100
+#define HIGHMEM     0x7f00
+
+#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	IALTPIN			0x0080		/* Input flag to swap DSR <-> DCD */
+
+/************************************************************************
+ * FEP supported functions
+ ************************************************************************/
+#define SRLOW		0xe0		/* Set receive low water	*/
+#define SRHIGH		0xe1		/* Set receive high water	*/
+#define FLUSHTX		0xe2		/* Flush transmit buffer	*/
+#define PAUSETX		0xe3		/* Pause data transmission	*/
+#define RESUMETX	0xe4		/* Resume data transmission	*/
+#define SMINT		0xe5		/* Set Modem Interrupt		*/
+#define SAFLOWC		0xe6		/* Set Aux. flow control chars	*/
+#define SBREAK		0xe8		/* Send break			*/
+#define SMODEM		0xe9		/* Set 8530 modem control lines	*/
+#define SIFLAG		0xea		/* Set UNIX iflags		*/
+#define SFLOWC		0xeb		/* Set flow control characters	*/
+#define STLOW		0xec		/* Set transmit low water mark	*/
+#define RPAUSE		0xee		/* Pause receive		*/
+#define RRESUME		0xef		/* Resume receive		*/
+#define CHRESET		0xf0		/* Reset Channel		*/
+#define BUFSETALL	0xf2		/* Set Tx & Rx buffer size avail*/
+#define SOFLAG		0xf3		/* Set UNIX oflags		*/
+#define SHFLOW		0xf4		/* Set hardware handshake	*/
+#define SCFLAG		0xf5		/* Set UNIX cflags		*/
+#define SVNEXT		0xf6		/* Set VNEXT character		*/
+#define SPINTFC		0xfc		/* Reserved			*/
+#define SCOMMODE	0xfd		/* Set RS232/422 mode		*/
+
+
+/************************************************************************
+ *	Modes for SCOMMODE
+ ************************************************************************/
+#define MODE_232	0x00
+#define MODE_422	0x01
+
+
+/************************************************************************
+ *      Event flags.
+ ************************************************************************/
+#define IFBREAK         0x01            /* Break received               */
+#define IFTLW           0x02            /* Transmit low water           */
+#define IFTEM           0x04            /* Transmitter empty            */
+#define IFDATA          0x08            /* Receive data present         */
+#define IFMODEM         0x20            /* Modem status change          */
+
+/************************************************************************
+ *      Modem flags
+ ************************************************************************/
+#       define  DM_RTS          0x02    /* Request to send              */
+#       define  DM_CD           0x80    /* Carrier detect               */
+#       define  DM_DSR          0x20    /* Data set ready               */
+#       define  DM_CTS          0x10    /* Clear to send                */
+#       define  DM_RI           0x40    /* Ring indicator               */
+#       define  DM_DTR          0x01    /* Data terminal ready          */
+
+/*
+ * defines from dgap_conf.h
+ */
+#define NULLNODE 0		/* header node, not used */
+#define BNODE 1			/* Board node */
+#define LNODE 2			/* Line node */
+#define CNODE 3			/* Concentrator node */
+#define MNODE 4			/* EBI Module node */
+#define TNODE 5			/* tty name prefix node */
+#define	CUNODE 6		/* cu name prefix (non-SCO) */
+#define PNODE 7			/* trans. print prefix node */
+#define JNODE 8			/* maJor number node */
+#define ANODE 9			/* altpin */
+#define	TSNODE 10		/* tty structure size */
+#define CSNODE 11		/* channel structure size */
+#define BSNODE 12		/* board structure size */
+#define USNODE 13		/* unit schedule structure size */
+#define FSNODE 14		/* f2200 structure size */
+#define VSNODE 15		/* size of VPIX structures */
+#define INTRNODE 16		/* enable interrupt */
+
+/* Enumeration of tokens */
+#define	BEGIN	1
+#define	END	2
+#define	BOARD	10
+
+#define EPCFS	11 /* start of EPC family definitions */
+#define	ICX		11
+#define	MCX		13
+#define PCX	14
+#define	IEPC	15
+#define	EEPC	16
+#define	MEPC	17
+#define	IPCM	18
+#define	EPCM	19
+#define	MPCM	20
+#define PEPC	21
+#define PPCM	22
+#ifdef CP
+#define ICP     23
+#define ECP     24
+#define MCP     25
+#endif
+#define EPCFE	25 /* end of EPC family definitions */
+#define	PC2E	26
+#define	PC4E	27
+#define	PC4E8K	28
+#define	PC8E	29
+#define	PC8E8K	30
+#define	PC16E	31
+#define MC2E8K  34
+#define MC4E8K  35
+#define MC8E8K  36
+
+#define AVANFS	42	/* start of Avanstar family definitions */
+#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 DA28		46 /* AccelePort 2008 */
+#define DA216		47 /* AccelePort 2016 */
+#define DAR4		48 /* AccelePort RAS 4 port */
+#define DAR8		49 /* AccelePort RAS 8 port */
+#define DDR24		50 /* DataFire RAS 24 port */
+#define DDR30		51 /* DataFire RAS 30 port */
+#define DDR48		52 /* DataFire RAS 48 port */
+#define DDR60		53 /* DataFire RAS 60 port */
+#define DA2000FE	53 /* end of AccelePort 2000/RAS family definitions */
+
+#define PCXRFS	106	/* start of PCXR family definitions */
+#define	APORT4	106
+#define	APORT8	107
+#define PAPORT4 108
+#define PAPORT8 109
+#define APORT4_920I	110
+#define APORT8_920I	111
+#define APORT4_920P	112
+#define APORT8_920P	113
+#define APORT2_920P 114
+#define PCXRFE	117	/* end of PCXR family definitions */
+
+#define	LINE	82
+#ifdef T1
+#define T1M	83
+#define E1M	84
+#endif
+#define	CONC	64
+#define	CX	65
+#define	EPC	66
+#define	MOD	67
+#define	PORTS	68
+#define METHOD	69
+#define CUSTOM	70
+#define BASIC	71
+#define STATUS	72
+#define MODEM	73
+/* The following tokens can appear in multiple places */
+#define	SPEED	74
+#define	NPORTS	75
+#define	ID	76
+#define CABLE	77
+#define CONNECT	78
+#define	IO	79
+#define	MEM	80
+#define DPSZ	81
+
+#define	TTYN	90
+#define	CU	91
+#define	PRINT	92
+#define	XPRINT	93
+#define CMAJOR   94
+#define ALTPIN  95
+#define STARTO 96
+#define USEINTR  97
+#define PCIINFO  98
+
+#define	TTSIZ	100
+#define	CHSIZ	101
+#define BSSIZ	102
+#define	UNTSIZ	103
+#define	F2SIZ	104
+#define	VPSIZ	105
+
+#define	TOTAL_BOARD	2
+#define	CURRENT_BRD	4
+#define	BOARD_TYPE	6
+#define	IO_ADDRESS	8
+#define	MEM_ADDRESS	10
+
+#define	FIELDS_PER_PAGE	18
+
+#define TB_FIELD	1
+#define CB_FIELD	3
+#define BT_FIELD	5
+#define IO_FIELD	7
+#define ID_FIELD	8
+#define ME_FIELD	9
+#define TTY_FIELD	11
+#define CU_FIELD	13
+#define PR_FIELD	15
+#define MPR_FIELD	17
+
+#define	MAX_FIELD	512
+
+#define	INIT		0
+#define	NITEMS		128
+#define MAX_ITEM	512
+
+#define	DSCRINST	1
+#define	DSCRNUM		3
+#define	ALTPINQ		5
+#define	SSAVE		7
+
+#define	DSCR		"32"
+#define	ONETONINE	"123456789"
+#define	ALL		"1234567890"
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+	DRIVER_INITIALIZED = 0,
+	DRIVER_NEED_CONFIG_LOAD,
+	DRIVER_REQUESTED_CONFIG,
+	DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+	BOARD_FAILED = 0,
+	CONFIG_NOT_FOUND,
+	BOARD_FOUND,
+	NEED_RESET,
+	FINISHED_RESET,
+	NEED_CONFIG,
+	FINISHED_CONFIG,
+	NEED_DEVICE_CREATION,
+	REQUESTED_DEVICE_CREATION,
+	FINISHED_DEVICE_CREATION,
+	NEED_BIOS_LOAD,
+	REQUESTED_BIOS,
+	WAIT_BIOS_LOAD,
+	FINISHED_BIOS_LOAD,
+	NEED_FEP_LOAD,
+	REQUESTED_FEP,
+	WAIT_FEP_LOAD,
+	FINISHED_FEP_LOAD,
+	NEED_PROC_CREATION,
+	FINISHED_PROC_CREATION,
+	BOARD_READY
+};
+
+/*
+ * All the possible states that a requested concentrator image can be in.
+ */
+enum {
+	NO_PENDING_CONCENTRATOR_REQUESTS = 0,
+	NEED_CONCENTRATOR,
+	REQUESTED_CONCENTRATOR
+};
+
+
+
+/*
+ * Modem line constants are defined as macros because DSR and
+ * DCD are swapable using the ditty altpin option.
+ */
+#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
+#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
+#define D_RTS(ch)       DM_RTS          /* Request to send      */
+#define D_CTS(ch)       DM_CTS          /* Clear to send        */
+#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.
+ */
+struct macounter
+{
+	u32		cnt;	/* Total count */
+	ulong		accum;	/* Acuumulator per period */
+	ulong		sma;	/* Simple moving average */
+	ulong		ema;	/* Exponential moving average */
+};
+
+
+/************************************************************************
+ * Device flag definitions for bd_flags.
+ ************************************************************************/
+#define	BD_FEP5PLUS	0x0001          /* Supports FEP5 Plus commands */
+#define BD_HAS_VPD	0x0002		/* Board has VPD info available */
+
+/*
+ *	Per-board information
+ */
+struct board_t
+{
+	int		magic;		/* Board Magic number.  */
+	int		boardnum;	/* Board number: 0-3 */
+	int		firstminor;	/* First minor, e.g. 0, 30, 60 */
+
+	int		type;		/* Type of board */
+	char		*name;		/* Product Name */
+	struct pci_dev	*pdev;		/* Pointer to the pci_dev struct */
+	u16		vendor;		/* PCI vendor ID */
+	u16		device;		/* PCI device ID */
+	u16		subvendor;	/* PCI subsystem vendor ID */
+	u16		subdevice;	/* PCI subsystem device ID */
+	uchar		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 */
+	u32		bd_flags;	/* Board flags */
+
+	spinlock_t	bd_lock;	/* Used to protect board */
+
+	u32		state;		/* State of card. */
+	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
+
+	struct		tasklet_struct helper_tasklet; /* Poll helper tasklet */
+
+	u32		wait_for_bios;
+	u32		wait_for_fep;
+
+	struct cnode *  bd_config;	/* Config of board */
+
+	u16		nasync;		/* Number of ports on card */
+
+	u32		use_interrupts;	/* Should we be interrupt driven? */
+	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 */
+
+	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 */
+
+	uchar		runwait;	/* # Processes waiting for FEP  */
+	uchar		inhibit_poller; /* Tells  the poller to leave us alone */
+
+	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
+
+	struct tty_driver	*SerialDriver;
+	struct tty_port *SerialPorts;
+	char		SerialName[200];
+	struct tty_driver	*PrintDriver;
+	struct tty_port *PrinterPorts;
+	char		PrintName[200];
+
+	u32		dgap_Major_Serial_Registered;
+	u32		dgap_Major_TransparentPrint_Registered;
+
+	u32		dgap_Serial_Major;
+	u32		dgap_TransparentPrint_Major;
+
+	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 */
+
+	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 */
+	/*
+	 *	Mgmt data.
+	 */
+        char		*msgbuf_head;
+        char		*msgbuf;
+};
+
+
+
+/************************************************************************
+ * Unit flag definitions for un_flags.
+ ************************************************************************/
+#define UN_ISOPEN	0x0001		/* Device is open		*/
+#define UN_CLOSING	0x0002		/* Line is being closed		*/
+#define UN_IMM		0x0004		/* Service immediately		*/
+#define UN_BUSY		0x0008		/* Some work this channel	*/
+#define UN_BREAKI	0x0010		/* Input break received		*/
+#define UN_PWAIT	0x0020		/* Printer waiting for terminal	*/
+#define UN_TIME		0x0040		/* Waiting on time		*/
+#define UN_EMPTY	0x0080		/* Waiting output queue empty	*/
+#define UN_LOW		0x0100		/* Waiting output low water mark*/
+#define UN_EXCL_OPEN	0x0200		/* Open for exclusive use	*/
+#define UN_WOPEN	0x0400		/* Device waiting for open	*/
+#define UN_WIOCTL	0x0800		/* Device waiting for open	*/
+#define UN_HANGUP	0x8000		/* Carrier lost			*/
+
+struct device;
+
+/************************************************************************
+ * Structure for terminal or printer unit.
+ ************************************************************************/
+struct un_t {
+	int	magic;		/* Unit Magic Number.			*/
+	struct	channel_t *un_ch;
+	u32	un_time;
+	u32	un_type;
+	u32	un_open_count;	/* Counter of opens to port		*/
+	struct tty_struct *un_tty;/* Pointer to unit tty structure	*/
+	u32	un_flags;	/* Unit flags				*/
+	wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
+	u32	un_dev;		/* Minor device number			*/
+	tcflag_t un_oflag;	/* oflags being done on board		*/
+	tcflag_t un_lflag;	/* lflags being done on board		*/
+	struct device *un_sysfs;
+};
+
+
+/************************************************************************
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON         0x0001          /* Printer on string                */
+#define CH_OUT          0x0002          /* Dial-out device open             */
+#define CH_STOP         0x0004          /* Output is stopped                */
+#define CH_STOPI        0x0008          /* Input is stopped                 */
+#define CH_CD           0x0010          /* Carrier is present               */
+#define CH_FCAR         0x0020          /* Carrier forced on                */
+
+#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
+#define CH_WLOW         0x0100          /* Term waiting low event           */
+#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
+#define CH_RENABLE      0x0400          /* Buffer just emptied          */
+#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
+#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
+#define CH_BAUD0	0x2000		/* Used for checking B0 transitions */
+#define CH_HANGUP       0x8000		/* Hangup received                  */
+
+/*
+ * Definitions for ch_sniff_flags
+ */
+#define SNIFF_OPEN	0x1
+#define SNIFF_WAIT_DATA	0x2
+#define SNIFF_WAIT_SPACE 0x4
+
+
+/************************************************************************
+ ***	Definitions for Digi ditty(1) command.
+ ************************************************************************/
+
+
+/*
+ * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
+ */
+
+/************************************************************************
+ * This module provides application access to special Digi
+ * serial line enhancements which are not standard UNIX(tm) features.
+ ************************************************************************/
+
+#if !defined(TIOCMODG)
+
+#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		*/
+#define		TIOCM_DTR	0x02		/* data terminal ready	*/
+#define		TIOCM_RTS	0x04		/* request to send	*/
+#define		TIOCM_ST	0x08		/* secondary transmit	*/
+#define		TIOCM_SR	0x10		/* secondary receive	*/
+#define		TIOCM_CTS	0x20		/* clear to send	*/
+#define		TIOCM_CAR	0x40		/* carrier detect	*/
+#define		TIOCM_RNG	0x80		/* ring	indicator	*/
+#define		TIOCM_DSR	0x100		/* data set ready	*/
+#define		TIOCM_RI	TIOCM_RNG	/* ring (alternate)	*/
+#define		TIOCM_CD	TIOCM_CAR	/* carrier detect (alt)	*/
+#endif
+
+#endif
+
+#if !defined(TIOCMSET)
+#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 */
+#endif
+
+
+#if !defined(TIOCSDTR)
+#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
+#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
+
+#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
+#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
+#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
+
+#define DIGI_KME	('e'<<8) | 98		/* Read/Write Host	*/
+						/* 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_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 */
+
+struct	digiflow_t {
+	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_MASK	0x03		/* 2200 flow cntl bit mask  */
+#define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
+#define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
+#define	F2200_XON	0xf8
+#define	P2200_XON	0xf9
+#define	F2200_XOFF	0xfa
+#define	P2200_XOFF	0xfb
+
+#define	FXOFF_MASK	0x03			/* 2200 flow status mask    */
+#define	RCVD_FXOFF	0x01			/* 2x36 Terminal XOFF rcvd  */
+#define	RCVD_PXOFF	0x02			/* 2x36 Printer XOFF rcvd   */
+#endif
+
+/************************************************************************
+ * Values for digi_flags
+ ************************************************************************/
+#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
+#define DIGI_FAST	0x0002		/* Fast baud rates		*/
+#define RTSPACE		0x0004		/* RTS input flow control	*/
+#define CTSPACE		0x0008		/* CTS output flow control	*/
+#define DSRPACE		0x0010		/* DSR output flow control	*/
+#define DCDPACE		0x0020		/* DCD output flow control	*/
+#define DTRPACE		0x0040		/* DTR input flow control	*/
+#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
+#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
+#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
+#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
+#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl*/
+#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input*/
+#define DIGI_DTR_TOGGLE 0x2000		/* Support DTR Toggle		*/
+#define	DIGI_422	0x4000		/* for 422/232 selectable panel */
+#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		*/
+
+/************************************************************************
+ * These options are not supported on the comxi.
+ ************************************************************************/
+#define	DIGI_COMXI	(DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
+
+#define DIGI_PLEN	28		/* String length		*/
+#define	DIGI_TSIZ	10		/* Terminal string len		*/
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_t {
+	unsigned short	digi_flags;		/* Flags (see above)	*/
+	unsigned short	digi_maxcps;		/* Max printer CPS	*/
+	unsigned short	digi_maxchar;		/* Max chars in print queue */
+	unsigned short	digi_bufsize;		/* Buffer size		*/
+	unsigned char	digi_onlen;		/* Length of ON string	*/
+	unsigned char	digi_offlen;		/* Length of OFF string	*/
+	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
+	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
+	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
+};
+
+/************************************************************************
+ * KME definitions and structures.
+ ************************************************************************/
+#define	RW_IDLE		0	/* Operation complete			*/
+#define	RW_READ		1	/* Read Concentrator Memory		*/
+#define	RW_WRITE	2	/* Write Concentrator Memory		*/
+
+struct rw_t {
+	unsigned char	rw_req;		/* Request type			*/
+	unsigned char	rw_board;	/* Host Adapter board number	*/
+	unsigned char	rw_conc;	/* Concentrator number		*/
+	unsigned char	rw_reserved;	/* Reserved for expansion	*/
+	unsigned long	rw_addr;	/* Address in concentrator	*/
+	unsigned short	rw_size;	/* Read/write request length	*/
+	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
+ ************************************************************************/
+struct digi_dinfo {
+	unsigned long	dinfo_nboards;		/* # boards configured	*/
+	char		dinfo_reserved[12];	/* for future expansion */
+	char		dinfo_version[16];	/* driver version       */
+};
+
+#define	DIGI_GETDD	('d'<<8) | 248		/* get driver info      */
+
+/************************************************************************
+ * Structure used with ioctl commands for per-board information
+ *
+ * physsize and memsize differ when board has "windowed" memory
+ ************************************************************************/
+struct digi_info {
+	unsigned long	info_bdnum;		/* Board number (0 based)  */
+	unsigned long	info_ioport;		/* io port address         */
+	unsigned long	info_physaddr;		/* memory address          */
+	unsigned long	info_physsize;		/* Size of host mem window */
+	unsigned long	info_memsize;		/* Amount of dual-port mem */
+						/* on board                */
+	unsigned short	info_bdtype;		/* Board type              */
+	unsigned short	info_nports;		/* number of ports         */
+	char		info_bdstate;		/* board state             */
+	char		info_reserved[7];	/* for future expansion    */
+};
+
+#define	DIGI_GETBD	('d'<<8) | 249		/* get board info          */
+
+struct digi_stat {
+	unsigned int	info_chan;		/* Channel number (0 based)  */
+	unsigned int	info_brd;		/* Board number (0 based)  */
+	unsigned long	info_cflag;		/* cflag for channel       */
+	unsigned long	info_iflag;		/* iflag for channel       */
+	unsigned long	info_oflag;		/* oflag for channel       */
+	unsigned long	info_mstat;		/* mstat for channel       */
+	unsigned long	info_tx_data;		/* tx_data for channel       */
+	unsigned long	info_rx_data;		/* rx_data for channel       */
+	unsigned long	info_hflow;		/* hflow for channel       */
+	unsigned long	info_reserved[8];	/* for future expansion    */
+};
+
+#define	DIGI_GETSTAT	('d'<<8) | 244		/* get board info          */
+/************************************************************************
+ *
+ * Structure used with ioctl commands for per-channel information
+ *
+ ************************************************************************/
+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_chsize;		/* Channel structure size  */
+	unsigned long	info_sleep_stat;	/* sleep status		   */
+	dev_t		info_dev;		/* device number	   */
+	unsigned char	info_initstate;		/* Channel init state	   */
+	unsigned char	info_running;		/* Channel running state   */
+	long		reserved[8];		/* reserved for future use */
+};
+
+/*
+* This structure is used with the DIGI_FEPCMD ioctl to
+* tell the driver which port to send the command for.
+*/
+struct digi_cmd {
+	int	cmd;
+	int	word;
+	int	ncmds;
+	int	chan; /* channel index (zero based) */
+	int	bdid; /* board index (zero based) */
+};
+
+/*
+*  info_sleep_stat defines
+*/
+#define INFO_RUNWAIT	0x0001
+#define INFO_WOPEN	0x0002
+#define INFO_TTIOW	0x0004
+#define INFO_CH_RWAIT	0x0008
+#define INFO_CH_WEMPTY	0x0010
+#define INFO_CH_WLOW	0x0020
+#define INFO_XXBUF_BUSY 0x0040
+
+#define	DIGI_GETCH	('d'<<8) | 245		/* get board info          */
+
+/* Board type definitions */
+
+#define	SUBTYPE		0007
+#define	T_PCXI		0000
+#define T_PCXM		0001
+#define T_PCXE		0002
+#define T_PCXR		0003
+#define T_SP		0004
+#define T_SP_PLUS	0005
+#	define T_HERC	0000
+#	define T_HOU	0001
+#	define T_LON	0002
+#	define T_CHA	0003
+#define FAMILY		0070
+#define T_COMXI		0000
+#define T_PCXX		0010
+#define T_CX		0020
+#define T_EPC		0030
+#define	T_PCLITE	0040
+#define	T_SPXX		0050
+#define	T_AVXX		0060
+#define T_DXB		0070
+#define T_A2K_4_8	0070
+#define BUSTYPE		0700
+#define T_ISABUS	0000
+#define T_MCBUS		0100
+#define	T_EISABUS	0200
+#define	T_PCIBUS	0400
+
+/* Board State Definitions */
+
+#define	BD_RUNNING	0x0
+#define	BD_REASON	0x7f
+#define	BD_NOTFOUND	0x1
+#define	BD_NOIOPORT	0x2
+#define	BD_NOMEM	0x3
+#define	BD_NOBIOS	0x4
+#define	BD_NOFEP	0x5
+#define	BD_FAILED	0x6
+#define BD_ALLOCATED	0x7
+#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_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.
+ ************************************************************************/
+struct channel_t {
+	int magic;			/* Channel Magic Number		*/
+	struct bs_t	*ch_bs;		/* Base structure pointer       */
+	struct cm_t	*ch_cm;		/* Command queue pointer        */
+	struct board_t *ch_bd;		/* Board structure pointer      */
+	unsigned char *ch_vaddr;	/* FEP memory origin            */
+	unsigned char *ch_taddr;	/* Write buffer origin          */
+	unsigned char *ch_raddr;	/* Read buffer origin           */
+	struct digi_t  ch_digi;		/* Transparent Print structure  */
+	struct un_t ch_tun;		/* Terminal unit info           */
+	struct un_t ch_pun;		/* Printer unit info            */
+
+	spinlock_t	ch_lock;	/* provide for serialization */
+	wait_queue_head_t ch_flags_wait;
+
+	u32	pscan_state;
+	uchar	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_cpstime;		/* Time for CPS calculations    */
+
+	tcflag_t ch_c_iflag;		/* channel iflags               */
+	tcflag_t ch_c_cflag;		/* channel cflags               */
+	tcflag_t ch_c_oflag;		/* channel oflags               */
+	tcflag_t ch_c_lflag;		/* channel lflags               */
+
+	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 */
+	u16  ch_tstart;			/* Transmit buffer start        */
+	u16  ch_tsize;			/* Transmit buffer size         */
+	u16  ch_rstart;			/* Receive buffer start         */
+	u16  ch_rsize;			/* Receive buffer size          */
+	u16  ch_rdelay;			/* Receive delay time           */
+
+	u16	ch_tlw;			/* Our currently set low water mark */
+
+	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     */
+	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	*/
+	ulong	ch_err_break;		/* Count of breaks on channel	*/
+	ulong	ch_err_overrun;		/* Count of overruns on channel	*/
+
+	uint ch_sniff_in;
+	uint ch_sniff_out;
+	char *ch_sniff_buf;		/* Sniff buffer for proc */
+	ulong ch_sniff_flags;		/* Channel flags                */
+	wait_queue_head_t ch_sniff_wait;
+};
+
+/************************************************************************
+ * 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	*/
+};
+
+/************************************************************************
+ * 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	*/
+};
+
+/************************************************************************
+ * Download buffer structure.
+ ************************************************************************/
+struct downld_t {
+	uchar	dl_type;		/* Header                       */
+	uchar	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                */
+};
+
+/************************************************************************
+ * Per channel buffer structure
+ ************************************************************************
+ *              Base Structure Entries Usage Meanings to Host           *
+ *                                                                      *
+ *        W = read write        R = read only                           *
+ *        C = changed by commands only                                  *
+ *        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            */
+};
+
+struct cnode {
+	struct cnode *next;
+	int type;
+	int numbrd;
+
+	union {
+		struct {
+			char  type;	/* Board Type 		*/
+			short port;	/* I/O Address		*/
+			char  *portstr; /* I/O Address in string */
+			long  addr;	/* Memory Address	*/
+			char  *addrstr; /* Memory Address in string */
+			long  pcibus;	/* PCI BUS		*/
+			char  *pcibusstr; /* PCI BUS in string */
+			long  pcislot;	/* PCI SLOT		*/
+			char  *pcislotstr; /* PCI SLOT in string */
+			char  nport;	/* Number of Ports	*/
+			char  *id;	/* tty id		*/
+			int   start;	/* start of tty counting */
+			char  *method;  /* Install method       */
+			char  v_type;
+			char  v_port;
+			char  v_addr;
+			char  v_pcibus;
+			char  v_pcislot;
+			char  v_nport;
+			char  v_id;
+			char  v_start;
+			char  v_method;
+			char  line1;
+			char  line2;
+			char  conc1;   /* total concs in line1 */
+			char  conc2;   /* total concs in line2 */
+			char  module1; /* total modules for line1 */
+			char  module2; /* total modules for line2 */
+			char  *status; /* config status */
+			char  *dimstatus;	 /* Y/N */
+			int   status_index; /* field pointer */
+		} board;
+
+		struct {
+			char  *cable;
+			char  v_cable;
+			char  speed;
+			char  v_speed;
+		} line;
+
+		struct {
+			char  type;
+			char  *connect;
+			char  speed;
+			char  nport;
+			char  *id;
+			char  *idstr;
+			int   start;
+			char  v_type;
+			char  v_connect;
+			char  v_speed;
+			char  v_nport;
+			char  v_id;
+			char  v_start;
+		} conc;
+
+		struct {
+			char type;
+			char nport;
+			char *id;
+			char *idstr;
+			int  start;
+			char v_type;
+			char v_nport;
+			char v_id;
+			char v_start;
+		} module;
+
+		char *ttyname;
+
+		char *cuname;
+
+		char *printname;
+
+		int  majornumber;
+
+		int  altpin;
+
+		int  ttysize;
+
+		int  chsize;
+
+		int  bssize;
+
+		int  unsize;
+
+		int  f2size;
+
+		int  vpixsize;
+
+		int  useintr;
+	} u;
+};
+
+#endif
diff --git a/drivers/staging/dgap/dgap_conf.h b/drivers/staging/dgap/dgap_conf.h
deleted file mode 100644
index 484ed726a4d6..000000000000
--- a/drivers/staging/dgap/dgap_conf.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- *****************************************************************************
- *
- *	dgap_conf.h - Header file for installations and parse files.
- *
- *	$Id: dgap_conf.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_CONF_H
-#define _DGAP_CONF_H
-
-#define NULLNODE 0		/* header node, not used */
-#define BNODE 1			/* Board node */
-#define LNODE 2			/* Line node */
-#define CNODE 3			/* Concentrator node */
-#define MNODE 4			/* EBI Module node */
-#define TNODE 5			/* tty name prefix node */
-#define	CUNODE 6		/* cu name prefix (non-SCO) */
-#define PNODE 7			/* trans. print prefix node */
-#define JNODE 8			/* maJor number node */
-#define ANODE 9			/* altpin */
-#define	TSNODE 10		/* tty structure size */
-#define CSNODE 11		/* channel structure size */
-#define BSNODE 12		/* board structure size */
-#define USNODE 13		/* unit schedule structure size */
-#define FSNODE 14		/* f2200 structure size */
-#define VSNODE 15		/* size of VPIX structures */
-#define INTRNODE 16		/* enable interrupt */
-
-/* Enumeration of tokens */
-#define	BEGIN	1
-#define	END	2
-#define	BOARD	10
-
-#define EPCFS	11 /* start of EPC family definitions */
-#define	ICX		11
-#define	MCX		13
-#define PCX	14
-#define	IEPC	15
-#define	EEPC	16
-#define	MEPC	17
-#define	IPCM	18
-#define	EPCM	19
-#define	MPCM	20
-#define PEPC	21
-#define PPCM	22
-#ifdef CP
-#define ICP     23
-#define ECP     24
-#define MCP     25
-#endif
-#define EPCFE	25 /* end of EPC family definitions */
-#define	PC2E	26
-#define	PC4E	27
-#define	PC4E8K	28
-#define	PC8E	29
-#define	PC8E8K	30
-#define	PC16E	31
-#define MC2E8K  34
-#define MC4E8K  35
-#define MC8E8K  36
-
-#define AVANFS	42	/* start of Avanstar family definitions */
-#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 DA28		46 /* AccelePort 2008 */
-#define DA216		47 /* AccelePort 2016 */
-#define DAR4		48 /* AccelePort RAS 4 port */
-#define DAR8		49 /* AccelePort RAS 8 port */
-#define DDR24		50 /* DataFire RAS 24 port */
-#define DDR30		51 /* DataFire RAS 30 port */
-#define DDR48		52 /* DataFire RAS 48 port */
-#define DDR60		53 /* DataFire RAS 60 port */
-#define DA2000FE	53 /* end of AccelePort 2000/RAS family definitions */
-
-#define PCXRFS	106	/* start of PCXR family definitions */
-#define	APORT4	106
-#define	APORT8	107
-#define PAPORT4 108
-#define PAPORT8 109
-#define APORT4_920I	110
-#define APORT8_920I	111
-#define APORT4_920P	112
-#define APORT8_920P	113
-#define APORT2_920P 114
-#define PCXRFE	117	/* end of PCXR family definitions */
-
-#define	LINE	82
-#ifdef T1
-#define T1M	83
-#define E1M	84
-#endif
-#define	CONC	64
-#define	CX	65
-#define	EPC	66
-#define	MOD	67
-#define	PORTS	68
-#define METHOD	69
-#define CUSTOM	70
-#define BASIC	71
-#define STATUS	72
-#define MODEM	73
-/* The following tokens can appear in multiple places */
-#define	SPEED	74
-#define	NPORTS	75
-#define	ID	76
-#define CABLE	77
-#define CONNECT	78
-#define	IO	79
-#define	MEM	80
-#define DPSZ	81
-
-#define	TTYN	90
-#define	CU	91
-#define	PRINT	92
-#define	XPRINT	93
-#define CMAJOR   94
-#define ALTPIN  95
-#define STARTO 96
-#define USEINTR  97
-#define PCIINFO  98
-
-#define	TTSIZ	100
-#define	CHSIZ	101
-#define BSSIZ	102
-#define	UNTSIZ	103
-#define	F2SIZ	104
-#define	VPSIZ	105
-
-#define	TOTAL_BOARD	2
-#define	CURRENT_BRD	4
-#define	BOARD_TYPE	6
-#define	IO_ADDRESS	8
-#define	MEM_ADDRESS	10
-
-#define	FIELDS_PER_PAGE	18
-
-#define TB_FIELD	1
-#define CB_FIELD	3
-#define BT_FIELD	5
-#define IO_FIELD	7
-#define ID_FIELD	8
-#define ME_FIELD	9
-#define TTY_FIELD	11
-#define CU_FIELD	13
-#define PR_FIELD	15
-#define MPR_FIELD	17
-
-#define	MAX_FIELD	512
-
-#define	INIT		0
-#define	NITEMS		128
-#define MAX_ITEM	512
-
-#define	DSCRINST	1
-#define	DSCRNUM		3
-#define	ALTPINQ		5
-#define	SSAVE		7
-
-#define	DSCR		"32"
-#define	ONETONINE	"123456789"
-#define	ALL		"1234567890"
-
-
-struct cnode {
-	struct cnode *next;
-	int type;
-	int numbrd;
-
-	union {
-		struct {
-			char  type;	/* Board Type 		*/
-			short port;	/* I/O Address		*/
-			char  *portstr; /* I/O Address in string */
-			long  addr;	/* Memory Address	*/
-			char  *addrstr; /* Memory Address in string */
-			long  pcibus;	/* PCI BUS		*/
-			char  *pcibusstr; /* PCI BUS in string */
-			long  pcislot;	/* PCI SLOT		*/
-			char  *pcislotstr; /* PCI SLOT in string */
-			char  nport;	/* Number of Ports	*/
-			char  *id;	/* tty id		*/
-			int   start;	/* start of tty counting */
-			char  *method;  /* Install method       */
-			char  v_type;
-			char  v_port;
-			char  v_addr;
-			char  v_pcibus;
-			char  v_pcislot;
-			char  v_nport;
-			char  v_id;
-			char  v_start;
-			char  v_method;
-			char  line1;
-			char  line2;
-			char  conc1;   /* total concs in line1 */
-			char  conc2;   /* total concs in line2 */
-			char  module1; /* total modules for line1 */
-			char  module2; /* total modules for line2 */
-			char  *status; /* config status */
-			char  *dimstatus;	 /* Y/N */
-			int   status_index; /* field pointer */
-		} board;
-
-		struct {
-			char  *cable;
-			char  v_cable;
-			char  speed;
-			char  v_speed;
-		} line;
-
-		struct {
-			char  type;
-			char  *connect;
-			char  speed;
-			char  nport;
-			char  *id;
-			char  *idstr;
-			int   start;
-			char  v_type;
-			char  v_connect;
-			char  v_speed;
-			char  v_nport;
-			char  v_id;
-			char  v_start;
-		} conc;
-
-		struct {
-			char type;
-			char nport;
-			char *id;
-			char *idstr;
-			int  start;
-			char v_type;
-			char v_nport;
-			char v_id;
-			char v_start;
-		} module;
-
-		char *ttyname;
-
-		char *cuname;
-
-		char *printname;
-
-		int  majornumber;
-
-		int  altpin;
-
-		int  ttysize;
-
-		int  chsize;
-
-		int  bssize;
-
-		int  unsize;
-
-		int  f2size;
-
-		int  vpixsize;
-
-		int  useintr;
-	} u;
-};
-
-#endif
diff --git a/drivers/staging/dgap/dgap_downld.h b/drivers/staging/dgap/dgap_downld.h
deleted file mode 100644
index 271ac19257f9..000000000000
--- a/drivers/staging/dgap/dgap_downld.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- * $Id: dgap_downld.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- */
-
-/*
-** downld.h 
-**  - describes the interface between the user level download process
-**    and the concentrator download driver.
-*/
-
-#ifndef _DGAP_DOWNLD_H_
-#define _DGAP_DOWNLD_H_
-
-
-struct fepimg {
-    int type;				/* board type */
-    int	len;				/* length of image */
-    char fepimage[1];			/* beginning of image */
-};
-
-struct downldio {
-    unsigned int req_type;		/* FEP or concentrator */
-    unsigned int bdid;			/* opaque board identifier */
-    union {
-	struct downld_t dl;		/* download structure */
-	struct fepimg   fi;		/* fep/bios image structure */
-    } image;
-};
-
-#define DIGI_DLREQ_GET	(('d'<<8) | 220)
-#define DIGI_DLREQ_SET	(('d'<<8) | 221)
-
-#define DIGI_DL_NUKE    (('d'<<8) | 222) /* Not really a dl request, but
-					  dangerous enuff to not put in
-					  digi.h */
-/* Packed bits of intarg for DIGI_DL_NUKE */
-#define DIGI_NUKE_RESET_ALL	 (1 << 31)
-#define DIGI_NUKE_INHIBIT_POLLER (1 << 30)
-#define DIGI_NUKE_BRD_NUMB        0x0f
-	
-
-
-#define	DLREQ_BIOS	0
-#define	DLREQ_FEP	1
-#define	DLREQ_CONC	2
-#define	DLREQ_CONFIG	3
-#define DLREQ_DEVCREATE 4
-
-#endif
diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c
deleted file mode 100644
index 089d017fc291..000000000000
--- a/drivers/staging/dgap/dgap_driver.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- * 
- * 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.
- *
- * $Id: dgap_driver.c,v 1.3 2011/06/21 10:35:16 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>	/* For udelay */
-#include <linux/slab.h>
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <linux/sched.h>
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-#include "dgap_sysfs.h"
-
-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");
-
-/*
- * insmod command line overrideable parameters
- *
- * NOTE: we use a set of macros to create the variables, which allows
- * us to specify the variable type, name, initial value, and description.
- */
-PARM_INT(debug,		0x00,		0644,	"Driver debugging level");
-PARM_INT(rawreadok,	1,		0644,	"Bypass flip buffers on input");
-PARM_INT(trcbuf_size,	0x100000,	0644,	"Debugging trace buffer size.");
-
-
-/**************************************************************************
- *
- * 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);
-static void		dgap_cleanup_board(struct board_t *brd);
-static void		dgap_poll_handler(ulong dummy);
-static int		dgap_init_pci(void);
-static int		dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void		dgap_remove_one(struct pci_dev *dev);
-static int		dgap_probe1(struct pci_dev *pdev, int card_type);
-static void		dgap_mbuf(struct board_t *brd, const char *fmt, ...);
-static int		dgap_do_remap(struct board_t *brd);
-static irqreturn_t	dgap_intr(int irq, void *voidbrd);
-
-/* Driver load/unload functions */
-int			dgap_init_module(void);
-void			dgap_cleanup_module(void);
-
-module_init(dgap_init_module);
-module_exit(dgap_cleanup_module);
-
-
-/*
- * File operations permitted on Control/Management major.
- */
-static struct file_operations DgapBoardFops =
-{
-	.owner		=	THIS_MODULE,
-};
-
-
-/*
- * Globals
- */
-uint			dgap_NumBoards;
-struct board_t		*dgap_Board[MAXBOARDS];
-DEFINE_SPINLOCK(dgap_global_lock);
-ulong			dgap_poll_counter;
-char			*dgap_config_buf;
-int			dgap_driver_state = DRIVER_INITIALIZED;
-DEFINE_SPINLOCK(dgap_dl_lock);
-wait_queue_head_t	dgap_dl_wait;
-int			dgap_dl_action;
-int			dgap_poll_tick = 20;	/* Poll interval - 20 ms */
-
-/*
- * Static vars.
- */
-static int		dgap_Major_Control_Registered = FALSE;
-static uint		dgap_driver_start = FALSE;
-
-static struct class *	dgap_class;
-
-/*
- * Poller stuff
- */
-static 			DEFINE_SPINLOCK(dgap_poll_lock);	/* Poll scheduling lock */
-static ulong		dgap_poll_time;				/* Time of next poll */
-static uint		dgap_poll_stop;				/* Used to tell poller to stop */
-static struct timer_list dgap_poll_timer;
-
-
-static struct pci_device_id dgap_pci_tbl[] = {
-	{       DIGI_VID, PCI_DEVICE_XEM_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	0 },
-	{       DIGI_VID, PCI_DEVICE_CX_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
-	{       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	2 },
-	{       DIGI_VID, PCI_DEVICE_EPCJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	3 },
-	{       DIGI_VID, PCI_DEVICE_920_2_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	4 },
-	{       DIGI_VID, PCI_DEVICE_920_4_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	5 },
-	{       DIGI_VID, PCI_DEVICE_920_8_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	6 },
-	{       DIGI_VID, PCI_DEVICE_XR_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	7 },
-	{       DIGI_VID, PCI_DEVICE_XRJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	8 },
-	{       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	9 },
-	{       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	10 },
-	{       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	11 },
-	{       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	12 },
-	{       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
-	{       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	14 },
-	{0,}					/* 0 terminated list. */
-};
-MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
-
-
-/*
- * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
- */
-struct board_id {
-	uint config_type;
-	uchar *name;
-	uint maxports;
-	uint dpatype;
-};
-
-static struct board_id dgap_Ids[] =
-{
-	{	PPCM,		PCI_DEVICE_XEM_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
-	{	PCX,		PCI_DEVICE_CX_NAME,	128,	(T_CX | T_PCIBUS)		},
-	{	PCX,		PCI_DEVICE_CX_IBM_NAME,	128,	(T_CX | T_PCIBUS)		},
-	{	PEPC,		PCI_DEVICE_EPCJ_NAME,	224,	(T_EPC  | T_PCIBUS)		},
-	{	APORT2_920P,	PCI_DEVICE_920_2_NAME,	2,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT4_920P,	PCI_DEVICE_920_4_NAME,	4,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT8_920P,	PCI_DEVICE_920_8_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XRJ_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_422_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_IBM_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_SAIP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_BULL_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT8_920P,	PCI_DEVICE_920_8_HP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PPCM,		PCI_DEVICE_XEM_HP_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
-	{0,}						/* 0 terminated list. */
-};
-
-static struct pci_driver dgap_driver = {
-	.name		= "dgap",
-	.probe		= dgap_init_one,
-	.id_table	= dgap_pci_tbl,
-	.remove		= dgap_remove_one,
-};
-
-
-char *dgap_state_text[] = {
-	"Board Failed",
-	"Configuration for board not found.\n\t\t\tRun mpi to configure board.",
-	"Board Found",
-	"Need Reset",
-	"Finished Reset",
-	"Need Config",
-	"Finished Config",
-	"Need Device Creation",
-	"Requested Device Creation",
-	"Finished Device Creation",
-	"Need BIOS Load", 
-	"Requested BIOS", 
-	"Doing BIOS Load",
-	"Finished BIOS Load",
-	"Need FEP Load", 
-	"Requested FEP",
-	"Doing FEP Load",
-	"Finished FEP Load",
-	"Requested PROC creation",
-	"Finished PROC creation",
-	"Board READY",
-};
-
-char *dgap_driver_state_text[] = {
-	"Driver Initialized",
-	"Driver needs configuration load.",
-	"Driver requested configuration from download daemon.",
-	"Driver Ready."
-};
-
-
-
-/************************************************************************
- *
- * Driver load/unload functions
- *
- ************************************************************************/
-
-/*
- * init_module()
- *
- * Module load.  This is where it all starts.
- */
-int dgap_init_module(void)
-{
-	int rc = 0;
-
-	APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
-
-	/*
-	 * Initialize global stuff
-	 */
-	rc = dgap_start();
-
-	if (rc < 0) {
-		return(rc);
-	}
-
-	/*
-	 * Find and configure all the cards
-	 */
-	rc = dgap_init_pci();
-
-	/*
-	 * If something went wrong in the scan, bail out of driver.
-	 */
-	if (rc < 0) {
-		/* Only unregister the pci driver if it was actually registered. */
-		if (dgap_NumBoards)
-			pci_unregister_driver(&dgap_driver);
-		else
-			printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
-
-		dgap_cleanup_module();
-	}
-	else {
-		dgap_create_driver_sysfiles(&dgap_driver);
-	}
-  
-	DPR_INIT(("Finished init_module. Returning %d\n", rc));
-	return (rc);
-}
-
-
-/*
- * Start of driver.
- */
-static int dgap_start(void)
-{
-	int rc = 0;
-	unsigned long flags;
-
-	if (dgap_driver_start == FALSE) {
-
-		dgap_driver_start = TRUE;
-
-	        /* make sure that the globals are init'd before we do anything else */
-	        dgap_init_globals();
-
-		dgap_NumBoards = 0;
-
-		APR(("For the tools package or updated drivers please visit http://www.digi.com\n"));
-
-		/*
-		 * Register our base character device into the kernel.
-		 * This allows the download daemon to connect to the downld device
-		 * before any of the boards are init'ed.
-		 */
-		if (!dgap_Major_Control_Registered) {
-			/*
-			 * Register management/dpa devices
-			 */
-			rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
-			if (rc < 0) {
-				APR(("Can't register dgap driver device (%d)\n", rc));
-				return (rc);
-			}
-
-			dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
-			device_create(dgap_class, NULL,
-				MKDEV(DIGI_DGAP_MAJOR, 0),
-				NULL, "dgap_mgmt");
-			device_create(dgap_class, NULL,
-				MKDEV(DIGI_DGAP_MAJOR, 1),
-				NULL, "dgap_downld");
-			dgap_Major_Control_Registered = TRUE;
-		}
-
-		/*
-		 * Init any global tty stuff.
-		 */
-		rc = dgap_tty_preinit();
-
-		if (rc < 0) {
-			APR(("tty preinit - not enough memory (%d)\n", rc));
-			return(rc); 
-		}
-
-		/* Start the poller */
-		DGAP_LOCK(dgap_poll_lock, flags);
-		init_timer(&dgap_poll_timer);
-		dgap_poll_timer.function = dgap_poll_handler;
-		dgap_poll_timer.data = 0;
-		dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
-		dgap_poll_timer.expires = dgap_poll_time;
-		DGAP_UNLOCK(dgap_poll_lock, flags);
-
-		add_timer(&dgap_poll_timer);
-
-		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-	}
-
-	return (rc);
-}
-
-
-/*
- * Register pci driver, and return how many boards we have.
- */
-static int dgap_init_pci(void)
-{
-	return pci_register_driver(&dgap_driver);
-}
-
-
-/* returns count (>= 0), or negative on error */
-static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int rc;
-
-	/* wake up and enable device */
-	rc = pci_enable_device(pdev);
-
-	if (rc < 0) {
-		rc = -EIO;
-	} else {  
-		rc = dgap_probe1(pdev, ent->driver_data);
-		if (rc == 0) {
-			dgap_NumBoards++;
-			DPR_INIT(("Incrementing numboards to %d\n", dgap_NumBoards));
-		}
-	}
-	return rc;
-}               
-
-
-static int dgap_probe1(struct pci_dev *pdev, int card_type)
-{
-	return dgap_found_board(pdev, card_type);
-}
-         
-        
-static void dgap_remove_one(struct pci_dev *dev)
-{
-	/* Do Nothing */
-}
-
-
-/*
- * dgap_cleanup_module()
- *
- * Module unload.  This is where it all ends.
- */
-void dgap_cleanup_module(void)
-{
-	int i;
-	ulong lock_flags;
-
-	DGAP_LOCK(dgap_poll_lock, lock_flags);
-	dgap_poll_stop = 1;
-	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
-
-	/* Turn off poller right away. */
-	del_timer_sync( &dgap_poll_timer);
-
-	dgap_remove_driver_sysfiles(&dgap_driver);
-
-
-	if (dgap_Major_Control_Registered) {
-		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
-		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
-		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]);
-		dgap_cleanup_board(dgap_Board[i]);
-	}
-
-	dgap_tty_post_uninit();
-
-#if defined(DGAP_TRACER)
-	/* last thing, make sure we release the tracebuffer */
-	dgap_tracer_free();
-#endif
-	if (dgap_NumBoards)
-		pci_unregister_driver(&dgap_driver);
-}
-
-
-/*
- * dgap_cleanup_board()
- *
- * Free all the memory associated with a board
- */
-static void dgap_cleanup_board(struct board_t *brd)
-{
-	int i = 0;
-
-        if(!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return;
-
-	if (brd->intr_used && brd->irq)
-		free_irq(brd->irq, brd);
-
-	tasklet_kill(&brd->helper_tasklet);
-
-	if (brd->re_map_port) {
-		release_mem_region(brd->membase + 0x200000, 0x200000);
-		iounmap(brd->re_map_port);
-		brd->re_map_port = NULL;
-	}
-
-	if (brd->re_map_membase) {
-		release_mem_region(brd->membase, 0x200000);
-		iounmap(brd->re_map_membase);
-		brd->re_map_membase = NULL;
-	}
-
-        if (brd->msgbuf_head) {
-                unsigned long flags;
-
-                DGAP_LOCK(dgap_global_lock, flags);
-                brd->msgbuf = NULL;
-                printk("%s", brd->msgbuf_head);
-                kfree(brd->msgbuf_head);
-                brd->msgbuf_head = NULL;
-                DGAP_UNLOCK(dgap_global_lock, flags);
-        }
-
-	/* Free all allocated channels structs */
-	for (i = 0; i < MAXPORTS ; i++) {
-		if (brd->channels[i]) {
-			kfree(brd->channels[i]);
-			brd->channels[i] = NULL;
-		}
-	}
-
-	kfree(brd->flipbuf);
-	kfree(brd->flipflagbuf);
-
-	dgap_Board[brd->boardnum] = NULL;
-
-        kfree(brd);
-}
-
-
-/*
- * dgap_found_board()
- *
- * A board has been found, init it.
- */
-static int dgap_found_board(struct pci_dev *pdev, int id)
-{
-	struct board_t *brd;
-	unsigned int pci_irq;
-	int i = 0;
-	unsigned long flags;
-
-	/* get the board structure and prep it */
-	brd = dgap_Board[dgap_NumBoards] =
-	(struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
-	if (!brd) {
-		APR(("memory allocation for board structure failed\n"));
-		return(-ENOMEM);
-	}
-
-	/* make a temporary message buffer for the boot messages */
-	brd->msgbuf = brd->msgbuf_head =
-		(char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
-	if(!brd->msgbuf) {
-		kfree(brd);
-		APR(("memory allocation for board msgbuf failed\n"));
-		return(-ENOMEM);
-	}
-
-	/* store the info for the board we've found */
-	brd->magic = DGAP_BOARD_MAGIC;
-	brd->boardnum = dgap_NumBoards;
-	brd->firstminor = 0;
-	brd->vendor = dgap_pci_tbl[id].vendor;
-	brd->device = dgap_pci_tbl[id].device;
-	brd->pdev = pdev;
-	brd->pci_bus = pdev->bus->number;
-	brd->pci_slot = PCI_SLOT(pdev->devfn);
-	brd->name = dgap_Ids[id].name;
-	brd->maxports = dgap_Ids[id].maxports;
-	brd->type = dgap_Ids[id].config_type;
-	brd->dpatype = dgap_Ids[id].dpatype;
-	brd->dpastatus = BD_NOFEP;
-	init_waitqueue_head(&brd->state_wait);
-
-	DGAP_SPINLOCK_INIT(brd->bd_lock);
-
-	brd->state		= BOARD_FOUND;
-	brd->runwait		= 0;
-	brd->inhibit_poller	= FALSE;
-	brd->wait_for_bios	= 0;
-	brd->wait_for_fep	= 0;
-
-	for (i = 0; i < MAXPORTS; i++) {
-		brd->channels[i] = NULL;
-	}
-
-	/* store which card & revision we have */
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
-
-	pci_irq = pdev->irq;
-	brd->irq = pci_irq;
-
-	/* get the PCI Base Address Registers */
-
-	/* Xr Jupiter and EPC use BAR 2 */
-	if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
-		brd->membase     = pci_resource_start(pdev, 2);
-		brd->membase_end = pci_resource_end(pdev, 2);
-	}
-	/* Everyone else uses BAR 0 */
-	else {
-		brd->membase     = pci_resource_start(pdev, 0);
-		brd->membase_end = pci_resource_end(pdev, 0);
-	}
-
-	if (!brd->membase) {
-		APR(("card has no PCI IO resources, failing board.\n"));
-		return -ENODEV;
-	}
-
-	if (brd->membase & 1)
-		brd->membase &= ~3;
-	else
-		brd->membase &= ~15;
-
-	/*
-	 * On the PCI boards, there is no IO space allocated
-	 * The I/O registers will be in the first 3 bytes of the
-	 * upper 2MB of the 4MB memory space.  The board memory
-	 * will be mapped into the low 2MB of the 4MB memory space
-	 */
-	brd->port = brd->membase + PCI_IO_OFFSET;
-	brd->port_end = brd->port + PCI_IO_SIZE;
-
-
-	/*
-	 * Special initialization for non-PLX boards
-	 */
-	if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
-		unsigned short cmd;
-
-		pci_write_config_byte(pdev, 0x40, 0);
-		pci_write_config_byte(pdev, 0x46, 0);
-
-		/* Limit burst length to 2 doubleword transactions */ 
-		pci_write_config_byte(pdev, 0x42, 1);
-
-		/*
-		 * Enable IO and mem if not already done.
-		 * This was needed for support on Itanium.
-		 */
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-	}
-
-	/* init our poll helper tasklet */
-	tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
-
-	 /* Log the information about the board */
-	dgap_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n",
-		dgap_NumBoards, brd->name, brd->rev, brd->irq);
-
-	DPR_INIT(("dgap_scan(%d) - printing out the msgbuf\n", i));
-	DGAP_LOCK(dgap_global_lock, flags);
-	brd->msgbuf = NULL;
-	printk("%s", brd->msgbuf_head);
-	kfree(brd->msgbuf_head);
-	brd->msgbuf_head = NULL;
-	DGAP_UNLOCK(dgap_global_lock, flags);
-
-	i = dgap_do_remap(brd);
-	if (i)
-		brd->state = BOARD_FAILED;
-	else
-		brd->state = NEED_RESET;
-
-        return(0);
-}
-
-
-int dgap_finalize_board_init(struct board_t *brd) {
-
-        int rc;
-
-        DPR_INIT(("dgap_finalize_board_init() - start\n"));
-
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return(-ENODEV);
-
-        DPR_INIT(("dgap_finalize_board_init() - start #2\n"));
-
-	brd->use_interrupts = dgap_config_get_useintr(brd);
-
-	/*
-	 * Set up our interrupt handler if we are set to do interrupts.
-	 */
-	if (brd->use_interrupts && brd->irq) {
-
-		rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
-
-		if (rc) {
-			dgap_mbuf(brd, DRVSTR": Failed to hook IRQ %d. Board will work in poll mode.\n",
-                                  brd->irq);
-			brd->intr_used = 0;
-		}
-		else
-			brd->intr_used = 1;
-	} else {
-		brd->intr_used = 0;
-	}
-
-	return(0);
-}
-
-
-/*
- * Remap PCI memory.
- */
-static int dgap_do_remap(struct board_t *brd)
-{
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	if (!request_mem_region(brd->membase, 0x200000, "dgap")) {
-		APR(("dgap: mem_region %lx already in use.\n", brd->membase));
-		return -ENOMEM;
-        }
-
-	if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
-		APR(("dgap: mem_region IO %lx already in use.\n",
-			brd->membase + PCI_IO_OFFSET));
-		release_mem_region(brd->membase, 0x200000);
-		return -ENOMEM;
-        }
-
-	brd->re_map_membase = ioremap(brd->membase, 0x200000);
-	if (!brd->re_map_membase) {
-		APR(("dgap: ioremap mem %lx cannot be mapped.\n", brd->membase));
-		release_mem_region(brd->membase, 0x200000);
-		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-		return -ENOMEM;
-	}
-
-	brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
-	if (!brd->re_map_port) {
-		release_mem_region(brd->membase, 0x200000);
-		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-		iounmap(brd->re_map_membase);
-		APR(("dgap: ioremap IO mem %lx cannot be mapped.\n",
-			brd->membase + PCI_IO_OFFSET));
-		return -ENOMEM;
-	}
-
-	DPR_INIT(("remapped io: 0x%p  remapped mem: 0x%p\n",
-		brd->re_map_port, brd->re_map_membase));
-	return 0;
-}
-
-
-/*****************************************************************************
-*
-* Function:
-*                                       
-*    dgap_poll_handler
-*
-* Author:
-*
-*    Scott H Kilau
-*       
-* Parameters:
-*
-*    dummy -- ignored                    
-*
-* Return Values:
-*
-*    none
-*
-* Description:   
-*                                       
-*    As each timer expires, it determines (a) whether the "transmit"
-*    waiter needs to be woken up, and (b) whether the poller needs to
-*    be rescheduled.
-*
-******************************************************************************/
-
-static void dgap_poll_handler(ulong dummy)
-{
-	int i;
-        struct board_t *brd;
-        unsigned long lock_flags;
-        unsigned long lock_flags2;
-	ulong new_time;
-
-	dgap_poll_counter++;
-
-
-	/*
-	 * If driver needs the config file still,
-	 * keep trying to wake up the downloader to
-	 * send us the file.
-	 */
-        if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-		goto schedule_poller;
-        }
-	/*
-	 * Do not start the board state machine until
-	 * driver tells us its up and running, and has
-	 * everything it needs.
-	 */
-	else if (dgap_driver_state != DRIVER_READY) {
-		goto schedule_poller;
-	}
-
-	/*
-	 * If we have just 1 board, or the system is not SMP,
-	 * then use the typical old style poller.
-	 * Otherwise, use our new tasklet based poller, which should
-	 * speed things up for multiple boards.
-	 */
-	if ( (dgap_NumBoards == 1) || (num_online_cpus() <= 1) ) {
-		for (i = 0; i < dgap_NumBoards; i++) {
-
-			brd = dgap_Board[i];
-
-			if (brd->state == BOARD_FAILED) {
-				continue;
-			}
-			if (!brd->intr_running) {
-				/* Call the real board poller directly */
-				dgap_poll_tasklet((unsigned long) brd);
-			}
-		}
-	}
-	else {
-		/* Go thru each board, kicking off a tasklet for each if needed */
-		for (i = 0; i < dgap_NumBoards; i++) {
-			brd = dgap_Board[i];
-
-			/*
-			 * Attempt to grab the board lock.
-			 *
-			 * If we can't get it, no big deal, the next poll will get it.
-			 * Basically, I just really don't want to spin in here, because I want
-			 * to kick off my tasklets as fast as I can, and then get out the poller.
-			 */
-			if (!spin_trylock(&brd->bd_lock)) {
-				continue;
-			}
-
-			/* If board is in a failed state, don't bother scheduling a tasklet */
-			if (brd->state == BOARD_FAILED) {
-				spin_unlock(&brd->bd_lock);
-				continue;
-			}
-
-			/* Schedule a poll helper task */
-			if (!brd->intr_running) {
-				tasklet_schedule(&brd->helper_tasklet);
-			}
-
-			/*
-			 * Can't do DGAP_UNLOCK here, as we don't have
-			 * lock_flags because we did a trylock above.
-			 */
-			spin_unlock(&brd->bd_lock);
-		}
-	}
-
-schedule_poller:
-
-	/*
-	 * Schedule ourself back at the nominal wakeup interval.
-	 */
-	DGAP_LOCK(dgap_poll_lock, lock_flags );
-	dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
-
-	new_time = dgap_poll_time - jiffies;
-
-	if ((ulong) new_time >= 2 * dgap_poll_tick) {
-		dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
-	}
-
-	dgap_poll_timer.function = dgap_poll_handler;
-	dgap_poll_timer.data = 0;
-	dgap_poll_timer.expires = dgap_poll_time;
-	DGAP_UNLOCK(dgap_poll_lock, lock_flags );
-
-	if (!dgap_poll_stop)
-		add_timer(&dgap_poll_timer);
-}
-
-
-
-
-/*
- * dgap_intr()
- *
- * Driver interrupt handler.
- */
-static irqreturn_t dgap_intr(int irq, void *voidbrd)
-{
-	struct board_t *brd = (struct board_t *) voidbrd;
-
-	if (!brd) {
-		APR(("Received interrupt (%d) with null board associated\n", irq));
-		return IRQ_NONE;
-	}
-
-	/*
-	 * Check to make sure its for us.
-	 */
-	if (brd->magic != DGAP_BOARD_MAGIC) {
-		APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
-		return IRQ_NONE;
-	}
-
-	brd->intr_count++;
-
-	/*
-	 * Schedule tasklet to run at a better time.
-	 */
-	tasklet_schedule(&brd->helper_tasklet);
-	return IRQ_HANDLED;
-}
-
-
-/*
- * dgap_init_globals()
- *
- * This is where we initialize the globals from the static insmod
- * configuration variables.  These are declared near the head of
- * this file.
- */
-static void dgap_init_globals(void)
-{
-	int i = 0;
-
-	dgap_rawreadok		= rawreadok;
-        dgap_trcbuf_size	= trcbuf_size;
-	dgap_debug		= debug;
-
-	for (i = 0; i < MAXBOARDS; i++) {
-		dgap_Board[i] = NULL;
-	}
-
-	init_timer( &dgap_poll_timer ); 
-
-	init_waitqueue_head(&dgap_dl_wait);
-	dgap_dl_action = 0;
-}
-
-
-/************************************************************************
- *
- * Utility functions
- *
- ************************************************************************/
-
-
-/*
- * dgap_mbuf()
- *
- * Used to print to the message buffer during board init.
- */
-static void dgap_mbuf(struct board_t *brd, const char *fmt, ...) {
-	va_list		ap;
-	char		buf[1024];
-	int		i;
-	unsigned long	flags;
-	size_t		length;
-
-	DGAP_LOCK(dgap_global_lock, flags);
-
-	/* Format buf using fmt and arguments contained in ap. */
-	va_start(ap, fmt);
-	i = vsnprintf(buf, sizeof(buf), fmt,  ap);
-	va_end(ap);
-
-	DPR((buf));
-
-	if (!brd || !brd->msgbuf) {
-		printk("%s", buf);
-		DGAP_UNLOCK(dgap_global_lock, flags);
-		return;
-	}
-
-	length = strlen(buf) + 1;
-	if (brd->msgbuf - brd->msgbuf_head < length)
-		length = brd->msgbuf - brd->msgbuf_head;
-	memcpy(brd->msgbuf, buf, length);
-	brd->msgbuf += length;
-
-	DGAP_UNLOCK(dgap_global_lock, flags);
-}
-
-
-/*
- * dgap_ms_sleep()
- *
- * Put the driver to sleep for x ms's
- *
- * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
- */
-int dgap_ms_sleep(ulong ms)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((ms * HZ) / 1000);
-	return (signal_pending(current));
-}
-
-
-
-/*
- *      dgap_ioctl_name() : Returns a text version of each ioctl value.
- */
-char *dgap_ioctl_name(int cmd)
-{
-	switch(cmd) {
-
-	case TCGETA:		return("TCGETA");
-	case TCGETS:		return("TCGETS");
-	case TCSETA:		return("TCSETA");
-	case TCSETS:		return("TCSETS");
-	case TCSETAW:		return("TCSETAW");
-	case TCSETSW:		return("TCSETSW");
-	case TCSETAF:		return("TCSETAF");
-	case TCSETSF:		return("TCSETSF");
-	case TCSBRK:		return("TCSBRK");
-	case TCXONC:		return("TCXONC");
-	case TCFLSH:		return("TCFLSH");
-	case TIOCGSID:		return("TIOCGSID");
-
-	case TIOCGETD:		return("TIOCGETD");
-	case TIOCSETD:		return("TIOCSETD");
-	case TIOCGWINSZ:	return("TIOCGWINSZ");
-	case TIOCSWINSZ:	return("TIOCSWINSZ");
-
-	case TIOCMGET:		return("TIOCMGET");
-	case TIOCMSET:		return("TIOCMSET");
-	case TIOCMBIS:		return("TIOCMBIS");
-	case TIOCMBIC:		return("TIOCMBIC");
-
-	/* from digi.h */
-	case DIGI_SETA:		return("DIGI_SETA");
-	case DIGI_SETAW:	return("DIGI_SETAW");
-	case DIGI_SETAF:	return("DIGI_SETAF");
-	case DIGI_SETFLOW:	return("DIGI_SETFLOW");
-	case DIGI_SETAFLOW:	return("DIGI_SETAFLOW");
-	case DIGI_GETFLOW:	return("DIGI_GETFLOW");
-	case DIGI_GETAFLOW:	return("DIGI_GETAFLOW");
-	case DIGI_GETA:		return("DIGI_GETA");
-	case DIGI_GEDELAY:	return("DIGI_GEDELAY");
-	case DIGI_SEDELAY:	return("DIGI_SEDELAY");
-	case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
-	case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
-	case TIOCMODG:		return("TIOCMODG");
-	case TIOCMODS:		return("TIOCMODS");
-	case TIOCSDTR:		return("TIOCSDTR");
-	case TIOCCDTR:		return("TIOCCDTR");
-
-	default:		return("unknown");
-	}
-}
diff --git a/drivers/staging/dgap/dgap_driver.h b/drivers/staging/dgap/dgap_driver.h
deleted file mode 100644
index 2f7a55a7e40d..000000000000
--- a/drivers/staging/dgap/dgap_driver.h
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * Driver includes
- *
- *************************************************************************/
-
-#ifndef __DGAP_DRIVER_H
-#define __DGAP_DRIVER_H
-
-#include <linux/version.h>	/* To get the current Linux version */
-#include <linux/types.h>        /* To pick up the varions Linux types */
-#include <linux/tty.h>          /* To pick up the various tty structs/defines */
-#include <linux/interrupt.h>    /* For irqreturn_t type */
-
-#include "dgap_types.h"         /* Additional types needed by the Digi header files */
-#include "digi.h"               /* Digi specific ioctl header */
-#include "dgap_kcompat.h"       /* Kernel 2.4/2.6 compat includes */
-#include "dgap_sysfs.h"		/* Support for SYSFS */
-
-/*************************************************************************
- *
- * Driver defines
- *
- *************************************************************************/
-
-/*
- * Driver identification, error and debugging statments
- *
- * In theory, you can change all occurrences of "digi" in the next
- * three lines, and the driver printk's will all automagically change.
- *
- * APR((fmt, args, ...));	Always prints message
- * DPR((fmt, args, ...));	Only prints if DGAP_TRACER is defined at
- *				  compile time and dgap_debug!=0
- */
-#define	DG_NAME		"dgap-1.3-16"
-#define	DG_PART		"40002347_C"
-
-#define	PROCSTR		"dgap"			/* /proc entries	 */
-#define	DEVSTR		"/dev/dg/dgap"		/* /dev entries		 */
-#define	DRVSTR		"dgap"			/* Driver name string 
-						 * displayed by APR	 */
-#define	APR(args)	do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
-			   } while (0)
-#define	RAPR(args)	do { PRINTF_TO_KMEM(args); printk args; } while (0)
-
-#define TRC_TO_CONSOLE 1
-
-/*
- * Debugging levels can be set using debug insmod variable
- * They can also be compiled out completely.
- */
-
-#define	DBG_INIT		(dgap_debug & 0x01)
-#define	DBG_BASIC		(dgap_debug & 0x02)
-#define	DBG_CORE		(dgap_debug & 0x04)
-
-#define	DBG_OPEN		(dgap_debug & 0x08)
-#define	DBG_CLOSE		(dgap_debug & 0x10)
-#define	DBG_READ		(dgap_debug & 0x20)
-#define	DBG_WRITE		(dgap_debug & 0x40)
-
-#define	DBG_IOCTL		(dgap_debug & 0x80)
-
-#define	DBG_PROC		(dgap_debug & 0x100)
-#define	DBG_PARAM		(dgap_debug & 0x200)
-#define	DBG_PSCAN		(dgap_debug & 0x400)
-#define	DBG_EVENT		(dgap_debug & 0x800)
-
-#define	DBG_DRAIN		(dgap_debug & 0x1000)
-#define	DBG_CARR		(dgap_debug & 0x2000)
-
-#define	DBG_MGMT		(dgap_debug & 0x4000)
-
-
-#if defined(DGAP_TRACER)
-
-# if defined(TRC_TO_KMEM)
-/* Choose one: */
-#  define TRC_ON_OVERFLOW_WRAP_AROUND
-#  undef  TRC_ON_OVERFLOW_SHIFT_BUFFER
-# endif //TRC_TO_KMEM
-
-# define TRC_MAXMSG		1024
-# define TRC_OVERFLOW		"(OVERFLOW)"
-# define TRC_DTRC		"/usr/bin/dtrc"
-
-#if defined TRC_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
-#else //!defined TRACE_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args)
-#endif
-
-#if defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args) dgap_tracef args 
-#else //!defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args)
-#endif
-
-#define	TRC(args)	{ PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
-
-# define DPR_INIT(ARGS)		if (DBG_INIT) TRC(ARGS)
-# define DPR_BASIC(ARGS)	if (DBG_BASIC) TRC(ARGS)
-# define DPR_CORE(ARGS)		if (DBG_CORE) TRC(ARGS)
-# define DPR_OPEN(ARGS)		if (DBG_OPEN)  TRC(ARGS)
-# define DPR_CLOSE(ARGS)	if (DBG_CLOSE)  TRC(ARGS)
-# define DPR_READ(ARGS)		if (DBG_READ)  TRC(ARGS)
-# define DPR_WRITE(ARGS)	if (DBG_WRITE) TRC(ARGS)
-# define DPR_IOCTL(ARGS)	if (DBG_IOCTL) TRC(ARGS)
-# define DPR_PROC(ARGS)		if (DBG_PROC)  TRC(ARGS)
-# define DPR_PARAM(ARGS)	if (DBG_PARAM)  TRC(ARGS)
-# define DPR_PSCAN(ARGS)	if (DBG_PSCAN)  TRC(ARGS)
-# define DPR_EVENT(ARGS)	if (DBG_EVENT)  TRC(ARGS)
-# define DPR_DRAIN(ARGS)	if (DBG_DRAIN)  TRC(ARGS)
-# define DPR_CARR(ARGS)		if (DBG_CARR)  TRC(ARGS)
-# define DPR_MGMT(ARGS)		if (DBG_MGMT)  TRC(ARGS)
-
-# define DPR(ARGS)		if (dgap_debug) TRC(ARGS)
-# define P(X)			dgap_tracef(#X "=%p\n", X)
-# define X(X)			dgap_tracef(#X "=%x\n", X)
-
-#else//!defined DGAP_TRACER
-
-#define PRINTF_TO_KMEM(args)
-# define TRC(ARGS)
-# define DPR_INIT(ARGS)
-# define DPR_BASIC(ARGS)
-# define DPR_CORE(ARGS)
-# define DPR_OPEN(ARGS)
-# define DPR_CLOSE(ARGS)
-# define DPR_READ(ARGS)
-# define DPR_WRITE(ARGS)
-# define DPR_IOCTL(ARGS)
-# define DPR_PROC(ARGS)
-# define DPR_PARAM(ARGS)
-# define DPR_PSCAN(ARGS)
-# define DPR_EVENT(ARGS)
-# define DPR_DRAIN(ARGS)
-# define DPR_CARR(ARGS)
-# define DPR_MGMT(ARGS)
-
-# define DPR(args)
-
-#endif//DGAP_TRACER
-
-/* Number of boards we support at once. */
-#define	MAXBOARDS	32
-#define	MAXPORTS	224
-#define MAXTTYNAMELEN	200
-
-/* Our 3 magic numbers for our board, channel and unit structs */
-#define DGAP_BOARD_MAGIC	0x5c6df104
-#define DGAP_CHANNEL_MAGIC	0x6c6df104
-#define DGAP_UNIT_MAGIC		0x7c6df104
-
-/* Serial port types */
-#define DGAP_SERIAL		0
-#define DGAP_PRINT		1
-
-#define	SERIAL_TYPE_NORMAL	1
-
-/* 4 extra for alignment play space */
-#define WRITEBUFLEN		((4096) + 4)
-#define MYFLIPLEN		N_TTY_BUF_SIZE
-
-#define SBREAK_TIME 0x25
-#define U2BSIZE 0x400
-
-#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
-
-/*
- * Our major for the mgmt devices.
- *
- * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
- * 22 has now become obsolete now that the "cu" devices have 
- * been removed from 2.6.
- * Also, this *IS* the epca driver, just PCI only now.
- */
-#ifndef DIGI_DGAP_MAJOR
-# define DIGI_DGAP_MAJOR         22
-#endif
-
-/*
- * The parameters we use to define the periods of the moving averages.
- */
-#define		MA_PERIOD	(HZ / 10)
-#define		SMA_DUR		(1 * HZ)
-#define		EMA_DUR		(1 * HZ)
-#define		SMA_NPERIODS	(SMA_DUR / MA_PERIOD)
-#define		EMA_NPERIODS	(EMA_DUR / MA_PERIOD)
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.  This is the same structure that is defined
- * as the default in tty_io.c with the same settings overriden as in serial.c
- *
- * In short, this should match the internal serial ports' defaults.
- */
-#define	DEFAULT_IFLAGS	(ICRNL | IXON)
-#define	DEFAULT_OFLAGS	(OPOST | ONLCR)
-#define	DEFAULT_CFLAGS	(B9600 | CS8 | CREAD | HUPCL | CLOCAL)
-#define	DEFAULT_LFLAGS	(ISIG | ICANON | ECHO | ECHOE | ECHOK | \
-			ECHOCTL | ECHOKE | IEXTEN)
-
-#ifndef _POSIX_VDISABLE
-#define   _POSIX_VDISABLE '\0'
-#endif
-
-#define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
-#define SNIFF_MASK	(SNIFF_MAX - 1)	/* Sniff wrap mask */
-
-#define VPDSIZE (512)
-
-/*
- * Lock function/defines.
- * Makes spotting lock/unlock locations easier.
- */
-# define DGAP_SPINLOCK_INIT(x)		spin_lock_init(&(x))
-# define DGAP_LOCK(x,y)			spin_lock_irqsave(&(x), y)
-# define DGAP_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
-# define DGAP_TRYLOCK(x,y)		spin_trylock(&(x))
-
-/*
- * All the possible states the driver can be while being loaded.
- */
-enum {
-	DRIVER_INITIALIZED = 0,
-	DRIVER_NEED_CONFIG_LOAD,
-	DRIVER_REQUESTED_CONFIG,
-	DRIVER_READY
-};
-
-/*
- * All the possible states the board can be while booting up.
- */
-enum {
-	BOARD_FAILED = 0,
-	CONFIG_NOT_FOUND,
-	BOARD_FOUND,
-	NEED_RESET,
-	FINISHED_RESET,
-	NEED_CONFIG,
-	FINISHED_CONFIG,
-	NEED_DEVICE_CREATION,
-	REQUESTED_DEVICE_CREATION,
-	FINISHED_DEVICE_CREATION,
-	NEED_BIOS_LOAD,
-	REQUESTED_BIOS,
-	WAIT_BIOS_LOAD,
-	FINISHED_BIOS_LOAD,
-	NEED_FEP_LOAD,
-	REQUESTED_FEP,
-	WAIT_FEP_LOAD,
-	FINISHED_FEP_LOAD,
-	NEED_PROC_CREATION,
-	FINISHED_PROC_CREATION,
-	BOARD_READY
-};
-
-/*
- * All the possible states that a requested concentrator image can be in.
- */
-enum {
-	NO_PENDING_CONCENTRATOR_REQUESTS = 0,
-	NEED_CONCENTRATOR,
-	REQUESTED_CONCENTRATOR
-};
-
-extern char *dgap_state_text[];
-extern char *dgap_driver_state_text[];
-
-
-/* 
- * Modem line constants are defined as macros because DSR and
- * DCD are swapable using the ditty altpin option.
- */
-#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
-#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
-#define D_RTS(ch)       DM_RTS          /* Request to send      */
-#define D_CTS(ch)       DM_CTS          /* Clear to send        */
-#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.
- */
-struct macounter
-{
-	u32		cnt;	/* Total count */
-	ulong		accum;	/* Acuumulator per period */
-	ulong		sma;	/* Simple moving average */
-	ulong		ema;	/* Exponential moving average */
-};
-
-
-/************************************************************************ 
- * Device flag definitions for bd_flags.
- ************************************************************************/
-#define	BD_FEP5PLUS	0x0001          /* Supports FEP5 Plus commands */
-#define BD_HAS_VPD	0x0002		/* Board has VPD info available */
-
-
-/*
- *	Per-board information
- */
-struct board_t
-{
-	int		magic;		/* Board Magic number.  */
-	int		boardnum;	/* Board number: 0-3 */
-	int		firstminor;	/* First minor, e.g. 0, 30, 60 */
-
-	int		type;		/* Type of board */
-	char		*name;		/* Product Name */
-	struct pci_dev	*pdev;		/* Pointer to the pci_dev struct */ 
-	u16		vendor;		/* PCI vendor ID */
-	u16		device;		/* PCI device ID */
-	u16		subvendor;	/* PCI subsystem vendor ID */
-	u16		subdevice;	/* PCI subsystem device ID */
-	uchar		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 */
-	u32		bd_flags;	/* Board flags */
-
-	spinlock_t	bd_lock;	/* Used to protect board */
-
-	u32		state;		/* State of card. */
-	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
-
-	struct		tasklet_struct helper_tasklet; /* Poll helper tasklet */
-
-	u32		wait_for_bios;
-	u32		wait_for_fep;
-
-	struct cnode *  bd_config;	/* Config of board */
-
-	u16		nasync;		/* Number of ports on card */
-
-	u32		use_interrupts;	/* Should we be interrupt driven? */
-	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 */
-
-	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 */
-
-	uchar		runwait;	/* # Processes waiting for FEP  */
-	uchar		inhibit_poller; /* Tells  the poller to leave us alone */
-
-	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
-
-	struct tty_driver	*SerialDriver;
-	char		SerialName[200];
-	struct tty_driver	*PrintDriver;
-	char		PrintName[200];
-
-	u32		dgap_Major_Serial_Registered;
-	u32		dgap_Major_TransparentPrint_Registered;
-
-	u32		dgap_Serial_Major;
-	u32		dgap_TransparentPrint_Major;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-	u32		TtyRefCnt;
-#endif
-
-	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 */
-
-	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 */
-	/*
-	 *	Mgmt data.
-	 */
-        char		*msgbuf_head;
-        char		*msgbuf;
-};
-
-
-
-/************************************************************************ 
- * Unit flag definitions for un_flags.
- ************************************************************************/
-#define UN_ISOPEN	0x0001		/* Device is open		*/
-#define UN_CLOSING	0x0002		/* Line is being closed		*/
-#define UN_IMM		0x0004		/* Service immediately		*/
-#define UN_BUSY		0x0008		/* Some work this channel	*/
-#define UN_BREAKI	0x0010		/* Input break received		*/
-#define UN_PWAIT	0x0020		/* Printer waiting for terminal	*/
-#define UN_TIME		0x0040		/* Waiting on time		*/
-#define UN_EMPTY	0x0080		/* Waiting output queue empty	*/
-#define UN_LOW		0x0100		/* Waiting output low water mark*/
-#define UN_EXCL_OPEN	0x0200		/* Open for exclusive use	*/
-#define UN_WOPEN	0x0400		/* Device waiting for open	*/
-#define UN_WIOCTL	0x0800		/* Device waiting for open	*/
-#define UN_HANGUP	0x8000		/* Carrier lost			*/
-
-struct device;
-
-/************************************************************************
- * Structure for terminal or printer unit. 
- ************************************************************************/
-struct un_t {
-	int	magic;		/* Unit Magic Number.			*/
-	struct	channel_t *un_ch;
-	u32	un_time;
-	u32	un_type;
-	u32	un_open_count;	/* Counter of opens to port		*/
-	struct tty_struct *un_tty;/* Pointer to unit tty structure	*/
-	u32	un_flags;	/* Unit flags				*/
-	wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
-	u32	un_dev;		/* Minor device number			*/
-	tcflag_t un_oflag;	/* oflags being done on board		*/
-	tcflag_t un_lflag;	/* lflags being done on board		*/
-	struct device *un_sysfs;
-};
-
-
-/************************************************************************ 
- * Device flag definitions for ch_flags.
- ************************************************************************/
-#define CH_PRON         0x0001          /* Printer on string                */
-#define CH_OUT          0x0002          /* Dial-out device open             */
-#define CH_STOP         0x0004          /* Output is stopped                */
-#define CH_STOPI        0x0008          /* Input is stopped                 */
-#define CH_CD           0x0010          /* Carrier is present               */
-#define CH_FCAR         0x0020          /* Carrier forced on                */
-
-#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
-#define CH_WLOW         0x0100          /* Term waiting low event           */
-#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
-#define CH_RENABLE      0x0400          /* Buffer just emptied          */
-#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
-#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
-#define CH_BAUD0	0x2000		/* Used for checking B0 transitions */
-#define CH_HANGUP       0x8000		/* Hangup received                  */
-
-/*
- * Definitions for ch_sniff_flags
- */
-#define SNIFF_OPEN	0x1
-#define SNIFF_WAIT_DATA	0x2
-#define SNIFF_WAIT_SPACE 0x4
-
-
-/************************************************************************ 
- * Channel information structure.
- ************************************************************************/
-struct channel_t {
-	int magic;			/* Channel Magic Number		*/
-	struct bs_t	*ch_bs;		/* Base structure pointer       */
-	struct cm_t	*ch_cm;		/* Command queue pointer        */
-	struct board_t *ch_bd;		/* Board structure pointer      */
-	unsigned char *ch_vaddr;	/* FEP memory origin            */
-	unsigned char *ch_taddr;	/* Write buffer origin          */
-	unsigned char *ch_raddr;	/* Read buffer origin           */
-	struct digi_t  ch_digi;		/* Transparent Print structure  */
-	struct un_t ch_tun;		/* Terminal unit info           */
-	struct un_t ch_pun;		/* Printer unit info            */
-
-	spinlock_t	ch_lock;	/* provide for serialization */
-	wait_queue_head_t ch_flags_wait;
-
-	u32	pscan_state;
-	uchar	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_cpstime;		/* Time for CPS calculations    */
-
-	tcflag_t ch_c_iflag;		/* channel iflags               */
-	tcflag_t ch_c_cflag;		/* channel cflags               */
-	tcflag_t ch_c_oflag;		/* channel oflags               */
-	tcflag_t ch_c_lflag;		/* channel lflags               */
-
-	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 */
-	u16  ch_tstart;			/* Transmit buffer start        */
-	u16  ch_tsize;			/* Transmit buffer size         */
-	u16  ch_rstart;			/* Receive buffer start         */
-	u16  ch_rsize;			/* Receive buffer size          */
-	u16  ch_rdelay;			/* Receive delay time           */
-
-	u16	ch_tlw;			/* Our currently set low water mark */
-
-	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     */
-	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	*/
-	ulong	ch_err_break;		/* Count of breaks on channel	*/
-	ulong	ch_err_overrun;		/* Count of overruns on channel	*/
-
-	uint ch_sniff_in;
-	uint ch_sniff_out;
-	char *ch_sniff_buf;		/* Sniff buffer for proc */
-	ulong ch_sniff_flags;		/* Channel flags                */
-	wait_queue_head_t ch_sniff_wait;
-};
-
-
-/*************************************************************************
- *
- * Prototypes for non-static functions used in more than one module
- *
- *************************************************************************/
-
-extern int		dgap_ms_sleep(ulong ms);
-extern char		*dgap_ioctl_name(int cmd);
-extern void		dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
-extern void		dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
-extern void		dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
-extern void		dgap_do_config_load(uchar __user *uaddr, int len);
-extern int		dgap_after_config_loaded(void);
-extern int		dgap_finalize_board_init(struct board_t *brd);
-
-/*
- * Our Global Variables.
- */
-extern int		dgap_driver_state;	/* The state of the driver	*/
-extern int		dgap_debug;		/* Debug variable		*/
-extern int		dgap_rawreadok;		/* Set if user wants rawreads	*/
-extern int		dgap_poll_tick;		/* Poll interval - 20 ms	*/
-extern spinlock_t	dgap_global_lock;	/* Driver global spinlock	*/
-extern uint		dgap_NumBoards;		/* Total number of boards	*/
-extern struct board_t	*dgap_Board[MAXBOARDS];	/* Array of board structs	*/
-extern ulong		dgap_poll_counter;	/* Times the poller has run	*/
-extern char		*dgap_config_buf;	/* The config file buffer	*/
-extern spinlock_t	dgap_dl_lock;		/* Downloader spinlock		*/
-extern wait_queue_head_t dgap_dl_wait;		/* Wait queue for downloader	*/
-extern int		dgap_dl_action;		/* Action flag for downloader	*/
-extern int		dgap_registerttyswithsysfs; /* Should we register the	*/
-						    /* ttys with sysfs or not	*/
-
-/*
- * Global functions declared in dgap_fep5.c, but must be hidden from
- * user space programs.
- */
-extern void	dgap_poll_tasklet(unsigned long data); 
-extern void	dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
-extern void	dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
-extern void	dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
-extern int	dgap_param(struct tty_struct *tty);
-extern void	dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
-extern uint	dgap_get_custom_baud(struct channel_t *ch);
-extern void	dgap_firmware_reset_port(struct channel_t *ch);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_fep5.c b/drivers/staging/dgap/dgap_fep5.c
deleted file mode 100644
index f75831a422e8..000000000000
--- a/drivers/staging/dgap/dgap_fep5.c
+++ /dev/null
@@ -1,1938 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- *	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.
- *
- * $Id: dgap_fep5.c,v 1.2 2011/06/21 10:35:40 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>	/* For udelay */
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>	/* For tty_schedule_flip */
-#include <linux/slab.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
-#include <linux/sched.h>
-#endif
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-
-/*
- * Our function prototypes
- */
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
-static int dgap_event(struct board_t *bd);
-
-/*
- * internal variables
- */
-static uint dgap_count = 500;
-
-
-/*
- * Loads the dgap.conf config file from the user.
- */
-void dgap_do_config_load(uchar __user *uaddr, int len)
-{
-	int orig_len = len;
-	char *to_addr;
-	uchar __user *from_addr = uaddr;
-	char buf[U2BSIZE];
-	int n;
-
-	to_addr = dgap_config_buf = kzalloc(len + 1, GFP_ATOMIC);
-	if (!dgap_config_buf) {
-		DPR_INIT(("dgap_do_config_load - unable to allocate memory for file\n"));
-		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-		return;
-	}
-
-	n = U2BSIZE;
-	while (len) {
-
-		if (n > len)
-			n = len;
-
-		if (copy_from_user((char *) &buf, from_addr, n) == -1 )
-			return;
-
-		/* Copy data from buffer to kernel memory */
-		memcpy(to_addr, buf, n);
-
-		/* increment counts */
-		len -= n;
-		to_addr += n;
-		from_addr += n;
-		n = U2BSIZE;
-	}
-
-	dgap_config_buf[orig_len] = '\0';
-
-	to_addr = dgap_config_buf;
-	dgap_parsefile(&to_addr, TRUE);
-
-	DPR_INIT(("dgap_config_load() finish\n"));
-
-	return;
-}
-
-
-int dgap_after_config_loaded(void)
-{
-	int i = 0;
-	int rc = 0;
-
-	/*
-	 * Register our ttys, now that we have the config loaded.
-	 */
-	for (i = 0; i < dgap_NumBoards; ++i) {
-
-		/*
-		 * Initialize KME waitqueues...
-		 */
-		init_waitqueue_head(&(dgap_Board[i]->kme_wait));
-
-		/*
-		 * allocate flip buffer for board.
-		 */
-		dgap_Board[i]->flipbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-		dgap_Board[i]->flipflagbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-	}
-
-	return rc;
-}
-
-
-
-/*=======================================================================
- *
- *      usertoboard - copy from user space to board space.
- *
- *=======================================================================*/
-static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user *from_addr, int len)
-{
-	char buf[U2BSIZE];
-	int n = U2BSIZE;
-
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-		return -EFAULT;
-
-	while (len) {
-		if (n > len)
-			n = len;
-
-		if (copy_from_user((char *) &buf, from_addr, n) == -1 ) {
-			return -EFAULT;
-		}
-
-		/* Copy data from buffer to card memory */
-		memcpy_toio(to_addr, buf, n);
-
-		/* increment counts */
-		len -= n;
-		to_addr += n;
-		from_addr += n;
-		n = U2BSIZE;
-	}
-	return 0;
-}
-
-
-/*
- * Copies the BIOS code from the user to the board,
- * and starts the BIOS running.
- */
-void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
-{
-	uchar *addr;
-	uint offset;
-	int i;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	DPR_INIT(("dgap_do_bios_load() start\n"));
-
-	addr = brd->re_map_membase;
-
-	/*
-	 * clear POST area
-	 */
-	for (i = 0; i < 16; i++)
-		writeb(0, addr + POSTAREA + i);
-
-	/*
-	 * Download bios
-	 */
-	offset = 0x1000;
-	if (dgap_usertoboard(brd, addr + offset, ubios, len) == -1 ) {
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		return;
-	}
-
-	writel(0x0bf00401, addr);
-	writel(0, (addr + 4));
-
-	/* Clear the reset, and change states. */
-	writeb(FEPCLR, brd->re_map_port);
-	brd->state = WAIT_BIOS_LOAD;
-}
-
-
-/*
- * Checks to see if the BIOS completed running on the card.
- */
-static void dgap_do_wait_for_bios(struct board_t *brd)
-{
-	uchar *addr;
-	u16 word;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-	word = readw(addr + POSTAREA);
-
-	/* Check to see if BIOS thinks board is good. (GD). */
-	if (word == *(u16 *) "GD") {
-		DPR_INIT(("GOT GD in memory, moving states.\n"));
-		brd->state = FINISHED_BIOS_LOAD;
-		return;
-	}
-
-	/* Give up on board after too long of time taken */
-	if (brd->wait_for_bios++ > 5000) {
-		u16 err1 = readw(addr + SEQUENCE);
-		u16 err2 = readw(addr + ERROR);
-		APR(("***WARNING*** %s failed diagnostics.  Error #(%x,%x).\n",
-			brd->name, err1, err2));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-	}
-}
-
-
-/*
- * Copies the FEP code from the user to the board,
- * and starts the FEP running.
- */
-void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len)
-{
-	uchar *addr;
-	uint offset;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-
-	DPR_INIT(("dgap_do_fep_load() for board %s : start\n", brd->name));
-
-	/*
-	 * Download FEP
-	 */
-	offset = 0x1000;
-	if (dgap_usertoboard(brd, addr + offset, ufep, len) == -1 ) {
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		return;
-	}
-
-	/*
-	 * If board is a concentrator product, we need to give
-	 * it its config string describing how the concentrators look.
-	 */
-	if ((brd->type == PCX) || (brd->type == PEPC)) {
-		uchar string[100];
-		uchar *config, *xconfig;
-		int i = 0;
-
-		xconfig = dgap_create_config_string(brd, string);
-
-		/* Write string to board memory */
-		config = addr + CONFIG;
-		for (; i < CONFIGSIZE; i++, config++, xconfig++) {
-			writeb(*xconfig, config);
-			if ((*xconfig & 0xff) == 0xff)
-				break;
-		}
-	}
-
-	writel(0xbfc01004, (addr + 0xc34));
-	writel(0x3, (addr + 0xc30));
-
-	/* change states. */
-	brd->state = WAIT_FEP_LOAD;
-
-	DPR_INIT(("dgap_do_fep_load() for board %s : finish\n", brd->name));
-
-}
-
-
-/*
- * Waits for the FEP to report thats its ready for us to use.
- */
-static void dgap_do_wait_for_fep(struct board_t *brd)
-{
-	uchar *addr;
-	u16 word;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-
-	DPR_INIT(("dgap_do_wait_for_fep() for board %s : start. addr: %p\n", brd->name, addr));
-
-	word = readw(addr + FEPSTAT);
-
-	/* Check to see if FEP is up and running now. */
-	if (word == *(u16 *) "OS") {
-		DPR_INIT(("GOT OS in memory for board %s, moving states.\n", brd->name));
-		brd->state = FINISHED_FEP_LOAD;
-
-		/*
-		 * Check to see if the board can support FEP5+ commands.
-		 */
-		word = readw(addr + FEP5_PLUS);
-		if (word == *(u16 *) "5A") {
-			DPR_INIT(("GOT 5A in memory for board %s, board supports extended FEP5 commands.\n", brd->name));
-			brd->bd_flags |= BD_FEP5PLUS;
-		}
-
-		return;
-	}
-
-	/* Give up on board after too long of time taken */
-	if (brd->wait_for_fep++ > 5000) {
-		u16 err1 = readw(addr + SEQUENCE);
-		u16 err2 = readw(addr + ERROR);
-		APR(("***WARNING*** FEPOS for %s not functioning.  Error #(%x,%x).\n",
-			brd->name, err1, err2));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-	}
-
-	DPR_INIT(("dgap_do_wait_for_fep() for board %s : finish\n", brd->name));
-}
-
-
-/*
- * Physically forces the FEP5 card to reset itself.
- */
-static void dgap_do_reset_board(struct board_t *brd)
-{
-	uchar check;
-	u32 check1;
-	u32 check2;
-	int i = 0;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase || !brd->re_map_port) {
-		DPR_INIT(("dgap_do_reset_board() start. bad values. brd: %p mem: %p io: %p\n",
-			brd, brd ? brd->re_map_membase : 0, brd ? brd->re_map_port : 0));
-		return;
-	}
-
-	DPR_INIT(("dgap_do_reset_board() start. io: %p\n", brd->re_map_port));
-
-	/* FEPRST does not vary among supported boards */
-	writeb(FEPRST, brd->re_map_port);
-
-	for (i = 0; i <= 1000; i++) {
-		check = readb(brd->re_map_port) & 0xe;
-		if (check == FEPRST)
-			break;
-		udelay(10);
-
-	}
-	if (i > 1000) {
-		APR(("*** WARNING *** Board not resetting...  Failing board.\n"));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		goto failed;
-	}
-
-	/*
-	 * Make sure there really is memory out there.
-	 */
-	writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
-	writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
-	check1 = readl(brd->re_map_membase + LOWMEM);
-	check2 = readl(brd->re_map_membase + HIGHMEM);
-
-	if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
-		APR(("*** Warning *** No memory at %p for board.\n", brd->re_map_membase));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		goto failed;
-	}
-
-	if (brd->state != BOARD_FAILED)
-		brd->state = FINISHED_RESET;
-
-failed:
-	DPR_INIT(("dgap_do_reset_board() finish\n"));
-}
-
-
-/*
- * Sends a concentrator image into the FEP5 board.
- */
-void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
-{
-	char *vaddr;
-	u16 offset = 0;
-	struct downld_t *to_dp;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	vaddr = brd->re_map_membase;
-
-	offset = readw((u16 *) (vaddr + DOWNREQ));
-	to_dp = (struct downld_t *) (vaddr + (int) offset);
-
-	/*
-	 * The image was already read into kernel space,
-	 * we do NOT need a user space read here
-	 */
-	memcpy_toio((char *) to_dp, uaddr, sizeof(struct downld_t));
-
-	/* Tell card we have data for it */
-	writew(0, vaddr + (DOWNREQ));
-
-	brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
-}
-
-
-#define EXPANSION_ROM_SIZE	(64 * 1024)
-#define FEP5_ROM_MAGIC		(0xFEFFFFFF)
-
-static void dgap_get_vpd(struct board_t *brd)
-{
-	u32 magic;
-	u32 base_offset;
-	u16 rom_offset;
-	u16 vpd_offset;
-	u16 image_length;
-	u16 i;
-	uchar byte1;
-	uchar byte2;
-
-	/*
-	 * Poke the magic number at the PCI Rom Address location.
-	 * If VPD is supported, the value read from that address
-	 * will be non-zero.
-	 */
-	magic = FEP5_ROM_MAGIC;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-	/* VPD not supported, bail */
-	if (!magic)
-		return;
-
-	/*
-	 * To get to the OTPROM memory, we have to send the boards base
-	 * address or'ed with 1 into the PCI Rom Address location.
-	 */
-	magic = brd->membase | 0x01;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-	byte1 = readb(brd->re_map_membase);
-	byte2 = readb(brd->re_map_membase + 1);
-
-	/*
-	 * If the board correctly swapped to the OTPROM memory,
-	 * the first 2 bytes (header) should be 0x55, 0xAA
-	 */
-	if (byte1 == 0x55 && byte2 == 0xAA) {
-
-		base_offset = 0;
-
-		/*
-		 * We have to run through all the OTPROM memory looking
-		 * for the VPD offset.
-		 */
-		while (base_offset <= EXPANSION_ROM_SIZE) {
-
-			/*
-			 * Lots of magic numbers here.
-			 *
-			 * The VPD offset is located inside the ROM Data Structure.
-			 * We also have to remember the length of each
-			 * ROM Data Structure, so we can "hop" to the next
-			 * entry if the VPD isn't in the current
-			 * ROM Data Structure.
-			 */
-			rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
-			image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
-			vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
-
-			/* Found the VPD entry */
-			if (vpd_offset)
-				break;
-
-			/* We didn't find a VPD entry, go to next ROM entry. */
-			base_offset += image_length;
-
-			byte1 = readb(brd->re_map_membase + base_offset);
-			byte2 = readb(brd->re_map_membase + base_offset + 1);
-
-			/*
-			 * If the new ROM offset doesn't have 0x55, 0xAA
-			 * as its header, we have run out of ROM.
-			 */
-			if (byte1 != 0x55 || byte2 != 0xAA)
-				break;
-		}
-
-		/*
-		 * If we have a VPD offset, then mark the board
-		 * as having a valid VPD, and copy VPDSIZE (512) bytes of
-		 * that VPD to the buffer we have in our board structure.
-		 */
-		if (vpd_offset) {
-			brd->bd_flags |= BD_HAS_VPD;
-			for (i = 0; i < VPDSIZE; i++)
-				brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
-		}
-	}
-
-	/*
-	 * We MUST poke the magic number at the PCI Rom Address location again.
-	 * This makes the card report the regular board memory back to us,
-	 * rather than the OTPROM memory.
-	 */
-	magic = FEP5_ROM_MAGIC;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-}
-
-
-/*
- * Our board poller function.
- */
-void dgap_poll_tasklet(unsigned long data)
-{
-	struct board_t *bd = (struct board_t *) data;
-	ulong  lock_flags;
-	ulong  lock_flags2;
-	char *vaddr;
-	u16 head, tail;
-	u16 *chk_addr;
-	u16 check = 0;
-
-	if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) {
-		APR(("dgap_poll_tasklet() - NULL or bad bd.\n"));
-		return;
-	}
-
-	if (bd->inhibit_poller)
-		return;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-
-	vaddr = bd->re_map_membase;
-
-	/*
-	 * If board is ready, parse deeper to see if there is anything to do.
-	 */
-	if (bd->state == BOARD_READY) {
-
-		struct ev_t *eaddr = NULL;
-
-		if (!bd->re_map_membase) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return;
-		}
-		if (!bd->re_map_port) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return;
-		}
-
-		if (!bd->nasync) {
-			goto out;
-		}
-
-		/*
-		 * If this is a CX or EPCX, we need to see if the firmware
-		 * is requesting a concentrator image from us.
-		 */
-		if ((bd->type == PCX) || (bd->type == PEPC)) {
-			chk_addr = (u16 *) (vaddr + DOWNREQ);
-			check = readw(chk_addr);
-			/* Nonzero if FEP is requesting concentrator image. */
-			if (check) {
-				if (bd->conc_dl_status == NO_PENDING_CONCENTRATOR_REQUESTS)
-					bd->conc_dl_status = NEED_CONCENTRATOR;
-				/*
-				 * Signal downloader, its got some work to do.
-				 */
-				DGAP_LOCK(dgap_dl_lock, lock_flags2);
-				if (dgap_dl_action != 1) {
-					dgap_dl_action = 1;
-					wake_up_interruptible(&dgap_dl_wait);
-				}
-				DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-
-			}
-		}
-
-		eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-		/* Get our head and tail */
-		head = readw(&(eaddr->ev_head));
-		tail = readw(&(eaddr->ev_tail));
-
-		/*
-		 * If there is an event pending. Go service it.
-		 */
-		if (head != tail) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_event(bd);
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-		}
-
-out:
-		/*
-		 * If board is doing interrupts, ACK the interrupt.
-		 */
-		if (bd && bd->intr_running) {
-			readb(bd->re_map_port + 2);
-		}
-
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return;
-	}
-
-	/* Our state machine to get the board up and running */
-
-	/* Reset board */
-	if (bd->state == NEED_RESET) {
-
-		/* Get VPD info */
-		dgap_get_vpd(bd);
-
-		dgap_do_reset_board(bd);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_RESET) {
-		bd->state = NEED_CONFIG;
-	}
-
-	if (bd->state == NEED_CONFIG) {
-		/*
-		 * Match this board to a config the user created for us.
-		 */
-		bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
-
-		/*
-		 * Because the 4 port Xr products share the same PCI ID
-		 * as the 8 port Xr products, if we receive a NULL config
-		 * back, and this is a PAPORT8 board, retry with a
-		 * PAPORT4 attempt as well.
-		 */
-		if (bd->type == PAPORT8 && !bd->bd_config) {
-			bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
-		}
-
-		/*
-		 * Register the ttys (if any) into the kernel.
-		 */
-		if (bd->bd_config) {
-			bd->state = FINISHED_CONFIG;
-		}
-		else {
-			bd->state = CONFIG_NOT_FOUND;
-		}
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_CONFIG) {
-		bd->state = NEED_DEVICE_CREATION;
-	}
-
-	/* Move to next state */
-	if (bd->state == NEED_DEVICE_CREATION) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_DEVICE_CREATION) {
-		bd->state = NEED_BIOS_LOAD;
-	}
-
-	/* Move to next state */
-	if (bd->state == NEED_BIOS_LOAD) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Wait for BIOS to test board... */
-	if (bd->state == WAIT_BIOS_LOAD) {
-		dgap_do_wait_for_bios(bd);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_BIOS_LOAD) {
-		bd->state = NEED_FEP_LOAD;
-
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Wait for FEP to load on board... */
-	if (bd->state == WAIT_FEP_LOAD) {
-		dgap_do_wait_for_fep(bd);
-	}
-
-
-	/* Move to next state */
-	if (bd->state == FINISHED_FEP_LOAD) {
-
-		/*
-		 * Do tty device initialization.
-		 */
-		int rc = dgap_tty_init(bd);
-
-		if (rc < 0) {
-			dgap_tty_uninit(bd);
-			APR(("Can't init tty devices (%d)\n", rc));
-			bd->state = BOARD_FAILED;
-			bd->dpastatus = BD_NOFEP;
-		}
-		else {
-			bd->state = NEED_PROC_CREATION;
-
-			/*
-			 * Signal downloader, its got some work to do.
-			 */
-			DGAP_LOCK(dgap_dl_lock, lock_flags2);
-			if (dgap_dl_action != 1) {
-				dgap_dl_action = 1;
-				wake_up_interruptible(&dgap_dl_wait);
-			}
-			DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-		}
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_PROC_CREATION) {
-
-		bd->state = BOARD_READY;
-		bd->dpastatus = BD_RUNNING;
-
-		/*
-		 * If user requested the board to run in interrupt mode,
-		 * go and set it up on the board.
-		 */
-		if (bd->intr_used) {
-			writew(1, (bd->re_map_membase + ENABLE_INTR));
-			/*
-			 * Tell the board to poll the UARTS as fast as possible.
-			 */
-			writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
-			bd->intr_running = 1;
-		}
-
-		/* Wake up anyone waiting for board state to change to ready */
-		wake_up_interruptible(&bd->state_wait);
-	}
-
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdb - Sends a 2 byte command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              byte1   - Integer containing first byte to be sent.
- *              byte2   - Integer containing second byte to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is in failed state.\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d pointers out of range, failing board!\n", __FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * 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(byte1, (char *) (vaddr + head + CMDSTART + 2));
-	writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
-
-	head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdw - Sends a 1 word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * 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));
-	writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
-
-	head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-
-/*=======================================================================
- *
- *      dgap_cmdw_ext - Sends a extended word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * Put the data in the circular command buffer.
-	 */
-
-	/* Write an FF to tell the FEP that we want an extended command */
-	writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
-
-	writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
-	writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
-
-	/*
-	 * If the second part of the command won't fit,
-	 * put it at the beginning of the circular buffer.
-	 */
-	if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03))) {
-		writew((u16) word, (char *) (vaddr + CMDSTART));
-	} else {
-		writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
-	}
-
-	head = (head + 8) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-/*=======================================================================
- *
- *      dgap_wmove - Write data to FEP buffer.
- *
- *              ch      - Pointer to channel structure.
- *              buf     - Poiter to characters to be moved.
- *              cnt     - Number of characters to move.
- *
- *=======================================================================*/
-void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
-{
-	int    n;
-	char   *taddr;
-	struct bs_t    *bs;
-	u16    head;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check parameters.
-	 */
-	bs   = ch->ch_bs;
-	head = readw(&(bs->tx_head));
-
-	/*
-	 * If pointers are out of range, just return.
-	 */
-	if ((cnt > ch->ch_tsize) || (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize) {
-		DPR_CORE(("%s:%d pointer out of range", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * If the write wraps over the top of the circular buffer,
-	 * move the portion up to the wrap point, and reset the
-	 * pointers to the bottom.
-	 */
-	n = ch->ch_tstart + ch->ch_tsize - head;
-
-	if (cnt >= n) {
-		cnt -= n;
-		taddr = ch->ch_taddr + head;
-		memcpy_toio(taddr, buf, n);
-		head = ch->ch_tstart;
-		buf += n;
-	}
-
-	/*
-	 * Move rest of data.
-	 */
-	taddr = ch->ch_taddr + head;
-	n = cnt;
-	memcpy_toio(taddr, buf, n);
-	head += cnt;
-
-	writew(head, &(bs->tx_head));
-}
-
-/*
- * Retrives the current custom baud rate from FEP memory,
- * and returns it back to the user.
- * Returns 0 on error.
- */
-uint dgap_get_custom_baud(struct channel_t *ch)
-{
-	uchar *vaddr;
-	ulong offset = 0;
-	uint value = 0;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return 0;
-	}
-
-	if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) {
-		return 0;
-	}
-
-	if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
-		return 0;
-
-	vaddr = ch->ch_bd->re_map_membase;
-
-	if (!vaddr)
-		return 0;
-
-	/*
-	 * Go get from fep mem, what the fep
-	 * believes the custom baud rate is.
-	 */
-	offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
-		(ch->ch_portnum * 0x28) + LINE_SPEED));
-
-	value = readw(vaddr + offset);
-	return value;
-}
-
-
-/*
- * Calls the firmware to reset this channel.
- */
-void dgap_firmware_reset_port(struct channel_t *ch)
-{
-	dgap_cmdb(ch, CHRESET, 0, 0, 0);
-
-	/*
-	 * Now that the channel is reset, we need to make sure
-	 * all the current settings get reapplied to the port
-	 * in the firmware.
-	 *
-	 * So we will set the driver's cache of firmware
-	 * settings all to 0, and then call param.
-	 */
-	ch->ch_fepiflag = 0;
-	ch->ch_fepcflag = 0;
-	ch->ch_fepoflag = 0;
-	ch->ch_fepstartc = 0;
-	ch->ch_fepstopc = 0;
-	ch->ch_fepastartc = 0;
-	ch->ch_fepastopc = 0;
-	ch->ch_mostat = 0;
-	ch->ch_hflow = 0;
-}
-
-
-/*=======================================================================
- *
- *      dgap_param - Set Digi parameters.
- *
- *              struct tty_struct *     - TTY for port.
- *
- *=======================================================================*/
-int dgap_param(struct tty_struct *tty)
-{
-	struct ktermios *ts;
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct bs_t   *bs;
-	struct un_t   *un;
-	u16	head;
-	u16	cflag;
-	u16	iflag;
-	uchar	mval;
-	uchar	hflow;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -ENXIO;
-
-	un = (struct un_t *) tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -ENXIO;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -ENXIO;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	bs = ch->ch_bs;
-	if (!bs)
-		return -ENXIO;
-
-	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
-		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
-
-	ts = &tty->termios;
-
-	/*
-	 * If baud rate is zero, flush queues, and set mval to drop DTR.
-	 */
-	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
-
-		/* flush rx */
-		head = readw(&(ch->ch_bs->rx_head));
-		writew(head, &(ch->ch_bs->rx_tail));
-
-		/* flush tx */
-		head = readw(&(ch->ch_bs->tx_head));
-		writew(head, &(ch->ch_bs->tx_tail));
-
-		ch->ch_flags |= (CH_BAUD0);
-
-		/* Drop RTS and DTR */
-		ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
-		mval = D_DTR(ch) | D_RTS(ch);
-		ch->ch_baud_info = 0;
-
-	} else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
-		/*
-		 * Tell the fep to do the command
-		 */
-
-		DPR_PARAM(("param: Want %d speed\n", ch->ch_custom_speed));
-
-		dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
-
-		/*
-		 * Now go get from fep mem, what the fep
-		 * believes the custom baud rate is.
-		 */
-		ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
-
-		DPR_PARAM(("param: Got %d speed\n", ch->ch_custom_speed));
-
-		/* Handle transition from B0 */
-		if (ch->ch_flags & CH_BAUD0) {
-			ch->ch_flags &= ~(CH_BAUD0);
-			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-		}
-		mval = D_DTR(ch) | D_RTS(ch);
-
-	} else {
-		/*
-		 * Set baud rate, character size, and parity.
-		 */
-
-
-		int iindex = 0;
-		int jindex = 0;
-		int baud = 0;
-
-		ulong bauds[4][16] = {
-			{ /* slowbaud */
-				0,	50,	75,	110,
-				134,	150,	200,	300,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 },
-			{ /* slowbaud & CBAUDEX */
-				0,	57600,	115200,	230400,
-				460800,	150,	200,	921600,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 },
-			{ /* fastbaud */
-				0,	57600,	76800,	115200,
-				14400,	57600,	230400,	76800,
-				115200,	230400,	28800,	460800,
-				921600,	9600,	19200,	38400 },
-			{ /* fastbaud & CBAUDEX */
-				0,	57600,	115200,	230400,
-				460800,	150,	200,	921600,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 }
-		};
-
-		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
-		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
-			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
-		else
-			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
-
-		if (ch->ch_c_cflag & CBAUDEX)
-			iindex = 1;
-
-		if (ch->ch_digi.digi_flags & DIGI_FAST)
-			iindex += 2;
-
-		jindex = baud;
-
-		if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
-			baud = bauds[iindex][jindex];
-		} else {
-			DPR_IOCTL(("baud indices were out of range (%d)(%d)",
-				iindex, jindex));
-			baud = 0;
-		}
-
-		if (baud == 0)
-			baud = 9600;
-
-		ch->ch_baud_info = baud;
-
-
-		/*
-		 * CBAUD has bit position 0x1000 set these days to indicate Linux
-		 * baud rate remap.
-		 * We use a different bit assignment for high speed.  Clear this
-		 * bit out while grabbing the parts of "cflag" we want.
-		 */
-		cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
-		/*
-		 * HUPCL bit is used by FEP to indicate fast baud
-		 * table is to be used.
-		 */
-		if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
-			cflag |= HUPCL;
-
-
-		if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
-		/*
-		 * The below code is trying to guarantee that only baud rates
-		 * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
-		 * because the various baud rates share common bit positions
-		 * and therefore can't be tested for easily.
-		 */
-			tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
-			int baudpart = 0;
-
-			/* Map high speed requests to index into FEP's baud table */
-			switch (tcflag) {
-			case B57600 :
-				baudpart = 1;
-				break;
-#ifdef B76800
-			case B76800 :
-				baudpart = 2;
-				break;
-#endif
-			case B115200 :
-				baudpart = 3;
-				break;
-			case B230400 :
-				baudpart = 9;
-				break;
-			case B460800 :
-				baudpart = 11;
-				break;
-#ifdef B921600
-			case B921600 :
-				baudpart = 12;
-				break;
-#endif
-			default:
-				baudpart = 0;
-			}
-
-			if (baudpart)
-				cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
-		}
-
-		cflag &= 0xffff;
-
-		if (cflag != ch->ch_fepcflag) {
-			ch->ch_fepcflag = (u16) (cflag & 0xffff);
-
-			/* Okay to have channel and board locks held calling this */
-			dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
-		}
-
-		/* Handle transition from B0 */
-		if (ch->ch_flags & CH_BAUD0) {
-			ch->ch_flags &= ~(CH_BAUD0);
-			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-		}
-		mval = D_DTR(ch) | D_RTS(ch);
-	}
-
-	/*
-	 * Get input flags.
-	 */
-	iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
-
-	if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
-		iflag &= ~(IXON | IXOFF);
-		ch->ch_c_iflag &= ~(IXON | IXOFF);
-	}
-
-	/*
-	 * Only the IBM Xr card can switch between
-	 * 232 and 422 modes on the fly
-	 */
-	if (bd->device == PCI_DEVICE_XR_IBM_DID) {
-		if (ch->ch_digi.digi_flags & DIGI_422)
-			dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
-		else
-			dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
-	}
-
-	if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
-		iflag |= IALTPIN ;
-
-	if (iflag != ch->ch_fepiflag) {
-		ch->ch_fepiflag = iflag;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
-	}
-
-	/*
-	 * Select hardware handshaking.
-	 */
-	hflow = 0;
-
-	if (ch->ch_c_cflag & CRTSCTS) {
-		hflow |= (D_RTS(ch) | D_CTS(ch));
-	}
-	if (ch->ch_digi.digi_flags & RTSPACE)
-		hflow |= D_RTS(ch);
-	if (ch->ch_digi.digi_flags & DTRPACE)
-		hflow |= D_DTR(ch);
-	if (ch->ch_digi.digi_flags & CTSPACE)
-		hflow |= D_CTS(ch);
-	if (ch->ch_digi.digi_flags & DSRPACE)
-		hflow |= D_DSR(ch);
-	if (ch->ch_digi.digi_flags & DCDPACE)
-		hflow |= D_CD(ch);
-
-	if (hflow != ch->ch_hflow) {
-		ch->ch_hflow = hflow;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
-	}
-
-
-	/*
-	 * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
-	 */
-	if (bd->bd_flags & BD_FEP5PLUS) {
-		u16 hflow2 = 0;
-		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
-			hflow2 |= (D_RTS(ch));
-		}
-		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
-			hflow2 |= (D_DTR(ch));
-		}
-
-		dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
-	}
-
-	/*
-	 * Set modem control lines.
-	 */
-
-	mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
-
-	DPR_PARAM(("dgap_param: mval: %x ch_mforce: %x ch_mval: %x ch_mostat: %x\n",
-		mval, ch->ch_mforce, ch->ch_mval, ch->ch_mostat));
-
-	if (ch->ch_mostat ^ mval) {
-		ch->ch_mostat = mval;
-
-		/* Okay to have channel and board locks held calling this */
-		DPR_PARAM(("dgap_param: Sending SMODEM mval: %x\n", mval));
-		dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
-	}
-
-	/*
-	 * Read modem signals, and then call carrier function.
-	 */
-	ch->ch_mistat = readb(&(bs->m_stat));
-	dgap_carrier(ch);
-
-	/*
-	 * Set the start and stop characters.
-	 */
-	if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
-		ch->ch_fepstartc = ch->ch_startc;
-		ch->ch_fepstopc =  ch->ch_stopc;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
-	}
-
-	/*
-	 * Set the Auxiliary start and stop characters.
-	 */
-	if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
-		ch->ch_fepastartc = ch->ch_astartc;
-		ch->ch_fepastopc = ch->ch_astopc;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
-	}
-
-	DPR_PARAM(("param finish\n"));
-
-	return 0;
-}
-
-
-/*
- * dgap_parity_scan()
- *
- * Convert the FEP5 way of reporting parity errors and breaks into
- * the Linux line discipline way.
- */
-void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
-{
-	int l = *len;
-	int count = 0;
-	unsigned char *in, *cout, *fout;
-	unsigned char c;
-
-	in = cbuf;
-	cout = cbuf;
-	fout = fbuf;
-
-	DPR_PSCAN(("dgap_parity_scan start\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	while (l--) {
-		c = *in++;
-		switch (ch->pscan_state) {
-		default:
-			/* reset to sanity and fall through */
-			ch->pscan_state = 0;
-
-		case 0:
-			/* No FF seen yet */
-			if (c == (unsigned char) '\377') {
-				/* delete this character from stream */
-				ch->pscan_state = 1;
-			} else {
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-			}
-			break;
-
-		case 1:
-			/* first FF seen */
-			if (c == (unsigned char) '\377') {
-				/* doubled ff, transform to single ff */
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-				ch->pscan_state = 0;
-			} else {
-				/* save value examination in next state */
-				ch->pscan_savechar = c;
-				ch->pscan_state = 2;
-			}
-			break;
-
-		case 2:
-			/* third character of ff sequence */
-
-			*cout++ = c;
-
-			if (ch->pscan_savechar == 0x0) {
-
-				if (c == 0x0) {
-					DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting break.\n", c));
-					ch->ch_err_break++;
-					*fout++ = TTY_BREAK;
-				}
-				else {
-					DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting parity.\n", c));
-					ch->ch_err_parity++;
-					*fout++ = TTY_PARITY;
-				}
-			}
-			else {
-				DPR_PSCAN(("%s:%d Logic Error.\n", __FILE__, __LINE__));
-			}
-
-			count += 1;
-			ch->pscan_state = 0;
-		}
-	}
-	*len = count;
-	DPR_PSCAN(("dgap_parity_scan finish\n"));
-}
-
-
-
-
-/*=======================================================================
- *
- *      dgap_event - FEP to host event processing routine.
- *
- *              bd     - Board of current event.
- *
- *=======================================================================*/
-static int dgap_event(struct board_t *bd)
-{
-	struct channel_t *ch;
-	ulong		lock_flags;
-	ulong		lock_flags2;
-	struct bs_t	*bs;
-	uchar		*event;
-	uchar		*vaddr = NULL;
-	struct ev_t	*eaddr = NULL;
-	uint		head;
-	uint		tail;
-	int		port;
-	int		reason;
-	int		modem;
-	int		b1;
-
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-
-	vaddr = bd->re_map_membase;
-
-	if (!vaddr) {
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-	/* Get our head and tail */
-	head = readw(&(eaddr->ev_head));
-	tail = readw(&(eaddr->ev_tail));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-
-	if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
-	    (head | tail) & 03) {
-		DPR_EVENT(("should be calling xxfail %d\n", __LINE__));
-		/* Let go of board lock */
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/*
-	 * Loop to process all the events in the buffer.
-	 */
-	while (tail != head) {
-
-		/*
-		 * Get interrupt information.
-		 */
-
-		event = bd->re_map_membase + tail + EVSTART;
-
-		port   = event[0];
-		reason = event[1];
-		modem  = event[2];
-		b1     = event[3];
-
-		DPR_EVENT(("event: jiffies: %ld port: %d reason: %x modem: %x\n",
-			jiffies, port, reason, modem));
-
-		/*
-		 * Make sure the interrupt is valid.
-		 */
-		if (port >= bd->nasync)
-			goto next;
-
-		if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) {
-			goto next;
-		}
-
-		ch = bd->channels[port];
-
-		if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-			goto next;
-		}
-
-		/*
-		 * If we have made it here, the event was valid.
-		 * Lock down the channel.
-		 */
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		bs = ch->ch_bs;
-
-		if (!bs) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			goto next;
-		}
-
-		/*
-		 * Process received data.
-		 */
-		if (reason & IFDATA) {
-
-			/*
-			 * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
-			 * input could send some data to ld, which in turn
-			 * could do a callback to one of our other functions.
-			 */
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-			dgap_input(ch);
-
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-			if (ch->ch_flags & CH_RACTIVE)
-				ch->ch_flags |= CH_RENABLE;
-			else
-				writeb(1, &(bs->idata));
-
-			if (ch->ch_flags & CH_RWAIT) {
-				ch->ch_flags &= ~CH_RWAIT;
-
-				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-			}
-		}
-
-		/*
-		 * Process Modem change signals.
-		 */
-		if (reason & IFMODEM) {
-			ch->ch_mistat = modem;
-			dgap_carrier(ch);
-		}
-
-		/*
-		 * Process break.
-		 */
-		if (reason & IFBREAK) {
-
-			DPR_EVENT(("got IFBREAK\n"));
-
-			if (ch->ch_tun.un_tty) {
-				/* A break has been indicated */
-				ch->ch_err_break++;
-				tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
-				tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
-				tty_flip_buffer_push(ch->ch_tun.un_tty->port);
-			}
-		}
-
-		/*
-		 * Process Transmit low.
-		 */
-		if (reason & IFTLW) {
-
-			DPR_EVENT(("event: got low event\n"));
-
-			if (ch->ch_tun.un_flags & UN_LOW) {
-				ch->ch_tun.un_flags &= ~UN_LOW;
-
-				if (ch->ch_tun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_tun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-#else
-						ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
-#endif
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-#else
-						(ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
-#endif
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-
-					DPR_EVENT(("event: Got low event. jiffies: %lu\n", jiffies));
-				}
-			}
-
-			if (ch->ch_pun.un_flags & UN_LOW) {
-				ch->ch_pun.un_flags &= ~UN_LOW;
-				if (ch->ch_pun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_pun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-#else
-						ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
-#endif
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-#else
-						(ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
-#endif
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-				}
-			}
-
-			if (ch->ch_flags & CH_WLOW) {
-				ch->ch_flags &= ~CH_WLOW;
-				wake_up_interruptible(&ch->ch_flags_wait);
-			}
-		}
-
-		/*
-		 * Process Transmit empty.
-		 */
-		if (reason & IFTEM) {
-			DPR_EVENT(("event: got empty event\n"));
-
-			if (ch->ch_tun.un_flags & UN_EMPTY) {
-				ch->ch_tun.un_flags &= ~UN_EMPTY;
-				if (ch->ch_tun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_tun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-#else
-						ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
-#endif
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-#else
-						(ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
-#endif
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-				}
-			}
-
-			if (ch->ch_pun.un_flags & UN_EMPTY) {
-				ch->ch_pun.un_flags &= ~UN_EMPTY;
-				if (ch->ch_pun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_pun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-#else
-						ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
-#endif
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-#else
-						(ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
-#endif
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-				}
-			}
-
-
-			if (ch->ch_flags & CH_WEMPTY) {
-				ch->ch_flags &= ~CH_WEMPTY;
-				wake_up_interruptible(&ch->ch_flags_wait);
-			}
-		}
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-
-next:
-		tail = (tail + 4) & (EVMAX - EVSTART - 4);
-	}
-
-	writew(tail, &(eaddr->ev_tail));
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	return 0;
-}
diff --git a/drivers/staging/dgap/dgap_fep5.h b/drivers/staging/dgap/dgap_fep5.h
deleted file mode 100644
index c9abc406a1e0..000000000000
--- a/drivers/staging/dgap/dgap_fep5.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- ************************************************************************ 
- ***	FEP Version 5 dependent definitions
- ************************************************************************/
-
-#ifndef __DGAP_FEP5_H
-#define __DGAP_FEP5_H
-
-/************************************************************************
- *      FEP memory offsets
- ************************************************************************/
-#define START           0x0004L         /* Execution start address      */
-
-#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
-#define CMDSTART        0x0400L         /* Start of command buffer      */   
-#define CMDMAX          0x0800L         /* End of command buffer        */
-
-#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
-#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 */
-
-/* BIOS MAGIC SPOTS */
-#define ERROR           0x0C14L		/* BIOS error code              */
-#define SEQUENCE	0x0C12L		/* BIOS sequence indicator      */
-#define POSTAREA	0x0C00L		/* POST complete message area   */
-
-/* FEP MAGIC SPOTS */
-#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
-#define NCHAN           0x0C02L         /* number of ports FEP sees     */
-#define PANIC           0x0C10L         /* PANIC area for FEP           */
-#define KMEMEM          0x0C30L         /* Memory for KME use           */   
-#define CONFIG          0x0CD0L         /* Concentrator configuration info */
-#define CONFIGSIZE      0x0030          /* configuration info size      */
-#define DOWNREQ         0x0D00          /* Download request buffer pointer */
-
-#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
-#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
-
-#define XEMPORTS    0xC02	/*
-				 * Offset in board memory where FEP5 stores
-				 * how many ports it has detected.
-				 * NOTE: FEP5 reports 64 ports when the user
-				 * has the cable in EBI OUT instead of EBI IN.
-				 */
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02 
-#define FEPRST      0x04 
-#define FEPINT      0x08
-#define FEPMASK     0x0e
-#define FEPWIN      0x80
-
-#define LOWMEM      0x0100
-#define HIGHMEM     0x7f00
-
-#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	IALTPIN			0x0080		/* Input flag to swap DSR <-> DCD */
-
-/************************************************************************ 
- * 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	*/
-};
-
-/************************************************************************
- * 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	*/
-};
-
-/************************************************************************
- * Download buffer structure.
- ************************************************************************/
-struct downld_t {
-	uchar	dl_type;		/* Header                       */
-	uchar	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                */
-};
-
-/************************************************************************ 
- * Per channel buffer structure
- ************************************************************************
- *              Base Structure Entries Usage Meanings to Host           * 
- *                                                                      * 
- *        W = read write        R = read only                           * 
- *        C = changed by commands only                                  * 
- *        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            */
-};
-
-
-/************************************************************************   
- * FEP supported functions
- ************************************************************************/
-#define SRLOW		0xe0		/* Set receive low water	*/
-#define SRHIGH		0xe1		/* Set receive high water	*/
-#define FLUSHTX		0xe2		/* Flush transmit buffer	*/
-#define PAUSETX		0xe3		/* Pause data transmission	*/
-#define RESUMETX	0xe4		/* Resume data transmission	*/
-#define SMINT		0xe5		/* Set Modem Interrupt		*/
-#define SAFLOWC		0xe6		/* Set Aux. flow control chars	*/
-#define SBREAK		0xe8		/* Send break			*/
-#define SMODEM		0xe9		/* Set 8530 modem control lines	*/  
-#define SIFLAG		0xea		/* Set UNIX iflags		*/
-#define SFLOWC		0xeb		/* Set flow control characters	*/
-#define STLOW		0xec		/* Set transmit low water mark	*/
-#define RPAUSE		0xee		/* Pause receive		*/
-#define RRESUME		0xef		/* Resume receive		*/  
-#define CHRESET		0xf0		/* Reset Channel		*/
-#define BUFSETALL	0xf2		/* Set Tx & Rx buffer size avail*/
-#define SOFLAG		0xf3		/* Set UNIX oflags		*/
-#define SHFLOW		0xf4		/* Set hardware handshake	*/
-#define SCFLAG		0xf5		/* Set UNIX cflags		*/
-#define SVNEXT		0xf6		/* Set VNEXT character		*/
-#define SPINTFC		0xfc		/* Reserved			*/
-#define SCOMMODE	0xfd		/* Set RS232/422 mode		*/
-
-
-/************************************************************************ 
- *	Modes for SCOMMODE
- ************************************************************************/
-#define MODE_232	0x00
-#define MODE_422	0x01
-
-
-/************************************************************************ 
- *      Event flags.
- ************************************************************************/
-#define IFBREAK         0x01            /* Break received               */  
-#define IFTLW           0x02            /* Transmit low water           */
-#define IFTEM           0x04            /* Transmitter empty            */
-#define IFDATA          0x08            /* Receive data present         */
-#define IFMODEM         0x20            /* Modem status change          */
-
-/************************************************************************   
- *      Modem flags
- ************************************************************************/
-#       define  DM_RTS          0x02    /* Request to send              */
-#       define  DM_CD           0x80    /* Carrier detect               */
-#       define  DM_DSR          0x20    /* Data set ready               */
-#       define  DM_CTS          0x10    /* Clear to send                */
-#       define  DM_RI           0x40    /* Ring indicator               */
-#       define  DM_DTR          0x01    /* Data terminal ready          */
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_kcompat.h b/drivers/staging/dgap/dgap_kcompat.h
deleted file mode 100644
index 0dc2404922ff..000000000000
--- a/drivers/staging/dgap/dgap_kcompat.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * This file is intended to contain all the kernel "differences" between the
- * various kernels that we support.
- *
- *************************************************************************/
-
-#ifndef __DGAP_KCOMPAT_H
-#define __DGAP_KCOMPAT_H
-
-#if !defined(TTY_FLIPBUF_SIZE)
-# define TTY_FLIPBUF_SIZE 512
-#endif
-
-
-/* Sparse stuff */
-# ifndef __user
-#  define __user
-#  define __kernel
-#  define __safe
-#  define __force
-#  define __chk_user_ptr(x) (void)0
-# endif
-
-
-#  define PARM_STR(VAR, INIT, PERM, DESC) \
-		static char *VAR = INIT; \
-		char *dgap_##VAR; \
-		module_param(VAR, charp, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_INT(VAR, INIT, PERM, DESC) \
-		static int VAR = INIT; \
-		int dgap_##VAR; \
-		module_param(VAR, int, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
-		static ulong VAR = INIT; \
-		ulong dgap_##VAR; \
-		module_param(VAR, long, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#endif /* ! __DGAP_KCOMPAT_H */
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c
deleted file mode 100644
index 36fd93d3f5f6..000000000000
--- a/drivers/staging/dgap/dgap_parse.c
+++ /dev/null
@@ -1,1374 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- *
- *****************************************************************************
- *
- * dgap_parse.c - Parses the configuration information from the input file.
- *
- * $Id: dgap_parse.c,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
-
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_driver.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-
-
-/*
- * Function prototypes.
- */
-static int dgap_gettok(char **in, struct cnode *p);
-static char *dgap_getword(char **in);
-static char *dgap_savestring(char *s);
-static struct cnode *dgap_newnode(int t);
-static int dgap_checknode(struct cnode *p);
-static void dgap_err(char *s);
-
-/*
- * Our needed internal static variables...
- */
-static struct cnode dgap_head;
-#define MAXCWORD 200
-static char dgap_cword[MAXCWORD];
-
-struct toklist {
-	int	token;
-	char	*string;
-};
-
-static struct toklist dgap_tlist[] = {
-	{	BEGIN,		"config_begin"			},
-	{	END,		"config_end"			},
-	{	BOARD,		"board"				},
-	{	PCX,		"Digi_AccelePort_C/X_PCI"	},	/* C/X_PCI */
-	{	PEPC,		"Digi_AccelePort_EPC/X_PCI"	},	/* EPC/X_PCI */
-	{	PPCM,		"Digi_AccelePort_Xem_PCI"	},	/* PCI/Xem */
-	{	APORT2_920P,	"Digi_AccelePort_2r_920_PCI"	},
-	{	APORT4_920P,	"Digi_AccelePort_4r_920_PCI"	},
-	{	APORT8_920P,	"Digi_AccelePort_8r_920_PCI"	},
-	{	PAPORT4,	"Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
-	{	PAPORT8,	"Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
-	{	IO,		"io"				},
-	{	PCIINFO,	"pciinfo"			},
-	{	LINE,		"line"				},
-	{	CONC,		"conc"				},
-	{	CONC,		"concentrator"			},
-	{	CX,		"cx"				},
-	{	CX,		"ccon"				},
-	{	EPC,		"epccon"			},
-	{	EPC,		"epc"				},
-	{	MOD,		"module"			},
-	{	ID,		"id"				},
-	{	STARTO,		"start"				},
-	{	SPEED,		"speed"				},
-	{	CABLE,		"cable"				},
-	{	CONNECT,	"connect"			},
-	{	METHOD,		"method"			},
-	{	STATUS,		"status"			},
-	{	CUSTOM,		"Custom"			},
-	{	BASIC,		"Basic"				},
-	{	MEM,		"mem"				},
-	{	MEM,		"memory"			},
-	{	PORTS,		"ports"				},
-	{	MODEM,		"modem"				},
-	{	NPORTS,		"nports"			},
-	{	TTYN,		"ttyname"			},
-	{	CU,		"cuname"			},
-	{	PRINT,		"prname"			},
-	{	CMAJOR,		"major"				},
-	{	ALTPIN,		"altpin"			},
-	{	USEINTR,	"useintr"			},
-	{	TTSIZ,		"ttysize"			},
-	{	CHSIZ,		"chsize"			},
-	{	BSSIZ,		"boardsize"			},
-	{	UNTSIZ,		"schedsize"			},
-	{	F2SIZ,		"f2200size"			},
-	{	VPSIZ,		"vpixsize"			},
-	{	0,		NULL				}
-};
-
-
-/*
- * Parse a configuration file read into memory as a string.
- */
-int	dgap_parsefile(char **in, int Remove)
-{
-	struct cnode *p, *brd, *line, *conc;
-	int	rc;
-	char	*s = NULL, *s2 = NULL;
-	int	linecnt = 0;
-
-	p = &dgap_head;
-	brd = line = conc = NULL;
-
-	/* perhaps we are adding to an existing list? */
-	while (p->next != NULL) {
-		p = p->next;
-	}
-
-	/* file must start with a BEGIN */
-	while ( (rc = dgap_gettok(in,p)) != BEGIN ) {
-		if (rc == 0) {
-			dgap_err("unexpected EOF");
-			return(-1);
-		}
-	}
-
-	for (; ; ) {
-		rc = dgap_gettok(in,p);
-		if (rc == 0) {
-			dgap_err("unexpected EOF");
-			return(-1);
-		}
-
-		switch (rc) {
-		case 0:
-			dgap_err("unexpected end of file");
-			return(-1);
-
-		case BEGIN:	/* should only be 1 begin */
-			dgap_err("unexpected config_begin\n");
-			return(-1);
-
-		case END:
-			return(0);
-
-		case BOARD:	/* board info */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(BNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-
-			p->u.board.status = dgap_savestring("No");
-			line = conc = NULL;
-			brd = p;
-			linecnt = -1;
-			break;
-
-		case APORT2_920P:	/* AccelePort_4 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_2r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT2_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_2r_920 PCI to config...\n"));
-			break;
-
-		case APORT4_920P:	/* AccelePort_4 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_4r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT4_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_4r_920 PCI to config...\n"));
-			break;
-
-		case APORT8_920P:	/* AccelePort_8 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_8r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT8_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_8r_920 PCI to config...\n"));
-			break;
-
-		case PAPORT4:	/* AccelePort_4 PCI */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_4r(PCI) string");
-				return(-1);
-			}
-			p->u.board.type = PAPORT4;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_4r PCI to config...\n"));
-			break;
-
-		case PAPORT8:	/* AccelePort_8 PCI */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_8r string");
-				return(-1);
-			}
-			p->u.board.type = PAPORT8;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_8r PCI to config...\n"));
-			break;
-
-		case PCX:	/* PCI C/X */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_C/X_(PCI) string");
-				return(-1);
-			}
-			p->u.board.type = PCX;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			p->u.board.module1 = 0;
-			p->u.board.module2 = 0;
-			DPR_INIT(("Adding PCI C/X to config...\n"));
-			break;
-
-		case PEPC:	/* PCI EPC/X */
-			if (p->type != BNODE) {
-				dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
-				return(-1);
-			}
-			p->u.board.type = PEPC;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			p->u.board.module1 = 0;
-			p->u.board.module2 = 0;
-			DPR_INIT(("Adding PCI EPC/X to config...\n"));
-			break;
-
-		case PPCM:	/* PCI/Xem */
-			if (p->type != BNODE) {
-				dgap_err("unexpected PCI/Xem string");
-				return(-1);
-			}
-			p->u.board.type = PPCM;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			DPR_INIT(("Adding PCI XEM to config...\n"));
-			break;
-
-		case IO:	/* i/o port */
-			if (p->type != BNODE) {
-				dgap_err("IO port only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.portstr = dgap_savestring(s);
-			p->u.board.port = (short)simple_strtol(s, &s2, 0);
-			if ((short)strlen(s) > (short)(s2 - s)) {
-				dgap_err("bad number for IO port");
-				return(-1);
-			}
-			p->u.board.v_port = 1;
-			DPR_INIT(("Adding IO (%s) to config...\n", s));
-			break;
-
-		case MEM:	/* memory address */
-			if (p->type != BNODE) {
-				dgap_err("memory address only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.addrstr = dgap_savestring(s);
-			p->u.board.addr = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for memory address");
-				return(-1);
-			}
-			p->u.board.v_addr = 1;
-			DPR_INIT(("Adding MEM (%s) to config...\n", s));
-			break;
-
-		case PCIINFO:	/* pci information */
-			if (p->type != BNODE) {
-				dgap_err("memory address only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.pcibusstr = dgap_savestring(s);
-			p->u.board.pcibus = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for pci bus");
-				return(-1);
-			}
-			p->u.board.v_pcibus = 1;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.pcislotstr = dgap_savestring(s);
-			p->u.board.pcislot = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for pci slot");
-				return(-1);
-			}
-			p->u.board.v_pcislot = 1;
-
-			DPR_INIT(("Adding PCIINFO (%s %s) to config...\n", p->u.board.pcibusstr, 
-				p->u.board.pcislotstr));
-			break;
-
-		case METHOD:
-			if (p->type != BNODE) {
-				dgap_err("install method only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.method = dgap_savestring(s);
-			p->u.board.v_method = 1;
-			DPR_INIT(("Adding METHOD (%s) to config...\n", s));
-			break;
-
-		case STATUS:
-			if (p->type != BNODE) {
-				dgap_err("config status only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.status = dgap_savestring(s);
-			DPR_INIT(("Adding STATUS (%s) to config...\n", s));
-			break;
-
-		case NPORTS:	/* number of ports */
-			if (p->type == BNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.board.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.board.v_nport = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.conc.v_nport = 1;
-			} else if (p->type == MNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.module.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.module.v_nport = 1;
-			} else {
-				dgap_err("nports only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding NPORTS (%s) to config...\n", s));
-			break;
-
-		case ID:	/* letter ID used in tty name */
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-
-			p->u.board.status = dgap_savestring(s);
-
-			if (p->type == CNODE) {
-				p->u.conc.id = dgap_savestring(s);
-				p->u.conc.v_id = 1;
-			} else if (p->type == MNODE) {
-				p->u.module.id = dgap_savestring(s);
-				p->u.module.v_id = 1;
-			} else {
-				dgap_err("id only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding ID (%s) to config...\n", s));
-			break;
-
-		case STARTO:	/* start offset of ID */
-			if (p->type == BNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.board.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.board.v_start = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.conc.v_start = 1;
-			} else if (p->type == MNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.module.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.module.v_start = 1;
-			} else {
-				dgap_err("start only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding START (%s) to config...\n", s));
-			break;
-
-		case TTYN:	/* tty name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(TNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.ttyname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding TTY (%s) to config...\n", s));
-			break;
-
-		case CU:	/* cu name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(CUNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.cuname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding CU (%s) to config...\n", s));
-			break;
-
-		case LINE:	/* line information */
-			if (dgap_checknode(p))
-				return(-1);
-			if (brd == NULL) {
-				dgap_err("must specify board before line info");
-				return(-1);
-			}
-			switch (brd->u.board.type) {
-			case PPCM:
-				dgap_err("line not vaild for PC/em");
-				return(-1);
-			}
-			if ( (p->next = dgap_newnode(LNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			conc = NULL;
-			line = p;
-			linecnt++;
-			DPR_INIT(("Adding LINE to config...\n"));
-			break;
-
-		case CONC:	/* concentrator information */
-			if (dgap_checknode(p))
-				return(-1);
-			if (line == NULL) {
-				dgap_err("must specify line info before concentrator");
-				return(-1);
-			}
-			if ( (p->next = dgap_newnode(CNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			conc = p;
-			if (linecnt)
-				brd->u.board.conc2++;
-			else
-				brd->u.board.conc1++;
-
-			DPR_INIT(("Adding CONC to config...\n"));
-			break;
-
-		case CX:	/* c/x type concentrator */
-			if (p->type != CNODE) {
-				dgap_err("cx only valid for concentrators");
-				return(-1);
-			}
-			p->u.conc.type = CX;
-			p->u.conc.v_type = 1;
-			DPR_INIT(("Adding CX to config...\n"));
-			break;
-
-		case EPC:	/* epc type concentrator */
-			if (p->type != CNODE) {
-				dgap_err("cx only valid for concentrators");
-				return(-1);
-			}
-			p->u.conc.type = EPC;
-			p->u.conc.v_type = 1;
-			DPR_INIT(("Adding EPC to config...\n"));
-			break;
-
-		case MOD:	/* EBI module */
-			if (dgap_checknode(p))
-				return(-1);
-			if (brd == NULL) {
-				dgap_err("must specify board info before EBI modules");
-				return(-1);
-			}
-			switch (brd->u.board.type) {
-			case PPCM:
-				linecnt = 0;
-				break;
-			default:
-				if (conc == NULL) {
-					dgap_err("must specify concentrator info before EBI module");
-					return(-1);
-				}
-			}
-			if ( (p->next = dgap_newnode(MNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if (linecnt)
-				brd->u.board.module2++;
-			else
-				brd->u.board.module1++;
-
-			DPR_INIT(("Adding MOD to config...\n"));
-			break;
-
-		case PORTS:	/* ports type EBI module */
-			if (p->type != MNODE) {
-				dgap_err("ports only valid for EBI modules");
-				return(-1);
-			}
-			p->u.module.type = PORTS;
-			p->u.module.v_type = 1;
-			DPR_INIT(("Adding PORTS to config...\n"));
-			break;
-
-		case MODEM:	/* ports type EBI module */
-			if (p->type != MNODE) {
-				dgap_err("modem only valid for modem modules");
-				return(-1);
-			}
-			p->u.module.type = MODEM;
-			p->u.module.v_type = 1;
-			DPR_INIT(("Adding MODEM to config...\n"));
-			break;
-
-		case CABLE:
-			if (p->type == LNODE) {
-				if ((s = dgap_getword(in)) == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.line.cable = dgap_savestring(s);
-				p->u.line.v_cable = 1;
-			}
-			DPR_INIT(("Adding CABLE (%s) to config...\n", s));
-			break;
-
-		case SPEED:	/* sync line speed indication */
-			if (p->type == LNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.line.speed = (char)simple_strtol(s, &s2, 0);
-				if ((short)strlen(s) > (short)(s2 - s)) {
-					dgap_err("bad number for line speed");
-					return(-1);
-				}
-				p->u.line.v_speed = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
-				if ((short)strlen(s) > (short)(s2 - s)) {
-					dgap_err("bad number for line speed");
-					return(-1);
-				}
-				p->u.conc.v_speed = 1;
-			} else {
-				dgap_err("speed valid only for lines or concentrators.");
-				return(-1);
-			}
-			DPR_INIT(("Adding SPEED (%s) to config...\n", s));
-			break;
-
-		case CONNECT:
-			if (p->type == CNODE) {
-				if ((s = dgap_getword(in)) == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.connect = dgap_savestring(s);
-				p->u.conc.v_connect = 1;
-			}
-			DPR_INIT(("Adding CONNECT (%s) to config...\n", s));
-			break;
-		case PRINT:	/* transparent print name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(PNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.printname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding PRINT (%s) to config...\n", s));
-			break;
-
-		case CMAJOR:	/* major number */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(JNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.majornumber = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for major number");
-				return(-1);
-			}
-			DPR_INIT(("Adding CMAJOR (%s) to config...\n", s));
-			break;
-
-		case ALTPIN:	/* altpin setting */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(ANODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.altpin = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for altpin");
-				return(-1);
-			}
-			DPR_INIT(("Adding ALTPIN (%s) to config...\n", s));
-			break;
-
-		case USEINTR:		/* enable interrupt setting */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(INTRNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.useintr = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for useintr");
-				return(-1);
-			}
-			DPR_INIT(("Adding USEINTR (%s) to config...\n", s));
-			break;
-
-		case TTSIZ:	/* size of tty structure */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(TSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.ttysize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for ttysize");
-				return(-1);
-			}
-			DPR_INIT(("Adding TTSIZ (%s) to config...\n", s));
-			break;
-
-		case CHSIZ:	/* channel structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(CSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.chsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for chsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding CHSIZE (%s) to config...\n", s));
-			break;
-
-		case BSSIZ:	/* board structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(BSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.bssize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for bssize");
-				return(-1);
-			}
-			DPR_INIT(("Adding BSSIZ (%s) to config...\n", s));
-			break;
-
-		case UNTSIZ:	/* sched structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(USNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.unsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for schedsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding UNTSIZ (%s) to config...\n", s));
-			break;
-
-		case F2SIZ:	/* f2200 structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(FSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.f2size = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for f2200size");
-				return(-1);
-			}
-			DPR_INIT(("Adding F2SIZ (%s) to config...\n", s));
-			break;
-
-		case VPSIZ:	/* vpix structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(VSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.vpixsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for vpixsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding VPSIZ (%s) to config...\n", s));
-			break;
-		}
-	}
-}
-
-
-/*
- * dgap_sindex: much like index(), but it looks for a match of any character in
- * the group, and returns that position.  If the first character is a ^, then
- * this will match the first occurrence not in that group.
- */
-static char *dgap_sindex (char *string, char *group)
-{
-	char    *ptr;
-
-	if (!string || !group)
-		return (char *) NULL;
-
-	if (*group == '^') {   
-		group++;
-		for (; *string; string++) {
-			for (ptr = group; *ptr; ptr++) {
-				if (*ptr == *string)
-					break;
-			}
-			if (*ptr == '\0')
-				return string;
-		}
-	}   
-	else {
-		for (; *string; string++) {
-			for (ptr = group; *ptr; ptr++) {
-				if (*ptr == *string)
-					return string;
-			}
-		}
-	}
-
-	return (char *) NULL;
-}
-
-
-/*
- * Get a token from the input file; return 0 if end of file is reached
- */
-static int dgap_gettok(char **in, struct cnode *p)
-{
-	char	*w;
-	struct toklist *t;
-	
-	if (strstr(dgap_cword, "boar")) {
-		w = dgap_getword(in);
-		snprintf(dgap_cword, MAXCWORD, "%s", w);
-		for (t = dgap_tlist; t->token != 0; t++) {
-			if ( !strcmp(w, t->string)) {
-				return(t->token);
-			} 
-		}
-		dgap_err("board !!type not specified");
-		return(1);
-	}
-	else {
-		while ( (w = dgap_getword(in)) != NULL ) {
-			snprintf(dgap_cword, MAXCWORD, "%s", w);
-			for (t = dgap_tlist; t->token != 0; t++) {
-				if ( !strcmp(w, t->string) )
-					return(t->token);
-			}
-		}
-		return(0);
-	}
-}
-
-
-/*
- * get a word from the input stream, also keep track of current line number.
- * words are separated by whitespace.
- */
-static char *dgap_getword(char **in)
-{
-	char *ret_ptr = *in;
-
-        char *ptr = dgap_sindex(*in, " \t\n");
-
-	/* If no word found, return null */
-	if (!ptr)
-		return NULL;
-
-	/* Mark new location for our buffer */
-	*ptr = '\0';
-	*in = ptr + 1;
-
-	/* Eat any extra spaces/tabs/newlines that might be present */
-	while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
-		**in = '\0';
-		*in = *in + 1;
-	}
-
-	return ret_ptr;
-}
-
-
-/*
- * print an error message, giving the line number in the file where
- * the error occurred.
- */
-static void dgap_err(char *s)
-{
-	printk("DGAP: parse: %s\n", s);
-}
-
-
-/*
- * allocate a new configuration node of type t
- */
-static struct cnode *dgap_newnode(int t)
-{
-	struct cnode *n;
-
-	n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
-	if (n != NULL) {
-		memset((char *)n, 0, sizeof(struct cnode));
-		n->type = t;
-	}
-	return(n);
-}
-
-
-/*
- * dgap_checknode: see if all the necessary info has been supplied for a node
- * before creating the next node.
- */
-static int dgap_checknode(struct cnode *p)
-{
-	switch (p->type) {
-	case BNODE:
-		if (p->u.board.v_type == 0) {
-			dgap_err("board type !not specified");
-			return(1);
-		}
-
-		return(0);
-
-	case LNODE:
-		if (p->u.line.v_speed == 0) {
-			dgap_err("line speed not specified");
-			return(1);
-		}
-		return(0);
-
-	case CNODE:
-		if (p->u.conc.v_type == 0) {
-			dgap_err("concentrator type not specified");
-			return(1);
-		}
-		if (p->u.conc.v_speed == 0) {
-			dgap_err("concentrator line speed not specified");
-			return(1);
-		}
-		if (p->u.conc.v_nport == 0) {
-			dgap_err("number of ports on concentrator not specified");
-			return(1);
-		}
-		if (p->u.conc.v_id == 0) {
-			dgap_err("concentrator id letter not specified");
-			return(1);
-		}
-		return(0);
-
-	case MNODE:
-		if (p->u.module.v_type == 0) {
-			dgap_err("EBI module type not specified");
-			return(1);
-		}
-		if (p->u.module.v_nport == 0) {
-			dgap_err("number of ports on EBI module not specified");
-			return(1);
-		}
-		if (p->u.module.v_id == 0) {
-			dgap_err("EBI module id letter not specified");
-			return(1);
-		}
-		return(0);
-	}
-	return(0);
-}
-
-/*
- * save a string somewhere
- */
-static char	*dgap_savestring(char *s)
-{
-	char	*p;
-	if ( (p = kmalloc(strlen(s) + 1, GFP_ATOMIC) ) != NULL) {
-		strcpy(p, s);
-	}
-	return(p);
-}
-
-
-/*
- * Given a board pointer, returns whether we should use interrupts or not.
- */
-uint dgap_config_get_useintr(struct board_t *bd)
-{
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-		switch (p->type) {
-		case INTRNODE:
-			/*
-			 * check for pcxr types.
-			 */
-			return p->u.useintr;
-		default:
-			break;
-		}
-	}
-
-	/* If not found, then don't turn on interrupts. */
-	return 0;
-}
-
-
-/*
- * Given a board pointer, returns whether we turn on altpin or not.
- */
-uint dgap_config_get_altpin(struct board_t *bd)
-{
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-		switch (p->type) {
-		case ANODE:
-			/*
-			 * check for pcxr types.
-			 */
-			return p->u.altpin;
-		default:
-			break;
-		}
-	}
-
-	/* If not found, then don't turn on interrupts. */
-	return 0;
-}
-
-
-
-/*
- * Given a specific type of board, if found, detached link and 
- * returns the first occurrence in the list.
- */
-struct cnode *dgap_find_config(int type, int bus, int slot)
-{
-	struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
-
-	p = &dgap_head;
-
-	while (p->next != NULL) {
-		prev = p;
-		p = p->next;
-
-		if (p->type == BNODE) {
-
-			if (p->u.board.type == type) {
-
-				if (p->u.board.v_pcibus && p->u.board.pcibus != bus) {
-					DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n",
-						bus, p->u.board.pcibus));
-					continue;
-				}
-				if (p->u.board.v_pcislot && p->u.board.pcislot != slot) {
-					DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n",
-						slot, p->u.board.pcislot));
-					continue;
-				}
-
-				DPR_INIT(("Matched type in config file\n"));
-
-				found = p;
-				/*
-				 * Keep walking thru the list till we find the next board.
-				 */
-				while (p->next != NULL) {
-					prev2 = p;
-					p = p->next;
-					if (p->type == BNODE) {
-
-						/*
-						 * Mark the end of our 1 board chain of configs.
-						 */
-						prev2->next = NULL;
-
-						/*
-						 * Link the "next" board to the previous board,
-						 * effectively "unlinking" our board from the main config.
-						 */
-						prev->next = p;
-
-						return found;
-					}
-				}
-				/*
-				 * It must be the last board in the list.
-				 */
-				prev->next = NULL;
-				return found;
-			}
-		}
-	}
-	return NULL;
-}
-
-/*
- * Given a board pointer, walks the config link, counting up
- * all ports user specified should be on the board.
- * (This does NOT mean they are all actually present right now tho)
- */
-uint dgap_config_get_number_of_ports(struct board_t *bd)
-{
-	int count = 0;
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-
-		switch (p->type) {
-		case BNODE:
-			/*
-			 * check for pcxr types.
-			 */
-			if (p->u.board.type > EPCFE)
-				count += p->u.board.nport;
-			break;
-		case CNODE:
-			count += p->u.conc.nport;
-			break;
-		case MNODE:
-			count += p->u.module.nport;
-			break;
-		}
-	}
-	return (count);
-}
-
-char *dgap_create_config_string(struct board_t *bd, char *string)
-{
-	char *ptr = string;
-	struct cnode *p = NULL;
-	struct cnode *q = NULL;
-	int speed;
-
-	if (!bd) {
-		*ptr = 0xff;
-		return string;
-	}
-
-	for (p = bd->bd_config; p; p = p->next) {
-
-		switch (p->type) {
-		case LNODE:
-			*ptr = '\0';
-			ptr++;
-			*ptr = p->u.line.speed;
-			ptr++;
-			break;
-		case CNODE:
-			/*
-			 * Because the EPC/con concentrators can have EM modules
-			 * hanging off of them, we have to walk ahead in the list
-			 * and keep adding the number of ports on each EM to the config.
-			 * UGH!
-			 */
-			speed = p->u.conc.speed;
-			q = p->next;
-			if ((q != NULL) && (q->type == MNODE) ) {
-				*ptr = (p->u.conc.nport + 0x80);
-				ptr++;
-				p = q;
-				while ((q->next != NULL) && (q->next->type) == MNODE) {
-					*ptr = (q->u.module.nport + 0x80);
-					ptr++;
-					p = q;
-					q = q->next;
-				}
-				*ptr = q->u.module.nport;
-				ptr++;
-			} else {
-				*ptr = p->u.conc.nport;
-				ptr++;
-			}
-
-			*ptr = speed;
-			ptr++;
-			break;
-		}
-	}
-
-	*ptr = 0xff;
-	return string;
-}
-
-
-
-char *dgap_get_config_letters(struct board_t *bd, char *string)
-{
-	int found = FALSE;
-	char *ptr = string;
-	struct cnode *cptr = NULL;
-	int len = 0;
-	int left = MAXTTYNAMELEN;
-
-	if (!bd) {
-		return "<NULL>";
-	}
-
-	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-		if ((cptr->type == BNODE) &&
-		     ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-		     (cptr->u.board.type == PAPORT8))) {
-
-			found = TRUE;
-		}
-
-		if (cptr->type == TNODE && found == TRUE) {
-			char *ptr1;
-			if (strstr(cptr->u.ttyname, "tty")) {
-				ptr1 = cptr->u.ttyname;
-				ptr1 += 3;
-			}
-			else {
-				ptr1 = cptr->u.ttyname;
-			}
-			if (ptr1) {
-				len = snprintf(ptr, left, "%s", ptr1);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-		}
-
-		if (cptr->type == CNODE) {
-			if (cptr->u.conc.id) {
-				len = snprintf(ptr, left, "%s", cptr->u.conc.id);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-                }
-
-		if (cptr->type == MNODE) {
-			if (cptr->u.module.id) {
-				len = snprintf(ptr, left, "%s", cptr->u.module.id);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-		}
-	}
-
-	return string;
-}
diff --git a/drivers/staging/dgap/dgap_parse.h b/drivers/staging/dgap/dgap_parse.h
deleted file mode 100644
index 8128c47343cb..000000000000
--- a/drivers/staging/dgap/dgap_parse.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_PARSE_H
-#define _DGAP_PARSE_H
-
-#include "dgap_driver.h"
-
-extern int dgap_parsefile(char **in, int Remove);
-extern struct cnode *dgap_find_config(int type, int bus, int slot);
-extern uint dgap_config_get_number_of_ports(struct board_t *bd);
-extern char *dgap_create_config_string(struct board_t *bd, char *string);
-extern char *dgap_get_config_letters(struct board_t *bd, char *string);
-extern uint dgap_config_get_useintr(struct board_t *bd);
-extern uint dgap_config_get_altpin(struct board_t *bd);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_pci.h b/drivers/staging/dgap/dgap_pci.h
deleted file mode 100644
index 05ed374f08e1..000000000000
--- a/drivers/staging/dgap/dgap_pci.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-/* $Id: dgap_pci.h,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#ifndef __DGAP_PCI_H
-#define __DGAP_PCI_H
-
-#define PCIMAX 32			/* maximum number of PCI boards */
-
-#define DIGI_VID		0x114F
-
-#define PCI_DEVICE_EPC_DID	0x0002
-#define PCI_DEVICE_XEM_DID	0x0004
-#define PCI_DEVICE_XR_DID	0x0005
-#define PCI_DEVICE_CX_DID	0x0006
-#define PCI_DEVICE_XRJ_DID	0x0009	/* PLX-based Xr adapter */
-#define PCI_DEVICE_XR_IBM_DID	0x0011	/* IBM 8-port Async Adapter */
-#define PCI_DEVICE_XR_BULL_DID	0x0013	/* BULL 8-port Async Adapter */
-#define PCI_DEVICE_XR_SAIP_DID	0x001c	/* SAIP card - Xr adapter */
-#define PCI_DEVICE_XR_422_DID	0x0012	/* Xr-422 */
-#define PCI_DEVICE_920_2_DID	0x0034	/* XR-Plus 920 K, 2 port */
-#define PCI_DEVICE_920_4_DID	0x0026	/* XR-Plus 920 K, 4 port */
-#define PCI_DEVICE_920_8_DID	0x0027	/* XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_EPCJ_DID	0x000a	/* PLX 9060 chip for PCI  */
-#define PCI_DEVICE_CX_IBM_DID	0x001b	/* IBM 128-port Async Adapter */
-#define PCI_DEVICE_920_8_HP_DID	0x0058	/* HP XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_XEM_HP_DID	0x0059  /* HP Xem PCI */
-
-#define PCI_DEVICE_XEM_NAME	"AccelePort XEM"
-#define PCI_DEVICE_CX_NAME	"AccelePort CX"
-#define PCI_DEVICE_XR_NAME	"AccelePort Xr"
-#define PCI_DEVICE_XRJ_NAME	"AccelePort Xr (PLX)"
-#define PCI_DEVICE_XR_SAIP_NAME	"AccelePort Xr (SAIP)"
-#define PCI_DEVICE_920_2_NAME	"AccelePort Xr920 2 port"
-#define PCI_DEVICE_920_4_NAME	"AccelePort Xr920 4 port"
-#define PCI_DEVICE_920_8_NAME	"AccelePort Xr920 8 port"
-#define PCI_DEVICE_XR_422_NAME	"AccelePort Xr 422"
-#define PCI_DEVICE_EPCJ_NAME	"AccelePort EPC (PLX)"
-#define PCI_DEVICE_XR_BULL_NAME	"AccelePort Xr (BULL)"
-#define PCI_DEVICE_XR_IBM_NAME	"AccelePort Xr (IBM)"
-#define PCI_DEVICE_CX_IBM_NAME	"AccelePort CX (IBM)"
-#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
-#define PCI_DEVICE_XEM_HP_NAME	"AccelePort XEM (HP)"
-
-
-/*
- * On the PCI boards, there is no IO space allocated
- * The I/O registers will be in the first 3 bytes of the
- * upper 2MB of the 4MB memory space.  The board memory
- * will be mapped into the low 2MB of the 4MB memory space
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE		0x00020000
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE		0x00400000
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE		0x00200000
-
-/* Max PCI Window Size (2MB) */
-#define PCI_WIN_SIZE		0x00200000
-
-#define PCI_WIN_SHIFT		21 /* 21 bits max */
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET		0x00200000
-
-/* Size of IO (2MB) */
-#define PCI_IO_SIZE		0x00200000
-
-#endif
diff --git a/drivers/staging/dgap/dgap_sysfs.c b/drivers/staging/dgap/dgap_sysfs.c
deleted file mode 100644
index 7f4ec9a18293..000000000000
--- a/drivers/staging/dgap/dgap_sysfs.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- *
- * 
- * $Id: dgap_sysfs.c,v 1.1 2009/10/23 14:01:57 markh Exp $   
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/serial_reg.h>
-#include <linux/device.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-  
-#include "dgap_driver.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-
-
-static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
-}
-static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
-
-
-static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
-}
-static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
-
-
-static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
-}
-static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
-
-
-static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
-}
-static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
-
-
-static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
-}
-static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
-
-
-static ssize_t dgap_driver_debug_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_debug);
-}
-
-static ssize_t dgap_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "0x%x\n", &dgap_debug);
-	return count;
-}
-static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgap_driver_debug_show, dgap_driver_debug_store);
-
-
-static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
-}
-
-static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "0x%x\n", &dgap_rawreadok);
-	return count;
-}
-static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
-
-
-static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
-}
-
-static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "%d\n", &dgap_poll_tick);
-	return count;
-}
-static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
-
-
-void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-	int rc = 0;
-	struct device_driver *driverfs = &dgap_driver->driver;
-
-	rc |= driver_create_file(driverfs, &driver_attr_version);
-	rc |= driver_create_file(driverfs, &driver_attr_boards);
-	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
-	rc |= driver_create_file(driverfs, &driver_attr_debug);
-	rc |= driver_create_file(driverfs, &driver_attr_rawreadok); 
-	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
-	rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
-	rc |= driver_create_file(driverfs, &driver_attr_state);
-	if (rc) {
-		printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
-	}
-}
-
-
-void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-	struct device_driver *driverfs = &dgap_driver->driver;
-	driver_remove_file(driverfs, &driver_attr_version);
-	driver_remove_file(driverfs, &driver_attr_boards);
-	driver_remove_file(driverfs, &driver_attr_maxboards);
-	driver_remove_file(driverfs, &driver_attr_debug);
-	driver_remove_file(driverfs, &driver_attr_rawreadok);
-	driver_remove_file(driverfs, &driver_attr_pollrate);
-	driver_remove_file(driverfs, &driver_attr_pollcounter);
-	driver_remove_file(driverfs, &driver_attr_state);
-}
-
-
-#define DGAP_VERIFY_BOARD(p, bd)			\
-	if (!p)						\
-		return (0);				\
-							\
-	bd = dev_get_drvdata(p);			\
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)	\
-		return (0);				\
-	if (bd->state != BOARD_READY)			\
-		return (0);				\
-
-
-static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count,
-			"%d %s\n", bd->channels[i]->ch_portnum,
-			bd->channels[i]->ch_open_count ? "Open" : "Closed");
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
-
-
-static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count +=  snprintf(buf + count, PAGE_SIZE - count,
-			"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
-
-
-static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		if (bd->channels[i]->ch_open_count) {
-			count += snprintf(buf + count, PAGE_SIZE - count,
-				"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
-				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-		} else {
-			count += snprintf(buf + count, PAGE_SIZE - count,
-				"%d\n", bd->channels[i]->ch_portnum);
-		}
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
-
-
-static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
-
-
-static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
-
-
-static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
-
-
-static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
-
-
-static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
-
-
-static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
-
-
-static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
-
-
-/* this function creates the sys files that will export each signal status
- * to sysfs each value will be put in a separate filename
- */
-void dgap_create_ports_sysfiles(struct board_t *bd)
-{
-	int rc = 0;
-
-	dev_set_drvdata(&bd->pdev->dev, bd);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-	if (rc) {
-		printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
-	}
-}
-
-
-/* removes all the sys files created for that port */
-void dgap_remove_ports_sysfiles(struct board_t *bd)
-{
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-}
-
-
-static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
-}
-static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
-
-
-static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
-}
-static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
-
-
-static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	if (ch->ch_open_count) {
-		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
-			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-	}
-	return 0;
-}
-static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
-
-
-static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
-}
-static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
-
-
-static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
-}
-static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
-
-
-static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
-}
-static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
-
-
-static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
-}
-static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
-
-
-static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
-}
-static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
-
-
-static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
-}
-static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
-
-
-static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
-}
-static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
-
-
-static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int	cn;
-	int	bn;
-	struct cnode *cptr = NULL;
-	int found = FALSE;
-	int ncount = 0;
-	int starto = 0;
-	int i = 0;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-        bn = bd->boardnum;
-	cn = ch->ch_portnum;
-
-	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-		if ((cptr->type == BNODE) &&
-		    ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-		     (cptr->u.board.type == PAPORT8))) {
-
-				found = TRUE;
-				if (cptr->u.board.v_start)
-					starto = cptr->u.board.start;
-				else
-					starto = 1;
-		}
-
-		if (cptr->type == TNODE && found == TRUE) {
-			char *ptr1;
-			if (strstr(cptr->u.ttyname, "tty")) {
-				ptr1 = cptr->u.ttyname;
-				ptr1 += 3;
-			}
-			else {
-				ptr1 = cptr->u.ttyname;
-			}
-
-			for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
-				if (cn == i) {
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						ptr1, i + starto);
-				}
-			}
-		}
-
-		if (cptr->type == CNODE) {
-
-			for (i = 0; i < cptr->u.conc.nport; i++) {
-				if (cn == (i + ncount)) {
-
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						cptr->u.conc.id,
-						i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
-				}
-			}
-
-			ncount += cptr->u.conc.nport;
-		}
-
-		if (cptr->type == MNODE) {
-
-			for (i = 0; i < cptr->u.module.nport; i++) {
-				if (cn == (i + ncount)) {
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						cptr->u.module.id,
-						i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
-				}
-			}
-
-			ncount += cptr->u.module.nport;
-
-		}
-	}
-
-	return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
-		(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
-
-}
-static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
-
-
-static struct attribute *dgap_sysfs_tty_entries[] = {
-	&dev_attr_state.attr,
-	&dev_attr_baud.attr,
-	&dev_attr_msignals.attr,
-	&dev_attr_iflag.attr,
-	&dev_attr_cflag.attr,
-	&dev_attr_oflag.attr,
-	&dev_attr_lflag.attr,
-	&dev_attr_digi_flag.attr,
-	&dev_attr_rxcount.attr,
-	&dev_attr_txcount.attr,
-	&dev_attr_custom_name.attr,
-	NULL
-};
-
-
-static struct attribute_group dgap_tty_attribute_group = {
-	.name = NULL,
-	.attrs = dgap_sysfs_tty_entries,
-};
-
-
-
-
-void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
-{
-	int ret;
-
-	ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
-	if (ret) {
-		printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
-		sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-		return;
-	}
-
-	dev_set_drvdata(c, un);
-
-}
-
-
-void dgap_remove_tty_sysfs(struct device *c)
-{
-	sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-}
diff --git a/drivers/staging/dgap/dgap_sysfs.h b/drivers/staging/dgap/dgap_sysfs.h
deleted file mode 100644
index dde690eec5cf..000000000000
--- a/drivers/staging/dgap/dgap_sysfs.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_SYSFS_H
-#define __DGAP_SYSFS_H
-
-#include "dgap_driver.h"
-
-#include <linux/device.h>
-
-struct board_t;
-struct channel_t;
-struct un_t;
-struct pci_driver;
-struct class_device;
-
-extern void dgap_create_ports_sysfiles(struct board_t *bd); 
-extern void dgap_remove_ports_sysfiles(struct board_t *bd);
-
-extern void dgap_create_driver_sysfiles(struct pci_driver *);
-extern void dgap_remove_driver_sysfiles(struct pci_driver *);
-
-extern int dgap_tty_class_init(void);
-extern int dgap_tty_class_destroy(void);
-
-extern void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
-extern void dgap_remove_tty_sysfs(struct device *c);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_trace.c b/drivers/staging/dgap/dgap_trace.c
deleted file mode 100644
index a53db9e0a577..000000000000
--- a/drivers/staging/dgap/dgap_trace.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- */
-
-/* $Id: dgap_trace.c,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>	/* For jiffies, task states */
-#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
-#include <linux/vmalloc.h>
-
-#include "dgap_driver.h"
-#include "dgap_trace.h"
-
-#define TRC_TO_CONSOLE 1
-
-/* file level globals */
-static char *dgap_trcbuf;		/* the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static int dgap_trcbufi = 0;		/* index of the tilde at the end of */
-#endif
-
-extern int dgap_trcbuf_size;		/* size of the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static DEFINE_SPINLOCK(dgap_tracef_lock);
-#endif
-
-#if 0
-
-#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
-void dgap_tracef(const char *fmt, ...)
-{
-	return;
-}
-
-#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-void dgap_tracef(const char *fmt, ...)
-{
-	va_list	         ap;
-	char  	         buf[TRC_MAXMSG+1];
-	size_t		 lenbuf;
-	int		 i;
-	static int	 failed = FALSE;
-# if defined(TRC_TO_KMEM)
-	unsigned long	 flags;
-#endif
-
-	if(failed)
-		return;
-# if defined(TRC_TO_KMEM)
-	DGAP_LOCK(dgap_tracef_lock, flags);
-#endif
-
-	/* Format buf using fmt and arguments contained in ap. */
-	va_start(ap, fmt);
-	i = vsprintf(buf, fmt,  ap);
-	va_end(ap);
-	lenbuf = strlen(buf);
-
-# if defined(TRC_TO_KMEM)
-	{
-		static int	 initd=0;
-
-		/*
-		 * Now, in addition to (or instead of) printing this stuff out
-		 * (which is a buffered operation), also tuck it away into a
-		 * corner of memory which can be examined post-crash in kdb.
-		 */
-		if (!initd) {
-			dgap_trcbuf = (char *) vmalloc(dgap_trcbuf_size);
-			if(!dgap_trcbuf) {
-				failed = TRUE;
-				printk("dgap: tracing init failed!\n");
-				return;
-			}
-
-			memset(dgap_trcbuf, '\0',  dgap_trcbuf_size);
-			dgap_trcbufi = 0;
-			initd++;
-
-			printk("dgap: tracing enabled - " TRC_DTRC
-				" 0x%lx 0x%x\n",
-				(unsigned long)dgap_trcbuf,
-				dgap_trcbuf_size);
-		}
-
-#  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
-		/*
-		 * This is the less CPU-intensive way to do things.  We simply
-		 * wrap around before we fall off the end of the buffer.  A
-		 * tilde (~) demarcates the current end of the trace.
-		 *
-		 * This method should be used if you are concerned about race
-		 * conditions as it is less likely to affect the timing of
-		 * things.
-		 */
-
-		if (dgap_trcbufi + lenbuf >= dgap_trcbuf_size) {
-			/* We are wrapping, so wipe out the last tilde. */
-			dgap_trcbuf[dgap_trcbufi] = '\0';
-			/* put the new string at the beginning of the buffer */
-			dgap_trcbufi = 0;
-		}
-
-		strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-		dgap_trcbufi += lenbuf;
-		dgap_trcbuf[dgap_trcbufi] = '~';
-
-#  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
-		/*
-		 * This is the more CPU-intensive way to do things.  If we
-		 * venture into the last 1/8 of the buffer, we shift the
-		 * last 7/8 of the buffer forward, wiping out the first 1/8.
-		 * Advantage: No wrap-around, only truncation from the
-		 * beginning.
-		 *
-		 * This method should not be used if you are concerned about
-		 * timing changes affecting the behaviour of the driver (ie,
-		 * race conditions).
-		 */
-		strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-		dgap_trcbufi += lenbuf;
-		dgap_trcbuf[dgap_trcbufi] = '~';
-		dgap_trcbuf[dgap_trcbufi+1] = '\0';
-
-		/* If we're near the end of the trace buffer... */
-		if (dgap_trcbufi > (dgap_trcbuf_size/8)*7) {
-			/* Wipe out the first eighth to make some more room. */
-			strcpy(dgap_trcbuf, &dgap_trcbuf[dgap_trcbuf_size/8]);
-			dgap_trcbufi = strlen(dgap_trcbuf)-1;
-			/* Plop overflow message at the top of the buffer. */
-			bcopy(TRC_OVERFLOW, dgap_trcbuf, strlen(TRC_OVERFLOW));
-		}
-#  else
-#   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
-#  endif
-	}
-	DGAP_UNLOCK(dgap_tracef_lock, flags);
-
-# endif /* defined(TRC_TO_KMEM) */
-}
-
-#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-#endif
-
-/*
- * dgap_tracer_free()
- *
- *
- */
-void dgap_tracer_free(void)
-{
-	if(dgap_trcbuf)
-		vfree(dgap_trcbuf);
-}
diff --git a/drivers/staging/dgap/dgap_trace.h b/drivers/staging/dgap/dgap_trace.h
deleted file mode 100644
index b21f46198e71..000000000000
--- a/drivers/staging/dgap/dgap_trace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *****************************************************************************
- * Header file for dgap_trace.c
- *
- * $Id: dgap_trace.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- */
-
-#ifndef __DGAP_TRACE_H
-#define __DGAP_TRACE_H
-
-#include "dgap_driver.h"
-
-void dgap_tracef(const char *fmt, ...);
-void dgap_tracer_free(void);
-
-#endif
-
diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c
deleted file mode 100644
index 39fb4dfb8b7e..000000000000
--- a/drivers/staging/dgap/dgap_tty.c
+++ /dev/null
@@ -1,3580 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- */
-
-/************************************************************************
- *
- * This file implements the tty driver functionality for the
- * FEP5 based product lines.
- *
- ************************************************************************
- *
- * $Id: dgap_tty.c,v 1.3 2011/06/23 12:11:31 markh Exp $
- */
-
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/sched.h>	/* For jiffies, task states */
-#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/delay.h>	/* For udelay */
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <asm/io.h>		/* For read[bwl]/write[bwl] */
-#include <linux/pci.h>
-
-#include "dgap_driver.h"
-#include "dgap_tty.h"
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-#include "dgap_sysfs.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
-#define init_MUTEX(sem)         sema_init(sem, 1)
-#define DECLARE_MUTEX(name)     \
-        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-#endif
-
-/*
- * internal variables
- */
-static struct board_t	*dgap_BoardsByMajor[256];
-static uchar		*dgap_TmpWriteBuf = NULL;
-static DECLARE_MUTEX(dgap_TmpWriteSem);
-
-/*
- * Default transparent print information.
- */
-static struct digi_t dgap_digi_init = {
-	.digi_flags =	DIGI_COOK,	/* Flags			*/
-	.digi_maxcps =	100,		/* Max CPS			*/
-	.digi_maxchar =	50,		/* Max chars in print queue	*/
-	.digi_bufsize =	100,		/* Printer buffer size		*/
-	.digi_onlen =	4,		/* size of printer on string	*/
-	.digi_offlen =	4,		/* size of printer off string	*/
-	.digi_onstr =	"\033[5i",	/* ANSI printer on string ]	*/
-	.digi_offstr =	"\033[4i",	/* ANSI printer off string ]	*/
-	.digi_term =	"ansi"		/* default terminal type	*/
-};
-
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.
- *
- * This defines a raw port at 9600 baud, 8 data bits, no parity,
- * 1 stop bit.
- */
-
-static struct ktermios DgapDefaultTermios =
-{
-	.c_iflag =	(DEFAULT_IFLAGS),	/* iflags */
-	.c_oflag =	(DEFAULT_OFLAGS),	/* oflags */
-	.c_cflag =	(DEFAULT_CFLAGS),	/* cflags */
-	.c_lflag =	(DEFAULT_LFLAGS),	/* lflags */
-	.c_cc =		INIT_C_CC,
-	.c_line = 	0,
-};
-
-/* 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, struct channel_t *ch);
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_write_room(struct tty_struct* tty);
-static int dgap_tty_chars_in_buffer(struct tty_struct* tty);
-static void dgap_tty_start(struct tty_struct *tty);
-static void dgap_tty_stop(struct tty_struct *tty);
-static void dgap_tty_throttle(struct tty_struct *tty);
-static void dgap_tty_unthrottle(struct tty_struct *tty);
-static void dgap_tty_flush_chars(struct tty_struct *tty);
-static void dgap_tty_flush_buffer(struct tty_struct *tty);
-static void dgap_tty_hangup(struct tty_struct *tty);
-static int dgap_wait_for_drain(struct tty_struct *tty);
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
-static int dgap_tty_tiocmget(struct tty_struct *tty);
-static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-#else
-static int dgap_tty_tiocmget(struct tty_struct *tty, struct file *file);
-static int dgap_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
-#endif
-static int dgap_tty_send_break(struct tty_struct *tty, int msec);
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
-static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
-
-static const struct tty_operations dgap_tty_ops = {
-	.open = dgap_tty_open,
-	.close = dgap_tty_close,
-	.write = dgap_tty_write,
-	.write_room = dgap_tty_write_room,
-	.flush_buffer = dgap_tty_flush_buffer,
-	.chars_in_buffer = dgap_tty_chars_in_buffer,
-	.flush_chars = dgap_tty_flush_chars,
-	.ioctl = dgap_tty_ioctl,
-	.set_termios = dgap_tty_set_termios,
-	.stop = dgap_tty_stop,
-	.start = dgap_tty_start,
-	.throttle = dgap_tty_throttle,
-	.unthrottle = dgap_tty_unthrottle,
-	.hangup = dgap_tty_hangup,
-	.put_char = dgap_tty_put_char,
-	.tiocmget = dgap_tty_tiocmget,
-	.tiocmset = dgap_tty_tiocmset,
-	.break_ctl = dgap_tty_send_break,
-	.wait_until_sent = dgap_tty_wait_until_sent,
-	.send_xchar = dgap_tty_send_xchar
-};
-
-
-
-
-
-/************************************************************************
- *
- * TTY Initialization/Cleanup Functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_preinit()
- *
- * Initialize any global tty related data before we download any boards.
- */
-int dgap_tty_preinit(void)
-{
-	unsigned long flags;
-
-	DGAP_LOCK(dgap_global_lock, flags);
-
-	/*
-	 * Allocate a buffer for doing the copy from user space to
-	 * kernel space in dgap_input().  We only use one buffer and
-	 * control access to it with a semaphore.  If we are paging, we
-	 * are already in trouble so one buffer won't hurt much anyway.
-	 */
-	dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
-
-	if (!dgap_TmpWriteBuf) {
-		DGAP_UNLOCK(dgap_global_lock, flags);
-		DPR_INIT(("unable to allocate tmp write buf"));
-		return (-ENOMEM);
-	}
-
-        DGAP_UNLOCK(dgap_global_lock, flags);
-        return(0);
-}
-
-
-/*
- * dgap_tty_register()
- *
- * Init the tty subsystem for this board.
- */
-int dgap_tty_register(struct board_t *brd)
-{
-	int rc = 0;
-
-	DPR_INIT(("tty_register start"));
-
-	brd->SerialDriver = alloc_tty_driver(MAXPORTS);
-
-	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
-	brd->SerialDriver->name = brd->SerialName;
-	brd->SerialDriver->name_base = 0;
-	brd->SerialDriver->major = 0;
-	brd->SerialDriver->minor_start = 0;
-	brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
-	brd->SerialDriver->init_termios = DgapDefaultTermios;
-	brd->SerialDriver->driver_name = DRVSTR;
-	brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs */
-	brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!brd->SerialDriver->ttys)
-		return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-	brd->SerialDriver->refcount = brd->TtyRefCnt;
-#endif
-
-	/*
-	 * Entry points for driver.  Called by the kernel from
-	 * tty_io.c and n_tty.c.
-	 */
-	tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
-
-	/*
-	 * If we're doing transparent print, we have to do all of the above
-	 * again, separately so we don't get the LD confused about what major
-	 * we are when we get into the dgap_tty_open() routine.
-	 */
-	brd->PrintDriver = alloc_tty_driver(MAXPORTS);
-
-	snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
-	brd->PrintDriver->name = brd->PrintName;
-	brd->PrintDriver->name_base = 0;
-	brd->PrintDriver->major = 0;
-	brd->PrintDriver->minor_start = 0;
-	brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
-	brd->PrintDriver->init_termios = DgapDefaultTermios;
-	brd->PrintDriver->driver_name = DRVSTR;
-	brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs */
-	brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!brd->PrintDriver->ttys)
-		return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-	brd->PrintDriver->refcount = brd->TtyRefCnt;
-#endif
-
-	/*
-	 * Entry points for driver.  Called by the kernel from
-	 * tty_io.c and n_tty.c.
-	 */
-	tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
-
-	if (!brd->dgap_Major_Serial_Registered) {
-		/* Register tty devices */
-		rc = tty_register_driver(brd->SerialDriver);
-		if (rc < 0) {
-			APR(("Can't register tty device (%d)\n", rc));
-			return(rc);
-		}
-		brd->dgap_Major_Serial_Registered = TRUE;
-		dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
-		brd->dgap_Serial_Major = brd->SerialDriver->major;
-	}
-
-	if (!brd->dgap_Major_TransparentPrint_Registered) {
-		/* Register Transparent Print devices */
- 		rc = tty_register_driver(brd->PrintDriver);
-		if (rc < 0) {
-			APR(("Can't register Transparent Print device (%d)\n", rc));
-			return(rc);
-		}
-		brd->dgap_Major_TransparentPrint_Registered = TRUE;
-		dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
-		brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
-	}
-
-	DPR_INIT(("DGAP REGISTER TTY: MAJORS: %d %d\n", brd->SerialDriver->major,
-		brd->PrintDriver->major));
-
-	return (rc);
-}
-
-
-/*
- * dgap_tty_init()
- *
- * Init the tty subsystem.  Called once per board after board has been
- * downloaded and init'ed.
- */
-int dgap_tty_init(struct board_t *brd)
-{
-	int i;
-	int tlw;
-	uint true_count = 0;
-	uchar *vaddr;
-	uchar modem = 0;
-	struct channel_t *ch;
-	struct bs_t *bs;
-	struct cm_t *cm;
-
-	if (!brd)
-		return (-ENXIO);
-
-	DPR_INIT(("dgap_tty_init start\n"));
-
-	/*
-	 * Initialize board structure elements.
-	 */
-
-	vaddr = brd->re_map_membase;
-	true_count = readw((vaddr + NCHAN));
-
-	brd->nasync = dgap_config_get_number_of_ports(brd);
-
-	if (!brd->nasync) {
-		brd->nasync = brd->maxports;
-	}
-
-	if (brd->nasync > brd->maxports) {
-		brd->nasync = brd->maxports;
-	}
-
-	if (true_count != brd->nasync) {
-		if ((brd->type == PPCM) && (true_count == 64)) {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-				brd->name, brd->nasync, true_count));
-		}
-		else if ((brd->type == PPCM) && (true_count == 0)) {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-				brd->name, brd->nasync, true_count));
-		}
-		else {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\n",
-				brd->name, brd->nasync, true_count));
-		}
-
-		brd->nasync = true_count;
-
-		/* If no ports, don't bother going any further */
-		if (!brd->nasync) {
-			brd->state = BOARD_FAILED;
-			brd->dpastatus = BD_NOFEP;
-			return(-ENXIO);
-		}
-	}
-
-	/*
-	 * Allocate channel memory that might not have been allocated
-	 * when the driver was first loaded.
-	 */
-	for (i = 0; i < brd->nasync; i++) {
-		if (!brd->channels[i]) {
-			brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
-			if (!brd->channels[i]) {
-				DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
-				    __FILE__, __LINE__));
-			}
-		}
-	}
-
-	ch = brd->channels[0];
-	vaddr = brd->re_map_membase;
-
-	bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
-	cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
-
-	brd->bd_bs = bs;
-
-	/* Set up channel variables */
-	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
-
-		if (!brd->channels[i])
-			continue;
-
-		DGAP_SPINLOCK_INIT(ch->ch_lock);
-
-		/* Store all our magic numbers */
-		ch->magic = DGAP_CHANNEL_MAGIC;
-		ch->ch_tun.magic = DGAP_UNIT_MAGIC;
-		ch->ch_tun.un_type = DGAP_SERIAL;
-		ch->ch_tun.un_ch = ch;
-		ch->ch_tun.un_dev = i;
-
-		ch->ch_pun.magic = DGAP_UNIT_MAGIC;
-		ch->ch_pun.un_type = DGAP_PRINT;
-		ch->ch_pun.un_ch = ch;
-		ch->ch_pun.un_dev = i;
-
-		ch->ch_vaddr = vaddr;
-		ch->ch_bs = bs;
-		ch->ch_cm = cm;
-		ch->ch_bd = brd;
-		ch->ch_portnum = i;
-		ch->ch_digi = dgap_digi_init;
-
-		/*
-		 * Set up digi dsr and dcd bits based on altpin flag.
-		 */
-		if (dgap_config_get_altpin(brd)) {
-			ch->ch_dsr	= DM_CD;
-			ch->ch_cd	= DM_DSR;
-			ch->ch_digi.digi_flags |= DIGI_ALTPIN;
-		}
-		else {
-			ch->ch_cd	= DM_CD;
-			ch->ch_dsr	= DM_DSR;
-		}
-
-		ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
-		ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
-		ch->ch_tx_win = 0;
-		ch->ch_rx_win = 0;
-		ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
-		ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
-		ch->ch_tstart = 0;
-		ch->ch_rstart = 0;
-
-		/* .25 second delay */
-		ch->ch_close_delay = 250;
-
-		/*
-		 * Set queue water marks, interrupt mask,
-		 * and general tty parameters.
-		 */
-		ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
-
-		dgap_cmdw(ch, STLOW, tlw, 0);
-
-		dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
-
-		dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
-
-		ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
-
-		init_waitqueue_head(&ch->ch_flags_wait);
-		init_waitqueue_head(&ch->ch_tun.un_flags_wait);
-		init_waitqueue_head(&ch->ch_pun.un_flags_wait);
-		init_waitqueue_head(&ch->ch_sniff_wait);
-
-		/* Turn on all modem interrupts for now */
-		modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
-		writeb(modem, &(ch->ch_bs->m_int));
-
-		/*
-		 * Set edelay to 0 if interrupts are turned on,
-		 * otherwise set edelay to the usual 100.
-		 */
-		if (brd->intr_used)
-			writew(0, &(ch->ch_bs->edelay));
-		else
-			writew(100, &(ch->ch_bs->edelay));
-
-		writeb(1, &(ch->ch_bs->idata));
-	}
-
-
-	DPR_INIT(("dgap_tty_init finish\n"));
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_post_uninit()
- *
- * UnInitialize any global tty related data.
- */
-void dgap_tty_post_uninit(void)
-{
-	kfree(dgap_TmpWriteBuf);
-	dgap_TmpWriteBuf = NULL;
-}
-
-
-/*
- * dgap_tty_uninit()
- *
- * Uninitialize the TTY portion of this driver.  Free all memory and
- * resources.
- */
-void dgap_tty_uninit(struct board_t *brd)
-{
-	int i = 0;
-
-	if (brd->dgap_Major_Serial_Registered) {
-		dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
-		brd->dgap_Serial_Major = 0;
-		for (i = 0; i < brd->nasync; i++) {
-			dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
-			tty_unregister_device(brd->SerialDriver, i);
-		}
-		tty_unregister_driver(brd->SerialDriver);
-		kfree(brd->SerialDriver->ttys);
-		brd->SerialDriver->ttys = NULL;
-		put_tty_driver(brd->SerialDriver);
-		brd->dgap_Major_Serial_Registered = FALSE;
-	}
-
-	if (brd->dgap_Major_TransparentPrint_Registered) {
-		dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
-		brd->dgap_TransparentPrint_Major = 0;
-		for (i = 0; i < brd->nasync; i++) {
-			dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
-			tty_unregister_device(brd->PrintDriver, i);
-		}
-		tty_unregister_driver(brd->PrintDriver);
-		kfree(brd->PrintDriver->ttys);
-		brd->PrintDriver->ttys = NULL;
-		put_tty_driver(brd->PrintDriver);
-		brd->dgap_Major_TransparentPrint_Registered = FALSE;
-	}
-}
-
-
-#define TMPBUFLEN (1024)
-
-/*
- * 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)
-{
-	struct timeval tv;
-	int n;
-	int r;
-	int nbuf;
-	int i;
-	int tmpbuflen;
-	char tmpbuf[TMPBUFLEN];
-	char *p = tmpbuf;
-	int too_much_data;
-
-	/* Leave if sniff not open */
-	if (!(ch->ch_sniff_flags & SNIFF_OPEN))
-		return;
-
-	do_gettimeofday(&tv);
-
-	/* Create our header for data dump */
-	p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
-	tmpbuflen = p - tmpbuf;
-
-	do {
-		too_much_data = 0;
-
-		for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
-			p += sprintf(p, "%02x ", *buf);
-			buf++;
-			tmpbuflen = p - tmpbuf;
-		}
-
-		if (tmpbuflen < (TMPBUFLEN - 4)) {
-			if (i > 0)
-				p += sprintf(p - 1, "%s\n", ">");
-			else
-				p += sprintf(p, "%s\n", ">");
-		} else {
-			too_much_data = 1;
-			len -= i;
-		}
-
-		nbuf = strlen(tmpbuf);
-		p = tmpbuf;
-
-		/*
-		 *  Loop while data remains.
-		 */
-		while (nbuf > 0 && ch->ch_sniff_buf) {
-			/*
-			 *  Determine the amount of available space left in the
-			 *  buffer.  If there's none, wait until some appears.
-			 */
-			n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
-
-			/*
-			 * If there is no space left to write to in our sniff buffer,
-			 * we have no choice but to drop the data.
-			 * We *cannot* sleep here waiting for space, because this
-			 * function was probably called by the interrupt/timer routines!
-			 */
-			if (n == 0) {
-				return;
-			}
-
-			/*
-			 * Copy as much data as will fit.
-			 */
-
-			if (n > nbuf)
-				n = nbuf;
-
-			r = SNIFF_MAX - ch->ch_sniff_in;
-
-			if (r <= n) {
-				memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
-
-				n -= r;
-				ch->ch_sniff_in = 0;
-				p += r;
-				nbuf -= r;
-			}
-
-			memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
-
-			ch->ch_sniff_in += n;
-			p += n;
-			nbuf -= n;
-
-			/*
-			 *  Wakeup any thread waiting for data
-			 */
-			if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
-				ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
-				wake_up_interruptible(&ch->ch_sniff_wait);
-			}
-		}
-
-		/*
-		 * If the user sent us too much data to push into our tmpbuf,
-		 * we need to keep looping around on all the data.
-		 */
-		if (too_much_data) {
-			p = tmpbuf;
-			tmpbuflen = 0;
-		}
-
-	} while (too_much_data);
-}
-
-
-/*=======================================================================
- *
- *      dgap_input - Process received data.
- *
- *              ch      - Pointer to channel structure.
- *
- *=======================================================================*/
-
-void dgap_input(struct channel_t *ch)
-{
-	struct board_t *bd;
-	struct bs_t	*bs;
-	struct tty_struct *tp;
-	struct tty_ldisc *ld;
-	uint	rmask;
-	uint	head;
-	uint	tail;
-	int	data_len;
-	ulong	lock_flags;
-	ulong   lock_flags2;
-	int flip_len;
-	int len = 0;
-	int n = 0;
-	uchar *buf;
-	uchar tmpchar;
-	int s = 0;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	tp = ch->ch_tun.un_tty;
-
-	bs  = ch->ch_bs;
-	if (!bs) {
-		return;
-	}
-
-	bd = ch->ch_bd;
-	if(!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_READ(("dgap_input start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/*
-	 *      Figure the number of characters in the buffer.
-	 *      Exit immediately if none.
-	 */
-
-	rmask = ch->ch_rsize - 1;
-
-	head = readw(&(bs->rx_head));
-	head &= rmask;
-	tail = readw(&(bs->rx_tail));
-	tail &= rmask;
-
-	data_len = (head - tail) & rmask;
-
-	if (data_len == 0) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("No data on port %d\n", ch->ch_portnum));
-		return;
-	}
-
-	/*
-	 * If the device is not open, or CREAD is off, flush
-	 * input data and return immediately.
-	 */
-	if ((bd->state != BOARD_READY) || !tp  || (tp->magic != TTY_MAGIC) ||
-            !(ch->ch_tun.un_flags & UN_ISOPEN) || !(tp->termios.c_cflag & CREAD) ||
-	    (ch->ch_tun.un_flags & UN_CLOSING)) {
-
-		DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
-		DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n",
-			tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags));
-		writew(head, &(bs->rx_tail));
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return;
-	}
-
-	/*
-	 * If we are throttled, simply don't read any data.
-	 */
-	if (ch->ch_flags & CH_RXBLOCK) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n",
-			ch->ch_portnum, head, tail));
-		return;
-	}
-
-	/*
-	 *      Ignore oruns.
-	 */
-	tmpchar = readb(&(bs->orun));
-	if (tmpchar) {
-		ch->ch_err_overrun++;
-		writeb(0, &(bs->orun));
-	}
-
-	DPR_READ(("dgap_input start 2\n"));
-
-	/* Decide how much data we can send into the tty layer */
-	flip_len = TTY_FLIPBUF_SIZE;
-
-	/* Chop down the length, if needed */
-	len = min(data_len, flip_len);
-	len = min(len, (N_TTY_BUF_SIZE - 1));
-
-	ld = tty_ldisc_ref(tp);
-
-#ifdef TTY_DONT_FLIP
-	/*
-	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
-	 * like the ld doesn't have any space to put the data right now.
-	 */
-	if (test_bit(TTY_DONT_FLIP, &tp->flags))
-		len = 0;
-#endif
-
-	/*
-	 * If we were unable to get a reference to the ld,
-	 * don't flush our buffer, and act like the ld doesn't
-	 * have any space to put the data right now.
-	 */
-	if (!ld) {
-		len = 0;
-	} else {
-		/*
-		 * If ld doesn't have a pointer to a receive_buf function,
-		 * flush the data, then act like the ld doesn't have any
-		 * space to put the data right now.
-		 */
-		if (!ld->ops->receive_buf) {
-			writew(head, &(bs->rx_tail));
-			len = 0;
-		}
-	}
-
-	if (len <= 0) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("dgap_input 1 - finish\n"));
-		if (ld)
-			tty_ldisc_deref(ld);
-		return;
-	}
-
-	buf = ch->ch_bd->flipbuf;
-	n = len;
-
-	/*
-	 * n now contains the most amount of data we can copy,
-	 * bounded either by our buffer size or the amount
-	 * of data the card actually has pending...
-	 */
-	while (n) {
-
-		s = ((head >= tail) ? head : ch->ch_rsize) - tail;
-		s = min(s, n);
-
-		if (s <= 0)
-			break;
-
-		memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
-		dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
-
-		tail += s;
-		buf += s;
-
-		n -= s;
-		/* Flip queue if needed */
-		tail &= rmask;
-	}
-
-	writew(tail, &(bs->rx_tail));
-	writeb(1, &(bs->idata));
-	ch->ch_rxcount += len;
-
-	/*
-	 * If we are completely raw, we don't need to go through a lot
-	 * of the tty layers that exist.
-	 * In this case, we take the shortest and fastest route we
-	 * can to relay the data to the user.
-	 *
-	 * On the other hand, if we are not raw, we need to go through
-	 * the tty layer, which has its API more well defined.
-	 */
-	if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
-		dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
-
-		len = tty_buffer_request_room(tp->port, len);
-		tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
-			ch->ch_bd->flipflagbuf, len);
-	}
-	else {
-		len = tty_buffer_request_room(tp->port, len);
-		tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
-	}
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	/* Tell the tty layer its okay to "eat" the data now */
-	tty_flip_buffer_push(tp->port);
-
-	if (ld)
-		tty_ldisc_deref(ld);
-
-	DPR_READ(("dgap_input - finish\n"));
-}
-
-
-/************************************************************************
- * Determines when CARRIER changes state and takes appropriate
- * action.
- ************************************************************************/
-void dgap_carrier(struct channel_t *ch)
-{
-	struct board_t *bd;
-
-        int virt_carrier = 0;
-        int phys_carrier = 0;
-
-	DPR_CARR(("dgap_carrier called...\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	/* Make sure altpin is always set correctly */
-	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
-		ch->ch_dsr      = DM_CD;
-		ch->ch_cd       = DM_DSR;
-	}
-	else {
-		ch->ch_dsr      = DM_DSR;
-		ch->ch_cd       = DM_CD;
-	}
-
-	if (ch->ch_mistat & D_CD(ch)) {
-		DPR_CARR(("mistat: %x  D_CD: %x\n", ch->ch_mistat, D_CD(ch)));
-		phys_carrier = 1;
-	}
-
-	if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
-		virt_carrier = 1;
-	}
-
-	if (ch->ch_c_cflag & CLOCAL) {
-		virt_carrier = 1;
-	}
-
-
-	DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
-
-	/*
-	 * Test for a VIRTUAL carrier transition to HIGH.
-	 */
-	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
-
-		/*
-		 * When carrier rises, wake any threads waiting
-		 * for carrier in the open routine.
-		 */
-
-		DPR_CARR(("carrier: virt DCD rose\n"));
-
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-	}
-
-	/*
-	 * Test for a PHYSICAL carrier transition to HIGH.
-	 */
-	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
-
-		/*
-		 * When carrier rises, wake any threads waiting
-		 * for carrier in the open routine.
-		 */
-
-		DPR_CARR(("carrier: physical DCD rose\n"));
-
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-	}
-
-	/*
-	 *  Test for a PHYSICAL transition to low, so long as we aren't
-	 *  currently ignoring physical transitions (which is what "virtual
-	 *  carrier" indicates).
-	 *
-	 *  The transition of the virtual carrier to low really doesn't
-	 *  matter... it really only means "ignore carrier state", not
-	 *  "make pretend that carrier is there".
-	 */
-	if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
-	    (phys_carrier == 0))
-	{
-
-		/*
-		 *   When carrier drops:
-		 *
-		 *   Drop carrier on all open units.
-		 *
-		 *   Flush queues, waking up any task waiting in the
-		 *   line discipline.
-		 *
-		 *   Send a hangup to the control terminal.
-		 *
-		 *   Enable all select calls.
-		 */
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-
-		if (ch->ch_tun.un_open_count > 0) {
-			DPR_CARR(("Sending tty hangup\n"));
-			tty_hangup(ch->ch_tun.un_tty);
-		}
-
-		if (ch->ch_pun.un_open_count > 0) {
-			DPR_CARR(("Sending pr hangup\n"));
-			tty_hangup(ch->ch_pun.un_tty);
-		}
-	}
-
-	/*
-	 *  Make sure that our cached values reflect the current reality.
-	 */
-	if (virt_carrier == 1)
-		ch->ch_flags |= CH_FCAR;
-	else
-		ch->ch_flags &= ~CH_FCAR;
-
-	if (phys_carrier == 1)
-		ch->ch_flags |= CH_CD;
-	else
-		ch->ch_flags &= ~CH_CD;
-}
-
-
-/************************************************************************
- *
- * TTY Entry points and helper functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_open()
- *
- */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file)
-{
-	struct board_t	*brd;
-	struct channel_t *ch;
-	struct un_t	*un;
-	struct bs_t	*bs;
-	uint		major = 0;
-	uint		minor = 0;
-	int		rc = 0;
-	ulong		lock_flags;
-	ulong		lock_flags2;
-	u16		head;
-
-	rc = 0;
-
-	major = MAJOR(tty_devnum(tty));
-	minor = MINOR(tty_devnum(tty));
-
-	if (major > 255) {
-		return -ENXIO;
-	}
-
-	/* Get board pointer from our array of majors we have allocated */
-	brd = dgap_BoardsByMajor[major];
-	if (!brd) {
-		return -ENXIO;
-	}
-
-	/*
-	 * If board is not yet up to a state of READY, go to
-	 * sleep waiting for it to happen or they cancel the open.
-	 */
-	rc = wait_event_interruptible(brd->state_wait,
-		(brd->state & BOARD_READY));
-
-	if (rc) {
-		return rc;
-	}
-
-	DGAP_LOCK(brd->bd_lock, lock_flags);
-
-	/* The wait above should guarantee this cannot happen */
-	if (brd->state != BOARD_READY) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/* If opened device is greater than our number of ports, bail. */
-	if (MINOR(tty_devnum(tty)) > brd->nasync) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	ch = brd->channels[minor];
-	if (!ch) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/* Grab channel lock */
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/* Figure out our type */
-	if (major == brd->dgap_Serial_Major) {
-		un = &brd->channels[minor]->ch_tun;
-		un->un_type = DGAP_SERIAL;
-	}
-	else if (major == brd->dgap_TransparentPrint_Major) {
-		un = &brd->channels[minor]->ch_pun;
-		un->un_type = DGAP_PRINT;
-	}
-	else {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		DPR_OPEN(("%d Unknown TYPE!\n", __LINE__));
-		return -ENXIO;
-	}
-
-	/* Store our unit into driver_data, so we always have it available. */
-	tty->driver_data = un;
-
-	DPR_OPEN(("Open called. MAJOR: %d MINOR:%d unit: %p NAME: %s\n",
-		MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), un, brd->name));
-
-	/*
-	 * Error if channel info pointer is NULL.
-	 */
-	bs = ch->ch_bs;
-	if (!bs) {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		DPR_OPEN(("%d BS is 0!\n", __LINE__));
-		return -ENXIO;
-        }
-
-	DPR_OPEN(("%d: tflag=%x  pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags));
-
-	/*
-	 * Initialize tty's
-	 */
-	if (!(un->un_flags & UN_ISOPEN)) {
-		/* Store important variables. */
-		un->un_tty     = tty;
-
-		/* Maybe do something here to the TTY struct as well? */
-	}
-
-	/*
-	 * Initialize if neither terminal or printer is open.
-	 */
-	if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
-
-		DPR_OPEN(("dgap_open: initializing channel in open...\n"));
-
-		ch->ch_mforce = 0;
-		ch->ch_mval = 0;
-
-		/*
-		 * Flush input queue.
-		 */
-		head = readw(&(bs->rx_head));
-		writew(head, &(bs->rx_tail));
-
-		ch->ch_flags = 0;
-		ch->pscan_state = 0;
-		ch->pscan_savechar = 0;
-
-		ch->ch_c_cflag   = tty->termios.c_cflag;
-		ch->ch_c_iflag   = tty->termios.c_iflag;
-		ch->ch_c_oflag   = tty->termios.c_oflag;
-		ch->ch_c_lflag   = tty->termios.c_lflag;
-		ch->ch_startc = tty->termios.c_cc[VSTART];
-		ch->ch_stopc  = tty->termios.c_cc[VSTOP];
-
-		/* TODO: flush our TTY struct here? */
-	}
-
-	dgap_carrier(ch);
-	/*
-	 * Run param in case we changed anything
-	 */
-	dgap_param(tty);
-
-	/*
-	 * follow protocol for opening port
-	 */
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(brd->bd_lock, lock_flags);
-
-	rc = dgap_block_til_ready(tty, file, ch);
-
-	if (!un->un_tty) {
-		return -ENODEV;
-	}
-
-	if (rc) {
-		DPR_OPEN(("dgap_tty_open returning after dgap_block_til_ready "
-			"with %d\n", rc));
-	}
-
-	/* No going back now, increment our unit and channel counters */
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	ch->ch_open_count++;
-	un->un_open_count++;
-	un->un_flags |= (UN_ISOPEN);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_OPEN(("dgap_tty_open finished\n"));
-	return (rc);
-}
-
-
-/*
- * dgap_block_til_ready()
- *
- * Wait for DCD, if needed.
- */
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
-{
-	int retval = 0;
-	struct un_t *un = NULL;
-	ulong   lock_flags;
-	uint	old_flags = 0;
-	int sleep_on_un_flags = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return (-ENXIO);
-	}
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC) {
-		return (-ENXIO);
-	}
-
-	DPR_OPEN(("dgap_block_til_ready - before block.\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	ch->ch_wopen++;
-
-	/* Loop forever */
-	while (1) {
-
-		sleep_on_un_flags = 0;
-
-		/*
-		 * If board has failed somehow during our sleep, bail with error.
-		 */
-		if (ch->ch_bd->state == BOARD_FAILED) {
-			retval = -ENXIO;
-			break;
-		}
-
-		/* If tty was hung up, break out of loop and set error. */
-		if (tty_hung_up_p(file)) {
-			retval = -EAGAIN;
-			break;
-		}
-
-		/*
-		 * If either unit is in the middle of the fragile part of close,
-		 * we just cannot touch the channel safely.
-		 * Go back to sleep, knowing that when the channel can be
-		 * touched safely, the close routine will signal the
-		 * ch_wait_flags to wake us back up.
-		 */
-		if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
-
-			/*
-			 * Our conditions to leave cleanly and happily:
-			 * 1) NONBLOCKING on the tty is set.
-			 * 2) CLOCAL is set.
-			 * 3) DCD (fake or real) is active.
-			 */
-
-			if (file->f_flags & O_NONBLOCK) {
-				break;
-			}
-
-			if (tty->flags & (1 << TTY_IO_ERROR)) {
-				break;
-			}
-
-			if (ch->ch_flags & CH_CD) {
-				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-				break;
-			}
-
-			if (ch->ch_flags & CH_FCAR) {
-				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-				break;
-			}
-		}
-		else {
-			sleep_on_un_flags = 1;
-		}
-
-		/*
-		 * If there is a signal pending, the user probably
-		 * interrupted (ctrl-c) us.
-		 * Leave loop with error set.
-		 */
-		if (signal_pending(current)) {
-			DPR_OPEN(("%d: signal pending...\n", __LINE__));
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		DPR_OPEN(("dgap_block_til_ready - blocking.\n"));
-
-		/*
-		 * Store the flags before we let go of channel lock
-		 */
-		if (sleep_on_un_flags)
-			old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
-		else
-			old_flags = ch->ch_flags;
-
-		/*
-		 * Let go of channel lock before calling schedule.
-		 * Our poller will get any FEP events and wake us up when DCD
-		 * eventually goes active.
-		 */
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		DPR_OPEN(("Going to sleep on %s flags...\n",
-			(sleep_on_un_flags ? "un" : "ch")));
-
-		/*
-		 * Wait for something in the flags to change from the current value.
-		 */
-		if (sleep_on_un_flags) {
-			retval = wait_event_interruptible(un->un_flags_wait,
-				(old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
-		}
-		else {
-			retval = wait_event_interruptible(ch->ch_flags_wait,
-				(old_flags != ch->ch_flags));
-		}
-
-		DPR_OPEN(("After sleep... retval: %x\n", retval));
-
-		/*
-		 * We got woken up for some reason.
-		 * Before looping around, grab our channel lock.
-		 */
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-	}
-
-	ch->ch_wopen--;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_OPEN(("dgap_block_til_ready - after blocking.\n"));
-
-	if (retval) {
-		DPR_OPEN(("dgap_block_til_ready - done. error. retval: %x\n", retval));
-		return(retval);
-	}
-
-	DPR_OPEN(("dgap_block_til_ready - done no error. jiffies: %lu\n", jiffies));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_hangup()
- *
- * Hangup the port.  Like a close, but don't wait for output to drain.
- */
-static void dgap_tty_hangup(struct tty_struct *tty)
-{
-	struct board_t	*bd;
-	struct channel_t *ch;
-	struct un_t	*un;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_CLOSE(("dgap_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n",
-		ch->ch_open_count, un->un_open_count));
-
-	/* flush the transmit queues */
-	dgap_tty_flush_buffer(tty);
-
-	DPR_CLOSE(("dgap_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n",
-		ch->ch_open_count, un->un_open_count));
-}
-
-
-
-/*
- * dgap_tty_close()
- *
- */
-static void dgap_tty_close(struct tty_struct *tty, struct file *file)
-{
-	struct ktermios *ts;
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong lock_flags;
-	int rc = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	ts = &tty->termios;
-
-	DPR_CLOSE(("Close called\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	/*
-	 * Determine if this is the last close or not - and if we agree about
-	 * which type of close it is with the Line Discipline
-	 */
-	if ((tty->count == 1) && (un->un_open_count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  un_open_count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
-		un->un_open_count = 1;
-	}
-
-	if (--un->un_open_count < 0) {
-		APR(("bad serial port open count of %d\n", un->un_open_count));
-		un->un_open_count = 0;
-	}
-
-	ch->ch_open_count--;
-
-	if (ch->ch_open_count && un->un_open_count) {
-		DPR_CLOSE(("dgap_tty_close: not last close ch: %d un:%d\n",
-			ch->ch_open_count, un->un_open_count));
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-                return;
-        }
-
-	/* OK, its the last close on the unit */
-	DPR_CLOSE(("dgap_tty_close - last close on unit procedures\n"));
-
-	un->un_flags |= UN_CLOSING;
-
-	tty->closing = 1;
-
-	/*
-	 * Only officially close channel if count is 0 and
-         * DIGI_PRINTER bit is not set.
-	 */
-	if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
-
-		ch->ch_flags &= ~(CH_RXBLOCK);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/* wait for output to drain */
-		/* This will also return if we take an interrupt */
-
-		DPR_CLOSE(("Calling wait_for_drain\n"));
-		rc = dgap_wait_for_drain(tty);
-		DPR_CLOSE(("After calling wait_for_drain\n"));
-
-		if (rc) {
-			DPR_BASIC(("dgap_tty_close - bad return: %d ", rc));
-		}
-
-		dgap_tty_flush_buffer(tty);
-		tty_ldisc_flush(tty);
-
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-
-		tty->closing = 0;
-
-		/*
-		 * If we have HUPCL set, lower DTR and RTS
-		 */
-		if (ch->ch_c_cflag & HUPCL ) {
-			DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n"));
-			ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
-			dgap_cmdb( ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0 );
-
-			/*
-			 * Go to sleep to ensure RTS/DTR
-			 * have been dropped for modems to see it.
-			 */
-			if (ch->ch_close_delay) {
-				DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n"));
-
-				DGAP_UNLOCK(ch->ch_lock, lock_flags);
-				dgap_ms_sleep(ch->ch_close_delay);
-				DGAP_LOCK(ch->ch_lock, lock_flags);
-
-				DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n"));
-			}
-		}
-
-		ch->pscan_state = 0;
-		ch->pscan_savechar = 0;
-		ch->ch_baud_info = 0;
-
-	}
-
-	/*
-	 * turn off print device when closing print device.
-	 */
-	if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON) ) {
-		dgap_wmove(ch, ch->ch_digi.digi_offstr,
-			(int) ch->ch_digi.digi_offlen);
-		ch->ch_flags &= ~CH_PRON;
-	}
-
-	un->un_tty = NULL;
-	un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
-	tty->driver_data = NULL;
-
-	DPR_CLOSE(("Close. Doing wakeups\n"));
-	wake_up_interruptible(&ch->ch_flags_wait);
-	wake_up_interruptible(&un->un_flags_wait);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-        DPR_BASIC(("dgap_tty_close - complete\n"));
-}
-
-
-/*
- * dgap_tty_chars_in_buffer()
- *
- * Return number of characters that have not been transmitted yet.
- *
- * This routine is used by the line discipline to determine if there
- * is data waiting to be transmitted/drained/flushed or not.
- */
-static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct board_t *bd = NULL;
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	uchar tbusy;
-	uint chars = 0;
-	u16 thead, ttail, tmask, chead, ctail;
-	ulong   lock_flags = 0;
-	ulong   lock_flags2 = 0;
-
-	if (tty == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return (0);
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	tmask = (ch->ch_tsize - 1);
-
-	/* Get Transmit queue pointers */
-	thead = readw(&(bs->tx_head)) & tmask;
-	ttail = readw(&(bs->tx_tail)) & tmask;
-
-	/* Get tbusy flag */
-	tbusy = readb(&(bs->tbusy));
-
-	/* Get Command queue pointers */
-	chead = readw(&(ch->ch_cm->cm_head));
-	ctail = readw(&(ch->ch_cm->cm_tail));
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	/*
-	 * The only way we know for sure if there is no pending
-	 * data left to be transferred, is if:
-	 * 1) Transmit head and tail are equal (empty).
-	 * 2) Command queue head and tail are equal (empty).
-	 * 3) The "TBUSY" flag is 0. (Transmitter not busy).
- 	 */
-
-	if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
-		chars = 0;
-	}
-	else {
-		if (thead >= ttail)
-			chars = thead - ttail;
-		else
-			chars = thead - ttail + ch->ch_tsize;
-		/*
-		 * Fudge factor here.
-		 * If chars is zero, we know that the command queue had
-		 * something in it or tbusy was set.  Because we cannot
-		 * be sure if there is still some data to be transmitted,
-		 * lets lie, and tell ld we have 1 byte left.
-		 */
-		if (chars == 0) {
-			/*
-			 * If TBUSY is still set, and our tx buffers are empty,
-			 * force the firmware to send me another wakeup after
-			 * TBUSY has been cleared.
-			 */
-			if (tbusy != 0) {
-				DGAP_LOCK(ch->ch_lock, lock_flags);
-				un->un_flags |= UN_EMPTY;
-				writeb(1, &(bs->iempty));
-				DGAP_UNLOCK(ch->ch_lock, lock_flags);
-			}
-			chars = 1;
-		}
-	}
-
- 	DPR_WRITE(("dgap_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d tsize: %d)\n",
-		ch->ch_portnum, chars, thead, ttail, ch->ch_tsize));
-        return(chars);
-}
-
-
-static int dgap_wait_for_drain(struct tty_struct *tty)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	struct bs_t *bs;
-	int ret = -EIO;
-	uint count = 1;
-	ulong   lock_flags = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return ret;
-
-	ret = 0;
-
-	DPR_DRAIN(("dgap_wait_for_drain start\n"));
-
-	/* Loop until data is drained */
-	while (count != 0) {
-
-		count = dgap_tty_chars_in_buffer(tty);
-
-		if (count == 0)
-			break;
-
-		/* Set flag waiting for drain */
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-		un->un_flags |= UN_EMPTY;
-		writeb(1, &(bs->iempty));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/* Go to sleep till we get woken up */
-		ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
-		/* If ret is non-zero, user ctrl-c'ed us */
-		if (ret) {
-			break;
-		}
-	}
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	un->un_flags &= ~(UN_EMPTY);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_DRAIN(("dgap_wait_for_drain finish\n"));
-	return (ret);
-}
-
-
-/*
- * dgap_maxcps_room
- *
- * Reduces bytes_available to the max number of characters
- * that can be sent currently given the maxcps value, and
- * returns the new bytes_available.  This only affects printer
- * output.
- */
-static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-
-	if (tty == NULL)
-		return (bytes_available);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (bytes_available);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (bytes_available);
-
-	/*
-	 * If its not the Transparent print device, return
-	 * the full data amount.
-	 */
-	if (un->un_type != DGAP_PRINT)
-		return (bytes_available);
-
-	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
-		int cps_limit = 0;
-		unsigned long current_time = jiffies;
-		unsigned long buffer_time = current_time +
-			(HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
-
-		if (ch->ch_cpstime < current_time) {
-			/* buffer is empty */
-			ch->ch_cpstime = current_time;            /* reset ch_cpstime */
-			cps_limit = ch->ch_digi.digi_bufsize;
-		}
-		else if (ch->ch_cpstime < buffer_time) {
-			/* still room in the buffer */
-			cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
-		}
-		else {
-			/* no room in the buffer */
-			cps_limit = 0;
-		}
-
-		bytes_available = min(cps_limit, bytes_available);
-	}
-
-	return (bytes_available);
-}
-
-
-static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
-{
-	struct channel_t *ch = NULL;
-	struct bs_t *bs = NULL;
-
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-        bs = ch->ch_bs;
-	if (!bs)
-		return;
-
-	if ((event & UN_LOW) != 0) {
-		if ((un->un_flags & UN_LOW) == 0) {
-			un->un_flags |= UN_LOW;
-			writeb(1, &(bs->ilow));
-		}
-	}
-	if ((event & UN_LOW) != 0) {
-		if ((un->un_flags & UN_EMPTY) == 0) {
-			un->un_flags |= UN_EMPTY;
-			writeb(1, &(bs->iempty));
-		}
-	}
-}
-
-
-/*
- * dgap_tty_write_room()
- *
- * Return space available in Tx buffer
- */
-static int dgap_tty_write_room(struct tty_struct *tty)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	u16 head, tail, tmask;
-	int ret = 0;
-	ulong   lock_flags = 0;
-
-	if (tty == NULL || dgap_TmpWriteBuf == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return (0);
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	tmask = ch->ch_tsize - 1;
-	head = readw(&(bs->tx_head)) & tmask;
-	tail = readw(&(bs->tx_tail)) & tmask;
-
-        if ((ret = tail - head - 1) < 0)
-                ret += ch->ch_tsize;
-
-	/* Limit printer to maxcps */
-	ret = dgap_maxcps_room(tty, ret);
-
-	/*
-	 * If we are printer device, leave space for
-	 * possibly both the on and off strings.
-	 */
-	if (un->un_type == DGAP_PRINT) {
-		if (!(ch->ch_flags & CH_PRON))
-			ret -= ch->ch_digi.digi_onlen;
-		ret -= ch->ch_digi.digi_offlen;
-	}
-	else {
-		if (ch->ch_flags & CH_PRON)
-			ret -= ch->ch_digi.digi_offlen;
-	}
-
-	if (ret < 0)
-		ret = 0;
-
-	/*
-	 * Schedule FEP to wake us up if needed.
-	 *
-	 * TODO:  This might be overkill...
-	 * Do we really need to schedule callbacks from the FEP
-	 * in every case?  Can we get smarter based on ret?
-	 */
-	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_WRITE(("dgap_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
-
-        return(ret);
-}
-
-
-/*
- * dgap_tty_put_char()
- *
- * Put a character into ch->ch_buf
- *
- *      - used by the line discipline for OPOST processing
- */
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
-{
-	/*
-	 * Simply call tty_write.
-	 */
-	DPR_WRITE(("dgap_tty_put_char called\n"));
-	dgap_tty_write(tty, &c, 1);
-	return 1;
-}
-
-
-/*
- * dgap_tty_write()
- *
- * Take data from the user or kernel and send it out to the FEP.
- * In here exists all the Transparent Print magic as well.
- */
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	char *vaddr = NULL;
-	u16 head, tail, tmask, remain;
-	int bufcount = 0, n = 0;
-	int orig_count = 0;
-	ulong lock_flags;
-	int from_user = 0;
-
-	if (tty == NULL || dgap_TmpWriteBuf == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return(0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return(0);
-
-	if (!count)
-		return(0);
-
-	DPR_WRITE(("dgap_tty_write: Port: %x tty=%p user=%d len=%d\n",
-		ch->ch_portnum, tty, from_user, count));
-
-	/*
-	 * Store original amount of characters passed in.
-	 * This helps to figure out if we should ask the FEP
-	 * to send us an event when it has more space available.
-	 */
-	orig_count = count;
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	/* Get our space available for the channel from the board */
-	tmask = ch->ch_tsize - 1;
-	head = readw(&(bs->tx_head)) & tmask;
-	tail = readw(&(bs->tx_tail)) & tmask;
-
-	if ((bufcount = tail - head - 1) < 0)
-		bufcount += ch->ch_tsize;
-
-	DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n",
-		__LINE__, bufcount, count, tail, head, tmask));
-
-	/*
-	 * Limit printer output to maxcps overall, with bursts allowed
-	 * up to bufsize characters.
-	 */
-	bufcount = dgap_maxcps_room(tty, bufcount);
-
-	/*
-	 * Take minimum of what the user wants to send, and the
-	 * space available in the FEP buffer.
-	 */
-	count = min(count, bufcount);
-
-	/*
-	 * Bail if no space left.
-	 */
-	if (count <= 0) {
-		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
-	}
-
-	/*
-	 * Output the printer ON string, if we are in terminal mode, but
-	 * need to be in printer mode.
-	 */
-	if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
-		dgap_wmove(ch, ch->ch_digi.digi_onstr,
-		    (int) ch->ch_digi.digi_onlen);
-		head = readw(&(bs->tx_head)) & tmask;
-		ch->ch_flags |= CH_PRON;
-	}
-
-	/*
-	 * On the other hand, output the printer OFF string, if we are
-	 * currently in printer mode, but need to output to the terminal.
-	 */
-	if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-		dgap_wmove(ch, ch->ch_digi.digi_offstr,
-			(int) ch->ch_digi.digi_offlen);
-		head = readw(&(bs->tx_head)) & tmask;
-		ch->ch_flags &= ~CH_PRON;
-	}
-
-	/*
-	 * If there is nothing left to copy, or I can't handle any more data, leave.
-	 */
-	if (count <= 0) {
-		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
-	}
-
-	if (from_user) {
-
-		count = min(count, WRITEBUFLEN);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/*
-		 * If data is coming from user space, copy it into a temporary
-		 * buffer so we don't get swapped out while doing the copy to
-		 * the board.
-		 */
-		/* we're allowed to block if it's from_user */
-		if (down_interruptible(&dgap_TmpWriteSem)) {
-			return (-EINTR);
-		}
-
-		if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
-			up(&dgap_TmpWriteSem);
-			printk("Write: Copy from user failed!\n");
-			return -EFAULT;
-		}
-
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-
-		buf = dgap_TmpWriteBuf;
-	}
-
-	n = count;
-
-	/*
-	 * If the write wraps over the top of the circular buffer,
-	 * move the portion up to the wrap point, and reset the
-	 * pointers to the bottom.
-	 */
-	remain = ch->ch_tstart + ch->ch_tsize - head;
-
-	if (n >= remain) {
-		n -= remain;
-		vaddr = ch->ch_taddr + head;
-
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-		head = ch->ch_tstart;
-		buf += remain;
-	}
-
-	if (n > 0) {
-
-		/*
-		 * Move rest of data.
-		 */
-		vaddr = ch->ch_taddr + head;
-		remain = n;
-
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-		head += remain;
-
-	}
-
-	if (count) {
-		ch->ch_txcount += count;
-		head &= tmask;
-		writew(head, &(bs->tx_head));
-	}
-
-
-	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-
-	/*
-	 * If this is the print device, and the
-	 * printer is still on, we need to turn it
-	 * off before going idle.  If the buffer is
-	 * non-empty, wait until it goes empty.
-	 * Otherwise turn it off right now.
-	 */
-	if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-		tail = readw(&(bs->tx_tail)) & tmask;
-
-		if (tail != head) {
-			un->un_flags |= UN_EMPTY;
-			writeb(1, &(bs->iempty));
-		}
-		else {
-			dgap_wmove(ch, ch->ch_digi.digi_offstr,
-				(int) ch->ch_digi.digi_offlen);
-			head = readw(&(bs->tx_head)) & tmask;
-			ch->ch_flags &= ~CH_PRON;
-		}
-	}
-
-	/* Update printer buffer empty time. */
-	if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
-	    && (ch->ch_digi.digi_bufsize > 0)) {
-                ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
-	}
-
-	if (from_user) {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		up(&dgap_TmpWriteSem);
-	}
-	else {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-	}
-
-	DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count));
-
-	return (count);
-}
-
-
-
-/*
- * Return modem signals to ld.
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
-static int dgap_tty_tiocmget(struct tty_struct *tty)
-#else
-static int dgap_tty_tiocmget(struct tty_struct *tty, struct file *file)
-#endif
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int result = -EIO;
-	uchar mstat = 0;
-	ulong lock_flags;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return result;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return result;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return result;
-
-	DPR_IOCTL(("dgap_tty_tiocmget start\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	mstat = readb(&(ch->ch_bs->m_stat));
-        /* Append any outbound signals that might be pending... */
-        mstat |= ch->ch_mostat;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	result = 0;
-
-	if (mstat & D_DTR(ch))
-		result |= TIOCM_DTR;
-	if (mstat & D_RTS(ch))
-		result |= TIOCM_RTS;
-	if (mstat & D_CTS(ch))
-		result |= TIOCM_CTS;
-	if (mstat & D_DSR(ch))
-		result |= TIOCM_DSR;
-	if (mstat & D_RI(ch))
-		result |= TIOCM_RI;
-	if (mstat & D_CD(ch))
-		result |= TIOCM_CD;
-
-	DPR_IOCTL(("dgap_tty_tiocmget finish\n"));
-
-	return result;
-}
-
-
-/*
- * dgap_tty_tiocmset()
- *
- * Set modem signals, called by ld.
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
-static int dgap_tty_tiocmset(struct tty_struct *tty,
-                unsigned int set, unsigned int clear)
-#else
-static int dgap_tty_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-#endif
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -EIO;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	DPR_IOCTL(("dgap_tty_tiocmset start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	if (set & TIOCM_RTS) {
-		ch->ch_mforce |= D_RTS(ch);
-		ch->ch_mval   |= D_RTS(ch);
-        }
-
-	if (set & TIOCM_DTR) {
-		ch->ch_mforce |= D_DTR(ch);
-		ch->ch_mval   |= D_DTR(ch);
-        }
-
-	if (clear & TIOCM_RTS) {
-		ch->ch_mforce |= D_RTS(ch);
-		ch->ch_mval   &= ~(D_RTS(ch));
-        }
-
-	if (clear & TIOCM_DTR) {
-		ch->ch_mforce |= D_DTR(ch);
-		ch->ch_mval   &= ~(D_DTR(ch));
-        }
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_tiocmset finish\n"));
-
-	return (0);
-}
-
-
-
-/*
- * dgap_tty_send_break()
- *
- * Send a Break, called by ld.
- */
-static int dgap_tty_send_break(struct tty_struct *tty, int msec)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -EIO;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	switch (msec) {
-	case -1:
-		msec = 0xFFFF;
-		break;
-	case 0:
-		msec = 1;
-		break;
-	default:
-		msec /= 10;
-		break;
-	}
-
-	DPR_IOCTL(("dgap_tty_send_break start 1.  %lx\n", jiffies));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-#if 0
-	dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-#endif
-	dgap_cmdw(ch, SBREAK, (u16) msec, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_send_break finish\n"));
-
-	return (0);
-}
-
-
-
-
-/*
- * dgap_tty_wait_until_sent()
- *
- * wait until data has been transmitted, called by ld.
- */
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	int rc;
-	rc = dgap_wait_for_drain(tty);
-	if (rc) {
-		DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-		return;
-	}
-	return;
-}
-
-
-
-/*
- * dgap_send_xchar()
- *
- * send a high priority character, called by ld.
- */
-static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_send_xchar start 1.  %lx\n", jiffies));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/*
-	 * This is technically what we should do.
-	 * However, the NIST tests specifically want
-	 * to see each XON or XOFF character that it
-	 * sends, so lets just send each character
-	 * by hand...
-	 */
-#if 0
-	if (c == STOP_CHAR(tty)) {
-		dgap_cmdw(ch, RPAUSE, 0, 0);
-	}
-	else if (c == START_CHAR(tty)) {
-		dgap_cmdw(ch, RRESUME, 0, 0);
-	}
-	else {
-		dgap_wmove(ch, &c, 1);
-	}
-#else
-	dgap_wmove(ch, &c, 1);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_send_xchar finish\n"));
-
-	return;
-}
-
-
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
-{
-	int result = 0;
-	uchar mstat = 0;
-	ulong lock_flags;
-	int rc = 0;
-
-	DPR_IOCTL(("dgap_get_modem_info start\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return(-ENXIO);
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	mstat = readb(&(ch->ch_bs->m_stat));
-	/* Append any outbound signals that might be pending... */
-	mstat |= ch->ch_mostat;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	result = 0;
-
-	if (mstat & D_DTR(ch))
-		result |= TIOCM_DTR;
-	if (mstat & D_RTS(ch))
-		result |= TIOCM_RTS;
-	if (mstat & D_CTS(ch))
-		result |= TIOCM_CTS;
-	if (mstat & D_DSR(ch))
-		result |= TIOCM_DSR;
-	if (mstat & D_RI(ch))
-		result |= TIOCM_RI;
-	if (mstat & D_CD(ch))
-		result |= TIOCM_CD;
-
-	rc = put_user(result, value);
-
-	DPR_IOCTL(("dgap_get_modem_info finish\n"));
-	return(rc);
-}
-
-
-/*
- * dgap_set_modem_info()
- *
- * Set modem signals, called by ld.
- */
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -ENXIO;
-	unsigned int arg = 0;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	DPR_IOCTL(("dgap_set_modem_info() start\n"));
-
-	ret = get_user(arg, value);
-	if (ret) {
-		DPR_IOCTL(("dgap_set_modem_info %d ret: %x. finished.\n", __LINE__, ret));
-		return(ret);
-	}
-
-	DPR_IOCTL(("dgap_set_modem_info: command: %x arg: %x\n", command, arg));
-
-	switch (command) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS) {
-			ch->ch_mforce |= D_RTS(ch);
-			ch->ch_mval   |= D_RTS(ch);
-        	}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mforce |= D_DTR(ch);
-			ch->ch_mval   |= D_DTR(ch);
-        	}
-
-		break;
-
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS) {
-			ch->ch_mforce |= D_RTS(ch);
-			ch->ch_mval   &= ~(D_RTS(ch));
-        	}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mforce |= D_DTR(ch);
-			ch->ch_mval   &= ~(D_DTR(ch));
-        	}
-
-		break;
-
-        case TIOCMSET:
-		ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
-
-		if (arg & TIOCM_RTS) {
-			ch->ch_mval |= D_RTS(ch);
-        	}
-		else {
-			ch->ch_mval &= ~(D_RTS(ch));
-		}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mval |= (D_DTR(ch));
-        	}
-		else {
-			ch->ch_mval &= ~(D_DTR(ch));
-		}
-
-		break;
-
-	default:
-		return(-EINVAL);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_set_modem_info finish\n"));
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digigeta()
- *
- * Ioctl to get the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	struct digi_t tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digiseta()
- *
- * Ioctl to set the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	struct digi_t new_digi;
-	ulong   lock_flags = 0;
-	unsigned long lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETA start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
-		DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
-                return(-EFAULT);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
-
-	if (ch->ch_digi.digi_maxcps < 1)
-		ch->ch_digi.digi_maxcps = 1;
-
-	if (ch->ch_digi.digi_maxcps > 10000)
-		ch->ch_digi.digi_maxcps = 10000;
-
-	if (ch->ch_digi.digi_bufsize < 10)
-		ch->ch_digi.digi_bufsize = 10;
-
-	if (ch->ch_digi.digi_maxchar < 1)
-		ch->ch_digi.digi_maxchar = 1;
-
-	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
-		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
-
-	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
-		ch->ch_digi.digi_onlen = DIGI_PLEN;
-
-	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
-		ch->ch_digi.digi_offlen = DIGI_PLEN;
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_SETA finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_digigetedelay()
- *
- * Ioctl to get the current edelay setting.
- *
- *
- *
- */
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	tmp = readw(&(ch->ch_bs->edelay));
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digisetedelay()
- *
- * Ioctl to set the EDELAY setting
- *
- */
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int new_digi;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETA start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(int))) {
-		DPR_IOCTL(("DIGI_SETEDELAY failed copy_from_user\n"));
-                return(-EFAULT);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	writew((u16) new_digi, &(ch->ch_bs->edelay));
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_SETA finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_digigetcustombaud()
- *
- * Ioctl to get the current custom baud rate setting.
- */
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	tmp = dgap_get_custom_baud(ch);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_GETCUSTOMBAUD. Returning %d\n", tmp));
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digisetcustombaud()
- *
- * Ioctl to set the custom baud rate setting
- */
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	uint new_rate;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETCUSTOMBAUD start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-
-	if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) {
-		DPR_IOCTL(("DIGI_SETCUSTOMBAUD failed copy_from_user\n"));
-		return(-EFAULT);
-	}
-
-	if (bd->bd_flags & BD_FEP5PLUS) {
-
-		DPR_IOCTL(("DIGI_SETCUSTOMBAUD. Setting %d\n", new_rate));
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		ch->ch_custom_speed = new_rate;
-
-		dgap_param(tty);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-	}
-
-	DPR_IOCTL(("DIGI_SETCUSTOMBAUD finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_set_termios()
- */
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	unsigned long lock_flags;
-	unsigned long lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_c_cflag   = tty->termios.c_cflag;
-	ch->ch_c_iflag   = tty->termios.c_iflag;
-	ch->ch_c_oflag   = tty->termios.c_oflag;
-	ch->ch_c_lflag   = tty->termios.c_lflag;
-	ch->ch_startc    = tty->termios.c_cc[VSTART];
-	ch->ch_stopc     = tty->termios.c_cc[VSTOP];
-
-	dgap_carrier(ch);
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-static void dgap_tty_throttle(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_throttle start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags |= (CH_RXBLOCK);
-#if 1
-	dgap_cmdw(ch, RPAUSE, 0, 0);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_throttle finish\n"));
-}
-
-
-static void dgap_tty_unthrottle(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_unthrottle start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags &= ~(CH_RXBLOCK);
-
-#if 1
-	dgap_cmdw(ch, RRESUME, 0, 0);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_unthrottle finish\n"));
-}
-
-
-static void dgap_tty_start(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_start start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_cmdw(ch, RESUMETX, 0, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_start finish\n"));
-}
-
-
-static void dgap_tty_stop(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_stop start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_cmdw(ch, PAUSETX, 0, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_stop finish\n"));
-}
-
-
-/*
- * dgap_tty_flush_chars()
- *
- * Flush the cook buffer
- *
- * Note to self, and any other poor souls who venture here:
- *
- * flush in this case DOES NOT mean dispose of the data.
- * instead, it means "stop buffering and send it if you
- * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
- *
- * It is also always called in interrupt context - JAR 8-Sept-99
- */
-static void dgap_tty_flush_chars(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_flush_chars start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/* TODO: Do something here */
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_flush_chars finish\n"));
-}
-
-
-
-/*
- * dgap_tty_flush_buffer()
- *
- * Flush Tx buffer (make in == out)
- */
-static void dgap_tty_flush_buffer(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-	u16	head = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_flush_buffer on port: %d start\n", ch->ch_portnum));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags &= ~CH_STOP;
-	head = readw(&(ch->ch_bs->tx_head));
-	dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
-	dgap_cmdw(ch, RESUMETX, 0, 0);
-	if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-		ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-	}
-	if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-		ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-	}
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-	if (waitqueue_active(&tty->write_wait))
-		wake_up_interruptible(&tty->write_wait);
-	tty_wakeup(tty);
-
-	DPR_IOCTL(("dgap_tty_flush_buffer finish\n"));
-}
-
-
-
-/*****************************************************************************
- *
- * The IOCTL function and all of its helpers
- *
- *****************************************************************************/
-
-/*
- * dgap_tty_ioctl()
- *
- * The usual assortment of ioctl's
- */
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
-		unsigned long arg)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int rc;
-	u16	head = 0;
-	ulong   lock_flags = 0;
-	ulong   lock_flags2 = 0;
-	void __user *uarg = (void __user *) arg;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-ENODEV);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-ENODEV);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-ENODEV);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-ENODEV);
-
-	DPR_IOCTL(("dgap_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
-		ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	if (un->un_open_count <= 0) {
-		DPR_BASIC(("dgap_tty_ioctl - unit not open.\n"));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(-EIO);
-	}
-
-	switch (cmd) {
-
-	/* Here are all the standard ioctl's that we MUST implement */
-
-	case TCSBRK:
-		/*
-		 * TCSBRK is SVID version: non-zero arg --> no break
-		 * this behaviour is exploited by tcdrain().
-		 *
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds so we'll ask for something
-		 * in the middle: 0.375 seconds.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) {
-			dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-		}
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-                return(0);
-
-
-	case TCSBRKP:
- 		/* support for POSIX tcsendbreak()
-
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds so we'll ask for something
-		 * in the middle: 0.375 seconds.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return(0);
-
-        case TIOCSBRK:
-		/*
-		 * FEP5 doesn't support turning on a break unconditionally.
-		 * The FEP5 device will stop sending a break automatically
-		 * after the specified time value that was sent when turning on
-		 * the break.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return 0;
-
-        case TIOCCBRK:
-		/*
-		 * FEP5 doesn't support turning off a break unconditionally.
-		 * The FEP5 device will stop sending a break automatically
-		 * after the specified time value that was sent when turning on
-		 * the break.
-		 */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return 0;
-
-	case TIOCGSOFTCAR:
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
-		return(rc);
-
-	case TIOCSSOFTCAR:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		rc = get_user(arg, (unsigned long __user *) arg);
-		if (rc)
-			return(rc);
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
-		dgap_param(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		return(0);
-
-	case TIOCMGET:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                return(dgap_get_modem_info(ch, uarg));
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_set_modem_info(tty, cmd, uarg));
-
-		/*
-		 * Here are any additional ioctl's that we want to implement
-		 */
-
-	case TCFLSH:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-		rc = tty_check_change(tty);
-		if (rc) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(rc);
-		}
-
-		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
-			if (!(un->un_type == DGAP_PRINT)) {
-				head = readw(&(ch->ch_bs->rx_head));
-				writew(head, &(ch->ch_bs->rx_tail));
-				writeb(0, &(ch->ch_bs->orun));
-			}
-		}
-
-		if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
-			ch->ch_flags &= ~CH_STOP;
-			head = readw(&(ch->ch_bs->tx_head));
-			dgap_cmdw(ch, FLUSHTX, (u16) head, 0 );
-			dgap_cmdw(ch, RESUMETX, 0, 0);
-			if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-				ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-			}
-			if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-				ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-				wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-			}
-			if (waitqueue_active(&tty->write_wait))
-				wake_up_interruptible(&tty->write_wait);
-
-			/* Can't hold any locks when calling tty_wakeup! */
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			tty_wakeup(tty);
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-		}
-
-		/* pretend we didn't recognize this IOCTL */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n",
-			__LINE__, ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return(-ENOIOCTLCMD);
-
-	case TCSETSF:
-	case TCSETSW:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-		if (cmd == TCSETSF) {
-			/* flush rx */
-			ch->ch_flags &= ~CH_STOP;
-			head = readw(&(ch->ch_bs->rx_head));
-			writew(head, &(ch->ch_bs->rx_tail));
-		}
-
-		/* now wait for all the output to drain */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
-
-	case TCSETAW:
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
-
-	case TCXONC:
-		/*
-		 * The Linux Line Discipline (LD) would do this for us if we
-		 * let it, but we have the special firmware options to do this
-		 * the "right way" regardless of hardware or software flow
-		 * control so we'll do it outselves instead of letting the LD
-		 * do it.
-		 */
-		rc = tty_check_change(tty);
-		if (rc) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(rc);
-		}
-
-		DPR_IOCTL(("dgap_ioctl - in TCXONC - %d\n", cmd));
-		switch (arg) {
-
-		case TCOON:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_tty_start(tty);
-			return(0);
-		case TCOOFF:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_tty_stop(tty);
-			return(0);
-		case TCION:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			/* Make the ld do it */
-			return(-ENOIOCTLCMD);
-		case TCIOFF:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			/* Make the ld do it */
-			return(-ENOIOCTLCMD);
-		default:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(-EINVAL);
-		}
-
-	case DIGI_GETA:
-		/* get information for ditty */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigeta(tty, uarg));
-
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-
-		/* set information for ditty */
-		if (cmd == (DIGI_SETAW)) {
-
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			rc = dgap_wait_for_drain(tty);
-			if (rc) {
-				DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-				return(-EINTR);
-			}
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-		}
-		else {
-			tty_ldisc_flush(tty);
-		}
-		/* fall thru */
-
-	case DIGI_SETA:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digiseta(tty, uarg));
-
-	case DIGI_GEDELAY:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigetedelay(tty, uarg));
-
-	case DIGI_SEDELAY:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digisetedelay(tty, uarg));
-
-	case DIGI_GETCUSTOMBAUD:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigetcustombaud(tty, uarg));
-
-	case DIGI_SETCUSTOMBAUD:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digisetcustombaud(tty, uarg));
-
-	case DIGI_RESET_PORT:
-		dgap_firmware_reset_port(ch);
-		dgap_param(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return 0;
-
-	default:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl - in default\n"));
-		DPR_IOCTL(("dgap_tty_ioctl end - cmd %s (%x), arg %lx\n",
-			dgap_ioctl_name(cmd), cmd, arg));
-
-		return(-ENOIOCTLCMD);
-	}
-}
diff --git a/drivers/staging/dgap/dgap_tty.h b/drivers/staging/dgap/dgap_tty.h
deleted file mode 100644
index 464a460b6be8..000000000000
--- a/drivers/staging/dgap/dgap_tty.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TTY_H
-#define __DGAP_TTY_H
-
-#include "dgap_driver.h"
-
-int	dgap_tty_register(struct board_t *brd);
-
-int	dgap_tty_preinit(void);
-int     dgap_tty_init(struct board_t *);
-
-void	dgap_tty_post_uninit(void);
-void	dgap_tty_uninit(struct board_t *);
-
-void	dgap_carrier(struct channel_t *ch);
-void	dgap_input(struct channel_t *ch);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_types.h b/drivers/staging/dgap/dgap_types.h
deleted file mode 100644
index eca38c7f359d..000000000000
--- a/drivers/staging/dgap/dgap_types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TYPES_H
-#define __DGAP_TYPES_H
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-/* Required for our shared headers! */
-typedef unsigned char		uchar;
-
-#endif
diff --git a/drivers/staging/dgap/digi.h b/drivers/staging/dgap/digi.h
deleted file mode 100644
index bcea4f734a32..000000000000
--- a/drivers/staging/dgap/digi.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- * $Id: digi.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DIGI_H
-#define __DIGI_H
-
-/************************************************************************
- ***	Definitions for Digi ditty(1) command.
- ************************************************************************/
-
-
-/*
- * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
- */
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-#if !defined(TIOCMODG)
-
-#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		*/
-#define		TIOCM_DTR	0x02		/* data terminal ready	*/
-#define		TIOCM_RTS	0x04		/* request to send	*/
-#define		TIOCM_ST	0x08		/* secondary transmit	*/
-#define		TIOCM_SR	0x10		/* secondary receive	*/
-#define		TIOCM_CTS	0x20		/* clear to send	*/
-#define		TIOCM_CAR	0x40		/* carrier detect	*/
-#define		TIOCM_RNG	0x80		/* ring	indicator	*/
-#define		TIOCM_DSR	0x100		/* data set ready	*/
-#define		TIOCM_RI	TIOCM_RNG	/* ring (alternate)	*/
-#define		TIOCM_CD	TIOCM_CAR	/* carrier detect (alt)	*/
-#endif
-
-#endif
-
-#if !defined(TIOCMSET)
-#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 */
-#endif
-
-
-#if !defined(TIOCSDTR)
-#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
-#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
-
-#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
-#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
-#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
-
-#define DIGI_KME	('e'<<8) | 98		/* Read/Write Host	*/
-						/* 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_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 */
-
-struct	digiflow_t {
-	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_MASK	0x03		/* 2200 flow cntl bit mask  */
-#define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
-#define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
-#define	F2200_XON	0xf8
-#define	P2200_XON	0xf9
-#define	F2200_XOFF	0xfa
-#define	P2200_XOFF	0xfb
-
-#define	FXOFF_MASK	0x03			/* 2200 flow status mask    */
-#define	RCVD_FXOFF	0x01			/* 2x36 Terminal XOFF rcvd  */
-#define	RCVD_PXOFF	0x02			/* 2x36 Printer XOFF rcvd   */
-#endif
-
-/************************************************************************
- * Values for digi_flags 
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl*/
-#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input*/
-#define DIGI_DTR_TOGGLE 0x2000		/* Support DTR Toggle		*/
-#define	DIGI_422	0x4000		/* for 422/232 selectable panel */
-#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		*/
-
-/************************************************************************
- * These options are not supported on the comxi.
- ************************************************************************/
-#define	DIGI_COMXI	(DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
-
-#define DIGI_PLEN	28		/* String length		*/
-#define	DIGI_TSIZ	10		/* Terminal string len		*/
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_t {
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-	unsigned short	digi_maxcps;		/* Max printer CPS	*/
-	unsigned short	digi_maxchar;		/* Max chars in print queue */
-	unsigned short	digi_bufsize;		/* Buffer size		*/
-	unsigned char	digi_onlen;		/* Length of ON string	*/
-	unsigned char	digi_offlen;		/* Length of OFF string	*/
-	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
-	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
-	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
-};
-
-/************************************************************************
- * KME definitions and structures.
- ************************************************************************/
-#define	RW_IDLE		0	/* Operation complete			*/
-#define	RW_READ		1	/* Read Concentrator Memory		*/
-#define	RW_WRITE	2	/* Write Concentrator Memory		*/
-
-struct rw_t {
-	unsigned char	rw_req;		/* Request type			*/
-	unsigned char	rw_board;	/* Host Adapter board number	*/
-	unsigned char	rw_conc;	/* Concentrator number		*/
-	unsigned char	rw_reserved;	/* Reserved for expansion	*/
-	unsigned long	rw_addr;	/* Address in concentrator	*/
-	unsigned short	rw_size;	/* Read/write request length	*/
-	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
- ************************************************************************/
-struct digi_dinfo {
-	unsigned long	dinfo_nboards;		/* # boards configured	*/
-	char		dinfo_reserved[12];	/* for future expansion */
-	char		dinfo_version[16];	/* driver version       */
-};
-
-#define	DIGI_GETDD	('d'<<8) | 248		/* get driver info      */
- 
-/************************************************************************
- * Structure used with ioctl commands for per-board information
- *
- * physsize and memsize differ when board has "windowed" memory
- ************************************************************************/
-struct digi_info {
-	unsigned long	info_bdnum;		/* Board number (0 based)  */
-	unsigned long	info_ioport;		/* io port address         */
-	unsigned long	info_physaddr;		/* memory address          */
-	unsigned long	info_physsize;		/* Size of host mem window */
-	unsigned long	info_memsize;		/* Amount of dual-port mem */
-						/* on board                */
-	unsigned short	info_bdtype;		/* Board type              */
-	unsigned short	info_nports;		/* number of ports         */
-	char		info_bdstate;		/* board state             */
-	char		info_reserved[7];	/* for future expansion    */
-};
-
-#define	DIGI_GETBD	('d'<<8) | 249		/* get board info          */
- 
-struct digi_stat {
-	unsigned int	info_chan;		/* Channel number (0 based)  */
-	unsigned int	info_brd;		/* Board number (0 based)  */
-	unsigned long	info_cflag;		/* cflag for channel       */
-	unsigned long	info_iflag;		/* iflag for channel       */
-	unsigned long	info_oflag;		/* oflag for channel       */
-	unsigned long	info_mstat;		/* mstat for channel       */
-	unsigned long	info_tx_data;		/* tx_data for channel       */
-	unsigned long	info_rx_data;		/* rx_data for channel       */
-	unsigned long	info_hflow;		/* hflow for channel       */
-	unsigned long	info_reserved[8];	/* for future expansion    */
-};
-
-#define	DIGI_GETSTAT	('d'<<8) | 244		/* get board info          */
-/************************************************************************
- *
- * Structure used with ioctl commands for per-channel information
- *
- ************************************************************************/
-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_chsize;		/* Channel structure size  */
-	unsigned long	info_sleep_stat;	/* sleep status		   */
-	dev_t		info_dev;		/* device number	   */
-	unsigned char	info_initstate;		/* Channel init state	   */
-	unsigned char	info_running;		/* Channel running state   */
-	long		reserved[8];		/* reserved for future use */
-};
-
-/*
-* This structure is used with the DIGI_FEPCMD ioctl to 
-* tell the driver which port to send the command for.
-*/
-struct digi_cmd {
-	int	cmd;
-	int	word;
-	int	ncmds;
-	int	chan; /* channel index (zero based) */
-	int	bdid; /* board index (zero based) */
-};
-
-/*
-*  info_sleep_stat defines
-*/
-#define INFO_RUNWAIT	0x0001
-#define INFO_WOPEN	0x0002
-#define INFO_TTIOW	0x0004
-#define INFO_CH_RWAIT	0x0008
-#define INFO_CH_WEMPTY	0x0010
-#define INFO_CH_WLOW	0x0020
-#define INFO_XXBUF_BUSY 0x0040
-
-#define	DIGI_GETCH	('d'<<8) | 245		/* get board info          */
-
-/* Board type definitions */
-
-#define	SUBTYPE		0007
-#define	T_PCXI		0000
-#define T_PCXM		0001
-#define T_PCXE		0002
-#define T_PCXR		0003
-#define T_SP		0004
-#define T_SP_PLUS	0005
-#	define T_HERC	0000
-#	define T_HOU	0001
-#	define T_LON	0002
-#	define T_CHA	0003
-#define FAMILY		0070
-#define T_COMXI		0000
-#define T_PCXX		0010
-#define T_CX		0020
-#define T_EPC		0030
-#define	T_PCLITE	0040
-#define	T_SPXX		0050
-#define	T_AVXX		0060
-#define T_DXB		0070
-#define T_A2K_4_8	0070
-#define BUSTYPE		0700
-#define T_ISABUS	0000
-#define T_MCBUS		0100
-#define	T_EISABUS	0200
-#define	T_PCIBUS	0400
-
-/* Board State Definitions */
-
-#define	BD_RUNNING	0x0
-#define	BD_REASON	0x7f
-#define	BD_NOTFOUND	0x1
-#define	BD_NOIOPORT	0x2
-#define	BD_NOMEM	0x3
-#define	BD_NOBIOS	0x4
-#define	BD_NOFEP	0x5
-#define	BD_FAILED	0x6
-#define BD_ALLOCATED	0x7
-#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_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		*/
-
-#endif /* DIGI_H */
diff --git a/drivers/staging/dgap/downld.c b/drivers/staging/dgap/downld.c
deleted file mode 100644
index 1f4aa2eca437..000000000000
--- a/drivers/staging/dgap/downld.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- *
- * 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.
- *
- * $Id: downld.c,v 1.6 2009/01/14 14:10:54 markh Exp $
- */
-
-/*
-** downld.c
-**
-**  This is the daemon that sends the fep, bios, and concentrator images
-**  from user space to the driver.
-** BUGS:
-**  If the file changes in the middle of the download, you probably
-**     will get what you deserve.
-**
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-
-#include "dgap_types.h"
-#include "digi.h"
-#include "dgap_fep5.h"
-
-#include "dgap_downld.h"
-
-#include <string.h>
-#include <malloc.h>
-#include <stddef.h>
-#include <unistd.h>
-
-char		*pgm;
-void		myperror();
-
-/*
-**  This structure is used to keep track of the different images available
-**  to give to the driver.  It is arranged so that the things that are
-**  constants or that have defaults are first inthe strucutre to simplify
-**  the table of initializers.
-*/
-struct image_info {
-	short	type;		/* bios, fep, conc */
-	short	family;		/* boards this applies to */
-	short	subtype;	/* subtype */
-	int	len;		/* size of image */
-	char	*image;		/* ioctl struct + image */
-	char	*name;
-	char	*fname;		/* filename of binary (i.e. "asfep.bin") */
-	char	*pathname;	/* pathname to this binary ("/etc/dgap/xrfep.bin"); */
-	time_t	mtime;		/* Last modification time */
-};
-
-#define IBIOS	0
-#define	IFEP	1
-#define	ICONC	2
-#define ICONFIG	3
-#define	IBAD	4
-
-#define DEFAULT_LOC "/lib/firmware/dgap/"
-
-struct image_info	*image_list;
-int			nimages, count;
-
-struct image_info images[] = {
-{IBIOS, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxbios.bin", DEFAULT_LOC "fxbios.bin", 0 },
-{IFEP,  T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxfep.bin", DEFAULT_LOC "fxfep.bin", 0 },
-{ICONC, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxcon.bin", DEFAULT_LOC "fxcon.bin", 0 },
-
-{IBIOS, T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxbios.bin", DEFAULT_LOC "cxbios.bin", 0 },
-{IFEP,  T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxhost.bin", DEFAULT_LOC "cxhost.bin", 0 },
-
-{IBIOS, T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpbios.bin", DEFAULT_LOC "cxpbios.bin", 0 },
-{IFEP,  T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpfep.bin", DEFAULT_LOC "cxpfep.bin", 0 },
-
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxcon.bin", DEFAULT_LOC "cxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"ibmcxcon.bin", DEFAULT_LOC "ibmcxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"ibmencon.bin", DEFAULT_LOC "ibmencon.bin", 0 },
-
-{IBIOS, FAMILY,   T_PCXR, 0, NULL, "PCXR",	"xrbios.bin", DEFAULT_LOC "xrbios.bin", 0 },
-{IFEP,  FAMILY,   T_PCXR, 0,  NULL,  "PCXR",	"xrfep.bin", DEFAULT_LOC "xrfep.bin", 0  },
-
-{IBIOS, T_PCLITE,   SUBTYPE, 0, NULL, "X/em",	"sxbios.bin", DEFAULT_LOC "sxbios.bin", 0 },
-{IFEP,  T_PCLITE,   SUBTYPE, 0,  NULL,  "X/em",	"sxfep.bin", DEFAULT_LOC "sxfep.bin", 0  },
-
-{IBIOS, T_EPC,      T_PCIBUS, 0, NULL, "PCI",	"pcibios.bin", DEFAULT_LOC "pcibios.bin", 0 },
-{IFEP,  T_EPC,      T_PCIBUS, 0, NULL, "PCI",	"pcifep.bin", DEFAULT_LOC "pcifep.bin", 0 },
-{ICONFIG, 0,	    0, 0, NULL,         NULL,	"dgap.conf",	"/etc/dgap.conf", 0 },
-
-/* IBAD/NULL entry indicating end-of-table */
-
-{IBAD,  0,     0, 0,  NULL,  NULL, NULL, NULL, 0 }
-
-} ;
-
-int 	errorprint = 1;
-int 	nodldprint = 1;
-int	debugflag;
-int 	fd;
-
-struct downld_t *ip;	/* Image pointer in current image  */
-struct downld_t *dp; 	/* conc. download */
-
-
-/*
- * The same for either the FEP or the BIOS.
- *  Append the downldio header, issue the ioctl, then free
- *  the buffer.  Not horribly CPU efficient, but quite RAM efficient.
- */
-
-void squirt(int req_type, int bdid, struct image_info *ii)
-{
-	struct downldio	*dliop;
-	int size_buf;
-	int sfd;
-	struct stat sb;
-
-	/*
-	 * If this binary comes from a file, stat it to see how
-	 * large it is. Yes, we intentionally do this each
-	 * time for the binary may change between loads.
-	 */
-
-	if (ii->pathname) {
-		sfd = open(ii->pathname, O_RDONLY);
-
-		if (sfd < 0 ) {
-			myperror(ii->pathname);
-			goto squirt_end;
-		}
-
-		if (fstat(sfd, &sb) == -1 ) {
-			myperror(ii->pathname);
-			goto squirt_end;
-		}
-
-		ii->len = sb.st_size;
-	}
-
-	size_buf = ii->len + sizeof(struct downldio);
-
-	/*
-	 * This buffer will be freed at the end of this function.  It is
-	 * not resilient and should be around only long enough for the d/l
-	 * to happen.
-	 */
-	dliop = (struct downldio *) malloc(size_buf);
-
-	if (dliop == NULL) {
-		fprintf(stderr,"%s: can't get %d bytes of memory; aborting\n",
-			pgm, size_buf);
-		exit (1);
-	}
-
-	/* Now, stick the image in fepimage.  This can come from either
-	 *  the compiled-in image or from the filesystem.
-	 */
-	if (ii->pathname)
-		read(sfd, dliop->image.fi.fepimage, ii->len);
-	else
-		memcpy(dliop ->image.fi.fepimage, ii->image, ii->len);
-
-	dliop->req_type = req_type;
-	dliop->bdid = bdid;
-
-	dliop->image.fi.len = ii->len;
-
-	if (debugflag)
-		printf("sending %d bytes of %s %s from %s\n",
-			ii->len,
-			(ii->type == IFEP) ? "FEP" : (ii->type == IBIOS) ? "BIOS" : "CONFIG",
-			ii->name ? ii->name : "",
-			(ii->pathname) ? ii->pathname : "internal image" );
-
-	if (ioctl(fd, DIGI_DLREQ_SET, (char *) dliop) == -1) {
-		if(errorprint) {
-			fprintf(stderr,
-				"%s: warning - download ioctl failed\n",pgm);
-			errorprint = 0;
-		}
-		sleep(2);
-	}
-
-squirt_end:
-
-	if (ii->pathname) {
-		close(sfd);
-	}
-	free(dliop);
-}
-
-
-/*
- *  See if we need to reload the download image in core
- *
- */
-void consider_file_rescan(struct image_info *ii)
-{
-	int sfd;
-	int len;
-	struct stat 	sb;
-
-	/* This operation only makes sense when we're working from a file */
-
-	if (ii->pathname) {
-
-		sfd = open (ii->pathname, O_RDONLY) ;
-		if (sfd < 0 ) {
-			myperror(ii->pathname);
-			exit(1) ;
-		}
-
-		if( fstat(sfd,&sb) == -1 ) {
-			myperror(ii->pathname);
-			exit(1);
-		}
-
-		/* If the file hasn't changed since we last did this,
-		 * and we have not done a free() on the image, bail
-		 */
-		if (ii->image && (sb.st_mtime == ii->mtime))
-			goto end_rescan;
-
-		ii->len = len = sb.st_size;
-
-		/* Record the timestamp of the file */
-		ii->mtime = sb.st_mtime;
-
-		/* image should be NULL unless there is an image malloced
-		 * in already.  Before we malloc again, make sure we don't
-		 * have a memory leak.
-		 */
-		if ( ii->image ) {
-			free( ii->image );
-			/* ii->image = NULL; */ /* not necessary */
-		}
-
-		/* This image will be kept only long enough for the
-		 * download to happen.  After sending the last block,
-		 * it will be freed
-		 */
-		ii->image = malloc(len) ;
-
-		if (ii->image == NULL) {
-			fprintf(stderr,
-				"%s: can't get %d bytes of memory; aborting\n",
-				 pgm, len);
-			exit (1);
-		}
-
-		if (read(sfd, ii->image, len) < len) {
-			fprintf(stderr,"%s: read error on %s; aborting\n",
-				pgm, ii->pathname);
-			exit (1);
-		}
-
-end_rescan:
-		close(sfd);
-
-	}
-}
-
-/*
- * Scan for images to match the driver requests
- */
-
-struct image_info * find_conc_image()
-{
-	int x;
-	struct image_info *i = NULL;
-
-	for ( x = 0; x < nimages; x++ ) {
-		i=&image_list[x];
-
-		if(i->type != ICONC)
-			continue;
-
-		consider_file_rescan(i) ;
-
-		ip = (struct downld_t *) image_list[x].image;
-		if (ip == NULL) continue;
-
-		/*
-		 * When I removed Clusterport, I kept only the code that I
-		 * was SURE wasn't ClusterPort.  We may not need the next two
-		 * lines of code.
-		 */
-		if ((dp->dl_type != 'P' ) && ( ip->dl_srev == dp->dl_srev ))
-			return i;
-	}
-	return NULL;
-}
-
-
-int main(int argc, char **argv)
-{
-	struct downldio	dlio;
-	int 		offset, bsize;
-	int 		x;
-	char 		*down, *image, *fname;
-	struct image_info *ii;
-
-	pgm = argv[0];
-	dp = &dlio.image.dl;		/* conc. download */
-
-	while((argc > 2) && !strcmp(argv[1],"-d")) {
-		debugflag++ ;
-		argc-- ;
-		argv++ ;
-	}
-
-	if(argc < 2) {
-		fprintf(stderr,
-			"usage: %s download-device [image-file] ...\n",
-			pgm);
-		exit(1);
-	}
-
-
-
-	/*
-	 * Daemonize, unless debugging is turned on.
-	 */
-	if (debugflag == 0) {
-		switch (fork())
-		{
-		case 0:
-			break;
-
-		case -1:
-			return 1;
-
-		default:
-			return 0;
-		}
-
-		setsid();
-
-		/*
-		 * The child no longer needs "stdin", "stdout", or "stderr",
-		 * and should not block processes waiting for them to close.
-		 */
-		fclose(stdin);
-		fclose(stdout);
-		fclose(stderr);
-
-	}
-
-	while (1) {
-		if( (fd = open(argv[1], O_RDWR)) == -1 ) {
-			sleep(1);
-		}
-		else
-			break;
-	}
-
-	/*
-	** create a list of images to search through when trying to match
-	** requests from the driver.  Put images from the command line in
-	** the list before built in images so that the command line images
-	** can override the built in ones.
-	*/
-
-	/* allocate space for the list */
-
-	nimages = argc - 2;
-
-	/* count the number of default list entries */
-
-	for (count = 0; images[count].type != IBAD; ++count) ;
-
-	nimages += count;
-
-	/* Really should just remove the variable "image_list".... robertl */
-	image_list = images;
-
-	/* get the images from the command line */
-	for(x = 2; x < argc; x++) {
-		int xx;
-
-		/*
-		 * strip off any leading path information for
-		 * determining file type
-		 */
-		if( (fname = strrchr(argv[x],'/')) == NULL)
-			fname = argv[x];
-		else
-			fname++;	/* skip the slash */
-
-		for (xx = 0; xx < count; xx++) {
-			if (strcmp(fname, images[xx].fname) == 0 ) {
-				images[xx].pathname = argv[x];
-
-				/* image should be NULL until */
-				/* space is malloced */
-				images[xx].image = NULL;
-			}
-		}
-	}
-
-        sleep(3);
-
-	/*
-	** Endless loop: get a request from the fep, and service that request.
-	*/
-	for(;;) {
-		/* get the request */
-		if (debugflag)
-			printf("b4 get ioctl...");
-
-		if (ioctl(fd,DIGI_DLREQ_GET, &dlio) == -1 ) {
-			if (errorprint) {
-				fprintf(stderr,
-					"%s: warning - download ioctl failed\n",
-					pgm);
-				errorprint = 0;
-			}
-			sleep(2);
-		} else {
-			if (debugflag)
-				printf("dlio.req_type is %d bd %d\n",
-					dlio.req_type,dlio.bdid);
-
-			switch(dlio.req_type) {
-			case DLREQ_BIOS:
-				/*
-				** find the bios image for this type
-				*/
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != IBIOS)
-						continue;
-
-					if ((dlio.image.fi.type & FAMILY) ==
-						image_list[x].family) {
-
-						if ( image_list[x].family == T_CX   ) {
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-								break;
-							}
-						}
-						else if ( image_list[x].family == T_EPC ) {
-						/* If subtype of image is T_PCIBUS, it is */
-						/* a PCI EPC image, so the board must */
-						/* have bus type T_PCIBUS to match */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* NON PCI EPC doesn't use PCI image */
-								if ( image_list[x].subtype
-									!= T_PCIBUS )
-									break;
-							}
-						}
-						else
-							break;
-					}
-					else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-						/* PCXR board will break out of the loop here */
-						if ( image_list[x].subtype == T_PCXR   ) {
-									break;
-						}
-					}
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct BIOS image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type = -1;
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1) {
-						if (errorprint) {
-							fprintf(stderr,
-							"%s: warning - download ioctl failed\n",
-							pgm);
-							errorprint = 0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break ;
-
-			case DLREQ_FEP:
-				/*
-				** find the fep image for this type
-				*/
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != IFEP)
-						continue;
-					if( (dlio.image.fi.type & FAMILY) ==
-						image_list[x].family ) {
-						if ( image_list[x].family == T_CX   ) {
-							/* C/X PCI board */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* Regular CX */
-								break;
-							}
-						}
-						else if ( image_list[x].family == T_EPC   )  {
-						/* If subtype of image is T_PCIBUS, it is */
-						/* a PCI EPC image, so the board must */
-						/* have bus type T_PCIBUS to match */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* NON PCI EPC doesn't use PCI image */
-								if ( image_list[x].subtype
-									!= T_PCIBUS )
-									break;
-							}
-						}
-						else
-							break;
-					}
-					else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-						/* PCXR board will break out of the loop here */
-						if ( image_list[x].subtype == T_PCXR   ) {
-									break;
-						}
-					}
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct FEP image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type=-1;
-					if( ioctl(fd,DIGI_DLREQ_SET,&dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-								pgm);
-							errorprint=0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break;
-
-			case DLREQ_DEVCREATE:
-				{
-					char string[1024];
-#if 0
-					sprintf(string, "%s /proc/dgap/%d/mknod", DEFSHELL, dlio.bdid);
-#endif
-					sprintf(string, "%s /usr/sbin/dgap_updatedevs %d", DEFSHELL, dlio.bdid);
-					system(string);
-
-					if (debugflag)
-						printf("Created Devices.\n");
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr, "%s: warning - DEVCREATE ioctl failed\n",pgm);
-							errorprint = 0;
-						}
-						sleep(2);
-					}
-					if (debugflag)
-						printf("After ioctl set - Created Device.\n");
-				}
-
-				break;
-
-			case DLREQ_CONFIG:
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != ICONFIG)
-						continue;
-					else
-						break;
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct CONFIG image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type=-1;
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-								pgm);
-							errorprint=0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break;
-
-			case DLREQ_CONC:
-				/*
-				** find the image needed for this download
-				*/
-				if ( dp->dl_seq == 0 ) {
-					/*
-					** find image for hardware rev range
-					*/
-					for ( x = 0; x < nimages; x++ ) {
-						ii=&image_list[x];
-
-						if(image_list[x].type != ICONC)
-							continue;
-
-						consider_file_rescan(ii) ;
-
-						ip = (struct downld_t *) image_list[x].image;
-						if (ip == NULL) continue;
-
-						/*
-						 * When I removed Clusterport, I kept only the
-						 * code that I was SURE wasn't ClusterPort.
-						 * We may not need the next four lines of code.
-						 */
-
-						if ((dp->dl_type != 'P' ) &&
-						 (ip->dl_lrev <= dp->dl_lrev ) &&
-						 ( dp->dl_lrev <= ip->dl_hrev))
-							break;
-					}
-
-					if ( x >= nimages ) {
-						/*
-						** No valid images exist
-						*/
-						if(nodldprint) {
-							fprintf(stderr,
-						"%s: cannot find correct download image %d\n",
-								pgm, dp->dl_lrev);
-							nodldprint=0;
-						}
-						continue;
-					}
-
-				} else {
-					/*
-					** find image version required
-					*/
-					if ((ii = find_conc_image()) == NULL ) {
-						/*
-						** No valid images exist
-						*/
-						fprintf(stderr,
-						"%s: can't find rest of download image??\n",
-							pgm);
-						continue;
-					}
-				}
-
-				/*
-				** download block of image
-				*/
-
-				offset = 1024 * dp->dl_seq;
-
-				/*
-				** test if block requested within image
-				*/
-				if ( offset < ii->len ) {
-
-					/*
-					** if it is, determine block size, set segment,
-					** set size, set pointers, and copy block
-					*/
-					if (( bsize = ii->len - offset ) > 1024 )
-						bsize = 1024;
-
-					/*
-					** copy image version info to download area
-					*/
-					dp->dl_srev = ip->dl_srev;
-					dp->dl_lrev = ip->dl_lrev;
-					dp->dl_hrev = ip->dl_hrev;
-
-					dp->dl_seg = (64 * dp->dl_seq) + ip->dl_seg;
-					dp->dl_size = bsize;
-
-					down = (char *)&dp->dl_data[0];
-					image = (char *)((char *)ip + offset);
-
-					memcpy(down, image, bsize);
-				}
-				else {
-					/*
-					** Image has been downloaded, set segment and
-					** size to indicate no more blocks
-					*/
-					dp->dl_seg = ip->dl_seg;
-					dp->dl_size = 0;
-
-					/* Now, we can release the concentrator */
-					/* image from memory if we're running  */
-					/* from filesystem images */
-
-					if (ii->pathname)
-						if (ii->image) {
-							free(ii->image);
-							ii->image = NULL;
-						}
-				}
-
-				if (debugflag)
-						printf(
-						"sending conc dl section %d to %s from %s\n",
-							dp->dl_seq, ii->name,
-						ii->pathname ? ii->pathname : "Internal Image");
-
-				if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-					if (errorprint) {
-						fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-							pgm);
-						errorprint=0;
-					}
-					sleep(2);
-				}
-				break;
-			} /* switch */
-		}
-		if (debugflag > 1) {
-			printf("pausing: "); fflush(stdout);
-			fflush(stdin);
-			while(getchar() != '\n');
-				printf("continuing\n");
-		}
-	}
-}
-
-/*
-** myperror()
-**
-**  Same as normal perror(), but places the program name at the beginning
-**  of the message.
-*/
-void myperror(char *s)
-{
-	fprintf(stderr,"%s: %s: %s.\n",pgm, s, strerror(errno));
-}
diff --git a/drivers/staging/echo/Kconfig b/drivers/staging/echo/Kconfig
deleted file mode 100644
index f1d41ea9cd48..000000000000
--- a/drivers/staging/echo/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config ECHO
-	tristate "Line Echo Canceller support"
-	default n
-	---help---
-	  This driver provides line echo cancelling support for mISDN and
-	  Zaptel drivers.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called echo.
diff --git a/drivers/staging/echo/Makefile b/drivers/staging/echo/Makefile
deleted file mode 100644
index 7d4caac12a8d..000000000000
--- a/drivers/staging/echo/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_ECHO) += echo.o
diff --git a/drivers/staging/echo/TODO b/drivers/staging/echo/TODO
deleted file mode 100644
index 72a311a5a9cc..000000000000
--- a/drivers/staging/echo/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
-	- send to lkml for review
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: Steve
-Underwood <steveu@coppice.org> and David Rowe <david@rowetel.com>
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
deleted file mode 100644
index 9597e9523cac..000000000000
--- a/drivers/staging/echo/echo.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * echo.c - A line echo canceller.  This code is being developed
- *          against and partially complies with G168.
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *         and David Rowe <david_at_rowetel_dot_com>
- *
- * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
- *
- * Based on a bit from here, a bit from there, eye of toad, ear of
- * bat, 15 years of failed attempts by David and a few fried brain
- * cells.
- *
- * 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.
- *
- * 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.
- */
-
-/*! \file */
-
-/* Implementation Notes
-   David Rowe
-   April 2007
-
-   This code started life as Steve's NLMS algorithm with a tap
-   rotation algorithm to handle divergence during double talk.  I
-   added a Geigel Double Talk Detector (DTD) [2] and performed some
-   G168 tests.  However I had trouble meeting the G168 requirements,
-   especially for double talk - there were always cases where my DTD
-   failed, for example where near end speech was under the 6dB
-   threshold required for declaring double talk.
-
-   So I tried a two path algorithm [1], which has so far given better
-   results.  The original tap rotation/Geigel algorithm is available
-   in SVN http://svn.rowetel.com/software/oslec/tags/before_16bit.
-   It's probably possible to make it work if some one wants to put some
-   serious work into it.
-
-   At present no special treatment is provided for tones, which
-   generally cause NLMS algorithms to diverge.  Initial runs of a
-   subset of the G168 tests for tones (e.g ./echo_test 6) show the
-   current algorithm is passing OK, which is kind of surprising.  The
-   full set of tests needs to be performed to confirm this result.
-
-   One other interesting change is that I have managed to get the NLMS
-   code to work with 16 bit coefficients, rather than the original 32
-   bit coefficents.  This reduces the MIPs and storage required.
-   I evaulated the 16 bit port using g168_tests.sh and listening tests
-   on 4 real-world samples.
-
-   I also attempted the implementation of a block based NLMS update
-   [2] but although this passes g168_tests.sh it didn't converge well
-   on the real-world samples.  I have no idea why, perhaps a scaling
-   problem.  The block based code is also available in SVN
-   http://svn.rowetel.com/software/oslec/tags/before_16bit.  If this
-   code can be debugged, it will lead to further reduction in MIPS, as
-   the block update code maps nicely onto DSP instruction sets (it's a
-   dot product) compared to the current sample-by-sample update.
-
-   Steve also has some nice notes on echo cancellers in echo.h
-
-   References:
-
-   [1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
-       Path Models", IEEE Transactions on communications, COM-25,
-       No. 6, June
-       1977.
-       http://www.rowetel.com/images/echo/dual_path_paper.pdf
-
-   [2] The classic, very useful paper that tells you how to
-       actually build a real world echo canceller:
-	 Messerschmitt, Hedberg, Cole, Haoui, Winship, "Digital Voice
-	 Echo Canceller with a TMS320020,
-	 http://www.rowetel.com/images/echo/spra129.pdf
-
-   [3] I have written a series of blog posts on this work, here is
-       Part 1: http://www.rowetel.com/blog/?p=18
-
-   [4] The source code http://svn.rowetel.com/software/oslec/
-
-   [5] A nice reference on LMS filters:
-	 http://en.wikipedia.org/wiki/Least_mean_squares_filter
-
-   Credits:
-
-   Thanks to Steve Underwood, Jean-Marc Valin, and Ramakrishnan
-   Muthukrishnan for their suggestions and email discussions.  Thanks
-   also to those people who collected echo samples for me such as
-   Mark, Pawel, and Pavel.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "echo.h"
-
-#define MIN_TX_POWER_FOR_ADAPTION	64
-#define MIN_RX_POWER_FOR_ADAPTION	64
-#define DTD_HANGOVER			600	/* 600 samples, or 75ms     */
-#define DC_LOG2BETA			3	/* log2() of DC filter Beta */
-
-/* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
-
-#ifdef __bfin__
-static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
-{
-	int i;
-	int offset1;
-	int offset2;
-	int factor;
-	int exp;
-	int16_t *phist;
-	int n;
-
-	if (shift > 0)
-		factor = clean << shift;
-	else
-		factor = clean >> -shift;
-
-	/* Update the FIR taps */
-
-	offset2 = ec->curr_pos;
-	offset1 = ec->taps - offset2;
-	phist = &ec->fir_state_bg.history[offset2];
-
-	/* st: and en: help us locate the assembler in echo.s */
-
-	/* asm("st:"); */
-	n = ec->taps;
-	for (i = 0; i < n; i++) {
-		exp = *phist++ * factor;
-		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
-	}
-	/* asm("en:"); */
-
-	/* Note the asm for the inner loop above generated by Blackfin gcc
-	   4.1.1 is pretty good (note even parallel instructions used):
-
-	   R0 = W [P0++] (X);
-	   R0 *= R2;
-	   R0 = R0 + R3 (NS) ||
-	   R1 = W [P1] (X) ||
-	   nop;
-	   R0 >>>= 15;
-	   R0 = R0 + R1;
-	   W [P1++] = R0;
-
-	   A block based update algorithm would be much faster but the
-	   above can't be improved on much.  Every instruction saved in
-	   the loop above is 2 MIPs/ch!  The for loop above is where the
-	   Blackfin spends most of it's time - about 17 MIPs/ch measured
-	   with speedtest.c with 256 taps (32ms).  Write-back and
-	   Write-through cache gave about the same performance.
-	 */
-}
-
-/*
-   IDEAS for further optimisation of lms_adapt_bg():
-
-   1/ The rounding is quite costly.  Could we keep as 32 bit coeffs
-   then make filter pluck the MS 16-bits of the coeffs when filtering?
-   However this would lower potential optimisation of filter, as I
-   think the dual-MAC architecture requires packed 16 bit coeffs.
-
-   2/ Block based update would be more efficient, as per comments above,
-   could use dual MAC architecture.
-
-   3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC
-   packing.
-
-   4/ Execute the whole e/c in a block of say 20ms rather than sample
-   by sample.  Processing a few samples every ms is inefficient.
-*/
-
-#else
-static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
-{
-	int i;
-
-	int offset1;
-	int offset2;
-	int factor;
-	int exp;
-
-	if (shift > 0)
-		factor = clean << shift;
-	else
-		factor = clean >> -shift;
-
-	/* Update the FIR taps */
-
-	offset2 = ec->curr_pos;
-	offset1 = ec->taps - offset2;
-
-	for (i = ec->taps - 1; i >= offset1; i--) {
-		exp = (ec->fir_state_bg.history[i - offset1] * factor);
-		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
-	}
-	for (; i >= 0; i--) {
-		exp = (ec->fir_state_bg.history[i + offset2] * factor);
-		ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
-	}
-}
-#endif
-
-static inline int top_bit(unsigned int bits)
-{
-	if (bits == 0)
-		return -1;
-	else
-		return (int)fls((int32_t) bits) - 1;
-}
-
-struct oslec_state *oslec_create(int len, int adaption_mode)
-{
-	struct oslec_state *ec;
-	int i;
-	const int16_t *history;
-
-	ec = kzalloc(sizeof(*ec), GFP_KERNEL);
-	if (!ec)
-		return NULL;
-
-	ec->taps = len;
-	ec->log2taps = top_bit(len);
-	ec->curr_pos = ec->taps - 1;
-
-	ec->fir_taps16[0] =
-	    kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
-	if (!ec->fir_taps16[0])
-		goto error_oom_0;
-
-	ec->fir_taps16[1] =
-	    kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
-	if (!ec->fir_taps16[1])
-		goto error_oom_1;
-
-	history = fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
-	if (!history)
-		goto error_state;
-	history = fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
-	if (!history)
-		goto error_state_bg;
-
-	for (i = 0; i < 5; i++)
-		ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
-
-	ec->cng_level = 1000;
-	oslec_adaption_mode(ec, adaption_mode);
-
-	ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
-	if (!ec->snapshot)
-		goto error_snap;
-
-	ec->cond_met = 0;
-	ec->pstates = 0;
-	ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
-	ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
-	ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
-	ec->lbgn = ec->lbgn_acc = 0;
-	ec->lbgn_upper = 200;
-	ec->lbgn_upper_acc = ec->lbgn_upper << 13;
-
-	return ec;
-
-error_snap:
-	fir16_free(&ec->fir_state_bg);
-error_state_bg:
-	fir16_free(&ec->fir_state);
-error_state:
-	kfree(ec->fir_taps16[1]);
-error_oom_1:
-	kfree(ec->fir_taps16[0]);
-error_oom_0:
-	kfree(ec);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(oslec_create);
-
-void oslec_free(struct oslec_state *ec)
-{
-	int i;
-
-	fir16_free(&ec->fir_state);
-	fir16_free(&ec->fir_state_bg);
-	for (i = 0; i < 2; i++)
-		kfree(ec->fir_taps16[i]);
-	kfree(ec->snapshot);
-	kfree(ec);
-}
-EXPORT_SYMBOL_GPL(oslec_free);
-
-void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
-{
-	ec->adaption_mode = adaption_mode;
-}
-EXPORT_SYMBOL_GPL(oslec_adaption_mode);
-
-void oslec_flush(struct oslec_state *ec)
-{
-	int i;
-
-	ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
-	ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
-	ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
-
-	ec->lbgn = ec->lbgn_acc = 0;
-	ec->lbgn_upper = 200;
-	ec->lbgn_upper_acc = ec->lbgn_upper << 13;
-
-	ec->nonupdate_dwell = 0;
-
-	fir16_flush(&ec->fir_state);
-	fir16_flush(&ec->fir_state_bg);
-	ec->fir_state.curr_pos = ec->taps - 1;
-	ec->fir_state_bg.curr_pos = ec->taps - 1;
-	for (i = 0; i < 2; i++)
-		memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
-
-	ec->curr_pos = ec->taps - 1;
-	ec->pstates = 0;
-}
-EXPORT_SYMBOL_GPL(oslec_flush);
-
-void oslec_snapshot(struct oslec_state *ec)
-{
-	memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
-}
-EXPORT_SYMBOL_GPL(oslec_snapshot);
-
-/* Dual Path Echo Canceller */
-
-int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
-{
-	int32_t echo_value;
-	int clean_bg;
-	int tmp;
-	int tmp1;
-
-	/*
-	 * Input scaling was found be required to prevent problems when tx
-	 * starts clipping.  Another possible way to handle this would be the
-	 * filter coefficent scaling.
-	 */
-
-	ec->tx = tx;
-	ec->rx = rx;
-	tx >>= 1;
-	rx >>= 1;
-
-	/*
-	 * Filter DC, 3dB point is 160Hz (I think), note 32 bit precision
-	 * required otherwise values do not track down to 0. Zero at DC, Pole
-	 * at (1-Beta) on real axis.  Some chip sets (like Si labs) don't
-	 * need this, but something like a $10 X100P card does.  Any DC really
-	 * slows down convergence.
-	 *
-	 * Note: removes some low frequency from the signal, this reduces the
-	 * speech quality when listening to samples through headphones but may
-	 * not be obvious through a telephone handset.
-	 *
-	 * Note that the 3dB frequency in radians is approx Beta, e.g. for Beta
-	 * = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
-	 */
-
-	if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
-		tmp = rx << 15;
-
-		/*
-		 * Make sure the gain of the HPF is 1.0. This can still
-		 * saturate a little under impulse conditions, and it might
-		 * roll to 32768 and need clipping on sustained peak level
-		 * signals. However, the scale of such clipping is small, and
-		 * the error due to any saturation should not markedly affect
-		 * the downstream processing.
-		 */
-		tmp -= (tmp >> 4);
-
-		ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
-
-		/*
-		 * hard limit filter to prevent clipping.  Note that at this
-		 * stage rx should be limited to +/- 16383 due to right shift
-		 * above
-		 */
-		tmp1 = ec->rx_1 >> 15;
-		if (tmp1 > 16383)
-			tmp1 = 16383;
-		if (tmp1 < -16383)
-			tmp1 = -16383;
-		rx = tmp1;
-		ec->rx_2 = tmp;
-	}
-
-	/* Block average of power in the filter states.  Used for
-	   adaption power calculation. */
-
-	{
-		int new, old;
-
-		/* efficient "out with the old and in with the new" algorithm so
-		   we don't have to recalculate over the whole block of
-		   samples. */
-		new = (int)tx * (int)tx;
-		old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
-		    (int)ec->fir_state.history[ec->fir_state.curr_pos];
-		ec->pstates +=
-		    ((new - old) + (1 << (ec->log2taps - 1))) >> ec->log2taps;
-		if (ec->pstates < 0)
-			ec->pstates = 0;
-	}
-
-	/* Calculate short term average levels using simple single pole IIRs */
-
-	ec->ltxacc += abs(tx) - ec->ltx;
-	ec->ltx = (ec->ltxacc + (1 << 4)) >> 5;
-	ec->lrxacc += abs(rx) - ec->lrx;
-	ec->lrx = (ec->lrxacc + (1 << 4)) >> 5;
-
-	/* Foreground filter */
-
-	ec->fir_state.coeffs = ec->fir_taps16[0];
-	echo_value = fir16(&ec->fir_state, tx);
-	ec->clean = rx - echo_value;
-	ec->lcleanacc += abs(ec->clean) - ec->lclean;
-	ec->lclean = (ec->lcleanacc + (1 << 4)) >> 5;
-
-	/* Background filter */
-
-	echo_value = fir16(&ec->fir_state_bg, tx);
-	clean_bg = rx - echo_value;
-	ec->lclean_bgacc += abs(clean_bg) - ec->lclean_bg;
-	ec->lclean_bg = (ec->lclean_bgacc + (1 << 4)) >> 5;
-
-	/* Background Filter adaption */
-
-	/* Almost always adap bg filter, just simple DT and energy
-	   detection to minimise adaption in cases of strong double talk.
-	   However this is not critical for the dual path algorithm.
-	 */
-	ec->factor = 0;
-	ec->shift = 0;
-	if ((ec->nonupdate_dwell == 0)) {
-		int p, logp, shift;
-
-		/* Determine:
-
-		   f = Beta * clean_bg_rx/P ------ (1)
-
-		   where P is the total power in the filter states.
-
-		   The Boffins have shown that if we obey (1) we converge
-		   quickly and avoid instability.
-
-		   The correct factor f must be in Q30, as this is the fixed
-		   point format required by the lms_adapt_bg() function,
-		   therefore the scaled version of (1) is:
-
-		   (2^30) * f  = (2^30) * Beta * clean_bg_rx/P
-		   factor      = (2^30) * Beta * clean_bg_rx/P     ----- (2)
-
-		   We have chosen Beta = 0.25 by experiment, so:
-
-		   factor      = (2^30) * (2^-2) * clean_bg_rx/P
-
-		   (30 - 2 - log2(P))
-		   factor      = clean_bg_rx 2                     ----- (3)
-
-		   To avoid a divide we approximate log2(P) as top_bit(P),
-		   which returns the position of the highest non-zero bit in
-		   P.  This approximation introduces an error as large as a
-		   factor of 2, but the algorithm seems to handle it OK.
-
-		   Come to think of it a divide may not be a big deal on a
-		   modern DSP, so its probably worth checking out the cycles
-		   for a divide versus a top_bit() implementation.
-		 */
-
-		p = MIN_TX_POWER_FOR_ADAPTION + ec->pstates;
-		logp = top_bit(p) + ec->log2taps;
-		shift = 30 - 2 - logp;
-		ec->shift = shift;
-
-		lms_adapt_bg(ec, clean_bg, shift);
-	}
-
-	/* very simple DTD to make sure we dont try and adapt with strong
-	   near end speech */
-
-	ec->adapt = 0;
-	if ((ec->lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->lrx > ec->ltx))
-		ec->nonupdate_dwell = DTD_HANGOVER;
-	if (ec->nonupdate_dwell)
-		ec->nonupdate_dwell--;
-
-	/* Transfer logic */
-
-	/* These conditions are from the dual path paper [1], I messed with
-	   them a bit to improve performance. */
-
-	if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
-	    (ec->nonupdate_dwell == 0) &&
-	    /* (ec->Lclean_bg < 0.875*ec->Lclean) */
-	    (8 * ec->lclean_bg < 7 * ec->lclean) &&
-	    /* (ec->Lclean_bg < 0.125*ec->Ltx) */
-	    (8 * ec->lclean_bg < ec->ltx)) {
-		if (ec->cond_met == 6) {
-			/*
-			 * BG filter has had better results for 6 consecutive
-			 * samples
-			 */
-			ec->adapt = 1;
-			memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
-			       ec->taps * sizeof(int16_t));
-		} else
-			ec->cond_met++;
-	} else
-		ec->cond_met = 0;
-
-	/* Non-Linear Processing */
-
-	ec->clean_nlp = ec->clean;
-	if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
-		/*
-		 * Non-linear processor - a fancy way to say "zap small
-		 * signals, to avoid residual echo due to (uLaw/ALaw)
-		 * non-linearity in the channel.".
-		 */
-
-		if ((16 * ec->lclean < ec->ltx)) {
-			/*
-			 * Our e/c has improved echo by at least 24 dB (each
-			 * factor of 2 is 6dB, so 2*2*2*2=16 is the same as
-			 * 6+6+6+6=24dB)
-			 */
-			if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
-				ec->cng_level = ec->lbgn;
-
-				/*
-				 * Very elementary comfort noise generation.
-				 * Just random numbers rolled off very vaguely
-				 * Hoth-like.  DR: This noise doesn't sound
-				 * quite right to me - I suspect there are some
-				 * overflow issues in the filtering as it's too
-				 * "crackly".
-				 * TODO: debug this, maybe just play noise at
-				 * high level or look at spectrum.
-				 */
-
-				ec->cng_rndnum =
-				    1664525U * ec->cng_rndnum + 1013904223U;
-				ec->cng_filter =
-				    ((ec->cng_rndnum & 0xFFFF) - 32768 +
-				     5 * ec->cng_filter) >> 3;
-				ec->clean_nlp =
-				    (ec->cng_filter * ec->cng_level * 8) >> 14;
-
-			} else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
-				/* This sounds much better than CNG */
-				if (ec->clean_nlp > ec->lbgn)
-					ec->clean_nlp = ec->lbgn;
-				if (ec->clean_nlp < -ec->lbgn)
-					ec->clean_nlp = -ec->lbgn;
-			} else {
-				/*
-				 * just mute the residual, doesn't sound very
-				 * good, used mainly in G168 tests
-				 */
-				ec->clean_nlp = 0;
-			}
-		} else {
-			/*
-			 * Background noise estimator.  I tried a few
-			 * algorithms here without much luck.  This very simple
-			 * one seems to work best, we just average the level
-			 * using a slow (1 sec time const) filter if the
-			 * current level is less than a (experimentally
-			 * derived) constant.  This means we dont include high
-			 * level signals like near end speech.  When combined
-			 * with CNG or especially CLIP seems to work OK.
-			 */
-			if (ec->lclean < 40) {
-				ec->lbgn_acc += abs(ec->clean) - ec->lbgn;
-				ec->lbgn = (ec->lbgn_acc + (1 << 11)) >> 12;
-			}
-		}
-	}
-
-	/* Roll around the taps buffer */
-	if (ec->curr_pos <= 0)
-		ec->curr_pos = ec->taps;
-	ec->curr_pos--;
-
-	if (ec->adaption_mode & ECHO_CAN_DISABLE)
-		ec->clean_nlp = rx;
-
-	/* Output scaled back up again to match input scaling */
-
-	return (int16_t) ec->clean_nlp << 1;
-}
-EXPORT_SYMBOL_GPL(oslec_update);
-
-/* This function is separated from the echo canceller is it is usually called
-   as part of the tx process.  See rx HP (DC blocking) filter above, it's
-   the same design.
-
-   Some soft phones send speech signals with a lot of low frequency
-   energy, e.g. down to 20Hz.  This can make the hybrid non-linear
-   which causes the echo canceller to fall over.  This filter can help
-   by removing any low frequency before it gets to the tx port of the
-   hybrid.
-
-   It can also help by removing and DC in the tx signal.  DC is bad
-   for LMS algorithms.
-
-   This is one of the classic DC removal filters, adjusted to provide
-   sufficient bass rolloff to meet the above requirement to protect hybrids
-   from things that upset them. The difference between successive samples
-   produces a lousy HPF, and then a suitably placed pole flattens things out.
-   The final result is a nicely rolled off bass end. The filtering is
-   implemented with extended fractional precision, which noise shapes things,
-   giving very clean DC removal.
-*/
-
-int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
-{
-	int tmp;
-	int tmp1;
-
-	if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
-		tmp = tx << 15;
-
-		/*
-		 * Make sure the gain of the HPF is 1.0. The first can still
-		 * saturate a little under impulse conditions, and it might
-		 * roll to 32768 and need clipping on sustained peak level
-		 * signals. However, the scale of such clipping is small, and
-		 * the error due to any saturation should not markedly affect
-		 * the downstream processing.
-		 */
-		tmp -= (tmp >> 4);
-
-		ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
-		tmp1 = ec->tx_1 >> 15;
-		if (tmp1 > 32767)
-			tmp1 = 32767;
-		if (tmp1 < -32767)
-			tmp1 = -32767;
-		tx = tmp1;
-		ec->tx_2 = tmp;
-	}
-
-	return tx;
-}
-EXPORT_SYMBOL_GPL(oslec_hpf_tx);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Rowe");
-MODULE_DESCRIPTION("Open Source Line Echo Canceller");
-MODULE_VERSION("0.3.0");
diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h
deleted file mode 100644
index 9b08c63e6369..000000000000
--- a/drivers/staging/echo/echo.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * echo.c - A line echo canceller.  This code is being developed
- *          against and partially complies with G168.
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *         and David Rowe <david_at_rowetel_dot_com>
- *
- * Copyright (C) 2001 Steve Underwood and 2007 David Rowe
- *
- * 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.
- *
- * 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 __ECHO_H
-#define __ECHO_H
-
-/*
-Line echo cancellation for voice
-
-What does it do?
-
-This module aims to provide G.168-2002 compliant echo cancellation, to remove
-electrical echoes (e.g. from 2-4 wire hybrids) from voice calls.
-
-How does it work?
-
-The heart of the echo cancellor is FIR filter. This is adapted to match the
-echo impulse response of the telephone line. It must be long enough to
-adequately cover the duration of that impulse response. The signal transmitted
-to the telephone line is passed through the FIR filter. Once the FIR is
-properly adapted, the resulting output is an estimate of the echo signal
-received from the line. This is subtracted from the received signal. The result
-is an estimate of the signal which originated at the far end of the line, free
-from echos of our own transmitted signal.
-
-The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and
-was introduced in 1960. It is the commonest form of filter adaption used in
-things like modem line equalisers and line echo cancellers. There it works very
-well.  However, it only works well for signals of constant amplitude. It works
-very poorly for things like speech echo cancellation, where the signal level
-varies widely.  This is quite easy to fix. If the signal level is normalised -
-similar to applying AGC - LMS can work as well for a signal of varying
-amplitude as it does for a modem signal. This normalised least mean squares
-(NLMS) algorithm is the commonest one used for speech echo cancellation. Many
-other algorithms exist - e.g. RLS (essentially the same as Kalman filtering),
-FAP, etc. Some perform significantly better than NLMS.  However, factors such
-as computational complexity and patents favour the use of NLMS.
-
-A simple refinement to NLMS can improve its performance with speech. NLMS tends
-to adapt best to the strongest parts of a signal. If the signal is white noise,
-the NLMS algorithm works very well. However, speech has more low frequency than
-high frequency content. Pre-whitening (i.e. filtering the signal to flatten its
-spectrum) the echo signal improves the adapt rate for speech, and ensures the
-final residual signal is not heavily biased towards high frequencies. A very
-low complexity filter is adequate for this, so pre-whitening adds little to the
-compute requirements of the echo canceller.
-
-An FIR filter adapted using pre-whitened NLMS performs well, provided certain
-conditions are met:
-
-    - The transmitted signal has poor self-correlation.
-    - There is no signal being generated within the environment being
-      cancelled.
-
-The difficulty is that neither of these can be guaranteed.
-
-If the adaption is performed while transmitting noise (or something fairly
-noise like, such as voice) the adaption works very well. If the adaption is
-performed while transmitting something highly correlative (typically narrow
-band energy such as signalling tones or DTMF), the adaption can go seriously
-wrong. The reason is there is only one solution for the adaption on a near
-random signal - the impulse response of the line. For a repetitive signal,
-there are any number of solutions which converge the adaption, and nothing
-guides the adaption to choose the generalised one. Allowing an untrained
-canceller to converge on this kind of narrowband energy probably a good thing,
-since at least it cancels the tones. Allowing a well converged canceller to
-continue converging on such energy is just a way to ruin its generalised
-adaption. A narrowband detector is needed, so adapation can be suspended at
-appropriate times.
-
-The adaption process is based on trying to eliminate the received signal. When
-there is any signal from within the environment being cancelled it may upset
-the adaption process. Similarly, if the signal we are transmitting is small,
-noise may dominate and disturb the adaption process. If we can ensure that the
-adaption is only performed when we are transmitting a significant signal level,
-and the environment is not, things will be OK. Clearly, it is easy to tell when
-we are sending a significant signal. Telling, if the environment is generating
-a significant signal, and doing it with sufficient speed that the adaption will
-not have diverged too much more we stop it, is a little harder.
-
-The key problem in detecting when the environment is sourcing significant
-energy is that we must do this very quickly. Given a reasonably long sample of
-the received signal, there are a number of strategies which may be used to
-assess whether that signal contains a strong far end component. However, by the
-time that assessment is complete the far end signal will have already caused
-major mis-convergence in the adaption process. An assessment algorithm is
-needed which produces a fairly accurate result from a very short burst of far
-end energy.
-
-How do I use it?
-
-The echo cancellor processes both the transmit and receive streams sample by
-sample. The processing function is not declared inline. Unfortunately,
-cancellation requires many operations per sample, so the call overhead is only
-a minor burden.
-*/
-
-#include "fir.h"
-#include "oslec.h"
-
-/*
-    G.168 echo canceller descriptor. This defines the working state for a line
-    echo canceller.
-*/
-struct oslec_state {
-	int16_t tx;
-	int16_t rx;
-	int16_t clean;
-	int16_t clean_nlp;
-
-	int nonupdate_dwell;
-	int curr_pos;
-	int taps;
-	int log2taps;
-	int adaption_mode;
-
-	int cond_met;
-	int32_t pstates;
-	int16_t adapt;
-	int32_t factor;
-	int16_t shift;
-
-	/* Average levels and averaging filter states */
-	int ltxacc;
-	int lrxacc;
-	int lcleanacc;
-	int lclean_bgacc;
-	int ltx;
-	int lrx;
-	int lclean;
-	int lclean_bg;
-	int lbgn;
-	int lbgn_acc;
-	int lbgn_upper;
-	int lbgn_upper_acc;
-
-	/* foreground and background filter states */
-	struct fir16_state_t fir_state;
-	struct fir16_state_t fir_state_bg;
-	int16_t *fir_taps16[2];
-
-	/* DC blocking filter states */
-	int tx_1;
-	int tx_2;
-	int rx_1;
-	int rx_2;
-
-	/* optional High Pass Filter states */
-	int32_t xvtx[5];
-	int32_t yvtx[5];
-	int32_t xvrx[5];
-	int32_t yvrx[5];
-
-	/* Parameters for the optional Hoth noise generator */
-	int cng_level;
-	int cng_rndnum;
-	int cng_filter;
-
-	/* snapshot sample of coeffs used for development */
-	int16_t *snapshot;
-};
-
-#endif /* __ECHO_H */
diff --git a/drivers/staging/echo/fir.h b/drivers/staging/echo/fir.h
deleted file mode 100644
index 7b9fabf1fea5..000000000000
--- a/drivers/staging/echo/fir.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * fir.h - General telephony FIR routines
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2002 Steve Underwood
- *
- * 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.
- *
- * 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.
- */
-
-#if !defined(_FIR_H_)
-#define _FIR_H_
-
-/*
-   Blackfin NOTES & IDEAS:
-
-   A simple dot product function is used to implement the filter.  This performs
-   just one MAC/cycle which is inefficient but was easy to implement as a first
-   pass.  The current Blackfin code also uses an unrolled form of the filter
-   history to avoid 0 length hardware loop issues.  This is wasteful of
-   memory.
-
-   Ideas for improvement:
-
-   1/ Rewrite filter for dual MAC inner loop.  The issue here is handling
-   history sample offsets that are 16 bit aligned - the dual MAC needs
-   32 bit aligmnent.  There are some good examples in libbfdsp.
-
-   2/ Use the hardware circular buffer facility tohalve memory usage.
-
-   3/ Consider using internal memory.
-
-   Using less memory might also improve speed as cache misses will be
-   reduced. A drop in MIPs and memory approaching 50% should be
-   possible.
-
-   The foreground and background filters currenlty use a total of
-   about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
-   can.
-*/
-
-/*
- * 16 bit integer FIR descriptor. This defines the working state for a single
- * instance of an FIR filter using 16 bit integer coefficients.
- */
-struct fir16_state_t {
-	int taps;
-	int curr_pos;
-	const int16_t *coeffs;
-	int16_t *history;
-};
-
-/*
- * 32 bit integer FIR descriptor. This defines the working state for a single
- * instance of an FIR filter using 32 bit integer coefficients, and filtering
- * 16 bit integer data.
- */
-struct fir32_state_t {
-	int taps;
-	int curr_pos;
-	const int32_t *coeffs;
-	int16_t *history;
-};
-
-/*
- * Floating point FIR descriptor. This defines the working state for a single
- * instance of an FIR filter using floating point coefficients and data.
- */
-struct fir_float_state_t {
-	int taps;
-	int curr_pos;
-	const float *coeffs;
-	float *history;
-};
-
-static inline const int16_t *fir16_create(struct fir16_state_t *fir,
-					      const int16_t *coeffs, int taps)
-{
-	fir->taps = taps;
-	fir->curr_pos = taps - 1;
-	fir->coeffs = coeffs;
-#if defined(__bfin__)
-	fir->history = kcalloc(2 * taps, sizeof(int16_t), GFP_KERNEL);
-#else
-	fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
-#endif
-	return fir->history;
-}
-
-static inline void fir16_flush(struct fir16_state_t *fir)
-{
-#if defined(__bfin__)
-	memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t));
-#else
-	memset(fir->history, 0, fir->taps * sizeof(int16_t));
-#endif
-}
-
-static inline void fir16_free(struct fir16_state_t *fir)
-{
-	kfree(fir->history);
-}
-
-#ifdef __bfin__
-static inline int32_t dot_asm(short *x, short *y, int len)
-{
-	int dot;
-
-	len--;
-
-	__asm__("I0 = %1;\n\t"
-		"I1 = %2;\n\t"
-		"A0 = 0;\n\t"
-		"R0.L = W[I0++] || R1.L = W[I1++];\n\t"
-		"LOOP dot%= LC0 = %3;\n\t"
-		"LOOP_BEGIN dot%=;\n\t"
-		"A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
-		"LOOP_END dot%=;\n\t"
-		"A0 += R0.L*R1.L (IS);\n\t"
-		"R0 = A0;\n\t"
-		"%0 = R0;\n\t"
-		: "=&d"(dot)
-		: "a"(x), "a"(y), "a"(len)
-		: "I0", "I1", "A1", "A0", "R0", "R1"
-	);
-
-	return dot;
-}
-#endif
-
-static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample)
-{
-	int32_t y;
-#if defined(__bfin__)
-	fir->history[fir->curr_pos] = sample;
-	fir->history[fir->curr_pos + fir->taps] = sample;
-	y = dot_asm((int16_t *) fir->coeffs, &fir->history[fir->curr_pos],
-		    fir->taps);
-#else
-	int i;
-	int offset1;
-	int offset2;
-
-	fir->history[fir->curr_pos] = sample;
-
-	offset2 = fir->curr_pos;
-	offset1 = fir->taps - offset2;
-	y = 0;
-	for (i = fir->taps - 1; i >= offset1; i--)
-		y += fir->coeffs[i] * fir->history[i - offset1];
-	for (; i >= 0; i--)
-		y += fir->coeffs[i] * fir->history[i + offset2];
-#endif
-	if (fir->curr_pos <= 0)
-		fir->curr_pos = fir->taps;
-	fir->curr_pos--;
-	return (int16_t) (y >> 15);
-}
-
-static inline const int16_t *fir32_create(struct fir32_state_t *fir,
-					      const int32_t *coeffs, int taps)
-{
-	fir->taps = taps;
-	fir->curr_pos = taps - 1;
-	fir->coeffs = coeffs;
-	fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
-	return fir->history;
-}
-
-static inline void fir32_flush(struct fir32_state_t *fir)
-{
-	memset(fir->history, 0, fir->taps * sizeof(int16_t));
-}
-
-static inline void fir32_free(struct fir32_state_t *fir)
-{
-	kfree(fir->history);
-}
-
-static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample)
-{
-	int i;
-	int32_t y;
-	int offset1;
-	int offset2;
-
-	fir->history[fir->curr_pos] = sample;
-	offset2 = fir->curr_pos;
-	offset1 = fir->taps - offset2;
-	y = 0;
-	for (i = fir->taps - 1; i >= offset1; i--)
-		y += fir->coeffs[i] * fir->history[i - offset1];
-	for (; i >= 0; i--)
-		y += fir->coeffs[i] * fir->history[i + offset2];
-	if (fir->curr_pos <= 0)
-		fir->curr_pos = fir->taps;
-	fir->curr_pos--;
-	return (int16_t) (y >> 15);
-}
-
-#endif
diff --git a/drivers/staging/echo/oslec.h b/drivers/staging/echo/oslec.h
deleted file mode 100644
index f4175360ce27..000000000000
--- a/drivers/staging/echo/oslec.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *  OSLEC - A line echo canceller.  This code is being developed
- *          against and partially complies with G168. Using code from SpanDSP
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *         and David Rowe <david_at_rowetel_dot_com>
- *
- * Copyright (C) 2001 Steve Underwood and 2007-2008 David Rowe
- *
- * 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.
- *
- * 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 __OSLEC_H
-#define __OSLEC_H
-
-/* Mask bits for the adaption mode */
-#define ECHO_CAN_USE_ADAPTION	0x01
-#define ECHO_CAN_USE_NLP	0x02
-#define ECHO_CAN_USE_CNG	0x04
-#define ECHO_CAN_USE_CLIP	0x08
-#define ECHO_CAN_USE_TX_HPF	0x10
-#define ECHO_CAN_USE_RX_HPF	0x20
-#define ECHO_CAN_DISABLE	0x40
-
-/**
- * oslec_state: G.168 echo canceller descriptor.
- *
- * This defines the working state for a line echo canceller.
- */
-struct oslec_state;
-
-/**
- * oslec_create - Create a voice echo canceller context.
- * @len: The length of the canceller, in samples.
- * @return: The new canceller context, or NULL if the canceller could not be
- * created.
- */
-struct oslec_state *oslec_create(int len, int adaption_mode);
-
-/**
- * oslec_free - Free a voice echo canceller context.
- * @ec: The echo canceller context.
- */
-void oslec_free(struct oslec_state *ec);
-
-/**
- * oslec_flush - Flush (reinitialise) a voice echo canceller context.
- * @ec: The echo canceller context.
- */
-void oslec_flush(struct oslec_state *ec);
-
-/**
- * oslec_adaption_mode - set the adaption mode of a voice echo canceller context.
- * @ec The echo canceller context.
- * @adaption_mode: The mode.
- */
-void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode);
-
-void oslec_snapshot(struct oslec_state *ec);
-
-/**
- * oslec_update: Process a sample through a voice echo canceller.
- * @ec: The echo canceller context.
- * @tx: The transmitted audio sample.
- * @rx: The received audio sample.
- *
- * The return value is the clean (echo cancelled) received sample.
- */
-int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx);
-
-/**
- * oslec_hpf_tx: Process to high pass filter the tx signal.
- * @ec: The echo canceller context.
- * @tx: The transmitted auio sample.
- *
- * The return value is the HP filtered transmit sample, send this to your D/A.
- */
-int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx);
-
-#endif /* __OSLEC_H */
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index e516bb69f3b4..cc600df69ec6 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -485,8 +485,6 @@ struct et131x_adapter {
 	u8 eeprom_data[2];
 
 	/* Spinlocks */
-	spinlock_t lock;
-
 	spinlock_t tcb_send_qlock;
 	spinlock_t tcb_ready_qlock;
 	spinlock_t send_hw_lock;
@@ -1388,6 +1386,7 @@ static int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
 			    mii_indicator);
 
 		status = -EIO;
+		goto out;
 	}
 
 	/* If we hit here we were able to read the register and we need to
@@ -1395,6 +1394,7 @@ static int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
 	 */
 	*value = readl(&mac->mii_mgmt_stat) & ET_MAC_MIIMGMT_STAT_PHYCRTL_MASK;
 
+out:
 	/* Stop the read operation */
 	writel(0, &mac->mii_mgmt_cmd);
 
@@ -2124,7 +2124,11 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 
 	/* Alloc memory for the lookup table */
 	rx_ring->fbr[0] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
+	if (rx_ring->fbr[0] == NULL)
+		return -ENOMEM;
 	rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
+	if (rx_ring->fbr[1] == NULL)
+		return -ENOMEM;
 
 	/* The first thing we will do is configure the sizes of the buffer
 	 * rings. These will change based on jumbo packet support.  Larger
@@ -2289,7 +2293,7 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 	for (id = 0; id < NUM_FBRS; id++) {
 		fbr = rx_ring->fbr[id];
 
-		if (!fbr->ring_virtaddr)
+		if (!fbr || !fbr->ring_virtaddr)
 			continue;
 
 		/* First the packet memory */
@@ -3591,6 +3595,7 @@ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
 	if (status) {
 		dev_err(&adapter->pdev->dev,
 			  "et131x_tx_dma_memory_alloc FAILED\n");
+		et131x_tx_dma_memory_free(adapter);
 		return status;
 	}
 	/* Receive buffer memory allocation */
@@ -3598,7 +3603,7 @@ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
 	if (status) {
 		dev_err(&adapter->pdev->dev,
 			  "et131x_rx_dma_memory_alloc FAILED\n");
-		et131x_tx_dma_memory_free(adapter);
+		et131x_adapter_memory_free(adapter);
 		return status;
 	}
 
@@ -3760,7 +3765,6 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
 	adapter->netdev = netdev;
 
 	/* Initialize spinlocks here */
-	spin_lock_init(&adapter->lock);
 	spin_lock_init(&adapter->tcb_send_qlock);
 	spin_lock_init(&adapter->tcb_ready_qlock);
 	spin_lock_init(&adapter->send_hw_lock);
@@ -4292,12 +4296,9 @@ static void et131x_multicast(struct net_device *netdev)
 {
 	struct et131x_adapter *adapter = netdev_priv(netdev);
 	int packet_filter;
-	unsigned long flags;
 	struct netdev_hw_addr *ha;
 	int i;
 
-	spin_lock_irqsave(&adapter->lock, flags);
-
 	/* Before we modify the platform-independent filter flags, store them
 	 * locally. This allows us to determine if anything's changed and if
 	 * we even need to bother the hardware
@@ -4349,8 +4350,6 @@ static void et131x_multicast(struct net_device *netdev)
 	 */
 	if (packet_filter != adapter->packet_filter)
 		et131x_set_packet_filter(adapter);
-
-	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
 /* et131x_tx - The handler to tx a packet on the device */
diff --git a/drivers/staging/frontier/Kconfig b/drivers/staging/frontier/Kconfig
index 7121853bd397..4da290b2f5bd 100644
--- a/drivers/staging/frontier/Kconfig
+++ b/drivers/staging/frontier/Kconfig
@@ -1,6 +1,5 @@
 config TRANZPORT
 	tristate "Frontier Tranzport and Alphatrack support"
 	depends on USB
-	default N
 	---help---
 	  Enable support for the Frontier Tranzport and Alphatrack devices.
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
index 33458a583142..03b43056fcf2 100644
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ b/drivers/staging/gdm724x/gdm_usb.c
@@ -119,28 +119,15 @@ out:
 
 static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
 {
-	struct usb_tx_sdu *t_sdu = NULL;
-	int ret = 0;
-
+	struct usb_tx_sdu *t_sdu;
 
 	t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC);
-	if (!t_sdu) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!t_sdu)
+		return NULL;
 
 	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC);
 	if (!t_sdu->buf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-out:
-
-	if (ret < 0) {
-		if (t_sdu) {
-			kfree(t_sdu->buf);
-			kfree(t_sdu);
-		}
+		kfree(t_sdu);
 		return NULL;
 	}
 
diff --git a/drivers/staging/gs_fpgaboot/Kconfig b/drivers/staging/gs_fpgaboot/Kconfig
new file mode 100644
index 000000000000..550645291fab
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/Kconfig
@@ -0,0 +1,8 @@
+#
+# "xilinx FPGA firmware download, fpgaboot"
+#
+config GS_FPGABOOT
+	tristate "Xilinx FPGA firmware download module"
+	default n
+	help
+	  Xilinx FPGA firmware download module
diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile
new file mode 100644
index 000000000000..34cb606e0e3d
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/Makefile
@@ -0,0 +1,4 @@
+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/README b/drivers/staging/gs_fpgaboot/README
new file mode 100644
index 000000000000..cfa8624304e5
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/README
@@ -0,0 +1,71 @@
+==============================================================================
+Linux Driver Source for Xilinx FPGA firmware download
+==============================================================================
+
+
+TABLE OF CONTENTS.
+
+1.  SUMMARY
+2.  BACKGROUND
+3.  DESIGN
+4.  HOW TO USE
+5.  REFERENCE
+
+1. SUMMARY
+
+	- Download Xilinx FPGA firmware
+	- This module downloads Xilinx FPGA firmware using gpio pins.
+
+2. BACKGROUND
+
+	An FPGA (Field Programmable Gate Array) is a programmable hardware that is
+	used in various applications. Hardware design needs to programmed through
+	a dedicated device or CPU assisted way (serial or parallel).
+	This driver provides a way to download FPGA firmware.
+
+3. DESIGN
+
+	- load Xilinx FPGA bitstream format[1] firmware image file using 
+	  kernel firmware framework, request_firmware()
+	- program the Xilinx FPGA using SelectMAP (parallel) mode [2]
+	- FPGA prgram is done by gpio based bit-banging, as an example
+	- platform independent file: gs_fpgaboot.c
+	- platform dependent file: io.c
+	
+
+4. HOW TO USE
+
+	$ insmod gs_fpga.ko file="xlinx_fpga_top_bitstream.bit"
+	$ rmmod gs_fpga
+
+5. USE CASE (from a mailing list discussion with Greg)
+
+	a. As a FPGA development support tool,
+	During FPGA firmware development, you need to download a new FPGA
+	image frequently.
+	You would do that with a dedicated JTAG, which usually a limited
+	resource in the lab.
+	However, if you use my driver, you don't have to have a dedicated JTAG.
+	This is a real gain :)
+
+	b. For the FPGA that runs without config after the download, which
+	doesn't talk to any of Linux interfaces (such as PCIE).
+
+	We download FPGA firmware from user triggered or some other way, and that's it.
+	Since that FPGA runs on its own, it doesn't require a linux driver
+	after the download.
+
+	c. For the FPGA that requires config after the download, which talk to
+	any of linux interfaces (such as PCIE)
+
+	Then, this type of FPGA config can be put into device tree and have a
+	separate driver (pcie or others), then THAT driver calls my driver to
+	download FPGA firmware during the Linux boot, the take over the device
+	through the interface.
+
+6. REFERENCE
+
+	1. Xilinx APP NOTE XAPP583:
+	  http://www.xilinx.com/support/documentation/application_notes/xapp583-fpga-configuration.pdf
+	2. bitstream file info:
+	  http://home.earthlink.net/~davesullins/software/bitinfo.html
diff --git a/drivers/staging/gs_fpgaboot/TODO b/drivers/staging/gs_fpgaboot/TODO
new file mode 100644
index 000000000000..2d9fb17d606d
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/TODO
@@ -0,0 +1,7 @@
+TODO:
+	- get bus width input instead of hardcoded bus width
+	- get it reviewed
+
+Please send any patches for this driver to Insop Song<insop.song@gainspeed.com>
+and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
+And please CC to "Staging subsystem" mail list <devel@driverdev.osuosl.org> too.
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
new file mode 100644
index 000000000000..89bc84d833e6
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
@@ -0,0 +1,422 @@
+/*
+ * This program is free software; you can redistribute 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/firmware.h>
+
+#include "gs_fpgaboot.h"
+#include "io.h"
+
+#define DEVICE_NAME "device"
+#define CLASS_NAME  "fpgaboot"
+
+static uint8_t bits_magic[] = {
+	0x0, 0x9, 0xf, 0xf0, 0xf, 0xf0,
+	0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x1};
+
+/* fake device for request_firmware */
+static struct platform_device	*firmware_pdev;
+
+static char	*file = "xlinx_fpga_firmware.bit";
+module_param(file, charp, S_IRUGO);
+MODULE_PARM_DESC(file, "Xilinx FPGA firmware file.");
+
+#ifdef DEBUG_FPGA
+static void datadump(char *msg, void *m, int n)
+{
+	int i;
+	unsigned char *c;
+
+	pr_info("=== %s ===\n", msg);
+
+	c = m;
+
+	for (i = 0; i < n; i++) {
+		if ((i&0xf) == 0)
+			pr_info(KERN_INFO "\n  0x%4x: ", i);
+
+		pr_info("%02X ", c[i]);
+	}
+
+	pr_info("\n");
+}
+#endif /* DEBUG_FPGA */
+
+static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize)
+{
+	memcpy(buf, bitdata + *offset, rdsize);
+	*offset += rdsize;
+}
+
+static void readinfo_bitstream(char *bitdata, char *buf, int *offset)
+{
+	char tbuf[64];
+	int32_t len;
+
+	/* read section char */
+	read_bitstream(bitdata, tbuf, offset, 1);
+
+	/* read length */
+	read_bitstream(bitdata, tbuf, offset, 2);
+
+	len = tbuf[0] << 8 | tbuf[1];
+
+	read_bitstream(bitdata, buf, offset, len);
+	buf[len] = '\0';
+}
+
+/*
+ * read bitdata length
+ */
+static int readlength_bitstream(char *bitdata, int *lendata, int *offset)
+{
+	char tbuf[64];
+
+	/* read section char */
+	read_bitstream(bitdata, tbuf, offset, 1);
+
+	/* make sure it is section 'e' */
+	if (tbuf[0] != 'e') {
+		pr_err("error: length section is not 'e', but %c\n", tbuf[0]);
+		return -1;
+	}
+
+	/* read 4bytes length */
+	read_bitstream(bitdata, tbuf, offset, 4);
+
+	*lendata = tbuf[0] << 24 | tbuf[1] << 16 |
+		tbuf[2] << 8 | tbuf[3];
+
+	return 0;
+}
+
+
+/*
+ * read first 13 bytes to check bitstream magic number
+ */
+static int readmagic_bitstream(char *bitdata, int *offset)
+{
+	char buf[13];
+	int r;
+
+	read_bitstream(bitdata, buf, offset, 13);
+	r = memcmp(buf, bits_magic, 13);
+	if (r) {
+		pr_err("error: corrupted header");
+		return -1;
+	}
+	pr_info("bitstream file magic number Ok\n");
+
+	*offset = 13;	/* magic length */
+
+	return 0;
+}
+
+/*
+ * NOTE: supports only bitstream format
+ */
+static enum fmt_image get_imageformat(struct fpgaimage *fimage)
+{
+	return f_bit;
+}
+
+static void gs_print_header(struct fpgaimage *fimage)
+{
+	pr_info("file: %s\n", fimage->filename);
+	pr_info("part: %s\n", fimage->part);
+	pr_info("date: %s\n", fimage->date);
+	pr_info("time: %s\n", fimage->time);
+	pr_info("lendata: %d\n", fimage->lendata);
+}
+
+static void gs_read_bitstream(struct fpgaimage *fimage)
+{
+	char *bitdata;
+	int size;
+	int offset;
+
+	offset = 0;
+	bitdata = (char *)fimage->fw_entry->data;
+	size = fimage->fw_entry->size;
+
+	readmagic_bitstream(bitdata, &offset);
+	readinfo_bitstream(bitdata, fimage->filename, &offset);
+	readinfo_bitstream(bitdata, fimage->part, &offset);
+	readinfo_bitstream(bitdata, fimage->date, &offset);
+	readinfo_bitstream(bitdata, fimage->time, &offset);
+	readlength_bitstream(bitdata, &fimage->lendata, &offset);
+
+	fimage->fpgadata = bitdata + offset;
+}
+
+static int gs_read_image(struct fpgaimage *fimage)
+{
+	int img_fmt;
+
+	img_fmt = get_imageformat(fimage);
+
+	switch (img_fmt) {
+	case f_bit:
+		pr_info("image is bitstream format\n");
+		gs_read_bitstream(fimage);
+		break;
+	default:
+		pr_err("unsupported fpga image format\n");
+		return -1;
+	}
+
+	gs_print_header(fimage);
+
+	return 0;
+}
+
+static int gs_load_image(struct fpgaimage *fimage, char *file)
+{
+	int err;
+
+	pr_info("load fpgaimage %s\n", file);
+
+	err = request_firmware(&fimage->fw_entry, file, &firmware_pdev->dev);
+	if (err != 0) {
+		pr_err("firmware %s is missing, cannot continue.\n", file);
+		return err;
+	}
+
+	return 0;
+}
+
+static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes)
+{
+	char *bitdata;
+	int size, i, cnt;
+	cnt = 0;
+
+	bitdata = (char *)fimage->fpgadata;
+	size = fimage->lendata;
+
+#ifdef DEBUG_FPGA
+	datadump("bitfile sample", bitdata, 0x100);
+#endif /* DEBUG_FPGA */
+
+	if (!xl_supported_prog_bus_width(bus_bytes)) {
+		pr_err("unsupported program bus width %d\n",
+				bus_bytes);
+		return -1;
+	}
+
+	/* Bring csi_b, rdwr_b Low and program_b High */
+	xl_program_b(1);
+	xl_rdwr_b(0);
+	xl_csi_b(0);
+
+	/* Configuration reset */
+	xl_program_b(0);
+	msleep(20);
+	xl_program_b(1);
+
+	/* Wait for Device Initialization */
+	while (xl_get_init_b() == 0)
+		;
+
+	pr_info("device init done\n");
+
+	for (i = 0; i < size; i += bus_bytes)
+		xl_shift_bytes_out(bus_bytes, bitdata+i);
+
+	pr_info("program done\n");
+
+	/* Check INIT_B */
+	if (xl_get_init_b() == 0) {
+		pr_err("init_b 0\n");
+		return -1;
+	}
+
+	while (xl_get_done_b() == 0) {
+		if (cnt++ > MAX_WAIT_DONE) {
+			pr_err("init_B %d\n", xl_get_init_b());
+			break;
+		}
+	}
+
+	if (cnt > MAX_WAIT_DONE) {
+		pr_err("fpga download fail\n");
+		return -1;
+	}
+
+	pr_info("download fpgaimage\n");
+
+	/* Compensate for Special Startup Conditions */
+	xl_shift_cclk(8);
+
+	return 0;
+}
+
+static int gs_release_image(struct fpgaimage *fimage)
+{
+	release_firmware(fimage->fw_entry);
+	pr_info("release fpgaimage\n");
+
+	return 0;
+}
+
+/*
+ * NOTE: supports systemmap parallel programming
+ */
+static int gs_set_download_method(struct fpgaimage *fimage)
+{
+	pr_info("set program method\n");
+
+	fimage->dmethod = m_systemmap;
+
+	pr_info("systemmap program method\n");
+
+	return 0;
+}
+
+static int init_driver(void)
+{
+	firmware_pdev = platform_device_register_simple("fpgaboot", -1,
+							 NULL, 0);
+	return PTR_ERR_OR_ZERO(firmware_pdev);
+}
+
+static void finish_driver(void)
+{
+	platform_device_unregister(firmware_pdev);
+}
+
+static int gs_fpgaboot(void)
+{
+	int err;
+	struct fpgaimage	*fimage;
+
+	fimage = kmalloc(sizeof(struct fpgaimage), GFP_KERNEL);
+	if (fimage == NULL) {
+		pr_err("No memory is available\n");
+		goto err_out;
+	}
+
+	err = gs_load_image(fimage, file);
+	if (err) {
+		pr_err("gs_load_image error\n");
+		goto err_out1;
+	}
+
+	err = gs_read_image(fimage);
+	if (err) {
+		pr_err("gs_read_image error\n");
+		goto err_out2;
+	}
+
+	err = gs_set_download_method(fimage);
+	if (err) {
+		pr_err("gs_set_download_method error\n");
+		goto err_out2;
+	}
+
+	err = gs_download_image(fimage, bus_2byte);
+	if (err) {
+		pr_err("gs_download_image error\n");
+		goto err_out2;
+	}
+
+	err = gs_release_image(fimage);
+	if (err) {
+		pr_err("gs_release_image error\n");
+		goto err_out1;
+	}
+
+	kfree(fimage);
+	return 0;
+
+err_out2:
+	err = gs_release_image(fimage);
+	if (err)
+		pr_err("gs_release_image error\n");
+err_out1:
+	kfree(fimage);
+
+err_out:
+	return -1;
+
+}
+
+static int __init gs_fpgaboot_init(void)
+{
+	int err, r;
+
+	r = -1;
+
+	pr_info("FPGA DOWNLOAD --->\n");
+	pr_info("built at %s UTC\n", __TIMESTAMP__);
+
+	pr_info("FPGA image file name: %s\n", file);
+
+	err = init_driver();
+	if (err != 0) {
+		pr_err("FPGA DRIVER INIT FAIL!!\n");
+		return r;
+	}
+
+	err = xl_init_io();
+	if (err) {
+		pr_err("GPIO INIT FAIL!!\n");
+		r = -1;
+		goto errout;
+	}
+
+	err = gs_fpgaboot();
+	if (err) {
+		pr_err("FPGA DOWNLOAD FAIL!!\n");
+		r = -1;
+		goto errout;
+	}
+
+	pr_info("FPGA DOWNLOAD DONE <---\n");
+
+	r = 0;
+	return r;
+
+errout:
+	finish_driver();
+
+	return r;
+}
+
+static void __exit gs_fpgaboot_exit(void)
+{
+	finish_driver();
+	pr_info("FPGA image download module removed\n");
+}
+
+module_init(gs_fpgaboot_init);
+module_exit(gs_fpgaboot_exit);
+
+MODULE_AUTHOR("Insop Song");
+MODULE_DESCRIPTION("Xlinix FPGA firmware download");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
new file mode 100644
index 000000000000..f41f4cc798cc
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute 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.
+ */
+
+#include <linux/firmware.h>
+
+#define	MAX_STR	256
+
+enum fmt_image {
+	f_bit,	/* only bitstream is supported */
+	f_rbt,
+	f_bin,
+	f_mcs,
+	f_hex,
+};
+
+enum mdownload {
+	m_systemmap,	/* only system map is supported */
+	m_serial,
+	m_jtag,
+};
+
+/*
+ * xilinx fpgaimage information
+ * NOTE: use MAX_STR instead of dynamic alloc for simplicity
+ */
+struct fpgaimage {
+	enum fmt_image	fmt_img;
+	enum mdownload	dmethod;
+
+	const struct	firmware	*fw_entry;
+
+	/*
+	 * the followings can be read from bitstream,
+	 * but other image format should have as well
+	 */
+	char	filename[MAX_STR];
+	char	part[MAX_STR];
+	char	date[MAX_STR];
+	char	time[MAX_STR];
+	int32_t	lendata;
+	char	*fpgadata;
+};
diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c
new file mode 100644
index 000000000000..61f976be5899
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/io.c
@@ -0,0 +1,294 @@
+/*
+ * This program is free software; you can redistribute 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+
+#include "io.h"
+
+#ifdef CONFIG_B4860G100
+static struct gpiobus gbus;
+#endif /* CONFIG_B4860G100 */
+
+static inline void byte0_out(unsigned char data);
+static inline void byte1_out(unsigned char data);
+static inline void xl_cclk_b(int32_t i);
+
+
+/* Assert and Deassert CCLK */
+void xl_shift_cclk(int count)
+{
+	int i;
+	for (i = 0; i < count; i++) {
+		xl_cclk_b(1);
+		xl_cclk_b(0);
+	}
+}
+
+int xl_supported_prog_bus_width(enum wbus bus_bytes)
+{
+	switch (bus_bytes) {
+	case bus_1byte:
+		break;
+	case bus_2byte:
+		break;
+	default:
+		pr_err("unsupported program bus width %d\n",
+				bus_bytes);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Serialize byte and clock each bit on target's DIN and CCLK pins */
+void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata)
+{
+	/*
+	 * supports 1 and 2 bytes programming mode
+	 */
+	if (likely(bus_byte == bus_2byte))
+		byte0_out(pdata[0]);
+
+	byte1_out(pdata[1]);
+	xl_shift_cclk(1);
+}
+
+/*
+ * generic bit swap for xilinx SYSTEMMAP FPGA programming
+ */
+static inline unsigned char bitswap(unsigned char s)
+{
+	unsigned char d;
+	d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) |
+		((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<5) | ((s&0x01)<<7));
+	return d;
+}
+
+#ifdef CONFIG_B4860G100
+/*
+ * ======================================================================
+ * board specific configuration
+ */
+
+static inline void mpc85xx_gpio_set_dir(
+			int32_t port,
+			uint32_t mask,
+			uint32_t dir)
+{
+	dir |= (in_be32(gbus.r[port]+GPDIR) & ~mask);
+	out_be32(gbus.r[port]+GPDIR, dir);
+}
+
+static inline void mpc85xx_gpio_set(int32_t port, uint32_t mask, uint32_t val)
+{
+	/* First mask off the unwanted parts of "dir" and "val" */
+	val &= mask;
+
+	/* Now read in the values we're supposed to preserve */
+	val |= (in_be32(gbus.r[port]+GPDAT) & ~mask);
+
+	out_be32(gbus.r[port]+GPDAT, val);
+}
+
+static inline uint32_t mpc85xx_gpio_get(int32_t port, uint32_t mask)
+{
+	/* Read the requested values */
+	return in_be32(gbus.r[port]+GPDAT) & mask;
+}
+
+static inline void mpc85xx_gpio_set_low(int32_t port, uint32_t gpios)
+{
+	mpc85xx_gpio_set(port, gpios, 0x00000000);
+}
+
+static inline void mpc85xx_gpio_set_high(int32_t port, uint32_t gpios)
+{
+	mpc85xx_gpio_set(port, gpios, 0xFFFFFFFF);
+}
+
+static inline void gpio_set_value(int32_t port, uint32_t gpio, uint32_t value)
+{
+	int32_t g;
+	g = 31 - gpio;
+	if (value)
+		mpc85xx_gpio_set_high(port, 1U << g);
+	else
+		mpc85xx_gpio_set_low(port, 1U << g);
+}
+
+static inline int gpio_get_value(int32_t port, uint32_t gpio)
+{
+	int32_t g;
+	g = 31 - gpio;
+	return !!mpc85xx_gpio_get(port, 1U << g);
+}
+
+static inline void xl_cclk_b(int32_t i)
+{
+	gpio_set_value(XL_CCLK_PORT, XL_CCLK_PIN, i);
+}
+
+void xl_program_b(int32_t i)
+{
+	gpio_set_value(XL_PROGN_PORT, XL_PROGN_PIN, i);
+}
+
+void xl_rdwr_b(int32_t i)
+{
+	gpio_set_value(XL_RDWRN_PORT, XL_RDWRN_PIN, i);
+}
+
+void xl_csi_b(int32_t i)
+{
+	gpio_set_value(XL_CSIN_PORT, XL_CSIN_PIN, i);
+}
+
+int xl_get_init_b(void)
+{
+	return gpio_get_value(XL_INITN_PORT, XL_INITN_PIN);
+}
+
+int xl_get_done_b(void)
+{
+	return gpio_get_value(XL_DONE_PORT, XL_DONE_PIN);
+}
+
+
+/* G100 specific bit swap and remmap (to gpio pins) for byte 0 */
+static inline uint32_t bit_remap_byte0(uint32_t s)
+{
+	uint32_t d;
+	d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) |
+		((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<6) | ((s&0x01)<<9));
+	return d;
+}
+
+/*
+ * G100 specific MSB, in this order [byte0 | byte1], out
+ */
+static inline void byte0_out(unsigned char data)
+{
+	uint32_t swap32;
+	swap32 =  bit_remap_byte0((uint32_t) data) << 8;
+
+	mpc85xx_gpio_set(0, 0x0002BF00, (uint32_t) swap32);
+}
+
+/*
+ * G100 specific LSB, in this order [byte0 | byte1], out
+ */
+static inline void byte1_out(unsigned char data)
+{
+	mpc85xx_gpio_set(0, 0x000000FF, (uint32_t) bitswap(data));
+}
+
+/*
+ * configurable per device type for different I/O config
+ */
+int xl_init_io()
+{
+	struct device_node *np;
+	const u32 *p_reg;
+	int reg, cnt;
+
+	cnt = 0;
+	memset(&gbus, 0, sizeof(struct gpiobus));
+	for_each_compatible_node(np, NULL, "fsl,qoriq-gpio") {
+		p_reg = of_get_property(np, "reg", NULL);
+		if (p_reg == NULL)
+			break;
+		reg = (int) *p_reg;
+		gbus.r[cnt] = of_iomap(np, 0);
+
+		if (!gbus.r[cnt]) {
+			pr_err("not findding gpio cell-index %d\n", cnt);
+			return -ENODEV;
+		}
+		cnt++;
+	}
+	mpc85xx_gpio_set_dir(0, 0x0002BFFF, 0x0002BFFF);
+	mpc85xx_gpio_set_dir(1, 0x00240060, 0x00240060);
+
+	gbus.ngpio = cnt;
+
+	return 0;
+}
+
+
+#else	/* placeholder for boards with different config */
+
+void xl_program_b(int32_t i)
+{
+	return;
+}
+
+void xl_rdwr_b(int32_t i)
+{
+	return;
+}
+
+void xl_csi_b(int32_t i)
+{
+	return;
+}
+
+int xl_get_init_b(void)
+{
+	return -1;
+}
+
+int xl_get_done_b(void)
+{
+	return -1;
+}
+
+static inline void byte0_out(unsigned char data)
+{
+	return;
+}
+
+static inline void byte1_out(unsigned char data)
+{
+	return;
+}
+
+static inline void xl_cclk_b(int32_t i)
+{
+	return;
+}
+
+/*
+ * configurable per device type for different I/O config
+ */
+int xl_init_io()
+{
+	return -1;
+}
+
+#endif /* CONFIG_B4860G100 */
diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h
new file mode 100644
index 000000000000..7b46ac24b74e
--- /dev/null
+++ b/drivers/staging/gs_fpgaboot/io.h
@@ -0,0 +1,90 @@
+/*
+ * This program is free software; you can redistribute 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.
+ */
+
+#define GPDIR	0
+#define GPCFG	4	/* open drain or not */
+#define GPDAT	8
+
+/*
+ * gpio port and pin definitions
+ * NOTE: port number starts from 0
+ */
+#define	XL_INITN_PORT	1
+#define	XL_INITN_PIN	14
+#define	XL_RDWRN_PORT	1
+#define	XL_RDWRN_PIN	13
+#define	XL_CCLK_PORT	1
+#define	XL_CCLK_PIN	10
+#define	XL_PROGN_PORT	1
+#define	XL_PROGN_PIN	25
+#define	XL_CSIN_PORT	1
+#define	XL_CSIN_PIN	26
+#define	XL_DONE_PORT	1
+#define	XL_DONE_PIN	27
+
+/*
+ * gpio mapping
+ *
+	XL_config_D0 – gpio1_31
+	Xl_config_d1 – gpio1_30
+	Xl_config_d2 – gpio1_29
+	Xl_config_d3 – gpio1_28
+	Xl_config_d4 – gpio1_27
+	Xl_config_d5 – gpio1_26
+	Xl_config_d6 – gpio1_25
+	Xl_config_d7 – gpio1_24
+	Xl_config_d8 – gpio1_23
+	Xl_config_d9 – gpio1_22
+	Xl_config_d10 – gpio1_21
+	Xl_config_d11 – gpio1_20
+	Xl_config_d12 – gpio1_19
+	Xl_config_d13 – gpio1_18
+	Xl_config_d14 – gpio1_16
+	Xl_config_d15 – gpio1_14
+*
+*/
+
+/*
+ * program bus width in bytes
+ */
+enum wbus {
+	bus_1byte	= 1,
+	bus_2byte	= 2,
+};
+
+
+#define MAX_WAIT_DONE	10000
+
+
+struct gpiobus {
+	int	ngpio;
+	void __iomem *r[4];
+};
+
+int xl_supported_prog_bus_width(enum wbus bus_bytes);
+
+void xl_program_b(int32_t i);
+void xl_rdwr_b(int32_t i);
+void xl_csi_b(int32_t i);
+
+int xl_get_init_b(void);
+int xl_get_done_b(void);
+
+void xl_shift_cclk(int count);
+void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata);
+
+int xl_init_io(void);
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index c9fedb79e3a2..2064839ef2cd 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -652,3 +652,25 @@ error_free:
 	free(temp);
 	return ret;
 }
+
+read_sysfs_string(const char *filename, const char *basedir, char *str)
+{
+	float ret = 0;
+	FILE  *sysfsfp;
+	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+	if (temp == NULL) {
+		printf("Memory allocation failed");
+		return -ENOMEM;
+	}
+	sprintf(temp, "%s/%s", basedir, filename);
+	sysfsfp = fopen(temp, "r");
+	if (sysfsfp == NULL) {
+		ret = -errno;
+		goto error_free;
+	}
+	fscanf(sysfsfp, "%s\n", str);
+	fclose(sysfsfp);
+error_free:
+	free(temp);
+	return ret;
+}
diff --git a/drivers/staging/iio/Documentation/lsiio.c b/drivers/staging/iio/Documentation/lsiio.c
new file mode 100644
index 000000000000..24ae9694eb41
--- /dev/null
+++ b/drivers/staging/iio/Documentation/lsiio.c
@@ -0,0 +1,157 @@
+/*
+ * Industrial I/O utilities - lsiio.c
+ *
+ * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.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 <string.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include "iio_utils.h"
+
+
+static enum verbosity {
+	VERBLEVEL_DEFAULT,	/* 0 gives lspci behaviour */
+	VERBLEVEL_SENSORS,	/* 1 lists sensors */
+} verblevel = VERBLEVEL_DEFAULT;
+
+const char *type_device = "iio:device";
+const char *type_trigger = "trigger";
+
+
+static inline int check_prefix(const char *str, const char *prefix)
+{
+	return strlen(str) > strlen(prefix) &&
+		strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+static inline int check_postfix(const char *str, const char *postfix)
+{
+	return strlen(str) > strlen(postfix) &&
+		strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+}
+
+static int dump_channels(const char *dev_dir_name)
+{
+	DIR *dp;
+	const struct dirent *ent;
+	dp = opendir(dev_dir_name);
+	if (dp == NULL)
+		return -errno;
+	while (ent = readdir(dp), ent != NULL)
+		if (check_prefix(ent->d_name, "in_") &&
+		    check_postfix(ent->d_name, "_raw")) {
+			printf("   %-10s\n", ent->d_name);
+		}
+
+	return 0;
+}
+
+static int dump_one_device(const char *dev_dir_name)
+{
+	char name[IIO_MAX_NAME_LENGTH];
+	int dev_idx;
+
+	sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
+			"%i", &dev_idx);
+	read_sysfs_string("name", dev_dir_name, name);
+	printf("Device %03d: %s\n", dev_idx, name);
+
+	if (verblevel >= VERBLEVEL_SENSORS) {
+		int ret = dump_channels(dev_dir_name);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int dump_one_trigger(const char *dev_dir_name)
+{
+	char name[IIO_MAX_NAME_LENGTH];
+	int dev_idx;
+
+	sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
+			"%i", &dev_idx);
+	read_sysfs_string("name", dev_dir_name, name);
+	printf("Trigger %03d: %s\n", dev_idx, name);
+	return 0;
+}
+
+static void dump_devices(void)
+{
+	const struct dirent *ent;
+	int number, numstrlen;
+
+	FILE *nameFile;
+	DIR *dp;
+	char thisname[IIO_MAX_NAME_LENGTH];
+	char *filename;
+
+	dp = opendir(iio_dir);
+	if (dp == NULL) {
+		printf("No industrial I/O devices available\n");
+		return;
+	}
+
+	while (ent = readdir(dp), ent != NULL) {
+		if (check_prefix(ent->d_name, type_device)) {
+			char *dev_dir_name;
+			asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
+			dump_one_device(dev_dir_name);
+			free(dev_dir_name);
+			if (verblevel >= VERBLEVEL_SENSORS)
+				printf("\n");
+		}
+	}
+	rewinddir(dp);
+	while (ent = readdir(dp), ent != NULL) {
+		if (check_prefix(ent->d_name, type_trigger)) {
+			char *dev_dir_name;
+			asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
+			dump_one_trigger(dev_dir_name);
+			free(dev_dir_name);
+		}
+	}
+	closedir(dp);
+}
+
+int main(int argc, char **argv)
+{
+	int c, err = 0;
+
+	while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
+		switch (c) {
+		case 'v':
+			verblevel++;
+			break;
+
+		case '?':
+		default:
+			err++;
+			break;
+		}
+	}
+	if (err || argc > optind) {
+		fprintf(stderr, "Usage: lsiio [options]...\n"
+			"List industrial I/O devices\n"
+			"  -v, --verbose\n"
+			"      Increase verbosity (may be given multiple times)\n"
+			);
+		exit(1);
+	}
+
+	dump_devices();
+
+	return 0;
+}
diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h
index c1016c510dae..b284e5a6cac1 100644
--- a/drivers/staging/iio/accel/sca3000.h
+++ b/drivers/staging/iio/accel/sca3000.h
@@ -65,7 +65,8 @@
 
 #define SCA3000_RING_BUF_ENABLE			0x80
 #define SCA3000_RING_BUF_8BIT			0x40
-/* Free fall detection triggers an interrupt if the acceleration
+/*
+ * Free fall detection triggers an interrupt if the acceleration
  * is below a threshold for equivalent of 25cm drop
  */
 #define SCA3000_FREE_FALL_DETECT		0x10
@@ -73,8 +74,9 @@
 #define SCA3000_MEAS_MODE_OP_1			0x01
 #define SCA3000_MEAS_MODE_OP_2			0x02
 
-/* In motion detection mode the accelerations are band pass filtered
- * (aprox 1 - 25Hz) and then a programmable threshold used to trigger
+/*
+ * In motion detection mode the accelerations are band pass filtered
+ * (approx 1 - 25Hz) and then a programmable threshold used to trigger
  * and interrupt.
  */
 #define SCA3000_MEAS_MODE_MOT_DET		0x03
@@ -99,8 +101,10 @@
 #define SCA3000_REG_CTRL_SEL_MD_Y_TH		0x03
 #define SCA3000_REG_CTRL_SEL_MD_X_TH		0x04
 #define SCA3000_REG_CTRL_SEL_MD_Z_TH		0x05
-/* BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
-   will not function */
+/*
+ * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
+ * will not function
+ */
 #define SCA3000_REG_CTRL_SEL_OUT_CTRL		0x0B
 #define SCA3000_OUT_CTRL_PROT_MASK		0xE0
 #define SCA3000_OUT_CTRL_BUF_X_EN		0x10
@@ -109,8 +113,9 @@
 #define SCA3000_OUT_CTRL_BUF_DIV_4		0x02
 #define SCA3000_OUT_CTRL_BUF_DIV_2		0x01
 
-/* Control which motion detector interrupts are on.
- * For now only OR combinations are supported.x
+/*
+ * Control which motion detector interrupts are on.
+ * For now only OR combinations are supported.
  */
 #define SCA3000_MD_CTRL_PROT_MASK		0xC0
 #define SCA3000_MD_CTRL_OR_Y			0x01
@@ -121,7 +126,8 @@
 #define SCA3000_MD_CTRL_AND_X			0x10
 #define SAC3000_MD_CTRL_AND_Z			0x20
 
-/* Some control registers of complex access methods requiring this register to
+/*
+ * Some control registers of complex access methods requiring this register to
  * be used to remove a lock.
  */
 #define SCA3000_REG_ADDR_UNLOCK			0x1e
@@ -139,7 +145,8 @@
 /* Values of multiplexed registers (write to ctrl_data after select) */
 #define SCA3000_REG_ADDR_CTRL_DATA		0x22
 
-/* Measurement modes available on some sca3000 series chips. Code assumes others
+/*
+ * Measurement modes available on some sca3000 series chips. Code assumes others
  * may become available in the future.
  *
  * Bypass - Bypass the low-pass filter in the signal channel so as to increase
@@ -160,7 +167,6 @@
  * struct sca3000_state - device instance state information
  * @us:			the associated spi device
  * @info:			chip variant information
- * @indio_dev:			device information used by the IIO core
  * @interrupt_handler_ws:	event interrupt handler for all events
  * @last_timestamp:		the timestamp of the last event
  * @mo_det_use_count:		reference counter for the motion detection unit
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 7f6ccdfaf168..ed30e32e60de 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -32,7 +32,8 @@ enum sca3000_variant {
 	e05,
 };
 
-/* Note where option modes are not defined, the chip simply does not
+/*
+ * Note where option modes are not defined, the chip simply does not
  * support any.
  * Other chips in the sca3000 series use i2c and are not included here.
  *
@@ -191,7 +192,6 @@ error_ret:
 	return ret;
 }
 
-/* Crucial that lock is called before calling this */
 /**
  * sca3000_read_ctrl_reg() read from lock protected control register.
  *
@@ -250,9 +250,8 @@ error_ret:
 }
 #endif /* SCA3000_DEBUG */
 
-
 /**
- * sca3000_show_reg() - sysfs interface to read the chip revision number
+ * sca3000_show_rev() - sysfs interface to read the chip revision number
  **/
 static ssize_t sca3000_show_rev(struct device *dev,
 				struct device_attribute *attr,
@@ -312,7 +311,7 @@ sca3000_show_available_measurement_modes(struct device *dev,
 }
 
 /**
- * sca3000_show_measurmenet_mode() sysfs read of current mode
+ * sca3000_show_measurement_mode() sysfs read of current mode
  **/
 static ssize_t
 sca3000_show_measurement_mode(struct device *dev,
@@ -403,7 +402,8 @@ error_ret:
 }
 
 
-/* Not even vaguely standard attributes so defined here rather than
+/*
+ * Not even vaguely standard attributes so defined here rather than
  * in the relevant IIO core headers
  */
 static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO,
@@ -450,6 +450,18 @@ static const struct iio_chan_spec sca3000_channels[] = {
 	SCA3000_CHAN(2, IIO_MOD_Z),
 };
 
+static const struct iio_chan_spec sca3000_channels_with_temp[] = {
+	SCA3000_CHAN(0, IIO_MOD_X),
+	SCA3000_CHAN(1, IIO_MOD_Y),
+	SCA3000_CHAN(2, IIO_MOD_Z),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
+	},
+};
+
 static u8 sca3000_addresses[3][3] = {
 	[0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH,
 	       SCA3000_MD_CTRL_OR_X},
@@ -472,19 +484,30 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&st->lock);
-		if (st->mo_det_use_count) {
-			mutex_unlock(&st->lock);
-			return -EBUSY;
-		}
-		address = sca3000_addresses[chan->address][0];
-		ret = sca3000_read_data_short(st, address, 2);
-		if (ret < 0) {
-			mutex_unlock(&st->lock);
-			return ret;
+		if (chan->type == IIO_ACCEL) {
+			if (st->mo_det_use_count) {
+				mutex_unlock(&st->lock);
+				return -EBUSY;
+			}
+			address = sca3000_addresses[chan->address][0];
+			ret = sca3000_read_data_short(st, address, 2);
+			if (ret < 0) {
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+			*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
+			*val = ((*val) << (sizeof(*val)*8 - 13)) >>
+				(sizeof(*val)*8 - 13);
+		} else {
+			/* get the temperature when available */
+			ret = sca3000_read_data_short(st,
+				SCA3000_REG_ADDR_TEMP_MSB, 2);
+			if (ret < 0) {
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+			*val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
 		}
-		*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
-		*val = ((*val) << (sizeof(*val)*8 - 13)) >>
-			(sizeof(*val)*8 - 13);
 		mutex_unlock(&st->lock);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
@@ -494,6 +517,10 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
 		else /* temperature */
 			*val2 = 555556;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = -214;
+		*val2 = 600000;
+		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
 	}
@@ -547,7 +574,7 @@ error_ret:
 	return ret;
 }
 /**
- * __sca3000_get_base_frequency() obtain mode specific base frequency
+ * __sca3000_get_base_freq() obtain mode specific base frequency
  *
  * lock must be held
  **/
@@ -663,7 +690,8 @@ error_free_lock:
 	return ret ? ret : len;
 }
 
-/* Should only really be registered if ring buffer support is compiled in.
+/*
+ * Should only really be registered if ring buffer support is compiled in.
  * Does no harm however and doing it right would add a fair bit of complexity
  */
 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
@@ -672,37 +700,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 			      sca3000_read_frequency,
 			      sca3000_set_frequency);
 
-
-/**
- * sca3000_read_temp() sysfs interface to get the temperature when available
- *
-* The alignment of data in here is downright odd. See data sheet.
-* Converting this into a meaningful value is left to inline functions in
-* userspace part of header.
-**/
-static ssize_t sca3000_read_temp(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct sca3000_state *st = iio_priv(indio_dev);
-	int ret;
-	int val;
-	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_TEMP_MSB, 2);
-	if (ret < 0)
-		goto error_ret;
-	val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
-
-	return sprintf(buf, "%d\n", val);
-
-error_ret:
-	return ret;
-}
-static IIO_DEV_ATTR_TEMP_RAW(sca3000_read_temp);
-
-static IIO_CONST_ATTR_TEMP_SCALE("0.555556");
-static IIO_CONST_ATTR_TEMP_OFFSET("-214.6");
-
 /**
  * sca3000_read_thresh() - query of a threshold
  **/
@@ -782,33 +779,16 @@ static struct attribute *sca3000_attributes[] = {
 	NULL,
 };
 
-static struct attribute *sca3000_attributes_with_temp[] = {
-	&iio_dev_attr_revision.dev_attr.attr,
-	&iio_dev_attr_measurement_mode_available.dev_attr.attr,
-	&iio_dev_attr_measurement_mode.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	/* Only present if temp sensor is */
-	&iio_dev_attr_in_temp_raw.dev_attr.attr,
-	&iio_const_attr_in_temp_offset.dev_attr.attr,
-	&iio_const_attr_in_temp_scale.dev_attr.attr,
-	NULL,
-};
-
 static const struct attribute_group sca3000_attribute_group = {
 	.attrs = sca3000_attributes,
 };
 
-static const struct attribute_group sca3000_attribute_group_with_temp = {
-	.attrs = sca3000_attributes_with_temp,
-};
-
-/* RING RELATED interrupt handler */
-/* depending on event, push to the ring buffer event chrdev or the event one */
-
 /**
  * sca3000_event_handler() - handling ring and non ring events
  *
+ * Ring related interrupt handler. Depending on event, push to
+ * the ring buffer event chrdev or the event one.
+ *
  * This function is complicated by the fact that the devices can signify ring
  * and non ring events via the same interrupt line and they can only
  * be distinguished via a read of the relevant status register.
@@ -820,7 +800,8 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
 	int ret, val;
 	s64 last_timestamp = iio_get_time_ns();
 
-	/* Could lead if badly timed to an extra read of status reg,
+	/*
+	 * Could lead if badly timed to an extra read of status reg,
 	 * but ensures no interrupt is missed.
 	 */
 	mutex_lock(&st->lock);
@@ -935,7 +916,6 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
  * the device falls more than 25cm.  This has not been tested due
  * to fragile wiring.
  **/
-
 static ssize_t sca3000_set_free_fall_mode(struct device *dev,
 					  struct device_attribute *attr,
 					  const char *buf,
@@ -957,7 +937,7 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
 	if (ret)
 		goto error_ret;
 
-	/*if off and should be on*/
+	/* if off and should be on */
 	if (val && !(st->rx[0] & protect_mask))
 		ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
 					(st->rx[0] | SCA3000_FREE_FALL_DETECT));
@@ -972,7 +952,7 @@ error_ret:
 }
 
 /**
- * sca3000_set_mo_det() simple on off control for motion detector
+ * sca3000_write_event_config() simple on off control for motion detector
  *
  * This is a per axis control, but enabling any will result in the
  * motion detector unit being enabled.
@@ -992,13 +972,15 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
 	int num = chan->channel2;
 
 	mutex_lock(&st->lock);
-	/* First read the motion detector config to find out if
-	 * this axis is on*/
+	/*
+	 * First read the motion detector config to find out if
+	 * this axis is on
+	 */
 	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
 	if (ret < 0)
 		goto exit_point;
 	ctrlval = ret;
-	/* Off and should be on */
+	/* if off and should be on */
 	if (state && !(ctrlval & sca3000_addresses[num][2])) {
 		ret = sca3000_write_ctrl_reg(st,
 					     SCA3000_REG_CTRL_SEL_MD_CTRL,
@@ -1021,7 +1003,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
 	if (ret)
 		goto exit_point;
-	/*if off and should be on*/
+	/* if off and should be on */
 	if ((st->mo_det_use_count)
 	    && ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
 		ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
@@ -1067,7 +1049,7 @@ static struct attribute_group sca3000_event_attribute_group = {
  * Devices use flash memory to store many of the register values
  * and hence can come up in somewhat unpredictable states.
  * Hence reset everything on driver load.
-  **/
+ **/
 static int sca3000_clean_setup(struct sca3000_state *st)
 {
 	int ret;
@@ -1107,9 +1089,11 @@ static int sca3000_clean_setup(struct sca3000_state *st)
 				| SCA3000_INT_MASK_ACTIVE_LOW);
 	if (ret)
 		goto error_ret;
-	/* Select normal measurement mode, free fall off, ring off */
-	/* Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
-	 * as that occurs in one of the example on the datasheet */
+	/*
+	 * Select normal measurement mode, free fall off, ring off
+	 * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
+	 * as that occurs in one of the example on the datasheet
+	 */
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
 	if (ret)
 		goto error_ret;
@@ -1133,16 +1117,6 @@ static const struct iio_info sca3000_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static const struct iio_info sca3000_info_with_temp = {
-	.attrs = &sca3000_attribute_group_with_temp,
-	.read_raw = &sca3000_read_raw,
-	.read_event_value = &sca3000_read_thresh,
-	.write_event_value = &sca3000_write_thresh,
-	.read_event_config = &sca3000_read_event_config,
-	.write_event_config = &sca3000_write_event_config,
-	.driver_module = THIS_MODULE,
-};
-
 static int sca3000_probe(struct spi_device *spi)
 {
 	int ret;
@@ -1162,10 +1136,12 @@ static int sca3000_probe(struct spi_device *spi)
 
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->name = spi_get_device_id(spi)->name;
-	if (st->info->temp_output)
-		indio_dev->info = &sca3000_info_with_temp;
-	else {
-		indio_dev->info = &sca3000_info;
+	indio_dev->info = &sca3000_info;
+	if (st->info->temp_output) {
+		indio_dev->channels = sca3000_channels_with_temp;
+		indio_dev->num_channels =
+			ARRAY_SIZE(sca3000_channels_with_temp);
+	} else {
 		indio_dev->channels = sca3000_channels;
 		indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
 	}
@@ -1236,7 +1212,7 @@ static int sca3000_remove(struct spi_device *spi)
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct sca3000_state *st = iio_priv(indio_dev);
 
-	/* Must ensure no interrupts can be generated after this!*/
+	/* Must ensure no interrupts can be generated after this! */
 	sca3000_stop_all_interrupts(st);
 	if (spi->irq)
 		free_irq(spi->irq, indio_dev);
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index a591aa6feae1..fc8c85298feb 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -95,7 +95,7 @@ struct ad799x_state {
 	struct i2c_client		*client;
 	const struct ad799x_chip_info	*chip_info;
 	struct regulator		*reg;
-	u16				int_vref_mv;
+	struct regulator		*vref;
 	unsigned			id;
 	u16				config;
 
@@ -103,14 +103,6 @@ struct ad799x_state {
 	unsigned int			transfer_size;
 };
 
-/*
- * TODO: struct ad799x_platform_data needs to go into include/linux/iio
- */
-
-struct ad799x_platform_data {
-	u16				vref_mv;
-};
-
 #ifdef CONFIG_AD799X_RING_BUFFER
 int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
 void ad799x_ring_cleanup(struct iio_dev *indio_dev);
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 5708ffc62aec..979ec77d6c2d 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -1,6 +1,6 @@
 /*
  * iio/adc/ad799x.c
- * Copyright (C) 2010-1011 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
  *
  * based on iio/adc/max1363
  * Copyright (C) 2008-2010 Jonathan Cameron
@@ -179,7 +179,10 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
 			RES_MASK(chan->scan_type.realbits);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = st->int_vref_mv;
+		ret = regulator_get_voltage(st->vref);
+		if (ret < 0)
+			return ret;
+		*val = ret / 1000;
 		*val2 = chan->scan_type.realbits;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	}
@@ -533,7 +536,6 @@ static int ad799x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	int ret;
-	struct ad799x_platform_data *pdata = client->dev.platform_data;
 	struct ad799x_state *st;
 	struct iio_dev *indio_dev;
 
@@ -551,17 +553,21 @@ static int ad799x_probe(struct i2c_client *client,
 
 	/* TODO: Add pdata options for filtering and bit delay */
 
-	if (!pdata)
-		return -EINVAL;
-
-	st->int_vref_mv = pdata->vref_mv;
-
 	st->reg = devm_regulator_get(&client->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
-		if (ret)
-			return ret;
+	if (IS_ERR(st->reg))
+		return PTR_ERR(st->reg);
+	ret = regulator_enable(st->reg);
+	if (ret)
+		return ret;
+	st->vref = devm_regulator_get(&client->dev, "vref");
+	if (IS_ERR(st->vref)) {
+		ret = PTR_ERR(st->vref);
+		goto error_disable_reg;
 	}
+	ret = regulator_enable(st->vref);
+	if (ret)
+		goto error_disable_reg;
+
 	st->client = client;
 
 	indio_dev->dev.parent = &client->dev;
@@ -577,28 +583,28 @@ static int ad799x_probe(struct i2c_client *client,
 		goto error_disable_reg;
 
 	if (client->irq > 0) {
-		ret = request_threaded_irq(client->irq,
-					   NULL,
-					   ad799x_event_handler,
-					   IRQF_TRIGGER_FALLING |
-					   IRQF_ONESHOT,
-					   client->name,
-					   indio_dev);
+		ret = devm_request_threaded_irq(&client->dev,
+						client->irq,
+						NULL,
+						ad799x_event_handler,
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT,
+						client->name,
+						indio_dev);
 		if (ret)
 			goto error_cleanup_ring;
 	}
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_irq;
+		goto error_cleanup_ring;
 
 	return 0;
 
-error_free_irq:
-	if (client->irq > 0)
-		free_irq(client->irq, indio_dev);
 error_cleanup_ring:
 	ad799x_ring_cleanup(indio_dev);
 error_disable_reg:
+	if (!IS_ERR(st->vref))
+		regulator_disable(st->vref);
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
 
@@ -611,10 +617,10 @@ static int ad799x_remove(struct i2c_client *client)
 	struct ad799x_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (client->irq > 0)
-		free_irq(client->irq, indio_dev);
 
 	ad799x_ring_cleanup(indio_dev);
+	if (!IS_ERR(st->vref))
+		regulator_disable(st->vref);
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
 	kfree(st->rx_buf);
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 514844efac75..25bea0556c1e 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -898,10 +898,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 {
 	struct mxs_lradc *lradc = iio_priv(iio_dev);
 
-	/* Check for invalid channel */
-	if (chan->channel > LRADC_MAX_TOTAL_CHANS)
-		return -EINVAL;
-
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
 		if (chan->type == IIO_TEMP)
@@ -1563,7 +1559,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	for (i = 0; i < of_cfg->irq_count; i++) {
 		lradc->irq[i] = platform_get_irq(pdev, i);
 		if (lradc->irq[i] < 0)
-			return -EINVAL;
+			return lradc->irq[i];
 
 		ret = devm_request_irq(dev, lradc->irq[i],
 					mxs_lradc_handle_irq, 0,
diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
index 78319ad176cd..c6e8ba7b3e4e 100644
--- a/drivers/staging/imx-drm/Kconfig
+++ b/drivers/staging/imx-drm/Kconfig
@@ -20,6 +20,7 @@ config DRM_IMX_FB_HELPER
 
 config DRM_IMX_PARALLEL_DISPLAY
 	tristate "Support for parallel displays"
+	select DRM_PANEL
 	depends on DRM_IMX
 	select VIDEOMODE_HELPERS
 
diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
index 4677585b5ad5..129e3a3f59f1 100644
--- a/drivers/staging/imx-drm/Makefile
+++ b/drivers/staging/imx-drm/Makefile
@@ -1,12 +1,11 @@
 
-imxdrm-objs := imx-drm-core.o imx-fb.o
+imxdrm-objs := imx-drm-core.o
 
 obj-$(CONFIG_DRM_IMX) += imxdrm.o
 
 obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
 obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
 
 imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 236ed66f116a..6b91c8e67174 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -13,14 +13,14 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/component.h>
 #include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
-#include <linux/fb.h>
-#include <linux/module.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
@@ -28,45 +28,26 @@
 
 #define MAX_CRTC	4
 
-struct crtc_cookie {
-	void *cookie;
-	int id;
-	struct list_head list;
-};
+struct imx_drm_crtc;
 
 struct imx_drm_device {
 	struct drm_device			*drm;
-	struct device				*dev;
-	struct list_head			crtc_list;
-	struct list_head			encoder_list;
-	struct list_head			connector_list;
-	struct mutex				mutex;
+	struct imx_drm_crtc			*crtc[MAX_CRTC];
 	int					pipes;
 	struct drm_fbdev_cma			*fbhelper;
 };
 
 struct imx_drm_crtc {
 	struct drm_crtc				*crtc;
-	struct list_head			list;
-	struct imx_drm_device			*imxdrm;
 	int					pipe;
 	struct imx_drm_crtc_helper_funcs	imx_drm_helper_funcs;
-	struct module				*owner;
-	struct crtc_cookie			cookie;
-};
-
-struct imx_drm_encoder {
-	struct drm_encoder			*encoder;
-	struct list_head			list;
-	struct module				*owner;
-	struct list_head			possible_crtcs;
+	void					*cookie;
+	int					id;
+	int					mux_id;
 };
 
-struct imx_drm_connector {
-	struct drm_connector			*connector;
-	struct list_head			list;
-	struct module				*owner;
-};
+static int legacyfb_depth = 16;
+module_param(legacyfb_depth, int, 0444);
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
 {
@@ -76,69 +57,71 @@ EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
 
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
 	struct imx_drm_device *imxdrm = drm->dev_private;
 
 	if (imxdrm->fbhelper)
 		drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
+#endif
 }
 
 static int imx_drm_driver_unload(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
 	struct imx_drm_device *imxdrm = drm->dev_private;
+#endif
 
-	imx_drm_device_put();
+	drm_kms_helper_poll_fini(drm);
+
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	if (imxdrm->fbhelper)
+		drm_fbdev_cma_fini(imxdrm->fbhelper);
+#endif
+
+	component_unbind_all(drm->dev, drm);
 
 	drm_vblank_cleanup(drm);
-	drm_kms_helper_poll_fini(drm);
 	drm_mode_config_cleanup(drm);
 
 	return 0;
 }
 
-/*
- * We don't care at all for crtc numbers, but the core expects the
- * crtcs to be numbered
- */
-static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm,
-		int num)
+static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
 {
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_device *imxdrm = crtc->dev->dev_private;
+	unsigned i;
+
+	for (i = 0; i < MAX_CRTC; i++)
+		if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
+			return imxdrm->crtc[i];
 
-	list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list)
-		if (imx_drm_crtc->pipe == num)
-			return imx_drm_crtc;
 	return NULL;
 }
 
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
 		u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
-	struct imx_drm_device *imxdrm = crtc->dev->dev_private;
-	struct imx_drm_crtc *imx_crtc;
 	struct imx_drm_crtc_helper_funcs *helper;
+	struct imx_drm_crtc *imx_crtc;
 
-	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list)
-		if (imx_crtc->crtc == crtc)
-			goto found;
+	imx_crtc = imx_drm_find_crtc(encoder->crtc);
+	if (!imx_crtc)
+		return -EINVAL;
 
-	return -EINVAL;
-found:
 	helper = &imx_crtc->imx_drm_helper_funcs;
 	if (helper->set_interface_pix_fmt)
-		return helper->set_interface_pix_fmt(crtc,
-				encoder_type, interface_pix_fmt,
+		return helper->set_interface_pix_fmt(encoder->crtc,
+				encoder->encoder_type, interface_pix_fmt,
 				hsync_pin, vsync_pin);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
 
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
-		u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
 {
-	return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
-					      interface_pix_fmt, 2, 3);
+	return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format);
 
 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
 {
@@ -161,10 +144,9 @@ EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
 static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
 	int ret;
 
-	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
 	if (!imx_drm_crtc)
 		return -EINVAL;
 
@@ -180,9 +162,8 @@ static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
 static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
 
-	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
 	if (!imx_drm_crtc)
 		return;
 
@@ -215,172 +196,54 @@ static const struct file_operations imx_drm_driver_fops = {
 	.llseek = noop_llseek,
 };
 
-static struct imx_drm_device *imx_drm_device;
-
-static struct imx_drm_device *__imx_drm_device(void)
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+	struct drm_display_mode *mode)
 {
-	return imx_drm_device;
+	return MODE_OK;
 }
+EXPORT_SYMBOL(imx_drm_connector_mode_valid);
 
-struct drm_device *imx_drm_device_get(void)
+void imx_drm_connector_destroy(struct drm_connector *connector)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *enc;
-	struct imx_drm_connector *con;
-	struct imx_drm_crtc *crtc;
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-		if (!try_module_get(enc->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(enc->owner));
-			goto unwind_enc;
-		}
-	}
-
-	list_for_each_entry(con, &imxdrm->connector_list, list) {
-		if (!try_module_get(con->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(con->owner));
-			goto unwind_con;
-		}
-	}
-
-	list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
-		if (!try_module_get(crtc->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(crtc->owner));
-			goto unwind_crtc;
-		}
-	}
-
-	return imxdrm->drm;
-
-unwind_crtc:
-	list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
-		module_put(crtc->owner);
-unwind_con:
-	list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
-		module_put(con->owner);
-unwind_enc:
-	list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
-		module_put(enc->owner);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	return NULL;
-
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_get);
-
-void imx_drm_device_put(void)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *enc;
-	struct imx_drm_connector *con;
-	struct imx_drm_crtc *crtc;
-
-	mutex_lock(&imxdrm->mutex);
-
-	list_for_each_entry(crtc, &imxdrm->crtc_list, list)
-		module_put(crtc->owner);
-
-	list_for_each_entry(con, &imxdrm->connector_list, list)
-		module_put(con->owner);
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list)
-		module_put(enc->owner);
-
-	mutex_unlock(&imxdrm->mutex);
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_put);
-
-static int drm_mode_group_reinit(struct drm_device *dev)
-{
-	struct drm_mode_group *group = &dev->primary->mode_group;
-	uint32_t *id_list = group->id_list;
-	int ret;
-
-	ret = drm_mode_group_init_legacy_group(dev, group);
-	if (ret < 0)
-		return ret;
-
-	kfree(id_list);
-	return 0;
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
 }
+EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
 
-/*
- * register an encoder to the drm core
- */
-static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
+void imx_drm_encoder_destroy(struct drm_encoder *encoder)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs);
-
-	drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
-			imx_drm_encoder->encoder->funcs,
-			imx_drm_encoder->encoder->encoder_type);
-
-	drm_mode_group_reinit(imxdrm->drm);
-
-	return 0;
+	drm_encoder_cleanup(encoder);
 }
+EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
 
-/*
- * unregister an encoder from the drm core
- */
-static void imx_drm_encoder_unregister(struct imx_drm_encoder
-		*imx_drm_encoder)
+static void imx_drm_output_poll_changed(struct drm_device *drm)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_encoder_cleanup(imx_drm_encoder->encoder);
-
-	drm_mode_group_reinit(imxdrm->drm);
-}
-
-/*
- * register a connector to the drm core
- */
-static int imx_drm_connector_register(
-		struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
-			imx_drm_connector->connector->funcs,
-			imx_drm_connector->connector->connector_type);
-	drm_mode_group_reinit(imxdrm->drm);
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	struct imx_drm_device *imxdrm = drm->dev_private;
 
-	return drm_sysfs_connector_add(imx_drm_connector->connector);
+	drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
+#endif
 }
 
-/*
- * unregister a connector from the drm core
- */
-static void imx_drm_connector_unregister(
-		struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_sysfs_connector_remove(imx_drm_connector->connector);
-	drm_connector_cleanup(imx_drm_connector->connector);
-
-	drm_mode_group_reinit(imxdrm->drm);
-}
+static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = imx_drm_output_poll_changed,
+};
 
 /*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
  */
 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_device *imxdrm;
+	struct drm_connector *connector;
 	int ret;
 
+	imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL);
+	if (!imxdrm)
+		return -ENOMEM;
+
 	imxdrm->drm = drm;
 
 	drm->dev_private = imxdrm;
@@ -396,120 +259,123 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 	 */
 	drm->irq_enabled = true;
 
-	drm_mode_config_init(drm);
-	imx_drm_mode_config_init(drm);
-
-	mutex_lock(&imxdrm->mutex);
-
-	drm_kms_helper_poll_init(drm);
+	/*
+	 * set max width and height as default value(4096x4096).
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	drm->mode_config.min_width = 64;
+	drm->mode_config.min_height = 64;
+	drm->mode_config.max_width = 4096;
+	drm->mode_config.max_height = 4096;
+	drm->mode_config.funcs = &imx_drm_mode_config_funcs;
 
-	/* setup the grouping for the legacy output */
-	ret = drm_mode_group_init_legacy_group(drm,
-			&drm->primary->mode_group);
-	if (ret)
-		goto err_kms;
+	drm_mode_config_init(drm);
 
 	ret = drm_vblank_init(drm, MAX_CRTC);
 	if (ret)
 		goto err_kms;
 
 	/*
-	 * with vblank_disable_allowed = true, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
+	 * with vblank_disable_allowed = true, vblank interrupt will be
+	 * disabled by drm timer once a current process gives up ownership
+	 * of vblank event. (after drm_vblank_put function is called)
 	 */
 	drm->vblank_disable_allowed = true;
 
-	if (!imx_drm_device_get()) {
-		ret = -EINVAL;
+	platform_set_drvdata(drm->platformdev, drm);
+
+	/* Now try and bind all our sub-components */
+	ret = component_bind_all(drm->dev, drm);
+	if (ret)
 		goto err_vblank;
+
+	/*
+	 * All components are now added, we can publish the connector sysfs
+	 * entries to userspace.  This will generate hotplug events and so
+	 * userspace will expect to be able to access DRM at this point.
+	 */
+	list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+		ret = drm_sysfs_connector_add(connector);
+		if (ret) {
+			dev_err(drm->dev,
+				"[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n",
+				connector->base.id,
+				drm_get_connector_name(connector), ret);
+			goto err_unbind;
+		}
 	}
 
-	platform_set_drvdata(drm->platformdev, drm);
-	mutex_unlock(&imxdrm->mutex);
+	/*
+	 * All components are now initialised, so setup the fb helper.
+	 * The fb helper takes copies of key hardware information, so the
+	 * crtcs/connectors/encoders must not change after this point.
+	 */
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	if (legacyfb_depth != 16 && legacyfb_depth != 32) {
+		dev_warn(drm->dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
+		legacyfb_depth = 16;
+	}
+	imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
+				drm->mode_config.num_crtc, MAX_CRTC);
+	if (IS_ERR(imxdrm->fbhelper)) {
+		ret = PTR_ERR(imxdrm->fbhelper);
+		imxdrm->fbhelper = NULL;
+		goto err_unbind;
+	}
+#endif
+
+	drm_kms_helper_poll_init(drm);
+
 	return 0;
 
+err_unbind:
+	component_unbind_all(drm->dev, drm);
 err_vblank:
 	drm_vblank_cleanup(drm);
 err_kms:
-	drm_kms_helper_poll_fini(drm);
 	drm_mode_config_cleanup(drm);
-	mutex_unlock(&imxdrm->mutex);
 
 	return ret;
 }
 
-static void imx_drm_update_possible_crtcs(void)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_crtc *imx_drm_crtc;
-	struct imx_drm_encoder *enc;
-	struct crtc_cookie *cookie;
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-		u32 possible_crtcs = 0;
-
-		list_for_each_entry(cookie, &enc->possible_crtcs, list) {
-			list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) {
-				if (imx_drm_crtc->cookie.cookie == cookie->cookie &&
-						imx_drm_crtc->cookie.id == cookie->id) {
-					possible_crtcs |= 1 << imx_drm_crtc->pipe;
-				}
-			}
-		}
-		enc->encoder->possible_crtcs = possible_crtcs;
-		enc->encoder->possible_clones = possible_crtcs;
-	}
-}
-
 /*
  * imx_drm_add_crtc - add a new crtc
  *
  * The return value if !NULL is a cookie for the caller to pass to
  * imx_drm_remove_crtc later.
  */
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
 		struct imx_drm_crtc **new_crtc,
 		const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
-		struct module *owner, void *cookie, int id)
+		void *cookie, int id)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_device *imxdrm = drm->dev_private;
 	struct imx_drm_crtc *imx_drm_crtc;
 	int ret;
 
-	mutex_lock(&imxdrm->mutex);
-
 	/*
 	 * The vblank arrays are dimensioned by MAX_CRTC - we can't
 	 * pass IDs greater than this to those functions.
 	 */
-	if (imxdrm->pipes >= MAX_CRTC) {
-		ret = -EINVAL;
-		goto err_busy;
-	}
+	if (imxdrm->pipes >= MAX_CRTC)
+		return -EINVAL;
 
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
-	}
+	if (imxdrm->drm->open_count)
+		return -EBUSY;
 
 	imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
-	if (!imx_drm_crtc) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
+	if (!imx_drm_crtc)
+		return -ENOMEM;
 
 	imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
 	imx_drm_crtc->pipe = imxdrm->pipes++;
-	imx_drm_crtc->cookie.cookie = cookie;
-	imx_drm_crtc->cookie.id = id;
-
+	imx_drm_crtc->cookie = cookie;
+	imx_drm_crtc->id = id;
+	imx_drm_crtc->mux_id = imx_drm_crtc->pipe;
 	imx_drm_crtc->crtc = crtc;
-	imx_drm_crtc->imxdrm = imxdrm;
 
-	imx_drm_crtc->owner = owner;
-
-	list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list);
+	imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
 
 	*new_crtc = imx_drm_crtc;
 
@@ -520,23 +386,14 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 	drm_crtc_helper_add(crtc,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
-	drm_crtc_init(imxdrm->drm, crtc,
+	drm_crtc_init(drm, crtc,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
 
-	drm_mode_group_reinit(imxdrm->drm);
-
-	imx_drm_update_possible_crtcs();
-
-	mutex_unlock(&imxdrm->mutex);
-
 	return 0;
 
 err_register:
-	list_del(&imx_drm_crtc->list);
+	imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
 	kfree(imx_drm_crtc);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
@@ -546,17 +403,11 @@ EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
  */
 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
 {
-	struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
-
-	mutex_lock(&imxdrm->mutex);
+	struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
 
 	drm_crtc_cleanup(imx_drm_crtc->crtc);
 
-	list_del(&imx_drm_crtc->list);
-
-	drm_mode_group_reinit(imxdrm->drm);
-
-	mutex_unlock(&imxdrm->mutex);
+	imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
 
 	kfree(imx_drm_crtc);
 
@@ -565,220 +416,78 @@ int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
 
 /*
- * imx_drm_add_encoder - add a new encoder
+ * Find the DRM CRTC possible mask for the device node cookie/id.
+ *
+ * The encoder possible masks are defined by their position in the
+ * mode_config crtc_list.  This means that CRTCs must not be added
+ * or removed once the DRM device has been fully initialised.
  */
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-		struct imx_drm_encoder **newenc, struct module *owner)
+static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
+	void *cookie, int id)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *imx_drm_encoder;
-	int ret;
-
-	mutex_lock(&imxdrm->mutex);
-
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
-	}
+	unsigned i;
 
-	imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL);
-	if (!imx_drm_encoder) {
-		ret = -ENOMEM;
-		goto err_alloc;
+	for (i = 0; i < MAX_CRTC; i++) {
+		struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
+		if (imx_drm_crtc && imx_drm_crtc->id == id &&
+		    imx_drm_crtc->cookie == cookie)
+			return drm_crtc_mask(imx_drm_crtc->crtc);
 	}
 
-	imx_drm_encoder->encoder = encoder;
-	imx_drm_encoder->owner = owner;
-
-	ret = imx_drm_encoder_register(imx_drm_encoder);
-	if (ret) {
-		ret = -ENOMEM;
-		goto err_register;
-	}
-
-	list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
-
-	*newenc = imx_drm_encoder;
-
-	mutex_unlock(&imxdrm->mutex);
-
 	return 0;
-
-err_register:
-	kfree(imx_drm_encoder);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
-
-	return ret;
 }
-EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
 
-int imx_drm_encoder_add_possible_crtcs(
-		struct imx_drm_encoder *imx_drm_encoder,
-		struct device_node *np)
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+	struct drm_encoder *encoder, struct device_node *np)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct of_phandle_args args;
-	struct crtc_cookie *c;
-	int ret = 0;
-	int i;
-
-	if (!list_empty(&imx_drm_encoder->possible_crtcs))
-		return -EBUSY;
+	struct imx_drm_device *imxdrm = drm->dev_private;
+	uint32_t crtc_mask = 0;
+	int i, ret = 0;
 
 	for (i = 0; !ret; i++) {
-		ret = of_parse_phandle_with_args(np, "crtcs",
-				"#crtc-cells", i, &args);
-		if (ret < 0)
-			break;
+		struct of_phandle_args args;
+		uint32_t mask;
+		int id;
 
-		c = kzalloc(sizeof(*c), GFP_KERNEL);
-		if (!c) {
-			of_node_put(args.np);
-			return -ENOMEM;
-		}
-
-		c->cookie = args.np;
-		c->id = args.args_count > 0 ? args.args[0] : 0;
+		ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
+						 &args);
+		if (ret == -ENOENT)
+			break;
+		if (ret < 0)
+			return ret;
 
+		id = args.args_count > 0 ? args.args[0] : 0;
+		mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
 		of_node_put(args.np);
 
-		mutex_lock(&imxdrm->mutex);
+		/*
+		 * If we failed to find the CRTC(s) which this encoder is
+		 * supposed to be connected to, it's because the CRTC has
+		 * not been registered yet.  Defer probing, and hope that
+		 * the required CRTC is added later.
+		 */
+		if (mask == 0)
+			return -EPROBE_DEFER;
 
-		list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs);
-
-		mutex_unlock(&imxdrm->mutex);
+		crtc_mask |= mask;
 	}
 
-	imx_drm_update_possible_crtcs();
+	encoder->possible_crtcs = crtc_mask;
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs);
-
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-		struct drm_crtc *crtc)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_crtc *imx_crtc;
-	int i = 0;
-
-	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) {
-		if (imx_crtc->crtc == crtc)
-			goto found;
-		i++;
-	}
-
-	return -EINVAL;
-found:
-	return i;
-}
-EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
-
-/*
- * imx_drm_remove_encoder - remove an encoder
- */
-int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct crtc_cookie *c, *tmp;
-
-	mutex_lock(&imxdrm->mutex);
-
-	imx_drm_encoder_unregister(imx_drm_encoder);
-
-	list_del(&imx_drm_encoder->list);
-
-	list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs,
-			list)
-		kfree(c);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	kfree(imx_drm_encoder);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
-
-/*
- * imx_drm_add_connector - add a connector
- */
-int imx_drm_add_connector(struct drm_connector *connector,
-		struct imx_drm_connector **new_con,
-		struct module *owner)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_connector *imx_drm_connector;
-	int ret;
-
-	mutex_lock(&imxdrm->mutex);
-
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
-	}
-
-	imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL);
-	if (!imx_drm_connector) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
-
-	imx_drm_connector->connector = connector;
-	imx_drm_connector->owner = owner;
-
-	ret = imx_drm_connector_register(imx_drm_connector);
-	if (ret)
-		goto err_register;
-
-	list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
-
-	*new_con = imx_drm_connector;
-
-	mutex_unlock(&imxdrm->mutex);
+	/* FIXME: this is the mask of outputs which can clone this output. */
+	encoder->possible_clones = ~0;
 
 	return 0;
-
-err_register:
-	kfree(imx_drm_connector);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
-
-	return ret;
 }
-EXPORT_SYMBOL_GPL(imx_drm_add_connector);
+EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
 
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper)
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
 
-	imxdrm->fbhelper = fbdev_helper;
+	return imx_crtc ? imx_crtc->mux_id : -EINVAL;
 }
-EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set);
-
-/*
- * imx_drm_remove_connector - remove a connector
- */
-int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	mutex_lock(&imxdrm->mutex);
-
-	imx_drm_connector_unregister(imx_drm_connector);
-
-	list_del(&imx_drm_connector->list);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	kfree(imx_drm_connector);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
+EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 	/* none so far */
@@ -819,80 +528,103 @@ static struct drm_driver imx_drm_driver = {
 	.patchlevel		= 0,
 };
 
-static int imx_drm_platform_probe(struct platform_device *pdev)
+static int compare_parent_of(struct device *dev, void *data)
 {
-	int ret;
-
-	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-	if (ret)
-		return ret;
-
-	imx_drm_device->dev = &pdev->dev;
-
-	return drm_platform_init(&imx_drm_driver, pdev);
+	struct of_phandle_args *args = data;
+	return dev->parent && dev->parent->of_node == args->np;
 }
 
-static int imx_drm_platform_remove(struct platform_device *pdev)
+static int compare_of(struct device *dev, void *data)
 {
-	drm_put_dev(platform_get_drvdata(pdev));
-
-	return 0;
+	return dev->of_node == data;
 }
 
-static struct platform_driver imx_drm_pdrv = {
-	.probe		= imx_drm_platform_probe,
-	.remove		= imx_drm_platform_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "imx-drm",
-	},
-};
-
-static struct platform_device *imx_drm_pdev;
-
-static int __init imx_drm_init(void)
+static int imx_drm_add_components(struct device *master, struct master *m)
 {
+	struct device_node *np = master->of_node;
+	unsigned i;
 	int ret;
 
-	imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
-	if (!imx_drm_device)
-		return -ENOMEM;
+	for (i = 0; ; i++) {
+		struct of_phandle_args args;
+
+		ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+						       i, &args);
+		if (ret)
+			break;
 
-	mutex_init(&imx_drm_device->mutex);
-	INIT_LIST_HEAD(&imx_drm_device->crtc_list);
-	INIT_LIST_HEAD(&imx_drm_device->connector_list);
-	INIT_LIST_HEAD(&imx_drm_device->encoder_list);
+		ret = component_master_add_child(m, compare_parent_of, &args);
+		of_node_put(args.np);
 
-	imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
-	if (IS_ERR(imx_drm_pdev)) {
-		ret = PTR_ERR(imx_drm_pdev);
-		goto err_pdev;
+		if (ret)
+			return ret;
 	}
 
-	ret = platform_driver_register(&imx_drm_pdrv);
-	if (ret)
-		goto err_pdrv;
+	for (i = 0; ; i++) {
+		struct device_node *node;
+
+		node = of_parse_phandle(np, "connectors", i);
+		if (!node)
+			break;
+
+		ret = component_master_add_child(m, compare_of, node);
+		of_node_put(node);
 
+		if (ret)
+			return ret;
+	}
 	return 0;
+}
 
-err_pdrv:
-	platform_device_unregister(imx_drm_pdev);
-err_pdev:
-	kfree(imx_drm_device);
+static int imx_drm_bind(struct device *dev)
+{
+	return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
 
-	return ret;
+static void imx_drm_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
 }
 
-static void __exit imx_drm_exit(void)
+static const struct component_master_ops imx_drm_ops = {
+	.add_components = imx_drm_add_components,
+	.bind = imx_drm_bind,
+	.unbind = imx_drm_unbind,
+};
+
+static int imx_drm_platform_probe(struct platform_device *pdev)
 {
-	platform_device_unregister(imx_drm_pdev);
-	platform_driver_unregister(&imx_drm_pdrv);
+	int ret;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret)
+		return ret;
 
-	kfree(imx_drm_device);
+	return component_master_add(&pdev->dev, &imx_drm_ops);
 }
 
-module_init(imx_drm_init);
-module_exit(imx_drm_exit);
+static int imx_drm_platform_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &imx_drm_ops);
+	return 0;
+}
+
+static const struct of_device_id imx_drm_dt_ids[] = {
+	{ .compatible = "fsl,imx-drm", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
+static struct platform_driver imx_drm_pdrv = {
+	.probe		= imx_drm_platform_probe,
+	.remove		= imx_drm_platform_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "imx-drm",
+		.of_match_table = imx_drm_dt_ids,
+	},
+};
+module_platform_driver(imx_drm_pdrv);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX drm driver core");
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index ae90c9c15312..035ab6258ad0 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -1,17 +1,15 @@
 #ifndef _IMX_DRM_H_
 #define _IMX_DRM_H_
 
-#include <linux/videodev2.h>
-
-#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
-
+struct device_node;
 struct drm_crtc;
 struct drm_connector;
 struct drm_device;
+struct drm_display_mode;
 struct drm_encoder;
-struct imx_drm_crtc;
 struct drm_fbdev_cma;
 struct drm_framebuffer;
+struct imx_drm_crtc;
 struct platform_device;
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
@@ -25,10 +23,10 @@ struct imx_drm_crtc_helper_funcs {
 	const struct drm_crtc_funcs *crtc_funcs;
 };
 
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
 		struct imx_drm_crtc **new_crtc,
 		const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
-		struct module *owner, void *cookie, int id);
+		void *cookie, int id);
 int imx_drm_remove_crtc(struct imx_drm_crtc *);
 int imx_drm_init_drm(struct platform_device *pdev,
 		int preferred_bpp);
@@ -38,35 +36,22 @@ int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc);
 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);
 
-struct imx_drm_encoder;
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-		struct imx_drm_encoder **new_enc,
-		struct module *owner);
-int imx_drm_remove_encoder(struct imx_drm_encoder *);
-
-struct imx_drm_connector;
-int imx_drm_add_connector(struct drm_connector *connector,
-		struct imx_drm_connector **new_con,
-		struct module *owner);
-int imx_drm_remove_connector(struct imx_drm_connector *);
-
 void imx_drm_mode_config_init(struct drm_device *drm);
 
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
-struct drm_device *imx_drm_device_get(void);
-void imx_drm_device_put(void);
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
 		u32 interface_pix_fmt, int hsync_pin, int vsync_pin);
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format(struct drm_encoder *encoder,
 		u32 interface_pix_fmt);
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper);
 
-struct device_node;
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder);
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+	struct drm_encoder *encoder, struct device_node *np);
 
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-		struct drm_crtc *crtc);
-int imx_drm_encoder_add_possible_crtcs(struct imx_drm_encoder *imx_drm_encoder,
-		struct device_node *np);
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+	struct drm_display_mode *mode);
+void imx_drm_connector_destroy(struct drm_connector *connector);
+void imx_drm_encoder_destroy(struct drm_encoder *encoder);
 
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/imx-fb.c b/drivers/staging/imx-drm/imx-fb.c
deleted file mode 100644
index 03a7b4e14f67..000000000000
--- a/drivers/staging/imx-drm/imx-fb.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., 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.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
-	.fb_create = drm_fb_cma_create,
-};
-
-void imx_drm_mode_config_init(struct drm_device *dev)
-{
-	dev->mode_config.min_width = 64;
-	dev->mode_config.min_height = 64;
-
-	/*
-	 * set max width and height as default value(4096x4096).
-	 * this value would be used to check framebuffer size limitation
-	 * at drm_mode_addfb().
-	 */
-	dev->mode_config.max_width = 4096;
-	dev->mode_config.max_height = 4096;
-
-	dev->mode_config.funcs = &imx_drm_mode_config_funcs;
-}
diff --git a/drivers/staging/imx-drm/imx-fbdev.c b/drivers/staging/imx-drm/imx-fbdev.c
deleted file mode 100644
index 8331739c3d08..000000000000
--- a/drivers/staging/imx-drm/imx-fbdev.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., 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.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-#define MAX_CONNECTOR		4
-#define PREFERRED_BPP		16
-
-static struct drm_fbdev_cma *fbdev_cma;
-
-static int legacyfb_depth = 16;
-
-module_param(legacyfb_depth, int, 0444);
-
-static int __init imx_fb_helper_init(void)
-{
-	struct drm_device *drm = imx_drm_device_get();
-
-	if (!drm)
-		return -EINVAL;
-
-	if (legacyfb_depth != 16 && legacyfb_depth != 32) {
-		pr_warn("i.MX legacyfb: invalid legacyfb_depth setting. defaulting to 16bpp\n");
-		legacyfb_depth = 16;
-	}
-
-	fbdev_cma = drm_fbdev_cma_init(drm, legacyfb_depth,
-			drm->mode_config.num_crtc, MAX_CONNECTOR);
-
-	if (IS_ERR(fbdev_cma)) {
-		imx_drm_device_put();
-		return PTR_ERR(fbdev_cma);
-	}
-
-	imx_drm_fb_helper_set(fbdev_cma);
-
-	return 0;
-}
-
-static void __exit imx_fb_helper_exit(void)
-{
-	imx_drm_fb_helper_set(NULL);
-	drm_fbdev_cma_fini(fbdev_cma);
-	imx_drm_device_put();
-}
-
-late_initcall(imx_fb_helper_init);
-module_exit(imx_fb_helper_exit);
-
-MODULE_DESCRIPTION("Freescale i.MX legacy fb driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c
index 62ce0e86f14b..8384ceab932a 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -12,6 +12,7 @@
  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  */
 
+#include <linux/component.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -112,15 +113,15 @@ struct hdmi_data_info {
 
 struct imx_hdmi {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 
 	enum imx_hdmi_devtype dev_type;
 	struct device *dev;
 	struct clk *isfr_clk;
 	struct clk *iahb_clk;
 
+	enum drm_connector_status connector_status;
+
 	struct hdmi_data_info hdmi_data;
 	int vic;
 
@@ -134,7 +135,6 @@ struct imx_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *regs;
 
-	unsigned long pixel_clk_rate;
 	unsigned int sample_rate;
 	int ratio;
 };
@@ -156,37 +156,34 @@ static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
 	return readb(hdmi->regs + offset);
 }
 
+static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+	u8 val = hdmi_readb(hdmi, reg) & ~mask;
+	val |= data & mask;
+	hdmi_writeb(hdmi, val, reg);
+}
+
 static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
 		      u8 shift, u8 mask)
 {
-	u8 value = hdmi_readb(hdmi, reg) & ~mask;
-	value |= (data << shift) & mask;
-	hdmi_writeb(hdmi, value, reg);
+	hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
 static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
 					 unsigned int value)
 {
-	u8 val;
-
 	hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
 	hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
 	hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
 
 	/* nshift factor = 0 */
-	val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-	val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
-	hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 }
 
 static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
 {
-	u8 val;
-
 	/* Must be set/cleared first */
-	val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-	val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
-	hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
 	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
@@ -331,34 +328,25 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 		return (cts * ratio) / 100;
 }
 
-static void hdmi_get_pixel_clk(struct imx_hdmi *hdmi)
-{
-	unsigned long rate;
-
-	rate = 65000000; /* FIXME */
-
-	if (rate)
-		hdmi->pixel_clk_rate = rate;
-}
-
-static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi)
+static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
+	unsigned long pixel_clk)
 {
 	unsigned int clk_n, clk_cts;
 
-	clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
+	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
 			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
+	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
 				   hdmi->ratio);
 
 	if (!clk_cts) {
 		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			 __func__, hdmi->pixel_clk_rate);
+			 __func__, pixel_clk);
 		return;
 	}
 
 	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
 		__func__, hdmi->sample_rate, hdmi->ratio,
-		hdmi->pixel_clk_rate, clk_n, clk_cts);
+		pixel_clk, clk_n, clk_cts);
 
 	hdmi_set_clock_regenerator_n(hdmi, clk_n);
 	hdmi_regenerate_cts(hdmi, clk_cts);
@@ -366,32 +354,12 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi)
 
 static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
 {
-	unsigned int clk_n, clk_cts;
-
-	clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
-			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
-				   hdmi->ratio);
-
-	if (!clk_cts) {
-		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			 __func__, hdmi->pixel_clk_rate);
-		return;
-	}
-
-	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-		__func__, hdmi->sample_rate, hdmi->ratio,
-		hdmi->pixel_clk_rate, clk_n, clk_cts);
-
-	hdmi_set_clock_regenerator_n(hdmi, clk_n);
-	hdmi_regenerate_cts(hdmi, clk_cts);
+	hdmi_set_clk_regenerator(hdmi, 74250000);
 }
 
 static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
 {
-	/* Get pixel clock from ipu */
-	hdmi_get_pixel_clk(hdmi);
-	hdmi_set_clk_regenerator(hdmi);
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
 }
 
 /*
@@ -459,29 +427,34 @@ static void hdmi_video_sample(struct imx_hdmi *hdmi)
 
 static int is_color_space_conversion(struct imx_hdmi *hdmi)
 {
-	return (hdmi->hdmi_data.enc_in_format !=
-		hdmi->hdmi_data.enc_out_format);
+	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
 }
 
 static int is_color_space_decimation(struct imx_hdmi *hdmi)
 {
-	return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
-		(hdmi->hdmi_data.enc_in_format == RGB ||
-		hdmi->hdmi_data.enc_in_format == YCBCR444));
+	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
+		return 0;
+	if (hdmi->hdmi_data.enc_in_format == RGB ||
+	    hdmi->hdmi_data.enc_in_format == YCBCR444)
+		return 1;
+	return 0;
 }
 
 static int is_color_space_interpolation(struct imx_hdmi *hdmi)
 {
-	return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
-		(hdmi->hdmi_data.enc_out_format == RGB ||
-		hdmi->hdmi_data.enc_out_format == YCBCR444));
+	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
+		return 0;
+	if (hdmi->hdmi_data.enc_out_format == RGB ||
+	    hdmi->hdmi_data.enc_out_format == YCBCR444)
+		return 1;
+	return 0;
 }
 
 static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
 {
 	const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+	unsigned i;
 	u32 csc_scale = 1;
-	u8 val;
 
 	if (is_color_space_conversion(hdmi)) {
 		if (hdmi->hdmi_data.enc_out_format == RGB) {
@@ -498,37 +471,22 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
 		}
 	}
 
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][0] & 0xff), HDMI_CSC_COEF_A1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][0] >> 8), HDMI_CSC_COEF_A1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][1] & 0xff), HDMI_CSC_COEF_A2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][1] >> 8), HDMI_CSC_COEF_A2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][2] & 0xff), HDMI_CSC_COEF_A3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][2] >> 8), HDMI_CSC_COEF_A3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][3] & 0xff), HDMI_CSC_COEF_A4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][3] >> 8), HDMI_CSC_COEF_A4_MSB);
-
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][0] & 0xff), HDMI_CSC_COEF_B1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][0] >> 8), HDMI_CSC_COEF_B1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][1] & 0xff), HDMI_CSC_COEF_B2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][1] >> 8), HDMI_CSC_COEF_B2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][2] & 0xff), HDMI_CSC_COEF_B3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][2] >> 8), HDMI_CSC_COEF_B3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][3] & 0xff), HDMI_CSC_COEF_B4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][3] >> 8), HDMI_CSC_COEF_B4_MSB);
-
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][0] & 0xff), HDMI_CSC_COEF_C1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][0] >> 8), HDMI_CSC_COEF_C1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][1] & 0xff), HDMI_CSC_COEF_C2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][1] >> 8), HDMI_CSC_COEF_C2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][2] & 0xff), HDMI_CSC_COEF_C3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][2] >> 8), HDMI_CSC_COEF_C3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][3] & 0xff), HDMI_CSC_COEF_C4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][3] >> 8), HDMI_CSC_COEF_C4_MSB);
-
-	val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-	val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
-	val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
-	hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+	/* The CSC registers are sequential, alternating MSB then LSB */
+	for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+		u16 coeff_a = (*csc_coeff)[0][i];
+		u16 coeff_b = (*csc_coeff)[1][i];
+		u16 coeff_c = (*csc_coeff)[2][i];
+
+		hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+	}
+
+	hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+		  HDMI_CSC_SCALE);
 }
 
 static void hdmi_video_csc(struct imx_hdmi *hdmi)
@@ -536,7 +494,6 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
 	int color_depth = 0;
 	int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
 	int decimation = 0;
-	u8 val;
 
 	/* YCC422 interpolation to 444 mode */
 	if (is_color_space_interpolation(hdmi))
@@ -557,10 +514,8 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
 
 	/* Configure the CSC registers */
 	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
-	val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-	val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
-	val |= color_depth;
-	hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+	hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+		  HDMI_CSC_SCALE);
 
 	imx_hdmi_update_csc_coeffs(hdmi);
 }
@@ -576,7 +531,7 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
 	unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
 	unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
 	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
-	u8 val;
+	u8 val, vp_conf;
 
 	if (hdmi_data->enc_out_format == RGB
 		|| hdmi_data->enc_out_format == YCBCR444) {
@@ -615,107 +570,75 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
 		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
 	hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
-	val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
 
 	/* Data from pixel repeater block */
 	if (hdmi_data->pix_repet_factor > 1) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-			HDMI_VP_CONF_BYPASS_SELECT_MASK);
-		val |= HDMI_VP_CONF_PR_EN_ENABLE |
-			HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
 	} else { /* data from packetizer block */
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-			HDMI_VP_CONF_BYPASS_SELECT_MASK);
-		val |= HDMI_VP_CONF_PR_EN_DISABLE |
-			HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
 	}
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
-	val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_PR_EN_MASK |
+		  HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+	hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+		  HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
 
 	hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
 
 	if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-			HDMI_VP_CONF_PP_EN_ENABLE |
-			HDMI_VP_CONF_YCC422_EN_DISABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_ENABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-			HDMI_VP_CONF_PP_EN_DISABLE |
-			HDMI_VP_CONF_YCC422_EN_ENABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_ENABLE;
 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
-			HDMI_VP_CONF_PP_EN_DISABLE |
-			HDMI_VP_CONF_YCC422_EN_DISABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
 	} else {
 		return;
 	}
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
-		HDMI_VP_STUFF_YCC422_STUFFING_MASK);
-	val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
-		HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+		  HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
 
-	val = hdmi_readb(hdmi, HDMI_VP_CONF);
-	val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
-	val |= output_select;
-	hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+			HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PP_STUFFING_MASK |
+		  HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
+
+	hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+		  HDMI_VP_CONF);
 }
 
 static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
-		HDMI_PHY_TST0_TSTCLR_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+		  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTEN_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
-		HDMI_PHY_TST0_TSTEN_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
+		  HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
-		HDMI_PHY_TST0_TSTCLK_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
+		  HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
@@ -806,19 +729,94 @@ static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+enum {
+	RES_8,
+	RES_10,
+	RES_12,
+	RES_MAX,
+};
+
+struct mpll_config {
+	unsigned long mpixelclock;
+	struct {
+		u16 cpce;
+		u16 gmp;
+	} res[RES_MAX];
+};
+
+static const struct mpll_config mpll_config[] = {
+	{
+		45250000, {
+			{ 0x01e0, 0x0000 },
+			{ 0x21e1, 0x0000 },
+			{ 0x41e2, 0x0000 }
+		},
+	}, {
+		92500000, {
+			{ 0x0140, 0x0005 },
+			{ 0x2141, 0x0005 },
+			{ 0x4142, 0x0005 },
+		},
+	}, {
+		148500000, {
+			{ 0x00a0, 0x000a },
+			{ 0x20a1, 0x000a },
+			{ 0x40a2, 0x000a },
+		},
+	}, {
+		~0UL, {
+			{ 0x00a0, 0x000a },
+			{ 0x2001, 0x000f },
+			{ 0x4002, 0x000f },
+		},
+	}
+};
+
+struct curr_ctrl {
+	unsigned long mpixelclock;
+	u16 curr[RES_MAX];
+};
+
+static const struct curr_ctrl curr_ctrl[] = {
+	/*	pixelclk     bpp8    bpp10   bpp12 */
+	{
+		 54000000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		 58400000, { 0x091c, 0x06dc, 0x06dc },
+	}, {
+		 72000000, { 0x06dc, 0x06dc, 0x091c },
+	}, {
+		 74250000, { 0x06dc, 0x0b5c, 0x091c },
+	}, {
+		118800000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		216000000, { 0x06dc, 0x0b5c, 0x091c },
+	}
+};
+
 static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
 			      unsigned char res, int cscon)
 {
+	unsigned res_idx, i;
 	u8 val, msec;
 
-	/* color resolution 0 is 8 bit colour depth */
-	if (!res)
-		res = 8;
-
 	if (prep)
 		return -EINVAL;
-	else if (res != 8 && res != 12)
+
+	switch (res) {
+	case 0:	/* color resolution 0 is 8 bit colour depth */
+	case 8:
+		res_idx = RES_8;
+		break;
+	case 10:
+		res_idx = RES_10;
+		break;
+	case 12:
+		res_idx = RES_12;
+		break;
+	default:
 		return -EINVAL;
+	}
 
 	/* Enable csc path */
 	if (cscon)
@@ -845,165 +843,30 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
 			HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	if (hdmi->hdmi_data.video_mode.mpixelclock <= 45250000) {
-		switch (res) {
-		case 8:
-			/* PLL/MPLL Cfg */
-			hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);  /* GMPCTRL */
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
+	/* PLL/MPLL Cfg - always match on final entry */
+	for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    mpll_config[i].mpixelclock)
 			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 92500000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x2141, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x4142, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 148500000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-		default:
-			return -EINVAL;
-		}
-	} else {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x2001, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x4002, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-		default:
-			return -EINVAL;
-		}
-	}
 
-	if (hdmi->hdmi_data.video_mode.mpixelclock <= 54000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);  /* CURRCTRL */
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 58400000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 72000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 74250000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 118800000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 216000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+
+	for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    curr_ctrl[i].mpixelclock)
 			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
+
+	if (i >= ARRAY_SIZE(curr_ctrl)) {
 		dev_err(hdmi->dev,
 				"Pixel clock %d - unsupported by HDMI\n",
 				hdmi->hdmi_data.video_mode.mpixelclock);
 		return -EINVAL;
 	}
 
+	/* CURRCTRL */
+	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+
 	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
 	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
 	/* RESISTANCE TERM 133Ohm Cfg */
@@ -1072,7 +935,7 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
 
 static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
 {
-	u8 de, val;
+	u8 de;
 
 	if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
 		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
@@ -1080,20 +943,13 @@ static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
 		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
 
 	/* disable rx detect */
-	val = hdmi_readb(hdmi, HDMI_A_HDCPCFG0);
-	val &= HDMI_A_HDCPCFG0_RXDETECT_MASK;
-	val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE;
-	hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG0);
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+		  HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
 
-	val = hdmi_readb(hdmi, HDMI_A_VIDPOLCFG);
-	val &= HDMI_A_VIDPOLCFG_DATAENPOL_MASK;
-	val |= de;
-	hdmi_writeb(hdmi, val, HDMI_A_VIDPOLCFG);
+	hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
 
-	val = hdmi_readb(hdmi, HDMI_A_HDCPCFG1);
-	val &= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK;
-	val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE;
-	hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG1);
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+		  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
 static void hdmi_config_AVI(struct imx_hdmi *hdmi)
@@ -1317,11 +1173,7 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
 
 static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
 {
-	u8 clkdis;
-
-	clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS);
-	clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
-	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
 }
 
 /* Workaround to clear the overflow condition */
@@ -1456,9 +1308,6 @@ static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi)
 	/* Clear Hotplug interrupts */
 	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
 
-	/* Unmute interrupts */
-	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
-
 	return 0;
 }
 
@@ -1527,12 +1376,9 @@ static void imx_hdmi_poweroff(struct imx_hdmi *hdmi)
 static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
 							*connector, bool force)
 {
-	/* FIXME */
-	return connector_status_connected;
-}
-
-static void imx_hdmi_connector_destroy(struct drm_connector *connector)
-{
+	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+					     connector);
+	return hdmi->connector_status;
 }
 
 static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1560,13 +1406,6 @@ static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
 	return 0;
 }
 
-static int imx_hdmi_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-
-	return MODE_OK;
-}
-
 static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
 							   *connector)
 {
@@ -1614,28 +1453,21 @@ static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
 	struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
 
 	imx_hdmi_poweroff(hdmi);
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-				  V4L2_PIX_FMT_RGB24);
+	imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
 }
 
 static void imx_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
 	struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
-	int mux = imx_drm_encoder_get_mux_id(hdmi->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	imx_hdmi_set_ipu_di_mux(hdmi, mux);
 
 	imx_hdmi_poweron(hdmi);
 }
 
-static void imx_hdmi_encoder_destroy(struct drm_encoder *encoder)
-{
-	return;
-}
-
 static struct drm_encoder_funcs imx_hdmi_encoder_funcs = {
-	.destroy = imx_hdmi_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = {
@@ -1651,21 +1483,32 @@ static struct drm_connector_funcs imx_hdmi_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_hdmi_connector_detect,
-	.destroy = imx_hdmi_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
 	.get_modes = imx_hdmi_connector_get_modes,
-	.mode_valid = imx_hdmi_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 	.best_encoder = imx_hdmi_connector_best_encoder,
 };
 
+static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id)
+{
+	struct imx_hdmi *hdmi = dev_id;
+	u8 intr_stat;
+
+	intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
+	if (intr_stat)
+		hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
+}
+
 static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
 {
 	struct imx_hdmi *hdmi = dev_id;
 	u8 intr_stat;
 	u8 phy_int_pol;
-	u8 val;
 
 	intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
 
@@ -1675,55 +1518,46 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
 		if (phy_int_pol & HDMI_PHY_HPD) {
 			dev_dbg(hdmi->dev, "EVENT=plugin\n");
 
-			val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-			val &= ~HDMI_PHY_HPD;
-			hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+			hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+			hdmi->connector_status = connector_status_connected;
 			imx_hdmi_poweron(hdmi);
 		} else {
 			dev_dbg(hdmi->dev, "EVENT=plugout\n");
 
-			val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-			val |= HDMI_PHY_HPD;
-			hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+			hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+			hdmi->connector_status = connector_status_disconnected;
 			imx_hdmi_poweroff(hdmi);
 		}
+		drm_helper_hpd_irq_event(hdmi->connector.dev);
 	}
 
 	hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
 	return IRQ_HANDLED;
 }
 
-static int imx_hdmi_register(struct imx_hdmi *hdmi)
+static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi)
 {
 	int ret;
 
-	hdmi->connector.funcs = &imx_hdmi_connector_funcs;
-	hdmi->encoder.funcs = &imx_hdmi_encoder_funcs;
+	ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder,
+				       hdmi->dev->of_node);
+	if (ret)
+		return ret;
 
-	hdmi->encoder.encoder_type = DRM_MODE_ENCODER_TMDS;
-	hdmi->connector.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
 	drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&hdmi->encoder, &hdmi->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(hdmi->dev, "adding encoder failed: %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_connector_helper_add(&hdmi->connector,
 			&imx_hdmi_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&hdmi->connector,
-			&hdmi->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(hdmi->imx_drm_encoder);
-		dev_err(hdmi->dev, "adding connector failed: %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
+			   DRM_MODE_CONNECTOR_HDMIA);
 
 	hdmi->connector.encoder = &hdmi->encoder;
 
@@ -1750,21 +1584,26 @@ static const struct of_device_id imx_hdmi_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
 
-static int imx_hdmi_platform_probe(struct platform_device *pdev)
+static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	const struct of_device_id *of_id =
-				of_match_device(imx_hdmi_dt_ids, &pdev->dev);
-	struct device_node *np = pdev->dev.of_node;
+				of_match_device(imx_hdmi_dt_ids, dev);
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	struct device_node *ddc_node;
 	struct imx_hdmi *hdmi;
 	struct resource *iores;
 	int ret, irq;
 
-	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 	if (!hdmi)
 		return -ENOMEM;
 
-	hdmi->dev = &pdev->dev;
+	hdmi->dev = dev;
+	hdmi->connector_status = connector_status_disconnected;
+	hdmi->sample_rate = 48000;
+	hdmi->ratio = 100;
 
 	if (of_id) {
 		const struct platform_device_id *device_id = of_id->data;
@@ -1786,13 +1625,14 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return -EINVAL;
 
-	ret = devm_request_irq(&pdev->dev, irq, imx_hdmi_irq, 0,
-			       dev_name(&pdev->dev), hdmi);
+	ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq,
+					imx_hdmi_irq, IRQF_SHARED,
+					dev_name(dev), hdmi);
 	if (ret)
 		return ret;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hdmi->regs = devm_ioremap_resource(&pdev->dev, iores);
+	hdmi->regs = devm_ioremap_resource(dev, iores);
 	if (IS_ERR(hdmi->regs))
 		return PTR_ERR(hdmi->regs);
 
@@ -1831,7 +1671,7 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
 	}
 
 	/* Product and revision IDs */
-	dev_info(&pdev->dev,
+	dev_info(dev,
 		"Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
 		hdmi_readb(hdmi, HDMI_DESIGN_ID),
 		hdmi_readb(hdmi, HDMI_REVISION_ID),
@@ -1859,13 +1699,14 @@ static int imx_hdmi_platform_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_iahb;
 
-	ret = imx_hdmi_register(hdmi);
+	ret = imx_hdmi_register(drm, hdmi);
 	if (ret)
 		goto err_iahb;
 
-	imx_drm_encoder_add_possible_crtcs(hdmi->imx_drm_encoder, np);
+	/* Unmute interrupts */
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
-	platform_set_drvdata(pdev, hdmi);
+	dev_set_drvdata(dev, hdmi);
 
 	return 0;
 
@@ -1877,20 +1718,35 @@ err_isfr:
 	return ret;
 }
 
-static int imx_hdmi_platform_remove(struct platform_device *pdev)
+static void imx_hdmi_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_hdmi *hdmi = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &hdmi->connector;
-	struct drm_encoder *encoder = &hdmi->encoder;
+	struct imx_hdmi *hdmi = dev_get_drvdata(dev);
 
-	drm_mode_connector_detach_encoder(connector, encoder);
-	imx_drm_remove_connector(hdmi->imx_drm_connector);
-	imx_drm_remove_encoder(hdmi->imx_drm_encoder);
+	/* Disable all interrupts */
+	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	hdmi->connector.funcs->destroy(&hdmi->connector);
+	hdmi->encoder.funcs->destroy(&hdmi->encoder);
 
 	clk_disable_unprepare(hdmi->iahb_clk);
 	clk_disable_unprepare(hdmi->isfr_clk);
 	i2c_put_adapter(hdmi->ddc);
+}
+
+static const struct component_ops hdmi_ops = {
+	.bind	= imx_hdmi_bind,
+	.unbind	= imx_hdmi_unbind,
+};
+
+static int imx_hdmi_platform_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &hdmi_ops);
+}
 
+static int imx_hdmi_platform_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &hdmi_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index 7e593296ac47..daa54df4527f 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -58,9 +59,8 @@ struct imx_ldb;
 struct imx_ldb_channel {
 	struct imx_ldb *ldb;
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
+	struct device_node *child;
 	int chno;
 	void *edid;
 	int edid_len;
@@ -91,11 +91,6 @@ static enum drm_connector_status imx_ldb_connector_detect(
 	return connector_status_connected;
 }
 
-static void imx_ldb_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
@@ -111,6 +106,8 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 		struct drm_display_mode *mode;
 
 		mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		drm_mode_copy(mode, &imx_ldb_ch->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 		drm_mode_probed_add(connector, mode);
@@ -120,12 +117,6 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 	return num_modes;
 }
 
-static int imx_ldb_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-	return 0;
-}
-
 static struct drm_encoder *imx_ldb_connector_best_encoder(
 		struct drm_connector *connector)
 {
@@ -179,8 +170,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
 	u32 pixel_fmt;
 	unsigned long serial_clk;
 	unsigned long di_clk = mode->clock * 1000;
-	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
 		/* dual channel LVDS mode */
@@ -207,8 +197,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
 		pixel_fmt = V4L2_PIX_FMT_RGB24;
 	}
 
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_LVDS,
-			pixel_fmt);
+	imx_drm_panel_format(encoder, pixel_fmt);
 }
 
 static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
@@ -216,8 +205,7 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
 	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
 	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
-	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	if (dual) {
 		clk_prepare_enable(ldb->clk[0]);
@@ -316,26 +304,21 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
 	}
 }
 
-static void imx_ldb_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_ldb_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_ldb_connector_detect,
-	.destroy = imx_ldb_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
 	.get_modes = imx_ldb_connector_get_modes,
 	.best_encoder = imx_ldb_connector_best_encoder,
-	.mode_valid = imx_ldb_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
-	.destroy = imx_ldb_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
@@ -351,56 +334,47 @@ static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
 {
 	char clkname[16];
 
-	sprintf(clkname, "di%d", chno);
+	snprintf(clkname, sizeof(clkname), "di%d", chno);
 	ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
 	if (IS_ERR(ldb->clk[chno]))
 		return PTR_ERR(ldb->clk[chno]);
 
-	sprintf(clkname, "di%d_pll", chno);
+	snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
 	ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
 
 	return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
 }
 
-static int imx_ldb_register(struct imx_ldb_channel *imx_ldb_ch)
+static int imx_ldb_register(struct drm_device *drm,
+	struct imx_ldb_channel *imx_ldb_ch)
 {
-	int ret;
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
+	int ret;
+
+	ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
+				       imx_ldb_ch->child);
+	if (ret)
+		return ret;
 
 	ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
 	if (ret)
 		return ret;
+
 	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
-		ret |= imx_ldb_get_clk(ldb, 1);
+		ret = imx_ldb_get_clk(ldb, 1);
 		if (ret)
 			return ret;
 	}
 
-	imx_ldb_ch->connector.funcs = &imx_ldb_connector_funcs;
-	imx_ldb_ch->encoder.funcs = &imx_ldb_encoder_funcs;
-
-	imx_ldb_ch->encoder.encoder_type = DRM_MODE_ENCODER_LVDS;
-	imx_ldb_ch->connector.connector_type = DRM_MODE_CONNECTOR_LVDS;
-
 	drm_encoder_helper_add(&imx_ldb_ch->encoder,
 			&imx_ldb_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&imx_ldb_ch->encoder,
-			&imx_ldb_ch->imx_drm_encoder, THIS_MODULE);
-	if (ret) {
-		dev_err(ldb->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
+			 DRM_MODE_ENCODER_LVDS);
 
 	drm_connector_helper_add(&imx_ldb_ch->connector,
 			&imx_ldb_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&imx_ldb_ch->connector,
-			&imx_ldb_ch->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(imx_ldb_ch->imx_drm_encoder);
-		dev_err(ldb->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &imx_ldb_ch->connector,
+			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
 
 	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
 			&imx_ldb_ch->encoder);
@@ -459,11 +433,12 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
 
-static int imx_ldb_probe(struct platform_device *pdev)
+static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	const struct of_device_id *of_id =
-			of_match_device(imx_ldb_dt_ids, &pdev->dev);
+			of_match_device(imx_ldb_dt_ids, dev);
 	struct device_node *child;
 	const u8 *edidp;
 	struct imx_ldb *imx_ldb;
@@ -473,17 +448,17 @@ static int imx_ldb_probe(struct platform_device *pdev)
 	int ret;
 	int i;
 
-	imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+	imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
 	if (!imx_ldb)
 		return -ENOMEM;
 
 	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
 	if (IS_ERR(imx_ldb->regmap)) {
-		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		dev_err(dev, "failed to get parent regmap\n");
 		return PTR_ERR(imx_ldb->regmap);
 	}
 
-	imx_ldb->dev = &pdev->dev;
+	imx_ldb->dev = dev;
 
 	if (of_id)
 		imx_ldb->lvds_mux = of_id->data;
@@ -521,7 +496,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
 			return -EINVAL;
 
 		if (dual && i > 0) {
-			dev_warn(&pdev->dev, "dual-channel mode, ignoring second output\n");
+			dev_warn(dev, "dual-channel mode, ignoring second output\n");
 			continue;
 		}
 
@@ -531,6 +506,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
 		channel = &imx_ldb->channel[i];
 		channel->ldb = imx_ldb;
 		channel->chno = i;
+		channel->child = child;
 
 		edidp = of_get_property(child, "edid", &channel->edid_len);
 		if (edidp) {
@@ -560,7 +536,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
 			break;
 		case LVDS_BIT_MAP_JEIDA:
 			if (datawidth == 18) {
-				dev_err(&pdev->dev, "JEIDA standard only supported in 24 bit\n");
+				dev_err(dev, "JEIDA standard only supported in 24 bit\n");
 				return -EINVAL;
 			}
 			if (i == 0 || dual)
@@ -569,38 +545,47 @@ static int imx_ldb_probe(struct platform_device *pdev)
 				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
 			break;
 		default:
-			dev_err(&pdev->dev, "data mapping not specified or invalid\n");
+			dev_err(dev, "data mapping not specified or invalid\n");
 			return -EINVAL;
 		}
 
-		ret = imx_ldb_register(channel);
+		ret = imx_ldb_register(drm, channel);
 		if (ret)
 			return ret;
-
-		imx_drm_encoder_add_possible_crtcs(channel->imx_drm_encoder, child);
 	}
 
-	platform_set_drvdata(pdev, imx_ldb);
+	dev_set_drvdata(dev, imx_ldb);
 
 	return 0;
 }
 
-static int imx_ldb_remove(struct platform_device *pdev)
+static void imx_ldb_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_ldb *imx_ldb = platform_get_drvdata(pdev);
+	struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
 	int i;
 
 	for (i = 0; i < 2; i++) {
 		struct imx_ldb_channel *channel = &imx_ldb->channel[i];
-		struct drm_connector *connector = &channel->connector;
-		struct drm_encoder *encoder = &channel->encoder;
-
-		drm_mode_connector_detach_encoder(connector, encoder);
 
-		imx_drm_remove_connector(channel->imx_drm_connector);
-		imx_drm_remove_encoder(channel->imx_drm_encoder);
+		channel->connector.funcs->destroy(&channel->connector);
+		channel->encoder.funcs->destroy(&channel->encoder);
 	}
+}
+
+static const struct component_ops imx_ldb_ops = {
+	.bind	= imx_ldb_bind,
+	.unbind	= imx_ldb_unbind,
+};
 
+static int imx_ldb_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_ldb_ops);
+}
+
+static int imx_ldb_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &imx_ldb_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index 9abc7ca8b6cf..50b25f1a85d5 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
@@ -30,6 +31,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
+#include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
 
 #define TVE_COM_CONF_REG	0x00
@@ -110,9 +112,7 @@ enum {
 
 struct imx_tve {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 	struct device *dev;
 	spinlock_t lock;	/* register lock */
 	bool enabled;
@@ -225,11 +225,6 @@ static enum drm_connector_status imx_tve_connector_detect(
 	return connector_status_connected;
 }
 
-static void imx_tve_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_tve_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_tve *tve = con_to_tve(connector);
@@ -254,6 +249,11 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
 {
 	struct imx_tve *tve = con_to_tve(connector);
 	unsigned long rate;
+	int ret;
+
+	ret = imx_drm_connector_mode_valid(connector, mode);
+	if (ret != MODE_OK)
+		return ret;
 
 	/* pixel clock with 2x oversampling */
 	rate = clk_round_rate(tve->clk, 2000UL * mode->clock) / 2000;
@@ -305,13 +305,11 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
 
 	switch (tve->mode) {
 	case TVE_MODE_VGA:
-		imx_drm_crtc_panel_format_pins(encoder->crtc,
-				DRM_MODE_ENCODER_DAC, IPU_PIX_FMT_GBR24,
+		imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24,
 				tve->hsync_pin, tve->vsync_pin);
 		break;
 	case TVE_MODE_TVOUT:
-		imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_TVDAC,
-					  V4L2_PIX_FMT_YUV444);
+		imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444);
 		break;
 	}
 }
@@ -364,16 +362,11 @@ static void imx_tve_encoder_disable(struct drm_encoder *encoder)
 	tve_disable(tve);
 }
 
-static void imx_tve_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_tve_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_tve_connector_detect,
-	.destroy = imx_tve_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
@@ -383,7 +376,7 @@ static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
 };
 
 static struct drm_encoder_funcs imx_tve_encoder_funcs = {
-	.destroy = imx_tve_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = {
@@ -503,34 +496,27 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem *base)
 	return 0;
 }
 
-static int imx_tve_register(struct imx_tve *tve)
+static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
 {
+	int encoder_type;
 	int ret;
 
-	tve->connector.funcs = &imx_tve_connector_funcs;
-	tve->encoder.funcs = &imx_tve_encoder_funcs;
+	encoder_type = tve->mode == TVE_MODE_VGA ?
+				DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
 
-	tve->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-	tve->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+	ret = imx_drm_encoder_parse_of(drm, &tve->encoder,
+				       tve->dev->of_node);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&tve->encoder, &tve->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(tve->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
+			 encoder_type);
 
 	drm_connector_helper_add(&tve->connector,
 			&imx_tve_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&tve->connector,
-			&tve->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(tve->imx_drm_encoder);
-		dev_err(tve->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
+			   DRM_MODE_CONNECTOR_VGA);
 
 	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
 
@@ -576,9 +562,11 @@ static const int of_get_tve_mode(struct device_node *np)
 	return -EINVAL;
 }
 
-static int imx_tve_probe(struct platform_device *pdev)
+static int imx_tve_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	struct device_node *ddc_node;
 	struct imx_tve *tve;
 	struct resource *res;
@@ -587,11 +575,11 @@ static int imx_tve_probe(struct platform_device *pdev)
 	int irq;
 	int ret;
 
-	tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+	tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
 	if (!tve)
 		return -ENOMEM;
 
-	tve->dev = &pdev->dev;
+	tve->dev = dev;
 	spin_lock_init(&tve->lock);
 
 	ddc_node = of_parse_phandle(np, "ddc", 0);
@@ -602,7 +590,7 @@ static int imx_tve_probe(struct platform_device *pdev)
 
 	tve->mode = of_get_tve_mode(np);
 	if (tve->mode != TVE_MODE_VGA) {
-		dev_err(&pdev->dev, "only VGA mode supported, currently\n");
+		dev_err(dev, "only VGA mode supported, currently\n");
 		return -EINVAL;
 	}
 
@@ -611,7 +599,7 @@ static int imx_tve_probe(struct platform_device *pdev)
 					   &tve->hsync_pin);
 
 		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to get vsync pin\n");
+			dev_err(dev, "failed to get vsync pin\n");
 			return ret;
 		}
 
@@ -619,40 +607,40 @@ static int imx_tve_probe(struct platform_device *pdev)
 					    &tve->vsync_pin);
 
 		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to get vsync pin\n");
+			dev_err(dev, "failed to get vsync pin\n");
 			return ret;
 		}
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
 	tve_regmap_config.lock_arg = tve;
-	tve->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "tve", base,
+	tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,
 						&tve_regmap_config);
 	if (IS_ERR(tve->regmap)) {
-		dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+		dev_err(dev, "failed to init regmap: %ld\n",
 			PTR_ERR(tve->regmap));
 		return PTR_ERR(tve->regmap);
 	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to get irq\n");
+		dev_err(dev, "failed to get irq\n");
 		return irq;
 	}
 
-	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+	ret = devm_request_threaded_irq(dev, irq, NULL,
 					imx_tve_irq_handler, IRQF_ONESHOT,
 					"imx-tve", tve);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+		dev_err(dev, "failed to request irq: %d\n", ret);
 		return ret;
 	}
 
-	tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
+	tve->dac_reg = devm_regulator_get(dev, "dac");
 	if (!IS_ERR(tve->dac_reg)) {
 		regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
 		ret = regulator_enable(tve->dac_reg);
@@ -660,17 +648,17 @@ static int imx_tve_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	tve->clk = devm_clk_get(&pdev->dev, "tve");
+	tve->clk = devm_clk_get(dev, "tve");
 	if (IS_ERR(tve->clk)) {
-		dev_err(&pdev->dev, "failed to get high speed tve clock: %ld\n",
+		dev_err(dev, "failed to get high speed tve clock: %ld\n",
 			PTR_ERR(tve->clk));
 		return PTR_ERR(tve->clk);
 	}
 
 	/* this is the IPU DI clock input selector, can be parented to tve_di */
-	tve->di_sel_clk = devm_clk_get(&pdev->dev, "di_sel");
+	tve->di_sel_clk = devm_clk_get(dev, "di_sel");
 	if (IS_ERR(tve->di_sel_clk)) {
-		dev_err(&pdev->dev, "failed to get ipu di mux clock: %ld\n",
+		dev_err(dev, "failed to get ipu di mux clock: %ld\n",
 			PTR_ERR(tve->di_sel_clk));
 		return PTR_ERR(tve->di_sel_clk);
 	}
@@ -681,42 +669,51 @@ static int imx_tve_probe(struct platform_device *pdev)
 
 	ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to read configuration register: %d\n", ret);
+		dev_err(dev, "failed to read configuration register: %d\n", ret);
 		return ret;
 	}
 	if (val != 0x00100000) {
-		dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n");
+		dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");
 		return -ENODEV;
 	}
 
 	/* disable cable detection for VGA mode */
 	ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0);
 
-	ret = imx_tve_register(tve);
+	ret = imx_tve_register(drm, tve);
 	if (ret)
 		return ret;
 
-	ret = imx_drm_encoder_add_possible_crtcs(tve->imx_drm_encoder, np);
-
-	platform_set_drvdata(pdev, tve);
+	dev_set_drvdata(dev, tve);
 
 	return 0;
 }
 
-static int imx_tve_remove(struct platform_device *pdev)
+static void imx_tve_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_tve *tve = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &tve->connector;
-	struct drm_encoder *encoder = &tve->encoder;
+	struct imx_tve *tve = dev_get_drvdata(dev);
 
-	drm_mode_connector_detach_encoder(connector, encoder);
-
-	imx_drm_remove_connector(tve->imx_drm_connector);
-	imx_drm_remove_encoder(tve->imx_drm_encoder);
+	tve->connector.funcs->destroy(&tve->connector);
+	tve->encoder.funcs->destroy(&tve->encoder);
 
 	if (!IS_ERR(tve->dac_reg))
 		regulator_disable(tve->dac_reg);
+}
+
+static const struct component_ops imx_tve_ops = {
+	.bind	= imx_tve_bind,
+	.unbind	= imx_tve_unbind,
+};
 
+static int imx_tve_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_tve_ops);
+}
+
+static int imx_tve_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &imx_tve_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 4826b5c0249d..c4d14ead5837 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -25,6 +25,8 @@ enum ipuv3_type {
 	IPUV3H,
 };
 
+#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
+
 /*
  * Bitfield of Display Interface signal polarities.
  */
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
index d0e3bc3c53e7..d5de8bb5c803 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
@@ -262,7 +262,7 @@ void ipu_dc_disable_channel(struct ipu_dc *dc)
 
 	/* Wait for DC triple buffer to empty */
 	while ((readl(priv->dc_reg + DC_STAT) & val) != val) {
-		msleep(2);
+		usleep_range(2000, 20000);
 		timeout -= 2;
 		if (timeout <= 0)
 			break;
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
index 948a49b289ef..82a9ebad697c 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
@@ -19,9 +19,6 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
@@ -33,10 +30,7 @@ struct ipu_di {
 	struct clk *clk_di;	/* display input clock */
 	struct clk *clk_ipu;	/* IPU bus clock */
 	struct clk *clk_di_pixel; /* resulting pixel clock */
-	struct clk_hw clk_hw_out;
-	char *clk_name;
 	bool inuse;
-	unsigned long clkflags;
 	struct ipu_soc *ipu;
 };
 
@@ -141,130 +135,6 @@ static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
 	writel(value, di->base + offset);
 }
 
-static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate)
-{
-	u64 tmp = inrate;
-	int div;
-
-	tmp *= 16;
-
-	do_div(tmp, outrate);
-
-	div = tmp;
-
-	if (div < 0x10)
-		div = 0x10;
-
-#ifdef WTF_IS_THIS
-	/*
-	 * Freescale has this in their Kernel. It is neither clear what
-	 * it does nor why it does it
-	 */
-	if (div & 0x10)
-		div &= ~0x7;
-	else {
-		/* Round up divider if it gets us closer to desired pix clk */
-		if ((div & 0xC) == 0xC) {
-			div += 0x10;
-			div &= ~0xF;
-		}
-	}
-#endif
-	return div;
-}
-
-static unsigned long clk_di_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	unsigned long outrate;
-	u32 div = ipu_di_read(di, DI_BS_CLKGEN0);
-
-	if (div < 0x10)
-		div = 0x10;
-
-	outrate = (parent_rate / div) * 16;
-
-	return outrate;
-}
-
-static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	unsigned long outrate;
-	int div;
-	u32 val;
-
-	div = ipu_di_clk_calc_div(*prate, rate);
-
-	outrate = (*prate / div) * 16;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2)
-		outrate = *prate / 2;
-
-	dev_dbg(di->ipu->dev,
-		"%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n",
-			__func__, *prate, div, outrate, rate);
-
-	return outrate;
-}
-
-static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long parent_rate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	int div;
-	u32 clkgen0;
-
-	clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff;
-
-	div = ipu_di_clk_calc_div(parent_rate, rate);
-
-	ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0);
-
-	dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n",
-			__func__, parent_rate, rate, div);
-	return 0;
-}
-
-static u8 clk_di_get_parent(struct clk_hw *hw)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	u32 val;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	return val & DI_GEN_DI_CLK_EXT ? 1 : 0;
-}
-
-static int clk_di_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	u32 val;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	if (index)
-		val |= DI_GEN_DI_CLK_EXT;
-	else
-		val &= ~DI_GEN_DI_CLK_EXT;
-
-	ipu_di_write(di, val, DI_GENERAL);
-
-	return 0;
-}
-
-static struct clk_ops clk_di_ops = {
-	.round_rate = clk_di_round_rate,
-	.set_rate = clk_di_set_rate,
-	.recalc_rate = clk_di_recalc_rate,
-	.set_parent = clk_di_set_parent,
-	.get_parent = clk_di_get_parent,
-};
-
 static void ipu_di_data_wave_config(struct ipu_di *di,
 				     int wave_gen,
 				     int access_size, int component_size)
@@ -528,15 +398,125 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
 		ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
 }
 
+static void ipu_di_config_clock(struct ipu_di *di,
+	const struct ipu_di_signal_cfg *sig)
+{
+	struct clk *clk;
+	unsigned clkgen0;
+	uint32_t val;
+
+	if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
+		/*
+		 * CLKMODE_EXT means we must use the DI clock: this is
+		 * needed for things like LVDS which needs to feed the
+		 * DI and LDB with the same pixel clock.
+		 */
+		clk = di->clk_di;
+
+		if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
+			/*
+			 * CLKMODE_SYNC means that we want the DI to be
+			 * clocked at the same rate as the parent clock.
+			 * This is needed (eg) for LDB which needs to be
+			 * fed with the same pixel clock.  We assume that
+			 * the LDB clock has already been set correctly.
+			 */
+			clkgen0 = 1 << 4;
+		} else {
+			/*
+			 * We can use the divider.  We should really have
+			 * a flag here indicating whether the bridge can
+			 * cope with a fractional divider or not.  For the
+			 * time being, let's go for simplicitly and
+			 * reliability.
+			 */
+			unsigned long in_rate;
+			unsigned div;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	} else {
+		/*
+		 * For other interfaces, we can arbitarily select between
+		 * the DI specific clock and the internal IPU clock.  See
+		 * DI_GENERAL bit 20.  We select the IPU clock if it can
+		 * give us a clock rate within 1% of the requested frequency,
+		 * otherwise we use the DI clock.
+		 */
+		unsigned long rate, clkrate;
+		unsigned div, error;
+
+		clkrate = clk_get_rate(di->clk_ipu);
+		div = (clkrate + sig->pixelclock / 2) / sig->pixelclock;
+		rate = clkrate / div;
+
+		error = rate / (sig->pixelclock / 1000);
+
+		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
+			rate, div, (signed)(error - 1000) / 10, error % 10);
+
+		/* Allow a 1% error */
+		if (error < 1010 && error >= 990) {
+			clk = di->clk_ipu;
+
+			clkgen0 = div << 4;
+		} else {
+			unsigned long in_rate;
+			unsigned div;
+
+			clk = di->clk_di;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	}
+
+	di->clk_di_pixel = clk;
+
+	/* Set the divider */
+	ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
+
+	/*
+	 * Set the high/low periods.  Bits 24:16 give us the falling edge,
+	 * and bits 8:0 give the rising edge.  LSB is fraction, and is
+	 * based on the divider above.  We want a 50% duty cycle, so set
+	 * the falling edge to be half the divider.
+	 */
+	ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
+
+	/* Finally select the input clock */
+	val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
+	if (clk == di->clk_di)
+		val |= DI_GEN_DI_CLK_EXT;
+	ipu_di_write(di, val, DI_GENERAL);
+
+	dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+		sig->pixelclock,
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		clk == di->clk_di ? "DI" : "IPU",
+		clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
+}
+
 int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 {
 	u32 reg;
 	u32 di_gen, vsync_cnt;
 	u32 div;
 	u32 h_total, v_total;
-	int ret;
-	unsigned long round;
-	struct clk *parent;
 
 	dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
 		di->id, sig->width, sig->height);
@@ -544,33 +524,20 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 	if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
 		return -EINVAL;
 
-	if (sig->clkflags & IPU_DI_CLKMODE_EXT)
-		parent = di->clk_di;
-	else
-		parent = di->clk_ipu;
-
-	ret = clk_set_parent(di->clk_di_pixel, parent);
-	if (ret) {
-		dev_err(di->ipu->dev,
-			"setting pixel clock to parent %s failed with %d\n",
-				__clk_get_name(parent), ret);
-		return ret;
-	}
-
-	if (sig->clkflags & IPU_DI_CLKMODE_SYNC)
-		round = clk_get_rate(parent);
-	else
-		round = clk_round_rate(di->clk_di_pixel, sig->pixelclock);
-
-	ret = clk_set_rate(di->clk_di_pixel, round);
-
 	h_total = sig->width + sig->h_sync_width + sig->h_start_width +
 		sig->h_end_width;
 	v_total = sig->height + sig->v_sync_width + sig->v_start_width +
 		sig->v_end_width;
 
+	dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		sig->pixelclock);
+
 	mutex_lock(&di_mutex);
 
+	ipu_di_config_clock(di, sig);
+
 	div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
 	div = div / 16;		/* Now divider is integer portion */
 
@@ -654,7 +621,11 @@ EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
 
 int ipu_di_enable(struct ipu_di *di)
 {
-	int ret = clk_prepare_enable(di->clk_di_pixel);
+	int ret;
+
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
+	ret = clk_prepare_enable(di->clk_di_pixel);
 	if (ret)
 		return ret;
 
@@ -666,6 +637,8 @@ EXPORT_SYMBOL_GPL(ipu_di_enable);
 
 int ipu_di_disable(struct ipu_di *di)
 {
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
 	ipu_module_disable(di->ipu, di->module);
 
 	clk_disable_unprepare(di->clk_di_pixel);
@@ -721,13 +694,6 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
 		u32 module, struct clk *clk_ipu)
 {
 	struct ipu_di *di;
-	int ret;
-	const char *di_parent[2];
-	struct clk_init_data init = {
-		.ops = &clk_di_ops,
-		.num_parents = 2,
-		.flags = 0,
-	};
 
 	if (id > 1)
 		return -ENODEV;
@@ -749,45 +715,16 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
 	if (!di->base)
 		return -ENOMEM;
 
-	di_parent[0] = __clk_get_name(di->clk_ipu);
-	di_parent[1] = __clk_get_name(di->clk_di);
-
 	ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
 
-	init.parent_names = (const char **)&di_parent;
-	di->clk_name = kasprintf(GFP_KERNEL, "%s_di%d_pixel",
-			dev_name(dev), id);
-	if (!di->clk_name)
-		return -ENOMEM;
-
-	init.name = di->clk_name;
-
-	di->clk_hw_out.init = &init;
-	di->clk_di_pixel = clk_register(dev, &di->clk_hw_out);
-
-	if (IS_ERR(di->clk_di_pixel)) {
-		ret = PTR_ERR(di->clk_di_pixel);
-		goto failed_clk_register;
-	}
-
 	dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
 			id, base, di->base);
 	di->inuse = false;
 	di->ipu = ipu;
 
 	return 0;
-
-failed_clk_register:
-
-	kfree(di->clk_name);
-
-	return ret;
 }
 
 void ipu_di_exit(struct ipu_soc *ipu, int id)
 {
-	struct ipu_di *di = ipu->di_priv[id];
-
-	clk_unregister(di->clk_di_pixel);
-	kfree(di->clk_name);
 }
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
index 98070dd8c920..45213017fa4b 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
@@ -161,9 +161,6 @@ static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
 			"dmfc: using %d slots starting from segment %d for IPU channel %d\n",
 			slots, segment, dmfc->data->ipu_channel);
 
-	if (!dmfc)
-		return -EINVAL;
-
 	switch (slots) {
 	case 1:
 		field = DMFC_FIFO_SIZE_64;
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 22be104fbda9..e646017c32ac 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/export.h>
 #include <linux/device.h>
@@ -284,6 +285,7 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
 		ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
 			IPU_DI_CLKMODE_EXT;
 		break;
+	case DRM_MODE_ENCODER_TMDS:
 	case DRM_MODE_ENCODER_NONE:
 		ipu_crtc->di_clkflags = 0;
 		break;
@@ -334,7 +336,7 @@ err_out:
 }
 
 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
-		struct ipu_client_platformdata *pdata)
+	struct ipu_client_platformdata *pdata, struct drm_device *drm)
 {
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 	int dp = -EINVAL;
@@ -348,9 +350,9 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 		return ret;
 	}
 
-	ret = imx_drm_add_crtc(&ipu_crtc->base,
+	ret = imx_drm_add_crtc(drm, &ipu_crtc->base,
 			&ipu_crtc->imx_crtc,
-			&ipu_crtc_helper_funcs, THIS_MODULE,
+			&ipu_crtc_helper_funcs,
 			ipu_crtc->dev->parent->of_node, pdata->di);
 	if (ret) {
 		dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
@@ -399,43 +401,61 @@ err_put_resources:
 	return ret;
 }
 
-static int ipu_drm_probe(struct platform_device *pdev)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
-	struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
+	struct ipu_client_platformdata *pdata = dev->platform_data;
+	struct drm_device *drm = data;
 	struct ipu_crtc *ipu_crtc;
 	int ret;
 
-	if (!pdata)
-		return -EINVAL;
-
-	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-	if (ret)
-		return ret;
-
-	ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL);
+	ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
 	if (!ipu_crtc)
 		return -ENOMEM;
 
-	ipu_crtc->dev = &pdev->dev;
+	ipu_crtc->dev = dev;
 
-	ret = ipu_crtc_init(ipu_crtc, pdata);
+	ret = ipu_crtc_init(ipu_crtc, pdata, drm);
 	if (ret)
 		return ret;
 
-	platform_set_drvdata(pdev, ipu_crtc);
+	dev_set_drvdata(dev, ipu_crtc);
 
 	return 0;
 }
 
-static int ipu_drm_remove(struct platform_device *pdev)
+static void ipu_drm_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
+	struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
 
 	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 
 	ipu_plane_put_resources(ipu_crtc->plane[0]);
 	ipu_put_resources(ipu_crtc);
+}
+
+static const struct component_ops ipu_crtc_ops = {
+	.bind = ipu_drm_bind,
+	.unbind = ipu_drm_unbind,
+};
+
+static int ipu_drm_probe(struct platform_device *pdev)
+{
+	int ret;
 
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret)
+		return ret;
+
+	return component_add(&pdev->dev, &ipu_crtc_ops);
+}
+
+static int ipu_drm_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &ipu_crtc_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
index 34b642a12f8b..b0c9b6ce4854 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -72,8 +72,8 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
 		return -EFAULT;
 	}
 
-	dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d",
-		cma_obj->paddr, x, y);
+	dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
+		&cma_obj->paddr, x, y);
 
 	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
 	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index 351d61dede00..c60b6c645f42 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -18,10 +18,12 @@
  * MA 02110-1301, USA.
  */
 
+#include <linux/component.h>
 #include <linux/module.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
 
@@ -32,15 +34,14 @@
 
 struct imx_parallel_display {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 	struct device *dev;
 	void *edid;
 	int edid_len;
 	u32 interface_pix_fmt;
 	int mode_valid;
 	struct drm_display_mode mode;
+	struct drm_panel *panel;
 };
 
 static enum drm_connector_status imx_pd_connector_detect(
@@ -49,17 +50,19 @@ static enum drm_connector_status imx_pd_connector_detect(
 	return connector_status_connected;
 }
 
-static void imx_pd_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
 	struct device_node *np = imxpd->dev->of_node;
 	int num_modes = 0;
 
+	if (imxpd->panel && imxpd->panel->funcs &&
+	    imxpd->panel->funcs->get_modes) {
+		num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
+		if (num_modes > 0)
+			return num_modes;
+	}
+
 	if (imxpd->edid) {
 		drm_mode_connector_update_edid_property(connector, imxpd->edid);
 		num_modes = drm_add_edid_modes(connector, imxpd->edid);
@@ -67,6 +70,8 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 
 	if (imxpd->mode_valid) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		drm_mode_probed_add(connector, mode);
@@ -75,6 +80,8 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 
 	if (np) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE);
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
@@ -85,12 +92,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 	return num_modes;
 }
 
-static int imx_pd_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-	return 0;
-}
-
 static struct drm_encoder *imx_pd_connector_best_encoder(
 		struct drm_connector *connector)
 {
@@ -101,6 +102,12 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
 
 static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+
+	if (mode != DRM_MODE_DPMS_ON)
+		drm_panel_disable(imxpd->panel);
+	else
+		drm_panel_enable(imxpd->panel);
 }
 
 static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -114,8 +121,7 @@ static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
 {
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
 
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-			imxpd->interface_pix_fmt);
+	imx_drm_panel_format(encoder, imxpd->interface_pix_fmt);
 }
 
 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -132,26 +138,21 @@ static void imx_pd_encoder_disable(struct drm_encoder *encoder)
 {
 }
 
-static void imx_pd_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_pd_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_pd_connector_detect,
-	.destroy = imx_pd_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
 	.get_modes = imx_pd_connector_get_modes,
 	.best_encoder = imx_pd_connector_best_encoder,
-	.mode_valid = imx_pd_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_pd_encoder_funcs = {
-	.destroy = imx_pd_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
@@ -163,51 +164,46 @@ static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
 	.disable = imx_pd_encoder_disable,
 };
 
-static int imx_pd_register(struct imx_parallel_display *imxpd)
+static int imx_pd_register(struct drm_device *drm,
+	struct imx_parallel_display *imxpd)
 {
 	int ret;
 
-	drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
-
-	imxpd->connector.funcs = &imx_pd_connector_funcs;
-	imxpd->encoder.funcs = &imx_pd_encoder_funcs;
-
-	imxpd->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-	imxpd->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+	ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder,
+				       imxpd->dev->of_node);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(imxpd->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs,
+			 DRM_MODE_ENCODER_NONE);
 
 	drm_connector_helper_add(&imxpd->connector,
 			&imx_pd_connector_helper_funcs);
+	drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
+			   DRM_MODE_CONNECTOR_VGA);
 
-	ret = imx_drm_add_connector(&imxpd->connector,
-			&imxpd->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(imxpd->imx_drm_encoder);
-		dev_err(imxpd->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	if (imxpd->panel)
+		drm_panel_attach(imxpd->panel, &imxpd->connector);
+
+	drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
 
 	imxpd->connector.encoder = &imxpd->encoder;
 
 	return 0;
 }
 
-static int imx_pd_probe(struct platform_device *pdev)
+static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
+	struct device_node *panel_node;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
 	const char *fmt;
 
-	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+	imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
 	if (!imxpd)
 		return -ENOMEM;
 
@@ -225,30 +221,43 @@ static int imx_pd_probe(struct platform_device *pdev)
 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
 	}
 
-	imxpd->dev = &pdev->dev;
+	panel_node = of_parse_phandle(np, "fsl,panel", 0);
+	if (panel_node)
+		imxpd->panel = of_drm_find_panel(panel_node);
 
-	ret = imx_pd_register(imxpd);
+	imxpd->dev = dev;
+
+	ret = imx_pd_register(drm, imxpd);
 	if (ret)
 		return ret;
 
-	ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np);
-
-	platform_set_drvdata(pdev, imxpd);
+	dev_set_drvdata(dev, imxpd);
 
 	return 0;
 }
 
-static int imx_pd_remove(struct platform_device *pdev)
+static void imx_pd_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &imxpd->connector;
-	struct drm_encoder *encoder = &imxpd->encoder;
+	struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
 
-	drm_mode_connector_detach_encoder(connector, encoder);
+	imxpd->encoder.funcs->destroy(&imxpd->encoder);
+	imxpd->connector.funcs->destroy(&imxpd->connector);
+}
 
-	imx_drm_remove_connector(imxpd->imx_drm_connector);
-	imx_drm_remove_encoder(imxpd->imx_drm_encoder);
+static const struct component_ops imx_pd_ops = {
+	.bind	= imx_pd_bind,
+	.unbind	= imx_pd_unbind,
+};
 
+static int imx_pd_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_pd_ops);
+}
+
+static int imx_pd_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &imx_pd_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c
index a92e21f7d55b..171d80c1b020 100644
--- a/drivers/staging/line6/audio.c
+++ b/drivers/staging/line6/audio.c
@@ -24,8 +24,9 @@ int line6_init_audio(struct usb_line6 *line6)
 	struct snd_card *card;
 	int err;
 
-	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			      THIS_MODULE, 0, &card);
+	err = snd_card_new(line6->ifcdev,
+			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			   THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index 7a6d85ebb29b..e7a9d8dae499 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -217,7 +217,7 @@ static int line6_send_raw_message_async_part(struct message *msg,
 	Setup and start timer.
 */
 void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-		       void (*function) (unsigned long), unsigned long data)
+		       void (*function)(unsigned long), unsigned long data)
 {
 	setup_timer(timer, function, data);
 	timer->expires = jiffies + msecs * HZ / 1000;
diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h
index 34ae95e7e512..16e3fc2f1f15 100644
--- a/drivers/staging/line6/driver.h
+++ b/drivers/staging/line6/driver.h
@@ -204,7 +204,7 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
 extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count);
 extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-			      void (*function) (unsigned long),
+			      void (*function)(unsigned long),
 			      unsigned long data);
 extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
 				    u8 value);
diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c
index 3f6d78c585fb..c61cd0515baf 100644
--- a/drivers/staging/line6/midi.c
+++ b/drivers/staging/line6/midi.c
@@ -307,8 +307,6 @@ int line6_init_midi(struct usb_line6 *line6)
 	if (err < 0)
 		return err;
 
-	snd_card_set_dev(line6->card, line6->ifcdev);
-
 	err = snd_line6_new_midi(line6midi);
 	if (err < 0)
 		return err;
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index df8331bce175..661080b3c39d 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -501,8 +501,6 @@ int line6_init_pcm(struct usb_line6 *line6,
 	if (err < 0)
 		return err;
 
-	snd_card_set_dev(line6->card, line6->ifcdev);
-
 	err = snd_line6_new_pcm(line6pcm);
 	if (err < 0)
 		return err;
diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h
index 90cadddec56e..eda04562d576 100644
--- a/drivers/staging/line6/usbdefs.h
+++ b/drivers/staging/line6/usbdefs.h
@@ -91,9 +91,9 @@ enum {
 	LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE |
 			      LINE6_BIT_PODXTPRO,
 	LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
-	LINE6_BITS_PODHDALL = 	LINE6_BIT_PODHD300 |
-				LINE6_BIT_PODHD400 |
-				LINE6_BIT_PODHD500,
+	LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 |
+			      LINE6_BIT_PODHD400 |
+			      LINE6_BIT_PODHD500,
 	LINE6_BITS_BASSPODXTALL	= LINE6_BIT_BASSPODXT |
 				  LINE6_BIT_BASSPODXTLIVE |
 				  LINE6_BIT_BASSPODXTPRO
diff --git a/drivers/staging/lustre/include/linux/libcfs/curproc.h b/drivers/staging/lustre/include/linux/libcfs/curproc.h
index 507d16b9213c..8fd47c98fd33 100644
--- a/drivers/staging/lustre/include/linux/libcfs/curproc.h
+++ b/drivers/staging/lustre/include/linux/libcfs/curproc.h
@@ -44,13 +44,6 @@
 #define __LIBCFS_CURPROC_H__
 
 /*
- * Portable API to access common characteristics of "current" UNIX process.
- *
- * Implemented in portals/include/libcfs/<os>/
- */
-int    cfs_curproc_groups_nr(void);
-
-/*
  * Plus, platform-specific constant
  *
  * CFS_CURPROC_COMM_MAX,
@@ -91,8 +84,6 @@ void cfs_cap_raise(cfs_cap_t cap);
 void cfs_cap_lower(cfs_cap_t cap);
 int cfs_cap_raised(cfs_cap_t cap);
 cfs_cap_t cfs_curproc_cap_pack(void);
-void cfs_curproc_cap_unpack(cfs_cap_t cap);
-int cfs_capable(cfs_cap_t cap);
 
 /* __LIBCFS_CURPROC_H__ */
 #endif
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
index 9d5ee1a69c0c..e5d5db255622 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
@@ -65,8 +65,6 @@
 
 #include <linux/hash.h>
 
-#define cfs_hash_long(val, bits)    hash_long(val, bits)
-
 /** disable debug */
 #define CFS_HASH_DEBUG_NONE	 0
 /** record hash depth and output to console when it's too deep,
diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
index 3ac2bb5fd2db..856fcfaafafa 100644
--- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
+++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
@@ -628,7 +628,7 @@ void lnet_ni_free(lnet_ni_t *ni);
 static inline int
 lnet_nid2peerhash(lnet_nid_t nid)
 {
-	return cfs_hash_long(nid, LNET_PEER_HASH_BITS);
+	return hash_long(nid, LNET_PEER_HASH_BITS);
 }
 
 static inline struct list_head *
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index 644a0000130a..0727998a7667 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -41,7 +41,7 @@
 #include "o2iblnd.h"
 #include <asm/div64.h>
 
-lnd_t the_o2iblnd = {
+static lnd_t the_o2iblnd = {
 	.lnd_type       = O2IBLND,
 	.lnd_startup    = kiblnd_startup,
 	.lnd_shutdown   = kiblnd_shutdown,
@@ -53,8 +53,8 @@ lnd_t the_o2iblnd = {
 
 kib_data_t	      kiblnd_data;
 
-__u32
-kiblnd_cksum (void *ptr, int nob)
+static __u32
+kiblnd_cksum(void *ptr, int nob)
 {
 	char  *c  = ptr;
 	__u32  sum = 0;
@@ -429,8 +429,8 @@ kiblnd_unlink_peer_locked (kib_peer_t *peer)
 	kiblnd_peer_decref(peer);
 }
 
-int
-kiblnd_get_peer_info (lnet_ni_t *ni, int index,
+static int
+kiblnd_get_peer_info(lnet_ni_t *ni, int index,
 		      lnet_nid_t *nidp, int *count)
 {
 	kib_peer_t	    *peer;
@@ -468,8 +468,8 @@ kiblnd_get_peer_info (lnet_ni_t *ni, int index,
 	return -ENOENT;
 }
 
-void
-kiblnd_del_peer_locked (kib_peer_t *peer)
+static void
+kiblnd_del_peer_locked(kib_peer_t *peer)
 {
 	struct list_head	   *ctmp;
 	struct list_head	   *cnxt;
@@ -489,8 +489,8 @@ kiblnd_del_peer_locked (kib_peer_t *peer)
 	 * last ref on it. */
 }
 
-int
-kiblnd_del_peer (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
 {
 	LIST_HEAD	 (zombies);
 	struct list_head	    *ptmp;
@@ -543,8 +543,8 @@ kiblnd_del_peer (lnet_ni_t *ni, lnet_nid_t nid)
 	return rc;
 }
 
-kib_conn_t *
-kiblnd_get_conn_by_idx (lnet_ni_t *ni, int index)
+static kib_conn_t *
+kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
 {
 	kib_peer_t	    *peer;
 	struct list_head	    *ptmp;
@@ -584,16 +584,16 @@ kiblnd_get_conn_by_idx (lnet_ni_t *ni, int index)
 	return NULL;
 }
 
-void
-kiblnd_debug_rx (kib_rx_t *rx)
+static void
+kiblnd_debug_rx(kib_rx_t *rx)
 {
 	CDEBUG(D_CONSOLE, "      %p status %d msg_type %x cred %d\n",
 	       rx, rx->rx_status, rx->rx_msg->ibm_type,
 	       rx->rx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_tx (kib_tx_t *tx)
+static void
+kiblnd_debug_tx(kib_tx_t *tx)
 {
 	CDEBUG(D_CONSOLE, "      %p snd %d q %d w %d rc %d dl %lx "
 	       "cookie "LPX64" msg %s%s type %x cred %d\n",
@@ -604,8 +604,8 @@ kiblnd_debug_tx (kib_tx_t *tx)
 	       tx->tx_msg->ibm_type, tx->tx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_conn (kib_conn_t *conn)
+static void
+kiblnd_debug_conn(kib_conn_t *conn)
 {
 	struct list_head	*tmp;
 	int		i;
@@ -1039,8 +1039,8 @@ kiblnd_close_stale_conns_locked (kib_peer_t *peer,
 	return count;
 }
 
-int
-kiblnd_close_matching_conns (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
 {
 	kib_peer_t	     *peer;
 	struct list_head	     *ptmp;
@@ -1440,7 +1440,7 @@ kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd)
 	return mr;
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
 {
 	LASSERT (pool->fpo_map_count == 0);
@@ -1454,7 +1454,7 @@ kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
 	LIBCFS_FREE(pool, sizeof(kib_fmr_pool_t));
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool_list(struct list_head *head)
 {
 	kib_fmr_pool_t *pool;
@@ -1480,7 +1480,7 @@ static int kiblnd_fmr_flush_trigger(int ncpts)
 	return max(IBLND_FMR_POOL_FLUSH, size);
 }
 
-int
+static int
 kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_fmr_pool_t **pp_fpo)
 {
 	/* FMR pool for RDMA */
@@ -1719,7 +1719,7 @@ kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size)
 	pool->po_size     = size;
 }
 
-void
+static void
 kiblnd_destroy_pool_list(struct list_head *head)
 {
 	kib_pool_t *pool;
@@ -2192,7 +2192,7 @@ kiblnd_tx_init(kib_pool_t *pool, struct list_head *node)
 	tx->tx_cookie = tps->tps_next_tx_cookie ++;
 }
 
-void
+static void
 kiblnd_net_fini_pools(kib_net_t *net)
 {
 	int	i;
@@ -2234,7 +2234,7 @@ kiblnd_net_fini_pools(kib_net_t *net)
 	}
 }
 
-int
+static int
 kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
 {
 	unsigned long	flags;
@@ -2408,7 +2408,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev)
 	return -EINVAL;
 }
 
-void
+static void
 kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
 {
 	int     i;
@@ -2442,7 +2442,7 @@ kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
 	LIBCFS_FREE(hdev, sizeof(*hdev));
 }
 
-int
+static int
 kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 {
 	struct ib_mr *mr;
@@ -2746,7 +2746,7 @@ kiblnd_destroy_dev (kib_dev_t *dev)
 	LIBCFS_FREE(dev, sizeof(*dev));
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_create_dev(char *ifname)
 {
 	struct net_device *netdev;
@@ -2800,7 +2800,7 @@ kiblnd_create_dev(char *ifname)
 	return dev;
 }
 
-void
+static void
 kiblnd_base_shutdown(void)
 {
 	struct kib_sched_info	*sched;
@@ -2940,7 +2940,7 @@ out:
 	return;
 }
 
-int
+static int
 kiblnd_base_startup(void)
 {
 	struct kib_sched_info	*sched;
@@ -3030,7 +3030,7 @@ kiblnd_base_startup(void)
 	return -ENETDOWN;
 }
 
-int
+static int
 kiblnd_start_schedulers(struct kib_sched_info *sched)
 {
 	int	rc = 0;
@@ -3071,7 +3071,7 @@ kiblnd_start_schedulers(struct kib_sched_info *sched)
 	return rc;
 }
 
-int
+static int
 kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
 {
 	int	cpt;
@@ -3097,7 +3097,7 @@ kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
 	return 0;
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_dev_search(char *ifname)
 {
 	kib_dev_t	*alias = NULL;
@@ -3226,13 +3226,13 @@ failed:
 	return -ENETDOWN;
 }
 
-void __exit
+static void __exit
 kiblnd_module_fini (void)
 {
 	lnet_unregister_lnd(&the_o2iblnd);
 }
 
-int __init
+static int __init
 kiblnd_module_init (void)
 {
 	int    rc;
diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c
index c562ff3e9283..a18fee56147b 100644
--- a/drivers/staging/lustre/lnet/lnet/api-ni.c
+++ b/drivers/staging/lustre/lnet/lnet/api-ni.c
@@ -770,7 +770,7 @@ lnet_nid_cpt_hash(lnet_nid_t nid, unsigned int number)
 	if (number == 1)
 		return 0;
 
-	val = cfs_hash_long(key, LNET_CPT_BITS);
+	val = hash_long(key, LNET_CPT_BITS);
 	/* NB: LNET_CP_NUMBER doesn't have to be PO2 */
 	if (val < number)
 		return val;
diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c
index 6fffd5e96f9c..920df69960a5 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c
@@ -366,7 +366,7 @@ lnet_mt_match_head(struct lnet_match_table *mtable,
 		unsigned long hash = mbits + id.nid + id.pid;
 
 		LASSERT(lnet_ptl_is_unique(ptl));
-		hash = cfs_hash_long(hash, LNET_MT_HASH_BITS);
+		hash = hash_long(hash, LNET_MT_HASH_BITS);
 		return &mtable->mt_mhash[hash];
 	}
 }
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index 4d692dcd96cf..76e1b68b38ed 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -2392,7 +2392,11 @@ struct cl_io {
 	/**
 	 * file is released, restore has to to be triggered by vvp layer
 	 */
-			     ci_restore_needed:1;
+			     ci_restore_needed:1,
+	/**
+	 * O_NOATIME
+	 */
+			     ci_noatime:1;
 	/**
 	 * Number of pages owned by this IO. For invariant checking.
 	 */
diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h
index 27316f7b7a70..de8f82ccb94d 100644
--- a/drivers/staging/lustre/lustre/include/lclient.h
+++ b/drivers/staging/lustre/lustre/include/lclient.h
@@ -118,7 +118,7 @@ struct ccc_io {
 };
 
 /**
- * True, if \a io is a normal io, False for other (sendfile, splice*).
+ * True, if \a io is a normal io, False for splice_{read,write}.
  * must be impementated in arch specific code.
  */
 int cl_is_normalio(const struct lu_env *env, const struct cl_io *io);
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index 5da31c54924a..5f5b0ba9ea94 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -91,8 +91,8 @@
 #ifndef _LUSTRE_IDL_H_
 #define _LUSTRE_IDL_H_
 
-#if !defined(LASSERT) && !defined(LPU64)
-#include <linux/libcfs/libcfs.h> /* for LASSERT, LPUX64, etc */
+#if !defined(LPU64)
+#include <linux/libcfs/libcfs.h> /* for LPUX64, etc */
 #endif
 
 /* Defn's shared with user-space. */
@@ -232,7 +232,6 @@ static inline unsigned fld_range_is_any(const struct lu_seq_range *range)
 static inline void fld_range_set_type(struct lu_seq_range *range,
 				      unsigned flags)
 {
-	LASSERT(!(flags & ~LU_SEQ_RANGE_MASK));
 	range->lsr_flags |= flags;
 }
 
@@ -615,7 +614,6 @@ static inline obd_id fid_idif_id(obd_seq seq, __u32 oid, __u32 ver)
 /* extract ost index from IDIF FID */
 static inline __u32 fid_idif_ost_idx(const struct lu_fid *fid)
 {
-	LASSERT(fid_is_idif(fid));
 	return (fid_seq(fid) >> 16) & 0xffff;
 }
 
@@ -833,11 +831,6 @@ static inline void lu_igif_build(struct lu_fid *fid, __u32 ino, __u32 gen)
  */
 static inline void fid_cpu_to_le(struct lu_fid *dst, const struct lu_fid *src)
 {
-	/* check that all fields are converted */
-	CLASSERT(sizeof(*src) ==
-		 sizeof(fid_seq(src)) +
-		 sizeof(fid_oid(src)) +
-		 sizeof(fid_ver(src)));
 	dst->f_seq = cpu_to_le64(fid_seq(src));
 	dst->f_oid = cpu_to_le32(fid_oid(src));
 	dst->f_ver = cpu_to_le32(fid_ver(src));
@@ -845,11 +838,6 @@ static inline void fid_cpu_to_le(struct lu_fid *dst, const struct lu_fid *src)
 
 static inline void fid_le_to_cpu(struct lu_fid *dst, const struct lu_fid *src)
 {
-	/* check that all fields are converted */
-	CLASSERT(sizeof(*src) ==
-		 sizeof(fid_seq(src)) +
-		 sizeof(fid_oid(src)) +
-		 sizeof(fid_ver(src)));
 	dst->f_seq = le64_to_cpu(fid_seq(src));
 	dst->f_oid = le32_to_cpu(fid_oid(src));
 	dst->f_ver = le32_to_cpu(fid_ver(src));
@@ -857,11 +845,6 @@ static inline void fid_le_to_cpu(struct lu_fid *dst, const struct lu_fid *src)
 
 static inline void fid_cpu_to_be(struct lu_fid *dst, const struct lu_fid *src)
 {
-	/* check that all fields are converted */
-	CLASSERT(sizeof(*src) ==
-		 sizeof(fid_seq(src)) +
-		 sizeof(fid_oid(src)) +
-		 sizeof(fid_ver(src)));
 	dst->f_seq = cpu_to_be64(fid_seq(src));
 	dst->f_oid = cpu_to_be32(fid_oid(src));
 	dst->f_ver = cpu_to_be32(fid_ver(src));
@@ -869,11 +852,6 @@ static inline void fid_cpu_to_be(struct lu_fid *dst, const struct lu_fid *src)
 
 static inline void fid_be_to_cpu(struct lu_fid *dst, const struct lu_fid *src)
 {
-	/* check that all fields are converted */
-	CLASSERT(sizeof(*src) ==
-		 sizeof(fid_seq(src)) +
-		 sizeof(fid_oid(src)) +
-		 sizeof(fid_ver(src)));
 	dst->f_seq = be64_to_cpu(fid_seq(src));
 	dst->f_oid = be32_to_cpu(fid_oid(src));
 	dst->f_ver = be32_to_cpu(fid_ver(src));
@@ -897,11 +875,6 @@ extern void lustre_swab_lu_seq_range(struct lu_seq_range *range);
 
 static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1)
 {
-	/* Check that there is no alignment padding. */
-	CLASSERT(sizeof(*f0) ==
-		 sizeof(f0->f_seq) +
-		 sizeof(f0->f_oid) +
-		 sizeof(f0->f_ver));
 	return memcmp(f0, f1, sizeof(*f0)) == 0;
 }
 
@@ -1331,6 +1304,9 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 #define OBD_CONNECT_LIGHTWEIGHT 0x1000000000000ULL/* lightweight connection */
 #define OBD_CONNECT_SHORTIO     0x2000000000000ULL/* short io */
 #define OBD_CONNECT_PINGLESS	0x4000000000000ULL/* pings not required */
+#define OBD_CONNECT_FLOCK_DEAD	0x8000000000000ULL/* flock deadlock detection */
+#define OBD_CONNECT_DISP_STRIPE 0x10000000000000ULL/*create stripe disposition*/
+
 /* XXX README XXX:
  * Please DO NOT add flag values here before first ensuring that this same
  * flag value is not in use on some other branch.  Please clear any such
@@ -1368,7 +1344,10 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 				OBD_CONNECT_EINPROGRESS | \
 				OBD_CONNECT_LIGHTWEIGHT | OBD_CONNECT_UMASK | \
 				OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
-				OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE)
+				OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
+				OBD_CONNECT_FLOCK_DEAD | \
+				OBD_CONNECT_DISP_STRIPE)
+
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
 				OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
 				OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \
@@ -1771,7 +1750,6 @@ static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic)
 			  OBD_MD_FLGID   | OBD_MD_FLFLAGS | OBD_MD_FLNLINK | \
 			  OBD_MD_FLGENER | OBD_MD_FLRDEV  | OBD_MD_FLGROUP)
 
-#define OBD_MD_FLXATTRLOCKED OBD_MD_FLGETATTRLOCK
 #define OBD_MD_FLXATTRALL (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS)
 
 /* don't forget obdo_fid which is way down at the bottom so it can
@@ -2134,19 +2112,32 @@ extern void lustre_swab_generic_32s (__u32 *val);
 #define DISP_LOOKUP_POS      0x00000008
 #define DISP_OPEN_CREATE     0x00000010
 #define DISP_OPEN_OPEN       0x00000020
-#define DISP_ENQ_COMPLETE    0x00400000
+#define DISP_ENQ_COMPLETE    0x00400000		/* obsolete and unused */
 #define DISP_ENQ_OPEN_REF    0x00800000
 #define DISP_ENQ_CREATE_REF  0x01000000
 #define DISP_OPEN_LOCK       0x02000000
 #define DISP_OPEN_LEASE      0x04000000
+#define DISP_OPEN_STRIPE     0x08000000
 
 /* INODE LOCK PARTS */
-#define MDS_INODELOCK_LOOKUP 0x000001       /* dentry, mode, owner, group */
-#define MDS_INODELOCK_UPDATE 0x000002       /* size, links, timestamps */
-#define MDS_INODELOCK_OPEN   0x000004       /* For opened files */
-#define MDS_INODELOCK_LAYOUT 0x000008       /* for layout */
-#define MDS_INODELOCK_PERM   0x000010       /* for permission */
-#define MDS_INODELOCK_XATTR  0x000020       /* extended attributes */
+#define MDS_INODELOCK_LOOKUP 0x000001	/* For namespace, dentry etc, and also
+					 * was used to protect permission (mode,
+					 * owner, group etc) before 2.4. */
+#define MDS_INODELOCK_UPDATE 0x000002	/* size, links, timestamps */
+#define MDS_INODELOCK_OPEN   0x000004	/* For opened files */
+#define MDS_INODELOCK_LAYOUT 0x000008	/* for layout */
+
+/* The PERM bit is added int 2.4, and it is used to protect permission(mode,
+ * owner, group, acl etc), so to separate the permission from LOOKUP lock.
+ * Because for remote directories(in DNE), these locks will be granted by
+ * different MDTs(different ldlm namespace).
+ *
+ * For local directory, MDT will always grant UPDATE_LOCK|PERM_LOCK together.
+ * For Remote directory, the master MDT, where the remote directory is, will
+ * grant UPDATE_LOCK|PERM_LOCK, and the remote MDT, where the name entry is,
+ * will grant LOOKUP_LOCK. */
+#define MDS_INODELOCK_PERM   0x000010
+#define MDS_INODELOCK_XATTR  0x000020	/* extended attributes */
 
 #define MDS_INODELOCK_MAXSHIFT 5
 /* This FULL lock is useful to take on unlink sort of operations */
@@ -3328,9 +3319,10 @@ struct obdo {
 #define o_grant_used o_data_version
 
 static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd,
-					struct obdo *wobdo, struct obdo *lobdo)
+					struct obdo *wobdo,
+					const struct obdo *lobdo)
 {
-	memcpy(wobdo, lobdo, sizeof(*lobdo));
+	*wobdo = *lobdo;
 	wobdo->o_flags &= ~OBD_FL_LOCAL_MASK;
 	if (ocd == NULL)
 		return;
@@ -3345,16 +3337,15 @@ static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd,
 }
 
 static inline void lustre_get_wire_obdo(struct obd_connect_data *ocd,
-					struct obdo *lobdo, struct obdo *wobdo)
+					struct obdo *lobdo,
+					const struct obdo *wobdo)
 {
 	obd_flag local_flags = 0;
 
 	if (lobdo->o_valid & OBD_MD_FLFLAGS)
 		 local_flags = lobdo->o_flags & OBD_FL_LOCAL_MASK;
 
-	LASSERT(!(wobdo->o_flags & OBD_FL_LOCAL_MASK));
-
-	memcpy(lobdo, wobdo, sizeof(*lobdo));
+	*lobdo = *wobdo;
 	if (local_flags != 0) {
 		lobdo->o_valid |= OBD_MD_FLFLAGS;
 		lobdo->o_flags &= ~OBD_FL_LOCAL_MASK;
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
index 7893d83e131f..336360580910 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
@@ -265,13 +265,11 @@ struct ost_id {
 
 #define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */
 
-/* Hopefully O_LOV_DELAY_CREATE does not conflict with standard O_xxx flags.
- * Previously it was defined as 0100000000 and conflicts with FMODE_NONOTIFY
- * which was added since kernel 2.6.36, so we redefine it as 020000000.
- * To be compatible with old version's statically linked binary, finally we
- * define it as (020000000 | 0100000000).
- * */
-#define O_LOV_DELAY_CREATE      0120000000
+/* Define O_LOV_DELAY_CREATE to be a mask that is not useful for regular
+ * files, but are unlikely to be used in practice and are not harmful if
+ * used incorrectly.  O_NOCTTY and FASYNC are only meaningful for character
+ * devices and are safe for use on new files (See LU-812, LU-4209). */
+#define O_LOV_DELAY_CREATE	(O_NOCTTY | FASYNC)
 
 #define LL_FILE_IGNORE_LOCK     0x00000001
 #define LL_FILE_GROUP_LOCKED    0x00000002
@@ -1159,12 +1157,6 @@ struct hsm_progress {
 	__u32			padding;
 };
 
-/**
- * Use by copytool during any hsm request they handled.
- * This structure is initialized by llapi_hsm_copy_start()
- * which is an helper over the ioctl() interface
- * Store Lustre, internal use only, data.
- */
 struct hsm_copy {
 	__u64			hc_data_version;
 	__u16			hc_flags;
diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h
index e14a5f674e85..3680668a8920 100644
--- a/drivers/staging/lustre/lustre/include/lustre_cfg.h
+++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h
@@ -88,6 +88,8 @@ enum lcfg_command_type {
 	LCFG_SET_LDLM_TIMEOUT   = 0x00ce030, /**< set ldlm_timeout */
 	LCFG_PRE_CLEANUP	= 0x00cf031, /**< call type-specific pre
 					      * cleanup cleanup */
+	LCFG_SET_PARAM		= 0x00ce032, /**< use set_param syntax to set
+					      *a proc parameters */
 };
 
 struct lustre_cfg_bufs {
diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h
index 1de9a8bed497..ac08164793cb 100644
--- a/drivers/staging/lustre/lustre/include/lustre_disk.h
+++ b/drivers/staging/lustre/lustre/include/lustre_disk.h
@@ -99,6 +99,8 @@
 #define LDD_F_IR_CAPABLE    0x2000
 /** the MGS refused to register the target. */
 #define LDD_F_ERROR	 0x4000
+/** process at lctl conf_param */
+#define LDD_F_PARAM2		0x8000
 
 /* opc for target register */
 #define LDD_F_OPC_REG   0x10000000
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
index 75716f17f64b..73fb38ee0a34 100644
--- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
@@ -35,10 +35,10 @@
 #ifndef LDLM_ALL_FLAGS_MASK
 
 /** l_flags bits marked as "all_flags" bits */
-#define LDLM_FL_ALL_FLAGS_MASK          0x00FFFFFFC08F132FULL
+#define LDLM_FL_ALL_FLAGS_MASK          0x00FFFFFFC08F932FULL
 
 /** l_flags bits marked as "ast" bits */
-#define LDLM_FL_AST_MASK                0x0000000080000000ULL
+#define LDLM_FL_AST_MASK                0x0000000080008000ULL
 
 /** l_flags bits marked as "blocked" bits */
 #define LDLM_FL_BLOCKED_MASK            0x000000000000000EULL
@@ -56,7 +56,7 @@
 #define LDLM_FL_LOCAL_ONLY_MASK         0x00FFFFFF00000000ULL
 
 /** l_flags bits marked as "on_wire" bits */
-#define LDLM_FL_ON_WIRE_MASK            0x00000000C08F132FULL
+#define LDLM_FL_ON_WIRE_MASK            0x00000000C08F932FULL
 
 /** extent, mode, or resource changed */
 #define LDLM_FL_LOCK_CHANGED            0x0000000000000001ULL // bit   0
@@ -114,6 +114,12 @@
 #define ldlm_set_has_intent(_l)         LDLM_SET_FLAG((  _l), 1ULL << 12)
 #define ldlm_clear_has_intent(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 12)
 
+/** flock deadlock detected */
+#define LDLM_FL_FLOCK_DEADLOCK          0x0000000000008000ULL /* bit  15 */
+#define ldlm_is_flock_deadlock(_l)      LDLM_TEST_FLAG((_l), 1ULL << 15)
+#define ldlm_set_flock_deadlock(_l)     LDLM_SET_FLAG((_l), 1ULL << 15)
+#define ldlm_clear_flock_deadlock(_l)   LDLM_CLEAR_FLAG((_l), 1ULL << 15)
+
 /** discard (no writeback) on cancel */
 #define LDLM_FL_DISCARD_DATA            0x0000000000010000ULL // bit  16
 #define ldlm_is_discard_data(_l)        LDLM_TEST_FLAG(( _l), 1ULL << 16)
@@ -390,6 +396,7 @@ static int hf_lustre_ldlm_fl_ast_sent            = -1;
 static int hf_lustre_ldlm_fl_replay              = -1;
 static int hf_lustre_ldlm_fl_intent_only         = -1;
 static int hf_lustre_ldlm_fl_has_intent          = -1;
+static int hf_lustre_ldlm_fl_flock_deadlock      = -1;
 static int hf_lustre_ldlm_fl_discard_data        = -1;
 static int hf_lustre_ldlm_fl_no_timeout          = -1;
 static int hf_lustre_ldlm_fl_block_nowait        = -1;
@@ -431,6 +438,7 @@ const value_string lustre_ldlm_flags_vals[] = {
 	{LDLM_FL_REPLAY,              "LDLM_FL_REPLAY"},
 	{LDLM_FL_INTENT_ONLY,         "LDLM_FL_INTENT_ONLY"},
 	{LDLM_FL_HAS_INTENT,          "LDLM_FL_HAS_INTENT"},
+	{LDLM_FL_FLOCK_DEADLOCK,      "LDLM_FL_FLOCK_DEADLOCK"},
 	{LDLM_FL_DISCARD_DATA,        "LDLM_FL_DISCARD_DATA"},
 	{LDLM_FL_NO_TIMEOUT,          "LDLM_FL_NO_TIMEOUT"},
 	{LDLM_FL_BLOCK_NOWAIT,        "LDLM_FL_BLOCK_NOWAIT"},
diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h
index 2feb38b51af2..6f7f48c7f2f1 100644
--- a/drivers/staging/lustre/lustre/include/lustre_export.h
+++ b/drivers/staging/lustre/lustre/include/lustre_export.h
@@ -380,6 +380,23 @@ static inline bool imp_connect_lvb_type(struct obd_import *imp)
 		return false;
 }
 
+static inline __u64 exp_connect_ibits(struct obd_export *exp)
+{
+	struct obd_connect_data *ocd;
+
+	ocd = &exp->exp_connect_data;
+	return ocd->ocd_ibits_known;
+}
+
+static inline bool imp_connect_disp_stripe(struct obd_import *imp)
+{
+	struct obd_connect_data *ocd;
+
+	LASSERT(imp != NULL);
+	ocd = &imp->imp_connect_data;
+	return ocd->ocd_connect_flags & OBD_CONNECT_DISP_STRIPE;
+}
+
 extern struct obd_export *class_conn2export(struct lustre_handle *conn);
 extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h
index 84a897eed1df..cf78761356a4 100644
--- a/drivers/staging/lustre/lustre/include/lustre_fid.h
+++ b/drivers/staging/lustre/lustre/include/lustre_fid.h
@@ -685,7 +685,7 @@ static inline __u32 fid_hash(const struct lu_fid *f, int bits)
 {
 	/* all objects with same id and different versions will belong to same
 	 * collisions list. */
-	return cfs_hash_long(fid_flatten(f), bits);
+	return hash_long(fid_flatten(f), bits);
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
index 67259eb43cde..e9833ae8b171 100644
--- a/drivers/staging/lustre/lustre/include/lustre_import.h
+++ b/drivers/staging/lustre/lustre/include/lustre_import.h
@@ -180,6 +180,17 @@ struct obd_import {
 	struct list_head		imp_delayed_list;
 	/** @} */
 
+	/**
+	 * List of requests that are retained for committed open replay. Once
+	 * open is committed, open replay request will be moved from the
+	 * imp_replay_list into the imp_committed_list.
+	 * The imp_replay_cursor is for accelerating searching during replay.
+	 * @{
+	 */
+	struct list_head		imp_committed_list;
+	struct list_head	       *imp_replay_cursor;
+	/** @} */
+
 	/** obd device for this import */
 	struct obd_device	*imp_obd;
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h
index c1e02702b931..468f36344a34 100644
--- a/drivers/staging/lustre/lustre/include/lustre_mdc.h
+++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h
@@ -166,6 +166,17 @@ void it_clear_disposition(struct lookup_intent *it, int flag);
 void it_set_disposition(struct lookup_intent *it, int flag);
 int it_open_error(int phase, struct lookup_intent *it);
 
+static inline bool cl_is_lov_delay_create(unsigned int flags)
+{
+	return (flags & O_LOV_DELAY_CREATE) == O_LOV_DELAY_CREATE;
+}
+
+static inline void cl_lov_delay_create_clear(unsigned int *flags)
+{
+	if ((*flags & O_LOV_DELAY_CREATE) == O_LOV_DELAY_CREATE)
+		*flags &= ~O_LOV_DELAY_CREATE;
+}
+
 /** @} mdc */
 
 #endif
diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h
index d8d088035428..11382abf9291 100644
--- a/drivers/staging/lustre/lustre/include/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/lustre_net.h
@@ -2621,6 +2621,8 @@ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd);
  * request queues, request management, etc.
  * @{
  */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force);
+
 void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
 			struct ptlrpc_client *);
 void ptlrpc_cleanup_client(struct obd_import *imp);
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index c3470ce62cff..1b386955adda 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -1323,7 +1323,8 @@ struct md_open_data {
 	struct obd_client_handle *mod_och;
 	struct ptlrpc_request    *mod_open_req;
 	struct ptlrpc_request    *mod_close_req;
-	atomic_t	      mod_refcount;
+	atomic_t		  mod_refcount;
+	bool			  mod_is_create;
 };
 
 struct lookup_intent;
@@ -1392,7 +1393,7 @@ struct md_ops {
 
 	int (*m_set_open_replay_data)(struct obd_export *,
 				      struct obd_client_handle *,
-				      struct ptlrpc_request *);
+				      struct lookup_intent *);
 	int (*m_clear_open_replay_data)(struct obd_export *,
 					struct obd_client_handle *);
 	int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *);
diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h
index 983718fe1e55..0a188207014c 100644
--- a/drivers/staging/lustre/lustre/include/obd_class.h
+++ b/drivers/staging/lustre/lustre/include/obd_class.h
@@ -175,9 +175,13 @@ enum {
 	CONFIG_T_CONFIG  = 0,
 	CONFIG_T_SPTLRPC = 1,
 	CONFIG_T_RECOVER = 2,
-	CONFIG_T_MAX     = 3
+	CONFIG_T_PARAMS  = 3,
+	CONFIG_T_MAX     = 4
 };
 
+#define PARAMS_FILENAME	"params"
+#define LCTL_UPCALL	"lctl"
+
 /* list of active configuration logs  */
 struct config_llog_data {
 	struct ldlm_res_id	  cld_resid;
@@ -185,7 +189,8 @@ struct config_llog_data {
 	struct list_head		  cld_list_chain;
 	atomic_t		cld_refcount;
 	struct config_llog_data    *cld_sptlrpc;/* depended sptlrpc log */
-	struct config_llog_data    *cld_recover;    /* imperative recover log */
+	struct config_llog_data	   *cld_params;	/* common parameters log */
+	struct config_llog_data    *cld_recover;/* imperative recover log */
 	struct obd_export	  *cld_mgcexp;
 	struct mutex		    cld_lock;
 	int			 cld_type;
@@ -1996,11 +2001,11 @@ static inline int md_getxattr(struct obd_export *exp,
 
 static inline int md_set_open_replay_data(struct obd_export *exp,
 					  struct obd_client_handle *och,
-					  struct ptlrpc_request *open_req)
+					  struct lookup_intent *it)
 {
 	EXP_CHECK_MD_OP(exp, set_open_replay_data);
 	EXP_MD_COUNTER_INCREMENT(exp, set_open_replay_data);
-	return MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req);
+	return MDP(exp->exp_obd, set_open_replay_data)(exp, och, it);
 }
 
 static inline int md_clear_open_replay_data(struct obd_export *exp,
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
index c9aae132f98a..986bf384bff7 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
@@ -205,6 +205,26 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
 	return 0;
 }
 
+static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock,
+					  struct list_head *work_list)
+{
+	CDEBUG(D_INFO, "reprocess deadlock req=%p\n", lock);
+
+	if ((exp_connect_flags(lock->l_export) &
+				OBD_CONNECT_FLOCK_DEAD) == 0) {
+		CERROR(
+		      "deadlock found, but client doesn't support flock canceliation\n");
+	} else {
+		LASSERT(lock->l_completion_ast);
+		LASSERT((lock->l_flags & LDLM_FL_AST_SENT) == 0);
+		lock->l_flags |= LDLM_FL_AST_SENT | LDLM_FL_CANCEL_ON_BLOCK |
+			LDLM_FL_FLOCK_DEADLOCK;
+		ldlm_flock_blocking_unlink(lock);
+		ldlm_resource_unlink_lock(lock);
+		ldlm_add_ast_work_item(lock, NULL, work_list);
+	}
+}
+
 /**
  * Process a granting attempt for flock lock.
  * Must be called under ns lock held.
@@ -272,6 +292,7 @@ reprocess:
 			}
 		}
 	} else {
+		int reprocess_failed = 0;
 		lockmode_verify(mode);
 
 		/* This loop determines if there are existing locks
@@ -293,8 +314,15 @@ reprocess:
 			if (!ldlm_flocks_overlap(lock, req))
 				continue;
 
-			if (!first_enq)
-				return LDLM_ITER_CONTINUE;
+			if (!first_enq) {
+				reprocess_failed = 1;
+				if (ldlm_flock_deadlock(req, lock)) {
+					ldlm_flock_cancel_on_deadlock(req,
+							work_list);
+					return LDLM_ITER_CONTINUE;
+				}
+				continue;
+			}
 
 			if (*flags & LDLM_FL_BLOCK_NOWAIT) {
 				ldlm_flock_destroy(req, mode, *flags);
@@ -330,6 +358,8 @@ reprocess:
 			*flags |= LDLM_FL_BLOCK_GRANTED;
 			return LDLM_ITER_STOP;
 		}
+		if (reprocess_failed)
+			return LDLM_ITER_CONTINUE;
 	}
 
 	if (*flags & LDLM_FL_TEST_LOCK) {
@@ -646,7 +676,10 @@ granted:
 	/* ldlm_lock_enqueue() has already placed lock on the granted list. */
 	list_del_init(&lock->l_res_link);
 
-	if (flags & LDLM_FL_TEST_LOCK) {
+	if (lock->l_flags & LDLM_FL_FLOCK_DEADLOCK) {
+		LDLM_DEBUG(lock, "client-side enqueue deadlock received");
+		rc = -EDEADLK;
+	} else if (flags & LDLM_FL_TEST_LOCK) {
 		/* fcntl(F_GETLK) request */
 		/* The old mode was saved in getlk->fl_type so that if the mode
 		 * in the lock changes we can decref the appropriate refcount.*/
@@ -672,7 +705,7 @@ granted:
 		ldlm_process_flock_lock(lock, &noreproc, 1, &err, NULL);
 	}
 	unlock_res_and_lock(lock);
-	return 0;
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_flock_completion_ast);
 
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
index 692623beee12..0548aca45e8e 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
@@ -145,8 +145,6 @@ char *ldlm_it2str(int it)
 		return "getxattr";
 	case IT_LAYOUT:
 		return "layout";
-	case IT_SETXATTR:
-		return "setxattr";
 	default:
 		CERROR("Unknown intent %d\n", it);
 		return "UNKNOWN";
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
index 3ed020eb89c0..d87048dcc70c 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
@@ -228,6 +228,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 
 			lock_res_and_lock(lock);
 			LASSERT(lock->l_lvb_data == NULL);
+			lock->l_lvb_type = LVB_T_LAYOUT;
 			lock->l_lvb_data = lvb_data;
 			lock->l_lvb_len = lvb_len;
 			unlock_res_and_lock(lock);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index 5f89864cda14..2824d4a9a85b 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -421,9 +421,9 @@ static unsigned ldlm_res_hop_fid_hash(struct cfs_hash *hs,
 	} else {
 		val = fid_oid(&fid);
 	}
-	hash = cfs_hash_long(hash, hs->hs_bkt_bits);
+	hash = hash_long(hash, hs->hs_bkt_bits);
 	/* give me another random factor */
-	hash -= cfs_hash_long((unsigned long)hs, val % 11 + 3);
+	hash -= hash_long((unsigned long)hs, val % 11 + 3);
 
 	hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
 	hash |= ldlm_res_hop_hash(hs, key, CFS_HASH_NBKT(hs) - 1);
diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
index 7b2c31599327..b6ddc998f750 100644
--- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
+++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
@@ -44,106 +44,6 @@
 
 #include <linux/libcfs/libcfs.h>
 
-#ifdef LUSTRE_UTILS
-/* This is the userspace side. */
-
-/** Start the userspace side of a KUC pipe.
- * @param link Private descriptor for pipe/socket.
- * @param groups KUC broadcast group to listen to
- *	  (can be null for unicast to this pid)
- */
-int libcfs_ukuc_start(lustre_kernelcomm *link, int group)
-{
-	int pfd[2];
-
-	if (pipe(pfd) < 0)
-		return -errno;
-
-	memset(link, 0, sizeof(*link));
-	link->lk_rfd = pfd[0];
-	link->lk_wfd = pfd[1];
-	link->lk_group = group;
-	link->lk_uid = getpid();
-	return 0;
-}
-
-int libcfs_ukuc_stop(lustre_kernelcomm *link)
-{
-	if (link->lk_wfd > 0)
-		close(link->lk_wfd);
-	return close(link->lk_rfd);
-}
-
-#define lhsz sizeof(*kuch)
-
-/** Read a message from the link.
- * Allocates memory, returns handle
- *
- * @param link Private descriptor for pipe/socket.
- * @param buf Buffer to read into, must include size for kuc_hdr
- * @param maxsize Maximum message size allowed
- * @param transport Only listen to messages on this transport
- *      (and the generic transport)
- */
-int libcfs_ukuc_msg_get(lustre_kernelcomm *link, char *buf, int maxsize,
-			int transport)
-{
-	struct kuc_hdr *kuch;
-	int rc = 0;
-
-	memset(buf, 0, maxsize);
-
-	CDEBUG(D_KUC, "Waiting for message from kernel on fd %d\n",
-	       link->lk_rfd);
-
-	while (1) {
-		/* Read header first to get message size */
-		rc = read(link->lk_rfd, buf, lhsz);
-		if (rc <= 0) {
-			rc = -errno;
-			break;
-		}
-		kuch = (struct kuc_hdr *)buf;
-
-		CDEBUG(D_KUC, "Received message mg=%x t=%d m=%d l=%d\n",
-		       kuch->kuc_magic, kuch->kuc_transport, kuch->kuc_msgtype,
-		       kuch->kuc_msglen);
-
-		if (kuch->kuc_magic != KUC_MAGIC) {
-			CERROR("bad message magic %x != %x\n",
-			       kuch->kuc_magic, KUC_MAGIC);
-			rc = -EPROTO;
-			break;
-		}
-
-		if (kuch->kuc_msglen > maxsize) {
-			rc = -EMSGSIZE;
-			break;
-		}
-
-		/* Read payload */
-		rc = read(link->lk_rfd, buf + lhsz, kuch->kuc_msglen - lhsz);
-		if (rc < 0) {
-			rc = -errno;
-			break;
-		}
-		if (rc < (kuch->kuc_msglen - lhsz)) {
-			CERROR("short read: got %d of %d bytes\n",
-			       rc, kuch->kuc_msglen);
-			rc = -EPROTO;
-			break;
-		}
-
-		if (kuch->kuc_transport == transport ||
-		    kuch->kuc_transport == KUC_TRANSPORT_GENERIC) {
-			return 0;
-		}
-		/* Drop messages for other transports */
-	}
-	return rc;
-}
-
-#else /* LUSTRE_UTILS */
 /* This is the kernel side (liblustre as well). */
 
 /**
@@ -338,5 +238,3 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
 	return rc;
 }
 EXPORT_SYMBOL(libcfs_kkuc_group_foreach);
-
-#endif /* LUSTRE_UTILS */
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
index 58bb256ee047..77b1ef64ecc0 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
@@ -952,6 +952,7 @@ static int
 cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 {
 	unsigned int  cpu = (unsigned long)hcpu;
+	bool	     warn;
 
 	switch (action) {
 	case CPU_DEAD:
@@ -962,9 +963,21 @@ cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 		cpt_data.cpt_version++;
 		spin_unlock(&cpt_data.cpt_lock);
 	default:
-		CWARN("Lustre: can't support CPU hotplug well now, "
-		      "performance and stability could be impacted"
-		      "[CPU %u notify: %lx]\n", cpu, action);
+		if (action != CPU_DEAD && action != CPU_DEAD_FROZEN) {
+			CDEBUG(D_INFO, "CPU changed [cpu %u action %lx]\n",
+			       cpu, action);
+			break;
+		}
+
+		down(&cpt_data.cpt_mutex);
+		/* if all HTs in a core are offline, it may break affinity */
+		cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
+		warn = any_online_cpu(*cpt_data.cpt_cpumask) >= nr_cpu_ids;
+		up(&cpt_data.cpt_mutex);
+		CDEBUG(warn ? D_WARNING : D_INFO,
+		       "Lustre: can't support CPU plug-out well now, "
+		       "performance and stability could be impacted "
+		       "[CPU %u action: %lx]\n", cpu, action);
 	}
 
 	return NOTIFY_OK;
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
index a2ef64c3403d..6d0bd220d53d 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
@@ -55,25 +55,11 @@
  * for Linux kernel.
  */
 
-int    cfs_curproc_groups_nr(void)
-{
-	int nr;
-
-	task_lock(current);
-	nr = current_cred()->group_info->ngroups;
-	task_unlock(current);
-	return nr;
-}
-
-/* Currently all the CFS_CAP_* defines match CAP_* ones. */
-#define cfs_cap_pack(cap) (cap)
-#define cfs_cap_unpack(cap) (cap)
-
 void cfs_cap_raise(cfs_cap_t cap)
 {
 	struct cred *cred;
 	if ((cred = prepare_creds())) {
-		cap_raise(cred->cap_effective, cfs_cap_unpack(cap));
+		cap_raise(cred->cap_effective, cap);
 		commit_creds(cred);
 	}
 }
@@ -82,41 +68,25 @@ void cfs_cap_lower(cfs_cap_t cap)
 {
 	struct cred *cred;
 	if ((cred = prepare_creds())) {
-		cap_lower(cred->cap_effective, cfs_cap_unpack(cap));
+		cap_lower(cred->cap_effective, cap);
 		commit_creds(cred);
 	}
 }
 
 int cfs_cap_raised(cfs_cap_t cap)
 {
-	return cap_raised(current_cap(), cfs_cap_unpack(cap));
+	return cap_raised(current_cap(), cap);
 }
 
 void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap)
 {
-#if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330
-	*cap = cfs_cap_pack(kcap);
-#elif defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x20071026
-	*cap = cfs_cap_pack(kcap[0]);
-#elif defined(_KERNEL_CAPABILITY_VERSION) && _KERNEL_CAPABILITY_VERSION == 0x20080522
 	/* XXX lost high byte */
-	*cap = cfs_cap_pack(kcap.cap[0]);
-#else
-	#error "need correct _KERNEL_CAPABILITY_VERSION "
-#endif
+	*cap = kcap.cap[0];
 }
 
 void cfs_kernel_cap_unpack(kernel_cap_t *kcap, cfs_cap_t cap)
 {
-#if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330
-	*kcap = cfs_cap_unpack(cap);
-#elif defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x20071026
-	(*kcap)[0] = cfs_cap_unpack(cap);
-#elif defined(_KERNEL_CAPABILITY_VERSION) && _KERNEL_CAPABILITY_VERSION == 0x20080522
-	kcap->cap[0] = cfs_cap_unpack(cap);
-#else
-	#error "need correct _KERNEL_CAPABILITY_VERSION "
-#endif
+	kcap->cap[0] = cap;
 }
 
 cfs_cap_t cfs_curproc_cap_pack(void)
@@ -126,20 +96,6 @@ cfs_cap_t cfs_curproc_cap_pack(void)
 	return cap;
 }
 
-void cfs_curproc_cap_unpack(cfs_cap_t cap)
-{
-	struct cred *cred;
-	if ((cred = prepare_creds())) {
-		cfs_kernel_cap_unpack(&cred->cap_effective, cap);
-		commit_creds(cred);
-	}
-}
-
-int cfs_capable(cfs_cap_t cap)
-{
-	return capable(cfs_cap_unpack(cap));
-}
-
 static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr,
 				 void *buf, int len, int write)
 {
@@ -292,13 +248,10 @@ out:
 }
 EXPORT_SYMBOL(cfs_get_environ);
 
-EXPORT_SYMBOL(cfs_curproc_groups_nr);
 EXPORT_SYMBOL(cfs_cap_raise);
 EXPORT_SYMBOL(cfs_cap_lower);
 EXPORT_SYMBOL(cfs_cap_raised);
 EXPORT_SYMBOL(cfs_curproc_cap_pack);
-EXPORT_SYMBOL(cfs_curproc_cap_unpack);
-EXPORT_SYMBOL(cfs_capable);
 
 /*
  * Local variables:
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
index 55296a3591d5..e6eae0666f0d 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
@@ -150,12 +150,12 @@ static long libcfs_ioctl(struct file *file,
 	/* Handle platform-dependent IOC requests */
 	switch (cmd) {
 	case IOC_LIBCFS_PANIC:
-		if (!cfs_capable(CFS_CAP_SYS_BOOT))
+		if (!capable(CFS_CAP_SYS_BOOT))
 			return (-EPERM);
 		panic("debugctl-invoked panic");
 		return (0);
 	case IOC_LIBCFS_MEMHOG:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			return -EPERM;
 		/* go thought */
 	}
diff --git a/drivers/staging/lustre/lustre/libcfs/workitem.c b/drivers/staging/lustre/lustre/libcfs/workitem.c
index 1a55c81892e0..53813fca536f 100644
--- a/drivers/staging/lustre/lustre/libcfs/workitem.c
+++ b/drivers/staging/lustre/lustre/libcfs/workitem.c
@@ -389,11 +389,11 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
 		spin_unlock(&cfs_wi_data.wi_glock);
 
 		if (sched->ws_cptab != NULL && sched->ws_cpt >= 0) {
-			snprintf(name, sizeof(name), "%s_%02d_%02d",
+			snprintf(name, sizeof(name), "%s_%02d_%02u",
 				 sched->ws_name, sched->ws_cpt,
 				 sched->ws_nthreads);
 		} else {
-			snprintf(name, sizeof(name), "%s_%02d",
+			snprintf(name, sizeof(name), "%s_%02u",
 				 sched->ws_name, sched->ws_nthreads);
 		}
 
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index cbd663ed030c..f971a543cb58 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -176,7 +176,7 @@ static int ll_ddelete(const struct dentry *de)
 	return 0;
 }
 
-static int ll_set_dd(struct dentry *de)
+int ll_d_init(struct dentry *de)
 {
 	LASSERT(de != NULL);
 
@@ -190,40 +190,22 @@ static int ll_set_dd(struct dentry *de)
 		OBD_ALLOC_PTR(lld);
 		if (likely(lld != NULL)) {
 			spin_lock(&de->d_lock);
-			if (likely(de->d_fsdata == NULL))
+			if (likely(de->d_fsdata == NULL)) {
 				de->d_fsdata = lld;
-			else
+				__d_lustre_invalidate(de);
+			} else {
 				OBD_FREE_PTR(lld);
+			}
 			spin_unlock(&de->d_lock);
 		} else {
 			return -ENOMEM;
 		}
 	}
+	LASSERT(de->d_op == &ll_d_ops);
 
 	return 0;
 }
 
-int ll_dops_init(struct dentry *de, int block, int init_sa)
-{
-	struct ll_dentry_data *lld = ll_d2d(de);
-	int rc = 0;
-
-	if (lld == NULL && block != 0) {
-		rc = ll_set_dd(de);
-		if (rc)
-			return rc;
-
-		lld = ll_d2d(de);
-	}
-
-	if (lld != NULL && init_sa != 0)
-		lld->lld_sa_generation = 0;
-
-	/* kernel >= 2.6.38 d_op is set in d_alloc() */
-	LASSERT(de->d_op == &ll_d_ops);
-	return rc;
-}
-
 void ll_intent_drop_lock(struct lookup_intent *it)
 {
 	if (it->it_op && it->d.lustre.it_lock_mode) {
@@ -259,9 +241,6 @@ void ll_intent_release(struct lookup_intent *it)
 		 ptlrpc_req_finished(it->d.lustre.it_data); /* ll_file_open */
 	if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
 		ptlrpc_req_finished(it->d.lustre.it_data);
-	if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
-						    * to lookup */
-		ptlrpc_req_finished(it->d.lustre.it_data);
 
 	it->d.lustre.it_disposition = 0;
 	it->d.lustre.it_data = NULL;
@@ -346,268 +325,32 @@ void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft)
 
 }
 
-int ll_revalidate_it(struct dentry *de, int lookup_flags,
-		     struct lookup_intent *it)
+static int ll_revalidate_dentry(struct dentry *dentry,
+				unsigned int lookup_flags)
 {
-	struct md_op_data *op_data;
-	struct ptlrpc_request *req = NULL;
-	struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
-	struct obd_export *exp;
-	struct inode *parent = de->d_parent->d_inode;
-	int rc;
-
-	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
-	       LL_IT2STR(it));
+	struct inode *dir = dentry->d_parent->d_inode;
 
-	if (de->d_inode == NULL) {
-		__u64 ibits;
-
-		/* We can only use negative dentries if this is stat or lookup,
-		   for opens and stuff we do need to query server. */
-		/* If there is IT_CREAT in intent op set, then we must throw
-		   away this negative dentry and actually do the request to
-		   kernel to create whatever needs to be created (if possible)*/
-		if (it && (it->it_op & IT_CREAT))
-			return 0;
-
-		if (d_lustre_invalid(de))
-			return 0;
-
-		ibits = MDS_INODELOCK_UPDATE;
-		rc = ll_have_md_lock(parent, &ibits, LCK_MINMODE);
-		GOTO(out_sa, rc);
-	}
-
-	/* Never execute intents for mount points.
-	 * Attributes will be fixed up in ll_inode_revalidate_it */
-	if (d_mountpoint(de))
-		GOTO(out_sa, rc = 1);
-
-	/* need to get attributes in case root got changed from other client */
-	if (de == de->d_sb->s_root) {
-		rc = __ll_inode_revalidate_it(de, it, MDS_INODELOCK_LOOKUP);
-		if (rc == 0)
-			rc = 1;
-		GOTO(out_sa, rc);
-	}
-
-	exp = ll_i2mdexp(de->d_inode);
-
-	OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
-	ll_frob_intent(&it, &lookup_it);
-	LASSERT(it);
+	/*
+	 * if open&create is set, talk to MDS to make sure file is created if
+	 * necessary, because we can't do this in ->open() later since that's
+	 * called on an inode. return 0 here to let lookup to handle this.
+	 */
+	if ((lookup_flags & (LOOKUP_OPEN | LOOKUP_CREATE)) ==
+	    (LOOKUP_OPEN | LOOKUP_CREATE))
+		return 0;
 
-	if (it->it_op == IT_LOOKUP && !d_lustre_invalid(de))
+	if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
 		return 1;
 
-	if (it->it_op == IT_OPEN) {
-		struct inode *inode = de->d_inode;
-		struct ll_inode_info *lli = ll_i2info(inode);
-		struct obd_client_handle **och_p;
-		__u64 ibits;
-
-		/*
-		 * We used to check for MDS_INODELOCK_OPEN here, but in fact
-		 * just having LOOKUP lock is enough to justify inode is the
-		 * same. And if inode is the same and we have suitable
-		 * openhandle, then there is no point in doing another OPEN RPC
-		 * just to throw away newly received openhandle.  There are no
-		 * security implications too, if file owner or access mode is
-		 * change, LOOKUP lock is revoked.
-		 */
-
-
-		if (it->it_flags & FMODE_WRITE)
-			och_p = &lli->lli_mds_write_och;
-		else if (it->it_flags & FMODE_EXEC)
-			och_p = &lli->lli_mds_exec_och;
-		else
-			och_p = &lli->lli_mds_read_och;
-
-		/* Check for the proper lock. */
-		ibits = MDS_INODELOCK_LOOKUP;
-		if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE))
-			goto do_lock;
-		mutex_lock(&lli->lli_och_mutex);
-		if (*och_p) { /* Everything is open already, do nothing */
-			/* Originally it was idea to do not let them steal our
-			 * open handle from under us by (*och_usecount)++ here.
-			 * But in case we have the handle, but we cannot use it
-			 * due to later checks (e.g. O_CREAT|O_EXCL flags set),
-			 * nobody would decrement counter increased here. So we
-			 * just hope the lock won't be invalidated in between.
-			 * But if it would be, we'll reopen the open request to
-			 * MDS later during file open path.
-			 */
-			mutex_unlock(&lli->lli_och_mutex);
-			return 1;
-		}
-		mutex_unlock(&lli->lli_och_mutex);
-	}
-
-	if (it->it_op == IT_GETATTR) {
-		rc = ll_statahead_enter(parent, &de, 0);
-		if (rc == 1)
-			goto mark;
-		else if (rc != -EAGAIN && rc != 0)
-			GOTO(out, rc = 0);
-	}
-
-do_lock:
-	op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
-				     de->d_name.name, de->d_name.len,
-				     0, LUSTRE_OPC_ANY, NULL);
-	if (IS_ERR(op_data))
-		return PTR_ERR(op_data);
-
-	if (!IS_POSIXACL(parent) || !exp_connect_umask(exp))
-		it->it_create_mode &= ~current_umask();
-	it->it_create_mode |= M_CHECK_STALE;
-	rc = md_intent_lock(exp, op_data, NULL, 0, it,
-			    lookup_flags,
-			    &req, ll_md_blocking_ast, 0);
-	it->it_create_mode &= ~M_CHECK_STALE;
-	ll_finish_md_op_data(op_data);
-
-	/* If req is NULL, then md_intent_lock only tried to do a lock match;
-	 * if all was well, it will return 1 if it found locks, 0 otherwise. */
-	if (req == NULL && rc >= 0) {
-		if (!rc)
-			goto do_lookup;
-		GOTO(out, rc);
-	}
-
-	if (rc < 0) {
-		if (rc != -ESTALE) {
-			CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
-			       "%d\n", rc, it->d.lustre.it_status);
-		}
-		GOTO(out, rc = 0);
-	}
-
-revalidate_finish:
-	rc = ll_revalidate_it_finish(req, it, de);
-	if (rc != 0) {
-		if (rc != -ESTALE && rc != -ENOENT)
-			ll_intent_release(it);
-		GOTO(out, rc = 0);
-	}
-
-	if ((it->it_op & IT_OPEN) && de->d_inode &&
-	    !S_ISREG(de->d_inode->i_mode) &&
-	    !S_ISDIR(de->d_inode->i_mode)) {
-		ll_release_openhandle(de, it);
-	}
-	rc = 1;
-
-out:
-	/* We do not free request as it may be reused during following lookup
-	 * (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
-	 * be freed in ll_lookup_it or in ll_intent_release. But if
-	 * request was not completed, we need to free it. (bug 5154, 9903) */
-	if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
-		ptlrpc_req_finished(req);
-	if (rc == 0) {
-		/* mdt may grant layout lock for the newly created file, so
-		 * release the lock to avoid leaking */
-		ll_intent_drop_lock(it);
-		ll_invalidate_aliases(de->d_inode);
-	} else {
-		__u64 bits = 0;
-		__u64 matched_bits = 0;
-
-		CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
-		       "inode %p refc %d\n", de->d_name.len,
-		       de->d_name.name, de, de->d_parent, de->d_inode,
-		       d_count(de));
-
-		ll_set_lock_data(exp, de->d_inode, it, &bits);
-
-		/* Note: We have to match both LOOKUP and PERM lock
-		 * here to make sure the dentry is valid and no one
-		 * changing the permission.
-		 * But if the client connects < 2.4 server, which will
-		 * only grant LOOKUP lock, so we can only Match LOOKUP
-		 * lock for old server */
-		if (exp_connect_flags(ll_i2mdexp(de->d_inode)) &&
-							OBD_CONNECT_LVB_TYPE)
-			matched_bits =
-				MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM;
-		else
-			matched_bits = MDS_INODELOCK_LOOKUP;
-
-		if (((bits & matched_bits) == matched_bits) &&
-		    d_lustre_invalid(de))
-			d_lustre_revalidate(de);
-		ll_lookup_finish_locks(it, de);
-	}
-
-mark:
-	if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
-		ll_statahead_mark(parent, de);
-	return rc;
-
-	/*
-	 * This part is here to combat evil-evil race in real_lookup on 2.6
-	 * kernels.  The race details are: We enter do_lookup() looking for some
-	 * name, there is nothing in dcache for this name yet and d_lookup()
-	 * returns NULL.  We proceed to real_lookup(), and while we do this,
-	 * another process does open on the same file we looking up (most simple
-	 * reproducer), open succeeds and the dentry is added. Now back to
-	 * us. In real_lookup() we do d_lookup() again and suddenly find the
-	 * dentry, so we call d_revalidate on it, but there is no lock, so
-	 * without this code we would return 0, but unpatched real_lookup just
-	 * returns -ENOENT in such a case instead of retrying the lookup. Once
-	 * this is dealt with in real_lookup(), all of this ugly mess can go and
-	 * we can just check locks in ->d_revalidate without doing any RPCs
-	 * ever.
-	 */
-do_lookup:
-	if (it != &lookup_it) {
-		/* MDS_INODELOCK_UPDATE needed for IT_GETATTR case. */
-		if (it->it_op == IT_GETATTR)
-			lookup_it.it_op = IT_GETATTR;
-		ll_lookup_finish_locks(it, de);
-		it = &lookup_it;
-	}
+	if (d_need_statahead(dir, dentry) <= 0)
+		return 1;
 
-	/* Do real lookup here. */
-	op_data = ll_prep_md_op_data(NULL, parent, NULL, de->d_name.name,
-				     de->d_name.len, 0, (it->it_op & IT_CREAT ?
-							 LUSTRE_OPC_CREATE :
-							 LUSTRE_OPC_ANY), NULL);
-	if (IS_ERR(op_data))
-		return PTR_ERR(op_data);
-
-	rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
-			    ll_md_blocking_ast, 0);
-	if (rc >= 0) {
-		struct mdt_body *mdt_body;
-		struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
-		mdt_body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-
-		if (de->d_inode)
-			fid = *ll_inode2fid(de->d_inode);
-
-		/* see if we got same inode, if not - return error */
-		if (lu_fid_eq(&fid, &mdt_body->fid1)) {
-			ll_finish_md_op_data(op_data);
-			op_data = NULL;
-			goto revalidate_finish;
-		}
-		ll_intent_release(it);
-	}
-	ll_finish_md_op_data(op_data);
-	GOTO(out, rc = 0);
+	if (lookup_flags & LOOKUP_RCU)
+		return -ECHILD;
 
-out_sa:
-	/*
-	 * For rc == 1 case, should not return directly to prevent losing
-	 * statahead windows; for rc == 0 case, the "lookup" will be done later.
-	 */
-	if (it != NULL && it->it_op == IT_GETATTR && rc == 1)
-		ll_statahead_enter(parent, &de, 1);
-	goto mark;
+	do_statahead_enter(dir, &dentry, dentry->d_inode == NULL);
+	ll_statahead_mark(dir, dentry);
+	return 1;
 }
 
 /*
@@ -615,24 +358,13 @@ out_sa:
  */
 int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 {
-	struct inode *parent = dentry->d_parent->d_inode;
-	int unplug = 0;
+	int rc;
 
-	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n",
+	CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n",
 	       dentry->d_name.name, flags);
 
-	if (!(flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) &&
-	    ll_need_statahead(parent, dentry) > 0) {
-		if (flags & LOOKUP_RCU)
-			return -ECHILD;
-
-		if (dentry->d_inode == NULL)
-			unplug = 1;
-		do_statahead_enter(parent, &dentry, unplug);
-		ll_statahead_mark(parent, dentry);
-	}
-
-	return 1;
+	rc = ll_revalidate_dentry(dentry, flags);
+	return rc;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 52b7731bcc38..7fbc18e3e654 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -362,7 +362,7 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
 		struct ptlrpc_request *request;
 		struct md_op_data *op_data;
 
-		op_data = ll_prep_md_op_data(NULL, dir, NULL, NULL, 0, 0,
+		op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0,
 		LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
 			return (void *)op_data;
@@ -1048,20 +1048,25 @@ progress:
 }
 
 
-static int copy_and_ioctl(int cmd, struct obd_export *exp, void *data, int len)
+static int copy_and_ioctl(int cmd, struct obd_export *exp,
+			  const void __user *data, size_t size)
 {
-	void *ptr;
+	void *copy;
 	int rc;
 
-	OBD_ALLOC(ptr, len);
-	if (ptr == NULL)
+	OBD_ALLOC(copy, size);
+	if (copy == NULL)
 		return -ENOMEM;
-	if (copy_from_user(ptr, data, len)) {
-		OBD_FREE(ptr, len);
-		return -EFAULT;
+
+	if (copy_from_user(copy, data, size)) {
+		rc = -EFAULT;
+		goto out;
 	}
-	rc = obd_iocontrol(cmd, exp, len, data, NULL);
-	OBD_FREE(ptr, len);
+
+	rc = obd_iocontrol(cmd, exp, size, copy, NULL);
+out:
+	OBD_FREE(copy, size);
+
 	return rc;
 }
 
@@ -1080,7 +1085,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 	case Q_QUOTAOFF:
 	case Q_SETQUOTA:
 	case Q_SETINFO:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
+		if (!capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
 			return -EPERM;
 		break;
@@ -1089,7 +1094,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 		      !uid_eq(current_euid(), make_kuid(&init_user_ns, id))) ||
 		     (type == GRPQUOTA &&
 		      !in_egroup_p(make_kgid(&init_user_ns, id)))) &&
-		    (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
+		    (!capable(CFS_CAP_SYS_ADMIN) ||
 		     sbi->ll_flags & LL_SBI_RMT_CLIENT))
 			return -EPERM;
 		break;
@@ -1395,7 +1400,7 @@ lmv_out_free:
 		if (tmp == NULL)
 			GOTO(free_lmv, rc = -ENOMEM);
 
-		memcpy(tmp, &lum, sizeof(lum));
+		*tmp = lum;
 		tmp->lum_type = LMV_STRIPE_TYPE;
 		tmp->lum_stripe_count = 1;
 		mdtindex = ll_get_mdt_idx(inode);
@@ -1597,7 +1602,7 @@ out_rmdir:
 		struct obd_quotactl *oqctl;
 		int error = 0;
 
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
+		if (!capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
 			return -EPERM;
 
@@ -1621,7 +1626,7 @@ out_rmdir:
 	case OBD_IOC_POLL_QUOTACHECK: {
 		struct if_quotacheck *check;
 
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
+		if (!capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
 			return -EPERM;
 
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index c12821aedc2f..70b48ab30fe8 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -205,7 +205,7 @@ out:
 	return rc;
 }
 
-int ll_md_real_close(struct inode *inode, int flags)
+int ll_md_real_close(struct inode *inode, fmode_t fmode)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct obd_client_handle **och_p;
@@ -213,30 +213,33 @@ int ll_md_real_close(struct inode *inode, int flags)
 	__u64 *och_usecount;
 	int rc = 0;
 
-	if (flags & FMODE_WRITE) {
+	if (fmode & FMODE_WRITE) {
 		och_p = &lli->lli_mds_write_och;
 		och_usecount = &lli->lli_open_fd_write_count;
-	} else if (flags & FMODE_EXEC) {
+	} else if (fmode & FMODE_EXEC) {
 		och_p = &lli->lli_mds_exec_och;
 		och_usecount = &lli->lli_open_fd_exec_count;
 	} else {
-		LASSERT(flags & FMODE_READ);
+		LASSERT(fmode & FMODE_READ);
 		och_p = &lli->lli_mds_read_och;
 		och_usecount = &lli->lli_open_fd_read_count;
 	}
 
 	mutex_lock(&lli->lli_och_mutex);
-	if (*och_usecount) { /* There are still users of this handle, so
-				skip freeing it. */
+	if (*och_usecount > 0) {
+		/* There are still users of this handle, so skip
+		 * freeing it. */
 		mutex_unlock(&lli->lli_och_mutex);
 		return 0;
 	}
+
 	och=*och_p;
 	*och_p = NULL;
 	mutex_unlock(&lli->lli_och_mutex);
 
-	if (och) { /* There might be a race and somebody have freed this och
-		      already */
+	if (och != NULL) {
+		/* There might be a race and this handle may already
+		   be closed. */
 		rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
 					       inode, och, NULL);
 	}
@@ -443,8 +446,7 @@ static int ll_intent_file_open(struct file *file, void *lmm,
 				 itp, NULL);
 
 out:
-	ptlrpc_req_finished(itp->d.lustre.it_data);
-	it_clear_disposition(itp, DISP_ENQ_COMPLETE);
+	ptlrpc_req_finished(req);
 	ll_intent_drop_lock(itp);
 
 	return rc;
@@ -477,7 +479,7 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it,
 	och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
 	och->och_flags = it->it_flags;
 
-	return md_set_open_replay_data(md_exp, och, req);
+	return md_set_open_replay_data(md_exp, och, it);
 }
 
 int ll_local_open(struct file *file, struct lookup_intent *it,
@@ -671,14 +673,13 @@ restart:
 
 	ll_capa_open(inode);
 
-	if (!lli->lli_has_smd) {
-		if (file->f_flags & O_LOV_DELAY_CREATE ||
-		    !(file->f_mode & FMODE_WRITE)) {
-			CDEBUG(D_INODE, "object creation was delayed\n");
-			GOTO(out_och_free, rc);
-		}
+	if (!lli->lli_has_smd &&
+	    (cl_is_lov_delay_create(file->f_flags) ||
+	     (file->f_mode & FMODE_WRITE) == 0)) {
+		CDEBUG(D_INODE, "object creation was delayed\n");
+		GOTO(out_och_free, rc);
 	}
-	file->f_flags &= ~O_LOV_DELAY_CREATE;
+	cl_lov_delay_create_clear(&file->f_flags);
 	GOTO(out_och_free, rc);
 
 out_och_free:
@@ -813,10 +814,7 @@ struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file,
 	 * doesn't deal with openhandle, so normal openhandle will be leaked. */
 				LDLM_FL_NO_LRU | LDLM_FL_EXCL);
 	ll_finish_md_op_data(op_data);
-	if (req != NULL) {
-		ptlrpc_req_finished(req);
-		it_clear_disposition(&it, DISP_ENQ_COMPLETE);
-	}
+	ptlrpc_req_finished(req);
 	if (rc < 0)
 		GOTO(out_release_it, rc);
 
@@ -1033,6 +1031,33 @@ int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm,
 	return rc;
 }
 
+static bool file_is_noatime(const struct file *file)
+{
+	const struct vfsmount *mnt = file->f_path.mnt;
+	const struct inode *inode = file->f_path.dentry->d_inode;
+
+	/* Adapted from file_accessed() and touch_atime().*/
+	if (file->f_flags & O_NOATIME)
+		return true;
+
+	if (inode->i_flags & S_NOATIME)
+		return true;
+
+	if (IS_NOATIME(inode))
+		return true;
+
+	if (mnt->mnt_flags & (MNT_NOATIME | MNT_READONLY))
+		return true;
+
+	if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+		return true;
+
+	if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+		return true;
+
+	return false;
+}
+
 void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
 	struct inode *inode = file->f_dentry->d_inode;
@@ -1052,6 +1077,8 @@ void ll_io_init(struct cl_io *io, const struct file *file, int write)
 	} else if (file->f_flags & O_APPEND) {
 		io->ci_lockreq = CILR_MANDATORY;
 	}
+
+	io->ci_noatime = file_is_noatime(file);
 }
 
 static ssize_t
@@ -1092,10 +1119,6 @@ restart:
 				down_read(&lli->lli_trunc_sem);
 			}
 			break;
-		case IO_SENDFILE:
-			vio->u.sendfile.cui_actor = args->u.sendfile.via_actor;
-			vio->u.sendfile.cui_target = args->u.sendfile.via_target;
-			break;
 		case IO_SPLICE:
 			vio->u.splice.cui_pipe = args->u.splice.via_pipe;
 			vio->u.splice.cui_flags = args->u.splice.via_flags;
@@ -1340,7 +1363,7 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg)
 	struct ll_recreate_obj ucreat;
 	struct ost_id		oi;
 
-	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+	if (!capable(CFS_CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg,
@@ -1358,7 +1381,7 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg)
 	struct ost_id	oi;
 	obd_count	ost_idx;
 
-	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+	if (!capable(CFS_CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid)))
@@ -1381,23 +1404,25 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
 		ccc_inode_lsm_put(inode, lsm);
 		CDEBUG(D_IOCTL, "stripe already exists for ino %lu\n",
 		       inode->i_ino);
-		return -EEXIST;
+		GOTO(out, rc = -EEXIST);
 	}
 
 	ll_inode_size_lock(inode);
 	rc = ll_intent_file_open(file, lum, lum_size, &oit);
 	if (rc)
-		GOTO(out, rc);
+		GOTO(out_unlock, rc);
 	rc = oit.d.lustre.it_status;
 	if (rc < 0)
 		GOTO(out_req_free, rc);
 
 	ll_release_openhandle(file->f_dentry, &oit);
 
- out:
+out_unlock:
 	ll_inode_size_unlock(inode);
 	ll_intent_release(&oit);
 	ccc_inode_lsm_put(inode, lsm);
+out:
+	cl_lov_delay_create_clear(&file->f_flags);
 	return rc;
 out_req_free:
 	ptlrpc_req_finished((struct ptlrpc_request *) oit.d.lustre.it_data);
@@ -1497,7 +1522,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
 					    sizeof(struct lov_user_ost_data);
 	int			 rc;
 
-	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+	if (!capable(CFS_CAP_SYS_ADMIN))
 		return -EPERM;
 
 	OBD_ALLOC_LARGE(lump, lum_size);
@@ -1747,7 +1772,7 @@ int ll_fid2path(struct inode *inode, void *arg)
 	struct getinfo_fid2path	*gfout, *gfin;
 	int			 outsize, rc;
 
-	if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) &&
+	if (!capable(CFS_CAP_DAC_READ_SEARCH) &&
 	    !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
 		return -EPERM;
 
@@ -2093,7 +2118,7 @@ static int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
 	/* Non-root users are forbidden to set or clear flags which are
 	 * NOT defined in HSM_USER_MASK. */
 	if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) &&
-	    !cfs_capable(CFS_CAP_SYS_ADMIN))
+	    !capable(CFS_CAP_SYS_ADMIN))
 		return -EPERM;
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
@@ -2891,7 +2916,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 			oit.it_op = IT_LOOKUP;
 
 		/* Call getattr by fid, so do not provide name at all. */
-		op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode,
+		op_data = ll_prep_md_op_data(NULL, dentry->d_inode,
 					     dentry->d_inode, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index 7ee5c02783f9..f67c50829437 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -296,13 +296,6 @@ int ll_xattr_cache_get(struct inode *inode,
 			size_t size,
 			__u64 valid);
 
-int ll_xattr_cache_update(struct inode *inode,
-			const char *name,
-			const char *newval,
-			size_t size,
-			__u64 valid,
-			int flags);
-
 /*
  * Locking to guarantee consistency of non-atomic updates to long long i_size,
  * consistency between file size and KMS.
@@ -782,7 +775,7 @@ int ll_local_open(struct file *file,
 int ll_release_openhandle(struct dentry *, struct lookup_intent *);
 int ll_md_close(struct obd_export *md_exp, struct inode *inode,
 		struct file *file);
-int ll_md_real_close(struct inode *inode, int flags);
+int ll_md_real_close(struct inode *inode, fmode_t fmode);
 void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
 		      struct obd_client_handle **och, unsigned long flags);
 void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data);
@@ -828,7 +821,7 @@ int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
 
 /* llite/dcache.c */
 
-int ll_dops_init(struct dentry *de, int block, int init_sa);
+int ll_d_init(struct dentry *de);
 extern struct dentry_operations ll_d_ops;
 void ll_intent_drop_lock(struct lookup_intent *);
 void ll_intent_release(struct lookup_intent *);
@@ -919,8 +912,6 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page);
 enum vvp_io_subtype {
 	/** normal IO */
 	IO_NORMAL,
-	/** io called from .sendfile */
-	IO_SENDFILE,
 	/** io started from splice_{read|write} */
 	IO_SPLICE
 };
@@ -932,10 +923,6 @@ struct vvp_io {
 
 	union {
 		struct {
-			read_actor_t      cui_actor;
-			void	     *cui_target;
-		} sendfile;
-		struct {
 			struct pipe_inode_info *cui_pipe;
 			unsigned int	    cui_flags;
 		} splice;
@@ -981,7 +968,7 @@ struct vvp_io {
  * IO arguments for various VFS I/O interfaces.
  */
 struct vvp_io_args {
-	/** normal/sendfile/splice */
+	/** normal/splice */
 	enum vvp_io_subtype via_io_subtype;
 
 	union {
@@ -991,10 +978,6 @@ struct vvp_io_args {
 			unsigned long      via_nrsegs;
 		} normal;
 		struct {
-			read_actor_t       via_actor;
-			void	      *via_target;
-		} sendfile;
-		struct {
 			struct pipe_inode_info  *via_pipe;
 			unsigned int       via_flags;
 		} splice;
@@ -1320,12 +1303,13 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry)
 	if (lli->lli_opendir_pid != current_pid())
 		return;
 
-	if (sai != NULL && ldd != NULL)
+	LASSERT(ldd != NULL);
+	if (sai != NULL)
 		ldd->lld_sa_generation = sai->sai_generation;
 }
 
 static inline int
-ll_need_statahead(struct inode *dir, struct dentry *dentryp)
+d_need_statahead(struct inode *dir, struct dentry *dentryp)
 {
 	struct ll_inode_info  *lli;
 	struct ll_dentry_data *ldd;
@@ -1370,7 +1354,7 @@ ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug)
 {
 	int ret;
 
-	ret = ll_need_statahead(dir, *dentryp);
+	ret = d_need_statahead(dir, *dentryp);
 	if (ret <= 0)
 		return ret;
 
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 6cfdb9e4b74b..9100c934d222 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -155,11 +155,6 @@ void ll_free_sbi(struct super_block *sb)
 	}
 }
 
-static struct dentry_operations ll_d_root_ops = {
-	.d_compare = ll_dcompare,
-	.d_revalidate = ll_revalidate_nd,
-};
-
 static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 				    struct vfsmount *mnt)
 {
@@ -211,7 +206,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 				  OBD_CONNECT_EINPROGRESS |
 				  OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE |
 				  OBD_CONNECT_LAYOUTLOCK |
-				  OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE;
+				  OBD_CONNECT_PINGLESS |
+				  OBD_CONNECT_MAX_EASIZE |
+				  OBD_CONNECT_FLOCK_DEAD |
+				  OBD_CONNECT_DISP_STRIPE;
 
 	if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
 		data->ocd_connect_flags |= OBD_CONNECT_SOM;
@@ -579,10 +577,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 		GOTO(out_root, err = -ENOMEM);
 	}
 
-	/* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */
-	d_set_d_op(sb->s_root, &ll_d_root_ops);
-	sb->s_d_op = &ll_d_ops;
-
 	sbi->ll_sdev_orig = sb->s_dev;
 
 	/* We set sb->s_dev equal on all lustre clients in order to support
@@ -1013,6 +1007,8 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
 		GOTO(out_free, err);
 
 	sb->s_bdi = &lsi->lsi_bdi;
+	/* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */
+	sb->s_d_op = &ll_d_ops;
 
 	/* Generate a string unique to this super, in case some joker tries
 	   to mount the same fs at two mount points.
@@ -1067,7 +1063,7 @@ out_free:
 
 void ll_put_super(struct super_block *sb)
 {
-	struct config_llog_instance cfg;
+	struct config_llog_instance cfg, params_cfg;
 	struct obd_device *obd;
 	struct lustre_sb_info *lsi = s2lsi(sb);
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -1081,6 +1077,9 @@ void ll_put_super(struct super_block *sb)
 	cfg.cfg_instance = sb;
 	lustre_end_log(sb, profilenm, &cfg);
 
+	params_cfg.cfg_instance = sb;
+	lustre_end_log(sb, PARAMS_FILENAME, &params_cfg);
+
 	if (sbi->ll_md_exp) {
 		obd = class_exp2obd(sbi->ll_md_exp);
 		if (obd)
@@ -1405,7 +1404,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
 	/* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
 	if (attr->ia_valid & TIMES_SET_FLAGS) {
 		if ((!uid_eq(current_fsuid(), inode->i_uid)) &&
-		    !cfs_capable(CFS_CAP_FOWNER))
+		    !capable(CFS_CAP_FOWNER))
 			return -EPERM;
 	}
 
@@ -1877,7 +1876,7 @@ void ll_delete_inode(struct inode *inode)
 		cl_sync_file_range(inode, 0, OBD_OBJECT_EOF,
 				   CL_FSYNC_DISCARD, 1);
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	/* Workaround for LU-118 */
 	if (inode->i_data.nrpages) {
diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c
index 1767c741fb72..3580069789fc 100644
--- a/drivers/staging/lustre/lustre/llite/llite_nfs.c
+++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c
@@ -167,10 +167,10 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
 	}
 
 	result = d_obtain_alias(inode);
-	if (IS_ERR(result))
+	if (IS_ERR(result)) {
+		iput(inode);
 		return result;
-
-	ll_dops_init(result, 1, 0);
+	}
 
 	return result;
 }
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index fc8d264f6c9a..86ff708c8e3e 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -195,101 +195,107 @@ static void ll_invalidate_negative_children(struct inode *dir)
 int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		       void *data, int flag)
 {
-	int rc;
 	struct lustre_handle lockh;
+	int rc;
 
 	switch (flag) {
 	case LDLM_CB_BLOCKING:
 		ldlm_lock2handle(lock, &lockh);
 		rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
 		if (rc < 0) {
-			CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
+			CDEBUG(D_INODE, "ldlm_cli_cancel: rc = %d\n", rc);
 			return rc;
 		}
 		break;
 	case LDLM_CB_CANCELING: {
 		struct inode *inode = ll_inode_from_resource_lock(lock);
-		struct ll_inode_info *lli;
 		__u64 bits = lock->l_policy_data.l_inodebits.bits;
-		struct lu_fid *fid;
-		ldlm_mode_t mode = lock->l_req_mode;
 
 		/* Inode is set to lock->l_resource->lr_lvb_inode
 		 * for mdc - bug 24555 */
 		LASSERT(lock->l_ast_data == NULL);
 
-		/* Invalidate all dentries associated with this inode */
 		if (inode == NULL)
 			break;
 
+		/* Invalidate all dentries associated with this inode */
 		LASSERT(lock->l_flags & LDLM_FL_CANCELING);
 
-		if (bits & MDS_INODELOCK_XATTR)
+		if (!fid_res_name_eq(ll_inode2fid(inode),
+				     &lock->l_resource->lr_name)) {
+			LDLM_ERROR(lock, "data mismatch with object "DFID"(%p)",
+				   PFID(ll_inode2fid(inode)), inode);
+			LBUG();
+		}
+
+		if (bits & MDS_INODELOCK_XATTR) {
 			ll_xattr_cache_destroy(inode);
+			bits &= ~MDS_INODELOCK_XATTR;
+		}
 
 		/* For OPEN locks we differentiate between lock modes
 		 * LCK_CR, LCK_CW, LCK_PR - bug 22891 */
-		if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
-			    MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM))
-			ll_have_md_lock(inode, &bits, LCK_MINMODE);
-
 		if (bits & MDS_INODELOCK_OPEN)
-			ll_have_md_lock(inode, &bits, mode);
-
-		fid = ll_inode2fid(inode);
-		if (!fid_res_name_eq(fid, &lock->l_resource->lr_name))
-			LDLM_ERROR(lock, "data mismatch with object "
-				   DFID" (%p)", PFID(fid), inode);
+			ll_have_md_lock(inode, &bits, lock->l_req_mode);
 
 		if (bits & MDS_INODELOCK_OPEN) {
-			int flags = 0;
+			fmode_t fmode;
+
 			switch (lock->l_req_mode) {
 			case LCK_CW:
-				flags = FMODE_WRITE;
+				fmode = FMODE_WRITE;
 				break;
 			case LCK_PR:
-				flags = FMODE_EXEC;
+				fmode = FMODE_EXEC;
 				break;
 			case LCK_CR:
-				flags = FMODE_READ;
+				fmode = FMODE_READ;
 				break;
 			default:
-				CERROR("Unexpected lock mode for OPEN lock "
-				       "%d, inode %ld\n", lock->l_req_mode,
-				       inode->i_ino);
+				LDLM_ERROR(lock, "bad lock mode for OPEN lock");
+				LBUG();
 			}
-			ll_md_real_close(inode, flags);
+
+			ll_md_real_close(inode, fmode);
 		}
 
-		lli = ll_i2info(inode);
+		if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
+			    MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM))
+			ll_have_md_lock(inode, &bits, LCK_MINMODE);
+
 		if (bits & MDS_INODELOCK_LAYOUT) {
-			struct cl_object_conf conf = { { 0 } };
+			struct cl_object_conf conf = {
+				.coc_opc = OBJECT_CONF_INVALIDATE,
+				.coc_inode = inode,
+			};
 
-			conf.coc_opc = OBJECT_CONF_INVALIDATE;
-			conf.coc_inode = inode;
 			rc = ll_layout_conf(inode, &conf);
-			if (rc)
-				CDEBUG(D_INODE, "invaliding layout %d.\n", rc);
+			if (rc < 0)
+				CDEBUG(D_INODE, "cannot invalidate layout of "
+				       DFID": rc = %d\n",
+				       PFID(ll_inode2fid(inode)), rc);
 		}
 
 		if (bits & MDS_INODELOCK_UPDATE) {
+			struct ll_inode_info *lli = ll_i2info(inode);
+
 			spin_lock(&lli->lli_lock);
 			lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
 			spin_unlock(&lli->lli_lock);
 		}
 
-		if (S_ISDIR(inode->i_mode) &&
-		     (bits & MDS_INODELOCK_UPDATE)) {
+		if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) {
 			CDEBUG(D_INODE, "invalidating inode %lu\n",
 			       inode->i_ino);
 			truncate_inode_pages(inode->i_mapping, 0);
 			ll_invalidate_negative_children(inode);
 		}
 
-		if (inode->i_sb->s_root &&
-		    inode != inode->i_sb->s_root->d_inode &&
-		    (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)))
+		if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) &&
+		    inode->i_sb->s_root != NULL &&
+		    inode != inode->i_sb->s_root->d_inode)
 			ll_invalidate_aliases(inode);
+
 		iput(inode);
 		break;
 	}
@@ -400,11 +406,16 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry)
 struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
 {
 	struct dentry *new;
+	int rc;
 
 	if (inode) {
 		new = ll_find_alias(inode, de);
 		if (new) {
-			ll_dops_init(new, 1, 1);
+			rc = ll_d_init(new);
+			if (rc < 0) {
+				dput(new);
+				return ERR_PTR(rc);
+			}
 			d_move(new, de);
 			iput(inode);
 			CDEBUG(D_DENTRY,
@@ -413,8 +424,9 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
 			return new;
 		}
 	}
-	ll_dops_init(de, 1, 1);
-	__d_lustre_invalidate(de);
+	rc = ll_d_init(de);
+	if (rc < 0)
+		return ERR_PTR(rc);
 	d_add(de, inode);
 	CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n",
 	       de, de->d_inode, d_count(de), de->d_flags);
@@ -455,8 +467,20 @@ int ll_lookup_it_finish(struct ptlrpc_request *request,
 	/* Only hash *de if it is unhashed (new dentry).
 	 * Atoimc_open may passin hashed dentries for open.
 	 */
-	if (d_unhashed(*de))
-		*de = ll_splice_alias(inode, *de);
+	if (d_unhashed(*de)) {
+		struct dentry *alias;
+
+		alias = ll_splice_alias(inode, *de);
+		if (IS_ERR(alias))
+			return PTR_ERR(alias);
+		*de = alias;
+	} else if (!it_disposition(it, DISP_LOOKUP_NEG)  &&
+		   !it_disposition(it, DISP_OPEN_CREATE)) {
+		/* With DISP_OPEN_CREATE dentry will
+		   instantiated in ll_create_it. */
+		LASSERT((*de)->d_inode == NULL);
+		d_instantiate(*de, inode);
+	}
 
 	if (!it_disposition(it, DISP_LOOKUP_NEG)) {
 		/* we have lookup look - unhide dentry */
@@ -505,16 +529,6 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 
 	ll_frob_intent(&it, &lookup_it);
 
-	/* As do_lookup is called before follow_mount, root dentry may be left
-	 * not valid, revalidate it here. */
-	if (parent->i_sb->s_root && (parent->i_sb->s_root->d_inode == parent) &&
-	    (it->it_op & (IT_OPEN | IT_CREAT))) {
-		rc = ll_inode_revalidate_it(parent->i_sb->s_root, it,
-					    MDS_INODELOCK_LOOKUP);
-		if (rc)
-			return ERR_PTR(rc);
-	}
-
 	if (it->it_op == IT_GETATTR) {
 		rc = ll_statahead_enter(parent, &dentry, 0);
 		if (rc == 1) {
@@ -584,12 +598,8 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
 	       parent->i_generation, parent, flags);
 
 	/* Optimize away (CREATE && !OPEN). Let .create handle the race. */
-	if ((flags & LOOKUP_CREATE ) && !(flags & LOOKUP_OPEN)) {
-		ll_dops_init(dentry, 1, 1);
-		__d_lustre_invalidate(dentry);
-		d_add(dentry, NULL);
+	if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN))
 		return NULL;
-	}
 
 	if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE))
 		itp = NULL;
diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
index e9ba38a553cf..ca8fa4eacf66 100644
--- a/drivers/staging/lustre/lustre/llite/rw.c
+++ b/drivers/staging/lustre/lustre/llite/rw.c
@@ -135,7 +135,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
 		}
 
 		/*
-		 * Loop-back driver calls ->prepare_write() and ->sendfile()
+		 * Loop-back driver calls ->prepare_write().
 		 * methods directly, bypassing file system ->write() operation,
 		 * so cl_io has to be created here.
 		 */
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index f6b5f4b95f37..ad61ad446f22 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -877,9 +877,6 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry,
 	if (d_mountpoint(dentry))
 		return 1;
 
-	if (unlikely(dentry == dentry->d_sb->s_root))
-		return 1;
-
 	entry->se_inode = igrab(inode);
 	rc = md_revalidate_lock(ll_i2mdexp(dir), &it, ll_inode2fid(inode),NULL);
 	if (rc == 1) {
@@ -1588,8 +1585,15 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 						ll_inode2fid(inode), &bits);
 			if (rc == 1) {
 				if ((*dentryp)->d_inode == NULL) {
-					*dentryp = ll_splice_alias(inode,
+					struct dentry *alias;
+
+					alias = ll_splice_alias(inode,
 								   *dentryp);
+					if (IS_ERR(alias)) {
+						ll_sai_unplug(sai, entry);
+						return PTR_ERR(alias);
+					}
+					*dentryp = alias;
 				} else if ((*dentryp)->d_inode != inode) {
 					/* revalidate, but inode is recreated */
 					CDEBUG(D_READA,
diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
index 93cbfbb7e7f7..50383d365a0f 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -51,7 +51,7 @@ static struct vvp_io *cl2vvp_io(const struct lu_env *env,
 				const struct cl_io_slice *slice);
 
 /**
- * True, if \a io is a normal io, False for sendfile() / splice_{read|write}
+ * True, if \a io is a normal io, False for splice_{read,write}
  */
 int cl_is_normalio(const struct lu_env *env, const struct cl_io *io)
 {
@@ -474,20 +474,6 @@ static void vvp_io_setattr_fini(const struct lu_env *env,
 	vvp_io_fini(env, ios);
 }
 
-static ssize_t lustre_generic_file_read(struct file *file,
-					struct ccc_io *vio, loff_t *ppos)
-{
-	return generic_file_aio_read(vio->cui_iocb, vio->cui_iov,
-				     vio->cui_nrsegs, *ppos);
-}
-
-static ssize_t lustre_generic_file_write(struct file *file,
-					struct ccc_io *vio, loff_t *ppos)
-{
-	return generic_file_aio_write(vio->cui_iocb, vio->cui_iov,
-				      vio->cui_nrsegs, *ppos);
-}
-
 static int vvp_io_read_start(const struct lu_env *env,
 			     const struct cl_io_slice *ios)
 {
@@ -540,8 +526,11 @@ static int vvp_io_read_start(const struct lu_env *env,
 	file_accessed(file);
 	switch (vio->cui_io_subtype) {
 	case IO_NORMAL:
-		 result = lustre_generic_file_read(file, cio, &pos);
-		 break;
+		LASSERT(cio->cui_iocb->ki_pos == pos);
+		result = generic_file_aio_read(cio->cui_iocb,
+					       cio->cui_iov, cio->cui_nrsegs,
+					       cio->cui_iocb->ki_pos);
+		break;
 	case IO_SPLICE:
 		result = generic_file_splice_read(file, &pos,
 				vio->u.splice.cui_pipe, cnt,
@@ -586,7 +575,6 @@ static int vvp_io_write_start(const struct lu_env *env,
 	struct cl_io       *io    = ios->cis_io;
 	struct cl_object   *obj   = io->ci_obj;
 	struct inode       *inode = ccc_object_inode(obj);
-	struct file	*file  = cio->cui_fd->fd_file;
 	ssize_t result = 0;
 	loff_t pos = io->u.ci_wr.wr.crw_pos;
 	size_t cnt = io->u.ci_wr.wr.crw_count;
@@ -601,6 +589,8 @@ static int vvp_io_write_start(const struct lu_env *env,
 		 */
 		pos = io->u.ci_wr.wr.crw_pos = i_size_read(inode);
 		cio->cui_iocb->ki_pos = pos;
+	} else {
+		LASSERT(cio->cui_iocb->ki_pos == pos);
 	}
 
 	CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt);
@@ -608,8 +598,9 @@ static int vvp_io_write_start(const struct lu_env *env,
 	if (cio->cui_iov == NULL) /* from a temp io in ll_cl_init(). */
 		result = 0;
 	else
-		result = lustre_generic_file_write(file, cio, &pos);
-
+		result = generic_file_aio_write(cio->cui_iocb,
+						cio->cui_iov, cio->cui_nrsegs,
+						cio->cui_iocb->ki_pos);
 	if (result > 0) {
 		if (result < cnt)
 			io->ci_continue = 0;
diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c
index 3a7d03c12dd9..b1ed4d9ea6be 100644
--- a/drivers/staging/lustre/lustre/llite/xattr.c
+++ b/drivers/staging/lustre/lustre/llite/xattr.c
@@ -95,7 +95,7 @@ int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
 
 	if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
 		return -EOPNOTSUPP;
-	if (xattr_type == XATTR_TRUSTED_T && !cfs_capable(CFS_CAP_SYS_ADMIN))
+	if (xattr_type == XATTR_TRUSTED_T && !capable(CFS_CAP_SYS_ADMIN))
 		return -EPERM;
 	if (xattr_type == XATTR_OTHER_T)
 		return -EOPNOTSUPP;
@@ -183,17 +183,11 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 		valid |= rce_ops2valid(rce->rce_ops);
 	}
 #endif
-	if (sbi->ll_xattr_cache_enabled &&
-	    (rce == NULL || rce->rce_ops == RMT_LSETFACL)) {
-		rc = ll_xattr_cache_update(inode, name, pv, size, valid, flags);
-	} else {
 		oc = ll_mdscapa_get(inode);
 		rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
 				valid, name, pv, size, 0, flags,
 				ll_i2suppgid(inode), &req);
 		capa_put(oc);
-	}
-
 #ifdef CONFIG_FS_POSIX_ACL
 	if (new_value != NULL)
 		lustre_posix_acl_xattr_free(new_value, size);
@@ -292,6 +286,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 	void *xdata;
 	struct obd_capa *oc;
 	struct rmtacl_ctl_entry *rce = NULL;
+	struct ll_inode_info *lli = ll_i2info(inode);
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
 	       inode->i_ino, inode->i_generation, inode);
@@ -339,7 +334,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 	 */
 	if (xattr_type == XATTR_ACL_ACCESS_T &&
 	    !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
-		struct ll_inode_info *lli = ll_i2info(inode);
+
 		struct posix_acl *acl;
 
 		spin_lock(&lli->lli_lock);
@@ -358,13 +353,27 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 #endif
 
 do_getxattr:
-	if (sbi->ll_xattr_cache_enabled && (rce == NULL ||
-					    rce->rce_ops == RMT_LGETFACL ||
-					    rce->rce_ops == RMT_LSETFACL)) {
+	if (sbi->ll_xattr_cache_enabled && xattr_type != XATTR_ACL_ACCESS_T) {
 		rc = ll_xattr_cache_get(inode, name, buffer, size, valid);
+		if (rc == -EAGAIN)
+			goto getxattr_nocache;
 		if (rc < 0)
 			GOTO(out_xattr, rc);
+
+		/* Add "system.posix_acl_access" to the list */
+		if (lli->lli_posix_acl != NULL && valid & OBD_MD_FLXATTRLS) {
+			if (size == 0) {
+				rc += sizeof(XATTR_NAME_ACL_ACCESS);
+			} else if (size - rc >= sizeof(XATTR_NAME_ACL_ACCESS)) {
+				memcpy(buffer + rc, XATTR_NAME_ACL_ACCESS,
+				       sizeof(XATTR_NAME_ACL_ACCESS));
+				rc += sizeof(XATTR_NAME_ACL_ACCESS);
+			} else {
+				GOTO(out_xattr, rc = -ERANGE);
+			}
+		}
 	} else {
+getxattr_nocache:
 		oc = ll_mdscapa_get(inode);
 		rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
 				valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c
index 3e3be1f13502..616d5bdf854d 100644
--- a/drivers/staging/lustre/lustre/llite/xattr_cache.c
+++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c
@@ -98,13 +98,13 @@ static int ll_xattr_cache_find(struct list_head *cache,
 }
 
 /**
- * This adds or updates an xattr.
+ * This adds an xattr.
  *
  * Add @xattr_name attr with @xattr_val value and @xattr_val_len length,
- * if the attribute already exists, then update its value.
  *
  * \retval 0       success
  * \retval -ENOMEM if no memory could be allocated for the cached attr
+ * \retval -EPROTO if duplicate xattr is being added
  */
 static int ll_xattr_cache_add(struct list_head *cache,
 			      const char *xattr_name,
@@ -116,27 +116,8 @@ static int ll_xattr_cache_add(struct list_head *cache,
 
 
 	if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) {
-		/* Found a cached EA, update it */
-
-		if (xattr_val_len != xattr->xe_vallen) {
-			char *val;
-			OBD_ALLOC(val, xattr_val_len);
-			if (val == NULL) {
-				CDEBUG(D_CACHE,
-				       "failed to allocate %u bytes for xattr %s update\n",
-				       xattr_val_len, xattr_name);
-				return -ENOMEM;
-			}
-			OBD_FREE(xattr->xe_value, xattr->xe_vallen);
-			xattr->xe_value = val;
-			xattr->xe_vallen = xattr_val_len;
-		}
-		memcpy(xattr->xe_value, xattr_val, xattr_val_len);
-
-		CDEBUG(D_CACHE, "update: [%s]=%.*s\n", xattr_name,
-			xattr_val_len, xattr_val);
-
-		return 0;
+		CDEBUG(D_CACHE, "duplicate xattr: [%s]\n", xattr_name);
+		return -EPROTO;
 	}
 
 	OBD_SLAB_ALLOC_PTR_GFP(xattr, xattr_kmem, __GFP_IO);
@@ -292,7 +273,7 @@ int ll_xattr_cache_destroy(struct inode *inode)
 }
 
 /**
- * Match or enqueue a PR or PW LDLM lock.
+ * Match or enqueue a PR lock.
  *
  * Find or request an LDLM lock with xattr data.
  * Since LDLM does not provide API for atomic match_or_enqueue,
@@ -322,9 +303,7 @@ static int ll_xattr_find_get_lock(struct inode *inode,
 
 	mutex_lock(&lli->lli_xattrs_enq_lock);
 	/* Try matching first. */
-	mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0,
-			       oit->it_op == IT_SETXATTR ? LCK_PW :
-							   (LCK_PR | LCK_PW));
+	mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0, LCK_PR);
 	if (mode != 0) {
 		/* fake oit in mdc_revalidate_lock() manner */
 		oit->d.lustre.it_lock_handle = lockh.cookie;
@@ -340,13 +319,7 @@ static int ll_xattr_find_get_lock(struct inode *inode,
 		return PTR_ERR(op_data);
 	}
 
-	op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS |
-			    OBD_MD_FLXATTRLOCKED;
-#ifdef CONFIG_FS_POSIX_ACL
-	/* If working with ACLs, we would like to cache local ACLs */
-	if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
-		op_data->op_valid |= OBD_MD_FLRMTLGETFACL;
-#endif
+	op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS;
 
 	rc = md_enqueue(exp, &einfo, oit, op_data, &lockh, NULL, 0, NULL, 0);
 	ll_finish_md_op_data(op_data);
@@ -409,7 +382,11 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
 	if (oit->d.lustre.it_status < 0) {
 		CDEBUG(D_CACHE, "getxattr intent returned %d for fid "DFID"\n",
 		       oit->d.lustre.it_status, PFID(ll_inode2fid(inode)));
-		GOTO(out_destroy, rc = oit->d.lustre.it_status);
+		rc = oit->d.lustre.it_status;
+		/* xattr data is so large that we don't want to cache it */
+		if (rc == -ERANGE)
+			rc = -EAGAIN;
+		GOTO(out_destroy, rc);
 	}
 
 	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
@@ -447,6 +424,11 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
 			rc = -EPROTO;
 		} else if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_XATTR_ENOMEM)) {
 			rc = -ENOMEM;
+		} else if (!strcmp(xdata, XATTR_NAME_ACL_ACCESS)) {
+			/* Filter out ACL ACCESS since it's cached separately */
+			CDEBUG(D_CACHE, "not caching %s\n",
+			       XATTR_NAME_ACL_ACCESS);
+			rc = 0;
 		} else {
 			rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval,
 						*xsizes);
@@ -467,8 +449,7 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
 
 	GOTO(out_maybe_drop, rc);
 out_maybe_drop:
-	/* drop lock on error or getxattr */
-	if (rc != 0 || oit->it_op != IT_SETXATTR)
+
 		ll_intent_drop_lock(oit);
 
 	if (rc != 0)
@@ -553,65 +534,3 @@ out:
 
 	return rc;
 }
-
-
-/**
- * Set/update an xattr value or remove xattr using the write-through cache.
- *
- * Set/update the xattr value (if @valid has OBD_MD_FLXATTR) of @name to @newval
- * or
- * remove the xattr @name (@valid has OBD_MD_FLXATTRRM set) from @inode.
- * @flags is either XATTR_CREATE or XATTR_REPLACE as defined by setxattr(2)
- *
- * \retval 0        no error occured
- * \retval -EPROTO  network protocol error
- * \retval -ENOMEM  not enough memory for the cache
- * \retval -ERANGE  the buffer is not large enough
- * \retval -ENODATA no such attr (in the removal case)
- */
-int ll_xattr_cache_update(struct inode *inode,
-			const char *name,
-			const char *newval,
-			size_t size,
-			__u64 valid,
-			int flags)
-{
-	struct lookup_intent oit = { .it_op = IT_SETXATTR };
-	struct ll_sb_info *sbi = ll_i2sbi(inode);
-	struct ptlrpc_request *req = NULL;
-	struct ll_inode_info *lli = ll_i2info(inode);
-	struct obd_capa *oc;
-	int rc;
-
-
-
-	LASSERT(!!(valid & OBD_MD_FLXATTR) ^ !!(valid & OBD_MD_FLXATTRRM));
-
-	rc = ll_xattr_cache_refill(inode, &oit);
-	if (rc)
-		return rc;
-
-	oc = ll_mdscapa_get(inode);
-	rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
-			valid | OBD_MD_FLXATTRLOCKED, name, newval,
-			size, 0, flags, ll_i2suppgid(inode), &req);
-	capa_put(oc);
-
-	if (rc) {
-		ll_intent_drop_lock(&oit);
-		GOTO(out, rc);
-	}
-
-	if (valid & OBD_MD_FLXATTR)
-		rc = ll_xattr_cache_add(&lli->lli_xattrs, name, newval, size);
-	else if (valid & OBD_MD_FLXATTRRM)
-		rc = ll_xattr_cache_del(&lli->lli_xattrs, name);
-
-	ll_intent_drop_lock(&oit);
-	GOTO(out, rc);
-out:
-	up_write(&lli->lli_xattrs_list_rwsem);
-	ptlrpc_req_finished(req);
-
-	return rc;
-}
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index 56dedceaf0a0..9ba5a0a57390 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -119,7 +119,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm,
 	CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n",
 	       PFID(&body->fid1), tgt->ltd_idx);
 
-	it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
 	rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
 			    flags, &req, cb_blocking, extra_lock_flags);
 	if (rc)
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index 1bddd8f62fbf..3ba0a0a1d945 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -1744,7 +1744,6 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 	it->d.lustre.it_data = NULL;
 	fid1 = body->fid1;
 
-	it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
 	ptlrpc_req_finished(req);
 
 	tgt = lmv_find_target(lmv, &fid1);
@@ -2593,7 +2592,7 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
 
 int lmv_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req)
+			     struct lookup_intent *it)
 {
 	struct obd_device       *obd = exp->exp_obd;
 	struct lmv_obd	  *lmv = &obd->u.lmv;
@@ -2603,7 +2602,7 @@ int lmv_set_open_replay_data(struct obd_export *exp,
 	if (IS_ERR(tgt))
 		return PTR_ERR(tgt);
 
-	return md_set_open_replay_data(tgt->ltd_exp, och, open_req);
+	return md_set_open_replay_data(tgt->ltd_exp, och, it);
 }
 
 int lmv_clear_open_replay_data(struct obd_export *exp,
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index 5a6ab70ed0a1..65133ea308b6 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -194,6 +194,7 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
 		sub_io->ci_lockreq = io->ci_lockreq;
 		sub_io->ci_type    = io->ci_type;
 		sub_io->ci_no_srvlock = io->ci_no_srvlock;
+		sub_io->ci_noatime = io->ci_noatime;
 
 		lov_sub_enter(sub);
 		result = cl_io_sub_init(sub->sub_env, sub_io,
diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c
index df8b5b5b7cf4..fe0b70a097aa 100644
--- a/drivers/staging/lustre/lustre/lov/lov_object.c
+++ b/drivers/staging/lustre/lustre/lov/lov_object.c
@@ -122,8 +122,8 @@ static struct cl_object *lov_sub_find(const struct lu_env *env,
 }
 
 static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
-			struct cl_object *stripe,
-			struct lov_layout_raid0 *r0, int idx)
+			struct cl_object *stripe, struct lov_layout_raid0 *r0,
+			int idx)
 {
 	struct cl_object_header *hdr;
 	struct cl_object_header *subhdr;
@@ -144,7 +144,6 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
 
 	hdr    = cl_object_header(lov2cl(lov));
 	subhdr = cl_object_header(stripe);
-	parent = subhdr->coh_parent;
 
 	oinfo = lov->lo_lsm->lsm_oinfo[idx];
 	CDEBUG(D_INODE, DFID"@%p[%d] -> "DFID"@%p: ostid: "DOSTID
@@ -153,8 +152,12 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
 	       PFID(&hdr->coh_lu.loh_fid), hdr, POSTID(&oinfo->loi_oi),
 	       oinfo->loi_ost_idx, oinfo->loi_ost_gen);
 
+	/* reuse ->coh_attr_guard to protect coh_parent change */
+	spin_lock(&subhdr->coh_attr_guard);
+	parent = subhdr->coh_parent;
 	if (parent == NULL) {
 		subhdr->coh_parent = hdr;
+		spin_unlock(&subhdr->coh_attr_guard);
 		subhdr->coh_nesting = hdr->coh_nesting + 1;
 		lu_object_ref_add(&stripe->co_lu, "lov-parent", lov);
 		r0->lo_sub[idx] = cl2lovsub(stripe);
@@ -166,6 +169,7 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
 		struct lov_object *old_lov;
 		unsigned int mask = D_INODE;
 
+		spin_unlock(&subhdr->coh_attr_guard);
 		old_obj = lu_object_locate(&parent->coh_lu, &lov_device_type);
 		LASSERT(old_obj != NULL);
 		old_lov = cl2lov(lu2cl(old_obj));
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
index 998ea1cbc7bb..926c35a25ceb 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
@@ -131,6 +131,10 @@ static struct lu_device *lovsub_device_free(const struct lu_env *env,
 	struct lovsub_device *lsd  = lu2lovsub_dev(d);
 	struct lu_device     *next = cl2lu_dev(lsd->acid_next);
 
+	if (atomic_read(&d->ld_ref) && d->ld_site) {
+		LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL);
+		lu_site_print(env, d->ld_site, &msgdata, lu_cdebug_printer);
+	}
 	cl_device_fini(lu2cl_dev(d));
 	OBD_FREE_PTR(lsd);
 	return next;
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
index 506982996c0e..c78bf003c2c5 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h
+++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
@@ -101,7 +101,7 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 		struct lustre_handle *lockh, void *lmm, int lmmsize,
 		struct ptlrpc_request **req, __u64 extra_lock_flags);
 
-int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid,
+int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid,
 			    struct list_head *cancels, ldlm_mode_t mode,
 			    __u64 bits);
 /* mdc/mdc_request.c */
@@ -122,7 +122,7 @@ int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md);
 
 int mdc_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req);
+			     struct lookup_intent *it);
 
 int mdc_clear_open_replay_data(struct obd_export *exp,
 			       struct obd_client_handle *och);
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
index 91f6876dac3f..5b9f37141512 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
@@ -197,7 +197,7 @@ static __u64 mds_pack_open_flags(__u64 flags, __u32 mode)
 	if (flags & FMODE_EXEC)
 		cr_flags |= MDS_FMODE_EXEC;
 #endif
-	if (flags & O_LOV_DELAY_CREATE)
+	if (cl_is_lov_delay_create(flags))
 		cr_flags |= MDS_OPEN_DELAY_CREATE;
 
 	if (flags & O_NONBLOCK)
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
index 8aa7c80c2002..b0d0e2a1744e 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
@@ -37,15 +37,15 @@
 #define DEBUG_SUBSYSTEM S_MDC
 
 # include <linux/module.h>
-# include <linux/pagemap.h>
-# include <linux/miscdevice.h>
 
-#include <lustre_acl.h>
+#include <linux/lustre_intent.h>
+#include <obd.h>
 #include <obd_class.h>
 #include <lustre_dlm.h>
-/* fid_res_name_eq() */
-#include <lustre_fid.h>
-#include <lprocfs_status.h>
+#include <lustre_fid.h> /* fid_res_name_eq() */
+#include <lustre_mdc.h>
+#include <lustre_net.h>
+#include <lustre_req_layout.h>
 #include "mdc_internal.h"
 
 struct mdc_getattr_args {
@@ -160,6 +160,8 @@ ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags,
 	ldlm_mode_t rc;
 
 	fid_build_reg_res_name(fid, &res_id);
+	/* LU-4405: Clear bits not supported by server */
+	policy->l_inodebits.bits &= exp_connect_ibits(exp);
 	rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags,
 			     &res_id, type, policy, mode, lockh, 0);
 	return rc;
@@ -334,9 +336,9 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp,
 			     max(lmmsize, obddev->u.cli.cl_default_mds_easize));
 
 	rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
-	if (rc) {
+	if (rc < 0) {
 		ptlrpc_request_free(req);
-		return NULL;
+		return ERR_PTR(rc);
 	}
 
 	spin_lock(&req->rq_lock);
@@ -378,13 +380,6 @@ mdc_intent_getxattr_pack(struct obd_export *exp,
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
-	if (it->it_op == IT_SETXATTR)
-		/* If we want to upgrade to LCK_PW, let's cancel LCK_PR
-		 * locks now. This avoids unnecessary ASTs. */
-		count = mdc_resource_get_unused(exp, &op_data->op_fid1,
-						&cancels, LCK_PW,
-						MDS_INODELOCK_XATTR);
-
 	rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
@@ -646,7 +641,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 			 * happens immediately after swabbing below, new reply
 			 * is swabbed by that handler correctly.
 			 */
-			mdc_set_open_replay_data(NULL, NULL, req);
+			mdc_set_open_replay_data(NULL, NULL, it);
 		}
 
 		if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) {
@@ -758,6 +753,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 		/* install lvb_data */
 		lock_res_and_lock(lock);
 		if (lock->l_lvb_data == NULL) {
+			lock->l_lvb_type = LVB_T_LAYOUT;
 			lock->l_lvb_data = lmm;
 			lock->l_lvb_len = lvb_len;
 			lmm = NULL;
@@ -842,7 +838,7 @@ resend:
 			return -EOPNOTSUPP;
 		req = mdc_intent_layout_pack(exp, it, op_data);
 		lvb_type = LVB_T_LAYOUT;
-	} else if (it->it_op & (IT_GETXATTR | IT_SETXATTR)) {
+	} else if (it->it_op & IT_GETXATTR) {
 		req = mdc_intent_getxattr_pack(exp, it, op_data);
 	} else {
 		LBUG();
@@ -973,7 +969,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
 	if (fid_is_sane(&op_data->op_fid2) &&
 	    it->it_create_mode & M_CHECK_STALE &&
 	    it->it_op != IT_GETATTR) {
-		it_set_disposition(it, DISP_ENQ_COMPLETE);
 
 		/* Also: did we find the same inode? */
 		/* sever can return one of two fids:
@@ -1068,7 +1063,23 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
 		fid_build_reg_res_name(fid, &res_id);
 		switch (it->it_op) {
 		case IT_GETATTR:
-			policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
+			/* File attributes are held under multiple bits:
+			 * nlink is under lookup lock, size and times are
+			 * under UPDATE lock and recently we've also got
+			 * a separate permissions lock for owner/group/acl that
+			 * were protected by lookup lock before.
+			 * Getattr must provide all of that information,
+			 * so we need to ensure we have all of those locks.
+			 * Unfortunately, if the bits are split across multiple
+			 * locks, there's no easy way to match all of them here,
+			 * so an extra RPC would be performed to fetch all
+			 * of those bits at once for now. */
+			/* For new MDTs(> 2.4), UPDATE|PERM should be enough,
+			 * but for old MDTs (< 2.4), permission is covered
+			 * by LOOKUP lock, so it needs to match all bits here.*/
+			policy.l_inodebits.bits = MDS_INODELOCK_UPDATE |
+						  MDS_INODELOCK_LOOKUP |
+						  MDS_INODELOCK_PERM;
 			break;
 		case IT_LAYOUT:
 			policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT;
@@ -1077,10 +1088,11 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
 			policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP;
 			break;
 		}
-		mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
-				       LDLM_FL_BLOCK_GRANTED, &res_id,
+
+		mode = mdc_lock_match(exp, LDLM_FL_BLOCK_GRANTED, fid,
 				       LDLM_IBITS, &policy,
-				       LCK_CR|LCK_CW|LCK_PR|LCK_PW, &lockh, 0);
+				      LCK_CR | LCK_CW | LCK_PR | LCK_PW,
+				      &lockh);
 	}
 
 	if (mode) {
@@ -1127,6 +1139,12 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 		    ldlm_blocking_callback cb_blocking,
 		    __u64 extra_lock_flags)
 {
+	struct ldlm_enqueue_info einfo = {
+		.ei_type	= LDLM_IBITS,
+		.ei_mode	= it_to_lock_mode(it),
+		.ei_cb_bl	= cb_blocking,
+		.ei_cb_cp	= ldlm_completion_ast,
+	};
 	struct lustre_handle lockh;
 	int rc = 0;
 
@@ -1152,42 +1170,19 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 			return rc;
 	}
 
-	/* lookup_it may be called only after revalidate_it has run, because
-	 * revalidate_it cannot return errors, only zero.  Returning zero causes
-	 * this call to lookup, which *can* return an error.
-	 *
-	 * We only want to execute the request associated with the intent one
-	 * time, however, so don't send the request again.  Instead, skip past
-	 * this and use the request from revalidate.  In this case, revalidate
-	 * never dropped its reference, so the refcounts are all OK */
-	if (!it_disposition(it, DISP_ENQ_COMPLETE)) {
-		struct ldlm_enqueue_info einfo = {
-			.ei_type	= LDLM_IBITS,
-			.ei_mode	= it_to_lock_mode(it),
-			.ei_cb_bl	= cb_blocking,
-			.ei_cb_cp	= ldlm_completion_ast,
-		};
-
-		/* For case if upper layer did not alloc fid, do it now. */
-		if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
-			rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
-			if (rc < 0) {
-				CERROR("Can't alloc new fid, rc %d\n", rc);
-				return rc;
-			}
-		}
-		rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh,
-				 lmm, lmmsize, NULL, extra_lock_flags);
-		if (rc < 0)
+	/* For case if upper layer did not alloc fid, do it now. */
+	if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
+		rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
+		if (rc < 0) {
+			CERROR("Can't alloc new fid, rc %d\n", rc);
 			return rc;
-	} else if (!fid_is_sane(&op_data->op_fid2) ||
-		   !(it->it_create_mode & M_CHECK_STALE)) {
-		/* DISP_ENQ_COMPLETE set means there is extra reference on
-		 * request referenced from this intent, saved for subsequent
-		 * lookup.  This path is executed when we proceed to this
-		 * lookup, so we clear DISP_ENQ_COMPLETE */
-		it_clear_disposition(it, DISP_ENQ_COMPLETE);
+		}
 	}
+	rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh, lmm, lmmsize, NULL,
+			 extra_lock_flags);
+	if (rc < 0)
+		return rc;
+
 	*reqp = it->d.lustre.it_data;
 	rc = mdc_finish_intent_lock(exp, *reqp, op_data, it, &lockh);
 	return rc;
@@ -1269,8 +1264,8 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 
 	fid_build_reg_res_name(&op_data->op_fid1, &res_id);
 	req = mdc_intent_getattr_pack(exp, it, op_data);
-	if (!req)
-		return -ENOMEM;
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	rc = mdc_enter_request(&obddev->u.cli);
 	if (rc != 0) {
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
index 9f3a345f34e0..d79aa1641fef 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
@@ -66,7 +66,7 @@ static int mdc_reint(struct ptlrpc_request *request,
 /* Find and cancel locally locks matched by inode @bits & @mode in the resource
  * found by @fid. Found locks are added into @cancel list. Returns the amount of
  * locks added to @cancels list. */
-int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid,
+int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid,
 			    struct list_head *cancels, ldlm_mode_t mode,
 			    __u64 bits)
 {
@@ -165,6 +165,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
 			req->rq_cb_data = *mod;
 			(*mod)->mod_open_req = req;
 			req->rq_commit_cb = mdc_commit_open;
+			(*mod)->mod_is_create = true;
 			/**
 			 * Take an extra reference on \var mod, it protects \var
 			 * mod from being freed on eviction (commit callback is
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 83013927e131..d9ddb3934919 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -355,10 +355,32 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 				     input_size);
 	}
 
-	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, opcode);
-	if (rc) {
-		ptlrpc_request_free(req);
-		return rc;
+	/* Flush local XATTR locks to get rid of a possible cancel RPC */
+	if (opcode == MDS_REINT && fid_is_sane(fid) &&
+	    exp->exp_connect_data.ocd_ibits_known & MDS_INODELOCK_XATTR) {
+		LIST_HEAD(cancels);
+		int count;
+
+		/* Without that packing would fail */
+		if (input_size == 0)
+			req_capsule_set_size(&req->rq_pill, &RMF_EADATA,
+					     RCL_CLIENT, 0);
+
+		count = mdc_resource_get_unused(exp, fid,
+						&cancels, LCK_EX,
+						MDS_INODELOCK_XATTR);
+
+		rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
+		if (rc) {
+			ptlrpc_request_free(req);
+			return rc;
+		}
+	} else {
+		rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, opcode);
+		if (rc) {
+			ptlrpc_request_free(req);
+			return rc;
+		}
 	}
 
 	if (opcode == MDS_REINT) {
@@ -700,11 +722,12 @@ void mdc_commit_open(struct ptlrpc_request *req)
 
 int mdc_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req)
+			     struct lookup_intent *it)
 {
 	struct md_open_data   *mod;
 	struct mdt_rec_create *rec;
 	struct mdt_body       *body;
+	struct ptlrpc_request *open_req = it->d.lustre.it_data;
 	struct obd_import     *imp = open_req->rq_import;
 
 	if (!open_req->rq_replay)
@@ -738,6 +761,8 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 		spin_lock(&open_req->rq_lock);
 		och->och_mod = mod;
 		mod->mod_och = och;
+		mod->mod_is_create = it_disposition(it, DISP_OPEN_CREATE) ||
+				     it_disposition(it, DISP_OPEN_STRIPE);
 		mod->mod_open_req = open_req;
 		open_req->rq_cb_data = mod;
 		open_req->rq_commit_cb = mdc_commit_open;
@@ -758,6 +783,23 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 	return 0;
 }
 
+static void mdc_free_open(struct md_open_data *mod)
+{
+	int committed = 0;
+
+	if (mod->mod_is_create == 0 &&
+	    imp_connect_disp_stripe(mod->mod_open_req->rq_import))
+		committed = 1;
+
+	LASSERT(mod->mod_open_req->rq_replay == 0);
+
+	DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, "free open request\n");
+
+	ptlrpc_request_committed(mod->mod_open_req, committed);
+	if (mod->mod_close_req)
+		ptlrpc_request_committed(mod->mod_close_req, committed);
+}
+
 int mdc_clear_open_replay_data(struct obd_export *exp,
 			       struct obd_client_handle *och)
 {
@@ -771,6 +813,8 @@ int mdc_clear_open_replay_data(struct obd_export *exp,
 		return 0;
 
 	LASSERT(mod != LP_POISON);
+	LASSERT(mod->mod_open_req != NULL);
+	mdc_free_open(mod);
 
 	mod->mod_och = NULL;
 	och->och_mod = NULL;
@@ -969,6 +1013,9 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data,
 	if (mod) {
 		if (rc != 0)
 			mod->mod_close_req = NULL;
+		LASSERT(mod->mod_open_req != NULL);
+		mdc_free_open(mod);
+
 		/* Since now, mod is accessed through setattr req only,
 		 * thus DW req does not keep a reference on mod anymore. */
 		obd_mod_put(mod);
diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c
index 3bdbb94e020f..b391b05ab6f8 100644
--- a/drivers/staging/lustre/lustre/mgc/mgc_request.c
+++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c
@@ -56,7 +56,7 @@ static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id,
 {
 	__u64 resname = 0;
 
-	if (len > 8) {
+	if (len > sizeof(resname)) {
 		CERROR("name too long: %s\n", name);
 		return -EINVAL;
 	}
@@ -76,6 +76,7 @@ static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id,
 		resname = 0;
 		break;
 	case CONFIG_T_RECOVER:
+	case CONFIG_T_PARAMS:
 		resname = type;
 		break;
 	default:
@@ -101,10 +102,13 @@ int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id, int type)
 	int len;
 
 	/* logname consists of "fsname-nodetype".
-	 * e.g. "lustre-MDT0001", "SUN-000-client" */
+	 * e.g. "lustre-MDT0001", "SUN-000-client"
+	 * there is an exception: llog "params" */
 	name_end = strrchr(logname, '-');
-	LASSERT(name_end);
-	len = name_end - logname;
+	if (!name_end)
+		len = strlen(logname);
+	else
+		len = name_end - logname;
 	return mgc_name2resid(logname, len, res_id, type);
 }
 
@@ -140,6 +144,8 @@ static void config_log_put(struct config_llog_data *cld)
 			config_log_put(cld->cld_recover);
 		if (cld->cld_sptlrpc)
 			config_log_put(cld->cld_sptlrpc);
+		if (cld->cld_params)
+			config_log_put(cld->cld_params);
 		if (cld_is_sptlrpc(cld))
 			sptlrpc_conf_log_stop(cld->cld_logname);
 
@@ -271,6 +277,19 @@ static struct config_llog_data *config_recover_log_add(struct obd_device *obd,
 	return cld;
 }
 
+static struct config_llog_data *config_params_log_add(struct obd_device *obd,
+	struct config_llog_instance *cfg, struct super_block *sb)
+{
+	struct config_llog_instance	lcfg = *cfg;
+	struct config_llog_data		*cld;
+
+	lcfg.cfg_instance = sb;
+
+	cld = do_config_log_add(obd, PARAMS_FILENAME, CONFIG_T_PARAMS,
+				&lcfg, sb);
+
+	return cld;
+}
 
 /** Add this log to the list of active logs watched by an MGC.
  * Active means we're watching for updates.
@@ -284,8 +303,10 @@ static int config_log_add(struct obd_device *obd, char *logname,
 	struct lustre_sb_info *lsi = s2lsi(sb);
 	struct config_llog_data *cld;
 	struct config_llog_data *sptlrpc_cld;
-	char		     seclogname[32];
-	char		    *ptr;
+	struct config_llog_data *params_cld;
+	char			seclogname[32];
+	char			*ptr;
+	int			rc;
 
 	CDEBUG(D_MGC, "adding config log %s:%p\n", logname, cfg->cfg_instance);
 
@@ -308,32 +329,49 @@ static int config_log_add(struct obd_device *obd, char *logname,
 						CONFIG_T_SPTLRPC, NULL, NULL);
 		if (IS_ERR(sptlrpc_cld)) {
 			CERROR("can't create sptlrpc log: %s\n", seclogname);
-			return PTR_ERR(sptlrpc_cld);
+			GOTO(out_err, rc = PTR_ERR(sptlrpc_cld));
 		}
 	}
+	params_cld = config_params_log_add(obd, cfg, sb);
+	if (IS_ERR(params_cld)) {
+		rc = PTR_ERR(params_cld);
+		CERROR("%s: can't create params log: rc = %d\n",
+		       obd->obd_name, rc);
+		GOTO(out_err1, rc);
+	}
 
 	cld = do_config_log_add(obd, logname, CONFIG_T_CONFIG, cfg, sb);
 	if (IS_ERR(cld)) {
 		CERROR("can't create log: %s\n", logname);
-		config_log_put(sptlrpc_cld);
-		return PTR_ERR(cld);
+		GOTO(out_err2, rc = PTR_ERR(cld));
 	}
 
 	cld->cld_sptlrpc = sptlrpc_cld;
+	cld->cld_params = params_cld;
 
 	LASSERT(lsi->lsi_lmd);
 	if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)) {
 		struct config_llog_data *recover_cld;
 		*strrchr(seclogname, '-') = 0;
 		recover_cld = config_recover_log_add(obd, seclogname, cfg, sb);
-		if (IS_ERR(recover_cld)) {
-			config_log_put(cld);
-			return PTR_ERR(recover_cld);
-		}
+		if (IS_ERR(recover_cld))
+			GOTO(out_err3, rc = PTR_ERR(recover_cld));
 		cld->cld_recover = recover_cld;
 	}
 
 	return 0;
+
+out_err3:
+	config_log_put(cld);
+
+out_err2:
+	config_log_put(params_cld);
+
+out_err1:
+	config_log_put(sptlrpc_cld);
+
+out_err:
+	return rc;
 }
 
 DEFINE_MUTEX(llog_process_lock);
@@ -344,6 +382,7 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 {
 	struct config_llog_data *cld;
 	struct config_llog_data *cld_sptlrpc = NULL;
+	struct config_llog_data *cld_params = NULL;
 	struct config_llog_data *cld_recover = NULL;
 	int rc = 0;
 
@@ -382,11 +421,20 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 	spin_lock(&config_list_lock);
 	cld_sptlrpc = cld->cld_sptlrpc;
 	cld->cld_sptlrpc = NULL;
+	cld_params = cld->cld_params;
+	cld->cld_params = NULL;
 	spin_unlock(&config_list_lock);
 
 	if (cld_sptlrpc)
 		config_log_put(cld_sptlrpc);
 
+	if (cld_params) {
+		mutex_lock(&cld_params->cld_lock);
+		cld_params->cld_stopping = 1;
+		mutex_unlock(&cld_params->cld_lock);
+		config_log_put(cld_params);
+	}
+
 	/* drop the ref from the find */
 	config_log_put(cld);
 	/* drop the start ref */
@@ -1664,7 +1712,7 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
 				LCONSOLE_ERROR_MSG(0x13a,
 						   "Failed to get MGS log %s and no local copy.\n",
 						   cld->cld_logname);
-				GOTO(out_pop, rc = -ENOTCONN);
+				GOTO(out_pop, rc = -ENOENT);
 			}
 			CDEBUG(D_MGC,
 			       "Failed to get MGS log %s, using local copy for now, will try to update later.\n",
@@ -1863,6 +1911,20 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
 			if (rc)
 				CERROR("Cannot process recover llog %d\n", rc);
 		}
+
+		if (rc == 0 && cld->cld_params != NULL) {
+			rc = mgc_process_log(obd, cld->cld_params);
+			if (rc == -ENOENT) {
+				CDEBUG(D_MGC,
+				       "There is no params config file yet\n");
+				rc = 0;
+			}
+			/* params log is optional */
+			if (rc)
+				CERROR(
+				       "%s: can't process params llog: rc = %d\n",
+				       obd->obd_name, rc);
+		}
 		config_log_put(cld);
 
 		break;
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c
index e048500edd60..3bebc78e7673 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_io.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c
@@ -942,7 +942,7 @@ int cl_io_cancel(const struct lu_env *env, struct cl_io *io,
 	struct cl_page *page;
 	int result = 0;
 
-	CERROR("Canceling ongoing page trasmission\n");
+	CERROR("Canceling ongoing page transmission\n");
 	cl_page_list_for_each(page, queue) {
 		int rc;
 
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
index 1a926036724b..0fc256f59e92 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c
@@ -508,7 +508,7 @@ EXPORT_SYMBOL(cl_site_stats_print);
  * about journal_info. Currently following fields in task_struct are identified
  * can be used for this purpose:
  *  - cl_env: for liblustre.
- *  - tux_info: ony on RedHat kernel.
+ *  - tux_info: only on RedHat kernel.
  *  - ...
  * \note As long as we use task_struct to store cl_env, we assume that once
  * called into Lustre, we'll never call into the other part of the kernel
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index d9f750d42c80..169c9ed56521 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -1010,6 +1010,8 @@ struct obd_import *class_new_import(struct obd_device *obd)
 	INIT_LIST_HEAD(&imp->imp_replay_list);
 	INIT_LIST_HEAD(&imp->imp_sending_list);
 	INIT_LIST_HEAD(&imp->imp_delayed_list);
+	INIT_LIST_HEAD(&imp->imp_committed_list);
+	imp->imp_replay_cursor = &imp->imp_committed_list;
 	spin_lock_init(&imp->imp_lock);
 	imp->imp_last_success_conn = 0;
 	imp->imp_state = LUSTRE_IMP_NEW;
@@ -1625,7 +1627,7 @@ static int obd_zombie_impexp_check(void *arg)
 }
 
 /**
- * Add export to the obd_zombe thread and notify it.
+ * Add export to the obd_zombie thread and notify it.
  */
 static void obd_zombie_export_add(struct obd_export *exp) {
 	spin_lock(&exp->exp_obd->obd_dev_lock);
@@ -1641,7 +1643,7 @@ static void obd_zombie_export_add(struct obd_export *exp) {
 }
 
 /**
- * Add import to the obd_zombe thread and notify it.
+ * Add import to the obd_zombie thread and notify it.
  */
 static void obd_zombie_import_add(struct obd_import *imp) {
 	LASSERT(imp->imp_sec == NULL);
@@ -1661,7 +1663,7 @@ static void obd_zombie_import_add(struct obd_import *imp) {
 static void obd_zombie_impexp_notify(void)
 {
 	/*
-	 * Make sure obd_zomebie_impexp_thread get this notification.
+	 * Make sure obd_zombie_impexp_thread get this notification.
 	 * It is possible this signal only get by obd_zombie_barrier, and
 	 * barrier gulps this notification and sleeps away and hangs ensues
 	 */
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
index 121a856d5052..ba20776ebfa1 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
@@ -184,7 +184,7 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd,
 	int err = 0;
 
 	/* Allow non-root access for OBD_IOC_PING_TARGET - used by lfs check */
-	if (!cfs_capable(CFS_CAP_SYS_ADMIN) && (cmd != OBD_IOC_PING_TARGET))
+	if (!capable(CFS_CAP_SYS_ADMIN) && (cmd != OBD_IOC_PING_TARGET))
 		return err = -EACCES;
 	if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
 		return err = -ENOTTY;
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
index c0f3af725747..1d999310ec92 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
@@ -551,9 +551,8 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
 
 	if (rec->lrh_index < d->lpd_startcat)
 		/* Skip processing of the logs until startcat */
-		return 0;
-
-	if (d->lpd_startidx > 0) {
+		rc = 0;
+	else if (d->lpd_startidx > 0) {
 		struct llog_process_cat_data cd;
 
 		cd.lpcd_first_idx = d->lpd_startidx;
@@ -566,6 +565,7 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
 		rc = llog_process_or_fork(env, llh, d->lpd_cb, d->lpd_data,
 					  NULL, false);
 	}
+
 	llog_handle_put(llh);
 
 	return rc;
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
index 5385d8e658cf..d86bb8c60354 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
@@ -376,7 +376,7 @@ static void llog_skip_over(__u64 *off, int curr, int goal)
 
 /* sets:
  *  - cur_offset to the furthest point read in the log file
- *  - cur_idx to the log index preceeding cur_offset
+ *  - cur_idx to the log index preceding cur_offset
  * returns -EIO/-EINVAL on error
  */
 static int llog_lvfs_next_block(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_osd.c b/drivers/staging/lustre/lustre/obdclass/llog_osd.c
index 654c8e189653..682279de8bea 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_osd.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_osd.c
@@ -514,7 +514,7 @@ static void llog_skip_over(__u64 *off, int curr, int goal)
 
 /* sets:
  *  - cur_offset to the furthest point read in the log file
- *  - cur_idx to the log index preceeding cur_offset
+ *  - cur_idx to the log index preceding cur_offset
  * returns -EIO/-EINVAL on error
  */
 static int llog_osd_next_block(const struct lu_env *env,
@@ -1073,7 +1073,7 @@ static int llog_osd_setup(const struct lu_env *env, struct obd_device *obd,
 	LASSERT(ctxt);
 
 	/* initialize data allowing to generate new fids,
-	 * literally we need a sequece */
+	 * literally we need a sequence */
 	lgi->lgi_fid.f_seq = FID_SEQ_LLOG;
 	lgi->lgi_fid.f_oid = 1;
 	lgi->lgi_fid.f_ver = 0;
@@ -1280,7 +1280,7 @@ int llog_osd_put_cat_list(const struct lu_env *env, struct dt_device *d,
 	lgi->lgi_buf.lb_len = size;
 	rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
 	if (rc)
-		CDEBUG(D_INODE, "error writeing CATALOGS: rc = %d\n", rc);
+		CDEBUG(D_INODE, "error writing CATALOGS: rc = %d\n", rc);
 out_trans:
 	dt_trans_stop(env, d, th);
 out:
diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c
index e79e4beb3628..e76f7d044231 100644
--- a/drivers/staging/lustre/lustre/obdclass/local_storage.c
+++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c
@@ -737,7 +737,7 @@ int lastid_compat_check(const struct lu_env *env, struct dt_device *dev,
  * All dynamic fids will be generated with the same sequence and incremented
  * OIDs
  *
- * Returned local_oid_storage is in-memory representaion of OID storage
+ * Returned local_oid_storage is in-memory representation of OID storage
  */
 int local_oid_storage_init(const struct lu_env *env, struct dt_device *dev,
 			   const struct lu_fid *first_fid,
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index ec3b605dae6b..1432dd74fe95 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -98,6 +98,8 @@ static const char * const obd_connect_names[] = {
 	"lightweight_conn",
 	"short_io",
 	"pingless",
+	"flock_deadlock",
+	"disp_stripe",
 	"unknown",
 	NULL
 };
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index 9887d8fffb6e..8800384c061c 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -890,10 +890,10 @@ static unsigned lu_obj_hop_hash(struct cfs_hash *hs,
 
 	hash = fid_flatten32(fid);
 	hash += (hash >> 4) + (hash << 12); /* mixing oid and seq */
-	hash = cfs_hash_long(hash, hs->hs_bkt_bits);
+	hash = hash_long(hash, hs->hs_bkt_bits);
 
 	/* give me another random factor */
-	hash -= cfs_hash_long((unsigned long)hs, fid_oid(fid) % 11 + 3);
+	hash -= hash_long((unsigned long)hs, fid_oid(fid) % 11 + 3);
 
 	hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
 	hash |= (fid_seq(fid) + fid_oid(fid)) & (CFS_HASH_NBKT(hs) - 1);
@@ -2100,7 +2100,7 @@ void lu_object_assign_fid(const struct lu_env *env, struct lu_object *o,
 EXPORT_SYMBOL(lu_object_assign_fid);
 
 /**
- * allocates object with 0 (non-assiged) fid
+ * allocates object with 0 (non-assigned) fid
  * XXX: temporary solution to be able to assign fid in ->do_create()
  *      till we have fully-functional OST fids
  */
diff --git a/drivers/staging/lustre/lustre/obdclass/md_attrs.c b/drivers/staging/lustre/lustre/obdclass/md_attrs.c
index f7187829e276..f080cceb384c 100644
--- a/drivers/staging/lustre/lustre/obdclass/md_attrs.c
+++ b/drivers/staging/lustre/lustre/obdclass/md_attrs.c
@@ -60,7 +60,7 @@ EXPORT_SYMBOL(lustre_lma_init);
  */
 void lustre_lma_swab(struct lustre_mdt_attrs *lma)
 {
-	/* Use LUSTRE_MSG_MAGIC to detect local endianess. */
+	/* Use LUSTRE_MSG_MAGIC to detect local endianness. */
 	if (LUSTRE_MSG_MAGIC != cpu_to_le32(LUSTRE_MSG_MAGIC)) {
 		__swab32s(&lma->lma_compat);
 		__swab32s(&lma->lma_incompat);
@@ -77,7 +77,7 @@ EXPORT_SYMBOL(lustre_lma_swab);
  */
 void lustre_som_swab(struct som_attrs *attrs)
 {
-	/* Use LUSTRE_MSG_MAGIC to detect local endianess. */
+	/* Use LUSTRE_MSG_MAGIC to detect local endianness. */
 	if (LUSTRE_MSG_MAGIC != cpu_to_le32(LUSTRE_MSG_MAGIC)) {
 		__swab32s(&attrs->som_compat);
 		__swab32s(&attrs->som_incompat);
@@ -135,7 +135,7 @@ EXPORT_SYMBOL(lustre_buf2som);
  */
 void lustre_hsm_swab(struct hsm_attrs *attrs)
 {
-	/* Use LUSTRE_MSG_MAGIC to detect local endianess. */
+	/* Use LUSTRE_MSG_MAGIC to detect local endianness. */
 	if (LUSTRE_MSG_MAGIC != cpu_to_le32(LUSTRE_MSG_MAGIC)) {
 		__swab32s(&attrs->hsm_compat);
 		__swab32s(&attrs->hsm_flags);
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
index 362ae541b209..2cdfa21638e2 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
@@ -592,7 +592,7 @@ int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
 }
 EXPORT_SYMBOL(class_detach);
 
-/** Start shutting down the obd.  There may be in-progess ops when
+/** Start shutting down the obd.  There may be in-progress ops when
  * this is called.  We tell them to start shutting down with a call
  * to class_disconnect_exports().
  */
@@ -655,7 +655,7 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	/* The three references that should be remaining are the
 	 * obd_self_export and the attach and setup references. */
 	if (atomic_read(&obd->obd_refcount) > 3) {
-		/* refcounf - 3 might be the number of real exports
+		/* refcount - 3 might be the number of real exports
 		   (excluding self export). But class_incref is called
 		   by other things as well, so don't count on it. */
 		CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
@@ -1027,6 +1027,46 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 }
 EXPORT_SYMBOL(lustre_cfg_rename);
 
+static int process_param2_config(struct lustre_cfg *lcfg)
+{
+	char *param = lustre_cfg_string(lcfg, 1);
+	char *upcall = lustre_cfg_string(lcfg, 2);
+	char *argv[] = {
+		[0] = "/usr/sbin/lctl",
+		[1] = "set_param",
+		[2] = param,
+		[3] = NULL
+	};
+	struct timeval	start;
+	struct timeval	end;
+	int		rc;
+
+
+	/* Add upcall processing here. Now only lctl is supported */
+	if (strcmp(upcall, LCTL_UPCALL) != 0) {
+		CERROR("Unsupported upcall %s\n", upcall);
+		return -EINVAL;
+	}
+
+	do_gettimeofday(&start);
+	rc = USERMODEHELPER(argv[0], argv, NULL);
+	do_gettimeofday(&end);
+
+	if (rc < 0) {
+		CERROR(
+		       "lctl: error invoking upcall %s %s %s: rc = %d; time %ldus\n",
+		       argv[0], argv[1], argv[2], rc,
+		       cfs_timeval_sub(&end, &start, NULL));
+	} else {
+		CDEBUG(D_HA, "lctl: invoked upcall %s %s %s, time %ldus\n",
+		       argv[0], argv[1], argv[2],
+		       cfs_timeval_sub(&end, &start, NULL));
+		       rc = 0;
+	}
+
+	return rc;
+}
+
 void lustre_register_quota_process_config(int (*qpc)(struct lustre_cfg *lcfg))
 {
 	quota_process_config = qpc;
@@ -1142,11 +1182,14 @@ int class_process_config(struct lustre_cfg *lcfg)
 			err = (*quota_process_config)(lcfg);
 			GOTO(out, err);
 		}
-		/* Fall through */
+
 		break;
 	}
+	case LCFG_SET_PARAM: {
+		err = process_param2_config(lcfg);
+		GOTO(out, 0);
+	}
 	}
-
 	/* Commands that require a device */
 	obd = class_name2obd(lustre_cfg_string(lcfg, 0));
 	if (obd == NULL) {
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index a69a630b596e..6f8ba54e9667 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -501,7 +501,7 @@ static int lustre_stop_mgc(struct super_block *sb)
 	}
 
 	/* The MGC has no recoverable data in any case.
-	 * force shotdown set in umount_begin */
+	 * force shutdown set in umount_begin */
 	obd->obd_no_recov = 1;
 
 	if (obd->u.cli.cl_mgc_mgsexp) {
@@ -754,7 +754,7 @@ int server_name2index(const char *svname, __u32 *idx, const char **endptr)
 }
 EXPORT_SYMBOL(server_name2index);
 
-/*************** mount common betweeen server and client ***************/
+/*************** mount common between server and client ***************/
 
 /* Common umount */
 int lustre_common_put_super(struct super_block *sb)
diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c
index 70997648a4f3..3b1b28afd6b1 100644
--- a/drivers/staging/lustre/lustre/obdclass/obdo.c
+++ b/drivers/staging/lustre/lustre/obdclass/obdo.c
@@ -191,7 +191,7 @@ int obdo_cmp_md(struct obdo *dst, struct obdo *src, obd_flag compare)
 	}
 	if ( compare & OBD_MD_FLGENER )
 		res = (res || (dst->o_parent_oid != src->o_parent_oid));
-	/* XXX Don't know if thses should be included here - wasn't previously
+	/* XXX Don't know if these should be included here - wasn't previously
 	if ( compare & OBD_MD_FLINLINE )
 		res = (res || memcmp(dst->o_inline, src->o_inline));
 	*/
@@ -233,7 +233,7 @@ void obdo_from_iattr(struct obdo *oa, struct iattr *attr, unsigned int ia_valid)
 		oa->o_mode = attr->ia_mode;
 		oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLMODE;
 		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
-		    !cfs_capable(CFS_CAP_FSETID))
+		    !capable(CFS_CAP_FSETID))
 			oa->o_mode &= ~S_ISGID;
 	}
 	if (ia_valid & ATTR_UID) {
@@ -282,7 +282,7 @@ void iattr_from_obdo(struct iattr *attr, struct obdo *oa, obd_flag valid)
 		attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT);
 		attr->ia_valid |= ATTR_MODE;
 		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
-		    !cfs_capable(CFS_CAP_FSETID))
+		    !capable(CFS_CAP_FSETID))
 			attr->ia_mode &= ~S_ISGID;
 	}
 	if (valid & OBD_MD_FLUID) {
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index 9b2dea292363..268a202c21e5 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -2764,7 +2764,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
 	switch (cmd) {
 	case OBD_IOC_CREATE:		    /* may create echo object */
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		rc = echo_create_object(env, ed, 1, oa, data->ioc_pbuf1,
@@ -2778,7 +2778,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		int dirlen;
 		__u64 id;
 
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO(out, rc = -EPERM);
 
 		count = data->ioc_count;
@@ -2806,7 +2806,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		__u64	    seq;
 		int	      max_count;
 
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO(out, rc = -EPERM);
 
 		cl_env = cl_env_get(&refcheck);
@@ -2838,7 +2838,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO(out, rc);
 	}
 	case OBD_IOC_DESTROY:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		rc = echo_get_object(&eco, ed, oa);
@@ -2863,7 +2863,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO(out, rc);
 
 	case OBD_IOC_SETATTR:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		rc = echo_get_object(&eco, ed, oa);
@@ -2878,7 +2878,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO(out, rc);
 
 	case OBD_IOC_BRW_WRITE:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		rw = OBD_BRW_WRITE;
@@ -2897,7 +2897,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO(out, rc);
 
 	case ECHO_IOC_SET_STRIPE:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		if (data->ioc_pbuf1 == NULL) {  /* unset */
@@ -2914,7 +2914,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO (out, rc);
 
 	case ECHO_IOC_ENQUEUE:
-		if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+		if (!capable(CFS_CAP_SYS_ADMIN))
 			GOTO (out, rc = -EPERM);
 
 		rc = echo_client_enqueue(exp, oa,
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index be4511e78c04..af25c19c88fa 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -2146,7 +2146,7 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops,
 	oap->oap_obj_off = offset;
 	LASSERT(!(offset & ~CFS_PAGE_MASK));
 
-	if (!client_is_remote(exp) && cfs_capable(CFS_CAP_SYS_RESOURCE))
+	if (!client_is_remote(exp) && capable(CFS_CAP_SYS_RESOURCE))
 		oap->oap_brw_flags = OBD_BRW_NOQUOTA;
 
 	INIT_LIST_HEAD(&oap->oap_pending_item);
@@ -2186,7 +2186,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
 	/* Set the OBD_BRW_SRVLOCK before the page is queued. */
 	brw_flags |= ops->ops_srvlock ? OBD_BRW_SRVLOCK : 0;
 	if (!client_is_remote(osc_export(osc)) &&
-	    cfs_capable(CFS_CAP_SYS_RESOURCE)) {
+	    capable(CFS_CAP_SYS_RESOURCE)) {
 		brw_flags |= OBD_BRW_NOQUOTA;
 		cmd |= OBD_BRW_NOQUOTA;
 	}
@@ -2394,6 +2394,12 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
 		 * really sending the RPC. */
 	case OES_TRUNC:
 		/* race with truncate, page will be redirtied */
+	case OES_ACTIVE:
+		/* The extent is active so we need to abort and let the caller
+		 * re-dirty the page. If we continued on here, and we were the
+		 * one making the extent active, we could deadlock waiting for
+		 * the page writeback to clear but it won't because the extent
+		 * is active and won't be written out. */
 		GOTO(out, rc = -EAGAIN);
 	default:
 		break;
diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
index 681d60a7d5ef..5f3c545418d1 100644
--- a/drivers/staging/lustre/lustre/osc/osc_io.c
+++ b/drivers/staging/lustre/lustre/osc/osc_io.c
@@ -297,7 +297,7 @@ static int osc_io_commit_write(const struct lu_env *env,
 	 */
 	osc_page_touch(env, cl2osc_page(slice), to);
 	if (!client_is_remote(osc_export(obj)) &&
-	    cfs_capable(CFS_CAP_SYS_RESOURCE))
+	    capable(CFS_CAP_SYS_RESOURCE))
 		oap->oap_brw_flags |= OBD_BRW_NOQUOTA;
 
 	if (oio->oi_lockless)
@@ -512,19 +512,15 @@ static int osc_io_read_start(const struct lu_env *env,
 	struct osc_io    *oio   = cl2osc_io(env, slice);
 	struct cl_object *obj   = slice->cis_obj;
 	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
-	int	      result = 0;
+	int rc = 0;
 
-	if (oio->oi_lockless == 0) {
+	if (oio->oi_lockless == 0 && !slice->cis_io->ci_noatime) {
 		cl_object_attr_lock(obj);
-		result = cl_object_attr_get(env, obj, attr);
-		if (result == 0) {
-			attr->cat_atime = LTIME_S(CURRENT_TIME);
-			result = cl_object_attr_set(env, obj, attr,
-						    CAT_ATIME);
-		}
+		attr->cat_atime = LTIME_S(CURRENT_TIME);
+		rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
 		cl_object_attr_unlock(obj);
 	}
-	return result;
+	return rc;
 }
 
 static int osc_io_write_start(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
index 4909e486dc5c..96cb6e2b9c4e 100644
--- a/drivers/staging/lustre/lustre/osc/osc_page.c
+++ b/drivers/staging/lustre/lustre/osc/osc_page.c
@@ -561,7 +561,7 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg,
 	oap->oap_brw_flags = OBD_BRW_SYNC | brw_flags;
 
 	if (!client_is_remote(osc_export(obj)) &&
-			cfs_capable(CFS_CAP_SYS_RESOURCE)) {
+			capable(CFS_CAP_SYS_RESOURCE)) {
 		oap->oap_brw_flags |= OBD_BRW_NOQUOTA;
 		oap->oap_cmd |= OBD_BRW_NOQUOTA;
 	}
diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
index 6045a78a2baa..f395ae4ec944 100644
--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
+++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
@@ -51,11 +51,8 @@ int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
 
 		oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
 		if (oqi) {
-			obd_uid id = oqi->oqi_id;
-
-			LASSERTF(id == qid[type],
-				 "The ids don't match %u != %u\n",
-				 id, qid[type]);
+			/* do not try to access oqi here, it could have been
+			 * freed by osc_quota_setdq() */
 
 			/* the slot is busy, the user is about to run out of
 			 * quota space on this OST */
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index d90efe408414..4c9e00695087 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -48,6 +48,7 @@
 #include "ptlrpc_internal.h"
 
 static int ptlrpc_send_new_req(struct ptlrpc_request *req);
+static int ptlrpcd_check_work(struct ptlrpc_request *req);
 
 /**
  * Initialize passed in client structure \a cl.
@@ -62,7 +63,7 @@ void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
 EXPORT_SYMBOL(ptlrpc_init_client);
 
 /**
- * Return PortalRPC connection for remore uud \a uuid
+ * Return PortalRPC connection for remote uud \a uuid
  */
 struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid)
 {
@@ -127,7 +128,7 @@ struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw,
  * Prepare bulk descriptor for specified outgoing request \a req that
  * can fit \a npages * pages. \a type is bulk type. \a portal is where
  * the bulk to be sent. Used on client-side.
- * Returns pointer to newly allocatrd initialized bulk descriptor or NULL on
+ * Returns pointer to newly allocated initialized bulk descriptor or NULL on
  * error.
  */
 struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req,
@@ -631,7 +632,7 @@ int ptlrpc_request_pack(struct ptlrpc_request *request,
 
 	/* For some old 1.8 clients (< 1.8.7), they will LASSERT the size of
 	 * ptlrpc_body sent from server equal to local ptlrpc_body size, so we
-	 * have to send old ptlrpc_body to keep interoprability with these
+	 * have to send old ptlrpc_body to keep interoperability with these
 	 * clients.
 	 *
 	 * Only three kinds of server->client RPCs so far:
@@ -639,7 +640,7 @@ int ptlrpc_request_pack(struct ptlrpc_request *request,
 	 *  - LDLM_CP_CALLBACK
 	 *  - LDLM_GL_CALLBACK
 	 *
-	 * XXX This should be removed whenever we drop the interoprability with
+	 * XXX This should be removed whenever we drop the interoperability with
 	 *     the these old clients.
 	 */
 	if (opcode == LDLM_BL_CALLBACK || opcode == LDLM_CP_CALLBACK ||
@@ -686,7 +687,7 @@ struct ptlrpc_request *__ptlrpc_request_alloc(struct obd_import *imp,
 
 /**
  * Helper function for creating a request.
- * Calls __ptlrpc_request_alloc to allocate new request sturcture and inits
+ * Calls __ptlrpc_request_alloc to allocate new request structure and inits
  * buffer structures according to capsule template \a format.
  * Returns allocated request structure pointer or NULL on error.
  */
@@ -743,7 +744,7 @@ void ptlrpc_request_free(struct ptlrpc_request *request)
 EXPORT_SYMBOL(ptlrpc_request_free);
 
 /**
- * Allocate new request for operatione \a opcode and immediatelly pack it for
+ * Allocate new request for operation \a opcode and immediately pack it for
  * network transfer.
  * Only used for simple requests like OBD_PING where the only important
  * part of the request is operation itself.
@@ -768,7 +769,7 @@ struct ptlrpc_request *ptlrpc_request_alloc_pack(struct obd_import *imp,
 EXPORT_SYMBOL(ptlrpc_request_alloc_pack);
 
 /**
- * Prepare request (fetched from pool \a poolif not NULL) on import \a imp
+ * Prepare request (fetched from pool \a pool if not NULL) on import \a imp
  * for operation \a opcode. Request would contain \a count buffers.
  * Sizes of buffers are described in array \a lengths and buffers themselves
  * are provided by a pointer \a bufs.
@@ -1073,7 +1074,7 @@ static int ptlrpc_import_delay_req(struct obd_import *imp,
 }
 
 /**
- * Decide if the eror message regarding provided request \a req
+ * Decide if the error message regarding provided request \a req
  * should be printed to the console or not.
  * Makes it's decision on request status and other properties.
  * Returns 1 to print error on the system console or 0 if not.
@@ -1159,7 +1160,7 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req)
 /**
  * Callback function called when client receives RPC reply for \a req.
  * Returns 0 on success or error code.
- * The return alue would be assigned to req->rq_status by the caller
+ * The return value would be assigned to req->rq_status by the caller
  * as request processing status.
  * This function also decides if the request needs to be saved for later replay.
  */
@@ -1190,7 +1191,9 @@ static int after_reply(struct ptlrpc_request *req)
 		 * will roundup it */
 		req->rq_replen       = req->rq_nob_received;
 		req->rq_nob_received = 0;
+		spin_lock(&req->rq_lock);
 		req->rq_resend       = 1;
+		spin_unlock(&req->rq_lock);
 		return 0;
 	}
 
@@ -1313,7 +1316,11 @@ static int after_reply(struct ptlrpc_request *req)
 			/** version recovery */
 			ptlrpc_save_versions(req);
 			ptlrpc_retain_replayable_request(req, imp);
-		} else if (req->rq_commit_cb != NULL) {
+		} else if (req->rq_commit_cb != NULL &&
+			   list_empty(&req->rq_replay_list)) {
+			/* NB: don't call rq_commit_cb if it's already on
+			 * rq_replay_list, ptlrpc_free_committed() will call
+			 * it later, see LU-3618 for details */
 			spin_unlock(&imp->imp_lock);
 			req->rq_commit_cb(req);
 			spin_lock(&imp->imp_lock);
@@ -1408,7 +1415,9 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 			req->rq_status = rc;
 			return 1;
 		} else {
+			spin_lock(&req->rq_lock);
 			req->rq_wait_ctx = 1;
+			spin_unlock(&req->rq_lock);
 			return 0;
 		}
 	}
@@ -1423,7 +1432,9 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 	rc = ptl_send_rpc(req, 0);
 	if (rc) {
 		DEBUG_REQ(D_HA, req, "send failed (%d); expect timeout", rc);
+		spin_lock(&req->rq_lock);
 		req->rq_net_err = 1;
+		spin_unlock(&req->rq_lock);
 		return rc;
 	}
 	return 0;
@@ -1688,6 +1699,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
 					spin_lock(&req->rq_lock);
 					req->rq_net_err = 1;
 					spin_unlock(&req->rq_lock);
+					continue;
 				}
 				/* need to reset the timeout */
 				force_timer_recalc = 1;
@@ -1773,6 +1785,10 @@ interpret:
 
 		ptlrpc_req_interpret(env, req, req->rq_status);
 
+		if (ptlrpcd_check_work(req)) {
+			atomic_dec(&set->set_remaining);
+			continue;
+		}
 		ptlrpc_rqphase_move(req, RQ_PHASE_COMPLETE);
 
 		CDEBUG(req->rq_reqmsg != NULL ? D_RPCTRACE : 0,
@@ -2031,7 +2047,7 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
 EXPORT_SYMBOL(ptlrpc_set_next_timeout);
 
 /**
- * Send all unset request from the set and then wait untill all
+ * Send all unset request from the set and then wait until all
  * requests in the set complete (either get a reply, timeout, get an
  * error or otherwise be interrupted).
  * Returns 0 on success or error code otherwise.
@@ -2156,7 +2172,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 EXPORT_SYMBOL(ptlrpc_set_wait);
 
 /**
- * Helper fuction for request freeing.
+ * Helper function for request freeing.
  * Called when request count reached zero and request needs to be freed.
  * Removes request from all sorts of sending/replay lists it might be on,
  * frees network buffers if any are present.
@@ -2223,7 +2239,7 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
 static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked);
 /**
  * Drop one request reference. Must be called with import imp_lock held.
- * When reference count drops to zero, reuqest is freed.
+ * When reference count drops to zero, request is freed.
  */
 void ptlrpc_req_finished_with_imp_lock(struct ptlrpc_request *request)
 {
@@ -2236,7 +2252,7 @@ EXPORT_SYMBOL(ptlrpc_req_finished_with_imp_lock);
  * Helper function
  * Drops one reference count for request \a request.
  * \a locked set indicates that caller holds import imp_lock.
- * Frees the request whe reference count reaches zero.
+ * Frees the request when reference count reaches zero.
  */
 static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked)
 {
@@ -2360,19 +2376,52 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 }
 EXPORT_SYMBOL(ptlrpc_unregister_reply);
 
+static void ptlrpc_free_request(struct ptlrpc_request *req)
+{
+	spin_lock(&req->rq_lock);
+	req->rq_replay = 0;
+	spin_unlock(&req->rq_lock);
+
+	if (req->rq_commit_cb != NULL)
+		req->rq_commit_cb(req);
+	list_del_init(&req->rq_replay_list);
+
+	__ptlrpc_req_finished(req, 1);
+}
+
+/**
+ * the request is committed and dropped from the replay list of its import
+ */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force)
+{
+	struct obd_import	*imp = req->rq_import;
+
+	spin_lock(&imp->imp_lock);
+	if (list_empty(&req->rq_replay_list)) {
+		spin_unlock(&imp->imp_lock);
+		return;
+	}
+
+	if (force || req->rq_transno <= imp->imp_peer_committed_transno)
+		ptlrpc_free_request(req);
+
+	spin_unlock(&imp->imp_lock);
+}
+EXPORT_SYMBOL(ptlrpc_request_committed);
+
 /**
  * Iterates through replay_list on import and prunes
  * all requests have transno smaller than last_committed for the
  * import and don't have rq_replay set.
- * Since requests are sorted in transno order, stops when meetign first
+ * Since requests are sorted in transno order, stops when meeting first
  * transno bigger than last_committed.
  * caller must hold imp->imp_lock
  */
 void ptlrpc_free_committed(struct obd_import *imp)
 {
-	struct list_head *tmp, *saved;
-	struct ptlrpc_request *req;
+	struct ptlrpc_request *req, *saved;
 	struct ptlrpc_request *last_req = NULL; /* temporary fire escape */
+	bool		       skip_committed_list = true;
 
 	LASSERT(imp != NULL);
 
@@ -2388,13 +2437,15 @@ void ptlrpc_free_committed(struct obd_import *imp)
 	CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n",
 	       imp->imp_obd->obd_name, imp->imp_peer_committed_transno,
 	       imp->imp_generation);
+
+	if (imp->imp_generation != imp->imp_last_generation_checked)
+		skip_committed_list = false;
+
 	imp->imp_last_transno_checked = imp->imp_peer_committed_transno;
 	imp->imp_last_generation_checked = imp->imp_generation;
 
-	list_for_each_safe(tmp, saved, &imp->imp_replay_list) {
-		req = list_entry(tmp, struct ptlrpc_request,
-				     rq_replay_list);
-
+	list_for_each_entry_safe(req, saved, &imp->imp_replay_list,
+				 rq_replay_list) {
 		/* XXX ok to remove when 1357 resolved - rread 05/29/03  */
 		LASSERT(req != last_req);
 		last_req = req;
@@ -2408,27 +2459,34 @@ void ptlrpc_free_committed(struct obd_import *imp)
 			GOTO(free_req, 0);
 		}
 
-		if (req->rq_replay) {
-			DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
-			continue;
-		}
-
 		/* not yet committed */
 		if (req->rq_transno > imp->imp_peer_committed_transno) {
 			DEBUG_REQ(D_RPCTRACE, req, "stopping search");
 			break;
 		}
 
+		if (req->rq_replay) {
+			DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
+			list_move_tail(&req->rq_replay_list,
+				       &imp->imp_committed_list);
+			continue;
+		}
+
 		DEBUG_REQ(D_INFO, req, "commit (last_committed "LPU64")",
 			  imp->imp_peer_committed_transno);
 free_req:
-		spin_lock(&req->rq_lock);
-		req->rq_replay = 0;
-		spin_unlock(&req->rq_lock);
-		if (req->rq_commit_cb != NULL)
-			req->rq_commit_cb(req);
-		list_del_init(&req->rq_replay_list);
-		__ptlrpc_req_finished(req, 1);
+		ptlrpc_free_request(req);
+	}
+	if (skip_committed_list)
+		return;
+
+	list_for_each_entry_safe(req, saved, &imp->imp_committed_list,
+				 rq_replay_list) {
+		LASSERT(req->rq_transno != 0);
+		if (req->rq_import_generation < imp->imp_generation) {
+			DEBUG_REQ(D_RPCTRACE, req, "free stale open request");
+			ptlrpc_free_request(req);
+		}
 	}
 }
 
@@ -2585,7 +2643,7 @@ struct ptlrpc_replay_async_args {
 
 /**
  * Callback used for replayed requests reply processing.
- * In case of succesful reply calls registeresd request replay callback.
+ * In case of successful reply calls registered request replay callback.
  * In case of error restart replay process.
  */
 static int ptlrpc_replay_interpret(const struct lu_env *env,
@@ -2834,7 +2892,7 @@ void ptlrpc_init_xid(void)
 		ptlrpc_last_xid = (__u64)now << 20;
 	}
 
-	/* Need to always be aligned to a power-of-two for mutli-bulk BRW */
+	/* Always need to be aligned to a power-of-two for multi-bulk BRW */
 	CLASSERT((PTLRPC_BULK_OPS_COUNT & (PTLRPC_BULK_OPS_COUNT - 1)) == 0);
 	ptlrpc_last_xid &= PTLRPC_BULK_OPS_MASK;
 }
@@ -2904,22 +2962,50 @@ EXPORT_SYMBOL(ptlrpc_sample_next_xid);
  *    have delay before it really runs by ptlrpcd thread.
  */
 struct ptlrpc_work_async_args {
-	__u64   magic;
 	int   (*cb)(const struct lu_env *, void *);
 	void   *cbdata;
 };
 
-#define PTLRPC_WORK_MAGIC 0x6655436b676f4f44ULL /* magic code */
+static void ptlrpcd_add_work_req(struct ptlrpc_request *req)
+{
+	/* re-initialize the req */
+	req->rq_timeout		= obd_timeout;
+	req->rq_sent		= cfs_time_current_sec();
+	req->rq_deadline	= req->rq_sent + req->rq_timeout;
+	req->rq_reply_deadline	= req->rq_deadline;
+	req->rq_phase		= RQ_PHASE_INTERPRET;
+	req->rq_next_phase	= RQ_PHASE_COMPLETE;
+	req->rq_xid		= ptlrpc_next_xid();
+	req->rq_import_generation = req->rq_import->imp_generation;
+
+	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+}
 
 static int work_interpreter(const struct lu_env *env,
 			    struct ptlrpc_request *req, void *data, int rc)
 {
 	struct ptlrpc_work_async_args *arg = data;
 
-	LASSERT(arg->magic == PTLRPC_WORK_MAGIC);
+	LASSERT(ptlrpcd_check_work(req));
 	LASSERT(arg->cb != NULL);
 
-	return arg->cb(env, arg->cbdata);
+	rc = arg->cb(env, arg->cbdata);
+
+	list_del_init(&req->rq_set_chain);
+	req->rq_set = NULL;
+
+	if (atomic_dec_return(&req->rq_refcount) > 1) {
+		atomic_set(&req->rq_refcount, 2);
+		ptlrpcd_add_work_req(req);
+	}
+	return rc;
+}
+
+static int worker_format;
+
+static int ptlrpcd_check_work(struct ptlrpc_request *req)
+{
+	return req->rq_pill.rc_fmt == (void *)&worker_format;
 }
 
 /**
@@ -2952,6 +3038,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
 	req->rq_receiving_reply = 0;
 	req->rq_must_unlink = 0;
 	req->rq_no_delay = req->rq_no_resend = 1;
+	req->rq_pill.rc_fmt = (void *)&worker_format;
 
 	spin_lock_init(&req->rq_lock);
 	INIT_LIST_HEAD(&req->rq_list);
@@ -2965,7 +3052,6 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
 
 	CLASSERT(sizeof(*args) <= sizeof(req->rq_async_args));
 	args = ptlrpc_req_async_args(req);
-	args->magic  = PTLRPC_WORK_MAGIC;
 	args->cb     = cb;
 	args->cbdata = cbdata;
 
@@ -2995,25 +3081,8 @@ int ptlrpcd_queue_work(void *handler)
 	 * req as opaque data. - Jinshan
 	 */
 	LASSERT(atomic_read(&req->rq_refcount) > 0);
-	if (atomic_read(&req->rq_refcount) > 1)
-		return -EBUSY;
-
-	if (atomic_inc_return(&req->rq_refcount) > 2) { /* race */
-		atomic_dec(&req->rq_refcount);
-		return -EBUSY;
-	}
-
-	/* re-initialize the req */
-	req->rq_timeout	= obd_timeout;
-	req->rq_sent	   = cfs_time_current_sec();
-	req->rq_deadline       = req->rq_sent + req->rq_timeout;
-	req->rq_reply_deadline = req->rq_deadline;
-	req->rq_phase	  = RQ_PHASE_INTERPRET;
-	req->rq_next_phase     = RQ_PHASE_COMPLETE;
-	req->rq_xid	    = ptlrpc_next_xid();
-	req->rq_import_generation = req->rq_import->imp_generation;
-
-	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+	if (atomic_inc_return(&req->rq_refcount) == 2)
+		ptlrpcd_add_work_req(req);
 	return 0;
 }
 EXPORT_SYMBOL(ptlrpcd_queue_work);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c
index f66cfea87acf..6ea0a491cfb3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/events.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/events.c
@@ -545,7 +545,7 @@ int ptlrpc_ni_init(void)
 	 * different depending on... */
 	/* kernel LNet calls our master callback when there are new event,
 	 * because we are guaranteed to get every event via callback,
-	 * so we just set EQ size to 0 to avoid overhread of serializing
+	 * so we just set EQ size to 0 to avoid overhead of serializing
 	 * enqueue/dequeue operations in LNet. */
 	rc = LNetEQAlloc(0, ptlrpc_master_callback, &ptlrpc_eq_h);
 	if (rc == 0)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
index 55247af3910e..c279edf5b2a5 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
@@ -336,7 +336,7 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
 	if (rc) {
 		/* If any _real_ denial be made, we expect server return
 		 * -EACCES reply or return success but indicate gss error
-		 * inside reply messsage. All other errors are treated as
+		 * inside reply message. All other errors are treated as
 		 * timeout, caller might try the negotiation repeatedly,
 		 * leave recovery decisions to general ptlrpc layer.
 		 *
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
index d43a13c69669..4642bbfb9273 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
@@ -1176,7 +1176,7 @@ int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
 
 /*
  * called with key semaphore write locked. it means we can operate
- * on the context without fear of loosing refcount.
+ * on the context without fear of losing refcount.
  */
 static
 int gss_kt_update(struct key *key, const void *data, size_t datalen)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
index b9fa3b4a40db..6eda1799be8f 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
@@ -54,7 +54,6 @@
 #include <linux/slab.h>
 #include <linux/crypto.h>
 #include <linux/mutex.h>
-#include <linux/crypto.h>
 
 #include <obd.h>
 #include <obd_class.h>
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
index c624518c181a..7a1ff4fecbe3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
@@ -85,7 +85,7 @@ static void gss_sec_pipe_upcall_fini(struct gss_sec *gsec)
 }
 
 /****************************************
- * internel context helpers	     *
+ * internal context helpers	     *
  ****************************************/
 
 static
@@ -652,7 +652,7 @@ __u32 mech_name2idx(const char *name)
 
 /* pipefs dentries for each mechanisms */
 static struct dentry *de_pipes[MECH_MAX] = { NULL, };
-/* all upcall messgaes linked here */
+/* all upcall messages linked here */
 static struct list_head upcall_lists[MECH_MAX];
 /* and protected by this */
 static spinlock_t upcall_locks[MECH_MAX];
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
index 5b5365b4629f..f0aba500764e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
@@ -102,7 +102,7 @@ static inline unsigned long hash_mem(char *buf, int length, int bits)
 		len++;
 
 		if ((len & (BITS_PER_LONG/8-1)) == 0)
-			hash = cfs_hash_long(hash^l, BITS_PER_LONG);
+			hash = hash_long(hash^l, BITS_PER_LONG);
 	} while (len);
 
 	return hash >> (BITS_PER_LONG - bits);
@@ -586,7 +586,7 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
 			goto out;
 
 		/* currently the expiry time passed down from user-space
-		 * is invalid, here we retrive it from mech. */
+		 * is invalid, here we retrieve it from mech. */
 		if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
 			CERROR("unable to get expire time, drop it\n");
 			goto out;
@@ -1067,7 +1067,7 @@ int __init gss_init_svc_upcall(void)
 	 * the init upcall channel, otherwise there's big chance that the first
 	 * upcall issued before the channel be opened thus nfsv4 cache code will
 	 * drop the request direclty, thus lead to unnecessary recovery time.
-	 * here we wait at miximum 1.5 seconds. */
+	 * here we wait at maximum 1.5 seconds. */
 	for (i = 0; i < 6; i++) {
 		if (atomic_read(&rsi_cache.readers) > 0)
 			break;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
index 8ce6271a5daa..383601cdd4e6 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
@@ -382,7 +382,7 @@ void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx)
 	/* At this point this ctx might have been marked as dead by
 	 * someone else, in which case nobody will make further use
 	 * of it. we don't care, and mark it UPTODATE will help
-	 * destroying server side context when it be destroied. */
+	 * destroying server side context when it be destroyed. */
 	set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
 
 	if (sec_is_reverse(ctx->cc_sec)) {
@@ -676,7 +676,7 @@ redo:
 	 * lead to the sequence number fall behind the window on server and
 	 * be dropped. also applies to gss_cli_ctx_seal().
 	 *
-	 * Note: null mode dosen't check sequence number. */
+	 * Note: null mode doesn't check sequence number. */
 	if (svc != SPTLRPC_SVC_NULL &&
 	    atomic_read(&gctx->gc_seq) - seq > GSS_SEQ_REPACK_THRESHOLD) {
 		int behind = atomic_read(&gctx->gc_seq) - seq;
@@ -1215,7 +1215,7 @@ int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
 	/*
 	 * remove UPTODATE flag of reverse ctx thus we won't send fini rpc,
 	 * this is to avoid potential problems of client side reverse svc ctx
-	 * be mis-destroyed in various recovery senarios. anyway client can
+	 * be mis-destroyed in various recovery scenarios. anyway client can
 	 * manage its reverse ctx well by associating it with its buddy ctx.
 	 */
 	if (sec_is_reverse(sec))
@@ -1882,7 +1882,7 @@ int gss_svc_sign(struct ptlrpc_request *req,
 
 	LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0));
 
-	/* embedded lustre_msg might have been shrinked */
+	/* embedded lustre_msg might have been shrunk */
 	if (req->rq_replen != rs->rs_repbuf->lm_buflens[1])
 		lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1);
 
@@ -2596,7 +2596,7 @@ static int gss_svc_seal(struct ptlrpc_request *req,
 	int		      msglen, rc;
 
 	/* get clear data length. note embedded lustre_msg might
-	 * have been shrinked */
+	 * have been shrunk */
 	if (req->rq_replen != lustre_msg_buflen(rs->rs_repbuf, 0))
 		msglen = lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1);
 	else
@@ -2765,7 +2765,7 @@ int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx,
 	 * replay.
 	 *
 	 * each reverse root ctx will record its latest sequence number on its
-	 * buddy svcctx before be destroied, so here we continue use it.
+	 * buddy svcctx before be destroyed, so here we continue use it.
 	 */
 	atomic_set(&cli_gctx->gc_seq, svc_gctx->gsc_rvs_seq);
 
@@ -2836,7 +2836,7 @@ int __init sptlrpc_gss_init(void)
 	if (rc)
 		goto out_svc_upcall;
 
-	/* register policy after all other stuff be intialized, because it
+	/* register policy after all other stuff be initialized, because it
 	 * might be in used immediately after the registration. */
 
 	rc = gss_init_keyring();
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index f465547eb95e..537aa6204a51 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -560,17 +560,30 @@ static int ptlrpc_first_transno(struct obd_import *imp, __u64 *transno)
 	struct ptlrpc_request *req;
 	struct list_head *tmp;
 
-	if (list_empty(&imp->imp_replay_list))
-		return 0;
-	tmp = imp->imp_replay_list.next;
-	req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
-	*transno = req->rq_transno;
-	if (req->rq_transno == 0) {
-		DEBUG_REQ(D_ERROR, req, "zero transno in replay");
-		LBUG();
+	/* The requests in committed_list always have smaller transnos than
+	 * the requests in replay_list */
+	if (!list_empty(&imp->imp_committed_list)) {
+		tmp = imp->imp_committed_list.next;
+		req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+		*transno = req->rq_transno;
+		if (req->rq_transno == 0) {
+			DEBUG_REQ(D_ERROR, req,
+				  "zero transno in committed_list");
+			LBUG();
+		}
+		return 1;
 	}
-
-	return 1;
+	if (!list_empty(&imp->imp_replay_list)) {
+		tmp = imp->imp_replay_list.next;
+		req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+		*transno = req->rq_transno;
+		if (req->rq_transno == 0) {
+			DEBUG_REQ(D_ERROR, req, "zero transno in replay_list");
+			LBUG();
+		}
+		return 1;
+	}
+	return 0;
 }
 
 /**
@@ -1042,7 +1055,7 @@ finish:
 			if ((ocd->ocd_cksum_types &
 			     cksum_types_supported_client()) == 0) {
 				LCONSOLE_WARN("The negotiation of the checksum "
-					      "alogrithm to use with server %s "
+					      "algorithm to use with server %s "
 					      "failed (%x/%x), disabling "
 					      "checksums\n",
 					      obd2cli_tgt(imp->imp_obd),
@@ -1260,7 +1273,7 @@ static int ptlrpc_invalidate_import_thread(void *data)
 /**
  * This is the state machine for client-side recovery on import.
  *
- * Typicaly we have two possibly paths. If we came to server and it is not
+ * Typically we have two possibly paths. If we came to server and it is not
  * in recovery, we just enter IMP_EVICTED state, invalidate our import
  * state and reconnect from scratch.
  * If we came to server that is in recovery, we enter IMP_REPLAY import state.
diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c
index dfcb410fe485..41c12e00129f 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/layout.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c
@@ -295,7 +295,8 @@ static const struct req_msg_field *mds_reint_setxattr_client[] = {
 	&RMF_REC_REINT,
 	&RMF_CAPA1,
 	&RMF_NAME,
-	&RMF_EADATA
+	&RMF_EADATA,
+	&RMF_DLM_REQ
 };
 
 static const struct req_msg_field *mdt_swap_layouts[] = {
@@ -2154,7 +2155,7 @@ EXPORT_SYMBOL(req_capsule_server_sized_swab_get);
  * request (if the caller is executing on the server-side) or reply (if the
  * caller is executing on the client-side).
  *
- * This function convienient for use is code that could be executed on the
+ * This function convenient for use is code that could be executed on the
  * client and server alike.
  */
 const void *req_capsule_other_get(struct req_capsule *pill,
diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
index 1be978609c59..58f1c8bf25b0 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
@@ -616,7 +616,7 @@ out:
 }
 
 /**
- * The longest valid command string is the maxium policy name size, plus the
+ * The longest valid command string is the maximum policy name size, plus the
  * length of the " reg" substring
  */
 #define LPROCFS_NRS_WR_MAX_CMD	(NRS_POL_NAME_MAX + sizeof(" reg") - 1)
@@ -1184,7 +1184,7 @@ int lprocfs_wr_evict_client(struct file *file, const char *buffer,
 	}
 	tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
 	/* Kludge code(deadlock situation): the lprocfs lock has been held
-	 * since the client is evicted by writting client's
+	 * since the client is evicted by writing client's
 	 * uuid/nid to procfs "evict_client" entry. However,
 	 * obd_export_evict_by_uuid() will call lprocfs_remove() to destroy
 	 * the proc entries under the being destroyed export{}, so I have
diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
index 3c6bf23415f9..a47a8d807d5b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
@@ -349,7 +349,7 @@ static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags)
 /**
  * Send request reply from request \a req reply buffer.
  * \a flags defines reply types
- * Returns 0 on sucess or error code
+ * Returns 0 on success or error code
  */
 int ptlrpc_send_reply(struct ptlrpc_request *req, int flags)
 {
@@ -389,7 +389,7 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags)
 	 * ptlrpc_body in reply buffer to ptlrpc_body_v2, otherwise, the
 	 * reply buffer on client will be overflow.
 	 *
-	 * XXX Remove this whenver we drop the interoprability with such client.
+	 * XXX Remove this whenever we drop the interoprability with such client.
 	 */
 	req->rq_replen = lustre_shrink_msg(req->rq_repmsg, 0,
 					   sizeof(struct ptlrpc_body_v2), 1);
@@ -511,7 +511,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
 		CDEBUG(D_HA, "muting rpc for failed imp obd %s\n",
 		       request->rq_import->imp_obd->obd_name);
 		/* this prevents us from waiting in ptlrpc_queue_wait */
+		spin_lock(&request->rq_lock);
 		request->rq_err = 1;
+		spin_unlock(&request->rq_lock);
 		request->rq_status = -ENODEV;
 		return -ENODEV;
 	}
@@ -553,7 +555,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
 			if (rc) {
 				/* this prevents us from looping in
 				 * ptlrpc_queue_wait */
+				spin_lock(&request->rq_lock);
 				request->rq_err = 1;
+				spin_unlock(&request->rq_lock);
 				request->rq_status = rc;
 				GOTO(cleanup_bulk, rc);
 			}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
index 0abcd6d82273..bcba1c8e8693 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
@@ -1322,7 +1322,7 @@ EXPORT_SYMBOL(ptlrpc_nrs_policy_unregister);
  * Setup NRS heads on all service partitions of service \a svc, and register
  * all compatible policies on those NRS heads.
  *
- * To be called from withing ptl
+ * To be called from within ptl
  * \param[in] svc the service to setup
  *
  * \retval -ve error, the calling logic should eventually call
@@ -1736,7 +1736,7 @@ fail:
 }
 
 /**
- * Removes all policy desciptors from nrs_core::nrs_policies, and frees the
+ * Removes all policy descriptors from nrs_core::nrs_policies, and frees the
  * policy descriptors.
  *
  * Since all PTLRPC services are stopped at this point, there are no more
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
index 464479c0f00b..45c0b84621e4 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
@@ -123,7 +123,7 @@ int lustre_msg_early_size(void)
 		 * with the old client (< 2.3) which doesn't have pb_jobid
 		 * in the ptlrpc_body.
 		 *
-		 * XXX Remove this whenever we dorp interoprability with such
+		 * XXX Remove this whenever we drop interoprability with such
 		 *     client.
 		 */
 		__u32 pblen = sizeof(struct ptlrpc_body_v2);
@@ -244,15 +244,7 @@ int lustre_pack_request(struct ptlrpc_request *req, __u32 magic, int count,
 	LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
 
 	/* only use new format, we don't need to be compatible with 1.4 */
-	magic = LUSTRE_MSG_MAGIC_V2;
-
-	switch (magic) {
-	case LUSTRE_MSG_MAGIC_V2:
-		return lustre_pack_request_v2(req, count, lens, bufs);
-	default:
-		LASSERTF(0, "incorrect message magic: %08x\n", magic);
-		return -EINVAL;
-	}
+	return lustre_pack_request_v2(req, count, lens, bufs);
 }
 EXPORT_SYMBOL(lustre_pack_request);
 
@@ -1545,7 +1537,7 @@ void lustre_msg_set_jobid(struct lustre_msg *msg, char *jobid)
 		__u32 opc = lustre_msg_get_opc(msg);
 		struct ptlrpc_body *pb;
 
-		/* Don't set jobid for ldlm ast RPCs, they've been shrinked.
+		/* Don't set jobid for ldlm ast RPCs, they've been shrunk.
 		 * See the comment in ptlrpc_request_pack(). */
 		if (!opc || opc == LDLM_BL_CALLBACK ||
 		    opc == LDLM_CP_CALLBACK || opc == LDLM_GL_CALLBACK)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
index 2d26fd543d46..ca734ce079c1 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
@@ -229,7 +229,7 @@ void ptlrpcd_add_req(struct ptlrpc_request *req, pdl_policy_t policy, int idx)
 		spin_unlock(&req->rq_lock);
 		l_wait_event(req->rq_set_waitq, (req->rq_set == NULL), &lwi);
 	} else if (req->rq_set) {
-		/* If we have a vaid "rq_set", just reuse it to avoid double
+		/* If we have a valid "rq_set", just reuse it to avoid double
 		 * linked. */
 		LASSERT(req->rq_phase == RQ_PHASE_NEW);
 		LASSERT(req->rq_send_state == LUSTRE_IMP_REPLAY);
@@ -471,7 +471,7 @@ static int ptlrpcd(void *arg)
  *      be better. But it breaks former data transfer policy.
  *
  *      So we shouldn't be blind for avoiding the data transfer. We make some
- *      compromise: divide the ptlrpcd threds pool into two parts. One part is
+ *      compromise: divide the ptlrpcd threads pool into two parts. One part is
  *      for bound mode, each ptlrpcd thread in this part is bound to some CPU
  *      core. The other part is for free mode, all the ptlrpcd threads in the
  *      part can be scheduled on any CPU core. We specify some partnership
diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c
index 84c39e083ea4..48ae328ce24e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/recover.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c
@@ -105,24 +105,59 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
 	 * imp_lock is being held by ptlrpc_replay, but it's not. it's
 	 * just a little race...
 	 */
-	list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+
+	/* Replay all the committed open requests on committed_list first */
+	if (!list_empty(&imp->imp_committed_list)) {
+		tmp = imp->imp_committed_list.prev;
 		req = list_entry(tmp, struct ptlrpc_request,
 				     rq_replay_list);
 
-		/* If need to resend the last sent transno (because a
-		   reconnect has occurred), then stop on the matching
-		   req and send it again. If, however, the last sent
-		   transno has been committed then we continue replay
-		   from the next request. */
+		/* The last request on committed_list hasn't been replayed */
 		if (req->rq_transno > last_transno) {
-			if (imp->imp_resend_replay)
-				lustre_msg_add_flags(req->rq_reqmsg,
-						     MSG_RESENT);
-			break;
+			/* Since the imp_committed_list is immutable before
+			 * all of it's requests being replayed, it's safe to
+			 * use a cursor to accelerate the search */
+			imp->imp_replay_cursor = imp->imp_replay_cursor->next;
+
+			while (imp->imp_replay_cursor !=
+			       &imp->imp_committed_list) {
+				req = list_entry(imp->imp_replay_cursor,
+						 struct ptlrpc_request,
+						 rq_replay_list);
+				if (req->rq_transno > last_transno)
+					break;
+
+				req = NULL;
+				imp->imp_replay_cursor =
+					imp->imp_replay_cursor->next;
+			}
+		} else {
+			/* All requests on committed_list have been replayed */
+			imp->imp_replay_cursor = &imp->imp_committed_list;
+			req = NULL;
+		}
+	}
+
+	/* All the requests in committed list have been replayed, let's replay
+	 * the imp_replay_list */
+	if (req == NULL) {
+		list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+			req = list_entry(tmp, struct ptlrpc_request,
+					 rq_replay_list);
+
+			if (req->rq_transno > last_transno)
+				break;
+			req = NULL;
 		}
-		req = NULL;
 	}
 
+	/* If need to resend the last sent transno (because a reconnect
+	 * has occurred), then stop on the matching req and send it again.
+	 * If, however, the last sent transno has been committed then we
+	 * continue replay from the next request. */
+	if (req != NULL && imp->imp_resend_replay)
+		lustre_msg_add_flags(req->rq_reqmsg, MSG_RESENT);
+
 	spin_lock(&imp->imp_lock);
 	imp->imp_resend_replay = 0;
 	spin_unlock(&imp->imp_lock);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c
index 962b31d163de..9145dd25023b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c
@@ -779,7 +779,7 @@ again:
 	 *   e.g. ptlrpc_abort_inflight();
 	 */
 	if (!cli_ctx_is_refreshed(ctx)) {
-		/* timed out or interruptted */
+		/* timed out or interrupted */
 		req_off_ctx_list(req, ctx);
 
 		LASSERT(rc != 0);
@@ -805,7 +805,7 @@ void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode)
 	LASSERT(req->rq_cli_ctx->cc_sec);
 	LASSERT(req->rq_bulk_read == 0 || req->rq_bulk_write == 0);
 
-	/* special security flags accoding to opcode */
+	/* special security flags according to opcode */
 	switch (opcode) {
 	case OST_READ:
 	case MDS_READPAGE:
@@ -1218,7 +1218,7 @@ static void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
 	LASSERT_ATOMIC_ZERO(&sec->ps_nctx);
 	LASSERT(policy->sp_cops->destroy_sec);
 
-	CDEBUG(D_SEC, "%s@%p: being destroied\n", sec->ps_policy->sp_name, sec);
+	CDEBUG(D_SEC, "%s@%p: being destroyed\n", sec->ps_policy->sp_name, sec);
 
 	policy->sp_cops->destroy_sec(sec);
 	sptlrpc_policy_put(policy);
@@ -1264,7 +1264,7 @@ void sptlrpc_sec_put(struct ptlrpc_sec *sec)
 EXPORT_SYMBOL(sptlrpc_sec_put);
 
 /*
- * policy module is responsible for taking refrence of import
+ * policy module is responsible for taking reference of import
  */
 static
 struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp,
@@ -1419,7 +1419,7 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp,
 
 		sp = imp->imp_obd->u.cli.cl_sp_me;
 	} else {
-		/* reverse import, determine flavor from incoming reqeust */
+		/* reverse import, determine flavor from incoming request */
 		sf = *flvr;
 
 		if (sf.sf_rpc != SPTLRPC_FLVR_NULL)
@@ -2057,7 +2057,7 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 
 	/*
 	 * if it's not null flavor (which means embedded packing msg),
-	 * reset the swab mask for the comming inner msg unpacking.
+	 * reset the swab mask for the coming inner msg unpacking.
 	 */
 	if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL)
 		req->rq_req_swab_mask = 0;
@@ -2108,7 +2108,7 @@ int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 /**
  * Used by ptlrpc server, to perform transformation upon reply message.
  *
- * \post req->rq_reply_off is set to approriate server-controlled reply offset.
+ * \post req->rq_reply_off is set to appropriate server-controlled reply offset.
  * \post req->rq_repmsg and req->rq_reply_state->rs_msg becomes inaccessible.
  */
 int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
index 316103ab7c3c..f65955d40d92 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
@@ -113,7 +113,7 @@ static struct ptlrpc_enc_page_pool {
 	unsigned long    epp_st_missings;       /* # of cache missing */
 	unsigned long    epp_st_lowfree;	/* lowest free pages reached */
 	unsigned int     epp_st_max_wqlen;      /* highest waitqueue length */
-	cfs_time_t       epp_st_max_wait;       /* in jeffies */
+	cfs_time_t       epp_st_max_wait;       /* in jiffies */
 	/*
 	 * pointers to pools
 	 */
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
index 6cc3f23c27cc..bf56120abfaf 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
@@ -255,7 +255,7 @@ void sptlrpc_rule_set_free(struct sptlrpc_rule_set *rset)
 EXPORT_SYMBOL(sptlrpc_rule_set_free);
 
 /*
- * return 0 if the rule set could accomodate one more rule.
+ * return 0 if the rule set could accommodate one more rule.
  */
 int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset)
 {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
index 590fa8df8b7f..192adec5382a 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
@@ -177,7 +177,7 @@ ptlrpc_grow_req_bufs(struct ptlrpc_service_part *svcpt, int post)
 
 /**
  * Part of Rep-Ack logic.
- * Puts a lock and its mode into reply state assotiated to request reply.
+ * Puts a lock and its mode into reply state associated to request reply.
  */
 void
 ptlrpc_save_lock(struct ptlrpc_request *req,
@@ -252,7 +252,7 @@ struct rs_batch {
 static struct ptlrpc_hr_service		ptlrpc_hr;
 
 /**
- * maximum mumber of replies scheduled in one batch
+ * maximum number of replies scheduled in one batch
  */
 #define MAX_SCHEDULED 256
 
@@ -612,7 +612,7 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc,
 	INIT_LIST_HEAD(&svcpt->scp_hist_reqs);
 	INIT_LIST_HEAD(&svcpt->scp_hist_rqbds);
 
-	/* acitve requests and hp requests */
+	/* active requests and hp requests */
 	spin_lock_init(&svcpt->scp_req_lock);
 
 	/* reply states */
@@ -752,7 +752,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 	spin_lock_init(&service->srv_lock);
 	service->srv_name		= conf->psc_name;
 	service->srv_watchdog_factor	= conf->psc_watchdog_factor;
-	INIT_LIST_HEAD(&service->srv_list); /* for safty of cleanup */
+	INIT_LIST_HEAD(&service->srv_list); /* for safety of cleanup */
 
 	/* buffer configuration */
 	service->srv_nbuf_per_group	= test_req_buffer_pressure ?
@@ -1982,7 +1982,7 @@ put_conn:
 	do_gettimeofday(&work_end);
 	timediff = cfs_timeval_sub(&work_end, &work_start, NULL);
 	CDEBUG(D_RPCTRACE, "Handled RPC pname:cluuid+ref:pid:xid:nid:opc "
-	       "%s:%s+%d:%d:x"LPU64":%s:%d Request procesed in "
+	       "%s:%s+%d:%d:x"LPU64":%s:%d Request processed in "
 	       "%ldus (%ldus total) trans "LPU64" rc %d/%d\n",
 		current_comm(),
 		(request->rq_export ?
@@ -2736,7 +2736,7 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 		spin_lock(&svcpt->scp_lock);
 		--svcpt->scp_nthrs_starting;
 		if (thread_is_stopping(thread)) {
-			/* this ptlrpc_thread is being hanled
+			/* this ptlrpc_thread is being handled
 			 * by ptlrpc_svcpt_stop_threads now
 			 */
 			thread_add_flags(thread, SVC_STOPPED);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c
index 3aa445952024..3c8846006a7b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c
@@ -1152,6 +1152,8 @@ void lustre_assert_wire_constants(void)
 		 OBD_CONNECT_SHORTIO);
 	LASSERTF(OBD_CONNECT_PINGLESS == 0x4000000000000ULL, "found 0x%.16llxULL\n",
 		 OBD_CONNECT_PINGLESS);
+	LASSERTF(OBD_CONNECT_FLOCK_DEAD == 0x8000000000000ULL,
+		 "found 0x%.16llxULL\n", OBD_CONNECT_FLOCK_DEAD);
 	LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
 		(unsigned)OBD_CKSUM_CRC32);
 	LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",
diff --git a/drivers/staging/media/go7007/Kconfig b/drivers/staging/media/go7007/Kconfig
index 04bd0fba7b1f..95a3af644a92 100644
--- a/drivers/staging/media/go7007/Kconfig
+++ b/drivers/staging/media/go7007/Kconfig
@@ -13,7 +13,6 @@ config VIDEO_GO7007
 	select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
-	default N
 	---help---
 	  This is a video4linux driver for the WIS GO7007 MPEG
 	  encoder chip.
@@ -24,7 +23,6 @@ config VIDEO_GO7007
 config VIDEO_GO7007_USB
 	tristate "WIS GO7007 USB support"
 	depends on VIDEO_GO7007 && USB
-	default N
 	---help---
 	  This is a video4linux driver for the WIS GO7007 MPEG
 	  encoder chip over USB.
@@ -46,7 +44,6 @@ config VIDEO_GO7007_LOADER
 config VIDEO_GO7007_USB_S2250_BOARD
 	tristate "Sensoray 2250/2251 support"
 	depends on VIDEO_GO7007_USB && USB
-	default N
 	---help---
 	  This is a video4linux driver for the Sensoray 2250/2251 device.
 
diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c
index 16dd64920767..9eb2a20ae40a 100644
--- a/drivers/staging/media/go7007/snd-go7007.c
+++ b/drivers/staging/media/go7007/snd-go7007.c
@@ -245,8 +245,8 @@ int go7007_snd_init(struct go7007 *go)
 	spin_lock_init(&gosnd->lock);
 	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
 	gosnd->capturing = 0;
-	ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0,
-			      &gosnd->card);
+	ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0,
+			   &gosnd->card);
 	if (ret < 0) {
 		kfree(gosnd);
 		return ret;
@@ -257,7 +257,6 @@ int go7007_snd_init(struct go7007 *go)
 		kfree(gosnd);
 		return ret;
 	}
-	snd_card_set_dev(gosnd->card, go->dev);
 	ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
 	if (ret < 0) {
 		snd_card_free(gosnd->card);
diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/staging/media/solo6x10/solo6x10-g723.c
index 1db18c7972a0..74f037b6166c 100644
--- a/drivers/staging/media/solo6x10/solo6x10-g723.c
+++ b/drivers/staging/media/solo6x10/solo6x10-g723.c
@@ -366,8 +366,9 @@ int solo_g723_init(struct solo_dev *solo_dev)
 	/* Allows for easier mapping between video and audio */
 	sprintf(name, "Softlogic%d", solo_dev->vfd->num);
 
-	ret = snd_card_create(SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
-			      &solo_dev->snd_card);
+	ret = snd_card_new(&solo_dev->pdev->dev,
+			   SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
+			   &solo_dev->snd_card);
 	if (ret < 0)
 		return ret;
 
@@ -377,7 +378,6 @@ int solo_g723_init(struct solo_dev *solo_dev)
 	strcpy(card->shortname, "SOLO-6x10 Audio");
 	sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
 		pci_name(solo_dev->pdev), solo_dev->pdev->irq);
-	snd_card_set_dev(card, &solo_dev->pdev->dev);
 
 	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
 	if (ret < 0)
diff --git a/drivers/staging/nokia_h4p/Kconfig b/drivers/staging/nokia_h4p/Kconfig
new file mode 100644
index 000000000000..4336c0ad065b
--- /dev/null
+++ b/drivers/staging/nokia_h4p/Kconfig
@@ -0,0 +1,9 @@
+config BT_NOKIA_H4P
+	tristate "HCI driver with H4 Nokia extensions"
+	depends on BT && ARCH_OMAP
+	help
+	  Bluetooth HCI driver with H4 extensions.  This driver provides
+	  support for H4+ Bluetooth chip with vendor-specific H4 extensions.
+
+	  Say Y here to compile support for h4 extended devices into the kernel
+	  or say M to compile it as module (btnokia_h4p).
diff --git a/drivers/staging/nokia_h4p/Makefile b/drivers/staging/nokia_h4p/Makefile
new file mode 100644
index 000000000000..9625db4a9af3
--- /dev/null
+++ b/drivers/staging/nokia_h4p/Makefile
@@ -0,0 +1,6 @@
+
+obj-$(CONFIG_BT_NOKIA_H4P)		+= btnokia_h4p.o
+btnokia_h4p-objs := nokia_core.o nokia_fw.o nokia_uart.o nokia_fw-csr.o \
+		nokia_fw-bcm.o nokia_fw-ti1273.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/nokia_h4p/TODO b/drivers/staging/nokia_h4p/TODO
new file mode 100644
index 000000000000..d997afe14173
--- /dev/null
+++ b/drivers/staging/nokia_h4p/TODO
@@ -0,0 +1,140 @@
+Few attempts to submission have been made, last review comments were received in
+
+Date: Wed, 15 Jan 2014 19:01:51 -0800
+From: Marcel Holtmann <marcel@holtmann.org>
+Subject: Re: [PATCH v6] Bluetooth: Add hci_h4p driver
+
+Some code refactoring is still needed.
+
+TODO:
+
+> +++ b/drivers/bluetooth/hci_h4p.h
+
+can we please get the naming straight. File names do not start with
+hci_ anymore. We moved away from it since that term is too generic.
+
+> +#define FW_NAME_TI1271_LE    "ti1273_le.bin"
+> +#define FW_NAME_TI1271               "ti1273.bin"
+> +#define FW_NAME_BCM2048              "bcmfw.bin"
+> +#define FW_NAME_CSR          "bc4fw.bin"
+
+We do these have to be global in a header file. This should be
+confined to the specific firmware part.
+
+> +struct hci_h4p_info {
+
+Can we please get rid of the hci_ prefix for everything. Copying from
+drivers that are over 10 years old is not a good idea. Please look at
+recent ones.
+
+> +     struct timer_list lazy_release;
+
+Timer? Not delayed work?
+
+> +void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val);
+> +u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset);
+> +void hci_h4p_set_rts(struct hci_h4p_info *info, int active);
+> +int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active, int timeout_ms);
+> +void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+> +void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+> +void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed);
+> +int hci_h4p_reset_uart(struct hci_h4p_info *info);
+> +void hci_h4p_init_uart(struct hci_h4p_info *info);
+> +void hci_h4p_enable_tx(struct hci_h4p_info *info);
+> +void hci_h4p_store_regs(struct hci_h4p_info *info);
+> +void hci_h4p_restore_regs(struct hci_h4p_info *info);
+> +void hci_h4p_smart_idle(struct hci_h4p_info *info, bool enable);
+
+These are a lot of public functions. Are they all really needed or can
+the code be done smart.
+
+> +static ssize_t hci_h4p_store_bdaddr(struct device *dev,
+> +                                 struct device_attribute *attr,
+> +                                 const char *buf, size_t count)
+> +{
+> +     struct hci_h4p_info *info = dev_get_drvdata(dev);
+
+Since none of these devices can function without having a valid
+address, the way this should work is that we should not register the
+HCI device when probing the platform device.
+    
+The HCI device should be registered once a valid address has been
+written into the sysfs file. I do not want to play the tricks with
+bringing up the device without a valid address.
+
+> +     hdev->close = hci_h4p_hci_close;
+> +     hdev->flush = hci_h4p_hci_flush;
+> +     hdev->send = hci_h4p_hci_send_frame;
+    
+It needs to use hdev->setup to load the firmware. I assume the
+firmware only needs to be loaded once. That is exactly what
+hdev->setup does. It gets executed once.
+    
+> +     set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+Is this quirk really needed? Normally only Bluetooth 1.1 and early
+devices qualify for it.
+
+> +static int hci_h4p_bcm_set_bdaddr(struct hci_h4p_info *info, struct sk_buff *skb)
+> +{
+> +     int i;
+> +     static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+> +     int not_valid;
+
+Has this actually been confirmed that we can just randomly set an
+address out of the Nokia range. I do not think so. This is a pretty
+bad idea.
+
+I have no interest in merging a driver with such a hack.
+
+> +     not_valid = 1;
+> +     for (i = 0; i < 6; i++) {
+> +             if (info->bd_addr[i] != 0x00) {
+> +                     not_valid = 0;
+> +                     break;
+> +             }   
+> +     }
+
+Anybody every heard of memcmp or bacmp and BDADDR_ANY?
+
+> +             if (not_valid) {
+> +                     dev_info(info->dev, "Valid bluetooth address not found,"
+> +                                     " setting some random\n");
+> +                     /* When address is not valid, use some random */
+> +                     memcpy(info->bd_addr, nokia_oui, 3);
+> +                     get_random_bytes(info->bd_addr + 3, 3);
+> +             }
+
+
+And why does every single chip firmware does this differently. Seriously, this is a mess.
+
+> +void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+> +{
+> +     switch (info->man_id) {
+> +     case H4P_ID_CSR:
+> +             hci_h4p_bc4_parse_fw_event(info, skb);
+> +             break;
+...
+> +}
+
+We have proper HCI sync command handling in recent kernels. I really
+do not know why this is hand coded these days. Check how the Intel
+firmware loading inside btusb.c does it.
+
+> +inline u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset)
+> +{ 
+> +     return __raw_readb(info->uart_base + (offset << 2));
+> +}
+
+Inline in a *.c file for a non-static function. Makes no sense to me.
+
+> +/**
+> + * struct hci_h4p_platform data - hci_h4p Platform data structure
+> + */
+> +struct hci_h4p_platform_data {
+
+please have a proper name here. For example
+btnokia_h4p_platform_data.
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
+Pavel Machek <pavel@ucw.cz>
diff --git a/drivers/staging/nokia_h4p/hci_h4p.h b/drivers/staging/nokia_h4p/hci_h4p.h
new file mode 100644
index 000000000000..fd7a6407f20c
--- /dev/null
+++ b/drivers/staging/nokia_h4p/hci_h4p.h
@@ -0,0 +1,228 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef __DRIVERS_BLUETOOTH_HCI_H4P_H
+#define __DRIVERS_BLUETOOTH_HCI_H4P_H
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#define FW_NAME_TI1271_PRELE	"ti1273_prele.bin"
+#define FW_NAME_TI1271_LE	"ti1273_le.bin"
+#define FW_NAME_TI1271		"ti1273.bin"
+#define FW_NAME_BCM2048		"bcmfw.bin"
+#define FW_NAME_CSR		"bc4fw.bin"
+
+#define UART_SYSC_OMAP_RESET	0x03
+#define UART_SYSS_RESETDONE	0x01
+#define UART_OMAP_SCR_EMPTY_THR	0x08
+#define UART_OMAP_SCR_WAKEUP	0x10
+#define UART_OMAP_SSR_WAKEUP	0x02
+#define UART_OMAP_SSR_TXFULL	0x01
+
+#define UART_OMAP_SYSC_IDLEMODE		0x03
+#define UART_OMAP_SYSC_IDLEMASK		(3 << UART_OMAP_SYSC_IDLEMODE)
+
+#define UART_OMAP_SYSC_FORCE_IDLE	(0 << UART_OMAP_SYSC_IDLEMODE)
+#define UART_OMAP_SYSC_NO_IDLE		(1 << UART_OMAP_SYSC_IDLEMODE)
+#define UART_OMAP_SYSC_SMART_IDLE	(2 << UART_OMAP_SYSC_IDLEMODE)
+
+#define H4P_TRANSFER_MODE		1
+#define H4P_SCHED_TRANSFER_MODE		2
+#define H4P_ACTIVE_MODE			3
+
+struct hci_h4p_info {
+	struct timer_list lazy_release;
+	struct hci_dev *hdev;
+	spinlock_t lock;
+
+	void __iomem *uart_base;
+	unsigned long uart_phys_base;
+	int irq;
+	struct device *dev;
+	u8 chip_type;
+	u8 bt_wakeup_gpio;
+	u8 host_wakeup_gpio;
+	u8 reset_gpio;
+	u8 reset_gpio_shared;
+	u8 bt_sysclk;
+	u8 man_id;
+	u8 ver_id;
+
+	struct sk_buff_head fw_queue;
+	struct sk_buff *alive_cmd_skb;
+	struct completion init_completion;
+	struct completion fw_completion;
+	struct completion test_completion;
+	int fw_error;
+	int init_error;
+
+	struct sk_buff_head txq;
+
+	struct sk_buff *rx_skb;
+	long rx_count;
+	unsigned long rx_state;
+	unsigned long garbage_bytes;
+
+	u8 bd_addr[6];
+	struct sk_buff_head *fw_q;
+
+	int pm_enabled;
+	int tx_enabled;
+	int autorts;
+	int rx_enabled;
+	unsigned long pm_flags;
+
+	int tx_clocks_en;
+	int rx_clocks_en;
+	spinlock_t clocks_lock;
+	struct clk *uart_iclk;
+	struct clk *uart_fclk;
+	atomic_t clk_users;
+	u16 dll;
+	u16 dlh;
+	u16 ier;
+	u16 mdr1;
+	u16 efr;
+};
+
+struct hci_h4p_radio_hdr {
+	__u8 evt;
+	__u8 dlen;
+} __attribute__ ((packed));
+
+struct hci_h4p_neg_hdr {
+	__u8 dlen;
+} __attribute__ ((packed));
+#define H4P_NEG_HDR_SIZE 1
+
+#define H4P_NEG_REQ	0x00
+#define H4P_NEG_ACK	0x20
+#define H4P_NEG_NAK	0x40
+
+#define H4P_PROTO_PKT	0x44
+#define H4P_PROTO_BYTE	0x4c
+
+#define H4P_ID_CSR	0x02
+#define H4P_ID_BCM2048	0x04
+#define H4P_ID_TI1271	0x31
+
+struct hci_h4p_neg_cmd {
+	__u8	ack;
+	__u16	baud;
+	__u16	unused1;
+	__u8	proto;
+	__u16	sys_clk;
+	__u16	unused2;
+} __attribute__ ((packed));
+
+struct hci_h4p_neg_evt {
+	__u8	ack;
+	__u16	baud;
+	__u16	unused1;
+	__u8	proto;
+	__u16	sys_clk;
+	__u16	unused2;
+	__u8	man_id;
+	__u8	ver_id;
+} __attribute__ ((packed));
+
+#define H4P_ALIVE_REQ	0x55
+#define H4P_ALIVE_RESP	0xcc
+
+struct hci_h4p_alive_hdr {
+	__u8	dlen;
+} __attribute__ ((packed));
+#define H4P_ALIVE_HDR_SIZE 1
+
+struct hci_h4p_alive_pkt {
+	__u8	mid;
+	__u8	unused;
+} __attribute__ ((packed));
+
+#define MAX_BAUD_RATE		921600
+#define BC4_MAX_BAUD_RATE	3692300
+#define UART_CLOCK		48000000
+#define BT_INIT_DIVIDER		320
+#define BT_BAUDRATE_DIVIDER	384000000
+#define BT_SYSCLK_DIV		1000
+#define INIT_SPEED		120000
+
+#define H4_TYPE_SIZE		1
+#define H4_RADIO_HDR_SIZE	2
+
+/* H4+ packet types */
+#define H4_CMD_PKT		0x01
+#define H4_ACL_PKT		0x02
+#define H4_SCO_PKT		0x03
+#define H4_EVT_PKT		0x04
+#define H4_NEG_PKT		0x06
+#define H4_ALIVE_PKT		0x07
+#define H4_RADIO_PKT		0x08
+
+/* TX states */
+#define WAIT_FOR_PKT_TYPE	1
+#define WAIT_FOR_HEADER		2
+#define WAIT_FOR_DATA		3
+
+struct hci_fw_event {
+	struct hci_event_hdr hev;
+	struct hci_ev_cmd_complete cmd;
+	u8 status;
+} __attribute__ ((packed));
+
+int hci_h4p_send_alive_packet(struct hci_h4p_info *info);
+
+void hci_h4p_bcm_parse_fw_event(struct hci_h4p_info *info,
+				struct sk_buff *skb);
+int hci_h4p_bcm_send_fw(struct hci_h4p_info *info,
+			struct sk_buff_head *fw_queue);
+
+void hci_h4p_bc4_parse_fw_event(struct hci_h4p_info *info,
+				struct sk_buff *skb);
+int hci_h4p_bc4_send_fw(struct hci_h4p_info *info,
+			struct sk_buff_head *fw_queue);
+
+void hci_h4p_ti1273_parse_fw_event(struct hci_h4p_info *info,
+				    struct sk_buff *skb);
+int hci_h4p_ti1273_send_fw(struct hci_h4p_info *info,
+			    struct sk_buff_head *fw_queue);
+
+int hci_h4p_read_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue);
+int hci_h4p_send_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue);
+void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb);
+
+void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val);
+u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset);
+void hci_h4p_set_rts(struct hci_h4p_info *info, int active);
+int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active, int timeout_ms);
+void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed);
+int hci_h4p_reset_uart(struct hci_h4p_info *info);
+void hci_h4p_init_uart(struct hci_h4p_info *info);
+void hci_h4p_enable_tx(struct hci_h4p_info *info);
+void hci_h4p_store_regs(struct hci_h4p_info *info);
+void hci_h4p_restore_regs(struct hci_h4p_info *info);
+void hci_h4p_smart_idle(struct hci_h4p_info *info, bool enable);
+
+#endif /* __DRIVERS_BLUETOOTH_HCI_H4P_H */
diff --git a/drivers/staging/nokia_h4p/nokia_core.c b/drivers/staging/nokia_h4p/nokia_core.c
new file mode 100644
index 000000000000..5da84b06eff3
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_core.c
@@ -0,0 +1,1205 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia 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.
+ *
+ * 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
+ *
+ * Thanks to all the Nokia people that helped with this driver,
+ * including Ville Tervo and Roger Quadros.
+ *
+ * Power saving functionality was removed from this driver to make
+ * merging easier.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/serial_reg.h>
+#include <linux/skbuff.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/timer.h>
+#include <linux/kthread.h>
+#include <linux/io.h>
+#include <linux/completion.h>
+#include <linux/sizes.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#include <linux/platform_data/bt-nokia-h4p.h>
+
+#include "hci_h4p.h"
+
+/* This should be used in function that cannot release clocks */
+static void hci_h4p_set_clk(struct hci_h4p_info *info, int *clock, int enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->clocks_lock, flags);
+	if (enable && !*clock) {
+		BT_DBG("Enabling %p", clock);
+		clk_prepare_enable(info->uart_fclk);
+		clk_prepare_enable(info->uart_iclk);
+		if (atomic_read(&info->clk_users) == 0)
+			hci_h4p_restore_regs(info);
+		atomic_inc(&info->clk_users);
+	}
+
+	if (!enable && *clock) {
+		BT_DBG("Disabling %p", clock);
+		if (atomic_dec_and_test(&info->clk_users))
+			hci_h4p_store_regs(info);
+		clk_disable_unprepare(info->uart_fclk);
+		clk_disable_unprepare(info->uart_iclk);
+	}
+
+	*clock = enable;
+	spin_unlock_irqrestore(&info->clocks_lock, flags);
+}
+
+static void hci_h4p_lazy_clock_release(unsigned long data)
+{
+	struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (!info->tx_enabled)
+		hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+/* Power management functions */
+void hci_h4p_smart_idle(struct hci_h4p_info *info, bool enable)
+{
+	u8 v;
+
+	v = hci_h4p_inb(info, UART_OMAP_SYSC);
+	v &= ~(UART_OMAP_SYSC_IDLEMASK);
+
+	if (enable)
+		v |= UART_OMAP_SYSC_SMART_IDLE;
+	else
+		v |= UART_OMAP_SYSC_NO_IDLE;
+
+	hci_h4p_outb(info, UART_OMAP_SYSC, v);
+}
+
+static inline void h4p_schedule_pm(struct hci_h4p_info *info)
+{
+}
+
+static void hci_h4p_disable_tx(struct hci_h4p_info *info)
+{
+	if (!info->pm_enabled)
+		return;
+
+	/* Re-enable smart-idle */
+	hci_h4p_smart_idle(info, 1);
+
+	gpio_set_value(info->bt_wakeup_gpio, 0);
+	mod_timer(&info->lazy_release, jiffies + msecs_to_jiffies(100));
+	info->tx_enabled = 0;
+}
+
+void hci_h4p_enable_tx(struct hci_h4p_info *info)
+{
+	unsigned long flags;
+
+	if (!info->pm_enabled)
+		return;
+
+	h4p_schedule_pm(info);
+
+	spin_lock_irqsave(&info->lock, flags);
+	del_timer(&info->lazy_release);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+	info->tx_enabled = 1;
+	gpio_set_value(info->bt_wakeup_gpio, 1);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+		     UART_IER_THRI);
+	/*
+	 * Disable smart-idle as UART TX interrupts
+	 * are not wake-up capable
+	 */
+	hci_h4p_smart_idle(info, 0);
+
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static void hci_h4p_disable_rx(struct hci_h4p_info *info)
+{
+	if (!info->pm_enabled)
+		return;
+
+	info->rx_enabled = 0;
+
+	if (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR)
+		return;
+
+	if (!(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT))
+		return;
+
+	__hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+	info->autorts = 0;
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+}
+
+static void hci_h4p_enable_rx(struct hci_h4p_info *info)
+{
+	if (!info->pm_enabled)
+		return;
+
+	h4p_schedule_pm(info);
+
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+	info->rx_enabled = 1;
+
+	if (!(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT))
+		return;
+
+	__hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+	info->autorts = 1;
+}
+
+/* Negotiation functions */
+int hci_h4p_send_alive_packet(struct hci_h4p_info *info)
+{
+	struct hci_h4p_alive_hdr *hdr;
+	struct hci_h4p_alive_pkt *pkt;
+	struct sk_buff *skb;
+	unsigned long flags;
+	int len;
+
+	BT_DBG("Sending alive packet");
+
+	len = H4_TYPE_SIZE + sizeof(*hdr) + sizeof(*pkt);
+	skb = bt_skb_alloc(len, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	memset(skb->data, 0x00, len);
+	*skb_put(skb, 1) = H4_ALIVE_PKT;
+	hdr = (struct hci_h4p_alive_hdr *)skb_put(skb, sizeof(*hdr));
+	hdr->dlen = sizeof(*pkt);
+	pkt = (struct hci_h4p_alive_pkt *)skb_put(skb, sizeof(*pkt));
+	pkt->mid = H4P_ALIVE_REQ;
+
+	skb_queue_tail(&info->txq, skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+		     UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	BT_DBG("Alive packet sent");
+
+	return 0;
+}
+
+static void hci_h4p_alive_packet(struct hci_h4p_info *info,
+				 struct sk_buff *skb)
+{
+	struct hci_h4p_alive_hdr *hdr;
+	struct hci_h4p_alive_pkt *pkt;
+
+	BT_DBG("Received alive packet");
+	hdr = (struct hci_h4p_alive_hdr *)skb->data;
+	if (hdr->dlen != sizeof(*pkt)) {
+		dev_err(info->dev, "Corrupted alive message\n");
+		info->init_error = -EIO;
+		goto finish_alive;
+	}
+
+	pkt = (struct hci_h4p_alive_pkt *)skb_pull(skb, sizeof(*hdr));
+	if (pkt->mid != H4P_ALIVE_RESP) {
+		dev_err(info->dev, "Could not negotiate hci_h4p settings\n");
+		info->init_error = -EINVAL;
+	}
+
+finish_alive:
+	complete(&info->init_completion);
+	kfree_skb(skb);
+}
+
+static int hci_h4p_send_negotiation(struct hci_h4p_info *info)
+{
+	struct hci_h4p_neg_cmd *neg_cmd;
+	struct hci_h4p_neg_hdr *neg_hdr;
+	struct sk_buff *skb;
+	unsigned long flags;
+	int err, len;
+	u16 sysclk;
+
+	BT_DBG("Sending negotiation..");
+
+	switch (info->bt_sysclk) {
+	case 1:
+		sysclk = 12000;
+		break;
+	case 2:
+		sysclk = 38400;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	len = sizeof(*neg_cmd) + sizeof(*neg_hdr) + H4_TYPE_SIZE;
+	skb = bt_skb_alloc(len, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	memset(skb->data, 0x00, len);
+	*skb_put(skb, 1) = H4_NEG_PKT;
+	neg_hdr = (struct hci_h4p_neg_hdr *)skb_put(skb, sizeof(*neg_hdr));
+	neg_cmd = (struct hci_h4p_neg_cmd *)skb_put(skb, sizeof(*neg_cmd));
+
+	neg_hdr->dlen = sizeof(*neg_cmd);
+	neg_cmd->ack = H4P_NEG_REQ;
+	neg_cmd->baud = cpu_to_le16(BT_BAUDRATE_DIVIDER/MAX_BAUD_RATE);
+	neg_cmd->proto = H4P_PROTO_BYTE;
+	neg_cmd->sys_clk = cpu_to_le16(sysclk);
+
+	hci_h4p_change_speed(info, INIT_SPEED);
+
+	hci_h4p_set_rts(info, 1);
+	info->init_error = 0;
+	init_completion(&info->init_completion);
+	skb_queue_tail(&info->txq, skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+		     UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	if (!wait_for_completion_interruptible_timeout(&info->init_completion,
+				msecs_to_jiffies(1000)))
+		return -ETIMEDOUT;
+
+	if (info->init_error < 0)
+		return info->init_error;
+
+	/* Change to operational settings */
+	hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+	hci_h4p_set_rts(info, 0);
+	hci_h4p_change_speed(info, MAX_BAUD_RATE);
+
+	err = hci_h4p_wait_for_cts(info, 1, 100);
+	if (err < 0)
+		return err;
+
+	hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+	init_completion(&info->init_completion);
+	err = hci_h4p_send_alive_packet(info);
+
+	if (err < 0)
+		return err;
+
+	if (!wait_for_completion_interruptible_timeout(&info->init_completion,
+				msecs_to_jiffies(1000)))
+		return -ETIMEDOUT;
+
+	if (info->init_error < 0)
+		return info->init_error;
+
+	BT_DBG("Negotiation successful");
+	return 0;
+}
+
+static void hci_h4p_negotiation_packet(struct hci_h4p_info *info,
+				       struct sk_buff *skb)
+{
+	struct hci_h4p_neg_hdr *hdr;
+	struct hci_h4p_neg_evt *evt;
+
+	hdr = (struct hci_h4p_neg_hdr *)skb->data;
+	if (hdr->dlen != sizeof(*evt)) {
+		info->init_error = -EIO;
+		goto finish_neg;
+	}
+
+	evt = (struct hci_h4p_neg_evt *)skb_pull(skb, sizeof(*hdr));
+
+	if (evt->ack != H4P_NEG_ACK) {
+		dev_err(info->dev, "Could not negotiate hci_h4p settings\n");
+		info->init_error = -EINVAL;
+	}
+
+	info->man_id = evt->man_id;
+	info->ver_id = evt->ver_id;
+
+finish_neg:
+
+	complete(&info->init_completion);
+	kfree_skb(skb);
+}
+
+/* H4 packet handling functions */
+static int hci_h4p_get_hdr_len(struct hci_h4p_info *info, u8 pkt_type)
+{
+	long retval;
+
+	switch (pkt_type) {
+	case H4_EVT_PKT:
+		retval = HCI_EVENT_HDR_SIZE;
+		break;
+	case H4_ACL_PKT:
+		retval = HCI_ACL_HDR_SIZE;
+		break;
+	case H4_SCO_PKT:
+		retval = HCI_SCO_HDR_SIZE;
+		break;
+	case H4_NEG_PKT:
+		retval = H4P_NEG_HDR_SIZE;
+		break;
+	case H4_ALIVE_PKT:
+		retval = H4P_ALIVE_HDR_SIZE;
+		break;
+	case H4_RADIO_PKT:
+		retval = H4_RADIO_HDR_SIZE;
+		break;
+	default:
+		dev_err(info->dev, "Unknown H4 packet type 0x%.2x\n", pkt_type);
+		retval = -1;
+		break;
+	}
+
+	return retval;
+}
+
+static unsigned int hci_h4p_get_data_len(struct hci_h4p_info *info,
+					 struct sk_buff *skb)
+{
+	long retval = -1;
+	struct hci_acl_hdr *acl_hdr;
+	struct hci_sco_hdr *sco_hdr;
+	struct hci_event_hdr *evt_hdr;
+	struct hci_h4p_neg_hdr *neg_hdr;
+	struct hci_h4p_alive_hdr *alive_hdr;
+	struct hci_h4p_radio_hdr *radio_hdr;
+
+	switch (bt_cb(skb)->pkt_type) {
+	case H4_EVT_PKT:
+		evt_hdr = (struct hci_event_hdr *)skb->data;
+		retval = evt_hdr->plen;
+		break;
+	case H4_ACL_PKT:
+		acl_hdr = (struct hci_acl_hdr *)skb->data;
+		retval = le16_to_cpu(acl_hdr->dlen);
+		break;
+	case H4_SCO_PKT:
+		sco_hdr = (struct hci_sco_hdr *)skb->data;
+		retval = sco_hdr->dlen;
+		break;
+	case H4_RADIO_PKT:
+		radio_hdr = (struct hci_h4p_radio_hdr *)skb->data;
+		retval = radio_hdr->dlen;
+		break;
+	case H4_NEG_PKT:
+		neg_hdr = (struct hci_h4p_neg_hdr *)skb->data;
+		retval = neg_hdr->dlen;
+		break;
+	case H4_ALIVE_PKT:
+		alive_hdr = (struct hci_h4p_alive_hdr *)skb->data;
+		retval = alive_hdr->dlen;
+		break;
+	}
+
+	return retval;
+}
+
+static inline void hci_h4p_recv_frame(struct hci_h4p_info *info,
+				      struct sk_buff *skb)
+{
+	if (unlikely(!test_bit(HCI_RUNNING, &info->hdev->flags))) {
+		switch (bt_cb(skb)->pkt_type) {
+		case H4_NEG_PKT:
+			hci_h4p_negotiation_packet(info, skb);
+			info->rx_state = WAIT_FOR_PKT_TYPE;
+			return;
+		case H4_ALIVE_PKT:
+			hci_h4p_alive_packet(info, skb);
+			info->rx_state = WAIT_FOR_PKT_TYPE;
+			return;
+		}
+
+		if (!test_bit(HCI_UP, &info->hdev->flags)) {
+			BT_DBG("fw_event");
+			hci_h4p_parse_fw_event(info, skb);
+			return;
+		}
+	}
+
+	hci_recv_frame(info->hdev, skb);
+	BT_DBG("Frame sent to upper layer");
+}
+
+static inline void hci_h4p_handle_byte(struct hci_h4p_info *info, u8 byte)
+{
+	switch (info->rx_state) {
+	case WAIT_FOR_PKT_TYPE:
+		bt_cb(info->rx_skb)->pkt_type = byte;
+		info->rx_count = hci_h4p_get_hdr_len(info, byte);
+		if (info->rx_count < 0) {
+			info->hdev->stat.err_rx++;
+			kfree_skb(info->rx_skb);
+			info->rx_skb = NULL;
+		} else {
+			info->rx_state = WAIT_FOR_HEADER;
+		}
+		break;
+	case WAIT_FOR_HEADER:
+		info->rx_count--;
+		*skb_put(info->rx_skb, 1) = byte;
+		if (info->rx_count != 0)
+			break;
+		info->rx_count = hci_h4p_get_data_len(info, info->rx_skb);
+		if (info->rx_count > skb_tailroom(info->rx_skb)) {
+			dev_err(info->dev, "frame too long\n");
+			info->garbage_bytes = info->rx_count
+				- skb_tailroom(info->rx_skb);
+			kfree_skb(info->rx_skb);
+			info->rx_skb = NULL;
+			break;
+		}
+		info->rx_state = WAIT_FOR_DATA;
+		break;
+	case WAIT_FOR_DATA:
+		info->rx_count--;
+		*skb_put(info->rx_skb, 1) = byte;
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	if (info->rx_count == 0) {
+		/* H4+ devices should always send word aligned packets */
+		if (!(info->rx_skb->len % 2))
+			info->garbage_bytes++;
+		hci_h4p_recv_frame(info, info->rx_skb);
+		info->rx_skb = NULL;
+	}
+}
+
+static void hci_h4p_rx_tasklet(unsigned long data)
+{
+	u8 byte;
+	struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+
+	BT_DBG("tasklet woke up");
+	BT_DBG("rx_tasklet woke up");
+
+	while (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR) {
+		byte = hci_h4p_inb(info, UART_RX);
+		if (info->garbage_bytes) {
+			info->garbage_bytes--;
+			continue;
+		}
+		if (info->rx_skb == NULL) {
+			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE,
+						    GFP_ATOMIC | GFP_DMA);
+			if (!info->rx_skb) {
+				dev_err(info->dev,
+					"No memory for new packet\n");
+				goto finish_rx;
+			}
+			info->rx_state = WAIT_FOR_PKT_TYPE;
+			info->rx_skb->dev = (void *)info->hdev;
+		}
+		info->hdev->stat.byte_rx++;
+		hci_h4p_handle_byte(info, byte);
+	}
+
+	if (!info->rx_enabled) {
+		if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT &&
+						  info->autorts) {
+			__hci_h4p_set_auto_ctsrts(info, 0 , UART_EFR_RTS);
+			info->autorts = 0;
+		}
+		/* Flush posted write to avoid spurious interrupts */
+		hci_h4p_inb(info, UART_OMAP_SCR);
+		hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+	}
+
+finish_rx:
+	BT_DBG("rx_ended");
+}
+
+static void hci_h4p_tx_tasklet(unsigned long data)
+{
+	unsigned int sent = 0;
+	struct sk_buff *skb;
+	struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+
+	BT_DBG("tasklet woke up");
+	BT_DBG("tx_tasklet woke up");
+
+	if (info->autorts != info->rx_enabled) {
+		if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT) {
+			if (info->autorts && !info->rx_enabled) {
+				__hci_h4p_set_auto_ctsrts(info, 0,
+							  UART_EFR_RTS);
+				info->autorts = 0;
+			}
+			if (!info->autorts && info->rx_enabled) {
+				__hci_h4p_set_auto_ctsrts(info, 1,
+							  UART_EFR_RTS);
+				info->autorts = 1;
+			}
+		} else {
+			hci_h4p_outb(info, UART_OMAP_SCR,
+				     hci_h4p_inb(info, UART_OMAP_SCR) |
+				     UART_OMAP_SCR_EMPTY_THR);
+			goto finish_tx;
+		}
+	}
+
+	skb = skb_dequeue(&info->txq);
+	if (!skb) {
+		/* No data in buffer */
+		BT_DBG("skb ready");
+		if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT) {
+			hci_h4p_outb(info, UART_IER,
+				     hci_h4p_inb(info, UART_IER) &
+				     ~UART_IER_THRI);
+			hci_h4p_inb(info, UART_OMAP_SCR);
+			hci_h4p_disable_tx(info);
+			return;
+		}
+		hci_h4p_outb(info, UART_OMAP_SCR,
+			     hci_h4p_inb(info, UART_OMAP_SCR) |
+			     UART_OMAP_SCR_EMPTY_THR);
+		goto finish_tx;
+	}
+
+	/* Copy data to tx fifo */
+	while (!(hci_h4p_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) &&
+	       (sent < skb->len)) {
+		hci_h4p_outb(info, UART_TX, skb->data[sent]);
+		sent++;
+	}
+
+	info->hdev->stat.byte_tx += sent;
+	if (skb->len == sent) {
+		kfree_skb(skb);
+	} else {
+		skb_pull(skb, sent);
+		skb_queue_head(&info->txq, skb);
+	}
+
+	hci_h4p_outb(info, UART_OMAP_SCR, hci_h4p_inb(info, UART_OMAP_SCR) &
+						     ~UART_OMAP_SCR_EMPTY_THR);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+						 UART_IER_THRI);
+
+finish_tx:
+	/* Flush posted write to avoid spurious interrupts */
+	hci_h4p_inb(info, UART_OMAP_SCR);
+
+}
+
+static irqreturn_t hci_h4p_interrupt(int irq, void *data)
+{
+	struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+	u8 iir, msr;
+	int ret;
+
+	ret = IRQ_NONE;
+
+	iir = hci_h4p_inb(info, UART_IIR);
+	if (iir & UART_IIR_NO_INT)
+		return IRQ_HANDLED;
+
+	BT_DBG("In interrupt handler iir 0x%.2x", iir);
+
+	iir &= UART_IIR_ID;
+
+	if (iir == UART_IIR_MSI) {
+		msr = hci_h4p_inb(info, UART_MSR);
+		ret = IRQ_HANDLED;
+	}
+	if (iir == UART_IIR_RLSI) {
+		hci_h4p_inb(info, UART_RX);
+		hci_h4p_inb(info, UART_LSR);
+		ret = IRQ_HANDLED;
+	}
+
+	if (iir == UART_IIR_RDI) {
+		hci_h4p_rx_tasklet((unsigned long)data);
+		ret = IRQ_HANDLED;
+	}
+
+	if (iir == UART_IIR_THRI) {
+		hci_h4p_tx_tasklet((unsigned long)data);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static irqreturn_t hci_h4p_wakeup_interrupt(int irq, void *dev_inst)
+{
+	struct hci_h4p_info *info = dev_inst;
+	int should_wakeup;
+	struct hci_dev *hdev;
+
+	if (!info->hdev)
+		return IRQ_HANDLED;
+
+	should_wakeup = gpio_get_value(info->host_wakeup_gpio);
+	hdev = info->hdev;
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		if (should_wakeup == 1)
+			complete_all(&info->test_completion);
+
+		return IRQ_HANDLED;
+	}
+
+	BT_DBG("gpio interrupt %d", should_wakeup);
+
+	/* Check if wee have missed some interrupts */
+	if (info->rx_enabled == should_wakeup)
+		return IRQ_HANDLED;
+
+	if (should_wakeup)
+		hci_h4p_enable_rx(info);
+	else
+		hci_h4p_disable_rx(info);
+
+	return IRQ_HANDLED;
+}
+
+static inline void hci_h4p_set_pm_limits(struct hci_h4p_info *info, bool set)
+{
+	struct hci_h4p_platform_data *bt_plat_data = info->dev->platform_data;
+	const char *sset = set ? "set" : "clear";
+
+	if (unlikely(!bt_plat_data || !bt_plat_data->set_pm_limits))
+		return;
+
+	if (set != !!test_bit(H4P_ACTIVE_MODE, &info->pm_flags)) {
+		bt_plat_data->set_pm_limits(info->dev, set);
+		if (set)
+			set_bit(H4P_ACTIVE_MODE, &info->pm_flags);
+		else
+			clear_bit(H4P_ACTIVE_MODE, &info->pm_flags);
+		BT_DBG("Change pm constraints to: %s", sset);
+		return;
+	}
+
+	BT_DBG("pm constraints remains: %s", sset);
+}
+
+static int hci_h4p_reset(struct hci_h4p_info *info)
+{
+	int err;
+
+	err = hci_h4p_reset_uart(info);
+	if (err < 0) {
+		dev_err(info->dev, "Uart reset failed\n");
+		return err;
+	}
+	hci_h4p_init_uart(info);
+	hci_h4p_set_rts(info, 0);
+
+	gpio_set_value(info->reset_gpio, 0);
+	gpio_set_value(info->bt_wakeup_gpio, 1);
+	msleep(10);
+
+	if (gpio_get_value(info->host_wakeup_gpio) == 1) {
+		dev_err(info->dev, "host_wakeup_gpio not low\n");
+		return -EPROTO;
+	}
+
+	init_completion(&info->test_completion);
+	gpio_set_value(info->reset_gpio, 1);
+
+	if (!wait_for_completion_interruptible_timeout(&info->test_completion,
+						       msecs_to_jiffies(100))) {
+		dev_err(info->dev, "wakeup test timed out\n");
+		complete_all(&info->test_completion);
+		return -EPROTO;
+	}
+
+	err = hci_h4p_wait_for_cts(info, 1, 100);
+	if (err < 0) {
+		dev_err(info->dev, "No cts from bt chip\n");
+		return err;
+	}
+
+	hci_h4p_set_rts(info, 1);
+
+	return 0;
+}
+
+/* hci callback functions */
+static int hci_h4p_hci_flush(struct hci_dev *hdev)
+{
+	struct hci_h4p_info *info = hci_get_drvdata(hdev);
+	skb_queue_purge(&info->txq);
+
+	return 0;
+}
+
+static int hci_h4p_bt_wakeup_test(struct hci_h4p_info *info)
+{
+	/*
+	 * Test Sequence:
+	 * Host de-asserts the BT_WAKE_UP line.
+	 * Host polls the UART_CTS line, waiting for it to be de-asserted.
+	 * Host asserts the BT_WAKE_UP line.
+	 * Host polls the UART_CTS line, waiting for it to be asserted.
+	 * Host de-asserts the BT_WAKE_UP line (allow the Bluetooth device to
+	 * sleep).
+	 * Host polls the UART_CTS line, waiting for it to be de-asserted.
+	 */
+	int err;
+	int ret = -ECOMM;
+
+	if (!info)
+		return -EINVAL;
+
+	/* Disable wakeup interrupts */
+	disable_irq(gpio_to_irq(info->host_wakeup_gpio));
+
+	gpio_set_value(info->bt_wakeup_gpio, 0);
+	err = hci_h4p_wait_for_cts(info, 0, 100);
+	if (err) {
+		dev_warn(info->dev, "bt_wakeup_test: fail: "
+			 "CTS low timed out: %d\n", err);
+		goto out;
+	}
+
+	gpio_set_value(info->bt_wakeup_gpio, 1);
+	err = hci_h4p_wait_for_cts(info, 1, 100);
+	if (err) {
+		dev_warn(info->dev, "bt_wakeup_test: fail: "
+			 "CTS high timed out: %d\n", err);
+		goto out;
+	}
+
+	gpio_set_value(info->bt_wakeup_gpio, 0);
+	err = hci_h4p_wait_for_cts(info, 0, 100);
+	if (err) {
+		dev_warn(info->dev, "bt_wakeup_test: fail: "
+			 "CTS re-low timed out: %d\n", err);
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+
+	/* Re-enable wakeup interrupts */
+	enable_irq(gpio_to_irq(info->host_wakeup_gpio));
+
+	return ret;
+}
+
+static int hci_h4p_hci_open(struct hci_dev *hdev)
+{
+	struct hci_h4p_info *info;
+	int err, retries = 0;
+	struct sk_buff_head fw_queue;
+	unsigned long flags;
+
+	info = hci_get_drvdata(hdev);
+
+	if (test_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	/* TI1271 has HW bug and boot up might fail. Retry up to three times */
+again:
+
+	info->rx_enabled = 1;
+	info->rx_state = WAIT_FOR_PKT_TYPE;
+	info->rx_count = 0;
+	info->garbage_bytes = 0;
+	info->rx_skb = NULL;
+	info->pm_enabled = 0;
+	init_completion(&info->fw_completion);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+	skb_queue_head_init(&fw_queue);
+
+	err = hci_h4p_reset(info);
+	if (err < 0)
+		goto err_clean;
+
+	hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_CTS | UART_EFR_RTS);
+	info->autorts = 1;
+
+	err = hci_h4p_send_negotiation(info);
+
+	err = hci_h4p_read_fw(info, &fw_queue);
+	if (err < 0) {
+		dev_err(info->dev, "Cannot read firmware\n");
+		goto err_clean;
+	}
+
+	err = hci_h4p_send_fw(info, &fw_queue);
+	if (err < 0) {
+		dev_err(info->dev, "Sending firmware failed.\n");
+		goto err_clean;
+	}
+
+	info->pm_enabled = 1;
+
+	err = hci_h4p_bt_wakeup_test(info);
+	if (err < 0) {
+		dev_err(info->dev, "BT wakeup test failed.\n");
+		goto err_clean;
+	}
+
+	spin_lock_irqsave(&info->lock, flags);
+	info->rx_enabled = gpio_get_value(info->host_wakeup_gpio);
+	hci_h4p_set_clk(info, &info->rx_clocks_en, info->rx_enabled);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+
+	kfree_skb(info->alive_cmd_skb);
+	info->alive_cmd_skb = NULL;
+	set_bit(HCI_RUNNING, &hdev->flags);
+
+	BT_DBG("hci up and running");
+	return 0;
+
+err_clean:
+	hci_h4p_hci_flush(hdev);
+	hci_h4p_reset_uart(info);
+	del_timer_sync(&info->lazy_release);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+	gpio_set_value(info->reset_gpio, 0);
+	gpio_set_value(info->bt_wakeup_gpio, 0);
+	skb_queue_purge(&fw_queue);
+	kfree_skb(info->alive_cmd_skb);
+	info->alive_cmd_skb = NULL;
+	kfree_skb(info->rx_skb);
+	info->rx_skb = NULL;
+
+	if (retries++ < 3) {
+		dev_err(info->dev, "FW loading try %d fail. Retry.\n", retries);
+		goto again;
+	}
+
+	return err;
+}
+
+static int hci_h4p_hci_close(struct hci_dev *hdev)
+{
+	struct hci_h4p_info *info = hci_get_drvdata(hdev);
+
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	hci_h4p_hci_flush(hdev);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+	hci_h4p_reset_uart(info);
+	del_timer_sync(&info->lazy_release);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+	hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+	gpio_set_value(info->reset_gpio, 0);
+	gpio_set_value(info->bt_wakeup_gpio, 0);
+	kfree_skb(info->rx_skb);
+
+	return 0;
+}
+
+static int hci_h4p_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_h4p_info *info;
+	int err = 0;
+
+	BT_DBG("dev %p, skb %p", hdev, skb);
+
+	info = hci_get_drvdata(hdev);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		dev_warn(info->dev, "Frame for non-running device\n");
+		return -EIO;
+	}
+
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	}
+
+	/* Push frame type to skb */
+	*skb_push(skb, 1) = (bt_cb(skb)->pkt_type);
+	/* We should allways send word aligned data to h4+ devices */
+	if (skb->len % 2) {
+		err = skb_pad(skb, 1);
+		if (!err)
+			*skb_put(skb, 1) = 0x00;
+	}
+	if (err)
+		return err;
+
+	skb_queue_tail(&info->txq, skb);
+	hci_h4p_enable_tx(info);
+
+	return 0;
+}
+
+static ssize_t hci_h4p_store_bdaddr(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct hci_h4p_info *info = dev_get_drvdata(dev);
+	unsigned int bdaddr[6];
+	int ret, i;
+
+	ret = sscanf(buf, "%2x:%2x:%2x:%2x:%2x:%2x\n",
+			&bdaddr[0], &bdaddr[1], &bdaddr[2],
+			&bdaddr[3], &bdaddr[4], &bdaddr[5]);
+
+	if (ret != 6)
+		return -EINVAL;
+
+	for (i = 0; i < 6; i++) {
+		if (bdaddr[i] > 0xff)
+			return -EINVAL;
+		info->bd_addr[i] = bdaddr[i] & 0xff;
+	}
+
+	return count;
+}
+
+static ssize_t hci_h4p_show_bdaddr(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct hci_h4p_info *info = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%pMR\n", info->bd_addr);
+}
+
+static DEVICE_ATTR(bdaddr, S_IRUGO | S_IWUSR, hci_h4p_show_bdaddr,
+		   hci_h4p_store_bdaddr);
+
+static int hci_h4p_sysfs_create_files(struct device *dev)
+{
+	return device_create_file(dev, &dev_attr_bdaddr);
+}
+
+static void hci_h4p_sysfs_remove_files(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_bdaddr);
+}
+
+static int hci_h4p_register_hdev(struct hci_h4p_info *info)
+{
+	struct hci_dev *hdev;
+
+	/* Initialize and register HCI device */
+
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		dev_err(info->dev, "Can't allocate memory for device\n");
+		return -ENOMEM;
+	}
+	info->hdev = hdev;
+
+	hdev->bus = HCI_UART;
+	hci_set_drvdata(hdev, info);
+
+	hdev->open = hci_h4p_hci_open;
+	hdev->close = hci_h4p_hci_close;
+	hdev->flush = hci_h4p_hci_flush;
+	hdev->send = hci_h4p_hci_send_frame;
+	set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+	SET_HCIDEV_DEV(hdev, info->dev);
+
+	if (hci_h4p_sysfs_create_files(info->dev) < 0) {
+		dev_err(info->dev, "failed to create sysfs files\n");
+		goto free;
+	}
+
+	if (hci_register_dev(hdev) >= 0)
+		return 0;
+
+	dev_err(info->dev, "hci_register failed %s.\n", hdev->name);
+	hci_h4p_sysfs_remove_files(info->dev);
+free:
+	hci_free_dev(info->hdev);
+	return -ENODEV;
+}
+
+static int hci_h4p_probe(struct platform_device *pdev)
+{
+	struct hci_h4p_platform_data *bt_plat_data;
+	struct hci_h4p_info *info;
+	int err;
+
+	dev_info(&pdev->dev, "Registering HCI H4P device\n");
+	info = devm_kzalloc(&pdev->dev, sizeof(struct hci_h4p_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = &pdev->dev;
+	info->tx_enabled = 1;
+	info->rx_enabled = 1;
+	spin_lock_init(&info->lock);
+	spin_lock_init(&info->clocks_lock);
+	skb_queue_head_init(&info->txq);
+
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "Could not get Bluetooth config data\n");
+		return -ENODATA;
+	}
+
+	bt_plat_data = pdev->dev.platform_data;
+	info->chip_type = bt_plat_data->chip_type;
+	info->bt_wakeup_gpio = bt_plat_data->bt_wakeup_gpio;
+	info->host_wakeup_gpio = bt_plat_data->host_wakeup_gpio;
+	info->reset_gpio = bt_plat_data->reset_gpio;
+	info->reset_gpio_shared = bt_plat_data->reset_gpio_shared;
+	info->bt_sysclk = bt_plat_data->bt_sysclk;
+
+	BT_DBG("RESET gpio: %d", info->reset_gpio);
+	BT_DBG("BTWU gpio: %d", info->bt_wakeup_gpio);
+	BT_DBG("HOSTWU gpio: %d", info->host_wakeup_gpio);
+	BT_DBG("sysclk: %d", info->bt_sysclk);
+
+	init_completion(&info->test_completion);
+	complete_all(&info->test_completion);
+
+	if (!info->reset_gpio_shared) {
+		err = devm_gpio_request_one(&pdev->dev, info->reset_gpio,
+					    GPIOF_OUT_INIT_LOW, "bt_reset");
+		if (err < 0) {
+			dev_err(&pdev->dev, "Cannot get GPIO line %d\n",
+				info->reset_gpio);
+			return err;
+		}
+	}
+
+	err = devm_gpio_request_one(&pdev->dev, info->bt_wakeup_gpio,
+				    GPIOF_OUT_INIT_LOW, "bt_wakeup");
+
+	if (err < 0) {
+		dev_err(info->dev, "Cannot get GPIO line 0x%d",
+			info->bt_wakeup_gpio);
+		return err;
+	}
+
+	err = devm_gpio_request_one(&pdev->dev, info->host_wakeup_gpio,
+				    GPIOF_DIR_IN, "host_wakeup");
+	if (err < 0) {
+		dev_err(info->dev, "Cannot get GPIO line %d",
+		       info->host_wakeup_gpio);
+		return err;
+	}
+
+	info->irq = bt_plat_data->uart_irq;
+	info->uart_base = devm_ioremap(&pdev->dev, bt_plat_data->uart_base, SZ_2K);
+	info->uart_iclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_iclk);
+	info->uart_fclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_fclk);
+
+	err = devm_request_irq(&pdev->dev, info->irq, hci_h4p_interrupt, IRQF_DISABLED,
+			       "hci_h4p", info);
+	if (err < 0) {
+		dev_err(info->dev, "hci_h4p: unable to get IRQ %d\n", info->irq);
+		return err;
+	}
+
+	err = devm_request_irq(&pdev->dev, gpio_to_irq(info->host_wakeup_gpio),
+			  hci_h4p_wakeup_interrupt,  IRQF_TRIGGER_FALLING |
+			  IRQF_TRIGGER_RISING | IRQF_DISABLED,
+			  "hci_h4p_wkup", info);
+	if (err < 0) {
+		dev_err(info->dev, "hci_h4p: unable to get wakeup IRQ %d\n",
+			  gpio_to_irq(info->host_wakeup_gpio));
+		return err;
+	}
+
+	err = irq_set_irq_wake(gpio_to_irq(info->host_wakeup_gpio), 1);
+	if (err < 0) {
+		dev_err(info->dev, "hci_h4p: unable to set wakeup for IRQ %d\n",
+				gpio_to_irq(info->host_wakeup_gpio));
+		return err;
+	}
+
+	init_timer_deferrable(&info->lazy_release);
+	info->lazy_release.function = hci_h4p_lazy_clock_release;
+	info->lazy_release.data = (unsigned long)info;
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+	err = hci_h4p_reset_uart(info);
+	if (err < 0)
+		return err;
+	gpio_set_value(info->reset_gpio, 0);
+	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+
+	platform_set_drvdata(pdev, info);
+
+	if (hci_h4p_register_hdev(info) < 0) {
+		dev_err(info->dev, "failed to register hci_h4p hci device\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hci_h4p_remove(struct platform_device *pdev)
+{
+	struct hci_h4p_info *info;
+
+	info = platform_get_drvdata(pdev);
+
+	hci_h4p_sysfs_remove_files(info->dev);
+	hci_h4p_hci_close(info->hdev);
+	hci_unregister_dev(info->hdev);
+	hci_free_dev(info->hdev);
+
+	return 0;
+}
+
+static struct platform_driver hci_h4p_driver = {
+	.probe		= hci_h4p_probe,
+	.remove		= hci_h4p_remove,
+	.driver		= {
+		.name	= "hci_h4p",
+	},
+};
+
+module_platform_driver(hci_h4p_driver);
+
+MODULE_ALIAS("platform:hci_h4p");
+MODULE_DESCRIPTION("Bluetooth h4 driver with nokia extensions");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ville Tervo");
+MODULE_FIRMWARE(FW_NAME_TI1271_PRELE);
+MODULE_FIRMWARE(FW_NAME_TI1271_LE);
+MODULE_FIRMWARE(FW_NAME_TI1271);
+MODULE_FIRMWARE(FW_NAME_BCM2048);
+MODULE_FIRMWARE(FW_NAME_CSR);
diff --git a/drivers/staging/nokia_h4p/nokia_fw-bcm.c b/drivers/staging/nokia_h4p/nokia_fw-bcm.c
new file mode 100644
index 000000000000..e8912bfc0a91
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_fw-bcm.c
@@ -0,0 +1,147 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia 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.
+ *
+ * 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/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+static int hci_h4p_bcm_set_bdaddr(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+	int i;
+	static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+	int not_valid;
+
+	not_valid = 1;
+	for (i = 0; i < 6; i++) {
+		if (info->bd_addr[i] != 0x00) {
+			not_valid = 0;
+			break;
+		}
+	}
+
+	if (not_valid) {
+		dev_info(info->dev, "Valid bluetooth address not found, setting some random\n");
+		/* When address is not valid, use some random but Nokia MAC */
+		memcpy(info->bd_addr, nokia_oui, 3);
+		get_random_bytes(info->bd_addr + 3, 3);
+	}
+
+	for (i = 0; i < 6; i++)
+		skb->data[9 - i] = info->bd_addr[i];
+
+	return 0;
+}
+
+void hci_h4p_bcm_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+	struct sk_buff *fw_skb;
+	int err;
+	unsigned long flags;
+
+	if (skb->data[5] != 0x00) {
+		dev_err(info->dev, "Firmware sending command failed 0x%.2x\n",
+			skb->data[5]);
+		info->fw_error = -EPROTO;
+	}
+
+	kfree_skb(skb);
+
+	fw_skb = skb_dequeue(info->fw_q);
+	if (fw_skb == NULL || info->fw_error) {
+		complete(&info->fw_completion);
+		return;
+	}
+
+	if (fw_skb->data[1] == 0x01 && fw_skb->data[2] == 0xfc && fw_skb->len >= 10) {
+		BT_DBG("Setting bluetooth address");
+		err = hci_h4p_bcm_set_bdaddr(info, fw_skb);
+		if (err < 0) {
+			kfree_skb(fw_skb);
+			info->fw_error = err;
+			complete(&info->fw_completion);
+			return;
+		}
+	}
+
+	skb_queue_tail(&info->txq, fw_skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+			UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+
+int hci_h4p_bcm_send_fw(struct hci_h4p_info *info,
+			struct sk_buff_head *fw_queue)
+{
+	struct sk_buff *skb;
+	unsigned long flags, time;
+
+	info->fw_error = 0;
+
+	BT_DBG("Sending firmware");
+
+	time = jiffies;
+
+	info->fw_q = fw_queue;
+	skb = skb_dequeue(fw_queue);
+	if (!skb)
+		return -ENODATA;
+
+	BT_DBG("Sending commands");
+
+	/*
+	 * Disable smart-idle as UART TX interrupts
+	 * are not wake-up capable
+	 */
+	hci_h4p_smart_idle(info, 0);
+
+	/* Check if this is bd_address packet */
+	init_completion(&info->fw_completion);
+	skb_queue_tail(&info->txq, skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+			UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	if (!wait_for_completion_timeout(&info->fw_completion,
+				msecs_to_jiffies(2000))) {
+		dev_err(info->dev, "No reply to fw command\n");
+		return -ETIMEDOUT;
+	}
+
+	if (info->fw_error) {
+		dev_err(info->dev, "FW error\n");
+		return -EPROTO;
+	}
+
+	BT_DBG("Firmware sent in %d msecs",
+		   jiffies_to_msecs(jiffies-time));
+
+	hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+	hci_h4p_set_rts(info, 0);
+	hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+	hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+
+	return 0;
+}
diff --git a/drivers/staging/nokia_h4p/nokia_fw-csr.c b/drivers/staging/nokia_h4p/nokia_fw-csr.c
new file mode 100644
index 000000000000..e39c4a31a879
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_fw-csr.c
@@ -0,0 +1,150 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia 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.
+ *
+ * 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/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+void hci_h4p_bc4_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+	/* Check if this is fw packet */
+	if (skb->data[0] != 0xff) {
+		hci_recv_frame(info->hdev, skb);
+		return;
+	}
+
+	if (skb->data[11] || skb->data[12]) {
+		dev_err(info->dev, "Firmware sending command failed\n");
+		info->fw_error = -EPROTO;
+	}
+
+	kfree_skb(skb);
+	complete(&info->fw_completion);
+}
+
+int hci_h4p_bc4_send_fw(struct hci_h4p_info *info,
+			struct sk_buff_head *fw_queue)
+{
+	static const u8 nokia_oui[3] = {0x00, 0x19, 0x4F};
+	struct sk_buff *skb;
+	unsigned int offset;
+	int retries, count, i, not_valid;
+	unsigned long flags;
+
+	info->fw_error = 0;
+
+	BT_DBG("Sending firmware");
+	skb = skb_dequeue(fw_queue);
+
+	if (!skb)
+		return -ENOMSG;
+
+	/* Check if this is bd_address packet */
+	if (skb->data[15] == 0x01 && skb->data[16] == 0x00) {
+		offset = 21;
+		skb->data[offset + 1] = 0x00;
+		skb->data[offset + 5] = 0x00;
+
+		not_valid = 1;
+		for (i = 0; i < 6; i++) {
+			if (info->bd_addr[i] != 0x00) {
+				not_valid = 0;
+				break;
+			}
+		}
+
+		if (not_valid) {
+			dev_info(info->dev, "Valid bluetooth address not found,"
+					" setting some random\n");
+			/* When address is not valid, use some random */
+			memcpy(info->bd_addr, nokia_oui, 3);
+			get_random_bytes(info->bd_addr + 3, 3);
+		}
+
+		skb->data[offset + 7] = info->bd_addr[0];
+		skb->data[offset + 6] = info->bd_addr[1];
+		skb->data[offset + 4] = info->bd_addr[2];
+		skb->data[offset + 0] = info->bd_addr[3];
+		skb->data[offset + 3] = info->bd_addr[4];
+		skb->data[offset + 2] = info->bd_addr[5];
+	}
+
+	for (count = 1; ; count++) {
+		BT_DBG("Sending firmware command %d", count);
+		init_completion(&info->fw_completion);
+		skb_queue_tail(&info->txq, skb);
+		spin_lock_irqsave(&info->lock, flags);
+		hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+							 UART_IER_THRI);
+		spin_unlock_irqrestore(&info->lock, flags);
+
+		skb = skb_dequeue(fw_queue);
+		if (!skb)
+			break;
+
+		if (!wait_for_completion_timeout(&info->fw_completion,
+						 msecs_to_jiffies(1000))) {
+			dev_err(info->dev, "No reply to fw command\n");
+			return -ETIMEDOUT;
+		}
+
+		if (info->fw_error) {
+			dev_err(info->dev, "FW error\n");
+			return -EPROTO;
+		}
+	};
+
+	/* Wait for chip warm reset */
+	retries = 100;
+	while ((!skb_queue_empty(&info->txq) ||
+	       !(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT)) &&
+	       retries--) {
+		msleep(10);
+	}
+	if (!retries) {
+		dev_err(info->dev, "Transmitter not empty\n");
+		return -ETIMEDOUT;
+	}
+
+	hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+
+	if (hci_h4p_wait_for_cts(info, 1, 100)) {
+		dev_err(info->dev, "cts didn't deassert after final speed\n");
+		return -ETIMEDOUT;
+	}
+
+	retries = 100;
+	do {
+		init_completion(&info->init_completion);
+		hci_h4p_send_alive_packet(info);
+		retries--;
+	} while (!wait_for_completion_timeout(&info->init_completion, 100) &&
+		 retries > 0);
+
+	if (!retries) {
+		dev_err(info->dev, "No alive reply after speed change\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
diff --git a/drivers/staging/nokia_h4p/nokia_fw-ti1273.c b/drivers/staging/nokia_h4p/nokia_fw-ti1273.c
new file mode 100644
index 000000000000..f5500f71c839
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_fw-ti1273.c
@@ -0,0 +1,110 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2009 Nokia 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.
+ *
+ * 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/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+static struct sk_buff_head *fw_q;
+
+void hci_h4p_ti1273_parse_fw_event(struct hci_h4p_info *info,
+			struct sk_buff *skb)
+{
+	struct sk_buff *fw_skb;
+	unsigned long flags;
+
+	if (skb->data[5] != 0x00) {
+		dev_err(info->dev, "Firmware sending command failed 0x%.2x\n",
+			skb->data[5]);
+		info->fw_error = -EPROTO;
+	}
+
+	kfree_skb(skb);
+
+	fw_skb = skb_dequeue(fw_q);
+	if (fw_skb == NULL || info->fw_error) {
+		complete(&info->fw_completion);
+		return;
+	}
+
+	skb_queue_tail(&info->txq, fw_skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+			UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+
+int hci_h4p_ti1273_send_fw(struct hci_h4p_info *info,
+			struct sk_buff_head *fw_queue)
+{
+	struct sk_buff *skb;
+	unsigned long flags, time;
+
+	info->fw_error = 0;
+
+	BT_DBG("Sending firmware");
+
+	time = jiffies;
+
+	fw_q = fw_queue;
+	skb = skb_dequeue(fw_queue);
+	if (!skb)
+		return -ENODATA;
+
+	BT_DBG("Sending commands");
+	/* Check if this is bd_address packet */
+	init_completion(&info->fw_completion);
+	hci_h4p_smart_idle(info, 0);
+	skb_queue_tail(&info->txq, skb);
+	spin_lock_irqsave(&info->lock, flags);
+	hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+			UART_IER_THRI);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	if (!wait_for_completion_timeout(&info->fw_completion,
+				msecs_to_jiffies(2000))) {
+		dev_err(info->dev, "No reply to fw command\n");
+		return -ETIMEDOUT;
+	}
+
+	if (info->fw_error) {
+		dev_err(info->dev, "FW error\n");
+		return -EPROTO;
+	}
+
+	BT_DBG("Firmware sent in %d msecs",
+		   jiffies_to_msecs(jiffies-time));
+
+	hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+	hci_h4p_set_rts(info, 0);
+	hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+	if (hci_h4p_wait_for_cts(info, 1, 100)) {
+		dev_err(info->dev,
+			"cts didn't go down after final speed change\n");
+		return -ETIMEDOUT;
+	}
+	hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+
+	return 0;
+}
diff --git a/drivers/staging/nokia_h4p/nokia_fw.c b/drivers/staging/nokia_h4p/nokia_fw.c
new file mode 100644
index 000000000000..cfea61cd59e9
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_fw.c
@@ -0,0 +1,195 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/firmware.h>
+#include <linux/clk.h>
+
+#include <net/bluetooth/bluetooth.h>
+
+#include "hci_h4p.h"
+
+static int fw_pos;
+
+/* Firmware handling */
+static int hci_h4p_open_firmware(struct hci_h4p_info *info,
+				 const struct firmware **fw_entry)
+{
+	int err;
+
+	fw_pos = 0;
+	BT_DBG("Opening firmware man_id 0x%.2x ver_id 0x%.2x",
+			info->man_id, info->ver_id);
+	switch (info->man_id) {
+	case H4P_ID_TI1271:
+		switch (info->ver_id) {
+		case 0xe1:
+			err = request_firmware(fw_entry, FW_NAME_TI1271_PRELE,
+						info->dev);
+			break;
+		case 0xd1:
+		case 0xf1:
+			err = request_firmware(fw_entry, FW_NAME_TI1271_LE,
+						info->dev);
+			break;
+		default:
+			err = request_firmware(fw_entry, FW_NAME_TI1271,
+						info->dev);
+		}
+		break;
+	case H4P_ID_CSR:
+		err = request_firmware(fw_entry, FW_NAME_CSR, info->dev);
+		break;
+	case H4P_ID_BCM2048:
+		err = request_firmware(fw_entry, FW_NAME_BCM2048, info->dev);
+		break;
+	default:
+		dev_err(info->dev, "Invalid chip type\n");
+		*fw_entry = NULL;
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static void hci_h4p_close_firmware(const struct firmware *fw_entry)
+{
+	release_firmware(fw_entry);
+}
+
+/* Read fw. Return length of the command. If no more commands in
+ * fw 0 is returned. In error case return value is negative.
+ */
+static int hci_h4p_read_fw_cmd(struct hci_h4p_info *info, struct sk_buff **skb,
+			       const struct firmware *fw_entry, gfp_t how)
+{
+	unsigned int cmd_len;
+
+	if (fw_pos >= fw_entry->size)
+		return 0;
+
+	if (fw_pos + 2 > fw_entry->size) {
+		dev_err(info->dev, "Corrupted firmware image 1\n");
+		return -EMSGSIZE;
+	}
+
+	cmd_len = fw_entry->data[fw_pos++];
+	cmd_len += fw_entry->data[fw_pos++] << 8;
+	if (cmd_len == 0)
+		return 0;
+
+	if (fw_pos + cmd_len > fw_entry->size) {
+		dev_err(info->dev, "Corrupted firmware image 2\n");
+		return -EMSGSIZE;
+	}
+
+	*skb = bt_skb_alloc(cmd_len, how);
+	if (!*skb) {
+		dev_err(info->dev, "Cannot reserve memory for buffer\n");
+		return -ENOMEM;
+	}
+	memcpy(skb_put(*skb, cmd_len), &fw_entry->data[fw_pos], cmd_len);
+
+	fw_pos += cmd_len;
+
+	return (*skb)->len;
+}
+
+int hci_h4p_read_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue)
+{
+	const struct firmware *fw_entry = NULL;
+	struct sk_buff *skb = NULL;
+	int err;
+
+	err = hci_h4p_open_firmware(info, &fw_entry);
+	if (err < 0 || !fw_entry)
+		goto err_clean;
+
+	while ((err = hci_h4p_read_fw_cmd(info, &skb, fw_entry, GFP_KERNEL))) {
+		if (err < 0 || !skb)
+			goto err_clean;
+
+		skb_queue_tail(fw_queue, skb);
+	}
+
+	/* Chip detection code does neg and alive stuff
+	 * discard two first skbs */
+	skb = skb_dequeue(fw_queue);
+	if (!skb) {
+		err = -EMSGSIZE;
+		goto err_clean;
+	}
+	kfree_skb(skb);
+	skb = skb_dequeue(fw_queue);
+	if (!skb) {
+		err = -EMSGSIZE;
+		goto err_clean;
+	}
+	kfree_skb(skb);
+
+err_clean:
+	hci_h4p_close_firmware(fw_entry);
+	return err;
+}
+
+int hci_h4p_send_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue)
+{
+	int err;
+
+	switch (info->man_id) {
+	case H4P_ID_CSR:
+		err = hci_h4p_bc4_send_fw(info, fw_queue);
+		break;
+	case H4P_ID_TI1271:
+		err = hci_h4p_ti1273_send_fw(info, fw_queue);
+		break;
+	case H4P_ID_BCM2048:
+		err = hci_h4p_bcm_send_fw(info, fw_queue);
+		break;
+	default:
+		dev_err(info->dev, "Don't know how to send firmware\n");
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+	switch (info->man_id) {
+	case H4P_ID_CSR:
+		hci_h4p_bc4_parse_fw_event(info, skb);
+		break;
+	case H4P_ID_TI1271:
+		hci_h4p_ti1273_parse_fw_event(info, skb);
+		break;
+	case H4P_ID_BCM2048:
+		hci_h4p_bcm_parse_fw_event(info, skb);
+		break;
+	default:
+		dev_err(info->dev, "Don't know how to parse fw event\n");
+		info->fw_error = -EINVAL;
+	}
+
+	return;
+}
diff --git a/drivers/staging/nokia_h4p/nokia_uart.c b/drivers/staging/nokia_h4p/nokia_uart.c
new file mode 100644
index 000000000000..0fb57de4b750
--- /dev/null
+++ b/drivers/staging/nokia_h4p/nokia_uart.c
@@ -0,0 +1,199 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2005, 2006 Nokia 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.
+ *
+ * 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/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <linux/io.h>
+
+#include "hci_h4p.h"
+
+inline void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val)
+{
+	__raw_writeb(val, info->uart_base + (offset << 2));
+}
+
+inline u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset)
+{
+	return __raw_readb(info->uart_base + (offset << 2));
+}
+
+void hci_h4p_set_rts(struct hci_h4p_info *info, int active)
+{
+	u8 b;
+
+	b = hci_h4p_inb(info, UART_MCR);
+	if (active)
+		b |= UART_MCR_RTS;
+	else
+		b &= ~UART_MCR_RTS;
+	hci_h4p_outb(info, UART_MCR, b);
+}
+
+int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active,
+			 int timeout_ms)
+{
+	unsigned long timeout;
+	int state;
+
+	timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	for (;;) {
+		state = hci_h4p_inb(info, UART_MSR) & UART_MSR_CTS;
+		if (active) {
+			if (state)
+				return 0;
+		} else {
+			if (!state)
+				return 0;
+		}
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		msleep(1);
+	}
+}
+
+void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
+{
+	u8 lcr, b;
+
+	lcr = hci_h4p_inb(info, UART_LCR);
+	hci_h4p_outb(info, UART_LCR, 0xbf);
+	b = hci_h4p_inb(info, UART_EFR);
+	if (on)
+		b |= which;
+	else
+		b &= ~which;
+	hci_h4p_outb(info, UART_EFR, b);
+	hci_h4p_outb(info, UART_LCR, lcr);
+}
+
+void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock, flags);
+	__hci_h4p_set_auto_ctsrts(info, on, which);
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed)
+{
+	unsigned int divisor;
+	u8 lcr, mdr1;
+
+	BT_DBG("Setting speed %lu", speed);
+
+	if (speed >= 460800) {
+		divisor = UART_CLOCK / 13 / speed;
+		mdr1 = 3;
+	} else {
+		divisor = UART_CLOCK / 16 / speed;
+		mdr1 = 0;
+	}
+
+	/* Make sure UART mode is disabled */
+	hci_h4p_outb(info, UART_OMAP_MDR1, 7);
+
+	lcr = hci_h4p_inb(info, UART_LCR);
+	hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);     /* Set DLAB */
+	hci_h4p_outb(info, UART_DLL, divisor & 0xff);    /* Set speed */
+	hci_h4p_outb(info, UART_DLM, divisor >> 8);
+	hci_h4p_outb(info, UART_LCR, lcr);
+
+	/* Make sure UART mode is enabled */
+	hci_h4p_outb(info, UART_OMAP_MDR1, mdr1);
+}
+
+int hci_h4p_reset_uart(struct hci_h4p_info *info)
+{
+	int count = 0;
+
+	/* Reset the UART */
+	hci_h4p_outb(info, UART_OMAP_SYSC, UART_SYSC_OMAP_RESET);
+	while (!(hci_h4p_inb(info, UART_OMAP_SYSS) & UART_SYSS_RESETDONE)) {
+		if (count++ > 100) {
+			dev_err(info->dev, "hci_h4p: UART reset timeout\n");
+			return -ENODEV;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+void hci_h4p_store_regs(struct hci_h4p_info *info)
+{
+	u16 lcr = 0;
+
+	lcr = hci_h4p_inb(info, UART_LCR);
+	hci_h4p_outb(info, UART_LCR, 0xBF);
+	info->dll = hci_h4p_inb(info, UART_DLL);
+	info->dlh = hci_h4p_inb(info, UART_DLM);
+	info->efr = hci_h4p_inb(info, UART_EFR);
+	hci_h4p_outb(info, UART_LCR, lcr);
+	info->mdr1 = hci_h4p_inb(info, UART_OMAP_MDR1);
+	info->ier = hci_h4p_inb(info, UART_IER);
+}
+
+void hci_h4p_restore_regs(struct hci_h4p_info *info)
+{
+	u16 lcr = 0;
+
+	hci_h4p_init_uart(info);
+
+	hci_h4p_outb(info, UART_OMAP_MDR1, 7);
+	lcr = hci_h4p_inb(info, UART_LCR);
+	hci_h4p_outb(info, UART_LCR, 0xBF);
+	hci_h4p_outb(info, UART_DLL, info->dll);    /* Set speed */
+	hci_h4p_outb(info, UART_DLM, info->dlh);
+	hci_h4p_outb(info, UART_EFR, info->efr);
+	hci_h4p_outb(info, UART_LCR, lcr);
+	hci_h4p_outb(info, UART_OMAP_MDR1, info->mdr1);
+	hci_h4p_outb(info, UART_IER, info->ier);
+}
+
+void hci_h4p_init_uart(struct hci_h4p_info *info)
+{
+	u8 mcr, efr;
+
+	/* Enable and setup FIFO */
+	hci_h4p_outb(info, UART_OMAP_MDR1, 0x00);
+
+	hci_h4p_outb(info, UART_LCR, 0xbf);
+	efr = hci_h4p_inb(info, UART_EFR);
+	hci_h4p_outb(info, UART_EFR, UART_EFR_ECB);
+	hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
+	mcr = hci_h4p_inb(info, UART_MCR);
+	hci_h4p_outb(info, UART_MCR, UART_MCR_TCRTLR);
+	hci_h4p_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO |
+			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
+			(3 << 6) | (0 << 4));
+	hci_h4p_outb(info, UART_LCR, 0xbf);
+	hci_h4p_outb(info, UART_TI752_TLR, 0xed);
+	hci_h4p_outb(info, UART_TI752_TCR, 0xef);
+	hci_h4p_outb(info, UART_EFR, efr);
+	hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
+	hci_h4p_outb(info, UART_MCR, 0x00);
+	hci_h4p_outb(info, UART_LCR, UART_LCR_WLEN8);
+	hci_h4p_outb(info, UART_IER, UART_IER_RDI);
+	hci_h4p_outb(info, UART_OMAP_SYSC, (1 << 0) | (1 << 2) | (2 << 3));
+}
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index e2663b189c66..aec98958f795 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -37,7 +37,7 @@
 /* Load Delay Locked Loop (DLL) settings for clock delay */
 #define MEM_DLL_CLOCK_DELAY	(1<<0)
 /* Memory controller power down function */
-#define MEM_POWER_DOWN  	(1<<8)
+#define MEM_POWER_DOWN		(1<<8)
 /* Memory controller software reset */
 #define MEM_SOFT_RESET		(1<<0)
 
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
index 5d965cf06d59..e7138ed325dd 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -664,32 +664,26 @@ void oz_binding_add(const char *net_dev)
 {
 	struct oz_binding *binding;
 
-	binding = kmalloc(sizeof(struct oz_binding), GFP_KERNEL);
-	if (binding) {
-		binding->ptype.type = __constant_htons(OZ_ETHERTYPE);
-		binding->ptype.func = oz_pkt_recv;
-		if (net_dev && *net_dev) {
-			memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
-			oz_dbg(ON, "Adding binding: %s\n", net_dev);
-			binding->ptype.dev =
-				dev_get_by_name(&init_net, net_dev);
-			if (binding->ptype.dev == NULL) {
-				oz_dbg(ON, "Netdev %s not found\n", net_dev);
-				kfree(binding);
-				binding = NULL;
-			}
-		} else {
-			oz_dbg(ON, "Binding to all netcards\n");
-			memset(binding->name, 0, OZ_MAX_BINDING_LEN);
-			binding->ptype.dev = NULL;
-		}
-		if (binding) {
-			dev_add_pack(&binding->ptype);
-			spin_lock_bh(&g_binding_lock);
-			list_add_tail(&binding->link, &g_binding);
-			spin_unlock_bh(&g_binding_lock);
+	binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL);
+	if (!binding)
+		return;
+
+	binding->ptype.type = __constant_htons(OZ_ETHERTYPE);
+	binding->ptype.func = oz_pkt_recv;
+	if (net_dev && *net_dev) {
+		memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
+		oz_dbg(ON, "Adding binding: %s\n", net_dev);
+		binding->ptype.dev = dev_get_by_name(&init_net, net_dev);
+		if (binding->ptype.dev == NULL) {
+			oz_dbg(ON, "Netdev %s not found\n", net_dev);
+			kfree(binding);
+			return;
 		}
 	}
+	dev_add_pack(&binding->ptype);
+	spin_lock_bh(&g_binding_lock);
+	list_add_tail(&binding->link, &g_binding);
+	spin_unlock_bh(&g_binding_lock);
 }
 
 /*
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index ec4b1fd14021..08f9a4896116 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -171,8 +171,8 @@ struct logical_input {
 
 	union {
 		struct {	/* valid when type == INPUT_TYPE_STD */
-			void (*press_fct) (int);
-			void (*release_fct) (int);
+			void (*press_fct)(int);
+			void (*release_fct)(int);
 			int press_data;
 			int release_data;
 		} std;
@@ -417,9 +417,9 @@ static char lcd_must_clear;
 static char lcd_left_shift;
 static char init_in_progress;
 
-static void (*lcd_write_cmd) (int);
-static void (*lcd_write_data) (int);
-static void (*lcd_clear_fast) (void);
+static void (*lcd_write_cmd)(int);
+static void (*lcd_write_data)(int);
+static void (*lcd_clear_fast)(void);
 
 static DEFINE_SPINLOCK(pprt_lock);
 static struct timer_list scan_timer;
@@ -457,14 +457,12 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-		 "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-		 "3=hantronix //, 4=nexcom //, 5=compiled-in");
+		 "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
 MODULE_PARM_DESC(lcd_proto,
-		"LCD communication: 0=parallel (//), 1=serial,"
-		"2=TI LCD Interface");
+		"LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
 
 static int lcd_charset = -1;
 module_param(lcd_charset, int, 0000);
@@ -473,8 +471,7 @@ MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
 static int keypad_type = -1;
 module_param(keypad_type, int, 0000);
 MODULE_PARM_DESC(keypad_type,
-		 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, "
-		 "3=nexcom 4 keys");
+		 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
 
 static int profile = DEFAULT_PROFILE;
 module_param(profile, int, 0000);
@@ -494,38 +491,32 @@ MODULE_PARM_DESC(profile,
 static int lcd_e_pin  = PIN_NOT_SET;
 module_param(lcd_e_pin, int, 0000);
 MODULE_PARM_DESC(lcd_e_pin,
-		 "# of the // port pin connected to LCD 'E' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
 
 static int lcd_rs_pin = PIN_NOT_SET;
 module_param(lcd_rs_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rs_pin,
-		 "# of the // port pin connected to LCD 'RS' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
 
 static int lcd_rw_pin = PIN_NOT_SET;
 module_param(lcd_rw_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rw_pin,
-		 "# of the // port pin connected to LCD 'RW' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
 
 static int lcd_bl_pin = PIN_NOT_SET;
 module_param(lcd_bl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_bl_pin,
-		 "# of the // port pin connected to LCD backlight, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
 
 static int lcd_da_pin = PIN_NOT_SET;
 module_param(lcd_da_pin, int, 0000);
 MODULE_PARM_DESC(lcd_da_pin,
-		 "# of the // port pin connected to serial LCD 'SDA' "
-		 "signal, with polarity (-17..17)");
+		 "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
 
 static int lcd_cl_pin = PIN_NOT_SET;
 module_param(lcd_cl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_cl_pin,
-		 "# of the // port pin connected to serial LCD 'SCL' "
-		 "signal, with polarity (-17..17)");
+		 "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
 
 static const unsigned char *lcd_char_conv;
 
@@ -2017,9 +2008,9 @@ static struct logical_input *panel_bind_key(const char *name, const char *press,
  * be bound.
  */
 static struct logical_input *panel_bind_callback(char *name,
-						 void (*press_fct) (int),
+						 void (*press_fct)(int),
 						 int press_data,
-						 void (*release_fct) (int),
+						 void (*release_fct)(int),
 						 int release_data)
 {
 	struct logical_input *callback;
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
index 3162aabbeb07..ff8d41ebca36 100644
--- a/drivers/staging/rtl8187se/Kconfig
+++ b/drivers/staging/rtl8187se/Kconfig
@@ -6,6 +6,5 @@ config R8187SE
 	select WEXT_PRIV
 	select EEPROM_93CX6
 	select CRYPTO
-	default N
 	---help---
 	  If built as a module, it will be called r8187se.ko.
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 09ffd9bc8991..4978b2bba186 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -709,10 +709,10 @@ enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
 
 #define MAX_IE_LEN						0xFF //+YJ,080625
 
-typedef struct _CHANNEL_LIST{
-	u8	Channel[MAX_CHANNEL_NUMBER + 1];
-	u8	Len;
-}CHANNEL_LIST, *PCHANNEL_LIST;
+struct rtl8187se_channel_list {
+	u8	channel[MAX_CHANNEL_NUMBER + 1];
+	u8	len;
+};
 
 //by amy for ps
 #define IEEE80211_WATCH_DOG_TIME    2000
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index 8999ec62450d..f81e6b51d277 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -1,19 +1,18 @@
 /*
-   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.
-*/
+ * 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
@@ -21,13 +20,13 @@
 #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)
+#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/config.h>
+/* #include <linux/config.h> */
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -36,22 +35,22 @@
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/rtnetlink.h>	//for rtnl_lock()
+#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/proc_fs.h> /* Necessary because we use the proc fs. */
 #include <linux/if_arp.h>
 #include "ieee80211/ieee80211.h"
 #include <asm/io.h>
-//#include <asm/semaphore.h>
+/* #include <asm/semaphore.h> */
 
 #define EPROM_93c46 0
 #define EPROM_93c56 1
 
-#define RTL_IOCTL_WPA_SUPPLICANT		SIOCIWFIRSTPRIV+30
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
 
 #define DEFAULT_FRAG_THRESHOLD 2342U
-#define MIN_FRAG_THRESHOLD     256U
+#define MIN_FRAG_THRESHOLD 256U
 #define DEFAULT_RTS_THRESHOLD 2342U
 #define MIN_RTS_THRESHOLD 0U
 #define MAX_RTS_THRESHOLD 2342U
@@ -60,14 +59,14 @@
 #define DEFAULT_RETRY_RTS 7
 #define DEFAULT_RETRY_DATA 7
 
-#define BEACON_QUEUE					6
+#define BEACON_QUEUE 6
 
-#define aSifsTime 	10
+#define aSifsTime 10
 
-#define sCrcLng         4
-#define sAckCtsLng	112		// bits in ACK and CTS frames
-//+by amy 080312
-#define RATE_ADAPTIVE_TIMER_PERIOD	300
+#define sCrcLng 4
+#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
+/* +by amy 080312. */
+#define RATE_ADAPTIVE_TIMER_PERIOD 300
 
 typedef enum _WIRELESS_MODE {
 	WIRELESS_MODE_UNKNOWN = 0x00,
@@ -77,115 +76,111 @@ typedef enum _WIRELESS_MODE {
 	WIRELESS_MODE_AUTO = 0x08,
 } WIRELESS_MODE;
 
-typedef struct 	ChnlAccessSetting {
-	u16 SIFS_Timer;
-	u16 DIFS_Timer;
-	u16 SlotTimeTimer;
-	u16 EIFS_Timer;
-	u16 CWminIndex;
-	u16 CWmaxIndex;
-}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING;
+struct chnl_access_setting {
+	u16 sifs_timer;
+	u16 difs_timer;
+	u16 slot_time_timer;
+	u16 eifs_timer;
+	u16 cwmin_index;
+	u16 cwmax_index;
+};
 
-typedef enum{
-        NIC_8185 = 1,
-        NIC_8185B
-        } nic_t;
+typedef enum {
+	NIC_8185 = 1,
+	NIC_8185B
+	} nic_t;
 
 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;
+#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.
+		   */
 
-/* it is a wrong definition. -xiong-2006-11-17
-typedef struct ThreeWireReg {
-	u16	longData;
+/*
+ * ECWmin/ECWmax field.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
+ */
+typedef union _ECW {
+	u8 charData;
 	struct {
-		u8	enableB;
-		u8	data;
-		u8	clk;
-		u8	read_write;
+		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;
+
+/* it is a wrong definition. -xiong-2006-11-17
+ * typedef struct ThreeWireReg {
+ *	u16	longData;
+ *	struct {
+ *		u8 enableB;
+ *		u8 data;
+ *		u8 clk;
+ *		u8 read_write;
+ *	} struc;
+ * } ThreeWireReg;
+ */
+
+typedef union _ThreeWire {
+	struct _ThreeWireStruc {
+		u16 data:1;
+		u16 clk:1;
+		u16 enableB:1;
+		u16 read_write:1;
+		u16 resv1:12;
+		/* u2Byte resv2:14; */
+		/* u2Byte ThreeWireEnable:1; */
+		/* u2Byte resv3:1; */
 	} struc;
+	u16 longData;
 } ThreeWireReg;
-*/
-
-typedef	union _ThreeWire{
-	struct _ThreeWireStruc{
-		u16		data:1;
-		u16		clk:1;
-		u16		enableB:1;
-		u16		read_write:1;
-		u16		resv1:12;
-//		u2Byte	resv2:14;
-//		u2Byte	ThreeWireEnable:1;
-//		u2Byte	resv3:1;
-	}struc;
-	u16			longData;
-}ThreeWireReg;
-
-
-typedef struct buffer
-{
+
+
+typedef struct buffer {
 	struct buffer *next;
 	u32 *buf;
 	dma_addr_t dma;
 } buffer;
 
-//YJ,modified,080828
-typedef struct Stats
-{
+/* YJ,modified,080828. */
+struct stats {
 	unsigned long txrdu;
 	unsigned long rxrdu;
 	unsigned long rxnolast;
 	unsigned long rxnodata;
-//	unsigned long rxreset;
-//	unsigned long rxwrkaround;
+	/* unsigned long rxreset; */
+	/* unsigned long rxwrkaround; */
 	unsigned long rxnopointer;
 	unsigned long txnperr;
 	unsigned long txresumed;
@@ -207,52 +202,59 @@ typedef struct Stats
 	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
-} Stats;
+	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
-
-typedef struct _link_detect_t
-{
-	u32				RxFrameNum[MAX_LD_SLOT_NUM];	// number of Rx Frame / CheckForHang_period  to determine link status
-	u16				SlotNum;	// number of CheckForHang period to determine link status, default is 2
-	u16				SlotIndex;
-
-	u32				NumTxOkInPeriod;  //number of packet transmitted during CheckForHang
-	u32				NumRxOkInPeriod;  //number of packet received during CheckForHang
-
-	u8				IdleCount;     // (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)
-	u32				LastNumTxUnicast;
-	u32				LastNumRxUnicast;
-
-	bool				bBusyTraffic;    //when it is set to 1, UI cann't scan at will.
-}link_detect_t, *plink_detect_t;
-
-//YJ,modified,080828,end
-
-//by amy for led
-//================================================================================
-// LED customization.
-//================================================================================
-
-typedef	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)
-}LED_STRATEGY_8185, *PLED_STRATEGY_8185;
-//by amy for led
-//by amy for power save
-typedef	enum _LED_CTL_MODE{
+#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.
+ * ==========================================================================
+ */
+typedef 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). */
+} LED_STRATEGY_8185, *PLED_STRATEGY_8185;
+/* by amy for led. */
+/* by amy for power save. */
+typedef enum _LED_CTL_MODE {
 	LED_CTL_POWER_ON = 1,
 	LED_CTL_LINK = 2,
 	LED_CTL_NO_LINK = 3,
@@ -260,73 +262,74 @@ typedef	enum _LED_CTL_MODE{
 	LED_CTL_RX = 5,
 	LED_CTL_SITE_SURVEY = 6,
 	LED_CTL_POWER_OFF = 7
-}LED_CTL_MODE;
+} LED_CTL_MODE;
 
-typedef	enum _RT_RF_POWER_STATE
-{
+typedef enum _RT_RF_POWER_STATE {
 	eRfOn,
 	eRfSleep,
 	eRfOff
-}RT_RF_POWER_STATE;
-
-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,
+} RT_RF_POWER_STATE;
+
+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,
+	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
+	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 */
 };
-typedef	enum _RT_PS_MODE
-{
-	eActive,	// Active/Continuous access.
-	eMaxPs,		// Max power save mode.
-	eFastPs		// Fast power save mode.
-}RT_PS_MODE;
-//by amy for power save
-typedef struct r8180_priv
-{
+
+typedef enum _RT_PS_MODE {
+	eActive, /* Active/Continuous access. */
+	eMaxPs,	/* Max power save mode. */
+	eFastPs /* Fast power save mode. */
+} RT_PS_MODE;
+
+/* by amy for power save. */
+typedef 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
+	short plcp_preamble_mode; /* 0:auto 1:short 2:long */
 
 	spinlock_t irq_th_lock;
 	spinlock_t tx_lock;
@@ -339,19 +342,20 @@ typedef struct r8180_priv
 	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 challow[15]; //channels from 1 to 14, 0 not used
-	u8 channel_plan;  // it's the channel plan index
+	u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
+	u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
+	/* u8 challow[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
+	short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
 
 	struct timer_list scan_timer;
-	/*short scanpending;
-	short stopscan;*/
+	/* short scanpending;
+	 * short stopscan;
+	 */
 	spinlock_t scan_lock;
 	u8 active_probe;
-	//u8 active_scan_num;
+	/* u8 active_scan_num; */
 	struct semaphore wx_sem;
 	short hw_wep;
 
@@ -359,20 +363,20 @@ typedef struct r8180_priv
 	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);
+	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 rate; */
 	short promisc;
-	/*stats*/
-	struct Stats stats;
-	struct _link_detect_t link_detect;  //YJ,add,080828
+	/* stats */
+	struct stats stats;
+	struct link_detect_t link_detect; /* YJ,add,080828 */
 	struct iw_statistics wstats;
 
-	/*RX stuff*/
+	/* RX stuff. */
 	u32 *rxring;
 	u32 *rxringtail;
 	dma_addr_t rxringdma;
@@ -387,27 +391,27 @@ typedef struct r8180_priv
 
 	u32 rx_prevlen;
 
-	/*TX stuff*/
-/*
-	u32 *txlpring;
-	u32 *txhpring;
-	u32 *txnpring;
-	dma_addr_t txlpringdma;
-	dma_addr_t txhpringdma;
-	dma_addr_t txnpringdma;
-	u32 *txlpringtail;
-	u32 *txhpringtail;
-	u32 *txnpringtail;
-	u32 *txlpringhead;
-	u32 *txhpringhead;
-	u32 *txnpringhead;
-	struct buffer *txlpbufs;
-	struct buffer *txhpbufs;
-	struct buffer *txnpbufs;
-	struct buffer *txlpbufstail;
-	struct buffer *txhpbufstail;
-	struct buffer *txnpbufstail;
-*/
+	/* TX stuff */
+	/*
+	 * u32 *txlpring;
+	 * u32 *txhpring;
+	 * u32 *txnpring;
+	 * dma_addr_t txlpringdma;
+	 * dma_addr_t txhpringdma;
+	 * dma_addr_t txnpringdma;
+	 * u32 *txlpringtail;
+	 * u32 *txhpringtail;
+	 * u32 *txnpringtail;
+	 * u32 *txlpringhead;
+	 * u32 *txhpringhead;
+	 * u32 *txnpringhead;
+	 * struct buffer *txlpbufs;
+	 * struct buffer *txhpbufs;
+	 * struct buffer *txnpbufs;
+	 * struct buffer *txlpbufstail;
+	 * struct buffer *txhpbufstail;
+	 * struct buffer *txnpbufstail;
+	 */
 	u32 *txmapring;
 	u32 *txbkpring;
 	u32 *txbepring;
@@ -447,54 +451,56 @@ typedef struct r8180_priv
 
 	int txringcount;
 	int txbuffsize;
-	//struct tx_pendingbuf txnp_pending;
-	//struct tasklet_struct irq_tx_tasklet;
+	/* struct tx_pendingbuf txnp_pending; */
+	/* struct tasklet_struct irq_tx_tasklet; */
 	struct tasklet_struct irq_rx_tasklet;
 	u8 dma_poll_mask;
-	//short tx_suspend;
+	/* short tx_suspend; */
 
-	/* adhoc/master mode stuff */
+	/* adhoc/master mode stuff. */
 	u32 *txbeaconringtail;
 	dma_addr_t txbeaconringdma;
 	u32 *txbeaconring;
 	int txbeaconcount;
 	struct buffer *txbeaconbufs;
 	struct buffer *txbeaconbufstail;
-	//char *master_essid;
-	//u16 master_beaconinterval;
-	//u32 master_beaconsize;
-	//u16 beacon_interval;
+	/* char *master_essid; */
+	/* u16 master_beaconinterval; */
+	/* u32 master_beaconsize; */
+	/* u16 beacon_interval; */
 
 	u8 retry_data;
 	u8 retry_rts;
 	u16 rts;
 
-//by amy for led
+	/* by amy for led. */
 	LED_STRATEGY_8185 LedStrategy;
-//by amy for led
+	/* by amy for led. */
 
-//by amy for power save
+	/* by amy for power save. */
 	struct timer_list watch_dog_timer;
 	bool bInactivePs;
 	bool bSwRfProcessing;
-	RT_RF_POWER_STATE	eInactivePowerState;
+	RT_RF_POWER_STATE eInactivePowerState;
 	RT_RF_POWER_STATE eRFPowerState;
 	u32 RfOffReason;
 	bool RFChangeInProgress;
 	bool SetRFPowerStateInProgress;
-	u8   RFProgType;
+	u8 RFProgType;
 	bool bLeisurePs;
 	RT_PS_MODE dot11PowerSaveMode;
-	//u32 NumRxOkInPeriod;   //YJ,del,080828
-	//u32 NumTxOkInPeriod;   //YJ,del,080828
-	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
+	/* u32 NumRxOkInPeriod;*/ /* YJ,del,080828 */
+	/* u32 NumTxOkInPeriod;*/ /* YJ,del,080828 */
+	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;
@@ -503,115 +509,133 @@ typedef struct r8180_priv
 	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 LastSignalStrengthInPercent; /* In percentage, used for smoothing,
+					   * e.g. Moving Average.
+					   */
+	u8 SignalQuality; /* in 0-100 index. */
 	long Stats_SignalQuality;
-	long RecvSignalPower; // in dBm.
+	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.
+	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.
+	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					UndercorateSmoothedRxPower;
-	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;
-//by amy for rate adaptive
-//by amy 080312}
-//	short wq_hurryup;
-//	struct workqueue_struct *workqueue;
+	/* 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 UndercorateSmoothedRxPower;
+	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;
+	/* by amy for rate adaptive. */
+	/* by amy 080312} */
+	/* short wq_hurryup; */
+	/* struct workqueue_struct *workqueue; */
 	struct work_struct reset_wq;
 	struct work_struct watch_dog_wq;
 	short ack_tx_to_ieee;
 
 	u8 dma_poll_stop_mask;
 
-	//u8 RegThreeWireMode;
+	/* u8 RegThreeWireMode; */
 	u16 ShortRetryLimit;
 	u16 LongRetryLimit;
 	u16 EarlyRxThreshold;
@@ -619,8 +643,8 @@ typedef struct r8180_priv
 	u32 ReceiveConfig;
 	u32 IntrMask;
 
-	struct 	ChnlAccessSetting  ChannelAccessSetting;
-}r8180_priv;
+	struct chnl_access_setting ChannelAccessSetting;
+} r8180_priv;
 
 #define MANAGE_PRIORITY 0
 #define BK_PRIORITY 1
@@ -632,7 +656,7 @@ typedef struct r8180_priv
 
 #define LOW_PRIORITY VI_PRIORITY
 #define NORM_PRIORITY VO_PRIORITY
-//AC2Queue mapping
+/* AC2Queue mapping. */
 #define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
 		((_ac) == WME_AC_VI) ? VI_PRIORITY : \
 		((_ac) == WME_AC_BK) ? BK_PRIORITY : \
@@ -673,7 +697,7 @@ void UpdateInitialGain(struct net_device *dev);
 bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
 			  bool bAntDiversity);
 
-//#ifdef CONFIG_RTL8185B
+/* #ifdef CONFIG_RTL8185B */
 void rtl8185b_adapter_start(struct net_device *dev);
 void rtl8185b_rx_enable(struct net_device *dev);
 void rtl8185b_tx_enable(struct net_device *dev);
@@ -682,8 +706,8 @@ 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);
-//#endif
+void rtl8180_rate_adapter(struct work_struct *work);
+/* #endif */
 bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet,
 			 u32 ChangeSource);
 
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 6cafee22bec4..7480a39165e7 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -1,31 +1,31 @@
 /*
-   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.
-*/
+ * 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
 
@@ -347,9 +347,9 @@ static void rtl8180_proc_init_one(struct net_device *dev)
 }
 
 /*
-  FIXME: check if we can use some standard already-existent
-  data type+functions in kernel
-*/
+ * 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)
@@ -1206,8 +1206,9 @@ static void rtl8180_rx(struct net_device *dev)
 	rx_desc_size = 8;
 
 	if ((*(priv->rxringtail)) & (1<<31)) {
-		/* we have got an RX int, but the descriptor
-		 * we are pointing is empty */
+		/* we have got an RX int, but the descriptor. we are pointing
+		 * is empty.
+		 */
 
 		priv->stats.rxnodata++;
 		priv->ieee80211->stats.rx_errors++;
@@ -1254,10 +1255,9 @@ static void rtl8180_rx(struct net_device *dev)
 		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
+			/* 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
 			 */
@@ -1293,11 +1293,11 @@ static void rtl8180_rx(struct net_device *dev)
 		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
-			*/
+			/* 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;
@@ -1361,7 +1361,9 @@ static void rtl8180_rx(struct net_device *dev)
 			quality = 127 - quality;
 		priv->SignalQuality = quality;
 
-		stats.signal = (u8)quality; /*priv->wstats.qual.level = priv->SignalStrength; */
+		stats.signal = (u8)quality; /* priv->wstats.qual.level = priv->
+					     * SignalStrength;
+					     */
 		stats.signalstrength = RXAGC;
 		if (stats.signalstrength > 100)
 			stats.signalstrength = 100;
@@ -1402,14 +1404,17 @@ static void rtl8180_rx(struct net_device *dev)
 
 			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.
-		 */
+			/*
+			 * 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 that received the last packet. */
+			/* Figure out which antenna that received the last
+			 * packet.
+			 */
 			priv->LastRxPktAntenna = Antenna ? 1 : 0; /* 0: aux, 1: main. */
 			SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
 		}
@@ -1417,7 +1422,8 @@ static void rtl8180_rx(struct net_device *dev)
 		if (first) {
 			if (!priv->rx_skb_complete) {
 				/* seems that HW sometimes fails to receive and
-				   doesn't provide the last descriptor */
+				 * doesn't provide the last descriptor.
+				 */
 				dev_kfree_skb_any(priv->rx_skb);
 				priv->stats.rxnolast++;
 			}
@@ -1428,12 +1434,12 @@ static void rtl8180_rx(struct net_device *dev)
 			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 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);
@@ -1547,11 +1553,10 @@ static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	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.
+	 * 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);
@@ -1613,55 +1618,6 @@ static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
-/* longpre 144+48 shortpre 72+24 */
-u16 rtl8180_len2duration(u32 len, short rate, short *ext)
-{
-	u16 duration;
-	u16 drift;
-	*ext = 0;
-
-	switch (rate) {
-	case 0: /* 1mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x2;
-		drift = ((len+4)<<4) % 0x2;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	case 1: /* 2mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x4;
-		drift = ((len+4)<<4) % 0x4;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	case 2: /* 5.5mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0xb;
-		drift = ((len+4)<<4) % 0xb;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	default:
-	case 3: /* 11mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x16;
-		drift = ((len+4)<<4) % 0x16;
-		if (drift == 0)
-			break;
-		duration++;
-		if (drift > 6)
-			break;
-		*ext = 1;
-		break;
-	}
-
-	return duration;
-}
-
 static void rtl8180_prepare_beacon(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -1681,9 +1637,9 @@ static void rtl8180_prepare_beacon(struct net_device *dev)
 }
 
 /*
- * 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.
+ * 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,
 		 short morefrag, short descfrag, int rate)
@@ -2225,7 +2181,7 @@ static void watch_dog_adaptive(unsigned long data)
 	add_timer(&priv->watch_dog_timer);
 }
 
-static CHANNEL_LIST ChannelPlan[] = {
+static struct rtl8187se_channel_list channel_plan_list[] = {
 	{{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 */
@@ -2261,13 +2217,13 @@ static void rtl8180_set_channel_map(u8 channel_plan,
 		{
 			Dot11d_Init(ieee);
 			ieee->bGlobalDomain = false;
-			if (ChannelPlan[channel_plan].Len != 0) {
+			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 < ChannelPlan[channel_plan].Len; i++) {
-					if (ChannelPlan[channel_plan].Channel[i] <= 14)
-						GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
+				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;
@@ -2300,15 +2256,15 @@ static void rtl8180_set_channel_map(u8 channel_plan,
 void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
 
 /* YJ,add,080828 */
-static void rtl8180_statistics_init(struct Stats *pstats)
+static void rtl8180_statistics_init(struct stats *pstats)
 {
-	memset(pstats, 0, sizeof(struct Stats));
+	memset(pstats, 0, sizeof(struct stats));
 }
 
-static void rtl8180_link_detect_init(plink_detect_t plink_detect)
+static void rtl8180_link_detect_init(struct link_detect_t *plink_detect)
 {
-	memset(plink_detect, 0, sizeof(link_detect_t));
-	plink_detect->SlotNum = DEFAULT_SLOT_NUM;
+	memset(plink_detect, 0, sizeof(struct link_detect_t));
+	plink_detect->slot_num = DEFAULT_SLOT_NUM;
 }
 
 /* YJ,add,080828,end */
@@ -2812,9 +2768,9 @@ void rtl8180_start_tx_beacon(struct net_device *dev)
 	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;
-	*/
+		       * ((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);
@@ -2890,23 +2846,23 @@ static void MgntLinkKeepAlive(struct r8180_priv *priv)
 		 */
 
 		if ((priv->keepAliveLevel == 2) ||
-			(priv->link_detect.LastNumTxUnicast == priv->NumTxUnicast &&
-			priv->link_detect.LastNumRxUnicast == priv->ieee80211->NumRxUnicast)
+			(priv->link_detect.last_num_tx_unicast == priv->NumTxUnicast &&
+			priv->link_detect.last_num_rx_unicast == priv->ieee80211->NumRxUnicast)
 			) {
-			priv->link_detect.IdleCount++;
+			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.IdleCount >= ((KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)-1)) {
-				priv->link_detect.IdleCount = 0;
+			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.IdleCount = 0;
+			priv->link_detect.idle_count = 0;
 		}
-		priv->link_detect.LastNumTxUnicast = priv->NumTxUnicast;
-		priv->link_detect.LastNumRxUnicast = priv->ieee80211->NumRxUnicast;
+		priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast;
+		priv->link_detect.last_num_rx_unicast = priv->ieee80211->NumRxUnicast;
 	}
 }
 
@@ -2927,10 +2883,10 @@ void rtl8180_watch_dog(struct net_device *dev)
 	}
 	/* YJ,add,080828,for link state check */
 	if ((priv->ieee80211->state == IEEE80211_LINKED) && (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
-		SlotIndex = (priv->link_detect.SlotIndex++) % priv->link_detect.SlotNum;
-		priv->link_detect.RxFrameNum[SlotIndex] = priv->ieee80211->NumRxDataInPeriod + priv->ieee80211->NumRxBcnInPeriod;
-		for (i = 0; i < priv->link_detect.SlotNum; i++)
-			TotalRxNum += priv->link_detect.RxFrameNum[i];
+		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;
@@ -2945,13 +2901,13 @@ void rtl8180_watch_dog(struct net_device *dev)
 	LeisurePSLeave(priv);
 
 	if (priv->ieee80211->state == IEEE80211_LINKED) {
-		priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
-		if (priv->link_detect.NumRxOkInPeriod > 666 ||
-			priv->link_detect.NumTxOkInPeriod > 666) {
+		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.NumRxOkInPeriod + priv->link_detect.NumTxOkInPeriod) > 8)
-			|| (priv->link_detect.NumRxOkInPeriod > 2)) {
+		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;
@@ -2962,9 +2918,9 @@ void rtl8180_watch_dog(struct net_device *dev)
 			LeisurePSLeave(priv);
 	} else
 		LeisurePSLeave(priv);
-	priv->link_detect.bBusyTraffic = bBusyTraffic;
-	priv->link_detect.NumRxOkInPeriod = 0;
-	priv->link_detect.NumTxOkInPeriod = 0;
+	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;
 }
@@ -3586,7 +3542,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
 	}
 
 	if (inta & ISR_THPDOK) { /* High priority tx ok */
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		priv->stats.txhpokint++;
 		rtl8180_tx_isr(dev, HI_PRIORITY, 0);
 	}
@@ -3649,14 +3605,14 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
 		priv->stats.txoverflow++;
 
 	if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		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.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		priv->stats.txlpokint++;
 		rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, LOW_PRIORITY);
@@ -3664,14 +3620,14 @@ static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
 
 	if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
 		priv->stats.txbkpokint++;
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		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.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		rtl8180_tx_isr(dev, BE_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, BE_PRIORITY);
 	}
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
index 9b676e027cad..b55249170f18 100644
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ b/drivers/staging/rtl8187se/r8180_wx.c
@@ -29,7 +29,7 @@ static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
 
 #define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
 
-static CHANNEL_LIST DefaultChannelPlan[] = {
+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	*/
@@ -337,7 +337,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 		}	else	{
 			/* prevent scan in BusyTraffic */
 			/* FIXME: Need to consider last scan time */
-			if ((priv->link_detect.bBusyTraffic) && (true))	{
+			if ((priv->link_detect.b_busy_traffic) && (true)) {
 				ret = 0;
 				printk("Now traffic is busy, please try later!\n");
 			}	else
@@ -1030,15 +1030,15 @@ static int r8180_wx_set_channelplan(struct net_device *dev,
 
 	/* unsigned long flags; */
 	down(&priv->wx_sem);
-	if (DefaultChannelPlan[*val].Len != 0)	{
+	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 <= DefaultChannelPlan[*val].Len; i++)
-			GET_DOT11D_INFO(priv->ieee80211)->channel_map[DefaultChannelPlan[*val].Channel[i-1]] = 1;
+		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);
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index c8b9baff1dbc..48eda5564ba5 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -873,7 +873,7 @@ static u8 GetSupportedWirelessMode8185(struct net_device *dev)
 static void
 ActUpdateChannelAccessSetting(struct net_device *dev,
 			      WIRELESS_MODE WirelessMode,
-			      PCHANNEL_ACCESS_SETTING ChnlAccessSetting)
+			      struct chnl_access_setting *chnl_access_setting)
 {
 	AC_CODING	eACI;
 
@@ -890,25 +890,25 @@ ActUpdateChannelAccessSetting(struct net_device *dev,
 	 */
 
 	/* Suggested by Jong, 2005.12.08. */
-	ChnlAccessSetting->SIFS_Timer = 0x22;
-	ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
-	ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
+	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.
 	 */
-	ChnlAccessSetting->EIFS_Timer = 0x5B;
-	ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
-	ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
+	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, ChnlAccessSetting->SIFS_Timer);
+	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, ChnlAccessSetting->SlotTimeTimer);
+	write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer);
 
-	write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
+	write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer);
 
 	/*
 	 * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
diff --git a/drivers/staging/rtl8188eu/Kconfig b/drivers/staging/rtl8188eu/Kconfig
index c9c548f17494..e45c106c2162 100644
--- a/drivers/staging/rtl8188eu/Kconfig
+++ b/drivers/staging/rtl8188eu/Kconfig
@@ -3,7 +3,6 @@ config R8188EU
 	depends on WLAN && USB
 	select WIRELESS_EXT
 	select WEXT_PRIV
-	default N
 	---help---
 	This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N.
 	If built as a module, it will be called r8188eu.
@@ -12,7 +11,7 @@ if R8188EU
 
 config 88EU_AP_MODE
 	bool "Realtek RTL8188EU AP mode"
-	default Y
+	default y
 	---help---
 	This option enables Access Point mode. Unless you know that your system
 	will never be used as an AP, or the target system has limited memory,
@@ -20,7 +19,7 @@ config 88EU_AP_MODE
 
 config 88EU_P2P
 	bool "Realtek RTL8188EU Peer-to-peer mode"
-	default Y
+	default y
 	---help---
 	This option enables peer-to-peer mode for the r8188eu driver. Unless you
 	know that peer-to-peer (P2P) mode will never be used, or the target system has
diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile
index 0a617b42cc99..6a138ff699e9 100644
--- a/drivers/staging/rtl8188eu/Makefile
+++ b/drivers/staging/rtl8188eu/Makefile
@@ -34,7 +34,6 @@ r8188eu-y :=				\
 		hal/hal_com.o		\
 		hal/odm.o		\
 		hal/odm_debug.o		\
-		hal/odm_interface.o	\
 		hal/odm_HWConfig.o	\
 		hal/odm_RegConfig8188E.o\
 		hal/odm_RTL8188E.o	\
diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO
index f7f389c40e71..b574b235b340 100644
--- a/drivers/staging/rtl8188eu/TODO
+++ b/drivers/staging/rtl8188eu/TODO
@@ -9,6 +9,11 @@ TODO:
 - merge Realtek's bugfixes and new features into the driver
 - switch to use LIB80211
 - switch to use MAC80211
+- figure out what to do with this code in rtw_recv_indicatepkt():
+	rcu_read_lock();
+	rcu_dereference(padapter->pnetdev->rx_handler_data);
+	rcu_read_unlock();
+  Perhaps delete it, perhaps assign to some local variable.
 
 Please send any patches to Greg Kroah-Hartman <gregkh@linux.com>,
 and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 8ebe6bc40022..0f1c1e5d25dd 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -94,7 +94,7 @@ static void update_BCNTIM(struct adapter *padapter)
 		} else {
 			tim_ielen = 0;
 
-			/* calucate head_len */
+			/* calculate head_len */
 			offset = _FIXED_IE_LENGTH_;
 			offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
 
@@ -129,7 +129,7 @@ static void update_BCNTIM(struct adapter *padapter)
 		*dst_ie++ = tim_ielen;
 
 		*dst_ie++ = 0;/* DTIM count */
-		*dst_ie++ = 1;/* DTIM peroid */
+		*dst_ie++ = 1;/* DTIM period */
 
 		if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
 			*dst_ie++ = BIT(0);/* bitmap ctrl */
@@ -285,12 +285,12 @@ void	expire_timeout_chk(struct adapter *padapter)
 	spin_lock_bh(&pstapriv->auth_list_lock);
 
 	phead = &pstapriv->auth_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* check auth_queue */
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
-		plist = get_next(plist);
+		psta = container_of(plist, struct sta_info, auth_list);
+		plist = plist->next;
 
 		if (psta->expire_to > 0) {
 			psta->expire_to--;
@@ -319,12 +319,12 @@ void	expire_timeout_chk(struct adapter *padapter)
 	spin_lock_bh(&pstapriv->asoc_list_lock);
 
 	phead = &pstapriv->asoc_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* check asoc_queue */
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-		plist = get_next(plist);
+		psta = container_of(plist, struct sta_info, asoc_list);
+		plist = plist->next;
 
 		if (chk_sta_is_alive(psta) || !psta->expire_to) {
 			psta->expire_to = pstapriv->expire_to;
@@ -821,7 +821,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
 	/* update cur_wireless_mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability after cur_wireless_mode updated */
+	/* update capability after cur_wireless_mode updated */
 	update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
 
 	/* let pnetwork_mlmeext == pnetwork_mlme. */
@@ -980,7 +980,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf,  int len)
 	for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
 		p = rtw_get_ie(p, _SSN_IE_1_, &ie_len,
 			       (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
-		if ((p) && (_rtw_memcmp(p+2, OUI1, 4))) {
+		if ((p) && (!memcmp(p+2, OUI1, 4))) {
 			if (rtw_parse_wpa_ie(p, ie_len+2, &group_cipher,
 					     &pairwise_cipher, NULL) == _SUCCESS) {
 				psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
@@ -1005,7 +1005,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf,  int len)
 		for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
 			p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len,
 				       (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
-			if ((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) {
+			if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
 				pmlmepriv->qospriv.qos_option = 1;
 
 				*(p+8) |= BIT(7);/* QoS Info, support U-APSD */
@@ -1144,13 +1144,13 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
 	spin_lock_bh(&(pacl_node_q->lock));
 
 	phead = get_list_head(pacl_node_q);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-		plist = get_next(plist);
+		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+		plist = plist->next;
 
-		if (_rtw_memcmp(paclnode->addr, addr, ETH_ALEN)) {
+		if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
 			if (paclnode->valid) {
 				added = true;
 				DBG_88E("%s, sta has been added\n", __func__);
@@ -1205,13 +1205,13 @@ int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
 	spin_lock_bh(&(pacl_node_q->lock));
 
 	phead = get_list_head(pacl_node_q);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-		plist = get_next(plist);
+		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+		plist = plist->next;
 
-		if (_rtw_memcmp(paclnode->addr, addr, ETH_ALEN)) {
+		if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
 			if (paclnode->valid) {
 				paclnode->valid = false;
 
@@ -1351,13 +1351,13 @@ static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
 {
 	DBG_88E("%s\n", __func__);
 
-	if (_rtw_memcmp(RTW_WPA_OUI, oui, 4))
+	if (!memcmp(RTW_WPA_OUI, oui, 4))
 		update_bcn_wpa_ie(padapter);
-	else if (_rtw_memcmp(WMM_OUI, oui, 4))
+	else if (!memcmp(WMM_OUI, oui, 4))
 		update_bcn_wmm_ie(padapter);
-	else if (_rtw_memcmp(WPS_OUI, oui, 4))
+	else if (!memcmp(WPS_OUI, oui, 4))
 		update_bcn_wps_ie(padapter);
-	else if (_rtw_memcmp(P2P_OUI, oui, 4))
+	else if (!memcmp(P2P_OUI, oui, 4))
 		update_bcn_p2p_ie(padapter);
 	else
 		DBG_88E("unknown OUI type!\n");
@@ -1415,7 +1415,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
 
 /*
 op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
 	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
 	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
 Set to 1 (HT non-member protection) if there may be non-HT STAs
@@ -1494,7 +1494,7 @@ static int rtw_ht_operation_update(struct adapter *padapter)
 
 void associated_clients_update(struct adapter *padapter, u8 updated)
 {
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	if (updated) {
 		struct list_head *phead, *plist;
 		struct sta_info *psta = NULL;
@@ -1503,13 +1503,13 @@ void associated_clients_update(struct adapter *padapter, u8 updated)
 		spin_lock_bh(&pstapriv->asoc_list_lock);
 
 		phead = &pstapriv->asoc_list;
-		plist = get_next(phead);
+		plist = phead->next;
 
 		/* check asoc_queue */
 		while ((rtw_end_of_queue_search(phead, plist)) == false) {
-			psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+			psta = container_of(plist, struct sta_info, asoc_list);
 
-			plist = get_next(plist);
+			plist = plist->next;
 
 			VCS_update(padapter, psta);
 		}
@@ -1647,7 +1647,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
 		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	associated_clients_update(padapter,  beacon_updated);
 
 	DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
@@ -1711,7 +1711,7 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
 		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 
 	DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
 
@@ -1777,12 +1777,12 @@ int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset)
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
 	phead = &pstapriv->asoc_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* for each sta in asoc_queue */
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-		plist = get_next(plist);
+		psta = container_of(plist, struct sta_info, asoc_list);
+		plist = plist->next;
 
 		issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
 		psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
@@ -1811,13 +1811,13 @@ int rtw_sta_flush(struct adapter *padapter)
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
 	phead = &pstapriv->asoc_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* free sta asoc_queue */
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		psta = container_of(plist, struct sta_info, asoc_list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 		rtw_list_delete(&psta->asoc_list);
 		pstapriv->asoc_list_cnt--;
@@ -1942,10 +1942,10 @@ void stop_ap_mode(struct adapter *padapter)
 	/* for ACL */
 	spin_lock_bh(&(pacl_node_q->lock));
 	phead = get_list_head(pacl_node_q);
-	plist = get_next(phead);
+	plist = phead->next;
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-		plist = get_next(plist);
+		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+		plist = plist->next;
 
 		if (paclnode->valid) {
 			paclnode->valid = false;
diff --git a/drivers/staging/rtl8188eu/core/rtw_br_ext.c b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
index 75e38d4ff4c3..96c8a93ad97f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_br_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
@@ -543,10 +543,10 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
 			if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
 				if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
 					/*  L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
-					DEBUG_INFO("NAT25: Set DA as boardcast\n");
+					DEBUG_INFO("NAT25: Set DA as broadcast\n");
 					memset(skb->data, 0xff, ETH_ALEN);
 				} else {
-					/*  forward unknow IP packet to upper TCP/IP */
+					/*  forward unknown IP packet to upper TCP/IP */
 					DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
 					if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
 						printk("Re-init netdev_br_init() due to br_mac == 0!\n");
@@ -932,7 +932,7 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
 						(ph->code == PADO_CODE ? "PADO" : "PADS"),	skb->dev->name);
 				} else { /*  not add relay tag */
 					if (!priv->pppoe_connection_in_progress) {
-						DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
+						DEBUG_ERR("Discard PPPoE packet due to no connection in progress!\n");
 						return -1;
 					}
 					memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 82fe8c47a1de..c0a0a521e591 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -36,7 +36,6 @@ int	_rtw_init_cmd_priv (struct	cmd_priv *pcmdpriv)
 {
 	int res = _SUCCESS;
 
-_func_enter_;
 
 	sema_init(&(pcmdpriv->cmd_queue_sema), 0);
 	/* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
@@ -71,7 +70,6 @@ _func_enter_;
 	pcmdpriv->cmd_done_cnt = 0;
 	pcmdpriv->rsp_cnt = 0;
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -81,24 +79,21 @@ int _rtw_init_evt_priv(struct evt_priv *pevtpriv)
 {
 	int res = _SUCCESS;
 
-_func_enter_;
 
 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
 	atomic_set(&pevtpriv->event_seq, 0);
 	pevtpriv->evt_done_cnt = 0;
 
-	_init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
+	INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback);
 	pevtpriv->c2h_wk_alive = false;
 	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
 
-_func_exit_;
 
 	return res;
 }
 
 void rtw_free_evt_priv(struct	evt_priv *pevtpriv)
 {
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+rtw_free_evt_priv\n"));
 
@@ -113,12 +108,10 @@ _func_enter_;
 	}
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-rtw_free_evt_priv\n"));
 
-_func_exit_;
 }
 
 void _rtw_free_cmd_priv (struct	cmd_priv *pcmdpriv)
 {
-_func_enter_;
 
 	if (pcmdpriv) {
 		if (pcmdpriv->cmd_allocated_buf)
@@ -127,7 +120,6 @@ _func_enter_;
 		if (pcmdpriv->rsp_allocated_buf)
 			kfree(pcmdpriv->rsp_allocated_buf);
 	}
-_func_exit_;
 }
 
 /*
@@ -144,7 +136,6 @@ int	_rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
 {
 	unsigned long irqL;
 
-_func_enter_;
 
 	if (obj == NULL)
 		goto exit;
@@ -157,7 +148,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -167,19 +157,17 @@ struct	cmd_obj	*_rtw_dequeue_cmd(struct __queue *queue)
 	unsigned long irqL;
 	struct cmd_obj *obj;
 
-_func_enter_;
 
 	spin_lock_irqsave(&queue->lock, irqL);
 	if (rtw_is_list_empty(&(queue->queue))) {
 		obj = NULL;
 	} else {
-		obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
+		obj = container_of((&queue->queue)->next, struct cmd_obj, list);
 		rtw_list_delete(&obj->list);
 	}
 
 	spin_unlock_irqrestore(&queue->lock, irqL);
 
-_func_exit_;
 
 	return obj;
 }
@@ -187,27 +175,21 @@ _func_exit_;
 u32	rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
 {
 	u32	res;
-_func_enter_;
 	res = _rtw_init_cmd_priv (pcmdpriv);
-_func_exit_;
 	return res;
 }
 
 u32	rtw_init_evt_priv (struct	evt_priv *pevtpriv)
 {
 	int	res;
-_func_enter_;
 	res = _rtw_init_evt_priv(pevtpriv);
-_func_exit_;
 	return res;
 }
 
 void rtw_free_cmd_priv(struct	cmd_priv *pcmdpriv)
 {
-_func_enter_;
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
 	_rtw_free_cmd_priv(pcmdpriv);
-_func_exit_;
 }
 
 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
@@ -238,7 +220,6 @@ u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 	int res = _FAIL;
 	struct adapter *padapter = pcmdpriv->padapter;
 
-_func_enter_;
 
 	if (cmd_obj == NULL)
 		goto exit;
@@ -258,7 +239,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -267,25 +247,20 @@ struct	cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
 {
 	struct cmd_obj *cmd_obj;
 
-_func_enter_;
 
 	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
 
-_func_exit_;
 	return cmd_obj;
 }
 
 void rtw_cmd_clr_isr(struct	cmd_priv *pcmdpriv)
 {
-_func_enter_;
 	pcmdpriv->cmd_done_cnt++;
 	/* up(&(pcmdpriv->cmd_done_sema)); */
-_func_exit_;
 }
 
 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
 {
-_func_enter_;
 
 	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
 		/* free parmbuf in cmd_obj */
@@ -302,7 +277,6 @@ _func_enter_;
 	/* free cmd_obj */
 	kfree(pcmd);
 
-_func_exit_;
 }
 
 int rtw_cmd_thread(void *context)
@@ -315,7 +289,6 @@ int rtw_cmd_thread(void *context)
 	struct adapter *padapter = (struct adapter *)context;
 	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
 
-_func_enter_;
 
 	thread_enter("RTW_CMD_THREAD");
 
@@ -410,7 +383,6 @@ post_process:
 
 	up(&pcmdpriv->terminate_cmdthread_sema);
 
-_func_exit_;
 
 	complete_and_exit(NULL, 0);
 }
@@ -423,7 +395,6 @@ u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
 
 	u8 ret = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -446,7 +417,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
@@ -465,7 +435,6 @@ u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid,
 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
 	}
@@ -537,7 +506,6 @@ _func_enter_;
 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 	}
 
-_func_exit_;
 
 	return res;
 }
@@ -549,7 +517,6 @@ u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -570,7 +537,6 @@ _func_enter_;
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -582,7 +548,6 @@ u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset)
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -604,7 +569,6 @@ _func_enter_;
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -624,7 +588,6 @@ u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -648,7 +611,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -659,7 +621,6 @@ u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
 		res = _FAIL;
@@ -680,7 +641,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -691,7 +651,6 @@ u8 rtw_getbbreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
 		res = _FAIL;
@@ -715,7 +674,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -725,7 +683,6 @@ u8 rtw_setrfreg_cmd(struct adapter  *padapter, u8 offset, u32 val)
 	struct writeRF_parm *pwriterfparm;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
-_func_enter_;
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
 		res = _FAIL;
@@ -746,7 +703,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -757,7 +713,6 @@ u8 rtw_getrfreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -785,33 +740,28 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
 
 void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 {
- _func_enter_;
 
 	kfree(pcmd->parmbuf);
 	kfree(pcmd);
 
 	if (padapter->registrypriv.mp_mode == 1)
 		padapter->mppriv.workparam.bcompleted = true;
-_func_exit_;
 }
 
 void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 {
- _func_enter_;
 
 	kfree(pcmd->parmbuf);
 	kfree(pcmd);
 
 	if (padapter->registrypriv.mp_mode == 1)
 		padapter->mppriv.workparam.bcompleted = true;
-_func_exit_;
 }
 
 u8 rtw_createbss_cmd(struct adapter  *padapter)
@@ -822,7 +772,6 @@ u8 rtw_createbss_cmd(struct adapter  *padapter)
 	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
 
@@ -847,7 +796,6 @@ _func_enter_;
 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -858,7 +806,6 @@ u8 rtw_createbss_cmd_ex(struct adapter  *padapter, unsigned char *pbss, unsigned
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (pcmd == NULL) {
@@ -877,7 +824,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -898,7 +844,6 @@ u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-_func_enter_;
 
 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
 
@@ -1020,7 +965,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1032,7 +976,6 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu
 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
 	u8 res = _SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
 
@@ -1063,7 +1006,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1076,7 +1018,6 @@ u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra n
 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1098,7 +1039,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1115,7 +1055,6 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
 	struct sta_info *sta = (struct sta_info *)psta;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1161,7 +1100,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1175,7 +1113,6 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
 	struct sta_info *sta = (struct sta_info *)psta;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	if (!enqueue) {
 		clear_cam_entry(padapter, entry);
@@ -1215,7 +1152,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1226,7 +1162,6 @@ u8 rtw_setrttbl_cmd(struct adapter  *padapter, struct setratable_parm *prate_tab
 	struct setratable_parm *psetrttblparm;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1247,7 +1182,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -1257,7 +1191,6 @@ u8 rtw_getrttbl_cmd(struct adapter  *padapter, struct getratable_rsp *pval)
 	struct getratable_parm *pgetrttblparm;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1285,7 +1218,6 @@ _func_enter_;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -1298,7 +1230,6 @@ u8 rtw_setassocsta_cmd(struct adapter  *padapter, u8 *mac_addr)
 
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1330,7 +1261,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
  }
@@ -1342,7 +1272,6 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
 	struct addBaReq_parm *paddbareq_parm;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1369,7 +1298,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1381,7 +1309,6 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -1406,7 +1333,6 @@ _func_enter_;
 	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -1418,7 +1344,6 @@ u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enque
 
 	u8 res = _SUCCESS;
 
-_func_enter_;
 
 	DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
 		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
@@ -1460,7 +1385,6 @@ exit:
 
 	DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
 
-_func_exit_;
 
 	return res;
 }
@@ -1473,7 +1397,6 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
 
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
 
@@ -1516,7 +1439,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1529,7 +1451,6 @@ u8 rtw_led_blink_cmd(struct adapter *padapter, struct LED_871x *pLed)
 
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_led_blink_cmd\n"));
 
@@ -1553,7 +1474,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1566,7 +1486,6 @@ u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
 
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
 
@@ -1590,7 +1509,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1685,7 +1603,6 @@ static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	u8	mstatus;
 
-_func_enter_;
 
 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
 	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
@@ -1724,7 +1641,6 @@ _func_enter_;
 		break;
 	}
 
-_func_exit_;
 }
 
 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
@@ -1735,7 +1651,6 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
 	/* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	/* if (!pwrctrlpriv->bLeisurePs) */
 	/* 	return res; */
@@ -1767,7 +1682,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1785,7 +1699,6 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
 
 	u8	res = _SUCCESS;
 
-_func_enter_;
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
 		res = _FAIL;
@@ -1806,7 +1719,6 @@ _func_enter_;
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1824,7 +1736,6 @@ u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
 	u8	support_ant_div;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
 	if (!support_ant_div)
 		return res;
@@ -1854,7 +1765,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1873,7 +1783,6 @@ u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
 		return res;
@@ -1901,7 +1810,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1914,7 +1822,6 @@ u8 rtw_ps_cmd(struct adapter *padapter)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 
 	u8	res = _SUCCESS;
-_func_enter_;
 
 	ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ppscmd == NULL) {
@@ -1937,7 +1844,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -2174,7 +2080,6 @@ void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	if (pcmd->res == H2C_DROPPED) {
 		/* TODO: cancel timer and do timeout handler directly... */
@@ -2188,13 +2093,11 @@ _func_enter_;
 	/*  free cmd */
 	rtw_free_cmd_obj(pcmd);
 
-_func_exit_;
 }
 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	if (pcmd->res != H2C_SUCCESS) {
 		spin_lock_bh(&pmlmepriv->lock);
@@ -2202,24 +2105,18 @@ _func_enter_;
 		spin_unlock_bh(&pmlmepriv->lock);
 
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
-
-		goto exit;
+		return;
 	} else /* clear bridge database */
 		nat25_db_cleanup(padapter);
 
 	/*  free cmd */
 	rtw_free_cmd_obj(pcmd);
-
-exit:
-
-_func_exit_;
 }
 
 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	if (pcmd->res == H2C_DROPPED) {
 		/* TODO: cancel timer and do timeout handler directly... */
@@ -2232,7 +2129,6 @@ _func_enter_;
 
 	rtw_free_cmd_obj(pcmd);
 
-_func_exit_;
 }
 
 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
@@ -2244,7 +2140,6 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
 	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 
-_func_enter_;
 
 	if ((pcmd->res != H2C_SUCCESS)) {
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
@@ -2298,7 +2193,6 @@ createbss_cmd_fail:
 
 	rtw_free_cmd_obj(pcmd);
 
-_func_exit_;
 }
 
 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
@@ -2307,7 +2201,6 @@ void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pc
 	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
 	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
 
-_func_enter_;
 
 	if (psta == NULL) {
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
@@ -2315,7 +2208,6 @@ _func_enter_;
 	}
 exit:
 	rtw_free_cmd_obj(pcmd);
-_func_exit_;
 }
 
 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
@@ -2326,7 +2218,6 @@ void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *
 	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
 	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
 
-_func_enter_;
 
 	if (psta == NULL) {
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
@@ -2347,5 +2238,4 @@ _func_enter_;
 exit:
 	rtw_free_cmd_obj(pcmd);
 
-_func_exit_;
 }
diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c
index af32041a1e97..78a7adf61609 100644
--- a/drivers/staging/rtl8188eu/core/rtw_debug.c
+++ b/drivers/staging/rtl8188eu/core/rtw_debug.c
@@ -233,7 +233,7 @@ int proc_get_rf_info(char *page, char **start,
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	int len = 0;
 
-	len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n",
+	len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offset=%d\n",
 					pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
 	*eof = 1;
 	return len;
@@ -851,12 +851,12 @@ int proc_get_all_sta_info(char *page, char **start,
 
 	for (i = 0; i < NUM_STA; i++) {
 		phead = &(pstapriv->sta_hash[i]);
-		plist = get_next(phead);
+		plist = phead->next;
 
 		while ((rtw_end_of_queue_search(phead, plist)) == false) {
-			psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+			psta = container_of(plist, struct sta_info, hash_list);
 
-			plist = get_next(plist);
+			plist = plist->next;
 
 			len += snprintf(page + len, count - len, "sta's macaddr: %pM\n", psta->hwaddr);
 			len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index e6f98fb8f113..4076c66833a4 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -147,7 +147,6 @@ u8 *rtw_set_ie
 	uint *frlen /* frame length */
 )
 {
-_func_enter_;
 	*pbuf = (u8)index;
 
 	*(pbuf + 1) = (u8)len;
@@ -157,7 +156,6 @@ _func_enter_;
 
 	*frlen = *frlen + (len + 2);
 
-_func_exit_;
 	return pbuf + len + 2;
 }
 
@@ -221,9 +219,7 @@ u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit)
 {
 	int tmp, i;
 	u8 *p;
-_func_enter_;
 	if (limit < 1) {
-		_func_exit_;
 		return NULL;
 	}
 
@@ -242,7 +238,6 @@ _func_enter_;
 		if (i >= limit)
 			break;
 	}
-_func_exit_;
 	return NULL;
 }
 
@@ -273,7 +268,7 @@ u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, u
 	cnt = 0;
 
 	while (cnt < in_len) {
-		if (eid == in_ie[cnt] && (!oui || _rtw_memcmp(&in_ie[cnt+2], oui, oui_len))) {
+		if (eid == in_ie[cnt] && (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) {
 			target_ie = &in_ie[cnt];
 
 			if (ie)
@@ -339,7 +334,6 @@ exit:
 
 void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
 {
-_func_enter_;
 
 	_rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
@@ -361,13 +355,11 @@ _func_enter_;
 		memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
 		break;
 	}
-_func_exit_;
 }
 
 uint	rtw_get_rateset_len(u8	*rateset)
 {
 	uint i = 0;
-_func_enter_;
 	while (1) {
 		if ((rateset[i]) == 0)
 			break;
@@ -375,7 +367,6 @@ _func_enter_;
 			break;
 		i++;
 	}
-_func_exit_;
 	return i;
 }
 
@@ -386,7 +377,6 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv)
 	struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
 	u8 *ie = pdev_network->IEs;
 
-_func_enter_;
 
 	/* timestamp will be inserted by hardware */
 	sz += 8;
@@ -444,7 +434,6 @@ _func_enter_;
 
 	if (rateLen > 8)
 		ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
-_func_exit_;
 
 	return sz;
 }
@@ -463,7 +452,7 @@ unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
 
 		if (pbuf) {
 			/* check if oui matches... */
-			if (_rtw_memcmp((pbuf + 2), wpa_oui_type, sizeof (wpa_oui_type)) == false)
+			if (!memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)) == false)
 				goto check_next_ie;
 
 			/* check version... */
@@ -497,15 +486,15 @@ unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
 
 int rtw_get_wpa_cipher_suite(u8 *s)
 {
-	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == true)
+	if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
-	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == true)
+	if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_WEP40;
-	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == true)
+	if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_TKIP;
-	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == true)
+	if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_CCMP;
-	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == true)
+	if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_WEP104;
 
 	return 0;
@@ -513,15 +502,15 @@ int rtw_get_wpa_cipher_suite(u8 *s)
 
 int rtw_get_wpa2_cipher_suite(u8 *s)
 {
-	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == true)
+	if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
-	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == true)
+	if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_WEP40;
-	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == true)
+	if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_TKIP;
-	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == true)
+	if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_CCMP;
-	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == true)
+	if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_WEP104;
 
 	return 0;
@@ -542,7 +531,7 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis
 
 
 	if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
-	    (_rtw_memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN) != true))
+	    (memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
 		return _FAIL;
 
 	pos = wpa_ie;
@@ -587,7 +576,7 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis
 	if (is_8021x) {
 		if (left >= 6) {
 			pos += 2;
-			if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
+			if (!memcmp(pos, SUITE_1X, 4)) {
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__));
 				*is_8021x = 1;
 			}
@@ -657,7 +646,7 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi
 	if (is_8021x) {
 		if (left >= 6) {
 			pos += 2;
-			if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
+			if (!memcmp(pos, SUITE_1X, 4)) {
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__));
 				*is_8021x = 1;
 			}
@@ -672,7 +661,6 @@ int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie,
 	u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
 	uint	cnt;
 
-_func_enter_;
 
 	/* Search required WPA or WPA2 IE and copy to sec_ie[] */
 
@@ -683,7 +671,7 @@ _func_enter_;
 	while (cnt < in_len) {
 		authmode = in_ie[cnt];
 
-		if ((authmode == _WPA_IE_ID_) && (_rtw_memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) {
+		if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) {
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 					 ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
 					 sec_idx, in_ie[cnt+1]+2));
@@ -726,7 +714,6 @@ _func_enter_;
 		}
 	}
 
-_func_exit_;
 
 	return *rsn_len + *wpa_len;
 }
@@ -741,7 +728,7 @@ u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
 
 	eid = ie_ptr[0];
 
-	if ((eid == _WPA_IE_ID_) && (_rtw_memcmp(&ie_ptr[2], wps_oui, 4))) {
+	if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
 		*wps_ielen = ie_ptr[1]+2;
 		match = true;
 	}
@@ -774,7 +761,7 @@ u8 *rtw_get_wps_ie(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_) && (_rtw_memcmp(&in_ie[cnt+2], wps_oui, 4))) {
+		if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt+2], wps_oui, 4))) {
 			wpsie_ptr = &in_ie[cnt];
 
 			if (wps_ie)
@@ -813,7 +800,7 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_at
 		*len_attr = 0;
 
 	if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-	    (_rtw_memcmp(wps_ie + 2, wps_oui , 4) != true))
+	    (memcmp(wps_ie + 2, wps_oui , 4)))
 		return attr_ptr;
 
 	/*  6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
@@ -1223,7 +1210,7 @@ u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
 			dump_stack();
 			return NULL;
 		}
-		if ((eid == _VENDOR_SPECIFIC_IE_) && (_rtw_memcmp(&in_ie[cnt+2], p2p_oui, 4) == true)) {
+		if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&in_ie[cnt+2], p2p_oui, 4))) {
 			p2p_ie_ptr = in_ie + cnt;
 
 			if (p2p_ie != NULL)
@@ -1258,7 +1245,7 @@ u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id , u8 *buf_att
 		*len_attr = 0;
 
 	if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-	    (_rtw_memcmp(p2p_ie + 2, p2p_oui , 4) != true))
+	    (memcmp(p2p_ie + 2, p2p_oui , 4)))
 		return attr_ptr;
 
 	/*  6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
diff --git a/drivers/staging/rtl8188eu/core/rtw_io.c b/drivers/staging/rtl8188eu/core/rtw_io.c
index ff0398fca52b..7530532b3ff0 100644
--- a/drivers/staging/rtl8188eu/core/rtw_io.c
+++ b/drivers/staging/rtl8188eu/core/rtw_io.c
@@ -59,10 +59,8 @@ u8 _rtw_read8(struct adapter *adapter, u32 addr)
 	struct	intf_hdl *pintfhdl = &(pio_priv->intf);
 	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
 
-	_func_enter_;
 	_read8 = pintfhdl->io_ops._read8;
 	r_val = _read8(pintfhdl, addr);
-	_func_exit_;
 	return r_val;
 }
 
@@ -72,11 +70,9 @@ u16 _rtw_read16(struct adapter *adapter, u32 addr)
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
-_func_enter_;
 	_read16 = pintfhdl->io_ops._read16;
 
 	r_val = _read16(pintfhdl, addr);
-_func_exit_;
 	return r_val;
 }
 
@@ -86,11 +82,9 @@ u32 _rtw_read32(struct adapter *adapter, u32 addr)
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
-_func_enter_;
 	_read32 = pintfhdl->io_ops._read32;
 
 	r_val = _read32(pintfhdl, addr);
-_func_exit_;
 	return r_val;
 }
 
@@ -100,11 +94,9 @@ int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int ret;
-	_func_enter_;
 	_write8 = pintfhdl->io_ops._write8;
 
 	ret = _write8(pintfhdl, addr, val);
-	_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -115,11 +107,9 @@ int _rtw_write16(struct adapter *adapter, u32 addr, u16 val)
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
 	int ret;
-	_func_enter_;
 	_write16 = pintfhdl->io_ops._write16;
 
 	ret = _write16(pintfhdl, addr, val);
-	_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -129,11 +119,9 @@ int _rtw_write32(struct adapter *adapter, u32 addr, u32 val)
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
 	int ret;
-	_func_enter_;
 	_write32 = pintfhdl->io_ops._write32;
 
 	ret = _write32(pintfhdl, addr, val);
-	_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -144,11 +132,9 @@ int _rtw_writeN(struct adapter *adapter, u32 addr , u32 length , u8 *pdata)
 	struct	intf_hdl *pintfhdl = (struct intf_hdl *)(&(pio_priv->intf));
 	int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
 	int ret;
-	_func_enter_;
 	_writeN = pintfhdl->io_ops._writeN;
 
 	ret = _writeN(pintfhdl, addr, length, pdata);
-	_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -158,11 +144,9 @@ int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val)
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int ret;
-	_func_enter_;
 	_write8_async = pintfhdl->io_ops._write8_async;
 
 	ret = _write8_async(pintfhdl, addr, val);
-	_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -174,10 +158,8 @@ int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val)
 	int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
 	int ret;
 
-_func_enter_;
 	_write16_async = pintfhdl->io_ops._write16_async;
 	ret = _write16_async(pintfhdl, addr, val);
-_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -189,10 +171,8 @@ int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val)
 	int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
 	int ret;
 
-_func_enter_;
 	_write32_async = pintfhdl->io_ops._write32_async;
 	ret = _write32_async(pintfhdl, addr, val);
-_func_exit_;
 
 	return RTW_STATUS_CODE(ret);
 }
@@ -203,7 +183,6 @@ void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 
-	_func_enter_;
 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
 		RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
 			 ("rtw_read_mem:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
@@ -212,7 +191,6 @@ void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 	}
 	_read_mem = pintfhdl->io_ops._read_mem;
 	_read_mem(pintfhdl, addr, cnt, pmem);
-	_func_exit_;
 }
 
 void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
@@ -221,13 +199,11 @@ void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 
-	_func_enter_;
 
 	_write_mem = pintfhdl->io_ops._write_mem;
 
 	_write_mem(pintfhdl, addr, cnt, pmem);
 
-	_func_exit_;
 }
 
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
@@ -236,7 +212,6 @@ void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 
-	_func_enter_;
 
 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
 		RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
@@ -249,7 +224,6 @@ void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 
 	_read_port(pintfhdl, addr, cnt, pmem);
 
-	_func_exit_;
 }
 
 void _rtw_read_port_cancel(struct adapter *adapter)
@@ -271,13 +245,11 @@ u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
 	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
 	u32 ret = _SUCCESS;
 
-	_func_enter_;
 
 	_write_port = pintfhdl->io_ops._write_port;
 
 	ret = _write_port(pintfhdl, addr, cnt, pmem);
 
-	 _func_exit_;
 
 	return ret;
 }
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
index e25b39b97d9e..2a54e3369f64 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -42,7 +42,6 @@ u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
 	u8	 i;
 	u8	ret = true;
 
-_func_enter_;
 
 	if (ssid->SsidLength > 32) {
 		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
@@ -61,8 +60,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
-
 	return ret;
 }
 
@@ -74,11 +71,10 @@ u8 rtw_do_join(struct adapter *padapter)
 	struct __queue *queue	= &(pmlmepriv->scanned_queue);
 	u8 ret = _SUCCESS;
 
-_func_enter_;
 
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist));
 
@@ -170,7 +166,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
@@ -181,7 +176,6 @@ u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
 	u32 cur_time = 0;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid);
 
@@ -205,7 +199,7 @@ _func_enter_;
 	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
 		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
 
-		if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
+		if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
 			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)
 				goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
 		} else {
@@ -257,7 +251,6 @@ exit:
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
 		 ("rtw_set_802_11_bssid: status=%d\n", status));
 
-_func_exit_;
 
 	return status;
 }
@@ -270,7 +263,6 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
 
-_func_enter_;
 
 	DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
 		      ssid->Ssid, get_fwstate(pmlmepriv));
@@ -296,7 +288,7 @@ _func_enter_;
 			 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
 
 		if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
-		    (_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
+		    (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
 			if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
 				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
 					 ("Set SSID is the same ssid, fw_state = 0x%08x\n",
@@ -369,7 +361,6 @@ release_mlme_lock:
 exit:
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
 		 ("-rtw_set_802_11_ssid: status =%d\n", status));
-_func_exit_;
 	return status;
 }
 
@@ -380,7 +371,6 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
 	struct	wlan_network	*cur_network = &pmlmepriv->cur_network;
 	enum ndis_802_11_network_infra *pold_state = &(cur_network->network.InfrastructureMode);
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
 		 ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n",
@@ -411,7 +401,7 @@ _func_enter_;
 
 		if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
 			if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
+				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether  issue dis-assoc_cmd or not */
 	       }
 
 		*pold_state = networktype;
@@ -438,7 +428,6 @@ _func_enter_;
 		spin_unlock_bh(&pmlmepriv->lock);
 	}
 
-_func_exit_;
 
 	return true;
 }
@@ -448,7 +437,6 @@ u8 rtw_set_802_11_disassociate(struct adapter *padapter)
 {
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	spin_lock_bh(&pmlmepriv->lock);
 
@@ -464,7 +452,6 @@ _func_enter_;
 
 	spin_unlock_bh(&pmlmepriv->lock);
 
-_func_exit_;
 
 	return true;
 }
@@ -474,7 +461,6 @@ u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_s
 	struct	mlme_priv		*pmlmepriv = &padapter->mlmepriv;
 	u8	res = true;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+rtw_set_802_11_bssid_list_scan(), fw_state =%x\n", get_fwstate(pmlmepriv)));
 
@@ -514,7 +500,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -525,7 +510,6 @@ u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11
 	int res;
 	u8 ret;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_802_11_auth.mode(): mode =%x\n", authmode));
 
@@ -545,7 +529,6 @@ _func_enter_;
 	else
 		ret = false;
 
-_func_exit_;
 
 	return ret;
 }
@@ -556,7 +539,6 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
 	struct security_priv *psecuritypriv = &(padapter->securitypriv);
 	u8		ret = _SUCCESS;
 
-_func_enter_;
 
 	keyid = wep->KeyIndex & 0x3fffffff;
 
@@ -581,7 +563,7 @@ _func_enter_;
 		break;
 	}
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-		 ("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
+		 ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
 		 wep->KeyLength, wep->KeyIndex, keyid));
 
 	memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
@@ -611,7 +593,6 @@ _func_enter_;
 	if (res == _FAIL)
 		ret = false;
 exit:
-_func_exit_;
 	return ret;
 }
 
@@ -619,7 +600,6 @@ u8 rtw_set_802_11_remove_wep(struct adapter *padapter, u32 keyindex)
 {
 	u8 ret = _SUCCESS;
 
-_func_enter_;
 	if (keyindex >= 0x80000000 || padapter == NULL) {
 		ret = false;
 		goto exit;
@@ -638,7 +618,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 	return ret;
 }
 
@@ -651,7 +630,6 @@ u8 rtw_set_802_11_add_key(struct adapter *padapter, struct ndis_802_11_key *key)
 	u8	bgrouptkey = false;/* can be removed later */
 	u8	ret = _SUCCESS;
 
-_func_enter_;
 
 	if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)) {
 		/*  It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, */
@@ -992,7 +970,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 	return ret;
 }
 
@@ -1004,7 +981,6 @@ u8 rtw_set_802_11_remove_key(struct adapter *padapter, struct ndis_802_11_remove
 	u8	keyIndex = (u8)key->KeyIndex & 0x03;
 	u8	ret = _SUCCESS;
 
-_func_enter_;
 
 	if ((key->KeyIndex & 0xbffffffc) > 0) {
 		ret = _FAIL;
@@ -1032,7 +1008,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 	return ret;
 }
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c
index afac53709843..42b41ab1bce1 100644
--- a/drivers/staging/rtl8188eu/core/rtw_led.c
+++ b/drivers/staging/rtl8188eu/core/rtw_led.c
@@ -34,7 +34,7 @@ void BlinkTimerCallback(void *data)
 	if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
 		return;
 
-	_set_workitem(&(pLed->BlinkWorkItem));
+	schedule_work(&(pLed->BlinkWorkItem));
 }
 
 /*  */
@@ -80,7 +80,7 @@ void InitLed871x(struct adapter *padapter, struct LED_871x *pLed, enum LED_PIN_8
 
 	_init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed);
 
-	_init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed);
+	INIT_WORK(&(pLed->BlinkWorkItem), BlinkWorkItemCallback);
 }
 
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index c7382303088f..a934bd97219d 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -31,6 +31,7 @@
 #include <wlan_bssdef.h>
 #include <rtw_ioctl_set.h>
 #include <usb_osintf.h>
+#include <linux/vmalloc.h>
 
 extern unsigned char	MCS_rate_2R[16];
 extern unsigned char	MCS_rate_1R[16];
@@ -43,9 +44,7 @@ int	_rtw_init_mlme_priv (struct adapter *padapter)
 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
 	int	res = _SUCCESS;
 
-_func_enter_;
-
-	/*  We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
+	/*  We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
 
 	pmlmepriv->nic_hdl = (u8 *)padapter;
 
@@ -62,7 +61,7 @@ _func_enter_;
 
 	_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
 
-	pbuf = rtw_zvmalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
+	pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
 
 	if (pbuf == NULL) {
 		res = _FAIL;
@@ -87,9 +86,6 @@ _func_enter_;
 	rtw_init_mlme_timer(padapter);
 
 exit:
-
-_func_exit_;
-
 	return res;
 }
 
@@ -124,22 +120,16 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
 
 void _rtw_free_mlme_priv (struct mlme_priv *pmlmepriv)
 {
-_func_enter_;
-
 	rtw_free_mlme_priv_ie_data(pmlmepriv);
 
 	if (pmlmepriv) {
-		if (pmlmepriv->free_bss_buf) {
-			rtw_vmfree(pmlmepriv->free_bss_buf, MAX_BSS_CNT * sizeof(struct wlan_network));
-		}
+		if (pmlmepriv->free_bss_buf)
+			vfree(pmlmepriv->free_bss_buf);
 	}
-_func_exit_;
 }
 
 int	_rtw_enqueue_network(struct __queue *queue, struct wlan_network *pnetwork)
 {
-_func_enter_;
-
 	if (pnetwork == NULL)
 		goto exit;
 
@@ -150,9 +140,6 @@ _func_enter_;
 	spin_unlock_bh(&queue->lock);
 
 exit:
-
-_func_exit_;
-
 	return _SUCCESS;
 }
 
@@ -160,22 +147,18 @@ struct	wlan_network *_rtw_dequeue_network(struct __queue *queue)
 {
 	struct wlan_network *pnetwork;
 
-_func_enter_;
-
 	spin_lock_bh(&queue->lock);
 
 	if (_rtw_queue_empty(queue)) {
 		pnetwork = NULL;
 	} else {
-		pnetwork = LIST_CONTAINOR(get_next(&queue->queue), struct wlan_network, list);
+		pnetwork = container_of((&queue->queue)->next, struct wlan_network, list);
 
 		rtw_list_delete(&(pnetwork->list));
 	}
 
 	spin_unlock_bh(&queue->lock);
 
-_func_exit_;
-
 	return pnetwork;
 }
 
@@ -185,17 +168,15 @@ struct	wlan_network *_rtw_alloc_network(struct	mlme_priv *pmlmepriv)/* _queue *f
 	struct __queue *free_queue = &pmlmepriv->free_bss_pool;
 	struct list_head *plist = NULL;
 
-_func_enter_;
-
 	spin_lock_bh(&free_queue->lock);
 
 	if (_rtw_queue_empty(free_queue) == true) {
 		pnetwork = NULL;
 		goto exit;
 	}
-	plist = get_next(&(free_queue->queue));
+	plist = free_queue->queue.next;
 
-	pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list);
+	pnetwork = container_of(plist , struct wlan_network, list);
 
 	rtw_list_delete(&pnetwork->list);
 
@@ -211,8 +192,6 @@ _func_enter_;
 exit:
 	spin_unlock_bh(&free_queue->lock);
 
-_func_exit_;
-
 	return pnetwork;
 }
 
@@ -222,13 +201,11 @@ void _rtw_free_network(struct	mlme_priv *pmlmepriv , struct wlan_network *pnetwo
 	u32 lifetime = SCANQUEUE_LIFETIME;
 	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
 
-_func_enter_;
-
 	if (pnetwork == NULL)
-		goto exit;
+		return;
 
 	if (pnetwork->fixed)
-		goto exit;
+		return;
 	curr_time = jiffies;
 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
 	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
@@ -236,33 +213,26 @@ _func_enter_;
 	if (!isfreeall) {
 		delta_time = (curr_time - pnetwork->last_scanned)/HZ;
 		if (delta_time < lifetime)/*  unit:sec */
-			goto exit;
+			return;
 	}
 	spin_lock_bh(&free_queue->lock);
 	rtw_list_delete(&(pnetwork->list));
 	rtw_list_insert_tail(&(pnetwork->list), &(free_queue->queue));
 	pmlmepriv->num_of_scanned--;
 	spin_unlock_bh(&free_queue->lock);
-
-exit:
-_func_exit_;
 }
 
 void _rtw_free_network_nolock(struct	mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
 {
 	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
 
-_func_enter_;
 	if (pnetwork == NULL)
-		goto exit;
+		return;
 	if (pnetwork->fixed)
-		goto exit;
+		return;
 	rtw_list_delete(&(pnetwork->list));
 	rtw_list_insert_tail(&(pnetwork->list), get_list_head(free_queue));
 	pmlmepriv->num_of_scanned--;
-exit:
-
-_func_exit_;
 }
 
 /*
@@ -276,24 +246,22 @@ struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
 	struct	wlan_network *pnetwork = NULL;
 	u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
 
-_func_enter_;
-	if (_rtw_memcmp(zero_addr, addr, ETH_ALEN)) {
+	if (!memcmp(zero_addr, addr, ETH_ALEN)) {
 		pnetwork = NULL;
 		goto exit;
 	}
 	phead = get_list_head(scanned_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (plist != phead) {
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network , list);
-		if (_rtw_memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN) == true)
+		pnetwork = container_of(plist, struct wlan_network , list);
+		if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
 			break;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	if (plist == phead)
 		pnetwork = NULL;
 exit:
-_func_exit_;
 	return pnetwork;
 }
 
@@ -305,29 +273,24 @@ void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
 
-_func_enter_;
-
-
 	spin_lock_bh(&scanned_queue->lock);
 
 	phead = get_list_head(scanned_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (rtw_end_of_queue_search(phead, plist) == false) {
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 		_rtw_free_network(pmlmepriv, pnetwork, isfreeall);
 	}
 	spin_unlock_bh(&scanned_queue->lock);
-_func_exit_;
 }
 
 int rtw_if_up(struct adapter *padapter)
 {
 	int res;
-_func_enter_;
 
 	if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
 	    (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false)) {
@@ -338,8 +301,6 @@ _func_enter_;
 	} else {
 		res =  true;
 	}
-
-_func_exit_;
 	return res;
 }
 
@@ -347,14 +308,12 @@ void rtw_generate_random_ibss(u8 *pibss)
 {
 	u32	curtime = jiffies;
 
-_func_enter_;
 	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]; */
-_func_exit_;
 	return;
 }
 
@@ -367,11 +326,9 @@ u8 *rtw_get_capability_from_ie(u8 *ie)
 u16 rtw_get_capability(struct wlan_bssid_ex *bss)
 {
 	__le16	val;
-_func_enter_;
 
 	memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
 
-_func_exit_;
 	return le16_to_cpu(val);
 }
 
@@ -388,43 +345,31 @@ u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
 int	rtw_init_mlme_priv (struct adapter *padapter)/* struct	mlme_priv *pmlmepriv) */
 {
 	int	res;
-_func_enter_;
 	res = _rtw_init_mlme_priv(padapter);/*  (pmlmepriv); */
-_func_exit_;
 	return res;
 }
 
 void rtw_free_mlme_priv (struct mlme_priv *pmlmepriv)
 {
-_func_enter_;
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv\n"));
 	_rtw_free_mlme_priv (pmlmepriv);
-_func_exit_;
 }
 
 static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
 {
-	struct	wlan_network	*pnetwork;
-_func_enter_;
-	pnetwork = _rtw_alloc_network(pmlmepriv);
-_func_exit_;
-	return pnetwork;
+	return _rtw_alloc_network(pmlmepriv);
 }
 
 static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
 				    struct wlan_network *pnetwork)
 {
-_func_enter_;
 	_rtw_free_network_nolock(pmlmepriv, pnetwork);
-_func_exit_;
 }
 
 
 void rtw_free_network_queue(struct adapter *dev, u8 isfreeall)
 {
-_func_enter_;
 	_rtw_free_network_queue(dev, isfreeall);
-_func_exit_;
 }
 
 /*
@@ -458,7 +403,7 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
 static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
 {
 	return (a->Ssid.SsidLength == b->Ssid.SsidLength) &&
-	       _rtw_memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
+	       !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
 }
 
 int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
@@ -466,7 +411,6 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
 	 u16 s_cap, d_cap;
 	__le16 le_scap, le_dcap;
 
-_func_enter_;
 	memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->IEs), 2);
 	memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->IEs), 2);
 
@@ -474,11 +418,9 @@ _func_enter_;
 	s_cap = le16_to_cpu(le_scap);
 	d_cap = le16_to_cpu(le_dcap);
 
-_func_exit_;
-
 	return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
-		((_rtw_memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) == true) &&
-		((_rtw_memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == true) &&
+		((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) == true) &&
+		((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == true) &&
 		((s_cap & WLAN_CAPABILITY_IBSS) ==
 		(d_cap & WLAN_CAPABILITY_IBSS)) &&
 		((s_cap & WLAN_CAPABILITY_BSS) ==
@@ -491,25 +433,23 @@ struct	wlan_network	*rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
 	struct	wlan_network	*pwlan = NULL;
 	struct	wlan_network	*oldest = NULL;
 
-_func_enter_;
 	phead = get_list_head(scanned_queue);
 
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pwlan = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pwlan = container_of(plist, struct wlan_network, list);
 
 		if (!pwlan->fixed) {
 			if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
 				oldest = pwlan;
 		}
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
-_func_exit_;
 	return oldest;
 }
 
@@ -522,7 +462,6 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
 	u8 sq_final;
 	long rssi_final;
 
-_func_enter_;
 	rtw_hal_antdiv_rssi_compared(padapter, dst, src); /* this will update src.Rssi, need consider again */
 
 	/* The rule below is 1/5 for sample value, 4/5 for history value */
@@ -553,22 +492,18 @@ _func_enter_;
 	dst->PhyInfo.SignalQuality = sq_final;
 	dst->Rssi = rssi_final;
 
-_func_exit_;
 }
 
 static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
 {
 	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
 
-_func_enter_;
-
 	if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) &&
 	    (is_same_network(&(pmlmepriv->cur_network.network), pnetwork))) {
 		update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, true);
 		rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fixed_ie),
 				      pmlmepriv->cur_network.network.IELength);
 	}
-_func_exit_;
 }
 
 /*
@@ -583,24 +518,22 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
 	struct wlan_network	*pnetwork = NULL;
 	struct wlan_network	*oldest = NULL;
 
-_func_enter_;
-
 	spin_lock_bh(&queue->lock);
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork	= LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork	= container_of(plist, struct wlan_network, list);
 
 		if (is_same_network(&(pnetwork->network), target))
 			break;
 		if ((oldest == ((struct wlan_network *)0)) ||
 		    time_after(oldest->last_scanned, pnetwork->last_scanned))
 			oldest = pnetwork;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	/* If we didn't find a match, then get a new network slot to initialize
 	 * with this beacon's information */
@@ -663,19 +596,16 @@ _func_enter_;
 exit:
 	spin_unlock_bh(&queue->lock);
 
-_func_exit_;
 }
 
 static void rtw_add_network(struct adapter *adapter,
 			    struct wlan_bssid_ex *pnetwork)
 {
-_func_enter_;
 #if defined(CONFIG_88EU_P2P)
 	rtw_wlan_bssid_ex_remove_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO);
 #endif
 	update_current_network(adapter, pnetwork);
 	rtw_update_scanned_network(adapter, pnetwork);
-_func_exit_;
 }
 
 /* select the desired network based on the capability of the (i)bss. */
@@ -728,9 +658,7 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *
 /* TODO: Perry: For Power Management */
 void rtw_atimdone_event_callback(struct adapter	*adapter , u8 *pbuf)
 {
-_func_enter_;
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n"));
-_func_exit_;
 	return;
 }
 
@@ -741,8 +669,6 @@ void rtw_survey_event_callback(struct adapter	*adapter, u8 *pbuf)
 	struct wlan_bssid_ex *pnetwork;
 	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
 
-_func_enter_;
-
 	pnetwork = (struct wlan_bssid_ex *)pbuf;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_survey_event_callback, ssid=%s\n",  pnetwork->Ssid.Ssid));
@@ -756,7 +682,7 @@ _func_enter_;
 
 	/*  update IBSS_network 's timestamp */
 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
-		if (_rtw_memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
+		if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
 			struct wlan_network *ibss_wlan = NULL;
 
 			memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
@@ -781,20 +707,14 @@ _func_enter_;
 exit:
 
 	spin_unlock_bh(&pmlmepriv->lock);
-
-_func_exit_;
-
 	return;
 }
 
-
-
 void rtw_surveydone_event_callback(struct adapter	*adapter, u8 *pbuf)
 {
 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
 	struct mlme_ext_priv *pmlmeext;
 
-_func_enter_;
 	spin_lock_bh(&pmlmepriv->lock);
 
 	if (pmlmepriv->wps_probe_req_ie) {
@@ -884,7 +804,6 @@ _func_enter_;
 	pmlmeext = &adapter->mlmeextpriv;
 	if (pmlmeext->sitesurvey_res.bss_cnt == 0)
 		rtw_hal_sreset_reset(adapter);
-_func_exit_;
 }
 
 void rtw_dummy_event_callback(struct adapter *adapter , u8 *pbuf)
@@ -901,17 +820,15 @@ static void free_scanqueue(struct	mlme_priv *pmlmepriv)
 	struct __queue *scan_queue = &pmlmepriv->scanned_queue;
 	struct list_head *plist, *phead, *ptemp;
 
-_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
 	spin_lock_bh(&scan_queue->lock);
 	spin_lock_bh(&free_queue->lock);
 
 	phead = get_list_head(scan_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (plist != phead) {
-		ptemp = get_next(plist);
+		ptemp = plist->next;
 		rtw_list_delete(plist);
 		rtw_list_insert_tail(plist, &free_queue->queue);
 		plist = ptemp;
@@ -920,8 +837,6 @@ _func_enter_;
 
 	spin_unlock_bh(&free_queue->lock);
 	spin_unlock_bh(&scan_queue->lock);
-
-_func_exit_;
 }
 
 /*
@@ -934,8 +849,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 
-_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 		 ("tgt_network->network.MacAddress=%pM ssid=%s\n",
@@ -979,7 +892,6 @@ _func_enter_;
 	if (lock_scanned_queue)
 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 	pmlmepriv->key_mask = 0;
-_func_exit_;
 }
 
 /*
@@ -989,8 +901,6 @@ void rtw_indicate_connect(struct adapter *padapter)
 {
 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect\n"));
 
 	pmlmepriv->to_join = false;
@@ -1008,7 +918,6 @@ _func_enter_;
 	rtw_set_scan_deny(padapter, 3000);
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
-_func_exit_;
 }
 
 /*
@@ -1018,7 +927,6 @@ void rtw_indicate_disconnect(struct adapter *padapter)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect\n"));
 
 	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS);
@@ -1038,8 +946,6 @@ _func_enter_;
 	p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
 
 	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
-
-_func_exit_;
 }
 
 inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
@@ -1206,8 +1112,6 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
 	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
 	unsigned int		the_same_macaddr = false;
 
-_func_enter_;
-
 	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_registrypriv(adapter);
@@ -1218,12 +1122,12 @@ _func_enter_;
 	else
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@   rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
 
-	the_same_macaddr = _rtw_memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
+	the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
 
 	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"));
-		goto ignore_nolock;
+		return;
 	}
 
 	spin_lock_bh(&pmlmepriv->lock);
@@ -1319,21 +1223,15 @@ _func_enter_;
 
 ignore_joinbss_callback:
 	spin_unlock_bh(&pmlmepriv->lock);
-ignore_nolock:
-_func_exit_;
 }
 
 void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
 {
 	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
 
-_func_enter_;
-
 	mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
 
 	rtw_os_xmit_schedule(adapter);
-
-_func_exit_;
 }
 
 static u8 search_max_mac_id(struct adapter *padapter)
@@ -1388,8 +1286,6 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
 	struct wlan_network	*cur_network = &(pmlmepriv->cur_network);
 	struct wlan_network	*ptarget_wlan = NULL;
 
-_func_enter_;
-
 	if (rtw_access_ctrl(adapter, pstassoc->macaddr) == false)
 		return;
 
@@ -1400,7 +1296,7 @@ _func_enter_;
 			ap_sta_info_defer_update(adapter, psta);
 			rtw_stassoc_hw_rpt(adapter, psta);
 		}
-		goto exit;
+		return;
 	}
 #endif
 	/* for AD-HOC mode */
@@ -1408,12 +1304,12 @@ _func_enter_;
 	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_callback: sta has been in sta_hash_queue\n"));
-		goto exit; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
+		return; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
 	}
 	psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
 	if (psta == NULL) {
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
-		goto exit;
+		return;
 	}
 	/* to do: init sta_info variable */
 	psta->qos_option = 0;
@@ -1440,8 +1336,6 @@ _func_enter_;
 	}
 	spin_unlock_bh(&pmlmepriv->lock);
 	mlmeext_sta_add_event_callback(adapter, psta);
-exit:
-_func_exit_;
 }
 
 void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
@@ -1456,8 +1350,6 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 
-_func_enter_;
-
 	psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
 	if (psta)
 		mac_id = psta->mac_id;
@@ -1541,14 +1433,11 @@ _func_enter_;
 		}
 	}
 	spin_unlock_bh(&pmlmepriv->lock);
-_func_exit_;
 }
 
 void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
 {
-_func_enter_;
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_cpwm_event_callback !!!\n"));
-_func_exit_;
 }
 
 /*
@@ -1560,8 +1449,6 @@ void _rtw_join_timeout_handler (struct adapter *adapter)
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	int do_join_r;
 
-_func_enter_;
-
 	DBG_88E("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
 
 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
@@ -1592,7 +1479,6 @@ _func_enter_;
 		free_scanqueue(pmlmepriv);/*  */
 	}
 	spin_unlock_bh(&pmlmepriv->lock);
-_func_exit_;
 }
 
 /*
@@ -1687,14 +1573,14 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
 
 	/* check bssid, if needed */
 	if (pmlmepriv->assoc_by_bssid) {
-		if (!_rtw_memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN))
+		if (memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN))
 			goto exit;
 	}
 
 	/* check ssid, if needed */
-	if (pmlmepriv->assoc_ssid.Ssid && pmlmepriv->assoc_ssid.SsidLength) {
+	if (pmlmepriv->assoc_ssid.SsidLength) {
 		if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength ||
-		    _rtw_memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength) == false)
+		    !memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength) == false)
 			goto exit;
 	}
 
@@ -1742,20 +1628,18 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
 	struct	wlan_network	*candidate = NULL;
 	u8	supp_ant_div = false;
 
-_func_enter_;
-
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 	phead = get_list_head(queue);
 	adapter = (struct adapter *)pmlmepriv->nic_hdl;
-	pmlmepriv->pscanned = get_next(phead);
+	pmlmepriv->pscanned = phead->next;
 	while (!rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) {
-		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+		pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 		if (pnetwork == NULL) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork==NULL)\n", __func__));
 			ret = _FAIL;
 			goto exit;
 		}
-		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 		rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
 	}
 	if (candidate == NULL) {
@@ -1792,9 +1676,6 @@ _func_enter_;
 
 exit:
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-_func_exit_;
-
 	return ret;
 }
 
@@ -1805,8 +1686,6 @@ int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
 	struct	cmd_priv *pcmdpriv = &(adapter->cmdpriv);
 	int		res = _SUCCESS;
 
-_func_enter_;
-
 	pcmd = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (pcmd == NULL) {
 		res = _FAIL;  /* try again */
@@ -1832,7 +1711,6 @@ _func_enter_;
 		 psecuritypriv->dot11AuthAlgrthm));
 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -1845,7 +1723,6 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in
 	struct mlme_priv		*pmlmepriv = &(adapter->mlmepriv);
 	int	res = _SUCCESS;
 
-_func_enter_;
 	pcmd = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
 	if (pcmd == NULL) {
 		res = _FAIL;  /* try again */
@@ -1914,7 +1791,6 @@ _func_enter_;
 	_rtw_init_listhead(&pcmd->list);
 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -1964,7 +1840,7 @@ static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
 
 	do {
 		if ((psecuritypriv->PMKIDList[i].bUsed) &&
-		    (_rtw_memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN) == true)) {
+		    (!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN))) {
 			break;
 		} else {
 			i++;
@@ -2018,8 +1894,6 @@ int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
 	uint	ndisauthmode = psecuritypriv->ndisauthtype;
 	uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
 
-_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
 		 ("+rtw_restruct_sec_ie: ndisauthmode=%d ndissecuritytype=%d\n",
 		  ndisauthmode, ndissecuritytype));
@@ -2052,9 +1926,6 @@ _func_enter_;
 		if (authmode == _WPA2_IE_ID_)
 			ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
 	}
-
-_func_exit_;
-
 	return ielength;
 }
 
@@ -2065,8 +1936,6 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter)
 	struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
 	u8 *myhwaddr = myid(peepriv);
 
-_func_enter_;
-
 	memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
 
 	memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
@@ -2077,8 +1946,6 @@ _func_enter_;
 	pdev_network->Configuration.FHConfig.HopPattern = 0;
 	pdev_network->Configuration.FHConfig.HopSet = 0;
 	pdev_network->Configuration.FHConfig.DwellTime = 0;
-
-_func_exit_;
 }
 
 void rtw_update_registrypriv_dev_network(struct adapter *adapter)
@@ -2089,8 +1956,6 @@ void rtw_update_registrypriv_dev_network(struct adapter *adapter)
 	struct	security_priv *psecuritypriv = &adapter->securitypriv;
 	struct	wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
 
-_func_enter_;
-
 	pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); /*  adhoc no 802.1x */
 
 	pdev_network->Rssi = 0;
@@ -2140,13 +2005,10 @@ _func_enter_;
 
 	/* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
 	/* pdev_network->IELength = cpu_to_le32(sz); */
-_func_exit_;
 }
 
 void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
 {
-_func_enter_;
-_func_exit_;
 }
 
 /* the function is at passive_level */
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index 6f7e415ecb6c..4942759b19c8 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -171,7 +171,7 @@ static struct rt_channel_plan_map	RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
 	{0x03},	/* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 };
 
-static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
+static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */
 
 /*
  * Search the @param channel_num in given @param channel_set
@@ -414,21 +414,21 @@ void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
 	}
 }
 
-static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
+static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame)
 {
 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 
 	  if (ptable->func) {
 	 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
-		if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
-		    !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+		if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+		    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 			return;
 		ptable->func(padapter, precv_frame);
 	}
 }
 
-void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
+void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	int index;
 	struct mlme_handler *ptable;
@@ -436,7 +436,7 @@ void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 #endif /* CONFIG_88EU_AP_MODE */
 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
@@ -449,8 +449,8 @@ void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 	}
 
 	/* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
-	if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
-	    !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+	if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+	    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 		return;
 
 	ptable = mlme_sta_tbl;
@@ -465,13 +465,15 @@ void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 
 	if (psta != NULL) {
 		if (GetRetry(pframe)) {
-			if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
+			if (precv_frame->attrib.seq_num ==
+			    psta->RxMgmtFrameSeqNum) {
 				/* drop the duplicate management frame */
-				DBG_88E("Drop duplicate management frame with seq_num=%d.\n", precv_frame->u.hdr.attrib.seq_num);
+				DBG_88E("Drop duplicate management frame with seq_num=%d.\n",
+					precv_frame->attrib.seq_num);
 				return;
 			}
 		}
-		psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
+		psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
 	}
 
 #ifdef CONFIG_88EU_AP_MODE
@@ -532,7 +534,7 @@ Following are the callback functions for each subtype of the management frames
 
 *****************************************************************************/
 
-unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	unsigned int	ielen;
 	unsigned char	*p;
@@ -540,8 +542,8 @@ unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint len = precv_frame->len;
 	u8 is_valid_p2p_probereq = false;
 
 #ifdef CONFIG_88EU_P2P
@@ -596,7 +598,7 @@ _continue:
 		if (is_valid_p2p_probereq)
 			goto _issue_probersp;
 
-		if ((ielen != 0 && !_rtw_memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
+		if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
 		    (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
 			return _SUCCESS;
 
@@ -609,18 +611,18 @@ _issue_probersp:
 	return _SUCCESS;
 }
 
-unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 #ifdef CONFIG_88EU_P2P
 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 #endif
 
 #ifdef CONFIG_88EU_P2P
 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
 		if (pwdinfo->tx_prov_disc_info.benable) {
-			if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+			if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
 					pwdinfo->tx_prov_disc_info.benable = false;
 					issue_p2p_provision_request(padapter,
@@ -638,7 +640,7 @@ unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
 		if (pwdinfo->nego_req_info.benable) {
 			DBG_88E("[%s] P2P State is GONEGO ING!\n", __func__);
-			if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+			if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 				pwdinfo->nego_req_info.benable = false;
 				issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
 			}
@@ -646,7 +648,7 @@ unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
 		if (pwdinfo->invitereq_info.benable) {
 			DBG_88E("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
-			if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+			if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 				pwdinfo->invitereq_info.benable = false;
 				issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
 			}
@@ -663,7 +665,7 @@ unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 	return _SUCCESS;
 }
 
-unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	int cam_idx;
 	struct sta_info	*psta;
@@ -671,8 +673,8 @@ unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct sta_priv	*pstapriv = &padapter->stapriv;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint len = precv_frame->len;
 	struct wlan_bssid_ex *pbss;
 	int ret = _SUCCESS;
 
@@ -681,7 +683,7 @@ unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
 		return _SUCCESS;
 	}
 
-	if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
+	if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
 		if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 			/* we should update current network before auth, or some IE is wrong */
 			pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
@@ -753,7 +755,7 @@ _END_ONBEACON_:
 	return _SUCCESS;
 }
 
-unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_AP_MODE
 	unsigned int	auth_mode, ie_len;
@@ -767,8 +769,8 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint len = precv_frame->len;
 
 	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 		return _FAIL;
@@ -878,7 +880,7 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
 				goto auth_fail;
 			}
 
-			if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
+			if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
 				pstat->state &= (~WIFI_FW_AUTH_STATE);
 				pstat->state |= WIFI_FW_AUTH_SUCCESS;
 				/*  challenging txt is correct... */
@@ -926,20 +928,20 @@ auth_fail:
 	return _FAIL;
 }
 
-unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	unsigned int	seq, len, status, offset;
 	unsigned char	*p;
 	unsigned int	go2asoc = 0;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint pkt_len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint pkt_len = precv_frame->len;
 
 	DBG_88E("%s\n", __func__);
 
 	/* check A1 matches or not */
-	if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
+	if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
 		return _SUCCESS;
 
 	if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
@@ -1001,7 +1003,7 @@ authclnt_fail:
 	return _FAIL;
 }
 
-unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_AP_MODE
 	u16 capab_info;
@@ -1020,8 +1022,8 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
 	struct sta_priv *pstapriv = &padapter->stapriv;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint pkt_len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint pkt_len = precv_frame->len;
 #ifdef CONFIG_88EU_P2P
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
 	u8 p2p_status_code = P2P_STATUS_SUCCESS;
@@ -1097,7 +1099,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
 		status = _STATS_FAILURE_;
 	} else {
 		/*  check if ssid match */
-		if (!_rtw_memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
+		if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
 			status = _STATS_FAILURE_;
 
 		if (ie_len != cur->Ssid.SsidLength)
@@ -1270,7 +1272,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
 		for (;;) {
 			p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
 			if (p != NULL) {
-				if (_rtw_memcmp(p+2, WMM_IE, 6)) {
+				if (!memcmp(p+2, WMM_IE, 6)) {
 					pstat->flags |= WLAN_STA_WME;
 
 					pstat->qos_option = 1;
@@ -1470,7 +1472,7 @@ OnAssocReqFail:
 	return _FAIL;
 }
 
-unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	uint i;
 	int res;
@@ -1480,13 +1482,13 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	/* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint pkt_len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint pkt_len = precv_frame->len;
 
 	DBG_88E("%s\n", __func__);
 
 	/* check A1 matches or not */
-	if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
+	if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
 		return _SUCCESS;
 
 	if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
@@ -1524,7 +1526,7 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
 
 		switch (pIE->ElementID) {
 		case _VENDOR_SPECIFIC_IE_:
-			if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))	/* WMM */
+			if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
 				WMM_param_handler(padapter, pIE);
 			break;
 		case _HT_CAPABILITY_IE_:	/* HT caps */
@@ -1560,19 +1562,20 @@ report_assoc_result:
 	return _SUCCESS;
 }
 
-unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnDeAuth(struct 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_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 #ifdef CONFIG_88EU_P2P
 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
 #endif /* CONFIG_88EU_P2P */
 
 	/* check A3 */
-	if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+	if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
+		   ETH_ALEN))
 		return _SUCCESS;
 
 #ifdef CONFIG_88EU_P2P
@@ -1623,19 +1626,20 @@ unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
 	return _SUCCESS;
 }
 
-unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	u16 reason;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 #ifdef CONFIG_88EU_P2P
 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
 #endif /* CONFIG_88EU_P2P */
 
 	/* check A3 */
-	if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+	if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
+		   ETH_ALEN))
 		return _SUCCESS;
 
 #ifdef CONFIG_88EU_P2P
@@ -1685,18 +1689,18 @@ unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
 	return _SUCCESS;
 }
 
-unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAtim(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	DBG_88E("%s\n", __func__);
 	return _SUCCESS;
 }
 
-unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int on_action_spct(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	unsigned int ret = _FAIL;
 	struct sta_info *psta = NULL;
 	struct sta_priv *pstapriv = &padapter->stapriv;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
 	u8 category;
 	u8 action;
@@ -1729,17 +1733,17 @@ exit:
 	return ret;
 }
 
-unsigned int OnAction_qos(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_qos(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction_dls(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_dls(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	u8 *addr;
 	struct sta_info *psta = NULL;
@@ -1749,10 +1753,11 @@ unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_fra
 	unsigned short	tid, status, reason_code = 0;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	/* check RA matches or not */
-	if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
+	if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe),
+		   ETH_ALEN))/* for if1, sta/ap mode */
 		return _SUCCESS;
 
 	DBG_88E("%s\n", __func__);
@@ -1937,7 +1942,7 @@ void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
 	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 */
+	/*	According to the P2P Specification, the group negotiation request frame should contain 9 P2P attributes */
 	/*	1. P2P Capability */
 	/*	2. Group Owner Intent */
 	/*	3. Configuration Timeout */
@@ -2280,7 +2285,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame
 	/*	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 (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
+	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)
@@ -2302,7 +2307,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame
 	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 */
+	/*	According to the P2P Specification, the group negotiation response frame should contain 9 P2P attributes */
 	/*	1. Status */
 	/*	2. P2P Capability */
 	/*	3. Group Owner Intent */
@@ -2604,7 +2609,7 @@ static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
 	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 */
+	/*	According to the P2P Specification, the group negotiation request frame should contain 5 P2P attributes */
 	/*	1. Status */
 	/*	2. P2P Capability */
 	/*	3. Operating Channel */
@@ -2825,7 +2830,8 @@ void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
 	/*	Channel Number */
 	p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;	/*	operating channel number */
 
-	if (_rtw_memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
+	if (!memcmp(myid(&padapter->eeprompriv),
+		    pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
 		/*	P2P Group BSSID */
 		/*	Type: */
 		p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
@@ -3260,7 +3266,7 @@ static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profil
 	for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
 	       DBG_88E("[%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 (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
+		if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
 			match_result = 1;
 			DBG_88E("[%s] Match!\n", __func__);
 			break;
@@ -3853,13 +3859,13 @@ exit:
 
 #endif /* CONFIG_88EU_P2P */
 
-static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
+static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
 {
-	struct adapter *adapter = recv_frame->u.hdr.adapter;
+	struct adapter *adapter = recv_frame->adapter;
 	struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
-	u8 *frame = recv_frame->u.hdr.rx_data;
-	u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
-		(recv_frame->u.hdr.attrib.frag_num & 0xf);
+	u8 *frame = recv_frame->rx_data;
+	u16 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
+		(recv_frame->attrib.frag_num & 0xf);
 
 	if (GetRetry(frame)) {
 		if (token >= 0) {
@@ -3885,14 +3891,14 @@ static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
 	return _SUCCESS;
 }
 
-static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
+static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
 {
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body;
 	u8 dialogToken = 0;
 #ifdef CONFIG_88EU_P2P
-	struct adapter *padapter = precv_frame->u.hdr.adapter;
-	uint len = precv_frame->u.hdr.len;
+	struct adapter *padapter = precv_frame->adapter;
+	uint len = precv_frame->len;
 	u8 *p2p_ie;
 	u32	p2p_ielen;
 	struct	wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -3939,7 +3945,8 @@ static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
 
 		/*	Commented by Kurt 20120113 */
 		/*	Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
-		if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
+		if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr,
+			    ETH_ALEN))
 			memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
 
 		result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
@@ -4021,7 +4028,7 @@ static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
 					_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
 					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
 					if (attr_contentlen) {
-						if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
+						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
 							/*	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);
@@ -4069,7 +4076,7 @@ static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
 					_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
 					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
 					if (attr_contentlen) {
-						if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
+						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
 							/*	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;
@@ -4116,7 +4123,7 @@ static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
 				pwdinfo->invitereq_info.benable = false;
 
 				if (attr_content == P2P_STATUS_SUCCESS) {
-					if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
+					if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
 					} else {
 						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
@@ -4175,23 +4182,22 @@ static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
 	return _SUCCESS;
 }
 
-static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
+static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
 {
 	unsigned int ret = _FAIL;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
 
-	if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == true) {
+	if (!memcmp(frame_body + 2, P2P_OUI, 4))
 		ret = on_action_public_p2p(precv_frame);
-	}
 
 	return ret;
 }
 
-static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
+static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 action)
 {
 	unsigned int ret = _FAIL;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
 	u8 token;
 
@@ -4206,15 +4212,15 @@ exit:
 	return ret;
 }
 
-unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	unsigned int ret = _FAIL;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
 	u8 category, action;
 
 	/* check RA matches or not */
-	if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
+	if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
 		goto exit;
 
 	category = frame_body[0];
@@ -4235,30 +4241,30 @@ exit:
 	return ret;
 }
 
-unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_ht(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction_wmm(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_wmm(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction_p2p(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_P2P
 	u8 *frame_body;
 	u8 category, OUI_Subtype;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	uint len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	uint len = precv_frame->len;
 	struct	wifidirect_info	*pwdinfo = &(padapter->wdinfo);
 
 
 	DBG_88E("%s\n", __func__);
 
 	/* check RA matches or not */
-	if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
+	if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
 		return _SUCCESS;
 
 	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
@@ -4290,13 +4296,13 @@ unsigned int OnAction_p2p(struct adapter *padapter, union recv_frame *precv_fram
 	return _SUCCESS;
 }
 
-unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	int i;
 	unsigned char	category;
 	struct action_handler *ptable;
 	unsigned char	*frame_body;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
+	u8 *pframe = precv_frame->rx_data;
 
 	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
 
@@ -4310,7 +4316,7 @@ unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
 	return _SUCCESS;
 }
 
-unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
+unsigned int DoReserved(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
@@ -4341,7 +4347,7 @@ struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
 
 /****************************************************************************
 
-Following are some TX fuctions for WiFi MLME
+Following are some TX functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -4432,7 +4438,7 @@ s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg
 	}
 
 	pxmitpriv->ack_tx = false;
-	_exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	mutex_unlock(&pxmitpriv->ack_tx_mutex);
 
 	 return ret;
 }
@@ -4995,7 +5001,7 @@ exit:
 	return ret;
 }
 
-/*  if psta == NULL, indiate we are station(client) now... */
+/*  if psta == NULL, indicate we are station(client) now... */
 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
 {
 	struct xmit_frame *pmgntframe;
@@ -5234,7 +5240,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
 
 		for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
 			pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
-			if (pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) {
+			if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
 				memcpy(pframe, pbuf, ie_len+2);
 				pframe += (ie_len+2);
 				pattrib->pktlen += (ie_len+2);
@@ -5439,14 +5445,14 @@ void issue_assocreq(struct adapter *padapter)
 
 		switch (pIE->ElementID) {
 		case _VENDOR_SPECIFIC_IE_:
-			if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
-			    (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
-			    (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {
+			if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
+			    (!memcmp(pIE->data, WMM_OUI, 4)) ||
+			    (!memcmp(pIE->data, WPS_OUI, 4))) {
 				if (!padapter->registrypriv.wifi_spec) {
 					/* Commented by Kurt 20110629 */
 					/* In some older APs, WPS handshake */
 					/* would be fail if we append vender extensions informations to AP */
-					if (_rtw_memcmp(pIE->data, WPS_OUI, 4))
+					if (!memcmp(pIE->data, WPS_OUI, 4))
 						pIE->Length = 14;
 				}
 				pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
@@ -5606,7 +5612,7 @@ exit:
 	return;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
 {
 	int ret = _FAIL;
@@ -5676,7 +5682,7 @@ exit:
 }
 
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
 {
@@ -5686,7 +5692,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -5721,7 +5727,7 @@ exit:
 	return ret;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
 {
 	int ret = _FAIL;
@@ -5799,7 +5805,7 @@ exit:
 	return ret;
 }
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
 {
@@ -5809,7 +5815,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -6222,7 +6228,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter)
 		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 		phead = get_list_head(queue);
-		plist = get_next(phead);
+		plist = phead->next;
 
 		while (1) {
 			int len;
@@ -6232,9 +6238,9 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter)
 			if (rtw_end_of_queue_search(phead, plist))
 				break;
 
-			pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+			pnetwork = container_of(plist, struct wlan_network, list);
 
-			plist = get_next(plist);
+			plist = plist->next;
 
 			pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
 
@@ -6355,7 +6361,7 @@ unsigned int send_beacon(struct adapter *padapter)
 
 /****************************************************************************
 
-Following are some utitity fuctions for WiFi MLME
+Following are some utility functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -6468,7 +6474,7 @@ void site_survey(struct adapter *padapter)
 		{
 			/*  20100721:Interrupt scan operation here. */
 			/*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
-			/*  It compares the scan result and select beter one to do connection. */
+			/*  It compares the scan result and select better one to do connection. */
 			if (rtw_hal_antdiv_before_linked(padapter)) {
 				pmlmeext->sitesurvey_res.bss_cnt = 0;
 				pmlmeext->sitesurvey_res.channel_idx = -1;
@@ -6526,14 +6532,14 @@ void site_survey(struct adapter *padapter)
 }
 
 /* collect bss info from Beacon and Probe request/response frames. */
-u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
+u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
 {
 	int	i;
 	u32	len;
 	u8 *p;
 	u16 val16, subtype;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	u32	packet_len = precv_frame->u.hdr.len;
+	u8 *pframe = precv_frame->rx_data;
+	u32	packet_len = precv_frame->len;
 	u8 ie_offset;
 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
@@ -6572,10 +6578,10 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str
 	bssid->IELength = len;
 	memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
 
-	/* get the signal strength */
-	bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recvpower; /*  in dBM.raw data */
-	bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
-	bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
+	/* get the signal strength in dBM.raw data */
+	bssid->Rssi = precv_frame->attrib.phy_info.recvpower;
+	bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
+	bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
 	rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
 
 	/*  checking SSID */
@@ -6707,7 +6713,7 @@ void start_create_ibss(struct adapter *padapter)
 	/* update wireless mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability */
+	/* update capability */
 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
 	update_capinfo(padapter, caps);
 	if (caps&cap_IBSS) {/* adhoc master */
@@ -6759,7 +6765,7 @@ void start_clnt_join(struct adapter *padapter)
 	/* update wireless mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability */
+	/* update capability */
 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
 	update_capinfo(padapter, caps);
 	if (caps&cap_ESS) {
@@ -6851,7 +6857,7 @@ unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
 	/* check A3 */
-	if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+	if (memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
 		return _SUCCESS;
 
 	DBG_88E("%s\n", __func__);
@@ -7028,7 +7034,8 @@ Following are the functions to report events
 
 *****************************************************************************/
 
-void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
+void report_survey_event(struct adapter *padapter,
+			 struct recv_frame *precv_frame)
 {
 	struct cmd_obj *pcmd_obj;
 	u8 *pevtcmd;
@@ -7037,8 +7044,6 @@ void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame
 	struct C2HEvent_Header *pc2h_evt_hdr;
 	struct mlme_ext_priv *pmlmeext;
 	struct cmd_priv *pcmdpriv;
-	/* u8 *pframe = precv_frame->u.hdr.rx_data; */
-	/* uint len = precv_frame->u.hdr.len; */
 
 	if (!padapter)
 		return;
@@ -7373,7 +7378,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
 	/* turn on dynamic functions */
 	Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
 
-	/*  update IOT-releated issue */
+	/*  update IOT-related issue */
 	update_IOT_info(padapter);
 
 	rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
@@ -7381,7 +7386,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
 	/* BCN interval */
 	rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
 
-	/* udpate capability */
+	/* update capability */
 	update_capinfo(padapter, pmlmeinfo->capability);
 
 	/* WMM, Update EDCA param */
@@ -7902,7 +7907,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
 
 		switch (pIE->ElementID) {
 		case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
-			if (_rtw_memcmp(pIE->data, WMM_OUI, 4))
+			if (!memcmp(pIE->data, WMM_OUI, 4))
 				pmlmeinfo->WMM_enable = 1;
 			break;
 		case _HT_CAPABILITY_IE_:	/* Get HT Cap IE. */
@@ -8261,7 +8266,6 @@ u8 set_tx_beacon_cmd(struct adapter *padapter)
 	u8 res = _SUCCESS;
 	int len_diff = 0;
 
-_func_enter_;
 
 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL) {
@@ -8290,7 +8294,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -8368,12 +8371,12 @@ u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
 			spin_lock_bh(&psta_bmc->sleep_q.lock);
 
 			xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
-			xmitframe_plist = get_next(xmitframe_phead);
+			xmitframe_plist = xmitframe_phead->next;
 
 			while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-				pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+				pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-				xmitframe_plist = get_next(xmitframe_plist);
+				xmitframe_plist = xmitframe_plist->next;
 
 				rtw_list_delete(&pxmitframe->list);
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_mp.c b/drivers/staging/rtl8188eu/core/rtw_mp.c
index 6451efdfb132..2e02b2063c20 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mp.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mp.c
@@ -23,6 +23,7 @@
 
 #include "odm_precomp.h"
 #include "rtl8188e_hal.h"
+#include <linux/vmalloc.h>
 
 u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
 {
@@ -406,7 +407,7 @@ s32 mp_start_test(struct adapter *padapter)
 		goto end_of_mp_start_test;
 	}
 
-	/* 3 3. join psudo AdHoc */
+	/* 3 3. join pseudo AdHoc */
 	tgt_network->join_res = 1;
 	tgt_network->aid = 1;
 	psta->aid = 1;
@@ -442,7 +443,7 @@ void mp_stop_test(struct adapter *padapter)
 		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
 			goto end_of_mp_stop_test;
 
-		/* 3 1. disconnect psudo AdHoc */
+		/* 3 1. disconnect pseudo AdHoc */
 		rtw_indicate_disconnect(padapter);
 
 		/* 3 2. clear psta used in mp test mode. */
@@ -943,7 +944,7 @@ void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv)
 	}
 
 	if (pxmitpriv->pallocated_xmit_extbuf)
-		rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+		vfree(pxmitpriv->pallocated_xmit_extbuf);
 
 	if (padapter->registrypriv.mp_mode == 0) {
 		max_xmit_extbuf_size = 20000;
@@ -956,7 +957,7 @@ void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv)
 	/*  Init xmit extension buff */
 	_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
 
-	pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+	pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
 
 	if (pxmitpriv->pallocated_xmit_extbuf  == NULL) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
diff --git a/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c b/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c
index edcd8a5042be..e783968b29ea 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c
@@ -33,7 +33,6 @@ int rtl8188eu_oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->information_buf_len < sizeof(u8))
 		return NDIS_STATUS_INVALID_LENGTH;
@@ -48,7 +47,6 @@ _func_enter_;
 		status = NDIS_STATUS_NOT_ACCEPTED;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -61,7 +59,6 @@ int rtl8188eu_oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_write_bb_reg_hdl\n"));
 
@@ -87,7 +84,6 @@ _func_enter_;
 	write_bbreg(Adapter, offset, 0xFFFFFFFF, value);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -100,7 +96,6 @@ int rtl8188eu_oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_read_bb_reg_hdl\n"));
 
@@ -126,7 +121,6 @@ _func_enter_;
 	RT_TRACE(_module_mp_, _drv_notice_,
 		 ("-rtl8188eu_oid_rt_pro_read_bb_reg_hdl: offset=0x%03X value:0x%08X\n",
 		  offset, value));
-_func_exit_;
 
 	return status;
 }
@@ -140,7 +134,6 @@ int rtl8188eu_oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_write_rf_reg_hdl\n"));
 
@@ -171,7 +164,6 @@ _func_enter_;
 	write_rfreg(Adapter, path, offset, value);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -185,7 +177,6 @@ int rtl8188eu_oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 	int status = NDIS_STATUS_SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_read_rf_reg_hdl\n"));
 
@@ -217,7 +208,6 @@ _func_enter_;
 		 ("-rtl8188eu_oid_rt_pro_read_rf_reg_hdl: path=%d offset=0x%02X value=0x%05X\n",
 		  path, offset, value));
 
-_func_exit_;
 
 	return status;
 }
@@ -232,7 +222,6 @@ int rtl8188eu_oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_,
 		 ("+rtl8188eu_oid_rt_pro_set_data_rate_hdl\n"));
@@ -255,7 +244,6 @@ _func_enter_;
 	SetDataRate(Adapter);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -266,7 +254,6 @@ int rtl8188eu_oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_start_test_hdl\n"));
 
@@ -293,7 +280,6 @@ exit:
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("-rtl8188eu_oid_rt_pro_start_test_hdl: mp_mode=%d\n", Adapter->mppriv.mode));
 
-_func_exit_;
 
 	return status;
 }
@@ -303,7 +289,6 @@ int rtl8188eu_oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+Set OID_RT_PRO_STOP_TEST\n"));
 
@@ -316,7 +301,6 @@ _func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("-Set OID_RT_PRO_STOP_TEST\n"));
 
-_func_exit_;
 
 	return status;
 }
@@ -327,7 +311,6 @@ int rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_p
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl\n"));
 
@@ -352,7 +335,6 @@ _func_enter_;
 	SetChannel(Adapter);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -364,7 +346,6 @@ int rtl8188eu_oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_,
 		 ("+rtl8188eu_oid_rt_set_bandwidth_hdl\n"));
@@ -391,7 +372,6 @@ _func_enter_;
 		 ("-rtl8188eu_oid_rt_set_bandwidth_hdl: bandwidth=%d channel_offset=%d\n",
 		  bandwidth, channel_offset));
 
-_func_exit_;
 
 	return status;
 }
@@ -402,7 +382,6 @@ int rtl8188eu_oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_antenna_bb_hdl\n"));
 
@@ -426,7 +405,6 @@ _func_enter_;
 		*(u32 *)poid_par_priv->information_buf = antenna;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -437,7 +415,6 @@ int rtl8188eu_oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_pro_set_tx_power_control_hdl\n"));
 
@@ -461,7 +438,6 @@ _func_enter_;
 	SetTxPower(Adapter);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -474,7 +450,6 @@ int rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -488,7 +463,6 @@ _func_enter_;
 		status = NDIS_STATUS_INVALID_LENGTH;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -498,7 +472,6 @@ int rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -513,7 +486,6 @@ _func_enter_;
 		status = NDIS_STATUS_INVALID_LENGTH;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -523,7 +495,6 @@ int rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *po
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -538,7 +509,6 @@ _func_enter_;
 		status = NDIS_STATUS_INVALID_LENGTH;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -549,7 +519,6 @@ int rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -559,7 +528,6 @@ _func_enter_;
 	RT_TRACE(_module_mp_, _drv_alert_, ("===> rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl.\n"));
 	Adapter->mppriv.tx_pktcount = 0;
 
-_func_exit_;
 
 	return status;
 }
@@ -569,7 +537,6 @@ int rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -583,7 +550,6 @@ _func_enter_;
 		status = NDIS_STATUS_INVALID_LENGTH;
 	}
 
-_func_exit_;
 
 	return status;
 }
@@ -593,7 +559,6 @@ int rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -604,7 +569,6 @@ _func_enter_;
 	ResetPhyRxPktCount(Adapter);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -614,7 +578,6 @@ int rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_pa
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl\n"));
 
@@ -632,7 +595,6 @@ _func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("-rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl: recv_ok=%d\n", *(u32 *)poid_par_priv->information_buf));
 
-_func_exit_;
 
 	return status;
 }
@@ -642,7 +604,6 @@ int rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl\n"));
 
@@ -663,7 +624,6 @@ _func_enter_;
 		 ("-rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl: recv_err =%d\n",
 		 *(u32 *)poid_par_priv->information_buf));
 
-_func_exit_;
 
 	return status;
 }
@@ -674,7 +634,6 @@ int rtl8188eu_oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_pri
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_continuous_tx_hdl\n"));
 
@@ -698,7 +657,6 @@ _func_enter_;
 	}
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -709,7 +667,6 @@ int rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_alert_, ("+rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl\n"));
 
@@ -733,7 +690,6 @@ _func_enter_;
 	}
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -744,7 +700,6 @@ int rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poi
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl\n"));
 
@@ -768,7 +723,6 @@ _func_enter_;
 	}
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -779,7 +733,6 @@ int rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_pr
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_alert_, ("+rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl\n"));
 
@@ -792,7 +745,6 @@ _func_enter_;
 	SetSingleToneTx(Adapter, (u8)bStartTest);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -806,7 +758,6 @@ int rtl8188eu_oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv)
 {
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 	int status = NDIS_STATUS_SUCCESS;
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -815,7 +766,6 @@ _func_enter_;
 	rtw_hal_set_hwreg(Adapter, HW_VAR_TRIGGER_GPIO_0, NULL);
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -833,7 +783,6 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_,
 		 ("+rtl8188eu_oid_rt_pro_read_register_hdl\n"));
@@ -870,7 +819,6 @@ _func_enter_;
 
 	*poid_par_priv->bytes_rw = width;
 
-_func_exit_;
 
 	return status;
 }
@@ -882,7 +830,6 @@ int rtl8188eu_oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_,
 		 ("+rtl8188eu_oid_rt_pro_write_register_hdl\n"));
@@ -929,7 +876,6 @@ _func_enter_;
 		 ("-rtl8188eu_oid_rt_pro_write_register_hdl: offset=0x%08X width=%d value=0x%X\n",
 		  offset, width, value));
 
-_func_exit_;
 
 	return status;
 }
@@ -1002,7 +948,6 @@ int rtl8188eu_oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv
 
 	int status = NDIS_STATUS_SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+OID_RT_PRO_SET_DATA_RATE_EX\n"));
 
@@ -1016,7 +961,6 @@ _func_enter_;
 
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -1027,7 +971,6 @@ int rtl8188eu_oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
 	u8 thermal = 0;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_get_thermal_meter_hdl\n"));
 
@@ -1044,7 +987,6 @@ _func_enter_;
 	*(u32 *)poid_par_priv->information_buf = (u32)thermal;
 	*poid_par_priv->bytes_rw = sizeof(u32);
 
-_func_exit_;
 
 	return status;
 }
@@ -1060,7 +1002,6 @@ int rtl8188eu_oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_pr
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
 
-_func_enter_;
 
 	if (poid_par_priv->information_buf_len < sizeof(u8))
 		return NDIS_STATUS_INVALID_LENGTH;
@@ -1079,7 +1020,6 @@ _func_enter_;
 	}
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -1143,7 +1083,6 @@ int rtl8188eu_oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -1176,7 +1115,6 @@ _func_enter_;
 	}
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -1190,7 +1128,6 @@ int rtl8188eu_oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -1216,7 +1153,6 @@ _func_enter_;
 		status = NDIS_STATUS_FAILURE;
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
@@ -1227,7 +1163,6 @@ int rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	*poid_par_priv->bytes_rw = 0;
 
@@ -1267,7 +1202,6 @@ _func_enter_;
 	RT_TRACE(_module_mp_, _drv_info_,
 		 ("-rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl: status=0x%08X\n", status));
 
-_func_exit_;
 
 	return status;
 }
@@ -1279,7 +1213,6 @@ int rtl8188eu_oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_pr
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -1296,7 +1229,6 @@ _func_enter_;
 	} else {
 		status = NDIS_STATUS_FAILURE;
 	}
-_func_exit_;
 
 	return status;
 }
@@ -1306,7 +1238,6 @@ int rtl8188eu_oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -1321,7 +1252,6 @@ _func_enter_;
 		 ("-rtl8188eu_oid_rt_get_efuse_max_size_hdl: size=%d status=0x%08X\n",
 		  *(int *)poid_par_priv->information_buf, status));
 
-_func_exit_;
 
 	return status;
 }
@@ -1330,7 +1260,6 @@ int rtl8188eu_oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
 {
 	int status;
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_pro_efuse_hdl\n"));
 
@@ -1341,7 +1270,6 @@ _func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_info_, ("-rtl8188eu_oid_rt_pro_efuse_hdl: status=0x%08X\n", status));
 
-_func_exit_;
 
 	return status;
 }
@@ -1353,7 +1281,6 @@ int rtl8188eu_oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
 	u16	maplen = 0;
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_efuse_map_hdl\n"));
 
@@ -1398,7 +1325,6 @@ _func_enter_;
 	RT_TRACE(_module_mp_, _drv_info_,
 		 ("-rtl8188eu_oid_rt_pro_efuse_map_hdl: status=0x%08X\n", status));
 
-_func_exit_;
 
 	return status;
 }
@@ -1414,7 +1340,6 @@ int rtl8188eu_oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
 	u8		rx_pkt_type;
 	int status = NDIS_STATUS_SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_set_rx_packet_type_hdl\n"));
 
@@ -1427,7 +1352,6 @@ _func_enter_;
 	rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/* 4 */
 
 	RT_TRACE(_module_mp_, _drv_info_, ("rx_pkt_type: %x\n", rx_pkt_type));
-_func_exit_;
 
 	return status;
 }
@@ -1482,7 +1406,6 @@ int rtl8188eu_oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
 {
 	int status = NDIS_STATUS_SUCCESS;
 
-_func_enter_;
 
 	if (poid_par_priv->type_of_oid != SET_OID) {
 		status = NDIS_STATUS_NOT_ACCEPTED;
@@ -1497,7 +1420,6 @@ _func_enter_;
 	/* CALL  the power_down function */
 	_irqlevel_changed_(&oldirql, RAISE);
 
-_func_exit_;
 
 	return status;
 }
diff --git a/drivers/staging/rtl8188eu/core/rtw_p2p.c b/drivers/staging/rtl8188eu/core/rtw_p2p.c
index 6e8c06e840b3..9425c4991ccd 100644
--- a/drivers/staging/rtl8188eu/core/rtw_p2p.c
+++ b/drivers/staging/rtl8188eu/core/rtw_p2p.c
@@ -57,13 +57,13 @@ static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
 	phead = &pstapriv->asoc_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* look up sta asoc_queue */
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		psta = container_of(plist, struct sta_info, asoc_list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 
 		if (psta->is_p2p_device) {
@@ -824,7 +824,7 @@ u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint l
 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
 		p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);
 		if (p2pie) {
-			if ((p != NULL) && _rtw_memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid , 7)) {
+			if ((p != NULL) && !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 */
@@ -972,24 +972,24 @@ u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint le
 		u32	attr_contentlen = 0;
 
 		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
-			if (_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
-			    _rtw_memcmp(pwdinfo->p2p_group_ssid, groupid+ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
+			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_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
 					struct list_head *phead, *plist;
 
 					spin_lock_bh(&pstapriv->asoc_list_lock);
 					phead = &pstapriv->asoc_list;
-					plist = get_next(phead);
+					plist = phead->next;
 
 					/* look up sta asoc_queue */
 					while ((rtw_end_of_queue_search(phead, plist)) == false) {
-						psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+						psta = container_of(plist, struct sta_info, asoc_list);
 
-						plist = get_next(plist);
+						plist = plist->next;
 
 						if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
-						    _rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
+						    !memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
 							/* issue GO Discoverability Request */
 							issue_group_disc_req(pwdinfo, psta->hwaddr);
 							status = P2P_STATUS_SUCCESS;
@@ -1118,7 +1118,7 @@ u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe,
 		/*	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 (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
+		if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
 			rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
 			wps_devicepassword_id = be16_to_cpu(be_tmp);
 
@@ -1498,7 +1498,6 @@ static void find_phase_handler(struct adapter *padapter)
 	struct ndis_802_11_ssid	ssid;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	_rtw_memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
 	memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
@@ -1509,7 +1508,6 @@ _func_enter_;
         spin_lock_bh(&pmlmepriv->lock);
         rtw_sitesurvey_cmd(padapter, &ssid, 1, NULL, 0);
         spin_unlock_bh(&pmlmepriv->lock);
-_func_exit_;
 }
 
 void p2p_concurrent_handler(struct adapter *padapter);
@@ -1518,7 +1516,6 @@ static void restore_p2p_state_handler(struct adapter *padapter)
 {
 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
 
-_func_enter_;
 	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));
@@ -1528,54 +1525,46 @@ _func_enter_;
 		/*	because this P2P client should stay at the operating channel of P2P GO. */
 		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
 	}
-_func_exit_;
 }
 
 static void pre_tx_invitereq_handler(struct adapter *padapter)
 {
 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
 	u8	val8 = 1;
-_func_enter_;
 
 	set_channel_bwmode(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));
 	issue_probereq_p2p(padapter, NULL);
 	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
 
-_func_exit_;
 }
 
 static void pre_tx_provdisc_handler(struct adapter *padapter)
 {
 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
 	u8	val8 = 1;
-_func_enter_;
 
 	set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
 	issue_probereq_p2p(padapter, NULL);
 	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
 
-_func_exit_;
 }
 
 static void pre_tx_negoreq_handler(struct adapter *padapter)
 {
 	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
 	u8	val8 = 1;
-_func_enter_;
 
 	set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
 	issue_probereq_p2p(padapter, NULL);
 	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
 
-_func_exit_;
 }
 
 void p2p_protocol_wk_hdl(struct adapter *padapter, int intCmdType)
 {
-_func_enter_;
 	switch (intCmdType) {
 	case P2P_FIND_PHASE_WK:
 		find_phase_handler(padapter);
@@ -1594,7 +1583,6 @@ _func_enter_;
 		break;
 	}
 
-_func_exit_;
 }
 
 void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
@@ -1610,7 +1598,6 @@ void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
 	u8	find_p2p = false, find_p2p_ps = false;
 	u8	noa_offset, noa_num, noa_index;
 
-_func_enter_;
 
 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
 		return;
@@ -1683,7 +1670,6 @@ _func_enter_;
 			p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
 	}
 
-_func_exit_;
 }
 
 void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state)
@@ -1691,7 +1677,6 @@ void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state)
 	struct pwrctrl_priv		*pwrpriv = &padapter->pwrctrlpriv;
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
 
-_func_enter_;
 
 	/*  Pre action for p2p state */
 	switch (p2p_ps_state) {
@@ -1738,7 +1723,6 @@ _func_enter_;
 		break;
 	}
 
-_func_exit_;
 }
 
 u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
@@ -1749,7 +1733,6 @@ u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-_func_enter_;
 
 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
 		return res;
@@ -1781,7 +1764,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -2024,11 +2006,11 @@ int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role)
 
 		/* Disable P2P function */
 		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			_cancel_timer_ex(&pwdinfo->find_phase_timer);
-			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-			_cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
-			_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
-			_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
+			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(padapter);
 			reset_ch_sitesurvey_timer_process2(padapter);
 			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index b5db22cc81ed..f6583734aefa 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -226,11 +226,8 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
 	u8	rpwm;
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 
-_func_enter_;
-
 	pslv = PS_STATE(pslv);
 
-
 	if (pwrpriv->btcoex_rfon) {
 		if (pslv < PS_STATE_S4)
 			pslv = PS_STATE_S3;
@@ -274,8 +271,6 @@ _func_enter_;
 
 	pwrpriv->tog += 0x80;
 	pwrpriv->cpwm = pslv;
-
-_func_exit_;
 }
 
 static u8 PS_RDY_CHECK(struct adapter *padapter)
@@ -313,8 +308,6 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
 #endif /* CONFIG_88EU_P2P */
 
-_func_enter_;
-
 	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 		 ("%s: PowerMode=%d Smart_PS=%d\n",
 		  __func__, ps_mode, smart_ps));
@@ -362,8 +355,6 @@ _func_enter_;
 			rtw_set_rpwm(padapter, PS_STATE_S2);
 		}
 	}
-
-_func_exit_;
 }
 
 /*
@@ -410,8 +401,6 @@ void LPS_Enter(struct adapter *padapter)
 {
 	struct pwrctrl_priv	*pwrpriv = &padapter->pwrctrlpriv;
 
-_func_enter_;
-
 	if (PS_RDY_CHECK(padapter) == false)
 		return;
 
@@ -428,8 +417,6 @@ _func_enter_;
 			pwrpriv->LpsIdleCount++;
 		}
 	}
-
-_func_exit_;
 }
 
 #define LPS_LEAVE_TIMEOUT_MS 100
@@ -440,8 +427,6 @@ void LPS_Leave(struct adapter *padapter)
 {
 	struct pwrctrl_priv	*pwrpriv = &padapter->pwrctrlpriv;
 
-_func_enter_;
-
 	if (pwrpriv->bLeisurePs) {
 		if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
 			rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
@@ -452,8 +437,6 @@ _func_enter_;
 	}
 
 	pwrpriv->bpower_saving = false;
-
-_func_exit_;
 }
 
 /*  */
@@ -465,23 +448,17 @@ void LeaveAllPowerSaveMode(struct adapter *Adapter)
 	struct mlme_priv	*pmlmepriv = &(Adapter->mlmepriv);
 	u8	enqueue = 0;
 
-_func_enter_;
-
 	if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
 		p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
 
 		rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
 	}
-
-_func_exit_;
 }
 
 void rtw_init_pwrctrl_priv(struct adapter *padapter)
 {
 	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
 
-_func_enter_;
-
 	_init_pwrlock(&pwrctrlpriv->lock);
 	pwrctrlpriv->rf_pwrstate = rf_on;
 	pwrctrlpriv->ips_enter_cnts = 0;
@@ -518,8 +495,6 @@ _func_enter_;
 	pwrctrlpriv->btcoex_rfon = false;
 
 	_init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
-
-_func_exit_;
 }
 
 u8 rtw_interface_ps_func(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
@@ -540,7 +515,7 @@ inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
 /*
 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
 * @adapter: pointer to struct adapter structure
-* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
 * Return _SUCCESS or _FAIL
 */
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index c9c180649c12..636ec553ae83 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -23,11 +23,12 @@
 #include <drv_types.h>
 #include <recv_osdep.h>
 #include <mlme_osdep.h>
-#include <ip.h>
-#include <if_ether.h>
-#include <ethernet.h>
 #include <usb_ops.h>
 #include <wifi.h>
+#include <linux/vmalloc.h>
+
+#define ETHERNET_HEADER_SIZE	14	/*  Ethernet Header Length */
+#define LLC_HEADER_SIZE			6	/*  LLC Header Length */
 
 static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
 static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
@@ -45,7 +46,6 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS);
 
 void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
 {
-_func_enter_;
 
 	_rtw_memset((u8 *)psta_recvpriv, 0, sizeof (struct sta_recv_priv));
 
@@ -53,18 +53,16 @@ _func_enter_;
 
 	_rtw_init_queue(&psta_recvpriv->defrag_q);
 
-_func_exit_;
 }
 
 int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
 {
 	int i;
 
-	union recv_frame *precvframe;
+	struct recv_frame *precvframe;
 
 	int	res = _SUCCESS;
 
-_func_enter_;
 	spin_lock_init(&precvpriv->lock);
 
 	_rtw_init_queue(&precvpriv->free_recv_queue);
@@ -77,7 +75,7 @@ _func_enter_;
 
 	rtw_os_recv_resource_init(precvpriv, padapter);
 
-	precvpriv->pallocated_frame_buf = rtw_zvmalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+	precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ);
 
 	if (precvpriv->pallocated_frame_buf == NULL) {
 		res = _FAIL;
@@ -86,18 +84,19 @@ _func_enter_;
 
 	precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
 
-	precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
+	precvframe = (struct recv_frame *)precvpriv->precv_frame_buf;
 
 	for (i = 0; i < NR_RECVFRAME; i++) {
-		_rtw_init_listhead(&(precvframe->u.list));
+		_rtw_init_listhead(&(precvframe->list));
 
-		rtw_list_insert_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
+		rtw_list_insert_tail(&(precvframe->list),
+				     &(precvpriv->free_recv_queue.queue));
 
 		res = rtw_os_recv_resource_alloc(padapter, precvframe);
 
-		precvframe->u.hdr.len = 0;
+		precvframe->len = 0;
 
-		precvframe->u.hdr.adapter = padapter;
+		precvframe->adapter = padapter;
 		precvframe++;
 	}
 	precvpriv->rx_pending_cnt = 1;
@@ -113,7 +112,6 @@ _func_enter_;
 	rtw_set_signal_stat_timer(precvpriv);
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -122,40 +120,37 @@ void _rtw_free_recv_priv (struct recv_priv *precvpriv)
 {
 	struct adapter	*padapter = precvpriv->adapter;
 
-_func_enter_;
 
 	rtw_free_uc_swdec_pending_queue(padapter);
 
 	rtw_os_recv_resource_free(precvpriv);
 
 	if (precvpriv->pallocated_frame_buf) {
-		rtw_vmfree(precvpriv->pallocated_frame_buf, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+		vfree(precvpriv->pallocated_frame_buf);
 	}
 
 	rtw_hal_free_recv_priv(padapter);
 
-_func_exit_;
 }
 
-union recv_frame *_rtw_alloc_recvframe (struct __queue *pfree_recv_queue)
+struct recv_frame *_rtw_alloc_recvframe (struct __queue *pfree_recv_queue)
 {
-	union recv_frame  *precvframe;
+	struct recv_frame *hdr;
 	struct list_head *plist, *phead;
 	struct adapter *padapter;
 	struct recv_priv *precvpriv;
-_func_enter_;
 
 	if (_rtw_queue_empty(pfree_recv_queue)) {
-		precvframe = NULL;
+		hdr = NULL;
 	} else {
 		phead = get_list_head(pfree_recv_queue);
 
-		plist = get_next(phead);
+		plist = phead->next;
 
-		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+		hdr = container_of(plist, struct recv_frame, list);
 
-		rtw_list_delete(&precvframe->u.hdr.list);
-		padapter = precvframe->u.hdr.adapter;
+		rtw_list_delete(&hdr->list);
+		padapter = hdr->adapter;
 		if (padapter != NULL) {
 			precvpriv = &padapter->recvpriv;
 			if (pfree_recv_queue == &precvpriv->free_recv_queue)
@@ -163,14 +158,13 @@ _func_enter_;
 		}
 	}
 
-_func_exit_;
 
-	return precvframe;
+	return (struct recv_frame *)hdr;
 }
 
-union recv_frame *rtw_alloc_recvframe (struct __queue *pfree_recv_queue)
+struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
 {
-	union recv_frame  *precvframe;
+	struct recv_frame  *precvframe;
 
 	spin_lock_bh(&pfree_recv_queue->lock);
 
@@ -181,36 +175,36 @@ union recv_frame *rtw_alloc_recvframe (struct __queue *pfree_recv_queue)
 	return precvframe;
 }
 
-void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpriv)
+void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv)
 {
 	/* Perry: This can be removed */
-	_rtw_init_listhead(&precvframe->u.hdr.list);
+	_rtw_init_listhead(&precvframe->list);
 
-	precvframe->u.hdr.len = 0;
+	precvframe->len = 0;
 }
 
-int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue)
+int rtw_free_recvframe(struct recv_frame *precvframe,
+		       struct __queue *pfree_recv_queue)
 {
 	struct adapter *padapter;
 	struct recv_priv *precvpriv;
 
-_func_enter_;
 	if (!precvframe)
 		return _FAIL;
-	padapter = precvframe->u.hdr.adapter;
+	padapter = precvframe->adapter;
 	precvpriv = &padapter->recvpriv;
-	if (precvframe->u.hdr.pkt) {
-		dev_kfree_skb_any(precvframe->u.hdr.pkt);/* free skb by driver */
-		precvframe->u.hdr.pkt = NULL;
+	if (precvframe->pkt) {
+		dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
+		precvframe->pkt = NULL;
 	}
 
 	spin_lock_bh(&pfree_recv_queue->lock);
 
-	rtw_list_delete(&(precvframe->u.hdr.list));
+	rtw_list_delete(&(precvframe->list));
 
-	precvframe->u.hdr.len = 0;
+	precvframe->len = 0;
 
-	rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
+	rtw_list_insert_tail(&(precvframe->list), get_list_head(pfree_recv_queue));
 
 	if (padapter != NULL) {
 		if (pfree_recv_queue == &precvpriv->free_recv_queue)
@@ -219,32 +213,29 @@ _func_enter_;
 
       spin_unlock_bh(&pfree_recv_queue->lock);
 
-_func_exit_;
 
 	return _SUCCESS;
 }
 
-int _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
+int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
 {
-	struct adapter *padapter = precvframe->u.hdr.adapter;
+	struct adapter *padapter = precvframe->adapter;
 	struct recv_priv *precvpriv = &padapter->recvpriv;
 
-_func_enter_;
 
-	rtw_list_delete(&(precvframe->u.hdr.list));
-	rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(queue));
+	rtw_list_delete(&(precvframe->list));
+	rtw_list_insert_tail(&(precvframe->list), get_list_head(queue));
 
 	if (padapter != NULL) {
 		if (queue == &precvpriv->free_recv_queue)
 			precvpriv->free_recvframe_cnt++;
 	}
 
-_func_exit_;
 
 	return _SUCCESS;
 }
 
-int rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
+int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
 {
 	int ret;
 
@@ -265,32 +256,30 @@ using spinlock to protect
 
 void rtw_free_recvframe_queue(struct __queue *pframequeue,  struct __queue *pfree_recv_queue)
 {
-	union	recv_frame	*precvframe;
+	struct recv_frame *hdr;
 	struct list_head *plist, *phead;
 
-_func_enter_;
 	spin_lock(&pframequeue->lock);
 
 	phead = get_list_head(pframequeue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (rtw_end_of_queue_search(phead, plist) == false) {
-		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+		hdr = container_of(plist, struct recv_frame, list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
-		rtw_free_recvframe(precvframe, pfree_recv_queue);
+		rtw_free_recvframe((struct recv_frame *)hdr, pfree_recv_queue);
 	}
 
 	spin_unlock(&pframequeue->lock);
 
-_func_exit_;
 }
 
 u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter)
 {
 	u32 cnt = 0;
-	union recv_frame *pending_frame;
+	struct recv_frame *pending_frame;
 	while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
 		rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
 		DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__);
@@ -337,9 +326,9 @@ struct recv_buf *rtw_dequeue_recvbuf (struct __queue *queue)
 	} else {
 		phead = get_list_head(queue);
 
-		plist = get_next(phead);
+		plist = phead->next;
 
-		precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);
+		precvbuf = container_of(plist, struct recv_buf, list);
 
 		rtw_list_delete(&precvbuf->list);
 	}
@@ -349,7 +338,8 @@ struct recv_buf *rtw_dequeue_recvbuf (struct __queue *queue)
 	return precvbuf;
 }
 
-static int recvframe_chkmic(struct adapter *adapter,  union recv_frame *precvframe)
+static int recvframe_chkmic(struct adapter *adapter,
+			    struct recv_frame *precvframe)
 {
 	int	i, res = _SUCCESS;
 	u32	datalen;
@@ -358,12 +348,11 @@ static int recvframe_chkmic(struct adapter *adapter,  union recv_frame *precvfra
 	u8	*pframe, *payload, *pframemic;
 	u8	*mickey;
 	struct	sta_info		*stainfo;
-	struct	rx_pkt_attrib	*prxattrib = &precvframe->u.hdr.attrib;
+	struct	rx_pkt_attrib	*prxattrib = &precvframe->attrib;
 	struct	security_priv	*psecuritypriv = &adapter->securitypriv;
 
 	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-_func_enter_;
 
 	stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
 
@@ -375,23 +364,24 @@ _func_enter_;
 		/* calculate mic code */
 		if (stainfo != NULL) {
 			if (IS_MCAST(prxattrib->ra)) {
-				mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
-
-				RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic: bcmc key\n"));
-
 				if (!psecuritypriv) {
 					res = _FAIL;
 					RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n"));
 					DBG_88E("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");
 					goto exit;
 				}
+				mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
+
+				RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic: bcmc key\n"));
 			} else {
 				mickey = &stainfo->dot11tkiprxmickey.skey[0];
 				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic: unicast key\n"));
 			}
 
-			datalen = precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;/* icv_len included the mic code */
-			pframe = precvframe->u.hdr.rx_data;
+			/* icv_len included the mic code */
+			datalen = precvframe->len-prxattrib->hdrlen -
+				  prxattrib->iv_len-prxattrib->icv_len-8;
+			pframe = precvframe->rx_data;
 			payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
 
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len));
@@ -424,16 +414,30 @@ _func_enter_;
 					 *(pframemic-10), *(pframemic-9)));
 				{
 					uint i;
-					RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ======demp packet (len=%d)======\n", precvframe->u.hdr.len));
-					for (i = 0; i < precvframe->u.hdr.len; i = i+8) {
-						RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
-							 *(precvframe->u.hdr.rx_data+i), *(precvframe->u.hdr.rx_data+i+1),
-							 *(precvframe->u.hdr.rx_data+i+2), *(precvframe->u.hdr.rx_data+i+3),
-							 *(precvframe->u.hdr.rx_data+i+4), *(precvframe->u.hdr.rx_data+i+5),
-							 *(precvframe->u.hdr.rx_data+i+6), *(precvframe->u.hdr.rx_data+i+7)));
+					RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+						 ("\n ======demp packet (len=%d)======\n",
+						 precvframe->len));
+					for (i = 0; i < precvframe->len; i += 8) {
+						RT_TRACE(_module_rtl871x_recv_c_,
+							 _drv_err_,
+							 ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
+							 *(precvframe->rx_data+i),
+							 *(precvframe->rx_data+i+1),
+							 *(precvframe->rx_data+i+2),
+							 *(precvframe->rx_data+i+3),
+							 *(precvframe->rx_data+i+4),
+							 *(precvframe->rx_data+i+5),
+							 *(precvframe->rx_data+i+6),
+							 *(precvframe->rx_data+i+7)));
 					}
-					RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ====== demp packet end [len=%d]======\n", precvframe->u.hdr.len));
-					RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n hrdlen=%d,\n", prxattrib->hdrlen));
+					RT_TRACE(_module_rtl871x_recv_c_,
+						 _drv_err_,
+						 ("\n ====== demp packet end [len=%d]======\n",
+						 precvframe->len));
+					RT_TRACE(_module_rtl871x_recv_c_,
+						 _drv_err_,
+						 ("\n hrdlen=%d,\n",
+						 prxattrib->hdrlen));
 				}
 
 				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
@@ -471,24 +475,23 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
 
 /* decrypt and set the ivlen, icvlen of the recv_frame */
-static union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame)
+static struct recv_frame *decryptor(struct adapter *padapter,
+				    struct recv_frame *precv_frame)
 {
-	struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
+	struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
-	union recv_frame *return_packet = precv_frame;
+	struct recv_frame *return_packet = precv_frame;
 	u32	 res = _SUCCESS;
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("prxstat->decrypted=%x prxattrib->encrypt=0x%03x\n", prxattrib->bdecrypted, prxattrib->encrypt));
 
 	if (prxattrib->encrypt > 0) {
-		u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen;
+		u8 *iv = precv_frame->rx_data+prxattrib->hdrlen;
 		prxattrib->key_index = (((iv[3])>>6)&0x3);
 
 		if (prxattrib->key_index > WEP_KEYS) {
@@ -534,34 +537,33 @@ _func_enter_;
 		return_packet = NULL;
 	}
 
-_func_exit_;
 
 	return return_packet;
 }
 
 /* set the security information in the recv_frame */
-static union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame)
+static struct recv_frame *portctrl(struct adapter *adapter,
+				   struct recv_frame *precv_frame)
 {
 	u8   *psta_addr = NULL, *ptr;
 	uint  auth_alg;
-	struct recv_frame_hdr *pfhdr;
+	struct recv_frame *pfhdr;
 	struct sta_info *psta;
 	struct sta_priv *pstapriv;
-	union recv_frame *prtnframe;
+	struct recv_frame *prtnframe;
 	u16	ether_type = 0;
 	u16  eapol_type = 0x888e;/* for Funia BD's WPA issue */
 	struct rx_pkt_attrib *pattrib;
 	__be16 be_tmp;
 
-_func_enter_;
 
 	pstapriv = &adapter->stapriv;
 	psta = rtw_get_stainfo(pstapriv, psta_addr);
 
 	auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
 
-	ptr = get_recvframe_data(precv_frame);
-	pfhdr = &precv_frame->u.hdr;
+	ptr = precv_frame->rx_data;
+	pfhdr = precv_frame;
 	pattrib = &pfhdr->attrib;
 	psta_addr = pattrib->ta;
 
@@ -593,7 +595,9 @@ _func_enter_;
 			/* allowed */
 			/* check decryption status, and decrypt the frame if needed */
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==0\n"));
-			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:precv_frame->hdr.attrib.privacy=%x\n", precv_frame->u.hdr.attrib.privacy));
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+				 ("portctrl:precv_frame->hdr.attrib.privacy=%x\n",
+				 precv_frame->attrib.privacy));
 
 			if (pattrib->bdecrypted == 0)
 				RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:prxstat->decrypted=%x\n", pattrib->bdecrypted));
@@ -613,19 +617,18 @@ _func_enter_;
 		prtnframe = precv_frame;
 	}
 
-_func_exit_;
 
 		return prtnframe;
 }
 
-static int recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache)
+static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
+			struct stainfo_rxcache *prxcache)
 {
-	int tid = precv_frame->u.hdr.attrib.priority;
+	int tid = precv_frame->attrib.priority;
 
-	u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
-		(precv_frame->u.hdr.attrib.frag_num & 0xf);
+	u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) |
+		(precv_frame->attrib.frag_num & 0xf);
 
-_func_enter_;
 
 	if (tid > 15) {
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid));
@@ -643,18 +646,17 @@ _func_enter_;
 
 	prxcache->tid_rxseq[tid] = seq_ctrl;
 
-_func_exit_;
 
 	return _SUCCESS;
 }
 
-void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame);
-void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame)
+void process_pwrbit_data(struct adapter *padapter,
+			 struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_AP_MODE
 	unsigned char pwrbit;
-	u8 *ptr = precv_frame->u.hdr.rx_data;
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	u8 *ptr = precv_frame->rx_data;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	struct sta_info *psta = NULL;
 
@@ -675,10 +677,11 @@ void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame
 #endif
 }
 
-static void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame)
+static void process_wmmps_data(struct adapter *padapter,
+			       struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_AP_MODE
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	struct sta_info *psta = NULL;
 
@@ -730,15 +733,17 @@ static void process_wmmps_data(struct adapter *padapter, union recv_frame *precv
 #endif
 }
 
-static void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta)
+static void count_rx_stats(struct adapter *padapter,
+			   struct recv_frame *prframe,
+			   struct sta_info *sta)
 {
 	int	sz;
 	struct sta_info		*psta = NULL;
 	struct stainfo_stats	*pstats = NULL;
-	struct rx_pkt_attrib	*pattrib = &prframe->u.hdr.attrib;
+	struct rx_pkt_attrib	*pattrib = &prframe->attrib;
 	struct recv_priv	*precvpriv = &padapter->recvpriv;
 
-	sz = get_recvframe_len(prframe);
+	sz = prframe->len;
 	precvpriv->rx_bytes += sz;
 
 	padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
@@ -749,7 +754,7 @@ static void count_rx_stats(struct adapter *padapter, union recv_frame *prframe,
 	if (sta)
 		psta = sta;
 	else
-		psta = prframe->u.hdr.psta;
+		psta = prframe->psta;
 
 	if (psta) {
 		pstats = &psta->sta_stats;
@@ -761,15 +766,16 @@ static void count_rx_stats(struct adapter *padapter, union recv_frame *prframe,
 
 int sta2sta_data_frame(
 	struct adapter *adapter,
-	union recv_frame *precv_frame,
+	struct recv_frame *precv_frame,
 	struct sta_info **psta
 );
 
-int sta2sta_data_frame(struct adapter *adapter, union recv_frame *precv_frame, struct sta_info **psta)
+int sta2sta_data_frame(struct adapter *adapter, struct recv_frame *precv_frame,
+		       struct sta_info **psta)
 {
-	u8 *ptr = precv_frame->u.hdr.rx_data;
+	u8 *ptr = precv_frame->rx_data;
 	int ret = _SUCCESS;
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	u8 *mybssid  = get_bssid(pmlmepriv);
@@ -777,25 +783,24 @@ int sta2sta_data_frame(struct adapter *adapter, union recv_frame *precv_frame, s
 	u8 *sta_addr = NULL;
 	int bmcast = IS_MCAST(pattrib->dst);
 
-_func_enter_;
 
 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
 	    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
 		/*  filter packets that SA is myself or multicast or broadcast */
-		if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
+		if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n"));
 			ret = _FAIL;
 			goto exit;
 		}
 
-		if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN))	&& (!bmcast)) {
+		if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
 			ret = _FAIL;
 			goto exit;
 		}
 
-		if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-		    _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-		    !_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
+		if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		    !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		    memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
 			ret = _FAIL;
 			goto exit;
 		}
@@ -803,7 +808,7 @@ _func_enter_;
 		sta_addr = pattrib->src;
 	} else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 		/*  For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */
-		if (!_rtw_memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {
+		if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("bssid!=TA under STATION_MODE; drop pkt\n"));
 			ret = _FAIL;
 			goto exit;
@@ -818,7 +823,7 @@ _func_enter_;
 			}
 		} else { /*  not mc-frame */
 			/*  For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
-			if (!_rtw_memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
+			if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
 				ret = _FAIL;
 				goto exit;
 			}
@@ -853,17 +858,16 @@ _func_enter_;
 	}
 
 exit:
-_func_exit_;
 	return ret;
 }
 
 static int ap2sta_data_frame (
 	struct adapter *adapter,
-	union recv_frame *precv_frame,
+	struct recv_frame *precv_frame,
 	struct sta_info **psta)
 {
-	u8 *ptr = precv_frame->u.hdr.rx_data;
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	u8 *ptr = precv_frame->rx_data;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	int ret = _SUCCESS;
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -871,20 +875,19 @@ static int ap2sta_data_frame (
 	u8 *myhwaddr = myid(&adapter->eeprompriv);
 	int bmcast = IS_MCAST(pattrib->dst);
 
-_func_enter_;
 
 	if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) &&
 	    (check_fwstate(pmlmepriv, _FW_LINKED) == true ||
 	    check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
 		/*  filter packets that SA is myself or multicast or broadcast */
-		if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
+		if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n"));
 			ret = _FAIL;
 			goto exit;
 		}
 
 		/*  da should be for me */
-		if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
+		if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 				 (" ap2sta_data_frame:  compare DA fail; DA=%pM\n", (pattrib->dst)));
 			ret = _FAIL;
@@ -892,9 +895,9 @@ _func_enter_;
 		}
 
 		/*  check BSSID */
-		if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-		    _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-		     (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
+		if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		    !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		     (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 				 (" ap2sta_data_frame:  compare BSSID fail ; BSSID=%pM\n", (pattrib->bssid)));
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("mybssid=%pM\n", (mybssid)));
@@ -950,7 +953,7 @@ _func_enter_;
 		ret = RTW_RX_HANDLED;
 		goto exit;
 	} else {
-		if (_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
+		if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
 			*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /*  get sta_info */
 			if (*psta == NULL) {
 				DBG_88E("issue_deauth to the ap =%pM for the reason(7)\n", (pattrib->bssid));
@@ -964,27 +967,25 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
 
 static int sta2ap_data_frame(struct adapter *adapter,
-			     union recv_frame *precv_frame,
+			     struct recv_frame *precv_frame,
 			     struct sta_info **psta)
 {
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	u8 *ptr = precv_frame->u.hdr.rx_data;
+	u8 *ptr = precv_frame->rx_data;
 	unsigned char *mybssid  = get_bssid(pmlmepriv);
 	int ret = _SUCCESS;
 
-_func_enter_;
 
 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
 		/* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
-		if (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
+		if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
 			ret = _FAIL;
 			goto exit;
 		}
@@ -1014,7 +1015,7 @@ _func_enter_;
 		}
 	} else {
 		u8 *myhwaddr = myid(&adapter->eeprompriv);
-		if (!_rtw_memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
+		if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
 			ret = RTW_RX_HANDLED;
 			goto exit;
 		}
@@ -1026,25 +1027,23 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
 
 static int validate_recv_ctrl_frame(struct adapter *padapter,
-				    union recv_frame *precv_frame)
+				    struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_88EU_AP_MODE
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 	struct sta_priv *pstapriv = &padapter->stapriv;
-	u8 *pframe = precv_frame->u.hdr.rx_data;
-	/* uint len = precv_frame->u.hdr.len; */
+	u8 *pframe = precv_frame->rx_data;
 
 	if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
 		return _FAIL;
 
 	/* receive the frames that ra(a1) is my address */
-	if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN))
+	if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN))
 		return _FAIL;
 
 	/* only handle ps-poll */
@@ -1098,12 +1097,12 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
 			spin_lock_bh(&psta->sleep_q.lock);
 
 			xmitframe_phead = get_list_head(&psta->sleep_q);
-			xmitframe_plist = get_next(xmitframe_phead);
+			xmitframe_plist = xmitframe_phead->next;
 
 			if ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false) {
-				pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+				pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-				xmitframe_plist = get_next(xmitframe_plist);
+				xmitframe_plist = xmitframe_plist->next;
 
 				rtw_list_delete(&pxmitframe->list);
 
@@ -1124,7 +1123,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
 				if (psta->sleepq_len == 0) {
 					pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
@@ -1142,7 +1141,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
 
 					pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
@@ -1157,10 +1156,11 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
 	return _FAIL;
 }
 
-union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame);
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
+					struct recv_frame *precv_frame);
 
 static int validate_recv_mgnt_frame(struct adapter *padapter,
-				    union recv_frame *precv_frame)
+				    struct recv_frame *precv_frame)
 {
 	struct sta_info *psta;
 
@@ -1173,18 +1173,20 @@ static int validate_recv_mgnt_frame(struct adapter *padapter,
 	}
 
 	/* for rx pkt statistics */
-	psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data));
+	psta = rtw_get_stainfo(&padapter->stapriv,
+			       GetAddr2Ptr(precv_frame->rx_data));
 	if (psta) {
 		psta->sta_stats.rx_mgnt_pkts++;
-		if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON) {
+		if (GetFrameSubType(precv_frame->rx_data) == WIFI_BEACON) {
 			psta->sta_stats.rx_beacon_pkts++;
-		} else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ) {
+		} else if (GetFrameSubType(precv_frame->rx_data) == WIFI_PROBEREQ) {
 			psta->sta_stats.rx_probereq_pkts++;
-		} else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) {
-			if (_rtw_memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN) == true)
+		} else if (GetFrameSubType(precv_frame->rx_data) == WIFI_PROBERSP) {
+			if (!memcmp(padapter->eeprompriv.mac_addr,
+				    GetAddr1Ptr(precv_frame->rx_data), ETH_ALEN))
 				psta->sta_stats.rx_probersp_pkts++;
-			else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)) ||
-				 is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)))
+			else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->rx_data)) ||
+				 is_multicast_mac_addr(GetAddr1Ptr(precv_frame->rx_data)))
 				psta->sta_stats.rx_probersp_bm_pkts++;
 			else
 				psta->sta_stats.rx_probersp_uo_pkts++;
@@ -1197,17 +1199,16 @@ static int validate_recv_mgnt_frame(struct adapter *padapter,
 }
 
 static int validate_recv_data_frame(struct adapter *adapter,
-				    union recv_frame *precv_frame)
+				    struct recv_frame *precv_frame)
 {
 	u8 bretry;
 	u8 *psa, *pda, *pbssid;
 	struct sta_info *psta = NULL;
-	u8 *ptr = precv_frame->u.hdr.rx_data;
-	struct rx_pkt_attrib	*pattrib = &precv_frame->u.hdr.attrib;
+	u8 *ptr = precv_frame->rx_data;
+	struct rx_pkt_attrib	*pattrib = &precv_frame->attrib;
 	struct security_priv	*psecuritypriv = &adapter->securitypriv;
 	int ret = _SUCCESS;
 
-_func_enter_;
 
 	bretry = GetRetry(ptr);
 	pda = get_da(ptr);
@@ -1265,7 +1266,7 @@ _func_enter_;
 
 	/* psta->rssi = prxcmd->rssi; */
 	/* psta->signal_quality = prxcmd->sq; */
-	precv_frame->u.hdr.psta = psta;
+	precv_frame->psta = psta;
 
 	pattrib->amsdu = 0;
 	pattrib->ack_policy = 0;
@@ -1286,7 +1287,7 @@ _func_enter_;
 	if (pattrib->order)/* HT-CTRL 11n */
 		pattrib->hdrlen += 4;
 
-	precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
+	precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
 
 	/*  decache, drop duplicate recv packets */
 	if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) {
@@ -1312,12 +1313,12 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
 
-static int validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame)
+static int validate_recv_frame(struct adapter *adapter,
+			       struct recv_frame *precv_frame)
 {
 	/* shall check frame subtype, to / from ds, da, bssid */
 
@@ -1327,12 +1328,11 @@ static int validate_recv_frame(struct adapter *adapter, union recv_frame *precv_
 	u8 subtype;
 	int retval = _SUCCESS;
 	u8 bDumpRxPkt;
-	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+	u8 *ptr = precv_frame->rx_data;
 	u8  ver = (unsigned char) (*ptr)&0x3;
 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
 
-_func_enter_;
 
 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 		int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
@@ -1422,14 +1422,13 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return retval;
 }
 
 /* remove the wlanhdr and add the eth_hdr */
 
-static int wlanhdr_to_ethhdr (union recv_frame *precvframe)
+static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
 {
 	int	rmv_len;
 	u16	eth_type, len;
@@ -1439,13 +1438,10 @@ static int wlanhdr_to_ethhdr (union recv_frame *precvframe)
 	struct ieee80211_snap_hdr	*psnap;
 
 	int ret = _SUCCESS;
-	struct adapter			*adapter = precvframe->u.hdr.adapter;
+	struct adapter		*adapter = precvframe->adapter;
 	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
-
-	u8	*ptr = get_recvframe_data(precvframe); /*  point to frame_ctrl field */
-	struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
-
-_func_enter_;
+	u8 *ptr = precvframe->rx_data;
+	struct rx_pkt_attrib *pattrib = &precvframe->attrib;
 
 	if (pattrib->encrypt)
 		recvframe_pull_tail(precvframe, pattrib->icv_len);
@@ -1453,10 +1449,10 @@ _func_enter_;
 	psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
 	psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
 	/* convert hdr + possible LLC headers into Ethernet header */
-	if ((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
-	     (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
-	     (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2) == false)) ||
-	    _rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {
+	if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
+	     (!memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
+	     (!memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2) == false)) ||
+	     !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {
 		/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
 		bsnaphdr = true;
 	} else {
@@ -1465,7 +1461,7 @@ _func_enter_;
 	}
 
 	rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
-	len = precvframe->u.hdr.len - rmv_len;
+	len = precvframe->len - rmv_len;
 
 	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 		 ("\n===pattrib->hdrlen: %x,  pattrib->iv_len:%x===\n\n", pattrib->hdrlen,  pattrib->iv_len));
@@ -1496,30 +1492,29 @@ _func_enter_;
 		memcpy(ptr+12, &be_tmp, 2);
 	}
 
-_func_exit_;
 	return ret;
 }
 
 /* perform defrag */
-static union recv_frame *recvframe_defrag(struct adapter *adapter, struct __queue *defrag_q)
+static struct recv_frame *recvframe_defrag(struct adapter *adapter,
+					   struct __queue *defrag_q)
 {
 	struct list_head *plist, *phead;
 	u8 wlanhdr_offset;
 	u8	curfragnum;
-	struct recv_frame_hdr *pfhdr, *pnfhdr;
-	union recv_frame *prframe, *pnextrframe;
+	struct recv_frame *pfhdr, *pnfhdr;
+	struct recv_frame *prframe, *pnextrframe;
 	struct __queue *pfree_recv_queue;
 
-_func_enter_;
 
 	curfragnum = 0;
 	pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
 
 	phead = get_list_head(defrag_q);
-	plist = get_next(phead);
-	prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-	pfhdr = &prframe->u.hdr;
-	rtw_list_delete(&(prframe->u.list));
+	plist = phead->next;
+	pfhdr = container_of(plist, struct recv_frame, list);
+	prframe = (struct recv_frame *)pfhdr;
+	rtw_list_delete(&(prframe->list));
 
 	if (curfragnum != pfhdr->attrib.frag_num) {
 		/* the first fragment number must be 0 */
@@ -1534,11 +1529,11 @@ _func_enter_;
 
 	plist = get_list_head(defrag_q);
 
-	plist = get_next(plist);
+	plist = plist->next;
 
 	while (rtw_end_of_queue_search(phead, plist) == false) {
-		pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u);
-		pnfhdr = &pnextrframe->u.hdr;
+		pnfhdr = container_of(plist, struct recv_frame, list);
+		pnextrframe = (struct recv_frame *)pnfhdr;
 
 		/* check the fragment sequence  (2nd ~n fragment frame) */
 
@@ -1568,7 +1563,7 @@ _func_enter_;
 		recvframe_put(prframe, pnfhdr->len);
 
 		pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	/* free the defrag_q queue and return the prframe */
@@ -1576,29 +1571,28 @@ _func_enter_;
 
 	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
 
-_func_exit_;
 
 	return prframe;
 }
 
 /* check if need to defrag, if needed queue the frame to defrag_q */
-union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame)
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
+					struct recv_frame *precv_frame)
 {
 	u8	ismfrag;
 	u8	fragnum;
 	u8	*psta_addr;
-	struct recv_frame_hdr *pfhdr;
+	struct recv_frame *pfhdr;
 	struct sta_info *psta;
 	struct sta_priv *pstapriv;
 	struct list_head *phead;
-	union recv_frame *prtnframe = NULL;
+	struct recv_frame *prtnframe = NULL;
 	struct __queue *pfree_recv_queue, *pdefrag_q;
 
-_func_enter_;
 
 	pstapriv = &padapter->stapriv;
 
-	pfhdr = &precv_frame->u.hdr;
+	pfhdr = precv_frame;
 
 	pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
 
@@ -1670,7 +1664,7 @@ _func_enter_;
 		}
 	}
 
-	if ((prtnframe != NULL) && (prtnframe->u.hdr.attrib.privacy)) {
+	if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) {
 		/* after defrag we must check tkip mic code */
 		if (recvframe_chkmic(padapter,  prtnframe) == _FAIL) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter,  prtnframe)==_FAIL\n"));
@@ -1679,12 +1673,11 @@ _func_enter_;
 		}
 	}
 
-_func_exit_;
 
 	return prtnframe;
 }
 
-static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
+static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
 {
 	int	a_len, padding_len;
 	u16	eth_type, nSubframe_Length;
@@ -1698,16 +1691,16 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
 	int	ret = _SUCCESS;
 	nr_subframes = 0;
 
-	pattrib = &prframe->u.hdr.attrib;
+	pattrib = &prframe->attrib;
 
-	recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
+	recvframe_pull(prframe, prframe->attrib.hdrlen);
 
-	if (prframe->u.hdr.attrib.iv_len > 0)
-		recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
+	if (prframe->attrib.iv_len > 0)
+		recvframe_pull(prframe, prframe->attrib.iv_len);
 
-	a_len = prframe->u.hdr.len;
+	a_len = prframe->len;
 
-	pdata = prframe->u.hdr.rx_data;
+	pdata = prframe->rx_data;
 
 	while (a_len > ETH_HLEN) {
 		/* Offset 12 denote 2 mac address */
@@ -1729,7 +1722,7 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
 			data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
 			memcpy(data_ptr, pdata, nSubframe_Length);
 		} else {
-			sub_skb = skb_clone(prframe->u.hdr.pkt, GFP_ATOMIC);
+			sub_skb = skb_clone(prframe->pkt, GFP_ATOMIC);
 			if (sub_skb) {
 				sub_skb->data = pdata;
 				sub_skb->len = nSubframe_Length;
@@ -1768,9 +1761,9 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
 		/* convert hdr + possible LLC headers into Ethernet header */
 		eth_type = RTW_GET_BE16(&sub_skb->data[6]);
 		if (sub_skb->len >= 8 &&
-		    ((_rtw_memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
+		    ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
 			  eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
-			 _rtw_memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) {
+			 !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) {
 			/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
 			skb_pull(sub_skb, SNAP_SIZE);
 			memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
@@ -1796,7 +1789,7 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
 
 exit:
 
-	prframe->u.hdr.len = 0;
+	prframe->len = 0;
 	rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
 
 	return ret;
@@ -1832,70 +1825,72 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_n
 	return true;
 }
 
-int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe);
-int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe)
+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
+			      struct recv_frame *prframe)
 {
-	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &prframe->attrib;
 	struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
 	struct list_head *phead, *plist;
-	union recv_frame *pnextrframe;
+	struct recv_frame *hdr;
 	struct rx_pkt_attrib *pnextattrib;
 
 	phead = get_list_head(ppending_recvframe_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (rtw_end_of_queue_search(phead, plist) == false) {
-		pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
-		pnextattrib = &pnextrframe->u.hdr.attrib;
+		hdr = container_of(plist, struct recv_frame, list);
+		pnextattrib = &hdr->attrib;
 
 		if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
-			plist = get_next(plist);
+			plist = plist->next;
 		else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
 			return false;
 		else
 			break;
 	}
 
-	rtw_list_delete(&(prframe->u.hdr.list));
+	rtw_list_delete(&(prframe->list));
 
-	rtw_list_insert_tail(&(prframe->u.hdr.list), plist);
+	rtw_list_insert_tail(&(prframe->list), plist);
 	return true;
 }
 
 static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)
 {
 	struct list_head *phead, *plist;
-	union recv_frame *prframe;
+	struct recv_frame *prframe;
+	struct recv_frame *prhdr;
 	struct rx_pkt_attrib *pattrib;
 	int bPktInBuf = false;
 	struct recv_priv *precvpriv = &padapter->recvpriv;
 	struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
 
 	phead =		get_list_head(ppending_recvframe_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/*  Handling some condition for forced indicate case. */
 	if (bforced) {
 		if (rtw_is_list_empty(phead))
 			return true;
 
-		prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-		pattrib = &prframe->u.hdr.attrib;
+		prhdr = container_of(plist, struct recv_frame, list);
+	        pattrib = &prhdr->attrib;
 		preorder_ctrl->indicate_seq = pattrib->seq_num;
 	}
 
 	/*  Prepare indication list and indication. */
 	/*  Check if there is any packet need indicate. */
 	while (!rtw_is_list_empty(phead)) {
-		prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-		pattrib = &prframe->u.hdr.attrib;
+		prhdr = container_of(plist, struct recv_frame, list);
+		prframe = (struct recv_frame *)prhdr;
+		pattrib = &prframe->attrib;
 
 		if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
 				 ("recv_indicatepkts_in_order: indicate=%d seq=%d amsdu=%d\n",
 				  preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
-			plist = get_next(plist);
-			rtw_list_delete(&(prframe->u.hdr.list));
+			plist = plist->next;
+			rtw_list_delete(&(prframe->list));
 
 			if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num))
 				preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
@@ -1924,11 +1919,12 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor
 	return bPktInBuf;
 }
 
-static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe)
+static int recv_indicatepkt_reorder(struct adapter *padapter,
+				    struct recv_frame *prframe)
 {
 	int retval = _SUCCESS;
-	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-	struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
+	struct rx_pkt_attrib *pattrib = &prframe->attrib;
+	struct recv_reorder_ctrl *preorder_ctrl = prframe->preorder_ctrl;
 	struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
 
 	if (!pattrib->amsdu) {
@@ -2001,7 +1997,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *
 		spin_unlock_bh(&ppending_recvframe_queue->lock);
 	} else {
 		spin_unlock_bh(&ppending_recvframe_queue->lock);
-		_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 	}
 
 _success_exit:
@@ -2032,17 +2028,14 @@ void rtw_reordering_ctrl_timeout_handler(void *pcontext)
 	spin_unlock_bh(&ppending_recvframe_queue->lock);
 }
 
-static int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe)
+static int process_recv_indicatepkts(struct adapter *padapter,
+				     struct recv_frame *prframe)
 {
 	int retval = _SUCCESS;
-	/* struct recv_priv *precvpriv = &padapter->recvpriv; */
-	/* struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; */
 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
 	struct ht_priv	*phtpriv = &pmlmepriv->htpriv;
 
 	if (phtpriv->ht_option) {  /* B/G/N Mode */
-		/* prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
-
 		if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
 			/*  including perform A-MPDU Rx Ordering Buffer Control */
 			if ((!padapter->bDriverStopped) &&
@@ -2075,10 +2068,11 @@ static int process_recv_indicatepkts(struct adapter *padapter, union recv_frame
 	return retval;
 }
 
-static int recv_func_prehandle(struct adapter *padapter, union recv_frame *rframe)
+static int recv_func_prehandle(struct adapter *padapter,
+			       struct recv_frame *rframe)
 {
 	int ret = _SUCCESS;
-	struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &rframe->attrib;
 	struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
@@ -2110,10 +2104,11 @@ exit:
 	return ret;
 }
 
-static int recv_func_posthandle(struct adapter *padapter, union recv_frame *prframe)
+static int recv_func_posthandle(struct adapter *padapter,
+				struct recv_frame *prframe)
 {
 	int ret = _SUCCESS;
-	union recv_frame *orig_prframe = prframe;
+	struct recv_frame *orig_prframe = prframe;
 	struct recv_priv *precvpriv = &padapter->recvpriv;
 	struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
 
@@ -2155,16 +2150,16 @@ _recv_data_drop:
 	return ret;
 }
 
-static int recv_func(struct adapter *padapter, union recv_frame *rframe)
+static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
 {
 	int ret;
-	struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib;
+	struct rx_pkt_attrib *prxattrib = &rframe->attrib;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
 
 	/* check if need to handle uc_swdec_pending_queue*/
 	if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
-		union recv_frame *pending_frame;
+		struct recv_frame *pending_frame;
 
 		while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
 			if (recv_func_posthandle(padapter, pending_frame) == _SUCCESS)
@@ -2193,15 +2188,14 @@ exit:
 	return ret;
 }
 
-s32 rtw_recv_entry(union recv_frame *precvframe)
+s32 rtw_recv_entry(struct recv_frame *precvframe)
 {
 	struct adapter *padapter;
 	struct recv_priv *precvpriv;
 	s32 ret = _SUCCESS;
 
-_func_enter_;
 
-	padapter = precvframe->u.hdr.adapter;
+	padapter = precvframe->adapter;
 
 	precvpriv = &padapter->recvpriv;
 
@@ -2213,7 +2207,6 @@ _func_enter_;
 
 	precvpriv->rx_pkts++;
 
-_func_exit_;
 
 	return ret;
 
@@ -2222,7 +2215,6 @@ _recv_entry_drop:
 	if (padapter->registrypriv.mp_mode == 1)
 		padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
 
-_func_exit_;
 
 	return ret;
 }
@@ -2244,13 +2236,13 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
 	} else {
 		if (recvpriv->signal_strength_data.update_req == 0) {/*  update_req is clear, means we got rx */
 			avg_signal_strength = recvpriv->signal_strength_data.avg_val;
-			/*  after avg_vals are accquired, we can re-stat the signal values */
+			/*  after avg_vals are acquired, we can re-stat the signal values */
 			recvpriv->signal_strength_data.update_req = 1;
 		}
 
 		if (recvpriv->signal_qual_data.update_req == 0) {/*  update_req is clear, means we got rx */
 			avg_signal_qual = recvpriv->signal_qual_data.avg_val;
-			/*  after avg_vals are accquired, we can re-stat the signal values */
+			/*  after avg_vals are acquired, we can re-stat the signal values */
 			recvpriv->signal_qual_data.update_req = 1;
 		}
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
index e08845729772..c4b16ea6348a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -41,7 +41,6 @@ static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32	key_len)
 	u32	stateindex;
 	u8 *state;
 	u32	counter;
-_func_enter_;
 	state = parc4ctx->state;
 	parc4ctx->x = 0;
 	parc4ctx->y = 0;
@@ -58,7 +57,6 @@ _func_enter_;
 		if (++keyindex >= key_len)
 			keyindex = 0;
 	}
-_func_exit_;
 }
 
 static u32 arcfour_byte(struct arc4context *parc4ctx)
@@ -67,7 +65,6 @@ static u32 arcfour_byte(struct arc4context *parc4ctx)
 	u32 y;
 	u32 sx, sy;
 	u8 *state;
-_func_enter_;
 	state = parc4ctx->state;
 	x = (parc4ctx->x + 1) & 0xff;
 	sx = state[x];
@@ -77,17 +74,14 @@ _func_enter_;
 	parc4ctx->y = y;
 	state[y] = (u8)sx;
 	state[x] = (u8)sy;
-_func_exit_;
 	return state[(sx + sy) & 0xff];
 }
 
 static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, u8 *src, u32 len)
 {
 	u32	i;
-_func_enter_;
 	for (i = 0; i < len; i++)
 		dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-_func_exit_;
 }
 
 static int bcrc32initialized;
@@ -102,9 +96,8 @@ static u8 crc32_reverseBit(u8 data)
 
 static void crc32_init(void)
 {
-_func_enter_;
 	if (bcrc32initialized == 1) {
-		goto exit;
+		return;
 	} else {
 		int i, j;
 		u32 c;
@@ -126,15 +119,12 @@ _func_enter_;
 		}
 		bcrc32initialized = 1;
 	}
-exit:
-_func_exit_;
 }
 
 static __le32 getcrc32(u8 *buf, int len)
 {
 	u8 *p;
 	u32  crc;
-_func_enter_;
 	if (bcrc32initialized == 0)
 		crc32_init();
 
@@ -142,7 +132,6 @@ _func_enter_;
 
 	for (p = buf; len > 0; ++p, --len)
 		crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
-_func_exit_;
 	return cpu_to_le32(~crc);    /* transmit complement, per CRC-32 spec */
 }
 
@@ -165,7 +154,6 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
 	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
 	struct	xmit_priv		*pxmitpriv = &padapter->xmitpriv;
 
-_func_enter_;
 
 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
 		return;
@@ -206,7 +194,6 @@ _func_enter_;
 		}
 	}
 
-_func_exit_;
 }
 
 void rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
@@ -218,12 +205,11 @@ void rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
 	u32	keylength;
 	u8	*pframe, *payload, *iv, wepkey[16];
 	u8	 keyindex;
-	struct	rx_pkt_attrib	 *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib);
+	struct	rx_pkt_attrib	 *prxattrib = &(((struct recv_frame *)precvframe)->attrib);
 	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
 
-_func_enter_;
 
-	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
+	pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
 
 	/* start to decrypt recvframe */
 	if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
@@ -232,7 +218,7 @@ _func_enter_;
 		keylength = psecuritypriv->dot11DefKeylen[keyindex];
 		memcpy(&wepkey[0], iv, 3);
 		memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
-		length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+		length = ((struct recv_frame *)precvframe)->len-prxattrib->hdrlen-prxattrib->iv_len;
 
 		payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
 
@@ -252,7 +238,6 @@ _func_enter_;
 				 &crc, &payload[length-4]));
 		}
 	}
-_func_exit_;
 	return;
 }
 
@@ -263,10 +248,8 @@ static u32 secmicgetuint32(u8 *p)
 {
 	s32 i;
 	u32 res = 0;
-_func_enter_;
 	for (i = 0; i < 4; i++)
 		res |= ((u32)(*p++)) << (8*i);
-_func_exit_;
 	return res;
 }
 
@@ -274,39 +257,32 @@ static void secmicputuint32(u8 *p, u32 val)
 /*  Convert from Us3232 to Byte[] in a portable way */
 {
 	long i;
-_func_enter_;
 	for (i = 0; i < 4; i++) {
 		*p++ = (u8) (val & 0xff);
 		val >>= 8;
 	}
-_func_exit_;
 }
 
 static void secmicclear(struct mic_data *pmicdata)
 {
 /*  Reset the state to the empty message. */
-_func_enter_;
 	pmicdata->L = pmicdata->K0;
 	pmicdata->R = pmicdata->K1;
 	pmicdata->nBytesInM = 0;
 	pmicdata->M = 0;
-_func_exit_;
 }
 
 void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
 {
 	/*  Set the key */
-_func_enter_;
 	pmicdata->K0 = secmicgetuint32(key);
 	pmicdata->K1 = secmicgetuint32(key + 4);
 	/*  and reset the message */
 	secmicclear(pmicdata);
-_func_exit_;
 }
 
 void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
 {
-_func_enter_;
 	/*  Append the byte to our word-sized buffer */
 	pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
 	pmicdata->nBytesInM++;
@@ -325,23 +301,19 @@ _func_enter_;
 		pmicdata->M = 0;
 		pmicdata->nBytesInM = 0;
 	}
-_func_exit_;
 }
 
 void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
 {
-_func_enter_;
 	/*  This is simple */
 	while (nbytes > 0) {
 		rtw_secmicappendbyte(pmicdata, *src++);
 		nbytes--;
 	}
-_func_exit_;
 }
 
 void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
 {
-_func_enter_;
 	/*  Append the minimum padding */
 	rtw_secmicappendbyte(pmicdata, 0x5a);
 	rtw_secmicappendbyte(pmicdata, 0);
@@ -356,14 +328,12 @@ _func_enter_;
 	secmicputuint32(dst+4, pmicdata->R);
 	/*  Reset to the empty message. */
 	secmicclear(pmicdata);
-_func_exit_;
 }
 
 void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
 {
 	struct mic_data	micdata;
 	u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-_func_enter_;
 	rtw_secmicsetkey(&micdata, key);
 	priority[0] = pri;
 
@@ -386,7 +356,6 @@ _func_enter_;
 	rtw_secmicappend(&micdata, data, data_len);
 
 	rtw_secgetmic(&micdata, mic_code);
-_func_exit_;
 }
 
 
@@ -505,7 +474,6 @@ static const unsigned short Sbox1[2][256] = {  /* Sbox for hash (can be in ROM)
 static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
 {
 	int  i;
-_func_enter_;
 	/* Initialize the 80 bits of P1K[] from IV32 and TA[0..5]     */
 	p1k[0]      = Lo16(iv32);
 	p1k[1]      = Hi16(iv32);
@@ -523,7 +491,6 @@ _func_enter_;
 		p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
 		p1k[4] +=  (unsigned short)i;   /* avoid "slide attacks" */
 	}
-_func_exit_;
 }
 
 /*
@@ -553,7 +520,6 @@ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
 {
 	int  i;
 	u16 PPK[6];			/* temporary key for mixing    */
-_func_enter_;
 	/* Note: all adds in the PPK[] equations below are mod 2**16	 */
 	for (i = 0; i < 5; i++)
 		PPK[i] = p1k[i];	/* first, copy P1K to PPK      */
@@ -590,7 +556,6 @@ _func_enter_;
 		rc4key[4+2*i] = Lo8(PPK[i]);
 		rc4key[5+2*i] = Hi8(PPK[i]);
 	}
-_func_exit_;
 }
 
 /* The hlen isn't include the IV */
@@ -612,7 +577,6 @@ u32	rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
 	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
 	struct	xmit_priv		*pxmitpriv = &padapter->xmitpriv;
 	u32	res = _SUCCESS;
-_func_enter_;
 
 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
 		return _FAIL;
@@ -672,7 +636,6 @@ _func_enter_;
 			res = _FAIL;
 		}
 	}
-_func_exit_;
 	return res;
 }
 
@@ -690,13 +653,12 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
 	u8	*pframe, *payload, *iv, *prwskey;
 	union pn48 dot11txpn;
 	struct	sta_info		*stainfo;
-	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+	struct	rx_pkt_attrib	 *prxattrib = &((struct recv_frame *)precvframe)->attrib;
 	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
 	u32		res = _SUCCESS;
 
-_func_enter_;
 
-	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
+	pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
 
 	/* 4 start to decrypt recvframe */
 	if (prxattrib->encrypt == _TKIP_) {
@@ -716,7 +678,7 @@ _func_enter_;
 
 			iv = pframe+prxattrib->hdrlen;
 			payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
-			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+			length = ((struct recv_frame *)precvframe)->len-prxattrib->hdrlen-prxattrib->iv_len;
 
 			GET_TKIP_PN(iv, dot11txpn);
 
@@ -747,7 +709,6 @@ _func_enter_;
 			res = _FAIL;
 		}
 	}
-_func_exit_;
 exit:
 	return res;
 }
@@ -821,19 +782,15 @@ static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
 static void xor_128(u8 *a, u8 *b, u8 *out)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		out[i] = a[i] ^ b[i];
-_func_exit_;
 }
 
 static void xor_32(u8 *a, u8 *b, u8 *out)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 4; i++)
 		out[i] = a[i] ^ b[i];
-_func_exit_;
 }
 
 static u8 sbox(u8 a)
@@ -849,7 +806,6 @@ static void next_key(u8 *key, int round)
 		0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
 		0x1b, 0x36, 0x36, 0x36
 	};
-_func_enter_;
 	sbox_key[0] = sbox(key[13]);
 	sbox_key[1] = sbox(key[14]);
 	sbox_key[2] = sbox(key[15]);
@@ -863,21 +819,17 @@ _func_enter_;
 	xor_32(&key[4], &key[0], &key[4]);
 	xor_32(&key[8], &key[4], &key[8]);
 	xor_32(&key[12], &key[8], &key[12]);
-_func_exit_;
 }
 
 static void byte_sub(u8 *in, u8 *out)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		out[i] = sbox(in[i]);
-_func_exit_;
 }
 
 static void shift_row(u8 *in, u8 *out)
 {
-_func_enter_;
 	out[0] =  in[0];
 	out[1] =  in[5];
 	out[2] =  in[10];
@@ -894,7 +846,6 @@ _func_enter_;
 	out[13] = in[1];
 	out[14] = in[6];
 	out[15] = in[11];
-_func_exit_;
 }
 
 static void mix_column(u8 *in, u8 *out)
@@ -908,7 +859,6 @@ static void mix_column(u8 *in, u8 *out)
 	u8 rotr[4];
 	u8 temp[4];
 	u8 tempb[4];
-_func_enter_;
 	for (i = 0 ; i < 4; i++) {
 		if ((in[i] & 0x80) == 0x80)
 			add1b[i] = 0x1b;
@@ -952,7 +902,6 @@ _func_enter_;
 	xor_32(add1bf7, rotr, temp);
 	xor_32(swap_halfs, rotl, tempb);
 	xor_32(temp, tempb, out);
-_func_exit_;
 }
 
 static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
@@ -962,7 +911,6 @@ static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
 	u8 intermediatea[16];
 	u8 intermediateb[16];
 	u8 round_key[16];
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		round_key[i] = key[i];
 	for (round = 0; round < 11; round++) {
@@ -984,7 +932,6 @@ _func_enter_;
 			next_key(round_key, round);
 		}
 	}
-_func_exit_;
 }
 
 /************************************************/
@@ -995,7 +942,6 @@ static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
 			     uint payload_length, u8 *pn_vector)
 {
 	int i;
-_func_enter_;
 	mic_iv[0] = 0x59;
 	if (qc_exists && a4_exists)
 		mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC	   */
@@ -1009,7 +955,6 @@ _func_enter_;
 		mic_iv[i] = pn_vector[13 - i];	/* mic_iv[8:13] = PN[5:0] */
 	mic_iv[14] = (unsigned char) (payload_length / 256);
 	mic_iv[15] = (unsigned char) (payload_length % 256);
-_func_exit_;
 }
 
 /************************************************/
@@ -1019,7 +964,6 @@ _func_exit_;
 /************************************************/
 static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
 {
-_func_enter_;
 	mic_header1[0] = (u8)((header_length - 2) / 256);
 	mic_header1[1] = (u8)((header_length - 2) % 256);
 	mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
@@ -1036,7 +980,6 @@ _func_enter_;
 	mic_header1[13] = mpdu[13];
 	mic_header1[14] = mpdu[14];
 	mic_header1[15] = mpdu[15];
-_func_exit_;
 }
 
 /************************************************/
@@ -1047,7 +990,6 @@ _func_exit_;
 static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		mic_header2[i] = 0x00;
 
@@ -1079,7 +1021,6 @@ _func_enter_;
 		mic_header2[15] = mpdu[31] & 0x00;
 	}
 
-_func_exit_;
 }
 
 /************************************************/
@@ -1090,7 +1031,6 @@ _func_exit_;
 static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		ctr_preload[i] = 0x00;
 	i = 0;
@@ -1107,7 +1047,6 @@ _func_enter_;
 		ctr_preload[i] =    pn_vector[13 - i];	  /* ctr_preload[8:13] = PN[5:0] */
 	ctr_preload[14] =  (unsigned char) (c / 256); /* Ctr */
 	ctr_preload[15] =  (unsigned char) (c % 256);
-_func_exit_;
 }
 
 /************************************/
@@ -1117,10 +1056,8 @@ _func_exit_;
 static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < 16; i++)
 		out[i] = ina[i] ^ inb[i];
-_func_exit_;
 }
 
 static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
@@ -1142,7 +1079,6 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
 	uint	frtype  = GetFrameType(pframe);
 	uint	frsubtype  = GetFrameSubType(pframe);
 
-_func_enter_;
 	frsubtype = frsubtype>>4;
 
 	_rtw_memset((void *)mic_iv, 0, 16);
@@ -1253,7 +1189,6 @@ _func_enter_;
 	bitwise_xor(aes_out, padded_buffer, chain_buffer);
 	for (j = 0; j < 8; j++)
 		pframe[payload_index++] = chain_buffer[j];
-_func_exit_;
 	return _SUCCESS;
 }
 
@@ -1274,7 +1209,6 @@ u32	rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
 
 /*	uint	offset = 0; */
 	u32 res = _SUCCESS;
-_func_enter_;
 
 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
 		return _FAIL;
@@ -1318,7 +1252,6 @@ _func_enter_;
 	}
 
 
-_func_exit_;
 		return res;
 }
 
@@ -1344,7 +1277,6 @@ static int aes_decipher(u8 *key, uint	hdrlen,
 /*	uint	offset = 0; */
 	uint	frtype  = GetFrameType(pframe);
 	uint	frsubtype  = GetFrameSubType(pframe);
-_func_enter_;
 	frsubtype = frsubtype>>4;
 
 	_rtw_memset((void *)mic_iv, 0, 16);
@@ -1514,7 +1446,6 @@ _func_enter_;
 			res = _FAIL;
 		}
 	}
-_func_exit_;
 	return res;
 }
 
@@ -1524,11 +1455,10 @@ u32	rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
 	int		length;
 	u8	*pframe, *prwskey;	/*  *payload,*iv */
 	struct	sta_info		*stainfo;
-	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+	struct	rx_pkt_attrib	 *prxattrib = &((struct recv_frame *)precvframe)->attrib;
 	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
 	u32	res = _SUCCESS;
-_func_enter_;
-	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
+	pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
 	/* 4 start to encrypt each fragment */
 	if ((prxattrib->encrypt == _AES_)) {
 		stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
@@ -1552,14 +1482,13 @@ _func_enter_;
 			} else {
 				prwskey = &stainfo->dot118021x_UncstKey.skey[0];
 			}
-			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+			length = ((struct recv_frame *)precvframe)->len-prxattrib->hdrlen-prxattrib->iv_len;
 			res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
 		} else {
 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo==NULL!!!\n"));
 			res = _FAIL;
 		}
 	}
-_func_exit_;
 exit:
 	return res;
 }
@@ -1767,7 +1696,6 @@ void rtw_use_tkipkey_handler(void *FunctionContext)
 {
 	struct adapter *padapter = (struct adapter *)FunctionContext;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler ^^^\n"));
 
@@ -1775,5 +1703,4 @@ _func_enter_;
 
 	RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler padapter->securitypriv.busetkipkey=%d^^^\n", padapter->securitypriv.busetkipkey));
 
-_func_exit_;
 }
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
index 02e1e1f8b3ea..2d0b60686a01 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -25,10 +25,10 @@
 #include <xmit_osdep.h>
 #include <mlme_osdep.h>
 #include <sta_info.h>
+#include <linux/vmalloc.h>
 
 static void _rtw_init_stainfo(struct sta_info *psta)
 {
-_func_enter_;
 	_rtw_memset((u8 *)psta, 0, sizeof (struct sta_info));
 
 	 spin_lock_init(&psta->lock);
@@ -69,7 +69,6 @@ _func_enter_;
 
 #endif	/*  CONFIG_88EU_AP_MODE */
 
-_func_exit_;
 }
 
 u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
@@ -77,9 +76,8 @@ u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
 	struct sta_info *psta;
 	s32 i;
 
-_func_enter_;
 
-	pstapriv->pallocated_stainfo_buf = rtw_zvmalloc(sizeof(struct sta_info) * NUM_STA + 4);
+	pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
 
 	if (!pstapriv->pallocated_stainfo_buf)
 		return _FAIL;
@@ -125,7 +123,6 @@ _func_enter_;
 	pstapriv->max_num_sta = NUM_STA;
 #endif
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -154,21 +151,19 @@ static void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
 	struct list_head *plist, *phead;
 	struct sta_info *psta = NULL;
 
-_func_enter_;
 
 	spin_lock_bh(&pstapriv->sta_hash_lock);
 
 	phead = get_list_head(&pstapriv->free_sta_queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = LIST_CONTAINOR(plist, struct sta_info , list);
-		plist = get_next(plist);
+		psta = container_of(plist, struct sta_info , list);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pstapriv->sta_hash_lock);
 
-_func_exit_;
 }
 
 static void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
@@ -183,22 +178,21 @@ u32	_rtw_free_sta_priv(struct	sta_priv *pstapriv)
 	struct recv_reorder_ctrl *preorder_ctrl;
 	int	index;
 
-_func_enter_;
 	if (pstapriv) {
 		/*	delete all reordering_ctrl_timer		*/
 		spin_lock_bh(&pstapriv->sta_hash_lock);
 		for (index = 0; index < NUM_STA; index++) {
 			phead = &(pstapriv->sta_hash[index]);
-			plist = get_next(phead);
+			plist = phead->next;
 
 			while ((rtw_end_of_queue_search(phead, plist)) == false) {
 				int i;
-				psta = LIST_CONTAINOR(plist, struct sta_info , hash_list);
-				plist = get_next(plist);
+				psta = container_of(plist, struct sta_info , hash_list);
+				plist = plist->next;
 
 				for (i = 0; i < 16; i++) {
 					preorder_ctrl = &psta->recvreorder_ctrl[i];
-					_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+					del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 				}
 			}
 		}
@@ -208,10 +202,9 @@ _func_enter_;
 		rtw_mfree_sta_priv_lock(pstapriv);
 
 		if (pstapriv->pallocated_stainfo_buf)
-			rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
+			vfree(pstapriv->pallocated_stainfo_buf);
 	}
 
-_func_exit_;
 	return _SUCCESS;
 }
 
@@ -225,7 +218,6 @@ struct	sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
 	int i = 0;
 	u16  wRxSeqInitialValue = 0xffff;
 
-_func_enter_;
 
 	pfree_sta_queue = &pstapriv->free_sta_queue;
 
@@ -235,7 +227,7 @@ _func_enter_;
 		spin_unlock_bh(&pfree_sta_queue->lock);
 		psta = NULL;
 	} else {
-		psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
+		psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
 		rtw_list_delete(&(psta->list));
 		spin_unlock_bh(&pfree_sta_queue->lock);
 		_rtw_init_stainfo(psta);
@@ -297,9 +289,6 @@ _func_enter_;
 	}
 
 exit:
-
-_func_exit_;
-
 	return psta;
 }
 
@@ -313,7 +302,6 @@ u32	rtw_free_stainfo(struct adapter *padapter , struct sta_info *psta)
 	struct	xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	struct	sta_priv *pstapriv = &padapter->stapriv;
 
-_func_enter_;
 
 	if (psta == NULL)
 		goto exit;
@@ -353,32 +341,34 @@ _func_enter_;
 	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
 	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
 
-	_cancel_timer_ex(&psta->addba_retry_timer);
+	del_timer_sync(&psta->addba_retry_timer);
 
 	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
 	for (i = 0; i < 16; i++) {
 		struct list_head *phead, *plist;
-		union recv_frame *prframe;
+		struct recv_frame *prhdr;
+		struct recv_frame *prframe;
 		struct __queue *ppending_recvframe_queue;
 		struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
 
 		preorder_ctrl = &psta->recvreorder_ctrl[i];
 
-		_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 
 		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
 
 		spin_lock_bh(&ppending_recvframe_queue->lock);
 
 		phead =		get_list_head(ppending_recvframe_queue);
-		plist = get_next(phead);
+		plist = phead->next;
 
 		while (!rtw_is_list_empty(phead)) {
-			prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+			prhdr = container_of(plist, struct recv_frame, list);
+			prframe = (struct recv_frame *)prhdr;
 
-			plist = get_next(plist);
+			plist = plist->next;
 
-			rtw_list_delete(&(prframe->u.hdr.list));
+			rtw_list_delete(&(prframe->list));
 
 			rtw_free_recvframe(prframe, pfree_recv_queue);
 		}
@@ -428,7 +418,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -442,32 +431,26 @@ void rtw_free_all_stainfo(struct adapter *padapter)
 	struct	sta_priv *pstapriv = &padapter->stapriv;
 	struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
 
-_func_enter_;
 
 	if (pstapriv->asoc_sta_count == 1)
-		goto exit;
+		return;
 
 	spin_lock_bh(&pstapriv->sta_hash_lock);
 
 	for (index = 0; index < NUM_STA; index++) {
 		phead = &(pstapriv->sta_hash[index]);
-		plist = get_next(phead);
+		plist = phead->next;
 
 		while ((!rtw_end_of_queue_search(phead, plist))) {
-			psta = LIST_CONTAINOR(plist, struct sta_info , hash_list);
+			psta = container_of(plist, struct sta_info , hash_list);
 
-			plist = get_next(plist);
+			plist = plist->next;
 
 			if (pbcmc_stainfo != psta)
 				rtw_free_stainfo(padapter , psta);
 		}
 	}
-
 	spin_unlock_bh(&pstapriv->sta_hash_lock);
-
-exit:
-
-_func_exit_;
 }
 
 /* any station allocated can be searched by hash list */
@@ -479,7 +462,6 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
 	u8 *addr;
 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-_func_enter_;
 
 	if (hwaddr == NULL)
 		return NULL;
@@ -494,21 +476,20 @@ _func_enter_;
 	spin_lock_bh(&pstapriv->sta_hash_lock);
 
 	phead = &(pstapriv->sta_hash[index]);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while ((!rtw_end_of_queue_search(phead, plist))) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+		psta = container_of(plist, struct sta_info, hash_list);
 
-		if ((_rtw_memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
+		if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
 			/*  if found the matched address */
 			break;
 		}
 		psta = NULL;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pstapriv->sta_hash_lock);
-_func_exit_;
 	return psta;
 }
 
@@ -519,7 +500,6 @@ u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
 	unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	struct	sta_priv *pstapriv = &padapter->stapriv;
 
-_func_enter_;
 
 	psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
 
@@ -533,7 +513,6 @@ _func_enter_;
 	psta->mac_id = 1;
 
 exit:
-_func_exit_;
 	return res;
 }
 
@@ -542,9 +521,7 @@ struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
 	struct sta_info		*psta;
 	struct sta_priv		*pstapriv = &padapter->stapriv;
 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-_func_enter_;
 	 psta = rtw_get_stainfo(pstapriv, bc_addr);
-_func_exit_;
 	return psta;
 }
 
@@ -561,12 +538,12 @@ u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
 
 	spin_lock_bh(&(pacl_node_q->lock));
 	phead = get_list_head(pacl_node_q);
-	plist = get_next(phead);
+	plist = phead->next;
 	while ((!rtw_end_of_queue_search(phead, plist))) {
-		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-		plist = get_next(plist);
+		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+		plist = plist->next;
 
-		if (_rtw_memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
+		if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
 			if (paclnode->valid) {
 				match = true;
 				break;
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 96df62f95b6b..3dd90599fd4b 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -929,7 +929,7 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
 		return _FAIL;
 	}
 
-	if (_rtw_memcmp(cur_network->network.MacAddress, pbssid, 6) == false) {
+	if (!memcmp(cur_network->network.MacAddress, pbssid, 6) == false) {
 		DBG_88E("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n%pM %pM\n",
 			(pbssid), (cur_network->network.MacAddress));
 		return true;
@@ -1014,7 +1014,7 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
 				bssid->Ssid.SsidLength, cur_network->network.Ssid.Ssid,
 				cur_network->network.Ssid.SsidLength));
 
-	if (!_rtw_memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
+	if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
 	    bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) {
 		if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */
 			DBG_88E("%s(), SSID is not match return FAIL\n", __func__);
@@ -1050,7 +1050,7 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
 	}
 
 	if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-		DBG_88E("%s(): enctyp is not match , return FAIL\n", __func__);
+		DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__);
 		goto _mismatch;
 	}
 
@@ -1090,12 +1090,10 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
 	}
 
 	kfree(bssid);
-	_func_exit_;
 	return _SUCCESS;
 
 _mismatch:
 	kfree(bssid);
-	_func_exit_;
 	return _FAIL;
 }
 
@@ -1141,11 +1139,11 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
 
 			switch (pIE->ElementID) {
 			case _VENDOR_SPECIFIC_IE_:
-				if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) && (_rtw_memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
+				if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
 					return true;
 				break;
 			case _RSN_IE_2_:
-				if (_rtw_memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
+				if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
 					return true;
 			default:
 				break;
@@ -1172,14 +1170,14 @@ unsigned int should_forbid_n_rate(struct adapter *padapter)
 
 			switch (pIE->ElementID) {
 			case _VENDOR_SPECIFIC_IE_:
-				if (_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4) &&
-				    ((_rtw_memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP, 4)) ||
-				    (_rtw_memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP, 4))))
+				if (!memcmp(pIE->data, RTW_WPA_OUI, 4) &&
+				    ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP, 4)) ||
+				    (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP, 4))))
 					return false;
 				break;
 			case _RSN_IE_2_:
-				if  ((_rtw_memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4))  ||
-				       (_rtw_memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
+				if  ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4))  ||
+				       (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
 					return false;
 			default:
 				break;
@@ -1208,7 +1206,7 @@ unsigned int is_ap_in_wep(struct adapter *padapter)
 
 			switch (pIE->ElementID) {
 			case _VENDOR_SPECIFIC_IE_:
-				if (_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4))
+				if (!memcmp(pIE->data, RTW_WPA_OUI, 4))
 					return false;
 				break;
 			case _RSN_IE_2_:
@@ -1400,35 +1398,35 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
 
 		switch (pIE->ElementID) {
 		case _VENDOR_SPECIFIC_IE_:
-			if ((_rtw_memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
-			    (_rtw_memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
+			if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
+			    (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
 				DBG_88E("link to Artheros AP\n");
 				return HT_IOT_PEER_ATHEROS;
-			} else if ((_rtw_memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
-				   (_rtw_memcmp(pIE->data, BROADCOM_OUI2, 3)) ||
-				   (_rtw_memcmp(pIE->data, BROADCOM_OUI2, 3))) {
+			} else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
+				   (!memcmp(pIE->data, BROADCOM_OUI2, 3)) ||
+				   (!memcmp(pIE->data, BROADCOM_OUI2, 3))) {
 				DBG_88E("link to Broadcom AP\n");
 				return HT_IOT_PEER_BROADCOM;
-			} else if (_rtw_memcmp(pIE->data, MARVELL_OUI, 3)) {
+			} else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
 				DBG_88E("link to Marvell AP\n");
 				return HT_IOT_PEER_MARVELL;
-			} else if (_rtw_memcmp(pIE->data, RALINK_OUI, 3)) {
+			} else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
 				if (!ralink_vendor_flag) {
 					ralink_vendor_flag = 1;
 				} else {
 					DBG_88E("link to Ralink AP\n");
 					return HT_IOT_PEER_RALINK;
 				}
-			} else if (_rtw_memcmp(pIE->data, CISCO_OUI, 3)) {
+			} else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
 				DBG_88E("link to Cisco AP\n");
 				return HT_IOT_PEER_CISCO;
-			} else if (_rtw_memcmp(pIE->data, REALTEK_OUI, 3)) {
+			} else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
 				DBG_88E("link to Realtek 96B\n");
 				return HT_IOT_PEER_REALTEK;
-			} else if (_rtw_memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
+			} else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
 				DBG_88E("link to Airgo Cap\n");
 				return HT_IOT_PEER_AIRGO;
-			} else if (_rtw_memcmp(pIE->data, EPIGRAM_OUI, 3)) {
+			} else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
 				epigram_vendor_flag = 1;
 				if (ralink_vendor_flag) {
 					DBG_88E("link to Tenda W311R AP\n");
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index 24182fbc6a71..8d4265fb486d 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -23,25 +23,22 @@
 #include <drv_types.h>
 #include <wifi.h>
 #include <osdep_intf.h>
-#include <ip.h>
 #include <usb_ops.h>
 #include <usb_osintf.h>
+#include <linux/vmalloc.h>
 
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
 
 static void _init_txservq(struct tx_servq *ptxservq)
 {
-_func_enter_;
 	_rtw_init_listhead(&ptxservq->tx_pending);
 	_rtw_init_queue(&ptxservq->sta_pending);
 	ptxservq->qcnt = 0;
-_func_exit_;
 }
 
 void	_rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
 {
-_func_enter_;
 	_rtw_memset((unsigned char *)psta_xmitpriv, 0, sizeof (struct sta_xmit_priv));
 	spin_lock_init(&psta_xmitpriv->lock);
 	_init_txservq(&psta_xmitpriv->be_q);
@@ -51,7 +48,6 @@ _func_enter_;
 	_rtw_init_listhead(&psta_xmitpriv->legacy_dz);
 	_rtw_init_listhead(&psta_xmitpriv->apsd);
 
-_func_exit_;
 }
 
 s32	_rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
@@ -63,9 +59,8 @@ s32	_rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
 	u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 	u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
 
-_func_enter_;
 
-	/*  We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
+	/*  We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
 
 	spin_lock_init(&pxmitpriv->lock);
 	sema_init(&pxmitpriv->xmit_sema, 0);
@@ -91,7 +86,7 @@ _func_enter_;
 	Please also apply  free_txobj to link_up all the xmit_frames...
 	*/
 
-	pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+	pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
 
 	if (pxmitpriv->pallocated_frame_buf  == NULL) {
 		pxmitpriv->pxmit_frame_buf = NULL;
@@ -129,7 +124,7 @@ _func_enter_;
 	_rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);
 	_rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);
 
-	pxmitpriv->pallocated_xmitbuf = rtw_zvmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
+	pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
 
 	if (pxmitpriv->pallocated_xmitbuf  == NULL) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_buf fail!\n"));
@@ -171,7 +166,7 @@ _func_enter_;
 	/*  Init xmit extension buff */
 	_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
 
-	pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+	pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
 
 	if (pxmitpriv->pallocated_xmit_extbuf  == NULL) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
@@ -226,7 +221,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -240,12 +234,11 @@ void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv)
 	u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 	u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
 
- _func_enter_;
 
 	rtw_hal_free_xmit_priv(padapter);
 
 	if (pxmitpriv->pxmit_frame_buf == NULL)
-		goto out;
+		return;
 
 	for (i = 0; i < NR_XMITFRAME; i++) {
 		rtw_os_xmit_complete(padapter, pxmitframe);
@@ -259,10 +252,10 @@ void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv)
 	}
 
 	if (pxmitpriv->pallocated_frame_buf)
-		rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+		vfree(pxmitpriv->pallocated_frame_buf);
 
 	if (pxmitpriv->pallocated_xmitbuf)
-		rtw_vmfree(pxmitpriv->pallocated_xmitbuf, NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
+		vfree(pxmitpriv->pallocated_xmitbuf);
 
 	/*  free xmit extension buff */
 	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
@@ -272,16 +265,12 @@ void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv)
 	}
 
 	if (pxmitpriv->pallocated_xmit_extbuf) {
-		rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+		vfree(pxmitpriv->pallocated_xmit_extbuf);
 	}
 
 	rtw_free_hwxmits(padapter);
 
 	mutex_destroy(&pxmitpriv->ack_tx_mutex);
-
-out:
-
-_func_exit_;
 }
 
 static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *pxmitframe)
@@ -455,7 +444,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
 	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
 	int res = _SUCCESS;
 
- _func_enter_;
 
 	_rtw_open_pktfile(pkt, &pktfile);
 	_rtw_pktfile_read(&pktfile, (u8 *)&etherhdr, ETH_HLEN);
@@ -639,7 +627,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -662,7 +649,6 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
 	else
 		stainfo = rtw_get_stainfo(&padapter->stapriv , &pattrib->ra[0]);
 
-_func_enter_;
 
 	hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
 
@@ -676,12 +662,12 @@ _func_enter_;
 			pframe = pxmitframe->buf_addr + hw_hdr_offset;
 
 			if (bmcst) {
-				if (_rtw_memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16))
+				if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16))
 					return _FAIL;
 				/* start to calculate the mic code */
 				rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
 			} else {
-				if (_rtw_memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16) == true) {
+				if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16)) {
 					/* DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey == 0\n"); */
 					/* msleep(10); */
 					return _FAIL;
@@ -760,7 +746,6 @@ _func_enter_;
 			}
 	}
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -769,7 +754,6 @@ static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmi
 {
 	struct	pkt_attrib	 *pattrib = &pxmitframe->attrib;
 
-_func_enter_;
 
 	if (pattrib->bswenc) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("### xmitframe_swencrypt\n"));
@@ -791,7 +775,6 @@ _func_enter_;
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, ("### xmitframe_hwencrypt\n"));
 	}
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -812,7 +795,6 @@ s32 rtw_make_wlanhdr (struct adapter *padapter , u8 *hdr, struct pkt_attrib *pat
 
 	int bmcst = IS_MCAST(pattrib->ra);
 
-_func_enter_;
 
 	if (pattrib->psta) {
 		psta = pattrib->psta;
@@ -918,7 +900,6 @@ _func_enter_;
 	}
 exit:
 
-_func_exit_;
 	return res;
 }
 
@@ -1007,7 +988,6 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
 	s32 bmcst = IS_MCAST(pattrib->ra);
 	s32 res = _SUCCESS;
 
-_func_enter_;
 
 	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
 
@@ -1145,7 +1125,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1162,7 +1141,6 @@ s32 rtw_put_snap(u8 *data, u16 h_proto)
 	struct ieee80211_snap_hdr *snap;
 	u8 *oui;
 
-_func_enter_;
 
 	snap = (struct ieee80211_snap_hdr *)data;
 	snap->dsap = 0xaa;
@@ -1180,7 +1158,6 @@ _func_enter_;
 
 	*(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
 
-_func_exit_;
 
 	return SNAP_SIZE + sizeof(u16);
 }
@@ -1193,7 +1170,6 @@ void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
 	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct	registry_priv *pregistrypriv = &padapter->registrypriv;
 
-_func_enter_;
 
 	switch (pxmitpriv->vcs_setting) {
 	case DISABLE_VCS:
@@ -1220,7 +1196,6 @@ _func_enter_;
 		break;
 	}
 
-_func_exit_;
 }
 
 void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz)
@@ -1250,7 +1225,6 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
 	struct list_head *plist, *phead;
 	struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
 
-_func_enter_;
 
 	spin_lock_irqsave(&pfree_queue->lock, irql);
 
@@ -1259,9 +1233,9 @@ _func_enter_;
 	} else {
 		phead = get_list_head(pfree_queue);
 
-		plist = get_next(phead);
+		plist = phead->next;
 
-		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+		pxmitbuf = container_of(plist, struct xmit_buf, list);
 
 		rtw_list_delete(&(pxmitbuf->list));
 	}
@@ -1280,7 +1254,6 @@ _func_enter_;
 
 	spin_unlock_irqrestore(&pfree_queue->lock, irql);
 
-_func_exit_;
 
 	return pxmitbuf;
 }
@@ -1290,7 +1263,6 @@ s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
 	unsigned long irql;
 	struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
 
-_func_enter_;
 
 	if (pxmitbuf == NULL)
 		return _FAIL;
@@ -1304,7 +1276,6 @@ _func_enter_;
 
 	spin_unlock_irqrestore(&pfree_queue->lock, irql);
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -1316,7 +1287,6 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
 	struct list_head *plist, *phead;
 	struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
 
-_func_enter_;
 
 	/* DBG_88E("+rtw_alloc_xmitbuf\n"); */
 
@@ -1327,9 +1297,9 @@ _func_enter_;
 	} else {
 		phead = get_list_head(pfree_xmitbuf_queue);
 
-		plist = get_next(phead);
+		plist = phead->next;
 
-		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+		pxmitbuf = container_of(plist, struct xmit_buf, list);
 
 		rtw_list_delete(&(pxmitbuf->list));
 	}
@@ -1344,7 +1314,6 @@ _func_enter_;
 	}
 	spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
 
-_func_exit_;
 
 	return pxmitbuf;
 }
@@ -1354,7 +1323,6 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
 	unsigned long irql;
 	struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
 
-_func_enter_;
 	if (pxmitbuf == NULL)
 		return _FAIL;
 
@@ -1376,7 +1344,6 @@ _func_enter_;
 		spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
 	}
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -1405,7 +1372,6 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pf
 	struct list_head *plist, *phead;
 	struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
 
-_func_enter_;
 
 	spin_lock_bh(&pfree_xmit_queue->lock);
 
@@ -1415,9 +1381,9 @@ _func_enter_;
 	} else {
 		phead = get_list_head(pfree_xmit_queue);
 
-		plist = get_next(phead);
+		plist = phead->next;
 
-		pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+		pxframe = container_of(plist, struct xmit_frame, list);
 
 		rtw_list_delete(&(pxframe->list));
 	}
@@ -1444,7 +1410,6 @@ _func_enter_;
 
 	spin_unlock_bh(&pfree_xmit_queue->lock);
 
-_func_exit_;
 
 	return pxframe;
 }
@@ -1455,7 +1420,6 @@ s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitfram
 	struct adapter *padapter = pxmitpriv->adapter;
 	struct sk_buff *pndis_pkt = NULL;
 
-_func_enter_;
 
 	if (pxmitframe == NULL) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== rtw_free_xmitframe():pxmitframe == NULL!!!!!!!!!!\n"));
@@ -1483,7 +1447,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return _SUCCESS;
 }
@@ -1493,23 +1456,21 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram
 	struct list_head *plist, *phead;
 	struct	xmit_frame	*pxmitframe;
 
-_func_enter_;
 
 	spin_lock_bh(&(pframequeue->lock));
 
 	phead = get_list_head(pframequeue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+		pxmitframe = container_of(plist, struct xmit_frame, list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
 	}
 	spin_unlock_bh(&(pframequeue->lock));
 
-_func_exit_;
 }
 
 s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
@@ -1530,12 +1491,12 @@ static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, str
 	struct	xmit_frame	*pxmitframe = NULL;
 
 	xmitframe_phead = get_list_head(pframe_queue);
-	xmitframe_plist = get_next(xmitframe_phead);
+	xmitframe_plist = xmitframe_phead->next;
 
 	if (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-		xmitframe_plist = get_next(xmitframe_plist);
+		xmitframe_plist = xmitframe_plist->next;
 
 		rtw_list_delete(&pxmitframe->list);
 
@@ -1555,7 +1516,6 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmi
 	struct registry_priv	*pregpriv = &padapter->registrypriv;
 	int i, inx[4];
 
-_func_enter_;
 
 	inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
 
@@ -1572,10 +1532,10 @@ _func_enter_;
 		phwxmit = phwxmit_i + inx[i];
 
 		sta_phead = get_list_head(phwxmit->sta_queue);
-		sta_plist = get_next(sta_phead);
+		sta_plist = sta_phead->next;
 
 		while (!rtw_end_of_queue_search(sta_phead, sta_plist)) {
-			ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
+			ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
 
 			pframe_queue = &ptxservq->sta_pending;
 
@@ -1590,12 +1550,11 @@ _func_enter_;
 				goto exit;
 			}
 
-			sta_plist = get_next(sta_plist);
+			sta_plist = sta_plist->next;
 		}
 	}
 exit:
 	spin_unlock_bh(&pxmitpriv->lock);
-_func_exit_;
 	return pxmitframe;
 }
 
@@ -1603,7 +1562,6 @@ struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *
 {
 	struct tx_servq *ptxservq;
 
-_func_enter_;
 	switch (up) {
 	case 1:
 	case 2:
@@ -1632,7 +1590,6 @@ _func_enter_;
 	break;
 	}
 
-_func_exit_;
 
 	return ptxservq;
 }
@@ -1651,7 +1608,6 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
 	struct hw_xmit	*phwxmits =  padapter->xmitpriv.hwxmits;
 	int res = _SUCCESS;
 
-_func_enter_;
 
 	if (pattrib->psta) {
 		psta = pattrib->psta;
@@ -1676,7 +1632,6 @@ _func_enter_;
 	phwxmits[ac_index].accnt++;
 exit:
 
-_func_exit_;
 
 	return res;
 }
@@ -1719,10 +1674,8 @@ void rtw_free_hwxmits(struct adapter *padapter)
 void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry)
 {
 	int i;
-_func_enter_;
 	for (i = 0; i < entry; i++, phwxmit++)
 		phwxmit->accnt = 0;
-_func_exit_;
 }
 
 static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb)
@@ -1997,7 +1950,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
 			pstapriv->tim_bitmap |= BIT(0);/*  */
 			pstapriv->sta_dz_bitmap |= BIT(0);
 
-			update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
+			update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after update bcn */
 
 			ret = true;
 		}
@@ -2047,7 +2000,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
 				pstapriv->tim_bitmap |= BIT(psta->aid);
 
 				if (psta->sleepq_len == 1) {
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
 			}
@@ -2070,12 +2023,12 @@ static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struc
 	struct hw_xmit *phwxmits =  padapter->xmitpriv.hwxmits;
 
 	phead = get_list_head(pframequeue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+		pxmitframe = container_of(plist, struct xmit_frame, list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 		xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);
 
@@ -2137,12 +2090,12 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
 	spin_lock_bh(&psta->sleep_q.lock);
 
 	xmitframe_phead = get_list_head(&psta->sleep_q);
-	xmitframe_plist = get_next(xmitframe_phead);
+	xmitframe_plist = xmitframe_phead->next;
 
 	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-		xmitframe_plist = get_next(xmitframe_plist);
+		xmitframe_plist = xmitframe_plist->next;
 
 		rtw_list_delete(&pxmitframe->list);
 
@@ -2218,12 +2171,12 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
 		spin_lock_bh(&psta_bmc->sleep_q.lock);
 
 		xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
-		xmitframe_plist = get_next(xmitframe_phead);
+		xmitframe_plist = xmitframe_phead->next;
 
 		while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-			pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+			pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-			xmitframe_plist = get_next(xmitframe_plist);
+			xmitframe_plist = xmitframe_plist->next;
 
 			rtw_list_delete(&pxmitframe->list);
 
@@ -2265,12 +2218,12 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
 	spin_lock_bh(&psta->sleep_q.lock);
 
 	xmitframe_phead = get_list_head(&psta->sleep_q);
-	xmitframe_plist = get_next(xmitframe_phead);
+	xmitframe_plist = xmitframe_phead->next;
 
 	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
-		xmitframe_plist = get_next(xmitframe_plist);
+		xmitframe_plist = xmitframe_plist->next;
 
 		switch (pxmitframe->attrib.priority) {
 		case 1:
@@ -2316,7 +2269,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
 		if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
 			pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-			/* upate BCN for TIM IE */
+			/* update BCN for TIM IE */
 			update_beacon(padapter, _TIM_IE_, NULL, false);
 		}
 	}
diff --git a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
index 3df33bc7197a..dea220b507ad 100644
--- a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
+++ b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
@@ -331,6 +331,7 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
 
 static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
 {  /*  Wilson 2011/10/26 */
+	struct adapter *adapt = dm_odm->Adapter;
 	u32 MaskFromReg;
 	s8 i;
 
@@ -357,19 +358,19 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0000000d;
 		break;
 	case 12:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR0);
+		MaskFromReg = rtw_read32(adapt, REG_ARFR0);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 13:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR1);
+		MaskFromReg = rtw_read32(adapt, REG_ARFR1);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 14:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR2);
+		MaskFromReg = rtw_read32(adapt, REG_ARFR2);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 15:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR3);
+		MaskFromReg = rtw_read32(adapt, REG_ARFR3);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	default:
@@ -667,7 +668,9 @@ void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
 
 void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime)
 {
-	ODM_Write2Byte(dm_odm, REG_TX_RPT_TIME, minRptTime);
+	struct adapter *adapt = dm_odm->Adapter;
+
+	rtw_write16(adapt, REG_TX_RPT_TIME, minRptTime);
 }
 
 void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
diff --git a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
index 15e8e3f62198..056052ddd82e 100644
--- a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
+++ b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
@@ -217,7 +217,7 @@ odm_TXPowerTrackingCallback_ThermalMeter_8188E(
 
 		for (i = 0; i < CCK_TABLE_SIZE; i++) {
 			if (dm_odm->RFCalibrateInfo.bCCKinCH14) {
-				if (ODM_CompareMemory(dm_odm, (void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4) == 0) {
+				if (memcmp(&TempCCk, &CCKSwingTable_Ch14[i][2], 4)) {
 					CCK_index_old = (u8)i;
 					dm_odm->BbSwingIdxCckBase = (u8)i;
 					ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
@@ -229,7 +229,7 @@ odm_TXPowerTrackingCallback_ThermalMeter_8188E(
 				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
 					     ("RegA24: 0x%X, CCKSwingTable_Ch1_Ch13[%d][2]: CCKSwingTable_Ch1_Ch13[i][2]: 0x%X\n",
 					     TempCCk, i, CCKSwingTable_Ch1_Ch13[i][2]));
-				if (ODM_CompareMemory(dm_odm, (void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4) == 0) {
+				if (memcmp(&TempCCk, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
 					CCK_index_old = (u8)i;
 					dm_odm->BbSwingIdxCckBase = (u8)i;
 					ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
@@ -839,9 +839,9 @@ static void _PHY_SaveMACRegisters(
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save MAC parameters.\n"));
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		MACBackup[i] = ODM_Read1Byte(dm_odm, MACReg[i]);
+		MACBackup[i] = rtw_read8(adapt, MACReg[i]);
 	}
-	MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
+	MACBackup[i] = rtw_read32(adapt, MACReg[i]);
 }
 
 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
@@ -868,9 +868,9 @@ _PHY_ReloadMACRegisters(
 
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("Reload MAC parameters !\n"));
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		ODM_Write1Byte(dm_odm, MACReg[i], (u8)MACBackup[i]);
+		rtw_write8(adapt, MACReg[i], (u8)MACBackup[i]);
 	}
-	ODM_Write4Byte(dm_odm, MACReg[i], MACBackup[i]);
+	rtw_write32(adapt, MACReg[i], MACBackup[i]);
 }
 
 void
@@ -912,12 +912,12 @@ _PHY_MACSettingCalibration(
 
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("MAC settings for Calibration.\n"));
 
-	ODM_Write1Byte(dm_odm, MACReg[i], 0x3F);
+	rtw_write8(adapt, MACReg[i], 0x3F);
 
 	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
-		ODM_Write1Byte(dm_odm, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
+		rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
 	}
-	ODM_Write1Byte(dm_odm, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
+	rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
 }
 
 void
@@ -1223,16 +1223,14 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
 {
 	u8 tmpreg;
 	u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
-	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
 
 	/* Check continuous TX and Packet TX */
-	tmpreg = ODM_Read1Byte(dm_odm, 0xd03);
+	tmpreg = rtw_read8(adapt, 0xd03);
 
 	if ((tmpreg&0x70) != 0)			/* Deal with contisuous TX case */
-		ODM_Write1Byte(dm_odm, 0xd03, tmpreg&0x8F);	/* disable all continuous TX */
+		rtw_write8(adapt, 0xd03, tmpreg&0x8F);	/* disable all continuous TX */
 	else							/*  Deal with Packet TX case */
-		ODM_Write1Byte(dm_odm, REG_TXPAUSE, 0xFF);			/*  block all queues */
+		rtw_write8(adapt, REG_TXPAUSE, 0xFF);			/*  block all queues */
 
 	if ((tmpreg&0x70) != 0) {
 		/* 1. Read original RF mode */
@@ -1264,7 +1262,7 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
 	if ((tmpreg&0x70) != 0) {
 		/* Deal with continuous TX case */
 		/* Path-A */
-		ODM_Write1Byte(dm_odm, 0xd03, tmpreg);
+		rtw_write8(adapt, 0xd03, tmpreg);
 		PHY_SetRFReg(adapt, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
 
 		/* Path-B */
@@ -1272,7 +1270,7 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
 			PHY_SetRFReg(adapt, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
 	} else {
 		/*  Deal with Packet TX case */
-		ODM_Write1Byte(dm_odm, REG_TXPAUSE, 0x00);
+		rtw_write8(adapt, REG_TXPAUSE, 0x00);
 	}
 }
 
@@ -1468,13 +1466,10 @@ void PHY_LCCalibrate_8188E(struct adapter *adapt)
 
 static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2t)
 {
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
-	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-
 	if (!adapt->hw_init_completed) {
 		u8 u1btmp;
-		u1btmp = ODM_Read1Byte(dm_odm, REG_LEDCFG2) | BIT7;
-		ODM_Write1Byte(dm_odm, REG_LEDCFG2, u1btmp);
+		u1btmp = rtw_read8(adapt, REG_LEDCFG2) | BIT7;
+		rtw_write8(adapt, REG_LEDCFG2, u1btmp);
 		PHY_SetBBReg(adapt, rFPGA0_XAB_RFParameter, BIT13, 0x01);
 	}
 
diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c
index 598140464f05..d75ca7a27c86 100644
--- a/drivers/staging/rtl8188eu/hal/hal_intf.c
+++ b/drivers/staging/rtl8188eu/hal/hal_intf.c
@@ -116,8 +116,6 @@ uint rtw_hal_deinit(struct adapter *adapt)
 {
 	uint	status = _SUCCESS;
 
-_func_enter_;
-
 	status = adapt->HalFunc.hal_deinit(adapt);
 
 	if (status == _SUCCESS)
@@ -125,8 +123,6 @@ _func_enter_;
 	else
 		DBG_88E("\n rtw_hal_deinit: hal_init fail\n");
 
-_func_exit_;
-
 	return status;
 }
 
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
index 3555ffaa4e06..89a26e3e217f 100644
--- a/drivers/staging/rtl8188eu/hal/odm.c
+++ b/drivers/staging/rtl8188eu/hal/odm.c
@@ -887,9 +887,10 @@ void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm)
 void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres)
 {
 	struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+	struct adapter *adapt = pDM_Odm->Adapter;
 
 	if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)		/* modify by Guo.Mingzhi 2012-01-03 */
-		ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
+		rtw_write8(adapt, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
 	pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
 	pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
 }
@@ -1301,8 +1302,8 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm)
 		psta = pDM_Odm->pODM_StaInfo[i];
 		if (IS_STA_VALID(psta) &&
 		    (psta->state & WIFI_ASOC_STATE) &&
-		    !_rtw_memcmp(psta->hwaddr, bcast_addr, ETH_ALEN) &&
-		    !_rtw_memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) {
+		    memcmp(psta->hwaddr, bcast_addr, ETH_ALEN) &&
+		    memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) {
 			if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
 				tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
 
@@ -1433,10 +1434,10 @@ void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm)
 	pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
 	Adapter->recvpriv.bIsAnyNonBEPkts = false;
 
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VO_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VI_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BE_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BK_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_VO_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_VI_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_BE_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_BK_PARAM)));
 }	/*  ODM_InitEdcaTurbo */
 
 void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm)
diff --git a/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c b/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c
index 6193d9fafb98..a9886122b459 100644
--- a/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c
+++ b/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c
@@ -66,7 +66,9 @@ void odm_ConfigRF_RadioB_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data
 
 void odm_ConfigMAC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u8 Data)
 {
-	ODM_Write1Byte(pDM_Odm, Addr, Data);
+	struct adapter *adapt = pDM_Odm->Adapter;
+
+	rtw_write8(adapt, Addr, Data);
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigMACWithHeaderFile: [MAC_REG] %08X %08X\n", Addr, Data));
 }
 
diff --git a/drivers/staging/rtl8188eu/hal/odm_interface.c b/drivers/staging/rtl8188eu/hal/odm_interface.c
deleted file mode 100644
index 3cd68212afd1..000000000000
--- a/drivers/staging/rtl8188eu/hal/odm_interface.c
+++ /dev/null
@@ -1,101 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-/*  ODM IO Relative API. */
-
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read8(Adapter, RegAddr);
-}
-
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read16(Adapter, RegAddr);
-}
-
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read32(Adapter, RegAddr);
-}
-
-void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	rtw_write8(Adapter, RegAddr, Data);
-}
-
-void ODM_Write2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 Data)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	rtw_write16(Adapter, RegAddr, Data);
-}
-
-void ODM_Write4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 Data)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	rtw_write32(Adapter, RegAddr, Data);
-}
-
-/*  ODM Memory relative API. */
-void ODM_AllocateMemory(struct odm_dm_struct *pDM_Odm, void **pPtr, u32 length)
-{
-	*pPtr = rtw_zvmalloc(length);
-}
-
-/*  length could be ignored, used to detect memory leakage. */
-void ODM_FreeMemory(struct odm_dm_struct *pDM_Odm, void *pPtr, u32 length)
-{
-	rtw_vmfree(pPtr, length);
-}
-
-s32 ODM_CompareMemory(struct odm_dm_struct *pDM_Odm, void *pBuf1, void *pBuf2, u32 length)
-{
-	return _rtw_memcmp(pBuf1, pBuf2, length);
-}
-
-void ODM_SetTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
-{
-	_set_timer(pTimer, msDelay); /* ms */
-}
-
-void ODM_InitializeTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer,
-			 void *CallBackFunc, void *pContext,
-			 const char *szID)
-{
-	struct adapter *Adapter = pDM_Odm->Adapter;
-	_init_timer(pTimer, Adapter->pnetdev, CallBackFunc, pDM_Odm);
-}
-
-void ODM_CancelTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer)
-{
-	_cancel_timer_ex(pTimer);
-}
-
-/*  ODM FW relative API. */
-u32 ODM_FillH2CCmd(u8 *pH2CBuffer, u32 H2CBufferLen, u32 CmdNum,
-		      u32 *pElementID, u32 *pCmdLen,
-		      u8 **pCmbBuffer, u8 *CmdStartSeq)
-{
-	return	true;
-}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index ca0a7085445f..021e5879abcf 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -72,7 +72,6 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p
 	u32 h2c_cmd_ex = 0;
 	s32 ret = _FAIL;
 
-_func_enter_;
 
 	if (!adapt->bFWReady) {
 		DBG_88E("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n");
@@ -125,7 +124,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 
 	return ret;
 }
@@ -134,7 +132,6 @@ u8 rtl8188e_set_rssi_cmd(struct adapter *adapt, u8 *param)
 {
 	u8 res = _SUCCESS;
 	struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
-_func_enter_;
 
 	if (haldata->fw_ractrl) {
 		;
@@ -143,7 +140,6 @@ _func_enter_;
 		res = _FAIL;
 	}
 
-_func_exit_;
 
 	return res;
 }
@@ -154,7 +150,6 @@ u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask)
 	u8 res = _SUCCESS;
 	struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
 
-_func_enter_;
 	if (haldata->fw_ractrl) {
 		__le32 lmask;
 
@@ -168,7 +163,6 @@ _func_enter_;
 		res = _FAIL;
 	}
 
-_func_exit_;
 
 	return res;
 }
@@ -215,7 +209,6 @@ void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
 	struct setpwrmode_parm H2CSetPwrMode;
 	struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv;
 	u8 RLBM = 0; /*  0:Min, 1:Max, 2:User define */
-_func_enter_;
 
 	DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__,
 		Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable);
@@ -256,7 +249,6 @@ _func_enter_;
 
 	FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
 
-_func_exit_;
 }
 
 void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt)
@@ -617,7 +609,6 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 	u8 DLBcnCount = 0;
 	u32 poll = 0;
 
-_func_enter_;
 
 	DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
 
@@ -701,7 +692,6 @@ _func_enter_;
 		haldata->RegCR_1 &= (~BIT0);
 		rtw_write8(adapt,  REG_CR+1, haldata->RegCR_1);
 	}
-_func_exit_;
 }
 
 void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state)
@@ -712,7 +702,6 @@ void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state)
 	struct P2P_PS_Offload_t	*p2p_ps_offload = &haldata->p2p_ps_offload;
 	u8 i;
 
-_func_enter_;
 
 	switch (p2p_ps_state) {
 	case P2P_PS_DISABLE:
@@ -775,5 +764,4 @@ _func_enter_;
 	FillH2CCmd_88E(adapt, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);
 #endif
 
-_func_exit_;
 }
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
index 4c934e2e0911..cf88bf247c85 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
@@ -160,7 +160,6 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter)
 	u8 hw_init_completed = false;
 	struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
 
-	_func_enter_;
 	hw_init_completed = Adapter->hw_init_completed;
 
 	if (!hw_init_completed)
@@ -178,7 +177,6 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter)
 		/*  Calculate Tx/Rx statistics. */
 		dm_CheckStatistics(Adapter);
 
-	_func_exit_;
 	}
 
 	/* ODM */
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index 5921db86547f..f9d5558431e0 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -20,6 +20,7 @@
 #define _HAL_INIT_C_
 
 #include <linux/firmware.h>
+#include <linux/vmalloc.h>
 #include <drv_types.h>
 #include <rtw_efuse.h>
 
@@ -365,7 +366,7 @@ void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int data_len)
 	u32 fifo_data, reg_140;
 	u32 addr, rstatus, loop = 0;
 	u16 data_cnts = (data_len/8)+1;
-	u8 *pbuf = rtw_zvmalloc(data_len+10);
+	u8 *pbuf = vzalloc(data_len+10);
 	DBG_88E("###### %s ######\n", __func__);
 
 	rtw_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
@@ -387,7 +388,7 @@ void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int data_len)
 			} while (!rstatus && (loop++ < 10));
 		}
 		rtw_IOL_cmd_buf_dump(Adapter, data_len, pbuf);
-		rtw_vmfree(pbuf, data_len+10);
+		vfree(pbuf);
 	}
 	DBG_88E("###### %s ######\n", __func__);
 }
@@ -583,59 +584,70 @@ static s32 _FWFreeToGo(struct adapter *padapter)
 
 #define IS_FW_81xxC(padapter)	(((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
 
-s32 rtl8188e_FirmwareDownload(struct adapter *padapter)
+static int load_firmware(struct rt_firmware *pFirmware, struct device *device)
 {
-	s32	rtStatus = _SUCCESS;
-	u8 writeFW_retry = 0;
-	u32 fwdl_start_time;
-	struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
-	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-	struct device *device = dvobj_to_dev(dvobj);
-	struct rt_firmware *pFirmware = NULL;
+	int rtstatus = _SUCCESS;
 	const struct firmware *fw;
-	struct rt_firmware_hdr *pFwHdr = NULL;
-	u8 *pFirmwareBuf;
-	u32 FirmwareLen;
-	char fw_name[] = "rtlwifi/rtl8188eufw.bin";
-	static int log_version;
-
-	RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
-	pFirmware = (struct rt_firmware *)rtw_zmalloc(sizeof(struct rt_firmware));
-	if (!pFirmware) {
-		rtStatus = _FAIL;
-		goto Exit;
-	}
+	const char fw_name[] = "rtlwifi/rtl8188eufw.bin";
 
 	if (request_firmware(&fw, fw_name, device)) {
-		rtStatus = _FAIL;
-		goto Exit;
+		rtstatus = _FAIL;
+		goto exit;
 	}
 	if (!fw) {
 		pr_err("Firmware %s not available\n", fw_name);
-		rtStatus = _FAIL;
-		goto Exit;
+		rtstatus = _FAIL;
+		goto exit;
 	}
 	if (fw->size > FW_8188E_SIZE) {
-		rtStatus = _FAIL;
-		RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE));
-		goto Exit;
+		rtstatus = _FAIL;
+		RT_TRACE(_module_hal_init_c_, _drv_err_,
+			 ("Firmware size exceed 0x%X. Check it.\n",
+			 FW_8188E_SIZE));
+		goto exit;
 	}
 
 	pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL);
 	if (!pFirmware->szFwBuffer) {
-		rtStatus = _FAIL;
-		goto Exit;
+		rtstatus = _FAIL;
+		goto exit;
 	}
 	memcpy(pFirmware->szFwBuffer, fw->data, fw->size);
 	pFirmware->ulFwLength = fw->size;
-	pFirmwareBuf = pFirmware->szFwBuffer;
-	FirmwareLen = pFirmware->ulFwLength;
 	release_firmware(fw);
 
-	DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, FirmwareLen);
+	DBG_88E_LEVEL(_drv_info_,
+		      "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__,
+		      pFirmware->ulFwLength);
+exit:
+	return rtstatus;
+}
+
+s32 rtl8188e_FirmwareDownload(struct adapter *padapter)
+{
+	s32	rtStatus = _SUCCESS;
+	u8 writeFW_retry = 0;
+	u32 fwdl_start_time;
+	struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct device *device = dvobj_to_dev(dvobj);
+	struct rt_firmware_hdr *pFwHdr = NULL;
+	u8 *pFirmwareBuf;
+	u32 FirmwareLen;
+	static int log_version;
+
+	RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
+	if (!dvobj->firmware.szFwBuffer)
+		rtStatus = load_firmware(&dvobj->firmware, device);
+	if (rtStatus == _FAIL) {
+		dvobj->firmware.szFwBuffer = NULL;
+		goto Exit;
+	}
+	pFirmwareBuf = dvobj->firmware.szFwBuffer;
+	FirmwareLen = dvobj->firmware.ulFwLength;
 
 	/*  To Check Fw header. Added by tynli. 2009.12.04. */
-	pFwHdr = (struct rt_firmware_hdr *)pFirmware->szFwBuffer;
+	pFwHdr = (struct rt_firmware_hdr *)dvobj->firmware.szFwBuffer;
 
 	pHalData->FirmwareVersion =  le16_to_cpu(pFwHdr->Version);
 	pHalData->FirmwareSubVersion = pFwHdr->Subversion;
@@ -687,10 +699,7 @@ s32 rtl8188e_FirmwareDownload(struct adapter *padapter)
 		goto Exit;
 	}
 	RT_TRACE(_module_hal_init_c_, _drv_info_, ("Firmware is ready to run!\n"));
-	kfree(pFirmware->szFwBuffer);
 Exit:
-
-	kfree(pFirmware);
 	return rtStatus;
 }
 
@@ -707,10 +716,8 @@ void rtl8188e_InitializeFirmwareVars(struct adapter *padapter)
 
 static void rtl8188e_free_hal_data(struct adapter *padapter)
 {
-_func_enter_;
 	kfree(padapter->HalData);
 	padapter->HalData = NULL;
-_func_exit_;
 }
 
 /*  */
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c b/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c
index 3d0e6c9e0310..cc71784b8d73 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c
@@ -184,12 +184,12 @@ void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven)
 		TempCCk = read_bbreg(pAdapter, rCCK0_TxFilter2, bMaskDWord) & bMaskCCK;
 		for (i = 0; i < CCK_TABLE_SIZE; i++) {
 			if (pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
-				if (_rtw_memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4)) {
+				if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4)) {
 					CCK_index_old = (u8)i;
 					break;
 				}
 			} else {
-				if (_rtw_memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4)) {
+				if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4)) {
 					CCK_index_old = (u8)i;
 					break;
 				}
@@ -201,6 +201,8 @@ void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven)
 		else
 			CCK_index = CCK_index_old + 1;
 
+		if (CCK_index > 32)
+			CCK_index = 32;
 		/* Adjust CCK according to gain index */
 		if (!pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
 			rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]);
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
index 511f61cbb9e0..43eb960e4e0b 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
@@ -23,9 +23,9 @@
 #include <drv_types.h>
 #include <rtl8188e_hal.h>
 
-static void process_rssi(struct adapter *padapter, union recv_frame *prframe)
+static void process_rssi(struct adapter *padapter, struct recv_frame *prframe)
 {
-	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	struct rx_pkt_attrib *pattrib = &prframe->attrib;
 	struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
 
 	if (signal_stat->update_req) {
@@ -39,7 +39,8 @@ static void process_rssi(struct adapter *padapter, union recv_frame *prframe)
 	signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
 } /*  Process_UI_RSSI_8192C */
 
-static void process_link_qual(struct adapter *padapter, union recv_frame *prframe)
+static void process_link_qual(struct adapter *padapter,
+			      struct recv_frame *prframe)
 {
 	struct rx_pkt_attrib *pattrib;
 	struct signal_stat *signal_stat;
@@ -47,7 +48,7 @@ static void process_link_qual(struct adapter *padapter, union recv_frame *prfram
 	if (prframe == NULL || padapter == NULL)
 		return;
 
-	pattrib = &prframe->u.hdr.attrib;
+	pattrib = &prframe->attrib;
 	signal_stat = &padapter->recvpriv.signal_qual_data;
 
 	if (signal_stat->update_req) {
@@ -63,7 +64,7 @@ static void process_link_qual(struct adapter *padapter, union recv_frame *prfram
 
 void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe)
 {
-	union recv_frame *precvframe = (union recv_frame *)prframe;
+	struct recv_frame *precvframe = (struct recv_frame *)prframe;
 
 	/*  Check RSSI */
 	process_rssi(padapter, precvframe);
@@ -71,7 +72,8 @@ void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe)
 	process_link_qual(padapter,  precvframe);
 }
 
-void update_recvframe_attrib_88e(union recv_frame *precvframe, struct recv_stat *prxstat)
+void update_recvframe_attrib_88e(struct recv_frame *precvframe,
+				 struct recv_stat *prxstat)
 {
 	struct rx_pkt_attrib	*pattrib;
 	struct recv_stat	report;
@@ -83,7 +85,7 @@ void update_recvframe_attrib_88e(union recv_frame *precvframe, struct recv_stat
 	report.rxdw4 = prxstat->rxdw4;
 	report.rxdw5 = prxstat->rxdw5;
 
-	pattrib = &precvframe->u.hdr.attrib;
+	pattrib = &precvframe->attrib;
 	_rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
 
 	pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);/* u8)prxreport->crc32; */
@@ -136,12 +138,13 @@ void update_recvframe_attrib_88e(union recv_frame *precvframe, struct recv_stat
 /*
  * Notice:
  *	Before calling this function,
- *	precvframe->u.hdr.rx_data should be ready!
+ *	precvframe->rx_data should be ready!
  */
-void update_recvframe_phyinfo_88e(union recv_frame *precvframe, struct phy_stat *pphy_status)
+void update_recvframe_phyinfo_88e(struct recv_frame *precvframe,
+				  struct phy_stat *pphy_status)
 {
-	struct adapter *padapter = precvframe->u.hdr.adapter;
-	struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
+	struct adapter *padapter = precvframe->adapter;
+	struct rx_pkt_attrib *pattrib = &precvframe->attrib;
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
 	struct odm_phy_status_info *pPHYInfo  = (struct odm_phy_status_info *)(&pattrib->phy_info);
 	u8 *wlanhdr;
@@ -154,15 +157,15 @@ void update_recvframe_phyinfo_88e(union recv_frame *precvframe, struct phy_stat
 	pkt_info.bPacketToSelf = false;
 	pkt_info.bPacketBeacon = false;
 
-	wlanhdr = get_recvframe_data(precvframe);
+	wlanhdr = precvframe->rx_data;
 
 	pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) &&
 		!pattrib->icv_err && !pattrib->crc_err &&
-		_rtw_memcmp(get_hdr_bssid(wlanhdr),
+		!memcmp(get_hdr_bssid(wlanhdr),
 		 get_bssid(&padapter->mlmepriv), ETH_ALEN));
 
 	pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
-				 (_rtw_memcmp(get_da(wlanhdr),
+				 (!memcmp(get_da(wlanhdr),
 				  myid(&padapter->eeprompriv), ETH_ALEN));
 
 	pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
@@ -185,17 +188,17 @@ void update_recvframe_phyinfo_88e(union recv_frame *precvframe, struct phy_stat
 
 	ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info));
 
-	precvframe->u.hdr.psta = NULL;
+	precvframe->psta = NULL;
 	if (pkt_info.bPacketMatchBSSID &&
 	    (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE))) {
 		if (psta) {
-			precvframe->u.hdr.psta = psta;
+			precvframe->psta = psta;
 			rtl8188e_process_phy_info(padapter, precvframe);
 		}
 	} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
 		if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
 			if (psta)
-				precvframe->u.hdr.psta = psta;
+				precvframe->psta = psta;
 		}
 		rtl8188e_process_phy_info(padapter, precvframe);
 	}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
index 17c94f4cc477..b1b1584af1cd 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
@@ -22,9 +22,6 @@
 #include <drv_types.h>
 #include <recv_osdep.h>
 #include <mlme_osdep.h>
-#include <ip.h>
-#include <if_ether.h>
-#include <ethernet.h>
 
 #include <usb_ops.h>
 #include <wifi.h>
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
index 6fb6a46f04fe..3476f8898330 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -537,11 +537,11 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp
 	spin_lock_bh(&pxmitpriv->lock);
 
 	xmitframe_phead = get_list_head(&ptxservq->sta_pending);
-	xmitframe_plist = get_next(xmitframe_phead);
+	xmitframe_plist = xmitframe_phead->next;
 
 	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
-		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-		xmitframe_plist = get_next(xmitframe_plist);
+		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+		xmitframe_plist = xmitframe_plist->next;
 
 		pxmitframe->agg_num = 0; /*  not first frame of aggregation */
 		pxmitframe->pkt_offset = 0; /*  not first frame of aggregation, no need to reserve offset */
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
index b24ad495062c..c92067f0ef15 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -709,7 +709,6 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 
 	#define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
 
-_func_enter_;
 
 	HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN);
 
@@ -967,7 +966,6 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
 
 	DBG_88E("%s in %dms\n", __func__, rtw_get_passing_time_ms(init_start_time));
 
-_func_exit_;
 
 	return status;
 }
@@ -1084,7 +1082,6 @@ static unsigned int rtl8188eu_inirp_init(struct adapter *Adapter)
 	struct recv_priv *precvpriv = &(Adapter->recvpriv);
 	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
 
-_func_enter_;
 
 	_read_port = pintfhdl->io_ops._read_port;
 
@@ -1112,7 +1109,6 @@ exit:
 
 	RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("<=== usb_inirp_init\n"));
 
-_func_exit_;
 
 	return status;
 }
@@ -1402,7 +1398,6 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 	struct hal_data_8188e	*haldata = GET_HAL_DATA(Adapter);
 	struct dm_priv	*pdmpriv = &haldata->dmpriv;
 	struct odm_dm_struct *podmpriv = &haldata->odmpriv;
-_func_enter_;
 
 	switch (variable) {
 	case HW_VAR_MEDIA_STATUS:
@@ -1921,14 +1916,12 @@ _func_enter_;
 	default:
 		break;
 	}
-_func_exit_;
 }
 
 static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 {
 	struct hal_data_8188e	*haldata = GET_HAL_DATA(Adapter);
 	struct odm_dm_struct *podmpriv = &haldata->odmpriv;
-_func_enter_;
 
 	switch (variable) {
 	case HW_VAR_BASIC_RATE:
@@ -1980,7 +1973,6 @@ _func_enter_;
 		break;
 	}
 
-_func_exit_;
 }
 
 /*  */
@@ -2302,7 +2294,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt)
 {
 	struct hal_ops	*halfunc = &adapt->HalFunc;
 
-_func_enter_;
 
 	adapt->HalData = rtw_zmalloc(sizeof(struct hal_data_8188e));
 	if (adapt->HalData == NULL)
@@ -2342,5 +2333,4 @@ _func_enter_;
 	halfunc->interface_ps_func = &rtl8188eu_ps_func;
 
 	rtl8188e_set_hal_ops(halfunc);
-_func_exit_;
 }
diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
index 31ae21a54c92..1fa5370f1da6 100644
--- a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
@@ -111,7 +111,7 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u
 			break;
 	}
 release_mutex:
-	_exit_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+	mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
 exit:
 	return status;
 }
@@ -125,7 +125,6 @@ static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
 	u16 len;
 	u8 data = 0;
 
-	_func_enter_;
 
 	request = 0x05;
 	requesttype = 0x01;/* read_in */
@@ -136,7 +135,6 @@ static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
 
 	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
 
-	_func_exit_;
 
 	return data;
 
@@ -151,14 +149,12 @@ static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
 	u16 len;
 	__le32 data;
 
-_func_enter_;
 	request = 0x05;
 	requesttype = 0x01;/* read_in */
 	index = 0;/* n/a */
 	wvalue = (u16)(addr&0x0000ffff);
 	len = 2;
 	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-_func_exit_;
 
 	return (u16)(le32_to_cpu(data)&0xffff);
 }
@@ -172,7 +168,6 @@ static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
 	u16 len;
 	__le32 data;
 
-_func_enter_;
 
 	request = 0x05;
 	requesttype = 0x01;/* read_in */
@@ -183,7 +178,6 @@ _func_enter_;
 
 	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
 
-_func_exit_;
 
 	return le32_to_cpu(data);
 }
@@ -198,7 +192,6 @@ static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
 	u8 data;
 	int ret;
 
-	_func_enter_;
 	request = 0x05;
 	requesttype = 0x00;/* write_out */
 	index = 0;/* n/a */
@@ -206,7 +199,6 @@ static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
 	len = 1;
 	data = val;
 	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-	_func_exit_;
 	return ret;
 }
 
@@ -220,7 +212,6 @@ static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
 	__le32 data;
 	int ret;
 
-	_func_enter_;
 
 	request = 0x05;
 	requesttype = 0x00;/* write_out */
@@ -233,7 +224,6 @@ static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
 
 	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
 
-	_func_exit_;
 
 	return ret;
 }
@@ -248,7 +238,6 @@ static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
 	__le32 data;
 	int ret;
 
-	_func_enter_;
 
 	request = 0x05;
 	requesttype = 0x00;/* write_out */
@@ -260,7 +249,6 @@ static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
 
 	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
 
-	_func_exit_;
 
 	return ret;
 }
@@ -275,7 +263,6 @@ static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata
 	u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
 	int ret;
 
-	_func_enter_;
 
 	request = 0x05;
 	requesttype = 0x00;/* write_out */
@@ -287,7 +274,6 @@ static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata
 
 	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
 
-	_func_exit_;
 
 	return ret;
 }
@@ -320,7 +306,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
 	struct recv_stat	*prxstat;
 	struct phy_stat	*pphy_status = NULL;
 	struct sk_buff *pkt_copy = NULL;
-	union recv_frame	*precvframe = NULL;
+	struct recv_frame	*precvframe = NULL;
 	struct rx_pkt_attrib	*pattrib = NULL;
 	struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
 	struct recv_priv	*precvpriv = &adapt->recvpriv;
@@ -346,13 +332,13 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
 			goto _exit_recvbuf2recvframe;
 		}
 
-		_rtw_init_listhead(&precvframe->u.hdr.list);
-		precvframe->u.hdr.precvbuf = NULL;	/* can't access the precvbuf for new arch. */
-		precvframe->u.hdr.len = 0;
+		_rtw_init_listhead(&precvframe->list);
+		precvframe->precvbuf = NULL;	/* can't access the precvbuf for new arch. */
+		precvframe->len = 0;
 
 		update_recvframe_attrib_88e(precvframe, prxstat);
 
-		pattrib = &precvframe->u.hdr.attrib;
+		pattrib = &precvframe->attrib;
 
 		if ((pattrib->crc_err) || (pattrib->icv_err)) {
 			DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
@@ -399,26 +385,26 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
 		pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
 		if (pkt_copy) {
 			pkt_copy->dev = adapt->pnetdev;
-			precvframe->u.hdr.pkt = pkt_copy;
-			precvframe->u.hdr.rx_head = pkt_copy->data;
-			precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
+			precvframe->pkt = pkt_copy;
+			precvframe->rx_head = pkt_copy->data;
+			precvframe->rx_end = pkt_copy->data + alloc_sz;
 			skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
 			skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
 			memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
-			precvframe->u.hdr.rx_tail = pkt_copy->data;
-			precvframe->u.hdr.rx_data = pkt_copy->data;
+			precvframe->rx_tail = pkt_copy->data;
+			precvframe->rx_data = pkt_copy->data;
 		} else {
 			if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
 				DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
 				rtw_free_recvframe(precvframe, pfree_recv_queue);
 				goto _exit_recvbuf2recvframe;
 			}
-			precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC);
-			if (precvframe->u.hdr.pkt) {
-				precvframe->u.hdr.rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
-				precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_tail;
-				precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail;
-				precvframe->u.hdr.rx_end =  pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
+			precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
+			if (precvframe->pkt) {
+				precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
+				precvframe->rx_head = precvframe->rx_tail;
+				precvframe->rx_data = precvframe->rx_tail;
+				precvframe->rx_end =  pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
 			} else {
 				DBG_88E("recvbuf2recvframe: skb_clone fail\n");
 				rtw_free_recvframe(precvframe, pfree_recv_queue);
@@ -451,17 +437,17 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
 			/* enqueue recvframe to txrtp queue */
 			if (pattrib->pkt_rpt_type == TX_REPORT1) {
 				/* CCX-TXRPT ack for xmit mgmt frames. */
-				handle_txrpt_ccx_88e(adapt, precvframe->u.hdr.rx_data);
+				handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
 			} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
 				ODM_RA_TxRPT2Handle_8188E(
 							&haldata->odmpriv,
-							precvframe->u.hdr.rx_data,
+							precvframe->rx_data,
 							pattrib->pkt_len,
 							pattrib->MacIDValidEntry[0],
 							pattrib->MacIDValidEntry[1]
 							);
 			} else if (pattrib->pkt_rpt_type == HIS_REPORT) {
-				interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->u.hdr.rx_data);
+				interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data);
 			}
 			rtw_free_recvframe(precvframe, pfree_recv_queue);
 		}
@@ -519,7 +505,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
 		DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
 			__func__, adapt->bDriverStopped,
 			adapt->bSurpriseRemoved, adapt->bReadPortCancel);
-		goto exit;
+		return;
 	}
 
 	if (purb->status == 0) { /* SUCCESS */
@@ -579,9 +565,6 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
 			break;
 		}
 	}
-
-exit:
-_func_exit_;
 }
 
 static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
@@ -598,7 +581,6 @@ static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
 	size_t alignment = 0;
 	u32 ret = _SUCCESS;
 
-_func_enter_;
 
 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
 	    adapter->pwrctrlpriv.pnp_bstop_trx) {
@@ -672,7 +654,6 @@ _func_enter_;
 		ret = _FAIL;
 	}
 
-_func_exit_;
 	return ret;
 }
 
@@ -702,7 +683,6 @@ void rtl8188eu_xmit_tasklet(void *priv)
 
 void rtl8188eu_set_intf_ops(struct _io_ops	*pops)
 {
-	_func_enter_;
 	_rtw_memset((u8 *)pops, 0, sizeof(struct _io_ops));
 	pops->_read8 = &usb_read8;
 	pops->_read16 = &usb_read16;
@@ -717,7 +697,6 @@ void rtl8188eu_set_intf_ops(struct _io_ops	*pops)
 	pops->_write_port = &usb_write_port;
 	pops->_read_port_cancel = &usb_read_port_cancel;
 	pops->_write_port_cancel = &usb_write_port_cancel;
-	_func_exit_;
 }
 
 void rtl8188eu_set_hw_type(struct adapter *adapt)
diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h
index a492a1c547ae..936c196699af 100644
--- a/drivers/staging/rtl8188eu/include/drv_types.h
+++ b/drivers/staging/rtl8188eu/include/drv_types.h
@@ -159,9 +159,15 @@ struct registry_priv {
 
 #define MAX_CONTINUAL_URB_ERR		4
 
+struct rt_firmware {
+	u8			*szFwBuffer;
+	u32			ulFwLength;
+};
+
 struct dvobj_priv {
 	struct adapter *if1;
 	struct adapter *if2;
+	struct rt_firmware firmware;
 
 	/* For 92D, DMDP have 2 interface. */
 	u8	InterfaceNumber;
diff --git a/drivers/staging/rtl8188eu/include/ethernet.h b/drivers/staging/rtl8188eu/include/ethernet.h
deleted file mode 100644
index a59f9120cd7e..000000000000
--- a/drivers/staging/rtl8188eu/include/ethernet.h
+++ /dev/null
@@ -1,42 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-/*! \file */
-#ifndef __INC_ETHERNET_H
-#define __INC_ETHERNET_H
-
-#define ETHERNET_ADDRESS_LENGTH		6	/*  Ethernet Address Length */
-#define ETHERNET_HEADER_SIZE		14	/*  Ethernet Header Length */
-#define LLC_HEADER_SIZE			6	/*  LLC Header Length */
-#define TYPE_LENGTH_FIELD_SIZE		2	/*  Type/Length Size */
-#define MINIMUM_ETHERNET_PACKET_SIZE	60	/*  Min Ethernet Packet Size */
-#define MAXIMUM_ETHERNET_PACKET_SIZE	1514	/*  Max Ethernet Packet Size */
-
-/*  Is Multicast Address? */
-#define RT_ETH_IS_MULTICAST(_addr)	((((u8 *)(_addr))[0]&0x01) != 0)
-#define RT_ETH_IS_BROADCAST(_addr)	(			\
-		((u8 *)(_addr))[0] == 0xff &&		\
-		((u8 *)(_addr))[1] == 0xff &&		\
-		((u8 *)(_addr))[2] == 0xff &&		\
-		((u8 *)(_addr))[3] == 0xff &&		\
-		((u8 *)(_addr))[4] == 0xff &&		\
-		((u8 *)(_addr))[5] == 0xff)	/*  Is Broadcast Address? */
-
-
-#endif /*  #ifndef __INC_ETHERNET_H */
diff --git a/drivers/staging/rtl8188eu/include/h2clbk.h b/drivers/staging/rtl8188eu/include/h2clbk.h
deleted file mode 100644
index e595030ac8a3..000000000000
--- a/drivers/staging/rtl8188eu/include/h2clbk.h
+++ /dev/null
@@ -1,35 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-
-
-#define _H2CLBK_H_
-
-
-#include <rtl8711_spec.h>
-#include <TypeDef.h>
-
-
-void _lbk_cmd(struct adapter *adapter);
-
-void _lbk_rsp(struct adapter *adapter);
-
-void _lbk_evt(IN struct adapter *adapter);
-
-void h2c_event_callback(unsigned char *dev, unsigned char *pbuf);
diff --git a/drivers/staging/rtl8188eu/include/if_ether.h b/drivers/staging/rtl8188eu/include/if_ether.h
deleted file mode 100644
index db157712a203..000000000000
--- a/drivers/staging/rtl8188eu/include/if_ether.h
+++ /dev/null
@@ -1,111 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-
-#ifndef _LINUX_IF_ETHER_H
-#define _LINUX_IF_ETHER_H
-
-/*
- *	IEEE 802.3 Ethernet magic constants.  The frame sizes omit the preamble
- *	and FCS/CRC (frame check sequence).
- */
-
-#define ETH_ALEN	6		/* Octets in one ethernet addr	 */
-#define ETH_HLEN	14		/* Total octets in header.	 */
-#define ETH_ZLEN	60		/* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN	1500		/* Max. octets in payload	 */
-#define ETH_FRAME_LEN	1514		/* Max. octets in frame sans FCS */
-
-/*
- *	These are the defined Ethernet Protocol ID's.
- */
-
-#define ETH_P_LOOP	0x0060		/* Ethernet Loopback packet	*/
-#define ETH_P_PUP	0x0200		/* Xerox PUP packet		*/
-#define ETH_P_PUPAT	0x0201		/* Xerox PUP Addr Trans packet	*/
-#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
-#define ETH_P_X25	0x0805		/* CCITT X.25			*/
-#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
-#define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet  */
-#define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet   */
-#define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP		*/
-#define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
-#define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
-#define ETH_P_DNA_RC    0x6002          /* DEC DNA Remote Console       */
-#define ETH_P_DNA_RT    0x6003          /* DEC DNA Routing              */
-#define ETH_P_LAT       0x6004          /* DEC LAT                      */
-#define ETH_P_DIAG      0x6005          /* DEC Diagnostics              */
-#define ETH_P_CUST      0x6006          /* DEC Customer use             */
-#define ETH_P_SCA       0x6007          /* DEC Systems Comms Arch       */
-#define ETH_P_RARP      0x8035		/* Reverse Addr Res packet	*/
-#define ETH_P_ATALK	0x809B		/* Appletalk DDP		*/
-#define ETH_P_AARP	0x80F3		/* Appletalk AARP		*/
-#define ETH_P_8021Q	0x8100          /* 802.1Q VLAN Extended Header  */
-#define ETH_P_IPX	0x8137		/* IPX over DIX			*/
-#define ETH_P_IPV6	0x86DD		/* IPv6 over bluebook		*/
-#define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
-#define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
-#define ETH_P_ATMMPOA	0x884c		/* MultiProtocol Over ATM	*/
-#define ETH_P_ATMFATE	0x8884		/* Frame-based ATM Transport
-					 * over Ethernet
-					 */
-
-/*
- *	Non DIX types. Won't clash for 1500 types.
- */
-
-#define ETH_P_802_3	0x0001		/* Dummy type for 802.3 frames  */
-#define ETH_P_AX25	0x0002		/* Dummy protocol id for AX.25  */
-#define ETH_P_ALL	0x0003		/* Every packet (be careful!!!) */
-#define ETH_P_802_2	0x0004		/* 802.2 frames			*/
-#define ETH_P_SNAP	0x0005		/* Internal only		*/
-#define ETH_P_DDCMP     0x0006          /* DEC DDCMP: Internal only     */
-#define ETH_P_WAN_PPP   0x0007          /* Dummy type for WAN PPP frames*/
-#define ETH_P_PPP_MP    0x0008          /* Dummy type for PPP MP frames */
-#define ETH_P_LOCALTALK 0x0009		/* Localtalk pseudo type	*/
-#define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
-#define ETH_P_TR_802_2	0x0011		/* 802.2 frames			*/
-#define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@cafe.net)	*/
-#define ETH_P_CONTROL	0x0016		/* Card specific control frames */
-#define ETH_P_IRDA	0x0017		/* Linux-IrDA			*/
-#define ETH_P_ECONET	0x0018		/* Acorn Econet			*/
-
-/*
- *	This is an Ethernet frame header.
- */
-
-struct ethhdr {
-	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
-	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
-	unsigned short	h_proto;		/* packet type ID field	*/
-};
-
-struct _vlan {
-	unsigned short       h_vlan_TCI;	/*  Encap prio and VLAN ID */
-	unsigned short       h_vlan_encapsulated_proto;
-};
-
-#define get_vlan_id(pvlan)				\
-	((ntohs((unsigned short)pvlan->h_vlan_TCI)) & 0xfff)
-#define get_vlan_priority(pvlan)			\
-	((ntohs((unsigned short)pvlan->h_vlan_TCI))>>13)
-#define get_vlan_encap_proto(pvlan)			\
-	 (ntohs((unsigned short)pvlan->h_vlan_encapsulated_proto))
-
-#endif	/* _LINUX_IF_ETHER_H */
diff --git a/drivers/staging/rtl8188eu/include/ioctl_cfg80211.h b/drivers/staging/rtl8188eu/include/ioctl_cfg80211.h
deleted file mode 100644
index 037e9a5e5af9..000000000000
--- a/drivers/staging/rtl8188eu/include/ioctl_cfg80211.h
+++ /dev/null
@@ -1,107 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-#ifndef __IOCTL_CFG80211_H__
-#define __IOCTL_CFG80211_H__
-
-struct rtw_wdev_invit_info {
-	u8 token;
-	u8 flags;
-	u8 status;
-	u8 req_op_ch;
-	u8 rsp_op_ch;
-};
-
-#define rtw_wdev_invit_info_init(invit_info) \
-	do { \
-		(invit_info)->token = 0; \
-		(invit_info)->flags = 0x00; \
-		(invit_info)->status = 0xff; \
-		(invit_info)->req_op_ch = 0; \
-		(invit_info)->rsp_op_ch = 0; \
-	} while (0)
-
-struct rtw_wdev_priv {
-	struct wireless_dev *rtw_wdev;
-
-	struct adapter *padapter;
-
-	struct cfg80211_scan_request *scan_request;
-	spinlock_t scan_req_lock;
-
-	struct net_device *pmon_ndev;/* for monitor interface */
-	char ifname_mon[IFNAMSIZ + 1]; /* name of monitor interface */
-
-	u8 p2p_enabled;
-
-	u8 provdisc_req_issued;
-
-	struct rtw_wdev_invit_info invit_info;
-
-	u8 bandroid_scan;
-	bool block;
-	bool power_mgmt;
-};
-
-#define wdev_to_priv(w) ((struct rtw_wdev_priv *)(wdev_priv(w)))
-
-#define wiphy_to_wdev(x)				\
-((struct wireless_dev *)(((struct rtw_wdev_priv *)wiphy_priv(x))->rtw_wdev))
-
-int rtw_wdev_alloc(struct adapter *padapter, struct device *dev);
-void rtw_wdev_free(struct wireless_dev *wdev);
-void rtw_wdev_unregister(struct wireless_dev *wdev);
-
-void rtw_cfg80211_init_wiphy(struct adapter *padapter);
-
-void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter);
-
-void rtw_cfg80211_indicate_connect(struct adapter *padapter);
-void rtw_cfg80211_indicate_disconnect(struct adapter *padapter);
-void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
-				     bool aborted);
-
-#ifdef CONFIG_88EU_AP_MODE
-void rtw_cfg80211_indicate_sta_assoc(struct adapter *padapter,
-				     u8 *pmgmt_frame, uint frame_len);
-void rtw_cfg80211_indicate_sta_disassoc(struct adapter *padapter,
-					unsigned char *da,
-					unsigned short reason);
-#endif /* CONFIG_88EU_AP_MODE */
-
-void rtw_cfg80211_issue_p2p_provision_request(struct adapter *padapter,
-					      const u8 *buf, size_t len);
-void rtw_cfg80211_rx_p2p_action_public(struct adapter *padapter,
-				       u8 *pmgmt_frame, uint frame_len);
-void rtw_cfg80211_rx_action_p2p(struct adapter *padapter, u8 *pmgmt_frame,
-				uint frame_len);
-void rtw_cfg80211_rx_action(struct adapter *adapter, u8 *frame,
-			    uint frame_len, const char *msg);
-
-int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net,
-				   char *buf, int len, int type);
-
-bool rtw_cfg80211_pwr_mgmt(struct adapter *adapter);
-
-#define rtw_cfg80211_rx_mgmt(dev, freq, sig_dbm, buf, len, gfp)		\
-	cfg80211_rx_mgmt(dev, freq, sig_dbm, buf, len, gfp)
-#define rtw_cfg80211_send_rx_assoc(dev, bss, buf, len)			\
-	cfg80211_send_rx_assoc(dev, bss, buf, len)
-
-#endif /* __IOCTL_CFG80211_H__ */
diff --git a/drivers/staging/rtl8188eu/include/ip.h b/drivers/staging/rtl8188eu/include/ip.h
deleted file mode 100644
index 9fdac6d42d17..000000000000
--- a/drivers/staging/rtl8188eu/include/ip.h
+++ /dev/null
@@ -1,126 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-#ifndef _LINUX_IP_H
-#define _LINUX_IP_H
-
-/* SOL_IP socket options */
-
-#define IPTOS_TOS_MASK		0x1E
-#define IPTOS_TOS(tos)		((tos)&IPTOS_TOS_MASK)
-#define	IPTOS_LOWDELAY		0x10
-#define	IPTOS_THROUGHPUT	0x08
-#define	IPTOS_RELIABILITY	0x04
-#define	IPTOS_MINCOST		0x02
-
-#define IPTOS_PREC_MASK		0xE0
-#define IPTOS_PREC(tos)		((tos)&IPTOS_PREC_MASK)
-#define IPTOS_PREC_NETCONTROL           0xe0
-#define IPTOS_PREC_INTERNETCONTROL      0xc0
-#define IPTOS_PREC_CRITIC_ECP           0xa0
-#define IPTOS_PREC_FLASHOVERRIDE        0x80
-#define IPTOS_PREC_FLASH                0x60
-#define IPTOS_PREC_IMMEDIATE            0x40
-#define IPTOS_PREC_PRIORITY             0x20
-#define IPTOS_PREC_ROUTINE              0x00
-
-
-/* IP options */
-#define IPOPT_COPY		0x80
-#define IPOPT_CLASS_MASK	0x60
-#define IPOPT_NUMBER_MASK	0x1f
-
-#define	IPOPT_COPIED(o)		((o)&IPOPT_COPY)
-#define	IPOPT_CLASS(o)		((o)&IPOPT_CLASS_MASK)
-#define	IPOPT_NUMBER(o)		((o)&IPOPT_NUMBER_MASK)
-
-#define	IPOPT_CONTROL		0x00
-#define	IPOPT_RESERVED1		0x20
-#define	IPOPT_MEASUREMENT	0x40
-#define	IPOPT_RESERVED2		0x60
-
-#define IPOPT_END	(0 | IPOPT_CONTROL)
-#define IPOPT_NOOP	(1 | IPOPT_CONTROL)
-#define IPOPT_SEC	(2 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_LSRR	(3 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_TIMESTAMP	(4 | IPOPT_MEASUREMENT)
-#define IPOPT_RR	(7 | IPOPT_CONTROL)
-#define IPOPT_SID	(8 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_SSRR	(9 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_RA	(20 | IPOPT_CONTROL | IPOPT_COPY)
-
-#define IPVERSION	4
-#define MAXTTL		255
-#define IPDEFTTL	64
-#define IPOPT_OPTVAL 0
-#define IPOPT_OLEN   1
-#define IPOPT_OFFSET 2
-#define IPOPT_MINOFF 4
-#define MAX_IPOPTLEN 40
-#define IPOPT_NOP IPOPT_NOOP
-#define IPOPT_EOL IPOPT_END
-#define IPOPT_TS  IPOPT_TIMESTAMP
-
-#define	IPOPT_TS_TSONLY		0	/* timestamps only */
-#define	IPOPT_TS_TSANDADDR	1	/* timestamps and addresses */
-#define	IPOPT_TS_PRESPEC	3	/* specified modules only */
-
-struct ip_options {
-	__u32		faddr;			/* Saved first hop address */
-	unsigned char	optlen;
-	unsigned char srr;
-	unsigned char rr;
-	unsigned char ts;
-	unsigned char	is_setbyuser:1,	/* Set by setsockopt?		*/
-			is_data:1,	/* Options in __data, rather than skb*/
-			is_strictroute:1,/* Strict source route		*/
-			srr_is_hit:1,	/* Packet destn addr was ours */
-			is_changed:1,	/* IP checksum more not valid	*/
-			rr_needaddr:1,	/* Need to record addr of out dev*/
-			ts_needtime:1,	/* Need to record timestamp	*/
-			ts_needaddr:1;	/* Need to record addr of out dev  */
-	unsigned char router_alert;
-	unsigned char __pad1;
-	unsigned char __pad2;
-	unsigned char __data[0];
-};
-
-#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
-
-struct iphdr {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8	ihl:4,
-		version:4;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	__u8	version:4,
-		ihl:4;
-#endif
-	__u8	tos;
-	__u16	tot_len;
-	__u16	id;
-	__u16	frag_off;
-	__u8	ttl;
-	__u8	protocol;
-	__u16	check;
-	__u32	saddr;
-	__u32	daddr;
-	/*The options start here. */
-};
-
-#endif	/* _LINUX_IP_H */
diff --git a/drivers/staging/rtl8188eu/include/nic_spec.h b/drivers/staging/rtl8188eu/include/nic_spec.h
deleted file mode 100644
index d42244788ca9..000000000000
--- a/drivers/staging/rtl8188eu/include/nic_spec.h
+++ /dev/null
@@ -1,44 +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.
- *
- * 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
- *
- *
- ******************************************************************************/
-
-
-#ifndef __NIC_SPEC_H__
-#define __NIC_SPEC_H__
-
-#define RTL8711_MCTRL_		(0x20000)
-#define RTL8711_UART_		(0x30000)
-#define RTL8711_TIMER_		(0x40000)
-#define RTL8711_FINT_		(0x50000)
-#define RTL8711_HINT_		(0x50000)
-#define RTL8711_GPIO_		(0x60000)
-#define RTL8711_WLANCTRL_	(0x200000)
-#define RTL8711_WLANFF_		(0xe00000)
-#define RTL8711_HCICTRL_	(0x600000)
-#define RTL8711_SYSCFG_		(0x620000)
-#define RTL8711_SYSCTRL_	(0x620000)
-#define RTL8711_MCCTRL_		(0x020000)
-
-
-#include <rtl8711_regdef.h>
-
-#include <rtl8711_bitdef.h>
-
-
-#endif /*  __RTL8711_SPEC_H__ */
diff --git a/drivers/staging/rtl8188eu/include/odm_interface.h b/drivers/staging/rtl8188eu/include/odm_interface.h
index a50eae3ec68e..548a309db199 100644
--- a/drivers/staging/rtl8188eu/include/odm_interface.h
+++ b/drivers/staging/rtl8188eu/include/odm_interface.h
@@ -77,32 +77,9 @@ typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
 
 /*  =========== EXtern Function Prototype */
 
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
-
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
-
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
-
-void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data);
-
-void ODM_Write2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 Data);
-
-void ODM_Write4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 Data);
-
 /*  Memory Relative Function. */
-void ODM_AllocateMemory(struct odm_dm_struct *pDM_Odm, void **pPtr, u32 length);
-void ODM_FreeMemory(struct odm_dm_struct *pDM_Odm, void *pPtr, u32 length);
-
-s32 ODM_CompareMemory(struct odm_dm_struct *pDM_Odm, void *pBuf1, void *pBuf2,
-		      u32 length);
 
 /*  ODM Timer relative API. */
-void ODM_SetTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer,
-		  u32 msDelay);
-
-void ODM_InitializeTimer(struct odm_dm_struct *pDM_Odm,
-			 struct timer_list *pTimer, void *CallBackFunc,
-			 void *pContext, const char *szID);
 
 void ODM_CancelTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer);
 
diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
index 7956f0cdb96b..5889f58ed7d3 100644
--- a/drivers/staging/rtl8188eu/include/osdep_service.h
+++ b/drivers/staging/rtl8188eu/include/osdep_service.h
@@ -62,20 +62,11 @@ struct	__queue	{
 	spinlock_t lock;
 };
 
-static inline struct list_head *get_next(struct list_head *list)
-{
-	return list->next;
-}
-
 static inline struct list_head *get_list_head(struct __queue *queue)
 {
 	return &(queue->queue);
 }
 
-
-#define LIST_CONTAINOR(ptr, type, member) \
-	((type *)((char *)(ptr)-(size_t)(&((type *)0)->member)))
-
 static inline int _enter_critical_mutex(struct mutex *pmutex,
 					unsigned long *pirqL)
 {
@@ -85,13 +76,6 @@ static inline int _enter_critical_mutex(struct mutex *pmutex,
 	return ret;
 }
 
-
-static inline void _exit_critical_mutex(struct mutex *pmutex,
-					unsigned long *pirqL)
-{
-		mutex_unlock(pmutex);
-}
-
 static inline void rtw_list_delete(struct list_head *plist)
 {
 	list_del_init(plist);
@@ -122,17 +106,6 @@ static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled)
 #define RTW_DECLARE_TIMER_HDL(name) \
 	void RTW_TIMER_HDL_NAME(name)(RTW_TIMER_HDL_ARGS)
 
-static inline void _init_workitem(struct work_struct *pwork, void *pfunc,
-				  void *cntx)
-{
-	INIT_WORK(pwork, pfunc);
-}
-
-static inline void _set_workitem(struct work_struct *pwork)
-{
-	schedule_work(pwork);
-}
-
 static inline void _cancel_workitem_sync(struct work_struct *pwork)
 {
 	cancel_work_sync(pwork);
@@ -230,15 +203,9 @@ extern unsigned char WPA_TKIP_CIPHER[4];
 extern unsigned char RSN_TKIP_CIPHER[4];
 
 #define rtw_update_mem_stat(flag, sz) do {} while (0)
-u8 *_rtw_vmalloc(u32 sz);
-u8 *_rtw_zvmalloc(u32 sz);
-void _rtw_vmfree(u8 *pbuf, u32 sz);
 u8 *_rtw_zmalloc(u32 sz);
 u8 *_rtw_malloc(u32 sz);
 void _rtw_mfree(u8 *pbuf, u32 sz);
-#define rtw_vmalloc(sz)			_rtw_vmalloc((sz))
-#define rtw_zvmalloc(sz)			_rtw_zvmalloc((sz))
-#define rtw_vmfree(pbuf, sz)		_rtw_vmfree((pbuf), (sz))
 #define rtw_malloc(sz)			_rtw_malloc((sz))
 #define rtw_zmalloc(sz)			_rtw_zmalloc((sz))
 #define rtw_mfree(pbuf, sz)		_rtw_mfree((pbuf), (sz))
@@ -247,7 +214,6 @@ void *rtw_malloc2d(int h, int w, int size);
 void rtw_mfree2d(void *pbuf, int h, int w, int size);
 
 void _rtw_memcpy(void *dec, void *sour, u32 sz);
-int  _rtw_memcmp(void *dst, void *src, u32 sz);
 void _rtw_memset(void *pbuf, int c, u32 sz);
 
 void _rtw_init_listhead(struct list_head *list);
diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h
index 691238078075..d76cc2db5028 100644
--- a/drivers/staging/rtl8188eu/include/recv_osdep.h
+++ b/drivers/staging/rtl8188eu/include/recv_osdep.h
@@ -28,18 +28,20 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
 void _rtw_free_recv_priv(struct recv_priv *precvpriv);
 
 
-s32  rtw_recv_entry(union recv_frame *precv_frame);
-int rtw_recv_indicatepkt(struct adapter *adapter, union recv_frame *recv_frame);
+s32  rtw_recv_entry(struct recv_frame *precv_frame);
+int rtw_recv_indicatepkt(struct adapter *adapter,
+			 struct recv_frame *recv_frame);
 void rtw_recv_returnpacket(struct  net_device *cnxt, struct sk_buff *retpkt);
 
-void rtw_hostapd_mlme_rx(struct adapter *padapter, union recv_frame *recv_fr);
+void rtw_hostapd_mlme_rx(struct adapter *padapter, struct recv_frame *recv_fr);
 void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup);
 
 int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
 void rtw_free_recv_priv(struct recv_priv *precvpriv);
 
 int rtw_os_recv_resource_init(struct recv_priv *recvpr, struct adapter *adapt);
-int rtw_os_recv_resource_alloc(struct adapter *adapt, union recv_frame *recvfr);
+int rtw_os_recv_resource_alloc(struct adapter *adapt,
+			       struct recv_frame *recvfr);
 void rtw_os_recv_resource_free(struct recv_priv *precvpriv);
 
 int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
index 161f1e5af9e6..75e41c4aeb27 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
@@ -76,17 +76,6 @@
 	(le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300 ||	\
 	(le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88E0)
 
-enum firmware_source {
-	FW_SOURCE_IMG_FILE = 0,
-	FW_SOURCE_HEADER_FILE = 1,		/* from header file */
-};
-
-struct rt_firmware {
-	enum firmware_source	eFWSource;
-	u8			*szFwBuffer;
-	u32			ulFwLength;
-};
-
 /*  This structure must be careful with byte-ordering */
 
 struct rt_firmware_hdr {
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
index a8facf00eac0..07e5f5227336 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
@@ -61,9 +61,10 @@ s32 rtl8188eu_init_recv_priv(struct adapter *padapter);
 void rtl8188eu_free_recv_priv(struct adapter *padapter);
 void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf);
 void rtl8188eu_recv_tasklet(void *priv);
-void rtl8188e_query_rx_phy_status(union recv_frame *fr, struct phy_stat *phy);
+void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy);
 void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe);
-void update_recvframe_phyinfo_88e(union recv_frame *fra, struct phy_stat *phy);
-void update_recvframe_attrib_88e(union recv_frame *fra, struct recv_stat *stat);
+void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy);
+void update_recvframe_attrib_88e(struct recv_frame *fra,
+				 struct recv_stat *stat);
 
 #endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h
index c6b193a2e795..ae05141f5ddf 100644
--- a/drivers/staging/rtl8188eu/include/rtw_debug.h
+++ b/drivers/staging/rtl8188eu/include/rtw_debug.h
@@ -99,20 +99,6 @@ extern u32 GlobalDebugLevel;
 		}							\
 	} while (0)
 
-#define _func_enter_							\
-	do {								\
-		if (GlobalDebugLevel >= _drv_debug_)			\
-			pr_info("%s : %s enters at %d\n",		\
-				 DRIVER_PREFIX, __func__, __LINE__);	\
-	} while (0)
-
-#define _func_exit_							\
-	do {								\
-		if (GlobalDebugLevel >= _drv_debug_)			\
-			pr_info("%s : %s exits at %d\n",		\
-				 DRIVER_PREFIX, __func__, __LINE__);	\
-	} while (0)
-
 #define RT_PRINT_DATA(_comp, _level, _titlestring, _hexdata, _hexdatalen)\
 	do {								\
 		if (_level <= GlobalDebugLevel) {			\
@@ -277,14 +263,4 @@ int proc_get_rssi_disp(char *page, char **start,
 int proc_set_rssi_disp(struct file *file, const char __user *buffer,
 		       unsigned long count, void *data);
 
-#ifdef CONFIG_BT_COEXIST
-int proc_get_btcoex_dbg(char *page, char **start,
-			off_t offset, int count,
-			int *eof, void *data);
-
-int proc_set_btcoex_dbg(struct file *file, const char *buffer,
-			signed long count, void *data);
-
-#endif /* CONFIG_BT_COEXIST */
-
 #endif	/* __RTW_DEBUG_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_io.h b/drivers/staging/rtl8188eu/include/rtw_io.h
index 3d1dfcc1b603..e8790f8f913e 100644
--- a/drivers/staging/rtl8188eu/include/rtw_io.h
+++ b/drivers/staging/rtl8188eu/include/rtw_io.h
@@ -99,7 +99,6 @@
 
 struct intf_priv;
 struct intf_hdl;
-struct io_queue;
 
 struct _io_ops {
 	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
@@ -117,7 +116,6 @@ struct _io_ops {
 			  u8 *pmem);
 	void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
 			   u8 *pmem);
-	void (*_sync_irp_protocol_rw)(struct io_queue *pio_q);
 	u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr);
 	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
 			  u8 *pmem);
@@ -237,34 +235,11 @@ struct reg_protocol_wt {
 Below is the data structure used by _io_handler
 */
 
-struct io_queue {
-	spinlock_t lock;
-	struct list_head free_ioreqs;
-	struct list_head pending;	/* The io_req list that will be served
-					 * in the single protocol read/write.*/
-	struct list_head processing;
-	u8	*free_ioreqs_buf; /*  4-byte aligned */
-	u8	*pallocated_free_ioreqs_buf;
-	struct	intf_hdl	intf;
-};
-
 struct io_priv {
 	struct adapter *padapter;
 	struct intf_hdl intf;
 };
 
-uint ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue);
-void sync_ioreq_enqueue(struct io_req *preq, struct io_queue *ioqueue);
-uint sync_ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue);
-uint free_ioreq(struct io_req *preq, struct io_queue *pio_queue);
-struct io_req *alloc_ioreq(struct io_queue *pio_q);
-
-uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl);
-void unregister_intf_hdl(struct intf_hdl *pintfhdl);
-
-void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-
 u8 _rtw_read8(struct adapter *adapter, u32 addr);
 u16 _rtw_read16(struct adapter *adapter, u32 addr);
 u32 _rtw_read32(struct adapter *adapter, u32 addr);
@@ -363,25 +338,6 @@ void async_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 int rtw_init_io_priv(struct adapter *padapter,
 		     void (*set_intf_ops)(struct _io_ops *pops));
 
-uint alloc_io_queue(struct adapter *adapter);
-void free_io_queue(struct adapter *adapter);
-void async_bus_io(struct io_queue *pio_q);
-void bus_sync_io(struct io_queue *pio_q);
-u32 _ioreq2rwmem(struct io_queue *pio_q);
 void dev_power_down(struct adapter *Adapter, u8 bpwrup);
 
-#define PlatformEFIOWrite1Byte(_a, _b, _c)		\
-	rtw_write8(_a, _b, _c)
-#define PlatformEFIOWrite2Byte(_a, _b, _c)		\
-	rtw_write16(_a, _b, _c)
-#define PlatformEFIOWrite4Byte(_a, _b, _c)		\
-	rtw_write32(_a, _b, _c)
-
-#define PlatformEFIORead1Byte(_a, _b)		\
-		rtw_read8(_a, _b)
-#define PlatformEFIORead2Byte(_a, _b)		\
-		rtw_read16(_a, _b)
-#define PlatformEFIORead4Byte(_a, _b)		\
-		rtw_read32(_a, _b)
-
 #endif	/* _RTL8711_IO_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h
index 8772d1d178c6..f3aa924f2029 100644
--- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h
+++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h
@@ -102,8 +102,6 @@ struct oid_obj_priv {
 
 #if defined(_RTW_MP_IOCTL_C_)
 static int oid_null_function(struct oid_par_priv *poid_par_priv) {
-	_func_enter_;
-	_func_exit_;
 	return NDIS_STATUS_SUCCESS;
 }
 #endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
index 6cd988f867da..45c22efe93fe 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h
@@ -106,13 +106,6 @@ SHALL not lock up more than one lock at a time!
 #define traffic_threshold	10
 #define	traffic_scan_period	500
 
-struct sitesurvey_ctrl {
-	u64	last_tx_pkts;
-	uint	last_rx_pkts;
-	int	traffic_busy;
-	struct timer_list sitesurvey_ctrl_timer;
-};
-
 struct rt_link_detect {
 	u32	NumTxOkInPeriod;
 	u32	NumRxOkInPeriod;
@@ -304,31 +297,6 @@ struct wifidirect_info {
 	u32 noa_start_time[P2P_MAX_NOA_NUM];
 };
 
-struct tdls_ss_record {	/* signal strength record */
-	u8 macaddr[ETH_ALEN];
-	u8 RxPWDBAll;
-	u8 is_tdls_sta;	/*  true: direct link sta, false: else */
-};
-
-struct tdls_info {
-	u8 ap_prohibited;
-	uint setup_state;
-	u8 sta_cnt;
-	u8 sta_maximum;	/*  1:tdls sta is equal (NUM_STA-1), reach max direct link number; 0: else; */
-	struct tdls_ss_record	ss_record;
-	u8 macid_index;	/* macid entry that is ready to write */
-	u8 clear_cam;	/* cam entry that is trying to clear, using it in direct link teardown */
-	u8 ch_sensing;
-	u8 cur_channel;
-	u8 candidate_ch;
-	u8 collect_pkt_num[MAX_CHANNEL_NUM];
-	spinlock_t cmd_lock;
-	spinlock_t hdl_lock;
-	u8 watchdog_count;
-	u8 dev_discovered;		/* WFD_TDLS: for sigma test */
-	u8 enable;
-};
-
 struct mlme_priv {
 	spinlock_t lock;
 	int fw_state;	/* shall we protect this variable? maybe not necessarily... */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
index f0c982d6d5f2..09e2a3980ea7 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
@@ -236,13 +236,13 @@ enum SCAN_STATE {
 struct mlme_handler {
 	unsigned int   num;
 	char *str;
-	unsigned int (*func)(struct adapter *adapt, union recv_frame *frame);
+	unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
 };
 
 struct action_handler {
 	unsigned int   num;
 	char *str;
-	unsigned int (*func)(struct adapter *adapt, union recv_frame *frame);
+	unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
 };
 
 struct	ss_res {
@@ -490,7 +490,7 @@ int allocate_fw_sta_entry(struct adapter *padapter);
 void flush_all_cam_entry(struct adapter *padapter);
 
 void site_survey(struct adapter *padapter);
-u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame,
+u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame,
 		    struct wlan_bssid_ex *bssid);
 void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
 		    struct adapter *adapter, bool update_ie);
@@ -544,7 +544,8 @@ unsigned int is_ap_in_wep(struct adapter *padapter);
 unsigned int should_forbid_n_rate(struct adapter *padapter);
 
 void report_join_res(struct adapter *padapter, int res);
-void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame);
+void report_survey_event(struct adapter *padapter,
+			 struct recv_frame *precv_frame);
 void report_surveydone_event(struct adapter *padapter);
 void report_del_sta_event(struct adapter *padapter,
 			  unsigned char *addr, unsigned short reason);
@@ -609,46 +610,46 @@ void start_clnt_join(struct adapter *padapter);
 void start_create_ibss(struct adapter *padapter);
 
 unsigned int OnAssocReq(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int OnAssocRsp(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int OnProbeReq(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int OnProbeRsp(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int DoReserved(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int OnBeacon(struct adapter *padapter,
-		      union recv_frame *precv_frame);
+		      struct recv_frame *precv_frame);
 unsigned int OnAtim(struct adapter *padapter,
-		    union recv_frame *precv_frame);
+		    struct recv_frame *precv_frame);
 unsigned int OnDisassoc(struct adapter *padapter,
-			union recv_frame *precv_frame);
+			struct recv_frame *precv_frame);
 unsigned int OnAuth(struct adapter *padapter,
-		    union recv_frame *precv_frame);
+		    struct recv_frame *precv_frame);
 unsigned int OnAuthClient(struct adapter *padapter,
-			  union recv_frame *precv_frame);
+			  struct recv_frame *precv_frame);
 unsigned int OnDeAuth(struct adapter *padapter,
-		      union recv_frame *precv_frame);
+		      struct recv_frame *precv_frame);
 unsigned int OnAction(struct adapter *padapter,
-		      union recv_frame *precv_frame);
+		      struct recv_frame *precv_frame);
 
 unsigned int on_action_spct(struct adapter *padapter,
-			    union recv_frame *precv_frame);
+			    struct recv_frame *precv_frame);
 unsigned int OnAction_qos(struct adapter *padapter,
-			  union recv_frame *precv_frame);
+			  struct recv_frame *precv_frame);
 unsigned int OnAction_dls(struct adapter *padapter,
-			  union recv_frame *precv_frame);
+			  struct recv_frame *precv_frame);
 unsigned int OnAction_back(struct adapter *padapter,
-			   union recv_frame *precv_frame);
+			   struct recv_frame *precv_frame);
 unsigned int on_action_public(struct adapter *padapter,
-			      union recv_frame *precv_frame);
+			      struct recv_frame *precv_frame);
 unsigned int OnAction_ht(struct adapter *padapter,
-			 union recv_frame *precv_frame);
+			 struct recv_frame *precv_frame);
 unsigned int OnAction_wmm(struct adapter *padapter,
-			  union recv_frame *precv_frame);
+			  struct recv_frame *precv_frame);
 unsigned int OnAction_p2p(struct adapter *padapter,
-			  union recv_frame *precv_frame);
+			  struct recv_frame *precv_frame);
 
 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res);
 void mlmeext_sta_del_event_callback(struct adapter *padapter);
diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
index 4a0e9ff3d479..9a42859d612b 100644
--- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
+++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
@@ -206,10 +206,6 @@ struct pwrctrl_priv {
 
 	u8		bInternalAutoSuspend;
 	u8		bInSuspend;
-#ifdef	CONFIG_BT_COEXIST
-	u8		bAutoResume;
-	u8		autopm_cnt;
-#endif
 	u8		bSupportRemoteWakeup;
 	struct timer_list pwr_state_check_timer;
 	int		pwr_state_check_interval;
diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h
index be9c30c57419..bcbce46cec85 100644
--- a/drivers/staging/rtl8188eu/include/rtw_recv.h
+++ b/drivers/staging/rtl8188eu/include/rtw_recv.h
@@ -270,7 +270,7 @@ struct recv_buf {
 	len = (unsigned int )(tail - data);
 
 */
-struct recv_frame_hdr {
+struct recv_frame {
 	struct list_head list;
 	struct sk_buff	 *pkt;
 	struct sk_buff	 *pkt_newalloc;
@@ -289,23 +289,16 @@ struct recv_frame_hdr {
 	struct recv_reorder_ctrl *preorder_ctrl;
 };
 
-union recv_frame {
-	union {
-		struct list_head list;
-		struct recv_frame_hdr hdr;
-		uint mem[RECVFRAME_HDR_ALIGN>>2];
-	} u;
-};
-
-union recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
-union recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
-void rtw_init_recvframe(union recv_frame *precvframe,
+struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+void rtw_init_recvframe(struct recv_frame *precvframe,
 			struct recv_priv *precvpriv);
-int  rtw_free_recvframe(union recv_frame *precvframe,
+int  rtw_free_recvframe(struct recv_frame *precvframe,
 			struct __queue *pfree_recv_queue);
 #define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue)
-int _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue);
-int rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue);
+int _rtw_enqueue_recvframe(struct recv_frame *precvframe,
+			   struct __queue *queue);
+int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue);
 void rtw_free_recvframe_queue(struct __queue *pframequeue,
 			      struct __queue *pfree_recv_queue);
 u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter);
@@ -315,29 +308,20 @@ struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue);
 
 void rtw_reordering_ctrl_timeout_handler(void *pcontext);
 
-static inline u8 *get_rxmem(union recv_frame *precvframe)
+static inline u8 *get_rxmem(struct recv_frame *precvframe)
 {
 	/* always return rx_head... */
 	if (precvframe == NULL)
 		return NULL;
-	return precvframe->u.hdr.rx_head;
+	return precvframe->rx_head;
 }
 
-static inline u8 *get_rx_status(union recv_frame *precvframe)
+static inline u8 *get_rx_status(struct recv_frame *precvframe)
 {
 	return get_rxmem(precvframe);
 }
 
-static inline u8 *get_recvframe_data(union recv_frame *precvframe)
-{
-	/* always return rx_data */
-	if (precvframe == NULL)
-		return NULL;
-
-	return precvframe->u.hdr.rx_data;
-}
-
-static inline u8 *recvframe_push(union recv_frame *precvframe, int sz)
+static inline u8 *recvframe_push(struct recv_frame *precvframe, int sz)
 {
 	/*  append data before rx_data */
 
@@ -348,16 +332,16 @@ static inline u8 *recvframe_push(union recv_frame *precvframe, int sz)
  */
 	if (precvframe == NULL)
 		return NULL;
-	precvframe->u.hdr.rx_data -= sz ;
-	if (precvframe->u.hdr.rx_data < precvframe->u.hdr.rx_head) {
-		precvframe->u.hdr.rx_data += sz;
+	precvframe->rx_data -= sz;
+	if (precvframe->rx_data < precvframe->rx_head) {
+		precvframe->rx_data += sz;
 		return NULL;
 	}
-	precvframe->u.hdr.len += sz;
-	return precvframe->u.hdr.rx_data;
+	precvframe->len += sz;
+	return precvframe->rx_data;
 }
 
-static inline u8 *recvframe_pull(union recv_frame *precvframe, int sz)
+static inline u8 *recvframe_pull(struct recv_frame *precvframe, int sz)
 {
 	/*  rx_data += sz; move rx_data sz bytes  hereafter */
 
@@ -366,16 +350,16 @@ static inline u8 *recvframe_pull(union recv_frame *precvframe, int sz)
 
 	if (precvframe == NULL)
 		return NULL;
-	precvframe->u.hdr.rx_data += sz;
-	if (precvframe->u.hdr.rx_data > precvframe->u.hdr.rx_tail) {
-		precvframe->u.hdr.rx_data -= sz;
+	precvframe->rx_data += sz;
+	if (precvframe->rx_data > precvframe->rx_tail) {
+		precvframe->rx_data -= sz;
 		return NULL;
 	}
-	precvframe->u.hdr.len -= sz;
-	return precvframe->u.hdr.rx_data;
+	precvframe->len -= sz;
+	return precvframe->rx_data;
 }
 
-static inline u8 *recvframe_put(union recv_frame *precvframe, int sz)
+static inline u8 *recvframe_put(struct recv_frame *precvframe, int sz)
 {
 	/* used for append sz bytes from ptr to rx_tail, update rx_tail
 	 * and return the updated rx_tail to the caller */
@@ -384,17 +368,17 @@ static inline u8 *recvframe_put(union recv_frame *precvframe, int sz)
 	if (precvframe == NULL)
 		return NULL;
 
-	precvframe->u.hdr.rx_tail += sz;
+	precvframe->rx_tail += sz;
 
-	if (precvframe->u.hdr.rx_tail > precvframe->u.hdr.rx_end) {
-		precvframe->u.hdr.rx_tail -= sz;
+	if (precvframe->rx_tail > precvframe->rx_end) {
+		precvframe->rx_tail -= sz;
 		return NULL;
 	}
-	precvframe->u.hdr.len += sz;
-	return precvframe->u.hdr.rx_tail;
+	precvframe->len += sz;
+	return precvframe->rx_tail;
 }
 
-static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, int sz)
+static inline u8 *recvframe_pull_tail(struct recv_frame *precvframe, int sz)
 {
 	/*  rmv data from rx_tail (by yitsen) */
 
@@ -404,64 +388,13 @@ static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, int sz)
 
 	if (precvframe == NULL)
 		return NULL;
-	precvframe->u.hdr.rx_tail -= sz;
-	if (precvframe->u.hdr.rx_tail < precvframe->u.hdr.rx_data) {
-		precvframe->u.hdr.rx_tail += sz;
+	precvframe->rx_tail -= sz;
+	if (precvframe->rx_tail < precvframe->rx_data) {
+		precvframe->rx_tail += sz;
 		return NULL;
 	}
-	precvframe->u.hdr.len -= sz;
-	return precvframe->u.hdr.rx_tail;
-}
-
-static inline unsigned char *get_rxbuf_desc(union recv_frame *precvframe)
-{
-	unsigned char *buf_desc;
-
-	if (precvframe == NULL)
-		return NULL;
-	return buf_desc;
-}
-
-static inline union recv_frame *rxmem_to_recvframe(u8 *rxmem)
-{
-	/* due to the design of 2048 bytes alignment of recv_frame,
-	 * we can reference the union recv_frame */
-	/* from any given member of recv_frame. */
-	/*  rxmem indicates the any member/address in recv_frame */
-
-	return (union recv_frame *)(((size_t)rxmem >> RXFRAME_ALIGN) << RXFRAME_ALIGN);
-}
-
-static inline union recv_frame *pkt_to_recvframe(struct sk_buff *pkt)
-{
-	u8 *buf_star;
-	union recv_frame *precv_frame;
-	precv_frame = rxmem_to_recvframe((unsigned char *)buf_star);
-
-	return precv_frame;
-}
-
-static inline u8 *pkt_to_recvmem(struct sk_buff *pkt)
-{
-	/*  return the rx_head */
-
-	union recv_frame *precv_frame = pkt_to_recvframe(pkt);
-
-	return	precv_frame->u.hdr.rx_head;
-}
-
-static inline u8 *pkt_to_recvdata(struct sk_buff *pkt)
-{
-	/*  return the rx_data */
-
-	union recv_frame *precv_frame = pkt_to_recvframe(pkt);
-
-	return	precv_frame->u.hdr.rx_data;
-}
-
-static inline int get_recvframe_len(union recv_frame *precvframe)
-{
-	return precvframe->u.hdr.len;
+	precvframe->len -= sz;
+	return precvframe->rx_tail;
 }
 
 static inline s32 translate_percentage_to_dbm(u32 sig_stren_index)
@@ -480,6 +413,6 @@ struct sta_info;
 
 void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
 
-void  mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame);
+void  mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame);
 
 #endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h
index 1ac1dd31db68..62f5db169523 100644
--- a/drivers/staging/rtl8188eu/include/rtw_xmit.h
+++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h
@@ -105,11 +105,6 @@ struct tx_desc {
 	__le32 txdw7;
 };
 
-union txdesc {
-	struct tx_desc txdesc;
-	unsigned int value[TXDESC_SIZE>>2];
-};
-
 struct	hw_xmit	{
 	struct __queue *sta_queue;
 	int	accnt;
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 4ad80ae1067f..36910072cf87 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -35,6 +35,7 @@
 
 #include <rtw_mp.h>
 #include <rtw_iol.h>
+#include <linux/vmalloc.h>
 
 #define RTL_IOCTL_WPA_SUPPLICANT	(SIOCIWFIRSTPRIV + 30)
 
@@ -472,8 +473,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
 #endif /* CONFIG_88EU_P2P */
 
-_func_enter_;
-
 	param->u.crypt.err = 0;
 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
 
@@ -614,9 +613,6 @@ _func_enter_;
 exit:
 
 	kfree(pwep);
-
-_func_exit_;
-
 	return ret;
 }
 
@@ -770,8 +766,6 @@ static int rtw_wx_get_name(struct net_device *dev,
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
 
-	_func_enter_;
-
 	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
 		/* parsing HT_CAP_IE */
 		p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
@@ -806,9 +800,6 @@ static int rtw_wx_get_name(struct net_device *dev,
 	} else {
 		snprintf(wrqu->name, IFNAMSIZ, "unassociated");
 	}
-
-	_func_exit_;
-
 	return 0;
 }
 
@@ -816,12 +807,7 @@ static int rtw_wx_set_freq(struct net_device *dev,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra)
 {
-	_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
-
-	_func_exit_;
-
 	return 0;
 }
 
@@ -854,8 +840,6 @@ static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 	enum ndis_802_11_network_infra networkType;
 	int ret = 0;
 
-	_func_enter_;
-
 	if (_FAIL == rtw_pwr_wakeup(padapter)) {
 		ret = -EPERM;
 		goto exit;
@@ -894,7 +878,6 @@ static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 	}
 	rtw_setopmode_cmd(padapter, networkType);
 exit:
-	_func_exit_;
 	return ret;
 }
 
@@ -906,8 +889,6 @@ static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
 
-	_func_enter_;
-
 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 		wrqu->mode = IW_MODE_INFRA;
 	else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
@@ -918,8 +899,6 @@ static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
 	else
 		wrqu->mode = IW_MODE_AUTO;
 
-	_func_exit_;
-
 	return 0;
 }
 
@@ -1011,8 +990,6 @@ static int rtw_wx_get_range(struct net_device *dev,
 	u16 val;
 	int i;
 
-	_func_enter_;
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
 
 	wrqu->data.length = sizeof(*range);
@@ -1093,8 +1070,6 @@ static int rtw_wx_get_range(struct net_device *dev,
 	range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
 			   IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
 			   IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
-	_func_exit_;
-
 	return 0;
 }
 
@@ -1118,8 +1093,6 @@ static int rtw_wx_set_wap(struct net_device *dev,
 	struct	wlan_network	*pnetwork = NULL;
 	enum ndis_802_11_auth_mode	authmode;
 
-	_func_enter_;
-
 	if (_FAIL == rtw_pwr_wakeup(padapter)) {
 		ret = -1;
 		goto exit;
@@ -1138,15 +1111,15 @@ static int rtw_wx_set_wap(struct net_device *dev,
 	authmode = padapter->securitypriv.ndisauthtype;
 	spin_lock_bh(&queue->lock);
 	phead = get_list_head(queue);
-	pmlmepriv->pscanned = get_next(phead);
+	pmlmepriv->pscanned = phead->next;
 
 	while (1) {
 		if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+		pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 
-		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 
 		dst_bssid = pnetwork->network.MacAddress;
 
@@ -1173,8 +1146,6 @@ static int rtw_wx_set_wap(struct net_device *dev,
 
 exit:
 
-	_func_exit_;
-
 	return ret;
 }
 
@@ -1192,17 +1163,12 @@ static int rtw_wx_get_wap(struct net_device *dev,
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
 
-	_func_enter_;
-
 	if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
 	    ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
 	    ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
 		memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
 	else
 		_rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
-
-	_func_exit_;
-
 	return 0;
 }
 
@@ -1252,7 +1218,6 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 #endif /* CONFIG_88EU_P2P */
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
 
-_func_enter_;
 	if (padapter->registrypriv.mp_mode == 1) {
 		if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
 			ret = -1;
@@ -1383,7 +1348,6 @@ _func_enter_;
 
 exit:
 
-_func_exit_;
 	return ret;
 }
 
@@ -1407,8 +1371,6 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
 	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
 
-	_func_enter_;
-
 	if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
 		ret = -EINVAL;
 		goto exit;
@@ -1440,7 +1402,7 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist))
@@ -1451,13 +1413,13 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
 			break;
 		}
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 
 		/* report network only if the current channel set contains the channel to which this network belongs */
 		if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
 			ev = translate_scan(padapter, a, pnetwork, ev, stop);
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -1466,7 +1428,6 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
 	wrqu->data.flags = 0;
 
 exit:
-	_func_exit_;
 	return ret;
 }
 
@@ -1490,7 +1451,6 @@ static int rtw_wx_set_essid(struct net_device *dev,
 
 	uint ret = 0, len;
 
-	_func_enter_;
 
 	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
 		 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
@@ -1530,7 +1490,7 @@ static int rtw_wx_set_essid(struct net_device *dev,
 		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
 		spin_lock_bh(&queue->lock);
 	       phead = get_list_head(queue);
-	      pmlmepriv->pscanned = get_next(phead);
+	      pmlmepriv->pscanned = phead->next;
 
 		while (1) {
 			if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
@@ -1540,9 +1500,9 @@ static int rtw_wx_set_essid(struct net_device *dev,
 				break;
 			}
 
-			pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+			pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 
-			pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+			pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 
 			dst_ssid = pnetwork->network.Ssid.Ssid;
 
@@ -1583,7 +1543,6 @@ exit:
 
 	DBG_88E("<=%s, ret %d\n", __func__, ret);
 
-	_func_exit_;
 
 	return ret;
 }
@@ -1599,7 +1558,6 @@ static int rtw_wx_get_essid(struct net_device *dev,
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
 
-	_func_enter_;
 
 	if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
 	    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
@@ -1617,7 +1575,6 @@ static int rtw_wx_get_essid(struct net_device *dev,
 
 exit:
 
-	_func_exit_;
 
 	return ret;
 }
@@ -1634,7 +1591,6 @@ static int rtw_wx_set_rate(struct net_device *dev,
 	u32	ratevalue = 0;
 	 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
 	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
@@ -1706,7 +1662,6 @@ set_rate:
 		ret = -1;
 	}
 
-_func_exit_;
 
 	return ret;
 }
@@ -1734,7 +1689,6 @@ static int rtw_wx_set_rts(struct net_device *dev,
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
-	_func_enter_;
 
 	if (wrqu->rts.disabled) {
 		padapter->registrypriv.rts_thresh = 2347;
@@ -1748,7 +1702,6 @@ static int rtw_wx_set_rts(struct net_device *dev,
 
 	DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
 
-	_func_exit_;
 
 	return 0;
 }
@@ -1759,7 +1712,6 @@ static int rtw_wx_get_rts(struct net_device *dev,
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
-	_func_enter_;
 
 	DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
 
@@ -1767,7 +1719,6 @@ static int rtw_wx_get_rts(struct net_device *dev,
 	wrqu->rts.fixed = 0;	/* no auto select */
 	/* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
 
-	_func_exit_;
 
 	return 0;
 }
@@ -1778,7 +1729,6 @@ static int rtw_wx_set_frag(struct net_device *dev,
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
-	_func_enter_;
 
 	if (wrqu->frag.disabled) {
 		padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
@@ -1792,7 +1742,6 @@ static int rtw_wx_set_frag(struct net_device *dev,
 
 	DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
 
-	_func_exit_;
 
 	return 0;
 }
@@ -1803,14 +1752,12 @@ static int rtw_wx_get_frag(struct net_device *dev,
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
-	_func_enter_;
 
 	DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
 
 	wrqu->frag.value = padapter->xmitpriv.frag_len;
 	wrqu->frag.fixed = 0;	/* no auto select */
 
-	_func_exit_;
 
 	return 0;
 }
@@ -1844,7 +1791,6 @@ static int rtw_wx_set_enc(struct net_device *dev,
 
 	key = erq->flags & IW_ENCODE_INDEX;
 
-	_func_enter_;
 
 	if (erq->flags & IW_ENCODE_DISABLED) {
 		DBG_88E("EncryptionDisabled\n");
@@ -1939,7 +1885,6 @@ static int rtw_wx_set_enc(struct net_device *dev,
 
 exit:
 
-	_func_exit_;
 
 	return ret;
 }
@@ -1953,7 +1898,6 @@ static int rtw_wx_get_enc(struct net_device *dev,
 	struct iw_point *erq = &(wrqu->encoding);
 	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
 
-	_func_enter_;
 
 	if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
 		if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
@@ -2007,7 +1951,6 @@ static int rtw_wx_get_enc(struct net_device *dev,
 		erq->flags |= IW_ENCODE_DISABLED;
 		break;
 	}
-	_func_exit_;
 
 	return ret;
 }
@@ -2607,13 +2550,13 @@ static int rtw_get_ap_info(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 
 		if (hwaddr_aton_i(data, bssid)) {
 			DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
@@ -2638,7 +2581,7 @@ static int rtw_get_ap_info(struct net_device *dev,
 			}
 		}
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -2690,13 +2633,13 @@ static int rtw_wps_start(struct net_device *dev,
 	struct iw_point *pdata = &wrqu->data;
 	u32   u32wps_start = 0;
 
-	ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
-	if (ret) {
+	if ((padapter->bDriverStopped) || (pdata == NULL)) {
 		ret = -EINVAL;
 		goto exit;
 	}
 
-	if ((padapter->bDriverStopped) || (pdata == NULL)) {
+	ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
+	if (ret) {
 		ret = -EINVAL;
 		goto exit;
 	}
@@ -3110,13 +3053,13 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			u8 *wpsie;
 			uint wpsie_len = 0;
@@ -3134,7 +3077,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
 			}
 			break;
 		}
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3180,13 +3123,13 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			/*	Commented by Albert 2011/05/18 */
 			/*	Match the device address located in the P2P IE */
@@ -3215,7 +3158,7 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
 			}
 	     }
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3264,13 +3207,13 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			u8 *wpsie;
 			uint wpsie_len = 0;
@@ -3295,7 +3238,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
 			break;
 	     }
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3343,13 +3286,13 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			u8 *wpsie;
 			uint wpsie_len = 0;
@@ -3366,7 +3309,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
 			break;
 		}
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3414,13 +3357,13 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			/*	Commented by Albert 20121226 */
 			/*	Match the device address located in the P2P IE */
@@ -3440,7 +3383,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
 				}
 			}
 		}
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3496,19 +3439,19 @@ static int rtw_p2p_connect(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
 			uintPeerChannel = pnetwork->network.Configuration.DSConfig;
 			break;
 		}
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3591,13 +3534,13 @@ static int rtw_p2p_invite_req(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 
 		/*	Commented by Albert 2011/05/18 */
 		/*	Match the device address located in the P2P IE */
@@ -3622,7 +3565,7 @@ static int rtw_p2p_invite_req(struct net_device *dev,
 				}
 			}
 		}
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -3741,7 +3684,7 @@ static int rtw_p2p_prov_disc(struct net_device *dev,
 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
 	phead = get_list_head(queue);
-	plist = get_next(phead);
+	plist = phead->next;
 
 	while (1) {
 		if (rtw_end_of_queue_search(phead, plist) == true)
@@ -3750,7 +3693,7 @@ static int rtw_p2p_prov_disc(struct net_device *dev,
 		if (uintPeerChannel != 0)
 			break;
 
-		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		pnetwork = container_of(plist, struct wlan_network, list);
 
 		/*	Commented by Albert 2011/05/18 */
 		/*	Match the device address located in the P2P IE */
@@ -3781,7 +3724,7 @@ static int rtw_p2p_prov_disc(struct net_device *dev,
 			}
 		}
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -4436,12 +4379,12 @@ static int rtw_dbg_port(struct net_device *dev,
 
 				for (i = 0; i < NUM_STA; i++) {
 					phead = &(pstapriv->sta_hash[i]);
-					plist = get_next(phead);
+					plist = phead->next;
 
 					while ((rtw_end_of_queue_search(phead, plist)) == false) {
-						psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+						psta = container_of(plist, struct sta_info, hash_list);
 
-						plist = get_next(plist);
+						plist = plist->next;
 
 						if (extra_arg == psta->aid) {
 							DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
@@ -4507,11 +4450,9 @@ static int rtw_dbg_port(struct net_device *dev,
 			struct registry_priv	*pregpriv = &padapter->registrypriv;
 			/*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
 			/* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
-			if (pregpriv &&
-			    (extra_arg == 0 ||
-			     extra_arg == 1 ||
-			     extra_arg == 2 ||
-			     extra_arg == 3)) {
+			if (!pregpriv)
+				break;
+			if (extra_arg >= 0 && extra_arg <= 3) {
 				pregpriv->rx_stbc = extra_arg;
 				DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
 			} else {
@@ -4523,7 +4464,9 @@ static int rtw_dbg_port(struct net_device *dev,
 		{
 			struct registry_priv	*pregpriv = &padapter->registrypriv;
 			/*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
-			if (pregpriv && extra_arg >= 0 && extra_arg < 3) {
+			if (!pregpriv)
+				break;
+			if (extra_arg >= 0 && extra_arg < 3) {
 				pregpriv->ampdu_enable = extra_arg;
 				DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
 			} else {
@@ -5648,12 +5591,12 @@ static int rtw_wx_set_priv(struct net_device *dev,
 		return -EFAULT;
 
 	len = dwrq->length;
-	ext = rtw_vmalloc(len);
+	ext = vmalloc(len);
 	if (!ext)
 		return -ENOMEM;
 
 	if (copy_from_user(ext, dwrq->pointer, len)) {
-		rtw_vmfree(ext, len);
+		vfree(ext);
 		return -EFAULT;
 	}
 
@@ -5693,7 +5636,7 @@ static int rtw_wx_set_priv(struct net_device *dev,
 
 FREE_EXT:
 
-	rtw_vmfree(ext, len);
+	vfree(ext);
 
 	return ret;
 }
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
index 57d1ff750d52..0624378efd6f 100644
--- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
@@ -61,12 +61,10 @@ void rtw_init_mlme_timer(struct adapter *padapter)
 
 void rtw_os_indicate_connect(struct adapter *adapter)
 {
-_func_enter_;
 	rtw_indicate_wx_assoc_event(adapter);
 	netif_carrier_on(adapter->pnetdev);
 	if (adapter->pid[2] != 0)
 		rtw_signal_process(adapter->pid[2], SIGALRM);
-_func_exit_;
 }
 
 void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted)
@@ -119,11 +117,9 @@ void rtw_reset_securitypriv(struct adapter *adapter)
 
 void rtw_os_indicate_disconnect(struct adapter *adapter)
 {
-_func_enter_;
 	netif_carrier_off(adapter->pnetdev); /*  Do it first for tx broadcast pkt after disconnection issue! */
 	rtw_indicate_wx_disassoc_event(adapter);
 	 rtw_reset_securitypriv(adapter);
-_func_exit_;
 }
 
 void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
@@ -132,7 +128,6 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
 	u8	*buff, *p, i;
 	union iwreq_data wrqu;
 
-_func_enter_;
 	RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
 		 ("+rtw_report_sec_ie, authmode=%d\n", authmode));
 	buff = NULL;
@@ -141,7 +136,7 @@ _func_enter_;
 			 ("rtw_report_sec_ie, authmode=%d\n", authmode));
 		buff = rtw_malloc(IW_CUSTOM_MAX);
 		if (!buff)
-			goto exit;
+			return;
 		_rtw_memset(buff, 0, IW_CUSTOM_MAX);
 		p = buff;
 		p += sprintf(p, "ASSOCINFO(ReqIEs =");
@@ -157,8 +152,6 @@ _func_enter_;
 		wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
 		kfree(buff);
 	}
-exit:
-_func_exit_;
 }
 
 static void _survey_timer_hdl(void *FunctionContext)
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index 7c9ee58f47bb..b225d1c07210 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -520,7 +520,6 @@ static uint loadparam(struct adapter *padapter,  struct  net_device *pnetdev)
 	uint status = _SUCCESS;
 	struct registry_priv  *registry_par = &padapter->registrypriv;
 
-_func_enter_;
 
 	GlobalDebugLevel = rtw_debug;
 	registry_par->chip_version = (u8)rtw_chip_version;
@@ -588,7 +587,6 @@ _func_enter_;
 	snprintf(registry_par->ifname, 16, "%s", ifname);
 	snprintf(registry_par->if2name, 16, "%s", if2name);
 	registry_par->notch_filter = (u8)rtw_notch_filter;
-_func_exit_;
 	return status;
 }
 
@@ -855,7 +853,6 @@ u8 rtw_init_drv_sw(struct adapter *padapter)
 {
 	u8	ret8 = _SUCCESS;
 
-_func_enter_;
 
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw\n"));
 
@@ -930,7 +927,6 @@ _func_enter_;
 exit:
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw\n"));
 
-	_func_exit_;
 
 	return ret8;
 }
@@ -1115,7 +1111,7 @@ int netdev_open(struct net_device *pnetdev)
 
 	_enter_critical_mutex(padapter->hw_init_mutex, NULL);
 	ret = _netdev_open(pnetdev);
-	_exit_critical_mutex(padapter->hw_init_mutex, NULL);
+	mutex_unlock(padapter->hw_init_mutex);
 	return ret;
 }
 
@@ -1208,6 +1204,7 @@ int pm_netdev_open(struct net_device *pnetdev, u8 bnormal)
 int netdev_close(struct net_device *pnetdev)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
 
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - drv_close\n"));
 
@@ -1246,6 +1243,9 @@ int netdev_close(struct net_device *pnetdev)
 	rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
 #endif /* CONFIG_88EU_P2P */
 
+	kfree(dvobj->firmware.szFwBuffer);
+	dvobj->firmware.szFwBuffer = NULL;
+
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n"));
 	DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup);
 	return 0;
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
index 8c3b077448af..2579a404a766 100644
--- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -55,27 +55,6 @@ u32 rtw_atoi(u8 *s)
 	return num;
 }
 
-inline u8 *_rtw_vmalloc(u32 sz)
-{
-	u8	*pbuf;
-	pbuf = vmalloc(sz);
-	return pbuf;
-}
-
-inline u8 *_rtw_zvmalloc(u32 sz)
-{
-	u8	*pbuf;
-	pbuf = _rtw_vmalloc(sz);
-	if (pbuf != NULL)
-		memset(pbuf, 0, sz);
-	return pbuf;
-}
-
-inline void _rtw_vmfree(u8 *pbuf, u32 sz)
-{
-	vfree(pbuf);
-}
-
 u8 *_rtw_malloc(u32 sz)
 {
 	u8	*pbuf = NULL;
@@ -114,16 +93,6 @@ void rtw_mfree2d(void *pbuf, int h, int w, int size)
 	kfree(pbuf);
 }
 
-int _rtw_memcmp(void *dst, void *src, u32 sz)
-{
-/* under Linux/GNU/GLibc, the return value of memcmp for two same
- * mem. chunk is 0 */
-	if (!(memcmp(dst, src, sz)))
-		return true;
-	else
-		return false;
-}
-
 void _rtw_memset(void *pbuf, int c, u32 sz)
 {
 	memset(pbuf, c, sz);
@@ -252,7 +221,7 @@ struct net_device *rtw_alloc_etherdev(int sizeof_priv)
 
 	pnpi = netdev_priv(pnetdev);
 
-	pnpi->priv = rtw_zvmalloc(sizeof_priv);
+	pnpi->priv = vzalloc(sizeof_priv);
 	if (!pnpi->priv) {
 		free_netdev(pnetdev);
 		pnetdev = NULL;
@@ -276,7 +245,7 @@ void rtw_free_netdev(struct net_device *netdev)
 	if (!pnpi->priv)
 		goto RETURN;
 
-	rtw_vmfree(pnpi->priv, pnpi->sizeof_priv);
+	vfree(pnpi->priv);
 	free_netdev(netdev);
 
 RETURN:
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
index 2a18b3208a00..da397e4c6773 100644
--- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -26,7 +26,6 @@
 #include <recv_osdep.h>
 
 #include <osdep_intf.h>
-#include <ethernet.h>
 #include <usb_ops.h>
 
 /* init os related resource in struct recv_priv */
@@ -36,16 +35,16 @@ int rtw_os_recv_resource_init(struct recv_priv *precvpriv,
 	return _SUCCESS;
 }
 
-/* alloc os related resource in union recv_frame */
+/* alloc os related resource in struct recv_frame */
 int rtw_os_recv_resource_alloc(struct adapter *padapter,
-			       union recv_frame *precvframe)
+			       struct recv_frame *precvframe)
 {
-	precvframe->u.hdr.pkt_newalloc = NULL;
-	precvframe->u.hdr.pkt = NULL;
+	precvframe->pkt_newalloc = NULL;
+	precvframe->pkt = NULL;
 	return _SUCCESS;
 }
 
-/* free os related resource in union recv_frame */
+/* free os related resource in struct recv_frame */
 void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
 {
 }
@@ -118,24 +117,23 @@ void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
 }
 
 void rtw_hostapd_mlme_rx(struct adapter *padapter,
-			 union recv_frame *precv_frame)
+			 struct recv_frame *precv_frame)
 {
 }
 
 int rtw_recv_indicatepkt(struct adapter *padapter,
-			 union recv_frame *precv_frame)
+			 struct recv_frame *precv_frame)
 {
 	struct recv_priv *precvpriv;
 	struct __queue *pfree_recv_queue;
 	struct sk_buff *skb;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-_func_enter_;
 
 	precvpriv = &(padapter->recvpriv);
 	pfree_recv_queue = &(precvpriv->free_recv_queue);
 
-	skb = precv_frame->u.hdr.pkt;
+	skb = precv_frame->pkt;
 	if (skb == NULL) {
 		RT_TRACE(_module_recv_osdep_c_, _drv_err_,
 			 ("rtw_recv_indicatepkt():skb == NULL something wrong!!!!\n"));
@@ -145,18 +143,18 @@ _func_enter_;
 	RT_TRACE(_module_recv_osdep_c_, _drv_info_,
 		 ("rtw_recv_indicatepkt():skb != NULL !!!\n"));
 	RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-		 ("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head =%p  precv_frame->hdr.rx_data =%p\n",
-		 precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data));
+		 ("rtw_recv_indicatepkt():precv_frame->rx_head =%p  precv_frame->hdr.rx_data =%p\n",
+		 precv_frame->rx_head, precv_frame->rx_data));
 	RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-		 ("precv_frame->hdr.rx_tail =%p precv_frame->u.hdr.rx_end =%p precv_frame->hdr.len =%d\n",
-		 precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end,
-		 precv_frame->u.hdr.len));
+		 ("precv_frame->hdr.rx_tail =%p precv_frame->rx_end =%p precv_frame->hdr.len =%d\n",
+		 precv_frame->rx_tail, precv_frame->rx_end,
+		 precv_frame->len));
 
-	skb->data = precv_frame->u.hdr.rx_data;
+	skb->data = precv_frame->rx_data;
 
-	skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
+	skb_set_tail_pointer(skb, precv_frame->len);
 
-	skb->len = precv_frame->u.hdr.len;
+	skb->len = precv_frame->len;
 
 	RT_TRACE(_module_recv_osdep_c_, _drv_info_,
 		 ("skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n",
@@ -167,11 +165,11 @@ _func_enter_;
 		struct sk_buff *pskb2 = NULL;
 		struct sta_info *psta = NULL;
 		struct sta_priv *pstapriv = &padapter->stapriv;
-		struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+		struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
 		int bmcast = IS_MCAST(pattrib->dst);
 
-		if (!_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv),
-				 ETH_ALEN)) {
+		if (memcmp(pattrib->dst, myid(&padapter->eeprompriv),
+			   ETH_ALEN)) {
 			if (bmcast) {
 				psta = rtw_get_bcmc_stainfo(padapter);
 				pskb2 = skb_clone(skb, GFP_ATOMIC);
@@ -209,14 +207,13 @@ _func_enter_;
 _recv_indicatepkt_end:
 
 	/*  pointers to NULL before rtw_free_recvframe() */
-	precv_frame->u.hdr.pkt = NULL;
+	precv_frame->pkt = NULL;
 
 	rtw_free_recvframe(precv_frame, pfree_recv_queue);
 
 	RT_TRACE(_module_recv_osdep_c_, _drv_info_,
 		 ("\n rtw_recv_indicatepkt :after netif_rx!!!!\n"));
 
-_func_exit_;
 
 	return _SUCCESS;
 
@@ -225,7 +222,6 @@ _recv_indicatepkt_drop:
 	 /* enqueue back to free_recv_queue */
 	rtw_free_recvframe(precv_frame, pfree_recv_queue);
 
-_func_exit_;
 	 return _FAIL;
 }
 
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
index a3c2bc5922e4..ca2736d60b62 100644
--- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
@@ -24,7 +24,6 @@
 #include <rtw_android.h>
 #include <osdep_service.h>
 #include <rtw_debug.h>
-#include <ioctl_cfg80211.h>
 #include <rtw_ioctl_set.h>
 
 static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 2f40ff5901d6..2e49cd583212 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -26,6 +26,7 @@
 #include <hal_intf.h>
 #include <rtw_version.h>
 #include <linux/usb.h>
+#include <linux/vmalloc.h>
 #include <osdep_intf.h>
 
 #include <usb_vendor_req.h>
@@ -162,7 +163,6 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
 	struct usb_endpoint_descriptor	*pendp_desc;
 	struct usb_device	*pusbd;
 
-_func_enter_;
 
 	pdvobjpriv = (struct dvobj_priv *)rtw_zmalloc(sizeof(*pdvobjpriv));
 	if (pdvobjpriv == NULL)
@@ -255,7 +255,6 @@ free_dvobj:
 		pdvobjpriv = NULL;
 	}
 exit:
-_func_exit_;
 	return pdvobjpriv;
 }
 
@@ -263,7 +262,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf)
 {
 	struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
 
-_func_enter_;
 
 	usb_set_intfdata(usb_intf, NULL);
 	if (dvobj) {
@@ -288,7 +286,6 @@ _func_enter_;
 
 	usb_put_dev(interface_to_usbdev(usb_intf));
 
-_func_exit_;
 }
 
 static void chip_by_usb_id(struct adapter *padapter,
@@ -390,7 +387,6 @@ int rtw_hw_suspend(struct adapter *padapter)
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 	struct net_device *pnetdev = padapter->pnetdev;
 
-	_func_enter_;
 
 	if ((!padapter->bup) || (padapter->bDriverStopped) ||
 	    (padapter->bSurpriseRemoved)) {
@@ -443,7 +439,6 @@ int rtw_hw_suspend(struct adapter *padapter)
 	} else {
 		goto error_exit;
 	}
-	_func_exit_;
 	return 0;
 
 error_exit:
@@ -456,7 +451,6 @@ int rtw_hw_resume(struct adapter *padapter)
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 	struct net_device *pnetdev = padapter->pnetdev;
 
-	_func_enter_;
 
 	if (padapter) { /* system resume */
 		DBG_88E("==> rtw_hw_resume\n");
@@ -488,7 +482,6 @@ int rtw_hw_resume(struct adapter *padapter)
 		goto error_exit;
 	}
 
-	_func_exit_;
 
 	return 0;
 error_exit:
@@ -507,7 +500,6 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
 	int ret = 0;
 	u32 start_time = jiffies;
 
-	_func_enter_;
 
 	DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
 
@@ -564,7 +556,6 @@ exit:
 	DBG_88E("<===  %s return %d.............. in %dms\n", __func__
 		, ret, rtw_get_passing_time_ms(start_time));
 
-	_func_exit_;
 	return ret;
 }
 
@@ -588,7 +579,6 @@ int rtw_resume_process(struct adapter *padapter)
 	struct pwrctrl_priv *pwrpriv = NULL;
 	int ret = -1;
 	u32 start_time = jiffies;
-	_func_enter_;
 
 	DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
 
@@ -627,7 +617,6 @@ exit:
 	DBG_88E("<===  %s return %d.............. in %dms\n", __func__,
 		ret, rtw_get_passing_time_ms(start_time));
 
-	_func_exit_;
 
 	return ret;
 }
@@ -647,7 +636,7 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
 	struct net_device *pnetdev = NULL;
 	int status = _FAIL;
 
-	padapter = (struct adapter *)rtw_zvmalloc(sizeof(*padapter));
+	padapter = (struct adapter *)vzalloc(sizeof(*padapter));
 	if (padapter == NULL)
 		goto exit;
 	padapter->dvobj = dvobj;
@@ -747,7 +736,7 @@ free_adapter:
 		if (pnetdev)
 			rtw_free_netdev(pnetdev);
 		else if (padapter)
-			rtw_vmfree((u8 *)padapter, sizeof(*padapter));
+			vfree(padapter);
 		padapter = NULL;
 	}
 exit:
@@ -836,7 +825,6 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf)
 	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
 	struct adapter *padapter = dvobj->if1;
 
-_func_enter_;
 
 	DBG_88E("+rtw_dev_remove\n");
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
@@ -855,7 +843,6 @@ _func_enter_;
 
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
 	DBG_88E("-r871xu_dev_remove, done\n");
-_func_exit_;
 
 	return;
 }
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 7e3f2fadd5bf..fb0bba85373b 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -80,7 +80,6 @@ static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	struct hal_data_8188e	*haldata;
 
-_func_enter_;
 
 	switch (pxmitbuf->flags) {
 	case VO_QUEUE_INX:
@@ -156,8 +155,6 @@ check_completion:
 	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
 
 	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-
-_func_exit_;
 }
 
 u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
@@ -174,7 +171,6 @@ u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
 	struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
 	struct usb_device *pusbd = pdvobj->pusbdev;
 
-_func_enter_;
 
 	RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port\n"));
 
@@ -255,7 +251,6 @@ _func_enter_;
 exit:
 	if (ret != _SUCCESS)
 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
-_func_exit_;
 	return ret;
 }
 
diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
index 9005971084b7..2c8e3f72dec7 100644
--- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
@@ -23,8 +23,6 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 
-#include <if_ether.h>
-#include <ip.h>
 #include <wifi.h>
 #include <mlme_osdep.h>
 #include <xmit_osdep.h>
@@ -39,7 +37,6 @@ uint rtw_remainder_len(struct pkt_file *pfile)
 
 void _rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile)
 {
-_func_enter_;
 
 	pfile->pkt = pktptr;
 	pfile->cur_addr = pktptr->data;
@@ -49,14 +46,12 @@ _func_enter_;
 
 	pfile->cur_buffer = pfile->buf_start;
 
-_func_exit_;
 }
 
 uint _rtw_pktfile_read (struct pkt_file *pfile, u8 *rmem, uint rlen)
 {
 	uint	len = 0;
 
-_func_enter_;
 
 	len =  rtw_remainder_len(pfile);
 	len = (rlen > len) ? len : rlen;
@@ -67,21 +62,17 @@ _func_enter_;
 	pfile->cur_addr += len;
 	pfile->pkt_len -= len;
 
-_func_exit_;
 
 	return len;
 }
 
 int rtw_endofpktfile(struct pkt_file *pfile)
 {
-_func_enter_;
 
 	if (pfile->pkt_len == 0) {
-	_func_exit_;
 		return true;
 	}
 
-_func_exit_;
 
 	return false;
 }
@@ -200,13 +191,13 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
 	phead = &pstapriv->asoc_list;
-	plist = get_next(phead);
+	plist = phead->next;
 
 	/* free sta asoc_queue */
 	while (!rtw_end_of_queue_search(phead, plist)) {
-		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		psta = container_of(plist, struct sta_info, asoc_list);
 
-		plist = get_next(plist);
+		plist = plist->next;
 
 		/* avoid   come from STA1 and send back STA1 */
 		if (!memcmp(psta->hwaddr, &skb->data[6], 6))
@@ -246,7 +237,6 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct  net_device *pnetdev)
 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
 	s32 res = 0;
 
-_func_enter_;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
 
@@ -282,7 +272,6 @@ drop_packet:
 
 exit:
 
-_func_exit_;
 
 	return 0;
 }
diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig
index 50e0d91a409a..ad82bc348a75 100644
--- a/drivers/staging/rtl8192e/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/rtl8192e/Kconfig
@@ -5,5 +5,4 @@ config RTL8192E
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select CRYPTO
-	default N
 	---help---
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
index 356aec437963..4b94653c50d9 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
@@ -28,31 +28,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-static inline void NdisRawWritePortUlong(u32 port,  u32 val)
-{
-	outl(val, port);
-}
-
-static inline void NdisRawWritePortUchar(u32 port,  u8 val)
-{
-	outb(val, port);
-}
-
-static inline void NdisRawReadPortUchar(u32 port, u8 *pval)
-{
-	*pval = inb(port);
-}
-
-static inline void NdisRawReadPortUshort(u32 port, u16 *pval)
-{
-	*pval = inw(port);
-}
-
-static inline void NdisRawReadPortUlong(u32 port, u32 *pval)
-{
-	*pval = inl(port);
-}
-
 struct mp_adapter {
 	u8		LinkCtrlReg;
 
@@ -70,33 +45,6 @@ struct mp_adapter {
 	u8		PciBridgeLinkCtrlReg;
 };
 
-struct rt_pci_capab_header {
-	unsigned char   CapabilityID;
-	unsigned char   Next;
-};
-
-#define PCI_MAX_BRIDGE_NUMBER				255
-#define PCI_MAX_DEVICES						32
-#define PCI_MAX_FUNCTION					8
-
-#define PCI_CONF_ADDRESS					0x0CF8
-#define PCI_CONF_DATA						0x0CFC
-
-#define	PCI_CLASS_BRIDGE_DEV				0x06
-#define	PCI_SUBCLASS_BR_PCI_TO_PCI		0x04
-
-#define	U1DONTCARE						0xFF
-#define	U2DONTCARE						0xFFFF
-#define	U4DONTCARE						0xFFFFFFFF
-
-#define	INTEL_VENDOR_ID					0x8086
-#define	SIS_VENDOR_ID						0x1039
-#define	ATI_VENDOR_ID						0x1002
-#define	ATI_DEVICE_ID						0x7914
-#define	AMD_VENDOR_ID						0x1022
-
-#define PCI_CAPABILITY_ID_PCI_EXPRESS		0x10
-
 struct net_device;
 bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 6202358c2984..498995d833e7 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -609,7 +609,7 @@ static int r8192_wx_set_nick(struct net_device *dev,
 	if (wrqu->data.length > IW_ESSID_MAX_SIZE)
 		return -E2BIG;
 	down(&priv->wx_sem);
-	wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+	wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick));
 	memset(priv->nick, 0, sizeof(priv->nick));
 	memcpy(priv->nick, extra, wrqu->data.length);
 	up(&priv->wx_sem);
diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig
index 3f055091b35f..3ee9d0d00fb6 100644
--- a/drivers/staging/rtl8192u/Kconfig
+++ b/drivers/staging/rtl8192u/Kconfig
@@ -5,5 +5,4 @@ config RTL8192U
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select CRYPTO
-	default N
 	---help---
diff --git a/drivers/staging/rtl8192u/ieee80211/EndianFree.h b/drivers/staging/rtl8192u/ieee80211/EndianFree.h
deleted file mode 100644
index dc85fb913dc2..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/EndianFree.h
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef __INC_ENDIANFREE_H
-#define __INC_ENDIANFREE_H
-
-/*
- *	Call endian free function when
- *		1. Read/write packet content.
- *		2. Before write integer to IO.
- *		3. After read integer from IO.
- */
-
-#define __MACHINE_LITTLE_ENDIAN 1234    /* LSB first: i386, vax */
-#define __MACHINE_BIG_ENDIAN    4321    /* MSB first: 68000, ibm, net, ppc */
-
-#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN
-
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-// Convert data
-#define EF1Byte(_val)				((u8)(_val))
-#define EF2Byte(_val)				((u16)(_val))
-#define EF4Byte(_val)				((u32)(_val))
-
-#else
-// Convert data
-#define EF1Byte(_val)				((u8)(_val))
-#define EF2Byte(_val)				(((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8))
-#define EF4Byte(_val)				(((((u32)(_val))&0x000000ff)<<24)|\
-						((((u32)(_val))&0x0000ff00)<<8)|\
-						((((u32)(_val))&0x00ff0000)>>8)|\
-						((((u32)(_val))&0xff000000)>>24))
-#endif
-
-// Read data from memory
-#define ReadEF1Byte(_ptr)		EF1Byte(*((u8 *)(_ptr)))
-#define ReadEF2Byte(_ptr)		EF2Byte(*((u16 *)(_ptr)))
-#define ReadEF4Byte(_ptr)		EF4Byte(*((u32 *)(_ptr)))
-
-// Write data to memory
-#define WriteEF1Byte(_ptr, _val)	(*((u8 *)(_ptr)))=EF1Byte(_val)
-#define WriteEF2Byte(_ptr, _val)	(*((u16 *)(_ptr)))=EF2Byte(_val)
-#define WriteEF4Byte(_ptr, _val)	(*((u32 *)(_ptr)))=EF4Byte(_val)
-// Convert Host system specific byte ording (litten or big endia) to Network byte ording (big endian).
-// 2006.05.07, by rcnjko.
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-#define H2N1BYTE(_val)	((u8)(_val))
-#define H2N2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
-			((((u16)(_val))&0xff00)>>8))
-#define H2N4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
-			((((u32)(_val))&0x0000ff00)<<8)	|\
-			((((u32)(_val))&0x00ff0000)>>8)	|\
-			((((u32)(_val))&0xff000000)>>24))
-#else
-#define H2N1BYTE(_val)			((u8)(_val))
-#define H2N2BYTE(_val)			((u16)(_val))
-#define H2N4BYTE(_val)			((u32)(_val))
-#endif
-
-// Convert from Network byte ording (big endian) to Host system specific byte ording (litten or big endia).
-// 2006.05.07, by rcnjko.
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-#define N2H1BYTE(_val)	((u8)(_val))
-#define N2H2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
-			((((u16)(_val))&0xff00)>>8))
-#define N2H4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
-			((((u32)(_val))&0x0000ff00)<<8)	|\
-			((((u32)(_val))&0x00ff0000)>>8)	|\
-			((((u32)(_val))&0xff000000)>>24))
-#else
-#define N2H1BYTE(_val)			((u8)(_val))
-#define N2H2BYTE(_val)			((u16)(_val))
-#define N2H4BYTE(_val)			((u32)(_val))
-#endif
-
-//
-//	Example:
-//		BIT_LEN_MASK_32(0) => 0x00000000
-//		BIT_LEN_MASK_32(1) => 0x00000001
-//		BIT_LEN_MASK_32(2) => 0x00000003
-//		BIT_LEN_MASK_32(32) => 0xFFFFFFFF
-//
-#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen)))
-//
-//	Example:
-//		BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
-//		BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000
-//
-#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset))
-
-//
-//	Description:
-//		Return 4-byte value in host byte ordering from
-//		4-byte pointer in litten-endian system.
-//
-#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart))))
-
-//
-//	Description:
-//		Translate subfield (continuous bits in little-endian) of 4-byte value in litten byte to
-//		4-byte value in host byte ordering.
-//
-#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \
-	  & \
-	  BIT_LEN_MASK_32(__BitLen) \
-	)
-
-//
-//	Description:
-//		Mask subfield (continuous bits in little-endian) of 4-byte value in litten byte oredering
-//		and return the result in 4-byte value in host byte ordering.
-//
-#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  LE_P4BYTE_TO_HOST_4BYTE(__pStart) \
-	  & \
-	  ( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \
-	)
-
-//
-//	Description:
-//		Set subfield of little-endian 4-byte value to specified value.
-//
-#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \
-	*((u32 *)(__pStart)) = \
-	EF4Byte( \
-	LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
-	| \
-	( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \
-       );
-
-
-#define BIT_LEN_MASK_16(__BitLen) \
-	(0xFFFF >> (16 - (__BitLen)))
-
-#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \
-	(BIT_LEN_MASK_16(__BitLen) << (__BitOffset))
-
-#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
-	(EF2Byte(*((u16 *)(__pStart))))
-
-#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \
-	  & \
-	  BIT_LEN_MASK_16(__BitLen) \
-	)
-
-#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
-	  & \
-	  ( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \
-	)
-
-#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \
-	*((u16 *)(__pStart)) = \
-	EF2Byte( \
-		LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
-		| \
-		( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \
-       );
-
-#define BIT_LEN_MASK_8(__BitLen) \
-	(0xFF >> (8 - (__BitLen)))
-
-#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \
-	(BIT_LEN_MASK_8(__BitLen) << (__BitOffset))
-
-#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
-	(EF1Byte(*((u8 *)(__pStart))))
-
-#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \
-	  & \
-	  BIT_LEN_MASK_8(__BitLen) \
-	)
-
-#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
-	( \
-	  LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
-	  & \
-	  ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \
-	)
-
-#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \
-	*((u8 *)(__pStart)) = \
-	EF1Byte( \
-		LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
-		| \
-		( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \
-       );
-
-#endif // #ifndef __INC_ENDIANFREE_H
diff --git a/drivers/staging/rtl8192u/ieee80211/aes.c b/drivers/staging/rtl8192u/ieee80211/aes.c
deleted file mode 100644
index abc1023cef65..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/aes.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Cryptographic API.
- *
- * AES Cipher Algorithm.
- *
- * Based on Brian Gladman's code.
- *
- * Linux developers:
- *  Alexander Kjeldaas <astor@fast.no>
- *  Herbert Valerio Riedel <hvr@hvrlab.org>
- *  Kyle McMartin <kyle@debian.org>
- *  Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
- *
- * This program is free software; you can redistribute 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.
- *
- * ---------------------------------------------------------------------------
- * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- * All rights reserved.
- *
- * LICENSE TERMS
- *
- * The free distribution and use of this software in both source and binary
- * form is allowed (with or without changes) provided that:
- *
- *   1. distributions of this source code include the above copyright
- *      notice, this list of conditions and the following disclaimer;
- *
- *   2. distributions in binary form include the above copyright
- *      notice, this list of conditions and the following disclaimer
- *      in the documentation and/or other associated materials;
- *
- *   3. the copyright holder's name is not used to endorse products
- *      built using this software without specific written permission.
- *
- * ALTERNATIVELY, provided that this notice is retained in full, this product
- * may be distributed under the terms of the GNU General Public License (GPL),
- * in which case the provisions of the GPL apply INSTEAD OF those given above.
- *
- * DISCLAIMER
- *
- * This software is provided 'as is' with no explicit or implied warranties
- * in respect of its properties, including, but not limited to, correctness
- * and/or fitness for purpose.
- * ---------------------------------------------------------------------------
- */
-
-/* Some changes from the Gladman version:
-    s/RIJNDAEL(e_key)/E_KEY/g
-    s/RIJNDAEL(d_key)/D_KEY/g
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-#include <asm/byteorder.h>
-
-#define AES_MIN_KEY_SIZE	16
-#define AES_MAX_KEY_SIZE	32
-
-#define AES_BLOCK_SIZE		16
-
-static inline
-u32 generic_rotr32 (const u32 x, const unsigned bits)
-{
-	const unsigned n = bits % 32;
-	return (x >> n) | (x << (32 - n));
-}
-
-static inline
-u32 generic_rotl32 (const u32 x, const unsigned bits)
-{
-	const unsigned n = bits % 32;
-	return (x << n) | (x >> (32 - n));
-}
-
-#define rotl generic_rotl32
-#define rotr generic_rotr32
-
-/*
- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
- */
-inline static u8
-byte(const u32 x, const unsigned n)
-{
-	return x >> (n << 3);
-}
-
-#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
-#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
-
-struct aes_ctx {
-	int key_length;
-	u32 E[60];
-	u32 D[60];
-};
-
-#define E_KEY ctx->E
-#define D_KEY ctx->D
-
-static u8 pow_tab[256] __initdata;
-static u8 log_tab[256] __initdata;
-static u8 sbx_tab[256] __initdata;
-static u8 isb_tab[256] __initdata;
-static u32 rco_tab[10];
-static u32 ft_tab[4][256];
-static u32 it_tab[4][256];
-
-static u32 fl_tab[4][256];
-static u32 il_tab[4][256];
-
-static inline u8 __init
-f_mult (u8 a, u8 b)
-{
-	u8 aa = log_tab[a], cc = aa + log_tab[b];
-
-	return pow_tab[cc + (cc < aa ? 1 : 0)];
-}
-
-#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
-
-#define f_rn(bo, bi, n, k)					\
-    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
-	     ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
-	     ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
-	     ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
-
-#define i_rn(bo, bi, n, k)					\
-    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
-	     it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
-	     it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
-	     it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
-
-#define ls_box(x)				\
-    ( fl_tab[0][byte(x, 0)] ^			\
-      fl_tab[1][byte(x, 1)] ^			\
-      fl_tab[2][byte(x, 2)] ^			\
-      fl_tab[3][byte(x, 3)] )
-
-#define f_rl(bo, bi, n, k)					\
-    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
-	     fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
-	     fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
-	     fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
-
-#define i_rl(bo, bi, n, k)					\
-    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
-	     il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
-	     il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
-	     il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
-
-static void __init
-gen_tabs (void)
-{
-	u32 i, t;
-	u8 p, q;
-
-	/* log and power tables for GF(2**8) finite field with
-	   0x011b as modular polynomial - the simplest primitive
-	   root is 0x03, used here to generate the tables */
-
-	for (i = 0, p = 1; i < 256; ++i) {
-		pow_tab[i] = (u8) p;
-		log_tab[p] = (u8) i;
-
-		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
-	}
-
-	log_tab[1] = 0;
-
-	for (i = 0, p = 1; i < 10; ++i) {
-		rco_tab[i] = p;
-
-		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
-	}
-
-	for (i = 0; i < 256; ++i) {
-		p = (i ? pow_tab[255 - log_tab[i]] : 0);
-		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
-		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
-		sbx_tab[i] = p;
-		isb_tab[p] = (u8) i;
-	}
-
-	for (i = 0; i < 256; ++i) {
-		p = sbx_tab[i];
-
-		t = p;
-		fl_tab[0][i] = t;
-		fl_tab[1][i] = rotl (t, 8);
-		fl_tab[2][i] = rotl (t, 16);
-		fl_tab[3][i] = rotl (t, 24);
-
-		t = ((u32) ff_mult (2, p)) |
-		    ((u32) p << 8) |
-		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
-
-		ft_tab[0][i] = t;
-		ft_tab[1][i] = rotl (t, 8);
-		ft_tab[2][i] = rotl (t, 16);
-		ft_tab[3][i] = rotl (t, 24);
-
-		p = isb_tab[i];
-
-		t = p;
-		il_tab[0][i] = t;
-		il_tab[1][i] = rotl (t, 8);
-		il_tab[2][i] = rotl (t, 16);
-		il_tab[3][i] = rotl (t, 24);
-
-		t = ((u32) ff_mult (14, p)) |
-		    ((u32) ff_mult (9, p) << 8) |
-		    ((u32) ff_mult (13, p) << 16) |
-		    ((u32) ff_mult (11, p) << 24);
-
-		it_tab[0][i] = t;
-		it_tab[1][i] = rotl (t, 8);
-		it_tab[2][i] = rotl (t, 16);
-		it_tab[3][i] = rotl (t, 24);
-	}
-}
-
-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
-
-#define imix_col(y,x)       \
-    u   = star_x(x);        \
-    v   = star_x(u);        \
-    w   = star_x(v);        \
-    t   = w ^ (x);          \
-   (y)  = u ^ v ^ w;        \
-   (y) ^= rotr(u ^ t,  8) ^ \
-	  rotr(v ^ t, 16) ^ \
-	  rotr(t,24)
-
-/* initialise the key schedule from the user supplied key */
-
-#define loop4(i)                                    \
-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
-    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
-    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
-    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
-    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
-}
-
-#define loop6(i)                                    \
-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
-    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
-    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
-    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
-    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
-    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
-    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
-}
-
-#define loop8(i)                                    \
-{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
-    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
-    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
-    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
-    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
-    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
-    E_KEY[8 * i + 12] = t;                \
-    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
-    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
-    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
-}
-
-static int
-aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
-{
-	struct aes_ctx *ctx = ctx_arg;
-	u32 i, t, u, v, w;
-
-	if (key_len != 16 && key_len != 24 && key_len != 32) {
-		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-		return -EINVAL;
-	}
-
-	ctx->key_length = key_len;
-
-	E_KEY[0] = u32_in (in_key);
-	E_KEY[1] = u32_in (in_key + 4);
-	E_KEY[2] = u32_in (in_key + 8);
-	E_KEY[3] = u32_in (in_key + 12);
-
-	switch (key_len) {
-	case 16:
-		t = E_KEY[3];
-		for (i = 0; i < 10; ++i)
-			loop4 (i);
-		break;
-
-	case 24:
-		E_KEY[4] = u32_in (in_key + 16);
-		t = E_KEY[5] = u32_in (in_key + 20);
-		for (i = 0; i < 8; ++i)
-			loop6 (i);
-		break;
-
-	case 32:
-		E_KEY[4] = u32_in (in_key + 16);
-		E_KEY[5] = u32_in (in_key + 20);
-		E_KEY[6] = u32_in (in_key + 24);
-		t = E_KEY[7] = u32_in (in_key + 28);
-		for (i = 0; i < 7; ++i)
-			loop8 (i);
-		break;
-	}
-
-	D_KEY[0] = E_KEY[0];
-	D_KEY[1] = E_KEY[1];
-	D_KEY[2] = E_KEY[2];
-	D_KEY[3] = E_KEY[3];
-
-	for (i = 4; i < key_len + 24; ++i) {
-		imix_col (D_KEY[i], E_KEY[i]);
-	}
-
-	return 0;
-}
-
-/* encrypt a block of text */
-
-#define f_nround(bo, bi, k) \
-    f_rn(bo, bi, 0, k);     \
-    f_rn(bo, bi, 1, k);     \
-    f_rn(bo, bi, 2, k);     \
-    f_rn(bo, bi, 3, k);     \
-    k += 4
-
-#define f_lround(bo, bi, k) \
-    f_rl(bo, bi, 0, k);     \
-    f_rl(bo, bi, 1, k);     \
-    f_rl(bo, bi, 2, k);     \
-    f_rl(bo, bi, 3, k)
-
-static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
-{
-	const struct aes_ctx *ctx = ctx_arg;
-	u32 b0[4], b1[4];
-	const u32 *kp = E_KEY + 4;
-
-	b0[0] = u32_in (in) ^ E_KEY[0];
-	b0[1] = u32_in (in + 4) ^ E_KEY[1];
-	b0[2] = u32_in (in + 8) ^ E_KEY[2];
-	b0[3] = u32_in (in + 12) ^ E_KEY[3];
-
-	if (ctx->key_length > 24) {
-		f_nround (b1, b0, kp);
-		f_nround (b0, b1, kp);
-	}
-
-	if (ctx->key_length > 16) {
-		f_nround (b1, b0, kp);
-		f_nround (b0, b1, kp);
-	}
-
-	f_nround (b1, b0, kp);
-	f_nround (b0, b1, kp);
-	f_nround (b1, b0, kp);
-	f_nround (b0, b1, kp);
-	f_nround (b1, b0, kp);
-	f_nround (b0, b1, kp);
-	f_nround (b1, b0, kp);
-	f_nround (b0, b1, kp);
-	f_nround (b1, b0, kp);
-	f_lround (b0, b1, kp);
-
-	u32_out (out, b0[0]);
-	u32_out (out + 4, b0[1]);
-	u32_out (out + 8, b0[2]);
-	u32_out (out + 12, b0[3]);
-}
-
-/* decrypt a block of text */
-
-#define i_nround(bo, bi, k) \
-    i_rn(bo, bi, 0, k);     \
-    i_rn(bo, bi, 1, k);     \
-    i_rn(bo, bi, 2, k);     \
-    i_rn(bo, bi, 3, k);     \
-    k -= 4
-
-#define i_lround(bo, bi, k) \
-    i_rl(bo, bi, 0, k);     \
-    i_rl(bo, bi, 1, k);     \
-    i_rl(bo, bi, 2, k);     \
-    i_rl(bo, bi, 3, k)
-
-static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
-{
-	const struct aes_ctx *ctx = ctx_arg;
-	u32 b0[4], b1[4];
-	const int key_len = ctx->key_length;
-	const u32 *kp = D_KEY + key_len + 20;
-
-	b0[0] = u32_in (in) ^ E_KEY[key_len + 24];
-	b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25];
-	b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26];
-	b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27];
-
-	if (key_len > 24) {
-		i_nround (b1, b0, kp);
-		i_nround (b0, b1, kp);
-	}
-
-	if (key_len > 16) {
-		i_nround (b1, b0, kp);
-		i_nround (b0, b1, kp);
-	}
-
-	i_nround (b1, b0, kp);
-	i_nround (b0, b1, kp);
-	i_nround (b1, b0, kp);
-	i_nround (b0, b1, kp);
-	i_nround (b1, b0, kp);
-	i_nround (b0, b1, kp);
-	i_nround (b1, b0, kp);
-	i_nround (b0, b1, kp);
-	i_nround (b1, b0, kp);
-	i_lround (b0, b1, kp);
-
-	u32_out (out, b0[0]);
-	u32_out (out + 4, b0[1]);
-	u32_out (out + 8, b0[2]);
-	u32_out (out + 12, b0[3]);
-}
-
-
-static struct crypto_alg aes_alg = {
-	.cra_name		=	"aes",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	AES_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct aes_ctx),
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
-	.cra_u			=	{
-		.cipher = {
-			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
-			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
-			.cia_setkey		=	aes_set_key,
-			.cia_encrypt		=	aes_encrypt,
-			.cia_decrypt		=	aes_decrypt
-		}
-	}
-};
-
-static int __init aes_init(void)
-{
-	gen_tabs();
-	return crypto_register_alg(&aes_alg);
-}
-
-static void __exit aes_fini(void)
-{
-	crypto_unregister_alg(&aes_alg);
-}
-
-module_init(aes_init);
-module_exit(aes_fini);
-
-MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/staging/rtl8192u/ieee80211/arc4.c b/drivers/staging/rtl8192u/ieee80211/arc4.c
deleted file mode 100644
index b790e9ad104c..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/arc4.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Cryptographic API
- *
- * ARC4 Cipher Algorithm
- *
- * Jon Oberheide <jon@oberheide.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/module.h>
-#include <linux/init.h>
-#include "rtl_crypto.h"
-
-#define ARC4_MIN_KEY_SIZE	1
-#define ARC4_MAX_KEY_SIZE	256
-#define ARC4_BLOCK_SIZE		1
-
-struct arc4_ctx {
-	u8 S[256];
-	u8 x, y;
-};
-
-static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
-{
-	struct arc4_ctx *ctx = ctx_arg;
-	int i, j = 0, k = 0;
-
-	ctx->x = 1;
-	ctx->y = 0;
-
-	for(i = 0; i < 256; i++)
-		ctx->S[i] = i;
-
-	for(i = 0; i < 256; i++)
-	{
-		u8 a = ctx->S[i];
-		j = (j + in_key[k] + a) & 0xff;
-		ctx->S[i] = ctx->S[j];
-		ctx->S[j] = a;
-		if((unsigned int)++k >= key_len)
-			k = 0;
-	}
-
-	return 0;
-}
-
-static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
-{
-	struct arc4_ctx *ctx = ctx_arg;
-
-	u8 *const S = ctx->S;
-	u8 x = ctx->x;
-	u8 y = ctx->y;
-	u8 a, b;
-
-	a = S[x];
-	y = (y + a) & 0xff;
-	b = S[y];
-	S[x] = b;
-	S[y] = a;
-	x = (x + 1) & 0xff;
-	*out++ = *in ^ S[(a + b) & 0xff];
-
-	ctx->x = x;
-	ctx->y = y;
-}
-
-static struct crypto_alg arc4_alg = {
-	.cra_name		=	"arc4",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	ARC4_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct arc4_ctx),
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
-	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
-	.cia_setkey		=	arc4_set_key,
-	.cia_encrypt		=	arc4_crypt,
-	.cia_decrypt		=	arc4_crypt } }
-};
-
-static int __init arc4_init(void)
-{
-	return crypto_register_alg(&arc4_alg);
-}
-
-
-static void __exit arc4_exit(void)
-{
-	crypto_unregister_alg(&arc4_alg);
-}
-
-module_init(arc4_init);
-module_exit(arc4_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
-MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
diff --git a/drivers/staging/rtl8192u/ieee80211/autoload.c b/drivers/staging/rtl8192u/ieee80211/autoload.c
deleted file mode 100644
index c97756f3b2ea..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/autoload.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Algorithm autoloader.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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 "kmap_types.h"
-
-#include <linux/kernel.h>
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/string.h>
-#include <linux/kmod.h>
-#include "internal.h"
-
-/*
- * A far more intelligent version of this is planned.  For now, just
- * try an exact match on the name of the algorithm.
- */
-void crypto_alg_autoload(const char *name)
-{
-	request_module(name);
-}
-
-struct crypto_alg *crypto_alg_mod_lookup(const char *name)
-{
-	struct crypto_alg *alg = crypto_alg_lookup(name);
-	if (alg == NULL) {
-		crypto_alg_autoload(name);
-		alg = crypto_alg_lookup(name);
-	}
-	return alg;
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/cipher.c b/drivers/staging/rtl8192u/ieee80211/cipher.c
deleted file mode 100644
index d47345c4adcf..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/cipher.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Cipher operations.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <asm/scatterlist.h>
-#include "internal.h"
-#include "scatterwalk.h"
-
-typedef void (cryptfn_t)(void *, u8 *, const u8 *);
-typedef void (procfn_t)(struct crypto_tfm *, u8 *,
-			u8*, cryptfn_t, int enc, void *, int);
-
-static inline void xor_64(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-}
-
-static inline void xor_128(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-	((u32 *)a)[2] ^= ((u32 *)b)[2];
-	((u32 *)a)[3] ^= ((u32 *)b)[3];
-}
-
-
-/*
- * Generic encrypt/decrypt wrapper for ciphers, handles operations across
- * multiple page boundaries by using temporary blocks.  In user context,
- * the kernel is given a chance to schedule us once per block.
- */
-static int crypt(struct crypto_tfm *tfm,
-		 struct scatterlist *dst,
-		 struct scatterlist *src,
-		 unsigned int nbytes, cryptfn_t crfn,
-		 procfn_t prfn, int enc, void *info)
-{
-	struct scatter_walk walk_in, walk_out;
-	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
-	u8 tmp_src[bsize];
-	u8 tmp_dst[bsize];
-
-	if (!nbytes)
-		return 0;
-
-	if (nbytes % bsize) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		return -EINVAL;
-	}
-
-	scatterwalk_start(&walk_in, src);
-	scatterwalk_start(&walk_out, dst);
-
-	for(;;) {
-		u8 *src_p, *dst_p;
-		int in_place;
-
-		scatterwalk_map(&walk_in);
-		scatterwalk_map(&walk_out);
-		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
-		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
-		in_place = scatterwalk_samebuf(&walk_in, &walk_out,
-					       src_p, dst_p);
-
-		nbytes -= bsize;
-
-		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
-
-		prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
-
-		scatterwalk_done(&walk_in, nbytes);
-
-		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
-		scatterwalk_done(&walk_out, nbytes);
-
-		if (!nbytes)
-			return 0;
-
-		crypto_yield(tfm);
-	}
-}
-
-static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-			cryptfn_t fn, int enc, void *info, int in_place)
-{
-	u8 *iv = info;
-
-	/* Null encryption */
-	if (!iv)
-		return;
-
-	if (enc) {
-		tfm->crt_u.cipher.cit_xor_block(iv, src);
-		fn(crypto_tfm_ctx(tfm), dst, iv);
-		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
-	} else {
-		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
-		u8 *buf = in_place ? stack : dst;
-
-		fn(crypto_tfm_ctx(tfm), buf, src);
-		tfm->crt_u.cipher.cit_xor_block(buf, iv);
-		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
-		if (buf != dst)
-			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
-	}
-}
-
-static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-			cryptfn_t fn, int enc, void *info, int in_place)
-{
-	fn(crypto_tfm_ctx(tfm), dst, src);
-}
-
-static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
-{
-	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
-
-	if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-		return -EINVAL;
-	} else
-		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
-				       &tfm->crt_flags);
-}
-
-static int ecb_encrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_encrypt,
-		     ecb_process, 1, NULL);
-}
-
-static int ecb_decrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-		       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_decrypt,
-		     ecb_process, 1, NULL);
-}
-
-static int cbc_encrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-		       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_encrypt,
-		     cbc_process, 1, tfm->crt_cipher.cit_iv);
-}
-
-static int cbc_encrypt_iv(struct crypto_tfm *tfm,
-			  struct scatterlist *dst,
-			  struct scatterlist *src,
-			  unsigned int nbytes, u8 *iv)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_encrypt,
-		     cbc_process, 1, iv);
-}
-
-static int cbc_decrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-		       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_decrypt,
-		     cbc_process, 0, tfm->crt_cipher.cit_iv);
-}
-
-static int cbc_decrypt_iv(struct crypto_tfm *tfm,
-			  struct scatterlist *dst,
-			  struct scatterlist *src,
-			  unsigned int nbytes, u8 *iv)
-{
-	return crypt(tfm, dst, src, nbytes,
-		     tfm->__crt_alg->cra_cipher.cia_decrypt,
-		     cbc_process, 0, iv);
-}
-
-static int nocrypt(struct crypto_tfm *tfm,
-		   struct scatterlist *dst,
-		   struct scatterlist *src,
-		   unsigned int nbytes)
-{
-	return -ENOSYS;
-}
-
-static int nocrypt_iv(struct crypto_tfm *tfm,
-		      struct scatterlist *dst,
-		      struct scatterlist *src,
-		      unsigned int nbytes, u8 *iv)
-{
-	return -ENOSYS;
-}
-
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
-
-	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
-	if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
-		tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
-
-	return 0;
-}
-
-int crypto_init_cipher_ops(struct crypto_tfm *tfm)
-{
-	int ret = 0;
-	struct cipher_tfm *ops = &tfm->crt_cipher;
-
-	ops->cit_setkey = setkey;
-
-	switch (tfm->crt_cipher.cit_mode) {
-	case CRYPTO_TFM_MODE_ECB:
-		ops->cit_encrypt = ecb_encrypt;
-		ops->cit_decrypt = ecb_decrypt;
-		break;
-
-	case CRYPTO_TFM_MODE_CBC:
-		ops->cit_encrypt = cbc_encrypt;
-		ops->cit_decrypt = cbc_decrypt;
-		ops->cit_encrypt_iv = cbc_encrypt_iv;
-		ops->cit_decrypt_iv = cbc_decrypt_iv;
-		break;
-
-	case CRYPTO_TFM_MODE_CFB:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-
-	case CRYPTO_TFM_MODE_CTR:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-
-	default:
-		BUG();
-	}
-
-	if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
-
-		switch (crypto_tfm_alg_blocksize(tfm)) {
-		case 8:
-			ops->cit_xor_block = xor_64;
-			break;
-
-		case 16:
-			ops->cit_xor_block = xor_128;
-			break;
-
-		default:
-			printk(KERN_WARNING "%s: block size %u not supported\n",
-			       crypto_tfm_alg_name(tfm),
-			       crypto_tfm_alg_blocksize(tfm));
-			ret = -EINVAL;
-			goto out;
-		}
-
-		ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
-		ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
-		if (ops->cit_iv == NULL)
-			ret = -ENOMEM;
-	}
-
-out:
-	return ret;
-}
-
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
-{
-	kfree(tfm->crt_cipher.cit_iv);
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/compress.c b/drivers/staging/rtl8192u/ieee80211/compress.c
deleted file mode 100644
index 5416ab63a738..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/compress.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Compression operations.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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/types.h>
-/*#include <linux/crypto.h>*/
-#include "rtl_crypto.h"
-#include <linux/errno.h>
-#include <linux/scatterlist.h>
-#include <linux/string.h>
-#include "internal.h"
-
-static int crypto_compress(struct crypto_tfm *tfm,
-			    const u8 *src, unsigned int slen,
-			    u8 *dst, unsigned int *dlen)
-{
-	return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm),
-							 src, slen, dst,
-							 dlen);
-}
-
-static int crypto_decompress(struct crypto_tfm *tfm,
-			     const u8 *src, unsigned int slen,
-			     u8 *dst, unsigned int *dlen)
-{
-	return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm),
-							   src, slen, dst,
-							   dlen);
-}
-
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
-}
-
-int crypto_init_compress_ops(struct crypto_tfm *tfm)
-{
-	int ret = 0;
-	struct compress_tfm *ops = &tfm->crt_compress;
-
-	ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm));
-	if (ret)
-		goto out;
-
-	ops->cot_compress = crypto_compress;
-	ops->cot_decompress = crypto_decompress;
-
-out:
-	return ret;
-}
-
-void crypto_exit_compress_ops(struct crypto_tfm *tfm)
-{
-	tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/crypto_compat.h b/drivers/staging/rtl8192u/ieee80211/crypto_compat.h
deleted file mode 100644
index 2ba374a64178..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/crypto_compat.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Header file to maintain compatibility among different kernel versions.
- *
- * Copyright (c) 2004-2006  <lawrence_wang@realsil.com.cn>
- *
- * 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/crypto.h>
-
-static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-					struct scatterlist *dst,
-					struct scatterlist *src,
-					unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
-}
-
-
-static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-					struct scatterlist *dst,
-					struct scatterlist *src,
-					unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
-}
-
- struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
-{
-	struct crypto_tfm *tfm = NULL;
-	int err;
-	printk("call crypto_alloc_tfm!!!\n");
-	do {
-		struct crypto_alg *alg;
-
-		alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
-		err = PTR_ERR(alg);
-		if (IS_ERR(alg))
-			continue;
-
-		tfm = __crypto_alloc_tfm(alg, flags);
-		err = 0;
-		if (IS_ERR(tfm)) {
-			crypto_mod_put(alg);
-			err = PTR_ERR(tfm);
-			tfm = NULL;
-		}
-	} while (err == -EAGAIN && !signal_pending(current));
-
-	return tfm;
-}
-//EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
-//EXPORT_SYMBOL_GPL(crypto_free_tfm);
diff --git a/drivers/staging/rtl8192u/ieee80211/digest.c b/drivers/staging/rtl8192u/ieee80211/digest.c
deleted file mode 100644
index 05e7497fd106..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/digest.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Digest operations.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/highmem.h>
-#include <asm/scatterlist.h>
-#include "internal.h"
-
-static void init(struct crypto_tfm *tfm)
-{
-	tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
-}
-
-static void update(struct crypto_tfm *tfm,
-		   struct scatterlist *sg, unsigned int nsg)
-{
-	unsigned int i;
-
-	for (i = 0; i < nsg; i++) {
-
-		struct page *pg = sg[i].page;
-		unsigned int offset = sg[i].offset;
-		unsigned int l = sg[i].length;
-
-		do {
-			unsigned int bytes_from_page = min(l, ((unsigned int)
-							   (PAGE_SIZE)) -
-							   offset);
-			char *p = kmap_atomic(pg) + offset;
-
-			tfm->__crt_alg->cra_digest.dia_update
-					(crypto_tfm_ctx(tfm), p,
-					 bytes_from_page);
-			kunmap_atomic(p);
-			crypto_yield(tfm);
-			offset = 0;
-			pg++;
-			l -= bytes_from_page;
-		} while (l > 0);
-	}
-}
-
-static void final(struct crypto_tfm *tfm, u8 *out)
-{
-	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
-}
-
-static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
-{
-	u32 flags;
-	if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
-		return -ENOSYS;
-	return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
-						     key, keylen, &flags);
-}
-
-static void digest(struct crypto_tfm *tfm,
-		   struct scatterlist *sg, unsigned int nsg, u8 *out)
-{
-	unsigned int i;
-
-	tfm->crt_digest.dit_init(tfm);
-
-	for (i = 0; i < nsg; i++) {
-		char *p = kmap_atomic(sg[i].page) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
-						      p, sg[i].length);
-		kunmap_atomic(p);
-		crypto_yield(tfm);
-	}
-	crypto_digest_final(tfm, out);
-}
-
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
-}
-
-int crypto_init_digest_ops(struct crypto_tfm *tfm)
-{
-	struct digest_tfm *ops = &tfm->crt_digest;
-
-	ops->dit_init	= init;
-	ops->dit_update	= update;
-	ops->dit_final	= final;
-	ops->dit_digest	= digest;
-	ops->dit_setkey	= setkey;
-
-	return crypto_alloc_hmac_block(tfm);
-}
-
-void crypto_exit_digest_ops(struct crypto_tfm *tfm)
-{
-	crypto_free_hmac_block(tfm);
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/internal.h b/drivers/staging/rtl8192u/ieee80211/internal.h
deleted file mode 100644
index 6f54cfe8a467..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/internal.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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 _CRYPTO_INTERNAL_H
-#define _CRYPTO_INTERNAL_H
-
-
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
-#include <asm/kmap_types.h>
-
-
-static inline void crypto_yield(struct crypto_tfm *tfm)
-{
-	if (!in_softirq())
-		cond_resched();
-}
-
-static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
-{
-	return (void *)&tfm[1];
-}
-
-struct crypto_alg *crypto_alg_lookup(const char *name);
-
-#ifdef CONFIG_KMOD
-void crypto_alg_autoload(const char *name);
-struct crypto_alg *crypto_alg_mod_lookup(const char *name);
-#else
-static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
-{
-	return crypto_alg_lookup(name);
-}
-#endif
-
-#ifdef CONFIG_CRYPTO_HMAC
-int crypto_alloc_hmac_block(struct crypto_tfm *tfm);
-void crypto_free_hmac_block(struct crypto_tfm *tfm);
-#else
-static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
-{
-	return 0;
-}
-
-static inline void crypto_free_hmac_block(struct crypto_tfm *tfm)
-{ }
-#endif
-
-#ifdef CONFIG_PROC_FS
-void __init crypto_init_proc(void);
-#else
-static inline void crypto_init_proc(void)
-{ }
-#endif
-
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
-
-int crypto_init_digest_ops(struct crypto_tfm *tfm);
-int crypto_init_cipher_ops(struct crypto_tfm *tfm);
-int crypto_init_compress_ops(struct crypto_tfm *tfm);
-
-void crypto_exit_digest_ops(struct crypto_tfm *tfm);
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
-void crypto_exit_compress_ops(struct crypto_tfm *tfm);
-
-#endif	/* _CRYPTO_INTERNAL_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/michael_mic.c b/drivers/staging/rtl8192u/ieee80211/michael_mic.c
deleted file mode 100644
index df256e487c20..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/michael_mic.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Cryptographic API
- *
- * Michael MIC (IEEE 802.11i/TKIP) keyed digest
- *
- * Copyright (c) 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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-
-
-struct michael_mic_ctx {
-	u8 pending[4];
-	size_t pending_len;
-
-	u32 l, r;
-};
-
-
-static inline u32 rotl(u32 val, int bits)
-{
-	return (val << bits) | (val >> (32 - bits));
-}
-
-
-static inline u32 rotr(u32 val, int bits)
-{
-	return (val >> bits) | (val << (32 - bits));
-}
-
-
-static inline u32 xswap(u32 val)
-{
-	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
-}
-
-
-#define michael_block(l, r)	\
-do {				\
-	r ^= rotl(l, 17);	\
-	l += r;			\
-	r ^= xswap(l);		\
-	l += r;			\
-	r ^= rotl(l, 3);	\
-	l += r;			\
-	r ^= rotr(l, 2);	\
-	l += r;			\
-} while (0)
-
-
-static inline u32 get_le32(const u8 *p)
-{
-	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-
-static inline void put_le32(u8 *p, u32 v)
-{
-	p[0] = v;
-	p[1] = v >> 8;
-	p[2] = v >> 16;
-	p[3] = v >> 24;
-}
-
-
-static void michael_init(void *ctx)
-{
-	struct michael_mic_ctx *mctx = ctx;
-	mctx->pending_len = 0;
-}
-
-
-static void michael_update(void *ctx, const u8 *data, unsigned int len)
-{
-	struct michael_mic_ctx *mctx = ctx;
-
-	if (mctx->pending_len) {
-		int flen = 4 - mctx->pending_len;
-		if (flen > len)
-			flen = len;
-		memcpy(&mctx->pending[mctx->pending_len], data, flen);
-		mctx->pending_len += flen;
-		data += flen;
-		len -= flen;
-
-		if (mctx->pending_len < 4)
-			return;
-
-		mctx->l ^= get_le32(mctx->pending);
-		michael_block(mctx->l, mctx->r);
-		mctx->pending_len = 0;
-	}
-
-	while (len >= 4) {
-		mctx->l ^= get_le32(data);
-		michael_block(mctx->l, mctx->r);
-		data += 4;
-		len -= 4;
-	}
-
-	if (len > 0) {
-		mctx->pending_len = len;
-		memcpy(mctx->pending, data, len);
-	}
-}
-
-
-static void michael_final(void *ctx, u8 *out)
-{
-	struct michael_mic_ctx *mctx = ctx;
-	u8 *data = mctx->pending;
-
-	/* Last block and padding (0x5a, 4..7 x 0) */
-	switch (mctx->pending_len) {
-	case 0:
-		mctx->l ^= 0x5a;
-		break;
-	case 1:
-		mctx->l ^= data[0] | 0x5a00;
-		break;
-	case 2:
-		mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
-		break;
-	case 3:
-		mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
-			0x5a000000;
-		break;
-	}
-	michael_block(mctx->l, mctx->r);
-	/* l ^= 0; */
-	michael_block(mctx->l, mctx->r);
-
-	put_le32(out, mctx->l);
-	put_le32(out + 4, mctx->r);
-}
-
-
-static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
-			  u32 *flags)
-{
-	struct michael_mic_ctx *mctx = ctx;
-	if (keylen != 8) {
-		if (flags)
-			*flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
-		return -EINVAL;
-	}
-	mctx->l = get_le32(key);
-	mctx->r = get_le32(key + 4);
-	return 0;
-}
-
-
-static struct crypto_alg michael_mic_alg = {
-	.cra_name	= "michael_mic",
-	.cra_flags	= CRYPTO_ALG_TYPE_DIGEST,
-	.cra_blocksize	= 8,
-	.cra_ctxsize	= sizeof(struct michael_mic_ctx),
-	.cra_module	= THIS_MODULE,
-	.cra_list	= LIST_HEAD_INIT(michael_mic_alg.cra_list),
-	.cra_u		= { .digest = {
-	.dia_digestsize	= 8,
-	.dia_init	= michael_init,
-	.dia_update	= michael_update,
-	.dia_final	= michael_final,
-	.dia_setkey	= michael_setkey } }
-};
-
-
-static int __init michael_mic_init(void)
-{
-	return crypto_register_alg(&michael_mic_alg);
-}
-
-
-static void __exit michael_mic_exit(void)
-{
-	crypto_unregister_alg(&michael_mic_alg);
-}
-
-
-module_init(michael_mic_init);
-module_exit(michael_mic_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Michael MIC");
-MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");
diff --git a/drivers/staging/rtl8192u/ieee80211/proc.c b/drivers/staging/rtl8192u/ieee80211/proc.c
deleted file mode 100644
index c426dfdd9fdd..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/proc.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Scatterlist Cryptographic API.
- *
- * Procfs information.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute 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/init.h>
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/rwsem.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include "internal.h"
-
-extern struct list_head crypto_alg_list;
-extern struct rw_semaphore crypto_alg_sem;
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	struct list_head *v;
-	loff_t n = *pos;
-
-	down_read(&crypto_alg_sem);
-	list_for_each(v, &crypto_alg_list)
-		if (!n--)
-			return list_entry(v, struct crypto_alg, cra_list);
-	return NULL;
-}
-
-static void *c_next(struct seq_file *m, void *p, loff_t *pos)
-{
-	struct list_head *v = p;
-
-	(*pos)++;
-	v = v->next;
-	return (v == &crypto_alg_list) ?
-		NULL : list_entry(v, struct crypto_alg, cra_list);
-}
-
-static void c_stop(struct seq_file *m, void *p)
-{
-	up_read(&crypto_alg_sem);
-}
-
-static int c_show(struct seq_file *m, void *p)
-{
-	struct crypto_alg *alg = (struct crypto_alg *)p;
-
-	seq_printf(m, "name         : %s\n", alg->cra_name);
-	seq_printf(m, "module       : %s\n",
-		   (alg->cra_module ?
-		    alg->cra_module->name :
-		    "kernel"));
-
-	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
-	case CRYPTO_ALG_TYPE_CIPHER:
-		seq_printf(m, "type         : cipher\n");
-		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-		seq_printf(m, "min keysize  : %u\n",
-					alg->cra_cipher.cia_min_keysize);
-		seq_printf(m, "max keysize  : %u\n",
-					alg->cra_cipher.cia_max_keysize);
-		break;
-
-	case CRYPTO_ALG_TYPE_DIGEST:
-		seq_printf(m, "type         : digest\n");
-		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-		seq_printf(m, "digestsize   : %u\n",
-			   alg->cra_digest.dia_digestsize);
-		break;
-	case CRYPTO_ALG_TYPE_COMPRESS:
-		seq_printf(m, "type         : compression\n");
-		break;
-	default:
-		seq_printf(m, "type         : unknown\n");
-		break;
-	}
-
-	seq_putc(m, '\n');
-	return 0;
-}
-
-static struct seq_operations crypto_seq_ops = {
-	.start		= c_start,
-	.next		= c_next,
-	.stop		= c_stop,
-	.show		= c_show
-};
-
-static int crypto_info_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &crypto_seq_ops);
-}
-
-static const struct file_operations proc_crypto_ops = {
-	.open		= crypto_info_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release
-};
-
-void __init crypto_init_proc(void)
-{
-	proc_create("crypto", 0, NULL, &proc_crypto_ops);
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h b/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h
deleted file mode 100644
index c3c87108ee9e..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/rtl_crypto.h
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Scatterlist Cryptographic API.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2002 David S. Miller (davem@redhat.com)
- *
- * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels M鰈ler.
- *
- * This program is free software; you can redistribute 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_CRYPTO_H
-#define _LINUX_CRYPTO_H
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <asm/page.h>
-#include <asm/errno.h>
-
-#define crypto_register_alg crypto_register_alg_rsl
-#define crypto_unregister_alg crypto_unregister_alg_rsl
-#define crypto_alloc_tfm crypto_alloc_tfm_rsl
-#define crypto_free_tfm crypto_free_tfm_rsl
-#define crypto_alg_available crypto_alg_available_rsl
-
-/*
- * Algorithm masks and types.
- */
-#define CRYPTO_ALG_TYPE_MASK		0x000000ff
-#define CRYPTO_ALG_TYPE_CIPHER		0x00000001
-#define CRYPTO_ALG_TYPE_DIGEST		0x00000002
-#define CRYPTO_ALG_TYPE_COMPRESS	0x00000004
-
-/*
- * Transform masks and values (for crt_flags).
- */
-#define CRYPTO_TFM_MODE_MASK		0x000000ff
-#define CRYPTO_TFM_REQ_MASK		0x000fff00
-#define CRYPTO_TFM_RES_MASK		0xfff00000
-
-#define CRYPTO_TFM_MODE_ECB		0x00000001
-#define CRYPTO_TFM_MODE_CBC		0x00000002
-#define CRYPTO_TFM_MODE_CFB		0x00000004
-#define CRYPTO_TFM_MODE_CTR		0x00000008
-
-#define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
-#define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
-#define CRYPTO_TFM_RES_BAD_KEY_LEN	0x00200000
-#define CRYPTO_TFM_RES_BAD_KEY_SCHED	0x00400000
-#define CRYPTO_TFM_RES_BAD_BLOCK_LEN	0x00800000
-#define CRYPTO_TFM_RES_BAD_FLAGS	0x01000000
-
-/*
- * Miscellaneous stuff.
- */
-#define CRYPTO_UNSPEC			0
-#define CRYPTO_MAX_ALG_NAME		64
-
-struct scatterlist;
-
-/*
- * Algorithms: modular crypto algorithm implementations, managed
- * via crypto_register_alg() and crypto_unregister_alg().
- */
-struct cipher_alg {
-	unsigned int cia_min_keysize;
-	unsigned int cia_max_keysize;
-	int (*cia_setkey)(void *ctx, const u8 *key,
-			  unsigned int keylen, u32 *flags);
-	void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
-	void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
-};
-
-struct digest_alg {
-	unsigned int dia_digestsize;
-	void (*dia_init)(void *ctx);
-	void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
-	void (*dia_final)(void *ctx, u8 *out);
-	int (*dia_setkey)(void *ctx, const u8 *key,
-			  unsigned int keylen, u32 *flags);
-};
-
-struct compress_alg {
-	int (*coa_init)(void *ctx);
-	void (*coa_exit)(void *ctx);
-	int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
-			    u8 *dst, unsigned int *dlen);
-	int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
-			      u8 *dst, unsigned int *dlen);
-};
-
-#define cra_cipher	cra_u.cipher
-#define cra_digest	cra_u.digest
-#define cra_compress	cra_u.compress
-
-struct crypto_alg {
-	struct list_head cra_list;
-	u32 cra_flags;
-	unsigned int cra_blocksize;
-	unsigned int cra_ctxsize;
-	const char cra_name[CRYPTO_MAX_ALG_NAME];
-
-	union {
-		struct cipher_alg cipher;
-		struct digest_alg digest;
-		struct compress_alg compress;
-	} cra_u;
-
-	struct module *cra_module;
-};
-
-/*
- * Algorithm registration interface.
- */
-int crypto_register_alg(struct crypto_alg *alg);
-int crypto_unregister_alg(struct crypto_alg *alg);
-
-/*
- * Algorithm query interface.
- */
-int crypto_alg_available(const char *name, u32 flags);
-
-/*
- * Transforms: user-instantiated objects which encapsulate algorithms
- * and core processing logic.  Managed via crypto_alloc_tfm() and
- * crypto_free_tfm(), as well as the various helpers below.
- */
-struct crypto_tfm;
-
-struct cipher_tfm {
-	void *cit_iv;
-	unsigned int cit_ivsize;
-	u32 cit_mode;
-	int (*cit_setkey)(struct crypto_tfm *tfm,
-			  const u8 *key, unsigned int keylen);
-	int (*cit_encrypt)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes);
-	int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
-			      struct scatterlist *dst,
-			      struct scatterlist *src,
-			      unsigned int nbytes, u8 *iv);
-	int (*cit_decrypt)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes);
-	int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes, u8 *iv);
-	void (*cit_xor_block)(u8 *dst, const u8 *src);
-};
-
-struct digest_tfm {
-	void (*dit_init)(struct crypto_tfm *tfm);
-	void (*dit_update)(struct crypto_tfm *tfm,
-			   struct scatterlist *sg, unsigned int nsg);
-	void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
-	void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
-			   unsigned int nsg, u8 *out);
-	int (*dit_setkey)(struct crypto_tfm *tfm,
-			  const u8 *key, unsigned int keylen);
-#ifdef CONFIG_CRYPTO_HMAC
-	void *dit_hmac_block;
-#endif
-};
-
-struct compress_tfm {
-	int (*cot_compress)(struct crypto_tfm *tfm,
-			    const u8 *src, unsigned int slen,
-			    u8 *dst, unsigned int *dlen);
-	int (*cot_decompress)(struct crypto_tfm *tfm,
-			      const u8 *src, unsigned int slen,
-			      u8 *dst, unsigned int *dlen);
-};
-
-#define crt_cipher	crt_u.cipher
-#define crt_digest	crt_u.digest
-#define crt_compress	crt_u.compress
-
-struct crypto_tfm {
-
-	u32 crt_flags;
-
-	union {
-		struct cipher_tfm cipher;
-		struct digest_tfm digest;
-		struct compress_tfm compress;
-	} crt_u;
-
-	struct crypto_alg *__crt_alg;
-};
-
-/*
- * Transform user interface.
- */
-
-/*
- * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
- * If that fails and the kernel supports dynamically loadable modules, it
- * will then attempt to load a module of the same name or alias.  A refcount
- * is grabbed on the algorithm which is then associated with the new transform.
- *
- * crypto_free_tfm() frees up the transform and any associated resources,
- * then drops the refcount on the associated algorithm.
- */
-struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
-void crypto_free_tfm(struct crypto_tfm *tfm);
-
-/*
- * Transform helpers which query the underlying algorithm.
- */
-static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
-{
-	return tfm->__crt_alg->cra_name;
-}
-
-static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
-{
-	struct crypto_alg *alg = tfm->__crt_alg;
-
-	if (alg->cra_module)
-		return alg->cra_module->name;
-	else
-		return NULL;
-}
-
-static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
-{
-	return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
-}
-
-static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_min_keysize;
-}
-
-static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_max_keysize;
-}
-
-static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_ivsize;
-}
-
-static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
-{
-	return tfm->__crt_alg->cra_blocksize;
-}
-
-static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	return tfm->__crt_alg->cra_digest.dia_digestsize;
-}
-
-/*
- * API wrappers.
- */
-static inline void crypto_digest_init(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	tfm->crt_digest.dit_init(tfm);
-}
-
-static inline void crypto_digest_update(struct crypto_tfm *tfm,
-					struct scatterlist *sg,
-					unsigned int nsg)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	tfm->crt_digest.dit_update(tfm, sg, nsg);
-}
-
-static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	tfm->crt_digest.dit_final(tfm, out);
-}
-
-static inline void crypto_digest_digest(struct crypto_tfm *tfm,
-					struct scatterlist *sg,
-					unsigned int nsg, u8 *out)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
-}
-
-static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
-				       const u8 *key, unsigned int keylen)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	if (tfm->crt_digest.dit_setkey == NULL)
-		return -ENOSYS;
-	return tfm->crt_digest.dit_setkey(tfm, key, keylen);
-}
-
-static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
-				       const u8 *key, unsigned int keylen)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
-}
-
-static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-					struct scatterlist *dst,
-					struct scatterlist *src,
-					unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
-}
-
-static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
-					   struct scatterlist *dst,
-					   struct scatterlist *src,
-					   unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
-	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
-}
-
-static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-					struct scatterlist *dst,
-					struct scatterlist *src,
-					unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
-}
-
-static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
-					   struct scatterlist *dst,
-					   struct scatterlist *src,
-					   unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
-	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
-}
-
-static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
-					const u8 *src, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(tfm->crt_cipher.cit_iv, src, len);
-}
-
-static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
-					u8 *dst, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(dst, tfm->crt_cipher.cit_iv, len);
-}
-
-static inline int crypto_comp_compress(struct crypto_tfm *tfm,
-				       const u8 *src, unsigned int slen,
-				       u8 *dst, unsigned int *dlen)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
-	return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
-}
-
-static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
-					 const u8 *src, unsigned int slen,
-					 u8 *dst, unsigned int *dlen)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
-	return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
-}
-
-/*
- * HMAC support.
- */
-#ifdef CONFIG_CRYPTO_HMAC
-void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
-void crypto_hmac_update(struct crypto_tfm *tfm,
-			struct scatterlist *sg, unsigned int nsg);
-void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
-		       unsigned int *keylen, u8 *out);
-void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
-		 struct scatterlist *sg, unsigned int nsg, u8 *out);
-#endif	/* CONFIG_CRYPTO_HMAC */
-
-#endif	/* _LINUX_CRYPTO_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c
deleted file mode 100644
index 8b73f6cefcf9..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Cipher operations.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *               2002 Adam J. Richter <adam@yggdrasil.com>
- *               2004 Jean-Luc Cooke <jlcooke@certainkey.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/kernel.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
-#include <asm/scatterlist.h>
-#include "internal.h"
-#include "scatterwalk.h"
-
-void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
-	if (nbytes <= walk->len_this_page &&
-	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
-	    PAGE_CACHE_SIZE)
-		return walk->data;
-	else
-		return scratch;
-}
-
-static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
-{
-	if (out)
-		memcpy(sgdata, buf, nbytes);
-	else
-		memcpy(buf, sgdata, nbytes);
-}
-
-void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
-{
-	unsigned int rest_of_page;
-
-	walk->sg = sg;
-
-	walk->page = sg->page;
-	walk->len_this_segment = sg->length;
-
-	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
-	walk->len_this_page = min(sg->length, rest_of_page);
-	walk->offset = sg->offset;
-}
-
-void scatterwalk_map(struct scatter_walk *walk)
-{
-	walk->data = kmap_atomic(walk->page) + walk->offset;
-}
-
-static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
-				 unsigned int more)
-{
-	/* walk->data may be pointing the first byte of the next page;
-	   however, we know we transferred at least one byte.  So,
-	   walk->data - 1 will be a virtual address in the mapped page. */
-
-	if (out)
-		flush_dcache_page(walk->page);
-
-	if (more) {
-		walk->len_this_segment -= walk->len_this_page;
-
-		if (walk->len_this_segment) {
-			walk->page++;
-			walk->len_this_page = min(walk->len_this_segment,
-						  (unsigned)PAGE_CACHE_SIZE);
-			walk->offset = 0;
-		}
-		else
-			scatterwalk_start(walk, sg_next(walk->sg));
-	}
-}
-
-void scatterwalk_done(struct scatter_walk *walk, int out, int more)
-{
-	crypto_kunmap(walk->data, out);
-	if (walk->len_this_page == 0 || !more)
-		scatterwalk_pagedone(walk, out, more);
-}
-
-/*
- * Do not call this unless the total length of all of the fragments
- * has been verified as multiple of the block size.
- */
-int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
-			   size_t nbytes)
-{
-	if (buf != walk->data) {
-		while (nbytes > walk->len_this_page) {
-			memcpy_dir(buf, walk->data, walk->len_this_page, out);
-			buf += walk->len_this_page;
-			nbytes -= walk->len_this_page;
-
-			kunmap_atomic(walk->data);
-			scatterwalk_pagedone(walk, out, 1);
-			scatterwalk_map(walk);
-		}
-
-		memcpy_dir(buf, walk->data, nbytes, out);
-	}
-
-	walk->offset += nbytes;
-	walk->len_this_page -= nbytes;
-	walk->len_this_segment -= nbytes;
-	return 0;
-}
diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.h b/drivers/staging/rtl8192u/ieee80211/scatterwalk.h
deleted file mode 100644
index b16446519017..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/scatterwalk.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
- * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.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 _CRYPTO_SCATTERWALK_H
-#define _CRYPTO_SCATTERWALK_H
-#include <linux/mm.h>
-#include <asm/scatterlist.h>
-
-struct scatter_walk {
-	struct scatterlist	*sg;
-	struct page		*page;
-	void			*data;
-	unsigned int		len_this_page;
-	unsigned int		len_this_segment;
-	unsigned int		offset;
-};
-
-/* Define sg_next is an inline routine now in case we want to change
-   scatterlist to a linked list later. */
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
-{
-	return sg + 1;
-}
-
-static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
-				      struct scatter_walk *walk_out,
-				      void *src_p, void *dst_p)
-{
-	return walk_in->page == walk_out->page &&
-	       walk_in->offset == walk_out->offset &&
-	       walk_in->data == src_p && walk_out->data == dst_p;
-}
-
-void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
-void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
-int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
-void scatterwalk_map(struct scatter_walk *walk, int out);
-void scatterwalk_done(struct scatter_walk *walk, int out, int more);
-
-#endif  /* _CRYPTO_SCATTERWALK_H */
diff --git a/drivers/staging/rtl8192u/r819xU_HTGen.h b/drivers/staging/rtl8192u/r819xU_HTGen.h
deleted file mode 100644
index 6a4678f7da5f..000000000000
--- a/drivers/staging/rtl8192u/r819xU_HTGen.h
+++ /dev/null
@@ -1,12 +0,0 @@
-//
-// IOT Action for different AP
-//
-typedef enum _HT_IOT_ACTION{
-	HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
-	HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
-	HT_IOT_ACT_DECLARE_MCS13 = 0x00000004,
-	HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000008,
-	HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000010,
-	HT_IOT_ACT_CDD_FSYNC = 0x00000020,
-	HT_IOT_ACT_PURE_N_MODE = 0x00000040,
-}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h
deleted file mode 100644
index 2cbb8e6584f8..000000000000
--- a/drivers/staging/rtl8192u/r819xU_HTType.h
+++ /dev/null
@@ -1,379 +0,0 @@
-#ifndef _R819XU_HTTYPE_H_
-#define _R819XU_HTTYPE_H_
-
-
-/*----------------------------------------------------------------------
- * The HT Capability element is present in beacons, association request,
- * reassociation request and probe response frames
- *----------------------------------------------------------------------*/
-
-/* Operation mode value */
-#define HT_OPMODE_NO_PROTECT		0
-#define HT_OPMODE_OPTIONAL		1
-#define HT_OPMODE_40MHZ_PROTECT		2
-#define HT_OPMODE_MIXED			3
-
-/* MIMO Power Save Settings */
-#define MIMO_PS_STATIC			0
-#define MIMO_PS_DYNAMIC			1
-#define MIMO_PS_NOLIMIT			3
-
-
-/* There should be 128 bits to cover all of the MCS rates. However, since
- * 8190 does not support too much rates, one integer is quite enough. */
-
-#define sHTCLng				4
-
-
-#define HT_SUPPORTED_MCS_1SS_BITMAP	0x000000ff
-#define HT_SUPPORTED_MCS_2SS_BITMAP	0x0000ff00
-#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP	\
-		(HT_MCS_1SS_BITMAP | HT_MCS_1SS_2SS_BITMAP)
-
-
-typedef enum _HT_MCS_RATE {
-	HT_MCS0   = 0x00000001,
-	HT_MCS1   = 0x00000002,
-	HT_MCS2   = 0x00000004,
-	HT_MCS3   = 0x00000008,
-	HT_MCS4   = 0x00000010,
-	HT_MCS5   = 0x00000020,
-	HT_MCS6   = 0x00000040,
-	HT_MCS7   = 0x00000080,
-	HT_MCS8   = 0x00000100,
-	HT_MCS9   = 0x00000200,
-	HT_MCS10  = 0x00000400,
-	HT_MCS11  = 0x00000800,
-	HT_MCS12  = 0x00001000,
-	HT_MCS13  = 0x00002000,
-	HT_MCS14  = 0x00004000,
-	HT_MCS15  = 0x00008000,
-	/* Do not define MCS32 here although 8190 support MCS32 */
-} HT_MCS_RATE, *PHT_MCS_RATE;
-
-/* Represent Channel Width in HT Capabilities */
-typedef enum _HT_CHANNEL_WIDTH {
-	HT_CHANNEL_WIDTH_20    = 0,
-	HT_CHANNEL_WIDTH_20_40 = 1,
-} HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
-
-/* Represent Extension Channel Offset in HT Capabilities
- * This is available only in 40Mhz mode. */
-typedef enum _HT_EXTCHNL_OFFSET {
-	HT_EXTCHNL_OFFSET_NO_EXT = 0,
-	HT_EXTCHNL_OFFSET_UPPER  = 1,
-	HT_EXTCHNL_OFFSET_NO_DEF = 2,
-	HT_EXTCHNL_OFFSET_LOWER  = 3,
-} HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
-
-typedef enum _CHNLOP {
-	CHNLOP_NONE   = 0,	/* No Action now */
-	CHNLOP_SCAN   = 1,	/* Scan in progress */
-	CHNLOP_SWBW   = 2,	/* Bandwidth switching in progress */
-	CHNLOP_SWCHNL = 3,	/* Software Channel switching in progress */
-} CHNLOP, *PCHNLOP;
-
-/* Determine if the Channel Operation is in progress */
-#define CHHLOP_IN_PROGRESS(_pHTInfo)	\
-		(((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE)
-
-
-typedef enum _HT_ACTION {
-	ACT_RECOMMAND_WIDTH		= 0,
-	ACT_MIMO_PWR_SAVE		= 1,
-	ACT_PSMP			= 2,
-	ACT_SET_PCO_PHASE		= 3,
-	ACT_MIMO_CHL_MEASURE		= 4,
-	ACT_RECIPROCITY_CORRECT		= 5,
-	ACT_MIMO_CSI_MATRICS		= 6,
-	ACT_MIMO_NOCOMPR_STEER		= 7,
-	ACT_MIMO_COMPR_STEER		= 8,
-	ACT_ANTENNA_SELECT		= 9,
-} HT_ACTION, *PHT_ACTION;
-
-
-/* Define sub-carrier mode for 40MHZ. */
-typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier {
-	SC_MODE_DUPLICATE = 0,
-	SC_MODE_LOWER     = 1,
-	SC_MODE_UPPER     = 2,
-	SC_MODE_FULL40MHZ = 3,
-} HT_BW40_SC_E;
-
-typedef	struct _HT_CAPABILITY_ELE {
-
-	/* HT capability info */
-	u8	AdvCoding:1;
-	u8	ChlWidth:1;
-	u8	MimoPwrSave:2;
-	u8	GreenField:1;
-	u8	ShortGI20Mhz:1;
-	u8	ShortGI40Mhz:1;
-	u8	TxSTBC:1;
-	u8	RxSTBC:2;
-	u8	DelayBA:1;
-	u8	MaxAMSDUSize:1;
-	u8	DssCCk:1;
-	u8	PSMP:1;
-	u8	Rsvd1:1;
-	u8	LSigTxopProtect:1;
-
-	/* MAC HT parameters info */
-	u8	MaxRxAMPDUFactor:2;
-	u8	MPDUDensity:3;
-	u8	Rsvd2:3;
-
-	/* Supported MCS set */
-	u8	MCS[16];
-
-
-	/* Extended HT Capability Info */
-	u16	ExtHTCapInfo;
-
-	/* TXBF Capabilities */
-	u8	TxBFCap[4];
-
-	/* Antenna Selection Capabilities */
-	u8	ASCap;
-
-} __packed HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
-
-/*------------------------------------------------------------
- * The HT Information element is present in beacons
- * Only AP is required to include this element
- *------------------------------------------------------------*/
-
-typedef struct _HT_INFORMATION_ELE {
-	u8	ControlChl;
-
-	u8	ExtChlOffset:2;
-	u8	RecommemdedTxWidth:1;
-	u8	RIFS:1;
-	u8	PSMPAccessOnly:1;
-	u8	SrvIntGranularity:3;
-
-	u8	OptMode:2;
-	u8	NonGFDevPresent:1;
-	u8	Revd1:5;
-	u8	Revd2:8;
-
-	u8	Rsvd3:6;
-	u8	DualBeacon:1;
-	u8	DualCTSProtect:1;
-
-	u8	SecondaryBeacon:1;
-	u8	LSigTxopProtectFull:1;
-	u8	PcoActive:1;
-	u8	PcoPhase:1;
-	u8	Rsvd4:4;
-
-	u8	BasicMSC[16];
-} __packed HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
-
-/* MIMO Power Save control field.
- * This is appear in MIMO Power Save Action Frame */
-typedef struct _MIMOPS_CTRL {
-	u8	MimoPsEnable:1;
-	u8	MimoPsMode:1;
-	u8	Reserved:6;
-} MIMOPS_CTRL, *PMIMOPS_CTRL;
-
-typedef enum _HT_SPEC_VER {
-	HT_SPEC_VER_IEEE = 0,
-	HT_SPEC_VER_EWC = 1,
-} HT_SPEC_VER, *PHT_SPEC_VER;
-
-typedef enum _HT_AGGRE_MODE_E {
-	HT_AGG_AUTO = 0,
-	HT_AGG_FORCE_ENABLE = 1,
-	HT_AGG_FORCE_DISABLE = 2,
-} HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
-
-/*----------------------------------------------------------------------------
- *  The Data structure is used to keep HT related variables when card is
- *  configured as non-AP STA mode.
- *  **Note** Current_xxx should be set to default value in HTInitializeHTInfo()
- *----------------------------------------------------------------------------*/
-
-typedef struct _RT_HIGH_THROUGHPUT {
-	u8			bEnableHT;
-	u8			bCurrentHTSupport;
-	/* Tx 40MHz channel capability */
-	u8			bRegBW40MHz;
-	u8			bCurBW40MHz;
-	/* Tx Short GI for 40Mhz */
-	u8			bRegShortGI40MHz;
-	u8			bCurShortGI40MHz;
-	/* Tx Short GI for 20MHz */
-	u8			bRegShortGI20MHz;
-	u8			bCurShortGI20MHz;
-	/* Tx CCK rate capability */
-	u8			bRegSuppCCK;
-	u8			bCurSuppCCK;
-
-	/* 802.11n spec version for "peer" */
-	HT_SPEC_VER		ePeerHTSpecVer;
-
-
-	/* HT related information for "Self" */
-	/* This is HT cap element sent to peer STA, which also indicate
-	 * HT Rx capabilities. */
-	HT_CAPABILITY_ELE	SelfHTCap;
-	HT_INFORMATION_ELE	SelfHTInfo;
-
-	/* HT related information for "Peer" */
-	u8			PeerHTCapBuf[32];
-	u8			PeerHTInfoBuf[32];
-
-
-	/* A-MSDU related */
-	/* This indicates Tx A-MSDU capability */
-	u8			bAMSDU_Support;
-	u16			nAMSDU_MaxSize;
-	u8			bCurrent_AMSDU_Support;
-	u16			nCurrent_AMSDU_MaxSize;
-
-
-	/* A-MPDU related */
-	/* This indicate Tx A-MPDU capability */
-	u8			bAMPDUEnable;
-	u8			bCurrentAMPDUEnable;
-	u8			AMPDU_Factor;
-	u8			CurrentAMPDUFactor;
-	u8			MPDU_Density;
-	u8			CurrentMPDUDensity;
-
-	/* Forced A-MPDU enable */
-	HT_AGGRE_MODE_E		ForcedAMPDUMode;
-	u8			ForcedAMPDUFactor;
-	u8			ForcedMPDUDensity;
-
-	/* Forced A-MSDU enable */
-	HT_AGGRE_MODE_E		ForcedAMSDUMode;
-	u16			ForcedAMSDUMaxSize;
-
-	u8			bForcedShortGI;
-
-	u8			CurrentOpMode;
-
-	/* MIMO PS related */
-	u8			SelfMimoPs;
-	u8			PeerMimoPs;
-
-	/* 40MHz Channel Offset settings. */
-	HT_EXTCHNL_OFFSET	CurSTAExtChnlOffset;
-	u8			bCurTxBW40MHz;	/* If we use 40 MHz to Tx */
-	u8			PeerBandwidth;
-
-	/* For Bandwidth Switching */
-	u8			bSwBwInProgress;
-	CHNLOP			ChnlOp; /* sw switching channel in progress. */
-	u8			SwBwStep;
-	struct timer_list	SwBwTimer;
-
-	/* For Realtek proprietary A-MPDU factor for aggregation */
-	u8			bRegRT2RTAggregation;
-	u8			bCurrentRT2RTAggregation;
-	u8			bCurrentRT2RTLongSlotTime;
-	u8			szRT2RTAggBuffer[10];
-
-	/* Rx Reorder control */
-	u8			bRegRxReorderEnable;
-	u8			bCurRxReorderEnable;
-	u8			RxReorderWinSize;
-	u8			RxReorderPendingTime;
-	u16			RxReorderDropCounter;
-
-#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
-	u8			UsbTxAggrNum;
-#endif
-#ifdef USB_RX_AGGREGATION_SUPPORT
-	u8			UsbRxFwAggrEn;
-	u8			UsbRxFwAggrPageNum;
-	u8			UsbRxFwAggrPacketNum;
-	u8			UsbRxFwAggrTimeout;
-#endif
-
-	/* Add for Broadcom(Linksys) IOT. */
-	u8			bIsPeerBcm;
-
-	/* For IOT issue. */
-	u32			IOTAction;
-} RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
-
-
-/*----------------------------------------------------------------------
- * The Data structure is used to keep HT related variable for "each Sta"
- * when card is configured as "AP mode"
- *----------------------------------------------------------------------*/
-
-typedef struct _RT_HTINFO_STA_ENTRY {
-	u8			bEnableHT;
-
-	u8			bSupportCck;
-
-	u16			AMSDU_MaxSize;
-
-	u8			AMPDU_Factor;
-	u8			MPDU_Density;
-
-	u8			HTHighestOperaRate;
-
-	u8			bBw40MHz;
-
-	u8			MimoPs;
-
-	u8			McsRateSet[16];
-
-
-} RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
-
-
-
-
-
-/*---------------------------------------------------------------------
- * The Data structure is used to keep HT related variable for "each AP"
- * when card is configured as "STA mode"
- *---------------------------------------------------------------------*/
-
-typedef struct _BSS_HT {
-
-	u8				bdSupportHT;
-
-	/* HT related elements */
-	u8				bdHTCapBuf[32];
-	u16				bdHTCapLen;
-	u8				bdHTInfoBuf[32];
-	u16				bdHTInfoLen;
-
-	HT_SPEC_VER			bdHTSpecVer;
-
-	u8				bdRT2RTAggregation;
-	u8				bdRT2RTLongSlotTime;
-} BSS_HT, *PBSS_HT;
-
-typedef struct _MIMO_RSSI {
-	u32	EnableAntenna;
-	u32	AntennaA;
-	u32	AntennaB;
-	u32	AntennaC;
-	u32	AntennaD;
-	u32	Average;
-} MIMO_RSSI, *PMIMO_RSSI;
-
-typedef struct _MIMO_EVM {
-	u32	EVM1;
-	u32	EVM2;
-} MIMO_EVM, *PMIMO_EVM;
-
-typedef struct _FALSE_ALARM_STATISTICS {
-	u32	Cnt_Parity_Fail;
-	u32	Cnt_Rate_Illegal;
-	u32	Cnt_Crc8_fail;
-	u32	Cnt_all;
-} FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
-
-
-
-#endif
diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig
index 6a43312380e0..f160eee52f09 100644
--- a/drivers/staging/rtl8712/Kconfig
+++ b/drivers/staging/rtl8712/Kconfig
@@ -4,7 +4,6 @@ config R8712U
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select FW_LOADER
-	default N
 	---help---
 	This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130.
 	If built as a module, it will be called r8712u.
@@ -12,7 +11,6 @@ config R8712U
 config R8712_TX_AGGR
 	bool "Realtek RTL8712U Transmit Aggregation code"
 	depends on R8712U && BROKEN
-	default N
 	---help---
 	This option provides transmit aggregation for the Realtek RTL8712 USB device.
 
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index ea965370d1ac..0723b2f73aad 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -90,7 +90,6 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter)
 		pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ +
 		       RECVBUFF_ALIGN_SZ);
 		if (pskb) {
-			pskb->dev = padapter->pnetdev;
 			tmpaddr = (addr_t)pskb->data;
 			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
 			skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
@@ -1083,7 +1082,6 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
 		alloc_sz += 6;
 		pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
 		if (pkt_copy) {
-			pkt_copy->dev = padapter->pnetdev;
 			precvframe->u.hdr.pkt = pkt_copy;
 			skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data)
 				    % 4));
diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c
index 18c936fbdf1e..fce9c3fb2170 100644
--- a/drivers/staging/rtl8821ae/base.c
+++ b/drivers/staging/rtl8821ae/base.c
@@ -39,10 +39,10 @@
 #include "pci.h"
 
 /*
- *NOTICE!!!: This file will be very big, we hsould
- *keep it clear under follwing roles:
+ *NOTICE!!!: This file will be very big, we should
+ *keep it clear under following roles:
  *
- *This file include follwing part, so, if you add new
+ *This file include following part, so, if you add new
  *functions into this file, please check which part it
  *should includes. or check if you should add new part
  *for this file:
@@ -64,73 +64,73 @@
  *
  *********************************************************/
 static struct ieee80211_channel rtl_channeltable_2g[] = {
-	{.center_freq = 2412,.hw_value = 1,},
-	{.center_freq = 2417,.hw_value = 2,},
-	{.center_freq = 2422,.hw_value = 3,},
-	{.center_freq = 2427,.hw_value = 4,},
-	{.center_freq = 2432,.hw_value = 5,},
-	{.center_freq = 2437,.hw_value = 6,},
-	{.center_freq = 2442,.hw_value = 7,},
-	{.center_freq = 2447,.hw_value = 8,},
-	{.center_freq = 2452,.hw_value = 9,},
-	{.center_freq = 2457,.hw_value = 10,},
-	{.center_freq = 2462,.hw_value = 11,},
-	{.center_freq = 2467,.hw_value = 12,},
-	{.center_freq = 2472,.hw_value = 13,},
-	{.center_freq = 2484,.hw_value = 14,},
+	{.center_freq = 2412, .hw_value = 1,},
+	{.center_freq = 2417, .hw_value = 2,},
+	{.center_freq = 2422, .hw_value = 3,},
+	{.center_freq = 2427, .hw_value = 4,},
+	{.center_freq = 2432, .hw_value = 5,},
+	{.center_freq = 2437, .hw_value = 6,},
+	{.center_freq = 2442, .hw_value = 7,},
+	{.center_freq = 2447, .hw_value = 8,},
+	{.center_freq = 2452, .hw_value = 9,},
+	{.center_freq = 2457, .hw_value = 10,},
+	{.center_freq = 2462, .hw_value = 11,},
+	{.center_freq = 2467, .hw_value = 12,},
+	{.center_freq = 2472, .hw_value = 13,},
+	{.center_freq = 2484, .hw_value = 14,},
 };
 
 static struct ieee80211_channel rtl_channeltable_5g[] = {
-	{.center_freq = 5180,.hw_value = 36,},
-	{.center_freq = 5200,.hw_value = 40,},
-	{.center_freq = 5220,.hw_value = 44,},
-	{.center_freq = 5240,.hw_value = 48,},
-	{.center_freq = 5260,.hw_value = 52,},
-	{.center_freq = 5280,.hw_value = 56,},
-	{.center_freq = 5300,.hw_value = 60,},
-	{.center_freq = 5320,.hw_value = 64,},
-	{.center_freq = 5500,.hw_value = 100,},
-	{.center_freq = 5520,.hw_value = 104,},
-	{.center_freq = 5540,.hw_value = 108,},
-	{.center_freq = 5560,.hw_value = 112,},
-	{.center_freq = 5580,.hw_value = 116,},
-	{.center_freq = 5600,.hw_value = 120,},
-	{.center_freq = 5620,.hw_value = 124,},
-	{.center_freq = 5640,.hw_value = 128,},
-	{.center_freq = 5660,.hw_value = 132,},
-	{.center_freq = 5680,.hw_value = 136,},
-	{.center_freq = 5700,.hw_value = 140,},
-	{.center_freq = 5745,.hw_value = 149,},
-	{.center_freq = 5765,.hw_value = 153,},
-	{.center_freq = 5785,.hw_value = 157,},
-	{.center_freq = 5805,.hw_value = 161,},
-	{.center_freq = 5825,.hw_value = 165,},
+	{.center_freq = 5180, .hw_value = 36,},
+	{.center_freq = 5200, .hw_value = 40,},
+	{.center_freq = 5220, .hw_value = 44,},
+	{.center_freq = 5240, .hw_value = 48,},
+	{.center_freq = 5260, .hw_value = 52,},
+	{.center_freq = 5280, .hw_value = 56,},
+	{.center_freq = 5300, .hw_value = 60,},
+	{.center_freq = 5320, .hw_value = 64,},
+	{.center_freq = 5500, .hw_value = 100,},
+	{.center_freq = 5520, .hw_value = 104,},
+	{.center_freq = 5540, .hw_value = 108,},
+	{.center_freq = 5560, .hw_value = 112,},
+	{.center_freq = 5580, .hw_value = 116,},
+	{.center_freq = 5600, .hw_value = 120,},
+	{.center_freq = 5620, .hw_value = 124,},
+	{.center_freq = 5640, .hw_value = 128,},
+	{.center_freq = 5660, .hw_value = 132,},
+	{.center_freq = 5680, .hw_value = 136,},
+	{.center_freq = 5700, .hw_value = 140,},
+	{.center_freq = 5745, .hw_value = 149,},
+	{.center_freq = 5765, .hw_value = 153,},
+	{.center_freq = 5785, .hw_value = 157,},
+	{.center_freq = 5805, .hw_value = 161,},
+	{.center_freq = 5825, .hw_value = 165,},
 };
 
 static struct ieee80211_rate rtl_ratetable_2g[] = {
-	{.bitrate = 10,.hw_value = 0x00,},
-	{.bitrate = 20,.hw_value = 0x01,},
-	{.bitrate = 55,.hw_value = 0x02,},
-	{.bitrate = 110,.hw_value = 0x03,},
-	{.bitrate = 60,.hw_value = 0x04,},
-	{.bitrate = 90,.hw_value = 0x05,},
-	{.bitrate = 120,.hw_value = 0x06,},
-	{.bitrate = 180,.hw_value = 0x07,},
-	{.bitrate = 240,.hw_value = 0x08,},
-	{.bitrate = 360,.hw_value = 0x09,},
-	{.bitrate = 480,.hw_value = 0x0a,},
-	{.bitrate = 540,.hw_value = 0x0b,},
+	{.bitrate = 10, .hw_value = 0x00,},
+	{.bitrate = 20, .hw_value = 0x01,},
+	{.bitrate = 55, .hw_value = 0x02,},
+	{.bitrate = 110, .hw_value = 0x03,},
+	{.bitrate = 60, .hw_value = 0x04,},
+	{.bitrate = 90, .hw_value = 0x05,},
+	{.bitrate = 120, .hw_value = 0x06,},
+	{.bitrate = 180, .hw_value = 0x07,},
+	{.bitrate = 240, .hw_value = 0x08,},
+	{.bitrate = 360, .hw_value = 0x09,},
+	{.bitrate = 480, .hw_value = 0x0a,},
+	{.bitrate = 540, .hw_value = 0x0b,},
 };
 
 static struct ieee80211_rate rtl_ratetable_5g[] = {
-	{.bitrate = 60,.hw_value = 0x04,},
-	{.bitrate = 90,.hw_value = 0x05,},
-	{.bitrate = 120,.hw_value = 0x06,},
-	{.bitrate = 180,.hw_value = 0x07,},
-	{.bitrate = 240,.hw_value = 0x08,},
-	{.bitrate = 360,.hw_value = 0x09,},
-	{.bitrate = 480,.hw_value = 0x0a,},
-	{.bitrate = 540,.hw_value = 0x0b,},
+	{.bitrate = 60, .hw_value = 0x04,},
+	{.bitrate = 90, .hw_value = 0x05,},
+	{.bitrate = 120, .hw_value = 0x06,},
+	{.bitrate = 180, .hw_value = 0x07,},
+	{.bitrate = 240, .hw_value = 0x08,},
+	{.bitrate = 360, .hw_value = 0x09,},
+	{.bitrate = 480, .hw_value = 0x0a,},
+	{.bitrate = 540, .hw_value = 0x0b,},
 };
 
 static const struct ieee80211_supported_band rtl_band_2ghz = {
@@ -320,7 +320,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	/* <5> set hw caps */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_RX_INCLUDES_FCS |
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
 	    IEEE80211_HW_BEACON_FILTER |
 #endif
 	    IEEE80211_HW_AMPDU_AGGREGATION |
@@ -336,7 +336,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	    		/* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */
 			0;
 /*<delete in kernel start>*/
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
 	hw->wiphy->interface_modes =
 	    BIT(NL80211_IFTYPE_AP) |
 	    BIT(NL80211_IFTYPE_STATION) |
@@ -354,11 +354,11 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 /*<delete in kernel start>*/
 #endif
 /*<delete in kernel end>*/
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 #endif
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
 	hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 #endif
 
@@ -402,7 +402,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
 /*<delete in kernel start>*/
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
 /*<delete in kernel end>*/
 	rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
 /*<delete in kernel start>*/
@@ -662,7 +662,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 
 	if (rtlpriv->dm.b_useramask) {
 		tcb_desc->ratr_index = ratr_index;
-		/* TODO we will differentiate adhoc and station futrue  */
+		/* TODO we will differentiate adhoc and station future  */
 		if (mac->opmode == NL80211_IFTYPE_STATION ||
 			mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 			tcb_desc->mac_id = 0;
@@ -730,7 +730,7 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw,
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	u8 hw_rate;
 
-	if ((get_rf_type(rtlphy) == RF_2T2R) && (sta->ht_cap.mcs.rx_mask[1]!=0))
+	if ((get_rf_type(rtlphy) == RF_2T2R) && (sta->ht_cap.mcs.rx_mask[1] != 0))
 		hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15];
 	else
 		hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7];
@@ -772,16 +772,16 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 			tcb_desc->disable_ratefallback = 1;
 		} else {
 			/*
-			 *because hw will nerver use hw_rate
+			 *because hw will never use hw_rate
 			 *when tcb_desc->use_driver_rate = false
 			 *so we never set highest N rate here,
-			 *and N rate will all be controled by FW
+			 *and N rate will all be controlled by FW
 			 *when tcb_desc->use_driver_rate = false
 			 */
 			if (sta && (sta->ht_cap.ht_supported)) {
 				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw, sta);
 			} else {
-				if(rtlmac->mode == WIRELESS_MODE_B) {
+				if (rtlmac->mode == WIRELESS_MODE_B) {
 					tcb_desc->hw_rate =
 					    rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
 				} else {
@@ -897,7 +897,7 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 								    hdr->addr3,
 								    tid);
 					if (skb_delba) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
 						rx_status.freq = hw->conf.chandef.chan->center_freq;
 						rx_status.band = hw->conf.chandef.chan->band;
 #else
@@ -1184,7 +1184,7 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
 		return;
 
-	rtlpriv->link_info.bcn_rx_inperiod ++;
+	rtlpriv->link_info.bcn_rx_inperiod++;
 }
 
 void rtl_watchdog_wq_callback(void *data)
@@ -1478,13 +1478,13 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
 		/* rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); */
 
 		info->control.rates[0].idx = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
 		info->band = hw->conf.chandef.chan->band;
 #else
 		info->band = hw->conf.channel->band;
 #endif
 /*<delete in kernel start>*/
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
 		info->control.sta = sta;
 		rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc);
 #else
@@ -1671,7 +1671,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len)
 		(memcmp(mac->bssid, ap4_2, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_3, 3) == 0) ||
 		vendor == PEER_RAL) {
-		RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral findn\n"));
+		RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral find\n"));
 		vendor = PEER_RAL;
 	} else if (memcmp(mac->bssid, ap6_1, 3) == 0 ||
 		vendor == PEER_CISCO) {
@@ -1715,7 +1715,7 @@ static ssize_t rtl_store_debug_level(struct device *d,
 	unsigned long val;
 	int ret;
 
-	ret = strict_strtoul(buf, 0, &val);
+	ret = kstrtoul(buf, 0, &val);
 	if (ret) {
 		printk(KERN_DEBUG "%s is not in hex or decimal form.\n", buf);
 	} else {
diff --git a/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c b/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
index b30f17ae0215..5a54bb10698c 100644
--- a/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
@@ -1653,7 +1653,7 @@ halbtc8812a1ant_TdmaDurationAdjustForAcl(
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retry_count = coex_sta->bt_retry_cnt;
 		bt_info_ext = coex_sta->bt_info_ext;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retry_count = %d\n", retry_count));
diff --git a/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c b/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
index e619923ef0ab..8e4293a35872 100644
--- a/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
@@ -629,7 +629,7 @@ halbtc8723a1ant_TdmaDurationAdjust(
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], retryCount = %d\n", retryCount));
 		result = 0;
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
index 973d0ea82cb8..1b04530d46bc 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
@@ -1721,7 +1721,7 @@ halbtc8192e1ant_TdmaDurationAdjustForAcl(
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		btInfoExt = pCoexSta->btInfoExt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
index 44ec78562e2d..115908928ae4 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
@@ -1803,7 +1803,7 @@ void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
 		result = 0;
 		wait_cnt = 0;
 	} else {
-		/* accquire the BT TRx retry count from BT_Info byte2 */
+		/* acquire the BT TRx retry count from BT_Info byte2 */
 		retry_cnt = coex_sta->bt_retry_cnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
 			  "[BTCoex], retry_cnt = %d\n", retry_cnt);
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
index 180d6f12e7b5..3f5c4fd2e73f 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
@@ -1687,7 +1687,7 @@ halbtc8723a2ant_TdmaDurationAdjust(
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], up=%d, dn=%d, m=%d, n=%d, WaitCount=%d\n", 
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
index 3414ba78cc43..9677943fc20d 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
@@ -1950,7 +1950,7 @@ void halbtc8723b1ant_tdma_duration_adjust_for_acl(struct btc_coexist *btcoexist,
 		result = 0;
 		wait_count = 0;
 	} else {
-		/*accquire the BT TRx retry count from BT_Info byte2 */
+		/*acquire the BT TRx retry count from BT_Info byte2 */
 		retry_count = coex_sta->bt_retry_cnt;
 		bt_info_ext = coex_sta->bt_info_ext;
 		result = 0;
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
index 83b1b4218333..d337bd0b3c1b 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
@@ -1830,7 +1830,7 @@ void halbtc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
 		result = 0;
 		wait_count = 0;
 	} else {
-		/*accquire the BT TRx retry count from BT_Info byte2*/
+		/*acquire the BT TRx retry count from BT_Info byte2*/
 		retryCount = coex_sta->bt_retry_cnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
 			  "[BTCoex], retryCount = %d\n", retryCount);
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.c b/drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.c
index 9d9fa4d7575d..1152fc8683a0 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.c
@@ -732,17 +732,7 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
 	else
 		btcoexist->binded = true;
 
-#if ( defined(CONFIG_PCI_HCI))
-	btcoexist->chip_interface = BTC_INTF_PCI;
-#elif ( defined(CONFIG_USB_HCI))
-	btcoexist->chip_interface = BTC_INTF_USB;
-#elif ( defined(CONFIG_SDIO_HCI))
-	btcoexist->chip_interface = BTC_INTF_SDIO;
-#elif ( defined(CONFIG_GSPI_HCI))
-	btcoexist->chip_interface = BTC_INTF_GSPI;
-#else
 	btcoexist->chip_interface = BTC_INTF_UNKNOWN;
-#endif
 
 	if (NULL == btcoexist->adapter)
 		btcoexist->adapter = adapter;
diff --git a/drivers/staging/rtl8821ae/core.c b/drivers/staging/rtl8821ae/core.c
index 40de6089039e..ff3139b6da65 100644
--- a/drivers/staging/rtl8821ae/core.c
+++ b/drivers/staging/rtl8821ae/core.c
@@ -373,7 +373,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 			/* sleep here is must, or we may recv the beacon and
 			 * cause mac80211 into wrong ps state, this will cause
 			 * power save nullfunc send fail, and further cause
-			 * pkt loss, So sleep must quickly but not immediatly
+			 * pkt loss, So sleep must quickly but not immediately
 			 * because that will cause nullfunc send by mac80211
 			 * fail, and cause pkt loss, we have tested that 5mA
 			 * is worked very well */
@@ -1200,8 +1200,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key_type = AESCMAC_ENCRYPTION;
 		RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
 		RT_TRACE(COMP_SEC, DBG_DMESG,
-				("HW don't support CMAC encrypiton, "
-				"use software CMAC encrypiton\n"));
+				("HW don't support CMAC encryption, "
+				"use software CMAC encryption\n"));
 		err = -EOPNOTSUPP;
 		goto out_unlock;
 	default:
@@ -1235,8 +1235,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key_type = AESCMAC_ENCRYPTION;
 		RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
 		RT_TRACE(COMP_SEC, DBG_DMESG,
-			 ("HW don't support CMAC encrypiton, "
-			  "use software CMAC encrypiton\n"));
+			 ("HW don't support CMAC encryption, "
+			  "use software CMAC encryption\n"));
 		err = -EOPNOTSUPP;
 		goto out_unlock;
 	default:
@@ -1411,7 +1411,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
 }
 
 /* this function is called by mac80211 to flush tx buffer
- * before switch channle or power save, or tx buffer packet
+ * before switch channel or power save, or tx buffer packet
  * maybe send after offchannel or rf sleep, this may cause
  * dis-association by AP */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
diff --git a/drivers/staging/rtl8821ae/core.h b/drivers/staging/rtl8821ae/core.h
index 4b247db2861d..f0c74e9239fd 100644
--- a/drivers/staging/rtl8821ae/core.h
+++ b/drivers/staging/rtl8821ae/core.h
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
diff --git a/drivers/staging/rtl8821ae/debug.c b/drivers/staging/rtl8821ae/debug.c
index cb051223c684..8a6c794bda41 100644
--- a/drivers/staging/rtl8821ae/debug.c
+++ b/drivers/staging/rtl8821ae/debug.c
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -985,4 +985,4 @@ void rtl_proc_remove_topdir(void)
 {
 	if (proc_topdir)
 		remove_proc_entry("rtlwifi", init_net.proc_net);
-}
\ No newline at end of file
+}
diff --git a/drivers/staging/rtl8821ae/debug.h b/drivers/staging/rtl8821ae/debug.h
index 5eb6251b89da..6c0a553e98b7 100644
--- a/drivers/staging/rtl8821ae/debug.h
+++ b/drivers/staging/rtl8821ae/debug.h
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -44,7 +44,7 @@
 #define DBG_EMERG			0
 
 /*
- *Abnormal, rare, or unexpeted cases.
+ *Abnormal, rare, or unexpected cases.
  *For example, Packet/IO Ctl canceled,
  *device suprisely unremoved and so on.
  */
@@ -54,7 +54,7 @@
  *Normal case driver developer should
  *open, we can see link status like
  *assoc/AddBA/DHCP/adapter start and
- *so on basic and useful infromations.
+ *so on basic and useful informations.
  */
 #define DBG_DMESG			3
 
diff --git a/drivers/staging/rtl8821ae/efuse.c b/drivers/staging/rtl8821ae/efuse.c
index 74c19ecc95a9..250aae1ce631 100644
--- a/drivers/staging/rtl8821ae/efuse.c
+++ b/drivers/staging/rtl8821ae/efuse.c
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * 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.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -149,7 +149,7 @@ u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address)
 		return 0xFF;
 
 }
-//EXPORT_SYMBOL(efuse_read_1byte);
+/* EXPORT_SYMBOL(efuse_read_1byte); */
 
 void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
 {
@@ -517,7 +517,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
 			rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 }
-//EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
+/* EXPORT_SYMBOL(rtl_efuse_shadow_map_update); */
 
 void efuse_force_write_vendor_Id(struct ieee80211_hw *hw)
 {
@@ -628,7 +628,7 @@ int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data)
 	}
 	return bresult;
 }
-//EXPORT_SYMBOL(efuse_one_byte_read);
+/* EXPORT_SYMBOL(efuse_one_byte_read); */
 
 static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
 {
@@ -1120,16 +1120,16 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
 		{
 			rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
 
-			// 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid
+			/* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
 			tmpV16 = rtl_read_word(rtlpriv,
 					       rtlpriv->cfg->maps[SYS_ISO_CTRL]);
 
 			printk("SYS_ISO_CTRL=%04x.\n",tmpV16);
 			if( ! (tmpV16 & PWC_EV12V ) ){
 				tmpV16 |= PWC_EV12V ;
-				 //PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16);
+				 /* PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16); */
 			}
-			// Reset: 0x0000h[28], default valid
+			/* Reset: 0x0000h[28], default valid */
  			tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_FUNC_EN]);
 			printk("SYS_FUNC_EN=%04x.\n",tmpV16);
 			if( !(tmpV16 & FEN_ELDR) ){
@@ -1137,7 +1137,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
 				rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16);
 			}
 
-			// Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid
+			/* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
 			tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_CLK] );
 			printk("SYS_CLK=%04x.\n",tmpV16);
 			if( (!(tmpV16 & LOADER_CLK_EN) )  ||(!(tmpV16 & ANA8M) ) )
@@ -1148,7 +1148,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
 
 			if(bwrite == true)
 			{
-				// Enable LDO 2.5V before read/write action
+				/* Enable LDO 2.5V before read/write action */
 				tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
 				printk("EFUSE_TEST=%04x.\n",tmpV16);
 				tempval &= ~(BIT(3) | BIT(4) |BIT(5) | BIT(6));
@@ -1161,7 +1161,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate)
 		{
 			rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x00);
 			if(bwrite == true){
-				// Disable LDO 2.5V after read/write action
+				/* Disable LDO 2.5V after read/write action */
 				tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
 				rtl_write_byte(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval & 0x7F));
 			}
diff --git a/drivers/staging/rtl8821ae/pci.c b/drivers/staging/rtl8821ae/pci.c
index cfa651edd238..a562aa60d595 100644
--- a/drivers/staging/rtl8821ae/pci.c
+++ b/drivers/staging/rtl8821ae/pci.c
@@ -388,13 +388,13 @@ static u8 _rtl_pci_get_pciehdr_offset(struct ieee80211_hw *hw)
 		 * capability that we are looking for, follow the link to
 		 * the next capability and continue looping.
 		 */
-		rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS , 
-					     pcicfg_addr_port + 
+		rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS ,
+					     pcicfg_addr_port +
 					     (num4bytes << 2));
 		rtl_pci_raw_read_port_ushort(PCI_CONF_DATA,
 					     (u16*)&capability_hdr);
 		/* Found the PCI express capability. */
-		if (capability_hdr.capability_id == 
+		if (capability_hdr.capability_id ==
 		    PCI_CAPABILITY_ID_PCI_EXPRESS)
 			break;
 		else
@@ -418,7 +418,7 @@ bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
 		list_for_each_entry(temp_priv, &rtlpriv->glb_var->glb_priv_list,
 			list) {
 			if (temp_priv) {
-				temp_pcipriv = 
+				temp_pcipriv =
 					(struct rtl_pci_priv *)temp_priv->priv;
 				RT_TRACE(COMP_INIT, DBG_LOUD,
 					(("pcipriv->ndis_adapter.funcnumber %x \n"),
@@ -526,8 +526,8 @@ static void _rtl_pci_io_handler_init(struct device *dev,
 }
 
 static bool _rtl_pci_update_earlymode_info(struct ieee80211_hw *hw,
-					   struct sk_buff *skb, 
-					   struct rtl_tcb_desc *tcb_desc, 
+					   struct sk_buff *skb,
+					   struct rtl_tcb_desc *tcb_desc,
 					   u8 tid)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -535,7 +535,7 @@ static bool _rtl_pci_update_earlymode_info(struct ieee80211_hw *hw,
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u8 additionlen = FCS_LEN;
 	struct sk_buff *next_skb;
-		
+
 	/* here open is 4, wep/tkip is 8, aes is 12*/
 	if (info->control.hw_key)
 		additionlen += info->control.hw_key->icv_len;
@@ -544,7 +544,7 @@ static bool _rtl_pci_update_earlymode_info(struct ieee80211_hw *hw,
 	tcb_desc->empkt_num = 0;
 	spin_lock_bh(&rtlpriv->locks.waitq_lock);
 	skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) {
-		struct ieee80211_tx_info *next_info = 
+		struct ieee80211_tx_info *next_info =
 					IEEE80211_SKB_CB(next_skb);
 		if (next_info->flags & IEEE80211_TX_CTL_AMPDU) {
 			tcb_desc->empkt_len[tcb_desc->empkt_num] =
@@ -554,7 +554,7 @@ static bool _rtl_pci_update_earlymode_info(struct ieee80211_hw *hw,
 			break;
 		}
 
-		if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], 
+		if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid],
 				      next_skb))
 			break;
 
@@ -575,26 +575,26 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
 	struct sk_buff *skb = NULL;
 	struct ieee80211_tx_info *info = NULL;
 	int tid; /* should be int */
-	
+
 	if (!rtlpriv->rtlhal.b_earlymode_enable)
-		return;	
+		return;
 	if (rtlpriv->dm.supp_phymode_switch &&
 		(rtlpriv->easy_concurrent_ctl.bswitch_in_process ||
-		(rtlpriv->buddy_priv && 
+		(rtlpriv->buddy_priv &&
 		 rtlpriv->buddy_priv->easy_concurrent_ctl.bswitch_in_process)))
 		return;
-	/* we juse use em for BE/BK/VI/VO */
+	/* we just use em for BE/BK/VI/VO */
 	for (tid = 7; tid >= 0; tid--) {
 		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)];
 		struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
-		while (!mac->act_scanning && 
+		while (!mac->act_scanning &&
 		       rtlpriv->psc.rfpwr_state == ERFON) {
 			struct rtl_tcb_desc tcb_desc;
-			memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));			
+			memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 
 			spin_lock_bh(&rtlpriv->locks.waitq_lock);
 			if (!skb_queue_empty(&mac->skb_waitq[tid]) &&
-			    (ring->entries - skb_queue_len(&ring->queue) > 
+			    (ring->entries - skb_queue_len(&ring->queue) >
 			     rtlhal->max_earlymode_num)) {
 				skb = skb_dequeue(&mac->skb_waitq[tid]);
 			} else {
@@ -607,7 +607,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
 			 * multicast/broadcast/no_qos data */
 			info = IEEE80211_SKB_CB(skb);
 			if (info->flags & IEEE80211_TX_CTL_AMPDU)
-				_rtl_pci_update_earlymode_info(hw, skb, 
+				_rtl_pci_update_earlymode_info(hw, skb,
 							       &tcb_desc, tid);
 
 /*<delete in kernel start>*/
@@ -635,7 +635,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 		u8 tid;
 		u8 *entry;
 
-		
+
 		if (rtlpriv->use_new_trx_flow)
 			entry = (u8 *)(&ring->buffer_desc[ring->idx]);
 		else
@@ -643,11 +643,11 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 
 		if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx))
 			return;
-			
+
 		ring->idx = (ring->idx + 1) % ring->entries;
-		
+
 		skb = __skb_dequeue(&ring->queue);
-		
+
 		pci_unmap_single(rtlpci->pdev,
 				 le32_to_cpu(rtlpriv->cfg->ops->
 					     get_desc((u8 *) entry, true,
@@ -672,7 +672,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 		}
 
 		/* for sw LPS, just after NULL skb send out, we can
-		 * sure AP kown we are sleeped, our we should not let
+		 * sure AP known we are slept, our we should not let
 		 * rf to sleep*/
 		fc = rtl_get_fc(skb);
 		if (ieee80211_is_nullfunc(fc)) {
@@ -740,7 +740,7 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
 	u8 tmp_one = 1;
 	struct sk_buff *skb;
 
-	skb = dev_alloc_skb(rtlpci->rxbuffersize);	
+	skb = dev_alloc_skb(rtlpci->rxbuffersize);
 	if (!skb)
 		return 0;
 	rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb;
@@ -754,25 +754,25 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
 	if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress))
 		return 0;
 	if (rtlpriv->use_new_trx_flow) {
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false, 
+		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false,
 					    HW_DESC_RX_PREPARE,
 					    (u8 *) & bufferaddress);
-	} else {	
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false, 
+	} else {
+		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false,
 					    HW_DESC_RXBUFF_ADDR,
 					    (u8 *) & bufferaddress);
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false, 
+		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false,
 					    HW_DESC_RXPKT_LEN,
 					    (u8 *) & rtlpci->rxbuffersize);
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false, 
+		rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, false,
 					    HW_DESC_RXOWN,
 					    (u8 *) & tmp_one);
 	}
-	
+
 	return 1;
 }
 
-/* inorder to receive 8K AMSDU we have set skb to
+/* In order to receive 8K AMSDU we have set skb to
  * 9100bytes in init rx ring, but if this packet is
  * not a AMSDU, this so big packet will be sent to
  * TCP/IP directly, this cause big packet ping fail
@@ -783,7 +783,7 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
 /* but some platform will fail when alloc skb sometimes.
  * in this condition, we will send the old skb to
  * mac80211 directly, this will not cause any other
- * issues, but only be losted by TCP/IP */
+ * issues, but only be lost by TCP/IP */
 static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
 	struct sk_buff *skb, struct ieee80211_rx_status rx_status)
 {
@@ -792,7 +792,7 @@ static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
 	} else {
 		struct sk_buff *uskb = NULL;
 		u8 *pdata;
-		
+
 		uskb = dev_alloc_skb(skb->len + 128);
 		if (likely(uskb)) {
 			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
@@ -804,7 +804,7 @@ static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
 			ieee80211_rx_irqsafe(hw, uskb);
 		} else {
 			ieee80211_rx_irqsafe(hw, skb);
-		}	
+		}
 	}
 }
 
@@ -814,11 +814,11 @@ static void _rtl_pci_hs_interrupt(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-	rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR], 
-		       rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR]) | 
+	rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR],
+		       rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR]) |
 		       rtlpci->sys_irq_mask);
 
-	
+
 }
 static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 {
@@ -839,7 +839,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		.noise = -98,
 		.rate = 0,
 	};
-	
+
 	/*RX NORMAL PKT */
 	while (count--) {
 		struct ieee80211_hdr *hdr;
@@ -852,65 +852,65 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		/*rx pkt */
 		struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[
 					rtlpci->rx_ring[rxring_idx].idx];
-		
+
 		if (rtlpriv->use_new_trx_flow) {
-			rx_remained_cnt = 
+			rx_remained_cnt =
 				rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw,
 								      hw_queue);
-			if (rx_remained_cnt < 1) 
+			if (rx_remained_cnt < 1)
 				return;
-			
+
 		} else {	/* rx descriptor */
 			pdesc = &rtlpci->rx_ring[rxring_idx].desc[
 				rtlpci->rx_ring[rxring_idx].idx];
-			
+
 			own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
-							       false, 
+							       false,
 							       HW_DESC_OWN);
 			if (own) /* wait data to be filled by hardware */
 				return;
 		}
-		
+
 		/* Get here means: data is filled already*/
 		/* AAAAAAttention !!!
 		 * We can NOT access 'skb' before 'pci_unmap_single' */
 		pci_unmap_single(rtlpci->pdev, *((dma_addr_t *) skb->cb),
 			 	 rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE);
-		
+
 		if (rtlpriv->use_new_trx_flow) {
 			buffer_desc = &rtlpci->rx_ring[rxring_idx].buffer_desc[
 				rtlpci->rx_ring[rxring_idx].idx];
 			/*means rx wifi info*/
 			pdesc = (struct rtl_rx_desc *)skb->data;
 		}
-		
+
 		rtlpriv->cfg->ops->query_rx_desc(hw, &status,
 						 &rx_status, (u8 *) pdesc, skb);
-			
+
 		if (rtlpriv->use_new_trx_flow)
-			rtlpriv->cfg->ops->rx_check_dma_ok(hw, 
-							   (u8 *)buffer_desc, 
+			rtlpriv->cfg->ops->rx_check_dma_ok(hw,
+							   (u8 *)buffer_desc,
 							   hw_queue);
 
-			
-		len = rtlpriv->cfg->ops->get_desc((u8 *)pdesc, false, 
+
+		len = rtlpriv->cfg->ops->get_desc((u8 *)pdesc, false,
 						  HW_DESC_RXPKT_LEN);
-			
+
 		if (skb->end - skb->tail > len) {
 			skb_put(skb, len);
-			if (rtlpriv->use_new_trx_flow)	
-				skb_reserve(skb, status.rx_drvinfo_size + 
+			if (rtlpriv->use_new_trx_flow)
+				skb_reserve(skb, status.rx_drvinfo_size +
 						 status.rx_bufshift + 24);
 			else
-				skb_reserve(skb, status.rx_drvinfo_size + 
+				skb_reserve(skb, status.rx_drvinfo_size +
 						 status.rx_bufshift);
 
 		} else {
-			printk("skb->end - skb->tail = %d, len is %d\n", 
+			printk("skb->end - skb->tail = %d, len is %d\n",
 			       skb->end - skb->tail, len);
 			break;
 		}
-			
+
 		rtlpriv->cfg->ops->rx_command_packet_handler(hw, status, skb);
 
 		/*
@@ -922,9 +922,9 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 
 		hdr = rtl_get_hdr(skb);
 		fc = rtl_get_fc(skb);
-		
+
 		if (!status.b_crc && !status.b_hwerror) {
-			memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, 
+			memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
 			       sizeof(rx_status));
 
 			if (is_broadcast_ether_addr(hdr->addr1)) {
@@ -947,13 +947,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 
 			/* static bcn for roaming */
 			rtl_beacon_statistic(hw, skb);
-			rtl_p2p_info(hw, (void*)skb->data, skb->len);	
+			rtl_p2p_info(hw, (void*)skb->data, skb->len);
 			/* for sw lps */
 			rtl_swlps_beacon(hw, (void*)skb->data, skb->len);
 			rtl_recognize_peer(hw, (void*)skb->data, skb->len);
 			if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
 			    (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)&&
-			    (ieee80211_is_beacon(fc) || 
+			    (ieee80211_is_beacon(fc) ||
 			     ieee80211_is_probe_resp(fc))) {
 				dev_kfree_skb_any(skb);
 			} else {
@@ -964,13 +964,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		}
 		if (rtlpriv->use_new_trx_flow) {
 			rtlpci->rx_ring[hw_queue].next_rx_rp += 1;
-			rtlpci->rx_ring[hw_queue].next_rx_rp %= 
+			rtlpci->rx_ring[hw_queue].next_rx_rp %=
 							RTL_PCI_MAX_RX_COUNT;
 
 
 			rx_remained_cnt--;
 			if (1/*rx_remained_cnt == 0*/) {
-				rtl_write_word(rtlpriv, 0x3B4, 
+				rtl_write_word(rtlpriv, 0x3B4,
 					rtlpci->rx_ring[hw_queue].next_rx_rp);
 			}
 		}
@@ -981,22 +981,22 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		}
 
 		if (rtlpriv->use_new_trx_flow) {
-			_rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc, 
+			_rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc,
 						 rxring_idx,
-					       rtlpci->rx_ring[rxring_idx].idx);			
+					       rtlpci->rx_ring[rxring_idx].idx);
 		} else {
 			_rtl_pci_init_one_rxdesc(hw, (u8 *)pdesc, rxring_idx,
-					       rtlpci->rx_ring[rxring_idx].idx);			
+					       rtlpci->rx_ring[rxring_idx].idx);
 
-			if (rtlpci->rx_ring[rxring_idx].idx == 
+			if (rtlpci->rx_ring[rxring_idx].idx ==
 			    rtlpci->rxringcount - 1)
-				rtlpriv->cfg->ops->set_desc(hw, (u8 *) pdesc, 
-							    false, 
+				rtlpriv->cfg->ops->set_desc(hw, (u8 *) pdesc,
+							    false,
 							    HW_DESC_RXERO,
 							    (u8 *) & tmp_one);
 		}
-		rtlpci->rx_ring[rxring_idx].idx = 
-				(rtlpci->rx_ring[rxring_idx].idx + 1) % 
+		rtlpci->rx_ring[rxring_idx].idx =
+				(rtlpci->rx_ring[rxring_idx].idx + 1) %
 				rtlpci->rxringcount;
 	}
 }
@@ -1011,7 +1011,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 intb = 0;
 
-	
+
 
 	if (rtlpci->irq_enabled == 0)
 		return IRQ_HANDLED;
@@ -1020,7 +1020,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 
 
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[MAC_HIMR], 0x0);
-	
+
 
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[MAC_HIMRE], 0x0);
 
@@ -1029,7 +1029,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
 
 
-	/*Shared IRQ or HW disappared */
+	/*Shared IRQ or HW disappeared */
 	if (!inta || inta == 0xffff)
 		goto done;
 	/*<1> beacon related */
@@ -1127,7 +1127,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	/*<4> fw related*/
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) {
 		if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) {
-			RT_TRACE(COMP_INTR, DBG_TRACE, 
+			RT_TRACE(COMP_INTR, DBG_TRACE,
 				 ("firmware interrupt!\n"));
 			queue_delayed_work(rtlpriv->works.rtl_wq,
 					   &rtlpriv->works.fwevt_wq, 0);
@@ -1142,12 +1142,12 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE ||
 	    rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
 		if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_HSISR_IND])) {
-			RT_TRACE(COMP_INTR, DBG_TRACE, 
+			RT_TRACE(COMP_INTR, DBG_TRACE,
 					 ("hsisr interrupt!\n"));
 			_rtl_pci_hs_interrupt(hw);
 		}
 	}
-	
+
 
 	if(rtlpriv->rtlhal.b_earlymode_enable)
 		tasklet_schedule(&rtlpriv->works.irq_tasklet);
@@ -1157,7 +1157,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[MAC_HIMRE],
 			rtlpci->irq_mask[1]);
 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-	
+
 	return IRQ_HANDLED;
 
 done:
@@ -1200,16 +1200,16 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 	pdesc = &ring->desc[0];
 	if (rtlpriv->use_new_trx_flow)
 		pbuffer_desc = &ring->buffer_desc[0];
-	
+
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
-	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, 
-				        (u8 *)pbuffer_desc, info, pskb, 
+	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc,
+				        (u8 *)pbuffer_desc, info, pskb,
 				        BEACON_QUEUE, &tcb_desc);
 #else
 /*<delete in kernel end>*/
 	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc,
-					(u8 *)pbuffer_desc, info, NULL, pskb, 
+					(u8 *)pbuffer_desc, info, NULL, pskb,
 					BEACON_QUEUE, &tcb_desc);
 /*<delete in kernel start>*/
 #endif
@@ -1235,7 +1235,7 @@ static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
 		desc_num = TX_DESC_NUM_92E;
 	else
 		desc_num = RT_TXDESC_NUM;
-	
+
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
 		rtlpci->txringcount[i] = desc_num;
 	}
@@ -1309,12 +1309,12 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 	/* alloc tx buffer desc for new trx flow*/
 	if (rtlpriv->use_new_trx_flow) {
 		buffer_desc = pci_alloc_consistent(rtlpci->pdev,
-					    sizeof(*buffer_desc) * entries, 
+					    sizeof(*buffer_desc) * entries,
 					    &buffer_desc_dma);
 
 		if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) {
 			RT_TRACE(COMP_ERR, DBG_EMERG,
-				 ("Cannot allocate TX ring (prio = %d)\n", 
+				 ("Cannot allocate TX ring (prio = %d)\n",
 				 prio));
 			return -ENOMEM;
 		}
@@ -1322,13 +1322,13 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 		memset(buffer_desc, 0, sizeof(*buffer_desc) * entries);
 		rtlpci->tx_ring[prio].buffer_desc = buffer_desc;
 		rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma;
-		
+
 		rtlpci->tx_ring[prio].cur_tx_rp = 0;
 		rtlpci->tx_ring[prio].cur_tx_wp = 0;
 		rtlpci->tx_ring[prio].avl_desc = entries;
 
 	}
-	
+
 	/* alloc dma for this ring */
 	desc = pci_alloc_consistent(rtlpci->pdev,
 				    sizeof(*desc) * entries, &desc_dma);
@@ -1342,7 +1342,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 	memset(desc, 0, sizeof(*desc) * entries);
 	rtlpci->tx_ring[prio].desc = desc;
 	rtlpci->tx_ring[prio].dma = desc_dma;
-	
+
 	rtlpci->tx_ring[prio].idx = 0;
 	rtlpci->tx_ring[prio].entries = entries;
 	skb_queue_head_init(&rtlpci->tx_ring[prio].queue);
@@ -1357,7 +1357,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 						      sizeof(*desc));
 
 			rtlpriv->cfg->ops->set_desc(hw, (u8 *) & (desc[i]),
-						    true, 
+						    true,
 						    HW_DESC_TX_NEXTDESC_ADDR,
 						    (u8 *) & nextdescaddress);
 		}
@@ -1371,15 +1371,15 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	int i;
-	
+
 	if (rtlpriv->use_new_trx_flow) {
 		struct rtl_rx_buffer_desc *entry = NULL;
 		/* alloc dma for this ring */
-		rtlpci->rx_ring[rxring_idx].buffer_desc = 
+		rtlpci->rx_ring[rxring_idx].buffer_desc =
 		    pci_alloc_consistent(rtlpci->pdev,
 					 sizeof(*rtlpci->rx_ring[rxring_idx].
-					        buffer_desc) * 
-					        rtlpci->rxringcount, 
+					        buffer_desc) *
+					        rtlpci->rxringcount,
 					 &rtlpci->rx_ring[rxring_idx].dma);
 		if (!rtlpci->rx_ring[rxring_idx].buffer_desc ||
 		    (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) {
@@ -1393,9 +1393,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
 
 		/* init every desc in this ring */
 		rtlpci->rx_ring[rxring_idx].idx = 0;
-		for (i = 0; i < rtlpci->rxringcount; i++) {			
+		for (i = 0; i < rtlpci->rxringcount; i++) {
 			entry = &rtlpci->rx_ring[rxring_idx].buffer_desc[i];
-			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry, 
+			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry,
 						      rxring_idx, i))
 				return -ENOMEM;
 		}
@@ -1403,14 +1403,14 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
 		struct rtl_rx_desc *entry = NULL;
 		u8 tmp_one = 1;
 		/* alloc dma for this ring */
-		rtlpci->rx_ring[rxring_idx].desc = 
+		rtlpci->rx_ring[rxring_idx].desc =
 		    pci_alloc_consistent(rtlpci->pdev,
 					 sizeof(*rtlpci->rx_ring[rxring_idx].
-					        desc) * rtlpci->rxringcount, 
+					        desc) * rtlpci->rxringcount,
 					 &rtlpci->rx_ring[rxring_idx].dma);
 		if (!rtlpci->rx_ring[rxring_idx].desc ||
 		    (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) {
-			RT_TRACE(COMP_ERR, DBG_EMERG, 
+			RT_TRACE(COMP_ERR, DBG_EMERG,
 				 ("Cannot allocate RX ring\n"));
 			return -ENOMEM;
 		}
@@ -1421,9 +1421,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
 
 		/* init every desc in this ring */
 		rtlpci->rx_ring[rxring_idx].idx = 0;
-		for (i = 0; i < rtlpci->rxringcount; i++) {			
+		for (i = 0; i < rtlpci->rxringcount; i++) {
 			entry = &rtlpci->rx_ring[rxring_idx].desc[i];
-			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry, 
+			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry,
 						      rxring_idx, i))
 				return -ENOMEM;
 		}
@@ -1467,7 +1467,7 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
 				    sizeof(*ring->buffer_desc) * ring->entries,
 				    ring->buffer_desc, ring->buffer_desc_dma);
 		ring->buffer_desc = NULL;
-	}	
+	}
 }
 
 static void _rtl_pci_free_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
@@ -1532,7 +1532,7 @@ err_free_rings:
 		_rtl_pci_free_rx_ring(hw, rxring_idx);
 
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++)
-		if (rtlpci->tx_ring[i].desc || 
+		if (rtlpci->tx_ring[i].desc ||
 		    rtlpci->tx_ring[i].buffer_desc)
 			_rtl_pci_free_tx_ring(hw, i);
 
@@ -1567,16 +1567,16 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 		/* force the rx_ring[RX_MPDU_QUEUE/
 		 * RX_CMD_QUEUE].idx to the first one */
 		/*new trx flow, do nothing*/
-		if ((rtlpriv->use_new_trx_flow == false) && 
+		if ((rtlpriv->use_new_trx_flow == false) &&
 		     rtlpci->rx_ring[rxring_idx].desc) {
 			struct rtl_rx_desc *entry = NULL;
 
 			for (i = 0; i < rtlpci->rxringcount; i++) {
-				entry = &rtlpci->rx_ring[rxring_idx].desc[i];			
-				rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry, 
+				entry = &rtlpci->rx_ring[rxring_idx].desc[i];
+				rtlpriv->cfg->ops->set_desc(hw, (u8 *) entry,
 							    false,
-							    HW_DESC_RXOWN, 
-							    (u8 *) & tmp_one);		
+							    HW_DESC_RXOWN,
+							    (u8 *) & tmp_one);
 			}
 		}
 		rtlpci->rx_ring[rxring_idx].idx = 0;	}
@@ -1585,13 +1585,13 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 	 * and force the  tx idx to the first one */
 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
-		if (rtlpci->tx_ring[i].desc || 
+		if (rtlpci->tx_ring[i].desc ||
 			rtlpci->tx_ring[i].buffer_desc) {
 			struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i];
 
 			while (skb_queue_len(&ring->queue)) {
 				u8 *entry;
-				struct sk_buff *skb = 
+				struct sk_buff *skb =
 					__skb_dequeue(&ring->queue);
 				if (rtlpriv->use_new_trx_flow)
 					entry = (u8 *)(&ring->buffer_desc
@@ -1618,7 +1618,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
-static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, 
+static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 					struct sk_buff *skb)
 #else
 /*<delete in kernel end>*/
@@ -1741,10 +1741,10 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
 	}
 
 	pdesc = &ring->desc[idx];
-	
+
 	if (rtlpriv->use_new_trx_flow) {
 		ptx_bd_desc = &ring->buffer_desc[idx];
-	} else {	
+	} else {
 		own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
 				true, HW_DESC_OWN);
 
@@ -1755,17 +1755,17 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
 				  hw_queue, ring->idx, idx,
 				  skb_queue_len(&ring->queue)));
 
-			spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, 
+			spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
 					       flags);
 			return skb->len;
 		}
 	}
-	
+
 	if (ieee80211_is_data_qos(fc)) {
 		tid = rtl_get_tid(skb);
 		if (sta) {
 			sta_entry = (struct rtl_sta_info *)sta->drv_priv;
-			seq_number = (le16_to_cpu(hdr->seq_ctrl) & 
+			seq_number = (le16_to_cpu(hdr->seq_ctrl) &
 				      IEEE80211_SCTL_SEQ) >> 4;
 			seq_number += 1;
 
@@ -1779,13 +1779,13 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
 
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
-	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, 
-					(u8 *)ptx_bd_desc, info, skb, 
+	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc,
+					(u8 *)ptx_bd_desc, info, skb,
 					hw_queue, ptcb_desc);
 #else
 /*<delete in kernel end>*/
-	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, 
-					(u8 *)ptx_bd_desc, info, sta, skb, 
+	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc,
+					(u8 *)ptx_bd_desc, info, sta, skb,
 					hw_queue, ptcb_desc);
 /*<delete in kernel start>*/
 #endif
@@ -1832,10 +1832,10 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop)
 	u16 i = 0;
 	int queue_id;
 	struct rtl8192_tx_ring *ring;
-	
+
 	if (mac->skip_scan)
 		return;
-	
+
 	for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) {
 		u32 queue_len;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
@@ -1936,7 +1936,7 @@ void rtl_pci_stop(struct ieee80211_hw *hw)
 	u8 RFInProgressTimeOut = 0;
 
 	/*
-	 *should before disable interrrupt&adapter
+	 *should before disable interrupt&adapter
 	 *and will do it immediately.
 	 */
 	set_hal_stop(rtlhal);
@@ -2081,13 +2081,13 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 			rtlhal->interfaceindex = 0;
 		}
 	}
-	
+
 	/* 92ee use new trx flow */
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE)
 		rtlpriv->use_new_trx_flow = true;
 	else
 		rtlpriv->use_new_trx_flow = false;
-	
+
 	/*find bus info */
 	pcipriv->ndis_adapter.busnumber = pdev->bus->number;
 	pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
@@ -2095,7 +2095,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 
 	/*find bridge info */
 	pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN;
-	/* some ARM have no bridge_pdev and will crash here 
+	/* some ARM have no bridge_pdev and will crash here
 	 * so we should check if bridge_pdev is NULL */
 	if (bridge_pdev) {
 		pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
@@ -2187,7 +2187,7 @@ static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw)
 	}
 
 	rtlpci->using_msi = true;
-	
+
 	RT_TRACE(COMP_INIT|COMP_INTR, DBG_DMESG, ("MSI Interrupt Mode!\n"));
 	return 0;
 }
@@ -2198,7 +2198,7 @@ static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw)
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
 	int ret;
-	
+
 	ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
 			  IRQF_SHARED, KBUILD_MODNAME, hw);
 	if (ret < 0) {
@@ -2206,7 +2206,7 @@ static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw)
 	}
 
 	rtlpci->using_msi = false;
-	RT_TRACE(COMP_INIT|COMP_INTR, DBG_DMESG, 
+	RT_TRACE(COMP_INIT|COMP_INTR, DBG_DMESG,
 		 ("Pin-based Interrupt Mode!\n"));
 	return 0;
 }
@@ -2293,7 +2293,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 	/*
 	 *init dbgp flags before all
 	 *other functions, because we will
-	 *use it in other funtions like
+	 *use it in other functions like
 	 *RT_TRACE/RT_PRINT/RTL_PRINT_DATA
 	 *you can not use these macro
 	 *before this
@@ -2377,7 +2377,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 	} else {
 		rtlpriv->mac80211.mac80211_registered = 1;
 	}
-	/* the wiphy must have been registed to 
+	/* the wiphy must have been registed to
 	 * cfg80211 prior to regulatory_hint */
 	if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) {
 		RT_TRACE(COMP_ERR, DBG_WARNING, ("regulatory_hint fail\n"));
@@ -2428,13 +2428,13 @@ fail1:
 	return -ENODEV;
 
 }
-//EXPORT_SYMBOL(rtl_pci_probe);
+/* EXPORT_SYMBOL(rtl_pci_probe); */
 
 struct ieee80211_hw *rtl_pci_get_hw_pointer(void)
 {
 	return hw_export;
 }
-//EXPORT_SYMBOL(rtl_pci_get_hw_pointer);
+/* EXPORT_SYMBOL(rtl_pci_get_hw_pointer); */
 
 void rtl_pci_disconnect(struct pci_dev *pdev)
 {
@@ -2450,7 +2450,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 
 	/* add for prov */
 	rtl_proc_remove_one(hw);
-	
+
 
 	/*ieee80211_unregister_hw will call ops_stop */
 	if (rtlmac->mac80211_registered == 1) {
@@ -2491,7 +2491,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 
 	ieee80211_free_hw(hw);
 }
-//EXPORT_SYMBOL(rtl_pci_disconnect);
+/* EXPORT_SYMBOL(rtl_pci_disconnect); */
 
 /***************************************
 kernel pci power state define:
@@ -2519,7 +2519,7 @@ int rtl_pci_suspend(struct device *dev)
 
 	return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_suspend);
+/* EXPORT_SYMBOL(rtl_pci_suspend); */
 
 int rtl_pci_resume(struct device *dev)
 {
@@ -2529,10 +2529,10 @@ int rtl_pci_resume(struct device *dev)
 
 	rtlpriv->cfg->ops->hw_resume(hw);
 	rtl_init_rfkill(hw);
-	
+
 	return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_resume);
+/* EXPORT_SYMBOL(rtl_pci_resume); */
 
 struct rtl_intf_ops rtl_pci_ops = {
 	.read_efuse_byte = read_efuse_byte,
diff --git a/drivers/staging/rtl8821ae/pci.h b/drivers/staging/rtl8821ae/pci.h
index 9f206550a657..06eaa521e0eb 100644
--- a/drivers/staging/rtl8821ae/pci.h
+++ b/drivers/staging/rtl8821ae/pci.h
@@ -148,11 +148,11 @@ struct rtl_pci_capabilities_header {
   * RX wifi info == RX descriptor in old flow */
 struct rtl_tx_buffer_desc {
 #if (RTL8192EE_SEG_NUM == 2)
-	u32 dword[2*(DMA_IS_64BIT + 1)*8]; //seg = 8
+	u32 dword[2*(DMA_IS_64BIT + 1)*8]; /* seg = 8 */
 #elif (RTL8192EE_SEG_NUM == 1)
-	u32 dword[2*(DMA_IS_64BIT + 1)*4]; //seg = 4
+	u32 dword[2*(DMA_IS_64BIT + 1)*4]; /* seg = 4 */
 #elif (RTL8192EE_SEG_NUM == 0)
-	u32 dword[2*(DMA_IS_64BIT + 1)*2]; //seg = 2
+	u32 dword[2*(DMA_IS_64BIT + 1)*2]; /* seg = 2 */
 #endif
 } __packed;
 
@@ -187,7 +187,7 @@ struct rtl8192_tx_ring {
 };
 
 struct rtl8192_rx_ring {
-	struct rtl_rx_desc *desc;/*for old trx flow, not uesd in new trx*/
+	struct rtl_rx_desc *desc;/*for old trx flow, not used in new trx*/
 	/*dma matches either 'desc' or 'buffer_desc'*/
 	dma_addr_t dma;
 	unsigned int idx;
diff --git a/drivers/staging/rtl8821ae/ps.c b/drivers/staging/rtl8821ae/ps.c
index f12ffa83c58d..7876442417f4 100644
--- a/drivers/staging/rtl8821ae/ps.c
+++ b/drivers/staging/rtl8821ae/ps.c
@@ -257,7 +257,7 @@ void rtl_ips_nic_off_wq_callback(void *data)
 		 *Do not enter IPS in the following conditions:
 		 *(1) RF is already OFF or Sleep
 		 *(2) b_swrf_processing (indicates the IPS is still under going)
-		 *(3) Connectted (only disconnected can trigger IPS)
+		 *(3) Connected (only disconnected can trigger IPS)
 		 *(4) IBSS (send Beacon)
 		 *(5) AP mode (send Beacon)
 		 *(6) monitor mode (rcv packet)
diff --git a/drivers/staging/rtl8821ae/rc.c b/drivers/staging/rtl8821ae/rc.c
index d387f13ea7dc..0cc32c60ddee 100644
--- a/drivers/staging/rtl8821ae/rc.c
+++ b/drivers/staging/rtl8821ae/rc.c
@@ -286,7 +286,6 @@ static void rtl_rate_free_sta(void *rtlpriv,
 }
 
 static struct rate_control_ops rtl_rate_ops = {
-	.module = NULL,
 	.name = "rtl_rc",
 	.alloc = rtl_rate_alloc,
 	.free = rtl_rate_free,
diff --git a/drivers/staging/rtl8821ae/regd.c b/drivers/staging/rtl8821ae/regd.c
index d89f15cb8089..0a4b3984b7ef 100644
--- a/drivers/staging/rtl8821ae/regd.c
+++ b/drivers/staging/rtl8821ae/regd.c
@@ -243,7 +243,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
 	}
 
 	/*
-	 *If a country IE has been recieved check its rule for this
+	 *If a country IE has been received check its rule for this
 	 *channel first before enabling active scan. The passive scan
 	 *would have been enforced by the initial processing of our
 	 *custom regulatory domain.
@@ -455,7 +455,7 @@ int rtl_regd_init(struct ieee80211_hw *hw,
 
 	if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
 		RT_TRACE(COMP_REGD, DBG_DMESG,
-			 (KERN_DEBUG "rtl: EEPROM indicates invalid contry code"
+			 (KERN_DEBUG "rtl: EEPROM indicates invalid country code"
 			  "world wide 13 should be used\n"));
 
 		rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
diff --git a/drivers/staging/rtl8821ae/regd.h b/drivers/staging/rtl8821ae/regd.h
index abc60ab8165c..dceb3f18200b 100644
--- a/drivers/staging/rtl8821ae/regd.h
+++ b/drivers/staging/rtl8821ae/regd.h
@@ -30,8 +30,8 @@
 #ifndef __RTL_REGD_H__
 #define __RTL_REGD_H__
 
-#define IEEE80211_CHAN_NO_IBSS		1<<2
-#define IEEE80211_CHAN_PASSIVE_SCAN	1<<1
+#define IEEE80211_CHAN_NO_IBSS		(1 << 2)
+#define IEEE80211_CHAN_PASSIVE_SCAN	(1 << 1)
 #define WIPHY_FLAG_CUSTOM_REGULATORY	BIT(0)
 #define WIPHY_FLAG_STRICT_REGULATORY	BIT(1)
 #define WIPHY_FLAG_DISABLE_BEACON_HINTS	BIT(2)
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/dm.c b/drivers/staging/rtl8821ae/rtl8821ae/dm.c
index 8634206b8929..e0efcd281dfe 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/dm.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/dm.c
@@ -731,7 +731,7 @@ void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 		rtl_dm_dig->min_undecorated_pwdb_for_dm =
 		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
 		RT_TRACE(COMP_BB_POWERSAVING, DBG_LOUD,
-			 ("AP Ext Port or disconnet PWDB = 0x%x \n",
+			 ("AP Ext Port or disconnect PWDB = 0x%x \n",
 			  rtl_dm_dig->min_undecorated_pwdb_for_dm));
 	}
 	RT_TRACE(COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
@@ -925,7 +925,7 @@ static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 
 	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 		RT_TRACE(COMP_DIG, DBG_LOUD,
-			("rtl8821ae_dm_dig(): Abnornally false alarm case. \n"));
+			("rtl8821ae_dm_dig(): Abnormally false alarm case. \n"));
 
 		if (dm_digtable.large_fa_hit != 3)
 		        dm_digtable.large_fa_hit++;
@@ -1087,7 +1087,7 @@ static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 	else
 		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 
-	/*reset OFDM FA coutner*/
+	/*reset OFDM FA counter*/
 	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
 	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
 	/* reset CCK FA counter*/
@@ -1316,7 +1316,7 @@ u8 rtl8812ae_hw_rate_to_mrate(
 /*-----------------------------------------------------------------------------
  * Function:	odm_TxPwrTrackSetPwr88E()
  *
- * Overview:	88E change all channel tx power accordign to flag.
+ * Overview:	88E change all channel tx power according to flag.
  *				OFDM & CCK are all different.
  *
  * Input:		NONE
@@ -1537,7 +1537,7 @@ void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
 					rtldm->modify_txagc_flag_path_b = false;
 
 					RT_TRACE(COMP_POWER_TRACKING, DBG_LOUD,
-						("******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE \n"));
+						("******Path_B dm_Odm->Modify_TxAGC_Flag = FALSE \n"));
 				}
 			}
 		}
@@ -1654,7 +1654,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter
 
 	if (delta > 0 && rtldm->txpower_track_control)
 	{
-		/*"delta" here is used to record the absolute value of differrence.*/
+		/*"delta" here is used to record the absolute value of difference.*/
 	    	delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
 		    	(thermal_value - rtlefuse->eeprom_thermalmeter) : \
 		    	(rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -1976,7 +1976,7 @@ void rtl8821ae_phy_lccalibrate(
 /*-----------------------------------------------------------------------------
  * Function:	odm_TxPwrTrackSetPwr88E()
  *
- * Overview:	88E change all channel tx power accordign to flag.
+ * Overview:	88E change all channel tx power according to flag.
  *				OFDM & CCK are all different.
  *
  * Input:		NONE
@@ -2159,7 +2159,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter
 	u8 *delta_swing_table_idx_tup_b;
 	u8 *delta_swing_table_idx_tdown_b;
 
-	/*2. Initilization ( 7 steps in total )*/
+	/*2. Initialization ( 7 steps in total )*/
 	rtl8821ae_get_delta_swing_table(hw, (u8**)&delta_swing_table_idx_tup_a,
 									(u8**)&delta_swing_table_idx_tdown_a,
 									  (u8**)&delta_swing_table_idx_tup_b,
@@ -2244,7 +2244,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter
 
 	if (delta > 0 && rtldm->txpower_track_control)
 	{
-		/*"delta" here is used to record the absolute value of differrence.*/
+		/*"delta" here is used to record the absolute value of difference.*/
 	    	delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
 		    	(thermal_value - rtlefuse->eeprom_thermalmeter) : \
 		    	(rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -2613,11 +2613,11 @@ static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
 	RT_TRACE(COMP_TURBO, DBG_LOUD,
 		("rtl8821ae_dm_check_edca_turbo=====>"));
 	RT_TRACE(COMP_TURBO, DBG_LOUD,
-		("Orginial BE PARAM: 0x%x\n",
+		("Original BE PARAM: 0x%x\n",
 		rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)));
 
 	/*===============================
-	list paramter for different platform
+	list parameter for different platform
 	===============================*/
 	b_last_is_cur_rdl_state = rtlpriv->dm.bis_cur_rdlstate;
 	pb_is_cur_rdl_state = &( rtlpriv->dm.bis_cur_rdlstate);
@@ -2963,7 +2963,7 @@ void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
 			"Crystal cap = 0x%x, Crystal cap offset = %d\n",
 			rtldm->crystal_cap, adjust_xtal));
 
-		/*3.Adjudt Crystal Cap.*/
+		/*3.Adjust Crystal Cap.*/
 		if (adjust_xtal != 0){
 			rtldm->is_freeze = 0;
 			rtldm->crystal_cap += adjust_xtal;
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/fw.c b/drivers/staging/rtl8821ae/rtl8821ae/fw.c
index 4083cab926a3..46eb4125d18f 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/fw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/fw.c
@@ -164,7 +164,7 @@ static int _rtl8821ae_fw_free_to_go(struct ieee80211_hw *hw)
 
 	if (counter >= FW_8821AE_POLLING_TIMEOUT_COUNT) {
 		RT_TRACE(COMP_ERR, DBG_LOUD,
-			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			 ("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
 			  value32));
 		goto exit;
 	}
@@ -368,7 +368,7 @@ static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw,
 				wait_h2c_limmit--;
 				if (wait_h2c_limmit == 0) {
 					RT_TRACE(COMP_CMD, DBG_LOUD,
-						 ("Wating too long for FW read "
+						 ("Waiting too long for FW read "
 						  "clear HMEBox(%d)!\n", boxnum));
 					break;
 				}
@@ -378,7 +378,7 @@ static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw,
 				isfw_read = _rtl8821ae_check_fw_read_last_h2c(hw, boxnum);
 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 				RT_TRACE(COMP_CMD, DBG_LOUD,
-					 ("Wating for FW read clear HMEBox(%d)!!! "
+					 ("Waiting for FW read clear HMEBox(%d)!!! "
 					  "0x130 = %2x\n", boxnum, u1b_tmp));
 			}
 		}
@@ -1179,7 +1179,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
 }
 
-/*Shoud check FW support p2p or not.*/
+/*Should check FW support p2p or not.*/
 void rtl8821ae_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 {
 	u8 u1_ctwindow_period[1] ={ ctwindow};
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h b/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
index 799cc6f95cc1..b365f82f481c 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
@@ -142,7 +142,7 @@ void rtl8821ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw);
 long rtl8821ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw);
 void rtl8821ae_dm_bt_balance(struct ieee80211_hw *hw,
 			bool b_balance_on, u8 ms0, u8 ms1);
-void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 tyep);
+void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type);
 void rtl8821ae_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type);
 u8 rtl8821ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
 						u8	level_num, u8	rssi_thresh, u8 rssi_thresh1);
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c b/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
index 79386ee142f9..6898868ce6e7 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
@@ -157,7 +157,7 @@ bool rtl8821ae_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw)
 		&&(rtlpcipriv->btcoexist.previous_state_h
 		== rtlpcipriv->btcoexist.current_state_h)) {
 		RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
-				("[DM][BT], Coexist state do not chang!!\n"));
+				("[DM][BT], Coexist state do not change!!\n"));
 		return true;
 	} else {
 		RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
@@ -902,7 +902,7 @@ void rtl8821ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw, struct btdm_8821ae *p_bt
 
 	/*
 	 * Note:
-	 * We should add delay for making sure sw DacSwing can be set sucessfully.
+	 * We should add delay for making sure sw DacSwing can be set successfully.
 	 * because of that rtl8821ae_dm_bt_set_fw_2_ant_hid() and rtl8821ae_dm_bt_set_fw_tdma_ctrl()
 	 * will overwrite the reg 0x880.
 	*/
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hw.c b/drivers/staging/rtl8821ae/rtl8821ae/hw.c
index 5ed7a114c56b..1b8583b689d4 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hw.c
@@ -147,6 +147,7 @@ static void _rtl8821ae_set_fw_clock_on(struct ieee80211_hw *hw,
 		} else {
 			rtlhal->bfw_clk_change_in_progress = false;
 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+			break;
 		}
 	}
 
@@ -1016,7 +1017,7 @@ static void _rtl8821ae_hw_configure(struct ieee80211_hw *hw)
 	/* ARFB table 12 for 11ac 24G 1SS */
 	rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015);
 	rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000);
-	/* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */
+	/* 0x420[7] = 0 , enable retry AMPDU in new AMPD not signal MPDU. */
 	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00);
 	rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70);
 
@@ -1406,7 +1407,7 @@ int rtl8821ae_hw_init(struct ieee80211_hw *hw)
 	rtl8821ae_phy_mac_config(hw);
 	/* because last function modify RCR, so we update
 	 * rcr var here, or TP will unstable for receive_config
-	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+	 * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
 	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
 	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
 	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
@@ -1562,7 +1563,7 @@ static enum version_8821ae _rtl8821ae_read_chip_version(struct ieee80211_hw *hw)
 			break;
 		default:
 			RT_TRACE(COMP_INIT, DBG_LOUD,
-				("Chip Version ID: Unknow (0x%X).\n", version));
+				("Chip Version ID: Unknown (0x%X).\n", version));
 			break;
 	}
 
@@ -1622,7 +1623,7 @@ static int _rtl8821ae_set_media_status(struct ieee80211_hw *hw,
 
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0xfc) == MSR_AP)
+	if ((bt_msr & ~0xfc) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
@@ -2371,7 +2372,7 @@ static void _rtl8812ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_
 	if (rtlefuse->eeprom_channelplan == 0xff)
 		rtlefuse->eeprom_channelplan = 0x7F;
 
-	/* set channel paln to world wide 13 */
+	/* set channel plan to world wide 13 */
 	//rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
 	/*parse xtal*/
@@ -2534,7 +2535,7 @@ static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_
 	if (rtlefuse->eeprom_channelplan == 0xff)
 		rtlefuse->eeprom_channelplan = 0x7F;
 
-	/* set channel paln to world wide 13 */
+	/* set channel plan to world wide 13 */
 	//rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
 	/*parse xtal*/
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/phy.c b/drivers/staging/rtl8821ae/rtl8821ae/phy.c
index d02fca38a2b2..c66129087a67 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/phy.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/phy.c
@@ -86,7 +86,7 @@ void rtl8812ae_fixspur(
 			/* 0x8AC[11:10] = 2'b10*/
 
 
-		/* <20120914, Kordan> A workarould to resolve
+		/* <20120914, Kordan> A workaround to resolve
 		2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
 		if (band_width == HT_CHANNEL_WIDTH_20 &&
 			(channel == 13 || channel == 14)) {
@@ -107,7 +107,7 @@ void rtl8812ae_fixspur(
 	}
 	else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 	{
-		/* <20120914, Kordan> A workarould to resolve
+		/* <20120914, Kordan> A workaround to resolve
 		2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
 		if (band_width == HT_CHANNEL_WIDTH_20 &&
 			(channel == 13 || channel == 14))
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/phy.h b/drivers/staging/rtl8821ae/rtl8821ae/phy.h
index a932d8c9d45d..a80bf739940a 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/phy.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/phy.h
@@ -30,7 +30,7 @@
 #ifndef __RTL8821AE_PHY_H__
 #define __RTL8821AE_PHY_H__
 
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT	4
 #define	TX_1S			0
 #define	TX_2S			1
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h b/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
index 8b39c042fa93..480a6bb6d76b 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
@@ -81,7 +81,7 @@
 	{0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */	\
 	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* suspend option all off */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */	\
 	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */	\
 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, BIT3}, /*0x04[11] = 2b'11 enable WL suspend for PCIe*/
@@ -91,7 +91,7 @@
 	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/								\
 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, 0}, /*0x04[11] = 2b'01enable WL suspend*/   \
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO sleep mode leave */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */	\
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */	\
 	{0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */
@@ -110,7 +110,7 @@
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0xff},/* gpio0~7 output mode */	\
 	{0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */	\
 	{0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/*0x12[0] = 0 force PFM mode */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */	\
 	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */	\
@@ -124,7 +124,7 @@
 	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/                       \
 	{0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, BIT0},/*0x12[0] = 1 force PWM mode */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO leave sleep mode */	\
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */	\
 	{0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */ \
@@ -204,7 +204,7 @@ extern struct wlan_pwr_cfg  rtl8812_leave_lps_flow[RTL8812_TRANS_LPS_TO_ACT_STEP
 	4: LPS--Low Power State
 	5: SUS--Suspend
 
-	The transision from different states are defined below
+	The transition from different states are defined below
 	TRANS_CARDEMU_TO_ACT
 	TRANS_ACT_TO_CARDEMU
 	TRANS_CARDEMU_TO_SUS
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c b/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
index 710bc015251c..ff1887187770 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
@@ -82,7 +82,7 @@ bool rtl_hal_pwrseqcmdparsing (struct rtl_priv* rtlpriv, u8 cut_version,
 					value = value | (GET_PWR_CFG_VALUE(pwr_cfg_cmd)
 							& GET_PWR_CFG_MASK(pwr_cfg_cmd));
 
-					/*Write the value back to sytem register*/
+					/*Write the value back to system register*/
 					rtl_write_byte(rtlpriv, offset, value);
 				}
 				break;
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/reg.h b/drivers/staging/rtl8821ae/rtl8821ae/reg.h
index 09c5f00d2603..beffb4243b1e 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/reg.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/reg.h
@@ -596,13 +596,13 @@
 #define	IMR_BCNDMAINT3			BIT(23)		/* Beacon DMA Interrupt 3		*/
 #define	IMR_BCNDMAINT2			BIT(22)		/* Beacon DMA Interrupt 2		*/
 #define	IMR_BCNDMAINT1			BIT(21)		/* Beacon DMA Interrupt 1		*/
-#define	IMR_BCNDOK7				BIT(20)		/* Beacon Queue DMA OK Interrup 7 */
-#define	IMR_BCNDOK6				BIT(19)		/* Beacon Queue DMA OK Interrup 6 */
-#define	IMR_BCNDOK5				BIT(18)		/* Beacon Queue DMA OK Interrup 5 */
-#define	IMR_BCNDOK4				BIT(17)		/* Beacon Queue DMA OK Interrup 4 */
-#define	IMR_BCNDOK3				BIT(16)		/* Beacon Queue DMA OK Interrup 3 */
-#define	IMR_BCNDOK2				BIT(15)		/* Beacon Queue DMA OK Interrup 2 */
-#define	IMR_BCNDOK1				BIT(14)		/* Beacon Queue DMA OK Interrup 1 */
+#define	IMR_BCNDOK7				BIT(20)		/* Beacon Queue DMA OK Interrupt 7 */
+#define	IMR_BCNDOK6				BIT(19)		/* Beacon Queue DMA OK Interrupt 6 */
+#define	IMR_BCNDOK5				BIT(18)		/* Beacon Queue DMA OK Interrupt 5 */
+#define	IMR_BCNDOK4				BIT(17)		/* Beacon Queue DMA OK Interrupt 4 */
+#define	IMR_BCNDOK3				BIT(16)		/* Beacon Queue DMA OK Interrupt 3 */
+#define	IMR_BCNDOK2				BIT(15)		/* Beacon Queue DMA OK Interrupt 2 */
+#define	IMR_BCNDOK1				BIT(14)		/* Beacon Queue DMA OK Interrupt 1 */
 #define	IMR_ATIMEND_E		BIT(13)		/* ATIM Window End Extension for Win7 */
 #define	IMR_TXERR				BIT(11)		/* Tx Error Flag Interrupt Status, write 1 clear. */
 #define	IMR_RXERR				BIT(10)		/* Rx Error Flag INT Status, Write 1 clear */
@@ -613,7 +613,7 @@
 #define	HWSET_MAX_SIZE				512
 #define   EFUSE_MAX_SECTION			64
 #define   EFUSE_REAL_CONTENT_LEN			256
-#define 	EFUSE_OOB_PROTECT_BYTES    	18 	/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/
+#define 	EFUSE_OOB_PROTECT_BYTES    	18 	/* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte.*/
 
 
 #define	EEPROM_DEFAULT_TSSI					0x0
@@ -1511,7 +1511,7 @@
 #define	ROFDM0_TXCOEFF5				0xcb4
 #define	ROFDM0_TXCOEFF6				0xcb8
 
-/*Path_A RFE cotrol */
+/*Path_A RFE control */
 #define	RA_RFE_CTRL_8812				0xcb8
 /*Path_B RFE control*/
 #define	RB_RFE_CTRL_8812				0xeb8
@@ -2336,19 +2336,19 @@
 #define		WOL_REASON_DEAUTH			BIT(3)
 #define		WOL_REASON_FW_DISCONNECT	BIT(4)
 
-#define		RA_RFE_PINMUX	0xcb0  /* Path_A RFE cotrol pinmux*/
+#define		RA_RFE_PINMUX	0xcb0  /* Path_A RFE control pinmux*/
 #define		RB_RFE_PINMUX	0xeb0 /* Path_B RFE control pinmux*/
 
 #define		RA_RFE_INV 0xcb4
 #define		RB_RFE_INV 0xeb4
 
 /* RXIQC */
-#define		RA_RXIQC_AB    	0xc10  /*RxIQ imblance matrix coeff. A & B*/
-#define		RA_RXIQC_CD    	0xc14  /*RxIQ imblance matrix coeff. C & D*/
+#define		RA_RXIQC_AB    	0xc10  /*RxIQ imbalance matrix coeff. A & B*/
+#define		RA_RXIQC_CD    	0xc14  /*RxIQ imbalance matrix coeff. C & D*/
 #define	 	RA_TXSCALE 		0xc1c  /* Pah_A TX scaling factor*/
 #define		RB_TXSCALE 		0xe1c  /* Path_B TX scaling factor*/
-#define		RB_RXIQC_AB    	0xe10  /*RxIQ imblance matrix coeff. A & B*/
-#define		RB_RXIQC_CD    	0xe14  /*RxIQ imblance matrix coeff. C & D*/
+#define		RB_RXIQC_AB    	0xe10  /*RxIQ imbalance matrix coeff. A & B*/
+#define		RB_RXIQC_CD    	0xe14  /*RxIQ imbalance matrix coeff. C & D*/
 #define		RXIQC_AC		0x02ff  /*bit mask for IQC matrix element A & C*/
 #define		RXIQC_BD		0x02ff0000 /*bit mask for IQC matrix element A & C*/
 
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/sw.c b/drivers/staging/rtl8821ae/rtl8821ae/sw.c
index 85a3474fc099..a8d175569770 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/sw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/sw.c
@@ -57,9 +57,9 @@ void rtl8821ae_init_aspm_vars(struct ieee80211_hw *hw)
 	 * 0 - Disable ASPM,
 	 * 1 - Enable ASPM without Clock Req,
 	 * 2 - Enable ASPM with Clock Req,
-	 * 3 - Alwyas Enable ASPM with Clock Req,
+	 * 3 - Always Enable ASPM with Clock Req,
 	 * 4 - Always Enable ASPM without Clock Req.
-	 * set defult to RTL8192CE:3 RTL8192E:2
+	 * set default to RTL8192CE:3 RTL8192E:2
 	 * */
 	rtlpci->const_pci_aspm = 3;
 
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/trx.c b/drivers/staging/rtl8821ae/rtl8821ae/trx.c
index 75ae4387fe19..5f3246454e3e 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/trx.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/trx.c
@@ -37,7 +37,7 @@
 #include "trx.h"
 #include "led.h"
 #include "dm.h"
-#include "phy.h"
+
 u8 _rtl8821ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
 {
 	u16 fc = rtl_get_fc(skb);
@@ -244,7 +244,7 @@ static void _rtl8821ae_query_rxphystatus(struct ieee80211_hw *hw,
 		cck_agc_rpt = cck_buf->cck_agc_rpt;
 
 		/* (1)Hardware does not provide RSSI for CCK */
-		/* (2)PWDB, Average PWDB cacluated by
+		/* (2)PWDB, Average PWDB calculated by
 		 * hardware (for rate adaptive) */
 		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
@@ -363,7 +363,7 @@ static void _rtl8821ae_query_rxphystatus(struct ieee80211_hw *hw,
 				pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
-		/* (2)PWDB, Average PWDB cacluated by
+		/* (2)PWDB, Average PWDB calculated by
 		 * hardware (for rate adaptive) */
 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 
@@ -603,7 +603,7 @@ bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw,
 
 	/* hw will set status->decrypted true, if it finds the
 	 * frame is open data frame or mgmt frame. */
-	/* So hw will not decryption robust managment frame
+	/* So hw will not decryption robust management frame
 	 * for IEEE80211w but still set status->decrypted
 	 * true, so here we should set it back to undecrypted
 	 * for IEEE80211w frame, and mac80211 sw will help
diff --git a/drivers/staging/rtl8821ae/wifi.h b/drivers/staging/rtl8821ae/wifi.h
index 76bef93ad70a..17a9d9f8781d 100644
--- a/drivers/staging/rtl8821ae/wifi.h
+++ b/drivers/staging/rtl8821ae/wifi.h
@@ -40,10 +40,10 @@
 
 
 #define RF_CHANGE_BY_INIT		0
-#define RF_CHANGE_BY_IPS 		BIT(28)
-#define RF_CHANGE_BY_PS 		BIT(29)
-#define RF_CHANGE_BY_HW 		BIT(30)
-#define RF_CHANGE_BY_SW 		BIT(31)
+#define RF_CHANGE_BY_IPS		BIT(28)
+#define RF_CHANGE_BY_PS			BIT(29)
+#define RF_CHANGE_BY_HW			BIT(30)
+#define RF_CHANGE_BY_SW			BIT(31)
 
 #define IQK_ADDA_REG_NUM		16
 #define IQK_MAC_REG_NUM			4
@@ -69,35 +69,35 @@
 #define QBSS_LOAD_SIZE			5
 #define MAX_WMMELE_LENGTH		64
 
-#define TOTAL_CAM_ENTRY 		32
+#define TOTAL_CAM_ENTRY			32
 
 /*slot time for 11g. */
 #define RTL_SLOT_TIME_9			9
 #define RTL_SLOT_TIME_20		20
 
 /*related with tcp/ip. */
-/*if_ehther.h*/
-#define ETH_P_PAE 			0x888E	/*Port Access Entity
+/*if_ether.h*/
+#define ETH_P_PAE			0x888E	/*Port Access Entity
 						 *(IEEE 802.1X) */
-#define ETH_P_IP        		0x0800	/*Internet Protocol packet */
-#define ETH_P_ARP       		0x0806	/*Address Resolution packet */
-#define SNAP_SIZE 			6
+#define ETH_P_IP			0x0800	/*Internet Protocol packet */
+#define ETH_P_ARP			0x0806	/*Address Resolution packet */
+#define SNAP_SIZE			6
 #define PROTOC_TYPE_SIZE		2
 
 /*related with 802.11 frame*/
-#define MAC80211_3ADDR_LEN 		24
-#define MAC80211_4ADDR_LEN 		30
+#define MAC80211_3ADDR_LEN		24
+#define MAC80211_4ADDR_LEN		30
 
 #define CHANNEL_MAX_NUMBER		(14 + 24 + 21)	/* 14 is the max
 							 * channel number */
 #define CHANNEL_MAX_NUMBER_2G		14
-#define CHANNEL_MAX_NUMBER_5G	    	54 /* Please refer to
+#define CHANNEL_MAX_NUMBER_5G		54 /* Please refer to
 					    *"phy_GetChnlGroup8812A" and
 					    * "Hal_ReadTxPowerInfo8812A"*/
 #define CHANNEL_MAX_NUMBER_5G_80M	7
 #define CHANNEL_GROUP_MAX		(3 + 9)	/* ch1~3, ch4~9, ch10~14
 						 * total three groups */
-#define MAX_PG_GROUP 			13
+#define MAX_PG_GROUP			13
 #define	CHANNEL_GROUP_MAX_2G		3
 #define	CHANNEL_GROUP_IDX_5GL		3
 #define	CHANNEL_GROUP_IDX_5GM		6
@@ -112,14 +112,14 @@
 #define MAX_NUM_RATES			264
 
 /*for 88E use*/
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT			4
 #define	MAX_RF_PATH			4
 #define	MAX_CHNL_GROUP_24G		6
 #define	MAX_CHNL_GROUP_5G		14
 
 /* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */
-#define MAX_TX_QUEUE 			9
+#define MAX_TX_QUEUE			9
 
 #define TX_PWR_BY_RATE_NUM_BAND		2
 #define TX_PWR_BY_RATE_NUM_RF		4
@@ -127,11 +127,11 @@
 #define MAX_BASE_NUM_IN_PHY_REG_PG_24G  6
 #define MAX_BASE_NUM_IN_PHY_REG_PG_5G	5
 
-#define DELTA_SWINGIDX_SIZE	30
-#define BAND_NUM 				3
+#define DELTA_SWINGIDX_SIZE		30
+#define BAND_NUM			3
 /*Now, it's just for 8192ee
  *not OK yet, keep it 0*/
-#define DMA_IS_64BIT 0
+#define DMA_IS_64BIT			0
 #define RTL8192EE_SEG_NUM		1 /* 0:2 seg, 1: 4 seg, 2: 8 seg */
 
 struct txpower_info_2g {
@@ -219,7 +219,7 @@ enum hardware_type {
 };
 
 enum scan_operation_backup_opt {
-	SCAN_OPT_BACKUP_BAND0=0,
+	SCAN_OPT_BACKUP_BAND0 = 0,
 	SCAN_OPT_BACKUP_BAND1,
 	SCAN_OPT_RESTORE,
 	SCAN_OPT_MAX
@@ -435,7 +435,7 @@ enum ht_channel_width {
 	HT_CHANNEL_WIDTH_80 = 2,
 };
 
-/* Ref: 802.11i sepc D10.0 7.3.2.25.1
+/* Ref: 802.11i spec D10.0 7.3.2.25.1
 Cipher Suites Encryption Algorithms */
 enum rt_enc_alg {
 	NO_ENCRYPTION = 0,
@@ -499,14 +499,14 @@ enum rtl_var_map {
 	RTL_IMR_BCNDMAINT3,	/*Beacon DMA Interrupt 3 */
 	RTL_IMR_BCNDMAINT2,	/*Beacon DMA Interrupt 2 */
 	RTL_IMR_BCNDMAINT1,	/*Beacon DMA Interrupt 1 */
-	RTL_IMR_BCNDOK8,	/*Beacon Queue DMA OK Interrup 8 */
-	RTL_IMR_BCNDOK7,	/*Beacon Queue DMA OK Interrup 7 */
-	RTL_IMR_BCNDOK6,	/*Beacon Queue DMA OK Interrup 6 */
-	RTL_IMR_BCNDOK5,	/*Beacon Queue DMA OK Interrup 5 */
-	RTL_IMR_BCNDOK4,	/*Beacon Queue DMA OK Interrup 4 */
-	RTL_IMR_BCNDOK3,	/*Beacon Queue DMA OK Interrup 3 */
-	RTL_IMR_BCNDOK2,	/*Beacon Queue DMA OK Interrup 2 */
-	RTL_IMR_BCNDOK1,	/*Beacon Queue DMA OK Interrup 1 */
+	RTL_IMR_BCNDOK8,	/*Beacon Queue DMA OK Interrupt 8 */
+	RTL_IMR_BCNDOK7,	/*Beacon Queue DMA OK Interrupt 7 */
+	RTL_IMR_BCNDOK6,	/*Beacon Queue DMA OK Interrupt 6 */
+	RTL_IMR_BCNDOK5,	/*Beacon Queue DMA OK Interrupt 5 */
+	RTL_IMR_BCNDOK4,	/*Beacon Queue DMA OK Interrupt 4 */
+	RTL_IMR_BCNDOK3,	/*Beacon Queue DMA OK Interrupt 3 */
+	RTL_IMR_BCNDOK2,	/*Beacon Queue DMA OK Interrupt 2 */
+	RTL_IMR_BCNDOK1,	/*Beacon Queue DMA OK Interrupt 1 */
 	RTL_IMR_TIMEOUT2,	/*Timeout interrupt 2 */
 	RTL_IMR_TIMEOUT1,	/*Timeout interrupt 1 */
 	RTL_IMR_TXFOVW,		/*Transmit FIFO Overflow */
@@ -515,10 +515,10 @@ enum rtl_var_map {
 	RTL_IMR_RXFOVW,		/*Receive FIFO Overflow */
 	RTL_IMR_RDU,		/*Receive Descriptor Unavailable */
 	RTL_IMR_ATIMEND,	/*For 92C,ATIM Window End Interrupt */
-	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrup */
+	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrupt */
 	RTL_IMR_HIGHDOK,	/*High Queue DMA OK Interrupt */
 	RTL_IMR_COMDOK,		/*Command Queue DMA OK Interrupt*/
-	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrup */
+	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrupt */
 	RTL_IMR_MGNTDOK,	/*Management Queue DMA OK Interrupt */
 	RTL_IMR_TBDER,		/*For 92C,Transmit Beacon Error Interrupt */
 	RTL_IMR_BKDOK,		/*AC_BK DMA OK Interrupt */
@@ -645,9 +645,9 @@ enum wireless_mode {
 };
 
 enum ratr_table_mode {
-	RATR_INX_WIRELESS_NGB = 0,		// BGN 40 Mhz 2SS 1SS
-	RATR_INX_WIRELESS_NG = 1,		// GN or N
-	RATR_INX_WIRELESS_NB = 2,		// BGN 20 Mhz 2SS 1SS  or BN
+	RATR_INX_WIRELESS_NGB = 0,		/* BGN 40 Mhz 2SS 1SS */
+	RATR_INX_WIRELESS_NG = 1,		/* GN or N */
+	RATR_INX_WIRELESS_NB = 2,		/* BGN 20 Mhz 2SS 1SS  or BN */
 	RATR_INX_WIRELESS_N = 3,
 	RATR_INX_WIRELESS_GB = 4,
 	RATR_INX_WIRELESS_G = 5,
@@ -759,7 +759,7 @@ struct rtl_tid_data {
 	struct rtl_ht_agg agg;
 };
 
-struct rssi_sta{
+struct rssi_sta {
 	long undecorated_smoothed_pwdb;
 };
 
@@ -899,7 +899,7 @@ struct regd_pair_mapping {
 	u16 reg_2ghz_ctl;
 };
 
-struct dynamic_primary_cca{
+struct dynamic_primary_cca {
 	u8 pricca_flag;
 	u8 intf_flag;
 	u8 intf_type;
@@ -939,14 +939,14 @@ enum p2p_ps_state {
 	P2P_PS_ENABLE = 1,
 	P2P_PS_SCAN = 2,
 	P2P_PS_SCAN_DONE = 3,
-	P2P_PS_ALLSTASLEEP = 4, // for P2P GO
+	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
+	P2P_PS_MIX = 3, /* CTWindow and NoA */
 };
 
 struct rtl_p2p_ps_info {
@@ -969,7 +969,7 @@ struct rtl_p2p_ps_info {
 	u32 noa_start_time[P2P_MAX_NOA_NUM];
 };
 
- struct p2p_ps_offload_t {
+struct p2p_ps_offload_t {
 	u8 Offload_En:1;
 	u8 role:1; /* 1: Owner, 0: Client */
 	u8 CTWindow_En:1;
@@ -981,7 +981,7 @@ struct rtl_p2p_ps_info {
 };
 
 #define IQK_MATRIX_REG_NUM	8
-#define IQK_MATRIX_SETTINGS_NUM	 (14+24+21) // Channels_2_4G_NUM + Channels_5G_20M_NUM + Channels_5G
+#define IQK_MATRIX_SETTINGS_NUM	 (14+24+21) /* Channels_2_4G_NUM + Channels_5G_20M_NUM + Channels_5G */
 struct iqk_matrix_regs {
 	bool b_iqk_done;
 	long value[1][IQK_MATRIX_REG_NUM];
@@ -1074,12 +1074,12 @@ struct rtl_phy {
 	enum rt_polarity_ctl polarity_ctl;
 };
 
-#define RTL_AGG_STOP 						0
+#define RTL_AGG_STOP						0
 #define RTL_AGG_PROGRESS					1
-#define RTL_AGG_START 						2
+#define RTL_AGG_START						2
 #define RTL_AGG_OPERATIONAL					3
-#define RTL_RX_AGG_START 					1
-#define RTL_RX_AGG_STOP 					0
+#define RTL_RX_AGG_START					1
+#define RTL_RX_AGG_STOP						0
 
 struct rtl_priv;
 struct rtl_io {
@@ -1092,13 +1092,13 @@ struct rtl_io {
 	/*PCI IO map */
 	unsigned long pci_base_addr;	/*device I/O address */
 
-	void (*write8_async) (struct rtl_priv * rtlpriv, u32 addr, u8 val);
-	void (*write16_async) (struct rtl_priv * rtlpriv, u32 addr, u16 val);
-	void (*write32_async) (struct rtl_priv * rtlpriv, u32 addr, u32 val);
+	void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val);
+	void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val);
+	void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val);
 
-	u8(*read8_sync) (struct rtl_priv * rtlpriv, u32 addr);
-	u16(*read16_sync) (struct rtl_priv * rtlpriv, u32 addr);
-	u32(*read32_sync) (struct rtl_priv * rtlpriv, u32 addr);
+	u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr);
+	u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr);
+	u32 (*read32_sync)(struct rtl_priv *rtlpriv, u32 addr);
 
 };
 
@@ -1256,7 +1256,7 @@ struct rtl_security {
 	bool use_defaultkey;
 	/*Encryption Algorithm for Unicast Packet */
 	enum rt_enc_alg pairwise_enc_algorithm;
-	/*Encryption Algorithm for Brocast/Multicast */
+	/*Encryption Algorithm for Broadcast/Multicast */
 	enum rt_enc_alg group_enc_algorithm;
 	/*Cam Entry Bitmap */
 	u32 hwsec_cam_bitmap;
@@ -1317,9 +1317,9 @@ struct rtl_pstbl {
 
 };
 
-#define ASSOCIATE_ENTRY_NUM	32+1
+#define ASSOCIATE_ENTRY_NUM	(32+1)
 
-struct fast_ant_trainning{
+struct fast_ant_trainning {
 	u8 bssid[6];
 	u8 antsel_rx_keep_0;
 	u8 antsel_rx_keep_1;
@@ -1427,19 +1427,19 @@ struct rtl_dm {
 	char bb_swing_diff_5g;
 
 	u8 delta_swing_table_idx_24gccka_p[DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_24gccka_n[DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_24gcckb_p[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24gccka_n[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24gcckb_p[DELTA_SWINGIDX_SIZE];
 	u8 delta_swing_table_idx_24gcckb_n[DELTA_SWINGIDX_SIZE];
 	u8 delta_swing_table_idx_24ga_p[DELTA_SWINGIDX_SIZE];
-   	u8 delta_swing_table_idx_24ga_n[DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_24gb_p[DELTA_SWINGIDX_SIZE];
-   	u8 delta_swing_table_idx_24gb_n[DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_5ga_p[BAND_NUM][DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_5ga_n[BAND_NUM][DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_5gb_p[BAND_NUM][DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_5gb_n[BAND_NUM][DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_24ga_p_8188e[DELTA_SWINGIDX_SIZE];
-    u8 delta_swing_table_idx_24ga_n_8188e[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24ga_n[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24gb_p[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24gb_n[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_5ga_p[BAND_NUM][DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_5ga_n[BAND_NUM][DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_5gb_p[BAND_NUM][DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_5gb_n[BAND_NUM][DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24ga_p_8188e[DELTA_SWINGIDX_SIZE];
+	u8 delta_swing_table_idx_24ga_n_8188e[DELTA_SWINGIDX_SIZE];
 
 
 	/* DMSP */
@@ -1451,7 +1451,7 @@ struct rtl_dm {
 	struct fast_ant_trainning fat_table;
 
 	u8	resp_tx_path;
-	u8 	path_sel;
+	u8	path_sel;
 	u32	patha_sum;
 	u32	pathb_sum;
 	u32	patha_cnt;
@@ -1671,7 +1671,6 @@ struct rtl_stats {
 	u8 rx_mimo_evm_dbm[4];
 	u16 cfo_short[4]; 		/* per-path's Cfo_short */
 	u16 cfo_tail[4];
-
 	u8 rx_pwr[4]; /* per-path's pwdb */
 	u8 rx_snr[4]; /* per-path's SNR */
 	u8 bandwidth;
@@ -1692,7 +1691,7 @@ struct rtl_stats {
 };
 
 struct rt_link_detect {
-	/* count for raoming */
+	/* count for roaming */
 	u32 bcn_rx_inperiod;
 	u32 roam_times;
 
@@ -1756,48 +1755,48 @@ struct proxim {
 	void *proximity_priv;
 	int (*proxim_rx)(struct ieee80211_hw *hw, struct rtl_stats *status,
 			 struct sk_buff *skb);
-	u8  (*proxim_get_var)(struct ieee80211_hw *hw, u8 type);
+	u8 (*proxim_get_var)(struct ieee80211_hw *hw, u8 type);
 };
 
 struct rtl_hal_ops {
-	int (*init_sw_vars) (struct ieee80211_hw * hw);
-	void (*deinit_sw_vars) (struct ieee80211_hw * hw);
-	void (*read_eeprom_info) (struct ieee80211_hw * hw);
-	void (*interrupt_recognized) (struct ieee80211_hw * hw,
-				      u32 * p_inta, u32 * p_intb);
-	int (*hw_init) (struct ieee80211_hw * hw);
-	void (*hw_disable) (struct ieee80211_hw * hw);
-	void (*hw_suspend) (struct ieee80211_hw * hw);
-	void (*hw_resume) (struct ieee80211_hw * hw);
-	void (*enable_interrupt) (struct ieee80211_hw * hw);
-	void (*disable_interrupt) (struct ieee80211_hw * hw);
-	int (*set_network_type) (struct ieee80211_hw * hw,
-				 enum nl80211_iftype type);
+	int (*init_sw_vars)(struct ieee80211_hw *hw);
+	void (*deinit_sw_vars)(struct ieee80211_hw *hw);
+	void (*read_eeprom_info)(struct ieee80211_hw *hw);
+	void (*interrupt_recognized)(struct ieee80211_hw *hw,
+				     u32 *p_inta, u32 *p_intb);
+	int (*hw_init)(struct ieee80211_hw *hw);
+	void (*hw_disable)(struct ieee80211_hw *hw);
+	void (*hw_suspend)(struct ieee80211_hw *hw);
+	void (*hw_resume)(struct ieee80211_hw *hw);
+	void (*enable_interrupt)(struct ieee80211_hw *hw);
+	void (*disable_interrupt)(struct ieee80211_hw *hw);
+	int (*set_network_type)(struct ieee80211_hw *hw,
+				enum nl80211_iftype type);
 	void (*set_chk_bssid)(struct ieee80211_hw *hw,
 			      bool check_bssid);
-	void (*set_bw_mode) (struct ieee80211_hw * hw,
-			     enum nl80211_channel_type ch_type);
-	 u8(*switch_channel) (struct ieee80211_hw * hw);
-	void (*set_qos) (struct ieee80211_hw * hw, int aci);
-	void (*set_bcn_reg) (struct ieee80211_hw * hw);
-	void (*set_bcn_intv) (struct ieee80211_hw * hw);
-	void (*update_interrupt_mask) (struct ieee80211_hw * hw,
-				       u32 add_msr, u32 rm_msr);
-	void (*get_hw_reg) (struct ieee80211_hw * hw, u8 variable, u8 * val);
-	void (*set_hw_reg) (struct ieee80211_hw * hw, u8 variable, u8 * val);
-	void (*update_rate_tbl) (struct ieee80211_hw * hw,
-				 struct ieee80211_sta *sta, u8 rssi_level);
-	void (*pre_fill_tx_bd_desc) (struct ieee80211_hw *hw, u8 *tx_bd_desc,
-				     u8 *desc, u8 queue_index,
-				     struct sk_buff *skb, dma_addr_t addr);
-	u16 (*rx_desc_buff_remained_cnt) (struct ieee80211_hw *hw,
-					  u8 queue_index);
-	void (*rx_check_dma_ok) (struct ieee80211_hw *hw, u8 *header_desc,
-				 u8 queue_index);
-	void (*fill_tx_desc) (struct ieee80211_hw * hw,
-			      struct ieee80211_hdr * hdr,
-			      u8 * pdesc_tx, u8 * pbd_desc,
-			      struct ieee80211_tx_info * info,
+	void (*set_bw_mode)(struct ieee80211_hw *hw,
+			    enum nl80211_channel_type ch_type);
+	u8 (*switch_channel)(struct ieee80211_hw *hw);
+	void (*set_qos)(struct ieee80211_hw *hw, int aci);
+	void (*set_bcn_reg)(struct ieee80211_hw *hw);
+	void (*set_bcn_intv)(struct ieee80211_hw *hw);
+	void (*update_interrupt_mask)(struct ieee80211_hw *hw,
+				      u32 add_msr, u32 rm_msr);
+	void (*get_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val);
+	void (*set_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val);
+	void (*update_rate_tbl)(struct ieee80211_hw *hw,
+				struct ieee80211_sta *sta, u8 rssi_level);
+	void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc,
+				    u8 *desc, u8 queue_index,
+				    struct sk_buff *skb, dma_addr_t addr);
+	u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw,
+					 u8 queue_index);
+	void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc,
+				u8 queue_index);
+	void (*fill_tx_desc)(struct ieee80211_hw *hw,
+			     struct ieee80211_hdr *hdr,
+			     u8 *pdesc_tx, u8 *pbd_desc,
+			     struct ieee80211_tx_info *info,
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
 /*<delete in kernel end>*/
@@ -1805,74 +1804,77 @@ struct rtl_hal_ops {
 /*<delete in kernel start>*/
 #endif
 /*<delete in kernel end>*/
-			      struct sk_buff * skb, u8 hw_queue,
+			      struct sk_buff *skb, u8 hw_queue,
 			      struct rtl_tcb_desc *ptcb_desc);
-	void (*fill_tx_cmddesc) (struct ieee80211_hw * hw, u8 * pdesc,
-				 bool b_firstseg, bool b_lastseg,
-				 struct sk_buff * skb);
-	 bool(*query_rx_desc) (struct ieee80211_hw * hw,
-			       struct rtl_stats * status,
-			       struct ieee80211_rx_status * rx_status,
-			       u8 * pdesc, struct sk_buff * skb);
-	void (*set_channel_access) (struct ieee80211_hw * hw);
-	 bool(*radio_onoff_checking) (struct ieee80211_hw * hw, u8 * valid);
-	void (*dm_watchdog) (struct ieee80211_hw * hw);
-	void (*scan_operation_backup) (struct ieee80211_hw * hw, u8 operation);
-	 bool(*set_rf_power_state) (struct ieee80211_hw * hw,
-				    enum rf_pwrstate rfpwr_state);
-	void (*led_control) (struct ieee80211_hw * hw,
-			     enum led_ctl_mode ledaction);
-	void (*set_desc) (struct ieee80211_hw *hw, u8 * pdesc, bool istx,
-			  u8 desc_name, u8 * val);
-	 u32(*get_desc) (u8 * pdesc, bool istx, u8 desc_name);
-	bool (*is_tx_desc_closed) (struct ieee80211_hw *hw,
-				   u8 hw_queue, u16 index);
-	void (*tx_polling) (struct ieee80211_hw * hw, u8 hw_queue);
-	void (*enable_hw_sec) (struct ieee80211_hw * hw);
-	void (*set_key) (struct ieee80211_hw * hw, u32 key_index,
-			 u8 * p_macaddr, bool is_group, u8 enc_algo,
-			 bool is_wepkey, bool clear_all);
-	void (*init_sw_leds) (struct ieee80211_hw * hw);
-	 u32(*get_bbreg) (struct ieee80211_hw * hw, u32 regaddr, u32 bitmask);
-	void (*set_bbreg) (struct ieee80211_hw * hw, u32 regaddr, u32 bitmask,
-			   u32 data);
-	 u32(*get_rfreg) (struct ieee80211_hw * hw, enum radio_path rfpath,
-			  u32 regaddr, u32 bitmask);
-	void (*set_rfreg) (struct ieee80211_hw * hw, enum radio_path rfpath,
-			   u32 regaddr, u32 bitmask, u32 data);
+	void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc,
+				bool b_firstseg, bool b_lastseg,
+				struct sk_buff *skb);
+	bool (*query_rx_desc)(struct ieee80211_hw *hw,
+			      struct rtl_stats *status,
+			      struct ieee80211_rx_status *rx_status,
+			      u8 *pdesc, struct sk_buff *skb);
+	void (*set_channel_access)(struct ieee80211_hw *hw);
+	bool (*radio_onoff_checking)(struct ieee80211_hw *hw, u8 *valid);
+	void (*dm_watchdog)(struct ieee80211_hw *hw);
+	void (*scan_operation_backup)(struct ieee80211_hw *hw, u8 operation);
+	bool (*set_rf_power_state)(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state);
+	void (*led_control)(struct ieee80211_hw *hw,
+			    enum led_ctl_mode ledaction);
+	void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
+			 u8 desc_name, u8 *val);
+	u32 (*get_desc)(u8 *pdesc, bool istx, u8 desc_name);
+	bool (*is_tx_desc_closed)(struct ieee80211_hw *hw,
+				  u8 hw_queue, u16 index);
+	void (*tx_polling)(struct ieee80211_hw *hw, u8 hw_queue);
+	void (*enable_hw_sec)(struct ieee80211_hw *hw);
+	void (*set_key)(struct ieee80211_hw *hw, u32 key_index,
+			u8 *p_macaddr, bool is_group, u8 enc_algo,
+			bool is_wepkey, bool clear_all);
+	void (*init_sw_leds)(struct ieee80211_hw *hw);
+	u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+	void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+			  u32 data);
+	u32 (*get_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath,
+			 u32 regaddr, u32 bitmask);
+	void (*set_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath,
+			  u32 regaddr, u32 bitmask, u32 data);
 	void (*allow_all_destaddr)(struct ieee80211_hw *hw,
-		bool allow_all_da, bool write_into_reg);
-	void (*linked_set_reg) (struct ieee80211_hw * hw);
-	void (*check_switch_to_dmdp) (struct ieee80211_hw * hw);
-	void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw);
-	void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw);
-	void (*c2h_command_handle) (struct ieee80211_hw *hw);
-	void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, bool mstate);
-	void (*bt_turn_off_bt_coexist_before_enter_lps) (struct ieee80211_hw *hw);
-	void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id,
-			      u32 cmd_len, u8 *p_cmdbuffer);
-	bool (*get_btc_status) (void);
-  	u32 (*rx_command_packet_handler)(struct ieee80211_hw *hw, struct rtl_stats status, struct sk_buff *skb);
+				   bool allow_all_da, bool write_into_reg);
+	void (*linked_set_reg)(struct ieee80211_hw *hw);
+	void (*check_switch_to_dmdp)(struct ieee80211_hw *hw);
+	void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw);
+	void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw);
+	void (*c2h_command_handle)(struct ieee80211_hw *hw);
+	void (*bt_wifi_media_status_notify)(struct ieee80211_hw *hw,
+					    bool mstate);
+	void (*bt_turn_off_bt_coexist_before_enter_lps)(struct ieee80211_hw *hw);
+	void (*fill_h2c_cmd)(struct ieee80211_hw *hw, u8 element_id,
+			     u32 cmd_len, u8 *p_cmdbuffer);
+	bool (*get_btc_status)(void);
+	u32 (*rx_command_packet_handler)(struct ieee80211_hw *hw,
+					 struct rtl_stats status,
+					 struct sk_buff *skb);
 };
 
 struct rtl_intf_ops {
 	/*com */
 	void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
-	int (*adapter_start) (struct ieee80211_hw * hw);
-	void (*adapter_stop) (struct ieee80211_hw * hw);
+	int (*adapter_start)(struct ieee80211_hw *hw);
+	void (*adapter_stop)(struct ieee80211_hw *hw);
 	bool (*check_buddy_priv)(struct ieee80211_hw *hw,
-			struct rtl_priv **buddy_priv);
+				 struct rtl_priv **buddy_priv);
 
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
-	int (*adapter_tx) (struct ieee80211_hw * hw, struct sk_buff * skb,
-			   struct rtl_tcb_desc *ptcb_desc);
+	int (*adapter_tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+			  struct rtl_tcb_desc *ptcb_desc);
 #else
 /*<delete in kernel end>*/
-	int (*adapter_tx) (struct ieee80211_hw *hw,
-			   struct ieee80211_sta *sta,
-			   struct sk_buff *skb,
-			   struct rtl_tcb_desc *ptcb_desc);
+	int (*adapter_tx)(struct ieee80211_hw *hw,
+			  struct ieee80211_sta *sta,
+			  struct sk_buff *skb,
+			  struct rtl_tcb_desc *ptcb_desc);
 /*<delete in kernel start>*/
 #endif
 /*<delete in kernel end>*/
@@ -1881,22 +1883,22 @@ struct rtl_intf_ops {
 #else
 	void (*flush)(struct ieee80211_hw *hw, bool drop);
 #endif
-	int (*reset_trx_ring) (struct ieee80211_hw * hw);
+	int (*reset_trx_ring)(struct ieee80211_hw *hw);
 /*<delete in kernel start>*/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
-	bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb);
+	bool (*waitq_insert)(struct ieee80211_hw *hw, struct sk_buff *skb);
 #else
 /*<delete in kernel end>*/
-	bool (*waitq_insert) (struct ieee80211_hw *hw,
-			      struct ieee80211_sta *sta,
-			      struct sk_buff *skb);
+	bool (*waitq_insert)(struct ieee80211_hw *hw,
+			     struct ieee80211_sta *sta,
+			     struct sk_buff *skb);
 /*<delete in kernel start>*/
 #endif
 /*<delete in kernel end>*/
 
 	/*pci */
-	void (*disable_aspm) (struct ieee80211_hw * hw);
-	void (*enable_aspm) (struct ieee80211_hw * hw);
+	void (*disable_aspm)(struct ieee80211_hw *hw);
+	void (*enable_aspm)(struct ieee80211_hw *hw);
 
 	/*usb */
 };
@@ -2027,21 +2029,21 @@ struct rtl_btc_info {
 };
 
 struct rtl_btc_ops {
-	void (*btc_init_variables) (struct rtl_priv *rtlpriv);
-	void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv);
-	void (*btc_init_hw_config) (struct rtl_priv *rtlpriv);
-	void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
-	void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype);
-	void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action);
-	void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv,
-					enum rt_media_status mstatus);
-	void (*btc_periodical) (struct rtl_priv *rtlpriv);
-	void (*btc_halt_notify) (void);
-	void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv,
-				   u8 * tmp_buf, u8 length);
-	bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv);
-	bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv);
-	bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
+	void (*btc_init_variables)(struct rtl_priv *rtlpriv);
+	void (*btc_init_hal_vars)(struct rtl_priv *rtlpriv);
+	void (*btc_init_hw_config)(struct rtl_priv *rtlpriv);
+	void (*btc_ips_notify)(struct rtl_priv *rtlpriv, u8 type);
+	void (*btc_scan_notify)(struct rtl_priv *rtlpriv, u8 scantype);
+	void (*btc_connect_notify)(struct rtl_priv *rtlpriv, u8 action);
+	void (*btc_mediastatus_notify)(struct rtl_priv *rtlpriv,
+				       enum rt_media_status mstatus);
+	void (*btc_periodical)(struct rtl_priv *rtlpriv);
+	void (*btc_halt_notify)(void);
+	void (*btc_btinfo_notify)(struct rtl_priv *rtlpriv,
+				  u8 *tmp_buf, u8 length);
+	bool (*btc_is_limited_dig)(struct rtl_priv *rtlpriv);
+	bool (*btc_is_disable_edca_turbo)(struct rtl_priv *rtlpriv);
+	bool (*btc_is_bt_disabled)(struct rtl_priv *rtlpriv);
 };
 
 struct rtl_bt_coexist {
@@ -2087,7 +2089,7 @@ struct rtl_priv {
 
 	/*
 	 *hal_cfg : for diff cards
-	 *intf_ops : for diff interrface usb/pcie
+	 *intf_ops : for diff interface usb/pcie
 	 */
 	struct rtl_hal_cfg *cfg;
 	struct rtl_intf_ops *intf_ops;
@@ -2105,7 +2107,7 @@ struct rtl_priv {
 	/*for bt coexist use*/
 	struct rtl_bt_coexist btcoexist;
 
-	/* seperate 92ee from other ICs,
+	/* separate 92ee from other ICs,
 	  * 92ee use new trx flow. */
 	bool use_new_trx_flow;
 	/*This must be the last item so
@@ -2120,57 +2122,57 @@ struct rtl_priv {
 #define rtl_hal(rtlpriv)	(&((rtlpriv)->rtlhal))
 #define rtl_efuse(rtlpriv)	(&((rtlpriv)->efuse))
 #define rtl_psc(rtlpriv)	(&((rtlpriv)->psc))
-#define rtl_sec(rtlpriv) 	(&((rtlpriv)->sec))
-#define rtl_dm(rtlpriv)	(&((rtlpriv)->dm))
+#define rtl_sec(rtlpriv)	(&((rtlpriv)->sec))
+#define rtl_dm(rtlpriv)		(&((rtlpriv)->dm))
 /***************************************
     Bluetooth Co-existance Related
 ****************************************/
 
 enum bt_ant_num {
-        ANT_X2 = 0,
-        ANT_X1 = 1,
+	ANT_X2 = 0,
+	ANT_X1 = 1,
 };
 
 enum bt_co_type {
-        BT_2WIRE = 0,
-        BT_ISSC_3WIRE = 1,
-        BT_ACCEL = 2,
-        BT_CSR_BC4 = 3,
-        BT_CSR_BC8 = 4,
-        BT_RTL8756 = 5,
-        BT_RTL8723A = 6,
-        BT_RTL8821A = 7,
-        BT_RTL8723B = 8,
-        BT_RTL8192E = 9,
-        BT_RTL8812A = 11,
-};
-
-enum bt_total_ant_num{
+	BT_2WIRE = 0,
+	BT_ISSC_3WIRE = 1,
+	BT_ACCEL = 2,
+	BT_CSR_BC4 = 3,
+	BT_CSR_BC8 = 4,
+	BT_RTL8756 = 5,
+	BT_RTL8723A = 6,
+	BT_RTL8821A = 7,
+	BT_RTL8723B = 8,
+	BT_RTL8192E = 9,
+	BT_RTL8812A = 11,
+};
+
+enum bt_total_ant_num {
 	ANT_TOTAL_X2 = 0,
 	ANT_TOTAL_X1 = 1
 };
 
 enum bt_cur_state {
-        BT_OFF = 0,
-        BT_ON = 1,
+	BT_OFF = 0,
+	BT_ON = 1,
 };
 
 enum bt_service_type {
-        BT_SCO = 0,
-        BT_A2DP = 1,
-        BT_HID = 2,
-        BT_HID_IDLE = 3,
-        BT_SCAN = 4,
-        BT_IDLE = 5,
-        BT_OTHER_ACTION = 6,
-        BT_BUSY = 7,
-        BT_OTHERBUSY = 8,
-        BT_PAN = 9,
+	BT_SCO = 0,
+	BT_A2DP = 1,
+	BT_HID = 2,
+	BT_HID_IDLE = 3,
+	BT_SCAN = 4,
+	BT_IDLE = 5,
+	BT_OTHER_ACTION = 6,
+	BT_BUSY = 7,
+	BT_OTHERBUSY = 8,
+	BT_PAN = 9,
 };
 
 enum bt_radio_shared {
-        BT_RADIO_SHARED = 0,
-        BT_RADIO_INDIVIDUAL = 1,
+	BT_RADIO_SHARED = 0,
+	BT_RADIO_INDIVIDUAL = 1,
 };
 
 struct bt_coexist_info {
@@ -2255,11 +2257,11 @@ struct bt_coexist_info {
 
 /* Write data to memory */
 #define WRITEEF1BYTE(_ptr, _val)	\
-	(*((u8 *)(_ptr)))=EF1BYTE(_val)
+	((*((u8 *)(_ptr))) = EF1BYTE(_val))
 #define WRITEEF2BYTE(_ptr, _val)	\
-	(*((u16 *)(_ptr)))=EF2BYTE(_val)
+	((*((u16 *)(_ptr))) = EF2BYTE(_val))
 #define WRITEEF4BYTE(_ptr, _val)	\
-	(*((u32 *)(_ptr)))=EF4BYTE(_val)
+	((*((u32 *)(_ptr))) = EF4BYTE(_val))
 
 /*Example:
 BIT_LEN_MASK_32(0) => 0x00000000
@@ -2298,17 +2300,17 @@ Translate subfield (continuous bits in little-endian) of 4-byte
 value to host byte ordering.*/
 #define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
-		( LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset) )  & \
+		(LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset))  & \
 		BIT_LEN_MASK_32(__bitlen) \
 	)
 #define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
-		( LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset) ) & \
+		(LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \
 		BIT_LEN_MASK_16(__bitlen) \
 	)
 #define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
-		( LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset) ) & \
+		(LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \
 		BIT_LEN_MASK_8(__bitlen) \
 	)
 
@@ -2318,17 +2320,17 @@ and return the result in 4-byte value in host byte ordering.*/
 #define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
 		LE_P4BYTE_TO_HOST_4BYTE(__pstart)  & \
-		( ~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) ) \
+		(~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \
 	)
 #define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
 		LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \
-		( ~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) ) \
+		(~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \
 	)
 #define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
 		LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \
-		( ~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen) ) \
+		(~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \
 	)
 
 /*Description:
@@ -2337,19 +2339,19 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 	*((u32 *)(__pstart)) = EF4BYTE \
 	( \
 		LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
-		( (((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset) )\
+		((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset))\
        );
 #define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
 	*((u16 *)(__pstart)) = EF2BYTE \
 	( \
 		LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
-		( (((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset) )\
+		((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset))\
        );
 #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \
 	*((u8 *)(__pstart)) = EF1BYTE \
 	( \
 		LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \
-		( (((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset) ) \
+		((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \
        );
 
 #define	N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \
@@ -2359,18 +2361,18 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 	mem access macro define end
 ****************************************/
 
-#define byte(x,n) ((x >> (8 * n)) & 0xff)
+#define byte(x, n) ((x >> (8 * n)) & 0xff)
 
 #define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC)
-#define RTL_WATCH_DOG_TIME    	2000
+#define RTL_WATCH_DOG_TIME	2000
 #define MSECS(t)		msecs_to_jiffies(t)
-#define WLAN_FC_GET_VERS(fc) 	((fc) & IEEE80211_FCTL_VERS)
-#define WLAN_FC_GET_TYPE(fc) 	((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc) 	((fc) & IEEE80211_FCTL_STYPE)
-#define WLAN_FC_MORE_DATA(fc) 	((fc) & IEEE80211_FCTL_MOREDATA)
-#define SEQ_TO_SN(seq) 		(((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) 		(((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN 			((IEEE80211_SCTL_SEQ) >> 4)
+#define WLAN_FC_GET_VERS(fc)	((fc) & IEEE80211_FCTL_VERS)
+#define WLAN_FC_GET_TYPE(fc)	((fc) & IEEE80211_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc)	((fc) & IEEE80211_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc)	((fc) & IEEE80211_FCTL_MOREDATA)
+#define SEQ_TO_SN(seq)		(((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn)		(((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN			((IEEE80211_SCTL_SEQ) >> 4)
 
 #define	RT_RF_OFF_LEVL_ASPM		BIT(0)	/*PCI ASPM */
 #define	RT_RF_OFF_LEVL_CLK_REQ		BIT(1)	/*PCI clock request */
@@ -2383,7 +2385,7 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 #define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT(6)
 /* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/
 #define	RT_PS_LEVEL_ASPM		BIT(7)
-/*When LPS is on, disable 2R if no packet is received or transmittd.*/
+/*When LPS is on, disable 2R if no packet is received or transmitted.*/
 #define	RT_RF_LPS_DISALBE_2R		BIT(30)
 #define	RT_RF_LPS_LEVEL_ASPM		BIT(31)	/*LPS with ASPM */
 #define	RT_IN_PS_LEVEL(ppsc, _ps_flg)		\
@@ -2397,13 +2399,13 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 	container_of(container_of(x, struct delayed_work, work), y, z)
 
 #define FILL_OCTET_STRING(_os,_octet,_len)	\
-		(_os).octet=(u8*)(_octet);		\
-		(_os).length=(_len);
+		(_os).octet = (u8 *)(_octet);		\
+		(_os).length = (_len);
 
 #define CP_MACADDR(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])
+	((des)[0] = (src)[0],(des)[1] = (src)[1],\
+	(des)[2] = (src)[2],(des)[3] = (src)[3],\
+	(des)[4] = (src)[4],(des)[5] = (src)[5])
 
 static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr)
 {
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index edf979f18a6c..d22916a4b9d8 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -259,7 +259,7 @@ static int ms_read_bytes(struct rtsx_chip *chip,
 		MS_TRANSFER_END, MS_TRANSFER_END);
 
 	for (i = 0; i < data_len - 1; i++)
-	       rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
 
 	if (data_len % 2)
 		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig
deleted file mode 100644
index 245e7847a354..000000000000
--- a/drivers/staging/sb105x/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config SB105X
-	tristate "SystemBase PCI Multiport UART"
-	select SERIAL_CORE
-	depends on PCI && X86 && TTY && BROKEN
-	help
-	  A driver for the SystemBase Multi-2/PCI serial card
-
-	  To compile this driver a module, choose M here: the module
-	  will be called "sb105x".
diff --git a/drivers/staging/sb105x/Makefile b/drivers/staging/sb105x/Makefile
deleted file mode 100644
index b1bf3779acae..000000000000
--- a/drivers/staging/sb105x/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_SB105X) +=	sb105x.o
-
-sb105x-y :=  sb_pci_mp.o
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
deleted file mode 100644
index 276c1bbcc18d..000000000000
--- a/drivers/staging/sb105x/sb_mp_register.h
+++ /dev/null
@@ -1,295 +0,0 @@
-
-/*
- * SB105X_UART.h
- *
- * Copyright (C) 2008 systembase
- *
- * UART registers.
- *
- * This program is free software; you can redistribute 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 UART_SB105X_H
-#define UART_SB105X_H
-
-/*
- * option register
- */
-
-/* Device Information Register */
-#define MP_OPTR_DIR0		0x04 	/* port0 ~ port8 */
-#define MP_OPTR_DIR1		0x05 	/* port8 ~ port15 */
-#define MP_OPTR_DIR2		0x06 	/* port16 ~ port23 */
-#define MP_OPTR_DIR3		0x07 	/* port24 ~ port31 */
-
-#define DIR_UART_16C550 	0
-#define DIR_UART_16C1050	1
-#define DIR_UART_16C1050A	2
-
-#define	DIR_CLK_1843200		0x0		/* input clock 1843200 Hz */
-#define	DIR_CLK_3686400		0x1		/* input clock 3686400 Hz */
-#define	DIR_CLK_7372800		0x2		/* input clock 7372800 Hz */
-#define	DIR_CLK_14745600	0x3		/* input clock 14745600 Hz */
-#define	DIR_CLK_29491200	0x4		/* input clock 29491200 Hz */
-#define	DIR_CLK_58985400	0x5		/* input clock 58985400 Hz */
-
-/* Interface Information Register */
-#define MP_OPTR_IIR0		0x08 	/* port0 ~ port8 */
-#define MP_OPTR_IIR1		0x09 	/* port8 ~ port15 */
-#define MP_OPTR_IIR2		0x0A 	/* port16 ~ port23 */
-#define MP_OPTR_IIR3		0x0B 	/* port24 ~ port31 */
-
-#define IIR_RS232		0x00		/* RS232 type */
-#define IIR_RS422		0x10		/* RS422 type */
-#define IIR_RS485		0x20		/* RS485 type */
-#define IIR_TYPE_MASK		0x30
-
-/* Interrupt Mask Register */
-#define MP_OPTR_IMR0		0x0C 	/* port0 ~ port8 */
-#define MP_OPTR_IMR1		0x0D 	/* port8 ~ port15 */
-#define MP_OPTR_IMR2		0x0E 	/* port16 ~ port23 */
-#define MP_OPTR_IMR3		0x0F 	/* port24 ~ port31 */
-
-/* Interrupt Poll Register */
-#define MP_OPTR_IPR0		0x10 	/* port0 ~ port8 */
-#define MP_OPTR_IPR1		0x11 	/* port8 ~ port15 */
-#define MP_OPTR_IPR2		0x12 	/* port16 ~ port23 */
-#define MP_OPTR_IPR3		0x13 	/* port24 ~ port31 */
-
-/* General Purpose Output Control Register */
-#define MP_OPTR_GPOCR		0x20
-
-/* General Purpose Output Data Register */
-#define MP_OPTR_GPODR		0x21
-
-/* Parallel Additional Function Register */
-#define MP_OPTR_PAFR		0x23
-
-/*
- * systembase 16c105x UART register
- */
-
-#define PAGE_0 0
-#define PAGE_1 1
-#define PAGE_2 2
-#define PAGE_3 3
-#define PAGE_4 4
-
-/*
- *  ******************************************************************
- *  * DLAB=0                  ===============       Page 0 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_RX		0	/* In:  Receive buffer */
-#define SB105X_TX		0	/* Out: Transmit buffer */
-
-#define SB105X_IER		1	/* Out: Interrupt Enable Register */
-
-#define SB105X_IER_CTSI	  	0x80	/* CTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_RTSI	  	0x40	/* RTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_XOI	  	0x20	/* Xoff Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_SME	  	0x10	/* Sleep Mode Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_MSI	  	0x08	/* Enable Modem status interrupt */
-#define SB105X_IER_RLSI	  	0x04	/* Enable receiver line status interrupt */
-#define SB105X_IER_THRI	  	0x02	/* Enable Transmitter holding register int. */
-#define SB105X_IER_RDI	  	0x01	/* Enable receiver data interrupt */
-
-#define SB105X_ISR		2	/* In:  Interrupt ID Register */
-
-#define SB105X_ISR_NOINT	0x01	/* No interrupts pending */
-#define SB105X_ISR_RLSI	  	0x06	/* Receiver line status interrupt (Priority = 1)*/
-#define SB105X_ISR_RDAI	  	0x0c	/* Receive Data Available interrupt */
-#define SB105X_ISR_CTII	  	0x04	/* Character Timeout Indication interrupt */
-#define SB105X_ISR_THRI	  	0x02	/* Transmitter holding register empty */
-#define SB105X_ISR_MSI	  	0x00	/* Modem status interrupt */
-#define SB105X_ISR_RXCI	  	0x10	/* Receive Xoff or Special Character interrupt */
-#define SB105X_ISR_RCSI	  	0x20	/* RTS#, CTS# status interrupt during Auto RTS/CTS flow control */
-
-#define SB105X_FCR		2	/* Out: FIFO Control Register */
-
-#define SB105X_FCR_FEN    	0x01	/* FIFO Enable */
-#define SB105X_FCR_RXFR	  	0x02	/* RX FIFO Reset */
-#define SB105X_FCR_TXFR	  	0x04	/* TX FIFO Reset */
-#define SB105X_FCR_DMS	  	0x08	/* DMA Mode Select */
-
-#define SB105X_FCR_RTR08  	0x00  /* Receive Trigger Level set at 8 */
-#define SB105X_FCR_RTR16  	0x40  /* Receive Trigger Level set at 16 */
-#define SB105X_FCR_RTR56  	0x80  /* Receive Trigger Level set at 56 */
-#define SB105X_FCR_RTR60  	0xc0  /* Receive Trigger Level set at 60 */
-#define SB105X_FCR_TTR08  	0x00  /* Transmit Trigger Level set at 8 */
-#define SB105X_FCR_TTR16	0x10  /* Transmit Trigger Level set at 16 */
-#define SB105X_FCR_TTR32	0x20  /* Transmit Trigger Level set at 32 */
-#define SB105X_FCR_TTR56	0x30  /* Transmit Trigger Level set at 56 */
-
-#define SB105X_LCR		3	/* Out: Line Control Register */
-/*
- *  * Note: if the word length is 5 bits (SB105X_LCR_WLEN5), then setting 
- *  * SB105X_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
- */
-#define SB105X_LCR_DLAB   	0x80  /* Divisor Latch Enable */
-#define SB105X_LCR_SBC    	0x40  /* Break Enable*/
-#define SB105X_LCR_SPAR   	0x20  /* Set Stick parity */
-#define SB105X_LCR_EPAR   	0x10  /* Even parity select */
-#define SB105X_LCR_PAREN  	0x08  /* Parity Enable */
-#define SB105X_LCR_STOP   	0x04  /* Stop bits: 0->1 bit, 1->2 bits, 1 and SB105X_LCR_WLEN5 -> 1.5 bit */
-#define SB105X_LCR_WLEN5  	0x00  /* Wordlength: 5 bits */
-#define SB105X_LCR_WLEN6  	0x01  /* Wordlength: 6 bits */
-#define SB105X_LCR_WLEN7  	0x02  /* Wordlength: 7 bits */
-#define SB105X_LCR_WLEN8  	0x03  /* Wordlength: 8 bits */
-
-#define SB105X_LCR_BF		0xBF
-
-#define SB105X_MCR		4	/* Out: Modem Control Register */
-#define SB105X_MCR_CPS    	0x80  /* Clock Prescaler Select */
-#define SB105X_MCR_P2S    	0x40  /* Page 2 Select /Xoff Re-Transmit Access Enable */
-#define SB105X_MCR_XOA    	0x20  /* Xon Any Enable */
-#define SB105X_MCR_ILB		0x10  /* Internal Loopback Enable */
-#define SB105X_MCR_OUT2		0x08  /* Out2/Interrupt Output Enable*/
-#define SB105X_MCR_OUT1		0x04  /* Out1/Interrupt Output Enable */
-#define SB105X_MCR_RTS    	0x02  /* RTS# Output */
-#define SB105X_MCR_DTR    	0x01  /* DTR# Output */
-
-#define SB105X_LSR		5	/* In:  Line Status Register */
-#define SB105X_LSR_RFEI   	0x80  /* Receive FIFO data error Indicator */
-#define SB105X_LSR_TEMI   	0x40  /* THR and TSR Empty Indicator */
-#define SB105X_LSR_THRE		0x20  /* THR Empty Indicator */
-#define SB105X_LSR_BII		0x10  /* Break interrupt indicator */
-#define SB105X_LSR_FEI		0x08  /* Frame error indicator */
-#define SB105X_LSR_PEI		0x04  /* Parity error indicator */
-#define SB105X_LSR_OEI		0x02  /* Overrun error indicator */
-#define SB105X_LSR_RDRI		0x01  /* Receive data ready Indicator*/
-
-#define SB105X_MSR		6	/* In:  Modem Status Register */
-#define SB105X_MSR_DCD		0x80  /* Data Carrier Detect */
-#define SB105X_MSR_RI		0x40  /* Ring Indicator */
-#define SB105X_MSR_DSR		0x20  /* Data Set Ready */
-#define SB105X_MSR_CTS		0x10  /* Clear to Send */
-#define SB105X_MSR_DDCD		0x08  /* Delta DCD */
-#define SB105X_MSR_DRI		0x04  /* Delta ring indicator */
-#define SB105X_MSR_DDSR		0x02  /* Delta DSR */
-#define SB105X_MSR_DCTS		0x01  /* Delta CTS */
-
-#define SB105XA_MDR		6	/* Out: Multi Drop mode Register */
-#define SB105XA_MDR_NPS		0x08  /* 9th Bit Polarity Select */
-#define SB105XA_MDR_AME		0x02  /* Auto Multi-drop Enable */
-#define SB105XA_MDR_MDE		0x01  /* Multi Drop Enable */
-
-#define SB105X_SPR		7	/* I/O: Scratch Register */
-
-/*
- * DLAB=1
- */
-#define SB105X_DLL		0	/* Out: Divisor Latch Low */
-#define SB105X_DLM		1	/* Out: Divisor Latch High */
-
-/*
- *  ******************************************************************
- *  * DLAB(LCR[7]) = 0 , MCR[6] = 1  =============  Page 2 Registers *
- *  ******************************************************************
- */
-#define SB105X_GICR		1	/* Global Interrupt Control Register */
-#define SB105X_GICR_GIM   	0x01  /* Global Interrupt Mask */
-
-#define SB105X_GISR		2	/* Global Interrupt Status Register */
-#define SB105X_GISR_MGICR0  	0x80  /* Mirror the content of GICR[0] */
-#define SB105X_GISR_CS3IS   	0x08  /* SB105X of CS3# Interrupt Status */
-#define SB105X_GISR_CS2IS   	0x04  /* SB105X of CS2# Interrupt Status */
-#define SB105X_GISR_CS1IS   	0x02  /* SB105X of CS1# Interrupt Status */
-#define SB105X_GISR_CS0IS   	0x01  /* SB105X of CS0# Interrupt Status */
-
-#define SB105X_TFCR		5	/* Transmit FIFO Count Register */
-
-#define SB105X_RFCR		6	/* Receive FIFO Count Register */
-
-#define	SB105X_FSR		7	/* Flow Control Status Register */
-#define SB105X_FSR_THFS     	0x20  /* Transmit Hardware Flow Control Status */
-#define SB105X_FSR_TSFS     	0x10  /* Transmit Software Flow Control Status */
-#define SB105X_FSR_RHFS     	0x02  /* Receive Hardware Flow Control Status */
-#define SB105X_FSR_RSFS     	0x01  /* Receive Software Flow Control Status */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 0       =============    Page 3 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_PSR		0	/* Page Select Register */
-#define SB105X_PSR_P3KEY    	0xA4 /* Page 3 Select Key */
-#define SB105X_PSR_P4KEY    	0xA5 /* Page 5 Select Key */
-
-#define SB105X_ATR		1	/* Auto Toggle Control Register */
-#define SB105X_ATR_RPS      	0x80  /* RXEN Polarity Select */
-#define SB105X_ATR_RCMS     	0x40  /* RXEN Control Mode Select */
-#define SB105X_ATR_TPS      	0x20  /* TXEN Polarity Select */
-#define SB105X_ATR_TCMS     	0x10  /* TXEN Control Mode Select */
-#define SB105X_ATR_ATDIS    	0x00  /* Auto Toggle is disabled */
-#define SB105X_ATR_ART      	0x01  /* RTS#/TXEN pin operates as TXEN */
-#define SB105X_ATR_ADT      	0x02  /* DTR#/TXEN pin operates as TXEN */
-#define SB105X_ATR_A80      	0x03  /* only in 80 pin use */
-
-#define SB105X_EFR		2	/* (Auto) Enhanced Feature Register */
-#define SB105X_EFR_ACTS     	0x80  /* Auto-CTS Flow Control Enable */
-#define SB105X_EFR_ARTS     	0x40  /* Auto-RTS Flow Control Enable */
-#define SB105X_EFR_SCD      	0x20  /* Special Character Detect */
-#define SB105X_EFR_EFBEN    	0x10  /* Enhanced Function Bits Enable */
-
-#define SB105X_XON1		4	/* Xon1 Character Register */
-#define SB105X_XON2		5	/* Xon2 Character Register */
-#define SB105X_XOFF1		6	/* Xoff1 Character Register */
-#define SB105X_XOFF2		7	/* Xoff2 Character Register */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 1       ============     Page 4 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_AFR		1	/* Additional Feature Register */
-#define SB105X_AFR_GIPS     	0x20  /* Global Interrupt Polarity Select */
-#define SB105X_AFR_GIEN     	0x10  /* Global Interrupt Enable */
-#define SB105X_AFR_AFEN     	0x01  /* 256-byte FIFO Enable */
-
-#define SB105X_XRCR		2	/* Xoff Re-transmit Count Register */
-#define SB105X_XRCR_NRC1    	0x00  /* Transmits Xoff Character whenever the number of received data is 1 during XOFF status */
-#define SB105X_XRCR_NRC4    	0x01  /* Transmits Xoff Character whenever the number of received data is 4 during XOFF status */
-#define SB105X_XRCR_NRC8    	0x02  /* Transmits Xoff Character whenever the number of received data is 8 during XOFF status */
-#define SB105X_XRCR_NRC16   	0x03  /* Transmits Xoff Character whenever the number of received data is 16 during XOFF status */
-
-#define SB105X_TTR		4	/* Transmit FIFO Trigger Level Register */
-#define SB105X_RTR		5	/* Receive FIFO Trigger Level Register */
-#define SB105X_FUR		6	/* Flow Control Upper Threshold Register */
-#define SB105X_FLR		7	/* Flow Control Lower Threshold Register */
-
-
-/* page 0 */
-
-#define SB105X_GET_CHAR(port)	inb((port)->iobase + SB105X_RX)
-#define SB105X_GET_IER(port)	inb((port)->iobase + SB105X_IER)
-#define SB105X_GET_ISR(port)	inb((port)->iobase + SB105X_ISR)
-#define SB105X_GET_LCR(port)	inb((port)->iobase + SB105X_LCR)
-#define SB105X_GET_MCR(port)	inb((port)->iobase + SB105X_MCR)
-#define SB105X_GET_LSR(port)	inb((port)->iobase + SB105X_LSR)
-#define SB105X_GET_MSR(port)	inb((port)->iobase + SB105X_MSR)
-#define SB105X_GET_SPR(port)	inb((port)->iobase + SB105X_SPR)
-
-#define SB105X_PUT_CHAR(port,v)	outb((v),(port)->iobase + SB105X_TX )
-#define SB105X_PUT_IER(port,v)	outb((v),(port)->iobase + SB105X_IER )
-#define SB105X_PUT_FCR(port,v)	outb((v),(port)->iobase + SB105X_FCR )
-#define SB105X_PUT_LCR(port,v)	outb((v),(port)->iobase + SB105X_LCR )
-#define SB105X_PUT_MCR(port,v)	outb((v),(port)->iobase + SB105X_MCR )
-#define SB105X_PUT_SPR(port,v)	outb((v),(port)->iobase + SB105X_SPR )
-
-
-/* page 1 */
-#define SB105X_GET_REG(port,reg)	inb((port)->iobase + (reg))
-#define SB105X_PUT_REG(port,reg,v)	outb((v),(port)->iobase + (reg))
-
-/* page 2 */
-
-#define SB105X_PUT_PSR(port,v)	outb((v),(port)->iobase + SB105X_PSR )
-
-#endif 
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
deleted file mode 100644
index c9d6ee3903ad..000000000000
--- a/drivers/staging/sb105x/sb_pci_mp.c
+++ /dev/null
@@ -1,3189 +0,0 @@
-#include "sb_pci_mp.h"
-#include <linux/module.h>
-#include <linux/parport.h>
-
-extern struct parport *parport_pc_probe_port(unsigned long base_lo,
-		unsigned long base_hi,
-		int irq, int dma,
-		struct device *dev,
-		int irqflags);
-
-static struct mp_device_t mp_devs[MAX_MP_DEV];
-static int mp_nrpcibrds = sizeof(mp_pciboards)/sizeof(mppcibrd_t);
-static int NR_BOARD=0;
-static int NR_PORTS=0;
-static struct mp_port multi_ports[MAX_MP_PORT];
-static struct irq_info irq_lists[NR_IRQS];
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset);
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value);
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset);
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg);
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value);
-static void SendATCommand(struct mp_port *mtpt);
-static int set_deep_fifo(struct sb_uart_port *port, int status);
-static int get_deep_fifo(struct sb_uart_port *port);
-static int get_device_type(int arg);
-static int set_auto_rts(struct sb_uart_port *port, int status);
-static void mp_stop(struct tty_struct *tty);
-static void __mp_start(struct tty_struct *tty);
-static void mp_start(struct tty_struct *tty);
-static void mp_tasklet_action(unsigned long data);
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear);
-static int mp_startup(struct sb_uart_state *state, int init_hw);
-static void mp_shutdown(struct sb_uart_state *state);
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios);
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c);
-static int mp_put_char(struct tty_struct *tty, unsigned char ch);
-
-static void mp_put_chars(struct tty_struct *tty);
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int mp_write_room(struct tty_struct *tty);
-static int mp_chars_in_buffer(struct tty_struct *tty);
-static void mp_flush_buffer(struct tty_struct *tty);
-static void mp_send_xchar(struct tty_struct *tty, char ch);
-static void mp_throttle(struct tty_struct *tty);
-static void mp_unthrottle(struct tty_struct *tty);
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo);
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo);
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value);
-
-static int mp_tiocmget(struct tty_struct *tty);
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-static int mp_break_ctl(struct tty_struct *tty, int break_state);
-static int mp_do_autoconfig(struct sb_uart_state *state);
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg);
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt);
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios);
-static void mp_close(struct tty_struct *tty, struct file *filp);
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void mp_hangup(struct tty_struct *tty);
-static void mp_update_termios(struct sb_uart_state *state);
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state);
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line);
-static int mp_open(struct tty_struct *tty, struct file *filp);
-static const char *mp_type(struct sb_uart_port *port);
-static void mp_change_pm(struct sb_uart_state *state, int pm_state);
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port);
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state);
-static int mp_register_driver(struct uart_driver *drv);
-static void mp_unregister_driver(struct uart_driver *drv);
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags);
-static void autoconfig_irq(struct mp_port *mtpt);
-static void multi_stop_tx(struct sb_uart_port *port);
-static void multi_start_tx(struct sb_uart_port *port);
-static void multi_stop_rx(struct sb_uart_port *port);
-static void multi_enable_ms(struct sb_uart_port *port);
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status );
-static _INLINE_ void transmit_chars(struct mp_port *mtpt);
-static _INLINE_ void check_modem_status(struct mp_port *mtpt);
-static inline void multi_handle_port(struct mp_port *mtpt);
-static irqreturn_t multi_interrupt(int irq, void *dev_id);
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt);
-static int serial_link_irq_chain(struct mp_port *mtpt);
-static void serial_unlink_irq_chain(struct mp_port *mtpt);
-static void multi_timeout(unsigned long data);
-static unsigned int multi_tx_empty(struct sb_uart_port *port);
-static unsigned int multi_get_mctrl(struct sb_uart_port *port);
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl);
-static void multi_break_ctl(struct sb_uart_port *port, int break_state);
-static int multi_startup(struct sb_uart_port *port);
-static void multi_shutdown(struct sb_uart_port *port);
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud);
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old);
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate);
-static void multi_release_std_resource(struct mp_port *mtpt);
-static void multi_release_port(struct sb_uart_port *port);
-static int multi_request_port(struct sb_uart_port *port);
-static void multi_config_port(struct sb_uart_port *port, int flags);
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser);
-static const char *multi_type(struct sb_uart_port *port);
-static void __init multi_init_ports(void);
-static void __init multi_register_ports(struct uart_driver *drv);
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd);
-
-static int deep[256];
-static int deep_count;
-static int fcr_arr[256];
-static int fcr_count;
-static int ttr[256];
-static int ttr_count;
-static int rtr[256];
-static int rtr_count;
-
-module_param_array(deep,int,&deep_count,0);
-module_param_array(fcr_arr,int,&fcr_count,0);
-module_param_array(ttr,int,&ttr_count,0);
-module_param_array(rtr,int,&rtr_count,0);
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset)
-{
-	return inb(mtpt->port.iobase + offset);
-}
-
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value)
-{
-	outb(value, mtpt->port.iobase + offset);
-}
-
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset)
-{
-	return inb(mtpt->option_base_addr + offset);
-}
-
-static int sb1053a_get_interface(struct mp_port *mtpt, int port_num)
-{
-	unsigned long option_base_addr = mtpt->option_base_addr;
-	unsigned int  interface = 0;
-
-	switch (port_num)
-	{
-		case 0:
-		case 1:
-			/* set GPO[1:0] = 00 */
-			outb(0x00, option_base_addr + MP_OPTR_GPODR);
-			break;
-		case 2:
-		case 3:
-			/* set GPO[1:0] = 01 */
-			outb(0x01, option_base_addr + MP_OPTR_GPODR);
-			break;
-		case 4:
-		case 5:
-			/* set GPO[1:0] = 10 */
-			outb(0x02, option_base_addr + MP_OPTR_GPODR);
-			break;
-		default:
-			break;
-	}
-
-	port_num &= 0x1;
-
-	/* get interface */
-	interface = inb(option_base_addr + MP_OPTR_IIR0 + port_num);
-
-	/* set GPO[1:0] = 11 */
-	outb(0x03, option_base_addr + MP_OPTR_GPODR);
-
-	return (interface);
-}
-		
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg)
-{
-	int ret = 0;
-	unsigned int lcr = 0;
-	unsigned int mcr = 0;
-	unsigned int tmp = 0;
-
-	if( page <= 0)
-	{
-		printk(" page 0 can not use this function\n");
-		return -1;
-	}
-
-	switch(page)
-	{
-		case 1:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_DLAB;
-			SB105X_PUT_LCR(port, tmp);
-
-			tmp = SB105X_GET_LCR(port);
-
-			ret = SB105X_GET_REG(port,reg);
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		case 2:
-			mcr = SB105X_GET_MCR(port);
-			tmp = mcr | SB105X_MCR_P2S;
-			SB105X_PUT_MCR(port,tmp);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_MCR(port,mcr);
-			break;
-		case 3:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_BF;
-			SB105X_PUT_LCR(port,tmp);
-			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P3KEY);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		case 4:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_BF;
-			SB105X_PUT_LCR(port,tmp);
-			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P4KEY);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		default:
-			printk(" error invalid page number \n");
-			return -1;
-	}
-
-	return ret;
-}
-
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value)
-{  
-	int lcr = 0;
-	int mcr = 0;
-	int ret = 0;
-
-	if( page <= 0)
-	{
-		printk(" page 0 can not use this function\n");
-		return -1;
-	}
-	switch(page)
-	{
-		case 1:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_DLAB);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		case 2:
-			mcr = SB105X_GET_MCR(port);
-			SB105X_PUT_MCR(port, mcr | SB105X_MCR_P2S);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_MCR(port, mcr);
-			ret = 1;
-			break;
-		case 3:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-			SB105X_PUT_PSR(port, SB105X_PSR_P3KEY);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		case 4:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-			SB105X_PUT_PSR(port, SB105X_PSR_P4KEY);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		default:
-			printk(" error invalid page number \n");
-			return -1;
-	}
-
-	return ret;
-}
-
-static int set_multidrop_mode(struct sb_uart_port *port, unsigned int mode)
-{
-	int mdr = SB105XA_MDR_NPS;
-
-	if (mode & MDMODE_ENABLE)
-	{
-		mdr |= SB105XA_MDR_MDE;
-	}
-
-	if (1) //(mode & MDMODE_AUTO)
-	{
-		int efr = 0;
-		mdr |= SB105XA_MDR_AME;
-		efr = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-		efr |= SB105X_EFR_SCD;
-		sb1054_set_register(port, PAGE_3, SB105X_EFR, efr);
-	}
-
-	sb1054_set_register(port, PAGE_1, SB105XA_MDR, mdr);
-	port->mdmode &= ~0x6;
-	port->mdmode |= mode;
-	printk("[%d] multidrop init: %x\n", port->line, port->mdmode);
-
-	return 0;
-}
-
-static int get_multidrop_addr(struct sb_uart_port *port)
-{
-	return sb1054_get_register(port, PAGE_3, SB105X_XOFF2);
-}
-
-static int set_multidrop_addr(struct sb_uart_port *port, unsigned int addr)
-{
-	sb1054_set_register(port, PAGE_3, SB105X_XOFF2, addr);
-
-	return 0;
-}
-
-static void SendATCommand(struct mp_port *mtpt)
-{
-	//		      a    t	cr   lf
-	unsigned char ch[] = {0x61,0x74,0x0d,0x0a,0x0};
-	unsigned char lineControl;
-	unsigned char i=0;
-	unsigned char Divisor = 0xc;
-
-	lineControl = serial_inp(mtpt,UART_LCR);
-	serial_outp(mtpt,UART_LCR,(lineControl | UART_LCR_DLAB));
-	serial_outp(mtpt,UART_DLL,(Divisor & 0xff));
-	serial_outp(mtpt,UART_DLM,(Divisor & 0xff00)>>8); //baudrate is 4800
-
-
-	serial_outp(mtpt,UART_LCR,lineControl);	
-	serial_outp(mtpt,UART_LCR,0x03); // N-8-1
-	serial_outp(mtpt,UART_FCR,7); 
-	serial_outp(mtpt,UART_MCR,0x3);
-	while(ch[i]){
-		while((serial_inp(mtpt,UART_LSR) & 0x60) !=0x60){
-			;
-		}
-		serial_outp(mtpt,0,ch[i++]);
-	}
-
-
-}// end of SendATCommand()
-
-static int set_deep_fifo(struct sb_uart_port *port, int status)
-{
-	int afr_status = 0;
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-
-	if(status == ENABLE)
-	{
-		afr_status |= SB105X_AFR_AFEN;
-	}
-	else
-	{
-		afr_status &= ~SB105X_AFR_AFEN;
-	}
-		
-	sb1054_set_register(port,PAGE_4,SB105X_AFR,afr_status);
-	sb1054_set_register(port,PAGE_4,SB105X_TTR,ttr[port->line]); 
-	sb1054_set_register(port,PAGE_4,SB105X_RTR,rtr[port->line]); 
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-		
-	return afr_status;
-}
-
-static int get_device_type(int arg)
-{
-	int ret;
-        ret = inb(mp_devs[arg].option_reg_addr+MP_OPTR_DIR0);
-        ret = (ret & 0xf0) >> 4;
-        switch (ret)
-        {
-               case DIR_UART_16C550:
-                    return PORT_16C55X;
-               case DIR_UART_16C1050:
-                    return PORT_16C105X;
-               case DIR_UART_16C1050A:
-               /*
-               if (mtpt->port.line < 2)
-               {
-                    return PORT_16C105XA;
-               }
-               else
-               {
-                   if (mtpt->device->device_id & 0x50)
-                   {
-                       return PORT_16C55X;
-                   }
-                   else
-                   {
-                       return PORT_16C105X;
-                   }
-               }*/
-               return PORT_16C105XA;
-               default:
-                    return PORT_UNKNOWN;
-        }
-
-}
-static int get_deep_fifo(struct sb_uart_port *port)
-{
-	int afr_status = 0;
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-	return afr_status;
-}
-
-static int set_auto_rts(struct sb_uart_port *port, int status)
-{
-	int atr_status = 0;
-
-#if 0
-	int efr_status = 0;
-
-	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-	if(status == ENABLE)
-		efr_status |= SB105X_EFR_ARTS;
-	else
-		efr_status &= ~SB105X_EFR_ARTS;
-	sb1054_set_register(port,PAGE_3,SB105X_EFR,efr_status);
-	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-#endif
-		
-//ATR
-	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-	switch(status)
-	{
-		case RS422PTP:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_A80);
-			break;
-		case RS422MD:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-		case RS485NE:
-			atr_status = (SB105X_ATR_RCMS) | (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-		case RS485ECHO:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-	}
-
-	sb1054_set_register(port,PAGE_3,SB105X_ATR,atr_status);
-	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-
-	return atr_status;
-}
-
-static void mp_stop(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->ops->stop_tx(port);
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __mp_start(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
-			!tty->stopped && !tty->hw_stopped)
-		port->ops->start_tx(port);
-}
-
-static void mp_start(struct tty_struct *tty)
-{
-	__mp_start(tty);
-}
-
-static void mp_tasklet_action(unsigned long data)
-{
-	struct sb_uart_state *state = (struct sb_uart_state *)data;
-	struct tty_struct *tty;
-
-	printk("tasklet is called!\n");
-	tty = state->info->tty;
-	tty_wakeup(tty);
-}
-
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear)
-{
-	unsigned int old;
-
-	old = port->mctrl;
-	port->mctrl = (old & ~clear) | set;
-	if (old != port->mctrl)
-		port->ops->set_mctrl(port, port->mctrl);
-}
-
-#define uart_set_mctrl(port,set)	mp_update_mctrl(port,set,0)
-#define uart_clear_mctrl(port,clear)	mp_update_mctrl(port,0,clear)
-
-static int mp_startup(struct sb_uart_state *state, int init_hw)
-{
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-	unsigned long page;
-	int retval = 0;
-
-	if (info->flags & UIF_INITIALIZED)
-		return 0;
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	if (port->type == PORT_UNKNOWN)
-		return 0;
-
-	if (!info->xmit.buf) {
-		page = get_zeroed_page(GFP_KERNEL);
-		if (!page)
-			return -ENOMEM;
-
-		info->xmit.buf = (unsigned char *) page;
-			
-		uart_circ_clear(&info->xmit);
-	}
-
-	retval = port->ops->startup(port);
-	if (retval == 0) {
-		if (init_hw) {
-			mp_change_speed(state, NULL);
-
-			if (info->tty && (info->tty->termios.c_cflag & CBAUD))
-				uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-		}
-
-		info->flags |= UIF_INITIALIZED;
-
-		if (info->tty)
-			clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-
-	if (retval && capable(CAP_SYS_ADMIN))
-		retval = 0;
-
-	return retval;
-}
-
-static void mp_shutdown(struct sb_uart_state *state)
-{
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	if (info->flags & UIF_INITIALIZED) {
-		info->flags &= ~UIF_INITIALIZED;
-
-		if (!info->tty || (info->tty->termios.c_cflag & HUPCL))
-			uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-
-		wake_up_interruptible(&info->delta_msr_wait);
-
-		port->ops->shutdown(port);
-
-		synchronize_irq(port->irq);
-	}
-	tasklet_kill(&info->tlet);
-
-	if (info->xmit.buf) {
-		free_page((unsigned long)info->xmit.buf);
-		info->xmit.buf = NULL;
-	}
-}
-
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios)
-{
-	struct tty_struct *tty = state->info->tty;
-	struct sb_uart_port *port = state->port;
-
-	if (!tty || port->type == PORT_UNKNOWN)
-		return;
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		state->info->flags |= UIF_CTS_FLOW;
-	else
-		state->info->flags &= ~UIF_CTS_FLOW;
-
-	if (tty->termios.c_cflag & CLOCAL)
-		state->info->flags &= ~UIF_CHECK_CD;
-	else
-		state->info->flags |= UIF_CHECK_CD;
-
-	port->ops->set_termios(port, &tty->termios, old_termios);
-}
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (!circ->buf)
-		return 0;
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (uart_circ_chars_free(circ) != 0) {
-		circ->buf[circ->head] = c;
-		circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-	return ret;
-}
-
-static int mp_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return __mp_put_char(state->port, &state->info->xmit, ch);
-}
-
-static void mp_put_chars(struct tty_struct *tty)
-{
-	mp_start(tty);
-}
-
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-	struct circ_buf *circ;
-	int c, ret = 0;
-
-	if (!state || !state->info) {
-		return -EL3HLT;
-	}
-
-	port = state->port;
-	circ = &state->info->xmit;
-
-	if (!circ->buf)
-		return 0;
-		
-	while (1) {
-		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-		if (count < c)
-			c = count;
-		if (c <= 0)
-			break;
-	memcpy(circ->buf + circ->head, buf, c);
-
-		circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	mp_start(tty);
-	return ret;
-}
-
-static int mp_write_room(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return uart_circ_chars_free(&state->info->xmit);
-}
-
-static int mp_chars_in_buffer(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return uart_circ_chars_pending(&state->info->xmit);
-}
-
-static void mp_flush_buffer(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-	unsigned long flags;
-
-	if (!state || !state->info) {
-		return;
-	}
-
-	port = state->port;
-	spin_lock_irqsave(&port->lock, flags);
-	uart_circ_clear(&state->info->xmit);
-	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	tty_wakeup(tty);
-}
-
-static void mp_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long flags;
-
-	if (port->ops->send_xchar)
-		port->ops->send_xchar(port, ch);
-	else {
-		port->x_char = ch;
-		if (ch) {
-			spin_lock_irqsave(&port->lock, flags);
-			port->ops->start_tx(port);
-			spin_unlock_irqrestore(&port->lock, flags);
-		}
-	}
-}
-
-static void mp_throttle(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	if (I_IXOFF(tty))
-		mp_send_xchar(tty, STOP_CHAR(tty));
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_clear_mctrl(state->port, TIOCM_RTS);
-}
-
-static void mp_unthrottle(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	if (I_IXOFF(tty)) {
-		if (port->x_char)
-			port->x_char = 0;
-		else
-			mp_send_xchar(tty, START_CHAR(tty));
-	}
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_set_mctrl(port, TIOCM_RTS);
-}
-
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo)
-{
-	struct sb_uart_port *port = state->port;
-	struct serial_struct tmp;
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type	    = port->type;
-	tmp.line	    = port->line;
-	tmp.port	    = port->iobase;
-	if (HIGH_BITS_OFFSET)
-		tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
-	tmp.irq		    = port->irq;
-	tmp.flags	    = port->flags;
-	tmp.xmit_fifo_size  = port->fifosize;
-	tmp.baud_base	    = port->uartclk / 16;
-	tmp.close_delay	    = state->close_delay;
-	tmp.closing_wait    = state->closing_wait == USF_CLOSING_WAIT_NONE ?
-		ASYNC_CLOSING_WAIT_NONE :
-		state->closing_wait;
-	tmp.custom_divisor  = port->custom_divisor;
-	tmp.hub6	    = port->hub6;
-	tmp.io_type         = port->iotype;
-	tmp.iomem_reg_shift = port->regshift;
-	tmp.iomem_base      = (void *)port->mapbase;
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo)
-{
-	struct serial_struct new_serial;
-	struct sb_uart_port *port = state->port;
-	unsigned long new_port;
-	unsigned int change_irq, change_port, closing_wait;
-	unsigned int old_custom_divisor;
-	unsigned int old_flags, new_flags;
-	int retval = 0;
-
-	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-		return -EFAULT;
-
-	new_port = new_serial.port;
-	if (HIGH_BITS_OFFSET)
-		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-
-	new_serial.irq = irq_canonicalize(new_serial.irq);
-
-	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
-		USF_CLOSING_WAIT_NONE : new_serial.closing_wait;
-	MP_STATE_LOCK(state);
-
-	change_irq  = new_serial.irq != port->irq;
-	change_port = new_port != port->iobase ||
-		(unsigned long)new_serial.iomem_base != port->mapbase ||
-		new_serial.hub6 != port->hub6 ||
-		new_serial.io_type != port->iotype ||
-		new_serial.iomem_reg_shift != port->regshift ||
-		new_serial.type != port->type;
-	old_flags = port->flags;
-	new_flags = new_serial.flags;
-	old_custom_divisor = port->custom_divisor;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		retval = -EPERM;
-		if (change_irq || change_port ||
-				(new_serial.baud_base != port->uartclk / 16) ||
-				(new_serial.close_delay != state->close_delay) ||
-				(closing_wait != state->closing_wait) ||
-				(new_serial.xmit_fifo_size != port->fifosize) ||
-				(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
-			goto exit;
-		port->flags = ((port->flags & ~UPF_USR_MASK) |
-				(new_flags & UPF_USR_MASK));
-		port->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	if (port->ops->verify_port)
-		retval = port->ops->verify_port(port, &new_serial);
-
-	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-			(new_serial.baud_base < 9600))
-		retval = -EINVAL;
-
-	if (retval)
-		goto exit;
-
-	if (change_port || change_irq) {
-		retval = -EBUSY;
-
-		if (uart_users(state) > 1)
-			goto exit;
-
-		mp_shutdown(state);
-	}
-
-	if (change_port) {
-		unsigned long old_iobase, old_mapbase;
-		unsigned int old_type, old_iotype, old_hub6, old_shift;
-
-		old_iobase = port->iobase;
-		old_mapbase = port->mapbase;
-		old_type = port->type;
-		old_hub6 = port->hub6;
-		old_iotype = port->iotype;
-		old_shift = port->regshift;
-
-		if (old_type != PORT_UNKNOWN)
-			port->ops->release_port(port);
-
-		port->iobase = new_port;
-		port->type = new_serial.type;
-		port->hub6 = new_serial.hub6;
-		port->iotype = new_serial.io_type;
-		port->regshift = new_serial.iomem_reg_shift;
-		port->mapbase = (unsigned long)new_serial.iomem_base;
-
-		if (port->type != PORT_UNKNOWN) {
-			retval = port->ops->request_port(port);
-		} else {
-			retval = 0;
-		}
-
-		if (retval && old_type != PORT_UNKNOWN) {
-			port->iobase = old_iobase;
-			port->type = old_type;
-			port->hub6 = old_hub6;
-			port->iotype = old_iotype;
-			port->regshift = old_shift;
-			port->mapbase = old_mapbase;
-			retval = port->ops->request_port(port);
-			if (retval)
-				port->type = PORT_UNKNOWN;
-
-			retval = -EBUSY;
-		}
-	}
-
-	port->irq              = new_serial.irq;
-	port->uartclk          = new_serial.baud_base * 16;
-	port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
-		(new_flags & UPF_CHANGE_MASK);
-	port->custom_divisor   = new_serial.custom_divisor;
-	state->close_delay     = new_serial.close_delay;
-	state->closing_wait    = closing_wait;
-	port->fifosize         = new_serial.xmit_fifo_size;
-	if (state->info->tty)
-		state->info->tty->low_latency =
-			(port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-
-check_and_exit:
-	retval = 0;
-	if (port->type == PORT_UNKNOWN)
-		goto exit;
-	if (state->info->flags & UIF_INITIALIZED) {
-		if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
-				old_custom_divisor != port->custom_divisor) {
-			if (port->flags & UPF_SPD_MASK) {
-				printk(KERN_NOTICE
-						"%s sets custom speed on ttyMP%d. This "
-						"is deprecated.\n", current->comm,
-						port->line);
-			}
-			mp_change_speed(state, NULL);
-		}
-	} else
-		retval = mp_startup(state, 1);
-exit:
-	MP_STATE_UNLOCK(state);
-	return retval;
-}
-
-
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value)
-{
-	struct sb_uart_port *port = state->port;
-	unsigned int result;
-
-	result = port->ops->tx_empty(port);
-
-	if (port->x_char ||
-			((uart_circ_chars_pending(&state->info->xmit) > 0) &&
-				!state->info->tty->stopped && !state->info->tty->hw_stopped))
-		result &= ~TIOCSER_TEMT;
-
-	return put_user(result, value);
-}
-
-static int mp_tiocmget(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	int result = -EIO;
-
-	MP_STATE_LOCK(state);
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		result = port->mctrl;
-		spin_lock_irq(&port->lock);
-		result |= port->ops->get_mctrl(port);
-		spin_unlock_irq(&port->lock);
-	}
-	MP_STATE_UNLOCK(state);
-	return result;
-}
-
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	int ret = -EIO;
-
-
-	MP_STATE_LOCK(state);
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		mp_update_mctrl(port, set, clear);
-		ret = 0;
-	}
-	MP_STATE_UNLOCK(state);
-
-	return ret;
-}
-
-static int mp_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	MP_STATE_LOCK(state);
-
-	if (port->type != PORT_UNKNOWN)
-		port->ops->break_ctl(port, break_state);
-
-	MP_STATE_UNLOCK(state);
-	return 0;
-}
-
-static int mp_do_autoconfig(struct sb_uart_state *state)
-{
-	struct sb_uart_port *port = state->port;
-	int flags, ret;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&state->mutex))
-		return -ERESTARTSYS;
-	ret = -EBUSY;
-	if (uart_users(state) == 1) {
-		mp_shutdown(state);
-
-		if (port->type != PORT_UNKNOWN)
-			port->ops->release_port(port);
-
-		flags = UART_CONFIG_TYPE;
-		if (port->flags & UPF_AUTO_IRQ)
-			flags |= UART_CONFIG_IRQ;
-
-		port->ops->config_port(port, flags);
-
-		ret = mp_startup(state, 1);
-	}
-	MP_STATE_UNLOCK(state);
-	return ret;
-}
-
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg)
-{
-	struct sb_uart_port *port = state->port;
-	DECLARE_WAITQUEUE(wait, current);
-	struct sb_uart_icount cprev, cnow;
-	int ret;
-
-	spin_lock_irq(&port->lock);
-	memcpy(&cprev, &port->icount, sizeof(struct sb_uart_icount));
-
-	port->ops->enable_ms(port);
-	spin_unlock_irq(&port->lock);
-
-	add_wait_queue(&state->info->delta_msr_wait, &wait);
-	for (;;) {
-		spin_lock_irq(&port->lock);
-		memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-		spin_unlock_irq(&port->lock);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-			ret = 0;
-			break;
-		}
-
-		schedule();
-
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		cprev = cnow;
-	}
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&state->info->delta_msr_wait, &wait);
-
-	return ret;
-}
-
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt)
-{
-	struct serial_icounter_struct icount = {};
-	struct sb_uart_icount cnow;
-	struct sb_uart_port *port = state->port;
-
-	spin_lock_irq(&port->lock);
-	memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-	spin_unlock_irq(&port->lock);
-
-	icount.cts         = cnow.cts;
-	icount.dsr         = cnow.dsr;
-	icount.rng         = cnow.rng;
-	icount.dcd         = cnow.dcd;
-	icount.rx          = cnow.rx;
-	icount.tx          = cnow.tx;
-	icount.frame       = cnow.frame;
-	icount.overrun     = cnow.overrun;
-	icount.parity      = cnow.parity;
-	icount.brk         = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
-
-	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
-}
-
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct mp_port *info = (struct mp_port *)state->port;
-	int ret = -ENOIOCTLCMD;
-
-
-	switch (cmd) {
-		case TIOCSMULTIDROP:
-			/* set multi-drop mode enable or disable, and default operation mode is H/W mode */
-			if (info->port.type == PORT_16C105XA)
-			{
-				//arg &= ~0x6;
-				//state->port->mdmode = 0;
-				return set_multidrop_mode((struct sb_uart_port *)info, (unsigned int)arg);
-			}
-			ret = -ENOTSUPP;
-			break;
-		case GETDEEPFIFO:
-			ret = get_deep_fifo(state->port);
-			return ret;
-		case SETDEEPFIFO:
-			ret = set_deep_fifo(state->port,arg);
-			deep[state->port->line] = arg;
-			return ret;
-		case SETTTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_4,SB105X_TTR,arg);
-				ttr[state->port->line] = arg;
-			}
-			return ret;
-		case SETRTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_4,SB105X_RTR,arg);
-				rtr[state->port->line] = arg;
-			}
-			return ret;
-		case GETTTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_get_register(state->port,PAGE_4,SB105X_TTR);
-			}
-			return ret;
-		case GETRTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_get_register(state->port,PAGE_4,SB105X_RTR);
-			}
-			return ret;
-
-		case SETFCR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_1,SB105X_FCR,arg);
-			}
-			else{
-				serial_out(info,2,arg);
-			}
-
-			return ret;
-		case TIOCSMDADDR:
-			/* set multi-drop address */
-			if (info->port.type == PORT_16C105XA)
-			{
-				state->port->mdmode |= MDMODE_ADDR;
-				return set_multidrop_addr((struct sb_uart_port *)info, (unsigned int)arg);
-			}
-			ret = -ENOTSUPP;
-			break;
-
-		case TIOCGMDADDR:
-			/* set multi-drop address */
-			if ((info->port.type == PORT_16C105XA) && (state->port->mdmode & MDMODE_ADDR))
-			{
-				return get_multidrop_addr((struct sb_uart_port *)info);
-			}
-			ret = -ENOTSUPP;
-			break;
-
-		case TIOCSENDADDR:
-			/* send address in multi-drop mode */
-			if ((info->port.type == PORT_16C105XA) 
-					&& (state->port->mdmode & (MDMODE_ENABLE)))
-			{
-				if (mp_chars_in_buffer(tty) > 0)
-				{
-					tty_wait_until_sent(tty, 0);
-				}
-				//while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-				//while (sb1054_get_register(state->port, PAGE_2, SB105X_TFCR) != 0);
-				while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-				serial_out(info, UART_SCR, (int)arg);
-			}
-			break;
-
-		case TIOCGSERIAL:
-			ret = mp_get_info(state, (struct serial_struct *)arg);
-			break;
-
-		case TIOCSSERIAL:
-			ret = mp_set_info(state, (struct serial_struct *)arg);
-			break;
-
-		case TIOCSERCONFIG:
-			ret = mp_do_autoconfig(state);
-			break;
-
-		case TIOCSERGWILD: /* obsolete */
-		case TIOCSERSWILD: /* obsolete */
-			ret = 0;
-			break;
-			/* for Multiport */
-		case TIOCGNUMOFPORT: /* Get number of ports */
-			return NR_PORTS;
-		case TIOCGGETDEVID:
-			return mp_devs[arg].device_id;
-		case TIOCGGETREV:
-			return mp_devs[arg].revision;
-		case TIOCGGETNRPORTS:
-			return mp_devs[arg].nr_ports;
-		case TIOCGGETBDNO:
-			return NR_BOARD;
-		case TIOCGGETINTERFACE:
-			if (mp_devs[arg].revision == 0xc0)
-			{
-				/* for SB16C1053APCI */
-				return (sb1053a_get_interface(info, info->port.line));
-			}
-			else
-			{
-				return (inb(mp_devs[arg].option_reg_addr+MP_OPTR_IIR0+(state->port->line/8)));
-			}
-		case TIOCGGETPORTTYPE:
-			ret = get_device_type(arg);
-			return ret;
-		case TIOCSMULTIECHO: /* set to multi-drop mode(RS422) or echo mode(RS485)*/
-			outb( ( inb(info->interface_config_addr) & ~0x03 ) | 0x01 ,  
-					info->interface_config_addr);
-			return 0;
-		case TIOCSPTPNOECHO: /* set to multi-drop mode(RS422) or echo mode(RS485) */
-			outb( ( inb(info->interface_config_addr) & ~0x03 )  ,             
-					info->interface_config_addr);
-			return 0;
-	}
-
-	if (ret != -ENOIOCTLCMD)
-		goto out;
-
-	if (tty->flags & (1 << TTY_IO_ERROR)) {
-		ret = -EIO;
-		goto out;
-	}
-
-	switch (cmd) {
-		case TIOCMIWAIT:
-			ret = mp_wait_modem_status(state, arg);
-			break;
-
-		case TIOCGICOUNT:
-			ret = mp_get_count(state, (struct serial_icounter_struct *)arg);
-			break;
-	}
-
-	if (ret != -ENOIOCTLCMD)
-		goto out;
-
-	MP_STATE_LOCK(state);
-	switch (cmd) {
-		case TIOCSERGETLSR: /* Get line status register */
-			ret = mp_get_lsr_info(state, (unsigned int *)arg);
-			break;
-
-		default: {
-					struct sb_uart_port *port = state->port;
-					if (port->ops->ioctl)
-						ret = port->ops->ioctl(port, cmd, arg);
-					break;
-				}
-	}
-
-	MP_STATE_UNLOCK(state);
-out:
-	return ret;
-}
-
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	unsigned long flags;
-	unsigned int cflag = tty->termios.c_cflag;
-
-#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-	if ((cflag ^ old_termios->c_cflag) == 0 &&
-			RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0)
-		return;
-
-	mp_change_speed(state, old_termios);
-
-	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
-
-	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-		unsigned int mask = TIOCM_DTR;
-		if (!(cflag & CRTSCTS) ||
-				!test_bit(TTY_THROTTLED, &tty->flags))
-			mask |= TIOCM_RTS;
-		uart_set_mctrl(state->port, mask);
-	}
-
-	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->port->lock, flags);
-		tty->hw_stopped = 0;
-		__mp_start(tty);
-		spin_unlock_irqrestore(&state->port->lock, flags);
-	}
-
-	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->port->lock, flags);
-		if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
-			tty->hw_stopped = 1;
-			state->port->ops->stop_tx(state->port);
-		}
-		spin_unlock_irqrestore(&state->port->lock, flags);
-	}
-}
-
-static void mp_close(struct tty_struct *tty, struct file *filp)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-
-	printk("mp_close!\n");
-	if (!state || !state->port)
-		return;
-
-	port = state->port;
-
-	printk("close1 %d\n", __LINE__);
-	MP_STATE_LOCK(state);
-
-	printk("close2 %d\n", __LINE__);
-	if (tty_hung_up_p(filp))
-		goto done;
-
-	printk("close3 %d\n", __LINE__);
-	if ((tty->count == 1) && (state->count != 1)) {
-		printk("mp_close: bad serial port count; tty->count is 1, "
-				"state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	printk("close4 %d\n", __LINE__);
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttyMP%d: %d\n",
-				port->line, state->count);
-		state->count = 0;
-	}
-	if (state->count)
-		goto done;
-
-	tty->closing = 1;
-
-	printk("close5 %d\n", __LINE__);
-	if (state->closing_wait != USF_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, state->closing_wait);
-
-	printk("close6 %d\n", __LINE__);
-	if (state->info->flags & UIF_INITIALIZED) {
-		unsigned long flags;
-		spin_lock_irqsave(&port->lock, flags);
-		port->ops->stop_rx(port);
-		spin_unlock_irqrestore(&port->lock, flags);
-		mp_wait_until_sent(tty, port->timeout);
-	}
-	printk("close7 %d\n", __LINE__);
-
-	mp_shutdown(state);
-	printk("close8 %d\n", __LINE__);
-	mp_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-	state->info->tty = NULL;
-	if (state->info->blocked_open) 
-	{
-		if (state->close_delay)
-		{
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(state->close_delay);
-		}
-	}
-	else
-	{
-		mp_change_pm(state, 3);
-	}
-	printk("close8 %d\n", __LINE__);
-
-	state->info->flags &= ~UIF_NORMAL_ACTIVE;
-	wake_up_interruptible(&state->info->open_wait);
-
-done:
-	printk("close done\n");
-	MP_STATE_UNLOCK(state);
-	module_put(THIS_MODULE);
-}
-
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long char_time, expire;
-
-	if (port->type == PORT_UNKNOWN || port->fifosize == 0)
-		return;
-
-	char_time = (port->timeout - HZ/50) / port->fifosize;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout && timeout < char_time)
-		char_time = timeout;
-
-	if (timeout == 0 || timeout > 2 * port->timeout)
-		timeout = 2 * port->timeout;
-
-	expire = jiffies + timeout;
-
-	while (!port->ops->tx_empty(port)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(char_time);
-		if (signal_pending(current))
-			break;
-		if (time_after(jiffies, expire))
-			break;
-	}
-	set_current_state(TASK_RUNNING); /* might not be needed */
-}
-
-static void mp_hangup(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	MP_STATE_LOCK(state);
-	if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
-		mp_flush_buffer(tty);
-		mp_shutdown(state);
-		state->count = 0;
-		state->info->flags &= ~UIF_NORMAL_ACTIVE;
-		state->info->tty = NULL;
-		wake_up_interruptible(&state->info->open_wait);
-		wake_up_interruptible(&state->info->delta_msr_wait);
-	}
-	MP_STATE_UNLOCK(state);
-}
-
-static void mp_update_termios(struct sb_uart_state *state)
-{
-	struct tty_struct *tty = state->info->tty;
-	struct sb_uart_port *port = state->port;
-
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		mp_change_speed(state, NULL);
-
-		if (tty->termios.c_cflag & CBAUD)
-			uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-	}
-}
-
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-	unsigned int mctrl;
-
-	info->blocked_open++;
-	state->count--;
-
-	add_wait_queue(&info->open_wait, &wait);
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || info->tty == NULL)
-			break;
-
-		if (!(info->flags & UIF_INITIALIZED))
-			break;
-
-		if ((filp->f_flags & O_NONBLOCK) ||
-				(info->tty->termios.c_cflag & CLOCAL) ||
-				(info->tty->flags & (1 << TTY_IO_ERROR))) {
-			break;
-		}
-
-		if (info->tty->termios.c_cflag & CBAUD)
-			uart_set_mctrl(port, TIOCM_DTR);
-
-		spin_lock_irq(&port->lock);
-		port->ops->enable_ms(port);
-		mctrl = port->ops->get_mctrl(port);
-		spin_unlock_irq(&port->lock);
-		if (mctrl & TIOCM_CAR)
-			break;
-
-		MP_STATE_UNLOCK(state);
-		schedule();
-		MP_STATE_LOCK(state);
-
-		if (signal_pending(current))
-			break;
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-
-	state->count++;
-	info->blocked_open--;
-
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (!info->tty || tty_hung_up_p(filp))
-		return -EAGAIN;
-
-	return 0;
-}
-
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line)
-{
-	struct sb_uart_state *state;
-
-	MP_MUTEX_LOCK(mp_mutex);
-	state = drv->state + line;
-	if (mutex_lock_interruptible(&state->mutex)) {
-		state = ERR_PTR(-ERESTARTSYS);
-		goto out;
-	}
-	state->count++;
-	if (!state->port) {
-		state->count--;
-		MP_STATE_UNLOCK(state);
-		state = ERR_PTR(-ENXIO);
-		goto out;
-	}
-
-	if (!state->info) {
-		state->info = kmalloc(sizeof(struct sb_uart_info), GFP_KERNEL);
-		if (state->info) {
-			memset(state->info, 0, sizeof(struct sb_uart_info));
-			init_waitqueue_head(&state->info->open_wait);
-			init_waitqueue_head(&state->info->delta_msr_wait);
-
-			state->port->info = state->info;
-
-			tasklet_init(&state->info->tlet, mp_tasklet_action,
-					(unsigned long)state);
-		} else {
-			state->count--;
-			MP_STATE_UNLOCK(state);
-			state = ERR_PTR(-ENOMEM);
-		}
-	}
-
-out:
-	MP_MUTEX_UNLOCK(mp_mutex);
-	return state;
-}
-
-static int mp_open(struct tty_struct *tty, struct file *filp)
-{
-	struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
-	struct sb_uart_state *state;
-	int retval;
-	int  line = tty->index;
-	struct mp_port *mtpt;
-
-	retval = -ENODEV;
-	if (line >= tty->driver->num)
-		goto fail;
-
-	state = uart_get(drv, line);
-
-	if (IS_ERR(state)) {
-		retval = PTR_ERR(state);
-		goto fail;
-	}
-
-	mtpt  = (struct mp_port *)state->port;
-
-	tty->driver_data = state;
-	tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-	tty->alt_speed = 0;
-	state->info->tty = tty;
-
-	if (tty_hung_up_p(filp)) {
-		retval = -EAGAIN;
-		state->count--;
-		MP_STATE_UNLOCK(state);
-		goto fail;
-	}
-
-	if (state->count == 1)
-		mp_change_pm(state, 0);
-
-	retval = mp_startup(state, 0);
-
-	if (retval == 0)
-		retval = mp_block_til_ready(filp, state);
-	MP_STATE_UNLOCK(state);
-
-	if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
-		state->info->flags |= UIF_NORMAL_ACTIVE;
-
-		mp_update_termios(state);
-	}
-
-	uart_clear_mctrl(state->port, TIOCM_RTS);
-	try_module_get(THIS_MODULE);
-fail:
-	return retval;
-}
-
-
-static const char *mp_type(struct sb_uart_port *port)
-{
-	const char *str = NULL;
-
-	if (port->ops->type)
-		str = port->ops->type(port);
-
-	if (!str)
-		str = "unknown";
-
-	return str;
-}
-
-static void mp_change_pm(struct sb_uart_state *state, int pm_state)
-{
-	struct sb_uart_port *port = state->port;
-	if (port->ops->pm)
-		port->ops->pm(port, pm_state, state->pm_state);
-	state->pm_state = pm_state;
-}
-
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	char address[64];
-
-	switch (port->iotype) {
-		case UPIO_PORT:
-			snprintf(address, sizeof(address),"I/O 0x%x", port->iobase);
-			break;
-		case UPIO_HUB6:
-			snprintf(address, sizeof(address),"I/O 0x%x offset 0x%x", port->iobase, port->hub6);
-			break;
-		case UPIO_MEM:
-			snprintf(address, sizeof(address),"MMIO 0x%lx", port->mapbase);
-			break;
-		default:
-			snprintf(address, sizeof(address),"*unknown*" );
-			strlcpy(address, "*unknown*", sizeof(address));
-			break;
-	}
-
-	printk( "%s%d at %s (irq = %d) is a %s\n",
-			drv->dev_name, port->line, address, port->irq, mp_type(port));
-
-}
-
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port)
-{
-	unsigned int flags;
-
-
-	if (!port->iobase && !port->mapbase && !port->membase)
-	{
-		DPRINTK("%s error \n",__FUNCTION__);
-		return;
-	}
-	flags = UART_CONFIG_TYPE;
-	if (port->flags & UPF_AUTO_IRQ)
-		flags |= UART_CONFIG_IRQ;
-	if (port->flags & UPF_BOOT_AUTOCONF) {
-		port->type = PORT_UNKNOWN;
-		port->ops->config_port(port, flags);
-	}
-
-	if (port->type != PORT_UNKNOWN) {
-		unsigned long flags;
-
-		mp_report_port(drv, port);
-
-		spin_lock_irqsave(&port->lock, flags);
-		port->ops->set_mctrl(port, 0);
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		mp_change_pm(state, 3);
-	}
-}
-
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state)
-{
-	struct sb_uart_port *port = state->port;
-	struct sb_uart_info *info = state->info;
-
-	if (info && info->tty)
-		tty_hangup(info->tty);
-
-	MP_STATE_LOCK(state);
-
-	state->info = NULL;
-
-	if (port->type != PORT_UNKNOWN)
-		port->ops->release_port(port);
-
-	port->type = PORT_UNKNOWN;
-
-	if (info) {
-		tasklet_kill(&info->tlet);
-		kfree(info);
-	}
-
-	MP_STATE_UNLOCK(state);
-}
-static struct tty_operations mp_ops = {
-	.open		= mp_open,
-	.close		= mp_close,
-	.write		= mp_write,
-	.put_char	= mp_put_char,
-	.flush_chars	= mp_put_chars,
-	.write_room	= mp_write_room,
-	.chars_in_buffer= mp_chars_in_buffer,
-	.flush_buffer	= mp_flush_buffer,
-	.ioctl		= mp_ioctl,
-	.throttle	= mp_throttle,
-	.unthrottle	= mp_unthrottle,
-	.send_xchar	= mp_send_xchar,
-	.set_termios	= mp_set_termios,
-	.stop		= mp_stop,
-	.start		= mp_start,
-	.hangup		= mp_hangup,
-	.break_ctl	= mp_break_ctl,
-	.wait_until_sent= mp_wait_until_sent,
-#ifdef CONFIG_PROC_FS
-	.proc_fops	= NULL,
-#endif
-	.tiocmget	= mp_tiocmget,
-	.tiocmset	= mp_tiocmset,
-};
-
-static int mp_register_driver(struct uart_driver *drv)
-{
-	struct tty_driver *normal = NULL;
-	int i, retval;
-
-	drv->state = kmalloc(sizeof(struct sb_uart_state) * drv->nr, GFP_KERNEL);
-	retval = -ENOMEM;
-	if (!drv->state)
-	{
-		printk("SB PCI Error: Kernel memory allocation error!\n");
-		goto out;
-	}
-	memset(drv->state, 0, sizeof(struct sb_uart_state) * drv->nr);
-
-	normal = alloc_tty_driver(drv->nr);
-	if (!normal)
-	{
-		printk("SB PCI Error: tty allocation error!\n");
-		goto out;
-	}
-
-	drv->tty_driver = normal;
-
-	normal->owner           = drv->owner;
-	normal->magic		= TTY_DRIVER_MAGIC;
-	normal->driver_name     = drv->driver_name;
-	normal->name		= drv->dev_name;
-	normal->major		= drv->major;
-	normal->minor_start	= drv->minor;
-
-	normal->num		= MAX_MP_PORT ; 
-
-	normal->type		= TTY_DRIVER_TYPE_SERIAL;
-	normal->subtype		= SERIAL_TYPE_NORMAL;
-	normal->init_termios	= tty_std_termios;
-	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	normal->driver_state    = drv;
-
-	tty_set_operations(normal, &mp_ops);
-
-for (i = 0; i < drv->nr; i++) {
-	struct sb_uart_state *state = drv->state + i;
-
-	state->close_delay     = 500;   
-	state->closing_wait    = 30000; 
-
-	mutex_init(&state->mutex);
-	}
-
-	retval = tty_register_driver(normal);
-out:
-	if (retval < 0) {
-		printk("Register tty driver Fail!\n");
-		put_tty_driver(normal);
-		kfree(drv->state);
-	}
-
-	return retval;
-}
-
-void mp_unregister_driver(struct uart_driver *drv)
-{
-    struct tty_driver *normal = NULL;
-
-    normal = drv->tty_driver;
-
-    if (!normal)
-    {
-        return;
-    }
-
-    tty_unregister_driver(normal);
-    put_tty_driver(normal);
-    drv->tty_driver = NULL;
-
-
-    kfree(drv->state);
-
-}
-
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	struct sb_uart_state *state;
-	int ret = 0;
-
-
-	if (port->line >= drv->nr)
-		return -EINVAL;
-
-	state = drv->state + port->line;
-
-	MP_MUTEX_LOCK(mp_mutex);
-	if (state->port) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	state->port = port;
-
-	spin_lock_init(&port->lock);
-	port->cons = drv->cons;
-	port->info = state->info;
-
-	mp_configure_port(drv, state, port);
-
-	tty_register_device(drv->tty_driver, port->line, port->dev);
-
-out:
-	MP_MUTEX_UNLOCK(mp_mutex);
-
-
-	return ret;
-}
-
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	struct sb_uart_state *state = drv->state + port->line;
-
-	if (state->port != port)
-		printk(KERN_ALERT "Removing wrong port: %p != %p\n",
-				state->port, port);
-
-	MP_MUTEX_LOCK(mp_mutex);
-
-	tty_unregister_device(drv->tty_driver, port->line);
-
-	mp_unconfigure_port(drv, state);
-	state->port = NULL;
-	MP_MUTEX_UNLOCK(mp_mutex);
-
-	return 0;
-}
-
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags)
-{
-	unsigned char status1, scratch, scratch2, scratch3;
-	unsigned char save_lcr, save_mcr;
-	unsigned long flags;
-
-	unsigned char u_type;
-	unsigned char b_ret = 0;
-
-	if (!mtpt->port.iobase && !mtpt->port.mapbase && !mtpt->port.membase)
-		return;
-
-	DEBUG_AUTOCONF("ttyMP%d: autoconf (0x%04x, 0x%p): ",
-			mtpt->port.line, mtpt->port.iobase, mtpt->port.membase);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-
-	if (!(mtpt->port.flags & UPF_BUGGY_UART)) {
-		scratch = serial_inp(mtpt, UART_IER);
-		serial_outp(mtpt, UART_IER, 0);
-#ifdef __i386__
-		outb(0xff, 0x080);
-#endif
-		scratch2 = serial_inp(mtpt, UART_IER) & 0x0f;
-		serial_outp(mtpt, UART_IER, 0x0F);
-#ifdef __i386__
-		outb(0, 0x080);
-#endif
-		scratch3 = serial_inp(mtpt, UART_IER) & 0x0F;
-		serial_outp(mtpt, UART_IER, scratch);
-		if (scratch2 != 0 || scratch3 != 0x0F) {
-			DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-					scratch2, scratch3);
-			goto out;
-		}
-	}
-
-	save_mcr = serial_in(mtpt, UART_MCR);
-	save_lcr = serial_in(mtpt, UART_LCR);
-
-	if (!(mtpt->port.flags & UPF_SKIP_TEST)) {
-		serial_outp(mtpt, UART_MCR, UART_MCR_LOOP | 0x0A);
-		status1 = serial_inp(mtpt, UART_MSR) & 0xF0;
-		serial_outp(mtpt, UART_MCR, save_mcr);
-		if (status1 != 0x90) {
-			DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-					status1);
-			goto out;
-		}
-	}
-
-	serial_outp(mtpt, UART_LCR, 0xBF);
-	serial_outp(mtpt, UART_EFR, 0);
-	serial_outp(mtpt, UART_LCR, 0);
-
-	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-	scratch = serial_in(mtpt, UART_IIR) >> 6;
-
-	DEBUG_AUTOCONF("iir=%d ", scratch);
-	if(mtpt->device->nr_ports >= 8)
-		b_ret = read_option_register(mtpt,(MP_OPTR_DIR0 + ((mtpt->port.line)/8)));
-	else	
-		b_ret = read_option_register(mtpt,MP_OPTR_DIR0);
-	u_type = (b_ret & 0xf0) >> 4;
-	if(mtpt->port.type == PORT_UNKNOWN )
-	{
-		switch (u_type)
-		{
-			case DIR_UART_16C550:
-				mtpt->port.type = PORT_16C55X;
-				break;
-			case DIR_UART_16C1050:
-				mtpt->port.type = PORT_16C105X;
-				break;
-			case DIR_UART_16C1050A:
-				if (mtpt->port.line < 2)
-				{
-					mtpt->port.type = PORT_16C105XA;
-				}
-				else
-				{
-					if (mtpt->device->device_id & 0x50)
-					{
-						mtpt->port.type = PORT_16C55X;
-					}
-					else
-					{
-						mtpt->port.type = PORT_16C105X;
-					}
-				}
-				break;
-			default:	
-				mtpt->port.type = PORT_UNKNOWN;
-				break;
-		}
-	}
-
-	if(mtpt->port.type == PORT_UNKNOWN )
-	{
-printk("unknow2\n");
-		switch (scratch) {
-			case 0:
-			case 1:
-				mtpt->port.type = PORT_UNKNOWN;
-				break;
-			case 2:
-			case 3:
-				mtpt->port.type = PORT_16C55X;
-				break;
-		}
-	}
-
-	serial_outp(mtpt, UART_LCR, save_lcr);
-
-	mtpt->port.fifosize = uart_config[mtpt->port.type].dfl_xmit_fifo_size;
-	mtpt->capabilities = uart_config[mtpt->port.type].flags;
-
-	if (mtpt->port.type == PORT_UNKNOWN)
-		goto out;
-	serial_outp(mtpt, UART_MCR, save_mcr);
-	serial_outp(mtpt, UART_FCR, (UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR |
-				UART_FCR_CLEAR_XMIT));
-	serial_outp(mtpt, UART_FCR, 0);
-	(void)serial_in(mtpt, UART_RX);
-	serial_outp(mtpt, UART_IER, 0);
-
-out:
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-	DEBUG_AUTOCONF("type=%s\n", uart_config[mtpt->port.type].name);
-}
-
-static void autoconfig_irq(struct mp_port *mtpt)
-{
-	unsigned char save_mcr, save_ier;
-	unsigned long irqs;
-	int irq;
-
-	/* forget possible initially masked and pending IRQ */
-	probe_irq_off(probe_irq_on());
-	save_mcr = serial_inp(mtpt, UART_MCR);
-	save_ier = serial_inp(mtpt, UART_IER);
-	serial_outp(mtpt, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
-	irqs = probe_irq_on();
-	serial_outp(mtpt, UART_MCR, 0);
-	serial_outp(mtpt, UART_MCR,
-		UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-
-	serial_outp(mtpt, UART_IER, 0x0f);    /* enable all intrs */
-	(void)serial_inp(mtpt, UART_LSR);
-	(void)serial_inp(mtpt, UART_RX);
-	(void)serial_inp(mtpt, UART_IIR);
-	(void)serial_inp(mtpt, UART_MSR);
-	serial_outp(mtpt, UART_TX, 0xFF);
-	irq = probe_irq_off(irqs);
-
-	serial_outp(mtpt, UART_MCR, save_mcr);
-	serial_outp(mtpt, UART_IER, save_ier);
-
-	mtpt->port.irq = (irq > 0) ? irq : 0;
-}
-
-static void multi_stop_tx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	if (mtpt->ier & UART_IER_THRI) {
-		mtpt->ier &= ~UART_IER_THRI;
-		serial_out(mtpt, UART_IER, mtpt->ier);
-	}
-
-	tasklet_schedule(&port->info->tlet);
-}
-
-static void multi_start_tx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	if (!(mtpt->ier & UART_IER_THRI)) {
-		mtpt->ier |= UART_IER_THRI;
-		serial_out(mtpt, UART_IER, mtpt->ier);
-	}
-}
-
-static void multi_stop_rx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	mtpt->ier &= ~UART_IER_RLSI;
-	mtpt->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-static void multi_enable_ms(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	mtpt->ier |= UART_IER_MSI;
-	serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status )
-{
-	struct tty_struct *tty = mtpt->port.info->tty;
-	unsigned char lsr = *status;
-	int max_count = 256;
-	unsigned char ch;
-	char flag;
-
-	//lsr &= mtpt->port.read_status_mask;
-
-	do {
-		if ((lsr & UART_LSR_PE) && (mtpt->port.mdmode & MDMODE_ENABLE))
-		{
-			ch = serial_inp(mtpt, UART_RX);
-		}
-		else if (lsr & UART_LSR_SPECIAL) 
-		{
-			flag = 0;
-			ch = serial_inp(mtpt, UART_RX);
-
-			if (lsr & UART_LSR_BI) 
-			{
-
-				mtpt->port.icount.brk++;
-				flag = TTY_BREAK;
-
-				if (sb_uart_handle_break(&mtpt->port))
-					goto ignore_char;
-			} 
-			if (lsr & UART_LSR_PE)
-			{
-				mtpt->port.icount.parity++;
-				flag = TTY_PARITY;
-			}
-			if (lsr & UART_LSR_FE)
-			{
-				mtpt->port.icount.frame++;
-				flag = TTY_FRAME;
-			}
-			if (lsr & UART_LSR_OE)
-			{
-				mtpt->port.icount.overrun++;
-				flag = TTY_OVERRUN;
-			}
-			tty_insert_flip_char(tty, ch, flag);
-		}
-		else
-		{
-			ch = serial_inp(mtpt, UART_RX);
-			tty_insert_flip_char(tty, ch, 0);
-		}
-ignore_char:
-		lsr = serial_inp(mtpt, UART_LSR);
-	} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
-
-	tty_flip_buffer_push(tty);
-}
-
-
-
-
-static _INLINE_ void transmit_chars(struct mp_port *mtpt)
-{
-	struct circ_buf *xmit = &mtpt->port.info->xmit;
-	int count;
-
-	if (mtpt->port.x_char) {
-		serial_outp(mtpt, UART_TX, mtpt->port.x_char);
-		mtpt->port.icount.tx++;
-		mtpt->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&mtpt->port)) {
-		multi_stop_tx(&mtpt->port);
-		return;
-	}
-
-	count = uart_circ_chars_pending(xmit);
-
-	if(count > mtpt->port.fifosize)
-	{
-		count = mtpt->port.fifosize;
-	}
-
-	printk("[%d] mdmode: %x\n", mtpt->port.line, mtpt->port.mdmode);
-	do {
-#if 0
-		/* check multi-drop mode */
-		if ((mtpt->port.mdmode & (MDMODE_ENABLE | MDMODE_ADDR)) == (MDMODE_ENABLE | MDMODE_ADDR))
-		{
-			printk("send address\n");
-			/* send multi-drop address */
-			serial_out(mtpt, UART_SCR, xmit->buf[xmit->tail]);
-		}
-		else
-#endif
-		{
-			serial_out(mtpt, UART_TX, xmit->buf[xmit->tail]);
-		}
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		mtpt->port.icount.tx++;
-	} while (--count > 0);
-}
-
-
-
-static _INLINE_ void check_modem_status(struct mp_port *mtpt)
-{
-	int status;
-
-	status = serial_in(mtpt, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		mtpt->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		mtpt->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		sb_uart_handle_dcd_change(&mtpt->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		sb_uart_handle_cts_change(&mtpt->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&mtpt->port.info->delta_msr_wait);
-}
-
-static inline void multi_handle_port(struct mp_port *mtpt)
-{
-	unsigned int status = serial_inp(mtpt, UART_LSR);
-
-	//printk("lsr: %x\n", status);
-
-	if ((status & UART_LSR_DR) || (status & UART_LSR_SPECIAL))
-		receive_chars(mtpt, &status);
-	check_modem_status(mtpt);
-	if (status & UART_LSR_THRE)
-	{
-		if ((mtpt->port.type == PORT_16C105X)
-			|| (mtpt->port.type == PORT_16C105XA))
-			transmit_chars(mtpt);
-		else
-		{
-			if (mtpt->interface >= RS485NE)
-				uart_set_mctrl(&mtpt->port, TIOCM_RTS);
-			
-			transmit_chars(mtpt);
-
-
-			if (mtpt->interface >= RS485NE)
-			{
-				while((status=serial_in(mtpt,UART_LSR) &0x60)!=0x60);
-				uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-			}
-		}
-	}
-}
-
-
-
-static irqreturn_t multi_interrupt(int irq, void *dev_id)
-{
-	struct irq_info *iinfo = dev_id;
-	struct list_head *lhead, *end = NULL;
-	int pass_counter = 0;
-
-
-	spin_lock(&iinfo->lock);
-
-	lhead = iinfo->head;
-	do {
-		struct mp_port *mtpt;
-		unsigned int iir;
-
-		mtpt = list_entry(lhead, struct mp_port, list);
-		
-		iir = serial_in(mtpt, UART_IIR);
-		printk("interrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
-		if (!(iir & UART_IIR_NO_INT)) 
-		{
-			printk("interrupt handle\n");
-			spin_lock(&mtpt->port.lock);
-			multi_handle_port(mtpt);
-			spin_unlock(&mtpt->port.lock);
-
-			end = NULL;
-		} else if (end == NULL)
-			end = lhead;
-
-		lhead = lhead->next;
-		if (lhead == iinfo->head && pass_counter++ > PASS_LIMIT) 
-		{
-			printk(KERN_ERR "multi: too much work for "
-					"irq%d\n", irq);
-			printk( "multi: too much work for "
-					"irq%d\n", irq);
-			break;
-		}
-	} while (lhead != end);
-
-	spin_unlock(&iinfo->lock);
-
-
-        return IRQ_HANDLED;
-}
-
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt)
-{
-	spin_lock_irq(&i->lock);
-
-	if (!list_empty(i->head)) {
-		if (i->head == &mtpt->list)
-			i->head = i->head->next;
-		list_del(&mtpt->list);
-	} else {
-		i->head = NULL;
-	}
-
-	spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct mp_port *mtpt)
-{
-	struct irq_info *i = irq_lists + mtpt->port.irq;
-	int ret, irq_flags = mtpt->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-	spin_lock_irq(&i->lock);
-
-	if (i->head) {
-		list_add(&mtpt->list, i->head);
-		spin_unlock_irq(&i->lock);
-
-		ret = 0;
-	} else {
-		INIT_LIST_HEAD(&mtpt->list);
-		i->head = &mtpt->list;
-		spin_unlock_irq(&i->lock);
-
-		ret = request_irq(mtpt->port.irq, multi_interrupt,
-				irq_flags, "serial", i);
-		if (ret < 0)
-			serial_do_unlink(i, mtpt);
-	}
-
-	return ret;
-}
-
-
-
-
-static void serial_unlink_irq_chain(struct mp_port *mtpt)
-{
-	struct irq_info *i = irq_lists + mtpt->port.irq;
-
-	if (list_empty(i->head))
-	{
-		free_irq(mtpt->port.irq, i);
-	}
-	serial_do_unlink(i, mtpt);
-}
-
-static void multi_timeout(unsigned long data)
-{
-	struct mp_port *mtpt = (struct mp_port *)data;
-
-
-	spin_lock(&mtpt->port.lock);
-	multi_handle_port(mtpt);
-	spin_unlock(&mtpt->port.lock);
-
-	mod_timer(&mtpt->timer, jiffies+1 );
-}
-
-static unsigned int multi_tx_empty(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	ret = serial_in(mtpt, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	return ret;
-}
-
-
-static unsigned int multi_get_mctrl(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(mtpt, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char mcr = 0;
-
-	mctrl &= 0xff;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-
-	serial_out(mtpt, UART_MCR, mcr);
-}
-
-
-static void multi_break_ctl(struct sb_uart_port *port, int break_state)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	if (break_state == -1)
-		mtpt->lcr |= UART_LCR_SBC;
-	else
-		mtpt->lcr &= ~UART_LCR_SBC;
-	serial_out(mtpt, UART_LCR, mtpt->lcr);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-
-
-static int multi_startup(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-	int retval;
-
-	mtpt->capabilities = uart_config[mtpt->port.type].flags;
-	mtpt->mcr = 0;
-
-	if (mtpt->capabilities & UART_CLEAR_FIFO) {
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-		serial_outp(mtpt, UART_FCR, 0);
-	}
-
-	(void) serial_inp(mtpt, UART_LSR);
-	(void) serial_inp(mtpt, UART_RX);
-	(void) serial_inp(mtpt, UART_IIR);
-	(void) serial_inp(mtpt, UART_MSR);
-	//test-wlee 9-bit disable
-	serial_outp(mtpt, UART_MSR, 0);
-
-
-	if (!(mtpt->port.flags & UPF_BUGGY_UART) &&
-			(serial_inp(mtpt, UART_LSR) == 0xff)) {
-		printk("ttyS%d: LSR safety check engaged!\n", mtpt->port.line);
-		//return -ENODEV;
-	}
-
-	if ((!is_real_interrupt(mtpt->port.irq)) || (mtpt->poll_type==TYPE_POLL)) {
-		unsigned int timeout = mtpt->port.timeout;
-
-		timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
-		mtpt->timer.data = (unsigned long)mtpt;
-		mod_timer(&mtpt->timer, jiffies + timeout);
-	} 
-	else 
-	{
-		retval = serial_link_irq_chain(mtpt);
-		if (retval)
-			return retval;
-	}
-
-	serial_outp(mtpt, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	if ((is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_INTERRUPT))
-		mtpt->port.mctrl |= TIOCM_OUT2;
-
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	
-	mtpt->ier = UART_IER_RLSI | UART_IER_RDI;
-	serial_outp(mtpt, UART_IER, mtpt->ier);
-
-	(void) serial_inp(mtpt, UART_LSR);
-	(void) serial_inp(mtpt, UART_RX);
-	(void) serial_inp(mtpt, UART_IIR);
-	(void) serial_inp(mtpt, UART_MSR);
-
-	return 0;
-}
-
-
-
-static void multi_shutdown(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-
-
-	mtpt->ier = 0;
-	serial_outp(mtpt, UART_IER, 0);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	mtpt->port.mctrl &= ~TIOCM_OUT2;
-
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	serial_out(mtpt, UART_LCR, serial_inp(mtpt, UART_LCR) & ~UART_LCR_SBC);
-	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR |
-			UART_FCR_CLEAR_XMIT);
-	serial_outp(mtpt, UART_FCR, 0);
-
-
-	(void) serial_in(mtpt, UART_RX);
-
-	if ((!is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_POLL))
-	{
-		del_timer_sync(&mtpt->timer);
-	}
-	else
-	{
-		serial_unlink_irq_chain(mtpt);
-	}
-}
-
-
-
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-	unsigned int quot;
-
-	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-			baud == (port->uartclk/4))
-		quot = 0x8001;
-	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-			baud == (port->uartclk/8))
-		quot = 0x8002;
-	else
-		quot = sb_uart_get_divisor(port, baud);
-
-	return quot;
-}
-
-
-
-
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-
-	switch (termios->c_cflag & CSIZE) {
-		case CS5:
-			cval = 0x00;
-			break;
-		case CS6:
-			cval = 0x01;
-			break;
-		case CS7:
-			cval = 0x02;
-			break;
-		default:
-		case CS8:
-			cval = 0x03;
-			break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-#ifdef CMSPAR
-	if (termios->c_cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-#endif
-
-	baud = sb_uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = multi_get_divisor(port, baud);
-
-	if (mtpt->capabilities & UART_USE_FIFO) {
-		//if (baud < 2400)
-		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-		//else
-		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-
-		//	fcr = UART_FCR_ENABLE_FIFO | 0x90;
-			fcr = fcr_arr[mtpt->port.line];
-	}
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-
-	sb_uart_update_timeout(port, termios->c_cflag, baud);
-
-	mtpt->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		mtpt->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		mtpt->port.read_status_mask |= UART_LSR_BI;
-
-	mtpt->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		mtpt->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		mtpt->port.ignore_status_mask |= UART_LSR_BI;
-		if (termios->c_iflag & IGNPAR)
-			mtpt->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	if ((termios->c_cflag & CREAD) == 0)
-		mtpt->port.ignore_status_mask |= UART_LSR_DR;
-
-	mtpt->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&mtpt->port, termios->c_cflag))
-		mtpt->ier |= UART_IER_MSI;
-
-	serial_out(mtpt, UART_IER, mtpt->ier);
-
-	if (mtpt->capabilities & UART_STARTECH) {
-		serial_outp(mtpt, UART_LCR, 0xBF);
-		serial_outp(mtpt, UART_EFR,
-				termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
-	}
-
-	serial_outp(mtpt, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-
-	serial_outp(mtpt, UART_DLL, quot & 0xff);     /* LS of divisor */
-	serial_outp(mtpt, UART_DLM, quot >> 8);       /* MS of divisor */
-
-	serial_outp(mtpt, UART_LCR, cval);        /* reset DLAB */
-	mtpt->lcr = cval;                 /* Save LCR */
-
-	if (fcr & UART_FCR_ENABLE_FIFO) {
-		/* emulated UARTs (Lucent Venus 167x) need two steps */
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-	}
-
-	serial_outp(mtpt, UART_FCR, fcr);     /* set fcr */
-
-
-	if ((mtpt->port.type == PORT_16C105X)
-		|| (mtpt->port.type == PORT_16C105XA))
-	{
-		if(deep[mtpt->port.line]!=0)
-			set_deep_fifo(port, ENABLE);
-
-		if (mtpt->interface != RS232)
-			set_auto_rts(port,mtpt->interface);
-
-	}
-	else
-	{
-		if (mtpt->interface >= RS485NE)
-		{
-			uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-		}
-	}
-
-	if(mtpt->device->device_id == PCI_DEVICE_ID_MP4M)
-	{
-		SendATCommand(mtpt);
-		printk("SendATCommand\n");
-	}	
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	if (state) {
-		if (mtpt->capabilities & UART_STARTECH) {
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-			serial_outp(mtpt, UART_LCR, 0);
-			serial_outp(mtpt, UART_IER, UART_IERX_SLEEP);
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, 0);
-			serial_outp(mtpt, UART_LCR, 0);
-		}
-
-		if (mtpt->pm)
-			mtpt->pm(port, state, oldstate);
-	} 
-	else 
-	{
-		if (mtpt->capabilities & UART_STARTECH) {
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-			serial_outp(mtpt, UART_LCR, 0);
-			serial_outp(mtpt, UART_IER, 0);
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, 0);
-			serial_outp(mtpt, UART_LCR, 0);
-		}
-
-		if (mtpt->pm)
-			mtpt->pm(port, state, oldstate);
-	}
-}
-
-static void multi_release_std_resource(struct mp_port *mtpt)
-{
-	unsigned int size = 8 << mtpt->port.regshift;
-
-	switch (mtpt->port.iotype) {
-		case UPIO_MEM:
-			if (!mtpt->port.mapbase)
-				break;
-
-			if (mtpt->port.flags & UPF_IOREMAP) {
-				iounmap(mtpt->port.membase);
-				mtpt->port.membase = NULL;
-			}
-
-			release_mem_region(mtpt->port.mapbase, size);
-			break;
-
-		case UPIO_HUB6:
-		case UPIO_PORT:
-			release_region(mtpt->port.iobase,size);
-			break;
-	}
-}
-
-static void multi_release_port(struct sb_uart_port *port)
-{
-}
-
-static int multi_request_port(struct sb_uart_port *port)
-{
-	return 0;
-}
-
-static void multi_config_port(struct sb_uart_port *port, int flags)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	int probeflags = PROBE_ANY;
-
-	if (flags & UART_CONFIG_TYPE)
-		autoconfig(mtpt, probeflags);
-	if (mtpt->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-		autoconfig_irq(mtpt);
-
-	if (mtpt->port.type == PORT_UNKNOWN)
-		multi_release_std_resource(mtpt);
-}
-
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser)
-{
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
-			ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-			ser->type == PORT_STARTECH)
-		return -EINVAL;
-	return 0;
-}
-
-static const char *multi_type(struct sb_uart_port *port)
-{
-	int type = port->type;
-
-	if (type >= ARRAY_SIZE(uart_config))
-		type = 0;
-	return uart_config[type].name;
-}
-
-static struct sb_uart_ops multi_pops = {
-	.tx_empty   = multi_tx_empty,
-	.set_mctrl  = multi_set_mctrl,
-	.get_mctrl  = multi_get_mctrl,
-	.stop_tx    = multi_stop_tx,
-	.start_tx   = multi_start_tx,
-	.stop_rx    = multi_stop_rx,
-	.enable_ms  = multi_enable_ms,
-	.break_ctl  = multi_break_ctl,
-	.startup    = multi_startup,
-	.shutdown   = multi_shutdown,
-	.set_termios    = multi_set_termios,
-	.pm     	= multi_pm,
-	.type       	= multi_type,
-	.release_port   = multi_release_port,
-	.request_port   = multi_request_port,
-	.config_port    = multi_config_port,
-	.verify_port    = multi_verify_port,
-};
-
-static struct uart_driver multi_reg = {
-	.owner          = THIS_MODULE,
-	.driver_name    = "goldel_tulip",
-	.dev_name       = "ttyMP",
-	.major          = SB_TTY_MP_MAJOR,
-	.minor          = 0,
-	.nr             = MAX_MP_PORT, 
-	.cons           = NULL,
-};
-
-static void __init multi_init_ports(void)
-{
-	struct mp_port *mtpt;
-	static int first = 1;
-	int i,j,k;
-	unsigned char osc;
-	unsigned char b_ret = 0;
-	static struct mp_device_t *sbdev; 
-
-	if (!first)
-		return;
-	first = 0;
-
-	mtpt = multi_ports; 
-
-	for (k=0;k<NR_BOARD;k++)
-	{
-		sbdev = &mp_devs[k];
-
-		for (i = 0; i < sbdev->nr_ports; i++, mtpt++) 
-		{
-			mtpt->device 		= sbdev;
-			mtpt->port.iobase   = sbdev->uart_access_addr + 8*i;
-			mtpt->port.irq      = sbdev->irq;
-			if ( ((sbdev->device_id == PCI_DEVICE_ID_MP4)&&(sbdev->revision==0x91)))
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i;
-			else if (sbdev->revision == 0xc0)
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + (i & 0x1);
-			else
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i/8;
-
-			mtpt->option_base_addr = sbdev->option_reg_addr;
-
-			mtpt->poll_type = sbdev->poll_type;
-
-			mtpt->port.uartclk  = BASE_BAUD * 16;
-
-			/* get input clock information */
-			osc = inb(sbdev->option_reg_addr + MP_OPTR_DIR0 + i/8) & 0x0F;
-			if (osc==0x0f)
-				osc = 0;
-			for(j=0;j<osc;j++)
-				mtpt->port.uartclk *= 2;
-			mtpt->port.flags    |= STD_COM_FLAGS | UPF_SHARE_IRQ ;
-			mtpt->port.iotype   = UPIO_PORT;
-			mtpt->port.ops      = &multi_pops;
-
-			if (sbdev->revision == 0xc0)
-			{
-				/* for SB16C1053APCI */
-				b_ret = sb1053a_get_interface(mtpt, i);
-			}
-			else
-			{
-				b_ret = read_option_register(mtpt,(MP_OPTR_IIR0 + i/8));
-				printk("IIR_RET = %x\n",b_ret);
-			}
-
-			/* default to RS232 */
-			mtpt->interface = RS232;
-			if (IIR_RS422 == (b_ret & IIR_TYPE_MASK))
-				mtpt->interface = RS422PTP;
-			if (IIR_RS485 == (b_ret & IIR_TYPE_MASK))
-				mtpt->interface = RS485NE;
-		}
-	}
-}
-
-static void __init multi_register_ports(struct uart_driver *drv)
-{
-	int i;
-
-	multi_init_ports();
-
-	for (i = 0; i < NR_PORTS; i++) {
-		struct mp_port *mtpt = &multi_ports[i];
-
-		mtpt->port.line = i;
-		mtpt->port.ops = &multi_pops;
-		init_timer(&mtpt->timer);
-		mtpt->timer.function = multi_timeout;
-		mp_add_one_port(drv, &mtpt->port);
-	}
-}
-
-/**
- * pci_remap_base - remap BAR value of pci device
- *
- * PARAMETERS
- *  pcidev  - pci_dev structure address
- *  offset  - BAR offset PCI_BASE_ADDRESS_0 ~ PCI_BASE_ADDRESS_4
- *  address - address to be changed BAR value
- *  size	- size of address space 
- *
- * RETURNS
- *  If this function performs successful, it returns 0. Otherwise, It returns -1.
- */
-static int pci_remap_base(struct pci_dev *pcidev, unsigned int offset, 
-		unsigned int address, unsigned int size) 
-{
-#if 0
-	struct resource *root;
-	unsigned index = (offset - 0x10) >> 2;
-#endif
-
-	pci_write_config_dword(pcidev, offset, address);
-#if 0
-	root = pcidev->resource[index].parent;
-	release_resource(&pcidev->resource[index]);
-	address &= ~0x1;
-	pcidev->resource[index].start = address;
-	pcidev->resource[index].end	  = address + size - 1;
-
-	if (request_resource(root, &pcidev->resource[index]) != NULL)
-	{
-		printk(KERN_ERR "pci remap conflict!! 0x%x\n", address);
-		return (-1);
-	}
-#endif
-
-	return (0);
-}
-
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
-{
-	static struct mp_device_t *sbdev = mp_devs;
-	unsigned long addr = 0;
-	int j;
-	struct resource *ret = NULL;
-
-	sbdev->device_id = brd.device_id;
-	pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &(sbdev->revision));
-	sbdev->name = brd.name;
-	sbdev->uart_access_addr = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-
-	/* check revision. The SB16C1053APCI's option i/o address is BAR4 */
-	if (sbdev->revision == 0xc0)
-	{
-		/* SB16C1053APCI */
-		sbdev->option_reg_addr = pcidev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
-	}
-	else
-	{
-		sbdev->option_reg_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-	}
-#if 1	
-	if (sbdev->revision == 0xc0)
-	{
-		outb(0x00, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-		inb(sbdev->option_reg_addr + MP_OPTR_GPOCR);
-		outb(0x83, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-	}
-#endif
-
-	sbdev->irq = pcidev->irq;
-
-	if ((brd.device_id & 0x0800) || !(brd.device_id &0xff00))
-	{
-		sbdev->poll_type = TYPE_INTERRUPT;
-	}
-	else
-	{
-		sbdev->poll_type = TYPE_POLL;
-	}
-
-	/* codes which is specific to each board*/
-	switch(brd.device_id){
-		case PCI_DEVICE_ID_MP1 :
-		case PCIE_DEVICE_ID_MP1 :
-		case PCIE_DEVICE_ID_MP1E :
-		case PCIE_DEVICE_ID_GT_MP1 :
-			sbdev->nr_ports = 1;
-			break;
-		case PCI_DEVICE_ID_MP2 :
-		case PCIE_DEVICE_ID_MP2 :
-		case PCIE_DEVICE_ID_GT_MP2 :
-		case PCIE_DEVICE_ID_MP2B :
-		case PCIE_DEVICE_ID_MP2E :
-			sbdev->nr_ports = 2;
-
-			/* serial base address remap */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-			}
-			break;
-		case PCI_DEVICE_ID_MP4 :
-		case PCI_DEVICE_ID_MP4A :
-		case PCIE_DEVICE_ID_MP4 :
-		case PCI_DEVICE_ID_GT_MP4 :
-		case PCI_DEVICE_ID_GT_MP4A :
-		case PCIE_DEVICE_ID_GT_MP4 :
-		case PCI_DEVICE_ID_MP4M :
-		case PCIE_DEVICE_ID_MP4B :
-			sbdev->nr_ports = 4;
-
-			if(sbdev->revision == 0x91){
-				sbdev->reserved_addr[0] = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-				outb(0x03 , sbdev->reserved_addr[0] + 0x01);
-				outb(0x03 , sbdev->reserved_addr[0] + 0x02);
-				outb(0x01 , sbdev->reserved_addr[0] + 0x20);
-				outb(0x00 , sbdev->reserved_addr[0] + 0x21);
-				request_region(sbdev->reserved_addr[0], 32, sbdev->name);
-				sbdev->uart_access_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-				sbdev->option_reg_addr = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
-			}
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 24, 8);
-			}
-			break;
-		case PCI_DEVICE_ID_MP6 :
-		case PCI_DEVICE_ID_MP6A :
-		case PCI_DEVICE_ID_GT_MP6 :
-		case PCI_DEVICE_ID_GT_MP6A :
-			sbdev->nr_ports = 6;
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 16);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 32, 16);
-			}
-			break;
-		case PCI_DEVICE_ID_MP8 :
-		case PCIE_DEVICE_ID_MP8 :
-		case PCI_DEVICE_ID_GT_MP8 :
-		case PCIE_DEVICE_ID_GT_MP8 :
-		case PCIE_DEVICE_ID_MP8B :
-			sbdev->nr_ports = 8;
-			break;
-		case PCI_DEVICE_ID_MP32 :
-		case PCIE_DEVICE_ID_MP32 :
-		case PCI_DEVICE_ID_GT_MP32 :
-		case PCIE_DEVICE_ID_GT_MP32 :
-			{
-				int portnum_hex=0;
-				portnum_hex = inb(sbdev->option_reg_addr);
-				sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
-			}
-			break;
-#ifdef CONFIG_PARPORT_PC
-		case PCI_DEVICE_ID_MP2S1P :
-			sbdev->nr_ports = 2;
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-			}
-
-			/* add PC compatible parallel port */
-			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-			break;
-		case PCI_DEVICE_ID_MP1P :
-			/* add PC compatible parallel port */
-			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-			break;
-#endif
-	}
-
-	ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
-
-	if (sbdev->revision == 0xc0)
-	{
-		ret = request_region(sbdev->option_reg_addr, 0x40, sbdev->name);
-	}
-	else
-	{
-		ret = request_region(sbdev->option_reg_addr, 0x20, sbdev->name);
-	}
-
-
-	NR_BOARD++;
-	NR_PORTS += sbdev->nr_ports;
-
-	/* Enable PCI interrupt */
-	addr = sbdev->option_reg_addr + MP_OPTR_IMR0;
-	for(j=0; j < (sbdev->nr_ports/8)+1; j++)
-	{
-		if (sbdev->poll_type == TYPE_INTERRUPT)
-		{
-			outb(0xff,addr +j);
-		}
-	}
-	sbdev++;
-
-	return 0;
-}
-
-static int __init multi_init(void)
-{
-	int ret, i;
-	struct pci_dev  *dev = NULL;
-
-	if(fcr_count==0)
-	{
-		for(i=0;i<256;i++)
-		{
-			fcr_arr[i] = 0x01;
-			
-		}
-	}
-	if(deep_count==0)
-	{
-		for(i=0;i<256;i++)
-		{
-			deep[i] = 1;
-			
-		}
-	}
-	if(rtr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        rtr[i] = 0x10;
-                }
-        }
-	if(ttr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        ttr[i] = 0x38;
-                }
-        }
-
-
-printk("MULTI INIT\n");
-	for( i=0; i< mp_nrpcibrds; i++)
-	{
-
-		while( (dev = pci_get_device(mp_pciboards[i].vendor_id, mp_pciboards[i].device_id, dev) ) )
-
-		{
-printk("FOUND~~~\n");
-//	Cent OS bug fix
-//			if (mp_pciboards[i].device_id & 0x0800)
-			{
-				int status;
-	        		pci_disable_device(dev);
-	        		status = pci_enable_device(dev);
-            
-	   		     	if (status != 0)
-        			{ 
-               				printk("Multiport Board Enable Fail !\n\n");
-               				status = -ENXIO;
-                			return status;
-           			}
-			}
-
-			init_mp_dev(dev, mp_pciboards[i]);	
-		}
-	}
-
-	for (i = 0; i < NR_IRQS; i++)
-		spin_lock_init(&irq_lists[i].lock);
-
-	ret = mp_register_driver(&multi_reg);
-
-	if (ret >= 0)
-		multi_register_ports(&multi_reg);
-
-	return ret;
-}
-
-static void __exit multi_exit(void)
-{
-	int i;
-
-	for (i = 0; i < NR_PORTS; i++)
-		mp_remove_one_port(&multi_reg, &multi_ports[i].port);
-
-	mp_unregister_driver(&multi_reg);
-}
-
-module_init(multi_init);
-module_exit(multi_exit);
-
-MODULE_DESCRIPTION("SystemBase Multiport PCI/PCIe CORE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sb105x/sb_pci_mp.h b/drivers/staging/sb105x/sb_pci_mp.h
deleted file mode 100644
index 80ae4ab04603..000000000000
--- a/drivers/staging/sb105x/sb_pci_mp.h
+++ /dev/null
@@ -1,291 +0,0 @@
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/tty_driver.h>
-#include <linux/pci.h>
-#include <linux/circ_buf.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/serial.h>
-#include <linux/interrupt.h>
-
-
-#include <linux/parport.h>
-#include <linux/ctype.h>
-#include <linux/poll.h>
-
-
-#define MP_TERMIOS  ktermios
-
-#include "sb_mp_register.h"
-#include "sb_ser_core.h"
-
-#define DRIVER_VERSION  "1.1"
-#define DRIVER_DATE     "2012/01/05"
-#define DRIVER_AUTHOR  "SYSTEMBASE<tech@sysbas.com>"
-#define DRIVER_DESC  "SystemBase PCI/PCIe Multiport Core"
-
-#define SB_TTY_MP_MAJOR			54
-#define PCI_VENDOR_ID_MULTIPORT		0x14A1
-
-#define PCI_DEVICE_ID_MP1		0x4d01
-#define PCI_DEVICE_ID_MP2		0x4d02
-#define PCI_DEVICE_ID_MP4		0x4d04
-#define PCI_DEVICE_ID_MP4A		0x4d54
-#define PCI_DEVICE_ID_MP6		0x4d06
-#define PCI_DEVICE_ID_MP6A		0x4d56
-#define PCI_DEVICE_ID_MP8		0x4d08
-#define PCI_DEVICE_ID_MP32		0x4d32
-/* Parallel port */
-#define PCI_DEVICE_ID_MP1P		0x4301
-#define PCI_DEVICE_ID_MP2S1P		0x4303
-
-#define PCIE_DEVICE_ID_MP1		0x4501
-#define PCIE_DEVICE_ID_MP2		0x4502
-#define PCIE_DEVICE_ID_MP4		0x4504
-#define PCIE_DEVICE_ID_MP8		0x4508
-#define PCIE_DEVICE_ID_MP32		0x4532
-
-#define PCIE_DEVICE_ID_MP1E		0x4e01
-#define PCIE_DEVICE_ID_MP2E		0x4e02
-#define PCIE_DEVICE_ID_MP2B		0x4b02
-#define PCIE_DEVICE_ID_MP4B		0x4b04
-#define PCIE_DEVICE_ID_MP8B		0x4b08
-
-#define PCI_DEVICE_ID_GT_MP4		0x0004
-#define PCI_DEVICE_ID_GT_MP4A		0x0054
-#define PCI_DEVICE_ID_GT_MP6		0x0006
-#define PCI_DEVICE_ID_GT_MP6A		0x0056
-#define PCI_DEVICE_ID_GT_MP8		0x0008
-#define PCI_DEVICE_ID_GT_MP32		0x0032
-
-#define PCIE_DEVICE_ID_GT_MP1		0x1501
-#define PCIE_DEVICE_ID_GT_MP2		0x1502
-#define PCIE_DEVICE_ID_GT_MP4		0x1504
-#define PCIE_DEVICE_ID_GT_MP8		0x1508
-#define PCIE_DEVICE_ID_GT_MP32		0x1532
-
-#define PCI_DEVICE_ID_MP4M		0x4604  //modem
-
-#define MAX_MP_DEV  8
-#define BD_MAX_PORT 32 	/* Max serial port in one board */
-#define MAX_MP_PORT 256 /* Max serial port in one PC */
-
-#define PORT_16C105XA	3
-#define PORT_16C105X	2
-#define PORT_16C55X		1
-
-#define ENABLE		1
-#define DISABLE		0
-
-/* ioctls */
-#define TIOCGNUMOFPORT		0x545F
-#define TIOCSMULTIECHO		0x5440
-#define TIOCSPTPNOECHO		0x5441
-
-#define TIOCGOPTIONREG		0x5461
-#define TIOCGDISABLEIRQ		0x5462
-#define TIOCGENABLEIRQ		0x5463
-#define TIOCGSOFTRESET		0x5464
-#define TIOCGSOFTRESETR		0x5465
-#define TIOCGREGINFO		0x5466
-#define TIOCGGETLSR		0x5467
-#define TIOCGGETDEVID		0x5468
-#define TIOCGGETBDNO		0x5469
-#define TIOCGGETINTERFACE	0x546A
-#define TIOCGGETREV		0x546B
-#define TIOCGGETNRPORTS		0x546C
-#define TIOCGGETPORTTYPE	0x546D
-#define GETDEEPFIFO		0x54AA
-#define SETDEEPFIFO		0x54AB
-#define SETFCR			0x54BA
-#define SETTTR			0x54B1
-#define SETRTR			0x54B2
-#define GETTTR			0x54B3
-#define GETRTR			0x54B4
-
-/* multi-drop mode related ioctl commands */
-#define TIOCSMULTIDROP		0x5470
-#define TIOCSMDADDR   		0x5471
-#define TIOCGMDADDR   		0x5472
-#define TIOCSENDADDR		0x5473
-
-
-/* serial interface */
-#define RS232		1 
-#define RS422PTP	2
-#define RS422MD		3
-#define RS485NE		4
-#define RS485ECHO	5
-
-#define serial_inp(up, offset)      serial_in(up, offset)
-#define serial_outp(up, offset, value)  serial_out(up, offset, value)
-	
-#define PASS_LIMIT  256
-#define is_real_interrupt(irq)  ((irq) != 0)
-
-#define PROBE_ANY   (~0)
-
-static DEFINE_MUTEX(mp_mutex);
-#define MP_MUTEX_LOCK(x) mutex_lock(&(x)) 
-#define MP_MUTEX_UNLOCK(x) mutex_unlock(&(x)) 
-#define MP_STATE_LOCK(x) mutex_lock(&((x)->mutex)) 
-#define MP_STATE_UNLOCK(x) mutex_unlock(&((x)->mutex)) 
-        
-
-#define UART_LSR_SPECIAL    0x1E
-        
-#define HIGH_BITS_OFFSET        ((sizeof(long)-sizeof(int))*8)
-#define uart_users(state)       ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
-
-
-//#define MP_DEBUG 1
-#undef MP_DEBUG
-
-#ifdef MP_DEBUG
-#define DPRINTK(x...)   printk(x)
-#else
-#define DPRINTK(x...)   do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_AUTOCONF(fmt...)  printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...)  do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_INTR(fmt...)  printk(fmt)
-#else
-#define DEBUG_INTR(fmt...)  do { } while (0)
-#endif
-
-#if defined(__i386__) && defined(CONFIG_M486)
-#define SERIAL_INLINE
-#endif
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
-#define TYPE_POLL	1
-#define TYPE_INTERRUPT	2
-
-
-struct mp_device_t {
-        unsigned short  device_id;
-        unsigned char   revision;
-        char            *name;
-        unsigned long   uart_access_addr;
-        unsigned long   option_reg_addr;
-        unsigned long   reserved_addr[4];
-        int             irq;
-        int             nr_ports;
-        int             poll_type;
-};
-
-typedef struct mppcibrd {
-        char            *name;
-        unsigned short  vendor_id;
-        unsigned short  device_id;
-} mppcibrd_t;
-
-static mppcibrd_t mp_pciboards[] = {
-
-        { "Multi-1 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1} ,
-        { "Multi-2 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4A} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6A} ,
-        { "Multi-8 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP8} ,
-        { "Multi-32 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP32} ,
-
-        { "Multi-1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1P} ,
-        { "Multi-2S1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2S1P} ,
-
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4} ,
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4A} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6A} ,
-        { "Multi-8(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-1 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1} ,
-        { "Multi-2 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2} ,
-        { "Multi-4 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4} ,
-        { "Multi-8 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8} ,
-        { "Multi-32 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP32} ,
-
-        { "Multi-1 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1E} ,
-        { "Multi-2 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2E} ,
-        { "Multi-2 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2B} ,
-        { "Multi-4 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4B} ,
-        { "Multi-8 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8B} ,
-
-        { "Multi-1(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP1} ,
-        { "Multi-2(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP2} ,
-        { "Multi-4(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP4} ,
-        { "Multi-8(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-4M PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4M} ,
-};
-
-struct mp_port {
-        struct sb_uart_port port;
-
-        struct timer_list   timer;      /* "no irq" timer */
-        struct list_head    list;       /* ports on this IRQ */
-        unsigned int        capabilities;   /* port capabilities */
-        unsigned short      rev;
-        unsigned char       acr;
-        unsigned char       ier;
-        unsigned char       lcr;
-        unsigned char       mcr;
-        unsigned char       mcr_mask;   /* mask of user bits */
-        unsigned char       mcr_force;  /* mask of forced bits */
-        unsigned char       lsr_break_flag;
-
-        void            (*pm)(struct sb_uart_port *port,
-                        unsigned int state, unsigned int old);
-        struct mp_device_t *device;
-        unsigned long   interface_config_addr;
-        unsigned long   option_base_addr;
-        unsigned char   interface;
-        unsigned char   poll_type;
-};
-
-struct irq_info {
-        spinlock_t      lock;
-        struct list_head    *head;
-};
-
-struct sb105x_uart_config {
-	char    *name;
-	int     dfl_xmit_fifo_size;
-	int     flags;
-};
-
-static const struct sb105x_uart_config uart_config[] = {
-        { "unknown",    1,  0 },
-        { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
-        { "SB16C1050",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-        { "SB16C1050A",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-};
-
-
-
diff --git a/drivers/staging/sb105x/sb_ser_core.h b/drivers/staging/sb105x/sb_ser_core.h
deleted file mode 100644
index c8fb99173299..000000000000
--- a/drivers/staging/sb105x/sb_ser_core.h
+++ /dev/null
@@ -1,368 +0,0 @@
-#include <linux/wait.h>
-
-#define UART_CONFIG_TYPE	(1 << 0)
-#define UART_CONFIG_IRQ		(1 << 1)
-#define UPIO_PORT		(0)
-#define UPIO_HUB6		(1)
-#define UPIO_MEM		(2)
-#define UPIO_MEM32		(3)
-#define UPIO_AU			(4)			/* Au1x00 type IO */
-#define UPIO_TSI		(5)			/* Tsi108/109 type IO */
-#define UPF_FOURPORT		(1 << 1)
-#define UPF_SAK			(1 << 2)
-#define UPF_SPD_MASK		(0x1030)
-#define UPF_SPD_HI		(0x0010)
-#define UPF_SPD_VHI		(0x0020)
-#define UPF_SPD_CUST		(0x0030)
-#define UPF_SPD_SHI		(0x1000)
-#define UPF_SPD_WARP		(0x1010)
-#define UPF_SKIP_TEST		(1 << 6)
-#define UPF_AUTO_IRQ		(1 << 7)
-#define UPF_HARDPPS_CD		(1 << 11)
-#define UPF_LOW_LATENCY		(1 << 13)
-#define UPF_BUGGY_UART		(1 << 14)
-#define UPF_MAGIC_MULTIPLIER	(1 << 16)
-#define UPF_CONS_FLOW		(1 << 23)
-#define UPF_SHARE_IRQ		(1 << 24)
-#define UPF_BOOT_AUTOCONF	(1 << 28)
-#define UPF_DEAD		(1 << 30)
-#define UPF_IOREMAP		(1 << 31)
-#define UPF_CHANGE_MASK		(0x17fff)
-#define UPF_USR_MASK		(UPF_SPD_MASK|UPF_LOW_LATENCY)
-#define USF_CLOSING_WAIT_INF	(0)
-#define USF_CLOSING_WAIT_NONE	(~0U)
-
-#define UART_XMIT_SIZE	PAGE_SIZE
-
-#define UIF_CHECK_CD		(1 << 25)
-#define UIF_CTS_FLOW		(1 << 26)
-#define UIF_NORMAL_ACTIVE	(1 << 29)
-#define UIF_INITIALIZED		(1 << 31)
-#define UIF_SUSPENDED		(1 << 30)
-
-#define WAKEUP_CHARS		256
-
-#define uart_circ_empty(circ)		((circ)->head == (circ)->tail)
-#define uart_circ_clear(circ)		((circ)->head = (circ)->tail = 0)
-
-#define uart_circ_chars_pending(circ)	\
-	(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_circ_chars_free(circ)	\
-	(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_tx_stopped(port)		\
-	((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
-
-#define UART_ENABLE_MS(port,cflag)	((port)->flags & UPF_HARDPPS_CD || \
-					 (cflag) & CRTSCTS || \
-					 !((cflag) & CLOCAL))
-
-
-struct sb_uart_port;
-struct sb_uart_info;
-struct serial_struct;
-struct device;
-
-struct sb_uart_ops {
-	unsigned int	(*tx_empty)(struct sb_uart_port *);
-	void		(*set_mctrl)(struct sb_uart_port *, unsigned int mctrl);
-	unsigned int	(*get_mctrl)(struct sb_uart_port *);
-	void		(*stop_tx)(struct sb_uart_port *);
-	void		(*start_tx)(struct sb_uart_port *);
-	void		(*send_xchar)(struct sb_uart_port *, char ch);
-	void		(*stop_rx)(struct sb_uart_port *);
-	void		(*enable_ms)(struct sb_uart_port *);
-	void		(*break_ctl)(struct sb_uart_port *, int ctl);
-	int		(*startup)(struct sb_uart_port *);
-	void		(*shutdown)(struct sb_uart_port *);
-	void		(*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new,
-				       struct MP_TERMIOS *old);
-	void		(*pm)(struct sb_uart_port *, unsigned int state,
-			      unsigned int oldstate);
-	int		(*set_wake)(struct sb_uart_port *, unsigned int state);
-
-	const char *(*type)(struct sb_uart_port *);
-
-	void		(*release_port)(struct sb_uart_port *);
-
-	int		(*request_port)(struct sb_uart_port *);
-	void		(*config_port)(struct sb_uart_port *, int);
-	int		(*verify_port)(struct sb_uart_port *, struct serial_struct *);
-	int		(*ioctl)(struct sb_uart_port *, unsigned int, unsigned long);
-};
-
-
-struct sb_uart_icount {
-	__u32	cts;
-	__u32	dsr;
-	__u32	rng;
-	__u32	dcd;
-	__u32	rx;
-	__u32	tx;
-	__u32	frame;
-	__u32	overrun;
-	__u32	parity;
-	__u32	brk;
-	__u32	buf_overrun;
-};
-typedef unsigned int  upf_t;
-
-struct sb_uart_port {
-	spinlock_t		lock;			/* port lock */
-	unsigned int		iobase;			/* in/out[bwl] */
-	unsigned char __iomem	*membase;		/* read/write[bwl] */
-	unsigned int		irq;			/* irq number */
-	unsigned int		uartclk;		/* base uart clock */
-	unsigned int		fifosize;		/* tx fifo size */
-	unsigned char		x_char;			/* xon/xoff char */
-	unsigned char		regshift;		/* reg offset shift */
-	unsigned char		iotype;			/* io access style */
-	unsigned char		unused1;
-
-
-	unsigned int		read_status_mask;	/* driver specific */
-	unsigned int		ignore_status_mask;	/* driver specific */
-	struct sb_uart_info	*info;			/* pointer to parent info */
-	struct sb_uart_icount	icount;			/* statistics */
-
-	struct console		*cons;			/* struct console, if any */
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	unsigned long		sysrq;			/* sysrq timeout */
-#endif
-
-	upf_t			flags;
-
-	unsigned int		mctrl;			/* current modem ctrl settings */
-	unsigned int		timeout;		/* character-based timeout */
-	unsigned int		type;			/* port type */
-	const struct sb_uart_ops	*ops;
-	unsigned int		custom_divisor;
-	unsigned int		line;			/* port index */
-	unsigned long		mapbase;		/* for ioremap */
-	struct device		*dev;			/* parent device */
-	unsigned char		hub6;			/* this should be in the 8250 driver */
-	unsigned char		unused[3];
-};
-
-#define mdmode			unused[2]
-#define MDMODE_ADDR		0x1
-#define MDMODE_ENABLE	0x2
-#define MDMODE_AUTO		0x4
-#define MDMODE_ADDRSEND	0x8
-
-struct sb_uart_state {
-	unsigned int		close_delay;		/* msec */
-	unsigned int		closing_wait;		/* msec */
-
-
-	int			count;
-	int			pm_state;
-	struct sb_uart_info	*info;
-	struct sb_uart_port	*port;
-
-	struct mutex		mutex;
-};
-
-typedef unsigned int  uif_t;
-
-struct sb_uart_info {
-	struct tty_struct	*tty;
-	struct circ_buf		xmit;
-	uif_t			flags;
-
-	int			blocked_open;
-
-	struct tasklet_struct	tlet;
-
-	wait_queue_head_t	open_wait;
-	wait_queue_head_t	delta_msr_wait;
-};
-
-
-struct module;
-struct tty_driver;
-
-struct uart_driver {
-	struct module		*owner;
-	const char		*driver_name;
-	const char		*dev_name;
-	int			 major;
-	int			 minor;
-	int			 nr;
-	struct console		*cons;
-
-	struct sb_uart_state	*state;
-        struct tty_driver               *tty_driver;
-};
-
-void sb_uart_write_wakeup(struct sb_uart_port *port)
-{
-    struct sb_uart_info *info = port->info;
-    tasklet_schedule(&info->tlet);
-}
-
-void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag,
-			 unsigned int baud)
-{
-    unsigned int bits;
-
-    switch (cflag & CSIZE)
-    {
-        case CS5:
-            bits = 7;
-            break;
-
-        case CS6:
-            bits = 8;
-            break;
-
-        case CS7:
-            bits = 9;
-            break;
-
-        default:
-            bits = 10;
-            break;
-    }
-
-    if (cflag & CSTOPB)
-    {
-        bits++;
-    }
-
-    if (cflag & PARENB)
-    {
-        bits++;
-    }
-
-    bits = bits * port->fifosize;
-
-    port->timeout = (HZ * bits) / baud + HZ/50;
-}
-unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios,
-				struct MP_TERMIOS *old, unsigned int min,
-				unsigned int max)
-{
-        unsigned int try, baud, altbaud = 38400;
-        upf_t flags = port->flags & UPF_SPD_MASK;
-
-        if (flags == UPF_SPD_HI)
-                altbaud = 57600;
-        if (flags == UPF_SPD_VHI)
-                altbaud = 115200;
-        if (flags == UPF_SPD_SHI)
-                altbaud = 230400;
-        if (flags == UPF_SPD_WARP)
-                altbaud = 460800;
-
-        for (try = 0; try < 2; try++) {
-
-                switch (termios->c_cflag & (CBAUD | CBAUDEX))
-                {
-                	case B921600    : baud = 921600;    break;
-                	case B460800    : baud = 460800;    break;
-                	case B230400    : baud = 230400;    break;
-                	case B115200    : baud = 115200;    break;
-                	case B57600     : baud = 57600;     break;
-                	case B38400     : baud = 38400;     break;
-                	case B19200     : baud = 19200;     break;
-                	case B9600      : baud = 9600;      break;
-                	case B4800      : baud = 4800;      break;
-                	case B2400      : baud = 2400;      break;
-                	case B1800      : baud = 1800;      break;
-                	case B1200      : baud = 1200;      break;
-                	case B600       : baud = 600;       break;
-                	case B300       : baud = 300;       break;
-                        case B200       : baud = 200;       break;
-                	case B150       : baud = 150;       break;
-                	case B134       : baud = 134;       break;
-                	case B110       : baud = 110;       break;
-                	case B75        : baud = 75;        break;
-                	case B50        : baud = 50;        break;
-                	default         : baud = 9600;      break;
-                }
-
-                if (baud == 38400)
-                        baud = altbaud;
-
-                if (baud == 0)
-                        baud = 9600;
-
-                if (baud >= min && baud <= max)
-                        return baud;
-
-                termios->c_cflag &= ~CBAUD;
-                if (old) {
-                        termios->c_cflag |= old->c_cflag & CBAUD;
-                        old = NULL;
-                        continue;
-                }
-
-                termios->c_cflag |= B9600;
-        }
-
-        return 0;
-}
-unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-        unsigned int quot;
-
-        if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
-                quot = port->custom_divisor;
-        else
-                quot = (port->uartclk + (8 * baud)) / (16 * baud);
-
-        return quot;
-}
-
-
-
-static inline int sb_uart_handle_break(struct sb_uart_port *port)
-{
-	struct sb_uart_info *info = port->info;
-
-	if (port->flags & UPF_SAK)
-		do_SAK(info->tty);
-	return 0;
-}
-
-static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status)
-{
-	struct sb_uart_info *info = port->info;
-
-	port->icount.dcd++;
-
-	if (info->flags & UIF_CHECK_CD) {
-		if (status)
-			wake_up_interruptible(&info->open_wait);
-		else if (info->tty)
-			tty_hangup(info->tty);
-	}
-}
-
-static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status)
-{
-	struct sb_uart_info *info = port->info;
-	struct tty_struct *tty = info->tty;
-
-	port->icount.cts++;
-
-	if (info->flags & UIF_CTS_FLOW) {
-		if (tty->hw_stopped) {
-			if (status) {
-				tty->hw_stopped = 0;
-				port->ops->start_tx(port);
-				sb_uart_write_wakeup(port);
-			}
-		} else {
-			if (!status) {
-				tty->hw_stopped = 1;
-				port->ops->stop_tx(port);
-			}
-		}
-	}
-}
-
-
-
diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c
index 0e32be5c2471..a6f93a43d216 100644
--- a/drivers/staging/sbe-2t3e3/module.c
+++ b/drivers/staging/sbe-2t3e3/module.c
@@ -122,7 +122,7 @@ static void t3e3_remove_card(struct pci_dev *pdev)
 	struct channel *channel0 = pci_get_drvdata(pdev);
 	struct card *card = channel0->card;
 
-	del_timer(&card->timer);
+	del_timer_sync(&card->timer);
 	if (has_two_ports(channel0->pdev)) {
 		t3e3_remove_channel(&card->channels[1]);
 		pci_dev_put(card->channels[1].pdev);
diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c
index 7fc267550c65..965485f71fe9 100644
--- a/drivers/staging/sep/sep_crypto.c
+++ b/drivers/staging/sep/sep_crypto.c
@@ -112,7 +112,7 @@ static void sep_do_callback(struct work_struct *work)
  *	on what operation is to be done
  */
 static int sep_submit_work(struct workqueue_struct *work_queue,
-	void(*funct)(void *),
+	void (*funct)(void *),
 	void *data)
 {
 	struct sep_work_struct *sep_work;
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index 122614c4092b..cbfc0cffb1d8 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -1266,9 +1266,8 @@ static int sep_lock_user_pages(struct sep_device *sep,
 	/* Check the number of pages locked - if not all then exit with error */
 	if (result != num_pages) {
 		dev_warn(&sep->pdev->dev,
-			"[PID%d] not all pages locked by get_user_pages, "
-			"result 0x%X, num_pages 0x%X\n",
-				current->pid, result, num_pages);
+			"[PID%d] not all pages locked by get_user_pages, result 0x%X, num_pages 0x%X\n",
+			current->pid, result, num_pages);
 		error = -ENOMEM;
 		goto end_function_with_error3;
 	}
@@ -1293,9 +1292,9 @@ static int sep_lock_user_pages(struct sep_device *sep,
 		lli_array[count].block_size = PAGE_SIZE;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n", current->pid,
-			count, (unsigned long)lli_array[count].bus_address,
+			"[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
+			current->pid, count,
+			(unsigned long)lli_array[count].bus_address,
 			count, lli_array[count].block_size);
 	}
 
@@ -1314,8 +1313,7 @@ static int sep_lock_user_pages(struct sep_device *sep,
 			"[PID%d] After check if page 0 has all data\n",
 			current->pid);
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[0].bus_address is (hex) %08lx, "
-			"lli_array[0].block_size is (hex) %x\n",
+			"[PID%d] lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
 			current->pid,
 			(unsigned long)lli_array[0].bus_address,
 			lli_array[0].block_size);
@@ -1332,8 +1330,7 @@ static int sep_lock_user_pages(struct sep_device *sep,
 			"[PID%d] After last page size adjustment\n",
 			current->pid);
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is (hex) %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"[PID%d] lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid,
 			num_pages - 1,
 			(unsigned long)lli_array[num_pages - 1].bus_address,
@@ -1449,8 +1446,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
 		start_page += PAGE_SIZE;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid,
 			count, (unsigned long)lli_array[count].bus_address,
 			count, lli_array[count].block_size);
@@ -1469,8 +1465,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
 
 	dev_dbg(&sep->pdev->dev,
 		"[PID%d] After check if page 0 has all data\n"
-		"lli_array[0].bus_address is (hex) %08lx, "
-		"lli_array[0].block_size is (hex) %x\n",
+		"lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
 		current->pid,
 		(unsigned long)lli_array[0].bus_address,
 		lli_array[0].block_size);
@@ -1484,8 +1479,7 @@ static int sep_lli_table_secure_dma(struct sep_device *sep,
 
 		dev_dbg(&sep->pdev->dev,
 			"[PID%d] After last page size adjustment\n"
-			"lli_array[%x].bus_address is (hex) %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid, num_pages - 1,
 			(unsigned long)lli_array[num_pages - 1].bus_address,
 			num_pages - 1,
@@ -1745,9 +1739,8 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
 
 	while ((unsigned long) lli_table_ptr->bus_address != 0xffffffff) {
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli table %08lx, "
-			"table_data_size is (hex) %lx\n",
-				current->pid, table_count, table_data_size);
+			"[PID%d] lli table %08lx, table_data_size is (hex) %lx\n",
+			current->pid, table_count, table_data_size);
 		dev_dbg(&sep->pdev->dev,
 			"[PID%d] num_table_entries is (hex) %lx\n",
 				current->pid, num_table_entries);
@@ -1762,8 +1755,8 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
 				(unsigned long) lli_table_ptr);
 
 			dev_dbg(&sep->pdev->dev,
-				"[PID%d] phys address is %08lx "
-				"block size is (hex) %x\n", current->pid,
+				"[PID%d] phys address is %08lx block size is (hex) %x\n",
+				current->pid,
 				(unsigned long)lli_table_ptr->bus_address,
 				lli_table_ptr->block_size);
 		}
@@ -1772,14 +1765,12 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
 		lli_table_ptr--;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys lli_table_ptr->block_size "
-			"is (hex) %x\n",
+			"[PID%d] phys lli_table_ptr->block_size is (hex) %x\n",
 			current->pid,
 			lli_table_ptr->block_size);
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys lli_table_ptr->physical_address "
-			"is %08lx\n",
+			"[PID%d] phys lli_table_ptr->physical_address is %08lx\n",
 			current->pid,
 			(unsigned long)lli_table_ptr->bus_address);
 
@@ -1788,13 +1779,11 @@ static void sep_debug_print_lli_tables(struct sep_device *sep,
 		num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys table_data_size is "
-			"(hex) %lx num_table_entries is"
-			" %lx bus_address is%lx\n",
-				current->pid,
-				table_data_size,
-				num_table_entries,
-				(unsigned long)lli_table_ptr->bus_address);
+			"[PID%d] phys table_data_size is (hex) %lx num_table_entries is %lx bus_address is%lx\n",
+			current->pid,
+			table_data_size,
+			num_table_entries,
+			(unsigned long)lli_table_ptr->bus_address);
 
 		if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff)
 			lli_table_ptr = (struct sep_lli_entry *)
@@ -2244,14 +2233,12 @@ static int sep_construct_dma_tables_from_lli(
 			table_data_size = out_table_data_size;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] construct tables from lli"
-			" in_table_data_size is (hex) %x\n", current->pid,
-			in_table_data_size);
+			"[PID%d] construct tables from lli in_table_data_size is (hex) %x\n",
+			current->pid, in_table_data_size);
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] construct tables from lli"
-			"out_table_data_size is (hex) %x\n", current->pid,
-			out_table_data_size);
+			"[PID%d] construct tables from lli out_table_data_size is (hex) %x\n",
+			current->pid, out_table_data_size);
 
 		/* Construct input lli table */
 		sep_build_lli_table(sep, &lli_in_array[current_in_entry],
@@ -2316,8 +2303,7 @@ static int sep_construct_dma_tables_from_lli(
 				info_in_entry_ptr->block_size);
 
 			dev_dbg(&sep->pdev->dev,
-				"[PID%d] output lli_table_out_ptr:"
-				"%08lx  %08x\n",
+				"[PID%d] output lli_table_out_ptr: %08lx  %08x\n",
 				current->pid,
 				(unsigned long)info_out_entry_ptr->bus_address,
 				info_out_entry_ptr->block_size);
@@ -2446,8 +2432,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 				dma_ctx);
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_kernel_pages for input "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_kernel_pages for input virtual buffer failed\n",
+				current->pid);
 
 			goto end_function;
 		}
@@ -2460,8 +2446,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_kernel_pages for output "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_kernel_pages for output virtual buffer failed\n",
+				current->pid);
 
 			goto end_function_free_lli_in;
 		}
@@ -2476,8 +2462,8 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 				dma_ctx);
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_user_pages for input "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_user_pages for input virtual buffer failed\n",
+				current->pid);
 
 			goto end_function;
 		}
@@ -2491,8 +2477,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 				SEP_DRIVER_OUT_FLAG, dma_ctx);
 			if (error) {
 				dev_warn(&sep->pdev->dev,
-					"[PID%d] secure dma table setup "
-					" for output virtual buffer failed\n",
+					"[PID%d] secure dma table setup for output virtual buffer failed\n",
 					current->pid);
 
 				goto end_function_free_lli_in;
@@ -2512,8 +2497,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 
 			if (error) {
 				dev_warn(&sep->pdev->dev,
-					"[PID%d] sep_lock_user_pages"
-					" for output virtual buffer failed\n",
+					"[PID%d] sep_lock_user_pages for output virtual buffer failed\n",
 					current->pid);
 
 				goto end_function_free_lli_in;
@@ -2826,8 +2810,7 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 
 	if (error) {
 		dev_warn(&sep->pdev->dev,
-			"prepare DMA table call failed "
-			"from prepare DCB call\n");
+			"prepare DMA table call failed from prepare DCB call\n");
 		goto end_function_error;
 	}
 
@@ -2889,7 +2872,8 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
 		 * Go over each DCB and see if
 		 * tail pointer must be updated
 		 */
-		for (i = 0; i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) {
+		for (i = 0; i < (*dma_ctx)->nr_dcb_creat;
+		     i++, dcb_table_ptr++) {
 			if (dcb_table_ptr->out_vr_tail_pt) {
 				pt_hold = (unsigned long)dcb_table_ptr->
 					out_vr_tail_pt;
@@ -3762,8 +3746,7 @@ static inline ssize_t sep_fastcall_args_get(struct sep_device *sep,
 
 	if (actual_count != count_user) {
 		dev_warn(&sep->pdev->dev,
-			 "[PID%d] inconsistent message "
-			 "sizes 0x%08zX vs 0x%08zX\n",
+			 "[PID%d] inconsistent message sizes 0x%08zX vs 0x%08zX\n",
 			 current->pid, actual_count, count_user);
 		error = -EMSGSIZE;
 		goto end_function;
diff --git a/drivers/staging/silicom/bp_mod.h b/drivers/staging/silicom/bp_mod.h
index 8154a7bf050f..9999e6eb03a4 100644
--- a/drivers/staging/silicom/bp_mod.h
+++ b/drivers/staging/silicom/bp_mod.h
@@ -698,5 +698,3 @@ static inline unsigned int jiffies_to_msecs(const unsigned long j)
 	readl((void *)((a)->mem_map) + BP10GB_##reg))
 
 #endif
-
-int bp_proc_create(void);
diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c
index 20325f53328e..f4aea92133c8 100644
--- a/drivers/staging/silicom/bpctl_mod.c
+++ b/drivers/staging/silicom/bpctl_mod.c
@@ -117,12 +117,12 @@ static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left);
 static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev);
 static void if_scan_init(void);
 
-int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block);
-int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block);
-int bp_proc_create(void);
+static int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block);
+static int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block);
+static int bp_proc_create(void);
 
-int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
-int get_dev_idx_bsf(int bus, int slot, int func);
+static int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
+static int get_dev_idx_bsf(int bus, int slot, int func);
 
 static int bp_get_dev_idx_bsf(struct net_device *dev, int *index)
 {
@@ -262,7 +262,7 @@ static struct notifier_block bp_notifier_block = {
 	.notifier_call = bp_device_event,
 };
 
-int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
+static int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
 int wdt_time_left(struct bpctl_dev *pbpctl_dev);
 
 static void write_pulse(struct bpctl_dev *pbpctl_dev,
@@ -1502,7 +1502,8 @@ static int send_wdt_pulse(struct bpctl_dev *pbpctl_dev)
 	return 0;
 }
 
-void send_bypass_clear_pulse(struct bpctl_dev *pbpctl_dev, unsigned int value)
+static void send_bypass_clear_pulse(struct bpctl_dev *pbpctl_dev,
+				    unsigned int value)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1757,7 +1758,7 @@ static int wdt_pulse_int(struct bpctl_dev *pbpctl_dev)
 /*************************************/
 
 /* CMND_ON  0x4 (100)*/
-int cmnd_on(struct bpctl_dev *pbpctl_dev)
+static int cmnd_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1774,7 +1775,7 @@ int cmnd_on(struct bpctl_dev *pbpctl_dev)
 }
 
 /* CMND_OFF  0x2 (10)*/
-int cmnd_off(struct bpctl_dev *pbpctl_dev)
+static int cmnd_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1792,7 +1793,7 @@ int cmnd_off(struct bpctl_dev *pbpctl_dev)
 }
 
 /* BYPASS_ON (0xa)*/
-int bypass_on(struct bpctl_dev *pbpctl_dev)
+static int bypass_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1813,7 +1814,7 @@ int bypass_on(struct bpctl_dev *pbpctl_dev)
 }
 
 /* BYPASS_OFF (0x8 111)*/
-int bypass_off(struct bpctl_dev *pbpctl_dev)
+static int bypass_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1836,7 +1837,7 @@ int bypass_off(struct bpctl_dev *pbpctl_dev)
 }
 
 /* TAP_OFF (0x9)*/
-int tap_off(struct bpctl_dev *pbpctl_dev)
+static int tap_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if ((pbpctl_dev->bp_caps & TAP_CAP)
@@ -1849,7 +1850,7 @@ int tap_off(struct bpctl_dev *pbpctl_dev)
 }
 
 /* TAP_ON (0xb)*/
-int tap_on(struct bpctl_dev *pbpctl_dev)
+static int tap_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if ((pbpctl_dev->bp_caps & TAP_CAP)
@@ -1862,7 +1863,7 @@ int tap_on(struct bpctl_dev *pbpctl_dev)
 }
 
 /* DISC_OFF (0x9)*/
-int disc_off(struct bpctl_dev *pbpctl_dev)
+static int disc_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
@@ -1874,7 +1875,7 @@ int disc_off(struct bpctl_dev *pbpctl_dev)
 }
 
 /* DISC_ON (0xb)*/
-int disc_on(struct bpctl_dev *pbpctl_dev)
+static int disc_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
@@ -1885,58 +1886,8 @@ int disc_on(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-/* DISC_PORT_ON */
-int disc_port_on(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	struct bpctl_dev *pbpctl_dev_m;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1)
-			write_data(pbpctl_dev_m, TX_DISA);
-		else
-			write_data(pbpctl_dev_m, TX_DISB);
-
-		msec_delay_bp(LATCH_DELAY);
-
-	}
-	return ret;
-}
-
-/* DISC_PORT_OFF */
-int disc_port_off(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	struct bpctl_dev *pbpctl_dev_m;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1)
-			write_data(pbpctl_dev_m, TX_ENA);
-		else
-			write_data(pbpctl_dev_m, TX_ENB);
-
-		msec_delay_bp(LATCH_DELAY);
-
-	}
-	return ret;
-}
-
 /*TWO_PORT_LINK_HW_EN (0xe)*/
-int tpl_hw_on(struct bpctl_dev *pbpctl_dev)
+static int tpl_hw_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0, ctrl = 0;
 	struct bpctl_dev *pbpctl_dev_b = NULL;
@@ -1964,7 +1915,7 @@ int tpl_hw_on(struct bpctl_dev *pbpctl_dev)
 }
 
 /*TWO_PORT_LINK_HW_DIS (0xc)*/
-int tpl_hw_off(struct bpctl_dev *pbpctl_dev)
+static int tpl_hw_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0, ctrl = 0;
 	struct bpctl_dev *pbpctl_dev_b = NULL;
@@ -1990,7 +1941,7 @@ int tpl_hw_off(struct bpctl_dev *pbpctl_dev)
 }
 
 /* WDT_OFF (0x6 110)*/
-int wdt_off(struct bpctl_dev *pbpctl_dev)
+static int wdt_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -2013,7 +1964,7 @@ int wdt_off(struct bpctl_dev *pbpctl_dev)
 static unsigned int
     wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 };
 
-int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout)
+static int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout)
 {
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -2065,7 +2016,7 @@ int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout)
 	return BP_NOT_CAP;
 }
 
-void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
+static void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
 {
 	u32 swsm;
 
@@ -2076,7 +2027,7 @@ void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
 	BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm);
 }
 
-s32 bp75_get_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
+static s32 bp75_get_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
 {
 	u32 swsm;
 	s32 ret_val = 0;
@@ -2190,7 +2141,8 @@ static s32 bp75_acquire_phy(struct bpctl_dev *pbpctl_dev)
 	return ret_val;
 }
 
-s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data)
+static s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset,
+				  u16 *data)
 {
 	u32 i, mdic = 0;
 	s32 ret_val = 0;
@@ -2223,7 +2175,8 @@ s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data)
 	return ret_val;
 }
 
-s32 bp75_write_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data)
+static s32 bp75_write_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset,
+				   u16 data)
 {
 	u32 i, mdic = 0;
 	s32 ret_val = 0;
@@ -2534,7 +2487,7 @@ static int set_bp_force_link(struct bpctl_dev *pbpctl_dev, int tx_state)
 }
 
 /*RESET_CONT 0x20 */
-int reset_cont(struct bpctl_dev *pbpctl_dev)
+static int reset_cont(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -2551,7 +2504,7 @@ int reset_cont(struct bpctl_dev *pbpctl_dev)
 }
 
 /*DIS_BYPASS_CAP 0x22 */
-int dis_bypass_cap(struct bpctl_dev *pbpctl_dev)
+static int dis_bypass_cap(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
@@ -2570,7 +2523,7 @@ int dis_bypass_cap(struct bpctl_dev *pbpctl_dev)
 }
 
 /*EN_BYPASS_CAP 0x24 */
-int en_bypass_cap(struct bpctl_dev *pbpctl_dev)
+static int en_bypass_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
 		if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
@@ -2586,7 +2539,7 @@ int en_bypass_cap(struct bpctl_dev *pbpctl_dev)
 }
 
 /* BYPASS_STATE_PWRON 0x26*/
-int bypass_state_pwron(struct bpctl_dev *pbpctl_dev)
+static int bypass_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) {
 		write_data(pbpctl_dev, BYPASS_STATE_PWRON);
@@ -2600,7 +2553,7 @@ int bypass_state_pwron(struct bpctl_dev *pbpctl_dev)
 }
 
 /* NORMAL_STATE_PWRON 0x28*/
-int normal_state_pwron(struct bpctl_dev *pbpctl_dev)
+static int normal_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP)
 	    || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) {
@@ -2615,7 +2568,7 @@ int normal_state_pwron(struct bpctl_dev *pbpctl_dev)
 }
 
 /* BYPASS_STATE_PWROFF 0x27*/
-int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev)
+static int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) {
 		write_data(pbpctl_dev, BYPASS_STATE_PWROFF);
@@ -2626,7 +2579,7 @@ int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev)
 }
 
 /* NORMAL_STATE_PWROFF 0x29*/
-int normal_state_pwroff(struct bpctl_dev *pbpctl_dev)
+static int normal_state_pwroff(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) {
 		write_data(pbpctl_dev, NORMAL_STATE_PWROFF);
@@ -2637,7 +2590,7 @@ int normal_state_pwroff(struct bpctl_dev *pbpctl_dev)
 }
 
 /*TAP_STATE_PWRON 0x2a*/
-int tap_state_pwron(struct bpctl_dev *pbpctl_dev)
+static int tap_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		write_data(pbpctl_dev, TAP_STATE_PWRON);
@@ -2648,7 +2601,7 @@ int tap_state_pwron(struct bpctl_dev *pbpctl_dev)
 }
 
 /*DIS_TAP_CAP 0x2c*/
-int dis_tap_cap(struct bpctl_dev *pbpctl_dev)
+static int dis_tap_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
 		write_data(pbpctl_dev, DIS_TAP_CAP);
@@ -2659,7 +2612,7 @@ int dis_tap_cap(struct bpctl_dev *pbpctl_dev)
 }
 
 /*EN_TAP_CAP 0x2e*/
-int en_tap_cap(struct bpctl_dev *pbpctl_dev)
+static int en_tap_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
 		write_data(pbpctl_dev, EN_TAP_CAP);
@@ -2670,7 +2623,7 @@ int en_tap_cap(struct bpctl_dev *pbpctl_dev)
 }
 
 /*DISC_STATE_PWRON 0x2a*/
-int disc_state_pwron(struct bpctl_dev *pbpctl_dev)
+static int disc_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2683,7 +2636,7 @@ int disc_state_pwron(struct bpctl_dev *pbpctl_dev)
 }
 
 /*DIS_DISC_CAP 0x2c*/
-int dis_disc_cap(struct bpctl_dev *pbpctl_dev)
+static int dis_disc_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2695,60 +2648,8 @@ int dis_disc_cap(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-/*DISC_STATE_PWRON 0x2a*/
-int disc_port_state_pwron(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	struct bpctl_dev *pbpctl_dev_m;
-
-	return BP_NOT_CAP;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1)
-			write_data(pbpctl_dev_m, TX_DISA_PWRUP);
-		else
-			write_data(pbpctl_dev_m, TX_DISB_PWRUP);
-
-		msec_delay_bp(LATCH_DELAY);
-
-	}
-	return ret;
-}
-
-int normal_port_state_pwron(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	struct bpctl_dev *pbpctl_dev_m;
-	return BP_NOT_CAP;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1)
-			write_data(pbpctl_dev_m, TX_ENA_PWRUP);
-		else
-			write_data(pbpctl_dev_m, TX_ENB_PWRUP);
-
-		msec_delay_bp(LATCH_DELAY);
-
-	}
-	return ret;
-}
-
 /*EN_TAP_CAP 0x2e*/
-int en_disc_cap(struct bpctl_dev *pbpctl_dev)
+static int en_disc_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2760,7 +2661,7 @@ int en_disc_cap(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int std_nic_on(struct bpctl_dev *pbpctl_dev)
+static int std_nic_on(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
@@ -2814,7 +2715,7 @@ int std_nic_on(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int std_nic_off(struct bpctl_dev *pbpctl_dev)
+static int std_nic_off(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
@@ -2977,7 +2878,7 @@ static void wd_reset_timer(unsigned long param)
 }
 
 /*WAIT_AT_PWRUP 0x80   */
-int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev)
+static int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -2992,7 +2893,7 @@ int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev)
 }
 
 /*DIS_WAIT_AT_PWRUP       0x81 */
-int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev)
+static int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3009,7 +2910,7 @@ int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev)
 
 /*EN_HW_RESET  0x82   */
 
-int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev)
+static int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3025,7 +2926,7 @@ int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev)
 
 /*DIS_HW_RESET             0x83   */
 
-int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev)
+static int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3040,7 +2941,7 @@ int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev)
 }
 
 
-int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode)
+static int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode)
 {
 	uint32_t status_reg = 0, status_reg1 = 0;
 
@@ -3091,7 +2992,7 @@ int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode)
 	return BP_NOT_CAP;
 }
 
-int bypass_fw_ver(struct bpctl_dev *pbpctl_dev)
+static int bypass_fw_ver(struct bpctl_dev *pbpctl_dev)
 {
 	if (is_bypass_fn(pbpctl_dev))
 		return read_reg(pbpctl_dev, VER_REG_ADDR);
@@ -3099,7 +3000,7 @@ int bypass_fw_ver(struct bpctl_dev *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_sign_check(struct bpctl_dev *pbpctl_dev)
+static int bypass_sign_check(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (is_bypass_fn(pbpctl_dev))
@@ -3210,7 +3111,7 @@ static int bp_force_link_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_from_last_read(struct bpctl_dev *pbpctl_dev)
+static int bypass_from_last_read(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 	struct bpctl_dev *pbpctl_dev_b = NULL;
@@ -3230,7 +3131,7 @@ int bypass_from_last_read(struct bpctl_dev *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_status_clear(struct bpctl_dev *pbpctl_dev)
+static int bypass_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 	struct bpctl_dev *pbpctl_dev_b = NULL;
 
@@ -3244,7 +3145,7 @@ int bypass_status_clear(struct bpctl_dev *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_flag_status(struct bpctl_dev *pbpctl_dev)
+static int bypass_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if ((pbpctl_dev->bp_caps & BP_CAP)) {
@@ -3257,7 +3158,7 @@ int bypass_flag_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev)
+static int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_CAP) {
@@ -3272,7 +3173,7 @@ int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_change_status(struct bpctl_dev *pbpctl_dev)
+static int bypass_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -3291,18 +3192,6 @@ int bypass_change_status(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int bypass_off_status(struct bpctl_dev *pbpctl_dev)
-{
-
-	if (pbpctl_dev->bp_caps & BP_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
-			return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
-				  BYPASS_OFF_MASK) == BYPASS_OFF_MASK) ? 1 : 0);
-		}
-	}
-	return BP_NOT_CAP;
-}
-
 static int bypass_status(struct bpctl_dev *pbpctl_dev)
 {
 	u32 ctrl_ext = 0;
@@ -3386,7 +3275,7 @@ static int bypass_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_status(struct bpctl_dev *pbpctl_dev)
+static int default_pwron_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3418,7 +3307,7 @@ static int default_pwroff_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev)
+static int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
@@ -3431,31 +3320,7 @@ int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int cmd_en_status(struct bpctl_dev *pbpctl_dev)
-{
-
-	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
-			return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
-				  CMND_EN_MASK) == CMND_EN_MASK) ? 1 : 0);
-		}
-	}
-	return BP_NOT_CAP;
-}
-
-int wdt_en_status(struct bpctl_dev *pbpctl_dev)
-{
-
-	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) {
-			return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) &
-				  WDT_EN_MASK) == WDT_EN_MASK) ? 1 : 0);
-		}
-	}
-	return BP_NOT_CAP;
-}
-
-int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout)
+static int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout)
 {
 	int ret = 0;
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -3481,40 +3346,7 @@ int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout)
 	return ret;
 }
 
-int bypass_support(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-
-	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
-			ret =
-			    ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) &
-			       BYPASS_SUPPORT_MASK) ==
-			      BYPASS_SUPPORT_MASK) ? 1 : 0);
-		} else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
-			ret = 1;
-	} else
-		ret = BP_NOT_CAP;
-	return ret;
-}
-
-int tap_support(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-
-	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
-			ret =
-			    ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) &
-			       TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) ? 1 : 0);
-		} else if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER)
-			ret = 0;
-	} else
-		ret = BP_NOT_CAP;
-	return ret;
-}
-
-int normal_support(struct bpctl_dev *pbpctl_dev)
+static int normal_support(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -3530,7 +3362,7 @@ int normal_support(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev)
+static int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & SW_CTL_CAP) &&
 	    (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER))
@@ -3539,7 +3371,7 @@ int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev)
 
 }
 
-int tap_flag_status(struct bpctl_dev *pbpctl_dev)
+static int tap_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
@@ -3551,7 +3383,7 @@ int tap_flag_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev)
+static int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t status_reg = 0;
 	if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
@@ -3565,7 +3397,7 @@ int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tap_change_status(struct bpctl_dev *pbpctl_dev)
+static int tap_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
@@ -3582,17 +3414,7 @@ int tap_change_status(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int tap_off_status(struct bpctl_dev *pbpctl_dev)
-{
-	if (pbpctl_dev->bp_caps & TAP_CAP) {
-		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
-			return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
-				  TAP_OFF_MASK) == TAP_OFF_MASK) ? 1 : 0);
-	}
-	return BP_NOT_CAP;
-}
-
-int tap_status(struct bpctl_dev *pbpctl_dev)
+static int tap_status(struct bpctl_dev *pbpctl_dev)
 {
 	u32 ctrl_ext = 0;
 
@@ -3631,7 +3453,7 @@ int tap_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev)
+static int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
@@ -3642,7 +3464,7 @@ int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev)
+static int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
@@ -3653,7 +3475,7 @@ int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_flag_status(struct bpctl_dev *pbpctl_dev)
+static int disc_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3665,7 +3487,7 @@ int disc_flag_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev)
+static int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t status_reg = 0;
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3679,7 +3501,7 @@ int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_change_status(struct bpctl_dev *pbpctl_dev)
+static int disc_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3690,7 +3512,7 @@ int disc_change_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_off_status(struct bpctl_dev *pbpctl_dev)
+static int disc_off_status(struct bpctl_dev *pbpctl_dev)
 {
 	struct bpctl_dev *pbpctl_dev_b = NULL;
 	u32 ctrl_ext = 0;
@@ -3786,7 +3608,7 @@ static int disc_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev)
+static int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3797,7 +3619,7 @@ int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev)
+static int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DIS_DISC_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3808,55 +3630,7 @@ int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_port_status(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = BP_NOT_CAP;
-	struct bpctl_dev *pbpctl_dev_m;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1) {
-			return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
-				  TX_DISA_MASK) == TX_DISA_MASK) ? 1 : 0);
-		} else
-			return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) &
-				  TX_DISB_MASK) == TX_DISB_MASK) ? 1 : 0);
-
-	}
-	return ret;
-}
-
-int default_pwron_disc_port_status(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = BP_NOT_CAP;
-	struct bpctl_dev *pbpctl_dev_m;
-
-	if ((is_bypass_fn(pbpctl_dev)) == 1)
-		pbpctl_dev_m = pbpctl_dev;
-	else
-		pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
-	if (pbpctl_dev_m == NULL)
-		return BP_NOT_CAP;
-
-	if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) {
-		if (is_bypass_fn(pbpctl_dev) == 1)
-			return ret;
-		/*  return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */
-		else
-			return ret;
-		/*   return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */
-
-	}
-	return ret;
-}
-
-int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev)
+static int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER)
@@ -3879,7 +3653,7 @@ int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tpl2_flag_status(struct bpctl_dev *pbpctl_dev)
+static int tpl2_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) {
@@ -3890,22 +3664,7 @@ int tpl2_flag_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tpl_hw_status(struct bpctl_dev *pbpctl_dev)
-{
-	struct bpctl_dev *pbpctl_dev_b = NULL;
-
-	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
-	if (!pbpctl_dev_b)
-		return BP_NOT_CAP;
-
-	if (TPL_IF_SERIES(pbpctl_dev->subdevice))
-		return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) &
-			 BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0);
-	return BP_NOT_CAP;
-}
-
-
-int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev)
+static int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3916,7 +3675,7 @@ int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev)
+static int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3930,7 +3689,7 @@ int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev)
 }
 
 
-int std_nic_status(struct bpctl_dev *pbpctl_dev)
+static int std_nic_status(struct bpctl_dev *pbpctl_dev)
 {
 	int status_val = 0;
 
@@ -3978,7 +3737,7 @@ int std_nic_status(struct bpctl_dev *pbpctl_dev)
 /******************************************************/
 /**************SW_INIT*********************************/
 /******************************************************/
-void bypass_caps_init(struct bpctl_dev *pbpctl_dev)
+static void bypass_caps_init(struct bpctl_dev *pbpctl_dev)
 {
 	u_int32_t ctrl_ext = 0;
 	struct bpctl_dev *pbpctl_dev_m = NULL;
@@ -4196,23 +3955,7 @@ void bypass_caps_init(struct bpctl_dev *pbpctl_dev)
 	}
 }
 
-int bypass_off_init(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = cmnd_on(pbpctl_dev);
-	if (ret < 0)
-		return ret;
-	if (INTEL_IF_SERIES(pbpctl_dev->subdevice))
-		return dis_bypass_cap(pbpctl_dev);
-	wdt_off(pbpctl_dev);
-	if (pbpctl_dev->bp_caps & BP_CAP)
-		bypass_off(pbpctl_dev);
-	if (pbpctl_dev->bp_caps & TAP_CAP)
-		tap_off(pbpctl_dev);
-	cmnd_off(pbpctl_dev);
-	return 0;
-}
-
-void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
+static void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 #ifdef BP_SELF_TEST
 	struct bpctl_dev *pbpctl_dev_sl = NULL;
@@ -4241,7 +3984,7 @@ void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 
 }
 
-int init_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
+static int init_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		init_timer(&pbpctl_dev->bp_timer);
@@ -4288,7 +4031,7 @@ int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 #endif
 
-int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
+static int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		if (pbpctl_dev->reset_time != param) {
@@ -4307,7 +4050,7 @@ int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 	return BP_NOT_CAP;
 }
 
-int get_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP)
 		return pbpctl_dev->reset_time;
@@ -4378,7 +4121,7 @@ int is_bypass_fn(struct bpctl_dev *pbpctl_dev)
 	return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0);
 }
 
-int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
+static int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 
@@ -4396,12 +4139,12 @@ int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_fn(struct bpctl_dev *pbpctl_dev)
 {
 	return bypass_status(pbpctl_dev);
 }
 
-int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4409,7 +4152,7 @@ int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev)
 	return bypass_change_status(pbpctl_dev);
 }
 
-int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
+static int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4428,7 +4171,7 @@ int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 	return ret;
 }
 
-int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev)
+static int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4436,7 +4179,7 @@ int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev)
 	return dis_bypass_cap_status(pbpctl_dev);
 }
 
-int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
+static int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4455,7 +4198,7 @@ int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4463,7 +4206,7 @@ int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev)
 	return default_pwroff_status(pbpctl_dev);
 }
 
-int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
+static int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4482,7 +4225,7 @@ int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4490,7 +4233,7 @@ int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev)
 	return default_pwron_status(pbpctl_dev);
 }
 
-int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout)
+static int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4512,7 +4255,7 @@ int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout)
 	return ret;
 }
 
-int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout)
+static int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4520,7 +4263,7 @@ int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout)
 	return wdt_programmed(pbpctl_dev, timeout);
 }
 
-int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left)
+static int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4528,7 +4271,7 @@ int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left)
 	return wdt_timer(pbpctl_dev, time_left);
 }
 
-int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev)
+static int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4536,7 +4279,7 @@ int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev)
 	return wdt_timer_reload(pbpctl_dev);
 }
 
-int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev)
+static int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int bp_status = 0;
 
@@ -4560,7 +4303,7 @@ int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev)
 	return bp_status;
 }
 
-int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode)
+static int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4580,7 +4323,7 @@ int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode)
 	return ret;
 }
 
-int get_std_nic_fn(struct bpctl_dev *pbpctl_dev)
+static int get_std_nic_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4588,7 +4331,7 @@ int get_std_nic_fn(struct bpctl_dev *pbpctl_dev)
 	return std_nic_status(pbpctl_dev);
 }
 
-int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
+static int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4604,7 +4347,7 @@ int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_tap_fn(struct bpctl_dev *pbpctl_dev)
+static int get_tap_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4612,7 +4355,7 @@ int get_tap_fn(struct bpctl_dev *pbpctl_dev)
 	return tap_status(pbpctl_dev);
 }
 
-int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
+static int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4630,7 +4373,7 @@ int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 	return ret;
 }
 
-int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev)
+static int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4642,7 +4385,7 @@ int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev)
 	return ((ret == 0) ? 1 : 0);
 }
 
-int get_tap_change_fn(struct bpctl_dev *pbpctl_dev)
+static int get_tap_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4650,7 +4393,7 @@ int get_tap_change_fn(struct bpctl_dev *pbpctl_dev)
 	return tap_change_status(pbpctl_dev);
 }
 
-int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
+static int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4667,7 +4410,7 @@ int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 		return BP_NOT_CAP;
 }
 
-int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev)
+static int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4675,7 +4418,7 @@ int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev)
 	return dis_tap_cap_status(pbpctl_dev);
 }
 
-int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
+static int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4692,7 +4435,7 @@ int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 	return BP_NOT_CAP;
 }
 
-int get_disc_fn(struct bpctl_dev *pbpctl_dev)
+static int get_disc_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4703,7 +4446,7 @@ int get_disc_fn(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
+static int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4721,7 +4464,7 @@ int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 	return ret;
 }
 
-int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev)
+static int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4731,7 +4474,7 @@ int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev)
 	return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0));
 }
 
-int get_disc_change_fn(struct bpctl_dev *pbpctl_dev)
+static int get_disc_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4741,7 +4484,7 @@ int get_disc_change_fn(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
+static int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4759,7 +4502,7 @@ int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 		return BP_NOT_CAP;
 }
 
-int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev)
+static int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4770,55 +4513,7 @@ int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int set_disc_port_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
-{
-	int ret = BP_NOT_CAP;
-	if (!pbpctl_dev)
-		return -1;
-
-	if (!disc_mode)
-		ret = disc_port_off(pbpctl_dev);
-	else
-		ret = disc_port_on(pbpctl_dev);
-
-	return ret;
-}
-
-int get_disc_port_fn(struct bpctl_dev *pbpctl_dev)
-{
-	if (!pbpctl_dev)
-		return -1;
-
-	return disc_port_status(pbpctl_dev);
-}
-
-int set_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
-{
-	int ret = BP_NOT_CAP;
-	if (!pbpctl_dev)
-		return -1;
-
-	if (!disc_mode)
-		ret = normal_port_state_pwron(pbpctl_dev);
-	else
-		ret = disc_port_state_pwron(pbpctl_dev);
-
-	return ret;
-}
-
-int get_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	if (!pbpctl_dev)
-		return -1;
-
-	ret = default_pwron_disc_port_status(pbpctl_dev);
-	if (ret < 0)
-		return ret;
-	return ((ret == 0) ? 1 : 0);
-}
-
-int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev)
+static int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4826,7 +4521,7 @@ int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev)
 	return wdt_exp_mode_status(pbpctl_dev);
 }
 
-int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param)
+static int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4834,19 +4529,7 @@ int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param)
 	return wdt_exp_mode(pbpctl_dev, param);
 }
 
-int reset_cont_fn(struct bpctl_dev *pbpctl_dev)
-{
-	int ret = 0;
-	if (!pbpctl_dev)
-		return -1;
-
-	ret = cmnd_on(pbpctl_dev);
-	if (ret < 0)
-		return ret;
-	return reset_cont(pbpctl_dev);
-}
-
-int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state)
+static int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state)
 {
 
 	struct bpctl_dev *pbpctl_dev_b = NULL;
@@ -4867,7 +4550,7 @@ int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state)
 	return set_tx(pbpctl_dev, tx_state);
 }
 
-int set_bp_force_link_fn(int dev_num, int tx_state)
+static int set_bp_force_link_fn(int dev_num, int tx_state)
 {
 	static struct bpctl_dev *bpctl_dev_curr;
 
@@ -4879,7 +4562,7 @@ int set_bp_force_link_fn(int dev_num, int tx_state)
 	return set_bp_force_link(bpctl_dev_curr, tx_state);
 }
 
-int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param)
+static int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4887,7 +4570,7 @@ int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param)
 	return set_bypass_wd_auto(pbpctl_dev, param);
 }
 
-int get_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev)
+static int get_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4914,7 +4597,7 @@ int get_bp_self_test_fn(struct bpctl_dev *pbpctl_dev)
 
 #endif
 
-int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4923,7 +4606,8 @@ int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev)
 
 }
 
-int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev, struct bpctl_dev **pbpctl_dev_out)
+static int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev,
+			       struct bpctl_dev **pbpctl_dev_out)
 {
 	int idx_dev = 0;
 	if (!pbpctl_dev)
@@ -4955,7 +4639,7 @@ int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev, struct bpctl_dev **pbpctl_
 		return 0;
 }
 
-int is_bypass(struct bpctl_dev *pbpctl_dev)
+static int is_bypass(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4966,7 +4650,7 @@ int is_bypass(struct bpctl_dev *pbpctl_dev)
 		return 0;
 }
 
-int get_tx_fn(struct bpctl_dev *pbpctl_dev)
+static int get_tx_fn(struct bpctl_dev *pbpctl_dev)
 {
 	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
@@ -4986,7 +4670,7 @@ int get_tx_fn(struct bpctl_dev *pbpctl_dev)
 	return tx_status(pbpctl_dev);
 }
 
-int get_bp_force_link_fn(int dev_num)
+static int get_bp_force_link_fn(int dev_num)
 {
 	static struct bpctl_dev *bpctl_dev_curr;
 
@@ -5049,7 +4733,7 @@ static void bp_tpl_timer_fn(unsigned long param)
 	mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ);
 }
 
-void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
+static void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 {
 	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
@@ -5067,7 +4751,7 @@ void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 	return;
 }
 
-int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
+static int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5080,7 +4764,7 @@ int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
+static int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5098,17 +4782,7 @@ int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 	return BP_NOT_CAP;
 }
 
-int get_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
-{
-	if (!pbpctl_dev)
-		return -1;
-	if (pbpctl_dev->bp_caps & TPL_CAP)
-		return pbpctl_dev->bp_tpl_flag;
-
-	return BP_NOT_CAP;
-}
-
-int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode)
+static int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode)
 {
 
 	struct bpctl_dev *pbpctl_dev_b = NULL;
@@ -5138,7 +4812,7 @@ int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode)
 	return BP_NOT_CAP;
 }
 
-int get_tpl_fn(struct bpctl_dev *pbpctl_dev)
+static int get_tpl_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (!pbpctl_dev)
@@ -5152,7 +4826,7 @@ int get_tpl_fn(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
+static int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5172,7 +4846,7 @@ int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -5185,7 +4859,7 @@ int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev)
 	return ret;
 }
 
-int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
+static int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5205,7 +4879,7 @@ int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev)
+static int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -5220,7 +4894,7 @@ int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev)
 }
 
 
-int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name,
+static int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name,
 		       char *add_param)
 {
 	if (!pbpctl_dev)
@@ -5232,7 +4906,7 @@ int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name,
 	return 0;
 }
 
-int get_dev_idx_bsf(int bus, int slot, int func)
+static int get_dev_idx_bsf(int bus, int slot, int func)
 {
 	int idx_dev = 0;
 	for (idx_dev = 0;
@@ -7022,12 +6696,6 @@ int set_wd_exp_mode_sd(int ifindex, int param)
 }
 EXPORT_SYMBOL(set_wd_exp_mode_sd);
 
-int reset_cont_sd(int ifindex)
-{
-	return reset_cont_fn(get_dev_idx_p(ifindex));
-
-}
-
 int set_tx_sd(int ifindex, int tx_state)
 {
 	return set_tx_fn(get_dev_idx_p(ifindex), tx_state);
@@ -7118,7 +6786,7 @@ EXPORT_SYMBOL(bp_if_scan_sd);
 
 static struct proc_dir_entry *bp_procfs_dir;
 
-int bp_proc_create(void)
+static int bp_proc_create(void)
 {
 	bp_procfs_dir = proc_mkdir(BP_PROC_DIR, init_net.proc_net);
 	if (bp_procfs_dir == (struct proc_dir_entry *)0) {
@@ -7746,7 +7414,7 @@ static int show_wd_autoreset(struct seq_file *m, void *v)
 }
 RW_FOPS(wd_autoreset)
 
-int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block)
+static int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block)
 {
 	struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
 	static struct proc_dir_entry *procfs_dir;
@@ -7816,7 +7484,7 @@ int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block)
 	return ret;
 }
 
-int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block)
+static int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block)
 {
 
 	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
diff --git a/drivers/staging/silicom/bypasslib/bp_ioctl.h b/drivers/staging/silicom/bypasslib/bp_ioctl.h
index 2d1ef5384436..a0fb79fd1909 100644
--- a/drivers/staging/silicom/bypasslib/bp_ioctl.h
+++ b/drivers/staging/silicom/bypasslib/bp_ioctl.h
@@ -51,7 +51,7 @@
 #define WDT_STEP_TIME              0x10	/* BIT_4 */
 
 #define WD_MIN_TIME_GET(desc)   (desc & 0xf)
-#define WD_STEP_COUNT_GET(desc) (desc>>5) & 0xf
+#define WD_STEP_COUNT_GET(desc) ((desc>>5) & 0xf)
 
 typedef enum {
 	IS_BYPASS = 1,
@@ -156,7 +156,7 @@ typedef enum {
 
 } CMND_TYPE_SD;
 
-#define SIOCGIFBYPASS SIOCDEVPRIVATE+10
+#define SIOCGIFBYPASS (SIOCDEVPRIVATE+10)
 
 struct bp_info {
 	char prod_name[14];
diff --git a/drivers/staging/slicoss/README b/drivers/staging/slicoss/README
index 53052c4e78ae..4fa50e73ce86 100644
--- a/drivers/staging/slicoss/README
+++ b/drivers/staging/slicoss/README
@@ -5,43 +5,3 @@ This driver is supposed to support:
 	Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
 
 The driver was actually tested on Oasis and Kalahari cards.
-
-TODO:
-	- move firmware loading to request_firmware()
-	- remove direct memory access of structures
-	- any remaining sparse and checkpatch.pl warnings
-
-	- use net_device_ops
-	- use dev->stats rather than adapter->stats
-	- don't cast netdev_priv it is already void
-	- GET RID OF MACROS
-	- work on all architectures
-	   - without CONFIG_X86_64 confusion
-	   - do 64 bit correctly
-	   - don't depend on order of union
-	- get rid of ASSERT(), use BUG() instead but only where necessary
-	  looks like most aren't really useful
-	- no new SIOCDEVPRIVATE ioctl allowed
-	- don't use module_param for configuring interrupt mitigation
-	  use ethtool instead
-	- reorder code to elminate use of forward declarations
-	- don't keep private linked list of drivers.
-	- remove all the gratiutous debug infrastructure
-	- use PCI_DEVICE()
-	- do ethtool correctly using ethtool_ops
-	- NAPI?
-	- wasted overhead of extra stats
-	- state variables for things that are
-	  easily available and shouldn't be kept in card structure, cardnum, ...
-	  slotnumber, events, ...
-	- get rid of slic_spinlock wrapper
-	- volatile == bad design => bad code
-	- locking too fine grained, not designed just throw more locks
-	  at problem
-
-
-Please send patches to:
-        Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-and Cc: Lior Dotan <liodot@gmail.com> and Christopher Harrer
-<charrer@alacritech.com> as well as they are also able to test out any
-changes.
diff --git a/drivers/staging/slicoss/TODO b/drivers/staging/slicoss/TODO
new file mode 100644
index 000000000000..62ff1008b1ee
--- /dev/null
+++ b/drivers/staging/slicoss/TODO
@@ -0,0 +1,38 @@
+TODO:
+	- move firmware loading to request_firmware()
+	- remove direct memory access of structures
+	- any remaining sparse and checkpatch.pl warnings
+
+	- use net_device_ops
+	- use dev->stats rather than adapter->stats
+	- don't cast netdev_priv it is already void
+	- GET RID OF MACROS
+	- work on all architectures
+	   - without CONFIG_X86_64 confusion
+	   - do 64 bit correctly
+	   - don't depend on order of union
+	- get rid of ASSERT(), use BUG() instead but only where necessary
+	  looks like most aren't really useful
+	- no new SIOCDEVPRIVATE ioctl allowed
+	- don't use module_param for configuring interrupt mitigation
+	  use ethtool instead
+	- reorder code to elminate use of forward declarations
+	- don't keep private linked list of drivers.
+	- remove all the gratiutous debug infrastructure
+	- use PCI_DEVICE()
+	- do ethtool correctly using ethtool_ops
+	- NAPI?
+	- wasted overhead of extra stats
+	- state variables for things that are
+	  easily available and shouldn't be kept in card structure, cardnum, ...
+	  slotnumber, events, ...
+	- get rid of slic_spinlock wrapper
+	- volatile == bad design => bad code
+	- locking too fine grained, not designed just throw more locks
+	  at problem
+
+Please send patches to:
+        Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+and Cc: Lior Dotan <liodot@gmail.com> and Christopher Harrer
+<charrer@alacritech.com> as well as they are also able to test out any
+changes.
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
index 4c7822bd5358..702902cdb461 100644
--- a/drivers/staging/slicoss/slic.h
+++ b/drivers/staging/slicoss/slic.h
@@ -464,9 +464,12 @@ struct adapter {
 	/*
 	*  SLIC Handles
 	*/
-	struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1]; /* Object handles*/
-	struct slic_handle *pfree_slic_handles;          /* Free object handles*/
-	struct slic_spinlock     handle_lock;           /* Object handle list lock*/
+	/* Object handles*/
+	struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1];
+	/* Free object handles*/
+	struct slic_handle *pfree_slic_handles;
+	/* Object handle list lock*/
+	struct slic_spinlock     handle_lock;
 	ushort              slic_handle_ix;
 
 	u32             xmitq_full;
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 1426ca49bfe8..758c4efea0de 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -1830,7 +1830,7 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 #endif
 
 	seq_printf(seq, "driver_version           : %s\n", slic_proc_version);
-	seq_puts(seq, "Microcode versions:           \n");
+	seq_puts(seq, "Microcode versions:\n");
 	seq_printf(seq, "    Gigabit (gb)         : %s %s\n",
 		    MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE);
 	seq_printf(seq, "    Gigabit Receiver     : %s %s\n",
@@ -1917,16 +1917,14 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 
 			if (config->OEMFruFormat == VENDOR4_FRU_FORMAT) {
 				seq_printf(seq,
-					    "Serial   #               : "
-					    "%c%c%c%c%c%c%c%c%c%c%c%c\n",
+					    "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c\n",
 					    fru[8], fru[9], fru[10],
 					    fru[11], fru[12], fru[13],
 					    fru[16], fru[17], fru[18],
 					    fru[19], fru[20], fru[21]);
 			} else {
 				seq_printf(seq,
-					    "Serial   #               : "
-					    "%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+					    "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
 					    fru[8], fru[9], fru[10],
 					    fru[11], fru[12], fru[13],
 					    fru[14], fru[15], fru[16],
@@ -1974,8 +1972,7 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 		{
 			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
-				    "    Part     #           : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    Part     #           : %c%c%c%c%c%c%c%c\n",
 				    oemfru[0], oemfru[1], oemfru[2],
 				    oemfru[3], oemfru[4], oemfru[5],
 				    oemfru[6], oemfru[7]);
@@ -2002,20 +1999,17 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 		{
 			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
-				    "    FRU Number           : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    FRU Number           : %c%c%c%c%c%c%c%c\n",
 				    oemfru[0], oemfru[1], oemfru[2],
 				    oemfru[3], oemfru[4], oemfru[5],
 				    oemfru[6], oemfru[7]);
 			seq_sprintf(seq,
-				    "    Part Number          : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    Part Number          : %c%c%c%c%c%c%c%c\n",
 				    oemfru[8], oemfru[9], oemfru[10],
 				    oemfru[11], oemfru[12], oemfru[13],
 				    oemfru[14], oemfru[15]);
 			seq_printf(seq,
-				    "    EC Level             : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    EC Level             : %c%c%c%c%c%c%c%c\n",
 				    oemfru[16], oemfru[17], oemfru[18],
 				    oemfru[19], oemfru[20], oemfru[21],
 				    oemfru[22], oemfru[23]);
@@ -2412,8 +2406,7 @@ static void slic_xmit_fail(struct adapter *adapter,
 		switch (status) {
 		case XMIT_FAIL_LINK_STATE:
 			dev_err(&adapter->netdev->dev,
-				"reject xmit skb[%p: %x] linkstate[%s] "
-				"adapter[%s:%d] card[%s:%d]\n",
+				"reject xmit skb[%p: %x] linkstate[%s] adapter[%s:%d] card[%s:%d]\n",
 				skb, skb->pkt_type,
 				SLIC_LINKSTATE(adapter->linkstate),
 				SLIC_ADAPTER_STATE(adapter->state),
@@ -2428,8 +2421,7 @@ static void slic_xmit_fail(struct adapter *adapter,
 			break;
 		case XMIT_FAIL_HOSTCMD_FAIL:
 			dev_err(&adapter->netdev->dev,
-				"xmit_start skb[%p] type[%x] No host commands "
-				"available\n", skb, skb->pkt_type);
+				"xmit_start skb[%p] type[%x] No host commands available\n", skb, skb->pkt_type);
 			break;
 		}
 	}
@@ -2642,8 +2634,7 @@ static void slic_interrupt_card_up(u32 isr, struct adapter *adapter,
 				}
 			} else if (isr & ISR_XDROP) {
 				dev_err(&dev->dev,
-						"isr & ISR_ERR [%x] "
-						"ISR_XDROP \n", isr);
+						"isr & ISR_ERR [%x] ISR_XDROP\n", isr);
 			} else {
 				dev_err(&dev->dev,
 						"isr & ISR_ERR [%x]\n",
@@ -2970,7 +2961,7 @@ static void slic_card_cleanup(struct sliccard *card)
 {
 	if (card->loadtimerset) {
 		card->loadtimerset = 0;
-		del_timer(&card->loadtimer);
+		del_timer_sync(&card->loadtimer);
 	}
 
 	slic_debug_card_destroy(card);
@@ -3269,8 +3260,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
 
 		if (!peeprom) {
 			dev_err(&adapter->pcidev->dev,
-				"eeprom read failed to get memory "
-				"bus %d slot %d\n", adapter->busnumber,
+				"eeprom read failed to get memory bus %d slot %d\n", adapter->busnumber,
 				adapter->slotnumber);
 			return -ENOMEM;
 		} else {
diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig
deleted file mode 100644
index e2922ae3a3ee..000000000000
--- a/drivers/staging/sm7xxfb/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config FB_SM7XX
-	tristate "Silicon Motion SM7XX framebuffer support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Frame buffer driver for the Silicon Motion SM710, SM712, SM721
-	  and SM722 chips.
-
-	  This driver is also available as a module. The module will be
-	  called sm7xxfb. If you want to compile it as a module, say M
-	  here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile
deleted file mode 100644
index 48f471cf9f36..000000000000
--- a/drivers/staging/sm7xxfb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o
diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO
deleted file mode 100644
index 1fcead591c16..000000000000
--- a/drivers/staging/sm7xxfb/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
-- Dual head support
-- 2D acceleration support
-- use kernel coding style
-- refine the code and remove unused code
-- move it to drivers/video/sm7xxfb.c
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
-Teddy Wang <teddy.wang@siliconmotion.com.cn>.
diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h
deleted file mode 100644
index 85998615b801..000000000000
--- a/drivers/staging/sm7xxfb/sm7xx.h
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- * Silicon Motion SM712 frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:	Ge Wang, gewang@siliconmotion.com
- *		Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.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.
- */
-
-#define NR_PALETTE        256
-
-#define FB_ACCEL_SMI_LYNX 88
-
-#define SCREEN_X_RES      1024
-#define SCREEN_Y_RES      600
-#define SCREEN_BPP        16
-
-/*Assume SM712 graphics chip has 4MB VRAM */
-#define SM712_VIDEOMEMORYSIZE	  0x00400000
-/*Assume SM722 graphics chip has 8MB VRAM */
-#define SM722_VIDEOMEMORYSIZE	  0x00800000
-
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
-
-extern void __iomem *smtc_RegBaseAddress;
-#define smtc_mmiowb(dat, reg)	writeb(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmioww(dat, reg)	writew(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmiowl(dat, reg)	writel(dat, smtc_RegBaseAddress + reg)
-
-#define smtc_mmiorb(reg)	readb(smtc_RegBaseAddress + reg)
-#define smtc_mmiorw(reg)	readw(smtc_RegBaseAddress + reg)
-#define smtc_mmiorl(reg)	readl(smtc_RegBaseAddress + reg)
-
-#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
-#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
-#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
-#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
-#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
-#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
-#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
-#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
-#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
-#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
-#define SIZE_VPR		(0x6C + 1)
-#define SIZE_DPR		(0x44 + 1)
-
-static inline void smtc_crtcw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3d4);
-	smtc_mmiowb(val, 0x3d5);
-}
-
-static inline unsigned int smtc_crtcr(int reg)
-{
-	smtc_mmiowb(reg, 0x3d4);
-	return smtc_mmiorb(0x3d5);
-}
-
-static inline void smtc_grphw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3ce);
-	smtc_mmiowb(val, 0x3cf);
-}
-
-static inline unsigned int smtc_grphr(int reg)
-{
-	smtc_mmiowb(reg, 0x3ce);
-	return smtc_mmiorb(0x3cf);
-}
-
-static inline void smtc_attrw(int reg, int val)
-{
-	smtc_mmiorb(0x3da);
-	smtc_mmiowb(reg, 0x3c0);
-	smtc_mmiorb(0x3c1);
-	smtc_mmiowb(val, 0x3c0);
-}
-
-static inline void smtc_seqw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3c4);
-	smtc_mmiowb(val, 0x3c5);
-}
-
-static inline unsigned int smtc_seqr(int reg)
-{
-	smtc_mmiowb(reg, 0x3c4);
-	return smtc_mmiorb(0x3c5);
-}
-
-/* The next structure holds all information relevant for a specific video mode.
- */
-
-struct ModeInit {
-	int mmSizeX;
-	int mmSizeY;
-	int bpp;
-	int hz;
-	unsigned char Init_MISC;
-	unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
-	unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
-	unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
-	unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
-	unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
-	unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
-	unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
-	unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
-	unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
-	unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
-};
-
-/**********************************************************************
-			 SM712 Mode table.
- **********************************************************************/
-struct ModeInit VGAMode[] = {
-	{
-	 /*  mode#0: 640 x 480  16Bpp  60Hz */
-	 640, 480, 16, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-	{
-	 /*  mode#1: 640 x 480  24Bpp  60Hz */
-	 640, 480, 24, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-	{
-	 /*  mode#0: 640 x 480  32Bpp  60Hz */
-	 640, 480, 32, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-
-	{			/*  mode#2: 800 x 600  16Bpp  60Hz */
-	 800, 600, 16, 60,
-	 /*  Init_MISC */
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-	  0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-	  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	{			/*  mode#3: 800 x 600  24Bpp  60Hz */
-	 800, 600, 24, 60,
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
-	  0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	{			/*  mode#7: 800 x 600  32Bpp  60Hz */
-	 800, 600, 32, 60,
-	 /*  Init_MISC */
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-	  0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-	  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	/* We use 1024x768 table to light 1024x600 panel for lemote */
-	{			/*  mode#4: 1024 x 600  16Bpp  60Hz  */
-	 1024, 600, 16, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
-	  0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x00, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
-	  0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
-	  0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
-	  0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#5: 1024 x 768  24Bpp  60Hz */
-	 1024, 768, 24, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-	  0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#4: 1024 x 768  32Bpp  60Hz */
-	 1024, 768, 32, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-	  0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#6: 320 x 240  16Bpp  60Hz */
-	 320, 240, 16, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-	  0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-
-	{			/*  mode#8: 320 x 240  32Bpp  60Hz */
-	 320, 240, 32, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-	  0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-};
-
-#define numVGAModes		ARRAY_SIZE(VGAMode)
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
deleted file mode 100644
index 6176d98744cc..000000000000
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * Silicon Motion SM7XX frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:  Ge Wang, gewang@siliconmotion.com
- *	     Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author:   Wu Zhangjin, wuzhangjin@gmail.com
- *
- * Copyright (C) 2011 Igalia, S.L.
- * Author:   Javier M. Mellid <jmunhoz@igalia.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.
- *
- * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
- */
-
-#include <linux/io.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/screen_info.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include "sm7xx.h"
-
-/*
-* Private structure
-*/
-struct smtcfb_info {
-	struct pci_dev *pdev;
-	struct fb_info fb;
-	u16 chip_id;
-	u8  chip_rev_id;
-
-	void __iomem *lfb;	/* linear frame buffer */
-	void __iomem *dp_regs;	/* drawing processor control regs */
-	void __iomem *vp_regs;	/* video processor control regs */
-	void __iomem *cp_regs;	/* capture processor control regs */
-	void __iomem *mmio;	/* memory map IO port */
-
-	u_int width;
-	u_int height;
-	u_int hz;
-
-	u32 colreg[17];
-};
-
-void __iomem *smtc_RegBaseAddress;	/* Memory Map IO starting address */
-
-static struct fb_var_screeninfo smtcfb_var = {
-	.xres           = 1024,
-	.yres           = 600,
-	.xres_virtual   = 1024,
-	.yres_virtual   = 600,
-	.bits_per_pixel = 16,
-	.red            = {16, 8, 0},
-	.green          = {8, 8, 0},
-	.blue           = {0, 8, 0},
-	.activate       = FB_ACTIVATE_NOW,
-	.height         = -1,
-	.width          = -1,
-	.vmode          = FB_VMODE_NONINTERLACED,
-	.nonstd         = 0,
-	.accel_flags    = FB_ACCELF_TEXT,
-};
-
-static struct fb_fix_screeninfo smtcfb_fix = {
-	.id             = "smXXXfb",
-	.type           = FB_TYPE_PACKED_PIXELS,
-	.visual         = FB_VISUAL_TRUECOLOR,
-	.line_length    = 800 * 3,
-	.accel          = FB_ACCEL_SMI_LYNX,
-	.type_aux       = 0,
-	.xpanstep       = 0,
-	.ypanstep       = 0,
-	.ywrapstep      = 0,
-};
-
-struct vesa_mode {
-	char index[6];
-	u16  lfb_width;
-	u16  lfb_height;
-	u16  lfb_depth;
-};
-
-static struct vesa_mode vesa_mode_table[] = {
-	{"0x301", 640,  480,  8},
-	{"0x303", 800,  600,  8},
-	{"0x305", 1024, 768,  8},
-	{"0x307", 1280, 1024, 8},
-
-	{"0x311", 640,  480,  16},
-	{"0x314", 800,  600,  16},
-	{"0x317", 1024, 768,  16},
-	{"0x31A", 1280, 1024, 16},
-
-	{"0x312", 640,  480,  24},
-	{"0x315", 800,  600,  24},
-	{"0x318", 1024, 768,  24},
-	{"0x31B", 1280, 1024, 24},
-};
-
-struct screen_info smtc_scr_info;
-
-/* process command line options, get vga parameter */
-static int __init sm7xx_vga_setup(char *options)
-{
-	int i;
-
-	if (!options || !*options)
-		return -EINVAL;
-
-	smtc_scr_info.lfb_width = 0;
-	smtc_scr_info.lfb_height = 0;
-	smtc_scr_info.lfb_depth = 0;
-
-	pr_debug("sm7xx_vga_setup = %s\n", options);
-
-	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
-		if (strstr(options, vesa_mode_table[i].index)) {
-			smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
-			smtc_scr_info.lfb_height =
-						vesa_mode_table[i].lfb_height;
-			smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
-			return 0;
-		}
-	}
-
-	return -1;
-}
-__setup("vga=", sm7xx_vga_setup);
-
-static void sm712_setpalette(int regno, unsigned red, unsigned green,
-			     unsigned blue, struct fb_info *info)
-{
-	/* set bit 5:4 = 01 (write LCD RAM only) */
-	smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
-
-	smtc_mmiowb(regno, dac_reg);
-	smtc_mmiowb(red >> 10, dac_val);
-	smtc_mmiowb(green >> 10, dac_val);
-	smtc_mmiowb(blue >> 10, dac_val);
-}
-
-/* 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;
-}
-
-static int smtc_blank(int blank_mode, struct fb_info *info)
-{
-	/* clear DPMS setting */
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* Screen On: HSync: On, VSync : On */
-		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
-		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-		smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
-		break;
-	case FB_BLANK_NORMAL:
-		/* Screen Off: HSync: On, VSync : On   Soft blank */
-		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		/* Screen On: HSync: On, VSync : Off */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		/* Screen On: HSync: Off, VSync : On */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	case FB_BLANK_POWERDOWN:
-		/* Screen On: HSync: Off, VSync : Off */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned trans, struct fb_info *info)
-{
-	struct smtcfb_info *sfb;
-	u32 val;
-
-	sfb = info->par;
-
-	if (regno > 255)
-		return 1;
-
-	switch (sfb->fb.fix.visual) {
-	case FB_VISUAL_DIRECTCOLOR:
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 16/32 bit true-colour, use pseudo-palette for 16 base color
-		 */
-		if (regno < 16) {
-			if (sfb->fb.var.bits_per_pixel == 16) {
-				u32 *pal = sfb->fb.pseudo_palette;
-				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, &sfb->fb.var.green);
-				val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-				pal[regno] =
-				    ((red & 0xf800) >> 8) |
-				    ((green & 0xe000) >> 13) |
-				    ((green & 0x1c00) << 3) |
-				    ((blue & 0xf800) >> 3);
-#else
-				pal[regno] = val;
-#endif
-			} else {
-				u32 *pal = sfb->fb.pseudo_palette;
-				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, &sfb->fb.var.green);
-				val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-				val =
-				    (val & 0xff00ff00 >> 8) |
-				    (val & 0x00ff00ff << 8);
-#endif
-				pal[regno] = val;
-			}
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		/* color depth 8 bit */
-		sm712_setpalette(regno, red, green, blue, info);
-		break;
-
-	default:
-		return 1;	/* unknown type */
-	}
-
-	return 0;
-
-}
-
-#ifdef __BIG_ENDIAN
-static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t
-				count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-
-	u32 *buffer, *dst;
-	u32 __iomem *src;
-	int c, i, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || !info->screen_base)
-		return -ENODEV;
-
-	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;
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	src = (u32 __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;
-		for (i = c >> 2; i--;) {
-			*dst = fb_readl(src++);
-			*dst =
-			    (*dst & 0xff00ff00 >> 8) |
-			    (*dst & 0x00ff00ff << 8);
-			dst++;
-		}
-		if (c & 3) {
-			u8 *dst8 = (u8 *) dst;
-			u8 __iomem *src8 = (u8 __iomem *) src;
-
-			for (i = c & 3; i--;) {
-				if (i & 1) {
-					*dst8++ = fb_readb(++src8);
-				} else {
-					*dst8++ = fb_readb(--src8);
-					src8 += 2;
-				}
-			}
-			src = (u32 __iomem *) src8;
-		}
-
-		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
-smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
-	     loff_t *ppos)
-{
-	unsigned long p = *ppos;
-
-	u32 *buffer, *src;
-	u32 __iomem *dst;
-	int c, i, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || !info->screen_base)
-		return -ENODEV;
-
-	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;
-	}
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	dst = (u32 __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;
-		}
-
-		for (i = c >> 2; i--;) {
-			fb_writel((*src & 0xff00ff00 >> 8) |
-				  (*src & 0x00ff00ff << 8), dst++);
-			src++;
-		}
-		if (c & 3) {
-			u8 *src8 = (u8 *) src;
-			u8 __iomem *dst8 = (u8 __iomem *) dst;
-
-			for (i = c & 3; i--;) {
-				if (i & 1) {
-					fb_writeb(*src8++, ++dst8);
-				} else {
-					fb_writeb(*src8++, --dst8);
-					dst8 += 2;
-				}
-			}
-			dst = (u32 __iomem *) dst8;
-		}
-
-		*ppos += c;
-		buf += c;
-		cnt += c;
-		count -= c;
-	}
-
-	kfree(buffer);
-
-	return (cnt) ? cnt : err;
-}
-#endif	/* ! __BIG_ENDIAN */
-
-static void sm7xx_set_timing(struct smtcfb_info *sfb)
-{
-	int i = 0, j = 0;
-	u32 m_nScreenStride;
-
-	dev_dbg(&sfb->pdev->dev,
-		"sfb->width=%d sfb->height=%d "
-		"sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
-		sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);
-
-	for (j = 0; j < numVGAModes; j++) {
-		if (VGAMode[j].mmSizeX == sfb->width &&
-		    VGAMode[j].mmSizeY == sfb->height &&
-		    VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
-		    VGAMode[j].hz == sfb->hz) {
-
-			dev_dbg(&sfb->pdev->dev,
-				"VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
-				"VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
-				VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
-				VGAMode[j].bpp, VGAMode[j].hz);
-
-			dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);
-
-			smtc_mmiowb(0x0, 0x3c6);
-
-			smtc_seqw(0, 0x1);
-
-			smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
-
-			/* init SEQ register SR00 - SR04 */
-			for (i = 0; i < SIZE_SR00_SR04; i++)
-				smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
-
-			/* init SEQ register SR10 - SR24 */
-			for (i = 0; i < SIZE_SR10_SR24; i++)
-				smtc_seqw(i + 0x10,
-					  VGAMode[j].Init_SR10_SR24[i]);
-
-			/* init SEQ register SR30 - SR75 */
-			for (i = 0; i < SIZE_SR30_SR75; i++)
-				if ((i + 0x30) != 0x62 &&
-				    (i + 0x30) != 0x6a &&
-				    (i + 0x30) != 0x6b)
-					smtc_seqw(i + 0x30,
-						VGAMode[j].Init_SR30_SR75[i]);
-
-			/* init SEQ register SR80 - SR93 */
-			for (i = 0; i < SIZE_SR80_SR93; i++)
-				smtc_seqw(i + 0x80,
-					  VGAMode[j].Init_SR80_SR93[i]);
-
-			/* init SEQ register SRA0 - SRAF */
-			for (i = 0; i < SIZE_SRA0_SRAF; i++)
-				smtc_seqw(i + 0xa0,
-					  VGAMode[j].Init_SRA0_SRAF[i]);
-
-			/* init Graphic register GR00 - GR08 */
-			for (i = 0; i < SIZE_GR00_GR08; i++)
-				smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
-
-			/* init Attribute register AR00 - AR14 */
-			for (i = 0; i < SIZE_AR00_AR14; i++)
-				smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
-
-			/* init CRTC register CR00 - CR18 */
-			for (i = 0; i < SIZE_CR00_CR18; i++)
-				smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
-
-			/* init CRTC register CR30 - CR4D */
-			for (i = 0; i < SIZE_CR30_CR4D; i++)
-				smtc_crtcw(i + 0x30,
-					   VGAMode[j].Init_CR30_CR4D[i]);
-
-			/* init CRTC register CR90 - CRA7 */
-			for (i = 0; i < SIZE_CR90_CRA7; i++)
-				smtc_crtcw(i + 0x90,
-					   VGAMode[j].Init_CR90_CRA7[i]);
-		}
-	}
-	smtc_mmiowb(0x67, 0x3c2);
-
-	/* set VPR registers */
-	writel(0x0, sfb->vp_regs + 0x0C);
-	writel(0x0, sfb->vp_regs + 0x40);
-
-	/* set data width */
-	m_nScreenStride =
-		(sfb->width * sfb->fb.var.bits_per_pixel) / 64;
-	switch (sfb->fb.var.bits_per_pixel) {
-	case 8:
-		writel(0x0, sfb->vp_regs + 0x0);
-		break;
-	case 16:
-		writel(0x00020000, sfb->vp_regs + 0x0);
-		break;
-	case 24:
-		writel(0x00040000, sfb->vp_regs + 0x0);
-		break;
-	case 32:
-		writel(0x00030000, sfb->vp_regs + 0x0);
-		break;
-	}
-	writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
-	       sfb->vp_regs + 0x10);
-
-}
-
-static void smtc_set_timing(struct smtcfb_info *sfb)
-{
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-	case 0x720:
-		sm7xx_set_timing(sfb);
-		break;
-	}
-}
-
-static void smtcfb_setmode(struct smtcfb_info *sfb)
-{
-	switch (sfb->fb.var.bits_per_pixel) {
-	case 32:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 4;
-		sfb->fb.var.red.length   = 8;
-		sfb->fb.var.green.length = 8;
-		sfb->fb.var.blue.length  = 8;
-		sfb->fb.var.red.offset   = 16;
-		sfb->fb.var.green.offset = 8;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 24:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 3;
-		sfb->fb.var.red.length   = 8;
-		sfb->fb.var.green.length = 8;
-		sfb->fb.var.blue.length  = 8;
-		sfb->fb.var.red.offset   = 16;
-		sfb->fb.var.green.offset = 8;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 8:
-		sfb->fb.fix.visual       = FB_VISUAL_PSEUDOCOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres;
-		sfb->fb.var.red.length   = 3;
-		sfb->fb.var.green.length = 3;
-		sfb->fb.var.blue.length  = 2;
-		sfb->fb.var.red.offset   = 5;
-		sfb->fb.var.green.offset = 2;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 16:
-	default:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 2;
-		sfb->fb.var.red.length   = 5;
-		sfb->fb.var.green.length = 6;
-		sfb->fb.var.blue.length  = 5;
-		sfb->fb.var.red.offset   = 11;
-		sfb->fb.var.green.offset = 5;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	}
-
-	sfb->width  = sfb->fb.var.xres;
-	sfb->height = sfb->fb.var.yres;
-	sfb->hz = 60;
-	smtc_set_timing(sfb);
-}
-
-static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	/* sanity checks */
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	/* set valid default bpp */
-	if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
-	    (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
-		var->bits_per_pixel = 16;
-
-	return 0;
-}
-
-static int smtc_set_par(struct fb_info *info)
-{
-	smtcfb_setmode(info->par);
-
-	return 0;
-}
-
-static struct fb_ops smtcfb_ops = {
-	.owner        = THIS_MODULE,
-	.fb_check_var = smtc_check_var,
-	.fb_set_par   = smtc_set_par,
-	.fb_setcolreg = smtc_setcolreg,
-	.fb_blank     = smtc_blank,
-	.fb_fillrect  = cfb_fillrect,
-	.fb_imageblit = cfb_imageblit,
-	.fb_copyarea  = cfb_copyarea,
-#ifdef __BIG_ENDIAN
-	.fb_read      = smtcfb_read,
-	.fb_write     = smtcfb_write,
-#endif
-};
-
-/*
- * alloc struct smtcfb_info and assign default values
- */
-static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev)
-{
-	struct smtcfb_info *sfb;
-
-	sfb = kzalloc(sizeof(*sfb), GFP_KERNEL);
-
-	if (!sfb)
-		return NULL;
-
-	sfb->pdev = pdev;
-
-	sfb->fb.flags          = FBINFO_FLAG_DEFAULT;
-	sfb->fb.fbops          = &smtcfb_ops;
-	sfb->fb.fix            = smtcfb_fix;
-	sfb->fb.var            = smtcfb_var;
-	sfb->fb.pseudo_palette = sfb->colreg;
-	sfb->fb.par            = sfb;
-
-	return sfb;
-}
-
-/*
- * free struct smtcfb_info
- */
-static void smtc_free_fb_info(struct smtcfb_info *sfb)
-{
-	kfree(sfb);
-}
-
-/*
- * Unmap in the memory mapped IO registers
- */
-
-static void smtc_unmap_mmio(struct smtcfb_info *sfb)
-{
-	if (sfb && smtc_RegBaseAddress)
-		smtc_RegBaseAddress = NULL;
-}
-
-/*
- * Map in the screen memory
- */
-
-static int smtc_map_smem(struct smtcfb_info *sfb,
-		struct pci_dev *pdev, u_long smem_len)
-{
-
-	sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
-
-#ifdef __BIG_ENDIAN
-	if (sfb->fb.var.bits_per_pixel == 32)
-		sfb->fb.fix.smem_start += 0x800000;
-#endif
-
-	sfb->fb.fix.smem_len = smem_len;
-
-	sfb->fb.screen_base = sfb->lfb;
-
-	if (!sfb->fb.screen_base) {
-		dev_err(&pdev->dev,
-			"%s: unable to map screen memory\n", sfb->fb.fix.id);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-/*
- * Unmap in the screen memory
- *
- */
-static void smtc_unmap_smem(struct smtcfb_info *sfb)
-{
-	if (sfb && sfb->fb.screen_base) {
-		iounmap(sfb->fb.screen_base);
-		sfb->fb.screen_base = NULL;
-	}
-}
-
-/*
- * We need to wake up the device and make sure its in linear memory mode.
- */
-static inline void sm7xx_init_hw(void)
-{
-	outb_p(0x18, 0x3c4);
-	outb_p(0x11, 0x3c5);
-}
-
-static int smtcfb_pci_probe(struct pci_dev *pdev,
-				   const struct pci_device_id *ent)
-{
-	struct smtcfb_info *sfb;
-	u_long smem_size = 0x00800000;	/* default 8MB */
-	int err;
-	unsigned long mmio_base;
-
-	dev_info(&pdev->dev, "Silicon Motion display driver.");
-
-	err = pci_enable_device(pdev);	/* enable SMTC chip */
-	if (err)
-		return err;
-
-	sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
-
-	sfb = smtc_alloc_fb_info(pdev);
-
-	if (!sfb) {
-		err = -ENOMEM;
-		goto failed_free;
-	}
-
-	sfb->chip_id = ent->device;
-
-	pci_set_drvdata(pdev, sfb);
-
-	sm7xx_init_hw();
-
-	/* get mode parameter from smtc_scr_info */
-	if (smtc_scr_info.lfb_width != 0) {
-		sfb->fb.var.xres = smtc_scr_info.lfb_width;
-		sfb->fb.var.yres = smtc_scr_info.lfb_height;
-		sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth;
-	} else {
-		/* default resolution 1024x600 16bit mode */
-		sfb->fb.var.xres = SCREEN_X_RES;
-		sfb->fb.var.yres = SCREEN_Y_RES;
-		sfb->fb.var.bits_per_pixel = SCREEN_BPP;
-	}
-
-#ifdef __BIG_ENDIAN
-	if (sfb->fb.var.bits_per_pixel == 24)
-		sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
-#endif
-	/* Map address and memory detection */
-	mmio_base = pci_resource_start(pdev, 0);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
-
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-		sfb->fb.fix.mmio_start = mmio_base + 0x00400000;
-		sfb->fb.fix.mmio_len = 0x00400000;
-		smem_size = SM712_VIDEOMEMORYSIZE;
-#ifdef __BIG_ENDIAN
-		sfb->lfb = ioremap(mmio_base, 0x00c00000);
-#else
-		sfb->lfb = ioremap(mmio_base, 0x00800000);
-#endif
-		sfb->mmio = (smtc_RegBaseAddress =
-		    sfb->lfb + 0x00700000);
-		sfb->dp_regs = sfb->lfb + 0x00408000;
-		sfb->vp_regs = sfb->lfb + 0x0040c000;
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32) {
-			sfb->lfb += 0x800000;
-			dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb);
-		}
-#endif
-		if (!smtc_RegBaseAddress) {
-			dev_err(&pdev->dev,
-				"%s: unable to map memory mapped IO!",
-				sfb->fb.fix.id);
-			err = -ENOMEM;
-			goto failed_fb;
-		}
-
-		/* set MCLK = 14.31818 * (0x16 / 0x2) */
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x62, 0x3e);
-		/* enable PCI burst */
-		smtc_seqw(0x17, 0x20);
-		/* enable word swap */
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32)
-			smtc_seqw(0x17, 0x30);
-#endif
-		break;
-	case 0x720:
-		sfb->fb.fix.mmio_start = mmio_base;
-		sfb->fb.fix.mmio_len = 0x00200000;
-		smem_size = SM722_VIDEOMEMORYSIZE;
-		sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
-		sfb->lfb = sfb->dp_regs + 0x00200000;
-		sfb->mmio = (smtc_RegBaseAddress =
-		    sfb->dp_regs + 0x000c0000);
-		sfb->vp_regs = sfb->dp_regs + 0x800;
-
-		smtc_seqw(0x62, 0xff);
-		smtc_seqw(0x6a, 0x0d);
-		smtc_seqw(0x6b, 0x02);
-		break;
-	default:
-		dev_err(&pdev->dev,
-			"No valid Silicon Motion display chip was detected!");
-
-		goto failed_fb;
-	}
-
-	/* can support 32 bpp */
-	if (15 == sfb->fb.var.bits_per_pixel)
-		sfb->fb.var.bits_per_pixel = 16;
-
-	sfb->fb.var.xres_virtual = sfb->fb.var.xres;
-	sfb->fb.var.yres_virtual = sfb->fb.var.yres;
-	err = smtc_map_smem(sfb, pdev, smem_size);
-	if (err)
-		goto failed;
-
-	smtcfb_setmode(sfb);
-
-	err = register_framebuffer(&sfb->fb);
-	if (err < 0)
-		goto failed;
-
-	dev_info(&pdev->dev,
-		 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
-		 sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres,
-		 sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
-
-	return 0;
-
-failed:
-	dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");
-
-	smtc_unmap_smem(sfb);
-	smtc_unmap_mmio(sfb);
-failed_fb:
-	smtc_free_fb_info(sfb);
-
-failed_free:
-	pci_disable_device(pdev);
-
-	return err;
-}
-
-/*
- * 0x710 (LynxEM)
- * 0x712 (LynxEM+)
- * 0x720 (Lynx3DM, Lynx3DM+)
- */
-static const struct pci_device_id smtcfb_pci_table[] = {
-	{ PCI_DEVICE(0x126f, 0x710), },
-	{ PCI_DEVICE(0x126f, 0x712), },
-	{ PCI_DEVICE(0x126f, 0x720), },
-	{0,}
-};
-
-static void smtcfb_pci_remove(struct pci_dev *pdev)
-{
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-	smtc_unmap_smem(sfb);
-	smtc_unmap_mmio(sfb);
-	unregister_framebuffer(&sfb->fb);
-	smtc_free_fb_info(sfb);
-}
-
-#ifdef CONFIG_PM
-static int smtcfb_pci_suspend(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-
-	/* set the hw in sleep mode use external clock and self memory refresh
-	 * so that we can turn off internal PLLs later on
-	 */
-	smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
-	smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
-
-	console_lock();
-	fb_set_suspend(&sfb->fb, 1);
-	console_unlock();
-
-	/* additionally turn off all function blocks including internal PLLs */
-	smtc_seqw(0x21, 0xff);
-
-	return 0;
-}
-
-static int smtcfb_pci_resume(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-
-	/* reinit hardware */
-	sm7xx_init_hw();
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-		/* set MCLK = 14.31818 *  (0x16 / 0x2) */
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x62, 0x3e);
-		/* enable PCI burst */
-		smtc_seqw(0x17, 0x20);
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32)
-			smtc_seqw(0x17, 0x30);
-#endif
-		break;
-	case 0x720:
-		smtc_seqw(0x62, 0xff);
-		smtc_seqw(0x6a, 0x0d);
-		smtc_seqw(0x6b, 0x02);
-		break;
-	}
-
-	smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
-	smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
-
-	smtcfb_setmode(sfb);
-
-	console_lock();
-	fb_set_suspend(&sfb->fb, 0);
-	console_unlock();
-
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
-#define SM7XX_PM_OPS (&sm7xx_pm_ops)
-
-#else  /* !CONFIG_PM */
-
-#define SM7XX_PM_OPS NULL
-
-#endif /* !CONFIG_PM */
-
-static struct pci_driver smtcfb_driver = {
-	.name = "smtcfb",
-	.id_table = smtcfb_pci_table,
-	.probe = smtcfb_pci_probe,
-	.remove = smtcfb_pci_remove,
-	.driver.pm  = SM7XX_PM_OPS,
-};
-
-module_pci_driver(smtcfb_driver);
-
-MODULE_AUTHOR("Siliconmotion ");
-MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig
index 1b6d581c438b..b5e74e9de6bd 100644
--- a/drivers/staging/tidspbridge/Kconfig
+++ b/drivers/staging/tidspbridge/Kconfig
@@ -17,7 +17,7 @@ menuconfig TIDSPBRIDGE
 
 config TIDSPBRIDGE_DVFS
 	bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
-	depends on TIDSPBRIDGE && OMAP_PM_SRF && CPU_FREQ
+	depends on TIDSPBRIDGE && CPU_FREQ
 	help
 	  DVFS allows DSP Bridge to initiate the operating point change to
 	  scale the chip voltage and frequency in order to match the
diff --git a/drivers/staging/tidspbridge/dynload/tramp.c b/drivers/staging/tidspbridge/dynload/tramp.c
index 404af1895980..5f0431305fbb 100644
--- a/drivers/staging/tidspbridge/dynload/tramp.c
+++ b/drivers/staging/tidspbridge/dynload/tramp.c
@@ -503,7 +503,7 @@ static int priv_tgt_img_gen(struct dload_state *dlthis, u32 base,
  *	  TRAMPOLINES ARE TREATED AS 2ND PASS even though this is really
  *	  the first (and only) relocation that will be performed on them.
  */
-static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t * data,
+static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t *data,
 			 struct reloc_record_t *rp[], u32 relo_count)
 {
 	int ret_val = 1;
diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c
index 190ca3fe7327..2ae48c9a9362 100644
--- a/drivers/staging/tidspbridge/rmgr/dbdcd.c
+++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c
@@ -101,14 +101,14 @@ static int dcd_uuid_from_string(char *sz_uuid, struct dsp_uuid *uuid_obj)
 	 * if the converted value doesn't fit in u32. So, convert the
 	 * last six bytes to u64 and memcpy what is needed
 	 */
-	if(sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
+	if (sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
 	       &uuid_tmp.data1, &c, &uuid_tmp.data2, &c,
 	       &uuid_tmp.data3, &c, &uuid_tmp.data4,
 	       &uuid_tmp.data5, &c, &t) != 10)
 		return -EINVAL;
 
 	t = cpu_to_be64(t);
-	memcpy(&uuid_tmp.data6[0], ((char*)&t) + 2, 6);
+	memcpy(&uuid_tmp.data6[0], ((char *)&t) + 2, 6);
 	*uuid_obj = uuid_tmp;
 
 	return 0;
diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c
index be26917a6896..757ae20b38ee 100644
--- a/drivers/staging/tidspbridge/rmgr/drv.c
+++ b/drivers/staging/tidspbridge/rmgr/drv.c
@@ -738,7 +738,7 @@ void mem_ext_phys_pool_release(void)
  *     Allocate physically contiguous, uncached memory from external memory pool
  */
 
-static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 * phys_addr)
+static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 *phys_addr)
 {
 	u32 new_alloc_ptr;
 	u32 offset;
diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c
index ca3805046a73..7e10c9575b70 100644
--- a/drivers/staging/tidspbridge/rmgr/nldr.c
+++ b/drivers/staging/tidspbridge/rmgr/nldr.c
@@ -623,7 +623,7 @@ void nldr_delete(struct nldr_object *nldr_obj)
  *  ======== nldr_get_fxn_addr ========
  */
 int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj,
-			     char *str_fxn, u32 * addr)
+			     char *str_fxn, u32 *addr)
 {
 	struct dbll_sym_val *dbll_sym;
 	struct nldr_object *nldr_obj;
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index 87dfa92ab45b..c0211dd903a6 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -246,7 +246,7 @@ static void fill_stream_def(struct node_object *hnode,
 			    struct node_strmdef *pstrm_def,
 			    struct dsp_strmattr *pattrs);
 static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
 				  u32 phase);
 static int get_node_props(struct dcd_manager *hdcd_mgr,
 				 struct node_object *hnode,
@@ -1576,7 +1576,7 @@ func_end:
  *  Purpose:
  *      Frees the message buffer.
  */
-int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer,
+int node_free_msg_buf(struct node_object *hnode, u8 *pbuffer,
 			     struct dsp_bufferattr *pattr)
 {
 	struct node_object *pnode = (struct node_object *)hnode;
@@ -2640,7 +2640,7 @@ static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
  *  Purpose:
  *      Retrieves the address for create, execute or delete phase for a node.
  */
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
 				  u32 phase)
 {
 	char *pstr_fxn_name = NULL;
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index 886000980474..bd99e9e47e50 100644
--- a/drivers/staging/usbip/Kconfig
+++ b/drivers/staging/usbip/Kconfig
@@ -1,7 +1,6 @@
 config USBIP_CORE
 	tristate "USB/IP support"
 	depends on USB && NET
-	default N
 	---help---
 	  This enables pushing USB packets over IP to allow remote
 	  machines direct access to USB devices. It provides the
@@ -18,7 +17,6 @@ config USBIP_CORE
 config USBIP_VHCI_HCD
 	tristate "VHCI hcd"
 	depends on USBIP_CORE
-	default N
 	---help---
 	  This enables the USB/IP virtual host controller driver,
 	  which is run on the remote machine.
@@ -29,7 +27,6 @@ config USBIP_VHCI_HCD
 config USBIP_HOST
 	tristate "Host driver"
 	depends on USBIP_CORE
-	default N
 	---help---
 	  This enables the USB/IP host driver, which is run on the
 	  machine that is sharing the USB devices.
@@ -40,6 +37,5 @@ config USBIP_HOST
 config USBIP_DEBUG
 	bool "Debug messages for USB/IP"
 	depends on USBIP_CORE
-	default N
 	---help---
 	  This enables the debug messages from the USB/IP drivers.
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
index a73e437ec215..82e539a4fcff 100644
--- a/drivers/staging/usbip/stub.h
+++ b/drivers/staging/usbip/stub.h
@@ -93,7 +93,7 @@ struct bus_id_priv {
 extern struct kmem_cache *stub_priv_cache;
 
 /* stub_dev.c */
-extern struct usb_driver stub_driver;
+extern struct usb_device_driver stub_driver;
 
 /* stub_main.c */
 struct bus_id_priv *get_busid_priv(const char *busid);
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 76a1ff0e6275..60a3e3fe4dcb 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -87,13 +87,16 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
 	int sockfd = 0;
 	struct socket *socket;
 	ssize_t err = -EINVAL;
+	int rv;
 
 	if (!sdev) {
 		dev_err(dev, "sdev is null\n");
 		return -ENODEV;
 	}
 
-	sscanf(buf, "%d", &sockfd);
+	rv = sscanf(buf, "%d", &sockfd);
+	if (rv != 1)
+		return -EINVAL;
 
 	if (sockfd != -1) {
 		dev_info(dev, "stub up\n");
@@ -279,21 +282,19 @@ static void stub_device_unusable(struct usbip_device *ud)
  *
  * Allocates and initializes a new stub_device struct.
  */
-static struct stub_device *stub_device_alloc(struct usb_device *udev,
-					     struct usb_interface *interface)
+static struct stub_device *stub_device_alloc(struct usb_device *udev)
 {
 	struct stub_device *sdev;
-	int busnum = interface_to_busnum(interface);
-	int devnum = interface_to_devnum(interface);
+	int busnum = udev->bus->busnum;
+	int devnum = udev->devnum;
 
-	dev_dbg(&interface->dev, "allocating stub device");
+	dev_dbg(&udev->dev, "allocating stub device");
 
 	/* yes, it's a new device */
 	sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL);
 	if (!sdev)
 		return NULL;
 
-	sdev->interface = usb_get_intf(interface);
 	sdev->udev = usb_get_dev(udev);
 
 	/*
@@ -322,7 +323,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev,
 
 	usbip_start_eh(&sdev->ud);
 
-	dev_dbg(&interface->dev, "register new interface\n");
+	dev_dbg(&udev->dev, "register new device\n");
 
 	return sdev;
 }
@@ -332,32 +333,20 @@ static void stub_device_free(struct stub_device *sdev)
 	kfree(sdev);
 }
 
-/*
- * If a usb device has multiple active interfaces, this driver is bound to all
- * the active interfaces. However, usbip exports *a* usb device (i.e., not *an*
- * active interface). Currently, a userland program must ensure that it
- * looks at the usbip's sysfs entries of only the first active interface.
- *
- * TODO: use "struct usb_device_driver" to bind a usb device.
- * However, it seems it is not fully supported in mainline kernel yet
- * (2.6.19.2).
- */
-static int stub_probe(struct usb_interface *interface,
-		      const struct usb_device_id *id)
+static int stub_probe(struct usb_device *udev)
 {
-	struct usb_device *udev = interface_to_usbdev(interface);
 	struct stub_device *sdev = NULL;
-	const char *udev_busid = dev_name(interface->dev.parent);
-	int err = 0;
+	const char *udev_busid = dev_name(&udev->dev);
+	int err = 0, config;
 	struct bus_id_priv *busid_priv;
 
-	dev_dbg(&interface->dev, "Enter\n");
+	dev_dbg(&udev->dev, "Enter\n");
 
 	/* check we should claim or not by busid_table */
 	busid_priv = get_busid_priv(udev_busid);
 	if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
 	    (busid_priv->status == STUB_BUSID_OTHER)) {
-		dev_info(&interface->dev,
+		dev_info(&udev->dev,
 			"%s is not in match_busid table... skip!\n",
 			udev_busid);
 
@@ -383,60 +372,36 @@ static int stub_probe(struct usb_interface *interface,
 		return -ENODEV;
 	}
 
-	if (busid_priv->status == STUB_BUSID_ALLOC) {
-		sdev = busid_priv->sdev;
-		if (!sdev)
-			return -ENODEV;
-
-		busid_priv->interf_count++;
-		dev_info(&interface->dev,
-			"usbip-host: register new interface (bus %u dev %u ifn %u)\n",
-			udev->bus->busnum, udev->devnum,
-			interface->cur_altsetting->desc.bInterfaceNumber);
-
-		/* set private data to usb_interface */
-		usb_set_intfdata(interface, sdev);
-
-		err = stub_add_files(&interface->dev);
-		if (err) {
-			dev_err(&interface->dev, "stub_add_files for %s\n",
-				udev_busid);
-			usb_set_intfdata(interface, NULL);
-			busid_priv->interf_count--;
-			return err;
-		}
-
-		usb_get_intf(interface);
-		return 0;
-	}
-
 	/* ok, this is my device */
-	sdev = stub_device_alloc(udev, interface);
+	sdev = stub_device_alloc(udev);
 	if (!sdev)
 		return -ENOMEM;
 
-	dev_info(&interface->dev,
-		"usbip-host: register new device (bus %u dev %u ifn %u)\n",
-		udev->bus->busnum, udev->devnum,
-		interface->cur_altsetting->desc.bInterfaceNumber);
+	dev_info(&udev->dev,
+		"usbip-host: register new device (bus %u dev %u)\n",
+		udev->bus->busnum, udev->devnum);
 
-	busid_priv->interf_count = 0;
 	busid_priv->shutdown_busid = 0;
 
-	/* set private data to usb_interface */
-	usb_set_intfdata(interface, sdev);
-	busid_priv->interf_count++;
+	config = usb_choose_configuration(udev);
+	if (config >= 0) {
+		err = usb_set_configuration(udev, config);
+		if (err && err != -ENODEV)
+			dev_err(&udev->dev, "can't set config #%d, error %d\n",
+				config, err);
+	}
+
+	/* set private data to usb_device */
+	dev_set_drvdata(&udev->dev, sdev);
 	busid_priv->sdev = sdev;
 
-	err = stub_add_files(&interface->dev);
+	err = stub_add_files(&udev->dev);
 	if (err) {
-		dev_err(&interface->dev, "stub_add_files for %s\n", udev_busid);
-		usb_set_intfdata(interface, NULL);
-		usb_put_intf(interface);
+		dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
+		dev_set_drvdata(&udev->dev, NULL);
 		usb_put_dev(udev);
 		kthread_stop_put(sdev->ud.eh);
 
-		busid_priv->interf_count = 0;
 		busid_priv->sdev = NULL;
 		stub_device_free(sdev);
 		return err;
@@ -461,13 +426,13 @@ static void shutdown_busid(struct bus_id_priv *busid_priv)
  * called in usb_disconnect() or usb_deregister()
  * but only if actconfig(active configuration) exists
  */
-static void stub_disconnect(struct usb_interface *interface)
+static void stub_disconnect(struct usb_device *udev)
 {
 	struct stub_device *sdev;
-	const char *udev_busid = dev_name(interface->dev.parent);
+	const char *udev_busid = dev_name(&udev->dev);
 	struct bus_id_priv *busid_priv;
 
-	dev_dbg(&interface->dev, "Enter\n");
+	dev_dbg(&udev->dev, "Enter\n");
 
 	busid_priv = get_busid_priv(udev_busid);
 	if (!busid_priv) {
@@ -475,41 +440,29 @@ static void stub_disconnect(struct usb_interface *interface)
 		return;
 	}
 
-	sdev = usb_get_intfdata(interface);
+	sdev = dev_get_drvdata(&udev->dev);
 
 	/* get stub_device */
 	if (!sdev) {
-		dev_err(&interface->dev, "could not get device");
+		dev_err(&udev->dev, "could not get device");
 		return;
 	}
 
-	usb_set_intfdata(interface, NULL);
+	dev_set_drvdata(&udev->dev, NULL);
 
 	/*
 	 * NOTE: rx/tx threads are invoked for each usb_device.
 	 */
-	stub_remove_files(&interface->dev);
+	stub_remove_files(&udev->dev);
 
 	/* If usb reset is called from event handler */
-	if (busid_priv->sdev->ud.eh == current) {
-		busid_priv->interf_count--;
+	if (busid_priv->sdev->ud.eh == current)
 		return;
-	}
-
-	if (busid_priv->interf_count > 1) {
-		busid_priv->interf_count--;
-		shutdown_busid(busid_priv);
-		usb_put_intf(interface);
-		return;
-	}
-
-	busid_priv->interf_count = 0;
 
 	/* shutdown the current connection */
 	shutdown_busid(busid_priv);
 
 	usb_put_dev(sdev->udev);
-	usb_put_intf(interface);
 
 	/* free sdev */
 	busid_priv->sdev = NULL;
@@ -523,28 +476,34 @@ static void stub_disconnect(struct usb_interface *interface)
 	}
 }
 
-/*
- * Presence of pre_reset and post_reset prevents the driver from being unbound
- * when the device is being reset
- */
+#ifdef CONFIG_PM
 
-static int stub_pre_reset(struct usb_interface *interface)
+/* These functions need usb_port_suspend and usb_port_resume,
+ * which reside in drivers/usb/core/usb.h. Skip for now. */
+
+static int stub_suspend(struct usb_device *udev, pm_message_t message)
 {
-	dev_dbg(&interface->dev, "pre_reset\n");
+	dev_dbg(&udev->dev, "stub_suspend\n");
+
 	return 0;
 }
 
-static int stub_post_reset(struct usb_interface *interface)
+static int stub_resume(struct usb_device *udev, pm_message_t message)
 {
-	dev_dbg(&interface->dev, "post_reset\n");
+	dev_dbg(&udev->dev, "stub_resume\n");
+
 	return 0;
 }
 
-struct usb_driver stub_driver = {
+#endif	/* CONFIG_PM */
+
+struct usb_device_driver stub_driver = {
 	.name		= "usbip-host",
 	.probe		= stub_probe,
 	.disconnect	= stub_disconnect,
-	.id_table	= stub_table,
-	.pre_reset	= stub_pre_reset,
-	.post_reset	= stub_post_reset,
+#ifdef CONFIG_PM
+	.suspend	= stub_suspend,
+	.resume		= stub_resume,
+#endif
+	.supports_autosuspend	=	0,
 };
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index baf857f7cc88..bd7b83a9d758 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -254,7 +254,7 @@ static int __init usbip_host_init(void)
 		return -ENOMEM;
 	}
 
-	ret = usb_register(&stub_driver);
+	ret = usb_register_device_driver(&stub_driver, THIS_MODULE);
 	if (ret) {
 		pr_err("usb_register failed %d\n", ret);
 		goto err_usb_register;
@@ -271,7 +271,7 @@ static int __init usbip_host_init(void)
 	return ret;
 
 err_create_file:
-	usb_deregister(&stub_driver);
+	usb_deregister_device_driver(&stub_driver);
 err_usb_register:
 	kmem_cache_destroy(stub_priv_cache);
 	return ret;
@@ -286,7 +286,7 @@ static void __exit usbip_host_exit(void)
 	 * deregister() calls stub_disconnect() for all devices. Device
 	 * specific data is cleared in stub_disconnect().
 	 */
-	usb_deregister(&stub_driver);
+	usb_deregister_device_driver(&stub_driver);
 
 	kmem_cache_destroy(stub_priv_cache);
 }
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index 5d1d4a183300..76e44d949232 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -550,7 +550,7 @@ static void stub_rx_pdu(struct usbip_device *ud)
 	int ret;
 	struct usbip_header pdu;
 	struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-	struct device *dev = &sdev->interface->dev;
+	struct device *dev = &sdev->udev->dev;
 
 	usbip_dbg_stub_rx("Enter\n");
 
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 96552e3a1bfb..4a2aab16b10c 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -99,26 +99,8 @@ static void usbip_dump_usb_device(struct usb_device *udev)
 	struct device *dev = &udev->dev;
 	int i;
 
-	dev_dbg(dev, "       devnum(%d) devpath(%s) ",
-		udev->devnum, udev->devpath);
-
-	switch (udev->speed) {
-	case USB_SPEED_HIGH:
-		pr_debug("SPD_HIGH ");
-		break;
-	case USB_SPEED_FULL:
-		pr_debug("SPD_FULL ");
-		break;
-	case USB_SPEED_LOW:
-		pr_debug("SPD_LOW ");
-		break;
-	case USB_SPEED_UNKNOWN:
-		pr_debug("SPD_UNKNOWN ");
-		break;
-	default:
-		pr_debug("SPD_ERROR ");
-		break;
-	}
+	dev_dbg(dev, "       devnum(%d) devpath(%s) usb speed(%s)",
+		udev->devnum, udev->devpath, usb_speed_string(udev->speed));
 
 	pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport);
 
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
index 66f03cc62ac6..6620d185d4bf 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
@@ -23,6 +23,8 @@ static const struct speed_string speed_strings[] = {
 	{ USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
 	{ USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
 	{ USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
+	{ USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
+	{ USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
 	{ 0, NULL, NULL }
 };
 
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
index 938ad1c36947..2cb81b3b35f7 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
@@ -14,6 +14,7 @@
 
 #include <syslog.h>
 #include <unistd.h>
+#include <linux/usb/ch9.h>
 
 #ifndef USBIDS_FILE
 #define USBIDS_FILE "/usr/share/hwdata/usb.ids"
@@ -76,13 +77,6 @@ extern int usbip_use_debug ;
 		abort();				\
 	} while (0)
 
-enum usb_device_speed {
-	USB_SPEED_UNKNOWN = 0,                  /* enumerating */
-	USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
-	USB_SPEED_HIGH,                         /* usb 2.0 */
-	USB_SPEED_VARIABLE                      /* wireless (usb 2.5) */
-};
-
 /* FIXME: how to sync with drivers/usbip_common.h ? */
 enum usbip_device_status {
 	/* sdev is available. */
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
index 71a449cf50db..35b2f5b0e350 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -32,7 +32,6 @@ struct usbip_host_driver *host_driver;
 
 #define SYSFS_OPEN_RETRIES 100
 
-/* only the first interface value is true! */
 static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
 {
 	char attrpath[SYSFS_PATH_MAX];
@@ -56,8 +55,8 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
 	 * usbip_status to reappear.
 	 */
 
-	snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
-		 udev->path, udev->busid, udev->bConfigurationValue, 0);
+	snprintf(attrpath, SYSFS_PATH_MAX, "%s/usbip_status",
+		 udev->path);
 
 	while (retries > 0) {
 		if (stat(attrpath, &s) == 0)
@@ -102,6 +101,7 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
 static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
 {
 	struct usbip_exported_device *edev = NULL;
+	struct usbip_exported_device *edev_old;
 	size_t size;
 	int i;
 
@@ -127,8 +127,10 @@ static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
 	size = sizeof(*edev) + edev->udev.bNumInterfaces *
 		sizeof(struct usbip_usb_interface);
 
+	edev_old = edev;
 	edev = realloc(edev, size);
 	if (!edev) {
+		edev = edev_old;
 		dbg("realloc failed");
 		goto err;
 	}
@@ -168,19 +170,18 @@ static void delete_nothing(void *unused_data)
 
 static int refresh_exported_devices(void)
 {
-	/* sysfs_device of usb_interface */
-	struct sysfs_device	*suintf;
-	struct dlist		*suintf_list;
 	/* sysfs_device of usb_device */
 	struct sysfs_device	*sudev;
 	struct dlist		*sudev_list;
+	struct dlist		*sudev_unique_list;
 	struct usbip_exported_device *edev;
 
-	sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device),
-					   delete_nothing);
+	sudev_unique_list = dlist_new_with_delete(sizeof(struct sysfs_device),
+						  delete_nothing);
 
-	suintf_list = sysfs_get_driver_devices(host_driver->sysfs_driver);
-	if (!suintf_list) {
+	sudev_list = sysfs_get_driver_devices(host_driver->sysfs_driver);
+
+	if (!sudev_list) {
 		/*
 		 * Not an error condition. There are simply no devices bound to
 		 * the driver yet.
@@ -190,23 +191,13 @@ static int refresh_exported_devices(void)
 		return 0;
 	}
 
-	/* collect unique USB devices (not interfaces) */
-	dlist_for_each_data(suintf_list, suintf, struct sysfs_device) {
-		/* get usb device of this usb interface */
-		sudev = sysfs_get_device_parent(suintf);
-		if (!sudev) {
-			dbg("sysfs_get_device_parent failed: %s", suintf->name);
-			continue;
-		}
+	dlist_for_each_data(sudev_list, sudev, struct sysfs_device)
+		if (check_new(sudev_unique_list, sudev))
+			dlist_unshift(sudev_unique_list, sudev);
 
-		if (check_new(sudev_list, sudev)) {
-			/* insert item at head of list */
-			dlist_unshift(sudev_list, sudev);
-		}
-	}
-
-	dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
+	dlist_for_each_data(sudev_unique_list, sudev, struct sysfs_device) {
 		edev = usbip_exported_device_new(sudev->path);
+
 		if (!edev) {
 			dbg("usbip_exported_device_new failed");
 			continue;
@@ -216,7 +207,7 @@ static int refresh_exported_devices(void)
 		host_driver->ndevs++;
 	}
 
-	dlist_destroy(sudev_list);
+	dlist_destroy(sudev_unique_list);
 
 	return 0;
 }
@@ -356,9 +347,8 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
 	}
 
 	/* only the first interface is true */
-	snprintf(attr_path, sizeof(attr_path), "%s/%s:%d.%d/%s",
-		 edev->udev.path, edev->udev.busid,
-		 edev->udev.bConfigurationValue, 0, attr_name);
+	snprintf(attr_path, sizeof(attr_path), "%s/%s",
+		 edev->udev.path, attr_name);
 
 	attr = sysfs_open_attribute(attr_path);
 	if (!attr) {
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index 209df9b37cb4..d80d37c64cb3 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -339,27 +339,67 @@ err:
 	return -1;
 }
 
-static int read_record(int rhport, char *host, char *port, char *busid)
+/*
+ * Read the given port's record.
+ *
+ * To avoid buffer overflow we will read the entire line and
+ * validate each part's size. The initial buffer is padded by 4 to
+ * accommodate the 2 spaces, 1 newline and an additional character
+ * which is needed to properly validate the 3rd part without it being
+ * truncated to an acceptable length.
+ */
+static int read_record(int rhport, char *host, unsigned long host_len,
+		char *port, unsigned long port_len, char *busid)
+
 {
+	int part;
 	FILE *file;
 	char path[PATH_MAX+1];
+	char *buffer, *start, *end;
+	char delim[] = {' ', ' ', '\n'};
+	int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
+	size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
+
+	buffer = malloc(buffer_len);
+	if (!buffer)
+		return -1;
 
 	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
 
 	file = fopen(path, "r");
 	if (!file) {
 		err("fopen");
+		free(buffer);
 		return -1;
 	}
 
-	if (fscanf(file, "%s %s %s\n", host, port, busid) != 3) {
-		err("fscanf");
+	if (fgets(buffer, buffer_len, file) == NULL) {
+		err("fgets");
+		free(buffer);
 		fclose(file);
 		return -1;
 	}
-
 	fclose(file);
 
+	/* validate the length of each of the 3 parts */
+	start = buffer;
+	for (part = 0; part < 3; part++) {
+		end = strchr(start, delim[part]);
+		if (end == NULL || (end - start) > max_len[part]) {
+			free(buffer);
+			return -1;
+		}
+		start = end + 1;
+	}
+
+	if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
+		err("sscanf");
+		free(buffer);
+		return -1;
+	}
+
+	free(buffer);
+
 	return 0;
 }
 
@@ -505,7 +545,7 @@ int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
 		return -1;
 	}
 
-	snprintf(buff, sizeof(buff), "%u %u %u %u",
+	snprintf(buff, sizeof(buff), "%u %d %u %u",
 			port, sockfd, devid, speed);
 	dbg("writing: %s", buff);
 
@@ -573,7 +613,8 @@ int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
 	if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
 		return 0;
 
-	ret = read_record(idev->port, host, serv, remote_busid);
+	ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
+			  remote_busid);
 	if (ret) {
 		err("read_record");
 		read_record_error = 1;
diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c
index 9ecaf6e574df..8cfd2dbd9510 100644
--- a/drivers/staging/usbip/userspace/src/usbip_bind.c
+++ b/drivers/staging/usbip/userspace/src/usbip_bind.c
@@ -52,12 +52,8 @@ static int bind_usbip(char *busid)
 	char attr_name[] = "bind";
 	char sysfs_mntpath[SYSFS_PATH_MAX];
 	char bind_attr_path[SYSFS_PATH_MAX];
-	char intf_busid[SYSFS_BUS_ID_SIZE];
-	struct sysfs_device *busid_dev;
 	struct sysfs_attribute *bind_attr;
-	struct sysfs_attribute *bConfValue;
-	struct sysfs_attribute *bNumIntfs;
-	int i, failed = 0;
+	int failed = 0;
 	int rc, ret = -1;
 
 	rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
@@ -76,39 +72,15 @@ static int bind_usbip(char *busid)
 		return -1;
 	}
 
-	busid_dev = sysfs_open_device(bus_type, busid);
-	if (!busid_dev) {
-		dbg("sysfs_open_device %s failed: %s", busid, strerror(errno));
-		goto err_close_bind_attr;
-	}
-
-	bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue");
-	bNumIntfs  = sysfs_get_device_attr(busid_dev, "bNumInterfaces");
-
-	if (!bConfValue || !bNumIntfs) {
-		dbg("problem getting device attributes: %s",
-		    strerror(errno));
-		goto err_close_busid_dev;
-	}
-
-	for (i = 0; i < atoi(bNumIntfs->value); i++) {
-		snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid,
-			 bConfValue->value, i);
-
-		rc = sysfs_write_attribute(bind_attr, intf_busid,
-					   SYSFS_BUS_ID_SIZE);
-		if (rc < 0) {
-			dbg("bind driver at %s failed", intf_busid);
-			failed = 1;
-		}
+	rc = sysfs_write_attribute(bind_attr, busid, SYSFS_BUS_ID_SIZE);
+	if (rc < 0) {
+		dbg("bind driver at %s failed", busid);
+		failed = 1;
 	}
 
 	if (!failed)
 		ret = 0;
 
-err_close_busid_dev:
-	sysfs_close_device(busid_dev);
-err_close_bind_attr:
 	sysfs_close_attribute(bind_attr);
 
 	return ret;
@@ -118,15 +90,12 @@ err_close_bind_attr:
 static int unbind_other(char *busid)
 {
 	char bus_type[] = "usb";
-	char intf_busid[SYSFS_BUS_ID_SIZE];
 	struct sysfs_device *busid_dev;
-	struct sysfs_device *intf_dev;
-	struct sysfs_driver *intf_drv;
+	struct sysfs_device *dev;
+	struct sysfs_driver *drv;
 	struct sysfs_attribute *unbind_attr;
-	struct sysfs_attribute *bConfValue;
 	struct sysfs_attribute *bDevClass;
-	struct sysfs_attribute *bNumIntfs;
-	int i, rc;
+	int rc;
 	enum unbind_status status = UNBIND_ST_OK;
 
 	busid_dev = sysfs_open_device(bus_type, busid);
@@ -134,12 +103,11 @@ static int unbind_other(char *busid)
 		dbg("sysfs_open_device %s failed: %s", busid, strerror(errno));
 		return -1;
 	}
+	dbg("busid path: %s", busid_dev->path);
 
-	bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue");
 	bDevClass  = sysfs_get_device_attr(busid_dev, "bDeviceClass");
-	bNumIntfs  = sysfs_get_device_attr(busid_dev, "bNumInterfaces");
-	if (!bConfValue || !bDevClass || !bNumIntfs) {
-		dbg("problem getting device attributes: %s",
+	if (!bDevClass) {
+		dbg("problem getting device attribute: %s",
 		    strerror(errno));
 		goto err_close_busid_dev;
 	}
@@ -149,62 +117,62 @@ static int unbind_other(char *busid)
 		goto err_close_busid_dev;
 	}
 
-	for (i = 0; i < atoi(bNumIntfs->value); i++) {
-		snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid,
-			 bConfValue->value, i);
-		intf_dev = sysfs_open_device(bus_type, intf_busid);
-		if (!intf_dev) {
-			dbg("could not open interface device: %s",
-			    strerror(errno));
-			goto err_close_busid_dev;
-		}
-
-		dbg("%s -> %s", intf_dev->name,  intf_dev->driver_name);
+	dev = sysfs_open_device(bus_type, busid);
+	if (!dev) {
+		dbg("could not open device: %s",
+				strerror(errno));
+		goto err_close_busid_dev;
+	}
 
-		if (!strncmp("unknown", intf_dev->driver_name, SYSFS_NAME_LEN))
-			/* unbound interface */
-			continue;
+	dbg("%s -> %s", dev->name,  dev->driver_name);
 
-		if (!strncmp(USBIP_HOST_DRV_NAME, intf_dev->driver_name,
-			     SYSFS_NAME_LEN)) {
-			/* already bound to usbip-host */
-			status = UNBIND_ST_USBIP_HOST;
-			continue;
-		}
+	if (!strncmp("unknown", dev->driver_name, SYSFS_NAME_LEN)) {
+		/* unbound interface */
+		sysfs_close_device(dev);
+		goto out;
+	}
 
-		/* unbinding */
-		intf_drv = sysfs_open_driver(bus_type, intf_dev->driver_name);
-		if (!intf_drv) {
-			dbg("could not open interface driver on %s: %s",
-			    intf_dev->name, strerror(errno));
-			goto err_close_intf_dev;
-		}
+	if (!strncmp(USBIP_HOST_DRV_NAME, dev->driver_name,
+				SYSFS_NAME_LEN)) {
+		/* already bound to usbip-host */
+		status = UNBIND_ST_USBIP_HOST;
+		sysfs_close_device(dev);
+		goto out;
+	}
 
-		unbind_attr = sysfs_get_driver_attr(intf_drv, "unbind");
-		if (!unbind_attr) {
-			dbg("problem getting interface driver attribute: %s",
-			    strerror(errno));
-			goto err_close_intf_drv;
-		}
+	/* unbinding */
+	drv = sysfs_open_driver(bus_type, dev->driver_name);
+	if (!drv) {
+		dbg("could not open device driver on %s: %s",
+				dev->name, strerror(errno));
+		goto err_close_intf_dev;
+	}
+	dbg("device driver: %s", drv->path);
 
-		rc = sysfs_write_attribute(unbind_attr, intf_dev->bus_id,
-					   SYSFS_BUS_ID_SIZE);
-		if (rc < 0) {
-			/* NOTE: why keep unbinding other interfaces? */
-			dbg("unbind driver at %s failed", intf_dev->bus_id);
-			status = UNBIND_ST_FAILED;
-		}
+	unbind_attr = sysfs_get_driver_attr(drv, "unbind");
+	if (!unbind_attr) {
+		dbg("problem getting device driver attribute: %s",
+				strerror(errno));
+		goto err_close_intf_drv;
+	}
 
-		sysfs_close_driver(intf_drv);
-		sysfs_close_device(intf_dev);
+	rc = sysfs_write_attribute(unbind_attr, dev->bus_id,
+			SYSFS_BUS_ID_SIZE);
+	if (rc < 0) {
+		/* NOTE: why keep unbinding other interfaces? */
+		dbg("unbind driver at %s failed", dev->bus_id);
+		status = UNBIND_ST_FAILED;
 	}
 
+	sysfs_close_driver(drv);
+	sysfs_close_device(dev);
+
 	goto out;
 
 err_close_intf_drv:
-	sysfs_close_driver(intf_drv);
+	sysfs_close_driver(drv);
 err_close_intf_dev:
-	sysfs_close_device(intf_dev);
+	sysfs_close_device(dev);
 err_close_busid_dev:
 	status = UNBIND_ST_FAILED;
 out:
diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c
index 237e099337a1..8864fa2a7f0b 100644
--- a/drivers/staging/usbip/userspace/src/usbip_list.c
+++ b/drivers/staging/usbip/userspace/src/usbip_list.c
@@ -52,9 +52,8 @@ static int get_exported_devices(char *host, int sockfd)
 	struct op_devlist_reply reply;
 	uint16_t code = OP_REP_DEVLIST;
 	struct usbip_usb_device udev;
-	struct usbip_usb_interface uintf;
 	unsigned int i;
-	int j, rc;
+	int rc;
 
 	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
 	if (rc < 0) {
@@ -104,22 +103,6 @@ static int get_exported_devices(char *host, int sockfd)
 		printf("%11s: %s\n", "", udev.path);
 		printf("%11s: %s\n", "", class_name);
 
-		for (j = 0; j < udev.bNumInterfaces; j++) {
-			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
-			if (rc < 0) {
-				dbg("usbip_net_recv failed: usbip_usb_intf[%d]",
-				    j);
-
-				return -1;
-			}
-			usbip_net_pack_usb_interface(0, &uintf);
-
-			usbip_names_get_class(class_name, sizeof(class_name),
-					      uintf.bInterfaceClass,
-					      uintf.bInterfaceSubClass,
-					      uintf.bInterfaceProtocol);
-			printf("%11s: %2d - %s\n", "", j, class_name);
-		}
 		printf("\n");
 	}
 
diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c
index d5a9ab6af2a6..cace87838c24 100644
--- a/drivers/staging/usbip/userspace/src/usbip_unbind.c
+++ b/drivers/staging/usbip/userspace/src/usbip_unbind.c
@@ -47,12 +47,10 @@ static int unbind_device(char *busid)
 	int verified = 0;
 	int rc, ret = -1;
 
-	char attr_name[] = "bConfigurationValue";
+	char attr_name[] = "unbind";
 	char sysfs_mntpath[SYSFS_PATH_MAX];
-	char busid_attr_path[SYSFS_PATH_MAX];
-	struct sysfs_attribute *busid_attr;
-	char *val = NULL;
-	int len;
+	char unbind_attr_path[SYSFS_PATH_MAX];
+	struct sysfs_attribute *unbind_attr;
 
 	/* verify the busid device is using usbip-host */
 	usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME);
@@ -99,55 +97,34 @@ static int unbind_device(char *busid)
 		return -1;
 	}
 
-	snprintf(busid_attr_path, sizeof(busid_attr_path), "%s/%s/%s/%s/%s/%s",
-		 sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DEVICES_NAME,
-		 busid, attr_name);
+	snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
+		 sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
+		 USBIP_HOST_DRV_NAME, attr_name);
 
 	/* read a device attribute */
-	busid_attr = sysfs_open_attribute(busid_attr_path);
-	if (!busid_attr) {
+	unbind_attr = sysfs_open_attribute(unbind_attr_path);
+	if (!unbind_attr) {
 		err("could not open %s/%s: %s", busid, attr_name,
 		    strerror(errno));
 		return -1;
 	}
 
-	if (sysfs_read_attribute(busid_attr) < 0) {
-		err("problem reading attribute: %s", strerror(errno));
-		goto err_out;
-	}
-
-	len = busid_attr->len;
-	val = malloc(len);
-	*val = *busid_attr->value;
-	sysfs_close_attribute(busid_attr);
-
 	/* notify driver of unbind */
 	rc = modify_match_busid(busid, 0);
 	if (rc < 0) {
 		err("unable to unbind device on %s", busid);
-		goto err_out;
-	}
-
-	/* write the device attribute */
-	busid_attr = sysfs_open_attribute(busid_attr_path);
-	if (!busid_attr) {
-		err("could not open %s/%s: %s", busid, attr_name,
-		    strerror(errno));
-		return -1;
 	}
 
-	rc = sysfs_write_attribute(busid_attr, val, len);
-	if (rc < 0) {
-		err("problem writing attribute: %s", strerror(errno));
-		goto err_out;
-	}
-	sysfs_close_attribute(busid_attr);
+	rc = sysfs_write_attribute(unbind_attr, busid,
+				   SYSFS_BUS_ID_SIZE);
+		if (rc < 0) {
+			dbg("bind driver at %s failed", busid);
+		}
+	sysfs_close_attribute(unbind_attr);
 
 	ret = 0;
 	printf("unbind device on busid %s: complete\n", busid);
 
-err_out:
-	free(val);
 err_close_usbip_host_drv:
 	sysfs_close_driver(usbip_host_drv);
 
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index 7980f8b5517b..c2b3ced9ca6e 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -159,9 +159,7 @@ static int send_reply_devlist(int connfd)
 {
 	struct usbip_exported_device *edev;
 	struct usbip_usb_device pdu_udev;
-	struct usbip_usb_interface pdu_uinf;
 	struct op_devlist_reply reply;
-	int i;
 	int rc;
 
 	reply.ndev = 0;
@@ -196,19 +194,6 @@ static int send_reply_devlist(int connfd)
 			dbg("usbip_net_send failed: pdu_udev");
 			return -1;
 		}
-
-		for (i = 0; i < edev->udev.bNumInterfaces; i++) {
-			dump_usb_interface(&edev->uinf[i]);
-			memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
-			usbip_net_pack_usb_interface(1, &pdu_uinf);
-
-			rc = usbip_net_send(connfd, &pdu_uinf,
-					    sizeof(pdu_uinf));
-			if (rc < 0) {
-				dbg("usbip_net_send failed: pdu_uinf");
-				return -1;
-			}
-		}
 	}
 
 	return 0;
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index 72391ef87646..adb6201479dc 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -205,8 +205,6 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
 		}
 	}
 
-	pr_info("changed %d\n", changed);
-
 	if ((hcd->state == HC_STATE_SUSPENDED) && (changed == 1))
 		usb_hcd_resume_root_hub(hcd);
 
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 0141bc34d5cc..03e6edf46e7c 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -215,8 +215,9 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 	}
 
-	dev_info(dev, "rhport(%u) sockfd(%d) devid(%u) speed(%u)\n",
-		 rhport, sockfd, devid, speed);
+	dev_info(dev,
+		 "rhport(%u) sockfd(%d) devid(%u) speed(%u) speed_str(%s)\n",
+		 rhport, sockfd, devid, speed, usb_speed_string(speed));
 
 	vdev->devid         = devid;
 	vdev->speed         = speed;
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
index c3017a74fa0f..f843e50875f9 100644
--- a/drivers/staging/vt6656/card.h
+++ b/drivers/staging/vt6656/card.h
@@ -39,13 +39,6 @@ typedef enum _CARD_PHY_TYPE {
     PHY_TYPE_11A
 } CARD_PHY_TYPE, *PCARD_PHY_TYPE;
 
-typedef enum _CARD_OP_MODE {
-    OP_MODE_INFRASTRUCTURE = 0,
-    OP_MODE_ADHOC,
-    OP_MODE_AP,
-    OP_MODE_UNKNOWN
-} CARD_OP_MODE, *PCARD_OP_MODE;
-
 #define CB_MAX_CHANNEL_24G  14
 #define CB_MAX_CHANNEL_5G       42 /* add channel9(5045MHz), 41==>42 */
 #define CB_MAX_CHANNEL      (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G)
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index 1f422574c3d8..e2abe3ddd244 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -158,10 +158,10 @@ typedef enum __device_msg_level {
 /*
  * Enum of context types for SendPacket
  */
-typedef enum _CONTEXT_TYPE {
-    CONTEXT_DATA_PACKET = 1,
-    CONTEXT_MGMT_PACKET
-} CONTEXT_TYPE;
+enum {
+	CONTEXT_DATA_PACKET = 1,
+	CONTEXT_MGMT_PACKET
+};
 
 /* RCB (Receive Control Block) */
 struct vnt_rcb {
@@ -180,9 +180,7 @@ struct vnt_usb_send_context {
 	struct sk_buff *pPacket;
 	struct urb *pUrb;
 	unsigned int uBufLen;
-	CONTEXT_TYPE Type;
-	struct ethhdr sEthHeader;
-	void *Next;
+	u8 type;
 	bool bBoolInUse;
 	unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS];
 };
@@ -206,29 +204,10 @@ typedef struct _DEFAULT_CONFIG {
 /*
  * Structure to keep track of USB interrupt packets
  */
-typedef struct {
-    unsigned int            uDataLen;
-    u8 *           pDataBuf;
-  /* struct urb *pUrb; */
-    bool            bInUse;
-} INT_BUFFER, *PINT_BUFFER;
-
-/* 0:11A 1:11B 2:11G */
-typedef enum _VIA_BB_TYPE
-{
-    BB_TYPE_11A = 0,
-    BB_TYPE_11B,
-    BB_TYPE_11G
-} VIA_BB_TYPE, *PVIA_BB_TYPE;
-
-/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga(OFDM in BasicRate) */
-typedef enum _VIA_PKT_TYPE
-{
-    PK_TYPE_11A = 0,
-    PK_TYPE_11B,
-    PK_TYPE_11GB,
-    PK_TYPE_11GA
-} VIA_PKT_TYPE, *PVIA_PKT_TYPE;
+struct vnt_interrupt_buffer {
+	u8 *data_buf;
+	bool in_use;
+};
 
 /*++ NDIS related */
 
@@ -297,16 +276,6 @@ typedef struct tagSPMKIDCandidateEvent {
     PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST];
 } SPMKIDCandidateEvent, *PSPMKIDCandidateEvent;
 
-/*++ 802.11h related */
-#define MAX_QUIET_COUNT     8
-
-typedef struct tagSQuietControl {
-    bool        bEnable;
-    u32       dwStartTime;
-    u8        byPeriod;
-    u16        wDuration;
-} SQuietControl, *PSQuietControl;
-
 /* The receive duplicate detection cache entry */
 typedef struct tagSCacheEntry{
     u16        wFmSequence;
@@ -386,8 +355,6 @@ struct vnt_private {
 
 	OPTIONS sOpts;
 
-	struct tasklet_struct CmdWorkItem;
-	struct tasklet_struct EventWorkItem;
 	struct work_struct read_work_item;
 	struct work_struct rx_mng_work_item;
 
@@ -437,29 +404,11 @@ struct vnt_private {
 	struct vnt_tx_pkt_info pkt_info[16];
 
 	/* Variables to track resources for the Interrupt In Pipe */
-	INT_BUFFER intBuf;
-	int fKillEventPollingThread;
-	int bEventAvailable;
+	struct vnt_interrupt_buffer int_buf;
 
 	/* default config from file by user setting */
 	DEFAULT_CONFIG config_file;
 
-	/* Statistic for USB */
-	unsigned long ulBulkInPosted;
-	unsigned long ulBulkInError;
-	unsigned long ulBulkInContCRCError;
-	unsigned long ulBulkInBytesRead;
-
-	unsigned long ulBulkOutPosted;
-	unsigned long ulBulkOutError;
-	unsigned long ulBulkOutContCRCError;
-	unsigned long ulBulkOutBytesWrite;
-
-	unsigned long ulIntInPosted;
-	unsigned long ulIntInError;
-	unsigned long ulIntInContCRCError;
-	unsigned long ulIntInBytesRead;
-
 	/* Version control */
 	u16 wFirmwareVersion;
 	u8 byLocalID;
@@ -480,11 +429,6 @@ struct vnt_private {
 	int bExistSWNetAddr;
 
 	/* Maintain statistical debug info. */
-	unsigned long packetsReceived;
-	unsigned long packetsReceivedDropped;
-	unsigned long packetsReceivedOverflow;
-	unsigned long packetsSent;
-	unsigned long packetsSentDropped;
 	unsigned long SendContextsInUse;
 	unsigned long RcvBuffersInUse;
 
@@ -549,8 +493,8 @@ struct vnt_private {
 	u8  byCWMaxMin;
 
 	/* Rate */
-	VIA_BB_TYPE byBBType; /* 0: 11A, 1:11B, 2:11G */
-	VIA_PKT_TYPE byPacketType; /* 0:11a 1:11b 2:11gb 3:11ga */
+	u8 byBBType; /* 0: 11A, 1:11B, 2:11G */
+	u8 byPacketType; /* 0:11a 1:11b 2:11gb 3:11ga */
 	u16 wBasicRate;
 	u8 byACKRate;
 	u8 byTopOFDMBasicRate;
@@ -588,7 +532,9 @@ struct vnt_private {
 	u16 wFragmentationThreshold;
 	u8 byShortRetryLimit;
 	u8 byLongRetryLimit;
-	CARD_OP_MODE eOPMode;
+
+	enum nl80211_iftype op_mode;
+
 	int bBSSIDFilter;
 	u16 wMaxTransmitMSDULifetime;
 	u8 abyBSSID[ETH_ALEN];
@@ -807,5 +753,6 @@ struct vnt_private {
                                  (fMP_DISCONNECTED | fMP_RESET_IN_PROGRESS | fMP_HALT_IN_PROGRESS | fMP_INIT_IN_PROGRESS | fMP_SURPRISE_REMOVED)) == 0)
 
 int device_alloc_frag_buf(struct vnt_private *, PSDeFragControlBlock pDeF);
+void vnt_configure_filter(struct vnt_private *);
 
 #endif
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index eca04c0c1d97..4ccaa7e29a1c 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -627,7 +627,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB,
 
     // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps
     if (pDevice->bDiversityEnable && (FrameSize>50) &&
-       (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
+	pDevice->op_mode == NL80211_IFTYPE_STATION &&
        (pDevice->bLinkPass == true)) {
         BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0);
     }
@@ -1227,14 +1227,13 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
     if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) {
        if (pMgmt->sNodeDBTable[0].bPSEnable) {
 
-           skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
+	    skbcpy = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
 
         // if any node in PS mode, buffer packet until DTIM.
            if (skbcpy == NULL) {
                DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n");
            }
            else {
-               skbcpy->dev = pDevice->dev;
                skbcpy->len = FrameSize;
                memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize);
                skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy);
@@ -1295,63 +1294,66 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
 
 void RXvWorkItem(struct work_struct *work)
 {
-	struct vnt_private *pDevice =
+	struct vnt_private *priv =
 		container_of(work, struct vnt_private, read_work_item);
-	int ntStatus;
-	struct vnt_rcb *pRCB = NULL;
+	int status;
+	struct vnt_rcb *rcb = NULL;
 
-	if (pDevice->Flags & fMP_DISCONNECTED)
+	if (priv->Flags & fMP_DISCONNECTED)
 		return;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
-    spin_lock_irq(&pDevice->lock);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
 
-    while ((pDevice->Flags & fMP_POST_READS) &&
-            MP_IS_READY(pDevice) &&
-            (pDevice->NumRecvFreeList != 0) ) {
-        pRCB = pDevice->FirstRecvFreeList;
-        pDevice->NumRecvFreeList--;
-        DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList);
-        ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB);
-    }
-    pDevice->bIsRxWorkItemQueued = false;
-    spin_unlock_irq(&pDevice->lock);
+	spin_lock_irq(&priv->lock);
+
+	while ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+			(priv->NumRecvFreeList != 0)) {
+		rcb = priv->FirstRecvFreeList;
+
+		priv->NumRecvFreeList--;
+
+		DequeueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList);
+
+		status = PIPEnsBulkInUsbRead(priv, rcb);
+	}
 
+	priv->bIsRxWorkItemQueued = false;
+
+	spin_unlock_irq(&priv->lock);
 }
 
-void RXvFreeRCB(struct vnt_rcb *pRCB, int bReAllocSkb)
+void RXvFreeRCB(struct vnt_rcb *rcb, int re_alloc_skb)
 {
-	struct vnt_private *pDevice = pRCB->pDevice;
+	struct vnt_private *priv = rcb->pDevice;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
 
-	if (bReAllocSkb == false) {
-		kfree_skb(pRCB->skb);
-		bReAllocSkb = true;
+	if (re_alloc_skb == false) {
+		kfree_skb(rcb->skb);
+		re_alloc_skb = true;
 	}
 
-    if (bReAllocSkb == true) {
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        // todo error handling
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to re-alloc rx skb\n");
-        }else {
-            pRCB->skb->dev = pDevice->dev;
-        }
-    }
-    //
-    // Insert the RCB back in the Recv free list
-    //
-    EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-    pDevice->NumRecvFreeList++;
+	if (re_alloc_skb == true) {
+		rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+		/* TODO error handling */
+		if (!rcb->skb) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				" Failed to re-alloc rx skb\n");
+		}
+	}
 
-    if ((pDevice->Flags & fMP_POST_READS) && MP_IS_READY(pDevice) &&
-        (pDevice->bIsRxWorkItemQueued == false) ) {
+	/* Insert the RCB back in the Recv free list */
+	EnqueueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList, rcb);
+	priv->NumRecvFreeList++;
 
-        pDevice->bIsRxWorkItemQueued = true;
-	schedule_work(&pDevice->read_work_item);
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList);
+	if ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+			(priv->bIsRxWorkItemQueued == false)) {
+		priv->bIsRxWorkItemQueued = true;
+		schedule_work(&priv->read_work_item);
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",
+			priv->NumRecvFreeList, priv->NumRecvMngList);
 }
 
 void RXvMngWorkItem(struct work_struct *work)
diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c
index e0e93869a681..cca56b2f243d 100644
--- a/drivers/staging/vt6656/int.c
+++ b/drivers/staging/vt6656/int.c
@@ -70,119 +70,117 @@ void INTvWorkItem(struct vnt_private *pDevice)
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Interrupt Polling Thread\n");
 
 	spin_lock_irq(&pDevice->lock);
-	if (pDevice->fKillEventPollingThread != true)
-		ntStatus = PIPEnsInterruptRead(pDevice);
+
+	ntStatus = PIPEnsInterruptRead(pDevice);
+
 	spin_unlock_irq(&pDevice->lock);
 }
 
-void INTnsProcessData(struct vnt_private *pDevice)
+void INTnsProcessData(struct vnt_private *priv)
 {
-	PSINTData pINTData;
-	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
-	struct net_device_stats *pStats = &pDevice->stats;
+	struct vnt_interrupt_data *int_data;
+	struct vnt_manager *mgmt = &priv->vnt_mgmt;
+	struct net_device_stats *stats = &priv->stats;
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n");
 
-	pINTData = (PSINTData) pDevice->intBuf.pDataBuf;
-	if (pINTData->byTSR0 & TSR_VALID) {
-		if (pINTData->byTSR0 & (TSR_TMO | TSR_RETRYTMO))
-			pDevice->wstats.discard.retries++;
+	int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
+
+	if (int_data->tsr0 & TSR_VALID) {
+		if (int_data->tsr0 & (TSR_TMO | TSR_RETRYTMO))
+			priv->wstats.discard.retries++;
 		else
-			pStats->tx_packets++;
+			stats->tx_packets++;
 
-		BSSvUpdateNodeTxCounter(pDevice,
-					pINTData->byTSR0,
-					pINTData->byPkt0);
-		/*DBG_PRN_GRP01(("TSR0 %02x\n", pINTData->byTSR0));*/
+		BSSvUpdateNodeTxCounter(priv,
+					int_data->tsr0,
+					int_data->pkt0);
 	}
-	if (pINTData->byTSR1 & TSR_VALID) {
-		if (pINTData->byTSR1 & (TSR_TMO | TSR_RETRYTMO))
-			pDevice->wstats.discard.retries++;
+
+	if (int_data->tsr1 & TSR_VALID) {
+		if (int_data->tsr1 & (TSR_TMO | TSR_RETRYTMO))
+			priv->wstats.discard.retries++;
 		else
-			pStats->tx_packets++;
+			stats->tx_packets++;
 
 
-		BSSvUpdateNodeTxCounter(pDevice,
-					pINTData->byTSR1,
-					pINTData->byPkt1);
-		/*DBG_PRN_GRP01(("TSR1 %02x\n", pINTData->byTSR1));*/
+		BSSvUpdateNodeTxCounter(priv,
+					int_data->tsr1,
+					int_data->pkt1);
 	}
-	if (pINTData->byTSR2 & TSR_VALID) {
-		if (pINTData->byTSR2 & (TSR_TMO | TSR_RETRYTMO))
-			pDevice->wstats.discard.retries++;
+
+	if (int_data->tsr2 & TSR_VALID) {
+		if (int_data->tsr2 & (TSR_TMO | TSR_RETRYTMO))
+			priv->wstats.discard.retries++;
 		else
-			pStats->tx_packets++;
+			stats->tx_packets++;
 
-		BSSvUpdateNodeTxCounter(pDevice,
-					pINTData->byTSR2,
-					pINTData->byPkt2);
-		/*DBG_PRN_GRP01(("TSR2 %02x\n", pINTData->byTSR2));*/
+		BSSvUpdateNodeTxCounter(priv,
+					int_data->tsr2,
+					int_data->pkt2);
 	}
-	if (pINTData->byTSR3 & TSR_VALID) {
-		if (pINTData->byTSR3 & (TSR_TMO | TSR_RETRYTMO))
-			pDevice->wstats.discard.retries++;
+
+	if (int_data->tsr3 & TSR_VALID) {
+		if (int_data->tsr3 & (TSR_TMO | TSR_RETRYTMO))
+			priv->wstats.discard.retries++;
 		else
-			pStats->tx_packets++;
+			stats->tx_packets++;
 
-		BSSvUpdateNodeTxCounter(pDevice,
-					pINTData->byTSR3,
-					pINTData->byPkt3);
-		/*DBG_PRN_GRP01(("TSR3 %02x\n", pINTData->byTSR3));*/
+		BSSvUpdateNodeTxCounter(priv,
+					int_data->tsr3,
+					int_data->pkt3);
 	}
-	if (pINTData->byISR0 != 0) {
-		if (pINTData->byISR0 & ISR_BNTX) {
-			if (pDevice->eOPMode == OP_MODE_AP) {
-				if (pMgmt->byDTIMCount > 0) {
-					pMgmt->byDTIMCount--;
-					pMgmt->sNodeDBTable[0].bRxPSPoll =
+
+	if (int_data->isr0 != 0) {
+		if (int_data->isr0 & ISR_BNTX) {
+			if (priv->op_mode == NL80211_IFTYPE_AP) {
+				if (mgmt->byDTIMCount > 0) {
+					mgmt->byDTIMCount--;
+					mgmt->sNodeDBTable[0].bRxPSPoll =
 						false;
-				} else if (pMgmt->byDTIMCount == 0) {
+				} else if (mgmt->byDTIMCount == 0) {
 					/* check if multicast tx buffering */
-					pMgmt->byDTIMCount =
-						pMgmt->byDTIMPeriod-1;
-					pMgmt->sNodeDBTable[0].bRxPSPoll = true;
-					if (pMgmt->sNodeDBTable[0].bPSEnable)
-						bScheduleCommand((void *) pDevice,
+					mgmt->byDTIMCount =
+						mgmt->byDTIMPeriod-1;
+					mgmt->sNodeDBTable[0].bRxPSPoll = true;
+					if (mgmt->sNodeDBTable[0].bPSEnable)
+						bScheduleCommand((void *) priv,
 								 WLAN_CMD_RX_PSPOLL,
 								 NULL);
 				}
-				bScheduleCommand((void *) pDevice,
+				bScheduleCommand((void *) priv,
 						WLAN_CMD_BECON_SEND,
 						NULL);
-			} /* if (pDevice->eOPMode == OP_MODE_AP) */
-		pDevice->bBeaconSent = true;
+			}
+			priv->bBeaconSent = true;
 		} else {
-			pDevice->bBeaconSent = false;
+			priv->bBeaconSent = false;
 		}
-		if (pINTData->byISR0 & ISR_TBTT) {
-			if (pDevice->bEnablePSMode)
-				bScheduleCommand((void *) pDevice,
+
+		if (int_data->isr0 & ISR_TBTT) {
+			if (priv->bEnablePSMode)
+				bScheduleCommand((void *) priv,
 						WLAN_CMD_TBTT_WAKEUP,
 						NULL);
-			if (pDevice->bChannelSwitch) {
-				pDevice->byChannelSwitchCount--;
-				if (pDevice->byChannelSwitchCount == 0)
-					bScheduleCommand((void *) pDevice,
+			if (priv->bChannelSwitch) {
+				priv->byChannelSwitchCount--;
+				if (priv->byChannelSwitchCount == 0)
+					bScheduleCommand((void *) priv,
 							WLAN_CMD_11H_CHSW,
 							NULL);
 			}
 		}
-		pDevice->qwCurrTSF = cpu_to_le64(pINTData->qwTSF);
-		/*DBG_PRN_GRP01(("ISR0 = %02x ,
-		  LoTsf =  %08x,
-		  HiTsf =  %08x\n",
-		  pINTData->byISR0,
-		  pINTData->dwLoTSF,
-		  pINTData->dwHiTSF)); */
+		priv->qwCurrTSF = le64_to_cpu(int_data->tsf);
 	}
-	if (pINTData->byISR1 != 0)
-		if (pINTData->byISR1 & ISR_GPIO3)
-			bScheduleCommand((void *) pDevice,
+
+	if (int_data->isr1 != 0)
+		if (int_data->isr1 & ISR_GPIO3)
+			bScheduleCommand((void *) priv,
 					WLAN_CMD_RADIO,
 					NULL);
-	pDevice->intBuf.uDataLen = 0;
-	pDevice->intBuf.bInUse = false;
 
-	pStats->tx_errors = pDevice->wstats.discard.retries;
-	pStats->tx_dropped = pDevice->wstats.discard.retries;
+	priv->int_buf.in_use = false;
+
+	stats->tx_errors = priv->wstats.discard.retries;
+	stats->tx_dropped = priv->wstats.discard.retries;
 }
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 8e6e217ba4ff..08db868e1d07 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -32,29 +32,28 @@
 
 #include "device.h"
 
-typedef struct tagSINTData {
-	u8 byTSR0;
-	u8 byPkt0;
-	u16 wTime0;
-	u8 byTSR1;
-	u8 byPkt1;
-	u16 wTime1;
-	u8 byTSR2;
-	u8 byPkt2;
-	u16 wTime2;
-	u8 byTSR3;
-	u8 byPkt3;
-	u16 wTime3;
-	u64 qwTSF;
-	u8 byISR0;
-	u8 byISR1;
-	u8 byRTSSuccess;
-	u8 byRTSFail;
-	u8 byACKFail;
-	u8 byFCSErr;
-	u8 abySW[2];
-} __attribute__ ((__packed__))
-SINTData, *PSINTData;
+struct vnt_interrupt_data {
+	u8 tsr0;
+	u8 pkt0;
+	u16 time0;
+	u8 tsr1;
+	u8 pkt1;
+	u16 time1;
+	u8 tsr2;
+	u8 pkt2;
+	u16 time2;
+	u8 tsr3;
+	u8 pkt3;
+	u16 time3;
+	__le64 tsf;
+	u8 isr0;
+	u8 isr1;
+	u8 rts_success;
+	u8 rts_fail;
+	u8 ack_fail;
+	u8 fcs_err;
+	u8 sw[2];
+} __packed;
 
 void INTvWorkItem(struct vnt_private *);
 void INTnsProcessData(struct vnt_private *);
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index 3a68dfa23d84..60264a655f24 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -41,6 +41,7 @@
 #include "wpactl.h"
 #include "control.h"
 #include "rndis.h"
+#include "baseband.h"
 
 static const long frequency_list[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
@@ -57,7 +58,7 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
 	struct vnt_private *pDevice = netdev_priv(dev);
 	long ldBm;
 
-	pDevice->wstats.status = pDevice->eOPMode;
+	pDevice->wstats.status = pDevice->op_mode;
 	RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm);
 	pDevice->wstats.qual.level = ldBm;
 	pDevice->wstats.qual.noise = 0;
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index 54414ed27191..3ce19ddbc569 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -47,25 +47,19 @@ static int          msglevel                =MSG_LEVEL_INFO;
  *
  * Parameters:
  *  In:
- *      uByteidx    - Index of Mask
- *      byData      - Mask Value to write
+ *	mc_filter (mac filter)
  *  Out:
  *      none
  *
  * Return Value: none
  *
  */
-void MACvWriteMultiAddr(struct vnt_private *pDevice, u32 uByteIdx, u8 byData)
+void MACvWriteMultiAddr(struct vnt_private *pDevice, u64 mc_filter)
 {
-	u8 byData1;
+	__le64 le_mc = cpu_to_le64(mc_filter);
 
-    byData1 = byData;
-    CONTROLnsRequestOut(pDevice,
-                        MESSAGE_TYPE_WRITE,
-                        (u16) (MAC_REG_MAR0 + uByteIdx),
-                        MESSAGE_REQUEST_MACREG,
-                        1,
-                        &byData1);
+	CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, MAC_REG_MAR0,
+		MESSAGE_REQUEST_MACREG, sizeof(le_mc), (u8 *)&le_mc);
 }
 
 /*
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index 0db1be5b01c8..4053e431ef99 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -403,7 +403,7 @@
 #define MAC_REVISION_A0     0x00
 #define MAC_REVISION_A1     0x01
 
-void MACvWriteMultiAddr(struct vnt_private *, u32, u8);
+void MACvWriteMultiAddr(struct vnt_private *, u64);
 void MACbShutdown(struct vnt_private *);
 void MACvSetBBType(struct vnt_private *, u8);
 void MACvDisableKeyEntry(struct vnt_private *, u32);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 58edcae74efc..7dd885fe2010 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -256,7 +256,7 @@ device_set_options(struct vnt_private *pDevice) {
     pDevice->byShortPreamble = PREAMBLE_TYPE_DEF;
     pDevice->ePSMode = PS_MODE_DEF;
     pDevice->b11hEnable = X80211h_MODE_DEF;
-    pDevice->eOPMode = OP_MODE_DEF;
+    pDevice->op_mode = NL80211_IFTYPE_UNSPECIFIED;
     pDevice->uConnectionRate = DATA_RATE_DEF;
     if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
     pDevice->byBBType = BBP_TYPE_DEF;
@@ -409,7 +409,7 @@ static int device_init_registers(struct vnt_private *pDevice)
 
 		if (pDevice->abyCCKPwrTbl[ii] == 0)
 			pDevice->abyCCKPwrTbl[ii] = pDevice->byCCKPwr;
-			pDevice->abyOFDMPwrTbl[ii] =
+		pDevice->abyOFDMPwrTbl[ii] =
 				pDevice->abyEEPROM[ii + EEP_OFS_OFDM_PWR_TBL];
 		if (pDevice->abyOFDMPwrTbl[ii] == 0)
 			pDevice->abyOFDMPwrTbl[ii] = pDevice->byOFDMPwrG;
@@ -749,44 +749,47 @@ err_nomem:
 	return rc;
 }
 
-static void device_free_tx_bufs(struct vnt_private *pDevice)
+static void device_free_tx_bufs(struct vnt_private *priv)
 {
-	struct vnt_usb_send_context *pTxContext;
-    int ii;
+	struct vnt_usb_send_context *tx_context;
+	int ii;
 
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
+	for (ii = 0; ii < priv->cbTD; ii++) {
+		tx_context = priv->apTD[ii];
+		/* deallocate URBs */
+		if (tx_context->pUrb) {
+			usb_kill_urb(tx_context->pUrb);
+			usb_free_urb(tx_context->pUrb);
+		}
 
-        pTxContext = pDevice->apTD[ii];
-	/* deallocate URBs */
-        if (pTxContext->pUrb) {
-            usb_kill_urb(pTxContext->pUrb);
-            usb_free_urb(pTxContext->pUrb);
-        }
-        kfree(pTxContext);
-    }
-    return;
+		kfree(tx_context);
+	}
+
+	return;
 }
 
-static void device_free_rx_bufs(struct vnt_private *pDevice)
+static void device_free_rx_bufs(struct vnt_private *priv)
 {
-	struct vnt_rcb *pRCB;
+	struct vnt_rcb *rcb;
 	int ii;
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
+	for (ii = 0; ii < priv->cbRD; ii++) {
+		rcb = priv->apRCB[ii];
 
-        pRCB = pDevice->apRCB[ii];
-	/* deallocate URBs */
-        if (pRCB->pUrb) {
-            usb_kill_urb(pRCB->pUrb);
-            usb_free_urb(pRCB->pUrb);
-        }
-	/* deallocate skb */
-        if (pRCB->skb)
-            dev_kfree_skb(pRCB->skb);
-    }
-    kfree(pDevice->pRCBMem);
+		/* deallocate URBs */
+		if (rcb->pUrb) {
+			usb_kill_urb(rcb->pUrb);
+			usb_free_urb(rcb->pUrb);
+		}
 
-    return;
+		/* deallocate skb */
+		if (rcb->skb)
+			dev_kfree_skb(rcb->skb);
+	}
+
+	kfree(priv->pRCBMem);
+
+	return;
 }
 
 static void usb_device_reset(struct vnt_private *pDevice)
@@ -798,95 +801,109 @@ static void usb_device_reset(struct vnt_private *pDevice)
 	return ;
 }
 
-static void device_free_int_bufs(struct vnt_private *pDevice)
+static void device_free_int_bufs(struct vnt_private *priv)
 {
-    kfree(pDevice->intBuf.pDataBuf);
-    return;
+	kfree(priv->int_buf.data_buf);
+
+	return;
 }
 
-static bool device_alloc_bufs(struct vnt_private *pDevice)
+static bool device_alloc_bufs(struct vnt_private *priv)
 {
-	struct vnt_usb_send_context *pTxContext;
-	struct vnt_rcb *pRCB;
+	struct vnt_usb_send_context *tx_context;
+	struct vnt_rcb *rcb;
 	int ii;
 
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
+	for (ii = 0; ii < priv->cbTD; ii++) {
+		tx_context = kmalloc(sizeof(struct vnt_usb_send_context),
+								GFP_KERNEL);
+		if (tx_context == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				"%s : allocate tx usb context failed\n",
+					priv->dev->name);
+			goto free_tx;
+		}
 
-	pTxContext = kmalloc(sizeof(struct vnt_usb_send_context), GFP_KERNEL);
-        if (pTxContext == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate tx usb context failed\n", pDevice->dev->name);
-            goto free_tx;
-        }
-        pDevice->apTD[ii] = pTxContext;
-	pTxContext->pDevice = (void *) pDevice;
-	/* allocate URBs */
-        pTxContext->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
-        if (pTxContext->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "alloc tx urb failed\n");
-            goto free_tx;
-        }
-        pTxContext->bBoolInUse = false;
-    }
+		priv->apTD[ii] = tx_context;
+		tx_context->pDevice = priv;
+
+		/* allocate URBs */
+		tx_context->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (tx_context->pUrb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR,
+				KERN_ERR "alloc tx urb failed\n");
+			goto free_tx;
+		}
+
+		tx_context->bBoolInUse = false;
+	}
 
-    /* allocate RCB mem */
-	pDevice->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * pDevice->cbRD),
+	/* allocate RCB mem */
+	priv->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * priv->cbRD),
 								GFP_KERNEL);
-    if (pDevice->pRCBMem == NULL) {
-        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name);
-        goto free_tx;
-    }
+	if (priv->pRCBMem == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s : alloc rx usb context failed\n",
+				priv->dev->name);
+		goto free_tx;
+	}
 
-    pDevice->FirstRecvFreeList = NULL;
-    pDevice->LastRecvFreeList = NULL;
-    pDevice->FirstRecvMngList = NULL;
-    pDevice->LastRecvMngList = NULL;
-    pDevice->NumRecvFreeList = 0;
+	priv->FirstRecvFreeList = NULL;
+	priv->LastRecvFreeList = NULL;
+	priv->FirstRecvMngList = NULL;
+	priv->LastRecvMngList = NULL;
+	priv->NumRecvFreeList = 0;
 
-	pRCB = (struct vnt_rcb *)pDevice->pRCBMem;
+	rcb = (struct vnt_rcb *)priv->pRCBMem;
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
+	for (ii = 0; ii < priv->cbRD; ii++) {
+		priv->apRCB[ii] = rcb;
+		rcb->pDevice = priv;
 
-        pDevice->apRCB[ii] = pRCB;
-	pRCB->pDevice = (void *) pDevice;
-	/* allocate URBs */
-        pRCB->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+		/* allocate URBs */
+		rcb->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (rcb->pUrb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				" Failed to alloc rx urb\n");
+			goto free_rx_tx;
+		}
 
-        if (pRCB->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx urb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx skb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb->dev = pDevice->dev;
-        pRCB->bBoolInUse = false;
-        EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-        pDevice->NumRecvFreeList++;
-        pRCB++;
-    }
+		rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+		if (rcb->skb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+						" Failed to alloc rx skb\n");
+			goto free_rx_tx;
+		}
+
+		rcb->bBoolInUse = false;
+
+		EnqueueRCB(priv->FirstRecvFreeList,
+						priv->LastRecvFreeList, rcb);
 
-	pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
-	if (pDevice->pInterruptURB == NULL) {
-	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n");
-	    goto free_rx_tx;
+		priv->NumRecvFreeList++;
+		rcb++;
 	}
 
-    pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
-	if (pDevice->intBuf.pDataBuf == NULL) {
-	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n");
-	    usb_free_urb(pDevice->pInterruptURB);
-	    goto free_rx_tx;
+	priv->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
+	if (priv->pInterruptURB == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int urb\n");
+		goto free_rx_tx;
 	}
 
-    return true;
+	priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
+	if (priv->int_buf.data_buf == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int buf\n");
+		usb_free_urb(priv->pInterruptURB);
+		goto free_rx_tx;
+	}
+
+	return true;
 
 free_rx_tx:
-    device_free_rx_bufs(pDevice);
+	device_free_rx_bufs(priv);
 
 free_tx:
-    device_free_tx_bufs(pDevice);
+	device_free_tx_bufs(priv);
 
 	return false;
 }
@@ -931,13 +948,11 @@ static void device_free_frag_bufs(struct vnt_private *pDevice)
 int device_alloc_frag_buf(struct vnt_private *pDevice,
 		PSDeFragControlBlock pDeF)
 {
+	pDeF->skb = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
+	if (!pDeF->skb)
+		return false;
 
-    pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-    if (pDeF->skb == NULL)
-        return false;
-    pDeF->skb->dev = pDevice->dev;
-
-    return true;
+	return true;
 }
 
 static int  device_open(struct net_device *dev)
@@ -974,8 +989,6 @@ static int  device_open(struct net_device *dev)
 		goto free_all;
 	}
 
-    device_set_multi(pDevice->dev);
-
     /* init for key management */
     KeyvInitTable(pDevice,&pDevice->sKey);
 	memcpy(pDevice->vnt_mgmt.abyMACAddr,
@@ -992,16 +1005,12 @@ static int  device_open(struct net_device *dev)
 
     vMgrObjectInit(pDevice);
 
-    tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice);
-
 	schedule_delayed_work(&pDevice->second_callback_work, HZ);
 
 	pDevice->int_interval = 100;  /* max 100 microframes */
     pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
     pDevice->bIsRxWorkItemQueued = true;
-    pDevice->fKillEventPollingThread = false;
-    pDevice->bEventAvailable = false;
 
    pDevice->bWPADEVUp = false;
      pDevice->bwextstep0 = false;
@@ -1084,7 +1093,6 @@ static int device_close(struct net_device *dev)
     MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
     MP_CLEAR_FLAG(pDevice, fMP_POST_WRITES);
     MP_CLEAR_FLAG(pDevice, fMP_POST_READS);
-    pDevice->fKillEventPollingThread = true;
 
 	cancel_delayed_work_sync(&pDevice->run_command_work);
 	cancel_delayed_work_sync(&pDevice->second_callback_work);
@@ -1098,8 +1106,6 @@ static int device_close(struct net_device *dev)
 	cancel_work_sync(&pDevice->rx_mng_work_item);
 	cancel_work_sync(&pDevice->read_work_item);
 
-    tasklet_kill(&pDevice->EventWorkItem);
-
    pDevice->bRoaming = false;
    pDevice->bIsRoaming = false;
    pDevice->bEnableRoaming = false;
@@ -1350,69 +1356,73 @@ static int Read_config_file(struct vnt_private *pDevice)
 
 static void device_set_multi(struct net_device *dev)
 {
-	struct vnt_private *pDevice = netdev_priv(dev);
-	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
+	struct vnt_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	if (priv->flags & DEVICE_FLAGS_OPENED) {
+		spin_lock_irqsave(&priv->lock, flags);
+
+		bScheduleCommand(priv, WLAN_CMD_CONFIGURE_FILTER, NULL);
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+}
+
+void vnt_configure_filter(struct vnt_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	struct vnt_manager *mgmt = &priv->vnt_mgmt;
 	struct netdev_hw_addr *ha;
-	u32 mc_filter[2];
-	int ii;
-	u8 pbyData[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	u8 byTmpMode = 0;
+	u64 mc_filter = 0;
+	u8 tmp = 0;
 	int rc;
 
-	spin_lock_irq(&pDevice->lock);
-    rc = CONTROLnsRequestIn(pDevice,
-                            MESSAGE_TYPE_READ,
-                            MAC_REG_RCR,
-                            MESSAGE_REQUEST_MACREG,
-                            1,
-                            &byTmpMode
-                            );
-    if (rc == 0) pDevice->byRxMode = byTmpMode;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode in= %x\n", pDevice->byRxMode);
-
-    if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
-        DBG_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
-	/* unconditionally log net taps */
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
-    }
-    else if ((netdev_mc_count(dev) > pDevice->multicast_limit) ||
-	     (dev->flags & IFF_ALLMULTI)) {
-        CONTROLnsRequestOut(pDevice,
-                            MESSAGE_TYPE_WRITE,
-                            MAC_REG_MAR0,
-                            MESSAGE_REQUEST_MACREG,
-                            8,
-                            pbyData
-                            );
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-    }
-    else {
-        memset(mc_filter, 0, sizeof(mc_filter));
-	netdev_for_each_mc_addr(ha, dev) {
-            int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-            mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
-        }
-        for (ii = 0; ii < 4; ii++) {
-             MACvWriteMultiAddr(pDevice, ii, *((u8 *)&mc_filter[0] + ii));
-             MACvWriteMultiAddr(pDevice, ii+ 4, *((u8 *)&mc_filter[1] + ii));
-        }
-        pDevice->byRxMode &= ~(RCR_UNICAST);
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-    }
+	rc = CONTROLnsRequestIn(priv, MESSAGE_TYPE_READ,
+		MAC_REG_RCR, MESSAGE_REQUEST_MACREG, 1, &tmp);
+	if (rc == 0)
+		priv->byRxMode = tmp;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "priv->byRxMode in= %x\n",
+							priv->byRxMode);
+
+	if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
+		DBG_PRT(MSG_LEVEL_ERR, KERN_NOTICE
+			"%s: Promiscuous mode enabled.\n", dev->name);
+		/* unconditionally log net taps */
+		priv->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
+	} else if ((netdev_mc_count(dev) > priv->multicast_limit) ||
+			(dev->flags & IFF_ALLMULTI)) {
+		mc_filter = ~0x0;
+		MACvWriteMultiAddr(priv, mc_filter);
+
+		priv->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+	} else {
+		netdev_for_each_mc_addr(ha, dev) {
+			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 
-    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-	/*
-	 * If AP mode, don't enable RCR_UNICAST since HW only compares
-	 * addr1 with local MAC
-	 */
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-        pDevice->byRxMode &= ~(RCR_UNICAST);
-    }
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, pDevice->byRxMode);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode out= %x\n", pDevice->byRxMode);
-	spin_unlock_irq(&pDevice->lock);
+			mc_filter |= 1ULL << (bit_nr & 0x3f);
+		}
+
+		MACvWriteMultiAddr(priv, mc_filter);
+
+		priv->byRxMode &= ~(RCR_UNICAST);
+		priv->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+	}
+
+	if (mgmt->eConfigMode == WMAC_CONFIG_AP) {
+		/*
+		 * If AP mode, don't enable RCR_UNICAST since HW only compares
+		 * addr1 with local MAC
+		 */
+		priv->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+		priv->byRxMode &= ~(RCR_UNICAST);
+	}
+
+	ControlvWriteByte(priv, MESSAGE_REQUEST_MACREG,
+					MAC_REG_RCR, priv->byRxMode);
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"priv->byRxMode out= %x\n", priv->byRxMode);
 }
 
 static struct net_device_stats *device_get_stats(struct net_device *dev)
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index e7d5487d1041..cd4f5bd2029f 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -67,7 +67,7 @@ void PSvEnablePowerSaving(struct vnt_private *pDevice, u16 wListenInterval)
 	/* set period of power up before TBTT */
 	MACvWriteWord(pDevice, MAC_REG_PWBT, C_PWBT);
 
-	if (pDevice->eOPMode != OP_MODE_ADHOC) {
+	if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) {
 		/* set AID */
 		MACvWriteWord(pDevice, MAC_REG_AIDATIM, wAID);
 	} else {
@@ -106,7 +106,7 @@ void PSvEnablePowerSaving(struct vnt_private *pDevice, u16 wListenInterval)
 	pDevice->bEnablePSMode = true;
 
 	/* We don't send null pkt in ad hoc mode since beacon will handle this. */
-	if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
+	if (pDevice->op_mode == NL80211_IFTYPE_STATION)
 		PSbSendNullPacket(pDevice);
 
 	pDevice->bPWBitOn = true;
@@ -137,7 +137,7 @@ void PSvDisablePowerSaving(struct vnt_private *pDevice)
 	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
 	pDevice->bEnablePSMode = false;
 
-	if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
+	if (pDevice->op_mode == NL80211_IFTYPE_STATION)
 		PSbSendNullPacket(pDevice);
 
 	pDevice->bPWBitOn = false;
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 51fff896fcb5..7083af32e43c 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -553,12 +553,13 @@ static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
 	rts->duration = duration;
 	rts->frame_control = TYPE_CTL_RTS;
 
-	if (priv->eOPMode == OP_MODE_ADHOC || priv->eOPMode == OP_MODE_AP)
+	if (priv->op_mode == NL80211_IFTYPE_ADHOC ||
+				priv->op_mode == NL80211_IFTYPE_AP)
 		memcpy(rts->ra, eth_hdr->h_dest, ETH_ALEN);
 	else
 		memcpy(rts->ra, priv->abyBSSID, ETH_ALEN);
 
-	if (priv->eOPMode == OP_MODE_AP)
+	if (priv->op_mode == NL80211_IFTYPE_AP)
 		memcpy(rts->ta, priv->abyBSSID, ETH_ALEN);
 	else
 		memcpy(rts->ta, eth_hdr->h_source, ETH_ALEN);
@@ -991,8 +992,8 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     //Set packet type
     pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8);
 
-	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-			(pDevice->eOPMode == OP_MODE_AP)) {
+	if (pDevice->op_mode == NL80211_IFTYPE_ADHOC ||
+			pDevice->op_mode == NL80211_IFTYPE_AP) {
 		if (is_multicast_ether_addr(psEthHeader->h_dest)) {
 			bNeedACK = false;
 			pTxBufHead->wFIFOCtl =
@@ -1292,7 +1293,7 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice,
 
 	pMACHeader->frame_control = TYPE_802_11_DATA;
 
-    if (pDevice->eOPMode == OP_MODE_AP) {
+    if (pDevice->op_mode == NL80211_IFTYPE_AP) {
 	memcpy(&(pMACHeader->addr1[0]),
 	       &(psEthHeader->h_dest[0]),
 	       ETH_ALEN);
@@ -1302,7 +1303,7 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice,
 	       ETH_ALEN);
         pMACHeader->frame_control |= FC_FROMDS;
     } else {
-	if (pDevice->eOPMode == OP_MODE_ADHOC) {
+	if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
 		memcpy(&(pMACHeader->addr1[0]),
 		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
@@ -1541,8 +1542,8 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
         pbyIVHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
         pbyPayloadHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
         do {
-            if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
-                (pDevice->bLinkPass == true)) {
+	    if (pDevice->op_mode == NL80211_IFTYPE_STATION &&
+					pDevice->bLinkPass == true) {
                 pbyBSSID = pDevice->abyBSSID;
                 // get pairwise key
                 if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
@@ -1560,7 +1561,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
             pbyBSSID = pDevice->abyBroadcastAddr;
             if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
                 pTransmitKey = NULL;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->op_mode);
             } else {
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
             }
@@ -1609,7 +1610,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -1701,7 +1702,7 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
     pTX_Buffer->byType = 0x01;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     PIPEnsSendBulkOut(pDevice,pContext);
@@ -2049,7 +2050,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -2305,7 +2306,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
         }
     }
     else {
-        if (pDevice->eOPMode == OP_MODE_ADHOC) {
+	if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
             // Adhoc Tx rate decided from node DB
 	    if (is_multicast_ether_addr(pDevice->sTxEthHeader.h_dest)) {
                 // Multicast use highest data rate
@@ -2336,7 +2337,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
                 }
             }
         }
-        if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
+	if (pDevice->op_mode == NL80211_IFTYPE_STATION) {
             // Infra STA rate decided from AP Node, index = 0
             pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
         }
@@ -2439,11 +2440,11 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-			&pContext->sEthHeader.h_dest[0],
+			&pDevice->sTxEthHeader.h_dest[0],
 			(u16)(BytesToWrite-uHeaderLen),
 			pTX_Buffer->fifo_head.wFIFOCtl);
 
@@ -2593,11 +2594,11 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-		&pContext->sEthHeader.h_dest[0],
+		&pDevice->sTxEthHeader.h_dest[0],
 		(u16)(BytesToWrite - uHeaderLen),
 		pTX_Buffer->fifo_head.wFIFOCtl);
 
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 01cf09999b6d..a4a4bf24aad6 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -295,40 +295,38 @@ static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsInterruptRead(struct vnt_private *pDevice)
+int PIPEnsInterruptRead(struct vnt_private *priv)
 {
-	int ntStatus = STATUS_FAILURE;
+	int status = STATUS_FAILURE;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"---->s_nsStartInterruptUsbRead()\n");
 
-    if(pDevice->intBuf.bInUse == true){
-        return (STATUS_FAILURE);
-    }
-    pDevice->intBuf.bInUse = true;
-//    pDevice->bEventAvailable = false;
-    pDevice->ulIntInPosted++;
-
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    pDevice->pInterruptURB->interval = pDevice->int_interval;
-
-usb_fill_bulk_urb(pDevice->pInterruptURB,
-		pDevice->usb,
-		usb_rcvbulkpipe(pDevice->usb, 1),
-		(void *) pDevice->intBuf.pDataBuf,
+	if (priv->int_buf.in_use == true)
+		return STATUS_FAILURE;
+
+	priv->int_buf.in_use = true;
+
+	usb_fill_int_urb(priv->pInterruptURB,
+		priv->usb,
+		usb_rcvbulkpipe(priv->usb, 1),
+		priv->int_buf.data_buf,
 		MAX_INTERRUPT_SIZE,
 		s_nsInterruptUsbIoCompleteRead,
-		pDevice);
+		priv,
+		priv->int_interval);
 
-	ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
-	if (ntStatus != 0) {
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
-    }
+	status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
+	if (status) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Submit int URB failed %d\n", status);
+		priv->int_buf.in_use = false;
+	}
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
-    return ntStatus;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+		"<----s_nsStartInterruptUsbRead Return(%x)\n", status);
+
+	return status;
 }
 
 /*
@@ -348,67 +346,48 @@ usb_fill_bulk_urb(pDevice->pInterruptURB,
 
 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
 {
-	struct vnt_private *pDevice = (struct vnt_private *)urb->context;
-	int ntStatus;
+	struct vnt_private *priv = urb->context;
+	int status;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
-    //
-    // The context given to IoSetCompletionRoutine is the receive buffer object
-    //
-
-    //
-    // We have a number of cases:
-    //      1) The USB read timed out and we received no data.
-    //      2) The USB read timed out and we received some data.
-    //      3) The USB read was successful and fully filled our irp buffer.
-    //      4) The irp was cancelled.
-    //      5) Some other failure from the USB device object.
-    //
-    ntStatus = urb->status;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
-
-    // if we were not successful, we need to free the int buffer for future use right here
-    // otherwise interrupt data handler will free int buffer after it handle it.
-    if (( ntStatus != STATUS_SUCCESS )) {
-        pDevice->ulBulkInError++;
-        pDevice->intBuf.bInUse = false;
-
-//        if (ntStatus == USBD_STATUS_CRC) {
-//            pDevice->ulIntInContCRCError++;
-//        }
-
-//        if (ntStatus == STATUS_NOT_CONNECTED )
-//        {
-            pDevice->fKillEventPollingThread = true;
-//        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
-    } else {
-	    pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length;
-	    pDevice->ulIntInContCRCError = 0;
-	    pDevice->bEventAvailable = true;
-	    INTnsProcessData(pDevice);
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"---->s_nsInterruptUsbIoCompleteRead\n");
+
+	switch (urb->status) {
+	case 0:
+	case -ETIMEDOUT:
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		priv->int_buf.in_use = false;
+		return;
+	default:
+		break;
+	}
 
-    if (pDevice->fKillEventPollingThread != true) {
-       usb_fill_bulk_urb(pDevice->pInterruptURB,
-		      pDevice->usb,
-		      usb_rcvbulkpipe(pDevice->usb, 1),
-		     (void *) pDevice->intBuf.pDataBuf,
-		     MAX_INTERRUPT_SIZE,
-		     s_nsInterruptUsbIoCompleteRead,
-		     pDevice);
+	status = urb->status;
 
-	ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
-	if (ntStatus != 0) {
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
-           }
-    }
-    //
-    // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
-    // routine (IofCompleteRequest) will stop working on the irp.
-    //
-    return ;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+		"s_nsInterruptUsbIoCompleteRead Status %d\n", status);
+
+	if (status != STATUS_SUCCESS) {
+		priv->int_buf.in_use = false;
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"IntUSBIoCompleteControl STATUS = %d\n", status);
+	} else {
+		INTnsProcessData(priv);
+	}
+
+	status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
+	if (status) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Submit int URB failed %d\n", status);
+	} else {
+		priv->int_buf.in_use = true;
+	}
+
+	return;
 }
 
 /*
@@ -425,45 +404,41 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, struct vnt_rcb *pRCB)
+int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
 {
-	int ntStatus = 0;
-	struct urb *pUrb;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
+	int status = 0;
+	struct urb *urb;
 
-    if (pDevice->Flags & fMP_DISCONNECTED)
-        return STATUS_FAILURE;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
 
-    pDevice->ulBulkInPosted++;
+	if (priv->Flags & fMP_DISCONNECTED)
+		return STATUS_FAILURE;
 
-	pUrb = pRCB->pUrb;
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    if (pRCB->skb == NULL) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
-        return ntStatus;
-    }
+	urb = rcb->pUrb;
+	if (rcb->skb == NULL) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n");
+		return status;
+	}
 
-	usb_fill_bulk_urb(pUrb,
-		pDevice->usb,
-		usb_rcvbulkpipe(pDevice->usb, 2),
-		(void *) (pRCB->skb->data),
+	usb_fill_bulk_urb(urb,
+		priv->usb,
+		usb_rcvbulkpipe(priv->usb, 2),
+		(void *) (rcb->skb->data),
 		MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
 		s_nsBulkInUsbIoCompleteRead,
-		pRCB);
+		rcb);
 
-	ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
-	if (ntStatus != 0) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status != 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Submit Rx URB failed %d\n", status);
 		return STATUS_FAILURE ;
 	}
-    pRCB->Ref = 1;
-    pRCB->bBoolInUse= true;
 
-    return ntStatus;
+	rcb->Ref = 1;
+	rcb->bBoolInUse = true;
+
+	return status;
 }
 
 /*
@@ -483,51 +458,47 @@ int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, struct vnt_rcb *pRCB)
 
 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
 {
-	struct vnt_rcb *pRCB = (struct vnt_rcb *)urb->context;
-	struct vnt_private *pDevice = pRCB->pDevice;
-	unsigned long   bytesRead;
-	int bIndicateReceive = false;
-	int bReAllocSkb = false;
-	int status;
+	struct vnt_rcb *rcb = urb->context;
+	struct vnt_private *priv = rcb->pDevice;
+	int re_alloc_skb = false;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
-    status = urb->status;
-    bytesRead = urb->actual_length;
-
-    if (status) {
-        pDevice->ulBulkInError++;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
-//todo...xxxxxx
-//        if (status == USBD_STATUS_CRC) {
-//            pDevice->ulBulkInContCRCError++;
-//        }
-//        if (status == STATUS_DEVICE_NOT_CONNECTED )
-//        {
-//            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
-//        }
-    } else {
-	if (bytesRead)
-		bIndicateReceive = true;
-        pDevice->ulBulkInContCRCError = 0;
-        pDevice->ulBulkInBytesRead += bytesRead;
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
 
-    if (bIndicateReceive) {
-        spin_lock(&pDevice->lock);
-        if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == true)
-            bReAllocSkb = true;
-        spin_unlock(&pDevice->lock);
-    }
-    pRCB->Ref--;
-    if (pRCB->Ref == 0)
-    {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
-        spin_lock(&pDevice->lock);
-        RXvFreeRCB(pRCB, bReAllocSkb);
-        spin_unlock(&pDevice->lock);
-    }
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	case -ETIMEDOUT:
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"BULK In failed %d\n", urb->status);
+		break;
+	}
+
+	if (urb->actual_length) {
+		spin_lock(&priv->lock);
+
+		if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
+			re_alloc_skb = true;
+
+		spin_unlock(&priv->lock);
+	}
+
+	rcb->Ref--;
+	if (rcb->Ref == 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n",
+							priv->NumRecvFreeList);
+		spin_lock(&priv->lock);
+
+		RXvFreeRCB(rcb, re_alloc_skb);
 
-    return;
+		spin_unlock(&priv->lock);
+	}
+
+	return;
 }
 
 /*
@@ -544,53 +515,40 @@ static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
  *
  */
 
-int PIPEnsSendBulkOut(struct vnt_private *pDevice,
-				struct vnt_usb_send_context *pContext)
+int PIPEnsSendBulkOut(struct vnt_private *priv,
+				struct vnt_usb_send_context *context)
 {
 	int status;
-	struct urb          *pUrb;
+	struct urb *urb;
 
-    pDevice->bPWBitOn = false;
+	priv->bPWBitOn = false;
 
-/*
-    if (pDevice->pPendingBulkOutContext != NULL) {
-        pDevice->NumContextsQueued++;
-        EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
-        status = STATUS_PENDING;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
-        return status;
-    }
-*/
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
-
-    if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) {
-
-        pUrb = pContext->pUrb;
-        pDevice->ulBulkOutPosted++;
-//        pDevice->pPendingBulkOutContext = pContext;
-        usb_fill_bulk_urb(
-        	    pUrb,
-        		pDevice->usb,
-		    usb_sndbulkpipe(pDevice->usb, 3),
-		    (void *) &(pContext->Data[0]),
-        		pContext->uBufLen,
-        		s_nsBulkOutIoCompleteWrite,
-        		pContext);
-
-    	status = usb_submit_urb(pUrb, GFP_ATOMIC);
-    	if (status != 0)
-    	{
-    		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
-		pContext->bBoolInUse = false;
-    		return STATUS_FAILURE;
-    	}
-        return STATUS_PENDING;
-    }
-    else {
-        pContext->bBoolInUse = false;
-        return STATUS_RESOURCES;
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
+
+	if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
+		context->bBoolInUse = false;
+		return STATUS_RESOURCES;
+	}
+
+	urb = context->pUrb;
+
+	usb_fill_bulk_urb(urb,
+			priv->usb,
+			usb_sndbulkpipe(priv->usb, 3),
+			context->Data,
+			context->uBufLen,
+			s_nsBulkOutIoCompleteWrite,
+			context);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status != 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Submit Tx URB failed %d\n", status);
+		context->bBoolInUse = false;
+		return STATUS_FAILURE;
+	}
+
+	return STATUS_PENDING;
 }
 
 /*
@@ -623,68 +581,49 @@ int PIPEnsSendBulkOut(struct vnt_private *pDevice,
 
 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
 {
-	struct vnt_private *pDevice;
-	int status;
-	CONTEXT_TYPE ContextType;
-	unsigned long ulBufLen;
-	struct vnt_usb_send_context *pContext;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
-    //
-    // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
-    //
-	pContext = (struct vnt_usb_send_context *)urb->context;
-
-    pDevice = pContext->pDevice;
-    ContextType = pContext->Type;
-    ulBufLen = pContext->uBufLen;
-
-    if (!netif_device_present(pDevice->dev))
-	    return;
+	struct vnt_usb_send_context *context = urb->context;
+	struct vnt_private *priv = context->pDevice;
+	u8 context_type = context->type;
 
-   //
-    // Perform various IRP, URB, and buffer 'sanity checks'
-    //
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
 
-    status = urb->status;
-
-    if(status == STATUS_SUCCESS) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
-        pDevice->ulBulkOutBytesWrite += ulBufLen;
-        pDevice->ulBulkOutContCRCError = 0;
-    } else {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
-        pDevice->ulBulkOutError++;
-    }
+	switch (urb->status) {
+	case 0:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Write %d bytes\n", context->uBufLen);
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		context->bBoolInUse = false;
+		return;
+	case -ETIMEDOUT:
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"BULK Out failed %d\n", urb->status);
+		break;
+	}
 
-//    pDevice->ulCheckForHangCount = 0;
-//    pDevice->pPendingBulkOutContext = NULL;
+	if (!netif_device_present(priv->dev))
+		return;
 
-    if ( CONTEXT_DATA_PACKET == ContextType ) {
-        // Indicate to the protocol the status of the sent packet and return
-        // ownership of the packet.
-	    if (pContext->pPacket != NULL) {
-	        dev_kfree_skb_irq(pContext->pPacket);
-	        pContext->pPacket = NULL;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
-	    }
+	if (CONTEXT_DATA_PACKET == context_type) {
+		if (context->pPacket != NULL) {
+			dev_kfree_skb_irq(context->pPacket);
+			context->pPacket = NULL;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"tx  %d bytes\n", context->uBufLen);
+		}
 
-        pDevice->dev->trans_start = jiffies;
+		priv->dev->trans_start = jiffies;
+	}
 
-        if (status == STATUS_SUCCESS) {
-            pDevice->packetsSent++;
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
-            pDevice->packetsSentDropped++;
-        }
+	if (priv->bLinkPass == true) {
+		if (netif_queue_stopped(priv->dev))
+			netif_wake_queue(priv->dev);
+	}
 
-    }
-    if (pDevice->bLinkPass == true) {
-        if (netif_queue_stopped(pDevice->dev))
-            netif_wake_queue(pDevice->dev);
-    }
-    pContext->bBoolInUse = false;
+	context->bBoolInUse = false;
 
-    return;
+	return;
 }
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 6b9522914634..3cf3f24247a3 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -293,17 +293,11 @@ void vRunCommand(struct work_struct *work)
 	case WLAN_CMD_SCAN_START:
 
 		pDevice->byReAssocCount = 0;
-		if (pDevice->bRadioOff == true) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pDevice->bRadioOff == true)
+			break;
 
-		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
+			break;
 
 		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
 
@@ -311,16 +305,12 @@ void vRunCommand(struct work_struct *work)
 			pMgmt->uScanChannel = pDevice->byMinChannel;
 		if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
 			pDevice->eCommandState = WLAN_CMD_SCAN_END;
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
+			break;
 		} else {
 			if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) {
 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel);
 				pMgmt->uScanChannel++;
-				s_bCommandComplete(pDevice);
-				spin_unlock_irq(&pDevice->lock);
-				return;
+				break;
 			}
 			if (pMgmt->uScanChannel == pDevice->byMinChannel) {
 				// pMgmt->eScanType = WMAC_SCAN_ACTIVE;          //mike mark
@@ -420,16 +410,13 @@ void vRunCommand(struct work_struct *work)
 		memset(&wrqu, 0, sizeof(wrqu));
 		wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_DISASSOCIATE_START:
 		pDevice->byReAssocCount = 0;
 		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
 		    (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
+			break;
 		} else {
 			pDevice->bwextstep0 = false;
 			pDevice->bwextstep1 = false;
@@ -458,17 +445,14 @@ void vRunCommand(struct work_struct *work)
 		netif_stop_queue(pDevice->dev);
 		if (pDevice->bNeedRadioOFF == true)
 			CARDbRadioPowerOff(pDevice);
-		s_bCommandComplete(pDevice);
+
 		break;
 
 	case WLAN_CMD_SSID_START:
 
 		pDevice->byReAssocCount = 0;
-		if (pDevice->bRadioOff == true) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pDevice->bRadioOff == true)
+			break;
 
 		memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID,
 		       ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN);
@@ -489,11 +473,9 @@ void vRunCommand(struct work_struct *work)
 		if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
 		    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
 			if (pItemSSID->len == pItemSSIDCurr->len) {
-				if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
-					s_bCommandComplete(pDevice);
-					spin_unlock_irq(&pDevice->lock);
-					return;
-				}
+				if (!memcmp(pItemSSID->abySSID,
+					pItemSSIDCurr->abySSID, pItemSSID->len))
+					break;
 			}
 			netif_stop_queue(pDevice->dev);
 			pDevice->bLinkPass = false;
@@ -582,7 +564,6 @@ void vRunCommand(struct work_struct *work)
 				}
 			}
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_AUTHENTICATE_WAIT:
@@ -612,7 +593,6 @@ void vRunCommand(struct work_struct *work)
 		}
 		pDevice->byLinkWaitCount = 0;
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_ASSOCIATE_WAIT:
@@ -647,7 +627,6 @@ void vRunCommand(struct work_struct *work)
 			return;
 		}
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_AP_MODE_START:
@@ -683,7 +662,6 @@ void vRunCommand(struct work_struct *work)
 			ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER);
 			schedule_delayed_work(&pDevice->second_callback_work, HZ);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_TX_PSPACKET_START:
@@ -738,8 +716,6 @@ void vRunCommand(struct work_struct *work)
 				pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
 			}
 		}
-
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_RADIO_START:
@@ -760,11 +736,8 @@ void vRunCommand(struct work_struct *work)
 					1,
 					&byTmp);
 
-			if (ntStatus != STATUS_SUCCESS) {
-				s_bCommandComplete(pDevice);
-				spin_unlock_irq(&pDevice->lock);
-				return;
-			}
+			if (ntStatus != STATUS_SUCCESS)
+				break;
 			if ((byTmp & GPIO3_DATA) == 0) {
 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n");
 				// Old commands are useless.
@@ -833,7 +806,6 @@ void vRunCommand(struct work_struct *work)
 			}
 		}
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_CHANGE_BBSENSITIVITY_START:
@@ -843,24 +815,20 @@ void vRunCommand(struct work_struct *work)
 		BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent);
 		pDevice->bStopDataPkt = false;
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_TBTT_WAKEUP_START:
 		PSbIsNextTBTTWakeUp(pDevice);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_BECON_SEND_START:
 		bMgrPrepareBeaconToSend(pDevice, pMgmt);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_SETPOWER_START:
 
 		RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel);
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_CHANGE_ANTENNA_START:
@@ -878,12 +846,10 @@ void vRunCommand(struct work_struct *work)
 			else
 				BBvSetAntennaMode(pDevice, ANT_RXA);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_REMOVE_ALLKEY_START:
 		KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_MAC_DISPOWERSAVING_START:
@@ -898,7 +864,6 @@ void vRunCommand(struct work_struct *work)
 					NULL
 					);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_11H_CHSW_START:
@@ -906,14 +871,17 @@ void vRunCommand(struct work_struct *work)
 		pDevice->bChannelSwitch = false;
 		pMgmt->uCurrChannel = pDevice->byNewChannel;
 		pDevice->bStopDataPkt = false;
-		s_bCommandComplete(pDevice);
 		break;
 
+	case WLAN_CMD_CONFIGURE_FILTER_START:
+		vnt_configure_filter(pDevice);
+		break;
 	default:
-		s_bCommandComplete(pDevice);
 		break;
 	} //switch
 
+	s_bCommandComplete(pDevice);
+
 	spin_unlock_irq(&pDevice->lock);
 	return;
 }
@@ -1009,6 +977,11 @@ static int s_bCommandComplete(struct vnt_private *pDevice)
 			pDevice->eCommandState = WLAN_CMD_11H_CHSW_START;
 			break;
 
+		case WLAN_CMD_CONFIGURE_FILTER:
+			pDevice->eCommandState =
+						WLAN_CMD_CONFIGURE_FILTER_START;
+			break;
+
 		default:
 			break;
 		}
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index caf2684ce915..736572101bad 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -51,7 +51,8 @@ typedef enum tagCMD_CODE {
     WLAN_CMD_REMOVE_ALLKEY,
     WLAN_CMD_MAC_DISPOWERSAVING,
     WLAN_CMD_11H_CHSW,
-    WLAN_CMD_RUN_AP
+    WLAN_CMD_RUN_AP,
+    WLAN_CMD_CONFIGURE_FILTER
 } CMD_CODE, *PCMD_CODE;
 
 #define CMD_Q_SIZE              32
@@ -96,6 +97,7 @@ typedef enum tagCMD_STATE {
     WLAN_CMD_REMOVE_ALLKEY_START,
     WLAN_CMD_MAC_DISPOWERSAVING_START,
     WLAN_CMD_11H_CHSW_START,
+    WLAN_CMD_CONFIGURE_FILTER_START,
     WLAN_CMD_IDLE
 } CMD_STATE, *PCMD_STATE;
 
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index d74b0e7cb171..0d69719a7426 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -2164,12 +2164,12 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
         pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
         pMgmt->byDTIMPeriod = DEFAULT_DTIM_PERIOD;
         pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
-        pDevice->eOPMode = OP_MODE_AP;
+	pDevice->op_mode = NL80211_IFTYPE_AP;
     }
 
     if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
         pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_IBSS(1);
-        pDevice->eOPMode = OP_MODE_ADHOC;
+	pDevice->op_mode = NL80211_IFTYPE_ADHOC;
     }
 
     if (pDevice->bEncryptionEnable) {
@@ -2359,7 +2359,7 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
 
             pMgmt->eCurrState = WMAC_STATE_JOINTED;
             // Adopt BSS state in Adapter Device Object
-            pDevice->eOPMode = OP_MODE_INFRASTRUCTURE;
+	    pDevice->op_mode = NL80211_IFTYPE_STATION;
             memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
 
             // Add current BSS to Candidate list
@@ -2500,7 +2500,7 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
             pMgmt->eCurrMode = WMAC_MODE_IBSS_STA;
             pMgmt->eCurrState = WMAC_STATE_STARTED;
             // Adopt BSS state in Adapter Device Object
-            pDevice->eOPMode = OP_MODE_ADHOC;
+	    pDevice->op_mode = NL80211_IFTYPE_ADHOC;
             pDevice->bLinkPass = true;
             ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER);
             memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index a7d24c95191d..6c317304b658 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -400,6 +400,8 @@ static int prism2_scan(struct wiphy *wiphy,
 	numbss = msg1.numbss.data;
 
 	for (i = 0; i < numbss; i++) {
+		int freq;
+
 		memset(&msg2, 0, sizeof(msg2));
 		msg2.msgcode = DIDmsg_dot11req_scan_results;
 		msg2.bssindex.data = i;
@@ -414,9 +416,10 @@ static int prism2_scan(struct wiphy *wiphy,
 		ie_buf[1] = msg2.ssid.data.len;
 		ie_len = ie_buf[1] + 2;
 		memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
+		freq = ieee80211_channel_to_frequency(msg2.dschannel.data,
+						      IEEE80211_BAND_2GHZ);
 		bss = cfg80211_inform_bss(wiphy,
-			ieee80211_get_channel(wiphy,
-			      ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
+			ieee80211_get_channel(wiphy, freq),
 			(const u8 *) &(msg2.bssid.data.data),
 			msg2.timestamp.data, msg2.capinfo.data,
 			msg2.beaconperiod.data,
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index b3ff603e6225..466804687fc0 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -1754,8 +1754,7 @@ static int xgifb_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev, "Unable request memory size %x\n",
 		       xgifb_info->video_size);
 		dev_err(&pdev->dev,
-			"Fatal error: Unable to reserve frame buffer memory. "
-			"Is there another framebuffer driver active?\n");
+			"Fatal error: Unable to reserve frame buffer memory. Is there another framebuffer driver active?\n");
 		ret = -ENODEV;
 		goto error_disable;
 	}
@@ -2087,23 +2086,19 @@ static struct pci_driver xgifb_driver = {
 
 module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode,
-	"Selects the desired default display mode in the format XxYxDepth "
-	"(eg. 1024x768x16).");
+	"Selects the desired default display mode in the format XxYxDepth (eg. 1024x768x16).");
 
 module_param(forcecrt2type, charp, 0);
 MODULE_PARM_DESC(forcecrt2type,
-	"Force the second display output type. Possible values are NONE, "
-	"LCD, TV, VGA, SVIDEO or COMPOSITE.");
+	"Force the second display output type. Possible values are NONE, LCD, TV, VGA, SVIDEO or COMPOSITE.");
 
 module_param(vesa, int, 0);
 MODULE_PARM_DESC(vesa,
-	"Selects the desired default display mode by VESA mode number "
-	"(eg. 0x117).");
+	"Selects the desired default display mode by VESA mode number (eg. 0x117).");
 
 module_param(filter, int, 0);
 MODULE_PARM_DESC(filter,
-	"Selects TV flicker filter type (only for systems with a SiS301 video bridge). "
-	"Possible values 0-7. Default: [no filter]).");
+	"Selects TV flicker filter type (only for systems with a SiS301 video bridge). Possible values 0-7. Default: [no filter]).");
 
 static int __init xgifb_init(void)
 {
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/target/target_core_alua.c b/drivers/target/target_core_alua.c
index c3d9df6aaf5f..fcbe6125b73e 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -455,11 +455,26 @@ out:
 	return rc;
 }
 
-static inline int core_alua_state_nonoptimized(
+static inline void set_ascq(struct se_cmd *cmd, u8 alua_ascq)
+{
+	/*
+	 * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
+	 * The ALUA additional sense code qualifier (ASCQ) is determined
+	 * by the ALUA primary or secondary access state..
+	 */
+	pr_debug("[%s]: ALUA TG Port not available, "
+		"SenseKey: NOT_READY, ASC/ASCQ: "
+		"0x04/0x%02x\n",
+		cmd->se_tfo->get_fabric_name(), alua_ascq);
+
+	cmd->scsi_asc = 0x04;
+	cmd->scsi_ascq = alua_ascq;
+}
+
+static inline void core_alua_state_nonoptimized(
 	struct se_cmd *cmd,
 	unsigned char *cdb,
-	int nonop_delay_msecs,
-	u8 *alua_ascq)
+	int nonop_delay_msecs)
 {
 	/*
 	 * Set SCF_ALUA_NON_OPTIMIZED here, this value will be checked
@@ -468,13 +483,11 @@ static inline int core_alua_state_nonoptimized(
 	 */
 	cmd->se_cmd_flags |= SCF_ALUA_NON_OPTIMIZED;
 	cmd->alua_nonop_delay = nonop_delay_msecs;
-	return 0;
 }
 
 static inline int core_alua_state_lba_dependent(
 	struct se_cmd *cmd,
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	u8 *alua_ascq)
+	struct t10_alua_tg_pt_gp *tg_pt_gp)
 {
 	struct se_device *dev = cmd->se_dev;
 	u64 segment_size, segment_mult, sectors, lba;
@@ -520,7 +533,7 @@ static inline int core_alua_state_lba_dependent(
 		}
 		if (!cur_map) {
 			spin_unlock(&dev->t10_alua.lba_map_lock);
-			*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+			set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
 			return 1;
 		}
 		list_for_each_entry(map_mem, &cur_map->lba_map_mem_list,
@@ -531,11 +544,11 @@ static inline int core_alua_state_lba_dependent(
 			switch(map_mem->lba_map_mem_alua_state) {
 			case ALUA_ACCESS_STATE_STANDBY:
 				spin_unlock(&dev->t10_alua.lba_map_lock);
-				*alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
+				set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
 				return 1;
 			case ALUA_ACCESS_STATE_UNAVAILABLE:
 				spin_unlock(&dev->t10_alua.lba_map_lock);
-				*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+				set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
 				return 1;
 			default:
 				break;
@@ -548,8 +561,7 @@ static inline int core_alua_state_lba_dependent(
 
 static inline int core_alua_state_standby(
 	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u8 *alua_ascq)
+	unsigned char *cdb)
 {
 	/*
 	 * Allowed CDBs for ALUA_ACCESS_STATE_STANDBY as defined by
@@ -570,7 +582,7 @@ static inline int core_alua_state_standby(
 		case MI_REPORT_TARGET_PGS:
 			return 0;
 		default:
-			*alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
+			set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
 			return 1;
 		}
 	case MAINTENANCE_OUT:
@@ -578,7 +590,7 @@ static inline int core_alua_state_standby(
 		case MO_SET_TARGET_PGS:
 			return 0;
 		default:
-			*alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
+			set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
 			return 1;
 		}
 	case REQUEST_SENSE:
@@ -588,7 +600,7 @@ static inline int core_alua_state_standby(
 	case WRITE_BUFFER:
 		return 0;
 	default:
-		*alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
+		set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
 		return 1;
 	}
 
@@ -597,8 +609,7 @@ static inline int core_alua_state_standby(
 
 static inline int core_alua_state_unavailable(
 	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u8 *alua_ascq)
+	unsigned char *cdb)
 {
 	/*
 	 * Allowed CDBs for ALUA_ACCESS_STATE_UNAVAILABLE as defined by
@@ -613,7 +624,7 @@ static inline int core_alua_state_unavailable(
 		case MI_REPORT_TARGET_PGS:
 			return 0;
 		default:
-			*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+			set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
 			return 1;
 		}
 	case MAINTENANCE_OUT:
@@ -621,7 +632,7 @@ static inline int core_alua_state_unavailable(
 		case MO_SET_TARGET_PGS:
 			return 0;
 		default:
-			*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+			set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
 			return 1;
 		}
 	case REQUEST_SENSE:
@@ -629,7 +640,7 @@ static inline int core_alua_state_unavailable(
 	case WRITE_BUFFER:
 		return 0;
 	default:
-		*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+		set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
 		return 1;
 	}
 
@@ -638,8 +649,7 @@ static inline int core_alua_state_unavailable(
 
 static inline int core_alua_state_transition(
 	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u8 *alua_ascq)
+	unsigned char *cdb)
 {
 	/*
 	 * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by
@@ -654,7 +664,7 @@ static inline int core_alua_state_transition(
 		case MI_REPORT_TARGET_PGS:
 			return 0;
 		default:
-			*alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION;
+			set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION);
 			return 1;
 		}
 	case REQUEST_SENSE:
@@ -662,7 +672,7 @@ static inline int core_alua_state_transition(
 	case WRITE_BUFFER:
 		return 0;
 	default:
-		*alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION;
+		set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION);
 		return 1;
 	}
 
@@ -684,8 +694,6 @@ target_alua_state_check(struct se_cmd *cmd)
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	int out_alua_state, nonop_delay_msecs;
-	u8 alua_ascq;
-	int ret;
 
 	if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
 		return 0;
@@ -701,9 +709,8 @@ target_alua_state_check(struct se_cmd *cmd)
 	if (atomic_read(&port->sep_tg_pt_secondary_offline)) {
 		pr_debug("ALUA: Got secondary offline status for local"
 				" target port\n");
-		alua_ascq = ASCQ_04H_ALUA_OFFLINE;
-		ret = 1;
-		goto out;
+		set_ascq(cmd, ASCQ_04H_ALUA_OFFLINE);
+		return TCM_CHECK_CONDITION_NOT_READY;
 	}
 	 /*
 	 * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the
@@ -731,20 +738,23 @@ target_alua_state_check(struct se_cmd *cmd)
 
 	switch (out_alua_state) {
 	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
-		ret = core_alua_state_nonoptimized(cmd, cdb,
-					nonop_delay_msecs, &alua_ascq);
+		core_alua_state_nonoptimized(cmd, cdb, nonop_delay_msecs);
 		break;
 	case ALUA_ACCESS_STATE_STANDBY:
-		ret = core_alua_state_standby(cmd, cdb, &alua_ascq);
+		if (core_alua_state_standby(cmd, cdb))
+			return TCM_CHECK_CONDITION_NOT_READY;
 		break;
 	case ALUA_ACCESS_STATE_UNAVAILABLE:
-		ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq);
+		if (core_alua_state_unavailable(cmd, cdb))
+			return TCM_CHECK_CONDITION_NOT_READY;
 		break;
 	case ALUA_ACCESS_STATE_TRANSITION:
-		ret = core_alua_state_transition(cmd, cdb, &alua_ascq);
+		if (core_alua_state_transition(cmd, cdb))
+			return TCM_CHECK_CONDITION_NOT_READY;
 		break;
 	case ALUA_ACCESS_STATE_LBA_DEPENDENT:
-		ret = core_alua_state_lba_dependent(cmd, tg_pt_gp, &alua_ascq);
+		if (core_alua_state_lba_dependent(cmd, tg_pt_gp))
+			return TCM_CHECK_CONDITION_NOT_READY;
 		break;
 	/*
 	 * OFFLINE is a secondary ALUA target port group access state, that is
@@ -757,23 +767,6 @@ target_alua_state_check(struct se_cmd *cmd)
 		return TCM_INVALID_CDB_FIELD;
 	}
 
-out:
-	if (ret > 0) {
-		/*
-		 * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
-		 * The ALUA additional sense code qualifier (ASCQ) is determined
-		 * by the ALUA primary or secondary access state..
-		 */
-		pr_debug("[%s]: ALUA TG Port not available, "
-			"SenseKey: NOT_READY, ASC/ASCQ: "
-			"0x04/0x%02x\n",
-			cmd->se_tfo->get_fabric_name(), alua_ascq);
-
-		cmd->scsi_asc = 0x04;
-		cmd->scsi_ascq = alua_ascq;
-		return TCM_CHECK_CONDITION_NOT_READY;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 35c066489a19..2d51912a6e40 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -136,13 +136,14 @@ config SPEAR_THERMAL
 config RCAR_THERMAL
 	tristate "Renesas R-Car thermal driver"
 	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on HAS_IOMEM
 	help
 	  Enable this to plug the R-Car thermal sensor driver into the Linux
 	  thermal framework.
 
 config KIRKWOOD_THERMAL
 	tristate "Temperature sensor on Marvell Kirkwood SoCs"
-	depends on ARCH_KIRKWOOD
+	depends on ARCH_KIRKWOOD || MACH_KIRKWOOD
 	depends on OF
 	help
 	  Support for the Kirkwood thermal sensor driver into the Linux thermal
@@ -210,8 +211,16 @@ config ACPI_INT3403_THERMAL
 	tristate "ACPI INT3403 thermal driver"
 	depends on X86 && ACPI
 	help
-	  This driver uses ACPI INT3403 device objects. If present, it will
-	  register each INT3403 thermal sensor as a thermal zone.
+	  Newer laptops and tablets that use ACPI may have thermal sensors
+	  outside the core CPU/SOC for thermal safety reasons. These
+	  temperature sensors are also exposed for the OS to use via the so
+	  called INT3403 ACPI object. This driver will, on devices that have
+	  such sensors, expose the temperature information from these sensors
+	  to userspace via the normal thermal framework. This means that a wide
+	  range of applications and GUI widgets can show this information to
+	  the user or use this information for making decisions. For example,
+	  the Intel Thermal Daemon can use this information to allow the user
+	  to select his laptop to run without turning on the fans.
 
 menu "Texas Instruments thermal drivers"
 source "drivers/thermal/ti-soc-thermal/Kconfig"
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 45af765a3198..a99c63152b8d 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -62,12 +62,16 @@ enum imx_thermal_trip {
 #define IMX_POLLING_DELAY		2000 /* millisecond */
 #define IMX_PASSIVE_DELAY		1000
 
+#define FACTOR0				10000000
+#define FACTOR1				15976
+#define FACTOR2				4297157
+
 struct imx_thermal_data {
 	struct thermal_zone_device *tz;
 	struct thermal_cooling_device *cdev;
 	enum thermal_device_mode mode;
 	struct regmap *tempmon;
-	int c1, c2; /* See formula in imx_get_sensor_data() */
+	u32 c1, c2; /* See formula in imx_get_sensor_data() */
 	unsigned long temp_passive;
 	unsigned long temp_critical;
 	unsigned long alarm_temp;
@@ -84,7 +88,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
 	int alarm_value;
 
 	data->alarm_temp = alarm_temp;
-	alarm_value = (alarm_temp - data->c2) / data->c1;
+	alarm_value = (data->c2 - alarm_temp) / data->c1;
 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
 	regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
 			TEMPSENSE0_ALARM_VALUE_SHIFT);
@@ -136,7 +140,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
 	n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
 
 	/* See imx_get_sensor_data() for formula derivation */
-	*temp = data->c2 + data->c1 * n_meas;
+	*temp = data->c2 - n_meas * data->c1;
 
 	/* Update alarm value to next higher trip point */
 	if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
@@ -305,6 +309,7 @@ static int imx_get_sensor_data(struct platform_device *pdev)
 	int t1, t2, n1, n2;
 	int ret;
 	u32 val;
+	u64 temp64;
 
 	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 					      "fsl,tempmon-data");
@@ -330,6 +335,8 @@ static int imx_get_sensor_data(struct platform_device *pdev)
 	 *   [31:20] - sensor value @ 25C
 	 *    [19:8] - sensor value of hot
 	 *     [7:0] - hot temperature value
+	 * Use universal formula now and only need sensor value @ 25C
+	 * slope = 0.4297157 - (0.0015976 * 25C fuse)
 	 */
 	n1 = val >> 20;
 	n2 = (val & 0xfff00) >> 8;
@@ -337,20 +344,26 @@ static int imx_get_sensor_data(struct platform_device *pdev)
 	t1 = 25; /* t1 always 25C */
 
 	/*
-	 * Derived from linear interpolation,
-	 * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2)
+	 * Derived from linear interpolation:
+	 * slope = 0.4297157 - (0.0015976 * 25C fuse)
+	 * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
+	 * (Nmeas - n1) / (Tmeas - t1) = slope
 	 * We want to reduce this down to the minimum computation necessary
 	 * for each temperature read.  Also, we want Tmeas in millicelsius
 	 * and we don't want to lose precision from integer division. So...
-	 * milli_Tmeas = 1000 * T2 + 1000 * (Nmeas - N2) * (T1 - T2) / (N1 - N2)
-	 * Let constant c1 = 1000 * (T1 - T2) / (N1 - N2)
-	 * milli_Tmeas = (1000 * T2) + c1 * (Nmeas - N2)
-	 * milli_Tmeas = (1000 * T2) + (c1 * Nmeas) - (c1 * N2)
-	 * Let constant c2 = (1000 * T2) - (c1 * N2)
-	 * milli_Tmeas = c2 + (c1 * Nmeas)
+	 * Tmeas = (Nmeas - n1) / slope + t1
+	 * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
+	 * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
+	 * Let constant c1 = (-1000 / slope)
+	 * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
+	 * Let constant c2 = n1 *c1 + 1000 * t1
+	 * milli_Tmeas = c2 - Nmeas * c1
 	 */
-	data->c1 = 1000 * (t1 - t2) / (n1 - n2);
-	data->c2 = 1000 * t2 - data->c1 * n2;
+	temp64 = FACTOR0;
+	temp64 *= 1000;
+	do_div(temp64, FACTOR1 * n1 - FACTOR2);
+	data->c1 = temp64;
+	data->c2 = n1 * data->c1 + 1000 * t1;
 
 	/*
 	 * Set the default passive cooling trip point to 20 °C below the
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 79a09d02bbca..5a37940b02c9 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -299,12 +299,17 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
 static void rcar_thermal_work(struct work_struct *work)
 {
 	struct rcar_thermal_priv *priv;
+	unsigned long cctemp, nctemp;
 
 	priv = container_of(work, struct rcar_thermal_priv, work.work);
 
+	rcar_thermal_get_temp(priv->zone, &cctemp);
 	rcar_thermal_update_temp(priv);
 	rcar_thermal_irq_enable(priv);
-	thermal_zone_device_update(priv->zone);
+
+	rcar_thermal_get_temp(priv->zone, &nctemp);
+	if (nctemp != cctemp)
+		thermal_zone_device_update(priv->zone);
 }
 
 static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status)
@@ -313,7 +318,7 @@ static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status)
 
 	status = (status >> rcar_id_to_shift(priv)) & 0x3;
 
-	if (status & 0x3) {
+	if (status) {
 		dev_dbg(dev, "thermal%d %s%s\n",
 			priv->id,
 			(status & 0x2) ? "Rising " : "",
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 338a88bf6662..71b0ec0c370d 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -56,10 +56,15 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+static struct thermal_governor *def_governor;
+
 static struct thermal_governor *__find_governor(const char *name)
 {
 	struct thermal_governor *pos;
 
+	if (!name || !name[0])
+		return def_governor;
+
 	list_for_each_entry(pos, &thermal_governor_list, governor_list)
 		if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
 			return pos;
@@ -82,17 +87,23 @@ int thermal_register_governor(struct thermal_governor *governor)
 	if (__find_governor(governor->name) == NULL) {
 		err = 0;
 		list_add(&governor->governor_list, &thermal_governor_list);
+		if (!def_governor && !strncmp(governor->name,
+			DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH))
+			def_governor = governor;
 	}
 
 	mutex_lock(&thermal_list_lock);
 
 	list_for_each_entry(pos, &thermal_tz_list, node) {
+		/*
+		 * only thermal zones with specified tz->tzp->governor_name
+		 * may run with tz->govenor unset
+		 */
 		if (pos->governor)
 			continue;
-		if (pos->tzp)
-			name = pos->tzp->governor_name;
-		else
-			name = DEFAULT_THERMAL_GOVERNOR;
+
+		name = pos->tzp->governor_name;
+
 		if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
 			pos->governor = governor;
 	}
@@ -342,8 +353,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
 static void handle_non_critical_trips(struct thermal_zone_device *tz,
 			int trip, enum thermal_trip_type trip_type)
 {
-	if (tz->governor)
-		tz->governor->throttle(tz, trip);
+	tz->governor ? tz->governor->throttle(tz, trip) :
+		       def_governor->throttle(tz, trip);
 }
 
 static void handle_critical_trips(struct thermal_zone_device *tz,
@@ -1107,7 +1118,7 @@ __thermal_cooling_device_register(struct device_node *np,
 	INIT_LIST_HEAD(&cdev->thermal_instances);
 	cdev->np = np;
 	cdev->ops = ops;
-	cdev->updated = true;
+	cdev->updated = false;
 	cdev->device.class = &thermal_class;
 	cdev->devdata = devdata;
 	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1533,7 +1544,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	if (tz->tzp)
 		tz->governor = __find_governor(tz->tzp->governor_name);
 	else
-		tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
+		tz->governor = def_governor;
 
 	mutex_unlock(&thermal_governor_lock);
 
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index 74c0e3474d6e..3ab12ee359b7 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1500,10 +1500,8 @@ static int ti_bandgap_resume(struct device *dev)
 
 	return ti_bandgap_restore_ctxt(bgp);
 }
-static const struct dev_pm_ops ti_bandgap_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(ti_bandgap_suspend,
-				ti_bandgap_resume)
-};
+static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend,
+			 ti_bandgap_resume);
 
 #define DEV_PM_OPS	(&ti_bandgap_dev_pm_ops)
 #else
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 972e1c73722a..081fd7e6a9f0 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -68,6 +68,10 @@ struct phy_dev_entry {
 	struct thermal_zone_device *tzone;
 };
 
+static const struct thermal_zone_params pkg_temp_tz_params = {
+	.no_hwmon	= true,
+};
+
 /* List maintaining number of package instances */
 static LIST_HEAD(phy_dev_list);
 static DEFINE_MUTEX(phy_dev_list_mutex);
@@ -394,7 +398,6 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
 	int err;
 	u32 tj_max;
 	struct phy_dev_entry *phy_dev_entry;
-	char buffer[30];
 	int thres_count;
 	u32 eax, ebx, ecx, edx;
 	u8 *temp;
@@ -440,13 +443,11 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
 	phy_dev_entry->first_cpu = cpu;
 	phy_dev_entry->tj_max = tj_max;
 	phy_dev_entry->ref_cnt = 1;
-	snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n",
-					phy_dev_entry->phys_proc_id);
-	phy_dev_entry->tzone = thermal_zone_device_register(buffer,
+	phy_dev_entry->tzone = thermal_zone_device_register("x86_pkg_temp",
 			thres_count,
 			(thres_count == MAX_NUMBER_OF_TRIPS) ?
 				0x03 : 0x01,
-			phy_dev_entry, &tzone_ops, NULL, 0, 0);
+			phy_dev_entry, &tzone_ops, &pkg_temp_tz_params, 0, 0);
 	if (IS_ERR(phy_dev_entry->tzone)) {
 		err = PTR_ERR(phy_dev_entry->tzone);
 		goto err_ret_free;
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/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 50b46881b6ca..94f9e3a38412 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -31,6 +31,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/major.h>
+#include <linux/atomic.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -70,6 +71,9 @@ static struct task_struct *hvc_task;
 /* Picks up late kicks after list walk but before schedule() */
 static int hvc_kicked;
 
+/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
+static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
+
 static int hvc_init(void);
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -851,7 +855,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
 	int i;
 
 	/* We wait until a driver actually comes along */
-	if (!hvc_driver) {
+	if (atomic_inc_not_zero(&hvc_needs_init)) {
 		int err = hvc_init();
 		if (err)
 			return ERR_PTR(err);
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index ebd5bff0f5c1..17ee3bf0926b 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -176,9 +176,6 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
 				": %d chars not inserted to flip buffer!\n",
 				length - work);
 
-	/*
-	 * This may sleep if ->low_latency is set
-	 */
 	if (work)
 		tty_flip_buffer_push(&tty->port);
 }
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index d15624c1b751..41fe8a047d37 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1900,13 +1900,10 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
 	struct n_tty_data *ldata = tty->disc_data;
 	int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
 
-	if (ldata->icanon && !L_EXTPROC(tty)) {
-		if (ldata->canon_head != ldata->read_tail)
-			return 1;
-	} else if (read_cnt(ldata) >= amt)
-		return 1;
-
-	return 0;
+	if (ldata->icanon && !L_EXTPROC(tty))
+		return ldata->canon_head != ldata->read_tail;
+	else
+		return read_cnt(ldata) >= amt;
 }
 
 /**
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 69932b7556cf..747073b8c38a 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1694,6 +1694,10 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
 
 static void serial_unlink_irq_chain(struct uart_8250_port *up)
 {
+	/*
+	 * yes, some broken gcc emit "warning: 'i' may be used uninitialized"
+	 * but no, we are not going to take a patch that assigns NULL below.
+	 */
 	struct irq_info *i;
 	struct hlist_node *n;
 	struct hlist_head *h;
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3815eaed421..2e6d8ddc4425 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -289,7 +289,7 @@ config SERIAL_MAX3100
 	  MAX3100 chip support
 
 config SERIAL_MAX310X
-	bool "MAX310X support"
+	tristate "MAX310X support"
 	depends on SPI_MASTER
 	select SERIAL_CORE
 	select REGMAP_SPI if SPI_MASTER
@@ -708,7 +708,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
 
 config SERIAL_SH_SCI
 	tristate "SuperH SCI(F) serial port support"
-	depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST)
+	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
 	select SERIAL_CORE
 
 config SERIAL_SH_SCI_NR_UARTS
@@ -1024,7 +1024,7 @@ config SERIAL_SGI_IOC3
 
 config SERIAL_MSM
 	bool "MSM on-chip serial port support"
-	depends on ARCH_MSM
+	depends on ARCH_MSM || ARCH_QCOM
 	select SERIAL_CORE
 
 config SERIAL_MSM_CONSOLE
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d58783d364e3..d4eda24aa68b 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2154,9 +2154,19 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	amba_ports[i] = uap;
 
 	amba_set_drvdata(dev, uap);
+
+	if (!amba_reg.state) {
+		ret = uart_register_driver(&amba_reg);
+		if (ret < 0) {
+			pr_err("Failed to register AMBA-PL011 driver\n");
+			return ret;
+		}
+	}
+
 	ret = uart_add_one_port(&amba_reg, &uap->port);
 	if (ret) {
 		amba_ports[i] = NULL;
+		uart_unregister_driver(&amba_reg);
 		pl011_dma_remove(uap);
 	}
  out:
@@ -2175,6 +2185,7 @@ static int pl011_remove(struct amba_device *dev)
 			amba_ports[i] = NULL;
 
 	pl011_dma_remove(uap);
+	uart_unregister_driver(&amba_reg);
 	return 0;
 }
 
@@ -2230,22 +2241,14 @@ static struct amba_driver pl011_driver = {
 
 static int __init pl011_init(void)
 {
-	int ret;
 	printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
 
-	ret = uart_register_driver(&amba_reg);
-	if (ret == 0) {
-		ret = amba_driver_register(&pl011_driver);
-		if (ret)
-			uart_unregister_driver(&amba_reg);
-	}
-	return ret;
+	return amba_driver_register(&pl011_driver);
 }
 
 static void __exit pl011_exit(void)
 {
 	amba_driver_unregister(&pl011_driver);
-	uart_unregister_driver(&amba_reg);
 }
 
 /*
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index a49f10d269b2..53eeea13ff16 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -35,21 +35,18 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/dma-mapping.h>
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
 #include <linux/platform_data/atmel.h>
 #include <linux/timer.h>
+#include <linux/gpio.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
 
-#ifdef CONFIG_ARM
-#include <mach/cpu.h>
-#include <asm/gpio.h>
-#endif
-
 #define PDC_BUFFER_SIZE		512
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
@@ -115,9 +112,6 @@ static void atmel_stop_rx(struct uart_port *port);
 #define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
 #define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
 
-static int (*atmel_open_hook)(struct uart_port *);
-static void (*atmel_close_hook)(struct uart_port *);
-
 struct atmel_dma_buffer {
 	unsigned char	*buf;
 	dma_addr_t	dma_addr;
@@ -168,6 +162,7 @@ struct atmel_uart_port {
 	struct circ_buf		rx_ring;
 
 	struct serial_rs485	rs485;		/* rs485 settings */
+	int			rts_gpio;	/* optional RTS GPIO */
 	unsigned int		tx_done_mask;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
@@ -301,20 +296,16 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	unsigned int mode;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-#ifdef CONFIG_ARCH_AT91RM9200
-	if (cpu_is_at91rm9200()) {
-		/*
-		 * AT91RM9200 Errata #39: RTS0 is not internally connected
-		 * to PA21. We need to drive the pin manually.
-		 */
-		if (port->mapbase == AT91RM9200_BASE_US0) {
-			if (mctrl & TIOCM_RTS)
-				at91_set_gpio_value(AT91_PIN_PA21, 0);
-			else
-				at91_set_gpio_value(AT91_PIN_PA21, 1);
-		}
+	/*
+	 * AT91RM9200 Errata #39: RTS0 is not internally connected
+	 * to PA21. We need to drive the pin as a GPIO.
+	 */
+	if (gpio_is_valid(atmel_port->rts_gpio)) {
+		if (mctrl & TIOCM_RTS)
+			gpio_set_value(atmel_port->rts_gpio, 0);
+		else
+			gpio_set_value(atmel_port->rts_gpio, 1);
 	}
-#endif
 
 	if (mctrl & TIOCM_RTS)
 		control |= ATMEL_US_RTSEN;
@@ -1555,7 +1546,7 @@ static int atmel_startup(struct uart_port *port)
 	retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
 			tty ? tty->name : "atmel_serial", port);
 	if (retval) {
-		printk("atmel_serial: atmel_startup - Can't get irq\n");
+		dev_err(port->dev, "atmel_startup - Can't get irq\n");
 		return retval;
 	}
 
@@ -1575,17 +1566,6 @@ static int atmel_startup(struct uart_port *port)
 		if (retval < 0)
 			atmel_set_ops(port);
 	}
-	/*
-	 * If there is a specific "open" function (to register
-	 * control line interrupts)
-	 */
-	if (atmel_open_hook) {
-		retval = atmel_open_hook(port);
-		if (retval) {
-			free_irq(port->irq, port);
-			return retval;
-		}
-	}
 
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = UART_GET_CSR(port);
@@ -1684,13 +1664,6 @@ static void atmel_shutdown(struct uart_port *port)
 	 * Free the interrupt
 	 */
 	free_irq(port->irq, port);
-
-	/*
-	 * If there is a specific "close" function (to unregister
-	 * control line interrupts)
-	 */
-	if (atmel_close_hook)
-		atmel_close_hook(port);
 }
 
 /*
@@ -1738,7 +1711,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
 		clk_disable_unprepare(atmel_port->clk);
 		break;
 	default:
-		printk(KERN_ERR "atmel_serial: unknown pm %d\n", state);
+		dev_err(port->dev, "atmel_serial: unknown pm %d\n", state);
 	}
 }
 
@@ -1853,13 +1826,10 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	mode &= ~ATMEL_US_USMODE;
 
 	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
-		dev_dbg(port->dev, "Setting UART to RS485\n");
 		if ((atmel_port->rs485.delay_rts_after_send) > 0)
 			UART_PUT_TTGR(port,
 					atmel_port->rs485.delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
-	} else {
-		dev_dbg(port->dev, "Setting UART to RS232\n");
 	}
 
 	/* set the parity, stop bits and data size */
@@ -2389,6 +2359,25 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port = &atmel_ports[ret];
 	port->backup_imr = 0;
 	port->uart.line = ret;
+	port->rts_gpio = -EINVAL; /* Invalid, zero could be valid */
+	if (pdata)
+		port->rts_gpio = pdata->rts_gpio;
+	else if (np)
+		port->rts_gpio = of_get_named_gpio(np, "rts-gpios", 0);
+
+	if (gpio_is_valid(port->rts_gpio)) {
+		ret = devm_gpio_request(&pdev->dev, port->rts_gpio, "RTS");
+		if (ret) {
+			dev_err(&pdev->dev, "error requesting RTS GPIO\n");
+			goto err;
+		}
+		/* Default to 1 as RTS is active low */
+		ret = gpio_direction_output(port->rts_gpio, 1);
+		if (ret) {
+			dev_err(&pdev->dev, "error setting up RTS GPIO\n");
+			goto err;
+		}
+	}
 
 	ret = atmel_init_port(port, pdev);
 	if (ret)
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 78e82b017b92..a47421e4627c 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -30,6 +30,8 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_bcm63xx.h>
+#include <linux/io.h>
+#include <linux/of.h>
 
 #define BCM63XX_NR_UARTS	2
 
@@ -588,7 +590,7 @@ static int bcm_uart_request_port(struct uart_port *port)
 {
 	unsigned int size;
 
-	size = RSET_UART_SIZE;
+	size = UART_REG_SIZE;
 	if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
 		dev_err(port->dev, "Memory region busy\n");
 		return -EBUSY;
@@ -608,7 +610,7 @@ static int bcm_uart_request_port(struct uart_port *port)
  */
 static void bcm_uart_release_port(struct uart_port *port)
 {
-	release_mem_region(port->mapbase, RSET_UART_SIZE);
+	release_mem_region(port->mapbase, UART_REG_SIZE);
 	iounmap(port->membase);
 }
 
@@ -805,6 +807,9 @@ static int bcm_uart_probe(struct platform_device *pdev)
 	struct clk *clk;
 	int ret;
 
+	if (pdev->dev.of_node)
+		pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
+
 	if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
 		return -EINVAL;
 
@@ -856,6 +861,12 @@ static int bcm_uart_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id bcm63xx_of_match[] = {
+	{ .compatible = "brcm,bcm6345-uart" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, bcm63xx_of_match);
+
 /*
  * platform driver stuff
  */
@@ -865,6 +876,7 @@ static struct platform_driver bcm_uart_platform_driver = {
 	.driver	= {
 		.owner = THIS_MODULE,
 		.name  = "bcm63xx_uart",
+		.of_match_table = bcm63xx_of_match,
 	},
 };
 
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 690bdea0a0c1..d567ac5d3af4 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -286,7 +286,6 @@ static struct e100_serial rs_table[] = {
 #endif
 
 },  /* ttyS0 */
-#ifndef CONFIG_SVINTO_SIM
 	{ .baud        = DEF_BAUD,
 	  .ioport        = (unsigned char *)R_SERIAL1_CTRL,
 	  .irq         = 1U << 16, /* uses DMA 8 and 9 */
@@ -447,7 +446,6 @@ static struct e100_serial rs_table[] = {
 	  .dma_in_enabled = 0
 #endif
  }   /* ttyS3 */
-#endif
 };
 
 
@@ -1035,7 +1033,6 @@ cflag_to_etrax_baud(unsigned int cflag)
 static inline void
 e100_dtr(struct e100_serial *info, int set)
 {
-#ifndef CONFIG_SVINTO_SIM
 	unsigned char mask = e100_modem_pins[info->line].dtr_mask;
 
 #ifdef SERIAL_DEBUG_IO
@@ -1060,7 +1057,6 @@ e100_dtr(struct e100_serial *info, int set)
 	       info->line, *e100_modem_pins[info->line].dtr_shadow,
 	       E100_DTR_GET(info));
 #endif
-#endif
 }
 
 /* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
@@ -1069,7 +1065,6 @@ e100_dtr(struct e100_serial *info, int set)
 static inline void
 e100_rts(struct e100_serial *info, int set)
 {
-#ifndef CONFIG_SVINTO_SIM
 	unsigned long flags;
 	local_irq_save(flags);
 	info->rx_ctrl &= ~E100_RTS_MASK;
@@ -1079,7 +1074,6 @@ e100_rts(struct e100_serial *info, int set)
 #ifdef SERIAL_DEBUG_IO
 	printk("ser%i rts %i\n", info->line, set);
 #endif
-#endif
 }
 
 
@@ -1087,7 +1081,6 @@ e100_rts(struct e100_serial *info, int set)
 static inline void
 e100_ri_out(struct e100_serial *info, int set)
 {
-#ifndef CONFIG_SVINTO_SIM
 	/* RI is active low */
 	{
 		unsigned char mask = e100_modem_pins[info->line].ri_mask;
@@ -1099,12 +1092,10 @@ e100_ri_out(struct e100_serial *info, int set)
 		*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
 		local_irq_restore(flags);
 	}
-#endif
 }
 static inline void
 e100_cd_out(struct e100_serial *info, int set)
 {
-#ifndef CONFIG_SVINTO_SIM
 	/* CD is active low */
 	{
 		unsigned char mask = e100_modem_pins[info->line].cd_mask;
@@ -1116,27 +1107,22 @@ e100_cd_out(struct e100_serial *info, int set)
 		*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
 		local_irq_restore(flags);
 	}
-#endif
 }
 
 static inline void
 e100_disable_rx(struct e100_serial *info)
 {
-#ifndef CONFIG_SVINTO_SIM
 	/* disable the receiver */
 	info->ioport[REG_REC_CTRL] =
 		(info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
-#endif
 }
 
 static inline void
 e100_enable_rx(struct e100_serial *info)
 {
-#ifndef CONFIG_SVINTO_SIM
 	/* enable the receiver */
 	info->ioport[REG_REC_CTRL] =
 		(info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
-#endif
 }
 
 /* the rx DMA uses both the dma_descr and the dma_eop interrupts */
@@ -1554,24 +1540,6 @@ transmit_chars_dma(struct e100_serial *info)
 	unsigned int c, sentl;
 	struct etrax_dma_descr *descr;
 
-#ifdef CONFIG_SVINTO_SIM
-	/* This will output too little if tail is not 0 always since
-	 * we don't reloop to send the other part. Anyway this SHOULD be a
-	 * no-op - transmit_chars_dma would never really be called during sim
-	 * since rs_write does not write into the xmit buffer then.
-	 */
-	if (info->xmit.tail)
-		printk("Error in serial.c:transmit_chars-dma(), tail!=0\n");
-	if (info->xmit.head != info->xmit.tail) {
-		SIMCOUT(info->xmit.buf + info->xmit.tail,
-			CIRC_CNT(info->xmit.head,
-				 info->xmit.tail,
-				 SERIAL_XMIT_SIZE));
-		info->xmit.head = info->xmit.tail;  /* move back head */
-		info->tr_running = 0;
-	}
-	return;
-#endif
 	/* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
 	*info->oclrintradr =
 		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
@@ -1842,13 +1810,6 @@ static void receive_chars_dma(struct e100_serial *info)
 	struct tty_struct *tty;
 	unsigned char rstat;
 
-#ifdef CONFIG_SVINTO_SIM
-	/* No receive in the simulator.  Will probably be when the rest of
-	 * the serial interface works, and this piece will just be removed.
-	 */
-	return;
-#endif
-
 	/* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
 	*info->iclrintradr =
 		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
@@ -1934,12 +1895,6 @@ static int start_recv_dma(struct e100_serial *info)
 static void
 start_receive(struct e100_serial *info)
 {
-#ifdef CONFIG_SVINTO_SIM
-	/* No receive in the simulator.  Will probably be when the rest of
-	 * the serial interface works, and this piece will just be removed.
-	 */
-	return;
-#endif
 	if (info->uses_dma_in) {
 		/* reset the input dma channel to be sure it works */
 
@@ -1972,17 +1927,6 @@ tr_interrupt(int irq, void *dev_id)
 	int i;
 	int handled = 0;
 
-#ifdef CONFIG_SVINTO_SIM
-	/* No receive in the simulator.  Will probably be when the rest of
-	 * the serial interface works, and this piece will just be removed.
-	 */
-	{
-		const char *s = "What? tr_interrupt in simulator??\n";
-		SIMCOUT(s,strlen(s));
-	}
-	return IRQ_HANDLED;
-#endif
-
 	/* find out the line that caused this irq and get it from rs_table */
 
 	ireg = *R_IRQ_MASK2_RD;  /* get the active irq bits for the dma channels */
@@ -2021,17 +1965,6 @@ rec_interrupt(int irq, void *dev_id)
 	int i;
 	int handled = 0;
 
-#ifdef CONFIG_SVINTO_SIM
-	/* No receive in the simulator.  Will probably be when the rest of
-	 * the serial interface works, and this piece will just be removed.
-	 */
-	{
-		const char *s = "What? rec_interrupt in simulator??\n";
-		SIMCOUT(s,strlen(s));
-	}
-	return IRQ_HANDLED;
-#endif
-
 	/* find out the line that caused this irq and get it from rs_table */
 
 	ireg = *R_IRQ_MASK2_RD;  /* get the active irq bits for the dma channels */
@@ -2173,10 +2106,6 @@ timed_flush_handler(unsigned long ptr)
 	struct e100_serial *info;
 	int i;
 
-#ifdef CONFIG_SVINTO_SIM
-	return;
-#endif
-
 	for (i = 0; i < NR_PORTS; i++) {
 		info = rs_table + i;
 		if (info->uses_dma_in)
@@ -2729,25 +2658,6 @@ startup(struct e100_serial * info)
 	printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf);
 #endif
 
-#ifdef CONFIG_SVINTO_SIM
-	/* Bits and pieces collected from below.  Better to have them
-	   in one ifdef:ed clause than to mix in a lot of ifdefs,
-	   right? */
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->xmit.head = info->xmit.tail = 0;
-	info->first_recv_buffer = info->last_recv_buffer = NULL;
-	info->recv_cnt = info->max_recv_cnt = 0;
-
-	for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
-		info->rec_descr[i].buf = NULL;
-
-	/* No real action in the simulator, but may set info important
-	   to ioctl. */
-	change_speed(info);
-#else
-
 	/*
 	 * Clear the FIFO buffers and disable them
 	 * (they will be reenabled in change_speed())
@@ -2837,8 +2747,6 @@ startup(struct e100_serial * info)
 	e100_rts(info, 1);
 	e100_dtr(info, 1);
 
-#endif /* CONFIG_SVINTO_SIM */
-
 	info->port.flags |= ASYNC_INITIALIZED;
 
 	local_irq_restore(flags);
@@ -2857,7 +2765,6 @@ shutdown(struct e100_serial * info)
 	struct etrax_recv_buffer *buffer;
 	int i;
 
-#ifndef CONFIG_SVINTO_SIM
 	/* shut down the transmitter and receiver */
 	DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line));
 	e100_disable_rx(info);
@@ -2882,8 +2789,6 @@ shutdown(struct e100_serial * info)
 		info->tr_running = 0;
 	}
 
-#endif /* CONFIG_SVINTO_SIM */
-
 	if (!(info->port.flags & ASYNC_INITIALIZED))
 		return;
 
@@ -2995,17 +2900,12 @@ change_speed(struct e100_serial *info)
 			IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
 		r_alt_ser_baudrate_shadow &= ~mask;
 		r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
-#ifndef CONFIG_SVINTO_SIM
 		*R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
-#endif /* CONFIG_SVINTO_SIM */
 
 		info->baud = cflag_to_baud(cflag);
-#ifndef CONFIG_SVINTO_SIM
 		info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag);
-#endif /* CONFIG_SVINTO_SIM */
 	}
 
-#ifndef CONFIG_SVINTO_SIM
 	/* start with default settings and then fill in changes */
 	local_irq_save(flags);
 	/* 8 bit, no/even parity */
@@ -3073,7 +2973,6 @@ change_speed(struct e100_serial *info)
 
 	*((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
 	local_irq_restore(flags);
-#endif /* !CONFIG_SVINTO_SIM */
 
 	update_char_time(info);
 
@@ -3122,11 +3021,6 @@ static int rs_raw_write(struct tty_struct *tty,
 		       count, info->ioport[REG_STATUS]);
 #endif
 
-#ifdef CONFIG_SVINTO_SIM
-	/* Really simple.  The output is here and now. */
-	SIMCOUT(buf, count);
-	return count;
-#endif
 	local_save_flags(flags);
 	DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
 	DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
@@ -3463,7 +3357,6 @@ static int
 get_lsr_info(struct e100_serial * info, unsigned int *value)
 {
 	unsigned int result = TIOCSER_TEMT;
-#ifndef CONFIG_SVINTO_SIM
 	unsigned long curr_time = jiffies;
 	unsigned long curr_time_usec = GET_JIFFIES_USEC();
 	unsigned long elapsed_usec =
@@ -3474,7 +3367,6 @@ get_lsr_info(struct e100_serial * info, unsigned int *value)
 	    elapsed_usec < 2*info->char_time_usec) {
 		result = 0;
 	}
-#endif
 
 	if (copy_to_user(value, &result, sizeof(int)))
 		return -EFAULT;
@@ -3804,7 +3696,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
 	e100_disable_serial_data_irq(info);
 #endif
 
-#ifndef CONFIG_SVINTO_SIM
 	e100_disable_rx(info);
 	e100_disable_rx_irq(info);
 
@@ -3816,7 +3707,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
 		 */
 		rs_wait_until_sent(tty, HZ);
 	}
-#endif
 
 	shutdown(info);
 	rs_flush_buffer(tty);
@@ -4479,7 +4369,6 @@ static int __init rs_init(void)
 	fast_timer_init();
 #endif
 
-#ifndef CONFIG_SVINTO_SIM
 #ifndef CONFIG_ETRAX_KGDB
 	/* Not needed in simulator.  May only complicate stuff. */
 	/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
@@ -4489,7 +4378,6 @@ static int __init rs_init(void)
 		panic("%s: Failed to request irq8", __func__);
 
 #endif
-#endif /* CONFIG_SVINTO_SIM */
 
 	return 0;
 }
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 8978dc9a58b7..c5eb897de9de 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -13,14 +13,19 @@
 #define SUPPORT_SYSRQ
 #endif
 
-#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/clk.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/console.h>
+#include <linux/of_dma.h>
 #include <linux/serial_core.h>
+#include <linux/slab.h>
 #include <linux/tty_flip.h>
 
 /* All registers are 8-bit width */
@@ -112,6 +117,10 @@
 #define UARTSFIFO_TXOF		0x02
 #define UARTSFIFO_RXUF		0x01
 
+#define DMA_MAXBURST		16
+#define DMA_MAXBURST_MASK	(DMA_MAXBURST - 1)
+#define FSL_UART_RX_DMA_BUFFER_SIZE	64
+
 #define DRIVER_NAME	"fsl-lpuart"
 #define DEV_NAME	"ttyLP"
 #define UART_NR		6
@@ -121,6 +130,24 @@ struct lpuart_port {
 	struct clk		*clk;
 	unsigned int		txfifo_size;
 	unsigned int		rxfifo_size;
+
+	bool			lpuart_dma_use;
+	struct dma_chan		*dma_tx_chan;
+	struct dma_chan		*dma_rx_chan;
+	struct dma_async_tx_descriptor  *dma_tx_desc;
+	struct dma_async_tx_descriptor  *dma_rx_desc;
+	dma_addr_t		dma_tx_buf_bus;
+	dma_addr_t		dma_rx_buf_bus;
+	dma_cookie_t		dma_tx_cookie;
+	dma_cookie_t		dma_rx_cookie;
+	unsigned char		*dma_tx_buf_virt;
+	unsigned char		*dma_rx_buf_virt;
+	unsigned int		dma_tx_bytes;
+	unsigned int		dma_rx_bytes;
+	int			dma_tx_in_progress;
+	int			dma_rx_in_progress;
+	unsigned int		dma_rx_timeout;
+	struct timer_list	lpuart_timer;
 };
 
 static struct of_device_id lpuart_dt_ids[] = {
@@ -131,6 +158,10 @@ static struct of_device_id lpuart_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
 
+/* Forward declare this for the dma callbacks*/
+static void lpuart_dma_tx_complete(void *arg);
+static void lpuart_dma_rx_complete(void *arg);
+
 static void lpuart_stop_tx(struct uart_port *port)
 {
 	unsigned char temp;
@@ -152,6 +183,210 @@ static void lpuart_enable_ms(struct uart_port *port)
 {
 }
 
+static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
+		struct tty_port *tty, int count)
+{
+	int copied;
+
+	sport->port.icount.rx += count;
+
+	if (!tty) {
+		dev_err(sport->port.dev, "No tty port\n");
+		return;
+	}
+
+	dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
+			FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+	copied = tty_insert_flip_string(tty,
+			((unsigned char *)(sport->dma_rx_buf_virt)), count);
+
+	if (copied != count) {
+		WARN_ON(1);
+		dev_err(sport->port.dev, "RxData copy to tty layer failed\n");
+	}
+
+	dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
+			FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
+}
+
+static void lpuart_pio_tx(struct lpuart_port *sport)
+{
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	while (!uart_circ_empty(xmit) &&
+		readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size) {
+		writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->port.icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
+
+	if (uart_circ_empty(xmit))
+		writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
+			sport->port.membase + UARTCR5);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
+{
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	dma_addr_t tx_bus_addr;
+
+	dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
+				UART_XMIT_SIZE, DMA_TO_DEVICE);
+	sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
+	tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
+	sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
+					tx_bus_addr, sport->dma_tx_bytes,
+					DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+
+	if (!sport->dma_tx_desc) {
+		dev_err(sport->port.dev, "Not able to get desc for tx\n");
+		return -EIO;
+	}
+
+	sport->dma_tx_desc->callback = lpuart_dma_tx_complete;
+	sport->dma_tx_desc->callback_param = sport;
+	sport->dma_tx_in_progress = 1;
+	sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
+	dma_async_issue_pending(sport->dma_tx_chan);
+
+	return 0;
+}
+
+static void lpuart_prepare_tx(struct lpuart_port *sport)
+{
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	unsigned long count =  CIRC_CNT_TO_END(xmit->head,
+					xmit->tail, UART_XMIT_SIZE);
+
+	if (!count)
+		return;
+
+	if (count < DMA_MAXBURST)
+		writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
+				sport->port.membase + UARTCR5);
+	else {
+		writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
+				sport->port.membase + UARTCR5);
+		lpuart_dma_tx(sport, count);
+	}
+}
+
+static void lpuart_dma_tx_complete(void *arg)
+{
+	struct lpuart_port *sport = arg;
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	unsigned long flags;
+
+	async_tx_ack(sport->dma_tx_desc);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
+	sport->dma_tx_in_progress = 0;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
+
+	lpuart_prepare_tx(sport);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int lpuart_dma_rx(struct lpuart_port *sport)
+{
+	dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
+			FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
+	sport->dma_rx_desc = dmaengine_prep_slave_single(sport->dma_rx_chan,
+			sport->dma_rx_buf_bus, FSL_UART_RX_DMA_BUFFER_SIZE,
+			DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+
+	if (!sport->dma_rx_desc) {
+		dev_err(sport->port.dev, "Not able to get desc for rx\n");
+		return -EIO;
+	}
+
+	sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
+	sport->dma_rx_desc->callback_param = sport;
+	sport->dma_rx_in_progress = 1;
+	sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
+	dma_async_issue_pending(sport->dma_rx_chan);
+
+	return 0;
+}
+
+static void lpuart_dma_rx_complete(void *arg)
+{
+	struct lpuart_port *sport = arg;
+	struct tty_port *port = &sport->port.state->port;
+	unsigned long flags;
+
+	async_tx_ack(sport->dma_rx_desc);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	sport->dma_rx_in_progress = 0;
+	lpuart_copy_rx_to_tty(sport, port, FSL_UART_RX_DMA_BUFFER_SIZE);
+	tty_flip_buffer_push(port);
+	lpuart_dma_rx(sport);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static void lpuart_timer_func(unsigned long data)
+{
+	struct lpuart_port *sport = (struct lpuart_port *)data;
+	struct tty_port *port = &sport->port.state->port;
+	struct dma_tx_state state;
+	unsigned long flags;
+	unsigned char temp;
+	int count;
+
+	del_timer(&sport->lpuart_timer);
+	dmaengine_pause(sport->dma_rx_chan);
+	dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
+	dmaengine_terminate_all(sport->dma_rx_chan);
+	count = FSL_UART_RX_DMA_BUFFER_SIZE - state.residue;
+	async_tx_ack(sport->dma_rx_desc);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	sport->dma_rx_in_progress = 0;
+	lpuart_copy_rx_to_tty(sport, port, count);
+	tty_flip_buffer_push(port);
+	temp = readb(sport->port.membase + UARTCR5);
+	writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static inline void lpuart_prepare_rx(struct lpuart_port *sport)
+{
+	unsigned long flags;
+	unsigned char temp;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	init_timer(&sport->lpuart_timer);
+	sport->lpuart_timer.function = lpuart_timer_func;
+	sport->lpuart_timer.data = (unsigned long)sport;
+	sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
+	add_timer(&sport->lpuart_timer);
+
+	lpuart_dma_rx(sport);
+	temp = readb(sport->port.membase + UARTCR5);
+	writeb(temp | UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
 static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
@@ -172,14 +407,21 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
 
 static void lpuart_start_tx(struct uart_port *port)
 {
-	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	struct lpuart_port *sport = container_of(port,
+			struct lpuart_port, port);
+	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned char temp;
 
 	temp = readb(port->membase + UARTCR2);
 	writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
 
-	if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
-		lpuart_transmit_buffer(sport);
+	if (sport->lpuart_dma_use) {
+		if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
+			lpuart_prepare_tx(sport);
+	} else {
+		if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
+			lpuart_transmit_buffer(sport);
+	}
 }
 
 static irqreturn_t lpuart_txint(int irq, void *dev_id)
@@ -279,12 +521,19 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
 
 	sts = readb(sport->port.membase + UARTSR1);
 
-	if (sts & UARTSR1_RDRF)
-		lpuart_rxint(irq, dev_id);
-
+	if (sts & UARTSR1_RDRF) {
+		if (sport->lpuart_dma_use)
+			lpuart_prepare_rx(sport);
+		else
+			lpuart_rxint(irq, dev_id);
+	}
 	if (sts & UARTSR1_TDRE &&
-		!(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS))
-		lpuart_txint(irq, dev_id);
+		!(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) {
+		if (sport->lpuart_dma_use)
+			lpuart_pio_tx(sport);
+		else
+			lpuart_txint(irq, dev_id);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -366,13 +615,156 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
 	writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
 			sport->port.membase + UARTCFIFO);
 
-	writeb(2, sport->port.membase + UARTTWFIFO);
+	writeb(0, sport->port.membase + UARTTWFIFO);
 	writeb(1, sport->port.membase + UARTRWFIFO);
 
 	/* Restore cr2 */
 	writeb(cr2_saved, sport->port.membase + UARTCR2);
 }
 
+static int lpuart_dma_tx_request(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port,
+					struct lpuart_port, port);
+	struct dma_chan *tx_chan;
+	struct dma_slave_config dma_tx_sconfig;
+	dma_addr_t dma_bus;
+	unsigned char *dma_buf;
+	int ret;
+
+	tx_chan  = dma_request_slave_channel(sport->port.dev, "tx");
+
+	if (!tx_chan) {
+		dev_err(sport->port.dev, "Dma tx channel request failed!\n");
+		return -ENODEV;
+	}
+
+	dma_bus = dma_map_single(tx_chan->device->dev,
+				sport->port.state->xmit.buf,
+				UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+	if (dma_mapping_error(tx_chan->device->dev, dma_bus)) {
+		dev_err(sport->port.dev, "dma_map_single tx failed\n");
+		dma_release_channel(tx_chan);
+		return -ENOMEM;
+	}
+
+	dma_buf = sport->port.state->xmit.buf;
+	dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
+	dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
+	dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
+	ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
+
+	if (ret < 0) {
+		dev_err(sport->port.dev,
+				"Dma slave config failed, err = %d\n", ret);
+		dma_release_channel(tx_chan);
+		return ret;
+	}
+
+	sport->dma_tx_chan = tx_chan;
+	sport->dma_tx_buf_virt = dma_buf;
+	sport->dma_tx_buf_bus = dma_bus;
+	sport->dma_tx_in_progress = 0;
+
+	return 0;
+}
+
+static int lpuart_dma_rx_request(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port,
+					struct lpuart_port, port);
+	struct dma_chan *rx_chan;
+	struct dma_slave_config dma_rx_sconfig;
+	dma_addr_t dma_bus;
+	unsigned char *dma_buf;
+	int ret;
+
+	rx_chan  = dma_request_slave_channel(sport->port.dev, "rx");
+
+	if (!rx_chan) {
+		dev_err(sport->port.dev, "Dma rx channel request failed!\n");
+		return -ENODEV;
+	}
+
+	dma_buf = devm_kzalloc(sport->port.dev,
+				FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
+
+	if (!dma_buf) {
+		dev_err(sport->port.dev, "Dma rx alloc failed\n");
+		dma_release_channel(rx_chan);
+		return -ENOMEM;
+	}
+
+	dma_bus = dma_map_single(rx_chan->device->dev, dma_buf,
+				FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(rx_chan->device->dev, dma_bus)) {
+		dev_err(sport->port.dev, "dma_map_single rx failed\n");
+		dma_release_channel(rx_chan);
+		return -ENOMEM;
+	}
+
+	dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
+	dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_rx_sconfig.src_maxburst = 1;
+	dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
+	ret = dmaengine_slave_config(rx_chan, &dma_rx_sconfig);
+
+	if (ret < 0) {
+		dev_err(sport->port.dev,
+				"Dma slave config failed, err = %d\n", ret);
+		dma_release_channel(rx_chan);
+		return ret;
+	}
+
+	sport->dma_rx_chan = rx_chan;
+	sport->dma_rx_buf_virt = dma_buf;
+	sport->dma_rx_buf_bus = dma_bus;
+	sport->dma_rx_in_progress = 0;
+
+	sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
+				FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
+				sport->rxfifo_size / 2;
+
+	if (sport->dma_rx_timeout < msecs_to_jiffies(20))
+		sport->dma_rx_timeout = msecs_to_jiffies(20);
+
+	return 0;
+}
+
+static void lpuart_dma_tx_free(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port,
+					struct lpuart_port, port);
+	struct dma_chan *dma_chan;
+
+	dma_unmap_single(sport->port.dev, sport->dma_tx_buf_bus,
+			UART_XMIT_SIZE, DMA_TO_DEVICE);
+	dma_chan = sport->dma_tx_chan;
+	sport->dma_tx_chan = NULL;
+	sport->dma_tx_buf_bus = 0;
+	sport->dma_tx_buf_virt = NULL;
+	dma_release_channel(dma_chan);
+}
+
+static void lpuart_dma_rx_free(struct uart_port *port)
+{
+	struct lpuart_port *sport = container_of(port,
+					struct lpuart_port, port);
+	struct dma_chan *dma_chan;
+
+	dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
+			FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+	dma_chan = sport->dma_rx_chan;
+	sport->dma_rx_chan = NULL;
+	sport->dma_rx_buf_bus = 0;
+	sport->dma_rx_buf_virt = NULL;
+	dma_release_channel(dma_chan);
+}
+
 static int lpuart_startup(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -380,6 +772,15 @@ static int lpuart_startup(struct uart_port *port)
 	unsigned long flags;
 	unsigned char temp;
 
+	/*whether use dma support by dma request results*/
+	if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
+		sport->lpuart_dma_use = false;
+	} else {
+		sport->lpuart_dma_use = true;
+		temp = readb(port->membase + UARTCR5);
+		writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
+	}
+
 	ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
 				DRIVER_NAME, sport);
 	if (ret)
@@ -414,6 +815,11 @@ static void lpuart_shutdown(struct uart_port *port)
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	devm_free_irq(port->dev, port->irq, sport);
+
+	if (sport->lpuart_dma_use) {
+		lpuart_dma_tx_free(port);
+		lpuart_dma_rx_free(port);
+	}
 }
 
 static void
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d799140e53b6..3b6c1a2e25de 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -496,8 +496,7 @@ static void dma_tx_callback(void *data)
 
 	dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&sport->port);
+	uart_write_wakeup(&sport->port);
 
 	if (waitqueue_active(&sport->dma_wait)) {
 		wake_up(&sport->dma_wait);
@@ -1117,25 +1116,25 @@ static int imx_startup(struct uart_port *port)
 	 */
 	if (sport->txirq > 0) {
 		retval = request_irq(sport->rxirq, imx_rxint, 0,
-				DRIVER_NAME, sport);
+				     dev_name(port->dev), sport);
 		if (retval)
 			goto error_out1;
 
 		retval = request_irq(sport->txirq, imx_txint, 0,
-				DRIVER_NAME, sport);
+				     dev_name(port->dev), sport);
 		if (retval)
 			goto error_out2;
 
 		/* do not use RTS IRQ on IrDA */
 		if (!USE_IRDA(sport)) {
 			retval = request_irq(sport->rtsirq, imx_rtsint, 0,
-					DRIVER_NAME, sport);
+					     dev_name(port->dev), sport);
 			if (retval)
 				goto error_out3;
 		}
 	} else {
 		retval = request_irq(sport->port.irq, imx_int, 0,
-				DRIVER_NAME, sport);
+				     dev_name(port->dev), sport);
 		if (retval) {
 			free_irq(sport->port.irq, sport);
 			goto error_out1;
@@ -1470,44 +1469,13 @@ static const char *imx_type(struct uart_port *port)
 }
 
 /*
- * Release the memory region(s) being used by 'port'.
- */
-static void imx_release_port(struct uart_port *port)
-{
-	struct platform_device *pdev = to_platform_device(port->dev);
-	struct resource *mmres;
-
-	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mmres->start, resource_size(mmres));
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int imx_request_port(struct uart_port *port)
-{
-	struct platform_device *pdev = to_platform_device(port->dev);
-	struct resource *mmres;
-	void *ret;
-
-	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mmres)
-		return -ENODEV;
-
-	ret = request_mem_region(mmres->start, resource_size(mmres), "imx-uart");
-
-	return  ret ? 0 : -EBUSY;
-}
-
-/*
  * Configure/autoconfigure the port.
  */
 static void imx_config_port(struct uart_port *port, int flags)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
-	if (flags & UART_CONFIG_TYPE &&
-	    imx_request_port(&sport->port) == 0)
+	if (flags & UART_CONFIG_TYPE)
 		sport->port.type = PORT_IMX;
 }
 
@@ -1617,8 +1585,6 @@ static struct uart_ops imx_pops = {
 	.flush_buffer	= imx_flush_buffer,
 	.set_termios	= imx_set_termios,
 	.type		= imx_type,
-	.release_port	= imx_release_port,
-	.request_port	= imx_request_port,
 	.config_port	= imx_config_port,
 	.verify_port	= imx_verify_port,
 #if defined(CONFIG_CONSOLE_POLL)
@@ -1935,7 +1901,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
 static int serial_imx_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
-	struct imxuart_platform_data *pdata;
 	void __iomem *base;
 	int ret = 0;
 	struct resource *res;
@@ -1951,12 +1916,9 @@ static int serial_imx_probe(struct platform_device *pdev)
 		return ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	base = devm_ioremap(&pdev->dev, res->start, PAGE_SIZE);
-	if (!base)
-		return -ENOMEM;
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	sport->port.dev = &pdev->dev;
 	sport->port.mapbase = res->start;
@@ -1992,38 +1954,16 @@ static int serial_imx_probe(struct platform_device *pdev)
 
 	imx_ports[sport->port.line] = sport;
 
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata && pdata->init) {
-		ret = pdata->init(pdev);
-		if (ret)
-			return ret;
-	}
-
-	ret = uart_add_one_port(&imx_reg, &sport->port);
-	if (ret)
-		goto deinit;
 	platform_set_drvdata(pdev, sport);
 
-	return 0;
-deinit:
-	if (pdata && pdata->exit)
-		pdata->exit(pdev);
-	return ret;
+	return uart_add_one_port(&imx_reg, &sport->port);
 }
 
 static int serial_imx_remove(struct platform_device *pdev)
 {
-	struct imxuart_platform_data *pdata;
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	pdata = dev_get_platdata(&pdev->dev);
-
-	uart_remove_one_port(&imx_reg, &sport->port);
-
-	if (pdata && pdata->exit)
-		pdata->exit(pdev);
-
-	return 0;
+	return uart_remove_one_port(&imx_reg, &sport->port);
 }
 
 static struct platform_driver serial_imx_driver = {
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 8d71e4047bb3..471dbc1e2b58 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1,7 +1,7 @@
 /*
  *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
  *
- *  Copyright (C) 2012-2013 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
  *
  *  Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
  *  Based on max3110.c, by Feng Tang <feng.tang@intel.com>
@@ -13,20 +13,21 @@
  *  (at your option) any later version.
  */
 
-#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include <linux/regmap.h>
-#include <linux/gpio.h>
 #include <linux/spi/spi.h>
 
-#include <linux/platform_data/max310x.h>
-
 #define MAX310X_NAME			"max310x"
 #define MAX310X_MAJOR			204
 #define MAX310X_MINOR			209
@@ -161,10 +162,6 @@
 /* IRDA register bits */
 #define MAX310X_IRDA_IRDAEN_BIT		(1 << 0) /* IRDA mode enable */
 #define MAX310X_IRDA_SIR_BIT		(1 << 1) /* SIR mode enable */
-#define MAX310X_IRDA_SHORTIR_BIT	(1 << 2) /* Short SIR mode enable */
-#define MAX310X_IRDA_MIR_BIT		(1 << 3) /* MIR mode enable */
-#define MAX310X_IRDA_RXINV_BIT		(1 << 4) /* RX logic inversion enable */
-#define MAX310X_IRDA_TXINV_BIT		(1 << 5) /* TX logic inversion enable */
 
 /* Flow control trigger level register masks */
 #define MAX310X_FLOWLVL_HALT_MASK	(0x000f) /* Flow control halt level */
@@ -220,26 +217,6 @@
 						  *       XOFF2
 						  */
 
-/* GPIO configuration register bits */
-#define MAX310X_GPIOCFG_GP0OUT_BIT	(1 << 0) /* GPIO 0 output enable */
-#define MAX310X_GPIOCFG_GP1OUT_BIT	(1 << 1) /* GPIO 1 output enable */
-#define MAX310X_GPIOCFG_GP2OUT_BIT	(1 << 2) /* GPIO 2 output enable */
-#define MAX310X_GPIOCFG_GP3OUT_BIT	(1 << 3) /* GPIO 3 output enable */
-#define MAX310X_GPIOCFG_GP0OD_BIT	(1 << 4) /* GPIO 0 open-drain enable */
-#define MAX310X_GPIOCFG_GP1OD_BIT	(1 << 5) /* GPIO 1 open-drain enable */
-#define MAX310X_GPIOCFG_GP2OD_BIT	(1 << 6) /* GPIO 2 open-drain enable */
-#define MAX310X_GPIOCFG_GP3OD_BIT	(1 << 7) /* GPIO 3 open-drain enable */
-
-/* GPIO DATA register bits */
-#define MAX310X_GPIODATA_GP0OUT_BIT	(1 << 0) /* GPIO 0 output value */
-#define MAX310X_GPIODATA_GP1OUT_BIT	(1 << 1) /* GPIO 1 output value */
-#define MAX310X_GPIODATA_GP2OUT_BIT	(1 << 2) /* GPIO 2 output value */
-#define MAX310X_GPIODATA_GP3OUT_BIT	(1 << 3) /* GPIO 3 output value */
-#define MAX310X_GPIODATA_GP0IN_BIT	(1 << 4) /* GPIO 0 input value */
-#define MAX310X_GPIODATA_GP1IN_BIT	(1 << 5) /* GPIO 1 input value */
-#define MAX310X_GPIODATA_GP2IN_BIT	(1 << 6) /* GPIO 2 input value */
-#define MAX310X_GPIODATA_GP3IN_BIT	(1 << 7) /* GPIO 3 input value */
-
 /* PLL configuration register masks */
 #define MAX310X_PLLCFG_PREDIV_MASK	(0x3f) /* PLL predivision value */
 #define MAX310X_PLLCFG_PLLFACTOR_MASK	(0xc0) /* PLL multiplication factor */
@@ -283,16 +260,15 @@ struct max310x_devtype {
 struct max310x_one {
 	struct uart_port	port;
 	struct work_struct	tx_work;
+	struct work_struct	md_work;
 };
 
 struct max310x_port {
 	struct uart_driver	uart;
 	struct max310x_devtype	*devtype;
 	struct regmap		*regmap;
-	struct regmap_config	regcfg;
 	struct mutex		mutex;
-	struct max310x_pdata	*pdata;
-	int			gpio_used;
+	struct clk		*clk;
 #ifdef CONFIG_GPIOLIB
 	struct gpio_chip	gpio;
 #endif
@@ -504,25 +480,33 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
 	return false;
 }
 
-static void max310x_set_baud(struct uart_port *port, int baud)
+static int max310x_set_baud(struct uart_port *port, int baud)
 {
-	unsigned int mode = 0, div = port->uartclk / baud;
+	unsigned int mode = 0, clk = port->uartclk, div = clk / baud;
 
-	if (!(div / 16)) {
+	/* Check for minimal value for divider */
+	if (div < 16)
+		div = 16;
+
+	if (clk % baud && (div / 16) < 0x8000) {
 		/* Mode x2 */
 		mode = MAX310X_BRGCFG_2XMODE_BIT;
-		div = (port->uartclk * 2) / baud;
-	}
-
-	if (!(div / 16)) {
-		/* Mode x4 */
-		mode = MAX310X_BRGCFG_4XMODE_BIT;
-		div = (port->uartclk * 4) / baud;
+		clk = port->uartclk * 2;
+		div = clk / baud;
+
+		if (clk % baud && (div / 16) < 0x8000) {
+			/* Mode x4 */
+			mode = MAX310X_BRGCFG_4XMODE_BIT;
+			clk = port->uartclk * 4;
+			div = clk / baud;
+		}
 	}
 
 	max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
 	max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
 	max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
+
+	return DIV_ROUND_CLOSEST(clk, div);
 }
 
 static int max310x_update_best_err(unsigned long f, long *besterr)
@@ -538,18 +522,19 @@ static int max310x_update_best_err(unsigned long f, long *besterr)
 	return 1;
 }
 
-static int max310x_set_ref_clk(struct max310x_port *s)
+static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
+			       bool xtal)
 {
 	unsigned int div, clksrc, pllcfg = 0;
 	long besterr = -1;
-	unsigned long fdiv, fmul, bestfreq = s->pdata->frequency;
+	unsigned long fdiv, fmul, bestfreq = freq;
 
 	/* First, update error without PLL */
-	max310x_update_best_err(s->pdata->frequency, &besterr);
+	max310x_update_best_err(freq, &besterr);
 
 	/* Try all possible PLL dividers */
 	for (div = 1; (div <= 63) && besterr; div++) {
-		fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div);
+		fdiv = DIV_ROUND_CLOSEST(freq, div);
 
 		/* Try multiplier 6 */
 		fmul = fdiv * 6;
@@ -582,10 +567,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
 	}
 
 	/* Configure clock source */
-	if (s->pdata->driver_flags & MAX310X_EXT_CLK)
-		clksrc = MAX310X_CLKSRC_EXTCLK_BIT;
-	else
-		clksrc = MAX310X_CLKSRC_CRYST_BIT;
+	clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT;
 
 	/* Configure PLL */
 	if (pllcfg) {
@@ -597,7 +579,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
 	regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
 
 	/* Wait for crystal */
-	if (pllcfg && !(s->pdata->driver_flags & MAX310X_EXT_CLK))
+	if (pllcfg && xtal)
 		msleep(10);
 
 	return (int)bestfreq;
@@ -782,11 +764,21 @@ static unsigned int max310x_get_mctrl(struct uart_port *port)
 	return TIOCM_DSR | TIOCM_CAR;
 }
 
+static void max310x_md_proc(struct work_struct *ws)
+{
+	struct max310x_one *one = container_of(ws, struct max310x_one, md_work);
+
+	max310x_port_update(&one->port, MAX310X_MODE2_REG,
+			    MAX310X_MODE2_LOOPBACK_BIT,
+			    (one->port.mctrl & TIOCM_LOOP) ?
+			    MAX310X_MODE2_LOOPBACK_BIT : 0);
+}
+
 static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-	/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
-	 * so do nothing
-	 */
+	struct max310x_one *one = container_of(port, struct max310x_one, port);
+
+	schedule_work(&one->md_work);
 }
 
 static void max310x_break_ctl(struct uart_port *port, int break_state)
@@ -875,40 +867,76 @@ static void max310x_set_termios(struct uart_port *port,
 				  port->uartclk / 4);
 
 	/* Setup baudrate generator */
-	max310x_set_baud(port, baud);
+	baud = max310x_set_baud(port, baud);
 
 	/* Update timeout according to new baud rate */
 	uart_update_timeout(port, termios->c_cflag, baud);
 }
 
+static int max310x_ioctl(struct uart_port *port, unsigned int cmd,
+			 unsigned long arg)
+{
+#if defined(TIOCSRS485) && defined(TIOCGRS485)
+	struct serial_rs485 rs485;
+	unsigned int val;
+
+	switch (cmd) {
+	case TIOCSRS485:
+		if (copy_from_user(&rs485, (void __user *)arg, sizeof(rs485)))
+			return -EFAULT;
+		if (rs485.delay_rts_before_send > 0x0f ||
+		    rs485.delay_rts_after_send > 0x0f)
+			return -ERANGE;
+		val = (rs485.delay_rts_before_send << 4) |
+		      rs485.delay_rts_after_send;
+		max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val);
+		if (rs485.flags & SER_RS485_ENABLED) {
+			max310x_port_update(port, MAX310X_MODE1_REG,
+					    MAX310X_MODE1_TRNSCVCTRL_BIT,
+					    MAX310X_MODE1_TRNSCVCTRL_BIT);
+			max310x_port_update(port, MAX310X_MODE2_REG,
+					    MAX310X_MODE2_ECHOSUPR_BIT,
+					    MAX310X_MODE2_ECHOSUPR_BIT);
+		} else {
+			max310x_port_update(port, MAX310X_MODE1_REG,
+					    MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
+			max310x_port_update(port, MAX310X_MODE2_REG,
+					    MAX310X_MODE2_ECHOSUPR_BIT, 0);
+		}
+		return 0;
+	case TIOCGRS485:
+		memset(&rs485, 0, sizeof(rs485));
+		val = max310x_port_read(port, MAX310X_MODE1_REG);
+		rs485.flags = (val & MAX310X_MODE1_TRNSCVCTRL_BIT) ?
+			      SER_RS485_ENABLED : 0;
+		rs485.flags |= SER_RS485_RTS_ON_SEND;
+		val = max310x_port_read(port, MAX310X_HDPIXDELAY_REG);
+		rs485.delay_rts_before_send = val >> 4;
+		rs485.delay_rts_after_send = val & 0x0f;
+		if (copy_to_user((void __user *)arg, &rs485, sizeof(rs485)))
+			return -EFAULT;
+		return 0;
+	default:
+		break;
+	}
+#endif
+
+	return -ENOIOCTLCMD;
+}
+
 static int max310x_startup(struct uart_port *port)
 {
-	unsigned int val, line = port->line;
 	struct max310x_port *s = dev_get_drvdata(port->dev);
+	unsigned int val;
 
 	s->devtype->power(port, 1);
 
-	/* Configure baud rate, 9600 as default */
-	max310x_set_baud(port, 9600);
-
-	/* Configure LCR register, 8N1 mode by default */
-	max310x_port_write(port, MAX310X_LCR_REG, MAX310X_LCR_WORD_LEN_8);
-
 	/* Configure MODE1 register */
 	max310x_port_update(port, MAX310X_MODE1_REG,
-			    MAX310X_MODE1_TRNSCVCTRL_BIT,
-			    (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
-			    ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
-
-	/* Configure MODE2 register */
-	val = MAX310X_MODE2_RXEMPTINV_BIT;
-	if (s->pdata->uart_flags[line] & MAX310X_LOOPBACK)
-		val |= MAX310X_MODE2_LOOPBACK_BIT;
-	if (s->pdata->uart_flags[line] & MAX310X_ECHO_SUPRESS)
-		val |= MAX310X_MODE2_ECHOSUPR_BIT;
-
-	/* Reset FIFOs */
-	val |= MAX310X_MODE2_FIFORST_BIT;
+			    MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
+
+	/* Configure MODE2 register & Reset FIFOs*/
+	val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
 	max310x_port_write(port, MAX310X_MODE2_REG, val);
 	max310x_port_update(port, MAX310X_MODE2_REG,
 			    MAX310X_MODE2_FIFORST_BIT, 0);
@@ -989,6 +1017,7 @@ static const struct uart_ops max310x_ops = {
 	.release_port	= max310x_null_void,
 	.config_port	= max310x_config_port,
 	.verify_port	= max310x_verify_port,
+	.ioctl		= max310x_ioctl,
 };
 
 static int __maybe_unused max310x_suspend(struct device *dev)
@@ -1017,6 +1046,8 @@ static int __maybe_unused max310x_resume(struct device *dev)
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
+
 #ifdef CONFIG_GPIOLIB
 static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
@@ -1063,23 +1094,16 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
 }
 #endif
 
-static int max310x_probe(struct device *dev, int is_spi,
-			 struct max310x_devtype *devtype, int irq)
+static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
+			 struct regmap *regmap, int irq, unsigned long flags)
 {
+	int i, ret, fmin, fmax, freq, uartclk;
+	struct clk *clk_osc, *clk_xtal;
 	struct max310x_port *s;
-	struct max310x_pdata *pdata = dev_get_platdata(dev);
-	int i, ret, uartclk;
-
-	/* Check for IRQ */
-	if (irq <= 0) {
-		dev_err(dev, "No IRQ specified\n");
-		return -ENOTSUPP;
-	}
+	bool xtal = false;
 
-	if (!pdata) {
-		dev_err(dev, "No platform data supplied\n");
-		return -EINVAL;
-	}
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
 
 	/* Alloc port structure */
 	s = devm_kzalloc(dev, sizeof(*s) +
@@ -1089,52 +1113,44 @@ static int max310x_probe(struct device *dev, int is_spi,
 		return -ENOMEM;
 	}
 
-	/* Check input frequency */
-	if ((pdata->driver_flags & MAX310X_EXT_CLK) &&
-	   ((pdata->frequency < 500000) || (pdata->frequency > 35000000)))
-		goto err_freq;
-	/* Check frequency for quartz */
-	if (!(pdata->driver_flags & MAX310X_EXT_CLK) &&
-	   ((pdata->frequency < 1000000) || (pdata->frequency > 4000000)))
-		goto err_freq;
-
-	s->pdata = pdata;
-	s->devtype = devtype;
-	dev_set_drvdata(dev, s);
-
-	mutex_init(&s->mutex);
+	clk_osc = devm_clk_get(dev, "osc");
+	clk_xtal = devm_clk_get(dev, "xtal");
+	if (!IS_ERR(clk_osc)) {
+		s->clk = clk_osc;
+		fmin = 500000;
+		fmax = 35000000;
+	} else if (!IS_ERR(clk_xtal)) {
+		s->clk = clk_xtal;
+		fmin = 1000000;
+		fmax = 4000000;
+		xtal = true;
+	} else if (PTR_ERR(clk_osc) == -EPROBE_DEFER ||
+		   PTR_ERR(clk_xtal) == -EPROBE_DEFER) {
+		return -EPROBE_DEFER;
+	} else {
+		dev_err(dev, "Cannot get clock\n");
+		return -EINVAL;
+	}
 
-	/* Setup regmap */
-	s->regcfg.reg_bits		= 8;
-	s->regcfg.val_bits		= 8;
-	s->regcfg.read_flag_mask	= 0x00;
-	s->regcfg.write_flag_mask	= 0x80;
-	s->regcfg.cache_type		= REGCACHE_RBTREE;
-	s->regcfg.writeable_reg		= max310x_reg_writeable;
-	s->regcfg.volatile_reg		= max310x_reg_volatile;
-	s->regcfg.precious_reg		= max310x_reg_precious;
-	s->regcfg.max_register		= devtype->nr * 0x20 - 1;
-
-	if (IS_ENABLED(CONFIG_SPI_MASTER) && is_spi) {
-		struct spi_device *spi = to_spi_device(dev);
-
-		s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
-	} else
-		return -ENOTSUPP;
+	ret = clk_prepare_enable(s->clk);
+	if (ret)
+		return ret;
 
-	if (IS_ERR(s->regmap)) {
-		dev_err(dev, "Failed to initialize register map\n");
-		return PTR_ERR(s->regmap);
+	freq = clk_get_rate(s->clk);
+	/* Check frequency limits */
+	if (freq < fmin || freq > fmax) {
+		ret = -ERANGE;
+		goto out_clk;
 	}
 
-	/* Board specific configure */
-	if (s->pdata->init)
-		s->pdata->init();
+	s->regmap = regmap;
+	s->devtype = devtype;
+	dev_set_drvdata(dev, s);
 
 	/* Check device to ensure we are talking to what we expect */
 	ret = devtype->detect(dev);
 	if (ret)
-		return ret;
+		goto out_clk;
 
 	for (i = 0; i < devtype->nr; i++) {
 		unsigned int offs = i << 5;
@@ -1156,7 +1172,7 @@ static int max310x_probe(struct device *dev, int is_spi,
 				   MAX310X_MODE1_AUTOSLEEP_BIT);
 	}
 
-	uartclk = max310x_set_ref_clk(s);
+	uartclk = max310x_set_ref_clk(s, freq, xtal);
 	dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
 
 	/* Register UART driver */
@@ -1168,9 +1184,28 @@ static int max310x_probe(struct device *dev, int is_spi,
 	ret = uart_register_driver(&s->uart);
 	if (ret) {
 		dev_err(dev, "Registering UART driver failed\n");
-		return ret;
+		goto out_clk;
 	}
 
+#ifdef CONFIG_GPIOLIB
+	/* Setup GPIO cotroller */
+	s->gpio.owner		= THIS_MODULE;
+	s->gpio.dev		= dev;
+	s->gpio.label		= dev_name(dev);
+	s->gpio.direction_input	= max310x_gpio_direction_input;
+	s->gpio.get		= max310x_gpio_get;
+	s->gpio.direction_output= max310x_gpio_direction_output;
+	s->gpio.set		= max310x_gpio_set;
+	s->gpio.base		= -1;
+	s->gpio.ngpio		= devtype->nr * 4;
+	s->gpio.can_sleep	= 1;
+	ret = gpiochip_add(&s->gpio);
+	if (ret)
+		goto out_uart;
+#endif
+
+	mutex_init(&s->mutex);
+
 	for (i = 0; i < devtype->nr; i++) {
 		/* Initialize port data */
 		s->p[i].port.line	= i;
@@ -1178,8 +1213,7 @@ static int max310x_probe(struct device *dev, int is_spi,
 		s->p[i].port.irq	= irq;
 		s->p[i].port.type	= PORT_MAX310X;
 		s->p[i].port.fifosize	= MAX310X_FIFO_SIZE;
-		s->p[i].port.flags	= UPF_SKIP_TEST | UPF_FIXED_TYPE |
-					  UPF_LOW_LATENCY;
+		s->p[i].port.flags	= UPF_FIXED_TYPE | UPF_LOW_LATENCY;
 		s->p[i].port.iotype	= UPIO_PORT;
 		s->p[i].port.iobase	= i * 0x20;
 		s->p[i].port.membase	= (void __iomem *)~0;
@@ -1195,48 +1229,35 @@ static int max310x_probe(struct device *dev, int is_spi,
 				    MAX310X_MODE1_IRQSEL_BIT);
 		/* Initialize queue for start TX */
 		INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
+		/* Initialize queue for changing mode */
+		INIT_WORK(&s->p[i].md_work, max310x_md_proc);
 		/* Register port */
 		uart_add_one_port(&s->uart, &s->p[i].port);
 		/* Go to suspend mode */
 		devtype->power(&s->p[i].port, 0);
 	}
 
-#ifdef CONFIG_GPIOLIB
-	/* Setup GPIO cotroller */
-	if (s->pdata->gpio_base) {
-		s->gpio.owner		= THIS_MODULE;
-		s->gpio.dev		= dev;
-		s->gpio.label		= dev_name(dev);
-		s->gpio.direction_input	= max310x_gpio_direction_input;
-		s->gpio.get		= max310x_gpio_get;
-		s->gpio.direction_output= max310x_gpio_direction_output;
-		s->gpio.set		= max310x_gpio_set;
-		s->gpio.base		= s->pdata->gpio_base;
-		s->gpio.ngpio		= devtype->nr * 4;
-		s->gpio.can_sleep	= 1;
-		if (!gpiochip_add(&s->gpio))
-			s->gpio_used = 1;
-	} else
-		dev_info(dev, "GPIO support not enabled\n");
-#endif
-
 	/* Setup interrupt */
 	ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
-					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-					dev_name(dev), s);
-	if (ret) {
-		dev_err(dev, "Unable to reguest IRQ %i\n", irq);
+					IRQF_ONESHOT | flags, dev_name(dev), s);
+	if (!ret)
+		return 0;
+
+	dev_err(dev, "Unable to reguest IRQ %i\n", irq);
+
+	mutex_destroy(&s->mutex);
+
 #ifdef CONFIG_GPIOLIB
-		if (s->gpio_used)
-			WARN_ON(gpiochip_remove(&s->gpio));
+	WARN_ON(gpiochip_remove(&s->gpio));
+
+out_uart:
 #endif
-	}
+	uart_unregister_driver(&s->uart);
 
-	return ret;
+out_clk:
+	clk_disable_unprepare(s->clk);
 
-err_freq:
-	dev_err(dev, "Frequency parameter incorrect\n");
-	return -EINVAL;
+	return ret;
 }
 
 static int max310x_remove(struct device *dev)
@@ -1244,30 +1265,51 @@ static int max310x_remove(struct device *dev)
 	struct max310x_port *s = dev_get_drvdata(dev);
 	int i, ret = 0;
 
+#ifdef CONFIG_GPIOLIB
+	ret = gpiochip_remove(&s->gpio);
+	if (ret)
+		return ret;
+#endif
+
 	for (i = 0; i < s->uart.nr; i++) {
 		cancel_work_sync(&s->p[i].tx_work);
+		cancel_work_sync(&s->p[i].md_work);
 		uart_remove_one_port(&s->uart, &s->p[i].port);
 		s->devtype->power(&s->p[i].port, 0);
 	}
 
+	mutex_destroy(&s->mutex);
 	uart_unregister_driver(&s->uart);
-
-#ifdef CONFIG_GPIOLIB
-	if (s->gpio_used)
-		ret = gpiochip_remove(&s->gpio);
-#endif
-
-	if (s->pdata->exit)
-		s->pdata->exit();
+	clk_disable_unprepare(s->clk);
 
 	return ret;
 }
 
+static const struct of_device_id __maybe_unused max310x_dt_ids[] = {
+	{ .compatible = "maxim,max3107",	.data = &max3107_devtype, },
+	{ .compatible = "maxim,max3108",	.data = &max3108_devtype, },
+	{ .compatible = "maxim,max3109",	.data = &max3109_devtype, },
+	{ .compatible = "maxim,max14830",	.data = &max14830_devtype },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max310x_dt_ids);
+
+static struct regmap_config regcfg = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.write_flag_mask = 0x80,
+	.cache_type = REGCACHE_RBTREE,
+	.writeable_reg = max310x_reg_writeable,
+	.volatile_reg = max310x_reg_volatile,
+	.precious_reg = max310x_reg_precious,
+};
+
 #ifdef CONFIG_SPI_MASTER
 static int max310x_spi_probe(struct spi_device *spi)
 {
-	struct max310x_devtype *devtype =
-		(struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
+	struct max310x_devtype *devtype;
+	unsigned long flags = 0;
+	struct regmap *regmap;
 	int ret;
 
 	/* Setup SPI bus */
@@ -1275,12 +1317,25 @@ static int max310x_spi_probe(struct spi_device *spi)
 	spi->mode		= spi->mode ? : SPI_MODE_0;
 	spi->max_speed_hz	= spi->max_speed_hz ? : 26000000;
 	ret = spi_setup(spi);
-	if (ret) {
-		dev_err(&spi->dev, "SPI setup failed\n");
+	if (ret)
 		return ret;
+
+	if (spi->dev.of_node) {
+		const struct of_device_id *of_id =
+			of_match_device(max310x_dt_ids, &spi->dev);
+
+		devtype = (struct max310x_devtype *)of_id->data;
+	} else {
+		const struct spi_device_id *id_entry = spi_get_device_id(spi);
+
+		devtype = (struct max310x_devtype *)id_entry->driver_data;
+		flags = IRQF_TRIGGER_FALLING;
 	}
 
-	return max310x_probe(&spi->dev, 1, devtype, spi->irq);
+	regcfg.max_register = devtype->nr * 0x20 - 1;
+	regmap = devm_regmap_init_spi(spi, &regcfg);
+
+	return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags);
 }
 
 static int max310x_spi_remove(struct spi_device *spi)
@@ -1288,8 +1343,6 @@ static int max310x_spi_remove(struct spi_device *spi)
 	return max310x_remove(&spi->dev);
 }
 
-static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
-
 static const struct spi_device_id max310x_id_table[] = {
 	{ "max3107",	(kernel_ulong_t)&max3107_devtype, },
 	{ "max3108",	(kernel_ulong_t)&max3108_devtype, },
@@ -1301,9 +1354,10 @@ MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
 static struct spi_driver max310x_uart_driver = {
 	.driver = {
-		.name	= MAX310X_NAME,
-		.owner	= THIS_MODULE,
-		.pm	= &max310x_pm_ops,
+		.name		= MAX310X_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(max310x_dt_ids),
+		.pm		= &max310x_pm_ops,
 	},
 	.probe		= max310x_spi_probe,
 	.remove		= max310x_spi_remove,
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b5d779cd3c2b..053b98eb46c8 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -39,6 +39,13 @@
 
 #include "msm_serial.h"
 
+enum {
+	UARTDM_1P1 = 1,
+	UARTDM_1P2,
+	UARTDM_1P3,
+	UARTDM_1P4,
+};
+
 struct msm_port {
 	struct uart_port	uart;
 	char			name[16];
@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
 
 static void msm_reset(struct uart_port *port)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
 	/* reset everything */
 	msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
 	msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)
 	msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
 	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
 	msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
+
+	/* Disable DM modes */
+	if (msm_port->is_uartdm)
+		msm_write(port, 0, UARTDM_DMEN);
 }
 
 static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state,
 	}
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int msm_poll_init(struct uart_port *port)
+{
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	/* Enable single character mode on RX FIFO */
+	if (msm_port->is_uartdm >= UARTDM_1P4)
+		msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
+
+	return 0;
+}
+
+static int msm_poll_get_char_single(struct uart_port *port)
+{
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
+
+	if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
+		return NO_POLL_CHAR;
+	else
+		return msm_read(port, rf_reg) & 0xff;
+}
+
+static int msm_poll_get_char_dm_1p3(struct uart_port *port)
+{
+	int c;
+	static u32 slop;
+	static int count;
+	unsigned char *sp = (unsigned char *)&slop;
+
+	/* Check if a previous read had more than one char */
+	if (count) {
+		c = sp[sizeof(slop) - count];
+		count--;
+	/* Or if FIFO is empty */
+	} else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
+		/*
+		 * If RX packing buffer has less than a word, force stale to
+		 * push contents into RX FIFO
+		 */
+		count = msm_read(port, UARTDM_RXFS);
+		count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
+		if (count) {
+			msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
+			slop = msm_read(port, UARTDM_RF);
+			c = sp[0];
+			count--;
+		} else {
+			c = NO_POLL_CHAR;
+		}
+	/* FIFO has a word */
+	} else {
+		slop = msm_read(port, UARTDM_RF);
+		c = sp[0];
+		count = sizeof(slop) - 1;
+	}
+
+	return c;
+}
+
+static int msm_poll_get_char(struct uart_port *port)
+{
+	u32 imr;
+	int c;
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	/* Disable all interrupts */
+	imr = msm_read(port, UART_IMR);
+	msm_write(port, 0, UART_IMR);
+
+	if (msm_port->is_uartdm == UARTDM_1P3)
+		c = msm_poll_get_char_dm_1p3(port);
+	else
+		c = msm_poll_get_char_single(port);
+
+	/* Enable interrupts */
+	msm_write(port, imr, UART_IMR);
+
+	return c;
+}
+
+static void msm_poll_put_char(struct uart_port *port, unsigned char c)
+{
+	u32 imr;
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	/* Disable all interrupts */
+	imr = msm_read(port, UART_IMR);
+	msm_write(port, 0, UART_IMR);
+
+	if (msm_port->is_uartdm)
+		reset_dm_count(port, 1);
+
+	/* Wait until FIFO is empty */
+	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
+		cpu_relax();
+
+	/* Write a character */
+	msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+
+	/* Wait until FIFO is empty */
+	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
+		cpu_relax();
+
+	/* Enable interrupts */
+	msm_write(port, imr, UART_IMR);
+
+	return;
+}
+#endif
+
 static struct uart_ops msm_uart_pops = {
 	.tx_empty = msm_tx_empty,
 	.set_mctrl = msm_set_mctrl,
@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
 	.config_port = msm_config_port,
 	.verify_port = msm_verify_port,
 	.pm = msm_power,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_init = msm_poll_init,
+	.poll_get_char	= msm_poll_get_char,
+	.poll_put_char	= msm_poll_put_char,
+#endif
 };
 
 static struct msm_port msm_uart_ports[] = {
@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {
 static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
 
 static const struct of_device_id msm_uartdm_table[] = {
-	{ .compatible = "qcom,msm-uartdm" },
+	{ .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
+	{ .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
+	{ .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
+	{ .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
 	{ }
 };
 
@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	struct msm_port *msm_port;
 	struct resource *resource;
 	struct uart_port *port;
+	const struct of_device_id *id;
 	int irq;
 
 	if (pdev->id == -1)
@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	port->dev = &pdev->dev;
 	msm_port = UART_TO_MSM(port);
 
-	if (of_match_device(msm_uartdm_table, &pdev->dev))
-		msm_port->is_uartdm = 1;
+	id = of_match_device(msm_uartdm_table, &pdev->dev);
+	if (id)
+		msm_port->is_uartdm = (unsigned long)id->data;
 	else
 		msm_port->is_uartdm = 0;
 
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 469fda50ac63..1e9b68b6f9eb 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -59,6 +59,7 @@
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
 #define UART_CR_CMD_PROTECTION_EN	(16 << 4)
 #define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
+#define UART_CR_CMD_FORCE_STALE		(4 << 8)
 #define UART_CR_CMD_RESET_TX_READY	(3 << 8)
 #define UART_CR_TX_DISABLE		(1 << 3)
 #define UART_CR_TX_ENABLE		(1 << 2)
@@ -113,6 +114,14 @@
 #define GSBI_PROTOCOL_UART	0x40
 #define GSBI_PROTOCOL_IDLE	0x0
 
+#define UARTDM_RXFS		0x50
+#define UARTDM_RXFS_BUF_SHIFT	0x7
+#define UARTDM_RXFS_BUF_MASK	0x7
+
+#define UARTDM_DMEN		0x3C
+#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
+#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
+
 #define UARTDM_DMRX		0x34
 #define UARTDM_NCF_TX		0x40
 #define UARTDM_RX_TOTAL_SNAP	0x38
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 8fa1134e0051..0931b3fe9edf 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1762,7 +1762,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
 	int fifosize;
 	int port_type;
 	struct pch_uart_driver_data *board;
+#ifdef CONFIG_DEBUG_FS
 	char name[32];	/* for debugfs file name */
+#endif
 
 	board = &drv_dat[id->driver_data];
 	port_type = board->port_type;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 9cd706df3b33..23f459600738 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1282,6 +1282,14 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto probe_err;
 
+	if (!s3c24xx_uart_drv.state) {
+		ret = uart_register_driver(&s3c24xx_uart_drv);
+		if (ret < 0) {
+			pr_err("Failed to register Samsung UART driver\n");
+			return ret;
+		}
+	}
+
 	dbg("%s: adding port\n", __func__);
 	uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
 	platform_set_drvdata(pdev, &ourport->port);
@@ -1321,6 +1329,8 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
 		uart_remove_one_port(&s3c24xx_uart_drv, port);
 	}
 
+	uart_unregister_driver(&s3c24xx_uart_drv);
+
 	return 0;
 }
 
@@ -1820,35 +1830,7 @@ static struct platform_driver samsung_serial_driver = {
 	},
 };
 
-/* module initialisation code */
-
-static int __init s3c24xx_serial_modinit(void)
-{
-	int ret;
-
-	ret = uart_register_driver(&s3c24xx_uart_drv);
-	if (ret < 0) {
-		pr_err("Failed to register Samsung UART driver\n");
-		return ret;
-	}
-
-	ret = platform_driver_register(&samsung_serial_driver);
-	if (ret < 0) {
-		pr_err("Failed to register platform driver\n");
-		uart_unregister_driver(&s3c24xx_uart_drv);
-	}
-
-	return ret;
-}
-
-static void __exit s3c24xx_serial_modexit(void)
-{
-	platform_driver_unregister(&samsung_serial_driver);
-	uart_unregister_driver(&s3c24xx_uart_drv);
-}
-
-module_init(s3c24xx_serial_modinit);
-module_exit(s3c24xx_serial_modexit);
+module_platform_driver(samsung_serial_driver);
 
 MODULE_ALIAS("platform:samsung-uart");
 MODULE_DESCRIPTION("Samsung SoC Serial port driver");
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index ece2049bd270..8ece7f14d89d 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2677,6 +2677,12 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
 		tty_vhangup(port->tty);
 
 	/*
+	 * If the port is used as a console, unregister it
+	 */
+	if (uart_console(uport))
+		unregister_console(uport->cons);
+
+	/*
 	 * Free the port IO and memory resources, if any.
 	 */
 	if (uport->type != PORT_UNKNOWN)
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index be33d2b0613b..0cb52376f97d 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2018,7 +2018,7 @@ static int sci_remap_port(struct uart_port *port)
 		 * need to do any remapping, just cast the cookie
 		 * directly.
 		 */
-		port->membase = (void __iomem *)port->mapbase;
+		port->membase = (void __iomem *)(uintptr_t)port->mapbase;
 	}
 
 	return 0;
@@ -2564,6 +2564,7 @@ static int sci_probe(struct platform_device *dev)
 	ret = cpufreq_register_notifier(&sp->freq_transition,
 					CPUFREQ_TRANSITION_NOTIFIER);
 	if (unlikely(ret < 0)) {
+		uart_remove_one_port(&sci_uart_driver, &sp->port);
 		sci_cleanup_single(sp);
 		return ret;
 	}
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index b7bfe24d4ebc..68b0fd4b9a6a 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -24,7 +24,6 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-direction.h>
 #include <linux/dma-mapping.h>
-#include <linux/sirfsoc_dma.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 
@@ -173,7 +172,7 @@ static void sirfsoc_uart_stop_tx(struct uart_port *port)
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
 
-	if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
+	if (sirfport->tx_dma_chan) {
 		if (sirfport->tx_dma_state == TX_DMA_RUNNING) {
 			dmaengine_pause(sirfport->tx_dma_chan);
 			sirfport->tx_dma_state = TX_DMA_PAUSE;
@@ -288,7 +287,7 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
 	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
 	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
 	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-	if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
+	if (sirfport->tx_dma_chan)
 		sirfsoc_uart_tx_with_dma(sirfport);
 	else {
 		sirfsoc_uart_pio_tx_chars(sirfport, 1);
@@ -310,7 +309,7 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port)
 	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
 
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
+	if (sirfport->rx_dma_chan) {
 		if (!sirfport->is_marco)
 			wr_regl(port, ureg->sirfsoc_int_en_reg,
 				rd_regl(port, ureg->sirfsoc_int_en_reg) &
@@ -675,7 +674,7 @@ recv_char:
 		uart_handle_cts_change(port, cts_status);
 		wake_up_interruptible(&state->port.delta_msr_wait);
 	}
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
+	if (sirfport->rx_dma_chan) {
 		if (intr_status & uint_st->sirfsoc_rx_timeout)
 			sirfsoc_uart_handle_rx_tmo(sirfport);
 		if (intr_status & uint_st->sirfsoc_rx_done)
@@ -686,7 +685,7 @@ recv_char:
 					SIRFSOC_UART_IO_RX_MAX_CNT);
 	}
 	if (intr_status & uint_st->sirfsoc_txfifo_empty) {
-		if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
+		if (sirfport->tx_dma_chan)
 			sirfsoc_uart_tx_with_dma(sirfport);
 		else {
 			if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
@@ -778,7 +777,7 @@ static void sirfsoc_uart_start_rx(struct uart_port *port)
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
+	if (sirfport->rx_dma_chan)
 		sirfsoc_uart_start_next_rx_dma(port);
 	else {
 		if (!sirfport->is_marco)
@@ -1014,11 +1013,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
 			(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
 			SIRFSOC_USP_ASYNC_DIV2_OFFSET);
 	}
-	if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no))
+	if (sirfport->tx_dma_chan)
 		wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE);
 	else
 		wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
+	if (sirfport->rx_dma_chan)
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
 	else
 		wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
@@ -1049,93 +1048,6 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state,
 		clk_disable_unprepare(sirfport->clk);
 }
 
-static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port)
-{
-	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-	dma_cap_mask_t dma_mask;
-	struct dma_slave_config tx_slv_cfg = {
-		.dst_maxburst = 2,
-	};
-
-	dma_cap_zero(dma_mask);
-	dma_cap_set(DMA_SLAVE, dma_mask);
-	sirfport->tx_dma_chan = dma_request_channel(dma_mask,
-		(dma_filter_fn)sirfsoc_dma_filter_id,
-		(void *)sirfport->tx_dma_no);
-	if (!sirfport->tx_dma_chan) {
-		dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
-					sirfport->tx_dma_no);
-		return  -EPROBE_DEFER;
-	}
-	dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
-
-	return 0;
-}
-
-static unsigned int sirfsoc_uart_init_rx_dma(struct uart_port *port)
-{
-	struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-	dma_cap_mask_t dma_mask;
-	int ret;
-	int i, j;
-	struct dma_slave_config slv_cfg = {
-		.src_maxburst = 2,
-	};
-
-	dma_cap_zero(dma_mask);
-	dma_cap_set(DMA_SLAVE, dma_mask);
-	sirfport->rx_dma_chan = dma_request_channel(dma_mask,
-					(dma_filter_fn)sirfsoc_dma_filter_id,
-					(void *)sirfport->rx_dma_no);
-	if (!sirfport->rx_dma_chan) {
-		dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
-				sirfport->rx_dma_no);
-		ret = -EPROBE_DEFER;
-		goto request_err;
-	}
-	for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
-		sirfport->rx_dma_items[i].xmit.buf =
-			dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-			&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
-		if (!sirfport->rx_dma_items[i].xmit.buf) {
-			dev_err(port->dev, "Uart alloc bufa failed\n");
-			ret = -ENOMEM;
-			goto alloc_coherent_err;
-		}
-		sirfport->rx_dma_items[i].xmit.head =
-			sirfport->rx_dma_items[i].xmit.tail = 0;
-	}
-	dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
-
-	return 0;
-alloc_coherent_err:
-	for (j = 0; j < i; j++)
-		dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-				sirfport->rx_dma_items[j].xmit.buf,
-				sirfport->rx_dma_items[j].dma_addr);
-	dma_release_channel(sirfport->rx_dma_chan);
-request_err:
-	return ret;
-}
-
-static void sirfsoc_uart_uninit_tx_dma(struct sirfsoc_uart_port *sirfport)
-{
-	dmaengine_terminate_all(sirfport->tx_dma_chan);
-	dma_release_channel(sirfport->tx_dma_chan);
-}
-
-static void sirfsoc_uart_uninit_rx_dma(struct sirfsoc_uart_port *sirfport)
-{
-	int i;
-	struct uart_port *port = &sirfport->port;
-	dmaengine_terminate_all(sirfport->rx_dma_chan);
-	dma_release_channel(sirfport->rx_dma_chan);
-	for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
-		dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
-				sirfport->rx_dma_items[i].xmit.buf,
-				sirfport->rx_dma_items[i].dma_addr);
-}
-
 static int sirfsoc_uart_startup(struct uart_port *port)
 {
 	struct sirfsoc_uart_port *sirfport	= to_sirfport(port);
@@ -1174,18 +1086,12 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 	wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
 	wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port));
 	wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
-
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
-		ret = sirfsoc_uart_init_rx_dma(port);
-		if (ret)
-			goto init_rx_err;
+	if (sirfport->rx_dma_chan)
 		wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
-				SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
-				SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
-				SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
-	}
-	if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
-		sirfsoc_uart_init_tx_dma(port);
+			SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
+			SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
+			SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
+	if (sirfport->tx_dma_chan) {
 		sirfport->tx_dma_state = TX_DMA_IDLE;
 		wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
 				SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) |
@@ -1232,12 +1138,8 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
 		gpio_set_value(sirfport->rts_gpio, 1);
 		free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport);
 	}
-	if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no))
-		sirfsoc_uart_uninit_rx_dma(sirfport);
-	if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
-		sirfsoc_uart_uninit_tx_dma(sirfport);
+	if (sirfport->tx_dma_chan)
 		sirfport->tx_dma_state = TX_DMA_IDLE;
-	}
 }
 
 static const char *sirfsoc_uart_type(struct uart_port *port)
@@ -1313,8 +1215,8 @@ sirfsoc_uart_console_setup(struct console *co, char *options)
 	port->cons = co;
 
 	/* default console tx/rx transfer using io mode */
-	sirfport->rx_dma_no = UNVALID_DMA_CHAN;
-	sirfport->tx_dma_no = UNVALID_DMA_CHAN;
+	sirfport->rx_dma_chan = NULL;
+	sirfport->tx_dma_chan = NULL;
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
@@ -1382,6 +1284,13 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 	struct uart_port *port;
 	struct resource *res;
 	int ret;
+	int i, j;
+	struct dma_slave_config slv_cfg = {
+		.src_maxburst = 2,
+	};
+	struct dma_slave_config tx_slv_cfg = {
+		.dst_maxburst = 2,
+	};
 	const struct of_device_id *match;
 
 	match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
@@ -1402,27 +1311,10 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
 
 	sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
 		"sirf,uart-has-rtscts");
-	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart")) {
+	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart"))
 		sirfport->uart_reg->uart_type = SIRF_REAL_UART;
-		if (of_property_read_u32(pdev->dev.of_node,
-				"sirf,uart-dma-rx-channel",
-				&sirfport->rx_dma_no))
-			sirfport->rx_dma_no = UNVALID_DMA_CHAN;
-		if (of_property_read_u32(pdev->dev.of_node,
-				"sirf,uart-dma-tx-channel",
-				&sirfport->tx_dma_no))
-			sirfport->tx_dma_no = UNVALID_DMA_CHAN;
-	}
 	if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) {
 		sirfport->uart_reg->uart_type =	SIRF_USP_UART;
-		if (of_property_read_u32(pdev->dev.of_node,
-				"sirf,usp-dma-rx-channel",
-				&sirfport->rx_dma_no))
-			sirfport->rx_dma_no = UNVALID_DMA_CHAN;
-		if (of_property_read_u32(pdev->dev.of_node,
-				"sirf,usp-dma-tx-channel",
-				&sirfport->tx_dma_no))
-			sirfport->tx_dma_no = UNVALID_DMA_CHAN;
 		if (!sirfport->hw_flow_ctrl)
 			goto usp_no_flow_control;
 		if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL))
@@ -1515,8 +1407,32 @@ usp_no_flow_control:
 		goto port_err;
 	}
 
-	return 0;
+	sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
+	for (i = 0; sirfport->rx_dma_chan && i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
+		sirfport->rx_dma_items[i].xmit.buf =
+			dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+			&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
+		if (!sirfport->rx_dma_items[i].xmit.buf) {
+			dev_err(port->dev, "Uart alloc bufa failed\n");
+			ret = -ENOMEM;
+			goto alloc_coherent_err;
+		}
+		sirfport->rx_dma_items[i].xmit.head =
+			sirfport->rx_dma_items[i].xmit.tail = 0;
+	}
+	if (sirfport->rx_dma_chan)
+		dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
+	sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx");
+	if (sirfport->tx_dma_chan)
+		dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
 
+	return 0;
+alloc_coherent_err:
+	for (j = 0; j < i; j++)
+		dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+				sirfport->rx_dma_items[j].xmit.buf,
+				sirfport->rx_dma_items[j].dma_addr);
+	dma_release_channel(sirfport->rx_dma_chan);
 port_err:
 	clk_put(sirfport->clk);
 err:
@@ -1529,6 +1445,19 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
 	struct uart_port *port = &sirfport->port;
 	clk_put(sirfport->clk);
 	uart_remove_one_port(&sirfsoc_uart_drv, port);
+	if (sirfport->rx_dma_chan) {
+		int i;
+		dmaengine_terminate_all(sirfport->rx_dma_chan);
+		dma_release_channel(sirfport->rx_dma_chan);
+		for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
+			dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
+					sirfport->rx_dma_items[i].xmit.buf,
+					sirfport->rx_dma_items[i].dma_addr);
+	}
+	if (sirfport->tx_dma_chan) {
+		dmaengine_terminate_all(sirfport->tx_dma_chan);
+		dma_release_channel(sirfport->tx_dma_chan);
+	}
 	return 0;
 }
 
diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h
index b7d679c0881b..8a6eddad2f3c 100644
--- a/drivers/tty/serial/sirfsoc_uart.h
+++ b/drivers/tty/serial/sirfsoc_uart.h
@@ -392,9 +392,6 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 /* Indicate how many buffers used */
 #define SIRFSOC_RX_LOOP_BUF_CNT		2
 
-/* Indicate if DMA channel valid */
-#define IS_DMA_CHAN_VALID(x)	((x) != -1)
-#define UNVALID_DMA_CHAN	-1
 /* For Fast Baud Rate Calculation */
 struct sirfsoc_baudrate_to_regv {
 	unsigned int baud_rate;
@@ -423,8 +420,6 @@ struct sirfsoc_uart_port {
 	/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
 	bool				is_marco;
 	struct sirfsoc_uart_register	*uart_reg;
-	int				rx_dma_no;
-	int				tx_dma_no;
 	struct dma_chan			*rx_dma_chan;
 	struct dma_chan			*tx_dma_chan;
 	dma_addr_t			tx_dma_addr;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 765125dff20e..8ebd9f88a6f6 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -351,14 +351,11 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
  *	Takes any pending buffers and transfers their ownership to the
  *	ldisc side of the queue. It then schedules those characters for
  *	processing by the line discipline.
- *	Note that this function can only be used when the low_latency flag
- *	is unset. Otherwise the workqueue won't be flushed.
  */
 
 void tty_schedule_flip(struct tty_port *port)
 {
 	struct tty_bufhead *buf = &port->buf;
-	WARN_ON(port->low_latency);
 
 	buf->tail->commit = buf->tail->used;
 	schedule_work(&buf->work);
@@ -482,17 +479,15 @@ static void flush_to_ldisc(struct work_struct *work)
  */
 void tty_flush_to_ldisc(struct tty_struct *tty)
 {
-	if (!tty->port->low_latency)
-		flush_work(&tty->port->buf.work);
+	flush_work(&tty->port->buf.work);
 }
 
 /**
  *	tty_flip_buffer_push	-	terminal
  *	@port: tty port to push
  *
- *	Queue a push of the terminal flip buffers to the line discipline. This
- *	function must not be called from IRQ context if port->low_latency is
- *	set.
+ *	Queue a push of the terminal flip buffers to the line discipline.
+ *	Can be called from IRQ/atomic context.
  *
  *	In the event of the queue being busy for flipping the work will be
  *	held off and retried later.
@@ -500,14 +495,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
 
 void tty_flip_buffer_push(struct tty_port *port)
 {
-	struct tty_bufhead *buf = &port->buf;
-
-	buf->tail->commit = buf->tail->used;
-
-	if (port->low_latency)
-		flush_to_ldisc(&buf->work);
-	else
-		schedule_work(&buf->work);
+	tty_schedule_flip(port);
 }
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index c74a00ad7add..d3448a90f0f9 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1271,12 +1271,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
  *
  *	Locking: None
  */
-static void tty_line_name(struct tty_driver *driver, int index, char *p)
+static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
-		strcpy(p, driver->name);
+		return sprintf(p, "%s", driver->name);
 	else
-		sprintf(p, "%s%d", driver->name, index + driver->name_base);
+		return sprintf(p, "%s%d", driver->name,
+			       index + driver->name_base);
 }
 
 /**
@@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev,
 		if (i >= ARRAY_SIZE(cs))
 			break;
 	}
-	while (i--)
-		count += sprintf(buf + count, "%s%d%c",
-				 cs[i]->name, cs[i]->index, i ? ' ':'\n');
+	while (i--) {
+		int index = cs[i]->index;
+		struct tty_driver *drv = cs[i]->device(cs[i], &index);
+
+		/* don't resolve tty0 as some programs depend on it */
+		if (drv && (cs[i]->index > 0 || drv->major != TTY_MAJOR))
+			count += tty_line_name(drv, index, buf + count);
+		else
+			count += sprintf(buf + count, "%s%d",
+					 cs[i]->name, cs[i]->index);
+
+		count += sprintf(buf + count, "%c", i ? ' ':'\n');
+	}
 	console_unlock();
 
 	return count;
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index d8a55e87877f..0ffb0cbe2823 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -39,17 +39,10 @@
 				lock_acquire(&(l)->dep_map, s, t, r, c, n, i)
 # define __rel(l, n, i)				\
 				lock_release(&(l)->dep_map, n, i)
-# ifdef CONFIG_PROVE_LOCKING
-#  define lockdep_acquire(l, s, t, i)		__acq(l, s, t, 0, 2, NULL, i)
-#  define lockdep_acquire_nest(l, s, t, n, i)	__acq(l, s, t, 0, 2, n, i)
-#  define lockdep_acquire_read(l, s, t, i)	__acq(l, s, t, 1, 2, NULL, i)
-#  define lockdep_release(l, n, i)		__rel(l, n, i)
-# else
-#  define lockdep_acquire(l, s, t, i)		__acq(l, s, t, 0, 1, NULL, i)
-#  define lockdep_acquire_nest(l, s, t, n, i)	__acq(l, s, t, 0, 1, n, i)
-#  define lockdep_acquire_read(l, s, t, i)	__acq(l, s, t, 1, 1, NULL, i)
-#  define lockdep_release(l, n, i)		__rel(l, n, i)
-# endif
+#define lockdep_acquire(l, s, t, i)		__acq(l, s, t, 0, 1, NULL, i)
+#define lockdep_acquire_nest(l, s, t, n, i)	__acq(l, s, t, 0, 1, n, i)
+#define lockdep_acquire_read(l, s, t, i)	__acq(l, s, t, 1, 1, NULL, i)
+#define lockdep_release(l, n, i)		__rel(l, n, i)
 #else
 # define lockdep_acquire(l, s, t, i)		do { } while (0)
 # define lockdep_acquire_nest(l, s, t, n, i)	do { } while (0)
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/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 23b5d32954bf..3ad0b61e35b4 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1590,9 +1590,9 @@ static void restore_cur(struct vc_data *vc)
 	vc->vc_need_wrap = 0;
 }
 
-enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
+enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
 	EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
-	ESpalette };
+	ESpalette, ESosc };
 
 /* console_lock is held (except via vc_init()) */
 static void reset_terminal(struct vc_data *vc, int do_clear)
@@ -1652,11 +1652,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 	 *  Control characters can be used in the _middle_
 	 *  of an escape sequence.
 	 */
+	if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */
+		return;
 	switch (c) {
 	case 0:
 		return;
 	case 7:
-		if (vc->vc_bell_duration)
+		if (vc->vc_state == ESosc)
+			vc->vc_state = ESnormal;
+		else if (vc->vc_bell_duration)
 			kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
 		return;
 	case 8:
@@ -1767,7 +1771,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 		} else if (c=='R') {   /* reset palette */
 			reset_palette(vc);
 			vc->vc_state = ESnormal;
-		} else
+		} else if (c>='0' && c<='9')
+			vc->vc_state = ESosc;
+		else
 			vc->vc_state = ESnormal;
 		return;
 	case ESpalette:
@@ -1807,9 +1813,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 			vc->vc_par[vc->vc_npar] *= 10;
 			vc->vc_par[vc->vc_npar] += c - '0';
 			return;
-		} else
-			vc->vc_state = ESgotpars;
-	case ESgotpars:
+		}
 		vc->vc_state = ESnormal;
 		switch(c) {
 		case 'h':
@@ -2023,6 +2027,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 			vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
 		vc->vc_state = ESnormal;
 		return;
+	case ESosc:
+		return;
 	default:
 		vc->vc_state = ESnormal;
 	}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 2e6b832e004b..e0cad4418085 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -2,10 +2,6 @@
 # USB device configuration
 #
 
-# These are unused now, remove them once they are no longer selected
-config USB_ARCH_HAS_OHCI
-	bool
-
 config USB_OHCI_BIG_ENDIAN_DESC
 	bool
 
@@ -17,18 +13,12 @@ config USB_OHCI_LITTLE_ENDIAN
 	default n if STB03xxx || PPC_MPC52xx
 	default y
 
-config USB_ARCH_HAS_EHCI
-	bool
-
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
 
-config USB_ARCH_HAS_XHCI
-	bool
-
 menuconfig USB_SUPPORT
 	bool "USB support"
 	depends on HAS_IOMEM
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index a85713165688..83d06c1455b7 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -50,12 +50,14 @@
 #define PORTSC_PTC            (0x0FUL << 16)
 #define PORTSC_PHCD(d)	      ((d) ? BIT(22) : BIT(23))
 /* PTS and PTW for non lpm version only */
+#define PORTSC_PFSC           BIT(24)
 #define PORTSC_PTS(d)						\
 	(u32)((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0))
 #define PORTSC_PTW            BIT(28)
 #define PORTSC_STS            BIT(29)
 
 /* DEVLC */
+#define DEVLC_PFSC            BIT(23)
 #define DEVLC_PSPD            (0x03UL << 25)
 #define DEVLC_PSPD_HS         (0x02UL << 25)
 #define DEVLC_PTW             BIT(27)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 88b80f7728e4..e206406ae1d9 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -196,8 +196,6 @@ struct ci_hdrc {
 
 	struct ci_hdrc_platform_data	*platdata;
 	int				vbus_active;
-	/* FIXME: some day, we'll not use global phy */
-	bool				global_phy;
 	struct usb_phy			*transceiver;
 	struct usb_hcd			*hcd;
 	struct dentry			*debugfs;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 33f22bc6ad7f..ca6831c5b763 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -64,6 +64,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/chipidea.h>
 #include <linux/usb/of.h>
+#include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/regulator/consumer.h>
 
@@ -298,6 +299,13 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode)
 	if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
 		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
 
+	if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
+		if (ci->hw_bank.lpm)
+			hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
+		else
+			hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
+	}
+
 	/* USBMODE should be configured step by step */
 	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
 	hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
@@ -412,6 +420,9 @@ static int ci_get_platdata(struct device *dev,
 		}
 	}
 
+	if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
+		platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
+
 	return 0;
 }
 
@@ -496,33 +507,6 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
 	}
 }
 
-static int ci_usb_phy_init(struct ci_hdrc *ci)
-{
-	if (ci->platdata->phy) {
-		ci->transceiver = ci->platdata->phy;
-		return usb_phy_init(ci->transceiver);
-	} else {
-		ci->global_phy = true;
-		ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
-		if (IS_ERR(ci->transceiver))
-			ci->transceiver = NULL;
-
-		return 0;
-	}
-}
-
-static void ci_usb_phy_destroy(struct ci_hdrc *ci)
-{
-	if (!ci->transceiver)
-		return;
-
-	otg_set_peripheral(ci->transceiver->otg, NULL);
-	if (ci->global_phy)
-		usb_put_phy(ci->transceiver);
-	else
-		usb_phy_shutdown(ci->transceiver);
-}
-
 static int ci_hdrc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
@@ -532,7 +516,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	int		ret;
 	enum usb_dr_mode dr_mode;
 
-	if (!dev->platform_data) {
+	if (!dev_get_platdata(dev)) {
 		dev_err(dev, "platform data missing\n");
 		return -ENODEV;
 	}
@@ -549,7 +533,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	}
 
 	ci->dev = dev;
-	ci->platdata = dev->platform_data;
+	ci->platdata = dev_get_platdata(dev);
 	ci->imx28_write_fix = !!(ci->platdata->flags &
 		CI_HDRC_IMX28_WRITE_FIX);
 
@@ -561,7 +545,26 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 
 	hw_phymode_configure(ci);
 
-	ret = ci_usb_phy_init(ci);
+	if (ci->platdata->phy)
+		ci->transceiver = ci->platdata->phy;
+	else
+		ci->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+
+	if (IS_ERR(ci->transceiver)) {
+		ret = PTR_ERR(ci->transceiver);
+		/*
+		 * if -ENXIO is returned, it means PHY layer wasn't
+		 * enabled, so it makes no sense to return -EPROBE_DEFER
+		 * in that case, since no PHY driver will ever probe.
+		 */
+		if (ret == -ENXIO)
+			return ret;
+
+		dev_err(dev, "no usb2 phy configured\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = usb_phy_init(ci->transceiver);
 	if (ret) {
 		dev_err(dev, "unable to init phy: %d\n", ret);
 		return ret;
@@ -572,8 +575,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	ci->irq = platform_get_irq(pdev, 0);
 	if (ci->irq < 0) {
 		dev_err(dev, "missing IRQ\n");
-		ret = -ENODEV;
-		goto destroy_phy;
+		ret = ci->irq;
+		goto deinit_phy;
 	}
 
 	ci_get_otg_capable(ci);
@@ -590,23 +593,12 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 		ret = ci_hdrc_gadget_init(ci);
 		if (ret)
 			dev_info(dev, "doesn't support gadget\n");
-		if (!ret && ci->transceiver) {
-			ret = otg_set_peripheral(ci->transceiver->otg,
-							&ci->gadget);
-			/*
-			 * If we implement all USB functions using chipidea drivers,
-			 * it doesn't need to call above API, meanwhile, if we only
-			 * use gadget function, calling above API is useless.
-			 */
-			if (ret && ret != -ENOTSUPP)
-				goto destroy_phy;
-		}
 	}
 
 	if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
 		dev_err(dev, "no supported roles\n");
 		ret = -ENODEV;
-		goto destroy_phy;
+		goto deinit_phy;
 	}
 
 	if (ci->is_otg) {
@@ -663,8 +655,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	free_irq(ci->irq, ci);
 stop:
 	ci_role_destroy(ci);
-destroy_phy:
-	ci_usb_phy_destroy(ci);
+deinit_phy:
+	usb_phy_shutdown(ci->transceiver);
 
 	return ret;
 }
@@ -677,7 +669,8 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 	free_irq(ci->irq, ci);
 	ci_role_destroy(ci);
 	ci_hdrc_enter_lpm(ci, true);
-	ci_usb_phy_destroy(ci);
+	usb_phy_shutdown(ci->transceiver);
+	kfree(ci->hw_bank.regmap);
 
 	return 0;
 }
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 4ab2cb62dfce..0dc56aebb807 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -178,19 +178,6 @@ static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir)
 }
 
 /**
- * hw_test_and_clear_setup_status: test & clear setup status (execute without
- *                                 interruption)
- * @n: endpoint number
- *
- * This function returns setup status
- */
-static int hw_test_and_clear_setup_status(struct ci_hdrc *ci, int n)
-{
-	n = ep_to_bit(ci, n);
-	return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n));
-}
-
-/**
  * hw_ep_prime: primes endpoint (execute without interruption)
  * @num:     endpoint number
  * @dir:     endpoint direction
@@ -997,15 +984,11 @@ __acquires(ci->lock)
 			}
 		}
 
-		if (hwep->type != USB_ENDPOINT_XFER_CONTROL ||
-		    !hw_test_and_clear_setup_status(ci, i))
+		/* Only handle setup packet below */
+		if (i != 0 ||
+			!hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(0)))
 			continue;
 
-		if (i != 0) {
-			dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i);
-			continue;
-		}
-
 		/*
 		 * Flush data and handshake transactions of previous
 		 * setup packet.
@@ -1193,6 +1176,11 @@ static int ep_enable(struct usb_ep *ep,
 
 	hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE);   /* needed? */
 
+	if (hwep->num != 0 && hwep->type == USB_ENDPOINT_XFER_CONTROL) {
+		dev_err(hwep->ci->dev, "Set control xfer at non-ep0\n");
+		retval = -EINVAL;
+	}
+
 	/*
 	 * Enable endpoints in the HW other than ep0 as ep0
 	 * is always enabled
@@ -1837,12 +1825,6 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
 
 	dma_pool_destroy(ci->td_pool);
 	dma_pool_destroy(ci->qh_pool);
-
-	if (ci->transceiver) {
-		otg_set_peripheral(ci->transceiver->otg, NULL);
-		if (ci->global_phy)
-			usb_put_phy(ci->transceiver);
-	}
 }
 
 static int udc_id_switch_for_device(struct ci_hdrc *ci)
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index fed7f68d025d..cb8e99156f5a 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -10,7 +10,6 @@ config USB_DEBUG
 
 config USB_ANNOUNCE_NEW_DEVICES
 	bool "USB announce new devices"
-	default N
 	help
 	  Say Y here if you want the USB core to always announce the
 	  idVendor, idProduct, Manufacturer, Product, and SerialNumber
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 90e18f6fa2bb..f3ba2e076ee3 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1043,6 +1043,20 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 	return ret;
 }
 
+static void check_reset_of_active_ep(struct usb_device *udev,
+		unsigned int epnum, char *ioctl_name)
+{
+	struct usb_host_endpoint **eps;
+	struct usb_host_endpoint *ep;
+
+	eps = (epnum & USB_DIR_IN) ? udev->ep_in : udev->ep_out;
+	ep = eps[epnum & 0x0f];
+	if (ep && !list_empty(&ep->urb_list))
+		dev_warn(&udev->dev, "Process %d (%s) called USBDEVFS_%s for active endpoint 0x%02x\n",
+				task_pid_nr(current), current->comm,
+				ioctl_name, epnum);
+}
+
 static int proc_resetep(struct dev_state *ps, void __user *arg)
 {
 	unsigned int ep;
@@ -1056,6 +1070,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
 	ret = checkintf(ps, ret);
 	if (ret)
 		return ret;
+	check_reset_of_active_ep(ps->dev, ep, "RESETEP");
 	usb_reset_endpoint(ps->dev, ep);
 	return 0;
 }
@@ -1074,6 +1089,7 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
 	ret = checkintf(ps, ret);
 	if (ret)
 		return ret;
+	check_reset_of_active_ep(ps->dev, ep, "CLEAR_HALT");
 	if (ep & USB_DIR_IN)
 		pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
 	else
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index ab90a0156828..85e0450a2bc7 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -312,9 +312,9 @@ static int usb_probe_interface(struct device *dev)
 		return error;
 	}
 
-	id = usb_match_id(intf, driver->id_table);
+	id = usb_match_dynamic_id(intf, driver);
 	if (!id)
-		id = usb_match_dynamic_id(intf, driver);
+		id = usb_match_id(intf, driver->id_table);
 	if (!id)
 		return error;
 
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index acbfeb0a0119..358ca8dd784f 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -155,6 +155,7 @@ int usb_choose_configuration(struct usb_device *udev)
 	}
 	return i;
 }
+EXPORT_SYMBOL_GPL(usb_choose_configuration);
 
 static int generic_probe(struct usb_device *udev)
 {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 64ea21971be2..f6c6b6f7cc9c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -499,7 +499,8 @@ static void led_work (struct work_struct *work)
 		changed++;
 	}
 	if (changed)
-		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+		queue_delayed_work(system_power_efficient_wq,
+				&hub->leds, LED_CYCLE_PERIOD);
 }
 
 /* use a short timeout for hub/port status fetches */
@@ -1041,7 +1042,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 		if (type == HUB_INIT) {
 			delay = hub_power_on(hub, false);
 			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
-			schedule_delayed_work(&hub->init_work,
+			queue_delayed_work(system_power_efficient_wq,
+					&hub->init_work,
 					msecs_to_jiffies(delay));
 
 			/* Suppress autosuspend until init is done */
@@ -1195,7 +1197,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 		/* Don't do a long sleep inside a workqueue routine */
 		if (type == HUB_INIT2) {
 			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
-			schedule_delayed_work(&hub->init_work,
+			queue_delayed_work(system_power_efficient_wq,
+					&hub->init_work,
 					msecs_to_jiffies(delay));
 			return;		/* Continues at init3: below */
 		} else {
@@ -1209,7 +1212,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 	if (status < 0)
 		dev_err(hub->intfdev, "activate --> %d\n", status);
 	if (hub->has_indicators && blinkenlights)
-		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+		queue_delayed_work(system_power_efficient_wq,
+				&hub->leds, LED_CYCLE_PERIOD);
 
 	/* Scan all ports that need attention */
 	kick_khubd(hub);
@@ -3958,7 +3962,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
 	connect_type = usb_get_hub_port_connect_type(udev->parent,
 			udev->portnum);
 
-	if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) ||
+	if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
 			connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
 		udev->usb2_hw_lpm_allowed = 1;
 		usb_set_usb2_hardware_lpm(udev, 1);
@@ -4107,8 +4111,12 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 
 			did_new_scheme = true;
 			retval = hub_enable_device(udev);
-			if (retval < 0)
+			if (retval < 0) {
+				dev_err(&udev->dev,
+					"hub failed to enable device, error %d\n",
+					retval);
 				goto fail;
+			}
 
 #define GET_DESCRIPTOR_BUFSIZE	64
 			buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
@@ -4311,7 +4319,8 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
 		/* hub LEDs are probably harder to miss than syslog */
 		if (hub->has_indicators) {
 			hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
-			schedule_delayed_work (&hub->leds, 0);
+			queue_delayed_work(system_power_efficient_wq,
+					&hub->leds, 0);
 		}
 	}
 	kfree(qual);
@@ -4540,7 +4549,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 				if (hub->has_indicators) {
 					hub->indicator[port1-1] =
 						INDICATOR_AMBER_BLINK;
-					schedule_delayed_work (&hub->leds, 0);
+					queue_delayed_work(
+						system_power_efficient_wq,
+						&hub->leds, 0);
 				}
 				status = -ENOTCONN;	/* Don't retry */
 				goto loop_disable;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f829a1aad1c3..378c96174382 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -178,7 +178,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg);
  *
  * Return:
  * If successful, 0. Otherwise a negative error number. The number of actual
- * bytes transferred will be stored in the @actual_length paramater.
+ * bytes transferred will be stored in the @actual_length parameter.
  */
 int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
 		      void *data, int len, int *actual_length, int timeout)
@@ -1920,6 +1920,7 @@ free_interfaces:
 	usb_autosuspend_device(dev);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_set_configuration);
 
 static LIST_HEAD(set_config_list);
 static DEFINE_SPINLOCK(set_config_lock);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 9ff665f1322f..991386ceb4ec 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -831,7 +831,7 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs);
  *
  * this allows all outstanding URBs to be unlinked starting
  * from the back of the queue. This function is asynchronous.
- * The unlinking is just tiggered. It may happen after this
+ * The unlinking is just triggered. It may happen after this
  * function has returned.
  *
  * This routine should not be called by a driver after its disconnect
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 8205799e6db3..c93918b70d03 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -72,6 +72,26 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
 }
 
 /**
+ * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts.
+ * When the PRTINT interrupt fires, there are certain status bits in the Host
+ * Port that needs to get cleared.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 hprt0 = readl(hsotg->regs + HPRT0);
+
+	if (hprt0 & HPRT0_ENACHG) {
+		hprt0 &= ~HPRT0_ENA;
+		writel(hprt0, hsotg->regs + HPRT0);
+	}
+
+	/* Clear interrupt */
+	writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
+}
+
+/**
  * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
  *
  * @hsotg: Programming view of DWC_otg controller
@@ -479,9 +499,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 		if (dwc2_is_device_mode(hsotg)) {
 			dev_dbg(hsotg->dev,
 				" --Port interrupt received in Device mode--\n");
-			gintsts = GINTSTS_PRTINT;
-			writel(gintsts, hsotg->regs + GINTSTS);
-			retval = 1;
+			dwc2_handle_usb_port_intr(hsotg);
+			retval = IRQ_HANDLED;
 		}
 	}
 
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 012f17ec1a37..47b9eb5389b4 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -975,8 +975,8 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 				  struct dwc2_qtd *qtd)
 {
 	struct dwc2_hcd_urb *urb = qtd->urb;
-	int pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
 	enum dwc2_halt_status halt_status = DWC2_HC_XFER_COMPLETE;
+	int pipe_type;
 	int urb_xfer_done;
 
 	if (dbg_hc(chan))
@@ -984,6 +984,11 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 			 "--Host Channel %d Interrupt: Transfer Complete--\n",
 			 chnum);
 
+	if (!urb)
+		goto handle_xfercomp_done;
+
+	pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+
 	if (hsotg->core_params->dma_desc_enable > 0) {
 		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status);
 		if (pipe_type == USB_ENDPOINT_XFER_ISOC)
@@ -1005,9 +1010,6 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 		}
 	}
 
-	if (!urb)
-		goto handle_xfercomp_done;
-
 	/* Update the QTD and URB states */
 	switch (pipe_type) {
 	case USB_ENDPOINT_XFER_CONTROL:
@@ -1105,7 +1107,7 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
 			       struct dwc2_qtd *qtd)
 {
 	struct dwc2_hcd_urb *urb = qtd->urb;
-	int pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+	int pipe_type;
 
 	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n",
 		chnum);
@@ -1119,6 +1121,8 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
 	if (!urb)
 		goto handle_stall_halt;
 
+	pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+
 	if (pipe_type == USB_ENDPOINT_XFER_CONTROL)
 		dwc2_host_complete(hsotg, qtd, -EPIPE);
 
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index a49217ae3533..07ea39da98f7 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -242,6 +242,80 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 	}
 }
 
+static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
+{
+	if (!dwc->has_hibernation)
+		return 0;
+
+	if (!dwc->nr_scratch)
+		return 0;
+
+	dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
+			DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
+	if (!dwc->scratchbuf)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
+{
+	dma_addr_t scratch_addr;
+	u32 param;
+	int ret;
+
+	scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf,
+			dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
+			DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(dwc->dev, scratch_addr)) {
+		dev_err(dwc->dev, "failed to map scratch buffer\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	dwc->scratch_addr = scratch_addr;
+
+	param = lower_32_bits(scratch_addr);
+
+	ret = dwc3_send_gadget_generic_command(dwc,
+			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
+	if (ret < 0)
+		goto err1;
+
+	param = upper_32_bits(scratch_addr);
+
+	ret = dwc3_send_gadget_generic_command(dwc,
+			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
+	if (ret < 0)
+		goto err1;
+
+	return 0;
+
+err1:
+	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
+			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
+
+err0:
+	return ret;
+}
+
+static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
+{
+	if (!dwc->has_hibernation)
+		return;
+
+	if (!dwc->nr_scratch)
+		return;
+
+	 /* should never fall here */
+	if (!WARN_ON(dwc->scratchbuf))
+		return;
+
+	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
+			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
+	kfree(dwc->scratchbuf);
+}
+
 static void dwc3_core_num_eps(struct dwc3 *dwc)
 {
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
@@ -277,6 +351,7 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
 static int dwc3_core_init(struct dwc3 *dwc)
 {
 	unsigned long		timeout;
+	u32			hwparams4 = dwc->hwparams.hwparams4;
 	u32			reg;
 	int			ret;
 
@@ -314,7 +389,29 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
-		reg &= ~DWC3_GCTL_DSBLCLKGTNG;
+		/**
+		 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
+		 * issue which would cause xHCI compliance tests to fail.
+		 *
+		 * Because of that we cannot enable clock gating on such
+		 * configurations.
+		 *
+		 * Refers to:
+		 *
+		 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
+		 * SOF/ITP Mode Used
+		 */
+		if ((dwc->dr_mode == USB_DR_MODE_HOST ||
+				dwc->dr_mode == USB_DR_MODE_OTG) &&
+				(dwc->revision >= DWC3_REVISION_210A &&
+				dwc->revision <= DWC3_REVISION_250A))
+			reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
+		else
+			reg &= ~DWC3_GCTL_DSBLCLKGTNG;
+		break;
+	case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
+		/* enable hibernation here */
+		dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
 		break;
 	default:
 		dev_dbg(dwc->dev, "No power optimization available\n");
@@ -333,14 +430,30 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
+	ret = dwc3_alloc_scratch_buffers(dwc);
+	if (ret)
+		goto err1;
+
+	ret = dwc3_setup_scratch_buffers(dwc);
+	if (ret)
+		goto err2;
+
 	return 0;
 
+err2:
+	dwc3_free_scratch_buffers(dwc);
+
+err1:
+	usb_phy_shutdown(dwc->usb2_phy);
+	usb_phy_shutdown(dwc->usb3_phy);
+
 err0:
 	return ret;
 }
 
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
+	dwc3_free_scratch_buffers(dwc);
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
 }
@@ -479,6 +592,14 @@ static int dwc3_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
+	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+		dwc->dr_mode = USB_DR_MODE_HOST;
+	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+		dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
+
+	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
+		dwc->dr_mode = USB_DR_MODE_OTG;
+
 	ret = dwc3_core_init(dwc);
 	if (ret) {
 		dev_err(dev, "failed to initialize core\n");
@@ -494,14 +615,6 @@ static int dwc3_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
-		dwc->dr_mode = USB_DR_MODE_HOST;
-	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
-		dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
-
-	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
-		dwc->dr_mode = USB_DR_MODE_OTG;
-
 	switch (dwc->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index f8af8d44af85..00b057860d74 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -36,6 +36,7 @@
 #define DWC3_ENDPOINTS_NUM	32
 #define DWC3_XHCI_RESOURCES_NUM	2
 
+#define DWC3_SCRATCHBUF_SIZE	4096	/* each buffer is assumed to be 4KiB */
 #define DWC3_EVENT_SIZE		4	/* bytes */
 #define DWC3_EVENT_MAX_NUM	64	/* 2 events/endpoint */
 #define DWC3_EVENT_BUFFERS_SIZE	(DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
@@ -157,6 +158,7 @@
 #define DWC3_GCTL_PRTCAP_OTG	3
 
 #define DWC3_GCTL_CORESOFTRESET		(1 << 11)
+#define DWC3_GCTL_SOFITPSYNC		(1 << 10)
 #define DWC3_GCTL_SCALEDOWN(n)		((n) << 4)
 #define DWC3_GCTL_SCALEDOWN_MASK	DWC3_GCTL_SCALEDOWN(3)
 #define DWC3_GCTL_DISSCRAMBLE		(1 << 3)
@@ -318,7 +320,7 @@
 /* Device Endpoint Command Register */
 #define DWC3_DEPCMD_PARAM_SHIFT		16
 #define DWC3_DEPCMD_PARAM(x)		((x) << DWC3_DEPCMD_PARAM_SHIFT)
-#define DWC3_DEPCMD_GET_RSC_IDX(x)     (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
+#define DWC3_DEPCMD_GET_RSC_IDX(x)	(((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
 #define DWC3_DEPCMD_STATUS(x)		(((x) >> 15) & 1)
 #define DWC3_DEPCMD_HIPRI_FORCERM	(1 << 11)
 #define DWC3_DEPCMD_CMDACT		(1 << 10)
@@ -393,6 +395,7 @@ struct dwc3_event_buffer {
  * @busy_slot: first slot which is owned by HW
  * @desc: usb_endpoint_descriptor pointer
  * @dwc: pointer to DWC controller
+ * @saved_state: ep state saved during hibernation
  * @flags: endpoint flags (wedged, stalled, ...)
  * @current_trb: index of current used trb
  * @number: endpoint number (1 - 15)
@@ -415,6 +418,7 @@ struct dwc3_ep {
 	const struct usb_ss_ep_comp_descriptor *comp_desc;
 	struct dwc3		*dwc;
 
+	u32			saved_state;
 	unsigned		flags;
 #define DWC3_EP_ENABLED		(1 << 0)
 #define DWC3_EP_STALL		(1 << 1)
@@ -598,6 +602,7 @@ struct dwc3_scratchpad_array {
  * @ep0_trb: dma address of ep0_trb
  * @ep0_usb_req: dummy req used while handling STD USB requests
  * @ep0_bounce_addr: dma address of ep0_bounce
+ * @scratch_addr: dma address of scratchbuf
  * @lock: for synchronizing
  * @dev: pointer to our struct device
  * @xhci: pointer to our xHCI child
@@ -606,6 +611,7 @@ struct dwc3_scratchpad_array {
  * @gadget_driver: pointer to the gadget driver
  * @regs: base address for our registers
  * @regs_size: address space size
+ * @nr_scratch: number of scratch buffers
  * @num_event_buffers: calculated number of event buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
@@ -615,14 +621,6 @@ struct dwc3_scratchpad_array {
  * @usb3_phy: pointer to USB3 PHY
  * @dcfg: saved contents of DCFG register
  * @gctl: saved contents of GCTL register
- * @is_selfpowered: true when we are selfpowered
- * @three_stage_setup: set if we perform a three phase setup
- * @ep0_bounced: true when we used bounce buffer
- * @ep0_expect_in: true when we expect a DATA IN transfer
- * @start_config_issued: true when StartConfig command has been issued
- * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
- * @needs_fifo_resize: not all users might want fifo resizing, flag it
- * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
  * @isoch_delay: wValue from Set Isochronous Delay request;
  * @u2sel: parameter from Set SEL request.
  * @u2pel: parameter from Set SEL request.
@@ -637,15 +635,31 @@ struct dwc3_scratchpad_array {
  * @mem: points to start of memory which is used for this struct.
  * @hwparams: copy of hwparams registers
  * @root: debugfs root folder pointer
+ * @regset: debugfs pointer to regdump file
+ * @test_mode: true when we're entering a USB test mode
+ * @test_mode_nr: test feature selector
+ * @delayed_status: true when gadget driver asks for delayed status
+ * @ep0_bounced: true when we used bounce buffer
+ * @ep0_expect_in: true when we expect a DATA IN transfer
+ * @has_hibernation: true when dwc3 was configured with Hibernation
+ * @is_selfpowered: true when we are selfpowered
+ * @needs_fifo_resize: not all users might want fifo resizing, flag it
+ * @pullups_connected: true when Run/Stop bit is set
+ * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
+ * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
+ * @start_config_issued: true when StartConfig command has been issued
+ * @three_stage_setup: set if we perform a three phase setup
  */
 struct dwc3 {
 	struct usb_ctrlrequest	*ctrl_req;
 	struct dwc3_trb		*ep0_trb;
 	void			*ep0_bounce;
+	void			*scratchbuf;
 	u8			*setup_buf;
 	dma_addr_t		ctrl_req_addr;
 	dma_addr_t		ep0_trb_addr;
 	dma_addr_t		ep0_bounce_addr;
+	dma_addr_t		scratch_addr;
 	struct dwc3_request	ep0_usb_req;
 
 	/* device lock */
@@ -674,6 +688,7 @@ struct dwc3 {
 	u32			dcfg;
 	u32			gctl;
 
+	u32			nr_scratch;
 	u32			num_event_buffers;
 	u32			u1u2;
 	u32			maximum_speed;
@@ -696,17 +711,6 @@ struct dwc3 {
 #define DWC3_REVISION_240A	0x5533240a
 #define DWC3_REVISION_250A	0x5533250a
 
-	unsigned		is_selfpowered:1;
-	unsigned		three_stage_setup:1;
-	unsigned		ep0_bounced:1;
-	unsigned		ep0_expect_in:1;
-	unsigned		start_config_issued:1;
-	unsigned		setup_packet_pending:1;
-	unsigned		delayed_status:1;
-	unsigned		needs_fifo_resize:1;
-	unsigned		resize_fifos:1;
-	unsigned		pullups_connected:1;
-
 	enum dwc3_ep0_next	ep0_next_event;
 	enum dwc3_ep0_state	ep0state;
 	enum dwc3_link_state	link_state;
@@ -730,6 +734,18 @@ struct dwc3 {
 
 	u8			test_mode;
 	u8			test_mode_nr;
+
+	unsigned		delayed_status:1;
+	unsigned		ep0_bounced:1;
+	unsigned		ep0_expect_in:1;
+	unsigned		has_hibernation:1;
+	unsigned		is_selfpowered:1;
+	unsigned		needs_fifo_resize:1;
+	unsigned		pullups_connected:1;
+	unsigned		resize_fifos:1;
+	unsigned		setup_packet_pending:1;
+	unsigned		start_config_issued:1;
+	unsigned		three_stage_setup:1;
 };
 
 /* -------------------------------------------------------------------------- */
@@ -815,15 +831,15 @@ struct dwc3_event_depevt {
  *	12	- VndrDevTstRcved
  * @reserved15_12: Reserved, not used
  * @event_info: Information about this event
- * @reserved31_24: Reserved, not used
+ * @reserved31_25: Reserved, not used
  */
 struct dwc3_event_devt {
 	u32	one_bit:1;
 	u32	device_event:7;
 	u32	type:4;
 	u32	reserved15_12:4;
-	u32	event_info:8;
-	u32	reserved31_24:8;
+	u32	event_info:9;
+	u32	reserved31_25:7;
 } __packed;
 
 /**
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index b269dbd47fc4..80b3357034b7 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -424,11 +424,6 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "missing memory base resource\n");
-		return -EINVAL;
-	}
-
 	base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2da0a5a2803a..eaf853721fec 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -68,6 +68,22 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
 }
 
 /**
+ * dwc3_gadget_get_link_state - Gets current state of USB Link
+ * @dwc: pointer to our context structure
+ *
+ * Caller should take care of locking. This function will
+ * return the link state on success (>= 0) or -ETIMEDOUT.
+ */
+int dwc3_gadget_get_link_state(struct dwc3 *dwc)
+{
+	u32		reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+
+	return DWC3_DSTS_USBLNKST(reg);
+}
+
+/**
  * dwc3_gadget_set_link_state - Sets USB Link to a particular State
  * @dwc: pointer to our context structure
  * @state: the state to put link into
@@ -417,7 +433,7 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
 static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
 		const struct usb_endpoint_descriptor *desc,
 		const struct usb_ss_ep_comp_descriptor *comp_desc,
-		bool ignore)
+		bool ignore, bool restore)
 {
 	struct dwc3_gadget_ep_cmd_params params;
 
@@ -436,6 +452,11 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
 	if (ignore)
 		params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM;
 
+	if (restore) {
+		params.param0 |= DWC3_DEPCFG_ACTION_RESTORE;
+		params.param2 |= dep->saved_state;
+	}
+
 	params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
 		| DWC3_DEPCFG_XFER_NOT_READY_EN;
 
@@ -494,7 +515,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep)
 static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 		const struct usb_endpoint_descriptor *desc,
 		const struct usb_ss_ep_comp_descriptor *comp_desc,
-		bool ignore)
+		bool ignore, bool restore)
 {
 	struct dwc3		*dwc = dep->dwc;
 	u32			reg;
@@ -508,7 +529,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 			return ret;
 	}
 
-	ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore);
+	ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore,
+			restore);
 	if (ret)
 		return ret;
 
@@ -548,13 +570,13 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 	return 0;
 }
 
-static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum);
+static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
 static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 	struct dwc3_request		*req;
 
 	if (!list_empty(&dep->req_queued)) {
-		dwc3_stop_active_transfer(dwc, dep->number);
+		dwc3_stop_active_transfer(dwc, dep->number, true);
 
 		/* - giveback all requests to gadget driver */
 		while (!list_empty(&dep->req_queued)) {
@@ -659,7 +681,7 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
 	}
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
+	ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return ret;
@@ -771,9 +793,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
 		else
 			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
-
-		if (!req->request.no_interrupt && !chain)
-			trb->ctrl |= DWC3_TRB_CTRL_IOC;
 		break;
 
 	case USB_ENDPOINT_XFER_BULK:
@@ -788,6 +807,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		BUG();
 	}
 
+	if (!req->request.no_interrupt && !chain)
+		trb->ctrl |= DWC3_TRB_CTRL_IOC;
+
 	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
 		trb->ctrl |= DWC3_TRB_CTRL_CSP;
@@ -1077,7 +1099,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		 */
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			if (list_empty(&dep->req_queued)) {
-				dwc3_stop_active_transfer(dwc, dep->number);
+				dwc3_stop_active_transfer(dwc, dep->number, true);
 				dep->flags = DWC3_EP_ENABLED;
 			}
 			return 0;
@@ -1107,6 +1129,23 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		return ret;
 	}
 
+	/*
+	 * 4. Stream Capable Bulk Endpoints. We need to start the transfer
+	 * right away, otherwise host will not know we have streams to be
+	 * handled.
+	 */
+	if (dep->stream_capable) {
+		int	ret;
+
+		ret = __dwc3_gadget_kick_transfer(dep, 0, true);
+		if (ret && ret != -EBUSY) {
+			struct dwc3	*dwc = dep->dwc;
+
+			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
+					dep->name);
+		}
+	}
+
 	return 0;
 }
 
@@ -1163,7 +1202,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
 		}
 		if (r == req) {
 			/* wait until it is processed */
-			dwc3_stop_active_transfer(dwc, dep->number);
+			dwc3_stop_active_transfer(dwc, dep->number, true);
 			goto out1;
 		}
 		dev_err(dwc->dev, "request %p was not queued to %s\n",
@@ -1387,7 +1426,7 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
 	return 0;
 }
 
-static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
+static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
 	u32			reg;
 	u32			timeout = 500;
@@ -1402,9 +1441,17 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 		if (dwc->revision >= DWC3_REVISION_194A)
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 		reg |= DWC3_DCTL_RUN_STOP;
+
+		if (dwc->has_hibernation)
+			reg |= DWC3_DCTL_KEEP_CONNECT;
+
 		dwc->pullups_connected = true;
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
+
+		if (dwc->has_hibernation && !suspend)
+			reg &= ~DWC3_DCTL_KEEP_CONNECT;
+
 		dwc->pullups_connected = false;
 	}
 
@@ -1442,7 +1489,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 	is_on = !!is_on;
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	ret = dwc3_gadget_run_stop(dwc, is_on);
+	ret = dwc3_gadget_run_stop(dwc, is_on, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return ret;
@@ -1549,14 +1596,16 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
 	dep = dwc->eps[0];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
+			false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
 		goto err2;
 	}
 
 	dep = dwc->eps[1];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
+			false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
 		goto err3;
@@ -1652,6 +1701,18 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 		if (epnum == 0 || epnum == 1) {
 			usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
 			dep->endpoint.maxburst = 1;
+			dep->endpoint.has_control = true;
+
+			/*
+			 * REVISIT here we lie a bit to gadget framework,
+			 * because gadget framework expects to see a single
+			 * USB Endpoint zero, and we want the driver to manage
+			 * HW endpoints, we must tell gadget framework that
+			 * HW Endpoint zero supports both directions.
+			 */
+			dep->endpoint.has_dir_in = true;
+			dep->endpoint.has_dir_out = true;
+
 			dep->endpoint.ops = &dwc3_gadget_ep0_ops;
 			if (!epnum)
 				dwc->gadget.ep0 = &dep->endpoint;
@@ -1660,6 +1721,13 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 
 			usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
 			dep->endpoint.max_streams = 15;
+
+			dep->endpoint.has_bulk = true;
+			dep->endpoint.has_interrupt = true;
+			dep->endpoint.has_isochronous = true;
+			dep->endpoint.has_dir_in = !!direction;
+			dep->endpoint.has_dir_out = !direction;
+
 			dep->endpoint.ops = &dwc3_gadget_ep_ops;
 			list_add_tail(&dep->endpoint.ep_list,
 					&dwc->gadget.ep_list);
@@ -1849,15 +1917,12 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 			 */
 			dep->flags = DWC3_EP_PENDING_REQUEST;
 		} else {
-			dwc3_stop_active_transfer(dwc, dep->number);
+			dwc3_stop_active_transfer(dwc, dep->number, true);
 			dep->flags = DWC3_EP_ENABLED;
 		}
 		return 1;
 	}
 
-	if ((event->status & DEPEVT_STATUS_IOC) &&
-			(trb->ctrl & DWC3_TRB_CTRL_IOC))
-		return 0;
 	return 1;
 }
 
@@ -1999,7 +2064,25 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)
 	}
 }
 
-static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
+static void dwc3_suspend_gadget(struct dwc3 *dwc)
+{
+	if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
+		spin_unlock(&dwc->lock);
+		dwc->gadget_driver->suspend(&dwc->gadget);
+		spin_lock(&dwc->lock);
+	}
+}
+
+static void dwc3_resume_gadget(struct dwc3 *dwc)
+{
+	if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
+		spin_unlock(&dwc->lock);
+		dwc->gadget_driver->resume(&dwc->gadget);
+		spin_lock(&dwc->lock);
+	}
+}
+
+static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
 {
 	struct dwc3_ep *dep;
 	struct dwc3_gadget_ep_cmd_params params;
@@ -2031,7 +2114,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
 	 */
 
 	cmd = DWC3_DEPCMD_ENDTRANSFER;
-	cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC;
+	cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
+	cmd |= DWC3_DEPCMD_CMDIOC;
 	cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
 	memset(&params, 0, sizeof(params));
 	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
@@ -2260,17 +2344,23 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 		reg |= DWC3_DCTL_HIRD_THRES(12);
 
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	} else {
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	}
 
 	dep = dwc->eps[0];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true,
+			false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
 		return;
 	}
 
 	dep = dwc->eps[1];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true,
+			false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
 		return;
@@ -2378,9 +2468,50 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 
 	dwc->link_state = next;
 
+	switch (next) {
+	case DWC3_LINK_STATE_U1:
+		if (dwc->speed == USB_SPEED_SUPER)
+			dwc3_suspend_gadget(dwc);
+		break;
+	case DWC3_LINK_STATE_U2:
+	case DWC3_LINK_STATE_U3:
+		dwc3_suspend_gadget(dwc);
+		break;
+	case DWC3_LINK_STATE_RESUME:
+		dwc3_resume_gadget(dwc);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+
 	dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
 }
 
+static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
+		unsigned int evtinfo)
+{
+	unsigned int is_ss = evtinfo & BIT(4);
+
+	/**
+	 * WORKAROUND: DWC3 revison 2.20a with hibernation support
+	 * have a known issue which can cause USB CV TD.9.23 to fail
+	 * randomly.
+	 *
+	 * Because of this issue, core could generate bogus hibernation
+	 * events which SW needs to ignore.
+	 *
+	 * Refers to:
+	 *
+	 * STAR#9000546576: Device Mode Hibernation: Issue in USB 2.0
+	 * Device Fallback from SuperSpeed
+	 */
+	if (is_ss ^ (dwc->speed == USB_SPEED_SUPER))
+		return;
+
+	/* enter hibernation here */
+}
+
 static void dwc3_gadget_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_devt *event)
 {
@@ -2397,6 +2528,13 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
 	case DWC3_DEVICE_EVENT_WAKEUP:
 		dwc3_gadget_wakeup_interrupt(dwc);
 		break;
+	case DWC3_DEVICE_EVENT_HIBER_REQ:
+		if (dev_WARN_ONCE(dwc->dev, !dwc->has_hibernation,
+					"unexpected hibernation event\n"))
+			break;
+
+		dwc3_gadget_hibernation_interrupt(dwc, event->event_info);
+		break;
 	case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
 		dwc3_gadget_linksts_change_interrupt(dwc, event->event_info);
 		break;
@@ -2661,8 +2799,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 int dwc3_gadget_prepare(struct dwc3 *dwc)
 {
-	if (dwc->pullups_connected)
+	if (dwc->pullups_connected) {
 		dwc3_gadget_disable_irq(dwc);
+		dwc3_gadget_run_stop(dwc, true, true);
+	}
 
 	return 0;
 }
@@ -2671,7 +2811,7 @@ void dwc3_gadget_complete(struct dwc3 *dwc)
 {
 	if (dwc->pullups_connected) {
 		dwc3_gadget_enable_irq(dwc);
-		dwc3_gadget_run_stop(dwc, true);
+		dwc3_gadget_run_stop(dwc, true, false);
 	}
 }
 
@@ -2694,12 +2834,14 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
 	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
 	dep = dwc->eps[0];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
+			false);
 	if (ret)
 		goto err0;
 
 	dep = dwc->eps[1];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
+			false);
 	if (ret)
 		goto err1;
 
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index febe1aa7b714..d10124477872 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -86,6 +86,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 		int status);
 
 int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode);
+int dwc3_gadget_get_link_state(struct dwc3 *dwc);
 int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
 
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8154165aa601..3557c7e5040d 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -226,7 +226,7 @@ config USB_GR_UDC
 config USB_OMAP
 	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP1
-	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
+	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
@@ -301,7 +301,6 @@ config USB_PXA27X
 	   gadget drivers to also be dynamically linked.
 
 config USB_S3C_HSOTG
-	depends on ARM
 	tristate "Designware/S3C HS/OtG USB Device controller"
 	help
 	  The Designware USB2.0 high-speed gadget controller
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index cea8c20a1425..f605ad8c1902 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1758,15 +1758,15 @@ static int at91udc_probe(struct platform_device *pdev)
 
 	/* newer chips have more FIFO memory than rm9200 */
 	if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
-		usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
-		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
-		usb_ep_set_maxpacket_limit(&udc->ep[4].ep, 512);
-		usb_ep_set_maxpacket_limit(&udc->ep[5].ep, 512);
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
+		udc->ep[4].maxpacket = 512;
+		udc->ep[5].maxpacket = 512;
 	} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
+		udc->ep[3].maxpacket = 64;
 	} else if (cpu_is_at91sam9263()) {
-		usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
-		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
 	}
 
 	udc->udp_baseaddr = ioremap(res->start, resource_size(res));
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 52771d4c44bc..18a44919ae9f 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1661,7 +1661,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
 	if (dma_status) {
 		int i;
 
-		for (i = 1; i < USBA_NR_ENDPOINTS; i++)
+		for (i = 1; i < USBA_NR_DMAS; i++)
 			if (dma_status & (1 << i))
 				usba_dma_irq(udc, &udc->usba_ep[i]);
 	}
@@ -1670,7 +1670,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
 	if (ep_status) {
 		int i;
 
-		for (i = 0; i < USBA_NR_ENDPOINTS; i++)
+		for (i = 0; i < udc->num_ep; i++)
 			if (ep_status & (1 << i)) {
 				if (ep_is_control(&udc->usba_ep[i]))
 					usba_control_irq(udc, &udc->usba_ep[i]);
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 2922db50befe..a70706e8cb02 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -210,7 +210,7 @@
 #define USBA_FIFO_BASE(x)	((x) << 16)
 
 /* Synth parameters */
-#define USBA_NR_ENDPOINTS	7
+#define USBA_NR_DMAS		7
 
 #define EP0_FIFO_SIZE		64
 #define EP0_EPT_SIZE		USBA_EPT_SIZE_64
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 0567cca1465e..d82ec7173710 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -61,6 +61,33 @@ ep_matches (
 	if (USB_ENDPOINT_XFER_CONTROL == type)
 		return 0;
 
+	/* first check feature flags */
+	if (usb_endpoint_dir_in(desc))
+		if (!ep->has_dir_in)
+			return 0;
+
+	if (usb_endpoint_dir_out(desc))
+		if (!ep->has_dir_out)
+			return 0;
+
+	switch (type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		/* only ep0 */
+		return 0;
+	case USB_ENDPOINT_XFER_BULK:
+		if (ep->has_bulk)
+			goto match;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		if (ep->has_interrupt)
+			goto match;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		if (ep->has_isochronous)
+			goto match;
+		break;
+	}
+
 	/* some other naming convention */
 	if ('e' != ep->name[0])
 		return 0;
@@ -158,8 +185,7 @@ ep_matches (
 		break;
 	}
 
-	/* MATCH!! */
-
+match:
 	/* report address */
 	desc->bEndpointAddress &= USB_DIR_IN;
 	if (isdigit (ep->name [2])) {
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 2b4334394076..b7d273a80675 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -28,6 +28,10 @@
 #include <linux/usb/composite.h>
 #include <linux/usb/functionfs.h>
 
+#include <linux/aio.h>
+#include <linux/mmu_context.h>
+#include <linux/poll.h>
+
 #include "u_fs.h"
 #include "configfs.h"
 
@@ -99,6 +103,14 @@ static struct ffs_function *ffs_func_from_usb(struct usb_function *f)
 }
 
 
+static inline enum ffs_setup_state
+ffs_setup_state_clear_cancelled(struct ffs_data *ffs)
+{
+	return (enum ffs_setup_state)
+		cmpxchg(&ffs->setup_state, FFS_SETUP_CANCELLED, FFS_NO_SETUP);
+}
+
+
 static void ffs_func_eps_disable(struct ffs_function *func);
 static int __must_check ffs_func_eps_enable(struct ffs_function *func);
 
@@ -148,6 +160,25 @@ struct ffs_epfile {
 	unsigned char			_pad;
 };
 
+/*  ffs_io_data structure ***************************************************/
+
+struct ffs_io_data {
+	bool aio;
+	bool read;
+
+	struct kiocb *kiocb;
+	const struct iovec *iovec;
+	unsigned long nr_segs;
+	char __user *buf;
+	size_t len;
+
+	struct mm_struct *mm;
+	struct work_struct work;
+
+	struct usb_ep *ep;
+	struct usb_request *req;
+};
+
 static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
 static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
 
@@ -161,8 +192,10 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
 DEFINE_MUTEX(ffs_lock);
 EXPORT_SYMBOL(ffs_lock);
 
-static struct ffs_dev *ffs_find_dev(const char *name);
+static struct ffs_dev *_ffs_find_dev(const char *name);
+static struct ffs_dev *_ffs_alloc_dev(void);
 static int _ffs_name_dev(struct ffs_dev *dev, const char *name);
+static void _ffs_free_dev(struct ffs_dev *dev);
 static void *ffs_acquire_dev(const char *dev_name);
 static void ffs_release_dev(struct ffs_data *ffs_data);
 static int ffs_ready(struct ffs_data *ffs);
@@ -218,7 +251,7 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
 	}
 
 	ffs->setup_state = FFS_NO_SETUP;
-	return ffs->ep0req_status;
+	return req->status ? req->status : req->actual;
 }
 
 static int __ffs_ep0_stall(struct ffs_data *ffs)
@@ -244,7 +277,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 	ENTER();
 
 	/* Fast check if setup was canceled */
-	if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED)
+	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
 		return -EIDRM;
 
 	/* Acquire mutex */
@@ -310,8 +343,8 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 		 * rather then _irqsave
 		 */
 		spin_lock_irq(&ffs->ev.waitq.lock);
-		switch (FFS_SETUP_STATE(ffs)) {
-		case FFS_SETUP_CANCELED:
+		switch (ffs_setup_state_clear_cancelled(ffs)) {
+		case FFS_SETUP_CANCELLED:
 			ret = -EIDRM;
 			goto done_spin;
 
@@ -346,7 +379,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 		/*
 		 * We are guaranteed to be still in FFS_ACTIVE state
 		 * but the state of setup could have changed from
-		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELED so we need
+		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELLED so we need
 		 * to check for that.  If that happened we copied data
 		 * from user space in vain but it's unlikely.
 		 *
@@ -355,7 +388,8 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 		 * transition can be performed and it's protected by
 		 * mutex.
 		 */
-		if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) {
+		if (ffs_setup_state_clear_cancelled(ffs) ==
+		    FFS_SETUP_CANCELLED) {
 			ret = -EIDRM;
 done_spin:
 			spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -421,7 +455,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 	ENTER();
 
 	/* Fast check if setup was canceled */
-	if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED)
+	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
 		return -EIDRM;
 
 	/* Acquire mutex */
@@ -441,8 +475,8 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 	 */
 	spin_lock_irq(&ffs->ev.waitq.lock);
 
-	switch (FFS_SETUP_STATE(ffs)) {
-	case FFS_SETUP_CANCELED:
+	switch (ffs_setup_state_clear_cancelled(ffs)) {
+	case FFS_SETUP_CANCELLED:
 		ret = -EIDRM;
 		break;
 
@@ -489,7 +523,8 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 		spin_lock_irq(&ffs->ev.waitq.lock);
 
 		/* See ffs_ep0_write() */
-		if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) {
+		if (ffs_setup_state_clear_cancelled(ffs) ==
+		    FFS_SETUP_CANCELLED) {
 			ret = -EIDRM;
 			break;
 		}
@@ -558,6 +593,45 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
 	return ret;
 }
 
+static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait)
+{
+	struct ffs_data *ffs = file->private_data;
+	unsigned int mask = POLLWRNORM;
+	int ret;
+
+	poll_wait(file, &ffs->ev.waitq, wait);
+
+	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
+	if (unlikely(ret < 0))
+		return mask;
+
+	switch (ffs->state) {
+	case FFS_READ_DESCRIPTORS:
+	case FFS_READ_STRINGS:
+		mask |= POLLOUT;
+		break;
+
+	case FFS_ACTIVE:
+		switch (ffs->setup_state) {
+		case FFS_NO_SETUP:
+			if (ffs->ev.count)
+				mask |= POLLIN;
+			break;
+
+		case FFS_SETUP_PENDING:
+		case FFS_SETUP_CANCELLED:
+			mask |= (POLLIN | POLLOUT);
+			break;
+		}
+	case FFS_CLOSING:
+		break;
+	}
+
+	mutex_unlock(&ffs->mutex);
+
+	return mask;
+}
+
 static const struct file_operations ffs_ep0_operations = {
 	.llseek =	no_llseek,
 
@@ -566,6 +640,7 @@ static const struct file_operations ffs_ep0_operations = {
 	.read =		ffs_ep0_read,
 	.release =	ffs_ep0_release,
 	.unlocked_ioctl =	ffs_ep0_ioctl,
+	.poll =		ffs_ep0_poll,
 };
 
 
@@ -581,8 +656,52 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
 	}
 }
 
-static ssize_t ffs_epfile_io(struct file *file,
-			     char __user *buf, size_t len, int read)
+static void ffs_user_copy_worker(struct work_struct *work)
+{
+	struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
+						   work);
+	int ret = io_data->req->status ? io_data->req->status :
+					 io_data->req->actual;
+
+	if (io_data->read && ret > 0) {
+		int i;
+		size_t pos = 0;
+		use_mm(io_data->mm);
+		for (i = 0; i < io_data->nr_segs; i++) {
+			if (unlikely(copy_to_user(io_data->iovec[i].iov_base,
+						 &io_data->buf[pos],
+						 io_data->iovec[i].iov_len))) {
+				ret = -EFAULT;
+				break;
+			}
+			pos += io_data->iovec[i].iov_len;
+		}
+		unuse_mm(io_data->mm);
+	}
+
+	aio_complete(io_data->kiocb, ret, ret);
+
+	usb_ep_free_request(io_data->ep, io_data->req);
+
+	io_data->kiocb->private = NULL;
+	if (io_data->read)
+		kfree(io_data->iovec);
+	kfree(io_data->buf);
+	kfree(io_data);
+}
+
+static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
+					 struct usb_request *req)
+{
+	struct ffs_io_data *io_data = req->context;
+
+	ENTER();
+
+	INIT_WORK(&io_data->work, ffs_user_copy_worker);
+	schedule_work(&io_data->work);
+}
+
+static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
 {
 	struct ffs_epfile *epfile = file->private_data;
 	struct ffs_ep *ep;
@@ -612,7 +731,7 @@ static ssize_t ffs_epfile_io(struct file *file,
 	}
 
 	/* Do we halt? */
-	halt = !read == !epfile->in;
+	halt = (!io_data->read == !epfile->in);
 	if (halt && epfile->isoc) {
 		ret = -EINVAL;
 		goto error;
@@ -630,15 +749,32 @@ static ssize_t ffs_epfile_io(struct file *file,
 		 * Controller may require buffer size to be aligned to
 		 * maxpacketsize of an out endpoint.
 		 */
-		data_len = read ? usb_ep_align_maybe(gadget, ep->ep, len) : len;
+		data_len = io_data->read ?
+			   usb_ep_align_maybe(gadget, ep->ep, io_data->len) :
+			   io_data->len;
 
 		data = kmalloc(data_len, GFP_KERNEL);
 		if (unlikely(!data))
 			return -ENOMEM;
-
-		if (!read && unlikely(copy_from_user(data, buf, len))) {
-			ret = -EFAULT;
-			goto error;
+		if (io_data->aio && !io_data->read) {
+			int i;
+			size_t pos = 0;
+			for (i = 0; i < io_data->nr_segs; i++) {
+				if (unlikely(copy_from_user(&data[pos],
+					     io_data->iovec[i].iov_base,
+					     io_data->iovec[i].iov_len))) {
+					ret = -EFAULT;
+					goto error;
+				}
+				pos += io_data->iovec[i].iov_len;
+			}
+		} else {
+			if (!io_data->read &&
+			    unlikely(__copy_from_user(data, io_data->buf,
+						      io_data->len))) {
+				ret = -EFAULT;
+				goto error;
+			}
 		}
 	}
 
@@ -661,24 +797,52 @@ static ssize_t ffs_epfile_io(struct file *file,
 		ret = -EBADMSG;
 	} else {
 		/* Fire the request */
-		DECLARE_COMPLETION_ONSTACK(done);
+		struct usb_request *req;
 
-		struct usb_request *req = ep->req;
-		req->context  = &done;
-		req->complete = ffs_epfile_io_complete;
-		req->buf      = data;
-		req->length   = data_len;
+		if (io_data->aio) {
+			req = usb_ep_alloc_request(ep->ep, GFP_KERNEL);
+			if (unlikely(!req))
+				goto error;
 
-		ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
+			req->buf      = data;
+			req->length   = io_data->len;
 
-		spin_unlock_irq(&epfile->ffs->eps_lock);
+			io_data->buf = data;
+			io_data->ep = ep->ep;
+			io_data->req = req;
 
-		if (unlikely(ret < 0)) {
-			/* nop */
-		} else if (unlikely(wait_for_completion_interruptible(&done))) {
-			ret = -EINTR;
-			usb_ep_dequeue(ep->ep, req);
+			req->context  = io_data;
+			req->complete = ffs_epfile_async_io_complete;
+
+			ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
+			if (unlikely(ret)) {
+				usb_ep_free_request(ep->ep, req);
+				goto error;
+			}
+			ret = -EIOCBQUEUED;
+
+			spin_unlock_irq(&epfile->ffs->eps_lock);
 		} else {
+			DECLARE_COMPLETION_ONSTACK(done);
+
+			req = ep->req;
+			req->buf      = data;
+			req->length   = io_data->len;
+
+			req->context  = &done;
+			req->complete = ffs_epfile_io_complete;
+
+			ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
+
+			spin_unlock_irq(&epfile->ffs->eps_lock);
+
+			if (unlikely(ret < 0)) {
+				/* nop */
+			} else if (unlikely(
+				   wait_for_completion_interruptible(&done))) {
+				ret = -EINTR;
+				usb_ep_dequeue(ep->ep, req);
+			} else {
 			/*
 			 * XXX We may end up silently droping data here.
 			 * Since data_len (i.e. req->length) may be bigger
@@ -687,14 +851,18 @@ static ssize_t ffs_epfile_io(struct file *file,
 			 * space for.
 			 */
 			ret = ep->status;
-			if (read && ret > 0 &&
-			    unlikely(copy_to_user(buf, data,
-						  min_t(size_t, ret, len))))
+			if (io_data->read && ret > 0 &&
+			    unlikely(copy_to_user(io_data->buf, data,
+						  min_t(size_t, ret,
+						  io_data->len))))
 				ret = -EFAULT;
+			}
+			kfree(data);
 		}
 	}
 
 	mutex_unlock(&epfile->mutex);
+	return ret;
 error:
 	kfree(data);
 	return ret;
@@ -704,17 +872,31 @@ static ssize_t
 ffs_epfile_write(struct file *file, const char __user *buf, size_t len,
 		 loff_t *ptr)
 {
+	struct ffs_io_data io_data;
+
 	ENTER();
 
-	return ffs_epfile_io(file, (char __user *)buf, len, 0);
+	io_data.aio = false;
+	io_data.read = false;
+	io_data.buf = (char * __user)buf;
+	io_data.len = len;
+
+	return ffs_epfile_io(file, &io_data);
 }
 
 static ssize_t
 ffs_epfile_read(struct file *file, char __user *buf, size_t len, loff_t *ptr)
 {
+	struct ffs_io_data io_data;
+
 	ENTER();
 
-	return ffs_epfile_io(file, buf, len, 1);
+	io_data.aio = false;
+	io_data.read = true;
+	io_data.buf = buf;
+	io_data.len = len;
+
+	return ffs_epfile_io(file, &io_data);
 }
 
 static int
@@ -733,6 +915,89 @@ ffs_epfile_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static int ffs_aio_cancel(struct kiocb *kiocb)
+{
+	struct ffs_io_data *io_data = kiocb->private;
+	struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
+	int value;
+
+	ENTER();
+
+	spin_lock_irq(&epfile->ffs->eps_lock);
+
+	if (likely(io_data && io_data->ep && io_data->req))
+		value = usb_ep_dequeue(io_data->ep, io_data->req);
+	else
+		value = -EINVAL;
+
+	spin_unlock_irq(&epfile->ffs->eps_lock);
+
+	return value;
+}
+
+static ssize_t ffs_epfile_aio_write(struct kiocb *kiocb,
+				    const struct iovec *iovec,
+				    unsigned long nr_segs, loff_t loff)
+{
+	struct ffs_io_data *io_data;
+
+	ENTER();
+
+	io_data = kmalloc(sizeof(*io_data), GFP_KERNEL);
+	if (unlikely(!io_data))
+		return -ENOMEM;
+
+	io_data->aio = true;
+	io_data->read = false;
+	io_data->kiocb = kiocb;
+	io_data->iovec = iovec;
+	io_data->nr_segs = nr_segs;
+	io_data->len = kiocb->ki_nbytes;
+	io_data->mm = current->mm;
+
+	kiocb->private = io_data;
+
+	kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
+
+	return ffs_epfile_io(kiocb->ki_filp, io_data);
+}
+
+static ssize_t ffs_epfile_aio_read(struct kiocb *kiocb,
+				   const struct iovec *iovec,
+				   unsigned long nr_segs, loff_t loff)
+{
+	struct ffs_io_data *io_data;
+	struct iovec *iovec_copy;
+
+	ENTER();
+
+	iovec_copy = kmalloc_array(nr_segs, sizeof(*iovec_copy), GFP_KERNEL);
+	if (unlikely(!iovec_copy))
+		return -ENOMEM;
+
+	memcpy(iovec_copy, iovec, sizeof(struct iovec)*nr_segs);
+
+	io_data = kmalloc(sizeof(*io_data), GFP_KERNEL);
+	if (unlikely(!io_data)) {
+		kfree(iovec_copy);
+		return -ENOMEM;
+	}
+
+	io_data->aio = true;
+	io_data->read = true;
+	io_data->kiocb = kiocb;
+	io_data->iovec = iovec_copy;
+	io_data->nr_segs = nr_segs;
+	io_data->len = kiocb->ki_nbytes;
+	io_data->mm = current->mm;
+
+	kiocb->private = io_data;
+
+	kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
+
+	return ffs_epfile_io(kiocb->ki_filp, io_data);
+}
+
 static int
 ffs_epfile_release(struct inode *inode, struct file *file)
 {
@@ -789,6 +1054,8 @@ static const struct file_operations ffs_epfile_operations = {
 	.open =		ffs_epfile_open,
 	.write =	ffs_epfile_write,
 	.read =		ffs_epfile_read,
+	.aio_write =	ffs_epfile_aio_write,
+	.aio_read =	ffs_epfile_aio_read,
 	.release =	ffs_epfile_release,
 	.unlocked_ioctl =	ffs_epfile_ioctl,
 };
@@ -1789,7 +2056,7 @@ static void __ffs_event_add(struct ffs_data *ffs,
 	 * the source does nothing.
 	 */
 	if (ffs->setup_state == FFS_SETUP_PENDING)
-		ffs->setup_state = FFS_SETUP_CANCELED;
+		ffs->setup_state = FFS_SETUP_CANCELLED;
 
 	switch (type) {
 	case FUNCTIONFS_RESUME:
@@ -2258,7 +2525,7 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
 
 static LIST_HEAD(ffs_devices);
 
-static struct ffs_dev *_ffs_find_dev(const char *name)
+static struct ffs_dev *_ffs_do_find_dev(const char *name)
 {
 	struct ffs_dev *dev;
 
@@ -2275,7 +2542,7 @@ static struct ffs_dev *_ffs_find_dev(const char *name)
 /*
  * ffs_lock must be taken by the caller of this function
  */
-static struct ffs_dev *ffs_get_single_dev(void)
+static struct ffs_dev *_ffs_get_single_dev(void)
 {
 	struct ffs_dev *dev;
 
@@ -2291,15 +2558,15 @@ static struct ffs_dev *ffs_get_single_dev(void)
 /*
  * ffs_lock must be taken by the caller of this function
  */
-static struct ffs_dev *ffs_find_dev(const char *name)
+static struct ffs_dev *_ffs_find_dev(const char *name)
 {
 	struct ffs_dev *dev;
 
-	dev = ffs_get_single_dev();
+	dev = _ffs_get_single_dev();
 	if (dev)
 		return dev;
 
-	return _ffs_find_dev(name);
+	return _ffs_do_find_dev(name);
 }
 
 /* Configfs support *********************************************************/
@@ -2335,7 +2602,7 @@ static void ffs_free_inst(struct usb_function_instance *f)
 
 	opts = to_f_fs_opts(f);
 	ffs_dev_lock();
-	ffs_free_dev(opts->dev);
+	_ffs_free_dev(opts->dev);
 	ffs_dev_unlock();
 	kfree(opts);
 }
@@ -2390,7 +2657,7 @@ static struct usb_function_instance *ffs_alloc_inst(void)
 	opts->func_inst.set_inst_name = ffs_set_inst_name;
 	opts->func_inst.free_func_inst = ffs_free_inst;
 	ffs_dev_lock();
-	dev = ffs_alloc_dev();
+	dev = _ffs_alloc_dev();
 	ffs_dev_unlock();
 	if (IS_ERR(dev)) {
 		kfree(opts);
@@ -2478,12 +2745,12 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
 /*
  * ffs_lock must be taken by the caller of this function
  */
-struct ffs_dev *ffs_alloc_dev(void)
+static struct ffs_dev *_ffs_alloc_dev(void)
 {
 	struct ffs_dev *dev;
 	int ret;
 
-	if (ffs_get_single_dev())
+	if (_ffs_get_single_dev())
 			return ERR_PTR(-EBUSY);
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -2511,10 +2778,10 @@ static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
 {
 	struct ffs_dev *existing;
 
-	existing = _ffs_find_dev(name);
+	existing = _ffs_do_find_dev(name);
 	if (existing)
 		return -EBUSY;
-	
+
 	dev->name = name;
 
 	return 0;
@@ -2555,7 +2822,7 @@ EXPORT_SYMBOL(ffs_single_dev);
 /*
  * ffs_lock must be taken by the caller of this function
  */
-void ffs_free_dev(struct ffs_dev *dev)
+static void _ffs_free_dev(struct ffs_dev *dev)
 {
 	list_del(&dev->entry);
 	if (dev->name_allocated)
@@ -2572,7 +2839,7 @@ static void *ffs_acquire_dev(const char *dev_name)
 	ENTER();
 	ffs_dev_lock();
 
-	ffs_dev = ffs_find_dev(dev_name);
+	ffs_dev = _ffs_find_dev(dev_name);
 	if (!ffs_dev)
 		ffs_dev = ERR_PTR(-ENODEV);
 	else if (ffs_dev->mounted)
@@ -2595,11 +2862,12 @@ static void ffs_release_dev(struct ffs_data *ffs_data)
 	ffs_dev_lock();
 
 	ffs_dev = ffs_data->private_data;
-	if (ffs_dev)
+	if (ffs_dev) {
 		ffs_dev->mounted = false;
-	
-	if (ffs_dev->ffs_release_dev_callback)
-		ffs_dev->ffs_release_dev_callback(ffs_dev);
+
+		if (ffs_dev->ffs_release_dev_callback)
+			ffs_dev->ffs_release_dev_callback(ffs_dev);
+	}
 
 	ffs_dev_unlock();
 }
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 36d4bb23087f..807b31c0edc3 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -664,9 +664,10 @@ static int f_midi_register_card(struct f_midi *midi)
 		.dev_free = f_midi_snd_free,
 	};
 
-	err = snd_card_create(midi->index, midi->id, THIS_MODULE, 0, &card);
+	err = snd_card_new(&midi->gadget->dev, midi->index, midi->id,
+			   THIS_MODULE, 0, &card);
 	if (err < 0) {
-		ERROR(midi, "snd_card_create() failed\n");
+		ERROR(midi, "snd_card_new() failed\n");
 		goto fail;
 	}
 	midi->card = card;
@@ -703,8 +704,6 @@ static int f_midi_register_card(struct f_midi *midi)
 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);
 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);
 
-	snd_card_set_dev(card, &midi->gadget->dev);
-
 	/* register it - we're ready to go */
 	err = snd_card_register(card);
 	if (err < 0) {
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
index 2f23566e53d8..bc23040c7790 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/f_uac2.c
@@ -394,7 +394,7 @@ static int snd_uac2_probe(struct platform_device *pdev)
 	int err;
 
 	/* Choose any slot, with no id */
-	err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card);
+	err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
@@ -421,8 +421,6 @@ static int snd_uac2_probe(struct platform_device *pdev)
 	strcpy(card->shortname, "UAC2_Gadget");
 	sprintf(card->longname, "UAC2_Gadget %i", pdev->id);
 
-	snd_card_set_dev(card, &pdev->dev);
-
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 		snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
 
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/gr_udc.c
index 914cbd84ee40..f984ee75324d 100644
--- a/drivers/usb/gadget/gr_udc.c
+++ b/drivers/usb/gadget/gr_udc.c
@@ -225,14 +225,8 @@ static void gr_dfs_create(struct gr_udc *dev)
 	const char *name = "gr_udc_state";
 
 	dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL);
-	if (IS_ERR(dev->dfs_root)) {
-		dev_err(dev->dev, "Failed to create debugfs directory\n");
-		return;
-	}
-	dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root,
-					     dev, &gr_dfs_fops);
-	if (IS_ERR(dev->dfs_state))
-		dev_err(dev->dev, "Failed to create debugfs file %s\n", name);
+	dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root, dev,
+					     &gr_dfs_fops);
 }
 
 static void gr_dfs_delete(struct gr_udc *dev)
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 049ebab0d360..a94bb10eeb03 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -55,7 +55,6 @@
 #include <mach/hardware.h>
 #include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <mach/platform.h>
 #include <mach/irqs.h>
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 69b76efd11e9..6474081dcbaf 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -427,12 +427,17 @@ setup_rx_reqs(struct printer_dev *dev)
 		req->length = USB_BUFSIZE;
 		req->complete = rx_complete;
 
+		/* here, we unlock, and only unlock, to avoid deadlock. */
+		spin_unlock(&dev->lock);
 		error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+		spin_lock(&dev->lock);
 		if (error) {
 			DBG(dev, "rx submit --> %d\n", error);
 			list_add(&req->list, &dev->rx_reqs);
 			break;
-		} else {
+		}
+		/* if the req is empty, then add it into dev->rx_reqs_active. */
+		else if (list_empty(&req->list)) {
 			list_add(&req->list, &dev->rx_reqs_active);
 		}
 	}
@@ -1133,6 +1138,7 @@ static int __init printer_bind_config(struct usb_configuration *c)
 				  NULL, "g_printer");
 	if (IS_ERR(dev->pdev)) {
 		ERROR(dev, "Failed to create device: g_printer\n");
+		status = PTR_ERR(dev->pdev);
 		goto fail;
 	}
 
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 1172eaeddd85..99c8e3ca6a3c 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -617,7 +617,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 	to_write = DIV_ROUND_UP(to_write, 4);
 	data = hs_req->req.buf + buf_pos;
 
-	writesl(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
+	iowrite32_rep(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
 
 	return (to_write >= can_write) ? -ENOSPC : 0;
 }
@@ -720,8 +720,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 		ureq->length, ureq->actual);
 	if (0)
 		dev_dbg(hsotg->dev,
-			"REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n",
-			ureq->buf, length, ureq->dma,
+			"REQ buf %p len %d dma 0x%pad noi=%d zp=%d snok=%d\n",
+			ureq->buf, length, &ureq->dma,
 			ureq->no_interrupt, ureq->zero, ureq->short_not_ok);
 
 	maxreq = get_ep_limit(hs_ep);
@@ -789,8 +789,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 		dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
 		writel(ureq->dma, hsotg->regs + dma_reg);
 
-		dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n",
-			__func__, ureq->dma, dma_reg);
+		dev_dbg(hsotg->dev, "%s: 0x%pad => 0x%08x\n",
+			__func__, &ureq->dma, dma_reg);
 	}
 
 	ctrl |= DxEPCTL_EPEna;	/* ensure ep enabled */
@@ -1186,6 +1186,41 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
 static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
 
 /**
+ * s3c_hsotg_stall_ep0 - stall ep0
+ * @hsotg: The device state
+ *
+ * Set stall for ep0 as response for setup request.
+ */
+static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
+	struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
+	u32 reg;
+	u32 ctrl;
+
+	dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
+	reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
+
+	/*
+	 * DxEPCTL_Stall will be cleared by EP once it has
+	 * taken effect, so no need to clear later.
+	 */
+
+	ctrl = readl(hsotg->regs + reg);
+	ctrl |= DxEPCTL_Stall;
+	ctrl |= DxEPCTL_CNAK;
+	writel(ctrl, hsotg->regs + reg);
+
+	dev_dbg(hsotg->dev,
+		"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
+		ctrl, reg, readl(hsotg->regs + reg));
+
+	 /*
+	  * complete won't be called, so we enqueue
+	  * setup request here
+	  */
+	 s3c_hsotg_enqueue_setup(hsotg);
+}
+
+/**
  * s3c_hsotg_process_control - process a control request
  * @hsotg: The device state
  * @ctrl: The control request received
@@ -1262,38 +1297,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
 	 * so respond with a STALL for the status stage to indicate failure.
 	 */
 
-	if (ret < 0) {
-		u32 reg;
-		u32 ctrl;
-
-		dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
-		reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
-
-		/*
-		 * DxEPCTL_Stall will be cleared by EP once it has
-		 * taken effect, so no need to clear later.
-		 */
-
-		ctrl = readl(hsotg->regs + reg);
-		ctrl |= DxEPCTL_Stall;
-		ctrl |= DxEPCTL_CNAK;
-		writel(ctrl, hsotg->regs + reg);
-
-		dev_dbg(hsotg->dev,
-			"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
-			ctrl, reg, readl(hsotg->regs + reg));
-
-		/*
-		 * don't believe we need to anything more to get the EP
-		 * to reply with a STALL packet
-		 */
-
-		 /*
-		  * complete won't be called, so we enqueue
-		  * setup request here
-		  */
-		 s3c_hsotg_enqueue_setup(hsotg);
-	}
+	if (ret < 0)
+		s3c_hsotg_stall_ep0(hsotg);
 }
 
 /**
@@ -1488,7 +1493,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 	 * note, we might over-write the buffer end by 3 bytes depending on
 	 * alignment of the data.
 	 */
-	readsl(fifo, hs_req->req.buf + read_ptr, to_read);
+	ioread32_rep(fifo, hs_req->req.buf + read_ptr, to_read);
 }
 
 /**
@@ -2832,6 +2837,15 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 
 	dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
 
+	if (index == 0) {
+		if (value)
+			s3c_hsotg_stall_ep0(hs);
+		else
+			dev_warn(hs->dev,
+				 "%s: can't clear halt on ep0\n", __func__);
+		return 0;
+	}
+
 	/* write both IN and OUT control registers */
 
 	epreg = DIEPCTL(index);
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index ea4bbfe72ec0..10c6a128250c 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1344,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	return 0;
 err_add_udc:
-err_add_device:
 	clk_disable(hsudc->uclk);
 err_res:
 	if (!IS_ERR_OR_NULL(hsudc->transceiver))
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h
index bc2d3718219b..c39e805025b9 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/u_fs.h
@@ -65,10 +65,8 @@ static inline void ffs_dev_unlock(void)
 	mutex_unlock(&ffs_lock);
 }
 
-struct ffs_dev *ffs_alloc_dev(void);
 int ffs_name_dev(struct ffs_dev *dev, const char *name);
 int ffs_single_dev(struct ffs_dev *dev);
-void ffs_free_dev(struct ffs_dev *dev);
 
 struct ffs_epfile;
 struct ffs_function;
@@ -125,7 +123,7 @@ enum ffs_setup_state {
 	 * setup.  If this state is set read/write on ep0 return
 	 * -EIDRM.  This state is only set when adding event.
 	 */
-	FFS_SETUP_CANCELED
+	FFS_SETUP_CANCELLED
 };
 
 struct ffs_data {
@@ -156,7 +154,6 @@ struct ffs_data {
 	 */
 	struct usb_request		*ep0req;		/* P: mutex */
 	struct completion		ep0req_completion;	/* P: mutex */
-	int				ep0req_status;		/* P: mutex */
 
 	/* reference counter */
 	atomic_t			ref;
@@ -168,19 +165,18 @@ struct ffs_data {
 
 	/*
 	 * Possible transitions:
-	 * + FFS_NO_SETUP       -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
+	 * + FFS_NO_SETUP        -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
 	 *               happens only in ep0 read which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_NO_SETUP       -- P: ev.waitq.lock
+	 * + FFS_SETUP_PENDING   -> FFS_NO_SETUP       -- P: ev.waitq.lock
 	 *               happens only in ep0 i/o  which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_SETUP_CANCELED -- P: ev.waitq.lock
-	 * + FFS_SETUP_CANCELED -> FFS_NO_SETUP       -- cmpxchg
+	 * + FFS_SETUP_PENDING   -> FFS_SETUP_CANCELLED -- P: ev.waitq.lock
+	 * + FFS_SETUP_CANCELLED -> FFS_NO_SETUP        -- cmpxchg
+	 *
+	 * This field should never be accessed directly and instead
+	 * ffs_setup_state_clear_cancelled function should be used.
 	 */
 	enum ffs_setup_state		setup_state;
 
-#define FFS_SETUP_STATE(ffs)					\
-	((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state,	\
-				       FFS_SETUP_CANCELED, FFS_NO_SETUP))
-
 	/* Events & such. */
 	struct {
 		u8				types[4];
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index b369292d4b90..ad0aca812002 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -549,8 +549,8 @@ static void gs_rx_push(unsigned long _port)
 		port->read_started--;
 	}
 
-	/* Push from tty to ldisc; without low_latency set this is handled by
-	 * a workqueue, so we won't get callbacks and can hold port_lock
+	/* Push from tty to ldisc; this is handled by a workqueue,
+	 * so we won't get callbacks and can hold port_lock
 	 */
 	if (do_push)
 		tty_flip_buffer_push(&port->port);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index a9707da7da0b..3d9e54062d62 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -314,7 +314,6 @@ config USB_ISP1760_HCD
 
 config USB_ISP1362_HCD
 	tristate "ISP1362 HCD support"
-	default N
 	---help---
 	  Supports the Philips ISP1362 chip as a host controller
 
@@ -326,7 +325,6 @@ config USB_ISP1362_HCD
 config USB_FUSBH200_HCD
 	tristate "FUSBH200 HCD support"
 	depends on USB
-	default N
 	---help---
 	Faraday FUSBH200 is designed to meet USB2.0 EHCI specification
 	with minor modification.
@@ -337,7 +335,6 @@ config USB_FUSBH200_HCD
 config USB_FOTG210_HCD
 	tristate "FOTG210 HCD support"
 	depends on USB
-	default N
 	---help---
 	  Faraday FOTG210 is an OTG controller which can be configured as
 	  an USB2.0 host. It is designed to meet USB2.0 EHCI specification
@@ -584,7 +581,6 @@ config FHCI_DEBUG
 config USB_U132_HCD
 	tristate "Elan U132 Adapter Host Controller"
 	depends on USB_FTDI_ELAN
-	default M
 	help
 	  The U132 adapter is a USB to CardBus adapter specifically designed
 	  for PC cards that contain an OHCI host controller. Typical PC cards
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 01536cfd361d..b3a0e11073aa 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2007 Steven Brown <sbrown@cortland.com>
  * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
  * Derived from the ohci-ssb driver
  * Copyright 2007 Michael Buesch <m@bues.ch>
@@ -18,6 +19,7 @@
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -25,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -33,6 +36,13 @@
 #include "ehci.h"
 
 #define DRIVER_DESC "EHCI generic platform driver"
+#define EHCI_MAX_CLKS 3
+#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
+
+struct ehci_platform_priv {
+	struct clk *clks[EHCI_MAX_CLKS];
+	struct phy *phy;
+};
 
 static const char hcd_name[] = "ehci-platform";
 
@@ -45,8 +55,6 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
 
 	hcd->has_tt = pdata->has_tt;
 	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
-	ehci->big_endian_desc = pdata->big_endian_desc;
-	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
 	if (pdata->pre_setup) {
 		retval = pdata->pre_setup(hcd);
@@ -64,38 +72,91 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
 	return 0;
 }
 
+static int ehci_platform_power_on(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+	int clk, ret;
+
+	for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+		ret = clk_prepare_enable(priv->clks[clk]);
+		if (ret)
+			goto err_disable_clks;
+	}
+
+	if (priv->phy) {
+		ret = phy_init(priv->phy);
+		if (ret)
+			goto err_disable_clks;
+
+		ret = phy_power_on(priv->phy);
+		if (ret)
+			goto err_exit_phy;
+	}
+
+	return 0;
+
+err_exit_phy:
+	phy_exit(priv->phy);
+err_disable_clks:
+	while (--clk >= 0)
+		clk_disable_unprepare(priv->clks[clk]);
+
+	return ret;
+}
+
+static void ehci_platform_power_off(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+	int clk;
+
+	if (priv->phy) {
+		phy_power_off(priv->phy);
+		phy_exit(priv->phy);
+	}
+
+	for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
+		if (priv->clks[clk])
+			clk_disable_unprepare(priv->clks[clk]);
+}
+
 static struct hc_driver __read_mostly ehci_platform_hc_driver;
 
 static const struct ehci_driver_overrides platform_overrides __initconst = {
-	.reset =	ehci_platform_reset,
+	.reset =		ehci_platform_reset,
+	.extra_priv_size =	sizeof(struct ehci_platform_priv),
 };
 
-static struct usb_ehci_pdata ehci_platform_defaults;
+static struct usb_ehci_pdata ehci_platform_defaults = {
+	.power_on =		ehci_platform_power_on,
+	.power_suspend =	ehci_platform_power_off,
+	.power_off =		ehci_platform_power_off,
+};
 
 static int ehci_platform_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
-	struct usb_ehci_pdata *pdata;
-	int irq;
-	int err;
+	struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+	struct ehci_platform_priv *priv;
+	struct ehci_hcd *ehci;
+	int err, irq, clk = 0;
 
 	if (usb_disabled())
 		return -ENODEV;
 
 	/*
-	 * use reasonable defaults so platforms don't have to provide these.
-	 * with DT probing on ARM, none of these are set.
+	 * Use reasonable defaults so platforms don't have to provide these
+	 * with DT probing on ARM.
 	 */
-	if (!dev_get_platdata(&dev->dev))
-		dev->dev.platform_data = &ehci_platform_defaults;
+	if (!pdata)
+		pdata = &ehci_platform_defaults;
 
 	err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
 	if (err)
 		return err;
 
-	pdata = dev_get_platdata(&dev->dev);
-
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
 		dev_err(&dev->dev, "no irq provided");
@@ -107,17 +168,72 @@ static int ehci_platform_probe(struct platform_device *dev)
 		return -ENXIO;
 	}
 
+	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+			     dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(dev, hcd);
+	dev->dev.platform_data = pdata;
+	priv = hcd_to_ehci_priv(hcd);
+	ehci = hcd_to_ehci(hcd);
+
+	if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
+		if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+			ehci->big_endian_mmio = 1;
+
+		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+			ehci->big_endian_desc = 1;
+
+		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+			ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+
+		priv->phy = devm_phy_get(&dev->dev, "usb");
+		if (IS_ERR(priv->phy)) {
+			err = PTR_ERR(priv->phy);
+			if (err == -EPROBE_DEFER)
+				goto err_put_hcd;
+			priv->phy = NULL;
+		}
+
+		for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
+			priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+			if (IS_ERR(priv->clks[clk])) {
+				err = PTR_ERR(priv->clks[clk]);
+				if (err == -EPROBE_DEFER)
+					goto err_put_clks;
+				priv->clks[clk] = NULL;
+				break;
+			}
+		}
+	}
+
+	if (pdata->big_endian_desc)
+		ehci->big_endian_desc = 1;
+	if (pdata->big_endian_mmio)
+		ehci->big_endian_mmio = 1;
+
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+	if (ehci->big_endian_mmio) {
+		dev_err(&dev->dev,
+			"Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n");
+		err = -EINVAL;
+		goto err_put_clks;
+	}
+#endif
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+	if (ehci->big_endian_desc) {
+		dev_err(&dev->dev,
+			"Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n");
+		err = -EINVAL;
+		goto err_put_clks;
+	}
+#endif
+
 	if (pdata->power_on) {
 		err = pdata->power_on(dev);
 		if (err < 0)
-			return err;
-	}
-
-	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
-			     dev_name(&dev->dev));
-	if (!hcd) {
-		err = -ENOMEM;
-		goto err_power;
+			goto err_put_clks;
 	}
 
 	hcd->rsrc_start = res_mem->start;
@@ -126,22 +242,28 @@ static int ehci_platform_probe(struct platform_device *dev)
 	hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
 	if (IS_ERR(hcd->regs)) {
 		err = PTR_ERR(hcd->regs);
-		goto err_put_hcd;
+		goto err_power;
 	}
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err)
-		goto err_put_hcd;
+		goto err_power;
 
 	device_wakeup_enable(hcd->self.controller);
 	platform_set_drvdata(dev, hcd);
 
 	return err;
 
-err_put_hcd:
-	usb_put_hcd(hcd);
 err_power:
 	if (pdata->power_off)
 		pdata->power_off(dev);
+err_put_clks:
+	while (--clk >= 0)
+		clk_put(priv->clks[clk]);
+err_put_hcd:
+	if (pdata == &ehci_platform_defaults)
+		dev->dev.platform_data = NULL;
+
+	usb_put_hcd(hcd);
 
 	return err;
 }
@@ -150,13 +272,19 @@ static int ehci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+	struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+	int clk;
 
 	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
 
 	if (pdata->power_off)
 		pdata->power_off(dev);
 
+	for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
+		clk_put(priv->clks[clk]);
+
+	usb_put_hcd(hcd);
+
 	if (pdata == &ehci_platform_defaults)
 		dev->dev.platform_data = NULL;
 
@@ -207,8 +335,10 @@ static int ehci_platform_resume(struct device *dev)
 static const struct of_device_id vt8500_ehci_ids[] = {
 	{ .compatible = "via,vt8500-ehci", },
 	{ .compatible = "wm,prizm-ehci", },
+	{ .compatible = "generic-ehci", },
 	{}
 };
+MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
 
 static const struct platform_device_id ehci_platform_table[] = {
 	{ "ehci-platform", 0 },
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index af28b748e87a..27ac6ad53c3d 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -38,10 +38,6 @@
 
 #include "ehci.h"
 
-#define TEGRA_USB_BASE			0xC5000000
-#define TEGRA_USB2_BASE			0xC5004000
-#define TEGRA_USB3_BASE			0xC5008000
-
 #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
 #define TEGRA_USB_DMA_ALIGN 32
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 68f674cd095f..b6002c951c5c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2007 Michael Buesch <m@bues.ch>
  * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
  * Derived from the OCHI-SSB driver
  * Derived from the OHCI-PCI driver
@@ -14,11 +15,14 @@
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <linux/hrtimer.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/usb.h>
@@ -27,6 +31,13 @@
 #include "ohci.h"
 
 #define DRIVER_DESC "OHCI generic platform driver"
+#define OHCI_MAX_CLKS 3
+#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
+
+struct ohci_platform_priv {
+	struct clk *clks[OHCI_MAX_CLKS];
+	struct phy *phy;
+};
 
 static const char hcd_name[] = "ohci-platform";
 
@@ -36,10 +47,6 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
 	struct usb_ohci_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
-	if (pdata->big_endian_desc)
-		ohci->flags |= OHCI_QUIRK_BE_DESC;
-	if (pdata->big_endian_mmio)
-		ohci->flags |= OHCI_QUIRK_BE_MMIO;
 	if (pdata->no_big_frame_no)
 		ohci->flags |= OHCI_QUIRK_FRAME_NO;
 	if (pdata->num_ports)
@@ -48,11 +55,67 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
 	return ohci_setup(hcd);
 }
 
+static int ohci_platform_power_on(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+	int clk, ret;
+
+	for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+		ret = clk_prepare_enable(priv->clks[clk]);
+		if (ret)
+			goto err_disable_clks;
+	}
+
+	if (priv->phy) {
+		ret = phy_init(priv->phy);
+		if (ret)
+			goto err_disable_clks;
+
+		ret = phy_power_on(priv->phy);
+		if (ret)
+			goto err_exit_phy;
+	}
+
+	return 0;
+
+err_exit_phy:
+	phy_exit(priv->phy);
+err_disable_clks:
+	while (--clk >= 0)
+		clk_disable_unprepare(priv->clks[clk]);
+
+	return ret;
+}
+
+static void ohci_platform_power_off(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+	int clk;
+
+	if (priv->phy) {
+		phy_power_off(priv->phy);
+		phy_exit(priv->phy);
+	}
+
+	for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
+		if (priv->clks[clk])
+			clk_disable_unprepare(priv->clks[clk]);
+}
+
 static struct hc_driver __read_mostly ohci_platform_hc_driver;
 
 static const struct ohci_driver_overrides platform_overrides __initconst = {
-	.product_desc =	"Generic Platform OHCI controller",
-	.reset =	ohci_platform_reset,
+	.product_desc =		"Generic Platform OHCI controller",
+	.reset =		ohci_platform_reset,
+	.extra_priv_size =	sizeof(struct ohci_platform_priv),
+};
+
+static struct usb_ohci_pdata ohci_platform_defaults = {
+	.power_on =		ohci_platform_power_on,
+	.power_suspend =	ohci_platform_power_off,
+	.power_off =		ohci_platform_power_off,
 };
 
 static int ohci_platform_probe(struct platform_device *dev)
@@ -60,17 +123,24 @@ static int ohci_platform_probe(struct platform_device *dev)
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
 	struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
-	int irq;
-	int err = -ENOMEM;
-
-	if (!pdata) {
-		WARN_ON(1);
-		return -ENODEV;
-	}
+	struct ohci_platform_priv *priv;
+	struct ohci_hcd *ohci;
+	int err, irq, clk = 0;
 
 	if (usb_disabled())
 		return -ENODEV;
 
+	/*
+	 * Use reasonable defaults so platforms don't have to provide these
+	 * with DT probing on ARM.
+	 */
+	if (!pdata)
+		pdata = &ohci_platform_defaults;
+
+	err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
 		dev_err(&dev->dev, "no irq provided");
@@ -83,17 +153,72 @@ static int ohci_platform_probe(struct platform_device *dev)
 		return -ENXIO;
 	}
 
+	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+			dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(dev, hcd);
+	dev->dev.platform_data = pdata;
+	priv = hcd_to_ohci_priv(hcd);
+	ohci = hcd_to_ohci(hcd);
+
+	if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
+		if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+			ohci->flags |= OHCI_QUIRK_BE_MMIO;
+
+		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+			ohci->flags |= OHCI_QUIRK_BE_DESC;
+
+		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+			ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+
+		priv->phy = devm_phy_get(&dev->dev, "usb");
+		if (IS_ERR(priv->phy)) {
+			err = PTR_ERR(priv->phy);
+			if (err == -EPROBE_DEFER)
+				goto err_put_hcd;
+			priv->phy = NULL;
+		}
+
+		for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
+			priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+			if (IS_ERR(priv->clks[clk])) {
+				err = PTR_ERR(priv->clks[clk]);
+				if (err == -EPROBE_DEFER)
+					goto err_put_clks;
+				priv->clks[clk] = NULL;
+				break;
+			}
+		}
+	}
+
+	if (pdata->big_endian_desc)
+		ohci->flags |= OHCI_QUIRK_BE_DESC;
+	if (pdata->big_endian_mmio)
+		ohci->flags |= OHCI_QUIRK_BE_MMIO;
+
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+	if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
+		dev_err(&dev->dev,
+			"Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n");
+		err = -EINVAL;
+		goto err_put_clks;
+	}
+#endif
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
+	if (ohci->flags & OHCI_QUIRK_BE_DESC) {
+		dev_err(&dev->dev,
+			"Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n");
+		err = -EINVAL;
+		goto err_put_clks;
+	}
+#endif
+
 	if (pdata->power_on) {
 		err = pdata->power_on(dev);
 		if (err < 0)
-			return err;
-	}
-
-	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
-			dev_name(&dev->dev));
-	if (!hcd) {
-		err = -ENOMEM;
-		goto err_power;
+			goto err_put_clks;
 	}
 
 	hcd->rsrc_start = res_mem->start;
@@ -102,11 +227,11 @@ static int ohci_platform_probe(struct platform_device *dev)
 	hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
 	if (IS_ERR(hcd->regs)) {
 		err = PTR_ERR(hcd->regs);
-		goto err_put_hcd;
+		goto err_power;
 	}
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err)
-		goto err_put_hcd;
+		goto err_power;
 
 	device_wakeup_enable(hcd->self.controller);
 
@@ -114,11 +239,17 @@ static int ohci_platform_probe(struct platform_device *dev)
 
 	return err;
 
-err_put_hcd:
-	usb_put_hcd(hcd);
 err_power:
 	if (pdata->power_off)
 		pdata->power_off(dev);
+err_put_clks:
+	while (--clk >= 0)
+		clk_put(priv->clks[clk]);
+err_put_hcd:
+	if (pdata == &ohci_platform_defaults)
+		dev->dev.platform_data = NULL;
+
+	usb_put_hcd(hcd);
 
 	return err;
 }
@@ -127,13 +258,22 @@ static int ohci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
+	struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+	int clk;
 
 	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
 
 	if (pdata->power_off)
 		pdata->power_off(dev);
 
+	for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
+		clk_put(priv->clks[clk]);
+
+	usb_put_hcd(hcd);
+
+	if (pdata == &ohci_platform_defaults)
+		dev->dev.platform_data = NULL;
+
 	return 0;
 }
 
@@ -180,6 +320,12 @@ static int ohci_platform_resume(struct device *dev)
 #define ohci_platform_resume	NULL
 #endif /* CONFIG_PM */
 
+static const struct of_device_id ohci_platform_ids[] = {
+	{ .compatible = "generic-ohci", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ohci_platform_ids);
+
 static const struct platform_device_id ohci_platform_table[] = {
 	{ "ohci-platform", 0 },
 	{ }
@@ -200,6 +346,7 @@ static struct platform_driver ohci_platform_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "ohci-platform",
 		.pm	= &ohci_platform_pm_ops,
+		.of_match_table = ohci_platform_ids,
 	}
 };
 
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 44e6c9da8892..01833ab2b5c3 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -148,6 +148,7 @@ static void uhci_hcd_platform_shutdown(struct platform_device *op)
 }
 
 static const struct of_device_id platform_uhci_ids[] = {
+	{ .compatible = "generic-uhci", },
 	{ .compatible = "platform-uhci", },
 	{}
 };
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8abda5c73ca1..8affef910782 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -226,6 +226,7 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
 
 #ifdef CONFIG_OF
 static const struct of_device_id usb_xhci_of_match[] = {
+	{ .compatible = "generic-xhci" },
 	{ .compatible = "xhci-platform" },
 	{ },
 };
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index ba5f70f92888..1bca274dc3b5 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -128,7 +128,6 @@ config USB_IDMOUSE
 
 config USB_FTDI_ELAN
 	tristate "Elan PCMCIA CardBus Adapter USB Client"
-	default M
 	help
 	  ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
 	  Currently only the U132 adapter is available.
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index de98906f786d..06b5d77cd9ad 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2123,8 +2123,8 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
 	u8 tmp8, tmp82, ramtype;
 	int bw = 0;
 	char *ramtypetext1 = NULL;
-	const char *ramtypetext2[] = {	"SDR SDRAM", "SDR SGRAM",
-					"DDR SDRAM", "DDR SGRAM" };
+	static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
+	static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
 	static const int busSDR[4]  = {64, 64, 128, 128};
 	static const int busDDR[4]  = {32, 32,  64,  64};
 	static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
@@ -2156,8 +2156,10 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
 		break;
 	}
 
-	dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1,
-			ramtypetext2[ramtype], bw);
+
+	dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n",
+		 sisusb->vramsize >> 20, ramtypetext1,
+		 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
 }
 
 static int
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 78eb4ff33269..bdef0d6eb91d 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -22,8 +22,27 @@
 enum led_type {
 	DELCOM_VISUAL_SIGNAL_INDICATOR,
 	DREAM_CHEEKY_WEBMAIL_NOTIFIER,
+	RISO_KAGAKU_LED
 };
 
+/* the Webmail LED made by RISO KAGAKU CORP. decodes a color index
+   internally, we want to keep the red+green+blue sysfs api, so we decode
+   from 1-bit RGB to the riso kagaku color index according to this table... */
+
+static unsigned const char riso_kagaku_tbl[] = {
+/* R+2G+4B -> riso kagaku color index */
+	[0] = 0, /* black   */
+	[1] = 2, /* red     */
+	[2] = 1, /* green   */
+	[3] = 5, /* yellow  */
+	[4] = 3, /* blue    */
+	[5] = 6, /* magenta */
+	[6] = 4, /* cyan    */
+	[7] = 7  /* white   */
+};
+
+#define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
+
 /* table of devices that work with this driver */
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0fc5, 0x1223),
@@ -32,6 +51,8 @@ static const struct usb_device_id id_table[] = {
 			.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
 	{ USB_DEVICE(0x1d34, 0x000a),
 			.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
+	{ USB_DEVICE(0x1294, 0x1320),
+			.driver_info = RISO_KAGAKU_LED },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -48,6 +69,7 @@ static void change_color(struct usb_led *led)
 {
 	int retval = 0;
 	unsigned char *buffer;
+	int actlength;
 
 	buffer = kmalloc(8, GFP_KERNEL);
 	if (!buffer) {
@@ -104,6 +126,18 @@ static void change_color(struct usb_led *led)
 					2000);
 		break;
 
+	case RISO_KAGAKU_LED:
+		buffer[0] = RISO_KAGAKU_IX(led->red, led->green, led->blue);
+		buffer[1] = 0;
+		buffer[2] = 0;
+		buffer[3] = 0;
+		buffer[4] = 0;
+
+		retval = usb_interrupt_msg(led->udev,
+			usb_sndctrlpipe(led->udev, 2),
+			buffer, 5, &actlength, 1000 /*ms timeout*/);
+		break;
+
 	default:
 		dev_err(&led->udev->dev, "unknown device type %d\n", led->type);
 	}
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 688dc8bb192d..8b789792f6fa 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -43,6 +43,7 @@ config USB_MUSB_HOST
 config USB_MUSB_GADGET
 	bool "Gadget only mode"
 	depends on USB_GADGET=y || USB_GADGET=USB_MUSB_HDRC
+	depends on HAS_DMA
 	help
 	  Select this when you want to use MUSB in gadget mode only,
 	  thereby the host feature will be regressed.
@@ -50,6 +51,7 @@ config USB_MUSB_GADGET
 config USB_MUSB_DUAL_ROLE
 	bool "Dual Role mode"
 	depends on ((USB=y || USB=USB_MUSB_HDRC) && (USB_GADGET=y || USB_GADGET=USB_MUSB_HDRC))
+	depends on HAS_DMA
 	help
 	  This is the default mode of working of MUSB controller where
 	  both host and gadget features are enabled.
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 239ad0b1ceb6..07576907e2c6 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -438,7 +438,6 @@ void musb_hnp_stop(struct musb *musb)
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 				u8 devctl)
 {
-	struct usb_otg *otg = musb->xceiv->otg;
 	irqreturn_t handled = IRQ_NONE;
 
 	dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,
@@ -656,7 +655,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 				break;
 		case OTG_STATE_B_PERIPHERAL:
 			musb_g_suspend(musb);
-			musb->is_active = otg->gadget->b_hnp_enable;
+			musb->is_active = musb->g.b_hnp_enable;
 			if (musb->is_active) {
 				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
 				dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
@@ -672,7 +671,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			break;
 		case OTG_STATE_A_HOST:
 			musb->xceiv->state = OTG_STATE_A_SUSPEND;
-			musb->is_active = otg->host->b_hnp_enable;
+			musb->is_active = musb->hcd->self.b_hnp_enable;
 			break;
 		case OTG_STATE_B_HOST:
 			/* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index f88929609bac..5b0f2a58f8ce 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -39,6 +39,7 @@ struct cppi41_dma_channel {
 	u32 transferred;
 	u32 packet_sz;
 	struct list_head tx_check;
+	struct work_struct dma_completion;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -112,6 +113,18 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
 	return true;
 }
 
+static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
+{
+	if (in && hw_ep->in_qh) {
+		if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
+			return true;
+	} else if (hw_ep->out_qh) {
+		if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
+			return true;
+	}
+	return false;
+}
+
 static void cppi41_dma_callback(void *private_data);
 
 static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
@@ -165,6 +178,32 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
 	}
 }
 
+static void cppi_trans_done_work(struct work_struct *work)
+{
+	unsigned long flags;
+	struct cppi41_dma_channel *cppi41_channel =
+		container_of(work, struct cppi41_dma_channel, dma_completion);
+	struct cppi41_dma_controller *controller = cppi41_channel->controller;
+	struct musb *musb = controller->musb;
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	bool empty;
+
+	if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
+		spin_lock_irqsave(&musb->lock, flags);
+		cppi41_trans_done(cppi41_channel);
+		spin_unlock_irqrestore(&musb->lock, flags);
+	} else {
+		empty = musb_is_tx_fifo_empty(hw_ep);
+		if (empty) {
+			spin_lock_irqsave(&musb->lock, flags);
+			cppi41_trans_done(cppi41_channel);
+			spin_unlock_irqrestore(&musb->lock, flags);
+		} else {
+			schedule_work(&cppi41_channel->dma_completion);
+		}
+	}
+}
+
 static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
 {
 	struct cppi41_dma_controller *controller;
@@ -228,6 +267,14 @@ static void cppi41_dma_callback(void *private_data)
 			transferred < cppi41_channel->packet_sz)
 		cppi41_channel->prog_len = 0;
 
+	if (!cppi41_channel->is_tx) {
+		if (is_isoc(hw_ep, 1))
+			schedule_work(&cppi41_channel->dma_completion);
+		else
+			cppi41_trans_done(cppi41_channel);
+		goto out;
+	}
+
 	empty = musb_is_tx_fifo_empty(hw_ep);
 	if (empty) {
 		cppi41_trans_done(cppi41_channel);
@@ -264,6 +311,10 @@ static void cppi41_dma_callback(void *private_data)
 				goto out;
 			}
 		}
+		if (is_isoc(hw_ep, 0)) {
+			schedule_work(&cppi41_channel->dma_completion);
+			goto out;
+		}
 		list_add_tail(&cppi41_channel->tx_check,
 				&controller->early_tx_list);
 		if (!hrtimer_active(&controller->early_tx)) {
@@ -448,12 +499,25 @@ static int cppi41_dma_channel_program(struct dma_channel *channel,
 				dma_addr_t dma_addr, u32 len)
 {
 	int ret;
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+	int hb_mult = 0;
 
 	BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
 		channel->status == MUSB_DMA_STATUS_BUSY);
 
+	if (is_host_active(cppi41_channel->controller->musb)) {
+		if (cppi41_channel->is_tx)
+			hb_mult = cppi41_channel->hw_ep->out_qh->hb_mult;
+		else
+			hb_mult = cppi41_channel->hw_ep->in_qh->hb_mult;
+	}
+
 	channel->status = MUSB_DMA_STATUS_BUSY;
 	channel->actual_len = 0;
+
+	if (hb_mult)
+		packet_sz = hb_mult * (packet_sz & 0x7FF);
+
 	ret = cppi41_configure_channel(channel, packet_sz, mode, dma_addr, len);
 	if (!ret)
 		channel->status = MUSB_DMA_STATUS_FREE;
@@ -607,6 +671,8 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
 		cppi41_channel->port_num = port;
 		cppi41_channel->is_tx = is_tx;
 		INIT_LIST_HEAD(&cppi41_channel->tx_check);
+		INIT_WORK(&cppi41_channel->dma_completion,
+			  cppi_trans_done_work);
 
 		musb_dma = &cppi41_channel->channel;
 		musb_dma->private_data = cppi41_channel;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 7a109eae9b9a..3372ded5def7 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -45,6 +45,8 @@
 #include <linux/of_irq.h>
 #include <linux/usb/of.h>
 
+#include <linux/debugfs.h>
+
 #include "musb_core.h"
 
 static const struct of_device_id musb_dsps_of_match[];
@@ -136,6 +138,26 @@ struct dsps_glue {
 	unsigned long last_timer;    /* last timer data for each instance */
 
 	struct dsps_context context;
+	struct debugfs_regset32 regset;
+	struct dentry *dbgfs_root;
+};
+
+static const struct debugfs_reg32 dsps_musb_regs[] = {
+	{ "revision",		0x00 },
+	{ "control",		0x14 },
+	{ "status",		0x18 },
+	{ "eoi",		0x24 },
+	{ "intr0_stat",		0x30 },
+	{ "intr1_stat",		0x34 },
+	{ "intr0_set",		0x38 },
+	{ "intr1_set",		0x3c },
+	{ "txmode",		0x70 },
+	{ "rxmode",		0x74 },
+	{ "autoreq",		0xd0 },
+	{ "srpfixtime",		0xd4 },
+	{ "tdown",		0xd8 },
+	{ "phy_utmi",		0xe0 },
+	{ "mode",		0xe8 },
 };
 
 static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
@@ -368,6 +390,30 @@ out:
 	return ret;
 }
 
+static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
+{
+	struct dentry *root;
+	struct dentry *file;
+	char buf[128];
+
+	sprintf(buf, "%s.dsps", dev_name(musb->controller));
+	root = debugfs_create_dir(buf, NULL);
+	if (!root)
+		return -ENOMEM;
+	glue->dbgfs_root = root;
+
+	glue->regset.regs = dsps_musb_regs;
+	glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs);
+	glue->regset.base = musb->ctrl_base;
+
+	file = debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset);
+	if (!file) {
+		debugfs_remove_recursive(root);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
 static int dsps_musb_init(struct musb *musb)
 {
 	struct device *dev = musb->controller;
@@ -377,6 +423,7 @@ static int dsps_musb_init(struct musb *musb)
 	void __iomem *reg_base;
 	struct resource *r;
 	u32 rev, val;
+	int ret;
 
 	r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
 	if (!r)
@@ -410,6 +457,10 @@ static int dsps_musb_init(struct musb *musb)
 	val &= ~(1 << wrp->otg_disable);
 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 
+	ret = dsps_musb_dbg_init(musb, glue);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -616,7 +667,7 @@ static int dsps_probe(struct platform_device *pdev)
 	wrp = match->data;
 
 	/* allocate glue */
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "unable to allocate glue memory\n");
 		return -ENOMEM;
@@ -644,7 +695,6 @@ err3:
 	pm_runtime_put(&pdev->dev);
 err2:
 	pm_runtime_disable(&pdev->dev);
-	kfree(glue);
 	return ret;
 }
 
@@ -657,7 +707,9 @@ static int dsps_remove(struct platform_device *pdev)
 	/* disable usbss clocks */
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	kfree(glue);
+
+	debugfs_remove_recursive(glue->dbgfs_root);
+
 	return 0;
 }
 
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index abb38c3833ef..eb06291a40c8 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1694,7 +1694,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 			| MUSB_RXCSR_RXPKTRDY);
 		musb_writew(hw_ep->regs, MUSB_RXCSR, val);
 
-#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) || \
+	defined(CONFIG_USB_TI_CPPI41_DMA)
 		if (usb_pipeisoc(pipe)) {
 			struct usb_iso_packet_descriptor *d;
 
@@ -1707,10 +1708,30 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 			if (d->status != -EILSEQ && d->status != -EOVERFLOW)
 				d->status = 0;
 
-			if (++qh->iso_idx >= urb->number_of_packets)
+			if (++qh->iso_idx >= urb->number_of_packets) {
 				done = true;
-			else
+			} else {
+#if defined(CONFIG_USB_TI_CPPI41_DMA)
+				struct dma_controller   *c;
+				dma_addr_t *buf;
+				u32 length, ret;
+
+				c = musb->dma_controller;
+				buf = (void *)
+					urb->iso_frame_desc[qh->iso_idx].offset
+					+ (u32)urb->transfer_dma;
+
+				length =
+					urb->iso_frame_desc[qh->iso_idx].length;
+
+				val |= MUSB_RXCSR_DMAENAB;
+				musb_writew(hw_ep->regs, MUSB_RXCSR, val);
+
+				ret = c->channel_program(dma, qh->maxpacket,
+						0, (u32) buf, length);
+#endif
 				done = false;
+			}
 
 		} else  {
 		/* done if urb buffer is full or short packet is recd */
@@ -1750,7 +1771,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 		}
 
 		/* we are expecting IN packets */
-#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) || \
+	defined(CONFIG_USB_TI_CPPI41_DMA)
 		if (dma) {
 			struct dma_controller	*c;
 			u16			rx_count;
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index d204f745ed05..5b37b81f2ef6 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1428,7 +1428,8 @@ static int __init msm_otg_probe(struct platform_device *pdev)
 	motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
 	if (!motg->phy.otg) {
 		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free_motg;
 	}
 
 	motg->pdata = dev_get_platdata(&pdev->dev);
diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c
index 551e0a6c0e22..388d89f6b141 100644
--- a/drivers/usb/phy/phy-rcar-gen2-usb.c
+++ b/drivers/usb/phy/phy-rcar-gen2-usb.c
@@ -177,15 +177,15 @@ static int rcar_gen2_usb_phy_probe(struct platform_device *pdev)
 	struct clk *clk;
 	int retval;
 
-	pdata = dev_get_platdata(&pdev->dev);
+	pdata = dev_get_platdata(dev);
 	if (!pdata) {
 		dev_err(dev, "No platform data\n");
 		return -EINVAL;
 	}
 
-	clk = devm_clk_get(&pdev->dev, "usbhs");
+	clk = devm_clk_get(dev, "usbhs");
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "Can't get the clock\n");
+		dev_err(dev, "Can't get the clock\n");
 		return PTR_ERR(clk);
 	}
 
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 3b959e83b28e..0677139c6065 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -284,7 +284,7 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc,
 	struct device *dev = wusbhc->dev;
 	struct wusb_dev *wusb_dev;
 	struct wusb_port *port;
-	unsigned idx, devnum;
+	unsigned idx;
 
 	mutex_lock(&wusbhc->mutex);
 
@@ -312,8 +312,6 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc,
 		goto error_unlock;
 	}
 
-	devnum = idx + 2;
-
 	/* Make sure we are using no crypto on that "virtual port" */
 	wusbhc->set_ptk(wusbhc, idx, 0, NULL, 0);
 
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index 6ca80a4efc1b..6d6da127f6de 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -298,7 +298,7 @@ static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find(
 			break;
 		}
 		itr += hdr->bLength;
-		itr_size -= hdr->bDescriptorType;
+		itr_size -= hdr->bLength;
 	}
 out:
 	return epcd;
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3cd96e936d77..404ce81b286c 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -167,6 +167,8 @@ struct wa_xfer {
 
 static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer,
 	struct wa_seg *seg, int curr_iso_frame);
+static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
+		int starting_index, enum wa_seg_status status);
 
 static inline void wa_xfer_init(struct wa_xfer *xfer)
 {
@@ -367,13 +369,13 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
 			break;
 		case WA_SEG_ERROR:
 			xfer->result = seg->result;
-			dev_dbg(dev, "xfer %p ID %08X#%u: ERROR result %zu(0x%08zX)\n",
+			dev_dbg(dev, "xfer %p ID %08X#%u: ERROR result %zi(0x%08zX)\n",
 				xfer, wa_xfer_id(xfer), seg->index, seg->result,
 				seg->result);
 			goto out;
 		case WA_SEG_ABORTED:
 			xfer->result = seg->result;
-			dev_dbg(dev, "xfer %p ID %08X#%u: ABORTED result %zu(0x%08zX)\n",
+			dev_dbg(dev, "xfer %p ID %08X#%u: ABORTED result %zi(0x%08zX)\n",
 				xfer, wa_xfer_id(xfer), seg->index, seg->result,
 				seg->result);
 			goto out;
@@ -390,6 +392,24 @@ out:
 }
 
 /*
+ * Mark the given segment as done.  Return true if this completes the xfer.
+ * This should only be called for segs that have been submitted to an RPIPE.
+ * Delayed segs are not marked as submitted so they do not need to be marked
+ * as done when cleaning up.
+ *
+ * xfer->lock has to be locked
+ */
+static unsigned __wa_xfer_mark_seg_as_done(struct wa_xfer *xfer,
+	struct wa_seg *seg, enum wa_seg_status status)
+{
+	seg->status = status;
+	xfer->segs_done++;
+
+	/* check for done. */
+	return __wa_xfer_is_done(xfer);
+}
+
+/*
  * Search for a transfer list ID on the HCD's URB list
  *
  * For 32 bit architectures, we use the pointer itself; for 64 bits, a
@@ -416,12 +436,51 @@ out:
 
 struct wa_xfer_abort_buffer {
 	struct urb urb;
+	struct wahc *wa;
 	struct wa_xfer_abort cmd;
 };
 
 static void __wa_xfer_abort_cb(struct urb *urb)
 {
 	struct wa_xfer_abort_buffer *b = urb->context;
+	struct wahc *wa = b->wa;
+
+	/*
+	 * If the abort request URB failed, then the HWA did not get the abort
+	 * command.  Forcibly clean up the xfer without waiting for a Transfer
+	 * Result from the HWA.
+	 */
+	if (urb->status < 0) {
+		struct wa_xfer *xfer;
+		struct device *dev = &wa->usb_iface->dev;
+
+		xfer = wa_xfer_get_by_id(wa, le32_to_cpu(b->cmd.dwTransferID));
+		dev_err(dev, "%s: Transfer Abort request failed. result: %d\n",
+			__func__, urb->status);
+		if (xfer) {
+			unsigned long flags;
+			int done;
+			struct wa_rpipe *rpipe = xfer->ep->hcpriv;
+
+			dev_err(dev, "%s: cleaning up xfer %p ID 0x%08X.\n",
+				__func__, xfer, wa_xfer_id(xfer));
+			spin_lock_irqsave(&xfer->lock, flags);
+			/* mark all segs as aborted. */
+			wa_complete_remaining_xfer_segs(xfer, 0,
+				WA_SEG_ABORTED);
+			done = __wa_xfer_is_done(xfer);
+			spin_unlock_irqrestore(&xfer->lock, flags);
+			if (done)
+				wa_xfer_completion(xfer);
+			wa_xfer_delayed_run(rpipe);
+			wa_xfer_put(xfer);
+		} else {
+			dev_err(dev, "%s: xfer ID 0x%08X already gone.\n",
+				 __func__, le32_to_cpu(b->cmd.dwTransferID));
+		}
+	}
+
+	wa_put(wa);	/* taken in __wa_xfer_abort */
 	usb_put_urb(&b->urb);
 }
 
@@ -449,6 +508,7 @@ static int __wa_xfer_abort(struct wa_xfer *xfer)
 	b->cmd.bRequestType = WA_XFER_ABORT;
 	b->cmd.wRPipe = rpipe->descr.wRPipeIndex;
 	b->cmd.dwTransferID = wa_xfer_id_le32(xfer);
+	b->wa = wa_get(xfer->wa);
 
 	usb_init_urb(&b->urb);
 	usb_fill_bulk_urb(&b->urb, xfer->wa->usb_dev,
@@ -462,6 +522,7 @@ static int __wa_xfer_abort(struct wa_xfer *xfer)
 
 
 error_submit:
+	wa_put(xfer->wa);
 	if (printk_ratelimit())
 		dev_err(dev, "xfer %p: Can't submit abort request: %d\n",
 			xfer, result);
@@ -733,6 +794,8 @@ static void wa_seg_dto_cb(struct urb *urb)
 				seg->isoc_frame_offset + seg->isoc_frame_index);
 
 			/* resubmit the URB with the next isoc frame. */
+			/* take a ref on resubmit. */
+			wa_xfer_get(xfer);
 			result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC);
 			if (result < 0) {
 				dev_err(dev, "xfer 0x%08X#%u: DTO submit failed: %d\n",
@@ -760,9 +823,13 @@ static void wa_seg_dto_cb(struct urb *urb)
 		goto error_default;
 	}
 
+	/* taken when this URB was submitted. */
+	wa_xfer_put(xfer);
 	return;
 
 error_dto_submit:
+	/* taken on resubmit attempt. */
+	wa_xfer_put(xfer);
 error_default:
 	spin_lock_irqsave(&xfer->lock, flags);
 	rpipe = xfer->ep->hcpriv;
@@ -772,12 +839,10 @@ error_default:
 		wa_reset_all(wa);
 	}
 	if (seg->status != WA_SEG_ERROR) {
-		seg->status = WA_SEG_ERROR;
 		seg->result = urb->status;
-		xfer->segs_done++;
 		__wa_xfer_abort(xfer);
 		rpipe_ready = rpipe_avail_inc(rpipe);
-		done = __wa_xfer_is_done(xfer);
+		done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR);
 	}
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	if (holding_dto) {
@@ -788,7 +853,8 @@ error_default:
 		wa_xfer_completion(xfer);
 	if (rpipe_ready)
 		wa_xfer_delayed_run(rpipe);
-
+	/* taken when this URB was submitted. */
+	wa_xfer_put(xfer);
 }
 
 /*
@@ -842,12 +908,11 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb)
 		}
 		if (seg->status != WA_SEG_ERROR) {
 			usb_unlink_urb(seg->dto_urb);
-			seg->status = WA_SEG_ERROR;
 			seg->result = urb->status;
-			xfer->segs_done++;
 			__wa_xfer_abort(xfer);
 			rpipe_ready = rpipe_avail_inc(rpipe);
-			done = __wa_xfer_is_done(xfer);
+			done = __wa_xfer_mark_seg_as_done(xfer, seg,
+					WA_SEG_ERROR);
 		}
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		if (done)
@@ -855,6 +920,8 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb)
 		if (rpipe_ready)
 			wa_xfer_delayed_run(rpipe);
 	}
+	/* taken when this URB was submitted. */
+	wa_xfer_put(xfer);
 }
 
 /*
@@ -919,18 +986,18 @@ static void wa_seg_tr_cb(struct urb *urb)
 		}
 		usb_unlink_urb(seg->isoc_pack_desc_urb);
 		usb_unlink_urb(seg->dto_urb);
-		seg->status = WA_SEG_ERROR;
 		seg->result = urb->status;
-		xfer->segs_done++;
 		__wa_xfer_abort(xfer);
 		rpipe_ready = rpipe_avail_inc(rpipe);
-		done = __wa_xfer_is_done(xfer);
+		done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR);
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		if (done)
 			wa_xfer_completion(xfer);
 		if (rpipe_ready)
 			wa_xfer_delayed_run(rpipe);
 	}
+	/* taken when this URB was submitted. */
+	wa_xfer_put(xfer);
 }
 
 /*
@@ -940,7 +1007,7 @@ static void wa_seg_tr_cb(struct urb *urb)
  */
 static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg,
 	const unsigned int bytes_transferred,
-	const unsigned int bytes_to_transfer, unsigned int *out_num_sgs)
+	const unsigned int bytes_to_transfer, int *out_num_sgs)
 {
 	struct scatterlist *out_sg;
 	unsigned int bytes_processed = 0, offset_into_current_page_data = 0,
@@ -1094,14 +1161,13 @@ static int __wa_populate_dto_urb(struct wa_xfer *xfer,
  */
 static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
 {
-	int result, cnt, iso_frame_offset;
+	int result, cnt, isoc_frame_offset = 0;
 	size_t alloc_size = sizeof(*xfer->seg[0])
 		- sizeof(xfer->seg[0]->xfer_hdr) + xfer_hdr_size;
 	struct usb_device *usb_dev = xfer->wa->usb_dev;
 	const struct usb_endpoint_descriptor *dto_epd = xfer->wa->dto_epd;
 	struct wa_seg *seg;
 	size_t buf_itr, buf_size, buf_itr_size;
-	int isoc_frame_offset = 0;
 
 	result = -ENOMEM;
 	xfer->seg = kcalloc(xfer->segs, sizeof(xfer->seg[0]), GFP_ATOMIC);
@@ -1109,7 +1175,6 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
 		goto error_segs_kzalloc;
 	buf_itr = 0;
 	buf_size = xfer->urb->transfer_buffer_length;
-	iso_frame_offset = 0;
 	for (cnt = 0; cnt < xfer->segs; cnt++) {
 		size_t iso_pkt_descr_size = 0;
 		int seg_isoc_frame_count = 0, seg_isoc_size = 0;
@@ -1318,30 +1383,41 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer,
 	/* default to done unless we encounter a multi-frame isoc segment. */
 	*dto_done = 1;
 
+	/*
+	 * Take a ref for each segment urb so the xfer cannot disappear until
+	 * all of the callbacks run.
+	 */
+	wa_xfer_get(xfer);
 	/* submit the transfer request. */
+	seg->status = WA_SEG_SUBMITTED;
 	result = usb_submit_urb(&seg->tr_urb, GFP_ATOMIC);
 	if (result < 0) {
 		pr_err("%s: xfer %p#%u: REQ submit failed: %d\n",
 		       __func__, xfer, seg->index, result);
-		goto error_seg_submit;
+		wa_xfer_put(xfer);
+		goto error_tr_submit;
 	}
 	/* submit the isoc packet descriptor if present. */
 	if (seg->isoc_pack_desc_urb) {
+		wa_xfer_get(xfer);
 		result = usb_submit_urb(seg->isoc_pack_desc_urb, GFP_ATOMIC);
 		seg->isoc_frame_index = 0;
 		if (result < 0) {
 			pr_err("%s: xfer %p#%u: ISO packet descriptor submit failed: %d\n",
 			       __func__, xfer, seg->index, result);
+			wa_xfer_put(xfer);
 			goto error_iso_pack_desc_submit;
 		}
 	}
 	/* submit the out data if this is an out request. */
 	if (seg->dto_urb) {
 		struct wahc *wa = xfer->wa;
+		wa_xfer_get(xfer);
 		result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC);
 		if (result < 0) {
 			pr_err("%s: xfer %p#%u: DTO submit failed: %d\n",
 			       __func__, xfer, seg->index, result);
+			wa_xfer_put(xfer);
 			goto error_dto_submit;
 		}
 		/*
@@ -1353,7 +1429,6 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer,
 			&& (seg->isoc_frame_count > 1))
 			*dto_done = 0;
 	}
-	seg->status = WA_SEG_SUBMITTED;
 	rpipe_avail_dec(rpipe);
 	return 0;
 
@@ -1361,7 +1436,7 @@ error_dto_submit:
 	usb_unlink_urb(seg->isoc_pack_desc_urb);
 error_iso_pack_desc_submit:
 	usb_unlink_urb(&seg->tr_urb);
-error_seg_submit:
+error_tr_submit:
 	seg->status = WA_SEG_ERROR;
 	seg->result = result;
 	*dto_done = 1;
@@ -1393,6 +1468,12 @@ static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, int *dto_waiting)
 				 list_node);
 		list_del(&seg->list_node);
 		xfer = seg->xfer;
+		/*
+		 * Get a reference to the xfer in case the callbacks for the
+		 * URBs submitted by __wa_seg_submit attempt to complete
+		 * the xfer before this function completes.
+		 */
+		wa_xfer_get(xfer);
 		result = __wa_seg_submit(rpipe, xfer, seg, &dto_done);
 		/* release the dto resource if this RPIPE is done with it. */
 		if (dto_done)
@@ -1401,13 +1482,23 @@ static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, int *dto_waiting)
 			xfer, wa_xfer_id(xfer), seg->index,
 			atomic_read(&rpipe->segs_available), result);
 		if (unlikely(result < 0)) {
+			int done;
+
 			spin_unlock_irqrestore(&rpipe->seg_lock, flags);
 			spin_lock_irqsave(&xfer->lock, flags);
 			__wa_xfer_abort(xfer);
+			/*
+			 * This seg was marked as submitted when it was put on
+			 * the RPIPE seg_list.  Mark it done.
+			 */
 			xfer->segs_done++;
+			done = __wa_xfer_is_done(xfer);
 			spin_unlock_irqrestore(&xfer->lock, flags);
+			if (done)
+				wa_xfer_completion(xfer);
 			spin_lock_irqsave(&rpipe->seg_lock, flags);
 		}
+		wa_xfer_put(xfer);
 	}
 	/*
 	 * Mark this RPIPE as waiting if dto was not acquired, there are
@@ -1592,12 +1683,19 @@ static int wa_urb_enqueue_b(struct wa_xfer *xfer)
 		dev_err(&(urb->dev->dev), "%s: error_xfer_setup\n", __func__);
 		goto error_xfer_setup;
 	}
+	/*
+	 * Get a xfer reference since __wa_xfer_submit starts asynchronous
+	 * operations that may try to complete the xfer before this function
+	 * exits.
+	 */
+	wa_xfer_get(xfer);
 	result = __wa_xfer_submit(xfer);
 	if (result < 0) {
 		dev_err(&(urb->dev->dev), "%s: error_xfer_submit\n", __func__);
 		goto error_xfer_submit;
 	}
 	spin_unlock_irqrestore(&xfer->lock, flags);
+	wa_xfer_put(xfer);
 	return 0;
 
 	/*
@@ -1623,6 +1721,7 @@ error_xfer_submit:
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	if (done)
 		wa_xfer_completion(xfer);
+	wa_xfer_put(xfer);
 	/* return success since the completion routine will run. */
 	return 0;
 }
@@ -1832,20 +1931,20 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status)
 	/* check if it is safe to unlink. */
 	spin_lock_irqsave(&wa->xfer_list_lock, flags);
 	result = usb_hcd_check_unlink_urb(&(wa->wusb->usb_hcd), urb, status);
+	if ((result == 0) && urb->hcpriv) {
+		/*
+		 * Get a xfer ref to prevent a race with wa_xfer_giveback
+		 * cleaning up the xfer while we are working with it.
+		 */
+		wa_xfer_get(urb->hcpriv);
+	}
 	spin_unlock_irqrestore(&wa->xfer_list_lock, flags);
 	if (result)
 		return result;
 
 	xfer = urb->hcpriv;
-	if (xfer == NULL) {
-		/*
-		 * Nothing setup yet enqueue will see urb->status !=
-		 * -EINPROGRESS (by hcd layer) and bail out with
-		 * error, no need to do completion
-		 */
-		BUG_ON(urb->status == -EINPROGRESS);
-		goto out;
-	}
+	if (xfer == NULL)
+		return -ENOENT;
 	spin_lock_irqsave(&xfer->lock, flags);
 	pr_debug("%s: DEQUEUE xfer id 0x%08X\n", __func__, wa_xfer_id(xfer));
 	rpipe = xfer->ep->hcpriv;
@@ -1856,6 +1955,16 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status)
 		result = -ENOENT;
 		goto out_unlock;
 	}
+	/*
+	 * Check for done to avoid racing with wa_xfer_giveback and completing
+	 * twice.
+	 */
+	if (__wa_xfer_is_done(xfer)) {
+		pr_debug("%s: xfer %p id 0x%08X already done.\n", __func__,
+			xfer, wa_xfer_id(xfer));
+		result = -ENOENT;
+		goto out_unlock;
+	}
 	/* Check the delayed list -> if there, release and complete */
 	spin_lock_irqsave(&wa->xfer_list_lock, flags2);
 	if (!list_empty(&xfer->list_node) && xfer->seg == NULL)
@@ -1924,11 +2033,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status)
 		wa_xfer_completion(xfer);
 	if (rpipe_ready)
 		wa_xfer_delayed_run(rpipe);
+	wa_xfer_put(xfer);
 	return result;
 
 out_unlock:
 	spin_unlock_irqrestore(&xfer->lock, flags);
-out:
+	wa_xfer_put(xfer);
 	return result;
 
 dequeue_delayed:
@@ -1937,6 +2047,7 @@ dequeue_delayed:
 	xfer->result = urb->status;
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	wa_xfer_giveback(xfer);
+	wa_xfer_put(xfer);
 	usb_put_urb(urb);		/* we got a ref in enqueue() */
 	return 0;
 }
@@ -1996,15 +2107,17 @@ static int wa_xfer_status_to_errno(u8 status)
  * no other segment transfer results will be returned from the device.
  * Mark the remaining submitted or pending xfers as completed so that
  * the xfer will complete cleanly.
+ *
+ * xfer->lock must be held
+ *
  */
 static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
-		struct wa_seg *incoming_seg, enum wa_seg_status status)
+		int starting_index, enum wa_seg_status status)
 {
 	int index;
 	struct wa_rpipe *rpipe = xfer->ep->hcpriv;
 
-	for (index = incoming_seg->index + 1; index < xfer->segs_submitted;
-		index++) {
+	for (index = starting_index; index < xfer->segs_submitted; index++) {
 		struct wa_seg *current_seg = xfer->seg[index];
 
 		BUG_ON(current_seg == NULL);
@@ -2044,7 +2157,7 @@ static void __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
 	wa->buf_in_urb->transfer_dma = xfer->urb->transfer_dma +
 		xfer->urb->iso_frame_desc[curr_iso_frame].offset;
 	wa->buf_in_urb->transfer_buffer_length =
-		xfer->urb->iso_frame_desc[curr_iso_frame].length;
+		xfer->urb->iso_frame_desc[curr_iso_frame].actual_length;
 	wa->buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	wa->buf_in_urb->transfer_buffer = NULL;
 	wa->buf_in_urb->sg = NULL;
@@ -2147,7 +2260,7 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
 	}
 	if (usb_status & 0x80) {
 		seg->result = wa_xfer_status_to_errno(usb_status);
-		dev_err(dev, "DTI: xfer %p#:%08X:%u failed (0x%02x)\n",
+		dev_err(dev, "DTI: xfer %p 0x%08X:#%u failed (0x%02x)\n",
 			xfer, xfer->id, seg->index, usb_status);
 		seg->status = ((usb_status & 0x7F) == WA_XFER_STATUS_ABORTED) ?
 			WA_SEG_ABORTED : WA_SEG_ERROR;
@@ -2162,7 +2275,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
 	 * transfers with data or below for no data, the xfer will complete.
 	 */
 	if (xfer_result->bTransferSegment & 0x80)
-		wa_complete_remaining_xfer_segs(xfer, seg, WA_SEG_DONE);
+		wa_complete_remaining_xfer_segs(xfer, seg->index + 1,
+			WA_SEG_DONE);
 	if (usb_pipeisoc(xfer->urb->pipe)
 		&& (le32_to_cpu(xfer_result->dwNumOfPackets) > 0)) {
 		/* set up WA state to read the isoc packet status next. */
@@ -2182,11 +2296,9 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
 			goto error_submit_buf_in;
 	} else {
 		/* OUT data phase or no data, complete it -- */
-		seg->status = WA_SEG_DONE;
 		seg->result = bytes_transferred;
-		xfer->segs_done++;
 		rpipe_ready = rpipe_avail_inc(rpipe);
-		done = __wa_xfer_is_done(xfer);
+		done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE);
 	}
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	if (done)
@@ -2213,7 +2325,7 @@ error_buf_in_populate:
 error_complete:
 	xfer->segs_done++;
 	rpipe_ready = rpipe_avail_inc(rpipe);
-	wa_complete_remaining_xfer_segs(xfer, seg, seg->status);
+	wa_complete_remaining_xfer_segs(xfer, seg->index + 1, seg->status);
 	done = __wa_xfer_is_done(xfer);
 	/*
 	 * queue work item to clear STALL for control endpoints.
@@ -2350,10 +2462,8 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
 			dti_busy = 1;
 	} else {
 		/* OUT transfer or no more IN data, complete it -- */
-		seg->status = WA_SEG_DONE;
-		xfer->segs_done++;
 		rpipe_ready = rpipe_avail_inc(rpipe);
-		done = __wa_xfer_is_done(xfer);
+		done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE);
 	}
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
@@ -2444,12 +2554,13 @@ static void wa_buf_in_cb(struct urb *urb)
 			}
 		} else {
 			rpipe = xfer->ep->hcpriv;
-			seg->status = WA_SEG_DONE;
-			dev_dbg(dev, "xfer %p#%u: data in done (%zu bytes)\n",
-				xfer, seg->index, seg->result);
-			xfer->segs_done++;
+			dev_dbg(dev,
+				"xfer %p 0x%08X#%u: data in done (%zu bytes)\n",
+				xfer, wa_xfer_id(xfer), seg->index,
+				seg->result);
 			rpipe_ready = rpipe_avail_inc(rpipe);
-			done = __wa_xfer_is_done(xfer);
+			done = __wa_xfer_mark_seg_as_done(xfer, seg,
+					WA_SEG_DONE);
 		}
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		if (done)
@@ -2464,20 +2575,19 @@ static void wa_buf_in_cb(struct urb *urb)
 		spin_lock_irqsave(&xfer->lock, flags);
 		rpipe = xfer->ep->hcpriv;
 		if (printk_ratelimit())
-			dev_err(dev, "xfer %p#%u: data in error %d\n",
-				xfer, seg->index, urb->status);
+			dev_err(dev, "xfer %p 0x%08X#%u: data in error %d\n",
+				xfer, wa_xfer_id(xfer), seg->index,
+				urb->status);
 		if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS,
 			    EDC_ERROR_TIMEFRAME)){
 			dev_err(dev, "DTO: URB max acceptable errors "
 				"exceeded, resetting device\n");
 			wa_reset_all(wa);
 		}
-		seg->status = WA_SEG_ERROR;
 		seg->result = urb->status;
-		xfer->segs_done++;
 		rpipe_ready = rpipe_avail_inc(rpipe);
 		__wa_xfer_abort(xfer);
-		done = __wa_xfer_is_done(xfer);
+		done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR);
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		if (done)
 			wa_xfer_completion(xfer);
@@ -2561,11 +2671,15 @@ static void wa_dti_cb(struct urb *urb)
 					xfer_result->hdr.bNotifyType);
 				break;
 			}
+			xfer_id = le32_to_cpu(xfer_result->dwTransferID);
 			usb_status = xfer_result->bTransferStatus & 0x3f;
-			if (usb_status == WA_XFER_STATUS_NOT_FOUND)
+			if (usb_status == WA_XFER_STATUS_NOT_FOUND) {
 				/* taken care of already */
+				dev_dbg(dev, "%s: xfer 0x%08X#%u not found.\n",
+					__func__, xfer_id,
+					xfer_result->bTransferSegment & 0x7f);
 				break;
-			xfer_id = le32_to_cpu(xfer_result->dwTransferID);
+			}
 			xfer = wa_xfer_get_by_id(wa, xfer_id);
 			if (xfer == NULL) {
 				/* FIXME: transaction not found. */
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 210357691dc0..9dd49c9839ac 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -482,15 +482,19 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
 		for (i = 0; i < nvec; i++)
 			vdev->msix[i].entry = i;
 
-		ret = pci_enable_msix(pdev, vdev->msix, nvec);
-		if (ret) {
+		ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec);
+		if (ret < nvec) {
+			if (ret > 0)
+				pci_disable_msix(pdev);
 			kfree(vdev->msix);
 			kfree(vdev->ctx);
 			return ret;
 		}
 	} else {
-		ret = pci_enable_msi_block(pdev, nvec);
-		if (ret) {
+		ret = pci_enable_msi_range(pdev, 1, nvec);
+		if (ret < nvec) {
+			if (ret > 0)
+				pci_disable_msi(pdev);
 			kfree(vdev->ctx);
 			return ret;
 		}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 21271d8df023..512f479d8a50 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1413,6 +1413,12 @@ int vfio_external_user_iommu_id(struct vfio_group *group)
 }
 EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id);
 
+long vfio_external_check_extension(struct vfio_group *group, unsigned long arg)
+{
+	return vfio_ioctl_check_extension(group->container, arg);
+}
+EXPORT_SYMBOL_GPL(vfio_external_check_extension);
+
 /**
  * Module/class support
  */
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 4fb7a8f83c8a..6673e7be507f 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -30,7 +30,6 @@
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/pci.h>		/* pci_bus_type */
 #include <linux/rbtree.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -55,11 +54,17 @@ MODULE_PARM_DESC(disable_hugepages,
 		 "Disable VFIO IOMMU support for IOMMU hugepages.");
 
 struct vfio_iommu {
-	struct iommu_domain	*domain;
+	struct list_head	domain_list;
 	struct mutex		lock;
 	struct rb_root		dma_list;
+	bool v2;
+};
+
+struct vfio_domain {
+	struct iommu_domain	*domain;
+	struct list_head	next;
 	struct list_head	group_list;
-	bool			cache;
+	int			prot;		/* IOMMU_CACHE */
 };
 
 struct vfio_dma {
@@ -99,7 +104,7 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
 	return NULL;
 }
 
-static void vfio_insert_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
+static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
 {
 	struct rb_node **link = &iommu->dma_list.rb_node, *parent = NULL;
 	struct vfio_dma *dma;
@@ -118,7 +123,7 @@ static void vfio_insert_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
 	rb_insert_color(&new->node, &iommu->dma_list);
 }
 
-static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *old)
+static void vfio_unlink_dma(struct vfio_iommu *iommu, struct vfio_dma *old)
 {
 	rb_erase(&old->node, &iommu->dma_list);
 }
@@ -186,12 +191,12 @@ static bool is_invalid_reserved_pfn(unsigned long pfn)
 	if (pfn_valid(pfn)) {
 		bool reserved;
 		struct page *tail = pfn_to_page(pfn);
-		struct page *head = compound_trans_head(tail);
+		struct page *head = compound_head(tail);
 		reserved = !!(PageReserved(head));
 		if (head != tail) {
 			/*
 			 * "head" is not a dangling pointer
-			 * (compound_trans_head takes care of that)
+			 * (compound_head takes care of that)
 			 * but the hugepage may have been split
 			 * from under us (and we may not hold a
 			 * reference count on the head page so it can
@@ -322,32 +327,39 @@ static long vfio_unpin_pages(unsigned long pfn, long npage,
 	return unlocked;
 }
 
-static int vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
-			    dma_addr_t iova, size_t *size)
+static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
 {
-	dma_addr_t start = iova, end = iova + *size;
+	dma_addr_t iova = dma->iova, end = dma->iova + dma->size;
+	struct vfio_domain *domain, *d;
 	long unlocked = 0;
 
+	if (!dma->size)
+		return;
+	/*
+	 * We use the IOMMU to track the physical addresses, otherwise we'd
+	 * need a much more complicated tracking system.  Unfortunately that
+	 * means we need to use one of the iommu domains to figure out the
+	 * pfns to unpin.  The rest need to be unmapped in advance so we have
+	 * no iommu translations remaining when the pages are unpinned.
+	 */
+	domain = d = list_first_entry(&iommu->domain_list,
+				      struct vfio_domain, next);
+
+	list_for_each_entry_continue(d, &iommu->domain_list, next)
+		iommu_unmap(d->domain, dma->iova, dma->size);
+
 	while (iova < end) {
 		size_t unmapped;
 		phys_addr_t phys;
 
-		/*
-		 * We use the IOMMU to track the physical address.  This
-		 * saves us from having a lot more entries in our mapping
-		 * tree.  The downside is that we don't track the size
-		 * used to do the mapping.  We request unmap of a single
-		 * page, but expect IOMMUs that support large pages to
-		 * unmap a larger chunk.
-		 */
-		phys = iommu_iova_to_phys(iommu->domain, iova);
+		phys = iommu_iova_to_phys(domain->domain, iova);
 		if (WARN_ON(!phys)) {
 			iova += PAGE_SIZE;
 			continue;
 		}
 
-		unmapped = iommu_unmap(iommu->domain, iova, PAGE_SIZE);
-		if (!unmapped)
+		unmapped = iommu_unmap(domain->domain, iova, PAGE_SIZE);
+		if (WARN_ON(!unmapped))
 			break;
 
 		unlocked += vfio_unpin_pages(phys >> PAGE_SHIFT,
@@ -357,119 +369,26 @@ static int vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
 	}
 
 	vfio_lock_acct(-unlocked);
-
-	*size = iova - start;
-
-	return 0;
 }
 
-static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start,
-				   size_t *size, struct vfio_dma *dma)
+static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
 {
-	size_t offset, overlap, tmp;
-	struct vfio_dma *split;
-	int ret;
-
-	if (!*size)
-		return 0;
-
-	/*
-	 * Existing dma region is completely covered, unmap all.  This is
-	 * the likely case since userspace tends to map and unmap buffers
-	 * in one shot rather than multiple mappings within a buffer.
-	 */
-	if (likely(start <= dma->iova &&
-		   start + *size >= dma->iova + dma->size)) {
-		*size = dma->size;
-		ret = vfio_unmap_unpin(iommu, dma, dma->iova, size);
-		if (ret)
-			return ret;
-
-		/*
-		 * Did we remove more than we have?  Should never happen
-		 * since a vfio_dma is contiguous in iova and vaddr.
-		 */
-		WARN_ON(*size != dma->size);
-
-		vfio_remove_dma(iommu, dma);
-		kfree(dma);
-		return 0;
-	}
-
-	/* Overlap low address of existing range */
-	if (start <= dma->iova) {
-		overlap = start + *size - dma->iova;
-		ret = vfio_unmap_unpin(iommu, dma, dma->iova, &overlap);
-		if (ret)
-			return ret;
-
-		vfio_remove_dma(iommu, dma);
-
-		/*
-		 * Check, we may have removed to whole vfio_dma.  If not
-		 * fixup and re-insert.
-		 */
-		if (overlap < dma->size) {
-			dma->iova += overlap;
-			dma->vaddr += overlap;
-			dma->size -= overlap;
-			vfio_insert_dma(iommu, dma);
-		} else
-			kfree(dma);
-
-		*size = overlap;
-		return 0;
-	}
-
-	/* Overlap high address of existing range */
-	if (start + *size >= dma->iova + dma->size) {
-		offset = start - dma->iova;
-		overlap = dma->size - offset;
-
-		ret = vfio_unmap_unpin(iommu, dma, start, &overlap);
-		if (ret)
-			return ret;
-
-		dma->size -= overlap;
-		*size = overlap;
-		return 0;
-	}
-
-	/* Split existing */
-
-	/*
-	 * Allocate our tracking structure early even though it may not
-	 * be used.  An Allocation failure later loses track of pages and
-	 * is more difficult to unwind.
-	 */
-	split = kzalloc(sizeof(*split), GFP_KERNEL);
-	if (!split)
-		return -ENOMEM;
-
-	offset = start - dma->iova;
-
-	ret = vfio_unmap_unpin(iommu, dma, start, size);
-	if (ret || !*size) {
-		kfree(split);
-		return ret;
-	}
-
-	tmp = dma->size;
+	vfio_unmap_unpin(iommu, dma);
+	vfio_unlink_dma(iommu, dma);
+	kfree(dma);
+}
 
-	/* Resize the lower vfio_dma in place, before the below insert */
-	dma->size = offset;
+static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
+{
+	struct vfio_domain *domain;
+	unsigned long bitmap = PAGE_MASK;
 
-	/* Insert new for remainder, assuming it didn't all get unmapped */
-	if (likely(offset + *size < tmp)) {
-		split->size = tmp - offset - *size;
-		split->iova = dma->iova + offset + *size;
-		split->vaddr = dma->vaddr + offset + *size;
-		split->prot = dma->prot;
-		vfio_insert_dma(iommu, split);
-	} else
-		kfree(split);
+	mutex_lock(&iommu->lock);
+	list_for_each_entry(domain, &iommu->domain_list, next)
+		bitmap &= domain->domain->ops->pgsize_bitmap;
+	mutex_unlock(&iommu->lock);
 
-	return 0;
+	return bitmap;
 }
 
 static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
@@ -477,10 +396,10 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
 {
 	uint64_t mask;
 	struct vfio_dma *dma;
-	size_t unmapped = 0, size;
+	size_t unmapped = 0;
 	int ret = 0;
 
-	mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1;
+	mask = ((uint64_t)1 << __ffs(vfio_pgsize_bitmap(iommu))) - 1;
 
 	if (unmap->iova & mask)
 		return -EINVAL;
@@ -491,20 +410,61 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
 
 	mutex_lock(&iommu->lock);
 
+	/*
+	 * vfio-iommu-type1 (v1) - User mappings were coalesced together to
+	 * avoid tracking individual mappings.  This means that the granularity
+	 * of the original mapping was lost and the user was allowed to attempt
+	 * to unmap any range.  Depending on the contiguousness of physical
+	 * memory and page sizes supported by the IOMMU, arbitrary unmaps may
+	 * or may not have worked.  We only guaranteed unmap granularity
+	 * matching the original mapping; even though it was untracked here,
+	 * the original mappings are reflected in IOMMU mappings.  This
+	 * resulted in a couple unusual behaviors.  First, if a range is not
+	 * able to be unmapped, ex. a set of 4k pages that was mapped as a
+	 * 2M hugepage into the IOMMU, the unmap ioctl returns success but with
+	 * a zero sized unmap.  Also, if an unmap request overlaps the first
+	 * address of a hugepage, the IOMMU will unmap the entire hugepage.
+	 * This also returns success and the returned unmap size reflects the
+	 * actual size unmapped.
+	 *
+	 * We attempt to maintain compatibility with this "v1" interface, but
+	 * we take control out of the hands of the IOMMU.  Therefore, an unmap
+	 * request offset from the beginning of the original mapping will
+	 * return success with zero sized unmap.  And an unmap request covering
+	 * the first iova of mapping will unmap the entire range.
+	 *
+	 * The v2 version of this interface intends to be more deterministic.
+	 * Unmap requests must fully cover previous mappings.  Multiple
+	 * mappings may still be unmaped by specifying large ranges, but there
+	 * must not be any previous mappings bisected by the range.  An error
+	 * will be returned if these conditions are not met.  The v2 interface
+	 * will only return success and a size of zero if there were no
+	 * mappings within the range.
+	 */
+	if (iommu->v2) {
+		dma = vfio_find_dma(iommu, unmap->iova, 0);
+		if (dma && dma->iova != unmap->iova) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
+		if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+	}
+
 	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
-		size = unmap->size;
-		ret = vfio_remove_dma_overlap(iommu, unmap->iova, &size, dma);
-		if (ret || !size)
+		if (!iommu->v2 && unmap->iova > dma->iova)
 			break;
-		unmapped += size;
+		unmapped += dma->size;
+		vfio_remove_dma(iommu, dma);
 	}
 
+unlock:
 	mutex_unlock(&iommu->lock);
 
-	/*
-	 * We may unmap more than requested, update the unmap struct so
-	 * userspace can know.
-	 */
+	/* Report how much was unmapped */
 	unmap->size = unmapped;
 
 	return ret;
@@ -516,22 +476,47 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
  * soon, so this is just a temporary workaround to break mappings down into
  * PAGE_SIZE.  Better to map smaller pages than nothing.
  */
-static int map_try_harder(struct vfio_iommu *iommu, dma_addr_t iova,
+static int map_try_harder(struct vfio_domain *domain, dma_addr_t iova,
 			  unsigned long pfn, long npage, int prot)
 {
 	long i;
 	int ret;
 
 	for (i = 0; i < npage; i++, pfn++, iova += PAGE_SIZE) {
-		ret = iommu_map(iommu->domain, iova,
+		ret = iommu_map(domain->domain, iova,
 				(phys_addr_t)pfn << PAGE_SHIFT,
-				PAGE_SIZE, prot);
+				PAGE_SIZE, prot | domain->prot);
 		if (ret)
 			break;
 	}
 
 	for (; i < npage && i > 0; i--, iova -= PAGE_SIZE)
-		iommu_unmap(iommu->domain, iova, PAGE_SIZE);
+		iommu_unmap(domain->domain, iova, PAGE_SIZE);
+
+	return ret;
+}
+
+static int vfio_iommu_map(struct vfio_iommu *iommu, dma_addr_t iova,
+			  unsigned long pfn, long npage, int prot)
+{
+	struct vfio_domain *d;
+	int ret;
+
+	list_for_each_entry(d, &iommu->domain_list, next) {
+		ret = iommu_map(d->domain, iova, (phys_addr_t)pfn << PAGE_SHIFT,
+				npage << PAGE_SHIFT, prot | d->prot);
+		if (ret) {
+			if (ret != -EBUSY ||
+			    map_try_harder(d, iova, pfn, npage, prot))
+				goto unwind;
+		}
+	}
+
+	return 0;
+
+unwind:
+	list_for_each_entry_continue_reverse(d, &iommu->domain_list, next)
+		iommu_unmap(d->domain, iova, npage << PAGE_SHIFT);
 
 	return ret;
 }
@@ -545,12 +530,12 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
 	long npage;
 	int ret = 0, prot = 0;
 	uint64_t mask;
-	struct vfio_dma *dma = NULL;
+	struct vfio_dma *dma;
 	unsigned long pfn;
 
 	end = map->iova + map->size;
 
-	mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1;
+	mask = ((uint64_t)1 << __ffs(vfio_pgsize_bitmap(iommu))) - 1;
 
 	/* READ/WRITE from device perspective */
 	if (map->flags & VFIO_DMA_MAP_FLAG_WRITE)
@@ -561,9 +546,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
 	if (!prot)
 		return -EINVAL; /* No READ/WRITE? */
 
-	if (iommu->cache)
-		prot |= IOMMU_CACHE;
-
 	if (vaddr & mask)
 		return -EINVAL;
 	if (map->iova & mask)
@@ -588,180 +570,257 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
 		return -EEXIST;
 	}
 
-	for (iova = map->iova; iova < end; iova += size, vaddr += size) {
-		long i;
+	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+	if (!dma) {
+		mutex_unlock(&iommu->lock);
+		return -ENOMEM;
+	}
+
+	dma->iova = map->iova;
+	dma->vaddr = map->vaddr;
+	dma->prot = prot;
+
+	/* Insert zero-sized and grow as we map chunks of it */
+	vfio_link_dma(iommu, dma);
 
+	for (iova = map->iova; iova < end; iova += size, vaddr += size) {
 		/* Pin a contiguous chunk of memory */
 		npage = vfio_pin_pages(vaddr, (end - iova) >> PAGE_SHIFT,
 				       prot, &pfn);
 		if (npage <= 0) {
 			WARN_ON(!npage);
 			ret = (int)npage;
-			goto out;
-		}
-
-		/* Verify pages are not already mapped */
-		for (i = 0; i < npage; i++) {
-			if (iommu_iova_to_phys(iommu->domain,
-					       iova + (i << PAGE_SHIFT))) {
-				ret = -EBUSY;
-				goto out_unpin;
-			}
+			break;
 		}
 
-		ret = iommu_map(iommu->domain, iova,
-				(phys_addr_t)pfn << PAGE_SHIFT,
-				npage << PAGE_SHIFT, prot);
+		/* Map it! */
+		ret = vfio_iommu_map(iommu, iova, pfn, npage, prot);
 		if (ret) {
-			if (ret != -EBUSY ||
-			    map_try_harder(iommu, iova, pfn, npage, prot)) {
-				goto out_unpin;
-			}
+			vfio_unpin_pages(pfn, npage, prot, true);
+			break;
 		}
 
 		size = npage << PAGE_SHIFT;
+		dma->size += size;
+	}
 
-		/*
-		 * Check if we abut a region below - nothing below 0.
-		 * This is the most likely case when mapping chunks of
-		 * physically contiguous regions within a virtual address
-		 * range.  Update the abutting entry in place since iova
-		 * doesn't change.
-		 */
-		if (likely(iova)) {
-			struct vfio_dma *tmp;
-			tmp = vfio_find_dma(iommu, iova - 1, 1);
-			if (tmp && tmp->prot == prot &&
-			    tmp->vaddr + tmp->size == vaddr) {
-				tmp->size += size;
-				iova = tmp->iova;
-				size = tmp->size;
-				vaddr = tmp->vaddr;
-				dma = tmp;
-			}
-		}
+	if (ret)
+		vfio_remove_dma(iommu, dma);
 
-		/*
-		 * Check if we abut a region above - nothing above ~0 + 1.
-		 * If we abut above and below, remove and free.  If only
-		 * abut above, remove, modify, reinsert.
-		 */
-		if (likely(iova + size)) {
-			struct vfio_dma *tmp;
-			tmp = vfio_find_dma(iommu, iova + size, 1);
-			if (tmp && tmp->prot == prot &&
-			    tmp->vaddr == vaddr + size) {
-				vfio_remove_dma(iommu, tmp);
-				if (dma) {
-					dma->size += tmp->size;
-					kfree(tmp);
-				} else {
-					size += tmp->size;
-					tmp->size = size;
-					tmp->iova = iova;
-					tmp->vaddr = vaddr;
-					vfio_insert_dma(iommu, tmp);
-					dma = tmp;
-				}
-			}
-		}
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
+static int vfio_bus_type(struct device *dev, void *data)
+{
+	struct bus_type **bus = data;
+
+	if (*bus && *bus != dev->bus)
+		return -EINVAL;
+
+	*bus = dev->bus;
+
+	return 0;
+}
+
+static int vfio_iommu_replay(struct vfio_iommu *iommu,
+			     struct vfio_domain *domain)
+{
+	struct vfio_domain *d;
+	struct rb_node *n;
+	int ret;
+
+	/* Arbitrarily pick the first domain in the list for lookups */
+	d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
+	n = rb_first(&iommu->dma_list);
+
+	/* If there's not a domain, there better not be any mappings */
+	if (WARN_ON(n && !d))
+		return -EINVAL;
+
+	for (; n; n = rb_next(n)) {
+		struct vfio_dma *dma;
+		dma_addr_t iova;
+
+		dma = rb_entry(n, struct vfio_dma, node);
+		iova = dma->iova;
+
+		while (iova < dma->iova + dma->size) {
+			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
+			size_t size;
 
-		if (!dma) {
-			dma = kzalloc(sizeof(*dma), GFP_KERNEL);
-			if (!dma) {
-				iommu_unmap(iommu->domain, iova, size);
-				ret = -ENOMEM;
-				goto out_unpin;
+			if (WARN_ON(!phys)) {
+				iova += PAGE_SIZE;
+				continue;
 			}
 
-			dma->size = size;
-			dma->iova = iova;
-			dma->vaddr = vaddr;
-			dma->prot = prot;
-			vfio_insert_dma(iommu, dma);
-		}
-	}
+			size = PAGE_SIZE;
 
-	WARN_ON(ret);
-	mutex_unlock(&iommu->lock);
-	return ret;
+			while (iova + size < dma->iova + dma->size &&
+			       phys + size == iommu_iova_to_phys(d->domain,
+								 iova + size))
+				size += PAGE_SIZE;
 
-out_unpin:
-	vfio_unpin_pages(pfn, npage, prot, true);
+			ret = iommu_map(domain->domain, iova, phys,
+					size, dma->prot | domain->prot);
+			if (ret)
+				return ret;
 
-out:
-	iova = map->iova;
-	size = map->size;
-	while ((dma = vfio_find_dma(iommu, iova, size))) {
-		int r = vfio_remove_dma_overlap(iommu, iova,
-						&size, dma);
-		if (WARN_ON(r || !size))
-			break;
+			iova += size;
+		}
 	}
 
-	mutex_unlock(&iommu->lock);
-	return ret;
+	return 0;
 }
 
 static int vfio_iommu_type1_attach_group(void *iommu_data,
 					 struct iommu_group *iommu_group)
 {
 	struct vfio_iommu *iommu = iommu_data;
-	struct vfio_group *group, *tmp;
+	struct vfio_group *group, *g;
+	struct vfio_domain *domain, *d;
+	struct bus_type *bus = NULL;
 	int ret;
 
-	group = kzalloc(sizeof(*group), GFP_KERNEL);
-	if (!group)
-		return -ENOMEM;
-
 	mutex_lock(&iommu->lock);
 
-	list_for_each_entry(tmp, &iommu->group_list, next) {
-		if (tmp->iommu_group == iommu_group) {
+	list_for_each_entry(d, &iommu->domain_list, next) {
+		list_for_each_entry(g, &d->group_list, next) {
+			if (g->iommu_group != iommu_group)
+				continue;
+
 			mutex_unlock(&iommu->lock);
-			kfree(group);
 			return -EINVAL;
 		}
 	}
 
+	group = kzalloc(sizeof(*group), GFP_KERNEL);
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!group || !domain) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	group->iommu_group = iommu_group;
+
+	/* Determine bus_type in order to allocate a domain */
+	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
+	if (ret)
+		goto out_free;
+
+	domain->domain = iommu_domain_alloc(bus);
+	if (!domain->domain) {
+		ret = -EIO;
+		goto out_free;
+	}
+
+	ret = iommu_attach_group(domain->domain, iommu_group);
+	if (ret)
+		goto out_domain;
+
+	INIT_LIST_HEAD(&domain->group_list);
+	list_add(&group->next, &domain->group_list);
+
+	if (!allow_unsafe_interrupts &&
+	    !iommu_domain_has_cap(domain->domain, IOMMU_CAP_INTR_REMAP)) {
+		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
+		       __func__);
+		ret = -EPERM;
+		goto out_detach;
+	}
+
+	if (iommu_domain_has_cap(domain->domain, IOMMU_CAP_CACHE_COHERENCY))
+		domain->prot |= IOMMU_CACHE;
+
 	/*
-	 * TODO: Domain have capabilities that might change as we add
-	 * groups (see iommu->cache, currently never set).  Check for
-	 * them and potentially disallow groups to be attached when it
-	 * would change capabilities (ugh).
+	 * Try to match an existing compatible domain.  We don't want to
+	 * preclude an IOMMU driver supporting multiple bus_types and being
+	 * able to include different bus_types in the same IOMMU domain, so
+	 * we test whether the domains use the same iommu_ops rather than
+	 * testing if they're on the same bus_type.
 	 */
-	ret = iommu_attach_group(iommu->domain, iommu_group);
-	if (ret) {
-		mutex_unlock(&iommu->lock);
-		kfree(group);
-		return ret;
+	list_for_each_entry(d, &iommu->domain_list, next) {
+		if (d->domain->ops == domain->domain->ops &&
+		    d->prot == domain->prot) {
+			iommu_detach_group(domain->domain, iommu_group);
+			if (!iommu_attach_group(d->domain, iommu_group)) {
+				list_add(&group->next, &d->group_list);
+				iommu_domain_free(domain->domain);
+				kfree(domain);
+				mutex_unlock(&iommu->lock);
+				return 0;
+			}
+
+			ret = iommu_attach_group(domain->domain, iommu_group);
+			if (ret)
+				goto out_domain;
+		}
 	}
 
-	group->iommu_group = iommu_group;
-	list_add(&group->next, &iommu->group_list);
+	/* replay mappings on new domains */
+	ret = vfio_iommu_replay(iommu, domain);
+	if (ret)
+		goto out_detach;
+
+	list_add(&domain->next, &iommu->domain_list);
 
 	mutex_unlock(&iommu->lock);
 
 	return 0;
+
+out_detach:
+	iommu_detach_group(domain->domain, iommu_group);
+out_domain:
+	iommu_domain_free(domain->domain);
+out_free:
+	kfree(domain);
+	kfree(group);
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
+static void vfio_iommu_unmap_unpin_all(struct vfio_iommu *iommu)
+{
+	struct rb_node *node;
+
+	while ((node = rb_first(&iommu->dma_list)))
+		vfio_remove_dma(iommu, rb_entry(node, struct vfio_dma, node));
 }
 
 static void vfio_iommu_type1_detach_group(void *iommu_data,
 					  struct iommu_group *iommu_group)
 {
 	struct vfio_iommu *iommu = iommu_data;
+	struct vfio_domain *domain;
 	struct vfio_group *group;
 
 	mutex_lock(&iommu->lock);
 
-	list_for_each_entry(group, &iommu->group_list, next) {
-		if (group->iommu_group == iommu_group) {
-			iommu_detach_group(iommu->domain, iommu_group);
+	list_for_each_entry(domain, &iommu->domain_list, next) {
+		list_for_each_entry(group, &domain->group_list, next) {
+			if (group->iommu_group != iommu_group)
+				continue;
+
+			iommu_detach_group(domain->domain, iommu_group);
 			list_del(&group->next);
 			kfree(group);
-			break;
+			/*
+			 * Group ownership provides privilege, if the group
+			 * list is empty, the domain goes away.  If it's the
+			 * last domain, then all the mappings go away too.
+			 */
+			if (list_empty(&domain->group_list)) {
+				if (list_is_singular(&iommu->domain_list))
+					vfio_iommu_unmap_unpin_all(iommu);
+				iommu_domain_free(domain->domain);
+				list_del(&domain->next);
+				kfree(domain);
+			}
+			goto done;
 		}
 	}
 
+done:
 	mutex_unlock(&iommu->lock);
 }
 
@@ -769,40 +828,17 @@ static void *vfio_iommu_type1_open(unsigned long arg)
 {
 	struct vfio_iommu *iommu;
 
-	if (arg != VFIO_TYPE1_IOMMU)
+	if (arg != VFIO_TYPE1_IOMMU && arg != VFIO_TYPE1v2_IOMMU)
 		return ERR_PTR(-EINVAL);
 
 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
 	if (!iommu)
 		return ERR_PTR(-ENOMEM);
 
-	INIT_LIST_HEAD(&iommu->group_list);
+	INIT_LIST_HEAD(&iommu->domain_list);
 	iommu->dma_list = RB_ROOT;
 	mutex_init(&iommu->lock);
-
-	/*
-	 * Wish we didn't have to know about bus_type here.
-	 */
-	iommu->domain = iommu_domain_alloc(&pci_bus_type);
-	if (!iommu->domain) {
-		kfree(iommu);
-		return ERR_PTR(-EIO);
-	}
-
-	/*
-	 * Wish we could specify required capabilities rather than create
-	 * a domain, see what comes out and hope it doesn't change along
-	 * the way.  Fortunately we know interrupt remapping is global for
-	 * our iommus.
-	 */
-	if (!allow_unsafe_interrupts &&
-	    !iommu_domain_has_cap(iommu->domain, IOMMU_CAP_INTR_REMAP)) {
-		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
-		       __func__);
-		iommu_domain_free(iommu->domain);
-		kfree(iommu);
-		return ERR_PTR(-EPERM);
-	}
+	iommu->v2 = (arg == VFIO_TYPE1v2_IOMMU);
 
 	return iommu;
 }
@@ -810,26 +846,42 @@ static void *vfio_iommu_type1_open(unsigned long arg)
 static void vfio_iommu_type1_release(void *iommu_data)
 {
 	struct vfio_iommu *iommu = iommu_data;
+	struct vfio_domain *domain, *domain_tmp;
 	struct vfio_group *group, *group_tmp;
-	struct rb_node *node;
 
-	list_for_each_entry_safe(group, group_tmp, &iommu->group_list, next) {
-		iommu_detach_group(iommu->domain, group->iommu_group);
-		list_del(&group->next);
-		kfree(group);
+	vfio_iommu_unmap_unpin_all(iommu);
+
+	list_for_each_entry_safe(domain, domain_tmp,
+				 &iommu->domain_list, next) {
+		list_for_each_entry_safe(group, group_tmp,
+					 &domain->group_list, next) {
+			iommu_detach_group(domain->domain, group->iommu_group);
+			list_del(&group->next);
+			kfree(group);
+		}
+		iommu_domain_free(domain->domain);
+		list_del(&domain->next);
+		kfree(domain);
 	}
 
-	while ((node = rb_first(&iommu->dma_list))) {
-		struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
-		size_t size = dma->size;
-		vfio_remove_dma_overlap(iommu, dma->iova, &size, dma);
-		if (WARN_ON(!size))
+	kfree(iommu);
+}
+
+static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
+{
+	struct vfio_domain *domain;
+	int ret = 1;
+
+	mutex_lock(&iommu->lock);
+	list_for_each_entry(domain, &iommu->domain_list, next) {
+		if (!(domain->prot & IOMMU_CACHE)) {
+			ret = 0;
 			break;
+		}
 	}
+	mutex_unlock(&iommu->lock);
 
-	iommu_domain_free(iommu->domain);
-	iommu->domain = NULL;
-	kfree(iommu);
+	return ret;
 }
 
 static long vfio_iommu_type1_ioctl(void *iommu_data,
@@ -841,7 +893,12 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 	if (cmd == VFIO_CHECK_EXTENSION) {
 		switch (arg) {
 		case VFIO_TYPE1_IOMMU:
+		case VFIO_TYPE1v2_IOMMU:
 			return 1;
+		case VFIO_DMA_CC_IOMMU:
+			if (!iommu)
+				return 0;
+			return vfio_domains_have_iommu_cache(iommu);
 		default:
 			return 0;
 		}
@@ -858,7 +915,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 
 		info.flags = 0;
 
-		info.iova_pgsizes = iommu->domain->ops->pgsize_bitmap;
+		info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
 
 		return copy_to_user((void __user *)arg, &info, minsz);
 
@@ -911,9 +968,6 @@ static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = {
 
 static int __init vfio_iommu_type1_init(void)
 {
-	if (!iommu_present(&pci_bus_type))
-		return -ENODEV;
-
 	return vfio_register_iommu_driver(&vfio_iommu_driver_ops_type1);
 }
 
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 dade5b7699bc..70d174090a54 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 "Framebuffer Devices"
+source "drivers/video/fbdev/Kconfig"
+endmenu
+
+source "drivers/video/backlight/Kconfig"
 
 config VGASTATE
        tristate
@@ -39,2491 +47,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_SGIVW
-	tristate "SGI Visual Workstation framebuffer support"
-	depends on FB && X86_VISWS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  SGI Visual Workstation support for framebuffer graphics.
-
-config FB_GBE
-	bool "SGI Graphics Backend frame buffer support"
-	depends on (FB = y) && (SGI_IP32 || X86_VISWS)
-	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
-	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 ae17ddf49a00..94fe9c486c60 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,179 +1,15 @@
-# 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_SGIVW)            += sgivwfb.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/
 
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+
 obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
 ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
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 cd961622f9c1..000000000000
--- a/drivers/video/atmel_lcdfb.c
+++ /dev/null
@@ -1,1447 +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;
-
-	strcpy(info->fix.id, sinfo->pdev->name);
-	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
-	info->pseudo_palette = sinfo->pseudo_palette;
-	info->fbops = &atmel_lcdfb_ops;
-
-	info->fix = atmel_lcdfb_fix;
-
-	/* 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;
-	}
-
-	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 28fafbf864a5..000000000000
--- a/drivers/video/aty/atyfb_base.c
+++ /dev/null
@@ -1,4028 +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 > 1600) || (yres > 1200)) {
-		FAIL("MACH64 chips are designed for max 1600x1200\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;
-
-#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 e45833ce975b..000000000000
--- a/drivers/video/aty/mach64_accel.c
+++ /dev/null
@@ -1,429 +0,0 @@
-
-/*
- *  ATI Mach64 Hardware Acceleration
- */
-
-#include <linux/delay.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, le32_to_cpup(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 95ec042ddbf8..000000000000
--- a/drivers/video/aty/mach64_cursor.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- *  ATI Mach64 CT/VT/GT/LT Cursor Support
- */
-
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/string.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++) {
-			b = *src++;
-			m = *msk++;
-			switch (cursor->rop) {
-			case ROP_XOR:
-			    // Upper 4 bits of mask data
-			    fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++);
-			    // Lower 4 bits of mask
-			    fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f],
-				      dst++);
-			    break;
-			case ROP_COPY:
-			    // Upper 4 bits of mask data
-			    fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++);
-			    // Lower 4 bits of mask
-			    fb_writeb(cursor_bits_lookup[(b & m) & 0x0f],
-				      dst++);
-			    break;
-			}
-		}
-		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/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c
index ee0c0a982e4e..ec5350f2c28a 100644
--- a/drivers/video/backlight/aat2870_bl.c
+++ b/drivers/video/backlight/aat2870_bl.c
@@ -149,8 +149,6 @@ static int aat2870_bl_probe(struct platform_device *pdev)
 				  sizeof(struct aat2870_bl_driver_data),
 				  GFP_KERNEL);
 	if (!aat2870_bl) {
-		dev_err(&pdev->dev,
-			"Failed to allocate memory for aat2870 backlight\n");
 		ret = -ENOMEM;
 		goto out;
 	}
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 9d656717d0f7..be8d83deca7d 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -224,10 +224,8 @@ static int adp8860_led_probe(struct i2c_client *client)
 
 	led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds,
 				GFP_KERNEL);
-	if (led == NULL) {
-		dev_err(&client->dev, "failed to alloc memory\n");
+	if (led == NULL)
 		return -ENOMEM;
-	}
 
 	ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law);
 	ret = adp8860_write(client, ADP8860_ISCT1,
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 63707205326b..251af4d38d86 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -246,10 +246,8 @@ static int adp8870_led_probe(struct i2c_client *client)
 
 	led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led),
 				GFP_KERNEL);
-	if (led == NULL) {
-		dev_err(&client->dev, "failed to alloc memory\n");
+	if (led == NULL)
 		return -ENOMEM;
-	}
 
 	ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
 	if (ret)
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 5d05555fe841..861df0fee11b 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -34,13 +34,15 @@ static const char *const backlight_types[] = {
 			   defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
 /* This callback gets called when something important happens inside a
  * framebuffer driver. We're looking if that important event is blanking,
- * and if it is, we're switching backlight power as well ...
+ * and if it is and necessary, we're switching backlight power as well ...
  */
 static int fb_notifier_callback(struct notifier_block *self,
 				unsigned long event, void *data)
 {
 	struct backlight_device *bd;
 	struct fb_event *evdata = data;
+	int node = evdata->info->node;
+	int fb_blank = 0;
 
 	/* If we aren't interested in this event, skip it immediately ... */
 	if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
@@ -51,12 +53,24 @@ static int fb_notifier_callback(struct notifier_block *self,
 	if (bd->ops)
 		if (!bd->ops->check_fb ||
 		    bd->ops->check_fb(bd, evdata->info)) {
-			bd->props.fb_blank = *(int *)evdata->data;
-			if (bd->props.fb_blank == FB_BLANK_UNBLANK)
-				bd->props.state &= ~BL_CORE_FBBLANK;
-			else
-				bd->props.state |= BL_CORE_FBBLANK;
-			backlight_update_status(bd);
+			fb_blank = *(int *)evdata->data;
+			if (fb_blank == FB_BLANK_UNBLANK &&
+			    !bd->fb_bl_on[node]) {
+				bd->fb_bl_on[node] = true;
+				if (!bd->use_count++) {
+					bd->props.state &= ~BL_CORE_FBBLANK;
+					bd->props.fb_blank = FB_BLANK_UNBLANK;
+					backlight_update_status(bd);
+				}
+			} else if (fb_blank != FB_BLANK_UNBLANK &&
+				   bd->fb_bl_on[node]) {
+				bd->fb_bl_on[node] = false;
+				if (!(--bd->use_count)) {
+					bd->props.state |= BL_CORE_FBBLANK;
+					bd->props.fb_blank = fb_blank;
+					backlight_update_status(bd);
+				}
+			}
 		}
 	mutex_unlock(&bd->ops_lock);
 	return 0;
@@ -175,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/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index db8db5fa6583..51d18d637e2b 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -543,10 +543,8 @@ static int corgi_lcd_probe(struct spi_device *spi)
 	}
 
 	lcd = devm_kzalloc(&spi->dev, sizeof(struct corgi_lcd), GFP_KERNEL);
-	if (!lcd) {
-		dev_err(&spi->dev, "failed to allocate memory\n");
+	if (!lcd)
 		return -ENOMEM;
-	}
 
 	lcd->spi_dev = spi;
 
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
index 985e854e244b..23f50b92a930 100644
--- a/drivers/video/backlight/hx8357.c
+++ b/drivers/video/backlight/hx8357.c
@@ -587,10 +587,8 @@ static int hx8357_probe(struct spi_device *spi)
 	int i, ret;
 
 	lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
-	if (!lcd) {
-		dev_err(&spi->dev, "Couldn't allocate lcd internal structure!\n");
+	if (!lcd)
 		return -ENOMEM;
-	}
 
 	ret = spi_setup(spi);
 	if (ret < 0) {
diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c
index 73464e4b4c74..ea67fe199e34 100644
--- a/drivers/video/backlight/ili922x.c
+++ b/drivers/video/backlight/ili922x.c
@@ -482,10 +482,8 @@ static int ili922x_probe(struct spi_device *spi)
 	u16 reg = 0;
 
 	ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL);
-	if (!ili) {
-		dev_err(&spi->dev, "cannot alloc priv data\n");
+	if (!ili)
 		return -ENOMEM;
-	}
 
 	ili->spi = spi;
 	spi_set_drvdata(spi, ili);
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index e2b8b40a9bd9..2cf39e6d519d 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -219,10 +219,8 @@ int ili9320_probe_spi(struct spi_device *spi,
 	/* allocate and initialse our state */
 
 	ili = devm_kzalloc(&spi->dev, sizeof(struct ili9320), GFP_KERNEL);
-	if (ili == NULL) {
-		dev_err(dev, "no memory for device\n");
+	if (ili == NULL)
 		return -ENOMEM;
-	}
 
 	ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
 
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 63e763828e0e..5fa2649c9631 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -181,11 +181,8 @@ static int l4f00242t03_probe(struct spi_device *spi)
 
 	priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
 				GFP_KERNEL);
-
-	if (priv == NULL) {
-		dev_err(&spi->dev, "No memory for this device.\n");
+	if (priv == NULL)
 		return -ENOMEM;
-	}
 
 	spi_set_drvdata(spi, priv);
 	spi->bits_per_word = 9;
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 187d1c283c1d..cff1fbe89a1b 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -296,11 +296,8 @@ static int lm3533_bl_probe(struct platform_device *pdev)
 	}
 
 	bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
-	if (!bl) {
-		dev_err(&pdev->dev,
-				"failed to allocate memory for backlight\n");
+	if (!bl)
 		return -ENOMEM;
-	}
 
 	bl->lm3533 = lm3533;
 	bl->id = pdev->id;
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index de8832504f68..14590c54aedf 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -168,10 +168,8 @@ static int lms283gf05_probe(struct spi_device *spi)
 
 	st = devm_kzalloc(&spi->dev, sizeof(struct lms283gf05_state),
 				GFP_KERNEL);
-	if (st == NULL) {
-		dev_err(&spi->dev, "No memory for device state\n");
+	if (st == NULL)
 		return -ENOMEM;
-	}
 
 	ld = devm_lcd_device_register(&spi->dev, "lms283gf05", &spi->dev, st,
 					&lms_ops);
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index d01884d4f1bf..c3d2e209fc8f 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -94,10 +94,8 @@ static int platform_lcd_probe(struct platform_device *pdev)
 
 	plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd),
 			    GFP_KERNEL);
-	if (!plcd) {
-		dev_err(dev, "no memory for state\n");
+	if (!plcd)
 		return -ENOMEM;
-	}
 
 	plcd->us = dev;
 	plcd->pdata = pdata;
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index cbba37e6836e..595dcf561020 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -200,7 +200,6 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
-		dev_err(&pdev->dev, "failed to allocate platform data\n");
 		err = ERR_PTR(-ENOMEM);
 		goto err;
 	}
@@ -296,10 +295,8 @@ static int tps65217_bl_probe(struct platform_device *pdev)
 
 	tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
 				GFP_KERNEL);
-	if (tps65217_bl == NULL) {
-		dev_err(&pdev->dev, "allocation of struct tps65217_bl failed\n");
+	if (tps65217_bl == NULL)
 		return -ENOMEM;
-	}
 
 	tps65217_bl->tps = tps;
 	tps65217_bl->dev = &pdev->dev;
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 bb5a96b1645d..000000000000
--- a/drivers/video/cfbcopyarea.c
+++ /dev/null
@@ -1,431 +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, int dst_idx,
-		const unsigned long __iomem *src, int src_idx, int bits,
-		unsigned n, u32 bswapmask)
-{
-	unsigned long first, last;
-	int const shift = dst_idx-src_idx;
-	int left, right;
-
-	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;
-
-		right = shift & (bits - 1);
-		left = -shift & (bits - 1);
-		bswapmask &= shift;
-
-		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 >>= right;
-			} else if (src_idx+n <= bits) {
-				// 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), 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 >>= right;
-				dst++;
-				n -= bits - dst_idx;
-			} else {
-				// 2 source words
-				d1 = FB_READL(src++);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-
-				d0 = d0<<left | d1>>right;
-				dst++;
-				n -= bits - dst_idx;
-			}
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
-			d0 = d1;
-
-			// 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 (last) {
-				if (m <= right) {
-					// 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);
-			}
-		}
-	}
-}
-
-    /*
-     *  Generic bitwise copy algorithm, operating backward
-     */
-
-static void
-bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
-		const unsigned long __iomem *src, int src_idx, int bits,
-		unsigned n, u32 bswapmask)
-{
-	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_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask);
-	last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits),
-					    bswapmask);
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if ((unsigned long)dst_idx+1 >= n) {
-			// 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 -= 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)
-				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);
-		bswapmask &= shift;
-
-		if ((unsigned long)dst_idx+1 >= n) {
-			// Single destination word
-			if (last)
-				first &= last;
-			d0 = FB_READL(src);
-			if (shift < 0) {
-				// Single source word
-				d0 <<= left;
-			} else if (1+(unsigned long)src_idx >= n) {
-				// 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;
-			} 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), 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 >> 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 (last) {
-				if (m <= left) {
-					// 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);
-			}
-		}
-	}
-}
-
-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 *dst = NULL, *src = NULL;
-	int bits = BITS_PER_LONG, bytes = bits >> 3;
-	int 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
-	dst = src = (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;
-			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, bswapmask);
-		}
-	} 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, 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/fbcon.c b/drivers/video/console/fbcon.c
index 4e39291ac8b4..f447734b09b4 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -759,7 +759,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
 		  newinfo in an undefined state. Thus, a call to
 		  fb_set_par() may be needed for the newinfo.
 		*/
-		if (newinfo->fbops->fb_set_par) {
+		if (newinfo && newinfo->fbops->fb_set_par) {
 			ret = newinfo->fbops->fb_set_par(newinfo);
 
 			if (ret)
@@ -3028,8 +3028,31 @@ static int fbcon_fb_unbind(int idx)
 			if (con2fb_map[i] == idx)
 				set_con2fb_map(i, new_idx, 0);
 		}
-	} else
+	} else {
+		struct fb_info *info = registered_fb[idx];
+
+		/* This is sort of like set_con2fb_map, except it maps
+		 * the consoles to no device and then releases the
+		 * oldinfo to free memory and cancel the cursor blink
+		 * timer. I can imagine this just becoming part of
+		 * set_con2fb_map where new_idx is -1
+		 */
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			if (con2fb_map[i] == idx) {
+				con2fb_map[i] = -1;
+				if (!search_fb_in_map(idx)) {
+					ret = con2fb_release_oldinfo(vc_cons[i].d,
+								     info, NULL, i,
+								     idx, 0);
+					if (ret) {
+						con2fb_map[i] = idx;
+						return ret;
+					}
+				}
+			}
+		}
 		ret = fbcon_unbind();
+	}
 
 	return ret;
 }
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 a1d74dd11988..000000000000
--- a/drivers/video/da8xx-fb.c
+++ /dev/null
@@ -1,1669 +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
-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 platform_device *dev, pm_message_t state)
-{
-	struct fb_info *info = platform_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->dev);
-	console_unlock();
-
-	return 0;
-}
-static int fb_resume(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct da8xx_fb_par *par = info->par;
-
-	console_lock();
-	pm_runtime_get_sync(&dev->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;
-}
-#else
-#define fb_suspend NULL
-#define fb_resume NULL
-#endif
-
-static struct platform_driver da8xx_fb_driver = {
-	.probe = fb_probe,
-	.remove = fb_remove,
-	.suspend = fb_suspend,
-	.resume = fb_resume,
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .owner = THIS_MODULE,
-		   },
-};
-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 cd7c0df9f24b..000000000000
--- a/drivers/video/efifb.c
+++ /dev/null
@@ -1,349 +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);
-	framebuffer_release(info);
-}
-
-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;
-	}
-	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 struct platform_driver efifb_driver = {
-	.driver = {
-		.name = "efi-framebuffer",
-		.owner = THIS_MODULE,
-	},
-	.probe = efifb_probe,
-};
-
-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 75c8a8e7efc0..000000000000
--- a/drivers/video/exynos/Kconfig
+++ /dev/null
@@ -1,39 +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.
-
-config EXYNOS_DP
-	bool "EXYNOS DP driver support"
-	depends on OF && ARCH_EXYNOS
-	default n
-	help
-	  This enables support for DP device.
-
-endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
deleted file mode 100644
index ec7772e452a9..000000000000
--- a/drivers/video/exynos/Makefile
+++ /dev/null
@@ -1,8 +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
-obj-$(CONFIG_EXYNOS_DP)			+= exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
deleted file mode 100644
index 5e1a71580051..000000000000
--- a/drivers/video/exynos/exynos_dp_core.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Samsung SoC DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.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/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-
-#include "exynos_dp_core.h"
-
-static int exynos_dp_init_dp(struct exynos_dp_device *dp)
-{
-	exynos_dp_reset(dp);
-
-	exynos_dp_swreset(dp);
-
-	exynos_dp_init_analog_param(dp);
-	exynos_dp_init_interrupt(dp);
-
-	/* SW defined function Normal operation */
-	exynos_dp_enable_sw_function(dp);
-
-	exynos_dp_config_interrupt(dp);
-	exynos_dp_init_analog_func(dp);
-
-	exynos_dp_init_hpd(dp);
-	exynos_dp_init_aux(dp);
-
-	return 0;
-}
-
-static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
-{
-	int timeout_loop = 0;
-
-	while (exynos_dp_get_plug_in_status(dp) != 0) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "failed to get hpd plug status\n");
-			return -ETIMEDOUT;
-		}
-		usleep_range(10, 11);
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-	int i;
-	unsigned char sum = 0;
-
-	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-		sum = sum + edid_data[i];
-
-	return sum;
-}
-
-static int exynos_dp_read_edid(struct exynos_dp_device *dp)
-{
-	unsigned char edid[EDID_BLOCK_LENGTH * 2];
-	unsigned int extend_block = 0;
-	unsigned char sum;
-	unsigned char test_vector;
-	int retval;
-
-	/*
-	 * EDID device address is 0x50.
-	 * However, if necessary, you must have set upper address
-	 * into E-EDID in I2C device, 0x30.
-	 */
-
-	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
-	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-				EDID_EXTENSION_FLAG,
-				&extend_block);
-	if (retval)
-		return retval;
-
-	if (extend_block > 0) {
-		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-						EDID_HEADER_PATTERN,
-						EDID_BLOCK_LENGTH,
-						&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		/* Read additional EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_BLOCK_LENGTH,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_BLOCK_LENGTH]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
-					&test_vector);
-		if (test_vector & DPCD_TEST_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_EDID_CHECKSUM,
-				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_RESPONSE,
-				DPCD_TEST_EDID_CHECKSUM_WRITE);
-		}
-	} else {
-		dev_info(dp->dev, "EDID data does not include any extensions.\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_HEADER_PATTERN,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TEST_REQUEST,
-			&test_vector);
-		if (test_vector & DPCD_TEST_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_EDID_CHECKSUM,
-				edid[EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_RESPONSE,
-				DPCD_TEST_EDID_CHECKSUM_WRITE);
-		}
-	}
-
-	dev_err(dp->dev, "EDID Read success!\n");
-	return 0;
-}
-
-static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
-{
-	u8 buf[12];
-	int i;
-	int retval;
-
-	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
-				12, buf);
-	if (retval)
-		return retval;
-
-	/* Read EDID */
-	for (i = 0; i < 3; i++) {
-		retval = exynos_dp_read_edid(dp);
-		if (!retval)
-			break;
-	}
-
-	return retval;
-}
-
-static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
-						bool enable)
-{
-	u8 data;
-
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
-
-	if (enable)
-		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-			DPCD_ENHANCED_FRAME_EN |
-			DPCD_LANE_COUNT_SET(data));
-	else
-		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-			DPCD_LANE_COUNT_SET(data));
-}
-
-static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
-{
-	u8 data;
-	int retval;
-
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-	retval = DPCD_ENHANCED_FRAME_CAP(data);
-
-	return retval;
-}
-
-static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
-{
-	u8 data;
-
-	data = exynos_dp_is_enhanced_mode_available(dp);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
-	exynos_dp_enable_enhanced_mode(dp, data);
-}
-
-static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
-{
-	exynos_dp_set_training_pattern(dp, DP_NONE);
-
-	exynos_dp_write_byte_to_dpcd(dp,
-		DPCD_ADDR_TRAINING_PATTERN_SET,
-		DPCD_TRAINING_PATTERN_DISABLED);
-}
-
-static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
-					int pre_emphasis, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
-		break;
-	case 1:
-		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
-		break;
-	}
-}
-
-static int exynos_dp_link_start(struct exynos_dp_device *dp)
-{
-	u8 buf[4];
-	int lane, lane_count, pll_tries, retval;
-
-	lane_count = dp->link_train.lane_count;
-
-	dp->link_train.lt_state = CLOCK_RECOVERY;
-	dp->link_train.eq_loop = 0;
-
-	for (lane = 0; lane < lane_count; lane++)
-		dp->link_train.cr_loop[lane] = 0;
-
-	/* Set link rate and count as you want to establish*/
-	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
-	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
-
-	/* Setup RX configuration */
-	buf[0] = dp->link_train.link_rate;
-	buf[1] = dp->link_train.lane_count;
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
-				2, buf);
-	if (retval)
-		return retval;
-
-	/* Set TX pre-emphasis to minimum */
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_lane_pre_emphasis(dp,
-			PRE_EMPHASIS_LEVEL_0, lane);
-
-	/* Wait for PLL lock */
-	pll_tries = 0;
-	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
-			dev_err(dp->dev, "Wait for PLL lock timed out\n");
-			return -ETIMEDOUT;
-		}
-
-		pll_tries++;
-		usleep_range(90, 120);
-	}
-
-	/* Set training pattern 1 */
-	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
-
-	/* Set RX training pattern */
-	retval = exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
-	if (retval)
-		return retval;
-
-	for (lane = 0; lane < lane_count; lane++)
-		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
-			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count, buf);
-
-	return retval;
-}
-
-static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = link_status[lane>>1];
-
-	return (link_value >> shift) & 0xf;
-}
-
-static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
-				int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
-		return -EINVAL;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		lane_status &= DPCD_CHANNEL_EQ_BITS;
-		if (lane_status != DPCD_CHANNEL_EQ_BITS)
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
-							int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return (link_value >> shift) & 0x3;
-}
-
-static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
-					u8 adjust_request[2],
-					int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return ((link_value >> shift) & 0xc) >> 2;
-}
-
-static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
-					u8 training_lane_set, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_link_training(dp, training_lane_set);
-		break;
-	case 1:
-		exynos_dp_set_lane1_link_training(dp, training_lane_set);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_link_training(dp, training_lane_set);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_link_training(dp, training_lane_set);
-		break;
-	}
-}
-
-static unsigned int exynos_dp_get_lane_link_training(
-				struct exynos_dp_device *dp,
-				int lane)
-{
-	u32 reg;
-
-	switch (lane) {
-	case 0:
-		reg = exynos_dp_get_lane0_link_training(dp);
-		break;
-	case 1:
-		reg = exynos_dp_get_lane1_link_training(dp);
-		break;
-	case 2:
-		reg = exynos_dp_get_lane2_link_training(dp);
-		break;
-	case 3:
-		reg = exynos_dp_get_lane3_link_training(dp);
-		break;
-	default:
-		WARN_ON(1);
-		return 0;
-	}
-
-	return reg;
-}
-
-static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
-{
-	exynos_dp_training_pattern_dis(dp);
-	exynos_dp_set_enhanced_mode(dp);
-
-	dp->link_train.lt_state = FAILED;
-}
-
-static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
-					u8 adjust_request[2])
-{
-	int lane, lane_count;
-	u8 voltage_swing, pre_emphasis, training_lane;
-
-	lane_count = dp->link_train.lane_count;
-	for (lane = 0; lane < lane_count; lane++) {
-		voltage_swing = exynos_dp_get_adjust_request_voltage(
-						adjust_request, lane);
-		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-						adjust_request, lane);
-		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-		if (voltage_swing == VOLTAGE_LEVEL_3)
-			training_lane |= DPCD_MAX_SWING_REACHED;
-		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-
-		dp->link_train.training_lane[lane] = training_lane;
-	}
-}
-
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u8 voltage_swing, pre_emphasis, training_lane;
-	u8 link_status[2], adjust_request[2];
-
-	usleep_range(100, 101);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-		/* set training pattern 2 for EQ */
-		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
-
-		retval = exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TRAINING_PATTERN_SET,
-				DPCD_SCRAMBLING_DISABLED |
-				DPCD_TRAINING_PATTERN_2);
-		if (retval)
-			return retval;
-
-		dev_info(dp->dev, "Link Training Clock Recovery success\n");
-		dp->link_train.lt_state = EQUALIZER_TRAINING;
-	} else {
-		for (lane = 0; lane < lane_count; lane++) {
-			training_lane = exynos_dp_get_lane_link_training(
-							dp, lane);
-			voltage_swing = exynos_dp_get_adjust_request_voltage(
-							adjust_request, lane);
-			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-							adjust_request, lane);
-
-			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
-					voltage_swing &&
-			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
-					pre_emphasis)
-				dp->link_train.cr_loop[lane]++;
-
-			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
-			    voltage_swing == VOLTAGE_LEVEL_3 ||
-			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
-					dp->link_train.cr_loop[lane],
-					voltage_swing, pre_emphasis);
-				exynos_dp_reduce_link_rate(dp);
-				return -EIO;
-			}
-		}
-	}
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
-			dp->link_train.training_lane);
-	if (retval)
-		return retval;
-
-	return retval;
-}
-
-static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u32 reg;
-	u8 link_align, link_status[2], adjust_request[2];
-
-	usleep_range(400, 401);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	retval = exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
-	if (retval)
-		return retval;
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
-		/* traing pattern Set to Normal */
-		exynos_dp_training_pattern_dis(dp);
-
-		dev_info(dp->dev, "Link Training success!\n");
-
-		exynos_dp_get_link_bandwidth(dp, &reg);
-		dp->link_train.link_rate = reg;
-		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-			dp->link_train.link_rate);
-
-		exynos_dp_get_lane_count(dp, &reg);
-		dp->link_train.lane_count = reg;
-		dev_dbg(dp->dev, "final lane count = %.2x\n",
-			dp->link_train.lane_count);
-
-		/* set enhanced mode if available */
-		exynos_dp_set_enhanced_mode(dp);
-		dp->link_train.lt_state = FINISHED;
-
-		return 0;
-	}
-
-	/* not all locked */
-	dp->link_train.eq_loop++;
-
-	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-		dev_err(dp->dev, "EQ Max loop\n");
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count, dp->link_train.training_lane);
-
-	return retval;
-}
-
-static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
-					u8 *bandwidth)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum link rate of Main Link lanes
-	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
-	*bandwidth = data;
-}
-
-static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
-					u8 *lane_count)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum number of Main Link lanes
-	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-	*lane_count = DPCD_MAX_LANE_COUNT(data);
-}
-
-static void exynos_dp_init_training(struct exynos_dp_device *dp,
-			enum link_lane_count_type max_lane,
-			enum link_rate_type max_rate)
-{
-	/*
-	 * MACRO_RST must be applied after the PLL_LOCK to avoid
-	 * the DP inter pair skew issue for at least 10 us
-	 */
-	exynos_dp_reset_macro(dp);
-
-	/* Initialize by reading RX's DPCD */
-	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
-	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
-
-	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
-	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
-		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
-			dp->link_train.link_rate);
-		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
-	}
-
-	if (dp->link_train.lane_count == 0) {
-		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
-			dp->link_train.lane_count);
-		dp->link_train.lane_count = (u8)LANE_COUNT1;
-	}
-
-	/* Setup TX lane count & rate */
-	if (dp->link_train.lane_count > max_lane)
-		dp->link_train.lane_count = max_lane;
-	if (dp->link_train.link_rate > max_rate)
-		dp->link_train.link_rate = max_rate;
-
-	/* All DP analog module power up */
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-}
-
-static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
-{
-	int retval = 0, training_finished = 0;
-
-	dp->link_train.lt_state = START;
-
-	/* Process here */
-	while (!retval && !training_finished) {
-		switch (dp->link_train.lt_state) {
-		case START:
-			retval = exynos_dp_link_start(dp);
-			if (retval)
-				dev_err(dp->dev, "LT link start failed!\n");
-			break;
-		case CLOCK_RECOVERY:
-			retval = exynos_dp_process_clock_recovery(dp);
-			if (retval)
-				dev_err(dp->dev, "LT CR failed!\n");
-			break;
-		case EQUALIZER_TRAINING:
-			retval = exynos_dp_process_equalizer_training(dp);
-			if (retval)
-				dev_err(dp->dev, "LT EQ failed!\n");
-			break;
-		case FINISHED:
-			training_finished = 1;
-			break;
-		case FAILED:
-			return -EREMOTEIO;
-		}
-	}
-	if (retval)
-		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
-
-	return retval;
-}
-
-static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
-				u32 count,
-				u32 bwtype)
-{
-	int i;
-	int retval;
-
-	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
-		exynos_dp_init_training(dp, count, bwtype);
-		retval = exynos_dp_sw_link_training(dp);
-		if (retval == 0)
-			break;
-
-		usleep_range(100, 110);
-	}
-
-	return retval;
-}
-
-static int exynos_dp_config_video(struct exynos_dp_device *dp)
-{
-	int retval = 0;
-	int timeout_loop = 0;
-	int done_count = 0;
-
-	exynos_dp_config_video_slave_mode(dp);
-
-	exynos_dp_set_video_color_format(dp);
-
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		dev_err(dp->dev, "PLL is not locked yet.\n");
-		return -EINVAL;
-	}
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
-			break;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1, 2);
-	}
-
-	/* Set to use the register calculated M/N video */
-	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
-
-	/* For video bist, Video timing must be generated by register */
-	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
-
-	/* Disable video mute */
-	exynos_dp_enable_video_mute(dp, 0);
-
-	/* Configure video slave mode */
-	exynos_dp_enable_video_master(dp, 0);
-
-	/* Enable video */
-	exynos_dp_start_video(dp);
-
-	timeout_loop = 0;
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_video_stream_on(dp) == 0) {
-			done_count++;
-			if (done_count > 10)
-				break;
-		} else if (done_count) {
-			done_count = 0;
-		}
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1000, 1001);
-	}
-
-	if (retval != 0)
-		dev_err(dp->dev, "Video stream is not detected!\n");
-
-	return retval;
-}
-
-static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
-{
-	u8 data;
-
-	if (enable) {
-		exynos_dp_enable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
-	} else {
-		exynos_dp_disable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			(u8)(data | DPCD_SCRAMBLING_DISABLED));
-	}
-}
-
-static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
-{
-	struct exynos_dp_device *dp = arg;
-
-	enum dp_irq_type irq_type;
-
-	irq_type = exynos_dp_get_irq_type(dp);
-	switch (irq_type) {
-	case DP_IRQ_TYPE_HP_CABLE_IN:
-		dev_dbg(dp->dev, "Received irq - cable in\n");
-		schedule_work(&dp->hotplug_work);
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CABLE_OUT:
-		dev_dbg(dp->dev, "Received irq - cable out\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CHANGE:
-		/*
-		 * We get these change notifications once in a while, but there
-		 * is nothing we can do with them. Just ignore it for now and
-		 * only handle cable changes.
-		 */
-		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	default:
-		dev_err(dp->dev, "Received irq - unknown type!\n");
-		break;
-	}
-	return IRQ_HANDLED;
-}
-
-static void exynos_dp_hotplug(struct work_struct *work)
-{
-	struct exynos_dp_device *dp;
-	int ret;
-
-	dp = container_of(work, struct exynos_dp_device, hotplug_work);
-
-	ret = exynos_dp_detect_hpd(dp);
-	if (ret) {
-		/* Cable has been disconnected, we're done */
-		return;
-	}
-
-	ret = exynos_dp_handle_edid(dp);
-	if (ret) {
-		dev_err(dp->dev, "unable to handle edid\n");
-		return;
-	}
-
-	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-					dp->video_info->link_rate);
-	if (ret) {
-		dev_err(dp->dev, "unable to do link train\n");
-		return;
-	}
-
-	exynos_dp_enable_scramble(dp, 1);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-	exynos_dp_enable_enhanced_mode(dp, 1);
-
-	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-	exynos_dp_init_video(dp);
-	ret = exynos_dp_config_video(dp);
-	if (ret)
-		dev_err(dp->dev, "unable to config video\n");
-}
-
-static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	struct device_node *dp_node = dev->of_node;
-	struct video_info *dp_video_config;
-
-	dp_video_config = devm_kzalloc(dev,
-				sizeof(*dp_video_config), GFP_KERNEL);
-	if (!dp_video_config) {
-		dev_err(dev, "memory allocation for video config failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	dp_video_config->h_sync_polarity =
-		of_property_read_bool(dp_node, "hsync-active-high");
-
-	dp_video_config->v_sync_polarity =
-		of_property_read_bool(dp_node, "vsync-active-high");
-
-	dp_video_config->interlaced =
-		of_property_read_bool(dp_node, "interlaced");
-
-	if (of_property_read_u32(dp_node, "samsung,color-space",
-				&dp_video_config->color_space)) {
-		dev_err(dev, "failed to get color-space\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
-				&dp_video_config->dynamic_range)) {
-		dev_err(dev, "failed to get dynamic-range\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
-				&dp_video_config->ycbcr_coeff)) {
-		dev_err(dev, "failed to get ycbcr-coeff\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,color-depth",
-				&dp_video_config->color_depth)) {
-		dev_err(dev, "failed to get color-depth\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,link-rate",
-				&dp_video_config->link_rate)) {
-		dev_err(dev, "failed to get link-rate\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,lane-count",
-				&dp_video_config->lane_count)) {
-		dev_err(dev, "failed to get lane-count\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return dp_video_config;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
-	u32 phy_base;
-	int ret = 0;
-
-	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
-	if (!dp_phy_node) {
-		dp->phy = devm_phy_get(dp->dev, "dp");
-		if (IS_ERR(dp->phy))
-			return PTR_ERR(dp->phy);
-		else
-			return 0;
-	}
-
-	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
-		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
-				&dp->enable_mask)) {
-		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	dp->phy_addr = ioremap(phy_base, SZ_4);
-	if (!dp->phy_addr) {
-		dev_err(dp->dev, "failed to ioremap dp-phy\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-err:
-	of_node_put(dp_phy_node);
-
-	return ret;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	if (dp->phy) {
-		phy_power_on(dp->phy);
-	} else if (dp->phy_addr) {
-		u32 reg;
-
-		reg = __raw_readl(dp->phy_addr);
-		reg |= dp->enable_mask;
-		__raw_writel(reg, dp->phy_addr);
-	}
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	if (dp->phy) {
-		phy_power_off(dp->phy);
-	} else if (dp->phy_addr) {
-		u32 reg;
-
-		reg = __raw_readl(dp->phy_addr);
-		reg &= ~(dp->enable_mask);
-		__raw_writel(reg, dp->phy_addr);
-	}
-}
-
-static int exynos_dp_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct exynos_dp_device *dp;
-
-	int ret = 0;
-
-	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
-				GFP_KERNEL);
-	if (!dp) {
-		dev_err(&pdev->dev, "no memory for device data\n");
-		return -ENOMEM;
-	}
-
-	dp->dev = &pdev->dev;
-
-	dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
-	if (IS_ERR(dp->video_info))
-		return PTR_ERR(dp->video_info);
-
-	ret = exynos_dp_dt_parse_phydata(dp);
-	if (ret)
-		return ret;
-
-	dp->clock = devm_clk_get(&pdev->dev, "dp");
-	if (IS_ERR(dp->clock)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		return PTR_ERR(dp->clock);
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dp->reg_base))
-		return PTR_ERR(dp->reg_base);
-
-	dp->irq = platform_get_irq(pdev, 0);
-	if (dp->irq == -ENXIO) {
-		dev_err(&pdev->dev, "failed to get irq\n");
-		return -ENODEV;
-	}
-
-	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
-
-	exynos_dp_phy_init(dp);
-
-	exynos_dp_init_dp(dp);
-
-	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
-				"exynos-dp", dp);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, dp);
-
-	return 0;
-}
-
-static int exynos_dp_remove(struct platform_device *pdev)
-{
-	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
-
-	flush_work(&dp->hotplug_work);
-
-	exynos_dp_phy_exit(dp);
-
-	clk_disable_unprepare(dp->clock);
-
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos_dp_suspend(struct device *dev)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	disable_irq(dp->irq);
-
-	flush_work(&dp->hotplug_work);
-
-	exynos_dp_phy_exit(dp);
-
-	clk_disable_unprepare(dp->clock);
-
-	return 0;
-}
-
-static int exynos_dp_resume(struct device *dev)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	exynos_dp_phy_init(dp);
-
-	clk_prepare_enable(dp->clock);
-
-	exynos_dp_init_dp(dp);
-
-	enable_irq(dp->irq);
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_dp_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
-};
-
-static const struct of_device_id exynos_dp_match[] = {
-	{ .compatible = "samsung,exynos5-dp" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_match);
-
-static struct platform_driver exynos_dp_driver = {
-	.probe		= exynos_dp_probe,
-	.remove		= exynos_dp_remove,
-	.driver		= {
-		.name	= "exynos-dp",
-		.owner	= THIS_MODULE,
-		.pm	= &exynos_dp_pm_ops,
-		.of_match_table = exynos_dp_match,
-	},
-};
-
-module_platform_driver(exynos_dp_driver);
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
deleted file mode 100644
index 607e36d0c147..000000000000
--- a/drivers/video/exynos/exynos_dp_core.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Header file for Samsung DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.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 _EXYNOS_DP_CORE_H
-#define _EXYNOS_DP_CORE_H
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
-	LINK_RATE_1_62GBPS = 0x06,
-	LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
-	LANE_COUNT1 = 1,
-	LANE_COUNT2 = 2,
-	LANE_COUNT4 = 4
-};
-
-enum link_training_state {
-	START,
-	CLOCK_RECOVERY,
-	EQUALIZER_TRAINING,
-	FINISHED,
-	FAILED
-};
-
-enum voltage_swing_level {
-	VOLTAGE_LEVEL_0,
-	VOLTAGE_LEVEL_1,
-	VOLTAGE_LEVEL_2,
-	VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
-	PRE_EMPHASIS_LEVEL_0,
-	PRE_EMPHASIS_LEVEL_1,
-	PRE_EMPHASIS_LEVEL_2,
-	PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
-	PRBS7,
-	D10_2,
-	TRAINING_PTN1,
-	TRAINING_PTN2,
-	DP_NONE
-};
-
-enum color_space {
-	COLOR_RGB,
-	COLOR_YCBCR422,
-	COLOR_YCBCR444
-};
-
-enum color_depth {
-	COLOR_6,
-	COLOR_8,
-	COLOR_10,
-	COLOR_12
-};
-
-enum color_coefficient {
-	COLOR_YCBCR601,
-	COLOR_YCBCR709
-};
-
-enum dynamic_range {
-	VESA,
-	CEA
-};
-
-enum pll_status {
-	PLL_UNLOCKED,
-	PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
-	CALCULATED_M,
-	REGISTER_M
-};
-
-enum video_timing_recognition_type {
-	VIDEO_TIMING_FROM_CAPTURE,
-	VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
-	AUX_BLOCK,
-	CH0_BLOCK,
-	CH1_BLOCK,
-	CH2_BLOCK,
-	CH3_BLOCK,
-	ANALOG_TOTAL,
-	POWER_ALL
-};
-
-enum dp_irq_type {
-	DP_IRQ_TYPE_HP_CABLE_IN,
-	DP_IRQ_TYPE_HP_CABLE_OUT,
-	DP_IRQ_TYPE_HP_CHANGE,
-	DP_IRQ_TYPE_UNKNOWN,
-};
-
-struct video_info {
-	char *name;
-
-	bool h_sync_polarity;
-	bool v_sync_polarity;
-	bool interlaced;
-
-	enum color_space color_space;
-	enum dynamic_range dynamic_range;
-	enum color_coefficient ycbcr_coeff;
-	enum color_depth color_depth;
-
-	enum link_rate_type link_rate;
-	enum link_lane_count_type lane_count;
-};
-
-struct link_train {
-	int eq_loop;
-	int cr_loop[4];
-
-	u8 link_rate;
-	u8 lane_count;
-	u8 training_lane[4];
-
-	enum link_training_state lt_state;
-};
-
-struct exynos_dp_device {
-	struct device		*dev;
-	struct clk		*clock;
-	unsigned int		irq;
-	void __iomem		*reg_base;
-	void __iomem		*phy_addr;
-	unsigned int		enable_mask;
-
-	struct video_info	*video_info;
-	struct link_train	link_train;
-	struct work_struct	hotplug_work;
-	struct phy		*phy;
-};
-
-/* exynos_dp_reg.c */
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_stop_video(struct exynos_dp_device *dp);
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
-void exynos_dp_reset(struct exynos_dp_device *dp);
-void exynos_dp_swreset(struct exynos_dp_device *dp);
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable);
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
-void exynos_dp_init_hpd(struct exynos_dp_device *dp);
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
-void exynos_dp_reset_aux(struct exynos_dp_device *dp);
-void exynos_dp_init_aux(struct exynos_dp_device *dp);
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data);
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data);
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr);
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data);
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[]);
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern);
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
-void exynos_dp_reset_macro(struct exynos_dp_device *dp);
-void exynos_dp_init_video(struct exynos_dp_device *dp);
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-			enum clock_recovery_m_value_type type,
-			u32 m_value,
-			u32 n_value);
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_start_video(struct exynos_dp_device *dp);
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
-
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR			0x50
-#define I2C_E_EDID_DEVICE_ADDR			0x30
-
-#define EDID_BLOCK_LENGTH			0x80
-#define EDID_HEADER_PATTERN			0x00
-#define EDID_EXTENSION_FLAG			0x7e
-#define EDID_CHECKSUM				0x7f
-
-/* Definition for DPCD Register */
-#define DPCD_ADDR_DPCD_REV			0x0000
-#define DPCD_ADDR_MAX_LINK_RATE			0x0001
-#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
-#define DPCD_ADDR_LINK_BW_SET			0x0100
-#define DPCD_ADDR_LANE_COUNT_SET		0x0101
-#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
-#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
-#define DPCD_ADDR_LANE0_1_STATUS		0x0202
-#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
-#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
-#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
-#define DPCD_ADDR_TEST_REQUEST			0x0218
-#define DPCD_ADDR_TEST_RESPONSE			0x0260
-#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
-#define DPCD_ADDR_SINK_POWER_STATE		0x0600
-
-/* DPCD_ADDR_MAX_LANE_COUNT */
-#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
-#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
-
-/* DPCD_ADDR_LANE_COUNT_SET */
-#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
-#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
-
-/* DPCD_ADDR_TRAINING_PATTERN_SET */
-#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
-#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
-#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
-#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
-#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
-
-/* DPCD_ADDR_TRAINING_LANE0_SET */
-#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
-#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
-#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
-#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
-#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
-#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
-#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
-#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
-
-/* DPCD_ADDR_LANE0_1_STATUS */
-#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
-#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
-#define DPCD_LANE_CR_DONE			(0x1 << 0)
-#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
-						 DPCD_LANE_CHANNEL_EQ_DONE|\
-						 DPCD_LANE_SYMBOL_LOCKED)
-
-/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
-#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
-#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
-#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
-
-/* DPCD_ADDR_TEST_REQUEST */
-#define DPCD_TEST_EDID_READ			(0x1 << 2)
-
-/* DPCD_ADDR_TEST_RESPONSE */
-#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
-
-/* DPCD_ADDR_SINK_POWER_STATE */
-#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
-#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
-
-#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
deleted file mode 100644
index b70da5052ff0..000000000000
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * Samsung DP (Display port) register interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.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/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include "exynos_dp_core.h"
-#include "exynos_dp_reg.h"
-
-#define COMMON_INT_MASK_1	0
-#define COMMON_INT_MASK_2	0
-#define COMMON_INT_MASK_3	0
-#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
-#define INT_STA_MASK		INT_HPD
-
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg |= HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg &= ~HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	}
-}
-
-void exynos_dp_stop_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg &= ~VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable)
-		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
-			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
-	else
-		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
-			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
-
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
-}
-
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = TX_TERMINAL_CTRL_50_OHM;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
-
-	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
-
-	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
-
-	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
-		TX_CUR1_2X | TX_CUR_16_MA;
-	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
-
-	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
-		CH1_AMP_400_MV | CH0_AMP_400_MV;
-	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
-}
-
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
-{
-	/* Set interrupt pin assertion polarity as high */
-	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
-
-	/* Clear pending regisers */
-	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
-	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
-	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* 0:mask,1: unmask */
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-void exynos_dp_reset(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	exynos_dp_stop_video(dp);
-	exynos_dp_enable_video_mute(dp, 0);
-
-	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
-		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
-		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
-		SERDES_FIFO_FUNC_EN_N |
-		LS_CLK_DOMAIN_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-
-	usleep_range(20, 30);
-
-	exynos_dp_lane_swap(dp, 0);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
-	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
-
-	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
-	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
-
-	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
-	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
-
-	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
-	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
-
-	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_swreset(struct exynos_dp_device *dp)
-{
-	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
-}
-
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* 0: mask, 1: unmask */
-	reg = COMMON_INT_MASK_1;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-
-	reg = COMMON_INT_MASK_2;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-
-	reg = COMMON_INT_MASK_3;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-
-	reg = COMMON_INT_MASK_4;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-
-	reg = INT_STA_MASK;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	if (reg & PLL_LOCK)
-		return PLL_LOCKED;
-	else
-		return PLL_UNLOCKED;
-}
-
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg |= DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg &= ~DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	}
-}
-
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable)
-{
-	u32 reg;
-
-	switch (block) {
-	case AUX_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH0_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH1_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH2_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH3_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case ANALOG_TOTAL:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case POWER_ALL:
-		if (enable) {
-			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
-				CH1_PD | CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
-{
-	u32 reg;
-	int timeout_loop = 0;
-
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-
-	reg = PLL_LOCK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-
-	/* Power up PLL */
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		exynos_dp_set_pll_power_down(dp, 0);
-
-		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-			timeout_loop++;
-			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-				dev_err(dp->dev, "failed to get pll lock status\n");
-				return;
-			}
-			usleep_range(10, 20);
-		}
-	}
-
-	/* Enable Serdes FIFO function and Link symbol clock domain module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
-		| AUX_FUNC_EN_N);
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-	reg = INT_HPD;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-}
-
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	exynos_dp_clear_hotplug_interrupts(dp);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	reg &= ~(F_HPD | HPD_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-}
-
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Parse hotplug interrupt status register */
-	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-	if (reg & PLUG)
-		return DP_IRQ_TYPE_HP_CABLE_IN;
-
-	if (reg & HPD_LOST)
-		return DP_IRQ_TYPE_HP_CABLE_OUT;
-
-	if (reg & HOTPLUG_CHG)
-		return DP_IRQ_TYPE_HP_CHANGE;
-
-	return DP_IRQ_TYPE_UNKNOWN;
-}
-
-void exynos_dp_reset_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Disable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg |= AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_init_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Clear inerrupts related to AUX channel */
-	reg = RPLY_RECEIV | AUX_ERR;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	exynos_dp_reset_aux(dp);
-
-	/* Disable AUX transaction H/W retry */
-	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
-		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
-
-	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
-	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
-
-	/* Enable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	if (reg & HPD_STATUS)
-		return 0;
-
-	return -EINVAL;
-}
-
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-}
-
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
-{
-	int reg;
-	int retval = 0;
-	int timeout_loop = 0;
-
-	/* Enable AUX CH operation */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-	reg |= AUX_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-	/* Is AUX CH command reply received? */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	while (!(reg & RPLY_RECEIV)) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "AUX CH command reply failed!\n");
-			return -ETIMEDOUT;
-		}
-		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-		usleep_range(10, 11);
-	}
-
-	/* Clear interrupt source for AUX CH command reply */
-	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* Clear interrupt source for AUX CH access error */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	if (reg & AUX_ERR) {
-		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
-		return -EREMOTEIO;
-	}
-
-	/* Check AUX CH error access status */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
-	if ((reg & AUX_STATUS_MASK) != 0) {
-		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
-			reg & AUX_STATUS_MASK);
-		return -EREMOTEIO;
-	}
-
-	return retval;
-}
-
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/* Write data buffer */
-		reg = (unsigned int)data;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-		/*
-		 * Set DisplayPort transaction and write 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/*
-		 * Set DisplayPort transaction and read 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data buffer */
-	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-	*data = (unsigned char)(reg & 0xff);
-
-	return retval;
-}
-
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-			     cur_data_idx++) {
-				reg = data[start_offset + cur_data_idx];
-				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
-							  + 4 * cur_data_idx);
-			}
-
-			/*
-			 * Set DisplayPort transaction and write
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		/* AUX CH Request Transaction process */
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			/*
-			 * Set DisplayPort transaction and read
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-		    cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			data[start_offset + cur_data_idx] =
-				(unsigned char)reg;
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr)
-{
-	u32 reg;
-	int retval;
-
-	/* Set EDID device address */
-	reg = device_addr;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-	/* Set offset from base address of EDID device */
-	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	/*
-	 * Set I2C transaction and write address
-	 * If bit 3 is 1, DisplayPort transaction.
-	 * If Bit 3 is 0, I2C transaction.
-	 */
-	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
-		AUX_TX_COMM_WRITE;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-	/* Start AUX transaction */
-	retval = exynos_dp_start_aux_transaction(dp);
-	if (retval != 0)
-		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select EDID device */
-		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-		if (retval != 0)
-			continue;
-
-		/*
-		 * Set I2C transaction and read data
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_I2C_TRANSACTION |
-			AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data */
-	if (retval == 0)
-		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[])
-{
-	u32 reg;
-	unsigned int i, j;
-	unsigned int cur_data_idx;
-	unsigned int defer = 0;
-	int retval = 0;
-
-	for (i = 0; i < count; i += 16) {
-		for (j = 0; j < 3; j++) {
-			/* Clear AUX CH data buffer */
-			reg = BUF_CLR;
-			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-			/* Set normal AUX CH command */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-			reg &= ~ADDR_ONLY;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-			/*
-			 * If Rx sends defer, Tx sends only reads
-			 * request without sending address
-			 */
-			if (!defer)
-				retval = exynos_dp_select_i2c_device(dp,
-						device_addr, reg_addr + i);
-			else
-				defer = 0;
-
-			if (retval == 0) {
-				/*
-				 * Set I2C transaction and write data
-				 * If bit 3 is 1, DisplayPort transaction.
-				 * If Bit 3 is 0, I2C transaction.
-				 */
-				reg = AUX_LENGTH(16) |
-					AUX_TX_COMM_I2C_TRANSACTION |
-					AUX_TX_COMM_READ;
-				writel(reg, dp->reg_base +
-					EXYNOS_DP_AUX_CH_CTL_1);
-
-				/* Start AUX transaction */
-				retval = exynos_dp_start_aux_transaction(dp);
-				if (retval == 0)
-					break;
-				else
-					dev_dbg(dp->dev,
-						"%s: Aux Transaction fail!\n",
-						__func__);
-			}
-			/* Check if Rx sends defer */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
-			if (reg == AUX_RX_COMM_AUX_DEFER ||
-				reg == AUX_RX_COMM_I2C_DEFER) {
-				dev_err(dp->dev, "Defer: %d\n\n", reg);
-				defer = 1;
-			}
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			edid[i + cur_data_idx] = (unsigned char)reg;
-		}
-	}
-
-	return retval;
-}
-
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
-{
-	u32 reg;
-
-	reg = bwtype;
-	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
-		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-}
-
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-	*bwtype = reg;
-}
-
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
-{
-	u32 reg;
-
-	reg = count;
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-}
-
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-	*count = reg;
-}
-
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	}
-}
-
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern)
-{
-	u32 reg;
-
-	switch (pattern) {
-	case PRBS7:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case D10_2:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN1:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN2:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case DP_NONE:
-		reg = SCRAMBLING_ENABLE |
-			LINK_QUAL_PATTERN_SET_DISABLE |
-			SW_TRAINING_PATTERN_SET_NORMAL;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	return reg;
-}
-
-void exynos_dp_reset_macro(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
-	reg |= MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	/* 10 us is the minimum reset time. */
-	usleep_range(10, 20);
-
-	reg &= ~MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-}
-
-void exynos_dp_init_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = CHA_CRI(4) | CHA_CTRL;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
-}
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Configure the input color depth, color space, dynamic range */
-	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
-		(dp->video_info->color_depth << IN_BPC_SHIFT) |
-		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
-
-	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-	reg &= ~IN_YC_COEFFI_MASK;
-	if (dp->video_info->ycbcr_coeff)
-		reg |= IN_YC_COEFFI_ITU709;
-	else
-		reg |= IN_YC_COEFFI_ITU601;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-}
-
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	if (!(reg & DET_STA)) {
-		dev_dbg(dp->dev, "Input stream clock not detected.\n");
-		return -EINVAL;
-	}
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
-
-	if (reg & CHA_STA) {
-		dev_dbg(dp->dev, "Input stream clk is changing\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-		enum clock_recovery_m_value_type type,
-		u32 m_value,
-		u32 n_value)
-{
-	u32 reg;
-
-	if (type == REGISTER_M) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg = m_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
-		reg = (m_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
-		reg = (m_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
-
-		reg = n_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
-		reg = (n_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
-		reg = (n_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
-	} else  {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
-		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
-	}
-}
-
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
-{
-	u32 reg;
-
-	if (type == VIDEO_TIMING_FROM_CAPTURE) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg &= ~FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg |= FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	}
-}
-
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MODE_SLAVE_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	}
-}
-
-void exynos_dp_start_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg |= VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	if (!(reg & STRM_VALID)) {
-		dev_dbg(dp->dev, "Input video stream is not detected.\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
-	reg |= MASTER_VID_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~INTERACE_SCAN_CFG;
-	reg |= (dp->video_info->interlaced << 2);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~VSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->v_sync_polarity << 1);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~HSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->h_sync_polarity << 0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
-	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg &= ~SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
-
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg |= SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
deleted file mode 100644
index 2e9bd0e0b9f2..000000000000
--- a/drivers/video/exynos/exynos_dp_reg.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Register definition file for Samsung DP driver
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@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_DP_REG_H
-#define _EXYNOS_DP_REG_H
-
-#define EXYNOS_DP_TX_SW_RESET			0x14
-#define EXYNOS_DP_FUNC_EN_1			0x18
-#define EXYNOS_DP_FUNC_EN_2			0x1C
-#define EXYNOS_DP_VIDEO_CTL_1			0x20
-#define EXYNOS_DP_VIDEO_CTL_2			0x24
-#define EXYNOS_DP_VIDEO_CTL_3			0x28
-
-#define EXYNOS_DP_VIDEO_CTL_8			0x3C
-#define EXYNOS_DP_VIDEO_CTL_10			0x44
-
-#define EXYNOS_DP_LANE_MAP			0x35C
-
-#define EXYNOS_DP_ANALOG_CTL_1			0x370
-#define EXYNOS_DP_ANALOG_CTL_2			0x374
-#define EXYNOS_DP_ANALOG_CTL_3			0x378
-#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
-#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
-
-#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
-
-#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
-#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
-#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
-#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
-#define EXYNOS_DP_INT_STA			0x3DC
-#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
-#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
-#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
-#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
-#define EXYNOS_DP_INT_STA_MASK			0x3F8
-#define EXYNOS_DP_INT_CTL			0x3FC
-
-#define EXYNOS_DP_SYS_CTL_1			0x600
-#define EXYNOS_DP_SYS_CTL_2			0x604
-#define EXYNOS_DP_SYS_CTL_3			0x608
-#define EXYNOS_DP_SYS_CTL_4			0x60C
-
-#define EXYNOS_DP_PKT_SEND_CTL			0x640
-#define EXYNOS_DP_HDCP_CTL			0x648
-
-#define EXYNOS_DP_LINK_BW_SET			0x680
-#define EXYNOS_DP_LANE_COUNT_SET		0x684
-#define EXYNOS_DP_TRAINING_PTN_SET		0x688
-#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
-#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
-#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
-#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
-
-#define EXYNOS_DP_DEBUG_CTL			0x6C0
-#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
-#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
-#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
-
-#define EXYNOS_DP_M_VID_0			0x700
-#define EXYNOS_DP_M_VID_1			0x704
-#define EXYNOS_DP_M_VID_2			0x708
-#define EXYNOS_DP_N_VID_0			0x70C
-#define EXYNOS_DP_N_VID_1			0x710
-#define EXYNOS_DP_N_VID_2			0x714
-
-#define EXYNOS_DP_PLL_CTL			0x71C
-#define EXYNOS_DP_PHY_PD			0x720
-#define EXYNOS_DP_PHY_TEST			0x724
-
-#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
-#define EXYNOS_DP_AUDIO_MARGIN			0x73C
-
-#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
-#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
-#define EXYNOS_DP_AUX_CH_STA			0x780
-#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
-#define EXYNOS_DP_AUX_RX_COMM			0x78C
-#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
-#define EXYNOS_DP_AUX_CH_CTL_1			0x794
-#define EXYNOS_DP_AUX_ADDR_7_0			0x798
-#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
-#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
-#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
-
-#define EXYNOS_DP_BUF_DATA_0			0x7C0
-
-#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
-
-/* EXYNOS_DP_TX_SW_RESET */
-#define RESET_DP_TX				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_1 */
-#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
-#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
-#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
-#define AUD_FUNC_EN_N				(0x1 << 3)
-#define HDCP_FUNC_EN_N				(0x1 << 2)
-#define CRC_FUNC_EN_N				(0x1 << 1)
-#define SW_FUNC_EN_N				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_2 */
-#define SSC_FUNC_EN_N				(0x1 << 7)
-#define AUX_FUNC_EN_N				(0x1 << 2)
-#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
-#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define VIDEO_EN				(0x1 << 7)
-#define HDCP_VIDEO_MUTE				(0x1 << 6)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define IN_D_RANGE_MASK				(0x1 << 7)
-#define IN_D_RANGE_SHIFT			(7)
-#define IN_D_RANGE_CEA				(0x1 << 7)
-#define IN_D_RANGE_VESA				(0x0 << 7)
-#define IN_BPC_MASK				(0x7 << 4)
-#define IN_BPC_SHIFT				(4)
-#define IN_BPC_12_BITS				(0x3 << 4)
-#define IN_BPC_10_BITS				(0x2 << 4)
-#define IN_BPC_8_BITS				(0x1 << 4)
-#define IN_BPC_6_BITS				(0x0 << 4)
-#define IN_COLOR_F_MASK				(0x3 << 0)
-#define IN_COLOR_F_SHIFT			(0)
-#define IN_COLOR_F_YCBCR444			(0x2 << 0)
-#define IN_COLOR_F_YCBCR422			(0x1 << 0)
-#define IN_COLOR_F_RGB				(0x0 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_3 */
-#define IN_YC_COEFFI_MASK			(0x1 << 7)
-#define IN_YC_COEFFI_SHIFT			(7)
-#define IN_YC_COEFFI_ITU709			(0x1 << 7)
-#define IN_YC_COEFFI_ITU601			(0x0 << 7)
-#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
-#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
-
-/* EXYNOS_DP_VIDEO_CTL_8 */
-#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
-#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_10 */
-#define FORMAT_SEL				(0x1 << 4)
-#define INTERACE_SCAN_CFG			(0x1 << 2)
-#define VSYNC_POLARITY_CFG			(0x1 << 1)
-#define HSYNC_POLARITY_CFG			(0x1 << 0)
-
-/* EXYNOS_DP_LANE_MAP */
-#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
-#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
-#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
-#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
-#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
-#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
-#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
-#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
-#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
-#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
-#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
-#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
-#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
-#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
-#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
-#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_1 */
-#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
-
-/* EXYNOS_DP_ANALOG_CTL_2 */
-#define SEL_24M					(0x1 << 3)
-#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_3 */
-#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
-#define VCO_BIT_600_MICRO			(0x5 << 0)
-
-/* EXYNOS_DP_PLL_FILTER_CTL_1 */
-#define PD_RING_OSC				(0x1 << 6)
-#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
-#define TX_CUR1_2X				(0x1 << 2)
-#define TX_CUR_16_MA				(0x3 << 0)
-
-/* EXYNOS_DP_TX_AMP_TUNING_CTL */
-#define CH3_AMP_400_MV				(0x0 << 24)
-#define CH2_AMP_400_MV				(0x0 << 16)
-#define CH1_AMP_400_MV				(0x0 << 8)
-#define CH0_AMP_400_MV				(0x0 << 0)
-
-/* EXYNOS_DP_AUX_HW_RETRY_CTL */
-#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
-#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
-#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
-#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
-#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
-#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
-#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_1 */
-#define VSYNC_DET				(0x1 << 7)
-#define PLL_LOCK_CHG				(0x1 << 6)
-#define SPDIF_ERR				(0x1 << 5)
-#define SPDIF_UNSTBL				(0x1 << 4)
-#define VID_FORMAT_CHG				(0x1 << 3)
-#define AUD_CLK_CHG				(0x1 << 2)
-#define VID_CLK_CHG				(0x1 << 1)
-#define SW_INT					(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_2 */
-#define ENC_EN_CHG				(0x1 << 6)
-#define HW_BKSV_RDY				(0x1 << 3)
-#define HW_SHA_DONE				(0x1 << 2)
-#define HW_AUTH_STATE_CHG			(0x1 << 1)
-#define HW_AUTH_DONE				(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_3 */
-#define AFIFO_UNDER				(0x1 << 7)
-#define AFIFO_OVER				(0x1 << 6)
-#define R0_CHK_FLAG				(0x1 << 5)
-
-/* EXYNOS_DP_COMMON_INT_STA_4 */
-#define PSR_ACTIVE				(0x1 << 7)
-#define PSR_INACTIVE				(0x1 << 6)
-#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
-#define HOTPLUG_CHG				(0x1 << 2)
-#define HPD_LOST				(0x1 << 1)
-#define PLUG					(0x1 << 0)
-
-/* EXYNOS_DP_INT_STA */
-#define INT_HPD					(0x1 << 6)
-#define HW_TRAINING_FINISH			(0x1 << 5)
-#define RPLY_RECEIV				(0x1 << 1)
-#define AUX_ERR					(0x1 << 0)
-
-/* EXYNOS_DP_INT_CTL */
-#define SOFT_INT_CTRL				(0x1 << 2)
-#define INT_POL1				(0x1 << 1)
-#define INT_POL0				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_1 */
-#define DET_STA					(0x1 << 2)
-#define FORCE_DET				(0x1 << 1)
-#define DET_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_2 */
-#define CHA_CRI(x)				(((x) & 0xf) << 4)
-#define CHA_STA					(0x1 << 2)
-#define FORCE_CHA				(0x1 << 1)
-#define CHA_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_3 */
-#define HPD_STATUS				(0x1 << 6)
-#define F_HPD					(0x1 << 5)
-#define HPD_CTRL				(0x1 << 4)
-#define HDCP_RDY				(0x1 << 3)
-#define STRM_VALID				(0x1 << 2)
-#define F_VALID					(0x1 << 1)
-#define VALID_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_4 */
-#define FIX_M_AUD				(0x1 << 4)
-#define ENHANCED				(0x1 << 3)
-#define FIX_M_VID				(0x1 << 2)
-#define M_VID_UPDATE_CTRL			(0x3 << 0)
-
-/* EXYNOS_DP_TRAINING_PTN_SET */
-#define SCRAMBLER_TYPE				(0x1 << 9)
-#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
-#define SCRAMBLING_DISABLE			(0x1 << 5)
-#define SCRAMBLING_ENABLE			(0x0 << 5)
-#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
-#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
-#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
-#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
-
-/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
-#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
-#define PRE_EMPHASIS_SET_SHIFT			(3)
-
-/* EXYNOS_DP_DEBUG_CTL */
-#define PLL_LOCK				(0x1 << 4)
-#define F_PLL_LOCK				(0x1 << 3)
-#define PLL_LOCK_CTRL				(0x1 << 2)
-#define PN_INV					(0x1 << 0)
-
-/* EXYNOS_DP_PLL_CTL */
-#define DP_PLL_PD				(0x1 << 7)
-#define DP_PLL_RESET				(0x1 << 6)
-#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
-#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
-#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
-
-/* EXYNOS_DP_PHY_PD */
-#define DP_PHY_PD				(0x1 << 5)
-#define AUX_PD					(0x1 << 4)
-#define CH3_PD					(0x1 << 3)
-#define CH2_PD					(0x1 << 2)
-#define CH1_PD					(0x1 << 1)
-#define CH0_PD					(0x1 << 0)
-
-/* EXYNOS_DP_PHY_TEST */
-#define MACRO_RST				(0x1 << 5)
-#define CH1_TEST				(0x1 << 1)
-#define CH0_TEST				(0x1 << 0)
-
-/* EXYNOS_DP_AUX_CH_STA */
-#define AUX_BUSY				(0x1 << 4)
-#define AUX_STATUS_MASK				(0xf << 0)
-
-/* EXYNOS_DP_AUX_CH_DEFER_CTL */
-#define DEFER_CTRL_EN				(0x1 << 7)
-#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
-
-/* EXYNOS_DP_AUX_RX_COMM */
-#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
-#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
-
-/* EXYNOS_DP_BUFFER_DATA_CTL */
-#define BUF_CLR					(0x1 << 7)
-#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
-
-/* EXYNOS_DP_AUX_CH_CTL_1 */
-#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
-#define AUX_TX_COMM_MASK			(0xf << 0)
-#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
-#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
-#define AUX_TX_COMM_MOT				(0x1 << 2)
-#define AUX_TX_COMM_WRITE			(0x0 << 0)
-#define AUX_TX_COMM_READ			(0x1 << 0)
-
-/* EXYNOS_DP_AUX_ADDR_7_0 */
-#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_15_8 */
-#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_19_16 */
-#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
-
-/* EXYNOS_DP_AUX_CH_CTL_2 */
-#define ADDR_ONLY				(0x1 << 1)
-#define AUX_EN					(0x1 << 0)
-
-/* EXYNOS_DP_SOC_GENERAL_CTL */
-#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
-#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
-#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
-#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
-#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
-#define VIDEO_MODE_MASK				(0x1 << 0)
-#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
-#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
-
-#endif /* _EXYNOS_DP_REG_H */
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 ca2602413aa4..000000000000
--- a/drivers/video/exynos/s6e8ax0.c
+++ /dev/null
@@ -1,903 +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 = lcd_device_register("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 = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd,
-			&s6e8ax0_backlight_ops, NULL);
-	if (IS_ERR(lcd->bd)) {
-		dev_err(lcd->dev, "failed to register backlight ops.\n");
-		ret = PTR_ERR(lcd->bd);
-		goto err_backlight_register;
-	}
-
-	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;
-
-err_backlight_register:
-	lcd_device_unregister(lcd->ld);
-	return ret;
-}
-
-#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..6b1984c7f4e7
--- /dev/null
+++ b/drivers/video/fbdev/Kconfig
@@ -0,0 +1,2472 @@
+#
+# 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 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
+	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..cd961622f9c1
--- /dev/null
+++ b/drivers/video/fbdev/atmel_lcdfb.c
@@ -0,0 +1,1447 @@
+/*
+ *  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;
+
+	strcpy(info->fix.id, sinfo->pdev->name);
+	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
+	info->pseudo_palette = sinfo->pseudo_palette;
+	info->fbops = &atmel_lcdfb_ops;
+
+	info->fix = atmel_lcdfb_fix;
+
+	/* 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;
+	}
+
+	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..42b8f9d11018
--- /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 <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/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..7309ac704e26
--- /dev/null
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -0,0 +1,2003 @@
+/*
+ *  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: conflicting fb hw usage "
+			       "%s vs %s - removing generic driver\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..0c0ba920ea48
--- /dev/null
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -0,0 +1,1667 @@
+/*
+ * 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/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..cd7c0df9f24b
--- /dev/null
+++ b/drivers/video/fbdev/efifb.c
@@ -0,0 +1,349 @@
+/*
+ * 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);
+	framebuffer_release(info);
+}
+
+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;
+	}
+	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 struct platform_driver efifb_driver = {
+	.driver = {
+		.name = "efi-framebuffer",
+		.owner = THIS_MODULE,
+	},
+	.probe = efifb_probe,
+};
+
+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..eb6f2b059821
--- /dev/null
+++ b/drivers/video/fbdev/exynos/Kconfig
@@ -0,0 +1,39 @@
+#
+# 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.
+
+config EXYNOS_DP
+	bool "EXYNOS DP driver support"
+	depends on ARCH_EXYNOS
+	default n
+	help
+	  This enables support for DP device.
+
+endif # EXYNOS_VIDEO
diff --git a/drivers/video/fbdev/exynos/Makefile b/drivers/video/fbdev/exynos/Makefile
new file mode 100644
index 000000000000..ec7772e452a9
--- /dev/null
+++ b/drivers/video/fbdev/exynos/Makefile
@@ -0,0 +1,8 @@
+#
+# 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
+obj-$(CONFIG_EXYNOS_DP)			+= exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/fbdev/exynos/exynos_dp_core.c b/drivers/video/fbdev/exynos/exynos_dp_core.c
new file mode 100644
index 000000000000..5e1a71580051
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_dp_core.c
@@ -0,0 +1,1156 @@
+/*
+ * Samsung SoC DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.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/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+
+#include "exynos_dp_core.h"
+
+static int exynos_dp_init_dp(struct exynos_dp_device *dp)
+{
+	exynos_dp_reset(dp);
+
+	exynos_dp_swreset(dp);
+
+	exynos_dp_init_analog_param(dp);
+	exynos_dp_init_interrupt(dp);
+
+	/* SW defined function Normal operation */
+	exynos_dp_enable_sw_function(dp);
+
+	exynos_dp_config_interrupt(dp);
+	exynos_dp_init_analog_func(dp);
+
+	exynos_dp_init_hpd(dp);
+	exynos_dp_init_aux(dp);
+
+	return 0;
+}
+
+static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
+{
+	int timeout_loop = 0;
+
+	while (exynos_dp_get_plug_in_status(dp) != 0) {
+		timeout_loop++;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "failed to get hpd plug status\n");
+			return -ETIMEDOUT;
+		}
+		usleep_range(10, 11);
+	}
+
+	return 0;
+}
+
+static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
+{
+	int i;
+	unsigned char sum = 0;
+
+	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
+		sum = sum + edid_data[i];
+
+	return sum;
+}
+
+static int exynos_dp_read_edid(struct exynos_dp_device *dp)
+{
+	unsigned char edid[EDID_BLOCK_LENGTH * 2];
+	unsigned int extend_block = 0;
+	unsigned char sum;
+	unsigned char test_vector;
+	int retval;
+
+	/*
+	 * EDID device address is 0x50.
+	 * However, if necessary, you must have set upper address
+	 * into E-EDID in I2C device, 0x30.
+	 */
+
+	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
+	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+				EDID_EXTENSION_FLAG,
+				&extend_block);
+	if (retval)
+		return retval;
+
+	if (extend_block > 0) {
+		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
+
+		/* Read EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+						EDID_HEADER_PATTERN,
+						EDID_BLOCK_LENGTH,
+						&edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		/* Read additional EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR,
+				EDID_BLOCK_LENGTH,
+				EDID_BLOCK_LENGTH,
+				&edid[EDID_BLOCK_LENGTH]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
+					&test_vector);
+		if (test_vector & DPCD_TEST_EDID_READ) {
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_EDID_CHECKSUM,
+				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_RESPONSE,
+				DPCD_TEST_EDID_CHECKSUM_WRITE);
+		}
+	} else {
+		dev_info(dp->dev, "EDID data does not include any extensions.\n");
+
+		/* Read EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR,
+				EDID_HEADER_PATTERN,
+				EDID_BLOCK_LENGTH,
+				&edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TEST_REQUEST,
+			&test_vector);
+		if (test_vector & DPCD_TEST_EDID_READ) {
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_EDID_CHECKSUM,
+				edid[EDID_CHECKSUM]);
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_RESPONSE,
+				DPCD_TEST_EDID_CHECKSUM_WRITE);
+		}
+	}
+
+	dev_err(dp->dev, "EDID Read success!\n");
+	return 0;
+}
+
+static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
+{
+	u8 buf[12];
+	int i;
+	int retval;
+
+	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
+	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+				12, buf);
+	if (retval)
+		return retval;
+
+	/* Read EDID */
+	for (i = 0; i < 3; i++) {
+		retval = exynos_dp_read_edid(dp);
+		if (!retval)
+			break;
+	}
+
+	return retval;
+}
+
+static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
+						bool enable)
+{
+	u8 data;
+
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
+
+	if (enable)
+		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+			DPCD_ENHANCED_FRAME_EN |
+			DPCD_LANE_COUNT_SET(data));
+	else
+		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+			DPCD_LANE_COUNT_SET(data));
+}
+
+static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
+{
+	u8 data;
+	int retval;
+
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+	retval = DPCD_ENHANCED_FRAME_CAP(data);
+
+	return retval;
+}
+
+static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
+{
+	u8 data;
+
+	data = exynos_dp_is_enhanced_mode_available(dp);
+	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
+	exynos_dp_enable_enhanced_mode(dp, data);
+}
+
+static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
+{
+	exynos_dp_set_training_pattern(dp, DP_NONE);
+
+	exynos_dp_write_byte_to_dpcd(dp,
+		DPCD_ADDR_TRAINING_PATTERN_SET,
+		DPCD_TRAINING_PATTERN_DISABLED);
+}
+
+static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
+					int pre_emphasis, int lane)
+{
+	switch (lane) {
+	case 0:
+		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
+		break;
+	case 1:
+		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 2:
+		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 3:
+		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
+		break;
+	}
+}
+
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
+{
+	u8 buf[4];
+	int lane, lane_count, pll_tries, retval;
+
+	lane_count = dp->link_train.lane_count;
+
+	dp->link_train.lt_state = CLOCK_RECOVERY;
+	dp->link_train.eq_loop = 0;
+
+	for (lane = 0; lane < lane_count; lane++)
+		dp->link_train.cr_loop[lane] = 0;
+
+	/* Set link rate and count as you want to establish*/
+	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
+	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
+
+	/* Setup RX configuration */
+	buf[0] = dp->link_train.link_rate;
+	buf[1] = dp->link_train.lane_count;
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+				2, buf);
+	if (retval)
+		return retval;
+
+	/* Set TX pre-emphasis to minimum */
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_lane_pre_emphasis(dp,
+			PRE_EMPHASIS_LEVEL_0, lane);
+
+	/* Wait for PLL lock */
+	pll_tries = 0;
+	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Wait for PLL lock timed out\n");
+			return -ETIMEDOUT;
+		}
+
+		pll_tries++;
+		usleep_range(90, 120);
+	}
+
+	/* Set training pattern 1 */
+	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
+
+	/* Set RX training pattern */
+	retval = exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+	if (retval)
+		return retval;
+
+	for (lane = 0; lane < lane_count; lane++)
+		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
+			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, buf);
+
+	return retval;
+}
+
+static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = link_status[lane>>1];
+
+	return (link_value >> shift) & 0xf;
+}
+
+static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = exynos_dp_get_lane_status(link_status, lane);
+		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+				int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+		return -EINVAL;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = exynos_dp_get_lane_status(link_status, lane);
+		lane_status &= DPCD_CHANNEL_EQ_BITS;
+		if (lane_status != DPCD_CHANNEL_EQ_BITS)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
+							int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane>>1];
+
+	return (link_value >> shift) & 0x3;
+}
+
+static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
+					u8 adjust_request[2],
+					int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane>>1];
+
+	return ((link_value >> shift) & 0xc) >> 2;
+}
+
+static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
+					u8 training_lane_set, int lane)
+{
+	switch (lane) {
+	case 0:
+		exynos_dp_set_lane0_link_training(dp, training_lane_set);
+		break;
+	case 1:
+		exynos_dp_set_lane1_link_training(dp, training_lane_set);
+		break;
+
+	case 2:
+		exynos_dp_set_lane2_link_training(dp, training_lane_set);
+		break;
+
+	case 3:
+		exynos_dp_set_lane3_link_training(dp, training_lane_set);
+		break;
+	}
+}
+
+static unsigned int exynos_dp_get_lane_link_training(
+				struct exynos_dp_device *dp,
+				int lane)
+{
+	u32 reg;
+
+	switch (lane) {
+	case 0:
+		reg = exynos_dp_get_lane0_link_training(dp);
+		break;
+	case 1:
+		reg = exynos_dp_get_lane1_link_training(dp);
+		break;
+	case 2:
+		reg = exynos_dp_get_lane2_link_training(dp);
+		break;
+	case 3:
+		reg = exynos_dp_get_lane3_link_training(dp);
+		break;
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+
+	return reg;
+}
+
+static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
+{
+	exynos_dp_training_pattern_dis(dp);
+	exynos_dp_set_enhanced_mode(dp);
+
+	dp->link_train.lt_state = FAILED;
+}
+
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+					u8 adjust_request[2])
+{
+	int lane, lane_count;
+	u8 voltage_swing, pre_emphasis, training_lane;
+
+	lane_count = dp->link_train.lane_count;
+	for (lane = 0; lane < lane_count; lane++) {
+		voltage_swing = exynos_dp_get_adjust_request_voltage(
+						adjust_request, lane);
+		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+						adjust_request, lane);
+		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+		if (voltage_swing == VOLTAGE_LEVEL_3)
+			training_lane |= DPCD_MAX_SWING_REACHED;
+		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+		dp->link_train.training_lane[lane] = training_lane;
+	}
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u8 voltage_swing, pre_emphasis, training_lane;
+	u8 link_status[2], adjust_request[2];
+
+	usleep_range(100, 101);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
+		/* set training pattern 2 for EQ */
+		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
+
+		retval = exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TRAINING_PATTERN_SET,
+				DPCD_SCRAMBLING_DISABLED |
+				DPCD_TRAINING_PATTERN_2);
+		if (retval)
+			return retval;
+
+		dev_info(dp->dev, "Link Training Clock Recovery success\n");
+		dp->link_train.lt_state = EQUALIZER_TRAINING;
+	} else {
+		for (lane = 0; lane < lane_count; lane++) {
+			training_lane = exynos_dp_get_lane_link_training(
+							dp, lane);
+			voltage_swing = exynos_dp_get_adjust_request_voltage(
+							adjust_request, lane);
+			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+							adjust_request, lane);
+
+			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+					voltage_swing &&
+			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
+					pre_emphasis)
+				dp->link_train.cr_loop[lane]++;
+
+			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+			    voltage_swing == VOLTAGE_LEVEL_3 ||
+			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+					dp->link_train.cr_loop[lane],
+					voltage_swing, pre_emphasis);
+				exynos_dp_reduce_link_rate(dp);
+				return -EIO;
+			}
+		}
+	}
+
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
+			dp->link_train.training_lane);
+	if (retval)
+		return retval;
+
+	return retval;
+}
+
+static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u32 reg;
+	u8 link_align, link_status[2], adjust_request[2];
+
+	usleep_range(400, 401);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	retval = exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+	if (retval)
+		return retval;
+
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+		/* traing pattern Set to Normal */
+		exynos_dp_training_pattern_dis(dp);
+
+		dev_info(dp->dev, "Link Training success!\n");
+
+		exynos_dp_get_link_bandwidth(dp, &reg);
+		dp->link_train.link_rate = reg;
+		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+			dp->link_train.link_rate);
+
+		exynos_dp_get_lane_count(dp, &reg);
+		dp->link_train.lane_count = reg;
+		dev_dbg(dp->dev, "final lane count = %.2x\n",
+			dp->link_train.lane_count);
+
+		/* set enhanced mode if available */
+		exynos_dp_set_enhanced_mode(dp);
+		dp->link_train.lt_state = FINISHED;
+
+		return 0;
+	}
+
+	/* not all locked */
+	dp->link_train.eq_loop++;
+
+	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+		dev_err(dp->dev, "EQ Max loop\n");
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, dp->link_train.training_lane);
+
+	return retval;
+}
+
+static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
+					u8 *bandwidth)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum link rate of Main Link lanes
+	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
+	 */
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
+	*bandwidth = data;
+}
+
+static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
+					u8 *lane_count)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum number of Main Link lanes
+	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
+	 */
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+	*lane_count = DPCD_MAX_LANE_COUNT(data);
+}
+
+static void exynos_dp_init_training(struct exynos_dp_device *dp,
+			enum link_lane_count_type max_lane,
+			enum link_rate_type max_rate)
+{
+	/*
+	 * MACRO_RST must be applied after the PLL_LOCK to avoid
+	 * the DP inter pair skew issue for at least 10 us
+	 */
+	exynos_dp_reset_macro(dp);
+
+	/* Initialize by reading RX's DPCD */
+	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
+	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
+
+	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
+	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
+		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
+			dp->link_train.link_rate);
+		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
+	}
+
+	if (dp->link_train.lane_count == 0) {
+		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
+			dp->link_train.lane_count);
+		dp->link_train.lane_count = (u8)LANE_COUNT1;
+	}
+
+	/* Setup TX lane count & rate */
+	if (dp->link_train.lane_count > max_lane)
+		dp->link_train.lane_count = max_lane;
+	if (dp->link_train.link_rate > max_rate)
+		dp->link_train.link_rate = max_rate;
+
+	/* All DP analog module power up */
+	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+}
+
+static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
+{
+	int retval = 0, training_finished = 0;
+
+	dp->link_train.lt_state = START;
+
+	/* Process here */
+	while (!retval && !training_finished) {
+		switch (dp->link_train.lt_state) {
+		case START:
+			retval = exynos_dp_link_start(dp);
+			if (retval)
+				dev_err(dp->dev, "LT link start failed!\n");
+			break;
+		case CLOCK_RECOVERY:
+			retval = exynos_dp_process_clock_recovery(dp);
+			if (retval)
+				dev_err(dp->dev, "LT CR failed!\n");
+			break;
+		case EQUALIZER_TRAINING:
+			retval = exynos_dp_process_equalizer_training(dp);
+			if (retval)
+				dev_err(dp->dev, "LT EQ failed!\n");
+			break;
+		case FINISHED:
+			training_finished = 1;
+			break;
+		case FAILED:
+			return -EREMOTEIO;
+		}
+	}
+	if (retval)
+		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
+
+	return retval;
+}
+
+static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
+				u32 count,
+				u32 bwtype)
+{
+	int i;
+	int retval;
+
+	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
+		exynos_dp_init_training(dp, count, bwtype);
+		retval = exynos_dp_sw_link_training(dp);
+		if (retval == 0)
+			break;
+
+		usleep_range(100, 110);
+	}
+
+	return retval;
+}
+
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
+{
+	int retval = 0;
+	int timeout_loop = 0;
+	int done_count = 0;
+
+	exynos_dp_config_video_slave_mode(dp);
+
+	exynos_dp_set_video_color_format(dp);
+
+	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		dev_err(dp->dev, "PLL is not locked yet.\n");
+		return -EINVAL;
+	}
+
+	for (;;) {
+		timeout_loop++;
+		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
+			break;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1, 2);
+	}
+
+	/* Set to use the register calculated M/N video */
+	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
+
+	/* For video bist, Video timing must be generated by register */
+	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
+
+	/* Disable video mute */
+	exynos_dp_enable_video_mute(dp, 0);
+
+	/* Configure video slave mode */
+	exynos_dp_enable_video_master(dp, 0);
+
+	/* Enable video */
+	exynos_dp_start_video(dp);
+
+	timeout_loop = 0;
+
+	for (;;) {
+		timeout_loop++;
+		if (exynos_dp_is_video_stream_on(dp) == 0) {
+			done_count++;
+			if (done_count > 10)
+				break;
+		} else if (done_count) {
+			done_count = 0;
+		}
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1000, 1001);
+	}
+
+	if (retval != 0)
+		dev_err(dp->dev, "Video stream is not detected!\n");
+
+	return retval;
+}
+
+static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
+{
+	u8 data;
+
+	if (enable) {
+		exynos_dp_enable_scrambling(dp);
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			&data);
+		exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
+	} else {
+		exynos_dp_disable_scrambling(dp);
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			&data);
+		exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			(u8)(data | DPCD_SCRAMBLING_DISABLED));
+	}
+}
+
+static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
+{
+	struct exynos_dp_device *dp = arg;
+
+	enum dp_irq_type irq_type;
+
+	irq_type = exynos_dp_get_irq_type(dp);
+	switch (irq_type) {
+	case DP_IRQ_TYPE_HP_CABLE_IN:
+		dev_dbg(dp->dev, "Received irq - cable in\n");
+		schedule_work(&dp->hotplug_work);
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CABLE_OUT:
+		dev_dbg(dp->dev, "Received irq - cable out\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CHANGE:
+		/*
+		 * We get these change notifications once in a while, but there
+		 * is nothing we can do with them. Just ignore it for now and
+		 * only handle cable changes.
+		 */
+		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	default:
+		dev_err(dp->dev, "Received irq - unknown type!\n");
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+	struct exynos_dp_device *dp;
+	int ret;
+
+	dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+	ret = exynos_dp_detect_hpd(dp);
+	if (ret) {
+		/* Cable has been disconnected, we're done */
+		return;
+	}
+
+	ret = exynos_dp_handle_edid(dp);
+	if (ret) {
+		dev_err(dp->dev, "unable to handle edid\n");
+		return;
+	}
+
+	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+					dp->video_info->link_rate);
+	if (ret) {
+		dev_err(dp->dev, "unable to do link train\n");
+		return;
+	}
+
+	exynos_dp_enable_scramble(dp, 1);
+	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+	exynos_dp_enable_enhanced_mode(dp, 1);
+
+	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+	exynos_dp_init_video(dp);
+	ret = exynos_dp_config_video(dp);
+	if (ret)
+		dev_err(dp->dev, "unable to config video\n");
+}
+
+static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+	struct device_node *dp_node = dev->of_node;
+	struct video_info *dp_video_config;
+
+	dp_video_config = devm_kzalloc(dev,
+				sizeof(*dp_video_config), GFP_KERNEL);
+	if (!dp_video_config) {
+		dev_err(dev, "memory allocation for video config failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dp_video_config->h_sync_polarity =
+		of_property_read_bool(dp_node, "hsync-active-high");
+
+	dp_video_config->v_sync_polarity =
+		of_property_read_bool(dp_node, "vsync-active-high");
+
+	dp_video_config->interlaced =
+		of_property_read_bool(dp_node, "interlaced");
+
+	if (of_property_read_u32(dp_node, "samsung,color-space",
+				&dp_video_config->color_space)) {
+		dev_err(dev, "failed to get color-space\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+				&dp_video_config->dynamic_range)) {
+		dev_err(dev, "failed to get dynamic-range\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+				&dp_video_config->ycbcr_coeff)) {
+		dev_err(dev, "failed to get ycbcr-coeff\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,color-depth",
+				&dp_video_config->color_depth)) {
+		dev_err(dev, "failed to get color-depth\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,link-rate",
+				&dp_video_config->link_rate)) {
+		dev_err(dev, "failed to get link-rate\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,lane-count",
+				&dp_video_config->lane_count)) {
+		dev_err(dev, "failed to get lane-count\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return dp_video_config;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
+	u32 phy_base;
+	int ret = 0;
+
+	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
+	if (!dp_phy_node) {
+		dp->phy = devm_phy_get(dp->dev, "dp");
+		if (IS_ERR(dp->phy))
+			return PTR_ERR(dp->phy);
+		else
+			return 0;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+				&dp->enable_mask)) {
+		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dp->phy_addr = ioremap(phy_base, SZ_4);
+	if (!dp->phy_addr) {
+		dev_err(dp->dev, "failed to ioremap dp-phy\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+err:
+	of_node_put(dp_phy_node);
+
+	return ret;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	if (dp->phy) {
+		phy_power_on(dp->phy);
+	} else if (dp->phy_addr) {
+		u32 reg;
+
+		reg = __raw_readl(dp->phy_addr);
+		reg |= dp->enable_mask;
+		__raw_writel(reg, dp->phy_addr);
+	}
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	if (dp->phy) {
+		phy_power_off(dp->phy);
+	} else if (dp->phy_addr) {
+		u32 reg;
+
+		reg = __raw_readl(dp->phy_addr);
+		reg &= ~(dp->enable_mask);
+		__raw_writel(reg, dp->phy_addr);
+	}
+}
+
+static int exynos_dp_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct exynos_dp_device *dp;
+
+	int ret = 0;
+
+	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+				GFP_KERNEL);
+	if (!dp) {
+		dev_err(&pdev->dev, "no memory for device data\n");
+		return -ENOMEM;
+	}
+
+	dp->dev = &pdev->dev;
+
+	dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
+	if (IS_ERR(dp->video_info))
+		return PTR_ERR(dp->video_info);
+
+	ret = exynos_dp_dt_parse_phydata(dp);
+	if (ret)
+		return ret;
+
+	dp->clock = devm_clk_get(&pdev->dev, "dp");
+	if (IS_ERR(dp->clock)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(dp->clock);
+	}
+
+	clk_prepare_enable(dp->clock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dp->reg_base))
+		return PTR_ERR(dp->reg_base);
+
+	dp->irq = platform_get_irq(pdev, 0);
+	if (dp->irq == -ENXIO) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		return -ENODEV;
+	}
+
+	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
+
+	exynos_dp_phy_init(dp);
+
+	exynos_dp_init_dp(dp);
+
+	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+				"exynos-dp", dp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, dp);
+
+	return 0;
+}
+
+static int exynos_dp_remove(struct platform_device *pdev)
+{
+	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+
+	flush_work(&dp->hotplug_work);
+
+	exynos_dp_phy_exit(dp);
+
+	clk_disable_unprepare(dp->clock);
+
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_dp_suspend(struct device *dev)
+{
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+
+	disable_irq(dp->irq);
+
+	flush_work(&dp->hotplug_work);
+
+	exynos_dp_phy_exit(dp);
+
+	clk_disable_unprepare(dp->clock);
+
+	return 0;
+}
+
+static int exynos_dp_resume(struct device *dev)
+{
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+
+	exynos_dp_phy_init(dp);
+
+	clk_prepare_enable(dp->clock);
+
+	exynos_dp_init_dp(dp);
+
+	enable_irq(dp->irq);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_dp_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
+};
+
+static const struct of_device_id exynos_dp_match[] = {
+	{ .compatible = "samsung,exynos5-dp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
+static struct platform_driver exynos_dp_driver = {
+	.probe		= exynos_dp_probe,
+	.remove		= exynos_dp_remove,
+	.driver		= {
+		.name	= "exynos-dp",
+		.owner	= THIS_MODULE,
+		.pm	= &exynos_dp_pm_ops,
+		.of_match_table = exynos_dp_match,
+	},
+};
+
+module_platform_driver(exynos_dp_driver);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DP Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/exynos/exynos_dp_core.h b/drivers/video/fbdev/exynos/exynos_dp_core.h
new file mode 100644
index 000000000000..607e36d0c147
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_dp_core.h
@@ -0,0 +1,320 @@
+/*
+ * Header file for Samsung DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.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 _EXYNOS_DP_CORE_H
+#define _EXYNOS_DP_CORE_H
+
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+enum link_rate_type {
+	LINK_RATE_1_62GBPS = 0x06,
+	LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+	LANE_COUNT1 = 1,
+	LANE_COUNT2 = 2,
+	LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+	START,
+	CLOCK_RECOVERY,
+	EQUALIZER_TRAINING,
+	FINISHED,
+	FAILED
+};
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7,
+	D10_2,
+	TRAINING_PTN1,
+	TRAINING_PTN2,
+	DP_NONE
+};
+
+enum color_space {
+	COLOR_RGB,
+	COLOR_YCBCR422,
+	COLOR_YCBCR444
+};
+
+enum color_depth {
+	COLOR_6,
+	COLOR_8,
+	COLOR_10,
+	COLOR_12
+};
+
+enum color_coefficient {
+	COLOR_YCBCR601,
+	COLOR_YCBCR709
+};
+
+enum dynamic_range {
+	VESA,
+	CEA
+};
+
+enum pll_status {
+	PLL_UNLOCKED,
+	PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+	CALCULATED_M,
+	REGISTER_M
+};
+
+enum video_timing_recognition_type {
+	VIDEO_TIMING_FROM_CAPTURE,
+	VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+	AUX_BLOCK,
+	CH0_BLOCK,
+	CH1_BLOCK,
+	CH2_BLOCK,
+	CH3_BLOCK,
+	ANALOG_TOTAL,
+	POWER_ALL
+};
+
+enum dp_irq_type {
+	DP_IRQ_TYPE_HP_CABLE_IN,
+	DP_IRQ_TYPE_HP_CABLE_OUT,
+	DP_IRQ_TYPE_HP_CHANGE,
+	DP_IRQ_TYPE_UNKNOWN,
+};
+
+struct video_info {
+	char *name;
+
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+
+	enum color_space color_space;
+	enum dynamic_range dynamic_range;
+	enum color_coefficient ycbcr_coeff;
+	enum color_depth color_depth;
+
+	enum link_rate_type link_rate;
+	enum link_lane_count_type lane_count;
+};
+
+struct link_train {
+	int eq_loop;
+	int cr_loop[4];
+
+	u8 link_rate;
+	u8 lane_count;
+	u8 training_lane[4];
+
+	enum link_training_state lt_state;
+};
+
+struct exynos_dp_device {
+	struct device		*dev;
+	struct clk		*clock;
+	unsigned int		irq;
+	void __iomem		*reg_base;
+	void __iomem		*phy_addr;
+	unsigned int		enable_mask;
+
+	struct video_info	*video_info;
+	struct link_train	link_train;
+	struct work_struct	hotplug_work;
+	struct phy		*phy;
+};
+
+/* exynos_dp_reg.c */
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_stop_video(struct exynos_dp_device *dp);
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
+void exynos_dp_reset(struct exynos_dp_device *dp);
+void exynos_dp_swreset(struct exynos_dp_device *dp);
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+				enum analog_power_block block,
+				bool enable);
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
+void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
+void exynos_dp_reset_aux(struct exynos_dp_device *dp);
+void exynos_dp_init_aux(struct exynos_dp_device *dp);
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char data);
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char *data);
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[]);
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[]);
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr);
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int *data);
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char edid[]);
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+				 enum pattern_set pattern);
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
+void exynos_dp_reset_macro(struct exynos_dp_device *dp);
+void exynos_dp_init_video(struct exynos_dp_device *dp);
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+			enum clock_recovery_m_value_type type,
+			u32 m_value,
+			u32 n_value);
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_start_video(struct exynos_dp_device *dp);
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
+
+/* I2C EDID Chip ID, Slave Address */
+#define I2C_EDID_DEVICE_ADDR			0x50
+#define I2C_E_EDID_DEVICE_ADDR			0x30
+
+#define EDID_BLOCK_LENGTH			0x80
+#define EDID_HEADER_PATTERN			0x00
+#define EDID_EXTENSION_FLAG			0x7e
+#define EDID_CHECKSUM				0x7f
+
+/* Definition for DPCD Register */
+#define DPCD_ADDR_DPCD_REV			0x0000
+#define DPCD_ADDR_MAX_LINK_RATE			0x0001
+#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
+#define DPCD_ADDR_LINK_BW_SET			0x0100
+#define DPCD_ADDR_LANE_COUNT_SET		0x0101
+#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
+#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
+#define DPCD_ADDR_LANE0_1_STATUS		0x0202
+#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
+#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
+#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
+#define DPCD_ADDR_TEST_REQUEST			0x0218
+#define DPCD_ADDR_TEST_RESPONSE			0x0260
+#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
+#define DPCD_ADDR_SINK_POWER_STATE		0x0600
+
+/* DPCD_ADDR_MAX_LANE_COUNT */
+#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
+#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
+
+/* DPCD_ADDR_LANE_COUNT_SET */
+#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
+#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
+
+/* DPCD_ADDR_TRAINING_PATTERN_SET */
+#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
+#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
+#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
+#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
+#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
+
+/* DPCD_ADDR_TRAINING_LANE0_SET */
+#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
+#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
+#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
+#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
+#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
+#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
+#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
+#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
+
+/* DPCD_ADDR_LANE0_1_STATUS */
+#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
+#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
+#define DPCD_LANE_CR_DONE			(0x1 << 0)
+#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
+						 DPCD_LANE_CHANNEL_EQ_DONE|\
+						 DPCD_LANE_SYMBOL_LOCKED)
+
+/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
+#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
+#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
+
+/* DPCD_ADDR_TEST_REQUEST */
+#define DPCD_TEST_EDID_READ			(0x1 << 2)
+
+/* DPCD_ADDR_TEST_RESPONSE */
+#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
+
+/* DPCD_ADDR_SINK_POWER_STATE */
+#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
+#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
+
+#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/fbdev/exynos/exynos_dp_reg.c b/drivers/video/fbdev/exynos/exynos_dp_reg.c
new file mode 100644
index 000000000000..b70da5052ff0
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_dp_reg.c
@@ -0,0 +1,1243 @@
+/*
+ * Samsung DP (Display port) register interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.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/device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "exynos_dp_core.h"
+#include "exynos_dp_reg.h"
+
+#define COMMON_INT_MASK_1	0
+#define COMMON_INT_MASK_2	0
+#define COMMON_INT_MASK_3	0
+#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK		INT_HPD
+
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+		reg |= HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+		reg &= ~HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	}
+}
+
+void exynos_dp_stop_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	reg &= ~VIDEO_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable)
+		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
+			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
+	else
+		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
+			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
+
+	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
+}
+
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = TX_TERMINAL_CTRL_50_OHM;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
+
+	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
+
+	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
+
+	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
+		TX_CUR1_2X | TX_CUR_16_MA;
+	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
+
+	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
+		CH1_AMP_400_MV | CH0_AMP_400_MV;
+	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
+}
+
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
+{
+	/* Set interrupt pin assertion polarity as high */
+	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
+
+	/* Clear pending regisers */
+	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
+	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
+	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	/* 0:mask,1: unmask */
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+void exynos_dp_reset(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	exynos_dp_stop_video(dp);
+	exynos_dp_enable_video_mute(dp, 0);
+
+	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
+		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
+		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
+		SERDES_FIFO_FUNC_EN_N |
+		LS_CLK_DOMAIN_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+
+	usleep_range(20, 30);
+
+	exynos_dp_lane_swap(dp, 0);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
+	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
+
+	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
+	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
+
+	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
+	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
+
+	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
+	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
+
+	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_swreset(struct exynos_dp_device *dp)
+{
+	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
+}
+
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* 0: mask, 1: unmask */
+	reg = COMMON_INT_MASK_1;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+
+	reg = COMMON_INT_MASK_2;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+
+	reg = COMMON_INT_MASK_3;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+
+	reg = COMMON_INT_MASK_4;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+
+	reg = INT_STA_MASK;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+	if (reg & PLL_LOCK)
+		return PLL_LOCKED;
+	else
+		return PLL_UNLOCKED;
+}
+
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+		reg |= DP_PLL_PD;
+		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+		reg &= ~DP_PLL_PD;
+		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+	}
+}
+
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+				enum analog_power_block block,
+				bool enable)
+{
+	u32 reg;
+
+	switch (block) {
+	case AUX_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= AUX_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~AUX_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH0_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH1_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH1_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH1_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH2_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH2_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH2_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH3_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH3_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH3_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case ANALOG_TOTAL:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= DP_PHY_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~DP_PHY_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case POWER_ALL:
+		if (enable) {
+			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
+				CH1_PD | CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
+{
+	u32 reg;
+	int timeout_loop = 0;
+
+	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+
+	reg = PLL_LOCK_CHG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
+	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+
+	/* Power up PLL */
+	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		exynos_dp_set_pll_power_down(dp, 0);
+
+		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+			timeout_loop++;
+			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+				dev_err(dp->dev, "failed to get pll lock status\n");
+				return;
+			}
+			usleep_range(10, 20);
+		}
+	}
+
+	/* Enable Serdes FIFO function and Link symbol clock domain module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
+		| AUX_FUNC_EN_N);
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+	reg = INT_HPD;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	exynos_dp_clear_hotplug_interrupts(dp);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	reg &= ~(F_HPD | HPD_CTRL);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+}
+
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Parse hotplug interrupt status register */
+	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+	if (reg & PLUG)
+		return DP_IRQ_TYPE_HP_CABLE_IN;
+
+	if (reg & HPD_LOST)
+		return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+	if (reg & HOTPLUG_CHG)
+		return DP_IRQ_TYPE_HP_CHANGE;
+
+	return DP_IRQ_TYPE_UNKNOWN;
+}
+
+void exynos_dp_reset_aux(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Disable AUX channel module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg |= AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_init_aux(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Clear inerrupts related to AUX channel */
+	reg = RPLY_RECEIV | AUX_ERR;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	exynos_dp_reset_aux(dp);
+
+	/* Disable AUX transaction H/W retry */
+	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
+		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
+
+	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
+
+	/* Enable AUX channel module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg &= ~AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	if (reg & HPD_STATUS)
+		return 0;
+
+	return -EINVAL;
+}
+
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+	reg &= ~SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+}
+
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
+{
+	int reg;
+	int retval = 0;
+	int timeout_loop = 0;
+
+	/* Enable AUX CH operation */
+	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+	reg |= AUX_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+	/* Is AUX CH command reply received? */
+	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+	while (!(reg & RPLY_RECEIV)) {
+		timeout_loop++;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "AUX CH command reply failed!\n");
+			return -ETIMEDOUT;
+		}
+		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+		usleep_range(10, 11);
+	}
+
+	/* Clear interrupt source for AUX CH command reply */
+	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	/* Clear interrupt source for AUX CH access error */
+	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+	if (reg & AUX_ERR) {
+		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
+		return -EREMOTEIO;
+	}
+
+	/* Check AUX CH error access status */
+	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
+	if ((reg & AUX_STATUS_MASK) != 0) {
+		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
+			reg & AUX_STATUS_MASK);
+		return -EREMOTEIO;
+	}
+
+	return retval;
+}
+
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+		/* Write data buffer */
+		reg = (unsigned int)data;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+		/*
+		 * Set DisplayPort transaction and write 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	return retval;
+}
+
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+		/*
+		 * Set DisplayPort transaction and read 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	/* Read data buffer */
+	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+	*data = (unsigned char)(reg & 0xff);
+
+	return retval;
+}
+
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+			     cur_data_idx++) {
+				reg = data[start_offset + cur_data_idx];
+				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
+							  + 4 * cur_data_idx);
+			}
+
+			/*
+			 * Set DisplayPort transaction and write
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = exynos_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+			else
+				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+					__func__);
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		/* AUX CH Request Transaction process */
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+			/*
+			 * Set DisplayPort transaction and read
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = exynos_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+			else
+				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+					__func__);
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+		    cur_data_idx++) {
+			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			data[start_offset + cur_data_idx] =
+				(unsigned char)reg;
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr)
+{
+	u32 reg;
+	int retval;
+
+	/* Set EDID device address */
+	reg = device_addr;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+	/* Set offset from base address of EDID device */
+	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+	/*
+	 * Set I2C transaction and write address
+	 * If bit 3 is 1, DisplayPort transaction.
+	 * If Bit 3 is 0, I2C transaction.
+	 */
+	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
+		AUX_TX_COMM_WRITE;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+	/* Start AUX transaction */
+	retval = exynos_dp_start_aux_transaction(dp);
+	if (retval != 0)
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+
+	return retval;
+}
+
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select EDID device */
+		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
+		if (retval != 0)
+			continue;
+
+		/*
+		 * Set I2C transaction and read data
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_I2C_TRANSACTION |
+			AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	/* Read data */
+	if (retval == 0)
+		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+	return retval;
+}
+
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char edid[])
+{
+	u32 reg;
+	unsigned int i, j;
+	unsigned int cur_data_idx;
+	unsigned int defer = 0;
+	int retval = 0;
+
+	for (i = 0; i < count; i += 16) {
+		for (j = 0; j < 3; j++) {
+			/* Clear AUX CH data buffer */
+			reg = BUF_CLR;
+			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+			/* Set normal AUX CH command */
+			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+			reg &= ~ADDR_ONLY;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+			/*
+			 * If Rx sends defer, Tx sends only reads
+			 * request without sending address
+			 */
+			if (!defer)
+				retval = exynos_dp_select_i2c_device(dp,
+						device_addr, reg_addr + i);
+			else
+				defer = 0;
+
+			if (retval == 0) {
+				/*
+				 * Set I2C transaction and write data
+				 * If bit 3 is 1, DisplayPort transaction.
+				 * If Bit 3 is 0, I2C transaction.
+				 */
+				reg = AUX_LENGTH(16) |
+					AUX_TX_COMM_I2C_TRANSACTION |
+					AUX_TX_COMM_READ;
+				writel(reg, dp->reg_base +
+					EXYNOS_DP_AUX_CH_CTL_1);
+
+				/* Start AUX transaction */
+				retval = exynos_dp_start_aux_transaction(dp);
+				if (retval == 0)
+					break;
+				else
+					dev_dbg(dp->dev,
+						"%s: Aux Transaction fail!\n",
+						__func__);
+			}
+			/* Check if Rx sends defer */
+			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
+			if (reg == AUX_RX_COMM_AUX_DEFER ||
+				reg == AUX_RX_COMM_I2C_DEFER) {
+				dev_err(dp->dev, "Defer: %d\n\n", reg);
+				defer = 1;
+			}
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			edid[i + cur_data_idx] = (unsigned char)reg;
+		}
+	}
+
+	return retval;
+}
+
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
+{
+	u32 reg;
+
+	reg = bwtype;
+	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
+		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+}
+
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+	*bwtype = reg;
+}
+
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
+{
+	u32 reg;
+
+	reg = count;
+	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+}
+
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+	*count = reg;
+}
+
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg |= ENHANCED;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg &= ~ENHANCED;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+	}
+}
+
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+				 enum pattern_set pattern)
+{
+	u32 reg;
+
+	switch (pattern) {
+	case PRBS7:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case D10_2:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN1:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN2:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case DP_NONE:
+		reg = SCRAMBLING_ENABLE |
+			LINK_QUAL_PATTERN_SET_DISABLE |
+			SW_TRAINING_PATTERN_SET_NORMAL;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	default:
+		break;
+	}
+}
+
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+	return reg;
+}
+
+void exynos_dp_reset_macro(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
+	reg |= MACRO_RST;
+	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+	/* 10 us is the minimum reset time. */
+	usleep_range(10, 20);
+
+	reg &= ~MACRO_RST;
+	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+}
+
+void exynos_dp_init_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	reg = CHA_CRI(4) | CHA_CTRL;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
+}
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Configure the input color depth, color space, dynamic range */
+	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+		(dp->video_info->color_depth << IN_BPC_SHIFT) |
+		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
+
+	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+	reg &= ~IN_YC_COEFFI_MASK;
+	if (dp->video_info->ycbcr_coeff)
+		reg |= IN_YC_COEFFI_ITU709;
+	else
+		reg |= IN_YC_COEFFI_ITU601;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+}
+
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	if (!(reg & DET_STA)) {
+		dev_dbg(dp->dev, "Input stream clock not detected.\n");
+		return -EINVAL;
+	}
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
+
+	if (reg & CHA_STA) {
+		dev_dbg(dp->dev, "Input stream clk is changing\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+		enum clock_recovery_m_value_type type,
+		u32 m_value,
+		u32 n_value)
+{
+	u32 reg;
+
+	if (type == REGISTER_M) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg |= FIX_M_VID;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg = m_value & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
+		reg = (m_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
+		reg = (m_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
+
+		reg = n_value & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
+		reg = (n_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
+		reg = (n_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
+	} else  {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg &= ~FIX_M_VID;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
+		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
+		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
+	}
+}
+
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
+{
+	u32 reg;
+
+	if (type == VIDEO_TIMING_FROM_CAPTURE) {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+		reg &= ~FORMAT_SEL;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+		reg |= FORMAT_SEL;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	}
+}
+
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
+		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MODE_SLAVE_MODE;
+		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+	}
+}
+
+void exynos_dp_start_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	reg |= VIDEO_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	if (!(reg & STRM_VALID)) {
+		dev_dbg(dp->dev, "Input video stream is not detected.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
+	reg |= MASTER_VID_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~INTERACE_SCAN_CFG;
+	reg |= (dp->video_info->interlaced << 2);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~VSYNC_POLARITY_CFG;
+	reg |= (dp->video_info->v_sync_polarity << 1);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~HSYNC_POLARITY_CFG;
+	reg |= (dp->video_info->h_sync_polarity << 0);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
+	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+	reg &= ~SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
+
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+	reg |= SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
diff --git a/drivers/video/fbdev/exynos/exynos_dp_reg.h b/drivers/video/fbdev/exynos/exynos_dp_reg.h
new file mode 100644
index 000000000000..2e9bd0e0b9f2
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_dp_reg.h
@@ -0,0 +1,366 @@
+/*
+ * Register definition file for Samsung DP driver
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@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_DP_REG_H
+#define _EXYNOS_DP_REG_H
+
+#define EXYNOS_DP_TX_SW_RESET			0x14
+#define EXYNOS_DP_FUNC_EN_1			0x18
+#define EXYNOS_DP_FUNC_EN_2			0x1C
+#define EXYNOS_DP_VIDEO_CTL_1			0x20
+#define EXYNOS_DP_VIDEO_CTL_2			0x24
+#define EXYNOS_DP_VIDEO_CTL_3			0x28
+
+#define EXYNOS_DP_VIDEO_CTL_8			0x3C
+#define EXYNOS_DP_VIDEO_CTL_10			0x44
+
+#define EXYNOS_DP_LANE_MAP			0x35C
+
+#define EXYNOS_DP_ANALOG_CTL_1			0x370
+#define EXYNOS_DP_ANALOG_CTL_2			0x374
+#define EXYNOS_DP_ANALOG_CTL_3			0x378
+#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
+#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
+
+#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
+
+#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
+#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
+#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
+#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
+#define EXYNOS_DP_INT_STA			0x3DC
+#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
+#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
+#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
+#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
+#define EXYNOS_DP_INT_STA_MASK			0x3F8
+#define EXYNOS_DP_INT_CTL			0x3FC
+
+#define EXYNOS_DP_SYS_CTL_1			0x600
+#define EXYNOS_DP_SYS_CTL_2			0x604
+#define EXYNOS_DP_SYS_CTL_3			0x608
+#define EXYNOS_DP_SYS_CTL_4			0x60C
+
+#define EXYNOS_DP_PKT_SEND_CTL			0x640
+#define EXYNOS_DP_HDCP_CTL			0x648
+
+#define EXYNOS_DP_LINK_BW_SET			0x680
+#define EXYNOS_DP_LANE_COUNT_SET		0x684
+#define EXYNOS_DP_TRAINING_PTN_SET		0x688
+#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
+#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
+#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
+#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
+
+#define EXYNOS_DP_DEBUG_CTL			0x6C0
+#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
+#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
+#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
+
+#define EXYNOS_DP_M_VID_0			0x700
+#define EXYNOS_DP_M_VID_1			0x704
+#define EXYNOS_DP_M_VID_2			0x708
+#define EXYNOS_DP_N_VID_0			0x70C
+#define EXYNOS_DP_N_VID_1			0x710
+#define EXYNOS_DP_N_VID_2			0x714
+
+#define EXYNOS_DP_PLL_CTL			0x71C
+#define EXYNOS_DP_PHY_PD			0x720
+#define EXYNOS_DP_PHY_TEST			0x724
+
+#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
+#define EXYNOS_DP_AUDIO_MARGIN			0x73C
+
+#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
+#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
+#define EXYNOS_DP_AUX_CH_STA			0x780
+#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
+#define EXYNOS_DP_AUX_RX_COMM			0x78C
+#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
+#define EXYNOS_DP_AUX_CH_CTL_1			0x794
+#define EXYNOS_DP_AUX_ADDR_7_0			0x798
+#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
+#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
+#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
+
+#define EXYNOS_DP_BUF_DATA_0			0x7C0
+
+#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
+
+/* EXYNOS_DP_TX_SW_RESET */
+#define RESET_DP_TX				(0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_1 */
+#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
+#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
+#define AUD_FUNC_EN_N				(0x1 << 3)
+#define HDCP_FUNC_EN_N				(0x1 << 2)
+#define CRC_FUNC_EN_N				(0x1 << 1)
+#define SW_FUNC_EN_N				(0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_2 */
+#define SSC_FUNC_EN_N				(0x1 << 7)
+#define AUX_FUNC_EN_N				(0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define VIDEO_EN				(0x1 << 7)
+#define HDCP_VIDEO_MUTE				(0x1 << 6)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define IN_D_RANGE_MASK				(0x1 << 7)
+#define IN_D_RANGE_SHIFT			(7)
+#define IN_D_RANGE_CEA				(0x1 << 7)
+#define IN_D_RANGE_VESA				(0x0 << 7)
+#define IN_BPC_MASK				(0x7 << 4)
+#define IN_BPC_SHIFT				(4)
+#define IN_BPC_12_BITS				(0x3 << 4)
+#define IN_BPC_10_BITS				(0x2 << 4)
+#define IN_BPC_8_BITS				(0x1 << 4)
+#define IN_BPC_6_BITS				(0x0 << 4)
+#define IN_COLOR_F_MASK				(0x3 << 0)
+#define IN_COLOR_F_SHIFT			(0)
+#define IN_COLOR_F_YCBCR444			(0x2 << 0)
+#define IN_COLOR_F_YCBCR422			(0x1 << 0)
+#define IN_COLOR_F_RGB				(0x0 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_3 */
+#define IN_YC_COEFFI_MASK			(0x1 << 7)
+#define IN_YC_COEFFI_SHIFT			(7)
+#define IN_YC_COEFFI_ITU709			(0x1 << 7)
+#define IN_YC_COEFFI_ITU601			(0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
+#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
+
+/* EXYNOS_DP_VIDEO_CTL_8 */
+#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
+#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_10 */
+#define FORMAT_SEL				(0x1 << 4)
+#define INTERACE_SCAN_CFG			(0x1 << 2)
+#define VSYNC_POLARITY_CFG			(0x1 << 1)
+#define HSYNC_POLARITY_CFG			(0x1 << 0)
+
+/* EXYNOS_DP_LANE_MAP */
+#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
+#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
+#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
+#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
+#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
+#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
+#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
+#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
+#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
+#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
+#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
+#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
+#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
+#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
+#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
+#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_1 */
+#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
+
+/* EXYNOS_DP_ANALOG_CTL_2 */
+#define SEL_24M					(0x1 << 3)
+#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_3 */
+#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
+#define VCO_BIT_600_MICRO			(0x5 << 0)
+
+/* EXYNOS_DP_PLL_FILTER_CTL_1 */
+#define PD_RING_OSC				(0x1 << 6)
+#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
+#define TX_CUR1_2X				(0x1 << 2)
+#define TX_CUR_16_MA				(0x3 << 0)
+
+/* EXYNOS_DP_TX_AMP_TUNING_CTL */
+#define CH3_AMP_400_MV				(0x0 << 24)
+#define CH2_AMP_400_MV				(0x0 << 16)
+#define CH1_AMP_400_MV				(0x0 << 8)
+#define CH0_AMP_400_MV				(0x0 << 0)
+
+/* EXYNOS_DP_AUX_HW_RETRY_CTL */
+#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
+#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
+#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
+#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
+#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
+#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
+#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_1 */
+#define VSYNC_DET				(0x1 << 7)
+#define PLL_LOCK_CHG				(0x1 << 6)
+#define SPDIF_ERR				(0x1 << 5)
+#define SPDIF_UNSTBL				(0x1 << 4)
+#define VID_FORMAT_CHG				(0x1 << 3)
+#define AUD_CLK_CHG				(0x1 << 2)
+#define VID_CLK_CHG				(0x1 << 1)
+#define SW_INT					(0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_2 */
+#define ENC_EN_CHG				(0x1 << 6)
+#define HW_BKSV_RDY				(0x1 << 3)
+#define HW_SHA_DONE				(0x1 << 2)
+#define HW_AUTH_STATE_CHG			(0x1 << 1)
+#define HW_AUTH_DONE				(0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_3 */
+#define AFIFO_UNDER				(0x1 << 7)
+#define AFIFO_OVER				(0x1 << 6)
+#define R0_CHK_FLAG				(0x1 << 5)
+
+/* EXYNOS_DP_COMMON_INT_STA_4 */
+#define PSR_ACTIVE				(0x1 << 7)
+#define PSR_INACTIVE				(0x1 << 6)
+#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
+#define HOTPLUG_CHG				(0x1 << 2)
+#define HPD_LOST				(0x1 << 1)
+#define PLUG					(0x1 << 0)
+
+/* EXYNOS_DP_INT_STA */
+#define INT_HPD					(0x1 << 6)
+#define HW_TRAINING_FINISH			(0x1 << 5)
+#define RPLY_RECEIV				(0x1 << 1)
+#define AUX_ERR					(0x1 << 0)
+
+/* EXYNOS_DP_INT_CTL */
+#define SOFT_INT_CTRL				(0x1 << 2)
+#define INT_POL1				(0x1 << 1)
+#define INT_POL0				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_1 */
+#define DET_STA					(0x1 << 2)
+#define FORCE_DET				(0x1 << 1)
+#define DET_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_2 */
+#define CHA_CRI(x)				(((x) & 0xf) << 4)
+#define CHA_STA					(0x1 << 2)
+#define FORCE_CHA				(0x1 << 1)
+#define CHA_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_3 */
+#define HPD_STATUS				(0x1 << 6)
+#define F_HPD					(0x1 << 5)
+#define HPD_CTRL				(0x1 << 4)
+#define HDCP_RDY				(0x1 << 3)
+#define STRM_VALID				(0x1 << 2)
+#define F_VALID					(0x1 << 1)
+#define VALID_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_4 */
+#define FIX_M_AUD				(0x1 << 4)
+#define ENHANCED				(0x1 << 3)
+#define FIX_M_VID				(0x1 << 2)
+#define M_VID_UPDATE_CTRL			(0x3 << 0)
+
+/* EXYNOS_DP_TRAINING_PTN_SET */
+#define SCRAMBLER_TYPE				(0x1 << 9)
+#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
+#define SCRAMBLING_DISABLE			(0x1 << 5)
+#define SCRAMBLING_ENABLE			(0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
+
+/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
+#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
+#define PRE_EMPHASIS_SET_SHIFT			(3)
+
+/* EXYNOS_DP_DEBUG_CTL */
+#define PLL_LOCK				(0x1 << 4)
+#define F_PLL_LOCK				(0x1 << 3)
+#define PLL_LOCK_CTRL				(0x1 << 2)
+#define PN_INV					(0x1 << 0)
+
+/* EXYNOS_DP_PLL_CTL */
+#define DP_PLL_PD				(0x1 << 7)
+#define DP_PLL_RESET				(0x1 << 6)
+#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
+#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
+#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
+
+/* EXYNOS_DP_PHY_PD */
+#define DP_PHY_PD				(0x1 << 5)
+#define AUX_PD					(0x1 << 4)
+#define CH3_PD					(0x1 << 3)
+#define CH2_PD					(0x1 << 2)
+#define CH1_PD					(0x1 << 1)
+#define CH0_PD					(0x1 << 0)
+
+/* EXYNOS_DP_PHY_TEST */
+#define MACRO_RST				(0x1 << 5)
+#define CH1_TEST				(0x1 << 1)
+#define CH0_TEST				(0x1 << 0)
+
+/* EXYNOS_DP_AUX_CH_STA */
+#define AUX_BUSY				(0x1 << 4)
+#define AUX_STATUS_MASK				(0xf << 0)
+
+/* EXYNOS_DP_AUX_CH_DEFER_CTL */
+#define DEFER_CTRL_EN				(0x1 << 7)
+#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
+
+/* EXYNOS_DP_AUX_RX_COMM */
+#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
+
+/* EXYNOS_DP_BUFFER_DATA_CTL */
+#define BUF_CLR					(0x1 << 7)
+#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
+
+/* EXYNOS_DP_AUX_CH_CTL_1 */
+#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK			(0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
+#define AUX_TX_COMM_MOT				(0x1 << 2)
+#define AUX_TX_COMM_WRITE			(0x0 << 0)
+#define AUX_TX_COMM_READ			(0x1 << 0)
+
+/* EXYNOS_DP_AUX_ADDR_7_0 */
+#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_15_8 */
+#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_19_16 */
+#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
+
+/* EXYNOS_DP_AUX_CH_CTL_2 */
+#define ADDR_ONLY				(0x1 << 1)
+#define AUX_EN					(0x1 << 0)
+
+/* EXYNOS_DP_SOC_GENERAL_CTL */
+#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
+#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
+#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
+#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
+#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
+#define VIDEO_MODE_MASK				(0x1 << 0)
+#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
+#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
+
+#endif /* _EXYNOS_DP_REG_H */
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..086e02431232
--- /dev/null
+++ b/drivers/video/fbdev/imxfb.c
@@ -0,0 +1,1072 @@
+/*
+ *  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,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..ccd9073f706f
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
@@ -0,0 +1,279 @@
+/*
+ * 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 <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,
+	.pixel_clock	= 13500,
+	.hsw		= 64,
+	.hfp		= 12,
+	.hbp		= 68,
+	.vsw		= 5,
+	.vfp		= 5,
+	.vbp		= 41,
+
+	.interlace	= true,
+};
+
+#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);
+
+	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(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 {
+		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 struct platform_driver tvc_connector_driver = {
+	.probe	= tvc_probe,
+	.remove	= __exit_p(tvc_remove),
+	.driver	= {
+		.name	= "connector-analog-tv",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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..b6c50904038e
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c
@@ -0,0 +1,358 @@
+/*
+ * 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,
+
+	.pixel_clock	= 23500,
+
+	.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(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 {
+		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 struct platform_driver dvi_connector_driver = {
+	.probe	= dvic_probe,
+	.remove	= __exit_p(dvic_remove),
+	.driver	= {
+		.name	= "connector-dvi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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..9abe2c039ae9
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
@@ -0,0 +1,375 @@
+/*
+ * 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 <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,
+	.pixel_clock	= 25175,
+	.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(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 {
+		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 struct platform_driver hdmi_connector_driver = {
+	.probe	= hdmic_probe,
+	.remove	= __exit_p(hdmic_remove),
+	.driver	= {
+		.name	= "connector-hdmi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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..4a291e756be9
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
@@ -0,0 +1,267 @@
+/*
+ * 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 <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);
+	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(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 {
+		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 struct platform_driver tfp410_driver = {
+	.probe	= tfp410_probe,
+	.remove	= __exit_p(tfp410_remove),
+	.driver	= {
+		.name	= "tfp410",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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..d5c936cb217f
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
@@ -0,0 +1,395 @@
+/*
+ * 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 <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(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 {
+		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 struct platform_driver tpd_driver = {
+	.probe	= tpd_probe,
+	.remove	= __exit_p(tpd_remove),
+	.driver	= {
+		.name	= "tpd12s015",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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..b7baafe83aa3
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
@@ -0,0 +1,1336 @@
+/*
+ * 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 <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,
+	};
+
+	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(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 {
+		return -ENODEV;
+	}
+
+	ddata->timings.x_res = 864;
+	ddata->timings.y_res = 480;
+	ddata->timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
+
+	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 struct platform_driver dsicm_driver = {
+	.probe = dsicm_probe,
+	.remove = __exit_p(dsicm_remove),
+	.driver = {
+		.name = "panel-dsi-cm",
+		.owner = THIS_MODULE,
+	},
+};
+
+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..6e8977b18950
--- /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,
+
+	.pixel_clock	= 6500,
+
+	.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..bb217da65c5f
--- /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		23800
+
+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,
+	.pixel_clock	= 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..72a4fb5aa6b1
--- /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,
+
+	.pixel_clock	= 19200,
+
+	.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..8e97d06921ff
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
@@ -0,0 +1,880 @@
+/*
+ * 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 <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,
+	.pixel_clock	= 24000,
+	.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);
+	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(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 {
+		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 struct spi_driver acx565akm_driver = {
+	.driver = {
+		.name	= "acx565akm",
+		.owner	= THIS_MODULE,
+	},
+	.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..9a08908fe998
--- /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,
+	.pixel_clock	= 22153,
+	.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..eadc6529fa3d
--- /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,
+
+	.pixel_clock	= 36000,
+
+	.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..d3aa91bdd6a8
--- /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 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..4e2177962eed
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -0,0 +1,3798 @@
+/*
+ * 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->pixel_clock * 1000);
+
+	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->pixel_clock * 1000) / xtot;
+		vt = (timings->pixel_clock * 1000) / xtot / ytot;
+
+		DSSDBG("pck %u\n", timings->pixel_clock);
+		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 struct platform_driver omap_dispchw_driver = {
+	.remove         = __exit_p(omap_dispchw_remove),
+	.driver         = {
+		.name   = "omapdss_dispc",
+		.owner  = THIS_MODULE,
+		.pm	= &dispc_pm_ops,
+	},
+};
+
+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..f7b5f9561041
--- /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.pixel_clock,
+			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.pixel_clock,
+				&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..669a81fdf58e
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/display.c
@@ -0,0 +1,314 @@
+/*
+ * 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 <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;
+
+	snprintf(dssdev->alias, sizeof(dssdev->alias),
+			"display%d", disp_num_counter++);
+
+	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->pixel_clock = vm->pixelclock / 1000;
+	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->pixel_clock * 1000;
+
+	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..23ef21ffc2c4
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -0,0 +1,728 @@
+/*
+ * 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 <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;
+} 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->pixel_clock * 1000, &fck,
+				&lck_div, &pck_div);
+	else
+		r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
+				&lck_div, &pck_div);
+	if (r)
+		return r;
+
+	pck = fck / lck_div / pck_div / 1000;
+
+	if (pck != t->pixel_clock) {
+		DSSWARN("Could not find exact pixel clock. "
+				"Requested %d kHz, got %lu kHz\n",
+				t->pixel_clock, pck);
+
+		t->pixel_clock = 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->pixel_clock == 0)
+		return -EINVAL;
+
+	if (dpi.dsidev) {
+		ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
+
+		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	} else {
+		ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &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 / 1000;
+
+	timings->pixel_clock = 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);
+}
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c
new file mode 100644
index 000000000000..a820c37e323e
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dsi.c
@@ -0,0 +1,5598 @@
+/*
+ * 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 <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;
+};
+
+#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, "vdds_dsi");
+
+	/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+	if (IS_ERR(vdds_dsi))
+		vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO");
+
+	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);
+	}
+
+	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->pixel_clock * 1000;
+	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.pixel_clock = pck / 1000;
+	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->pixel_clock = pck / 1000;
+	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->pixel_clock * 1000;
+	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->pixel_clock = dispc_pck / 1000;
+
+	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->pixel_clock * 1000 - 1000;
+	ctx->req_pck_nom = t->pixel_clock * 1000;
+	ctx->req_pck_max = t->pixel_clock * 1000 + 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);
+}
+
+/* DSI1 HW IP initialisation */
+static int omap_dsihw_probe(struct platform_device *dsidev)
+{
+	u32 rev;
+	int r, i;
+	struct dsi_data *dsi;
+	struct resource *res;
+	struct resource temp_res;
+
+	dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->module_id = dsidev->id;
+	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->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;
+	}
+
+	/* 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);
+
+	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_runtime_get:
+	pm_runtime_disable(&dsidev->dev);
+	return r;
+}
+
+static int __exit omap_dsihw_remove(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	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 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,
+	},
+};
+
+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.c b/drivers/video/fbdev/omap2/dss/dss.c
new file mode 100644
index 000000000000..96e400c51001
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -0,0 +1,906 @@
+/*
+ * 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/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 <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;
+}
+
+/* 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;
+
+	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)
+{
+	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 struct platform_driver omap_dsshw_driver = {
+	.remove         = __exit_p(omap_dsshw_remove),
+	.driver         = {
+		.name   = "omapdss_dss",
+		.owner  = THIS_MODULE,
+		.pm	= &dss_pm_ops,
+	},
+};
+
+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..570f7ed2bcbc
--- /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 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;
+
+/* 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;
+
+/* 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..4a74538f9ea5
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -0,0 +1,700 @@
+/*
+ * 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_hdmi_dac");
+
+	/* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
+	if (IS_ERR(reg))
+		reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
+
+	if (IS_ERR(reg)) {
+		if (PTR_ERR(reg) != -EPROBE_DEFER)
+			DSSERR("can't get VDDA_HDMI_DAC 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);
+
+	phy = p->pixel_clock;
+
+	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.pixel_clock * 1000);
+	} else {
+		hdmi.cfg.timings = *timings;
+		hdmi.cfg.cm.code = 0;
+		hdmi.cfg.cm.mode = HDMI_DVI;
+
+		dispc_set_tv_pclk(timings->pixel_clock * 1000);
+	}
+
+	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.pixel_clock;
+
+	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 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,
+	},
+};
+
+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..0614922902dd
--- /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, 25200, 96, 16, 48, 2, 10, 33,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 1, HDMI_HDMI },
+	},
+	{
+		{ 720, 480, 27027, 62, 16, 60, 6, 9, 30,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 2, HDMI_HDMI },
+	},
+	{
+		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 4, HDMI_HDMI },
+	},
+	{
+		{ 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			true, },
+		{ 5, HDMI_HDMI },
+	},
+	{
+		{ 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			true, },
+		{ 6, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 16, HDMI_HDMI },
+	},
+	{
+		{ 720, 576, 27000, 64, 12, 68, 5, 5, 39,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 17, HDMI_HDMI },
+	},
+	{
+		{ 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 19, HDMI_HDMI },
+	},
+	{
+		{ 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			true, },
+		{ 20, HDMI_HDMI },
+	},
+	{
+		{ 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			true, },
+		{ 21, HDMI_HDMI },
+	},
+	{
+		{ 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 29, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 31, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 32, HDMI_HDMI },
+	},
+	{
+		{ 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 35, HDMI_HDMI },
+	},
+	{
+		{ 2880, 576, 108000, 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, 25175, 96, 16, 48, 2, 11, 31,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 4, HDMI_DVI },
+	},
+	{
+		{ 800, 600, 40000, 128, 40, 88, 4, 1, 23,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 9, HDMI_DVI },
+	},
+	{
+		{ 848, 480, 33750, 112, 16, 112, 8, 6, 23,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0xE, HDMI_DVI },
+	},
+	{
+		{ 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x17, HDMI_DVI },
+	},
+	{
+		{ 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x1C, HDMI_DVI },
+	},
+	{
+		{ 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x27, HDMI_DVI },
+	},
+	{
+		{ 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x20, HDMI_DVI },
+	},
+	{
+		{ 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x23, HDMI_DVI },
+	},
+	{
+		{ 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x10, HDMI_DVI },
+	},
+	{
+		{ 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x2A, HDMI_DVI },
+	},
+	{
+		{ 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x2F, HDMI_DVI },
+	},
+	{
+		{ 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x3A, HDMI_DVI },
+	},
+	{
+		{ 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x51, HDMI_DVI },
+	},
+	{
+		{ 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x52, HDMI_DVI },
+	},
+	{
+		{ 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x16, HDMI_DVI },
+	},
+	{
+		{ 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x29, HDMI_DVI },
+	},
+	{
+		{ 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x39, HDMI_DVI },
+	},
+	{
+		{ 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x1B, HDMI_DVI },
+	},
+	{
+		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x55, HDMI_DVI },
+	},
+	{
+		{ 1920, 1200, 154000, 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->pixel_clock, 1000) ==
+			DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
+		(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/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..cd620c6e43a0
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
@@ -0,0 +1,273 @@
+/*
+ * 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;
+
+	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..ba806c9e7f54
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/sdi.c
@@ -0,0 +1,389 @@
+/*
+ * 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 <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;
+} 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->pixel_clock * 1000, &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 / 1000;
+
+	if (pck != t->pixel_clock) {
+		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
+				"got %lu kHz\n",
+				t->pixel_clock, pck);
+
+		t->pixel_clock = 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->pixel_clock == 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);
+}
diff --git a/drivers/video/fbdev/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c
new file mode 100644
index 000000000000..2cd7f7e42105
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/venc.c
@@ -0,0 +1,916 @@
+/*
+ * 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 <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,
+	.pixel_clock	= 13500,
+	.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,
+	.pixel_clock	= 13500,
+	.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;
+
+	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);
+}
+
+/* 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();
+
+	dss_debugfs_create_file("venc", venc_dump_regs);
+
+	venc_init_output(pdev);
+
+	return 0;
+
+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 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,
+	},
+};
+
+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..f7d92c57bd73
--- /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,
+		.pixel_clock	= 13500,
+		.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..fcb9e932d00c
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
@@ -0,0 +1,2623 @@
+/*
+ * 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.pixel_clock != 0 ?
+			KHZ2PICOS(timings.pixel_clock) :
+			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->pixel_clock = PICOS2KHZ(var->pixclock);
+	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->pixel_clock = PICOS2KHZ(m->pixclock);
+	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 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 = NULL;
+
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev;
+		const char *def_name;
+
+		def_name = omapdss_get_default_display_name();
+
+		dssdev = fbdev->displays[i].dssdev;
+
+		if (def_name == NULL ||
+			(dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
+			def_display = dssdev;
+			break;
+		}
+	}
+
+	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..ad382b3396cd
--- /dev/null
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
@@ -0,0 +1,753 @@
+/*
+ *  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 *file_dev(struct file *file)
+{
+	struct miscdevice *dev = file->private_data;
+	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
+}
+
+static ssize_t
+pxa3xx_gcu_misc_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 = file_dev(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_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	struct pxa3xx_gcu_priv *priv = file_dev(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_misc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned int size = vma->vm_end - vma->vm_start;
+	struct pxa3xx_gcu_priv *priv = file_dev(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
+add_buffer(struct platform_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->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
+free_buffers(struct platform_device *dev,
+	     struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
+
+	while (buffer) {
+		next = buffer->next;
+
+		dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
+				  buffer->ptr, buffer->phys);
+
+		kfree(buffer);
+
+		buffer = next;
+	}
+
+	priv->free = NULL;
+}
+
+static const struct file_operations misc_fops = {
+	.owner	= THIS_MODULE,
+	.write	= pxa3xx_gcu_misc_write,
+	.unlocked_ioctl = pxa3xx_gcu_misc_ioctl,
+	.mmap	= pxa3xx_gcu_misc_mmap
+};
+
+static int pxa3xx_gcu_probe(struct platform_device *dev)
+{
+	int i, ret, irq;
+	struct resource *r;
+	struct pxa3xx_gcu_priv *priv;
+
+	priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	for (i = 0; i < 8; i++) {
+		ret = add_buffer(dev, priv);
+		if (ret) {
+			dev_err(&dev->dev, "failed to allocate DMA memory\n");
+			goto err_free_priv;
+		}
+	}
+
+	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	= &misc_fops,
+
+	/* register misc device */
+	ret = misc_register(&priv->misc_dev);
+	if (ret < 0) {
+		dev_err(&dev->dev, "misc_register() for minor %d failed\n",
+			MISCDEV_MINOR);
+		goto err_free_priv;
+	}
+
+	/* handle IO resources */
+	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 err_misc_deregister;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r), dev->name)) {
+		dev_err(&dev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto err_misc_deregister;
+	}
+
+	priv->mmio_base = ioremap_nocache(r->start, resource_size(r));
+	if (!priv->mmio_base) {
+		dev_err(&dev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto err_free_mem_region;
+	}
+
+	/* allocate dma memory */
+	priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE,
+					  &priv->shared_phys, GFP_KERNEL);
+
+	if (!priv->shared) {
+		dev_err(&dev->dev, "failed to allocate DMA memory\n");
+		ret = -ENOMEM;
+		goto err_free_io;
+	}
+
+	/* enable the clock */
+	priv->clk = clk_get(&dev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&dev->dev, "failed to get clock\n");
+		ret = -ENODEV;
+		goto err_free_dma;
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret < 0) {
+		dev_err(&dev->dev, "failed to enable clock\n");
+		goto err_put_clk;
+	}
+
+	/* request the IRQ */
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	ret = request_irq(irq, pxa3xx_gcu_handle_irq,
+			  0, DRV_NAME, priv);
+	if (ret) {
+		dev_err(&dev->dev, "request_irq failed\n");
+		ret = -EBUSY;
+		goto err_put_clk;
+	}
+
+	platform_set_drvdata(dev, priv);
+	priv->resource_mem = r;
+	pxa3xx_gcu_reset(priv);
+	pxa3xx_gcu_init_debug_timer();
+
+	dev_info(&dev->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_put_clk:
+	clk_disable(priv->clk);
+	clk_put(priv->clk);
+
+err_free_dma:
+	dma_free_coherent(&dev->dev, SHARED_SIZE,
+			priv->shared, priv->shared_phys);
+
+err_free_io:
+	iounmap(priv->mmio_base);
+
+err_free_mem_region:
+	release_mem_region(r->start, resource_size(r));
+
+err_misc_deregister:
+	misc_deregister(&priv->misc_dev);
+
+err_free_priv:
+	free_buffers(dev, priv);
+	kfree(priv);
+	return ret;
+}
+
+static int pxa3xx_gcu_remove(struct platform_device *dev)
+{
+	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
+	struct resource *r = priv->resource_mem;
+
+	pxa3xx_gcu_wait_idle(priv);
+
+	misc_deregister(&priv->misc_dev);
+	dma_free_coherent(&dev->dev, SHARED_SIZE,
+			priv->shared, priv->shared_phys);
+	iounmap(priv->mmio_base);
+	release_mem_region(r->start, resource_size(r));
+	clk_disable(priv->clk);
+	free_buffers(dev, priv);
+	kfree(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..4f26bc28e60b
--- /dev/null
+++ b/drivers/video/fbdev/sis/init.c
@@ -0,0 +1,3654 @@
+/* $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];
+	     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..1f38445014c1
--- /dev/null
+++ b/drivers/video/fbdev/uvesafb.c
@@ -0,0 +1,2035 @@
+/*
+ * 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.
+	 */
+	if (mode != NULL) {
+		size_vmode = info->var.yres * mode->bytes_per_scan_line;
+	} else {
+		size_vmode = info->var.yres * info->var.xres *
+			     ((info->var.bits_per_pixel + 7) >> 3);
+	}
+
+	/*
+	 *   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);
+
+		if (par) {
+			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..1c7da3b098d6
--- /dev/null
+++ b/drivers/video/fbdev/vesafb.c
@@ -0,0 +1,511 @@
+/*
+ * 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);
+	framebuffer_release(info);
+}
+
+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;
+	}
+	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 struct platform_driver vesafb_driver = {
+	.driver = {
+		.name = "vesa-framebuffer",
+		.owner = THIS_MODULE,
+	},
+	.probe = vesafb_probe,
+};
+
+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 7309ac704e26..000000000000
--- a/drivers/video/fbmem.c
+++ /dev/null
@@ -1,2003 +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: conflicting fb hw usage "
-			       "%s vs %s - removing generic driver\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 4c7cb368a9dc..000000000000
--- a/drivers/video/gbefb.c
+++ /dev/null
@@ -1,1313 +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
-
-#ifdef CONFIG_X86_VISWS
-#define GBE_BASE	0xd0000000 /* SGI Visual Workstation */
-#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 130708f96430..000000000000
--- a/drivers/video/hyperv_fb.c
+++ /dev/null
@@ -1,871 +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/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;
-	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;
-		screen_fb_size = SYNTHVID_FB_SIZE_WIN7;
-	} else {
-		screen_depth = SYNTHVID_DEPTH_WIN8;
-		screen_fb_size = SYNTHVID_FB_SIZE_WIN8;
-	}
-
-	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 pci_dev *pdev;
-	ulong fb_phys;
-	void __iomem *fb_virt;
-
-	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;
-
-	fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1;
-	if (!request_mem_region(fb_phys, screen_fb_size, KBUILD_MODNAME))
-		goto err1;
-
-	fb_virt = ioremap(fb_phys, screen_fb_size);
-	if (!fb_virt)
-		goto err2;
-
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures)
-		goto err3;
-
-	info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
-	info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
-	info->fix.smem_start = fb_phys;
-	info->fix.smem_len = screen_fb_size;
-	info->screen_base = fb_virt;
-	info->screen_size = screen_fb_size;
-
-	pci_dev_put(pdev);
-	return 0;
-
-err3:
-	iounmap(fb_virt);
-err2:
-	release_mem_region(fb_phys, screen_fb_size);
-err1:
-	pci_dev_put(pdev);
-	return -ENOMEM;
-}
-
-/* Release the framebuffer */
-static void hvfb_putmem(struct fb_info *info)
-{
-	iounmap(info->screen_base);
-	release_mem_region(info->fix.smem_start, screen_fb_size);
-}
-
-
-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 44ee678481d5..000000000000
--- a/drivers/video/imxfb.c
+++ /dev/null
@@ -1,1143 +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/math64.h>
-#include <linux/of.h>
-#include <linux/of_device.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
-
-#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
-	(defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \
-		defined(CONFIG_FB_IMX_MODULE))
-#define PWMR_BACKLIGHT_AVAILABLE
-#endif
-
-#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_char			*map_cpu;
-	u_int			map_size;
-
-	u_char			*screen_cpu;
-	dma_addr_t		screen_dma;
-	u_int			palette_size;
-
-	dma_addr_t		dbar1;
-	dma_addr_t		dbar2;
-
-	u_int			pcr;
-	u_int			pwmr;
-	u_int			lscr1;
-	u_int			dmacr;
-	u_int			cmap_inverse:1,
-				cmap_static:1,
-				unused:30;
-
-	struct imx_fb_videomode *mode;
-	int			num_modes;
-#ifdef PWMR_BACKLIGHT_AVAILABLE
-	struct backlight_device *bl;
-#endif
-
-	void (*lcd_power)(int);
-	void (*backlight_power)(int);
-};
-
-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;
-}
-
-#ifdef PWMR_BACKLIGHT_AVAILABLE
-static int imxfb_bl_get_brightness(struct backlight_device *bl)
-{
-	struct imxfb_info *fbi = bl_get_data(bl);
-
-	return readl(fbi->regs + LCDC_PWMR) & 0xFF;
-}
-
-static int imxfb_bl_update_status(struct backlight_device *bl)
-{
-	struct imxfb_info *fbi = bl_get_data(bl);
-	int brightness = bl->props.brightness;
-
-	if (!fbi->pwmr)
-		return 0;
-
-	if (bl->props.power != FB_BLANK_UNBLANK)
-		brightness = 0;
-	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-		brightness = 0;
-
-	fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness;
-
-	if (bl->props.fb_blank != FB_BLANK_UNBLANK) {
-		clk_prepare_enable(fbi->clk_ipg);
-		clk_prepare_enable(fbi->clk_ahb);
-		clk_prepare_enable(fbi->clk_per);
-	}
-	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-	if (bl->props.fb_blank != FB_BLANK_UNBLANK) {
-		clk_disable_unprepare(fbi->clk_per);
-		clk_disable_unprepare(fbi->clk_ahb);
-		clk_disable_unprepare(fbi->clk_ipg);
-	}
-
-	return 0;
-}
-
-static const struct backlight_ops imxfb_lcdc_bl_ops = {
-	.update_status = imxfb_bl_update_status,
-	.get_brightness = imxfb_bl_get_brightness,
-};
-
-static void imxfb_init_backlight(struct imxfb_info *fbi)
-{
-	struct backlight_properties props;
-	struct backlight_device	*bl;
-
-	if (fbi->bl)
-		return;
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 0xff;
-	props.type = BACKLIGHT_RAW;
-	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-
-	bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
-				       &imxfb_lcdc_bl_ops, &props);
-	if (IS_ERR(bl)) {
-		dev_err(&fbi->pdev->dev, "error %ld on backlight register\n",
-				PTR_ERR(bl));
-		return;
-	}
-
-	fbi->bl = bl;
-	bl->props.power = FB_BLANK_UNBLANK;
-	bl->props.fb_blank = FB_BLANK_UNBLANK;
-	bl->props.brightness = imxfb_bl_get_brightness(bl);
-}
-
-static void imxfb_exit_backlight(struct imxfb_info *fbi)
-{
-	if (fbi->bl)
-		backlight_device_unregister(fbi->bl);
-}
-#endif
-
-static void imxfb_enable_controller(struct imxfb_info *fbi)
-{
-
-	if (fbi->enabled)
-		return;
-
-	pr_debug("Enabling LCD controller\n");
-
-	writel(fbi->screen_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;
-
-	if (fbi->backlight_power)
-		fbi->backlight_power(1);
-	if (fbi->lcd_power)
-		fbi->lcd_power(1);
-}
-
-static void imxfb_disable_controller(struct imxfb_info *fbi)
-{
-	if (!fbi->enabled)
-		return;
-
-	pr_debug("Disabling LCD controller\n");
-
-	if (fbi->backlight_power)
-		fbi->backlight_power(0);
-	if (fbi->lcd_power)
-		fbi->lcd_power(0);
-
-	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);
-#ifndef PWMR_BACKLIGHT_AVAILABLE
-	if (fbi->pwmr)
-		writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-#endif
-	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;
-}
-
-#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 imxfb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct imxfb_info *fbi = info->par;
-
-	pr_debug("%s\n", __func__);
-
-	imxfb_disable_controller(fbi);
-	return 0;
-}
-
-static int imxfb_resume(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct imxfb_info *fbi = info->par;
-
-	pr_debug("%s\n", __func__);
-
-	imxfb_enable_controller(fbi);
-	return 0;
-}
-#else
-#define imxfb_suspend	NULL
-#define imxfb_resume	NULL
-#endif
-
-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) {
-		info->var.grayscale		= pdata->cmap_greyscale;
-		fbi->cmap_inverse		= pdata->cmap_inverse;
-		fbi->cmap_static		= pdata->cmap_static;
-		fbi->lscr1			= pdata->lscr1;
-		fbi->dmacr			= pdata->dmacr;
-		fbi->pwmr			= pdata->pwmr;
-		fbi->lcd_power			= pdata->lcd_power;
-		fbi->backlight_power		= pdata->backlight_power;
-	} 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,lscr1", &fbi->lscr1);
-
-		of_property_read_u32(np, "fsl,dmacr", &fbi->dmacr);
-
-		/* These two function pointers could be used by some specific
-		 * platforms. */
-		fbi->lcd_power = NULL;
-		fbi->backlight_power = NULL;
-	}
-
-	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_probe(struct platform_device *pdev)
-{
-	struct imxfb_info *fbi;
-	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");
-
-	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;
-	}
-
-	/* Seems not being used by anyone, so no support for oftree */
-	if (!pdata || !pdata->fixed_screen_cpu) {
-		fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
-		fbi->map_cpu = dma_alloc_writecombine(&pdev->dev,
-				fbi->map_size, &fbi->map_dma, GFP_KERNEL);
-
-		if (!fbi->map_cpu) {
-			dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
-			ret = -ENOMEM;
-			goto failed_map;
-		}
-
-		info->screen_base = fbi->map_cpu;
-		fbi->screen_cpu = fbi->map_cpu;
-		fbi->screen_dma = fbi->map_dma;
-		info->fix.smem_start = fbi->screen_dma;
-	} else {
-		/* Fixed framebuffer mapping enables location of the screen in eSRAM */
-		fbi->map_cpu = pdata->fixed_screen_cpu;
-		fbi->map_dma = pdata->fixed_screen_dma;
-		info->screen_base = fbi->map_cpu;
-		fbi->screen_cpu = fbi->map_cpu;
-		fbi->screen_dma = fbi->map_dma;
-		info->fix.smem_start = fbi->screen_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;
-	}
-
-	imxfb_enable_controller(fbi);
-	fbi->pdev = pdev;
-#ifdef PWMR_BACKLIGHT_AVAILABLE
-	imxfb_init_backlight(fbi);
-#endif
-
-	return 0;
-
-failed_register:
-	fb_dealloc_cmap(&info->cmap);
-failed_cmap:
-	if (pdata && pdata->exit)
-		pdata->exit(fbi->pdev);
-failed_platform_init:
-	if (pdata && !pdata->fixed_screen_cpu)
-		dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
-			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);
-
-#ifdef PWMR_BACKLIGHT_AVAILABLE
-	imxfb_exit_backlight(fbi);
-#endif
-	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);
-
-	iounmap(fbi->regs);
-	release_mem_region(res->start, resource_size(res));
-
-	return 0;
-}
-
-static void imxfb_shutdown(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct imxfb_info *fbi = info->par;
-	imxfb_disable_controller(fbi);
-}
-
-static struct platform_driver imxfb_driver = {
-	.suspend	= imxfb_suspend,
-	.resume		= imxfb_resume,
-	.remove		= imxfb_remove,
-	.shutdown	= imxfb_shutdown,
-	.driver		= {
-		.name	= DRIVER_NAME,
-		.of_match_table = imxfb_of_dev_id,
-	},
-	.id_table	= imxfb_devtype,
-};
-
-static int imxfb_setup(void)
-{
-#ifndef MODULE
-	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;
-	}
-#endif
-	return 0;
-}
-
-static int __init imxfb_init(void)
-{
-	int ret = imxfb_setup();
-
-	if (ret < 0)
-		return ret;
-
-	return platform_driver_probe(&imxfb_driver, imxfb_probe);
-}
-
-static void __exit imxfb_cleanup(void)
-{
-	platform_driver_unregister(&imxfb_driver);
-}
-
-module_init(imxfb_init);
-module_exit(imxfb_cleanup);
-
-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/logo/Kconfig b/drivers/video/logo/Kconfig
index 39ac49e0682c..0037104d66ac 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -54,7 +54,7 @@ config LOGO_PARISC_CLUT224
 
 config LOGO_SGI_CLUT224
 	bool "224-color SGI Linux logo"
-	depends on SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS
+	depends on SGI_IP22 || SGI_IP27 || SGI_IP32
 	default y
 
 config LOGO_SUN_CLUT224
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index b670cbda38e3..940cd196eef5 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -81,7 +81,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
 		logo = &logo_parisc_clut224;
 #endif
 #ifdef CONFIG_LOGO_SGI_CLUT224
-		/* SGI Linux logo on MIPS/MIPS64 and VISWS */
+		/* SGI Linux logo on MIPS/MIPS64 */
 		logo = &logo_sgi_clut224;
 #endif
 #ifdef CONFIG_LOGO_SUN_CLUT224
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 8335a6fe303e..000000000000
--- a/drivers/video/matrox/matroxfb_accel.c
+++ /dev/null
@@ -1,501 +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;
-}
-
-EXPORT_SYMBOL(matrox_cfbX_init);
-
-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(2);
-		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(3);
-		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(4);
-	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(2);
-		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(3);
-		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(5);
-	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(5);
-	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(5);
-		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(3);
-	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(6);
-	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 87c64ff4546c..000000000000
--- a/drivers/video/matrox/matroxfb_base.c
+++ /dev/null
@@ -1,2583 +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 */
-	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 11ed57bb704e..000000000000
--- a/drivers/video/matrox/matroxfb_base.h
+++ /dev/null
@@ -1,733 +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;
-};
-
-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 ccd9073f706f..000000000000
--- a/drivers/video/omap2/displays-new/connector-analog-tv.c
+++ /dev/null
@@ -1,279 +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 <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,
-	.pixel_clock	= 13500,
-	.hsw		= 64,
-	.hfp		= 12,
-	.hbp		= 68,
-	.vsw		= 5,
-	.vfp		= 5,
-	.vbp		= 41,
-
-	.interlace	= true,
-};
-
-#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);
-
-	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(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 {
-		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 struct platform_driver tvc_connector_driver = {
-	.probe	= tvc_probe,
-	.remove	= __exit_p(tvc_remove),
-	.driver	= {
-		.name	= "connector-analog-tv",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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 b6c50904038e..000000000000
--- a/drivers/video/omap2/displays-new/connector-dvi.c
+++ /dev/null
@@ -1,358 +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,
-
-	.pixel_clock	= 23500,
-
-	.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(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 {
-		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 struct platform_driver dvi_connector_driver = {
-	.probe	= dvic_probe,
-	.remove	= __exit_p(dvic_remove),
-	.driver	= {
-		.name	= "connector-dvi",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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 9abe2c039ae9..000000000000
--- a/drivers/video/omap2/displays-new/connector-hdmi.c
+++ /dev/null
@@ -1,375 +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 <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,
-	.pixel_clock	= 25175,
-	.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(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 {
-		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 struct platform_driver hdmi_connector_driver = {
-	.probe	= hdmic_probe,
-	.remove	= __exit_p(hdmic_remove),
-	.driver	= {
-		.name	= "connector-hdmi",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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 4a291e756be9..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ /dev/null
@@ -1,267 +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 <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);
-	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(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 {
-		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 struct platform_driver tfp410_driver = {
-	.probe	= tfp410_probe,
-	.remove	= __exit_p(tfp410_remove),
-	.driver	= {
-		.name	= "tfp410",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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 d5c936cb217f..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ /dev/null
@@ -1,395 +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 <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(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 {
-		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 struct platform_driver tpd_driver = {
-	.probe	= tpd_probe,
-	.remove	= __exit_p(tpd_remove),
-	.driver	= {
-		.name	= "tpd12s015",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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 b7baafe83aa3..000000000000
--- a/drivers/video/omap2/displays-new/panel-dsi-cm.c
+++ /dev/null
@@ -1,1336 +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 <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,
-	};
-
-	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(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 {
-		return -ENODEV;
-	}
-
-	ddata->timings.x_res = 864;
-	ddata->timings.y_res = 480;
-	ddata->timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
-
-	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 struct platform_driver dsicm_driver = {
-	.probe = dsicm_probe,
-	.remove = __exit_p(dsicm_remove),
-	.driver = {
-		.name = "panel-dsi-cm",
-		.owner = THIS_MODULE,
-	},
-};
-
-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 6e8977b18950..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,
-
-	.pixel_clock	= 6500,
-
-	.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 bb217da65c5f..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		23800
-
-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,
-	.pixel_clock	= 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 72a4fb5aa6b1..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,
-
-	.pixel_clock	= 19200,
-
-	.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 8e97d06921ff..000000000000
--- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
+++ /dev/null
@@ -1,880 +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 <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,
-	.pixel_clock	= 24000,
-	.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);
-	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(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 {
-		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 struct spi_driver acx565akm_driver = {
-	.driver = {
-		.name	= "acx565akm",
-		.owner	= THIS_MODULE,
-	},
-	.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 9a08908fe998..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,
-	.pixel_clock	= 22153,
-	.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 eadc6529fa3d..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,
-
-	.pixel_clock	= 36000,
-
-	.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 d3aa91bdd6a8..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 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 77d6221618f4..000000000000
--- a/drivers/video/omap2/dss/dispc.c
+++ /dev/null
@@ -1,3800 +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		ctx_loss_cnt;
-
-	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_loss_cnt = dss_get_ctx_loss_count();
-	dispc.ctx_valid = true;
-
-	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
-}
-
-static void dispc_restore_context(void)
-{
-	int i, j, ctx;
-
-	DSSDBG("dispc_restore_context\n");
-
-	if (!dispc.ctx_valid)
-		return;
-
-	ctx = dss_get_ctx_loss_count();
-
-	if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
-		return;
-
-	DSSDBG("ctx_loss_count: saved %d, current %d\n",
-			dispc.ctx_loss_cnt, ctx);
-
-	/*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->pixel_clock * 1000);
-
-	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->pixel_clock * 1000) / xtot;
-		vt = (timings->pixel_clock * 1000) / xtot / ytot;
-
-		DSSDBG("pck %u\n", timings->pixel_clock);
-		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)
-{
-	_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 struct platform_driver omap_dispchw_driver = {
-	.remove         = __exit_p(omap_dispchw_remove),
-	.driver         = {
-		.name   = "omapdss_dispc",
-		.owner  = THIS_MODULE,
-		.pm	= &dispc_pm_ops,
-	},
-};
-
-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 f7b5f9561041..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.pixel_clock,
-			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.pixel_clock,
-				&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 669a81fdf58e..000000000000
--- a/drivers/video/omap2/dss/display.c
+++ /dev/null
@@ -1,314 +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 <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;
-
-	snprintf(dssdev->alias, sizeof(dssdev->alias),
-			"display%d", disp_num_counter++);
-
-	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->pixel_clock = vm->pixelclock / 1000;
-	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->pixel_clock * 1000;
-
-	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 23ef21ffc2c4..000000000000
--- a/drivers/video/omap2/dss/dpi.c
+++ /dev/null
@@ -1,728 +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 <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;
-} 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->pixel_clock * 1000, &fck,
-				&lck_div, &pck_div);
-	else
-		r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
-				&lck_div, &pck_div);
-	if (r)
-		return r;
-
-	pck = fck / lck_div / pck_div / 1000;
-
-	if (pck != t->pixel_clock) {
-		DSSWARN("Could not find exact pixel clock. "
-				"Requested %d kHz, got %lu kHz\n",
-				t->pixel_clock, pck);
-
-		t->pixel_clock = 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->pixel_clock == 0)
-		return -EINVAL;
-
-	if (dpi.dsidev) {
-		ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
-		if (!ok)
-			return -EINVAL;
-
-		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	} else {
-		ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &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 / 1000;
-
-	timings->pixel_clock = 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);
-}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
deleted file mode 100644
index a820c37e323e..000000000000
--- a/drivers/video/omap2/dss/dsi.c
+++ /dev/null
@@ -1,5598 +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 <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;
-};
-
-#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, "vdds_dsi");
-
-	/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
-	if (IS_ERR(vdds_dsi))
-		vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO");
-
-	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);
-	}
-
-	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->pixel_clock * 1000;
-	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.pixel_clock = pck / 1000;
-	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->pixel_clock = pck / 1000;
-	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->pixel_clock * 1000;
-	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->pixel_clock = dispc_pck / 1000;
-
-	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->pixel_clock * 1000 - 1000;
-	ctx->req_pck_nom = t->pixel_clock * 1000;
-	ctx->req_pck_max = t->pixel_clock * 1000 + 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);
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsihw_probe(struct platform_device *dsidev)
-{
-	u32 rev;
-	int r, i;
-	struct dsi_data *dsi;
-	struct resource *res;
-	struct resource temp_res;
-
-	dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
-	if (!dsi)
-		return -ENOMEM;
-
-	dsi->module_id = dsidev->id;
-	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->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;
-	}
-
-	/* 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);
-
-	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_runtime_get:
-	pm_runtime_disable(&dsidev->dev);
-	return r;
-}
-
-static int __exit omap_dsihw_remove(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	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 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,
-	},
-};
-
-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.c b/drivers/video/omap2/dss/dss.c
deleted file mode 100644
index 9a145da35ad3..000000000000
--- a/drivers/video/omap2/dss/dss.c
+++ /dev/null
@@ -1,922 +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/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 <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
-
-int dss_get_ctx_loss_count(void)
-{
-	struct platform_device *core_pdev = dss_get_core_pdev();
-	struct omap_dss_board_info *board_data = core_pdev->dev.platform_data;
-	int cnt;
-
-	if (!board_data->get_context_loss_count)
-		return -ENOENT;
-
-	cnt = board_data->get_context_loss_count(&dss.pdev->dev);
-
-	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
-	return cnt;
-}
-
-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;
-}
-
-/* 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;
-
-	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)
-{
-	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 struct platform_driver omap_dsshw_driver = {
-	.remove         = __exit_p(omap_dsshw_remove),
-	.driver         = {
-		.name   = "omapdss_dss",
-		.owner  = THIS_MODULE,
-		.pm	= &dss_pm_ops,
-	},
-};
-
-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 057f24c8a332..000000000000
--- a/drivers/video/omap2/dss/dss.h
+++ /dev/null
@@ -1,440 +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
-
-int dss_get_ctx_loss_count(void);
-
-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;
-
-/* 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;
-
-/* 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 4a74538f9ea5..000000000000
--- a/drivers/video/omap2/dss/hdmi4.c
+++ /dev/null
@@ -1,700 +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_hdmi_dac");
-
-	/* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
-	if (IS_ERR(reg))
-		reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
-
-	if (IS_ERR(reg)) {
-		if (PTR_ERR(reg) != -EPROBE_DEFER)
-			DSSERR("can't get VDDA_HDMI_DAC 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);
-
-	phy = p->pixel_clock;
-
-	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.pixel_clock * 1000);
-	} else {
-		hdmi.cfg.timings = *timings;
-		hdmi.cfg.cm.code = 0;
-		hdmi.cfg.cm.mode = HDMI_DVI;
-
-		dispc_set_tv_pclk(timings->pixel_clock * 1000);
-	}
-
-	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.pixel_clock;
-
-	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 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,
-	},
-};
-
-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 0614922902dd..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, 25200, 96, 16, 48, 2, 10, 33,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 1, HDMI_HDMI },
-	},
-	{
-		{ 720, 480, 27027, 62, 16, 60, 6, 9, 30,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 2, HDMI_HDMI },
-	},
-	{
-		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 4, HDMI_HDMI },
-	},
-	{
-		{ 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			true, },
-		{ 5, HDMI_HDMI },
-	},
-	{
-		{ 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			true, },
-		{ 6, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 16, HDMI_HDMI },
-	},
-	{
-		{ 720, 576, 27000, 64, 12, 68, 5, 5, 39,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 17, HDMI_HDMI },
-	},
-	{
-		{ 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 19, HDMI_HDMI },
-	},
-	{
-		{ 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			true, },
-		{ 20, HDMI_HDMI },
-	},
-	{
-		{ 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			true, },
-		{ 21, HDMI_HDMI },
-	},
-	{
-		{ 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 29, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 31, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 32, HDMI_HDMI },
-	},
-	{
-		{ 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 35, HDMI_HDMI },
-	},
-	{
-		{ 2880, 576, 108000, 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, 25175, 96, 16, 48, 2, 11, 31,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 4, HDMI_DVI },
-	},
-	{
-		{ 800, 600, 40000, 128, 40, 88, 4, 1, 23,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 9, HDMI_DVI },
-	},
-	{
-		{ 848, 480, 33750, 112, 16, 112, 8, 6, 23,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0xE, HDMI_DVI },
-	},
-	{
-		{ 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x17, HDMI_DVI },
-	},
-	{
-		{ 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x1C, HDMI_DVI },
-	},
-	{
-		{ 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x27, HDMI_DVI },
-	},
-	{
-		{ 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x20, HDMI_DVI },
-	},
-	{
-		{ 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x23, HDMI_DVI },
-	},
-	{
-		{ 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x10, HDMI_DVI },
-	},
-	{
-		{ 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x2A, HDMI_DVI },
-	},
-	{
-		{ 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x2F, HDMI_DVI },
-	},
-	{
-		{ 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x3A, HDMI_DVI },
-	},
-	{
-		{ 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x51, HDMI_DVI },
-	},
-	{
-		{ 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x52, HDMI_DVI },
-	},
-	{
-		{ 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x16, HDMI_DVI },
-	},
-	{
-		{ 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x29, HDMI_DVI },
-	},
-	{
-		{ 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x39, HDMI_DVI },
-	},
-	{
-		{ 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x1B, HDMI_DVI },
-	},
-	{
-		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x55, HDMI_DVI },
-	},
-	{
-		{ 1920, 1200, 154000, 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->pixel_clock, 1000) ==
-			DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
-		(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 cd620c6e43a0..000000000000
--- a/drivers/video/omap2/dss/hdmi_wp.c
+++ /dev/null
@@ -1,273 +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;
-
-	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 ba806c9e7f54..000000000000
--- a/drivers/video/omap2/dss/sdi.c
+++ /dev/null
@@ -1,389 +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 <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;
-} 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->pixel_clock * 1000, &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 / 1000;
-
-	if (pck != t->pixel_clock) {
-		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
-				"got %lu kHz\n",
-				t->pixel_clock, pck);
-
-		t->pixel_clock = 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->pixel_clock == 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);
-}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
deleted file mode 100644
index 2cd7f7e42105..000000000000
--- a/drivers/video/omap2/dss/venc.c
+++ /dev/null
@@ -1,916 +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 <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,
-	.pixel_clock	= 13500,
-	.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,
-	.pixel_clock	= 13500,
-	.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;
-
-	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);
-}
-
-/* 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();
-
-	dss_debugfs_create_file("venc", venc_dump_regs);
-
-	venc_init_output(pdev);
-
-	return 0;
-
-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 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,
-	},
-};
-
-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 f7d92c57bd73..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,
-		.pixel_clock	= 13500,
-		.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 fcb9e932d00c..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ /dev/null
@@ -1,2623 +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.pixel_clock != 0 ?
-			KHZ2PICOS(timings.pixel_clock) :
-			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->pixel_clock = PICOS2KHZ(var->pixclock);
-	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->pixel_clock = PICOS2KHZ(m->pixclock);
-	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 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 = NULL;
-
-	for (i = 0; i < fbdev->num_displays; ++i) {
-		struct omap_dss_device *dssdev;
-		const char *def_name;
-
-		def_name = omapdss_get_default_display_name();
-
-		dssdev = fbdev->displays[i].dssdev;
-
-		if (def_name == NULL ||
-			(dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
-			def_display = dssdev;
-			break;
-		}
-	}
-
-	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 ad382b3396cd..000000000000
--- a/drivers/video/pxa3xx-gcu.c
+++ /dev/null
@@ -1,753 +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 *file_dev(struct file *file)
-{
-	struct miscdevice *dev = file->private_data;
-	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
-}
-
-static ssize_t
-pxa3xx_gcu_misc_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 = file_dev(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_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	unsigned long flags;
-	struct pxa3xx_gcu_priv *priv = file_dev(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_misc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	unsigned int size = vma->vm_end - vma->vm_start;
-	struct pxa3xx_gcu_priv *priv = file_dev(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
-add_buffer(struct platform_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->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
-free_buffers(struct platform_device *dev,
-	     struct pxa3xx_gcu_priv *priv)
-{
-	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
-
-	while (buffer) {
-		next = buffer->next;
-
-		dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
-				  buffer->ptr, buffer->phys);
-
-		kfree(buffer);
-
-		buffer = next;
-	}
-
-	priv->free = NULL;
-}
-
-static const struct file_operations misc_fops = {
-	.owner	= THIS_MODULE,
-	.write	= pxa3xx_gcu_misc_write,
-	.unlocked_ioctl = pxa3xx_gcu_misc_ioctl,
-	.mmap	= pxa3xx_gcu_misc_mmap
-};
-
-static int pxa3xx_gcu_probe(struct platform_device *dev)
-{
-	int i, ret, irq;
-	struct resource *r;
-	struct pxa3xx_gcu_priv *priv;
-
-	priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	for (i = 0; i < 8; i++) {
-		ret = add_buffer(dev, priv);
-		if (ret) {
-			dev_err(&dev->dev, "failed to allocate DMA memory\n");
-			goto err_free_priv;
-		}
-	}
-
-	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	= &misc_fops,
-
-	/* register misc device */
-	ret = misc_register(&priv->misc_dev);
-	if (ret < 0) {
-		dev_err(&dev->dev, "misc_register() for minor %d failed\n",
-			MISCDEV_MINOR);
-		goto err_free_priv;
-	}
-
-	/* handle IO resources */
-	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 err_misc_deregister;
-	}
-
-	if (!request_mem_region(r->start, resource_size(r), dev->name)) {
-		dev_err(&dev->dev, "failed to request I/O memory\n");
-		ret = -EBUSY;
-		goto err_misc_deregister;
-	}
-
-	priv->mmio_base = ioremap_nocache(r->start, resource_size(r));
-	if (!priv->mmio_base) {
-		dev_err(&dev->dev, "failed to map I/O memory\n");
-		ret = -EBUSY;
-		goto err_free_mem_region;
-	}
-
-	/* allocate dma memory */
-	priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE,
-					  &priv->shared_phys, GFP_KERNEL);
-
-	if (!priv->shared) {
-		dev_err(&dev->dev, "failed to allocate DMA memory\n");
-		ret = -ENOMEM;
-		goto err_free_io;
-	}
-
-	/* enable the clock */
-	priv->clk = clk_get(&dev->dev, NULL);
-	if (IS_ERR(priv->clk)) {
-		dev_err(&dev->dev, "failed to get clock\n");
-		ret = -ENODEV;
-		goto err_free_dma;
-	}
-
-	ret = clk_enable(priv->clk);
-	if (ret < 0) {
-		dev_err(&dev->dev, "failed to enable clock\n");
-		goto err_put_clk;
-	}
-
-	/* request the IRQ */
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0) {
-		dev_err(&dev->dev, "no IRQ defined\n");
-		ret = -ENODEV;
-		goto err_put_clk;
-	}
-
-	ret = request_irq(irq, pxa3xx_gcu_handle_irq,
-			  0, DRV_NAME, priv);
-	if (ret) {
-		dev_err(&dev->dev, "request_irq failed\n");
-		ret = -EBUSY;
-		goto err_put_clk;
-	}
-
-	platform_set_drvdata(dev, priv);
-	priv->resource_mem = r;
-	pxa3xx_gcu_reset(priv);
-	pxa3xx_gcu_init_debug_timer();
-
-	dev_info(&dev->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_put_clk:
-	clk_disable(priv->clk);
-	clk_put(priv->clk);
-
-err_free_dma:
-	dma_free_coherent(&dev->dev, SHARED_SIZE,
-			priv->shared, priv->shared_phys);
-
-err_free_io:
-	iounmap(priv->mmio_base);
-
-err_free_mem_region:
-	release_mem_region(r->start, resource_size(r));
-
-err_misc_deregister:
-	misc_deregister(&priv->misc_dev);
-
-err_free_priv:
-	free_buffers(dev, priv);
-	kfree(priv);
-	return ret;
-}
-
-static int pxa3xx_gcu_remove(struct platform_device *dev)
-{
-	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
-	struct resource *r = priv->resource_mem;
-
-	pxa3xx_gcu_wait_idle(priv);
-
-	misc_deregister(&priv->misc_dev);
-	dma_free_coherent(&dev->dev, SHARED_SIZE,
-			priv->shared, priv->shared_phys);
-	iounmap(priv->mmio_base);
-	release_mem_region(r->start, resource_size(r));
-	clk_disable(priv->clk);
-	free_buffers(dev, priv);
-	kfree(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/sgivwfb.c b/drivers/video/sgivwfb.c
deleted file mode 100644
index bc74d0408998..000000000000
--- a/drivers/video/sgivwfb.c
+++ /dev/null
@@ -1,889 +0,0 @@
-/*
- *  linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
- *
- *	Copyright (C) 1999 Silicon Graphics, Inc.
- *      Jeffrey Newquist, newquist@engr.sgi.som
- *
- *  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/mm.h>
-#include <linux/errno.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/mtrr.h>
-#include <asm/visws/sgivw.h>
-
-#define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE par->regs
-#include <video/sgivw.h>
-
-struct sgivw_par {
-	struct asregs *regs;
-	u32 cmap_fifo;
-	u_long timing_num;
-};
-
-#define FLATPANEL_SGI_1600SW	5
-
-/*
- *  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
- */
-
-static int ypan = 0;
-static int ywrap = 0;
-
-static int flatpanel_id = -1;
-
-static struct fb_fix_screeninfo sgivwfb_fix = {
-	.id		= "SGI Vis WS FB",
-	.type		= FB_TYPE_PACKED_PIXELS,
-        .visual		= FB_VISUAL_PSEUDOCOLOR,
-	.mmio_start	= DBE_REG_PHYS,
-	.mmio_len	= DBE_REG_SIZE,
-        .accel		= FB_ACCEL_NONE,
-	.line_length	= 640,
-};
-
-static struct fb_var_screeninfo sgivwfb_var = {
-	/* 640x480, 8 bpp */
-	.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,
-	.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_var_screeninfo sgivwfb_var1600sw = {
-	/* 1600x1024, 8 bpp */
-	.xres		= 1600,
-	.yres		= 1024,
-	.xres_virtual	= 1600,
-	.yres_virtual	= 1024,
-	.bits_per_pixel	= 8,
-	.red		= { 0, 8, 0 },
-	.green		= { 0, 8, 0 },
-	.blue		= { 0, 8, 0 },
-	.height		= -1,
-	.width		= -1,
-	.pixclock	= 9353,
-	.left_margin	= 20,
-	.right_margin	= 30,
-	.upper_margin	= 37,
-	.lower_margin	= 3,
-	.hsync_len	= 20,
-	.vsync_len	= 3,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-/*
- *  Interface used by the world
- */
-int sgivwfb_init(void);
-
-static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
-static int sgivwfb_set_par(struct fb_info *info);
-static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
-			     u_int blue, u_int transp,
-			     struct fb_info *info);
-static int sgivwfb_mmap(struct fb_info *info,
-			struct vm_area_struct *vma);
-
-static struct fb_ops sgivwfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= sgivwfb_check_var,
-	.fb_set_par	= sgivwfb_set_par,
-	.fb_setcolreg	= sgivwfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_mmap	= sgivwfb_mmap,
-};
-
-/*
- *  Internal routines
- */
-static unsigned long bytes_per_pixel(int bpp)
-{
-	switch (bpp) {
-		case 8:
-			return 1;
-		case 16:
-			return 2;
-		case 32:
-			return 4;
-		default:
-			printk(KERN_INFO "sgivwfb: unsupported bpp %d\n", bpp);
-			return 0;
-	}
-}
-
-static unsigned long get_line_length(int xres_virtual, int bpp)
-{
-	return (xres_virtual * bytes_per_pixel(bpp));
-}
-
-/*
- * Function:	dbe_TurnOffDma
- * Parameters:	(None)
- * Description:	This should turn off the monitor and dbe.  This is used
- *              when switching between the serial console and the graphics
- *              console.
- */
-
-static void dbe_TurnOffDma(struct sgivw_par *par)
-{
-	unsigned int readVal;
-	int i;
-
-	// Check to see if things are already turned off:
-	// 1) Check to see if dbe is not using the internal dotclock.
-	// 2) Check to see if the xy counter in dbe is already off.
-
-	DBE_GETREG(ctrlstat, readVal);
-	if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
-		return;
-
-	DBE_GETREG(vt_xy, readVal);
-	if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
-		return;
-
-	// Otherwise, turn off dbe
-
-	DBE_GETREG(ovr_control, readVal);
-	SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
-	DBE_SETREG(ovr_control, readVal);
-	udelay(1000);
-	DBE_GETREG(frm_control, readVal);
-	SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
-	DBE_SETREG(frm_control, readVal);
-	udelay(1000);
-	DBE_GETREG(did_control, readVal);
-	SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
-	DBE_SETREG(did_control, readVal);
-	udelay(1000);
-
-	// XXX HACK:
-	//
-	//    This was necessary for GBE--we had to wait through two
-	//    vertical retrace periods before the pixel DMA was
-	//    turned off for sure.  I've left this in for now, in
-	//    case dbe needs it.
-
-	for (i = 0; i < 10000; i++) {
-		DBE_GETREG(frm_inhwctrl, readVal);
-		if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) ==
-		    0)
-			udelay(10);
-		else {
-			DBE_GETREG(ovr_inhwctrl, readVal);
-			if (GET_DBE_FIELD
-			    (OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
-				udelay(10);
-			else {
-				DBE_GETREG(did_inhwctrl, readVal);
-				if (GET_DBE_FIELD
-				    (DID_INHWCTRL, DID_DMA_ENABLE,
-				     readVal) == 0)
-					udelay(10);
-				else
-					break;
-			}
-		}
-	}
-}
-
-/*
- *  Set the User Defined Part of the Display. Again if par use it to get
- *  real video mode.
- */
-static int sgivwfb_check_var(struct fb_var_screeninfo *var, 
-			     struct fb_info *info)
-{
-	struct sgivw_par *par = (struct sgivw_par *)info->par;
-	struct dbe_timing_info *timing;
-	u_long line_length;
-	u_long min_mode;
-	int req_dot;
-	int test_mode;
-
-	/*
-	 *  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;
-	}
-
-	/* XXX FIXME - forcing var's */
-	var->xoffset = 0;
-	var->yoffset = 0;
-
-	/* 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;
-
-	var->grayscale = 0;	/* No grayscale for now */
-
-	/* determine valid resolution and timing */
-	for (min_mode = 0; min_mode < ARRAY_SIZE(dbeVTimings); min_mode++) {
-		if (dbeVTimings[min_mode].width >= var->xres &&
-		    dbeVTimings[min_mode].height >= var->yres)
-			break;
-	}
-
-	if (min_mode == ARRAY_SIZE(dbeVTimings))
-		return -EINVAL;	/* Resolution to high */
-
-	/* XXX FIXME - should try to pick best refresh rate */
-	/* for now, pick closest dot-clock within 3MHz */
-	req_dot = PICOS2KHZ(var->pixclock);
-	printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n",
-	       var->pixclock, req_dot);
-	test_mode = min_mode;
-	while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
-		if (dbeVTimings[test_mode].cfreq + 3000 > req_dot)
-			break;
-		test_mode++;
-	}
-	if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
-		test_mode--;
-	min_mode = test_mode;
-	timing = &dbeVTimings[min_mode];
-	printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
-
-	/* 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;
-
-	/*
-	 *  Memory limit
-	 */
-	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > sgivwfb_mem_size)
-		return -ENOMEM;	/* Virtual resolution to high */
-
-	info->fix.line_length = line_length;
-
-	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:		/* RGBA 5551 */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 6;
-		var->green.length = 5;
-		var->blue.offset = 1;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGB 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;
-
-	/* set video timing information */
-	var->pixclock = KHZ2PICOS(timing->cfreq);
-	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;
-
-	/* Ouch. This breaks the rules but timing_num is only important if you
-	* change a video mode */
-	par->timing_num = min_mode;
-
-	printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	printk(KERN_INFO "         vxres=%d vyres=%d\n", var->xres_virtual,
-		var->yres_virtual);
-	return 0;
-}
-
-/*
- *  Setup flatpanel related registers.
- */
-static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
-{
-	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
-	u32 outputVal = 0;
-
-	SET_DBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal, 
-		(currentTiming->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
-	SET_DBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal, 
-		(currentTiming->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
-	DBE_SETREG(vt_flags, outputVal);
-
-	/* Turn on the flat panel */
-	switch (flatpanel_id) {
-		case FLATPANEL_SGI_1600SW:
-			fp_wid = 1600;
-			fp_hgt = 1024;
-			fp_vbs = 0;
-			fp_vbe = 1600;
-			currentTiming->pll_m = 4;
-			currentTiming->pll_n = 1;
-			currentTiming->pll_p = 0;
-			break;
-		default:
-      			fp_wid = fp_hgt = fp_vbs = fp_vbe = 0xfff;
-  	}
-
-	outputVal = 0;
-	SET_DBE_FIELD(FP_DE, FP_DE_ON, outputVal, fp_vbs);
-	SET_DBE_FIELD(FP_DE, FP_DE_OFF, outputVal, fp_vbe);
-	DBE_SETREG(fp_de, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(FP_HDRV, FP_HDRV_OFF, outputVal, fp_wid);
-	DBE_SETREG(fp_hdrv, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(FP_VDRV, FP_VDRV_ON, outputVal, 1);
-	SET_DBE_FIELD(FP_VDRV, FP_VDRV_OFF, outputVal, fp_hgt + 1);
-	DBE_SETREG(fp_vdrv, outputVal);
-}
-
-/*
- *  Set the hardware according to 'par'.
- */
-static int sgivwfb_set_par(struct fb_info *info)
-{
-	struct sgivw_par *par = info->par;
-	int i, j, htmp, temp;
-	u32 readVal, outputVal;
-	int wholeTilesX, maxPixelsPerTileX;
-	int frmWrite1, frmWrite2, frmWrite3b;
-	struct dbe_timing_info *currentTiming; /* Current Video Timing */
-	int xpmax, ypmax;	// Monitor resolution
-	int bytesPerPixel;	// Bytes per pixel
-
-	currentTiming = &dbeVTimings[par->timing_num];
-	bytesPerPixel = bytes_per_pixel(info->var.bits_per_pixel);
-	xpmax = currentTiming->width;
-	ypmax = currentTiming->height;
-
-	/* dbe_InitGraphicsBase(); */
-	/* Turn on dotclock PLL */
-	DBE_SETREG(ctrlstat, 0x20000000);
-
-	dbe_TurnOffDma(par);
-
-	/* dbe_CalculateScreenParams(); */
-	maxPixelsPerTileX = 512 / bytesPerPixel;
-	wholeTilesX = xpmax / maxPixelsPerTileX;
-	if (wholeTilesX * maxPixelsPerTileX < xpmax)
-		wholeTilesX++;
-
-	printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
-	       maxPixelsPerTileX, wholeTilesX);
-
-	/* dbe_InitGammaMap(); */
-	udelay(10);
-
-	for (i = 0; i < 256; i++) {
-		DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
-	}
-
-	/* dbe_TurnOn(); */
-	DBE_GETREG(vt_xy, readVal);
-	if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) {
-		DBE_SETREG(vt_xy, 0x00000000);
-		udelay(1);
-	} else
-		dbe_TurnOffDma(par);
-
-	/* dbe_Initdbe(); */
-	for (i = 0; i < 256; i++) {
-		for (j = 0; j < 100; j++) {
-			DBE_GETREG(cm_fifo, readVal);
-			if (readVal != 0x00000000)
-				break;
-			else
-				udelay(10);
-		}
-
-		// DBE_ISETREG(cmap, i, 0x00000000);
-		DBE_ISETREG(cmap, i, (i << 8) | (i << 16) | (i << 24));
-	}
-
-	/* dbe_InitFramebuffer(); */
-	frmWrite1 = 0;
-	SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1,
-		      wholeTilesX);
-	SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
-
-	switch (bytesPerPixel) {
-	case 1:
-		SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
-			      DBE_FRM_DEPTH_8);
-		break;
-	case 2:
-		SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
-			      DBE_FRM_DEPTH_16);
-		break;
-	case 4:
-		SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
-			      DBE_FRM_DEPTH_32);
-		break;
-	}
-
-	frmWrite2 = 0;
-	SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
-
-	// Tell dbe about the framebuffer location and type
-	// XXX What format is the FRM_TILE_PTR??  64K aligned address?
-	frmWrite3b = 0;
-	SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b,
-		      sgivwfb_mem_phys >> 9);
-	SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
-	SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
-
-	/* Initialize DIDs */
-
-	outputVal = 0;
-	switch (bytesPerPixel) {
-	case 1:
-		SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
-		break;
-	case 2:
-		SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
-		break;
-	case 4:
-		SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
-		break;
-	}
-	SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
-
-	for (i = 0; i < 32; i++) {
-		DBE_ISETREG(mode_regs, i, outputVal);
-	}
-
-	/* dbe_InitTiming(); */
-	DBE_SETREG(vt_intr01, 0xffffffff);
-	DBE_SETREG(vt_intr23, 0xffffffff);
-
-	DBE_GETREG(dotclock, readVal);
-	DBE_SETREG(dotclock, readVal & 0xffff);
-
-	DBE_SETREG(vt_xymax, 0x00000000);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal,
-		      currentTiming->vsync_start);
-	SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal,
-		      currentTiming->vsync_end);
-	DBE_SETREG(vt_vsync, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal,
-		      currentTiming->hsync_start);
-	SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal,
-		      currentTiming->hsync_end);
-	DBE_SETREG(vt_hsync, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal,
-		      currentTiming->vblank_start);
-	SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal,
-		      currentTiming->vblank_end);
-	DBE_SETREG(vt_vblank, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal,
-		      currentTiming->hblank_start);
-	SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal,
-		      currentTiming->hblank_end - 3);
-	DBE_SETREG(vt_hblank, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal,
-		      currentTiming->vblank_start);
-	SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal,
-		      currentTiming->vblank_end);
-	DBE_SETREG(vt_vcmap, outputVal);
-	outputVal = 0;
-	SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal,
-		      currentTiming->hblank_start);
-	SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal,
-		      currentTiming->hblank_end - 3);
-	DBE_SETREG(vt_hcmap, outputVal);
-
-	if (flatpanel_id != -1)
-		sgivwfb_setup_flatpanel(par, currentTiming);
-
-	outputVal = 0;
-	temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
-	if (temp > 0)
-		temp = -temp;
-
-	SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32) temp);
-	if (currentTiming->hblank_end >= 20)
-		SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
-			      currentTiming->hblank_end - 20);
-	else
-		SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
-			      currentTiming->htotal - (20 -
-						       currentTiming->
-						       hblank_end));
-	DBE_SETREG(did_start_xy, outputVal);
-
-	outputVal = 0;
-	SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal,
-		      (u32) (temp + 1));
-	if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
-		SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
-			      currentTiming->hblank_end - DBE_CRS_MAGIC);
-	else
-		SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
-			      currentTiming->htotal - (DBE_CRS_MAGIC -
-						       currentTiming->
-						       hblank_end));
-	DBE_SETREG(crs_start_xy, outputVal);
-
-	outputVal = 0;
-	SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32) temp);
-	SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
-		      currentTiming->hblank_end - 4);
-	DBE_SETREG(vc_start_xy, outputVal);
-
-	DBE_SETREG(frm_size_tile, frmWrite1);
-	DBE_SETREG(frm_size_pixel, frmWrite2);
-
-	outputVal = 0;
-	SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m - 1);
-	SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n - 1);
-	SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
-	SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
-	DBE_SETREG(dotclock, outputVal);
-
-	udelay(11 * 1000);
-
-	DBE_SETREG(vt_vpixen, 0xffffff);
-	DBE_SETREG(vt_hpixen, 0xffffff);
-
-	outputVal = 0;
-	SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
-	SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
-	DBE_SETREG(vt_xymax, outputVal);
-
-	outputVal = frmWrite1;
-	SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
-	DBE_SETREG(frm_size_tile, outputVal);
-	DBE_SETREG(frm_size_tile, frmWrite1);
-
-	outputVal = 0;
-	SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
-	DBE_SETREG(ovr_width_tile, outputVal);
-	DBE_SETREG(ovr_width_tile, 0);
-
-	DBE_SETREG(frm_control, frmWrite3b);
-	DBE_SETREG(did_control, 0);
-
-	// Wait for dbe to take frame settings
-	for (i = 0; i < 100000; i++) {
-		DBE_GETREG(frm_inhwctrl, readVal);
-		if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) !=
-		    0)
-			break;
-		else
-			udelay(1);
-	}
-
-	if (i == 100000)
-		printk(KERN_INFO
-		       "sgivwfb: timeout waiting for frame DMA enable.\n");
-
-	outputVal = 0;
-	htmp = currentTiming->hblank_end - 19;
-	if (htmp < 0)
-		htmp += currentTiming->htotal;	/* allow blank to wrap around */
-	SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
-	SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
-		      ((htmp + currentTiming->width -
-			2) % currentTiming->htotal));
-	DBE_SETREG(vt_hpixen, outputVal);
-
-	outputVal = 0;
-	SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
-		      currentTiming->vblank_start);
-	SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
-		      currentTiming->vblank_end);
-	DBE_SETREG(vt_vpixen, outputVal);
-
-	// Turn off mouse cursor
-	par->regs->crs_ctl = 0;
-
-	// XXX What's this section for??
-	DBE_GETREG(ctrlstat, readVal);
-	readVal &= 0x02000000;
-
-	if (readVal != 0) {
-		DBE_SETREG(ctrlstat, 0x30000000);
-	}
-	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 sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
-			     u_int blue, u_int transp,
-			     struct fb_info *info)
-{
-	struct sgivw_par *par = (struct sgivw_par *) info->par;
-
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	/* wait for the color map FIFO to have a free entry */
-	while (par->cmap_fifo == 0)
-		par->cmap_fifo = par->regs->cm_fifo;
-
-	par->regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
-	par->cmap_fifo--;	/* assume FIFO is filling up */
-	return 0;
-}
-
-static int sgivwfb_mmap(struct fb_info *info,
-			struct vm_area_struct *vma)
-{
-	int r;
-
-	pgprot_val(vma->vm_page_prot) =
-		pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
-
-	r = vm_iomap_memory(vma, sgivwfb_mem_phys, sgivwfb_mem_size);
-
-	printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
-		sgivwfb_mem_phys + (vma->vm_pgoff << PAGE_SHIFT), vma->vm_start);
-
-	return r;
-}
-
-int __init sgivwfb_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))
-				flatpanel_id = -1;
-			else if (!strncmp(this_opt + 8, "1600sw", 6))
-				flatpanel_id = FLATPANEL_SGI_1600SW;
-		}
-	}
-	return 0;
-}
-
-/*
- *  Initialisation
- */
-static int sgivwfb_probe(struct platform_device *dev)
-{
-	struct sgivw_par *par;
-	struct fb_info *info;
-	char *monitor;
-
-	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 16, &dev->dev);
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-
-	if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
-		printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
-		framebuffer_release(info);
-		return -EBUSY;
-	}
-
-	par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
-	if (!par->regs) {
-		printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
-		goto fail_ioremap_regs;
-	}
-
-	mtrr_add(sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
-
-	sgivwfb_fix.smem_start = sgivwfb_mem_phys;
-	sgivwfb_fix.smem_len = sgivwfb_mem_size;
-	sgivwfb_fix.ywrapstep = ywrap;
-	sgivwfb_fix.ypanstep = ypan;
-
-	info->fix = sgivwfb_fix;
-
-	switch (flatpanel_id) {
-		case FLATPANEL_SGI_1600SW:
-			info->var = sgivwfb_var1600sw;
-			monitor = "SGI 1600SW flatpanel";
-			break;
-		default:
-			info->var = sgivwfb_var;
-			monitor = "CRT";
-	}
-
-	printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
-
-	info->fbops = &sgivwfb_ops;
-	info->pseudo_palette = (void *) (par + 1);
-	info->flags = FBINFO_DEFAULT;
-
-	info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
-	if (!info->screen_base) {
-		printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
-		goto fail_ioremap_fbmem;
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
-		goto fail_color_map;
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
-		goto fail_register_framebuffer;
-	}
-
-	platform_set_drvdata(dev, info);
-
-	fb_info(info, "SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",
-		sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
-	return 0;
-
-fail_register_framebuffer:
-	fb_dealloc_cmap(&info->cmap);
-fail_color_map:
-	iounmap((char *) info->screen_base);
-fail_ioremap_fbmem:
-	iounmap(par->regs);
-fail_ioremap_regs:
-	release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
-	framebuffer_release(info);
-	return -ENXIO;
-}
-
-static int sgivwfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		struct sgivw_par *par = info->par;
-
-		unregister_framebuffer(info);
-		dbe_TurnOffDma(par);
-		iounmap(par->regs);
-		iounmap(info->screen_base);
-		release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver sgivwfb_driver = {
-	.probe	= sgivwfb_probe,
-	.remove	= sgivwfb_remove,
-	.driver	= {
-		.name	= "sgivwfb",
-	},
-};
-
-static struct platform_device *sgivwfb_device;
-
-int __init sgivwfb_init(void)
-{
-	int ret;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("sgivwfb", &option))
-		return -ENODEV;
-	sgivwfb_setup(option);
-#endif
-	ret = platform_driver_register(&sgivwfb_driver);
-	if (!ret) {
-		sgivwfb_device = platform_device_alloc("sgivwfb", 0);
-		if (sgivwfb_device) {
-			ret = platform_device_add(sgivwfb_device);
-		} else
-			ret = -ENOMEM;
-		if (ret) {
-			platform_driver_unregister(&sgivwfb_driver);
-			platform_device_put(sgivwfb_device);
-		}
-	}
-	return ret;
-}
-
-module_init(sgivwfb_init);
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-static void __exit sgivwfb_exit(void)
-{
-	platform_device_unregister(sgivwfb_device);
-	platform_driver_unregister(&sgivwfb_driver);
-}
-
-module_exit(sgivwfb_exit);
-
-#endif				/* MODULE */
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 4f26bc28e60b..000000000000
--- a/drivers/video/sis/init.c
+++ /dev/null
@@ -1,3654 +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];
-	     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 07c7df9ee77b..000000000000
--- a/drivers/video/tgafb.c
+++ /dev/null
@@ -1,1763 +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->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 64 bytes.  */
-	if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 64)
-		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;
-
-	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 general case of forward copy in 8bpp mode.  */
-static inline void
-copyarea_foreward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
-		       u32 height, u32 width, u32 line_length)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	unsigned long i, copied, left;
-	unsigned long dpos, spos, dalign, salign, yincr;
-	u32 smask_first, dmask_first, dmask_last;
-	int pixel_shift, need_prime, need_second;
-	unsigned long n64, n32, xincr_first;
-	void __iomem *tga_regs;
-	void __iomem *tga_fb;
-
-	yincr = line_length;
-	if (dy > sy) {
-		dy += height - 1;
-		sy += height - 1;
-		yincr = -yincr;
-	}
-
-	/* Compute the offsets and alignments in the frame buffer.
-	   More than anything else, these control how we do copies.  */
-	dpos = dy * line_length + dx;
-	spos = sy * line_length + sx;
-	dalign = dpos & 7;
-	salign = spos & 7;
-	dpos &= -8;
-	spos &= -8;
-
-	/* Compute the value for the PIXELSHIFT register.  This controls
-	   both non-co-aligned source and destination and copy direction.  */
-	if (dalign >= salign)
-		pixel_shift = dalign - salign;
-	else
-		pixel_shift = 8 - (salign - dalign);
-
-	/* Figure out if we need an additional priming step for the
-	   residue register.  */
-	need_prime = (salign > dalign);
-	if (need_prime)
-		dpos -= 8;
-
-	/* Begin by copying the leading unaligned destination.  Copy enough
-	   to make the next destination address 32-byte aligned.  */
-	copied = 32 - (dalign + (dpos & 31));
-	if (copied == 32)
-		copied = 0;
-	xincr_first = (copied + 7) & -8;
-	smask_first = dmask_first = (1ul << copied) - 1;
-	smask_first <<= salign;
-	dmask_first <<= dalign + need_prime*8;
-	if (need_prime && copied > 24)
-		copied -= 8;
-	left = width - copied;
-
-	/* Care for small copies.  */
-	if (copied > width) {
-		u32 t;
-		t = (1ul << width) - 1;
-		t <<= dalign + need_prime*8;
-		dmask_first &= t;
-		left = 0;
-	}
-
-	/* Attempt to use 64-byte copies.  This is only possible if the
-	   source and destination are co-aligned at 64 bytes.  */
-	n64 = need_second = 0;
-	if ((dpos & 63) == (spos & 63)
-	    && (height == 1 || line_length % 64 == 0)) {
-		/* We may need a 32-byte copy to ensure 64 byte alignment.  */
-		need_second = (dpos + xincr_first) & 63;
-		if ((need_second & 32) != need_second)
-			printk(KERN_ERR "tgafb: need_second wrong\n");
-		if (left >= need_second + 64) {
-			left -= need_second;
-			n64 = left / 64;
-			left %= 64;
-		} else
-			need_second = 0;
-	}
-
-	/* Copy trailing full 32-byte sections.  This will be the main
-	   loop if the 64 byte loop can't be used.  */
-	n32 = left / 32;
-	left %= 32;
-
-	/* Copy the trailing unaligned destination.  */
-	dmask_last = (1ul << left) - 1;
-
-	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(pixel_shift, tga_regs+TGA_PIXELSHIFT_REG);
-	wmb();
-
-	for (i = 0; i < height; ++i) {
-		unsigned long j;
-		void __iomem *sfb;
-		void __iomem *dfb;
-
-		sfb = tga_fb + spos;
-		dfb = tga_fb + dpos;
-		if (dmask_first) {
-			__raw_writel(smask_first, sfb);
-			wmb();
-			__raw_writel(dmask_first, dfb);
-			wmb();
-			sfb += xincr_first;
-			dfb += xincr_first;
-		}
-
-		if (need_second) {
-			__raw_writel(0xffffffff, sfb);
-			wmb();
-			__raw_writel(0xffffffff, dfb);
-			wmb();
-			sfb += 32;
-			dfb += 32;
-		}
-
-		if (n64 && (((unsigned long)sfb | (unsigned long)dfb) & 63))
-			printk(KERN_ERR
-			       "tgafb: misaligned copy64 (s:%p, d:%p)\n",
-			       sfb, dfb);
-
-		for (j = 0; j < n64; ++j) {
-			__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;
-		}
-
-		for (j = 0; j < n32; ++j) {
-			__raw_writel(0xffffffff, sfb);
-			wmb();
-			__raw_writel(0xffffffff, dfb);
-			wmb();
-			sfb += 32;
-			dfb += 32;
-		}
-
-		if (dmask_last) {
-			__raw_writel(0xffffffff, sfb);
-			wmb();
-			__raw_writel(dmask_last, dfb);
-			wmb();
-		}
-
-		spos += yincr;
-		dpos += yincr;
-	}
-
-	/* Reset the MODE register to normal.  */
-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
-}
-
-/* The (almost) general case of backward copy in 8bpp mode.  */
-static inline void
-copyarea_backward_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 long i, left, yincr;
-	unsigned long depos, sepos, dealign, sealign;
-	u32 mask_first, mask_last;
-	unsigned long n32;
-	void __iomem *tga_regs;
-	void __iomem *tga_fb;
-
-	yincr = line_length;
-	if (dy > sy) {
-		dy += height - 1;
-		sy += height - 1;
-		yincr = -yincr;
-	}
-
-	/* Compute the offsets and alignments in the frame buffer.
-	   More than anything else, these control how we do copies.  */
-	depos = dy * line_length + dx + width;
-	sepos = sy * line_length + sx + width;
-	dealign = depos & 7;
-	sealign = sepos & 7;
-
-	/* ??? The documentation appears to be incorrect (or very
-	   misleading) wrt how pixel shifting works in backward copy
-	   mode, i.e. when PIXELSHIFT is negative.  I give up for now.
-	   Do handle the common case of co-aligned backward copies,
-	   but frob everything else back on generic code.  */
-	if (dealign != sealign) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	/* We begin the copy with the trailing pixels of the
-	   unaligned destination.  */
-	mask_first = (1ul << dealign) - 1;
-	left = width - dealign;
-
-	/* Care for small copies.  */
-	if (dealign > width) {
-		mask_first ^= (1ul << (dealign - width)) - 1;
-		left = 0;
-	}
-
-	/* Next copy full words at a time.  */
-	n32 = left / 32;
-	left %= 32;
-
-	/* Finally copy the unaligned head of the span.  */
-	mask_last = -1 << (32 - left);
-
-	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;
-		if (mask_first) {
-			__raw_writel(mask_first, sfb);
-			wmb();
-			__raw_writel(mask_first, dfb);
-			wmb();
-		}
-
-		for (j = 0; j < n32; ++j) {
-			sfb -= 32;
-			dfb -= 32;
-			__raw_writel(0xffffffff, sfb);
-			wmb();
-			__raw_writel(0xffffffff, dfb);
-			wmb();
-		}
-
-		if (mask_last) {
-			sfb -= 32;
-			dfb -= 32;
-			__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 (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);
-
-	/* Detect overlapping source and destination that requires
-	   a backward copy.  */
-	else if (dy == sy && dx > sx && dx < sx + width)
-		copyarea_backward_8bpp(info, dx, dy, sx, sy, height,
-				       width, line_length, area);
-	else
-		copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,
-				       width, line_length);
-}
-
-
-/*
- *  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;
-
-	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";
-		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";
-		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";
-		break;
-	}
-	if (!tga_type_name)
-		tga_type_name = "Unknown";
-
-	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.line_length = par->xres * (par->bits_per_pixel >> 3);
-	info->fix.smem_start = (size_t) par->tga_fb_base;
-	info->fix.smem_len = info->fix.line_length * par->yres;
-	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;
-	}
-	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);
-	tgafb_init_fix(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 256fba7f4641..000000000000
--- a/drivers/video/uvesafb.c
+++ /dev/null
@@ -1,2035 +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, 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, 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.
-	 */
-	if (mode != NULL) {
-		size_vmode = info->var.yres * mode->bytes_per_scan_line;
-	} else {
-		size_vmode = info->var.yres * info->var.xres *
-			     ((info->var.bits_per_pixel + 7) >> 3);
-	}
-
-	/*
-	 *   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);
-
-		if (par) {
-			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 1c7da3b098d6..000000000000
--- a/drivers/video/vesafb.c
+++ /dev/null
@@ -1,511 +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);
-	framebuffer_release(info);
-}
-
-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;
-	}
-	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 struct platform_driver vesafb_driver = {
-	.driver = {
-		.name = "vesa-framebuffer",
-		.owner = THIS_MODULE,
-	},
-	.probe = vesafb_probe,
-};
-
-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 6ff1a91e9dfd..000000000000
--- a/drivers/video/xilinxfb.c
+++ /dev/null
@@ -1,496 +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/xilinxfb.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() */
-
-/*
- * 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/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 28b5338fff71..7ae3cba2f624 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/hrtimer.h>
+#include <linux/kmemleak.h>
 
 #ifdef DEBUG
 /* For development, we want to crash whenever the ring is screwed. */
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c
index 1b5d48c578e1..bfb2d3f06738 100644
--- a/drivers/vme/bridges/vme_ca91cx42.c
+++ b/drivers/vme/bridges/vme_ca91cx42.c
@@ -869,14 +869,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
 
 	spin_lock(&image->lock);
 
-	/* The following code handles VME address alignment problem
-	 * in order to assure the maximal data width cycle.
-	 * We cannot use memcpy_xxx directly here because it
-	 * may cut data transfer in 8-bits cycles, thus making
-	 * D16 cycle impossible.
-	 * From the other hand, the bridge itself assures that
-	 * maximal configured data cycle is used and splits it
-	 * automatically for non-aligned addresses.
+	/* The following code handles VME address alignment. We cannot use
+	 * memcpy_xxx here because it may cut data transfers in to 8-bit
+	 * cycles when D16 or D32 cycles are required on the VME bus.
+	 * On the other hand, the bridge itself assures that the maximum data
+	 * cycle configured for the transfer is used and splits it
+	 * automatically for non-aligned addresses, so we don't want the
+	 * overhead of needlessly forcing small transfers for the entire cycle.
 	 */
 	if ((uintptr_t)addr & 0x1) {
 		*(u8 *)buf = ioread8(addr);
@@ -896,9 +895,9 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
 	}
 
 	count32 = (count - done) & ~0x3;
-	if (count32 > 0) {
-		memcpy_fromio(buf + done, addr + done, (unsigned int)count);
-		done += count32;
+	while (done < count32) {
+		*(u32 *)(buf + done) = ioread32(addr + done);
+		done += 4;
 	}
 
 	if ((count - done) & 0x2) {
@@ -930,7 +929,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
 	spin_lock(&image->lock);
 
 	/* Here we apply for the same strategy we do in master_read
-	 * function in order to assure D16 cycle when required.
+	 * function in order to assure the correct cycles.
 	 */
 	if ((uintptr_t)addr & 0x1) {
 		iowrite8(*(u8 *)buf, addr);
@@ -950,9 +949,9 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
 	}
 
 	count32 = (count - done) & ~0x3;
-	if (count32 > 0) {
-		memcpy_toio(addr + done, buf + done, count32);
-		done += count32;
+	while (done < count32) {
+		iowrite32(*(u32 *)(buf + done), addr + done);
+		done += 4;
 	}
 
 	if ((count - done) & 0x2) {
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 9911cd5fddb5..06990c6a1a69 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -1276,8 +1276,8 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
 	spin_lock(&image->lock);
 
 	/* The following code handles VME address alignment. We cannot use
-	 * memcpy_xxx directly here because it may cut small data transfers in
-	 * to 8-bit cycles, thus making D16 cycle impossible.
+	 * memcpy_xxx here because it may cut data transfers in to 8-bit
+	 * cycles when D16 or D32 cycles are required on the VME bus.
 	 * On the other hand, the bridge itself assures that the maximum data
 	 * cycle configured for the transfer is used and splits it
 	 * automatically for non-aligned addresses, so we don't want the
@@ -1301,9 +1301,9 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
 	}
 
 	count32 = (count - done) & ~0x3;
-	if (count32 > 0) {
-		memcpy_fromio(buf + done, addr + done, count32);
-		done += count32;
+	while (done < count32) {
+		*(u32 *)(buf + done) = ioread32(addr + done);
+		done += 4;
 	}
 
 	if ((count - done) & 0x2) {
@@ -1363,7 +1363,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
 	spin_lock(&image->lock);
 
 	/* Here we apply for the same strategy we do in master_read
-	 * function in order to assure D16 cycle when required.
+	 * function in order to assure the correct cycles.
 	 */
 	if ((uintptr_t)addr & 0x1) {
 		iowrite8(*(u8 *)buf, addr);
@@ -1383,9 +1383,9 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
 	}
 
 	count32 = (count - done) & ~0x3;
-	if (count32 > 0) {
-		memcpy_toio(addr + done, buf + done, count32);
-		done += count32;
+	while (done < count32) {
+		iowrite32(*(u32 *)(buf + done), addr + done);
+		done += 4;
 	}
 
 	if ((count - done) & 0x2) {
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index efc7f075fcbe..1708b2300c7a 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -36,13 +36,12 @@ config W1_MASTER_DS2482
 
 config W1_MASTER_MXC
 	tristate "Freescale MXC 1-wire busmaster"
-	depends on W1 && ARCH_MXC
+	depends on ARCH_MXC || COMPILE_TEST
 	help
 	  Say Y here to enable MXC 1-wire host
 
 config W1_MASTER_DS1WM
 	tristate "Maxim DS1WM 1-wire busmaster"
-	depends on W1
 	help
 	  Say Y here to enable the DS1WM 1-wire driver, such as that
 	  in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 4f7e1d770f81..7404ad3062b7 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -1,5 +1,5 @@
 /*
- *	dscore.c
+ *	ds2490.c  USB to one wire bridge
  *
  * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
@@ -28,6 +28,10 @@
 #include "../w1_int.h"
 #include "../w1.h"
 
+/* USB Standard */
+/* USB Control request vendor type */
+#define VENDOR				0x40
+
 /* COMMAND TYPE CODES */
 #define CONTROL_CMD			0x00
 #define COMM_CMD			0x01
@@ -107,6 +111,8 @@
 #define ST_HALT				0x10  /* DS2490 is currently halted */
 #define ST_IDLE				0x20  /* DS2490 is currently idle */
 #define ST_EPOF				0x80
+/* Status transfer size, 16 bytes status, 16 byte result flags */
+#define ST_SIZE				0x20
 
 /* Result Register flags */
 #define RR_DETECT			0xA5 /* New device detected */
@@ -198,7 +204,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
 	int err;
 
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+			CONTROL_CMD, VENDOR, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
 				value, index, err);
@@ -213,7 +219,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
 	int err;
 
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+			MODE_CMD, VENDOR, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
 				value, index, err);
@@ -228,7 +234,7 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
 	int err;
 
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+			COMM_CMD, VENDOR, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
 				value, index, err);
@@ -246,7 +252,8 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
 	memset(st, 0, sizeof(*st));
 
 	count = 0;
-	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+	err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev,
+		dev->ep[EP_STATUS]), buf, size, &count, 100);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
 		return err;
@@ -353,7 +360,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
 				buf, size, &count, 1000);
 	if (err < 0) {
-		u8 buf[0x20];
+		u8 buf[ST_SIZE];
 		int count;
 
 		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
@@ -398,7 +405,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)
 {
 	struct ds_status st;
 	int count = 0, err = 0;
-	u8 buf[0x20];
+	u8 buf[ST_SIZE];
 
 	do {
 		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
@@ -450,10 +457,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
 
 static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 {
-	u8 buf[0x20];
+	u8 buf[ST_SIZE];
 	int err, count = 0;
 
 	do {
+		st->status = 0;
 		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
 #if 0
 		if (err >= 0) {
@@ -464,7 +472,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 			printk("\n");
 		}
 #endif
-	} while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100);
+	} while (!(st->status & ST_IDLE) && !(err < 0) && ++count < 100);
 
 	if (err >= 16 && st->status & ST_EPOF) {
 		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
@@ -690,37 +698,106 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
 	return !(err == len);
 }
 
-#if 0
-
-static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+static void ds9490r_search(void *data, struct w1_master *master,
+	u8 search_type, w1_slave_found_callback callback)
 {
+	/* When starting with an existing id, the first id returned will
+	 * be that device (if it is still on the bus most likely).
+	 *
+	 * If the number of devices found is less than or equal to the
+	 * search_limit, that number of IDs will be returned.  If there are
+	 * more, search_limit IDs will be returned followed by a non-zero
+	 * discrepency value.
+	 */
+	struct ds_device *dev = data;
 	int err;
 	u16 value, index;
 	struct ds_status st;
+	u8 st_buf[ST_SIZE];
+	int search_limit;
+	int found = 0;
+	int i;
 
-	memset(buf, 0, sizeof(buf));
+	/* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for
+	 * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time.
+	 */
+	const unsigned long jtime = msecs_to_jiffies(1000*8/75);
+	/* FIFO 128 bytes, bulk packet size 64, read a multiple of the
+	 * packet size.
+	 */
+	u64 buf[2*64/8];
 
-	err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
-	if (err)
-		return err;
+	mutex_lock(&master->bus_mutex);
 
-	ds_wait_status(ds_dev, &st);
+	/* address to start searching at */
+	if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0)
+		goto search_out;
+	master->search_id = 0;
 
-	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
-	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
-	err = ds_send_control(ds_dev, value, index);
-	if (err)
-		return err;
+	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F |
+		COMM_RTS;
+	search_limit = master->max_slave_count;
+	if (search_limit > 255)
+		search_limit = 0;
+	index = search_type | (search_limit << 8);
+	if (ds_send_control(dev, value, index) < 0)
+		goto search_out;
 
-	ds_wait_status(ds_dev, &st);
+	do {
+		schedule_timeout(jtime);
 
-	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
-	if (err < 0)
-		return err;
+		if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) <
+			sizeof(st)) {
+			break;
+		}
 
-	return err/8;
+		if (st.data_in_buffer_status) {
+			/* Bulk in can receive partial ids, but when it does
+			 * they fail crc and will be discarded anyway.
+			 * That has only been seen when status in buffer
+			 * is 0 and bulk is read anyway, so don't read
+			 * bulk without first checking if status says there
+			 * is data to read.
+			 */
+			err = ds_recv_data(dev, (u8 *)buf, sizeof(buf));
+			if (err < 0)
+				break;
+			for (i = 0; i < err/8; ++i) {
+				++found;
+				if (found <= search_limit)
+					callback(master, buf[i]);
+				/* can't know if there will be a discrepancy
+				 * value after until the next id */
+				if (found == search_limit)
+					master->search_id = buf[i];
+			}
+		}
+
+		if (test_bit(W1_ABORT_SEARCH, &master->flags))
+			break;
+	} while (!(st.status & (ST_IDLE | ST_HALT)));
+
+	/* only continue the search if some weren't found */
+	if (found <= search_limit) {
+		master->search_id = 0;
+	} else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) {
+		/* Only max_slave_count will be scanned in a search,
+		 * but it will start where it left off next search
+		 * until all ids are identified and then it will start
+		 * over.  A continued search will report the previous
+		 * last id as the first id (provided it is still on the
+		 * bus).
+		 */
+		dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, "
+			"will continue next search.\n", __func__,
+			master->max_slave_count);
+		set_bit(W1_WARN_MAX_COUNT, &master->flags);
+	}
+search_out:
+	mutex_unlock(&master->bus_mutex);
 }
 
+#if 0
 static int ds_match_access(struct ds_device *dev, u64 init)
 {
 	int err;
@@ -894,6 +971,7 @@ static int ds_w1_init(struct ds_device *dev)
 	dev->master.write_block	= &ds9490r_write_block;
 	dev->master.reset_bus	= &ds9490r_reset;
 	dev->master.set_pullup	= &ds9490r_set_pullup;
+	dev->master.search	= &ds9490r_search;
 
 	return w1_add_master_device(&dev->master);
 }
@@ -910,15 +988,13 @@ static int ds_probe(struct usb_interface *intf,
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_host_interface *iface_desc;
 	struct ds_device *dev;
-	int i, err;
+	int i, err, alt;
 
-	dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL);
 	if (!dev) {
 		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
 		return -ENOMEM;
 	}
-	dev->spu_sleep = 0;
-	dev->spu_bit = 0;
 	dev->udev = usb_get_dev(udev);
 	if (!dev->udev) {
 		err = -ENOMEM;
@@ -928,20 +1004,25 @@ static int ds_probe(struct usb_interface *intf,
 
 	usb_set_intfdata(intf, dev);
 
-	err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+	err = usb_reset_configuration(dev->udev);
 	if (err) {
-		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
-				intf->altsetting[0].desc.bInterfaceNumber, err);
+		dev_err(&dev->udev->dev,
+			"Failed to reset configuration: err=%d.\n", err);
 		goto err_out_clear;
 	}
 
-	err = usb_reset_configuration(dev->udev);
+	/* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */
+	alt = 3;
+	err = usb_set_interface(dev->udev,
+		intf->altsetting[alt].desc.bInterfaceNumber, alt);
 	if (err) {
-		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+		dev_err(&dev->udev->dev, "Failed to set alternative setting %d "
+			"for %d interface: err=%d.\n", alt,
+			intf->altsetting[alt].desc.bInterfaceNumber, err);
 		goto err_out_clear;
 	}
 
-	iface_desc = &intf->altsetting[0];
+	iface_desc = &intf->altsetting[alt];
 	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
 		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
 		err = -EINVAL;
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 1e5d94c5afc9..67b067a3e2ab 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -10,24 +10,16 @@
  * 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 
 #include "../w1.h"
 #include "../w1_int.h"
-#include "../w1_log.h"
 
 /* According to the mx27 Datasheet the reset procedure should take up to about
  * 1350us. We set the timeout to 500*100us = 50ms for sure */
@@ -36,13 +28,13 @@
 /*
  * MXC W1 Register offsets
  */
-#define MXC_W1_CONTROL          0x00
-#define MXC_W1_TIME_DIVIDER     0x02
-#define MXC_W1_RESET            0x04
-#define MXC_W1_COMMAND          0x06
-#define MXC_W1_TXRX             0x08
-#define MXC_W1_INTERRUPT        0x0A
-#define MXC_W1_INTERRUPT_EN     0x0C
+#define MXC_W1_CONTROL		0x00
+# define MXC_W1_CONTROL_RDST	BIT(3)
+# define MXC_W1_CONTROL_WR(x)	BIT(5 - (x))
+# define MXC_W1_CONTROL_PST	BIT(6)
+# define MXC_W1_CONTROL_RPP	BIT(7)
+#define MXC_W1_TIME_DIVIDER	0x02
+#define MXC_W1_RESET		0x04
 
 struct mxc_w1_device {
 	void __iomem *regs;
@@ -61,12 +53,12 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
 	unsigned int timeout_cnt = 0;
 	struct mxc_w1_device *dev = data;
 
-	__raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL));
+	writeb(MXC_W1_CONTROL_RPP, (dev->regs + MXC_W1_CONTROL));
 
 	while (1) {
-		reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL);
+		reg_val = readb(dev->regs + MXC_W1_CONTROL);
 
-		if (((reg_val >> 7) & 0x1) == 0 ||
+		if (!(reg_val & MXC_W1_CONTROL_RPP) ||
 		    timeout_cnt > MXC_W1_RESET_TIMEOUT)
 			break;
 		else
@@ -74,7 +66,7 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
 
 		udelay(100);
 	}
-	return (reg_val >> 7) & 0x1;
+	return !!(reg_val & MXC_W1_CONTROL_PST);
 }
 
 /*
@@ -90,16 +82,16 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
 					 * datasheet.
 					 */
 
-	__raw_writeb((1 << (5 - bit)), ctrl_addr);
+	writeb(MXC_W1_CONTROL_WR(bit), ctrl_addr);
 
 	while (timeout_cnt--) {
-		if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1))
+		if (!(readb(ctrl_addr) & MXC_W1_CONTROL_WR(bit)))
 			break;
 
 		udelay(1);
 	}
 
-	return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
+	return !!(readb(ctrl_addr) & MXC_W1_CONTROL_RDST);
 }
 
 static int mxc_w1_probe(struct platform_device *pdev)
@@ -139,7 +131,7 @@ static int mxc_w1_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	__raw_writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);
+	writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);
 
 	mdev->bus_master.data = mdev;
 	mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus;
@@ -177,6 +169,7 @@ MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids);
 static struct platform_driver mxc_w1_driver = {
 	.driver = {
 		.name = "mxc_w1",
+		.owner = THIS_MODULE,
 		.of_match_table = mxc_w1_dt_ids,
 	},
 	.probe = mxc_w1_probe,
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 9709b8b484ba..1d111e56c8c8 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -89,11 +89,22 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
 		pdata->is_open_drain = 1;
 
 	gpio = of_get_gpio(np, 0);
-	if (gpio < 0)
+	if (gpio < 0) {
+		if (gpio != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+					"Failed to parse gpio property for data pin (%d)\n",
+					gpio);
+
 		return gpio;
+	}
 	pdata->pin = gpio;
 
-	pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
+	gpio = of_get_gpio(np, 1);
+	if (gpio == -EPROBE_DEFER)
+		return gpio;
+	/* ignore other errors as the pullup gpio is optional */
+	pdata->ext_pullup_enable_pin = gpio;
+
 	pdev->dev.platform_data = pdata;
 
 	return 0;
@@ -107,10 +118,8 @@ static int w1_gpio_probe(struct platform_device *pdev)
 
 	if (of_have_populated_dt()) {
 		err = w1_gpio_probe_dt(pdev);
-		if (err < 0) {
-			dev_err(&pdev->dev, "Failed to parse DT\n");
+		if (err < 0)
 			return err;
-		}
 	}
 
 	pdata = dev_get_platdata(&pdev->dev);
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 5e6a3c9e510b..1cdce80b6abf 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -72,7 +72,6 @@ config W1_SLAVE_DS2433_CRC
 
 config W1_SLAVE_DS2760
 	tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
-	depends on W1
 	help
 	  If you enable this you will have the DS2760 battery monitor
 	  chip support.
@@ -85,7 +84,6 @@ config W1_SLAVE_DS2760
 
 config W1_SLAVE_DS2780
 	tristate "Dallas 2780 battery monitor chip"
-	depends on W1
 	help
 	  If you enable this you will have the DS2780 battery monitor
 	  chip support.
@@ -98,7 +96,6 @@ config W1_SLAVE_DS2780
 
 config W1_SLAVE_DS2781
 	tristate "Dallas 2781 battery monitor chip"
-	depends on W1
 	help
 	  If you enable this you will have the DS2781 battery monitor
 	  chip support.
@@ -111,7 +108,6 @@ config W1_SLAVE_DS2781
 
 config W1_SLAVE_DS28E04
 	tristate "4096-Bit Addressable 1-Wire EEPROM with PIO (DS28E04-100)"
-	depends on W1
 	select CRC16
 	help
 	  If you enable this you will have the DS28E04-100
@@ -124,7 +120,6 @@ config W1_SLAVE_DS28E04
 
 config W1_SLAVE_BQ27000
 	tristate "BQ27000 slave support"
-	depends on W1
 	help
 	  Say Y here if you want to use a hdq
 	  bq27000 slave support.
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 8b5ff33f72cf..1f11a20a8ab9 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 
 #include "../w1.h"
@@ -58,6 +59,19 @@ MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00));
 static int w1_strong_pullup = 1;
 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
 
+static int w1_therm_add_slave(struct w1_slave *sl)
+{
+	sl->family_data = kzalloc(9, GFP_KERNEL);
+	if (!sl->family_data)
+		return -ENOMEM;
+	return 0;
+}
+
+static void w1_therm_remove_slave(struct w1_slave *sl)
+{
+	kfree(sl->family_data);
+	sl->family_data = NULL;
+}
 
 static ssize_t w1_slave_show(struct device *device,
 	struct device_attribute *attr, char *buf);
@@ -71,6 +85,8 @@ static struct attribute *w1_therm_attrs[] = {
 ATTRIBUTE_GROUPS(w1_therm);
 
 static struct w1_family_ops w1_therm_fops = {
+	.add_slave	= w1_therm_add_slave,
+	.remove_slave	= w1_therm_remove_slave,
 	.groups		= w1_therm_groups,
 };
 
@@ -253,12 +269,13 @@ static ssize_t w1_slave_show(struct device *device,
 	c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
 			   crc, (verdict) ? "YES" : "NO");
 	if (verdict)
-		memcpy(sl->rom, rom, sizeof(sl->rom));
+		memcpy(sl->family_data, rom, sizeof(rom));
 	else
 		dev_warn(device, "Read failed CRC check\n");
 
 	for (i = 0; i < 9; ++i)
-		c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", sl->rom[i]);
+		c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ",
+			      ((u8 *)sl->family_data)[i]);
 
 	c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
 		w1_convert_temp(rom, sl->family->fid));
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 66efa96c4603..b96f61b15dc6 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -46,18 +46,29 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
 static int w1_timeout = 10;
-int w1_max_slave_count = 10;
+int w1_max_slave_count = 64;
 int w1_max_slave_ttl = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
+MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
+/* A search stops when w1_max_slave_count devices have been found in that
+ * search.  The next search will start over and detect the same set of devices
+ * on a static 1-wire bus.  Memory is not allocated based on this number, just
+ * on the number of devices known to the kernel.  Having a high number does not
+ * consume additional resources.  As a special case, if there is only one
+ * device on the network and w1_max_slave_count is set to 1, the device id can
+ * be read directly skipping the normal slower search process.
+ */
 module_param_named(max_slave_count, w1_max_slave_count, int, 0);
+MODULE_PARM_DESC(max_slave_count,
+	"maximum number of slaves detected in a search");
 module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
+MODULE_PARM_DESC(slave_ttl,
+	"Number of searches not seeing a slave before it will be removed");
 
 DEFINE_MUTEX(w1_mlock);
 LIST_HEAD(w1_masters);
 
-static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn);
-
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -81,19 +92,10 @@ static void w1_slave_release(struct device *dev)
 {
 	struct w1_slave *sl = dev_to_w1_slave(dev);
 
-	dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
-
-	while (atomic_read(&sl->refcnt)) {
-		dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
-				sl->name, atomic_read(&sl->refcnt));
-		if (msleep_interruptible(1000))
-			flush_signals(current);
-	}
+	dev_dbg(dev, "%s: Releasing %s [%p]\n", __func__, sl->name, sl);
 
 	w1_family_put(sl->family);
 	sl->master->slave_count--;
-
-	complete(&sl->released);
 }
 
 static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -243,7 +245,9 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
 	mutex_lock(&md->mutex);
 	md->search_count = tmp;
 	mutex_unlock(&md->mutex);
-	wake_up_process(md->thread);
+	/* Only wake if it is going to be searching. */
+	if (tmp)
+		wake_up_process(md->thread);
 
 	return count;
 }
@@ -277,7 +281,6 @@ static ssize_t w1_master_attribute_store_pullup(struct device *dev,
 	mutex_lock(&md->mutex);
 	md->enable_pullup = tmp;
 	mutex_unlock(&md->mutex);
-	wake_up_process(md->thread);
 
 	return count;
 }
@@ -314,6 +317,24 @@ static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct devic
 	return count;
 }
 
+static ssize_t w1_master_attribute_store_max_slave_count(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int tmp;
+	struct w1_master *md = dev_to_w1_master(dev);
+
+	if (kstrtoint(buf, 0, &tmp) == -EINVAL || tmp < 1)
+		return -EINVAL;
+
+	mutex_lock(&md->mutex);
+	md->max_slave_count = tmp;
+	/* allow each time the max_slave_count is updated */
+	clear_bit(W1_WARN_MAX_COUNT, &md->flags);
+	mutex_unlock(&md->mutex);
+
+	return count;
+}
+
 static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_master *md = dev_to_w1_master(dev);
@@ -352,23 +373,20 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev,
 {
 	struct w1_master *md = dev_to_w1_master(dev);
 	int c = PAGE_SIZE;
+	struct list_head *ent, *n;
+	struct w1_slave *sl = NULL;
 
-	mutex_lock(&md->mutex);
-
-	if (md->slave_count == 0)
-		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
-	else {
-		struct list_head *ent, *n;
-		struct w1_slave *sl;
+	mutex_lock(&md->list_mutex);
 
-		list_for_each_safe(ent, n, &md->slist) {
-			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+	list_for_each_safe(ent, n, &md->slist) {
+		sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
-			c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
-		}
+		c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
 	}
+	if (!sl)
+		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
 
-	mutex_unlock(&md->mutex);
+	mutex_unlock(&md->list_mutex);
 
 	return PAGE_SIZE - c;
 }
@@ -422,19 +440,22 @@ static int w1_atoreg_num(struct device *dev, const char *buf, size_t count,
 }
 
 /* Searches the slaves in the w1_master and returns a pointer or NULL.
- * Note: must hold the mutex
+ * Note: must not hold list_mutex
  */
-static struct w1_slave *w1_slave_search_device(struct w1_master *dev,
+struct w1_slave *w1_slave_search_device(struct w1_master *dev,
 	struct w1_reg_num *rn)
 {
 	struct w1_slave *sl;
+	mutex_lock(&dev->list_mutex);
 	list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
 		if (sl->reg_num.family == rn->family &&
 				sl->reg_num.id == rn->id &&
 				sl->reg_num.crc == rn->crc) {
+			mutex_unlock(&dev->list_mutex);
 			return sl;
 		}
 	}
+	mutex_unlock(&dev->list_mutex);
 	return NULL;
 }
 
@@ -491,7 +512,10 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
 	mutex_lock(&md->mutex);
 	sl = w1_slave_search_device(md, &rn);
 	if (sl) {
-		w1_slave_detach(sl);
+		result = w1_slave_detach(sl);
+		/* refcnt 0 means it was detached in the call */
+		if (result == 0)
+			result = count;
 	} else {
 		dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family,
 			(unsigned long long)rn.id);
@@ -516,7 +540,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
 static W1_MASTER_ATTR_RO(name, S_IRUGO);
 static W1_MASTER_ATTR_RO(slaves, S_IRUGO);
 static W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
-static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RW(max_slave_count, S_IRUGO | S_IWUSR | S_IWGRP);
 static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
 static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
 static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
@@ -686,12 +710,14 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 	dev_set_uevent_suppress(&sl->dev, false);
 	kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
 
+	mutex_lock(&sl->master->list_mutex);
 	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
+	mutex_unlock(&sl->master->list_mutex);
 
 	return 0;
 }
 
-static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
+int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 {
 	struct w1_slave *sl;
 	struct w1_family *f;
@@ -713,8 +739,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
 	memset(&msg, 0, sizeof(msg));
 	memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
-	atomic_set(&sl->refcnt, 0);
-	init_completion(&sl->released);
+	atomic_set(&sl->refcnt, 1);
+	atomic_inc(&sl->master->refcnt);
 
 	/* slave modules need to be loaded in a context with unlocked mutex */
 	mutex_unlock(&dev->mutex);
@@ -754,23 +780,48 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 	return 0;
 }
 
-void w1_slave_detach(struct w1_slave *sl)
+int w1_unref_slave(struct w1_slave *sl)
 {
-	struct w1_netlink_msg msg;
-
-	dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl);
-
-	list_del(&sl->w1_slave_entry);
-
-	memset(&msg, 0, sizeof(msg));
-	memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
-	msg.type = W1_SLAVE_REMOVE;
-	w1_netlink_send(sl->master, &msg);
-
-	device_unregister(&sl->dev);
+	struct w1_master *dev = sl->master;
+	int refcnt;
+	mutex_lock(&dev->list_mutex);
+	refcnt = atomic_sub_return(1, &sl->refcnt);
+	if (refcnt == 0) {
+		struct w1_netlink_msg msg;
+
+		dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__,
+			sl->name, sl);
+
+		list_del(&sl->w1_slave_entry);
+
+		memset(&msg, 0, sizeof(msg));
+		memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
+		msg.type = W1_SLAVE_REMOVE;
+		w1_netlink_send(sl->master, &msg);
+
+		device_unregister(&sl->dev);
+		#ifdef DEBUG
+		memset(sl, 0, sizeof(*sl));
+		#endif
+		kfree(sl);
+	}
+	atomic_dec(&dev->refcnt);
+	mutex_unlock(&dev->list_mutex);
+	return refcnt;
+}
 
-	wait_for_completion(&sl->released);
-	kfree(sl);
+int w1_slave_detach(struct w1_slave *sl)
+{
+	/* Only detach a slave once as it decreases the refcnt each time. */
+	int destroy_now;
+	mutex_lock(&sl->master->list_mutex);
+	destroy_now = !test_bit(W1_SLAVE_DETACH, &sl->flags);
+	set_bit(W1_SLAVE_DETACH, &sl->flags);
+	mutex_unlock(&sl->master->list_mutex);
+
+	if (destroy_now)
+		destroy_now = !w1_unref_slave(sl);
+	return destroy_now ? 0 : -EBUSY;
 }
 
 struct w1_master *w1_search_master_id(u32 id)
@@ -799,7 +850,7 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id)
 
 	mutex_lock(&w1_mlock);
 	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
-		mutex_lock(&dev->mutex);
+		mutex_lock(&dev->list_mutex);
 		list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
 			if (sl->reg_num.family == id->family &&
 					sl->reg_num.id == id->id &&
@@ -810,7 +861,7 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id)
 				break;
 			}
 		}
-		mutex_unlock(&dev->mutex);
+		mutex_unlock(&dev->list_mutex);
 
 		if (found)
 			break;
@@ -830,6 +881,7 @@ void w1_reconnect_slaves(struct w1_family *f, int attach)
 		dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
 			"for family %02x.\n", dev->name, f->fid);
 		mutex_lock(&dev->mutex);
+		mutex_lock(&dev->list_mutex);
 		list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
 			/* If it is a new family, slaves with the default
 			 * family driver and are that family will be
@@ -841,14 +893,19 @@ void w1_reconnect_slaves(struct w1_family *f, int attach)
 				(!attach && sl->family->fid == f->fid)) {
 				struct w1_reg_num rn;
 
+				mutex_unlock(&dev->list_mutex);
 				memcpy(&rn, &sl->reg_num, sizeof(rn));
-				w1_slave_detach(sl);
-
-				w1_attach_slave_device(dev, &rn);
+				/* If it was already in use let the automatic
+				 * scan pick it up again later.
+				 */
+				if (!w1_slave_detach(sl))
+					w1_attach_slave_device(dev, &rn);
+				mutex_lock(&dev->list_mutex);
 			}
 		}
 		dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
 			"has been finished.\n", dev->name);
+		mutex_unlock(&dev->list_mutex);
 		mutex_unlock(&dev->mutex);
 	}
 	mutex_unlock(&w1_mlock);
@@ -876,7 +933,12 @@ void w1_slave_found(struct w1_master *dev, u64 rn)
 }
 
 /**
- * Performs a ROM Search & registers any devices found.
+ * w1_search() - Performs a ROM Search & registers any devices found.
+ * @dev: The master device to search
+ * @search_type: W1_SEARCH to search all devices, or W1_ALARM_SEARCH
+ * to return only devices in the alarmed state
+ * @cb: Function to call when a device is found
+ *
  * The 1-wire search is a simple binary tree search.
  * For each bit of the address, we read two bits and write one bit.
  * The bit written will put to sleep all devies that don't match that bit.
@@ -886,8 +948,6 @@ void w1_slave_found(struct w1_master *dev, u64 rn)
  *
  * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
  *
- * @dev        The master device to search
- * @cb         Function to call when a device is found
  */
 void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
 {
@@ -898,7 +958,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
 	u8  triplet_ret = 0;
 
 	search_bit = 0;
-	rn = last_rn = 0;
+	rn = dev->search_id;
+	last_rn = 0;
 	last_device = 0;
 	last_zero = -1;
 
@@ -945,7 +1006,7 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
 			else
 				search_bit = ((last_rn >> i) & 0x1);
 
-			/** Read two bits and write one bit */
+			/* Read two bits and write one bit */
 			triplet_ret = w1_triplet(dev, search_bit);
 
 			/* quit if no device responded */
@@ -960,8 +1021,7 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
 			tmp64 = (triplet_ret >> 2);
 			rn |= (tmp64 << i);
 
-			/* ensure we're called from kthread and not by netlink callback */
-			if (!dev->priv && kthread_should_stop()) {
+			if (test_bit(W1_ABORT_SEARCH, &dev->flags)) {
 				mutex_unlock(&dev->bus_mutex);
 				dev_dbg(&dev->dev, "Abort w1_search\n");
 				return;
@@ -970,11 +1030,30 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
 		mutex_unlock(&dev->bus_mutex);
 
 		if ( (triplet_ret & 0x03) != 0x03 ) {
-			if ( (desc_bit == last_zero) || (last_zero < 0))
+			if ((desc_bit == last_zero) || (last_zero < 0)) {
 				last_device = 1;
+				dev->search_id = 0;
+			} else {
+				dev->search_id = rn;
+			}
 			desc_bit = last_zero;
 			cb(dev, rn);
 		}
+
+		if (!last_device && slave_count == dev->max_slave_count &&
+			!test_bit(W1_WARN_MAX_COUNT, &dev->flags)) {
+			/* Only max_slave_count will be scanned in a search,
+			 * but it will start where it left off next search
+			 * until all ids are identified and then it will start
+			 * over.  A continued search will report the previous
+			 * last id as the first id (provided it is still on the
+			 * bus).
+			 */
+			dev_info(&dev->dev, "%s: max_slave_count %d reached, "
+				"will continue next search.\n", __func__,
+				dev->max_slave_count);
+			set_bit(W1_WARN_MAX_COUNT, &dev->flags);
+		}
 	}
 }
 
@@ -983,17 +1062,24 @@ void w1_search_process_cb(struct w1_master *dev, u8 search_type,
 {
 	struct w1_slave *sl, *sln;
 
+	mutex_lock(&dev->list_mutex);
 	list_for_each_entry(sl, &dev->slist, w1_slave_entry)
 		clear_bit(W1_SLAVE_ACTIVE, &sl->flags);
+	mutex_unlock(&dev->list_mutex);
 
 	w1_search_devices(dev, search_type, cb);
 
+	mutex_lock(&dev->list_mutex);
 	list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-		if (!test_bit(W1_SLAVE_ACTIVE, &sl->flags) && !--sl->ttl)
+		if (!test_bit(W1_SLAVE_ACTIVE, &sl->flags) && !--sl->ttl) {
+			mutex_unlock(&dev->list_mutex);
 			w1_slave_detach(sl);
+			mutex_lock(&dev->list_mutex);
+		}
 		else if (test_bit(W1_SLAVE_ACTIVE, &sl->flags))
 			sl->ttl = dev->slave_ttl;
 	}
+	mutex_unlock(&dev->list_mutex);
 
 	if (dev->search_count > 0)
 		dev->search_count--;
@@ -1004,6 +1090,32 @@ static void w1_search_process(struct w1_master *dev, u8 search_type)
 	w1_search_process_cb(dev, search_type, w1_slave_found);
 }
 
+/**
+ * w1_process_callbacks() - execute each dev->async_list callback entry
+ * @dev: w1_master device
+ *
+ * Return: 1 if there were commands to executed 0 otherwise
+ */
+int w1_process_callbacks(struct w1_master *dev)
+{
+	int ret = 0;
+	struct w1_async_cmd *async_cmd, *async_n;
+
+	/* The list can be added to in another thread, loop until it is empty */
+	while (!list_empty(&dev->async_list)) {
+		list_for_each_entry_safe(async_cmd, async_n, &dev->async_list,
+			async_entry) {
+			/* drop the lock, if it is a search it can take a long
+			 * time */
+			mutex_unlock(&dev->list_mutex);
+			async_cmd->cb(dev, async_cmd);
+			ret = 1;
+			mutex_lock(&dev->list_mutex);
+		}
+	}
+	return ret;
+}
+
 int w1_process(void *data)
 {
 	struct w1_master *dev = (struct w1_master *) data;
@@ -1011,23 +1123,46 @@ int w1_process(void *data)
 	 * time can be calculated in jiffies once.
 	 */
 	const unsigned long jtime = msecs_to_jiffies(w1_timeout * 1000);
+	/* remainder if it woke up early */
+	unsigned long jremain = 0;
 
-	while (!kthread_should_stop()) {
-		if (dev->search_count) {
+	for (;;) {
+
+		if (!jremain && dev->search_count) {
 			mutex_lock(&dev->mutex);
 			w1_search_process(dev, W1_SEARCH);
 			mutex_unlock(&dev->mutex);
 		}
 
+		mutex_lock(&dev->list_mutex);
+		/* Note, w1_process_callback drops the lock while processing,
+		 * but locks it again before returning.
+		 */
+		if (!w1_process_callbacks(dev) && jremain) {
+			/* a wake up is either to stop the thread, process
+			 * callbacks, or search, it isn't process callbacks, so
+			 * schedule a search.
+			 */
+			jremain = 1;
+		}
+
 		try_to_freeze();
 		__set_current_state(TASK_INTERRUPTIBLE);
 
+		/* hold list_mutex until after interruptible to prevent loosing
+		 * the wakeup signal when async_cmd is added.
+		 */
+		mutex_unlock(&dev->list_mutex);
+
 		if (kthread_should_stop())
 			break;
 
 		/* Only sleep when the search is active. */
-		if (dev->search_count)
-			schedule_timeout(jtime);
+		if (dev->search_count) {
+			if (!jremain)
+				jremain = jtime;
+			jremain = schedule_timeout(jremain);
+		}
 		else
 			schedule();
 	}
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index ca8081a101d6..734dab7fc687 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -22,6 +22,13 @@
 #ifndef __W1_H
 #define __W1_H
 
+/**
+ * struct w1_reg_num - broken out slave device id
+ *
+ * @family: identifies the type of device
+ * @id: along with family is the unique device id
+ * @crc: checksum of the other bytes
+ */
 struct w1_reg_num
 {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -58,7 +65,24 @@ struct w1_reg_num
 #define W1_RESUME_CMD		0xA5
 
 #define W1_SLAVE_ACTIVE		0
+#define W1_SLAVE_DETACH		1
 
+/**
+ * struct w1_slave - holds a single slave device on the bus
+ *
+ * @owner: Points to the one wire "wire" kernel module.
+ * @name: Device id is ascii.
+ * @w1_slave_entry: data for the linked list
+ * @reg_num: the slave id in binary
+ * @refcnt: reference count, delete when 0
+ * @flags: bit flags for W1_SLAVE_ACTIVE W1_SLAVE_DETACH
+ * @ttl: decrement per search this slave isn't found, deatch at 0
+ * @master: bus which this slave is on
+ * @family: module for device family type
+ * @family_data: pointer for use by the family module
+ * @dev: kernel device identifier
+ *
+ */
 struct w1_slave
 {
 	struct module		*owner;
@@ -66,7 +90,6 @@ struct w1_slave
 	struct list_head	w1_slave_entry;
 	struct w1_reg_num	reg_num;
 	atomic_t		refcnt;
-	u8			rom[9];
 	int			ttl;
 	unsigned long		flags;
 
@@ -74,99 +97,146 @@ struct w1_slave
 	struct w1_family	*family;
 	void			*family_data;
 	struct device		dev;
-	struct completion	released;
 };
 
 typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
 
 
 /**
+ * struct w1_bus_master - operations available on a bus master
+ *
+ * @data: the first parameter in all the functions below
+ *
+ * @read_bit: Sample the line level @return the level read (0 or 1)
+ *
+ * @write_bit: Sets the line level
+ *
+ * @touch_bit: the lowest-level function for devices that really support the
+ * 1-wire protocol.
+ * touch_bit(0) = write-0 cycle
+ * touch_bit(1) = write-1 / read cycle
+ * @return the bit read (0 or 1)
+ *
+ * @read_byte: Reads a bytes. Same as 8 touch_bit(1) calls.
+ * @return the byte read
+ *
+ * @write_byte: Writes a byte. Same as 8 touch_bit(x) calls.
+ *
+ * @read_block: Same as a series of read_byte() calls
+ * @return the number of bytes read
+ *
+ * @write_block: Same as a series of write_byte() calls
+ *
+ * @triplet: Combines two reads and a smart write for ROM searches
+ * @return bit0=Id bit1=comp_id bit2=dir_taken
+ *
+ * @reset_bus: long write-0 with a read for the presence pulse detection
+ * @return -1=Error, 0=Device present, 1=No device present
+ *
+ * @set_pullup: Put out a strong pull-up pulse of the specified duration.
+ * @return -1=Error, 0=completed
+ *
+ * @search: Really nice hardware can handles the different types of ROM search
+ * w1_master* is passed to the slave found callback.
+ * u8 is search_type, W1_SEARCH or W1_ALARM_SEARCH
+ *
  * Note: read_bit and write_bit are very low level functions and should only
  * be used with hardware that doesn't really support 1-wire operations,
  * like a parallel/serial port.
  * Either define read_bit and write_bit OR define, at minimum, touch_bit and
  * reset_bus.
+ *
  */
 struct w1_bus_master
 {
-	/** the first parameter in all the functions below */
 	void		*data;
 
-	/**
-	 * Sample the line level
-	 * @return the level read (0 or 1)
-	 */
 	u8		(*read_bit)(void *);
 
-	/** Sets the line level */
 	void		(*write_bit)(void *, u8);
 
-	/**
-	 * touch_bit is the lowest-level function for devices that really
-	 * support the 1-wire protocol.
-	 * touch_bit(0) = write-0 cycle
-	 * touch_bit(1) = write-1 / read cycle
-	 * @return the bit read (0 or 1)
-	 */
 	u8		(*touch_bit)(void *, u8);
 
-	/**
-	 * Reads a bytes. Same as 8 touch_bit(1) calls.
-	 * @return the byte read
-	 */
 	u8		(*read_byte)(void *);
 
-	/**
-	 * Writes a byte. Same as 8 touch_bit(x) calls.
-	 */
 	void		(*write_byte)(void *, u8);
 
-	/**
-	 * Same as a series of read_byte() calls
-	 * @return the number of bytes read
-	 */
 	u8		(*read_block)(void *, u8 *, int);
 
-	/** Same as a series of write_byte() calls */
 	void		(*write_block)(void *, const u8 *, int);
 
-	/**
-	 * Combines two reads and a smart write for ROM searches
-	 * @return bit0=Id bit1=comp_id bit2=dir_taken
-	 */
 	u8		(*triplet)(void *, u8);
 
-	/**
-	 * long write-0 with a read for the presence pulse detection
-	 * @return -1=Error, 0=Device present, 1=No device present
-	 */
 	u8		(*reset_bus)(void *);
 
-	/**
-	 * Put out a strong pull-up pulse of the specified duration.
-	 * @return -1=Error, 0=completed
-	 */
 	u8		(*set_pullup)(void *, int);
 
-	/** Really nice hardware can handles the different types of ROM search
-	 *  w1_master* is passed to the slave found callback.
-	 */
 	void		(*search)(void *, struct w1_master *,
 		u8, w1_slave_found_callback);
 };
 
+/**
+ * enum w1_master_flags - bitfields used in w1_master.flags
+ * @W1_ABORT_SEARCH: abort searching early on shutdown
+ * @W1_WARN_MAX_COUNT: limit warning when the maximum count is reached
+ */
+enum w1_master_flags {
+	W1_ABORT_SEARCH = 0,
+	W1_WARN_MAX_COUNT = 1,
+};
+
+/**
+ * struct w1_master - one per bus master
+ * @w1_master_entry:	master linked list
+ * @owner:		module owner
+ * @name:		dynamically allocate bus name
+ * @list_mutex:		protect slist and async_list
+ * @slist:		linked list of slaves
+ * @async_list:		linked list of netlink commands to execute
+ * @max_slave_count:	maximum number of slaves to search for at a time
+ * @slave_count:	current number of slaves known
+ * @attempts:		number of searches ran
+ * @slave_ttl:		number of searches before a slave is timed out
+ * @initialized:	prevent init/removal race conditions
+ * @id:			w1 bus number
+ * @search_count:	number of automatic searches to run, -1 unlimited
+ * @search_id:		allows continuing a search
+ * @refcnt:		reference count
+ * @priv:		private data storage
+ * @priv_size:		size allocated
+ * @enable_pullup:	allows a strong pullup
+ * @pullup_duration:	time for the next strong pullup
+ * @flags:		one of w1_master_flags
+ * @thread:		thread for bus search and netlink commands
+ * @mutex:		protect most of w1_master
+ * @bus_mutex:		pretect concurrent bus access
+ * @driver:		sysfs driver
+ * @dev:		sysfs device
+ * @bus_master:		io operations available
+ * @seq:		sequence number used for netlink broadcasts
+ * @portid:		destination for the current netlink command
+ */
 struct w1_master
 {
 	struct list_head	w1_master_entry;
 	struct module		*owner;
 	unsigned char		name[W1_MAXNAMELEN];
+	/* list_mutex protects just slist and async_list so slaves can be
+	 * searched for and async commands added while the master has
+	 * w1_master.mutex locked and is operating on the bus.
+	 * lock order w1_mlock, w1_master.mutex, w1_master.list_mutex
+	 */
+	struct mutex		list_mutex;
 	struct list_head	slist;
+	struct list_head	async_list;
 	int			max_slave_count, slave_count;
 	unsigned long		attempts;
 	int			slave_ttl;
 	int			initialized;
 	u32			id;
 	int			search_count;
+	/* id to start searching on, to continue a search or 0 to restart */
+	u64			search_id;
 
 	atomic_t		refcnt;
 
@@ -178,6 +248,8 @@ struct w1_master
 	/** 5V strong pullup duration in milliseconds, zero disabled. */
 	int			pullup_duration;
 
+	long			flags;
+
 	struct task_struct	*thread;
 	struct mutex		mutex;
 	struct mutex		bus_mutex;
@@ -188,16 +260,41 @@ struct w1_master
 	struct w1_bus_master	*bus_master;
 
 	u32			seq;
+	/* port id to send netlink responses to.  The value is temporarily
+	 * stored here while processing a message, set after locking the
+	 * mutex, zero before unlocking the mutex.
+	 */
+	u32			portid;
+};
+
+/**
+ * struct w1_async_cmd - execute callback from the w1_process kthread
+ * @async_entry: link entry
+ * @cb: callback function, must list_del and destroy this list before
+ * returning
+ *
+ * When inserted into the w1_master async_list, w1_process will execute
+ * the callback.  Embed this into the structure with the command details.
+ */
+struct w1_async_cmd {
+	struct list_head	async_entry;
+	void (*cb)(struct w1_master *dev, struct w1_async_cmd *async_cmd);
 };
 
 int w1_create_master_attributes(struct w1_master *);
 void w1_destroy_master_attributes(struct w1_master *master);
 void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
 void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
+/* call w1_unref_slave to release the reference counts w1_search_slave added */
 struct w1_slave *w1_search_slave(struct w1_reg_num *id);
+/* decrements the reference on sl->master and sl, and cleans up if zero
+ * returns the reference count after it has been decremented */
+int w1_unref_slave(struct w1_slave *sl);
 void w1_slave_found(struct w1_master *dev, u64 rn);
 void w1_search_process_cb(struct w1_master *dev, u8 search_type,
 	w1_slave_found_callback cb);
+struct w1_slave *w1_slave_search_device(struct w1_master *dev,
+	struct w1_reg_num *rn);
 struct w1_master *w1_search_master_id(u32 id);
 
 /* Disconnect and reconnect devices in the given family.  Used for finding
@@ -206,7 +303,9 @@ struct w1_master *w1_search_master_id(u32 id);
  * has just been registered, to 0 when it has been unregistered.
  */
 void w1_reconnect_slaves(struct w1_family *f, int attach);
-void w1_slave_detach(struct w1_slave *sl);
+int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn);
+/* 0 success, otherwise EBUSY */
+int w1_slave_detach(struct w1_slave *sl);
 
 u8 w1_triplet(struct w1_master *dev, int bdir);
 void w1_write_8(struct w1_master *, u8);
@@ -242,6 +341,7 @@ extern int w1_max_slave_ttl;
 extern struct list_head w1_masters;
 extern struct mutex w1_mlock;
 
+extern int w1_process_callbacks(struct w1_master *dev);
 extern int w1_process(void *);
 
 #endif /* __KERNEL__ */
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index e9309778ee72..3bff6b37b472 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -31,6 +31,10 @@
 DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
 
+/**
+ * w1_register_family() - register a device family driver
+ * @newf:	family to register
+ */
 int w1_register_family(struct w1_family *newf)
 {
 	struct list_head *ent, *n;
@@ -59,6 +63,10 @@ int w1_register_family(struct w1_family *newf)
 	return ret;
 }
 
+/**
+ * w1_unregister_family() - unregister a device family driver
+ * @fent:	family to unregister
+ */
 void w1_unregister_family(struct w1_family *fent)
 {
 	struct list_head *ent, *n;
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 4ad0e81b6404..26ca1343055b 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -48,6 +48,12 @@
 
 struct w1_slave;
 
+/**
+ * struct w1_family_ops - operations for a family type
+ * @add_slave: add_slave
+ * @remove_slave: remove_slave
+ * @groups: sysfs group
+ */
 struct w1_family_ops
 {
 	int  (* add_slave)(struct w1_slave *);
@@ -55,6 +61,13 @@ struct w1_family_ops
 	const struct attribute_group **groups;
 };
 
+/**
+ * struct w1_family - reference counted family structure.
+ * @family_entry:	family linked list
+ * @fid:		8 bit family identifier
+ * @fops:		operations for this family
+ * @refcnt:		reference counter
+ */
 struct w1_family
 {
 	struct list_head	family_entry;
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 590bd8a7cd1b..3aaa15f6b7e9 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -75,8 +75,10 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 	atomic_set(&dev->refcnt, 2);
 
 	INIT_LIST_HEAD(&dev->slist);
+	INIT_LIST_HEAD(&dev->async_list);
 	mutex_init(&dev->mutex);
 	mutex_init(&dev->bus_mutex);
+	mutex_init(&dev->list_mutex);
 
 	memcpy(&dev->dev, device, sizeof(struct device));
 	dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);
@@ -90,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;
@@ -103,6 +104,10 @@ static void w1_free_dev(struct w1_master *dev)
 	device_unregister(&dev->dev);
 }
 
+/**
+ * w1_add_master_device() - registers a new master device
+ * @master:	master bus device to register
+ */
 int w1_add_master_device(struct w1_bus_master *master)
 {
 	struct w1_master *dev, *entry;
@@ -172,6 +177,7 @@ int w1_add_master_device(struct w1_bus_master *master)
 
 #if 0 /* Thread cleanup code, not required currently. */
 err_out_kill_thread:
+	set_bit(W1_ABORT_SEARCH, &dev->flags);
 	kthread_stop(dev->thread);
 #endif
 err_out_rm_attr:
@@ -187,16 +193,22 @@ void __w1_remove_master_device(struct w1_master *dev)
 	struct w1_netlink_msg msg;
 	struct w1_slave *sl, *sln;
 
-	kthread_stop(dev->thread);
-
 	mutex_lock(&w1_mlock);
 	list_del(&dev->w1_master_entry);
 	mutex_unlock(&w1_mlock);
 
+	set_bit(W1_ABORT_SEARCH, &dev->flags);
+	kthread_stop(dev->thread);
+
 	mutex_lock(&dev->mutex);
-	list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry)
+	mutex_lock(&dev->list_mutex);
+	list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+		mutex_unlock(&dev->list_mutex);
 		w1_slave_detach(sl);
+		mutex_lock(&dev->list_mutex);
+	}
 	w1_destroy_master_attributes(dev);
+	mutex_unlock(&dev->list_mutex);
 	mutex_unlock(&dev->mutex);
 	atomic_dec(&dev->refcnt);
 
@@ -206,7 +218,9 @@ void __w1_remove_master_device(struct w1_master *dev)
 
 		if (msleep_interruptible(1000))
 			flush_signals(current);
+		w1_process_callbacks(dev);
 	}
+	w1_process_callbacks(dev);
 
 	memset(&msg, 0, sizeof(msg));
 	msg.id.mst.id = dev->id;
@@ -216,6 +230,10 @@ void __w1_remove_master_device(struct w1_master *dev)
 	w1_free_dev(dev);
 }
 
+/**
+ * w1_remove_master_device() - unregister a master device
+ * @bm:	master bus device to remove
+ */
 void w1_remove_master_device(struct w1_bus_master *bm)
 {
 	struct w1_master *dev, *found = NULL;
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index e10acc237733..282092421cc9 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -62,7 +62,9 @@ static void w1_write_bit(struct w1_master *dev, int bit);
 static u8 w1_read_bit(struct w1_master *dev);
 
 /**
- * Generates a write-0 or write-1 cycle and samples the level.
+ * w1_touch_bit() - Generates a write-0 or write-1 cycle and samples the level.
+ * @dev:	the master device
+ * @bit:	0 - write a 0, 1 - write a 0 read the level
  */
 static u8 w1_touch_bit(struct w1_master *dev, int bit)
 {
@@ -77,7 +79,10 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit)
 }
 
 /**
- * Generates a write-0 or write-1 cycle.
+ * w1_write_bit() - Generates a write-0 or write-1 cycle.
+ * @dev:	the master device
+ * @bit:	bit to write
+ *
  * Only call if dev->bus_master->touch_bit is NULL
  */
 static void w1_write_bit(struct w1_master *dev, int bit)
@@ -102,11 +107,12 @@ static void w1_write_bit(struct w1_master *dev, int bit)
 }
 
 /**
+ * w1_pre_write() - pre-write operations
+ * @dev:	the master device
+ *
  * Pre-write operation, currently only supporting strong pullups.
  * Program the hardware for a strong pullup, if one has been requested and
  * the hardware supports it.
- *
- * @param dev     the master device
  */
 static void w1_pre_write(struct w1_master *dev)
 {
@@ -118,11 +124,12 @@ static void w1_pre_write(struct w1_master *dev)
 }
 
 /**
+ * w1_post_write() - post-write options
+ * @dev:	the master device
+ *
  * Post-write operation, currently only supporting strong pullups.
  * If a strong pullup was requested, clear it if the hardware supports
  * them, or execute the delay otherwise, in either case clear the request.
- *
- * @param dev     the master device
  */
 static void w1_post_write(struct w1_master *dev)
 {
@@ -136,10 +143,9 @@ static void w1_post_write(struct w1_master *dev)
 }
 
 /**
- * Writes 8 bits.
- *
- * @param dev     the master device
- * @param byte    the byte to write
+ * w1_write_8() - Writes 8 bits.
+ * @dev:	the master device
+ * @byte:	the byte to write
  */
 void w1_write_8(struct w1_master *dev, u8 byte)
 {
@@ -161,7 +167,9 @@ EXPORT_SYMBOL_GPL(w1_write_8);
 
 
 /**
- * Generates a write-1 cycle and samples the level.
+ * w1_read_bit() - Generates a write-1 cycle and samples the level.
+ * @dev:	the master device
+ *
  * Only call if dev->bus_master->touch_bit is NULL
  */
 static u8 w1_read_bit(struct w1_master *dev)
@@ -185,16 +193,17 @@ static u8 w1_read_bit(struct w1_master *dev)
 }
 
 /**
- * Does a triplet - used for searching ROM addresses.
+ * w1_triplet() - * Does a triplet - used for searching ROM addresses.
+ * @dev:	the master device
+ * @bdir:	the bit to write if both id_bit and comp_bit are 0
+ *
  * Return bits:
  *  bit 0 = id_bit
  *  bit 1 = comp_bit
  *  bit 2 = dir_taken
  * If both bits 0 & 1 are set, the search should be restarted.
  *
- * @param dev     the master device
- * @param bdir    the bit to write if both id_bit and comp_bit are 0
- * @return        bit fields - see above
+ * Return:        bit fields - see above
  */
 u8 w1_triplet(struct w1_master *dev, int bdir)
 {
@@ -226,10 +235,10 @@ u8 w1_triplet(struct w1_master *dev, int bdir)
 }
 
 /**
- * Reads 8 bits.
+ * w1_read_8() - Reads 8 bits.
+ * @dev:	the master device
  *
- * @param dev     the master device
- * @return        the byte read
+ * Return:        the byte read
  */
 u8 w1_read_8(struct w1_master *dev)
 {
@@ -247,11 +256,10 @@ u8 w1_read_8(struct w1_master *dev)
 EXPORT_SYMBOL_GPL(w1_read_8);
 
 /**
- * Writes a series of bytes.
- *
- * @param dev     the master device
- * @param buf     pointer to the data to write
- * @param len     the number of bytes to write
+ * w1_write_block() - Writes a series of bytes.
+ * @dev:	the master device
+ * @buf:	pointer to the data to write
+ * @len:	the number of bytes to write
  */
 void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 {
@@ -269,11 +277,10 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 EXPORT_SYMBOL_GPL(w1_write_block);
 
 /**
- * Touches a series of bytes.
- *
- * @param dev     the master device
- * @param buf     pointer to the data to write
- * @param len     the number of bytes to write
+ * w1_touch_block() - Touches a series of bytes.
+ * @dev:	the master device
+ * @buf:	pointer to the data to write
+ * @len:	the number of bytes to write
  */
 void w1_touch_block(struct w1_master *dev, u8 *buf, int len)
 {
@@ -294,12 +301,11 @@ void w1_touch_block(struct w1_master *dev, u8 *buf, int len)
 EXPORT_SYMBOL_GPL(w1_touch_block);
 
 /**
- * Reads a series of bytes.
- *
- * @param dev     the master device
- * @param buf     pointer to the buffer to fill
- * @param len     the number of bytes to read
- * @return        the number of bytes read
+ * w1_read_block() - Reads a series of bytes.
+ * @dev:	the master device
+ * @buf:	pointer to the buffer to fill
+ * @len:	the number of bytes to read
+ * Return:	the number of bytes read
  */
 u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
 {
@@ -319,10 +325,9 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
 EXPORT_SYMBOL_GPL(w1_read_block);
 
 /**
- * Issues a reset bus sequence.
- *
- * @param  dev The bus master pointer
- * @return     0=Device present, 1=No device present or error
+ * w1_reset_bus() - Issues a reset bus sequence.
+ * @dev:	the master device
+ * Return:	0=Device present, 1=No device present or error
  */
 int w1_reset_bus(struct w1_master *dev)
 {
@@ -383,12 +388,15 @@ void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_cal
 }
 
 /**
+ * w1_reset_select_slave() - reset and select a slave
+ * @sl:		the slave to select
+ *
  * Resets the bus and then selects the slave by sending either a skip rom
- * or a rom match.
+ * or a rom match.  A skip rom is issued if there is only one device
+ * registered on the bus.
  * The w1 master lock must be held.
  *
- * @param sl	the slave to select
- * @return 	0=success, anything else=error
+ * Return:	0=success, anything else=error
  */
 int w1_reset_select_slave(struct w1_slave *sl)
 {
@@ -409,6 +417,9 @@ int w1_reset_select_slave(struct w1_slave *sl)
 EXPORT_SYMBOL_GPL(w1_reset_select_slave);
 
 /**
+ * w1_reset_resume_command() - resume instead of another match ROM
+ * @dev:	the master device
+ *
  * When the workflow with a slave amongst many requires several
  * successive commands a reset between each, this function is similar
  * to doing a reset then a match ROM for the last matched ROM. The
@@ -420,8 +431,6 @@ EXPORT_SYMBOL_GPL(w1_reset_select_slave);
  * doesn't work of course, but the resume command is the next best thing.
  *
  * The w1 master lock must be held.
- *
- * @param dev     the master device
  */
 int w1_reset_resume_command(struct w1_master *dev)
 {
@@ -435,6 +444,10 @@ int w1_reset_resume_command(struct w1_master *dev)
 EXPORT_SYMBOL_GPL(w1_reset_resume_command);
 
 /**
+ * w1_next_pullup() - register for a strong pullup
+ * @dev:	the master device
+ * @delay:	time in milliseconds
+ *
  * Put out a strong pull-up of the specified duration after the next write
  * operation.  Not all hardware supports strong pullups.  Hardware that
  * doesn't support strong pullups will sleep for the given time after the
@@ -442,8 +455,7 @@ EXPORT_SYMBOL_GPL(w1_reset_resume_command);
  * the next write, specifying zero will clear a previous request.
  * The w1 master lock must be held.
  *
- * @param delay	time in milliseconds
- * @return	0=success, anything else=error
+ * Return:	0=success, anything else=error
  */
 void w1_next_pullup(struct w1_master *dev, int delay)
 {
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 40788c925d1c..5234964fe001 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -45,7 +45,7 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 
 	memcpy(w, msg, sizeof(struct w1_netlink_msg));
 
-	cn_netlink_send(m, 0, GFP_KERNEL);
+	cn_netlink_send(m, dev->portid, 0, GFP_KERNEL);
 }
 
 static void w1_send_slave(struct w1_master *dev, u64 rn)
@@ -54,53 +54,95 @@ static void w1_send_slave(struct w1_master *dev, u64 rn)
 	struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1);
 	struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1);
 	int avail;
-
-	/* update kernel slave list */
-	w1_slave_found(dev, rn);
+	u64 *data;
 
 	avail = dev->priv_size - cmd->len;
 
-	if (avail > 8) {
-		u64 *data = (void *)(cmd + 1) + cmd->len;
+	if (avail < 8) {
+		msg->ack++;
+		cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
 
-		*data = rn;
-		cmd->len += 8;
-		hdr->len += 8;
-		msg->len += 8;
-		return;
+		msg->len = sizeof(struct w1_netlink_msg) +
+			sizeof(struct w1_netlink_cmd);
+		hdr->len = sizeof(struct w1_netlink_cmd);
+		cmd->len = 0;
 	}
 
-	msg->ack++;
-	cn_netlink_send(msg, 0, GFP_KERNEL);
+	data = (void *)(cmd + 1) + cmd->len;
 
-	msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd);
-	hdr->len = sizeof(struct w1_netlink_cmd);
-	cmd->len = 0;
+	*data = rn;
+	cmd->len += 8;
+	hdr->len += 8;
+	msg->len += 8;
 }
 
-static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg,
-		unsigned int avail)
+static void w1_found_send_slave(struct w1_master *dev, u64 rn)
 {
-	struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1);
-	struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1);
-	int search_type = (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH;
+	/* update kernel slave list */
+	w1_slave_found(dev, rn);
 
-	dev->priv = msg;
-	dev->priv_size = avail;
+	w1_send_slave(dev, rn);
+}
+
+/* Get the current slave list, or search (with or without alarm) */
+static int w1_get_slaves(struct w1_master *dev,
+		struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr,
+		struct w1_netlink_cmd *req_cmd)
+{
+	struct cn_msg *msg;
+	struct w1_netlink_msg *hdr;
+	struct w1_netlink_cmd *cmd;
+	struct w1_slave *sl;
+
+	msg = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->id = req_msg->id;
+	msg->seq = req_msg->seq;
+	msg->ack = 0;
+	msg->len = sizeof(struct w1_netlink_msg) +
+		sizeof(struct w1_netlink_cmd);
+
+	hdr = (struct w1_netlink_msg *)(msg + 1);
+	cmd = (struct w1_netlink_cmd *)(hdr + 1);
+
+	hdr->type = W1_MASTER_CMD;
+	hdr->id = req_hdr->id;
+	hdr->len = sizeof(struct w1_netlink_cmd);
+
+	cmd->cmd = req_cmd->cmd;
+	cmd->len = 0;
 
-	w1_search_process_cb(dev, search_type, w1_send_slave);
+	dev->priv = msg;
+	dev->priv_size = PAGE_SIZE - msg->len - sizeof(struct cn_msg);
+
+	if (req_cmd->cmd == W1_CMD_LIST_SLAVES) {
+		__u64 rn;
+		mutex_lock(&dev->list_mutex);
+		list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+			memcpy(&rn, &sl->reg_num, sizeof(rn));
+			w1_send_slave(dev, rn);
+		}
+		mutex_unlock(&dev->list_mutex);
+	} else {
+		w1_search_process_cb(dev, cmd->cmd == W1_CMD_ALARM_SEARCH ?
+			W1_ALARM_SEARCH : W1_SEARCH, w1_found_send_slave);
+	}
 
 	msg->ack = 0;
-	cn_netlink_send(msg, 0, GFP_KERNEL);
+	cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
 
 	dev->priv = NULL;
 	dev->priv_size = 0;
 
+	kfree(msg);
+
 	return 0;
 }
 
 static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
-		struct w1_netlink_cmd *cmd)
+		struct w1_netlink_cmd *cmd, u32 portid)
 {
 	void *data;
 	struct w1_netlink_msg *h;
@@ -131,7 +173,7 @@ static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
 
 	memcpy(c->data, cmd->data, c->len);
 
-	err = cn_netlink_send(cm, 0, GFP_KERNEL);
+	err = cn_netlink_send(cm, portid, 0, GFP_KERNEL);
 
 	kfree(data);
 
@@ -146,11 +188,11 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
 	switch (cmd->cmd) {
 	case W1_CMD_TOUCH:
 		w1_touch_block(dev, cmd->data, cmd->len);
-		w1_send_read_reply(msg, hdr, cmd);
+		w1_send_read_reply(msg, hdr, cmd, dev->portid);
 		break;
 	case W1_CMD_READ:
 		w1_read_block(dev, cmd->data, cmd->len);
-		w1_send_read_reply(msg, hdr, cmd);
+		w1_send_read_reply(msg, hdr, cmd, dev->portid);
 		break;
 	case W1_CMD_WRITE:
 		w1_write_block(dev, cmd->data, cmd->len);
@@ -163,38 +205,57 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
 	return err;
 }
 
-static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_msg,
-		struct w1_netlink_msg *req_hdr, struct w1_netlink_cmd *req_cmd)
+static int w1_process_command_addremove(struct w1_master *dev,
+	struct cn_msg *msg, struct w1_netlink_msg *hdr,
+	struct w1_netlink_cmd *cmd)
 {
-	int err = -EINVAL;
-	struct cn_msg *msg;
-	struct w1_netlink_msg *hdr;
-	struct w1_netlink_cmd *cmd;
+	struct w1_slave *sl;
+	int err = 0;
+	struct w1_reg_num *id;
 
-	msg = kzalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
+	if (cmd->len != 8)
+		return -EINVAL;
 
-	msg->id = req_msg->id;
-	msg->seq = req_msg->seq;
-	msg->ack = 0;
-	msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd);
+	id = (struct w1_reg_num *)cmd->data;
 
-	hdr = (struct w1_netlink_msg *)(msg + 1);
-	cmd = (struct w1_netlink_cmd *)(hdr + 1);
+	sl = w1_slave_search_device(dev, id);
+	switch (cmd->cmd) {
+	case W1_CMD_SLAVE_ADD:
+		if (sl)
+			err = -EINVAL;
+		else
+			err = w1_attach_slave_device(dev, id);
+		break;
+	case W1_CMD_SLAVE_REMOVE:
+		if (sl)
+			w1_slave_detach(sl);
+		else
+			err = -EINVAL;
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
 
-	hdr->type = W1_MASTER_CMD;
-	hdr->id = req_hdr->id;
-	hdr->len = sizeof(struct w1_netlink_cmd);
+	return err;
+}
 
-	cmd->cmd = req_cmd->cmd;
-	cmd->len = 0;
+static int w1_process_command_master(struct w1_master *dev,
+	struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr,
+	struct w1_netlink_cmd *req_cmd)
+{
+	int err = -EINVAL;
 
-	switch (cmd->cmd) {
+	/* drop bus_mutex for search (does it's own locking), and add/remove
+	 * which doesn't use the bus
+	 */
+	switch (req_cmd->cmd) {
 	case W1_CMD_SEARCH:
 	case W1_CMD_ALARM_SEARCH:
-		err = w1_process_search_command(dev, msg,
-				PAGE_SIZE - msg->len - sizeof(struct cn_msg));
+	case W1_CMD_LIST_SLAVES:
+		mutex_unlock(&dev->bus_mutex);
+		err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd);
+		mutex_lock(&dev->bus_mutex);
 		break;
 	case W1_CMD_READ:
 	case W1_CMD_WRITE:
@@ -204,12 +265,20 @@ static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_m
 	case W1_CMD_RESET:
 		err = w1_reset_bus(dev);
 		break;
+	case W1_CMD_SLAVE_ADD:
+	case W1_CMD_SLAVE_REMOVE:
+		mutex_unlock(&dev->bus_mutex);
+		mutex_lock(&dev->mutex);
+		err = w1_process_command_addremove(dev, req_msg, req_hdr,
+			req_cmd);
+		mutex_unlock(&dev->mutex);
+		mutex_lock(&dev->bus_mutex);
+		break;
 	default:
 		err = -EINVAL;
 		break;
 	}
 
-	kfree(msg);
 	return err;
 }
 
@@ -223,7 +292,8 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
 	return w1_process_command_io(sl->master, msg, hdr, cmd);
 }
 
-static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd)
+static int w1_process_command_root(struct cn_msg *msg,
+	struct w1_netlink_msg *mcmd, u32 portid)
 {
 	struct w1_master *m;
 	struct cn_msg *cn;
@@ -256,7 +326,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
 	mutex_lock(&w1_mlock);
 	list_for_each_entry(m, &w1_masters, w1_master_entry) {
 		if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
-			cn_netlink_send(cn, 0, GFP_KERNEL);
+			cn_netlink_send(cn, portid, 0, GFP_KERNEL);
 			cn->ack++;
 			cn->len = sizeof(struct w1_netlink_msg);
 			w->len = 0;
@@ -269,7 +339,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
 		id++;
 	}
 	cn->ack = 0;
-	cn_netlink_send(cn, 0, GFP_KERNEL);
+	cn_netlink_send(cn, portid, 0, GFP_KERNEL);
 	mutex_unlock(&w1_mlock);
 
 	kfree(cn);
@@ -277,7 +347,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
 }
 
 static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg,
-		struct w1_netlink_cmd *rcmd, int error)
+		struct w1_netlink_cmd *rcmd, int portid, int error)
 {
 	struct cn_msg *cmsg;
 	struct w1_netlink_msg *msg;
@@ -304,35 +374,147 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
 		cmsg->len += sizeof(*cmd);
 	}
 
-	error = cn_netlink_send(cmsg, 0, GFP_KERNEL);
+	error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL);
 	kfree(cmsg);
 
 	return error;
 }
 
+/* Bundle together a reference count, the full message, and broken out
+ * commands to be executed on each w1 master kthread in one memory allocation.
+ */
+struct w1_cb_block {
+	atomic_t refcnt;
+	u32 portid; /* Sending process port ID */
+	struct cn_msg msg;
+	/* cn_msg data */
+	/* one or more variable length struct w1_cb_node */
+};
+struct w1_cb_node {
+	struct w1_async_cmd async;
+	/* pointers within w1_cb_block and msg data */
+	struct w1_cb_block *block;
+	struct w1_netlink_msg *m;
+	struct w1_slave *sl;
+	struct w1_master *dev;
+};
+
+static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
+{
+	struct w1_cb_node *node = container_of(async_cmd, struct w1_cb_node,
+		async);
+	u16 mlen = node->m->len;
+	u8 *cmd_data = node->m->data;
+	int err = 0;
+	struct w1_slave *sl = node->sl;
+	struct w1_netlink_cmd *cmd = NULL;
+
+	mutex_lock(&dev->bus_mutex);
+	dev->portid = node->block->portid;
+	if (sl && w1_reset_select_slave(sl))
+		err = -ENODEV;
+
+	while (mlen && !err) {
+		cmd = (struct w1_netlink_cmd *)cmd_data;
+
+		if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
+			err = -E2BIG;
+			break;
+		}
+
+		if (sl)
+			err = w1_process_command_slave(sl, &node->block->msg,
+				node->m, cmd);
+		else
+			err = w1_process_command_master(dev, &node->block->msg,
+				node->m, cmd);
+
+		w1_netlink_send_error(&node->block->msg, node->m, cmd,
+			node->block->portid, err);
+		err = 0;
+
+		cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
+		mlen -= cmd->len + sizeof(struct w1_netlink_cmd);
+	}
+
+	if (!cmd || err)
+		w1_netlink_send_error(&node->block->msg, node->m, cmd,
+			node->block->portid, err);
+
+	if (sl)
+		w1_unref_slave(sl);
+	else
+		atomic_dec(&dev->refcnt);
+	dev->portid = 0;
+	mutex_unlock(&dev->bus_mutex);
+
+	mutex_lock(&dev->list_mutex);
+	list_del(&async_cmd->async_entry);
+	mutex_unlock(&dev->list_mutex);
+
+	if (atomic_sub_return(1, &node->block->refcnt) == 0)
+		kfree(node->block);
+}
+
 static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 {
 	struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
-	struct w1_netlink_cmd *cmd;
 	struct w1_slave *sl;
 	struct w1_master *dev;
+	u16 msg_len;
 	int err = 0;
+	struct w1_cb_block *block = NULL;
+	struct w1_cb_node *node = NULL;
+	int node_count = 0;
+
+	/* Count the number of master or slave commands there are to allocate
+	 * space for one cb_node each.
+	 */
+	msg_len = msg->len;
+	while (msg_len && !err) {
+		if (m->len + sizeof(struct w1_netlink_msg) > msg_len) {
+			err = -E2BIG;
+			break;
+		}
+
+		if (m->type == W1_MASTER_CMD || m->type == W1_SLAVE_CMD)
+			++node_count;
 
-	while (msg->len && !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 *)(msg + 1);
+	if (node_count) {
+		/* msg->len doesn't include itself */
+		long size = sizeof(struct w1_cb_block) + msg->len +
+			node_count*sizeof(struct w1_cb_node);
+		block = kmalloc(size, GFP_KERNEL);
+		if (!block) {
+			w1_netlink_send_error(msg, m, NULL, nsp->portid,
+				-ENOMEM);
+			return;
+		}
+		atomic_set(&block->refcnt, 1);
+		block->portid = nsp->portid;
+		memcpy(&block->msg, msg, sizeof(*msg) + msg->len);
+		node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len);
+	}
+
+	msg_len = msg->len;
+	while (msg_len && !err) {
 		struct w1_reg_num id;
 		u16 mlen = m->len;
-		u8 *cmd_data = m->data;
 
 		dev = NULL;
 		sl = NULL;
-		cmd = 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) {
+		if (m->len + sizeof(struct w1_netlink_msg) > msg_len) {
 			err = -E2BIG;
 			break;
 		}
@@ -344,7 +526,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 			if (sl)
 				dev = sl->master;
 		} else {
-			err = w1_process_command_root(msg, m);
+			err = w1_process_command_root(msg, m, nsp->portid);
 			goto out_cont;
 		}
 
@@ -357,41 +539,24 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 		if (!mlen)
 			goto out_cont;
 
-		mutex_lock(&dev->mutex);
-
-		if (sl && w1_reset_select_slave(sl)) {
-			err = -ENODEV;
-			goto out_up;
-		}
+		atomic_inc(&block->refcnt);
+		node->async.cb = w1_process_cb;
+		node->block = block;
+		node->m = (struct w1_netlink_msg *)((u8 *)&block->msg +
+			(size_t)((u8 *)m - (u8 *)msg));
+		node->sl = sl;
+		node->dev = dev;
 
-		while (mlen) {
-			cmd = (struct w1_netlink_cmd *)cmd_data;
+		mutex_lock(&dev->list_mutex);
+		list_add_tail(&node->async.async_entry, &dev->async_list);
+		wake_up_process(dev->thread);
+		mutex_unlock(&dev->list_mutex);
+		++node;
 
-			if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
-				err = -E2BIG;
-				break;
-			}
-
-			if (sl)
-				err = w1_process_command_slave(sl, msg, m, cmd);
-			else
-				err = w1_process_command_master(dev, msg, m, cmd);
-
-			w1_netlink_send_error(msg, m, cmd, err);
-			err = 0;
-
-			cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
-			mlen -= cmd->len + sizeof(struct w1_netlink_cmd);
-		}
-out_up:
-		atomic_dec(&dev->refcnt);
-		if (sl)
-			atomic_dec(&sl->refcnt);
-		mutex_unlock(&dev->mutex);
 out_cont:
-		if (!cmd || err)
-			w1_netlink_send_error(msg, m, cmd, err);
-		msg->len -= sizeof(struct w1_netlink_msg) + m->len;
+		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);
 
 		/*
@@ -400,6 +565,8 @@ out_cont:
 		if (err == -ENODEV)
 			err = 0;
 	}
+	if (block && atomic_sub_return(1, &block->refcnt) == 0)
+		kfree(block);
 }
 
 int w1_init_netlink(void)
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index b0922dc29658..1e9504e67650 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -27,6 +27,18 @@
 
 #include "w1.h"
 
+/**
+ * enum w1_netlink_message_types - message type
+ *
+ * @W1_SLAVE_ADD: notification that a slave device was added
+ * @W1_SLAVE_REMOVE: notification that a slave device was removed
+ * @W1_MASTER_ADD: notification that a new bus master was added
+ * @W1_MASTER_REMOVE: notification that a bus masterwas removed
+ * @W1_MASTER_CMD: initiate operations on a specific master
+ * @W1_SLAVE_CMD: sends reset, selects the slave, then does a read/write/touch
+ * operation
+ * @W1_LIST_MASTERS: used to determine the bus master identifiers
+ */
 enum w1_netlink_message_types {
 	W1_SLAVE_ADD = 0,
 	W1_SLAVE_REMOVE,
@@ -52,6 +64,22 @@ struct w1_netlink_msg
 	__u8				data[0];
 };
 
+/**
+ * enum w1_commands - commands available for master or slave operations
+ * @W1_CMD_READ: read len bytes
+ * @W1_CMD_WRITE: write len bytes
+ * @W1_CMD_SEARCH: initiate a standard search, returns only the slave
+ * devices found during that search
+ * @W1_CMD_ALARM_SEARCH: search for devices that are currently alarming
+ * @W1_CMD_TOUCH: Touches a series of bytes.
+ * @W1_CMD_RESET: sends a bus reset on the given master
+ * @W1_CMD_SLAVE_ADD: adds a slave to the given master,
+ * 8 byte slave id at data[0]
+ * @W1_CMD_SLAVE_REMOVE: removes a slave to the given master,
+ * 8 byte slave id at data[0]
+ * @W1_CMD_LIST_SLAVES: list of slaves registered on this master
+ * @W1_CMD_MAX: number of available commands
+ */
 enum w1_commands {
 	W1_CMD_READ = 0,
 	W1_CMD_WRITE,
@@ -59,7 +87,10 @@ enum w1_commands {
 	W1_CMD_ALARM_SEARCH,
 	W1_CMD_TOUCH,
 	W1_CMD_RESET,
-	W1_CMD_MAX,
+	W1_CMD_SLAVE_ADD,
+	W1_CMD_SLAVE_REMOVE,
+	W1_CMD_LIST_SLAVES,
+	W1_CMD_MAX
 };
 
 struct w1_netlink_cmd
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 79d25894343a..a3497419496b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -111,6 +111,15 @@ config WM8350_WATCHDOG
 	  Support for the watchdog in the WM8350 AudioPlus PMIC.  When
 	  the watchdog triggers the system will be reset.
 
+config XILINX_WATCHDOG
+	tristate "Xilinx Watchdog timer"
+	select WATCHDOG_CORE
+	help
+	  Watchdog driver for the xps_timebase_wdt ip core.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called of_xilinx_wdt.
+
 # ALPHA Architecture
 
 # ARM Architecture
@@ -292,7 +301,7 @@ config DAVINCI_WATCHDOG
 
 config ORION_WATCHDOG
 	tristate "Orion watchdog"
-	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE
+	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_DOVE
 	select WATCHDOG_CORE
 	help
 	  Say Y here if to include support for the watchdog timer
@@ -421,6 +430,17 @@ config SIRFSOC_WATCHDOG
 	  Support for CSR SiRFprimaII and SiRFatlasVI watchdog. When
 	  the watchdog triggers the system will be reset.
 
+config TEGRA_WATCHDOG
+	tristate "Tegra watchdog"
+	depends on ARCH_TEGRA || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  embedded in NVIDIA Tegra SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tegra_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
@@ -1023,18 +1043,6 @@ config M54xx_WATCHDOG
 
 # MicroBlaze Architecture
 
-config XILINX_WATCHDOG
-	tristate "Xilinx Watchdog timer"
-	depends on MICROBLAZE
-	---help---
-	  Watchdog driver for the xps_timebase_wdt ip core.
-
-	  IMPORTANT: The xps_timebase_wdt parent must have the property
-	  "clock-frequency" at device tree.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called of_xilinx_wdt.
-
 # MIPS Architecture
 
 config ATH79_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 985a66cda76f..1b5f3d5efad5 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
 obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
 obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
 obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
+obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 3a996576343a..ae6c287a49cb 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index afe7d17e6776..25b5c67d3af9 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -323,10 +323,8 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
 
 	wdt = devm_kzalloc(&pdev->dev, sizeof(struct wdt_at32ap700x),
 			GFP_KERNEL);
-	if (!wdt) {
-		dev_dbg(&pdev->dev, "no memory for wdt structure\n");
+	if (!wdt)
 		return -ENOMEM;
-	}
 
 	wdt->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
 	if (!wdt->regs) {
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index 9fa1f69dac13..399c3fddecf6 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -22,7 +22,6 @@
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index cafa973c43be..8df450c090a9 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -114,10 +114,8 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
 	int err;
 
 	wdt = devm_kzalloc(dev, sizeof(struct bcm2835_wdt), GFP_KERNEL);
-	if (!wdt) {
-		dev_err(dev, "Failed to allocate memory for watchdog device");
+	if (!wdt)
 		return -ENOMEM;
-	}
 	platform_set_drvdata(pdev, wdt);
 
 	spin_lock_init(&wdt->lock);
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index b4021a2b459b..b61fcc535979 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -16,7 +16,6 @@
 #include <linux/bcm47xx_wdt.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 4eb188b87f8e..5a8e879a430a 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
@@ -45,7 +44,6 @@
 static struct {
 	void __iomem *regs;
 	struct timer_list timer;
-	int default_ticks;
 	unsigned long inuse;
 	atomic_t ticks;
 } bcm63xx_wdt_device;
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index f7ae49edb518..6d03e8e30f8b 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -27,7 +27,6 @@
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/completion.h>
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 213225edd059..e55ed702209f 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -21,7 +21,6 @@
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/major.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
index f09c54e9686f..2e9589652e1e 100644
--- a/drivers/watchdog/da9052_wdt.c
+++ b/drivers/watchdog/da9052_wdt.c
@@ -185,7 +185,6 @@ static int da9052_wdt_probe(struct platform_device *pdev)
 	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
 				   GFP_KERNEL);
 	if (!driver_data) {
-		dev_err(da9052->dev, "Unable to alloacate watchdog device\n");
 		ret = -ENOMEM;
 		goto err;
 	}
diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c
index 575f37a965a4..495089d8dbfe 100644
--- a/drivers/watchdog/da9055_wdt.c
+++ b/drivers/watchdog/da9055_wdt.c
@@ -151,10 +151,8 @@ static int da9055_wdt_probe(struct platform_device *pdev)
 
 	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
 				   GFP_KERNEL);
-	if (!driver_data) {
-		dev_err(da9055->dev, "Failed to allocate watchdog device\n");
+	if (!driver_data)
 		return -ENOMEM;
-	}
 
 	driver_data->da9055 = da9055;
 
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index b1bae03742a9..d09ad2254b57 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/device.h>
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index d1d07f2f69df..5f54e1e5819a 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -118,16 +118,9 @@ static int ep93xx_wdt_probe(struct platform_device *pdev)
 	int err;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
-
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res), pdev->name))
-		return -EBUSY;
-
-	mmio_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!mmio_base)
-		return -ENXIO;
+	mmio_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mmio_base))
+		return PTR_ERR(mmio_base);
 
 	if (timeout < 1 || timeout > 3600) {
 		timeout = WDT_TIMEOUT;
@@ -172,9 +165,9 @@ static struct platform_driver ep93xx_wdt_driver = {
 
 module_platform_driver(ep93xx_wdt_driver);
 
-MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
-		"Alessandro Zummo <a.zummo@towertech.it>,"
-		"H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 MODULE_DESCRIPTION("EP93xx Watchdog");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(WDT_VERSION);
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 2b75e8b47279..75d2243b94f5 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -17,7 +17,6 @@
 
 #include <linux/device.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 25a2bfdb4e9d..d7befd58b391 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -36,7 +36,6 @@
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/uaccess.h>
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 04f8af65acfd..6532e7a260d8 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -347,15 +347,15 @@ static const struct watchdog_info ident = {
 static const struct watchdog_ops iTCO_wdt_ops = {
 	.owner =		THIS_MODULE,
 	.start =		iTCO_wdt_start,
-	.stop = 		iTCO_wdt_stop,
-	.ping = 		iTCO_wdt_ping,
+	.stop =			iTCO_wdt_stop,
+	.ping =			iTCO_wdt_ping,
 	.set_timeout =		iTCO_wdt_set_timeout,
 	.get_timeleft =		iTCO_wdt_get_timeleft,
 };
 
 static struct watchdog_device iTCO_wdt_watchdog_dev = {
 	.info =		&ident,
-	.ops = 		&iTCO_wdt_ops,
+	.ops =		&iTCO_wdt_ops,
 };
 
 /*
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index db0a34460e57..366b0474f278 100644
--- a/drivers/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
@@ -360,7 +360,7 @@ struct ibmasr_id {
 	int type;
 };
 
-static struct ibmasr_id __initdata ibmasr_id_table[] = {
+static struct ibmasr_id ibmasr_id_table[] __initdata = {
 	{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
 	{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
 	{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
index 1b5c25a47b87..5d20cdd30efe 100644
--- a/drivers/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
@@ -41,24 +41,15 @@ MODULE_PARM_DESC(nowayout,
 
 static void indydog_start(void)
 {
-	u32 mc_ctrl0;
-
 	spin_lock(&indydog_lock);
-	mc_ctrl0 = sgimc->cpuctrl0;
-	mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
-	sgimc->cpuctrl0 = mc_ctrl0;
+	sgimc->cpuctrl0 |= SGIMC_CCTRL0_WDOG;
 	spin_unlock(&indydog_lock);
 }
 
 static void indydog_stop(void)
 {
-	u32 mc_ctrl0;
-
 	spin_lock(&indydog_lock);
-
-	mc_ctrl0 = sgimc->cpuctrl0;
-	mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
-	sgimc->cpuctrl0 = mc_ctrl0;
+	sgimc->cpuctrl0 &= ~SGIMC_CCTRL0_WDOG;
 	spin_unlock(&indydog_lock);
 
 	pr_info("Stopped watchdog timer\n");
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
index e13e65e996aa..0caab6241eb7 100644
--- a/drivers/watchdog/intel_scu_watchdog.c
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -211,7 +211,6 @@ static int intel_scu_set_heartbeat(u32 t)
 	int			 ipc_ret;
 	int			 retry_count;
 	u32			 soft_value;
-	u32			 hw_pre_value;
 	u32			 hw_value;
 
 	watchdog_device.timer_set = t;
@@ -273,8 +272,7 @@ static int intel_scu_set_heartbeat(u32 t)
 			watchdog_device.timer_load_count_addr);
 
 		/* read count value before starting timer */
-		hw_pre_value = ioread32(watchdog_device.timer_load_count_addr);
-		hw_pre_value = hw_pre_value & 0xFFFF0000;
+		ioread32(watchdog_device.timer_load_count_addr);
 
 		/* Start the timer */
 		iowrite32(0x00000003, watchdog_device.timer_control_addr);
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 3aa50cfa335f..91e45ca589e6 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/device.h>
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index bdb3f4a5b27c..0e9cc6f5a919 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -20,7 +20,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index c1f65b4c0aa4..7831955cd9e1 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -237,6 +237,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
 		.compatible = "fsl,mpc823-wdt",
 		.data = &(struct mpc8xxx_wdt_type) {
 			.prescaler = 0x800,
+			.hw_enabled = true,
 		},
 	},
 	{},
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index edb31ffd7927..ff27c4ac96e4 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -40,7 +40,6 @@
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/completion.h>
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
index a0d893b0930e..7135803ca1a3 100644
--- a/drivers/watchdog/nuc900_wdt.c
+++ b/drivers/watchdog/nuc900_wdt.c
@@ -12,7 +12,6 @@
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/kernel.h>
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index fb57103c8ebc..57ccae8327ff 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -1,6 +1,7 @@
 /*
  * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt
  *
+ * (C) Copyright 2013 - 2014 Xilinx, Inc.
  * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>)
  *
  * This program is free software; you can redistribute it and/or
@@ -9,18 +10,13 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/watchdog.h>
 #include <linux/io.h>
-#include <linux/uaccess.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
@@ -43,102 +39,103 @@
 #define XWT_TIMER_FAILED            0xFFFFFFFF
 
 #define WATCHDOG_NAME     "Xilinx Watchdog"
-#define PFX WATCHDOG_NAME ": "
 
 struct xwdt_device {
-	struct resource  res;
 	void __iomem *base;
-	u32 nowayout;
 	u32 wdt_interval;
-	u32 boot_status;
+	spinlock_t spinlock;
+	struct watchdog_device xilinx_wdt_wdd;
 };
 
-static struct xwdt_device xdev;
-
-static  u32 timeout;
-static  u32 control_status_reg;
-static  u8  expect_close;
-static  u8  no_timeout;
-static unsigned long driver_open;
-
-static  DEFINE_SPINLOCK(spinlock);
-
-static void xwdt_start(void)
+static int xilinx_wdt_start(struct watchdog_device *wdd)
 {
-	spin_lock(&spinlock);
+	u32 control_status_reg;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+
+	spin_lock(&xdev->spinlock);
 
 	/* Clean previous status and enable the watchdog timer */
-	control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+	control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
 	control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
 
 	iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK),
-				xdev.base + XWT_TWCSR0_OFFSET);
+		  xdev->base + XWT_TWCSR0_OFFSET);
+
+	iowrite32(XWT_CSRX_EWDT2_MASK, xdev->base + XWT_TWCSR1_OFFSET);
 
-	iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET);
+	spin_unlock(&xdev->spinlock);
 
-	spin_unlock(&spinlock);
+	return 0;
 }
 
-static void xwdt_stop(void)
+static int xilinx_wdt_stop(struct watchdog_device *wdd)
 {
-	spin_lock(&spinlock);
+	u32 control_status_reg;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+
+	spin_lock(&xdev->spinlock);
 
-	control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+	control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
 
 	iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK),
-				xdev.base + XWT_TWCSR0_OFFSET);
+		  xdev->base + XWT_TWCSR0_OFFSET);
 
-	iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
+	iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET);
 
-	spin_unlock(&spinlock);
+	spin_unlock(&xdev->spinlock);
 	pr_info("Stopped!\n");
+
+	return 0;
 }
 
-static void xwdt_keepalive(void)
+static int xilinx_wdt_keepalive(struct watchdog_device *wdd)
 {
-	spin_lock(&spinlock);
+	u32 control_status_reg;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
 
-	control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
-	control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
-	iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET);
+	spin_lock(&xdev->spinlock);
 
-	spin_unlock(&spinlock);
-}
+	control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
+	control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
+	iowrite32(control_status_reg, xdev->base + XWT_TWCSR0_OFFSET);
 
-static void xwdt_get_status(int *status)
-{
-	int new_status;
+	spin_unlock(&xdev->spinlock);
 
-	spin_lock(&spinlock);
+	return 0;
+}
 
-	control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
-	new_status = ((control_status_reg &
-			(XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK)) != 0);
-	spin_unlock(&spinlock);
+static const struct watchdog_info xilinx_wdt_ident = {
+	.options =  WDIOF_MAGICCLOSE |
+		    WDIOF_KEEPALIVEPING,
+	.firmware_version =	1,
+	.identity =	WATCHDOG_NAME,
+};
 
-	*status = 0;
-	if (new_status & 1)
-		*status |= WDIOF_CARDRESET;
-}
+static const struct watchdog_ops xilinx_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = xilinx_wdt_start,
+	.stop = xilinx_wdt_stop,
+	.ping = xilinx_wdt_keepalive,
+};
 
-static u32 xwdt_selftest(void)
+static u32 xwdt_selftest(struct xwdt_device *xdev)
 {
 	int i;
 	u32 timer_value1;
 	u32 timer_value2;
 
-	spin_lock(&spinlock);
+	spin_lock(&xdev->spinlock);
 
-	timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET);
-	timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+	timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET);
+	timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
 
 	for (i = 0;
 		((i <= XWT_MAX_SELFTEST_LOOP_COUNT) &&
 			(timer_value2 == timer_value1)); i++) {
-		timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+		timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
 	}
 
-	spin_unlock(&spinlock);
+	spin_unlock(&xdev->spinlock);
 
 	if (timer_value2 != timer_value1)
 		return ~XWT_TIMER_FAILED;
@@ -146,238 +143,83 @@ static u32 xwdt_selftest(void)
 		return XWT_TIMER_FAILED;
 }
 
-static int xwdt_open(struct inode *inode, struct file *file)
-{
-	/* Only one process can handle the wdt at a time */
-	if (test_and_set_bit(0, &driver_open))
-		return -EBUSY;
-
-	/* Make sure that the module are always loaded...*/
-	if (xdev.nowayout)
-		__module_get(THIS_MODULE);
-
-	xwdt_start();
-	pr_info("Started...\n");
-
-	return nonseekable_open(inode, file);
-}
-
-static int xwdt_release(struct inode *inode, struct file *file)
-{
-	if (expect_close == 42) {
-		xwdt_stop();
-	} else {
-		pr_crit("Unexpected close, not stopping watchdog!\n");
-		xwdt_keepalive();
-	}
-
-	clear_bit(0, &driver_open);
-	expect_close = 0;
-	return 0;
-}
-
-/*
- *      xwdt_write:
- *      @file: file handle to the watchdog
- *      @buf: buffer to write (unused as data does not matter here
- *      @count: count of bytes
- *      @ppos: pointer to the position to write. No seeks allowed
- *
- *      A write to a watchdog device is defined as a keepalive signal. Any
- *      write of data will do, as we don't define content meaning.
- */
-static ssize_t xwdt_write(struct file *file, const char __user *buf,
-						size_t len, loff_t *ppos)
-{
-	if (len) {
-		if (!xdev.nowayout) {
-			size_t i;
-
-			/* In case it was set long ago */
-			expect_close = 0;
-
-			for (i = 0; i != len; i++) {
-				char c;
-
-				if (get_user(c, buf + i))
-					return -EFAULT;
-				if (c == 'V')
-					expect_close = 42;
-			}
-		}
-		xwdt_keepalive();
-	}
-	return len;
-}
-
-static const struct watchdog_info ident = {
-	.options =  WDIOF_MAGICCLOSE |
-		    WDIOF_KEEPALIVEPING,
-	.firmware_version =	1,
-	.identity =	WATCHDOG_NAME,
-};
-
-/*
- *      xwdt_ioctl:
- *      @file: file handle to the device
- *      @cmd: watchdog command
- *      @arg: argument pointer
- *
- *      The watchdog API defines a common set of functions for all watchdogs
- *      according to their available features.
- */
-static long xwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int status;
-
-	union {
-		struct watchdog_info __user *ident;
-		int __user *i;
-	} uarg;
-
-	uarg.i = (int __user *)arg;
-
-	switch (cmd) {
-	case WDIOC_GETSUPPORT:
-		return copy_to_user(uarg.ident, &ident,
-					sizeof(ident)) ? -EFAULT : 0;
-
-	case WDIOC_GETBOOTSTATUS:
-		return put_user(xdev.boot_status, uarg.i);
-
-	case WDIOC_GETSTATUS:
-		xwdt_get_status(&status);
-		return put_user(status, uarg.i);
-
-	case WDIOC_KEEPALIVE:
-		xwdt_keepalive();
-		return 0;
-
-	case WDIOC_GETTIMEOUT:
-		if (no_timeout)
-			return -ENOTTY;
-		else
-			return put_user(timeout, uarg.i);
-
-	default:
-		return -ENOTTY;
-	}
-}
-
-static const struct file_operations xwdt_fops = {
-	.owner      = THIS_MODULE,
-	.llseek     = no_llseek,
-	.write      = xwdt_write,
-	.open       = xwdt_open,
-	.release    = xwdt_release,
-	.unlocked_ioctl = xwdt_ioctl,
-};
-
-static struct miscdevice xwdt_miscdev = {
-	.minor      = WATCHDOG_MINOR,
-	.name       = "watchdog",
-	.fops       = &xwdt_fops,
-};
-
 static int xwdt_probe(struct platform_device *pdev)
 {
 	int rc;
-	u32 *tmptr;
-	u32 *pfreq;
-
-	no_timeout = 0;
-
-	pfreq = (u32 *)of_get_property(pdev->dev.of_node,
-					"clock-frequency", NULL);
-
-	if (pfreq == NULL) {
-		pr_warn("The watchdog clock frequency cannot be obtained!\n");
-		no_timeout = 1;
-	}
-
-	rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res);
-	if (rc) {
-		pr_warn("invalid address!\n");
-		return rc;
-	}
-
-	tmptr = (u32 *)of_get_property(pdev->dev.of_node,
-					"xlnx,wdt-interval", NULL);
-	if (tmptr == NULL) {
-		pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
-		no_timeout = 1;
-	} else {
-		xdev.wdt_interval = *tmptr;
-	}
-
-	tmptr = (u32 *)of_get_property(pdev->dev.of_node,
-					"xlnx,wdt-enable-once", NULL);
-	if (tmptr == NULL) {
-		pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n");
-		xdev.nowayout = WATCHDOG_NOWAYOUT;
-	}
-
-/*
- *  Twice of the 2^wdt_interval / freq  because the first wdt overflow is
- *  ignored (interrupt), reset is only generated at second wdt overflow
- */
-	if (!no_timeout)
-		timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq);
-
-	if (!request_mem_region(xdev.res.start,
-			xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) {
-		rc = -ENXIO;
-		pr_err("memory request failure!\n");
-		goto err_out;
-	}
-
-	xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1);
-	if (xdev.base == NULL) {
-		rc = -ENOMEM;
-		pr_err("ioremap failure!\n");
-		goto release_mem;
-	}
-
-	rc = xwdt_selftest();
+	u32 pfreq = 0, enable_once = 0;
+	struct resource *res;
+	struct xwdt_device *xdev;
+	struct watchdog_device *xilinx_wdt_wdd;
+
+	xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+	if (!xdev)
+		return -ENOMEM;
+
+	xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+	xilinx_wdt_wdd->info = &xilinx_wdt_ident;
+	xilinx_wdt_wdd->ops = &xilinx_wdt_ops;
+	xilinx_wdt_wdd->parent = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xdev->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(xdev->base))
+		return PTR_ERR(xdev->base);
+
+	rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &pfreq);
+	if (rc)
+		dev_warn(&pdev->dev,
+			 "The watchdog clock frequency cannot be obtained\n");
+
+	rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval",
+				  &xdev->wdt_interval);
+	if (rc)
+		dev_warn(&pdev->dev,
+			 "Parameter \"xlnx,wdt-interval\" not found\n");
+
+	rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-enable-once",
+				  &enable_once);
+	if (rc)
+		dev_warn(&pdev->dev,
+			 "Parameter \"xlnx,wdt-enable-once\" not found\n");
+
+	watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+
+	/*
+	 * Twice of the 2^wdt_interval / freq  because the first wdt overflow is
+	 * ignored (interrupt), reset is only generated at second wdt overflow
+	 */
+	if (pfreq && xdev->wdt_interval)
+		xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
+					  pfreq);
+
+	spin_lock_init(&xdev->spinlock);
+	watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
+
+	rc = xwdt_selftest(xdev);
 	if (rc == XWT_TIMER_FAILED) {
-		pr_err("SelfTest routine error!\n");
-		goto unmap_io;
+		dev_err(&pdev->dev, "SelfTest routine error\n");
+		return rc;
 	}
 
-	xwdt_get_status(&xdev.boot_status);
-
-	rc = misc_register(&xwdt_miscdev);
+	rc = watchdog_register_device(xilinx_wdt_wdd);
 	if (rc) {
-		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-		       xwdt_miscdev.minor, rc);
-		goto unmap_io;
+		dev_err(&pdev->dev, "Cannot register watchdog (err=%d)\n", rc);
+		return rc;
 	}
 
-	if (no_timeout)
-		pr_info("driver loaded (timeout=? sec, nowayout=%d)\n",
-			xdev.nowayout);
-	else
-		pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n",
-			timeout, xdev.nowayout);
+	dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
+		 xdev->base, xilinx_wdt_wdd->timeout);
 
-	expect_close = 0;
-	clear_bit(0, &driver_open);
+	platform_set_drvdata(pdev, xdev);
 
 	return 0;
-
-unmap_io:
-	iounmap(xdev.base);
-release_mem:
-	release_mem_region(xdev.res.start, resource_size(&xdev.res));
-err_out:
-	return rc;
 }
 
-static int xwdt_remove(struct platform_device *dev)
+static int xwdt_remove(struct platform_device *pdev)
 {
-	misc_deregister(&xwdt_miscdev);
-	iounmap(xdev.base);
-	release_mem_region(xdev.res.start, resource_size(&xdev.res));
+	struct xwdt_device *xdev = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&xdev->xilinx_wdt_wdd);
 
 	return 0;
 }
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 09cf0135e8ac..3691b157516a 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -34,7 +34,6 @@
 #include <linux/mm.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
-#include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
@@ -58,7 +57,6 @@ struct omap_wdt_dev {
 	void __iomem    *base;          /* physical */
 	struct device   *dev;
 	bool		omap_wdt_users;
-	struct resource *mem;
 	int		wdt_trgr_pattern;
 	struct mutex	lock;		/* to avoid races with PM */
 };
@@ -207,7 +205,7 @@ static int omap_wdt_probe(struct platform_device *pdev)
 {
 	struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct watchdog_device *omap_wdt;
-	struct resource *res, *mem;
+	struct resource *res;
 	struct omap_wdt_dev *wdev;
 	u32 rs;
 	int ret;
@@ -216,29 +214,20 @@ static int omap_wdt_probe(struct platform_device *pdev)
 	if (!omap_wdt)
 		return -ENOMEM;
 
-	/* reserve static register mappings */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-
-	mem = devm_request_mem_region(&pdev->dev, res->start,
-				      resource_size(res), pdev->name);
-	if (!mem)
-		return -EBUSY;
-
 	wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
 	if (!wdev)
 		return -ENOMEM;
 
 	wdev->omap_wdt_users	= false;
-	wdev->mem		= mem;
 	wdev->dev		= &pdev->dev;
 	wdev->wdt_trgr_pattern	= 0x1234;
 	mutex_init(&wdev->lock);
 
-	wdev->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!wdev->base)
-		return -ENOMEM;
+	/* reserve static register mappings */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	wdev->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdev->base))
+		return PTR_ERR(wdev->base);
 
 	omap_wdt->info	      = &omap_wdt_info;
 	omap_wdt->ops	      = &omap_wdt_ops;
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index f7722a424676..9b3c41d18703 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -18,102 +18,204 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <mach/bridge-regs.h>
+#include <linux/of_device.h>
+
+/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
+#define ORION_RSTOUT_MASK_OFFSET	0x20108
+
+/* Internal registers can be configured at any 1 MiB aligned address */
+#define INTERNAL_REGS_MASK		~(SZ_1M - 1)
 
 /*
  * Watchdog timer block registers.
  */
 #define TIMER_CTRL		0x0000
-#define WDT_EN			0x0010
-#define WDT_VAL			0x0024
+#define TIMER_A370_STATUS	0x04
 
 #define WDT_MAX_CYCLE_COUNT	0xffffffff
-#define WDT_IN_USE		0
-#define WDT_OK_TO_CLOSE		1
 
-#define WDT_RESET_OUT_EN	BIT(1)
-#define WDT_INT_REQ		BIT(3)
+#define WDT_A370_RATIO_MASK(v)	((v) << 16)
+#define WDT_A370_RATIO_SHIFT	5
+#define WDT_A370_RATIO		(1 << WDT_A370_RATIO_SHIFT)
+
+#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
+#define WDT_A370_EXPIRED	BIT(31)
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
-static unsigned int wdt_max_duration;	/* (seconds) */
-static struct clk *clk;
-static unsigned int wdt_tclk;
-static void __iomem *wdt_reg;
-static DEFINE_SPINLOCK(wdt_lock);
 
-static int orion_wdt_ping(struct watchdog_device *wdt_dev)
+struct orion_watchdog;
+
+struct orion_watchdog_data {
+	int wdt_counter_offset;
+	int wdt_enable_bit;
+	int rstout_enable_bit;
+	int (*clock_init)(struct platform_device *,
+			  struct orion_watchdog *);
+	int (*start)(struct watchdog_device *);
+};
+
+struct orion_watchdog {
+	struct watchdog_device wdt;
+	void __iomem *reg;
+	void __iomem *rstout;
+	unsigned long clk_rate;
+	struct clk *clk;
+	const struct orion_watchdog_data *data;
+};
+
+static int orion_wdt_clock_init(struct platform_device *pdev,
+				struct orion_watchdog *dev)
 {
-	spin_lock(&wdt_lock);
+	int ret;
 
-	/* Reload watchdog duration */
-	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret) {
+		clk_put(dev->clk);
+		return ret;
+	}
 
-	spin_unlock(&wdt_lock);
+	dev->clk_rate = clk_get_rate(dev->clk);
 	return 0;
 }
 
-static int orion_wdt_start(struct watchdog_device *wdt_dev)
+static int armada370_wdt_clock_init(struct platform_device *pdev,
+				    struct orion_watchdog *dev)
 {
-	u32 reg;
+	int ret;
 
-	spin_lock(&wdt_lock);
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret) {
+		clk_put(dev->clk);
+		return ret;
+	}
+
+	/* Setup watchdog input clock */
+	atomic_io_modify(dev->reg + TIMER_CTRL,
+			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
+			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
+
+	dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
+	return 0;
+}
+
+static int armadaxp_wdt_clock_init(struct platform_device *pdev,
+				   struct orion_watchdog *dev)
+{
+	int ret;
+
+	dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret) {
+		clk_put(dev->clk);
+		return ret;
+	}
+
+	/* Enable the fixed watchdog clock input */
+	atomic_io_modify(dev->reg + TIMER_CTRL,
+			 WDT_AXP_FIXED_ENABLE_BIT,
+			 WDT_AXP_FIXED_ENABLE_BIT);
+
+	dev->clk_rate = clk_get_rate(dev->clk);
+	return 0;
+}
+
+static int orion_wdt_ping(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+	/* Reload watchdog duration */
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
+	return 0;
+}
+
+static int armada370_start(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
 	/* Set watchdog duration */
-	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
 
-	/* Clear watchdog timer interrupt */
-	writel(~WDT_INT_REQ, BRIDGE_CAUSE);
+	/* Clear the watchdog expiration bit */
+	atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
 
 	/* Enable watchdog timer */
-	reg = readl(wdt_reg + TIMER_CTRL);
-	reg |= WDT_EN;
-	writel(reg, wdt_reg + TIMER_CTRL);
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
+						dev->data->wdt_enable_bit);
+
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
+				      dev->data->rstout_enable_bit);
+	return 0;
+}
+
+static int orion_start(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
+	/* Set watchdog duration */
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
+
+	/* Enable watchdog timer */
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
+						dev->data->wdt_enable_bit);
 
 	/* Enable reset on watchdog */
-	reg = readl(RSTOUTn_MASK);
-	reg |= WDT_RESET_OUT_EN;
-	writel(reg, RSTOUTn_MASK);
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
+				      dev->data->rstout_enable_bit);
 
-	spin_unlock(&wdt_lock);
 	return 0;
 }
 
-static int orion_wdt_stop(struct watchdog_device *wdt_dev)
+static int orion_wdt_start(struct watchdog_device *wdt_dev)
 {
-	u32 reg;
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
-	spin_lock(&wdt_lock);
+	/* There are some per-SoC quirks to handle */
+	return dev->data->start(wdt_dev);
+}
+
+static int orion_wdt_stop(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
 	/* Disable reset on watchdog */
-	reg = readl(RSTOUTn_MASK);
-	reg &= ~WDT_RESET_OUT_EN;
-	writel(reg, RSTOUTn_MASK);
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
 
 	/* Disable watchdog timer */
-	reg = readl(wdt_reg + TIMER_CTRL);
-	reg &= ~WDT_EN;
-	writel(reg, wdt_reg + TIMER_CTRL);
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
 
-	spin_unlock(&wdt_lock);
 	return 0;
 }
 
-static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
+static int orion_wdt_enabled(struct orion_watchdog *dev)
 {
-	unsigned int time_left;
+	bool enabled, running;
+
+	enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
+	running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
 
-	spin_lock(&wdt_lock);
-	time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
-	spin_unlock(&wdt_lock);
+	return enabled && running;
+}
 
-	return time_left;
+static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+	return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
 }
 
 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
@@ -137,68 +239,188 @@ static const struct watchdog_ops orion_wdt_ops = {
 	.get_timeleft = orion_wdt_get_timeleft,
 };
 
-static struct watchdog_device orion_wdt = {
-	.info = &orion_wdt_info,
-	.ops = &orion_wdt_ops,
-	.min_timeout = 1,
+static irqreturn_t orion_wdt_irq(int irq, void *devid)
+{
+	panic("Watchdog Timeout");
+	return IRQ_HANDLED;
+}
+
+/*
+ * The original devicetree binding for this driver specified only
+ * one memory resource, so in order to keep DT backwards compatibility
+ * we try to fallback to a hardcoded register address, if the resource
+ * is missing from the devicetree.
+ */
+static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
+					      phys_addr_t internal_regs)
+{
+	struct resource *res;
+	phys_addr_t rstout;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res)
+		return devm_ioremap(&pdev->dev, res->start,
+				    resource_size(res));
+
+	/* This workaround works only for "orion-wdt", DT-enabled */
+	if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt"))
+		return NULL;
+
+	rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
+
+	WARN(1, FW_BUG "falling back to harcoded RSTOUT reg %pa\n", &rstout);
+	return devm_ioremap(&pdev->dev, rstout, 0x4);
+}
+
+static const struct orion_watchdog_data orion_data = {
+	.rstout_enable_bit = BIT(1),
+	.wdt_enable_bit = BIT(4),
+	.wdt_counter_offset = 0x24,
+	.clock_init = orion_wdt_clock_init,
+	.start = orion_start,
+};
+
+static const struct orion_watchdog_data armada370_data = {
+	.rstout_enable_bit = BIT(8),
+	.wdt_enable_bit = BIT(8),
+	.wdt_counter_offset = 0x34,
+	.clock_init = armada370_wdt_clock_init,
+	.start = armada370_start,
 };
 
+static const struct orion_watchdog_data armadaxp_data = {
+	.rstout_enable_bit = BIT(8),
+	.wdt_enable_bit = BIT(8),
+	.wdt_counter_offset = 0x34,
+	.clock_init = armadaxp_wdt_clock_init,
+	.start = armada370_start,
+};
+
+static const struct of_device_id orion_wdt_of_match_table[] = {
+	{
+		.compatible = "marvell,orion-wdt",
+		.data = &orion_data,
+	},
+	{
+		.compatible = "marvell,armada-370-wdt",
+		.data = &armada370_data,
+	},
+	{
+		.compatible = "marvell,armada-xp-wdt",
+		.data = &armadaxp_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
+
 static int orion_wdt_probe(struct platform_device *pdev)
 {
+	struct orion_watchdog *dev;
+	const struct of_device_id *match;
+	unsigned int wdt_max_duration;	/* (seconds) */
 	struct resource *res;
-	int ret;
+	int ret, irq;
 
-	clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "Orion Watchdog missing clock\n");
-		return -ENODEV;
-	}
-	clk_prepare_enable(clk);
-	wdt_tclk = clk_get_rate(clk);
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog),
+			   GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
+	if (!match)
+		/* Default legacy match */
+		match = &orion_wdt_of_match_table[0];
+
+	dev->wdt.info = &orion_wdt_info;
+	dev->wdt.ops = &orion_wdt_ops;
+	dev->wdt.min_timeout = 1;
+	dev->data = match->data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
-	wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!wdt_reg)
-		return -ENOMEM;
 
-	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
+	dev->reg = devm_ioremap(&pdev->dev, res->start,
+			       resource_size(res));
+	if (!dev->reg)
+		return -ENOMEM;
 
-	orion_wdt.timeout = wdt_max_duration;
-	orion_wdt.max_timeout = wdt_max_duration;
-	watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev);
+	dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
+						     INTERNAL_REGS_MASK);
+	if (!dev->rstout)
+		return -ENODEV;
 
-	watchdog_set_nowayout(&orion_wdt, nowayout);
-	ret = watchdog_register_device(&orion_wdt);
+	ret = dev->data->clock_init(pdev, dev);
 	if (ret) {
-		clk_disable_unprepare(clk);
+		dev_err(&pdev->dev, "cannot initialize clock\n");
 		return ret;
 	}
 
+	wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
+
+	dev->wdt.timeout = wdt_max_duration;
+	dev->wdt.max_timeout = wdt_max_duration;
+	watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev);
+
+	platform_set_drvdata(pdev, &dev->wdt);
+	watchdog_set_drvdata(&dev->wdt, dev);
+
+	/*
+	 * Let's make sure the watchdog is fully stopped, unless it's
+	 * explicitly enabled. This may be the case if the module was
+	 * removed and re-insterted, or if the bootloader explicitly
+	 * set a running watchdog before booting the kernel.
+	 */
+	if (!orion_wdt_enabled(dev))
+		orion_wdt_stop(&dev->wdt);
+
+	/* Request the IRQ only after the watchdog is disabled */
+	irq = platform_get_irq(pdev, 0);
+	if (irq > 0) {
+		/*
+		 * Not all supported platforms specify an interrupt for the
+		 * watchdog, so let's make it optional.
+		 */
+		ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
+				       pdev->name, dev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request IRQ\n");
+			goto disable_clk;
+		}
+	}
+
+	watchdog_set_nowayout(&dev->wdt, nowayout);
+	ret = watchdog_register_device(&dev->wdt);
+	if (ret)
+		goto disable_clk;
+
 	pr_info("Initial timeout %d sec%s\n",
-		orion_wdt.timeout, nowayout ? ", nowayout" : "");
+		dev->wdt.timeout, nowayout ? ", nowayout" : "");
 	return 0;
+
+disable_clk:
+	clk_disable_unprepare(dev->clk);
+	clk_put(dev->clk);
+	return ret;
 }
 
 static int orion_wdt_remove(struct platform_device *pdev)
 {
-	watchdog_unregister_device(&orion_wdt);
-	clk_disable_unprepare(clk);
+	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
+	watchdog_unregister_device(wdt_dev);
+	clk_disable_unprepare(dev->clk);
+	clk_put(dev->clk);
 	return 0;
 }
 
 static void orion_wdt_shutdown(struct platform_device *pdev)
 {
-	orion_wdt_stop(&orion_wdt);
+	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
+	orion_wdt_stop(wdt_dev);
 }
 
-static const struct of_device_id orion_wdt_of_match_table[] = {
-	{ .compatible = "marvell,orion-wdt", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
-
 static struct platform_driver orion_wdt_driver = {
 	.probe		= orion_wdt_probe,
 	.remove		= orion_wdt_remove,
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 5211d56b3681..9f15dd9435d1 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -512,9 +512,8 @@ static int __init pc87413_init(void)
 		return -EBUSY;
 
 	ret = register_reboot_notifier(&pc87413_notifier);
-	if (ret != 0) {
+	if (ret != 0)
 		pr_err("cannot register reboot notifier (err=%d)\n", ret);
-	}
 
 	ret = misc_register(&pc87413_miscdev);
 	if (ret != 0) {
@@ -575,8 +574,8 @@ static void __exit pc87413_exit(void)
 module_init(pc87413_init);
 module_exit(pc87413_exit);
 
-MODULE_AUTHOR("Sven Anders <anders@anduras.de>, "
-		"Marcus Junker <junker@anduras.de>,");
+MODULE_AUTHOR("Sven Anders <anders@anduras.de>");
+MODULE_AUTHOR("Marcus Junker <junker@anduras.de>");
 MODULE_DESCRIPTION("PC87413 WDT driver");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index e562e0476016..1a11aedc4fe8 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -645,10 +645,8 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
 	/* allocate memory for our device and initialize it */
 	usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
-	if (usb_pcwd == NULL) {
-		pr_err("Out of memory\n");
+	if (usb_pcwd == NULL)
 		goto error;
-	}
 
 	usb_pcwd_device = usb_pcwd;
 
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 5bec20f5dc2d..15fb316e9437 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 082d06262959..29cf4dcbc59c 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -27,7 +27,6 @@
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/completion.h>
diff --git a/drivers/watchdog/retu_wdt.c b/drivers/watchdog/retu_wdt.c
index f53615dc633d..a7a0695971e4 100644
--- a/drivers/watchdog/retu_wdt.c
+++ b/drivers/watchdog/retu_wdt.c
@@ -16,7 +16,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/device.h>
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 3dd8ed28adc8..cfed0fe264dc 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -10,7 +10,6 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/of.h>
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index aec946df6ed9..aba6cd46b45b 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/watchdog.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c
index f353e18b1a82..1cfd3f6a13d5 100644
--- a/drivers/watchdog/sc520_wdt.c
+++ b/drivers/watchdog/sc520_wdt.c
@@ -158,12 +158,11 @@ static void wdt_timer_ping(unsigned long data)
 
 static void wdt_config(int writeval)
 {
-	__u16 dummy;
 	unsigned long flags;
 
 	/* buy some time (ping) */
 	spin_lock_irqsave(&wdt_spinlock, flags);
-	dummy = readw(wdtmrctl);	/* ensure write synchronization */
+	readw(wdtmrctl);	/* ensure write synchronization */
 	writew(0xAAAA, wdtmrctl);
 	writew(0x5555, wdtmrctl);
 	/* unlock WDT = make WDT configuration register writable one time */
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index af3528f84d65..d04d02b41c32 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -293,8 +293,6 @@ static int sh_wdt_probe(struct platform_device *pdev)
 
 static int sh_wdt_remove(struct platform_device *pdev)
 {
-	struct sh_wdt *wdt = platform_get_drvdata(pdev);
-
 	watchdog_unregister_device(&sh_wdt_dev);
 
 	pm_runtime_disable(&pdev->dev);
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index c04a1aa158e2..0dc5e323d59d 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(nowayout,
 		"Watchdog cannot be stopped once started (default="
 				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static int soft_noboot = 0;
+static int soft_noboot;
 module_param(soft_noboot, int, 0);
 MODULE_PARM_DESC(soft_noboot,
 	"Softdog action, set to 1 to ignore reboots, 0 to reboot (default=0)");
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 3f786ce0a6f2..47629d268e0a 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -16,7 +16,6 @@
 #include <linux/amba/bus.h>
 #include <linux/bitops.h>
 #include <linux/clk.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
@@ -209,27 +208,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 	struct sp805_wdt *wdt;
 	int ret = 0;
 
-	if (!devm_request_mem_region(&adev->dev, adev->res.start,
-				resource_size(&adev->res), "sp805_wdt")) {
-		dev_warn(&adev->dev, "Failed to get memory region resource\n");
-		ret = -ENOENT;
-		goto err;
-	}
-
 	wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
 	if (!wdt) {
-		dev_warn(&adev->dev, "Kzalloc failed\n");
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	wdt->base = devm_ioremap(&adev->dev, adev->res.start,
-			resource_size(&adev->res));
-	if (!wdt->base) {
-		ret = -ENOMEM;
-		dev_warn(&adev->dev, "ioremap fail\n");
-		goto err;
-	}
+	wdt->base = devm_ioremap_resource(&adev->dev, &adev->res);
+	if (IS_ERR(wdt->base))
+		return PTR_ERR(wdt->base);
 
 	wdt->clk = devm_clk_get(&adev->dev, NULL);
 	if (IS_ERR(wdt->clk)) {
diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c
index bb64ae3f47da..3804d5e9baea 100644
--- a/drivers/watchdog/stmp3xxx_rtc_wdt.c
+++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c
@@ -9,7 +9,6 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/watchdog.h>
diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c
new file mode 100644
index 000000000000..750e2a26cb12
--- /dev/null
+++ b/drivers/watchdog/tegra_wdt.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+/* minimum and maximum watchdog trigger timeout, in seconds */
+#define MIN_WDT_TIMEOUT			1
+#define MAX_WDT_TIMEOUT			255
+
+/*
+ * Base of the WDT registers, from the timer base address.  There are
+ * actually 5 watchdogs that can be configured (by pairing with an available
+ * timer), at bases 0x100 + (WDT ID) * 0x20, where WDT ID is 0 through 4.
+ * This driver only configures the first watchdog (WDT ID 0).
+ */
+#define WDT_BASE			0x100
+#define WDT_ID				0
+
+/*
+ * Register base of the timer that's selected for pairing with the watchdog.
+ * This driver arbitrarily uses timer 5, which is currently unused by
+ * other drivers (in particular, the Tegra clocksource driver).  If this
+ * needs to change, take care that the new timer is not used by the
+ * clocksource driver.
+ */
+#define WDT_TIMER_BASE			0x60
+#define WDT_TIMER_ID			5
+
+/* WDT registers */
+#define WDT_CFG				0x0
+#define WDT_CFG_PERIOD_SHIFT		4
+#define WDT_CFG_PERIOD_MASK		0xff
+#define WDT_CFG_INT_EN			(1 << 12)
+#define WDT_CFG_PMC2CAR_RST_EN		(1 << 15)
+#define WDT_STS				0x4
+#define WDT_STS_COUNT_SHIFT		4
+#define WDT_STS_COUNT_MASK		0xff
+#define WDT_STS_EXP_SHIFT		12
+#define WDT_STS_EXP_MASK		0x3
+#define WDT_CMD				0x8
+#define WDT_CMD_START_COUNTER		(1 << 0)
+#define WDT_CMD_DISABLE_COUNTER		(1 << 1)
+#define WDT_UNLOCK			(0xc)
+#define WDT_UNLOCK_PATTERN		(0xc45a << 0)
+
+/* Timer registers */
+#define TIMER_PTV			0x0
+#define TIMER_EN			(1 << 31)
+#define TIMER_PERIODIC			(1 << 30)
+
+struct tegra_wdt {
+	struct watchdog_device	wdd;
+	void __iomem		*wdt_regs;
+	void __iomem		*tmr_regs;
+};
+
+#define WDT_HEARTBEAT 120
+static int heartbeat = WDT_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat,
+	"Watchdog heartbeats in seconds. (default = "
+	__MODULE_STRING(WDT_HEARTBEAT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+	"Watchdog cannot be stopped once started (default="
+	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int tegra_wdt_start(struct watchdog_device *wdd)
+{
+	struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
+	u32 val;
+
+	/*
+	 * This thing has a fixed 1MHz clock.  Normally, we would set the
+	 * period to 1 second by writing 1000000ul, but the watchdog system
+	 * reset actually occurs on the 4th expiration of this counter,
+	 * so we set the period to 1/4 of this amount.
+	 */
+	val = 1000000ul / 4;
+	val |= (TIMER_EN | TIMER_PERIODIC);
+	writel(val, wdt->tmr_regs + TIMER_PTV);
+
+	/*
+	 * Set number of periods and start counter.
+	 *
+	 * Interrupt handler is not required for user space
+	 * WDT accesses, since the caller is responsible to ping the
+	 * WDT to reset the counter before expiration, through ioctls.
+	 */
+	val = WDT_TIMER_ID |
+	      (wdd->timeout << WDT_CFG_PERIOD_SHIFT) |
+	      WDT_CFG_PMC2CAR_RST_EN;
+	writel(val, wdt->wdt_regs + WDT_CFG);
+
+	writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
+
+	return 0;
+}
+
+static int tegra_wdt_stop(struct watchdog_device *wdd)
+{
+	struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	writel(WDT_UNLOCK_PATTERN, wdt->wdt_regs + WDT_UNLOCK);
+	writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_regs + WDT_CMD);
+	writel(0, wdt->tmr_regs + TIMER_PTV);
+
+	return 0;
+}
+
+static int tegra_wdt_ping(struct watchdog_device *wdd)
+{
+	struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
+
+	return 0;
+}
+
+static int tegra_wdt_set_timeout(struct watchdog_device *wdd,
+				 unsigned int timeout)
+{
+	wdd->timeout = timeout;
+
+	if (watchdog_active(wdd))
+		return tegra_wdt_start(wdd);
+
+	return 0;
+}
+
+static unsigned int tegra_wdt_get_timeleft(struct watchdog_device *wdd)
+{
+	struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
+	u32 val;
+	int count;
+	int exp;
+
+	val = readl(wdt->wdt_regs + WDT_STS);
+
+	/* Current countdown (from timeout) */
+	count = (val >> WDT_STS_COUNT_SHIFT) & WDT_STS_COUNT_MASK;
+
+	/* Number of expirations (we are waiting for the 4th expiration) */
+	exp = (val >> WDT_STS_EXP_SHIFT) & WDT_STS_EXP_MASK;
+
+	/*
+	 * The entire thing is divided by 4 because we are ticking down 4 times
+	 * faster due to needing to wait for the 4th expiration.
+	 */
+	return (((3 - exp) * wdd->timeout) + count) / 4;
+}
+
+static const struct watchdog_info tegra_wdt_info = {
+	.options	= WDIOF_SETTIMEOUT |
+			  WDIOF_MAGICCLOSE |
+			  WDIOF_KEEPALIVEPING,
+	.firmware_version = 0,
+	.identity	= "Tegra Watchdog",
+};
+
+static struct watchdog_ops tegra_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = tegra_wdt_start,
+	.stop = tegra_wdt_stop,
+	.ping = tegra_wdt_ping,
+	.set_timeout = tegra_wdt_set_timeout,
+	.get_timeleft = tegra_wdt_get_timeleft,
+};
+
+static int tegra_wdt_probe(struct platform_device *pdev)
+{
+	struct watchdog_device *wdd;
+	struct tegra_wdt *wdt;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	/* This is the timer base. */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	/*
+	 * Allocate our watchdog driver data, which has the
+	 * struct watchdog_device nested within it.
+	 */
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	/* Initialize struct tegra_wdt. */
+	wdt->wdt_regs = regs + WDT_BASE;
+	wdt->tmr_regs = regs + WDT_TIMER_BASE;
+
+	/* Initialize struct watchdog_device. */
+	wdd = &wdt->wdd;
+	wdd->timeout = heartbeat;
+	wdd->info = &tegra_wdt_info;
+	wdd->ops = &tegra_wdt_ops;
+	wdd->min_timeout = MIN_WDT_TIMEOUT;
+	wdd->max_timeout = MAX_WDT_TIMEOUT;
+
+	watchdog_set_drvdata(wdd, wdt);
+
+	watchdog_set_nowayout(wdd, nowayout);
+
+	ret = watchdog_register_device(wdd);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to register watchdog device\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, wdt);
+
+	dev_info(&pdev->dev,
+		 "initialized (heartbeat = %d sec, nowayout = %d)\n",
+		 heartbeat, nowayout);
+
+	return 0;
+}
+
+static int tegra_wdt_remove(struct platform_device *pdev)
+{
+	struct tegra_wdt *wdt = platform_get_drvdata(pdev);
+
+	tegra_wdt_stop(&wdt->wdd);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	dev_info(&pdev->dev, "removed wdt\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_wdt_runtime_suspend(struct device *dev)
+{
+	struct tegra_wdt *wdt = dev_get_drvdata(dev);
+
+	if (watchdog_active(&wdt->wdd))
+		tegra_wdt_stop(&wdt->wdd);
+
+	return 0;
+}
+
+static int tegra_wdt_runtime_resume(struct device *dev)
+{
+	struct tegra_wdt *wdt = dev_get_drvdata(dev);
+
+	if (watchdog_active(&wdt->wdd))
+		tegra_wdt_start(&wdt->wdd);
+
+	return 0;
+}
+#endif
+
+static const struct of_device_id tegra_wdt_of_match[] = {
+	{ .compatible = "nvidia,tegra30-timer", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_wdt_of_match);
+
+static const struct dev_pm_ops tegra_wdt_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_wdt_runtime_suspend,
+				tegra_wdt_runtime_resume)
+};
+
+static struct platform_driver tegra_wdt_driver = {
+	.probe		= tegra_wdt_probe,
+	.remove		= tegra_wdt_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "tegra-wdt",
+		.pm	= &tegra_wdt_pm_ops,
+		.of_match_table = tegra_wdt_of_match,
+	},
+};
+module_platform_driver(tegra_wdt_driver);
+
+MODULE_AUTHOR("NVIDIA Corporation");
+MODULE_DESCRIPTION("Tegra Watchdog Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 09d4831aa61f..afa9d6ef353a 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -61,7 +61,7 @@ struct ts72xx_wdt {
 	struct platform_device *pdev;
 };
 
-struct platform_device *ts72xx_wdt_pdev;
+static struct platform_device *ts72xx_wdt_pdev;
 
 /*
  * TS-72xx Watchdog supports following timeouts (value written
@@ -394,10 +394,8 @@ static int ts72xx_wdt_probe(struct platform_device *pdev)
 	int error = 0;
 
 	wdt = devm_kzalloc(&pdev->dev, sizeof(struct ts72xx_wdt), GFP_KERNEL);
-	if (!wdt) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!wdt)
 		return -ENOMEM;
-	}
 
 	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1);
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index 68b45fc9ba6a..e9ea856b8ff2 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -455,6 +455,6 @@ module_init(wdt_init);
 module_exit(wdt_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marcus Junker <junker@anduras.de>, "
-		"Samuel Tardieu <sam@rfc1149.net>");
+MODULE_AUTHOR("Marcus Junker <junker@anduras.de>");
+MODULE_AUTHOR("Samuel Tardieu <sam@rfc1149.net>");
 MODULE_DESCRIPTION("w83697hf/hg WDT driver");
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
index 7355ddd0b207..ebbb183be618 100644
--- a/drivers/watchdog/wdt285.c
+++ b/drivers/watchdog/wdt285.c
@@ -139,9 +139,8 @@ static const struct watchdog_info ident = {
 static long watchdog_ioctl(struct file *file, unsigned int cmd,
 			   unsigned long arg)
 {
-	unsigned int new_margin;
 	int __user *int_arg = (int __user *)arg;
-	int ret = -ENOTTY;
+	int new_margin, ret = -ENOTTY;
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 3dc578e71211..48b2c058b009 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -49,7 +49,6 @@
 #include <linux/delay.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
-#include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/pci.h>
 #include <linux/io.h>
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index e243bd01c774..2fa17e746ff6 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -204,7 +204,6 @@ static int wm831x_wdt_probe(struct platform_device *pdev)
 	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
 				   GFP_KERNEL);
 	if (!driver_data) {
-		dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
 		ret = -ENOMEM;
 		goto err;
 	}
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 45e00afa7f2d..6b867e9e46b3 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),)
 obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 endif
 obj-$(CONFIG_X86)			+= fallback.o
-obj-y	+= grant-table.o features.o balloon.o manage.o
+obj-y	+= grant-table.o features.o balloon.o manage.o preempt.o
 obj-y	+= events/
 obj-y	+= xenbus/
 
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index f4a9e3311297..793053065629 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -391,10 +391,10 @@ static void xen_irq_init(unsigned irq)
 	list_add_tail(&info->list, &xen_irq_list_head);
 }
 
-static int __must_check xen_allocate_irq_dynamic(void)
+static int __must_check xen_allocate_irqs_dynamic(int nvec)
 {
 	int first = 0;
-	int irq;
+	int i, irq;
 
 #ifdef CONFIG_X86_IO_APIC
 	/*
@@ -408,14 +408,22 @@ static int __must_check xen_allocate_irq_dynamic(void)
 		first = get_nr_irqs_gsi();
 #endif
 
-	irq = irq_alloc_desc_from(first, -1);
+	irq = irq_alloc_descs_from(first, nvec, -1);
 
-	if (irq >= 0)
-		xen_irq_init(irq);
+	if (irq >= 0) {
+		for (i = 0; i < nvec; i++)
+			xen_irq_init(irq + i);
+	}
 
 	return irq;
 }
 
+static inline int __must_check xen_allocate_irq_dynamic(void)
+{
+
+	return xen_allocate_irqs_dynamic(1);
+}
+
 static int __must_check xen_allocate_irq_gsi(unsigned gsi)
 {
 	int irq;
@@ -469,9 +477,6 @@ static void xen_evtchn_close(unsigned int port)
 	close.port = port;
 	if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
 		BUG();
-
-	/* Closed ports are implicitly re-bound to VCPU0. */
-	bind_evtchn_to_cpu(port, 0);
 }
 
 static void pirq_query_unmask(int irq)
@@ -741,22 +746,25 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
 }
 
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-			     int pirq, const char *name, domid_t domid)
+			     int pirq, int nvec, const char *name, domid_t domid)
 {
-	int irq, ret;
+	int i, irq, ret;
 
 	mutex_lock(&irq_mapping_update_lock);
 
-	irq = xen_allocate_irq_dynamic();
+	irq = xen_allocate_irqs_dynamic(nvec);
 	if (irq < 0)
 		goto out;
 
-	irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
-			name);
+	for (i = 0; i < nvec; i++) {
+		irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name);
+
+		ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid,
+					      i == 0 ? 0 : PIRQ_MSI_GROUP);
+		if (ret < 0)
+			goto error_irq;
+	}
 
-	ret = xen_irq_info_pirq_setup(irq, 0, pirq, 0, domid, 0);
-	if (ret < 0)
-		goto error_irq;
 	ret = irq_set_msi_desc(irq, msidesc);
 	if (ret < 0)
 		goto error_irq;
@@ -764,7 +772,8 @@ out:
 	mutex_unlock(&irq_mapping_update_lock);
 	return irq;
 error_irq:
-	__unbind_from_irq(irq);
+	for (; i >= 0; i--)
+		__unbind_from_irq(irq + i);
 	mutex_unlock(&irq_mapping_update_lock);
 	return ret;
 }
@@ -783,7 +792,12 @@ int xen_destroy_irq(int irq)
 	if (!desc)
 		goto out;
 
-	if (xen_initial_domain()) {
+	/*
+	 * If trying to remove a vector in a MSI group different
+	 * than the first one skip the PIRQ unmap unless this vector
+	 * is the first one in the group.
+	 */
+	if (xen_initial_domain() && !(info->u.pirq.flags & PIRQ_MSI_GROUP)) {
 		unmap_irq.pirq = info->u.pirq.pirq;
 		unmap_irq.domid = info->u.pirq.domid;
 		rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
@@ -1344,26 +1358,6 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
 	return rebind_irq_to_cpu(data->irq, tcpu);
 }
 
-static int retrigger_evtchn(int evtchn)
-{
-	int masked;
-
-	if (!VALID_EVTCHN(evtchn))
-		return 0;
-
-	masked = test_and_set_mask(evtchn);
-	set_evtchn(evtchn);
-	if (!masked)
-		unmask_evtchn(evtchn);
-
-	return 1;
-}
-
-int resend_irq_on_evtchn(unsigned int irq)
-{
-	return retrigger_evtchn(evtchn_from_irq(irq));
-}
-
 static void enable_dynirq(struct irq_data *data)
 {
 	int evtchn = evtchn_from_irq(data->irq);
@@ -1398,7 +1392,18 @@ static void mask_ack_dynirq(struct irq_data *data)
 
 static int retrigger_dynirq(struct irq_data *data)
 {
-	return retrigger_evtchn(evtchn_from_irq(data->irq));
+	unsigned int evtchn = evtchn_from_irq(data->irq);
+	int masked;
+
+	if (!VALID_EVTCHN(evtchn))
+		return 0;
+
+	masked = test_and_set_mask(evtchn);
+	set_evtchn(evtchn);
+	if (!masked)
+		unmask_evtchn(evtchn);
+
+	return 1;
 }
 
 static void restore_pirqs(void)
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h
index 677f41a0fff9..50c2050a1e32 100644
--- a/drivers/xen/events/events_internal.h
+++ b/drivers/xen/events/events_internal.h
@@ -53,6 +53,7 @@ struct irq_info {
 
 #define PIRQ_NEEDS_EOI	(1 << 0)
 #define PIRQ_SHAREABLE	(1 << 1)
+#define PIRQ_MSI_GROUP	(1 << 2)
 
 struct evtchn_ops {
 	unsigned (*max_channels)(void);
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c
index 79e1dff7ed4f..0aac403d53fd 100644
--- a/drivers/xen/pcpu.c
+++ b/drivers/xen/pcpu.c
@@ -40,6 +40,7 @@
 #include <linux/capability.h>
 
 #include <xen/xen.h>
+#include <xen/acpi.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/interface/platform.h>
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index a1361c312c06..3454973dc3bb 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -45,7 +45,7 @@ static unsigned long platform_mmio_alloc;
 static unsigned long platform_mmiolen;
 static uint64_t callback_via;
 
-unsigned long alloc_xen_mmio(unsigned long len)
+static unsigned long alloc_xen_mmio(unsigned long len)
 {
 	unsigned long addr;
 
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
new file mode 100644
index 000000000000..b5a3e981b78c
--- /dev/null
+++ b/drivers/xen/preempt.c
@@ -0,0 +1,17 @@
+/*
+ * Preemptible hypercalls
+ *
+ * Copyright (C) 2014 Citrix Systems R&D ltd.
+ *
+ * This source code is free software; you can redistribute 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 <xen/xen-ops.h>
+
+#ifndef CONFIG_PREEMPT
+DEFINE_PER_CPU(bool, xen_in_preemptible_hcall);
+EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall);
+#endif
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 569a13b9e856..59ac71c4a043 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata)
 	if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
 		return -EFAULT;
 
+	xen_preemptible_hcall_begin();
 	ret = privcmd_call(hypercall.op,
 			   hypercall.arg[0], hypercall.arg[1],
 			   hypercall.arg[2], hypercall.arg[3],
 			   hypercall.arg[4]);
+	xen_preemptible_hcall_end();
 
 	return ret;
 }
diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c
index 80875fb770ed..3e62ee4b3b66 100644
--- a/drivers/xen/xen-acpi-cpuhotplug.c
+++ b/drivers/xen/xen-acpi-cpuhotplug.c
@@ -313,7 +313,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
 		goto out;
 	}
 
-	(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
+	(void) acpi_evaluate_ost(handle, event, ost_code, NULL);
 
 out:
 	acpi_scan_lock_release();
diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c
index f8d18626969a..34e40b733f9a 100644
--- a/drivers/xen/xen-acpi-memhotplug.c
+++ b/drivers/xen/xen-acpi-memhotplug.c
@@ -285,7 +285,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 		return;
 	}
 
-	(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
+	(void) acpi_evaluate_ost(handle, event, ost_code, NULL);
 	return;
 }
 
diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c
index 40c4bc06b5fa..f83b754505f8 100644
--- a/drivers/xen/xen-acpi-pad.c
+++ b/drivers/xen/xen-acpi-pad.c
@@ -77,27 +77,14 @@ static int acpi_pad_pur(acpi_handle handle)
 	return num;
 }
 
-/* Notify firmware how many CPUs are idle */
-static void acpi_pad_ost(acpi_handle handle, int stat,
-	uint32_t idle_nums)
-{
-	union acpi_object params[3] = {
-		{.type = ACPI_TYPE_INTEGER,},
-		{.type = ACPI_TYPE_INTEGER,},
-		{.type = ACPI_TYPE_BUFFER,},
-	};
-	struct acpi_object_list arg_list = {3, params};
-
-	params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
-	params[1].integer.value =  stat;
-	params[2].buffer.length = 4;
-	params[2].buffer.pointer = (void *)&idle_nums;
-	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-}
-
 static void acpi_pad_handle_notify(acpi_handle handle)
 {
 	int idle_nums;
+	struct acpi_buffer param = {
+		.length = 4,
+		.pointer = (void *)&idle_nums,
+	};
+
 
 	mutex_lock(&xen_cpu_lock);
 	idle_nums = acpi_pad_pur(handle);
@@ -109,7 +96,8 @@ static void acpi_pad_handle_notify(acpi_handle handle)
 	idle_nums = xen_acpi_pad_idle_cpus(idle_nums)
 		    ?: xen_acpi_pad_idle_cpus_num();
 	if (idle_nums >= 0)
-		acpi_pad_ost(handle, 0, idle_nums);
+		acpi_evaluate_ost(handle, ACPI_PROCESSOR_AGGREGATOR_NOTIFY,
+				  0, &param);
 	mutex_unlock(&xen_cpu_lock);
 }
 
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 64eb0cd8b8af..929dd46bb40c 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -213,8 +213,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
 		entries[i].vector = op->msix_entries[i].vector;
 	}
 
-	result = pci_enable_msix(dev, entries, op->value);
-
+	result = pci_enable_msix_exact(dev, entries, op->value);
 	if (result == 0) {
 		for (i = 0; i < op->value; i++) {
 			op->msix_entries[i].entry = entries[i].entry;
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
index 745ad79c1d8e..3b2bffde534f 100644
--- a/drivers/xen/xen-selfballoon.c
+++ b/drivers/xen/xen-selfballoon.c
@@ -170,6 +170,7 @@ static void frontswap_selfshrink(void)
 		tgt_frontswap_pages = cur_frontswap_pages -
 			(cur_frontswap_pages / frontswap_hysteresis);
 	frontswap_shrink(tgt_frontswap_pages);
+	frontswap_inertia_counter = frontswap_inertia;
 }
 
 #endif /* CONFIG_FRONTSWAP */
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 01d59e66565d..439c9dca9eee 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -401,33 +401,6 @@ EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
 
 
 /**
- * Bind to an existing interdomain event channel in another domain. Returns 0
- * on success and stores the local port in *port. On error, returns -errno,
- * switches the device to XenbusStateClosing, and saves the error in XenStore.
- */
-int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
-{
-	struct evtchn_bind_interdomain bind_interdomain;
-	int err;
-
-	bind_interdomain.remote_dom = dev->otherend_id;
-	bind_interdomain.remote_port = remote_port;
-
-	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
-					  &bind_interdomain);
-	if (err)
-		xenbus_dev_fatal(dev, err,
-				 "binding to event channel %d from domain %d",
-				 remote_port, dev->otherend_id);
-	else
-		*port = bind_interdomain.local_port;
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
-
-
-/**
  * Free an existing event channel. Returns 0 on success or -errno on error.
  */
 int xenbus_free_evtchn(struct xenbus_device *dev, int port)
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index a16b0ff497ca..d8223209d4b1 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -832,6 +832,7 @@ static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
 
 static const struct vm_operations_struct v9fs_file_vm_ops = {
 	.fault = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = v9fs_vm_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
@@ -839,6 +840,7 @@ static const struct vm_operations_struct v9fs_file_vm_ops = {
 static const struct vm_operations_struct v9fs_mmap_file_vm_ops = {
 	.close = v9fs_mmap_vm_close,
 	.fault = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = v9fs_vm_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index bb7991c7e5c7..53161ec058a7 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -451,7 +451,7 @@ void v9fs_evict_inode(struct inode *inode)
 {
 	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	truncate_inode_pages(inode->i_mapping, 0);
+	truncate_inode_pages_final(inode->i_mapping);
 	clear_inode(inode);
 	filemap_fdatawrite(inode->i_mapping);
 
diff --git a/fs/Kconfig b/fs/Kconfig
index 7385e54be4b9..312393f32948 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -96,6 +96,7 @@ endif # BLOCK
 menu "Pseudo filesystems"
 
 source "fs/proc/Kconfig"
+source "fs/kernfs/Kconfig"
 source "fs/sysfs/Kconfig"
 
 config TMPFS
diff --git a/fs/Makefile b/fs/Makefile
index 47ac07bb4acc..f9cb9876e466 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -52,7 +52,8 @@ obj-$(CONFIG_FHANDLE)		+= fhandle.o
 obj-y				+= quota/
 
 obj-$(CONFIG_PROC_FS)		+= proc/
-obj-$(CONFIG_SYSFS)		+= sysfs/ kernfs/
+obj-$(CONFIG_KERNFS)		+= kernfs/
+obj-$(CONFIG_SYSFS)		+= sysfs/
 obj-$(CONFIG_CONFIGFS_FS)	+= configfs/
 obj-y				+= devpts/
 
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 7b3003cb6f1b..15796f8e86f3 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -265,7 +265,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
 					     sizeof(struct adfs_inode_info),
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index f1eba8c3644e..cbbda476a805 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -52,8 +52,10 @@ affs_readdir(struct file *file, struct dir_context *ctx)
 	int			 hash_pos;
 	int			 chain_pos;
 	u32			 ino;
+	int			 error = 0;
 
-	pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)ctx->pos);
+	pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",
+		 inode->i_ino, (unsigned long)ctx->pos);
 
 	if (ctx->pos < 2) {
 		file->private_data = (void *)0;
@@ -72,7 +74,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
 	}
 	dir_bh = affs_bread(sb, inode->i_ino);
 	if (!dir_bh)
-		goto readdir_out;
+		goto out_unlock_dir;
 
 	/* If the directory hasn't changed since the last call to readdir(),
 	 * we can jump directly to where we left off.
@@ -88,7 +90,8 @@ affs_readdir(struct file *file, struct dir_context *ctx)
 		fh_bh = affs_bread(sb, ino);
 		if (!fh_bh) {
 			affs_error(sb, "readdir","Cannot read block %d", i);
-			return -EIO;
+			error = -EIO;
+			goto out_brelse_dir;
 		}
 		ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
 		affs_brelse(fh_bh);
@@ -107,29 +110,34 @@ inside:
 		do {
 			fh_bh = affs_bread(sb, ino);
 			if (!fh_bh) {
-				affs_error(sb, "readdir","Cannot read block %d", ino);
+				affs_error(sb, "readdir",
+					   "Cannot read block %d", ino);
 				break;
 			}
 
 			namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
 			name = AFFS_TAIL(sb, fh_bh)->name + 1;
-			pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
+			pr_debug("AFFS: readdir(): dir_emit(\"%.*s\", "
+				 "ino=%u), hash=%d, f_pos=%x\n",
 				 namelen, name, ino, hash_pos, (u32)ctx->pos);
+
 			if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
-				goto readdir_done;
+				goto done;
 			ctx->pos++;
 			ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
 			affs_brelse(fh_bh);
 			fh_bh = NULL;
 		} while (ino);
 	}
-readdir_done:
+done:
 	file->f_version = inode->i_version;
 	file->private_data = (void *)(long)ino;
+	affs_brelse(fh_bh);
 
-readdir_out:
+out_brelse_dir:
 	affs_brelse(dir_bh);
-	affs_brelse(fh_bh);
+
+out_unlock_dir:
 	affs_unlock_dir(inode);
-	return 0;
+	return error;
 }
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 0e092d08680e..96df91e8c334 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -259,7 +259,7 @@ affs_evict_inode(struct inode *inode)
 {
 	unsigned long cache_page;
 	pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	if (!inode->i_nlink) {
 		inode->i_size = 0;
diff --git a/fs/affs/super.c b/fs/affs/super.c
index d098731b82ff..41a755721fb5 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -128,7 +128,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	affs_inode_cachep = kmem_cache_create("affs_inode_cache",
 					     sizeof(struct affs_inode_info),
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index ce25d755b7aa..294671288449 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -422,7 +422,7 @@ void afs_evict_inode(struct inode *inode)
 
 	ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode);
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 
 	afs_give_up_callback(vnode);
diff --git a/fs/aio.c b/fs/aio.c
index 062a5f6a1448..50c089c94a7a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -366,6 +366,7 @@ static int aio_setup_ring(struct kioctx *ctx)
 	int nr_pages;
 	int i;
 	struct file *file;
+	unsigned long flags;
 
 	/* Compensate for the ring buffer's head/tail overlap entry */
 	nr_events += 2;	/* 1 is required, 2 for good luck */
@@ -437,6 +438,14 @@ static int aio_setup_ring(struct kioctx *ctx)
 	ctx->user_id = ctx->mmap_base;
 	ctx->nr_events = nr_events; /* trusted copy */
 
+	/*
+	 * The aio ring pages are user space pages, so they can be migrated.
+	 * When writing to an aio ring page, we should ensure the page is not
+	 * being migrated. Aio page migration procedure is protected by
+	 * ctx->completion_lock, so we add this lock here.
+	 */
+	spin_lock_irqsave(&ctx->completion_lock, flags);
+
 	ring = kmap_atomic(ctx->ring_pages[0]);
 	ring->nr = nr_events;	/* user copy */
 	ring->id = ~0U;
@@ -448,6 +457,8 @@ static int aio_setup_ring(struct kioctx *ctx)
 	kunmap_atomic(ring);
 	flush_dcache_page(ctx->ring_pages[0]);
 
+	spin_unlock_irqrestore(&ctx->completion_lock, flags);
+
 	return 0;
 }
 
@@ -542,6 +553,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
 	unsigned i, new_nr;
 	struct kioctx_table *table, *old;
 	struct aio_ring *ring;
+	unsigned long flags;
 
 	spin_lock(&mm->ioctx_lock);
 	rcu_read_lock();
@@ -556,9 +568,19 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
 					rcu_read_unlock();
 					spin_unlock(&mm->ioctx_lock);
 
+					/*
+					 * Accessing ring pages must be done
+					 * holding ctx->completion_lock to
+					 * prevent aio ring page migration
+					 * procedure from migrating ring pages.
+					 */
+					spin_lock_irqsave(&ctx->completion_lock,
+							  flags);
 					ring = kmap_atomic(ctx->ring_pages[0]);
 					ring->id = ctx->id;
 					kunmap_atomic(ring);
+					spin_unlock_irqrestore(
+						&ctx->completion_lock, flags);
 					return 0;
 				}
 
@@ -1021,6 +1043,7 @@ static long aio_read_events_ring(struct kioctx *ctx,
 	unsigned head, tail, pos;
 	long ret = 0;
 	int copy_ret;
+	unsigned long flags;
 
 	mutex_lock(&ctx->ring_lock);
 
@@ -1066,11 +1089,21 @@ static long aio_read_events_ring(struct kioctx *ctx,
 		head %= ctx->nr_events;
 	}
 
+	/*
+	 * The aio ring pages are user space pages, so they can be migrated.
+	 * When writing to an aio ring page, we should ensure the page is not
+	 * being migrated. Aio page migration procedure is protected by
+	 * ctx->completion_lock, so we add this lock here.
+	 */
+	spin_lock_irqsave(&ctx->completion_lock, flags);
+
 	ring = kmap_atomic(ctx->ring_pages[0]);
 	ring->head = head;
 	kunmap_atomic(ring);
 	flush_dcache_page(ctx->ring_pages[0]);
 
+	spin_unlock_irqrestore(&ctx->completion_lock, flags);
+
 	pr_debug("%li  h%u t%u\n", ret, head, tail);
 
 	put_reqs_available(ctx, ret);
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 845d2d690ce2..079872d61f75 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -39,7 +39,6 @@ static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int)
 static struct inode *befs_iget(struct super_block *, unsigned long);
 static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
-static int befs_init_inodecache(void);
 static void befs_destroy_inodecache(void);
 static void *befs_follow_link(struct dentry *, struct nameidata *);
 static void *befs_fast_follow_link(struct dentry *, struct nameidata *);
@@ -445,7 +444,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
  *
  * Taken from NFS implementation by Al Viro.
  */
-static int
+static int __init
 befs_init_inodecache(void)
 {
 	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
@@ -791,7 +790,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
 
 	save_mount_options(sb, data);
 
-	sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL);
+	sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
 	if (sb->s_fs_info == NULL) {
 		printk(KERN_ERR
 		       "BeFS(%s): Unable to allocate memory for private "
@@ -799,7 +798,6 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
 		goto unacquire_none;
 	}
 	befs_sb = BEFS_SB(sb);
-	memset(befs_sb, 0, sizeof(befs_sb_info));
 
 	if (!parse_options((char *) data, &befs_sb->mount_opts)) {
 		befs_error(sb, "cannot parse mount options");
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 8defc6b3f9a2..29aa5cf6639b 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -172,7 +172,7 @@ static void bfs_evict_inode(struct inode *inode)
 
 	dprintf("ino=%08lx\n", ino);
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	invalidate_inode_buffers(inode);
 	clear_inode(inode);
 
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 67be2951b98a..c2e5d4647345 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -46,10 +46,15 @@
 #endif
 
 static int load_elf_binary(struct linux_binprm *bprm);
-static int load_elf_library(struct file *);
 static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
 				int, int, unsigned long);
 
+#ifdef CONFIG_USELIB
+static int load_elf_library(struct file *);
+#else
+#define load_elf_library NULL
+#endif
+
 /*
  * If we don't support core dumping, then supply a NULL so we
  * don't even try.
@@ -140,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)
@@ -201,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)))
@@ -579,7 +603,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long reloc_func_desc __maybe_unused = 0;
 	int executable_stack = EXSTACK_DEFAULT;
-	unsigned long def_flags = 0;
 	struct pt_regs *regs = current_pt_regs();
 	struct {
 		struct elfhdr elf_ex;
@@ -719,9 +742,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 	if (retval)
 		goto out_free_dentry;
 
-	/* OK, This is the point of no return */
-	current->mm->def_flags = def_flags;
-
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
 	   may depend on the personality.  */
 	SET_PERSONALITY(loc->elf_ex);
@@ -1005,6 +1025,7 @@ out_free_ph:
 	goto out;
 }
 
+#ifdef CONFIG_USELIB
 /* This is really simpleminded and specialized - we are loading an
    a.out library that is given an ELF header. */
 static int load_elf_library(struct file *file)
@@ -1083,6 +1104,7 @@ out_free_ph:
 out:
 	return error;
 }
+#endif /* #ifdef CONFIG_USELIB */
 
 #ifdef CONFIG_ELF_CORE
 /*
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
index 0129b78a6908..413312f2b295 100644
--- a/fs/bio-integrity.c
+++ b/fs/bio-integrity.c
@@ -301,25 +301,26 @@ int bio_integrity_get_tag(struct bio *bio, void *tag_buf, unsigned int len)
 EXPORT_SYMBOL(bio_integrity_get_tag);
 
 /**
- * bio_integrity_generate - Generate integrity metadata for a bio
- * @bio:	bio to generate integrity metadata for
- *
- * Description: Generates integrity metadata for a bio by calling the
- * block device's generation callback function.  The bio must have a
- * bip attached with enough room to accommodate the generated
- * integrity metadata.
+ * bio_integrity_generate_verify - Generate/verify integrity metadata for a bio
+ * @bio:	bio to generate/verify integrity metadata for
+ * @operate:	operate number, 1 for generate, 0 for verify
  */
-static void bio_integrity_generate(struct bio *bio)
+static int bio_integrity_generate_verify(struct bio *bio, int operate)
 {
 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 	struct blk_integrity_exchg bix;
 	struct bio_vec bv;
 	struct bvec_iter iter;
-	sector_t sector = bio->bi_iter.bi_sector;
-	unsigned int sectors, total;
+	sector_t sector;
+	unsigned int sectors, total, ret;
 	void *prot_buf = bio->bi_integrity->bip_buf;
 
-	total = 0;
+	if (operate)
+		sector = bio->bi_iter.bi_sector;
+	else
+		sector = bio->bi_integrity->bip_iter.bi_sector;
+
+	total = ret = 0;
 	bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
 	bix.sector_size = bi->sector_size;
 
@@ -330,7 +331,15 @@ static void bio_integrity_generate(struct bio *bio)
 		bix.prot_buf = prot_buf;
 		bix.sector = sector;
 
-		bi->generate_fn(&bix);
+		if (operate) {
+			bi->generate_fn(&bix);
+		} else {
+			ret = bi->verify_fn(&bix);
+			if (ret) {
+				kunmap_atomic(kaddr);
+				return ret;
+			}
+		}
 
 		sectors = bv.bv_len / bi->sector_size;
 		sector += sectors;
@@ -340,6 +349,21 @@ static void bio_integrity_generate(struct bio *bio)
 
 		kunmap_atomic(kaddr);
 	}
+	return ret;
+}
+
+/**
+ * bio_integrity_generate - Generate integrity metadata for a bio
+ * @bio:	bio to generate integrity metadata for
+ *
+ * Description: Generates integrity metadata for a bio by calling the
+ * block device's generation callback function.  The bio must have a
+ * bip attached with enough room to accommodate the generated
+ * integrity metadata.
+ */
+static void bio_integrity_generate(struct bio *bio)
+{
+	bio_integrity_generate_verify(bio, 1);
 }
 
 static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
@@ -454,43 +478,7 @@ EXPORT_SYMBOL(bio_integrity_prep);
  */
 static int bio_integrity_verify(struct bio *bio)
 {
-	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
-	struct blk_integrity_exchg bix;
-	struct bio_vec *bv;
-	sector_t sector = bio->bi_integrity->bip_iter.bi_sector;
-	unsigned int sectors, total, ret;
-	void *prot_buf = bio->bi_integrity->bip_buf;
-	int i;
-
-	ret = total = 0;
-	bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
-	bix.sector_size = bi->sector_size;
-
-	bio_for_each_segment_all(bv, bio, i) {
-		void *kaddr = kmap_atomic(bv->bv_page);
-
-		bix.data_buf = kaddr + bv->bv_offset;
-		bix.data_size = bv->bv_len;
-		bix.prot_buf = prot_buf;
-		bix.sector = sector;
-
-		ret = bi->verify_fn(&bix);
-
-		if (ret) {
-			kunmap_atomic(kaddr);
-			return ret;
-		}
-
-		sectors = bv->bv_len / bi->sector_size;
-		sector += sectors;
-		prot_buf += sectors * bi->tuple_size;
-		total += sectors * bi->tuple_size;
-		BUG_ON(total > bio->bi_integrity->bip_iter.bi_size);
-
-		kunmap_atomic(kaddr);
-	}
-
-	return ret;
+	return bio_integrity_generate_verify(bio, 0);
 }
 
 /**
diff --git a/fs/bio.c b/fs/bio.c
index 8754e7b6eb49..b1bc722b89aa 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -116,7 +116,6 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
 	if (!slab)
 		goto out_unlock;
 
-	printk(KERN_INFO "bio: create slab <%s> at %d\n", bslab->name, entry);
 	bslab->slab = slab;
 	bslab->slab_ref = 1;
 	bslab->slab_size = sz;
@@ -1970,7 +1969,7 @@ int bio_associate_current(struct bio *bio)
 
 	/* associate blkcg if exists */
 	rcu_read_lock();
-	css = task_css(current, blkio_subsys_id);
+	css = task_css(current, blkio_cgrp_id);
 	if (css && css_tryget(css))
 		bio->bi_css = css;
 	rcu_read_unlock();
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1e86823a9cbd..ba0d2b05bb78 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -83,7 +83,7 @@ void kill_bdev(struct block_device *bdev)
 {
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
 
-	if (mapping->nrpages == 0)
+	if (mapping->nrpages == 0 && mapping->nrshadows == 0)
 		return;
 
 	invalidate_bh_lrus();
@@ -419,7 +419,7 @@ static void bdev_evict_inode(struct inode *inode)
 {
 	struct block_device *bdev = &BDEV_I(inode)->bdev;
 	struct list_head *p;
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	invalidate_inode_buffers(inode); /* is it needed here? */
 	clear_inode(inode);
 	spin_lock(&bdev_lock);
@@ -1523,7 +1523,7 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		ssize_t err;
 
 		err = generic_write_sync(file, pos, ret);
-		if (err < 0 && ret > 0)
+		if (err < 0)
 			ret = err;
 	}
 	blk_finish_plug(&plug);
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index b01fb6c527e3..d43c544d3b68 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -472,7 +472,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
 		rcu_read_lock();
 		page = radix_tree_lookup(&mapping->page_tree, pg_index);
 		rcu_read_unlock();
-		if (page) {
+		if (page && !radix_tree_exceptional_entry(page)) {
 			misses++;
 			if (misses > 4)
 				break;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 0165b8672f09..82af8cddbc6b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1797,7 +1797,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
 	BTRFS_I(inode)->last_sub_trans = root->log_transid;
 	if (num_written > 0) {
 		err = generic_write_sync(file, pos, num_written);
-		if (err < 0 && num_written > 0)
+		if (err < 0)
 			num_written = err;
 	}
 
@@ -1993,6 +1993,7 @@ out:
 
 static const struct vm_operations_struct btrfs_file_vm_ops = {
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite	= btrfs_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d3d44486290b..49ec1398879f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4593,7 +4593,7 @@ static void evict_inode_truncate_pages(struct inode *inode)
 	struct rb_node *node;
 
 	ASSERT(inode->i_state & I_FREEING);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	write_lock(&map_tree->lock);
 	while (!RB_EMPTY_ROOT(&map_tree->map)) {
diff --git a/fs/buffer.c b/fs/buffer.c
index 27265a8b43c1..8c53a2b15ecb 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -3088,7 +3088,7 @@ EXPORT_SYMBOL(submit_bh);
  * until the buffer gets unlocked).
  *
  * ll_rw_block sets b_end_io to simple completion handler that marks
- * the buffer up-to-date (if approriate), unlocks the buffer and wakes
+ * the buffer up-to-date (if appropriate), unlocks the buffer and wakes
  * any waiters. 
  *
  * All of the buffers must be for the same device, and must also be a
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index ebaff368120d..4b1fb5ca65b8 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -265,24 +265,22 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
 				goto nomem_monitor;
 		}
 
-		ret = add_to_page_cache(newpage, bmapping,
-					netpage->index, cachefiles_gfp);
+		ret = add_to_page_cache_lru(newpage, bmapping,
+					    netpage->index, cachefiles_gfp);
 		if (ret == 0)
 			goto installed_new_backing_page;
 		if (ret != -EEXIST)
 			goto nomem_page;
 	}
 
-	/* we've installed a new backing page, so now we need to add it
-	 * to the LRU list and start it reading */
+	/* we've installed a new backing page, so now we need to start
+	 * it reading */
 installed_new_backing_page:
 	_debug("- new %p", newpage);
 
 	backpage = newpage;
 	newpage = NULL;
 
-	lru_cache_add_file(backpage);
-
 read_backing_page:
 	ret = bmapping->a_ops->readpage(NULL, backpage);
 	if (ret < 0)
@@ -510,24 +508,23 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
 					goto nomem;
 			}
 
-			ret = add_to_page_cache(newpage, bmapping,
-						netpage->index, cachefiles_gfp);
+			ret = add_to_page_cache_lru(newpage, bmapping,
+						    netpage->index,
+						    cachefiles_gfp);
 			if (ret == 0)
 				goto installed_new_backing_page;
 			if (ret != -EEXIST)
 				goto nomem;
 		}
 
-		/* we've installed a new backing page, so now we need to add it
-		 * to the LRU list and start it reading */
+		/* we've installed a new backing page, so now we need
+		 * to start it reading */
 	installed_new_backing_page:
 		_debug("- new %p", newpage);
 
 		backpage = newpage;
 		newpage = NULL;
 
-		lru_cache_add_file(backpage);
-
 	reread_backing_page:
 		ret = bmapping->a_ops->readpage(NULL, backpage);
 		if (ret < 0)
@@ -538,8 +535,8 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
 	monitor_backing_page:
 		_debug("- monitor add");
 
-		ret = add_to_page_cache(netpage, op->mapping, netpage->index,
-					cachefiles_gfp);
+		ret = add_to_page_cache_lru(netpage, op->mapping,
+					    netpage->index, cachefiles_gfp);
 		if (ret < 0) {
 			if (ret == -EEXIST) {
 				page_cache_release(netpage);
@@ -549,8 +546,6 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
 			goto nomem;
 		}
 
-		lru_cache_add_file(netpage);
-
 		/* install a monitor */
 		page_cache_get(netpage);
 		monitor->netfs_page = netpage;
@@ -613,8 +608,8 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
 	backing_page_already_uptodate:
 		_debug("- uptodate");
 
-		ret = add_to_page_cache(netpage, op->mapping, netpage->index,
-					cachefiles_gfp);
+		ret = add_to_page_cache_lru(netpage, op->mapping,
+					    netpage->index, cachefiles_gfp);
 		if (ret < 0) {
 			if (ret == -EEXIST) {
 				page_cache_release(netpage);
@@ -631,8 +626,6 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
 
 		fscache_mark_page_cached(op, netpage);
 
-		lru_cache_add_file(netpage);
-
 		/* the netpage is unlocked and marked up to date here */
 		fscache_end_io(op, netpage, 0);
 		page_cache_release(netpage);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 849f6132b327..ab8ad2546c3e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -286,7 +286,7 @@ cifs_destroy_inode(struct inode *inode)
 static void
 cifs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	cifs_fscache_release_inode_cookie(inode);
 }
@@ -1005,7 +1005,7 @@ cifs_init_once(void *inode)
 	init_rwsem(&cifsi->lock_sem);
 }
 
-static int
+static int __init
 cifs_init_inodecache(void)
 {
 	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cf32f0393369..c0f3718b77a8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -513,7 +513,7 @@ struct cifs_mnt_data {
 static inline unsigned int
 get_rfc1002_length(void *buf)
 {
-	return be32_to_cpu(*((__be32 *)buf));
+	return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
 }
 
 static inline void
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 53c15074bb36..216d7e99f921 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2579,31 +2579,19 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
 	struct cifsInodeInfo *cinode = CIFS_I(inode);
 	struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
 	ssize_t rc = -EACCES;
+	loff_t lock_pos = pos;
 
-	BUG_ON(iocb->ki_pos != pos);
-
+	if (file->f_flags & O_APPEND)
+		lock_pos = i_size_read(inode);
 	/*
 	 * We need to hold the sem to be sure nobody modifies lock list
 	 * with a brlock that prevents writing.
 	 */
 	down_read(&cinode->lock_sem);
-	if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs),
+	if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs),
 				     server->vals->exclusive_lock_type, NULL,
-				     CIFS_WRITE_OP)) {
-		mutex_lock(&inode->i_mutex);
-		rc = __generic_file_aio_write(iocb, iov, nr_segs,
-					       &iocb->ki_pos);
-		mutex_unlock(&inode->i_mutex);
-	}
-
-	if (rc > 0) {
-		ssize_t err;
-
-		err = generic_write_sync(file, iocb->ki_pos - rc, rc);
-		if (err < 0)
-			rc = err;
-	}
-
+				     CIFS_WRITE_OP))
+		rc = generic_file_aio_write(iocb, iov, nr_segs, pos);
 	up_read(&cinode->lock_sem);
 	return rc;
 }
@@ -3125,6 +3113,7 @@ cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 static struct vm_operations_struct cifs_file_vm_ops = {
 	.fault = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = cifs_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index b37570952846..18cd5650a5fc 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -270,6 +270,26 @@ cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
 		iov->iov_len = rqst->rq_pagesz;
 }
 
+static unsigned long
+rqst_len(struct smb_rqst *rqst)
+{
+	unsigned int i;
+	struct kvec *iov = rqst->rq_iov;
+	unsigned long buflen = 0;
+
+	/* total up iov array first */
+	for (i = 0; i < rqst->rq_nvec; i++)
+		buflen += iov[i].iov_len;
+
+	/* add in the page array if there is one */
+	if (rqst->rq_npages) {
+		buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
+		buflen += rqst->rq_tailsz;
+	}
+
+	return buflen;
+}
+
 static int
 smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 {
@@ -277,6 +297,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	struct kvec *iov = rqst->rq_iov;
 	int n_vec = rqst->rq_nvec;
 	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
+	unsigned long send_length;
 	unsigned int i;
 	size_t total_len = 0, sent;
 	struct socket *ssocket = server->ssocket;
@@ -285,6 +306,14 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	if (ssocket == NULL)
 		return -ENOTSOCK;
 
+	/* sanity check send length */
+	send_length = rqst_len(rqst);
+	if (send_length != smb_buf_length + 4) {
+		WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
+			send_length, smb_buf_length);
+		return -EIO;
+	}
+
 	cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
 	dump_smb(iov[0].iov_base, iov[0].iov_len);
 
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 506de34a4ef3..62618ec9356c 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -250,7 +250,7 @@ static void coda_put_super(struct super_block *sb)
 
 static void coda_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	coda_cache_clear_inode(inode);
 }
diff --git a/fs/compat.c b/fs/compat.c
index 6af20de2c1a3..800914a1092a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -92,8 +92,8 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filena
 	struct timespec tv[2];
 
 	if  (t) {
-		if (get_compat_timespec(&tv[0], &t[0]) ||
-		    get_compat_timespec(&tv[1], &t[1]))
+		if (compat_get_timespec(&tv[0], &t[0]) ||
+		    compat_get_timespec(&tv[1], &t[1]))
 			return -EFAULT;
 
 		if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
@@ -399,12 +399,28 @@ static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *u
 }
 #endif
 
+static unsigned int
+convert_fcntl_cmd(unsigned int cmd)
+{
+	switch (cmd) {
+	case F_GETLK64:
+		return F_GETLK;
+	case F_SETLK64:
+		return F_SETLK;
+	case F_SETLKW64:
+		return F_SETLKW;
+	}
+
+	return cmd;
+}
+
 asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 		unsigned long arg)
 {
 	mm_segment_t old_fs;
 	struct flock f;
 	long ret;
+	unsigned int conv_cmd;
 
 	switch (cmd) {
 	case F_GETLK:
@@ -441,16 +457,18 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 	case F_GETLK64:
 	case F_SETLK64:
 	case F_SETLKW64:
+	case F_GETLKP:
+	case F_SETLKP:
+	case F_SETLKPW:
 		ret = get_compat_flock64(&f, compat_ptr(arg));
 		if (ret != 0)
 			break;
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
-		ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
-				((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
-				(unsigned long)&f);
+		conv_cmd = convert_fcntl_cmd(cmd);
+		ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
 		set_fs(old_fs);
-		if (cmd == F_GETLK64 && ret == 0) {
+		if ((conv_cmd == F_GETLK || conv_cmd == F_GETLKP) && ret == 0) {
 			/* need to return lock information - see above for commentary */
 			if (f.l_start > COMPAT_LOFF_T_MAX)
 				ret = -EOVERFLOW;
@@ -471,8 +489,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
 		unsigned long arg)
 {
-	if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
+	switch (cmd) {
+	case F_GETLK64:
+	case F_SETLK64:
+	case F_SETLKW64:
+	case F_GETLKP:
+	case F_SETLKP:
+	case F_SETLKPW:
 		return -EINVAL;
+	}
 	return compat_sys_fcntl64(fd, cmd, arg);
 }
 
@@ -512,7 +537,7 @@ compat_sys_io_getevents(aio_context_t ctx_id,
 				nr * sizeof(struct io_event))))
 		goto out;
 	if (timeout) {
-		if (get_compat_timespec(&t, timeout))
+		if (compat_get_timespec(&t, timeout))
 			goto out;
 
 		ut = compat_alloc_user_space(sizeof(*ut));
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 06610cf94d57..a1f801c14fbc 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -195,8 +195,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
 		struct page *page = NULL;
 
 		if (blocknr + i < devsize) {
-			page = read_mapping_page_async(mapping, blocknr + i,
-									NULL);
+			page = read_mapping_page(mapping, blocknr + i, NULL);
 			/* synchronous error? */
 			if (IS_ERR(page))
 				page = NULL;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 9c0444cccbe1..ca4a08f38374 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -358,7 +358,7 @@ exit:
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have.
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @data: a pointer to something that the caller will want to get to later
  *        on.  The inode.i_private pointer will point to this value on
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  * @name: a pointer to a string containing the name of the directory to
  *        create.
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is NULL, then the
  *          directory will be created in the root of the debugfs filesystem.
  *
  * This function creates a directory in debugfs with the given name.
@@ -425,7 +425,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir);
  * @name: a pointer to a string containing the name of the symbolic link to
  *        create.
  * @parent: a pointer to the parent dentry for this symbolic link.  This
- *          should be a directory dentry if set.  If this paramater is NULL,
+ *          should be a directory dentry if set.  If this parameter is NULL,
  *          then the symbolic link will be created in the root of the debugfs
  *          filesystem.
  * @target: a pointer to a string containing the path to the target of the
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 160a5489a939..31ba0935e32e 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -664,7 +664,6 @@ static inline int dio_new_bio(struct dio *dio, struct dio_submit *sdio,
 		goto out;
 	sector = start_sector << (sdio->blkbits - 9);
 	nr_pages = min(sdio->pages_in_io, bio_get_nr_vecs(map_bh->b_bdev));
-	nr_pages = min(nr_pages, BIO_MAX_PAGES);
 	BUG_ON(nr_pages <= 0);
 	dio_bio_alloc(dio, sdio, map_bh->b_bdev, sector, nr_pages);
 	sdio->boundary = 0;
@@ -1194,13 +1193,19 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	}
 
 	/*
-	 * For file extending writes updating i_size before data
-	 * writeouts complete can expose uninitialized blocks. So
-	 * even for AIO, we need to wait for i/o to complete before
-	 * returning in this case.
+	 * For file extending writes updating i_size before data writeouts
+	 * complete can expose uninitialized blocks in dumb filesystems.
+	 * In that case we need to wait for I/O completion even if asked
+	 * for an asynchronous write.
 	 */
-	dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&
-		(end > i_size_read(inode)));
+	if (is_sync_kiocb(iocb))
+		dio->is_async = false;
+	else if (!(dio->flags & DIO_ASYNC_EXTEND) &&
+            (rw & WRITE) && end > i_size_read(inode))
+		dio->is_async = false;
+	else
+		dio->is_async = true;
+
 	dio->inode = inode;
 	dio->rw = rw;
 
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 0e90f0c91b93..dcea1e37a1b7 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -14,6 +14,7 @@
 #include "dlm_internal.h"
 #include "lock.h"
 #include "user.h"
+#include "ast.h"
 
 static uint64_t dlm_cb_seq;
 static DEFINE_SPINLOCK(dlm_cb_seq_spin);
@@ -308,6 +309,6 @@ void dlm_callback_resume(struct dlm_ls *ls)
 	mutex_unlock(&ls->ls_cb_mutex);
 
 	if (count)
-		log_debug(ls, "dlm_callback_resume %d", count);
+		log_rinfo(ls, "dlm_callback_resume %d", count);
 }
 
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c
index 278a75cda446..d975851a7e1e 100644
--- a/fs/dlm/dir.c
+++ b/fs/dlm/dir.c
@@ -68,7 +68,7 @@ int dlm_recover_directory(struct dlm_ls *ls)
 	uint16_t namelen;
 	unsigned int count = 0, count_match = 0, count_bad = 0, count_add = 0;
 
-	log_debug(ls, "dlm_recover_directory");
+	log_rinfo(ls, "dlm_recover_directory");
 
 	if (dlm_no_directory(ls))
 		goto out_status;
@@ -189,7 +189,7 @@ int dlm_recover_directory(struct dlm_ls *ls)
 	error = 0;
 	dlm_set_recover_status(ls, DLM_RS_DIR);
 
-	log_debug(ls, "dlm_recover_directory %u in %u new",
+	log_rinfo(ls, "dlm_recover_directory %u in %u new",
 		  count, count_add);
  out_free:
 	kfree(last_name);
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index e7665c31f7b1..5eff6ea3e27f 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -65,6 +65,8 @@ struct dlm_mhandle;
 	printk(KERN_ERR "dlm: "fmt"\n" , ##args)
 #define log_error(ls, fmt, args...) \
 	printk(KERN_ERR "dlm: %s: " fmt "\n", (ls)->ls_name , ##args)
+#define log_rinfo(ls, fmt, args...) \
+	printk(KERN_INFO "dlm: %s: " fmt "\n", (ls)->ls_name , ##args);
 
 #define log_debug(ls, fmt, args...) \
 do { \
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index e223a911a834..83f3d5520307 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -687,6 +687,7 @@ static int find_rsb_dir(struct dlm_ls *ls, char *name, int len,
 		log_error(ls, "find_rsb new from_other %d dir %d our %d %s",
 			  from_nodeid, dir_nodeid, our_nodeid, r->res_name);
 		dlm_free_rsb(r);
+		r = NULL;
 		error = -ENOTBLK;
 		goto out_unlock;
 	}
@@ -5462,7 +5463,7 @@ void dlm_recover_purge(struct dlm_ls *ls)
 	up_write(&ls->ls_root_sem);
 
 	if (lkb_count)
-		log_debug(ls, "dlm_recover_purge %u locks for %u nodes",
+		log_rinfo(ls, "dlm_recover_purge %u locks for %u nodes",
 			  lkb_count, nodes_count);
 }
 
@@ -5536,7 +5537,7 @@ void dlm_recover_grant(struct dlm_ls *ls)
 	}
 
 	if (lkb_count)
-		log_debug(ls, "dlm_recover_grant %u locks on %u resources",
+		log_rinfo(ls, "dlm_recover_grant %u locks on %u resources",
 			  lkb_count, rsb_count);
 }
 
@@ -5695,7 +5696,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 	put_rsb(r);
  out:
 	if (error && error != -EEXIST)
-		log_debug(ls, "dlm_recover_master_copy remote %d %x error %d",
+		log_rinfo(ls, "dlm_recover_master_copy remote %d %x error %d",
 			  from_nodeid, remid, error);
 	rl->rl_result = cpu_to_le32(error);
 	return error;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index d5abafd56a6d..04d6398c1f1c 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -190,7 +190,7 @@ static int do_uevent(struct dlm_ls *ls, int in)
 	else
 		kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
 
-	log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
+	log_rinfo(ls, "%s the lockspace group...", in ? "joining" : "leaving");
 
 	/* dlm_controld will see the uevent, do the necessary group management
 	   and then write to sysfs to wake us */
@@ -198,7 +198,7 @@ static int do_uevent(struct dlm_ls *ls, int in)
 	error = wait_event_interruptible(ls->ls_uevent_wait,
 			test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
 
-	log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
+	log_rinfo(ls, "group event done %d %d", error, ls->ls_uevent_result);
 
 	if (error)
 		goto out;
@@ -640,7 +640,7 @@ static int new_lockspace(const char *name, const char *cluster,
 
 	dlm_create_debug_file(ls);
 
-	log_debug(ls, "join complete");
+	log_rinfo(ls, "join complete");
 	*lockspace = ls;
 	return 0;
 
@@ -835,7 +835,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
 	dlm_clear_members(ls);
 	dlm_clear_members_gone(ls);
 	kfree(ls->ls_node_array);
-	log_debug(ls, "release_lockspace final free");
+	log_rinfo(ls, "release_lockspace final free");
 	kobject_put(&ls->ls_kobj);
 	/* The ls structure will be freed when the kobject is done with */
 
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 476557b54921..9c47f1c14a8b 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -60,18 +60,15 @@ void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc)
 
 #define SLOT_DEBUG_LINE 128
 
-static void log_debug_slots(struct dlm_ls *ls, uint32_t gen, int num_slots,
-			    struct rcom_slot *ro0, struct dlm_slot *array,
-			    int array_size)
+static void log_slots(struct dlm_ls *ls, uint32_t gen, int num_slots,
+		      struct rcom_slot *ro0, struct dlm_slot *array,
+		      int array_size)
 {
 	char line[SLOT_DEBUG_LINE];
 	int len = SLOT_DEBUG_LINE - 1;
 	int pos = 0;
 	int ret, i;
 
-	if (!dlm_config.ci_log_debug)
-		return;
-
 	memset(line, 0, sizeof(line));
 
 	if (array) {
@@ -95,7 +92,7 @@ static void log_debug_slots(struct dlm_ls *ls, uint32_t gen, int num_slots,
 		}
 	}
 
-	log_debug(ls, "generation %u slots %d%s", gen, num_slots, line);
+	log_rinfo(ls, "generation %u slots %d%s", gen, num_slots, line);
 }
 
 int dlm_slots_copy_in(struct dlm_ls *ls)
@@ -129,7 +126,7 @@ int dlm_slots_copy_in(struct dlm_ls *ls)
 		ro->ro_slot = le16_to_cpu(ro->ro_slot);
 	}
 
-	log_debug_slots(ls, gen, num_slots, ro0, NULL, 0);
+	log_slots(ls, gen, num_slots, ro0, NULL, 0);
 
 	list_for_each_entry(memb, &ls->ls_nodes, list) {
 		for (i = 0, ro = ro0; i < num_slots; i++, ro++) {
@@ -274,7 +271,7 @@ int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size,
 
 	gen++;
 
-	log_debug_slots(ls, gen, num, NULL, array, array_size);
+	log_slots(ls, gen, num, NULL, array, array_size);
 
 	max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) -
 		     sizeof(struct rcom_config)) / sizeof(struct rcom_slot);
@@ -447,7 +444,7 @@ static int ping_members(struct dlm_ls *ls)
 			break;
 	}
 	if (error)
-		log_debug(ls, "ping_members aborted %d last nodeid %d",
+		log_rinfo(ls, "ping_members aborted %d last nodeid %d",
 			  error, ls->ls_recover_nodeid);
 	return error;
 }
@@ -539,7 +536,7 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 	   count as a negative change so the "neg" recovery steps will happen */
 
 	list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
-		log_debug(ls, "prev removed member %d", memb->nodeid);
+		log_rinfo(ls, "prev removed member %d", memb->nodeid);
 		neg++;
 	}
 
@@ -551,10 +548,10 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 			continue;
 
 		if (!node) {
-			log_debug(ls, "remove member %d", memb->nodeid);
+			log_rinfo(ls, "remove member %d", memb->nodeid);
 		} else {
 			/* removed and re-added */
-			log_debug(ls, "remove member %d comm_seq %u %u",
+			log_rinfo(ls, "remove member %d comm_seq %u %u",
 				  memb->nodeid, memb->comm_seq, node->comm_seq);
 		}
 
@@ -571,7 +568,7 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 		if (dlm_is_member(ls, node->nodeid))
 			continue;
 		dlm_add_member(ls, node);
-		log_debug(ls, "add member %d", node->nodeid);
+		log_rinfo(ls, "add member %d", node->nodeid);
 	}
 
 	list_for_each_entry(memb, &ls->ls_nodes, list) {
@@ -591,7 +588,7 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 		complete(&ls->ls_members_done);
 	}
 
-	log_debug(ls, "dlm_recover_members %d nodes", ls->ls_num_nodes);
+	log_rinfo(ls, "dlm_recover_members %d nodes", ls->ls_num_nodes);
 	return error;
 }
 
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index a6bc63f6e31b..eaea789bf97d 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -526,7 +526,7 @@ int dlm_recover_masters(struct dlm_ls *ls)
 	int nodir = dlm_no_directory(ls);
 	int error;
 
-	log_debug(ls, "dlm_recover_masters");
+	log_rinfo(ls, "dlm_recover_masters");
 
 	down_read(&ls->ls_root_sem);
 	list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
@@ -552,7 +552,7 @@ int dlm_recover_masters(struct dlm_ls *ls)
 	}
 	up_read(&ls->ls_root_sem);
 
-	log_debug(ls, "dlm_recover_masters %u of %u", count, total);
+	log_rinfo(ls, "dlm_recover_masters %u of %u", count, total);
 
 	error = dlm_wait_function(ls, &recover_idr_empty);
  out:
@@ -685,7 +685,7 @@ int dlm_recover_locks(struct dlm_ls *ls)
 	}
 	up_read(&ls->ls_root_sem);
 
-	log_debug(ls, "dlm_recover_locks %d out", count);
+	log_rinfo(ls, "dlm_recover_locks %d out", count);
 
 	error = dlm_wait_function(ls, &recover_list_empty);
  out:
@@ -883,7 +883,7 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
 	up_read(&ls->ls_root_sem);
 
 	if (count)
-		log_debug(ls, "dlm_recover_rsbs %d done", count);
+		log_rinfo(ls, "dlm_recover_rsbs %d done", count);
 }
 
 /* Create a single list of all root rsb's to be used during recovery */
@@ -950,6 +950,6 @@ void dlm_clear_toss(struct dlm_ls *ls)
 	}
 
 	if (count)
-		log_debug(ls, "dlm_clear_toss %u done", count);
+		log_rinfo(ls, "dlm_clear_toss %u done", count);
 }
 
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 32f9f8926ec3..6859b4bf971e 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -55,7 +55,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 	unsigned long start;
 	int error, neg = 0;
 
-	log_debug(ls, "dlm_recover %llu", (unsigned long long)rv->seq);
+	log_rinfo(ls, "dlm_recover %llu", (unsigned long long)rv->seq);
 
 	mutex_lock(&ls->ls_recoverd_active);
 
@@ -76,7 +76,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = dlm_recover_members(ls, rv, &neg);
 	if (error) {
-		log_debug(ls, "dlm_recover_members error %d", error);
+		log_rinfo(ls, "dlm_recover_members error %d", error);
 		goto fail;
 	}
 
@@ -90,7 +90,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = dlm_recover_members_wait(ls);
 	if (error) {
-		log_debug(ls, "dlm_recover_members_wait error %d", error);
+		log_rinfo(ls, "dlm_recover_members_wait error %d", error);
 		goto fail;
 	}
 
@@ -103,7 +103,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = dlm_recover_directory(ls);
 	if (error) {
-		log_debug(ls, "dlm_recover_directory error %d", error);
+		log_rinfo(ls, "dlm_recover_directory error %d", error);
 		goto fail;
 	}
 
@@ -111,11 +111,11 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = dlm_recover_directory_wait(ls);
 	if (error) {
-		log_debug(ls, "dlm_recover_directory_wait error %d", error);
+		log_rinfo(ls, "dlm_recover_directory_wait error %d", error);
 		goto fail;
 	}
 
-	log_debug(ls, "dlm_recover_directory %u out %u messages",
+	log_rinfo(ls, "dlm_recover_directory %u out %u messages",
 		  ls->ls_recover_dir_sent_res, ls->ls_recover_dir_sent_msg);
 
 	/*
@@ -144,7 +144,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 		error = dlm_recover_masters(ls);
 		if (error) {
-			log_debug(ls, "dlm_recover_masters error %d", error);
+			log_rinfo(ls, "dlm_recover_masters error %d", error);
 			goto fail;
 		}
 
@@ -154,7 +154,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 		error = dlm_recover_locks(ls);
 		if (error) {
-			log_debug(ls, "dlm_recover_locks error %d", error);
+			log_rinfo(ls, "dlm_recover_locks error %d", error);
 			goto fail;
 		}
 
@@ -162,11 +162,11 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 		error = dlm_recover_locks_wait(ls);
 		if (error) {
-			log_debug(ls, "dlm_recover_locks_wait error %d", error);
+			log_rinfo(ls, "dlm_recover_locks_wait error %d", error);
 			goto fail;
 		}
 
-		log_debug(ls, "dlm_recover_locks %u in",
+		log_rinfo(ls, "dlm_recover_locks %u in",
 			  ls->ls_recover_locks_in);
 
 		/*
@@ -186,7 +186,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 		error = dlm_recover_locks_wait(ls);
 		if (error) {
-			log_debug(ls, "dlm_recover_locks_wait error %d", error);
+			log_rinfo(ls, "dlm_recover_locks_wait error %d", error);
 			goto fail;
 		}
 	}
@@ -205,7 +205,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = dlm_recover_done_wait(ls);
 	if (error) {
-		log_debug(ls, "dlm_recover_done_wait error %d", error);
+		log_rinfo(ls, "dlm_recover_done_wait error %d", error);
 		goto fail;
 	}
 
@@ -217,25 +217,25 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	error = enable_locking(ls, rv->seq);
 	if (error) {
-		log_debug(ls, "enable_locking error %d", error);
+		log_rinfo(ls, "enable_locking error %d", error);
 		goto fail;
 	}
 
 	error = dlm_process_requestqueue(ls);
 	if (error) {
-		log_debug(ls, "dlm_process_requestqueue error %d", error);
+		log_rinfo(ls, "dlm_process_requestqueue error %d", error);
 		goto fail;
 	}
 
 	error = dlm_recover_waiters_post(ls);
 	if (error) {
-		log_debug(ls, "dlm_recover_waiters_post error %d", error);
+		log_rinfo(ls, "dlm_recover_waiters_post error %d", error);
 		goto fail;
 	}
 
 	dlm_recover_grant(ls);
 
-	log_debug(ls, "dlm_recover %llu generation %u done: %u ms",
+	log_rinfo(ls, "dlm_recover %llu generation %u done: %u ms",
 		  (unsigned long long)rv->seq, ls->ls_generation,
 		  jiffies_to_msecs(jiffies - start));
 	mutex_unlock(&ls->ls_recoverd_active);
@@ -245,7 +245,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
  fail:
 	dlm_release_root_list(ls);
-	log_debug(ls, "dlm_recover %llu error %d",
+	log_rinfo(ls, "dlm_recover %llu error %d",
 		  (unsigned long long)rv->seq, error);
 	mutex_unlock(&ls->ls_recoverd_active);
 	return error;
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 9fd702f5bfb2..9280202e488c 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -59,10 +59,22 @@ int drop_caches_sysctl_handler(ctl_table *table, int write,
 	if (ret)
 		return ret;
 	if (write) {
-		if (sysctl_drop_caches & 1)
+		static int stfu;
+
+		if (sysctl_drop_caches & 1) {
 			iterate_supers(drop_pagecache_sb, NULL);
-		if (sysctl_drop_caches & 2)
+			count_vm_event(DROP_PAGECACHE);
+		}
+		if (sysctl_drop_caches & 2) {
 			drop_slab();
+			count_vm_event(DROP_SLAB);
+		}
+		if (!stfu) {
+			pr_info("%s (%d): drop_caches: %d\n",
+				current->comm, task_pid_nr(current),
+				sysctl_drop_caches);
+		}
+		stfu |= sysctl_drop_caches & 4;
 	}
 	return 0;
 }
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 b167ca48b8ee..f234b0037f60 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/ecryptfs/super.c b/fs/ecryptfs/super.c
index e879cf8ff0b1..afa1b81c3418 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -132,7 +132,7 @@ static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  */
 static void ecryptfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	iput(ecryptfs_inode_to_lower(inode));
 }
diff --git a/fs/efs/super.c b/fs/efs/super.c
index 50215bbd6463..f8def1acf08c 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -91,7 +91,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	efs_inode_cachep = kmem_cache_create("efs_inode_cache",
 				sizeof(struct efs_inode_info),
diff --git a/fs/exec.c b/fs/exec.c
index 3d78fccdd723..48eb03952bae 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -97,6 +97,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
 	module_put(fmt->module);
 }
 
+#ifdef CONFIG_USELIB
 /*
  * Note that a shared library must be both readable and executable due to
  * security reasons.
@@ -156,6 +157,7 @@ exit:
 out:
   	return error;
 }
+#endif /* #ifdef CONFIG_USELIB */
 
 #ifdef CONFIG_MMU
 /*
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index ee4317faccb1..d1c244d67667 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -1486,7 +1486,7 @@ void exofs_evict_inode(struct inode *inode)
 	struct ore_io_state *ios;
 	int ret;
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	/* TODO: should do better here */
 	if (inode->i_nlink || is_bad_inode(inode))
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 94ed36849b71..b1d2a4675d42 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -78,7 +78,7 @@ void ext2_evict_inode(struct inode * inode)
 		dquot_drop(inode);
 	}
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	if (want_delete) {
 		sb_start_intwrite(inode->i_sb);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 384b6ebb655f..efce2bbfb5e5 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -228,7 +228,7 @@ void ext3_evict_inode (struct inode *inode)
 		log_wait_commit(journal, commit_tid);
 		filemap_write_and_wait(&inode->i_data);
 	}
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	ext3_discard_reservation(inode);
 	rsv = ei->i_block_alloc_info;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 74bc2d549c58..ef4b535e0a02 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1691,7 +1691,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
 	 * 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_uninitialized(ex1) != ext4_ext_is_uninitialized(ex2))
 		return 0;
 
 	ext1_ee_len = ext4_ext_get_actual_len(ex1);
@@ -1708,6 +1708,11 @@ 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) &&
+	    (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)))
+		return 0;
 #ifdef AGGRESSIVE_TEST
 	if (ext1_ee_len >= 4)
 		return 0;
@@ -1731,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;
+	int merge_done = 0, uninit;
 
 	depth = ext_depth(inode);
 	BUG_ON(path[depth].p_hdr == NULL);
@@ -1741,8 +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);
 		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 (ex + 1 < EXT_LAST_EXTENT(eh)) {
 			len = (EXT_LAST_EXTENT(eh) - ex - 1)
@@ -1896,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;
+	int mb_flags = 0, uninit;
 
 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
@@ -1946,9 +1954,11 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 						  path + depth);
 			if (err)
 				return err;
-
+			uninit = ext4_ext_is_uninitialized(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);
 			eh = path[depth].p_hdr;
 			nearex = ex;
 			goto merge;
@@ -1971,10 +1981,13 @@ prepend:
 			if (err)
 				return err;
 
+			uninit = ext4_ext_is_uninitialized(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);
 			eh = path[depth].p_hdr;
 			nearex = ex;
 			goto merge;
@@ -4128,7 +4141,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	struct ext4_extent newex, *ex, *ex2;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	ext4_fsblk_t newblock = 0;
-	int free_on_err = 0, err = 0, depth;
+	int free_on_err = 0, err = 0, depth, ret;
 	unsigned int allocated = 0, offset = 0;
 	unsigned int allocated_clusters = 0;
 	struct ext4_allocation_request ar;
@@ -4189,9 +4202,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			if (!ext4_ext_is_uninitialized(ex))
 				goto out;
 
-			allocated = ext4_ext_handle_uninitialized_extents(
+			ret = ext4_ext_handle_uninitialized_extents(
 				handle, inode, map, path, flags,
 				allocated, newblock);
+			if (ret < 0)
+				err = ret;
+			else
+				allocated = ret;
 			goto out3;
 		}
 	}
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 3981ff783950..0a014a7194b2 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -184,7 +184,7 @@ static void ext4_es_print_tree(struct inode *inode)
 	while (node) {
 		struct extent_status *es;
 		es = rb_entry(node, struct extent_status, rb_node);
-		printk(KERN_DEBUG " [%u/%u) %llu %llx",
+		printk(KERN_DEBUG " [%u/%u) %llu %x",
 		       es->es_lblk, es->es_len,
 		       ext4_es_pblock(es), ext4_es_status(es));
 		node = rb_next(node);
@@ -445,8 +445,8 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
 				pr_warn("ES insert assertion failed for "
 					"inode: %lu we can find an extent "
 					"at block [%d/%d/%llu/%c], but we "
-					"want to add an delayed/hole extent "
-					"[%d/%d/%llu/%llx]\n",
+					"want to add a delayed/hole extent "
+					"[%d/%d/%llu/%x]\n",
 					inode->i_ino, ee_block, ee_len,
 					ee_start, ee_status ? 'u' : 'w',
 					es->es_lblk, es->es_len,
@@ -486,8 +486,8 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
 		if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) {
 			pr_warn("ES insert assertion failed for inode: %lu "
 				"can't find an extent at block %d but we want "
-				"to add an written/unwritten extent "
-				"[%d/%d/%llu/%llx]\n", inode->i_ino,
+				"to add a written/unwritten extent "
+				"[%d/%d/%llu/%x]\n", inode->i_ino,
 				es->es_lblk, es->es_lblk, es->es_len,
 				ext4_es_pblock(es), ext4_es_status(es));
 		}
@@ -524,7 +524,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
 			 */
 			pr_warn("ES insert assertion failed for inode: %lu "
 				"We can find blocks but we want to add a "
-				"delayed/hole extent [%d/%d/%llu/%llx]\n",
+				"delayed/hole extent [%d/%d/%llu/%x]\n",
 				inode->i_ino, es->es_lblk, es->es_len,
 				ext4_es_pblock(es), ext4_es_status(es));
 			return;
@@ -554,7 +554,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
 		if (ext4_es_is_written(es)) {
 			pr_warn("ES insert assertion failed for inode: %lu "
 				"We can't find the block but we want to add "
-				"an written extent [%d/%d/%llu/%llx]\n",
+				"a written extent [%d/%d/%llu/%x]\n",
 				inode->i_ino, es->es_lblk, es->es_len,
 				ext4_es_pblock(es), ext4_es_status(es));
 			return;
@@ -658,8 +658,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 
 	newes.es_lblk = lblk;
 	newes.es_len = len;
-	ext4_es_store_pblock(&newes, pblk);
-	ext4_es_store_status(&newes, status);
+	ext4_es_store_pblock_status(&newes, pblk, status);
 	trace_ext4_es_insert_extent(inode, &newes);
 
 	ext4_es_insert_extent_check(inode, &newes);
@@ -699,8 +698,7 @@ void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
 
 	newes.es_lblk = lblk;
 	newes.es_len = len;
-	ext4_es_store_pblock(&newes, pblk);
-	ext4_es_store_status(&newes, status);
+	ext4_es_store_pblock_status(&newes, pblk, status);
 	trace_ext4_es_cache_extent(inode, &newes);
 
 	if (!len)
@@ -812,13 +810,13 @@ retry:
 
 			newes.es_lblk = end + 1;
 			newes.es_len = len2;
+			block = 0x7FDEADBEEF;
 			if (ext4_es_is_written(&orig_es) ||
-			    ext4_es_is_unwritten(&orig_es)) {
+			    ext4_es_is_unwritten(&orig_es))
 				block = ext4_es_pblock(&orig_es) +
 					orig_es.es_len - len2;
-				ext4_es_store_pblock(&newes, block);
-			}
-			ext4_es_store_status(&newes, ext4_es_status(&orig_es));
+			ext4_es_store_pblock_status(&newes, block,
+						    ext4_es_status(&orig_es));
 			err = __es_insert_extent(inode, &newes);
 			if (err) {
 				es->es_lblk = orig_es.es_lblk;
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index 167f4ab8ecc3..f1b62a419920 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -129,6 +129,15 @@ static inline void ext4_es_store_status(struct extent_status *es,
 		       (es->es_pblk & ~ES_MASK));
 }
 
+static inline void ext4_es_store_pblock_status(struct extent_status *es,
+					       ext4_fsblk_t pb,
+					       unsigned int status)
+{
+	es->es_pblk = (((ext4_fsblk_t)
+			(status & EXTENT_STATUS_FLAGS) << ES_SHIFT) |
+		       (pb & ~ES_MASK));
+}
+
 extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
 extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
 extern void ext4_es_lru_add(struct inode *inode);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 1a5073959f32..4e508fc83dcf 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -153,7 +153,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
 		ssize_t err;
 
 		err = generic_write_sync(file, iocb->ki_pos - ret, ret);
-		if (err < 0 && ret > 0)
+		if (err < 0)
 			ret = err;
 	}
 	blk_finish_plug(&plug);
@@ -200,6 +200,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
 
 static const struct vm_operations_struct ext4_file_vm_ops = {
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite   = ext4_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 6e39895a91b8..7b614b3ab437 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -214,7 +214,7 @@ void ext4_evict_inode(struct inode *inode)
 			jbd2_complete_transaction(journal, commit_tid);
 			filemap_write_and_wait(&inode->i_data);
 		}
-		truncate_inode_pages(&inode->i_data, 0);
+		truncate_inode_pages_final(&inode->i_data);
 
 		WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count));
 		goto no_delete;
@@ -225,7 +225,7 @@ void ext4_evict_inode(struct inode *inode)
 
 	if (ext4_should_order_data(inode))
 		ext4_begin_ordered_truncate(inode, 0);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count));
 	if (is_bad_inode(inode))
@@ -514,6 +514,12 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 		  "logical block %lu\n", inode->i_ino, flags, map->m_len,
 		  (unsigned long) map->m_lblk);
 
+	/*
+	 * ext4_map_blocks returns an int, and m_len is an unsigned int
+	 */
+	if (unlikely(map->m_len > INT_MAX))
+		map->m_len = INT_MAX;
+
 	/* Lookup extent status tree firstly */
 	if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
 		ext4_es_lru_add(inode);
@@ -3608,6 +3614,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 	up_write(&EXT4_I(inode)->i_data_sem);
 	if (IS_SYNC(inode))
 		ext4_handle_sync(handle);
+
+	/* Now release the pages again to reduce race window */
+	if (last_block_offset > first_block_offset)
+		truncate_pagecache_range(inode, first_block_offset,
+					 last_block_offset);
+
 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 	ext4_mark_inode_dirty(handle, inode);
 out_stop:
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index a2a837f00407..0f2252ec274d 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -104,21 +104,15 @@ static long swap_inode_boot_loader(struct super_block *sb,
 	struct ext4_inode_info *ei_bl;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) {
-		err = -EINVAL;
-		goto swap_boot_out;
-	}
+	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
+		return -EINVAL;
 
-	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) {
-		err = -EPERM;
-		goto swap_boot_out;
-	}
+	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
+		return -EPERM;
 
 	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
-	if (IS_ERR(inode_bl)) {
-		err = PTR_ERR(inode_bl);
-		goto swap_boot_out;
-	}
+	if (IS_ERR(inode_bl))
+		return PTR_ERR(inode_bl);
 	ei_bl = EXT4_I(inode_bl);
 
 	filemap_flush(inode->i_mapping);
@@ -193,20 +187,14 @@ static long swap_inode_boot_loader(struct super_block *sb,
 			ext4_mark_inode_dirty(handle, inode);
 		}
 	}
-
 	ext4_journal_stop(handle);
-
 	ext4_double_up_write_data_sem(inode, inode_bl);
 
 journal_err_out:
 	ext4_inode_resume_unlocked_dio(inode);
 	ext4_inode_resume_unlocked_dio(inode_bl);
-
 	unlock_two_nondirectories(inode, inode_bl);
-
 	iput(inode_bl);
-
-swap_boot_out:
 	return err;
 }
 
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 04a5c7504be9..a888cac76e9c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1808,6 +1808,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
 	ext4_lock_group(ac->ac_sb, group);
 	max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
 			     ac->ac_g_ex.fe_len, &ex);
+	ex.fe_logical = 0xDEADFA11; /* debug value */
 
 	if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
 		ext4_fsblk_t start;
@@ -1936,7 +1937,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
 			 */
 			break;
 		}
-
+		ex.fe_logical = 0xDEADC0DE; /* debug value */
 		ext4_mb_measure_extent(ac, &ex, e4b);
 
 		i += ex.fe_len;
@@ -1977,6 +1978,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
 			max = mb_find_extent(e4b, i, sbi->s_stripe, &ex);
 			if (max >= sbi->s_stripe) {
 				ac->ac_found++;
+				ex.fe_logical = 0xDEADF00D; /* debug value */
 				ac->ac_b_ex = ex;
 				ext4_mb_use_best_found(ac, e4b);
 				break;
@@ -4006,8 +4008,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
 			(unsigned long)ac->ac_b_ex.fe_len,
 			(unsigned long)ac->ac_b_ex.fe_logical,
 			(int)ac->ac_criteria);
-	ext4_msg(ac->ac_sb, KERN_ERR, "%lu scanned, %d found",
-		 ac->ac_ex_scanned, ac->ac_found);
+	ext4_msg(ac->ac_sb, KERN_ERR, "%d found", ac->ac_found);
 	ext4_msg(ac->ac_sb, KERN_ERR, "groups: ");
 	ngroups = ext4_get_groups_count(sb);
 	for (i = 0; i < ngroups; i++) {
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 08481ee84cd5..d634e183b4d4 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -48,7 +48,7 @@ extern ushort ext4_mballoc_debug;
 		}							\
 	} while (0)
 #else
-#define mb_debug(n, fmt, a...)
+#define mb_debug(n, fmt, a...)		no_printk(fmt, ## a)
 #endif
 
 #define EXT4_MB_HISTORY_ALLOC		1	/* allocation */
@@ -175,8 +175,6 @@ struct ext4_allocation_context {
 	/* copy of the best found extent taken before preallocation efforts */
 	struct ext4_free_extent ac_f_ex;
 
-	/* number of iterations done. we have to track to limit searching */
-	unsigned long ac_ex_scanned;
 	__u16 ac_groups_scanned;
 	__u16 ac_found;
 	__u16 ac_tail;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 773b503bd18c..f39a88abe32c 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -861,8 +861,7 @@ mext_page_mkuptodate(struct page *page, unsigned from, unsigned to)
 			}
 			if (!buffer_mapped(bh)) {
 				zero_user(page, block_start, blocksize);
-				if (!err)
-					set_buffer_uptodate(bh);
+				set_buffer_uptodate(bh);
 				continue;
 			}
 		}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 710fed2377d4..f5c13b8e1ebd 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -940,7 +940,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
 					     sizeof(struct ext4_inode_info),
@@ -3854,16 +3854,34 @@ 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
+	 */
+	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;
@@ -3901,14 +3919,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
@@ -4090,21 +4100,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;
 	}
 
@@ -4181,11 +4183,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:
@@ -4209,11 +4208,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 e175e94116ac..185066f475f1 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -567,12 +567,13 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
 				    size_t *min_offs, void *base, int *total)
 {
 	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
-		*total += EXT4_XATTR_LEN(last->e_name_len);
 		if (!last->e_value_block && last->e_value_size) {
 			size_t offs = le16_to_cpu(last->e_value_offs);
 			if (offs < *min_offs)
 				*min_offs = offs;
 		}
+		if (total)
+			*total += EXT4_XATTR_LEN(last->e_name_len);
 	}
 	return (*min_offs - ((void *)last - base) - sizeof(__u32));
 }
@@ -1228,7 +1229,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
 	struct ext4_xattr_block_find *bs = NULL;
 	char *buffer = NULL, *b_entry_name = NULL;
 	size_t min_offs, free;
-	int total_ino, total_blk;
+	int total_ino;
 	void *base, *start, *end;
 	int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
 	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
@@ -1286,8 +1287,7 @@ retry:
 		first = BFIRST(bh);
 		end = bh->b_data + bh->b_size;
 		min_offs = end - base;
-		free = ext4_xattr_free_space(first, &min_offs, base,
-					     &total_blk);
+		free = ext4_xattr_free_space(first, &min_offs, base, NULL);
 		if (free < new_extra_isize) {
 			if (!tried_min_extra_isize && s_min_extra_isize) {
 				tried_min_extra_isize++;
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 293d0486a40f..f069249011b2 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -75,23 +75,102 @@ out:
 	return page;
 }
 
+inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type)
+{
+	switch (type) {
+	case META_NAT:
+		return NM_I(sbi)->max_nid / NAT_ENTRY_PER_BLOCK;
+	case META_SIT:
+		return SIT_BLK_CNT(sbi);
+	case META_SSA:
+	case META_CP:
+		return 0;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Readahead CP/NAT/SIT/SSA pages
+ */
+int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type)
+{
+	block_t prev_blk_addr = 0;
+	struct page *page;
+	int blkno = start;
+	int max_blks = get_max_meta_blks(sbi, type);
+
+	struct f2fs_io_info fio = {
+		.type = META,
+		.rw = READ_SYNC | REQ_META | REQ_PRIO
+	};
+
+	for (; nrpages-- > 0; blkno++) {
+		block_t blk_addr;
+
+		switch (type) {
+		case META_NAT:
+			/* get nat block addr */
+			if (unlikely(blkno >= max_blks))
+				blkno = 0;
+			blk_addr = current_nat_addr(sbi,
+					blkno * NAT_ENTRY_PER_BLOCK);
+			break;
+		case META_SIT:
+			/* get sit block addr */
+			if (unlikely(blkno >= max_blks))
+				goto out;
+			blk_addr = current_sit_addr(sbi,
+					blkno * SIT_ENTRY_PER_BLOCK);
+			if (blkno != start && prev_blk_addr + 1 != blk_addr)
+				goto out;
+			prev_blk_addr = blk_addr;
+			break;
+		case META_SSA:
+		case META_CP:
+			/* get ssa/cp block addr */
+			blk_addr = blkno;
+			break;
+		default:
+			BUG();
+		}
+
+		page = grab_cache_page(META_MAPPING(sbi), blk_addr);
+		if (!page)
+			continue;
+		if (PageUptodate(page)) {
+			mark_page_accessed(page);
+			f2fs_put_page(page, 1);
+			continue;
+		}
+
+		f2fs_submit_page_mbio(sbi, page, blk_addr, &fio);
+		mark_page_accessed(page);
+		f2fs_put_page(page, 0);
+	}
+out:
+	f2fs_submit_merged_bio(sbi, META, READ);
+	return blkno - start;
+}
+
 static int f2fs_write_meta_page(struct page *page,
 				struct writeback_control *wbc)
 {
 	struct inode *inode = page->mapping->host;
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
-	/* Should not write any meta pages, if any IO error was occurred */
-	if (unlikely(sbi->por_doing ||
-			is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+	if (unlikely(sbi->por_doing))
 		goto redirty_out;
-
 	if (wbc->for_reclaim)
 		goto redirty_out;
 
-	wait_on_page_writeback(page);
+	/* Should not write any meta pages, if any IO error was occurred */
+	if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+		goto no_write;
 
+	wait_on_page_writeback(page);
 	write_meta_page(sbi, page);
+no_write:
 	dec_page_count(sbi, F2FS_DIRTY_META);
 	unlock_page(page);
 	return 0;
@@ -99,6 +178,7 @@ static int f2fs_write_meta_page(struct page *page,
 redirty_out:
 	dec_page_count(sbi, F2FS_DIRTY_META);
 	wbc->pages_skipped++;
+	account_page_redirty(page);
 	set_page_dirty(page);
 	return AOP_WRITEPAGE_ACTIVATE;
 }
@@ -148,10 +228,22 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
 
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
+
 			lock_page(page);
-			f2fs_bug_on(page->mapping != mapping);
-			f2fs_bug_on(!PageDirty(page));
-			clear_page_dirty_for_io(page);
+
+			if (unlikely(page->mapping != mapping)) {
+continue_unlock:
+				unlock_page(page);
+				continue;
+			}
+			if (!PageDirty(page)) {
+				/* someone wrote it for us */
+				goto continue_unlock;
+			}
+
+			if (!clear_page_dirty_for_io(page))
+				goto continue_unlock;
+
 			if (f2fs_write_meta_page(page, &wbc)) {
 				unlock_page(page);
 				break;
@@ -285,6 +377,8 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi)
 	start_blk = __start_cp_addr(sbi) + 1;
 	orphan_blkaddr = __start_sum_addr(sbi) - 1;
 
+	ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP);
+
 	for (i = 0; i < orphan_blkaddr; i++) {
 		struct page *page = get_meta_page(sbi, start_blk + i);
 		struct f2fs_orphan_block *orphan_blk;
@@ -495,7 +589,6 @@ void set_dirty_dir_page(struct inode *inode, struct page *page)
 	if (__add_dirty_inode(inode, new))
 		kmem_cache_free(inode_entry_slab, new);
 
-	inc_page_count(sbi, F2FS_DIRTY_DENTS);
 	inode_inc_dirty_dents(inode);
 	SetPagePrivate(page);
 	spin_unlock(&sbi->dir_inode_lock);
@@ -824,6 +917,7 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	unblock_operations(sbi);
 	mutex_unlock(&sbi->cp_mutex);
 
+	stat_inc_cp_count(sbi->stat_info);
 	trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint");
 }
 
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 2261ccdd0b5f..101b4cd4170d 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -45,7 +45,7 @@ static void f2fs_read_end_io(struct bio *bio, int err)
 
 static void f2fs_write_end_io(struct bio *bio, int err)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(bio->bi_io_vec->bv_page->mapping->host->i_sb);
+	struct f2fs_sb_info *sbi = bio->bi_private;
 	struct bio_vec *bvec;
 	int i;
 
@@ -55,15 +55,16 @@ static void f2fs_write_end_io(struct bio *bio, int err)
 		if (unlikely(err)) {
 			SetPageError(page);
 			set_bit(AS_EIO, &page->mapping->flags);
-			set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
-			sbi->sb->s_flags |= MS_RDONLY;
+			f2fs_stop_checkpoint(sbi);
 		}
 		end_page_writeback(page);
 		dec_page_count(sbi, F2FS_WRITEBACK);
 	}
 
-	if (bio->bi_private)
-		complete(bio->bi_private);
+	if (sbi->wait_io) {
+		complete(sbi->wait_io);
+		sbi->wait_io = NULL;
+	}
 
 	if (!get_pages(sbi, F2FS_WRITEBACK) &&
 			!list_empty(&sbi->cp_wait.task_list))
@@ -86,6 +87,7 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
 	bio->bi_bdev = sbi->sb->s_bdev;
 	bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
 	bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io;
+	bio->bi_private = sbi;
 
 	return bio;
 }
@@ -113,7 +115,7 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
 		 */
 		if (fio->type == META_FLUSH) {
 			DECLARE_COMPLETION_ONSTACK(wait);
-			io->bio->bi_private = &wait;
+			io->sbi->wait_io = &wait;
 			submit_bio(rw, io->bio);
 			wait_for_completion(&wait);
 		} else {
@@ -797,48 +799,36 @@ static int f2fs_write_data_page(struct page *page,
 	 */
 	offset = i_size & (PAGE_CACHE_SIZE - 1);
 	if ((page->index >= end_index + 1) || !offset) {
-		if (S_ISDIR(inode->i_mode)) {
-			dec_page_count(sbi, F2FS_DIRTY_DENTS);
-			inode_dec_dirty_dents(inode);
-		}
+		inode_dec_dirty_dents(inode);
 		goto out;
 	}
 
 	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
 write:
-	if (unlikely(sbi->por_doing)) {
-		err = AOP_WRITEPAGE_ACTIVATE;
+	if (unlikely(sbi->por_doing))
 		goto redirty_out;
-	}
 
 	/* Dentry blocks are controlled by checkpoint */
 	if (S_ISDIR(inode->i_mode)) {
-		dec_page_count(sbi, F2FS_DIRTY_DENTS);
 		inode_dec_dirty_dents(inode);
 		err = do_write_data_page(page, &fio);
-	} else {
-		f2fs_lock_op(sbi);
-
-		if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode)) {
-			err = f2fs_write_inline_data(inode, page, offset);
-			f2fs_unlock_op(sbi);
-			goto out;
-		} else {
-			err = do_write_data_page(page, &fio);
-		}
+		goto done;
+	}
 
-		f2fs_unlock_op(sbi);
+	if (!wbc->for_reclaim)
 		need_balance_fs = true;
-	}
-	if (err == -ENOENT)
-		goto out;
-	else if (err)
+	else if (has_not_enough_free_secs(sbi, 0))
 		goto redirty_out;
 
-	if (wbc->for_reclaim) {
-		f2fs_submit_merged_bio(sbi, DATA, WRITE);
-		need_balance_fs = false;
-	}
+	f2fs_lock_op(sbi);
+	if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode))
+		err = f2fs_write_inline_data(inode, page, offset);
+	else
+		err = do_write_data_page(page, &fio);
+	f2fs_unlock_op(sbi);
+done:
+	if (err && err != -ENOENT)
+		goto redirty_out;
 
 	clear_cold_data(page);
 out:
@@ -849,8 +839,9 @@ out:
 
 redirty_out:
 	wbc->pages_skipped++;
+	account_page_redirty(page);
 	set_page_dirty(page);
-	return err;
+	return AOP_WRITEPAGE_ACTIVATE;
 }
 
 #define MAX_DESIRED_PAGES_WP	4096
@@ -1031,11 +1022,8 @@ static void f2fs_invalidate_data_page(struct page *page, unsigned int offset,
 				      unsigned int length)
 {
 	struct inode *inode = page->mapping->host;
-	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	if (S_ISDIR(inode->i_mode) && PageDirty(page)) {
-		dec_page_count(sbi, F2FS_DIRTY_DENTS);
+	if (PageDirty(page))
 		inode_dec_dirty_dents(inode);
-	}
 	ClearPagePrivate(page);
 }
 
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 3de9d20d0c14..b7111c44a918 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -86,7 +86,6 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 	unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
-	struct sit_info *sit_i = SIT_I(sbi);
 	unsigned int segno, vblocks;
 	int ndirty = 0;
 
@@ -94,7 +93,6 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
 	total_vblocks = 0;
 	blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
 	hblks_per_sec = blks_per_sec / 2;
-	mutex_lock(&sit_i->sentry_lock);
 	for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
 		vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
 		dist = abs(vblocks - hblks_per_sec);
@@ -105,7 +103,6 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
 			ndirty++;
 		}
 	}
-	mutex_unlock(&sit_i->sentry_lock);
 	dist = TOTAL_SECS(sbi) * hblks_per_sec * hblks_per_sec / 100;
 	si->bimodal = bimodal / dist;
 	if (si->dirty_count)
@@ -236,6 +233,7 @@ static int stat_show(struct seq_file *s, void *v)
 			   si->dirty_count);
 		seq_printf(s, "  - Prefree: %d\n  - Free: %d (%d)\n\n",
 			   si->prefree_count, si->free_segs, si->free_secs);
+		seq_printf(s, "CP calls: %d\n", si->cp_count);
 		seq_printf(s, "GC calls: %d (BG: %d)\n",
 			   si->call_count, si->bg_gc);
 		seq_printf(s, "  - data segments : %d\n", si->data_segs);
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 2b7c255bcbdf..582fa00f3597 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -21,12 +21,12 @@ static unsigned long dir_blocks(struct inode *inode)
 							>> PAGE_CACHE_SHIFT;
 }
 
-static unsigned int dir_buckets(unsigned int level)
+static unsigned int dir_buckets(unsigned int level, int dir_level)
 {
 	if (level < MAX_DIR_HASH_DEPTH / 2)
-		return 1 << level;
+		return 1 << (level + dir_level);
 	else
-		return 1 << ((MAX_DIR_HASH_DEPTH / 2) - 1);
+		return 1 << ((MAX_DIR_HASH_DEPTH / 2 + dir_level) - 1);
 }
 
 static unsigned int bucket_blocks(unsigned int level)
@@ -65,13 +65,14 @@ static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
 	de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
 }
 
-static unsigned long dir_block_index(unsigned int level, unsigned int idx)
+static unsigned long dir_block_index(unsigned int level,
+				int dir_level, unsigned int idx)
 {
 	unsigned long i;
 	unsigned long bidx = 0;
 
 	for (i = 0; i < level; i++)
-		bidx += dir_buckets(i) * bucket_blocks(i);
+		bidx += dir_buckets(i, dir_level) * bucket_blocks(i);
 	bidx += idx * bucket_blocks(level);
 	return bidx;
 }
@@ -93,16 +94,20 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
 			f2fs_hash_t namehash, struct page **res_page)
 {
 	struct f2fs_dir_entry *de;
-	unsigned long bit_pos, end_pos, next_pos;
+	unsigned long bit_pos = 0;
 	struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
-	int slots;
+	int max_len = 0;
 
-	bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
-					NR_DENTRY_IN_BLOCK, 0);
 	while (bit_pos < NR_DENTRY_IN_BLOCK) {
 		de = &dentry_blk->dentry[bit_pos];
-		slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-
+		if (!test_bit_le(bit_pos, &dentry_blk->dentry_bitmap)) {
+			if (bit_pos == 0)
+				max_len = 1;
+			else if (!test_bit_le(bit_pos - 1, &dentry_blk->dentry_bitmap))
+				max_len++;
+			bit_pos++;
+			continue;
+		}
 		if (early_match_name(name, namelen, namehash, de)) {
 			if (!memcmp(dentry_blk->filename[bit_pos],
 							name, namelen)) {
@@ -110,20 +115,18 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
 				goto found;
 			}
 		}
-		next_pos = bit_pos + slots;
-		bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
-				NR_DENTRY_IN_BLOCK, next_pos);
-		if (bit_pos >= NR_DENTRY_IN_BLOCK)
-			end_pos = NR_DENTRY_IN_BLOCK;
-		else
-			end_pos = bit_pos;
-		if (*max_slots < end_pos - next_pos)
-			*max_slots = end_pos - next_pos;
+		if (max_len > *max_slots) {
+			*max_slots = max_len;
+			max_len = 0;
+		}
+		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
 	}
 
 	de = NULL;
 	kunmap(dentry_page);
 found:
+	if (max_len > *max_slots)
+		*max_slots = max_len;
 	return de;
 }
 
@@ -141,10 +144,11 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
 
 	f2fs_bug_on(level > MAX_DIR_HASH_DEPTH);
 
-	nbucket = dir_buckets(level);
+	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
 	nblock = bucket_blocks(level);
 
-	bidx = dir_block_index(level, le32_to_cpu(namehash) % nbucket);
+	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
+					le32_to_cpu(namehash) % nbucket);
 	end_block = bidx + nblock;
 
 	for (; bidx < end_block; bidx++) {
@@ -372,6 +376,10 @@ static struct page *init_inode_metadata(struct inode *inode,
 
 put_error:
 	f2fs_put_page(page, 1);
+	/* once the failed inode becomes a bad inode, i_mode is S_IFREG */
+	truncate_inode_pages(&inode->i_data, 0);
+	truncate_blocks(inode, 0);
+	remove_dirty_dir_inode(inode);
 error:
 	remove_inode_page(inode);
 	return ERR_PTR(err);
@@ -395,9 +403,6 @@ static void update_parent_metadata(struct inode *dir, struct inode *inode,
 		set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
 	}
 
-	if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR))
-		update_inode_page(dir);
-
 	if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
 		clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
 }
@@ -464,10 +469,11 @@ start:
 	if (level == current_depth)
 		++current_depth;
 
-	nbucket = dir_buckets(level);
+	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
 	nblock = bucket_blocks(level);
 
-	bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket));
+	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
+				(le32_to_cpu(dentry_hash) % nbucket));
 
 	for (block = bidx; block <= (bidx + nblock - 1); block++) {
 		dentry_page = get_new_data_page(dir, NULL, block, true);
@@ -511,7 +517,10 @@ add_dentry:
 
 	update_parent_metadata(dir, inode, current_depth);
 fail:
-	clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
+	if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
+		update_inode_page(dir);
+		clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
+	}
 	kunmap(dentry_page);
 	f2fs_put_page(dentry_page, 1);
 	return err;
@@ -528,7 +537,6 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
 	unsigned int bit_pos;
 	struct address_space *mapping = page->mapping;
 	struct inode *dir = mapping->host;
-	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
 	int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
 	void *kaddr = page_address(page);
 	int i;
@@ -551,6 +559,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 
 	if (inode) {
+		struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+
 		if (S_ISDIR(inode->i_mode)) {
 			drop_nlink(dir);
 			update_inode_page(dir);
@@ -573,7 +583,6 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
 		truncate_hole(dir, page->index, page->index + 1);
 		clear_page_dirty_for_io(page);
 		ClearPageUptodate(page);
-		dec_page_count(sbi, F2FS_DIRTY_DENTS);
 		inode_dec_dirty_dents(dir);
 	}
 	f2fs_put_page(page, 1);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index fc3c558cb4f3..8b2cb82f852b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -88,6 +88,16 @@ enum {
 	SIT_BITMAP
 };
 
+/*
+ * For CP/NAT/SIT/SSA readahead
+ */
+enum {
+	META_CP,
+	META_NAT,
+	META_SIT,
+	META_SSA
+};
+
 /* for the list of orphan inodes */
 struct orphan_inode_entry {
 	struct list_head list;	/* list head */
@@ -187,10 +197,13 @@ struct extent_info {
 #define FADVISE_COLD_BIT	0x01
 #define FADVISE_LOST_PINO_BIT	0x02
 
+#define DEF_DIR_LEVEL		0
+
 struct f2fs_inode_info {
 	struct inode vfs_inode;		/* serve a vfs inode */
 	unsigned long i_flags;		/* keep an inode flags for ioctl */
 	unsigned char i_advise;		/* use to give file attribute hints */
+	unsigned char i_dir_level;	/* use for dentry level for large dir */
 	unsigned int i_current_depth;	/* use only in directory structure */
 	unsigned int i_pino;		/* parent inode number */
 	umode_t i_acl_mode;		/* keep file acl mode temporarily */
@@ -238,6 +251,7 @@ struct f2fs_nm_info {
 	struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
 
 	/* free node ids management */
+	struct radix_tree_root free_nid_root;/* root of the free_nid cache */
 	struct list_head free_nid_list;	/* a list for free nids */
 	spinlock_t free_nid_list_lock;	/* protect free nid list */
 	unsigned int fcnt;		/* the number of free node id */
@@ -398,6 +412,7 @@ struct f2fs_sb_info {
 	/* for bio operations */
 	struct f2fs_bio_info read_io;			/* for read bios */
 	struct f2fs_bio_info write_io[NR_PAGE_TYPE];	/* for write bios */
+	struct completion *wait_io;		/* for completion bios */
 
 	/* for checkpoint */
 	struct f2fs_checkpoint *ckpt;		/* raw checkpoint pointer */
@@ -407,7 +422,6 @@ struct f2fs_sb_info {
 	struct mutex node_write;		/* locking node writes */
 	struct mutex writepages;		/* mutex for writepages() */
 	bool por_doing;				/* recovery is doing or not */
-	bool on_build_free_nids;		/* build_free_nids is doing */
 	wait_queue_head_t cp_wait;
 
 	/* for orphan inode management */
@@ -436,6 +450,7 @@ struct f2fs_sb_info {
 	unsigned int total_valid_node_count;	/* valid node block count */
 	unsigned int total_valid_inode_count;	/* valid inode count */
 	int active_logs;			/* # of active logs */
+	int dir_level;				/* directory level */
 
 	block_t user_block_count;		/* # of user blocks */
 	block_t total_valid_block_count;	/* # of valid blocks */
@@ -661,6 +676,7 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
 
 static inline void inode_inc_dirty_dents(struct inode *inode)
 {
+	inc_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS);
 	atomic_inc(&F2FS_I(inode)->dirty_dents);
 }
 
@@ -671,6 +687,10 @@ static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
 
 static inline void inode_dec_dirty_dents(struct inode *inode)
 {
+	if (!S_ISDIR(inode->i_mode))
+		return;
+
+	dec_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS);
 	atomic_dec(&F2FS_I(inode)->dirty_dents);
 }
 
@@ -689,11 +709,7 @@ static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
 
 static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
 {
-	block_t ret;
-	spin_lock(&sbi->stat_lock);
-	ret = sbi->total_valid_block_count;
-	spin_unlock(&sbi->stat_lock);
-	return ret;
+	return sbi->total_valid_block_count;
 }
 
 static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
@@ -789,11 +805,7 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 
 static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
 {
-	unsigned int ret;
-	spin_lock(&sbi->stat_lock);
-	ret = sbi->total_valid_node_count;
-	spin_unlock(&sbi->stat_lock);
-	return ret;
+	return sbi->total_valid_node_count;
 }
 
 static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
@@ -814,11 +826,7 @@ static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi)
 
 static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
 {
-	unsigned int ret;
-	spin_lock(&sbi->stat_lock);
-	ret = sbi->total_valid_inode_count;
-	spin_unlock(&sbi->stat_lock);
-	return ret;
+	return sbi->total_valid_inode_count;
 }
 
 static inline void f2fs_put_page(struct page *page, int unlock)
@@ -992,8 +1000,7 @@ static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi)
 
 static inline void *inline_xattr_addr(struct page *page)
 {
-	struct f2fs_inode *ri;
-	ri = (struct f2fs_inode *)page_address(page);
+	struct f2fs_inode *ri = F2FS_INODE(page);
 	return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE -
 					F2FS_INLINE_XATTR_ADDRS]);
 }
@@ -1013,8 +1020,7 @@ static inline int f2fs_has_inline_data(struct inode *inode)
 
 static inline void *inline_data_addr(struct page *page)
 {
-	struct f2fs_inode *ri;
-	ri = (struct f2fs_inode *)page_address(page);
+	struct f2fs_inode *ri = F2FS_INODE(page);
 	return (void *)&(ri->i_addr[1]);
 }
 
@@ -1023,6 +1029,12 @@ static inline int f2fs_readonly(struct super_block *sb)
 	return sb->s_flags & MS_RDONLY;
 }
 
+static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
+{
+	set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+	sbi->sb->s_flags |= MS_RDONLY;
+}
+
 #define get_inode_mode(i) \
 	((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
 	 (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
@@ -1048,7 +1060,7 @@ void f2fs_set_inode_flags(struct inode *);
 struct inode *f2fs_iget(struct super_block *, unsigned long);
 int try_to_free_nats(struct f2fs_sb_info *, int);
 void update_inode(struct inode *, struct page *);
-int update_inode_page(struct inode *);
+void update_inode_page(struct inode *);
 int f2fs_write_inode(struct inode *, struct writeback_control *);
 void f2fs_evict_inode(struct inode *);
 
@@ -1115,6 +1127,7 @@ void alloc_nid_done(struct f2fs_sb_info *, nid_t);
 void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
 void recover_node_page(struct f2fs_sb_info *, struct page *,
 		struct f2fs_summary *, struct node_info *, block_t);
+bool recover_xattr_data(struct inode *, struct page *, block_t);
 int recover_inode_page(struct f2fs_sb_info *, struct page *);
 int restore_node_summary(struct f2fs_sb_info *, unsigned int,
 				struct f2fs_summary_block *);
@@ -1130,6 +1143,7 @@ void destroy_node_manager_caches(void);
 void f2fs_balance_fs(struct f2fs_sb_info *);
 void f2fs_balance_fs_bg(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 *);
 int npages_for_summary_flush(struct f2fs_sb_info *);
 void allocate_new_segments(struct f2fs_sb_info *);
@@ -1162,6 +1176,7 @@ void destroy_segment_manager_caches(void);
  */
 struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
+int ra_meta_pages(struct f2fs_sb_info *, int, int, int);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
 int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
@@ -1231,7 +1246,7 @@ struct f2fs_stat_info {
 	int util_free, util_valid, util_invalid;
 	int rsvd_segs, overp_segs;
 	int dirty_count, node_pages, meta_pages;
-	int prefree_count, call_count;
+	int prefree_count, call_count, cp_count;
 	int tot_segs, node_segs, data_segs, free_segs, free_secs;
 	int tot_blks, data_blks, node_blks;
 	int curseg[NR_CURSEG_TYPE];
@@ -1248,6 +1263,7 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
 	return (struct f2fs_stat_info *)sbi->stat_info;
 }
 
+#define stat_inc_cp_count(si)		((si)->cp_count++)
 #define stat_inc_call_count(si)		((si)->call_count++)
 #define stat_inc_bggc_count(sbi)	((sbi)->bg_gc++)
 #define stat_inc_dirty_dir(sbi)		((sbi)->n_dirty_dirs++)
@@ -1302,6 +1318,7 @@ void f2fs_destroy_stats(struct f2fs_sb_info *);
 void __init f2fs_create_root_stats(void);
 void f2fs_destroy_root_stats(void);
 #else
+#define stat_inc_cp_count(si)
 #define stat_inc_call_count(si)
 #define stat_inc_bggc_count(si)
 #define stat_inc_dirty_dir(sbi)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 0dfcef53a6ed..bc9f9246acf5 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -84,6 +84,7 @@ out:
 
 static const struct vm_operations_struct f2fs_file_vm_ops = {
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite	= f2fs_vm_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
@@ -560,6 +561,8 @@ static long f2fs_fallocate(struct file *file, int mode,
 	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
 		return -EOPNOTSUPP;
 
+	mutex_lock(&inode->i_mutex);
+
 	if (mode & FALLOC_FL_PUNCH_HOLE)
 		ret = punch_hole(inode, offset, len);
 	else
@@ -569,6 +572,9 @@ static long f2fs_fallocate(struct file *file, int mode,
 		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 	}
+
+	mutex_unlock(&inode->i_mutex);
+
 	trace_f2fs_fallocate(inode, mode, offset, len, ret);
 	return ret;
 }
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ea0371e854b4..d94acbc3d928 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -531,15 +531,10 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
 		set_page_dirty(page);
 		set_cold_data(page);
 	} else {
-		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-
 		f2fs_wait_on_page_writeback(page, DATA);
 
-		if (clear_page_dirty_for_io(page) &&
-			S_ISDIR(inode->i_mode)) {
-			dec_page_count(sbi, F2FS_DIRTY_DENTS);
+		if (clear_page_dirty_for_io(page))
 			inode_dec_dirty_dents(inode);
-		}
 		set_cold_data(page);
 		do_write_data_page(page, &fio);
 		clear_cold_data(page);
@@ -701,6 +696,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi)
 gc_more:
 	if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE)))
 		goto stop;
+	if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+		goto stop;
 
 	if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) {
 		gc_type = FG_GC;
@@ -711,6 +708,11 @@ gc_more:
 		goto stop;
 	ret = 0;
 
+	/* readahead multi ssa blocks those have contiguous address */
+	if (sbi->segs_per_sec > 1)
+		ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), sbi->segs_per_sec,
+								META_SSA);
+
 	for (i = 0; i < sbi->segs_per_sec; i++)
 		do_garbage_collect(sbi, segno + i, &ilist, gc_type);
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 4d67ed736dca..a48cf1edffb1 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -107,6 +107,7 @@ static int do_read_inode(struct inode *inode)
 	fi->flags = 0;
 	fi->i_advise = ri->i_advise;
 	fi->i_pino = le32_to_cpu(ri->i_pino);
+	fi->i_dir_level = ri->i_dir_level;
 
 	get_extent_info(&fi->ext, ri->i_ext);
 	get_inline_info(fi, ri);
@@ -204,6 +205,7 @@ void update_inode(struct inode *inode, struct page *node_page)
 	ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
 	ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
 	ri->i_generation = cpu_to_le32(inode->i_generation);
+	ri->i_dir_level = F2FS_I(inode)->i_dir_level;
 
 	__set_inode_rdev(inode, ri);
 	set_cold_node(inode, node_page);
@@ -212,24 +214,29 @@ void update_inode(struct inode *inode, struct page *node_page)
 	clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE);
 }
 
-int update_inode_page(struct inode *inode)
+void update_inode_page(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct page *node_page;
-
+retry:
 	node_page = get_node_page(sbi, inode->i_ino);
-	if (IS_ERR(node_page))
-		return PTR_ERR(node_page);
-
+	if (IS_ERR(node_page)) {
+		int err = PTR_ERR(node_page);
+		if (err == -ENOMEM) {
+			cond_resched();
+			goto retry;
+		} else if (err != -ENOENT) {
+			f2fs_stop_checkpoint(sbi);
+		}
+		return;
+	}
 	update_inode(inode, node_page);
 	f2fs_put_page(node_page, 1);
-	return 0;
 }
 
 int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	int ret;
 
 	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
 			inode->i_ino == F2FS_META_INO(sbi))
@@ -243,13 +250,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	 * during the urgent cleaning time when runing out of free sections.
 	 */
 	f2fs_lock_op(sbi);
-	ret = update_inode_page(inode);
+	update_inode_page(inode);
 	f2fs_unlock_op(sbi);
 
 	if (wbc)
 		f2fs_balance_fs(sbi);
 
-	return ret;
+	return 0;
 }
 
 /*
@@ -260,7 +267,7 @@ void f2fs_evict_inode(struct inode *inode)
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	trace_f2fs_evict_inode(inode);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
 			inode->i_ino == F2FS_META_INO(sbi))
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index b0649b76eb4f..8c1411060e7e 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -21,6 +21,8 @@
 #include "segment.h"
 #include <trace/events/f2fs.h>
 
+#define on_build_free_nids(nmi) mutex_is_locked(&nm_i->build_lock)
+
 static struct kmem_cache *nat_entry_slab;
 static struct kmem_cache *free_nid_slab;
 
@@ -82,42 +84,6 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
 	return dst_page;
 }
 
-/*
- * Readahead NAT pages
- */
-static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
-{
-	struct address_space *mapping = META_MAPPING(sbi);
-	struct f2fs_nm_info *nm_i = NM_I(sbi);
-	struct page *page;
-	pgoff_t index;
-	int i;
-	struct f2fs_io_info fio = {
-		.type = META,
-		.rw = READ_SYNC | REQ_META | REQ_PRIO
-	};
-
-
-	for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
-		if (unlikely(nid >= nm_i->max_nid))
-			nid = 0;
-		index = current_nat_addr(sbi, nid);
-
-		page = grab_cache_page(mapping, index);
-		if (!page)
-			continue;
-		if (PageUptodate(page)) {
-			mark_page_accessed(page);
-			f2fs_put_page(page, 1);
-			continue;
-		}
-		f2fs_submit_page_mbio(sbi, page, index, &fio);
-		mark_page_accessed(page);
-		f2fs_put_page(page, 0);
-	}
-	f2fs_submit_merged_bio(sbi, META, READ);
-}
-
 static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
 {
 	return radix_tree_lookup(&nm_i->nat_root, n);
@@ -164,6 +130,7 @@ static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
 	}
 	memset(new, 0, sizeof(struct nat_entry));
 	nat_set_nid(new, nid);
+	new->checkpointed = true;
 	list_add_tail(&new->list, &nm_i->nat_entries);
 	nm_i->nat_cnt++;
 	return new;
@@ -185,7 +152,6 @@ retry:
 		nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
 		nat_set_ino(e, le32_to_cpu(ne->ino));
 		nat_set_version(e, ne->version);
-		e->checkpointed = true;
 	}
 	write_unlock(&nm_i->nat_tree_lock);
 }
@@ -205,7 +171,6 @@ retry:
 			goto retry;
 		}
 		e->ni = *ni;
-		e->checkpointed = true;
 		f2fs_bug_on(ni->blk_addr == NEW_ADDR);
 	} else if (new_blkaddr == NEW_ADDR) {
 		/*
@@ -217,9 +182,6 @@ retry:
 		f2fs_bug_on(ni->blk_addr != NULL_ADDR);
 	}
 
-	if (new_blkaddr == NEW_ADDR)
-		e->checkpointed = false;
-
 	/* sanity check */
 	f2fs_bug_on(nat_get_blkaddr(e) != ni->blk_addr);
 	f2fs_bug_on(nat_get_blkaddr(e) == NULL_ADDR &&
@@ -1231,6 +1193,7 @@ static int f2fs_write_node_page(struct page *page,
 redirty_out:
 	dec_page_count(sbi, F2FS_DIRTY_NODES);
 	wbc->pages_skipped++;
+	account_page_redirty(page);
 	set_page_dirty(page);
 	return AOP_WRITEPAGE_ACTIVATE;
 }
@@ -1307,21 +1270,17 @@ const struct address_space_operations f2fs_node_aops = {
 	.releasepage	= f2fs_release_node_page,
 };
 
-static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
+static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i,
+						nid_t n)
 {
-	struct list_head *this;
-	struct free_nid *i;
-	list_for_each(this, head) {
-		i = list_entry(this, struct free_nid, list);
-		if (i->nid == n)
-			return i;
-	}
-	return NULL;
+	return radix_tree_lookup(&nm_i->free_nid_root, n);
 }
 
-static void __del_from_free_nid_list(struct free_nid *i)
+static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i,
+						struct free_nid *i)
 {
 	list_del(&i->list);
+	radix_tree_delete(&nm_i->free_nid_root, i->nid);
 	kmem_cache_free(free_nid_slab, i);
 }
 
@@ -1342,7 +1301,8 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
 		/* do not add allocated nids */
 		read_lock(&nm_i->nat_tree_lock);
 		ne = __lookup_nat_cache(nm_i, nid);
-		if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
+		if (ne &&
+			(!ne->checkpointed || nat_get_blkaddr(ne) != NULL_ADDR))
 			allocated = true;
 		read_unlock(&nm_i->nat_tree_lock);
 		if (allocated)
@@ -1354,7 +1314,7 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
 	i->state = NID_NEW;
 
 	spin_lock(&nm_i->free_nid_list_lock);
-	if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
+	if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) {
 		spin_unlock(&nm_i->free_nid_list_lock);
 		kmem_cache_free(free_nid_slab, i);
 		return 0;
@@ -1369,9 +1329,9 @@ static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
 {
 	struct free_nid *i;
 	spin_lock(&nm_i->free_nid_list_lock);
-	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+	i = __lookup_free_nid_list(nm_i, nid);
 	if (i && i->state == NID_NEW) {
-		__del_from_free_nid_list(i);
+		__del_from_free_nid_list(nm_i, i);
 		nm_i->fcnt--;
 	}
 	spin_unlock(&nm_i->free_nid_list_lock);
@@ -1413,7 +1373,7 @@ static void build_free_nids(struct f2fs_sb_info *sbi)
 		return;
 
 	/* readahead nat pages to be scanned */
-	ra_nat_pages(sbi, nid);
+	ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, META_NAT);
 
 	while (1) {
 		struct page *page = get_current_nat_page(sbi, nid);
@@ -1462,7 +1422,7 @@ retry:
 	spin_lock(&nm_i->free_nid_list_lock);
 
 	/* We should not use stale free nids created by build_free_nids */
-	if (nm_i->fcnt && !sbi->on_build_free_nids) {
+	if (nm_i->fcnt && !on_build_free_nids(nm_i)) {
 		f2fs_bug_on(list_empty(&nm_i->free_nid_list));
 		list_for_each(this, &nm_i->free_nid_list) {
 			i = list_entry(this, struct free_nid, list);
@@ -1481,9 +1441,7 @@ retry:
 
 	/* Let's scan nat pages and its caches to get free nids */
 	mutex_lock(&nm_i->build_lock);
-	sbi->on_build_free_nids = true;
 	build_free_nids(sbi);
-	sbi->on_build_free_nids = false;
 	mutex_unlock(&nm_i->build_lock);
 	goto retry;
 }
@@ -1497,9 +1455,9 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
 	struct free_nid *i;
 
 	spin_lock(&nm_i->free_nid_list_lock);
-	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+	i = __lookup_free_nid_list(nm_i, nid);
 	f2fs_bug_on(!i || i->state != NID_ALLOC);
-	__del_from_free_nid_list(i);
+	__del_from_free_nid_list(nm_i, i);
 	spin_unlock(&nm_i->free_nid_list_lock);
 }
 
@@ -1515,10 +1473,10 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
 		return;
 
 	spin_lock(&nm_i->free_nid_list_lock);
-	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+	i = __lookup_free_nid_list(nm_i, nid);
 	f2fs_bug_on(!i || i->state != NID_ALLOC);
 	if (nm_i->fcnt > 2 * MAX_FREE_NIDS) {
-		__del_from_free_nid_list(i);
+		__del_from_free_nid_list(nm_i, i);
 	} else {
 		i->state = NID_NEW;
 		nm_i->fcnt++;
@@ -1535,6 +1493,46 @@ void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
 	clear_node_page_dirty(page);
 }
 
+bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
+	nid_t new_xnid = nid_of_node(page);
+	struct node_info ni;
+
+	if (ofs_of_node(page) != XATTR_NODE_OFFSET)
+		return false;
+
+	/* 1: invalidate the previous xattr nid */
+	if (!prev_xnid)
+		goto recover_xnid;
+
+	/* Deallocate node address */
+	get_node_info(sbi, prev_xnid, &ni);
+	f2fs_bug_on(ni.blk_addr == NULL_ADDR);
+	invalidate_blocks(sbi, ni.blk_addr);
+	dec_valid_node_count(sbi, inode);
+	set_node_addr(sbi, &ni, NULL_ADDR);
+
+recover_xnid:
+	/* 2: allocate new xattr nid */
+	if (unlikely(!inc_valid_node_count(sbi, inode)))
+		f2fs_bug_on(1);
+
+	remove_free_nid(NM_I(sbi), new_xnid);
+	get_node_info(sbi, new_xnid, &ni);
+	ni.ino = inode->i_ino;
+	set_node_addr(sbi, &ni, NEW_ADDR);
+	F2FS_I(inode)->i_xattr_nid = new_xnid;
+
+	/* 3: update xattr blkaddr */
+	refresh_sit_entry(sbi, NEW_ADDR, blkaddr);
+	set_node_addr(sbi, &ni, blkaddr);
+
+	update_inode_page(inode);
+	return true;
+}
+
 int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
 {
 	struct f2fs_inode *src, *dst;
@@ -1783,7 +1781,6 @@ flush_now:
 		} else {
 			write_lock(&nm_i->nat_tree_lock);
 			__clear_nat_cache_dirty(nm_i, ne);
-			ne->checkpointed = true;
 			write_unlock(&nm_i->nat_tree_lock);
 		}
 	}
@@ -1807,10 +1804,13 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
 	/* segment_count_nat includes pair segment so divide to 2. */
 	nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
 	nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
-	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
+
+	/* not used nids: 0, node, meta, (and root counted as valid node) */
+	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks - 3;
 	nm_i->fcnt = 0;
 	nm_i->nat_cnt = 0;
 
+	INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC);
 	INIT_LIST_HEAD(&nm_i->free_nid_list);
 	INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
 	INIT_LIST_HEAD(&nm_i->nat_entries);
@@ -1864,7 +1864,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
 	spin_lock(&nm_i->free_nid_list_lock);
 	list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
 		f2fs_bug_on(i->state == NID_ALLOC);
-		__del_from_free_nid_list(i);
+		__del_from_free_nid_list(nm_i, i);
 		nm_i->fcnt--;
 	}
 	f2fs_bug_on(nm_i->fcnt);
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index c4c79885c993..4dea719766ef 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -58,9 +58,15 @@ struct nat_entry {
 #define nat_set_version(nat, v)		(nat->ni.version = v)
 
 #define __set_nat_cache_dirty(nm_i, ne)					\
-	list_move_tail(&ne->list, &nm_i->dirty_nat_entries);
+	do {								\
+		ne->checkpointed = false;				\
+		list_move_tail(&ne->list, &nm_i->dirty_nat_entries);	\
+	} while (0);
 #define __clear_nat_cache_dirty(nm_i, ne)				\
-	list_move_tail(&ne->list, &nm_i->nat_entries);
+	do {								\
+		ne->checkpointed = true;				\
+		list_move_tail(&ne->list, &nm_i->nat_entries);		\
+	} while (0);
 #define inc_node_version(version)	(++version)
 
 static inline void node_info_from_raw_nat(struct node_info *ni,
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 976a7a934db5..aef77681e10b 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -136,7 +136,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
 
 	/* get node pages in the current segment */
 	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
-	blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
+	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
 
 	/* read node page */
 	page = alloc_page(GFP_F2FS_ZERO);
@@ -218,13 +218,12 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
 {
 	struct seg_entry *sentry;
 	unsigned int segno = GET_SEGNO(sbi, blkaddr);
-	unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
-					(sbi->blocks_per_seg - 1);
+	unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
+	struct f2fs_summary_block *sum_node;
 	struct f2fs_summary sum;
+	struct page *sum_page, *node_page;
 	nid_t ino, nid;
-	void *kaddr;
 	struct inode *inode;
-	struct page *node_page;
 	unsigned int offset;
 	block_t bidx;
 	int i;
@@ -238,18 +237,15 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
 		struct curseg_info *curseg = CURSEG_I(sbi, i);
 		if (curseg->segno == segno) {
 			sum = curseg->sum_blk->entries[blkoff];
-			break;
+			goto got_it;
 		}
 	}
-	if (i > CURSEG_COLD_DATA) {
-		struct page *sum_page = get_sum_page(sbi, segno);
-		struct f2fs_summary_block *sum_node;
-		kaddr = page_address(sum_page);
-		sum_node = (struct f2fs_summary_block *)kaddr;
-		sum = sum_node->entries[blkoff];
-		f2fs_put_page(sum_page, 1);
-	}
 
+	sum_page = get_sum_page(sbi, segno);
+	sum_node = (struct f2fs_summary_block *)page_address(sum_page);
+	sum = sum_node->entries[blkoff];
+	f2fs_put_page(sum_page, 1);
+got_it:
 	/* Use the locked dnode page and inode */
 	nid = le32_to_cpu(sum.nid);
 	if (dn->inode->i_ino == nid) {
@@ -301,6 +297,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 	if (recover_inline_data(inode, page))
 		goto out;
 
+	if (recover_xattr_data(inode, page, blkaddr))
+		goto out;
+
 	start = start_bidx_of_node(ofs_of_node(page), fi);
 	if (IS_INODE(page))
 		end = start + ADDRS_PER_INODE(fi);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 7caac5f2ca9e..fbb41ba818fd 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -405,7 +405,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
 
 	se = get_seg_entry(sbi, segno);
 	new_vblocks = se->valid_blocks + del;
-	offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
+	offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
 
 	f2fs_bug_on((new_vblocks >> (sizeof(unsigned short) << 3) ||
 				(new_vblocks > sbi->blocks_per_seg)));
@@ -434,12 +434,14 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
 		get_sec_entry(sbi, segno)->valid_blocks += del;
 }
 
-static void refresh_sit_entry(struct f2fs_sb_info *sbi,
-			block_t old_blkaddr, block_t new_blkaddr)
+void refresh_sit_entry(struct f2fs_sb_info *sbi, block_t old, block_t new)
 {
-	update_sit_entry(sbi, new_blkaddr, 1);
-	if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
-		update_sit_entry(sbi, old_blkaddr, -1);
+	update_sit_entry(sbi, new, 1);
+	if (GET_SEGNO(sbi, old) != NULL_SEGNO)
+		update_sit_entry(sbi, old, -1);
+
+	locate_dirty_segment(sbi, GET_SEGNO(sbi, old));
+	locate_dirty_segment(sbi, GET_SEGNO(sbi, new));
 }
 
 void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
@@ -881,17 +883,15 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 
 	stat_inc_block_count(sbi, curseg);
 
+	if (!__has_curseg_space(sbi, type))
+		sit_i->s_ops->allocate_segment(sbi, type, false);
 	/*
 	 * SIT information should be updated before segment allocation,
 	 * since SSR needs latest valid block information.
 	 */
 	refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr);
-
-	if (!__has_curseg_space(sbi, type))
-		sit_i->s_ops->allocate_segment(sbi, type, false);
-
 	locate_dirty_segment(sbi, old_cursegno);
-	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+
 	mutex_unlock(&sit_i->sentry_lock);
 
 	if (page && IS_NODESEG(type))
@@ -987,14 +987,11 @@ void recover_data_page(struct f2fs_sb_info *sbi,
 		change_curseg(sbi, type, true);
 	}
 
-	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
-					(sbi->blocks_per_seg - 1);
+	curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
 	__add_sum_entry(sbi, type, sum);
 
 	refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
-
 	locate_dirty_segment(sbi, old_cursegno);
-	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
 
 	mutex_unlock(&sit_i->sentry_lock);
 	mutex_unlock(&curseg->curseg_mutex);
@@ -1028,8 +1025,7 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
 		curseg->next_segno = segno;
 		change_curseg(sbi, type, true);
 	}
-	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
-					(sbi->blocks_per_seg - 1);
+	curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
 	__add_sum_entry(sbi, type, sum);
 
 	/* change the current log to the next block addr in advance */
@@ -1037,17 +1033,14 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
 		curseg->next_segno = next_segno;
 		change_curseg(sbi, type, true);
 	}
-	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) &
-					(sbi->blocks_per_seg - 1);
+	curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, next_blkaddr);
 
 	/* rewrite node page */
 	set_page_writeback(page);
 	f2fs_submit_page_mbio(sbi, page, new_blkaddr, &fio);
 	f2fs_submit_merged_bio(sbi, NODE, WRITE);
 	refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
-
 	locate_dirty_segment(sbi, old_cursegno);
-	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
 
 	mutex_unlock(&sit_i->sentry_lock);
 	mutex_unlock(&curseg->curseg_mutex);
@@ -1583,47 +1576,6 @@ static int build_curseg(struct f2fs_sb_info *sbi)
 	return restore_curseg_summaries(sbi);
 }
 
-static int ra_sit_pages(struct f2fs_sb_info *sbi, int start, int nrpages)
-{
-	struct address_space *mapping = META_MAPPING(sbi);
-	struct page *page;
-	block_t blk_addr, prev_blk_addr = 0;
-	int sit_blk_cnt = SIT_BLK_CNT(sbi);
-	int blkno = start;
-	struct f2fs_io_info fio = {
-		.type = META,
-		.rw = READ_SYNC | REQ_META | REQ_PRIO
-	};
-
-	for (; blkno < start + nrpages && blkno < sit_blk_cnt; blkno++) {
-
-		blk_addr = current_sit_addr(sbi, blkno * SIT_ENTRY_PER_BLOCK);
-
-		if (blkno != start && prev_blk_addr + 1 != blk_addr)
-			break;
-		prev_blk_addr = blk_addr;
-repeat:
-		page = grab_cache_page(mapping, blk_addr);
-		if (!page) {
-			cond_resched();
-			goto repeat;
-		}
-		if (PageUptodate(page)) {
-			mark_page_accessed(page);
-			f2fs_put_page(page, 1);
-			continue;
-		}
-
-		f2fs_submit_page_mbio(sbi, page, blk_addr, &fio);
-
-		mark_page_accessed(page);
-		f2fs_put_page(page, 0);
-	}
-
-	f2fs_submit_merged_bio(sbi, META, READ);
-	return blkno - start;
-}
-
 static void build_sit_entries(struct f2fs_sb_info *sbi)
 {
 	struct sit_info *sit_i = SIT_I(sbi);
@@ -1635,7 +1587,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi)
 	int nrpages = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
 
 	do {
-		readed = ra_sit_pages(sbi, start_blk, nrpages);
+		readed = ra_meta_pages(sbi, start_blk, nrpages, META_SIT);
 
 		start = start_blk * sit_i->sents_per_block;
 		end = (start_blk + readed) * sit_i->sents_per_block;
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 5731682d7516..c3d5e3689ffc 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -57,6 +57,9 @@
 	((blk_addr) - SM_I(sbi)->seg0_blkaddr)
 #define GET_SEGNO_FROM_SEG0(sbi, blk_addr)				\
 	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
+#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr)				\
+	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1))
+
 #define GET_SEGNO(sbi, blk_addr)					\
 	(((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ?		\
 	NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),			\
@@ -377,26 +380,12 @@ static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
 
 static inline block_t written_block_count(struct f2fs_sb_info *sbi)
 {
-	struct sit_info *sit_i = SIT_I(sbi);
-	block_t vblocks;
-
-	mutex_lock(&sit_i->sentry_lock);
-	vblocks = sit_i->written_valid_blocks;
-	mutex_unlock(&sit_i->sentry_lock);
-
-	return vblocks;
+	return SIT_I(sbi)->written_valid_blocks;
 }
 
 static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
 {
-	struct free_segmap_info *free_i = FREE_I(sbi);
-	unsigned int free_segs;
-
-	read_lock(&free_i->segmap_lock);
-	free_segs = free_i->free_segments;
-	read_unlock(&free_i->segmap_lock);
-
-	return free_segs;
+	return FREE_I(sbi)->free_segments;
 }
 
 static inline int reserved_segments(struct f2fs_sb_info *sbi)
@@ -406,14 +395,7 @@ static inline int reserved_segments(struct f2fs_sb_info *sbi)
 
 static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
 {
-	struct free_segmap_info *free_i = FREE_I(sbi);
-	unsigned int free_secs;
-
-	read_lock(&free_i->segmap_lock);
-	free_secs = free_i->free_sections;
-	read_unlock(&free_i->segmap_lock);
-
-	return free_secs;
+	return FREE_I(sbi)->free_sections;
 }
 
 static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1a85f83abd53..1bd915362154 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -184,6 +184,7 @@ F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
@@ -196,6 +197,7 @@ static struct attribute *f2fs_attrs[] = {
 	ATTR_LIST(ipu_policy),
 	ATTR_LIST(min_ipu_util),
 	ATTR_LIST(max_victim_search),
+	ATTR_LIST(dir_level),
 	NULL,
 };
 
@@ -359,6 +361,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 	if (test_opt(F2FS_SB(sb), INLINE_XATTR))
 		set_inode_flag(fi, FI_INLINE_XATTR);
 
+	/* Will be used by directory only */
+	fi->i_dir_level = F2FS_SB(sb)->dir_level;
+
 	return &fi->vfs_inode;
 }
 
@@ -785,6 +790,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
 
 	for (i = 0; i < NR_COUNT_TYPE; i++)
 		atomic_set(&sbi->nr_pages[i], 0);
+
+	sbi->dir_level = DEF_DIR_LEVEL;
 }
 
 /*
@@ -989,28 +996,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 		goto free_root_inode;
 	}
 
-	/* recover fsynced data */
-	if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
-		err = recover_fsync_data(sbi);
-		if (err)
-			f2fs_msg(sb, KERN_ERR,
-				"Cannot recover all fsync data errno=%ld", err);
-	}
-
-	/*
-	 * If filesystem is not mounted as read-only then
-	 * do start the gc_thread.
-	 */
-	if (!(sb->s_flags & MS_RDONLY)) {
-		/* After POR, we can run background GC thread.*/
-		err = start_gc_thread(sbi);
-		if (err)
-			goto free_gc;
-	}
-
 	err = f2fs_build_stats(sbi);
 	if (err)
-		goto free_gc;
+		goto free_root_inode;
 
 	if (f2fs_proc_root)
 		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
@@ -1032,17 +1020,36 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 	err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL,
 							"%s", sb->s_id);
 	if (err)
-		goto fail;
+		goto free_proc;
 
+	/* recover fsynced data */
+	if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
+		err = recover_fsync_data(sbi);
+		if (err)
+			f2fs_msg(sb, KERN_ERR,
+				"Cannot recover all fsync data errno=%ld", err);
+	}
+
+	/*
+	 * If filesystem is not mounted as read-only then
+	 * do start the gc_thread.
+	 */
+	if (!(sb->s_flags & MS_RDONLY)) {
+		/* After POR, we can run background GC thread.*/
+		err = start_gc_thread(sbi);
+		if (err)
+			goto free_kobj;
+	}
 	return 0;
-fail:
+
+free_kobj:
+	kobject_del(&sbi->s_kobj);
+free_proc:
 	if (sbi->s_proc) {
 		remove_proc_entry("segment_info", sbi->s_proc);
 		remove_proc_entry(sb->s_id, f2fs_proc_root);
 	}
 	f2fs_destroy_stats(sbi);
-free_gc:
-	stop_gc_thread(sbi);
 free_root_inode:
 	dput(sb->s_root);
 	sb->s_root = NULL;
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 91ad9e1c9441..d22c1a209808 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -325,19 +325,26 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
 
 	last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
 	if (sector >= last_block) {
-		if (!create)
-			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 (!create) {
+			/* Map a block in fallocated region */
+			if (atomic_read(&MSDOS_I(inode)->beyond_isize))
+				if (sector < last_block)
+					goto out_map_cluster;
+
+			return 0;
+		}
+
 		if (sector >= last_block)
 			return 0;
 	}
 
+out_map_cluster:
 	cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
 	offset  = sector & (sbi->sec_per_clus - 1);
 	cluster = fat_bmap_cluster(inode, cluster);
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 7c31f4bc74a9..b8842769b0c5 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 */
@@ -128,6 +129,9 @@ struct msdos_inode_info {
 	struct hlist_node i_dir_hash;	/* hash by i_logstart */
 	struct rw_semaphore truncate_lock; /* protect bmap against truncate */
 	struct inode vfs_inode;
+
+	/* for getting block number beyond file size in case of fallocate */
+	atomic_t beyond_isize;
 };
 
 struct fat_slot_info {
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 9b104f543056..79db8b6ab347 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)->mmu_private,
+			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 854b578f6695..95f0ac2f93fc 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;
 	}
 
 	/*
@@ -226,7 +256,10 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
 
 	/* fat_get_cluster() assumes the requested blocknr isn't truncated. */
 	down_read(&MSDOS_I(mapping->host)->truncate_lock);
+	/* To get block number beyond file size in fallocated region */
+	atomic_set(&MSDOS_I(mapping->host)->beyond_isize, 1);
 	blocknr = generic_block_bmap(mapping, block, fat_get_block);
+	atomic_set(&MSDOS_I(mapping->host)->beyond_isize, 0);
 	up_read(&MSDOS_I(mapping->host)->truncate_lock);
 
 	return blocknr;
@@ -408,6 +441,7 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 		if (error < 0)
 			return error;
 		MSDOS_I(inode)->mmu_private = inode->i_size;
+		MSDOS_I(inode)->i_disksize = inode->i_size;
 
 		set_nlink(inode, fat_subdirs(inode));
 	} else { /* not a directory */
@@ -423,6 +457,7 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 		inode->i_fop = &fat_file_operations;
 		inode->i_mapping->a_ops = &fat_aops;
 		MSDOS_I(inode)->mmu_private = inode->i_size;
+		MSDOS_I(inode)->i_disksize = inode->i_size;
 	}
 	if (de->attr & ATTR_SYS) {
 		if (sbi->options.sys_immutable)
@@ -490,10 +525,29 @@ EXPORT_SYMBOL_GPL(fat_build_inode);
 
 static void fat_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	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)->mmu_private < MSDOS_I(inode)->i_disksize) {
+			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
+			 * synchrnously to avoid any corruption on the next
+			 * access to the cluster chain for the file.
+			 */
+			err = fat_sync_inode(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);
@@ -1223,6 +1277,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/fcntl.c b/fs/fcntl.c
index ef6866592a0f..9ead1596399a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -272,9 +272,19 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
 	case F_SETFL:
 		err = setfl(fd, filp, arg);
 		break;
+#if BITS_PER_LONG != 32
+	/* 32-bit arches must use fcntl64() */
+	case F_GETLKP:
+#endif
 	case F_GETLK:
-		err = fcntl_getlk(filp, (struct flock __user *) arg);
+		err = fcntl_getlk(filp, cmd, (struct flock __user *) arg);
 		break;
+#if BITS_PER_LONG != 32
+	/* 32-bit arches must use fcntl64() */
+	case F_SETLKP:
+	case F_SETLKPW:
+#endif
+		/* Fallthrough */
 	case F_SETLK:
 	case F_SETLKW:
 		err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg);
@@ -388,17 +398,20 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
 		goto out1;
 	
 	switch (cmd) {
-		case F_GETLK64:
-			err = fcntl_getlk64(f.file, (struct flock64 __user *) arg);
-			break;
-		case F_SETLK64:
-		case F_SETLKW64:
-			err = fcntl_setlk64(fd, f.file, cmd,
-					(struct flock64 __user *) arg);
-			break;
-		default:
-			err = do_fcntl(fd, cmd, arg, f.file);
-			break;
+	case F_GETLK64:
+	case F_GETLKP:
+		err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg);
+		break;
+	case F_SETLK64:
+	case F_SETLKW64:
+	case F_SETLKP:
+	case F_SETLKPW:
+		err = fcntl_setlk64(fd, f.file, cmd,
+				(struct flock64 __user *) arg);
+		break;
+	default:
+		err = do_fcntl(fd, cmd, arg, f.file);
+		break;
 	}
 out1:
 	fdput(f);
diff --git a/fs/file.c b/fs/file.c
index db25c2bdfe46..18f7d27855c4 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -497,7 +497,7 @@ repeat:
 	error = fd;
 #if 1
 	/* Sanity check */
-	if (rcu_dereference_raw(fdt->fd[fd]) != NULL) {
+	if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
 		printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
 		rcu_assign_pointer(fdt->fd[fd], NULL);
 	}
diff --git a/fs/file_table.c b/fs/file_table.c
index 5fff9030be34..468543c1973d 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -234,7 +234,7 @@ static void __fput(struct file *file)
 	 * in the file cleanup chain.
 	 */
 	eventpoll_release(file);
-	locks_remove_flock(file);
+	locks_remove_file(file);
 
 	if (unlikely(file->f_flags & FASYNC)) {
 		if (file->f_op->fasync)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 92567d95ba6a..5797d45a78cb 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -121,6 +121,7 @@ int unregister_filesystem(struct file_system_type * fs)
 
 EXPORT_SYMBOL(unregister_filesystem);
 
+#ifdef CONFIG_SYSFS_SYSCALL
 static int fs_index(const char __user * __name)
 {
 	struct file_system_type * tmp;
@@ -199,6 +200,7 @@ SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
 	}
 	return retval;
 }
+#endif
 
 int __init get_filesystem_list(char *buf)
 {
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index f47df72cef17..363e3ae25f6b 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -354,7 +354,7 @@ static void vxfs_i_callback(struct rcu_head *head)
 void
 vxfs_evict_inode(struct inode *ip)
 {
-	truncate_inode_pages(&ip->i_data, 0);
+	truncate_inode_pages_final(&ip->i_data);
 	clear_inode(ip);
 	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index d754e3cf99a8..a6aae12ac7ff 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -89,6 +89,8 @@ static inline struct inode *wb_inode(struct list_head *head)
 #define CREATE_TRACE_POINTS
 #include <trace/events/writeback.h>
 
+EXPORT_TRACEPOINT_SYMBOL_GPL(wbc_writepage);
+
 static void bdi_queue_work(struct backing_dev_info *bdi,
 			   struct wb_writeback_work *work)
 {
@@ -1039,8 +1041,9 @@ void bdi_writeback_workfn(struct work_struct *work)
 		trace_writeback_pages_written(pages_written);
 	}
 
-	if (!list_empty(&bdi->work_list) ||
-	    (wb_has_dirty_io(wb) && dirty_writeback_interval))
+	if (!list_empty(&bdi->work_list))
+		mod_delayed_work(bdi_wq, &wb->dwork, 0);
+	else if (wb_has_dirty_io(wb) && dirty_writeback_interval)
 		queue_delayed_work(bdi_wq, &wb->dwork,
 			msecs_to_jiffies(dirty_writeback_interval * 10));
 
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index b96a49b37d66..23e363f38302 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -95,7 +95,7 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count,
 	struct iovec iov = { .iov_base = buf, .iov_len = count };
 	struct fuse_io_priv io = { .async = 0, .file = file };
 
-	return fuse_direct_io(&io, &iov, 1, count, &pos, 0);
+	return fuse_direct_io(&io, &iov, 1, count, &pos, FUSE_DIO_CUSE);
 }
 
 static ssize_t cuse_write(struct file *file, const char __user *buf,
@@ -109,7 +109,8 @@ static ssize_t cuse_write(struct file *file, const char __user *buf,
 	 * No locking or generic_write_checks(), the server is
 	 * responsible for locking and sanity checks.
 	 */
-	return fuse_direct_io(&io, &iov, 1, count, &pos, 1);
+	return fuse_direct_io(&io, &iov, 1, count, &pos,
+			      FUSE_DIO_WRITE | FUSE_DIO_CUSE);
 }
 
 static int cuse_open(struct inode *inode, struct file *file)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 1d1292c581c3..5b4e035b364c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -839,6 +839,14 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
 			  struct kstat *stat)
 {
 	unsigned int blkbits;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+
+	/* see the comment in fuse_change_attributes() */
+	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
+		attr->size = i_size_read(inode);
+		attr->mtime = inode->i_mtime.tv_sec;
+		attr->mtimensec = inode->i_mtime.tv_nsec;
+	}
 
 	stat->dev = inode->i_sb->s_dev;
 	stat->ino = attr->ino;
@@ -1477,12 +1485,16 @@ static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
 }
 
-static bool update_mtime(unsigned ivalid)
+static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
 {
 	/* Always update if mtime is explicitly set  */
 	if (ivalid & ATTR_MTIME_SET)
 		return true;
 
+	/* Or if kernel i_mtime is the official one */
+	if (trust_local_mtime)
+		return true;
+
 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
 		return false;
@@ -1491,7 +1503,8 @@ static bool update_mtime(unsigned ivalid)
 	return true;
 }
 
-static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
+			   bool trust_local_mtime)
 {
 	unsigned ivalid = iattr->ia_valid;
 
@@ -1510,11 +1523,11 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
 		if (!(ivalid & ATTR_ATIME_SET))
 			arg->valid |= FATTR_ATIME_NOW;
 	}
-	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
+	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_mtime)) {
 		arg->valid |= FATTR_MTIME;
 		arg->mtime = iattr->ia_mtime.tv_sec;
 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
-		if (!(ivalid & ATTR_MTIME_SET))
+		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_mtime)
 			arg->valid |= FATTR_MTIME_NOW;
 	}
 }
@@ -1563,6 +1576,63 @@ void fuse_release_nowrite(struct inode *inode)
 	spin_unlock(&fc->lock);
 }
 
+static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
+			      struct inode *inode,
+			      struct fuse_setattr_in *inarg_p,
+			      struct fuse_attr_out *outarg_p)
+{
+	req->in.h.opcode = FUSE_SETATTR;
+	req->in.h.nodeid = get_node_id(inode);
+	req->in.numargs = 1;
+	req->in.args[0].size = sizeof(*inarg_p);
+	req->in.args[0].value = inarg_p;
+	req->out.numargs = 1;
+	if (fc->minor < 9)
+		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
+	else
+		req->out.args[0].size = sizeof(*outarg_p);
+	req->out.args[0].value = outarg_p;
+}
+
+/*
+ * Flush inode->i_mtime to the server
+ */
+int fuse_flush_mtime(struct file *file, bool nofail)
+{
+	struct inode *inode = file->f_mapping->host;
+	struct fuse_inode *fi = get_fuse_inode(inode);
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_req *req = NULL;
+	struct fuse_setattr_in inarg;
+	struct fuse_attr_out outarg;
+	int err;
+
+	if (nofail) {
+		req = fuse_get_req_nofail_nopages(fc, file);
+	} else {
+		req = fuse_get_req_nopages(fc);
+		if (IS_ERR(req))
+			return PTR_ERR(req);
+	}
+
+	memset(&inarg, 0, sizeof(inarg));
+	memset(&outarg, 0, sizeof(outarg));
+
+	inarg.valid |= FATTR_MTIME;
+	inarg.mtime = inode->i_mtime.tv_sec;
+	inarg.mtimensec = inode->i_mtime.tv_nsec;
+
+	fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
+	fuse_request_send(fc, req);
+	err = req->out.h.error;
+	fuse_put_request(fc, req);
+
+	if (!err)
+		clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
+
+	return err;
+}
+
 /*
  * Set attributes, and at the same time refresh them.
  *
@@ -1580,8 +1650,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 	struct fuse_setattr_in inarg;
 	struct fuse_attr_out outarg;
 	bool is_truncate = false;
+	bool is_wb = fc->writeback_cache;
 	loff_t oldsize;
 	int err;
+	bool trust_local_mtime = is_wb && S_ISREG(inode->i_mode);
 
 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
 		attr->ia_valid |= ATTR_FORCE;
@@ -1610,7 +1682,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 
 	memset(&inarg, 0, sizeof(inarg));
 	memset(&outarg, 0, sizeof(outarg));
-	iattr_to_fattr(attr, &inarg);
+	iattr_to_fattr(attr, &inarg, trust_local_mtime);
 	if (file) {
 		struct fuse_file *ff = file->private_data;
 		inarg.valid |= FATTR_FH;
@@ -1621,17 +1693,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 		inarg.valid |= FATTR_LOCKOWNER;
 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
 	}
-	req->in.h.opcode = FUSE_SETATTR;
-	req->in.h.nodeid = get_node_id(inode);
-	req->in.numargs = 1;
-	req->in.args[0].size = sizeof(inarg);
-	req->in.args[0].value = &inarg;
-	req->out.numargs = 1;
-	if (fc->minor < 9)
-		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
-	else
-		req->out.args[0].size = sizeof(outarg);
-	req->out.args[0].value = &outarg;
+	fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
 	fuse_request_send(fc, req);
 	err = req->out.h.error;
 	fuse_put_request(fc, req);
@@ -1648,10 +1710,18 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 	}
 
 	spin_lock(&fc->lock);
+	/* the kernel maintains i_mtime locally */
+	if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) {
+		inode->i_mtime = attr->ia_mtime;
+		clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
+	}
+
 	fuse_change_attributes_common(inode, &outarg.attr,
 				      attr_timeout(&outarg));
 	oldsize = inode->i_size;
-	i_size_write(inode, outarg.attr.size);
+	/* see the comment in fuse_change_attributes() */
+	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
+		i_size_write(inode, outarg.attr.size);
 
 	if (is_truncate) {
 		/* NOTE: this may release/reacquire fc->lock */
@@ -1663,7 +1733,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 	 * Only call invalidate_inode_pages2() after removing
 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
 	 */
-	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
+	if ((is_truncate || !is_wb) &&
+	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
 		truncate_pagecache(inode, outarg.attr.size);
 		invalidate_inode_pages2(inode->i_mapping);
 	}
@@ -1875,6 +1946,17 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
 	return err;
 }
 
+static int fuse_update_time(struct inode *inode, struct timespec *now,
+			    int flags)
+{
+	if (flags & S_MTIME) {
+		inode->i_mtime = *now;
+		set_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state);
+		BUG_ON(!S_ISREG(inode->i_mode));
+	}
+	return 0;
+}
+
 static const struct inode_operations fuse_dir_inode_operations = {
 	.lookup		= fuse_lookup,
 	.mkdir		= fuse_mkdir,
@@ -1914,6 +1996,7 @@ static const struct inode_operations fuse_common_inode_operations = {
 	.getxattr	= fuse_getxattr,
 	.listxattr	= fuse_listxattr,
 	.removexattr	= fuse_removexattr,
+	.update_time	= fuse_update_time,
 };
 
 static const struct inode_operations fuse_symlink_inode_operations = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 77bcc303c3ae..40adffe12be7 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -188,6 +188,22 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 }
 EXPORT_SYMBOL_GPL(fuse_do_open);
 
+static void fuse_link_write_file(struct file *file)
+{
+	struct inode *inode = file_inode(file);
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_inode *fi = get_fuse_inode(inode);
+	struct fuse_file *ff = file->private_data;
+	/*
+	 * file may be written through mmap, so chain it onto the
+	 * inodes's write_file list
+	 */
+	spin_lock(&fc->lock);
+	if (list_empty(&ff->write_entry))
+		list_add(&ff->write_entry, &fi->write_files);
+	spin_unlock(&fc->lock);
+}
+
 void fuse_finish_open(struct inode *inode, struct file *file)
 {
 	struct fuse_file *ff = file->private_data;
@@ -208,6 +224,8 @@ void fuse_finish_open(struct inode *inode, struct file *file)
 		spin_unlock(&fc->lock);
 		fuse_invalidate_attr(inode);
 	}
+	if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
+		fuse_link_write_file(file);
 }
 
 int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
@@ -292,6 +310,15 @@ static int fuse_open(struct inode *inode, struct file *file)
 
 static int fuse_release(struct inode *inode, struct file *file)
 {
+	struct fuse_conn *fc = get_fuse_conn(inode);
+
+	/* see fuse_vma_close() for !writeback_cache case */
+	if (fc->writeback_cache)
+		filemap_write_and_wait(file->f_mapping);
+
+	if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state))
+		fuse_flush_mtime(file, true);
+
 	fuse_release_common(file, FUSE_RELEASE);
 
 	/* return value is ignored by VFS */
@@ -333,12 +360,13 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 }
 
 /*
- * Check if page is under writeback
+ * Check if any page in a range is under writeback
  *
  * This is currently done by walking the list of writepage requests
  * for the inode, which can be pretty inefficient.
  */
-static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
+static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from,
+				   pgoff_t idx_to)
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
@@ -351,8 +379,8 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
 
 		BUG_ON(req->inode != inode);
 		curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
-		if (curr_index <= index &&
-		    index < curr_index + req->num_pages) {
+		if (idx_from < curr_index + req->num_pages &&
+		    curr_index <= idx_to) {
 			found = true;
 			break;
 		}
@@ -362,6 +390,11 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
 	return found;
 }
 
+static inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
+{
+	return fuse_range_is_writeback(inode, index, index);
+}
+
 /*
  * Wait for page writeback to be completed.
  *
@@ -376,6 +409,21 @@ static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
 	return 0;
 }
 
+/*
+ * Wait for all pending writepages on the inode to finish.
+ *
+ * This is currently done by blocking further writes with FUSE_NOWRITE
+ * and waiting for all sent writes to complete.
+ *
+ * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
+ * could conflict with truncation.
+ */
+static void fuse_sync_writes(struct inode *inode)
+{
+	fuse_set_nowrite(inode);
+	fuse_release_nowrite(inode);
+}
+
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
 	struct inode *inode = file_inode(file);
@@ -391,6 +439,14 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 	if (fc->no_flush)
 		return 0;
 
+	err = filemap_write_and_wait(file->f_mapping);
+	if (err)
+		return err;
+
+	mutex_lock(&inode->i_mutex);
+	fuse_sync_writes(inode);
+	mutex_unlock(&inode->i_mutex);
+
 	req = fuse_get_req_nofail_nopages(fc, file);
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
@@ -411,21 +467,6 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 	return err;
 }
 
-/*
- * Wait for all pending writepages on the inode to finish.
- *
- * This is currently done by blocking further writes with FUSE_NOWRITE
- * and waiting for all sent writes to complete.
- *
- * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
- * could conflict with truncation.
- */
-static void fuse_sync_writes(struct inode *inode)
-{
-	fuse_set_nowrite(inode);
-	fuse_release_nowrite(inode);
-}
-
 int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 		      int datasync, int isdir)
 {
@@ -459,6 +500,12 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 
 	fuse_sync_writes(inode);
 
+	if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) {
+		int err = fuse_flush_mtime(file, false);
+		if (err)
+			goto out;
+	}
+
 	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
@@ -655,7 +702,33 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
 	spin_unlock(&fc->lock);
 }
 
-static int fuse_readpage(struct file *file, struct page *page)
+static void fuse_short_read(struct fuse_req *req, struct inode *inode,
+			    u64 attr_ver)
+{
+	size_t num_read = req->out.args[0].size;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+
+	if (fc->writeback_cache) {
+		/*
+		 * A hole in a file. Some data after the hole are in page cache,
+		 * but have not reached the client fs yet. So, the hole is not
+		 * present there.
+		 */
+		int i;
+		int start_idx = num_read >> PAGE_CACHE_SHIFT;
+		size_t off = num_read & (PAGE_CACHE_SIZE - 1);
+
+		for (i = start_idx; i < req->num_pages; i++) {
+			zero_user_segment(req->pages[i], off, PAGE_CACHE_SIZE);
+			off = 0;
+		}
+	} else {
+		loff_t pos = page_offset(req->pages[0]) + num_read;
+		fuse_read_update_size(inode, pos, attr_ver);
+	}
+}
+
+static int fuse_do_readpage(struct file *file, struct page *page)
 {
 	struct fuse_io_priv io = { .async = 0, .file = file };
 	struct inode *inode = page->mapping->host;
@@ -667,10 +740,6 @@ static int fuse_readpage(struct file *file, struct page *page)
 	u64 attr_ver;
 	int err;
 
-	err = -EIO;
-	if (is_bad_inode(inode))
-		goto out;
-
 	/*
 	 * Page writeback can extend beyond the lifetime of the
 	 * page-cache page, so make sure we read a properly synced
@@ -679,9 +748,8 @@ static int fuse_readpage(struct file *file, struct page *page)
 	fuse_wait_on_page_writeback(inode, page->index);
 
 	req = fuse_get_req(fc, 1);
-	err = PTR_ERR(req);
 	if (IS_ERR(req))
-		goto out;
+		return PTR_ERR(req);
 
 	attr_ver = fuse_get_attr_version(fc);
 
@@ -692,18 +760,32 @@ static int fuse_readpage(struct file *file, struct page *page)
 	req->page_descs[0].length = count;
 	num_read = fuse_send_read(req, &io, pos, count, NULL);
 	err = req->out.h.error;
-	fuse_put_request(fc, req);
 
 	if (!err) {
 		/*
 		 * Short read means EOF.  If file size is larger, truncate it
 		 */
 		if (num_read < count)
-			fuse_read_update_size(inode, pos + num_read, attr_ver);
+			fuse_short_read(req, inode, attr_ver);
 
 		SetPageUptodate(page);
 	}
 
+	fuse_put_request(fc, req);
+
+	return err;
+}
+
+static int fuse_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int err;
+
+	err = -EIO;
+	if (is_bad_inode(inode))
+		goto out;
+
+	err = fuse_do_readpage(file, page);
 	fuse_invalidate_atime(inode);
  out:
 	unlock_page(page);
@@ -726,13 +808,9 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
 		/*
 		 * Short read means EOF. If file size is larger, truncate it
 		 */
-		if (!req->out.h.error && num_read < count) {
-			loff_t pos;
+		if (!req->out.h.error && num_read < count)
+			fuse_short_read(req, inode, req->misc.read.attr_ver);
 
-			pos = page_offset(req->pages[0]) + num_read;
-			fuse_read_update_size(inode, pos,
-					      req->misc.read.attr_ver);
-		}
 		fuse_invalidate_atime(inode);
 	}
 
@@ -922,16 +1000,21 @@ static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
 	return req->misc.write.out.size;
 }
 
-void fuse_write_update_size(struct inode *inode, loff_t pos)
+bool fuse_write_update_size(struct inode *inode, loff_t pos)
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
+	bool ret = false;
 
 	spin_lock(&fc->lock);
 	fi->attr_version = ++fc->attr_version;
-	if (pos > inode->i_size)
+	if (pos > inode->i_size) {
 		i_size_write(inode, pos);
+		ret = true;
+	}
 	spin_unlock(&fc->lock);
+
+	return ret;
 }
 
 static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
@@ -1116,6 +1199,9 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	struct iov_iter i;
 	loff_t endbyte = 0;
 
+	if (get_fuse_conn(inode)->writeback_cache)
+		return generic_file_aio_write(iocb, iov, nr_segs, pos);
+
 	WARN_ON(iocb->ki_pos != pos);
 
 	ocount = 0;
@@ -1289,13 +1375,18 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p)
 
 ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
 		       unsigned long nr_segs, size_t count, loff_t *ppos,
-		       int write)
+		       int flags)
 {
+	int write = flags & FUSE_DIO_WRITE;
+	int cuse = flags & FUSE_DIO_CUSE;
 	struct file *file = io->file;
+	struct inode *inode = file->f_mapping->host;
 	struct fuse_file *ff = file->private_data;
 	struct fuse_conn *fc = ff->fc;
 	size_t nmax = write ? fc->max_write : fc->max_read;
 	loff_t pos = *ppos;
+	pgoff_t idx_from = pos >> PAGE_CACHE_SHIFT;
+	pgoff_t idx_to = (pos + count - 1) >> PAGE_CACHE_SHIFT;
 	ssize_t res = 0;
 	struct fuse_req *req;
 	struct iov_iter ii;
@@ -1309,6 +1400,14 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
+	if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) {
+		if (!write)
+			mutex_lock(&inode->i_mutex);
+		fuse_sync_writes(inode);
+		if (!write)
+			mutex_unlock(&inode->i_mutex);
+	}
+
 	while (count) {
 		size_t nres;
 		fl_owner_t owner = current->files;
@@ -1397,7 +1496,8 @@ static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
 
 	res = generic_write_checks(file, ppos, &count, 0);
 	if (!res)
-		res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1);
+		res = fuse_direct_io(io, iov, nr_segs, count, ppos,
+				     FUSE_DIO_WRITE);
 
 	fuse_invalidate_attr(inode);
 
@@ -1885,6 +1985,56 @@ out:
 	return err;
 }
 
+/*
+ * It's worthy to make sure that space is reserved on disk for the write,
+ * but how to implement it without killing performance need more thinking.
+ */
+static int fuse_write_begin(struct file *file, struct address_space *mapping,
+		loff_t pos, unsigned len, unsigned flags,
+		struct page **pagep, void **fsdata)
+{
+	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+	struct fuse_conn *fc = get_fuse_conn(file->f_dentry->d_inode);
+	struct page *page;
+
+	BUG_ON(!fc->writeback_cache);
+
+	page = grab_cache_page_write_begin(mapping, index, flags);
+	if (!page)
+		return -ENOMEM;
+
+	fuse_wait_on_page_writeback(mapping->host, page->index);
+
+	if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) {
+		int err = fuse_do_readpage(file, page);
+		if (err) {
+			unlock_page(page);
+			page_cache_release(page);
+			return err;
+		}
+	}
+	*pagep = page;
+
+	return 0;
+}
+
+static int fuse_write_end(struct file *file, struct address_space *mapping,
+		loff_t pos, unsigned len, unsigned copied,
+		struct page *page, void *fsdata)
+{
+	struct inode *inode = page->mapping->host;
+
+	if (!PageUptodate(page))
+		SetPageUptodate(page);
+
+	fuse_write_update_size(inode, pos + copied);
+	set_page_dirty(page);
+	unlock_page(page);
+	page_cache_release(page);
+
+	return copied;
+}
+
 static int fuse_launder_page(struct page *page)
 {
 	int err = 0;
@@ -1940,26 +2090,16 @@ static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 static const struct vm_operations_struct fuse_file_vm_ops = {
 	.close		= fuse_vma_close,
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite	= fuse_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
 
 static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
-		struct inode *inode = file_inode(file);
-		struct fuse_conn *fc = get_fuse_conn(inode);
-		struct fuse_inode *fi = get_fuse_inode(inode);
-		struct fuse_file *ff = file->private_data;
-		/*
-		 * file may be written through mmap, so chain it onto the
-		 * inodes's write_file list
-		 */
-		spin_lock(&fc->lock);
-		if (list_empty(&ff->write_entry))
-			list_add(&ff->write_entry, &fi->write_files);
-		spin_unlock(&fc->lock);
-	}
+	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+		fuse_link_write_file(file);
+
 	file_accessed(file);
 	vma->vm_ops = &fuse_file_vm_ops;
 	return 0;
@@ -2850,8 +2990,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 		goto out;
 
 	/* we could have extended the file */
-	if (!(mode & FALLOC_FL_KEEP_SIZE))
-		fuse_write_update_size(inode, offset + length);
+	if (!(mode & FALLOC_FL_KEEP_SIZE)) {
+		bool changed = fuse_write_update_size(inode, offset + length);
+
+		if (changed && fc->writeback_cache) {
+			struct fuse_inode *fi = get_fuse_inode(inode);
+
+			inode->i_mtime = current_fs_time(inode->i_sb);
+			set_bit(FUSE_I_MTIME_DIRTY, &fi->state);
+		}
+	}
 
 	if (mode & FALLOC_FL_PUNCH_HOLE)
 		truncate_pagecache_range(inode, offset, offset + length - 1);
@@ -2915,6 +3063,8 @@ static const struct address_space_operations fuse_file_aops  = {
 	.set_page_dirty	= __set_page_dirty_nobuffers,
 	.bmap		= fuse_bmap,
 	.direct_IO	= fuse_direct_IO,
+	.write_begin	= fuse_write_begin,
+	.write_end	= fuse_write_end,
 };
 
 void fuse_init_file_inode(struct inode *inode)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 2da5db2c8bdb..a257ed8ebee6 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -119,6 +119,8 @@ enum {
 	FUSE_I_INIT_RDPLUS,
 	/** An operation changing file size is in progress  */
 	FUSE_I_SIZE_UNSTABLE,
+	/** i_mtime has been updated locally; a flush to userspace needed */
+	FUSE_I_MTIME_DIRTY,
 };
 
 struct fuse_conn;
@@ -480,6 +482,9 @@ struct fuse_conn {
 	/** Set if bdi is valid */
 	unsigned bdi_initialized:1;
 
+	/** write-back cache policy (default is write-through) */
+	unsigned writeback_cache:1;
+
 	/*
 	 * The following bitfields are only for optimization purposes
 	 * and hence races in setting them will not cause malfunction
@@ -863,9 +868,20 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
 
 int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 		 bool isdir);
+
+/**
+ * fuse_direct_io() flags
+ */
+
+/** If set, it is WRITE; otherwise - READ */
+#define FUSE_DIO_WRITE (1 << 0)
+
+/** CUSE pass fuse_direct_io() a file which f_mapping->host is not from FUSE */
+#define FUSE_DIO_CUSE  (1 << 1)
+
 ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
 		       unsigned long nr_segs, size_t count, loff_t *ppos,
-		       int write);
+		       int flags);
 long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 		   unsigned int flags);
 long fuse_ioctl_common(struct file *file, unsigned int cmd,
@@ -873,7 +889,9 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd,
 unsigned fuse_file_poll(struct file *file, poll_table *wait);
 int fuse_dev_release(struct inode *inode, struct file *file);
 
-void fuse_write_update_size(struct inode *inode, loff_t pos);
+bool fuse_write_update_size(struct inode *inode, loff_t pos);
+
+int fuse_flush_mtime(struct file *file, bool nofail);
 
 int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 		    struct file *file);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index d468643a68b2..b4bff1b15028 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -123,7 +123,7 @@ static void fuse_destroy_inode(struct inode *inode)
 
 static void fuse_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	if (inode->i_sb->s_flags & MS_ACTIVE) {
 		struct fuse_conn *fc = get_fuse_conn(inode);
@@ -170,8 +170,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
 	inode->i_blocks  = attr->blocks;
 	inode->i_atime.tv_sec   = attr->atime;
 	inode->i_atime.tv_nsec  = attr->atimensec;
-	inode->i_mtime.tv_sec   = attr->mtime;
-	inode->i_mtime.tv_nsec  = attr->mtimensec;
+	/* mtime from server may be stale due to local buffered write */
+	if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) {
+		inode->i_mtime.tv_sec   = attr->mtime;
+		inode->i_mtime.tv_nsec  = attr->mtimensec;
+	}
 	inode->i_ctime.tv_sec   = attr->ctime;
 	inode->i_ctime.tv_nsec  = attr->ctimensec;
 
@@ -197,6 +200,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
+	bool is_wb = fc->writeback_cache;
 	loff_t oldsize;
 	struct timespec old_mtime;
 
@@ -211,10 +215,16 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
 	fuse_change_attributes_common(inode, attr, attr_valid);
 
 	oldsize = inode->i_size;
-	i_size_write(inode, attr->size);
+	/*
+	 * In case of writeback_cache enabled, the cached writes beyond EOF
+	 * extend local i_size without keeping userspace server in sync. So,
+	 * attr->size coming from server can be stale. We cannot trust it.
+	 */
+	if (!is_wb || !S_ISREG(inode->i_mode))
+		i_size_write(inode, attr->size);
 	spin_unlock(&fc->lock);
 
-	if (S_ISREG(inode->i_mode)) {
+	if (!is_wb && S_ISREG(inode->i_mode)) {
 		bool inval = false;
 
 		if (oldsize != attr->size) {
@@ -243,6 +253,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
 {
 	inode->i_mode = attr->mode & S_IFMT;
 	inode->i_size = attr->size;
+	inode->i_mtime.tv_sec  = attr->mtime;
+	inode->i_mtime.tv_nsec = attr->mtimensec;
 	if (S_ISREG(inode->i_mode)) {
 		fuse_init_common(inode);
 		fuse_init_file_inode(inode);
@@ -289,7 +301,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
 		return NULL;
 
 	if ((inode->i_state & I_NEW)) {
-		inode->i_flags |= S_NOATIME|S_NOCMTIME;
+		inode->i_flags |= S_NOATIME;
+		if (!fc->writeback_cache || !S_ISREG(inode->i_mode))
+			inode->i_flags |= S_NOCMTIME;
 		inode->i_generation = generation;
 		inode->i_data.backing_dev_info = &fc->bdi;
 		fuse_init_inode(inode, attr);
@@ -873,6 +887,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 			}
 			if (arg->flags & FUSE_ASYNC_DIO)
 				fc->async_dio = 1;
+			if (arg->flags & FUSE_WRITEBACK_CACHE)
+				fc->writeback_cache = 1;
 		} else {
 			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
 			fc->no_lock = 1;
@@ -900,7 +916,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
 		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
 		FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
 		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
-		FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO;
+		FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
+		FUSE_WRITEBACK_CACHE;
 	req->in.h.opcode = FUSE_INIT;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(*arg);
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 49436fa7cd4f..ce62dcac90b6 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -21,6 +21,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/backing-dev.h>
 #include <linux/aio.h>
+#include <trace/events/writeback.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -230,13 +231,11 @@ static int gfs2_writepages(struct address_space *mapping,
 static int gfs2_write_jdata_pagevec(struct address_space *mapping,
 				    struct writeback_control *wbc,
 				    struct pagevec *pvec,
-				    int nr_pages, pgoff_t end)
+				    int nr_pages, pgoff_t end,
+				    pgoff_t *done_index)
 {
 	struct inode *inode = mapping->host;
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
-	loff_t i_size = i_size_read(inode);
-	pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
-	unsigned offset = i_size & (PAGE_CACHE_SIZE-1);
 	unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize);
 	int i;
 	int ret;
@@ -248,40 +247,83 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
 	for(i = 0; i < nr_pages; i++) {
 		struct page *page = pvec->pages[i];
 
+		/*
+		 * At this point, the page may be truncated or
+		 * invalidated (changing page->mapping to NULL), or
+		 * even swizzled back from swapper_space to tmpfs file
+		 * mapping. However, page->index will not change
+		 * because we have a reference on the page.
+		 */
+		if (page->index > end) {
+			/*
+			 * can't be range_cyclic (1st pass) because
+			 * end == -1 in that case.
+			 */
+			ret = 1;
+			break;
+		}
+
+		*done_index = page->index;
+
 		lock_page(page);
 
 		if (unlikely(page->mapping != mapping)) {
+continue_unlock:
 			unlock_page(page);
 			continue;
 		}
 
-		if (!wbc->range_cyclic && page->index > end) {
-			ret = 1;
-			unlock_page(page);
-			continue;
+		if (!PageDirty(page)) {
+			/* someone wrote it for us */
+			goto continue_unlock;
 		}
 
-		if (wbc->sync_mode != WB_SYNC_NONE)
-			wait_on_page_writeback(page);
-
-		if (PageWriteback(page) ||
-		    !clear_page_dirty_for_io(page)) {
-			unlock_page(page);
-			continue;
+		if (PageWriteback(page)) {
+			if (wbc->sync_mode != WB_SYNC_NONE)
+				wait_on_page_writeback(page);
+			else
+				goto continue_unlock;
 		}
 
-		/* Is the page fully outside i_size? (truncate in progress) */
-		if (page->index > end_index || (page->index == end_index && !offset)) {
-			page->mapping->a_ops->invalidatepage(page, 0,
-							     PAGE_CACHE_SIZE);
-			unlock_page(page);
-			continue;
-		}
+		BUG_ON(PageWriteback(page));
+		if (!clear_page_dirty_for_io(page))
+			goto continue_unlock;
+
+		trace_wbc_writepage(wbc, mapping->backing_dev_info);
 
 		ret = __gfs2_jdata_writepage(page, wbc);
+		if (unlikely(ret)) {
+			if (ret == AOP_WRITEPAGE_ACTIVATE) {
+				unlock_page(page);
+				ret = 0;
+			} else {
+
+				/*
+				 * done_index is set past this page,
+				 * so media errors will not choke
+				 * background writeout for the entire
+				 * file. This has consequences for
+				 * range_cyclic semantics (ie. it may
+				 * not be suitable for data integrity
+				 * writeout).
+				 */
+				*done_index = page->index + 1;
+				ret = 1;
+				break;
+			}
+		}
 
-		if (ret || (--(wbc->nr_to_write) <= 0))
+		/*
+		 * We stop writing back only if we are not doing
+		 * integrity sync. In case of integrity sync we have to
+		 * keep going until we have written all the pages
+		 * we tagged for writeback prior to entering this loop.
+		 */
+		if (--wbc->nr_to_write <= 0 && wbc->sync_mode == WB_SYNC_NONE) {
 			ret = 1;
+			break;
+		}
+
 	}
 	gfs2_trans_end(sdp);
 	return ret;
@@ -306,51 +348,69 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
 	int done = 0;
 	struct pagevec pvec;
 	int nr_pages;
+	pgoff_t uninitialized_var(writeback_index);
 	pgoff_t index;
 	pgoff_t end;
-	int scanned = 0;
+	pgoff_t done_index;
+	int cycled;
 	int range_whole = 0;
+	int tag;
 
 	pagevec_init(&pvec, 0);
 	if (wbc->range_cyclic) {
-		index = mapping->writeback_index; /* Start from prev offset */
+		writeback_index = mapping->writeback_index; /* prev offset */
+		index = writeback_index;
+		if (index == 0)
+			cycled = 1;
+		else
+			cycled = 0;
 		end = -1;
 	} else {
 		index = wbc->range_start >> PAGE_CACHE_SHIFT;
 		end = wbc->range_end >> PAGE_CACHE_SHIFT;
 		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
 			range_whole = 1;
-		scanned = 1;
+		cycled = 1; /* ignore range_cyclic tests */
 	}
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+		tag = PAGECACHE_TAG_TOWRITE;
+	else
+		tag = PAGECACHE_TAG_DIRTY;
 
 retry:
-	 while (!done && (index <= end) &&
-		(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
-					       PAGECACHE_TAG_DIRTY,
-					       min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
-		scanned = 1;
-		ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end);
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+		tag_pages_for_writeback(mapping, index, end);
+	done_index = index;
+	while (!done && (index <= end)) {
+		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
+			      min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+		if (nr_pages == 0)
+			break;
+
+		ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end, &done_index);
 		if (ret)
 			done = 1;
 		if (ret > 0)
 			ret = 0;
-
 		pagevec_release(&pvec);
 		cond_resched();
 	}
 
-	if (!scanned && !done) {
+	if (!cycled && !done) {
 		/*
+		 * range_cyclic:
 		 * We hit the last page and there is more work to be done: wrap
 		 * back to the start of the file
 		 */
-		scanned = 1;
+		cycled = 1;
 		index = 0;
+		end = writeback_index - 1;
 		goto retry;
 	}
 
 	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
-		mapping->writeback_index = index;
+		mapping->writeback_index = done_index;
+
 	return ret;
 }
 
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index fa32655449c8..ffcfdd18d485 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1684,6 +1684,14 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
 	return 0;
 }
 
+static u16 gfs2_inode_ra_len(const struct gfs2_inode *ip)
+{
+	u64 where = ip->i_no_addr + 1;
+	if (ip->i_eattr == where)
+		return 1;
+	return 0;
+}
+
 /**
  * gfs2_dir_add - Add new filename into directory
  * @inode: The directory inode
@@ -1721,6 +1729,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
 			dent = gfs2_init_dirent(inode, dent, name, bh);
 			gfs2_inum_out(nip, dent);
 			dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode));
+			dent->de_rahead = cpu_to_be16(gfs2_inode_ra_len(nip));
 			tv = CURRENT_TIME;
 			if (ip->i_diskflags & GFS2_DIF_EXHASH) {
 				leaf = (struct gfs2_leaf *)bh->b_data;
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index efc078f0ee4e..80d67253623c 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -494,6 +494,7 @@ out:
 
 static const struct vm_operations_struct gfs2_vm_ops = {
 	.fault = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = gfs2_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
@@ -811,6 +812,8 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
 	loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1);
 	loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
 	loff_t max_chunk_size = UINT_MAX & bsize_mask;
+	struct gfs2_holder gh;
+
 	next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
 
 	/* We only support the FALLOC_FL_KEEP_SIZE mode */
@@ -831,8 +834,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
 	if (error)
 		return error;
 
-	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
-	error = gfs2_glock_nq(&ip->i_gh);
+	mutex_lock(&inode->i_mutex);
+
+	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+	error = gfs2_glock_nq(&gh);
 	if (unlikely(error))
 		goto out_uninit;
 
@@ -900,9 +905,10 @@ out_trans_fail:
 out_qunlock:
 	gfs2_quota_unlock(ip);
 out_unlock:
-	gfs2_glock_dq(&ip->i_gh);
+	gfs2_glock_dq(&gh);
 out_uninit:
-	gfs2_holder_uninit(&ip->i_gh);
+	gfs2_holder_uninit(&gh);
+	mutex_unlock(&inode->i_mutex);
 	return error;
 }
 
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 3bf0631b5d56..54b66809e818 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -82,6 +82,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	struct gfs2_trans tr;
 
 	memset(&tr, 0, sizeof(tr));
+	INIT_LIST_HEAD(&tr.tr_buf);
+	INIT_LIST_HEAD(&tr.tr_databuf);
 	tr.tr_revokes = atomic_read(&gl->gl_ail_count);
 
 	if (!tr.tr_revokes)
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index cf0e34400f71..d0c3928b2dea 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -52,7 +52,7 @@ struct gfs2_log_header_host {
  */
 
 struct gfs2_log_operations {
-	void (*lo_before_commit) (struct gfs2_sbd *sdp);
+	void (*lo_before_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
 	void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
 	void (*lo_before_scan) (struct gfs2_jdesc *jd,
 				struct gfs2_log_header_host *head, int pass);
@@ -462,11 +462,11 @@ struct gfs2_trans {
 	unsigned int tr_blocks;
 	unsigned int tr_revokes;
 	unsigned int tr_reserved;
+	unsigned int tr_touched:1;
+	unsigned int tr_attached:1;
 
 	struct gfs2_holder tr_t_gh;
 
-	int tr_touched;
-	int tr_attached;
 
 	unsigned int tr_num_buf_new;
 	unsigned int tr_num_databuf_new;
@@ -476,6 +476,8 @@ struct gfs2_trans {
 	unsigned int tr_num_revoke_rm;
 
 	struct list_head tr_list;
+	struct list_head tr_databuf;
+	struct list_head tr_buf;
 
 	unsigned int tr_first;
 	struct list_head tr_ail1_list;
@@ -746,19 +748,12 @@ struct gfs2_sbd {
 
 	struct gfs2_trans *sd_log_tr;
 	unsigned int sd_log_blks_reserved;
-	unsigned int sd_log_commited_buf;
-	unsigned int sd_log_commited_databuf;
 	int sd_log_commited_revoke;
 
 	atomic_t sd_log_pinned;
-	unsigned int sd_log_num_buf;
 	unsigned int sd_log_num_revoke;
-	unsigned int sd_log_num_rg;
-	unsigned int sd_log_num_databuf;
 
-	struct list_head sd_log_le_buf;
 	struct list_head sd_log_le_revoke;
-	struct list_head sd_log_le_databuf;
 	struct list_head sd_log_le_ordered;
 	spinlock_t sd_ordered_lock;
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 5c524180c98e..ec455b92091f 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -376,12 +376,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip,
 		inode->i_gid = current_fsgid();
 }
 
-static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
+static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-	struct gfs2_alloc_parms ap = { .target = RES_DINODE, .aflags = flags, };
+	struct gfs2_alloc_parms ap = { .target = *dblocks, .aflags = flags, };
 	int error;
-	int dblocks = 1;
 
 	error = gfs2_quota_lock_check(ip);
 	if (error)
@@ -391,11 +390,11 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 	if (error)
 		goto out_quota;
 
-	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 0);
+	error = gfs2_trans_begin(sdp, (*dblocks * RES_RG_BIT) + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipreserv;
 
-	error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation);
+	error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
 	ip->i_no_formal_ino = ip->i_generation;
 	ip->i_inode.i_ino = ip->i_no_addr;
 	ip->i_goal = ip->i_no_addr;
@@ -428,6 +427,33 @@ static void gfs2_init_dir(struct buffer_head *dibh,
 }
 
 /**
+ * gfs2_init_xattr - Initialise an xattr block for a new inode
+ * @ip: The inode in question
+ *
+ * This sets up an empty xattr block for a new inode, ready to
+ * take any ACLs, LSM xattrs, etc.
+ */
+
+static void gfs2_init_xattr(struct gfs2_inode *ip)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	struct buffer_head *bh;
+	struct gfs2_ea_header *ea;
+
+	bh = gfs2_meta_new(ip->i_gl, ip->i_eattr);
+	gfs2_trans_add_meta(ip->i_gl, bh);
+	gfs2_metatype_set(bh, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
+	gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
+
+	ea = GFS2_EA_BH2FIRST(bh);
+	ea->ea_rec_len = cpu_to_be32(sdp->sd_jbsize);
+	ea->ea_type = GFS2_EATYPE_UNUSED;
+	ea->ea_flags = GFS2_EAFLAG_LAST;
+
+	brelse(bh);
+}
+
+/**
  * init_dinode - Fill in a new dinode structure
  * @dip: The directory this inode is being created in
  * @ip: The inode
@@ -580,6 +606,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	struct dentry *d;
 	int error;
 	u32 aflags = 0;
+	unsigned blocks = 1;
 	struct gfs2_diradd da = { .bh = NULL, };
 
 	if (!name->len || name->len > GFS2_FNAMESIZE)
@@ -676,10 +703,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	    (dip->i_diskflags & GFS2_DIF_TOPDIR))
 		aflags |= GFS2_AF_ORLOV;
 
-	error = alloc_dinode(ip, aflags);
+	if (default_acl || acl)
+		blocks++;
+
+	error = alloc_dinode(ip, aflags, &blocks);
 	if (error)
 		goto fail_free_inode;
 
+	gfs2_set_inode_blocks(inode, blocks);
+
 	error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
 	if (error)
 		goto fail_free_inode;
@@ -689,10 +721,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		goto fail_free_inode;
 
-	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
+	error = gfs2_trans_begin(sdp, blocks, 0);
 	if (error)
 		goto fail_gunlock2;
 
+	if (blocks > 1) {
+		ip->i_eattr = ip->i_no_addr + 1;
+		gfs2_init_xattr(ip);
+	}
 	init_dinode(dip, ip, symname);
 	gfs2_trans_end(sdp);
 
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 2a6ba06bee6f..6b97d98919a6 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -1102,7 +1102,7 @@ static void gdlm_recover_slot(void *arg, struct dlm_slot *slot)
 	}
 
 	if (ls->ls_recover_submit[jid]) {
-		fs_info(sdp, "recover_slot jid %d gen %u prev %u",
+		fs_info(sdp, "recover_slot jid %d gen %u prev %u\n",
 			jid, ls->ls_recover_block, ls->ls_recover_submit[jid]);
 	}
 	ls->ls_recover_submit[jid] = ls->ls_recover_block;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 9dcb9777a5f8..edbd46113c28 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -18,6 +18,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/bio.h>
+#include <linux/blkdev.h>
 #include <linux/writeback.h>
 #include <linux/list_sort.h>
 
@@ -145,8 +146,10 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
 {
 	struct list_head *head = &sdp->sd_ail1_list;
 	struct gfs2_trans *tr;
+	struct blk_plug plug;
 
 	trace_gfs2_ail_flush(sdp, wbc, 1);
+	blk_start_plug(&plug);
 	spin_lock(&sdp->sd_ail_lock);
 restart:
 	list_for_each_entry_reverse(tr, head, tr_list) {
@@ -156,6 +159,7 @@ restart:
 			goto restart;
 	}
 	spin_unlock(&sdp->sd_ail_lock);
+	blk_finish_plug(&plug);
 	trace_gfs2_ail_flush(sdp, wbc, 0);
 }
 
@@ -410,24 +414,22 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
 static unsigned int calc_reserved(struct gfs2_sbd *sdp)
 {
 	unsigned int reserved = 0;
-	unsigned int mbuf_limit, metabufhdrs_needed;
-	unsigned int dbuf_limit, databufhdrs_needed;
-	unsigned int revokes = 0;
+	unsigned int mbuf;
+	unsigned int dbuf;
+	struct gfs2_trans *tr = sdp->sd_log_tr;
 
-	mbuf_limit = buf_limit(sdp);
-	metabufhdrs_needed = (sdp->sd_log_commited_buf +
-			      (mbuf_limit - 1)) / mbuf_limit;
-	dbuf_limit = databuf_limit(sdp);
-	databufhdrs_needed = (sdp->sd_log_commited_databuf +
-			      (dbuf_limit - 1)) / dbuf_limit;
+	if (tr) {
+		mbuf = tr->tr_num_buf_new - tr->tr_num_buf_rm;
+		dbuf = tr->tr_num_databuf_new - tr->tr_num_databuf_rm;
+		reserved = mbuf + dbuf;
+		/* Account for header blocks */
+		reserved += DIV_ROUND_UP(mbuf, buf_limit(sdp));
+		reserved += DIV_ROUND_UP(dbuf, databuf_limit(sdp));
+	}
 
 	if (sdp->sd_log_commited_revoke > 0)
-		revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
+		reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
 					  sizeof(u64));
-
-	reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
-		sdp->sd_log_commited_databuf + databufhdrs_needed +
-		revokes;
 	/* One for the overall header */
 	if (reserved)
 		reserved++;
@@ -682,33 +684,21 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
 	}
 	trace_gfs2_log_flush(sdp, 1);
 
+	sdp->sd_log_flush_head = sdp->sd_log_head;
+	sdp->sd_log_flush_wrapped = 0;
 	tr = sdp->sd_log_tr;
 	if (tr) {
 		sdp->sd_log_tr = NULL;
 		INIT_LIST_HEAD(&tr->tr_ail1_list);
 		INIT_LIST_HEAD(&tr->tr_ail2_list);
+		tr->tr_first = sdp->sd_log_flush_head;
 	}
 
-	if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) {
-		printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf,
-		       sdp->sd_log_commited_buf);
-		gfs2_assert_withdraw(sdp, 0);
-	}
-	if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) {
-		printk(KERN_INFO "GFS2: log databuf %u %u\n",
-		       sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf);
-		gfs2_assert_withdraw(sdp, 0);
-	}
 	gfs2_assert_withdraw(sdp,
 			sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
 
-	sdp->sd_log_flush_head = sdp->sd_log_head;
-	sdp->sd_log_flush_wrapped = 0;
-	if (tr)
-		tr->tr_first = sdp->sd_log_flush_head;
-
 	gfs2_ordered_write(sdp);
-	lops_before_commit(sdp);
+	lops_before_commit(sdp, tr);
 	gfs2_log_flush_bio(sdp, WRITE);
 
 	if (sdp->sd_log_head != sdp->sd_log_flush_head) {
@@ -723,8 +713,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
 	gfs2_log_lock(sdp);
 	sdp->sd_log_head = sdp->sd_log_flush_head;
 	sdp->sd_log_blks_reserved = 0;
-	sdp->sd_log_commited_buf = 0;
-	sdp->sd_log_commited_databuf = 0;
 	sdp->sd_log_commited_revoke = 0;
 
 	spin_lock(&sdp->sd_ail_lock);
@@ -740,34 +728,54 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
 	kfree(tr);
 }
 
+/**
+ * gfs2_merge_trans - Merge a new transaction into a cached transaction
+ * @old: Original transaction to be expanded
+ * @new: New transaction to be merged
+ */
+
+static void gfs2_merge_trans(struct gfs2_trans *old, struct gfs2_trans *new)
+{
+	WARN_ON_ONCE(old->tr_attached != 1);
+
+	old->tr_num_buf_new	+= new->tr_num_buf_new;
+	old->tr_num_databuf_new	+= new->tr_num_databuf_new;
+	old->tr_num_buf_rm	+= new->tr_num_buf_rm;
+	old->tr_num_databuf_rm	+= new->tr_num_databuf_rm;
+	old->tr_num_revoke	+= new->tr_num_revoke;
+	old->tr_num_revoke_rm	+= new->tr_num_revoke_rm;
+
+	list_splice_tail_init(&new->tr_databuf, &old->tr_databuf);
+	list_splice_tail_init(&new->tr_buf, &old->tr_buf);
+}
+
 static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
 	unsigned int reserved;
 	unsigned int unused;
+	unsigned int maxres;
 
 	gfs2_log_lock(sdp);
 
-	sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
-	sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
-		tr->tr_num_databuf_rm;
-	gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
-			     (((int)sdp->sd_log_commited_databuf) >= 0));
+	if (sdp->sd_log_tr) {
+		gfs2_merge_trans(sdp->sd_log_tr, tr);
+	} else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) {
+		gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
+		sdp->sd_log_tr = tr;
+		tr->tr_attached = 1;
+	}
+
 	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
 	reserved = calc_reserved(sdp);
-	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
-	unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
+	maxres = sdp->sd_log_blks_reserved + tr->tr_reserved;
+	gfs2_assert_withdraw(sdp, maxres >= reserved);
+	unused = maxres - reserved;
 	atomic_add(unused, &sdp->sd_log_blks_free);
 	trace_gfs2_log_blocks(sdp, unused);
 	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
 			     sdp->sd_jdesc->jd_blocks);
 	sdp->sd_log_blks_reserved = reserved;
 
-	if (sdp->sd_log_tr == NULL &&
-	    (tr->tr_num_buf_new || tr->tr_num_databuf_new)) {
-		gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
-		sdp->sd_log_tr = tr;
-		tr->tr_attached = 1;
-	}
 	gfs2_log_unlock(sdp);
 }
 
@@ -807,10 +815,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
 	down_write(&sdp->sd_log_flush_lock);
 
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
-	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
-	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
-	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
 	gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 76693793cedd..23c6e72f5164 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -491,32 +491,30 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
 	gfs2_log_unlock(sdp);
 }
 
-static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+static void buf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
 	unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */
-
-	gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf,
-			   &sdp->sd_log_le_buf, 0);
+	unsigned int nbuf;
+	if (tr == NULL)
+		return;
+	nbuf = tr->tr_num_buf_new - tr->tr_num_buf_rm;
+	gfs2_before_commit(sdp, limit, nbuf, &tr->tr_buf, 0);
 }
 
 static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	struct list_head *head = &sdp->sd_log_le_buf;
+	struct list_head *head;
 	struct gfs2_bufdata *bd;
 
-	if (tr == NULL) {
-		gfs2_assert(sdp, list_empty(head));
+	if (tr == NULL)
 		return;
-	}
 
+	head = &tr->tr_buf;
 	while (!list_empty(head)) {
 		bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
 		list_del_init(&bd->bd_list);
-		sdp->sd_log_num_buf--;
-
 		gfs2_unpin(sdp, bd->bd_bh, tr);
 	}
-	gfs2_assert_warn(sdp, !sdp->sd_log_num_buf);
 }
 
 static void buf_lo_before_scan(struct gfs2_jdesc *jd,
@@ -620,7 +618,7 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
 	        jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
 }
 
-static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
+static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
 	struct gfs2_meta_header *mh;
 	unsigned int offset;
@@ -760,12 +758,14 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
  *
  */
 
-static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
+static void databuf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	unsigned int limit = buf_limit(sdp) / 2;
-
-	gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf,
-			   &sdp->sd_log_le_databuf, 1);
+	unsigned int limit = databuf_limit(sdp);
+	unsigned int nbuf;
+	if (tr == NULL)
+		return;
+	nbuf = tr->tr_num_databuf_new - tr->tr_num_databuf_rm;
+	gfs2_before_commit(sdp, limit, nbuf, &tr->tr_databuf, 1);
 }
 
 static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
@@ -840,21 +840,18 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
 
 static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	struct list_head *head = &sdp->sd_log_le_databuf;
+	struct list_head *head;
 	struct gfs2_bufdata *bd;
 
-	if (tr == NULL) {
-		gfs2_assert(sdp, list_empty(head));
+	if (tr == NULL)
 		return;
-	}
 
+	head = &tr->tr_databuf;
 	while (!list_empty(head)) {
 		bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
 		list_del_init(&bd->bd_list);
-		sdp->sd_log_num_databuf--;
 		gfs2_unpin(sdp, bd->bd_bh, tr);
 	}
-	gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf);
 }
 
 
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 9ca2e6438419..a65a7ba32ffd 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -46,12 +46,13 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
 	return limit;
 }
 
-static inline void lops_before_commit(struct gfs2_sbd *sdp)
+static inline void lops_before_commit(struct gfs2_sbd *sdp,
+				      struct gfs2_trans *tr)
 {
 	int x;
 	for (x = 0; gfs2_log_ops[x]; x++)
 		if (gfs2_log_ops[x]->lo_before_commit)
-			gfs2_log_ops[x]->lo_before_commit(sdp);
+			gfs2_log_ops[x]->lo_before_commit(sdp, tr);
 }
 
 static inline void lops_after_commit(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index c7f24690ed05..005e4686af0d 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -267,15 +267,10 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
 		trace_gfs2_pin(bd, 0);
 		atomic_dec(&sdp->sd_log_pinned);
 		list_del_init(&bd->bd_list);
-		if (meta) {
-			gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
-			sdp->sd_log_num_buf--;
+		if (meta)
 			tr->tr_num_buf_rm++;
-		} else {
-			gfs2_assert_warn(sdp, sdp->sd_log_num_databuf);
-			sdp->sd_log_num_databuf--;
+		else
 			tr->tr_num_databuf_rm++;
-		}
 		tr->tr_touched = 1;
 		was_pinned = 1;
 		brelse(bh);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index c6872d09561a..1f855a74a4ec 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -114,9 +114,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
 	spin_lock_init(&sdp->sd_log_lock);
 	atomic_set(&sdp->sd_log_pinned, 0);
-	INIT_LIST_HEAD(&sdp->sd_log_le_buf);
 	INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
-	INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
 	INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
 	spin_lock_init(&sdp->sd_ordered_lock);
 
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 8bec0e3192dd..a5cccf694e3f 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1242,14 +1242,13 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
 	bm_size = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * sizeof(unsigned long));
 	bm_size *= sizeof(unsigned long);
 	error = -ENOMEM;
-	sdp->sd_quota_bitmap = kmalloc(bm_size, GFP_NOFS|__GFP_NOWARN);
+	sdp->sd_quota_bitmap = kzalloc(bm_size, GFP_NOFS | __GFP_NOWARN);
 	if (sdp->sd_quota_bitmap == NULL)
-		sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_NOFS, PAGE_KERNEL);
+		sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_NOFS |
+						 __GFP_ZERO, PAGE_KERNEL);
 	if (!sdp->sd_quota_bitmap)
 		return error;
 
-	memset(sdp->sd_quota_bitmap, 0, bm_size);
-
 	for (x = 0; x < blocks; x++) {
 		struct buffer_head *bh;
 		const struct gfs2_quota_change *qc;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index a1da21349235..f58574643d07 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1102,7 +1102,7 @@ static u32 count_unlinked(struct gfs2_rgrpd *rgd)
  * Returns: errno
  */
 
-int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
+static int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_glock *gl = rgd->rd_gl;
@@ -1169,7 +1169,7 @@ fail:
 	return error;
 }
 
-int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
+static int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
 {
 	u32 rl_flags;
 
@@ -2296,7 +2296,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
 
 	gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
 	if (dinode)
-		gfs2_trans_add_unrevoke(sdp, block, 1);
+		gfs2_trans_add_unrevoke(sdp, block, *nblocks);
 
 	gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid);
 
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 60f60f6181f3..24410cd9a82a 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1558,7 +1558,7 @@ out_unlock:
 		fs_warn(sdp, "gfs2_evict_inode: %d\n", error);
 out:
 	/* Case 3 starts here */
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	gfs2_rs_delete(ip, NULL);
 	gfs2_ordered_del_inode(ip);
 	clear_inode(inode);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 2b20d7046bf3..295f400f35ab 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -51,6 +51,9 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
 	if (revokes)
 		tr->tr_reserved += gfs2_struct2blk(sdp, revokes,
 						   sizeof(u64));
+	INIT_LIST_HEAD(&tr->tr_databuf);
+	INIT_LIST_HEAD(&tr->tr_buf);
+
 	sb_start_intwrite(sdp->sd_vfs);
 	gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh);
 
@@ -98,7 +101,7 @@ static void gfs2_print_trans(const struct gfs2_trans *tr)
 {
 	printk(KERN_WARNING "GFS2: Transaction created at: %pSR\n",
 	       (void *)tr->tr_ip);
-	printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n",
+	printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%u\n",
 	       tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched);
 	printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n",
 	       tr->tr_num_buf_new, tr->tr_num_buf_rm,
@@ -210,8 +213,7 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
 		set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
 		gfs2_pin(sdp, bd->bd_bh);
 		tr->tr_num_databuf_new++;
-		sdp->sd_log_num_databuf++;
-		list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
+		list_add_tail(&bd->bd_list, &tr->tr_databuf);
 	}
 	gfs2_log_unlock(sdp);
 	unlock_buffer(bh);
@@ -238,8 +240,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 	gfs2_pin(sdp, bd->bd_bh);
 	mh->__pad0 = cpu_to_be64(0);
 	mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
-	sdp->sd_log_num_buf++;
-	list_add(&bd->bd_list, &sdp->sd_log_le_buf);
+	list_add(&bd->bd_list, &tr->tr_buf);
 	tr->tr_num_buf_new++;
 }
 
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 380ab31b5e0f..9e2fecd62f62 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -547,7 +547,7 @@ out:
 
 void hfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {
 		HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 968ce411db53..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,
@@ -103,6 +112,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry,
 		folder = &entry->folder;
 		memset(folder, 0, sizeof(*folder));
 		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
+		if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags))
+			folder->flags |= cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT);
 		folder->id = cpu_to_be32(inode->i_ino);
 		HFSPLUS_I(inode)->create_date =
 			folder->create_date =
@@ -165,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;
 }
 
@@ -181,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;
@@ -203,6 +219,36 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 	return hfs_brec_find(fd, hfs_find_rec_by_key);
 }
 
+static void hfsplus_subfolders_inc(struct inode *dir)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+
+	if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+		/*
+		 * Increment subfolder count. Note, the value is only meaningful
+		 * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set.
+		 */
+		HFSPLUS_I(dir)->subfolders++;
+	}
+}
+
+static void hfsplus_subfolders_dec(struct inode *dir)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+
+	if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+		/*
+		 * Decrement subfolder count. Note, the value is only meaningful
+		 * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set.
+		 *
+		 * Check for zero. Some subfolders may have been created
+		 * by an implementation ignorant of this counter.
+		 */
+		if (HFSPLUS_I(dir)->subfolders)
+			HFSPLUS_I(dir)->subfolders--;
+	}
+}
+
 int hfsplus_create_cat(u32 cnid, struct inode *dir,
 		struct qstr *str, struct inode *inode)
 {
@@ -218,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)
@@ -233,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) {
@@ -247,6 +301,8 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 		goto err1;
 
 	dir->i_size++;
+	if (S_ISDIR(inode->i_mode))
+		hfsplus_subfolders_inc(dir);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
 	hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
 
@@ -254,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:
@@ -279,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;
@@ -295,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)
@@ -326,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;
@@ -336,6 +394,8 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 		goto out;
 
 	dir->i_size--;
+	if (type == HFSPLUS_FOLDER)
+		hfsplus_subfolders_dec(dir);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
 	hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
 
@@ -369,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;
@@ -380,9 +444,14 @@ int hfsplus_rename_cat(u32 cnid,
 
 	hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
 				src_fd.entrylength);
+	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)
@@ -394,10 +463,16 @@ int hfsplus_rename_cat(u32 cnid,
 	if (err)
 		goto out;
 	dst_dir->i_size++;
+	if (type == HFSPLUS_FOLDER)
+		hfsplus_subfolders_inc(dst_dir);
 	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;
@@ -405,10 +480,12 @@ int hfsplus_rename_cat(u32 cnid,
 	if (err)
 		goto out;
 	src_dir->i_size--;
+	if (type == HFSPLUS_FOLDER)
+		hfsplus_subfolders_dec(src_dir);
 	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;
@@ -418,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/extents.c b/fs/hfsplus/extents.c
index fbb212fbb1ef..a7aafb35b624 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -227,10 +227,8 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
 	u32 ablock, dblock, mask;
 	sector_t sector;
 	int was_dirty = 0;
-	int shift;
 
 	/* Convert inode block to disk allocation block */
-	shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
 	ablock = iblock >> sbi->fs_shift;
 
 	if (iblock >= hip->fs_blocks) {
@@ -498,11 +496,13 @@ int hfsplus_file_extend(struct inode *inode)
 			goto insert_extent;
 	}
 out:
-	mutex_unlock(&hip->extents_lock);
 	if (!res) {
 		hip->alloc_blocks += len;
+		mutex_unlock(&hip->extents_lock);
 		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
+		return 0;
 	}
+	mutex_unlock(&hip->extents_lock);
 	return res;
 
 insert_extent:
@@ -556,11 +556,13 @@ void hfsplus_file_truncate(struct inode *inode)
 
 	blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >>
 			HFSPLUS_SB(sb)->alloc_blksz_shift;
+
+	mutex_lock(&hip->extents_lock);
+
 	alloc_cnt = hip->alloc_blocks;
 	if (blk_cnt == alloc_cnt)
-		goto out;
+		goto out_unlock;
 
-	mutex_lock(&hip->extents_lock);
 	res = hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
 	if (res) {
 		mutex_unlock(&hip->extents_lock);
@@ -592,10 +594,10 @@ void hfsplus_file_truncate(struct inode *inode)
 		hfs_brec_remove(&fd);
 	}
 	hfs_find_exit(&fd);
-	mutex_unlock(&hip->extents_lock);
 
 	hip->alloc_blocks = blk_cnt;
-out:
+out_unlock:
+	mutex_unlock(&hip->extents_lock);
 	hip->phys_size = inode->i_size;
 	hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >>
 		sb->s_blocksize_bits;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 08846425b67f..62ed970eaaca 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -242,6 +242,7 @@ struct hfsplus_inode_info {
 	 */
 	sector_t fs_blocks;
 	u8 userflags;		/* BSD user file flags */
+	u32 subfolders;		/* Subfolder count (HFSX only) */
 	struct list_head open_dir_list;
 	loff_t phys_size;
 
@@ -443,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/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 8ffb3a8ffe75..5a126828d85e 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -261,7 +261,7 @@ struct hfsplus_cat_folder {
 	struct DInfo user_info;
 	struct DXInfo finder_info;
 	__be32 text_encoding;
-	u32 reserved;
+	__be32 subfolders;	/* Subfolder count in HFSX. Reserved in HFS+. */
 } __packed;
 
 /* HFS file info (stolen from hfs.h) */
@@ -301,11 +301,13 @@ struct hfsplus_cat_file {
 	struct hfsplus_fork_raw rsrc_fork;
 } __packed;
 
-/* File attribute bits */
+/* File and folder flag bits */
 #define HFSPLUS_FILE_LOCKED		0x0001
 #define HFSPLUS_FILE_THREAD_EXISTS	0x0002
 #define HFSPLUS_XATTR_EXISTS		0x0004
 #define HFSPLUS_ACL_EXISTS		0x0008
+#define HFSPLUS_HAS_FOLDER_COUNT	0x0010	/* Folder has subfolder count
+						 * (HFSX only) */
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index fa929f325f87..a4f45bd88a63 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -375,6 +375,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
 	hip->extent_state = 0;
 	hip->flags = 0;
 	hip->userflags = 0;
+	hip->subfolders = 0;
 	memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
 	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
 	hip->alloc_blocks = 0;
@@ -494,6 +495,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 		inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
 		HFSPLUS_I(inode)->create_date = folder->create_date;
 		HFSPLUS_I(inode)->fs_blocks = 0;
+		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
+			HFSPLUS_I(inode)->subfolders =
+				be32_to_cpu(folder->subfolders);
+		}
 		inode->i_op = &hfsplus_dir_inode_operations;
 		inode->i_fop = &hfsplus_dir_operations;
 	} else if (type == HFSPLUS_FILE) {
@@ -566,6 +571,10 @@ int hfsplus_cat_write_inode(struct inode *inode)
 		folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
 		folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
 		folder->valence = cpu_to_be32(inode->i_size - 2);
+		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
+			folder->subfolders =
+				cpu_to_be32(HFSPLUS_I(inode)->subfolders);
+		}
 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
 					 sizeof(struct hfsplus_cat_folder));
 	} else if (HFSPLUS_IS_RSRC(inode)) {
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 968eab5bc1f5..68537e8b7a09 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -75,7 +75,7 @@ int hfsplus_parse_options_remount(char *input, int *force)
 	int token;
 
 	if (!input)
-		return 0;
+		return 1;
 
 	while ((p = strsep(&input, ",")) != NULL) {
 		if (!*p)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 80875aa640ef..dd6056a5a021 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -161,7 +161,7 @@ static int hfsplus_write_inode(struct inode *inode,
 static void hfsplus_evict_inode(struct inode *inode)
 {
 	hfs_dbg(INODE, "hfsplus_evict_inode: %lu\n", inode->i_ino);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	if (HFSPLUS_IS_RSRC(inode)) {
 		HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
@@ -513,7 +513,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/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index fe649d325b1f..9c470fde9878 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -230,7 +230,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
 
 static void hostfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	if (HOSTFS_I(inode)->fd != -1) {
 		close_file(&HOSTFS_I(inode)->fd);
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 9edeeb0ea97e..50a427313835 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -304,7 +304,7 @@ void hpfs_write_if_changed(struct inode *inode)
 
 void hpfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	if (!inode->i_nlink) {
 		hpfs_lock(inode->i_sb);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index d19b30ababf1..204027520937 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -366,7 +366,13 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
 
 static void hugetlbfs_evict_inode(struct inode *inode)
 {
+	struct resv_map *resv_map;
+
 	truncate_hugepages(inode, 0);
+	resv_map = (struct resv_map *)inode->i_mapping->private_data;
+	/* root inode doesn't have the resv_map, so we should check it */
+	if (resv_map)
+		resv_map_release(&resv_map->refs);
 	clear_inode(inode);
 }
 
@@ -476,6 +482,11 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
 					umode_t mode, dev_t dev)
 {
 	struct inode *inode;
+	struct resv_map *resv_map;
+
+	resv_map = resv_map_alloc();
+	if (!resv_map)
+		return NULL;
 
 	inode = new_inode(sb);
 	if (inode) {
@@ -487,7 +498,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
 		inode->i_mapping->a_ops = &hugetlbfs_aops;
 		inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		INIT_LIST_HEAD(&inode->i_mapping->private_list);
+		inode->i_mapping->private_data = resv_map;
 		info = HUGETLBFS_I(inode);
 		/*
 		 * The policy is initialized here even if we are creating a
@@ -517,7 +528,9 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
 			break;
 		}
 		lockdep_annotate_inode_mutex_key(inode);
-	}
+	} else
+		kref_put(&resv_map->refs, resv_map_release);
+
 	return inode;
 }
 
diff --git a/fs/inode.c b/fs/inode.c
index 4bcdad3c9361..e6905152c39f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -503,6 +503,7 @@ void clear_inode(struct inode *inode)
 	 */
 	spin_lock_irq(&inode->i_data.tree_lock);
 	BUG_ON(inode->i_data.nrpages);
+	BUG_ON(inode->i_data.nrshadows);
 	spin_unlock_irq(&inode->i_data.tree_lock);
 	BUG_ON(!list_empty(&inode->i_data.private_list));
 	BUG_ON(!(inode->i_state & I_FREEING));
@@ -548,8 +549,7 @@ static void evict(struct inode *inode)
 	if (op->evict_inode) {
 		op->evict_inode(inode);
 	} else {
-		if (inode->i_data.nrpages)
-			truncate_inode_pages(&inode->i_data, 0);
+		truncate_inode_pages_final(&inode->i_data);
 		clear_inode(inode);
 	}
 	if (S_ISBLK(inode->i_mode) && inode->i_bdev)
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 5fa344afb49a..244b6f6b7908 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(__jbd2_debug);
 #endif
 
 /* Checksumming functions */
-int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
+static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
 {
 	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
@@ -143,7 +143,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
 	return cpu_to_be32(csum);
 }
 
-int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
+static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
 {
 	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
@@ -151,7 +151,7 @@ int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
 	return sb->s_checksum == jbd2_superblock_csum(j, sb);
 }
 
-void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
+static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
 {
 	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 		return;
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 16a5047903a6..406d9cc84ba8 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -33,7 +33,7 @@ static int jffs2_rtime_compress(unsigned char *data_in,
 				unsigned char *cpage_out,
 				uint32_t *sourcelen, uint32_t *dstlen)
 {
-	short positions[256];
+	unsigned short positions[256];
 	int outpos = 0;
 	int pos=0;
 
@@ -74,7 +74,7 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
 				  unsigned char *cpage_out,
 				  uint32_t srclen, uint32_t destlen)
 {
-	short positions[256];
+	unsigned short positions[256];
 	int outpos = 0;
 	int pos=0;
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index a69e426435dd..601afd1afddf 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -242,7 +242,7 @@ void jffs2_evict_inode (struct inode *inode)
 
 	jffs2_dbg(1, "%s(): ino #%lu mode %o\n",
 		  __func__, inode->i_ino, inode->i_mode);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	jffs2_do_clear_inode(c, f);
 }
@@ -457,12 +457,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
 	   The umask is only applied if there's no default ACL */
 	ret = jffs2_init_acl_pre(dir_i, inode, &mode);
 	if (ret) {
-	    make_bad_inode(inode);
-	    iput(inode);
-	    return ERR_PTR(ret);
+		mutex_unlock(&f->sem);
+		make_bad_inode(inode);
+		iput(inode);
+		return ERR_PTR(ret);
 	}
 	ret = jffs2_do_new_inode (c, f, mode, ri);
 	if (ret) {
+		mutex_unlock(&f->sem);
 		make_bad_inode(inode);
 		iput(inode);
 		return ERR_PTR(ret);
@@ -479,6 +481,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
 	inode->i_size = 0;
 
 	if (insert_inode_locked(inode) < 0) {
+		mutex_unlock(&f->sem);
 		make_bad_inode(inode);
 		iput(inode);
 		return ERR_PTR(-EINVAL);
@@ -687,7 +690,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
 	struct inode *inode = OFNI_EDONI_2SFFJ(f);
 	struct page *pg;
 
-	pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
+	pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
 			     (void *)jffs2_do_readpage_unlock, inode);
 	if (IS_ERR(pg))
 		return (void *)pg;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index e4619b00f7c5..fa35ff79ab35 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -231,7 +231,7 @@ struct jffs2_tmp_dnode_info
 	uint32_t version;
 	uint32_t data_crc;
 	uint32_t partial_crc;
-	uint16_t csize;
+	uint32_t csize;
 	uint16_t overlapped;
 };
 
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 03310721712f..b6bd4affd9ad 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -179,6 +179,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
 					spin_unlock(&c->erase_completion_lock);
 
 					schedule();
+					remove_wait_queue(&c->erase_wait, &wait);
 				} else
 					spin_unlock(&c->erase_completion_lock);
 			} else if (ret)
@@ -211,20 +212,25 @@ out:
 int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
 			   uint32_t *len, uint32_t sumsize)
 {
-	int ret = -EAGAIN;
+	int ret;
 	minsize = PAD(minsize);
 
 	jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
 
-	spin_lock(&c->erase_completion_lock);
-	while(ret == -EAGAIN) {
+	while (true) {
+		spin_lock(&c->erase_completion_lock);
 		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
 		if (ret) {
 			jffs2_dbg(1, "%s(): looping, ret is %d\n",
 				  __func__, ret);
 		}
+		spin_unlock(&c->erase_completion_lock);
+
+		if (ret == -EAGAIN)
+			cond_resched();
+		else
+			break;
 	}
-	spin_unlock(&c->erase_completion_lock);
 	if (!ret)
 		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
 
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index f4aab719add5..6f8fe72c2a7a 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -154,7 +154,7 @@ void jfs_evict_inode(struct inode *inode)
 		dquot_initialize(inode);
 
 		if (JFS_IP(inode)->fileset == FILESYSTEM_I) {
-			truncate_inode_pages(&inode->i_data, 0);
+			truncate_inode_pages_final(&inode->i_data);
 
 			if (test_cflag(COMMIT_Freewmap, inode))
 				jfs_free_zero_link(inode);
@@ -168,7 +168,7 @@ void jfs_evict_inode(struct inode *inode)
 			dquot_free_inode(inode);
 		}
 	} else {
-		truncate_inode_pages(&inode->i_data, 0);
+		truncate_inode_pages_final(&inode->i_data);
 	}
 	clear_inode(inode);
 	dquot_drop(inode);
diff --git a/fs/kernfs/Kconfig b/fs/kernfs/Kconfig
new file mode 100644
index 000000000000..397b5f7a7a16
--- /dev/null
+++ b/fs/kernfs/Kconfig
@@ -0,0 +1,7 @@
+#
+# KERNFS should be selected by its users
+#
+
+config KERNFS
+	bool
+	default n
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index bd6e18be6e1a..5a398c0c3d99 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -8,6 +8,7 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
@@ -18,9 +19,162 @@
 #include "kernfs-internal.h"
 
 DEFINE_MUTEX(kernfs_mutex);
+static DEFINE_SPINLOCK(kernfs_rename_lock);	/* kn->parent and ->name */
+static char kernfs_pr_cont_buf[PATH_MAX];	/* protected by rename_lock */
 
 #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
 
+static bool kernfs_active(struct kernfs_node *kn)
+{
+	lockdep_assert_held(&kernfs_mutex);
+	return atomic_read(&kn->active) >= 0;
+}
+
+static bool kernfs_lockdep(struct kernfs_node *kn)
+{
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	return kn->flags & KERNFS_LOCKDEP;
+#else
+	return false;
+#endif
+}
+
+static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
+{
+	return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
+}
+
+static char * __must_check kernfs_path_locked(struct kernfs_node *kn, char *buf,
+					      size_t buflen)
+{
+	char *p = buf + buflen;
+	int len;
+
+	*--p = '\0';
+
+	do {
+		len = strlen(kn->name);
+		if (p - buf < len + 1) {
+			buf[0] = '\0';
+			p = NULL;
+			break;
+		}
+		p -= len;
+		memcpy(p, kn->name, len);
+		*--p = '/';
+		kn = kn->parent;
+	} while (kn && kn->parent);
+
+	return p;
+}
+
+/**
+ * kernfs_name - obtain the name of a given node
+ * @kn: kernfs_node of interest
+ * @buf: buffer to copy @kn's name into
+ * @buflen: size of @buf
+ *
+ * Copies the name of @kn into @buf of @buflen bytes.  The behavior is
+ * similar to strlcpy().  It returns the length of @kn's name and if @buf
+ * isn't long enough, it's filled upto @buflen-1 and nul terminated.
+ *
+ * This function can be called from any context.
+ */
+int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&kernfs_rename_lock, flags);
+	ret = kernfs_name_locked(kn, buf, buflen);
+	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
+	return ret;
+}
+
+/**
+ * kernfs_path - build full path of a given node
+ * @kn: kernfs_node of interest
+ * @buf: buffer to copy @kn's name into
+ * @buflen: size of @buf
+ *
+ * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
+ * path is built from the end of @buf so the returned pointer usually
+ * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
+ * and %NULL is returned.
+ */
+char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
+{
+	unsigned long flags;
+	char *p;
+
+	spin_lock_irqsave(&kernfs_rename_lock, flags);
+	p = kernfs_path_locked(kn, buf, buflen);
+	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
+	return p;
+}
+EXPORT_SYMBOL_GPL(kernfs_path);
+
+/**
+ * pr_cont_kernfs_name - pr_cont name of a kernfs_node
+ * @kn: kernfs_node of interest
+ *
+ * This function can be called from any context.
+ */
+void pr_cont_kernfs_name(struct kernfs_node *kn)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kernfs_rename_lock, flags);
+
+	kernfs_name_locked(kn, kernfs_pr_cont_buf, sizeof(kernfs_pr_cont_buf));
+	pr_cont("%s", kernfs_pr_cont_buf);
+
+	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
+}
+
+/**
+ * pr_cont_kernfs_path - pr_cont path of a kernfs_node
+ * @kn: kernfs_node of interest
+ *
+ * This function can be called from any context.
+ */
+void pr_cont_kernfs_path(struct kernfs_node *kn)
+{
+	unsigned long flags;
+	char *p;
+
+	spin_lock_irqsave(&kernfs_rename_lock, flags);
+
+	p = kernfs_path_locked(kn, kernfs_pr_cont_buf,
+			       sizeof(kernfs_pr_cont_buf));
+	if (p)
+		pr_cont("%s", p);
+	else
+		pr_cont("<name too long>");
+
+	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
+}
+
+/**
+ * kernfs_get_parent - determine the parent node and pin it
+ * @kn: kernfs_node of interest
+ *
+ * Determines @kn's parent, pins and returns it.  This function can be
+ * called from any context.
+ */
+struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
+{
+	struct kernfs_node *parent;
+	unsigned long flags;
+
+	spin_lock_irqsave(&kernfs_rename_lock, flags);
+	parent = kn->parent;
+	kernfs_get(parent);
+	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
+
+	return parent;
+}
+
 /**
  *	kernfs_name_hash
  *	@name: Null terminated string to hash
@@ -105,18 +259,24 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
  *	kernfs_unlink_sibling - unlink kernfs_node from sibling rbtree
  *	@kn: kernfs_node of interest
  *
- *	Unlink @kn from its sibling rbtree which starts from
- *	kn->parent->dir.children.
+ *	Try to unlink @kn from its sibling rbtree which starts from
+ *	kn->parent->dir.children.  Returns %true if @kn was actually
+ *	removed, %false if @kn wasn't on the rbtree.
  *
  *	Locking:
  *	mutex_lock(kernfs_mutex)
  */
-static void kernfs_unlink_sibling(struct kernfs_node *kn)
+static bool kernfs_unlink_sibling(struct kernfs_node *kn)
 {
+	if (RB_EMPTY_NODE(&kn->rb))
+		return false;
+
 	if (kernfs_type(kn) == KERNFS_DIR)
 		kn->parent->dir.subdirs--;
 
 	rb_erase(&kn->rb, &kn->parent->dir.children);
+	RB_CLEAR_NODE(&kn->rb);
+	return true;
 }
 
 /**
@@ -137,7 +297,7 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn)
 	if (!atomic_inc_unless_negative(&kn->active))
 		return NULL;
 
-	if (kn->flags & KERNFS_LOCKDEP)
+	if (kernfs_lockdep(kn))
 		rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_);
 	return kn;
 }
@@ -151,59 +311,57 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn)
  */
 void kernfs_put_active(struct kernfs_node *kn)
 {
+	struct kernfs_root *root = kernfs_root(kn);
 	int v;
 
 	if (unlikely(!kn))
 		return;
 
-	if (kn->flags & KERNFS_LOCKDEP)
+	if (kernfs_lockdep(kn))
 		rwsem_release(&kn->dep_map, 1, _RET_IP_);
 	v = atomic_dec_return(&kn->active);
 	if (likely(v != KN_DEACTIVATED_BIAS))
 		return;
 
-	/*
-	 * atomic_dec_return() is a mb(), we'll always see the updated
-	 * kn->u.completion.
-	 */
-	complete(kn->u.completion);
+	wake_up_all(&root->deactivate_waitq);
 }
 
 /**
- *	kernfs_deactivate - deactivate kernfs_node
- *	@kn: kernfs_node to deactivate
+ * kernfs_drain - drain kernfs_node
+ * @kn: kernfs_node to drain
  *
- *	Deny new active references and drain existing ones.
+ * Drain existing usages and nuke all existing mmaps of @kn.  Mutiple
+ * removers may invoke this function concurrently on @kn and all will
+ * return after draining is complete.
  */
-static void kernfs_deactivate(struct kernfs_node *kn)
+static void kernfs_drain(struct kernfs_node *kn)
+	__releases(&kernfs_mutex) __acquires(&kernfs_mutex)
 {
-	DECLARE_COMPLETION_ONSTACK(wait);
-	int v;
+	struct kernfs_root *root = kernfs_root(kn);
 
-	BUG_ON(!(kn->flags & KERNFS_REMOVED));
-
-	if (!(kernfs_type(kn) & KERNFS_ACTIVE_REF))
-		return;
+	lockdep_assert_held(&kernfs_mutex);
+	WARN_ON_ONCE(kernfs_active(kn));
 
-	kn->u.completion = (void *)&wait;
+	mutex_unlock(&kernfs_mutex);
 
-	if (kn->flags & KERNFS_LOCKDEP)
+	if (kernfs_lockdep(kn)) {
 		rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
-	/* atomic_add_return() is a mb(), put_active() will always see
-	 * the updated kn->u.completion.
-	 */
-	v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active);
-
-	if (v != KN_DEACTIVATED_BIAS) {
-		if (kn->flags & KERNFS_LOCKDEP)
+		if (atomic_read(&kn->active) != KN_DEACTIVATED_BIAS)
 			lock_contended(&kn->dep_map, _RET_IP_);
-		wait_for_completion(&wait);
 	}
 
-	if (kn->flags & KERNFS_LOCKDEP) {
+	/* but everyone should wait for draining */
+	wait_event(root->deactivate_waitq,
+		   atomic_read(&kn->active) == KN_DEACTIVATED_BIAS);
+
+	if (kernfs_lockdep(kn)) {
 		lock_acquired(&kn->dep_map, _RET_IP_);
 		rwsem_release(&kn->dep_map, 1, _RET_IP_);
 	}
+
+	kernfs_unmap_bin_file(kn);
+
+	mutex_lock(&kernfs_mutex);
 }
 
 /**
@@ -234,13 +392,15 @@ void kernfs_put(struct kernfs_node *kn)
 		return;
 	root = kernfs_root(kn);
  repeat:
-	/* Moving/renaming is always done while holding reference.
+	/*
+	 * Moving/renaming is always done while holding reference.
 	 * kn->parent won't change beneath us.
 	 */
 	parent = kn->parent;
 
-	WARN(!(kn->flags & KERNFS_REMOVED), "kernfs: free using entry: %s/%s\n",
-	     parent ? parent->name : "", kn->name);
+	WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS,
+		  "kernfs_put: %s/%s: released with incorrect active_ref %d\n",
+		  parent ? parent->name : "", kn->name, atomic_read(&kn->active));
 
 	if (kernfs_type(kn) == KERNFS_LINK)
 		kernfs_put(kn->symlink.target_kn);
@@ -282,8 +442,8 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
 	kn = dentry->d_fsdata;
 	mutex_lock(&kernfs_mutex);
 
-	/* The kernfs node has been deleted */
-	if (kn->flags & KERNFS_REMOVED)
+	/* The kernfs node has been deactivated */
+	if (!kernfs_active(kn))
 		goto out_bad;
 
 	/* The kernfs node has been moved? */
@@ -328,6 +488,24 @@ const struct dentry_operations kernfs_dops = {
 	.d_release	= kernfs_dop_release,
 };
 
+/**
+ * kernfs_node_from_dentry - determine kernfs_node associated with a dentry
+ * @dentry: the dentry in question
+ *
+ * Return the kernfs_node associated with @dentry.  If @dentry is not a
+ * kernfs one, %NULL is returned.
+ *
+ * While the returned kernfs_node will stay accessible as long as @dentry
+ * is accessible, the returned node can be in any state and the caller is
+ * fully responsible for determining what's accessible.
+ */
+struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
+{
+	if (dentry->d_sb->s_op == &kernfs_sops)
+		return dentry->d_fsdata;
+	return NULL;
+}
+
 static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 					     const char *name, umode_t mode,
 					     unsigned flags)
@@ -352,11 +530,12 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 	kn->ino = ret;
 
 	atomic_set(&kn->count, 1);
-	atomic_set(&kn->active, 0);
+	atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
+	RB_CLEAR_NODE(&kn->rb);
 
 	kn->name = name;
 	kn->mode = mode;
-	kn->flags = flags | KERNFS_REMOVED;
+	kn->flags = flags;
 
 	return kn;
 
@@ -382,69 +561,44 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
 }
 
 /**
- *	kernfs_addrm_start - prepare for kernfs_node add/remove
- *	@acxt: pointer to kernfs_addrm_cxt to be used
- *
- *	This function is called when the caller is about to add or remove
- *	kernfs_node.  This function acquires kernfs_mutex.  @acxt is used
- *	to keep and pass context to other addrm functions.
- *
- *	LOCKING:
- *	Kernel thread context (may sleep).  kernfs_mutex is locked on
- *	return.
- */
-void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt)
-	__acquires(kernfs_mutex)
-{
-	memset(acxt, 0, sizeof(*acxt));
-
-	mutex_lock(&kernfs_mutex);
-}
-
-/**
  *	kernfs_add_one - add kernfs_node to parent without warning
- *	@acxt: addrm context to use
  *	@kn: kernfs_node to be added
  *
  *	The caller must already have initialized @kn->parent.  This
  *	function increments nlink of the parent's inode if @kn is a
  *	directory and link into the children list of the parent.
  *
- *	This function should be called between calls to
- *	kernfs_addrm_start() and kernfs_addrm_finish() and should be passed
- *	the same @acxt as passed to kernfs_addrm_start().
- *
- *	LOCKING:
- *	Determined by kernfs_addrm_start().
- *
  *	RETURNS:
  *	0 on success, -EEXIST if entry with the given name already
  *	exists.
  */
-int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn)
+int kernfs_add_one(struct kernfs_node *kn)
 {
 	struct kernfs_node *parent = kn->parent;
-	bool has_ns = kernfs_ns_enabled(parent);
 	struct kernfs_iattrs *ps_iattr;
+	bool has_ns;
 	int ret;
 
-	if (has_ns != (bool)kn->ns) {
-		WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",
-		     has_ns ? "required" : "invalid", parent->name, kn->name);
-		return -EINVAL;
-	}
+	mutex_lock(&kernfs_mutex);
+
+	ret = -EINVAL;
+	has_ns = kernfs_ns_enabled(parent);
+	if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",
+		 has_ns ? "required" : "invalid", parent->name, kn->name))
+		goto out_unlock;
 
 	if (kernfs_type(parent) != KERNFS_DIR)
-		return -EINVAL;
+		goto out_unlock;
 
-	if (parent->flags & KERNFS_REMOVED)
-		return -ENOENT;
+	ret = -ENOENT;
+	if ((parent->flags & KERNFS_ACTIVATED) && !kernfs_active(parent))
+		goto out_unlock;
 
 	kn->hash = kernfs_name_hash(kn->name, kn->ns);
 
 	ret = kernfs_link_sibling(kn);
 	if (ret)
-		return ret;
+		goto out_unlock;
 
 	/* Update timestamps on the parent */
 	ps_iattr = parent->iattr;
@@ -453,82 +607,22 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn)
 		ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
 	}
 
-	/* Mark the entry added into directory tree */
-	kn->flags &= ~KERNFS_REMOVED;
-
-	return 0;
-}
-
-/**
- *	kernfs_remove_one - remove kernfs_node from parent
- *	@acxt: addrm context to use
- *	@kn: kernfs_node to be removed
- *
- *	Mark @kn removed and drop nlink of parent inode if @kn is a
- *	directory.  @kn is unlinked from the children list.
- *
- *	This function should be called between calls to
- *	kernfs_addrm_start() and kernfs_addrm_finish() and should be
- *	passed the same @acxt as passed to kernfs_addrm_start().
- *
- *	LOCKING:
- *	Determined by kernfs_addrm_start().
- */
-static void kernfs_remove_one(struct kernfs_addrm_cxt *acxt,
-			      struct kernfs_node *kn)
-{
-	struct kernfs_iattrs *ps_iattr;
+	mutex_unlock(&kernfs_mutex);
 
 	/*
-	 * Removal can be called multiple times on the same node.  Only the
-	 * first invocation is effective and puts the base ref.
+	 * Activate the new node unless CREATE_DEACTIVATED is requested.
+	 * If not activated here, the kernfs user is responsible for
+	 * activating the node with kernfs_activate().  A node which hasn't
+	 * been activated is not visible to userland and its removal won't
+	 * trigger deactivation.
 	 */
-	if (kn->flags & KERNFS_REMOVED)
-		return;
-
-	if (kn->parent) {
-		kernfs_unlink_sibling(kn);
-
-		/* Update timestamps on the parent */
-		ps_iattr = kn->parent->iattr;
-		if (ps_iattr) {
-			ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME;
-			ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME;
-		}
-	}
-
-	kn->flags |= KERNFS_REMOVED;
-	kn->u.removed_list = acxt->removed;
-	acxt->removed = kn;
-}
+	if (!(kernfs_root(kn)->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
+		kernfs_activate(kn);
+	return 0;
 
-/**
- *	kernfs_addrm_finish - finish up kernfs_node add/remove
- *	@acxt: addrm context to finish up
- *
- *	Finish up kernfs_node add/remove.  Resources acquired by
- *	kernfs_addrm_start() are released and removed kernfs_nodes are
- *	cleaned up.
- *
- *	LOCKING:
- *	kernfs_mutex is released.
- */
-void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt)
-	__releases(kernfs_mutex)
-{
-	/* release resources acquired by kernfs_addrm_start() */
+out_unlock:
 	mutex_unlock(&kernfs_mutex);
-
-	/* kill removed kernfs_nodes */
-	while (acxt->removed) {
-		struct kernfs_node *kn = acxt->removed;
-
-		acxt->removed = kn->u.removed_list;
-
-		kernfs_deactivate(kn);
-		kernfs_unmap_bin_file(kn);
-		kernfs_put(kn);
-	}
+	return ret;
 }
 
 /**
@@ -599,13 +693,15 @@ EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns);
 
 /**
  * kernfs_create_root - create a new kernfs hierarchy
- * @kdops: optional directory syscall operations for the hierarchy
+ * @scops: optional syscall operations for the hierarchy
+ * @flags: KERNFS_ROOT_* flags
  * @priv: opaque data associated with the new directory
  *
  * Returns the root of the new hierarchy on success, ERR_PTR() value on
  * failure.
  */
-struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
+struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
+				       unsigned int flags, void *priv)
 {
 	struct kernfs_root *root;
 	struct kernfs_node *kn;
@@ -624,12 +720,16 @@ struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
 		return ERR_PTR(-ENOMEM);
 	}
 
-	kn->flags &= ~KERNFS_REMOVED;
 	kn->priv = priv;
 	kn->dir.root = root;
 
-	root->dir_ops = kdops;
+	root->syscall_ops = scops;
+	root->flags = flags;
 	root->kn = kn;
+	init_waitqueue_head(&root->deactivate_waitq);
+
+	if (!(root->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
+		kernfs_activate(kn);
 
 	return root;
 }
@@ -660,7 +760,6 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
 					 const char *name, umode_t mode,
 					 void *priv, const void *ns)
 {
-	struct kernfs_addrm_cxt acxt;
 	struct kernfs_node *kn;
 	int rc;
 
@@ -674,10 +773,7 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
 	kn->priv = priv;
 
 	/* link in */
-	kernfs_addrm_start(&acxt);
-	rc = kernfs_add_one(&acxt, kn);
-	kernfs_addrm_finish(&acxt);
-
+	rc = kernfs_add_one(kn);
 	if (!rc)
 		return kn;
 
@@ -703,7 +799,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
 	kn = kernfs_find_ns(parent, dentry->d_name.name, ns);
 
 	/* no such entry */
-	if (!kn) {
+	if (!kn || !kernfs_active(kn)) {
 		ret = NULL;
 		goto out_unlock;
 	}
@@ -728,23 +824,37 @@ static int kernfs_iop_mkdir(struct inode *dir, struct dentry *dentry,
 			    umode_t mode)
 {
 	struct kernfs_node *parent = dir->i_private;
-	struct kernfs_dir_ops *kdops = kernfs_root(parent)->dir_ops;
+	struct kernfs_syscall_ops *scops = kernfs_root(parent)->syscall_ops;
+	int ret;
 
-	if (!kdops || !kdops->mkdir)
+	if (!scops || !scops->mkdir)
 		return -EPERM;
 
-	return kdops->mkdir(parent, dentry->d_name.name, mode);
+	if (!kernfs_get_active(parent))
+		return -ENODEV;
+
+	ret = scops->mkdir(parent, dentry->d_name.name, mode);
+
+	kernfs_put_active(parent);
+	return ret;
 }
 
 static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct kernfs_node *kn  = dentry->d_fsdata;
-	struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops;
+	struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
+	int ret;
 
-	if (!kdops || !kdops->rmdir)
+	if (!scops || !scops->rmdir)
 		return -EPERM;
 
-	return kdops->rmdir(kn);
+	if (!kernfs_get_active(kn))
+		return -ENODEV;
+
+	ret = scops->rmdir(kn);
+
+	kernfs_put_active(kn);
+	return ret;
 }
 
 static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -752,12 +862,25 @@ static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry,
 {
 	struct kernfs_node *kn  = old_dentry->d_fsdata;
 	struct kernfs_node *new_parent = new_dir->i_private;
-	struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops;
+	struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
+	int ret;
 
-	if (!kdops || !kdops->rename)
+	if (!scops || !scops->rename)
 		return -EPERM;
 
-	return kdops->rename(kn, new_parent, new_dentry->d_name.name);
+	if (!kernfs_get_active(kn))
+		return -ENODEV;
+
+	if (!kernfs_get_active(new_parent)) {
+		kernfs_put_active(kn);
+		return -ENODEV;
+	}
+
+	ret = scops->rename(kn, new_parent, new_dentry->d_name.name);
+
+	kernfs_put_active(new_parent);
+	kernfs_put_active(kn);
+	return ret;
 }
 
 const struct inode_operations kernfs_dir_iops = {
@@ -830,23 +953,104 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos,
 	return pos->parent;
 }
 
-static void __kernfs_remove(struct kernfs_addrm_cxt *acxt,
-			    struct kernfs_node *kn)
+/**
+ * kernfs_activate - activate a node which started deactivated
+ * @kn: kernfs_node whose subtree is to be activated
+ *
+ * If the root has KERNFS_ROOT_CREATE_DEACTIVATED set, a newly created node
+ * needs to be explicitly activated.  A node which hasn't been activated
+ * isn't visible to userland and deactivation is skipped during its
+ * removal.  This is useful to construct atomic init sequences where
+ * creation of multiple nodes should either succeed or fail atomically.
+ *
+ * The caller is responsible for ensuring that this function is not called
+ * after kernfs_remove*() is invoked on @kn.
+ */
+void kernfs_activate(struct kernfs_node *kn)
 {
-	struct kernfs_node *pos, *next;
+	struct kernfs_node *pos;
 
-	if (!kn)
+	mutex_lock(&kernfs_mutex);
+
+	pos = NULL;
+	while ((pos = kernfs_next_descendant_post(pos, kn))) {
+		if (!pos || (pos->flags & KERNFS_ACTIVATED))
+			continue;
+
+		WARN_ON_ONCE(pos->parent && RB_EMPTY_NODE(&pos->rb));
+		WARN_ON_ONCE(atomic_read(&pos->active) != KN_DEACTIVATED_BIAS);
+
+		atomic_sub(KN_DEACTIVATED_BIAS, &pos->active);
+		pos->flags |= KERNFS_ACTIVATED;
+	}
+
+	mutex_unlock(&kernfs_mutex);
+}
+
+static void __kernfs_remove(struct kernfs_node *kn)
+{
+	struct kernfs_node *pos;
+
+	lockdep_assert_held(&kernfs_mutex);
+
+	/*
+	 * Short-circuit if non-root @kn has already finished removal.
+	 * This is for kernfs_remove_self() which plays with active ref
+	 * after removal.
+	 */
+	if (!kn || (kn->parent && RB_EMPTY_NODE(&kn->rb)))
 		return;
 
 	pr_debug("kernfs %s: removing\n", kn->name);
 
-	next = NULL;
+	/* prevent any new usage under @kn by deactivating all nodes */
+	pos = NULL;
+	while ((pos = kernfs_next_descendant_post(pos, kn)))
+		if (kernfs_active(pos))
+			atomic_add(KN_DEACTIVATED_BIAS, &pos->active);
+
+	/* deactivate and unlink the subtree node-by-node */
 	do {
-		pos = next;
-		next = kernfs_next_descendant_post(pos, kn);
-		if (pos)
-			kernfs_remove_one(acxt, pos);
-	} while (next);
+		pos = kernfs_leftmost_descendant(kn);
+
+		/*
+		 * kernfs_drain() drops kernfs_mutex temporarily and @pos's
+		 * base ref could have been put by someone else by the time
+		 * the function returns.  Make sure it doesn't go away
+		 * underneath us.
+		 */
+		kernfs_get(pos);
+
+		/*
+		 * Drain iff @kn was activated.  This avoids draining and
+		 * its lockdep annotations for nodes which have never been
+		 * activated and allows embedding kernfs_remove() in create
+		 * error paths without worrying about draining.
+		 */
+		if (kn->flags & KERNFS_ACTIVATED)
+			kernfs_drain(pos);
+		else
+			WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS);
+
+		/*
+		 * kernfs_unlink_sibling() succeeds once per node.  Use it
+		 * to decide who's responsible for cleanups.
+		 */
+		if (!pos->parent || kernfs_unlink_sibling(pos)) {
+			struct kernfs_iattrs *ps_iattr =
+				pos->parent ? pos->parent->iattr : NULL;
+
+			/* update timestamps on the parent */
+			if (ps_iattr) {
+				ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME;
+				ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME;
+			}
+
+			kernfs_put(pos);
+		}
+
+		kernfs_put(pos);
+	} while (pos != kn);
 }
 
 /**
@@ -857,11 +1061,140 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt,
  */
 void kernfs_remove(struct kernfs_node *kn)
 {
-	struct kernfs_addrm_cxt acxt;
+	mutex_lock(&kernfs_mutex);
+	__kernfs_remove(kn);
+	mutex_unlock(&kernfs_mutex);
+}
 
-	kernfs_addrm_start(&acxt);
-	__kernfs_remove(&acxt, kn);
-	kernfs_addrm_finish(&acxt);
+/**
+ * kernfs_break_active_protection - break out of active protection
+ * @kn: the self kernfs_node
+ *
+ * The caller must be running off of a kernfs operation which is invoked
+ * with an active reference - e.g. one of kernfs_ops.  Each invocation of
+ * this function must also be matched with an invocation of
+ * kernfs_unbreak_active_protection().
+ *
+ * This function releases the active reference of @kn the caller is
+ * holding.  Once this function is called, @kn may be removed at any point
+ * and the caller is solely responsible for ensuring that the objects it
+ * dereferences are accessible.
+ */
+void kernfs_break_active_protection(struct kernfs_node *kn)
+{
+	/*
+	 * Take out ourself out of the active ref dependency chain.  If
+	 * we're called without an active ref, lockdep will complain.
+	 */
+	kernfs_put_active(kn);
+}
+
+/**
+ * kernfs_unbreak_active_protection - undo kernfs_break_active_protection()
+ * @kn: the self kernfs_node
+ *
+ * If kernfs_break_active_protection() was called, this function must be
+ * invoked before finishing the kernfs operation.  Note that while this
+ * function restores the active reference, it doesn't and can't actually
+ * restore the active protection - @kn may already or be in the process of
+ * being removed.  Once kernfs_break_active_protection() is invoked, that
+ * protection is irreversibly gone for the kernfs operation instance.
+ *
+ * While this function may be called at any point after
+ * kernfs_break_active_protection() is invoked, its most useful location
+ * would be right before the enclosing kernfs operation returns.
+ */
+void kernfs_unbreak_active_protection(struct kernfs_node *kn)
+{
+	/*
+	 * @kn->active could be in any state; however, the increment we do
+	 * here will be undone as soon as the enclosing kernfs operation
+	 * finishes and this temporary bump can't break anything.  If @kn
+	 * is alive, nothing changes.  If @kn is being deactivated, the
+	 * soon-to-follow put will either finish deactivation or restore
+	 * deactivated state.  If @kn is already removed, the temporary
+	 * bump is guaranteed to be gone before @kn is released.
+	 */
+	atomic_inc(&kn->active);
+	if (kernfs_lockdep(kn))
+		rwsem_acquire(&kn->dep_map, 0, 1, _RET_IP_);
+}
+
+/**
+ * kernfs_remove_self - remove a kernfs_node from its own method
+ * @kn: the self kernfs_node to remove
+ *
+ * The caller must be running off of a kernfs operation which is invoked
+ * with an active reference - e.g. one of kernfs_ops.  This can be used to
+ * implement a file operation which deletes itself.
+ *
+ * For example, the "delete" file for a sysfs device directory can be
+ * implemented by invoking kernfs_remove_self() on the "delete" file
+ * itself.  This function breaks the circular dependency of trying to
+ * deactivate self while holding an active ref itself.  It isn't necessary
+ * to modify the usual removal path to use kernfs_remove_self().  The
+ * "delete" implementation can simply invoke kernfs_remove_self() on self
+ * before proceeding with the usual removal path.  kernfs will ignore later
+ * kernfs_remove() on self.
+ *
+ * kernfs_remove_self() can be called multiple times concurrently on the
+ * same kernfs_node.  Only the first one actually performs removal and
+ * returns %true.  All others will wait until the kernfs operation which
+ * won self-removal finishes and return %false.  Note that the losers wait
+ * for the completion of not only the winning kernfs_remove_self() but also
+ * the whole kernfs_ops which won the arbitration.  This can be used to
+ * guarantee, for example, all concurrent writes to a "delete" file to
+ * finish only after the whole operation is complete.
+ */
+bool kernfs_remove_self(struct kernfs_node *kn)
+{
+	bool ret;
+
+	mutex_lock(&kernfs_mutex);
+	kernfs_break_active_protection(kn);
+
+	/*
+	 * SUICIDAL is used to arbitrate among competing invocations.  Only
+	 * the first one will actually perform removal.  When the removal
+	 * is complete, SUICIDED is set and the active ref is restored
+	 * while holding kernfs_mutex.  The ones which lost arbitration
+	 * waits for SUICDED && drained which can happen only after the
+	 * enclosing kernfs operation which executed the winning instance
+	 * of kernfs_remove_self() finished.
+	 */
+	if (!(kn->flags & KERNFS_SUICIDAL)) {
+		kn->flags |= KERNFS_SUICIDAL;
+		__kernfs_remove(kn);
+		kn->flags |= KERNFS_SUICIDED;
+		ret = true;
+	} else {
+		wait_queue_head_t *waitq = &kernfs_root(kn)->deactivate_waitq;
+		DEFINE_WAIT(wait);
+
+		while (true) {
+			prepare_to_wait(waitq, &wait, TASK_UNINTERRUPTIBLE);
+
+			if ((kn->flags & KERNFS_SUICIDED) &&
+			    atomic_read(&kn->active) == KN_DEACTIVATED_BIAS)
+				break;
+
+			mutex_unlock(&kernfs_mutex);
+			schedule();
+			mutex_lock(&kernfs_mutex);
+		}
+		finish_wait(waitq, &wait);
+		WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb));
+		ret = false;
+	}
+
+	/*
+	 * This must be done while holding kernfs_mutex; otherwise, waiting
+	 * for SUICIDED && deactivated could finish prematurely.
+	 */
+	kernfs_unbreak_active_protection(kn);
+
+	mutex_unlock(&kernfs_mutex);
+	return ret;
 }
 
 /**
@@ -876,7 +1209,6 @@ void kernfs_remove(struct kernfs_node *kn)
 int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
 			     const void *ns)
 {
-	struct kernfs_addrm_cxt acxt;
 	struct kernfs_node *kn;
 
 	if (!parent) {
@@ -885,13 +1217,13 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
 		return -ENOENT;
 	}
 
-	kernfs_addrm_start(&acxt);
+	mutex_lock(&kernfs_mutex);
 
 	kn = kernfs_find_ns(parent, name, ns);
 	if (kn)
-		__kernfs_remove(&acxt, kn);
+		__kernfs_remove(kn);
 
-	kernfs_addrm_finish(&acxt);
+	mutex_unlock(&kernfs_mutex);
 
 	if (kn)
 		return 0;
@@ -909,12 +1241,18 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
 int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
 		     const char *new_name, const void *new_ns)
 {
+	struct kernfs_node *old_parent;
+	const char *old_name = NULL;
 	int error;
 
+	/* can't move or rename root */
+	if (!kn->parent)
+		return -EINVAL;
+
 	mutex_lock(&kernfs_mutex);
 
 	error = -ENOENT;
-	if ((kn->flags | new_parent->flags) & KERNFS_REMOVED)
+	if (!kernfs_active(kn) || !kernfs_active(new_parent))
 		goto out;
 
 	error = 0;
@@ -932,13 +1270,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
 		new_name = kstrdup(new_name, GFP_KERNEL);
 		if (!new_name)
 			goto out;
-
-		if (kn->flags & KERNFS_STATIC_NAME)
-			kn->flags &= ~KERNFS_STATIC_NAME;
-		else
-			kfree(kn->name);
-
-		kn->name = new_name;
+	} else {
+		new_name = NULL;
 	}
 
 	/*
@@ -946,12 +1279,29 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
 	 */
 	kernfs_unlink_sibling(kn);
 	kernfs_get(new_parent);
-	kernfs_put(kn->parent);
+
+	/* rename_lock protects ->parent and ->name accessors */
+	spin_lock_irq(&kernfs_rename_lock);
+
+	old_parent = kn->parent;
+	kn->parent = new_parent;
+
 	kn->ns = new_ns;
+	if (new_name) {
+		if (!(kn->flags & KERNFS_STATIC_NAME))
+			old_name = kn->name;
+		kn->flags &= ~KERNFS_STATIC_NAME;
+		kn->name = new_name;
+	}
+
+	spin_unlock_irq(&kernfs_rename_lock);
+
 	kn->hash = kernfs_name_hash(kn->name, kn->ns);
-	kn->parent = new_parent;
 	kernfs_link_sibling(kn);
 
+	kernfs_put(old_parent);
+	kfree(old_name);
+
 	error = 0;
  out:
 	mutex_unlock(&kernfs_mutex);
@@ -974,7 +1324,7 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
 	struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos)
 {
 	if (pos) {
-		int valid = !(pos->flags & KERNFS_REMOVED) &&
+		int valid = kernfs_active(pos) &&
 			pos->parent == parent && hash == pos->hash;
 		kernfs_put(pos);
 		if (!valid)
@@ -993,8 +1343,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
 				break;
 		}
 	}
-	/* Skip over entries in the wrong namespace */
-	while (pos && pos->ns != ns) {
+	/* Skip over entries which are dying/dead or in the wrong namespace */
+	while (pos && (!kernfs_active(pos) || pos->ns != ns)) {
 		struct rb_node *node = rb_next(&pos->rb);
 		if (!node)
 			pos = NULL;
@@ -1008,14 +1358,15 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
 	struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos)
 {
 	pos = kernfs_dir_pos(ns, parent, ino, pos);
-	if (pos)
+	if (pos) {
 		do {
 			struct rb_node *node = rb_next(&pos->rb);
 			if (!node)
 				pos = NULL;
 			else
 				pos = rb_to_kn(node);
-		} while (pos && pos->ns != ns);
+		} while (pos && (!kernfs_active(pos) || pos->ns != ns));
+	}
 	return pos;
 }
 
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index dbf397bfdff2..ddcb471b9cc9 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -252,19 +252,9 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
 				size_t count, loff_t *ppos)
 {
 	struct kernfs_open_file *of = kernfs_of(file);
-	ssize_t len = min_t(size_t, count, PAGE_SIZE);
 	const struct kernfs_ops *ops;
-	char *buf;
-
-	buf = kmalloc(len + 1, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, user_buf, len)) {
-		len = -EFAULT;
-		goto out_free;
-	}
-	buf[len] = '\0';	/* guarantee string termination */
+	char *buf = NULL;
+	ssize_t len;
 
 	/*
 	 * @of->mutex nests outside active ref and is just to ensure that
@@ -273,22 +263,45 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
 	mutex_lock(&of->mutex);
 	if (!kernfs_get_active(of->kn)) {
 		mutex_unlock(&of->mutex);
-		len = -ENODEV;
-		goto out_free;
+		return -ENODEV;
 	}
 
 	ops = kernfs_ops(of->kn);
-	if (ops->write)
-		len = ops->write(of, buf, len, *ppos);
-	else
+	if (!ops->write) {
 		len = -EINVAL;
+		goto out_unlock;
+	}
 
+	if (ops->atomic_write_len) {
+		len = count;
+		if (len > ops->atomic_write_len) {
+			len = -E2BIG;
+			goto out_unlock;
+		}
+	} else {
+		len = min_t(size_t, count, PAGE_SIZE);
+	}
+
+	buf = kmalloc(len + 1, GFP_KERNEL);
+	if (!buf) {
+		len = -ENOMEM;
+		goto out_unlock;
+	}
+
+	if (copy_from_user(buf, user_buf, len)) {
+		len = -EFAULT;
+		goto out_unlock;
+	}
+	buf[len] = '\0';	/* guarantee string termination */
+
+	len = ops->write(of, buf, len, *ppos);
+out_unlock:
 	kernfs_put_active(of->kn);
 	mutex_unlock(&of->mutex);
 
 	if (len > 0)
 		*ppos += len;
-out_free:
+
 	kfree(buf);
 	return len;
 }
@@ -820,7 +833,6 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
 					 bool name_is_static,
 					 struct lock_class_key *key)
 {
-	struct kernfs_addrm_cxt acxt;
 	struct kernfs_node *kn;
 	unsigned flags;
 	int rc;
@@ -855,10 +867,7 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
 	if (ops->mmap)
 		kn->flags |= KERNFS_HAS_MMAP;
 
-	kernfs_addrm_start(&acxt);
-	rc = kernfs_add_one(&acxt, kn);
-	kernfs_addrm_finish(&acxt);
-
+	rc = kernfs_add_one(kn);
 	if (rc) {
 		kernfs_put(kn);
 		return ERR_PTR(rc);
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index e55126f85bd2..abb0f1f53d93 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -355,7 +355,7 @@ void kernfs_evict_inode(struct inode *inode)
 {
 	struct kernfs_node *kn = inode->i_private;
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	kernfs_put(kn);
 }
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index eb536b76374a..8be13b2a079b 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -26,7 +26,8 @@ struct kernfs_iattrs {
 	struct simple_xattrs	xattrs;
 };
 
-#define KN_DEACTIVATED_BIAS		INT_MIN
+/* +1 to avoid triggering overflow warning when negating it */
+#define KN_DEACTIVATED_BIAS		(INT_MIN + 1)
 
 /* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */
 
@@ -45,13 +46,6 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
 }
 
 /*
- * Context structure to be used while adding/removing nodes.
- */
-struct kernfs_addrm_cxt {
-	struct kernfs_node	*removed;
-};
-
-/*
  * mount.c
  */
 struct kernfs_super_info {
@@ -71,6 +65,7 @@ struct kernfs_super_info {
 };
 #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
 
+extern const struct super_operations kernfs_sops;
 extern struct kmem_cache *kernfs_node_cache;
 
 /*
@@ -100,9 +95,7 @@ extern const struct inode_operations kernfs_dir_iops;
 
 struct kernfs_node *kernfs_get_active(struct kernfs_node *kn);
 void kernfs_put_active(struct kernfs_node *kn);
-void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt);
-int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn);
-void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt);
+int kernfs_add_one(struct kernfs_node *kn);
 struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
 				    const char *name, umode_t mode,
 				    unsigned flags);
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 0f4152defe7b..6a5f04ac8704 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -19,12 +19,49 @@
 
 struct kmem_cache *kernfs_node_cache;
 
-static const struct super_operations kernfs_sops = {
+static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+	struct kernfs_root *root = kernfs_info(sb)->root;
+	struct kernfs_syscall_ops *scops = root->syscall_ops;
+
+	if (scops && scops->remount_fs)
+		return scops->remount_fs(root, flags, data);
+	return 0;
+}
+
+static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
+{
+	struct kernfs_root *root = kernfs_root(dentry->d_fsdata);
+	struct kernfs_syscall_ops *scops = root->syscall_ops;
+
+	if (scops && scops->show_options)
+		return scops->show_options(sf, root);
+	return 0;
+}
+
+const struct super_operations kernfs_sops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
 	.evict_inode	= kernfs_evict_inode,
+
+	.remount_fs	= kernfs_sop_remount_fs,
+	.show_options	= kernfs_sop_show_options,
 };
 
+/**
+ * kernfs_root_from_sb - determine kernfs_root associated with a super_block
+ * @sb: the super_block in question
+ *
+ * Return the kernfs_root associated with @sb.  If @sb is not a kernfs one,
+ * %NULL is returned.
+ */
+struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
+{
+	if (sb->s_op == &kernfs_sops)
+		return kernfs_info(sb)->root;
+	return NULL;
+}
+
 static int kernfs_fill_super(struct super_block *sb)
 {
 	struct kernfs_super_info *info = kernfs_info(sb);
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 4d457055acb9..8a198898e39a 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -27,7 +27,6 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
 				       struct kernfs_node *target)
 {
 	struct kernfs_node *kn;
-	struct kernfs_addrm_cxt acxt;
 	int error;
 
 	kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK);
@@ -39,10 +38,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
 	kn->symlink.target_kn = target;
 	kernfs_get(target);	/* ref owned by symlink */
 
-	kernfs_addrm_start(&acxt);
-	error = kernfs_add_one(&acxt, kn);
-	kernfs_addrm_finish(&acxt);
-
+	error = kernfs_add_one(kn);
 	if (!error)
 		return kn;
 
diff --git a/fs/locks.c b/fs/locks.c
index 92a0f0a52b06..ce93815b0626 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -135,6 +135,7 @@
 #define IS_POSIX(fl)	(fl->fl_flags & FL_POSIX)
 #define IS_FLOCK(fl)	(fl->fl_flags & FL_FLOCK)
 #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG))
+#define IS_FILE_PVT(fl)	(fl->fl_flags & FL_FILE_PVT)
 
 static bool lease_breaking(struct file_lock *fl)
 {
@@ -344,48 +345,43 @@ static int assign_type(struct file_lock *fl, long type)
 	return 0;
 }
 
-/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
- * style lock.
- */
-static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
-			       struct flock *l)
+static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
+				 struct flock64 *l)
 {
-	off_t start, end;
-
 	switch (l->l_whence) {
 	case SEEK_SET:
-		start = 0;
+		fl->fl_start = 0;
 		break;
 	case SEEK_CUR:
-		start = filp->f_pos;
+		fl->fl_start = filp->f_pos;
 		break;
 	case SEEK_END:
-		start = i_size_read(file_inode(filp));
+		fl->fl_start = i_size_read(file_inode(filp));
 		break;
 	default:
 		return -EINVAL;
 	}
+	if (l->l_start > OFFSET_MAX - fl->fl_start)
+		return -EOVERFLOW;
+	fl->fl_start += l->l_start;
+	if (fl->fl_start < 0)
+		return -EINVAL;
 
 	/* POSIX-1996 leaves the case l->l_len < 0 undefined;
 	   POSIX-2001 defines it. */
-	start += l->l_start;
-	if (start < 0)
-		return -EINVAL;
-	fl->fl_end = OFFSET_MAX;
 	if (l->l_len > 0) {
-		end = start + l->l_len - 1;
-		fl->fl_end = end;
+		if (l->l_len - 1 > OFFSET_MAX - fl->fl_start)
+			return -EOVERFLOW;
+		fl->fl_end = fl->fl_start + l->l_len - 1;
+
 	} else if (l->l_len < 0) {
-		end = start - 1;
-		fl->fl_end = end;
-		start += l->l_len;
-		if (start < 0)
+		if (fl->fl_start + l->l_len < 0)
 			return -EINVAL;
-	}
-	fl->fl_start = start;	/* we record the absolute position */
-	if (fl->fl_end < fl->fl_start)
-		return -EOVERFLOW;
-	
+		fl->fl_end = fl->fl_start - 1;
+		fl->fl_start += l->l_len;
+	} else
+		fl->fl_end = OFFSET_MAX;
+
 	fl->fl_owner = current->files;
 	fl->fl_pid = current->tgid;
 	fl->fl_file = filp;
@@ -393,55 +389,36 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
 	fl->fl_ops = NULL;
 	fl->fl_lmops = NULL;
 
-	return assign_type(fl, l->l_type);
-}
-
-#if BITS_PER_LONG == 32
-static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
-				 struct flock64 *l)
-{
-	loff_t start;
-
-	switch (l->l_whence) {
-	case SEEK_SET:
-		start = 0;
-		break;
-	case SEEK_CUR:
-		start = filp->f_pos;
+	/* Ensure that fl->fl_filp has compatible f_mode */
+	switch (l->l_type) {
+	case F_RDLCK:
+		if (!(filp->f_mode & FMODE_READ))
+			return -EBADF;
 		break;
-	case SEEK_END:
-		start = i_size_read(file_inode(filp));
+	case F_WRLCK:
+		if (!(filp->f_mode & FMODE_WRITE))
+			return -EBADF;
 		break;
-	default:
-		return -EINVAL;
 	}
 
-	start += l->l_start;
-	if (start < 0)
-		return -EINVAL;
-	fl->fl_end = OFFSET_MAX;
-	if (l->l_len > 0) {
-		fl->fl_end = start + l->l_len - 1;
-	} else if (l->l_len < 0) {
-		fl->fl_end = start - 1;
-		start += l->l_len;
-		if (start < 0)
-			return -EINVAL;
-	}
-	fl->fl_start = start;	/* we record the absolute position */
-	if (fl->fl_end < fl->fl_start)
-		return -EOVERFLOW;
-	
-	fl->fl_owner = current->files;
-	fl->fl_pid = current->tgid;
-	fl->fl_file = filp;
-	fl->fl_flags = FL_POSIX;
-	fl->fl_ops = NULL;
-	fl->fl_lmops = NULL;
-
 	return assign_type(fl, l->l_type);
 }
-#endif
+
+/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
+ * style lock.
+ */
+static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
+			       struct flock *l)
+{
+	struct flock64 ll = {
+		.l_type = l->l_type,
+		.l_whence = l->l_whence,
+		.l_start = l->l_start,
+		.l_len = l->l_len,
+	};
+
+	return flock64_to_posix_lock(filp, fl, &ll);
+}
 
 /* default lease lock manager operations */
 static void lease_break_callback(struct file_lock *fl)
@@ -511,8 +488,7 @@ static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 }
 
 /* Must be called with the i_lock held! */
-static inline void
-locks_insert_global_locks(struct file_lock *fl)
+static void locks_insert_global_locks(struct file_lock *fl)
 {
 	lg_local_lock(&file_lock_lglock);
 	fl->fl_link_cpu = smp_processor_id();
@@ -521,8 +497,7 @@ locks_insert_global_locks(struct file_lock *fl)
 }
 
 /* Must be called with the i_lock held! */
-static inline void
-locks_delete_global_locks(struct file_lock *fl)
+static void locks_delete_global_locks(struct file_lock *fl)
 {
 	/*
 	 * Avoid taking lock if already unhashed. This is safe since this check
@@ -544,14 +519,12 @@ posix_owner_key(struct file_lock *fl)
 	return (unsigned long)fl->fl_owner;
 }
 
-static inline void
-locks_insert_global_blocked(struct file_lock *waiter)
+static void locks_insert_global_blocked(struct file_lock *waiter)
 {
 	hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter));
 }
 
-static inline void
-locks_delete_global_blocked(struct file_lock *waiter)
+static void locks_delete_global_blocked(struct file_lock *waiter)
 {
 	hash_del(&waiter->fl_link);
 }
@@ -581,7 +554,7 @@ static void locks_delete_block(struct file_lock *waiter)
  * it seems like the reasonable thing to do.
  *
  * Must be called with both the i_lock and blocked_lock_lock held. The fl_block
- * list itself is protected by the file_lock_list, but by ensuring that the
+ * list itself is protected by the blocked_lock_lock, but by ensuring that the
  * i_lock is also held on insertions we can avoid taking the blocked_lock_lock
  * in some cases when we see that the fl_block list is empty.
  */
@@ -591,7 +564,7 @@ static void __locks_insert_block(struct file_lock *blocker,
 	BUG_ON(!list_empty(&waiter->fl_block));
 	waiter->fl_next = blocker;
 	list_add_tail(&waiter->fl_block, &blocker->fl_block);
-	if (IS_POSIX(blocker))
+	if (IS_POSIX(blocker) && !IS_FILE_PVT(blocker))
 		locks_insert_global_blocked(waiter);
 }
 
@@ -652,15 +625,18 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
 	locks_insert_global_locks(fl);
 }
 
-/*
- * Delete a lock and then free it.
- * Wake up processes that are blocked waiting for this lock,
- * notify the FS that the lock has been cleared and
- * finally free the lock.
+/**
+ * locks_delete_lock - Delete a lock and then free it.
+ * @thisfl_p: pointer that points to the fl_next field of the previous
+ * 	      inode->i_flock list entry
+ *
+ * Unlink a lock from all lists and free the namespace reference, but don't
+ * free it yet. Wake up processes that are blocked waiting for this lock and
+ * notify the FS that the lock has been cleared.
  *
  * Must be called with the i_lock held!
  */
-static void locks_delete_lock(struct file_lock **thisfl_p)
+static void locks_unlink_lock(struct file_lock **thisfl_p)
 {
 	struct file_lock *fl = *thisfl_p;
 
@@ -675,6 +651,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
 	}
 
 	locks_wake_up_blocks(fl);
+}
+
+/*
+ * Unlink a lock from all lists and free it.
+ *
+ * Must be called with i_lock held!
+ */
+static void locks_delete_lock(struct file_lock **thisfl_p)
+{
+	struct file_lock *fl = *thisfl_p;
+
+	locks_unlink_lock(thisfl_p);
 	locks_free_lock(fl);
 }
 
@@ -769,8 +757,16 @@ EXPORT_SYMBOL(posix_test_lock);
  * Note: the above assumption may not be true when handling lock
  * requests from a broken NFS client. It may also fail in the presence
  * of tasks (such as posix threads) sharing the same open file table.
- *
  * To handle those cases, we just bail out after a few iterations.
+ *
+ * For FL_FILE_PVT locks, the owner is the filp, not the files_struct.
+ * Because the owner is not even nominally tied to a thread of
+ * execution, the deadlock detection below can't reasonably work well. Just
+ * skip it for those.
+ *
+ * In principle, we could do a more limited deadlock detection on FL_FILE_PVT
+ * locks that just checks for the case where two tasks are attempting to
+ * upgrade from read to write locks on the same inode.
  */
 
 #define MAX_DEADLK_ITERATIONS 10
@@ -793,6 +789,13 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
 {
 	int i = 0;
 
+	/*
+	 * This deadlock detector can't reasonably detect deadlocks with
+	 * FL_FILE_PVT locks, since they aren't owned by a process, per-se.
+	 */
+	if (IS_FILE_PVT(caller_fl))
+		return 0;
+
 	while ((block_fl = what_owner_is_waiting_for(block_fl))) {
 		if (i++ > MAX_DEADLK_ITERATIONS)
 			return 0;
@@ -1472,6 +1475,32 @@ int fcntl_getlease(struct file *filp)
 	return type;
 }
 
+/**
+ * check_conflicting_open - see if the given dentry points to a file that has
+ * 			    an existing open that would conflict with the
+ * 			    desired lease.
+ * @dentry:	dentry to check
+ * @arg:	type of lease that we're trying to acquire
+ *
+ * Check to see if there's an existing open fd on this file that would
+ * conflict with the lease we're trying to set.
+ */
+static int
+check_conflicting_open(const struct dentry *dentry, const long arg)
+{
+	int ret = 0;
+	struct inode *inode = dentry->d_inode;
+
+	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+		return -EAGAIN;
+
+	if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
+	    (atomic_read(&inode->i_count) > 1)))
+		ret = -EAGAIN;
+
+	return ret;
+}
+
 static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp)
 {
 	struct file_lock *fl, **before, **my_before = NULL, *lease;
@@ -1499,12 +1528,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
 		return -EINVAL;
 	}
 
-	error = -EAGAIN;
-	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
-		goto out;
-	if ((arg == F_WRLCK)
-	    && ((d_count(dentry) > 1)
-		|| (atomic_read(&inode->i_count) > 1)))
+	error = check_conflicting_open(dentry, arg);
+	if (error)
 		goto out;
 
 	/*
@@ -1549,7 +1574,19 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
 		goto out;
 
 	locks_insert_lock(before, lease);
-	error = 0;
+	/*
+	 * The check in break_lease() is lockless. It's possible for another
+	 * open to race in after we did the earlier check for a conflicting
+	 * open but before the lease was inserted. Check again for a
+	 * conflicting open and cancel the lease if there is one.
+	 *
+	 * We also add a barrier here to ensure that the insertion of the lock
+	 * precedes these checks.
+	 */
+	smp_mb();
+	error = check_conflicting_open(dentry, arg);
+	if (error)
+		locks_unlink_lock(flp);
 out:
 	if (is_deleg)
 		mutex_unlock(&inode->i_mutex);
@@ -1842,7 +1879,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock);
 
 static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
 {
-	flock->l_pid = fl->fl_pid;
+	flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
 #if BITS_PER_LONG == 32
 	/*
 	 * Make sure we can represent the posix lock via
@@ -1864,7 +1901,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
 #if BITS_PER_LONG == 32
 static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
 {
-	flock->l_pid = fl->fl_pid;
+	flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
 	flock->l_start = fl->fl_start;
 	flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
 		fl->fl_end - fl->fl_start + 1;
@@ -1876,7 +1913,7 @@ static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
 /* Report the first existing lock that would conflict with l.
  * This implements the F_GETLK command of fcntl().
  */
-int fcntl_getlk(struct file *filp, struct flock __user *l)
+int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
 {
 	struct file_lock file_lock;
 	struct flock flock;
@@ -1893,6 +1930,12 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
 	if (error)
 		goto out;
 
+	if (cmd == F_GETLKP) {
+		cmd = F_GETLK;
+		file_lock.fl_flags |= FL_FILE_PVT;
+		file_lock.fl_owner = (fl_owner_t)filp;
+	}
+
 	error = vfs_test_lock(filp, &file_lock);
 	if (error)
 		goto out;
@@ -2012,25 +2055,24 @@ again:
 	error = flock_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
-	if (cmd == F_SETLKW) {
-		file_lock->fl_flags |= FL_SLEEP;
-	}
-	
-	error = -EBADF;
-	switch (flock.l_type) {
-	case F_RDLCK:
-		if (!(filp->f_mode & FMODE_READ))
-			goto out;
-		break;
-	case F_WRLCK:
-		if (!(filp->f_mode & FMODE_WRITE))
-			goto out;
-		break;
-	case F_UNLCK:
+
+	/*
+	 * If the cmd is requesting file-private locks, then set the
+	 * FL_FILE_PVT flag and override the owner.
+	 */
+	switch (cmd) {
+	case F_SETLKP:
+		cmd = F_SETLK;
+		file_lock->fl_flags |= FL_FILE_PVT;
+		file_lock->fl_owner = (fl_owner_t)filp;
 		break;
-	default:
-		error = -EINVAL;
-		goto out;
+	case F_SETLKPW:
+		cmd = F_SETLKW;
+		file_lock->fl_flags |= FL_FILE_PVT;
+		file_lock->fl_owner = (fl_owner_t)filp;
+		/* Fallthrough */
+	case F_SETLKW:
+		file_lock->fl_flags |= FL_SLEEP;
 	}
 
 	error = do_lock_file_wait(filp, cmd, file_lock);
@@ -2061,7 +2103,7 @@ out:
 /* Report the first existing lock that would conflict with l.
  * This implements the F_GETLK command of fcntl().
  */
-int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
 {
 	struct file_lock file_lock;
 	struct flock64 flock;
@@ -2078,6 +2120,12 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
 	if (error)
 		goto out;
 
+	if (cmd == F_GETLKP) {
+		cmd = F_GETLK64;
+		file_lock.fl_flags |= FL_FILE_PVT;
+		file_lock.fl_owner = (fl_owner_t)filp;
+	}
+
 	error = vfs_test_lock(filp, &file_lock);
 	if (error)
 		goto out;
@@ -2130,27 +2178,26 @@ again:
 	error = flock64_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
-	if (cmd == F_SETLKW64) {
+
+	/*
+	 * If the cmd is requesting file-private locks, then set the
+	 * FL_FILE_PVT flag and override the owner.
+	 */
+	switch (cmd) {
+	case F_SETLKP:
+		cmd = F_SETLK64;
+		file_lock->fl_flags |= FL_FILE_PVT;
+		file_lock->fl_owner = (fl_owner_t)filp;
+		break;
+	case F_SETLKPW:
+		cmd = F_SETLKW64;
+		file_lock->fl_flags |= FL_FILE_PVT;
+		file_lock->fl_owner = (fl_owner_t)filp;
+		/* Fallthrough */
+	case F_SETLKW64:
 		file_lock->fl_flags |= FL_SLEEP;
 	}
 	
-	error = -EBADF;
-	switch (flock.l_type) {
-	case F_RDLCK:
-		if (!(filp->f_mode & FMODE_READ))
-			goto out;
-		break;
-	case F_WRLCK:
-		if (!(filp->f_mode & FMODE_WRITE))
-			goto out;
-		break;
-	case F_UNLCK:
-		break;
-	default:
-		error = -EINVAL;
-		goto out;
-	}
-
 	error = do_lock_file_wait(filp, cmd, file_lock);
 
 	/*
@@ -2209,7 +2256,7 @@ EXPORT_SYMBOL(locks_remove_posix);
 /*
  * This function is called on the last close of an open file.
  */
-void locks_remove_flock(struct file *filp)
+void locks_remove_file(struct file *filp)
 {
 	struct inode * inode = file_inode(filp);
 	struct file_lock *fl;
@@ -2218,6 +2265,8 @@ void locks_remove_flock(struct file *filp)
 	if (!inode->i_flock)
 		return;
 
+	locks_remove_posix(filp, (fl_owner_t)filp);
+
 	if (filp->f_op->flock) {
 		struct file_lock fl = {
 			.fl_pid = current->tgid,
@@ -2236,16 +2285,28 @@ void locks_remove_flock(struct file *filp)
 
 	while ((fl = *before) != NULL) {
 		if (fl->fl_file == filp) {
-			if (IS_FLOCK(fl)) {
-				locks_delete_lock(before);
-				continue;
-			}
 			if (IS_LEASE(fl)) {
 				lease_modify(before, F_UNLCK);
 				continue;
 			}
-			/* What? */
-			BUG();
+
+			/*
+			 * There's a leftover lock on the list of a type that
+			 * we didn't expect to see. Most likely a classic
+			 * POSIX lock that ended up not getting released
+			 * properly, or that raced onto the list somehow. Log
+			 * some info about it and then just remove it from
+			 * the list.
+			 */
+			WARN(!IS_FLOCK(fl),
+				"leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n",
+				MAJOR(inode->i_sb->s_dev),
+				MINOR(inode->i_sb->s_dev), inode->i_ino,
+				fl->fl_type, fl->fl_flags,
+				fl->fl_start, fl->fl_end);
+
+			locks_delete_lock(before);
+			continue;
  		}
 		before = &fl->fl_next;
 	}
@@ -2314,8 +2375,12 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
 
 	seq_printf(f, "%lld:%s ", id, pfx);
 	if (IS_POSIX(fl)) {
-		seq_printf(f, "%6s %s ",
-			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
+		if (fl->fl_flags & FL_ACCESS)
+			seq_printf(f, "ACCESS");
+		else
+			seq_printf(f, "POSIX%c", IS_FILE_PVT(fl) ? 'P' : ' ');
+
+		seq_printf(f, " %s ",
 			     (inode == NULL) ? "*NOINODE*" :
 			     mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
 	} else if (IS_FLOCK(fl)) {
@@ -2385,6 +2450,7 @@ static int locks_show(struct seq_file *f, void *v)
 }
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
+	__acquires(&blocked_lock_lock)
 {
 	struct locks_iterator *iter = f->private;
 
@@ -2403,6 +2469,7 @@ static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
 }
 
 static void locks_stop(struct seq_file *f, void *v)
+	__releases(&blocked_lock_lock)
 {
 	spin_unlock(&blocked_lock_lock);
 	lg_global_unlock(&file_lock_lglock);
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/readwrite.c b/fs/logfs/readwrite.c
index 9a59cbade2fb..48140315f627 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -2180,7 +2180,7 @@ void logfs_evict_inode(struct inode *inode)
 			do_delete_inode(inode);
 		}
 	}
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 
 	/* Cheaper version of write_inode.  All changes are concealed in
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/minix/inode.c b/fs/minix/inode.c
index 0332109162a5..0ad2ec9601de 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -26,7 +26,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data);
 
 static void minix_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	if (!inode->i_nlink) {
 		inode->i_size = 0;
 		minix_truncate(inode);
@@ -86,7 +86,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
 					     sizeof(struct minix_inode_info),
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index c320ac52353e..08b8ea8c353e 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -339,7 +339,7 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
 	if (val)
 		goto finished;
 
-	DDPRINTK("ncp_lookup_validate: %pd2 not valid, age=%ld, server lookup\n",
+	ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
 		dentry, NCP_GET_AGE(dentry));
 
 	len = sizeof(__name);
@@ -358,7 +358,7 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
 			res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 	}
 	finfo.volume = finfo.i.volNumber;
-	DDPRINTK("ncp_lookup_validate: looked for %pd/%s, res=%d\n",
+	ncp_dbg(2, "looked for %pd/%s, res=%d\n",
 		dentry->d_parent, __name, res);
 	/*
 	 * If we didn't find it, or if it has a different dirEntNum to
@@ -372,14 +372,14 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
 			ncp_new_dentry(dentry);
 			val=1;
 		} else
-			DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
+			ncp_dbg(2, "found, but dirEntNum changed\n");
 
 		ncp_update_inode2(inode, &finfo);
 		mutex_unlock(&inode->i_mutex);
 	}
 
 finished:
-	DDPRINTK("ncp_lookup_validate: result=%d\n", val);
+	ncp_dbg(2, "result=%d\n", val);
 	dput(parent);
 	return val;
 }
@@ -453,8 +453,7 @@ static int ncp_readdir(struct file *file, struct dir_context *ctx)
 	ctl.page  = NULL;
 	ctl.cache = NULL;
 
-	DDPRINTK("ncp_readdir: reading %pD2, pos=%d\n", file,
-		(int) ctx->pos);
+	ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
 
 	result = -EIO;
 	/* Do not generate '.' and '..' when server is dead. */
@@ -697,8 +696,7 @@ ncp_read_volume_list(struct file *file, struct dir_context *ctx,
 	struct ncp_entry_info entry;
 	int i;
 
-	DPRINTK("ncp_read_volume_list: pos=%ld\n",
-			(unsigned long) ctx->pos);
+	ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos);
 
 	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
 		int inval_dentry;
@@ -708,12 +706,11 @@ ncp_read_volume_list(struct file *file, struct dir_context *ctx,
 		if (!strlen(info.volume_name))
 			continue;
 
-		DPRINTK("ncp_read_volume_list: found vol: %s\n",
-			info.volume_name);
+		ncp_dbg(1, "found vol: %s\n", info.volume_name);
 
 		if (ncp_lookup_volume(server, info.volume_name,
 					&entry.i)) {
-			DPRINTK("ncpfs: could not lookup vol %s\n",
+			ncp_dbg(1, "could not lookup vol %s\n",
 				info.volume_name);
 			continue;
 		}
@@ -738,14 +735,13 @@ ncp_do_readdir(struct file *file, struct dir_context *ctx,
 	int more;
 	size_t bufsize;
 
-	DPRINTK("ncp_do_readdir: %pD2, fpos=%ld\n", file,
-		(unsigned long) ctx->pos);
-	PPRINTK("ncp_do_readdir: init %pD, volnum=%d, dirent=%u\n",
-		file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
+	ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
+	ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
+		 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
 
 	err = ncp_initialize_search(server, dir, &seq);
 	if (err) {
-		DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
+		ncp_dbg(1, "init failed, err=%d\n", err);
 		return;
 	}
 	/* We MUST NOT use server->buffer_size handshaked with server if we are
@@ -808,8 +804,7 @@ int ncp_conn_logged_in(struct super_block *sb)
 			goto out;
 		result = -ENOENT;
 		if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
-			PPRINTK("ncp_conn_logged_in: %s not found\n",
-				server->m.mounted_vol);
+			ncp_vdbg("%s not found\n", server->m.mounted_vol);
 			goto out;
 		}
 		dent = sb->s_root;
@@ -822,10 +817,10 @@ int ncp_conn_logged_in(struct super_block *sb)
 				NCP_FINFO(ino)->DosDirNum = DosDirNum;
 				result = 0;
 			} else {
-				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
+				ncp_dbg(1, "sb->s_root->d_inode == NULL!\n");
 			}
 		} else {
-			DPRINTK("ncpfs: sb->s_root == NULL!\n");
+			ncp_dbg(1, "sb->s_root == NULL!\n");
 		}
 	} else
 		result = 0;
@@ -846,7 +841,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
 	if (!ncp_conn_valid(server))
 		goto finished;
 
-	PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry);
+	ncp_vdbg("server lookup for %pd2\n", dentry);
 
 	len = sizeof(__name);
 	if (ncp_is_server_root(dir)) {
@@ -854,15 +849,15 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
 				 dentry->d_name.len, 1);
 		if (!res)
 			res = ncp_lookup_volume(server, __name, &(finfo.i));
-			if (!res)
-				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+		if (!res)
+			ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
 	} else {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, !ncp_preserve_case(dir));
 		if (!res)
 			res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 	}
-	PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res);
+	ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
 	/*
 	 * If we didn't find an entry, make a negative dentry.
 	 */
@@ -886,7 +881,7 @@ add_entry:
 	}
 
 finished:
-	PPRINTK("ncp_lookup: result=%d\n", error);
+	ncp_vdbg("result=%d\n", error);
 	return ERR_PTR(error);
 }
 
@@ -909,7 +904,7 @@ out:
 	return error;
 
 out_close:
-	PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry);
+	ncp_vdbg("%pd2 failed, closing file\n", dentry);
 	ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
 	goto out;
 }
@@ -923,7 +918,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
 	int opmode;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 	
-	PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode);
+	ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
 
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
@@ -952,7 +947,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
 				error = -ENAMETOOLONG;
 			else if (result < 0)
 				error = result;
-			DPRINTK("ncp_create: %pd2 failed\n", dentry);
+			ncp_dbg(1, "%pd2 failed\n", dentry);
 			goto out;
 		}
 		opmode = O_WRONLY;
@@ -985,7 +980,7 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	int error, len;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
-	DPRINTK("ncp_mkdir: making %pd2\n", dentry);
+	ncp_dbg(1, "making %pd2\n", dentry);
 
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
@@ -1022,7 +1017,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
 	int error, result, len;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
-	DPRINTK("ncp_rmdir: removing %pd2\n", dentry);
+	ncp_dbg(1, "removing %pd2\n", dentry);
 
 	len = sizeof(__name);
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -1067,13 +1062,13 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
 	int error;
 
 	server = NCP_SERVER(dir);
-	DPRINTK("ncp_unlink: unlinking %pd2\n", dentry);
+	ncp_dbg(1, "unlinking %pd2\n", dentry);
 	
 	/*
 	 * Check whether to close the file ...
 	 */
 	if (inode) {
-		PPRINTK("ncp_unlink: closing file\n");
+		ncp_vdbg("closing file\n");
 		ncp_make_closed(inode);
 	}
 
@@ -1087,7 +1082,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
 #endif
 	switch (error) {
 		case 0x00:
-			DPRINTK("ncp: removed %pd2\n", dentry);
+			ncp_dbg(1, "removed %pd2\n", dentry);
 			break;
 		case 0x85:
 		case 0x8A:
@@ -1120,7 +1115,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
 	int old_len, new_len;
 	__u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
 
-	DPRINTK("ncp_rename: %pd2 to %pd2\n", old_dentry, new_dentry);
+	ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
 
 	ncp_age_dentry(server, old_dentry);
 	ncp_age_dentry(server, new_dentry);
@@ -1150,8 +1145,8 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
 #endif
 	switch (error) {
 		case 0x00:
-               	        DPRINTK("ncp renamed %pd -> %pd.\n",
-                                old_dentry, new_dentry);
+			ncp_dbg(1, "renamed %pd -> %pd\n",
+				old_dentry, new_dentry);
 			break;
 		case 0x9E:
 			error = -ENAMETOOLONG;
@@ -1173,7 +1168,7 @@ static int ncp_mknod(struct inode * dir, struct dentry *dentry,
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 	if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
-		DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
+		ncp_dbg(1, "mode = 0%ho\n", mode);
 		return ncp_create_new(dir, dentry, mode, rdev, 0);
 	}
 	return -EPERM; /* Strange, but true */
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 8f5074e1ecb9..77640a8bfb87 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -6,6 +6,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/uaccess.h>
 
 #include <linux/time.h>
@@ -34,11 +36,11 @@ int ncp_make_open(struct inode *inode, int right)
 
 	error = -EINVAL;
 	if (!inode) {
-		printk(KERN_ERR "ncp_make_open: got NULL inode\n");
+		pr_err("%s: got NULL inode\n", __func__);
 		goto out;
 	}
 
-	DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
+	ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n",
 		atomic_read(&NCP_FINFO(inode)->opened), 
 		NCP_FINFO(inode)->volNumber, 
 		NCP_FINFO(inode)->dirEntNum);
@@ -71,7 +73,7 @@ int ncp_make_open(struct inode *inode, int right)
 				break;
 		}
 		if (result) {
-			PPRINTK("ncp_make_open: failed, result=%d\n", result);
+			ncp_vdbg("failed, result=%d\n", result);
 			goto out_unlock;
 		}
 		/*
@@ -83,7 +85,7 @@ int ncp_make_open(struct inode *inode, int right)
 	}
 
 	access = NCP_FINFO(inode)->access;
-	PPRINTK("ncp_make_open: file open, access=%x\n", access);
+	ncp_vdbg("file open, access=%x\n", access);
 	if (access == right || access == O_RDWR) {
 		atomic_inc(&NCP_FINFO(inode)->opened);
 		error = 0;
@@ -107,7 +109,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	void* freepage;
 	size_t freelen;
 
-	DPRINTK("ncp_file_read: enter %pd2\n", dentry);
+	ncp_dbg(1, "enter %pd2\n", dentry);
 
 	pos = *ppos;
 
@@ -124,7 +126,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
 	error = ncp_make_open(inode, O_RDONLY);
 	if (error) {
-		DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
+		ncp_dbg(1, "open failed, error=%d\n", error);
 		return error;
 	}
 
@@ -165,7 +167,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
 	file_accessed(file);
 
-	DPRINTK("ncp_file_read: exit %pd2\n", dentry);
+	ncp_dbg(1, "exit %pd2\n", dentry);
 outrel:
 	ncp_inode_close(inode);		
 	return already_read ? already_read : error;
@@ -182,7 +184,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 	int errno;
 	void* bouncebuffer;
 
-	DPRINTK("ncp_file_write: enter %pd2\n", dentry);
+	ncp_dbg(1, "enter %pd2\n", dentry);
 	if ((ssize_t) count < 0)
 		return -EINVAL;
 	pos = *ppos;
@@ -211,7 +213,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 		return 0;
 	errno = ncp_make_open(inode, O_WRONLY);
 	if (errno) {
-		DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
+		ncp_dbg(1, "open failed, error=%d\n", errno);
 		return errno;
 	}
 	bufsize = NCP_SERVER(inode)->buffer_size;
@@ -261,7 +263,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 			i_size_write(inode, pos);
 		mutex_unlock(&inode->i_mutex);
 	}
-	DPRINTK("ncp_file_write: exit %pd2\n", dentry);
+	ncp_dbg(1, "exit %pd2\n", dentry);
 outrel:
 	ncp_inode_close(inode);		
 	return already_written ? already_written : errno;
@@ -269,7 +271,7 @@ outrel:
 
 static int ncp_release(struct inode *inode, struct file *file) {
 	if (ncp_make_closed(inode)) {
-		DPRINTK("ncp_release: failed to close\n");
+		ncp_dbg(1, "failed to close\n");
 	}
 	return 0;
 }
diff --git a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c
index 0af3349de851..03ffde1f44d6 100644
--- a/fs/ncpfs/getopt.c
+++ b/fs/ncpfs/getopt.c
@@ -2,6 +2,8 @@
  * getopt.c
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 
@@ -46,8 +48,8 @@ int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts
 				if (opts->has_arg & OPT_NOPARAM) {
 					return opts->val;
 				}
-				printk(KERN_INFO "%s: the %s option requires an argument\n",
-				       caller, token);
+				pr_info("%s: the %s option requires an argument\n",
+					caller, token);
 				return -EINVAL;
 			}
 			if (opts->has_arg & OPT_INT) {
@@ -57,18 +59,18 @@ int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts
 				if (!*v) {
 					return opts->val;
 				}
-				printk(KERN_INFO "%s: invalid numeric value in %s=%s\n",
+				pr_info("%s: invalid numeric value in %s=%s\n",
 					caller, token, val);
 				return -EDOM;
 			}
 			if (opts->has_arg & OPT_STRING) {
 				return opts->val;
 			}
-			printk(KERN_INFO "%s: unexpected argument %s to the %s option\n",
+			pr_info("%s: unexpected argument %s to the %s option\n",
 				caller, val, token);
 			return -EINVAL;
 		}
 	}
-	printk(KERN_INFO "%s: Unrecognized mount option %s\n", caller, token);
+	pr_info("%s: Unrecognized mount option %s\n", caller, token);
 	return -EOPNOTSUPP;
 }
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 2cf2ebecb55f..aae77f7e70c5 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -9,6 +9,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 
 #include <asm/uaccess.h>
@@ -132,7 +134,7 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
 	NCP_FINFO(inode)->access = nwinfo->access;
 	memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
 			sizeof(nwinfo->file_handle));
-	DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
+	ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n",
 		nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
 		NCP_FINFO(inode)->dirEntNum);
 }
@@ -140,8 +142,7 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
 {
 	/* NFS namespace mode overrides others if it's set. */
-	DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
-		nwi->entryName, nwi->nfs.mode);
+	ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode);
 	if (nwi->nfs.mode) {
 		/* XXX Security? */
 		inode->i_mode = nwi->nfs.mode;
@@ -229,7 +230,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 	
 	ncp_update_attrs(inode, nwinfo);
 
-	DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
+	ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode);
 
 	set_nlink(inode, 1);
 	inode->i_uid = server->m.uid;
@@ -257,7 +258,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 	struct inode *inode;
 
 	if (info == NULL) {
-		printk(KERN_ERR "ncp_iget: info is NULL\n");
+		pr_err("%s: info is NULL\n", __func__);
 		return NULL;
 	}
 
@@ -289,23 +290,23 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 		}
 		insert_inode_hash(inode);
 	} else
-		printk(KERN_ERR "ncp_iget: iget failed!\n");
+		pr_err("%s: iget failed!\n", __func__);
 	return inode;
 }
 
 static void
 ncp_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 
 	if (S_ISDIR(inode->i_mode)) {
-		DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
+		ncp_dbg(2, "put directory %ld\n", inode->i_ino);
 	}
 
 	if (ncp_make_closed(inode) != 0) {
 		/* We can't do anything but complain. */
-		printk(KERN_ERR "ncp_evict_inode: could not close\n");
+		pr_err("%s: could not close\n", __func__);
 	}
 }
 
@@ -620,7 +621,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 	   now because of PATH_MAX changes.. */
 	if (server->m.time_out < 1) {
 		server->m.time_out = 10;
-		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
+		pr_info("You need to recompile your ncpfs utils..\n");
 	}
 	server->m.time_out = server->m.time_out * HZ / 100;
 	server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
@@ -681,7 +682,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 	ncp_unlock_server(server);
 	if (error < 0)
 		goto out_rxbuf;
-	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+	ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
 
 	error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
@@ -709,7 +710,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 	if (ncp_negotiate_buffersize(server, default_bufsize,
   				     &(server->buffer_size)) != 0)
 		goto out_disconnect;
-	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
+	ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
 
 	memset(&finfo, 0, sizeof(finfo));
 	finfo.i.attributes	= aDIR;
@@ -738,7 +739,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
         root_inode = ncp_iget(sb, &finfo);
         if (!root_inode)
 		goto out_disconnect;
-	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+	ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 	sb->s_root = d_make_root(root_inode);
         if (!sb->s_root)
 		goto out_disconnect;
@@ -984,8 +985,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
 		int written;
 
-		DPRINTK("ncpfs: trying to change size to %ld\n",
-			attr->ia_size);
+		ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
 
 		if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
 			result = -EACCES;
@@ -1071,7 +1071,7 @@ MODULE_ALIAS_FS("ncpfs");
 static int __init init_ncp_fs(void)
 {
 	int err;
-	DPRINTK("ncpfs: init_ncp_fs called\n");
+	ncp_dbg(1, "called\n");
 
 	err = init_inodecache();
 	if (err)
@@ -1088,7 +1088,7 @@ out1:
 
 static void __exit exit_ncp_fs(void)
 {
-	DPRINTK("ncpfs: exit_ncp_fs called\n");
+	ncp_dbg(1, "called\n");
 	unregister_filesystem(&ncp_fs_type);
 	destroy_inodecache();
 }
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 60426ccb3b65..d5659d96ee7f 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -41,7 +41,7 @@ ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
 		return -EFAULT;
 
 	if (info.version != NCP_GET_FS_INFO_VERSION) {
-		DPRINTK("info.version invalid: %d\n", info.version);
+		ncp_dbg(1, "info.version invalid: %d\n", info.version);
 		return -EINVAL;
 	}
 	/* TODO: info.addr = server->m.serv_addr; */
@@ -66,7 +66,7 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		return -EFAULT;
 
 	if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
-		DPRINTK("info.version invalid: %d\n", info2.version);
+		ncp_dbg(1, "info.version invalid: %d\n", info2.version);
 		return -EINVAL;
 	}
 	info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
@@ -132,7 +132,7 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		return -EFAULT;
 
 	if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
-		DPRINTK("info.version invalid: %d\n", info2.version);
+		ncp_dbg(1, "info.version invalid: %d\n", info2.version);
 		return -EINVAL;
 	}
 	info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
@@ -308,8 +308,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
 		else
 			result = server->reply_size;
 		ncp_unlock_server(server);
-		DPRINTK("ncp_ioctl: copy %d bytes\n",
-			result);
+		ncp_dbg(1, "copy %d bytes\n", result);
 		if (result >= 0)
 			if (copy_to_user(request.data, bouncebuffer, result))
 				result = -EFAULT;
@@ -385,9 +384,9 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
 						sr.namespace = server->name_space[sr.volNumber];
 						result = 0;
 					} else
-						DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+						ncp_dbg(1, "s_root->d_inode==NULL\n");
 				} else
-					DPRINTK("ncpfs: s_root==NULL\n");
+					ncp_dbg(1, "s_root==NULL\n");
 			} else {
 				sr.volNumber = -1;
 				sr.namespace = 0;
@@ -440,11 +439,11 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
 							NCP_FINFO(s_inode)->DosDirNum = dosde;
 							server->root_setuped = 1;
 						} else {
-							DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+							ncp_dbg(1, "s_root->d_inode==NULL\n");
 							result = -EIO;
 						}
 					} else {
-						DPRINTK("ncpfs: s_root==NULL\n");
+						ncp_dbg(1, "s_root==NULL\n");
 						result = -EIO;
 					}
 				}
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index 3c5dd55d284c..b359d12eb359 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -107,7 +107,7 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file_inode(file);
 	
-	DPRINTK("ncp_mmap: called\n");
+	ncp_dbg(1, "called\n");
 
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
diff --git a/fs/ncpfs/ncp_fs.h b/fs/ncpfs/ncp_fs.h
index 31831afe1c3b..b9f69e1b1f43 100644
--- a/fs/ncpfs/ncp_fs.h
+++ b/fs/ncpfs/ncp_fs.h
@@ -2,30 +2,32 @@
 #include "ncp_fs_i.h"
 #include "ncp_fs_sb.h"
 
-/* define because it is easy to change PRINTK to {*}PRINTK */
-#define PRINTK(format, args...) printk(KERN_DEBUG format , ## args)
-
 #undef NCPFS_PARANOIA
 #ifdef NCPFS_PARANOIA
-#define PPRINTK(format, args...) PRINTK(format , ## args)
+#define ncp_vdbg(fmt, ...)					\
+	pr_debug(fmt, ##__VA_ARGS__)
 #else
-#define PPRINTK(format, args...)
+#define ncp_vdbg(fmt, ...)					\
+do {								\
+	if (0)							\
+		pr_debug(fmt, ##__VA_ARGS__);			\
+} while (0)
 #endif
 
 #ifndef DEBUG_NCP
 #define DEBUG_NCP 0
 #endif
-#if DEBUG_NCP > 0
-#define DPRINTK(format, args...) PRINTK(format , ## args)
-#else
-#define DPRINTK(format, args...)
-#endif
-#if DEBUG_NCP > 1
-#define DDPRINTK(format, args...) PRINTK(format , ## args)
-#else
-#define DDPRINTK(format, args...)
+
+#if DEBUG_NCP > 0 && !defined(DEBUG)
+#define DEBUG
 #endif
 
+#define ncp_dbg(level, fmt, ...)				\
+do {								\
+	if (level <= DEBUG_NCP)					\
+		pr_debug(fmt, ##__VA_ARGS__);			\
+} while (0)
+
 #define NCP_MAX_RPC_TIMEOUT (6*HZ)
 
 
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 981a95617fc9..482387532f54 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -9,14 +9,14 @@
  *
  */
 
-
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include "ncp_fs.h"
 
 static inline void assert_server_locked(struct ncp_server *server)
 {
 	if (server->lock == 0) {
-		DPRINTK("ncpfs: server not locked!\n");
+		ncp_dbg(1, "server not locked!\n");
 	}
 }
 
@@ -75,7 +75,7 @@ static void ncp_add_pstring(struct ncp_server *server, const char *s)
 	int len = strlen(s);
 	assert_server_locked(server);
 	if (len > 255) {
-		DPRINTK("ncpfs: string too long: %s\n", s);
+		ncp_dbg(1, "string too long: %s\n", s);
 		len = 255;
 	}
 	ncp_add_byte(server, len);
@@ -225,7 +225,7 @@ int ncp_get_volume_info_with_number(struct ncp_server* server,
 	result = -EIO;
 	len = ncp_reply_byte(server, 29);
 	if (len > NCP_VOLNAME_LEN) {
-		DPRINTK("ncpfs: volume name too long: %d\n", len);
+		ncp_dbg(1, "volume name too long: %d\n", len);
 		goto out;
 	}
 	memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
@@ -259,7 +259,7 @@ int ncp_get_directory_info(struct ncp_server* server, __u8 n,
 	result = -EIO;
 	len = ncp_reply_byte(server, 21);
 	if (len > NCP_VOLNAME_LEN) {
-		DPRINTK("ncpfs: volume name too long: %d\n", len);
+		ncp_dbg(1, "volume name too long: %d\n", len);
 		goto out;
 	}
 	memcpy(&(target->volume_name), ncp_reply_data(server, 22), len);
@@ -295,9 +295,9 @@ ncp_make_closed(struct inode *inode)
 		err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
 
 		if (!err)
-			PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
-				NCP_FINFO(inode)->volNumber,
-				NCP_FINFO(inode)->dirEntNum, err);
+			ncp_vdbg("volnum=%d, dirent=%u, error=%d\n",
+				 NCP_FINFO(inode)->volNumber,
+				 NCP_FINFO(inode)->dirEntNum, err);
 	}
 	mutex_unlock(&NCP_FINFO(inode)->open_mutex);
 	return err;
@@ -394,8 +394,7 @@ int ncp_obtain_nfs_info(struct ncp_server *server,
 
 		if ((result = ncp_request(server, 87)) == 0) {
 			ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs);
-			DPRINTK(KERN_DEBUG
-				"ncp_obtain_nfs_info: (%s) mode=0%o, rdev=0x%x\n",
+			ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n",
 				target->entryName, target->nfs.mode,
 				target->nfs.rdev);
 		} else {
@@ -425,7 +424,7 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *pa
 	int result;
 
 	if (target == NULL) {
-		printk(KERN_ERR "ncp_obtain_info: invalid call\n");
+		pr_err("%s: invalid call\n", __func__);
 		return -EINVAL;
 	}
 	ncp_init_request(server);
@@ -498,7 +497,7 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
 	namespace = ncp_reply_data(server, 2);
 
 	while (no_namespaces > 0) {
-		DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume);
+		ncp_dbg(1, "found %d on %d\n", *namespace, volume);
 
 #ifdef CONFIG_NCPFS_NFS_NS
 		if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) 
@@ -531,8 +530,7 @@ ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
 	if (ret_ns)
 		*ret_ns = ns;
 
-	DPRINTK("lookup_vol: namespace[%d] = %d\n",
-		volume, server->name_space[volume]);
+	ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]);
 
 	if (server->name_space[volume] == ns)
 		return 0;
@@ -596,7 +594,7 @@ ncp_get_volume_root(struct ncp_server *server,
 {
 	int result;
 
-	DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
+	ncp_dbg(1, "looking up vol %s\n", volname);
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 22);	/* Subfunction: Generate dir handle */
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index 3a1587222c8a..04a69a4d8e96 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -8,6 +8,7 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/time.h>
 #include <linux/errno.h>
@@ -231,7 +232,7 @@ static void __ncptcp_try_send(struct ncp_server *server)
 		return;
 
 	if (result < 0) {
-		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
+		pr_err("tcp: Send failed: %d\n", result);
 		__ncp_abort_request(server, rq, result);
 		return;
 	}
@@ -332,7 +333,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *
 	mutex_lock(&server->rcv.creq_mutex);
 	if (!ncp_conn_valid(server)) {
 		mutex_unlock(&server->rcv.creq_mutex);
-		printk(KERN_ERR "ncpfs: tcp: Server died\n");
+		pr_err("tcp: Server died\n");
 		return -EIO;
 	}
 	ncp_req_get(req);
@@ -405,15 +406,15 @@ void ncpdgram_rcv_proc(struct work_struct *work)
 				}
 				result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
 				if (result < 0) {
-					DPRINTK("recv failed with %d\n", result);
+					ncp_dbg(1, "recv failed with %d\n", result);
 					continue;
 				}
 				if (result < 10) {
-					DPRINTK("too short (%u) watchdog packet\n", result);
+					ncp_dbg(1, "too short (%u) watchdog packet\n", result);
 					continue;
 				}
 				if (buf[9] != '?') {
-					DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
+					ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]);
 					continue;
 				}
 				buf[9] = 'Y';
@@ -448,7 +449,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
 							result -= 8;
 							hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
 							if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
-								printk(KERN_INFO "ncpfs: Signature violation\n");
+								pr_info("Signature violation\n");
 								result = -EIO;
 							}
 						}
@@ -524,7 +525,7 @@ static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
 		return result;
 	}
 	if (result > len) {
-		printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
+		pr_err("tcp: bug in recvmsg (%u > %Zu)\n", result, len);
 		return -EIO;			
 	}
 	return result;
@@ -552,9 +553,9 @@ static int __ncptcp_rcv_proc(struct ncp_server *server)
 					__ncptcp_abort(server);
 				}
 				if (result < 0) {
-					printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
+					pr_err("tcp: error in recvmsg: %d\n", result);
 				} else {
-					DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
+					ncp_dbg(1, "tcp: EOF\n");
 				}
 				return -EIO;
 			}
@@ -566,20 +567,20 @@ static int __ncptcp_rcv_proc(struct ncp_server *server)
 		switch (server->rcv.state) {
 			case 0:
 				if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
-					printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
+					pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
 					__ncptcp_abort(server);
 					return -EIO;
 				}
 				datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
 				if (datalen < 10) {
-					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
+					pr_err("tcp: Unexpected reply len %d\n", datalen);
 					__ncptcp_abort(server);
 					return -EIO;
 				}
 #ifdef CONFIG_NCPFS_PACKET_SIGNING				
 				if (server->sign_active) {
 					if (datalen < 18) {
-						printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
+						pr_err("tcp: Unexpected reply len %d\n", datalen);
 						__ncptcp_abort(server);
 						return -EIO;
 					}
@@ -604,7 +605,7 @@ cont:;
 						server->rcv.len = datalen - 10;
 						break;
 					}					
-					DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
+					ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type);
 skipdata2:;
 					server->rcv.state = 2;
 skipdata:;
@@ -614,11 +615,11 @@ skipdata:;
 				}
 				req = server->rcv.creq;
 				if (!req) {
-					DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
+					ncp_dbg(1, "Reply without appropriate request\n");
 					goto skipdata2;
 				}
 				if (datalen > req->datalen + 8) {
-					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
+					pr_err("tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
 					server->rcv.state = 3;
 					goto skipdata;
 				}
@@ -638,12 +639,12 @@ skipdata:;
 				req = server->rcv.creq;
 				if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
 					if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
-						printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
+						pr_err("tcp: Bad sequence number\n");
 						__ncp_abort_request(server, req, -EIO);
 						return -EIO;
 					}
 					if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
-						printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
+						pr_err("tcp: Connection number mismatch\n");
 						__ncp_abort_request(server, req, -EIO);
 						return -EIO;
 					}
@@ -651,7 +652,7 @@ skipdata:;
 #ifdef CONFIG_NCPFS_PACKET_SIGNING				
 				if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
 					if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
-						printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
+						pr_err("tcp: Signature violation\n");
 						__ncp_abort_request(server, req, -EIO);
 						return -EIO;
 					}
@@ -742,7 +743,7 @@ static int ncp_do_request(struct ncp_server *server, int size,
 	int result;
 
 	if (server->lock == 0) {
-		printk(KERN_ERR "ncpfs: Server not locked!\n");
+		pr_err("Server not locked!\n");
 		return -EIO;
 	}
 	if (!ncp_conn_valid(server)) {
@@ -781,7 +782,7 @@ static int ncp_do_request(struct ncp_server *server, int size,
 		spin_unlock_irqrestore(&current->sighand->siglock, flags);
 	}
 
-	DDPRINTK("do_ncp_rpc_call returned %d\n", result);
+	ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
 
 	return result;
 }
@@ -811,7 +812,7 @@ int ncp_request2(struct ncp_server *server, int function,
 
 	result = ncp_do_request(server, server->current_size, reply, size);
 	if (result < 0) {
-		DPRINTK("ncp_request_error: %d\n", result);
+		ncp_dbg(1, "ncp_request_error: %d\n", result);
 		goto out;
 	}
 	server->completion = reply->completion_code;
@@ -822,7 +823,7 @@ int ncp_request2(struct ncp_server *server, int function,
 	result = reply->completion_code;
 
 	if (result != 0)
-		PPRINTK("ncp_request: completion code=%x\n", result);
+		ncp_vdbg("completion code=%x\n", result);
 out:
 	return result;
 }
@@ -865,14 +866,14 @@ void ncp_lock_server(struct ncp_server *server)
 {
 	mutex_lock(&server->mutex);
 	if (server->lock)
-		printk(KERN_WARNING "ncp_lock_server: was locked!\n");
+		pr_warn("%s: was locked!\n", __func__);
 	server->lock = 1;
 }
 
 void ncp_unlock_server(struct ncp_server *server)
 {
 	if (!server->lock) {
-		printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
+		pr_warn("%s: was not locked!\n", __func__);
 		return;
 	}
 	server->lock = 0;
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index 52439ddc8de0..1a63bfdb4a65 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -112,7 +112,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
 	__le32 attr;
 	unsigned int hdr;
 
-	DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
+	ncp_dbg(1, "dir=%p, dentry=%p, symname=%s\n", dir, dentry, symname);
 
 	if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
 		kludge = 0;
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 56ff823ca82e..65d849bdf77a 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -1213,7 +1213,7 @@ static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx)
 	end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE);
 	if (end != NFS_I(inode)->npages) {
 		rcu_read_lock();
-		end = radix_tree_next_hole(&mapping->page_tree, idx + 1, ULONG_MAX);
+		end = page_cache_next_hole(mapping, idx + 1, ULONG_MAX);
 		rcu_read_unlock();
 	}
 
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index ef792f29f831..5d8ccecf5f5c 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode,
 
 	rcu_read_lock();
 	delegation = rcu_dereference(NFS_I(inode)->delegation);
+	if (delegation == NULL)
+		goto out_enoent;
 
-	if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) {
-		rcu_read_unlock();
-		return -ENOENT;
-	}
+	if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
+		goto out_enoent;
 	nfs_mark_return_delegation(server, delegation);
 	rcu_read_unlock();
 
 	nfs_delegation_run_state_manager(clp);
 	return 0;
+out_enoent:
+	rcu_read_unlock();
+	return -ENOENT;
 }
 
 static struct inode *
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 5bb790a69c71..284ca901fe16 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -617,6 +617,7 @@ out:
 
 static const struct vm_operations_struct nfs_file_vm_ops = {
 	.fault = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = nfs_vm_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 360114ae8b82..c4702baa22b8 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(nfs_clear_inode);
 
 void nfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	nfs_clear_inode(inode);
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2da6a698b8f7..44e088dc357c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5828,8 +5828,7 @@ struct nfs_release_lockowner_data {
 	struct nfs4_lock_state *lsp;
 	struct nfs_server *server;
 	struct nfs_release_lockowner_args args;
-	struct nfs4_sequence_args seq_args;
-	struct nfs4_sequence_res seq_res;
+	struct nfs_release_lockowner_res res;
 	unsigned long timestamp;
 };
 
@@ -5837,7 +5836,7 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata
 {
 	struct nfs_release_lockowner_data *data = calldata;
 	nfs40_setup_sequence(data->server,
-				&data->seq_args, &data->seq_res, task);
+				&data->args.seq_args, &data->res.seq_res, task);
 	data->timestamp = jiffies;
 }
 
@@ -5846,7 +5845,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
 	struct nfs_release_lockowner_data *data = calldata;
 	struct nfs_server *server = data->server;
 
-	nfs40_sequence_done(task, &data->seq_res);
+	nfs40_sequence_done(task, &data->res.seq_res);
 
 	switch (task->tk_status) {
 	case 0:
@@ -5887,7 +5886,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
 	data = kmalloc(sizeof(*data), GFP_NOFS);
 	if (!data)
 		return -ENOMEM;
-	nfs4_init_sequence(&data->seq_args, &data->seq_res, 0);
 	data->lsp = lsp;
 	data->server = server;
 	data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
@@ -5895,6 +5893,8 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
 	data->args.lock_owner.s_dev = server->s_dev;
 
 	msg.rpc_argp = &data->args;
+	msg.rpc_resp = &data->res;
+	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
 	rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
 	return 0;
 }
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 808f29574412..6f340f02f2ba 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -90,7 +90,7 @@ static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
  */
 static void nfs4_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	pnfs_return_layout(inode);
 	pnfs_destroy_layout(NFS_I(inode));
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 06cddd572264..2645be435e75 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -71,10 +71,8 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 	if (gid_eq(new->fsgid, INVALID_GID))
 		new->fsgid = exp->ex_anon_gid;
 
-	ret = set_groups(new, gi);
+	set_groups(new, gi);
 	put_group_info(gi);
-	if (ret < 0)
-		goto error;
 
 	if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID))
 		new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
@@ -89,7 +87,6 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 
 oom:
 	ret = -ENOMEM;
-error:
 	abort_creds(new);
 	return ret;
 }
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 017d3cb5e99b..6d7be3f80356 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -449,6 +449,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 	fh_lock(fhp);
 	host_err = notify_change(dentry, iap, NULL);
 	fh_unlock(fhp);
+	err = nfserrno(host_err);
 
 out_put_write_access:
 	if (size_change)
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index deaa3d33a0aa..0d58075f34e2 100644
--- a/fs/nilfs2/cpfile.c
+++ b/fs/nilfs2/cpfile.c
@@ -942,6 +942,18 @@ int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
 	struct inode *cpfile;
 	int err;
 
+	if (cpsize > sb->s_blocksize) {
+		printk(KERN_ERR
+		       "NILFS: too large checkpoint size: %zu bytes.\n",
+		       cpsize);
+		return -EINVAL;
+	} else if (cpsize < NILFS_MIN_CHECKPOINT_SIZE) {
+		printk(KERN_ERR
+		       "NILFS: too small checkpoint size: %zu bytes.\n",
+		       cpsize);
+		return -EINVAL;
+	}
+
 	cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
 	if (unlikely(!cpfile))
 		return -ENOMEM;
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index fa0f80308c2d..0d5fada91191 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -484,6 +484,18 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
 	struct nilfs_dat_info *di;
 	int err;
 
+	if (entry_size > sb->s_blocksize) {
+		printk(KERN_ERR
+		       "NILFS: too large DAT entry size: %zu bytes.\n",
+		       entry_size);
+		return -EINVAL;
+	} else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) {
+		printk(KERN_ERR
+		       "NILFS: too small DAT entry size: %zu bytes.\n",
+		       entry_size);
+		return -EINVAL;
+	}
+
 	dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
 	if (unlikely(!dat))
 		return -ENOMEM;
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 08fdb77852ac..f3a82fbcae02 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -134,6 +134,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 static const struct vm_operations_struct nilfs_file_vm_ops = {
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite	= nilfs_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 7e350c562e0e..b9c5726120e3 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -783,16 +783,14 @@ void nilfs_evict_inode(struct inode *inode)
 	int ret;
 
 	if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
-		if (inode->i_data.nrpages)
-			truncate_inode_pages(&inode->i_data, 0);
+		truncate_inode_pages_final(&inode->i_data);
 		clear_inode(inode);
 		nilfs_clear_inode(inode);
 		return;
 	}
 	nilfs_transaction_begin(sb, &ti, 0); /* never fails */
 
-	if (inode->i_data.nrpages)
-		truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	/* TODO: some of the following operations may fail.  */
 	nilfs_truncate_bmap(ii, 0);
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 2b34021948e4..422fb54b7377 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -1072,6 +1072,48 @@ out:
 }
 
 /**
+ * nilfs_ioctl_trim_fs() - trim ioctl handle function
+ * @inode: inode object
+ * @argp: pointer on argument from userspace
+ *
+ * Decription: nilfs_ioctl_trim_fs is the FITRIM ioctl handle function. It
+ * checks the arguments from userspace and calls nilfs_sufile_trim_fs, which
+ * performs the actual trim operation.
+ *
+ * Return Value: On success, 0 is returned or negative error code, otherwise.
+ */
+static int nilfs_ioctl_trim_fs(struct inode *inode, void __user *argp)
+{
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct request_queue *q = bdev_get_queue(nilfs->ns_bdev);
+	struct fstrim_range range;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!blk_queue_discard(q))
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&range, argp, sizeof(range)))
+		return -EFAULT;
+
+	range.minlen = max_t(u64, range.minlen, q->limits.discard_granularity);
+
+	down_read(&nilfs->ns_segctor_sem);
+	ret = nilfs_sufile_trim_fs(nilfs->ns_sufile, &range);
+	up_read(&nilfs->ns_segctor_sem);
+
+	if (ret < 0)
+		return ret;
+
+	if (copy_to_user(argp, &range, sizeof(range)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
  * nilfs_ioctl_set_alloc_range - limit range of segments to be allocated
  * @inode: inode object
  * @argp: pointer on argument from userspace
@@ -1163,6 +1205,95 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
 	return ret;
 }
 
+/**
+ * nilfs_ioctl_set_suinfo - set segment usage info
+ * @inode: inode object
+ * @filp: file object
+ * @cmd: ioctl's request code
+ * @argp: pointer on argument from userspace
+ *
+ * Description: Expects an array of nilfs_suinfo_update structures
+ * encapsulated in nilfs_argv and updates the segment usage info
+ * according to the flags in nilfs_suinfo_update.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the
+ * following negative error codes is returned.
+ *
+ * %-EPERM - Not enough permissions
+ *
+ * %-EFAULT - Error copying input data
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
+ */
+static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
+				unsigned int cmd, void __user *argp)
+{
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct nilfs_transaction_info ti;
+	struct nilfs_argv argv;
+	size_t len;
+	void __user *base;
+	void *kbuf;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ret = mnt_want_write_file(filp);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	if (copy_from_user(&argv, argp, sizeof(argv)))
+		goto out;
+
+	ret = -EINVAL;
+	if (argv.v_size < sizeof(struct nilfs_suinfo_update))
+		goto out;
+
+	if (argv.v_nmembs > nilfs->ns_nsegments)
+		goto out;
+
+	if (argv.v_nmembs >= UINT_MAX / argv.v_size)
+		goto out;
+
+	len = argv.v_size * argv.v_nmembs;
+	if (!len) {
+		ret = 0;
+		goto out;
+	}
+
+	base = (void __user *)(unsigned long)argv.v_base;
+	kbuf = vmalloc(len);
+	if (!kbuf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(kbuf, base, len)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	nilfs_transaction_begin(inode->i_sb, &ti, 0);
+	ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
+			argv.v_nmembs);
+	if (unlikely(ret < 0))
+		nilfs_transaction_abort(inode->i_sb);
+	else
+		nilfs_transaction_commit(inode->i_sb); /* never fails */
+
+out_free:
+	vfree(kbuf);
+out:
+	mnt_drop_write_file(filp);
+	return ret;
+}
+
 long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -1189,6 +1320,8 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
 					    sizeof(struct nilfs_suinfo),
 					    nilfs_ioctl_do_get_suinfo);
+	case NILFS_IOCTL_SET_SUINFO:
+		return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_SUSTAT:
 		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_VINFO:
@@ -1205,6 +1338,8 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return nilfs_ioctl_resize(inode, filp, argp);
 	case NILFS_IOCTL_SET_ALLOC_RANGE:
 		return nilfs_ioctl_set_alloc_range(inode, argp);
+	case FITRIM:
+		return nilfs_ioctl_trim_fs(inode, argp);
 	default:
 		return -ENOTTY;
 	}
@@ -1228,6 +1363,7 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case NILFS_IOCTL_GET_CPINFO:
 	case NILFS_IOCTL_GET_CPSTAT:
 	case NILFS_IOCTL_GET_SUINFO:
+	case NILFS_IOCTL_SET_SUINFO:
 	case NILFS_IOCTL_GET_SUSTAT:
 	case NILFS_IOCTL_GET_VINFO:
 	case NILFS_IOCTL_GET_BDESCS:
@@ -1235,6 +1371,7 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case NILFS_IOCTL_SYNC:
 	case NILFS_IOCTL_RESIZE:
 	case NILFS_IOCTL_SET_ALLOC_RANGE:
+	case FITRIM:
 		break;
 	default:
 		return -ENOIOCTLCMD;
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 3127e9f438a7..2a869c35c362 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -870,6 +870,289 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 }
 
 /**
+ * nilfs_sufile_set_suinfo - sets segment usage info
+ * @sufile: inode of segment usage file
+ * @buf: array of suinfo_update
+ * @supsz: byte size of suinfo_update
+ * @nsup: size of suinfo_update array
+ *
+ * Description: Takes an array of nilfs_suinfo_update structs and updates
+ * segment usage accordingly. Only the fields indicated by the sup_flags
+ * are updated.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the
+ * following negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
+ */
+ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,
+				unsigned supsz, size_t nsup)
+{
+	struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
+	struct buffer_head *header_bh, *bh;
+	struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup;
+	struct nilfs_segment_usage *su;
+	void *kaddr;
+	unsigned long blkoff, prev_blkoff;
+	int cleansi, cleansu, dirtysi, dirtysu;
+	long ncleaned = 0, ndirtied = 0;
+	int ret = 0;
+
+	if (unlikely(nsup == 0))
+		return ret;
+
+	for (sup = buf; sup < supend; sup = (void *)sup + supsz) {
+		if (sup->sup_segnum >= nilfs->ns_nsegments
+			|| (sup->sup_flags &
+				(~0UL << __NR_NILFS_SUINFO_UPDATE_FIELDS))
+			|| (nilfs_suinfo_update_nblocks(sup) &&
+				sup->sup_sui.sui_nblocks >
+				nilfs->ns_blocks_per_segment))
+			return -EINVAL;
+	}
+
+	down_write(&NILFS_MDT(sufile)->mi_sem);
+
+	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
+	if (ret < 0)
+		goto out_sem;
+
+	sup = buf;
+	blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+	ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+	if (ret < 0)
+		goto out_header;
+
+	for (;;) {
+		kaddr = kmap_atomic(bh->b_page);
+		su = nilfs_sufile_block_get_segment_usage(
+			sufile, sup->sup_segnum, bh, kaddr);
+
+		if (nilfs_suinfo_update_lastmod(sup))
+			su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
+
+		if (nilfs_suinfo_update_nblocks(sup))
+			su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
+
+		if (nilfs_suinfo_update_flags(sup)) {
+			/*
+			 * Active flag is a virtual flag projected by running
+			 * nilfs kernel code - drop it not to write it to
+			 * disk.
+			 */
+			sup->sup_sui.sui_flags &=
+					~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
+
+			cleansi = nilfs_suinfo_clean(&sup->sup_sui);
+			cleansu = nilfs_segment_usage_clean(su);
+			dirtysi = nilfs_suinfo_dirty(&sup->sup_sui);
+			dirtysu = nilfs_segment_usage_dirty(su);
+
+			if (cleansi && !cleansu)
+				++ncleaned;
+			else if (!cleansi && cleansu)
+				--ncleaned;
+
+			if (dirtysi && !dirtysu)
+				++ndirtied;
+			else if (!dirtysi && dirtysu)
+				--ndirtied;
+
+			su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
+		}
+
+		kunmap_atomic(kaddr);
+
+		sup = (void *)sup + supsz;
+		if (sup >= supend)
+			break;
+
+		prev_blkoff = blkoff;
+		blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+		if (blkoff == prev_blkoff)
+			continue;
+
+		/* get different block */
+		mark_buffer_dirty(bh);
+		put_bh(bh);
+		ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+		if (unlikely(ret < 0))
+			goto out_mark;
+	}
+	mark_buffer_dirty(bh);
+	put_bh(bh);
+
+ out_mark:
+	if (ncleaned || ndirtied) {
+		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
+				(u64)ndirtied);
+		NILFS_SUI(sufile)->ncleansegs += ncleaned;
+	}
+	nilfs_mdt_mark_dirty(sufile);
+ out_header:
+	put_bh(header_bh);
+ out_sem:
+	up_write(&NILFS_MDT(sufile)->mi_sem);
+	return ret;
+}
+
+/**
+ * nilfs_sufile_trim_fs() - trim ioctl handle function
+ * @sufile: inode of segment usage file
+ * @range: fstrim_range structure
+ *
+ * start:	First Byte to trim
+ * len:		number of Bytes to trim from start
+ * minlen:	minimum extent length in Bytes
+ *
+ * Decription: nilfs_sufile_trim_fs goes through all segments containing bytes
+ * from start to start+len. start is rounded up to the next block boundary
+ * and start+len is rounded down. For each clean segment blkdev_issue_discard
+ * function is invoked.
+ *
+ * Return Value: On success, 0 is returned or negative error code, otherwise.
+ */
+int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
+{
+	struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
+	struct buffer_head *su_bh;
+	struct nilfs_segment_usage *su;
+	void *kaddr;
+	size_t n, i, susz = NILFS_MDT(sufile)->mi_entry_size;
+	sector_t seg_start, seg_end, start_block, end_block;
+	sector_t start = 0, nblocks = 0;
+	u64 segnum, segnum_end, minlen, len, max_blocks, ndiscarded = 0;
+	int ret = 0;
+	unsigned int sects_per_block;
+
+	sects_per_block = (1 << nilfs->ns_blocksize_bits) /
+			bdev_logical_block_size(nilfs->ns_bdev);
+	len = range->len >> nilfs->ns_blocksize_bits;
+	minlen = range->minlen >> nilfs->ns_blocksize_bits;
+	max_blocks = ((u64)nilfs->ns_nsegments * nilfs->ns_blocks_per_segment);
+
+	if (!len || range->start >= max_blocks << nilfs->ns_blocksize_bits)
+		return -EINVAL;
+
+	start_block = (range->start + nilfs->ns_blocksize - 1) >>
+			nilfs->ns_blocksize_bits;
+
+	/*
+	 * range->len can be very large (actually, it is set to
+	 * ULLONG_MAX by default) - truncate upper end of the range
+	 * carefully so as not to overflow.
+	 */
+	if (max_blocks - start_block < len)
+		end_block = max_blocks - 1;
+	else
+		end_block = start_block + len - 1;
+
+	segnum = nilfs_get_segnum_of_block(nilfs, start_block);
+	segnum_end = nilfs_get_segnum_of_block(nilfs, end_block);
+
+	down_read(&NILFS_MDT(sufile)->mi_sem);
+
+	while (segnum <= segnum_end) {
+		n = nilfs_sufile_segment_usages_in_block(sufile, segnum,
+				segnum_end);
+
+		ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0,
+							   &su_bh);
+		if (ret < 0) {
+			if (ret != -ENOENT)
+				goto out_sem;
+			/* hole */
+			segnum += n;
+			continue;
+		}
+
+		kaddr = kmap_atomic(su_bh->b_page);
+		su = nilfs_sufile_block_get_segment_usage(sufile, segnum,
+				su_bh, kaddr);
+		for (i = 0; i < n; ++i, ++segnum, su = (void *)su + susz) {
+			if (!nilfs_segment_usage_clean(su))
+				continue;
+
+			nilfs_get_segment_range(nilfs, segnum, &seg_start,
+						&seg_end);
+
+			if (!nblocks) {
+				/* start new extent */
+				start = seg_start;
+				nblocks = seg_end - seg_start + 1;
+				continue;
+			}
+
+			if (start + nblocks == seg_start) {
+				/* add to previous extent */
+				nblocks += seg_end - seg_start + 1;
+				continue;
+			}
+
+			/* discard previous extent */
+			if (start < start_block) {
+				nblocks -= start_block - start;
+				start = start_block;
+			}
+
+			if (nblocks >= minlen) {
+				kunmap_atomic(kaddr);
+
+				ret = blkdev_issue_discard(nilfs->ns_bdev,
+						start * sects_per_block,
+						nblocks * sects_per_block,
+						GFP_NOFS, 0);
+				if (ret < 0) {
+					put_bh(su_bh);
+					goto out_sem;
+				}
+
+				ndiscarded += nblocks;
+				kaddr = kmap_atomic(su_bh->b_page);
+				su = nilfs_sufile_block_get_segment_usage(
+					sufile, segnum, su_bh, kaddr);
+			}
+
+			/* start new extent */
+			start = seg_start;
+			nblocks = seg_end - seg_start + 1;
+		}
+		kunmap_atomic(kaddr);
+		put_bh(su_bh);
+	}
+
+
+	if (nblocks) {
+		/* discard last extent */
+		if (start < start_block) {
+			nblocks -= start_block - start;
+			start = start_block;
+		}
+		if (start + nblocks > end_block + 1)
+			nblocks = end_block - start + 1;
+
+		if (nblocks >= minlen) {
+			ret = blkdev_issue_discard(nilfs->ns_bdev,
+					start * sects_per_block,
+					nblocks * sects_per_block,
+					GFP_NOFS, 0);
+			if (!ret)
+				ndiscarded += nblocks;
+		}
+	}
+
+out_sem:
+	up_read(&NILFS_MDT(sufile)->mi_sem);
+
+	range->len = ndiscarded << nilfs->ns_blocksize_bits;
+	return ret;
+}
+
+/**
  * nilfs_sufile_read - read or get sufile inode
  * @sb: super block instance
  * @susize: size of a segment usage entry
@@ -886,6 +1169,18 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize,
 	void *kaddr;
 	int err;
 
+	if (susize > sb->s_blocksize) {
+		printk(KERN_ERR
+		       "NILFS: too large segment usage size: %zu bytes.\n",
+		       susize);
+		return -EINVAL;
+	} else if (susize < NILFS_MIN_SEGMENT_USAGE_SIZE) {
+		printk(KERN_ERR
+		       "NILFS: too small segment usage size: %zu bytes.\n",
+		       susize);
+		return -EINVAL;
+	}
+
 	sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
 	if (unlikely(!sufile))
 		return -ENOMEM;
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h
index e84bc5b51fc1..b8afd72f2379 100644
--- a/fs/nilfs2/sufile.h
+++ b/fs/nilfs2/sufile.h
@@ -44,6 +44,7 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
 int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
 ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
 				size_t);
+ssize_t nilfs_sufile_set_suinfo(struct inode *, void *, unsigned , size_t);
 
 int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
 			 void (*dofunc)(struct inode *, __u64,
@@ -65,6 +66,7 @@ void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
 int nilfs_sufile_resize(struct inode *sufile, __u64 newnsegs);
 int nilfs_sufile_read(struct super_block *sb, size_t susize,
 		      struct nilfs_inode *raw_inode, struct inode **inodep);
+int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range);
 
 /**
  * nilfs_sufile_scrap - make a segment garbage
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 94c451ce6d24..8ba8229ba076 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -399,6 +399,16 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
 		return -EINVAL;
 
 	nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size);
+	if (nilfs->ns_inode_size > nilfs->ns_blocksize) {
+		printk(KERN_ERR "NILFS: too large inode size: %d bytes.\n",
+		       nilfs->ns_inode_size);
+		return -EINVAL;
+	} else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) {
+		printk(KERN_ERR "NILFS: too small inode size: %d bytes.\n",
+		       nilfs->ns_inode_size);
+		return -EINVAL;
+	}
+
 	nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
 
 	nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index ffb9b3675736..9d8153ebacfb 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2259,7 +2259,7 @@ void ntfs_evict_big_inode(struct inode *vi)
 {
 	ntfs_inode *ni = NTFS_I(vi);
 
-	truncate_inode_pages(&vi->i_data, 0);
+	truncate_inode_pages_final(&vi->i_data);
 	clear_inode(vi);
 
 #ifdef NTFS_RW
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index e2edff38be52..6b97d68e34d3 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -6932,6 +6932,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
 	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
 	spin_unlock(&oi->ip_lock);
 
+	ocfs2_update_inode_fsync_trans(handle, inode, 1);
 	ocfs2_dinode_new_extent_list(inode, di);
 
 	ocfs2_journal_dirty(handle, di_bh);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index aeb44e879c51..d310d12a9adc 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -571,7 +571,6 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 {
 	struct inode *inode = file_inode(iocb->ki_filp);
 	int level;
-	wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
 
 	/* this io's submitter should not have unlocked this before we could */
 	BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -582,10 +581,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 	if (ocfs2_iocb_is_unaligned_aio(iocb)) {
 		ocfs2_iocb_clear_unaligned_aio(iocb);
 
-		if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) &&
-		    waitqueue_active(wq)) {
-			wake_up_all(wq);
-		}
+		mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio);
 	}
 
 	ocfs2_iocb_clear_rw_locked(iocb);
@@ -2043,6 +2039,7 @@ out_write_size:
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
 	di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+	ocfs2_update_inode_fsync_trans(handle, inode, 1);
 	ocfs2_journal_dirty(handle, wc->w_di_bh);
 
 	ocfs2_commit_trans(osb, handle);
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index f671e49beb34..6cae155d54df 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -102,9 +102,4 @@ enum ocfs2_iocb_lock_bits {
 #define ocfs2_iocb_is_unaligned_aio(iocb) \
 	test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
 
-#define OCFS2_IOEND_WQ_HASH_SZ	37
-#define ocfs2_ioend_wq(v)   (&ocfs2__ioend_wq[((unsigned long)(v)) %\
-					    OCFS2_IOEND_WQ_HASH_SZ])
-extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
-
 #endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 2cd2406b4140..1828201bc901 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1826,7 +1826,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;
@@ -1837,6 +1837,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)
@@ -1848,6 +1849,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);
@@ -1949,8 +1951,15 @@ out:
 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;
+
+	for (;;) {
+		err = o2net_accept_one(sock, &more);
+		if (!more)
+			break;
 		cond_resched();
+	}
 }
 
 static void o2net_listen_data_ready(struct sock *sk, int bytes)
@@ -1964,18 +1973,30 @@ static void o2net_listen_data_ready(struct sock *sk, int bytes)
 		goto out;
 	}
 
-	/* ->sk_data_ready is also called for a newly established child socket
-	 * before it has been accepted and the acceptor has set up their
-	 * data_ready.. we only want to queue listen work for our listening
-	 * socket */
+	/* This callback may called twice when a new connection
+	 * is  being established as a child socket inherits everything
+	 * from a parent LISTEN socket, including the data_ready cb of
+	 * the parent. This leads to a hazard. In o2net_accept_one()
+	 * we are still initializing the child socket but have not
+	 * changed the inherited data_ready callback yet when
+	 * data starts arriving.
+	 * We avoid this hazard by checking the state.
+	 * For the listening socket,  the state will be TCP_LISTEN; for the new
+	 * socket, will be  TCP_ESTABLISHED. Also, in this case,
+	 * sk->sk_user_data is not a valid function pointer.
+	 */
+
 	if (sk->sk_state == TCP_LISTEN) {
 		mlog(ML_TCP, "bytes: %d\n", bytes);
 		queue_work(o2net_wq, &o2net_listen_work);
+	} else {
+		ready = NULL;
 	}
 
 out:
 	read_unlock(&sk->sk_callback_lock);
-	ready(sk, bytes);
+	if (ready != NULL)
+		ready(sk, bytes);
 }
 
 static int o2net_open_listening_sock(__be32 addr, __be16 port)
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 0d3a97d2d5f6..e2e05a106beb 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -37,7 +37,6 @@
 #include "dlmglue.h"
 #include "file.h"
 #include "inode.h"
-#include "super.h"
 #include "ocfs2_trace.h"
 
 void ocfs2_dentry_attach_gen(struct dentry *dentry)
@@ -346,52 +345,6 @@ out_attach:
 	return ret;
 }
 
-DEFINE_SPINLOCK(dentry_list_lock);
-
-/* We limit the number of dentry locks to drop in one go. We have
- * this limit so that we don't starve other users of ocfs2_wq. */
-#define DL_INODE_DROP_COUNT 64
-
-/* Drop inode references from dentry locks */
-static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
-{
-	struct ocfs2_dentry_lock *dl;
-
-	spin_lock(&dentry_list_lock);
-	while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
-		dl = osb->dentry_lock_list;
-		osb->dentry_lock_list = dl->dl_next;
-		spin_unlock(&dentry_list_lock);
-		iput(dl->dl_inode);
-		kfree(dl);
-		spin_lock(&dentry_list_lock);
-	}
-	spin_unlock(&dentry_list_lock);
-}
-
-void ocfs2_drop_dl_inodes(struct work_struct *work)
-{
-	struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
-					       dentry_lock_work);
-
-	__ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
-	/*
-	 * Don't queue dropping if umount is in progress. We flush the
-	 * list in ocfs2_dismount_volume
-	 */
-	spin_lock(&dentry_list_lock);
-	if (osb->dentry_lock_list &&
-	    !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
-		queue_work(ocfs2_wq, &osb->dentry_lock_work);
-	spin_unlock(&dentry_list_lock);
-}
-
-/* Flush the whole work queue */
-void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
-{
-	__ocfs2_drop_dl_inodes(osb, -1);
-}
-
 /*
  * ocfs2_dentry_iput() and friends.
  *
@@ -416,24 +369,16 @@ void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
 static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
 				   struct ocfs2_dentry_lock *dl)
 {
+	iput(dl->dl_inode);
 	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
 	ocfs2_lock_res_free(&dl->dl_lockres);
-
-	/* We leave dropping of inode reference to ocfs2_wq as that can
-	 * possibly lead to inode deletion which gets tricky */
-	spin_lock(&dentry_list_lock);
-	if (!osb->dentry_lock_list &&
-	    !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
-		queue_work(ocfs2_wq, &osb->dentry_lock_work);
-	dl->dl_next = osb->dentry_lock_list;
-	osb->dentry_lock_list = dl;
-	spin_unlock(&dentry_list_lock);
+	kfree(dl);
 }
 
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
 			   struct ocfs2_dentry_lock *dl)
 {
-	int unlock;
+	int unlock = 0;
 
 	BUG_ON(dl->dl_count == 0);
 
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index b79eff709958..55f58892b153 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -29,13 +29,8 @@
 extern const struct dentry_operations ocfs2_dentry_ops;
 
 struct ocfs2_dentry_lock {
-	/* Use count of dentry lock */
 	unsigned int		dl_count;
-	union {
-		/* Linked list of dentry locks to release */
-		struct ocfs2_dentry_lock *dl_next;
-		u64			dl_parent_blkno;
-	};
+	u64			dl_parent_blkno;
 
 	/*
 	 * The ocfs2_dentry_lock keeps an inode reference until
@@ -49,14 +44,9 @@ struct ocfs2_dentry_lock {
 int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
 			     u64 parent_blkno);
 
-extern spinlock_t dentry_list_lock;
-
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
 			   struct ocfs2_dentry_lock *dl);
 
-void ocfs2_drop_dl_inodes(struct work_struct *work);
-void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb);
-
 struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
 				      int skip_unhashed);
 
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 91a7e85ac8fd..8b48e9b7ad0e 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2957,6 +2957,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
 		ocfs2_init_dir_trailer(dir, dirdata_bh, i);
 	}
 
+	ocfs2_update_inode_fsync_trans(handle, dir, 1);
 	ocfs2_journal_dirty(handle, dirdata_bh);
 
 	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
@@ -3338,6 +3339,7 @@ do_extend:
 	} else {
 		de->rec_len = cpu_to_le16(sb->s_blocksize);
 	}
+	ocfs2_update_inode_fsync_trans(handle, dir, 1);
 	ocfs2_journal_dirty(handle, new_bh);
 
 	dir_i_size += dir->i_sb->s_blocksize;
@@ -3896,6 +3898,7 @@ out_commit:
 		dquot_free_space_nodirty(dir,
 				ocfs2_clusters_to_bytes(dir->i_sb, 1));
 
+	ocfs2_update_inode_fsync_trans(handle, dir, 1);
 	ocfs2_commit_trans(osb, handle);
 
 out:
@@ -4134,6 +4137,7 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
 		mlog_errno(ret);
 	did_quota = 0;
 
+	ocfs2_update_inode_fsync_trans(handle, dir, 1);
 	ocfs2_journal_dirty(handle, dx_root_bh);
 
 out_commit:
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 33660a4a52fa..1307a8cff8db 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -1877,19 +1877,19 @@ static int dlm_join_domain(struct dlm_ctxt *dlm)
 		goto bail;
 	}
 
-	status = dlm_debug_init(dlm);
+	status = dlm_launch_thread(dlm);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 
-	status = dlm_launch_thread(dlm);
+	status = dlm_launch_recovery_thread(dlm);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 
-	status = dlm_launch_recovery_thread(dlm);
+	status = dlm_debug_init(dlm);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 7035af09cc03..fe29f7978f81 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -537,7 +537,10 @@ master_here:
 		/* success!  see if any other nodes need recovery */
 		mlog(0, "DONE mastering recovery of %s:%u here(this=%u)!\n",
 		     dlm->name, dlm->reco.dead_node, dlm->node_num);
-		dlm_reset_recovery(dlm);
+		spin_lock(&dlm->spinlock);
+		__dlm_reset_recovery(dlm);
+		dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+		spin_unlock(&dlm->spinlock);
 	}
 	dlm_end_recovery(dlm);
 
@@ -695,6 +698,14 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
 		if (all_nodes_done) {
 			int ret;
 
+			/* Set this flag on recovery master to avoid
+			 * a new recovery for another dead node start
+			 * before the recovery is not done. That may
+			 * cause recovery hung.*/
+			spin_lock(&dlm->spinlock);
+			dlm->reco.state |= DLM_RECO_STATE_FINALIZE;
+			spin_unlock(&dlm->spinlock);
+
 			/* all nodes are now in DLM_RECO_NODE_DATA_DONE state
 	 		 * just send a finalize message to everyone and
 	 		 * clean up */
@@ -1750,13 +1761,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 				     struct dlm_migratable_lockres *mres)
 {
 	struct dlm_migratable_lock *ml;
-	struct list_head *queue;
+	struct list_head *queue, *iter;
 	struct list_head *tmpq = NULL;
 	struct dlm_lock *newlock = NULL;
 	struct dlm_lockstatus *lksb = NULL;
 	int ret = 0;
 	int i, j, bad;
-	struct dlm_lock *lock = NULL;
+	struct dlm_lock *lock;
 	u8 from = O2NM_MAX_NODES;
 	unsigned int added = 0;
 	__be64 c;
@@ -1791,14 +1802,16 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 			/* MIGRATION ONLY! */
 			BUG_ON(!(mres->flags & DLM_MRES_MIGRATION));
 
+			lock = NULL;
 			spin_lock(&res->spinlock);
 			for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
 				tmpq = dlm_list_idx_to_ptr(res, j);
-				list_for_each_entry(lock, tmpq, list) {
-					if (lock->ml.cookie != ml->cookie)
-						lock = NULL;
-					else
+				list_for_each(iter, tmpq) {
+					lock = list_entry(iter,
+						  struct dlm_lock, list);
+					if (lock->ml.cookie == ml->cookie)
 						break;
+					lock = NULL;
 				}
 				if (lock)
 					break;
@@ -2882,8 +2895,8 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
 				BUG();
 			}
 			dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+			__dlm_reset_recovery(dlm);
 			spin_unlock(&dlm->spinlock);
-			dlm_reset_recovery(dlm);
 			dlm_kick_recovery_thread(dlm);
 			break;
 		default:
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 19986959d149..6bd690b5a061 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -3144,22 +3144,60 @@ out:
 	return 0;
 }
 
+static void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
+				       struct ocfs2_lock_res *lockres);
+
 /* Mark the lockres as being dropped. It will no longer be
  * queued if blocking, but we still may have to wait on it
  * being dequeued from the downconvert thread before we can consider
  * it safe to drop.
  *
  * You can *not* attempt to call cluster_lock on this lockres anymore. */
-void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres)
+void ocfs2_mark_lockres_freeing(struct ocfs2_super *osb,
+				struct ocfs2_lock_res *lockres)
 {
 	int status;
 	struct ocfs2_mask_waiter mw;
-	unsigned long flags;
+	unsigned long flags, flags2;
 
 	ocfs2_init_mask_waiter(&mw);
 
 	spin_lock_irqsave(&lockres->l_lock, flags);
 	lockres->l_flags |= OCFS2_LOCK_FREEING;
+	if (lockres->l_flags & OCFS2_LOCK_QUEUED && current == osb->dc_task) {
+		/*
+		 * We know the downconvert is queued but not in progress
+		 * because we are the downconvert thread and processing
+		 * different lock. So we can just remove the lock from the
+		 * queue. This is not only an optimization but also a way
+		 * to avoid the following deadlock:
+		 *   ocfs2_dentry_post_unlock()
+		 *     ocfs2_dentry_lock_put()
+		 *       ocfs2_drop_dentry_lock()
+		 *         iput()
+		 *           ocfs2_evict_inode()
+		 *             ocfs2_clear_inode()
+		 *               ocfs2_mark_lockres_freeing()
+		 *                 ... blocks waiting for OCFS2_LOCK_QUEUED
+		 *                 since we are the downconvert thread which
+		 *                 should clear the flag.
+		 */
+		spin_unlock_irqrestore(&lockres->l_lock, flags);
+		spin_lock_irqsave(&osb->dc_task_lock, flags2);
+		list_del_init(&lockres->l_blocked_list);
+		osb->blocked_lock_count--;
+		spin_unlock_irqrestore(&osb->dc_task_lock, flags2);
+		/*
+		 * Warn if we recurse into another post_unlock call.  Strictly
+		 * speaking it isn't a problem but we need to be careful if
+		 * that happens (stack overflow, deadlocks, ...) so warn if
+		 * ocfs2 grows a path for which this can happen.
+		 */
+		WARN_ON_ONCE(lockres->l_ops->post_unlock);
+		/* Since the lock is freeing we don't do much in the fn below */
+		ocfs2_process_blocked_lock(osb, lockres);
+		return;
+	}
 	while (lockres->l_flags & OCFS2_LOCK_QUEUED) {
 		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_QUEUED, 0);
 		spin_unlock_irqrestore(&lockres->l_lock, flags);
@@ -3180,7 +3218,7 @@ void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
 {
 	int ret;
 
-	ocfs2_mark_lockres_freeing(lockres);
+	ocfs2_mark_lockres_freeing(osb, lockres);
 	ret = ocfs2_drop_lock(osb, lockres);
 	if (ret)
 		mlog_errno(ret);
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 1d596d8c4a4a..d293a22c32c5 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -157,7 +157,8 @@ int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex);
 void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex);
 
 
-void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
+void ocfs2_mark_lockres_freeing(struct ocfs2_super *osb,
+				struct ocfs2_lock_res *lockres);
 void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
 			       struct ocfs2_lock_res *lockres);
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8450262bcf2a..b54cd094784f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -175,9 +175,13 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
 			   int datasync)
 {
 	int err = 0;
-	journal_t *journal;
 	struct inode *inode = file->f_mapping->host;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+	journal_t *journal = osb->journal->j_journal;
+	int ret;
+	tid_t commit_tid;
+	bool needs_barrier = false;
 
 	trace_ocfs2_sync_file(inode, file, file->f_path.dentry,
 			      OCFS2_I(inode)->ip_blkno,
@@ -192,29 +196,19 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
 	if (err)
 		return err;
 
-	/*
-	 * Probably don't need the i_mutex at all in here, just putting it here
-	 * to be consistent with how fsync used to be called, someone more
-	 * familiar with the fs could possibly remove it.
-	 */
-	mutex_lock(&inode->i_mutex);
-	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
-		/*
-		 * We still have to flush drive's caches to get data to the
-		 * platter
-		 */
-		if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
-			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
-		goto bail;
+	commit_tid = datasync ? oi->i_datasync_tid : oi->i_sync_tid;
+	if (journal->j_flags & JBD2_BARRIER &&
+	    !jbd2_trans_will_send_data_barrier(journal, commit_tid))
+		needs_barrier = true;
+	err = jbd2_complete_transaction(journal, commit_tid);
+	if (needs_barrier) {
+		ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+		if (!err)
+			err = ret;
 	}
 
-	journal = osb->journal->j_journal;
-	err = jbd2_journal_force_commit(journal);
-
-bail:
 	if (err)
 		mlog_errno(err);
-	mutex_unlock(&inode->i_mutex);
 
 	return (err < 0) ? -EIO : 0;
 }
@@ -650,7 +644,7 @@ restarted_transaction:
 			mlog_errno(status);
 		goto leave;
 	}
-
+	ocfs2_update_inode_fsync_trans(handle, inode, 1);
 	ocfs2_journal_dirty(handle, bh);
 
 	spin_lock(&OCFS2_I(inode)->ip_lock);
@@ -2061,13 +2055,6 @@ out:
 	return ret;
 }
 
-static void ocfs2_aiodio_wait(struct inode *inode)
-{
-	wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
-
-	wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0));
-}
-
 static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
 {
 	int blockmask = inode->i_sb->s_blocksize - 1;
@@ -2345,10 +2332,8 @@ relock:
 		 * Wait on previous unaligned aio to complete before
 		 * proceeding.
 		 */
-		ocfs2_aiodio_wait(inode);
-
-		/* Mark the iocb as needing a decrement in ocfs2_dio_end_io */
-		atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio);
+		mutex_lock(&OCFS2_I(inode)->ip_unaligned_aio);
+		/* Mark the iocb as needing an unlock in ocfs2_dio_end_io */
 		ocfs2_iocb_set_unaligned_aio(iocb);
 	}
 
@@ -2428,7 +2413,7 @@ out_dio:
 
 	if (unaligned_dio) {
 		ocfs2_iocb_clear_unaligned_aio(iocb);
-		atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio);
+		mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio);
 	}
 
 out:
@@ -2645,7 +2630,16 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
 	case SEEK_SET:
 		break;
 	case SEEK_END:
-		offset += inode->i_size;
+		/* SEEK_END requires the OCFS2 inode lock for the file
+		 * because it references the file's size.
+		 */
+		ret = ocfs2_inode_lock(inode, NULL, 0);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+		offset += i_size_read(inode);
+		ocfs2_inode_unlock(inode, 0);
 		break;
 	case SEEK_CUR:
 		if (offset == 0) {
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index f29a90fde619..437de7f768c6 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -130,6 +130,7 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
 	struct inode *inode = NULL;
 	struct super_block *sb = osb->sb;
 	struct ocfs2_find_inode_args args;
+	journal_t *journal = OCFS2_SB(sb)->journal->j_journal;
 
 	trace_ocfs2_iget_begin((unsigned long long)blkno, flags,
 			       sysfile_type);
@@ -169,6 +170,32 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
 		goto bail;
 	}
 
+	/*
+	 * Set transaction id's of transactions that have to be committed
+	 * to finish f[data]sync. We set them to currently running transaction
+	 * as we cannot be sure that the inode or some of its metadata isn't
+	 * part of the transaction - the inode could have been reclaimed and
+	 * now it is reread from disk.
+	 */
+	if (journal) {
+		transaction_t *transaction;
+		tid_t tid;
+		struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+		read_lock(&journal->j_state_lock);
+		if (journal->j_running_transaction)
+			transaction = journal->j_running_transaction;
+		else
+			transaction = journal->j_committing_transaction;
+		if (transaction)
+			tid = transaction->t_tid;
+		else
+			tid = journal->j_commit_sequence;
+		read_unlock(&journal->j_state_lock);
+		oi->i_sync_tid = tid;
+		oi->i_datasync_tid = tid;
+	}
+
 bail:
 	if (!IS_ERR(inode)) {
 		trace_ocfs2_iget_end(inode, 
@@ -804,11 +831,13 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
 		goto bail;
 	}
 
-	/* If we're coming from downconvert_thread we can't go into our own
-	 * voting [hello, deadlock city!], so unforuntately we just
-	 * have to skip deleting this guy. That's OK though because
-	 * the node who's doing the actual deleting should handle it
-	 * anyway. */
+	/*
+	 * If we're coming from downconvert_thread we can't go into our own
+	 * voting [hello, deadlock city!] so we cannot delete the inode. But
+	 * since we dropped last inode ref when downconverting dentry lock,
+	 * we cannot have the file open and thus the node doing unlink will
+	 * take care of deleting the inode.
+	 */
 	if (current == osb->dc_task)
 		goto bail;
 
@@ -822,12 +851,6 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
 		goto bail_unlock;
 	}
 
-	/* If we have allowd wipe of this inode for another node, it
-	 * will be marked here so we can safely skip it. Recovery will
-	 * cleanup any inodes we might inadvertently skip here. */
-	if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE)
-		goto bail_unlock;
-
 	ret = 1;
 bail_unlock:
 	spin_unlock(&oi->ip_lock);
@@ -941,7 +964,7 @@ static void ocfs2_cleanup_delete_inode(struct inode *inode,
 		(unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
 	if (sync_data)
 		filemap_write_and_wait(inode->i_mapping);
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 }
 
 static void ocfs2_delete_inode(struct inode *inode)
@@ -960,8 +983,6 @@ static void ocfs2_delete_inode(struct inode *inode)
 	if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno)
 		goto bail;
 
-	dquot_initialize(inode);
-
 	if (!ocfs2_inode_is_valid_to_delete(inode)) {
 		/* It's probably not necessary to truncate_inode_pages
 		 * here but we do it for safety anyway (it will most
@@ -970,6 +991,8 @@ static void ocfs2_delete_inode(struct inode *inode)
 		goto bail;
 	}
 
+	dquot_initialize(inode);
+
 	/* We want to block signals in delete_inode as the lock and
 	 * messaging paths may return us -ERESTARTSYS. Which would
 	 * cause us to exit early, resulting in inodes being orphaned
@@ -1057,6 +1080,7 @@ static void ocfs2_clear_inode(struct inode *inode)
 {
 	int status;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	clear_inode(inode);
 	trace_ocfs2_clear_inode((unsigned long long)oi->ip_blkno,
@@ -1073,9 +1097,9 @@ static void ocfs2_clear_inode(struct inode *inode)
 
 	/* Do these before all the other work so that we don't bounce
 	 * the downconvert thread while waiting to destroy the locks. */
-	ocfs2_mark_lockres_freeing(&oi->ip_rw_lockres);
-	ocfs2_mark_lockres_freeing(&oi->ip_inode_lockres);
-	ocfs2_mark_lockres_freeing(&oi->ip_open_lockres);
+	ocfs2_mark_lockres_freeing(osb, &oi->ip_rw_lockres);
+	ocfs2_mark_lockres_freeing(osb, &oi->ip_inode_lockres);
+	ocfs2_mark_lockres_freeing(osb, &oi->ip_open_lockres);
 
 	ocfs2_resv_discard(&OCFS2_SB(inode->i_sb)->osb_la_resmap,
 			   &oi->ip_la_data_resv);
@@ -1157,7 +1181,7 @@ void ocfs2_evict_inode(struct inode *inode)
 	    (OCFS2_I(inode)->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)) {
 		ocfs2_delete_inode(inode);
 	} else {
-		truncate_inode_pages(&inode->i_data, 0);
+		truncate_inode_pages_final(&inode->i_data);
 	}
 	ocfs2_clear_inode(inode);
 }
@@ -1260,6 +1284,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
 	fe->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
 
 	ocfs2_journal_dirty(handle, bh);
+	ocfs2_update_inode_fsync_trans(handle, inode, 1);
 leave:
 	return status;
 }
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 621fc73bf23d..a6c991c0fc98 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -44,7 +44,7 @@ struct ocfs2_inode_info
 	struct rw_semaphore		ip_xattr_sem;
 
 	/* Number of outstanding AIO's which are not page aligned */
-	atomic_t			ip_unaligned_aio;
+	struct mutex			ip_unaligned_aio;
 
 	/* These fields are protected by ip_lock */
 	spinlock_t			ip_lock;
@@ -73,6 +73,13 @@ struct ocfs2_inode_info
 	u32				ip_dir_lock_gen;
 
 	struct ocfs2_alloc_reservation	ip_la_data_resv;
+
+	/*
+	 * Transactions that contain inode's metadata needed to complete
+	 * fsync and fdatasync, respectively.
+	 */
+	tid_t i_sync_tid;
+	tid_t i_datasync_tid;
 };
 
 /*
@@ -84,8 +91,6 @@ struct ocfs2_inode_info
 #define OCFS2_INODE_BITMAP		0x00000004
 /* This inode has been wiped from disk */
 #define OCFS2_INODE_DELETED		0x00000008
-/* Another node is deleting, so our delete is a nop */
-#define OCFS2_INODE_SKIP_DELETE		0x00000010
 /* Has the inode been orphaned on another node?
  *
  * This hints to ocfs2_drop_inode that it should clear i_nlink before
@@ -100,11 +105,11 @@ struct ocfs2_inode_info
  * rely on ocfs2_delete_inode to sort things out under the proper
  * cluster locks.
  */
-#define OCFS2_INODE_MAYBE_ORPHANED	0x00000020
+#define OCFS2_INODE_MAYBE_ORPHANED	0x00000010
 /* Does someone have the file open O_DIRECT */
-#define OCFS2_INODE_OPEN_DIRECT		0x00000040
+#define OCFS2_INODE_OPEN_DIRECT		0x00000020
 /* Tell the inode wipe code it's not in orphan dir */
-#define OCFS2_INODE_SKIP_ORPHAN_DIR     0x00000080
+#define OCFS2_INODE_SKIP_ORPHAN_DIR     0x00000040
 
 static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
 {
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 44fc3e530c3d..03ea9314fecd 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -2132,12 +2132,6 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
 		iter = oi->ip_next_orphan;
 
 		spin_lock(&oi->ip_lock);
-		/* The remote delete code may have set these on the
-		 * assumption that the other node would wipe them
-		 * successfully.  If they are still in the node's
-		 * orphan dir, we need to reset that state. */
-		oi->ip_flags &= ~(OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE);
-
 		/* Set the proper information to get us going into
 		 * ocfs2_delete_inode. */
 		oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 9ff4e8cf9d97..7f8cde94abfe 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -626,4 +626,15 @@ static inline int ocfs2_begin_ordered_truncate(struct inode *inode,
 				new_size);
 }
 
+static inline void ocfs2_update_inode_fsync_trans(handle_t *handle,
+						  struct inode *inode,
+						  int datasync)
+{
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+	oi->i_sync_tid = handle->h_transaction->t_tid;
+	if (datasync)
+		oi->i_datasync_tid = handle->h_transaction->t_tid;
+}
+
 #endif /* OCFS2_JOURNAL_H */
diff --git a/fs/ocfs2/locks.c b/fs/ocfs2/locks.c
index e57c804069ea..6b6d092b0998 100644
--- a/fs/ocfs2/locks.c
+++ b/fs/ocfs2/locks.c
@@ -82,6 +82,8 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
 	}
 
 	ret = flock_lock_file_wait(file, fl);
+	if (ret)
+		ocfs2_file_unlock(file);
 
 out:
 	mutex_unlock(&fp->fp_mutex);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 3683643f3f0e..d1f871399231 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -495,6 +495,7 @@ static int __ocfs2_mknod_locked(struct inode *dir,
 	struct ocfs2_dinode *fe = NULL;
 	struct ocfs2_extent_list *fel;
 	u16 feat;
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
 	*new_fe_bh = NULL;
 
@@ -576,6 +577,9 @@ static int __ocfs2_mknod_locked(struct inode *dir,
 			mlog_errno(status);
 	}
 
+	oi->i_sync_tid = handle->h_transaction->t_tid;
+	oi->i_datasync_tid = handle->h_transaction->t_tid;
+
 	status = 0; /* error in ocfs2_create_new_inode_locks is not
 		     * critical */
 
@@ -991,6 +995,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 +1065,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 +1079,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 +1215,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. */
@@ -2138,17 +2235,17 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
 		goto leave;
 	}
 
-	/* remove it from the orphan directory */
-	status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
+	status = ocfs2_journal_access_di(handle,
+					 INODE_CACHE(orphan_dir_inode),
+					 orphan_dir_bh,
+					 OCFS2_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
 	}
 
-	status = ocfs2_journal_access_di(handle,
-					 INODE_CACHE(orphan_dir_inode),
-					 orphan_dir_bh,
-					 OCFS2_JOURNAL_ACCESS_WRITE);
+	/* remove it from the orphan directory */
+	status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 553f53cc73ae..a780e20d4fba 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -30,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/list.h>
+#include <linux/llist.h>
 #include <linux/rbtree.h>
 #include <linux/workqueue.h>
 #include <linux/kref.h>
@@ -274,19 +275,16 @@ enum ocfs2_mount_options
 	OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */
 };
 
-#define OCFS2_OSB_SOFT_RO			0x0001
-#define OCFS2_OSB_HARD_RO			0x0002
-#define OCFS2_OSB_ERROR_FS			0x0004
-#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED	0x0008
-
-#define OCFS2_DEFAULT_ATIME_QUANTUM		60
+#define OCFS2_OSB_SOFT_RO	0x0001
+#define OCFS2_OSB_HARD_RO	0x0002
+#define OCFS2_OSB_ERROR_FS	0x0004
+#define OCFS2_DEFAULT_ATIME_QUANTUM	60
 
 struct ocfs2_journal;
 struct ocfs2_slot_info;
 struct ocfs2_recovery_map;
 struct ocfs2_replay_map;
 struct ocfs2_quota_recovery;
-struct ocfs2_dentry_lock;
 struct ocfs2_super
 {
 	struct task_struct *commit_task;
@@ -414,10 +412,9 @@ struct ocfs2_super
 	struct list_head blocked_lock_list;
 	unsigned long blocked_lock_count;
 
-	/* List of dentry locks to release. Anyone can add locks to
-	 * the list, ocfs2_wq processes the list  */
-	struct ocfs2_dentry_lock *dentry_lock_list;
-	struct work_struct dentry_lock_work;
+	/* List of dquot structures to drop last reference to */
+	struct llist_head dquot_drop_list;
+	struct work_struct dquot_drop_work;
 
 	wait_queue_head_t		osb_mount_event;
 
@@ -579,18 +576,6 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
 	spin_unlock(&osb->osb_lock);
 }
 
-
-static inline unsigned long  ocfs2_test_osb_flag(struct ocfs2_super *osb,
-						 unsigned long flag)
-{
-	unsigned long ret;
-
-	spin_lock(&osb->osb_lock);
-	ret = osb->osb_flags & flag;
-	spin_unlock(&osb->osb_lock);
-	return ret;
-}
-
 static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
 				     int hard)
 {
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h
index d5ab56cbe5c5..f266d67df3c6 100644
--- a/fs/ocfs2/quota.h
+++ b/fs/ocfs2/quota.h
@@ -28,6 +28,7 @@ struct ocfs2_dquot {
 	unsigned int dq_use_count;	/* Number of nodes having reference to this entry in global quota file */
 	s64 dq_origspace;	/* Last globally synced space usage */
 	s64 dq_originodes;	/* Last globally synced inode usage */
+	struct llist_node list;	/* Member of list of dquots to drop */
 };
 
 /* Description of one chunk to recover in memory */
@@ -110,6 +111,7 @@ int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
 int ocfs2_create_local_dquot(struct dquot *dquot);
 int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot);
 int ocfs2_local_write_dquot(struct dquot *dquot);
+void ocfs2_drop_dquot_refs(struct work_struct *work);
 
 extern const struct dquot_operations ocfs2_quota_operations;
 extern struct quota_format_type ocfs2_quota_format;
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index aaa50611ec66..b990a62cff50 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -10,6 +10,7 @@
 #include <linux/jiffies.h>
 #include <linux/writeback.h>
 #include <linux/workqueue.h>
+#include <linux/llist.h>
 
 #include <cluster/masklog.h>
 
@@ -679,6 +680,27 @@ static int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
 	       OCFS2_INODE_UPDATE_CREDITS;
 }
 
+void ocfs2_drop_dquot_refs(struct work_struct *work)
+{
+	struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
+					       dquot_drop_work);
+	struct llist_node *list;
+	struct ocfs2_dquot *odquot, *next_odquot;
+
+	list = llist_del_all(&osb->dquot_drop_list);
+	llist_for_each_entry_safe(odquot, next_odquot, list, list) {
+		/* Drop the reference we acquired in ocfs2_dquot_release() */
+		dqput(&odquot->dq_dquot);
+	}
+}
+
+/*
+ * Called when the last reference to dquot is dropped. If we are called from
+ * downconvert thread, we cannot do all the handling here because grabbing
+ * quota lock could deadlock (the node holding the quota lock could need some
+ * other cluster lock to proceed but with blocked downconvert thread we cannot
+ * release any lock).
+ */
 static int ocfs2_release_dquot(struct dquot *dquot)
 {
 	handle_t *handle;
@@ -694,6 +716,19 @@ static int ocfs2_release_dquot(struct dquot *dquot)
 	/* Check whether we are not racing with some other dqget() */
 	if (atomic_read(&dquot->dq_count) > 1)
 		goto out;
+	/* Running from downconvert thread? Postpone quota processing to wq */
+	if (current == osb->dc_task) {
+		/*
+		 * Grab our own reference to dquot and queue it for delayed
+		 * dropping.  Quota code rechecks after calling
+		 * ->release_dquot() and won't free dquot structure.
+		 */
+		dqgrab(dquot);
+		/* First entry on list -> queue work */
+		if (llist_add(&OCFS2_DQUOT(dquot)->list, &osb->dquot_drop_list))
+			queue_work(ocfs2_wq, &osb->dquot_drop_work);
+		goto out;
+	}
 	status = ocfs2_lock_global_qf(oinfo, 1);
 	if (status < 0)
 		goto out;
@@ -717,6 +752,12 @@ static int ocfs2_release_dquot(struct dquot *dquot)
 	 */
 	if (status < 0)
 		mlog_errno(status);
+	/*
+	 * Clear dq_off so that we search for the structure in quota file next
+	 * time we acquire it. The structure might be deleted and reallocated
+	 * elsewhere by another node while our dquot structure is on freelist.
+	 */
+	dquot->dq_off = 0;
 	clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
 out_trans:
 	ocfs2_commit_trans(osb, handle);
@@ -756,16 +797,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
 	status = ocfs2_lock_global_qf(info, 1);
 	if (status < 0)
 		goto out;
-	if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
-		status = ocfs2_qinfo_lock(info, 0);
-		if (status < 0)
-			goto out_dq;
-		status = qtree_read_dquot(&info->dqi_gi, dquot);
-		ocfs2_qinfo_unlock(info, 0);
-		if (status < 0)
-			goto out_dq;
-	}
-	set_bit(DQ_READ_B, &dquot->dq_flags);
+	status = ocfs2_qinfo_lock(info, 0);
+	if (status < 0)
+		goto out_dq;
+	/*
+	 * We always want to read dquot structure from disk because we don't
+	 * know what happened with it while it was on freelist.
+	 */
+	status = qtree_read_dquot(&info->dqi_gi, dquot);
+	ocfs2_qinfo_unlock(info, 0);
+	if (status < 0)
+		goto out_dq;
 
 	OCFS2_DQUOT(dquot)->dq_use_count++;
 	OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 2e4344be3b96..2001862bf2b1 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot)
 	ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
 
 out:
-	/* Clear the read bit so that next time someone uses this
-	 * dquot he reads fresh info from disk and allocates local
-	 * dquot structure */
-	clear_bit(DQ_READ_B, &dquot->dq_flags);
 	return status;
 }
 
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 1324e6600e57..4bc6093e144a 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -601,11 +601,25 @@ static struct kobj_attribute ocfs2_attr_cluster_stack =
 	       ocfs2_cluster_stack_show,
 	       ocfs2_cluster_stack_store);
 
+
+
+static ssize_t ocfs2_dlm_recover_show(struct kobject *kobj,
+					struct kobj_attribute *attr,
+					char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "1\n");
+}
+
+static struct kobj_attribute ocfs2_attr_dlm_recover_support =
+	__ATTR(dlm_recover_callback_support, S_IFREG | S_IRUGO,
+	       ocfs2_dlm_recover_show, NULL);
+
 static struct attribute *ocfs2_attrs[] = {
 	&ocfs2_attr_max_locking_protocol.attr,
 	&ocfs2_attr_loaded_cluster_plugins.attr,
 	&ocfs2_attr_active_cluster_plugin.attr,
 	&ocfs2_attr_cluster_stack.attr,
+	&ocfs2_attr_dlm_recover_support.attr,
 	NULL,
 };
 
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 49d84f80f36c..888a1457af96 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -561,6 +561,9 @@ static struct inode *ocfs2_alloc_inode(struct super_block *sb)
 	if (!oi)
 		return NULL;
 
+	oi->i_sync_tid = 0;
+	oi->i_datasync_tid = 0;
+
 	jbd2_journal_init_jbd_inode(&oi->ip_jinode, &oi->vfs_inode);
 	return &oi->vfs_inode;
 }
@@ -1238,30 +1241,11 @@ static struct dentry *ocfs2_mount(struct file_system_type *fs_type,
 	return mount_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);
 }
 
-static void ocfs2_kill_sb(struct super_block *sb)
-{
-	struct ocfs2_super *osb = OCFS2_SB(sb);
-
-	/* Failed mount? */
-	if (!osb || atomic_read(&osb->vol_state) == VOLUME_DISABLED)
-		goto out;
-
-	/* Prevent further queueing of inode drop events */
-	spin_lock(&dentry_list_lock);
-	ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
-	spin_unlock(&dentry_list_lock);
-	/* Wait for work to finish and/or remove it */
-	cancel_work_sync(&osb->dentry_lock_work);
-out:
-	kill_block_super(sb);
-}
-
 static struct file_system_type ocfs2_fs_type = {
 	.owner          = THIS_MODULE,
 	.name           = "ocfs2",
 	.mount          = ocfs2_mount,
-	.kill_sb        = ocfs2_kill_sb,
-
+	.kill_sb        = kill_block_super,
 	.fs_flags       = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
 	.next           = NULL
 };
@@ -1612,14 +1596,9 @@ static int ocfs2_show_options(struct seq_file *s, struct dentry *root)
 	return 0;
 }
 
-wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
-
 static int __init ocfs2_init(void)
 {
-	int status, i;
-
-	for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++)
-		init_waitqueue_head(&ocfs2__ioend_wq[i]);
+	int status;
 
 	status = init_ocfs2_uptodate_cache();
 	if (status < 0)
@@ -1761,7 +1740,7 @@ static void ocfs2_inode_init_once(void *data)
 	ocfs2_extent_map_init(&oi->vfs_inode);
 	INIT_LIST_HEAD(&oi->ip_io_markers);
 	oi->ip_dir_start_lookup = 0;
-	atomic_set(&oi->ip_unaligned_aio, 0);
+	mutex_init(&oi->ip_unaligned_aio);
 	init_rwsem(&oi->ip_alloc_sem);
 	init_rwsem(&oi->ip_xattr_sem);
 	mutex_init(&oi->ip_io_mutex);
@@ -1932,17 +1911,16 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
 
 	debugfs_remove(osb->osb_ctxt);
 
-	/*
-	 * Flush inode dropping work queue so that deletes are
-	 * performed while the filesystem is still working
-	 */
-	ocfs2_drop_all_dl_inodes(osb);
-
 	/* Orphan scan should be stopped as early as possible */
 	ocfs2_orphan_scan_stop(osb);
 
 	ocfs2_disable_quotas(osb);
 
+	/* All dquots should be freed by now */
+	WARN_ON(!llist_empty(&osb->dquot_drop_list));
+	/* Wait for worker to be done with the work structure in osb */
+	cancel_work_sync(&osb->dquot_drop_work);
+
 	ocfs2_shutdown_local_alloc(osb);
 
 	/* This will disable recovery and flush any recovery work. */
@@ -2077,7 +2055,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
 	struct inode *inode = NULL;
 	struct ocfs2_journal *journal;
-	__le32 uuid_net_key;
 	struct ocfs2_super *osb;
 	u64 total_blocks;
 
@@ -2276,8 +2253,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
 	journal->j_state = OCFS2_JOURNAL_FREE;
 
-	INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
-	osb->dentry_lock_list = NULL;
+	INIT_WORK(&osb->dquot_drop_work, ocfs2_drop_dquot_refs);
+	init_llist_head(&osb->dquot_drop_list);
 
 	/* get some pseudo constants for clustersize bits */
 	osb->s_clustersize_bits =
@@ -2311,8 +2288,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
 		goto bail;
 	}
 
-	memcpy(&uuid_net_key, di->id2.i_super.s_uuid, sizeof(uuid_net_key));
-
 	strncpy(osb->vol_label, di->id2.i_super.s_label, 63);
 	osb->vol_label[63] = '\0';
 	osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index d8b0afde2179..ec58c7659183 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -183,7 +183,7 @@ int omfs_sync_inode(struct inode *inode)
  */
 static void omfs_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 
 	if (inode->i_nlink)
diff --git a/fs/open.c b/fs/open.c
index 4b3e1edf2fe4..4a923a547d10 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -231,7 +231,8 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 		return -EINVAL;
 
 	/* Return error if mode is not supported */
-	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+		     FALLOC_FL_COLLAPSE_RANGE))
 		return -EOPNOTSUPP;
 
 	/* Punch hole must have keep size set */
@@ -239,11 +240,20 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	    !(mode & FALLOC_FL_KEEP_SIZE))
 		return -EOPNOTSUPP;
 
+	/* Collapse range should only be used exclusively. */
+	if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
+	    (mode & ~FALLOC_FL_COLLAPSE_RANGE))
+		return -EINVAL;
+
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EBADF;
 
-	/* It's not possible punch hole on append only file */
-	if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode))
+	/*
+	 * It's not possible to punch hole or perform collapse range
+	 * on append only file
+	 */
+	if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)
+	    && IS_APPEND(inode))
 		return -EPERM;
 
 	if (IS_IMMUTABLE(inode))
@@ -271,6 +281,14 @@ 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/posix_acl.c b/fs/posix_acl.c
index 11c54fd51e16..9e363e41dacc 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -723,7 +723,7 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 		   void *buffer, size_t size)
 {
 	posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
-	posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
+	posix_acl_xattr_entry *ext_entry;
 	int real_size, n;
 
 	real_size = posix_acl_xattr_size(acl->a_count);
@@ -731,7 +731,8 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 		return real_size;
 	if (real_size > size)
 		return -ERANGE;
-	
+
+	ext_entry = ext_acl->a_entries;
 	ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
 
 	for (n=0; n < acl->a_count; n++, ext_entry++) {
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 656e401794de..64db2bceac59 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -138,8 +138,8 @@ static const char * const task_state_array[] = {
 	"D (disk sleep)",	/*   2 */
 	"T (stopped)",		/*   4 */
 	"t (tracing stop)",	/*   8 */
-	"Z (zombie)",		/*  16 */
-	"X (dead)",		/*  32 */
+	"X (dead)",		/*  16 */
+	"Z (zombie)",		/*  32 */
 };
 
 static inline const char *get_task_state(struct task_struct *tsk)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 51507065263b..b1dcb283b2cf 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1236,6 +1236,9 @@ static ssize_t proc_fault_inject_write(struct file * file,
 	make_it_fail = simple_strtol(strstrip(buffer), &end, 0);
 	if (*end)
 		return -EINVAL;
+	if (make_it_fail < 0 || make_it_fail > 1)
+		return -EINVAL;
+
 	task = get_proc_task(file_inode(file));
 	if (!task)
 		return -ESRCH;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 124fc43c7090..8f20e3404fd2 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -35,7 +35,7 @@ static void proc_evict_inode(struct inode *inode)
 	const struct proc_ns_operations *ns_ops;
 	void *ns;
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 
 	/* Stop tracking associated processes */
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 136e548d9567..7445af0b1aa3 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -73,7 +73,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 	available += pagecache;
 
 	/*
-	 * Part of the reclaimable swap consists of items that are in use,
+	 * Part of the reclaimable slab consists of items that are in use,
 	 * and cannot be freed. Cap this estimate at the low watermark.
 	 */
 	available += global_page_state(NR_SLAB_RECLAIMABLE) -
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 02174a610315..e647c55275d9 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -121,9 +121,8 @@ u64 stable_page_flags(struct page *page)
 	 * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon
 	 * to make sure a given page is a thp, not a non-huge compound page.
 	 */
-	else if (PageTransCompound(page) &&
-		 (PageLRU(compound_trans_head(page)) ||
-		  PageAnon(compound_trans_head(page))))
+	else if (PageTransCompound(page) && (PageLRU(compound_head(page)) ||
+					     PageAnon(compound_head(page))))
 		u |= 1 << KPF_THP;
 
 	/*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index fb52b548080d..3746d89c768b 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -423,7 +423,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;
@@ -437,15 +436,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);
@@ -462,7 +462,7 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 	}
 
 	if (!page)
-		return;
+		return 0;
 
 	if (PageAnon(page))
 		mss->anonymous += ptent_size;
@@ -488,35 +488,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;
 }
 
@@ -581,16 +568,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);
 
@@ -711,7 +698,6 @@ enum clear_refs_types {
 };
 
 struct clear_refs_private {
-	struct vm_area_struct *vma;
 	enum clear_refs_types type;
 };
 
@@ -743,41 +729,43 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
 #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);
-	}
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
+	/*
+	 * 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 (cp->type == CLEAR_REFS_ANON && vma->vm_file)
+		walk->skip = 1;
+	if (cp->type == CLEAR_REFS_MAPPED && !vma->vm_file)
+		walk->skip = 1;
 	return 0;
 }
 
@@ -819,33 +807,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);
@@ -986,19 +957,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))
@@ -1017,41 +1002,9 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 				break;
 		}
 		spin_unlock(ptl);
-		return err;
-	}
-
-	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;
+		/* don't call pagemap_pte() */
+		walk->skip = 1;
 	}
-
-	cond_resched();
-
 	return err;
 }
 
@@ -1069,24 +1022,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,
+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);
@@ -1094,9 +1045,6 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
 		if (err)
 			return err;
 	}
-
-	cond_resched();
-
 	return err;
 }
 #endif /* HUGETLB_PAGE */
@@ -1163,10 +1111,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;
@@ -1242,7 +1191,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;
@@ -1308,44 +1256,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;
@@ -1363,8 +1309,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;
 }
@@ -1393,12 +1339,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);
@@ -1429,6 +1375,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/proc/vmcore.c b/fs/proc/vmcore.c
index 88d4585b30f1..ab852715916d 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -1118,4 +1118,3 @@ void vmcore_cleanup(void)
 	}
 	free_elfcorebuf();
 }
-EXPORT_SYMBOL_GPL(vmcore_cleanup);
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index cfc8dcc16043..9cd5f63715c0 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -528,7 +528,7 @@ restart:
 		if (atomic_read(&dquot->dq_count)) {
 			DEFINE_WAIT(wait);
 
-			atomic_inc(&dquot->dq_count);
+			dqgrab(dquot);
 			prepare_to_wait(&dquot->dq_wait_unused, &wait,
 					TASK_UNINTERRUPTIBLE);
 			spin_unlock(&dq_list_lock);
@@ -632,7 +632,7 @@ int dquot_writeback_dquots(struct super_block *sb, int type)
 			/* Now we have active dquot from which someone is
  			 * holding reference so we can safely just increase
 			 * use count */
-			atomic_inc(&dquot->dq_count);
+			dqgrab(dquot);
 			spin_unlock(&dq_list_lock);
 			dqstats_inc(DQST_LOOKUPS);
 			err = sb->dq_op->write_dquot(dquot);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ad62bdbb451e..bc8b8009897d 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -35,7 +35,7 @@ void reiserfs_evict_inode(struct inode *inode)
 	if (!inode->i_nlink && !is_bad_inode(inode))
 		dquot_initialize(inode);
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	if (inode->i_nlink)
 		goto no_delete;
 
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h
index 8d06adf89948..83d4eac8059a 100644
--- a/fs/reiserfs/reiserfs.h
+++ b/fs/reiserfs/reiserfs.h
@@ -2831,6 +2831,7 @@ void reiserfs_init_alloc_options(struct super_block *s);
  */
 __le32 reiserfs_choose_packing(struct inode *dir);
 
+void show_alloc_options(struct seq_file *seq, struct super_block *s);
 int reiserfs_init_bitmap_cache(struct super_block *sb);
 void reiserfs_free_bitmap_cache(struct super_block *sb);
 void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 2c803353f8ac..16d533597065 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -62,7 +62,6 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
 
 static int reiserfs_remount(struct super_block *s, int *flags, char *data);
 static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
-void show_alloc_options(struct seq_file *seq, struct super_block *s);
 
 static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
diff --git a/fs/sysfs/Kconfig b/fs/sysfs/Kconfig
index 8c41feacbac5..b2756014508c 100644
--- a/fs/sysfs/Kconfig
+++ b/fs/sysfs/Kconfig
@@ -1,6 +1,7 @@
 config SYSFS
 	bool "sysfs file system support" if EXPERT
 	default y
+	select KERNFS
 	help
 	The sysfs filesystem is a virtual filesystem that the kernel uses to
 	export internal kernel objects, their attributes, and their
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index ee0d761c3179..0b45ff42f374 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -19,39 +19,18 @@
 
 DEFINE_SPINLOCK(sysfs_symlink_target_lock);
 
-/**
- *	sysfs_pathname - return full path to sysfs dirent
- *	@kn: kernfs_node whose path we want
- *	@path: caller allocated buffer of size PATH_MAX
- *
- *	Gives the name "/" to the sysfs_root entry; any path returned
- *	is relative to wherever sysfs is mounted.
- */
-static char *sysfs_pathname(struct kernfs_node *kn, char *path)
-{
-	if (kn->parent) {
-		sysfs_pathname(kn->parent, path);
-		strlcat(path, "/", PATH_MAX);
-	}
-	strlcat(path, kn->name, PATH_MAX);
-	return path;
-}
-
 void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
 {
-	char *path;
+	char *buf, *path = NULL;
 
-	path = kzalloc(PATH_MAX, GFP_KERNEL);
-	if (path) {
-		sysfs_pathname(parent, path);
-		strlcat(path, "/", PATH_MAX);
-		strlcat(path, name, PATH_MAX);
-	}
+	buf = kzalloc(PATH_MAX, GFP_KERNEL);
+	if (buf)
+		path = kernfs_path(parent, buf, PATH_MAX);
 
-	WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n",
-	     path ? path : name);
+	WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s/%s'\n",
+	     path, name);
 
-	kfree(path);
+	kfree(buf);
 }
 
 /**
@@ -122,9 +101,13 @@ void sysfs_remove_dir(struct kobject *kobj)
 int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
 			const void *new_ns)
 {
-	struct kernfs_node *parent = kobj->sd->parent;
+	struct kernfs_node *parent;
+	int ret;
 
-	return kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
+	parent = kernfs_get_parent(kobj->sd);
+	ret = kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
+	kernfs_put(parent);
+	return ret;
 }
 
 int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
@@ -133,7 +116,6 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
 	struct kernfs_node *kn = kobj->sd;
 	struct kernfs_node *new_parent;
 
-	BUG_ON(!kn->parent);
 	new_parent = new_parent_kobj && new_parent_kobj->sd ?
 		new_parent_kobj->sd : sysfs_root_kn;
 
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 810cf6e613e5..28cc1acd5439 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -372,6 +372,29 @@ void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
 
+/**
+ * sysfs_remove_file_self - remove an object attribute from its own method
+ * @kobj: object we're acting for
+ * @attr: attribute descriptor
+ *
+ * See kernfs_remove_self() for details.
+ */
+bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
+{
+	struct kernfs_node *parent = kobj->sd;
+	struct kernfs_node *kn;
+	bool ret;
+
+	kn = kernfs_find_and_get(parent, attr->name);
+	if (WARN_ON_ONCE(!kn))
+		return false;
+
+	ret = kernfs_remove_self(kn);
+
+	kernfs_put(kn);
+	return ret;
+}
+
 void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
 {
 	int i;
@@ -430,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/sysfs/group.c b/fs/sysfs/group.c
index 6b579387c67a..aa0406895b53 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -70,8 +70,11 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
 	if (grp->bin_attrs) {
 		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
 			if (update)
-				sysfs_remove_bin_file(kobj, *bin_attr);
-			error = sysfs_create_bin_file(kobj, *bin_attr);
+				kernfs_remove_by_name(parent,
+						(*bin_attr)->attr.name);
+			error = sysfs_add_file_mode_ns(parent,
+					&(*bin_attr)->attr, true,
+					(*bin_attr)->attr.mode, NULL);
 			if (error)
 				break;
 		}
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 3eaf5c6622eb..a66ad6196f59 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -63,7 +63,7 @@ int __init sysfs_init(void)
 {
 	int err;
 
-	sysfs_root = kernfs_create_root(NULL, NULL);
+	sysfs_root = kernfs_create_root(NULL, 0, NULL);
 	if (IS_ERR(sysfs_root))
 		return PTR_ERR(sysfs_root);
 
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index c327d4ee1235..5625ca920f5e 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -295,7 +295,7 @@ int sysv_sync_inode(struct inode *inode)
 
 static void sysv_evict_inode(struct inode *inode)
 {
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	if (!inode->i_nlink) {
 		inode->i_size = 0;
 		sysv_truncate(inode);
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 123c79b7261e..4f34dbae823d 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1538,6 +1538,7 @@ out_unlock:
 
 static const struct vm_operations_struct ubifs_file_vm_ops = {
 	.fault        = filemap_fault,
+	.map_pages = filemap_map_pages,
 	.page_mkwrite = ubifs_vm_page_mkwrite,
 	.remap_pages = generic_file_remap_pages,
 };
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 5ded8490c0c6..48f943f7f5d5 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -351,7 +351,7 @@ static void ubifs_evict_inode(struct inode *inode)
 	dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode);
 	ubifs_assert(!atomic_read(&inode->i_count));
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 
 	if (inode->i_nlink)
 		goto done;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 982ce05c87ed..5d643706212f 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -146,8 +146,8 @@ void udf_evict_inode(struct inode *inode)
 		want_delete = 1;
 		udf_setsize(inode, 0);
 		udf_update_inode(inode, IS_SYNC(inode));
-	} else
-		truncate_inode_pages(&inode->i_data, 0);
+	}
+	truncate_inode_pages_final(&inode->i_data);
 	invalidate_inode_buffers(inode);
 	clear_inode(inode);
 	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 3306b9f69bed..6a1464999f02 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -175,7 +175,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
 					     sizeof(struct udf_inode_info),
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index a7ea492ae660..dd5d176c9c2f 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -38,7 +38,6 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, bit, end_bit, bbase, blkmap, i;
@@ -46,7 +45,6 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 	
 	UFSD("ENTER, fragment %llu, count %u\n",
 	     (unsigned long long)fragment, count);
@@ -54,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);
@@ -118,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;
 }
@@ -135,7 +133,6 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	unsigned overflow, cgno, bit, end_bit, i;
@@ -143,7 +140,6 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 
 	UFSD("ENTER, fragment %llu, count %u\n",
 	     (unsigned long long)fragment, count);
@@ -155,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;
@@ -215,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;
@@ -361,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) {
@@ -382,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;
 		}
 	}
@@ -403,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;
 	}
@@ -428,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;
 	}
@@ -443,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;
 	}
@@ -481,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);
@@ -489,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;
 }		
@@ -499,7 +495,6 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, fragno, fragoff, count, fragsize, i;
@@ -509,7 +504,6 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first (uspi);
 	count = newcount - oldcount;
 	
 	cgno = ufs_dtog(uspi, fragment);
@@ -577,7 +571,6 @@ static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	unsigned oldcg, i, j, k, allocsize;
@@ -588,7 +581,6 @@ static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 	oldcg = cgno;
 	
 	/*
@@ -690,7 +682,6 @@ static u64 ufs_alloccg_block(struct inode *inode,
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cylinder_group * ucg;
 	u64 result, blkno;
 
@@ -698,7 +689,6 @@ static u64 ufs_alloccg_block(struct inode *inode,
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal == 0) {
@@ -794,7 +784,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
 		0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
 	};
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
-	struct ufs_super_block_first *usb1;
 	struct ufs_cylinder_group *ucg;
 	unsigned start, length, loc;
 	unsigned pos, want, blockmap, mask, end;
@@ -803,7 +792,6 @@ static u64 ufs_bitmap_search(struct super_block *sb,
 	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
 	     (unsigned long long)goal, count);
 
-	usb1 = ubh_get_usb_first (uspi);
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal)
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index d0426d74817b..a9cc75ffa925 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -57,7 +57,6 @@ void ufs_free_inode (struct inode * inode)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	int is_directory;
@@ -67,15 +66,14 @@ void ufs_free_inode (struct inode * inode)
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 	
 	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;
 	}
 	
@@ -83,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));
@@ -117,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");
 }
 
@@ -175,7 +173,6 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
 	struct super_block * sb;
 	struct ufs_sb_info * sbi;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	struct inode * inode;
@@ -195,9 +192,8 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
 	ufsi = UFS_I(inode);
 	sbi = UFS_SB(sb);
 	uspi = sbi->s_uspi;
-	usb1 = ubh_get_usb_first(uspi);
 
-	mutex_lock(&sbi->s_lock);
+	lock_ufs(sb);
 
 	/*
 	 * Try to place the inode in its parent directory
@@ -332,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/inode.c b/fs/ufs/inode.c
index c8ca96086784..61e8a9b021dd 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -885,7 +885,7 @@ void ufs_evict_inode(struct inode * inode)
 	if (!inode->i_nlink && !is_bad_inode(inode))
 		want_delete = 1;
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	if (want_delete) {
 		loff_t old_i_size;
 		/*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 329f2f53b7ed..b446696aef86 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -524,11 +524,9 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned size, blks, i;
-	struct ufs_super_block_third *usb3;
 
 	UFSD("ENTER\n");
 
-	usb3 = ubh_get_usb_third(uspi);
 	/*
 	 * Read cs structures from (usually) first data block
 	 * on the device. 
@@ -699,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");
 
@@ -717,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;
@@ -762,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");
@@ -805,7 +802,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 	}
 #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);
 	/*
@@ -1262,6 +1258,7 @@ failed:
 	if (ubh)
 		ubh_brelse_uspi (uspi);
 	kfree (uspi);
+	mutex_destroy(&sbi->mutex);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 	UFSD("EXIT (FAILED)\n");
@@ -1281,7 +1278,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	unsigned flags;
 
 	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);
@@ -1295,7 +1291,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;
 	}
@@ -1303,14 +1298,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;
 	}
@@ -1335,7 +1328,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
@@ -1345,13 +1337,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;
 		}
@@ -1359,7 +1349,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;
 }
@@ -1389,15 +1378,11 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	struct super_block *sb = dentry->d_sb;
 	struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi;
 	unsigned  flags = UFS_SB(sb)->s_flags;
-	struct ufs_super_block_first *usb1;
-	struct ufs_super_block_second *usb2;
 	struct ufs_super_block_third *usb3;
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
 	lock_ufs(sb);
 
-	usb1 = ubh_get_usb_first(uspi);
-	usb2 = ubh_get_usb_second(uspi);
 	usb3 = ubh_get_usb_third(uspi);
 	
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
@@ -1453,7 +1438,7 @@ static void init_once(void *foo)
 	inode_init_once(&ei->vfs_inode);
 }
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
 					     sizeof(struct ufs_inode_info),
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_acl.c b/fs/xfs/xfs_acl.c
index 0ecec1896f25..6888ad886ff6 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -281,7 +281,7 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	if (!acl)
 		goto set_acl;
 
-	error = -EINVAL;
+	error = -E2BIG;
 	if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
 		return error;
 
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 3fc109819c34..0fdd4109c624 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -89,6 +89,8 @@ typedef struct xfs_agf {
 	/* structure must be padded to 64 bit alignment */
 } xfs_agf_t;
 
+#define XFS_AGF_CRC_OFF		offsetof(struct xfs_agf, agf_crc)
+
 #define	XFS_AGF_MAGICNUM	0x00000001
 #define	XFS_AGF_VERSIONNUM	0x00000002
 #define	XFS_AGF_SEQNO		0x00000004
@@ -167,6 +169,8 @@ typedef struct xfs_agi {
 	/* structure must be padded to 64 bit alignment */
 } xfs_agi_t;
 
+#define XFS_AGI_CRC_OFF		offsetof(struct xfs_agi, agi_crc)
+
 #define	XFS_AGI_MAGICNUM	0x00000001
 #define	XFS_AGI_VERSIONNUM	0x00000002
 #define	XFS_AGI_SEQNO		0x00000004
@@ -222,6 +226,8 @@ typedef struct xfs_agfl {
 	__be32		agfl_bno[];	/* actually XFS_AGFL_SIZE(mp) */
 } xfs_agfl_t;
 
+#define XFS_AGFL_CRC_OFF	offsetof(struct xfs_agfl, agfl_crc)
+
 /*
  * tags for inode radix tree
  */
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 9eab2dfdcbb5..c1cf6a336a72 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -474,7 +474,6 @@ xfs_agfl_read_verify(
 	struct xfs_buf	*bp)
 {
 	struct xfs_mount *mp = bp->b_target->bt_mount;
-	int		agfl_ok = 1;
 
 	/*
 	 * There is no verification of non-crc AGFLs because mkfs does not
@@ -485,15 +484,13 @@ xfs_agfl_read_verify(
 	if (!xfs_sb_version_hascrc(&mp->m_sb))
 		return;
 
-	agfl_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-				   offsetof(struct xfs_agfl, agfl_crc));
-
-	agfl_ok = agfl_ok && xfs_agfl_verify(bp);
-
-	if (!agfl_ok) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_agfl_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -508,16 +505,15 @@ xfs_agfl_write_verify(
 		return;
 
 	if (!xfs_agfl_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
 	if (bip)
 		XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 offsetof(struct xfs_agfl, agfl_crc));
+	xfs_buf_update_cksum(bp, XFS_AGFL_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_agfl_buf_ops = {
@@ -2238,19 +2234,17 @@ xfs_agf_read_verify(
 	struct xfs_buf	*bp)
 {
 	struct xfs_mount *mp = bp->b_target->bt_mount;
-	int		agf_ok = 1;
-
-	if (xfs_sb_version_hascrc(&mp->m_sb))
-		agf_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  offsetof(struct xfs_agf, agf_crc));
 
-	agf_ok = agf_ok && xfs_agf_verify(mp, bp);
-
-	if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
-			XFS_RANDOM_ALLOC_READ_AGF))) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	    !xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (XFS_TEST_ERROR(!xfs_agf_verify(mp, bp), mp,
+				XFS_ERRTAG_ALLOC_READ_AGF,
+				XFS_RANDOM_ALLOC_READ_AGF))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -2261,8 +2255,8 @@ xfs_agf_write_verify(
 	struct xfs_buf_log_item	*bip = bp->b_fspriv;
 
 	if (!xfs_agf_verify(mp, bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -2272,8 +2266,7 @@ xfs_agf_write_verify(
 	if (bip)
 		XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 offsetof(struct xfs_agf, agf_crc));
+	xfs_buf_update_cksum(bp, XFS_AGF_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_agf_buf_ops = {
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 13085429e523..cc1eadcbb049 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -355,12 +355,14 @@ static void
 xfs_allocbt_read_verify(
 	struct xfs_buf	*bp)
 {
-	if (!(xfs_btree_sblock_verify_crc(bp) &&
-	      xfs_allocbt_verify(bp))) {
-		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
+	if (!xfs_btree_sblock_verify_crc(bp))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_allocbt_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+
+	if (bp->b_error) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		xfs_verifier_error(bp);
 	}
 }
 
@@ -370,9 +372,9 @@ xfs_allocbt_write_verify(
 {
 	if (!xfs_allocbt_verify(bp)) {
 		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
+		return;
 	}
 	xfs_btree_sblock_calc_crc(bp);
 
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index db2cfb067d0b..ef62c6b6130a 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1441,7 +1441,8 @@ xfs_vm_direct_IO(
 		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov,
 					    offset, nr_segs,
 					    xfs_get_blocks_direct,
-					    xfs_end_io_direct_write, NULL, 0);
+					    xfs_end_io_direct_write, NULL,
+					    DIO_ASYNC_EXTEND);
 		if (ret != -EIOCBQUEUED && iocb->private)
 			goto out_destroy_ioend;
 	} else {
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 7b126f46a2f9..fe9587fab17a 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -213,8 +213,8 @@ xfs_attr3_leaf_write_verify(
 	struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr;
 
 	if (!xfs_attr3_leaf_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -224,7 +224,7 @@ xfs_attr3_leaf_write_verify(
 	if (bip)
 		hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_ATTR3_LEAF_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF);
 }
 
 /*
@@ -239,13 +239,14 @@ xfs_attr3_leaf_read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
-	     !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  XFS_ATTR3_LEAF_CRC_OFF)) ||
-	    !xfs_attr3_leaf_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	     !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_attr3_leaf_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index 5549d69ddb45..6e37823e2932 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -125,7 +125,6 @@ xfs_attr3_rmt_read_verify(
 	struct xfs_mount *mp = bp->b_target->bt_mount;
 	char		*ptr;
 	int		len;
-	bool		corrupt = false;
 	xfs_daddr_t	bno;
 
 	/* no verification of non-crc buffers */
@@ -140,11 +139,11 @@ xfs_attr3_rmt_read_verify(
 	while (len > 0) {
 		if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
 				      XFS_ATTR3_RMT_CRC_OFF)) {
-			corrupt = true;
+			xfs_buf_ioerror(bp, EFSBADCRC);
 			break;
 		}
 		if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
-			corrupt = true;
+			xfs_buf_ioerror(bp, EFSCORRUPTED);
 			break;
 		}
 		len -= XFS_LBSIZE(mp);
@@ -152,10 +151,9 @@ xfs_attr3_rmt_read_verify(
 		bno += mp->m_bsize;
 	}
 
-	if (corrupt) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
-		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	} else
+	if (bp->b_error)
+		xfs_verifier_error(bp);
+	else
 		ASSERT(len == 0);
 }
 
@@ -180,9 +178,8 @@ xfs_attr3_rmt_write_verify(
 
 	while (len > 0) {
 		if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
-			XFS_CORRUPTION_ERROR(__func__,
-					    XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 			xfs_buf_ioerror(bp, EFSCORRUPTED);
+			xfs_verifier_error(bp);
 			return;
 		}
 		if (bip) {
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 152543c4ca70..5b6092ef51ef 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5378,3 +5378,196 @@ error0:
 	}
 	return error;
 }
+
+/*
+ * Shift extent records to the left to cover a hole.
+ *
+ * The maximum number of extents to be shifted in a single operation
+ * is @num_exts, and @current_ext keeps track of the current extent
+ * index we have shifted. @offset_shift_fsb is the length by which each
+ * extent is shifted. If there is no hole to shift the extents
+ * into, this will be considered invalid operation and we abort immediately.
+ */
+int
+xfs_bmap_shift_extents(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	int			*done,
+	xfs_fileoff_t		start_fsb,
+	xfs_fileoff_t		offset_shift_fsb,
+	xfs_extnum_t		*current_ext,
+	xfs_fsblock_t		*firstblock,
+	struct xfs_bmap_free	*flist,
+	int			num_exts)
+{
+	struct xfs_btree_cur		*cur;
+	struct xfs_bmbt_rec_host	*gotp;
+	struct xfs_bmbt_irec            got;
+	struct xfs_bmbt_irec		left;
+	struct xfs_mount		*mp = ip->i_mount;
+	struct xfs_ifork		*ifp;
+	xfs_extnum_t			nexts = 0;
+	xfs_fileoff_t			startoff;
+	int				error = 0;
+	int				i;
+	int				whichfork = XFS_DATA_FORK;
+	int				logflags;
+	xfs_filblks_t			blockcount = 0;
+
+	if (unlikely(XFS_TEST_ERROR(
+	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
+	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+		XFS_ERROR_REPORT("xfs_bmap_shift_extents",
+				 XFS_ERRLEVEL_LOW, mp);
+		return XFS_ERROR(EFSCORRUPTED);
+	}
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	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);
+		if (error)
+			return error;
+	}
+
+	/*
+	 * If *current_ext is 0, we would need to lookup the extent
+	 * from where we would start shifting and store it in gotp.
+	 */
+	if (!*current_ext) {
+		gotp = xfs_iext_bno_to_ext(ifp, start_fsb, current_ext);
+		/*
+		 * gotp can be null in 2 cases: 1) if there are no extents
+		 * or 2) start_fsb lies in a hole beyond which there are
+		 * no extents. Either way, we are done.
+		 */
+		if (!gotp) {
+			*done = 1;
+			return 0;
+		}
+	}
+
+	/* 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;
+		cur->bc_private.b.flist = flist;
+		cur->bc_private.b.flags = 0;
+	} else {
+		cur = NULL;
+		logflags |= XFS_ILOG_DEXT;
+	}
+
+	while (nexts++ < num_exts &&
+	       *current_ext <  XFS_IFORK_NEXTENTS(ip, whichfork)) {
+
+		gotp = xfs_iext_get_ext(ifp, *current_ext);
+		xfs_bmbt_get_all(gotp, &got);
+		startoff = got.br_startoff - offset_shift_fsb;
+
+		/*
+		 * Before shifting extent into hole, make sure that the hole
+		 * is large enough to accomodate the shift.
+		 */
+		if (*current_ext) {
+			xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
+						*current_ext - 1), &left);
+
+			if (startoff < left.br_startoff + left.br_blockcount)
+				error = XFS_ERROR(EINVAL);
+		} else if (offset_shift_fsb > got.br_startoff) {
+			/*
+			 * When first extent is shifted, offset_shift_fsb
+			 * should be less than the stating offset of
+			 * the first extent.
+			 */
+			error = XFS_ERROR(EINVAL);
+		}
+
+		if (error)
+			goto del_cursor;
+
+		if (cur) {
+			error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+						   got.br_startblock,
+						   got.br_blockcount,
+						   &i);
+			if (error)
+				goto del_cursor;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+		}
+
+		/* Check if we can merge 2 adjacent extents */
+		if (*current_ext &&
+		    left.br_startoff + left.br_blockcount == startoff &&
+		    left.br_startblock + left.br_blockcount ==
+				got.br_startblock &&
+		    left.br_state == got.br_state &&
+		    left.br_blockcount + got.br_blockcount <= MAXEXTLEN) {
+			blockcount = left.br_blockcount +
+				got.br_blockcount;
+			xfs_iext_remove(ip, *current_ext, 1, 0);
+			if (cur) {
+				error = xfs_btree_delete(cur, &i);
+				if (error)
+					goto del_cursor;
+				XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+			}
+			XFS_IFORK_NEXT_SET(ip, whichfork,
+				XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+			gotp = xfs_iext_get_ext(ifp, --*current_ext);
+			xfs_bmbt_get_all(gotp, &got);
+
+			/* Make cursor point to the extent we will update */
+			if (cur) {
+				error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+							   got.br_startblock,
+							   got.br_blockcount,
+							   &i);
+				if (error)
+					goto del_cursor;
+				XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+			}
+
+			xfs_bmbt_set_blockcount(gotp, blockcount);
+			got.br_blockcount = blockcount;
+		} else {
+			/* We have to update the startoff */
+			xfs_bmbt_set_startoff(gotp, startoff);
+			got.br_startoff = startoff;
+		}
+
+		if (cur) {
+			error = xfs_bmbt_update(cur, got.br_startoff,
+						got.br_startblock,
+						got.br_blockcount,
+						got.br_state);
+			if (error)
+				goto del_cursor;
+		}
+
+		(*current_ext)++;
+	}
+
+	/* Check if we are done */
+	if (*current_ext ==  XFS_IFORK_NEXTENTS(ip, whichfork))
+		*done = 1;
+
+del_cursor:
+	if (cur)
+		xfs_btree_del_cursor(cur,
+			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+
+	xfs_trans_log_inode(tp, ip, logflags);
+
+	return error;
+}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 33b41f351225..f84bd7af43be 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -127,6 +127,16 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
 	{ BMAP_RIGHT_FILLING,	"RF" }, \
 	{ BMAP_ATTRFORK,	"ATTR" }
 
+
+/*
+ * This macro is used to determine how many extents will be shifted
+ * in one write transaction. We could require two splits,
+ * an extent move on the first and an extent merge on the second,
+ * So it is proper that one extent is shifted inside write transaction
+ * at a time.
+ */
+#define XFS_BMAP_MAX_SHIFT_EXTENTS	1
+
 #ifdef DEBUG
 void	xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
 		int whichfork, unsigned long caller_ip);
@@ -169,5 +179,10 @@ int	xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
 int	xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
 		xfs_extnum_t num);
 uint	xfs_default_attroffset(struct xfs_inode *ip);
+int	xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
+		int *done, xfs_fileoff_t start_fsb,
+		xfs_fileoff_t offset_shift_fsb, xfs_extnum_t *current_ext,
+		xfs_fsblock_t *firstblock, struct xfs_bmap_free	*flist,
+		int num_exts);
 
 #endif	/* __XFS_BMAP_H__ */
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 706bc3f777cb..818d546664e7 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -780,12 +780,14 @@ static void
 xfs_bmbt_read_verify(
 	struct xfs_buf	*bp)
 {
-	if (!(xfs_btree_lblock_verify_crc(bp) &&
-	      xfs_bmbt_verify(bp))) {
-		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
+	if (!xfs_btree_lblock_verify_crc(bp))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_bmbt_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+
+	if (bp->b_error) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		xfs_verifier_error(bp);
 	}
 }
 
@@ -794,11 +796,9 @@ xfs_bmbt_write_verify(
 	struct xfs_buf	*bp)
 {
 	if (!xfs_bmbt_verify(bp)) {
-		xfs_warn(bp->b_target->bt_mount, "bmbt daddr 0x%llx failed", bp->b_bn);
 		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 	xfs_btree_lblock_calc_crc(bp);
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index f264616080ca..01f6a646caa1 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1349,7 +1349,6 @@ xfs_free_file_space(
 		 * the freeing of the space succeeds at ENOSPC.
 		 */
 		tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-		tp->t_flags |= XFS_TRANS_RESERVE;
 		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, resblks, 0);
 
 		/*
@@ -1468,6 +1467,102 @@ out:
 }
 
 /*
+ * xfs_collapse_file_space()
+ *	This routine frees disk space and shift extent for the given file.
+ *	The first thing we do is to free data blocks in the specified range
+ *	by calling xfs_free_file_space(). It would also sync dirty data
+ *	and invalidate page cache over the region on which collapse range
+ *	is working. And Shift extent records to the left to cover a hole.
+ * RETURNS:
+ *	0 on success
+ *	errno on error
+ *
+ */
+int
+xfs_collapse_file_space(
+	struct xfs_inode	*ip,
+	xfs_off_t		offset,
+	xfs_off_t		len)
+{
+	int			done = 0;
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_trans	*tp;
+	int			error;
+	xfs_extnum_t		current_ext = 0;
+	struct xfs_bmap_free	free_list;
+	xfs_fsblock_t		first_block;
+	int			committed;
+	xfs_fileoff_t		start_fsb;
+	xfs_fileoff_t		shift_fsb;
+
+	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+
+	trace_xfs_collapse_file_space(ip);
+
+	start_fsb = XFS_B_TO_FSB(mp, offset + len);
+	shift_fsb = XFS_B_TO_FSB(mp, len);
+
+	error = xfs_free_file_space(ip, offset, len);
+	if (error)
+		return error;
+
+	while (!error && !done) {
+		tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
+		tp->t_flags |= XFS_TRANS_RESERVE;
+		/*
+		 * We would need to reserve permanent block for transaction.
+		 * This will come into picture when after shifting extent into
+		 * hole we found that adjacent extents can be merged which
+		 * may lead to freeing of a block during record update.
+		 */
+		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
+				XFS_DIOSTRAT_SPACE_RES(mp, 0), 0);
+		if (error) {
+			ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
+			xfs_trans_cancel(tp, 0);
+			break;
+		}
+
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot,
+				ip->i_gdquot, ip->i_pdquot,
+				XFS_DIOSTRAT_SPACE_RES(mp, 0), 0,
+				XFS_QMOPT_RES_REGBLKS);
+		if (error)
+			goto out;
+
+		xfs_trans_ijoin(tp, ip, 0);
+
+		xfs_bmap_init(&free_list, &first_block);
+
+		/*
+		 * We are using the write transaction in which max 2 bmbt
+		 * updates are allowed
+		 */
+		error = xfs_bmap_shift_extents(tp, ip, &done, start_fsb,
+					       shift_fsb, &current_ext,
+					       &first_block, &free_list,
+					       XFS_BMAP_MAX_SHIFT_EXTENTS);
+		if (error)
+			goto out;
+
+		error = xfs_bmap_finish(&tp, &free_list, &committed);
+		if (error)
+			goto out;
+
+		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	}
+
+	return error;
+
+out:
+	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	return error;
+}
+
+/*
  * We need to check that the format of the data fork in the temporary inode is
  * valid for the target inode before doing the swap. This is not a problem with
  * attr1 because of the fixed fork offset, but attr2 has a dynamically sized
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 900747b25772..935ed2b24edf 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -99,6 +99,8 @@ int	xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
 			    xfs_off_t len);
 int	xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset,
 			    xfs_off_t len);
+int	xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,
+				xfs_off_t len);
 
 /* EOF block manipulation functions */
 bool	xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 9adaae4f3e2f..e80d59fdf89a 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -234,8 +234,7 @@ xfs_btree_lblock_calc_crc(
 		return;
 	if (bip)
 		block->bb_u.l.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 XFS_BTREE_LBLOCK_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
 }
 
 bool
@@ -243,8 +242,8 @@ xfs_btree_lblock_verify_crc(
 	struct xfs_buf		*bp)
 {
 	if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
-		return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					XFS_BTREE_LBLOCK_CRC_OFF);
+		return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
+
 	return true;
 }
 
@@ -267,8 +266,7 @@ xfs_btree_sblock_calc_crc(
 		return;
 	if (bip)
 		block->bb_u.s.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 XFS_BTREE_SBLOCK_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
 }
 
 bool
@@ -276,8 +274,8 @@ xfs_btree_sblock_verify_crc(
 	struct xfs_buf		*bp)
 {
 	if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
-		return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					XFS_BTREE_SBLOCK_CRC_OFF);
+		return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
+
 	return true;
 }
 
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 995339534db6..b8a3abf6cf47 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -369,6 +369,20 @@ static inline void xfs_buf_relse(xfs_buf_t *bp)
 	xfs_buf_rele(bp);
 }
 
+static inline int
+xfs_buf_verify_cksum(struct xfs_buf *bp, unsigned long cksum_offset)
+{
+	return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
+				cksum_offset);
+}
+
+static inline void
+xfs_buf_update_cksum(struct xfs_buf *bp, unsigned long cksum_offset)
+{
+	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
+			 cksum_offset);
+}
+
 /*
  *	Handling of buftargs.
  */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 33149113e333..8752821443be 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -796,20 +796,6 @@ xfs_buf_item_init(
 		bip->bli_formats[i].blf_map_size = map_size;
 	}
 
-#ifdef XFS_TRANS_DEBUG
-	/*
-	 * Allocate the arrays for tracking what needs to be logged
-	 * and what our callers request to be logged.  bli_orig
-	 * holds a copy of the original, clean buffer for comparison
-	 * against, and bli_logged keeps a 1 bit flag per byte in
-	 * the buffer to indicate which bytes the callers have asked
-	 * to have logged.
-	 */
-	bip->bli_orig = kmem_alloc(BBTOB(bp->b_length), KM_SLEEP);
-	memcpy(bip->bli_orig, bp->b_addr, BBTOB(bp->b_length));
-	bip->bli_logged = kmem_zalloc(BBTOB(bp->b_length) / NBBY, KM_SLEEP);
-#endif
-
 	/*
 	 * Put the buf item into the list of items attached to the
 	 * buffer at the front.
@@ -957,11 +943,6 @@ STATIC void
 xfs_buf_item_free(
 	xfs_buf_log_item_t	*bip)
 {
-#ifdef XFS_TRANS_DEBUG
-	kmem_free(bip->bli_orig);
-	kmem_free(bip->bli_logged);
-#endif /* XFS_TRANS_DEBUG */
-
 	xfs_buf_item_free_format(bip);
 	kmem_zone_free(xfs_buf_item_zone, bip);
 }
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 796272a2e129..1f5af79c0568 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -185,8 +185,8 @@ xfs_da3_node_write_verify(
 	struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
 
 	if (!xfs_da3_node_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -196,7 +196,7 @@ xfs_da3_node_write_verify(
 	if (bip)
 		hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DA3_NODE_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF);
 }
 
 /*
@@ -209,18 +209,20 @@ static void
 xfs_da3_node_read_verify(
 	struct xfs_buf		*bp)
 {
-	struct xfs_mount	*mp = bp->b_target->bt_mount;
 	struct xfs_da_blkinfo	*info = bp->b_addr;
 
 	switch (be16_to_cpu(info->magic)) {
 		case XFS_DA3_NODE_MAGIC:
-			if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					      XFS_DA3_NODE_CRC_OFF))
+			if (!xfs_buf_verify_cksum(bp, XFS_DA3_NODE_CRC_OFF)) {
+				xfs_buf_ioerror(bp, EFSBADCRC);
 				break;
+			}
 			/* fall through */
 		case XFS_DA_NODE_MAGIC:
-			if (!xfs_da3_node_verify(bp))
+			if (!xfs_da3_node_verify(bp)) {
+				xfs_buf_ioerror(bp, EFSCORRUPTED);
 				break;
+			}
 			return;
 		case XFS_ATTR_LEAF_MAGIC:
 		case XFS_ATTR3_LEAF_MAGIC:
@@ -237,8 +239,7 @@ xfs_da3_node_read_verify(
 	}
 
 	/* corrupt block */
-	XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
-	xfs_buf_ioerror(bp, EFSCORRUPTED);
+	xfs_verifier_error(bp);
 }
 
 const struct xfs_buf_ops xfs_da3_node_buf_ops = {
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index e5869b50dc41..623bbe8fd921 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -89,6 +89,8 @@ typedef struct xfs_dinode {
 	/* structure must be padded to 64 bit alignment */
 } xfs_dinode_t;
 
+#define XFS_DINODE_CRC_OFF	offsetof(struct xfs_dinode, di_crc)
+
 #define DI_MAX_FLUSH 0xffff
 
 /*
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index ce16ef02997a..fda46253966a 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -180,16 +180,23 @@ xfs_dir_init(
 	xfs_inode_t	*dp,
 	xfs_inode_t	*pdp)
 {
-	xfs_da_args_t	args;
+	struct xfs_da_args *args;
 	int		error;
 
-	memset((char *)&args, 0, sizeof(args));
-	args.dp = dp;
-	args.trans = tp;
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
-	if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
+	error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
+	if (error)
 		return error;
-	return xfs_dir2_sf_create(&args, pdp->i_ino);
+
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	if (!args)
+		return ENOMEM;
+
+	args->dp = dp;
+	args->trans = tp;
+	error = xfs_dir2_sf_create(args, pdp->i_ino);
+	kmem_free(args);
+	return error;
 }
 
 /*
@@ -205,41 +212,56 @@ xfs_dir_createname(
 	xfs_bmap_free_t		*flist,		/* bmap's freeblock list */
 	xfs_extlen_t		total)		/* bmap's total block count */
 {
-	xfs_da_args_t		args;
+	struct xfs_da_args	*args;
 	int			rval;
 	int			v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
-	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+	rval = xfs_dir_ino_validate(tp->t_mountp, inum);
+	if (rval)
 		return rval;
 	XFS_STATS_INC(xs_dir_create);
 
-	memset(&args, 0, sizeof(xfs_da_args_t));
-	args.name = name->name;
-	args.namelen = name->len;
-	args.filetype = name->type;
-	args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-	args.inumber = inum;
-	args.dp = dp;
-	args.firstblock = first;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = tp;
-	args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
-
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-		rval = xfs_dir2_sf_addname(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_block_addname(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_leaf_addname(&args);
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	if (!args)
+		return ENOMEM;
+
+	args->name = name->name;
+	args->namelen = name->len;
+	args->filetype = name->type;
+	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+	args->inumber = inum;
+	args->dp = dp;
+	args->firstblock = first;
+	args->flist = flist;
+	args->total = total;
+	args->whichfork = XFS_DATA_FORK;
+	args->trans = tp;
+	args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
+
+	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		rval = xfs_dir2_sf_addname(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isblock(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v) {
+		rval = xfs_dir2_block_addname(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isleaf(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v)
+		rval = xfs_dir2_leaf_addname(args);
 	else
-		rval = xfs_dir2_node_addname(&args);
+		rval = xfs_dir2_node_addname(args);
+
+out_free:
+	kmem_free(args);
 	return rval;
 }
 
@@ -282,46 +304,66 @@ xfs_dir_lookup(
 	xfs_ino_t	*inum,		/* out: inode number */
 	struct xfs_name *ci_name)	/* out: actual name if CI match */
 {
-	xfs_da_args_t	args;
+	struct xfs_da_args *args;
 	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	XFS_STATS_INC(xs_dir_lookup);
 
-	memset(&args, 0, sizeof(xfs_da_args_t));
-	args.name = name->name;
-	args.namelen = name->len;
-	args.filetype = name->type;
-	args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-	args.dp = dp;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = tp;
-	args.op_flags = XFS_DA_OP_OKNOENT;
+	/*
+	 * We need to use KM_NOFS here so that lockdep will not throw false
+	 * positive deadlock warnings on a non-transactional lookup path. It is
+	 * safe to recurse into inode recalim in that case, but lockdep can't
+	 * easily be taught about it. Hence KM_NOFS avoids having to add more
+	 * lockdep Doing this avoids having to add a bunch of lockdep class
+	 * annotations into the reclaim path for the ilock.
+	 */
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	args->name = name->name;
+	args->namelen = name->len;
+	args->filetype = name->type;
+	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+	args->dp = dp;
+	args->whichfork = XFS_DATA_FORK;
+	args->trans = tp;
+	args->op_flags = XFS_DA_OP_OKNOENT;
 	if (ci_name)
-		args.op_flags |= XFS_DA_OP_CILOOKUP;
+		args->op_flags |= XFS_DA_OP_CILOOKUP;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-		rval = xfs_dir2_sf_lookup(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_block_lookup(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_leaf_lookup(&args);
+	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		rval = xfs_dir2_sf_lookup(args);
+		goto out_check_rval;
+	}
+
+	rval = xfs_dir2_isblock(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v) {
+		rval = xfs_dir2_block_lookup(args);
+		goto out_check_rval;
+	}
+
+	rval = xfs_dir2_isleaf(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v)
+		rval = xfs_dir2_leaf_lookup(args);
 	else
-		rval = xfs_dir2_node_lookup(&args);
+		rval = xfs_dir2_node_lookup(args);
+
+out_check_rval:
 	if (rval == EEXIST)
 		rval = 0;
 	if (!rval) {
-		*inum = args.inumber;
+		*inum = args->inumber;
 		if (ci_name) {
-			ci_name->name = args.value;
-			ci_name->len = args.valuelen;
+			ci_name->name = args->value;
+			ci_name->len = args->valuelen;
 		}
 	}
+out_free:
+	kmem_free(args);
 	return rval;
 }
 
@@ -338,38 +380,51 @@ xfs_dir_removename(
 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
 	xfs_extlen_t	total)		/* bmap's total block count */
 {
-	xfs_da_args_t	args;
+	struct xfs_da_args *args;
 	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	XFS_STATS_INC(xs_dir_remove);
 
-	memset(&args, 0, sizeof(xfs_da_args_t));
-	args.name = name->name;
-	args.namelen = name->len;
-	args.filetype = name->type;
-	args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-	args.inumber = ino;
-	args.dp = dp;
-	args.firstblock = first;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = tp;
-
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-		rval = xfs_dir2_sf_removename(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_block_removename(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_leaf_removename(&args);
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	if (!args)
+		return ENOMEM;
+
+	args->name = name->name;
+	args->namelen = name->len;
+	args->filetype = name->type;
+	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+	args->inumber = ino;
+	args->dp = dp;
+	args->firstblock = first;
+	args->flist = flist;
+	args->total = total;
+	args->whichfork = XFS_DATA_FORK;
+	args->trans = tp;
+
+	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		rval = xfs_dir2_sf_removename(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isblock(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v) {
+		rval = xfs_dir2_block_removename(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isleaf(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v)
+		rval = xfs_dir2_leaf_removename(args);
 	else
-		rval = xfs_dir2_node_removename(&args);
+		rval = xfs_dir2_node_removename(args);
+out_free:
+	kmem_free(args);
 	return rval;
 }
 
@@ -386,40 +441,54 @@ xfs_dir_replace(
 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
 	xfs_extlen_t	total)		/* bmap's total block count */
 {
-	xfs_da_args_t	args;
+	struct xfs_da_args *args;
 	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
 
-	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+	rval = xfs_dir_ino_validate(tp->t_mountp, inum);
+	if (rval)
 		return rval;
 
-	memset(&args, 0, sizeof(xfs_da_args_t));
-	args.name = name->name;
-	args.namelen = name->len;
-	args.filetype = name->type;
-	args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-	args.inumber = inum;
-	args.dp = dp;
-	args.firstblock = first;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = tp;
-
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-		rval = xfs_dir2_sf_replace(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_block_replace(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_leaf_replace(&args);
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	if (!args)
+		return ENOMEM;
+
+	args->name = name->name;
+	args->namelen = name->len;
+	args->filetype = name->type;
+	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+	args->inumber = inum;
+	args->dp = dp;
+	args->firstblock = first;
+	args->flist = flist;
+	args->total = total;
+	args->whichfork = XFS_DATA_FORK;
+	args->trans = tp;
+
+	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		rval = xfs_dir2_sf_replace(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isblock(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v) {
+		rval = xfs_dir2_block_replace(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isleaf(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v)
+		rval = xfs_dir2_leaf_replace(args);
 	else
-		rval = xfs_dir2_node_replace(&args);
+		rval = xfs_dir2_node_replace(args);
+out_free:
+	kmem_free(args);
 	return rval;
 }
 
@@ -434,7 +503,7 @@ xfs_dir_canenter(
 	struct xfs_name	*name,		/* name of entry to add */
 	uint		resblks)
 {
-	xfs_da_args_t	args;
+	struct xfs_da_args *args;
 	int		rval;
 	int		v;		/* type-checking value */
 
@@ -443,29 +512,42 @@ xfs_dir_canenter(
 
 	ASSERT(S_ISDIR(dp->i_d.di_mode));
 
-	memset(&args, 0, sizeof(xfs_da_args_t));
-	args.name = name->name;
-	args.namelen = name->len;
-	args.filetype = name->type;
-	args.hashval = dp->i_mount->m_dirnameops->hashname(name);
-	args.dp = dp;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = tp;
-	args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
+	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
+	if (!args)
+		return ENOMEM;
+
+	args->name = name->name;
+	args->namelen = name->len;
+	args->filetype = name->type;
+	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
+	args->dp = dp;
+	args->whichfork = XFS_DATA_FORK;
+	args->trans = tp;
+	args->op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
 							XFS_DA_OP_OKNOENT;
 
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
-		rval = xfs_dir2_sf_addname(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_block_addname(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
-		return rval;
-	else if (v)
-		rval = xfs_dir2_leaf_addname(&args);
+	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+		rval = xfs_dir2_sf_addname(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isblock(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v) {
+		rval = xfs_dir2_block_addname(args);
+		goto out_free;
+	}
+
+	rval = xfs_dir2_isleaf(tp, dp, &v);
+	if (rval)
+		goto out_free;
+	if (v)
+		rval = xfs_dir2_leaf_addname(args);
 	else
-		rval = xfs_dir2_node_addname(&args);
+		rval = xfs_dir2_node_addname(args);
+out_free:
+	kmem_free(args);
 	return rval;
 }
 
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 90cdbf4b5f19..4f6a38cb83a4 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -89,13 +89,14 @@ xfs_dir3_block_read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
-	     !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  XFS_DIR3_DATA_CRC_OFF)) ||
-	    !xfs_dir3_block_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	     !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_dir3_block_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -107,8 +108,8 @@ xfs_dir3_block_write_verify(
 	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;
 
 	if (!xfs_dir3_block_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -118,7 +119,7 @@ xfs_dir3_block_write_verify(
 	if (bip)
 		hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 70acff4ee173..afa4ad523f3f 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -241,7 +241,6 @@ static void
 xfs_dir3_data_reada_verify(
 	struct xfs_buf		*bp)
 {
-	struct xfs_mount	*mp = bp->b_target->bt_mount;
 	struct xfs_dir2_data_hdr *hdr = bp->b_addr;
 
 	switch (hdr->magic) {
@@ -255,8 +254,8 @@ xfs_dir3_data_reada_verify(
 		xfs_dir3_data_verify(bp);
 		return;
 	default:
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		break;
 	}
 }
@@ -267,13 +266,14 @@ xfs_dir3_data_read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
-	     !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  XFS_DIR3_DATA_CRC_OFF)) ||
-	    !xfs_dir3_data_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	     !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
+		 xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_dir3_data_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -285,8 +285,8 @@ xfs_dir3_data_write_verify(
 	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;
 
 	if (!xfs_dir3_data_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -296,7 +296,7 @@ xfs_dir3_data_write_verify(
 	if (bip)
 		hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index ae47ec6e16c4..d36e97df1187 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -179,13 +179,14 @@ __read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
-	     !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  XFS_DIR3_LEAF_CRC_OFF)) ||
-	    !xfs_dir3_leaf_verify(bp, magic)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	     !xfs_buf_verify_cksum(bp, XFS_DIR3_LEAF_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_dir3_leaf_verify(bp, magic))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -198,8 +199,8 @@ __write_verify(
 	struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr;
 
 	if (!xfs_dir3_leaf_verify(bp, magic)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -209,7 +210,7 @@ __write_verify(
 	if (bip)
 		hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_LEAF_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_DIR3_LEAF_CRC_OFF);
 }
 
 static void
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 48c7d18f68c3..cb434d732681 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -115,13 +115,14 @@ xfs_dir3_free_read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
-	     !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  XFS_DIR3_FREE_CRC_OFF)) ||
-	    !xfs_dir3_free_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	    !xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_dir3_free_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -133,8 +134,8 @@ xfs_dir3_free_write_verify(
 	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;
 
 	if (!xfs_dir3_free_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -144,7 +145,7 @@ xfs_dir3_free_write_verify(
 	if (bip)
 		hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF);
+	xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 7aeb4c895b32..868b19f096bf 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -615,7 +615,7 @@ xfs_qm_dqread(
 
 	if (flags & XFS_QMOPT_DQALLOC) {
 		tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC);
-		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_attrsetm,
+		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_dqalloc,
 					  XFS_QM_DQALLOC_SPACE_RES(mp), 0);
 		if (error)
 			goto error1;
diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c
index d401457d2f25..610da8177737 100644
--- a/fs/xfs/xfs_dquot_buf.c
+++ b/fs/xfs/xfs_dquot_buf.c
@@ -257,10 +257,13 @@ xfs_dquot_buf_read_verify(
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (!xfs_dquot_buf_verify_crc(mp, bp))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_dquot_buf_verify(mp, bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 /*
@@ -275,8 +278,8 @@ xfs_dquot_buf_write_verify(
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
 	if (!xfs_dquot_buf_verify(mp, bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 }
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 9995b807d627..edac5b057d28 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -156,7 +156,7 @@ xfs_error_report(
 {
 	if (level <= xfs_error_level) {
 		xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
-		"Internal error %s at line %d of file %s.  Caller 0x%p",
+		"Internal error %s at line %d of file %s.  Caller %pF",
 			    tag, linenum, filename, ra);
 
 		xfs_stack_trace();
@@ -178,3 +178,28 @@ xfs_corruption_error(
 	xfs_error_report(tag, level, mp, filename, linenum, ra);
 	xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
 }
+
+/*
+ * Warnings specifically for verifier errors.  Differentiate CRC vs. invalid
+ * values, and omit the stack trace unless the error level is tuned high.
+ */
+void
+xfs_verifier_error(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+
+	xfs_alert(mp, "Metadata %s detected at %pF, block 0x%llx",
+		  bp->b_error == EFSBADCRC ? "CRC error" : "corruption",
+		  __return_address, bp->b_bn);
+
+	xfs_alert(mp, "Unmount and run xfs_repair");
+
+	if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
+		xfs_alert(mp, "First 64 bytes of corrupted metadata buffer:");
+		xfs_hex_dump(xfs_buf_offset(bp, 0), 64);
+	}
+
+	if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
+		xfs_stack_trace();
+}
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 079a367f44ee..c1c57d4a4b5d 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -34,6 +34,7 @@ extern void xfs_error_report(const char *tag, int level, struct xfs_mount *mp,
 extern void xfs_corruption_error(const char *tag, int level,
 			struct xfs_mount *mp, void *p, const char *filename,
 			int linenum, inst_t *ra);
+extern void xfs_verifier_error(struct xfs_buf *bp);
 
 #define	XFS_ERROR_REPORT(e, lvl, mp)	\
 	xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 64b48eade91d..b7c77a295870 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -823,7 +823,8 @@ xfs_file_fallocate(
 
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
-	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+		     FALLOC_FL_COLLAPSE_RANGE))
 		return -EOPNOTSUPP;
 
 	xfs_ilock(ip, XFS_IOLOCK_EXCL);
@@ -831,6 +832,20 @@ xfs_file_fallocate(
 		error = xfs_free_file_space(ip, offset, len);
 		if (error)
 			goto out_unlock;
+	} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
+		unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
+
+		if (offset & blksize_mask || len & blksize_mask) {
+			error = -EINVAL;
+			goto out_unlock;
+		}
+
+		ASSERT(offset + len < i_size_read(inode));
+		new_size = i_size_read(inode) - len;
+
+		error = xfs_collapse_file_space(ip, offset, len);
+		if (error)
+			goto out_unlock;
 	} else {
 		if (!(mode & FALLOC_FL_KEEP_SIZE) &&
 		    offset + len > i_size_read(inode)) {
@@ -859,7 +874,7 @@ xfs_file_fallocate(
 	if (ip->i_d.di_mode & S_IXGRP)
 		ip->i_d.di_mode &= ~S_ISGID;
 
-	if (!(mode & FALLOC_FL_PUNCH_HOLE))
+	if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)))
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
 
 	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -1465,6 +1480,7 @@ const struct file_operations xfs_dir_file_operations = {
 
 static const struct vm_operations_struct xfs_file_vm_ops = {
 	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
 	.page_mkwrite	= xfs_vm_page_mkwrite,
 	.remap_pages	= generic_file_remap_pages,
 };
diff --git a/fs/xfs/xfs_format.h b/fs/xfs/xfs_format.h
index b6ab5a3cfa12..9898f31d05d8 100644
--- a/fs/xfs/xfs_format.h
+++ b/fs/xfs/xfs_format.h
@@ -145,6 +145,8 @@ struct xfs_dsymlink_hdr {
 	__be64	sl_lsn;
 };
 
+#define XFS_SYMLINK_CRC_OFF	offsetof(struct xfs_dsymlink_hdr, sl_crc)
+
 /*
  * The maximum pathlen is 1024 bytes. Since the minimum file system
  * blocksize is 512 bytes, we can get a max of 3 extents back from
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 5d7f105a1c82..5959b3b4c7c9 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -1568,18 +1568,17 @@ xfs_agi_read_verify(
 	struct xfs_buf	*bp)
 {
 	struct xfs_mount *mp = bp->b_target->bt_mount;
-	int		agi_ok = 1;
 
-	if (xfs_sb_version_hascrc(&mp->m_sb))
-		agi_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-					  offsetof(struct xfs_agi, agi_crc));
-	agi_ok = agi_ok && xfs_agi_verify(bp);
-
-	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
-			XFS_RANDOM_IALLOC_READ_AGI))) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	    !xfs_buf_verify_cksum(bp, XFS_AGI_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (XFS_TEST_ERROR(!xfs_agi_verify(bp), mp,
+				XFS_ERRTAG_IALLOC_READ_AGI,
+				XFS_RANDOM_IALLOC_READ_AGI))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -1590,8 +1589,8 @@ xfs_agi_write_verify(
 	struct xfs_buf_log_item	*bip = bp->b_fspriv;
 
 	if (!xfs_agi_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -1600,8 +1599,7 @@ xfs_agi_write_verify(
 
 	if (bip)
 		XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn);
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 offsetof(struct xfs_agi, agi_crc));
+	xfs_buf_update_cksum(bp, XFS_AGI_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_agi_buf_ops = {
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index c8fa5bbb36de..7e309b11e87d 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -243,12 +243,14 @@ static void
 xfs_inobt_read_verify(
 	struct xfs_buf	*bp)
 {
-	if (!(xfs_btree_sblock_verify_crc(bp) &&
-	      xfs_inobt_verify(bp))) {
-		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
+	if (!xfs_btree_sblock_verify_crc(bp))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_inobt_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+
+	if (bp->b_error) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		xfs_verifier_error(bp);
 	}
 }
 
@@ -258,9 +260,9 @@ xfs_inobt_write_verify(
 {
 	if (!xfs_inobt_verify(bp)) {
 		trace_xfs_btree_corrupt(bp, _RET_IP_);
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     bp->b_target->bt_mount, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
+		return;
 	}
 	xfs_btree_sblock_calc_crc(bp);
 
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c
index 4fc9f39dd89e..24e993996bdc 100644
--- a/fs/xfs/xfs_inode_buf.c
+++ b/fs/xfs/xfs_inode_buf.c
@@ -102,8 +102,7 @@ xfs_inode_buf_verify(
 			}
 
 			xfs_buf_ioerror(bp, EFSCORRUPTED);
-			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
-					     mp, dip);
+			xfs_verifier_error(bp);
 #ifdef DEBUG
 			xfs_alert(mp,
 				"bad inode magic/vsn daddr %lld #%d (magic=%x)",
@@ -306,7 +305,7 @@ xfs_dinode_verify(
 	if (!xfs_sb_version_hascrc(&mp->m_sb))
 		return false;
 	if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
-			      offsetof(struct xfs_dinode, di_crc)))
+			      XFS_DINODE_CRC_OFF))
 		return false;
 	if (be64_to_cpu(dip->di_ino) != ip->i_ino)
 		return false;
@@ -327,7 +326,7 @@ xfs_dinode_calc_crc(
 
 	ASSERT(xfs_sb_version_hascrc(&mp->m_sb));
 	crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
-			      offsetof(struct xfs_dinode, di_crc));
+			      XFS_DINODE_CRC_OFF);
 	dip->di_crc = xfs_end_cksum(crc);
 }
 
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 22d1cbea283d..3b80ebae05f5 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -128,7 +128,6 @@ xfs_iomap_write_direct(
 	xfs_fsblock_t	firstfsb;
 	xfs_extlen_t	extsz, temp;
 	int		nimaps;
-	int		bmapi_flag;
 	int		quota_flag;
 	int		rt;
 	xfs_trans_t	*tp;
@@ -200,18 +199,15 @@ xfs_iomap_write_direct(
 
 	xfs_trans_ijoin(tp, ip, 0);
 
-	bmapi_flag = 0;
-	if (offset < XFS_ISIZE(ip) || extsz)
-		bmapi_flag |= XFS_BMAPI_PREALLOC;
-
 	/*
 	 * From this point onwards we overwrite the imap pointer that the
 	 * caller gave to us.
 	 */
 	xfs_bmap_init(&free_list, &firstfsb);
 	nimaps = 1;
-	error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag,
-				&firstfsb, 0, imap, &nimaps, &free_list);
+	error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
+				XFS_BMAPI_PREALLOC, &firstfsb, 0,
+				imap, &nimaps, &free_list);
 	if (error)
 		goto out_bmap_cancel;
 
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 9ddfb8190ca1..bb3bb658e39c 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -48,6 +48,18 @@
 #include <linux/fiemap.h>
 #include <linux/slab.h>
 
+/*
+ * Directories have different lock order w.r.t. mmap_sem compared to regular
+ * files. This is due to readdir potentially triggering page faults on a user
+ * buffer inside filldir(), and this happens with the ilock on the directory
+ * held. For regular files, the lock order is the other way around - the
+ * mmap_sem is taken during the page fault, and then we lock the ilock to do
+ * block mapping. Hence we need a different class for the directory ilock so
+ * that lockdep can tell them apart.
+ */
+static struct lock_class_key xfs_nondir_ilock_class;
+static struct lock_class_key xfs_dir_ilock_class;
+
 static int
 xfs_initxattrs(
 	struct inode		*inode,
@@ -1191,6 +1203,7 @@ xfs_setup_inode(
 	xfs_diflags_to_iflags(inode, ip);
 
 	ip->d_ops = ip->i_mount->m_nondir_inode_ops;
+	lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class);
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
 		inode->i_op = &xfs_inode_operations;
@@ -1198,6 +1211,7 @@ xfs_setup_inode(
 		inode->i_mapping->a_ops = &xfs_address_space_operations;
 		break;
 	case S_IFDIR:
+		lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
 		if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
 			inode->i_op = &xfs_dir_ci_inode_operations;
 		else
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index f9bb590acc0e..825249d2dfc1 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -119,6 +119,7 @@ typedef __uint64_t __psunsigned_t;
 #include "xfs_iops.h"
 #include "xfs_aops.h"
 #include "xfs_super.h"
+#include "xfs_cksum.h"
 #include "xfs_buf.h"
 #include "xfs_message.h"
 
@@ -178,6 +179,7 @@ typedef __uint64_t __psunsigned_t;
 #define ENOATTR		ENODATA		/* Attribute not found */
 #define EWRONGFS	EINVAL		/* Mount with wrong filesystem type */
 #define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
+#define EFSBADCRC	EBADMSG		/* Bad CRC detected */
 
 #define SYNCHRONIZE()	barrier()
 #define __return_address __builtin_return_address(0)
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index b0f4ef77fa70..2c4004475e71 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -175,7 +175,7 @@ void	  xlog_iodone(struct xfs_buf *);
 struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
 void	  xfs_log_ticket_put(struct xlog_ticket *ticket);
 
-int	xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
+void	xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
 				xfs_lsn_t *commit_lsn, int flags);
 bool	xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
 
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 4ef6fdbced78..7e5455391176 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -499,13 +499,6 @@ xlog_cil_push(
 	cil->xc_ctx = new_ctx;
 
 	/*
-	 * mirror the new sequence into the cil structure so that we can do
-	 * unlocked checks against the current sequence in log forces without
-	 * risking deferencing a freed context pointer.
-	 */
-	cil->xc_current_sequence = new_ctx->sequence;
-
-	/*
 	 * The switch is now done, so we can drop the context lock and move out
 	 * of a shared context. We can't just go straight to the commit record,
 	 * though - we need to synchronise with previous and future commits so
@@ -523,8 +516,15 @@ xlog_cil_push(
 	 * Hence we need to add this context to the committing context list so
 	 * that higher sequences will wait for us to write out a commit record
 	 * before they do.
+	 *
+	 * xfs_log_force_lsn requires us to mirror the new sequence into the cil
+	 * structure atomically with the addition of this sequence to the
+	 * committing list. This also ensures that we can do unlocked checks
+	 * against the current sequence in log forces without risking
+	 * deferencing a freed context pointer.
 	 */
 	spin_lock(&cil->xc_push_lock);
+	cil->xc_current_sequence = new_ctx->sequence;
 	list_add(&ctx->committing, &cil->xc_committing);
 	spin_unlock(&cil->xc_push_lock);
 	up_write(&cil->xc_ctx_lock);
@@ -662,8 +662,14 @@ xlog_cil_push_background(
 
 }
 
+/*
+ * xlog_cil_push_now() is used to trigger an immediate CIL push to the sequence
+ * number that is passed. When it returns, the work will be queued for
+ * @push_seq, but it won't be completed. The caller is expected to do any
+ * waiting for push_seq to complete if it is required.
+ */
 static void
-xlog_cil_push_foreground(
+xlog_cil_push_now(
 	struct xlog	*log,
 	xfs_lsn_t	push_seq)
 {
@@ -688,10 +694,8 @@ xlog_cil_push_foreground(
 	}
 
 	cil->xc_push_seq = push_seq;
+	queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work);
 	spin_unlock(&cil->xc_push_lock);
-
-	/* do the push now */
-	xlog_cil_push(log);
 }
 
 bool
@@ -721,7 +725,7 @@ xlog_cil_empty(
  * background commit, returns without it held once background commits are
  * allowed again.
  */
-int
+void
 xfs_log_commit_cil(
 	struct xfs_mount	*mp,
 	struct xfs_trans	*tp,
@@ -767,7 +771,6 @@ xfs_log_commit_cil(
 	xlog_cil_push_background(log);
 
 	up_read(&cil->xc_ctx_lock);
-	return 0;
 }
 
 /*
@@ -796,7 +799,8 @@ xlog_cil_force_lsn(
 	 * xlog_cil_push() handles racing pushes for the same sequence,
 	 * so no need to deal with it here.
 	 */
-	xlog_cil_push_foreground(log, sequence);
+restart:
+	xlog_cil_push_now(log, sequence);
 
 	/*
 	 * See if we can find a previous sequence still committing.
@@ -804,7 +808,6 @@ xlog_cil_force_lsn(
 	 * before allowing the force of push_seq to go ahead. Hence block
 	 * on commits for those as well.
 	 */
-restart:
 	spin_lock(&cil->xc_push_lock);
 	list_for_each_entry(ctx, &cil->xc_committing, committing) {
 		if (ctx->sequence > sequence)
@@ -822,6 +825,28 @@ restart:
 		/* found it! */
 		commit_lsn = ctx->commit_lsn;
 	}
+
+	/*
+	 * The call to xlog_cil_push_now() executes the push in the background.
+	 * Hence by the time we have got here it our sequence may not have been
+	 * pushed yet. This is true if the current sequence still matches the
+	 * push sequence after the above wait loop and the CIL still contains
+	 * dirty objects.
+	 *
+	 * When the push occurs, it will empty the CIL and
+	 * atomically increment the currect sequence past the push sequence and
+	 * move it into the committing list. Of course, if the CIL is clean at
+	 * the time of the push, it won't have pushed the CIL at all, so in that
+	 * case we should try the push for this sequence again from the start
+	 * just in case.
+	 */
+
+	if (sequence == cil->xc_current_sequence &&
+	    !list_empty(&cil->xc_cil)) {
+		spin_unlock(&cil->xc_push_lock);
+		goto restart;
+	}
+
 	spin_unlock(&cil->xc_push_lock);
 	return commit_lsn;
 }
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index a6a76b2b6a85..ec5ca65c6211 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -842,7 +842,7 @@ xfs_growfs_rt_alloc(
 		/*
 		 * Reserve space & log for one extent added to the file.
 		 */
-		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata,
+		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc,
 					  resblks, 0);
 		if (error)
 			goto error_cancel;
diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c
index 1e116794bb66..0c0e41bbe4e3 100644
--- a/fs/xfs/xfs_sb.c
+++ b/fs/xfs/xfs_sb.c
@@ -288,6 +288,7 @@ xfs_mount_validate_sb(
 	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
 	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
 	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
+	    sbp->sb_inopblock != howmany(sbp->sb_blocksize,sbp->sb_inodesize) ||
 	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
@@ -610,12 +611,11 @@ xfs_sb_read_verify(
 						XFS_SB_VERSION_5) ||
 	     dsb->sb_crc != 0)) {
 
-		if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-				      offsetof(struct xfs_sb, sb_crc))) {
+		if (!xfs_buf_verify_cksum(bp, XFS_SB_CRC_OFF)) {
 			/* Only fail bad secondaries on a known V5 filesystem */
 			if (bp->b_bn == XFS_SB_DADDR ||
 			    xfs_sb_version_hascrc(&mp->m_sb)) {
-				error = EFSCORRUPTED;
+				error = EFSBADCRC;
 				goto out_error;
 			}
 		}
@@ -624,10 +624,9 @@ xfs_sb_read_verify(
 
 out_error:
 	if (error) {
-		if (error == EFSCORRUPTED)
-			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-					     mp, bp->b_addr);
 		xfs_buf_ioerror(bp, error);
+		if (error == EFSCORRUPTED || error == EFSBADCRC)
+			xfs_verifier_error(bp);
 	}
 }
 
@@ -662,9 +661,8 @@ xfs_sb_write_verify(
 
 	error = xfs_sb_verify(bp, false);
 	if (error) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
-				     mp, bp->b_addr);
 		xfs_buf_ioerror(bp, error);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -674,8 +672,7 @@ xfs_sb_write_verify(
 	if (bip)
 		XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 offsetof(struct xfs_sb, sb_crc));
+	xfs_buf_update_cksum(bp, XFS_SB_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_sb_buf_ops = {
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 35061d4b614c..f7b2fe77c5a5 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -182,6 +182,8 @@ typedef struct xfs_sb {
 	/* must be padded to 64 bit alignment */
 } xfs_sb_t;
 
+#define XFS_SB_CRC_OFF		offsetof(struct xfs_sb, sb_crc)
+
 /*
  * Superblock - on disk version.  Must match the in core version above.
  * Must be padded to 64 bit alignment.
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index d971f4932b5d..0ef599218991 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -996,7 +996,7 @@ xfs_fs_evict_inode(
 
 	trace_xfs_evict_inode(ip);
 
-	truncate_inode_pages(&inode->i_data, 0);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
 	XFS_STATS_INC(vn_rele);
 	XFS_STATS_INC(vn_remove);
diff --git a/fs/xfs/xfs_symlink_remote.c b/fs/xfs/xfs_symlink_remote.c
index bf59a2b45f8c..9b32052ff65e 100644
--- a/fs/xfs/xfs_symlink_remote.c
+++ b/fs/xfs/xfs_symlink_remote.c
@@ -133,12 +133,13 @@ xfs_symlink_read_verify(
 	if (!xfs_sb_version_hascrc(&mp->m_sb))
 		return;
 
-	if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-				  offsetof(struct xfs_dsymlink_hdr, sl_crc)) ||
-	    !xfs_symlink_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+	if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
+		xfs_buf_ioerror(bp, EFSBADCRC);
+	else if (!xfs_symlink_verify(bp))
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
-	}
+
+	if (bp->b_error)
+		xfs_verifier_error(bp);
 }
 
 static void
@@ -153,8 +154,8 @@ xfs_symlink_write_verify(
 		return;
 
 	if (!xfs_symlink_verify(bp)) {
-		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
 		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		xfs_verifier_error(bp);
 		return;
 	}
 
@@ -162,8 +163,7 @@ xfs_symlink_write_verify(
 		struct xfs_dsymlink_hdr *dsl = bp->b_addr;
 		dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 	}
-	xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-			 offsetof(struct xfs_dsymlink_hdr, sl_crc));
+	xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF);
 }
 
 const struct xfs_buf_ops xfs_symlink_buf_ops = {
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 425dfa45b9a0..a4ae41c179a8 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_collapse_file_space);
 DEFINE_INODE_EVENT(xfs_readdir);
 #ifdef CONFIG_XFS_POSIX_ACL
 DEFINE_INODE_EVENT(xfs_get_acl);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index c812c5c060de..54a57326d85b 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -887,12 +887,7 @@ xfs_trans_commit(
 		xfs_trans_apply_sb_deltas(tp);
 	xfs_trans_apply_dquot_deltas(tp);
 
-	error = xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
-	if (error == ENOMEM) {
-		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
-		error = XFS_ERROR(EIO);
-		goto out_unreserve;
-	}
+	xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
 
 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 	xfs_trans_free(tp);
@@ -902,10 +897,7 @@ xfs_trans_commit(
 	 * log out now and wait for it.
 	 */
 	if (sync) {
-		if (!error) {
-			error = _xfs_log_force_lsn(mp, commit_lsn,
-				      XFS_LOG_SYNC, NULL);
-		}
+		error = _xfs_log_force_lsn(mp, commit_lsn, XFS_LOG_SYNC, NULL);
 		XFS_STATS_INC(xs_trans_sync);
 	} else {
 		XFS_STATS_INC(xs_trans_async);
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index 2ffd3e331b49..8515b0449dc8 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -644,15 +644,14 @@ xfs_calc_qm_setqlim_reservation(
 
 /*
  * Allocating quota on disk if needed.
- *	the write transaction log space: M_RES(mp)->tr_write.tr_logres
+ *	the write transaction log space for quota file extent allocation
  *	the unit of quota allocation: one system block size
  */
 STATIC uint
 xfs_calc_qm_dqalloc_reservation(
 	struct xfs_mount	*mp)
 {
-	ASSERT(M_RES(mp)->tr_write.tr_logres);
-	return M_RES(mp)->tr_write.tr_logres +
+	return xfs_calc_write_reservation(mp) +
 		xfs_calc_buf_res(1,
 			XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
 }
@@ -784,7 +783,6 @@ xfs_trans_resv_calc(
 	/* The following transaction are logged in logical format */
 	resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
 	resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
-	resp->tr_swrite.tr_logres = xfs_calc_swrite_reservation(mp);
 	resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
 	resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
 	resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
diff --git a/fs/xfs/xfs_trans_resv.h b/fs/xfs/xfs_trans_resv.h
index de7de9aaad8a..f76c1297b83f 100644
--- a/fs/xfs/xfs_trans_resv.h
+++ b/fs/xfs/xfs_trans_resv.h
@@ -42,7 +42,6 @@ struct xfs_trans_resv {
 	struct xfs_trans_res	tr_ifree;	/* inode free trans */
 	struct xfs_trans_res	tr_ichange;	/* inode update trans */
 	struct xfs_trans_res	tr_growdata;	/* fs data section grow trans */
-	struct xfs_trans_res	tr_swrite;	/* sync write inode trans */
 	struct xfs_trans_res	tr_addafork;	/* add inode attr fork trans */
 	struct xfs_trans_res	tr_writeid;	/* write setuid/setgid file */
 	struct xfs_trans_res	tr_attrinval;	/* attr fork buffer
diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h
index c927a0b1de78..88cb477524a6 100644
--- a/include/acpi/acbuffer.h
+++ b/include/acpi/acbuffer.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 3ea214cff349..932a60d6ed82 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 4e280bd226dd..8b06e4c1dd5d 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index 1f36777e26fe..3dd6e838dc30 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 4607b027a657..1baae6edda89 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h
index 618787715d56..ca0cb603b171 100644
--- a/include/acpi/acpi.h
+++ b/include/acpi/acpi.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -62,5 +62,8 @@
 #include <acpi/acrestyp.h>		/* Resource Descriptor structs */
 #include <acpi/acpiosxf.h>		/* OSL interfaces (ACPICA-to-OS) */
 #include <acpi/acpixf.h>		/* ACPI core subsystem external interfaces */
+#ifdef ACPI_NATIVE_INTERFACE_HEADER
+#include ACPI_NATIVE_INTERFACE_HEADER
+#endif
 
 #endif				/* __ACPI_H__ */
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8256eb4ad057..9d82482643c8 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -49,8 +49,8 @@ acpi_evaluate_reference(acpi_handle handle,
 			struct acpi_object_list *arguments,
 			struct acpi_handle_list *list);
 acpi_status
-acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
-			u32 status_code, struct acpi_buffer *status_buf);
+acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
+		  struct acpi_buffer *status_buf);
 
 acpi_status
 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld);
@@ -133,10 +133,24 @@ struct acpi_scan_handler {
 	struct list_head list_node;
 	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
 	void (*detach)(struct acpi_device *dev);
+	void (*bind)(struct device *phys_dev);
+	void (*unbind)(struct device *phys_dev);
 	struct acpi_hotplug_profile hotplug;
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*notify)(struct acpi_device *, u32);
+	void (*uevent)(struct acpi_device *, u32);
+	void (*fixup)(struct acpi_device *);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -190,7 +204,9 @@ struct acpi_device_flags {
 	u32 initialized:1;
 	u32 visited:1;
 	u32 no_hotplug:1;
-	u32 reserved:24;
+	u32 hotplug_notify:1;
+	u32 is_dock_station:1;
+	u32 reserved:22;
 };
 
 /* File System */
@@ -329,6 +345,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +368,24 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*notify)(struct acpi_device *, u32),
+				       void (*uevent)(struct acpi_device *, u32),
+				       void (*fixup)(struct acpi_device *))
+{
+	hp->self = adev;
+	hp->notify = notify;
+	hp->uevent = uevent;
+	hp->fixup = fixup;
+	adev->hp = hp;
+}
+
+void acpi_initialize_hp_context(struct acpi_device *adev,
+				struct acpi_hotplug_context *hp,
+				int (*notify)(struct acpi_device *, u32),
+				void (*uevent)(struct acpi_device *, u32));
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -381,6 +416,8 @@ extern int unregister_acpi_notifier(struct notifier_block *);
  */
 
 int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
+void acpi_bus_put_acpi_device(struct acpi_device *adev);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
 				       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
@@ -402,6 +439,8 @@ static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
 
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
+void acpi_lock_hp_context(void);
+void acpi_unlock_hp_context(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index b124fdb26046..d504613bbf80 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -109,36 +109,14 @@ void pci_acpi_crs_quirks(void);
 /*--------------------------------------------------------------------------
                                   Dock Station
   -------------------------------------------------------------------------- */
-struct acpi_dock_ops {
-	acpi_notify_handler fixup;
-	acpi_notify_handler handler;
-	acpi_notify_handler uevent;
-};
 
 #ifdef CONFIG_ACPI_DOCK
-extern int is_dock_device(acpi_handle handle);
-extern int register_hotplug_dock_device(acpi_handle handle,
-					const struct acpi_dock_ops *ops,
-					void *context,
-					void (*init)(void *),
-					void (*release)(void *));
-extern void unregister_hotplug_dock_device(acpi_handle handle);
+extern int is_dock_device(struct acpi_device *adev);
 #else
-static inline int is_dock_device(acpi_handle handle)
+static inline int is_dock_device(struct acpi_device *adev)
 {
 	return 0;
 }
-static inline int register_hotplug_dock_device(acpi_handle handle,
-					       const struct acpi_dock_ops *ops,
-					       void *context,
-					       void (*init)(void *),
-					       void (*release)(void *))
-{
-	return -ENODEV;
-}
-static inline void unregister_hotplug_dock_device(acpi_handle handle)
-{
-}
 #endif /* CONFIG_ACPI_DOCK */
 
 #endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index 451823cb8837..94a37cd7fbda 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -13,7 +13,6 @@
 
 extern int pxm_to_node(int);
 extern int node_to_pxm(int);
-extern void __acpi_map_pxm_to_node(int, int);
 extern int acpi_map_pxm_to_node(int);
 extern unsigned char acpi_srat_revision;
 
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 01e6c6d8b7e1..f6f5f8af2112 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index fea6773f87fc..8b12faadcba2 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20131218
+#define ACPI_CA_VERSION                 0x20140114
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -230,6 +230,10 @@ acpi_attach_data(acpi_handle object, acpi_object_handler handler, void *data);
 acpi_status acpi_detach_data(acpi_handle object, acpi_object_handler handler);
 
 acpi_status
+acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data,
+		   void (*callback)(void *));
+
+acpi_status
 acpi_get_data(acpi_handle object, acpi_object_handler handler, void **data);
 
 acpi_status
diff --git a/include/acpi/acrestyp.h b/include/acpi/acrestyp.h
index cbf4bf977f75..eb760ca0b2e0 100644
--- a/include/acpi/acrestyp.h
+++ b/include/acpi/acrestyp.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index 325aeae1fa99..3b30e36b53b5 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 4ec8c194bfe5..212c65de75df 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 094a906a0e98..f3372441e3a5 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index 01c2a9013e40..c2295cc4a5c0 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 68a3ada689c9..e76356574374 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,18 +55,16 @@
 #error ACPI_MACHINE_WIDTH not defined
 #endif
 
-/*! [Begin] no source code translation */
-
 /*
  * Data type ranges
  * Note: These macros are designed to be compiler independent as well as
  * working around problems that some 32-bit compilers have with 64-bit
  * constants.
  */
-#define ACPI_UINT8_MAX                  (UINT8) (~((UINT8)  0))	/* 0xFF               */
-#define ACPI_UINT16_MAX                 (UINT16)(~((UINT16) 0))	/* 0xFFFF             */
-#define ACPI_UINT32_MAX                 (UINT32)(~((UINT32) 0))	/* 0xFFFFFFFF         */
-#define ACPI_UINT64_MAX                 (UINT64)(~((UINT64) 0))	/* 0xFFFFFFFFFFFFFFFF */
+#define ACPI_UINT8_MAX                  (u8) (~((u8)  0))	/* 0xFF               */
+#define ACPI_UINT16_MAX                 (u16)(~((u16) 0))	/* 0xFFFF             */
+#define ACPI_UINT32_MAX                 (u32)(~((u32) 0))	/* 0xFFFFFFFF         */
+#define ACPI_UINT64_MAX                 (u64)(~((u64) 0))	/* 0xFFFFFFFFFFFFFFFF */
 #define ACPI_ASCII_MAX                  0x7F
 
 /*
@@ -77,18 +75,18 @@
  *
  * 1) The following types are of fixed size for all targets (16/32/64):
  *
- * BOOLEAN      Logical boolean
+ * u8           Logical boolean
  *
- * UINT8        8-bit  (1 byte) unsigned value
- * UINT16       16-bit (2 byte) unsigned value
- * UINT32       32-bit (4 byte) unsigned value
- * UINT64       64-bit (8 byte) unsigned value
+ * u8           8-bit  (1 byte) unsigned value
+ * u16          16-bit (2 byte) unsigned value
+ * u32          32-bit (4 byte) unsigned value
+ * u64          64-bit (8 byte) unsigned value
  *
- * INT16        16-bit (2 byte) signed value
- * INT32        32-bit (4 byte) signed value
- * INT64        64-bit (8 byte) signed value
+ * s16          16-bit (2 byte) signed value
+ * s32          32-bit (4 byte) signed value
+ * s64          64-bit (8 byte) signed value
  *
- * COMPILER_DEPENDENT_UINT64/INT64 - These types are defined in the
+ * COMPILER_DEPENDENT_UINT64/s64 - These types are defined in the
  * compiler-dependent header(s) and were introduced because there is no common
  * 64-bit integer type across the various compilation models, as shown in
  * the table below.
@@ -110,11 +108,11 @@
  * usually used for memory allocation, efficient loop counters, and array
  * indexes. The types are similar to the size_t type in the C library and are
  * required because there is no C type that consistently represents the native
- * data width. ACPI_SIZE is needed because there is no guarantee that a
+ * data width. acpi_size is needed because there is no guarantee that a
  * kernel-level C library is present.
  *
- * ACPI_SIZE        16/32/64-bit unsigned value
- * ACPI_NATIVE_INT  16/32/64-bit signed value
+ * acpi_size        16/32/64-bit unsigned value
+ * acpi_native_int  16/32/64-bit signed value
  */
 
 /*******************************************************************************
@@ -123,13 +121,15 @@
  *
  ******************************************************************************/
 
-typedef unsigned char BOOLEAN;
-typedef unsigned char UINT8;
-typedef unsigned short UINT16;
-typedef COMPILER_DEPENDENT_UINT64 UINT64;
-typedef COMPILER_DEPENDENT_INT64 INT64;
+#ifndef ACPI_USE_SYSTEM_INTTYPES
+
+typedef unsigned char u8;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef COMPILER_DEPENDENT_UINT64 u64;
+typedef COMPILER_DEPENDENT_INT64 s64;
 
-/*! [End] no source code translation !*/
+#endif				/* ACPI_USE_SYSTEM_INTTYPES */
 
 /*
  * Value returned by acpi_os_get_thread_id. There is no standard "thread_id"
@@ -149,12 +149,12 @@ typedef COMPILER_DEPENDENT_INT64 INT64;
 
 #if ACPI_MACHINE_WIDTH == 64
 
-/*! [Begin] no source code translation (keep the typedefs as-is) */
+#ifndef ACPI_USE_SYSTEM_INTTYPES
 
-typedef unsigned int UINT32;
-typedef int INT32;
+typedef unsigned int u32;
+typedef int s32;
 
-/*! [End] no source code translation !*/
+#endif				/* ACPI_USE_SYSTEM_INTTYPES */
 
 typedef s64 acpi_native_int;
 
@@ -188,12 +188,12 @@ typedef u64 acpi_physical_address;
 
 #elif ACPI_MACHINE_WIDTH == 32
 
-/*! [Begin] no source code translation (keep the typedefs as-is) */
+#ifndef ACPI_USE_SYSTEM_INTTYPES
 
-typedef unsigned int UINT32;
-typedef int INT32;
+typedef unsigned int u32;
+typedef int s32;
 
-/*! [End] no source code translation !*/
+#endif				/* ACPI_USE_SYSTEM_INTTYPES */
 
 typedef s32 acpi_native_int;
 
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index b402eb67af83..e863dd5c4e04 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index e077ce6c38ca..a476b9118b49 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 008aa287c7a9..93c55ed7c53d 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2013, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,14 @@
 
 #ifdef __KERNEL__
 
+#define ACPI_USE_SYSTEM_INTTYPES
+
+/* Compile for reduced hardware mode only with this kernel config */
+
+#ifdef CONFIG_ACPI_REDUCED_HARDWARE_ONLY
+#define ACPI_REDUCED_HARDWARE 1
+#endif
+
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
@@ -83,6 +91,16 @@
 #include <ctype.h>
 #include <unistd.h>
 
+/* Disable kernel specific declarators */
+
+#ifndef __init
+#define __init
+#endif
+
+#ifndef __iomem
+#define __iomem
+#endif
+
 /* Host-dependent types and defines for user-space ACPICA */
 
 #define ACPI_FLUSH_CPU_CACHE()
diff --git a/include/asm-generic/bitops/const_hweight.h b/include/asm-generic/bitops/const_hweight.h
index fa2a50b7ee66..0a7e06623470 100644
--- a/include/asm-generic/bitops/const_hweight.h
+++ b/include/asm-generic/bitops/const_hweight.h
@@ -5,14 +5,15 @@
  * Compile time versions of __arch_hweightN()
  */
 #define __const_hweight8(w)		\
-      (	(!!((w) & (1ULL << 0))) +	\
-	(!!((w) & (1ULL << 1))) +	\
-	(!!((w) & (1ULL << 2))) +	\
-	(!!((w) & (1ULL << 3))) +	\
-	(!!((w) & (1ULL << 4))) +	\
-	(!!((w) & (1ULL << 5))) +	\
-	(!!((w) & (1ULL << 6))) +	\
-	(!!((w) & (1ULL << 7)))	)
+	((unsigned int)			\
+	 ((!!((w) & (1ULL << 0))) +	\
+	  (!!((w) & (1ULL << 1))) +	\
+	  (!!((w) & (1ULL << 2))) +	\
+	  (!!((w) & (1ULL << 3))) +	\
+	  (!!((w) & (1ULL << 4))) +	\
+	  (!!((w) & (1ULL << 5))) +	\
+	  (!!((w) & (1ULL << 6))) +	\
+	  (!!((w) & (1ULL << 7)))))
 
 #define __const_hweight16(w) (__const_hweight8(w)  + __const_hweight8((w)  >> 8 ))
 #define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 7d10f962aa13..653c44a90b82 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -51,10 +51,6 @@ struct bug_entry {
 } while (0)
 #endif
 
-#ifndef HAVE_ARCH_BUG_ON
-#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
-#endif
-
 /*
  * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
  * significant issues that need prompt attention if they should ever
@@ -106,33 +102,6 @@ extern void warn_slowpath_null(const char *file, const int line);
 	unlikely(__ret_warn_on);					\
 })
 
-#else /* !CONFIG_BUG */
-#ifndef HAVE_ARCH_BUG
-#define BUG() do {} while(0)
-#endif
-
-#ifndef HAVE_ARCH_BUG_ON
-#define BUG_ON(condition) do { if (condition) ; } while(0)
-#endif
-
-#ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) ({						\
-	int __ret_warn_on = !!(condition);				\
-	unlikely(__ret_warn_on);					\
-})
-#endif
-
-#ifndef WARN
-#define WARN(condition, format...) ({					\
-	int __ret_warn_on = !!(condition);				\
-	unlikely(__ret_warn_on);					\
-})
-#endif
-
-#define WARN_TAINT(condition, taint, format...) WARN_ON(condition)
-
-#endif
-
 #define WARN_ON_ONCE(condition)	({				\
 	static bool __section(.data.unlikely) __warned;		\
 	int __ret_warn_once = !!(condition);			\
@@ -163,6 +132,37 @@ extern void warn_slowpath_null(const char *file, const int line);
 	unlikely(__ret_warn_once);				\
 })
 
+#else /* !CONFIG_BUG */
+#ifndef HAVE_ARCH_BUG
+#define BUG() do {} while (0)
+#endif
+
+#ifndef HAVE_ARCH_WARN_ON
+#define WARN_ON(condition) ({						\
+	int __ret_warn_on = !!(condition);				\
+	unlikely(__ret_warn_on);					\
+})
+#endif
+
+#ifndef WARN
+#define WARN(condition, format...) ({					\
+	int __ret_warn_on = !!(condition);				\
+	no_printk(format);						\
+	unlikely(__ret_warn_on);					\
+})
+#endif
+
+#define WARN_ON_ONCE(condition) WARN_ON(condition)
+#define WARN_ONCE(condition, format...) WARN(condition, format)
+#define WARN_TAINT(condition, taint, format...) WARN(condition, format)
+#define WARN_TAINT_ONCE(condition, taint, format...) WARN(condition, format)
+
+#endif
+
+#ifndef HAVE_ARCH_BUG_ON
+#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
+#endif
+
 /*
  * WARN_ON_SMP() is for cases that the warning is either
  * meaningless for !SMP or may even cause failures.
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a5f56a0213a7..23e364538ab5 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -69,7 +69,7 @@ static inline int gpio_direction_input(unsigned gpio)
 }
 static inline int gpio_direction_output(unsigned gpio, int value)
 {
-	return gpiod_direction_output(gpio_to_desc(gpio), value);
+	return gpiod_direction_output_raw(gpio_to_desc(gpio), value);
 }
 
 static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index d5afe96adba6..975e1cc75edb 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -327,7 +327,7 @@ static inline void iounmap(void __iomem *addr)
 }
 #endif /* CONFIG_MMU */
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 #ifndef CONFIG_GENERIC_IOMAP
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
@@ -341,7 +341,7 @@ static inline void ioport_unmap(void __iomem *p)
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *p);
 #endif /* CONFIG_GENERIC_IOMAP */
-#endif /* CONFIG_HAS_IOPORT */
+#endif /* CONFIG_HAS_IOPORT_MAP */
 
 #ifndef xlate_dev_kmem_ptr
 #define xlate_dev_kmem_ptr(p)	p
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index 6afd7d6a9899..1b41011643a5 100644
--- a/include/asm-generic/iomap.h
+++ b/include/asm-generic/iomap.h
@@ -56,7 +56,7 @@ extern void iowrite8_rep(void __iomem *port, const void *buf, unsigned long coun
 extern void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
 extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
 
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 /* Create a virtual mapping cookie for an IO port range */
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *);
diff --git a/include/asm-generic/mcs_spinlock.h b/include/asm-generic/mcs_spinlock.h
new file mode 100644
index 000000000000..10cd4ffc6ba2
--- /dev/null
+++ b/include/asm-generic/mcs_spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_MCS_SPINLOCK_H
+#define __ASM_MCS_SPINLOCK_H
+
+/*
+ * Architectures can define their own:
+ *
+ *   arch_mcs_spin_lock_contended(l)
+ *   arch_mcs_spin_unlock_contended(l)
+ *
+ * See kernel/locking/mcs_spinlock.c.
+ */
+
+#endif /* __ASM_MCS_SPINLOCK_H */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 34c7bdc06014..1ec08c198b66 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -193,6 +193,19 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
 }
 #endif
 
+#ifndef __HAVE_ARCH_PTE_UNUSED
+/*
+ * Some architectures provide facilities to virtualization guests
+ * so that they can flag allocated pages as unused. This allows the
+ * host to transparently reclaim unused pages. This function returns
+ * whether the pte's page is unused.
+ */
+static inline int pte_unused(pte_t pte)
+{
+	return 0;
+}
+#endif
+
 #ifndef __HAVE_ARCH_PMD_SAME
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bc2121fa9132..bd02ca7a1d55 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -167,6 +167,15 @@
 #define CLK_OF_TABLES()
 #endif
 
+#ifdef CONFIG_SMP
+#define CPU_METHOD_OF_TABLES() . = ALIGN(8);				    \
+			   VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \
+			   *(__cpu_method_of_table)			    \
+			   VMLINUX_SYMBOL(__cpu_method_of_table_end) = .;
+#else
+#define CPU_METHOD_OF_TABLES()
+#endif
+
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
 	VMLINUX_SYMBOL(__dtb_start) = .;				\
@@ -491,6 +500,7 @@
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	CLKSRC_OF_TABLES()						\
+	CPU_METHOD_OF_TABLES()						\
 	KERNEL_DTB()							\
 	IRQCHIP_OF_MATCH_TABLE()
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8f3dee097579..f7646548660d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -994,6 +994,7 @@ extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
 extern const char *drm_get_connector_name(const struct drm_connector *connector);
 extern const char *drm_get_connector_status_name(enum drm_connector_status status);
+extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
 extern const char *drm_get_dpms_name(int val);
 extern const char *drm_get_dvi_i_subconnector_name(int val);
 extern const char *drm_get_dvi_i_select_name(int val);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 1d09050a8c00..42947566e755 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -279,11 +279,21 @@
 
 #define DP_TEST_PATTERN			    0x221
 
+#define DP_TEST_CRC_R_CR		    0x240
+#define DP_TEST_CRC_G_Y			    0x242
+#define DP_TEST_CRC_B_CB		    0x244
+
+#define DP_TEST_SINK_MISC		    0x246
+#define DP_TEST_CRC_SUPPORTED		    (1 << 5)
+
 #define DP_TEST_RESPONSE		    0x260
 # define DP_TEST_ACK			    (1 << 0)
 # define DP_TEST_NAK			    (1 << 1)
 # define DP_TEST_EDID_CHECKSUM_WRITE	    (1 << 2)
 
+#define DP_TEST_SINK			    0x270
+#define DP_TEST_SINK_START	    (1 << 0)
+
 #define DP_SOURCE_OUI			    0x300
 #define DP_SINK_OUI			    0x400
 #define DP_BRANCH_OUI			    0x500
@@ -291,6 +301,7 @@
 #define DP_SET_POWER                        0x600
 # define DP_SET_POWER_D0                    0x1
 # define DP_SET_POWER_D3                    0x2
+# define DP_SET_POWER_MASK                  0x3
 
 #define DP_PSR_ERROR_STATUS                 0x2006  /* XXX 1.2? */
 # define DP_PSR_LINK_CRC_ERROR              (1 << 0)
@@ -398,4 +409,114 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 		(dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP);
 }
 
+/*
+ * DisplayPort AUX channel
+ */
+
+/**
+ * struct drm_dp_aux_msg - DisplayPort AUX channel transaction
+ * @address: address of the (first) register to access
+ * @request: contains the type of transaction (see DP_AUX_* macros)
+ * @reply: upon completion, contains the reply type of the transaction
+ * @buffer: pointer to a transmission or reception buffer
+ * @size: size of @buffer
+ */
+struct drm_dp_aux_msg {
+	unsigned int address;
+	u8 request;
+	u8 reply;
+	void *buffer;
+	size_t size;
+};
+
+/**
+ * struct drm_dp_aux - DisplayPort AUX channel
+ * @ddc: I2C adapter that can be used for I2C-over-AUX communication
+ * @dev: pointer to struct device that is the parent for this AUX channel
+ * @transfer: transfers a message representing a single AUX transaction
+ *
+ * The .dev field should be set to a pointer to the device that implements
+ * the AUX channel.
+ *
+ * Drivers provide a hardware-specific implementation of how transactions
+ * are executed via the .transfer() function. A pointer to a drm_dp_aux_msg
+ * structure describing the transaction is passed into this function. Upon
+ * success, the implementation should return the number of payload bytes
+ * that were transferred, or a negative error-code on failure. Helpers
+ * propagate errors from the .transfer() function, with the exception of
+ * the -EBUSY error, which causes a transaction to be retried. On a short,
+ * helpers will return -EPROTO to make it simpler to check for failure.
+ *
+ * An AUX channel can also be used to transport I2C messages to a sink. A
+ * typical application of that is to access an EDID that's present in the
+ * sink device. The .transfer() function can also be used to execute such
+ * transactions. The drm_dp_aux_register_i2c_bus() function registers an
+ * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
+ * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
+ */
+struct drm_dp_aux {
+	struct i2c_adapter ddc;
+	struct device *dev;
+
+	ssize_t (*transfer)(struct drm_dp_aux *aux,
+			    struct drm_dp_aux_msg *msg);
+};
+
+ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
+			 void *buffer, size_t size);
+ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
+			  void *buffer, size_t size);
+
+/**
+ * drm_dp_dpcd_readb() - read a single byte from the DPCD
+ * @aux: DisplayPort AUX channel
+ * @offset: address of the register to read
+ * @valuep: location where the value of the register will be stored
+ *
+ * Returns the number of bytes transferred (1) on success, or a negative
+ * error code on failure.
+ */
+static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux,
+					unsigned int offset, u8 *valuep)
+{
+	return drm_dp_dpcd_read(aux, offset, valuep, 1);
+}
+
+/**
+ * drm_dp_dpcd_writeb() - write a single byte to the DPCD
+ * @aux: DisplayPort AUX channel
+ * @offset: address of the register to write
+ * @value: value to write to the register
+ *
+ * Returns the number of bytes transferred (1) on success, or a negative
+ * error code on failure.
+ */
+static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux,
+					 unsigned int offset, u8 value)
+{
+	return drm_dp_dpcd_write(aux, offset, &value, 1);
+}
+
+int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
+				 u8 status[DP_LINK_STATUS_SIZE]);
+
+/*
+ * DisplayPort link
+ */
+#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
+
+struct drm_dp_link {
+	unsigned char revision;
+	unsigned int rate;
+	unsigned int num_lanes;
+	unsigned long capabilities;
+};
+
+int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
+int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link);
+int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link);
+
+int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux);
+void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux);
+
 #endif /* _DRM_DP_HELPER_H_ */
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 471f276ce8f7..6e622f7d481d 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -55,7 +55,7 @@ struct drm_fb_helper_surface_size {
  *             save the current lut when force-restoring the fbdev for e.g.
  *             kdbg.
  * @fb_probe: Driver callback to allocate and initialize the fbdev info
- *            structure. Futhermore it also needs to allocate the drm
+ *            structure. Furthermore it also needs to allocate the drm
  *            framebuffer used to back the fbdev.
  * @initial_config: Setup an initial fbdev display configuration
  *
@@ -121,5 +121,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
 int drm_fb_helper_debug_enter(struct fb_info *info);
 int drm_fb_helper_debug_leave(struct fb_info *info);
+struct drm_display_mode *
+drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
+			int width, int height);
+struct drm_display_mode *
+drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
+		      int width, int height);
 
 #endif
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 97d5497debc1..595f85c392ac 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -56,6 +56,12 @@ extern bool i915_gpu_turbo_disable(void);
 
 #define I830_GMCH_CTRL			0x52
 
+#define I830_GMCH_GMS_MASK		0x70
+#define I830_GMCH_GMS_LOCAL		0x10
+#define I830_GMCH_GMS_STOLEN_512	0x20
+#define I830_GMCH_GMS_STOLEN_1024	0x30
+#define I830_GMCH_GMS_STOLEN_8192	0x40
+
 #define I855_GMCH_GMS_MASK		0xF0
 #define I855_GMCH_GMS_STOLEN_0M		0x0
 #define I855_GMCH_GMS_STOLEN_1M		(0x1 << 4)
@@ -72,4 +78,18 @@ extern bool i915_gpu_turbo_disable(void);
 #define INTEL_GMCH_GMS_STOLEN_224M	(0xc << 4)
 #define INTEL_GMCH_GMS_STOLEN_352M	(0xd << 4)
 
+#define I830_DRB3		0x63
+#define I85X_DRB3		0x43
+#define I865_TOUD		0xc4
+
+#define I830_ESMRAMC		0x91
+#define I845_ESMRAMC		0x9e
+#define I85X_ESMRAMC		0x61
+#define    TSEG_ENABLE		(1 << 0)
+#define    I830_TSEG_SIZE_512K	(0 << 1)
+#define    I830_TSEG_SIZE_1M	(1 << 1)
+#define    I845_TSEG_SIZE_MASK	(3 << 1)
+#define    I845_TSEG_SIZE_512K	(2 << 1)
+#define    I845_TSEG_SIZE_1M	(3 << 1)
+
 #endif				/* _I915_DRM_H_ */
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
 #define HI3620_MMC_CLK3		217
 #define HI3620_MCU_CLK		218
 
+#define HI3620_SD_CIUCLK	0
+#define HI3620_MMC_CIUCLK1	1
+#define HI3620_MMC_CIUCLK2	2
+#define HI3620_MMC_CIUCLK3	3
+
 #define HI3620_NR_CLKS		219
 
 #endif	/* __DTS_HI3620_CLOCK_H */
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h
index 859e9be511d9..6548a5fbcf4a 100644
--- a/include/dt-bindings/clock/r8a7790-clock.h
+++ b/include/dt-bindings/clock/r8a7790-clock.h
@@ -46,8 +46,8 @@
 #define R8A7790_CLK_MSIOF1		8
 #define R8A7790_CLK_MSIOF3		15
 #define R8A7790_CLK_SCIFB2		16
-#define R8A7790_CLK_SYS_DMAC0		18
-#define R8A7790_CLK_SYS_DMAC1		19
+#define R8A7790_CLK_SYS_DMAC1		18
+#define R8A7790_CLK_SYS_DMAC0		19
 
 /* MSTP3 */
 #define R8A7790_CLK_TPU0		4
diff --git a/include/dt-bindings/clock/s3c2412.h b/include/dt-bindings/clock/s3c2412.h
new file mode 100644
index 000000000000..aac1dcfda81c
--- /dev/null
+++ b/include/dt-bindings/clock/s3c2412.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 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.
+ *
+ * Device Tree binding constants clock controllers of Samsung S3C2412.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H
+#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H
+
+/*
+ * Let each exported clock get a unique index, which is used on DT-enabled
+ * platforms to lookup the clock from a clock specifier. These indices are
+ * therefore considered an ABI and so must not be changed. This implies
+ * that new clocks should be added either in free spaces between clock groups
+ * or at the end.
+ */
+
+/* Core clocks. */
+
+/* id 1 is reserved */
+#define MPLL			2
+#define UPLL			3
+#define MDIVCLK			4
+#define MSYSCLK			5
+#define USYSCLK			6
+#define HCLK			7
+#define PCLK			8
+#define ARMDIV			9
+#define ARMCLK			10
+
+
+/* Special clocks */
+#define SCLK_CAM		16
+#define SCLK_UART		17
+#define SCLK_I2S		18
+#define SCLK_USBD		19
+#define SCLK_USBH		20
+
+/* pclk-gates */
+#define PCLK_WDT		32
+#define PCLK_SPI		33
+#define PCLK_I2S		34
+#define PCLK_I2C		35
+#define PCLK_ADC		36
+#define PCLK_RTC		37
+#define PCLK_GPIO		38
+#define PCLK_UART2		39
+#define PCLK_UART1		40
+#define PCLK_UART0		41
+#define PCLK_SDI		42
+#define PCLK_PWM		43
+#define PCLK_USBD		44
+
+/* hclk-gates */
+#define HCLK_HALF		48
+#define HCLK_X2			49
+#define HCLK_SDRAM		50
+#define HCLK_USBH		51
+#define HCLK_LCD		52
+#define HCLK_NAND		53
+#define HCLK_DMA3		54
+#define HCLK_DMA2		55
+#define HCLK_DMA1		56
+#define HCLK_DMA0		57
+
+/* Total number of clocks. */
+#define NR_CLKS			(HCLK_DMA0 + 1)
+
+#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H */
diff --git a/include/dt-bindings/clock/s3c2443.h b/include/dt-bindings/clock/s3c2443.h
new file mode 100644
index 000000000000..37e66b054d64
--- /dev/null
+++ b/include/dt-bindings/clock/s3c2443.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 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.
+ *
+ * Device Tree binding constants clock controllers of Samsung S3C2443 and later.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H
+#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H
+
+/*
+ * Let each exported clock get a unique index, which is used on DT-enabled
+ * platforms to lookup the clock from a clock specifier. These indices are
+ * therefore considered an ABI and so must not be changed. This implies
+ * that new clocks should be added either in free spaces between clock groups
+ * or at the end.
+ */
+
+/* Core clocks. */
+#define MSYSCLK			1
+#define ESYSCLK			2
+#define ARMDIV			3
+#define ARMCLK			4
+#define HCLK			5
+#define PCLK			6
+
+/* Special clocks */
+#define SCLK_HSSPI0		16
+#define SCLK_FIMD		17
+#define SCLK_I2S0		18
+#define SCLK_I2S1		19
+#define SCLK_HSMMC1		20
+#define SCLK_HSMMC_EXT		21
+#define SCLK_CAM		22
+#define SCLK_UART		23
+#define SCLK_USBH		24
+
+/* Muxes */
+#define MUX_HSSPI0		32
+#define MUX_HSSPI1		33
+#define MUX_HSMMC0		34
+#define MUX_HSMMC1		35
+
+/* hclk-gates */
+#define HCLK_DMA0		48
+#define HCLK_DMA1		49
+#define HCLK_DMA2		50
+#define HCLK_DMA3		51
+#define HCLK_DMA4		52
+#define HCLK_DMA5		53
+#define HCLK_DMA6		54
+#define HCLK_DMA7		55
+#define HCLK_CAM		56
+#define HCLK_LCD		57
+#define HCLK_USBH		58
+#define HCLK_USBD		59
+#define HCLK_IROM		60
+#define HCLK_HSMMC0		61
+#define HCLK_HSMMC1		62
+#define HCLK_CFC		63
+#define HCLK_SSMC		64
+#define HCLK_DRAM		65
+#define HCLK_2D			66
+
+/* pclk-gates */
+#define PCLK_UART0		72
+#define PCLK_UART1		73
+#define PCLK_UART2		74
+#define PCLK_UART3		75
+#define PCLK_I2C0		76
+#define PCLK_SDI		77
+#define PCLK_SPI0		78
+#define PCLK_ADC		79
+#define PCLK_AC97		80
+#define PCLK_I2S0		81
+#define PCLK_PWM		82
+#define PCLK_WDT		83
+#define PCLK_RTC		84
+#define PCLK_GPIO		85
+#define PCLK_SPI1		86
+#define PCLK_CHIPID		87
+#define PCLK_I2C1		88
+#define PCLK_I2S1		89
+#define PCLK_PCM		90
+
+/* Total number of clocks. */
+#define NR_CLKS			(PCLK_PCM + 1)
+
+#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */
diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h
index a1116a3b54ef..8c1603b10665 100644
--- a/include/dt-bindings/clock/tegra124-car.h
+++ b/include/dt-bindings/clock/tegra124-car.h
@@ -36,10 +36,10 @@
 #define TEGRA124_CLK_PWM 17
 #define TEGRA124_CLK_I2S2 18
 /* 20 (register bit affects vi and vi_sensor) */
-#define TEGRA124_CLK_GR_2D 21
+/* 21 */
 #define TEGRA124_CLK_USBD 22
 #define TEGRA124_CLK_ISP 23
-#define TEGRA124_CLK_GR_3D 24
+/* 26 */
 /* 25 */
 #define TEGRA124_CLK_DISP2 26
 #define TEGRA124_CLK_DISP1 27
diff --git a/include/dt-bindings/spmi/spmi.h b/include/dt-bindings/spmi/spmi.h
new file mode 100644
index 000000000000..d11e1e543871
--- /dev/null
+++ b/include/dt-bindings/spmi/spmi.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2013, The Linux Foundation. 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 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.
+ */
+#ifndef __DT_BINDINGS_SPMI_H
+#define __DT_BINDINGS_SPMI_H
+
+#define SPMI_USID	0
+#define SPMI_GSID	1
+
+#endif
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 1151a1dcfe41..7a8f2cd66c8b 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -108,6 +108,10 @@ static inline void acpi_initrd_override(void *data, size_t size)
 }
 #endif
 
+#define BAD_MADT_ENTRY(entry, end) (					    \
+		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
+		((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
+
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -259,14 +263,9 @@ extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
 extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
-int acpi_get_pxm(acpi_handle handle);
-int acpi_get_node(acpi_handle *handle);
+int acpi_get_node(acpi_handle handle);
 #else
-static inline int acpi_get_pxm(acpi_handle handle)
-{
-	return 0;
-}
-static inline int acpi_get_node(acpi_handle *handle)
+static inline int acpi_get_node(acpi_handle handle)
 {
 	return 0;
 }
diff --git a/include/linux/acpi_dma.h b/include/linux/acpi_dma.h
index fb0298082916..329436d38e66 100644
--- a/include/linux/acpi_dma.h
+++ b/include/linux/acpi_dma.h
@@ -16,6 +16,7 @@
 
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/dmaengine.h>
 
 /**
@@ -103,12 +104,12 @@ static inline void devm_acpi_dma_controller_free(struct device *dev)
 static inline struct dma_chan *acpi_dma_request_slave_chan_by_index(
 		struct device *dev, size_t index)
 {
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 static inline struct dma_chan *acpi_dma_request_slave_chan_by_name(
 		struct device *dev, const char *name)
 {
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 
 #define acpi_dma_simple_xlate	NULL
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 73a25005d88a..1f16d502600c 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -19,15 +19,37 @@
 
 struct device;
 struct ata_port_info;
+struct ahci_host_priv;
+struct platform_device;
 
+/*
+ * Note ahci_platform_data is deprecated, it is only kept around for use
+ * by the old da850 and spear13xx ahci code.
+ * New drivers should instead declare their own platform_driver struct, and
+ * use ahci_platform* functions in their own probe, suspend and resume methods.
+ */
 struct ahci_platform_data {
 	int (*init)(struct device *dev, void __iomem *addr);
 	void (*exit)(struct device *dev);
 	int (*suspend)(struct device *dev);
 	int (*resume)(struct device *dev);
-	const struct ata_port_info *ata_port_info;
-	unsigned int force_port_map;
-	unsigned int mask_port_map;
 };
 
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
+struct ahci_host_priv *ahci_platform_get_resources(
+	struct platform_device *pdev);
+int ahci_platform_init_host(struct platform_device *pdev,
+			    struct ahci_host_priv *hpriv,
+			    const struct ata_port_info *pi_template,
+			    unsigned int force_port_map,
+			    unsigned int mask_port_map);
+
+int ahci_platform_suspend_host(struct device *dev);
+int ahci_platform_resume_host(struct device *dev);
+int ahci_platform_suspend(struct device *dev);
+int ahci_platform_resume(struct device *dev);
+
 #endif /* _AHCI_PLATFORM_H */
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 66a0e5384edd..571a12ebb018 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -18,6 +18,7 @@ struct ssc_device {
 	struct clk		*clk;
 	int			user;
 	int			irq;
+	bool			clk_from_rk_pin;
 };
 
 struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 5f9cd963213d..72647429adf6 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -9,6 +9,7 @@
 #define _LINUX_BACKLIGHT_H
 
 #include <linux/device.h>
+#include <linux/fb.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 
@@ -104,6 +105,11 @@ struct backlight_device {
 	struct list_head entry;
 
 	struct device dev;
+
+	/* Multiple framebuffers may share one backlight device */
+	bool fb_bl_on[FB_MAX];
+
+	int use_count;
 };
 
 static inline void backlight_update_status(struct backlight_device *bd)
diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h
index d8a97ec0e2b8..0e97856b2cff 100644
--- a/include/linux/basic_mmio_gpio.h
+++ b/include/linux/basic_mmio_gpio.h
@@ -19,6 +19,7 @@
 #include <linux/spinlock_types.h>
 
 struct bgpio_pdata {
+	const char *label;
 	int base;
 	int ngpio;
 };
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4afa4f8f6090..1e1fa3f93d5f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -99,6 +99,7 @@ struct request {
 	union {
 		struct call_single_data csd;
 		struct work_struct mq_flush_work;
+		unsigned long fifo_time;
 	};
 
 	struct request_queue *q;
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 677b4f01b2d0..6f76277baf39 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -13,10 +13,17 @@
 #define PHY_ID_BCM5461			0x002060c0
 #define PHY_ID_BCM57780			0x03625d90
 
+#define PHY_ID_BCM7366			0x600d8490
+#define PHY_ID_BCM7439			0x600d8480
+#define PHY_ID_BCM7445			0x600d8510
+#define PHY_ID_BCM7XXX_28		0x600d8400
+
 #define PHY_BCM_OUI_MASK		0xfffffc00
 #define PHY_BCM_OUI_1			0x00206000
 #define PHY_BCM_OUI_2			0x0143bc00
 #define PHY_BCM_OUI_3			0x03625c00
+#define PHY_BCM_OUI_4			0x600d0000
+#define PHY_BCM_OUI_5			0x03625e00
 
 
 #define PHY_BCM_FLAGS_MODE_COPPER	0x00000001
@@ -31,6 +38,59 @@
 #define PHY_BRCM_EXT_IBND_TX_ENABLE	0x00002000
 #define PHY_BRCM_CLEAR_RGMII_MODE	0x00004000
 #define PHY_BRCM_DIS_TXCRXC_NOENRGY	0x00008000
+/* Broadcom BCM7xxx specific workarounds */
+#define PHY_BRCM_100MBPS_WAR		0x00010000
 #define PHY_BCM_FLAGS_VALID		0x80000000
 
+/* Broadcom BCM54XX register definitions, common to most Broadcom PHYs */
+#define MII_BCM54XX_ECR		0x10	/* BCM54xx extended control register */
+#define MII_BCM54XX_ECR_IM	0x1000	/* Interrupt mask */
+#define MII_BCM54XX_ECR_IF	0x0800	/* Interrupt force */
+
+#define MII_BCM54XX_ESR		0x11	/* BCM54xx extended status register */
+#define MII_BCM54XX_ESR_IS	0x1000	/* Interrupt status */
+
+#define MII_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
+#define MII_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
+#define MII_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
+#define MII_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
+
+#define MII_BCM54XX_AUX_CTL	0x18	/* Auxiliary control register */
+#define MII_BCM54XX_ISR		0x1a	/* BCM54xx interrupt status register */
+#define MII_BCM54XX_IMR		0x1b	/* BCM54xx interrupt mask register */
+#define MII_BCM54XX_INT_CRCERR	0x0001	/* CRC error */
+#define MII_BCM54XX_INT_LINK	0x0002	/* Link status changed */
+#define MII_BCM54XX_INT_SPEED	0x0004	/* Link speed change */
+#define MII_BCM54XX_INT_DUPLEX	0x0008	/* Duplex mode changed */
+#define MII_BCM54XX_INT_LRS	0x0010	/* Local receiver status changed */
+#define MII_BCM54XX_INT_RRS	0x0020	/* Remote receiver status changed */
+#define MII_BCM54XX_INT_SSERR	0x0040	/* Scrambler synchronization error */
+#define MII_BCM54XX_INT_UHCD	0x0080	/* Unsupported HCD negotiated */
+#define MII_BCM54XX_INT_NHCD	0x0100	/* No HCD */
+#define MII_BCM54XX_INT_NHCDL	0x0200	/* No HCD link */
+#define MII_BCM54XX_INT_ANPR	0x0400	/* Auto-negotiation page received */
+#define MII_BCM54XX_INT_LC	0x0800	/* All counters below 128 */
+#define MII_BCM54XX_INT_HC	0x1000	/* Counter above 32768 */
+#define MII_BCM54XX_INT_MDIX	0x2000	/* MDIX status change */
+#define MII_BCM54XX_INT_PSERR	0x4000	/* Pair swap error */
+
+#define MII_BCM54XX_SHD		0x1c	/* 0x1c shadow registers */
+#define MII_BCM54XX_SHD_WRITE	0x8000
+#define MII_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
+#define MII_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
+
+/*
+ * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
+ */
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
+#define MII_BCM54XX_AUXCTL_ACTL_TX_6DB		0x0400
+#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA	0x0800
+
+#define MII_BCM54XX_AUXCTL_MISC_WREN	0x8000
+#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
+#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
+
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
+
 #endif /* _LINUX_BRCMPHY_H */
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index fb0ab651a041..dc5f9026b67f 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -124,6 +124,8 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
 void can_free_echo_skb(struct net_device *dev, unsigned int idx);
 
 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
+struct sk_buff *alloc_canfd_skb(struct net_device *dev,
+				struct canfd_frame **cfd);
 struct sk_buff *alloc_can_err_skb(struct net_device *dev,
 				  struct can_frame **cf);
 
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index b941ab9f762b..ebcc9d146219 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -232,6 +232,9 @@ enum ccp_sha_type {
  * @ctx_len: length in bytes of hash value
  * @src: data to be used for this operation
  * @src_len: length in bytes of data used for this operation
+ * @opad: data to be used for final HMAC operation
+ * @opad_len: length in bytes of data used for final HMAC operation
+ * @first: indicates first SHA operation
  * @final: indicates final SHA operation
  * @msg_bits: total length of the message in bits used in final SHA operation
  *
@@ -251,6 +254,10 @@ struct ccp_sha_engine {
 	struct scatterlist *src;
 	u64 src_len;		/* In bytes */
 
+	struct scatterlist *opad;
+	u32 opad_len;		/* In bytes */
+
+	u32 first;		/* Indicates first sha cmd */
 	u32 final;		/* Indicates final sha cmd */
 	u64 msg_bits;		/* Message length in bits required for
 				 * final sha cmd */
diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h
index 49ff69f0746b..8c8b3cefc28b 100644
--- a/include/linux/ceph/osdmap.h
+++ b/include/linux/ceph/osdmap.h
@@ -84,6 +84,9 @@ struct ceph_osdmap {
 	/* the CRUSH map specifies the mapping of placement groups to
 	 * the list of osds that store+replicate them. */
 	struct crush_map *crush;
+
+	struct mutex crush_scratch_mutex;
+	int crush_scratch_ary[CEPH_PG_MAX_SIZE * 3];
 };
 
 static inline void ceph_oid_set_name(struct ceph_object_id *oid,
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 9450f025fe0c..acbb9a4cb6e9 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -14,14 +14,13 @@
 #include <linux/rcupdate.h>
 #include <linux/rculist.h>
 #include <linux/cgroupstats.h>
-#include <linux/prio_heap.h>
 #include <linux/rwsem.h>
 #include <linux/idr.h>
 #include <linux/workqueue.h>
-#include <linux/xattr.h>
 #include <linux/fs.h>
 #include <linux/percpu-refcount.h>
 #include <linux/seq_file.h>
+#include <linux/kernfs.h>
 
 #ifdef CONFIG_CGROUPS
 
@@ -37,28 +36,13 @@ extern void cgroup_post_fork(struct task_struct *p);
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
 				struct dentry *dentry);
-extern int cgroup_load_subsys(struct cgroup_subsys *ss);
-extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
 extern int proc_cgroup_show(struct seq_file *, void *);
 
-/*
- * Define the enumeration of all cgroup subsystems.
- *
- * We define ids for builtin subsystems and then modular ones.
- */
-#define SUBSYS(_x) _x ## _subsys_id,
+/* define the enumeration of all cgroup subsystems */
+#define SUBSYS(_x) _x ## _cgrp_id,
 enum cgroup_subsys_id {
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
-#include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
-	CGROUP_BUILTIN_SUBSYS_COUNT,
-
-	__CGROUP_SUBSYS_TEMP_PLACEHOLDER = CGROUP_BUILTIN_SUBSYS_COUNT - 1,
-
-#define IS_SUBSYS_ENABLED(option) IS_MODULE(option)
 #include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
 	CGROUP_SUBSYS_COUNT,
 };
 #undef SUBSYS
@@ -153,11 +137,6 @@ enum {
 	CGRP_SANE_BEHAVIOR,
 };
 
-struct cgroup_name {
-	struct rcu_head rcu_head;
-	char name[];
-};
-
 struct cgroup {
 	unsigned long flags;		/* "unsigned long" so bitops work */
 
@@ -174,16 +153,17 @@ struct cgroup {
 	/* the number of attached css's */
 	int nr_css;
 
+	atomic_t refcnt;
+
 	/*
 	 * We link our 'sibling' struct into our parent's 'children'.
 	 * Our children link their 'sibling' into our 'children'.
 	 */
 	struct list_head sibling;	/* my parent's children */
 	struct list_head children;	/* my children */
-	struct list_head files;		/* my files */
 
 	struct cgroup *parent;		/* my parent */
-	struct dentry *dentry;		/* cgroup fs entry, RCU protected */
+	struct kernfs_node *kn;		/* cgroup kernfs entry */
 
 	/*
 	 * Monotonically increasing unique serial number which defines a
@@ -193,19 +173,6 @@ struct cgroup {
 	 */
 	u64 serial_nr;
 
-	/*
-	 * This is a copy of dentry->d_name, and it's needed because
-	 * we can't use dentry->d_name in cgroup_path().
-	 *
-	 * You must acquire rcu_read_lock() to access cgrp->name, and
-	 * the only place that can change it is rename(), which is
-	 * protected by parent dir's i_mutex.
-	 *
-	 * Normally you should use cgroup_name() wrapper rather than
-	 * access it directly.
-	 */
-	struct cgroup_name __rcu *name;
-
 	/* Private pointers for each registered subsystem */
 	struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
 
@@ -237,9 +204,6 @@ struct cgroup {
 	/* For css percpu_ref killing and RCU-protected deletion */
 	struct rcu_head rcu_head;
 	struct work_struct destroy_work;
-
-	/* directory xattrs */
-	struct simple_xattrs xattrs;
 };
 
 #define MAX_CGROUP_ROOT_NAMELEN 64
@@ -262,8 +226,8 @@ enum {
 	 *
 	 * The followings are the behaviors currently affected this flag.
 	 *
-	 * - Mount options "noprefix" and "clone_children" are disallowed.
-	 *   Also, cgroupfs file cgroup.clone_children is not created.
+	 * - Mount options "noprefix", "xattr", "clone_children",
+	 *   "release_agent" and "name" are disallowed.
 	 *
 	 * - When mounting an existing superblock, mount options should
 	 *   match.
@@ -281,6 +245,8 @@ enum {
 	 * - "release_agent" and "notify_on_release" are removed.
 	 *   Replacement notification mechanism will be implemented.
 	 *
+	 * - "cgroup.clone_children" is removed.
+	 *
 	 * - cpuset: tasks will be kept in empty cpusets when hotplug happens
 	 *   and take masks of ancestors with non-empty cpus/mems, instead of
 	 *   being moved to an ancestor.
@@ -300,17 +266,15 @@ enum {
 
 	/* mount options live below bit 16 */
 	CGRP_ROOT_OPTION_MASK	= (1 << 16) - 1,
-
-	CGRP_ROOT_SUBSYS_BOUND	= (1 << 16), /* subsystems finished binding */
 };
 
 /*
  * A cgroupfs_root represents the root of a cgroup hierarchy, and may be
- * associated with a superblock to form an active hierarchy.  This is
+ * associated with a kernfs_root to form an active hierarchy.  This is
  * internal to cgroup core.  Don't access directly from controllers.
  */
 struct cgroupfs_root {
-	struct super_block *sb;
+	struct kernfs_root *kf_root;
 
 	/* The bitmask of subsystems attached to this hierarchy */
 	unsigned long subsys_mask;
@@ -318,11 +282,11 @@ struct cgroupfs_root {
 	/* Unique id for this hierarchy. */
 	int hierarchy_id;
 
-	/* The root cgroup for this hierarchy */
+	/* The root cgroup.  Root is destroyed on its release. */
 	struct cgroup top_cgroup;
 
-	/* Tracks how many cgroups are currently defined in hierarchy.*/
-	int number_of_cgroups;
+	/* Number of cgroups in the hierarchy, used only for /proc/cgroups */
+	atomic_t nr_cgrps;
 
 	/* A list running through the active hierarchies */
 	struct list_head root_list;
@@ -360,10 +324,14 @@ struct css_set {
 	struct hlist_node hlist;
 
 	/*
-	 * List running through all tasks using this cgroup
-	 * group. Protected by css_set_lock
+	 * Lists running through all tasks using this cgroup group.
+	 * mg_tasks lists tasks which belong to this cset but are in the
+	 * process of being migrated out or in.  Protected by
+	 * css_set_rwsem, but, during migration, once tasks are moved to
+	 * mg_tasks, it can be read safely while holding cgroup_mutex.
 	 */
 	struct list_head tasks;
+	struct list_head mg_tasks;
 
 	/*
 	 * List of cgrp_cset_links pointing at cgroups referenced from this
@@ -372,13 +340,29 @@ struct css_set {
 	struct list_head cgrp_links;
 
 	/*
-	 * Set of subsystem states, one for each subsystem. This array
-	 * is immutable after creation apart from the init_css_set
-	 * during subsystem registration (at boot time) and modular subsystem
-	 * loading/unloading.
+	 * Set of subsystem states, one for each subsystem. This array is
+	 * immutable after creation apart from the init_css_set during
+	 * subsystem registration (at boot time).
 	 */
 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
 
+	/*
+	 * List of csets participating in the on-going migration either as
+	 * source or destination.  Protected by cgroup_mutex.
+	 */
+	struct list_head mg_preload_node;
+	struct list_head mg_node;
+
+	/*
+	 * If this cset is acting as the source of migration the following
+	 * two fields are set.  mg_src_cgrp is the source cgroup of the
+	 * on-going migration and mg_dst_cset is the destination cset the
+	 * target tasks on this cset should be migrated to.  Protected by
+	 * cgroup_mutex.
+	 */
+	struct cgroup *mg_src_cgrp;
+	struct css_set *mg_dst_cset;
+
 	/* For RCU-protected deletion */
 	struct rcu_head rcu_head;
 };
@@ -416,8 +400,9 @@ struct cftype {
 	umode_t mode;
 
 	/*
-	 * If non-zero, defines the maximum length of string that can
-	 * be passed to write_string; defaults to 64
+	 * The maximum length of string, excluding trailing nul, that can
+	 * be passed to write_string.  If < PAGE_SIZE-1, PAGE_SIZE-1 is
+	 * assumed.
 	 */
 	size_t max_write_len;
 
@@ -425,10 +410,12 @@ struct cftype {
 	unsigned int flags;
 
 	/*
-	 * The subsys this file belongs to.  Initialized automatically
-	 * during registration.  NULL for cgroup core files.
+	 * Fields used for internal bookkeeping.  Initialized automatically
+	 * during registration.
 	 */
-	struct cgroup_subsys *ss;
+	struct cgroup_subsys *ss;	/* NULL for cgroup core files */
+	struct list_head node;		/* anchored at ss->cfts */
+	struct kernfs_ops *kf_ops;
 
 	/*
 	 * read_u64() is a shortcut for the common case of returning a
@@ -475,36 +462,10 @@ struct cftype {
 	 * kick type for multiplexing.
 	 */
 	int (*trigger)(struct cgroup_subsys_state *css, unsigned int event);
-};
-
-/*
- * cftype_sets describe cftypes belonging to a subsystem and are chained at
- * cgroup_subsys->cftsets.  Each cftset points to an array of cftypes
- * terminated by zero length name.
- */
-struct cftype_set {
-	struct list_head		node;	/* chained at subsys->cftsets */
-	struct cftype			*cfts;
-};
 
-/*
- * cgroupfs file entry, pointed to from leaf dentry->d_fsdata.  Don't
- * access directly.
- */
-struct cfent {
-	struct list_head		node;
-	struct dentry			*dentry;
-	struct cftype			*type;
-	struct cgroup_subsys_state	*css;
-
-	/* file xattrs */
-	struct simple_xattrs		xattrs;
-};
-
-/* seq_file->private points to the following, only ->priv is public */
-struct cgroup_open_file {
-	struct cfent			*cfe;
-	void				*priv;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lock_class_key	lockdep_key;
+#endif
 };
 
 /*
@@ -516,34 +477,79 @@ static inline bool cgroup_sane_behavior(const struct cgroup *cgrp)
 	return cgrp->root->flags & CGRP_ROOT_SANE_BEHAVIOR;
 }
 
-/* Caller should hold rcu_read_lock() */
-static inline const char *cgroup_name(const struct cgroup *cgrp)
+/* no synchronization, the result can only be used as a hint */
+static inline bool cgroup_has_tasks(struct cgroup *cgrp)
 {
-	return rcu_dereference(cgrp->name)->name;
+	return !list_empty(&cgrp->cset_links);
 }
 
-static inline struct cgroup_subsys_state *seq_css(struct seq_file *seq)
+/* returns ino associated with a cgroup, 0 indicates unmounted root */
+static inline ino_t cgroup_ino(struct cgroup *cgrp)
 {
-	struct cgroup_open_file *of = seq->private;
-	return of->cfe->css;
+	if (cgrp->kn)
+		return cgrp->kn->ino;
+	else
+		return 0;
 }
 
 static inline struct cftype *seq_cft(struct seq_file *seq)
 {
-	struct cgroup_open_file *of = seq->private;
-	return of->cfe->type;
+	struct kernfs_open_file *of = seq->private;
+
+	return of->kn->priv;
+}
+
+struct cgroup_subsys_state *seq_css(struct seq_file *seq);
+
+/*
+ * Name / path handling functions.  All are thin wrappers around the kernfs
+ * counterparts and can be called under any context.
+ */
+
+static inline int cgroup_name(struct cgroup *cgrp, char *buf, size_t buflen)
+{
+	/* dummy_top doesn't have a kn associated */
+	if (cgrp->kn)
+		return kernfs_name(cgrp->kn, buf, buflen);
+	else
+		return strlcpy(buf, "/", buflen);
+}
+
+static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
+					      size_t buflen)
+{
+	/* dummy_top doesn't have a kn associated */
+	if (cgrp->kn)
+		return kernfs_path(cgrp->kn, buf, buflen);
+	strlcpy(buf, "/", buflen);
+	return (buflen <= 2) ? NULL : buf;
+}
+
+static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
+{
+	/* dummy_top doesn't have a kn associated */
+	if (cgrp->kn)
+		pr_cont_kernfs_name(cgrp->kn);
+	else
+		pr_cont("/");
 }
 
+static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
+{
+	/* dummy_top doesn't have a kn associated */
+	if (cgrp->kn)
+		pr_cont_kernfs_path(cgrp->kn);
+	else
+		pr_cont("/");
+}
+
+char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
+
 int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_rm_cftypes(struct cftype *cfts);
 
 bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
 
-int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
-int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
-
-int cgroup_task_count(const struct cgroup *cgrp);
-
 /*
  * Control Group taskset, used to pass around set of tasks to cgroup_subsys
  * methods.
@@ -551,22 +557,15 @@ int cgroup_task_count(const struct cgroup *cgrp);
 struct cgroup_taskset;
 struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset);
 struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset);
-struct cgroup_subsys_state *cgroup_taskset_cur_css(struct cgroup_taskset *tset,
-						   int subsys_id);
-int cgroup_taskset_size(struct cgroup_taskset *tset);
 
 /**
  * cgroup_taskset_for_each - iterate cgroup_taskset
  * @task: the loop cursor
- * @skip_css: skip if task's css matches this, %NULL to iterate through all
  * @tset: taskset to iterate
  */
-#define cgroup_taskset_for_each(task, skip_css, tset)			\
+#define cgroup_taskset_for_each(task, tset)				\
 	for ((task) = cgroup_taskset_first((tset)); (task);		\
-	     (task) = cgroup_taskset_next((tset)))			\
-		if (!(skip_css) ||					\
-		    cgroup_taskset_cur_css((tset),			\
-			(skip_css)->ss->subsys_id) != (skip_css))
+	     (task) = cgroup_taskset_next((tset)))
 
 /*
  * Control Group subsystem type.
@@ -591,7 +590,6 @@ struct cgroup_subsys {
 		     struct task_struct *task);
 	void (*bind)(struct cgroup_subsys_state *root_css);
 
-	int subsys_id;
 	int disabled;
 	int early_init;
 
@@ -610,27 +608,26 @@ struct cgroup_subsys {
 	bool broken_hierarchy;
 	bool warned_broken_hierarchy;
 
+	/* the following two fields are initialized automtically during boot */
+	int id;
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
 
 	/* link to parent, protected by cgroup_lock() */
 	struct cgroupfs_root *root;
 
-	/* list of cftype_sets */
-	struct list_head cftsets;
+	/*
+	 * List of cftypes.  Each entry is the first entry of an array
+	 * terminated by zero length name.
+	 */
+	struct list_head cfts;
 
-	/* base cftypes, automatically [de]registered with subsys itself */
+	/* base cftypes, automatically registered with subsys itself */
 	struct cftype *base_cftypes;
-	struct cftype_set base_cftset;
-
-	/* should be defined only by modular subsystems */
-	struct module *module;
 };
 
-#define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
+#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
 #include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
 #undef SUBSYS
 
 /**
@@ -661,10 +658,12 @@ struct cgroup_subsys_state *css_parent(struct cgroup_subsys_state *css)
  */
 #ifdef CONFIG_PROVE_RCU
 extern struct mutex cgroup_mutex;
+extern struct rw_semaphore css_set_rwsem;
 #define task_css_set_check(task, __c)					\
 	rcu_dereference_check((task)->cgroups,				\
-		lockdep_is_held(&(task)->alloc_lock) ||			\
-		lockdep_is_held(&cgroup_mutex) || (__c))
+		lockdep_is_held(&cgroup_mutex) ||			\
+		lockdep_is_held(&css_set_rwsem) ||			\
+		((task)->flags & PF_EXITING) || (__c))
 #else
 #define task_css_set_check(task, __c)					\
 	rcu_dereference((task)->cgroups)
@@ -837,16 +836,11 @@ void css_task_iter_start(struct cgroup_subsys_state *css,
 struct task_struct *css_task_iter_next(struct css_task_iter *it);
 void css_task_iter_end(struct css_task_iter *it);
 
-int css_scan_tasks(struct cgroup_subsys_state *css,
-		   bool (*test)(struct task_struct *, void *),
-		   void (*process)(struct task_struct *, void *),
-		   void *data, struct ptr_heap *heap);
-
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
 
-struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
-					 struct cgroup_subsys *ss);
+struct cgroup_subsys_state *css_tryget_from_dir(struct dentry *dentry,
+						struct cgroup_subsys *ss);
 
 #else /* !CONFIG_CGROUPS */
 
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 7b99d717411d..768fe44e19f0 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -3,51 +3,51 @@
  *
  * DO NOT ADD ANY SUBSYSTEM WITHOUT EXPLICIT ACKS FROM CGROUP MAINTAINERS.
  */
-#if IS_SUBSYS_ENABLED(CONFIG_CPUSETS)
+#if IS_ENABLED(CONFIG_CPUSETS)
 SUBSYS(cpuset)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)
+#if IS_ENABLED(CONFIG_CGROUP_DEBUG)
 SUBSYS(debug)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_SCHED)
-SUBSYS(cpu_cgroup)
+#if IS_ENABLED(CONFIG_CGROUP_SCHED)
+SUBSYS(cpu)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_CPUACCT)
+#if IS_ENABLED(CONFIG_CGROUP_CPUACCT)
 SUBSYS(cpuacct)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_MEMCG)
-SUBSYS(mem_cgroup)
+#if IS_ENABLED(CONFIG_MEMCG)
+SUBSYS(memory)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEVICE)
+#if IS_ENABLED(CONFIG_CGROUP_DEVICE)
 SUBSYS(devices)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_FREEZER)
+#if IS_ENABLED(CONFIG_CGROUP_FREEZER)
 SUBSYS(freezer)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_CLASSID)
+#if IS_ENABLED(CONFIG_CGROUP_NET_CLASSID)
 SUBSYS(net_cls)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_BLK_CGROUP)
+#if IS_ENABLED(CONFIG_BLK_CGROUP)
 SUBSYS(blkio)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_PERF)
-SUBSYS(perf)
+#if IS_ENABLED(CONFIG_CGROUP_PERF)
+SUBSYS(perf_event)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_PRIO)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 SUBSYS(net_prio)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_HUGETLB)
+#if IS_ENABLED(CONFIG_CGROUP_HUGETLB)
 SUBSYS(hugetlb)
 #endif
 /*
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0dd91148165e..fb5e097d8f72 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -78,8 +78,22 @@ struct clk_notifier_data {
 	unsigned long		new_rate;
 };
 
+/**
+ * clk_notifier_register: register a clock rate-change notifier callback
+ * @clk: clock whose rate we are interested in
+ * @nb: notifier block with callback function pointer
+ *
+ * ProTip: debugging across notifier chains can be frustrating. Make sure that
+ * your notifier callback function prints a nice big warning in case of
+ * failure.
+ */
 int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
 
+/**
+ * clk_notifier_unregister: unregister a clock rate-change notifier callback
+ * @clk: clock whose rate we are no longer interested in
+ * @nb: notifier block which will be unregistered
+ */
 int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
 
 /**
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 092b64168d7f..4a21a872dbbd 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -245,6 +245,10 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate);
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 493aa021c7a9..2e4cb67f6e56 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -62,6 +62,11 @@ enum clock_event_mode {
 #define CLOCK_EVT_FEAT_DYNIRQ		0x000020
 #define CLOCK_EVT_FEAT_PERCPU		0x000040
 
+/*
+ * Clockevent device is based on a hrtimer for broadcast
+ */
+#define CLOCK_EVT_FEAT_HRTIMER		0x000080
+
 /**
  * struct clock_event_device - clock event device descriptor
  * @event_handler:	Assigned by the framework to be called by the low
@@ -83,6 +88,7 @@ enum clock_event_mode {
  * @name:		ptr to clock event name
  * @rating:		variable to rate clock event devices
  * @irq:		IRQ number (only for non CPU local devices)
+ * @bound_on:		Bound on CPU
  * @cpumask:		cpumask to indicate for which CPUs this device works
  * @list:		list head for the management code
  * @owner:		module reference
@@ -113,6 +119,7 @@ struct clock_event_device {
 	const char		*name;
 	int			rating;
 	int			irq;
+	int			bound_on;
 	const struct cpumask	*cpumask;
 	struct list_head	list;
 	struct module		*owner;
@@ -180,15 +187,17 @@ extern int tick_receive_broadcast(void);
 #endif
 
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void tick_setup_hrtimer_broadcast(void);
 extern int tick_check_broadcast_expired(void);
 #else
 static inline int tick_check_broadcast_expired(void) { return 0; }
+static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-extern void clockevents_notify(unsigned long reason, void *arg);
+extern int clockevents_notify(unsigned long reason, void *arg);
 #else
-static inline void clockevents_notify(unsigned long reason, void *arg) {}
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 #endif
 
 #else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
@@ -196,8 +205,9 @@ static inline void clockevents_notify(unsigned long reason, void *arg) {}
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
 
-static inline void clockevents_notify(unsigned long reason, void *arg) {}
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
+static inline void tick_setup_hrtimer_broadcast(void) {};
 
 #endif
 
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 3f448c65511b..f7d5bc0a239f 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -141,26 +141,23 @@ struct compat_sigaction {
 };
 
 /*
- * These functions operate strictly on struct compat_time*
- */
-extern int get_compat_timespec(struct timespec *,
-			       const struct compat_timespec __user *);
-extern int put_compat_timespec(const struct timespec *,
-			       struct compat_timespec __user *);
-extern int get_compat_timeval(struct timeval *,
-			      const struct compat_timeval __user *);
-extern int put_compat_timeval(const struct timeval *,
-			      struct compat_timeval __user *);
-/*
  * These functions operate on 32- or 64-bit specs depending on
- * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments and the
- * naming as compat_get/put_ rather than get/put_compat_.
+ * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
  */
 extern int compat_get_timespec(struct timespec *, const void __user *);
 extern int compat_put_timespec(const struct timespec *, void __user *);
 extern int compat_get_timeval(struct timeval *, const void __user *);
 extern int compat_put_timeval(const struct timeval *, void __user *);
 
+/*
+ * This function convert a timespec if necessary and returns a *user
+ * space* pointer.  If no conversion is necessary, it returns the
+ * initial pointer.  NULL is a legitimate argument and will always
+ * output NULL.
+ */
+extern int compat_convert_timespec(struct timespec __user **,
+				   const void __user *);
+
 struct compat_iovec {
 	compat_uptr_t	iov_base;
 	compat_size_t	iov_len;
diff --git a/include/linux/connector.h b/include/linux/connector.h
index b2b5a41b6a24..be9c4747d511 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -71,7 +71,7 @@ struct cn_dev {
 int cn_add_callback(struct cb_id *id, const char *name,
 		    void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
 void cn_del_callback(struct cb_id *);
-int cn_netlink_send(struct cn_msg *, u32, gfp_t);
+int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 group, gfp_t gfp_mask);
 
 int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
 			  struct cb_id *id,
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 03e235ad1bba..03e962e23eaf 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -46,13 +46,6 @@ extern ssize_t arch_cpu_release(const char *, size_t);
 #endif
 struct notifier_block;
 
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
-extern ssize_t arch_print_cpu_modalias(struct device *dev,
-				       struct device_attribute *attr,
-				       char *bufptr);
-#endif
-
 /*
  * CPU notifier priorities.
  */
diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h
new file mode 100644
index 000000000000..c4d4eb8ac9fe
--- /dev/null
+++ b/include/linux/cpufeature.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.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.
+ */
+
+#ifndef __LINUX_CPUFEATURE_H
+#define __LINUX_CPUFEATURE_H
+
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+
+#include <linux/mod_devicetable.h>
+#include <asm/cpufeature.h>
+
+/*
+ * Macros imported from <asm/cpufeature.h>:
+ * - cpu_feature(x)		ordinal value of feature called 'x'
+ * - cpu_have_feature(u32 n)	whether feature #n is available
+ * - MAX_CPU_FEATURES		upper bound for feature ordinal values
+ * Optional:
+ * - CPU_FEATURE_TYPEFMT	format string fragment for printing the cpu type
+ * - CPU_FEATURE_TYPEVAL	set of values matching the format string above
+ */
+
+#ifndef CPU_FEATURE_TYPEFMT
+#define CPU_FEATURE_TYPEFMT	"%s"
+#endif
+
+#ifndef CPU_FEATURE_TYPEVAL
+#define CPU_FEATURE_TYPEVAL	ELF_PLATFORM
+#endif
+
+/*
+ * Use module_cpu_feature_match(feature, module_init_function) to
+ * declare that
+ * a) the module shall be probed upon discovery of CPU feature 'feature'
+ *    (typically at boot time using udev)
+ * b) the module must not be loaded if CPU feature 'feature' is not present
+ *    (not even by manual insmod).
+ *
+ * For a list of legal values for 'feature', please consult the file
+ * 'asm/cpufeature.h' of your favorite architecture.
+ */
+#define module_cpu_feature_match(x, __init)			\
+static struct cpu_feature const cpu_feature_match_ ## x[] =	\
+	{ { .feature = cpu_feature(x) }, { } };			\
+MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x);		\
+								\
+static int cpu_feature_match_ ## x ## _init(void)		\
+{								\
+	if (!cpu_have_feature(cpu_feature(x)))			\
+		return -ENODEV;					\
+	return __init();					\
+}								\
+module_init(cpu_feature_match_ ## x ## _init)
+
+#endif
+#endif
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 50fcbb0ac4e7..bab4f33a9468 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -84,6 +84,7 @@ struct cpuidle_device {
 };
 
 DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev);
 
 /**
  * cpuidle_get_last_residency - retrieves the last state's residency time
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 3fe661fe96d1..b19d3dc2e651 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -87,25 +87,26 @@ extern void rebuild_sched_domains(void);
 extern void cpuset_print_task_mems_allowed(struct task_struct *p);
 
 /*
- * get_mems_allowed is required when making decisions involving mems_allowed
- * such as during page allocation. mems_allowed can be updated in parallel
- * and depending on the new value an operation can fail potentially causing
- * process failure. A retry loop with get_mems_allowed and put_mems_allowed
- * prevents these artificial failures.
+ * read_mems_allowed_begin is required when making decisions involving
+ * mems_allowed such as during page allocation. mems_allowed can be updated in
+ * parallel and depending on the new value an operation can fail potentially
+ * causing process failure. A retry loop with read_mems_allowed_begin and
+ * read_mems_allowed_retry prevents these artificial failures.
  */
-static inline unsigned int get_mems_allowed(void)
+static inline unsigned int read_mems_allowed_begin(void)
 {
 	return read_seqcount_begin(&current->mems_allowed_seq);
 }
 
 /*
- * If this returns false, the operation that took place after get_mems_allowed
- * may have failed. It is up to the caller to retry the operation if
+ * If this returns true, the operation that took place after
+ * read_mems_allowed_begin may have failed artificially due to a concurrent
+ * update of mems_allowed. It is up to the caller to retry the operation if
  * appropriate.
  */
-static inline bool put_mems_allowed(unsigned int seq)
+static inline bool read_mems_allowed_retry(unsigned int seq)
 {
-	return !read_seqcount_retry(&current->mems_allowed_seq, seq);
+	return read_seqcount_retry(&current->mems_allowed_seq, seq);
 }
 
 static inline void set_mems_allowed(nodemask_t nodemask)
@@ -225,14 +226,14 @@ static inline void set_mems_allowed(nodemask_t nodemask)
 {
 }
 
-static inline unsigned int get_mems_allowed(void)
+static inline unsigned int read_mems_allowed_begin(void)
 {
 	return 0;
 }
 
-static inline bool put_mems_allowed(unsigned int seq)
+static inline bool read_mems_allowed_retry(unsigned int seq)
 {
-	return true;
+	return false;
 }
 
 #endif /* !CONFIG_CPUSETS */
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 7032518f8542..72ab536ad3de 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -25,6 +25,7 @@ extern int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma,
 
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
 						unsigned long, int);
+void vmcore_cleanup(void);
 
 /* Architecture code defines this if there are other possible ELF
  * machine types, e.g. on bi-arch capable hardware. */
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/cred.h b/include/linux/cred.h
index 04421e825365..f61d6c8f5ef3 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -66,7 +66,7 @@ extern struct group_info *groups_alloc(int);
 extern struct group_info init_groups;
 extern void groups_free(struct group_info *);
 extern int set_current_groups(struct group_info *);
-extern int set_groups(struct cred *, struct group_info *);
+extern void set_groups(struct cred *, struct group_info *);
 extern int groups_search(const struct group_info *, kgid_t);
 
 /* access the groups "array" with this macro */
diff --git a/include/linux/decompress/inflate.h b/include/linux/decompress/inflate.h
index 8c0aef1ba5f5..1d0aedef9822 100644
--- a/include/linux/decompress/inflate.h
+++ b/include/linux/decompress/inflate.h
@@ -1,5 +1,5 @@
-#ifndef INFLATE_H
-#define INFLATE_H
+#ifndef LINUX_DECOMPRESS_INFLATE_H
+#define LINUX_DECOMPRESS_INFLATE_H
 
 int gunzip(unsigned char *inbuf, int len,
 	   int(*fill)(void*, unsigned int),
diff --git a/include/linux/device.h b/include/linux/device.h
index 952b01033c32..d1d1c055b48e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -560,16 +560,12 @@ extern int device_create_file(struct device *device,
 			      const struct device_attribute *entry);
 extern void device_remove_file(struct device *dev,
 			       const struct device_attribute *attr);
+extern bool device_remove_file_self(struct device *dev,
+				    const struct device_attribute *attr);
 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);
@@ -626,6 +622,7 @@ static inline void *devm_kcalloc(struct device *dev,
 	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
 }
 extern void devm_kfree(struct device *dev, void *p);
+extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
 
 void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
 void __iomem *devm_request_and_ioremap(struct device *dev,
@@ -929,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/drbd.h b/include/linux/drbd.h
index de7d74ab3de6..3dbe9bd57a09 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -327,12 +327,6 @@ enum drbd_state_rv {
 	SS_AFTER_LAST_ERROR = -22,    /* Keep this at bottom */
 };
 
-/* from drbd_strings.c */
-extern const char *drbd_conn_str(enum drbd_conns);
-extern const char *drbd_role_str(enum drbd_role);
-extern const char *drbd_disk_str(enum drbd_disk_state);
-extern const char *drbd_set_st_err_str(enum drbd_state_rv);
-
 #define SHARED_SECRET_MAX 64
 
 #define MDF_CONSISTENT		(1 << 0)
@@ -382,4 +376,6 @@ enum drbd_timeout_flag {
 #define DRBD_MD_INDEX_FLEX_EXT -2
 #define DRBD_MD_INDEX_FLEX_INT -3
 
+#define DRBD_CPU_MASK_SIZE 32
+
 #endif
diff --git a/include/linux/drbd_genl.h b/include/linux/drbd_genl.h
index e8c44572b8cb..4193f5f2636c 100644
--- a/include/linux/drbd_genl.h
+++ b/include/linux/drbd_genl.h
@@ -135,7 +135,7 @@ GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf,
 )
 
 GENL_struct(DRBD_NLA_RESOURCE_OPTS, 4, res_opts,
-	__str_field_def(1,	DRBD_GENLA_F_MANDATORY,	cpu_mask,       32)
+	__str_field_def(1,	DRBD_GENLA_F_MANDATORY,	cpu_mask,       DRBD_CPU_MASK_SIZE)
 	__u32_field_def(2,	DRBD_GENLA_F_MANDATORY,	on_no_data, DRBD_ON_NO_DATA_DEF)
 )
 
@@ -276,9 +276,9 @@ GENL_op(
 )
 
 	/* add DRBD minor devices as volumes to resources */
-GENL_op(DRBD_ADM_NEW_MINOR, 5, GENL_doit(drbd_adm_add_minor),
+GENL_op(DRBD_ADM_NEW_MINOR, 5, GENL_doit(drbd_adm_new_minor),
 	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
-GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_delete_minor),
+GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_del_minor),
 	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
 
 	/* add or delete resources */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 481ab2345d6b..68b4024184de 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -1,6 +1,5 @@
 /*
- * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
- * AVR32 systems.)
+ * Driver for the Synopsys DesignWare DMA Controller
  *
  * Copyright (C) 2007 Atmel Corporation
  * Copyright (C) 2010-2011 ST Microelectronics
@@ -44,8 +43,6 @@ struct dw_dma_slave {
  * @nr_masters: Number of AHB masters supported by the controller
  * @data_width: Maximum data width supported by hardware per AHB master
  *		(0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
- * @sd: slave specific data. Used for configuring channels
- * @sd_count: count of slave data structures passed.
  */
 struct dw_dma_platform_data {
 	unsigned int	nr_channels;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 306dd8cd0b6f..df63bd3a8cf1 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -202,17 +202,8 @@ enum {
 #define rq_end_sector(rq)	(blk_rq_pos(rq) + blk_rq_sectors(rq))
 #define rb_entry_rq(node)	rb_entry((node), struct request, rb_node)
 
-/*
- * Hack to reuse the csd.list list_head as the fifo time holder while
- * the request is in the io scheduler. Saves an unsigned long in rq.
- */
-#define rq_fifo_time(rq)	((unsigned long) (rq)->csd.list.next)
-#define rq_set_fifo_time(rq,exp)	((rq)->csd.list.next = (void *) (exp))
 #define rq_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
-#define rq_fifo_clear(rq)	do {		\
-	list_del_init(&(rq)->queuelist);	\
-	INIT_LIST_HEAD(&(rq)->csd.list);	\
-	} while (0)
+#define rq_fifo_clear(rq)	list_del_init(&(rq)->queuelist)
 
 #else /* CONFIG_BLOCK */
 
diff --git a/include/linux/err.h b/include/linux/err.h
index 15f92e072450..a729120644d5 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -2,12 +2,13 @@
 #define _LINUX_ERR_H
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 
 #include <asm/errno.h>
 
 /*
  * Kernel pointers have redundant information, so we can use a
- * scheme where we can return either an error code or a dentry
+ * scheme where we can return either an error code or a normal
  * pointer with the same return value.
  *
  * This should be a per-architecture thing, to allow different
@@ -29,12 +30,12 @@ static inline long __must_check PTR_ERR(__force const void *ptr)
 	return (long) ptr;
 }
 
-static inline long __must_check IS_ERR(__force const void *ptr)
+static inline bool __must_check IS_ERR(__force const void *ptr)
 {
 	return IS_ERR_VALUE((unsigned long)ptr);
 }
 
-static inline long __must_check IS_ERR_OR_NULL(__force const void *ptr)
+static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
 {
 	return !ptr || IS_ERR_VALUE((unsigned long)ptr);
 }
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c8e3e7e39c6b..0a114d05f68d 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -183,6 +183,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
  * hold the RTNL lock.
  *
  * See the structures used by these operations for further documentation.
+ * Note that for all operations using a structure ending with a zero-
+ * length array, the array is allocated separately in the kernel and
+ * is passed to the driver as an additional parameter.
  *
  * See &struct net_device and &struct net_device_ops for documentation
  * of the generic netdev features interface.
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index da74d878dc4f..df53e1753a76 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -183,7 +183,7 @@ struct f2fs_inode {
 	__le32 i_pino;			/* parent inode number */
 	__le32 i_namelen;		/* file name length */
 	__u8 i_name[F2FS_NAME_LEN];	/* file name for SPOR */
-	__u8 i_reserved2;		/* for backward compatibility */
+	__u8 i_dir_level;		/* dentry_level for large dir */
 
 	struct f2fs_extent i_ext;	/* caching a largest extent */
 
diff --git a/include/linux/fmc-sdb.h b/include/linux/fmc-sdb.h
index 1974317a9b3d..599bd6bab56d 100644
--- a/include/linux/fmc-sdb.h
+++ b/include/linux/fmc-sdb.h
@@ -14,6 +14,8 @@ union sdb_record {
 	struct sdb_bridge bridge;
 	struct sdb_integration integr;
 	struct sdb_empty empty;
+	struct sdb_synthesis synthesis;
+	struct sdb_repo_url repo_url;
 };
 
 struct fmc_device;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 60829565e552..881accffc10e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -416,6 +416,7 @@ struct address_space {
 	struct mutex		i_mmap_mutex;	/* protect tree, count, list */
 	/* Protected by tree_lock together with the radix tree */
 	unsigned long		nrpages;	/* number of total pages */
+	unsigned long		nrshadows;	/* number of shadow entries */
 	pgoff_t			writeback_index;/* writeback starts here */
 	const struct address_space_operations *a_ops;	/* methods */
 	unsigned long		flags;		/* error bits/gfp mask */
@@ -888,6 +889,7 @@ static inline int file_check_writeable(struct file *filp)
 #define FL_SLEEP	128	/* A blocking lock */
 #define FL_DOWNGRADE_PENDING	256 /* Lease is being downgraded */
 #define FL_UNLOCK_PENDING	512 /* Lease is being broken */
+#define FL_FILE_PVT	1024	/* lock is private to the file */
 
 /*
  * Special return value from posix_lock_file() and vfs_lock_file() for
@@ -992,12 +994,12 @@ struct file_lock {
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
 #ifdef CONFIG_FILE_LOCKING
-extern int fcntl_getlk(struct file *, struct flock __user *);
+extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
 extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
 			struct flock __user *);
 
 #if BITS_PER_LONG == 32
-extern int fcntl_getlk64(struct file *, struct flock64 __user *);
+extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *);
 extern int fcntl_setlk64(unsigned int, struct file *, unsigned int,
 			struct flock64 __user *);
 #endif
@@ -1012,7 +1014,7 @@ extern struct file_lock * locks_alloc_lock(void);
 extern void locks_copy_lock(struct file_lock *, struct file_lock *);
 extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
 extern void locks_remove_posix(struct file *, fl_owner_t);
-extern void locks_remove_flock(struct file *);
+extern void locks_remove_file(struct file *);
 extern void locks_release_private(struct file_lock *);
 extern void posix_test_lock(struct file *, struct file_lock *);
 extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
@@ -1030,7 +1032,8 @@ extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
 #else /* !CONFIG_FILE_LOCKING */
-static inline int fcntl_getlk(struct file *file, struct flock __user *user)
+static inline int fcntl_getlk(struct file *file, unsigned int cmd,
+			      struct flock __user *user)
 {
 	return -EINVAL;
 }
@@ -1042,7 +1045,8 @@ static inline int fcntl_setlk(unsigned int fd, struct file *file,
 }
 
 #if BITS_PER_LONG == 32
-static inline int fcntl_getlk64(struct file *file, struct flock64 __user *user)
+static inline int fcntl_getlk64(struct file *file, unsigned int cmd,
+				struct flock64 __user *user)
 {
 	return -EINVAL;
 }
@@ -1083,7 +1087,7 @@ static inline void locks_remove_posix(struct file *filp, fl_owner_t owner)
 	return;
 }
 
-static inline void locks_remove_flock(struct file *filp)
+static inline void locks_remove_file(struct file *filp)
 {
 	return;
 }
@@ -1964,6 +1968,12 @@ static inline int locks_verify_truncate(struct inode *inode,
 
 static inline int break_lease(struct inode *inode, unsigned int mode)
 {
+	/*
+	 * Since this check is lockless, we must ensure that any refcounts
+	 * taken are done before checking inode->i_flock. Otherwise, we could
+	 * end up racing with tasks trying to set a new lease on this file.
+	 */
+	smp_mb();
 	if (inode->i_flock)
 		return __break_lease(inode, mode, FL_LEASE);
 	return 0;
@@ -2534,6 +2544,9 @@ enum {
 
 	/* filesystem does not support filling holes */
 	DIO_SKIP_HOLES	= 0x02,
+
+	/* filesystem can handle aio writes beyond i_size */
+	DIO_ASYNC_EXTEND = 0x04,
 };
 
 void dio_end_io(struct bio *bio, int error);
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h
new file mode 100644
index 000000000000..f49ddb1b2273
--- /dev/null
+++ b/include/linux/fsl_ifc.h
@@ -0,0 +1,838 @@
+/* Freescale Integrated Flash Controller
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc
+ *
+ * Author: Dipen Dudhat <dipen.dudhat@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.
+ *
+ * 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 __ASM_FSL_IFC_H
+#define __ASM_FSL_IFC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+
+#define FSL_IFC_BANK_COUNT 4
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA				0xFFFF0000
+#define CSPR_BA_SHIFT			16
+#define CSPR_PORT_SIZE			0x00000180
+#define CSPR_PORT_SIZE_SHIFT		7
+/* Port Size 8 bit */
+#define CSPR_PORT_SIZE_8		0x00000080
+/* Port Size 16 bit */
+#define CSPR_PORT_SIZE_16		0x00000100
+/* Port Size 32 bit */
+#define CSPR_PORT_SIZE_32		0x00000180
+/* Write Protect */
+#define CSPR_WP				0x00000040
+#define CSPR_WP_SHIFT			6
+/* Machine Select */
+#define CSPR_MSEL			0x00000006
+#define CSPR_MSEL_SHIFT			1
+/* NOR */
+#define CSPR_MSEL_NOR			0x00000000
+/* NAND */
+#define CSPR_MSEL_NAND			0x00000002
+/* GPCM */
+#define CSPR_MSEL_GPCM			0x00000004
+/* Bank Valid */
+#define CSPR_V				0x00000001
+#define CSPR_V_SHIFT			0
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK			0xFFFF0000
+#define IFC_AMASK_SHIFT			16
+#define IFC_AMASK(n)			(IFC_AMASK_MASK << \
+					(__ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+/* Enable ECC Encoder */
+#define CSOR_NAND_ECC_ENC_EN		0x80000000
+#define CSOR_NAND_ECC_MODE_MASK		0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4		0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8		0x10000000
+/* Enable ECC Decoder */
+#define CSOR_NAND_ECC_DEC_EN		0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK		0x01800000
+#define CSOR_NAND_RAL_SHIFT		20
+#define CSOR_NAND_RAL_1			0x00000000
+#define CSOR_NAND_RAL_2			0x00800000
+#define CSOR_NAND_RAL_3			0x01000000
+#define CSOR_NAND_RAL_4			0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK		0x00180000
+#define CSOR_NAND_PGS_SHIFT		16
+#define CSOR_NAND_PGS_512		0x00000000
+#define CSOR_NAND_PGS_2K		0x00080000
+#define CSOR_NAND_PGS_4K		0x00100000
+#define CSOR_NAND_PGS_8K		0x00180000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK		0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT		13
+#define CSOR_NAND_SPRZ_16		0x00000000
+#define CSOR_NAND_SPRZ_64		0x00002000
+#define CSOR_NAND_SPRZ_128		0x00004000
+#define CSOR_NAND_SPRZ_210		0x00006000
+#define CSOR_NAND_SPRZ_218		0x00008000
+#define CSOR_NAND_SPRZ_224		0x0000A000
+#define CSOR_NAND_SPRZ_CSOR_EXT		0x0000C000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK		0x00000700
+#define CSOR_NAND_PB_SHIFT		8
+#define CSOR_NAND_PB(n)		((__ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK		0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT		2
+#define CSOR_NAND_TRHZ_20		0x00000000
+#define CSOR_NAND_TRHZ_40		0x00000004
+#define CSOR_NAND_TRHZ_60		0x00000008
+#define CSOR_NAND_TRHZ_80		0x0000000C
+#define CSOR_NAND_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD			0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN	0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN		0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN		0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK		0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT	13
+#define CSOR_NOR_ADM_SHIFT(n)	((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_AYSNC_NOR	0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR	0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK		0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT		2
+#define CSOR_NOR_TRHZ_20		0x00000000
+#define CSOR_NOR_TRHZ_40		0x00000004
+#define CSOR_NOR_TRHZ_60		0x00000008
+#define CSOR_NOR_TRHZ_80		0x0000000C
+#define CSOR_NOR_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD			0x00000001
+
+/*
+ * Chip Select Option Register - GPCM Mode
+ */
+/* GPCM Mode - Normal */
+#define CSOR_GPCM_GPMODE_NORMAL		0x00000000
+/* GPCM Mode - GenericASIC */
+#define CSOR_GPCM_GPMODE_ASIC		0x80000000
+/* Parity Mode odd/even */
+#define CSOR_GPCM_PARITY_EVEN		0x40000000
+/* Parity Checking enable/disable */
+#define CSOR_GPCM_PAR_EN		0x20000000
+/* GPCM Timeout Count */
+#define CSOR_GPCM_GPTO_MASK		0x0F000000
+#define CSOR_GPCM_GPTO_SHIFT		24
+#define CSOR_GPCM_GPTO(n)	((__ilog2(n) - 8) << CSOR_GPCM_GPTO_SHIFT)
+/* GPCM External Access Termination mode for read access */
+#define CSOR_GPCM_RGETA_EXT		0x00080000
+/* GPCM External Access Termination mode for write access */
+#define CSOR_GPCM_WGETA_EXT		0x00040000
+/* Address Data Multiplexing Shift */
+#define CSOR_GPCM_ADM_MASK		0x0003E000
+#define CSOR_GPCM_ADM_SHIFT_SHIFT	13
+#define CSOR_GPCM_ADM_SHIFT(n)	((n) << CSOR_GPCM_ADM_SHIFT_SHIFT)
+/* Generic ASIC Parity error indication delay */
+#define CSOR_GPCM_GAPERRD_MASK		0x00000180
+#define CSOR_GPCM_GAPERRD_SHIFT		7
+#define CSOR_GPCM_GAPERRD(n)	(((n) - 1) << CSOR_GPCM_GAPERRD_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_GPCM_TRHZ_MASK		0x0000001C
+#define CSOR_GPCM_TRHZ_20		0x00000000
+#define CSOR_GPCM_TRHZ_40		0x00000004
+#define CSOR_GPCM_TRHZ_60		0x00000008
+#define CSOR_GPCM_TRHZ_80		0x0000000C
+#define CSOR_GPCM_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_GPCM_BCTLD			0x00000001
+
+/*
+ * Ready Busy Status Register (RB_STAT)
+ */
+/* CSn is READY */
+#define IFC_RB_STAT_READY_CS0		0x80000000
+#define IFC_RB_STAT_READY_CS1		0x40000000
+#define IFC_RB_STAT_READY_CS2		0x20000000
+#define IFC_RB_STAT_READY_CS3		0x10000000
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK			0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL		0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME		0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT	11
+
+/*
+ * Common Event and Error Status Register (CM_EVTER_STAT)
+ */
+/* Chip select error */
+#define IFC_CM_EVTER_STAT_CSER		0x80000000
+
+/*
+ * Common Event and Error Enable Register (CM_EVTER_EN)
+ */
+/* Chip select error checking enable */
+#define IFC_CM_EVTER_EN_CSEREN		0x80000000
+
+/*
+ * Common Event and Error Interrupt Enable Register (CM_EVTER_INTR_EN)
+ */
+/* Chip select error interrupt enable */
+#define IFC_CM_EVTER_INTR_EN_CSERIREN	0x80000000
+
+/*
+ * Common Transfer Error Attribute Register-0 (CM_ERATTR0)
+ */
+/* transaction type of error Read/Write */
+#define IFC_CM_ERATTR0_ERTYP_READ	0x80000000
+#define IFC_CM_ERATTR0_ERAID		0x0FF00000
+#define IFC_CM_ERATTR0_ERAID_SHIFT	20
+#define IFC_CM_ERATTR0_ESRCID		0x0000FF00
+#define IFC_CM_ERATTR0_ESRCID_SHIFT	8
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK			0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK		0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT		24
+#define IFC_CCR_CLK_DIV(n)		((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK		0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT		16
+#define IFC_CCR_CLK_DLY(n)		((n) << IFC_CCR_CLK_DLY_SHIFT)
+/* Invert IFC clock before sending out */
+#define IFC_CCR_INV_CLK_EN		0x00008000
+/* Fedback IFC Clock */
+#define IFC_CCR_FB_IFC_CLK_SEL		0x00000800
+
+/*
+ * Clock Status Register (CSR)
+ */
+/* Clk is stable */
+#define IFC_CSR_CLK_STAT_STABLE		0x80000000
+
+/*
+ * IFC_NAND Machine Specific Registers
+ */
+/*
+ * NAND Configuration Register (NCFGR)
+ */
+/* Auto Boot Mode */
+#define IFC_NAND_NCFGR_BOOT		0x80000000
+/* Addressing Mode-ROW0+n/COL0 */
+#define IFC_NAND_NCFGR_ADDR_MODE_RC0	0x00000000
+/* Addressing Mode-ROW0+n/COL0+n */
+#define IFC_NAND_NCFGR_ADDR_MODE_RC1	0x00400000
+/* Number of loop iterations of FIR sequences for multi page operations */
+#define IFC_NAND_NCFGR_NUM_LOOP_MASK	0x0000F000
+#define IFC_NAND_NCFGR_NUM_LOOP_SHIFT	12
+#define IFC_NAND_NCFGR_NUM_LOOP(n)	((n) << IFC_NAND_NCFGR_NUM_LOOP_SHIFT)
+/* Number of wait cycles */
+#define IFC_NAND_NCFGR_NUM_WAIT_MASK	0x000000FF
+#define IFC_NAND_NCFGR_NUM_WAIT_SHIFT	0
+
+/*
+ * NAND Flash Command Registers (NAND_FCR0/NAND_FCR1)
+ */
+/* General purpose FCM flash command bytes CMD0-CMD7 */
+#define IFC_NAND_FCR0_CMD0		0xFF000000
+#define IFC_NAND_FCR0_CMD0_SHIFT	24
+#define IFC_NAND_FCR0_CMD1		0x00FF0000
+#define IFC_NAND_FCR0_CMD1_SHIFT	16
+#define IFC_NAND_FCR0_CMD2		0x0000FF00
+#define IFC_NAND_FCR0_CMD2_SHIFT	8
+#define IFC_NAND_FCR0_CMD3		0x000000FF
+#define IFC_NAND_FCR0_CMD3_SHIFT	0
+#define IFC_NAND_FCR1_CMD4		0xFF000000
+#define IFC_NAND_FCR1_CMD4_SHIFT	24
+#define IFC_NAND_FCR1_CMD5		0x00FF0000
+#define IFC_NAND_FCR1_CMD5_SHIFT	16
+#define IFC_NAND_FCR1_CMD6		0x0000FF00
+#define IFC_NAND_FCR1_CMD6_SHIFT	8
+#define IFC_NAND_FCR1_CMD7		0x000000FF
+#define IFC_NAND_FCR1_CMD7_SHIFT	0
+
+/*
+ * Flash ROW and COL Address Register (ROWn, COLn)
+ */
+/* Main/spare region locator */
+#define IFC_NAND_COL_MS			0x80000000
+/* Column Address */
+#define IFC_NAND_COL_CA_MASK		0x00000FFF
+
+/*
+ * NAND Flash Byte Count Register (NAND_BC)
+ */
+/* Byte Count for read/Write */
+#define IFC_NAND_BC			0x000001FF
+
+/*
+ * NAND Flash Instruction Registers (NAND_FIR0/NAND_FIR1/NAND_FIR2)
+ */
+/* NAND Machine specific opcodes OP0-OP14*/
+#define IFC_NAND_FIR0_OP0		0xFC000000
+#define IFC_NAND_FIR0_OP0_SHIFT		26
+#define IFC_NAND_FIR0_OP1		0x03F00000
+#define IFC_NAND_FIR0_OP1_SHIFT		20
+#define IFC_NAND_FIR0_OP2		0x000FC000
+#define IFC_NAND_FIR0_OP2_SHIFT		14
+#define IFC_NAND_FIR0_OP3		0x00003F00
+#define IFC_NAND_FIR0_OP3_SHIFT		8
+#define IFC_NAND_FIR0_OP4		0x000000FC
+#define IFC_NAND_FIR0_OP4_SHIFT		2
+#define IFC_NAND_FIR1_OP5		0xFC000000
+#define IFC_NAND_FIR1_OP5_SHIFT		26
+#define IFC_NAND_FIR1_OP6		0x03F00000
+#define IFC_NAND_FIR1_OP6_SHIFT		20
+#define IFC_NAND_FIR1_OP7		0x000FC000
+#define IFC_NAND_FIR1_OP7_SHIFT		14
+#define IFC_NAND_FIR1_OP8		0x00003F00
+#define IFC_NAND_FIR1_OP8_SHIFT		8
+#define IFC_NAND_FIR1_OP9		0x000000FC
+#define IFC_NAND_FIR1_OP9_SHIFT		2
+#define IFC_NAND_FIR2_OP10		0xFC000000
+#define IFC_NAND_FIR2_OP10_SHIFT	26
+#define IFC_NAND_FIR2_OP11		0x03F00000
+#define IFC_NAND_FIR2_OP11_SHIFT	20
+#define IFC_NAND_FIR2_OP12		0x000FC000
+#define IFC_NAND_FIR2_OP12_SHIFT	14
+#define IFC_NAND_FIR2_OP13		0x00003F00
+#define IFC_NAND_FIR2_OP13_SHIFT	8
+#define IFC_NAND_FIR2_OP14		0x000000FC
+#define IFC_NAND_FIR2_OP14_SHIFT	2
+
+/*
+ * Instruction opcodes to be programmed
+ * in FIR registers- 6bits
+ */
+enum ifc_nand_fir_opcodes {
+	IFC_FIR_OP_NOP,
+	IFC_FIR_OP_CA0,
+	IFC_FIR_OP_CA1,
+	IFC_FIR_OP_CA2,
+	IFC_FIR_OP_CA3,
+	IFC_FIR_OP_RA0,
+	IFC_FIR_OP_RA1,
+	IFC_FIR_OP_RA2,
+	IFC_FIR_OP_RA3,
+	IFC_FIR_OP_CMD0,
+	IFC_FIR_OP_CMD1,
+	IFC_FIR_OP_CMD2,
+	IFC_FIR_OP_CMD3,
+	IFC_FIR_OP_CMD4,
+	IFC_FIR_OP_CMD5,
+	IFC_FIR_OP_CMD6,
+	IFC_FIR_OP_CMD7,
+	IFC_FIR_OP_CW0,
+	IFC_FIR_OP_CW1,
+	IFC_FIR_OP_CW2,
+	IFC_FIR_OP_CW3,
+	IFC_FIR_OP_CW4,
+	IFC_FIR_OP_CW5,
+	IFC_FIR_OP_CW6,
+	IFC_FIR_OP_CW7,
+	IFC_FIR_OP_WBCD,
+	IFC_FIR_OP_RBCD,
+	IFC_FIR_OP_BTRD,
+	IFC_FIR_OP_RDSTAT,
+	IFC_FIR_OP_NWAIT,
+	IFC_FIR_OP_WFR,
+	IFC_FIR_OP_SBRD,
+	IFC_FIR_OP_UA,
+	IFC_FIR_OP_RB,
+};
+
+/*
+ * NAND Chip Select Register (NAND_CSEL)
+ */
+#define IFC_NAND_CSEL			0x0C000000
+#define IFC_NAND_CSEL_SHIFT		26
+#define IFC_NAND_CSEL_CS0		0x00000000
+#define IFC_NAND_CSEL_CS1		0x04000000
+#define IFC_NAND_CSEL_CS2		0x08000000
+#define IFC_NAND_CSEL_CS3		0x0C000000
+
+/*
+ * NAND Operation Sequence Start (NANDSEQ_STRT)
+ */
+/* NAND Flash Operation Start */
+#define IFC_NAND_SEQ_STRT_FIR_STRT	0x80000000
+/* Automatic Erase */
+#define IFC_NAND_SEQ_STRT_AUTO_ERS	0x00800000
+/* Automatic Program */
+#define IFC_NAND_SEQ_STRT_AUTO_PGM	0x00100000
+/* Automatic Copyback */
+#define IFC_NAND_SEQ_STRT_AUTO_CPB	0x00020000
+/* Automatic Read Operation */
+#define IFC_NAND_SEQ_STRT_AUTO_RD	0x00004000
+/* Automatic Status Read */
+#define IFC_NAND_SEQ_STRT_AUTO_STAT_RD	0x00000800
+
+/*
+ * NAND Event and Error Status Register (NAND_EVTER_STAT)
+ */
+/* Operation Complete */
+#define IFC_NAND_EVTER_STAT_OPC		0x80000000
+/* Flash Timeout Error */
+#define IFC_NAND_EVTER_STAT_FTOER	0x08000000
+/* Write Protect Error */
+#define IFC_NAND_EVTER_STAT_WPER	0x04000000
+/* ECC Error */
+#define IFC_NAND_EVTER_STAT_ECCER	0x02000000
+/* RCW Load Done */
+#define IFC_NAND_EVTER_STAT_RCW_DN	0x00008000
+/* Boot Loadr Done */
+#define IFC_NAND_EVTER_STAT_BOOT_DN	0x00004000
+/* Bad Block Indicator search select */
+#define IFC_NAND_EVTER_STAT_BBI_SRCH_SE	0x00000800
+
+/*
+ * NAND Flash Page Read Completion Event Status Register
+ * (PGRDCMPL_EVT_STAT)
+ */
+#define PGRDCMPL_EVT_STAT_MASK		0xFFFF0000
+/* Small Page 0-15 Done */
+#define PGRDCMPL_EVT_STAT_SECTION_SP(n)	(1 << (31 - (n)))
+/* Large Page(2K) 0-3 Done */
+#define PGRDCMPL_EVT_STAT_LP_2K(n)	(0xF << (28 - (n)*4))
+/* Large Page(4K) 0-1 Done */
+#define PGRDCMPL_EVT_STAT_LP_4K(n)	(0xFF << (24 - (n)*8))
+
+/*
+ * NAND Event and Error Enable Register (NAND_EVTER_EN)
+ */
+/* Operation complete event enable */
+#define IFC_NAND_EVTER_EN_OPC_EN	0x80000000
+/* Page read complete event enable */
+#define IFC_NAND_EVTER_EN_PGRDCMPL_EN	0x20000000
+/* Flash Timeout error enable */
+#define IFC_NAND_EVTER_EN_FTOER_EN	0x08000000
+/* Write Protect error enable */
+#define IFC_NAND_EVTER_EN_WPER_EN	0x04000000
+/* ECC error logging enable */
+#define IFC_NAND_EVTER_EN_ECCER_EN	0x02000000
+
+/*
+ * NAND Event and Error Interrupt Enable Register (NAND_EVTER_INTR_EN)
+ */
+/* Enable interrupt for operation complete */
+#define IFC_NAND_EVTER_INTR_OPCIR_EN		0x80000000
+/* Enable interrupt for Page read complete */
+#define IFC_NAND_EVTER_INTR_PGRDCMPLIR_EN	0x20000000
+/* Enable interrupt for Flash timeout error */
+#define IFC_NAND_EVTER_INTR_FTOERIR_EN		0x08000000
+/* Enable interrupt for Write protect error */
+#define IFC_NAND_EVTER_INTR_WPERIR_EN		0x04000000
+/* Enable interrupt for ECC error*/
+#define IFC_NAND_EVTER_INTR_ECCERIR_EN		0x02000000
+
+/*
+ * NAND Transfer Error Attribute Register-0 (NAND_ERATTR0)
+ */
+#define IFC_NAND_ERATTR0_MASK		0x0C080000
+/* Error on CS0-3 for NAND */
+#define IFC_NAND_ERATTR0_ERCS_CS0	0x00000000
+#define IFC_NAND_ERATTR0_ERCS_CS1	0x04000000
+#define IFC_NAND_ERATTR0_ERCS_CS2	0x08000000
+#define IFC_NAND_ERATTR0_ERCS_CS3	0x0C000000
+/* Transaction type of error Read/Write */
+#define IFC_NAND_ERATTR0_ERTTYPE_READ	0x00080000
+
+/*
+ * NAND Flash Status Register (NAND_FSR)
+ */
+/* First byte of data read from read status op */
+#define IFC_NAND_NFSR_RS0		0xFF000000
+/* Second byte of data read from read status op */
+#define IFC_NAND_NFSR_RS1		0x00FF0000
+
+/*
+ * ECC Error Status Registers (ECCSTAT0-ECCSTAT3)
+ */
+/* Number of ECC errors on sector n (n = 0-15) */
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_MASK	0x0F000000
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_SHIFT	24
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_MASK	0x000F0000
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_SHIFT	16
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_MASK	0x00000F00
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_SHIFT	8
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_MASK	0x0000000F
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_SHIFT	0
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_MASK	0x0F000000
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_SHIFT	24
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_MASK	0x000F0000
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_SHIFT	16
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_MASK	0x00000F00
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_SHIFT	8
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_MASK	0x0000000F
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_SHIFT	0
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_MASK	0x0F000000
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_SHIFT	24
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_MASK	0x000F0000
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_SHIFT	16
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_MASK	0x00000F00
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_SHIFT	8
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_MASK	0x0000000F
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_SHIFT	0
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_MASK	0x0F000000
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_SHIFT	24
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_MASK	0x000F0000
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_SHIFT	16
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_MASK	0x00000F00
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_SHIFT	8
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_MASK	0x0000000F
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_SHIFT	0
+
+/*
+ * NAND Control Register (NANDCR)
+ */
+#define IFC_NAND_NCR_FTOCNT_MASK	0x1E000000
+#define IFC_NAND_NCR_FTOCNT_SHIFT	25
+#define IFC_NAND_NCR_FTOCNT(n)	((_ilog2(n) - 8)  << IFC_NAND_NCR_FTOCNT_SHIFT)
+
+/*
+ * NAND_AUTOBOOT_TRGR
+ */
+/* Trigger RCW load */
+#define IFC_NAND_AUTOBOOT_TRGR_RCW_LD	0x80000000
+/* Trigget Auto Boot */
+#define IFC_NAND_AUTOBOOT_TRGR_BOOT_LD	0x20000000
+
+/*
+ * NAND_MDR
+ */
+/* 1st read data byte when opcode SBRD */
+#define IFC_NAND_MDR_RDATA0		0xFF000000
+/* 2nd read data byte when opcode SBRD */
+#define IFC_NAND_MDR_RDATA1		0x00FF0000
+
+/*
+ * NOR Machine Specific Registers
+ */
+/*
+ * NOR Event and Error Status Register (NOR_EVTER_STAT)
+ */
+/* NOR Command Sequence Operation Complete */
+#define IFC_NOR_EVTER_STAT_OPC_NOR	0x80000000
+/* Write Protect Error */
+#define IFC_NOR_EVTER_STAT_WPER		0x04000000
+/* Command Sequence Timeout Error */
+#define IFC_NOR_EVTER_STAT_STOER	0x01000000
+
+/*
+ * NOR Event and Error Enable Register (NOR_EVTER_EN)
+ */
+/* NOR Command Seq complete event enable */
+#define IFC_NOR_EVTER_EN_OPCEN_NOR	0x80000000
+/* Write Protect Error Checking Enable */
+#define IFC_NOR_EVTER_EN_WPEREN		0x04000000
+/* Timeout Error Enable */
+#define IFC_NOR_EVTER_EN_STOEREN	0x01000000
+
+/*
+ * NOR Event and Error Interrupt Enable Register (NOR_EVTER_INTR_EN)
+ */
+/* Enable interrupt for OPC complete */
+#define IFC_NOR_EVTER_INTR_OPCEN_NOR	0x80000000
+/* Enable interrupt for write protect error */
+#define IFC_NOR_EVTER_INTR_WPEREN	0x04000000
+/* Enable interrupt for timeout error */
+#define IFC_NOR_EVTER_INTR_STOEREN	0x01000000
+
+/*
+ * NOR Transfer Error Attribute Register-0 (NOR_ERATTR0)
+ */
+/* Source ID for error transaction */
+#define IFC_NOR_ERATTR0_ERSRCID		0xFF000000
+/* AXI ID for error transation */
+#define IFC_NOR_ERATTR0_ERAID		0x000FF000
+/* Chip select corresponds to NOR error */
+#define IFC_NOR_ERATTR0_ERCS_CS0	0x00000000
+#define IFC_NOR_ERATTR0_ERCS_CS1	0x00000010
+#define IFC_NOR_ERATTR0_ERCS_CS2	0x00000020
+#define IFC_NOR_ERATTR0_ERCS_CS3	0x00000030
+/* Type of transaction read/write */
+#define IFC_NOR_ERATTR0_ERTYPE_READ	0x00000001
+
+/*
+ * NOR Transfer Error Attribute Register-2 (NOR_ERATTR2)
+ */
+#define IFC_NOR_ERATTR2_ER_NUM_PHASE_EXP	0x000F0000
+#define IFC_NOR_ERATTR2_ER_NUM_PHASE_PER	0x00000F00
+
+/*
+ * NOR Control Register (NORCR)
+ */
+#define IFC_NORCR_MASK			0x0F0F0000
+/* No. of Address/Data Phase */
+#define IFC_NORCR_NUM_PHASE_MASK	0x0F000000
+#define IFC_NORCR_NUM_PHASE_SHIFT	24
+#define IFC_NORCR_NUM_PHASE(n)	((n-1) << IFC_NORCR_NUM_PHASE_SHIFT)
+/* Sequence Timeout Count */
+#define IFC_NORCR_STOCNT_MASK		0x000F0000
+#define IFC_NORCR_STOCNT_SHIFT		16
+#define IFC_NORCR_STOCNT(n)	((__ilog2(n) - 8) << IFC_NORCR_STOCNT_SHIFT)
+
+/*
+ * GPCM Machine specific registers
+ */
+/*
+ * GPCM Event and Error Status Register (GPCM_EVTER_STAT)
+ */
+/* Timeout error */
+#define IFC_GPCM_EVTER_STAT_TOER	0x04000000
+/* Parity error */
+#define IFC_GPCM_EVTER_STAT_PER		0x01000000
+
+/*
+ * GPCM Event and Error Enable Register (GPCM_EVTER_EN)
+ */
+/* Timeout error enable */
+#define IFC_GPCM_EVTER_EN_TOER_EN	0x04000000
+/* Parity error enable */
+#define IFC_GPCM_EVTER_EN_PER_EN	0x01000000
+
+/*
+ * GPCM Event and Error Interrupt Enable Register (GPCM_EVTER_INTR_EN)
+ */
+/* Enable Interrupt for timeout error */
+#define IFC_GPCM_EEIER_TOERIR_EN	0x04000000
+/* Enable Interrupt for Parity error */
+#define IFC_GPCM_EEIER_PERIR_EN		0x01000000
+
+/*
+ * GPCM Transfer Error Attribute Register-0 (GPCM_ERATTR0)
+ */
+/* Source ID for error transaction */
+#define IFC_GPCM_ERATTR0_ERSRCID	0xFF000000
+/* AXI ID for error transaction */
+#define IFC_GPCM_ERATTR0_ERAID		0x000FF000
+/* Chip select corresponds to GPCM error */
+#define IFC_GPCM_ERATTR0_ERCS_CS0	0x00000000
+#define IFC_GPCM_ERATTR0_ERCS_CS1	0x00000040
+#define IFC_GPCM_ERATTR0_ERCS_CS2	0x00000080
+#define IFC_GPCM_ERATTR0_ERCS_CS3	0x000000C0
+/* Type of transaction read/Write */
+#define IFC_GPCM_ERATTR0_ERTYPE_READ	0x00000001
+
+/*
+ * GPCM Transfer Error Attribute Register-2 (GPCM_ERATTR2)
+ */
+/* On which beat of address/data parity error is observed */
+#define IFC_GPCM_ERATTR2_PERR_BEAT		0x00000C00
+/* Parity Error on byte */
+#define IFC_GPCM_ERATTR2_PERR_BYTE		0x000000F0
+/* Parity Error reported in addr or data phase */
+#define IFC_GPCM_ERATTR2_PERR_DATA_PHASE	0x00000001
+
+/*
+ * GPCM Status Register (GPCM_STAT)
+ */
+#define IFC_GPCM_STAT_BSY		0x80000000  /* GPCM is busy */
+
+/*
+ * IFC Controller NAND Machine registers
+ */
+struct fsl_ifc_nand {
+	__be32 ncfgr;
+	u32 res1[0x4];
+	__be32 nand_fcr0;
+	__be32 nand_fcr1;
+	u32 res2[0x8];
+	__be32 row0;
+	u32 res3;
+	__be32 col0;
+	u32 res4;
+	__be32 row1;
+	u32 res5;
+	__be32 col1;
+	u32 res6;
+	__be32 row2;
+	u32 res7;
+	__be32 col2;
+	u32 res8;
+	__be32 row3;
+	u32 res9;
+	__be32 col3;
+	u32 res10[0x24];
+	__be32 nand_fbcr;
+	u32 res11;
+	__be32 nand_fir0;
+	__be32 nand_fir1;
+	__be32 nand_fir2;
+	u32 res12[0x10];
+	__be32 nand_csel;
+	u32 res13;
+	__be32 nandseq_strt;
+	u32 res14;
+	__be32 nand_evter_stat;
+	u32 res15;
+	__be32 pgrdcmpl_evt_stat;
+	u32 res16[0x2];
+	__be32 nand_evter_en;
+	u32 res17[0x2];
+	__be32 nand_evter_intr_en;
+	u32 res18[0x2];
+	__be32 nand_erattr0;
+	__be32 nand_erattr1;
+	u32 res19[0x10];
+	__be32 nand_fsr;
+	u32 res20;
+	__be32 nand_eccstat[4];
+	u32 res21[0x20];
+	__be32 nanndcr;
+	u32 res22[0x2];
+	__be32 nand_autoboot_trgr;
+	u32 res23;
+	__be32 nand_mdr;
+	u32 res24[0x5C];
+};
+
+/*
+ * IFC controller NOR Machine registers
+ */
+struct fsl_ifc_nor {
+	__be32 nor_evter_stat;
+	u32 res1[0x2];
+	__be32 nor_evter_en;
+	u32 res2[0x2];
+	__be32 nor_evter_intr_en;
+	u32 res3[0x2];
+	__be32 nor_erattr0;
+	__be32 nor_erattr1;
+	__be32 nor_erattr2;
+	u32 res4[0x4];
+	__be32 norcr;
+	u32 res5[0xEF];
+};
+
+/*
+ * IFC controller GPCM Machine registers
+ */
+struct fsl_ifc_gpcm {
+	__be32 gpcm_evter_stat;
+	u32 res1[0x2];
+	__be32 gpcm_evter_en;
+	u32 res2[0x2];
+	__be32 gpcm_evter_intr_en;
+	u32 res3[0x2];
+	__be32 gpcm_erattr0;
+	__be32 gpcm_erattr1;
+	__be32 gpcm_erattr2;
+	__be32 gpcm_stat;
+	u32 res4[0x1F3];
+};
+
+/*
+ * IFC Controller Registers
+ */
+struct fsl_ifc_regs {
+	__be32 ifc_rev;
+	u32 res1[0x2];
+	struct {
+		__be32 cspr_ext;
+		__be32 cspr;
+		u32 res2;
+	} cspr_cs[FSL_IFC_BANK_COUNT];
+	u32 res3[0x19];
+	struct {
+		__be32 amask;
+		u32 res4[0x2];
+	} amask_cs[FSL_IFC_BANK_COUNT];
+	u32 res5[0x17];
+	struct {
+		__be32 csor_ext;
+		__be32 csor;
+		u32 res6;
+	} csor_cs[FSL_IFC_BANK_COUNT];
+	u32 res7[0x19];
+	struct {
+		__be32 ftim[4];
+		u32 res8[0x8];
+	} ftim_cs[FSL_IFC_BANK_COUNT];
+	u32 res9[0x60];
+	__be32 rb_stat;
+	u32 res10[0x2];
+	__be32 ifc_gcr;
+	u32 res11[0x2];
+	__be32 cm_evter_stat;
+	u32 res12[0x2];
+	__be32 cm_evter_en;
+	u32 res13[0x2];
+	__be32 cm_evter_intr_en;
+	u32 res14[0x2];
+	__be32 cm_erattr0;
+	__be32 cm_erattr1;
+	u32 res15[0x2];
+	__be32 ifc_ccr;
+	__be32 ifc_csr;
+	u32 res16[0x2EB];
+	struct fsl_ifc_nand ifc_nand;
+	struct fsl_ifc_nor ifc_nor;
+	struct fsl_ifc_gpcm ifc_gpcm;
+};
+
+extern unsigned int convert_ifc_address(phys_addr_t addr_base);
+extern int fsl_ifc_find(phys_addr_t addr_base);
+
+/* overview of the fsl ifc controller */
+
+struct fsl_ifc_ctrl {
+	/* device info */
+	struct device			*dev;
+	struct fsl_ifc_regs __iomem	*regs;
+	int				irq;
+	int				nand_irq;
+	spinlock_t			lock;
+	void				*nand;
+
+	u32 nand_stat;
+	wait_queue_head_t nand_wait;
+};
+
+extern struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
+
+
+#endif /* __ASM_FSL_IFC_H */
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index f4233b195dab..e6141be2fad5 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -92,6 +92,7 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
  * STUB   - The ftrace_ops is just a place holder.
  * INITIALIZED - The ftrace_ops has already been initialized (first use time
  *            register_ftrace_function() is called, it will initialized the ops)
+ * DELETED - The ops are being deleted, do not let them be registered again.
  */
 enum {
 	FTRACE_OPS_FL_ENABLED			= 1 << 0,
@@ -103,13 +104,26 @@ enum {
 	FTRACE_OPS_FL_RECURSION_SAFE		= 1 << 6,
 	FTRACE_OPS_FL_STUB			= 1 << 7,
 	FTRACE_OPS_FL_INITIALIZED		= 1 << 8,
+	FTRACE_OPS_FL_DELETED			= 1 << 9,
 };
 
+/*
+ * Note, ftrace_ops can be referenced outside of RCU protection.
+ * (Although, for perf, the control ops prevent that). If ftrace_ops is
+ * allocated and not part of kernel core data, the unregistering of it will
+ * perform a scheduling on all CPUs to make sure that there are no more users.
+ * Depending on the load of the system that may take a bit of time.
+ *
+ * Any private data added must also take care not to be freed and if private
+ * data is added to a ftrace_ops that is in core code, the user of the
+ * ftrace_ops must perform a schedule_on_each_cpu() before freeing it.
+ */
 struct ftrace_ops {
 	ftrace_func_t			func;
 	struct ftrace_ops		*next;
 	unsigned long			flags;
 	int __percpu			*disabled;
+	void				*private;
 #ifdef CONFIG_DYNAMIC_FTRACE
 	struct ftrace_hash		*notrace_hash;
 	struct ftrace_hash		*filter_hash;
diff --git a/include/linux/futex.h b/include/linux/futex.h
index b0d95cac826e..6435f46d6e13 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -55,7 +55,11 @@ union futex_key {
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
 extern void exit_pi_state_list(struct task_struct *curr);
+#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
+#define futex_cmpxchg_enabled 1
+#else
 extern int futex_cmpxchg_enabled;
+#endif
 #else
 static inline void exit_robust_list(struct task_struct *curr)
 {
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 0437439bc047..39b81dc7d01a 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -123,6 +123,10 @@ struct vm_area_struct;
 			 __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
 			 __GFP_NO_KSWAPD)
 
+/*
+ * GFP_THISNODE does not perform any reclaim, you most likely want to
+ * use __GFP_THISNODE to allocate from a given node without fallback!
+ */
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE	(__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
 #else
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index b581b13d29d9..85aa5d0b9357 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -3,7 +3,7 @@
 
 #include <linux/errno.h>
 
-/* see Documentation/gpio.txt */
+/* see Documentation/gpio/gpio-legacy.txt */
 
 /* make these flag values available regardless of GPIO kconfig options */
 #define GPIOF_DIR_OUT	(0 << 0)
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 7a8144fef406..bed128e8f4b1 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -5,7 +5,6 @@
 #include <linux/kernel.h>
 
 struct device;
-struct gpio_chip;
 
 /**
  * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
@@ -36,6 +35,7 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
 int gpiod_get_direction(const struct gpio_desc *desc);
 int gpiod_direction_input(struct gpio_desc *desc);
 int gpiod_direction_output(struct gpio_desc *desc, int value);
+int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
 
 /* Value get/set from non-sleeping context */
 int gpiod_get_value(const struct gpio_desc *desc);
@@ -59,7 +59,6 @@ int gpiod_to_irq(const struct gpio_desc *desc);
 /* Convert between the old gpio_ and new gpiod_ interfaces */
 struct gpio_desc *gpio_to_desc(unsigned gpio);
 int desc_to_gpio(const struct gpio_desc *desc);
-struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
 
 #else /* CONFIG_GPIOLIB */
 
@@ -121,6 +120,12 @@ static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
 	WARN_ON(1);
 	return -ENOSYS;
 }
+static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -ENOSYS;
+}
 
 
 static inline int gpiod_get_value(const struct gpio_desc *desc)
@@ -207,12 +212,6 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
 	WARN_ON(1);
 	return -EINVAL;
 }
-static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
-{
-	/* GPIO can never have been requested */
-	WARN_ON(1);
-	return ERR_PTR(-ENODEV);
-}
 
 
 #endif /* CONFIG_GPIOLIB */
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index a3e181e09636..9fe283642253 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -10,6 +10,8 @@ struct of_phandle_args;
 struct device_node;
 struct seq_file;
 
+#ifdef CONFIG_GPIOLIB
+
 /**
  * struct gpio_chip - abstract a GPIO controller
  * @label: for diagnostics
@@ -129,6 +131,11 @@ extern struct gpio_chip *gpiochip_find(void *data,
 int gpiod_lock_as_irq(struct gpio_desc *desc);
 void gpiod_unlock_as_irq(struct gpio_desc *desc);
 
+struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
+
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
+				    u16 hwnum);
+
 enum gpio_lookup_flags {
 	GPIO_ACTIVE_HIGH = (0 << 0),
 	GPIO_ACTIVE_LOW = (1 << 0),
@@ -183,4 +190,15 @@ struct gpiod_lookup_table {
 
 void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
 
+#else /* CONFIG_GPIOLIB */
+
+static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return ERR_PTR(-ENODEV);
+}
+
+#endif /* CONFIG_GPIOLIB */
+
 #endif
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 12d5f972f23f..cba442ec3c66 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -9,6 +9,7 @@
 
 
 extern void synchronize_irq(unsigned int irq);
+extern void synchronize_hardirq(unsigned int irq);
 
 #if defined(CONFIG_TINY_RCU)
 
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index b914ca3f57ba..b70cfd7ff29c 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -51,13 +51,15 @@ struct hid_sensor_hub_attribute_info {
  * @hdev:		Stores the hid instance.
  * @vendor_id:		Vendor id of hub device.
  * @product_id:		Product id of hub device.
- * @ref_cnt:		Number of MFD clients have opened this device
+ * @start_collection_index: Starting index for a phy type collection
+ * @end_collection_index: Last index for a phy type collection
  */
 struct hid_sensor_hub_device {
 	struct hid_device *hdev;
 	u32 vendor_id;
 	u32 product_id;
-	int ref_cnt;
+	int start_collection_index;
+	int end_collection_index;
 };
 
 /**
@@ -218,4 +220,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
 int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
 					int *val1, int *val2);
 
+int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev,
+				u32 report_id, int field_index, u32 usage_id);
+
 #endif
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h
index beaf965621c1..14ead9e8eda8 100644
--- a/include/linux/hid-sensor-ids.h
+++ b/include/linux/hid-sensor-ids.h
@@ -33,6 +33,16 @@
 #define HID_USAGE_SENSOR_DATA_LIGHT				0x2004d0
 #define HID_USAGE_SENSOR_LIGHT_ILLUM				0x2004d1
 
+/* PROX (200011) */
+#define HID_USAGE_SENSOR_PROX                                   0x200011
+#define HID_USAGE_SENSOR_DATA_PRESENCE                          0x2004b0
+#define HID_USAGE_SENSOR_HUMAN_PRESENCE                         0x2004b1
+
+/* Pressure (200031) */
+#define HID_USAGE_SENSOR_PRESSURE                               0x200031
+#define HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE              0x200430
+#define HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE                   0x200431
+
 /* Gyro 3D: (200076) */
 #define HID_USAGE_SENSOR_GYRO_3D				0x200076
 #define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY			0x200456
@@ -130,15 +140,15 @@
 #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS		0x1000
 
 /* Power state enumerations */
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM		0x00
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM		0x01
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM		0x02
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM	0x03
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM	0x04
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM		0x05
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM	0x200850
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM	0x200851
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM	0x200852
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM 0x200853
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM 0x200854
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM	0x200855
 
 /* Report State enumerations */
-#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM		0x00
-#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM		0x01
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM	0x200840
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM	0x200841
 
 #endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 31b9d299ef6c..5eb282e0dff7 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -508,9 +508,6 @@ struct hid_device {							/* device report descriptor */
 				  struct hid_usage *, __s32);
 	void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 
-	/* handler for raw input (Get_Report) data, used by hidraw */
-	int (*hid_get_raw_report) (struct hid_device *, unsigned char, __u8 *, size_t, unsigned char);
-
 	/* handler for raw output data, used by hidraw */
 	int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
 
@@ -675,11 +672,12 @@ struct hid_driver {
  * @stop: called on remove
  * @open: called by input layer on open
  * @close: called by input layer on close
- * @hidinput_input_event: event input event (e.g. ff or leds)
  * @parse: this method is called only once to parse the device data,
  *	   shouldn't allocate anything to not leak memory
  * @request: send report request to device (e.g. feature report)
  * @wait: wait for buffered io to complete (send/recv reports)
+ * @raw_request: send raw report request to device (e.g. feature report)
+ * @output_report: send output report to device
  * @idle: send idle request to device
  */
 struct hid_ll_driver {
@@ -691,17 +689,20 @@ struct hid_ll_driver {
 
 	int (*power)(struct hid_device *hdev, int level);
 
-	int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
-			unsigned int code, int value);
-
 	int (*parse)(struct hid_device *hdev);
 
 	void (*request)(struct hid_device *hdev,
 			struct hid_report *report, int reqtype);
 
 	int (*wait)(struct hid_device *hdev);
-	int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
 
+	int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
+			    __u8 *buf, size_t len, unsigned char rtype,
+			    int reqtype);
+
+	int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
+
+	int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
 };
 
 #define	PM_HINT_FULLON	1<<5
@@ -752,6 +753,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
 __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
 void hid_output_report(struct hid_report *report, __u8 *data);
+void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype);
 u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
@@ -964,7 +966,71 @@ static inline void hid_hw_request(struct hid_device *hdev,
 				  struct hid_report *report, int reqtype)
 {
 	if (hdev->ll_driver->request)
-		hdev->ll_driver->request(hdev, report, reqtype);
+		return hdev->ll_driver->request(hdev, report, reqtype);
+
+	__hid_request(hdev, report, reqtype);
+}
+
+/**
+ * hid_hw_raw_request - send report request to device
+ *
+ * @hdev: hid device
+ * @reportnum: report ID
+ * @buf: in/out data to transfer
+ * @len: length of buf
+ * @rtype: HID report type
+ * @reqtype: HID_REQ_GET_REPORT or HID_REQ_SET_REPORT
+ *
+ * @return: count of data transfered, negative if error
+ *
+ * Same behavior as hid_hw_request, but with raw buffers instead.
+ */
+static inline int hid_hw_raw_request(struct hid_device *hdev,
+				  unsigned char reportnum, __u8 *buf,
+				  size_t len, unsigned char rtype, int reqtype)
+{
+	if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
+		return -EINVAL;
+
+	return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
+						    rtype, reqtype);
+}
+
+/**
+ * hid_hw_output_report - send output report to device
+ *
+ * @hdev: hid device
+ * @buf: raw data to transfer
+ * @len: length of buf
+ *
+ * @return: count of data transfered, negative if error
+ */
+static inline int hid_hw_output_report(struct hid_device *hdev, __u8 *buf,
+					size_t len)
+{
+	if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
+		return -EINVAL;
+
+	if (hdev->ll_driver->output_report)
+		return hdev->ll_driver->output_report(hdev, buf, len);
+
+	return -ENOSYS;
+}
+
+/**
+ * hid_output_raw_report - send an output or a feature report to the device
+ *
+ * @hdev: hid device
+ * @buf: raw data to transfer
+ * @len: length of buf
+ * @report_type: HID_FEATURE_REPORT or HID_OUTPUT_REPORT
+ *
+ * @return: count of data transfered, negative if error
+ */
+static inline int hid_output_raw_report(struct hid_device *hdev, __u8 *buf,
+					size_t len, unsigned char report_type)
+{
+	return hdev->hid_output_raw_report(hdev, buf, len, report_type);
 }
 
 /**
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3af847273277..d2b52999e771 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -136,6 +136,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp);
 u32 host1x_syncpt_read_min(struct host1x_syncpt *sp);
 u32 host1x_syncpt_read_max(struct host1x_syncpt *sp);
 int host1x_syncpt_incr(struct host1x_syncpt *sp);
+u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
 int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
 		       u32 *value);
 struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
index 0dca785288cf..39bfd5b89077 100644
--- a/include/linux/hsi/hsi.h
+++ b/include/linux/hsi/hsi.h
@@ -178,7 +178,7 @@ static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv)
  * @complete: Transfer completion callback
  * @destructor: Destructor to free resources when flushing
  * @status: Status of the transfer when completed
- * @actual_len: Actual length of data transfered on completion
+ * @actual_len: Actual length of data transferred on completion
  * @channel: Channel were to TX/RX the message
  * @ttype: Transfer type (TX if set, RX otherwise)
  * @break_frame: if true HSI will send/receive a break frame. Data buffers are
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index db512014e061..b826239bdce0 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -157,46 +157,6 @@ static inline int hpage_nr_pages(struct page *page)
 		return HPAGE_PMD_NR;
 	return 1;
 }
-/*
- * compound_trans_head() should be used instead of compound_head(),
- * whenever the "page" passed as parameter could be the tail of a
- * transparent hugepage that could be undergoing a
- * __split_huge_page_refcount(). The page structure layout often
- * changes across releases and it makes extensive use of unions. So if
- * the page structure layout will change in a way that
- * page->first_page gets clobbered by __split_huge_page_refcount, the
- * implementation making use of smp_rmb() will be required.
- *
- * Currently we define compound_trans_head as compound_head, because
- * page->private is in the same union with page->first_page, and
- * page->private isn't clobbered. However this also means we're
- * currently leaving dirt into the page->private field of anonymous
- * pages resulting from a THP split, instead of setting page->private
- * to zero like for every other page that has PG_private not set. But
- * anonymous pages don't use page->private so this is not a problem.
- */
-#if 0
-/* This will be needed if page->private will be clobbered in split_huge_page */
-static inline struct page *compound_trans_head(struct page *page)
-{
-	if (PageTail(page)) {
-		struct page *head;
-		head = page->first_page;
-		smp_rmb();
-		/*
-		 * head may be a dangling pointer.
-		 * __split_huge_page_refcount clears PageTail before
-		 * overwriting first_page, so if PageTail is still
-		 * there it means the head pointer isn't dangling.
-		 */
-		if (PageTail(page))
-			return head;
-	}
-	return page;
-}
-#else
-#define compound_trans_head(page) compound_head(page)
-#endif
 
 extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
 				unsigned long addr, pmd_t pmd, pmd_t *pmdp);
@@ -226,7 +186,6 @@ static inline int split_huge_page(struct page *page)
 	do { } while (0)
 #define split_huge_page_pmd_mm(__mm, __address, __pmd)	\
 	do { } while (0)
-#define compound_trans_head(page) compound_head(page)
 static inline int hugepage_madvise(struct vm_area_struct *vma,
 				   unsigned long *vm_flags, int advice)
 {
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 8c43cc469d78..1ae16673c672 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -6,6 +6,8 @@
 #include <linux/fs.h>
 #include <linux/hugetlb_inline.h>
 #include <linux/cgroup.h>
+#include <linux/list.h>
+#include <linux/kref.h>
 
 struct ctl_table;
 struct user_struct;
@@ -23,6 +25,14 @@ struct hugepage_subpool {
 	long max_hpages, used_hpages;
 };
 
+struct resv_map {
+	struct kref refs;
+	spinlock_t lock;
+	struct list_head regions;
+};
+extern struct resv_map *resv_map_alloc(void);
+void resv_map_release(struct kref *ref);
+
 extern spinlock_t hugetlb_lock;
 extern int hugetlb_max_hstate __read_mostly;
 #define for_each_hstate(h) \
@@ -31,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 *);
@@ -99,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_cgroup.h b/include/linux/hugetlb_cgroup.h
index 787bba3bf552..0129f89cf98d 100644
--- a/include/linux/hugetlb_cgroup.h
+++ b/include/linux/hugetlb_cgroup.h
@@ -49,7 +49,7 @@ int set_hugetlb_cgroup(struct page *page, struct hugetlb_cgroup *h_cg)
 
 static inline bool hugetlb_cgroup_disabled(void)
 {
-	if (hugetlb_subsys.disabled)
+	if (hugetlb_cgrp_subsys.disabled)
 		return true;
 	return false;
 }
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 344883dce584..330ec44de575 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -25,328 +25,11 @@
 #ifndef _HYPERV_H
 #define _HYPERV_H
 
-#include <linux/types.h>
-
-/*
- * Framework version for util services.
- */
-#define UTIL_FW_MINOR  0
-
-#define UTIL_WS2K8_FW_MAJOR  1
-#define UTIL_WS2K8_FW_VERSION     (UTIL_WS2K8_FW_MAJOR << 16 | UTIL_FW_MINOR)
-
-#define UTIL_FW_MAJOR  3
-#define UTIL_FW_VERSION     (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
-
-
-/*
- * Implementation of host controlled snapshot of the guest.
- */
-
-#define VSS_OP_REGISTER 128
-
-enum hv_vss_op {
-	VSS_OP_CREATE = 0,
-	VSS_OP_DELETE,
-	VSS_OP_HOT_BACKUP,
-	VSS_OP_GET_DM_INFO,
-	VSS_OP_BU_COMPLETE,
-	/*
-	 * Following operations are only supported with IC version >= 5.0
-	 */
-	VSS_OP_FREEZE, /* Freeze the file systems in the VM */
-	VSS_OP_THAW, /* Unfreeze the file systems */
-	VSS_OP_AUTO_RECOVER,
-	VSS_OP_COUNT /* Number of operations, must be last */
-};
-
-
-/*
- * Header for all VSS messages.
- */
-struct hv_vss_hdr {
-	__u8 operation;
-	__u8 reserved[7];
-} __attribute__((packed));
-
-
-/*
- * Flag values for the hv_vss_check_feature. Linux supports only
- * one value.
- */
-#define VSS_HBU_NO_AUTO_RECOVERY	0x00000005
-
-struct hv_vss_check_feature {
-	__u32 flags;
-} __attribute__((packed));
-
-struct hv_vss_check_dm_info {
-	__u32 flags;
-} __attribute__((packed));
-
-struct hv_vss_msg {
-	union {
-		struct hv_vss_hdr vss_hdr;
-		int error;
-	};
-	union {
-		struct hv_vss_check_feature vss_cf;
-		struct hv_vss_check_dm_info dm_info;
-	};
-} __attribute__((packed));
-
-/*
- * An implementation of HyperV key value pair (KVP) functionality for Linux.
- *
- *
- * Copyright (C) 2010, Novell, Inc.
- * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
- *
- */
-
-/*
- * Maximum value size - used for both key names and value data, and includes
- * any applicable NULL terminators.
- *
- * Note:  This limit is somewhat arbitrary, but falls easily within what is
- * supported for all native guests (back to Win 2000) and what is reasonable
- * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
- * limited to 255 character key names.
- *
- * MSDN recommends not storing data values larger than 2048 bytes in the
- * registry.
- *
- * Note:  This value is used in defining the KVP exchange message - this value
- * cannot be modified without affecting the message size and compatibility.
- */
-
-/*
- * bytes, including any null terminators
- */
-#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
-
-
-/*
- * Maximum key size - the registry limit for the length of an entry name
- * is 256 characters, including the null terminator
- */
-
-#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
-
-/*
- * In Linux, we implement the KVP functionality in two components:
- * 1) The kernel component which is packaged as part of the hv_utils driver
- * is responsible for communicating with the host and responsible for
- * implementing the host/guest protocol. 2) A user level daemon that is
- * responsible for data gathering.
- *
- * Host/Guest Protocol: The host iterates over an index and expects the guest
- * to assign a key name to the index and also return the value corresponding to
- * the key. The host will have atmost one KVP transaction outstanding at any
- * given point in time. The host side iteration stops when the guest returns
- * an error. Microsoft has specified the following mapping of key names to
- * host specified index:
- *
- *	Index		Key Name
- *	0		FullyQualifiedDomainName
- *	1		IntegrationServicesVersion
- *	2		NetworkAddressIPv4
- *	3		NetworkAddressIPv6
- *	4		OSBuildNumber
- *	5		OSName
- *	6		OSMajorVersion
- *	7		OSMinorVersion
- *	8		OSVersion
- *	9		ProcessorArchitecture
- *
- * The Windows host expects the Key Name and Key Value to be encoded in utf16.
- *
- * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
- * data gathering functionality in a user mode daemon. The user level daemon
- * is also responsible for binding the key name to the index as well. The
- * kernel and user-level daemon communicate using a connector channel.
- *
- * The user mode component first registers with the
- * the kernel component. Subsequently, the kernel component requests, data
- * for the specified keys. In response to this message the user mode component
- * fills in the value corresponding to the specified key. We overload the
- * sequence field in the cn_msg header to define our KVP message types.
- *
- *
- * The kernel component simply acts as a conduit for communication between the
- * Windows host and the user-level daemon. The kernel component passes up the
- * index received from the Host to the user-level daemon. If the index is
- * valid (supported), the corresponding key as well as its
- * value (both are strings) is returned. If the index is invalid
- * (not supported), a NULL key string is returned.
- */
-
-
-/*
- * Registry value types.
- */
-
-#define REG_SZ 1
-#define REG_U32 4
-#define REG_U64 8
-
-/*
- * As we look at expanding the KVP functionality to include
- * IP injection functionality, we need to maintain binary
- * compatibility with older daemons.
- *
- * The KVP opcodes are defined by the host and it was unfortunate
- * that I chose to treat the registration operation as part of the
- * KVP operations defined by the host.
- * Here is the level of compatibility
- * (between the user level daemon and the kernel KVP driver) that we
- * will implement:
- *
- * An older daemon will always be supported on a newer driver.
- * A given user level daemon will require a minimal version of the
- * kernel driver.
- * If we cannot handle the version differences, we will fail gracefully
- * (this can happen when we have a user level daemon that is more
- * advanced than the KVP driver.
- *
- * We will use values used in this handshake for determining if we have
- * workable user level daemon and the kernel driver. We begin by taking the
- * registration opcode out of the KVP opcode namespace. We will however,
- * maintain compatibility with the existing user-level daemon code.
- */
-
-/*
- * Daemon code not supporting IP injection (legacy daemon).
- */
-
-#define KVP_OP_REGISTER	4
-
-/*
- * Daemon code supporting IP injection.
- * The KVP opcode field is used to communicate the
- * registration information; so define a namespace that
- * will be distinct from the host defined KVP opcode.
- */
-
-#define KVP_OP_REGISTER1 100
-
-enum hv_kvp_exchg_op {
-	KVP_OP_GET = 0,
-	KVP_OP_SET,
-	KVP_OP_DELETE,
-	KVP_OP_ENUMERATE,
-	KVP_OP_GET_IP_INFO,
-	KVP_OP_SET_IP_INFO,
-	KVP_OP_COUNT /* Number of operations, must be last. */
-};
-
-enum hv_kvp_exchg_pool {
-	KVP_POOL_EXTERNAL = 0,
-	KVP_POOL_GUEST,
-	KVP_POOL_AUTO,
-	KVP_POOL_AUTO_EXTERNAL,
-	KVP_POOL_AUTO_INTERNAL,
-	KVP_POOL_COUNT /* Number of pools, must be last. */
-};
-
-/*
- * Some Hyper-V status codes.
- */
+#include <uapi/linux/hyperv.h>
 
-#define HV_S_OK				0x00000000
-#define HV_E_FAIL			0x80004005
-#define HV_S_CONT			0x80070103
-#define HV_ERROR_NOT_SUPPORTED		0x80070032
-#define HV_ERROR_MACHINE_LOCKED		0x800704F7
-#define HV_ERROR_DEVICE_NOT_CONNECTED	0x8007048F
-#define HV_INVALIDARG			0x80070057
-#define HV_GUID_NOTFOUND		0x80041002
-
-#define ADDR_FAMILY_NONE	0x00
-#define ADDR_FAMILY_IPV4	0x01
-#define ADDR_FAMILY_IPV6	0x02
-
-#define MAX_ADAPTER_ID_SIZE	128
-#define MAX_IP_ADDR_SIZE	1024
-#define MAX_GATEWAY_SIZE	512
-
-
-struct hv_kvp_ipaddr_value {
-	__u16	adapter_id[MAX_ADAPTER_ID_SIZE];
-	__u8	addr_family;
-	__u8	dhcp_enabled;
-	__u16	ip_addr[MAX_IP_ADDR_SIZE];
-	__u16	sub_net[MAX_IP_ADDR_SIZE];
-	__u16	gate_way[MAX_GATEWAY_SIZE];
-	__u16	dns_addr[MAX_IP_ADDR_SIZE];
-} __attribute__((packed));
-
-
-struct hv_kvp_hdr {
-	__u8 operation;
-	__u8 pool;
-	__u16 pad;
-} __attribute__((packed));
-
-struct hv_kvp_exchg_msg_value {
-	__u32 value_type;
-	__u32 key_size;
-	__u32 value_size;
-	__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
-	union {
-		__u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
-		__u32 value_u32;
-		__u64 value_u64;
-	};
-} __attribute__((packed));
-
-struct hv_kvp_msg_enumerate {
-	__u32 index;
-	struct hv_kvp_exchg_msg_value data;
-} __attribute__((packed));
-
-struct hv_kvp_msg_get {
-	struct hv_kvp_exchg_msg_value data;
-};
-
-struct hv_kvp_msg_set {
-	struct hv_kvp_exchg_msg_value data;
-};
-
-struct hv_kvp_msg_delete {
-	__u32 key_size;
-	__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
-};
-
-struct hv_kvp_register {
-	__u8 version[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
-};
-
-struct hv_kvp_msg {
-	union {
-		struct hv_kvp_hdr	kvp_hdr;
-		int error;
-	};
-	union {
-		struct hv_kvp_msg_get		kvp_get;
-		struct hv_kvp_msg_set		kvp_set;
-		struct hv_kvp_msg_delete	kvp_delete;
-		struct hv_kvp_msg_enumerate	kvp_enum_data;
-		struct hv_kvp_ipaddr_value      kvp_ip_val;
-		struct hv_kvp_register		kvp_register;
-	} body;
-} __attribute__((packed));
-
-struct hv_kvp_ip_msg {
-	__u8 operation;
-	__u8 pool;
-	struct hv_kvp_ipaddr_value      kvp_ip_val;
-} __attribute__((packed));
-
-#ifdef __KERNEL__
+#include <linux/types.h>
 #include <linux/scatterlist.h>
 #include <linux/list.h>
-#include <linux/uuid.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/completion.h>
@@ -1043,6 +726,10 @@ struct vmbus_channel {
 	 * This will be NULL for the primary channel.
 	 */
 	struct vmbus_channel *primary_channel;
+	/*
+	 * Support per-channel state for use by vmbus drivers.
+	 */
+	void *per_channel_state;
 };
 
 static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
@@ -1050,6 +737,16 @@ static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
 	c->batched_reading = state;
 }
 
+static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
+{
+	c->per_channel_state = s;
+}
+
+static inline void *get_per_channel_state(struct vmbus_channel *c)
+{
+	return c->per_channel_state;
+}
+
 void vmbus_onmessage(void *context);
 
 int vmbus_request_offers(void);
@@ -1118,7 +815,7 @@ extern int vmbus_open(struct vmbus_channel *channel,
 extern void vmbus_close(struct vmbus_channel *channel);
 
 extern int vmbus_sendpacket(struct vmbus_channel *channel,
-				  const void *buffer,
+				  void *buffer,
 				  u32 bufferLen,
 				  u64 requestid,
 				  enum vmbus_packet_type type,
@@ -1352,6 +1049,17 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
 		}
 
 /*
+ * Guest File Copy Service
+ * {34D14BE3-DEE4-41c8-9AE7-6B174977C192}
+ */
+
+#define HV_FCOPY_GUID \
+	.guid = { \
+			0xE3, 0x4B, 0xD1, 0x34, 0xE4, 0xDE, 0xC8, 0x41, \
+			0x9A, 0xE7, 0x6B, 0x17, 0x49, 0x77, 0xC1, 0x92 \
+		}
+
+/*
  * Common header for Hyper-V ICs
  */
 
@@ -1459,11 +1167,12 @@ int hv_vss_init(struct hv_util_service *);
 void hv_vss_deinit(void);
 void hv_vss_onchannelcallback(void *);
 
+extern struct resource hyperv_mmio;
+
 /*
  * Negotiated version with the Host.
  */
 
 extern __u32 vmbus_proto_version;
 
-#endif /* __KERNEL__ */
 #endif /* _HYPERV_H */
diff --git a/include/linux/i2c/adp5588.h b/include/linux/i2c/adp5588.h
index d8341cb47b60..c2153049cfbd 100644
--- a/include/linux/i2c/adp5588.h
+++ b/include/linux/i2c/adp5588.h
@@ -161,10 +161,10 @@ struct adp5588_gpio_platform_data {
 	unsigned irq_base;	/* interrupt base # */
 	unsigned pullup_dis_mask; /* Pull-Up Disable Mask */
 	int	(*setup)(struct i2c_client *client,
-				int gpio, unsigned ngpio,
+				unsigned gpio, unsigned ngpio,
 				void *context);
 	int	(*teardown)(struct i2c_client *client,
-				int gpio, unsigned ngpio,
+				unsigned gpio, unsigned ngpio,
 				void *context);
 	void	*context;
 };
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 871a213a8477..f669585c4fc5 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -82,9 +82,9 @@ int idr_for_each(struct idr *idp,
 void *idr_get_next(struct idr *idp, int *nextid);
 void *idr_replace(struct idr *idp, void *ptr, int id);
 void idr_remove(struct idr *idp, int id);
-void idr_free(struct idr *idp, int id);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
+bool idr_is_empty(struct idr *idp);
 
 /**
  * idr_preload_end - end preload section started with idr_preload()
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index e526a8cecb70..5f349355ee54 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc)
 }
 
 /**
+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
+ * @fc: frame control field in little-endian byteorder
+ */
+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
+{
+	/* IEEE 802.11-2012, definition of "bufferable management frame";
+	 * note that this ignores the IBSS special case. */
+	return ieee80211_is_mgmt(fc) &&
+	       (ieee80211_is_action(fc) ||
+		ieee80211_is_disassoc(fc) ||
+		ieee80211_is_deauth(fc));
+}
+
+/**
  * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
  */
@@ -1636,51 +1650,22 @@ enum ieee80211_reasoncode {
 enum ieee80211_eid {
 	WLAN_EID_SSID = 0,
 	WLAN_EID_SUPP_RATES = 1,
-	WLAN_EID_FH_PARAMS = 2,
+	WLAN_EID_FH_PARAMS = 2, /* reserved now */
 	WLAN_EID_DS_PARAMS = 3,
 	WLAN_EID_CF_PARAMS = 4,
 	WLAN_EID_TIM = 5,
 	WLAN_EID_IBSS_PARAMS = 6,
-	WLAN_EID_CHALLENGE = 16,
-
 	WLAN_EID_COUNTRY = 7,
 	WLAN_EID_HP_PARAMS = 8,
 	WLAN_EID_HP_TABLE = 9,
 	WLAN_EID_REQUEST = 10,
-
 	WLAN_EID_QBSS_LOAD = 11,
 	WLAN_EID_EDCA_PARAM_SET = 12,
 	WLAN_EID_TSPEC = 13,
 	WLAN_EID_TCLAS = 14,
 	WLAN_EID_SCHEDULE = 15,
-	WLAN_EID_TS_DELAY = 43,
-	WLAN_EID_TCLAS_PROCESSING = 44,
-	WLAN_EID_QOS_CAPA = 46,
-	/* 802.11z */
-	WLAN_EID_LINK_ID = 101,
-	/* 802.11s */
-	WLAN_EID_MESH_CONFIG = 113,
-	WLAN_EID_MESH_ID = 114,
-	WLAN_EID_LINK_METRIC_REPORT = 115,
-	WLAN_EID_CONGESTION_NOTIFICATION = 116,
-	WLAN_EID_PEER_MGMT = 117,
-	WLAN_EID_CHAN_SWITCH_PARAM = 118,
-	WLAN_EID_MESH_AWAKE_WINDOW = 119,
-	WLAN_EID_BEACON_TIMING = 120,
-	WLAN_EID_MCCAOP_SETUP_REQ = 121,
-	WLAN_EID_MCCAOP_SETUP_RESP = 122,
-	WLAN_EID_MCCAOP_ADVERT = 123,
-	WLAN_EID_MCCAOP_TEARDOWN = 124,
-	WLAN_EID_GANN = 125,
-	WLAN_EID_RANN = 126,
-	WLAN_EID_PREQ = 130,
-	WLAN_EID_PREP = 131,
-	WLAN_EID_PERR = 132,
-	WLAN_EID_PXU = 137,
-	WLAN_EID_PXUC = 138,
-	WLAN_EID_AUTH_MESH_PEER_EXCH = 139,
-	WLAN_EID_MIC = 140,
-
+	WLAN_EID_CHALLENGE = 16,
+	/* 17-31 reserved for challenge text extension */
 	WLAN_EID_PWR_CONSTRAINT = 32,
 	WLAN_EID_PWR_CAPABILITY = 33,
 	WLAN_EID_TPC_REQUEST = 34,
@@ -1691,66 +1676,114 @@ enum ieee80211_eid {
 	WLAN_EID_MEASURE_REPORT = 39,
 	WLAN_EID_QUIET = 40,
 	WLAN_EID_IBSS_DFS = 41,
-
 	WLAN_EID_ERP_INFO = 42,
-	WLAN_EID_EXT_SUPP_RATES = 50,
-
+	WLAN_EID_TS_DELAY = 43,
+	WLAN_EID_TCLAS_PROCESSING = 44,
 	WLAN_EID_HT_CAPABILITY = 45,
-	WLAN_EID_HT_OPERATION = 61,
-	WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
-
+	WLAN_EID_QOS_CAPA = 46,
+	/* 47 reserved for Broadcom */
 	WLAN_EID_RSN = 48,
-	WLAN_EID_MMIE = 76,
-	WLAN_EID_VENDOR_SPECIFIC = 221,
-	WLAN_EID_QOS_PARAMETER = 222,
-
+	WLAN_EID_802_15_COEX = 49,
+	WLAN_EID_EXT_SUPP_RATES = 50,
 	WLAN_EID_AP_CHAN_REPORT = 51,
 	WLAN_EID_NEIGHBOR_REPORT = 52,
 	WLAN_EID_RCPI = 53,
+	WLAN_EID_MOBILITY_DOMAIN = 54,
+	WLAN_EID_FAST_BSS_TRANSITION = 55,
+	WLAN_EID_TIMEOUT_INTERVAL = 56,
+	WLAN_EID_RIC_DATA = 57,
+	WLAN_EID_DSE_REGISTERED_LOCATION = 58,
+	WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
+	WLAN_EID_EXT_CHANSWITCH_ANN = 60,
+	WLAN_EID_HT_OPERATION = 61,
+	WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
 	WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
 	WLAN_EID_ANTENNA_INFO = 64,
 	WLAN_EID_RSNI = 65,
 	WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
 	WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
 	WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
+	WLAN_EID_TIME_ADVERTISEMENT = 69,
 	WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
 	WLAN_EID_MULTIPLE_BSSID = 71,
 	WLAN_EID_BSS_COEX_2040 = 72,
 	WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
-	WLAN_EID_EXT_CAPABILITY = 127,
-
-	WLAN_EID_MOBILITY_DOMAIN = 54,
-	WLAN_EID_FAST_BSS_TRANSITION = 55,
-	WLAN_EID_TIMEOUT_INTERVAL = 56,
-	WLAN_EID_RIC_DATA = 57,
 	WLAN_EID_RIC_DESCRIPTOR = 75,
-
-	WLAN_EID_DSE_REGISTERED_LOCATION = 58,
-	WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
-	WLAN_EID_EXT_CHANSWITCH_ANN = 60,
-
-	WLAN_EID_VHT_CAPABILITY = 191,
-	WLAN_EID_VHT_OPERATION = 192,
-	WLAN_EID_OPMODE_NOTIF = 199,
-	WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
-	WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
-	WLAN_EID_EXTENDED_BSS_LOAD = 193,
-	WLAN_EID_VHT_TX_POWER_ENVELOPE = 195,
-	WLAN_EID_AID = 197,
-	WLAN_EID_QUIET_CHANNEL = 198,
-
-	/* 802.11ad */
+	WLAN_EID_MMIE = 76,
+	WLAN_EID_ASSOC_COMEBACK_TIME = 77,
+	WLAN_EID_EVENT_REQUEST = 78,
+	WLAN_EID_EVENT_REPORT = 79,
+	WLAN_EID_DIAGNOSTIC_REQUEST = 80,
+	WLAN_EID_DIAGNOSTIC_REPORT = 81,
+	WLAN_EID_LOCATION_PARAMS = 82,
 	WLAN_EID_NON_TX_BSSID_CAP =  83,
+	WLAN_EID_SSID_LIST = 84,
+	WLAN_EID_MULTI_BSSID_IDX = 85,
+	WLAN_EID_FMS_DESCRIPTOR = 86,
+	WLAN_EID_FMS_REQUEST = 87,
+	WLAN_EID_FMS_RESPONSE = 88,
+	WLAN_EID_QOS_TRAFFIC_CAPA = 89,
+	WLAN_EID_BSS_MAX_IDLE_PERIOD = 90,
+	WLAN_EID_TSF_REQUEST = 91,
+	WLAN_EID_TSF_RESPOSNE = 92,
+	WLAN_EID_WNM_SLEEP_MODE = 93,
+	WLAN_EID_TIM_BCAST_REQ = 94,
+	WLAN_EID_TIM_BCAST_RESP = 95,
+	WLAN_EID_COLL_IF_REPORT = 96,
+	WLAN_EID_CHANNEL_USAGE = 97,
+	WLAN_EID_TIME_ZONE = 98,
+	WLAN_EID_DMS_REQUEST = 99,
+	WLAN_EID_DMS_RESPONSE = 100,
+	WLAN_EID_LINK_ID = 101,
+	WLAN_EID_WAKEUP_SCHEDUL = 102,
+	/* 103 reserved */
+	WLAN_EID_CHAN_SWITCH_TIMING = 104,
+	WLAN_EID_PTI_CONTROL = 105,
+	WLAN_EID_PU_BUFFER_STATUS = 106,
+	WLAN_EID_INTERWORKING = 107,
+	WLAN_EID_ADVERTISEMENT_PROTOCOL = 108,
+	WLAN_EID_EXPEDITED_BW_REQ = 109,
+	WLAN_EID_QOS_MAP_SET = 110,
+	WLAN_EID_ROAMING_CONSORTIUM = 111,
+	WLAN_EID_EMERGENCY_ALERT = 112,
+	WLAN_EID_MESH_CONFIG = 113,
+	WLAN_EID_MESH_ID = 114,
+	WLAN_EID_LINK_METRIC_REPORT = 115,
+	WLAN_EID_CONGESTION_NOTIFICATION = 116,
+	WLAN_EID_PEER_MGMT = 117,
+	WLAN_EID_CHAN_SWITCH_PARAM = 118,
+	WLAN_EID_MESH_AWAKE_WINDOW = 119,
+	WLAN_EID_BEACON_TIMING = 120,
+	WLAN_EID_MCCAOP_SETUP_REQ = 121,
+	WLAN_EID_MCCAOP_SETUP_RESP = 122,
+	WLAN_EID_MCCAOP_ADVERT = 123,
+	WLAN_EID_MCCAOP_TEARDOWN = 124,
+	WLAN_EID_GANN = 125,
+	WLAN_EID_RANN = 126,
+	WLAN_EID_EXT_CAPABILITY = 127,
+	/* 128, 129 reserved for Agere */
+	WLAN_EID_PREQ = 130,
+	WLAN_EID_PREP = 131,
+	WLAN_EID_PERR = 132,
+	/* 133-136 reserved for Cisco */
+	WLAN_EID_PXU = 137,
+	WLAN_EID_PXUC = 138,
+	WLAN_EID_AUTH_MESH_PEER_EXCH = 139,
+	WLAN_EID_MIC = 140,
+	WLAN_EID_DESTINATION_URI = 141,
+	WLAN_EID_UAPSD_COEX = 142,
 	WLAN_EID_WAKEUP_SCHEDULE = 143,
 	WLAN_EID_EXT_SCHEDULE = 144,
 	WLAN_EID_STA_AVAILABILITY = 145,
 	WLAN_EID_DMG_TSPEC = 146,
 	WLAN_EID_DMG_AT = 147,
 	WLAN_EID_DMG_CAP = 148,
+	/* 149-150 reserved for Cisco */
 	WLAN_EID_DMG_OPERATION = 151,
 	WLAN_EID_DMG_BSS_PARAM_CHANGE = 152,
 	WLAN_EID_DMG_BEAM_REFINEMENT = 153,
 	WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154,
+	/* 155-156 reserved for Cisco */
 	WLAN_EID_AWAKE_WINDOW = 157,
 	WLAN_EID_MULTI_BAND = 158,
 	WLAN_EID_ADDBA_EXT = 159,
@@ -1767,11 +1800,34 @@ enum ieee80211_eid {
 	WLAN_EID_MULTIPLE_MAC_ADDR = 170,
 	WLAN_EID_U_PID = 171,
 	WLAN_EID_DMG_LINK_ADAPT_ACK = 172,
+	/* 173 reserved for Symbol */
+	WLAN_EID_MCCAOP_ADV_OVERVIEW = 174,
 	WLAN_EID_QUIET_PERIOD_REQ = 175,
+	/* 176 reserved for Symbol */
 	WLAN_EID_QUIET_PERIOD_RESP = 177,
+	/* 178-179 reserved for Symbol */
+	/* 180 reserved for ISO/IEC 20011 */
 	WLAN_EID_EPAC_POLICY = 182,
 	WLAN_EID_CLISTER_TIME_OFF = 183,
+	WLAN_EID_INTER_AC_PRIO = 184,
+	WLAN_EID_SCS_DESCRIPTOR = 185,
+	WLAN_EID_QLOAD_REPORT = 186,
+	WLAN_EID_HCCA_TXOP_UPDATE_COUNT = 187,
+	WLAN_EID_HL_STREAM_ID = 188,
+	WLAN_EID_GCR_GROUP_ADDR = 189,
 	WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190,
+	WLAN_EID_VHT_CAPABILITY = 191,
+	WLAN_EID_VHT_OPERATION = 192,
+	WLAN_EID_EXTENDED_BSS_LOAD = 193,
+	WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
+	WLAN_EID_VHT_TX_POWER_ENVELOPE = 195,
+	WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
+	WLAN_EID_AID = 197,
+	WLAN_EID_QUIET_CHANNEL = 198,
+	WLAN_EID_OPMODE_NOTIF = 199,
+
+	WLAN_EID_VENDOR_SPECIFIC = 221,
+	WLAN_EID_QOS_PARAMETER = 222,
 };
 
 /* Action category code */
@@ -2192,10 +2248,10 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
 }
 
 /**
- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
  * @hdr: the frame (buffer must include at least the first octet of payload)
  */
-static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
 {
 	if (ieee80211_is_disassoc(hdr->frame_control) ||
 	    ieee80211_is_deauth(hdr->frame_control))
@@ -2224,6 +2280,17 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
 }
 
 /**
+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
+ * @skb: the skb containing the frame, length will be checked
+ */
+static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
+{
+	if (skb->len < 25)
+		return false;
+	return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
+}
+
+/**
  * ieee80211_is_public_action - check if frame is a public action frame
  * @hdr: the frame
  * @len: length of the frame
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 75a8a20c8179..5f2d00e7e488 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -254,12 +254,16 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
 		(chan->info_mask_shared_by_all & BIT(type));
 }
 
-#define IIO_ST(si, rb, sb, sh)						\
-	{ .sign = si, .realbits = rb, .storagebits = sb, .shift = sh }
-
-#define IIO_CHAN_SOFT_TIMESTAMP(_si)					\
-	{ .type = IIO_TIMESTAMP, .channel = -1,				\
-			.scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) }
+#define IIO_CHAN_SOFT_TIMESTAMP(_si) {					\
+	.type = IIO_TIMESTAMP,						\
+	.channel = -1,							\
+	.scan_index = _si,						\
+	.scan_type = {							\
+		.sign = 's',						\
+		.realbits = 64,					\
+		.storagebits = 64,					\
+		},							\
+}
 
 /**
  * iio_get_time_ns() - utility function to get a time stamp for events etc
diff --git a/include/linux/init.h b/include/linux/init.h
index e1688802964f..a3ba27076342 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -163,6 +163,23 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
+#ifdef CONFIG_LTO
+/* Work around a LTO gcc problem: when there is no reference to a variable
+ * in a module it will be moved to the end of the program. This causes
+ * reordering of initcalls which the kernel does not like.
+ * Add a dummy reference function to avoid this. The function is
+ * deleted by the linker.
+ */
+#define LTO_REFERENCE_INITCALL(x) \
+	; /* yes this is needed */			\
+	static __used __exit void *reference_##x(void)	\
+	{						\
+		return &x;				\
+	}
+#else
+#define LTO_REFERENCE_INITCALL(x)
+#endif
+
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -175,7 +192,8 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn
+	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
+	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
 
 /*
  * Early initcalls run before initializing SMP.
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/interrupt.h b/include/linux/interrupt.h
index a2678d35b5a2..c7bfac1c4a7b 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -188,6 +188,7 @@ extern void disable_irq(unsigned int irq);
 extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
 extern void enable_percpu_irq(unsigned int irq, unsigned int type);
+extern void irq_wake_thread(unsigned int irq, void *dev_id);
 
 /* The following three functions are for the core kernel use only. */
 extern void suspend_device_irqs(void);
diff --git a/include/linux/io.h b/include/linux/io.h
index f4f42faec686..b76e6e545806 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -24,7 +24,7 @@
 
 struct device;
 
-void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
+__visible void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
 void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
 
 #ifdef CONFIG_MMU
@@ -41,7 +41,7 @@ static inline int ioremap_page_range(unsigned long addr, unsigned long end,
 /*
  * Managed iomap interface
  */
-#ifdef CONFIG_HAS_IOPORT
+#ifdef CONFIG_HAS_IOPORT_MAP
 void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
 			       unsigned int nr);
 void devm_ioport_unmap(struct device *dev, void __iomem *addr);
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
index 66017028dcb3..19ae05d4b8ec 100644
--- a/include/linux/irq_work.h
+++ b/include/linux/irq_work.h
@@ -30,7 +30,9 @@ void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
 	work->func = func;
 }
 
-void irq_work_queue(struct irq_work *work);
+#define DEFINE_IRQ_WORK(name, _f) struct irq_work name = { .func = (_f), }
+
+bool irq_work_queue(struct irq_work *work);
 void irq_work_run(void);
 void irq_work_sync(struct irq_work *work);
 
diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h
index e3c82dc95756..ba46c794b4e5 100644
--- a/include/linux/irqchip/arm-vic.h
+++ b/include/linux/irqchip/arm-vic.h
@@ -29,8 +29,10 @@
 struct device_node;
 struct pt_regs;
 
-void __vic_init(void __iomem *base, int irq_start, u32 vic_sources,
-		u32 resume_sources, struct device_node *node);
+void __vic_init(void __iomem *base, int parent_irq, int irq_start,
+		u32 vic_sources, u32 resume_sources, struct device_node *node);
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
+int vic_init_cascaded(void __iomem *base, unsigned int parent_irq,
+		      u32 vic_sources, u32 resume_sources);
 
 #endif
diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h
index e2d28b026a8c..3c77bf9b1efd 100644
--- a/include/linux/isapnp.h
+++ b/include/linux/isapnp.h
@@ -56,10 +56,6 @@
 #define ISAPNP_DEVICE_ID(_va, _vb, _vc, _function) \
 		{ .vendor = ISAPNP_VENDOR(_va, _vb, _vc), .function = ISAPNP_FUNCTION(_function) }
 
-/* export used IDs outside module */
-#define ISAPNP_CARD_TABLE(name) \
-		MODULE_GENERIC_TABLE(isapnp_card, name)
-
 struct isapnp_card_id {
 	unsigned long driver_data;	/* data private to the driver */
 	unsigned short card_vendor, card_device;
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index d267623c28cf..09669d092748 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,7 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
-#include <linux/completion.h>
+#include <linux/wait.h>
 
 struct file;
 struct dentry;
@@ -35,16 +35,22 @@ enum kernfs_node_type {
 };
 
 #define KERNFS_TYPE_MASK	0x000f
-#define KERNFS_ACTIVE_REF	KERNFS_FILE
 #define KERNFS_FLAG_MASK	~KERNFS_TYPE_MASK
 
 enum kernfs_node_flag {
-	KERNFS_REMOVED		= 0x0010,
+	KERNFS_ACTIVATED	= 0x0010,
 	KERNFS_NS		= 0x0020,
 	KERNFS_HAS_SEQ_SHOW	= 0x0040,
 	KERNFS_HAS_MMAP		= 0x0080,
 	KERNFS_LOCKDEP		= 0x0100,
 	KERNFS_STATIC_NAME	= 0x0200,
+	KERNFS_SUICIDAL		= 0x0400,
+	KERNFS_SUICIDED		= 0x0800,
+};
+
+/* @flags for kernfs_create_root() */
+enum kernfs_root_flag {
+	KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001,
 };
 
 /* type-specific structures for kernfs_node union members */
@@ -85,17 +91,17 @@ struct kernfs_node {
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map	dep_map;
 #endif
-	/* the following two fields are published */
+	/*
+	 * Use kernfs_get_parent() and kernfs_name/path() instead of
+	 * accessing the following two fields directly.  If the node is
+	 * never moved to a different parent, it is safe to access the
+	 * parent directly.
+	 */
 	struct kernfs_node	*parent;
 	const char		*name;
 
 	struct rb_node		rb;
 
-	union {
-		struct completion	*completion;
-		struct kernfs_node	*removed_list;
-	} u;
-
 	const void		*ns;	/* namespace tag */
 	unsigned int		hash;	/* ns + name hash */
 	union {
@@ -113,12 +119,16 @@ struct kernfs_node {
 };
 
 /*
- * kernfs_dir_ops may be specified on kernfs_create_root() to support
- * directory manipulation syscalls.  These optional callbacks are invoked
- * on the matching syscalls and can perform any kernfs operations which
- * don't necessarily have to be the exact operation requested.
+ * kernfs_syscall_ops may be specified on kernfs_create_root() to support
+ * syscalls.  These optional callbacks are invoked on the matching syscalls
+ * and can perform any kernfs operations which don't necessarily have to be
+ * the exact operation requested.  An active reference is held for each
+ * kernfs_node parameter.
  */
-struct kernfs_dir_ops {
+struct kernfs_syscall_ops {
+	int (*remount_fs)(struct kernfs_root *root, int *flags, char *data);
+	int (*show_options)(struct seq_file *sf, struct kernfs_root *root);
+
 	int (*mkdir)(struct kernfs_node *parent, const char *name,
 		     umode_t mode);
 	int (*rmdir)(struct kernfs_node *kn);
@@ -129,16 +139,19 @@ struct kernfs_dir_ops {
 struct kernfs_root {
 	/* published fields */
 	struct kernfs_node	*kn;
+	unsigned int		flags;	/* KERNFS_ROOT_* flags */
 
 	/* private fields, do not use outside kernfs proper */
 	struct ida		ino_ida;
-	struct kernfs_dir_ops	*dir_ops;
+	struct kernfs_syscall_ops *syscall_ops;
+	wait_queue_head_t	deactivate_waitq;
 };
 
 struct kernfs_open_file {
 	/* published fields */
 	struct kernfs_node	*kn;
 	struct file		*file;
+	void			*priv;
 
 	/* private fields, do not use outside kernfs proper */
 	struct mutex		mutex;
@@ -171,9 +184,13 @@ struct kernfs_ops {
 			loff_t off);
 
 	/*
-	 * write() is bounced through kernel buffer and a write larger than
-	 * PAGE_SIZE results in partial operation of PAGE_SIZE.
+	 * write() is bounced through kernel buffer.  If atomic_write_len
+	 * is not set, a write larger than PAGE_SIZE results in partial
+	 * operations of PAGE_SIZE chunks.  If atomic_write_len is set,
+	 * writes upto the specified size are executed atomically but
+	 * larger ones are rejected with -E2BIG.
 	 */
+	size_t atomic_write_len;
 	ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes,
 			 loff_t off);
 
@@ -184,7 +201,7 @@ struct kernfs_ops {
 #endif
 };
 
-#ifdef CONFIG_SYSFS
+#ifdef CONFIG_KERNFS
 
 static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
 {
@@ -217,13 +234,22 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
 	return kn->flags & KERNFS_NS;
 }
 
+int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
+char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
+				size_t buflen);
+void pr_cont_kernfs_name(struct kernfs_node *kn);
+void pr_cont_kernfs_path(struct kernfs_node *kn);
+struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
 struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
 					   const char *name, const void *ns);
 void kernfs_get(struct kernfs_node *kn);
 void kernfs_put(struct kernfs_node *kn);
 
-struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops,
-				       void *priv);
+struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry);
+struct kernfs_root *kernfs_root_from_sb(struct super_block *sb);
+
+struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
+				       unsigned int flags, void *priv);
 void kernfs_destroy_root(struct kernfs_root *root);
 
 struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
@@ -239,7 +265,11 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
 struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
 				       const char *name,
 				       struct kernfs_node *target);
+void kernfs_activate(struct kernfs_node *kn);
 void kernfs_remove(struct kernfs_node *kn);
+void kernfs_break_active_protection(struct kernfs_node *kn);
+void kernfs_unbreak_active_protection(struct kernfs_node *kn);
+bool kernfs_remove_self(struct kernfs_node *kn);
 int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
 			     const void *ns);
 int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
@@ -255,7 +285,7 @@ void kernfs_kill_sb(struct super_block *sb);
 
 void kernfs_init(void);
 
-#else	/* CONFIG_SYSFS */
+#else	/* CONFIG_KERNFS */
 
 static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
 { return 0; }	/* whatever */
@@ -265,6 +295,19 @@ static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
 static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
 { return false; }
 
+static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
+{ return -ENOSYS; }
+
+static inline char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
+					      size_t buflen)
+{ return NULL; }
+
+static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { }
+static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { }
+
+static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
+{ return NULL; }
+
 static inline struct kernfs_node *
 kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
 		       const void *ns)
@@ -273,8 +316,15 @@ kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
 static inline void kernfs_get(struct kernfs_node *kn) { }
 static inline void kernfs_put(struct kernfs_node *kn) { }
 
+static inline struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
+{ return NULL; }
+
+static inline struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
+{ return NULL; }
+
 static inline struct kernfs_root *
-kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
+kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags,
+		   void *priv)
 { return ERR_PTR(-ENOSYS); }
 
 static inline void kernfs_destroy_root(struct kernfs_root *root) { }
@@ -296,8 +346,13 @@ kernfs_create_link(struct kernfs_node *parent, const char *name,
 		   struct kernfs_node *target)
 { return ERR_PTR(-ENOSYS); }
 
+static inline void kernfs_activate(struct kernfs_node *kn) { }
+
 static inline void kernfs_remove(struct kernfs_node *kn) { }
 
+static inline bool kernfs_remove_self(struct kernfs_node *kn)
+{ return false; }
+
 static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn,
 					   const char *name, const void *ns)
 { return -ENOSYS; }
@@ -325,7 +380,7 @@ static inline void kernfs_kill_sb(struct super_block *sb) { }
 
 static inline void kernfs_init(void) { }
 
-#endif	/* CONFIG_SYSFS */
+#endif	/* CONFIG_KERNFS */
 
 static inline struct kernfs_node *
 kernfs_find_and_get(struct kernfs_node *kn, const char *name)
@@ -367,6 +422,13 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent,
 	return kernfs_remove_by_name_ns(parent, name, NULL);
 }
 
+static inline int kernfs_rename(struct kernfs_node *kn,
+				struct kernfs_node *new_parent,
+				const char *new_name)
+{
+	return kernfs_rename_ns(kn, new_parent, new_name, NULL);
+}
+
 static inline struct dentry *
 kernfs_mount(struct file_system_type *fs_type, int flags,
 	     struct kernfs_root *root, bool *new_sb_created)
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 552d51efb429..554fde3a3927 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -722,7 +722,7 @@ __kfifo_uint_must_check_helper( \
 /**
  * kfifo_dma_out_finish - finish a DMA OUT operation
  * @fifo: address of the fifo to be used
- * @len: number of bytes transferd
+ * @len: number of bytes transferrd
  *
  * This macro finish a DMA OUT operation. The out counter will be updated by
  * the len parameter. No error checking will be done.
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 926afb6f6b5f..f896a33e8341 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -119,6 +119,7 @@ struct kobj_type {
 };
 
 struct kobj_uevent_env {
+	char *argv[3];
 	char *envp[UEVENT_NUM_ENVP];
 	int envp_idx;
 	char buf[UEVENT_BUFFER_SIZE];
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 7dcef3317689..50050ae17b00 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -51,6 +51,7 @@ void kthread_parkme(void);
 int kthreadd(void *unused);
 extern struct task_struct *kthreadd_task;
 extern int tsk_fork_get_node(struct task_struct *tsk);
+void set_kthreadd_affinity(void);
 
 /*
  * Simple work processor based on kthread.
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b8e9a43e501a..9816b68b085f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -192,7 +192,7 @@ struct kvm_async_pf {
 
 void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu);
 void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu);
-int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
+int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
 		       struct kvm_arch_async_pf *arch);
 int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
 #endif
@@ -401,7 +401,9 @@ struct kvm {
 	unsigned long mmu_notifier_seq;
 	long mmu_notifier_count;
 #endif
-	long tlbs_dirty;
+	/* Protected by mmu_lock */
+	bool tlbs_dirty;
+
 	struct list_head devices;
 };
 
@@ -1064,6 +1066,7 @@ extern struct kvm_device_ops kvm_mpic_ops;
 extern struct kvm_device_ops kvm_xics_ops;
 extern struct kvm_device_ops kvm_vfio_ops;
 extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
+extern struct kvm_device_ops kvm_flic_ops;
 
 #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
 
diff --git a/include/linux/lglock.h b/include/linux/lglock.h
index 96549abe8842..0081f000e34b 100644
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -25,6 +25,8 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 
+#ifdef CONFIG_SMP
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 #define LOCKDEP_INIT_MAP lockdep_init_map
 #else
@@ -57,4 +59,18 @@ void lg_local_unlock_cpu(struct lglock *lg, int cpu);
 void lg_global_lock(struct lglock *lg);
 void lg_global_unlock(struct lglock *lg);
 
+#else
+/* When !CONFIG_SMP, map lglock to spinlock */
+#define lglock spinlock
+#define DEFINE_LGLOCK(name) DEFINE_SPINLOCK(name)
+#define DEFINE_STATIC_LGLOCK(name) static DEFINE_SPINLOCK(name)
+#define lg_lock_init(lg, name) spin_lock_init(lg)
+#define lg_local_lock spin_lock
+#define lg_local_unlock spin_unlock
+#define lg_local_lock_cpu(lg, cpu) spin_lock(lg)
+#define lg_local_unlock_cpu(lg, cpu) spin_unlock(lg)
+#define lg_global_lock spin_lock
+#define lg_global_unlock spin_unlock
+#endif
+
 #endif
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index a6a42dd02466..34a513a2727b 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -12,9 +12,9 @@
 #endif
 
 #ifdef __cplusplus
-#define CPP_ASMLINKAGE extern "C"
+#define CPP_ASMLINKAGE extern "C" __visible
 #else
-#define CPP_ASMLINKAGE
+#define CPP_ASMLINKAGE __visible
 #endif
 
 #ifndef asmlinkage
diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h
index 3ce541753c88..f3434533fbf8 100644
--- a/include/linux/list_lru.h
+++ b/include/linux/list_lru.h
@@ -13,6 +13,8 @@
 /* list_lru_walk_cb has to always return one of those */
 enum lru_status {
 	LRU_REMOVED,		/* item removed from list */
+	LRU_REMOVED_RETRY,	/* item removed, but lock has been
+				   dropped and reacquired */
 	LRU_ROTATE,		/* item referenced, give another pass */
 	LRU_SKIP,		/* item cannot be locked, skip */
 	LRU_RETRY,		/* item not freeable. May drop the lock
@@ -32,7 +34,11 @@ struct list_lru {
 };
 
 void list_lru_destroy(struct list_lru *lru);
-int list_lru_init(struct list_lru *lru);
+int list_lru_init_key(struct list_lru *lru, struct lock_class_key *key);
+static inline int list_lru_init(struct list_lru *lru)
+{
+	return list_lru_init_key(lru, NULL);
+}
 
 /**
  * list_lru_add: add an element to the lru list's tail
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 92b1bfc5da60..008388f920d7 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -252,9 +252,9 @@ struct held_lock {
 	unsigned int trylock:1;						/* 16 bits */
 
 	unsigned int read:2;        /* see lock_acquire() comment */
-	unsigned int check:2;       /* see lock_acquire() comment */
+	unsigned int check:1;       /* see lock_acquire() comment */
 	unsigned int hardirqs_off:1;
-	unsigned int references:11;					/* 32 bits */
+	unsigned int references:12;					/* 32 bits */
 };
 
 /*
@@ -265,7 +265,7 @@ extern void lockdep_info(void);
 extern void lockdep_reset(void);
 extern void lockdep_reset_lock(struct lockdep_map *lock);
 extern void lockdep_free_key_range(void *start, unsigned long size);
-extern void lockdep_sys_exit(void);
+extern asmlinkage void lockdep_sys_exit(void);
 
 extern void lockdep_off(void);
 extern void lockdep_on(void);
@@ -303,7 +303,7 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
 				 (lock)->dep_map.key, sub)
 
 #define lockdep_set_novalidate_class(lock) \
-	lockdep_set_class(lock, &__lockdep_no_validate__)
+	lockdep_set_class_and_name(lock, &__lockdep_no_validate__, #lock)
 /*
  * Compare locking classes
  */
@@ -326,9 +326,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
  *
  * Values for check:
  *
- *   0: disabled
- *   1: simple checks (freeing, held-at-exit-time, etc.)
- *   2: full validation
+ *   0: simple checks (freeing, held-at-exit-time, etc.)
+ *   1: full validation
  */
 extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 			 int trylock, int read, int check,
@@ -479,15 +478,9 @@ static inline void print_irqtrace_events(struct task_struct *curr)
  * on the per lock-class debug mode:
  */
 
-#ifdef CONFIG_PROVE_LOCKING
- #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 2, n, i)
- #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 2, n, i)
- #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 2, n, i)
-#else
- #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 1, n, i)
- #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 1, n, i)
- #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 1, n, i)
-#endif
+#define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 1, n, i)
+#define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 1, n, i)
+#define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 1, n, i)
 
 #define spin_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
 #define spin_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
@@ -518,13 +511,13 @@ static inline void print_irqtrace_events(struct task_struct *curr)
 # define might_lock(lock) 						\
 do {									\
 	typecheck(struct lockdep_map *, &(lock)->dep_map);		\
-	lock_acquire(&(lock)->dep_map, 0, 0, 0, 2, NULL, _THIS_IP_);	\
+	lock_acquire(&(lock)->dep_map, 0, 0, 0, 1, NULL, _THIS_IP_);	\
 	lock_release(&(lock)->dep_map, 0, _THIS_IP_);			\
 } while (0)
 # define might_lock_read(lock) 						\
 do {									\
 	typecheck(struct lockdep_map *, &(lock)->dep_map);		\
-	lock_acquire(&(lock)->dep_map, 0, 0, 1, 2, NULL, _THIS_IP_);	\
+	lock_acquire(&(lock)->dep_map, 0, 0, 1, 1, NULL, _THIS_IP_);	\
 	lock_release(&(lock)->dep_map, 0, _THIS_IP_);			\
 } while (0)
 #else
diff --git a/include/linux/mcb.h b/include/linux/mcb.h
new file mode 100644
index 000000000000..2db284d14064
--- /dev/null
+++ b/include/linux/mcb.h
@@ -0,0 +1,119 @@
+/*
+ * MEN Chameleon Bus.
+ *
+ * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
+ * Author: Johannes Thumshirn <johannes.thumshirn@men.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; version 2 of the License.
+ */
+#ifndef _LINUX_MCB_H
+#define _LINUX_MCB_H
+
+#include <linux/mod_devicetable.h>
+#include <linux/device.h>
+#include <linux/irqreturn.h>
+
+struct mcb_driver;
+
+/**
+ * struct mcb_bus - MEN Chameleon Bus
+ *
+ * @dev: pointer to carrier device
+ * @children: the child busses
+ * @bus_nr: mcb bus number
+ */
+struct mcb_bus {
+	struct list_head children;
+	struct device dev;
+	int bus_nr;
+};
+#define to_mcb_bus(b) container_of((b), struct mcb_bus, dev)
+
+/**
+ * struct mcb_device - MEN Chameleon Bus device
+ *
+ * @bus_list: internal list handling for bus code
+ * @dev: device in kernel representation
+ * @bus: mcb bus the device is plugged to
+ * @subordinate: subordinate MCBus in case of bridge
+ * @is_added: flag to check if device is added to bus
+ * @driver: associated mcb_driver
+ * @id: mcb device id
+ * @inst: instance in Chameleon table
+ * @group: group in Chameleon table
+ * @var: variant in Chameleon table
+ * @bar: BAR in Chameleon table
+ * @rev: revision in Chameleon table
+ * @irq: IRQ resource
+ * @memory: memory resource
+ */
+struct mcb_device {
+	struct list_head bus_list;
+	struct device dev;
+	struct mcb_bus *bus;
+	struct mcb_bus *subordinate;
+	bool is_added;
+	struct mcb_driver *driver;
+	u16 id;
+	int inst;
+	int group;
+	int var;
+	int bar;
+	int rev;
+	struct resource irq;
+	struct resource mem;
+};
+#define to_mcb_device(x) container_of((x), struct mcb_device, dev)
+
+/**
+ * struct mcb_driver - MEN Chameleon Bus device driver
+ *
+ * @driver: device_driver
+ * @id_table: mcb id table
+ * @probe: probe callback
+ * @remove: remove callback
+ * @shutdown: shutdown callback
+ */
+struct mcb_driver {
+	struct device_driver driver;
+	const struct mcb_device_id *id_table;
+	int (*probe)(struct mcb_device *mdev, const struct mcb_device_id *id);
+	void (*remove)(struct mcb_device *mdev);
+	void (*shutdown)(struct mcb_device *mdev);
+};
+#define to_mcb_driver(x) container_of((x), struct mcb_driver, driver)
+
+static inline void *mcb_get_drvdata(struct mcb_device *dev)
+{
+	return dev_get_drvdata(&dev->dev);
+}
+
+static inline void mcb_set_drvdata(struct mcb_device *dev, void *data)
+{
+	dev_set_drvdata(&dev->dev, data);
+}
+
+extern int __must_check __mcb_register_driver(struct mcb_driver *drv,
+					struct module *owner,
+					const char *mod_name);
+#define mcb_register_driver(driver)		\
+	__mcb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
+extern void mcb_unregister_driver(struct mcb_driver *driver);
+#define module_mcb_driver(__mcb_driver)		\
+	module_driver(__mcb_driver, mcb_register_driver, mcb_unregister_driver);
+extern void mcb_bus_add_devices(const struct mcb_bus *bus);
+extern int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev);
+extern struct mcb_bus *mcb_alloc_bus(void);
+extern struct mcb_bus *mcb_bus_get(struct mcb_bus *bus);
+extern void mcb_bus_put(struct mcb_bus *bus);
+extern struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus);
+extern void mcb_free_dev(struct mcb_device *dev);
+extern void mcb_release_bus(struct mcb_bus *bus);
+extern struct resource *mcb_request_mem(struct mcb_device *dev,
+					const char *name);
+extern void mcb_release_mem(struct resource *mem);
+extern int mcb_get_irq(struct mcb_device *dev);
+
+#endif /* _LINUX_MCB_H */
diff --git a/include/linux/mcs_spinlock.h b/include/linux/mcs_spinlock.h
new file mode 100644
index 000000000000..f2a5c6360083
--- /dev/null
+++ b/include/linux/mcs_spinlock.h
@@ -0,0 +1,114 @@
+/*
+ * MCS lock defines
+ *
+ * This file contains the main data structure and API definitions of MCS lock.
+ *
+ * The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spin-lock
+ * with the desirable properties of being fair, and with each cpu trying
+ * to acquire the lock spinning on a local variable.
+ * It avoids expensive cache bouncings that common test-and-set spin-lock
+ * implementations incur.
+ */
+#ifndef __LINUX_MCS_SPINLOCK_H
+#define __LINUX_MCS_SPINLOCK_H
+
+#include <asm/mcs_spinlock.h>
+
+struct mcs_spinlock {
+	struct mcs_spinlock *next;
+	int locked; /* 1 if lock acquired */
+};
+
+#ifndef arch_mcs_spin_lock_contended
+/*
+ * Using smp_load_acquire() provides a memory barrier that ensures
+ * subsequent operations happen after the lock is acquired.
+ */
+#define arch_mcs_spin_lock_contended(l)					\
+do {									\
+	while (!(smp_load_acquire(l)))					\
+		arch_mutex_cpu_relax();					\
+} while (0)
+#endif
+
+#ifndef arch_mcs_spin_unlock_contended
+/*
+ * smp_store_release() provides a memory barrier to ensure all
+ * operations in the critical section has been completed before
+ * unlocking.
+ */
+#define arch_mcs_spin_unlock_contended(l)				\
+	smp_store_release((l), 1)
+#endif
+
+/*
+ * Note: the smp_load_acquire/smp_store_release pair is not
+ * sufficient to form a full memory barrier across
+ * cpus for many architectures (except x86) for mcs_unlock and mcs_lock.
+ * For applications that need a full barrier across multiple cpus
+ * with mcs_unlock and mcs_lock pair, smp_mb__after_unlock_lock() should be
+ * used after mcs_lock.
+ */
+
+/*
+ * In order to acquire the lock, the caller should declare a local node and
+ * pass a reference of the node to this function in addition to the lock.
+ * If the lock has already been acquired, then this will proceed to spin
+ * on this node->locked until the previous lock holder sets the node->locked
+ * in mcs_spin_unlock().
+ *
+ * We don't inline mcs_spin_lock() so that perf can correctly account for the
+ * time spent in this lock function.
+ */
+static inline
+void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+	struct mcs_spinlock *prev;
+
+	/* Init node */
+	node->locked = 0;
+	node->next   = NULL;
+
+	prev = xchg(lock, node);
+	if (likely(prev == NULL)) {
+		/*
+		 * Lock acquired, don't need to set node->locked to 1. Threads
+		 * only spin on its own node->locked value for lock acquisition.
+		 * However, since this thread can immediately acquire the lock
+		 * and does not proceed to spin on its own node->locked, this
+		 * value won't be used. If a debug mode is needed to
+		 * audit lock status, then set node->locked value here.
+		 */
+		return;
+	}
+	ACCESS_ONCE(prev->next) = node;
+
+	/* Wait until the lock holder passes the lock down. */
+	arch_mcs_spin_lock_contended(&node->locked);
+}
+
+/*
+ * Releases the lock. The caller should pass in the corresponding node that
+ * was used to acquire the lock.
+ */
+static inline
+void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+	struct mcs_spinlock *next = ACCESS_ONCE(node->next);
+
+	if (likely(!next)) {
+		/*
+		 * Release the lock by setting it to NULL
+		 */
+		if (likely(cmpxchg(lock, node, NULL) == node))
+			return;
+		/* Wait until the next pointer is set */
+		while (!(next = ACCESS_ONCE(node->next)))
+			arch_mutex_cpu_relax();
+	}
+
+	/* Pass lock to next waiter. */
+	arch_mcs_spin_unlock_contended(&next->locked);
+}
+
+#endif /* __LINUX_MCS_SPINLOCK_H */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index abd0113b6620..af63e6004c62 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -162,7 +162,7 @@ extern int do_swap_account;
 
 static inline bool mem_cgroup_disabled(void)
 {
-	if (mem_cgroup_subsys.disabled)
+	if (memory_cgrp_subsys.disabled)
 		return true;
 	return false;
 }
@@ -497,6 +497,9 @@ void __memcg_kmem_commit_charge(struct page *page,
 void __memcg_kmem_uncharge_pages(struct page *page, int order);
 
 int memcg_cache_id(struct mem_cgroup *memcg);
+
+char *memcg_create_cache_name(struct mem_cgroup *memcg,
+			      struct kmem_cache *root_cache);
 int memcg_alloc_cache_params(struct mem_cgroup *memcg, struct kmem_cache *s,
 			     struct kmem_cache *root_cache);
 void memcg_free_cache_params(struct kmem_cache *s);
@@ -510,7 +513,7 @@ struct kmem_cache *
 __memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp);
 
 void mem_cgroup_destroy_cache(struct kmem_cache *cachep);
-void kmem_cache_destroy_memcg_children(struct kmem_cache *s);
+int __kmem_cache_destroy_memcg_children(struct kmem_cache *s);
 
 /**
  * memcg_kmem_newpage_charge: verify if a new kmem allocation is allowed.
@@ -664,10 +667,6 @@ memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp)
 {
 	return cachep;
 }
-
-static inline void kmem_cache_destroy_memcg_children(struct kmem_cache *s)
-{
-}
 #endif /* CONFIG_MEMCG_KMEM */
 #endif /* _LINUX_MEMCONTROL_H */
 
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index fdf3aa376eb2..90d57aec34e7 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -1034,6 +1034,27 @@
 #define ARIZONA_DSP1_STATUS_1                    0x1104
 #define ARIZONA_DSP1_STATUS_2                    0x1105
 #define ARIZONA_DSP1_STATUS_3                    0x1106
+#define ARIZONA_DSP1_STATUS_4                    0x1107
+#define ARIZONA_DSP1_WDMA_BUFFER_1               0x1110
+#define ARIZONA_DSP1_WDMA_BUFFER_2               0x1111
+#define ARIZONA_DSP1_WDMA_BUFFER_3               0x1112
+#define ARIZONA_DSP1_WDMA_BUFFER_4               0x1113
+#define ARIZONA_DSP1_WDMA_BUFFER_5               0x1114
+#define ARIZONA_DSP1_WDMA_BUFFER_6               0x1115
+#define ARIZONA_DSP1_WDMA_BUFFER_7               0x1116
+#define ARIZONA_DSP1_WDMA_BUFFER_8               0x1117
+#define ARIZONA_DSP1_RDMA_BUFFER_1               0x1120
+#define ARIZONA_DSP1_RDMA_BUFFER_2               0x1121
+#define ARIZONA_DSP1_RDMA_BUFFER_3               0x1122
+#define ARIZONA_DSP1_RDMA_BUFFER_4               0x1123
+#define ARIZONA_DSP1_RDMA_BUFFER_5               0x1124
+#define ARIZONA_DSP1_RDMA_BUFFER_6               0x1125
+#define ARIZONA_DSP1_WDMA_CONFIG_1               0x1130
+#define ARIZONA_DSP1_WDMA_CONFIG_2               0x1131
+#define ARIZONA_DSP1_WDMA_OFFSET_1               0x1132
+#define ARIZONA_DSP1_RDMA_CONFIG_1               0x1134
+#define ARIZONA_DSP1_RDMA_OFFSET_1               0x1135
+#define ARIZONA_DSP1_EXTERNAL_START_SELECT_1     0x1138
 #define ARIZONA_DSP1_SCRATCH_0                   0x1140
 #define ARIZONA_DSP1_SCRATCH_1                   0x1141
 #define ARIZONA_DSP1_SCRATCH_2                   0x1142
@@ -1043,6 +1064,27 @@
 #define ARIZONA_DSP2_STATUS_1                    0x1204
 #define ARIZONA_DSP2_STATUS_2                    0x1205
 #define ARIZONA_DSP2_STATUS_3                    0x1206
+#define ARIZONA_DSP2_STATUS_4                    0x1207
+#define ARIZONA_DSP2_WDMA_BUFFER_1               0x1210
+#define ARIZONA_DSP2_WDMA_BUFFER_2               0x1211
+#define ARIZONA_DSP2_WDMA_BUFFER_3               0x1212
+#define ARIZONA_DSP2_WDMA_BUFFER_4               0x1213
+#define ARIZONA_DSP2_WDMA_BUFFER_5               0x1214
+#define ARIZONA_DSP2_WDMA_BUFFER_6               0x1215
+#define ARIZONA_DSP2_WDMA_BUFFER_7               0x1216
+#define ARIZONA_DSP2_WDMA_BUFFER_8               0x1217
+#define ARIZONA_DSP2_RDMA_BUFFER_1               0x1220
+#define ARIZONA_DSP2_RDMA_BUFFER_2               0x1221
+#define ARIZONA_DSP2_RDMA_BUFFER_3               0x1222
+#define ARIZONA_DSP2_RDMA_BUFFER_4               0x1223
+#define ARIZONA_DSP2_RDMA_BUFFER_5               0x1224
+#define ARIZONA_DSP2_RDMA_BUFFER_6               0x1225
+#define ARIZONA_DSP2_WDMA_CONFIG_1               0x1230
+#define ARIZONA_DSP2_WDMA_CONFIG_2               0x1231
+#define ARIZONA_DSP2_WDMA_OFFSET_1               0x1232
+#define ARIZONA_DSP2_RDMA_CONFIG_1               0x1234
+#define ARIZONA_DSP2_RDMA_OFFSET_1               0x1235
+#define ARIZONA_DSP2_EXTERNAL_START_SELECT_1     0x1238
 #define ARIZONA_DSP2_SCRATCH_0                   0x1240
 #define ARIZONA_DSP2_SCRATCH_1                   0x1241
 #define ARIZONA_DSP2_SCRATCH_2                   0x1242
@@ -1052,6 +1094,27 @@
 #define ARIZONA_DSP3_STATUS_1                    0x1304
 #define ARIZONA_DSP3_STATUS_2                    0x1305
 #define ARIZONA_DSP3_STATUS_3                    0x1306
+#define ARIZONA_DSP3_STATUS_4                    0x1307
+#define ARIZONA_DSP3_WDMA_BUFFER_1               0x1310
+#define ARIZONA_DSP3_WDMA_BUFFER_2               0x1311
+#define ARIZONA_DSP3_WDMA_BUFFER_3               0x1312
+#define ARIZONA_DSP3_WDMA_BUFFER_4               0x1313
+#define ARIZONA_DSP3_WDMA_BUFFER_5               0x1314
+#define ARIZONA_DSP3_WDMA_BUFFER_6               0x1315
+#define ARIZONA_DSP3_WDMA_BUFFER_7               0x1316
+#define ARIZONA_DSP3_WDMA_BUFFER_8               0x1317
+#define ARIZONA_DSP3_RDMA_BUFFER_1               0x1320
+#define ARIZONA_DSP3_RDMA_BUFFER_2               0x1321
+#define ARIZONA_DSP3_RDMA_BUFFER_3               0x1322
+#define ARIZONA_DSP3_RDMA_BUFFER_4               0x1323
+#define ARIZONA_DSP3_RDMA_BUFFER_5               0x1324
+#define ARIZONA_DSP3_RDMA_BUFFER_6               0x1325
+#define ARIZONA_DSP3_WDMA_CONFIG_1               0x1330
+#define ARIZONA_DSP3_WDMA_CONFIG_2               0x1331
+#define ARIZONA_DSP3_WDMA_OFFSET_1               0x1332
+#define ARIZONA_DSP3_RDMA_CONFIG_1               0x1334
+#define ARIZONA_DSP3_RDMA_OFFSET_1               0x1335
+#define ARIZONA_DSP3_EXTERNAL_START_SELECT_1     0x1338
 #define ARIZONA_DSP3_SCRATCH_0                   0x1340
 #define ARIZONA_DSP3_SCRATCH_1                   0x1341
 #define ARIZONA_DSP3_SCRATCH_2                   0x1342
@@ -1061,6 +1124,27 @@
 #define ARIZONA_DSP4_STATUS_1                    0x1404
 #define ARIZONA_DSP4_STATUS_2                    0x1405
 #define ARIZONA_DSP4_STATUS_3                    0x1406
+#define ARIZONA_DSP4_STATUS_4                    0x1407
+#define ARIZONA_DSP4_WDMA_BUFFER_1               0x1410
+#define ARIZONA_DSP4_WDMA_BUFFER_2               0x1411
+#define ARIZONA_DSP4_WDMA_BUFFER_3               0x1412
+#define ARIZONA_DSP4_WDMA_BUFFER_4               0x1413
+#define ARIZONA_DSP4_WDMA_BUFFER_5               0x1414
+#define ARIZONA_DSP4_WDMA_BUFFER_6               0x1415
+#define ARIZONA_DSP4_WDMA_BUFFER_7               0x1416
+#define ARIZONA_DSP4_WDMA_BUFFER_8               0x1417
+#define ARIZONA_DSP4_RDMA_BUFFER_1               0x1420
+#define ARIZONA_DSP4_RDMA_BUFFER_2               0x1421
+#define ARIZONA_DSP4_RDMA_BUFFER_3               0x1422
+#define ARIZONA_DSP4_RDMA_BUFFER_4               0x1423
+#define ARIZONA_DSP4_RDMA_BUFFER_5               0x1424
+#define ARIZONA_DSP4_RDMA_BUFFER_6               0x1425
+#define ARIZONA_DSP4_WDMA_CONFIG_1               0x1430
+#define ARIZONA_DSP4_WDMA_CONFIG_2               0x1431
+#define ARIZONA_DSP4_WDMA_OFFSET_1               0x1432
+#define ARIZONA_DSP4_RDMA_CONFIG_1               0x1434
+#define ARIZONA_DSP4_RDMA_OFFSET_1               0x1435
+#define ARIZONA_DSP4_EXTERNAL_START_SELECT_1     0x1438
 #define ARIZONA_DSP4_SCRATCH_0                   0x1440
 #define ARIZONA_DSP4_SCRATCH_1                   0x1441
 #define ARIZONA_DSP4_SCRATCH_2                   0x1442
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h
index a3d0185196d3..c9b332fb0d5d 100644
--- a/include/linux/mfd/max14577-private.h
+++ b/include/linux/mfd/max14577-private.h
@@ -248,14 +248,6 @@ enum max14577_charger_reg {
 /* MAX14577 regulator SFOUT LDO voltage, fixed, uV */
 #define MAX14577_REGULATOR_SAFEOUT_VOLTAGE		4900000
 
-enum max14577_irq_source {
-	MAX14577_IRQ_INT1 = 0,
-	MAX14577_IRQ_INT2,
-	MAX14577_IRQ_INT3,
-
-	MAX14577_IRQ_REGS_NUM,
-};
-
 enum max14577_irq {
 	/* INT1 */
 	MAX14577_IRQ_INT1_ADC,
diff --git a/include/linux/mfd/max14577.h b/include/linux/mfd/max14577.h
index 247b021dfaaf..736d39c3ec0d 100644
--- a/include/linux/mfd/max14577.h
+++ b/include/linux/mfd/max14577.h
@@ -25,13 +25,8 @@
 #ifndef __MAX14577_H__
 #define __MAX14577_H__
 
-#include <linux/mfd/max14577-private.h>
 #include <linux/regulator/consumer.h>
 
-/*
- * MAX14577 Regulator
- */
-
 /* MAX14577 regulator IDs */
 enum max14577_regulators {
 	MAX14577_SAFEOUT = 0,
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index ac39d910e70b..a326c850f046 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -104,6 +104,9 @@ enum {
 	MC13892_LED_R,
 	MC13892_LED_G,
 	MC13892_LED_B,
+	/* MC34708 LED IDs */
+	MC34708_LED_R,
+	MC34708_LED_G,
 };
 
 struct mc13xxx_led_platform_data {
@@ -163,6 +166,9 @@ struct mc13xxx_leds_platform_data {
 #define MC13892_LED_C2_CURRENT_G(x)	(((x) & 0x7) << 21)
 /* MC13892 LED Control 3 */
 #define MC13892_LED_C3_CURRENT_B(x)	(((x) & 0x7) << 9)
+/* MC34708 LED Control 0 */
+#define MC34708_LED_C0_CURRENT_R(x)	(((x) & 0x3) << 9)
+#define MC34708_LED_C0_CURRENT_G(x)	(((x) & 0x3) << 21)
 	u32 led_control[MAX_LED_CONTROL_REGS];
 };
 
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
index 443176ee1ab0..7c36cc55d2c7 100644
--- a/include/linux/mfd/rtsx_common.h
+++ b/include/linux/mfd/rtsx_common.h
@@ -45,6 +45,7 @@ struct platform_device;
 struct rtsx_slot {
 	struct platform_device	*p_dev;
 	void			(*card_event)(struct platform_device *p_dev);
+	void			(*done_transfer)(struct platform_device *p_dev);
 };
 
 #endif
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
index 0ce772105508..8d6bbd609ad9 100644
--- a/include/linux/mfd/rtsx_pci.h
+++ b/include/linux/mfd/rtsx_pci.h
@@ -144,7 +144,7 @@
 #define HOST_TO_DEVICE		0
 #define DEVICE_TO_HOST		1
 
-#define MAX_PHASE		31
+#define RTSX_PHASE_MAX		32
 #define RX_TUNING_CNT		3
 
 /* SG descriptor */
@@ -943,6 +943,12 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
 int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
 int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
 		int num_sg, bool read, int timeout);
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read);
+int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read);
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int sg_count, bool read);
 int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
 int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
 int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 41c9bde410c5..55510444b9fd 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -119,7 +119,8 @@ struct sec_platform_data {
 struct sec_regulator_data {
 	int				id;
 	struct regulator_init_data	*initdata;
-	struct device_node *reg_node;
+	struct device_node		*reg_node;
+	int				ext_control_gpio;
 };
 
 /*
diff --git a/include/linux/mfd/samsung/s5m8767.h b/include/linux/mfd/samsung/s5m8767.h
index 2ab0b0f03641..243b58fec33d 100644
--- a/include/linux/mfd/samsung/s5m8767.h
+++ b/include/linux/mfd/samsung/s5m8767.h
@@ -183,10 +183,17 @@ enum s5m8767_regulators {
 	S5M8767_REG_MAX,
 };
 
+/* LDO_EN/BUCK_EN field in registers */
 #define S5M8767_ENCTRL_SHIFT		6
 #define S5M8767_ENCTRL_MASK		(0x3 << S5M8767_ENCTRL_SHIFT)
 
 /*
+ * LDO_EN/BUCK_EN register value for controlling this Buck or LDO
+ * by GPIO (PWREN, BUCKEN).
+ */
+#define S5M8767_ENCTRL_USE_GPIO		0x1
+
+/*
  * Values for BUCK_RAMP field in DVS_RAMP register, matching raw values
  * in mV/us.
  */
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index 866e355fa409..ff44374a1a4e 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -242,6 +242,24 @@
 
 #define IMX6Q_GPR5_L2_CLK_STOP			BIT(8)
 
+#define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK	(0xf << 0)
+#define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK	(0xf << 4)
+#define IMX6Q_GPR6_IPU1_ID10_WR_QOS_MASK	(0xf << 8)
+#define IMX6Q_GPR6_IPU1_ID11_WR_QOS_MASK	(0xf << 12)
+#define IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK	(0xf << 16)
+#define IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK	(0xf << 20)
+#define IMX6Q_GPR6_IPU1_ID10_RD_QOS_MASK	(0xf << 24)
+#define IMX6Q_GPR6_IPU1_ID11_RD_QOS_MASK	(0xf << 28)
+
+#define IMX6Q_GPR7_IPU2_ID00_WR_QOS_MASK	(0xf << 0)
+#define IMX6Q_GPR7_IPU2_ID01_WR_QOS_MASK	(0xf << 4)
+#define IMX6Q_GPR7_IPU2_ID10_WR_QOS_MASK	(0xf << 8)
+#define IMX6Q_GPR7_IPU2_ID11_WR_QOS_MASK	(0xf << 12)
+#define IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK	(0xf << 16)
+#define IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK	(0xf << 20)
+#define IMX6Q_GPR7_IPU2_ID10_RD_QOS_MASK	(0xf << 24)
+#define IMX6Q_GPR7_IPU2_ID11_RD_QOS_MASK	(0xf << 28)
+
 #define IMX6Q_GPR8_TX_SWING_LOW			(0x7f << 25)
 #define IMX6Q_GPR8_TX_SWING_FULL		(0x7f << 18)
 #define IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB		(0x3f << 12)
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 3737f7218f51..51e26f3cd3b3 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -11,23 +11,24 @@
  */
 
 #define PSMOUSE_MINOR		1
-#define MS_BUSMOUSE_MINOR	2
-#define ATIXL_BUSMOUSE_MINOR	3
+#define MS_BUSMOUSE_MINOR	2	/* unused */
+#define ATIXL_BUSMOUSE_MINOR	3	/* unused */
 /*#define AMIGAMOUSE_MINOR	4	FIXME OBSOLETE */
-#define ATARIMOUSE_MINOR	5
-#define SUN_MOUSE_MINOR		6
-#define APOLLO_MOUSE_MINOR	7
-#define PC110PAD_MINOR		9
+#define ATARIMOUSE_MINOR	5	/* unused */
+#define SUN_MOUSE_MINOR		6	/* unused */
+#define APOLLO_MOUSE_MINOR	7	/* unused */
+#define PC110PAD_MINOR		9	/* unused */
 /*#define ADB_MOUSE_MINOR	10	FIXME OBSOLETE */
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define RTC_MINOR		135
 #define EFI_RTC_MINOR		136	/* EFI Time services */
+#define VHCI_MINOR		137
 #define SUN_OPENPROM_MINOR	139
-#define DMAPI_MINOR		140	/* DMAPI */
+#define DMAPI_MINOR		140	/* unused */
 #define NVRAM_MINOR		144
 #define SGI_MMTIMER		153
-#define STORE_QUEUE_MINOR	155
+#define STORE_QUEUE_MINOR	155	/* unused */
 #define I2O_MINOR		166
 #define MICROCODE_MINOR		184
 #define VFIO_MINOR		196
diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h
index c257e1b211be..022055c8fb26 100644
--- a/include/linux/mlx4/driver.h
+++ b/include/linux/mlx4/driver.h
@@ -64,4 +64,16 @@ void mlx4_unregister_interface(struct mlx4_interface *intf);
 
 void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port);
 
+static inline u64 mlx4_mac_to_u64(u8 *addr)
+{
+	u64 mac = 0;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		mac <<= 8;
+		mac |= addr[i];
+	}
+	return mac;
+}
+
 #endif /* MLX4_DRIVER_H */
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 59f8ba84568b..b66e7610d4ee 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -270,9 +270,14 @@ enum {
 
 struct mlx4_wqe_ctrl_seg {
 	__be32			owner_opcode;
-	__be16			vlan_tag;
-	u8			ins_vlan;
-	u8			fence_size;
+	union {
+		struct {
+			__be16			vlan_tag;
+			u8			ins_vlan;
+			u8			fence_size;
+		};
+		__be32			bf_qpn;
+	};
 	/*
 	 * High 24 bits are SRC remote buffer; low 8 bits are flags:
 	 * [7]   SO (strong ordering)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f28f46eade6a..a620b698aada 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -175,7 +175,10 @@ extern unsigned int kobjsize(const void *objp);
  * Special vmas that are non-mergable, non-mlock()able.
  * Note: mm/huge_memory.c VM_NO_THP depends on this definition.
  */
-#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP)
+#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP)
+
+/* This mask defines which mm->def_flags a process can inherit its parent */
+#define VM_INIT_DEF_MASK	VM_NOHUGEPAGE
 
 /*
  * mapping from the currently active vm_flags protection bits (the
@@ -210,6 +213,10 @@ struct vm_fault {
 					 * is set (which is also implied by
 					 * VM_FAULT_ERROR).
 					 */
+	/* for ->map_pages() only */
+	pgoff_t max_pgoff;		/* map pages for offset from pgoff till
+					 * max_pgoff inclusive */
+	pte_t *pte;			/* pte entry associated with ->pgoff */
 };
 
 /*
@@ -221,6 +228,7 @@ struct vm_operations_struct {
 	void (*open)(struct vm_area_struct * area);
 	void (*close)(struct vm_area_struct * area);
 	int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
+	void (*map_pages)(struct vm_area_struct *vma, struct vm_fault *vmf);
 
 	/* notification that a previously read-only page is about to become
 	 * writable, if an error is returned it will cause a SIGBUS */
@@ -399,8 +407,18 @@ static inline void compound_unlock_irqrestore(struct page *page,
 
 static inline struct page *compound_head(struct page *page)
 {
-	if (unlikely(PageTail(page)))
-		return page->first_page;
+	if (unlikely(PageTail(page))) {
+		struct page *head = page->first_page;
+
+		/*
+		 * page->first_page may be a dangling pointer to an old
+		 * compound page, so recheck that it is still a tail
+		 * page before returning.
+		 */
+		smp_rmb();
+		if (likely(PageTail(page)))
+			return head;
+	}
 	return page;
 }
 
@@ -571,6 +589,9 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 		pte = pte_mkwrite(pte);
 	return pte;
 }
+
+void do_set_pte(struct vm_area_struct *vma, unsigned long address,
+		struct page *page, pte_t *pte, bool write, bool anon);
 #endif
 
 /*
@@ -757,7 +778,7 @@ static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)
 #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
 static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
 {
-	return xchg(&page->_last_cpupid, cpupid);
+	return xchg(&page->_last_cpupid, cpupid & LAST_CPUPID_MASK);
 }
 
 static inline int page_cpupid_last(struct page *page)
@@ -766,7 +787,7 @@ static inline int page_cpupid_last(struct page *page)
 }
 static inline void page_cpupid_reset_last(struct page *page)
 {
-	page->_last_cpupid = -1;
+	page->_last_cpupid = -1 & LAST_CPUPID_MASK;
 }
 #else
 static inline int page_cpupid_last(struct page *page)
@@ -1031,6 +1052,14 @@ extern void show_free_areas(unsigned int flags);
 extern bool skip_free_areas_node(unsigned int flags, int nid);
 
 int shmem_zero_setup(struct vm_area_struct *);
+#ifdef CONFIG_SHMEM
+bool shmem_mapping(struct address_space *mapping);
+#else
+static inline bool shmem_mapping(struct address_space *mapping)
+{
+	return false;
+}
+#endif
 
 extern int can_do_mlock(void);
 extern int user_shm_lock(size_t, struct user_struct *);
@@ -1067,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,
@@ -1083,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,
@@ -1477,9 +1518,15 @@ static inline void pgtable_page_dtor(struct page *page)
 
 #if USE_SPLIT_PMD_PTLOCKS
 
+static struct page *pmd_to_page(pmd_t *pmd)
+{
+	unsigned long mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
+	return virt_to_page((void *)((unsigned long) pmd & mask));
+}
+
 static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
-	return ptlock_ptr(virt_to_page(pmd));
+	return ptlock_ptr(pmd_to_page(pmd));
 }
 
 static inline bool pgtable_pmd_page_ctor(struct page *page)
@@ -1498,7 +1545,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page)
 	ptlock_free(page);
 }
 
-#define pmd_huge_pte(mm, pmd) (virt_to_page(pmd)->pmd_huge_pte)
+#define pmd_huge_pte(mm, pmd) (pmd_to_page(pmd)->pmd_huge_pte)
 
 #else
 
@@ -1642,10 +1689,8 @@ static inline int __early_pfn_to_nid(unsigned long pfn)
 #else
 /* please see mm/page_alloc.c */
 extern int __meminit early_pfn_to_nid(unsigned long pfn);
-#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
 /* there is a per-arch backend function. */
 extern int __meminit __early_pfn_to_nid(unsigned long pfn);
-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
 #endif
 
 extern void set_dma_reserve(unsigned long new_dma_reserve);
@@ -1807,9 +1852,11 @@ vm_unmapped_area(struct vm_unmapped_area_info *info)
 extern void truncate_inode_pages(struct address_space *, loff_t);
 extern void truncate_inode_pages_range(struct address_space *,
 				       loff_t lstart, loff_t lend);
+extern void truncate_inode_pages_final(struct address_space *);
 
 /* generic vm_area_ops exported for stackable file systems */
 extern int filemap_fault(struct vm_area_struct *, struct vm_fault *);
+extern void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
 
 /* mm/page-writeback.c */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 290901a8c1de..84b74080beb7 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -124,6 +124,8 @@ struct page {
 	union {
 		struct list_head lru;	/* Pageout list, eg. active_list
 					 * protected by zone->lru_lock !
+					 * Can be used as a generic list
+					 * by the page owner.
 					 */
 		struct {		/* slub per cpu partial pages */
 			struct page *next;	/* Next partial slab */
@@ -136,7 +138,6 @@ struct page {
 #endif
 		};
 
-		struct list_head list;	/* slobs list of pages */
 		struct slab *slab_page; /* slab fields */
 		struct rcu_head rcu_head;	/* Used by SLAB
 						 * when destroying via RCU
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 87079fc38011..f206e29f94d7 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -95,7 +95,7 @@ struct mmc_command {
  *              actively failing requests
  */
 
-	unsigned int		cmd_timeout_ms;	/* in milliseconds */
+	unsigned int		busy_timeout;	/* busy detect timeout in ms */
 	/* Set this flag only for blocking sanitize request */
 	bool			sanitize_busy;
 
@@ -152,7 +152,7 @@ extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
 	struct mmc_command *, int);
 extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
 extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
-			bool);
+			bool, bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
 extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 99f5709ac343..cb61ea4d6945 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -264,15 +264,12 @@ struct mmc_host {
 	u32			caps2;		/* More host capabilities */
 
 #define MMC_CAP2_BOOTPART_NOACC	(1 << 0)	/* Boot partition no access */
-#define MMC_CAP2_CACHE_CTRL	(1 << 1)	/* Allow cache control */
 #define MMC_CAP2_FULL_PWR_CYCLE	(1 << 2)	/* Can do full power cycle */
 #define MMC_CAP2_NO_MULTI_READ	(1 << 3)	/* Multiblock reads don't work */
-#define MMC_CAP2_NO_SLEEP_CMD	(1 << 4)	/* Don't allow sleep command */
 #define MMC_CAP2_HS200_1_8V_SDR	(1 << 5)        /* can support */
 #define MMC_CAP2_HS200_1_2V_SDR	(1 << 6)        /* can support */
 #define MMC_CAP2_HS200		(MMC_CAP2_HS200_1_8V_SDR | \
 				 MMC_CAP2_HS200_1_2V_SDR)
-#define MMC_CAP2_BROKEN_VOLTAGE	(1 << 7)	/* Use the broken voltage */
 #define MMC_CAP2_HC_ERASE_SZ	(1 << 9)	/* High-capacity erase size */
 #define MMC_CAP2_CD_ACTIVE_HIGH	(1 << 10)	/* Card-detect signal active high */
 #define MMC_CAP2_RO_ACTIVE_HIGH	(1 << 11)	/* Write-protect signal active high */
@@ -281,7 +278,6 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
-#define MMC_CAP2_SANITIZE	(1 << 15)		/* Support Sanitize */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -304,7 +300,7 @@ struct mmc_host {
 	unsigned int		max_req_size;	/* maximum number of bytes in one req */
 	unsigned int		max_blk_size;	/* maximum size of one mmc block */
 	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
-	unsigned int		max_discard_to;	/* max. discard timeout in ms */
+	unsigned int		max_busy_timeout; /* max busy timeout in ms */
 
 	/* private data */
 	spinlock_t		lock;		/* lock for claim and bus ops */
@@ -388,8 +384,6 @@ int mmc_power_restore_host(struct mmc_host *host);
 void mmc_detect_change(struct mmc_host *, unsigned long delay);
 void mmc_request_done(struct mmc_host *, struct mmc_request *);
 
-int mmc_cache_ctrl(struct mmc_host *, u8);
-
 static inline void mmc_signal_sdio_irq(struct mmc_host *host)
 {
 	host->ops->enable_sdio_irq(host, 0);
@@ -424,12 +418,9 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
 
 int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
 
-/* Module parameter */
-extern bool mmc_assume_removable;
-
 static inline int mmc_card_is_removable(struct mmc_host *host)
 {
-	return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable;
+	return !(host->caps & MMC_CAP_NONREMOVABLE);
 }
 
 static inline int mmc_card_keep_power(struct mmc_host *host)
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 362927c48f97..7be12b883485 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -100,6 +100,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL		(1<<5)
 /* Controller does not support HS200 */
 #define SDHCI_QUIRK2_BROKEN_HS200			(1<<6)
+/* Controller does not support DDR50 */
+#define SDHCI_QUIRK2_BROKEN_DDR50			(1<<7)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5f2052c83154..fac5509c18f0 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -142,6 +142,9 @@ enum zone_stat_item {
 	NUMA_LOCAL,		/* allocation from local node */
 	NUMA_OTHER,		/* allocation from other node */
 #endif
+	WORKINGSET_REFAULT,
+	WORKINGSET_ACTIVATE,
+	WORKINGSET_NODERECLAIM,
 	NR_ANON_TRANSPARENT_HUGEPAGES,
 	NR_FREE_CMA_PAGES,
 	NR_VM_ZONE_STAT_ITEMS };
@@ -392,6 +395,9 @@ struct zone {
 	spinlock_t		lru_lock;
 	struct lruvec		lruvec;
 
+	/* Evictions & activations on the inactive file list */
+	atomic_long_t		inactive_age;
+
 	unsigned long		pages_scanned;	   /* since last reclaim */
 	unsigned long		flags;		   /* zone flags, see below */
 
@@ -590,10 +596,10 @@ static inline bool zone_is_empty(struct zone *zone)
 
 /*
  * The NUMA zonelists are doubled because we need zonelists that restrict the
- * allocations to a single node for GFP_THISNODE.
+ * allocations to a single node for __GFP_THISNODE.
  *
  * [0]	: Zonelist with fallback
- * [1]	: No fallback (GFP_THISNODE)
+ * [1]	: No fallback (__GFP_THISNODE)
  */
 #define MAX_ZONELISTS 2
 
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 45e921401b06..9a165a213d93 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -432,6 +432,14 @@ struct spi_device_id {
 	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
+#define SPMI_NAME_SIZE	32
+#define SPMI_MODULE_PREFIX "spmi:"
+
+struct spmi_device_id {
+	char name[SPMI_NAME_SIZE];
+	kernel_ulong_t driver_data;	/* Data private to the driver */
+};
+
 /* dmi */
 enum dmi_field {
 	DMI_NONE,
@@ -564,6 +572,15 @@ struct x86_cpu_id {
 #define X86_MODEL_ANY  0
 #define X86_FEATURE_ANY 0	/* Same as FPU, you can't test for that */
 
+/*
+ * Generic table type for matching CPU features.
+ * @feature:	the bit number of the feature (0 - 65535)
+ */
+
+struct cpu_feature {
+	__u16	feature;
+};
+
 #define IPACK_ANY_FORMAT 0xff
 #define IPACK_ANY_ID (~0)
 struct ipack_device_id {
@@ -599,4 +616,9 @@ struct rio_device_id {
 	__u16 asm_did, asm_vid;
 };
 
+struct mcb_device_id {
+	__u16 device;
+	kernel_ulong_t driver_data;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index eaf60ff9ba94..5686b37e11d6 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -82,15 +82,6 @@ void sort_extable(struct exception_table_entry *start,
 void sort_main_extable(void);
 void trim_init_extable(struct module *m);
 
-#ifdef MODULE
-#define MODULE_GENERIC_TABLE(gtype, name)			\
-extern const struct gtype##_id __mod_##gtype##_table		\
-  __attribute__ ((unused, alias(__stringify(name))))
-
-#else  /* !MODULE */
-#define MODULE_GENERIC_TABLE(gtype, name)
-#endif
-
 /* Generic info of form tag = "info" */
 #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
 
@@ -141,8 +132,14 @@ extern const struct gtype##_id __mod_##gtype##_table		\
 /* What your module does. */
 #define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
 
-#define MODULE_DEVICE_TABLE(type, name)		\
-  MODULE_GENERIC_TABLE(type##_device, name)
+#ifdef MODULE
+/* Creates an alias so file2alias.c can find device table. */
+#define MODULE_DEVICE_TABLE(type, name)					\
+  extern const struct type##_device_id __mod_##type##__##name##_device_table \
+  __attribute__ ((unused, alias(__stringify(name))))
+#else  /* !MODULE */
+#define MODULE_DEVICE_TABLE(type, name)
+#endif
 
 /* Version of form [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 32f8612469d8..aa005e87d161 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -52,14 +52,6 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_MAX_CHIPS		8
 
 /*
- * This constant declares the max. oobsize / page, which
- * is supported now. If you add a chip with bigger oobsize/page
- * adjust this accordingly.
- */
-#define NAND_MAX_OOBSIZE	744
-#define NAND_MAX_PAGESIZE	8192
-
-/*
  * Constants for hardware specific CLE/ALE/NCE function
  *
  * These are bits which can be or'ed to set/clear multiple
@@ -350,6 +342,84 @@ struct nand_onfi_vendor_micron {
 	u8 param_revision;
 } __packed;
 
+struct jedec_ecc_info {
+	u8 ecc_bits;
+	u8 codeword_size;
+	__le16 bb_per_lun;
+	__le16 block_endurance;
+	u8 reserved[2];
+} __packed;
+
+/* JEDEC features */
+#define JEDEC_FEATURE_16_BIT_BUS	(1 << 0)
+
+struct nand_jedec_params {
+	/* rev info and features block */
+	/* 'J' 'E' 'S' 'D'  */
+	u8 sig[4];
+	__le16 revision;
+	__le16 features;
+	u8 opt_cmd[3];
+	__le16 sec_cmd;
+	u8 num_of_param_pages;
+	u8 reserved0[18];
+
+	/* manufacturer information block */
+	char manufacturer[12];
+	char model[20];
+	u8 jedec_id[6];
+	u8 reserved1[10];
+
+	/* memory organization block */
+	__le32 byte_per_page;
+	__le16 spare_bytes_per_page;
+	u8 reserved2[6];
+	__le32 pages_per_block;
+	__le32 blocks_per_lun;
+	u8 lun_count;
+	u8 addr_cycles;
+	u8 bits_per_cell;
+	u8 programs_per_page;
+	u8 multi_plane_addr;
+	u8 multi_plane_op_attr;
+	u8 reserved3[38];
+
+	/* electrical parameter block */
+	__le16 async_sdr_speed_grade;
+	__le16 toggle_ddr_speed_grade;
+	__le16 sync_ddr_speed_grade;
+	u8 async_sdr_features;
+	u8 toggle_ddr_features;
+	u8 sync_ddr_features;
+	__le16 t_prog;
+	__le16 t_bers;
+	__le16 t_r;
+	__le16 t_r_multi_plane;
+	__le16 t_ccs;
+	__le16 io_pin_capacitance_typ;
+	__le16 input_pin_capacitance_typ;
+	__le16 clk_pin_capacitance_typ;
+	u8 driver_strength_support;
+	__le16 t_ald;
+	u8 reserved4[36];
+
+	/* ECC and endurance block */
+	u8 guaranteed_good_blocks;
+	__le16 guaranteed_block_endurance;
+	struct jedec_ecc_info ecc_info[4];
+	u8 reserved5[29];
+
+	/* reserved */
+	u8 reserved6[148];
+
+	/* vendor */
+	__le16 vendor_rev_num;
+	u8 reserved7[88];
+
+	/* CRC for Parameter Page */
+	__le16 crc;
+} __packed;
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -435,17 +505,17 @@ struct nand_ecc_ctrl {
 
 /**
  * struct nand_buffers - buffer structure for read/write
- * @ecccalc:	buffer for calculated ECC
- * @ecccode:	buffer for ECC read from flash
- * @databuf:	buffer for data - dynamically sized
+ * @ecccalc:	buffer pointer for calculated ECC, size is oobsize.
+ * @ecccode:	buffer pointer for ECC read from flash, size is oobsize.
+ * @databuf:	buffer pointer for data, size is (page size + oobsize).
  *
  * Do not change the order of buffers. databuf and oobrbuf must be in
  * consecutive order.
  */
 struct nand_buffers {
-	uint8_t	ecccalc[NAND_MAX_OOBSIZE];
-	uint8_t	ecccode[NAND_MAX_OOBSIZE];
-	uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
+	uint8_t	*ecccalc;
+	uint8_t	*ecccode;
+	uint8_t *databuf;
 };
 
 /**
@@ -523,8 +593,12 @@ struct nand_buffers {
  * @subpagesize:	[INTERN] holds the subpagesize
  * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded),
  *			non 0 if ONFI supported.
+ * @jedec_version:	[INTERN] holds the chip JEDEC version (BCD encoded),
+ *			non 0 if JEDEC supported.
  * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
  *			supported, 0 otherwise.
+ * @jedec_params:	[INTERN] holds the JEDEC parameter page when JEDEC is
+ *			supported, 0 otherwise.
  * @read_retries:	[INTERN] the number of read retry modes supported
  * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand
@@ -597,7 +671,11 @@ struct nand_chip {
 	int badblockbits;
 
 	int onfi_version;
-	struct nand_onfi_params	onfi_params;
+	int jedec_version;
+	union {
+		struct nand_onfi_params	onfi_params;
+		struct nand_jedec_params jedec_params;
+	};
 
 	int read_retries;
 
@@ -840,4 +918,20 @@ static inline bool nand_is_slc(struct nand_chip *chip)
 {
 	return chip->bits_per_cell == 1;
 }
+
+/**
+ * Check if the opcode's address should be sent only on the lower 8 bits
+ * @command: opcode to check
+ */
+static inline int nand_opcode_8bits(unsigned int command)
+{
+	return command == NAND_CMD_READID || command == NAND_CMD_PARAM;
+}
+
+/* return the supported JEDEC features. */
+static inline int jedec_feature(struct nand_chip *chip)
+{
+	return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features)
+		: 0;
+}
 #endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index d3181936c138..c482e1d2cc49 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -46,6 +46,7 @@
  * - detects multi-task circular deadlocks and prints out all affected
  *   locks and tasks (and only those tasks)
  */
+struct mcs_spinlock;
 struct mutex {
 	/* 1: unlocked, 0: locked, negative: locked, possible waiters */
 	atomic_t		count;
@@ -55,7 +56,7 @@ struct mutex {
 	struct task_struct	*owner;
 #endif
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-	void			*spin_mlock;	/* Spinner MCS lock */
+	struct mcs_spinlock	*mcs_lock;	/* Spinner MCS lock */
 #endif
 #ifdef CONFIG_DEBUG_MUTEXES
 	const char 		*name;
@@ -179,4 +180,4 @@ extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
 # define arch_mutex_cpu_relax() cpu_relax()
 #endif
 
-#endif
+#endif /* __LINUX_MUTEX_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e8eeebd49a98..1a869488b8ae 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1147,6 +1147,89 @@ struct net_device_ops {
 							void *priv);
 };
 
+/**
+ * enum net_device_priv_flags - &struct net_device priv_flags
+ *
+ * These are the &struct net_device, they are only set internally
+ * by drivers and used in the kernel. These flags are invisible to
+ * userspace, this means that the order of these flags can change
+ * during any kernel release.
+ *
+ * You should have a pretty good reason to be extending these flags.
+ *
+ * @IFF_802_1Q_VLAN: 802.1Q VLAN device
+ * @IFF_EBRIDGE: Ethernet bridging device
+ * @IFF_SLAVE_INACTIVE: bonding slave not the curr. active
+ * @IFF_MASTER_8023AD: bonding master, 802.3ad
+ * @IFF_MASTER_ALB: bonding master, balance-alb
+ * @IFF_BONDING: bonding master or slave
+ * @IFF_SLAVE_NEEDARP: need ARPs for validation
+ * @IFF_ISATAP: ISATAP interface (RFC4214)
+ * @IFF_MASTER_ARPMON: bonding master, ARP mon in use
+ * @IFF_WAN_HDLC: WAN HDLC device
+ * @IFF_XMIT_DST_RELEASE: dev_hard_start_xmit() is allowed to
+ *	release skb->dst
+ * @IFF_DONT_BRIDGE: disallow bridging this ether dev
+ * @IFF_DISABLE_NETPOLL: disable netpoll at run-time
+ * @IFF_MACVLAN_PORT: device used as macvlan port
+ * @IFF_BRIDGE_PORT: device used as bridge port
+ * @IFF_OVS_DATAPATH: device used as Open vSwitch datapath port
+ * @IFF_TX_SKB_SHARING: The interface supports sharing skbs on transmit
+ * @IFF_UNICAST_FLT: Supports unicast filtering
+ * @IFF_TEAM_PORT: device used as team port
+ * @IFF_SUPP_NOFCS: device supports sending custom FCS
+ * @IFF_LIVE_ADDR_CHANGE: device supports hardware address
+ *	change when it's running
+ * @IFF_MACVLAN: Macvlan device
+ */
+enum netdev_priv_flags {
+	IFF_802_1Q_VLAN			= 1<<0,
+	IFF_EBRIDGE			= 1<<1,
+	IFF_SLAVE_INACTIVE		= 1<<2,
+	IFF_MASTER_8023AD		= 1<<3,
+	IFF_MASTER_ALB			= 1<<4,
+	IFF_BONDING			= 1<<5,
+	IFF_SLAVE_NEEDARP		= 1<<6,
+	IFF_ISATAP			= 1<<7,
+	IFF_MASTER_ARPMON		= 1<<8,
+	IFF_WAN_HDLC			= 1<<9,
+	IFF_XMIT_DST_RELEASE		= 1<<10,
+	IFF_DONT_BRIDGE			= 1<<11,
+	IFF_DISABLE_NETPOLL		= 1<<12,
+	IFF_MACVLAN_PORT		= 1<<13,
+	IFF_BRIDGE_PORT			= 1<<14,
+	IFF_OVS_DATAPATH		= 1<<15,
+	IFF_TX_SKB_SHARING		= 1<<16,
+	IFF_UNICAST_FLT			= 1<<17,
+	IFF_TEAM_PORT			= 1<<18,
+	IFF_SUPP_NOFCS			= 1<<19,
+	IFF_LIVE_ADDR_CHANGE		= 1<<20,
+	IFF_MACVLAN			= 1<<21,
+};
+
+#define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
+#define IFF_EBRIDGE			IFF_EBRIDGE
+#define IFF_SLAVE_INACTIVE		IFF_SLAVE_INACTIVE
+#define IFF_MASTER_8023AD		IFF_MASTER_8023AD
+#define IFF_MASTER_ALB			IFF_MASTER_ALB
+#define IFF_BONDING			IFF_BONDING
+#define IFF_SLAVE_NEEDARP		IFF_SLAVE_NEEDARP
+#define IFF_ISATAP			IFF_ISATAP
+#define IFF_MASTER_ARPMON		IFF_MASTER_ARPMON
+#define IFF_WAN_HDLC			IFF_WAN_HDLC
+#define IFF_XMIT_DST_RELEASE		IFF_XMIT_DST_RELEASE
+#define IFF_DONT_BRIDGE			IFF_DONT_BRIDGE
+#define IFF_DISABLE_NETPOLL		IFF_DISABLE_NETPOLL
+#define IFF_MACVLAN_PORT		IFF_MACVLAN_PORT
+#define IFF_BRIDGE_PORT			IFF_BRIDGE_PORT
+#define IFF_OVS_DATAPATH		IFF_OVS_DATAPATH
+#define IFF_TX_SKB_SHARING		IFF_TX_SKB_SHARING
+#define IFF_UNICAST_FLT			IFF_UNICAST_FLT
+#define IFF_TEAM_PORT			IFF_TEAM_PORT
+#define IFF_SUPP_NOFCS			IFF_SUPP_NOFCS
+#define IFF_LIVE_ADDR_CHANGE		IFF_LIVE_ADDR_CHANGE
+#define IFF_MACVLAN			IFF_MACVLAN
+
 /*
  *	The DEVICE structure.
  *	Actually, this whole structure is a big mistake.  It mixes I/O
@@ -1279,6 +1362,10 @@ struct net_device {
 						 * that share the same link
 						 * layer address
 						 */
+	unsigned short          dev_port;	/* Used to differentiate
+						 * devices that share the same
+						 * function
+						 */
 	spinlock_t		addr_list_lock;
 	struct netdev_hw_addr_list	uc;	/* Unicast mac addresses */
 	struct netdev_hw_addr_list	mc;	/* Multicast mac addresses */
@@ -1316,13 +1403,7 @@ struct net_device {
 /*
  * Cache lines mostly used on receive path (including eth_type_trans())
  */
-	unsigned long		last_rx;	/* Time of last Rx
-						 * This should not be set in
-						 * drivers, unless really needed,
-						 * because network stack (bonding)
-						 * use it if/when necessary, to
-						 * avoid dirtying this cache line.
-						 */
+	unsigned long		last_rx;	/* Time of last Rx */
 
 	/* Interface address info used in eth_type_trans() */
 	unsigned char		*dev_addr;	/* hw address, (before bcast
@@ -1729,6 +1810,20 @@ struct pcpu_sw_netstats {
 	struct u64_stats_sync   syncp;
 };
 
+#define netdev_alloc_pcpu_stats(type)				\
+({								\
+	typeof(type) *pcpu_stats = alloc_percpu(type);		\
+	if (pcpu_stats)	{					\
+		int i;						\
+		for_each_possible_cpu(i) {			\
+			typeof(type) *stat;			\
+			stat = per_cpu_ptr(pcpu_stats, i);	\
+			u64_stats_init(&stat->syncp);		\
+		}						\
+	}							\
+	pcpu_stats;						\
+})
+
 #include <linux/notifier.h>
 
 /* netdevice notifier chain. Please remember to update the rtnetlink
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b2fb167b2e6d..5624e4e2763c 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -467,9 +467,14 @@ struct nfs_lockt_res {
 };
 
 struct nfs_release_lockowner_args {
+	struct nfs4_sequence_args	seq_args;
 	struct nfs_lowner	lock_owner;
 };
 
+struct nfs_release_lockowner_res {
+	struct nfs4_sequence_res	seq_res;
+};
+
 struct nfs4_delegreturnargs {
 	struct nfs4_sequence_args	seq_args;
 	const struct nfs_fh *fhandle;
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index 98755767c7b0..ff3fea3194c6 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -82,6 +82,8 @@ struct nilfs_inode {
 	__le32	i_pad;
 };
 
+#define NILFS_MIN_INODE_SIZE		128
+
 /**
  * struct nilfs_super_root - structure of super root
  * @sr_sum: check sum
@@ -482,6 +484,8 @@ struct nilfs_dat_entry {
 	__le64 de_rsv;
 };
 
+#define NILFS_MIN_DAT_ENTRY_SIZE	32
+
 /**
  * struct nilfs_snapshot_list - snapshot list
  * @ssl_next: next checkpoint number on snapshot list
@@ -520,6 +524,8 @@ struct nilfs_checkpoint {
 	struct nilfs_inode cp_ifile_inode;
 };
 
+#define NILFS_MIN_CHECKPOINT_SIZE	(64 + NILFS_MIN_INODE_SIZE)
+
 /* checkpoint flags */
 enum {
 	NILFS_CHECKPOINT_SNAPSHOT,
@@ -615,6 +621,8 @@ struct nilfs_segment_usage {
 	__le32 su_flags;
 };
 
+#define NILFS_MIN_SEGMENT_USAGE_SIZE	16
+
 /* segment usage flag */
 enum {
 	NILFS_SEGMENT_USAGE_ACTIVE,
@@ -710,6 +718,48 @@ static inline int nilfs_suinfo_clean(const struct nilfs_suinfo *si)
 }
 
 /* ioctl */
+/**
+ * nilfs_suinfo_update - segment usage information update
+ * @sup_segnum: segment number
+ * @sup_flags: flags for which fields are active in sup_sui
+ * @sup_reserved: reserved necessary for alignment
+ * @sup_sui: segment usage information
+ */
+struct nilfs_suinfo_update {
+	__u64 sup_segnum;
+	__u32 sup_flags;
+	__u32 sup_reserved;
+	struct nilfs_suinfo sup_sui;
+};
+
+enum {
+	NILFS_SUINFO_UPDATE_LASTMOD,
+	NILFS_SUINFO_UPDATE_NBLOCKS,
+	NILFS_SUINFO_UPDATE_FLAGS,
+	__NR_NILFS_SUINFO_UPDATE_FIELDS,
+};
+
+#define NILFS_SUINFO_UPDATE_FNS(flag, name)				\
+static inline void							\
+nilfs_suinfo_update_set_##name(struct nilfs_suinfo_update *sup)		\
+{									\
+	sup->sup_flags |= 1UL << NILFS_SUINFO_UPDATE_##flag;		\
+}									\
+static inline void							\
+nilfs_suinfo_update_clear_##name(struct nilfs_suinfo_update *sup)	\
+{									\
+	sup->sup_flags &= ~(1UL << NILFS_SUINFO_UPDATE_##flag);		\
+}									\
+static inline int							\
+nilfs_suinfo_update_##name(const struct nilfs_suinfo_update *sup)	\
+{									\
+	return !!(sup->sup_flags & (1UL << NILFS_SUINFO_UPDATE_##flag));\
+}
+
+NILFS_SUINFO_UPDATE_FNS(LASTMOD, lastmod)
+NILFS_SUINFO_UPDATE_FNS(NBLOCKS, nblocks)
+NILFS_SUINFO_UPDATE_FNS(FLAGS, flags)
+
 enum {
 	NILFS_CHECKPOINT,
 	NILFS_SNAPSHOT,
@@ -863,5 +913,7 @@ struct nilfs_bdesc {
 	_IOW(NILFS_IOCTL_IDENT, 0x8B, __u64)
 #define NILFS_IOCTL_SET_ALLOC_RANGE  \
 	_IOW(NILFS_IOCTL_IDENT, 0x8C, __u64[2])
+#define NILFS_IOCTL_SET_SUINFO  \
+	_IOW(NILFS_IOCTL_IDENT, 0x8D, struct nilfs_argv)
 
 #endif	/* _LINUX_NILFS_FS_H */
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index fd4f2d1cdf6c..e110b8c266f5 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -70,6 +70,16 @@ enum {
 	IEEE802154_ATTR_PHY_NAME,
 	IEEE802154_ATTR_DEV_TYPE,
 
+	IEEE802154_ATTR_TXPOWER,
+	IEEE802154_ATTR_LBT_ENABLED,
+	IEEE802154_ATTR_CCA_MODE,
+	IEEE802154_ATTR_CCA_ED_LEVEL,
+	IEEE802154_ATTR_CSMA_RETRIES,
+	IEEE802154_ATTR_CSMA_MIN_BE,
+	IEEE802154_ATTR_CSMA_MAX_BE,
+
+	IEEE802154_ATTR_FRAME_RETRIES,
+
 	__IEEE802154_ATTR_MAX,
 };
 
@@ -122,6 +132,8 @@ enum {
 	IEEE802154_ADD_IFACE,
 	IEEE802154_DEL_IFACE,
 
+	IEEE802154_SET_PHYPARAMS,
+
 	__IEEE802154_CMD_MAX,
 };
 
diff --git a/include/linux/of.h b/include/linux/of.h
index 435cb995904d..8cc9cefb2a63 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -67,7 +67,7 @@ struct device_node {
 #endif
 };
 
-#define MAX_PHANDLE_ARGS 8
+#define MAX_PHANDLE_ARGS 16
 struct of_phandle_args {
 	struct device_node *np;
 	int args_count;
@@ -114,6 +114,26 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
 	set_bit(flag, &n->_flags);
 }
 
+static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
+{
+	clear_bit(flag, &n->_flags);
+}
+
+static inline int of_property_check_flag(struct property *p, unsigned long flag)
+{
+	return test_bit(flag, &p->_flags);
+}
+
+static inline void of_property_set_flag(struct property *p, unsigned long flag)
+{
+	set_bit(flag, &p->_flags);
+}
+
+static inline void of_property_clear_flag(struct property *p, unsigned long flag)
+{
+	clear_bit(flag, &p->_flags);
+}
+
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
 
 /*
@@ -198,6 +218,8 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
 					 const char *name,
 					 int *lenp);
+extern int of_property_count_elems_of_size(const struct device_node *np,
+				const char *propname, int elem_size);
 extern int of_property_read_u32_index(const struct device_node *np,
 				       const char *propname,
 				       u32 index, u32 *out_value);
@@ -390,6 +412,12 @@ static inline struct device_node *of_find_compatible_node(
 	return NULL;
 }
 
+static inline int of_property_count_elems_of_size(const struct device_node *np,
+			const char *propname, int elem_size)
+{
+	return -ENOSYS;
+}
+
 static inline int of_property_read_u32_index(const struct device_node *np,
 			const char *propname, u32 index, u32 *out_value)
 {
@@ -536,6 +564,74 @@ static inline struct device_node *of_find_matching_node(
 }
 
 /**
+ * of_property_count_u8_elems - Count the number of u8 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u8 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u8 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u8_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u8));
+}
+
+/**
+ * of_property_count_u16_elems - Count the number of u16 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u16 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u16 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u16_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u16));
+}
+
+/**
+ * of_property_count_u32_elems - Count the number of u32 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u32 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u32 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u32_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u32));
+}
+
+/**
+ * of_property_count_u64_elems - Count the number of u64 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u64 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u64 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u64_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u64));
+}
+
+/**
  * of_property_read_bool - Findfrom a property
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 7af25a9c9c51..41a13e70f41f 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -268,14 +268,27 @@ struct omap_dma_dev_attr {
 	u32 dev_caps;
 	u16 lch_count;
 	u16 chan_count;
-	struct omap_dma_lch *chan;
+};
+
+enum {
+	OMAP_DMA_REG_NONE,
+	OMAP_DMA_REG_16BIT,
+	OMAP_DMA_REG_2X16BIT,
+	OMAP_DMA_REG_32BIT,
+};
+
+struct omap_dma_reg {
+	u16	offset;
+	u8	stride;
+	u8	type;
 };
 
 /* System DMA platform data structure */
 struct omap_system_dma_plat_info {
+	const struct omap_dma_reg *reg_map;
+	unsigned channel_stride;
 	struct omap_dma_dev_attr *dma_attr;
 	u32 errata;
-	void (*disable_irq_lch)(int lch);
 	void (*show_dma_caps)(void);
 	void (*clear_lch_regs)(int lch);
 	void (*clear_dma)(int lch);
@@ -289,8 +302,12 @@ struct omap_system_dma_plat_info {
 #define dma_omap2plus()	0
 #endif
 #define dma_omap1()	(!dma_omap2plus())
-#define dma_omap15xx()	((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
-#define dma_omap16xx()	((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
+#define __dma_omap15xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE)
+#define __dma_omap16xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE)
+#define dma_omap15xx()	__dma_omap15xx(d)
+#define dma_omap16xx()	__dma_omap16xx(d)
+
+extern struct omap_system_dma_plat_info *omap_get_plat_info(void);
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 1710d1b060ba..532cedc8c1ee 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -25,6 +25,7 @@ enum mapping_flags {
 	AS_MM_ALL_LOCKS	= __GFP_BITS_SHIFT + 2,	/* under mm_take_all_locks() */
 	AS_UNEVICTABLE	= __GFP_BITS_SHIFT + 3,	/* e.g., ramdisk, SHM_LOCK */
 	AS_BALLOON_MAP  = __GFP_BITS_SHIFT + 4, /* balloon page special map */
+	AS_EXITING	= __GFP_BITS_SHIFT + 5, /* final truncate in progress */
 };
 
 static inline void mapping_set_error(struct address_space *mapping, int error)
@@ -69,6 +70,16 @@ static inline int mapping_balloon(struct address_space *mapping)
 	return mapping && test_bit(AS_BALLOON_MAP, &mapping->flags);
 }
 
+static inline void mapping_set_exiting(struct address_space *mapping)
+{
+	set_bit(AS_EXITING, &mapping->flags);
+}
+
+static inline int mapping_exiting(struct address_space *mapping)
+{
+	return test_bit(AS_EXITING, &mapping->flags);
+}
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
 	return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
@@ -243,12 +254,20 @@ static inline struct page *page_cache_alloc_readahead(struct address_space *x)
 
 typedef int filler_t(void *, struct page *);
 
-extern struct page * find_get_page(struct address_space *mapping,
-				pgoff_t index);
-extern struct page * find_lock_page(struct address_space *mapping,
-				pgoff_t index);
-extern struct page * find_or_create_page(struct address_space *mapping,
-				pgoff_t index, gfp_t gfp_mask);
+pgoff_t page_cache_next_hole(struct address_space *mapping,
+			     pgoff_t index, unsigned long max_scan);
+pgoff_t page_cache_prev_hole(struct address_space *mapping,
+			     pgoff_t index, unsigned long max_scan);
+
+struct page *__find_get_page(struct address_space *mapping, pgoff_t offset);
+struct page *find_get_page(struct address_space *mapping, pgoff_t offset);
+struct page *__find_lock_page(struct address_space *mapping, pgoff_t offset);
+struct page *find_lock_page(struct address_space *mapping, pgoff_t offset);
+struct page *find_or_create_page(struct address_space *mapping, pgoff_t index,
+				 gfp_t gfp_mask);
+unsigned __find_get_pages(struct address_space *mapping, pgoff_t start,
+			  unsigned int nr_pages, struct page **pages,
+			  pgoff_t *indices);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
 			unsigned int nr_pages, struct page **pages);
 unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
@@ -270,8 +289,6 @@ static inline struct page *grab_cache_page(struct address_space *mapping,
 
 extern struct page * grab_cache_page_nowait(struct address_space *mapping,
 				pgoff_t index);
-extern struct page * read_cache_page_async(struct address_space *mapping,
-				pgoff_t index, filler_t *filler, void *data);
 extern struct page * read_cache_page(struct address_space *mapping,
 				pgoff_t index, filler_t *filler, void *data);
 extern struct page * read_cache_page_gfp(struct address_space *mapping,
@@ -279,14 +296,6 @@ extern struct page * read_cache_page_gfp(struct address_space *mapping,
 extern int read_cache_pages(struct address_space *mapping,
 		struct list_head *pages, filler_t *filler, void *data);
 
-static inline struct page *read_mapping_page_async(
-				struct address_space *mapping,
-				pgoff_t index, void *data)
-{
-	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
-	return read_cache_page_async(mapping, index, filler, data);
-}
-
 static inline struct page *read_mapping_page(struct address_space *mapping,
 				pgoff_t index, void *data)
 {
@@ -307,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);
 
@@ -539,7 +576,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
 				pgoff_t index, gfp_t gfp_mask);
 extern void delete_from_page_cache(struct page *page);
-extern void __delete_from_page_cache(struct page *page);
+extern void __delete_from_page_cache(struct page *page, void *shadow);
 int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
 
 /*
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h
index e4dbfab37729..3c6b8b1e945b 100644
--- a/include/linux/pagevec.h
+++ b/include/linux/pagevec.h
@@ -22,6 +22,9 @@ struct pagevec {
 
 void __pagevec_release(struct pagevec *pvec);
 void __pagevec_lru_add(struct pagevec *pvec);
+unsigned __pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
+			  pgoff_t start, unsigned nr_pages, pgoff_t *indices);
+void pagevec_remove_exceptionals(struct pagevec *pvec);
 unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
 		pgoff_t start, unsigned nr_pages);
 unsigned pagevec_lookup_tag(struct pagevec *pvec,
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 5a462c4e5009..637a608ded0b 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -59,12 +59,12 @@ static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
 void acpiphp_init(void);
 void acpiphp_enumerate_slots(struct pci_bus *bus);
 void acpiphp_remove_slots(struct pci_bus *bus);
-void acpiphp_check_host_bridge(acpi_handle handle);
+void acpiphp_check_host_bridge(struct acpi_device *adev);
 #else
 static inline void acpiphp_init(void) { }
 static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { }
 static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
-static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
+static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
 #endif
 
 #else	/* CONFIG_ACPI */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33aa2caf0f0c..d47b352c2e11 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -29,7 +29,6 @@
 #include <linux/atomic.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/irqreturn.h>
 #include <uapi/linux/pci.h>
 
 #include <linux/pci_ids.h>
@@ -170,6 +169,8 @@ enum pci_dev_flags {
 	PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
 	/* Provide indication device is assigned by a Virtual Machine Manager */
 	PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
+	/* Flag for quirk use to store if quirk-specific ACS is enabled */
+	PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) 8,
 };
 
 enum pci_irq_reroute_variant {
@@ -461,7 +462,6 @@ struct pci_bus {
 	unsigned int		is_added:1;
 };
 
-#define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
 #define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
 
 /*
@@ -1530,6 +1530,7 @@ enum pci_fixup_pass {
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
 int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
+void pci_dev_specific_enable_acs(struct pci_dev *dev);
 #else
 static inline void pci_fixup_device(enum pci_fixup_pass pass,
 				    struct pci_dev *dev) { }
@@ -1542,6 +1543,7 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
 {
 	return -ENOTTY;
 }
+static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { }
 #endif
 
 void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
@@ -1597,7 +1599,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 #ifdef CONFIG_PCI_IOV
 int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 void pci_disable_sriov(struct pci_dev *dev);
-irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 int pci_num_vf(struct pci_dev *dev);
 int pci_vfs_assigned(struct pci_dev *dev);
 int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
@@ -1606,8 +1607,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev);
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 { return -ENODEV; }
 static inline void pci_disable_sriov(struct pci_dev *dev) { }
-static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev)
-{ return IRQ_NONE; }
 static inline int pci_num_vf(struct pci_dev *dev) { return 0; }
 static inline int pci_vfs_assigned(struct pci_dev *dev)
 { return 0; }
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 97fbecdd7a40..297a8026f454 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -528,6 +528,8 @@
 #define PCI_DEVICE_ID_AMD_15H_NB_F5	0x1605
 #define PCI_DEVICE_ID_AMD_16H_NB_F3	0x1533
 #define PCI_DEVICE_ID_AMD_16H_NB_F4	0x1534
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F3 0x1583
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F4 0x1584
 #define PCI_DEVICE_ID_AMD_CNB17H_F3	0x1703
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
@@ -2531,6 +2533,9 @@
 
 #define PCI_VENDOR_ID_INTEL		0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC	0x0008
+#define PCI_DEVICE_ID_INTEL_SNB_IMC	0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC	0x0154
+#define PCI_DEVICE_ID_INTEL_HSW_IMC	0x0c00
 #define PCI_DEVICE_ID_INTEL_PXHD_0	0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1	0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0	0x0329
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 565188ca328f..24126c4b27b5 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -74,8 +74,53 @@ typedef enum {
 	PHY_INTERFACE_MODE_RTBI,
 	PHY_INTERFACE_MODE_SMII,
 	PHY_INTERFACE_MODE_XGMII,
+	PHY_INTERFACE_MODE_MOCA,
+	PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
+/**
+ * It maps 'enum phy_interface_t' found in include/linux/phy.h
+ * into the device tree binding of 'phy-mode', so that Ethernet
+ * device driver can get phy interface from device tree.
+ */
+static inline const char *phy_modes(phy_interface_t interface)
+{
+	switch (interface) {
+	case PHY_INTERFACE_MODE_NA:
+		return "";
+	case PHY_INTERFACE_MODE_MII:
+		return "mii";
+	case PHY_INTERFACE_MODE_GMII:
+		return "gmii";
+	case PHY_INTERFACE_MODE_SGMII:
+		return "sgmii";
+	case PHY_INTERFACE_MODE_TBI:
+		return "tbi";
+	case PHY_INTERFACE_MODE_REVMII:
+		return "rev-mii";
+	case PHY_INTERFACE_MODE_RMII:
+		return "rmii";
+	case PHY_INTERFACE_MODE_RGMII:
+		return "rgmii";
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		return "rgmii-id";
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		return "rgmii-rxid";
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		return "rgmii-txid";
+	case PHY_INTERFACE_MODE_RTBI:
+		return "rtbi";
+	case PHY_INTERFACE_MODE_SMII:
+		return "smii";
+	case PHY_INTERFACE_MODE_XGMII:
+		return "xgmii";
+	case PHY_INTERFACE_MODE_MOCA:
+		return "moca";
+	default:
+		return "unknown";
+	}
+}
+
 
 #define PHY_INIT_TIMEOUT	100000
 #define PHY_STATE_TIME		1
@@ -308,6 +353,7 @@ struct phy_device {
 	struct phy_c45_device_ids c45_ids;
 	bool is_c45;
 	bool is_internal;
+	bool has_fixups;
 
 	enum phy_state state;
 
@@ -394,6 +440,11 @@ struct phy_driver {
 	u32 flags;
 
 	/*
+	 * Called to issue a PHY software reset
+	 */
+	int (*soft_reset)(struct phy_device *phydev);
+
+	/*
 	 * Called to initialize the PHY,
 	 * including after a reset
 	 */
@@ -417,6 +468,9 @@ struct phy_driver {
 	 */
 	int (*config_aneg)(struct phy_device *phydev);
 
+	/* Determines the auto negotiation result */
+	int (*aneg_done)(struct phy_device *phydev);
+
 	/* Determines the negotiated speed and duplex */
 	int (*read_status)(struct phy_device *phydev);
 
@@ -612,10 +666,12 @@ static inline int phy_read_status(struct phy_device *phydev)
 int genphy_setup_forced(struct phy_device *phydev);
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_config_aneg(struct phy_device *phydev);
+int genphy_aneg_done(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
 int genphy_read_status(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);
 int genphy_resume(struct phy_device *phydev);
+int genphy_soft_reset(struct phy_device *phydev);
 void phy_driver_unregister(struct phy_driver *drv);
 void phy_drivers_unregister(struct phy_driver *drv, int n);
 int phy_driver_register(struct phy_driver *new_driver);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ab5752692113..4d9389c79e61 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -35,7 +35,7 @@ struct pipe_buffer {
  *	@tmp_page: cached released page
  *	@readers: number of current readers of this pipe
  *	@writers: number of current writers of this pipe
- *	@files: number of struct file refering this pipe (protected by ->i_lock)
+ *	@files: number of struct file referring this pipe (protected by ->i_lock)
  *	@waiting_writers: number of writers blocked waiting for room
  *	@r_counter: reader counter
  *	@w_counter: writer counter
diff --git a/include/linux/platform_data/adau1977.h b/include/linux/platform_data/adau1977.h
new file mode 100644
index 000000000000..bed11d908f92
--- /dev/null
+++ b/include/linux/platform_data/adau1977.h
@@ -0,0 +1,45 @@
+/*
+ * ADAU1977/ADAU1978/ADAU1979 driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_ADAU1977_H__
+#define __LINUX_PLATFORM_DATA_ADAU1977_H__
+
+/**
+ * enum adau1977_micbias - ADAU1977 MICBIAS pin voltage setting
+ * @ADAU1977_MICBIAS_5V0: MICBIAS is set to 5.0 V
+ * @ADAU1977_MICBIAS_5V5: MICBIAS is set to 5.5 V
+ * @ADAU1977_MICBIAS_6V0: MICBIAS is set to 6.0 V
+ * @ADAU1977_MICBIAS_6V5: MICBIAS is set to 6.5 V
+ * @ADAU1977_MICBIAS_7V0: MICBIAS is set to 7.0 V
+ * @ADAU1977_MICBIAS_7V5: MICBIAS is set to 7.5 V
+ * @ADAU1977_MICBIAS_8V0: MICBIAS is set to 8.0 V
+ * @ADAU1977_MICBIAS_8V5: MICBIAS is set to 8.5 V
+ * @ADAU1977_MICBIAS_9V0: MICBIAS is set to 9.0 V
+ */
+enum adau1977_micbias {
+	ADAU1977_MICBIAS_5V0 = 0x0,
+	ADAU1977_MICBIAS_5V5 = 0x1,
+	ADAU1977_MICBIAS_6V0 = 0x2,
+	ADAU1977_MICBIAS_6V5 = 0x3,
+	ADAU1977_MICBIAS_7V0 = 0x4,
+	ADAU1977_MICBIAS_7V5 = 0x5,
+	ADAU1977_MICBIAS_8V0 = 0x6,
+	ADAU1977_MICBIAS_8V5 = 0x7,
+	ADAU1977_MICBIAS_9V0 = 0x8,
+};
+
+/**
+ * struct adau1977_platform_data - Platform configuration data for the ADAU1977
+ * @micbias: Specifies the voltage for the MICBIAS pin
+ */
+struct adau1977_platform_data {
+	enum adau1977_micbias micbias;
+};
+
+#endif
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h
index 9efc04dd255a..709c6f7e2f8c 100644
--- a/include/linux/platform_data/asoc-s3c.h
+++ b/include/linux/platform_data/asoc-s3c.h
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/include/plat/audio.h
- *
+/*
  * Copyright (c) 2009 Samsung Electronics Co. Ltd
  * Author: Jaswinder Singh <jassi.brar@samsung.com>
  *
diff --git a/include/linux/platform_data/asoc-s3c24xx_simtec.h b/include/linux/platform_data/asoc-s3c24xx_simtec.h
index 376af5286a3e..d220e54123aa 100644
--- a/include/linux/platform_data/asoc-s3c24xx_simtec.h
+++ b/include/linux/platform_data/asoc-s3c24xx_simtec.h
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/include/plat/audio-simtec.h
- *
+/*
  * Copyright 2008 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/include/linux/platform_data/ata-samsung_cf.h b/include/linux/platform_data/ata-samsung_cf.h
index 2a3855a8372a..c2049e3d7444 100644
--- a/include/linux/platform_data/ata-samsung_cf.h
+++ b/include/linux/platform_data/ata-samsung_cf.h
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-samsung/include/plat/ata.h
- *
+/*
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
@@ -10,8 +9,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_PLAT_ATA_H
-#define __ASM_PLAT_ATA_H __FILE__
+#ifndef __ATA_SAMSUNG_CF_H
+#define __ATA_SAMSUNG_CF_H __FILE__
 
 /**
  * struct s3c_ide_platdata - S3C IDE driver platform data.
@@ -33,4 +32,4 @@ extern void s3c64xx_ide_setup_gpio(void);
 extern void s5pc100_ide_setup_gpio(void);
 extern void s5pv210_ide_setup_gpio(void);
 
-#endif /*__ASM_PLAT_ATA_H */
+#endif /*__ATA_SAMSUNG_CF_H */
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index cea9f70133c5..e26b0c14edea 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -84,6 +84,7 @@ struct atmel_uart_data {
 	short			use_dma_rx;	/* use receive DMA? */
 	void __iomem		*regs;		/* virt. base address, if any */
 	struct serial_rs485	rs485;		/* rs485 settings */
+	int			rts_gpio;	/* optional RTS GPIO */
 };
 
  /* Touchscreen Controller */
diff --git a/include/linux/platform_data/bt-nokia-h4p.h b/include/linux/platform_data/bt-nokia-h4p.h
new file mode 100644
index 000000000000..30d169dfadf3
--- /dev/null
+++ b/include/linux/platform_data/bt-nokia-h4p.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of Nokia H4P bluetooth driver
+ *
+ * Copyright (C) 2010 Nokia 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.
+ *
+ * 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
+ *
+ */
+
+
+/**
+ * struct hci_h4p_platform data - hci_h4p Platform data structure
+ */
+struct hci_h4p_platform_data {
+	int chip_type;
+	int bt_sysclk;
+	unsigned int bt_wakeup_gpio;
+	unsigned int host_wakeup_gpio;
+	unsigned int reset_gpio;
+	int reset_gpio_shared;
+	unsigned int uart_irq;
+	phys_addr_t uart_base;
+	const char *uart_iclk;
+	const char *uart_fclk;
+	void (*set_pm_limits)(struct device *dev, bool set);
+};
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
index 280edac9d0a5..addd48cac625 100644
--- a/include/linux/platform_data/clk-integrator.h
+++ b/include/linux/platform_data/clk-integrator.h
@@ -1,3 +1,2 @@
-void integrator_clk_init(bool is_cp);
 void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
 void integrator_impd1_clk_exit(unsigned int id);
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 5245992b0367..85ad68f9206a 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -18,7 +18,7 @@
 
 #include <linux/genalloc.h>
 
-struct snd_platform_data {
+struct davinci_mcasp_pdata {
 	u32 tx_dma_offset;
 	u32 rx_dma_offset;
 	int asp_chan_q;	/* event queue number for ASP channel */
@@ -87,6 +87,8 @@ struct snd_platform_data {
 	int tx_dma_channel;
 	int rx_dma_channel;
 };
+/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */
+#define snd_platform_data davinci_mcasp_pdata
 
 enum {
 	MCASP_VERSION_1 = 0,	/* DM646x */
diff --git a/include/linux/platform_data/leds-s3c24xx.h b/include/linux/platform_data/leds-s3c24xx.h
index d8a7672519b6..441a6f290649 100644
--- a/include/linux/platform_data/leds-s3c24xx.h
+++ b/include/linux/platform_data/leds-s3c24xx.h
@@ -1,5 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/leds-gpio.h
- *
+/*
  * Copyright (c) 2006 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
@@ -11,8 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_ARCH_LEDSGPIO_H
-#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"
+#ifndef __LEDS_S3C24XX_H
+#define __LEDS_S3C24XX_H
 
 #define S3C24XX_LEDF_ACTLOW	(1<<0)		/* LED is on when GPIO low */
 #define S3C24XX_LEDF_TRISTATE	(1<<1)		/* tristate to turn off */
@@ -25,4 +24,4 @@ struct s3c24xx_led_platdata {
 	char			*def_trigger;
 };
 
-#endif /* __ASM_ARCH_LEDSGPIO_H */
+#endif /* __LEDS_S3C24XX_H */
diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h
deleted file mode 100644
index dd11dcd1a184..000000000000
--- a/include/linux/platform_data/max310x.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
- *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- *  Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
- *  Based on max3110.c, by Feng Tang <feng.tang@intel.com>
- *  Based on max3107.c, by Aavamobile
- *
- *  This program is free software; you can redistribute 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 _MAX310X_H_
-#define _MAX310X_H_
-
-/*
- * Example board initialization data:
- *
- * static struct max310x_pdata max3107_pdata = {
- *	.driver_flags	= MAX310X_EXT_CLK,
- *	.uart_flags[0]	= MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
- *	.frequency	= 3686400,
- *	.gpio_base	= -1,
- * };
- *
- * static struct spi_board_info spi_device_max3107[] = {
- *	{
- *		.modalias	= "max3107",
- *		.irq		= IRQ_EINT3,
- *		.bus_num	= 1,
- *		.chip_select	= 1,
- *		.platform_data	= &max3107_pdata,
- *	},
- * };
- */
-
-#define MAX310X_MAX_UARTS	4
-
-/* MAX310X platform data structure */
-struct max310x_pdata {
-	/* Flags global to driver */
-	const u8		driver_flags;
-#define MAX310X_EXT_CLK		(0x00000001)	/* External clock enable */
-	/* Flags global to UART port */
-	const u8		uart_flags[MAX310X_MAX_UARTS];
-#define MAX310X_LOOPBACK	(0x00000001)	/* Loopback mode enable */
-#define MAX310X_ECHO_SUPRESS	(0x00000002)	/* Enable echo supress */
-#define MAX310X_AUTO_DIR_CTRL	(0x00000004)	/* Enable Auto direction
-						 * control (RS-485)
-						 */
-	/* Frequency (extrenal clock or crystal) */
-	const int		frequency;
-	/* GPIO base number (can be negative) */
-	const int		gpio_base;
-	/* Called during startup */
-	void (*init)(void);
-	/* Called before finish */
-	void (*exit)(void);
-};
-
-#endif
diff --git a/include/linux/platform_data/mmc-msm_sdcc.h b/include/linux/platform_data/mmc-msm_sdcc.h
index ffcd9e3a6a7e..55aa873c9396 100644
--- a/include/linux/platform_data/mmc-msm_sdcc.h
+++ b/include/linux/platform_data/mmc-msm_sdcc.h
@@ -1,8 +1,5 @@
-/*
- *  arch/arm/include/asm/mach/mmc.h
- */
-#ifndef ASMARM_MACH_MMC_H
-#define ASMARM_MACH_MMC_H
+#ifndef __MMC_MSM_SDCC_H
+#define __MMC_MSM_SDCC_H
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
diff --git a/include/linux/platform_data/mmc-mvsdio.h b/include/linux/platform_data/mmc-mvsdio.h
index 1190efedcb94..d02704cd3695 100644
--- a/include/linux/platform_data/mmc-mvsdio.h
+++ b/include/linux/platform_data/mmc-mvsdio.h
@@ -1,13 +1,11 @@
 /*
- * arch/arm/plat-orion/include/plat/mvsdio.h
- *
  * 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.
  */
 
-#ifndef __MACH_MVSDIO_H
-#define __MACH_MVSDIO_H
+#ifndef __MMC_MVSDIO_H
+#define __MMC_MVSDIO_H
 
 #include <linux/mbus.h>
 
diff --git a/include/linux/platform_data/mtd-davinci-aemif.h b/include/linux/platform_data/mtd-davinci-aemif.h
index 05b293443097..97948ac2bb9b 100644
--- a/include/linux/platform_data/mtd-davinci-aemif.h
+++ b/include/linux/platform_data/mtd-davinci-aemif.h
@@ -10,6 +10,8 @@
 #ifndef _MACH_DAVINCI_AEMIF_H
 #define _MACH_DAVINCI_AEMIF_H
 
+#include <linux/platform_device.h>
+
 #define NRCSR_OFFSET		0x00
 #define AWCCR_OFFSET		0x04
 #define A1CR_OFFSET		0x10
@@ -31,6 +33,5 @@ struct davinci_aemif_timing {
 	u8	ta;
 };
 
-int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-					void __iomem *base, unsigned cs);
+int davinci_aemif_setup(struct platform_device *pdev);
 #endif
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index b64115fa93a4..36bb92172f47 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -1,5 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/nand.h
- *
+/*
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
@@ -10,6 +9,9 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __MTD_NAND_S3C2410_H
+#define __MTD_NAND_S3C2410_H
+
 /**
  * struct s3c2410_nand_set - define a set of one or more nand chips
  * @disable_ecc:	Entirely disable ECC - Dangerous
@@ -65,3 +67,5 @@ struct s3c2410_platform_nand {
  * it with the s3c_device_nand. This allows @nand to be __initdata.
 */
 extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);
+
+#endif /*__MTD_NAND_S3C2410_H */
diff --git a/include/linux/platform_data/serial-imx.h b/include/linux/platform_data/serial-imx.h
index 4adec9b154dd..3cc2e3c40914 100644
--- a/include/linux/platform_data/serial-imx.h
+++ b/include/linux/platform_data/serial-imx.h
@@ -23,8 +23,6 @@
 #define IMXUART_IRDA        (1<<1)
 
 struct imxuart_platform_data {
-	int (*init)(struct platform_device *pdev);
-	void (*exit)(struct platform_device *pdev);
 	unsigned int flags;
 	void (*irda_enable)(int enable);
 	unsigned int irda_inv_rx:1;
diff --git a/include/linux/platform_data/spi-s3c64xx.h b/include/linux/platform_data/spi-s3c64xx.h
index 8447f634c7f5..d3889b98a1a1 100644
--- a/include/linux/platform_data/spi-s3c64xx.h
+++ b/include/linux/platform_data/spi-s3c64xx.h
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
- *
+/*
  * Copyright (C) 2009 Samsung Electronics Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -8,8 +7,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __S3C64XX_PLAT_SPI_H
-#define __S3C64XX_PLAT_SPI_H
+#ifndef __SPI_S3C64XX_H
+#define __SPI_S3C64XX_H
 
 #include <linux/dmaengine.h>
 
@@ -68,4 +67,4 @@ extern int s3c64xx_spi2_cfg_gpio(void);
 extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
-#endif /* __S3C64XX_PLAT_SPI_H */
+#endif /*__SPI_S3C64XX_H */
diff --git a/include/linux/platform_data/touchscreen-s3c2410.h b/include/linux/platform_data/touchscreen-s3c2410.h
index 26fdb22e0fc2..58dc7c5ae63b 100644
--- a/include/linux/platform_data/touchscreen-s3c2410.h
+++ b/include/linux/platform_data/touchscreen-s3c2410.h
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/include/plat/ts.h
- *
+/*
  * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -7,14 +6,14 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_ARM_TS_H
-#define __ASM_ARM_TS_H
+#ifndef __TOUCHSCREEN_S3C2410_H
+#define __TOUCHSCREEN_S3C2410_H
 
 struct s3c2410_ts_mach_info {
-       int             delay;
-       int             presc;
-       int             oversampling_shift;
-	void    (*cfg_gpio)(struct platform_device *dev);
+	int delay;
+	int presc;
+	int oversampling_shift;
+	void (*cfg_gpio)(struct platform_device *dev);
 };
 
 extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
@@ -22,4 +21,4 @@ extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
 /* defined by architecture to configure gpio */
 extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev);
 
-#endif /* __ASM_ARM_TS_H */
+#endif /*__TOUCHSCREEN_S3C2410_H */
diff --git a/include/linux/platform_data/video-imxfb.h b/include/linux/platform_data/video-imxfb.h
index 9de8f062ad5d..18e908324549 100644
--- a/include/linux/platform_data/video-imxfb.h
+++ b/include/linux/platform_data/video-imxfb.h
@@ -61,24 +61,12 @@ struct imx_fb_platform_data {
 	struct imx_fb_videomode *mode;
 	int		num_modes;
 
-	u_int		cmap_greyscale:1,
-			cmap_inverse:1,
-			cmap_static:1,
-			unused:29;
-
 	u_int		pwmr;
 	u_int		lscr1;
 	u_int		dmacr;
 
-	u_char * fixed_screen_cpu;
-	dma_addr_t fixed_screen_dma;
-
 	int (*init)(struct platform_device *);
 	void (*exit)(struct platform_device *);
-
-	void (*lcd_power)(int);
-	void (*backlight_power)(int);
 };
 
-void set_imx_fb_info(struct imx_fb_platform_data *);
 #endif /* ifndef __MACH_IMXFB_H__ */
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 8c6583a53a06..e72eba63cf81 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -542,6 +542,8 @@ struct dev_pm_info {
 	unsigned int		async_suspend:1;
 	bool			is_prepared:1;	/* Owned by the PM core */
 	bool			is_suspended:1;	/* Ditto */
+	bool			is_noirq_suspended:1;
+	bool			is_late_suspended:1;
 	bool			ignore_children:1;
 	bool			early_init:1;	/* Owned by the PM core */
 	spinlock_t		lock;
@@ -582,6 +584,7 @@ struct dev_pm_info {
 	unsigned long		accounting_timestamp;
 #endif
 	struct pm_subsys_data	*subsys_data;  /* Owned by the subsystem. */
+	void (*set_latency_tolerance)(struct device *, s32);
 	struct dev_pm_qos	*qos;
 };
 
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 5a95013905c8..9ab4bf7c4646 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -32,7 +32,10 @@ enum pm_qos_flags_status {
 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE	(2000 * USEC_PER_SEC)
 #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE	(2000 * USEC_PER_SEC)
 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE	0
-#define PM_QOS_DEV_LAT_DEFAULT_VALUE		0
+#define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE	0
+#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE	0
+#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT	(-1)
+#define PM_QOS_LATENCY_ANY			((s32)(~(__u32)0 >> 1))
 
 #define PM_QOS_FLAG_NO_POWER_OFF	(1 << 0)
 #define PM_QOS_FLAG_REMOTE_WAKEUP	(1 << 1)
@@ -49,7 +52,8 @@ struct pm_qos_flags_request {
 };
 
 enum dev_pm_qos_req_type {
-	DEV_PM_QOS_LATENCY = 1,
+	DEV_PM_QOS_RESUME_LATENCY = 1,
+	DEV_PM_QOS_LATENCY_TOLERANCE,
 	DEV_PM_QOS_FLAGS,
 };
 
@@ -77,6 +81,7 @@ struct pm_qos_constraints {
 	struct plist_head list;
 	s32 target_value;	/* Do not change to 64 bit */
 	s32 default_value;
+	s32 no_constraint_value;
 	enum pm_qos_type type;
 	struct blocking_notifier_head *notifiers;
 };
@@ -87,9 +92,11 @@ struct pm_qos_flags {
 };
 
 struct dev_pm_qos {
-	struct pm_qos_constraints latency;
+	struct pm_qos_constraints resume_latency;
+	struct pm_qos_constraints latency_tolerance;
 	struct pm_qos_flags flags;
-	struct dev_pm_qos_request *latency_req;
+	struct dev_pm_qos_request *resume_latency_req;
+	struct dev_pm_qos_request *latency_tolerance_req;
 	struct dev_pm_qos_request *flags_req;
 };
 
@@ -142,7 +149,8 @@ int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier);
 void dev_pm_qos_constraints_init(struct device *dev);
 void dev_pm_qos_constraints_destroy(struct device *dev);
 int dev_pm_qos_add_ancestor_request(struct device *dev,
-				    struct dev_pm_qos_request *req, s32 value);
+				    struct dev_pm_qos_request *req,
+				    enum dev_pm_qos_req_type type, s32 value);
 #else
 static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
 							  s32 mask)
@@ -185,7 +193,9 @@ static inline void dev_pm_qos_constraints_destroy(struct device *dev)
 	dev->power.power_state = PMSG_INVALID;
 }
 static inline int dev_pm_qos_add_ancestor_request(struct device *dev,
-				    struct dev_pm_qos_request *req, s32 value)
+						  struct dev_pm_qos_request *req,
+						  enum dev_pm_qos_req_type type,
+						  s32 value)
 			{ return 0; }
 #endif
 
@@ -195,10 +205,12 @@ void dev_pm_qos_hide_latency_limit(struct device *dev);
 int dev_pm_qos_expose_flags(struct device *dev, s32 value);
 void dev_pm_qos_hide_flags(struct device *dev);
 int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set);
+s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev);
+int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val);
 
-static inline s32 dev_pm_qos_requested_latency(struct device *dev)
+static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev)
 {
-	return dev->power.qos->latency_req->data.pnode.prio;
+	return dev->power.qos->resume_latency_req->data.pnode.prio;
 }
 
 static inline s32 dev_pm_qos_requested_flags(struct device *dev)
@@ -214,8 +226,12 @@ static inline int dev_pm_qos_expose_flags(struct device *dev, s32 value)
 static inline void dev_pm_qos_hide_flags(struct device *dev) {}
 static inline int dev_pm_qos_update_flags(struct device *dev, s32 m, bool set)
 			{ return 0; }
+static inline s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev)
+			{ return PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; }
+static inline int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
+			{ return 0; }
 
-static inline s32 dev_pm_qos_requested_latency(struct device *dev) { return 0; }
+static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev) { return 0; }
 static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
 #endif
 
diff --git a/include/linux/printk.h b/include/linux/printk.h
index fa47e2708c01..8860575899f2 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -24,13 +24,9 @@ static inline int printk_get_level(const char *buffer)
 
 static inline const char *printk_skip_level(const char *buffer)
 {
-	if (printk_get_level(buffer)) {
-		switch (buffer[1]) {
-		case '0' ... '7':
-		case 'd':	/* KERN_DEFAULT */
-			return buffer + 2;
-		}
-	}
+	if (printk_get_level(buffer))
+		return buffer + 2;
+
 	return buffer;
 }
 
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index f0feafd184a0..4717f54051cb 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -7,7 +7,7 @@
 struct pwm_device;
 struct seq_file;
 
-#if IS_ENABLED(CONFIG_PWM) || IS_ENABLED(CONFIG_HAVE_PWM)
+#if IS_ENABLED(CONFIG_PWM)
 /*
  * pwm_request - request a PWM device
  */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 6965fe394c3b..1d3eee594cd6 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -46,6 +46,14 @@ void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
 void dquot_initialize(struct inode *inode);
 void dquot_drop(struct inode *inode);
 struct dquot *dqget(struct super_block *sb, struct kqid qid);
+static inline struct dquot *dqgrab(struct dquot *dquot)
+{
+	/* Make sure someone else has active reference to dquot */
+	WARN_ON_ONCE(!atomic_read(&dquot->dq_count));
+	WARN_ON_ONCE(!test_bit(DQ_ACTIVE_B, &dquot->dq_flags));
+	atomic_inc(&dquot->dq_count);
+	return dquot;
+}
 void dqput(struct dquot *dquot);
 int dquot_scan_active(struct super_block *sb,
 		      int (*fn)(struct dquot *dquot, unsigned long priv),
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 403940787be1..33170dbd9db4 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -60,6 +60,49 @@ static inline int radix_tree_is_indirect_ptr(void *ptr)
 
 #define RADIX_TREE_MAX_TAGS 3
 
+#ifdef __KERNEL__
+#define RADIX_TREE_MAP_SHIFT	(CONFIG_BASE_SMALL ? 4 : 6)
+#else
+#define RADIX_TREE_MAP_SHIFT	3	/* For more stressful testing */
+#endif
+
+#define RADIX_TREE_MAP_SIZE	(1UL << RADIX_TREE_MAP_SHIFT)
+#define RADIX_TREE_MAP_MASK	(RADIX_TREE_MAP_SIZE-1)
+
+#define RADIX_TREE_TAG_LONGS	\
+	((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
+#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
+#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
+					  RADIX_TREE_MAP_SHIFT))
+
+/* Height component in node->path */
+#define RADIX_TREE_HEIGHT_SHIFT	(RADIX_TREE_MAX_PATH + 1)
+#define RADIX_TREE_HEIGHT_MASK	((1UL << RADIX_TREE_HEIGHT_SHIFT) - 1)
+
+/* Internally used bits of node->count */
+#define RADIX_TREE_COUNT_SHIFT	(RADIX_TREE_MAP_SHIFT + 1)
+#define RADIX_TREE_COUNT_MASK	((1UL << RADIX_TREE_COUNT_SHIFT) - 1)
+
+struct radix_tree_node {
+	unsigned int	path;	/* Offset in parent & height from the bottom */
+	unsigned int	count;
+	union {
+		struct {
+			/* Used when ascending tree */
+			struct radix_tree_node *parent;
+			/* For tree user */
+			void *private_data;
+		};
+		/* Used when freeing node */
+		struct rcu_head	rcu_head;
+	};
+	/* For tree user */
+	struct list_head private_list;
+	void __rcu	*slots[RADIX_TREE_MAP_SIZE];
+	unsigned long	tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
+};
+
 /* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */
 struct radix_tree_root {
 	unsigned int		height;
@@ -101,6 +144,7 @@ do {									\
  *   concurrently with other readers.
  *
  * The notable exceptions to this rule are the following functions:
+ * __radix_tree_lookup
  * radix_tree_lookup
  * radix_tree_lookup_slot
  * radix_tree_tag_get
@@ -216,9 +260,16 @@ static inline void radix_tree_replace_slot(void **pslot, void *item)
 	rcu_assign_pointer(*pslot, item);
 }
 
+int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
+			struct radix_tree_node **nodep, void ***slotp);
 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
+void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index,
+			  struct radix_tree_node **nodep, void ***slotp);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
+bool __radix_tree_delete_node(struct radix_tree_root *root,
+			      struct radix_tree_node *node);
+void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
@@ -226,10 +277,6 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
 unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root,
 			void ***results, unsigned long *indices,
 			unsigned long first_index, unsigned int max_items);
-unsigned long radix_tree_next_hole(struct radix_tree_root *root,
-				unsigned long index, unsigned long max_scan);
-unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
-				unsigned long index, unsigned long max_scan);
 int radix_tree_preload(gfp_t gfp_mask);
 int radix_tree_maybe_preload(gfp_t gfp_mask);
 void radix_tree_init(void);
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index dbaf99084112..8183b46fbaa2 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_entry_rcu(ptr, type, member) \
-	({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
-	 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
-	})
+({ \
+	typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
+	container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
+})
 
 /**
  * Where are list_empty_rcu() and list_first_entry_rcu()?
@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_first_or_null_rcu(ptr, type, member) \
-	({struct list_head *__ptr = (ptr); \
-	  struct list_head *__next = ACCESS_ONCE(__ptr->next); \
-	  likely(__ptr != __next) ? \
-		list_entry_rcu(__next, type, member) : NULL; \
-	})
+({ \
+	struct list_head *__ptr = (ptr); \
+	struct list_head *__next = ACCESS_ONCE(__ptr->next); \
+	likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
+})
 
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 72bf3a01a4ee..00a7fd61b3c6 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -12,8 +12,8 @@
  * GNU 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2001
  *
@@ -44,7 +44,9 @@
 #include <linux/debugobjects.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
+#include <asm/barrier.h>
 
+extern int rcu_expedited; /* for sysctl */
 #ifdef CONFIG_RCU_TORTURE_TEST
 extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
@@ -314,7 +316,7 @@ static inline bool rcu_lockdep_current_cpu_online(void)
 
 static inline void rcu_lock_acquire(struct lockdep_map *map)
 {
-	lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_);
+	lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_);
 }
 
 static inline void rcu_lock_release(struct lockdep_map *map)
@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void)
 	do {								\
 		rcu_preempt_sleep_check();				\
 		rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map),	\
-				   "Illegal context switch in RCU-bh"	\
-				   " read-side critical section");	\
+				   "Illegal context switch in RCU-bh read-side critical section"); \
 		rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map),	\
-				   "Illegal context switch in RCU-sched"\
-				   " read-side critical section");	\
+				   "Illegal context switch in RCU-sched read-side critical section"); \
 	} while (0)
 
 #else /* #ifdef CONFIG_PROVE_RCU */
@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void)
 #endif /* #else #ifdef __CHECKER__ */
 
 #define __rcu_access_pointer(p, space) \
-	({ \
-		typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
-		rcu_dereference_sparse(p, space); \
-		((typeof(*p) __force __kernel *)(_________p1)); \
-	})
+({ \
+	typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
+	rcu_dereference_sparse(p, space); \
+	((typeof(*p) __force __kernel *)(_________p1)); \
+})
 #define __rcu_dereference_check(p, c, space) \
-	({ \
-		typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
-		rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
-				      " usage"); \
-		rcu_dereference_sparse(p, space); \
-		smp_read_barrier_depends(); \
-		((typeof(*p) __force __kernel *)(_________p1)); \
-	})
+({ \
+	typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
+	rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \
+	rcu_dereference_sparse(p, space); \
+	smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
+	((typeof(*p) __force __kernel *)(_________p1)); \
+})
 #define __rcu_dereference_protected(p, c, space) \
-	({ \
-		rcu_lockdep_assert(c, "suspicious rcu_dereference_protected()" \
-				      " usage"); \
-		rcu_dereference_sparse(p, space); \
-		((typeof(*p) __force __kernel *)(p)); \
-	})
+({ \
+	rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \
+	rcu_dereference_sparse(p, space); \
+	((typeof(*p) __force __kernel *)(p)); \
+})
 
 #define __rcu_access_index(p, space) \
-	({ \
-		typeof(p) _________p1 = ACCESS_ONCE(p); \
-		rcu_dereference_sparse(p, space); \
-		(_________p1); \
-	})
+({ \
+	typeof(p) _________p1 = ACCESS_ONCE(p); \
+	rcu_dereference_sparse(p, space); \
+	(_________p1); \
+})
 #define __rcu_dereference_index_check(p, c) \
-	({ \
-		typeof(p) _________p1 = ACCESS_ONCE(p); \
-		rcu_lockdep_assert(c, \
-				   "suspicious rcu_dereference_index_check()" \
-				   " usage"); \
-		smp_read_barrier_depends(); \
-		(_________p1); \
-	})
+({ \
+	typeof(p) _________p1 = ACCESS_ONCE(p); \
+	rcu_lockdep_assert(c, \
+			   "suspicious rcu_dereference_index_check() usage"); \
+	smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
+	(_________p1); \
+})
 
 /**
  * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void)
  * please be careful when making changes to rcu_assign_pointer() and the
  * other macros that it invokes.
  */
-#define rcu_assign_pointer(p, v) \
-	do { \
-		smp_wmb(); \
-		ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
-	} while (0)
-
+#define rcu_assign_pointer(p, v) smp_store_release(&p, RCU_INITIALIZER(v))
 
 /**
  * rcu_access_pointer() - fetch RCU pointer with no dereferencing
@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
 #define kfree_rcu(ptr, rcu_head)					\
 	__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
 
-#ifdef CONFIG_RCU_NOCB_CPU
+#if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL)
+static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+{
+	*delta_jiffies = ULONG_MAX;
+	return 0;
+}
+#endif /* #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) */
+
+#if defined(CONFIG_RCU_NOCB_CPU_ALL)
+static inline bool rcu_is_nocb_cpu(int cpu) { return true; }
+#elif defined(CONFIG_RCU_NOCB_CPU)
 bool rcu_is_nocb_cpu(int cpu);
 #else
 static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
-#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
+#endif
 
 
 /* Only for use by adaptive-ticks code. */
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 6f01771b571c..e8cb6e3b52a7 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -12,8 +12,8 @@
  * GNU 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
@@ -68,12 +68,6 @@ static inline void kfree_call_rcu(struct rcu_head *head,
 	call_rcu(head, func);
 }
 
-static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
-{
-	*delta_jiffies = ULONG_MAX;
-	return 0;
-}
-
 static inline void rcu_note_context_switch(int cpu)
 {
 	rcu_sched_qs(cpu);
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 72137ee8c603..e9c63884df0a 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -12,8 +12,8 @@
  * GNU 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
@@ -31,7 +31,9 @@
 #define __LINUX_RCUTREE_H
 
 void rcu_note_context_switch(int cpu);
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
 int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 void rcu_cpu_stall_reset(void);
 
 /*
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4149f1a9b003..36ef41a8c647 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -317,12 +317,16 @@ struct regmap *regmap_init(struct device *dev,
 			   const struct regmap_bus *bus,
 			   void *bus_context,
 			   const struct regmap_config *config);
+int regmap_attach_dev(struct device *dev, struct regmap *map,
+				 const struct regmap_config *config);
 struct regmap *regmap_init_i2c(struct i2c_client *i2c,
 			       const struct regmap_config *config);
 struct regmap *regmap_init_spi(struct spi_device *dev,
 			       const struct regmap_config *config);
-struct regmap *regmap_init_spmi(struct spmi_device *dev,
-			       const struct regmap_config *config);
+struct regmap *regmap_init_spmi_base(struct spmi_device *dev,
+				     const struct regmap_config *config);
+struct regmap *regmap_init_spmi_ext(struct spmi_device *dev,
+				    const struct regmap_config *config);
 struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
 				    void __iomem *regs,
 				    const struct regmap_config *config);
@@ -335,8 +339,10 @@ struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
 				    const struct regmap_config *config);
 struct regmap *devm_regmap_init_spi(struct spi_device *dev,
 				    const struct regmap_config *config);
-struct regmap *devm_regmap_init_spmi(struct spmi_device *dev,
-				     const struct regmap_config *config);
+struct regmap *devm_regmap_init_spmi_base(struct spmi_device *dev,
+					  const struct regmap_config *config);
+struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev,
+					 const struct regmap_config *config);
 struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
 					 void __iomem *regs,
 					 const struct regmap_config *config);
@@ -386,8 +392,11 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 		     const void *val, size_t val_len);
 int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 			size_t val_count);
-int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs,
+int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
 			int num_regs);
+int regmap_multi_reg_write_bypassed(struct regmap *map,
+				    const struct reg_default *regs,
+				    int num_regs);
 int regmap_raw_write_async(struct regmap *map, unsigned int reg,
 			   const void *val, size_t val_len);
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
diff --git a/include/linux/rio.h b/include/linux/rio.h
index b71d5738e683..6bda06f21930 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -83,7 +83,7 @@
 #define RIO_CTAG_UDEVID	0x0001ffff /* Unique device identifier */
 
 extern struct bus_type rio_bus_type;
-extern struct device rio_bus;
+extern struct class rio_mport_class;
 
 struct rio_mport;
 struct rio_dev;
@@ -201,6 +201,7 @@ struct rio_dev {
 #define rio_dev_f(n) list_entry(n, struct rio_dev, net_list)
 #define	to_rio_dev(n) container_of(n, struct rio_dev, dev)
 #define sw_to_rio_dev(n) container_of(n, struct rio_dev, rswitch[0])
+#define	to_rio_mport(n) container_of(n, struct rio_mport, dev)
 
 /**
  * struct rio_msg - RIO message event
@@ -248,6 +249,7 @@ enum rio_phy_type {
  * @phy_type: RapidIO phy type
  * @phys_efptr: RIO port extended features pointer
  * @name: Port name string
+ * @dev: device structure associated with an mport
  * @priv: Master port private data
  * @dma: DMA device associated with mport
  * @nscan: RapidIO network enumeration/discovery operations
@@ -272,6 +274,7 @@ struct rio_mport {
 	enum rio_phy_type phy_type;	/* RapidIO phy type */
 	u32 phys_efptr;
 	unsigned char name[RIO_MAX_MPORT_NAME];
+	struct device dev;
 	void *priv;		/* Master port private data */
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 	struct dma_device	dma;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a781dec1cd0b..ab52a9473b54 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -3,6 +3,8 @@
 
 #include <uapi/linux/sched.h>
 
+#include <linux/sched/prio.h>
+
 
 struct sched_param {
 	int sched_priority;
@@ -204,8 +206,9 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq);
 #define __TASK_STOPPED		4
 #define __TASK_TRACED		8
 /* in tsk->exit_state */
-#define EXIT_ZOMBIE		16
-#define EXIT_DEAD		32
+#define EXIT_DEAD		16
+#define EXIT_ZOMBIE		32
+#define EXIT_TRACE		(EXIT_ZOMBIE | EXIT_DEAD)
 /* in tsk->state again */
 #define TASK_DEAD		64
 #define TASK_WAKEKILL		128
@@ -1077,6 +1080,7 @@ struct sched_entity {
 #endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
+	int			depth;
 	struct sched_entity	*parent;
 	/* rq on which this entity is (to be) queued: */
 	struct cfs_rq		*cfs_rq;
@@ -1460,6 +1464,9 @@ struct task_struct {
 	struct mutex perf_event_mutex;
 	struct list_head perf_event_list;
 #endif
+#ifdef CONFIG_DEBUG_PREEMPT
+	unsigned long preempt_disable_ip;
+#endif
 #ifdef CONFIG_NUMA
 	struct mempolicy *mempolicy;	/* Protected by alloc_lock */
 	short il_next;
@@ -1470,9 +1477,10 @@ struct task_struct {
 	unsigned int numa_scan_period;
 	unsigned int numa_scan_period_max;
 	int numa_preferred_nid;
-	int numa_migrate_deferred;
 	unsigned long numa_migrate_retry;
 	u64 node_stamp;			/* migration stamp  */
+	u64 last_task_numa_placement;
+	u64 last_sum_exec_runtime;
 	struct callback_head numa_work;
 
 	struct list_head numa_entry;
@@ -1483,15 +1491,22 @@ struct task_struct {
 	 * Scheduling placement decisions are made based on the these counts.
 	 * The values remain static for the duration of a PTE scan
 	 */
-	unsigned long *numa_faults;
+	unsigned long *numa_faults_memory;
 	unsigned long total_numa_faults;
 
 	/*
 	 * numa_faults_buffer records faults per node during the current
-	 * scan window. When the scan completes, the counts in numa_faults
-	 * decay and these values are copied.
+	 * scan window. When the scan completes, the counts in
+	 * numa_faults_memory decay and these values are copied.
+	 */
+	unsigned long *numa_faults_buffer_memory;
+
+	/*
+	 * Track the nodes the process was running on when a NUMA hinting
+	 * fault was incurred.
 	 */
-	unsigned long *numa_faults_buffer;
+	unsigned long *numa_faults_cpu;
+	unsigned long *numa_faults_buffer_cpu;
 
 	/*
 	 * numa_faults_locality tracks if faults recorded during the last
@@ -1596,8 +1611,8 @@ extern void task_numa_fault(int last_node, int node, int pages, int flags);
 extern pid_t task_numa_group_id(struct task_struct *p);
 extern void set_numabalancing_state(bool enabled);
 extern void task_numa_free(struct task_struct *p);
-
-extern unsigned int sysctl_numa_balancing_migrate_deferred;
+extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page,
+					int src_nid, int dst_cpu);
 #else
 static inline void task_numa_fault(int last_node, int node, int pages,
 				   int flags)
@@ -1613,6 +1628,11 @@ static inline void set_numabalancing_state(bool enabled)
 static inline void task_numa_free(struct task_struct *p)
 {
 }
+static inline bool should_numa_migrate_memory(struct task_struct *p,
+				struct page *page, int src_nid, int dst_cpu)
+{
+	return true;
+}
 #endif
 
 static inline struct pid *task_pid(struct task_struct *task)
@@ -2080,7 +2100,16 @@ static inline void sched_autogroup_exit(struct signal_struct *sig) { }
 extern bool yield_to(struct task_struct *p, bool preempt);
 extern void set_user_nice(struct task_struct *p, long nice);
 extern int task_prio(const struct task_struct *p);
-extern int task_nice(const struct task_struct *p);
+/**
+ * task_nice - return the nice value of a given task.
+ * @p: the task in question.
+ *
+ * Return: The nice value [ -20 ... 0 ... 19 ].
+ */
+static inline int task_nice(const struct task_struct *p)
+{
+	return PRIO_TO_NICE((p)->static_prio);
+}
 extern int can_nice(const struct task_struct *p, const int nice);
 extern int task_curr(const struct task_struct *p);
 extern int idle_cpu(int cpu);
diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
new file mode 100644
index 000000000000..ac322583c820
--- /dev/null
+++ b/include/linux/sched/prio.h
@@ -0,0 +1,44 @@
+#ifndef _SCHED_PRIO_H
+#define _SCHED_PRIO_H
+
+#define MAX_NICE	19
+#define MIN_NICE	-20
+#define NICE_WIDTH	(MAX_NICE - MIN_NICE + 1)
+
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space.  This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO	100
+#define MAX_RT_PRIO		MAX_USER_RT_PRIO
+
+#define MAX_PRIO		(MAX_RT_PRIO + NICE_WIDTH)
+#define DEFAULT_PRIO		(MAX_RT_PRIO + NICE_WIDTH / 2)
+
+/*
+ * Convert user-nice values [ -20 ... 0 ... 19 ]
+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
+ * and back.
+ */
+#define NICE_TO_PRIO(nice)	((nice) + DEFAULT_PRIO)
+#define PRIO_TO_NICE(prio)	((prio) - DEFAULT_PRIO)
+
+/*
+ * 'User priority' is the nice value converted to something we
+ * can work with better when scaling various scheduler parameters,
+ * it's a [ 0 ... 39 ] range.
+ */
+#define USER_PRIO(p)		((p)-MAX_RT_PRIO)
+#define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
+#define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
+
+#endif /* _SCHED_PRIO_H */
diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h
index 34e4ebea8fce..6341f5be6e24 100644
--- a/include/linux/sched/rt.h
+++ b/include/linux/sched/rt.h
@@ -1,24 +1,7 @@
 #ifndef _SCHED_RT_H
 #define _SCHED_RT_H
 
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space.  This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO	100
-#define MAX_RT_PRIO		MAX_USER_RT_PRIO
-
-#define MAX_PRIO		(MAX_RT_PRIO + 40)
-#define DEFAULT_PRIO		(MAX_RT_PRIO + 20)
+#include <linux/sched/prio.h>
 
 static inline int rt_prio(int prio)
 {
@@ -35,6 +18,7 @@ static inline int rt_task(struct task_struct *p)
 #ifdef CONFIG_RT_MUTEXES
 extern int rt_mutex_getprio(struct task_struct *p);
 extern void rt_mutex_setprio(struct task_struct *p, int prio);
+extern int rt_mutex_check_prio(struct task_struct *task, int newprio);
 extern struct task_struct *rt_mutex_get_top_task(struct task_struct *task);
 extern void rt_mutex_adjust_pi(struct task_struct *p);
 static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
@@ -46,6 +30,12 @@ static inline int rt_mutex_getprio(struct task_struct *p)
 {
 	return p->normal_prio;
 }
+
+static inline int rt_mutex_check_prio(struct task_struct *task, int newprio)
+{
+	return 0;
+}
+
 static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
 {
 	return NULL;
diff --git a/include/linux/serial_bcm63xx.h b/include/linux/serial_bcm63xx.h
index 570e964dc899..a80aa1a5bee2 100644
--- a/include/linux/serial_bcm63xx.h
+++ b/include/linux/serial_bcm63xx.h
@@ -116,4 +116,6 @@
 					UART_FIFO_PARERR_MASK |		\
 					UART_FIFO_BRKDET_MASK)
 
+#define UART_REG_SIZE			24
+
 #endif /* _LINUX_SERIAL_BCM63XX_H */
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
index 60c72395ec6b..1f208b2a1ed6 100644
--- a/include/linux/sh_clk.h
+++ b/include/linux/sh_clk.h
@@ -52,6 +52,7 @@ struct clk {
 	unsigned long		flags;
 
 	void __iomem		*enable_reg;
+	void __iomem		*status_reg;
 	unsigned int		enable_bit;
 	void __iomem		*mapped_reg;
 
@@ -116,22 +117,26 @@ long clk_round_parent(struct clk *clk, unsigned long target,
 		      unsigned long *best_freq, unsigned long *parent_freq,
 		      unsigned int div_min, unsigned int div_max);
 
-#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags)		\
+#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _status_reg, _flags) \
 {									\
 	.parent		= _parent,					\
 	.enable_reg	= (void __iomem *)_enable_reg,			\
 	.enable_bit	= _enable_bit,					\
+	.status_reg	= _status_reg,					\
 	.flags		= _flags,					\
 }
 
-#define SH_CLK_MSTP32(_p, _r, _b, _f)					\
-	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT)
+#define SH_CLK_MSTP32(_p, _r, _b, _f)				\
+	SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_32BIT)
 
-#define SH_CLK_MSTP16(_p, _r, _b, _f)					\
-	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT)
+#define SH_CLK_MSTP32_STS(_p, _r, _b, _s, _f)			\
+	SH_CLK_MSTP(_p, _r, _b, _s, _f | CLK_ENABLE_REG_32BIT)
 
-#define SH_CLK_MSTP8(_p, _r, _b, _f)					\
-	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT)
+#define SH_CLK_MSTP16(_p, _r, _b, _f)				\
+	SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_16BIT)
+
+#define SH_CLK_MSTP8(_p, _r, _b, _f)				\
+	SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_8BIT)
 
 int sh_clk_mstp_register(struct clk *clks, int nr);
 
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 9d55438bc4ad..4d1771c2d29f 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -51,6 +51,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
 					    unsigned long flags);
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern bool shmem_mapping(struct address_space *mapping);
 extern void shmem_unlock_mapping(struct address_space *mapping);
 extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3ebbbe7b6d05..4dc1e6108df4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -32,6 +32,7 @@
 #include <linux/hrtimer.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdev_features.h>
+#include <linux/sched.h>
 #include <net/flow_keys.h>
 
 /* A. Checksumming of received packets by device.
@@ -356,11 +357,62 @@ typedef unsigned int sk_buff_data_t;
 typedef unsigned char *sk_buff_data_t;
 #endif
 
+/**
+ * struct skb_mstamp - multi resolution time stamps
+ * @stamp_us: timestamp in us resolution
+ * @stamp_jiffies: timestamp in jiffies
+ */
+struct skb_mstamp {
+	union {
+		u64		v64;
+		struct {
+			u32	stamp_us;
+			u32	stamp_jiffies;
+		};
+	};
+};
+
+/**
+ * skb_mstamp_get - get current timestamp
+ * @cl: place to store timestamps
+ */
+static inline void skb_mstamp_get(struct skb_mstamp *cl)
+{
+	u64 val = local_clock();
+
+	do_div(val, NSEC_PER_USEC);
+	cl->stamp_us = (u32)val;
+	cl->stamp_jiffies = (u32)jiffies;
+}
+
+/**
+ * skb_mstamp_delta - compute the difference in usec between two skb_mstamp
+ * @t1: pointer to newest sample
+ * @t0: pointer to oldest sample
+ */
+static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1,
+				      const struct skb_mstamp *t0)
+{
+	s32 delta_us = t1->stamp_us - t0->stamp_us;
+	u32 delta_jiffies = t1->stamp_jiffies - t0->stamp_jiffies;
+
+	/* If delta_us is negative, this might be because interval is too big,
+	 * or local_clock() drift is too big : fallback using jiffies.
+	 */
+	if (delta_us <= 0 ||
+	    delta_jiffies >= (INT_MAX / (USEC_PER_SEC / HZ)))
+
+		delta_us = jiffies_to_usecs(delta_jiffies);
+
+	return delta_us;
+}
+
+
 /** 
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
- *	@tstamp: Time we arrived
+ *	@tstamp: Time we arrived/left
  *	@sk: Socket we are owned by
  *	@dev: Device we arrived on/are leaving by
  *	@cb: Control buffer. Free for use by every layer. Put private vars here
@@ -429,7 +481,10 @@ struct sk_buff {
 	struct sk_buff		*next;
 	struct sk_buff		*prev;
 
-	ktime_t			tstamp;
+	union {
+		ktime_t		tstamp;
+		struct skb_mstamp skb_mstamp;
+	};
 
 	struct sock		*sk;
 	struct net_device	*dev;
@@ -691,6 +746,8 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
 				     unsigned int headroom);
 struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
 				int newtailroom, gfp_t priority);
+int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
+			int offset, int len);
 int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset,
 		 int len);
 int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
@@ -2038,7 +2095,7 @@ static inline void skb_propagate_pfmemalloc(struct page *page,
 }
 
 /**
- * skb_frag_page - retrieve the page refered to by a paged fragment
+ * skb_frag_page - retrieve the page referred to by a paged fragment
  * @frag: the paged fragment
  *
  * Returns the &struct page associated with @frag.
@@ -2725,7 +2782,7 @@ static inline void nf_reset(struct sk_buff *skb)
 
 static inline void nf_reset_trace(struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
 	skb->nf_trace = 0;
 #endif
 }
@@ -2742,6 +2799,9 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 	dst->nf_bridge  = src->nf_bridge;
 	nf_bridge_get(src->nf_bridge);
 #endif
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
+	dst->nf_trace = src->nf_trace;
+#endif
 }
 
 static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9260abdd67df..3dd389aa91c7 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -115,9 +115,9 @@ int slab_is_available(void);
 struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
 			unsigned long,
 			void (*)(void *));
-struct kmem_cache *
-kmem_cache_create_memcg(struct mem_cgroup *, const char *, size_t, size_t,
-			unsigned long, void (*)(void *), struct kmem_cache *);
+#ifdef CONFIG_MEMCG_KMEM
+void kmem_cache_create_memcg(struct mem_cgroup *, struct kmem_cache *);
+#endif
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
 void kmem_cache_free(struct kmem_cache *, void *);
@@ -410,7 +410,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
  *
  * %GFP_NOWAIT - Allocation will not sleep.
  *
- * %GFP_THISNODE - Allocate node-local memory only.
+ * %__GFP_THISNODE - Allocate node-local memory only.
  *
  * %GFP_DMA - Allocation suitable for DMA.
  *   Should only be used for kmalloc() caches. Otherwise, use a
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index f56bfa9e4526..f2f7398848cf 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -87,6 +87,9 @@ struct kmem_cache {
 #ifdef CONFIG_MEMCG_KMEM
 	struct memcg_cache_params *memcg_params;
 	int max_attr_size; /* for propagation, maximum size of a stored attr */
+#ifdef CONFIG_SYSFS
+	struct kset *memcg_kset;
+#endif
 #endif
 
 #ifdef CONFIG_NUMA
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 6ae004e437ea..633f5edd7470 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -17,10 +17,7 @@ extern void cpu_idle(void);
 
 typedef void (*smp_call_func_t)(void *info);
 struct call_single_data {
-	union {
-		struct list_head list;
-		struct llist_node llist;
-	};
+	struct llist_node llist;
 	smp_call_func_t func;
 	void *info;
 	u16 flags;
@@ -53,8 +50,7 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
 		smp_call_func_t func, void *info, bool wait,
 		gfp_t gfp_flags);
 
-void __smp_call_function_single(int cpuid, struct call_single_data *data,
-				int wait);
+int smp_call_function_single_async(int cpu, struct call_single_data *csd);
 
 #ifdef CONFIG_SMP
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 4203c66d8803..e713543336f1 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -24,6 +24,9 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/completion.h>
+#include <linux/scatterlist.h>
+
+struct dma_chan;
 
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -234,7 +237,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @mode_bits: flags understood by this controller driver
  * @bits_per_word_mask: A mask indicating which values of bits_per_word are
  *	supported by the driver. Bit n indicates that a bits_per_word n+1 is
- *	suported. If set, the SPI core will reject any transfer with an
+ *	supported. If set, the SPI core will reject any transfer with an
  *	unsupported bits_per_word. If not set, this value is simply ignored,
  *	and it's up to the individual driver to perform any validation.
  * @min_speed_hz: Lowest supported transfer speed
@@ -259,13 +262,14 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @cur_msg: the currently in-flight message
  * @cur_msg_prepared: spi_prepare_message was called for the currently
  *                    in-flight message
- * @xfer_completion: used by core tranfer_one_message()
+ * @xfer_completion: used by core transfer_one_message()
  * @busy: message pump is busy
  * @running: message pump is running
  * @rt: whether this queue is set to run as a realtime task
  * @auto_runtime_pm: the core should ensure a runtime PM reference is held
  *                   while the hardware is prepared, using the parent
  *                   device for the spidev
+ * @max_dma_len: Maximum length of a DMA transfer for the device.
  * @prepare_transfer_hardware: a message will soon arrive from the queue
  *	so the subsystem requests the driver to prepare the transfer hardware
  *	by issuing this call
@@ -348,6 +352,8 @@ struct spi_master {
 #define SPI_MASTER_HALF_DUPLEX	BIT(0)		/* can't do full duplex */
 #define SPI_MASTER_NO_RX	BIT(1)		/* can't do buffer read */
 #define SPI_MASTER_NO_TX	BIT(2)		/* can't do buffer write */
+#define SPI_MASTER_MUST_RX      BIT(3)		/* requires rx */
+#define SPI_MASTER_MUST_TX      BIT(4)		/* requires tx */
 
 	/* lock and mutex for SPI bus locking */
 	spinlock_t		bus_lock_spinlock;
@@ -390,6 +396,17 @@ struct spi_master {
 	void			(*cleanup)(struct spi_device *spi);
 
 	/*
+	 * Used to enable core support for DMA handling, if can_dma()
+	 * exists and returns true then the transfer will be mapped
+	 * prior to transfer_one() being called.  The driver should
+	 * not modify or store xfer and dma_tx and dma_rx must be set
+	 * while the device is prepared.
+	 */
+	bool			(*can_dma)(struct spi_master *master,
+					   struct spi_device *spi,
+					   struct spi_transfer *xfer);
+
+	/*
 	 * These hooks are for drivers that want to use the generic
 	 * master transfer queueing mechanism. If these are used, the
 	 * transfer() function above must NOT be specified by the driver.
@@ -407,7 +424,9 @@ struct spi_master {
 	bool				rt;
 	bool				auto_runtime_pm;
 	bool                            cur_msg_prepared;
+	bool				cur_msg_mapped;
 	struct completion               xfer_completion;
+	size_t				max_dma_len;
 
 	int (*prepare_transfer_hardware)(struct spi_master *master);
 	int (*transfer_one_message)(struct spi_master *master,
@@ -428,6 +447,14 @@ struct spi_master {
 
 	/* gpio chip select */
 	int			*cs_gpios;
+
+	/* DMA channels for use with core dmaengine helpers */
+	struct dma_chan		*dma_tx;
+	struct dma_chan		*dma_rx;
+
+	/* dummy data for full duplex devices */
+	void			*dummy_rx;
+	void			*dummy_tx;
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -498,7 +525,7 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * @rx_buf: data to be read (dma-safe memory), or NULL
  * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
  * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
- * @tx_nbits: number of bits used for writting. If 0 the default
+ * @tx_nbits: number of bits used for writing. If 0 the default
  *      (SPI_NBITS_SINGLE) is used.
  * @rx_nbits: number of bits used for reading. If 0 the default
  *      (SPI_NBITS_SINGLE) is used.
@@ -512,6 +539,8 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  *	(optionally) changing the chipselect status, then starting
  *	the next transfer or completing this @spi_message.
  * @transfer_list: transfers are sequenced through @spi_message.transfers
+ * @tx_sg: Scatterlist for transmit, currently not for client use
+ * @rx_sg: Scatterlist for receive, currently not for client use
  *
  * SPI transfers always write the same number of bytes as they read.
  * Protocol drivers should always provide @rx_buf and/or @tx_buf.
@@ -556,7 +585,7 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * by the results of previous messages and where the whole transaction
  * ends when the chipselect goes intactive.
  *
- * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
+ * When SPI can transfer in 1x,2x or 4x. It can get this transfer information
  * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
  * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x)
  * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
@@ -579,6 +608,8 @@ struct spi_transfer {
 
 	dma_addr_t	tx_dma;
 	dma_addr_t	rx_dma;
+	struct sg_table tx_sg;
+	struct sg_table rx_sg;
 
 	unsigned	cs_change:1;
 	unsigned	tx_nbits:3;
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
new file mode 100644
index 000000000000..91f5eab9e428
--- /dev/null
+++ b/include/linux/spmi.h
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 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.
+ */
+#ifndef _LINUX_SPMI_H
+#define _LINUX_SPMI_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* Maximum slave identifier */
+#define SPMI_MAX_SLAVE_ID		16
+
+/* SPMI Commands */
+#define SPMI_CMD_EXT_WRITE		0x00
+#define SPMI_CMD_RESET			0x10
+#define SPMI_CMD_SLEEP			0x11
+#define SPMI_CMD_SHUTDOWN		0x12
+#define SPMI_CMD_WAKEUP			0x13
+#define SPMI_CMD_AUTHENTICATE		0x14
+#define SPMI_CMD_MSTR_READ		0x15
+#define SPMI_CMD_MSTR_WRITE		0x16
+#define SPMI_CMD_TRANSFER_BUS_OWNERSHIP	0x1A
+#define SPMI_CMD_DDB_MASTER_READ	0x1B
+#define SPMI_CMD_DDB_SLAVE_READ		0x1C
+#define SPMI_CMD_EXT_READ		0x20
+#define SPMI_CMD_EXT_WRITEL		0x30
+#define SPMI_CMD_EXT_READL		0x38
+#define SPMI_CMD_WRITE			0x40
+#define SPMI_CMD_READ			0x60
+#define SPMI_CMD_ZERO_WRITE		0x80
+
+/**
+ * struct spmi_device - Basic representation of an SPMI device
+ * @dev:	Driver model representation of the device.
+ * @ctrl:	SPMI controller managing the bus hosting this device.
+ * @usid:	This devices' Unique Slave IDentifier.
+ */
+struct spmi_device {
+	struct device		dev;
+	struct spmi_controller	*ctrl;
+	u8			usid;
+};
+
+static inline struct spmi_device *to_spmi_device(struct device *d)
+{
+	return container_of(d, struct spmi_device, dev);
+}
+
+static inline void *spmi_device_get_drvdata(const struct spmi_device *sdev)
+{
+	return dev_get_drvdata(&sdev->dev);
+}
+
+static inline void spmi_device_set_drvdata(struct spmi_device *sdev, void *data)
+{
+	dev_set_drvdata(&sdev->dev, data);
+}
+
+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl);
+
+static inline void spmi_device_put(struct spmi_device *sdev)
+{
+	if (sdev)
+		put_device(&sdev->dev);
+}
+
+int spmi_device_add(struct spmi_device *sdev);
+
+void spmi_device_remove(struct spmi_device *sdev);
+
+/**
+ * struct spmi_controller - interface to the SPMI master controller
+ * @dev:	Driver model representation of the device.
+ * @nr:		board-specific number identifier for this controller/bus
+ * @cmd:	sends a non-data command sequence on the SPMI bus.
+ * @read_cmd:	sends a register read command sequence on the SPMI bus.
+ * @write_cmd:	sends a register write command sequence on the SPMI bus.
+ */
+struct spmi_controller {
+	struct device		dev;
+	unsigned int		nr;
+	int	(*cmd)(struct spmi_controller *ctrl, u8 opcode, u8 sid);
+	int	(*read_cmd)(struct spmi_controller *ctrl, u8 opcode,
+			    u8 sid, u16 addr, u8 *buf, size_t len);
+	int	(*write_cmd)(struct spmi_controller *ctrl, u8 opcode,
+			     u8 sid, u16 addr, const u8 *buf, size_t len);
+};
+
+static inline struct spmi_controller *to_spmi_controller(struct device *d)
+{
+	return container_of(d, struct spmi_controller, dev);
+}
+
+static inline
+void *spmi_controller_get_drvdata(const struct spmi_controller *ctrl)
+{
+	return dev_get_drvdata(&ctrl->dev);
+}
+
+static inline void spmi_controller_set_drvdata(struct spmi_controller *ctrl,
+					       void *data)
+{
+	dev_set_drvdata(&ctrl->dev, data);
+}
+
+struct spmi_controller *spmi_controller_alloc(struct device *parent,
+					      size_t size);
+
+/**
+ * spmi_controller_put() - decrement controller refcount
+ * @ctrl	SPMI controller.
+ */
+static inline void spmi_controller_put(struct spmi_controller *ctrl)
+{
+	if (ctrl)
+		put_device(&ctrl->dev);
+}
+
+int spmi_controller_add(struct spmi_controller *ctrl);
+void spmi_controller_remove(struct spmi_controller *ctrl);
+
+/**
+ * struct spmi_driver - SPMI slave device driver
+ * @driver:	SPMI device drivers should initialize name and owner field of
+ *		this structure.
+ * @probe:	binds this driver to a SPMI device.
+ * @remove:	unbinds this driver from the SPMI device.
+ * @shutdown:	standard shutdown callback used during powerdown/halt.
+ * @suspend:	standard suspend callback used during system suspend.
+ * @resume:	standard resume callback used during system resume.
+ *
+ * If PM runtime support is desired for a slave, a device driver can call
+ * pm_runtime_put() from their probe() routine (and a balancing
+ * pm_runtime_get() in remove()).  PM runtime support for a slave is
+ * implemented by issuing a SLEEP command to the slave on runtime_suspend(),
+ * transitioning the slave into the SLEEP state.  On runtime_resume(), a WAKEUP
+ * command is sent to the slave to bring it back to ACTIVE.
+ */
+struct spmi_driver {
+	struct device_driver driver;
+	int	(*probe)(struct spmi_device *sdev);
+	void	(*remove)(struct spmi_device *sdev);
+};
+
+static inline struct spmi_driver *to_spmi_driver(struct device_driver *d)
+{
+	return container_of(d, struct spmi_driver, driver);
+}
+
+int spmi_driver_register(struct spmi_driver *sdrv);
+
+/**
+ * spmi_driver_unregister() - unregister an SPMI client driver
+ * @sdrv:	the driver to unregister
+ */
+static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
+{
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
+}
+
+#define module_spmi_driver(__spmi_driver) \
+	module_driver(__spmi_driver, spmi_driver_register, \
+			spmi_driver_unregister)
+
+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf);
+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
+			   size_t len);
+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf,
+			    size_t len);
+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data);
+int spmi_register_zero_write(struct spmi_device *sdev, u8 data);
+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr,
+			    const u8 *buf, size_t len);
+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr,
+			     const u8 *buf, size_t len);
+int spmi_command_reset(struct spmi_device *sdev);
+int spmi_command_sleep(struct spmi_device *sdev);
+int spmi_command_wakeup(struct spmi_device *sdev);
+int spmi_command_shutdown(struct spmi_device *sdev);
+
+#endif
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 9b058eecd403..a2783cb5d275 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -12,8 +12,8 @@
  * GNU 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright (C) IBM Corporation, 2006
  * Copyright (C) Fujitsu, 2012
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/swap.h b/include/linux/swap.h
index 46ba0c6c219f..350711560753 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -260,6 +260,42 @@ struct swap_list_t {
 	int next;	/* swapfile to be used next */
 };
 
+/* linux/mm/workingset.c */
+void *workingset_eviction(struct address_space *mapping, struct page *page);
+bool workingset_refault(void *shadow);
+void workingset_activation(struct page *page);
+extern struct list_lru workingset_shadow_nodes;
+
+static inline unsigned int workingset_node_pages(struct radix_tree_node *node)
+{
+	return node->count & RADIX_TREE_COUNT_MASK;
+}
+
+static inline void workingset_node_pages_inc(struct radix_tree_node *node)
+{
+	node->count++;
+}
+
+static inline void workingset_node_pages_dec(struct radix_tree_node *node)
+{
+	node->count--;
+}
+
+static inline unsigned int workingset_node_shadows(struct radix_tree_node *node)
+{
+	return node->count >> RADIX_TREE_COUNT_SHIFT;
+}
+
+static inline void workingset_node_shadows_inc(struct radix_tree_node *node)
+{
+	node->count += 1U << RADIX_TREE_COUNT_SHIFT;
+}
+
+static inline void workingset_node_shadows_dec(struct radix_tree_node *node)
+{
+	node->count -= 1U << RADIX_TREE_COUNT_SHIFT;
+}
+
 /* linux/mm/page_alloc.c */
 extern unsigned long totalram_pages;
 extern unsigned long totalreserve_pages;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a747a77ea584..066e58f8112c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -198,6 +198,8 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 	}								\
 	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+			       qid_t id, void __user *addr);
 asmlinkage long sys_time(time_t __user *tloc);
 asmlinkage long sys_stime(time_t __user *tptr);
 asmlinkage long sys_gettimeofday(struct timeval __user *tv,
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 30b2ebee6439..fdaa0c6fc7a2 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -178,9 +178,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,
@@ -198,6 +195,7 @@ int __must_check sysfs_chmod_file(struct kobject *kobj,
 				  const struct attribute *attr, umode_t mode);
 void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
 			  const void *ns);
+bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr);
 void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
 
 int __must_check sysfs_create_bin_file(struct kobject *kobj,
@@ -246,14 +244,13 @@ void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
 
 int __must_check sysfs_init(void);
 
-#else /* CONFIG_SYSFS */
-
-static inline int sysfs_schedule_callback(struct kobject *kobj,
-		void (*func)(void *), void *data, struct module *owner)
+static inline void sysfs_enable_ns(struct kernfs_node *kn)
 {
-	return -ENOSYS;
+	return kernfs_enable_ns(kn);
 }
 
+#else /* CONFIG_SYSFS */
+
 static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
 {
 	return 0;
@@ -301,6 +298,12 @@ static inline void sysfs_remove_file_ns(struct kobject *kobj,
 {
 }
 
+static inline bool sysfs_remove_file_self(struct kobject *kobj,
+					  const struct attribute *attr)
+{
+	return false;
+}
+
 static inline void sysfs_remove_files(struct kobject *kobj,
 				     const struct attribute **attr)
 {
@@ -418,6 +421,10 @@ static inline int __must_check sysfs_init(void)
 	return 0;
 }
 
+static inline void sysfs_enable_ns(struct kernfs_node *kn)
+{
+}
+
 #endif /* CONFIG_SYSFS */
 
 static inline int __must_check sysfs_create_file(struct kobject *kobj,
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 4ad0706d40eb..239946868142 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -201,10 +201,10 @@ struct tcp_sock {
 	u32	tlp_high_seq;	/* snd_nxt at the time of TLP retransmit. */
 
 /* RTT measurement */
-	u32	srtt;		/* smoothed round trip time << 3	*/
-	u32	mdev;		/* medium deviation			*/
-	u32	mdev_max;	/* maximal mdev for the last rtt period	*/
-	u32	rttvar;		/* smoothed mdev_max			*/
+	u32	srtt_us;	/* smoothed round trip time << 3 in usecs */
+	u32	mdev_us;	/* medium deviation			*/
+	u32	mdev_max_us;	/* maximal mdev for the last rtt period	*/
+	u32	rttvar_us;	/* smoothed mdev_max			*/
 	u32	rtt_seq;	/* sequence number to update rttvar	*/
 
 	u32	packets_out;	/* Packets which are "in flight"	*/
diff --git a/include/linux/torture.h b/include/linux/torture.h
new file mode 100644
index 000000000000..b2e2b468e511
--- /dev/null
+++ b/include/linux/torture.h
@@ -0,0 +1,100 @@
+/*
+ * Common functions for in-kernel torture tests.
+ *
+ * This program is free software; you can redistribute 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, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2014
+ *
+ * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#ifndef __LINUX_TORTURE_H
+#define __LINUX_TORTURE_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/seqlock.h>
+#include <linux/lockdep.h>
+#include <linux/completion.h>
+#include <linux/debugobjects.h>
+#include <linux/bug.h>
+#include <linux/compiler.h>
+
+/* Definitions for a non-string torture-test module parameter. */
+#define torture_param(type, name, init, msg) \
+	static type name = init; \
+	module_param(name, type, 0444); \
+	MODULE_PARM_DESC(name, msg);
+
+#define TORTURE_FLAG "-torture:"
+#define TOROUT_STRING(s) \
+	pr_alert("%s" TORTURE_FLAG s "\n", torture_type)
+#define VERBOSE_TOROUT_STRING(s) \
+	do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0)
+#define VERBOSE_TOROUT_ERRSTRING(s) \
+	do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
+
+/* Definitions for a non-string torture-test module parameter. */
+#define torture_parm(type, name, init, msg) \
+	static type name = init; \
+	module_param(name, type, 0444); \
+	MODULE_PARM_DESC(name, msg);
+
+/* Definitions for online/offline exerciser. */
+int torture_onoff_init(long ooholdoff, long oointerval);
+char *torture_onoff_stats(char *page);
+bool torture_onoff_failures(void);
+
+/* Low-rider random number generator. */
+struct torture_random_state {
+	unsigned long trs_state;
+	long trs_count;
+};
+#define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 }
+unsigned long torture_random(struct torture_random_state *trsp);
+
+/* Task shuffler, which causes CPUs to occasionally go idle. */
+void torture_shuffle_task_register(struct task_struct *tp);
+int torture_shuffle_init(long shuffint);
+
+/* Test auto-shutdown handling. */
+void torture_shutdown_absorb(const char *title);
+int torture_shutdown_init(int ssecs, void (*cleanup)(void));
+
+/* Task stuttering, which forces load/no-load transitions. */
+void stutter_wait(const char *title);
+int torture_stutter_init(int s);
+
+/* Initialization and cleanup. */
+void torture_init_begin(char *ttype, bool v, int *runnable);
+void torture_init_end(void);
+bool torture_cleanup(void);
+bool torture_must_stop(void);
+bool torture_must_stop_irq(void);
+void torture_kthread_stopping(char *title);
+int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
+			     char *f, struct task_struct **tp);
+void _torture_stop_kthread(char *m, struct task_struct **tp);
+
+#define torture_create_kthread(n, arg, tp) \
+	_torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
+				"Failed to create " #n, &(tp))
+#define torture_stop_kthread(n, tp) \
+	_torture_stop_kthread("Stopping " #n " task", &(tp))
+
+#endif /* __LINUX_TORTURE_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 90b4fdc8a61f..1c3316a47d7e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -208,7 +208,7 @@ struct tty_port {
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
 	unsigned char		console:1,	/* port is a console */
-				low_latency:1;	/* direct buffer flush */
+				low_latency:1;	/* optional: tune for latency */
 	struct mutex		mutex;		/* Locking */
 	struct mutex		buf_mutex;	/* Buffer alloc lock */
 	unsigned char		*xmit_buf;	/* Optional buffer */
@@ -518,9 +518,9 @@ extern void tty_port_put(struct tty_port *port);
 
 static inline struct tty_port *tty_port_get(struct tty_port *port)
 {
-	if (port)
-		kref_get(&port->kref);
-	return port;
+	if (port && kref_get_unless_zero(&port->kref))
+		return port;
+	return NULL;
 }
 
 /* If the cts flow control is enabled, return true. */
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index b8347c207cb8..add26da2faeb 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -126,7 +126,6 @@
 
 #include <linux/fs.h>
 #include <linux/wait.h>
-#include <linux/wait.h>
 
 
 /*
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 0a4487d3fb1e..0994c0d01a09 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *	0.4	01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *		- add UI_GET_SYSNAME ioctl
  *	0.3	24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
  *		- update ff support for the changes in kernel interface
  *		- add UINPUT_VERSION
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7f6eb859873e..22de4affe9c8 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1666,6 +1666,10 @@ extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
 /* this request isn't really synchronous, but it belongs with the others */
 extern int usb_driver_set_configuration(struct usb_device *udev, int config);
 
+/* choose and set configuration for device */
+extern int usb_choose_configuration(struct usb_device *udev);
+extern int usb_set_configuration(struct usb_device *dev, int configuration);
+
 /*
  * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 708bd119627f..bbe779f640be 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -25,6 +25,7 @@ struct ci_hdrc_platform_data {
 	 */
 #define CI_HDRC_DUAL_ROLE_NOT_OTG	BIT(4)
 #define CI_HDRC_IMX28_WRITE_FIX		BIT(5)
+#define CI_HDRC_FORCE_FULLSPEED		BIT(6)
 	enum usb_dr_mode	dr_mode;
 #define CI_HDRC_CONTROLLER_RESET_EVENT		0
 #define CI_HDRC_CONTROLLER_STOPPED_EVENT	1
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index dba63f53906c..d3ca3b53837c 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -92,7 +92,7 @@ struct usb_configuration;
  * @suspend: Notifies functions when the host stops sending USB traffic.
  * @resume: Notifies functions when the host restarts USB traffic.
  * @get_status: Returns function status as a reply to
- *	GetStatus() request when the recepient is Interface.
+ *	GetStatus() request when the recipient is Interface.
  * @func_suspend: callback to be called when
  *	SetFeature(FUNCTION_SUSPEND) is reseived
  *
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c3a61853cd13..abd836e8d181 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -162,6 +162,12 @@ struct usb_ep_ops {
  *	enabled and remains valid until the endpoint is disabled.
  * @comp_desc: In case of SuperSpeed support, this is the endpoint companion
  *	descriptor that is used to configure the endpoint
+ * @has_bulk: endpoint supports bulk transfers
+ * @has_control: endpoint supports control transfers
+ * @has_interrupt: endpoint supports interrupt transfers
+ * @has_isochronous: endpoint supports isochronous transfers
+ * @has_dir_in: endpoint supports IN direction
+ * @has_dir_out: endpoint supports OUT direction
  *
  * the bus controller driver lists all the general purpose endpoints in
  * gadget->ep_list.  the control endpoint (gadget->ep0) is not in that list,
@@ -181,6 +187,13 @@ struct usb_ep {
 	u8			address;
 	const struct usb_endpoint_descriptor	*desc;
 	const struct usb_ss_ep_comp_descriptor	*comp_desc;
+
+	unsigned		has_bulk:1;
+	unsigned		has_control:1;
+	unsigned		has_interrupt:1;
+	unsigned		has_isochronous:1;
+	unsigned		has_dir_in:1;
+	unsigned		has_dir_out:1;
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 24579a0312a0..81022a52bc34 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -96,5 +96,7 @@ extern void vfio_unregister_iommu_driver(
 extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
 extern void vfio_group_put_external_user(struct vfio_group *group);
 extern int vfio_external_user_iommu_id(struct vfio_group *group);
+extern long vfio_external_check_extension(struct vfio_group *group,
+					  unsigned long arg);
 
 #endif /* VFIO_H */
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 3a712e2e7d76..486c3972c0be 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -37,6 +37,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		PGINODESTEAL, SLABS_SCANNED, KSWAPD_INODESTEAL,
 		KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY,
 		PAGEOUTRUN, ALLOCSTALL, PGROTATED,
+		DROP_PAGECACHE, DROP_SLAB,
 #ifdef CONFIG_NUMA_BALANCING
 		NUMA_PTE_UPDATES,
 		NUMA_HUGE_PTE_UPDATES,
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 67ce70c8279b..ea4476157e00 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -187,8 +187,6 @@ extern void zone_statistics(struct zone *, struct zone *, gfp_t gfp);
 #define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d)
 #define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d))
 
-extern void inc_zone_state(struct zone *, enum zone_stat_item);
-
 #ifdef CONFIG_SMP
 void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int);
 void __inc_zone_page_state(struct page *, enum zone_stat_item);
@@ -230,18 +228,18 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
 	atomic_long_inc(&vm_stat[item]);
 }
 
-static inline void __inc_zone_page_state(struct page *page,
-			enum zone_stat_item item)
-{
-	__inc_zone_state(page_zone(page), item);
-}
-
 static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
 {
 	atomic_long_dec(&zone->vm_stat[item]);
 	atomic_long_dec(&vm_stat[item]);
 }
 
+static inline void __inc_zone_page_state(struct page *page,
+			enum zone_stat_item item)
+{
+	__inc_zone_state(page_zone(page), item);
+}
+
 static inline void __dec_zone_page_state(struct page *page,
 			enum zone_stat_item item)
 {
@@ -256,6 +254,9 @@ static inline void __dec_zone_page_state(struct page *page,
 #define dec_zone_page_state __dec_zone_page_state
 #define mod_zone_page_state __mod_zone_page_state
 
+#define inc_zone_state __inc_zone_state
+#define dec_zone_state __dec_zone_state
+
 #define set_pgdat_percpu_threshold(pgdat, callback) { }
 
 static inline void refresh_cpu_vm_stats(int cpu) { }
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 704f4f652d0a..8059334a6b02 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -602,21 +602,6 @@ static inline bool keventd_up(void)
 	return system_wq != NULL;
 }
 
-/*
- * Like above, but uses del_timer() instead of del_timer_sync(). This means,
- * if it returns 0 the timer function may be running and the queueing is in
- * progress.
- */
-static inline bool __deprecated __cancel_delayed_work(struct delayed_work *work)
-{
-	bool ret;
-
-	ret = del_timer(&work->timer);
-	if (ret)
-		work_clear_pending(&work->work);
-	return ret;
-}
-
 /* used to be different but now identical to flush_work(), deprecated */
 static inline bool __deprecated flush_work_sync(struct work_struct *work)
 {
diff --git a/include/linux/xilinxfb.h b/include/linux/xilinxfb.h
deleted file mode 100644
index 5a155a968054..000000000000
--- a/include/linux/xilinxfb.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Platform device data for Xilinx Framebuffer device
- *
- * Copyright 2007 Secret Lab Technologies Ltd.
- *
- * 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.
- */
-
-#ifndef __XILINXFB_H__
-#define __XILINXFB_H__
-
-#include <linux/types.h>
-
-/* 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;
-};
-
-#endif  /* __XILINXFB_H__ */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 788d8378e587..3ee4c92afd1b 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -89,7 +89,7 @@ struct tc_action_ops {
 	struct module		*owner;
 	int     (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
 	int     (*dump)(struct sk_buff *, struct tc_action *, int, int);
-	int     (*cleanup)(struct tc_action *, int bind);
+	void	(*cleanup)(struct tc_action *, int bind);
 	int     (*lookup)(struct tc_action *, u32);
 	int     (*init)(struct net *net, struct nlattr *nla,
 			struct nlattr *est, struct tc_action *act, int ovr,
@@ -98,20 +98,18 @@ struct tc_action_ops {
 };
 
 int tcf_hash_search(struct tc_action *a, u32 index);
-void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
-int tcf_hash_release(struct tcf_common *p, int bind,
-		     struct tcf_hashinfo *hinfo);
+void tcf_hash_destroy(struct tc_action *a);
+int tcf_hash_release(struct tc_action *a, int bind);
 u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
-struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
-				  int bind);
-struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
-				   struct tc_action *a, int size,
-				   int bind);
-void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
+int tcf_hash_check(u32 index, struct tc_action *a, int bind);
+int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
+		    int size, int bind);
+void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
+void tcf_hash_insert(struct tc_action *a);
 
-int tcf_register_action(struct tc_action_ops *a);
+int tcf_register_action(struct tc_action_ops *a, unsigned int mask);
 int tcf_unregister_action(struct tc_action_ops *a);
-void tcf_action_destroy(struct list_head *actions, int bind);
+int tcf_action_destroy(struct list_head *actions, int bind);
 int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
 		    struct tcf_result *res);
 int tcf_action_init(struct net *net, struct nlattr *nla,
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 50e39a8822b4..933a9f22a05f 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -314,7 +314,7 @@ static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr)
 static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
 {
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
-	__u64 *p = (__u64 *)addr;
+	__be64 *p = (__be64 *)addr;
 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL;
 #else
 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
@@ -326,7 +326,7 @@ static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
 static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
 {
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
-	__u64 *p = (__u64 *)addr;
+	__be64 *p = (__be64 *)addr;
 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL;
 #else
 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
@@ -343,7 +343,7 @@ static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
 static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
 {
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
-	__u64 *p = (__u64 *)addr;
+	__be64 *p = (__be64 *)addr;
 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
 		((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
 		 cpu_to_be64(0xffffffffff000000UL))) == 0UL;
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index f4f9ee466791..904777c1cd24 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -65,6 +65,7 @@ struct bt_security {
 #define BT_SECURITY_LOW		1
 #define BT_SECURITY_MEDIUM	2
 #define BT_SECURITY_HIGH	3
+#define BT_SECURITY_FIPS	4
 
 #define BT_DEFER_SETUP	7
 
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 66c1cd87bfe7..be150cf8cd43 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -117,11 +117,18 @@ enum {
 	HCI_SERVICE_CACHE,
 	HCI_DEBUG_KEYS,
 	HCI_DUT_MODE,
+	HCI_FORCE_SC,
+	HCI_FORCE_STATIC_ADDR,
 	HCI_UNREGISTER,
 	HCI_USER_CHANNEL,
 
 	HCI_LE_SCAN,
 	HCI_SSP_ENABLED,
+	HCI_SC_ENABLED,
+	HCI_SC_ONLY,
+	HCI_PRIVACY,
+	HCI_RPA_EXPIRED,
+	HCI_RPA_RESOLVING,
 	HCI_HS_ENABLED,
 	HCI_LE_ENABLED,
 	HCI_ADVERTISING,
@@ -133,6 +140,7 @@ enum {
 	HCI_FAST_CONNECTABLE,
 	HCI_BREDR_ENABLED,
 	HCI_6LOWPAN_ENABLED,
+	HCI_LE_SCAN_INTERRUPTED,
 };
 
 /* A mask for the flags that are supposed to remain when a reset happens
@@ -175,6 +183,8 @@ enum {
 #define HCI_CMD_TIMEOUT		msecs_to_jiffies(2000)	/* 2 seconds */
 #define HCI_ACL_TX_TIMEOUT	msecs_to_jiffies(45000)	/* 45 seconds */
 #define HCI_AUTO_OFF_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */
+#define HCI_POWER_OFF_TIMEOUT	msecs_to_jiffies(5000)	/* 5 seconds */
+#define HCI_LE_CONN_TIMEOUT	msecs_to_jiffies(20000)	/* 20 seconds */
 
 /* HCI data types */
 #define HCI_COMMAND_PKT		0x01
@@ -282,10 +292,14 @@ enum {
 #define LMP_SYNC_TRAIN	0x04
 #define LMP_SYNC_SCAN	0x08
 
+#define LMP_SC		0x01
+#define LMP_PING	0x02
+
 /* Host features */
 #define LMP_HOST_SSP		0x01
 #define LMP_HOST_LE		0x02
 #define LMP_HOST_LE_BREDR	0x04
+#define LMP_HOST_SC		0x08
 
 /* Connection modes */
 #define HCI_CM_ACTIVE	0x0000
@@ -307,6 +321,7 @@ enum {
 #define HCI_LM_TRUSTED	0x0008
 #define HCI_LM_RELIABLE	0x0010
 #define HCI_LM_SECURE	0x0020
+#define HCI_LM_FIPS	0x0040
 
 /* Authentication types */
 #define HCI_AT_NO_BONDING		0x00
@@ -327,17 +342,24 @@ enum {
 #define HCI_LK_LOCAL_UNIT		0x01
 #define HCI_LK_REMOTE_UNIT		0x02
 #define HCI_LK_DEBUG_COMBINATION	0x03
-#define HCI_LK_UNAUTH_COMBINATION	0x04
-#define HCI_LK_AUTH_COMBINATION		0x05
+#define HCI_LK_UNAUTH_COMBINATION_P192	0x04
+#define HCI_LK_AUTH_COMBINATION_P192	0x05
 #define HCI_LK_CHANGED_COMBINATION	0x06
+#define HCI_LK_UNAUTH_COMBINATION_P256	0x07
+#define HCI_LK_AUTH_COMBINATION_P256	0x08
 /* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
 #define HCI_SMP_STK			0x80
 #define HCI_SMP_STK_SLAVE		0x81
 #define HCI_SMP_LTK			0x82
 #define HCI_SMP_LTK_SLAVE		0x83
 
+/* Long Term Key types */
+#define HCI_LTK_UNAUTH			0x00
+#define HCI_LTK_AUTH			0x01
+
 /* ---- HCI Error Codes ---- */
 #define HCI_ERROR_AUTH_FAILURE		0x05
+#define HCI_ERROR_MEMORY_EXCEEDED	0x07
 #define HCI_ERROR_CONNECTION_TIMEOUT	0x08
 #define HCI_ERROR_REJ_BAD_ADDR		0x0f
 #define HCI_ERROR_REMOTE_USER_TERM	0x13
@@ -660,6 +682,15 @@ struct hci_rp_set_csb {
 
 #define HCI_OP_START_SYNC_TRAIN		0x0443
 
+#define HCI_OP_REMOTE_OOB_EXT_DATA_REPLY	0x0445
+struct hci_cp_remote_oob_ext_data_reply {
+	bdaddr_t bdaddr;
+	__u8     hash192[16];
+	__u8     randomizer192[16];
+	__u8     hash256[16];
+	__u8     randomizer256[16];
+} __packed;
+
 #define HCI_OP_SNIFF_MODE		0x0803
 struct hci_cp_sniff_mode {
 	__le16   handle;
@@ -933,6 +964,26 @@ struct hci_rp_write_sync_train_params {
 	__le16	sync_train_int;
 } __packed;
 
+#define HCI_OP_READ_SC_SUPPORT		0x0c79
+struct hci_rp_read_sc_support {
+	__u8	status;
+	__u8	support;
+} __packed;
+
+#define HCI_OP_WRITE_SC_SUPPORT		0x0c7a
+struct hci_cp_write_sc_support {
+	__u8	support;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_OOB_EXT_DATA	0x0c7d
+struct hci_rp_read_local_oob_ext_data {
+	__u8     status;
+	__u8     hash192[16];
+	__u8     randomizer192[16];
+	__u8     hash256[16];
+	__u8     randomizer256[16];
+} __packed;
+
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
 struct hci_rp_read_local_version {
 	__u8     status;
@@ -1133,6 +1184,9 @@ struct hci_cp_le_set_scan_enable {
 	__u8     filter_dup;
 } __packed;
 
+#define HCI_LE_USE_PEER_ADDR		0x00
+#define HCI_LE_USE_WHITELIST		0x01
+
 #define HCI_OP_LE_CREATE_CONN		0x200d
 struct hci_cp_le_create_conn {
 	__le16   scan_interval;
@@ -1157,6 +1211,20 @@ struct hci_rp_le_read_white_list_size {
 	__u8	size;
 } __packed;
 
+#define HCI_OP_LE_CLEAR_WHITE_LIST	0x2010
+
+#define HCI_OP_LE_ADD_TO_WHITE_LIST	0x2011
+struct hci_cp_le_add_to_white_list {
+	__u8     bdaddr_type;
+	bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_LE_DEL_FROM_WHITE_LIST	0x2012
+struct hci_cp_le_del_from_white_list {
+	__u8     bdaddr_type;
+	bdaddr_t bdaddr;
+} __packed;
+
 #define HCI_OP_LE_CONN_UPDATE		0x2013
 struct hci_cp_le_conn_update {
 	__le16   handle;
@@ -1171,7 +1239,7 @@ struct hci_cp_le_conn_update {
 #define HCI_OP_LE_START_ENC		0x2019
 struct hci_cp_le_start_enc {
 	__le16	handle;
-	__u8	rand[8];
+	__le64	rand;
 	__le16	ediv;
 	__u8	ltk[16];
 } __packed;
@@ -1583,7 +1651,7 @@ struct hci_ev_le_conn_complete {
 #define HCI_EV_LE_LTK_REQ		0x05
 struct hci_ev_le_ltk_req {
 	__le16	handle;
-	__u8	random[8];
+	__le64	rand;
 	__le16	ediv;
 } __packed;
 
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f2f0cf5865c4..dbb788e4f265 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -99,9 +99,17 @@ struct smp_ltk {
 	u8 type;
 	u8 enc_size;
 	__le16 ediv;
-	u8 rand[8];
+	__le64 rand;
 	u8 val[16];
-} __packed;
+};
+
+struct smp_irk {
+	struct list_head list;
+	bdaddr_t rpa;
+	bdaddr_t bdaddr;
+	u8 addr_type;
+	u8 val[16];
+};
 
 struct link_key {
 	struct list_head list;
@@ -114,12 +122,17 @@ struct link_key {
 struct oob_data {
 	struct list_head list;
 	bdaddr_t bdaddr;
-	u8 hash[16];
-	u8 randomizer[16];
+	u8 hash192[16];
+	u8 randomizer192[16];
+	u8 hash256[16];
+	u8 randomizer256[16];
 };
 
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
+/* Default LE RPA expiry time, 15 minutes */
+#define HCI_DEFAULT_RPA_TIMEOUT		(15 * 60)
+
 struct amp_assoc {
 	__u16	len;
 	__u16	offset;
@@ -141,8 +154,9 @@ struct hci_dev {
 	__u8		bus;
 	__u8		dev_type;
 	bdaddr_t	bdaddr;
+	bdaddr_t	random_addr;
 	bdaddr_t	static_addr;
-	__u8		own_addr_type;
+	__u8		adv_addr_type;
 	__u8		dev_name[HCI_MAX_NAME_LENGTH];
 	__u8		short_name[HCI_MAX_SHORT_NAME_LENGTH];
 	__u8		eir[HCI_MAX_EIR_LENGTH];
@@ -167,6 +181,7 @@ struct hci_dev {
 	__u16		page_scan_interval;
 	__u16		page_scan_window;
 	__u8		page_scan_type;
+	__u8		le_adv_channel_map;
 	__u16		le_scan_interval;
 	__u16		le_scan_window;
 	__u16		le_conn_min_interval;
@@ -257,19 +272,21 @@ struct hci_dev {
 	__u32			req_status;
 	__u32			req_result;
 
-	struct list_head	mgmt_pending;
+	struct crypto_blkcipher	*tfm_aes;
 
 	struct discovery_state	discovery;
 	struct hci_conn_hash	conn_hash;
-	struct list_head	blacklist;
 
+	struct list_head	mgmt_pending;
+	struct list_head	blacklist;
 	struct list_head	uuids;
-
 	struct list_head	link_keys;
-
 	struct list_head	long_term_keys;
-
+	struct list_head	identity_resolving_keys;
 	struct list_head	remote_oob_data;
+	struct list_head	le_white_list;
+	struct list_head	le_conn_params;
+	struct list_head	pend_le_conns;
 
 	struct hci_dev_stats	stat;
 
@@ -291,6 +308,11 @@ struct hci_dev {
 	__u8			scan_rsp_data[HCI_MAX_AD_LENGTH];
 	__u8			scan_rsp_data_len;
 
+	__u8			irk[16];
+	__u32			rpa_timeout;
+	struct delayed_work	rpa_expired;
+	bdaddr_t		rpa;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -310,6 +332,10 @@ struct hci_conn {
 	__u8		dst_type;
 	bdaddr_t	src;
 	__u8		src_type;
+	bdaddr_t	init_addr;
+	__u8		init_addr_type;
+	bdaddr_t	resp_addr;
+	__u8		resp_addr_type;
 	__u16		handle;
 	__u16		state;
 	__u8		mode;
@@ -332,6 +358,8 @@ struct hci_conn {
 	__u8		passkey_entered;
 	__u16		disc_timeout;
 	__u16		setting;
+	__u16		le_conn_min_interval;
+	__u16		le_conn_max_interval;
 	unsigned long	flags;
 
 	__u8		remote_cap;
@@ -347,6 +375,7 @@ struct hci_conn {
 	struct delayed_work disc_work;
 	struct delayed_work auto_accept_work;
 	struct delayed_work idle_work;
+	struct delayed_work le_conn_timeout;
 
 	struct device	dev;
 
@@ -372,6 +401,22 @@ struct hci_chan {
 	__u8		state;
 };
 
+struct hci_conn_params {
+	struct list_head list;
+
+	bdaddr_t addr;
+	u8 addr_type;
+
+	u16 conn_min_interval;
+	u16 conn_max_interval;
+
+	enum {
+		HCI_AUTO_CONN_DISABLED,
+		HCI_AUTO_CONN_ALWAYS,
+		HCI_AUTO_CONN_LINK_LOSS,
+	} auto_connect;
+};
+
 extern struct list_head hci_dev_list;
 extern struct list_head hci_cb_list;
 extern rwlock_t hci_dev_list_lock;
@@ -446,6 +491,8 @@ enum {
 	HCI_CONN_LE_SMP_PEND,
 	HCI_CONN_MGMT_CONNECTED,
 	HCI_CONN_SSP_ENABLED,
+	HCI_CONN_SC_ENABLED,
+	HCI_CONN_AES_CCM,
 	HCI_CONN_POWER_SAVE,
 	HCI_CONN_REMOTE_OOB,
 	HCI_CONN_6LOWPAN,
@@ -458,6 +505,13 @@ static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
 	       test_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
 }
 
+static inline bool hci_conn_sc_enabled(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	return test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+	       test_bit(HCI_CONN_SC_ENABLED, &conn->flags);
+}
+
 static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
@@ -521,6 +575,13 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
 	}
 }
 
+static inline unsigned int hci_conn_count(struct hci_dev *hdev)
+{
+	struct hci_conn_hash *c = &hdev->conn_hash;
+
+	return c->acl_num + c->amp_num + c->sco_num + c->le_num;
+}
+
 static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
 								__u16 handle)
 {
@@ -594,8 +655,10 @@ void hci_chan_del(struct hci_chan *chan);
 void hci_chan_list_flush(struct hci_conn *conn);
 struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
-			     __u8 dst_type, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+				u8 dst_type, u8 sec_level, u8 auth_type);
+struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
+				 u8 sec_level, u8 auth_type);
 struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
 				 __u16 setting);
 int hci_conn_check_link_mode(struct hci_conn *conn);
@@ -606,6 +669,8 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
 
+void hci_le_conn_failed(struct hci_conn *conn, u8 status);
+
 /*
  * hci_conn_get() and hci_conn_put() are used to control the life-time of an
  * "hci_conn" object. They do not guarantee that the hci_conn object is running,
@@ -737,31 +802,64 @@ int hci_inquiry(void __user *arg);
 
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
 					 bdaddr_t *bdaddr, u8 type);
-int hci_blacklist_clear(struct hci_dev *hdev);
 int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 
-int hci_uuids_clear(struct hci_dev *hdev);
+struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev,
+					  bdaddr_t *bdaddr, u8 type);
+void hci_white_list_clear(struct hci_dev *hdev);
+int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+
+struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
+					       bdaddr_t *addr, u8 addr_type);
+int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+			u8 auto_connect, u16 conn_min_interval,
+			u16 conn_max_interval);
+void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_clear(struct hci_dev *hdev);
 
-int hci_link_keys_clear(struct hci_dev *hdev);
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+					    bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conns_clear(struct hci_dev *hdev);
+
+void hci_update_background_scan(struct hci_dev *hdev);
+
+void hci_uuids_clear(struct hci_dev *hdev);
+
+void hci_link_keys_clear(struct hci_dev *hdev);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 		     bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
-int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
-		int new_key, u8 authenticated, u8 tk[16], u8 enc_size,
-		__le16 ediv, u8 rand[8]);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
+			     bool master);
+struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			    u8 addr_type, u8 type, u8 authenticated,
+			    u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
 struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
-				     u8 addr_type);
-int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
-int hci_smp_ltks_clear(struct hci_dev *hdev);
+				     u8 addr_type, bool master);
+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
+void hci_smp_ltks_clear(struct hci_dev *hdev);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
-int hci_remote_oob_data_clear(struct hci_dev *hdev);
+struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa);
+struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 addr_type);
+struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			    u8 addr_type, u8 val[16], bdaddr_t *rpa);
+void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type);
+void hci_smp_irks_clear(struct hci_dev *hdev);
+
+void hci_remote_oob_data_clear(struct hci_dev *hdev);
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
-							bdaddr_t *bdaddr);
-int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
-								u8 *randomizer);
+					  bdaddr_t *bdaddr);
+int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			    u8 *hash, u8 *randomizer);
+int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				u8 *hash192, u8 *randomizer192,
+				u8 *hash256, u8 *randomizer256);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -803,9 +901,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_csb_slave_capable(dev)  ((dev)->features[2][0] & LMP_CSB_SLAVE)
 #define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN)
 #define lmp_sync_scan_capable(dev)  ((dev)->features[2][0] & LMP_SYNC_SCAN)
+#define lmp_sc_capable(dev)         ((dev)->features[2][1] & LMP_SC)
+#define lmp_ping_capable(dev)       ((dev)->features[2][1] & LMP_PING)
 
 /* ----- Host capabilities ----- */
 #define lmp_host_ssp_capable(dev)  ((dev)->features[1][0] & LMP_HOST_SSP)
+#define lmp_host_sc_capable(dev)   ((dev)->features[1][0] & LMP_HOST_SC)
 #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
 #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
 
@@ -1019,6 +1120,26 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
 	return false;
 }
 
+static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
+{
+	if (addr_type != 0x01)
+		return false;
+
+	if ((bdaddr->b[5] & 0xc0) == 0x40)
+	       return true;
+
+	return false;
+}
+
+static inline struct smp_irk *hci_get_irk(struct hci_dev *hdev,
+					  bdaddr_t *bdaddr, u8 addr_type)
+{
+	if (!hci_bdaddr_is_rpa(bdaddr, addr_type))
+		return NULL;
+
+	return hci_find_irk_by_rpa(hdev, bdaddr);
+}
+
 int hci_register_cb(struct hci_cb *hcb);
 int hci_unregister_cb(struct hci_cb *hcb);
 
@@ -1040,6 +1161,9 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
 		    const void *param, u8 event);
 void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
 
+void hci_req_add_le_scan_disable(struct hci_request *req);
+void hci_req_add_le_passive_scan(struct hci_request *req);
+
 struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
 			       const void *param, u32 timeout);
 struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
@@ -1085,6 +1209,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered);
 void mgmt_discoverable_timeout(struct hci_dev *hdev);
 void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
 void mgmt_connectable(struct hci_dev *hdev, u8 connectable);
+void mgmt_advertising(struct hci_dev *hdev, u8 advertising);
 void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
 void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
 		       bool persistent);
@@ -1092,7 +1217,8 @@ void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 			   u8 addr_type, u32 flags, u8 *name, u8 name_len,
 			   u8 *dev_class);
 void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			      u8 link_type, u8 addr_type, u8 reason);
+			      u8 link_type, u8 addr_type, u8 reason,
+			      bool mgmt_connected);
 void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
 			    u8 link_type, u8 addr_type, u8 status);
 void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
@@ -1122,11 +1248,13 @@ void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, u8 status);
 void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
 void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
+void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
 void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 				    u8 status);
 void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
-void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
-					     u8 *randomizer, u8 status);
+void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
+				       u8 *randomizer192, u8 *hash256,
+				       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);
@@ -1135,8 +1263,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
 int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
-void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
+void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key);
+void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
 void mgmt_reenable_advertising(struct hci_dev *hdev);
+void mgmt_smp_complete(struct hci_conn *conn, bool complete);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
@@ -1168,9 +1298,14 @@ struct hci_sec_filter {
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 					u16 latency, u16 to_multiplier);
-void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
 							__u8 ltk[16]);
 
+int hci_update_random_address(struct hci_request *req, bool require_privacy,
+			      u8 *own_addr_type);
+void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			       u8 *bdaddr_type);
+
 #define SCO_AIRMODE_MASK       0x0003
 #define SCO_AIRMODE_CVSD       0x0000
 #define SCO_AIRMODE_TRANSP     0x0003
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index dbc4a89984ca..4abdcb220e3a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -91,6 +91,7 @@ struct l2cap_conninfo {
 #define L2CAP_LM_TRUSTED	0x0008
 #define L2CAP_LM_RELIABLE	0x0010
 #define L2CAP_LM_SECURE		0x0020
+#define L2CAP_LM_FIPS		0x0040
 
 /* L2CAP command codes */
 #define L2CAP_COMMAND_REJ	0x01
@@ -623,6 +624,9 @@ struct l2cap_conn {
 	__u32			rx_len;
 	__u8			tx_ident;
 
+	struct sk_buff_head	pending_rx;
+	struct work_struct	pending_rx_work;
+
 	__u8			disc_reason;
 
 	struct delayed_work	security_timer;
@@ -647,7 +651,7 @@ struct l2cap_user {
 #define L2CAP_CHAN_RAW			1
 #define L2CAP_CHAN_CONN_LESS		2
 #define L2CAP_CHAN_CONN_ORIENTED	3
-#define L2CAP_CHAN_CONN_FIX_A2MP	4
+#define L2CAP_CHAN_FIXED		4
 
 /* ----- L2CAP socket info ----- */
 #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
@@ -853,7 +857,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
 }
 
 extern bool disable_ertm;
-extern bool enable_lecoc;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
@@ -878,6 +881,7 @@ int l2cap_ertm_init(struct l2cap_chan *chan);
 void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_conn_update_id_addr(struct hci_conn *hcon);
 void l2cap_send_conn_req(struct l2cap_chan *chan);
 void l2cap_move_start(struct l2cap_chan *chan);
 void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 518c5c84e39a..0326648fd799 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -94,6 +94,9 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_HS			0x00000100
 #define MGMT_SETTING_LE			0x00000200
 #define MGMT_SETTING_ADVERTISING	0x00000400
+#define MGMT_SETTING_SECURE_CONN	0x00000800
+#define MGMT_SETTING_DEBUG_KEYS		0x00001000
+#define MGMT_SETTING_PRIVACY		0x00002000
 
 #define MGMT_OP_READ_INFO		0x0004
 #define MGMT_READ_INFO_SIZE		0
@@ -180,11 +183,11 @@ struct mgmt_cp_load_link_keys {
 
 struct mgmt_ltk_info {
 	struct mgmt_addr_info addr;
-	__u8	authenticated;
+	__u8	type;
 	__u8	master;
 	__u8	enc_size;
 	__le16	ediv;
-	__u8	rand[8];
+	__le64	rand;
 	__u8	val[16];
 } __packed;
 
@@ -294,6 +297,12 @@ struct mgmt_rp_read_local_oob_data {
 	__u8	hash[16];
 	__u8	randomizer[16];
 } __packed;
+struct mgmt_rp_read_local_oob_ext_data {
+	__u8	hash192[16];
+	__u8	randomizer192[16];
+	__u8	hash256[16];
+	__u8	randomizer256[16];
+} __packed;
 
 #define MGMT_OP_ADD_REMOTE_OOB_DATA	0x0021
 struct mgmt_cp_add_remote_oob_data {
@@ -302,6 +311,14 @@ struct mgmt_cp_add_remote_oob_data {
 	__u8	randomizer[16];
 } __packed;
 #define MGMT_ADD_REMOTE_OOB_DATA_SIZE	(MGMT_ADDR_INFO_SIZE + 32)
+struct mgmt_cp_add_remote_oob_ext_data {
+	struct mgmt_addr_info addr;
+	__u8	hash192[16];
+	__u8	randomizer192[16];
+	__u8	hash256[16];
+	__u8	randomizer256[16];
+} __packed;
+#define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
 
 #define MGMT_OP_REMOVE_REMOTE_OOB_DATA	0x0022
 struct mgmt_cp_remove_remote_oob_data {
@@ -369,6 +386,29 @@ struct mgmt_cp_set_scan_params {
 } __packed;
 #define MGMT_SET_SCAN_PARAMS_SIZE	4
 
+#define MGMT_OP_SET_SECURE_CONN		0x002D
+
+#define MGMT_OP_SET_DEBUG_KEYS		0x002E
+
+#define MGMT_OP_SET_PRIVACY		0x002F
+struct mgmt_cp_set_privacy {
+	__u8 privacy;
+	__u8 irk[16];
+} __packed;
+#define MGMT_SET_PRIVACY_SIZE		17
+
+struct mgmt_irk_info {
+	struct mgmt_addr_info addr;
+	__u8 val[16];
+} __packed;
+
+#define MGMT_OP_LOAD_IRKS		0x0030
+struct mgmt_cp_load_irks {
+	__le16 irk_count;
+	struct mgmt_irk_info irks[0];
+} __packed;
+#define MGMT_LOAD_IRKS_SIZE		2
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
@@ -504,3 +544,10 @@ struct mgmt_ev_passkey_notify {
 	__le32	passkey;
 	__u8	entered;
 } __packed;
+
+#define MGMT_EV_NEW_IRK			0x0018
+struct mgmt_ev_new_irk {
+	__u8     store_hint;
+	bdaddr_t rpa;
+	struct mgmt_irk_info irk;
+} __packed;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 486213a1aed8..2611cc389d7d 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -238,9 +238,11 @@ int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
 								u8 channel);
 int  rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
 int  rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
+void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb);
 int  rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
 int  rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
 void rfcomm_dlc_accept(struct rfcomm_dlc *d);
+struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
 
 #define rfcomm_dlc_lock(d)     spin_lock(&d->lock)
 #define rfcomm_dlc_unlock(d)   spin_unlock(&d->lock)
@@ -295,6 +297,7 @@ struct rfcomm_conninfo {
 #define RFCOMM_LM_TRUSTED	0x0008
 #define RFCOMM_LM_RELIABLE	0x0010
 #define RFCOMM_LM_SECURE	0x0020
+#define RFCOMM_LM_FIPS		0x0040
 
 #define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
 
@@ -323,11 +326,16 @@ int  rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
 #define RFCOMMGETDEVINFO	_IOR('R', 211, int)
 #define RFCOMMSTEALDLC		_IOW('R', 220, int)
 
+/* rfcomm_dev.flags bit definitions */
 #define RFCOMM_REUSE_DLC      0
 #define RFCOMM_RELEASE_ONHUP  1
 #define RFCOMM_HANGUP_NOW     2
 #define RFCOMM_TTY_ATTACHED   3
-#define RFCOMM_TTY_RELEASED   4
+#define RFCOMM_DEFUNCT_BIT4   4	  /* don't reuse this bit - userspace visible */
+
+/* rfcomm_dev.status bit definitions */
+#define RFCOMM_DEV_RELEASED   0
+#define RFCOMM_TTY_OWNED      1
 
 struct rfcomm_dev_req {
 	s16      dev_id;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b1f84b05c67e..9f90554e88c4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1394,10 +1394,12 @@ struct cfg80211_scan_request {
 /**
  * struct cfg80211_match_set - sets of attributes to match
  *
- * @ssid: SSID to be matched
+ * @ssid: SSID to be matched; may be zero-length for no match (RSSI only)
+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
  */
 struct cfg80211_match_set {
 	struct cfg80211_ssid ssid;
+	s32 rssi_thold;
 };
 
 /**
@@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
  * @dev: the interface
  * @scan_start: start time of the scheduled scan
  * @channels: channels to scan
- * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
+ * @min_rssi_thold: for drivers only supporting a single threshold, this
+ *	contains the minimum over all matchsets
  */
 struct cfg80211_sched_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
 	u32 flags;
 	struct cfg80211_match_set *match_sets;
 	int n_match_sets;
-	s32 rssi_thold;
+	s32 min_rssi_thold;
 
 	/* internal */
 	struct wiphy *wiphy;
@@ -1701,8 +1704,14 @@ struct cfg80211_ibss_params {
  *
  * @channel: The channel to use or %NULL if not specified (auto-select based
  *	on scan results)
+ * @channel_hint: The channel of the recommended BSS for initial connection or
+ *	%NULL if not specified
  * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
  *	results)
+ * @bssid_hint: The recommended AP BSSID for initial connection to the BSS or
+ *	%NULL if not specified. Unlike the @bssid parameter, the driver is
+ *	allowed to ignore this @bssid_hint if it has knowledge of a better BSS
+ *	to use.
  * @ssid: SSID
  * @ssid_len: Length of ssid in octets
  * @auth_type: Authentication type (algorithm)
@@ -1725,11 +1734,13 @@ struct cfg80211_ibss_params {
  */
 struct cfg80211_connect_params {
 	struct ieee80211_channel *channel;
-	u8 *bssid;
-	u8 *ssid;
+	struct ieee80211_channel *channel_hint;
+	const u8 *bssid;
+	const u8 *bssid_hint;
+	const u8 *ssid;
 	size_t ssid_len;
 	enum nl80211_auth_type auth_type;
-	u8 *ie;
+	const u8 *ie;
 	size_t ie_len;
 	bool privacy;
 	enum nl80211_mfp mfp;
@@ -1768,6 +1779,7 @@ struct cfg80211_bitrate_mask {
 		u32 legacy;
 		u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
 		u16 vht_mcs[NL80211_VHT_NSS_MAX];
+		enum nl80211_txrate_gi gi;
 	} control[IEEE80211_NUM_BANDS];
 };
 /**
@@ -2875,6 +2887,11 @@ struct wiphy_vendor_command {
  * @n_vendor_commands: number of vendor commands
  * @vendor_events: array of vendor events supported by the hardware
  * @n_vendor_events: number of vendor events
+ *
+ * @max_ap_assoc_sta: maximum number of associated stations supported in AP mode
+ *	(including P2P GO) or 0 to indicate no such limit is advertised. The
+ *	driver is allowed to advertise a theoretical limit that it can reach in
+ *	some cases, but may not always reach.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2990,6 +3007,8 @@ struct wiphy {
 	const struct nl80211_vendor_cmd_info *vendor_events;
 	int n_vendor_commands, n_vendor_events;
 
+	u16 max_ap_assoc_sta;
+
 	char priv[0] __aligned(NETDEV_ALIGN);
 };
 
@@ -3127,8 +3146,8 @@ struct cfg80211_cached_keys;
  * @identifier: (private) Identifier used in nl80211 to identify this
  *	wireless device if it has no netdev
  * @current_bss: (private) Used by the internal configuration code
- * @channel: (private) Used by the internal configuration code to track
- *	the user-set AP, monitor and WDS channel
+ * @chandef: (private) Used by the internal configuration code to track
+ *	the user-set channel definition.
  * @preset_chandef: (private) Used by the internal configuration code to
  *	track the channel to be used for AP later
  * @bssid: (private) Used by the internal configuration code
@@ -3192,9 +3211,7 @@ struct wireless_dev {
 
 	struct cfg80211_internal_bss *current_bss; /* associated / joined */
 	struct cfg80211_chan_def preset_chandef;
-
-	/* for AP and mesh channel tracking */
-	struct ieee80211_channel *channel;
+	struct cfg80211_chan_def chandef;
 
 	bool ibss_fixed;
 	bool ibss_dfs_possible;
@@ -3876,6 +3893,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  *
  * @dev: network device
  * @bssid: the BSSID of the IBSS joined
+ * @channel: the channel of the IBSS joined
  * @gfp: allocation flags
  *
  * This function notifies cfg80211 that the device joined an IBSS or
@@ -3885,7 +3903,8 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  * with the locally generated beacon -- this guarantees that there is
  * always a scan result for this IBSS. cfg80211 will handle the rest.
  */
-void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
+			  struct ieee80211_channel *channel, gfp_t gfp);
 
 /**
  * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index 9cf2d5ef38d9..c15d39456e14 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -34,7 +34,7 @@ static inline u32 task_cls_classid(struct task_struct *p)
 		return 0;
 
 	rcu_read_lock();
-	classid = container_of(task_css(p, net_cls_subsys_id),
+	classid = container_of(task_css(p, net_cls_cgrp_id),
 			       struct cgroup_cls_state, css)->classid;
 	rcu_read_unlock();
 
diff --git a/include/net/flow.h b/include/net/flow.h
index d23e7fa2042e..bee3741e5a6f 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -218,9 +218,10 @@ struct flow_cache_object *flow_cache_lookup(struct net *net,
 					    const struct flowi *key, u16 family,
 					    u8 dir, flow_resolve_t resolver,
 					    void *ctx);
+int flow_cache_init(struct net *net);
 
-void flow_cache_flush(void);
-void flow_cache_flush_deferred(void);
+void flow_cache_flush(struct net *net);
+void flow_cache_flush_deferred(struct net *net);
 extern atomic_t flow_cache_genid;
 
 #endif
diff --git a/include/net/flowcache.h b/include/net/flowcache.h
new file mode 100644
index 000000000000..c8f665ec6e0d
--- /dev/null
+++ b/include/net/flowcache.h
@@ -0,0 +1,25 @@
+#ifndef _NET_FLOWCACHE_H
+#define _NET_FLOWCACHE_H
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/notifier.h>
+
+struct flow_cache_percpu {
+	struct hlist_head		*hash_table;
+	int				hash_count;
+	u32				hash_rnd;
+	int				hash_rnd_recalc;
+	struct tasklet_struct		flush_tasklet;
+};
+
+struct flow_cache {
+	u32				hash_shift;
+	struct flow_cache_percpu __percpu *percpu;
+	struct notifier_block		hotcpu_notifier;
+	int				low_watermark;
+	int				high_watermark;
+	struct timer_list		rnd_timer;
+};
+#endif	/* _NET_FLOWCACHE_H */
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 8b5b71433297..b0fd9476c538 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -316,6 +316,10 @@ enum ieee80211_radiotap_type {
 #define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM		0x10
 #define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED			0x20
 
+#define IEEE80211_RADIOTAP_CODING_LDPC_USER0			0x01
+#define IEEE80211_RADIOTAP_CODING_LDPC_USER1			0x02
+#define IEEE80211_RADIOTAP_CODING_LDPC_USER2			0x04
+#define IEEE80211_RADIOTAP_CODING_LDPC_USER3			0x08
 
 /* helpers */
 static inline int ieee80211_get_radiotap_len(unsigned char *data)
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 8196d5d40359..97b2e34d87f7 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -29,6 +29,12 @@
 
 #include <net/af_ieee802154.h>
 
+struct ieee802154_frag_info {
+	__be16 d_tag;
+	u16 d_size;
+	u8 d_offset;
+};
+
 /*
  * A control block of skb passed between the ARPHRD_IEEE802154 device
  * and other stack parts.
@@ -39,6 +45,7 @@ struct ieee802154_mac_cb {
 	struct ieee802154_addr da;
 	u8 flags;
 	u8 seq;
+	struct ieee802154_frag_info frag_info;
 };
 
 static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
diff --git a/include/net/ip.h b/include/net/ip.h
index 23be0fd37937..b885d75cede4 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -266,7 +266,8 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
 
 static inline bool ip_sk_accept_pmtu(const struct sock *sk)
 {
-	return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE;
+	return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE &&
+	       inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT;
 }
 
 static inline bool ip_sk_use_pmtu(const struct sock *sk)
@@ -274,6 +275,12 @@ static inline bool ip_sk_use_pmtu(const struct sock *sk)
 	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
 }
 
+static inline bool ip_sk_local_df(const struct sock *sk)
+{
+	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO ||
+	       inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT;
+}
+
 static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
 						    bool forwarding)
 {
@@ -489,7 +496,8 @@ int ip_options_rcv_srr(struct sk_buff *skb);
 
 void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
 void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
-int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc);
+int ip_cmsg_send(struct net *net, struct msghdr *msg,
+		 struct ipcm_cookie *ipc, bool allow_ipv6);
 int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
 		  unsigned int optlen);
 int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 017badb1aec7..00e3f12cb2f9 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -171,7 +171,14 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
 
 static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
 {
-	return inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_INTERFACE;
+	return inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_INTERFACE &&
+	       inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_OMIT;
+}
+
+static inline bool ip6_sk_local_df(const struct sock *sk)
+{
+	return inet6_sk(sk)->pmtudisc < IPV6_PMTUDISC_DO ||
+	       inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
 }
 
 static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 48ed75c21260..e77c10405d51 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -129,6 +129,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
 		      struct ip_tunnel_parm *p);
 void ip_tunnel_setup(struct net_device *dev, int net_id);
+void ip_tunnel_dst_reset_all(struct ip_tunnel *t);
 
 /* Extract dsfield from inner protocol */
 static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f4ab2fb4d50c..ea3e33be2516 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -808,9 +808,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
- * @RX_FLAG_80MHZ: 80 MHz was used
- * @RX_FLAG_80P80MHZ: 80+80 MHz was used
- * @RX_FLAG_160MHZ: 160 MHz was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
  * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
  *	Valid only for data frames (mainly A-MPDU)
@@ -830,6 +827,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  *	on this subframe
  * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
  *	is stored in the @ampdu_delimiter_crc field)
+ * @RX_FLAG_LDPC: LDPC was used
  * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
  * @RX_FLAG_10MHZ: 10 MHz (half channel) was used
  * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
@@ -866,9 +864,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_AMPDU_DELIM_CRC_KNOWN	= BIT(20),
 	RX_FLAG_MACTIME_END		= BIT(21),
 	RX_FLAG_VHT			= BIT(22),
-	RX_FLAG_80MHZ			= BIT(23),
-	RX_FLAG_80P80MHZ		= BIT(24),
-	RX_FLAG_160MHZ			= BIT(25),
+	RX_FLAG_LDPC			= BIT(23),
 	RX_FLAG_STBC_MASK		= BIT(26) | BIT(27),
 	RX_FLAG_10MHZ			= BIT(28),
 	RX_FLAG_5MHZ			= BIT(29),
@@ -878,6 +874,21 @@ enum mac80211_rx_flags {
 #define RX_FLAG_STBC_SHIFT		26
 
 /**
+ * enum mac80211_rx_vht_flags - receive VHT flags
+ *
+ * These flags are used with the @vht_flag member of
+ *	&struct ieee80211_rx_status.
+ * @RX_VHT_FLAG_80MHZ: 80 MHz was used
+ * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used
+ * @RX_VHT_FLAG_160MHZ: 160 MHz was used
+ */
+enum mac80211_rx_vht_flags {
+	RX_VHT_FLAG_80MHZ		= BIT(0),
+	RX_VHT_FLAG_80P80MHZ		= BIT(1),
+	RX_VHT_FLAG_160MHZ		= BIT(2),
+};
+
+/**
  * struct ieee80211_rx_status - receive status
  *
  * The low-level driver should provide this information (the subset
@@ -902,26 +913,19 @@ enum mac80211_rx_flags {
  *	HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
  * @vht_nss: number of streams (VHT only)
  * @flag: %RX_FLAG_*
+ * @vht_flag: %RX_VHT_FLAG_*
  * @rx_flags: internal RX flags for mac80211
  * @ampdu_reference: A-MPDU reference number, must be a different value for
  *	each A-MPDU but the same for each subframe within one A-MPDU
  * @ampdu_delimiter_crc: A-MPDU delimiter CRC
- * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
- * @vendor_radiotap_len: radiotap vendor namespace length
- * @vendor_radiotap_align: radiotap vendor namespace alignment. Note
- *	that the actual data must be at the start of the SKB data
- *	already.
- * @vendor_radiotap_oui: radiotap vendor namespace OUI
- * @vendor_radiotap_subns: radiotap vendor sub namespace
  */
 struct ieee80211_rx_status {
 	u64 mactime;
 	u32 device_timestamp;
 	u32 ampdu_reference;
 	u32 flag;
-	u32 vendor_radiotap_bitmap;
-	u16 vendor_radiotap_len;
 	u16 freq;
+	u8 vht_flag;
 	u8 rate_idx;
 	u8 vht_nss;
 	u8 rx_flags;
@@ -931,9 +935,6 @@ struct ieee80211_rx_status {
 	u8 chains;
 	s8 chain_signal[IEEE80211_MAX_CHAINS];
 	u8 ampdu_delimiter_crc;
-	u8 vendor_radiotap_align;
-	u8 vendor_radiotap_oui[3];
-	u8 vendor_radiotap_subns;
 };
 
 /**
@@ -1895,7 +1896,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  *
  * Driver informs U-APSD client support by enabling
  * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
- * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
+ * uapsd parameter in conf_tx() operation. Hardware needs to send the QoS
  * Nullfunc frames and stay awake until the service period has ended. To
  * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
  * from that AC are transmitted with powersave enabled.
@@ -2101,7 +2102,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  * with the number of frames to be released and which TIDs they are
  * to come from. In this case, the driver is responsible for setting
  * the EOSP (for uAPSD) and MORE_DATA bits in the released frames,
- * to help the @more_data paramter is passed to tell the driver if
+ * to help the @more_data parameter is passed to tell the driver if
  * there is more data on other TIDs -- the TIDs to release frames
  * from are ignored since mac80211 doesn't know how many frames the
  * buffers for those TIDs contain.
@@ -2662,7 +2663,7 @@ enum ieee80211_roc_type {
  *	parameters. In the case where the driver buffers some frames for
  *	sleeping stations mac80211 will use this callback to tell the driver
  *	to release some frames, either for PS-poll or uAPSD.
- *	Note that if the @more_data paramter is %false the driver must check
+ *	Note that if the @more_data parameter is %false the driver must check
  *	if there are more frames on the given TIDs, and if there are more than
  *	the frames being released then it must still set the more-data bit in
  *	the frame. If the @more_data parameter is %true, then of course the
@@ -2750,11 +2751,13 @@ enum ieee80211_roc_type {
  * @channel_switch_beacon: Starts a channel switch to a new channel.
  *	Beacons are modified to include CSA or ECSA IEs before calling this
  *	function. The corresponding count fields in these IEs must be
- *	decremented, and when they reach zero the driver must call
+ *	decremented, and when they reach 1 the driver must call
  *	ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
  *	get the csa counter decremented by mac80211, but must check if it is
- *	zero using ieee80211_csa_is_complete() after the beacon has been
+ *	1 using ieee80211_csa_is_complete() after the beacon has been
  *	transmitted and then call ieee80211_csa_finish().
+ *	If the CSA count starts as zero or 1, this function will not be called,
+ *	since there won't be any time to beacon before the switch anyway.
  *
  * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
  *	information in bss_conf is set up and the beacon can be retrieved. A
@@ -3452,13 +3455,13 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
  * After a channel switch announcement was scheduled and the counter in this
- * announcement hit zero, this function must be called by the driver to
+ * announcement hits 1, this function must be called by the driver to
  * notify mac80211 that the channel can be changed.
  */
 void ieee80211_csa_finish(struct ieee80211_vif *vif);
 
 /**
- * ieee80211_csa_is_complete - find out if counters reached zero
+ * ieee80211_csa_is_complete - find out if counters reached 1
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
  * This function returns whether the channel switch counters reached zero.
@@ -4451,7 +4454,6 @@ struct ieee80211_tx_rate_control {
 };
 
 struct rate_control_ops {
-	struct module *module;
 	const char *name;
 	void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
 	void (*free)(void *priv);
@@ -4553,8 +4555,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
 			   struct ieee80211_sta *pubsta,
 			   struct ieee80211_sta_rates *rates);
 
-int ieee80211_rate_control_register(struct rate_control_ops *ops);
-void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+int ieee80211_rate_control_register(const struct rate_control_ops *ops);
+void ieee80211_rate_control_unregister(const struct rate_control_ops *ops);
 
 static inline bool
 conf_is_ht20(struct ieee80211_conf *conf)
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 807d6b7a943f..8ca3d04e7558 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -113,6 +113,32 @@ struct ieee802154_dev {
  *	  Set radio for listening on specific address.
  *	  Set the device for listening on specified address.
  *	  Returns either zero, or negative errno.
+ *
+ * set_txpower:
+ *	  Set radio transmit power in dB. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_lbt
+ *	  Enables or disables listen before talk on the device. Called with
+ *	  pib_lock held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_cca_mode
+ *	  Sets the CCA mode used by the device. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_cca_ed_level
+ *	  Sets the CCA energy detection threshold in dBm. Called with pib_lock
+ *	  held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_csma_params
+ *	  Sets the CSMA parameter set for the PHY. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_frame_retries
+ *	  Sets the retransmission attempt limit. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -129,6 +155,15 @@ struct ieee802154_ops {
 					    unsigned long changed);
 	int		(*ieee_addr)(struct ieee802154_dev *dev,
 				     u8 addr[IEEE802154_ADDR_LEN]);
+	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
+	int		(*set_lbt)(struct ieee802154_dev *dev, bool on);
+	int		(*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
+	int		(*set_cca_ed_level)(struct ieee802154_dev *dev,
+					    s32 level);
+	int		(*set_csma_params)(struct ieee802154_dev *dev,
+					   u8 min_be, u8 max_be, u8 retries);
+	int		(*set_frame_retries)(struct ieee802154_dev *dev,
+					     s8 retries);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 991dcd94cbbf..79387f73f875 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -15,6 +15,7 @@
 #include <net/netns/packet.h>
 #include <net/netns/ipv4.h>
 #include <net/netns/ipv6.h>
+#include <net/netns/ieee802154_6lowpan.h>
 #include <net/netns/sctp.h>
 #include <net/netns/dccp.h>
 #include <net/netns/netfilter.h>
@@ -90,6 +91,9 @@ struct net {
 #if IS_ENABLED(CONFIG_IPV6)
 	struct netns_ipv6	ipv6;
 #endif
+#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
+	struct netns_ieee802154_lowpan	ieee802154_lowpan;
+#endif
 #if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
 	struct netns_sctp	sctp;
 #endif
diff --git a/include/net/netns/ieee802154_6lowpan.h b/include/net/netns/ieee802154_6lowpan.h
new file mode 100644
index 000000000000..079030c853d8
--- /dev/null
+++ b/include/net/netns/ieee802154_6lowpan.h
@@ -0,0 +1,22 @@
+/*
+ * ieee802154 6lowpan in net namespaces
+ */
+
+#include <net/inet_frag.h>
+
+#ifndef __NETNS_IEEE802154_6LOWPAN_H__
+#define __NETNS_IEEE802154_6LOWPAN_H__
+
+struct netns_sysctl_lowpan {
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *frags_hdr;
+#endif
+};
+
+struct netns_ieee802154_lowpan {
+	struct netns_sysctl_lowpan sysctl;
+	struct netns_frags	frags;
+	u16			max_dsize;
+};
+
+#endif
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 1006a265beb3..51f0dce7b643 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -6,6 +6,7 @@
 #include <linux/workqueue.h>
 #include <linux/xfrm.h>
 #include <net/dst_ops.h>
+#include <net/flowcache.h>
 
 struct ctl_table_header;
 
@@ -58,9 +59,18 @@ struct netns_xfrm {
 	struct dst_ops		xfrm6_dst_ops;
 #endif
 	spinlock_t xfrm_state_lock;
-	spinlock_t xfrm_policy_sk_bundle_lock;
 	rwlock_t xfrm_policy_lock;
 	struct mutex xfrm_cfg_mutex;
+
+	/* flow cache part */
+	struct flow_cache	flow_cache_global;
+	struct kmem_cache	*flow_cachep;
+	atomic_t		flow_cache_genid;
+	struct list_head	flow_cache_gc_list;
+	spinlock_t		flow_cache_gc_lock;
+	struct work_struct	flow_cache_gc_work;
+	struct work_struct	flow_cache_flush_work;
+	struct mutex		flow_flush_sem;
 };
 
 #endif
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
index dafc09f0fdbc..f2a9597ff53c 100644
--- a/include/net/netprio_cgroup.h
+++ b/include/net/netprio_cgroup.h
@@ -27,32 +27,17 @@ struct netprio_map {
 
 void sock_update_netprioidx(struct sock *sk);
 
-#if IS_BUILTIN(CONFIG_CGROUP_NET_PRIO)
 static inline u32 task_netprioidx(struct task_struct *p)
 {
 	struct cgroup_subsys_state *css;
 	u32 idx;
 
 	rcu_read_lock();
-	css = task_css(p, net_prio_subsys_id);
+	css = task_css(p, net_prio_cgrp_id);
 	idx = css->cgroup->id;
 	rcu_read_unlock();
 	return idx;
 }
-#elif IS_MODULE(CONFIG_CGROUP_NET_PRIO)
-static inline u32 task_netprioidx(struct task_struct *p)
-{
-	struct cgroup_subsys_state *css;
-	u32 idx = 0;
-
-	rcu_read_lock();
-	css = task_css(p, net_prio_subsys_id);
-	if (css)
-		idx = css->cgroup->id;
-	rcu_read_unlock();
-	return idx;
-}
-#endif
 #else /* !CONFIG_CGROUP_NET_PRIO */
 static inline u32 task_netprioidx(struct task_struct *p)
 {
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 661e45d38051..72240e5ac2c4 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -140,7 +140,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
 				    struct nlattr *tb[]);
 int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
 
-extern const struct nla_policy ifla_policy[IFLA_MAX+1];
+int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len);
 
 #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
 
diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
index 9e8710be7a04..fa8f5fac65e9 100644
--- a/include/net/tc_act/tc_csum.h
+++ b/include/net/tc_act/tc_csum.h
@@ -9,7 +9,7 @@ struct tcf_csum {
 
 	u32 update_flags;
 };
-#define to_tcf_csum(pc) \
-	container_of(pc,struct tcf_csum,common)
+#define to_tcf_csum(a) \
+	container_of(a->priv,struct tcf_csum,common)
 
 #endif /* __NET_TC_CSUM_H */
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
index 65f024b80958..9763dcbb9bc3 100644
--- a/include/net/tc_act/tc_defact.h
+++ b/include/net/tc_act/tc_defact.h
@@ -8,7 +8,7 @@ struct tcf_defact {
 	u32     		tcfd_datalen;
 	void    		*tcfd_defdata;
 };
-#define to_defact(pc) \
-	container_of(pc, struct tcf_defact, common)
+#define to_defact(a) \
+	container_of(a->priv, struct tcf_defact, common)
 
 #endif /* __NET_TC_DEF_H */
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
index 9e3f6767b80e..9fc9b578908a 100644
--- a/include/net/tc_act/tc_gact.h
+++ b/include/net/tc_act/tc_gact.h
@@ -11,7 +11,7 @@ struct tcf_gact {
         int			tcfg_paction;
 #endif
 };
-#define to_gact(pc) \
-	container_of(pc, struct tcf_gact, common)
+#define to_gact(a) \
+	container_of(a->priv, struct tcf_gact, common)
 
 #endif /* __NET_TC_GACT_H */
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
index f7d25dfcc4b7..c0f4193f432c 100644
--- a/include/net/tc_act/tc_ipt.h
+++ b/include/net/tc_act/tc_ipt.h
@@ -11,7 +11,7 @@ struct tcf_ipt {
 	char			*tcfi_tname;
 	struct xt_entry_target	*tcfi_t;
 };
-#define to_ipt(pc) \
-	container_of(pc, struct tcf_ipt, common)
+#define to_ipt(a) \
+	container_of(a->priv, struct tcf_ipt, common)
 
 #endif /* __NET_TC_IPT_H */
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
index cfe2943690ff..4dd77a1c106b 100644
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -11,7 +11,7 @@ struct tcf_mirred {
 	struct net_device	*tcfm_dev;
 	struct list_head	tcfm_list;
 };
-#define to_mirred(pc) \
-	container_of(pc, struct tcf_mirred, common)
+#define to_mirred(a) \
+	container_of(a->priv, struct tcf_mirred, common)
 
 #endif /* __NET_TC_MIR_H */
diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h
index 4a691f34d703..63d8e9ca9d99 100644
--- a/include/net/tc_act/tc_nat.h
+++ b/include/net/tc_act/tc_nat.h
@@ -13,9 +13,9 @@ struct tcf_nat {
 	u32 flags;
 };
 
-static inline struct tcf_nat *to_tcf_nat(struct tcf_common *pc)
+static inline struct tcf_nat *to_tcf_nat(struct tc_action *a)
 {
-	return container_of(pc, struct tcf_nat, common);
+	return container_of(a->priv, struct tcf_nat, common);
 }
 
 #endif /* __NET_TC_NAT_H */
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
index e6f6e15956f5..5b80998879c7 100644
--- a/include/net/tc_act/tc_pedit.h
+++ b/include/net/tc_act/tc_pedit.h
@@ -9,7 +9,7 @@ struct tcf_pedit {
 	unsigned char		tcfp_flags;
 	struct tc_pedit_key	*tcfp_keys;
 };
-#define to_pedit(pc) \
-	container_of(pc, struct tcf_pedit, common)
+#define to_pedit(a) \
+	container_of(a->priv, struct tcf_pedit, common)
 
 #endif /* __NET_TC_PED_H */
diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
index dd5d86fab030..0df9a0db4a8e 100644
--- a/include/net/tc_act/tc_skbedit.h
+++ b/include/net/tc_act/tc_skbedit.h
@@ -29,7 +29,7 @@ struct tcf_skbedit {
 	u16			queue_mapping;
 	/* XXX: 16-bit pad here? */
 };
-#define to_skbedit(pc) \
-	container_of(pc, struct tcf_skbedit, common)
+#define to_skbedit(a) \
+	container_of(a->priv, struct tcf_skbedit, common)
 
 #endif /* __NET_TC_SKBEDIT_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 56fc366da6d5..bb253b9b2f06 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -31,6 +31,7 @@
 #include <linux/crypto.h>
 #include <linux/cryptohash.h>
 #include <linux/kref.h>
+#include <linux/ktime.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -478,7 +479,6 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 			     struct ip_options *opt);
 #ifdef CONFIG_SYN_COOKIES
-#include <linux/ktime.h>
 
 /* Syncookies use a monotonic timer which increments every 64 seconds.
  * This counter is used both as a hash input and partially encoded into
@@ -619,7 +619,7 @@ static inline void tcp_bound_rto(const struct sock *sk)
 
 static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
 {
-	return (tp->srtt >> 3) + tp->rttvar;
+	return usecs_to_jiffies((tp->srtt_us >> 3) + tp->rttvar_us);
 }
 
 static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
@@ -656,6 +656,11 @@ static inline u32 tcp_rto_min(struct sock *sk)
 	return rto_min;
 }
 
+static inline u32 tcp_rto_min_us(struct sock *sk)
+{
+	return jiffies_to_usecs(tcp_rto_min(sk));
+}
+
 /* Compute the actual receive window we are currently advertising.
  * Rcv_nxt can be after the window if our peer push more data
  * than the offered window.
@@ -778,7 +783,6 @@ enum tcp_ca_event {
 #define TCP_CA_BUF_MAX	(TCP_CA_NAME_MAX*TCP_CA_MAX)
 
 #define TCP_CONG_NON_RESTRICTED 0x1
-#define TCP_CONG_RTT_STAMP	0x2
 
 struct tcp_congestion_ops {
 	struct list_head	list;
@@ -791,8 +795,6 @@ struct tcp_congestion_ops {
 
 	/* return slow start threshold (required) */
 	u32 (*ssthresh)(struct sock *sk);
-	/* lower bound for congestion window (optional) */
-	u32 (*min_cwnd)(const struct sock *sk);
 	/* do new cwnd calculation (required) */
 	void (*cong_avoid)(struct sock *sk, u32 ack, u32 acked, u32 in_flight);
 	/* call before changing ca_state (optional) */
@@ -827,7 +829,6 @@ void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w);
 extern struct tcp_congestion_ops tcp_init_congestion_ops;
 u32 tcp_reno_ssthresh(struct sock *sk);
 void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked, u32 in_flight);
-u32 tcp_reno_min_cwnd(const struct sock *sk);
 extern struct tcp_congestion_ops tcp_reno;
 
 static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
@@ -1303,7 +1304,8 @@ struct tcp_fastopen_request {
 	/* Fast Open cookie. Size 0 means a cookie request */
 	struct tcp_fastopen_cookie	cookie;
 	struct msghdr			*data;  /* data in MSG_FASTOPEN */
-	u16				copied;	/* queued in tcp_connect() */
+	size_t				size;
+	int				copied;	/* queued in tcp_connect() */
 };
 void tcp_free_fastopen_req(struct tcp_sock *tp);
 
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index b52bda8d13b1..10ab0fc6d4f7 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -37,15 +37,22 @@ struct wpan_phy {
 	struct mutex pib_lock;
 
 	/*
-	 * This is a PIB according to 802.15.4-2006.
+	 * This is a PIB according to 802.15.4-2011.
 	 * We do not provide timing-related variables, as they
 	 * aren't used outside of driver
 	 */
 	u8 current_channel;
 	u8 current_page;
 	u32 channels_supported[32];
-	u8 transmit_power;
+	s8 transmit_power;
 	u8 cca_mode;
+	u8 min_be;
+	u8 max_be;
+	u8 csma_retries;
+	s8 frame_retries;
+
+	bool lbt;
+	s32 cca_ed_level;
 
 	struct device dev;
 	int idx;
@@ -54,6 +61,14 @@ struct wpan_phy {
 					const char *name, int type);
 	void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
 
+	int (*set_txpower)(struct wpan_phy *phy, int db);
+	int (*set_lbt)(struct wpan_phy *phy, bool on);
+	int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
+	int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
+	int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
+			       u8 retries);
+	int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);
+
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index afa5730fb3bd..23bfd4591e8b 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -118,11 +118,10 @@
 struct xfrm_state_walk {
 	struct list_head	all;
 	u8			state;
-	union {
-		u8		dying;
-		u8		proto;
-	};
+	u8			dying;
+	u8			proto;
 	u32			seq;
+	struct xfrm_filter	*filter;
 };
 
 /* Full description of state of transformer. */
@@ -594,21 +593,33 @@ struct xfrm_mgr {
 					   const struct xfrm_migrate *m,
 					   int num_bundles,
 					   const struct xfrm_kmaddress *k);
+	bool			(*is_alive)(const struct km_event *c);
 };
 
 int xfrm_register_km(struct xfrm_mgr *km);
 int xfrm_unregister_km(struct xfrm_mgr *km);
 
+struct xfrm_tunnel_skb_cb {
+	union {
+		struct inet_skb_parm h4;
+		struct inet6_skb_parm h6;
+	} header;
+
+	union {
+		struct ip_tunnel *ip4;
+		struct ip6_tnl *ip6;
+	} tunnel;
+};
+
+#define XFRM_TUNNEL_SKB_CB(__skb) ((struct xfrm_tunnel_skb_cb *)&((__skb)->cb[0]))
+
 /*
  * This structure is used for the duration where packets are being
  * transformed by IPsec.  As soon as the packet leaves IPsec the
  * area beyond the generic IP part may be overwritten.
  */
 struct xfrm_skb_cb {
-	union {
-		struct inet_skb_parm h4;
-		struct inet6_skb_parm h6;
-        } header;
+	struct xfrm_tunnel_skb_cb header;
 
         /* Sequence number for replay protection. */
 	union {
@@ -630,10 +641,7 @@ struct xfrm_skb_cb {
  * to transmit header information to the mode input/output functions.
  */
 struct xfrm_mode_skb_cb {
-	union {
-		struct inet_skb_parm h4;
-		struct inet6_skb_parm h6;
-	} header;
+	struct xfrm_tunnel_skb_cb header;
 
 	/* Copied from header for IPv4, always set to zero and DF for IPv6. */
 	__be16 id;
@@ -665,10 +673,7 @@ struct xfrm_mode_skb_cb {
  * related information.
  */
 struct xfrm_spi_skb_cb {
-	union {
-		struct inet_skb_parm h4;
-		struct inet6_skb_parm h6;
-	} header;
+	struct xfrm_tunnel_skb_cb header;
 
 	unsigned int daddroff;
 	unsigned int family;
@@ -1347,6 +1352,18 @@ struct xfrm_algo_desc {
 	struct sadb_alg desc;
 };
 
+/* XFRM protocol handlers.  */
+struct xfrm4_protocol {
+	int (*handler)(struct sk_buff *skb);
+	int (*input_handler)(struct sk_buff *skb, int nexthdr, __be32 spi,
+			     int encap_type);
+	int (*cb_handler)(struct sk_buff *skb, int err);
+	int (*err_handler)(struct sk_buff *skb, u32 info);
+
+	struct xfrm4_protocol __rcu *next;
+	int priority;
+};
+
 /* XFRM tunnel handlers.  */
 struct xfrm_tunnel {
 	int (*handler)(struct sk_buff *skb);
@@ -1405,7 +1422,8 @@ static inline void xfrm_sysctl_fini(struct net *net)
 }
 #endif
 
-void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
+			  struct xfrm_filter *filter);
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
 		    int (*func)(struct xfrm_state *, int, void*), void *);
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
@@ -1497,18 +1515,22 @@ int xfrm4_rcv(struct sk_buff *skb);
 
 static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 {
-	return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
+	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
+	XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+	return xfrm_input(skb, nexthdr, spi, 0);
 }
 
 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_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);
+int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char protocol);
 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
-int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
-int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
 int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
 int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
 int xfrm6_extract_header(struct sk_buff *skb);
@@ -1646,8 +1668,27 @@ static inline int xfrm_aevent_is_on(struct net *net)
 	rcu_read_unlock();
 	return ret;
 }
+
+static inline int xfrm_acquire_is_on(struct net *net)
+{
+	struct sock *nlsk;
+	int ret = 0;
+
+	rcu_read_lock();
+	nlsk = rcu_dereference(net->xfrm.nlsk);
+	if (nlsk)
+		ret = netlink_has_listeners(nlsk, XFRMNLGRP_ACQUIRE);
+	rcu_read_unlock();
+
+	return ret;
+}
 #endif
 
+static inline int aead_len(struct xfrm_algo_aead *alg)
+{
+	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
 static inline int xfrm_alg_len(const struct xfrm_algo *alg)
 {
 	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -1686,6 +1727,12 @@ static inline int xfrm_replay_clone(struct xfrm_state *x,
 	return 0;
 }
 
+static inline struct xfrm_algo_aead *xfrm_algo_aead_clone(struct xfrm_algo_aead *orig)
+{
+	return kmemdup(orig, aead_len(orig), GFP_KERNEL);
+}
+
+
 static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
 {
 	return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
@@ -1737,4 +1784,36 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
 	return ret;
 }
 
+static inline int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family,
+			      u8 protocol, int err)
+{
+	switch(family) {
+#ifdef CONFIG_INET
+	case AF_INET:
+		return xfrm4_rcv_cb(skb, protocol, err);
+#endif
+	}
+	return 0;
+}
+
+static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
+				    unsigned int family)
+{
+	bool tunnel = false;
+
+	switch(family) {
+	case AF_INET:
+		if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4)
+			tunnel = true;
+		break;
+	case AF_INET6:
+		if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6)
+			tunnel = true;
+		break;
+	}
+	if (tunnel && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL))
+		return -EINVAL;
+
+	return 0;
+}
 #endif	/* _NET_XFRM_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 2a14f1f02d4f..d3f5f818e0b9 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/device.h>
 #include <linux/sched.h>		/* wake_up() */
 #include <linux/mutex.h>		/* struct mutex */
 #include <linux/rwsem.h>		/* struct rw_semaphore */
@@ -41,39 +42,33 @@
 /* forward declarations */
 struct pci_dev;
 struct module;
-struct device;
-struct device_attribute;
+struct completion;
 
 /* device allocation stuff */
 
-#define SNDRV_DEV_TYPE_RANGE_SIZE		0x1000
-
-typedef int __bitwise snd_device_type_t;
-#define	SNDRV_DEV_TOPLEVEL	((__force snd_device_type_t) 0)
-#define	SNDRV_DEV_CONTROL	((__force snd_device_type_t) 1)
-#define	SNDRV_DEV_LOWLEVEL_PRE	((__force snd_device_type_t) 2)
-#define	SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)
-#define	SNDRV_DEV_PCM		((__force snd_device_type_t) 0x1001)
-#define	SNDRV_DEV_RAWMIDI	((__force snd_device_type_t) 0x1002)
-#define	SNDRV_DEV_TIMER		((__force snd_device_type_t) 0x1003)
-#define	SNDRV_DEV_SEQUENCER	((__force snd_device_type_t) 0x1004)
-#define	SNDRV_DEV_HWDEP		((__force snd_device_type_t) 0x1005)
-#define	SNDRV_DEV_INFO		((__force snd_device_type_t) 0x1006)
-#define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
-#define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
-#define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
-#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
-#define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
-
-typedef int __bitwise snd_device_state_t;
-#define	SNDRV_DEV_BUILD		((__force snd_device_state_t) 0)
-#define	SNDRV_DEV_REGISTERED	((__force snd_device_state_t) 1)
-#define	SNDRV_DEV_DISCONNECTED	((__force snd_device_state_t) 2)
-
-typedef int __bitwise snd_device_cmd_t;
-#define	SNDRV_DEV_CMD_PRE	((__force snd_device_cmd_t) 0)
-#define	SNDRV_DEV_CMD_NORMAL	((__force snd_device_cmd_t) 1)	
-#define	SNDRV_DEV_CMD_POST	((__force snd_device_cmd_t) 2)
+/* type of the object used in snd_device_*()
+ * this also defines the calling order
+ */
+enum snd_device_type {
+	SNDRV_DEV_LOWLEVEL,
+	SNDRV_DEV_CONTROL,
+	SNDRV_DEV_INFO,
+	SNDRV_DEV_BUS,
+	SNDRV_DEV_CODEC,
+	SNDRV_DEV_PCM,
+	SNDRV_DEV_COMPRESS,
+	SNDRV_DEV_RAWMIDI,
+	SNDRV_DEV_TIMER,
+	SNDRV_DEV_SEQUENCER,
+	SNDRV_DEV_HWDEP,
+	SNDRV_DEV_JACK,
+};
+
+enum snd_device_state {
+	SNDRV_DEV_BUILD,
+	SNDRV_DEV_REGISTERED,
+	SNDRV_DEV_DISCONNECTED,
+};
 
 struct snd_device;
 
@@ -86,8 +81,8 @@ struct snd_device_ops {
 struct snd_device {
 	struct list_head list;		/* list of registered devices */
 	struct snd_card *card;		/* card which holds this device */
-	snd_device_state_t state;	/* state of the device */
-	snd_device_type_t type;		/* device type */
+	enum snd_device_state state;	/* state of the device */
+	enum snd_device_type type;	/* device type */
 	void *device_data;		/* device structure */
 	struct snd_device_ops *ops;	/* operations */
 };
@@ -131,11 +126,10 @@ struct snd_card {
 								state */
 	spinlock_t files_lock;		/* lock the files for this card */
 	int shutdown;			/* this card is going down */
-	int free_on_last_close;		/* free in context of file_release */
-	wait_queue_head_t shutdown_sleep;
-	atomic_t refcount;		/* refcount for disconnection */
+	struct completion *release_completion;
 	struct device *dev;		/* device assigned to this card */
-	struct device *card_dev;	/* cardX object for sysfs */
+	struct device card_dev;		/* cardX object for sysfs */
+	bool registered;		/* card_dev is registered? */
 
 #ifdef CONFIG_PM
 	unsigned int power_state;	/* power state */
@@ -149,6 +143,8 @@ struct snd_card {
 #endif
 };
 
+#define dev_to_snd_card(p)	container_of(p, struct snd_card, card_dev)
+
 #ifdef CONFIG_PM
 static inline void snd_power_lock(struct snd_card *card)
 {
@@ -197,7 +193,7 @@ struct snd_minor {
 /* return a device pointer linked to each sound device as a parent */
 static inline struct device *snd_card_get_device_link(struct snd_card *card)
 {
-	return card ? card->card_dev : NULL;
+	return card ? &card->card_dev : NULL;
 }
 
 /* sound.c */
@@ -244,13 +240,11 @@ static inline int snd_register_device(int type, struct snd_card *card, int dev,
 
 int snd_unregister_device(int type, struct snd_card *card, int dev);
 void *snd_lookup_minor_data(unsigned int minor, int type);
-int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
-			      struct device_attribute *attr);
+struct device *snd_get_device(int type, struct snd_card *card, int dev);
 
 #ifdef CONFIG_SND_OSSEMUL
 int snd_register_oss_device(int type, struct snd_card *card, int dev,
-			    const struct file_operations *f_ops, void *private_data,
-			    const char *name);
+			    const struct file_operations *f_ops, void *private_data);
 int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
 void *snd_lookup_oss_minor_data(unsigned int minor, int type);
 #endif
@@ -284,9 +278,16 @@ int snd_card_locked(int card);
 extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 #endif
 
-int snd_card_create(int idx, const char *id,
-		    struct module *module, int extra_size,
-		    struct snd_card **card_ret);
+int snd_card_new(struct device *parent, int idx, const char *xid,
+		 struct module *module, int extra_size,
+		 struct snd_card **card_ret);
+
+static inline int __deprecated
+snd_card_create(int idx, const char *id, struct module *module, int extra_size,
+		struct snd_card **ret)
+{
+	return snd_card_new(NULL, idx, id, module, extra_size, ret);
+}
 
 int snd_card_disconnect(struct snd_card *card);
 int snd_card_free(struct snd_card *card);
@@ -298,20 +299,19 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
-void snd_card_unref(struct snd_card *card);
+#define snd_card_unref(card)	put_device(&(card)->card_dev)
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
 /* device.c */
 
-int snd_device_new(struct snd_card *card, snd_device_type_t type,
+int snd_device_new(struct snd_card *card, enum snd_device_type type,
 		   void *device_data, struct snd_device_ops *ops);
 int snd_device_register(struct snd_card *card, void *device_data);
 int snd_device_register_all(struct snd_card *card);
-int snd_device_disconnect(struct snd_card *card, void *device_data);
 int snd_device_disconnect_all(struct snd_card *card);
-int snd_device_free(struct snd_card *card, void *device_data);
-int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd);
+void snd_device_free(struct snd_card *card, void *device_data);
+void snd_device_free_all(struct snd_card *card);
 
 /* isadma.c */
 
@@ -433,7 +433,6 @@ static inline void snd_printdd(const char *format, ...) {}
 #define gameport_get_port_data(gp) (gp)->port_data
 #endif
 
-#ifdef CONFIG_PCI
 /* PCI quirk list helper */
 struct snd_pci_quirk {
 	unsigned short subvendor;	/* PCI subvendor ID */
@@ -469,12 +468,26 @@ struct snd_pci_quirk {
 #define snd_pci_quirk_name(q)	""
 #endif
 
+#ifdef CONFIG_PCI
 const struct snd_pci_quirk *
 snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
 
 const struct snd_pci_quirk *
 snd_pci_quirk_lookup_id(u16 vendor, u16 device,
 			const struct snd_pci_quirk *list);
+#else
+static inline const struct snd_pci_quirk *
+snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
+{
+	return NULL;
+}
+
+static inline const struct snd_pci_quirk *
+snd_pci_quirk_lookup_id(u16 vendor, u16 device,
+			const struct snd_pci_quirk *list)
+{
+	return NULL;
+}
 #endif
 
 #endif /* __SOUND_CORE_H */
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index 8c05e47a4090..ae04a3ec9c77 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -60,7 +60,6 @@ struct snd_hwdep {
 	int iface;
 
 #ifdef CONFIG_SND_OSSEMUL
-	char oss_dev[32];
 	int oss_type;
 	int ossreg;
 #endif
@@ -69,6 +68,8 @@ struct snd_hwdep {
 	wait_queue_head_t open_wait;
 	void *private_data;
 	void (*private_free) (struct snd_hwdep *hwdep);
+	struct device *dev;
+	const struct attribute_group **groups;
 
 	struct mutex open_mutex;
 	int used;			/* reference counter */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 4883499ab38b..b4d6697085fe 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1141,4 +1141,12 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
 	return 1ULL << (__force int) pcm_format;
 }
 
+/* printk helpers */
+#define pcm_err(pcm, fmt, args...) \
+	dev_err((pcm)->card->dev, fmt, ##args)
+#define pcm_warn(pcm, fmt, args...) \
+	dev_warn((pcm)->card->dev, fmt, ##args)
+#define pcm_dbg(pcm, fmt, args...) \
+	dev_dbg((pcm)->card->dev, fmt, ##args)
+
 #endif /* __SOUND_PCM_H */
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index adf0885153f3..311dafe6cc4b 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -157,10 +157,8 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
 
 /* callbacks */
 
-void snd_rawmidi_receive_reset(struct snd_rawmidi_substream *substream);
 int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
 			const unsigned char *buffer, int count);
-void snd_rawmidi_transmit_reset(struct snd_rawmidi_substream *substream);
 int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream);
 int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 			      unsigned char *buffer, int count);
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index 6add6ccc811e..e3d585c67685 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -34,8 +34,6 @@
  * B : SSI direction
  */
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
-#define RSND_SSI_SYNC			(1 << 29) /* SSI34_sync etc */
-
 #define RSND_SSI_PLAY			(1 << 24)
 
 #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags)	\
@@ -55,9 +53,15 @@ struct rsnd_ssi_platform_info {
  */
 #define RSND_SCU_USE_HPBIF		(1 << 31) /* it needs RSND_SSI_DEPENDENT */
 
+#define RSND_SCU_SET(rate, _dma_id)		\
+	{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
+#define RSND_SCU_UNUSED				\
+	{ .flags = 0, .convert_rate = 0, .dma_id = 0, }
+
 struct rsnd_scu_platform_info {
 	u32 flags;
 	u32 convert_rate; /* sampling rate convert */
+	int dma_id; /* for Gen2 SCU */
 };
 
 /*
diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h
index 6c74527d4926..9b0ac77177b6 100644
--- a/include/sound/simple_card.h
+++ b/include/sound/simple_card.h
@@ -18,6 +18,8 @@ struct asoc_simple_dai {
 	const char *name;
 	unsigned int fmt;
 	unsigned int sysclk;
+	int slots;
+	int slot_width;
 };
 
 struct asoc_simple_card_info {
@@ -29,10 +31,6 @@ struct asoc_simple_card_info {
 	unsigned int daifmt;
 	struct asoc_simple_dai cpu_dai;
 	struct asoc_simple_dai codec_dai;
-
-	/* used in simple-card.c */
-	struct snd_soc_dai_link snd_link;
-	struct snd_soc_card snd_card;
 };
 
 #endif /* __SIMPLE_CARD_H */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 71f27c403194..d86e0fc41e80 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -142,6 +142,8 @@ struct snd_soc_dai_ops {
 	 * Called by soc_card drivers, normally in their hw_params.
 	 */
 	int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
+	int (*of_xlate_tdm_slot_mask)(unsigned int slots,
+		unsigned int *tx_mask, unsigned int *rx_mask);
 	int (*set_tdm_slot)(struct snd_soc_dai *dai,
 		unsigned int tx_mask, unsigned int rx_mask,
 		int slots, int slot_width);
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 6e89ef6c11c1..04d32d89bc7d 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -108,13 +108,9 @@ struct device;
 	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) \
-{	.id = snd_soc_dapm_virt_mux, .name = wname, \
-	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
-	.kcontrol_news = wcontrols, .num_kcontrols = 1}
+	SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
 #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{	.id = snd_soc_dapm_value_mux, .name = wname, \
-	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
-	.kcontrol_news = wcontrols, .num_kcontrols = 1}
+	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,\
@@ -172,10 +168,8 @@ struct device;
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_virt_mux, .name = wname, \
-	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
-	.kcontrol_news = wcontrols, .num_kcontrols = 1, \
-	.event = wevent, .event_flags = 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, \
@@ -311,12 +305,8 @@ 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)		    \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-	.info = snd_soc_info_enum_double, \
-	.get = snd_soc_dapm_get_enum_virt, \
-	.put = snd_soc_dapm_put_enum_virt, \
-	.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, \
@@ -324,11 +314,7 @@ struct device;
 	.put = xput, \
 	.private_value = (unsigned long)&xenum }
 #define SOC_DAPM_VALUE_ENUM(xname, xenum) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-	.info = snd_soc_info_enum_double, \
-	.get = snd_soc_dapm_get_value_enum_double, \
-	.put = snd_soc_dapm_put_value_enum_double, \
-	.private_value = (unsigned long)&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, \
@@ -392,14 +378,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
@@ -461,6 +439,7 @@ int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
 				const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
+int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 				  const char *pin);
 int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
@@ -484,8 +463,6 @@ enum snd_soc_dapm_type {
 	snd_soc_dapm_input = 0,		/* input pin */
 	snd_soc_dapm_output,		/* output pin */
 	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
-	snd_soc_dapm_virt_mux,			/* virtual version of snd_soc_dapm_mux */
-	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_mixer,			/* mixes several analog signals together */
 	snd_soc_dapm_mixer_named_ctl,		/* mixer with named controls */
 	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 9a001472b96a..56c4c712822f 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -45,6 +45,11 @@
 	((unsigned long)&(struct soc_mixer_control) \
 	{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
 	.max = xmax, .platform_max = xmax, .invert = xinvert})
+#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \
+	((unsigned long)&(struct soc_mixer_control) \
+	{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
+	.max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \
+	.invert = xinvert})
 #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
 	((unsigned long)&(struct soc_mixer_control) \
 	{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
@@ -152,6 +157,15 @@
 		{.reg = xreg, .rreg = xrreg, \
 		.shift = xshift, .rshift = xshift, \
 		.max = xmax, .min = xmin} }
+#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+	.tlv.p = (tlv_array), \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
+	.private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \
+					    xmin, xmax, xsign_bit, xinvert) }
 #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
 {	.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -162,30 +176,28 @@
 	.private_value = (unsigned long)&(struct soc_mixer_control) \
 		{.reg = xreg, .min = xmin, .max = xmax, \
 		 .platform_max = xmax} }
-#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
+#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \
 {	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
-	.max = xmax, .texts = xtexts, \
-	.mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0}
-#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \
-	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
-#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
-{	.max = xmax, .texts = xtexts }
-#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
+	.items = xitems, .texts = xtexts, \
+	.mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0}
+#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \
+	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts)
+#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \
+{	.items = xitems, .texts = xtexts }
+#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \
 {	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
-	.mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues}
-#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
-	SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues)
+	.mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues}
+#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \
+	SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues)
+#define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts)
 #define SOC_ENUM(xname, xenum) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
 	.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) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
-	.info = snd_soc_info_enum_double, \
-	.get = snd_soc_get_value_enum_double, \
-	.put = snd_soc_put_value_enum_double, \
-	.private_value = (unsigned long)&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, \
@@ -272,17 +284,19 @@
  * ARRAY_SIZE internally
  */
 #define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \
-	struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
+	const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
 						ARRAY_SIZE(xtexts), xtexts)
 #define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \
 	SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts)
 #define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \
-	struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts)
+	const struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts)
 #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \
-	struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \
+	const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \
 							ARRAY_SIZE(xtexts), xtexts, xvalues)
 #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \
 	SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)
+#define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \
+	const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts)
 
 /*
  * Component probe and remove ordering levels for components with runtime
@@ -341,8 +355,6 @@ typedef int (*hw_write_t)(void *,const char* ,int);
 extern struct snd_ac97_bus_ops *soc_ac97_ops;
 
 enum snd_soc_control_type {
-	SND_SOC_I2C = 1,
-	SND_SOC_SPI,
 	SND_SOC_REGMAP,
 };
 
@@ -496,10 +508,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 #define snd_soc_info_bool_ext		snd_ctl_boolean_mono_info
@@ -600,7 +608,8 @@ struct snd_soc_jack_gpio {
 	struct snd_soc_jack *jack;
 	struct delayed_work work;
 
-	int (*jack_status_check)(void);
+	void *data;
+	int (*jack_status_check)(void *data);
 };
 
 struct snd_soc_jack {
@@ -1067,6 +1076,7 @@ struct soc_mixer_control {
 	int min, max, platform_max;
 	int reg, rreg;
 	unsigned int shift, rshift;
+	unsigned int sign_bit;
 	unsigned int invert:1;
 	unsigned int autodisable:1;
 };
@@ -1085,11 +1095,10 @@ struct soc_mreg_control {
 
 /* enumerated kcontrol */
 struct soc_enum {
-	unsigned short reg;
-	unsigned short reg2;
+	int reg;
 	unsigned char shift_l;
 	unsigned char shift_r;
-	unsigned int max;
+	unsigned int items;
 	unsigned int mask;
 	const char * const *texts;
 	const unsigned int *values;
@@ -1168,11 +1177,40 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
 	return 1;
 }
 
+static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e,
+	unsigned int val)
+{
+	unsigned int i;
+
+	if (!e->values)
+		return val;
+
+	for (i = 0; i < e->items; i++)
+		if (val == e->values[i])
+			return i;
+
+	return 0;
+}
+
+static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
+	unsigned int item)
+{
+	if (!e->values)
+		return item;
+
+	return e->values[item];
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
 int snd_soc_of_parse_card_name(struct snd_soc_card *card,
 			       const char *propname);
+int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
+					  const char *propname);
+int snd_soc_of_parse_tdm_slot(struct device_node *np,
+			      unsigned int *slots,
+			      unsigned int *slot_width);
 int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
 				   const char *propname);
 unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
@@ -1188,4 +1226,15 @@ extern struct dentry *snd_soc_debugfs_root;
 
 extern const struct dev_pm_ops snd_soc_pm_ops;
 
+/* Helper functions */
+static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm)
+{
+	mutex_lock(&dapm->card->dapm_mutex);
+}
+
+static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
+{
+	mutex_unlock(&dapm->card->dapm_mutex);
+}
+
 #endif
diff --git a/include/trace/events/hswadsp.h b/include/trace/events/hswadsp.h
new file mode 100644
index 000000000000..0f78bbb02002
--- /dev/null
+++ b/include/trace/events/hswadsp.h
@@ -0,0 +1,384 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hswadsp
+
+#if !defined(_TRACE_HSWADSP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HSWADSP_H
+
+#include <linux/types.h>
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+struct sst_hsw;
+struct sst_hsw_stream;
+struct sst_hsw_ipc_stream_free_req;
+struct sst_hsw_ipc_volume_req;
+struct sst_hsw_ipc_stream_alloc_req;
+struct sst_hsw_audio_data_format_ipc;
+struct sst_hsw_ipc_stream_info_reply;
+struct sst_hsw_ipc_device_config_req;
+
+DECLARE_EVENT_CLASS(sst_irq,
+
+	TP_PROTO(uint32_t status, uint32_t mask),
+
+	TP_ARGS(status, mask),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	status		)
+		__field(	unsigned int,	mask		)
+	),
+
+	TP_fast_assign(
+		__entry->status = status;
+		__entry->mask = mask;
+	),
+
+	TP_printk("status 0x%8.8x mask 0x%8.8x",
+		(unsigned int)__entry->status, (unsigned int)__entry->mask)
+);
+
+DEFINE_EVENT(sst_irq, sst_irq_busy,
+
+	TP_PROTO(unsigned int status, unsigned int mask),
+
+	TP_ARGS(status, mask)
+
+);
+
+DEFINE_EVENT(sst_irq, sst_irq_done,
+
+	TP_PROTO(unsigned int status, unsigned int mask),
+
+	TP_ARGS(status, mask)
+
+);
+
+DECLARE_EVENT_CLASS(ipc,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val),
+
+	TP_STRUCT__entry(
+		__string(	name,	name		)
+		__field(	unsigned int,	val	)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, name);
+		__entry->val = val;
+	),
+
+	TP_printk("%s 0x%8.8x", __get_str(name), (unsigned int)__entry->val)
+
+);
+
+DEFINE_EVENT(ipc, ipc_request,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val)
+
+);
+
+DEFINE_EVENT(ipc, ipc_reply,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val)
+
+);
+
+DEFINE_EVENT(ipc, ipc_pending_reply,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val)
+
+);
+
+DEFINE_EVENT(ipc, ipc_notification,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val)
+
+);
+
+DEFINE_EVENT(ipc, ipc_error,
+
+	TP_PROTO(const char *name, int val),
+
+	TP_ARGS(name, val)
+
+);
+
+DECLARE_EVENT_CLASS(stream_position,
+
+	TP_PROTO(unsigned int id, unsigned int pos),
+
+	TP_ARGS(id, pos),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	id		)
+		__field(	unsigned int,	pos		)
+	),
+
+	TP_fast_assign(
+		__entry->id = id;
+		__entry->pos = pos;
+	),
+
+	TP_printk("id %d position 0x%x",
+		(unsigned int)__entry->id, (unsigned int)__entry->pos)
+);
+
+DEFINE_EVENT(stream_position, stream_read_position,
+
+	TP_PROTO(unsigned int id, unsigned int pos),
+
+	TP_ARGS(id, pos)
+
+);
+
+DEFINE_EVENT(stream_position, stream_write_position,
+
+	TP_PROTO(unsigned int id, unsigned int pos),
+
+	TP_ARGS(id, pos)
+
+);
+
+TRACE_EVENT(hsw_stream_buffer,
+
+	TP_PROTO(struct sst_hsw_stream *stream),
+
+	TP_ARGS(stream),
+
+	TP_STRUCT__entry(
+		__field(	int,	id	)
+		__field(	int,	pt_addr	)
+		__field(	int,	num_pages	)
+		__field(	int,	ring_size	)
+		__field(	int,	ring_offset	)
+		__field(	int,	first_pfn	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->pt_addr = stream->request.ringinfo.ring_pt_address;
+		__entry->num_pages = stream->request.ringinfo.num_pages;
+		__entry->ring_size = stream->request.ringinfo.ring_size;
+		__entry->ring_offset = stream->request.ringinfo.ring_offset;
+		__entry->first_pfn = stream->request.ringinfo.ring_first_pfn;
+	),
+
+	TP_printk("stream %d ring addr 0x%x pages %d size 0x%x offset 0x%x PFN 0x%x",
+		(int) __entry->id,  (int)__entry->pt_addr,
+		(int)__entry->num_pages, (int)__entry->ring_size,
+		(int)__entry->ring_offset, (int)__entry->first_pfn)
+);
+
+TRACE_EVENT(hsw_stream_alloc_reply,
+
+	TP_PROTO(struct sst_hsw_stream *stream),
+
+	TP_ARGS(stream),
+
+	TP_STRUCT__entry(
+		__field(	int,	id	)
+		__field(	int,	stream_id	)
+		__field(	int,	mixer_id	)
+		__field(	int,	peak0	)
+		__field(	int,	peak1	)
+		__field(	int,	vol0	)
+		__field(	int,	vol1	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->stream_id = stream->reply.stream_hw_id;
+		__entry->mixer_id = stream->reply.mixer_hw_id;
+		__entry->peak0 = stream->reply.peak_meter_register_address[0];
+		__entry->peak1 = stream->reply.peak_meter_register_address[1];
+		__entry->vol0 = stream->reply.volume_register_address[0];
+		__entry->vol1 = stream->reply.volume_register_address[1];
+	),
+
+	TP_printk("stream %d hw id %d mixer %d peak 0x%x:0x%x vol 0x%x,0x%x",
+		(int) __entry->id, (int) __entry->stream_id, (int)__entry->mixer_id,
+		(int)__entry->peak0, (int)__entry->peak1,
+		(int)__entry->vol0, (int)__entry->vol1)
+);
+
+TRACE_EVENT(hsw_mixer_info_reply,
+
+	TP_PROTO(struct sst_hsw_ipc_stream_info_reply *reply),
+
+	TP_ARGS(reply),
+
+	TP_STRUCT__entry(
+		__field(	int,	mixer_id	)
+		__field(	int,	peak0	)
+		__field(	int,	peak1	)
+		__field(	int,	vol0	)
+		__field(	int,	vol1	)
+	),
+
+	TP_fast_assign(
+		__entry->mixer_id = reply->mixer_hw_id;
+		__entry->peak0 = reply->peak_meter_register_address[0];
+		__entry->peak1 = reply->peak_meter_register_address[1];
+		__entry->vol0 = reply->volume_register_address[0];
+		__entry->vol1 = reply->volume_register_address[1];
+	),
+
+	TP_printk("mixer id %d peak 0x%x:0x%x vol 0x%x,0x%x",
+		(int)__entry->mixer_id,
+		(int)__entry->peak0, (int)__entry->peak1,
+		(int)__entry->vol0, (int)__entry->vol1)
+);
+
+TRACE_EVENT(hsw_stream_data_format,
+
+	TP_PROTO(struct sst_hsw_stream *stream,
+		struct sst_hsw_audio_data_format_ipc *req),
+
+	TP_ARGS(stream, req),
+
+	TP_STRUCT__entry(
+		__field(	uint32_t,	id	)
+		__field(	uint32_t,	frequency	)
+		__field(	uint32_t,	bitdepth	)
+		__field(	uint32_t,	map	)
+		__field(	uint32_t,	config	)
+		__field(	uint32_t,	style	)
+		__field(	uint8_t,	ch_num	)
+		__field(	uint8_t,	valid_bit	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->frequency = req->frequency;
+		__entry->bitdepth = req->bitdepth;
+		__entry->map = req->map;
+		__entry->config = req->config;
+		__entry->style = req->style;
+		__entry->ch_num = req->ch_num;
+		__entry->valid_bit = req->valid_bit;
+	),
+
+	TP_printk("stream %d freq %d depth %d map 0x%x config 0x%x style 0x%x ch %d bits %d",
+		(int) __entry->id, (uint32_t)__entry->frequency,
+		(uint32_t)__entry->bitdepth, (uint32_t)__entry->map,
+		(uint32_t)__entry->config, (uint32_t)__entry->style,
+		(uint8_t)__entry->ch_num, (uint8_t)__entry->valid_bit)
+);
+
+TRACE_EVENT(hsw_stream_alloc_request,
+
+	TP_PROTO(struct sst_hsw_stream *stream,
+		struct sst_hsw_ipc_stream_alloc_req *req),
+
+	TP_ARGS(stream, req),
+
+	TP_STRUCT__entry(
+		__field(	uint32_t,	id	)
+		__field(	uint8_t,	path_id	)
+		__field(	uint8_t,	stream_type	)
+		__field(	uint8_t,	format_id	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->path_id = req->path_id;
+		__entry->stream_type = req->stream_type;
+		__entry->format_id = req->format_id;
+	),
+
+	TP_printk("stream %d path %d type %d format %d",
+		(int) __entry->id, (uint8_t)__entry->path_id,
+		(uint8_t)__entry->stream_type, (uint8_t)__entry->format_id)
+);
+
+TRACE_EVENT(hsw_stream_free_req,
+
+	TP_PROTO(struct sst_hsw_stream *stream,
+		struct sst_hsw_ipc_stream_free_req *req),
+
+	TP_ARGS(stream, req),
+
+	TP_STRUCT__entry(
+		__field(	int,	id	)
+		__field(	int,	stream_id	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->stream_id = req->stream_id;
+	),
+
+	TP_printk("stream %d hw id %d",
+		(int) __entry->id, (int) __entry->stream_id)
+);
+
+TRACE_EVENT(hsw_volume_req,
+
+	TP_PROTO(struct sst_hsw_stream *stream,
+		struct sst_hsw_ipc_volume_req *req),
+
+	TP_ARGS(stream, req),
+
+	TP_STRUCT__entry(
+		__field(	int,	id	)
+		__field(	uint32_t,	channel	)
+		__field(	uint32_t,	target_volume	)
+		__field(	uint64_t,	curve_duration	)
+		__field(	uint32_t,	curve_type	)
+	),
+
+	TP_fast_assign(
+		__entry->id = stream->host_id;
+		__entry->channel = req->channel;
+		__entry->target_volume = req->target_volume;
+		__entry->curve_duration = req->curve_duration;
+		__entry->curve_type = req->curve_type;
+	),
+
+	TP_printk("stream %d chan 0x%x vol %d duration %llu type %d",
+		(int) __entry->id, (uint32_t) __entry->channel,
+		(uint32_t)__entry->target_volume,
+		(uint64_t)__entry->curve_duration,
+		(uint32_t)__entry->curve_type)
+);
+
+TRACE_EVENT(hsw_device_config_req,
+
+	TP_PROTO(struct sst_hsw_ipc_device_config_req *req),
+
+	TP_ARGS(req),
+
+	TP_STRUCT__entry(
+		__field(	uint32_t,	ssp	)
+		__field(	uint32_t,	clock_freq	)
+		__field(	uint32_t,	mode	)
+		__field(	uint16_t,	clock_divider	)
+	),
+
+	TP_fast_assign(
+		__entry->ssp = req->ssp_interface;
+		__entry->clock_freq = req->clock_frequency;
+		__entry->mode = req->mode;
+		__entry->clock_divider = req->clock_divider;
+	),
+
+	TP_printk("SSP %d Freq %d mode %d div %d",
+		(uint32_t)__entry->ssp,
+		(uint32_t)__entry->clock_freq, (uint32_t)__entry->mode,
+		(uint32_t)__entry->clock_divider)
+);
+
+#endif /* _TRACE_HSWADSP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/intel-sst.h b/include/trace/events/intel-sst.h
new file mode 100644
index 000000000000..76c72d3f1902
--- /dev/null
+++ b/include/trace/events/intel-sst.h
@@ -0,0 +1,148 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel-sst
+
+#if !defined(_TRACE_INTEL_SST_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_INTEL_SST_H
+
+#include <linux/types.h>
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(sst_ipc_msg,
+
+	TP_PROTO(unsigned int val),
+
+	TP_ARGS(val),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	val		)
+	),
+
+	TP_fast_assign(
+		__entry->val = val;
+	),
+
+	TP_printk("0x%8.8x", (unsigned int)__entry->val)
+);
+
+DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_tx,
+
+	TP_PROTO(unsigned int val),
+
+	TP_ARGS(val)
+
+);
+
+DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_rx,
+
+	TP_PROTO(unsigned int val),
+
+	TP_ARGS(val)
+
+);
+
+DECLARE_EVENT_CLASS(sst_ipc_mailbox,
+
+	TP_PROTO(unsigned int offset, unsigned int val),
+
+	TP_ARGS(offset, val),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	offset		)
+		__field(	unsigned int,	val		)
+	),
+
+	TP_fast_assign(
+		__entry->offset = offset;
+		__entry->val = val;
+	),
+
+	TP_printk(" 0x%4.4x = 0x%8.8x",
+		(unsigned int)__entry->offset, (unsigned int)__entry->val)
+);
+
+DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_rdata,
+
+	TP_PROTO(unsigned int offset, unsigned int val),
+
+	TP_ARGS(offset, val)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_wdata,
+
+	TP_PROTO(unsigned int offset, unsigned int val),
+
+	TP_ARGS(offset, val)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_rdata,
+
+	TP_PROTO(unsigned int offset, unsigned int val),
+
+	TP_ARGS(offset, val)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_wdata,
+
+	TP_PROTO(unsigned int offset, unsigned int val),
+
+	TP_ARGS(offset, val)
+
+);
+
+DECLARE_EVENT_CLASS(sst_ipc_mailbox_info,
+
+	TP_PROTO(unsigned int size),
+
+	TP_ARGS(size),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	size		)
+	),
+
+	TP_fast_assign(
+		__entry->size = size;
+	),
+
+	TP_printk("Mailbox bytes 0x%8.8x", (unsigned int)__entry->size)
+);
+
+DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_read,
+
+	TP_PROTO(unsigned int size),
+
+	TP_ARGS(size)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_write,
+
+	TP_PROTO(unsigned int size),
+
+	TP_ARGS(size)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_read,
+
+	TP_PROTO(unsigned int size),
+
+	TP_ARGS(size)
+
+);
+
+DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_write,
+
+	TP_PROTO(unsigned int size),
+
+	TP_ARGS(size)
+
+);
+
+#endif /* _TRACE_SST_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index e5bf9a76f169..9a7e08d61258 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -407,8 +407,8 @@ DECLARE_EVENT_CLASS(dev_pm_qos_request,
 	TP_printk("device=%s type=%s new_value=%d",
 		  __get_str(name),
 		  __print_symbolic(__entry->type,
-			{ DEV_PM_QOS_LATENCY,	"DEV_PM_QOS_LATENCY" },
-			{ DEV_PM_QOS_FLAGS,	"DEV_PM_QOS_FLAGS" }),
+			{ DEV_PM_QOS_RESUME_LATENCY, "DEV_PM_QOS_RESUME_LATENCY" },
+			{ DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" }),
 		  __entry->new_value)
 );
 
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 464ea82e10db..cee02d65ab3f 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -4,6 +4,7 @@
 #if !defined(_TRACE_WRITEBACK_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_WRITEBACK_H
 
+#include <linux/tracepoint.h>
 #include <linux/backing-dev.h>
 #include <linux/writeback.h>
 
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 95e46c8e05f9..a9b13f8b3595 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -132,6 +132,22 @@
 #define F_GETOWNER_UIDS	17
 #endif
 
+/*
+ * fd "private" POSIX locks.
+ *
+ * Usually POSIX locks held by a process are released on *any* close and are
+ * not inherited across a fork().
+ *
+ * These cmd values will set locks that conflict with normal POSIX locks, but
+ * are "owned" by the opened file, not the process. This means that they are
+ * inherited across fork() like BSD (flock) locks, and they are only released
+ * automatically when the last reference to the the open file against which
+ * they were acquired is put.
+ */
+#define F_GETLKP	36
+#define F_SETLKP	37
+#define F_SETLKPW	38
+
 #define F_OWNER_TID	0
 #define F_OWNER_PID	1
 #define F_OWNER_PGRP	2
@@ -186,8 +202,6 @@ struct flock {
 };
 #endif
 
-#ifndef CONFIG_64BIT
-
 #ifndef HAVE_ARCH_STRUCT_FLOCK64
 #ifndef __ARCH_FLOCK64_PAD
 #define __ARCH_FLOCK64_PAD
@@ -202,6 +216,5 @@ struct flock64 {
 	__ARCH_FLOCK64_PAD
 };
 #endif
-#endif /* !CONFIG_64BIT */
 
 #endif /* _ASM_GENERIC_FCNTL_H */
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
index d9ea3a73afe2..1cf18b4a39ec 100644
--- a/include/uapi/drm/radeon_drm.h
+++ b/include/uapi/drm/radeon_drm.h
@@ -919,6 +919,7 @@ struct drm_radeon_gem_va {
 #define RADEON_CS_RING_COMPUTE      1
 #define RADEON_CS_RING_DMA          2
 #define RADEON_CS_RING_UVD          3
+#define RADEON_CS_RING_VCE          4
 /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */
 /* 0 = normal, + = higher priority, - = lower priority */
 
@@ -987,6 +988,10 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_BACKEND_ENABLED_MASK	0x19
 /* max engine clock - needed for OpenCL */
 #define RADEON_INFO_MAX_SCLK		0x1a
+/* version of VCE firmware */
+#define RADEON_INFO_VCE_FW_VERSION	0x1b
+/* version of VCE feedback */
+#define RADEON_INFO_VCE_FB_VERSION	0x1c
 
 
 struct drm_radeon_info {
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 3ce25b5d75a9..6929571b79b0 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -139,6 +139,7 @@ header-y += hid.h
 header-y += hiddev.h
 header-y += hidraw.h
 header-y += hpet.h
+header-y += hyperv.h
 header-y += hysdn_if.h
 header-y += i2c-dev.h
 header-y += i2c.h
diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
index e52958d7c2d1..5d9d1d140718 100644
--- a/include/uapi/linux/can.h
+++ b/include/uapi/linux/can.h
@@ -8,6 +8,38 @@
  * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
  * All rights reserved.
  *
+ * 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. Neither the name of Volkswagen nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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 CAN_H
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 38dbafaa5341..fd161e91b6d7 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -16,37 +16,97 @@
 #include <linux/types.h>
 #include <linux/if_ether.h>
 
-/* This should work for both 32 and 64 bit userland. */
+/* All structures exposed to userland should be defined such that they
+ * have the same layout for 32-bit and 64-bit userland.
+ */
+
+/**
+ * struct ethtool_cmd - link control and status
+ * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET
+ * @supported: Bitmask of %SUPPORTED_* flags for the link modes,
+ *	physical connectors and other link features for which the
+ *	interface supports autonegotiation or auto-detection.
+ *	Read-only.
+ * @advertising: Bitmask of %ADVERTISED_* flags for the link modes,
+ *	physical connectors and other link features that are
+ *	advertised through autonegotiation or enabled for
+ *	auto-detection.
+ * @speed: Low bits of the speed
+ * @duplex: Duplex mode; one of %DUPLEX_*
+ * @port: Physical connector type; one of %PORT_*
+ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not
+ *	applicable.  For clause 45 PHYs this is the PRTAD.
+ * @transceiver: Historically used to distinguish different possible
+ *	PHY types, but not in a consistent way.  Deprecated.
+ * @autoneg: Enable/disable autonegotiation and auto-detection;
+ *	either %AUTONEG_DISABLE or %AUTONEG_ENABLE
+ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO
+ *	protocols supported by the interface; 0 if unknown.
+ *	Read-only.
+ * @maxtxpkt: Historically used to report TX IRQ coalescing; now
+ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
+ * @maxrxpkt: Historically used to report RX IRQ coalescing; now
+ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
+ * @speed_hi: High bits of the speed
+ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of
+ *	%ETH_TP_MDI_*.  If the status is unknown or not applicable, the
+ *	value will be %ETH_TP_MDI_INVALID.  Read-only.
+ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of
+ *	%ETH_TP_MDI_*.  If MDI(-X) control is not implemented, reads
+ *	yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected.
+ *	When written successfully, the link should be renegotiated if
+ *	necessary.
+ * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes
+ *	and other link features that the link partner advertised
+ *	through autonegotiation; 0 if unknown or not applicable.
+ *	Read-only.
+ *
+ * The link speed in Mbps is split between @speed and @speed_hi.  Use
+ * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to
+ * access it.
+ *
+ * If autonegotiation is disabled, the speed and @duplex represent the
+ * fixed link mode and are writable if the driver supports multiple
+ * link modes.  If it is enabled then they are read-only; if the link
+ * is up they represent the negotiated link mode; if the link is down,
+ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and
+ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
+ *
+ * Some hardware interfaces may have multiple PHYs and/or physical
+ * connectors fitted or do not allow the driver to detect which are
+ * fitted.  For these interfaces @port and/or @phy_address may be
+ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE.
+ * Otherwise, attempts to write different values may be ignored or
+ * rejected.
+ *
+ * Users should assume that all fields not marked read-only are
+ * writable and subject to validation by the driver.  They should use
+ * %ETHTOOL_GSET to get the current values before making specific
+ * changes and then applying them with %ETHTOOL_SSET.
+ *
+ * Drivers that implement set_settings() should validate all fields
+ * other than @cmd that are not described as read-only or deprecated,
+ * and must ignore all fields described as read-only.
+ *
+ * Deprecated fields should be ignored by both users and drivers.
+ */
 struct ethtool_cmd {
 	__u32	cmd;
-	__u32	supported;	/* Features this interface supports */
-	__u32	advertising;	/* Features this interface advertises */
-	__u16	speed;	        /* The forced speed (lower bits) in
-				 * Mbps. Please use
-				 * ethtool_cmd_speed()/_set() to
-				 * access it */
-	__u8	duplex;		/* Duplex, half or full */
-	__u8	port;		/* Which connector port */
-	__u8	phy_address;	/* MDIO PHY address (PRTAD for clause 45).
-				 * May be read-only or read-write
-				 * depending on the driver.
-				 */
-	__u8	transceiver;	/* Which transceiver to use */
-	__u8	autoneg;	/* Enable or disable autonegotiation */
-	__u8	mdio_support;	/* MDIO protocols supported.  Read-only.
-				 * Not set by all drivers.
-				 */
-	__u32	maxtxpkt;	/* Tx pkts before generating tx int */
-	__u32	maxrxpkt;	/* Rx pkts before generating rx int */
-	__u16	speed_hi;       /* The forced speed (upper
-				 * bits) in Mbps. Please use
-				 * ethtool_cmd_speed()/_set() to
-				 * access it */
-	__u8	eth_tp_mdix;	/* twisted pair MDI-X status */
-	__u8    eth_tp_mdix_ctrl; /* twisted pair MDI-X control, when set,
-				   * link should be renegotiated if necessary
-				   */
-	__u32	lp_advertising;	/* Features the link partner advertises */
+	__u32	supported;
+	__u32	advertising;
+	__u16	speed;
+	__u8	duplex;
+	__u8	port;
+	__u8	phy_address;
+	__u8	transceiver;
+	__u8	autoneg;
+	__u8	mdio_support;
+	__u32	maxtxpkt;
+	__u32	maxrxpkt;
+	__u16	speed_hi;
+	__u8	eth_tp_mdix;
+	__u8	eth_tp_mdix_ctrl;
+	__u32	lp_advertising;
 	__u32	reserved[2];
 };
 
@@ -79,37 +139,68 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
 
 #define ETHTOOL_FWVERS_LEN	32
 #define ETHTOOL_BUSINFO_LEN	32
-/* these strings are set to whatever the driver author decides... */
+
+/**
+ * struct ethtool_drvinfo - general driver and device information
+ * @cmd: Command number = %ETHTOOL_GDRVINFO
+ * @driver: Driver short name.  This should normally match the name
+ *	in its bus driver structure (e.g. pci_driver::name).  Must
+ *	not be an empty string.
+ * @version: Driver version string; may be an empty string
+ * @fw_version: Firmware version string; may be an empty string
+ * @bus_info: Device bus address.  This should match the dev_name()
+ *	string for the underlying bus device, if there is one.  May be
+ *	an empty string.
+ * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and
+ *	%ETHTOOL_SPFLAGS commands; also the number of strings in the
+ *	%ETH_SS_PRIV_FLAGS set
+ * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS
+ *	command; also the number of strings in the %ETH_SS_STATS set
+ * @testinfo_len: Number of results returned by the %ETHTOOL_TEST
+ *	command; also the number of strings in the %ETH_SS_TEST set
+ * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM
+ *	and %ETHTOOL_SEEPROM commands, in bytes
+ * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS
+ *	command, in bytes
+ *
+ * Users can use the %ETHTOOL_GSSET_INFO command to get the number of
+ * strings in any string set (from Linux 2.6.34).
+ *
+ * Drivers should set at most @driver, @version, @fw_version and
+ * @bus_info in their get_drvinfo() implementation.  The ethtool
+ * core fills in the other fields using other driver operations.
+ */
 struct ethtool_drvinfo {
 	__u32	cmd;
-	char	driver[32];	/* driver short name, "tulip", "eepro100" */
-	char	version[32];	/* driver version string */
-	char	fw_version[ETHTOOL_FWVERS_LEN];	/* firmware version string */
-	char	bus_info[ETHTOOL_BUSINFO_LEN];	/* Bus info for this IF. */
-				/* For PCI devices, use pci_name(pci_dev). */
+	char	driver[32];
+	char	version[32];
+	char	fw_version[ETHTOOL_FWVERS_LEN];
+	char	bus_info[ETHTOOL_BUSINFO_LEN];
 	char	reserved1[32];
 	char	reserved2[12];
-				/*
-				 * Some struct members below are filled in
-				 * using ops->get_sset_count().  Obtaining
-				 * this info from ethtool_drvinfo is now
-				 * deprecated; Use ETHTOOL_GSSET_INFO
-				 * instead.
-				 */
-	__u32	n_priv_flags;	/* number of flags valid in ETHTOOL_GPFLAGS */
-	__u32	n_stats;	/* number of u64's from ETHTOOL_GSTATS */
+	__u32	n_priv_flags;
+	__u32	n_stats;
 	__u32	testinfo_len;
-	__u32	eedump_len;	/* Size of data from ETHTOOL_GEEPROM (bytes) */
-	__u32	regdump_len;	/* Size of data from ETHTOOL_GREGS (bytes) */
+	__u32	eedump_len;
+	__u32	regdump_len;
 };
 
 #define SOPASS_MAX	6
-/* wake-on-lan settings */
+
+/**
+ * struct ethtool_wolinfo - Wake-On-Lan configuration
+ * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL
+ * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes.
+ *	Read-only.
+ * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes.
+ * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE
+ *	is set in @wolopts.
+ */
 struct ethtool_wolinfo {
 	__u32	cmd;
 	__u32	supported;
 	__u32	wolopts;
-	__u8	sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+	__u8	sopass[SOPASS_MAX];
 };
 
 /* for passing single values */
@@ -118,20 +209,51 @@ struct ethtool_value {
 	__u32	data;
 };
 
-/* for passing big chunks of data */
+/**
+ * struct ethtool_regs - hardware register dump
+ * @cmd: Command number = %ETHTOOL_GREGS
+ * @version: Dump format version.  This is driver-specific and may
+ *	distinguish different chips/revisions.  Drivers must use new
+ *	version numbers whenever the dump format changes in an
+ *	incompatible way.
+ * @len: On entry, the real length of @data.  On return, the number of
+ *	bytes used.
+ * @data: Buffer for the register dump
+ *
+ * Users should use %ETHTOOL_GDRVINFO to find the maximum length of
+ * a register dump for the interface.  They must allocate the buffer
+ * immediately following this structure.
+ */
 struct ethtool_regs {
 	__u32	cmd;
-	__u32	version; /* driver-specific, indicates different chips/revs */
-	__u32	len; /* bytes */
+	__u32	version;
+	__u32	len;
 	__u8	data[0];
 };
 
-/* for passing EEPROM chunks */
+/**
+ * struct ethtool_eeprom - EEPROM dump
+ * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or
+ *	%ETHTOOL_SEEPROM
+ * @magic: A 'magic cookie' value to guard against accidental changes.
+ *	The value passed in to %ETHTOOL_SEEPROM must match the value
+ *	returned by %ETHTOOL_GEEPROM for the same device.  This is
+ *	unused when @cmd is %ETHTOOL_GMODULEEEPROM.
+ * @offset: Offset within the EEPROM to begin reading/writing, in bytes
+ * @len: On entry, number of bytes to read/write.  On successful
+ *	return, number of bytes actually read/written.  In case of
+ *	error, this may indicate at what point the error occurred.
+ * @data: Buffer to read/write from
+ *
+ * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find
+ * the length of an on-board or module EEPROM, respectively.  They
+ * must allocate the buffer immediately following this structure.
+ */
 struct ethtool_eeprom {
 	__u32	cmd;
 	__u32	magic;
-	__u32	offset; /* in bytes */
-	__u32	len; /* in bytes */
+	__u32	offset;
+	__u32	len;
 	__u8	data[0];
 };
 
@@ -229,17 +351,18 @@ struct ethtool_modinfo {
  * @rate_sample_interval: How often to do adaptive coalescing packet rate
  *	sampling, measured in seconds.  Must not be zero.
  *
- * Each pair of (usecs, max_frames) fields specifies this exit
- * condition for interrupt coalescing:
+ * Each pair of (usecs, max_frames) fields specifies that interrupts
+ * should be coalesced until
  *	(usecs > 0 && time_since_first_completion >= usecs) ||
  *	(max_frames > 0 && completed_frames >= max_frames)
+ *
  * It is illegal to set both usecs and max_frames to zero as this
  * would cause interrupts to never be generated.  To disable
  * coalescing, set usecs = 0 and max_frames = 1.
  *
  * Some implementations ignore the value of max_frames and use the
- * condition:
- *	time_since_first_completion >= usecs
+ * condition time_since_first_completion >= usecs
+ *
  * This is deprecated.  Drivers for hardware that does not support
  * counting completions should validate that max_frames == !rx_usecs.
  *
@@ -279,22 +402,37 @@ struct ethtool_coalesce {
 	__u32	rate_sample_interval;
 };
 
-/* for configuring RX/TX ring parameters */
+/**
+ * struct ethtool_ringparam - RX/TX ring parameters
+ * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM
+ * @rx_max_pending: Maximum supported number of pending entries per
+ *	RX ring.  Read-only.
+ * @rx_mini_max_pending: Maximum supported number of pending entries
+ *	per RX mini ring.  Read-only.
+ * @rx_jumbo_max_pending: Maximum supported number of pending entries
+ *	per RX jumbo ring.  Read-only.
+ * @tx_max_pending: Maximum supported number of pending entries per
+ *	TX ring.  Read-only.
+ * @rx_pending: Current maximum number of pending entries per RX ring
+ * @rx_mini_pending: Current maximum number of pending entries per RX
+ *	mini ring
+ * @rx_jumbo_pending: Current maximum number of pending entries per RX
+ *	jumbo ring
+ * @tx_pending: Current maximum supported number of pending entries
+ *	per TX ring
+ *
+ * If the interface does not have separate RX mini and/or jumbo rings,
+ * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0.
+ *
+ * There may also be driver-dependent minimum values for the number
+ * of entries per ring.
+ */
 struct ethtool_ringparam {
-	__u32	cmd;	/* ETHTOOL_{G,S}RINGPARAM */
-
-	/* Read only attributes.  These indicate the maximum number
-	 * of pending RX/TX ring entries the driver will allow the
-	 * user to set.
-	 */
+	__u32	cmd;
 	__u32	rx_max_pending;
 	__u32	rx_mini_max_pending;
 	__u32	rx_jumbo_max_pending;
 	__u32	tx_max_pending;
-
-	/* Values changeable by the user.  The valid values are
-	 * in the range 1 to the "*_max_pending" counterpart above.
-	 */
 	__u32	rx_pending;
 	__u32	rx_mini_pending;
 	__u32	rx_jumbo_pending;
@@ -329,51 +467,96 @@ struct ethtool_channels {
 	__u32	combined_count;
 };
 
-/* for configuring link flow control parameters */
+/**
+ * struct ethtool_pauseparam - Ethernet pause (flow control) parameters
+ * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM
+ * @autoneg: Flag to enable autonegotiation of pause frame use
+ * @rx_pause: Flag to enable reception of pause frames
+ * @tx_pause: Flag to enable transmission of pause frames
+ *
+ * Drivers should reject a non-zero setting of @autoneg when
+ * autoneogotiation is disabled (or not supported) for the link.
+ *
+ * If the link is autonegotiated, drivers should use
+ * mii_advertise_flowctrl() or similar code to set the advertised
+ * pause frame capabilities based on the @rx_pause and @tx_pause flags,
+ * even if @autoneg is zero.  They should also allow the advertised
+ * pause frame capabilities to be controlled directly through the
+ * advertising field of &struct ethtool_cmd.
+ *
+ * If @autoneg is non-zero, the MAC is configured to send and/or
+ * receive pause frames according to the result of autonegotiation.
+ * Otherwise, it is configured directly based on the @rx_pause and
+ * @tx_pause flags.
+ */
 struct ethtool_pauseparam {
-	__u32	cmd;	/* ETHTOOL_{G,S}PAUSEPARAM */
-
-	/* If the link is being auto-negotiated (via ethtool_cmd.autoneg
-	 * being true) the user may set 'autoneg' here non-zero to have the
-	 * pause parameters be auto-negotiated too.  In such a case, the
-	 * {rx,tx}_pause values below determine what capabilities are
-	 * advertised.
-	 *
-	 * If 'autoneg' is zero or the link is not being auto-negotiated,
-	 * then {rx,tx}_pause force the driver to use/not-use pause
-	 * flow control.
-	 */
+	__u32	cmd;
 	__u32	autoneg;
 	__u32	rx_pause;
 	__u32	tx_pause;
 };
 
 #define ETH_GSTRING_LEN		32
+
+/**
+ * enum ethtool_stringset - string set ID
+ * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST
+ * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS
+ * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with
+ *	%ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS
+ * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
+ *	now deprecated
+ * @ETH_SS_FEATURES: Device feature names
+ */
 enum ethtool_stringset {
 	ETH_SS_TEST		= 0,
 	ETH_SS_STATS,
 	ETH_SS_PRIV_FLAGS,
-	ETH_SS_NTUPLE_FILTERS,	/* Do not use, GRXNTUPLE is now deprecated */
+	ETH_SS_NTUPLE_FILTERS,
 	ETH_SS_FEATURES,
 };
 
-/* for passing string sets for data tagging */
+/**
+ * struct ethtool_gstrings - string set for data tagging
+ * @cmd: Command number = %ETHTOOL_GSTRINGS
+ * @string_set: String set ID; one of &enum ethtool_stringset
+ * @len: On return, the number of strings in the string set
+ * @data: Buffer for strings.  Each string is null-padded to a size of
+ *	%ETH_GSTRING_LEN.
+ *
+ * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in
+ * the string set.  They must allocate a buffer of the appropriate
+ * size immediately following this structure.
+ */
 struct ethtool_gstrings {
-	__u32	cmd;		/* ETHTOOL_GSTRINGS */
-	__u32	string_set;	/* string set id e.c. ETH_SS_TEST, etc*/
-	__u32	len;		/* number of strings in the string set */
+	__u32	cmd;
+	__u32	string_set;
+	__u32	len;
 	__u8	data[0];
 };
 
+/**
+ * struct ethtool_sset_info - string set information
+ * @cmd: Command number = %ETHTOOL_GSSET_INFO
+ * @sset_mask: On entry, a bitmask of string sets to query, with bits
+ *	numbered according to &enum ethtool_stringset.  On return, a
+ *	bitmask of those string sets queried that are supported.
+ * @data: Buffer for string set sizes.  On return, this contains the
+ *	size of each string set that was queried and supported, in
+ *	order of ID.
+ *
+ * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on
+ * return @sset_mask == 0x6 (sets 1, 2).  Then @data[0] contains the
+ * size of set 1 and @data[1] contains the size of set 2.
+ *
+ * Users must allocate a buffer of the appropriate size (4 * number of
+ * sets queried) immediately following this structure.
+ */
 struct ethtool_sset_info {
-	__u32	cmd;		/* ETHTOOL_GSSET_INFO */
+	__u32	cmd;
 	__u32	reserved;
-	__u64	sset_mask;	/* input: each bit selects an sset to query */
-				/* output: each bit a returned sset */
-	__u32	data[0];	/* ETH_SS_xxx count, in order, based on bits
-				   in sset_mask.  One bit implies one
-				   __u32, two bits implies two
-				   __u32's, etc. */
+	__u64	sset_mask;
+	__u32	data[0];
 };
 
 /**
@@ -393,24 +576,58 @@ enum ethtool_test_flags {
 	ETH_TEST_FL_EXTERNAL_LB_DONE	= (1 << 3),
 };
 
-/* for requesting NIC test and getting results*/
+/**
+ * struct ethtool_test - device self-test invocation
+ * @cmd: Command number = %ETHTOOL_TEST
+ * @flags: A bitmask of flags from &enum ethtool_test_flags.  Some
+ *	flags may be set by the user on entry; others may be set by
+ *	the driver on return.
+ * @len: On return, the number of test results
+ * @data: Array of test results
+ *
+ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
+ * number of test results that will be returned.  They must allocate a
+ * buffer of the appropriate size (8 * number of results) immediately
+ * following this structure.
+ */
 struct ethtool_test {
-	__u32	cmd;		/* ETHTOOL_TEST */
-	__u32	flags;		/* ETH_TEST_FL_xxx */
+	__u32	cmd;
+	__u32	flags;
 	__u32	reserved;
-	__u32	len;		/* result length, in number of u64 elements */
+	__u32	len;
 	__u64	data[0];
 };
 
-/* for dumping NIC-specific statistics */
+/**
+ * struct ethtool_stats - device-specific statistics
+ * @cmd: Command number = %ETHTOOL_GSTATS
+ * @n_stats: On return, the number of statistics
+ * @data: Array of statistics
+ *
+ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
+ * number of statistics that will be returned.  They must allocate a
+ * buffer of the appropriate size (8 * number of statistics)
+ * immediately following this structure.
+ */
 struct ethtool_stats {
-	__u32	cmd;		/* ETHTOOL_GSTATS */
-	__u32	n_stats;	/* number of u64's being returned */
+	__u32	cmd;
+	__u32	n_stats;
 	__u64	data[0];
 };
 
+/**
+ * struct ethtool_perm_addr - permanent hardware address
+ * @cmd: Command number = %ETHTOOL_GPERMADDR
+ * @size: On entry, the size of the buffer.  On return, the size of the
+ *	address.  The command fails if the buffer is too small.
+ * @data: Buffer for the address
+ *
+ * Users must allocate the buffer immediately following this structure.
+ * A buffer size of %MAX_ADDR_LEN should be sufficient for any address
+ * type.
+ */
 struct ethtool_perm_addr {
-	__u32	cmd;		/* ETHTOOL_GPERMADDR */
+	__u32	cmd;
 	__u32	size;
 	__u8	data[0];
 };
@@ -593,7 +810,7 @@ struct ethtool_rx_flow_spec {
  * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused
  * location, and may remove a rule at a later location (lower
  * priority) that matches exactly the same set of flows.  The special
- * values are: %RX_CLS_LOC_ANY, selecting any location;
+ * values are %RX_CLS_LOC_ANY, selecting any location;
  * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum
  * priority); and %RX_CLS_LOC_LAST, selecting the last suitable
  * location (minimum priority).  Additional special values may be
@@ -704,9 +921,6 @@ struct ethtool_flash {
  * 	 for %ETHTOOL_GET_DUMP_FLAG command
  * @data: data collected for get dump data operation
  */
-
-#define ETH_FW_DUMP_DISABLE 0
-
 struct ethtool_dump {
 	__u32	cmd;
 	__u32	version;
@@ -715,6 +929,8 @@ struct ethtool_dump {
 	__u8	data[0];
 };
 
+#define ETH_FW_DUMP_DISABLE 0
+
 /* for returning and changing feature sets */
 
 /**
@@ -734,8 +950,9 @@ struct ethtool_get_features_block {
 /**
  * struct ethtool_gfeatures - command to get state of device's features
  * @cmd: command number = %ETHTOOL_GFEATURES
- * @size: in: number of elements in the features[] array;
- *       out: number of elements in features[] needed to hold all features
+ * @size: On entry, the number of elements in the features[] array;
+ *	on return, the number of elements in features[] needed to hold
+ *	all features
  * @features: state of features
  */
 struct ethtool_gfeatures {
@@ -905,7 +1122,6 @@ enum ethtool_sfeatures_retval_bits {
 #define SPARC_ETH_GSET		ETHTOOL_GSET
 #define SPARC_ETH_SSET		ETHTOOL_SSET
 
-/* Indicates what features are supported by the interface. */
 #define SUPPORTED_10baseT_Half		(1 << 0)
 #define SUPPORTED_10baseT_Full		(1 << 1)
 #define SUPPORTED_100baseT_Half		(1 << 2)
@@ -934,7 +1150,6 @@ enum ethtool_sfeatures_retval_bits {
 #define SUPPORTED_40000baseSR4_Full	(1 << 25)
 #define SUPPORTED_40000baseLR4_Full	(1 << 26)
 
-/* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half		(1 << 0)
 #define ADVERTISED_10baseT_Full		(1 << 1)
 #define ADVERTISED_100baseT_Half	(1 << 2)
@@ -999,9 +1214,7 @@ enum ethtool_sfeatures_retval_bits {
 #define XCVR_DUMMY2		0x03
 #define XCVR_DUMMY3		0x04
 
-/* Enable or disable autonegotiation.  If this is set to enable,
- * the forced link modes above are completely ignored.
- */
+/* Enable or disable autonegotiation. */
 #define AUTONEG_DISABLE		0x00
 #define AUTONEG_ENABLE		0x01
 
diff --git a/include/uapi/linux/falloc.h b/include/uapi/linux/falloc.h
index 990c4ccf8b61..5ff562ddac0b 100644
--- a/include/uapi/linux/falloc.h
+++ b/include/uapi/linux/falloc.h
@@ -5,5 +5,26 @@
 #define FALLOC_FL_PUNCH_HOLE	0x02 /* de-allocates range */
 #define FALLOC_FL_NO_HIDE_STALE	0x04 /* reserved codepoint */
 
+/*
+ * FALLOC_FL_COLLAPSE_RANGE is used to remove a range of a file
+ * without leaving a hole in the file. The contents of the file beyond
+ * the range being removed is appended to the start offset of the range
+ * being removed (i.e. the hole that was punched is "collapsed"),
+ * resulting in a file layout that looks like the range that was
+ * removed never existed. As such collapsing a range of a file changes
+ * the size of the file, reducing it by the same length of the range
+ * that has been removed by the operation.
+ *
+ * Different filesystems may implement different limitations on the
+ * granularity of the operation. Most will limit operations to
+ * filesystem block size boundaries, but this boundary may be larger or
+ * smaller depending on the filesystem and/or the configuration of the
+ * filesystem or file.
+ *
+ * Attempting to collapse a range that crosses the end of the file is
+ * considered an illegal operation - just use ftruncate(2) if you need
+ * to collapse a range that crosses EOF.
+ */
+#define FALLOC_FL_COLLAPSE_RANGE	0x08
 
 #endif /* _UAPI_FALLOC_H_ */
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 60bb2f9f7b74..797472139a65 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -93,6 +93,9 @@
  *
  * 7.22
  *  - add FUSE_ASYNC_DIO
+ *
+ * 7.23
+ *  - add FUSE_WRITEBACK_CACHE
  */
 
 #ifndef _LINUX_FUSE_H
@@ -219,6 +222,7 @@ struct fuse_file_lock {
  * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one)
  * FUSE_READDIRPLUS_AUTO: adaptive readdirplus
  * FUSE_ASYNC_DIO: asynchronous direct I/O submission
+ * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes
  */
 #define FUSE_ASYNC_READ		(1 << 0)
 #define FUSE_POSIX_LOCKS	(1 << 1)
@@ -236,6 +240,7 @@ struct fuse_file_lock {
 #define FUSE_DO_READDIRPLUS	(1 << 13)
 #define FUSE_READDIRPLUS_AUTO	(1 << 14)
 #define FUSE_ASYNC_DIO		(1 << 15)
+#define FUSE_WRITEBACK_CACHE	(1 << 16)
 
 /**
  * CUSE INIT request/reply flags
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 0f24c07aed51..db3fdd083882 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -304,7 +304,13 @@ struct gfs2_dirent {
 	__be16 de_rec_len;
 	__be16 de_name_len;
 	__be16 de_type;
-	__u8 __pad[14];
+	union {
+		__u8 __pad[14];
+		struct {
+			__be16 de_rahead;
+			__u8 pad2[12];
+		};
+	};
 };
 
 /*
@@ -347,9 +353,9 @@ struct gfs2_leaf {
  * metadata header. Each inode, if it has extended attributes, will
  * have either a single block containing the extended attribute headers
  * or a single indirect block pointing to blocks containing the
- * extended attribure headers.
+ * extended attribute headers.
  *
- * The maximim size of the data part of an extended attribute is 64k
+ * The maximum size of the data part of an extended attribute is 64k
  * so the number of blocks required depends upon block size. Since the
  * block size also determines the number of pointers in an indirect
  * block, its a fairly complicated calculation to work out the maximum
diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h
new file mode 100644
index 000000000000..9beb7c991638
--- /dev/null
+++ b/include/uapi/linux/hyperv.h
@@ -0,0 +1,390 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _UAPI_HYPERV_H
+#define _UAPI_HYPERV_H
+
+#include <linux/uuid.h>
+
+/*
+ * Framework version for util services.
+ */
+#define UTIL_FW_MINOR  0
+
+#define UTIL_WS2K8_FW_MAJOR  1
+#define UTIL_WS2K8_FW_VERSION     (UTIL_WS2K8_FW_MAJOR << 16 | UTIL_FW_MINOR)
+
+#define UTIL_FW_MAJOR  3
+#define UTIL_FW_VERSION     (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
+
+
+/*
+ * Implementation of host controlled snapshot of the guest.
+ */
+
+#define VSS_OP_REGISTER 128
+
+enum hv_vss_op {
+	VSS_OP_CREATE = 0,
+	VSS_OP_DELETE,
+	VSS_OP_HOT_BACKUP,
+	VSS_OP_GET_DM_INFO,
+	VSS_OP_BU_COMPLETE,
+	/*
+	 * Following operations are only supported with IC version >= 5.0
+	 */
+	VSS_OP_FREEZE, /* Freeze the file systems in the VM */
+	VSS_OP_THAW, /* Unfreeze the file systems */
+	VSS_OP_AUTO_RECOVER,
+	VSS_OP_COUNT /* Number of operations, must be last */
+};
+
+
+/*
+ * Header for all VSS messages.
+ */
+struct hv_vss_hdr {
+	__u8 operation;
+	__u8 reserved[7];
+} __attribute__((packed));
+
+
+/*
+ * Flag values for the hv_vss_check_feature. Linux supports only
+ * one value.
+ */
+#define VSS_HBU_NO_AUTO_RECOVERY	0x00000005
+
+struct hv_vss_check_feature {
+	__u32 flags;
+} __attribute__((packed));
+
+struct hv_vss_check_dm_info {
+	__u32 flags;
+} __attribute__((packed));
+
+struct hv_vss_msg {
+	union {
+		struct hv_vss_hdr vss_hdr;
+		int error;
+	};
+	union {
+		struct hv_vss_check_feature vss_cf;
+		struct hv_vss_check_dm_info dm_info;
+	};
+} __attribute__((packed));
+
+/*
+ * Implementation of a host to guest copy facility.
+ */
+
+#define FCOPY_VERSION_0 0
+#define FCOPY_CURRENT_VERSION FCOPY_VERSION_0
+#define W_MAX_PATH 260
+
+enum hv_fcopy_op {
+	START_FILE_COPY = 0,
+	WRITE_TO_FILE,
+	COMPLETE_FCOPY,
+	CANCEL_FCOPY,
+};
+
+struct hv_fcopy_hdr {
+	__u32 operation;
+	uuid_le service_id0; /* currently unused */
+	uuid_le service_id1; /* currently unused */
+} __attribute__((packed));
+
+#define OVER_WRITE	0x1
+#define CREATE_PATH	0x2
+
+struct hv_start_fcopy {
+	struct hv_fcopy_hdr hdr;
+	__u16 file_name[W_MAX_PATH];
+	__u16 path_name[W_MAX_PATH];
+	__u32 copy_flags;
+	__u64 file_size;
+} __attribute__((packed));
+
+/*
+ * The file is chunked into fragments.
+ */
+#define DATA_FRAGMENT	(6 * 1024)
+
+struct hv_do_fcopy {
+	struct hv_fcopy_hdr hdr;
+	__u64	offset;
+	__u32	size;
+	__u8	data[DATA_FRAGMENT];
+};
+
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ */
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note:  This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note:  This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatibility.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ *	Index		Key Name
+ *	0		FullyQualifiedDomainName
+ *	1		IntegrationServicesVersion
+ *	2		NetworkAddressIPv4
+ *	3		NetworkAddressIPv6
+ *	4		OSBuildNumber
+ *	5		OSName
+ *	6		OSMajorVersion
+ *	7		OSMinorVersion
+ *	8		OSVersion
+ *	9		ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+#define REG_U32 4
+#define REG_U64 8
+
+/*
+ * As we look at expanding the KVP functionality to include
+ * IP injection functionality, we need to maintain binary
+ * compatibility with older daemons.
+ *
+ * The KVP opcodes are defined by the host and it was unfortunate
+ * that I chose to treat the registration operation as part of the
+ * KVP operations defined by the host.
+ * Here is the level of compatibility
+ * (between the user level daemon and the kernel KVP driver) that we
+ * will implement:
+ *
+ * An older daemon will always be supported on a newer driver.
+ * A given user level daemon will require a minimal version of the
+ * kernel driver.
+ * If we cannot handle the version differences, we will fail gracefully
+ * (this can happen when we have a user level daemon that is more
+ * advanced than the KVP driver.
+ *
+ * We will use values used in this handshake for determining if we have
+ * workable user level daemon and the kernel driver. We begin by taking the
+ * registration opcode out of the KVP opcode namespace. We will however,
+ * maintain compatibility with the existing user-level daemon code.
+ */
+
+/*
+ * Daemon code not supporting IP injection (legacy daemon).
+ */
+
+#define KVP_OP_REGISTER	4
+
+/*
+ * Daemon code supporting IP injection.
+ * The KVP opcode field is used to communicate the
+ * registration information; so define a namespace that
+ * will be distinct from the host defined KVP opcode.
+ */
+
+#define KVP_OP_REGISTER1 100
+
+enum hv_kvp_exchg_op {
+	KVP_OP_GET = 0,
+	KVP_OP_SET,
+	KVP_OP_DELETE,
+	KVP_OP_ENUMERATE,
+	KVP_OP_GET_IP_INFO,
+	KVP_OP_SET_IP_INFO,
+	KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+	KVP_POOL_EXTERNAL = 0,
+	KVP_POOL_GUEST,
+	KVP_POOL_AUTO,
+	KVP_POOL_AUTO_EXTERNAL,
+	KVP_POOL_AUTO_INTERNAL,
+	KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+/*
+ * Some Hyper-V status codes.
+ */
+
+#define HV_S_OK				0x00000000
+#define HV_E_FAIL			0x80004005
+#define HV_S_CONT			0x80070103
+#define HV_ERROR_NOT_SUPPORTED		0x80070032
+#define HV_ERROR_MACHINE_LOCKED		0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED	0x8007048F
+#define HV_INVALIDARG			0x80070057
+#define HV_GUID_NOTFOUND		0x80041002
+
+#define ADDR_FAMILY_NONE	0x00
+#define ADDR_FAMILY_IPV4	0x01
+#define ADDR_FAMILY_IPV6	0x02
+
+#define MAX_ADAPTER_ID_SIZE	128
+#define MAX_IP_ADDR_SIZE	1024
+#define MAX_GATEWAY_SIZE	512
+
+
+struct hv_kvp_ipaddr_value {
+	__u16	adapter_id[MAX_ADAPTER_ID_SIZE];
+	__u8	addr_family;
+	__u8	dhcp_enabled;
+	__u16	ip_addr[MAX_IP_ADDR_SIZE];
+	__u16	sub_net[MAX_IP_ADDR_SIZE];
+	__u16	gate_way[MAX_GATEWAY_SIZE];
+	__u16	dns_addr[MAX_IP_ADDR_SIZE];
+} __attribute__((packed));
+
+
+struct hv_kvp_hdr {
+	__u8 operation;
+	__u8 pool;
+	__u16 pad;
+} __attribute__((packed));
+
+struct hv_kvp_exchg_msg_value {
+	__u32 value_type;
+	__u32 key_size;
+	__u32 value_size;
+	__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+	union {
+		__u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+		__u32 value_u32;
+		__u64 value_u64;
+	};
+} __attribute__((packed));
+
+struct hv_kvp_msg_enumerate {
+	__u32 index;
+	struct hv_kvp_exchg_msg_value data;
+} __attribute__((packed));
+
+struct hv_kvp_msg_get {
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg_set {
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg_delete {
+	__u32 key_size;
+	__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+};
+
+struct hv_kvp_register {
+	__u8 version[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+};
+
+struct hv_kvp_msg {
+	union {
+		struct hv_kvp_hdr	kvp_hdr;
+		int error;
+	};
+	union {
+		struct hv_kvp_msg_get		kvp_get;
+		struct hv_kvp_msg_set		kvp_set;
+		struct hv_kvp_msg_delete	kvp_delete;
+		struct hv_kvp_msg_enumerate	kvp_enum_data;
+		struct hv_kvp_ipaddr_value      kvp_ip_val;
+		struct hv_kvp_register		kvp_register;
+	} body;
+} __attribute__((packed));
+
+struct hv_kvp_ip_msg {
+	__u8 operation;
+	__u8 pool;
+	struct hv_kvp_ipaddr_value      kvp_ip_val;
+} __attribute__((packed));
+
+#endif /* _UAPI_HYPERV_H */
diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
index d758163b0e43..9cf2394f0bcf 100644
--- a/include/uapi/linux/if.h
+++ b/include/uapi/linux/if.h
@@ -27,65 +27,91 @@
 #define	IFALIASZ	256
 #include <linux/hdlc/ioctl.h>
 
-/* Standard interface flags (netdevice->flags). */
-#define	IFF_UP		0x1		/* interface is up		*/
-#define	IFF_BROADCAST	0x2		/* broadcast address valid	*/
-#define	IFF_DEBUG	0x4		/* turn on debugging		*/
-#define	IFF_LOOPBACK	0x8		/* is a loopback net		*/
-#define	IFF_POINTOPOINT	0x10		/* interface is has p-p link	*/
-#define	IFF_NOTRAILERS	0x20		/* avoid use of trailers	*/
-#define	IFF_RUNNING	0x40		/* interface RFC2863 OPER_UP	*/
-#define	IFF_NOARP	0x80		/* no ARP protocol		*/
-#define	IFF_PROMISC	0x100		/* receive all packets		*/
-#define	IFF_ALLMULTI	0x200		/* receive all multicast packets*/
-
-#define IFF_MASTER	0x400		/* master of a load balancer 	*/
-#define IFF_SLAVE	0x800		/* slave of a load balancer	*/
-
-#define IFF_MULTICAST	0x1000		/* Supports multicast		*/
-
-#define IFF_PORTSEL	0x2000          /* can set media type		*/
-#define IFF_AUTOMEDIA	0x4000		/* auto media select active	*/
-#define IFF_DYNAMIC	0x8000		/* dialup device with changing addresses*/
-
-#define IFF_LOWER_UP	0x10000		/* driver signals L1 up		*/
-#define IFF_DORMANT	0x20000		/* driver signals dormant	*/
+/**
+ * enum net_device_flags - &struct net_device flags
+ *
+ * These are the &struct net_device flags, they can be set by drivers, the
+ * kernel and some can be triggered by userspace. Userspace can query and
+ * set these flags using userspace utilities but there is also a sysfs
+ * entry available for all dev flags which can be queried and set. These flags
+ * are shared for all types of net_devices. The sysfs entries are available
+ * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs
+ * are annotated below, note that only a few flags can be toggled and some
+ * other flags are always always preserved from the original net_device flags
+ * even if you try to set them via sysfs. Flags which are always preserved
+ * are kept under the flag grouping @IFF_VOLATILE. Flags which are volatile
+ * are annotated below as such.
+ *
+ * You should have a pretty good reason to be extending these flags.
+ *
+ * @IFF_UP: interface is up. Can be toggled through sysfs.
+ * @IFF_BROADCAST: broadcast address valid. Volatile.
+ * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs.
+ * @IFF_LOOPBACK: is a loopback net. Volatile.
+ * @IFF_POINTOPOINT: interface is has p-p link. Volatile.
+ * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs.
+ *	Volatile.
+ * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile.
+ * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile.
+ * @IFF_PROMISC: receive all packets. Can be toggled through sysfs.
+ * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through
+ *	sysfs.
+ * @IFF_MASTER: master of a load balancer. Volatile.
+ * @IFF_SLAVE: slave of a load balancer. Volatile.
+ * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs.
+ * @IFF_PORTSEL: can set media type. Can be toggled through sysfs.
+ * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs.
+ * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled
+ *	through sysfs.
+ * @IFF_LOWER_UP: driver signals L1 up. Volatile.
+ * @IFF_DORMANT: driver signals dormant. Volatile.
+ * @IFF_ECHO: echo sent packets. Volatile.
+ */
+enum net_device_flags {
+	IFF_UP				= 1<<0,  /* sysfs */
+	IFF_BROADCAST			= 1<<1,  /* volatile */
+	IFF_DEBUG			= 1<<2,  /* sysfs */
+	IFF_LOOPBACK			= 1<<3,  /* volatile */
+	IFF_POINTOPOINT			= 1<<4,  /* volatile */
+	IFF_NOTRAILERS			= 1<<5,  /* sysfs */
+	IFF_RUNNING			= 1<<6,  /* volatile */
+	IFF_NOARP			= 1<<7,  /* sysfs */
+	IFF_PROMISC			= 1<<8,  /* sysfs */
+	IFF_ALLMULTI			= 1<<9,  /* sysfs */
+	IFF_MASTER			= 1<<10, /* volatile */
+	IFF_SLAVE			= 1<<11, /* volatile */
+	IFF_MULTICAST			= 1<<12, /* sysfs */
+	IFF_PORTSEL			= 1<<13, /* sysfs */
+	IFF_AUTOMEDIA			= 1<<14, /* sysfs */
+	IFF_DYNAMIC			= 1<<15, /* sysfs */
+	IFF_LOWER_UP			= 1<<16, /* volatile */
+	IFF_DORMANT			= 1<<17, /* volatile */
+	IFF_ECHO			= 1<<18, /* volatile */
+};
 
-#define IFF_ECHO	0x40000		/* echo sent packets		*/
+#define IFF_UP				IFF_UP
+#define IFF_BROADCAST			IFF_BROADCAST
+#define IFF_DEBUG			IFF_DEBUG
+#define IFF_LOOPBACK			IFF_LOOPBACK
+#define IFF_POINTOPOINT			IFF_POINTOPOINT
+#define IFF_NOTRAILERS			IFF_NOTRAILERS
+#define IFF_RUNNING			IFF_RUNNING
+#define IFF_NOARP			IFF_NOARP
+#define IFF_PROMISC			IFF_PROMISC
+#define IFF_ALLMULTI			IFF_ALLMULTI
+#define IFF_MASTER			IFF_MASTER
+#define IFF_SLAVE			IFF_SLAVE
+#define IFF_MULTICAST			IFF_MULTICAST
+#define IFF_PORTSEL			IFF_PORTSEL
+#define IFF_AUTOMEDIA			IFF_AUTOMEDIA
+#define IFF_DYNAMIC			IFF_DYNAMIC
+#define IFF_LOWER_UP			IFF_LOWER_UP
+#define IFF_DORMANT			IFF_DORMANT
+#define IFF_ECHO			IFF_ECHO
 
 #define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
 		IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
 
-/* Private (from user) interface flags (netdevice->priv_flags). */
-#define IFF_802_1Q_VLAN 0x1             /* 802.1Q VLAN device.          */
-#define IFF_EBRIDGE	0x2		/* Ethernet bridging device.	*/
-#define IFF_SLAVE_INACTIVE	0x4	/* bonding slave not the curr. active */
-#define IFF_MASTER_8023AD	0x8	/* bonding master, 802.3ad. 	*/
-#define IFF_MASTER_ALB	0x10		/* bonding master, balance-alb.	*/
-#define IFF_BONDING	0x20		/* bonding master or slave	*/
-#define IFF_SLAVE_NEEDARP 0x40		/* need ARPs for validation	*/
-#define IFF_ISATAP	0x80		/* ISATAP interface (RFC4214)	*/
-#define IFF_MASTER_ARPMON 0x100		/* bonding master, ARP mon in use */
-#define IFF_WAN_HDLC	0x200		/* WAN HDLC device		*/
-#define IFF_XMIT_DST_RELEASE 0x400	/* dev_hard_start_xmit() is allowed to
-					 * release skb->dst
-					 */
-#define IFF_DONT_BRIDGE 0x800		/* disallow bridging this ether dev */
-#define IFF_DISABLE_NETPOLL	0x1000	/* disable netpoll at run-time */
-#define IFF_MACVLAN_PORT	0x2000	/* device used as macvlan port */
-#define IFF_BRIDGE_PORT	0x4000		/* device used as bridge port */
-#define IFF_OVS_DATAPATH	0x8000	/* device used as Open vSwitch
-					 * datapath port */
-#define IFF_TX_SKB_SHARING	0x10000	/* The interface supports sharing
-					 * skbs on transmit */
-#define IFF_UNICAST_FLT	0x20000		/* Supports unicast filtering	*/
-#define IFF_TEAM_PORT	0x40000		/* device used as team port */
-#define IFF_SUPP_NOFCS	0x80000		/* device supports sending custom FCS */
-#define IFF_LIVE_ADDR_CHANGE 0x100000	/* device supports hardware address
-					 * change when it's running */
-#define IFF_MACVLAN 0x200000		/* Macvlan device */
-
-
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
 
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 2ce0f6a78fa5..ba8b15f07940 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -68,11 +68,11 @@
 #define ETH_P_SLOW	0x8809		/* Slow Protocol. See 802.3ad 43B */
 #define ETH_P_WCCP	0x883E		/* Web-cache coordination protocol
 					 * defined in draft-wilson-wrec-wccp-v2-00.txt */
-#define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
-#define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
 #define ETH_P_MPLS_UC	0x8847		/* MPLS Unicast traffic		*/
 #define ETH_P_MPLS_MC	0x8848		/* MPLS Multicast traffic	*/
 #define ETH_P_ATMMPOA	0x884c		/* MultiProtocol Over ATM	*/
+#define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
+#define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
 #define ETH_P_LINK_CTL	0x886c		/* HPNA, wlan link local tunnel */
 #define ETH_P_ATMFATE	0x8884		/* Frame-based ATM Transport
 					 * over Ethernet
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
index 393c5de09d42..c33a65e3d62c 100644
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -120,6 +120,10 @@ struct in_addr {
  * this socket to prevent accepting spoofed ones.
  */
 #define IP_PMTUDISC_INTERFACE		4
+/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get
+ * fragmented if they exeed the interface mtu
+ */
+#define IP_PMTUDISC_OMIT		5
 
 #define IP_MULTICAST_IF			32
 #define IP_MULTICAST_TTL 		33
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index e9a1d2d973b6..0d8e0f0342dc 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -185,6 +185,10 @@ struct in6_flowlabel_req {
  * also see comments on IP_PMTUDISC_INTERFACE
  */
 #define IPV6_PMTUDISC_INTERFACE		4
+/* weaker version of IPV6_PMTUDISC_INTERFACE, which allows packets to
+ * get fragmented if they exceed the interface mtu
+ */
+#define IPV6_PMTUDISC_OMIT		5
 
 /* Flowlabel */
 #define IPV6_FLOWLABEL_MGR	32
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 932d7f2637d6..7d76401d2bb5 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -413,6 +413,8 @@ struct kvm_s390_psw {
 #define KVM_S390_PROGRAM_INT		0xfffe0001u
 #define KVM_S390_SIGP_SET_PREFIX	0xfffe0002u
 #define KVM_S390_RESTART		0xfffe0003u
+#define KVM_S390_INT_PFAULT_INIT	0xfffe0004u
+#define KVM_S390_INT_PFAULT_DONE	0xfffe0005u
 #define KVM_S390_MCHK			0xfffe1000u
 #define KVM_S390_INT_VIRTIO		0xffff2603u
 #define KVM_S390_INT_SERVICE		0xffff2401u
@@ -434,6 +436,69 @@ struct kvm_s390_interrupt {
 	__u64 parm64;
 };
 
+struct kvm_s390_io_info {
+	__u16 subchannel_id;
+	__u16 subchannel_nr;
+	__u32 io_int_parm;
+	__u32 io_int_word;
+};
+
+struct kvm_s390_ext_info {
+	__u32 ext_params;
+	__u32 pad;
+	__u64 ext_params2;
+};
+
+struct kvm_s390_pgm_info {
+	__u64 trans_exc_code;
+	__u64 mon_code;
+	__u64 per_address;
+	__u32 data_exc_code;
+	__u16 code;
+	__u16 mon_class_nr;
+	__u8 per_code;
+	__u8 per_atmid;
+	__u8 exc_access_id;
+	__u8 per_access_id;
+	__u8 op_access_id;
+	__u8 pad[3];
+};
+
+struct kvm_s390_prefix_info {
+	__u32 address;
+};
+
+struct kvm_s390_extcall_info {
+	__u16 code;
+};
+
+struct kvm_s390_emerg_info {
+	__u16 code;
+};
+
+struct kvm_s390_mchk_info {
+	__u64 cr14;
+	__u64 mcic;
+	__u64 failing_storage_address;
+	__u32 ext_damage_code;
+	__u32 pad;
+	__u8 fixed_logout[16];
+};
+
+struct kvm_s390_irq {
+	__u64 type;
+	union {
+		struct kvm_s390_io_info io;
+		struct kvm_s390_ext_info ext;
+		struct kvm_s390_pgm_info pgm;
+		struct kvm_s390_emerg_info emerg;
+		struct kvm_s390_extcall_info extcall;
+		struct kvm_s390_prefix_info prefix;
+		struct kvm_s390_mchk_info mchk;
+		char reserved[64];
+	} u;
+};
+
 /* for KVM_SET_GUEST_DEBUG */
 
 #define KVM_GUESTDBG_ENABLE		0x00000001
@@ -855,6 +920,7 @@ struct kvm_device_attr {
 #define   KVM_DEV_VFIO_GROUP_ADD			1
 #define   KVM_DEV_VFIO_GROUP_DEL			2
 #define KVM_DEV_TYPE_ARM_VGIC_V2	5
+#define KVM_DEV_TYPE_FLIC		6
 
 /*
  * ioctls for VM fds
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 91054fd660e0..a12e6cae5132 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -418,8 +418,18 @@
  *	%NL80211_ATTR_SSID attribute, and can optionally specify the association
  *	IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP,
  *	%NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
- *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
- *	%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
+ *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
+ *	%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and
+ *	%NL80211_ATTR_WIPHY_FREQ_HINT.
+ *	If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are
+ *	restrictions on BSS selection, i.e., they effectively prevent roaming
+ *	within the ESS. %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT
+ *	can be included to provide a recommendation of the initial BSS while
+ *	allowing the driver to roam to other BSSes within the ESS and also to
+ *	ignore this recommendation if the indicated BSS is not ideal. Only one
+ *	set of BSSID,frequency parameters is used (i.e., either the enforcing
+ *	%NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
+ *	%NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
  *	Background scan period can optionally be
  *	specified in %NL80211_ATTR_BG_SCAN_PERIOD,
  *	if not specified default background scan configuration
@@ -1555,6 +1565,16 @@ enum nl80211_commands {
  *	data is in the format defined for the payload of the QoS Map Set element
  *	in IEEE Std 802.11-2012, 8.4.2.97.
  *
+ * @NL80211_ATTR_MAC_HINT: MAC address recommendation as initial BSS
+ * @NL80211_ATTR_WIPHY_FREQ_HINT: frequency of the recommended initial BSS
+ *
+ * @NL80211_ATTR_MAX_AP_ASSOC_STA: Device attribute that indicates how many
+ *	associated stations are supported in AP mode (including P2P GO); u32.
+ *	Since drivers may not have a fixed limit on the maximum number (e.g.,
+ *	other concurrent operations may affect this), drivers are allowed to
+ *	advertise values that cannot always be met. In such cases, an attempt
+ *	to add a new station entry with @NL80211_CMD_NEW_STATION may fail.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1883,6 +1903,11 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_QOS_MAP,
 
+	NL80211_ATTR_MAC_HINT,
+	NL80211_ATTR_WIPHY_FREQ_HINT,
+
+	NL80211_ATTR_MAX_AP_ASSOC_STA,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2412,7 +2437,10 @@ enum nl80211_reg_type {
  * 	in KHz. This is not a center a frequency but an actual regulatory
  * 	band edge.
  * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
- * 	frequency range, in KHz.
+ *	frequency range, in KHz. If not present or 0, maximum available
+ *	bandwidth should be calculated base on contiguous rules and wider
+ *	channels will be allowed to cross multiple contiguous/overlapping
+ *	frequency ranges.
  * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
  * 	for a given frequency range. The value is in mBi (100 * dBi).
  * 	If you don't have one then don't send this.
@@ -2442,9 +2470,15 @@ enum nl80211_reg_rule_attr {
  * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
  * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
  * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
- * only report BSS with matching SSID.
+ *	only report BSS with matching SSID.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
- *	BSS in scan results. Filtering is turned off if not specified.
+ *	BSS in scan results. Filtering is turned off if not specified. Note that
+ *	if this attribute is in a match set of its own, then it is treated as
+ *	the default value for all matchsets with an SSID, rather than being a
+ *	matchset of its own without an RSSI filter. This is due to problems with
+ *	how this API was implemented in the past. Also, due to the same problem,
+ *	the only way to create a matchset with only an RSSI filter (with this
+ *	attribute) is if there's only a single matchset with the RSSI attribute.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
  *	attribute number currently defined
  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3131,6 +3165,7 @@ enum nl80211_key_attributes {
  *	in an array of MCS numbers.
  * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
  *	see &struct nl80211_txrate_vht
+ * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi
  * @__NL80211_TXRATE_AFTER_LAST: internal
  * @NL80211_TXRATE_MAX: highest TX rate attribute
  */
@@ -3139,6 +3174,7 @@ enum nl80211_tx_rate_attributes {
 	NL80211_TXRATE_LEGACY,
 	NL80211_TXRATE_HT,
 	NL80211_TXRATE_VHT,
+	NL80211_TXRATE_GI,
 
 	/* keep last */
 	__NL80211_TXRATE_AFTER_LAST,
@@ -3156,6 +3192,12 @@ struct nl80211_txrate_vht {
 	__u16 mcs[NL80211_VHT_NSS_MAX];
 };
 
+enum nl80211_txrate_gi {
+	NL80211_TXRATE_DEFAULT_GI,
+	NL80211_TXRATE_FORCE_SGI,
+	NL80211_TXRATE_FORCE_LGI,
+};
+
 /**
  * enum nl80211_band - Frequency band
  * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
diff --git a/include/uapi/linux/pfkeyv2.h b/include/uapi/linux/pfkeyv2.h
index 0b80c806631f..ada7f0171ccc 100644
--- a/include/uapi/linux/pfkeyv2.h
+++ b/include/uapi/linux/pfkeyv2.h
@@ -235,6 +235,18 @@ struct sadb_x_kmaddress {
 } __attribute__((packed));
 /* sizeof(struct sadb_x_kmaddress) == 8 */
 
+/* To specify the SA dump filter */
+struct sadb_x_filter {
+	__u16	sadb_x_filter_len;
+	__u16	sadb_x_filter_exttype;
+	__u32	sadb_x_filter_saddr[4];
+	__u32	sadb_x_filter_daddr[4];
+	__u16	sadb_x_filter_family;
+	__u8	sadb_x_filter_splen;
+	__u8	sadb_x_filter_dplen;
+} __attribute__((packed));
+/* sizeof(struct sadb_x_filter) == 40 */
+
 /* Message types */
 #define SADB_RESERVED		0
 #define SADB_GETSPI		1
@@ -358,7 +370,8 @@ struct sadb_x_kmaddress {
 #define SADB_X_EXT_SEC_CTX		24
 /* Used with MIGRATE to pass @ to IKE for negotiation */
 #define SADB_X_EXT_KMADDRESS		25
-#define SADB_EXT_MAX			25
+#define SADB_X_EXT_FILTER		26
+#define SADB_EXT_MAX			26
 
 /* Identity Extension values */
 #define SADB_IDENTTYPE_RESERVED	0
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 289760f424aa..58afc04c107e 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -149,4 +149,7 @@
 
 #define PR_GET_TID_ADDRESS	40
 
+#define PR_SET_THP_DISABLE	41
+#define PR_GET_THP_DISABLE	42
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index bbaba22f2d1b..df40137f33dd 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -252,6 +252,7 @@ enum
 	LINUX_MIB_TCPCHALLENGEACK,		/* TCPChallengeACK */
 	LINUX_MIB_TCPSYNCHALLENGE,		/* TCPSYNChallenge */
 	LINUX_MIB_TCPFASTOPENACTIVE,		/* TCPFastOpenActive */
+	LINUX_MIB_TCPFASTOPENACTIVEFAIL,	/* TCPFastOpenActiveFail */
 	LINUX_MIB_TCPFASTOPENPASSIVE,		/* TCPFastOpenPassive*/
 	LINUX_MIB_TCPFASTOPENPASSIVEFAIL,	/* TCPFastOpenPassiveFail */
 	LINUX_MIB_TCPFASTOPENLISTENOVERFLOW,	/* TCPFastOpenListenOverflow */
@@ -259,6 +260,11 @@ enum
 	LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */
 	LINUX_MIB_BUSYPOLLRXPACKETS,		/* BusyPollRxPackets */
 	LINUX_MIB_TCPAUTOCORKING,		/* TCPAutoCorking */
+	LINUX_MIB_TCPFROMZEROWINDOWADV,		/* TCPFromZeroWindowAdv */
+	LINUX_MIB_TCPTOZEROWINDOWADV,		/* TCPToZeroWindowAdv */
+	LINUX_MIB_TCPWANTZEROWINDOWADV,		/* TCPWantZeroWindowAdv */
+	LINUX_MIB_TCPSYNRETRANS,		/* TCPSynRetrans */
+	LINUX_MIB_TCPORIGDATASENT,		/* TCPOrigDataSent */
 	__LINUX_MIB_MAX
 };
 
diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h
index 52d9ed01855f..dd5f21e75805 100644
--- a/include/uapi/linux/spi/spidev.h
+++ b/include/uapi/linux/spi/spidev.h
@@ -42,6 +42,10 @@
 #define SPI_LOOP		0x20
 #define SPI_NO_CS		0x40
 #define SPI_READY		0x80
+#define SPI_TX_DUAL		0x100
+#define SPI_TX_QUAD		0x200
+#define SPI_RX_DUAL		0x400
+#define SPI_RX_QUAD		0x800
 
 /*---------------------------------------------------------------------------*/
 
@@ -92,7 +96,9 @@ struct spi_ioc_transfer {
 	__u16		delay_usecs;
 	__u8		bits_per_word;
 	__u8		cs_change;
-	__u32		pad;
+	__u8		tx_nbits;
+	__u8		rx_nbits;
+	__u16		pad;
 
 	/* If the contents of 'struct spi_ioc_transfer' ever change
 	 * incompatibly, then the ioctl number (currently 0) must change;
@@ -110,7 +116,7 @@ struct spi_ioc_transfer {
 #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
 
 
-/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
+/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
 #define SPI_IOC_RD_MODE			_IOR(SPI_IOC_MAGIC, 1, __u8)
 #define SPI_IOC_WR_MODE			_IOW(SPI_IOC_MAGIC, 1, __u8)
 
@@ -126,6 +132,10 @@ struct spi_ioc_transfer {
 #define SPI_IOC_RD_MAX_SPEED_HZ		_IOR(SPI_IOC_MAGIC, 4, __u32)
 #define SPI_IOC_WR_MAX_SPEED_HZ		_IOW(SPI_IOC_MAGIC, 4, __u32)
 
+/* Read / Write of the SPI mode field */
+#define SPI_IOC_RD_MODE32		_IOR(SPI_IOC_MAGIC, 5, __u32)
+#define SPI_IOC_WR_MODE32		_IOW(SPI_IOC_MAGIC, 5, __u32)
+
 
 
 #endif /* SPIDEV_H */
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 377f1e59411d..3b9718328d8b 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -186,6 +186,9 @@ struct tcp_info {
 	__u32	tcpi_rcv_space;
 
 	__u32	tcpi_total_retrans;
+
+	__u64	tcpi_pacing_rate;
+	__u64	tcpi_max_pacing_rate;
 };
 
 /* for TCP_MD5SIG socket option */
diff --git a/include/uapi/linux/tcp_metrics.h b/include/uapi/linux/tcp_metrics.h
index 54a37b13f2c4..93533926035c 100644
--- a/include/uapi/linux/tcp_metrics.h
+++ b/include/uapi/linux/tcp_metrics.h
@@ -11,12 +11,15 @@
 #define TCP_METRICS_GENL_VERSION	0x1
 
 enum tcp_metric_index {
-	TCP_METRIC_RTT,
-	TCP_METRIC_RTTVAR,
+	TCP_METRIC_RTT,		/* in ms units */
+	TCP_METRIC_RTTVAR,	/* in ms units */
 	TCP_METRIC_SSTHRESH,
 	TCP_METRIC_CWND,
 	TCP_METRIC_REORDERING,
 
+	TCP_METRIC_RTT_US,	/* in usec units */
+	TCP_METRIC_RTTVAR_US,	/* in usec units */
+
 	/* Always last.  */
 	__TCP_METRIC_MAX,
 };
diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h
index fe46431593f9..0389b489bbba 100644
--- a/include/uapi/linux/uinput.h
+++ b/include/uapi/linux/uinput.h
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *	0.4	01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *		- add UI_GET_SYSNAME ioctl
  *	0.3	24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
  *		- update ff support for the changes in kernel interface
  *		- add UINPUT_VERSION
@@ -35,7 +37,7 @@
 #include <linux/types.h>
 #include <linux/input.h>
 
-#define UINPUT_VERSION		3
+#define UINPUT_VERSION		4
 
 
 struct uinput_ff_upload {
@@ -73,6 +75,15 @@ struct uinput_ff_erase {
 #define UI_BEGIN_FF_ERASE	_IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
 #define UI_END_FF_ERASE		_IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
 
+/**
+ * UI_GET_SYSNAME - get the sysfs name of the created uinput device
+ *
+ * @return the sysfs name of the created virtual input device.
+ * The complete sysfs path is then /sys/devices/virtual/input/--NAME--
+ * Usually, it is in the form "inputN"
+ */
+#define UI_GET_SYSNAME(len)	_IOC(_IOC_READ, UINPUT_IOCTL_BASE, 300, len)
+
 /*
  * To write a force-feedback-capable driver, the upload_effect
  * and erase_effect callbacks in input_dev must be implemented.
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 0fd47f5bc146..cb9023d4f063 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -23,6 +23,12 @@
 
 #define VFIO_TYPE1_IOMMU		1
 #define VFIO_SPAPR_TCE_IOMMU		2
+#define VFIO_TYPE1v2_IOMMU		3
+/*
+ * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping).  This
+ * capability is subject to change as groups are added or removed.
+ */
+#define VFIO_DMA_CC_IOMMU		4
 
 /*
  * The IOCTL interface is designed for extensibility by embedding the
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index a8cd6a4a2970..6550c679584f 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -298,6 +298,8 @@ enum xfrm_attr_type_t {
 	XFRMA_TFCPAD,		/* __u32 */
 	XFRMA_REPLAY_ESN_VAL,	/* struct xfrm_replay_esn */
 	XFRMA_SA_EXTRA_FLAGS,	/* __u32 */
+	XFRMA_PROTO,		/* __u8 */
+	XFRMA_FILTER,		/* struct xfrm_filter */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -474,6 +476,14 @@ struct xfrm_user_mapping {
 	__be16				new_sport;
 };
 
+struct xfrm_filter {
+	xfrm_address_t			saddr;
+	xfrm_address_t			daddr;
+	__u16				family;
+	__u8				splen;
+	__u8				dplen;
+};
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h
index 723c324590c1..b98585ad3346 100644
--- a/include/uapi/mtd/ubi-user.h
+++ b/include/uapi/mtd/ubi-user.h
@@ -134,6 +134,13 @@
  * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be
  * passed. The object describes which property should be set, and to which value
  * it should be set.
+ *
+ * Block devices on UBI volumes
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * To attach or detach a block device from an UBI volume the %UBI_IOCVOLATTBLK
+ * and %UBI_IOCVOLDETBLK ioctl commands should be used, respectively.
+ * These commands take no arguments.
  */
 
 /*
@@ -191,6 +198,10 @@
 /* Set an UBI volume property */
 #define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
 			       struct ubi_set_vol_prop_req)
+/* Attach a block device to an UBI volume */
+#define UBI_IOCVOLATTBLK _IO(UBI_VOL_IOC_MAGIC, 7)
+/* Detach a block device from an UBI volume */
+#define UBI_IOCVOLDETBLK _IO(UBI_VOL_IOC_MAGIC, 8)
 
 /* Maximum MTD device name length supported by UBI */
 #define MAX_UBI_MTD_NAME_LEN 127
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3d7c51a6f9ff..1eb9aa605eee 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -323,7 +323,6 @@ enum omapdss_version {
 
 /* Board specific data */
 struct omap_dss_board_info {
-	int (*get_context_loss_count)(struct device *dev);
 	int num_devices;
 	struct omap_dss_device **devices;
 	struct omap_dss_device *default_device;
diff --git a/include/video/sgivw.h b/include/video/sgivw.h
deleted file mode 100644
index f6aa5692e74b..000000000000
--- a/include/video/sgivw.h
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- *  linux/drivers/video/sgivw.h -- SGI DBE frame buffer device header
- *
- *      Copyright (C) 1999 Silicon Graphics, Inc.
- *      Jeffrey Newquist, newquist@engr.sgi.som
- *
- *  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 __SGIVWFB_H__
-#define __SGIVWFB_H__
-
-#define DBE_GETREG(reg, dest)		((dest) = DBE_REG_BASE->reg)
-#define DBE_SETREG(reg, src)		DBE_REG_BASE->reg = (src)
-#define DBE_IGETREG(reg, idx, dest)	((dest) = DBE_REG_BASE->reg[idx])
-#define DBE_ISETREG(reg, idx, src)	(DBE_REG_BASE->reg[idx] = (src))
-
-#define MASK(msb, lsb)          ( (((u32)1<<((msb)-(lsb)+1))-1) << (lsb) )
-#define GET(v, msb, lsb)        ( ((u32)(v) & MASK(msb,lsb)) >> (lsb) )
-#define SET(v, f, msb, lsb)     ( (v) = ((v)&~MASK(msb,lsb)) | (( (u32)(f)<<(lsb) ) & MASK(msb,lsb)) )
-
-#define GET_DBE_FIELD(reg, field, v)        GET((v), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB)
-#define SET_DBE_FIELD(reg, field, v, f)     SET((v), (f), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB)
-
-/* NOTE: All loads/stores must be 32 bits and uncached */
-
-#define DBE_REG_PHYS	0xd0000000
-#define DBE_REG_SIZE        0x01000000
-
-struct asregs {
-  volatile u32 ctrlstat;     /* 0x000000 general control */
-  volatile u32 dotclock;     /* 0x000004 dot clock PLL control */
-  volatile u32 i2c;          /* 0x000008 crt I2C control */
-  volatile u32 sysclk;       /* 0x00000c system clock PLL control */
-  volatile u32 i2cfp;        /* 0x000010 flat panel I2C control */
-  volatile u32 id;           /* 0x000014 device id/chip revision */
-  volatile u32 config;       /* 0x000018 power on configuration */
-  volatile u32 bist;         /* 0x00001c internal bist status */
-
-  char _pad0[ 0x010000 - 0x000020 ];
-
-  volatile u32 vt_xy;        /* 0x010000 current dot coords */
-  volatile u32 vt_xymax;     /* 0x010004 maximum dot coords */
-  volatile u32 vt_vsync;     /* 0x010008 vsync on/off */
-  volatile u32 vt_hsync;     /* 0x01000c hsync on/off */
-  volatile u32 vt_vblank;    /* 0x010010 vblank on/off */
-  volatile u32 vt_hblank;    /* 0x010014 hblank on/off */
-  volatile u32 vt_flags;     /* 0x010018 polarity of vt signals */
-  volatile u32 vt_f2rf_lock; /* 0x01001c f2rf & framelck y coord */
-  volatile u32 vt_intr01;    /* 0x010020 intr 0,1 y coords */
-  volatile u32 vt_intr23;    /* 0x010024 intr 2,3 y coords */
-  volatile u32 fp_hdrv;      /* 0x010028 flat panel hdrv on/off */
-  volatile u32 fp_vdrv;      /* 0x01002c flat panel vdrv on/off */
-  volatile u32 fp_de;        /* 0x010030 flat panel de on/off */
-  volatile u32 vt_hpixen;    /* 0x010034 intrnl horiz pixel on/off*/
-  volatile u32 vt_vpixen;    /* 0x010038 intrnl vert pixel on/off */
-  volatile u32 vt_hcmap;     /* 0x01003c cmap write (horiz) */
-  volatile u32 vt_vcmap;     /* 0x010040 cmap write (vert) */
-  volatile u32 did_start_xy; /* 0x010044 eol/f did/xy reset val */
-  volatile u32 crs_start_xy; /* 0x010048 eol/f crs/xy reset val */
-  volatile u32 vc_start_xy;  /* 0x01004c eol/f vc/xy reset val */
-
-  char _pad1[ 0x020000 - 0x010050 ];
-
-  volatile u32 ovr_width_tile; /* 0x020000 overlay plane ctrl 0 */
-  volatile u32 ovr_inhwctrl;   /* 0x020004 overlay plane ctrl 1 */
-  volatile u32 ovr_control;    /* 0x020008 overlay plane ctrl 1 */
-
-  char _pad2[ 0x030000 - 0x02000C ];
-
-  volatile u32 frm_size_tile;  /* 0x030000 normal plane ctrl 0 */
-  volatile u32 frm_size_pixel; /* 0x030004 normal plane ctrl 1 */
-  volatile u32 frm_inhwctrl;   /* 0x030008 normal plane ctrl 2 */
-  volatile u32 frm_control;	   /* 0x03000C normal plane ctrl 3 */
-
-  char _pad3[ 0x040000 - 0x030010 ];
-
-  volatile u32 did_inhwctrl;   /* 0x040000 DID control */
-  volatile u32 did_control;    /* 0x040004 DID shadow */
-
-  char _pad4[ 0x048000 - 0x040008 ];
-
-  volatile u32 mode_regs[32];  /* 0x048000 - 0x04807c WID table */
-
-  char _pad5[ 0x050000 - 0x048080 ];
-
-  volatile u32 cmap[6144];     /* 0x050000 - 0x055ffc color map */
-
-  char _pad6[ 0x058000 - 0x056000 ];
-
-  volatile u32 cm_fifo;        /* 0x058000 color map fifo status */
-
-  char _pad7[ 0x060000 - 0x058004 ];
-
-  volatile u32 gmap[256];      /* 0x060000 - 0x0603fc gamma map */
-
-  char _pad8[ 0x068000 - 0x060400 ];
-
-  volatile u32 gmap10[1024];   /* 0x068000 - 0x068ffc gamma map */
-
-  char _pad9[ 0x070000 - 0x069000 ];
-
-  volatile u32 crs_pos;        /* 0x070000 cusror control 0 */
-  volatile u32 crs_ctl;        /* 0x070004 cusror control 1 */
-  volatile u32 crs_cmap[3];    /* 0x070008 - 0x070010 crs cmap */
-
-  char _pad10[ 0x078000 - 0x070014 ];
-
-  volatile u32 crs_glyph[64];  /* 0x078000 - 0x0780fc crs glyph */
-
-  char _pad11[ 0x080000 - 0x078100 ];
-
-  volatile u32 vc_0;           /* 0x080000 video capture crtl 0 */
-  volatile u32 vc_1;           /* 0x080004 video capture crtl 1 */
-  volatile u32 vc_2;           /* 0x080008 video capture crtl 2 */
-  volatile u32 vc_3;           /* 0x08000c video capture crtl 3 */
-  volatile u32 vc_4;           /* 0x080010 video capture crtl 3 */
-  volatile u32 vc_5;           /* 0x080014 video capture crtl 3 */
-  volatile u32 vc_6;           /* 0x080018 video capture crtl 3 */
-  volatile u32 vc_7;           /* 0x08001c video capture crtl 3 */
-  volatile u32 vc_8;           /* 0x08000c video capture crtl 3 */
-};
-
-/* Bit mask information */
-
-#define DBE_CTRLSTAT_CHIPID_MSB     3
-#define DBE_CTRLSTAT_CHIPID_LSB     0
-#define DBE_CTRLSTAT_SENSE_N_MSB    4
-#define DBE_CTRLSTAT_SENSE_N_LSB    4
-#define DBE_CTRLSTAT_PCLKSEL_MSB    29
-#define DBE_CTRLSTAT_PCLKSEL_LSB    28
-
-#define DBE_DOTCLK_M_MSB            7
-#define DBE_DOTCLK_M_LSB            0
-#define DBE_DOTCLK_N_MSB            13
-#define DBE_DOTCLK_N_LSB            8
-#define DBE_DOTCLK_P_MSB            15
-#define DBE_DOTCLK_P_LSB            14
-#define DBE_DOTCLK_RUN_MSB          20
-#define DBE_DOTCLK_RUN_LSB          20
-
-#define DBE_VT_XY_VT_FREEZE_MSB     31
-#define DBE_VT_XY_VT_FREEZE_LSB     31
-
-#define DBE_FP_VDRV_FP_VDRV_ON_MSB	23
-#define DBE_FP_VDRV_FP_VDRV_ON_LSB	12
-#define DBE_FP_VDRV_FP_VDRV_OFF_MSB	11
-#define DBE_FP_VDRV_FP_VDRV_OFF_LSB	0
-
-#define DBE_FP_HDRV_FP_HDRV_ON_MSB	23
-#define DBE_FP_HDRV_FP_HDRV_ON_LSB	12
-#define DBE_FP_HDRV_FP_HDRV_OFF_MSB	11
-#define DBE_FP_HDRV_FP_HDRV_OFF_LSB	0
-
-#define DBE_FP_DE_FP_DE_ON_MSB		23
-#define DBE_FP_DE_FP_DE_ON_LSB		12
-#define DBE_FP_DE_FP_DE_OFF_MSB		11
-#define DBE_FP_DE_FP_DE_OFF_LSB		0
-
-#define DBE_VT_VSYNC_VT_VSYNC_ON_MSB        23
-#define DBE_VT_VSYNC_VT_VSYNC_ON_LSB        12
-#define DBE_VT_VSYNC_VT_VSYNC_OFF_MSB       11
-#define DBE_VT_VSYNC_VT_VSYNC_OFF_LSB       0
-
-#define DBE_VT_HSYNC_VT_HSYNC_ON_MSB        23
-#define DBE_VT_HSYNC_VT_HSYNC_ON_LSB        12
-#define DBE_VT_HSYNC_VT_HSYNC_OFF_MSB       11
-#define DBE_VT_HSYNC_VT_HSYNC_OFF_LSB       0
-
-#define DBE_VT_VBLANK_VT_VBLANK_ON_MSB        23
-#define DBE_VT_VBLANK_VT_VBLANK_ON_LSB        12
-#define DBE_VT_VBLANK_VT_VBLANK_OFF_MSB       11
-#define DBE_VT_VBLANK_VT_VBLANK_OFF_LSB       0
-
-#define DBE_VT_HBLANK_VT_HBLANK_ON_MSB        23
-#define DBE_VT_HBLANK_VT_HBLANK_ON_LSB        12
-#define DBE_VT_HBLANK_VT_HBLANK_OFF_MSB       11
-#define DBE_VT_HBLANK_VT_HBLANK_OFF_LSB       0
-
-#define DBE_VT_FLAGS_VDRV_INVERT_MSB		0
-#define DBE_VT_FLAGS_VDRV_INVERT_LSB		0
-#define DBE_VT_FLAGS_HDRV_INVERT_MSB		2
-#define DBE_VT_FLAGS_HDRV_INVERT_LSB		2
-
-#define DBE_VT_VCMAP_VT_VCMAP_ON_MSB        23
-#define DBE_VT_VCMAP_VT_VCMAP_ON_LSB        12
-#define DBE_VT_VCMAP_VT_VCMAP_OFF_MSB       11
-#define DBE_VT_VCMAP_VT_VCMAP_OFF_LSB       0
-
-#define DBE_VT_HCMAP_VT_HCMAP_ON_MSB        23
-#define DBE_VT_HCMAP_VT_HCMAP_ON_LSB        12
-#define DBE_VT_HCMAP_VT_HCMAP_OFF_MSB       11
-#define DBE_VT_HCMAP_VT_HCMAP_OFF_LSB       0
-
-#define DBE_VT_XYMAX_VT_MAXX_MSB    11
-#define DBE_VT_XYMAX_VT_MAXX_LSB    0
-#define DBE_VT_XYMAX_VT_MAXY_MSB    23
-#define DBE_VT_XYMAX_VT_MAXY_LSB    12
-
-#define DBE_VT_HPIXEN_VT_HPIXEN_ON_MSB      23
-#define DBE_VT_HPIXEN_VT_HPIXEN_ON_LSB      12
-#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_MSB     11
-#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_LSB     0
-
-#define DBE_VT_VPIXEN_VT_VPIXEN_ON_MSB      23
-#define DBE_VT_VPIXEN_VT_VPIXEN_ON_LSB      12
-#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_MSB     11
-#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_LSB     0
-
-#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_MSB  0
-#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_LSB  0
-
-#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_MSB 0
-#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_LSB 0
-
-#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_MSB       13
-#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_LSB       13
-
-#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_MSB  0
-#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_LSB  0
-#define DBE_FRM_CONTROL_FRM_TILE_PTR_MSB    31
-#define DBE_FRM_CONTROL_FRM_TILE_PTR_LSB    9
-#define DBE_FRM_CONTROL_FRM_LINEAR_MSB      1
-#define DBE_FRM_CONTROL_FRM_LINEAR_LSB      1
-
-#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_MSB 0
-#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_LSB 0
-
-#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_MSB        12
-#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_LSB        5
-#define DBE_FRM_SIZE_TILE_FRM_RHS_MSB       4
-#define DBE_FRM_SIZE_TILE_FRM_RHS_LSB       0
-#define DBE_FRM_SIZE_TILE_FRM_DEPTH_MSB     14
-#define DBE_FRM_SIZE_TILE_FRM_DEPTH_LSB     13
-#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_MSB        15
-#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_LSB        15
-
-#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_MSB        31
-#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_LSB        16
-
-#define DBE_DID_CONTROL_DID_DMA_ENABLE_MSB  0
-#define DBE_DID_CONTROL_DID_DMA_ENABLE_LSB  0
-#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_MSB 0
-#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_LSB 0
-
-#define DBE_DID_START_XY_DID_STARTY_MSB     23
-#define DBE_DID_START_XY_DID_STARTY_LSB     12
-#define DBE_DID_START_XY_DID_STARTX_MSB     11
-#define DBE_DID_START_XY_DID_STARTX_LSB     0
-
-#define DBE_CRS_START_XY_CRS_STARTY_MSB     23
-#define DBE_CRS_START_XY_CRS_STARTY_LSB     12
-#define DBE_CRS_START_XY_CRS_STARTX_MSB     11
-#define DBE_CRS_START_XY_CRS_STARTX_LSB     0
-
-#define DBE_WID_TYP_MSB     4
-#define DBE_WID_TYP_LSB     2
-#define DBE_WID_BUF_MSB     1
-#define DBE_WID_BUF_LSB     0
-
-#define DBE_VC_START_XY_VC_STARTY_MSB       23
-#define DBE_VC_START_XY_VC_STARTY_LSB       12
-#define DBE_VC_START_XY_VC_STARTX_MSB       11
-#define DBE_VC_START_XY_VC_STARTX_LSB       0
-
-/* Constants */
-
-#define DBE_FRM_DEPTH_8     0
-#define DBE_FRM_DEPTH_16    1
-#define DBE_FRM_DEPTH_32    2
-
-#define DBE_CMODE_I8        0
-#define DBE_CMODE_I12       1
-#define DBE_CMODE_RG3B2     2
-#define DBE_CMODE_RGB4      3
-#define DBE_CMODE_ARGB5     4
-#define DBE_CMODE_RGB8      5
-#define DBE_CMODE_RGBA5     6
-#define DBE_CMODE_RGB10     7
-
-#define DBE_BMODE_BOTH      3
-
-#define DBE_CRS_MAGIC       54
-
-#define DBE_CLOCK_REF_KHZ	27000
-
-/* Config Register (DBE Only) Definitions */
-
-#define DBE_CONFIG_VDAC_ENABLE       0x00000001
-#define DBE_CONFIG_VDAC_GSYNC        0x00000002
-#define DBE_CONFIG_VDAC_PBLANK       0x00000004
-#define DBE_CONFIG_FPENABLE          0x00000008
-#define DBE_CONFIG_LENDIAN           0x00000020
-#define DBE_CONFIG_TILEHIST          0x00000040
-#define DBE_CONFIG_EXT_ADDR          0x00000080
-
-#define DBE_CONFIG_FBDEV        ( DBE_CONFIG_VDAC_ENABLE | \
-                                      DBE_CONFIG_VDAC_GSYNC  | \
-                                      DBE_CONFIG_VDAC_PBLANK | \
-                                      DBE_CONFIG_LENDIAN     | \
-                                      DBE_CONFIG_EXT_ADDR )
-
-/*
- * Available Video Timings and Corresponding Indices
- */
-
-typedef enum {
-  DBE_VT_640_480_60,
-
-  DBE_VT_800_600_60,
-  DBE_VT_800_600_75,
-  DBE_VT_800_600_120,
-
-  DBE_VT_1024_768_50,
-  DBE_VT_1024_768_60,
-  DBE_VT_1024_768_75,
-  DBE_VT_1024_768_85,
-  DBE_VT_1024_768_120,
-
-  DBE_VT_1280_1024_50,
-  DBE_VT_1280_1024_60,
-  DBE_VT_1280_1024_75,
-  DBE_VT_1280_1024_85,
-
-  DBE_VT_1600_1024_53,
-  DBE_VT_1600_1024_60,
-
-  DBE_VT_1600_1200_50,
-  DBE_VT_1600_1200_60,
-  DBE_VT_1600_1200_75,
-
-  DBE_VT_1920_1080_50,
-  DBE_VT_1920_1080_60,
-  DBE_VT_1920_1080_72,
-
-  DBE_VT_1920_1200_50,
-  DBE_VT_1920_1200_60,
-  DBE_VT_1920_1200_66,
-
-  DBE_VT_UNKNOWN
-} dbe_timing_t;
-
-
-
-/*
- * Crime Video Timing Data Structure
- */
-
-struct dbe_timing_info
-{
-  dbe_timing_t type;
-  int flags;
-  short width;		    /* Monitor resolution		*/
-  short height;
-  int fields_sec;	    /* fields/sec  (Hz -3 dec. places */
-  int cfreq;		    /* pixel clock frequency (MHz -3 dec. places) */
-  short htotal;		    /* Horizontal total pixels	*/
-  short hblank_start;	    /* Horizontal blank start	*/
-  short hblank_end;	    /* Horizontal blank end		*/
-  short hsync_start;	    /* Horizontal sync start	*/
-  short hsync_end;	    /* Horizontal sync end		*/
-  short vtotal;		    /* Vertical total lines		*/
-  short vblank_start;	    /* Vertical blank start		*/
-  short vblank_end;	    /* Vertical blank end		*/
-  short vsync_start;	    /* Vertical sync start		*/
-  short vsync_end;	    /* Vertical sync end		*/
-  short pll_m;		    /* PLL M parameter		*/
-  short pll_n;		    /* PLL P parameter		*/
-  short pll_p;		    /* PLL N parameter		*/
-};
-
-/* Defines for dbe_vof_info_t flags */
-
-#define DBE_VOF_UNKNOWNMON    1
-#define DBE_VOF_STEREO        2
-#define DBE_VOF_DO_GENSYNC    4          /* enable incoming sync */
-#define DBE_VOF_SYNC_ON_GREEN 8          /* sync on green */
-#define DBE_VOF_FLATPANEL     0x1000     /* FLATPANEL Timing */
-#define DBE_VOF_MAGICKEY      0x2000     /* Backdoor key */
-
-/*
- * DBE Timing Tables
- */
-
-#ifdef INCLUDE_TIMING_TABLE_DATA
-struct dbe_timing_info dbeVTimings[] = {
-  {
-    DBE_VT_640_480_60,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	        640,			480,		59940,			25175,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    800,	640,		        800,		656,		752,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    525,	480,		        525,		490,		    492,
-    /*	pll_m,	pll_n,			pll_p */
-    15,	    2,				3
-  },
-
-  {
-    DBE_VT_800_600_60,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    800,			600,		60317,			40000,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1056,	800,		    1056,		840,		    968,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    628,	600,		    628,		601,		    605,
-    /*	pll_m,	pll_n,			pll_p */
-    3,	    1,				1
-  },
-
-  {
-    DBE_VT_800_600_75,
-    /*	flags,	width,		    height,		fields_sec,	    cfreq */
-    0,	    800,		    600,		75000,		    49500,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1056,	800,		    1056,		816,		    896,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    625,	600,		    625,		601,		    604,
-    /*	pll_m,	pll_n,		    pll_p */
-    11,	    3,		        1
-  },
-
-  {
-    DBE_VT_800_600_120,
-    /*	flags,					width,		height,			fields_sec,	    cfreq */
-    DBE_VOF_STEREO,	    800,		600,			119800,		    82978,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1040,	800,		    1040,		856,		    976,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    666,	600,		    666,		637,		    643,
-    /*	pll_m,	pll_n,		    pll_p */
-    31,	    5,		        1
-  },
-
-  {
-    DBE_VT_1024_768_50,
-    /*	flags,	width,		    height,		fields_sec,	    cfreq */
-    0,	    1024,		    768,		50000,		    54163,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1344,	1024,		    1344,		1048,		    1184,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    806,	768,		    806,		771,		    777,
-    /*	pll_m,	pll_n,		    pll_p */
-    4,	    1,		        1
-  },
-
-  {
-    DBE_VT_1024_768_60,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1024,			768,		60004,			65000,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1344,	1024,		    1344,		1048,		    1184,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    806,	768,		    806,		771,		    777,
-    /*	pll_m,	pll_n,			pll_p */
-    12,	    5,				0
-  },
-
-  {
-    DBE_VT_1024_768_75,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1024,			768,		75029,			78750,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1312,	1024,		    1312,		1040,		    1136,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    800,	768,		    800,		769,		    772,
-    /*	pll_m,	pll_n,			pll_p */
-    29,	    5,				1
-  },
-
-  {
-    DBE_VT_1024_768_85,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1024,			768,		84997,			94500,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1376,	1024,		    1376,		1072,		    1168,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    808,	768,		    808,		769,		    772,
-    /*	pll_m,	pll_n,			pll_p */
-    7,	    2,				0
-  },
-
-  {
-    DBE_VT_1024_768_120,
-    /*	flags,					width,		height,			fields_sec,		cfreq */
-    DBE_VOF_STEREO,	    1024,		768,			119800,			133195,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1376,	1024,		    1376,		1072,		    1168,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    808,	768,		    808,		769,		    772,
-    /*	pll_m,	pll_n,			pll_p */
-    5,	    1,				0
-  },
-
-  {
-    DBE_VT_1280_1024_50,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1280,			1024,		50000,			89460,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1680,	1280,		    1680,		1360,		    1480,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    1065,	1024,		    1065,		1027,		    1030,
-    /*	pll_m,	pll_n,			pll_p */
-    10,	    3,				0
-  },
-
-  {
-    DBE_VT_1280_1024_60,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1280,			1024,		60020,			108000,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1688,	1280,		    1688,		1328,		    1440,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    1066,	1024,		    1066,		1025,		    1028,
-    /*	pll_m,	pll_n,			pll_p */
-    4,	    1,			    0
-  },
-
-  {
-    DBE_VT_1280_1024_75,
-    /*	flags,	width,			height,		fields_sec,		cfreq */
-    0,	    1280,			1024,		75025,			135000,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1688,	1280,		    1688,		1296,		    1440,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    1066,	1024,		    1066,		1025,		    1028,
-    /*	pll_m,	pll_n,			pll_p */
-    5,	    1,				0
-  },
-
-  {
-    DBE_VT_1280_1024_85,
-    /*	flags,	width,		    height,		fields_sec,	    cfreq */
-    0,	    1280,		    1024,		85024,		    157500,
-    /*	htotal,	hblank_start,	hblank_end,	hsync_start,	hsync_end */
-    1728,	1280,		    1728,		1344,		    1504,
-    /*	vtotal,	vblank_start,	vblank_end,	vsync_start,	vsync_end */
-    1072,	1024,		    1072,		1025,		    1028,
-    /*	pll_m,	pll_n,		    pll_p */
-    29,	    5,		        0
-  },
-
-  {
-    DBE_VT_1600_1024_53,
-    /* flags,	width,			height,		fields_sec,     cfreq */
-    DBE_VOF_FLATPANEL | DBE_VOF_MAGICKEY,
-    1600,			1024,		53000,			107447,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    1900,   1600,           1900,           1630,           1730,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1067,   1024,           1067,           1027,           1030,
-    /* pll_m,  pll_n,          pll_p */
-    4,      1,              0
-  },
-
-  {
-    DBE_VT_1600_1024_60,
-    /* flags,					width,          height,			fields_sec,     cfreq */
-    DBE_VOF_FLATPANEL,   1600,           1024,			60000,          106913,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    1670,   1600,           1670,           1630,           1650,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1067,   1024,           1067,           1027,           1030,
-    /* pll_m,  pll_n,          pll_p */
-    4,      1,              0
-  },
-
-  {
-    DBE_VT_1600_1200_50,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1600,           1200,           50000,          130500,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2088,   1600,           2088,           1644,           1764,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1205,           1211,
-    /* pll_m,  pll_n,          pll_p */
-    24,     5,              0
-  },
-
-  {
-    DBE_VT_1600_1200_60,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1600,           1200,           59940,          162000,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2160,   1600,           2160,           1644,           1856,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1201,           1204,
-    /* pll_m,  pll_n,          pll_p */
-    6,		1,              0
-  },
-
-  {
-    DBE_VT_1600_1200_75,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1600,           1200,           75000,          202500,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2160,   1600,           2160,           1644,           1856,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1201,           1204,
-    /* pll_m,  pll_n,          pll_p */
-    15,		2,              0
-  },
-
-  {
-    DBE_VT_1920_1080_50,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1080,           50000,          133200,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2368,   1920,           2368,           1952,           2096,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1125,   1080,           1125,           1083,           1086,
-    /* pll_m,  pll_n,          pll_p */
-    5,      1,              0
-  },
-
-  {
-    DBE_VT_1920_1080_60,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1080,           59940,          159840,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2368,   1920,           2368,           1952,           2096,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1125,   1080,           1125,           1083,           1086,
-    /* pll_m,  pll_n,          pll_p */
-    6,      1,              0
-  },
-
-  {
-    DBE_VT_1920_1080_72,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1080,           72000,          216023,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2560,   1920,           2560,           1968,           2184,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1172,   1080,           1172,           1083,           1086,
-    /* pll_m,  pll_n,          pll_p */
-    8,      1,              0
-  },
-
-  {
-    DBE_VT_1920_1200_50,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1200,           50000,          161500,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2584,   1920,           2584,           1984,           2240,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1203,           1206,
-    /* pll_m,  pll_n,          pll_p */
-    6,      1,              0
-  },
-
-  {
-    DBE_VT_1920_1200_60,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1200,           59940,          193800,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2584,   1920,           2584,           1984,           2240,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1203,           1206,
-    /* pll_m,  pll_n,          pll_p */
-    29,     4,              0
-  },
-
-  {
-    DBE_VT_1920_1200_66,
-    /* flags,  width,          height,         fields_sec,     cfreq */
-    0,      1920,           1200,           66000,          213180,
-    /* htotal, hblank_start,   hblank_end,     hsync_start,    hsync_end */
-    2584,   1920,           2584,           1984,           2240,
-    /* vtotal, vblank_start,   vblank_end,     vsync_start,    vsync_end */
-    1250,   1200,           1250,           1203,           1206,
-    /* pll_m,  pll_n,          pll_p */
-    8,      1,              0
-  }
-};
-
-#endif // INCLUDE_TIMING_TABLE_DATA
-
-#endif // ! __SGIVWFB_H__
diff --git a/include/xen/events.h b/include/xen/events.h
index c9c85cf84895..fd7c587d0206 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -52,7 +52,6 @@ int evtchn_get(unsigned int evtchn);
 void evtchn_put(unsigned int evtchn);
 
 void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
-int resend_irq_on_evtchn(unsigned int irq);
 void rebind_evtchn_irq(int evtchn, int irq);
 
 static inline void notify_remote_via_evtchn(int port)
@@ -102,7 +101,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
 int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
 /* Bind an PSI pirq to an irq. */
 int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
-			     int pirq, const char *name, domid_t domid);
+			     int pirq, int nvec, const char *name, domid_t domid);
 #endif
 
 /* De-allocates the above mentioned physical interrupt. */
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index 42721d13a106..610dba9b620a 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -131,6 +131,7 @@ struct physdev_irq {
 #define MAP_PIRQ_TYPE_GSI		0x1
 #define MAP_PIRQ_TYPE_UNKNOWN		0x2
 #define MAP_PIRQ_TYPE_MSI_SEG		0x3
+#define MAP_PIRQ_TYPE_MULTI_MSI		0x4
 
 #define PHYSDEVOP_map_pirq		13
 struct physdev_map_pirq {
@@ -141,11 +142,16 @@ struct physdev_map_pirq {
     int index;
     /* IN or OUT */
     int pirq;
-    /* IN - high 16 bits hold segment for MAP_PIRQ_TYPE_MSI_SEG */
+    /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */
     int bus;
     /* IN */
     int devfn;
-    /* IN */
+    /* IN
+     * - For MSI-X contains entry number.
+     * - For MSI with ..._MULTI_MSI contains number of vectors.
+     * OUT (..._MULTI_MSI only)
+     * - Number of vectors allocated.
+     */
     int entry_nr;
     /* IN */
     uint64_t table_base;
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index fb2ea8f26552..6d8c042fee8a 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -35,4 +35,31 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 			       int numpgs, struct page **pages);
 
 bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
+
+#ifdef CONFIG_PREEMPT
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+}
+
+#else
+
+DECLARE_PER_CPU(bool, xen_in_preemptible_hcall);
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, true);
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, false);
+}
+
+#endif /* CONFIG_PREEMPT */
+
 #endif /* INCLUDE_XEN_OPS_H */
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index 569c07f2e344..0324c6d340c1 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -207,7 +207,6 @@ int xenbus_unmap_ring(struct xenbus_device *dev,
 		      grant_handle_t handle, void *vaddr);
 
 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
-int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port);
 int xenbus_free_evtchn(struct xenbus_device *dev, int port);
 
 enum xenbus_state xenbus_read_driver_state(const char *path);
diff --git a/init/Kconfig b/init/Kconfig
index 009a797dd242..427ba60d638f 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -273,6 +273,16 @@ config FHANDLE
 	  get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2)
 	  syscalls.
 
+config USELIB
+	bool "uselib syscall"
+	default y
+	help
+	  This option enables the uselib syscall, a system call used in the
+	  dynamic linker from libc5 and earlier.  glibc does not use this
+	  system call.  If you intend to run programs built on libc5 or
+	  earlier, you may need to enable this syscall.  Current systems
+	  running glibc can safely disable this.
+
 config AUDIT
 	bool "Auditing support"
 	depends on NET
@@ -854,6 +864,7 @@ config NUMA_BALANCING
 
 menuconfig CGROUPS
 	boolean "Control Group support"
+	select KERNFS
 	help
 	  This option adds support for grouping sets of processes together, for
 	  use with process control subsystems such as Cpusets, CFS, memory
@@ -1290,6 +1301,16 @@ config UID16
 	help
 	  This enables the legacy 16-bit UID syscall wrappers.
 
+config SYSFS_SYSCALL
+	bool "Sysfs syscall support" if EXPERT
+	default y
+	---help---
+	  sys_sysfs is an obsolete system call no longer supported in libc.
+	  Note that disabling this option is more secure but might break
+	  compatibility with some systems.
+
+	  If unsure say Y here.
+
 config SYSCTL_SYSCALL
 	bool "Sysctl syscall support" if EXPERT
 	depends on PROC_SYSCTL
@@ -1387,6 +1408,13 @@ config FUTEX
 	  support for "fast userspace mutexes".  The resulting kernel may not
 	  run glibc-based applications correctly.
 
+config HAVE_FUTEX_CMPXCHG
+	bool
+	help
+	  Architectures should select this if futex_atomic_cmpxchg_inatomic()
+	  is implemented and always working. This removes a couple of runtime
+	  checks.
+
 config EPOLL
 	bool "Enable eventpoll support" if EXPERT
 	default y
@@ -1455,6 +1483,7 @@ config PCI_QUIRKS
 
 config EMBEDDED
 	bool "Embedded system"
+	option allnoconfig_y
 	select EXPERT
 	help
 	  This option should be enabled if compiling the kernel for
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 8e5addc45874..82f22885c87e 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -102,13 +102,13 @@ no_match:
 
 /**
  * devt_from_partuuid - looks up the dev_t of a partition by its UUID
- * @uuid:	char array containing ascii UUID
+ * @uuid_str:	char array containing ascii UUID
  *
  * The function will return the first partition which contains a matching
  * UUID value in its partition_meta_info struct.  This does not search
  * by filesystem UUIDs.
  *
- * If @uuid is followed by a "/PARTNROFF=%d", then the number will be
+ * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be
  * extracted and used as an offset from the partition identified by the UUID.
  *
  * Returns the matching dev_t on success or 0 on failure.
diff --git a/init/initramfs.c b/init/initramfs.c
index 93b61396756b..a8497fab1c3d 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -455,6 +455,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len)
 		}
 		this_header = 0;
 		decompress = decompress_method(buf, len, &compress_name);
+		pr_debug("Detected %s compressed data\n", compress_name);
 		if (decompress) {
 			res = decompress(buf, len, NULL, flush_buffer, NULL,
 				   &my_inptr, error);
diff --git a/ipc/compat.c b/ipc/compat.c
index f486b0096a67..8e27104a39f5 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -113,9 +113,6 @@ struct compat_shm_info {
 	compat_ulong_t swap_attempts, swap_successes;
 };
 
-extern int sem_ctls[];
-#define sc_semopm	(sem_ctls[2])
-
 static inline int compat_ipc_parse_version(int *cmd)
 {
 #ifdef	CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
@@ -752,14 +749,8 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
 		unsigned nsops, const struct compat_timespec __user *timeout)
 {
-	struct timespec __user *ts64 = NULL;
-	if (timeout) {
-		struct timespec ts;
-		ts64 = compat_alloc_user_space(sizeof(*ts64));
-		if (get_compat_timespec(&ts, timeout))
-			return -EFAULT;
-		if (copy_to_user(ts64, &ts, sizeof(ts)))
-			return -EFAULT;
-	}
+	struct timespec __user *ts64;
+	if (compat_convert_timespec(&ts64, timeout))
+		return -EFAULT;
 	return sys_semtimedop(semid, tsems, nsops, ts64);
 }
diff --git a/ipc/compat_mq.c b/ipc/compat_mq.c
index 63d7c6de335b..a9cf16378d7a 100644
--- a/ipc/compat_mq.c
+++ b/ipc/compat_mq.c
@@ -64,20 +64,6 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name,
 	return sys_mq_open(u_name, oflag, mode, p);
 }
 
-static int compat_prepare_timeout(struct timespec __user **p,
-				  const struct compat_timespec __user *u)
-{
-	struct timespec ts;
-	if (!u) {
-		*p = NULL;
-		return 0;
-	}
-	*p = compat_alloc_user_space(sizeof(ts));
-	if (get_compat_timespec(&ts, u) || copy_to_user(*p, &ts, sizeof(ts)))
-		return -EFAULT;
-	return 0;
-}
-
 asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
 			const char __user *u_msg_ptr,
 			size_t msg_len, unsigned int msg_prio,
@@ -85,7 +71,7 @@ asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
 {
 	struct timespec __user *u_ts;
 
-	if (compat_prepare_timeout(&u_ts, u_abs_timeout))
+	if (compat_convert_timespec(&u_ts, u_abs_timeout))
 		return -EFAULT;
 
 	return sys_mq_timedsend(mqdes, u_msg_ptr, msg_len,
@@ -98,7 +84,8 @@ asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
 			const struct compat_timespec __user *u_abs_timeout)
 {
 	struct timespec __user *u_ts;
-	if (compat_prepare_timeout(&u_ts, u_abs_timeout))
+
+	if (compat_convert_timespec(&u_ts, u_abs_timeout))
 		return -EFAULT;
 
 	return sys_mq_timedreceive(mqdes, u_msg_ptr, msg_len,
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 17028648cfeb..998d31b230f1 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -281,4 +281,4 @@ static int __init ipc_sysctl_init(void)
 	return 0;
 }
 
-__initcall(ipc_sysctl_init);
+device_initcall(ipc_sysctl_init);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c3b31179122c..4fcf39af1776 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1459,4 +1459,4 @@ out_sysctl:
 	return error;
 }
 
-__initcall(init_mqueue_fs);
+device_initcall(init_mqueue_fs);
diff --git a/ipc/util.c b/ipc/util.c
index e1b4c6db8aa0..2eb0d1eaa312 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -128,7 +128,7 @@ static int __init ipc_init(void)
 	register_ipcns_notifier(&init_ipc_ns);
 	return 0;
 }
-__initcall(ipc_init);
+device_initcall(ipc_init);
 
 /**
  * ipc_init_ids	- initialise ipc identifiers
diff --git a/kernel/Makefile b/kernel/Makefile
index bc010ee272b6..f2a8b6246ce9 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -18,11 +18,13 @@ CFLAGS_REMOVE_cgroup-debug.o = -pg
 CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
+# cond_syscall is currently not LTO compatible
+CFLAGS_sys_ni.o = $(DISABLE_LTO)
+
 obj-y += sched/
 obj-y += locking/
 obj-y += power/
 obj-y += printk/
-obj-y += cpu/
 obj-y += irq/
 obj-y += rcu/
 
@@ -93,6 +95,7 @@ obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
+obj-$(CONFIG_TORTURE_TEST) += torture.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
diff --git a/kernel/audit.c b/kernel/audit.c
index 34c5a2310fbf..71fb41f393d7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -182,7 +182,7 @@ struct audit_buffer {
 
 struct audit_reply {
 	__u32 portid;
-	pid_t pid;
+	struct net *net;
 	struct sk_buff *skb;
 };
 
@@ -500,7 +500,7 @@ int audit_send_list(void *_dest)
 {
 	struct audit_netlink_list *dest = _dest;
 	struct sk_buff *skb;
-	struct net *net = get_net_ns_by_pid(dest->pid);
+	struct net *net = dest->net;
 	struct audit_net *aunet = net_generic(net, audit_net_id);
 
 	/* wait for parent to finish and send an ACK */
@@ -510,6 +510,7 @@ int audit_send_list(void *_dest)
 	while ((skb = __skb_dequeue(&dest->q)) != NULL)
 		netlink_unicast(aunet->nlsk, skb, dest->portid, 0);
 
+	put_net(net);
 	kfree(dest);
 
 	return 0;
@@ -543,7 +544,7 @@ out_kfree_skb:
 static int audit_send_reply_thread(void *arg)
 {
 	struct audit_reply *reply = (struct audit_reply *)arg;
-	struct net *net = get_net_ns_by_pid(reply->pid);
+	struct net *net = reply->net;
 	struct audit_net *aunet = net_generic(net, audit_net_id);
 
 	mutex_lock(&audit_cmd_mutex);
@@ -552,6 +553,7 @@ static int audit_send_reply_thread(void *arg)
 	/* Ignore failure. It'll only happen if the sender goes away,
 	   because our timeout is set to infinite. */
 	netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0);
+	put_net(net);
 	kfree(reply);
 	return 0;
 }
@@ -583,8 +585,8 @@ static void audit_send_reply(__u32 portid, int seq, int type, int done,
 	if (!skb)
 		goto out;
 
+	reply->net = get_net(current->nsproxy->net_ns);
 	reply->portid = portid;
-	reply->pid = task_pid_vnr(current);
 	reply->skb = skb;
 
 	tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
diff --git a/kernel/audit.h b/kernel/audit.h
index 57cc64d67718..8df132214606 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -247,7 +247,7 @@ extern void		    audit_panic(const char *message);
 
 struct audit_netlink_list {
 	__u32 portid;
-	pid_t pid;
+	struct net *net;
 	struct sk_buff_head q;
 };
 
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 14a78cca384e..a5e3d73d73e4 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <net/net_namespace.h>
 #include "audit.h"
 
 /*
@@ -1083,8 +1084,8 @@ int audit_list_rules_send(__u32 portid, int seq)
 	dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
 	if (!dest)
 		return -ENOMEM;
+	dest->net = get_net(current->nsproxy->net_ns);
 	dest->portid = portid;
-	dest->pid = task_pid_vnr(current);
 	skb_queue_head_init(&dest->q);
 
 	mutex_lock(&audit_filter_mutex);
diff --git a/kernel/capability.c b/kernel/capability.c
index 34019c57888d..a8d63df0c322 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -7,6 +7,8 @@
  * 30 May 2002:	Cleanup, Robert M. Love <rml@tech9.net>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/audit.h>
 #include <linux/capability.h>
 #include <linux/mm.h>
@@ -42,15 +44,10 @@ __setup("no_file_caps", file_caps_disable);
 
 static void warn_legacy_capability_use(void)
 {
-	static int warned;
-	if (!warned) {
-		char name[sizeof(current->comm)];
-
-		printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
-		       " (legacy support in use)\n",
-		       get_task_comm(name, current));
-		warned = 1;
-	}
+	char name[sizeof(current->comm)];
+
+	pr_info_once("warning: `%s' uses 32-bit capabilities (legacy support in use)\n",
+		     get_task_comm(name, current));
 }
 
 /*
@@ -71,16 +68,10 @@ static void warn_legacy_capability_use(void)
 
 static void warn_deprecated_v2(void)
 {
-	static int warned;
+	char name[sizeof(current->comm)];
 
-	if (!warned) {
-		char name[sizeof(current->comm)];
-
-		printk(KERN_INFO "warning: `%s' uses deprecated v2"
-		       " capabilities in a way that may be insecure.\n",
-		       get_task_comm(name, current));
-		warned = 1;
-	}
+	pr_info_once("warning: `%s' uses deprecated v2 capabilities in a way that may be insecure\n",
+		     get_task_comm(name, current));
 }
 
 /*
@@ -380,7 +371,7 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
 bool ns_capable(struct user_namespace *ns, int cap)
 {
 	if (unlikely(!cap_valid(cap))) {
-		printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
+		pr_crit("capable() called with invalid cap=%u\n", cap);
 		BUG();
 	}
 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 105f273b6f86..8f4ddbe23d58 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -40,23 +40,20 @@
 #include <linux/proc_fs.h>
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
-#include <linux/backing-dev.h>
 #include <linux/slab.h>
-#include <linux/magic.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 #include <linux/string.h>
 #include <linux/sort.h>
 #include <linux/kmod.h>
-#include <linux/module.h>
 #include <linux/delayacct.h>
 #include <linux/cgroupstats.h>
 #include <linux/hashtable.h>
-#include <linux/namei.h>
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
-#include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 #include <linux/atomic.h>
 
@@ -68,43 +65,49 @@
  */
 #define CGROUP_PIDLIST_DESTROY_DELAY	HZ
 
+#define CGROUP_FILE_NAME_MAX		(MAX_CGROUP_TYPE_NAMELEN +	\
+					 MAX_CFTYPE_NAME + 2)
+
+/*
+ * cgroup_tree_mutex nests above cgroup_mutex and protects cftypes, file
+ * creation/removal and hierarchy changing operations including cgroup
+ * creation, removal, css association and controller rebinding.  This outer
+ * lock is needed mainly to resolve the circular dependency between kernfs
+ * active ref and cgroup_mutex.  cgroup_tree_mutex nests above both.
+ */
+static DEFINE_MUTEX(cgroup_tree_mutex);
+
 /*
  * cgroup_mutex is the master lock.  Any modification to cgroup or its
  * hierarchy must be performed while holding it.
  *
- * cgroup_root_mutex nests inside cgroup_mutex and should be held to modify
- * cgroupfs_root of any cgroup hierarchy - subsys list, flags,
- * release_agent_path and so on.  Modifying requires both cgroup_mutex and
- * cgroup_root_mutex.  Readers can acquire either of the two.  This is to
- * break the following locking order cycle.
+ * css_set_rwsem protects task->cgroups pointer, the list of css_set
+ * objects, and the chain of tasks off each css_set.
  *
- *  A. cgroup_mutex -> cred_guard_mutex -> s_type->i_mutex_key -> namespace_sem
- *  B. namespace_sem -> cgroup_mutex
- *
- * B happens only through cgroup_show_options() and using cgroup_root_mutex
- * breaks it.
+ * These locks are exported if CONFIG_PROVE_RCU so that accessors in
+ * cgroup.h can use them for lockdep annotations.
  */
 #ifdef CONFIG_PROVE_RCU
 DEFINE_MUTEX(cgroup_mutex);
-EXPORT_SYMBOL_GPL(cgroup_mutex);	/* only for lockdep */
+DECLARE_RWSEM(css_set_rwsem);
+EXPORT_SYMBOL_GPL(cgroup_mutex);
+EXPORT_SYMBOL_GPL(css_set_rwsem);
 #else
 static DEFINE_MUTEX(cgroup_mutex);
+static DECLARE_RWSEM(css_set_rwsem);
 #endif
 
-static DEFINE_MUTEX(cgroup_root_mutex);
+/*
+ * Protects cgroup_subsys->release_agent_path.  Modifying it also requires
+ * cgroup_mutex.  Reading requires either cgroup_mutex or this spinlock.
+ */
+static DEFINE_SPINLOCK(release_agent_path_lock);
 
-#define cgroup_assert_mutex_or_rcu_locked()				\
+#define cgroup_assert_mutexes_or_rcu_locked()				\
 	rcu_lockdep_assert(rcu_read_lock_held() ||			\
+			   lockdep_is_held(&cgroup_tree_mutex) ||	\
 			   lockdep_is_held(&cgroup_mutex),		\
-			   "cgroup_mutex or RCU read lock required");
-
-#ifdef CONFIG_LOCKDEP
-#define cgroup_assert_mutex_or_root_locked()				\
-	WARN_ON_ONCE(debug_locks && (!lockdep_is_held(&cgroup_mutex) &&	\
-				     !lockdep_is_held(&cgroup_root_mutex)))
-#else
-#define cgroup_assert_mutex_or_root_locked()	do { } while (0)
-#endif
+			   "cgroup_[tree_]mutex or RCU read lock required");
 
 /*
  * cgroup destruction makes heavy use of work items and there can be a lot
@@ -120,17 +123,19 @@ static struct workqueue_struct *cgroup_destroy_wq;
  */
 static struct workqueue_struct *cgroup_pidlist_destroy_wq;
 
-/*
- * Generate an array of cgroup subsystem pointers. At boot time, this is
- * populated with the built in subsystems, and modular subsystems are
- * registered after that. The mutable section of this array is protected by
- * cgroup_mutex.
- */
-#define SUBSYS(_x) [_x ## _subsys_id] = &_x ## _subsys,
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
-static struct cgroup_subsys *cgroup_subsys[CGROUP_SUBSYS_COUNT] = {
+/* generate an array of cgroup subsystem pointers */
+#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
+static struct cgroup_subsys *cgroup_subsys[] = {
+#include <linux/cgroup_subsys.h>
+};
+#undef SUBSYS
+
+/* array of cgroup subsystem names */
+#define SUBSYS(_x) [_x ## _cgrp_id] = #_x,
+static const char *cgroup_subsys_name[] = {
 #include <linux/cgroup_subsys.h>
 };
+#undef SUBSYS
 
 /*
  * The dummy hierarchy, reserved for the subsystems that are otherwise
@@ -147,15 +152,9 @@ static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup;
 static LIST_HEAD(cgroup_roots);
 static int cgroup_root_count;
 
-/*
- * Hierarchy ID allocation and mapping.  It follows the same exclusion
- * rules as other root ops - both cgroup_mutex and cgroup_root_mutex for
- * writes, either for reads.
- */
+/* hierarchy ID allocation and mapping, protected by cgroup_mutex */
 static DEFINE_IDR(cgroup_hierarchy_idr);
 
-static struct cgroup_name root_cgroup_name = { .name = "/" };
-
 /*
  * Assign a monotonically increasing serial number to cgroups.  It
  * guarantees cgroups with bigger numbers are newer than those with smaller
@@ -175,11 +174,13 @@ static int need_forkexit_callback __read_mostly;
 
 static struct cftype cgroup_base_files[];
 
+static void cgroup_put(struct cgroup *cgrp);
+static int rebind_subsystems(struct cgroupfs_root *root,
+			     unsigned long added_mask, unsigned removed_mask);
 static void cgroup_destroy_css_killed(struct cgroup *cgrp);
 static int cgroup_destroy_locked(struct cgroup *cgrp);
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
 			      bool is_add);
-static int cgroup_file_release(struct inode *inode, struct file *file);
 static void cgroup_pidlist_destroy_all(struct cgroup *cgrp);
 
 /**
@@ -197,8 +198,9 @@ static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
 					      struct cgroup_subsys *ss)
 {
 	if (ss)
-		return rcu_dereference_check(cgrp->subsys[ss->subsys_id],
-					     lockdep_is_held(&cgroup_mutex));
+		return rcu_dereference_check(cgrp->subsys[ss->id],
+					lockdep_is_held(&cgroup_tree_mutex) ||
+					lockdep_is_held(&cgroup_mutex));
 	else
 		return &cgrp->dummy_css;
 }
@@ -209,6 +211,27 @@ static inline bool cgroup_is_dead(const struct cgroup *cgrp)
 	return test_bit(CGRP_DEAD, &cgrp->flags);
 }
 
+struct cgroup_subsys_state *seq_css(struct seq_file *seq)
+{
+	struct kernfs_open_file *of = seq->private;
+	struct cgroup *cgrp = of->kn->parent->priv;
+	struct cftype *cft = seq_cft(seq);
+
+	/*
+	 * This is open and unprotected implementation of cgroup_css().
+	 * seq_css() is only called from a kernfs file operation which has
+	 * an active reference on the file.  Because all the subsystem
+	 * files are drained before a css is disassociated with a cgroup,
+	 * the matching css from the cgroup's subsys table is guaranteed to
+	 * be and stay valid until the enclosing operation is complete.
+	 */
+	if (cft->ss)
+		return rcu_dereference_raw(cgrp->subsys[cft->ss->id]);
+	else
+		return &cgrp->dummy_css;
+}
+EXPORT_SYMBOL_GPL(seq_css);
+
 /**
  * cgroup_is_descendant - test ancestry
  * @cgrp: the cgroup to be tested
@@ -227,7 +250,6 @@ bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor)
 	}
 	return false;
 }
-EXPORT_SYMBOL_GPL(cgroup_is_descendant);
 
 static int cgroup_is_releasable(const struct cgroup *cgrp)
 {
@@ -254,54 +276,23 @@ static int notify_on_release(const struct cgroup *cgrp)
 	for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++)	\
 		if (!((css) = rcu_dereference_check(			\
 				(cgrp)->subsys[(ssid)],			\
+				lockdep_is_held(&cgroup_tree_mutex) ||	\
 				lockdep_is_held(&cgroup_mutex)))) { }	\
 		else
 
 /**
- * for_each_subsys - iterate all loaded cgroup subsystems
+ * for_each_subsys - iterate all enabled cgroup subsystems
  * @ss: the iteration cursor
  * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end
- *
- * Iterates through all loaded subsystems.  Should be called under
- * cgroup_mutex or cgroup_root_mutex.
  */
 #define for_each_subsys(ss, ssid)					\
-	for (({ cgroup_assert_mutex_or_root_locked(); (ssid) = 0; });	\
-	     (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++)			\
-		if (!((ss) = cgroup_subsys[(ssid)])) { }		\
-		else
-
-/**
- * for_each_builtin_subsys - iterate all built-in cgroup subsystems
- * @ss: the iteration cursor
- * @i: the index of @ss, CGROUP_BUILTIN_SUBSYS_COUNT after reaching the end
- *
- * Bulit-in subsystems are always present and iteration itself doesn't
- * require any synchronization.
- */
-#define for_each_builtin_subsys(ss, i)					\
-	for ((i) = 0; (i) < CGROUP_BUILTIN_SUBSYS_COUNT &&		\
-	     (((ss) = cgroup_subsys[i]) || true); (i)++)
+	for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT &&		\
+	     (((ss) = cgroup_subsys[ssid]) || true); (ssid)++)
 
 /* iterate across the active hierarchies */
 #define for_each_active_root(root)					\
 	list_for_each_entry((root), &cgroup_roots, root_list)
 
-static inline struct cgroup *__d_cgrp(struct dentry *dentry)
-{
-	return dentry->d_fsdata;
-}
-
-static inline struct cfent *__d_cfe(struct dentry *dentry)
-{
-	return dentry->d_fsdata;
-}
-
-static inline struct cftype *__d_cft(struct dentry *dentry)
-{
-	return __d_cfe(dentry)->type;
-}
-
 /**
  * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
  * @cgrp: the cgroup to be checked for liveness
@@ -356,13 +347,6 @@ struct cgrp_cset_link {
 
 static struct css_set init_css_set;
 static struct cgrp_cset_link init_cgrp_cset_link;
-
-/*
- * css_set_lock protects the list of css_set objects, and the chain of
- * tasks off each css_set.  Nests outside task->alloc_lock due to
- * css_task_iter_start().
- */
-static DEFINE_RWLOCK(css_set_lock);
 static int css_set_count;
 
 /*
@@ -386,30 +370,14 @@ static unsigned long css_set_hash(struct cgroup_subsys_state *css[])
 	return key;
 }
 
-/*
- * We don't maintain the lists running through each css_set to its task
- * until after the first call to css_task_iter_start().  This reduces the
- * fork()/exit() overhead for people who have cgroups compiled into their
- * kernel but not actually in use.
- */
-static int use_task_css_set_links __read_mostly;
-
-static void __put_css_set(struct css_set *cset, int taskexit)
+static void put_css_set_locked(struct css_set *cset, bool taskexit)
 {
 	struct cgrp_cset_link *link, *tmp_link;
 
-	/*
-	 * Ensure that the refcount doesn't hit zero while any readers
-	 * can see it. Similar to atomic_dec_and_lock(), but for an
-	 * rwlock
-	 */
-	if (atomic_add_unless(&cset->refcount, -1, 1))
-		return;
-	write_lock(&css_set_lock);
-	if (!atomic_dec_and_test(&cset->refcount)) {
-		write_unlock(&css_set_lock);
+	lockdep_assert_held(&css_set_rwsem);
+
+	if (!atomic_dec_and_test(&cset->refcount))
 		return;
-	}
 
 	/* This css_set is dead. unlink it and release cgroup refcounts */
 	hash_del(&cset->hlist);
@@ -421,7 +389,7 @@ static void __put_css_set(struct css_set *cset, int taskexit)
 		list_del(&link->cset_link);
 		list_del(&link->cgrp_link);
 
-		/* @cgrp can't go away while we're holding css_set_lock */
+		/* @cgrp can't go away while we're holding css_set_rwsem */
 		if (list_empty(&cgrp->cset_links) && notify_on_release(cgrp)) {
 			if (taskexit)
 				set_bit(CGRP_RELEASABLE, &cgrp->flags);
@@ -431,10 +399,24 @@ static void __put_css_set(struct css_set *cset, int taskexit)
 		kfree(link);
 	}
 
-	write_unlock(&css_set_lock);
 	kfree_rcu(cset, rcu_head);
 }
 
+static void put_css_set(struct css_set *cset, bool taskexit)
+{
+	/*
+	 * Ensure that the refcount doesn't hit zero while any readers
+	 * can see it. Similar to atomic_dec_and_lock(), but for an
+	 * rwlock
+	 */
+	if (atomic_add_unless(&cset->refcount, -1, 1))
+		return;
+
+	down_write(&css_set_rwsem);
+	put_css_set_locked(cset, taskexit);
+	up_write(&css_set_rwsem);
+}
+
 /*
  * refcounted get/put for css_set objects
  */
@@ -443,16 +425,6 @@ static inline void get_css_set(struct css_set *cset)
 	atomic_inc(&cset->refcount);
 }
 
-static inline void put_css_set(struct css_set *cset)
-{
-	__put_css_set(cset, 0);
-}
-
-static inline void put_css_set_taskexit(struct css_set *cset)
-{
-	__put_css_set(cset, 1);
-}
-
 /**
  * compare_css_sets - helper function for find_existing_css_set().
  * @cset: candidate css_set being tested
@@ -652,11 +624,11 @@ static struct css_set *find_css_set(struct css_set *old_cset,
 
 	/* First see if we already have a cgroup group that matches
 	 * the desired set */
-	read_lock(&css_set_lock);
+	down_read(&css_set_rwsem);
 	cset = find_existing_css_set(old_cset, cgrp, template);
 	if (cset)
 		get_css_set(cset);
-	read_unlock(&css_set_lock);
+	up_read(&css_set_rwsem);
 
 	if (cset)
 		return cset;
@@ -674,13 +646,16 @@ static struct css_set *find_css_set(struct css_set *old_cset,
 	atomic_set(&cset->refcount, 1);
 	INIT_LIST_HEAD(&cset->cgrp_links);
 	INIT_LIST_HEAD(&cset->tasks);
+	INIT_LIST_HEAD(&cset->mg_tasks);
+	INIT_LIST_HEAD(&cset->mg_preload_node);
+	INIT_LIST_HEAD(&cset->mg_node);
 	INIT_HLIST_NODE(&cset->hlist);
 
 	/* Copy the set of subsystem state objects generated in
 	 * find_existing_css_set() */
 	memcpy(cset->subsys, template, sizeof(cset->subsys));
 
-	write_lock(&css_set_lock);
+	down_write(&css_set_rwsem);
 	/* Add reference counts and links from the new css_set. */
 	list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) {
 		struct cgroup *c = link->cgrp;
@@ -698,29 +673,104 @@ static struct css_set *find_css_set(struct css_set *old_cset,
 	key = css_set_hash(cset->subsys);
 	hash_add(css_set_table, &cset->hlist, key);
 
-	write_unlock(&css_set_lock);
+	up_write(&css_set_rwsem);
 
 	return cset;
 }
 
-/*
- * Return the cgroup for "task" from the given hierarchy. Must be
- * called with cgroup_mutex held.
- */
-static struct cgroup *task_cgroup_from_root(struct task_struct *task,
-					    struct cgroupfs_root *root)
+static struct cgroupfs_root *cgroup_root_from_kf(struct kernfs_root *kf_root)
 {
-	struct css_set *cset;
-	struct cgroup *res = NULL;
+	struct cgroup *top_cgrp = kf_root->kn->priv;
+
+	return top_cgrp->root;
+}
+
+static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end)
+{
+	int id;
+
+	lockdep_assert_held(&cgroup_mutex);
+
+	id = idr_alloc_cyclic(&cgroup_hierarchy_idr, root, start, end,
+			      GFP_KERNEL);
+	if (id < 0)
+		return id;
+
+	root->hierarchy_id = id;
+	return 0;
+}
+
+static void cgroup_exit_root_id(struct cgroupfs_root *root)
+{
+	lockdep_assert_held(&cgroup_mutex);
+
+	if (root->hierarchy_id) {
+		idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id);
+		root->hierarchy_id = 0;
+	}
+}
+
+static void cgroup_free_root(struct cgroupfs_root *root)
+{
+	if (root) {
+		/* hierarhcy ID shoulid already have been released */
+		WARN_ON_ONCE(root->hierarchy_id);
+
+		idr_destroy(&root->cgroup_idr);
+		kfree(root);
+	}
+}
+
+static void cgroup_destroy_root(struct cgroupfs_root *root)
+{
+	struct cgroup *cgrp = &root->top_cgroup;
+	struct cgrp_cset_link *link, *tmp_link;
+
+	mutex_lock(&cgroup_tree_mutex);
+	mutex_lock(&cgroup_mutex);
+
+	BUG_ON(atomic_read(&root->nr_cgrps));
+	BUG_ON(!list_empty(&cgrp->children));
+
+	/* Rebind all subsystems back to the default hierarchy */
+	WARN_ON(rebind_subsystems(root, 0, root->subsys_mask));
 
-	BUG_ON(!mutex_is_locked(&cgroup_mutex));
-	read_lock(&css_set_lock);
 	/*
-	 * No need to lock the task - since we hold cgroup_mutex the
-	 * task can't change groups, so the only thing that can happen
-	 * is that it exits and its css is set back to init_css_set.
+	 * Release all the links from cset_links to this hierarchy's
+	 * root cgroup
 	 */
-	cset = task_css_set(task);
+	down_write(&css_set_rwsem);
+
+	list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
+		list_del(&link->cset_link);
+		list_del(&link->cgrp_link);
+		kfree(link);
+	}
+	up_write(&css_set_rwsem);
+
+	if (!list_empty(&root->root_list)) {
+		list_del(&root->root_list);
+		cgroup_root_count--;
+	}
+
+	cgroup_exit_root_id(root);
+
+	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
+
+	kernfs_destroy_root(root->kf_root);
+	cgroup_free_root(root);
+}
+
+/* look up cgroup associated with given css_set on the specified hierarchy */
+static struct cgroup *cset_cgroup_from_root(struct css_set *cset,
+					    struct cgroupfs_root *root)
+{
+	struct cgroup *res = NULL;
+
+	lockdep_assert_held(&cgroup_mutex);
+	lockdep_assert_held(&css_set_rwsem);
+
 	if (cset == &init_css_set) {
 		res = &root->top_cgroup;
 	} else {
@@ -735,16 +785,27 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
 			}
 		}
 	}
-	read_unlock(&css_set_lock);
+
 	BUG_ON(!res);
 	return res;
 }
 
 /*
- * There is one global cgroup mutex. We also require taking
- * task_lock() when dereferencing a task's cgroup subsys pointers.
- * See "The task_lock() exception", at the end of this comment.
- *
+ * Return the cgroup for "task" from the given hierarchy. Must be
+ * called with cgroup_mutex and css_set_rwsem held.
+ */
+static struct cgroup *task_cgroup_from_root(struct task_struct *task,
+					    struct cgroupfs_root *root)
+{
+	/*
+	 * No need to lock the task - since we hold cgroup_mutex the
+	 * task can't change groups, so the only thing that can happen
+	 * is that it exits and its css is set back to init_css_set.
+	 */
+	return cset_cgroup_from_root(task_css_set(task), root);
+}
+
+/*
  * A task must hold cgroup_mutex to modify cgroups.
  *
  * Any task can increment and decrement the count field without lock.
@@ -774,94 +835,75 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
  * always has either children cgroups and/or using tasks.  So we don't
  * need a special hack to ensure that top_cgroup cannot be deleted.
  *
- *	The task_lock() exception
- *
- * The need for this exception arises from the action of
- * cgroup_attach_task(), which overwrites one task's cgroup pointer with
- * another.  It does so using cgroup_mutex, however there are
- * several performance critical places that need to reference
- * task->cgroup without the expense of grabbing a system global
- * mutex.  Therefore except as noted below, when dereferencing or, as
- * in cgroup_attach_task(), modifying a task's cgroup pointer we use
- * task_lock(), which acts on a spinlock (task->alloc_lock) already in
- * the task_struct routinely used for such matters.
- *
  * P.S.  One more locking exception.  RCU is used to guard the
  * update of a tasks cgroup pointer by cgroup_attach_task()
  */
 
-/*
- * A couple of forward declarations required, due to cyclic reference loop:
- * cgroup_mkdir -> cgroup_create -> cgroup_populate_dir ->
- * cgroup_add_file -> cgroup_create_file -> cgroup_dir_inode_operations
- * -> cgroup_mkdir.
- */
-
-static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
-static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask);
-static const struct inode_operations cgroup_dir_inode_operations;
+static struct kernfs_syscall_ops cgroup_kf_syscall_ops;
 static const struct file_operations proc_cgroupstats_operations;
 
-static struct backing_dev_info cgroup_backing_dev_info = {
-	.name		= "cgroup",
-	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
-};
-
-static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)
+static char *cgroup_file_name(struct cgroup *cgrp, const struct cftype *cft,
+			      char *buf)
 {
-	struct inode *inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_ino = get_next_ino();
-		inode->i_mode = mode;
-		inode->i_uid = current_fsuid();
-		inode->i_gid = current_fsgid();
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
-	}
-	return inode;
+	if (cft->ss && !(cft->flags & CFTYPE_NO_PREFIX) &&
+	    !(cgrp->root->flags & CGRP_ROOT_NOPREFIX))
+		snprintf(buf, CGROUP_FILE_NAME_MAX, "%s.%s",
+			 cft->ss->name, cft->name);
+	else
+		strncpy(buf, cft->name, CGROUP_FILE_NAME_MAX);
+	return buf;
 }
 
-static struct cgroup_name *cgroup_alloc_name(struct dentry *dentry)
+/**
+ * cgroup_file_mode - deduce file mode of a control file
+ * @cft: the control file in question
+ *
+ * returns cft->mode if ->mode is not 0
+ * returns S_IRUGO|S_IWUSR if it has both a read and a write handler
+ * returns S_IRUGO if it has only a read handler
+ * returns S_IWUSR if it has only a write hander
+ */
+static umode_t cgroup_file_mode(const struct cftype *cft)
 {
-	struct cgroup_name *name;
+	umode_t mode = 0;
 
-	name = kmalloc(sizeof(*name) + dentry->d_name.len + 1, GFP_KERNEL);
-	if (!name)
-		return NULL;
-	strcpy(name->name, dentry->d_name.name);
-	return name;
+	if (cft->mode)
+		return cft->mode;
+
+	if (cft->read_u64 || cft->read_s64 || cft->seq_show)
+		mode |= S_IRUGO;
+
+	if (cft->write_u64 || cft->write_s64 || cft->write_string ||
+	    cft->trigger)
+		mode |= S_IWUSR;
+
+	return mode;
 }
 
 static void cgroup_free_fn(struct work_struct *work)
 {
 	struct cgroup *cgrp = container_of(work, struct cgroup, destroy_work);
 
-	mutex_lock(&cgroup_mutex);
-	cgrp->root->number_of_cgroups--;
-	mutex_unlock(&cgroup_mutex);
-
-	/*
-	 * We get a ref to the parent's dentry, and put the ref when
-	 * this cgroup is being freed, so it's guaranteed that the
-	 * parent won't be destroyed before its children.
-	 */
-	dput(cgrp->parent->dentry);
-
-	/*
-	 * Drop the active superblock reference that we took when we
-	 * created the cgroup. This will free cgrp->root, if we are
-	 * holding the last reference to @sb.
-	 */
-	deactivate_super(cgrp->root->sb);
-
+	atomic_dec(&cgrp->root->nr_cgrps);
 	cgroup_pidlist_destroy_all(cgrp);
 
-	simple_xattrs_free(&cgrp->xattrs);
-
-	kfree(rcu_dereference_raw(cgrp->name));
-	kfree(cgrp);
+	if (cgrp->parent) {
+		/*
+		 * We get a ref to the parent, and put the ref when this
+		 * cgroup is being freed, so it's guaranteed that the
+		 * parent won't be destroyed before its children.
+		 */
+		cgroup_put(cgrp->parent);
+		kernfs_put(cgrp->kn);
+		kfree(cgrp);
+	} else {
+		/*
+		 * This is top cgroup's refcnt reaching zero, which
+		 * indicates that the root should be released.
+		 */
+		cgroup_destroy_root(cgrp->root);
+	}
 }
 
 static void cgroup_free_rcu(struct rcu_head *head)
@@ -872,73 +914,40 @@ static void cgroup_free_rcu(struct rcu_head *head)
 	queue_work(cgroup_destroy_wq, &cgrp->destroy_work);
 }
 
-static void cgroup_diput(struct dentry *dentry, struct inode *inode)
-{
-	/* is dentry a directory ? if so, kfree() associated cgroup */
-	if (S_ISDIR(inode->i_mode)) {
-		struct cgroup *cgrp = dentry->d_fsdata;
-
-		BUG_ON(!(cgroup_is_dead(cgrp)));
-
-		/*
-		 * XXX: cgrp->id is only used to look up css's.  As cgroup
-		 * and css's lifetimes will be decoupled, it should be made
-		 * per-subsystem and moved to css->id so that lookups are
-		 * successful until the target css is released.
-		 */
-		mutex_lock(&cgroup_mutex);
-		idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
-		mutex_unlock(&cgroup_mutex);
-		cgrp->id = -1;
-
-		call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
-	} else {
-		struct cfent *cfe = __d_cfe(dentry);
-		struct cgroup *cgrp = dentry->d_parent->d_fsdata;
-
-		WARN_ONCE(!list_empty(&cfe->node) &&
-			  cgrp != &cgrp->root->top_cgroup,
-			  "cfe still linked for %s\n", cfe->type->name);
-		simple_xattrs_free(&cfe->xattrs);
-		kfree(cfe);
-	}
-	iput(inode);
-}
-
-static void remove_dir(struct dentry *d)
+static void cgroup_get(struct cgroup *cgrp)
 {
-	struct dentry *parent = dget(d->d_parent);
-
-	d_delete(d);
-	simple_rmdir(parent->d_inode, d);
-	dput(parent);
+	WARN_ON_ONCE(cgroup_is_dead(cgrp));
+	WARN_ON_ONCE(atomic_read(&cgrp->refcnt) <= 0);
+	atomic_inc(&cgrp->refcnt);
 }
 
-static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
+static void cgroup_put(struct cgroup *cgrp)
 {
-	struct cfent *cfe;
-
-	lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
-	lockdep_assert_held(&cgroup_mutex);
+	if (!atomic_dec_and_test(&cgrp->refcnt))
+		return;
+	if (WARN_ON_ONCE(cgrp->parent && !cgroup_is_dead(cgrp)))
+		return;
 
 	/*
-	 * If we're doing cleanup due to failure of cgroup_create(),
-	 * the corresponding @cfe may not exist.
+	 * XXX: cgrp->id is only used to look up css's.  As cgroup and
+	 * css's lifetimes will be decoupled, it should be made
+	 * per-subsystem and moved to css->id so that lookups are
+	 * successful until the target css is released.
 	 */
-	list_for_each_entry(cfe, &cgrp->files, node) {
-		struct dentry *d = cfe->dentry;
+	mutex_lock(&cgroup_mutex);
+	idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+	mutex_unlock(&cgroup_mutex);
+	cgrp->id = -1;
 
-		if (cft && cfe->type != cft)
-			continue;
+	call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
+}
 
-		dget(d);
-		d_delete(d);
-		simple_unlink(cgrp->dentry->d_inode, d);
-		list_del_init(&cfe->node);
-		dput(d);
+static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
+{
+	char name[CGROUP_FILE_NAME_MAX];
 
-		break;
-	}
+	lockdep_assert_held(&cgroup_tree_mutex);
+	kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name));
 }
 
 /**
@@ -952,81 +961,41 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
 	int i;
 
 	for_each_subsys(ss, i) {
-		struct cftype_set *set;
+		struct cftype *cfts;
 
 		if (!test_bit(i, &subsys_mask))
 			continue;
-		list_for_each_entry(set, &ss->cftsets, node)
-			cgroup_addrm_files(cgrp, set->cfts, false);
+		list_for_each_entry(cfts, &ss->cfts, node)
+			cgroup_addrm_files(cgrp, cfts, false);
 	}
 }
 
-/*
- * NOTE : the dentry must have been dget()'ed
- */
-static void cgroup_d_remove_dir(struct dentry *dentry)
-{
-	struct dentry *parent;
-
-	parent = dentry->d_parent;
-	spin_lock(&parent->d_lock);
-	spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-	list_del_init(&dentry->d_u.d_child);
-	spin_unlock(&dentry->d_lock);
-	spin_unlock(&parent->d_lock);
-	remove_dir(dentry);
-}
-
-/*
- * Call with cgroup_mutex held. Drops reference counts on modules, including
- * any duplicate ones that parse_cgroupfs_options took. If this function
- * returns an error, no reference counts are touched.
- */
 static int rebind_subsystems(struct cgroupfs_root *root,
 			     unsigned long added_mask, unsigned removed_mask)
 {
 	struct cgroup *cgrp = &root->top_cgroup;
 	struct cgroup_subsys *ss;
-	unsigned long pinned = 0;
 	int i, ret;
 
-	BUG_ON(!mutex_is_locked(&cgroup_mutex));
-	BUG_ON(!mutex_is_locked(&cgroup_root_mutex));
+	lockdep_assert_held(&cgroup_tree_mutex);
+	lockdep_assert_held(&cgroup_mutex);
 
 	/* Check that any added subsystems are currently free */
-	for_each_subsys(ss, i) {
-		if (!(added_mask & (1 << i)))
-			continue;
-
-		/* is the subsystem mounted elsewhere? */
-		if (ss->root != &cgroup_dummy_root) {
-			ret = -EBUSY;
-			goto out_put;
-		}
-
-		/* pin the module */
-		if (!try_module_get(ss->module)) {
-			ret = -ENOENT;
-			goto out_put;
-		}
-		pinned |= 1 << i;
-	}
-
-	/* subsys could be missing if unloaded between parsing and here */
-	if (added_mask != pinned) {
-		ret = -ENOENT;
-		goto out_put;
-	}
+	for_each_subsys(ss, i)
+		if ((added_mask & (1 << i)) && ss->root != &cgroup_dummy_root)
+			return -EBUSY;
 
 	ret = cgroup_populate_dir(cgrp, added_mask);
 	if (ret)
-		goto out_put;
+		return ret;
 
 	/*
 	 * Nothing can fail from this point on.  Remove files for the
 	 * removed subsystems and rebind each subsystem.
 	 */
+	mutex_unlock(&cgroup_mutex);
 	cgroup_clear_dir(cgrp, removed_mask);
+	mutex_lock(&cgroup_mutex);
 
 	for_each_subsys(ss, i) {
 		unsigned long bit = 1UL << i;
@@ -1059,35 +1028,21 @@ static int rebind_subsystems(struct cgroupfs_root *root,
 			RCU_INIT_POINTER(cgrp->subsys[i], NULL);
 
 			cgroup_subsys[i]->root = &cgroup_dummy_root;
-
-			/* subsystem is now free - drop reference on module */
-			module_put(ss->module);
 			root->subsys_mask &= ~bit;
 		}
 	}
 
-	/*
-	 * Mark @root has finished binding subsystems.  @root->subsys_mask
-	 * now matches the bound subsystems.
-	 */
-	root->flags |= CGRP_ROOT_SUBSYS_BOUND;
-
+	kernfs_activate(cgrp->kn);
 	return 0;
-
-out_put:
-	for_each_subsys(ss, i)
-		if (pinned & (1 << i))
-			module_put(ss->module);
-	return ret;
 }
 
-static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
+static int cgroup_show_options(struct seq_file *seq,
+			       struct kernfs_root *kf_root)
 {
-	struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
+	struct cgroupfs_root *root = cgroup_root_from_kf(kf_root);
 	struct cgroup_subsys *ss;
 	int ssid;
 
-	mutex_lock(&cgroup_root_mutex);
 	for_each_subsys(ss, ssid)
 		if (root->subsys_mask & (1 << ssid))
 			seq_printf(seq, ",%s", ss->name);
@@ -1097,13 +1052,16 @@ static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
 		seq_puts(seq, ",noprefix");
 	if (root->flags & CGRP_ROOT_XATTR)
 		seq_puts(seq, ",xattr");
+
+	spin_lock(&release_agent_path_lock);
 	if (strlen(root->release_agent_path))
 		seq_printf(seq, ",release_agent=%s", root->release_agent_path);
+	spin_unlock(&release_agent_path_lock);
+
 	if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->top_cgroup.flags))
 		seq_puts(seq, ",clone_children");
 	if (strlen(root->name))
 		seq_printf(seq, ",name=%s", root->name);
-	mutex_unlock(&cgroup_root_mutex);
 	return 0;
 }
 
@@ -1115,9 +1073,6 @@ struct cgroup_sb_opts {
 	char *name;
 	/* User explicitly requested empty subsystem */
 	bool none;
-
-	struct cgroupfs_root *new_root;
-
 };
 
 /*
@@ -1137,7 +1092,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 	BUG_ON(!mutex_is_locked(&cgroup_mutex));
 
 #ifdef CONFIG_CPUSETS
-	mask = ~(1UL << cpuset_subsys_id);
+	mask = ~(1UL << cpuset_cgrp_id);
 #endif
 
 	memset(opts, 0, sizeof(*opts));
@@ -1242,13 +1197,10 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 	if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
 		pr_warning("cgroup: sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
 
-		if (opts->flags & CGRP_ROOT_NOPREFIX) {
-			pr_err("cgroup: sane_behavior: noprefix is not allowed\n");
-			return -EINVAL;
-		}
-
-		if (opts->cpuset_clone_children) {
-			pr_err("cgroup: sane_behavior: clone_children is not allowed\n");
+		if ((opts->flags & (CGRP_ROOT_NOPREFIX | CGRP_ROOT_XATTR)) ||
+		    opts->cpuset_clone_children || opts->release_agent ||
+		    opts->name) {
+			pr_err("cgroup: sane_behavior: noprefix, xattr, clone_children, release_agent and name are not allowed\n");
 			return -EINVAL;
 		}
 	}
@@ -1276,11 +1228,10 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 	return 0;
 }
 
-static int cgroup_remount(struct super_block *sb, int *flags, char *data)
+static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
 {
 	int ret = 0;
-	struct cgroupfs_root *root = sb->s_fs_info;
-	struct cgroup *cgrp = &root->top_cgroup;
+	struct cgroupfs_root *root = cgroup_root_from_kf(kf_root);
 	struct cgroup_sb_opts opts;
 	unsigned long added_mask, removed_mask;
 
@@ -1289,9 +1240,8 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 		return -EINVAL;
 	}
 
-	mutex_lock(&cgrp->dentry->d_inode->i_mutex);
+	mutex_lock(&cgroup_tree_mutex);
 	mutex_lock(&cgroup_mutex);
-	mutex_lock(&cgroup_root_mutex);
 
 	/* See what subsystems are wanted */
 	ret = parse_cgroupfs_options(data, &opts);
@@ -1316,7 +1266,7 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 	}
 
 	/* remounting is not allowed for populated hierarchies */
-	if (root->number_of_cgroups > 1) {
+	if (!list_empty(&root->top_cgroup.children)) {
 		ret = -EBUSY;
 		goto out_unlock;
 	}
@@ -1325,35 +1275,81 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 	if (ret)
 		goto out_unlock;
 
-	if (opts.release_agent)
+	if (opts.release_agent) {
+		spin_lock(&release_agent_path_lock);
 		strcpy(root->release_agent_path, opts.release_agent);
+		spin_unlock(&release_agent_path_lock);
+	}
  out_unlock:
 	kfree(opts.release_agent);
 	kfree(opts.name);
-	mutex_unlock(&cgroup_root_mutex);
 	mutex_unlock(&cgroup_mutex);
-	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 	return ret;
 }
 
-static const struct super_operations cgroup_ops = {
-	.statfs = simple_statfs,
-	.drop_inode = generic_delete_inode,
-	.show_options = cgroup_show_options,
-	.remount_fs = cgroup_remount,
-};
+/*
+ * To reduce the fork() overhead for systems that are not actually using
+ * their cgroups capability, we don't maintain the lists running through
+ * each css_set to its tasks until we see the list actually used - in other
+ * words after the first mount.
+ */
+static bool use_task_css_set_links __read_mostly;
+
+static void cgroup_enable_task_cg_lists(void)
+{
+	struct task_struct *p, *g;
+
+	down_write(&css_set_rwsem);
+
+	if (use_task_css_set_links)
+		goto out_unlock;
+
+	use_task_css_set_links = true;
+
+	/*
+	 * We need tasklist_lock because RCU is not safe against
+	 * while_each_thread(). Besides, a forking task that has passed
+	 * cgroup_post_fork() without seeing use_task_css_set_links = 1
+	 * is not guaranteed to have its child immediately visible in the
+	 * tasklist if we walk through it with RCU.
+	 */
+	read_lock(&tasklist_lock);
+	do_each_thread(g, p) {
+		WARN_ON_ONCE(!list_empty(&p->cg_list) ||
+			     task_css_set(p) != &init_css_set);
+
+		/*
+		 * We should check if the process is exiting, otherwise
+		 * it will race with cgroup_exit() in that the list
+		 * entry won't be deleted though the process has exited.
+		 * Do it while holding siglock so that we don't end up
+		 * racing against cgroup_exit().
+		 */
+		spin_lock_irq(&p->sighand->siglock);
+		if (!(p->flags & PF_EXITING)) {
+			struct css_set *cset = task_css_set(p);
+
+			list_add(&p->cg_list, &cset->tasks);
+			get_css_set(cset);
+		}
+		spin_unlock_irq(&p->sighand->siglock);
+	} while_each_thread(g, p);
+	read_unlock(&tasklist_lock);
+out_unlock:
+	up_write(&css_set_rwsem);
+}
 
 static void init_cgroup_housekeeping(struct cgroup *cgrp)
 {
+	atomic_set(&cgrp->refcnt, 1);
 	INIT_LIST_HEAD(&cgrp->sibling);
 	INIT_LIST_HEAD(&cgrp->children);
-	INIT_LIST_HEAD(&cgrp->files);
 	INIT_LIST_HEAD(&cgrp->cset_links);
 	INIT_LIST_HEAD(&cgrp->release_list);
 	INIT_LIST_HEAD(&cgrp->pidlists);
 	mutex_init(&cgrp->pidlist_mutex);
 	cgrp->dummy_css.cgroup = cgrp;
-	simple_xattrs_init(&cgrp->xattrs);
 }
 
 static void init_cgroup_root(struct cgroupfs_root *root)
@@ -1361,66 +1357,18 @@ static void init_cgroup_root(struct cgroupfs_root *root)
 	struct cgroup *cgrp = &root->top_cgroup;
 
 	INIT_LIST_HEAD(&root->root_list);
-	root->number_of_cgroups = 1;
+	atomic_set(&root->nr_cgrps, 1);
 	cgrp->root = root;
-	RCU_INIT_POINTER(cgrp->name, &root_cgroup_name);
 	init_cgroup_housekeeping(cgrp);
 	idr_init(&root->cgroup_idr);
 }
 
-static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end)
-{
-	int id;
-
-	lockdep_assert_held(&cgroup_mutex);
-	lockdep_assert_held(&cgroup_root_mutex);
-
-	id = idr_alloc_cyclic(&cgroup_hierarchy_idr, root, start, end,
-			      GFP_KERNEL);
-	if (id < 0)
-		return id;
-
-	root->hierarchy_id = id;
-	return 0;
-}
-
-static void cgroup_exit_root_id(struct cgroupfs_root *root)
-{
-	lockdep_assert_held(&cgroup_mutex);
-	lockdep_assert_held(&cgroup_root_mutex);
-
-	if (root->hierarchy_id) {
-		idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id);
-		root->hierarchy_id = 0;
-	}
-}
-
-static int cgroup_test_super(struct super_block *sb, void *data)
-{
-	struct cgroup_sb_opts *opts = data;
-	struct cgroupfs_root *root = sb->s_fs_info;
-
-	/* If we asked for a name then it must match */
-	if (opts->name && strcmp(opts->name, root->name))
-		return 0;
-
-	/*
-	 * If we asked for subsystems (or explicitly for no
-	 * subsystems) then they must match
-	 */
-	if ((opts->subsys_mask || opts->none)
-	    && (opts->subsys_mask != root->subsys_mask))
-		return 0;
-
-	return 1;
-}
-
 static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
 {
 	struct cgroupfs_root *root;
 
 	if (!opts->subsys_mask && !opts->none)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	root = kzalloc(sizeof(*root), GFP_KERNEL);
 	if (!root)
@@ -1428,15 +1376,6 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
 
 	init_cgroup_root(root);
 
-	/*
-	 * We need to set @root->subsys_mask now so that @root can be
-	 * matched by cgroup_test_super() before it finishes
-	 * initialization; otherwise, competing mounts with the same
-	 * options may try to bind the same subsystems instead of waiting
-	 * for the first one leading to unexpected mount errors.
-	 * SUBSYS_BOUND will be set once actual binding is complete.
-	 */
-	root->subsys_mask = opts->subsys_mask;
 	root->flags = opts->flags;
 	if (opts->release_agent)
 		strcpy(root->release_agent_path, opts->release_agent);
@@ -1447,351 +1386,211 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
 	return root;
 }
 
-static void cgroup_free_root(struct cgroupfs_root *root)
+static int cgroup_setup_root(struct cgroupfs_root *root, unsigned long ss_mask)
 {
-	if (root) {
-		/* hierarhcy ID shoulid already have been released */
-		WARN_ON_ONCE(root->hierarchy_id);
-
-		idr_destroy(&root->cgroup_idr);
-		kfree(root);
-	}
-}
+	LIST_HEAD(tmp_links);
+	struct cgroup *root_cgrp = &root->top_cgroup;
+	struct css_set *cset;
+	int i, ret;
 
-static int cgroup_set_super(struct super_block *sb, void *data)
-{
-	int ret;
-	struct cgroup_sb_opts *opts = data;
+	lockdep_assert_held(&cgroup_tree_mutex);
+	lockdep_assert_held(&cgroup_mutex);
 
-	/* If we don't have a new root, we can't set up a new sb */
-	if (!opts->new_root)
-		return -EINVAL;
+	ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL);
+	if (ret < 0)
+		goto out;
+	root_cgrp->id = ret;
 
-	BUG_ON(!opts->subsys_mask && !opts->none);
+	/*
+	 * We're accessing css_set_count without locking css_set_rwsem here,
+	 * but that's OK - it can only be increased by someone holding
+	 * cgroup_lock, and that's us. The worst that can happen is that we
+	 * have some link structures left over
+	 */
+	ret = allocate_cgrp_cset_links(css_set_count, &tmp_links);
+	if (ret)
+		goto out;
 
-	ret = set_anon_super(sb, NULL);
+	/* ID 0 is reserved for dummy root, 1 for unified hierarchy */
+	ret = cgroup_init_root_id(root, 2, 0);
 	if (ret)
-		return ret;
+		goto out;
 
-	sb->s_fs_info = opts->new_root;
-	opts->new_root->sb = sb;
+	root->kf_root = kernfs_create_root(&cgroup_kf_syscall_ops,
+					   KERNFS_ROOT_CREATE_DEACTIVATED,
+					   root_cgrp);
+	if (IS_ERR(root->kf_root)) {
+		ret = PTR_ERR(root->kf_root);
+		goto exit_root_id;
+	}
+	root_cgrp->kn = root->kf_root->kn;
 
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = CGROUP_SUPER_MAGIC;
-	sb->s_op = &cgroup_ops;
+	ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
+	if (ret)
+		goto destroy_root;
 
-	return 0;
-}
+	ret = rebind_subsystems(root, ss_mask, 0);
+	if (ret)
+		goto destroy_root;
 
-static int cgroup_get_rootdir(struct super_block *sb)
-{
-	static const struct dentry_operations cgroup_dops = {
-		.d_iput = cgroup_diput,
-		.d_delete = always_delete_dentry,
-	};
+	/*
+	 * There must be no failure case after here, since rebinding takes
+	 * care of subsystems' refcounts, which are explicitly dropped in
+	 * the failure exit path.
+	 */
+	list_add(&root->root_list, &cgroup_roots);
+	cgroup_root_count++;
 
-	struct inode *inode =
-		cgroup_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, sb);
+	/*
+	 * Link the top cgroup in this hierarchy into all the css_set
+	 * objects.
+	 */
+	down_write(&css_set_rwsem);
+	hash_for_each(css_set_table, i, cset, hlist)
+		link_css_set(&tmp_links, cset, root_cgrp);
+	up_write(&css_set_rwsem);
 
-	if (!inode)
-		return -ENOMEM;
+	BUG_ON(!list_empty(&root_cgrp->children));
+	BUG_ON(atomic_read(&root->nr_cgrps) != 1);
 
-	inode->i_fop = &simple_dir_operations;
-	inode->i_op = &cgroup_dir_inode_operations;
-	/* directories start off with i_nlink == 2 (for "." entry) */
-	inc_nlink(inode);
-	sb->s_root = d_make_root(inode);
-	if (!sb->s_root)
-		return -ENOMEM;
-	/* for everything else we want ->d_op set */
-	sb->s_d_op = &cgroup_dops;
-	return 0;
+	kernfs_activate(root_cgrp->kn);
+	ret = 0;
+	goto out;
+
+destroy_root:
+	kernfs_destroy_root(root->kf_root);
+	root->kf_root = NULL;
+exit_root_id:
+	cgroup_exit_root_id(root);
+out:
+	free_cgrp_cset_links(&tmp_links);
+	return ret;
 }
 
 static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 			 int flags, const char *unused_dev_name,
 			 void *data)
 {
-	struct cgroup_sb_opts opts;
 	struct cgroupfs_root *root;
-	int ret = 0;
-	struct super_block *sb;
-	struct cgroupfs_root *new_root;
-	struct list_head tmp_links;
-	struct inode *inode;
-	const struct cred *cred;
-
-	/* First find the desired set of subsystems */
-	mutex_lock(&cgroup_mutex);
-	ret = parse_cgroupfs_options(data, &opts);
-	mutex_unlock(&cgroup_mutex);
-	if (ret)
-		goto out_err;
+	struct cgroup_sb_opts opts;
+	struct dentry *dentry;
+	int ret;
 
 	/*
-	 * Allocate a new cgroup root. We may not need it if we're
-	 * reusing an existing hierarchy.
+	 * The first time anyone tries to mount a cgroup, enable the list
+	 * linking each css_set to its tasks and fix up all existing tasks.
 	 */
-	new_root = cgroup_root_from_opts(&opts);
-	if (IS_ERR(new_root)) {
-		ret = PTR_ERR(new_root);
-		goto out_err;
-	}
-	opts.new_root = new_root;
-
-	/* Locate an existing or new sb for this hierarchy */
-	sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts);
-	if (IS_ERR(sb)) {
-		ret = PTR_ERR(sb);
-		cgroup_free_root(opts.new_root);
-		goto out_err;
-	}
-
-	root = sb->s_fs_info;
-	BUG_ON(!root);
-	if (root == opts.new_root) {
-		/* We used the new root structure, so this is a new hierarchy */
-		struct cgroup *root_cgrp = &root->top_cgroup;
-		struct cgroupfs_root *existing_root;
-		int i;
-		struct css_set *cset;
-
-		BUG_ON(sb->s_root != NULL);
-
-		ret = cgroup_get_rootdir(sb);
-		if (ret)
-			goto drop_new_super;
-		inode = sb->s_root->d_inode;
-
-		mutex_lock(&inode->i_mutex);
-		mutex_lock(&cgroup_mutex);
-		mutex_lock(&cgroup_root_mutex);
-
-		ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL);
-		if (ret < 0)
-			goto unlock_drop;
-		root_cgrp->id = ret;
-
-		/* Check for name clashes with existing mounts */
-		ret = -EBUSY;
-		if (strlen(root->name))
-			for_each_active_root(existing_root)
-				if (!strcmp(existing_root->name, root->name))
-					goto unlock_drop;
-
-		/*
-		 * We're accessing css_set_count without locking
-		 * css_set_lock here, but that's OK - it can only be
-		 * increased by someone holding cgroup_lock, and
-		 * that's us. The worst that can happen is that we
-		 * have some link structures left over
-		 */
-		ret = allocate_cgrp_cset_links(css_set_count, &tmp_links);
-		if (ret)
-			goto unlock_drop;
-
-		/* ID 0 is reserved for dummy root, 1 for unified hierarchy */
-		ret = cgroup_init_root_id(root, 2, 0);
-		if (ret)
-			goto unlock_drop;
-
-		sb->s_root->d_fsdata = root_cgrp;
-		root_cgrp->dentry = sb->s_root;
-
-		/*
-		 * We're inside get_sb() and will call lookup_one_len() to
-		 * create the root files, which doesn't work if SELinux is
-		 * in use.  The following cred dancing somehow works around
-		 * it.  See 2ce9738ba ("cgroupfs: use init_cred when
-		 * populating new cgroupfs mount") for more details.
-		 */
-		cred = override_creds(&init_cred);
-
-		ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
-		if (ret)
-			goto rm_base_files;
+	if (!use_task_css_set_links)
+		cgroup_enable_task_cg_lists();
+retry:
+	mutex_lock(&cgroup_tree_mutex);
+	mutex_lock(&cgroup_mutex);
 
-		ret = rebind_subsystems(root, root->subsys_mask, 0);
-		if (ret)
-			goto rm_base_files;
+	/* First find the desired set of subsystems */
+	ret = parse_cgroupfs_options(data, &opts);
+	if (ret)
+		goto out_unlock;
 
-		revert_creds(cred);
+	/* look for a matching existing root */
+	for_each_active_root(root) {
+		bool name_match = false;
 
 		/*
-		 * There must be no failure case after here, since rebinding
-		 * takes care of subsystems' refcounts, which are explicitly
-		 * dropped in the failure exit path.
+		 * If we asked for a name then it must match.  Also, if
+		 * name matches but sybsys_mask doesn't, we should fail.
+		 * Remember whether name matched.
 		 */
+		if (opts.name) {
+			if (strcmp(opts.name, root->name))
+				continue;
+			name_match = true;
+		}
 
-		list_add(&root->root_list, &cgroup_roots);
-		cgroup_root_count++;
-
-		/* Link the top cgroup in this hierarchy into all
-		 * the css_set objects */
-		write_lock(&css_set_lock);
-		hash_for_each(css_set_table, i, cset, hlist)
-			link_css_set(&tmp_links, cset, root_cgrp);
-		write_unlock(&css_set_lock);
-
-		free_cgrp_cset_links(&tmp_links);
-
-		BUG_ON(!list_empty(&root_cgrp->children));
-		BUG_ON(root->number_of_cgroups != 1);
-
-		mutex_unlock(&cgroup_root_mutex);
-		mutex_unlock(&cgroup_mutex);
-		mutex_unlock(&inode->i_mutex);
-	} else {
 		/*
-		 * We re-used an existing hierarchy - the new root (if
-		 * any) is not needed
+		 * If we asked for subsystems (or explicitly for no
+		 * subsystems) then they must match.
 		 */
-		cgroup_free_root(opts.new_root);
+		if ((opts.subsys_mask || opts.none) &&
+		    (opts.subsys_mask != root->subsys_mask)) {
+			if (!name_match)
+				continue;
+			ret = -EBUSY;
+			goto out_unlock;
+		}
 
 		if ((root->flags ^ opts.flags) & CGRP_ROOT_OPTION_MASK) {
 			if ((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) {
 				pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
 				ret = -EINVAL;
-				goto drop_new_super;
+				goto out_unlock;
 			} else {
 				pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n");
 			}
 		}
+
+		/*
+		 * A root's lifetime is governed by its top cgroup.  Zero
+		 * ref indicate that the root is being destroyed.  Wait for
+		 * destruction to complete so that the subsystems are free.
+		 * We can use wait_queue for the wait but this path is
+		 * super cold.  Let's just sleep for a bit and retry.
+		 */
+		if (!atomic_inc_not_zero(&root->top_cgroup.refcnt)) {
+			mutex_unlock(&cgroup_mutex);
+			mutex_unlock(&cgroup_tree_mutex);
+			kfree(opts.release_agent);
+			kfree(opts.name);
+			msleep(10);
+			goto retry;
+		}
+
+		ret = 0;
+		goto out_unlock;
 	}
 
-	kfree(opts.release_agent);
-	kfree(opts.name);
-	return dget(sb->s_root);
+	/* no such thing, create a new one */
+	root = cgroup_root_from_opts(&opts);
+	if (IS_ERR(root)) {
+		ret = PTR_ERR(root);
+		goto out_unlock;
+	}
 
- rm_base_files:
-	free_cgrp_cset_links(&tmp_links);
-	cgroup_addrm_files(&root->top_cgroup, cgroup_base_files, false);
-	revert_creds(cred);
- unlock_drop:
-	cgroup_exit_root_id(root);
-	mutex_unlock(&cgroup_root_mutex);
+	ret = cgroup_setup_root(root, opts.subsys_mask);
+	if (ret)
+		cgroup_free_root(root);
+
+out_unlock:
 	mutex_unlock(&cgroup_mutex);
-	mutex_unlock(&inode->i_mutex);
- drop_new_super:
-	deactivate_locked_super(sb);
- out_err:
+	mutex_unlock(&cgroup_tree_mutex);
+
 	kfree(opts.release_agent);
 	kfree(opts.name);
-	return ERR_PTR(ret);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	dentry = kernfs_mount(fs_type, flags, root->kf_root, NULL);
+	if (IS_ERR(dentry))
+		cgroup_put(&root->top_cgroup);
+	return dentry;
 }
 
 static void cgroup_kill_sb(struct super_block *sb)
 {
-	struct cgroupfs_root *root = sb->s_fs_info;
-	struct cgroup *cgrp = &root->top_cgroup;
-	struct cgrp_cset_link *link, *tmp_link;
-	int ret;
+	struct kernfs_root *kf_root = kernfs_root_from_sb(sb);
+	struct cgroupfs_root *root = cgroup_root_from_kf(kf_root);
 
-	BUG_ON(!root);
-
-	BUG_ON(root->number_of_cgroups != 1);
-	BUG_ON(!list_empty(&cgrp->children));
+	cgroup_put(&root->top_cgroup);
+	kernfs_kill_sb(sb);
+}
 
-	mutex_lock(&cgrp->dentry->d_inode->i_mutex);
-	mutex_lock(&cgroup_mutex);
-	mutex_lock(&cgroup_root_mutex);
+static struct file_system_type cgroup_fs_type = {
+	.name = "cgroup",
+	.mount = cgroup_mount,
+	.kill_sb = cgroup_kill_sb,
+};
 
-	/* Rebind all subsystems back to the default hierarchy */
-	if (root->flags & CGRP_ROOT_SUBSYS_BOUND) {
-		ret = rebind_subsystems(root, 0, root->subsys_mask);
-		/* Shouldn't be able to fail ... */
-		BUG_ON(ret);
-	}
-
-	/*
-	 * Release all the links from cset_links to this hierarchy's
-	 * root cgroup
-	 */
-	write_lock(&css_set_lock);
-
-	list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
-		list_del(&link->cset_link);
-		list_del(&link->cgrp_link);
-		kfree(link);
-	}
-	write_unlock(&css_set_lock);
-
-	if (!list_empty(&root->root_list)) {
-		list_del(&root->root_list);
-		cgroup_root_count--;
-	}
-
-	cgroup_exit_root_id(root);
-
-	mutex_unlock(&cgroup_root_mutex);
-	mutex_unlock(&cgroup_mutex);
-	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
-
-	simple_xattrs_free(&cgrp->xattrs);
-
-	kill_litter_super(sb);
-	cgroup_free_root(root);
-}
-
-static struct file_system_type cgroup_fs_type = {
-	.name = "cgroup",
-	.mount = cgroup_mount,
-	.kill_sb = cgroup_kill_sb,
-};
-
-static struct kobject *cgroup_kobj;
-
-/**
- * cgroup_path - generate the path of a cgroup
- * @cgrp: the cgroup in question
- * @buf: the buffer to write the path into
- * @buflen: the length of the buffer
- *
- * Writes path of cgroup into buf.  Returns 0 on success, -errno on error.
- *
- * We can't generate cgroup path using dentry->d_name, as accessing
- * dentry->name must be protected by irq-unsafe dentry->d_lock or parent
- * inode's i_mutex, while on the other hand cgroup_path() can be called
- * with some irq-safe spinlocks held.
- */
-int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
-{
-	int ret = -ENAMETOOLONG;
-	char *start;
-
-	if (!cgrp->parent) {
-		if (strlcpy(buf, "/", buflen) >= buflen)
-			return -ENAMETOOLONG;
-		return 0;
-	}
-
-	start = buf + buflen - 1;
-	*start = '\0';
-
-	rcu_read_lock();
-	do {
-		const char *name = cgroup_name(cgrp);
-		int len;
-
-		len = strlen(name);
-		if ((start -= len) < buf)
-			goto out;
-		memcpy(start, name, len);
-
-		if (--start < buf)
-			goto out;
-		*start = '/';
-
-		cgrp = cgrp->parent;
-	} while (cgrp->parent);
-	ret = 0;
-	memmove(buf, start, buf + buflen - start);
-out:
-	rcu_read_unlock();
-	return ret;
-}
-EXPORT_SYMBOL_GPL(cgroup_path);
+static struct kobject *cgroup_kobj;
 
 /**
  * task_cgroup_path - cgroup path of a task in the first cgroup hierarchy
@@ -1804,49 +1603,55 @@ EXPORT_SYMBOL_GPL(cgroup_path);
  * function grabs cgroup_mutex and shouldn't be used inside locks used by
  * cgroup controller callbacks.
  *
- * Returns 0 on success, fails with -%ENAMETOOLONG if @buflen is too short.
+ * Return value is the same as kernfs_path().
  */
-int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
+char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
 {
 	struct cgroupfs_root *root;
 	struct cgroup *cgrp;
-	int hierarchy_id = 1, ret = 0;
-
-	if (buflen < 2)
-		return -ENAMETOOLONG;
+	int hierarchy_id = 1;
+	char *path = NULL;
 
 	mutex_lock(&cgroup_mutex);
+	down_read(&css_set_rwsem);
 
 	root = idr_get_next(&cgroup_hierarchy_idr, &hierarchy_id);
 
 	if (root) {
 		cgrp = task_cgroup_from_root(task, root);
-		ret = cgroup_path(cgrp, buf, buflen);
+		path = cgroup_path(cgrp, buf, buflen);
 	} else {
 		/* if no hierarchy exists, everyone is in "/" */
-		memcpy(buf, "/", 2);
+		if (strlcpy(buf, "/", buflen) < buflen)
+			path = buf;
 	}
 
+	up_read(&css_set_rwsem);
 	mutex_unlock(&cgroup_mutex);
-	return ret;
+	return path;
 }
 EXPORT_SYMBOL_GPL(task_cgroup_path);
 
-/*
- * Control Group taskset
- */
-struct task_and_cgroup {
-	struct task_struct	*task;
-	struct cgroup		*cgrp;
-	struct css_set		*cset;
-};
-
+/* used to track tasks and other necessary states during migration */
 struct cgroup_taskset {
-	struct task_and_cgroup	single;
-	struct flex_array	*tc_array;
-	int			tc_array_len;
-	int			idx;
-	struct cgroup		*cur_cgrp;
+	/* the src and dst cset list running through cset->mg_node */
+	struct list_head	src_csets;
+	struct list_head	dst_csets;
+
+	/*
+	 * Fields for cgroup_taskset_*() iteration.
+	 *
+	 * Before migration is committed, the target migration tasks are on
+	 * ->mg_tasks of the csets on ->src_csets.  After, on ->mg_tasks of
+	 * the csets on ->dst_csets.  ->csets point to either ->src_csets
+	 * or ->dst_csets depending on whether migration is committed.
+	 *
+	 * ->cur_csets and ->cur_task point to the current task position
+	 * during iteration.
+	 */
+	struct list_head	*csets;
+	struct css_set		*cur_cset;
+	struct task_struct	*cur_task;
 };
 
 /**
@@ -1857,15 +1662,11 @@ struct cgroup_taskset {
  */
 struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset)
 {
-	if (tset->tc_array) {
-		tset->idx = 0;
-		return cgroup_taskset_next(tset);
-	} else {
-		tset->cur_cgrp = tset->single.cgrp;
-		return tset->single.task;
-	}
+	tset->cur_cset = list_first_entry(tset->csets, struct css_set, mg_node);
+	tset->cur_task = NULL;
+
+	return cgroup_taskset_next(tset);
 }
-EXPORT_SYMBOL_GPL(cgroup_taskset_first);
 
 /**
  * cgroup_taskset_next - iterate to the next task in taskset
@@ -1876,48 +1677,36 @@ EXPORT_SYMBOL_GPL(cgroup_taskset_first);
  */
 struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset)
 {
-	struct task_and_cgroup *tc;
+	struct css_set *cset = tset->cur_cset;
+	struct task_struct *task = tset->cur_task;
 
-	if (!tset->tc_array || tset->idx >= tset->tc_array_len)
-		return NULL;
+	while (&cset->mg_node != tset->csets) {
+		if (!task)
+			task = list_first_entry(&cset->mg_tasks,
+						struct task_struct, cg_list);
+		else
+			task = list_next_entry(task, cg_list);
 
-	tc = flex_array_get(tset->tc_array, tset->idx++);
-	tset->cur_cgrp = tc->cgrp;
-	return tc->task;
-}
-EXPORT_SYMBOL_GPL(cgroup_taskset_next);
+		if (&task->cg_list != &cset->mg_tasks) {
+			tset->cur_cset = cset;
+			tset->cur_task = task;
+			return task;
+		}
 
-/**
- * cgroup_taskset_cur_css - return the matching css for the current task
- * @tset: taskset of interest
- * @subsys_id: the ID of the target subsystem
- *
- * Return the css for the current (last returned) task of @tset for
- * subsystem specified by @subsys_id.  This function must be preceded by
- * either cgroup_taskset_first() or cgroup_taskset_next().
- */
-struct cgroup_subsys_state *cgroup_taskset_cur_css(struct cgroup_taskset *tset,
-						   int subsys_id)
-{
-	return cgroup_css(tset->cur_cgrp, cgroup_subsys[subsys_id]);
-}
-EXPORT_SYMBOL_GPL(cgroup_taskset_cur_css);
+		cset = list_next_entry(cset, mg_node);
+		task = NULL;
+	}
 
-/**
- * cgroup_taskset_size - return the number of tasks in taskset
- * @tset: taskset of interest
- */
-int cgroup_taskset_size(struct cgroup_taskset *tset)
-{
-	return tset->tc_array ? tset->tc_array_len : 1;
+	return NULL;
 }
-EXPORT_SYMBOL_GPL(cgroup_taskset_size);
 
-
-/*
+/**
  * cgroup_task_migrate - move a task from one cgroup to another.
+ * @old_cgrp; the cgroup @tsk is being migrated from
+ * @tsk: the task being migrated
+ * @new_cset: the new css_set @tsk is being attached to
  *
- * Must be called with cgroup_mutex and threadgroup locked.
+ * Must be called with cgroup_mutex, threadgroup and css_set_rwsem locked.
  */
 static void cgroup_task_migrate(struct cgroup *old_cgrp,
 				struct task_struct *tsk,
@@ -1925,6 +1714,9 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp,
 {
 	struct css_set *old_cset;
 
+	lockdep_assert_held(&cgroup_mutex);
+	lockdep_assert_held(&css_set_rwsem);
+
 	/*
 	 * We are synchronized through threadgroup_lock() against PF_EXITING
 	 * setting such that we can't race against cgroup_exit() changing the
@@ -1933,15 +1725,9 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp,
 	WARN_ON_ONCE(tsk->flags & PF_EXITING);
 	old_cset = task_css_set(tsk);
 
-	task_lock(tsk);
+	get_css_set(new_cset);
 	rcu_assign_pointer(tsk->cgroups, new_cset);
-	task_unlock(tsk);
-
-	/* Update the css_set linked lists if we're using them */
-	write_lock(&css_set_lock);
-	if (!list_empty(&tsk->cg_list))
-		list_move(&tsk->cg_list, &new_cset->tasks);
-	write_unlock(&css_set_lock);
+	list_move(&tsk->cg_list, &new_cset->mg_tasks);
 
 	/*
 	 * We just gained a reference on old_cset by taking it from the
@@ -1949,100 +1735,192 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp,
 	 * we're safe to drop it here; it will be freed under RCU.
 	 */
 	set_bit(CGRP_RELEASABLE, &old_cgrp->flags);
-	put_css_set(old_cset);
+	put_css_set_locked(old_cset, false);
 }
 
 /**
- * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
- * @cgrp: the cgroup to attach to
- * @tsk: the task or the leader of the threadgroup to be attached
- * @threadgroup: attach the whole threadgroup?
+ * cgroup_migrate_finish - cleanup after attach
+ * @preloaded_csets: list of preloaded css_sets
  *
- * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
- * task_lock of @tsk or each thread in the threadgroup individually in turn.
+ * Undo cgroup_migrate_add_src() and cgroup_migrate_prepare_dst().  See
+ * those functions for details.
  */
-static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
-			      bool threadgroup)
+static void cgroup_migrate_finish(struct list_head *preloaded_csets)
 {
-	int retval, i, group_size;
-	struct cgroupfs_root *root = cgrp->root;
-	struct cgroup_subsys_state *css, *failed_css = NULL;
-	/* threadgroup list cursor and array */
-	struct task_struct *leader = tsk;
-	struct task_and_cgroup *tc;
-	struct flex_array *group;
-	struct cgroup_taskset tset = { };
+	struct css_set *cset, *tmp_cset;
 
-	/*
-	 * step 0: in order to do expensive, possibly blocking operations for
-	 * every thread, we cannot iterate the thread group list, since it needs
-	 * rcu or tasklist locked. instead, build an array of all threads in the
-	 * group - group_rwsem prevents new threads from appearing, and if
-	 * threads exit, this will just be an over-estimate.
-	 */
-	if (threadgroup)
-		group_size = get_nr_threads(tsk);
-	else
-		group_size = 1;
-	/* flex_array supports very large thread-groups better than kmalloc. */
-	group = flex_array_alloc(sizeof(*tc), group_size, GFP_KERNEL);
-	if (!group)
-		return -ENOMEM;
-	/* pre-allocate to guarantee space while iterating in rcu read-side. */
-	retval = flex_array_prealloc(group, 0, group_size, GFP_KERNEL);
-	if (retval)
-		goto out_free_group_list;
+	lockdep_assert_held(&cgroup_mutex);
+
+	down_write(&css_set_rwsem);
+	list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) {
+		cset->mg_src_cgrp = NULL;
+		cset->mg_dst_cset = NULL;
+		list_del_init(&cset->mg_preload_node);
+		put_css_set_locked(cset, false);
+	}
+	up_write(&css_set_rwsem);
+}
+
+/**
+ * cgroup_migrate_add_src - add a migration source css_set
+ * @src_cset: the source css_set to add
+ * @dst_cgrp: the destination cgroup
+ * @preloaded_csets: list of preloaded css_sets
+ *
+ * Tasks belonging to @src_cset are about to be migrated to @dst_cgrp.  Pin
+ * @src_cset and add it to @preloaded_csets, which should later be cleaned
+ * up by cgroup_migrate_finish().
+ *
+ * This function may be called without holding threadgroup_lock even if the
+ * target is a process.  Threads may be created and destroyed but as long
+ * as cgroup_mutex is not dropped, no new css_set can be put into play and
+ * the preloaded css_sets are guaranteed to cover all migrations.
+ */
+static void cgroup_migrate_add_src(struct css_set *src_cset,
+				   struct cgroup *dst_cgrp,
+				   struct list_head *preloaded_csets)
+{
+	struct cgroup *src_cgrp;
+
+	lockdep_assert_held(&cgroup_mutex);
+	lockdep_assert_held(&css_set_rwsem);
+
+	src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
+
+	/* nothing to do if this cset already belongs to the cgroup */
+	if (src_cgrp == dst_cgrp)
+		return;
+
+	if (!list_empty(&src_cset->mg_preload_node))
+		return;
+
+	WARN_ON(src_cset->mg_src_cgrp);
+	WARN_ON(!list_empty(&src_cset->mg_tasks));
+	WARN_ON(!list_empty(&src_cset->mg_node));
+
+	src_cset->mg_src_cgrp = src_cgrp;
+	get_css_set(src_cset);
+	list_add(&src_cset->mg_preload_node, preloaded_csets);
+}
+
+/**
+ * cgroup_migrate_prepare_dst - prepare destination css_sets for migration
+ * @dst_cgrp: the destination cgroup
+ * @preloaded_csets: list of preloaded source css_sets
+ *
+ * Tasks are about to be moved to @dst_cgrp and all the source css_sets
+ * have been preloaded to @preloaded_csets.  This function looks up and
+ * pins all destination css_sets, links each to its source, and put them on
+ * @preloaded_csets.
+ *
+ * This function must be called after cgroup_migrate_add_src() has been
+ * called on each migration source css_set.  After migration is performed
+ * using cgroup_migrate(), cgroup_migrate_finish() must be called on
+ * @preloaded_csets.
+ */
+static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
+				      struct list_head *preloaded_csets)
+{
+	LIST_HEAD(csets);
+	struct css_set *src_cset;
+
+	lockdep_assert_held(&cgroup_mutex);
+
+	/* look up the dst cset for each src cset and link it to src */
+	list_for_each_entry(src_cset, preloaded_csets, mg_preload_node) {
+		struct css_set *dst_cset;
+
+		dst_cset = find_css_set(src_cset, dst_cgrp);
+		if (!dst_cset)
+			goto err;
+
+		WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
+		src_cset->mg_dst_cset = dst_cset;
+
+		if (list_empty(&dst_cset->mg_preload_node))
+			list_add(&dst_cset->mg_preload_node, &csets);
+		else
+			put_css_set(dst_cset, false);
+	}
+
+	list_splice(&csets, preloaded_csets);
+	return 0;
+err:
+	cgroup_migrate_finish(&csets);
+	return -ENOMEM;
+}
+
+/**
+ * cgroup_migrate - migrate a process or task to a cgroup
+ * @cgrp: the destination cgroup
+ * @leader: the leader of the process or the task to migrate
+ * @threadgroup: whether @leader points to the whole process or a single task
+ *
+ * Migrate a process or task denoted by @leader to @cgrp.  If migrating a
+ * process, the caller must be holding threadgroup_lock of @leader.  The
+ * caller is also responsible for invoking cgroup_migrate_add_src() and
+ * cgroup_migrate_prepare_dst() on the targets before invoking this
+ * function and following up with cgroup_migrate_finish().
+ *
+ * As long as a controller's ->can_attach() doesn't fail, this function is
+ * guaranteed to succeed.  This means that, excluding ->can_attach()
+ * failure, when migrating multiple targets, the success or failure can be
+ * decided for all targets by invoking group_migrate_prepare_dst() before
+ * actually starting migrating.
+ */
+static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader,
+			  bool threadgroup)
+{
+	struct cgroup_taskset tset = {
+		.src_csets	= LIST_HEAD_INIT(tset.src_csets),
+		.dst_csets	= LIST_HEAD_INIT(tset.dst_csets),
+		.csets		= &tset.src_csets,
+	};
+	struct cgroup_subsys_state *css, *failed_css = NULL;
+	struct css_set *cset, *tmp_cset;
+	struct task_struct *task, *tmp_task;
+	int i, ret;
 
-	i = 0;
 	/*
 	 * Prevent freeing of tasks while we take a snapshot. Tasks that are
 	 * already PF_EXITING could be freed from underneath us unless we
 	 * take an rcu_read_lock.
 	 */
+	down_write(&css_set_rwsem);
 	rcu_read_lock();
+	task = leader;
 	do {
-		struct task_and_cgroup ent;
+		/* @task either already exited or can't exit until the end */
+		if (task->flags & PF_EXITING)
+			goto next;
 
-		/* @tsk either already exited or can't exit until the end */
-		if (tsk->flags & PF_EXITING)
+		/* leave @task alone if post_fork() hasn't linked it yet */
+		if (list_empty(&task->cg_list))
 			goto next;
 
-		/* as per above, nr_threads may decrease, but not increase. */
-		BUG_ON(i >= group_size);
-		ent.task = tsk;
-		ent.cgrp = task_cgroup_from_root(tsk, root);
-		/* nothing to do if this task is already in the cgroup */
-		if (ent.cgrp == cgrp)
+		cset = task_css_set(task);
+		if (!cset->mg_src_cgrp)
 			goto next;
-		/*
-		 * saying GFP_ATOMIC has no effect here because we did prealloc
-		 * earlier, but it's good form to communicate our expectations.
-		 */
-		retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
-		BUG_ON(retval != 0);
-		i++;
+
+		list_move(&task->cg_list, &cset->mg_tasks);
+		list_move(&cset->mg_node, &tset.src_csets);
+		list_move(&cset->mg_dst_cset->mg_node, &tset.dst_csets);
 	next:
 		if (!threadgroup)
 			break;
-	} while_each_thread(leader, tsk);
+	} while_each_thread(leader, task);
 	rcu_read_unlock();
-	/* remember the number of threads in the array for later. */
-	group_size = i;
-	tset.tc_array = group;
-	tset.tc_array_len = group_size;
+	up_write(&css_set_rwsem);
 
 	/* methods shouldn't be called if no task is actually migrating */
-	retval = 0;
-	if (!group_size)
-		goto out_free_group_list;
+	if (list_empty(&tset.src_csets))
+		return 0;
 
-	/*
-	 * step 1: check that we can legitimately attach to the cgroup.
-	 */
+	/* check that we can legitimately attach to the cgroup */
 	for_each_css(css, i, cgrp) {
 		if (css->ss->can_attach) {
-			retval = css->ss->can_attach(css, &tset);
-			if (retval) {
+			ret = css->ss->can_attach(css, &tset);
+			if (ret) {
 				failed_css = css;
 				goto out_cancel_attach;
 			}
@@ -2050,70 +1928,91 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
 	}
 
 	/*
-	 * step 2: make sure css_sets exist for all threads to be migrated.
-	 * we use find_css_set, which allocates a new one if necessary.
+	 * Now that we're guaranteed success, proceed to move all tasks to
+	 * the new cgroup.  There are no failure cases after here, so this
+	 * is the commit point.
 	 */
-	for (i = 0; i < group_size; i++) {
-		struct css_set *old_cset;
-
-		tc = flex_array_get(group, i);
-		old_cset = task_css_set(tc->task);
-		tc->cset = find_css_set(old_cset, cgrp);
-		if (!tc->cset) {
-			retval = -ENOMEM;
-			goto out_put_css_set_refs;
-		}
+	down_write(&css_set_rwsem);
+	list_for_each_entry(cset, &tset.src_csets, mg_node) {
+		list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list)
+			cgroup_task_migrate(cset->mg_src_cgrp, task,
+					    cset->mg_dst_cset);
 	}
+	up_write(&css_set_rwsem);
 
 	/*
-	 * step 3: now that we're guaranteed success wrt the css_sets,
-	 * proceed to move all tasks to the new cgroup.  There are no
-	 * failure cases after here, so this is the commit point.
+	 * Migration is committed, all target tasks are now on dst_csets.
+	 * Nothing is sensitive to fork() after this point.  Notify
+	 * controllers that migration is complete.
 	 */
-	for (i = 0; i < group_size; i++) {
-		tc = flex_array_get(group, i);
-		cgroup_task_migrate(tc->cgrp, tc->task, tc->cset);
-	}
-	/* nothing is sensitive to fork() after this point. */
+	tset.csets = &tset.dst_csets;
 
-	/*
-	 * step 4: do subsystem attach callbacks.
-	 */
 	for_each_css(css, i, cgrp)
 		if (css->ss->attach)
 			css->ss->attach(css, &tset);
 
-	/*
-	 * step 5: success! and cleanup
-	 */
-	retval = 0;
-out_put_css_set_refs:
-	if (retval) {
-		for (i = 0; i < group_size; i++) {
-			tc = flex_array_get(group, i);
-			if (!tc->cset)
-				break;
-			put_css_set(tc->cset);
-		}
-	}
+	ret = 0;
+	goto out_release_tset;
+
 out_cancel_attach:
-	if (retval) {
-		for_each_css(css, i, cgrp) {
-			if (css == failed_css)
-				break;
-			if (css->ss->cancel_attach)
-				css->ss->cancel_attach(css, &tset);
-		}
+	for_each_css(css, i, cgrp) {
+		if (css == failed_css)
+			break;
+		if (css->ss->cancel_attach)
+			css->ss->cancel_attach(css, &tset);
 	}
-out_free_group_list:
-	flex_array_free(group);
-	return retval;
+out_release_tset:
+	down_write(&css_set_rwsem);
+	list_splice_init(&tset.dst_csets, &tset.src_csets);
+	list_for_each_entry_safe(cset, tmp_cset, &tset.src_csets, mg_node) {
+		list_splice_init(&cset->mg_tasks, &cset->tasks);
+		list_del_init(&cset->mg_node);
+	}
+	up_write(&css_set_rwsem);
+	return ret;
+}
+
+/**
+ * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
+ * @dst_cgrp: the cgroup to attach to
+ * @leader: the task or the leader of the threadgroup to be attached
+ * @threadgroup: attach the whole threadgroup?
+ *
+ * Call holding cgroup_mutex and threadgroup_lock of @leader.
+ */
+static int cgroup_attach_task(struct cgroup *dst_cgrp,
+			      struct task_struct *leader, bool threadgroup)
+{
+	LIST_HEAD(preloaded_csets);
+	struct task_struct *task;
+	int ret;
+
+	/* look up all src csets */
+	down_read(&css_set_rwsem);
+	rcu_read_lock();
+	task = leader;
+	do {
+		cgroup_migrate_add_src(task_css_set(task), dst_cgrp,
+				       &preloaded_csets);
+		if (!threadgroup)
+			break;
+	} while_each_thread(leader, task);
+	rcu_read_unlock();
+	up_read(&css_set_rwsem);
+
+	/* prepare dst csets and commit */
+	ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets);
+	if (!ret)
+		ret = cgroup_migrate(dst_cgrp, leader, threadgroup);
+
+	cgroup_migrate_finish(&preloaded_csets);
+	return ret;
 }
 
 /*
  * Find the task_struct of the task to attach by vpid and pass it along to the
  * function to attach either it or all tasks in its threadgroup. Will lock
- * cgroup_mutex and threadgroup; may take task_lock of task.
+ * cgroup_mutex and threadgroup.
  */
 static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
 {
@@ -2203,7 +2102,11 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 
 	mutex_lock(&cgroup_mutex);
 	for_each_active_root(root) {
-		struct cgroup *from_cgrp = task_cgroup_from_root(from, root);
+		struct cgroup *from_cgrp;
+
+		down_read(&css_set_rwsem);
+		from_cgrp = task_cgroup_from_root(from, root);
+		up_read(&css_set_rwsem);
 
 		retval = cgroup_attach_task(from_cgrp, tsk, false);
 		if (retval)
@@ -2230,14 +2133,15 @@ static int cgroup_procs_write(struct cgroup_subsys_state *css,
 static int cgroup_release_agent_write(struct cgroup_subsys_state *css,
 				      struct cftype *cft, const char *buffer)
 {
-	BUILD_BUG_ON(sizeof(css->cgroup->root->release_agent_path) < PATH_MAX);
-	if (strlen(buffer) >= PATH_MAX)
-		return -EINVAL;
+	struct cgroupfs_root *root = css->cgroup->root;
+
+	BUILD_BUG_ON(sizeof(root->release_agent_path) < PATH_MAX);
 	if (!cgroup_lock_live_group(css->cgroup))
 		return -ENODEV;
-	mutex_lock(&cgroup_root_mutex);
-	strcpy(css->cgroup->root->release_agent_path, buffer);
-	mutex_unlock(&cgroup_root_mutex);
+	spin_lock(&release_agent_path_lock);
+	strlcpy(root->release_agent_path, buffer,
+		sizeof(root->release_agent_path));
+	spin_unlock(&release_agent_path_lock);
 	mutex_unlock(&cgroup_mutex);
 	return 0;
 }
@@ -2262,32 +2166,23 @@ static int cgroup_sane_behavior_show(struct seq_file *seq, void *v)
 	return 0;
 }
 
-/* A buffer size big enough for numbers or short strings */
-#define CGROUP_LOCAL_BUFFER_SIZE 64
-
-static ssize_t cgroup_file_write(struct file *file, const char __user *userbuf,
-				 size_t nbytes, loff_t *ppos)
+static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
+				 size_t nbytes, loff_t off)
 {
-	struct cfent *cfe = __d_cfe(file->f_dentry);
-	struct cftype *cft = __d_cft(file->f_dentry);
-	struct cgroup_subsys_state *css = cfe->css;
-	size_t max_bytes = cft->max_write_len ?: CGROUP_LOCAL_BUFFER_SIZE - 1;
-	char *buf;
+	struct cgroup *cgrp = of->kn->parent->priv;
+	struct cftype *cft = of->kn->priv;
+	struct cgroup_subsys_state *css;
 	int ret;
 
-	if (nbytes >= max_bytes)
-		return -E2BIG;
-
-	buf = kmalloc(nbytes + 1, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, userbuf, nbytes)) {
-		ret = -EFAULT;
-		goto out_free;
-	}
-
-	buf[nbytes] = '\0';
+	/*
+	 * kernfs guarantees that a file isn't deleted with operations in
+	 * flight, which means that the matching css is and stays alive and
+	 * doesn't need to be pinned.  The RCU locking is not necessary
+	 * either.  It's just for the convenience of using cgroup_css().
+	 */
+	rcu_read_lock();
+	css = cgroup_css(cgrp, cft->ss);
+	rcu_read_unlock();
 
 	if (cft->write_string) {
 		ret = cft->write_string(css, cft, strstrip(buf));
@@ -2306,53 +2201,23 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *userbuf,
 	} else {
 		ret = -EINVAL;
 	}
-out_free:
-	kfree(buf);
+
 	return ret ?: nbytes;
 }
 
-/*
- * seqfile ops/methods for returning structured data. Currently just
- * supports string->u64 maps, but can be extended in future.
- */
-
 static void *cgroup_seqfile_start(struct seq_file *seq, loff_t *ppos)
 {
-	struct cftype *cft = seq_cft(seq);
-
-	if (cft->seq_start) {
-		return cft->seq_start(seq, ppos);
-	} else {
-		/*
-		 * The same behavior and code as single_open().  Returns
-		 * !NULL if pos is at the beginning; otherwise, NULL.
-		 */
-		return NULL + !*ppos;
-	}
+	return seq_cft(seq)->seq_start(seq, ppos);
 }
 
 static void *cgroup_seqfile_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-	struct cftype *cft = seq_cft(seq);
-
-	if (cft->seq_next) {
-		return cft->seq_next(seq, v, ppos);
-	} else {
-		/*
-		 * The same behavior and code as single_open(), always
-		 * terminate after the initial read.
-		 */
-		++*ppos;
-		return NULL;
-	}
+	return seq_cft(seq)->seq_next(seq, v, ppos);
 }
 
 static void cgroup_seqfile_stop(struct seq_file *seq, void *v)
 {
-	struct cftype *cft = seq_cft(seq);
-
-	if (cft->seq_stop)
-		cft->seq_stop(seq, v);
+	seq_cft(seq)->seq_stop(seq, v);
 }
 
 static int cgroup_seqfile_show(struct seq_file *m, void *arg)
@@ -2372,315 +2237,65 @@ static int cgroup_seqfile_show(struct seq_file *m, void *arg)
 	return 0;
 }
 
-static struct seq_operations cgroup_seq_operations = {
-	.start		= cgroup_seqfile_start,
-	.next		= cgroup_seqfile_next,
-	.stop		= cgroup_seqfile_stop,
-	.show		= cgroup_seqfile_show,
+static struct kernfs_ops cgroup_kf_single_ops = {
+	.atomic_write_len	= PAGE_SIZE,
+	.write			= cgroup_file_write,
+	.seq_show		= cgroup_seqfile_show,
 };
 
-static int cgroup_file_open(struct inode *inode, struct file *file)
-{
-	struct cfent *cfe = __d_cfe(file->f_dentry);
-	struct cftype *cft = __d_cft(file->f_dentry);
-	struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
-	struct cgroup_subsys_state *css;
-	struct cgroup_open_file *of;
-	int err;
-
-	err = generic_file_open(inode, file);
-	if (err)
-		return err;
-
-	/*
-	 * If the file belongs to a subsystem, pin the css.  Will be
-	 * unpinned either on open failure or release.  This ensures that
-	 * @css stays alive for all file operations.
-	 */
-	rcu_read_lock();
-	css = cgroup_css(cgrp, cft->ss);
-	if (cft->ss && !css_tryget(css))
-		css = NULL;
-	rcu_read_unlock();
-
-	if (!css)
-		return -ENODEV;
-
-	/*
-	 * @cfe->css is used by read/write/close to determine the
-	 * associated css.  @file->private_data would be a better place but
-	 * that's already used by seqfile.  Multiple accessors may use it
-	 * simultaneously which is okay as the association never changes.
-	 */
-	WARN_ON_ONCE(cfe->css && cfe->css != css);
-	cfe->css = css;
-
-	of = __seq_open_private(file, &cgroup_seq_operations,
-				sizeof(struct cgroup_open_file));
-	if (of) {
-		of->cfe = cfe;
-		return 0;
-	}
-
-	if (css->ss)
-		css_put(css);
-	return -ENOMEM;
-}
-
-static int cgroup_file_release(struct inode *inode, struct file *file)
-{
-	struct cfent *cfe = __d_cfe(file->f_dentry);
-	struct cgroup_subsys_state *css = cfe->css;
-
-	if (css->ss)
-		css_put(css);
-	return seq_release_private(inode, file);
-}
-
-/*
- * cgroup_rename - Only allow simple rename of directories in place.
- */
-static int cgroup_rename(struct inode *old_dir, struct dentry *old_dentry,
-			    struct inode *new_dir, struct dentry *new_dentry)
-{
-	int ret;
-	struct cgroup_name *name, *old_name;
-	struct cgroup *cgrp;
-
-	/*
-	 * It's convinient to use parent dir's i_mutex to protected
-	 * cgrp->name.
-	 */
-	lockdep_assert_held(&old_dir->i_mutex);
-
-	if (!S_ISDIR(old_dentry->d_inode->i_mode))
-		return -ENOTDIR;
-	if (new_dentry->d_inode)
-		return -EEXIST;
-	if (old_dir != new_dir)
-		return -EIO;
-
-	cgrp = __d_cgrp(old_dentry);
-
-	/*
-	 * This isn't a proper migration and its usefulness is very
-	 * limited.  Disallow if sane_behavior.
-	 */
-	if (cgroup_sane_behavior(cgrp))
-		return -EPERM;
-
-	name = cgroup_alloc_name(new_dentry);
-	if (!name)
-		return -ENOMEM;
-
-	ret = simple_rename(old_dir, old_dentry, new_dir, new_dentry);
-	if (ret) {
-		kfree(name);
-		return ret;
-	}
-
-	old_name = rcu_dereference_protected(cgrp->name, true);
-	rcu_assign_pointer(cgrp->name, name);
-
-	kfree_rcu(old_name, rcu_head);
-	return 0;
-}
-
-static struct simple_xattrs *__d_xattrs(struct dentry *dentry)
-{
-	if (S_ISDIR(dentry->d_inode->i_mode))
-		return &__d_cgrp(dentry)->xattrs;
-	else
-		return &__d_cfe(dentry)->xattrs;
-}
-
-static inline int xattr_enabled(struct dentry *dentry)
-{
-	struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
-	return root->flags & CGRP_ROOT_XATTR;
-}
-
-static bool is_valid_xattr(const char *name)
-{
-	if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
-	    !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN))
-		return true;
-	return false;
-}
-
-static int cgroup_setxattr(struct dentry *dentry, const char *name,
-			   const void *val, size_t size, int flags)
-{
-	if (!xattr_enabled(dentry))
-		return -EOPNOTSUPP;
-	if (!is_valid_xattr(name))
-		return -EINVAL;
-	return simple_xattr_set(__d_xattrs(dentry), name, val, size, flags);
-}
-
-static int cgroup_removexattr(struct dentry *dentry, const char *name)
-{
-	if (!xattr_enabled(dentry))
-		return -EOPNOTSUPP;
-	if (!is_valid_xattr(name))
-		return -EINVAL;
-	return simple_xattr_remove(__d_xattrs(dentry), name);
-}
-
-static ssize_t cgroup_getxattr(struct dentry *dentry, const char *name,
-			       void *buf, size_t size)
-{
-	if (!xattr_enabled(dentry))
-		return -EOPNOTSUPP;
-	if (!is_valid_xattr(name))
-		return -EINVAL;
-	return simple_xattr_get(__d_xattrs(dentry), name, buf, size);
-}
-
-static ssize_t cgroup_listxattr(struct dentry *dentry, char *buf, size_t size)
-{
-	if (!xattr_enabled(dentry))
-		return -EOPNOTSUPP;
-	return simple_xattr_list(__d_xattrs(dentry), buf, size);
-}
-
-static const struct file_operations cgroup_file_operations = {
-	.read = seq_read,
-	.write = cgroup_file_write,
-	.llseek = generic_file_llseek,
-	.open = cgroup_file_open,
-	.release = cgroup_file_release,
-};
-
-static const struct inode_operations cgroup_file_inode_operations = {
-	.setxattr = cgroup_setxattr,
-	.getxattr = cgroup_getxattr,
-	.listxattr = cgroup_listxattr,
-	.removexattr = cgroup_removexattr,
-};
-
-static const struct inode_operations cgroup_dir_inode_operations = {
-	.lookup = simple_lookup,
-	.mkdir = cgroup_mkdir,
-	.rmdir = cgroup_rmdir,
-	.rename = cgroup_rename,
-	.setxattr = cgroup_setxattr,
-	.getxattr = cgroup_getxattr,
-	.listxattr = cgroup_listxattr,
-	.removexattr = cgroup_removexattr,
-};
-
-static int cgroup_create_file(struct dentry *dentry, umode_t mode,
-				struct super_block *sb)
-{
-	struct inode *inode;
-
-	if (!dentry)
-		return -ENOENT;
-	if (dentry->d_inode)
-		return -EEXIST;
-
-	inode = cgroup_new_inode(mode, sb);
-	if (!inode)
-		return -ENOMEM;
-
-	if (S_ISDIR(mode)) {
-		inode->i_op = &cgroup_dir_inode_operations;
-		inode->i_fop = &simple_dir_operations;
-
-		/* start off with i_nlink == 2 (for "." entry) */
-		inc_nlink(inode);
-		inc_nlink(dentry->d_parent->d_inode);
-
-		/*
-		 * Control reaches here with cgroup_mutex held.
-		 * @inode->i_mutex should nest outside cgroup_mutex but we
-		 * want to populate it immediately without releasing
-		 * cgroup_mutex.  As @inode isn't visible to anyone else
-		 * yet, trylock will always succeed without affecting
-		 * lockdep checks.
-		 */
-		WARN_ON_ONCE(!mutex_trylock(&inode->i_mutex));
-	} else if (S_ISREG(mode)) {
-		inode->i_size = 0;
-		inode->i_fop = &cgroup_file_operations;
-		inode->i_op = &cgroup_file_inode_operations;
-	}
-	d_instantiate(dentry, inode);
-	dget(dentry);	/* Extra count - pin the dentry in core */
-	return 0;
-}
-
-/**
- * cgroup_file_mode - deduce file mode of a control file
- * @cft: the control file in question
- *
- * returns cft->mode if ->mode is not 0
- * returns S_IRUGO|S_IWUSR if it has both a read and a write handler
- * returns S_IRUGO if it has only a read handler
- * returns S_IWUSR if it has only a write hander
+static struct kernfs_ops cgroup_kf_ops = {
+	.atomic_write_len	= PAGE_SIZE,
+	.write			= cgroup_file_write,
+	.seq_start		= cgroup_seqfile_start,
+	.seq_next		= cgroup_seqfile_next,
+	.seq_stop		= cgroup_seqfile_stop,
+	.seq_show		= cgroup_seqfile_show,
+};
+
+/*
+ * cgroup_rename - Only allow simple rename of directories in place.
  */
-static umode_t cgroup_file_mode(const struct cftype *cft)
+static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent,
+			 const char *new_name_str)
 {
-	umode_t mode = 0;
+	struct cgroup *cgrp = kn->priv;
+	int ret;
 
-	if (cft->mode)
-		return cft->mode;
+	if (kernfs_type(kn) != KERNFS_DIR)
+		return -ENOTDIR;
+	if (kn->parent != new_parent)
+		return -EIO;
 
-	if (cft->read_u64 || cft->read_s64 || cft->seq_show)
-		mode |= S_IRUGO;
+	/*
+	 * This isn't a proper migration and its usefulness is very
+	 * limited.  Disallow if sane_behavior.
+	 */
+	if (cgroup_sane_behavior(cgrp))
+		return -EPERM;
 
-	if (cft->write_u64 || cft->write_s64 || cft->write_string ||
-	    cft->trigger)
-		mode |= S_IWUSR;
+	mutex_lock(&cgroup_tree_mutex);
+	mutex_lock(&cgroup_mutex);
 
-	return mode;
+	ret = kernfs_rename(kn, new_parent, new_name_str);
+
+	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
+	return ret;
 }
 
 static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
 {
-	struct dentry *dir = cgrp->dentry;
-	struct cgroup *parent = __d_cgrp(dir);
-	struct dentry *dentry;
-	struct cfent *cfe;
-	int error;
-	umode_t mode;
-	char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
-
-	if (cft->ss && !(cft->flags & CFTYPE_NO_PREFIX) &&
-	    !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
-		strcpy(name, cft->ss->name);
-		strcat(name, ".");
-	}
-	strcat(name, cft->name);
-
-	BUG_ON(!mutex_is_locked(&dir->d_inode->i_mutex));
+	char name[CGROUP_FILE_NAME_MAX];
+	struct kernfs_node *kn;
+	struct lock_class_key *key = NULL;
 
-	cfe = kzalloc(sizeof(*cfe), GFP_KERNEL);
-	if (!cfe)
-		return -ENOMEM;
-
-	dentry = lookup_one_len(name, dir, strlen(name));
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out;
-	}
-
-	cfe->type = (void *)cft;
-	cfe->dentry = dentry;
-	dentry->d_fsdata = cfe;
-	simple_xattrs_init(&cfe->xattrs);
-
-	mode = cgroup_file_mode(cft);
-	error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
-	if (!error) {
-		list_add_tail(&cfe->node, &parent->files);
-		cfe = NULL;
-	}
-	dput(dentry);
-out:
-	kfree(cfe);
-	return error;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	key = &cft->lockdep_key;
+#endif
+	kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name),
+				  cgroup_file_mode(cft), 0, cft->kf_ops, cft,
+				  NULL, false, key);
+	return PTR_ERR_OR_ZERO(kn);
 }
 
 /**
@@ -2700,8 +2315,7 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
 	struct cftype *cft;
 	int ret;
 
-	lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
-	lockdep_assert_held(&cgroup_mutex);
+	lockdep_assert_held(&cgroup_tree_mutex);
 
 	for (cft = cfts; cft->name[0] != '\0'; cft++) {
 		/* does cft->flags tell us to skip this file on @cgrp? */
@@ -2726,44 +2340,19 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
 	return 0;
 }
 
-static void cgroup_cfts_prepare(void)
-	__acquires(&cgroup_mutex)
-{
-	/*
-	 * Thanks to the entanglement with vfs inode locking, we can't walk
-	 * the existing cgroups under cgroup_mutex and create files.
-	 * Instead, we use css_for_each_descendant_pre() and drop RCU read
-	 * lock before calling cgroup_addrm_files().
-	 */
-	mutex_lock(&cgroup_mutex);
-}
-
-static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
-	__releases(&cgroup_mutex)
+static int cgroup_apply_cftypes(struct cftype *cfts, bool is_add)
 {
 	LIST_HEAD(pending);
 	struct cgroup_subsys *ss = cfts[0].ss;
 	struct cgroup *root = &ss->root->top_cgroup;
-	struct super_block *sb = ss->root->sb;
-	struct dentry *prev = NULL;
-	struct inode *inode;
 	struct cgroup_subsys_state *css;
-	u64 update_before;
 	int ret = 0;
 
-	/* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
-	if (!cfts || ss->root == &cgroup_dummy_root ||
-	    !atomic_inc_not_zero(&sb->s_active)) {
-		mutex_unlock(&cgroup_mutex);
-		return 0;
-	}
+	lockdep_assert_held(&cgroup_tree_mutex);
 
-	/*
-	 * All cgroups which are created after we drop cgroup_mutex will
-	 * have the updated set of files, so we only need to update the
-	 * cgroups created before the current @cgroup_serial_nr_next.
-	 */
-	update_before = cgroup_serial_nr_next;
+	/* don't bother if @ss isn't attached */
+	if (ss->root == &cgroup_dummy_root)
+		return 0;
 
 	/* add/rm files for all cgroups created before */
 	css_for_each_descendant_pre(css, cgroup_css(root, ss)) {
@@ -2772,62 +2361,75 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
 		if (cgroup_is_dead(cgrp))
 			continue;
 
-		inode = cgrp->dentry->d_inode;
-		dget(cgrp->dentry);
-		dput(prev);
-		prev = cgrp->dentry;
-
-		mutex_unlock(&cgroup_mutex);
-		mutex_lock(&inode->i_mutex);
-		mutex_lock(&cgroup_mutex);
-		if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
-			ret = cgroup_addrm_files(cgrp, cfts, is_add);
-		mutex_unlock(&inode->i_mutex);
+		ret = cgroup_addrm_files(cgrp, cfts, is_add);
 		if (ret)
 			break;
 	}
-	mutex_unlock(&cgroup_mutex);
-	dput(prev);
-	deactivate_super(sb);
+
+	if (is_add && !ret)
+		kernfs_activate(root->kn);
 	return ret;
 }
 
-/**
- * cgroup_add_cftypes - add an array of cftypes to a subsystem
- * @ss: target cgroup subsystem
- * @cfts: zero-length name terminated array of cftypes
- *
- * Register @cfts to @ss.  Files described by @cfts are created for all
- * existing cgroups to which @ss is attached and all future cgroups will
- * have them too.  This function can be called anytime whether @ss is
- * attached or not.
- *
- * Returns 0 on successful registration, -errno on failure.  Note that this
- * function currently returns 0 as long as @cfts registration is successful
- * even if some file creation attempts on existing cgroups fail.
- */
-int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+static void cgroup_exit_cftypes(struct cftype *cfts)
 {
-	struct cftype_set *set;
 	struct cftype *cft;
-	int ret;
 
-	set = kzalloc(sizeof(*set), GFP_KERNEL);
-	if (!set)
-		return -ENOMEM;
+	for (cft = cfts; cft->name[0] != '\0'; cft++) {
+		/* free copy for custom atomic_write_len, see init_cftypes() */
+		if (cft->max_write_len && cft->max_write_len != PAGE_SIZE)
+			kfree(cft->kf_ops);
+		cft->kf_ops = NULL;
+		cft->ss = NULL;
+	}
+}
+
+static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+{
+	struct cftype *cft;
+
+	for (cft = cfts; cft->name[0] != '\0'; cft++) {
+		struct kernfs_ops *kf_ops;
+
+		WARN_ON(cft->ss || cft->kf_ops);
+
+		if (cft->seq_start)
+			kf_ops = &cgroup_kf_ops;
+		else
+			kf_ops = &cgroup_kf_single_ops;
+
+		/*
+		 * Ugh... if @cft wants a custom max_write_len, we need to
+		 * make a copy of kf_ops to set its atomic_write_len.
+		 */
+		if (cft->max_write_len && cft->max_write_len != PAGE_SIZE) {
+			kf_ops = kmemdup(kf_ops, sizeof(*kf_ops), GFP_KERNEL);
+			if (!kf_ops) {
+				cgroup_exit_cftypes(cfts);
+				return -ENOMEM;
+			}
+			kf_ops->atomic_write_len = cft->max_write_len;
+		}
 
-	for (cft = cfts; cft->name[0] != '\0'; cft++)
+		cft->kf_ops = kf_ops;
 		cft->ss = ss;
+	}
 
-	cgroup_cfts_prepare();
-	set->cfts = cfts;
-	list_add_tail(&set->node, &ss->cftsets);
-	ret = cgroup_cfts_commit(cfts, true);
-	if (ret)
-		cgroup_rm_cftypes(cfts);
-	return ret;
+	return 0;
+}
+
+static int cgroup_rm_cftypes_locked(struct cftype *cfts)
+{
+	lockdep_assert_held(&cgroup_tree_mutex);
+
+	if (!cfts || !cfts[0].ss)
+		return -ENOENT;
+
+	list_del(&cfts->node);
+	cgroup_apply_cftypes(cfts, false);
+	cgroup_exit_cftypes(cfts);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
 
 /**
  * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
@@ -2842,24 +2444,48 @@ EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
  */
 int cgroup_rm_cftypes(struct cftype *cfts)
 {
-	struct cftype_set *set;
+	int ret;
 
-	if (!cfts || !cfts[0].ss)
-		return -ENOENT;
+	mutex_lock(&cgroup_tree_mutex);
+	ret = cgroup_rm_cftypes_locked(cfts);
+	mutex_unlock(&cgroup_tree_mutex);
+	return ret;
+}
+
+/**
+ * cgroup_add_cftypes - add an array of cftypes to a subsystem
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Register @cfts to @ss.  Files described by @cfts are created for all
+ * existing cgroups to which @ss is attached and all future cgroups will
+ * have them too.  This function can be called anytime whether @ss is
+ * attached or not.
+ *
+ * Returns 0 on successful registration, -errno on failure.  Note that this
+ * function currently returns 0 as long as @cfts registration is successful
+ * even if some file creation attempts on existing cgroups fail.
+ */
+int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+{
+	int ret;
 
-	cgroup_cfts_prepare();
+	if (!cfts || cfts[0].name[0] == '\0')
+		return 0;
 
-	list_for_each_entry(set, &cfts[0].ss->cftsets, node) {
-		if (set->cfts == cfts) {
-			list_del(&set->node);
-			kfree(set);
-			cgroup_cfts_commit(cfts, false);
-			return 0;
-		}
-	}
+	ret = cgroup_init_cftypes(ss, cfts);
+	if (ret)
+		return ret;
+
+	mutex_lock(&cgroup_tree_mutex);
+
+	list_add_tail(&cfts->node, &ss->cfts);
+	ret = cgroup_apply_cftypes(cfts, true);
+	if (ret)
+		cgroup_rm_cftypes_locked(cfts);
 
-	cgroup_cfts_commit(NULL, false);
-	return -ENOENT;
+	mutex_unlock(&cgroup_tree_mutex);
+	return ret;
 }
 
 /**
@@ -2868,57 +2494,18 @@ int cgroup_rm_cftypes(struct cftype *cfts)
  *
  * Return the number of tasks in the cgroup.
  */
-int cgroup_task_count(const struct cgroup *cgrp)
+static int cgroup_task_count(const struct cgroup *cgrp)
 {
 	int count = 0;
 	struct cgrp_cset_link *link;
 
-	read_lock(&css_set_lock);
+	down_read(&css_set_rwsem);
 	list_for_each_entry(link, &cgrp->cset_links, cset_link)
 		count += atomic_read(&link->cset->refcount);
-	read_unlock(&css_set_lock);
+	up_read(&css_set_rwsem);
 	return count;
 }
 
-/*
- * To reduce the fork() overhead for systems that are not actually using
- * their cgroups capability, we don't maintain the lists running through
- * each css_set to its tasks until we see the list actually used - in other
- * words after the first call to css_task_iter_start().
- */
-static void cgroup_enable_task_cg_lists(void)
-{
-	struct task_struct *p, *g;
-	write_lock(&css_set_lock);
-	use_task_css_set_links = 1;
-	/*
-	 * We need tasklist_lock because RCU is not safe against
-	 * while_each_thread(). Besides, a forking task that has passed
-	 * cgroup_post_fork() without seeing use_task_css_set_links = 1
-	 * is not guaranteed to have its child immediately visible in the
-	 * tasklist if we walk through it with RCU.
-	 */
-	read_lock(&tasklist_lock);
-	do_each_thread(g, p) {
-		task_lock(p);
-		/*
-		 * We should check if the process is exiting, otherwise
-		 * it will race with cgroup_exit() in that the list
-		 * entry won't be deleted though the process has exited.
-		 * Do it while holding siglock so that we don't end up
-		 * racing against cgroup_exit().
-		 */
-		spin_lock_irq(&p->sighand->siglock);
-		if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
-			list_add(&p->cg_list, &task_css_set(p)->tasks);
-		spin_unlock_irq(&p->sighand->siglock);
-
-		task_unlock(p);
-	} while_each_thread(g, p);
-	read_unlock(&tasklist_lock);
-	write_unlock(&css_set_lock);
-}
-
 /**
  * css_next_child - find the next child of a given css
  * @pos_css: the current position (%NULL to initiate traversal)
@@ -2937,7 +2524,7 @@ css_next_child(struct cgroup_subsys_state *pos_css,
 	struct cgroup *cgrp = parent_css->cgroup;
 	struct cgroup *next;
 
-	cgroup_assert_mutex_or_rcu_locked();
+	cgroup_assert_mutexes_or_rcu_locked();
 
 	/*
 	 * @pos could already have been removed.  Once a cgroup is removed,
@@ -2973,7 +2560,6 @@ css_next_child(struct cgroup_subsys_state *pos_css,
 
 	return cgroup_css(next, parent_css->ss);
 }
-EXPORT_SYMBOL_GPL(css_next_child);
 
 /**
  * css_next_descendant_pre - find the next descendant for pre-order walk
@@ -2995,7 +2581,7 @@ css_next_descendant_pre(struct cgroup_subsys_state *pos,
 {
 	struct cgroup_subsys_state *next;
 
-	cgroup_assert_mutex_or_rcu_locked();
+	cgroup_assert_mutexes_or_rcu_locked();
 
 	/* if first iteration, visit @root */
 	if (!pos)
@@ -3016,7 +2602,6 @@ css_next_descendant_pre(struct cgroup_subsys_state *pos,
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(css_next_descendant_pre);
 
 /**
  * css_rightmost_descendant - return the rightmost descendant of a css
@@ -3036,7 +2621,7 @@ css_rightmost_descendant(struct cgroup_subsys_state *pos)
 {
 	struct cgroup_subsys_state *last, *tmp;
 
-	cgroup_assert_mutex_or_rcu_locked();
+	cgroup_assert_mutexes_or_rcu_locked();
 
 	do {
 		last = pos;
@@ -3048,7 +2633,6 @@ css_rightmost_descendant(struct cgroup_subsys_state *pos)
 
 	return last;
 }
-EXPORT_SYMBOL_GPL(css_rightmost_descendant);
 
 static struct cgroup_subsys_state *
 css_leftmost_descendant(struct cgroup_subsys_state *pos)
@@ -3084,7 +2668,7 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
 {
 	struct cgroup_subsys_state *next;
 
-	cgroup_assert_mutex_or_rcu_locked();
+	cgroup_assert_mutexes_or_rcu_locked();
 
 	/* if first iteration, visit leftmost descendant which may be @root */
 	if (!pos)
@@ -3102,7 +2686,6 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
 	/* no sibling left, visit parent */
 	return css_parent(pos);
 }
-EXPORT_SYMBOL_GPL(css_next_descendant_post);
 
 /**
  * css_advance_task_iter - advance a task itererator to the next css_set
@@ -3125,9 +2708,14 @@ static void css_advance_task_iter(struct css_task_iter *it)
 		}
 		link = list_entry(l, struct cgrp_cset_link, cset_link);
 		cset = link->cset;
-	} while (list_empty(&cset->tasks));
+	} while (list_empty(&cset->tasks) && list_empty(&cset->mg_tasks));
+
 	it->cset_link = l;
-	it->task = cset->tasks.next;
+
+	if (!list_empty(&cset->tasks))
+		it->task = cset->tasks.next;
+	else
+		it->task = cset->mg_tasks.next;
 }
 
 /**
@@ -3146,17 +2734,12 @@ static void css_advance_task_iter(struct css_task_iter *it)
  */
 void css_task_iter_start(struct cgroup_subsys_state *css,
 			 struct css_task_iter *it)
-	__acquires(css_set_lock)
+	__acquires(css_set_rwsem)
 {
-	/*
-	 * The first time anyone tries to iterate across a css, we need to
-	 * enable the list linking each css_set to its tasks, and fix up
-	 * all existing tasks.
-	 */
-	if (!use_task_css_set_links)
-		cgroup_enable_task_cg_lists();
+	/* no one should try to iterate before mounting cgroups */
+	WARN_ON_ONCE(!use_task_css_set_links);
 
-	read_lock(&css_set_lock);
+	down_read(&css_set_rwsem);
 
 	it->origin_css = css;
 	it->cset_link = &css->cgroup->cset_links;
@@ -3172,223 +2755,99 @@ void css_task_iter_start(struct cgroup_subsys_state *css,
  * initialized via css_task_iter_start().  Returns NULL when the iteration
  * reaches the end.
  */
-struct task_struct *css_task_iter_next(struct css_task_iter *it)
-{
-	struct task_struct *res;
-	struct list_head *l = it->task;
-	struct cgrp_cset_link *link;
-
-	/* If the iterator cg is NULL, we have no tasks */
-	if (!it->cset_link)
-		return NULL;
-	res = list_entry(l, struct task_struct, cg_list);
-	/* Advance iterator to find next entry */
-	l = l->next;
-	link = list_entry(it->cset_link, struct cgrp_cset_link, cset_link);
-	if (l == &link->cset->tasks) {
-		/*
-		 * We reached the end of this task list - move on to the
-		 * next cgrp_cset_link.
-		 */
-		css_advance_task_iter(it);
-	} else {
-		it->task = l;
-	}
-	return res;
-}
-
-/**
- * css_task_iter_end - finish task iteration
- * @it: the task iterator to finish
- *
- * Finish task iteration started by css_task_iter_start().
- */
-void css_task_iter_end(struct css_task_iter *it)
-	__releases(css_set_lock)
-{
-	read_unlock(&css_set_lock);
-}
-
-static inline int started_after_time(struct task_struct *t1,
-				     struct timespec *time,
-				     struct task_struct *t2)
-{
-	int start_diff = timespec_compare(&t1->start_time, time);
-	if (start_diff > 0) {
-		return 1;
-	} else if (start_diff < 0) {
-		return 0;
-	} else {
-		/*
-		 * Arbitrarily, if two processes started at the same
-		 * time, we'll say that the lower pointer value
-		 * started first. Note that t2 may have exited by now
-		 * so this may not be a valid pointer any longer, but
-		 * that's fine - it still serves to distinguish
-		 * between two tasks started (effectively) simultaneously.
-		 */
-		return t1 > t2;
-	}
-}
-
-/*
- * This function is a callback from heap_insert() and is used to order
- * the heap.
- * In this case we order the heap in descending task start time.
- */
-static inline int started_after(void *p1, void *p2)
-{
-	struct task_struct *t1 = p1;
-	struct task_struct *t2 = p2;
-	return started_after_time(t1, &t2->start_time, t2);
-}
-
-/**
- * css_scan_tasks - iterate though all the tasks in a css
- * @css: the css to iterate tasks of
- * @test: optional test callback
- * @process: process callback
- * @data: data passed to @test and @process
- * @heap: optional pre-allocated heap used for task iteration
- *
- * Iterate through all the tasks in @css, calling @test for each, and if it
- * returns %true, call @process for it also.
- *
- * @test may be NULL, meaning always true (select all tasks), which
- * effectively duplicates css_task_iter_{start,next,end}() but does not
- * lock css_set_lock for the call to @process.
- *
- * It is guaranteed that @process will act on every task that is a member
- * of @css for the duration of this call.  This function may or may not
- * call @process for tasks that exit or move to a different css during the
- * call, or are forked or move into the css during the call.
- *
- * Note that @test may be called with locks held, and may in some
- * situations be called multiple times for the same task, so it should be
- * cheap.
- *
- * If @heap is non-NULL, a heap has been pre-allocated and will be used for
- * heap operations (and its "gt" member will be overwritten), else a
- * temporary heap will be used (allocation of which may cause this function
- * to fail).
- */
-int css_scan_tasks(struct cgroup_subsys_state *css,
-		   bool (*test)(struct task_struct *, void *),
-		   void (*process)(struct task_struct *, void *),
-		   void *data, struct ptr_heap *heap)
-{
-	int retval, i;
-	struct css_task_iter it;
-	struct task_struct *p, *dropped;
-	/* Never dereference latest_task, since it's not refcounted */
-	struct task_struct *latest_task = NULL;
-	struct ptr_heap tmp_heap;
-	struct timespec latest_time = { 0, 0 };
-
-	if (heap) {
-		/* The caller supplied our heap and pre-allocated its memory */
-		heap->gt = &started_after;
-	} else {
-		/* We need to allocate our own heap memory */
-		heap = &tmp_heap;
-		retval = heap_init(heap, PAGE_SIZE, GFP_KERNEL, &started_after);
-		if (retval)
-			/* cannot allocate the heap */
-			return retval;
-	}
-
- again:
-	/*
-	 * Scan tasks in the css, using the @test callback to determine
-	 * which are of interest, and invoking @process callback on the
-	 * ones which need an update.  Since we don't want to hold any
-	 * locks during the task updates, gather tasks to be processed in a
-	 * heap structure.  The heap is sorted by descending task start
-	 * time.  If the statically-sized heap fills up, we overflow tasks
-	 * that started later, and in future iterations only consider tasks
-	 * that started after the latest task in the previous pass. This
-	 * guarantees forward progress and that we don't miss any tasks.
-	 */
-	heap->size = 0;
-	css_task_iter_start(css, &it);
-	while ((p = css_task_iter_next(&it))) {
-		/*
-		 * Only affect tasks that qualify per the caller's callback,
-		 * if he provided one
-		 */
-		if (test && !test(p, data))
-			continue;
-		/*
-		 * Only process tasks that started after the last task
-		 * we processed
-		 */
-		if (!started_after_time(p, &latest_time, latest_task))
-			continue;
-		dropped = heap_insert(heap, p);
-		if (dropped == NULL) {
-			/*
-			 * The new task was inserted; the heap wasn't
-			 * previously full
-			 */
-			get_task_struct(p);
-		} else if (dropped != p) {
-			/*
-			 * The new task was inserted, and pushed out a
-			 * different task
-			 */
-			get_task_struct(p);
-			put_task_struct(dropped);
-		}
-		/*
-		 * Else the new task was newer than anything already in
-		 * the heap and wasn't inserted
-		 */
-	}
-	css_task_iter_end(&it);
+struct task_struct *css_task_iter_next(struct css_task_iter *it)
+{
+	struct task_struct *res;
+	struct list_head *l = it->task;
+	struct cgrp_cset_link *link = list_entry(it->cset_link,
+					struct cgrp_cset_link, cset_link);
 
-	if (heap->size) {
-		for (i = 0; i < heap->size; i++) {
-			struct task_struct *q = heap->ptrs[i];
-			if (i == 0) {
-				latest_time = q->start_time;
-				latest_task = q;
-			}
-			/* Process the task per the caller's callback */
-			process(q, data);
-			put_task_struct(q);
-		}
-		/*
-		 * If we had to process any tasks at all, scan again
-		 * in case some of them were in the middle of forking
-		 * children that didn't get processed.
-		 * Not the most efficient way to do it, but it avoids
-		 * having to take callback_mutex in the fork path
-		 */
-		goto again;
-	}
-	if (heap == &tmp_heap)
-		heap_free(&tmp_heap);
-	return 0;
+	/* If the iterator cg is NULL, we have no tasks */
+	if (!it->cset_link)
+		return NULL;
+	res = list_entry(l, struct task_struct, cg_list);
+
+	/*
+	 * Advance iterator to find next entry.  cset->tasks is consumed
+	 * first and then ->mg_tasks.  After ->mg_tasks, we move onto the
+	 * next cset.
+	 */
+	l = l->next;
+
+	if (l == &link->cset->tasks)
+		l = link->cset->mg_tasks.next;
+
+	if (l == &link->cset->mg_tasks)
+		css_advance_task_iter(it);
+	else
+		it->task = l;
+
+	return res;
 }
 
-static void cgroup_transfer_one_task(struct task_struct *task, void *data)
+/**
+ * css_task_iter_end - finish task iteration
+ * @it: the task iterator to finish
+ *
+ * Finish task iteration started by css_task_iter_start().
+ */
+void css_task_iter_end(struct css_task_iter *it)
+	__releases(css_set_rwsem)
 {
-	struct cgroup *new_cgroup = data;
-
-	mutex_lock(&cgroup_mutex);
-	cgroup_attach_task(new_cgroup, task, false);
-	mutex_unlock(&cgroup_mutex);
+	up_read(&css_set_rwsem);
 }
 
 /**
  * cgroup_trasnsfer_tasks - move tasks from one cgroup to another
  * @to: cgroup to which the tasks will be moved
  * @from: cgroup in which the tasks currently reside
+ *
+ * Locking rules between cgroup_post_fork() and the migration path
+ * guarantee that, if a task is forking while being migrated, the new child
+ * is guaranteed to be either visible in the source cgroup after the
+ * parent's migration is complete or put into the target cgroup.  No task
+ * can slip out of migration through forking.
  */
 int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
 {
-	return css_scan_tasks(&from->dummy_css, NULL, cgroup_transfer_one_task,
-			      to, NULL);
+	LIST_HEAD(preloaded_csets);
+	struct cgrp_cset_link *link;
+	struct css_task_iter it;
+	struct task_struct *task;
+	int ret;
+
+	mutex_lock(&cgroup_mutex);
+
+	/* all tasks in @from are being moved, all csets are source */
+	down_read(&css_set_rwsem);
+	list_for_each_entry(link, &from->cset_links, cset_link)
+		cgroup_migrate_add_src(link->cset, to, &preloaded_csets);
+	up_read(&css_set_rwsem);
+
+	ret = cgroup_migrate_prepare_dst(to, &preloaded_csets);
+	if (ret)
+		goto out_err;
+
+	/*
+	 * Migrate tasks one-by-one until @form is empty.  This fails iff
+	 * ->can_attach() fails.
+	 */
+	do {
+		css_task_iter_start(&from->dummy_css, &it);
+		task = css_task_iter_next(&it);
+		if (task)
+			get_task_struct(task);
+		css_task_iter_end(&it);
+
+		if (task) {
+			ret = cgroup_migrate(to, task, false);
+			put_task_struct(task);
+		}
+	} while (task && !ret);
+out_err:
+	cgroup_migrate_finish(&preloaded_csets);
+	mutex_unlock(&cgroup_mutex);
+	return ret;
 }
 
 /*
@@ -3687,21 +3146,31 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
  */
 int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
 {
-	int ret = -EINVAL;
+	struct kernfs_node *kn = kernfs_node_from_dentry(dentry);
 	struct cgroup *cgrp;
 	struct css_task_iter it;
 	struct task_struct *tsk;
 
+	/* it should be kernfs_node belonging to cgroupfs and is a directory */
+	if (dentry->d_sb->s_type != &cgroup_fs_type || !kn ||
+	    kernfs_type(kn) != KERNFS_DIR)
+		return -EINVAL;
+
+	mutex_lock(&cgroup_mutex);
+
 	/*
-	 * Validate dentry by checking the superblock operations,
-	 * and make sure it's a directory.
+	 * We aren't being called from kernfs and there's no guarantee on
+	 * @kn->priv's validity.  For this and css_tryget_from_dir(),
+	 * @kn->priv is RCU safe.  Let's do the RCU dancing.
 	 */
-	if (dentry->d_sb->s_op != &cgroup_ops ||
-	    !S_ISDIR(dentry->d_inode->i_mode))
-		 goto err;
-
-	ret = 0;
-	cgrp = dentry->d_fsdata;
+	rcu_read_lock();
+	cgrp = rcu_dereference(kn->priv);
+	if (!cgrp || cgroup_is_dead(cgrp)) {
+		rcu_read_unlock();
+		mutex_unlock(&cgroup_mutex);
+		return -ENOENT;
+	}
+	rcu_read_unlock();
 
 	css_task_iter_start(&cgrp->dummy_css, &it);
 	while ((tsk = css_task_iter_next(&it))) {
@@ -3726,8 +3195,8 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
 	}
 	css_task_iter_end(&it);
 
-err:
-	return ret;
+	mutex_unlock(&cgroup_mutex);
+	return 0;
 }
 
 
@@ -3745,7 +3214,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
 	 * after a seek to the start). Use a binary-search to find the
 	 * next pid to display, if any
 	 */
-	struct cgroup_open_file *of = s->private;
+	struct kernfs_open_file *of = s->private;
 	struct cgroup *cgrp = seq_css(s)->cgroup;
 	struct cgroup_pidlist *l;
 	enum cgroup_filetype type = seq_cft(s)->private;
@@ -3800,7 +3269,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
 
 static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 {
-	struct cgroup_open_file *of = s->private;
+	struct kernfs_open_file *of = s->private;
 	struct cgroup_pidlist *l = of->priv;
 
 	if (l)
@@ -3811,7 +3280,7 @@ static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 
 static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct cgroup_open_file *of = s->private;
+	struct kernfs_open_file *of = s->private;
 	struct cgroup_pidlist *l = of->priv;
 	pid_t *p = v;
 	pid_t *end = l->list + l->length;
@@ -3861,23 +3330,6 @@ static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css,
 	return 0;
 }
 
-/*
- * When dput() is called asynchronously, if umount has been done and
- * then deactivate_super() in cgroup_free_fn() kills the superblock,
- * there's a small window that vfs will see the root dentry with non-zero
- * refcnt and trigger BUG().
- *
- * That's why we hold a reference before dput() and drop it right after.
- */
-static void cgroup_dput(struct cgroup *cgrp)
-{
-	struct super_block *sb = cgrp->root->sb;
-
-	atomic_inc(&sb->s_active);
-	dput(cgrp->dentry);
-	deactivate_super(sb);
-}
-
 static u64 cgroup_clone_children_read(struct cgroup_subsys_state *css,
 				      struct cftype *cft)
 {
@@ -3944,7 +3396,7 @@ static struct cftype cgroup_base_files[] = {
 		.flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
 		.seq_show = cgroup_release_agent_show,
 		.write_string = cgroup_release_agent_write,
-		.max_write_len = PATH_MAX,
+		.max_write_len = PATH_MAX - 1,
 	},
 	{ }	/* terminate */
 };
@@ -3963,13 +3415,13 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
 
 	/* process cftsets of each subsystem */
 	for_each_subsys(ss, i) {
-		struct cftype_set *set;
+		struct cftype *cfts;
 
 		if (!test_bit(i, &subsys_mask))
 			continue;
 
-		list_for_each_entry(set, &ss->cftsets, node) {
-			ret = cgroup_addrm_files(cgrp, set->cfts, true);
+		list_for_each_entry(cfts, &ss->cfts, node) {
+			ret = cgroup_addrm_files(cgrp, cfts, true);
 			if (ret < 0)
 				goto err;
 		}
@@ -4012,7 +3464,7 @@ static void css_free_work_fn(struct work_struct *work)
 		css_put(css->parent);
 
 	css->ss->css_free(css);
-	cgroup_dput(cgrp);
+	cgroup_put(cgrp);
 }
 
 static void css_free_rcu_fn(struct rcu_head *rcu_head)
@@ -4020,10 +3472,6 @@ static void css_free_rcu_fn(struct rcu_head *rcu_head)
 	struct cgroup_subsys_state *css =
 		container_of(rcu_head, struct cgroup_subsys_state, rcu_head);
 
-	/*
-	 * css holds an extra ref to @cgrp->dentry which is put on the last
-	 * css_put().  dput() requires process context which we don't have.
-	 */
 	INIT_WORK(&css->destroy_work, css_free_work_fn);
 	queue_work(cgroup_destroy_wq, &css->destroy_work);
 }
@@ -4033,7 +3481,7 @@ static void css_release(struct percpu_ref *ref)
 	struct cgroup_subsys_state *css =
 		container_of(ref, struct cgroup_subsys_state, refcnt);
 
-	rcu_assign_pointer(css->cgroup->subsys[css->ss->subsys_id], NULL);
+	rcu_assign_pointer(css->cgroup->subsys[css->ss->id], NULL);
 	call_rcu(&css->rcu_head, css_free_rcu_fn);
 }
 
@@ -4058,6 +3506,7 @@ static int online_css(struct cgroup_subsys_state *css)
 	struct cgroup_subsys *ss = css->ss;
 	int ret = 0;
 
+	lockdep_assert_held(&cgroup_tree_mutex);
 	lockdep_assert_held(&cgroup_mutex);
 
 	if (ss->css_online)
@@ -4065,7 +3514,7 @@ static int online_css(struct cgroup_subsys_state *css)
 	if (!ret) {
 		css->flags |= CSS_ONLINE;
 		css->cgroup->nr_css++;
-		rcu_assign_pointer(css->cgroup->subsys[ss->subsys_id], css);
+		rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
 	}
 	return ret;
 }
@@ -4075,6 +3524,7 @@ static void offline_css(struct cgroup_subsys_state *css)
 {
 	struct cgroup_subsys *ss = css->ss;
 
+	lockdep_assert_held(&cgroup_tree_mutex);
 	lockdep_assert_held(&cgroup_mutex);
 
 	if (!(css->flags & CSS_ONLINE))
@@ -4085,7 +3535,7 @@ static void offline_css(struct cgroup_subsys_state *css)
 
 	css->flags &= ~CSS_ONLINE;
 	css->cgroup->nr_css--;
-	RCU_INIT_POINTER(css->cgroup->subsys[ss->subsys_id], css);
+	RCU_INIT_POINTER(css->cgroup->subsys[ss->id], css);
 }
 
 /**
@@ -4103,7 +3553,6 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
 	struct cgroup_subsys_state *css;
 	int err;
 
-	lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
 	lockdep_assert_held(&cgroup_mutex);
 
 	css = ss->css_alloc(cgroup_css(parent, ss));
@@ -4116,7 +3565,7 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
 
 	init_css(css, ss, cgrp);
 
-	err = cgroup_populate_dir(cgrp, 1 << ss->subsys_id);
+	err = cgroup_populate_dir(cgrp, 1 << ss->id);
 	if (err)
 		goto err_free;
 
@@ -4124,7 +3573,7 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
 	if (err)
 		goto err_free;
 
-	dget(cgrp->dentry);
+	cgroup_get(cgrp);
 	css_get(css->parent);
 
 	if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
@@ -4144,35 +3593,27 @@ err_free:
 	return err;
 }
 
-/*
+/**
  * cgroup_create - create a cgroup
  * @parent: cgroup that will be parent of the new cgroup
- * @dentry: dentry of the new cgroup
- * @mode: mode to set on new inode
- *
- * Must be called with the mutex on the parent inode held
+ * @name: name of the new cgroup
+ * @mode: mode to set on new cgroup
  */
-static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
-			     umode_t mode)
+static long cgroup_create(struct cgroup *parent, const char *name,
+			  umode_t mode)
 {
 	struct cgroup *cgrp;
-	struct cgroup_name *name;
 	struct cgroupfs_root *root = parent->root;
 	int ssid, err;
 	struct cgroup_subsys *ss;
-	struct super_block *sb = root->sb;
+	struct kernfs_node *kn;
 
 	/* allocate the cgroup and its ID, 0 is reserved for the root */
 	cgrp = kzalloc(sizeof(*cgrp), GFP_KERNEL);
 	if (!cgrp)
 		return -ENOMEM;
 
-	name = cgroup_alloc_name(dentry);
-	if (!name) {
-		err = -ENOMEM;
-		goto err_free_cgrp;
-	}
-	rcu_assign_pointer(cgrp->name, name);
+	mutex_lock(&cgroup_tree_mutex);
 
 	/*
 	 * Only live parents can have children.  Note that the liveliness
@@ -4183,7 +3624,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	 */
 	if (!cgroup_lock_live_group(parent)) {
 		err = -ENODEV;
-		goto err_free_name;
+		goto err_unlock_tree;
 	}
 
 	/*
@@ -4196,18 +3637,8 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		goto err_unlock;
 	}
 
-	/* Grab a reference on the superblock so the hierarchy doesn't
-	 * get deleted on unmount if there are child cgroups.  This
-	 * can be done outside cgroup_mutex, since the sb can't
-	 * disappear while someone has an open control file on the
-	 * fs */
-	atomic_inc(&sb->s_active);
-
 	init_cgroup_housekeeping(cgrp);
 
-	dentry->d_fsdata = cgrp;
-	cgrp->dentry = dentry;
-
 	cgrp->parent = parent;
 	cgrp->dummy_css.parent = &parent->dummy_css;
 	cgrp->root = parent->root;
@@ -4218,24 +3649,26 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags))
 		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 
+	/* create the directory */
+	kn = kernfs_create_dir(parent->kn, name, mode, cgrp);
+	if (IS_ERR(kn)) {
+		err = PTR_ERR(kn);
+		goto err_free_id;
+	}
+	cgrp->kn = kn;
+
 	/*
-	 * Create directory.  cgroup_create_file() returns with the new
-	 * directory locked on success so that it can be populated without
-	 * dropping cgroup_mutex.
+	 * This extra ref will be put in cgroup_free_fn() and guarantees
+	 * that @cgrp->kn is always accessible.
 	 */
-	err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
-	if (err < 0)
-		goto err_free_id;
-	lockdep_assert_held(&dentry->d_inode->i_mutex);
+	kernfs_get(kn);
 
 	cgrp->serial_nr = cgroup_serial_nr_next++;
 
 	/* allocation complete, commit to creation */
 	list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
-	root->number_of_cgroups++;
-
-	/* hold a ref to the parent's dentry */
-	dget(parent->dentry);
+	atomic_inc(&root->nr_cgrps);
+	cgroup_get(parent);
 
 	/*
 	 * @cgrp is now fully operational.  If something fails after this
@@ -4256,36 +3689,35 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		}
 	}
 
+	kernfs_activate(kn);
+
 	mutex_unlock(&cgroup_mutex);
-	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 
 	return 0;
 
 err_free_id:
 	idr_remove(&root->cgroup_idr, cgrp->id);
-	/* Release the reference count that we took on the superblock */
-	deactivate_super(sb);
 err_unlock:
 	mutex_unlock(&cgroup_mutex);
-err_free_name:
-	kfree(rcu_dereference_raw(cgrp->name));
-err_free_cgrp:
+err_unlock_tree:
+	mutex_unlock(&cgroup_tree_mutex);
 	kfree(cgrp);
 	return err;
 
 err_destroy:
 	cgroup_destroy_locked(cgrp);
 	mutex_unlock(&cgroup_mutex);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 	return err;
 }
 
-static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
+			umode_t mode)
 {
-	struct cgroup *c_parent = dentry->d_parent->d_fsdata;
+	struct cgroup *parent = parent_kn->priv;
 
-	/* the vfs holds inode->i_mutex already */
-	return cgroup_create(c_parent, dentry, mode | S_IFDIR);
+	return cgroup_create(parent, name, mode);
 }
 
 /*
@@ -4298,6 +3730,7 @@ static void css_killed_work_fn(struct work_struct *work)
 		container_of(work, struct cgroup_subsys_state, destroy_work);
 	struct cgroup *cgrp = css->cgroup;
 
+	mutex_lock(&cgroup_tree_mutex);
 	mutex_lock(&cgroup_mutex);
 
 	/*
@@ -4315,6 +3748,7 @@ static void css_killed_work_fn(struct work_struct *work)
 		cgroup_destroy_css_killed(cgrp);
 
 	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 
 	/*
 	 * Put the css refs from kill_css().  Each css holds an extra
@@ -4347,7 +3781,11 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
  */
 static void kill_css(struct cgroup_subsys_state *css)
 {
-	cgroup_clear_dir(css->cgroup, 1 << css->ss->subsys_id);
+	/*
+	 * This must happen before css is disassociated with its cgroup.
+	 * See seq_css() for details.
+	 */
+	cgroup_clear_dir(css->cgroup, 1 << css->ss->id);
 
 	/*
 	 * Killing would put the base ref, but we need to keep it alive
@@ -4395,22 +3833,21 @@ static void kill_css(struct cgroup_subsys_state *css)
 static int cgroup_destroy_locked(struct cgroup *cgrp)
 	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
-	struct dentry *d = cgrp->dentry;
-	struct cgroup_subsys_state *css;
 	struct cgroup *child;
+	struct cgroup_subsys_state *css;
 	bool empty;
 	int ssid;
 
-	lockdep_assert_held(&d->d_inode->i_mutex);
+	lockdep_assert_held(&cgroup_tree_mutex);
 	lockdep_assert_held(&cgroup_mutex);
 
 	/*
-	 * css_set_lock synchronizes access to ->cset_links and prevents
-	 * @cgrp from being removed while __put_css_set() is in progress.
+	 * css_set_rwsem synchronizes access to ->cset_links and prevents
+	 * @cgrp from being removed while put_css_set() is in progress.
 	 */
-	read_lock(&css_set_lock);
+	down_read(&css_set_rwsem);
 	empty = list_empty(&cgrp->cset_links);
-	read_unlock(&css_set_lock);
+	up_read(&css_set_rwsem);
 	if (!empty)
 		return -EBUSY;
 
@@ -4433,10 +3870,13 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 	/*
 	 * Initiate massacre of all css's.  cgroup_destroy_css_killed()
 	 * will be invoked to perform the rest of destruction once the
-	 * percpu refs of all css's are confirmed to be killed.
+	 * percpu refs of all css's are confirmed to be killed.  This
+	 * involves removing the subsystem's files, drop cgroup_mutex.
 	 */
+	mutex_unlock(&cgroup_mutex);
 	for_each_css(css, ssid, cgrp)
 		kill_css(css);
+	mutex_lock(&cgroup_mutex);
 
 	/*
 	 * Mark @cgrp dead.  This prevents further task migration and child
@@ -4462,14 +3902,20 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 	if (!cgrp->nr_css)
 		cgroup_destroy_css_killed(cgrp);
 
+	/* remove @cgrp directory along with the base files */
+	mutex_unlock(&cgroup_mutex);
+
 	/*
-	 * Clear the base files and remove @cgrp directory.  The removal
-	 * puts the base ref but we aren't quite done with @cgrp yet, so
-	 * hold onto it.
+	 * There are two control paths which try to determine cgroup from
+	 * dentry without going through kernfs - cgroupstats_build() and
+	 * css_tryget_from_dir().  Those are supported by RCU protecting
+	 * clearing of cgrp->kn->priv backpointer, which should happen
+	 * after all files under it have been removed.
 	 */
-	cgroup_addrm_files(cgrp, cgroup_base_files, false);
-	dget(d);
-	cgroup_d_remove_dir(d);
+	kernfs_remove(cgrp->kn);	/* @cgrp has an extra ref on its kn */
+	RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL);
+
+	mutex_lock(&cgroup_mutex);
 
 	return 0;
 };
@@ -4486,59 +3932,69 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 static void cgroup_destroy_css_killed(struct cgroup *cgrp)
 {
 	struct cgroup *parent = cgrp->parent;
-	struct dentry *d = cgrp->dentry;
 
+	lockdep_assert_held(&cgroup_tree_mutex);
 	lockdep_assert_held(&cgroup_mutex);
 
 	/* delete this cgroup from parent->children */
 	list_del_rcu(&cgrp->sibling);
 
-	dput(d);
+	cgroup_put(cgrp);
 
 	set_bit(CGRP_RELEASABLE, &parent->flags);
 	check_for_release(parent);
 }
 
-static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
+static int cgroup_rmdir(struct kernfs_node *kn)
 {
-	int ret;
-
-	mutex_lock(&cgroup_mutex);
-	ret = cgroup_destroy_locked(dentry->d_fsdata);
-	mutex_unlock(&cgroup_mutex);
+	struct cgroup *cgrp = kn->priv;
+	int ret = 0;
 
-	return ret;
-}
+	/*
+	 * This is self-destruction but @kn can't be removed while this
+	 * callback is in progress.  Let's break active protection.  Once
+	 * the protection is broken, @cgrp can be destroyed at any point.
+	 * Pin it so that it stays accessible.
+	 */
+	cgroup_get(cgrp);
+	kernfs_break_active_protection(kn);
 
-static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
-{
-	INIT_LIST_HEAD(&ss->cftsets);
+	mutex_lock(&cgroup_tree_mutex);
+	mutex_lock(&cgroup_mutex);
 
 	/*
-	 * base_cftset is embedded in subsys itself, no need to worry about
-	 * deregistration.
+	 * @cgrp might already have been destroyed while we're trying to
+	 * grab the mutexes.
 	 */
-	if (ss->base_cftypes) {
-		struct cftype *cft;
+	if (!cgroup_is_dead(cgrp))
+		ret = cgroup_destroy_locked(cgrp);
 
-		for (cft = ss->base_cftypes; cft->name[0] != '\0'; cft++)
-			cft->ss = ss;
+	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 
-		ss->base_cftset.cfts = ss->base_cftypes;
-		list_add_tail(&ss->base_cftset.node, &ss->cftsets);
-	}
+	kernfs_unbreak_active_protection(kn);
+	cgroup_put(cgrp);
+	return ret;
 }
 
+static struct kernfs_syscall_ops cgroup_kf_syscall_ops = {
+	.remount_fs		= cgroup_remount,
+	.show_options		= cgroup_show_options,
+	.mkdir			= cgroup_mkdir,
+	.rmdir			= cgroup_rmdir,
+	.rename			= cgroup_rename,
+};
+
 static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 {
 	struct cgroup_subsys_state *css;
 
 	printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
 
+	mutex_lock(&cgroup_tree_mutex);
 	mutex_lock(&cgroup_mutex);
 
-	/* init base cftset */
-	cgroup_init_cftsets(ss);
+	INIT_LIST_HEAD(&ss->cfts);
 
 	/* Create the top cgroup state for this subsystem */
 	ss->root = &cgroup_dummy_root;
@@ -4551,7 +4007,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 	 * pointer to this state - since the subsystem is
 	 * newly registered, all tasks and hence the
 	 * init_css_set is in the subsystem's top cgroup. */
-	init_css_set.subsys[ss->subsys_id] = css;
+	init_css_set.subsys[ss->id] = css;
 
 	need_forkexit_callback |= ss->fork || ss->exit;
 
@@ -4563,184 +4019,8 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 	BUG_ON(online_css(css));
 
 	mutex_unlock(&cgroup_mutex);
-
-	/* this function shouldn't be used with modular subsystems, since they
-	 * need to register a subsys_id, among other things */
-	BUG_ON(ss->module);
-}
-
-/**
- * cgroup_load_subsys: load and register a modular subsystem at runtime
- * @ss: the subsystem to load
- *
- * This function should be called in a modular subsystem's initcall. If the
- * subsystem is built as a module, it will be assigned a new subsys_id and set
- * up for use. If the subsystem is built-in anyway, work is delegated to the
- * simpler cgroup_init_subsys.
- */
-int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
-{
-	struct cgroup_subsys_state *css;
-	int i, ret;
-	struct hlist_node *tmp;
-	struct css_set *cset;
-	unsigned long key;
-
-	/* check name and function validity */
-	if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
-	    ss->css_alloc == NULL || ss->css_free == NULL)
-		return -EINVAL;
-
-	/*
-	 * we don't support callbacks in modular subsystems. this check is
-	 * before the ss->module check for consistency; a subsystem that could
-	 * be a module should still have no callbacks even if the user isn't
-	 * compiling it as one.
-	 */
-	if (ss->fork || ss->exit)
-		return -EINVAL;
-
-	/*
-	 * an optionally modular subsystem is built-in: we want to do nothing,
-	 * since cgroup_init_subsys will have already taken care of it.
-	 */
-	if (ss->module == NULL) {
-		/* a sanity check */
-		BUG_ON(cgroup_subsys[ss->subsys_id] != ss);
-		return 0;
-	}
-
-	/* init base cftset */
-	cgroup_init_cftsets(ss);
-
-	mutex_lock(&cgroup_mutex);
-	mutex_lock(&cgroup_root_mutex);
-	cgroup_subsys[ss->subsys_id] = ss;
-
-	/*
-	 * no ss->css_alloc seems to need anything important in the ss
-	 * struct, so this can happen first (i.e. before the dummy root
-	 * attachment).
-	 */
-	css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
-	if (IS_ERR(css)) {
-		/* failure case - need to deassign the cgroup_subsys[] slot. */
-		cgroup_subsys[ss->subsys_id] = NULL;
-		mutex_unlock(&cgroup_root_mutex);
-		mutex_unlock(&cgroup_mutex);
-		return PTR_ERR(css);
-	}
-
-	ss->root = &cgroup_dummy_root;
-
-	/* our new subsystem will be attached to the dummy hierarchy. */
-	init_css(css, ss, cgroup_dummy_top);
-
-	/*
-	 * Now we need to entangle the css into the existing css_sets. unlike
-	 * in cgroup_init_subsys, there are now multiple css_sets, so each one
-	 * will need a new pointer to it; done by iterating the css_set_table.
-	 * furthermore, modifying the existing css_sets will corrupt the hash
-	 * table state, so each changed css_set will need its hash recomputed.
-	 * this is all done under the css_set_lock.
-	 */
-	write_lock(&css_set_lock);
-	hash_for_each_safe(css_set_table, i, tmp, cset, hlist) {
-		/* skip entries that we already rehashed */
-		if (cset->subsys[ss->subsys_id])
-			continue;
-		/* remove existing entry */
-		hash_del(&cset->hlist);
-		/* set new value */
-		cset->subsys[ss->subsys_id] = css;
-		/* recompute hash and restore entry */
-		key = css_set_hash(cset->subsys);
-		hash_add(css_set_table, &cset->hlist, key);
-	}
-	write_unlock(&css_set_lock);
-
-	ret = online_css(css);
-	if (ret) {
-		ss->css_free(css);
-		goto err_unload;
-	}
-
-	/* success! */
-	mutex_unlock(&cgroup_root_mutex);
-	mutex_unlock(&cgroup_mutex);
-	return 0;
-
-err_unload:
-	mutex_unlock(&cgroup_root_mutex);
-	mutex_unlock(&cgroup_mutex);
-	/* @ss can't be mounted here as try_module_get() would fail */
-	cgroup_unload_subsys(ss);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(cgroup_load_subsys);
-
-/**
- * cgroup_unload_subsys: unload a modular subsystem
- * @ss: the subsystem to unload
- *
- * This function should be called in a modular subsystem's exitcall. When this
- * function is invoked, the refcount on the subsystem's module will be 0, so
- * the subsystem will not be attached to any hierarchy.
- */
-void cgroup_unload_subsys(struct cgroup_subsys *ss)
-{
-	struct cgrp_cset_link *link;
-	struct cgroup_subsys_state *css;
-
-	BUG_ON(ss->module == NULL);
-
-	/*
-	 * we shouldn't be called if the subsystem is in use, and the use of
-	 * try_module_get() in rebind_subsystems() should ensure that it
-	 * doesn't start being used while we're killing it off.
-	 */
-	BUG_ON(ss->root != &cgroup_dummy_root);
-
-	mutex_lock(&cgroup_mutex);
-	mutex_lock(&cgroup_root_mutex);
-
-	css = cgroup_css(cgroup_dummy_top, ss);
-	if (css)
-		offline_css(css);
-
-	/* deassign the subsys_id */
-	cgroup_subsys[ss->subsys_id] = NULL;
-
-	/*
-	 * disentangle the css from all css_sets attached to the dummy
-	 * top. as in loading, we need to pay our respects to the hashtable
-	 * gods.
-	 */
-	write_lock(&css_set_lock);
-	list_for_each_entry(link, &cgroup_dummy_top->cset_links, cset_link) {
-		struct css_set *cset = link->cset;
-		unsigned long key;
-
-		hash_del(&cset->hlist);
-		cset->subsys[ss->subsys_id] = NULL;
-		key = css_set_hash(cset->subsys);
-		hash_add(css_set_table, &cset->hlist, key);
-	}
-	write_unlock(&css_set_lock);
-
-	/*
-	 * remove subsystem's css from the cgroup_dummy_top and free it -
-	 * need to free before marking as null because ss->css_free needs
-	 * the cgrp->subsys pointer to find their state.
-	 */
-	if (css)
-		ss->css_free(css);
-	RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
-
-	mutex_unlock(&cgroup_root_mutex);
-	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgroup_tree_mutex);
 }
-EXPORT_SYMBOL_GPL(cgroup_unload_subsys);
 
 /**
  * cgroup_init_early - cgroup initialization at system boot
@@ -4756,6 +4036,9 @@ int __init cgroup_init_early(void)
 	atomic_set(&init_css_set.refcount, 1);
 	INIT_LIST_HEAD(&init_css_set.cgrp_links);
 	INIT_LIST_HEAD(&init_css_set.tasks);
+	INIT_LIST_HEAD(&init_css_set.mg_tasks);
+	INIT_LIST_HEAD(&init_css_set.mg_preload_node);
+	INIT_LIST_HEAD(&init_css_set.mg_node);
 	INIT_HLIST_NODE(&init_css_set.hlist);
 	css_set_count = 1;
 	init_cgroup_root(&cgroup_dummy_root);
@@ -4767,17 +4050,16 @@ int __init cgroup_init_early(void)
 	list_add(&init_cgrp_cset_link.cset_link, &cgroup_dummy_top->cset_links);
 	list_add(&init_cgrp_cset_link.cgrp_link, &init_css_set.cgrp_links);
 
-	/* at bootup time, we don't worry about modular subsystems */
-	for_each_builtin_subsys(ss, i) {
-		BUG_ON(!ss->name);
-		BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
-		BUG_ON(!ss->css_alloc);
-		BUG_ON(!ss->css_free);
-		if (ss->subsys_id != i) {
-			printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
-			       ss->name, ss->subsys_id);
-			BUG();
-		}
+	for_each_subsys(ss, i) {
+		WARN(!ss->css_alloc || !ss->css_free || ss->name || ss->id,
+		     "invalid cgroup_subsys %d:%s css_alloc=%p css_free=%p name:id=%d:%s\n",
+		     i, cgroup_subsys_name[i], ss->css_alloc, ss->css_free,
+		     ss->id, ss->name);
+		WARN(strlen(cgroup_subsys_name[i]) > MAX_CGROUP_TYPE_NAMELEN,
+		     "cgroup_subsys_name %s too long\n", cgroup_subsys_name[i]);
+
+		ss->id = i;
+		ss->name = cgroup_subsys_name[i];
 
 		if (ss->early_init)
 			cgroup_init_subsys(ss);
@@ -4797,18 +4079,22 @@ int __init cgroup_init(void)
 	unsigned long key;
 	int i, err;
 
-	err = bdi_init(&cgroup_backing_dev_info);
-	if (err)
-		return err;
+	BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files));
 
-	for_each_builtin_subsys(ss, i) {
+	for_each_subsys(ss, i) {
 		if (!ss->early_init)
 			cgroup_init_subsys(ss);
+
+		/*
+		 * cftype registration needs kmalloc and can't be done
+		 * during early_init.  Register base cftypes separately.
+		 */
+		if (ss->base_cftypes)
+			WARN_ON(cgroup_add_cftypes(ss, ss->base_cftypes));
 	}
 
 	/* allocate id for the dummy hierarchy */
 	mutex_lock(&cgroup_mutex);
-	mutex_lock(&cgroup_root_mutex);
 
 	/* Add init_css_set to the hash table */
 	key = css_set_hash(init_css_set.subsys);
@@ -4820,28 +4106,20 @@ int __init cgroup_init(void)
 			0, 1, GFP_KERNEL);
 	BUG_ON(err < 0);
 
-	mutex_unlock(&cgroup_root_mutex);
 	mutex_unlock(&cgroup_mutex);
 
 	cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
-	if (!cgroup_kobj) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!cgroup_kobj)
+		return -ENOMEM;
 
 	err = register_filesystem(&cgroup_fs_type);
 	if (err < 0) {
 		kobject_put(cgroup_kobj);
-		goto out;
+		return err;
 	}
 
 	proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
-
-out:
-	if (err)
-		bdi_destroy(&cgroup_backing_dev_info);
-
-	return err;
+	return 0;
 }
 
 static int __init cgroup_wq_init(void)
@@ -4873,12 +4151,6 @@ core_initcall(cgroup_wq_init);
  * proc_cgroup_show()
  *  - Print task's cgroup paths into seq_file, one line for each hierarchy
  *  - Used for /proc/<pid>/cgroup.
- *  - No need to task_lock(tsk) on this tsk->cgroup reference, as it
- *    doesn't really matter if tsk->cgroup changes after we read it,
- *    and we take cgroup_mutex, keeping cgroup_attach_task() from changing it
- *    anyway.  No need to check that tsk->cgroup != NULL, thanks to
- *    the_top_cgroup_hack in cgroup_exit(), which sets an exiting tasks
- *    cgroup to top_cgroup.
  */
 
 /* TODO: Use a proper seq_file iterator */
@@ -4886,12 +4158,12 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 {
 	struct pid *pid;
 	struct task_struct *tsk;
-	char *buf;
+	char *buf, *path;
 	int retval;
 	struct cgroupfs_root *root;
 
 	retval = -ENOMEM;
-	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	buf = kmalloc(PATH_MAX, GFP_KERNEL);
 	if (!buf)
 		goto out;
 
@@ -4904,6 +4176,7 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 	retval = 0;
 
 	mutex_lock(&cgroup_mutex);
+	down_read(&css_set_rwsem);
 
 	for_each_active_root(root) {
 		struct cgroup_subsys *ss;
@@ -4919,14 +4192,17 @@ int proc_cgroup_show(struct seq_file *m, void *v)
 				   root->name);
 		seq_putc(m, ':');
 		cgrp = task_cgroup_from_root(tsk, root);
-		retval = cgroup_path(cgrp, buf, PAGE_SIZE);
-		if (retval < 0)
+		path = cgroup_path(cgrp, buf, PATH_MAX);
+		if (!path) {
+			retval = -ENAMETOOLONG;
 			goto out_unlock;
-		seq_puts(m, buf);
+		}
+		seq_puts(m, path);
 		seq_putc(m, '\n');
 	}
 
 out_unlock:
+	up_read(&css_set_rwsem);
 	mutex_unlock(&cgroup_mutex);
 	put_task_struct(tsk);
 out_free:
@@ -4952,7 +4228,7 @@ static int proc_cgroupstats_show(struct seq_file *m, void *v)
 	for_each_subsys(ss, i)
 		seq_printf(m, "%s\t%d\t%d\t%d\n",
 			   ss->name, ss->root->hierarchy_id,
-			   ss->root->number_of_cgroups, !ss->disabled);
+			   atomic_read(&ss->root->nr_cgrps), !ss->disabled);
 
 	mutex_unlock(&cgroup_mutex);
 	return 0;
@@ -4971,27 +4247,16 @@ static const struct file_operations proc_cgroupstats_operations = {
 };
 
 /**
- * cgroup_fork - attach newly forked task to its parents cgroup.
+ * cgroup_fork - initialize cgroup related fields during copy_process()
  * @child: pointer to task_struct of forking parent process.
  *
- * Description: A task inherits its parent's cgroup at fork().
- *
- * A pointer to the shared css_set was automatically copied in
- * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU or cgroup_mutex, so
- * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
- * have already changed current->cgroups, allowing the previously
- * referenced cgroup group to be removed and freed.
- *
- * At the point that cgroup_fork() is called, 'current' is the parent
- * task, and the passed argument 'child' points to the child task.
+ * A task is associated with the init_css_set until cgroup_post_fork()
+ * attaches it to the parent's css_set.  Empty cg_list indicates that
+ * @child isn't holding reference to its css_set.
  */
 void cgroup_fork(struct task_struct *child)
 {
-	task_lock(current);
-	get_css_set(task_css_set(current));
-	child->cgroups = current->cgroups;
-	task_unlock(current);
+	RCU_INIT_POINTER(child->cgroups, &init_css_set);
 	INIT_LIST_HEAD(&child->cg_list);
 }
 
@@ -5011,23 +4276,37 @@ void cgroup_post_fork(struct task_struct *child)
 	int i;
 
 	/*
-	 * use_task_css_set_links is set to 1 before we walk the tasklist
-	 * under the tasklist_lock and we read it here after we added the child
-	 * to the tasklist under the tasklist_lock as well. If the child wasn't
-	 * yet in the tasklist when we walked through it from
-	 * cgroup_enable_task_cg_lists(), then use_task_css_set_links value
-	 * should be visible now due to the paired locking and barriers implied
-	 * by LOCK/UNLOCK: it is written before the tasklist_lock unlock
-	 * in cgroup_enable_task_cg_lists() and read here after the tasklist_lock
-	 * lock on fork.
+	 * This may race against cgroup_enable_task_cg_links().  As that
+	 * function sets use_task_css_set_links before grabbing
+	 * tasklist_lock and we just went through tasklist_lock to add
+	 * @child, it's guaranteed that either we see the set
+	 * use_task_css_set_links or cgroup_enable_task_cg_lists() sees
+	 * @child during its iteration.
+	 *
+	 * If we won the race, @child is associated with %current's
+	 * css_set.  Grabbing css_set_rwsem guarantees both that the
+	 * association is stable, and, on completion of the parent's
+	 * migration, @child is visible in the source of migration or
+	 * already in the destination cgroup.  This guarantee is necessary
+	 * when implementing operations which need to migrate all tasks of
+	 * a cgroup to another.
+	 *
+	 * Note that if we lose to cgroup_enable_task_cg_links(), @child
+	 * will remain in init_css_set.  This is safe because all tasks are
+	 * in the init_css_set before cg_links is enabled and there's no
+	 * operation which transfers all tasks out of init_css_set.
 	 */
 	if (use_task_css_set_links) {
-		write_lock(&css_set_lock);
-		task_lock(child);
-		if (list_empty(&child->cg_list))
-			list_add(&child->cg_list, &task_css_set(child)->tasks);
-		task_unlock(child);
-		write_unlock(&css_set_lock);
+		struct css_set *cset;
+
+		down_write(&css_set_rwsem);
+		cset = task_css_set(current);
+		if (list_empty(&child->cg_list)) {
+			rcu_assign_pointer(child->cgroups, cset);
+			list_add(&child->cg_list, &cset->tasks);
+			get_css_set(cset);
+		}
+		up_write(&css_set_rwsem);
 	}
 
 	/*
@@ -5036,15 +4315,7 @@ void cgroup_post_fork(struct task_struct *child)
 	 * and addition to css_set.
 	 */
 	if (need_forkexit_callback) {
-		/*
-		 * fork/exit callbacks are supported only for builtin
-		 * subsystems, and the builtin section of the subsys
-		 * array is immutable, so we don't need to lock the
-		 * subsys array here. On the other hand, modular section
-		 * of the array can be freed at module unload, so we
-		 * can't touch that.
-		 */
-		for_each_builtin_subsys(ss, i)
+		for_each_subsys(ss, i)
 			if (ss->fork)
 				ss->fork(child);
 	}
@@ -5063,57 +4334,39 @@ void cgroup_post_fork(struct task_struct *child)
  * use notify_on_release cgroups where very high task exit scaling
  * is required on large systems.
  *
- * the_top_cgroup_hack:
- *
- *    Set the exiting tasks cgroup to the root cgroup (top_cgroup).
- *
- *    We call cgroup_exit() while the task is still competent to
- *    handle notify_on_release(), then leave the task attached to the
- *    root cgroup in each hierarchy for the remainder of its exit.
- *
- *    To do this properly, we would increment the reference count on
- *    top_cgroup, and near the very end of the kernel/exit.c do_exit()
- *    code we would add a second cgroup function call, to drop that
- *    reference.  This would just create an unnecessary hot spot on
- *    the top_cgroup reference count, to no avail.
- *
- *    Normally, holding a reference to a cgroup without bumping its
- *    count is unsafe.   The cgroup could go away, or someone could
- *    attach us to a different cgroup, decrementing the count on
- *    the first cgroup that we never incremented.  But in this case,
- *    top_cgroup isn't going away, and either task has PF_EXITING set,
- *    which wards off any cgroup_attach_task() attempts, or task is a failed
- *    fork, never visible to cgroup_attach_task.
+ * We set the exiting tasks cgroup to the root cgroup (top_cgroup).  We
+ * call cgroup_exit() while the task is still competent to handle
+ * notify_on_release(), then leave the task attached to the root cgroup in
+ * each hierarchy for the remainder of its exit.  No need to bother with
+ * init_css_set refcnting.  init_css_set never goes away and we can't race
+ * with migration path - either PF_EXITING is visible to migration path or
+ * @tsk never got on the tasklist.
  */
 void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 {
 	struct cgroup_subsys *ss;
 	struct css_set *cset;
+	bool put_cset = false;
 	int i;
 
 	/*
-	 * Unlink from the css_set task list if necessary.
-	 * Optimistically check cg_list before taking
-	 * css_set_lock
+	 * Unlink from @tsk from its css_set.  As migration path can't race
+	 * with us, we can check cg_list without grabbing css_set_rwsem.
 	 */
 	if (!list_empty(&tsk->cg_list)) {
-		write_lock(&css_set_lock);
-		if (!list_empty(&tsk->cg_list))
-			list_del_init(&tsk->cg_list);
-		write_unlock(&css_set_lock);
+		down_write(&css_set_rwsem);
+		list_del_init(&tsk->cg_list);
+		up_write(&css_set_rwsem);
+		put_cset = true;
 	}
 
 	/* Reassign the task to the init_css_set. */
-	task_lock(tsk);
 	cset = task_css_set(tsk);
 	RCU_INIT_POINTER(tsk->cgroups, &init_css_set);
 
 	if (run_callbacks && need_forkexit_callback) {
-		/*
-		 * fork/exit callbacks are supported only for builtin
-		 * subsystems, see cgroup_post_fork() for details.
-		 */
-		for_each_builtin_subsys(ss, i) {
+		/* see cgroup_post_fork() for details */
+		for_each_subsys(ss, i) {
 			if (ss->exit) {
 				struct cgroup_subsys_state *old_css = cset->subsys[i];
 				struct cgroup_subsys_state *css = task_css(tsk, i);
@@ -5122,9 +4375,9 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 			}
 		}
 	}
-	task_unlock(tsk);
 
-	put_css_set_taskexit(cset);
+	if (put_cset)
+		put_css_set(cset, true);
 }
 
 static void check_for_release(struct cgroup *cgrp)
@@ -5181,16 +4434,17 @@ static void cgroup_release_agent(struct work_struct *work)
 	while (!list_empty(&release_list)) {
 		char *argv[3], *envp[3];
 		int i;
-		char *pathbuf = NULL, *agentbuf = NULL;
+		char *pathbuf = NULL, *agentbuf = NULL, *path;
 		struct cgroup *cgrp = list_entry(release_list.next,
 						    struct cgroup,
 						    release_list);
 		list_del_init(&cgrp->release_list);
 		raw_spin_unlock(&release_list_lock);
-		pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
 		if (!pathbuf)
 			goto continue_free;
-		if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0)
+		path = cgroup_path(cgrp, pathbuf, PATH_MAX);
+		if (!path)
 			goto continue_free;
 		agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
 		if (!agentbuf)
@@ -5198,7 +4452,7 @@ static void cgroup_release_agent(struct work_struct *work)
 
 		i = 0;
 		argv[i++] = agentbuf;
-		argv[i++] = pathbuf;
+		argv[i++] = path;
 		argv[i] = NULL;
 
 		i = 0;
@@ -5232,11 +4486,7 @@ static int __init cgroup_disable(char *str)
 		if (!*token)
 			continue;
 
-		/*
-		 * cgroup_disable, being at boot time, can't know about
-		 * module subsystems, so we don't worry about them.
-		 */
-		for_each_builtin_subsys(ss, i) {
+		for_each_subsys(ss, i) {
 			if (!strcmp(token, ss->name)) {
 				ss->disabled = 1;
 				printk(KERN_INFO "Disabling %s control group"
@@ -5250,28 +4500,42 @@ static int __init cgroup_disable(char *str)
 __setup("cgroup_disable=", cgroup_disable);
 
 /**
- * css_from_dir - get corresponding css from the dentry of a cgroup dir
+ * css_tryget_from_dir - get corresponding css from the dentry of a cgroup dir
  * @dentry: directory dentry of interest
  * @ss: subsystem of interest
  *
- * Must be called under cgroup_mutex or RCU read lock.  The caller is
- * responsible for pinning the returned css if it needs to be accessed
- * outside the critical section.
+ * If @dentry is a directory for a cgroup which has @ss enabled on it, try
+ * to get the corresponding css and return it.  If such css doesn't exist
+ * or can't be pinned, an ERR_PTR value is returned.
  */
-struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
-					 struct cgroup_subsys *ss)
+struct cgroup_subsys_state *css_tryget_from_dir(struct dentry *dentry,
+						struct cgroup_subsys *ss)
 {
+	struct kernfs_node *kn = kernfs_node_from_dentry(dentry);
+	struct cgroup_subsys_state *css = NULL;
 	struct cgroup *cgrp;
 
-	cgroup_assert_mutex_or_rcu_locked();
-
 	/* is @dentry a cgroup dir? */
-	if (!dentry->d_inode ||
-	    dentry->d_inode->i_op != &cgroup_dir_inode_operations)
+	if (dentry->d_sb->s_type != &cgroup_fs_type || !kn ||
+	    kernfs_type(kn) != KERNFS_DIR)
 		return ERR_PTR(-EBADF);
 
-	cgrp = __d_cgrp(dentry);
-	return cgroup_css(cgrp, ss) ?: ERR_PTR(-ENOENT);
+	rcu_read_lock();
+
+	/*
+	 * This path doesn't originate from kernfs and @kn could already
+	 * have been or be removed at any point.  @kn->priv is RCU
+	 * protected for this access.  See destroy_locked() for details.
+	 */
+	cgrp = rcu_dereference(kn->priv);
+	if (cgrp)
+		css = cgroup_css(cgrp, ss);
+
+	if (!css || !css_tryget(css))
+		css = ERR_PTR(-ENOENT);
+
+	rcu_read_unlock();
+	return css;
 }
 
 /**
@@ -5286,7 +4550,7 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
 {
 	struct cgroup *cgrp;
 
-	cgroup_assert_mutex_or_rcu_locked();
+	cgroup_assert_mutexes_or_rcu_locked();
 
 	cgrp = idr_find(&ss->root->cgroup_idr, id);
 	if (cgrp)
@@ -5338,23 +4602,30 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
 {
 	struct cgrp_cset_link *link;
 	struct css_set *cset;
+	char *name_buf;
 
-	read_lock(&css_set_lock);
+	name_buf = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+	if (!name_buf)
+		return -ENOMEM;
+
+	down_read(&css_set_rwsem);
 	rcu_read_lock();
 	cset = rcu_dereference(current->cgroups);
 	list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
 		struct cgroup *c = link->cgrp;
-		const char *name;
+		const char *name = "?";
+
+		if (c != cgroup_dummy_top) {
+			cgroup_name(c, name_buf, NAME_MAX + 1);
+			name = name_buf;
+		}
 
-		if (c->dentry)
-			name = c->dentry->d_name.name;
-		else
-			name = "?";
 		seq_printf(seq, "Root %d group %s\n",
 			   c->root->hierarchy_id, name);
 	}
 	rcu_read_unlock();
-	read_unlock(&css_set_lock);
+	up_read(&css_set_rwsem);
+	kfree(name_buf);
 	return 0;
 }
 
@@ -5364,23 +4635,30 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
 	struct cgroup_subsys_state *css = seq_css(seq);
 	struct cgrp_cset_link *link;
 
-	read_lock(&css_set_lock);
+	down_read(&css_set_rwsem);
 	list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
 		struct css_set *cset = link->cset;
 		struct task_struct *task;
 		int count = 0;
+
 		seq_printf(seq, "css_set %p\n", cset);
+
 		list_for_each_entry(task, &cset->tasks, cg_list) {
-			if (count++ > MAX_TASKS_SHOWN_PER_CSS) {
-				seq_puts(seq, "  ...\n");
-				break;
-			} else {
-				seq_printf(seq, "  task %d\n",
-					   task_pid_vnr(task));
-			}
+			if (count++ > MAX_TASKS_SHOWN_PER_CSS)
+				goto overflow;
+			seq_printf(seq, "  task %d\n", task_pid_vnr(task));
+		}
+
+		list_for_each_entry(task, &cset->mg_tasks, cg_list) {
+			if (count++ > MAX_TASKS_SHOWN_PER_CSS)
+				goto overflow;
+			seq_printf(seq, "  task %d\n", task_pid_vnr(task));
 		}
+		continue;
+	overflow:
+		seq_puts(seq, "  ...\n");
 	}
-	read_unlock(&css_set_lock);
+	up_read(&css_set_rwsem);
 	return 0;
 }
 
@@ -5423,11 +4701,9 @@ static struct cftype debug_files[] =  {
 	{ }	/* terminate */
 };
 
-struct cgroup_subsys debug_subsys = {
-	.name = "debug",
+struct cgroup_subsys debug_cgrp_subsys = {
 	.css_alloc = debug_css_alloc,
 	.css_free = debug_css_free,
-	.subsys_id = debug_subsys_id,
 	.base_cftypes = debug_files,
 };
 #endif /* CONFIG_CGROUP_DEBUG */
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index 6c3154e477f6..2ea98b216bff 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -52,7 +52,7 @@ static inline struct freezer *css_freezer(struct cgroup_subsys_state *css)
 
 static inline struct freezer *task_freezer(struct task_struct *task)
 {
-	return css_freezer(task_css(task, freezer_subsys_id));
+	return css_freezer(task_css(task, freezer_cgrp_id));
 }
 
 static struct freezer *parent_freezer(struct freezer *freezer)
@@ -84,8 +84,6 @@ static const char *freezer_state_strs(unsigned int state)
 	return "THAWED";
 };
 
-struct cgroup_subsys freezer_subsys;
-
 static struct cgroup_subsys_state *
 freezer_css_alloc(struct cgroup_subsys_state *parent_css)
 {
@@ -189,7 +187,7 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
 	 * current state before executing the following - !frozen tasks may
 	 * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
 	 */
-	cgroup_taskset_for_each(task, new_css, tset) {
+	cgroup_taskset_for_each(task, tset) {
 		if (!(freezer->state & CGROUP_FREEZING)) {
 			__thaw_task(task);
 		} else {
@@ -216,6 +214,16 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
 	}
 }
 
+/**
+ * freezer_fork - cgroup post fork callback
+ * @task: a task which has just been forked
+ *
+ * @task has just been created and should conform to the current state of
+ * the cgroup_freezer it belongs to.  This function may race against
+ * freezer_attach().  Losing to freezer_attach() means that we don't have
+ * to do anything as freezer_attach() will put @task into the appropriate
+ * state.
+ */
 static void freezer_fork(struct task_struct *task)
 {
 	struct freezer *freezer;
@@ -224,14 +232,26 @@ static void freezer_fork(struct task_struct *task)
 	freezer = task_freezer(task);
 
 	/*
-	 * The root cgroup is non-freezable, so we can skip the
-	 * following check.
+	 * The root cgroup is non-freezable, so we can skip locking the
+	 * freezer.  This is safe regardless of race with task migration.
+	 * If we didn't race or won, skipping is obviously the right thing
+	 * to do.  If we lost and root is the new cgroup, noop is still the
+	 * right thing to do.
 	 */
 	if (!parent_freezer(freezer))
 		goto out;
 
+	/*
+	 * Grab @freezer->lock and freeze @task after verifying @task still
+	 * belongs to @freezer and it's freezing.  The former is for the
+	 * case where we have raced against task migration and lost and
+	 * @task is already in a different cgroup which may not be frozen.
+	 * This isn't strictly necessary as freeze_task() is allowed to be
+	 * called spuriously but let's do it anyway for, if nothing else,
+	 * documentation.
+	 */
 	spin_lock_irq(&freezer->lock);
-	if (freezer->state & CGROUP_FREEZING)
+	if (freezer == task_freezer(task) && (freezer->state & CGROUP_FREEZING))
 		freeze_task(task);
 	spin_unlock_irq(&freezer->lock);
 out:
@@ -473,13 +493,11 @@ static struct cftype files[] = {
 	{ }	/* terminate */
 };
 
-struct cgroup_subsys freezer_subsys = {
-	.name		= "freezer",
+struct cgroup_subsys freezer_cgrp_subsys = {
 	.css_alloc	= freezer_css_alloc,
 	.css_online	= freezer_css_online,
 	.css_offline	= freezer_css_offline,
 	.css_free	= freezer_css_free,
-	.subsys_id	= freezer_subsys_id,
 	.attach		= freezer_attach,
 	.fork		= freezer_fork,
 	.base_cftypes	= files,
diff --git a/kernel/compat.c b/kernel/compat.c
index 0a09e481b70b..7076b57fa52e 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -30,28 +30,6 @@
 
 #include <asm/uaccess.h>
 
-/*
- * Get/set struct timeval with struct timespec on the native side
- */
-static int compat_get_timeval_convert(struct timespec *o,
-				      struct compat_timeval __user *i)
-{
-	long usec;
-
-	if (get_user(o->tv_sec, &i->tv_sec) ||
-	    get_user(usec, &i->tv_usec))
-		return -EFAULT;
-	o->tv_nsec = usec * 1000;
-	return 0;
-}
-
-static int compat_put_timeval_convert(struct compat_timeval __user *o,
-				      struct timeval *i)
-{
-	return (put_user(i->tv_sec, &o->tv_sec) ||
-		put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
-}
-
 static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
 {
 	memset(txc, 0, sizeof(struct timex));
@@ -116,7 +94,7 @@ asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
 	if (tv) {
 		struct timeval ktv;
 		do_gettimeofday(&ktv);
-		if (compat_put_timeval_convert(tv, &ktv))
+		if (compat_put_timeval(&ktv, tv))
 			return -EFAULT;
 	}
 	if (tz) {
@@ -130,59 +108,58 @@ asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
 asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
 		struct timezone __user *tz)
 {
-	struct timespec kts;
-	struct timezone ktz;
+	struct timeval user_tv;
+	struct timespec	new_ts;
+	struct timezone new_tz;
 
 	if (tv) {
-		if (compat_get_timeval_convert(&kts, tv))
+		if (compat_get_timeval(&user_tv, tv))
 			return -EFAULT;
+		new_ts.tv_sec = user_tv.tv_sec;
+		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
 	}
 	if (tz) {
-		if (copy_from_user(&ktz, tz, sizeof(ktz)))
+		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
 			return -EFAULT;
 	}
 
-	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+	return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
-int get_compat_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
+static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
 {
 	return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
 			__get_user(tv->tv_sec, &ctv->tv_sec) ||
 			__get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
 }
-EXPORT_SYMBOL_GPL(get_compat_timeval);
 
-int put_compat_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
+static int __compat_put_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
 {
 	return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) ||
 			__put_user(tv->tv_sec, &ctv->tv_sec) ||
 			__put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
 }
-EXPORT_SYMBOL_GPL(put_compat_timeval);
 
-int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
+static int __compat_get_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
 	return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
 			__get_user(ts->tv_sec, &cts->tv_sec) ||
 			__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
-EXPORT_SYMBOL_GPL(get_compat_timespec);
 
-int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
+static int __compat_put_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
 {
 	return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
 			__put_user(ts->tv_sec, &cts->tv_sec) ||
 			__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
-EXPORT_SYMBOL_GPL(put_compat_timespec);
 
 int compat_get_timeval(struct timeval *tv, const void __user *utv)
 {
 	if (COMPAT_USE_64BIT_TIME)
 		return copy_from_user(tv, utv, sizeof *tv) ? -EFAULT : 0;
 	else
-		return get_compat_timeval(tv, utv);
+		return __compat_get_timeval(tv, utv);
 }
 EXPORT_SYMBOL_GPL(compat_get_timeval);
 
@@ -191,7 +168,7 @@ int compat_put_timeval(const struct timeval *tv, void __user *utv)
 	if (COMPAT_USE_64BIT_TIME)
 		return copy_to_user(utv, tv, sizeof *tv) ? -EFAULT : 0;
 	else
-		return put_compat_timeval(tv, utv);
+		return __compat_put_timeval(tv, utv);
 }
 EXPORT_SYMBOL_GPL(compat_put_timeval);
 
@@ -200,7 +177,7 @@ int compat_get_timespec(struct timespec *ts, const void __user *uts)
 	if (COMPAT_USE_64BIT_TIME)
 		return copy_from_user(ts, uts, sizeof *ts) ? -EFAULT : 0;
 	else
-		return get_compat_timespec(ts, uts);
+		return __compat_get_timespec(ts, uts);
 }
 EXPORT_SYMBOL_GPL(compat_get_timespec);
 
@@ -209,10 +186,33 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
 	if (COMPAT_USE_64BIT_TIME)
 		return copy_to_user(uts, ts, sizeof *ts) ? -EFAULT : 0;
 	else
-		return put_compat_timespec(ts, uts);
+		return __compat_put_timespec(ts, uts);
 }
 EXPORT_SYMBOL_GPL(compat_put_timespec);
 
+int compat_convert_timespec(struct timespec __user **kts,
+			    const void __user *cts)
+{
+	struct timespec ts;
+	struct timespec __user *uts;
+
+	if (!cts || COMPAT_USE_64BIT_TIME) {
+		*kts = (struct timespec __user *)cts;
+		return 0;
+	}
+
+	uts = compat_alloc_user_space(sizeof(ts));
+	if (!uts)
+		return -EFAULT;
+	if (compat_get_timespec(&ts, cts))
+		return -EFAULT;
+	if (copy_to_user(uts, &ts, sizeof(ts)))
+		return -EFAULT;
+
+	*kts = uts;
+	return 0;
+}
+
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
 	struct compat_timespec __user *rmtp;
@@ -229,7 +229,7 @@ static long compat_nanosleep_restart(struct restart_block *restart)
 	if (ret) {
 		rmtp = restart->nanosleep.compat_rmtp;
 
-		if (rmtp && put_compat_timespec(&rmt, rmtp))
+		if (rmtp && compat_put_timespec(&rmt, rmtp))
 			return -EFAULT;
 	}
 
@@ -243,7 +243,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
 	mm_segment_t oldfs;
 	long ret;
 
-	if (get_compat_timespec(&tu, rqtp))
+	if (compat_get_timespec(&tu, rqtp))
 		return -EFAULT;
 
 	if (!timespec_valid(&tu))
@@ -263,7 +263,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
 		restart->fn = compat_nanosleep_restart;
 		restart->nanosleep.compat_rmtp = rmtp;
 
-		if (rmtp && put_compat_timespec(&rmt, rmtp))
+		if (rmtp && compat_put_timespec(&rmt, rmtp))
 			return -EFAULT;
 	}
 
@@ -451,7 +451,7 @@ asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_old_getrlimit(resource, &r);
+	ret = sys_old_getrlimit(resource, (struct rlimit __user *)&r);
 	set_fs(old_fs);
 
 	if (!ret) {
@@ -647,8 +647,8 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
 int get_compat_itimerspec(struct itimerspec *dst,
 			  const struct compat_itimerspec __user *src)
 {
-	if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
-	    get_compat_timespec(&dst->it_value, &src->it_value))
+	if (__compat_get_timespec(&dst->it_interval, &src->it_interval) ||
+	    __compat_get_timespec(&dst->it_value, &src->it_value))
 		return -EFAULT;
 	return 0;
 }
@@ -656,8 +656,8 @@ int get_compat_itimerspec(struct itimerspec *dst,
 int put_compat_itimerspec(struct compat_itimerspec __user *dst,
 			  const struct itimerspec *src)
 {
-	if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
-	    put_compat_timespec(&src->it_value, &dst->it_value))
+	if (__compat_put_timespec(&src->it_interval, &dst->it_interval) ||
+	    __compat_put_timespec(&src->it_value, &dst->it_value))
 		return -EFAULT;
 	return 0;
 }
@@ -727,7 +727,7 @@ long compat_sys_clock_settime(clockid_t which_clock,
 	mm_segment_t oldfs;
 	struct timespec ts;
 
-	if (get_compat_timespec(&ts, tp))
+	if (compat_get_timespec(&ts, tp))
 		return -EFAULT;
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
@@ -749,7 +749,7 @@ long compat_sys_clock_gettime(clockid_t which_clock,
 	err = sys_clock_gettime(which_clock,
 				(struct timespec __user *) &ts);
 	set_fs(oldfs);
-	if (!err && put_compat_timespec(&ts, tp))
+	if (!err && compat_put_timespec(&ts, tp))
 		return -EFAULT;
 	return err;
 }
@@ -789,7 +789,7 @@ long compat_sys_clock_getres(clockid_t which_clock,
 	err = sys_clock_getres(which_clock,
 			       (struct timespec __user *) &ts);
 	set_fs(oldfs);
-	if (!err && tp && put_compat_timespec(&ts, tp))
+	if (!err && tp && compat_put_timespec(&ts, tp))
 		return -EFAULT;
 	return err;
 }
@@ -799,7 +799,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
 	long err;
 	mm_segment_t oldfs;
 	struct timespec tu;
-	struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp;
+	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
 
 	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
 	oldfs = get_fs();
@@ -808,7 +808,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
 	set_fs(oldfs);
 
 	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    put_compat_timespec(&tu, rmtp))
+	    compat_put_timespec(&tu, rmtp))
 		return -EFAULT;
 
 	if (err == -ERESTART_RESTARTBLOCK) {
@@ -827,7 +827,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 	struct timespec in, out;
 	struct restart_block *restart;
 
-	if (get_compat_timespec(&in, rqtp))
+	if (compat_get_timespec(&in, rqtp))
 		return -EFAULT;
 
 	oldfs = get_fs();
@@ -838,7 +838,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 	set_fs(oldfs);
 
 	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    put_compat_timespec(&out, rmtp))
+	    compat_put_timespec(&out, rmtp))
 		return -EFAULT;
 
 	if (err == -ERESTART_RESTARTBLOCK) {
@@ -1130,7 +1130,7 @@ COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
 	set_fs(KERNEL_DS);
 	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
 	set_fs(old_fs);
-	if (put_compat_timespec(&t, interval))
+	if (compat_put_timespec(&t, interval))
 		return -EFAULT;
 	return ret;
 }
diff --git a/kernel/cpu/Makefile b/kernel/cpu/Makefile
deleted file mode 100644
index 59ab052ef7a0..000000000000
--- a/kernel/cpu/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-y	= idle.o
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c
deleted file mode 100644
index 277f494c2a9a..000000000000
--- a/kernel/cpu/idle.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Generic entry point for the idle threads
- */
-#include <linux/sched.h>
-#include <linux/cpu.h>
-#include <linux/tick.h>
-#include <linux/mm.h>
-#include <linux/stackprotector.h>
-
-#include <asm/tlb.h>
-
-#include <trace/events/power.h>
-
-static int __read_mostly cpu_idle_force_poll;
-
-void cpu_idle_poll_ctrl(bool enable)
-{
-	if (enable) {
-		cpu_idle_force_poll++;
-	} else {
-		cpu_idle_force_poll--;
-		WARN_ON_ONCE(cpu_idle_force_poll < 0);
-	}
-}
-
-#ifdef CONFIG_GENERIC_IDLE_POLL_SETUP
-static int __init cpu_idle_poll_setup(char *__unused)
-{
-	cpu_idle_force_poll = 1;
-	return 1;
-}
-__setup("nohlt", cpu_idle_poll_setup);
-
-static int __init cpu_idle_nopoll_setup(char *__unused)
-{
-	cpu_idle_force_poll = 0;
-	return 1;
-}
-__setup("hlt", cpu_idle_nopoll_setup);
-#endif
-
-static inline int cpu_idle_poll(void)
-{
-	rcu_idle_enter();
-	trace_cpu_idle_rcuidle(0, smp_processor_id());
-	local_irq_enable();
-	while (!tif_need_resched())
-		cpu_relax();
-	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
-	rcu_idle_exit();
-	return 1;
-}
-
-/* Weak implementations for optional arch specific functions */
-void __weak arch_cpu_idle_prepare(void) { }
-void __weak arch_cpu_idle_enter(void) { }
-void __weak arch_cpu_idle_exit(void) { }
-void __weak arch_cpu_idle_dead(void) { }
-void __weak arch_cpu_idle(void)
-{
-	cpu_idle_force_poll = 1;
-	local_irq_enable();
-}
-
-/*
- * Generic idle loop implementation
- */
-static void cpu_idle_loop(void)
-{
-	while (1) {
-		tick_nohz_idle_enter();
-
-		while (!need_resched()) {
-			check_pgt_cache();
-			rmb();
-
-			if (cpu_is_offline(smp_processor_id()))
-				arch_cpu_idle_dead();
-
-			local_irq_disable();
-			arch_cpu_idle_enter();
-
-			/*
-			 * In poll mode we reenable interrupts and spin.
-			 *
-			 * Also if we detected in the wakeup from idle
-			 * path that the tick broadcast device expired
-			 * for us, we don't want to go deep idle as we
-			 * know that the IPI is going to arrive right
-			 * away
-			 */
-			if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
-				cpu_idle_poll();
-			} else {
-				if (!current_clr_polling_and_test()) {
-					stop_critical_timings();
-					rcu_idle_enter();
-					arch_cpu_idle();
-					WARN_ON_ONCE(irqs_disabled());
-					rcu_idle_exit();
-					start_critical_timings();
-				} else {
-					local_irq_enable();
-				}
-				__current_set_polling();
-			}
-			arch_cpu_idle_exit();
-		}
-
-		/*
-		 * Since we fell out of the loop above, we know
-		 * TIF_NEED_RESCHED must be set, propagate it into
-		 * PREEMPT_NEED_RESCHED.
-		 *
-		 * This is required because for polling idle loops we will
-		 * not have had an IPI to fold the state for us.
-		 */
-		preempt_set_need_resched();
-		tick_nohz_idle_exit();
-		schedule_preempt_disabled();
-	}
-}
-
-void cpu_startup_entry(enum cpuhp_state state)
-{
-	/*
-	 * This #ifdef needs to die, but it's too late in the cycle to
-	 * make this generic (arm and sh have never invoked the canary
-	 * init for the non boot cpus!). Will be fixed in 3.11
-	 */
-#ifdef CONFIG_X86
-	/*
-	 * If we're the non-boot CPU, nothing set the stack canary up
-	 * for us. The boot CPU already has it initialized but no harm
-	 * in doing it again. This is a good place for updating it, as
-	 * we wont ever return from this function (so the invalid
-	 * canaries already on the stack wont ever trigger).
-	 */
-	boot_init_stack_canary();
-#endif
-	__current_set_polling();
-	arch_cpu_idle_prepare();
-	cpu_idle_loop();
-}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 4410ac6a55f1..0fe4fbb32f86 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -119,7 +119,7 @@ static inline struct cpuset *css_cs(struct cgroup_subsys_state *css)
 /* Retrieve the cpuset for a task */
 static inline struct cpuset *task_cs(struct task_struct *task)
 {
-	return css_cs(task_css(task, cpuset_subsys_id));
+	return css_cs(task_css(task, cpuset_cgrp_id));
 }
 
 static inline struct cpuset *parent_cs(struct cpuset *cs)
@@ -467,7 +467,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
 	 * be changed to have empty cpus_allowed or mems_allowed.
 	 */
 	ret = -ENOSPC;
-	if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress)) {
+	if ((cgroup_has_tasks(cur->css.cgroup) || cur->attach_in_progress)) {
 		if (!cpumask_empty(cur->cpus_allowed) &&
 		    cpumask_empty(trial->cpus_allowed))
 			goto out;
@@ -829,55 +829,36 @@ static struct cpuset *effective_nodemask_cpuset(struct cpuset *cs)
 }
 
 /**
- * cpuset_change_cpumask - make a task's cpus_allowed the same as its cpuset's
- * @tsk: task to test
- * @data: cpuset to @tsk belongs to
- *
- * Called by css_scan_tasks() for each task in a cgroup whose cpus_allowed
- * mask needs to be changed.
- *
- * We don't need to re-check for the cgroup/cpuset membership, since we're
- * holding cpuset_mutex at this point.
- */
-static void cpuset_change_cpumask(struct task_struct *tsk, void *data)
-{
-	struct cpuset *cs = data;
-	struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
-
-	set_cpus_allowed_ptr(tsk, cpus_cs->cpus_allowed);
-}
-
-/**
  * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
  * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
- * @heap: if NULL, defer allocating heap memory to css_scan_tasks()
- *
- * Called with cpuset_mutex held
  *
- * The css_scan_tasks() function will scan all the tasks in a cgroup,
- * calling callback functions for each.
- *
- * No return value. It's guaranteed that css_scan_tasks() always returns 0
- * if @heap != NULL.
+ * Iterate through each task of @cs updating its cpus_allowed to the
+ * effective cpuset's.  As this function is called with cpuset_mutex held,
+ * cpuset membership stays stable.
  */
-static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap)
+static void update_tasks_cpumask(struct cpuset *cs)
 {
-	css_scan_tasks(&cs->css, NULL, cpuset_change_cpumask, cs, heap);
+	struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
+	struct css_task_iter it;
+	struct task_struct *task;
+
+	css_task_iter_start(&cs->css, &it);
+	while ((task = css_task_iter_next(&it)))
+		set_cpus_allowed_ptr(task, cpus_cs->cpus_allowed);
+	css_task_iter_end(&it);
 }
 
 /*
  * update_tasks_cpumask_hier - Update the cpumasks of tasks in the hierarchy.
  * @root_cs: the root cpuset of the hierarchy
  * @update_root: update root cpuset or not?
- * @heap: the heap used by css_scan_tasks()
  *
  * This will update cpumasks of tasks in @root_cs and all other empty cpusets
  * which take on cpumask of @root_cs.
  *
  * Called with cpuset_mutex held
  */
-static void update_tasks_cpumask_hier(struct cpuset *root_cs,
-				      bool update_root, struct ptr_heap *heap)
+static void update_tasks_cpumask_hier(struct cpuset *root_cs, bool update_root)
 {
 	struct cpuset *cp;
 	struct cgroup_subsys_state *pos_css;
@@ -898,7 +879,7 @@ static void update_tasks_cpumask_hier(struct cpuset *root_cs,
 			continue;
 		rcu_read_unlock();
 
-		update_tasks_cpumask(cp, heap);
+		update_tasks_cpumask(cp);
 
 		rcu_read_lock();
 		css_put(&cp->css);
@@ -914,7 +895,6 @@ static void update_tasks_cpumask_hier(struct cpuset *root_cs,
 static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
 			  const char *buf)
 {
-	struct ptr_heap heap;
 	int retval;
 	int is_load_balanced;
 
@@ -947,19 +927,13 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
 	if (retval < 0)
 		return retval;
 
-	retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
-	if (retval)
-		return retval;
-
 	is_load_balanced = is_sched_load_balance(trialcs);
 
 	mutex_lock(&callback_mutex);
 	cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
 	mutex_unlock(&callback_mutex);
 
-	update_tasks_cpumask_hier(cs, true, &heap);
-
-	heap_free(&heap);
+	update_tasks_cpumask_hier(cs, true);
 
 	if (is_load_balanced)
 		rebuild_sched_domains_locked();
@@ -974,12 +948,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
  *    Temporarilly set tasks mems_allowed to target nodes of migration,
  *    so that the migration code can allocate pages on these nodes.
  *
- *    Call holding cpuset_mutex, so current's cpuset won't change
- *    during this call, as manage_mutex holds off any cpuset_attach()
- *    calls.  Therefore we don't need to take task_lock around the
- *    call to guarantee_online_mems(), as we know no one is changing
- *    our task's cpuset.
- *
  *    While the mm_struct we are migrating is typically from some
  *    other task, the task_struct mems_allowed that we are hacking
  *    is for our current task, which must allocate new pages for that
@@ -996,8 +964,10 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
 
 	do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
 
+	rcu_read_lock();
 	mems_cs = effective_nodemask_cpuset(task_cs(tsk));
 	guarantee_online_mems(mems_cs, &tsk->mems_allowed);
+	rcu_read_unlock();
 }
 
 /*
@@ -1026,7 +996,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
 	task_lock(tsk);
 	/*
 	 * Determine if a loop is necessary if another thread is doing
-	 * get_mems_allowed().  If at least one node remains unchanged and
+	 * read_mems_allowed_begin().  If at least one node remains unchanged and
 	 * tsk does not have a mempolicy, then an empty nodemask will not be
 	 * possible when mems_allowed is larger than a word.
 	 */
@@ -1052,53 +1022,22 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
 	task_unlock(tsk);
 }
 
-struct cpuset_change_nodemask_arg {
-	struct cpuset		*cs;
-	nodemask_t		*newmems;
-};
-
-/*
- * Update task's mems_allowed and rebind its mempolicy and vmas' mempolicy
- * of it to cpuset's new mems_allowed, and migrate pages to new nodes if
- * memory_migrate flag is set. Called with cpuset_mutex held.
- */
-static void cpuset_change_nodemask(struct task_struct *p, void *data)
-{
-	struct cpuset_change_nodemask_arg *arg = data;
-	struct cpuset *cs = arg->cs;
-	struct mm_struct *mm;
-	int migrate;
-
-	cpuset_change_task_nodemask(p, arg->newmems);
-
-	mm = get_task_mm(p);
-	if (!mm)
-		return;
-
-	migrate = is_memory_migrate(cs);
-
-	mpol_rebind_mm(mm, &cs->mems_allowed);
-	if (migrate)
-		cpuset_migrate_mm(mm, &cs->old_mems_allowed, arg->newmems);
-	mmput(mm);
-}
-
 static void *cpuset_being_rebound;
 
 /**
  * update_tasks_nodemask - Update the nodemasks of tasks in the cpuset.
  * @cs: the cpuset in which each task's mems_allowed mask needs to be changed
- * @heap: if NULL, defer allocating heap memory to css_scan_tasks()
  *
- * Called with cpuset_mutex held.  No return value. It's guaranteed that
- * css_scan_tasks() always returns 0 if @heap != NULL.
+ * Iterate through each task of @cs updating its mems_allowed to the
+ * effective cpuset's.  As this function is called with cpuset_mutex held,
+ * cpuset membership stays stable.
  */
-static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
+static void update_tasks_nodemask(struct cpuset *cs)
 {
 	static nodemask_t newmems;	/* protected by cpuset_mutex */
 	struct cpuset *mems_cs = effective_nodemask_cpuset(cs);
-	struct cpuset_change_nodemask_arg arg = { .cs = cs,
-						  .newmems = &newmems };
+	struct css_task_iter it;
+	struct task_struct *task;
 
 	cpuset_being_rebound = cs;		/* causes mpol_dup() rebind */
 
@@ -1114,7 +1053,25 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
 	 * It's ok if we rebind the same mm twice; mpol_rebind_mm()
 	 * is idempotent.  Also migrate pages in each mm to new nodes.
 	 */
-	css_scan_tasks(&cs->css, NULL, cpuset_change_nodemask, &arg, heap);
+	css_task_iter_start(&cs->css, &it);
+	while ((task = css_task_iter_next(&it))) {
+		struct mm_struct *mm;
+		bool migrate;
+
+		cpuset_change_task_nodemask(task, &newmems);
+
+		mm = get_task_mm(task);
+		if (!mm)
+			continue;
+
+		migrate = is_memory_migrate(cs);
+
+		mpol_rebind_mm(mm, &cs->mems_allowed);
+		if (migrate)
+			cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
+		mmput(mm);
+	}
+	css_task_iter_end(&it);
 
 	/*
 	 * All the tasks' nodemasks have been updated, update
@@ -1130,15 +1087,13 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
  * update_tasks_nodemask_hier - Update the nodemasks of tasks in the hierarchy.
  * @cs: the root cpuset of the hierarchy
  * @update_root: update the root cpuset or not?
- * @heap: the heap used by css_scan_tasks()
  *
  * This will update nodemasks of tasks in @root_cs and all other empty cpusets
  * which take on nodemask of @root_cs.
  *
  * Called with cpuset_mutex held
  */
-static void update_tasks_nodemask_hier(struct cpuset *root_cs,
-				       bool update_root, struct ptr_heap *heap)
+static void update_tasks_nodemask_hier(struct cpuset *root_cs, bool update_root)
 {
 	struct cpuset *cp;
 	struct cgroup_subsys_state *pos_css;
@@ -1159,7 +1114,7 @@ static void update_tasks_nodemask_hier(struct cpuset *root_cs,
 			continue;
 		rcu_read_unlock();
 
-		update_tasks_nodemask(cp, heap);
+		update_tasks_nodemask(cp);
 
 		rcu_read_lock();
 		css_put(&cp->css);
@@ -1184,7 +1139,6 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
 			   const char *buf)
 {
 	int retval;
-	struct ptr_heap heap;
 
 	/*
 	 * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
@@ -1223,17 +1177,11 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
 	if (retval < 0)
 		goto done;
 
-	retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
-	if (retval < 0)
-		goto done;
-
 	mutex_lock(&callback_mutex);
 	cs->mems_allowed = trialcs->mems_allowed;
 	mutex_unlock(&callback_mutex);
 
-	update_tasks_nodemask_hier(cs, true, &heap);
-
-	heap_free(&heap);
+	update_tasks_nodemask_hier(cs, true);
 done:
 	return retval;
 }
@@ -1261,38 +1209,22 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
 }
 
 /**
- * cpuset_change_flag - make a task's spread flags the same as its cpuset's
- * @tsk: task to be updated
- * @data: cpuset to @tsk belongs to
- *
- * Called by css_scan_tasks() for each task in a cgroup.
- *
- * We don't need to re-check for the cgroup/cpuset membership, since we're
- * holding cpuset_mutex at this point.
- */
-static void cpuset_change_flag(struct task_struct *tsk, void *data)
-{
-	struct cpuset *cs = data;
-
-	cpuset_update_task_spread_flag(cs, tsk);
-}
-
-/**
  * update_tasks_flags - update the spread flags of tasks in the cpuset.
  * @cs: the cpuset in which each task's spread flags needs to be changed
- * @heap: if NULL, defer allocating heap memory to css_scan_tasks()
- *
- * Called with cpuset_mutex held
- *
- * The css_scan_tasks() function will scan all the tasks in a cgroup,
- * calling callback functions for each.
  *
- * No return value. It's guaranteed that css_scan_tasks() always returns 0
- * if @heap != NULL.
+ * Iterate through each task of @cs updating its spread flags.  As this
+ * function is called with cpuset_mutex held, cpuset membership stays
+ * stable.
  */
-static void update_tasks_flags(struct cpuset *cs, struct ptr_heap *heap)
+static void update_tasks_flags(struct cpuset *cs)
 {
-	css_scan_tasks(&cs->css, NULL, cpuset_change_flag, cs, heap);
+	struct css_task_iter it;
+	struct task_struct *task;
+
+	css_task_iter_start(&cs->css, &it);
+	while ((task = css_task_iter_next(&it)))
+		cpuset_update_task_spread_flag(cs, task);
+	css_task_iter_end(&it);
 }
 
 /*
@@ -1310,7 +1242,6 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
 	struct cpuset *trialcs;
 	int balance_flag_changed;
 	int spread_flag_changed;
-	struct ptr_heap heap;
 	int err;
 
 	trialcs = alloc_trial_cpuset(cs);
@@ -1326,10 +1257,6 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
 	if (err < 0)
 		goto out;
 
-	err = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
-	if (err < 0)
-		goto out;
-
 	balance_flag_changed = (is_sched_load_balance(cs) !=
 				is_sched_load_balance(trialcs));
 
@@ -1344,8 +1271,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
 		rebuild_sched_domains_locked();
 
 	if (spread_flag_changed)
-		update_tasks_flags(cs, &heap);
-	heap_free(&heap);
+		update_tasks_flags(cs);
 out:
 	free_trial_cpuset(trialcs);
 	return err;
@@ -1449,6 +1375,8 @@ static int fmeter_getrate(struct fmeter *fmp)
 	return val;
 }
 
+static struct cpuset *cpuset_attach_old_cs;
+
 /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
 static int cpuset_can_attach(struct cgroup_subsys_state *css,
 			     struct cgroup_taskset *tset)
@@ -1457,6 +1385,9 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
 	struct task_struct *task;
 	int ret;
 
+	/* used later by cpuset_attach() */
+	cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset));
+
 	mutex_lock(&cpuset_mutex);
 
 	/*
@@ -1468,7 +1399,7 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
 	    (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
 		goto out_unlock;
 
-	cgroup_taskset_for_each(task, css, tset) {
+	cgroup_taskset_for_each(task, tset) {
 		/*
 		 * Kthreads which disallow setaffinity shouldn't be moved
 		 * to a new cpuset; we don't want to change their cpu
@@ -1520,10 +1451,8 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
 	struct mm_struct *mm;
 	struct task_struct *task;
 	struct task_struct *leader = cgroup_taskset_first(tset);
-	struct cgroup_subsys_state *oldcss = cgroup_taskset_cur_css(tset,
-							cpuset_subsys_id);
 	struct cpuset *cs = css_cs(css);
-	struct cpuset *oldcs = css_cs(oldcss);
+	struct cpuset *oldcs = cpuset_attach_old_cs;
 	struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
 	struct cpuset *mems_cs = effective_nodemask_cpuset(cs);
 
@@ -1537,7 +1466,7 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
 
 	guarantee_online_mems(mems_cs, &cpuset_attach_nodemask_to);
 
-	cgroup_taskset_for_each(task, css, tset) {
+	cgroup_taskset_for_each(task, tset) {
 		/*
 		 * can_attach beforehand should guarantee that this doesn't
 		 * fail.  TODO: have a better way to handle failure here
@@ -2024,8 +1953,7 @@ static void cpuset_css_free(struct cgroup_subsys_state *css)
 	kfree(cs);
 }
 
-struct cgroup_subsys cpuset_subsys = {
-	.name = "cpuset",
+struct cgroup_subsys cpuset_cgrp_subsys = {
 	.css_alloc = cpuset_css_alloc,
 	.css_online = cpuset_css_online,
 	.css_offline = cpuset_css_offline,
@@ -2033,7 +1961,6 @@ struct cgroup_subsys cpuset_subsys = {
 	.can_attach = cpuset_can_attach,
 	.cancel_attach = cpuset_cancel_attach,
 	.attach = cpuset_attach,
-	.subsys_id = cpuset_subsys_id,
 	.base_cftypes = files,
 	.early_init = 1,
 };
@@ -2090,10 +2017,9 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
 		parent = parent_cs(parent);
 
 	if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
-		rcu_read_lock();
-		printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n",
-		       cgroup_name(cs->css.cgroup));
-		rcu_read_unlock();
+		printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset ");
+		pr_cont_cgroup_name(cs->css.cgroup);
+		pr_cont("\n");
 	}
 }
 
@@ -2141,7 +2067,7 @@ retry:
 	 */
 	if ((sane && cpumask_empty(cs->cpus_allowed)) ||
 	    (!cpumask_empty(&off_cpus) && !cpumask_empty(cs->cpus_allowed)))
-		update_tasks_cpumask(cs, NULL);
+		update_tasks_cpumask(cs);
 
 	mutex_lock(&callback_mutex);
 	nodes_andnot(cs->mems_allowed, cs->mems_allowed, off_mems);
@@ -2155,7 +2081,7 @@ retry:
 	 */
 	if ((sane && nodes_empty(cs->mems_allowed)) ||
 	    (!nodes_empty(off_mems) && !nodes_empty(cs->mems_allowed)))
-		update_tasks_nodemask(cs, NULL);
+		update_tasks_nodemask(cs);
 
 	is_empty = cpumask_empty(cs->cpus_allowed) ||
 		nodes_empty(cs->mems_allowed);
@@ -2217,7 +2143,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
 		mutex_lock(&callback_mutex);
 		top_cpuset.mems_allowed = new_mems;
 		mutex_unlock(&callback_mutex);
-		update_tasks_nodemask(&top_cpuset, NULL);
+		update_tasks_nodemask(&top_cpuset);
 	}
 
 	mutex_unlock(&cpuset_mutex);
@@ -2309,10 +2235,10 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
 	struct cpuset *cpus_cs;
 
 	mutex_lock(&callback_mutex);
-	task_lock(tsk);
+	rcu_read_lock();
 	cpus_cs = effective_cpumask_cpuset(task_cs(tsk));
 	guarantee_online_cpus(cpus_cs, pmask);
-	task_unlock(tsk);
+	rcu_read_unlock();
 	mutex_unlock(&callback_mutex);
 }
 
@@ -2365,10 +2291,10 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
 	nodemask_t mask;
 
 	mutex_lock(&callback_mutex);
-	task_lock(tsk);
+	rcu_read_lock();
 	mems_cs = effective_nodemask_cpuset(task_cs(tsk));
 	guarantee_online_mems(mems_cs, &mask);
-	task_unlock(tsk);
+	rcu_read_unlock();
 	mutex_unlock(&callback_mutex);
 
 	return mask;
@@ -2484,11 +2410,11 @@ int __cpuset_node_allowed_softwall(int node, gfp_t gfp_mask)
 	/* Not hardwall and node outside mems_allowed: scan up cpusets */
 	mutex_lock(&callback_mutex);
 
-	task_lock(current);
+	rcu_read_lock();
 	cs = nearest_hardwall_ancestor(task_cs(current));
-	task_unlock(current);
-
 	allowed = node_isset(node, cs->mems_allowed);
+	rcu_read_unlock();
+
 	mutex_unlock(&callback_mutex);
 	return allowed;
 }
@@ -2613,27 +2539,27 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
  * @task: pointer to task_struct of some task.
  *
  * Description: Prints @task's name, cpuset name, and cached copy of its
- * mems_allowed to the kernel log.  Must hold task_lock(task) to allow
- * dereferencing task_cs(task).
+ * mems_allowed to the kernel log.
  */
 void cpuset_print_task_mems_allowed(struct task_struct *tsk)
 {
 	 /* Statically allocated to prevent using excess stack. */
 	static char cpuset_nodelist[CPUSET_NODELIST_LEN];
 	static DEFINE_SPINLOCK(cpuset_buffer_lock);
+	struct cgroup *cgrp;
 
-	struct cgroup *cgrp = task_cs(tsk)->css.cgroup;
-
-	rcu_read_lock();
 	spin_lock(&cpuset_buffer_lock);
+	rcu_read_lock();
 
+	cgrp = task_cs(tsk)->css.cgroup;
 	nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
 			   tsk->mems_allowed);
-	printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
-	       tsk->comm, cgroup_name(cgrp), cpuset_nodelist);
+	printk(KERN_INFO "%s cpuset=", tsk->comm);
+	pr_cont_cgroup_name(cgrp);
+	pr_cont(" mems_allowed=%s\n", cpuset_nodelist);
 
-	spin_unlock(&cpuset_buffer_lock);
 	rcu_read_unlock();
+	spin_unlock(&cpuset_buffer_lock);
 }
 
 /*
@@ -2664,9 +2590,9 @@ int cpuset_memory_pressure_enabled __read_mostly;
 
 void __cpuset_memory_pressure_bump(void)
 {
-	task_lock(current);
+	rcu_read_lock();
 	fmeter_markevent(&task_cs(current)->fmeter);
-	task_unlock(current);
+	rcu_read_unlock();
 }
 
 #ifdef CONFIG_PROC_PID_CPUSET
@@ -2683,12 +2609,12 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)
 {
 	struct pid *pid;
 	struct task_struct *tsk;
-	char *buf;
+	char *buf, *p;
 	struct cgroup_subsys_state *css;
 	int retval;
 
 	retval = -ENOMEM;
-	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	buf = kmalloc(PATH_MAX, GFP_KERNEL);
 	if (!buf)
 		goto out;
 
@@ -2698,14 +2624,16 @@ int proc_cpuset_sh